diff --git a/ethereum-consensus/Cargo.toml b/ethereum-consensus/Cargo.toml index 265d28334..085638967 100644 --- a/ethereum-consensus/Cargo.toml +++ b/ethereum-consensus/Cargo.toml @@ -11,6 +11,7 @@ serde = ["hex", "serde_json", "serde_yaml"] async = ["tokio", "tokio-stream", "async-stream"] secret-key-debug = [ ] # enable if you want to be able to print `crypto::SecretKey` +spec-tests = [] # enable extra features for testing ec = [ "secret-key-debug", "clap", diff --git a/ethereum-consensus/examples/sketch.rs b/ethereum-consensus/examples/sketch.rs index 21845764c..c975cbeb1 100644 --- a/ethereum-consensus/examples/sketch.rs +++ b/ethereum-consensus/examples/sketch.rs @@ -40,13 +40,7 @@ fn main() { let current_epoch = bellatrix::get_current_epoch(&state, &context); dbg!(current_epoch); - let execution_engine = bellatrix::DefaultExecutionEngine::default(); - let _ = bellatrix::state_transition( - &mut state, - &mut signed_block, - &execution_engine, - Validation::Enabled, - &context, - ); + let _ = + bellatrix::state_transition(&mut state, &mut signed_block, Validation::Enabled, &context); dbg!(state.fork); } diff --git a/ethereum-consensus/src/bellatrix/block_processing.rs b/ethereum-consensus/src/bellatrix/block_processing.rs index db92f443f..d3a93c08e 100644 --- a/ethereum-consensus/src/bellatrix/block_processing.rs +++ b/ethereum-consensus/src/bellatrix/block_processing.rs @@ -24,14 +24,6 @@ pub fn process_execution_payload< const MAX_EXTRA_DATA_BYTES: usize, const MAX_BYTES_PER_TRANSACTION: usize, const MAX_TRANSACTIONS_PER_PAYLOAD: usize, - E: ExecutionEngine< - NewPayloadRequest = ExecutionPayload< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - >, - >, >( state: &mut BeaconState< SLOTS_PER_HISTORICAL_ROOT, @@ -51,7 +43,6 @@ pub fn process_execution_payload< MAX_BYTES_PER_TRANSACTION, MAX_TRANSACTIONS_PER_PAYLOAD, >, - execution_engine: &E, context: &Context, ) -> Result<()> { let parent_hash_invalid = @@ -89,6 +80,7 @@ pub fn process_execution_payload< )) } + let execution_engine = context.execution_engine(); execution_engine.verify_and_notify_new_payload(&payload.clone())?; state.latest_execution_payload_header = ExecutionPayloadHeader { @@ -129,14 +121,6 @@ pub fn process_block< const MAX_EXTRA_DATA_BYTES: usize, const MAX_BYTES_PER_TRANSACTION: usize, const MAX_TRANSACTIONS_PER_PAYLOAD: usize, - E: ExecutionEngine< - NewPayloadRequest = ExecutionPayload< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - >, - >, >( state: &mut BeaconState< SLOTS_PER_HISTORICAL_ROOT, @@ -163,17 +147,11 @@ pub fn process_block< MAX_BYTES_PER_TRANSACTION, MAX_TRANSACTIONS_PER_PAYLOAD, >, - execution_engine: &E, context: &Context, ) -> Result<()> { process_block_header(state, block, context)?; if is_execution_enabled(state, &block.body) { - process_execution_payload( - state, - &mut block.body.execution_payload, - execution_engine, - context, - )?; + process_execution_payload(state, &mut block.body.execution_payload, context)?; } process_randao(state, &block.body, context)?; process_eth1_data(state, &block.body, context); diff --git a/ethereum-consensus/src/bellatrix/execution_engine.rs b/ethereum-consensus/src/bellatrix/execution_engine.rs deleted file mode 100644 index 0d4650737..000000000 --- a/ethereum-consensus/src/bellatrix/execution_engine.rs +++ /dev/null @@ -1,112 +0,0 @@ -use crate::{ - bellatrix::execution_payload::ExecutionPayload, error::ExecutionEngineError, - execution_engine::ExecutionEngine, state_transition::Result, -}; - -// The `DefaultExecutionEngine` performs no operations and validation -// is determined by `execution_is_valid`. -#[derive(Debug)] -pub struct DefaultExecutionEngine< - const BYTES_PER_LOGS_BLOOM: usize, - const MAX_EXTRA_DATA_BYTES: usize, - const MAX_BYTES_PER_TRANSACTION: usize, - const MAX_TRANSACTIONS_PER_PAYLOAD: usize, -> { - execution_is_valid: bool, -} - -impl< - const BYTES_PER_LOGS_BLOOM: usize, - const MAX_EXTRA_DATA_BYTES: usize, - const MAX_BYTES_PER_TRANSACTION: usize, - const MAX_TRANSACTIONS_PER_PAYLOAD: usize, - > Default - for DefaultExecutionEngine< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - > -{ - fn default() -> Self { - Self { execution_is_valid: true } - } -} - -impl< - const BYTES_PER_LOGS_BLOOM: usize, - const MAX_EXTRA_DATA_BYTES: usize, - const MAX_BYTES_PER_TRANSACTION: usize, - const MAX_TRANSACTIONS_PER_PAYLOAD: usize, - > - DefaultExecutionEngine< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - > -{ - pub fn new(execution_is_valid: bool) -> Self { - Self { execution_is_valid } - } - - fn is_valid_block_hash( - &self, - _payload: &ExecutionPayload< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - >, - ) -> Result<()> { - if !self.execution_is_valid { - Err(ExecutionEngineError::InvalidBlockHash.into()) - } else { - Ok(()) - } - } - - fn notify_new_payload( - &self, - _payload: &ExecutionPayload< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - >, - ) -> Result<()> { - if !self.execution_is_valid { - Err(ExecutionEngineError::InvalidPayload.into()) - } else { - Ok(()) - } - } -} - -impl< - const BYTES_PER_LOGS_BLOOM: usize, - const MAX_EXTRA_DATA_BYTES: usize, - const MAX_BYTES_PER_TRANSACTION: usize, - const MAX_TRANSACTIONS_PER_PAYLOAD: usize, - > ExecutionEngine - for DefaultExecutionEngine< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - > -{ - type NewPayloadRequest = ExecutionPayload< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - >; - fn verify_and_notify_new_payload( - &self, - new_payload_request: &Self::NewPayloadRequest, - ) -> Result<()> { - self.is_valid_block_hash(new_payload_request)?; - self.notify_new_payload(new_payload_request) - } -} diff --git a/ethereum-consensus/src/bellatrix/execution_payload.rs b/ethereum-consensus/src/bellatrix/execution_payload.rs index 03570e01d..ee1615a84 100644 --- a/ethereum-consensus/src/bellatrix/execution_payload.rs +++ b/ethereum-consensus/src/bellatrix/execution_payload.rs @@ -1,4 +1,5 @@ use crate::{ + execution_engine::PayloadRequest, primitives::{Bytes32, ExecutionAddress, Hash32, Root}, ssz::prelude::*, Error, @@ -36,6 +37,21 @@ pub struct ExecutionPayload< pub transactions: List, MAX_TRANSACTIONS_PER_PAYLOAD>, } +impl< + const BYTES_PER_LOGS_BLOOM: usize, + const MAX_EXTRA_DATA_BYTES: usize, + const MAX_BYTES_PER_TRANSACTION: usize, + const MAX_TRANSACTIONS_PER_PAYLOAD: usize, + > PayloadRequest + for ExecutionPayload< + BYTES_PER_LOGS_BLOOM, + MAX_EXTRA_DATA_BYTES, + MAX_BYTES_PER_TRANSACTION, + MAX_TRANSACTIONS_PER_PAYLOAD, + > +{ +} + #[derive( Default, Debug, Clone, SimpleSerialize, PartialEq, Eq, serde::Serialize, serde::Deserialize, )] diff --git a/ethereum-consensus/src/bellatrix/mod.rs b/ethereum-consensus/src/bellatrix/mod.rs index cfca13d21..f2940ad68 100644 --- a/ethereum-consensus/src/bellatrix/mod.rs +++ b/ethereum-consensus/src/bellatrix/mod.rs @@ -6,7 +6,6 @@ pub mod beacon_state; pub mod blinded_beacon_block; pub mod block_processing; pub mod epoch_processing; -pub mod execution_engine; pub mod execution_payload; pub mod fork; pub mod fork_choice; diff --git a/ethereum-consensus/src/bellatrix/spec/mod.rs b/ethereum-consensus/src/bellatrix/spec/mod.rs index bb291f04b..85f2ead86 100644 --- a/ethereum-consensus/src/bellatrix/spec/mod.rs +++ b/ethereum-consensus/src/bellatrix/spec/mod.rs @@ -28,7 +28,6 @@ pub use crate::{ }, block_processing::{process_block, process_execution_payload}, epoch_processing::{process_epoch, process_slashings}, - execution_engine::DefaultExecutionEngine, execution_payload::{ExecutionPayload, ExecutionPayloadHeader, Transaction}, fork::upgrade_to_bellatrix, fork_choice::PowBlock, diff --git a/ethereum-consensus/src/bellatrix/state_transition.rs b/ethereum-consensus/src/bellatrix/state_transition.rs index 4aaff87b7..78f3230ad 100644 --- a/ethereum-consensus/src/bellatrix/state_transition.rs +++ b/ethereum-consensus/src/bellatrix/state_transition.rs @@ -1,7 +1,6 @@ use crate::{ bellatrix::{ - execution_payload::ExecutionPayload, process_block, process_slots, verify_block_signature, - BeaconState, ExecutionEngine, SignedBeaconBlock, + process_block, process_slots, verify_block_signature, BeaconState, SignedBeaconBlock, }, ssz::prelude::Merkleized, state_transition::{Context, Result, Validation}, @@ -29,14 +28,6 @@ pub fn state_transition_block_in_slot< const MAX_EXTRA_DATA_BYTES: usize, const MAX_BYTES_PER_TRANSACTION: usize, const MAX_TRANSACTIONS_PER_PAYLOAD: usize, - E: ExecutionEngine< - NewPayloadRequest = ExecutionPayload< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - >, - >, >( state: &mut BeaconState< SLOTS_PER_HISTORICAL_ROOT, @@ -63,7 +54,6 @@ pub fn state_transition_block_in_slot< MAX_BYTES_PER_TRANSACTION, MAX_TRANSACTIONS_PER_PAYLOAD, >, - execution_engine: &E, validation: Validation, context: &Context, ) -> Result<()> { @@ -75,7 +65,7 @@ pub fn state_transition_block_in_slot< verify_block_signature(state, signed_block, context)?; } let block = &mut signed_block.message; - process_block(state, block, execution_engine, context)?; + process_block(state, block, context)?; if validate_result && block.state_root != state.hash_tree_root()? { Err(Error::InvalidStateRoot) } else { @@ -101,14 +91,6 @@ pub fn state_transition< const MAX_EXTRA_DATA_BYTES: usize, const MAX_BYTES_PER_TRANSACTION: usize, const MAX_TRANSACTIONS_PER_PAYLOAD: usize, - E: ExecutionEngine< - NewPayloadRequest = ExecutionPayload< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - >, - >, >( state: &mut BeaconState< SLOTS_PER_HISTORICAL_ROOT, @@ -135,11 +117,10 @@ pub fn state_transition< MAX_BYTES_PER_TRANSACTION, MAX_TRANSACTIONS_PER_PAYLOAD, >, - execution_engine: &E, validation: Validation, context: &Context, ) -> Result<()> { process_slots(state, signed_block.message.slot, context)?; - state_transition_block_in_slot(state, signed_block, execution_engine, validation, context) + state_transition_block_in_slot(state, signed_block, validation, context) } diff --git a/ethereum-consensus/src/capella/block_processing.rs b/ethereum-consensus/src/capella/block_processing.rs index 7db20653a..e82c364ff 100644 --- a/ethereum-consensus/src/capella/block_processing.rs +++ b/ethereum-consensus/src/capella/block_processing.rs @@ -181,15 +181,6 @@ pub fn process_execution_payload< const MAX_BYTES_PER_TRANSACTION: usize, const MAX_TRANSACTIONS_PER_PAYLOAD: usize, const MAX_WITHDRAWALS_PER_PAYLOAD: usize, - E: ExecutionEngine< - NewPayloadRequest = ExecutionPayload< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - MAX_WITHDRAWALS_PER_PAYLOAD, - >, - >, >( state: &mut BeaconState< SLOTS_PER_HISTORICAL_ROOT, @@ -210,7 +201,6 @@ pub fn process_execution_payload< MAX_TRANSACTIONS_PER_PAYLOAD, MAX_WITHDRAWALS_PER_PAYLOAD, >, - execution_engine: &E, context: &Context, ) -> Result<()> { let parent_hash_invalid = @@ -248,6 +238,7 @@ pub fn process_execution_payload< )) } + let execution_engine = context.execution_engine(); execution_engine.verify_and_notify_new_payload(&payload.clone())?; state.latest_execution_payload_header = ExecutionPayloadHeader { @@ -427,15 +418,6 @@ pub fn process_block< const MAX_TRANSACTIONS_PER_PAYLOAD: usize, const MAX_WITHDRAWALS_PER_PAYLOAD: usize, const MAX_BLS_TO_EXECUTION_CHANGES: usize, - E: ExecutionEngine< - NewPayloadRequest = ExecutionPayload< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - MAX_WITHDRAWALS_PER_PAYLOAD, - >, - >, >( state: &mut BeaconState< SLOTS_PER_HISTORICAL_ROOT, @@ -464,12 +446,11 @@ pub fn process_block< MAX_WITHDRAWALS_PER_PAYLOAD, MAX_BLS_TO_EXECUTION_CHANGES, >, - execution_engine: &E, context: &Context, ) -> Result<()> { process_block_header(state, block, context)?; process_withdrawals(state, &block.body.execution_payload, context)?; - process_execution_payload(state, &mut block.body.execution_payload, execution_engine, context)?; + process_execution_payload(state, &mut block.body.execution_payload, context)?; process_randao(state, &block.body, context)?; process_eth1_data(state, &block.body, context); process_operations(state, &mut block.body, context)?; diff --git a/ethereum-consensus/src/capella/execution_engine.rs b/ethereum-consensus/src/capella/execution_engine.rs deleted file mode 100644 index 826b5d0aa..000000000 --- a/ethereum-consensus/src/capella/execution_engine.rs +++ /dev/null @@ -1,103 +0,0 @@ -use crate::{ - capella::execution_payload::ExecutionPayload, error::ExecutionEngineError, - execution_engine::ExecutionEngine, state_transition::Result, -}; - -// The `DefaultExecutionEngine` performs no operations and validation -// is determined by `execution_is_valid`. -#[derive(Debug)] -pub struct DefaultExecutionEngine< - 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, -> { - pub execution_is_valid: bool, -} - -impl< - 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, - > - DefaultExecutionEngine< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - MAX_WITHDRAWALS_PER_PAYLOAD, - > -{ - pub fn new(execution_is_valid: bool) -> Self { - Self { execution_is_valid } - } - - fn is_valid_block_hash( - &self, - _payload: &ExecutionPayload< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - MAX_WITHDRAWALS_PER_PAYLOAD, - >, - ) -> Result<()> { - if !self.execution_is_valid { - Err(ExecutionEngineError::InvalidBlockHash.into()) - } else { - Ok(()) - } - } - - fn notify_new_payload( - &self, - _payload: &ExecutionPayload< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - MAX_WITHDRAWALS_PER_PAYLOAD, - >, - ) -> Result<()> { - if !self.execution_is_valid { - Err(ExecutionEngineError::InvalidPayload.into()) - } else { - Ok(()) - } - } -} - -impl< - 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, - > ExecutionEngine - for DefaultExecutionEngine< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - MAX_WITHDRAWALS_PER_PAYLOAD, - > -{ - type NewPayloadRequest = ExecutionPayload< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - MAX_WITHDRAWALS_PER_PAYLOAD, - >; - - fn verify_and_notify_new_payload( - &self, - new_payload_request: &Self::NewPayloadRequest, - ) -> Result<()> { - self.is_valid_block_hash(new_payload_request)?; - self.notify_new_payload(new_payload_request) - } -} diff --git a/ethereum-consensus/src/capella/execution_payload.rs b/ethereum-consensus/src/capella/execution_payload.rs index 51f853958..79f5f87cb 100644 --- a/ethereum-consensus/src/capella/execution_payload.rs +++ b/ethereum-consensus/src/capella/execution_payload.rs @@ -1,6 +1,7 @@ use crate::{ bellatrix::Transaction, capella::withdrawal::Withdrawal, + execution_engine::PayloadRequest, primitives::{Bytes32, ExecutionAddress, Hash32, Root}, ssz::prelude::*, Error, @@ -38,6 +39,23 @@ pub struct ExecutionPayload< pub withdrawals: List, } +impl< + 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, + > PayloadRequest + for ExecutionPayload< + BYTES_PER_LOGS_BLOOM, + MAX_EXTRA_DATA_BYTES, + MAX_BYTES_PER_TRANSACTION, + MAX_TRANSACTIONS_PER_PAYLOAD, + MAX_WITHDRAWALS_PER_PAYLOAD, + > +{ +} + #[derive( Default, Debug, Clone, SimpleSerialize, PartialEq, Eq, serde::Serialize, serde::Deserialize, )] diff --git a/ethereum-consensus/src/capella/mod.rs b/ethereum-consensus/src/capella/mod.rs index 1666a70a1..7cb78a091 100644 --- a/ethereum-consensus/src/capella/mod.rs +++ b/ethereum-consensus/src/capella/mod.rs @@ -7,7 +7,6 @@ pub mod blinded_beacon_block; pub mod block_processing; pub mod bls_to_execution_change; pub mod epoch_processing; -pub mod execution_engine; pub mod execution_payload; pub mod fork; pub mod genesis; diff --git a/ethereum-consensus/src/capella/spec/mod.rs b/ethereum-consensus/src/capella/spec/mod.rs index c9bcad9b0..c66e3fe13 100644 --- a/ethereum-consensus/src/capella/spec/mod.rs +++ b/ethereum-consensus/src/capella/spec/mod.rs @@ -33,7 +33,6 @@ pub use crate::{ }, bls_to_execution_change::{BlsToExecutionChange, SignedBlsToExecutionChange}, epoch_processing::{process_epoch, process_historical_summaries_update}, - execution_engine::DefaultExecutionEngine, execution_payload::{ExecutionPayload, ExecutionPayloadHeader}, fork::upgrade_to_capella, genesis::initialize_beacon_state_from_eth1, @@ -3196,15 +3195,6 @@ pub fn state_transition_block_in_slot< const MAX_TRANSACTIONS_PER_PAYLOAD: usize, const MAX_WITHDRAWALS_PER_PAYLOAD: usize, const MAX_BLS_TO_EXECUTION_CHANGES: usize, - E: ExecutionEngine< - NewPayloadRequest = ExecutionPayload< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - MAX_WITHDRAWALS_PER_PAYLOAD, - >, - >, >( state: &mut BeaconState< SLOTS_PER_HISTORICAL_ROOT, @@ -3233,7 +3223,6 @@ pub fn state_transition_block_in_slot< MAX_WITHDRAWALS_PER_PAYLOAD, MAX_BLS_TO_EXECUTION_CHANGES, >, - execution_engine: &E, validation: Validation, context: &Context, ) -> Result<()> { @@ -3245,7 +3234,7 @@ pub fn state_transition_block_in_slot< verify_block_signature(state, signed_block, context)?; } let block = &mut signed_block.message; - process_block(state, block, execution_engine, context)?; + process_block(state, block, context)?; if validate_result && block.state_root != state.hash_tree_root()? { Err(Error::InvalidStateRoot) } else { @@ -3272,15 +3261,6 @@ pub fn state_transition< const MAX_TRANSACTIONS_PER_PAYLOAD: usize, const MAX_WITHDRAWALS_PER_PAYLOAD: usize, const MAX_BLS_TO_EXECUTION_CHANGES: usize, - E: ExecutionEngine< - NewPayloadRequest = ExecutionPayload< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - MAX_WITHDRAWALS_PER_PAYLOAD, - >, - >, >( state: &mut BeaconState< SLOTS_PER_HISTORICAL_ROOT, @@ -3309,10 +3289,9 @@ pub fn state_transition< MAX_WITHDRAWALS_PER_PAYLOAD, MAX_BLS_TO_EXECUTION_CHANGES, >, - execution_engine: &E, validation: Validation, context: &Context, ) -> Result<()> { process_slots(state, signed_block.message.slot, context)?; - state_transition_block_in_slot(state, signed_block, execution_engine, validation, context) + state_transition_block_in_slot(state, signed_block, validation, context) } diff --git a/ethereum-consensus/src/deneb/block_processing.rs b/ethereum-consensus/src/deneb/block_processing.rs index 3990c3817..d2bb662f5 100644 --- a/ethereum-consensus/src/deneb/block_processing.rs +++ b/ethereum-consensus/src/deneb/block_processing.rs @@ -156,15 +156,6 @@ pub fn process_execution_payload< const MAX_VOLUNTARY_EXITS: usize, const MAX_BLS_TO_EXECUTION_CHANGES: usize, const MAX_BLOB_COMMITMENTS_PER_BLOCK: usize, - E: ExecutionEngine< - NewPayloadRequest = NewPayloadRequest< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - MAX_WITHDRAWALS_PER_PAYLOAD, - >, - >, >( state: &mut BeaconState< SLOTS_PER_HISTORICAL_ROOT, @@ -194,7 +185,6 @@ pub fn process_execution_payload< MAX_BLS_TO_EXECUTION_CHANGES, MAX_BLOB_COMMITMENTS_PER_BLOCK, >, - execution_engine: &E, context: &Context, ) -> Result<()> { let payload = &mut body.execution_payload; @@ -247,6 +237,7 @@ pub fn process_execution_payload< let versioned_hashes = body.blob_kzg_commitments.iter().map(kzg_commitment_to_versioned_hash).collect::>(); + let execution_engine = context.execution_engine(); let new_payload_request = NewPayloadRequest { execution_payload: payload.clone(), versioned_hashes, @@ -377,15 +368,6 @@ pub fn process_block< const MAX_VOLUNTARY_EXITS: usize, const MAX_BLS_TO_EXECUTION_CHANGES: usize, const MAX_BLOB_COMMITMENTS_PER_BLOCK: usize, - E: ExecutionEngine< - NewPayloadRequest = NewPayloadRequest< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - MAX_WITHDRAWALS_PER_PAYLOAD, - >, - >, >( state: &mut BeaconState< SLOTS_PER_HISTORICAL_ROOT, @@ -415,12 +397,11 @@ pub fn process_block< MAX_BLS_TO_EXECUTION_CHANGES, MAX_BLOB_COMMITMENTS_PER_BLOCK, >, - execution_engine: &E, context: &Context, ) -> Result<()> { process_block_header(state, block, context)?; process_withdrawals(state, &block.body.execution_payload, context)?; - process_execution_payload(state, &mut block.body, execution_engine, 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/ethereum-consensus/src/deneb/execution_engine.rs b/ethereum-consensus/src/deneb/execution_engine.rs index ac14d9909..fc6367b71 100644 --- a/ethereum-consensus/src/deneb/execution_engine.rs +++ b/ethereum-consensus/src/deneb/execution_engine.rs @@ -1,9 +1,7 @@ use crate::{ deneb::{execution_payload::ExecutionPayload, polynomial_commitments::VersionedHash}, - error::ExecutionEngineError, - execution_engine::ExecutionEngine, + execution_engine::PayloadRequest, primitives::Root, - state_transition::Result, }; pub struct NewPayloadRequest< @@ -24,27 +22,14 @@ pub struct NewPayloadRequest< pub parent_beacon_block_root: Root, } -// The `DefaultExecutionEngine` performs no operations and validation -// is determined by `execution_is_valid`. -#[derive(Debug)] -pub struct DefaultExecutionEngine< - 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, -> { - pub execution_is_valid: bool, -} - impl< 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, - > - DefaultExecutionEngine< + > PayloadRequest + for NewPayloadRequest< BYTES_PER_LOGS_BLOOM, MAX_EXTRA_DATA_BYTES, MAX_BYTES_PER_TRANSACTION, @@ -52,101 +37,4 @@ impl< MAX_WITHDRAWALS_PER_PAYLOAD, > { - pub fn new(execution_is_valid: bool) -> Self { - Self { execution_is_valid } - } - - fn is_valid_block_hash( - &self, - _payload: &ExecutionPayload< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - MAX_WITHDRAWALS_PER_PAYLOAD, - >, - _parent_beacon_block_root: &Root, - ) -> Result<()> { - if !self.execution_is_valid { - Err(ExecutionEngineError::InvalidBlockHash.into()) - } else { - Ok(()) - } - } - - fn is_valid_versioned_hashes( - &self, - _new_payload_request: &NewPayloadRequest< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - MAX_WITHDRAWALS_PER_PAYLOAD, - >, - ) -> Result<()> { - if !self.execution_is_valid { - Err(ExecutionEngineError::InvalidVersionedHashes.into()) - } else { - Ok(()) - } - } - - fn notify_new_payload( - &self, - _payload: &ExecutionPayload< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - MAX_WITHDRAWALS_PER_PAYLOAD, - >, - _parent_beacon_block_root: &Root, - ) -> Result<()> { - if !self.execution_is_valid { - Err(ExecutionEngineError::InvalidPayload.into()) - } else { - Ok(()) - } - } -} - -impl< - 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, - > ExecutionEngine - for DefaultExecutionEngine< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - MAX_WITHDRAWALS_PER_PAYLOAD, - > -{ - type NewPayloadRequest = NewPayloadRequest< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - MAX_WITHDRAWALS_PER_PAYLOAD, - >; - - fn verify_and_notify_new_payload( - &self, - new_payload_request: &Self::NewPayloadRequest, - ) -> Result<()> { - self.is_valid_block_hash( - &new_payload_request.execution_payload, - &new_payload_request.parent_beacon_block_root, - )?; - - self.is_valid_versioned_hashes(new_payload_request)?; - - self.notify_new_payload( - &new_payload_request.execution_payload, - &new_payload_request.parent_beacon_block_root, - ) - } } diff --git a/ethereum-consensus/src/deneb/spec/mod.rs b/ethereum-consensus/src/deneb/spec/mod.rs index 9f49e38d6..6a0356d68 100644 --- a/ethereum-consensus/src/deneb/spec/mod.rs +++ b/ethereum-consensus/src/deneb/spec/mod.rs @@ -39,7 +39,7 @@ pub use crate::{ process_attestation, process_block, process_execution_payload, process_voluntary_exit, }, epoch_processing::process_registry_updates, - execution_engine::{DefaultExecutionEngine, NewPayloadRequest}, + execution_engine::NewPayloadRequest, execution_payload::{ExecutionPayload, ExecutionPayloadHeader}, fork::upgrade_to_deneb, genesis::initialize_beacon_state_from_eth1, @@ -3267,15 +3267,6 @@ pub fn state_transition_block_in_slot< const MAX_WITHDRAWALS_PER_PAYLOAD: usize, const MAX_BLS_TO_EXECUTION_CHANGES: usize, const MAX_BLOB_COMMITMENTS_PER_BLOCK: usize, - E: ExecutionEngine< - NewPayloadRequest = NewPayloadRequest< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - MAX_WITHDRAWALS_PER_PAYLOAD, - >, - >, >( state: &mut BeaconState< SLOTS_PER_HISTORICAL_ROOT, @@ -3305,7 +3296,6 @@ pub fn state_transition_block_in_slot< MAX_BLS_TO_EXECUTION_CHANGES, MAX_BLOB_COMMITMENTS_PER_BLOCK, >, - execution_engine: &E, validation: Validation, context: &Context, ) -> Result<()> { @@ -3317,7 +3307,7 @@ pub fn state_transition_block_in_slot< verify_block_signature(state, signed_block, context)?; } let block = &mut signed_block.message; - process_block(state, block, execution_engine, context)?; + process_block(state, block, context)?; if validate_result && block.state_root != state.hash_tree_root()? { Err(Error::InvalidStateRoot) } else { @@ -3345,15 +3335,6 @@ pub fn state_transition< const MAX_WITHDRAWALS_PER_PAYLOAD: usize, const MAX_BLS_TO_EXECUTION_CHANGES: usize, const MAX_BLOB_COMMITMENTS_PER_BLOCK: usize, - E: ExecutionEngine< - NewPayloadRequest = NewPayloadRequest< - BYTES_PER_LOGS_BLOOM, - MAX_EXTRA_DATA_BYTES, - MAX_BYTES_PER_TRANSACTION, - MAX_TRANSACTIONS_PER_PAYLOAD, - MAX_WITHDRAWALS_PER_PAYLOAD, - >, - >, >( state: &mut BeaconState< SLOTS_PER_HISTORICAL_ROOT, @@ -3383,10 +3364,9 @@ pub fn state_transition< MAX_BLS_TO_EXECUTION_CHANGES, MAX_BLOB_COMMITMENTS_PER_BLOCK, >, - execution_engine: &E, validation: Validation, context: &Context, ) -> Result<()> { process_slots(state, signed_block.message.slot, context)?; - state_transition_block_in_slot(state, signed_block, execution_engine, validation, context) + state_transition_block_in_slot(state, signed_block, validation, context) } diff --git a/ethereum-consensus/src/execution_engine.rs b/ethereum-consensus/src/execution_engine.rs index cfaccb31e..98a92f8d4 100644 --- a/ethereum-consensus/src/execution_engine.rs +++ b/ethereum-consensus/src/execution_engine.rs @@ -1,23 +1,26 @@ -use crate::state_transition::Result; +use crate::{ + error::{Error, ExecutionEngineError}, + state_transition::Result, +}; + +/// `PayloadRequest` abstracts over the data sent to the `ExecutionEngine`. +/// NOTE: just a "marker" trait for now, until we have more substantial support for execution. +pub trait PayloadRequest {} /// `ExecutionEngine` abstracts over the interface between consensus and execution client. pub trait ExecutionEngine { - type NewPayloadRequest; - - /// Verify the new payload and associated data contained in `Self::NewPayloadRequest`. + /// Verify the new payload and associated data contained in `new_payload_request`. /// Either return `Err` describing a failure or `Ok(())` if validation succeeds. fn verify_and_notify_new_payload( &self, - new_payload_request: &Self::NewPayloadRequest, + new_payload_request: &impl PayloadRequest, ) -> Result<()>; } -/// "no-op" implementation for convenience. -/// Always succeeds validation. -impl ExecutionEngine for () { - type NewPayloadRequest = (); - - fn verify_and_notify_new_payload(&self, _: &Self::NewPayloadRequest) -> Result<()> { - Ok(()) +/// A "no-op" implementation that succeeds for `true` or fails for `false`. +/// Useful for mocking the execution engine behavior. +impl ExecutionEngine for bool { + fn verify_and_notify_new_payload(&self, _: &impl PayloadRequest) -> Result<()> { + self.then_some(()).ok_or(Error::ExecutionEngine(ExecutionEngineError::InvalidPayload)) } } diff --git a/ethereum-consensus/src/state_transition/context.rs b/ethereum-consensus/src/state_transition/context.rs index e5a11272c..2232ec04e 100644 --- a/ethereum-consensus/src/state_transition/context.rs +++ b/ethereum-consensus/src/state_transition/context.rs @@ -3,13 +3,17 @@ use crate::{ clock::{self, Clock, SystemTimeProvider}, configs::{self, Config}, deneb, + execution_engine::ExecutionEngine, networks::Network, phase0, primitives::{Epoch, ExecutionAddress, Gwei, Hash32, Slot, Version, U256}, Error, Fork, }; -#[derive(Debug, Default, Clone, serde::Deserialize)] +// Controls the default behavior of the execution engine via the `bool` impl of `ExecutionEngine`. +pub const DEFAULT_EXECUTION_ENGINE_VALIDITY: bool = true; + +#[derive(Clone)] pub struct Context { // phase0 preset pub max_committees_per_slot: u64, @@ -112,6 +116,13 @@ pub struct Context { pub deposit_chain_id: usize, pub deposit_network_id: usize, pub deposit_contract_address: ExecutionAddress, + + // Provides an implementation of `execution_engine::ExecutionEngine`. + #[cfg(feature = "spec-tests")] + // This field is exposed so that the execution engine behavior can be mocked when testing. + pub execution_engine: bool, + #[cfg(not(feature = "spec-tests"))] + execution_engine: bool, } impl Context { @@ -259,6 +270,7 @@ impl Context { deposit_chain_id: config.deposit_chain_id, deposit_network_id: config.deposit_network_id, deposit_contract_address: config.deposit_contract_address.clone(), + execution_engine: DEFAULT_EXECUTION_ENGINE_VALIDITY, } } @@ -399,4 +411,8 @@ impl Context { pub fn network(&self) -> &Network { &self.name } + + pub fn execution_engine(&self) -> impl ExecutionEngine { + self.execution_engine + } } diff --git a/ethereum-consensus/src/state_transition/executor.rs b/ethereum-consensus/src/state_transition/executor.rs index 44bbbf864..b767c359c 100644 --- a/ethereum-consensus/src/state_transition/executor.rs +++ b/ethereum-consensus/src/state_transition/executor.rs @@ -4,7 +4,6 @@ use crate::{ Error, Fork, }; -#[derive(Debug)] pub struct Executor< const SLOTS_PER_HISTORICAL_ROOT: usize, const HISTORICAL_ROOTS_LIMIT: usize, @@ -244,12 +243,10 @@ impl< let fork_slot = self.context.bellatrix_fork_epoch * self.context.slots_per_epoch; altair::process_slots(&mut state, fork_slot, &self.context)?; let mut state = bellatrix::upgrade_to_bellatrix(&state, &self.context); - let execution_engine = bellatrix::DefaultExecutionEngine::default(); if signed_block.message.slot == state.slot { bellatrix::state_transition_block_in_slot( &mut state, signed_block, - &execution_engine, validation, &self.context, )?; @@ -257,7 +254,6 @@ impl< bellatrix::state_transition( &mut state, signed_block, - &execution_engine, validation, &self.context, )?; @@ -269,12 +265,10 @@ impl< let fork_slot = self.context.bellatrix_fork_epoch * self.context.slots_per_epoch; altair::process_slots(state, fork_slot, &self.context)?; let mut state = bellatrix::upgrade_to_bellatrix(state, &self.context); - let execution_engine = bellatrix::DefaultExecutionEngine::default(); if signed_block.message.slot == state.slot { bellatrix::state_transition_block_in_slot( &mut state, signed_block, - &execution_engine, validation, &self.context, )?; @@ -282,7 +276,6 @@ impl< bellatrix::state_transition( &mut state, signed_block, - &execution_engine, validation, &self.context, )?; @@ -291,14 +284,7 @@ impl< Ok(()) } BeaconState::Bellatrix(state) => { - let execution_engine = bellatrix::DefaultExecutionEngine::default(); - bellatrix::state_transition( - state, - signed_block, - &execution_engine, - validation, - &self.context, - ) + bellatrix::state_transition(state, signed_block, validation, &self.context) } } } diff --git a/spec-tests/Cargo.toml b/spec-tests/Cargo.toml index c23a0067e..3d1f6e107 100644 --- a/spec-tests/Cargo.toml +++ b/spec-tests/Cargo.toml @@ -10,6 +10,7 @@ ssz_rs = { workspace = true } ethereum-consensus = { path = "../ethereum-consensus", features = [ "serde", "secret-key-debug", + "spec-tests", ] } libtest-mimic = "0.7.0" heck = "0.5.0" diff --git a/spec-tests/runners/finality.rs b/spec-tests/runners/finality.rs index 6ae694be9..570bb9622 100644 --- a/spec-tests/runners/finality.rs +++ b/spec-tests/runners/finality.rs @@ -1,66 +1,21 @@ use crate::{ - runners::{gen_exec, gen_match_for_all}, + runners::{ + gen_exec, gen_match_for_all, + utils::{load_blocks_test, run_blocks_test}, + }, test_case::TestCase, - test_utils::{load_snappy_ssz, load_yaml, Error}, + test_utils::Error, }; -use ethereum_consensus::state_transition::Context; -use serde::Deserialize; - -#[derive(Deserialize)] -struct FinalityMeta { - blocks_count: usize, -} - -fn load_test( - test_case_path: &str, -) -> (S, S, Vec) { - let path = test_case_path.to_string() + "/pre.ssz_snappy"; - let pre: S = load_snappy_ssz(&path).unwrap(); - - let path = test_case_path.to_string() + "/post.ssz_snappy"; - let post: S = load_snappy_ssz(&path).unwrap(); - - let path = test_case_path.to_string() + "/meta.yaml"; - let meta: FinalityMeta = load_yaml(&path); - let blocks_count = meta.blocks_count; - - let mut blocks = vec![]; - for i in 0..blocks_count { - let path = format!("{test_case_path}/blocks_{i}.ssz_snappy"); - let block: B = load_snappy_ssz(&path).unwrap(); - blocks.push(block); - } - - (pre, post, blocks) -} - -fn run_test( - pre: S, - post: S, - mut blocks: Vec, - _context: &Context, -) -> Result<(), Error> { - for _block in blocks.iter_mut() { - todo!(/* - TODO: move exec engine as member of `Context` - spec::state_transition(&mut pre, block, Validation::Enabled, $context).map_err(Error::from)?; - */); - } - if pre == post { - Ok(()) - } else { - Err(Error::InvalidState) - } -} +use ethereum_consensus::state_transition::Validation; pub fn dispatch(test: &TestCase) -> Result<(), Error> { match test.meta.handler.0.as_str() { "finality" => { gen_match_for_all! { test, - load_test, - |(pre, post, blocks): (spec::BeaconState, spec::BeaconState, Vec), _context| { - run_test(pre, post, blocks, _context) + load_blocks_test, + |(pre, post, blocks): (spec::BeaconState, Option, Vec), context| { + run_blocks_test(pre, post, blocks, context, |state, signed_block, context| { spec::state_transition(state, signed_block, Validation::Enabled, context) }) } } } diff --git a/spec-tests/runners/fork.rs b/spec-tests/runners/fork.rs index 17a0c2ae8..ad7bcb2c8 100644 --- a/spec-tests/runners/fork.rs +++ b/spec-tests/runners/fork.rs @@ -40,7 +40,7 @@ pub fn dispatch(test: &TestCase) -> Result<(), Error> { test, load_test, |(pre, expected): (pre_spec::BeaconState, spec::BeaconState), context| { - run_test(pre, expected, context, |state, context| spec::upgrade_to_altair(state,context).unwrap()) + run_test(pre, expected, context, |state, context| spec::upgrade_to_altair(state, context).unwrap()) } } } @@ -91,7 +91,7 @@ pub fn dispatch(test: &TestCase) -> Result<(), Error> { test, load_test, |(pre, expected): (pre_spec::BeaconState, spec::BeaconState), context| { - run_test(pre, expected, context, |state, context| spec::upgrade_to_altair(state,context).unwrap()) + run_test(pre, expected, context, |state, context| spec::upgrade_to_altair(state, context).unwrap()) } } } diff --git a/spec-tests/runners/mod.rs b/spec-tests/runners/mod.rs index 9d4c21394..fc19790cc 100644 --- a/spec-tests/runners/mod.rs +++ b/spec-tests/runners/mod.rs @@ -10,6 +10,7 @@ pub mod sanity; pub mod shuffling; pub mod ssz_static; pub mod transition; +pub mod utils; macro_rules! gen_exec { ($test_case:expr, $loader_fn:expr, $exec_fn:expr) => { diff --git a/spec-tests/runners/operations.rs b/spec-tests/runners/operations.rs index 28a9666c7..955f58ab2 100644 --- a/spec-tests/runners/operations.rs +++ b/spec-tests/runners/operations.rs @@ -172,23 +172,10 @@ pub fn dispatch(test: &TestCase) -> Result<(), Error> { gen_exec! { test, load_execution_payload_test, - |(mut pre, post, mut operation, execution_valid): (spec::BeaconState, Option, spec::ExecutionPayload, bool), context| { - let engine = spec::DefaultExecutionEngine::new(execution_valid); - let result = spec::process_execution_payload(&mut pre, &mut operation, &engine, context); - if let Some(post) = post { - assert_eq!(result.unwrap(), ()); - if pre == post { - Ok(()) - } else { - Err(Error::InvalidState) - } - } else { - if result.is_err() { - Ok(()) - } else { - Err(Error::ExpectedError) - } - } + |(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) } } } @@ -196,23 +183,10 @@ pub fn dispatch(test: &TestCase) -> Result<(), Error> { gen_exec! { test, load_execution_payload_test, - |(mut pre, post, mut operation, execution_valid): (spec::BeaconState, Option, spec::ExecutionPayload, bool), context| { - let engine = spec::DefaultExecutionEngine::new(execution_valid); - let result = spec::process_execution_payload(&mut pre, &mut operation, &engine, context); - if let Some(post) = post { - assert_eq!(result.unwrap(), ()); - if pre == post { - Ok(()) - } else { - Err(Error::InvalidState) - } - } else { - if result.is_err() { - Ok(()) - } else { - Err(Error::ExpectedError) - } - } + |(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) } } } @@ -220,23 +194,10 @@ pub fn dispatch(test: &TestCase) -> Result<(), Error> { gen_exec! { test, load_execution_payload_test, - |(mut pre, post, mut operation, execution_valid): (spec::BeaconState, Option, spec::BeaconBlockBody, bool), context| { - let engine = spec::DefaultExecutionEngine::new(execution_valid); - let result = spec::process_execution_payload(&mut pre, &mut operation, &engine, context); - if let Some(post) = post { - assert_eq!(result.unwrap(), ()); - if pre == post { - Ok(()) - } else { - Err(Error::InvalidState) - } - } else { - if result.is_err() { - Ok(()) - } else { - Err(Error::ExpectedError) - } - } + |(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) } } } @@ -244,23 +205,10 @@ pub fn dispatch(test: &TestCase) -> Result<(), Error> { gen_exec! { test, load_execution_payload_test, - |(mut pre, post, mut operation, execution_valid): (spec::BeaconState, Option, spec::ExecutionPayload, bool), context| { - let engine = spec::DefaultExecutionEngine::new(execution_valid); - let result = spec::process_execution_payload(&mut pre, &mut operation, &engine, context); - if let Some(post) = post { - assert_eq!(result.unwrap(), ()); - if pre == post { - Ok(()) - } else { - Err(Error::InvalidState) - } - } else { - if result.is_err() { - Ok(()) - } else { - Err(Error::ExpectedError) - } - } + |(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) } } } @@ -268,23 +216,10 @@ pub fn dispatch(test: &TestCase) -> Result<(), Error> { gen_exec! { test, load_execution_payload_test, - |(mut pre, post, mut operation, execution_valid): (spec::BeaconState, Option, spec::ExecutionPayload, bool), context| { - let engine = spec::DefaultExecutionEngine::new(execution_valid); - let result = spec::process_execution_payload(&mut pre, &mut operation, &engine, context); - if let Some(post) = post { - assert_eq!(result.unwrap(), ()); - if pre == post { - Ok(()) - } else { - Err(Error::InvalidState) - } - } else { - if result.is_err() { - Ok(()) - } else { - Err(Error::ExpectedError) - } - } + |(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) } } } @@ -292,23 +227,10 @@ pub fn dispatch(test: &TestCase) -> Result<(), Error> { gen_exec! { test, load_execution_payload_test, - |(mut pre, post, mut operation, execution_valid): (spec::BeaconState, Option, spec::BeaconBlockBody, bool), context| { - let engine = spec::DefaultExecutionEngine::new(execution_valid); - let result = spec::process_execution_payload(&mut pre, &mut operation, &engine, context); - if let Some(post) = post { - assert_eq!(result.unwrap(), ()); - if pre == post { - Ok(()) - } else { - Err(Error::InvalidState) - } - } else { - if result.is_err() { - Ok(()) - } else { - Err(Error::ExpectedError) - } - } + |(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) } } } diff --git a/spec-tests/runners/random.rs b/spec-tests/runners/random.rs index 9cddb9b8b..a35955105 100644 --- a/spec-tests/runners/random.rs +++ b/spec-tests/runners/random.rs @@ -1,46 +1,21 @@ use crate::{ - runners::{gen_exec, gen_match_for_all}, + runners::{ + gen_exec, gen_match_for_all, + utils::{load_blocks_test, run_blocks_test}, + }, test_case::TestCase, - test_utils::{load_snappy_ssz, load_yaml, Error}, + test_utils::Error, }; -use serde::Deserialize; - -#[derive(Deserialize)] -struct RandomMeta { - blocks_count: usize, -} - -fn load_test( - test_case_path: &str, -) -> (S, Option, Vec) { - let path = test_case_path.to_string() + "/pre.ssz_snappy"; - let pre: S = load_snappy_ssz(&path).unwrap(); - - let path = test_case_path.to_string() + "/post.ssz_snappy"; - let post: Option = load_snappy_ssz(&path); - - let path = test_case_path.to_string() + "/meta.yaml"; - let meta: RandomMeta = load_yaml(&path); - let blocks_count = meta.blocks_count; - - let mut blocks = vec![]; - for i in 0..blocks_count { - let path = format!("{test_case_path}/blocks_{i}.ssz_snappy"); - let block: B = load_snappy_ssz(&path).unwrap(); - blocks.push(block); - } - - (pre, post, blocks) -} +use ethereum_consensus::state_transition::Validation; pub fn dispatch(test: &TestCase) -> Result<(), Error> { match test.meta.handler.0.as_str() { "random" => { gen_match_for_all! { test, - load_test, - |(pre, post, blocks): (spec::BeaconState, Option, Vec), _context| { - crate::runners::sanity::run_test(pre, post, blocks, _context) + load_blocks_test, + |(pre, post, blocks): (spec::BeaconState, Option, Vec), context| { + run_blocks_test(pre, post, blocks, context, |state, signed_block, context| { spec::state_transition(state, signed_block, Validation::Enabled, context) }) } } } diff --git a/spec-tests/runners/sanity.rs b/spec-tests/runners/sanity.rs index 467fc9af9..cbca6e56c 100644 --- a/spec-tests/runners/sanity.rs +++ b/spec-tests/runners/sanity.rs @@ -1,76 +1,49 @@ use crate::{ - runners::{gen_exec, gen_match_for_all}, + runners::{ + gen_exec, gen_match_for_all, + utils::{load_blocks_test, run_blocks_test}, + }, test_case::TestCase, test_utils::{load_snappy_ssz, load_yaml, Error}, }; -use ethereum_consensus::state_transition::Context; -use serde::Deserialize; +use ethereum_consensus::state_transition::Validation; -#[derive(Deserialize)] -struct BlocksMeta { - blocks_count: usize, -} - -fn load_test( - test_case_path: &str, -) -> (S, Option, Vec) { +fn load_test(test_case_path: &str) -> (S, S, u64) { let path = test_case_path.to_string() + "/pre.ssz_snappy"; let pre: S = load_snappy_ssz(&path).unwrap(); let path = test_case_path.to_string() + "/post.ssz_snappy"; - let post: Option = load_snappy_ssz(&path); + let post: S = load_snappy_ssz(&path).unwrap(); - let path = test_case_path.to_string() + "/meta.yaml"; - let meta: BlocksMeta = load_yaml(&path); - let blocks_count = meta.blocks_count; - - let mut blocks = vec![]; - for i in 0..blocks_count { - let path = format!("{test_case_path}/blocks_{i}.ssz_snappy"); - let block: B = load_snappy_ssz(&path).unwrap(); - blocks.push(block); - } + let path = test_case_path.to_string() + "/slots.yaml"; + let slots: u64 = load_yaml(&path); - (pre, post, blocks) -} - -pub(crate) fn run_test( - pre: S, - post: Option, - mut blocks: Vec, - _context: &Context, -) -> Result<(), Error> { - for _block in blocks.iter_mut() { - todo!(/* - TODO: move exec engine as member of `Context` - spec::state_transition(&mut pre, block, Validation::Enabled, $context).map_err(Error::from)?; - */); - } - let result = Result::<(), _>::Err(Error::ExpectedError); - if let Some(post) = post { - assert_eq!(result.unwrap(), ()); - if pre == post { - Ok(()) - } else { - Err(Error::InvalidState) - } - } else { - if result.is_err() { - Ok(()) - } else { - Err(Error::ExpectedError) - } - } + (pre, post, slots) } pub fn dispatch(test: &TestCase) -> Result<(), Error> { match test.meta.handler.0.as_str() { - "sanity" => { + "blocks" => { + gen_match_for_all! { + test, + load_blocks_test, + |(pre, post, blocks): (spec::BeaconState, Option, Vec), context| { + run_blocks_test(pre, post, blocks, context, |state, signed_block, context| { spec::state_transition(state, signed_block, Validation::Enabled, context) }) + } + } + } + "slots" => { gen_match_for_all! { test, load_test, - |(pre, post, blocks): (spec::BeaconState, Option, Vec), _context| { - run_test(pre, post, blocks, _context) + |(mut pre, post, slots): (spec::BeaconState, spec::BeaconState, u64), context| { + let target_slot = pre.slot + slots; + spec::process_slots(&mut pre, target_slot, context)?; + if pre != post { + Err(Error::InvalidState) + } else { + Ok(()) + } } } } diff --git a/spec-tests/runners/utils.rs b/spec-tests/runners/utils.rs new file mode 100644 index 000000000..5826cbf25 --- /dev/null +++ b/spec-tests/runners/utils.rs @@ -0,0 +1,61 @@ +use crate::test_utils::{load_snappy_ssz, load_yaml, Error}; +use ethereum_consensus::{state_transition::Context, Error as SpecError}; +use serde::Deserialize; + +#[derive(Deserialize)] +struct BlocksMeta { + blocks_count: usize, +} + +pub(crate) fn load_blocks_test( + test_case_path: &str, +) -> (S, Option, Vec) { + let path = test_case_path.to_string() + "/pre.ssz_snappy"; + let pre: S = load_snappy_ssz(&path).unwrap(); + + let path = test_case_path.to_string() + "/post.ssz_snappy"; + let post: Option = load_snappy_ssz(&path); + + let path = test_case_path.to_string() + "/meta.yaml"; + let meta: BlocksMeta = load_yaml(&path); + let blocks_count = meta.blocks_count; + + let mut blocks = vec![]; + for i in 0..blocks_count { + let path = format!("{test_case_path}/blocks_{i}.ssz_snappy"); + let block: B = load_snappy_ssz(&path).unwrap(); + blocks.push(block); + } + + (pre, post, blocks) +} + +pub(crate) fn run_blocks_test( + mut pre: S, + post: Option, + mut blocks: Vec, + context: &Context, + exec_fn: F, +) -> Result<(), Error> +where + F: Fn(&mut S, &mut B, &Context) -> Result<(), SpecError>, +{ + let result = blocks + .iter_mut() + .map(|block| exec_fn(&mut pre, block, context)) + .collect::, SpecError>>(); + if let Some(post) = post { + assert!(result.is_ok()); + if pre == post { + Ok(()) + } else { + Err(Error::InvalidState) + } + } else { + if result.is_err() { + Ok(()) + } else { + Err(Error::ExpectedError) + } + } +}