From 87c22d22f8d7505824a839e7da81673cfbc95dc4 Mon Sep 17 00:00:00 2001 From: Thomas Coratger <60488569+tcoratger@users.noreply.github.com> Date: Tue, 11 Jun 2024 15:54:28 +0200 Subject: [PATCH] test: add unit tests for `BundleStateWithReceipts` (#8741) --- Cargo.lock | 2 + crates/evm/execution-types/Cargo.toml | 2 + crates/evm/execution-types/src/bundle.rs | 274 +++++++++++++++++++++++ 3 files changed, 278 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index fc39d9f63..c7fae2a44 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6982,6 +6982,8 @@ dependencies = [ name = "reth-execution-types" version = "0.2.0-beta.9" dependencies = [ + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=14ed25d)", + "alloy-primitives", "reth-execution-errors", "reth-primitives", "reth-trie", diff --git a/crates/evm/execution-types/Cargo.toml b/crates/evm/execution-types/Cargo.toml index 8c3ce4dc0..5f61a1eb8 100644 --- a/crates/evm/execution-types/Cargo.toml +++ b/crates/evm/execution-types/Cargo.toml @@ -19,6 +19,8 @@ revm.workspace = true [dev-dependencies] reth-primitives = { workspace = true, features = ["test-utils"] } +alloy-primitives.workspace = true +alloy-eips.workspace = true [features] optimism = [] \ No newline at end of file diff --git a/crates/evm/execution-types/src/bundle.rs b/crates/evm/execution-types/src/bundle.rs index 524a7ae88..baba882e8 100644 --- a/crates/evm/execution-types/src/bundle.rs +++ b/crates/evm/execution-types/src/bundle.rs @@ -299,3 +299,277 @@ impl BundleStateWithReceipts { std::mem::swap(&mut self.bundle, &mut other) } } + +#[cfg(test)] +mod tests { + use super::*; + use alloy_eips::{eip6110::DepositRequest, eip7002::WithdrawalRequest}; + use alloy_primitives::{FixedBytes, LogData}; + use reth_primitives::{Address, Receipts, Request, Requests, TxType, B256}; + use std::collections::HashMap; + + #[test] + fn test_initialisation() { + // Create a new BundleState object with initial data + let bundle = BundleState::new( + vec![(Address::new([2; 20]), None, Some(AccountInfo::default()), HashMap::default())], + vec![vec![(Address::new([2; 20]), None, vec![])]], + vec![], + ); + + // Create a Receipts object with a vector of receipt vectors + let receipts = Receipts { + receipt_vec: vec![vec![Some(Receipt { + tx_type: TxType::Legacy, + cumulative_gas_used: 46913, + logs: vec![], + success: true, + #[cfg(feature = "optimism")] + deposit_nonce: Some(18), + #[cfg(feature = "optimism")] + deposit_receipt_version: Some(34), + })]], + }; + + // Create a Requests object with a vector of requests, including DepositRequest and + // WithdrawalRequest + let requests = vec![Requests(vec![ + Request::DepositRequest(DepositRequest { + pubkey: FixedBytes::<48>::from([1; 48]), + withdrawal_credentials: B256::from([0; 32]), + amount: 1111, + signature: FixedBytes::<96>::from([2; 96]), + index: 222, + }), + Request::DepositRequest(DepositRequest { + pubkey: FixedBytes::<48>::from([23; 48]), + withdrawal_credentials: B256::from([0; 32]), + amount: 34343, + signature: FixedBytes::<96>::from([43; 96]), + index: 1212, + }), + Request::WithdrawalRequest(WithdrawalRequest { + source_address: Address::from([1; 20]), + validator_public_key: FixedBytes::<48>::from([10; 48]), + amount: 72, + }), + ])]; + + // Define the first block number + let first_block = 123; + + // Create a BundleStateWithReceipts object with the created bundle, receipts, requests, and + // first_block + let exec_res = BundleStateWithReceipts { + bundle: bundle.clone(), + receipts: receipts.clone(), + requests: requests.clone(), + first_block, + }; + + // Assert that creating a new BundleStateWithReceipts using the constructor matches exec_res + assert_eq!( + BundleStateWithReceipts::new(bundle, receipts.clone(), first_block, requests.clone()), + exec_res + ); + + // Create a BundleStateInit object and insert initial data + let mut state_init: BundleStateInit = HashMap::new(); + state_init + .insert(Address::new([2; 20]), (None, Some(Account::default()), HashMap::default())); + + // Create a HashMap for account reverts and insert initial data + let mut revert_inner: HashMap = HashMap::new(); + revert_inner.insert(Address::new([2; 20]), (None, vec![])); + + // Create a RevertsInit object and insert the revert_inner data + let mut revert_init: RevertsInit = HashMap::new(); + revert_init.insert(123, revert_inner); + + // Assert that creating a new BundleStateWithReceipts using the new_init method matches + // exec_res + assert_eq!( + BundleStateWithReceipts::new_init( + state_init, + revert_init, + vec![], + receipts, + first_block, + requests, + ), + exec_res + ); + } + + #[test] + fn test_block_number_to_index() { + // Create a Receipts object with a vector of receipt vectors + let receipts = Receipts { + receipt_vec: vec![vec![Some(Receipt { + tx_type: TxType::Legacy, + cumulative_gas_used: 46913, + logs: vec![], + success: true, + #[cfg(feature = "optimism")] + deposit_nonce: Some(18), + #[cfg(feature = "optimism")] + deposit_receipt_version: Some(34), + })]], + }; + + // Define the first block number + let first_block = 123; + + // Create a BundleStateWithReceipts object with the created bundle, receipts, requests, and + // first_block + let exec_res = BundleStateWithReceipts { + bundle: Default::default(), + receipts, + requests: vec![], + first_block, + }; + + // Test before the first block + assert_eq!(exec_res.block_number_to_index(12), None); + + // Test after after the first block but index larger than receipts length + assert_eq!(exec_res.block_number_to_index(133), None); + + // Test after the first block + assert_eq!(exec_res.block_number_to_index(123), Some(0)); + } + + #[test] + fn test_get_logs() { + // Create a Receipts object with a vector of receipt vectors + let receipts = Receipts { + receipt_vec: vec![vec![Some(Receipt { + tx_type: TxType::Legacy, + cumulative_gas_used: 46913, + logs: vec![Log::::default()], + success: true, + #[cfg(feature = "optimism")] + deposit_nonce: Some(18), + #[cfg(feature = "optimism")] + deposit_receipt_version: Some(34), + })]], + }; + + // Define the first block number + let first_block = 123; + + // Create a BundleStateWithReceipts object with the created bundle, receipts, requests, and + // first_block + let exec_res = BundleStateWithReceipts { + bundle: Default::default(), + receipts, + requests: vec![], + first_block, + }; + + // Get logs for block number 123 + let logs: Vec<&Log> = exec_res.logs(123).unwrap().collect(); + + // Assert that the logs match the expected logs + assert_eq!(logs, vec![&Log::::default()]); + } + + #[test] + fn test_receipts_by_block() { + // Create a Receipts object with a vector of receipt vectors + let receipts = Receipts { + receipt_vec: vec![vec![Some(Receipt { + tx_type: TxType::Legacy, + cumulative_gas_used: 46913, + logs: vec![Log::::default()], + success: true, + #[cfg(feature = "optimism")] + deposit_nonce: Some(18), + #[cfg(feature = "optimism")] + deposit_receipt_version: Some(34), + })]], + }; + + // Define the first block number + let first_block = 123; + + // Create a BundleStateWithReceipts object with the created bundle, receipts, requests, and + // first_block + let exec_res = BundleStateWithReceipts { + bundle: Default::default(), // Default value for bundle + receipts, // Include the created receipts + requests: vec![], // Empty vector for requests + first_block, // Set the first block number + }; + + // Get receipts for block number 123 and convert the result into a vector + let receipts_by_block: Vec<_> = exec_res.receipts_by_block(123).iter().collect(); + + // Assert that the receipts for block number 123 match the expected receipts + assert_eq!( + receipts_by_block, + vec![&Some(Receipt { + tx_type: TxType::Legacy, + cumulative_gas_used: 46913, + logs: vec![Log::::default()], + success: true, + #[cfg(feature = "optimism")] + deposit_nonce: Some(18), + #[cfg(feature = "optimism")] + deposit_receipt_version: Some(34), + })] + ); + } + + #[test] + fn test_receipts_len() { + // Create a Receipts object with a vector of receipt vectors + let receipts = Receipts { + receipt_vec: vec![vec![Some(Receipt { + tx_type: TxType::Legacy, + cumulative_gas_used: 46913, + logs: vec![Log::::default()], + success: true, + #[cfg(feature = "optimism")] + deposit_nonce: Some(18), + #[cfg(feature = "optimism")] + deposit_receipt_version: Some(34), + })]], + }; + + // Create an empty Receipts object + let receipts_empty = Receipts { receipt_vec: vec![] }; + + // Define the first block number + let first_block = 123; + + // Create a BundleStateWithReceipts object with the created bundle, receipts, requests, and + // first_block + let exec_res = BundleStateWithReceipts { + bundle: Default::default(), // Default value for bundle + receipts, // Include the created receipts + requests: vec![], // Empty vector for requests + first_block, // Set the first block number + }; + + // Assert that the length of receipts in exec_res is 1 + assert_eq!(exec_res.len(), 1); + + // Assert that exec_res is not empty + assert!(!exec_res.is_empty()); + + // Create a BundleStateWithReceipts object with an empty Receipts object + let exec_res_empty_receipts = BundleStateWithReceipts { + bundle: Default::default(), // Default value for bundle + receipts: receipts_empty, // Include the empty receipts + requests: vec![], // Empty vector for requests + first_block, // Set the first block number + }; + + // Assert that the length of receipts in exec_res_empty_receipts is 0 + assert_eq!(exec_res_empty_receipts.len(), 0); + + // Assert that exec_res_empty_receipts is empty + assert!(exec_res_empty_receipts.is_empty()); + } +}