eip-7732 containers

This commit is contained in:
shane-moore
2025-07-29 20:14:48 -07:00
committed by Mark Mackey
parent 3e78034de6
commit 7dac892c71
13 changed files with 589 additions and 3 deletions

View File

@@ -0,0 +1,34 @@
use crate::test_utils::TestRandom;
use crate::*;
use serde::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash;
#[derive(
Debug,
PartialEq,
Eq,
Hash,
Clone,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
TestRandom,
)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[context_deserialize(ForkName)]
pub struct BuilderPendingPayment {
#[serde(with = "serde_utils::quoted_u64")]
pub weight: u64,
pub withdrawal: BuilderPendingWithdrawal,
}
#[cfg(test)]
mod tests {
use super::*;
ssz_and_tree_hash_tests!(BuilderPendingPayment);
}

View File

@@ -0,0 +1,38 @@
use crate::test_utils::TestRandom;
use crate::*;
use serde::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash;
#[derive(
Debug,
PartialEq,
Eq,
Hash,
Clone,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
TestRandom,
)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[context_deserialize(ForkName)]
pub struct BuilderPendingWithdrawal {
#[serde(with = "serde_utils::address_hex")]
pub fee_recipient: Address,
#[serde(with = "serde_utils::quoted_u64")]
pub amount: u64,
#[serde(with = "serde_utils::quoted_u64")]
pub builder_index: u64,
pub withdrawable_epoch: Epoch,
}
#[cfg(test)]
mod tests {
use super::*;
ssz_and_tree_hash_tests!(BuilderPendingWithdrawal);
}

View File

@@ -28,6 +28,8 @@ pub enum Domain {
SyncCommittee,
ContributionAndProof,
SyncCommitteeSelectionProof,
BeaconBuilder,
PTCAttester,
ApplicationMask(ApplicationDomain),
}
@@ -81,6 +83,7 @@ pub struct ChainSpec {
pub bls_withdrawal_prefix_byte: u8,
pub eth1_address_withdrawal_prefix_byte: u8,
pub compounding_withdrawal_prefix_byte: u8,
pub builder_withdrawal_prefix_byte: u8,
/*
* Time parameters
@@ -113,6 +116,8 @@ pub struct ChainSpec {
pub(crate) domain_voluntary_exit: u32,
pub(crate) domain_selection_proof: u32,
pub(crate) domain_aggregate_and_proof: u32,
pub(crate) domain_beacon_builder: u32,
pub(crate) domain_ptc_attester: u32,
/*
* Fork choice
@@ -214,6 +219,8 @@ pub struct ChainSpec {
pub gloas_fork_version: [u8; 4],
/// The Gloas fork epoch is optional, with `None` representing "Gloas never happens".
pub gloas_fork_epoch: Option<Epoch>,
pub builder_payment_threshold_numerator: u64,
pub builder_payment_threshold_denominator: u64,
/*
* Networking
@@ -513,6 +520,8 @@ impl ChainSpec {
Domain::VoluntaryExit => self.domain_voluntary_exit,
Domain::SelectionProof => self.domain_selection_proof,
Domain::AggregateAndProof => self.domain_aggregate_and_proof,
Domain::BeaconBuilder => self.domain_beacon_builder,
Domain::PTCAttester => self.domain_ptc_attester,
Domain::SyncCommittee => self.domain_sync_committee,
Domain::ContributionAndProof => self.domain_contribution_and_proof,
Domain::SyncCommitteeSelectionProof => self.domain_sync_committee_selection_proof,
@@ -922,6 +931,7 @@ impl ChainSpec {
bls_withdrawal_prefix_byte: 0x00,
eth1_address_withdrawal_prefix_byte: 0x01,
compounding_withdrawal_prefix_byte: 0x02,
builder_withdrawal_prefix_byte: 0x03,
/*
* Time parameters
@@ -955,6 +965,8 @@ impl ChainSpec {
domain_voluntary_exit: 4,
domain_selection_proof: 5,
domain_aggregate_and_proof: 6,
domain_beacon_builder: 0x1B,
domain_ptc_attester: 0x0C,
/*
* Fork choice
@@ -1075,6 +1087,8 @@ impl ChainSpec {
*/
gloas_fork_version: [0x07, 0x00, 0x00, 0x00],
gloas_fork_epoch: None,
builder_payment_threshold_numerator: 6,
builder_payment_threshold_denominator: 10,
/*
* Network specific
@@ -1268,6 +1282,7 @@ impl ChainSpec {
bls_withdrawal_prefix_byte: 0x00,
eth1_address_withdrawal_prefix_byte: 0x01,
compounding_withdrawal_prefix_byte: 0x02,
builder_withdrawal_prefix_byte: 0x03,
/*
* Time parameters
@@ -1301,6 +1316,8 @@ impl ChainSpec {
domain_voluntary_exit: 4,
domain_selection_proof: 5,
domain_aggregate_and_proof: 6,
domain_beacon_builder: 0x1B,
domain_ptc_attester: 0x0C,
/*
* Fork choice
@@ -1421,6 +1438,8 @@ impl ChainSpec {
*/
gloas_fork_version: [0x07, 0x00, 0x00, 0x64],
gloas_fork_epoch: None,
builder_payment_threshold_numerator: 6,
builder_payment_threshold_denominator: 10,
/*
* Network specific
@@ -1690,6 +1709,12 @@ pub struct Config {
#[serde(serialize_with = "serialize_fork_epoch")]
#[serde(deserialize_with = "deserialize_fork_epoch")]
pub gloas_fork_epoch: Option<MaybeQuoted<Epoch>>,
#[serde(default = "default_builder_payment_threshold_numerator")]
#[serde(with = "serde_utils::quoted_u64")]
pub builder_payment_threshold_numerator: u64,
#[serde(default = "default_builder_payment_threshold_denominator")]
#[serde(with = "serde_utils::quoted_u64")]
pub builder_payment_threshold_denominator: u64,
#[serde(with = "serde_utils::quoted_u64")]
seconds_per_slot: u64,
@@ -1853,6 +1878,14 @@ fn default_gloas_fork_version() -> [u8; 4] {
[0xff, 0xff, 0xff, 0xff]
}
fn default_builder_payment_threshold_numerator() -> u64 {
6
}
fn default_builder_payment_threshold_denominator() -> u64 {
10
}
/// Placeholder value: 2^256-2^10 (115792089237316195423570985008687907853269984665640564039457584007913129638912).
///
/// Taken from https://github.com/ethereum/consensus-specs/blob/d5e4828aecafaf1c57ef67a5f23c4ae7b08c5137/configs/mainnet.yaml#L15-L16
@@ -2154,6 +2187,9 @@ impl Config {
.gloas_fork_epoch
.map(|epoch| MaybeQuoted { value: epoch }),
builder_payment_threshold_numerator: spec.builder_payment_threshold_numerator,
builder_payment_threshold_denominator: spec.builder_payment_threshold_denominator,
seconds_per_slot: spec.seconds_per_slot,
seconds_per_eth1_block: spec.seconds_per_eth1_block,
min_validator_withdrawability_delay: spec.min_validator_withdrawability_delay,
@@ -2245,6 +2281,8 @@ impl Config {
fulu_fork_version,
gloas_fork_version,
gloas_fork_epoch,
builder_payment_threshold_numerator,
builder_payment_threshold_denominator,
seconds_per_slot,
seconds_per_eth1_block,
min_validator_withdrawability_delay,
@@ -2318,6 +2356,8 @@ impl Config {
fulu_fork_version,
gloas_fork_version,
gloas_fork_epoch: gloas_fork_epoch.map(|q| q.value),
builder_payment_threshold_numerator,
builder_payment_threshold_denominator,
seconds_per_slot,
seconds_per_eth1_block,
min_validator_withdrawability_delay,
@@ -2443,6 +2483,8 @@ mod tests {
spec.domain_aggregate_and_proof,
&spec,
);
test_domain(Domain::BeaconBuilder, spec.domain_beacon_builder, &spec);
test_domain(Domain::PTCAttester, spec.domain_ptc_attester, &spec);
test_domain(Domain::SyncCommittee, spec.domain_sync_committee, &spec);
// The builder domain index is zero

View File

@@ -75,6 +75,7 @@ pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq +
type EpochsPerSlashingsVector: Unsigned + Clone + Sync + Send + Debug + PartialEq;
type HistoricalRootsLimit: Unsigned + Clone + Sync + Send + Debug + PartialEq;
type ValidatorRegistryLimit: Unsigned + Clone + Sync + Send + Debug + PartialEq;
type BuilderPendingWithdrawalsLimit: Unsigned + Clone + Sync + Send + Debug + PartialEq;
/*
* Max operations per block
*/
@@ -165,6 +166,12 @@ pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq +
type MaxWithdrawalRequestsPerPayload: Unsigned + Clone + Sync + Send + Debug + PartialEq;
type MaxPendingDepositsPerEpoch: Unsigned + Clone + Sync + Send + Debug + PartialEq;
/*
* New in Gloas
*/
type PTCSize: Unsigned + Clone + Sync + Send + Debug + PartialEq;
type MaxPayloadAttestations: Unsigned + Clone + Sync + Send + Debug + PartialEq;
fn default_spec() -> ChainSpec;
fn spec_name() -> EthSpecId;
@@ -346,6 +353,11 @@ pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq +
Self::PendingConsolidationsLimit::to_usize()
}
/// Returns the `BUILDER_PENDING_WITHDRAWALS_LIMIT` constant for this specification.
fn builder_pending_withdrawals_limit() -> usize {
Self::BuilderPendingWithdrawalsLimit::to_usize()
}
/// Returns the `MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD` constant for this specification.
fn max_consolidation_requests_per_payload() -> usize {
Self::MaxConsolidationRequestsPerPayload::to_usize()
@@ -391,6 +403,14 @@ pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq +
fn proposer_lookahead_slots() -> usize {
Self::ProposerLookaheadSlots::to_usize()
}
fn ptc_size() -> usize {
Self::PTCSize::to_usize()
}
fn max_payload_attestations() -> usize {
Self::MaxPayloadAttestations::to_usize()
}
}
/// Macro to inherit some type values from another EthSpec.
@@ -420,6 +440,7 @@ impl EthSpec for MainnetEthSpec {
type EpochsPerSlashingsVector = U8192;
type HistoricalRootsLimit = U16777216;
type ValidatorRegistryLimit = U1099511627776;
type BuilderPendingWithdrawalsLimit = U1048576;
type MaxProposerSlashings = U16;
type MaxAttesterSlashings = U2;
type MaxAttestations = U128;
@@ -460,6 +481,8 @@ impl EthSpec for MainnetEthSpec {
type MaxAttestationsElectra = U8;
type MaxWithdrawalRequestsPerPayload = U16;
type MaxPendingDepositsPerEpoch = U16;
type PTCSize = U64; // todo: verify if needs to be U512 for some reason like in Mark's OG implementation
type MaxPayloadAttestations = U2;
fn default_spec() -> ChainSpec {
ChainSpec::mainnet()
@@ -511,6 +534,7 @@ impl EthSpec for MinimalEthSpec {
GenesisEpoch,
HistoricalRootsLimit,
ValidatorRegistryLimit,
BuilderPendingWithdrawalsLimit,
MaxProposerSlashings,
MaxAttesterSlashings,
MaxAttestations,
@@ -530,7 +554,9 @@ impl EthSpec for MinimalEthSpec {
MaxAttesterSlashingsElectra,
MaxAttestationsElectra,
MaxDepositRequestsPerPayload,
MaxWithdrawalRequestsPerPayload
MaxWithdrawalRequestsPerPayload,
PTCSize,
MaxPayloadAttestations
});
fn default_spec() -> ChainSpec {
@@ -561,6 +587,7 @@ impl EthSpec for GnosisEthSpec {
type EpochsPerSlashingsVector = U8192;
type HistoricalRootsLimit = U16777216;
type ValidatorRegistryLimit = U1099511627776;
type BuilderPendingWithdrawalsLimit = U1048576;
type MaxProposerSlashings = U16;
type MaxAttesterSlashings = U2;
type MaxAttestations = U128;
@@ -601,6 +628,8 @@ impl EthSpec for GnosisEthSpec {
type CellsPerExtBlob = U128;
type NumberOfColumns = U128;
type ProposerLookaheadSlots = U32; // Derived from (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH
type PTCSize = U64; // todo: verify if needs to be U512 for some reason like in Mark's OG implementation
type MaxPayloadAttestations = U2;
fn default_spec() -> ChainSpec {
ChainSpec::gnosis()

View File

@@ -0,0 +1,47 @@
use crate::{test_utils::TestRandom, *};
use derivative::Derivative;
use serde::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash;
#[derive(
Default,
Debug,
Clone,
Serialize,
Encode,
Decode,
Deserialize,
TreeHash,
Derivative,
TestRandom,
)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derivative(PartialEq, Hash)]
#[context_deserialize(ForkName)]
// This is what Potuz' spec calls an `ExecutionPayload` even though it's clearly a bid.
pub struct ExecutionBid {
pub parent_block_hash: ExecutionBlockHash,
pub parent_block_root: Hash256,
pub block_hash: ExecutionBlockHash,
#[serde(with = "serde_utils::address_hex")]
pub fee_recipient: Address, // todo(eip-7732): verify if this needs address_hex serialization
#[serde(with = "serde_utils::quoted_u64")]
pub gas_limit: u64,
#[serde(with = "serde_utils::quoted_u64")]
pub builder_index: u64,
pub slot: Slot,
#[serde(with = "serde_utils::quoted_u64")]
pub value: u64,
pub blob_kzg_commitments_root: Hash256,
}
impl SignedRoot for ExecutionBid {}
#[cfg(test)]
mod tests {
use super::*;
ssz_and_tree_hash_tests!(ExecutionBid);
}

View File

@@ -0,0 +1,103 @@
use crate::test_utils::TestRandom;
use crate::*;
use beacon_block_body::KzgCommitments;
use derivative::Derivative;
use serde::de::{Deserializer, Error as _};
use serde::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode};
use superstruct::superstruct;
use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash;
// in all likelihood, this will be superstructed so might as well start early eh?
#[superstruct(
variants(Gloas, NextFork),
variant_attributes(
derive(
Debug,
Clone,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
TestRandom,
Derivative
),
cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary)),
derivative(PartialEq, Hash(bound = "E: EthSpec")),
serde(bound = "E: EthSpec", deny_unknown_fields),
cfg_attr(feature = "arbitrary", arbitrary(bound = "E: EthSpec"))
),
ref_attributes(
derive(Debug, PartialEq, TreeHash),
tree_hash(enum_behaviour = "transparent")
),
cast_error(ty = "Error", expr = "BeaconStateError::IncorrectStateVariant"),
partial_getter_error(ty = "Error", expr = "BeaconStateError::IncorrectStateVariant")
)]
#[derive(Debug, Clone, Serialize, Encode, Deserialize, TreeHash, Derivative)]
#[derivative(PartialEq, Hash(bound = "E: EthSpec"))]
#[serde(bound = "E: EthSpec", untagged)]
#[ssz(enum_behaviour = "transparent")]
#[tree_hash(enum_behaviour = "transparent")]
pub struct ExecutionPayloadEnvelope<E: EthSpec> {
#[superstruct(only(Gloas), partial_getter(rename = "payload_gloas"))]
pub payload: ExecutionPayloadGloas<E>,
#[superstruct(only(NextFork), partial_getter(rename = "payload_next_fork"))]
pub payload: ExecutionPayloadGloas<E>,
pub execution_requests: ExecutionRequests<E>,
#[serde(with = "serde_utils::quoted_u64")]
#[superstruct(getter(copy))]
pub builder_index: u64,
#[superstruct(getter(copy))]
pub beacon_block_root: Hash256,
#[superstruct(getter(copy))]
pub slot: Slot,
pub blob_kzg_commitments: KzgCommitments<E>,
#[superstruct(getter(copy))]
pub state_root: Hash256,
}
impl<'a, E: EthSpec> SignedRoot for ExecutionPayloadEnvelopeRef<'a, E> {}
impl<'a, E: EthSpec> ExecutionPayloadEnvelopeRef<'a, E> {
pub fn payload(&self) -> ExecutionPayloadRef<'a, E> {
match self {
Self::Gloas(envelope) => ExecutionPayloadRef::Gloas(&envelope.payload),
Self::NextFork(envelope) => ExecutionPayloadRef::Gloas(&envelope.payload),
}
}
}
impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for ExecutionPayloadEnvelope<E> {
fn context_deserialize<D>(deserializer: D, context: ForkName) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let value: Self = serde::Deserialize::deserialize(deserializer)?;
match (context, &value) {
(ForkName::Gloas, Self::Gloas { .. }) => Ok(value),
_ => Err(D::Error::custom(format!(
"ExecutionPayloadEnvelope does not support fork {context:?}"
))),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::MainnetEthSpec;
mod gloas {
use super::*;
ssz_and_tree_hash_tests!(ExecutionPayloadEnvelopeGloas<MainnetEthSpec>);
}
mod next_fork {
use super::*;
ssz_and_tree_hash_tests!(ExecutionPayloadEnvelopeNextFork<MainnetEthSpec>);
}
}

View File

@@ -0,0 +1,41 @@
use crate::test_utils::TestRandom;
use crate::*;
use core::slice::Iter;
use serde::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash;
#[derive(
TestRandom,
TreeHash,
Debug,
Clone,
PartialEq,
Encode,
Decode,
Serialize,
Deserialize,
)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[serde(bound = "E: EthSpec", deny_unknown_fields)]
#[cfg_attr(feature = "arbitrary", arbitrary(bound = "E: EthSpec"))]
#[context_deserialize(ForkName)]
pub struct IndexedPayloadAttestation<E: EthSpec> {
pub attesting_indices: VariableList<u64, E::PTCSize>,
pub data: PayloadAttestationData,
pub signature: AggregateSignature,
}
impl<E: EthSpec> IndexedPayloadAttestation<E> {
pub fn attesting_indices_iter(&self) -> Iter<'_, u64> {
self.attesting_indices.iter()
}
}
#[cfg(test)]
mod tests {
use super::*;
ssz_and_tree_hash_tests!(IndexedPayloadAttestation<MainnetEthSpec>);
}

View File

@@ -26,6 +26,8 @@ pub mod beacon_response;
pub mod beacon_state;
pub mod bls_to_execution_change;
pub mod builder_bid;
pub mod builder_pending_payment;
pub mod builder_pending_withdrawal;
pub mod chain_spec;
pub mod checkpoint;
pub mod consolidation_request;
@@ -39,8 +41,10 @@ pub mod deposit_tree_snapshot;
pub mod enr_fork_id;
pub mod eth1_data;
pub mod eth_spec;
pub mod execution_bid;
pub mod execution_block_hash;
pub mod execution_payload;
pub mod execution_payload_envelope;
pub mod execution_payload_header;
pub mod fork;
pub mod fork_data;
@@ -49,10 +53,15 @@ pub mod graffiti;
pub mod historical_batch;
pub mod historical_summary;
pub mod indexed_attestation;
pub mod indexed_payload_attestation;
pub mod light_client_bootstrap;
pub mod light_client_finality_update;
pub mod light_client_optimistic_update;
pub mod light_client_update;
pub mod payload;
pub mod payload_attestation;
pub mod payload_attestation_data;
pub mod payload_attestation_message;
pub mod pending_attestation;
pub mod pending_consolidation;
pub mod pending_deposit;
@@ -67,6 +76,8 @@ pub mod signed_beacon_block;
pub mod signed_beacon_block_header;
pub mod signed_bls_to_execution_change;
pub mod signed_contribution_and_proof;
pub mod signed_execution_bid;
pub mod signed_execution_payload_envelope;
pub mod signed_voluntary_exit;
pub mod signing_data;
pub mod sync_committee_subscription;
@@ -84,7 +95,6 @@ pub mod execution_block_header;
pub mod execution_requests;
pub mod fork_context;
pub mod participation_flags;
pub mod payload;
pub mod preset;
pub mod slot_epoch;
pub mod subnet_id;
@@ -144,6 +154,8 @@ pub use crate::beacon_response::{
pub use crate::beacon_state::{Error as BeaconStateError, *};
pub use crate::blob_sidecar::{BlobIdentifier, BlobSidecar, BlobSidecarList, BlobsList};
pub use crate::bls_to_execution_change::BlsToExecutionChange;
pub use crate::builder_pending_payment::BuilderPendingPayment;
pub use crate::builder_pending_withdrawal::BuilderPendingWithdrawal;
pub use crate::chain_spec::{ChainSpec, Config, Domain};
pub use crate::checkpoint::Checkpoint;
pub use crate::config_and_preset::{
@@ -163,8 +175,9 @@ pub use crate::deposit_request::DepositRequest;
pub use crate::deposit_tree_snapshot::{DepositTreeSnapshot, FinalizedExecutionBlock};
pub use crate::enr_fork_id::EnrForkId;
pub use crate::epoch_cache::{EpochCache, EpochCacheError, EpochCacheKey};
pub use crate::eth_spec::EthSpecId;
pub use crate::eth1_data::Eth1Data;
pub use crate::eth_spec::EthSpecId;
pub use crate::execution_bid::ExecutionBid;
pub use crate::execution_block_hash::ExecutionBlockHash;
pub use crate::execution_block_header::{EncodableExecutionBlockHeader, ExecutionBlockHeader};
pub use crate::execution_payload::{
@@ -172,6 +185,10 @@ pub use crate::execution_payload::{
ExecutionPayloadElectra, ExecutionPayloadFulu, ExecutionPayloadGloas, ExecutionPayloadRef,
Transaction, Transactions, Withdrawals,
};
pub use crate::execution_payload_envelope::{
ExecutionPayloadEnvelope, ExecutionPayloadEnvelopeGloas, ExecutionPayloadEnvelopeNextFork,
ExecutionPayloadEnvelopeRef,
};
pub use crate::execution_payload_header::{
ExecutionPayloadHeader, ExecutionPayloadHeaderBellatrix, ExecutionPayloadHeaderCapella,
ExecutionPayloadHeaderDeneb, ExecutionPayloadHeaderElectra, ExecutionPayloadHeaderFulu,
@@ -187,6 +204,7 @@ pub use crate::historical_batch::HistoricalBatch;
pub use crate::indexed_attestation::{
IndexedAttestation, IndexedAttestationBase, IndexedAttestationElectra, IndexedAttestationRef,
};
pub use crate::indexed_payload_attestation::IndexedPayloadAttestation;
pub use crate::light_client_bootstrap::{
LightClientBootstrap, LightClientBootstrapAltair, LightClientBootstrapCapella,
LightClientBootstrapDeneb, LightClientBootstrapElectra, LightClientBootstrapFulu,
@@ -220,6 +238,9 @@ pub use crate::payload::{
FullPayloadCapella, FullPayloadDeneb, FullPayloadElectra, FullPayloadFulu, FullPayloadGloas,
FullPayloadRef, OwnedExecPayload,
};
pub use crate::payload_attestation::PayloadAttestation;
pub use crate::payload_attestation_data::PayloadAttestationData;
pub use crate::payload_attestation_message::PayloadAttestationMessage;
pub use crate::pending_attestation::PendingAttestation;
pub use crate::pending_consolidation::PendingConsolidation;
pub use crate::pending_deposit::PendingDeposit;
@@ -247,6 +268,8 @@ pub use crate::signed_beacon_block::{
pub use crate::signed_beacon_block_header::SignedBeaconBlockHeader;
pub use crate::signed_bls_to_execution_change::SignedBlsToExecutionChange;
pub use crate::signed_contribution_and_proof::SignedContributionAndProof;
pub use crate::signed_execution_bid::SignedExecutionBid;
pub use crate::signed_execution_payload_envelope::SignedExecutionPayloadEnvelope;
pub use crate::signed_voluntary_exit::SignedVoluntaryExit;
pub use crate::signing_data::{SignedRoot, SigningData};
pub use crate::slot_epoch::{Epoch, Slot};

View File

@@ -0,0 +1,36 @@
use crate::test_utils::TestRandom;
use crate::*;
use derivative::Derivative;
use serde::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash;
#[derive(
TestRandom,
TreeHash,
Debug,
Clone,
Encode,
Decode,
Serialize,
Deserialize,
Derivative,
)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[serde(bound = "E: EthSpec", deny_unknown_fields)]
#[cfg_attr(feature = "arbitrary", arbitrary(bound = "E: EthSpec"))]
#[derivative(PartialEq, Hash)]
#[context_deserialize(ForkName)]
pub struct PayloadAttestation<E: EthSpec> {
pub aggregation_bits: BitList<E::PTCSize>,
pub data: PayloadAttestationData,
pub signature: AggregateSignature,
}
#[cfg(test)]
mod payload_attestation_tests {
use super::*;
ssz_and_tree_hash_tests!(PayloadAttestation<MinimalEthSpec>);
}

View File

@@ -0,0 +1,27 @@
use crate::test_utils::TestRandom;
use crate::*;
use serde::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash;
#[derive(
TestRandom, TreeHash, Debug, Clone, PartialEq, Eq, Encode, Decode, Serialize, Deserialize, Hash,
)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[context_deserialize(ForkName)]
pub struct PayloadAttestationData {
pub beacon_block_root: Hash256,
pub slot: Slot,
pub payload_present: bool,
}
// todo(eip-7732): Mark's implementation has PayloadStatus as an enum, but spec calls for a bool. Need to clarify this.
impl SignedRoot for PayloadAttestationData {}
#[cfg(test)]
mod payload_attestation_data_tests {
use super::*;
ssz_and_tree_hash_tests!(PayloadAttestationData);
}

View File

@@ -0,0 +1,33 @@
use crate::test_utils::TestRandom;
use crate::*;
use serde::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash;
#[derive(
TestRandom,
TreeHash,
Debug,
Clone,
PartialEq,
Encode,
Decode,
Serialize,
Deserialize,
)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[context_deserialize(ForkName)]
pub struct PayloadAttestationMessage {
#[serde(with = "serde_utils::quoted_u64")]
pub validator_index: u64,
pub data: PayloadAttestationData,
pub signature: AggregateSignature,
}
#[cfg(test)]
mod tests {
use super::*;
ssz_and_tree_hash_tests!(PayloadAttestationMessage);
}

View File

@@ -0,0 +1,42 @@
use crate::test_utils::TestRandom;
use crate::*;
use derivative::Derivative;
use serde::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode};
use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash;
#[derive(
TestRandom,
TreeHash,
Debug,
Clone,
Encode,
Decode,
Serialize,
Deserialize,
Derivative,
)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derivative(PartialEq, Hash)]
#[context_deserialize(ForkName)]
pub struct SignedExecutionBid {
pub message: ExecutionBid,
pub signature: Signature,
}
impl SignedExecutionBid {
pub fn empty() -> Self {
Self {
message: ExecutionBid::default(),
signature: Signature::empty(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
ssz_and_tree_hash_tests!(SignedExecutionBid);
}

View File

@@ -0,0 +1,91 @@
use crate::test_utils::TestRandom;
use crate::*;
use derivative::Derivative;
use serde::de::{Deserializer, Error as _};
use serde::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode};
use superstruct::superstruct;
use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash;
#[superstruct(
variants(Gloas, NextFork),
variant_attributes(
derive(
Debug,
Clone,
Serialize,
Deserialize,
Encode,
Decode,
TreeHash,
TestRandom,
Derivative
),
cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary)),
derivative(PartialEq, Hash(bound = "E: EthSpec")),
serde(bound = "E: EthSpec", deny_unknown_fields),
cfg_attr(feature = "arbitrary", arbitrary(bound = "E: EthSpec"))
),
ref_attributes(
derive(Debug, PartialEq, TreeHash),
tree_hash(enum_behaviour = "transparent")
),
cast_error(ty = "Error", expr = "BeaconStateError::IncorrectStateVariant"),
partial_getter_error(ty = "Error", expr = "BeaconStateError::IncorrectStateVariant")
)]
#[derive(Debug, Clone, Serialize, Encode, Deserialize, TreeHash, Derivative)]
#[derivative(PartialEq, Hash(bound = "E: EthSpec"))]
#[serde(bound = "E: EthSpec", untagged)]
#[ssz(enum_behaviour = "transparent")]
#[tree_hash(enum_behaviour = "transparent")]
pub struct SignedExecutionPayloadEnvelope<E: EthSpec> {
#[superstruct(only(Gloas), partial_getter(rename = "message_gloas"))]
pub message: ExecutionPayloadEnvelopeGloas<E>,
#[superstruct(only(NextFork), partial_getter(rename = "message_next_fork"))]
pub message: crate::execution_payload_envelope::ExecutionPayloadEnvelopeNextFork<E>,
pub signature: Signature,
}
impl<E: EthSpec> SignedExecutionPayloadEnvelope<E> {
pub fn message(&self) -> ExecutionPayloadEnvelopeRef<E> {
match self {
Self::Gloas(ref signed) => ExecutionPayloadEnvelopeRef::Gloas(&signed.message),
Self::NextFork(ref signed) => ExecutionPayloadEnvelopeRef::NextFork(&signed.message),
}
}
// todo(eip-7732): implement verify_signature since spec calls for verify_execution_payload_envelope_signature
}
impl<'de, E: EthSpec> ContextDeserialize<'de, ForkName> for SignedExecutionPayloadEnvelope<E> {
fn context_deserialize<D>(deserializer: D, context: ForkName) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let value: Self = Deserialize::deserialize(deserializer)?;
match (context, &value) {
(ForkName::Gloas, Self::Gloas { .. }) => Ok(value),
_ => Err(D::Error::custom(format!(
"SignedExecutionPayloadEnvelope does not support fork {context:?}"
))),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::MainnetEthSpec;
mod gloas {
use super::*;
ssz_and_tree_hash_tests!(SignedExecutionPayloadEnvelopeGloas<MainnetEthSpec>);
}
mod next_fork {
use super::*;
ssz_and_tree_hash_tests!(SignedExecutionPayloadEnvelopeNextFork<MainnetEthSpec>);
}
}