Updated for queueless withdrawals spec

This commit is contained in:
Mark Mackey
2022-11-09 18:09:07 -06:00
parent bc0af72c74
commit ab13f95db5
20 changed files with 209 additions and 224 deletions

View File

@@ -62,6 +62,10 @@ pub struct BeaconBlockBody<T: EthSpec, Payload: AbstractExecPayload<T> = FullPay
#[superstruct(only(Eip4844), partial_getter(rename = "execution_payload_eip4844"))]
#[serde(flatten)]
pub execution_payload: Payload::Eip4844,
#[cfg(feature = "withdrawals")]
#[superstruct(only(Capella, Eip4844))]
pub bls_to_execution_changes:
VariableList<SignedBlsToExecutionChange, T::MaxBlsToExecutionChanges>,
#[superstruct(only(Eip4844))]
pub blob_kzg_commitments: VariableList<KzgCommitment, T::MaxBlobsPerBlock>,
#[superstruct(only(Base, Altair))]

View File

@@ -297,13 +297,10 @@ where
// Withdrawals
#[cfg(feature = "withdrawals")]
#[superstruct(only(Capella, Eip4844))]
pub withdrawal_queue: VariableList<Withdrawal, T::WithdrawalQueueLimit>,
#[cfg(feature = "withdrawals")]
#[superstruct(only(Capella, Eip4844))]
pub next_withdrawal_index: u64,
#[cfg(feature = "withdrawals")]
#[superstruct(only(Capella, Eip4844))]
pub next_partial_withdrawal_validator_index: u64,
pub latest_withdrawal_validator_index: u64,
// Caching (not in the spec)
#[serde(skip_serializing, skip_deserializing)]

View File

@@ -98,8 +98,6 @@ pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq +
/*
* New in Capella
*/
type MaxPartialWithdrawalsPerEpoch: Unsigned + Clone + Sync + Send + Debug + PartialEq;
type WithdrawalQueueLimit: Unsigned + Clone + Sync + Send + Debug + PartialEq;
type MaxBlsToExecutionChanges: Unsigned + Clone + Sync + Send + Debug + PartialEq;
type MaxWithdrawalsPerPayload: Unsigned + Clone + Sync + Send + Debug + PartialEq;
/*
@@ -235,16 +233,6 @@ pub trait EthSpec: 'static + Default + Sync + Send + Clone + Debug + PartialEq +
Self::BytesPerLogsBloom::to_usize()
}
/// Returns the `MAX_PARTIAL_WITHDRAWALS_PER_EPOCH` constant for this specification.
fn max_partial_withdrawals_per_epoch() -> usize {
Self::MaxPartialWithdrawalsPerEpoch::to_usize()
}
/// Returns the `WITHDRAWAL_QUEUE_LIMIT` constant for this specification.
fn withdrawal_queue_limit() -> usize {
Self::WithdrawalQueueLimit::to_usize()
}
/// Returns the `MAX_BLS_TO_EXECUTION_CHANGES` constant for this specification.
fn max_bls_to_execution_changes() -> usize {
Self::MaxBlsToExecutionChanges::to_usize()
@@ -309,8 +297,6 @@ impl EthSpec for MainnetEthSpec {
type SyncSubcommitteeSize = U128; // 512 committee size / 4 sync committee subnet count
type MaxPendingAttestations = U4096; // 128 max attestations * 32 slots per epoch
type SlotsPerEth1VotingPeriod = U2048; // 64 epochs * 32 slots per epoch
type MaxPartialWithdrawalsPerEpoch = U256;
type WithdrawalQueueLimit = U1099511627776;
type MaxBlsToExecutionChanges = U16;
type MaxWithdrawalsPerPayload = U16;
@@ -358,8 +344,6 @@ impl EthSpec for MinimalEthSpec {
GasLimitDenominator,
MinGasLimit,
MaxExtraDataBytes,
MaxPartialWithdrawalsPerEpoch,
WithdrawalQueueLimit,
MaxBlsToExecutionChanges,
MaxWithdrawalsPerPayload,
MaxBlobsPerBlock,
@@ -408,8 +392,6 @@ impl EthSpec for GnosisEthSpec {
type SyncSubcommitteeSize = U128; // 512 committee size / 4 sync committee subnet count
type MaxPendingAttestations = U2048; // 128 max attestations * 16 slots per epoch
type SlotsPerEth1VotingPeriod = U1024; // 64 epochs * 16 slots per epoch
type MaxPartialWithdrawalsPerEpoch = U256;
type WithdrawalQueueLimit = U1099511627776;
type MaxBlsToExecutionChanges = U16;
type MaxWithdrawalsPerPayload = U16;
type MaxBlobsPerBlock = U16; // 2**4 = 16

View File

@@ -3,7 +3,6 @@ use derivative::Derivative;
use serde_derive::{Deserialize, Serialize};
use ssz::Encode;
use ssz_derive::{Decode, Encode};
use std::slice::Iter;
use test_random_derive::TestRandom;
use tree_hash_derive::TreeHash;
@@ -13,6 +12,8 @@ pub type Transactions<T> = VariableList<
<T as EthSpec>::MaxTransactionsPerPayload,
>;
pub type Withdrawals<T> = VariableList<Withdrawal, <T as EthSpec>::MaxWithdrawalsPerPayload>;
#[superstruct(
variants(Merge, Capella, Eip4844),
variant_attributes(
@@ -82,7 +83,7 @@ pub struct ExecutionPayload<T: EthSpec> {
pub transactions: Transactions<T>,
#[cfg(feature = "withdrawals")]
#[superstruct(only(Capella, Eip4844))]
pub withdrawals: VariableList<Withdrawal, T::MaxWithdrawalsPerPayload>,
pub withdrawals: Withdrawals<T>,
}
impl<T: EthSpec> ExecutionPayload<T> {

View File

@@ -27,6 +27,7 @@ pub mod beacon_block_body;
pub mod beacon_block_header;
pub mod beacon_committee;
pub mod beacon_state;
pub mod bls_to_execution_change;
pub mod builder_bid;
pub mod chain_spec;
pub mod checkpoint;
@@ -61,6 +62,7 @@ pub mod shuffling_id;
pub mod signed_aggregate_and_proof;
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_voluntary_exit;
pub mod signing_data;
@@ -117,6 +119,7 @@ pub use crate::beacon_block_header::BeaconBlockHeader;
pub use crate::beacon_committee::{BeaconCommittee, OwnedBeaconCommittee};
pub use crate::beacon_state::{BeaconTreeHashCache, Error as BeaconStateError, *};
pub use crate::blobs_sidecar::BlobsSidecar;
pub use crate::bls_to_execution_change::BlsToExecutionChange;
pub use crate::chain_spec::{ChainSpec, Config, Domain};
pub use crate::checkpoint::Checkpoint;
pub use crate::config_and_preset::{
@@ -133,7 +136,7 @@ pub use crate::eth_spec::EthSpecId;
pub use crate::execution_block_hash::ExecutionBlockHash;
pub use crate::execution_payload::{
ExecutionPayload, ExecutionPayloadCapella, ExecutionPayloadEip4844, ExecutionPayloadMerge,
ExecutionPayloadRef, Transaction, Transactions,
ExecutionPayloadRef, Transaction, Transactions, Withdrawals,
};
pub use crate::execution_payload_header::{
ExecutionPayloadHeader, ExecutionPayloadHeaderCapella, ExecutionPayloadHeaderEip4844,
@@ -170,6 +173,7 @@ pub use crate::signed_beacon_block::{
SignedBlindedBeaconBlock,
};
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_voluntary_exit::SignedVoluntaryExit;
pub use crate::signing_data::{SignedRoot, SigningData};

View File

@@ -36,6 +36,9 @@ pub trait ExecPayload<T: EthSpec>: Debug + Clone + PartialEq + Hash + TreeHash +
fn fee_recipient(&self) -> Address;
fn gas_limit(&self) -> u64;
fn transactions(&self) -> Option<&Transactions<T>>;
/// fork-specific fields
#[cfg(feature = "withdrawals")]
fn withdrawals(&self) -> Option<Result<&Withdrawals<T>, Error>>;
/// Is this a default payload? (pre-merge)
fn is_default(&self) -> bool;
@@ -225,6 +228,15 @@ impl<T: EthSpec> ExecPayload<T> for FullPayload<T> {
})
}
#[cfg(feature = "withdrawals")]
fn withdrawals(&self) -> Option<Result<&Withdrawals<T>, Error>> {
match self {
FullPayload::Merge(_) => Some(Err(Error::IncorrectStateVariant)),
FullPayload::Capella(ref inner) => Some(Ok(&inner.execution_payload.withdrawals)),
FullPayload::Eip4844(ref inner) => Some(Ok(&inner.execution_payload.withdrawals)),
}
}
fn is_default<'a>(&'a self) -> bool {
map_full_payload_ref!(&'a _, self.to_ref(), move |payload, cons| {
cons(payload);
@@ -309,6 +321,15 @@ impl<'b, T: EthSpec> ExecPayload<T> for FullPayloadRef<'b, T> {
})
}
#[cfg(feature = "withdrawals")]
fn withdrawals(&self) -> Option<Result<&Withdrawals<T>, Error>> {
match self {
FullPayloadRef::Merge(_inner) => Some(Err(Error::IncorrectStateVariant)),
FullPayloadRef::Capella(inner) => Some(Ok(&inner.execution_payload.withdrawals)),
FullPayloadRef::Eip4844(inner) => Some(Ok(&inner.execution_payload.withdrawals)),
}
}
// TODO: can this function be optimized?
fn is_default<'a>(&'a self) -> bool {
map_full_payload_ref!(&'a _, self, move |payload, cons| {
@@ -463,6 +484,11 @@ impl<T: EthSpec> ExecPayload<T> for BlindedPayload<T> {
None
}
#[cfg(feature = "withdrawals")]
fn withdrawals(&self) -> Option<Result<&Withdrawals<T>, Error>> {
None
}
fn is_default<'a>(&'a self) -> bool {
map_blinded_payload_ref!(&'a _, self.to_ref(), move |payload, cons| {
cons(payload);
@@ -536,6 +562,11 @@ impl<'b, T: EthSpec> ExecPayload<T> for BlindedPayloadRef<'b, T> {
None
}
#[cfg(feature = "withdrawals")]
fn withdrawals<'a>(&'a self) -> Option<Result<&Withdrawals<T>, Error>> {
None
}
// TODO: can this function be optimized?
fn is_default<'a>(&'a self) -> bool {
map_blinded_payload_ref!(&'a _, self, move |payload, cons| {
@@ -546,7 +577,7 @@ impl<'b, T: EthSpec> ExecPayload<T> for BlindedPayloadRef<'b, T> {
}
macro_rules! impl_exec_payload_common {
($wrapper_type:ident, $wrapped_type_full:ident, $wrapped_header_type:ident, $wrapped_field:ident, $fork_variant:ident, $block_type_variant:ident, $f:block) => {
($wrapper_type:ident, $wrapped_type_full:ident, $wrapped_header_type:ident, $wrapped_field:ident, $fork_variant:ident, $block_type_variant:ident, $f:block, $g:block) => {
impl<T: EthSpec> ExecPayload<T> for $wrapper_type<T> {
fn block_type() -> BlockType {
BlockType::$block_type_variant
@@ -594,6 +625,12 @@ macro_rules! impl_exec_payload_common {
let f = $f;
f(self)
}
#[cfg(feature = "withdrawals")]
fn withdrawals(&self) -> Option<Result<&Withdrawals<T>, Error>> {
let g = $g;
g(self)
}
}
impl<T: EthSpec> From<$wrapped_type_full<T>> for $wrapper_type<T> {
@@ -605,7 +642,7 @@ macro_rules! impl_exec_payload_common {
}
macro_rules! impl_exec_payload_for_fork {
($wrapper_type_header:ident, $wrapper_type_full:ident, $wrapped_type_header:ident, $wrapped_type_full:ident, $fork_variant:ident) => {
($wrapper_type_header:ident, $wrapper_type_full:ident, $wrapped_type_header:ident, $wrapped_type_full:ident, $fork_variant:ident, $withdrawal_fn:block) => {
//*************** Blinded payload implementations ******************//
impl_exec_payload_common!(
@@ -615,6 +652,7 @@ macro_rules! impl_exec_payload_for_fork {
execution_payload_header,
$fork_variant,
Blinded,
{ |_| { None } },
{ |_| { None } }
);
@@ -680,7 +718,8 @@ macro_rules! impl_exec_payload_for_fork {
let c: for<'a> fn(&'a $wrapper_type_full<T>) -> Option<&'a Transactions<T>> =
|payload: &$wrapper_type_full<T>| Some(&payload.execution_payload.transactions);
c
}
},
$withdrawal_fn
);
impl<T: EthSpec> Default for $wrapper_type_full<T> {
@@ -723,21 +762,36 @@ impl_exec_payload_for_fork!(
FullPayloadMerge,
ExecutionPayloadHeaderMerge,
ExecutionPayloadMerge,
Merge
Merge,
{
let c: for<'a> fn(&'a FullPayloadMerge<T>) -> Option<Result<&'a Withdrawals<T>, Error>> =
|_| Some(Err(Error::IncorrectStateVariant));
c
}
);
impl_exec_payload_for_fork!(
BlindedPayloadCapella,
FullPayloadCapella,
ExecutionPayloadHeaderCapella,
ExecutionPayloadCapella,
Capella
Capella,
{
let c: for<'a> fn(&'a FullPayloadCapella<T>) -> Option<Result<&Withdrawals<T>, Error>> =
|payload: &FullPayloadCapella<T>| Some(Ok(&payload.execution_payload.withdrawals));
c
}
);
impl_exec_payload_for_fork!(
BlindedPayloadEip4844,
FullPayloadEip4844,
ExecutionPayloadHeaderEip4844,
ExecutionPayloadEip4844,
Eip4844
Eip4844,
{
let c: for<'a> fn(&'a FullPayloadEip4844<T>) -> Option<Result<&Withdrawals<T>, Error>> =
|payload: &FullPayloadEip4844<T>| Some(Ok(&payload.execution_payload.withdrawals));
c
}
);
impl<T: EthSpec> AbstractExecPayload<T> for BlindedPayload<T> {

View File

@@ -1,5 +1,6 @@
use crate::{
test_utils::TestRandom, BeaconState, ChainSpec, Epoch, EthSpec, Hash256, PublicKeyBytes,
test_utils::TestRandom, Address, BeaconState, BlsToExecutionChange, ChainSpec, Epoch, EthSpec,
Hash256, PublicKeyBytes,
};
use serde_derive::{Deserialize, Serialize};
use ssz_derive::{Decode, Encode};
@@ -75,6 +76,16 @@ impl Validator {
.unwrap_or(false)
}
/// Changes withdrawal credentials to the provided eth1 execution address
///
/// WARNING: this function does NO VALIDATION - it just does it!
pub fn change_withdrawal_credentials(&mut self, execution_address: &Address, spec: &ChainSpec) {
let mut bytes = [0u8; 32];
bytes[0] = spec.eth1_address_withdrawal_prefix_byte;
bytes[12..].copy_from_slice(execution_address.as_bytes());
self.withdrawal_credentials = Hash256::from(bytes);
}
/// Returns `true` if the validator is fully withdrawable at some epoch
pub fn is_fully_withdrawable_at(&self, balance: u64, epoch: Epoch, spec: &ChainSpec) -> bool {
self.has_eth1_withdrawal_credential(spec) && self.withdrawable_epoch <= epoch && balance > 0