From c66bb33b352f1051bde430cce64f807092e97198 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Tue, 26 Mar 2024 13:49:36 -0600 Subject: [PATCH 1/5] impl ssz_static tests for deneb --- spec-tests/runners/ssz_static.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/spec-tests/runners/ssz_static.rs b/spec-tests/runners/ssz_static.rs index 902ce459b..c8b39d589 100644 --- a/spec-tests/runners/ssz_static.rs +++ b/spec-tests/runners/ssz_static.rs @@ -35,6 +35,31 @@ fn run_test( Ok(()) } +macro_rules! gen_deneb_and_later { + ($test_case:expr, $($handler:ident),*) => { + let result = match $test_case.meta.handler.0.as_str() { + $( + stringify!($handler) => gen_match_for! { + $test_case, + (mainnet, deneb), + (minimal, deneb) + { + gen_exec! { + $test_case, load_test, run_test:: + } + } + }, + )* + _ => Err(Error::InternalContinue), + }; + match result { + Ok(()) => return Ok(()), + Err(Error::InternalContinue) => {}, + Err(err) => return Err(err) + } + }; +} + macro_rules! gen_capella_and_later { ($test_case:expr, $($handler:ident),*) => { let result = match $test_case.meta.handler.0.as_str() { @@ -140,6 +165,12 @@ macro_rules! gen_match { } pub fn dispatch(test: &TestCase) -> Result<(), Error> { + gen_deneb_and_later! { + test, + BlobSidecar, + BlobIdentifier + } + gen_capella_and_later! { test, Withdrawal, From 2d674c4e215eed0ad2e0a8b8a5a957cd89ed0053 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Tue, 26 Mar 2024 13:50:06 -0600 Subject: [PATCH 2/5] impl operations tests for deneb --- .../src/bellatrix/block_processing.rs | 20 +++++- .../src/capella/block_processing.rs | 20 +++++- spec-tests/runners/operations.rs | 65 +++---------------- 3 files changed, 43 insertions(+), 62 deletions(-) diff --git a/ethereum-consensus/src/bellatrix/block_processing.rs b/ethereum-consensus/src/bellatrix/block_processing.rs index d3a93c08e..320bcf1b1 100644 --- a/ethereum-consensus/src/bellatrix/block_processing.rs +++ b/ethereum-consensus/src/bellatrix/block_processing.rs @@ -2,7 +2,7 @@ use crate::{ bellatrix::{ compute_timestamp_at_slot, get_current_epoch, get_randao_mix, is_execution_enabled, is_merge_transition_complete, process_block_header, process_eth1_data, process_operations, - process_randao, process_sync_aggregate, BeaconBlock, BeaconState, ExecutionPayload, + process_randao, process_sync_aggregate, BeaconBlock, BeaconBlockBody, BeaconState, ExecutionPayloadHeader, }, error::{invalid_operation_error, InvalidExecutionPayload}, @@ -20,6 +20,11 @@ pub fn process_execution_payload< const EPOCHS_PER_SLASHINGS_VECTOR: usize, const MAX_VALIDATORS_PER_COMMITTEE: usize, const SYNC_COMMITTEE_SIZE: usize, + const MAX_PROPOSER_SLASHINGS: usize, + const MAX_ATTESTER_SLASHINGS: usize, + const MAX_ATTESTATIONS: usize, + const MAX_DEPOSITS: usize, + const MAX_VOLUNTARY_EXITS: usize, const BYTES_PER_LOGS_BLOOM: usize, const MAX_EXTRA_DATA_BYTES: usize, const MAX_BYTES_PER_TRANSACTION: usize, @@ -37,7 +42,14 @@ pub fn process_execution_payload< BYTES_PER_LOGS_BLOOM, MAX_EXTRA_DATA_BYTES, >, - payload: &mut ExecutionPayload< + block: &mut BeaconBlockBody< + MAX_PROPOSER_SLASHINGS, + MAX_VALIDATORS_PER_COMMITTEE, + MAX_ATTESTER_SLASHINGS, + MAX_ATTESTATIONS, + MAX_DEPOSITS, + MAX_VOLUNTARY_EXITS, + SYNC_COMMITTEE_SIZE, BYTES_PER_LOGS_BLOOM, MAX_EXTRA_DATA_BYTES, MAX_BYTES_PER_TRANSACTION, @@ -45,6 +57,8 @@ pub fn process_execution_payload< >, context: &Context, ) -> Result<()> { + let payload = &mut block.execution_payload; + let parent_hash_invalid = payload.parent_hash != state.latest_execution_payload_header.block_hash; if is_merge_transition_complete(state) && parent_hash_invalid { @@ -151,7 +165,7 @@ pub fn process_block< ) -> Result<()> { process_block_header(state, block, context)?; if is_execution_enabled(state, &block.body) { - process_execution_payload(state, &mut block.body.execution_payload, context)?; + process_execution_payload(state, &mut block.body, context)?; } process_randao(state, &block.body, context)?; process_eth1_data(state, &block.body, context); diff --git a/ethereum-consensus/src/capella/block_processing.rs b/ethereum-consensus/src/capella/block_processing.rs index e82c364ff..5892be893 100644 --- a/ethereum-consensus/src/capella/block_processing.rs +++ b/ethereum-consensus/src/capella/block_processing.rs @@ -176,11 +176,17 @@ pub fn process_execution_payload< const EPOCHS_PER_SLASHINGS_VECTOR: usize, const MAX_VALIDATORS_PER_COMMITTEE: usize, const SYNC_COMMITTEE_SIZE: usize, + const MAX_PROPOSER_SLASHINGS: usize, + const MAX_ATTESTER_SLASHINGS: usize, + const MAX_ATTESTATIONS: usize, + const MAX_DEPOSITS: usize, + const MAX_VOLUNTARY_EXITS: usize, const BYTES_PER_LOGS_BLOOM: usize, const MAX_EXTRA_DATA_BYTES: usize, const MAX_BYTES_PER_TRANSACTION: usize, const MAX_TRANSACTIONS_PER_PAYLOAD: usize, const MAX_WITHDRAWALS_PER_PAYLOAD: usize, + const MAX_BLS_TO_EXECUTION_CHANGES: usize, >( state: &mut BeaconState< SLOTS_PER_HISTORICAL_ROOT, @@ -194,15 +200,25 @@ pub fn process_execution_payload< BYTES_PER_LOGS_BLOOM, MAX_EXTRA_DATA_BYTES, >, - payload: &mut ExecutionPayload< + block: &mut BeaconBlockBody< + MAX_PROPOSER_SLASHINGS, + MAX_VALIDATORS_PER_COMMITTEE, + MAX_ATTESTER_SLASHINGS, + MAX_ATTESTATIONS, + MAX_DEPOSITS, + MAX_VOLUNTARY_EXITS, + SYNC_COMMITTEE_SIZE, BYTES_PER_LOGS_BLOOM, MAX_EXTRA_DATA_BYTES, MAX_BYTES_PER_TRANSACTION, MAX_TRANSACTIONS_PER_PAYLOAD, MAX_WITHDRAWALS_PER_PAYLOAD, + MAX_BLS_TO_EXECUTION_CHANGES, >, context: &Context, ) -> Result<()> { + let payload = &mut block.execution_payload; + let parent_hash_invalid = payload.parent_hash != state.latest_execution_payload_header.block_hash; if parent_hash_invalid { @@ -450,7 +466,7 @@ pub fn process_block< ) -> Result<()> { process_block_header(state, block, context)?; process_withdrawals(state, &block.body.execution_payload, context)?; - process_execution_payload(state, &mut block.body.execution_payload, context)?; + process_execution_payload(state, &mut block.body, context)?; process_randao(state, &block.body, context)?; process_eth1_data(state, &block.body, context); process_operations(state, &mut block.body, context)?; diff --git a/spec-tests/runners/operations.rs b/spec-tests/runners/operations.rs index 060a515b8..439a82e18 100644 --- a/spec-tests/runners/operations.rs +++ b/spec-tests/runners/operations.rs @@ -70,7 +70,7 @@ fn load_execution_payload_test( let path = test_case_path.to_string() + "/post.ssz_snappy"; let post: Option = load_snappy_ssz(&path); - let path = test_case_path.to_string() + "/execution_payload.ssz_snappy"; + let path = test_case_path.to_string() + "/body.ssz_snappy"; let operation: O = load_snappy_ssz(&path).unwrap(); let path = test_case_path.to_string() + "/execution.yaml"; @@ -188,62 +188,13 @@ pub fn dispatch(test: &TestCase) -> Result<(), Error> { "execution_payload" => { gen_match_for! { test, - (mainnet, bellatrix) => { - gen_exec! { - test, - load_execution_payload_test, - |(pre, post, operation, execution_valid): (spec::BeaconState, Option, spec::ExecutionPayload, bool), context: &Context| { - let mut context = context.clone(); - context.execution_engine = execution_valid; - run_test(pre, post, operation, &context, spec::process_execution_payload) - } - } - } - (mainnet, capella) => { - gen_exec! { - test, - load_execution_payload_test, - |(pre, post, operation, execution_valid): (spec::BeaconState, Option, spec::ExecutionPayload, bool), context: &Context| { - let mut context = context.clone(); - context.execution_engine = execution_valid; - run_test(pre, post, operation, &context, spec::process_execution_payload) - } - } - } - (mainnet, deneb) => { - gen_exec! { - test, - load_execution_payload_test, - |(pre, post, operation, execution_valid): (spec::BeaconState, Option, spec::BeaconBlockBody, bool), context: &Context| { - let mut context = context.clone(); - context.execution_engine = execution_valid; - run_test(pre, post, operation, &context, spec::process_execution_payload) - } - } - } - (minimal, bellatrix) => { - gen_exec! { - test, - load_execution_payload_test, - |(pre, post, operation, execution_valid): (spec::BeaconState, Option, spec::ExecutionPayload, bool), context: &Context| { - let mut context = context.clone(); - context.execution_engine = execution_valid; - run_test(pre, post, operation, &context, spec::process_execution_payload) - } - } - } - (minimal, capella) => { - gen_exec! { - test, - load_execution_payload_test, - |(pre, post, operation, execution_valid): (spec::BeaconState, Option, spec::ExecutionPayload, bool), context: &Context| { - let mut context = context.clone(); - context.execution_engine = execution_valid; - run_test(pre, post, operation, &context, spec::process_execution_payload) - } - } - } - (minimal, deneb) => { + (mainnet, bellatrix), + (mainnet, capella), + (mainnet, deneb), + (minimal, bellatrix), + (minimal, capella), + (minimal, deneb) + { gen_exec! { test, load_execution_payload_test, From 6c20afd8e839395eea4f11e6463dbc15b3411996 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Tue, 26 Mar 2024 13:55:39 -0600 Subject: [PATCH 3/5] impl transition tests for deneb --- spec-tests/runners/transition.rs | 64 ++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/spec-tests/runners/transition.rs b/spec-tests/runners/transition.rs index 0645dde2d..75e974a89 100644 --- a/spec-tests/runners/transition.rs +++ b/spec-tests/runners/transition.rs @@ -77,6 +77,12 @@ fn set_fork_epochs(meta: &mut Meta, context: &mut Context) { context.bellatrix_fork_epoch = 0; context.capella_fork_epoch = meta.fork_epoch; } + "deneb" => { + context.altair_fork_epoch = 0; + context.bellatrix_fork_epoch = 0; + context.capella_fork_epoch = 0; + context.deneb_fork_epoch = meta.fork_epoch; + } _ => todo!(), } } @@ -172,6 +178,35 @@ pub fn dispatch(test: &TestCase) -> Result<(), Error> { } } } + Fork::Deneb => { + use ethereum_consensus::{ + capella::mainnet as pre_spec, deneb::mainnet as spec, + }; + gen_exec! { + test, + load_test, + | (pre, expected, pre_blocks, post_blocks, mut meta): (pre_spec::BeaconState, spec::BeaconState, Vec, Vec, Meta), context: &Context| { + assert_eq!(meta.post_fork, "deneb"); + let mut context = context.clone(); + set_fork_epochs(&mut meta, &mut context); + let mut executor = state_transition::mainnet::Executor::new(BeaconState::Capella(pre), context); + for block in pre_blocks.into_iter() { + let mut block = SignedBeaconBlock::Capella(block); + executor.apply_block(&mut block)?; + } + for block in post_blocks.into_iter() { + let mut block = SignedBeaconBlock::Deneb(block); + executor.apply_block(&mut block)?; + } + let post = executor.state.deneb().unwrap(); + if post != &expected { + Err(Error::InvalidState) + } else { + Ok(()) + } + } + } + } _ => todo!(), }, Config::Minimal => match test.meta.fork { @@ -262,6 +297,35 @@ pub fn dispatch(test: &TestCase) -> Result<(), Error> { } } } + Fork::Deneb => { + use ethereum_consensus::{ + capella::minimal as pre_spec, deneb::minimal as spec, + }; + gen_exec! { + test, + load_test, + | (pre, expected, pre_blocks, post_blocks, mut meta): (pre_spec::BeaconState, spec::BeaconState, Vec, Vec, Meta), context: &Context| { + assert_eq!(meta.post_fork, "deneb"); + let mut context = context.clone(); + set_fork_epochs(&mut meta, &mut context); + let mut executor = state_transition::minimal::Executor::new(BeaconState::Capella(pre), context); + for block in pre_blocks.into_iter() { + let mut block = SignedBeaconBlock::Capella(block); + executor.apply_block(&mut block)?; + } + for block in post_blocks.into_iter() { + let mut block = SignedBeaconBlock::Deneb(block); + executor.apply_block(&mut block)?; + } + let post = executor.state.deneb().unwrap(); + if post != &expected { + Err(Error::InvalidState) + } else { + Ok(()) + } + } + } + } _ => todo!(), }, config => unreachable!("no tests for {config:?}"), From 6b90d587cd9177247c93aa6f2f2f850495c7ce15 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Tue, 26 Mar 2024 14:21:26 -0600 Subject: [PATCH 4/5] bugfix: minimal config `MIN_PER_EPOCH_CHURN_LIMIT` --- ethereum-consensus/src/configs/minimal.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethereum-consensus/src/configs/minimal.rs b/ethereum-consensus/src/configs/minimal.rs index 077bedab6..3226b3af9 100644 --- a/ethereum-consensus/src/configs/minimal.rs +++ b/ethereum-consensus/src/configs/minimal.rs @@ -25,7 +25,7 @@ pub const ETH1_FOLLOW_DISTANCE: u64 = 16; pub const INACTIVITY_SCORE_BIAS: u64 = 4; pub const INACTIVITY_SCORE_RECOVERY_RATE: u64 = 16; pub const EJECTION_BALANCE: Gwei = 16 * 10u64.pow(9); -pub const MIN_PER_EPOCH_CHURN_LIMIT: u64 = 4; +pub const MIN_PER_EPOCH_CHURN_LIMIT: u64 = 2; pub const MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT: u64 = 4; pub const CHURN_LIMIT_QUOTIENT: u64 = 32; pub const PROPOSER_SCORE_BOOST: u64 = 40; From e533133beb167eb11732a3b6d77f9a59582bf0b4 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Tue, 26 Mar 2024 14:27:52 -0600 Subject: [PATCH 5/5] updates for v1.4.0 spec tests --- spec-tests/spec-test-version | 2 +- spec-tests/test_meta.rs | 15 ++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/spec-tests/spec-test-version b/spec-tests/spec-test-version index 18fa8e74f..0d0c52f84 100644 --- a/spec-tests/spec-test-version +++ b/spec-tests/spec-test-version @@ -1 +1 @@ -v1.3.0 +v1.4.0 diff --git a/spec-tests/test_meta.rs b/spec-tests/test_meta.rs index 2a5edbd36..49fcb6a1a 100644 --- a/spec-tests/test_meta.rs +++ b/spec-tests/test_meta.rs @@ -33,6 +33,8 @@ pub enum Fork { Bellatrix, Capella, Deneb, + Eip6110, + Whisk, } impl From<&str> for Fork { @@ -43,7 +45,9 @@ impl From<&str> for Fork { "bellatrix" => Self::Bellatrix, "capella" => Self::Capella, "deneb" => Self::Deneb, - _ => panic!("unsupported fork"), + "eip6110" => Self::Eip6110, + "whisk" => Self::Whisk, + fork => panic!("unsupported fork: {fork:?}"), } } } @@ -102,7 +106,7 @@ impl From<&str> for Runner { "genesis" => Self::Genesis, "kzg" => Self::Kzg, "light_client" => Self::LightClient, - "merkle" => Self::MerkleProof, + "merkle_proof" => Self::MerkleProof, "operations" => Self::Operations, "random" => Self::Random, "rewards" => Self::Rewards, @@ -203,11 +207,12 @@ impl TestMeta { let ignored_runner = self.runner.should_ignore(); let ignored_handler = matches!(self.runner, Runner::SszStatic) && self.handler.0.contains("LightClient"); - let ignored_fork = matches!(self.fork, Fork::Deneb); - ignored_runner | ignored_handler | ignored_fork + ignored_runner | ignored_handler } pub fn should_skip(&self) -> bool { - self.runner.should_skip() + let skipped_runner = self.runner.should_skip(); + let skipped_forks = matches!(self.fork, Fork::Eip6110 | Fork::Whisk); + skipped_runner | skipped_forks } }