From 81e105d90f9f422a53b26178926ef40d78dd8e63 Mon Sep 17 00:00:00 2001 From: Eitan Seri- Levi Date: Tue, 3 Mar 2026 18:57:13 -0800 Subject: [PATCH] more fixes --- .../lighthouse_network/src/rpc/codec.rs | 52 +++++-- .../lighthouse_network/src/rpc/protocol.rs | 34 ++++- consensus/types/src/block/beacon_block.rs | 142 +++++++++++++++++- 3 files changed, 205 insertions(+), 23 deletions(-) diff --git a/beacon_node/lighthouse_network/src/rpc/codec.rs b/beacon_node/lighthouse_network/src/rpc/codec.rs index ceb7090b21..10156a9ff5 100644 --- a/beacon_node/lighthouse_network/src/rpc/codec.rs +++ b/beacon_node/lighthouse_network/src/rpc/codec.rs @@ -668,16 +668,48 @@ fn handle_rpc_response( SupportedProtocol::BlocksByRootV1 => Ok(Some(RpcSuccessResponse::BlocksByRoot(Arc::new( SignedBeaconBlock::Base(SignedBeaconBlockBase::from_ssz_bytes(decoded_buffer)?), )))), - SupportedProtocol::PayloadEnvelopesByRangeV1 => { - Ok(Some(RpcSuccessResponse::PayloadEnvelopesByRange(Arc::new( - SignedExecutionPayloadEnvelope::from_ssz_bytes(decoded_buffer)?, - )))) - } - SupportedProtocol::PayloadEnvelopesByRootV1 => { - Ok(Some(RpcSuccessResponse::PayloadEnvelopesByRoot(Arc::new( - SignedExecutionPayloadEnvelope::from_ssz_bytes(decoded_buffer)?, - )))) - } + SupportedProtocol::PayloadEnvelopesByRangeV1 => match fork_name { + Some(fork_name) => { + if fork_name.gloas_enabled() { + Ok(Some(RpcSuccessResponse::PayloadEnvelopesByRange(Arc::new( + SignedExecutionPayloadEnvelope::from_ssz_bytes(decoded_buffer)?, + )))) + } else { + Err(RPCError::ErrorResponse( + RpcErrorResponse::InvalidRequest, + "Invalid fork name for payload envelopes by range".to_string(), + )) + } + } + None => Err(RPCError::ErrorResponse( + RpcErrorResponse::InvalidRequest, + format!( + "No context bytes provided for {:?} response", + versioned_protocol + ), + )), + }, + SupportedProtocol::PayloadEnvelopesByRootV1 => match fork_name { + Some(fork_name) => { + if fork_name.gloas_enabled() { + Ok(Some(RpcSuccessResponse::PayloadEnvelopesByRoot(Arc::new( + SignedExecutionPayloadEnvelope::from_ssz_bytes(decoded_buffer)?, + )))) + } else { + Err(RPCError::ErrorResponse( + RpcErrorResponse::InvalidRequest, + "Invalid fork name for payload envelopes by root".to_string(), + )) + } + } + None => Err(RPCError::ErrorResponse( + RpcErrorResponse::InvalidRequest, + format!( + "No context bytes provided for {:?} response", + versioned_protocol + ), + )), + }, SupportedProtocol::BlobsByRangeV1 => match fork_name { Some(fork_name) => { if fork_name.deneb_enabled() { diff --git a/beacon_node/lighthouse_network/src/rpc/protocol.rs b/beacon_node/lighthouse_network/src/rpc/protocol.rs index 74c9ddef9c..14bf2415c4 100644 --- a/beacon_node/lighthouse_network/src/rpc/protocol.rs +++ b/beacon_node/lighthouse_network/src/rpc/protocol.rs @@ -17,10 +17,10 @@ use tokio_util::{ compat::{Compat, FuturesAsyncReadCompatExt}, }; use types::{ - BeaconBlock, BeaconBlockAltair, BeaconBlockBase, BlobSidecar, ChainSpec, DataColumnSidecarFulu, - DataColumnSidecarGloas, EmptyBlock, Epoch, EthSpec, EthSpecId, ForkContext, ForkName, - LightClientBootstrap, LightClientBootstrapAltair, LightClientFinalityUpdate, - LightClientFinalityUpdateAltair, LightClientOptimisticUpdate, + BeaconBlock, BeaconBlockAltair, BeaconBlockBase, BeaconBlockGloas, BlobSidecar, ChainSpec, + DataColumnSidecarFulu, DataColumnSidecarGloas, EmptyBlock, Epoch, EthSpec, EthSpecId, + ForkContext, ForkName, LightClientBootstrap, LightClientBootstrapAltair, + LightClientFinalityUpdate, LightClientFinalityUpdateAltair, LightClientOptimisticUpdate, LightClientOptimisticUpdateAltair, LightClientUpdate, MainnetEthSpec, MinimalEthSpec, SignedBeaconBlock, SignedExecutionPayloadEnvelope, }; @@ -65,6 +65,17 @@ pub static SIGNED_BEACON_BLOCK_BELLATRIX_MAX: LazyLock = + types::ExecutionPayload::::max_execution_payload_bellatrix_size() // adding max size of execution payload (~16gb) + ssz::BYTES_PER_LENGTH_OFFSET); // Adding the additional ssz offset for the `ExecutionPayload` field +/// Gloas blocks no longer contain an execution payload (it's in the envelope), +/// so they are significantly smaller than Bellatrix+ blocks. +pub static SIGNED_BEACON_BLOCK_GLOAS_MAX: LazyLock = LazyLock::new(|| { + SignedBeaconBlock::::from_block( + BeaconBlock::Gloas(BeaconBlockGloas::full(&MainnetEthSpec::default_spec())), + Signature::empty(), + ) + .as_ssz_bytes() + .len() +}); + pub static SIGNED_EXECUTION_PAYLOAD_ENVELOPE_MIN: LazyLock = LazyLock::new(SignedExecutionPayloadEnvelope::::min_size); @@ -146,10 +157,19 @@ pub fn rpc_block_limits_by_fork(current_fork: ForkName) -> RpcLimits { ), // After the merge the max SSZ size of a block is absurdly big. The size is actually // bound by other constants, so here we default to the bellatrix's max value - _ => RpcLimits::new( + ForkName::Bellatrix + | ForkName::Capella + | ForkName::Deneb + | ForkName::Electra + | ForkName::Fulu => RpcLimits::new( *SIGNED_BEACON_BLOCK_BASE_MIN, // Base block is smaller than altair and bellatrix blocks *SIGNED_BEACON_BLOCK_BELLATRIX_MAX, // Bellatrix block is larger than base and altair blocks ), + // Gloas blocks no longer contain the execution payload, so they are much smaller + ForkName::Gloas => RpcLimits::new( + *SIGNED_BEACON_BLOCK_BASE_MIN, + *SIGNED_BEACON_BLOCK_GLOAS_MAX, + ), } } @@ -596,9 +616,7 @@ impl ProtocolId { Protocol::Goodbye => RpcLimits::new(0, 0), // Goodbye request has no response Protocol::BlocksByRange => rpc_block_limits_by_fork(fork_context.current_fork_name()), Protocol::BlocksByRoot => rpc_block_limits_by_fork(fork_context.current_fork_name()), - Protocol::PayloadEnvelopesByRange => { - rpc_block_limits_by_fork(fork_context.current_fork_name()) - } + Protocol::PayloadEnvelopesByRange => rpc_payload_limits(), Protocol::PayloadEnvelopesByRoot => rpc_payload_limits(), Protocol::BlobsByRange => rpc_blob_limits::(), Protocol::BlobsByRoot => rpc_blob_limits::(), diff --git a/consensus/types/src/block/beacon_block.rs b/consensus/types/src/block/beacon_block.rs index 5634d842b6..c5ce8586c4 100644 --- a/consensus/types/src/block/beacon_block.rs +++ b/consensus/types/src/block/beacon_block.rs @@ -15,8 +15,11 @@ use tree_hash_derive::TreeHash; use typenum::Unsigned; use crate::{ - SignedExecutionPayloadBid, - attestation::{AttestationBase, AttestationData, IndexedAttestationBase}, + Address, SignedBlsToExecutionChange, SignedExecutionPayloadBid, + attestation::{ + AttestationBase, AttestationData, AttestationElectra, IndexedAttestationBase, + IndexedAttestationElectra, PayloadAttestation, PayloadAttestationData, + }, block::{ BeaconBlockBodyAltair, BeaconBlockBodyBase, BeaconBlockBodyBellatrix, BeaconBlockBodyCapella, BeaconBlockBodyDeneb, BeaconBlockBodyElectra, BeaconBlockBodyFulu, @@ -26,12 +29,12 @@ use crate::{ core::{ChainSpec, Domain, Epoch, EthSpec, Graffiti, Hash256, SignedRoot, Slot}, deposit::{Deposit, DepositData}, execution::{ - AbstractExecPayload, BlindedPayload, Eth1Data, ExecutionPayload, ExecutionRequests, - FullPayload, + AbstractExecPayload, BlindedPayload, BlsToExecutionChange, Eth1Data, ExecutionPayload, + ExecutionRequests, FullPayload, }, exit::{SignedVoluntaryExit, VoluntaryExit}, fork::{Fork, ForkName, InconsistentFork, map_fork_name}, - slashing::{AttesterSlashingBase, ProposerSlashing}, + slashing::{AttesterSlashingBase, AttesterSlashingElectra, ProposerSlashing}, state::BeaconStateError, sync_committee::SyncAggregate, test_utils::TestRandom, @@ -724,6 +727,135 @@ impl> EmptyBlock for BeaconBlockGloa } } +impl> BeaconBlockGloas { + /// Returns a full Gloas block with all variable-length fields at max capacity. + /// Used for computing the maximum SSZ-encoded size. + pub fn full(spec: &ChainSpec) -> Self { + let header = BeaconBlockHeader { + slot: Slot::new(1), + proposer_index: 0, + parent_root: Hash256::zero(), + state_root: Hash256::zero(), + body_root: Hash256::zero(), + }; + + let signed_header = SignedBeaconBlockHeader { + message: header, + signature: Signature::empty(), + }; + + let indexed_attestation = IndexedAttestationElectra { + attesting_indices: VariableList::new(vec![0_u64; E::MaxValidatorsPerSlot::to_usize()]) + .unwrap(), + data: AttestationData::default(), + signature: AggregateSignature::empty(), + }; + + let proposer_slashing = ProposerSlashing { + signed_header_1: signed_header.clone(), + signed_header_2: signed_header, + }; + + let attester_slashing = AttesterSlashingElectra { + attestation_1: indexed_attestation.clone(), + attestation_2: indexed_attestation, + }; + + let attestation = AttestationElectra { + aggregation_bits: BitList::with_capacity(E::MaxValidatorsPerSlot::to_usize()).unwrap(), + data: AttestationData::default(), + signature: AggregateSignature::empty(), + committee_bits: BitVector::default(), + }; + + let deposit_data = DepositData { + pubkey: PublicKeyBytes::empty(), + withdrawal_credentials: Hash256::zero(), + amount: 0, + signature: SignatureBytes::empty(), + }; + + let deposit = Deposit { + proof: FixedVector::from_elem(Hash256::zero()), + data: deposit_data, + }; + + let signed_voluntary_exit = SignedVoluntaryExit { + message: VoluntaryExit { + epoch: Epoch::new(1), + validator_index: 1, + }, + signature: Signature::empty(), + }; + + let signed_bls_to_execution_change = SignedBlsToExecutionChange { + message: BlsToExecutionChange { + validator_index: 0, + from_bls_pubkey: PublicKeyBytes::empty(), + to_execution_address: Address::zero(), + }, + signature: Signature::empty(), + }; + + let payload_attestation = PayloadAttestation { + aggregation_bits: BitVector::default(), + data: PayloadAttestationData { + beacon_block_root: Hash256::zero(), + slot: Slot::new(0), + payload_present: false, + blob_data_available: false, + }, + signature: AggregateSignature::empty(), + }; + + let mut block = BeaconBlockGloas::::empty(spec); + + for _ in 0..E::MaxProposerSlashings::to_usize() { + block + .body + .proposer_slashings + .push(proposer_slashing.clone()) + .unwrap(); + } + for _ in 0..E::max_attester_slashings_electra() { + block + .body + .attester_slashings + .push(attester_slashing.clone()) + .unwrap(); + } + for _ in 0..E::max_attestations_electra() { + block.body.attestations.push(attestation.clone()).unwrap(); + } + for _ in 0..E::MaxDeposits::to_usize() { + block.body.deposits.push(deposit.clone()).unwrap(); + } + for _ in 0..E::MaxVoluntaryExits::to_usize() { + block + .body + .voluntary_exits + .push(signed_voluntary_exit.clone()) + .unwrap(); + } + for _ in 0..E::MaxBlsToExecutionChanges::to_usize() { + block + .body + .bls_to_execution_changes + .push(signed_bls_to_execution_change.clone()) + .unwrap(); + } + for _ in 0..E::MaxPayloadAttestations::to_usize() { + block + .body + .payload_attestations + .push(payload_attestation.clone()) + .unwrap(); + } + + block + } +} + // TODO(EIP-7732) Mark's branch had the following implementation but not sure if it's needed so will just add header below for reference // impl> BeaconBlockEIP7732 {