Move KZG commitments from payload envelope to payload bid and spec alpha.2 (#8725)

Co-Authored-By: Eitan Seri- Levi <eserilev@gmail.com>

Co-Authored-By: Michael Sproul <michael@sigmaprime.io>

Co-Authored-By: Jimmy Chen <jchen.tc@gmail.com>

Co-Authored-By: Michael Sproul <michaelsproul@users.noreply.github.com>
This commit is contained in:
Eitan Seri-Levi
2026-02-03 18:52:40 -08:00
committed by GitHub
parent 90a593aaea
commit 39727aa406
15 changed files with 81 additions and 39 deletions

View File

@@ -49,7 +49,7 @@ pub enum PubsubMessage<E: EthSpec> {
/// Gossipsub message providing notification of a payload attestation message. /// Gossipsub message providing notification of a payload attestation message.
PayloadAttestation(Box<PayloadAttestationMessage>), PayloadAttestation(Box<PayloadAttestationMessage>),
/// Gossipsub message providing notification of a signed execution payload bid. /// Gossipsub message providing notification of a signed execution payload bid.
ExecutionPayloadBid(Box<SignedExecutionPayloadBid>), ExecutionPayloadBid(Box<SignedExecutionPayloadBid<E>>),
/// Gossipsub message providing notification of signed proposer preferences. /// Gossipsub message providing notification of signed proposer preferences.
ProposerPreferences(Box<SignedProposerPreferences>), ProposerPreferences(Box<SignedProposerPreferences>),
/// Gossipsub message providing notification of a light client finality update. /// Gossipsub message providing notification of a light client finality update.

View File

@@ -3252,7 +3252,7 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
self: &Arc<Self>, self: &Arc<Self>,
message_id: MessageId, message_id: MessageId,
peer_id: PeerId, peer_id: PeerId,
payload_bid: SignedExecutionPayloadBid, payload_bid: SignedExecutionPayloadBid<T::EthSpec>,
) { ) {
// TODO(EIP-7732): Implement proper payload bid gossip processing. // TODO(EIP-7732): Implement proper payload bid gossip processing.
// This should integrate with a payload execution bid verification module once it's implemented. // This should integrate with a payload execution bid verification module once it's implemented.

View File

@@ -448,7 +448,7 @@ impl<T: BeaconChainTypes> NetworkBeaconProcessor<T> {
self: &Arc<Self>, self: &Arc<Self>,
message_id: MessageId, message_id: MessageId,
peer_id: PeerId, peer_id: PeerId,
execution_payload_bid: Box<SignedExecutionPayloadBid>, execution_payload_bid: Box<SignedExecutionPayloadBid<T::EthSpec>>,
) -> Result<(), Error<T::EthSpec>> { ) -> Result<(), Error<T::EthSpec>> {
let processor = self.clone(); let processor = self.clone();
let process_fn = move || { let process_fn = move || {

View File

@@ -84,11 +84,8 @@ pub fn get_builder_withdrawals<E: EthSpec>(
return Ok(None); 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().safe_sub(1)?;
let withdrawals_limit = E::max_withdrawals_per_payload();
// TODO(gloas): this assert is from `master`, remove this comment once it is part of the tested
// spec version.
block_verify!( block_verify!(
withdrawals.len() <= withdrawals_limit, withdrawals.len() <= withdrawals_limit,
BlockProcessingError::WithdrawalsLimitExceeded { BlockProcessingError::WithdrawalsLimitExceeded {
@@ -138,8 +135,6 @@ pub fn get_pending_partial_withdrawals<E: EthSpec>(
E::max_withdrawals_per_payload().safe_sub(1)?, 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!( block_verify!(
withdrawals.len() <= withdrawals_limit, withdrawals.len() <= withdrawals_limit,
BlockProcessingError::WithdrawalsLimitExceeded { BlockProcessingError::WithdrawalsLimitExceeded {
@@ -205,11 +200,8 @@ pub fn get_builders_sweep_withdrawals<E: EthSpec>(
let epoch = state.current_epoch(); let epoch = state.current_epoch();
let builders_limit = std::cmp::min(builders.len(), E::max_builders_per_withdrawals_sweep()); 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().safe_sub(1)?;
let withdrawals_limit = E::max_withdrawals_per_payload();
// TODO(gloas): this assert is from `master`, remove this comment once it is part of the tested
// spec version.
block_verify!( block_verify!(
withdrawals.len() <= withdrawals_limit, withdrawals.len() <= withdrawals_limit,
BlockProcessingError::WithdrawalsLimitExceeded { BlockProcessingError::WithdrawalsLimitExceeded {

View File

@@ -167,7 +167,7 @@ pub struct BeaconBlockBody<E: EthSpec, Payload: AbstractExecPayload<E> = FullPay
#[superstruct(only(Electra, Fulu))] #[superstruct(only(Electra, Fulu))]
pub execution_requests: ExecutionRequests<E>, pub execution_requests: ExecutionRequests<E>,
#[superstruct(only(Gloas))] #[superstruct(only(Gloas))]
pub signed_execution_payload_bid: SignedExecutionPayloadBid, pub signed_execution_payload_bid: SignedExecutionPayloadBid<E>,
#[superstruct(only(Gloas))] #[superstruct(only(Gloas))]
pub payload_attestations: VariableList<PayloadAttestation<E>, E::MaxPayloadAttestations>, pub payload_attestations: VariableList<PayloadAttestation<E>, E::MaxPayloadAttestations>,
#[superstruct(only(Base, Altair, Gloas))] #[superstruct(only(Base, Altair, Gloas))]

View File

@@ -1,5 +1,6 @@
use crate::kzg_ext::KzgCommitments;
use crate::test_utils::TestRandom; 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 context_deserialize::context_deserialize;
use educe::Educe; use educe::Educe;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -10,11 +11,16 @@ use tree_hash_derive::TreeHash;
#[derive( #[derive(
Default, Debug, Clone, Serialize, Encode, Decode, Deserialize, TreeHash, Educe, TestRandom, 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)] #[educe(PartialEq, Hash)]
#[serde(bound = "E: EthSpec")]
#[context_deserialize(ForkName)] #[context_deserialize(ForkName)]
// https://github.com/ethereum/consensus-specs/blob/master/specs/gloas/beacon-chain.md#executionpayloadbid // https://github.com/ethereum/consensus-specs/blob/master/specs/gloas/beacon-chain.md#executionpayloadbid
pub struct ExecutionPayloadBid { pub struct ExecutionPayloadBid<E: EthSpec> {
pub parent_block_hash: ExecutionBlockHash, pub parent_block_hash: ExecutionBlockHash,
pub parent_block_root: Hash256, pub parent_block_root: Hash256,
pub block_hash: ExecutionBlockHash, pub block_hash: ExecutionBlockHash,
@@ -30,14 +36,15 @@ pub struct ExecutionPayloadBid {
pub value: u64, pub value: u64,
#[serde(with = "serde_utils::quoted_u64")] #[serde(with = "serde_utils::quoted_u64")]
pub execution_payment: u64, pub execution_payment: u64,
pub blob_kzg_commitments_root: Hash256, pub blob_kzg_commitments: KzgCommitments<E>,
} }
impl SignedRoot for ExecutionPayloadBid {} impl<E: EthSpec> SignedRoot for ExecutionPayloadBid<E> {}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::MainnetEthSpec;
ssz_and_tree_hash_tests!(ExecutionPayloadBid); ssz_and_tree_hash_tests!(ExecutionPayloadBid<MainnetEthSpec>);
} }

View File

@@ -1,8 +1,6 @@
use crate::execution::{ExecutionPayloadGloas, ExecutionRequests};
use crate::test_utils::TestRandom; use crate::test_utils::TestRandom;
use crate::{ use crate::{EthSpec, ForkName, Hash256, SignedRoot, Slot};
EthSpec, ExecutionPayloadGloas, ExecutionRequests, ForkName, Hash256, KzgCommitments,
SignedRoot, Slot,
};
use context_deserialize::context_deserialize; use context_deserialize::context_deserialize;
use educe::Educe; use educe::Educe;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -21,7 +19,6 @@ pub struct ExecutionPayloadEnvelope<E: EthSpec> {
pub builder_index: u64, pub builder_index: u64,
pub beacon_block_root: Hash256, pub beacon_block_root: Hash256,
pub slot: Slot, pub slot: Slot,
pub blob_kzg_commitments: KzgCommitments<E>,
pub state_root: Hash256, pub state_root: Hash256,
} }

View File

@@ -1,5 +1,6 @@
use crate::execution::ExecutionPayloadBid;
use crate::test_utils::TestRandom; use crate::test_utils::TestRandom;
use crate::{ExecutionPayloadBid, ForkName}; use crate::{EthSpec, ForkName};
use bls::Signature; use bls::Signature;
use context_deserialize::context_deserialize; use context_deserialize::context_deserialize;
use educe::Educe; use educe::Educe;
@@ -9,16 +10,21 @@ use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash; use tree_hash_derive::TreeHash;
#[derive(TestRandom, TreeHash, Debug, Clone, Encode, Decode, Serialize, Deserialize, Educe)] #[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)] #[educe(PartialEq, Hash)]
#[serde(bound = "E: EthSpec")]
#[context_deserialize(ForkName)] #[context_deserialize(ForkName)]
// https://github.com/ethereum/consensus-specs/blob/master/specs/gloas/beacon-chain.md#signedexecutionpayloadbid // https://github.com/ethereum/consensus-specs/blob/master/specs/gloas/beacon-chain.md#signedexecutionpayloadbid
pub struct SignedExecutionPayloadBid { pub struct SignedExecutionPayloadBid<E: EthSpec> {
pub message: ExecutionPayloadBid, pub message: ExecutionPayloadBid<E>,
pub signature: Signature, pub signature: Signature,
} }
impl SignedExecutionPayloadBid { impl<E: EthSpec> SignedExecutionPayloadBid<E> {
pub fn empty() -> Self { pub fn empty() -> Self {
Self { Self {
message: ExecutionPayloadBid::default(), message: ExecutionPayloadBid::default(),
@@ -30,6 +36,7 @@ impl SignedExecutionPayloadBid {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::MainnetEthSpec;
ssz_and_tree_hash_tests!(SignedExecutionPayloadBid); ssz_and_tree_hash_tests!(SignedExecutionPayloadBid<MainnetEthSpec>);
} }

View File

@@ -548,7 +548,7 @@ where
pub latest_execution_payload_header: ExecutionPayloadHeaderFulu<E>, pub latest_execution_payload_header: ExecutionPayloadHeaderFulu<E>,
#[superstruct(only(Gloas))] #[superstruct(only(Gloas))]
#[metastruct(exclude_from(tree_lists))] #[metastruct(exclude_from(tree_lists))]
pub latest_execution_payload_bid: ExecutionPayloadBid, pub latest_execution_payload_bid: ExecutionPayloadBid<E>,
#[superstruct(only(Capella, Deneb, Electra, Fulu, Gloas), partial_getter(copy))] #[superstruct(only(Capella, Deneb, Electra, Fulu, Gloas), partial_getter(copy))]
#[serde(with = "serde_utils::quoted_u64")] #[serde(with = "serde_utils::quoted_u64")]
#[metastruct(exclude_from(tree_lists))] #[metastruct(exclude_from(tree_lists))]

View File

@@ -1,6 +1,6 @@
# To download/extract nightly tests, run: # To download/extract nightly tests, run:
# CONSENSUS_SPECS_TEST_VERSION=nightly make # 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 REPO_NAME := consensus-spec-tests
OUTPUT_DIR := ./$(REPO_NAME) OUTPUT_DIR := ./$(REPO_NAME)

View File

@@ -59,6 +59,8 @@ excluded_paths = [
# Ignore full epoch tests for now (just test the sub-transitions). # Ignore full epoch tests for now (just test the sub-transitions).
"tests/.*/.*/epoch_processing/.*/pre_epoch.ssz_snappy", "tests/.*/.*/epoch_processing/.*/pre_epoch.ssz_snappy",
"tests/.*/.*/epoch_processing/.*/post_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 # Ignore gloas tests for now
"tests/.*/gloas/.*", "tests/.*/gloas/.*",
# Ignore KZG tests that target internal kzg library functions # Ignore KZG tests that target internal kzg library functions

View File

@@ -45,7 +45,7 @@ struct ExecutionMetadata {
/// Newtype for testing withdrawals. /// Newtype for testing withdrawals.
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
pub struct WithdrawalsPayload<E: EthSpec> { pub struct WithdrawalsPayload<E: EthSpec> {
payload: ExecutionPayload<E>, payload: Option<ExecutionPayload<E>>,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@@ -405,10 +405,17 @@ impl<E: EthSpec> Operation<E> for WithdrawalsPayload<E> {
} }
fn decode(path: &Path, fork_name: ForkName, _spec: &ChainSpec) -> Result<Self, Error> { fn decode(path: &Path, fork_name: ForkName, _spec: &ChainSpec) -> Result<Self, Error> {
ssz_decode_file_with(path, |bytes| { if fork_name.gloas_enabled() {
ExecutionPayload::from_ssz_bytes_by_fork(bytes, fork_name) // No payload present or required for Gloas tests.
}) Ok(WithdrawalsPayload { payload: None })
.map(|payload| WithdrawalsPayload { payload }) } 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( fn apply_to(
@@ -420,7 +427,7 @@ impl<E: EthSpec> Operation<E> for WithdrawalsPayload<E> {
if state.fork_name_unchecked().gloas_enabled() { if state.fork_name_unchecked().gloas_enabled() {
withdrawals::gloas::process_withdrawals(state, spec) withdrawals::gloas::process_withdrawals(state, spec)
} else { } else {
let full_payload = FullPayload::from(self.payload.clone()); let full_payload = FullPayload::from(self.payload.clone().unwrap());
withdrawals::capella_electra::process_withdrawals::<_, FullPayload<_>>( withdrawals::capella_electra::process_withdrawals::<_, FullPayload<_>>(
state, state,
full_payload.to_ref(), full_payload.to_ref(),

View File

@@ -333,6 +333,10 @@ impl<T, E> SszStaticHandler<T, E> {
Self::for_forks(ForkName::list_all()[6..].to_vec()) 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 { pub fn pre_electra() -> Self {
Self::for_forks(ForkName::list_all()[0..5].to_vec()) Self::for_forks(ForkName::list_all()[0..5].to_vec())
} }

View File

@@ -55,6 +55,7 @@ type_name_generic!(BeaconBlockBodyCapella, "BeaconBlockBody");
type_name_generic!(BeaconBlockBodyDeneb, "BeaconBlockBody"); type_name_generic!(BeaconBlockBodyDeneb, "BeaconBlockBody");
type_name_generic!(BeaconBlockBodyElectra, "BeaconBlockBody"); type_name_generic!(BeaconBlockBodyElectra, "BeaconBlockBody");
type_name_generic!(BeaconBlockBodyFulu, "BeaconBlockBody"); type_name_generic!(BeaconBlockBodyFulu, "BeaconBlockBody");
type_name_generic!(BeaconBlockBodyGloas, "BeaconBlockBody");
type_name!(BeaconBlockHeader); type_name!(BeaconBlockHeader);
type_name_generic!(BeaconState); type_name_generic!(BeaconState);
type_name!(BlobIdentifier); type_name!(BlobIdentifier);
@@ -78,6 +79,7 @@ type_name_generic!(ExecutionPayloadCapella, "ExecutionPayload");
type_name_generic!(ExecutionPayloadDeneb, "ExecutionPayload"); type_name_generic!(ExecutionPayloadDeneb, "ExecutionPayload");
type_name_generic!(ExecutionPayloadElectra, "ExecutionPayload"); type_name_generic!(ExecutionPayloadElectra, "ExecutionPayload");
type_name_generic!(ExecutionPayloadFulu, "ExecutionPayload"); type_name_generic!(ExecutionPayloadFulu, "ExecutionPayload");
type_name_generic!(ExecutionPayloadGloas, "ExecutionPayload");
type_name_generic!(FullPayload, "ExecutionPayload"); type_name_generic!(FullPayload, "ExecutionPayload");
type_name_generic!(ExecutionPayloadHeader); type_name_generic!(ExecutionPayloadHeader);
type_name_generic!(ExecutionPayloadHeaderBellatrix, "ExecutionPayloadHeader"); type_name_generic!(ExecutionPayloadHeaderBellatrix, "ExecutionPayloadHeader");
@@ -85,6 +87,8 @@ type_name_generic!(ExecutionPayloadHeaderCapella, "ExecutionPayloadHeader");
type_name_generic!(ExecutionPayloadHeaderDeneb, "ExecutionPayloadHeader"); type_name_generic!(ExecutionPayloadHeaderDeneb, "ExecutionPayloadHeader");
type_name_generic!(ExecutionPayloadHeaderElectra, "ExecutionPayloadHeader"); type_name_generic!(ExecutionPayloadHeaderElectra, "ExecutionPayloadHeader");
type_name_generic!(ExecutionPayloadHeaderFulu, "ExecutionPayloadHeader"); type_name_generic!(ExecutionPayloadHeaderFulu, "ExecutionPayloadHeader");
type_name_generic!(ExecutionPayloadBid);
type_name_generic!(SignedExecutionPayloadBid);
type_name_generic!(ExecutionRequests); type_name_generic!(ExecutionRequests);
type_name_generic!(BlindedPayload, "ExecutionPayloadHeader"); type_name_generic!(BlindedPayload, "ExecutionPayloadHeader");
type_name!(Fork); type_name!(Fork);

View File

@@ -369,6 +369,10 @@ mod ssz_static {
.run(); .run();
SszStaticHandler::<BeaconBlockBodyFulu<MinimalEthSpec>, MinimalEthSpec>::fulu_only().run(); SszStaticHandler::<BeaconBlockBodyFulu<MinimalEthSpec>, MinimalEthSpec>::fulu_only().run();
SszStaticHandler::<BeaconBlockBodyFulu<MainnetEthSpec>, MainnetEthSpec>::fulu_only().run(); SszStaticHandler::<BeaconBlockBodyFulu<MainnetEthSpec>, MainnetEthSpec>::fulu_only().run();
SszStaticHandler::<BeaconBlockBodyGloas<MinimalEthSpec>, MinimalEthSpec>::gloas_only()
.run();
SszStaticHandler::<BeaconBlockBodyGloas<MainnetEthSpec>, MainnetEthSpec>::gloas_only()
.run();
} }
// Altair and later // Altair and later
@@ -596,6 +600,10 @@ mod ssz_static {
.run(); .run();
SszStaticHandler::<ExecutionPayloadFulu<MinimalEthSpec>, MinimalEthSpec>::fulu_only().run(); SszStaticHandler::<ExecutionPayloadFulu<MinimalEthSpec>, MinimalEthSpec>::fulu_only().run();
SszStaticHandler::<ExecutionPayloadFulu<MainnetEthSpec>, MainnetEthSpec>::fulu_only().run(); SszStaticHandler::<ExecutionPayloadFulu<MainnetEthSpec>, MainnetEthSpec>::fulu_only().run();
SszStaticHandler::<ExecutionPayloadGloas<MainnetEthSpec>, MainnetEthSpec>::gloas_only()
.run();
SszStaticHandler::<ExecutionPayloadGloas<MainnetEthSpec>, MainnetEthSpec>::gloas_only()
.run();
} }
#[test] #[test]
@@ -622,6 +630,20 @@ mod ssz_static {
.run(); .run();
} }
#[test]
fn execution_payload_bid() {
SszStaticHandler::<ExecutionPayloadBid<MinimalEthSpec>, MinimalEthSpec>::gloas_and_later()
.run();
SszStaticHandler::<ExecutionPayloadBid<MainnetEthSpec>, MainnetEthSpec>::gloas_and_later()
.run();
}
#[test]
fn signed_execution_payload_bid() {
SszStaticHandler::<SignedExecutionPayloadBid<MinimalEthSpec>, MinimalEthSpec>::gloas_and_later().run();
SszStaticHandler::<SignedExecutionPayloadBid<MainnetEthSpec>, MainnetEthSpec>::gloas_and_later().run();
}
#[test] #[test]
fn withdrawal() { fn withdrawal() {
SszStaticHandler::<Withdrawal, MinimalEthSpec>::capella_and_later().run(); SszStaticHandler::<Withdrawal, MinimalEthSpec>::capella_and_later().run();