From 39727aa4067dc19d999f24618f2c9841a18b2c29 Mon Sep 17 00:00:00 2001 From: Eitan Seri-Levi Date: Tue, 3 Feb 2026 18:52:40 -0800 Subject: [PATCH] Move KZG commitments from payload envelope to payload bid and spec alpha.2 (#8725) Co-Authored-By: Eitan Seri- Levi Co-Authored-By: Michael Sproul Co-Authored-By: Jimmy Chen Co-Authored-By: Michael Sproul --- .../lighthouse_network/src/types/pubsub.rs | 2 +- .../gossip_methods.rs | 2 +- .../src/network_beacon_processor/mod.rs | 2 +- .../src/per_block_processing/withdrawals.rs | 12 ++-------- .../types/src/block/beacon_block_body.rs | 2 +- .../src/execution/execution_payload_bid.rs | 19 +++++++++++----- .../execution/execution_payload_envelope.rs | 7 ++---- .../execution/signed_execution_payload_bid.rs | 19 +++++++++++----- consensus/types/src/state/beacon_state.rs | 2 +- testing/ef_tests/Makefile | 2 +- testing/ef_tests/check_all_files_accessed.py | 2 ++ testing/ef_tests/src/cases/operations.rs | 19 +++++++++++----- testing/ef_tests/src/handler.rs | 4 ++++ testing/ef_tests/src/type_name.rs | 4 ++++ testing/ef_tests/tests/tests.rs | 22 +++++++++++++++++++ 15 files changed, 81 insertions(+), 39 deletions(-) diff --git a/beacon_node/lighthouse_network/src/types/pubsub.rs b/beacon_node/lighthouse_network/src/types/pubsub.rs index d1df7face7..12567907f6 100644 --- a/beacon_node/lighthouse_network/src/types/pubsub.rs +++ b/beacon_node/lighthouse_network/src/types/pubsub.rs @@ -49,7 +49,7 @@ pub enum PubsubMessage { /// Gossipsub message providing notification of a payload attestation message. PayloadAttestation(Box), /// Gossipsub message providing notification of a signed execution payload bid. - ExecutionPayloadBid(Box), + ExecutionPayloadBid(Box>), /// Gossipsub message providing notification of signed proposer preferences. ProposerPreferences(Box), /// Gossipsub message providing notification of a light client finality update. diff --git a/beacon_node/network/src/network_beacon_processor/gossip_methods.rs b/beacon_node/network/src/network_beacon_processor/gossip_methods.rs index a45441a37a..6193725323 100644 --- a/beacon_node/network/src/network_beacon_processor/gossip_methods.rs +++ b/beacon_node/network/src/network_beacon_processor/gossip_methods.rs @@ -3252,7 +3252,7 @@ impl NetworkBeaconProcessor { self: &Arc, message_id: MessageId, peer_id: PeerId, - payload_bid: SignedExecutionPayloadBid, + payload_bid: SignedExecutionPayloadBid, ) { // TODO(EIP-7732): Implement proper payload bid gossip processing. // This should integrate with a payload execution bid verification module once it's implemented. diff --git a/beacon_node/network/src/network_beacon_processor/mod.rs b/beacon_node/network/src/network_beacon_processor/mod.rs index c326dfd597..fd67fcde82 100644 --- a/beacon_node/network/src/network_beacon_processor/mod.rs +++ b/beacon_node/network/src/network_beacon_processor/mod.rs @@ -448,7 +448,7 @@ impl NetworkBeaconProcessor { self: &Arc, message_id: MessageId, peer_id: PeerId, - execution_payload_bid: Box, + execution_payload_bid: Box>, ) -> Result<(), Error> { let processor = self.clone(); let process_fn = move || { diff --git a/consensus/state_processing/src/per_block_processing/withdrawals.rs b/consensus/state_processing/src/per_block_processing/withdrawals.rs index 39ad4efc5c..72c3339b10 100644 --- a/consensus/state_processing/src/per_block_processing/withdrawals.rs +++ b/consensus/state_processing/src/per_block_processing/withdrawals.rs @@ -84,11 +84,8 @@ pub fn get_builder_withdrawals( return Ok(None); }; - // TODO(gloas): this has already changed on `master`, we need to update at next spec release - let withdrawals_limit = E::max_withdrawals_per_payload(); + let withdrawals_limit = E::max_withdrawals_per_payload().safe_sub(1)?; - // TODO(gloas): this assert is from `master`, remove this comment once it is part of the tested - // spec version. block_verify!( withdrawals.len() <= withdrawals_limit, BlockProcessingError::WithdrawalsLimitExceeded { @@ -138,8 +135,6 @@ pub fn get_pending_partial_withdrawals( E::max_withdrawals_per_payload().safe_sub(1)?, ); - // TODO(gloas): this assert is from `master`, remove this comment once it is part of the tested - // spec version. block_verify!( withdrawals.len() <= withdrawals_limit, BlockProcessingError::WithdrawalsLimitExceeded { @@ -205,11 +200,8 @@ pub fn get_builders_sweep_withdrawals( let epoch = state.current_epoch(); let builders_limit = std::cmp::min(builders.len(), E::max_builders_per_withdrawals_sweep()); - // TODO(gloas): this has already changed on `master`, we should update at the next spec release - let withdrawals_limit = E::max_withdrawals_per_payload(); + let withdrawals_limit = E::max_withdrawals_per_payload().safe_sub(1)?; - // TODO(gloas): this assert is from `master`, remove this comment once it is part of the tested - // spec version. block_verify!( withdrawals.len() <= withdrawals_limit, BlockProcessingError::WithdrawalsLimitExceeded { diff --git a/consensus/types/src/block/beacon_block_body.rs b/consensus/types/src/block/beacon_block_body.rs index a113f85fd3..fd5d976c9b 100644 --- a/consensus/types/src/block/beacon_block_body.rs +++ b/consensus/types/src/block/beacon_block_body.rs @@ -167,7 +167,7 @@ pub struct BeaconBlockBody = FullPay #[superstruct(only(Electra, Fulu))] pub execution_requests: ExecutionRequests, #[superstruct(only(Gloas))] - pub signed_execution_payload_bid: SignedExecutionPayloadBid, + pub signed_execution_payload_bid: SignedExecutionPayloadBid, #[superstruct(only(Gloas))] pub payload_attestations: VariableList, E::MaxPayloadAttestations>, #[superstruct(only(Base, Altair, Gloas))] diff --git a/consensus/types/src/execution/execution_payload_bid.rs b/consensus/types/src/execution/execution_payload_bid.rs index f0056463e9..5c8771993e 100644 --- a/consensus/types/src/execution/execution_payload_bid.rs +++ b/consensus/types/src/execution/execution_payload_bid.rs @@ -1,5 +1,6 @@ +use crate::kzg_ext::KzgCommitments; use crate::test_utils::TestRandom; -use crate::{Address, ExecutionBlockHash, ForkName, Hash256, SignedRoot, Slot}; +use crate::{Address, EthSpec, ExecutionBlockHash, ForkName, Hash256, SignedRoot, Slot}; use context_deserialize::context_deserialize; use educe::Educe; use serde::{Deserialize, Serialize}; @@ -10,11 +11,16 @@ use tree_hash_derive::TreeHash; #[derive( Default, Debug, Clone, Serialize, Encode, Decode, Deserialize, TreeHash, Educe, TestRandom, )] -#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "arbitrary", + derive(arbitrary::Arbitrary), + arbitrary(bound = "E: EthSpec") +)] #[educe(PartialEq, Hash)] +#[serde(bound = "E: EthSpec")] #[context_deserialize(ForkName)] // https://github.com/ethereum/consensus-specs/blob/master/specs/gloas/beacon-chain.md#executionpayloadbid -pub struct ExecutionPayloadBid { +pub struct ExecutionPayloadBid { pub parent_block_hash: ExecutionBlockHash, pub parent_block_root: Hash256, pub block_hash: ExecutionBlockHash, @@ -30,14 +36,15 @@ pub struct ExecutionPayloadBid { pub value: u64, #[serde(with = "serde_utils::quoted_u64")] pub execution_payment: u64, - pub blob_kzg_commitments_root: Hash256, + pub blob_kzg_commitments: KzgCommitments, } -impl SignedRoot for ExecutionPayloadBid {} +impl SignedRoot for ExecutionPayloadBid {} #[cfg(test)] mod tests { use super::*; + use crate::MainnetEthSpec; - ssz_and_tree_hash_tests!(ExecutionPayloadBid); + ssz_and_tree_hash_tests!(ExecutionPayloadBid); } diff --git a/consensus/types/src/execution/execution_payload_envelope.rs b/consensus/types/src/execution/execution_payload_envelope.rs index 64e03cec5a..7f68dae037 100644 --- a/consensus/types/src/execution/execution_payload_envelope.rs +++ b/consensus/types/src/execution/execution_payload_envelope.rs @@ -1,8 +1,6 @@ +use crate::execution::{ExecutionPayloadGloas, ExecutionRequests}; use crate::test_utils::TestRandom; -use crate::{ - EthSpec, ExecutionPayloadGloas, ExecutionRequests, ForkName, Hash256, KzgCommitments, - SignedRoot, Slot, -}; +use crate::{EthSpec, ForkName, Hash256, SignedRoot, Slot}; use context_deserialize::context_deserialize; use educe::Educe; use serde::{Deserialize, Serialize}; @@ -21,7 +19,6 @@ pub struct ExecutionPayloadEnvelope { pub builder_index: u64, pub beacon_block_root: Hash256, pub slot: Slot, - pub blob_kzg_commitments: KzgCommitments, pub state_root: Hash256, } diff --git a/consensus/types/src/execution/signed_execution_payload_bid.rs b/consensus/types/src/execution/signed_execution_payload_bid.rs index 29dfd03ba0..48da445332 100644 --- a/consensus/types/src/execution/signed_execution_payload_bid.rs +++ b/consensus/types/src/execution/signed_execution_payload_bid.rs @@ -1,5 +1,6 @@ +use crate::execution::ExecutionPayloadBid; use crate::test_utils::TestRandom; -use crate::{ExecutionPayloadBid, ForkName}; +use crate::{EthSpec, ForkName}; use bls::Signature; use context_deserialize::context_deserialize; use educe::Educe; @@ -9,16 +10,21 @@ use test_random_derive::TestRandom; use tree_hash_derive::TreeHash; #[derive(TestRandom, TreeHash, Debug, Clone, Encode, Decode, Serialize, Deserialize, Educe)] -#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] +#[cfg_attr( + feature = "arbitrary", + derive(arbitrary::Arbitrary), + arbitrary(bound = "E: EthSpec") +)] #[educe(PartialEq, Hash)] +#[serde(bound = "E: EthSpec")] #[context_deserialize(ForkName)] // https://github.com/ethereum/consensus-specs/blob/master/specs/gloas/beacon-chain.md#signedexecutionpayloadbid -pub struct SignedExecutionPayloadBid { - pub message: ExecutionPayloadBid, +pub struct SignedExecutionPayloadBid { + pub message: ExecutionPayloadBid, pub signature: Signature, } -impl SignedExecutionPayloadBid { +impl SignedExecutionPayloadBid { pub fn empty() -> Self { Self { message: ExecutionPayloadBid::default(), @@ -30,6 +36,7 @@ impl SignedExecutionPayloadBid { #[cfg(test)] mod tests { use super::*; + use crate::MainnetEthSpec; - ssz_and_tree_hash_tests!(SignedExecutionPayloadBid); + ssz_and_tree_hash_tests!(SignedExecutionPayloadBid); } diff --git a/consensus/types/src/state/beacon_state.rs b/consensus/types/src/state/beacon_state.rs index 04d9a1aea8..f661988edb 100644 --- a/consensus/types/src/state/beacon_state.rs +++ b/consensus/types/src/state/beacon_state.rs @@ -548,7 +548,7 @@ where pub latest_execution_payload_header: ExecutionPayloadHeaderFulu, #[superstruct(only(Gloas))] #[metastruct(exclude_from(tree_lists))] - pub latest_execution_payload_bid: ExecutionPayloadBid, + pub latest_execution_payload_bid: ExecutionPayloadBid, #[superstruct(only(Capella, Deneb, Electra, Fulu, Gloas), partial_getter(copy))] #[serde(with = "serde_utils::quoted_u64")] #[metastruct(exclude_from(tree_lists))] diff --git a/testing/ef_tests/Makefile b/testing/ef_tests/Makefile index 0c6371f825..fd8a3f6da0 100644 --- a/testing/ef_tests/Makefile +++ b/testing/ef_tests/Makefile @@ -1,6 +1,6 @@ # To download/extract nightly tests, run: # CONSENSUS_SPECS_TEST_VERSION=nightly make -CONSENSUS_SPECS_TEST_VERSION ?= v1.7.0-alpha.1 +CONSENSUS_SPECS_TEST_VERSION ?= v1.7.0-alpha.2 REPO_NAME := consensus-spec-tests OUTPUT_DIR := ./$(REPO_NAME) diff --git a/testing/ef_tests/check_all_files_accessed.py b/testing/ef_tests/check_all_files_accessed.py index 7787af64f0..97c1c4f4f9 100755 --- a/testing/ef_tests/check_all_files_accessed.py +++ b/testing/ef_tests/check_all_files_accessed.py @@ -59,6 +59,8 @@ excluded_paths = [ # Ignore full epoch tests for now (just test the sub-transitions). "tests/.*/.*/epoch_processing/.*/pre_epoch.ssz_snappy", "tests/.*/.*/epoch_processing/.*/post_epoch.ssz_snappy", + # Ignore inactivity_scores tests for now (should implement soon). + "tests/.*/.*/rewards/inactivity_scores/.*", # Ignore gloas tests for now "tests/.*/gloas/.*", # Ignore KZG tests that target internal kzg library functions diff --git a/testing/ef_tests/src/cases/operations.rs b/testing/ef_tests/src/cases/operations.rs index 2c7a385bd5..e778300879 100644 --- a/testing/ef_tests/src/cases/operations.rs +++ b/testing/ef_tests/src/cases/operations.rs @@ -45,7 +45,7 @@ struct ExecutionMetadata { /// Newtype for testing withdrawals. #[derive(Debug, Clone, Deserialize)] pub struct WithdrawalsPayload { - payload: ExecutionPayload, + payload: Option>, } #[derive(Debug, Clone)] @@ -405,10 +405,17 @@ impl Operation for WithdrawalsPayload { } fn decode(path: &Path, fork_name: ForkName, _spec: &ChainSpec) -> Result { - ssz_decode_file_with(path, |bytes| { - ExecutionPayload::from_ssz_bytes_by_fork(bytes, fork_name) - }) - .map(|payload| WithdrawalsPayload { payload }) + if fork_name.gloas_enabled() { + // No payload present or required for Gloas tests. + Ok(WithdrawalsPayload { payload: None }) + } else { + ssz_decode_file_with(path, |bytes| { + ExecutionPayload::from_ssz_bytes_by_fork(bytes, fork_name) + }) + .map(|payload| WithdrawalsPayload { + payload: Some(payload), + }) + } } fn apply_to( @@ -420,7 +427,7 @@ impl Operation for WithdrawalsPayload { if state.fork_name_unchecked().gloas_enabled() { withdrawals::gloas::process_withdrawals(state, spec) } else { - let full_payload = FullPayload::from(self.payload.clone()); + let full_payload = FullPayload::from(self.payload.clone().unwrap()); withdrawals::capella_electra::process_withdrawals::<_, FullPayload<_>>( state, full_payload.to_ref(), diff --git a/testing/ef_tests/src/handler.rs b/testing/ef_tests/src/handler.rs index 86d317b564..117661143b 100644 --- a/testing/ef_tests/src/handler.rs +++ b/testing/ef_tests/src/handler.rs @@ -333,6 +333,10 @@ impl SszStaticHandler { Self::for_forks(ForkName::list_all()[6..].to_vec()) } + pub fn gloas_and_later() -> Self { + Self::for_forks(ForkName::list_all()[7..].to_vec()) + } + pub fn pre_electra() -> Self { Self::for_forks(ForkName::list_all()[0..5].to_vec()) } diff --git a/testing/ef_tests/src/type_name.rs b/testing/ef_tests/src/type_name.rs index 87d56968cc..ae00727fc3 100644 --- a/testing/ef_tests/src/type_name.rs +++ b/testing/ef_tests/src/type_name.rs @@ -55,6 +55,7 @@ type_name_generic!(BeaconBlockBodyCapella, "BeaconBlockBody"); type_name_generic!(BeaconBlockBodyDeneb, "BeaconBlockBody"); type_name_generic!(BeaconBlockBodyElectra, "BeaconBlockBody"); type_name_generic!(BeaconBlockBodyFulu, "BeaconBlockBody"); +type_name_generic!(BeaconBlockBodyGloas, "BeaconBlockBody"); type_name!(BeaconBlockHeader); type_name_generic!(BeaconState); type_name!(BlobIdentifier); @@ -78,6 +79,7 @@ type_name_generic!(ExecutionPayloadCapella, "ExecutionPayload"); type_name_generic!(ExecutionPayloadDeneb, "ExecutionPayload"); type_name_generic!(ExecutionPayloadElectra, "ExecutionPayload"); type_name_generic!(ExecutionPayloadFulu, "ExecutionPayload"); +type_name_generic!(ExecutionPayloadGloas, "ExecutionPayload"); type_name_generic!(FullPayload, "ExecutionPayload"); type_name_generic!(ExecutionPayloadHeader); type_name_generic!(ExecutionPayloadHeaderBellatrix, "ExecutionPayloadHeader"); @@ -85,6 +87,8 @@ type_name_generic!(ExecutionPayloadHeaderCapella, "ExecutionPayloadHeader"); type_name_generic!(ExecutionPayloadHeaderDeneb, "ExecutionPayloadHeader"); type_name_generic!(ExecutionPayloadHeaderElectra, "ExecutionPayloadHeader"); type_name_generic!(ExecutionPayloadHeaderFulu, "ExecutionPayloadHeader"); +type_name_generic!(ExecutionPayloadBid); +type_name_generic!(SignedExecutionPayloadBid); type_name_generic!(ExecutionRequests); type_name_generic!(BlindedPayload, "ExecutionPayloadHeader"); type_name!(Fork); diff --git a/testing/ef_tests/tests/tests.rs b/testing/ef_tests/tests/tests.rs index e5c043e27b..505693c31d 100644 --- a/testing/ef_tests/tests/tests.rs +++ b/testing/ef_tests/tests/tests.rs @@ -369,6 +369,10 @@ mod ssz_static { .run(); SszStaticHandler::, MinimalEthSpec>::fulu_only().run(); SszStaticHandler::, MainnetEthSpec>::fulu_only().run(); + SszStaticHandler::, MinimalEthSpec>::gloas_only() + .run(); + SszStaticHandler::, MainnetEthSpec>::gloas_only() + .run(); } // Altair and later @@ -596,6 +600,10 @@ mod ssz_static { .run(); SszStaticHandler::, MinimalEthSpec>::fulu_only().run(); SszStaticHandler::, MainnetEthSpec>::fulu_only().run(); + SszStaticHandler::, MainnetEthSpec>::gloas_only() + .run(); + SszStaticHandler::, MainnetEthSpec>::gloas_only() + .run(); } #[test] @@ -622,6 +630,20 @@ mod ssz_static { .run(); } + #[test] + fn execution_payload_bid() { + SszStaticHandler::, MinimalEthSpec>::gloas_and_later() + .run(); + SszStaticHandler::, MainnetEthSpec>::gloas_and_later() + .run(); + } + + #[test] + fn signed_execution_payload_bid() { + SszStaticHandler::, MinimalEthSpec>::gloas_and_later().run(); + SszStaticHandler::, MainnetEthSpec>::gloas_and_later().run(); + } + #[test] fn withdrawal() { SszStaticHandler::::capella_and_later().run();