From c46ff698baafd4c313d51b585d25490eb33920be Mon Sep 17 00:00:00 2001 From: Roman Krasiuk Date: Mon, 29 Jan 2024 11:06:53 +0100 Subject: [PATCH] test(tree): clean up tree testing utils (#6270) --- crates/blockchain-tree/src/blockchain_tree.rs | 12 +- crates/storage/provider/src/chain.rs | 5 + .../storage/provider/src/test_utils/blocks.rs | 171 ++++++++++-------- 3 files changed, 105 insertions(+), 83 deletions(-) diff --git a/crates/blockchain-tree/src/blockchain_tree.rs b/crates/blockchain-tree/src/blockchain_tree.rs index f88a8d1277..fe90047f62 100644 --- a/crates/blockchain-tree/src/blockchain_tree.rs +++ b/crates/blockchain-tree/src/blockchain_tree.rs @@ -1576,9 +1576,9 @@ mod tests { ); } - #[tokio::test] - async fn test_side_chain_fork() { - let data = BlockChainTestData::default_with_numbers(11, 12); + #[test] + fn test_side_chain_fork() { + let data = BlockChainTestData::default_from_number(11); let (block1, exec1) = data.blocks[0].clone(); let (block2, exec2) = data.blocks[1].clone(); let genesis = data.genesis; @@ -1664,9 +1664,9 @@ mod tests { assert_eq!(tree.state.chains.get(&1.into()).unwrap().state().state().reverts.len(), 1); } - #[tokio::test] - async fn sanity_path() { - let data = BlockChainTestData::default_with_numbers(11, 12); + #[test] + fn sanity_path() { + let data = BlockChainTestData::default_from_number(11); let (block1, exec1) = data.blocks[0].clone(); let (block2, exec2) = data.blocks[1].clone(); let genesis = data.genesis; diff --git a/crates/storage/provider/src/chain.rs b/crates/storage/provider/src/chain.rs index ae9e5a3f4b..6db59fc76b 100644 --- a/crates/storage/provider/src/chain.rs +++ b/crates/storage/provider/src/chain.rs @@ -68,6 +68,11 @@ impl Chain { self.blocks.values().map(|block| block.header.clone()) } + /// Get cached trie updates for this chain. + pub fn trie_updates(&self) -> Option<&TrieUpdates> { + self.trie_updates.as_ref() + } + /// Get post state of this chain pub fn state(&self) -> &BundleStateWithReceipts { &self.state diff --git a/crates/storage/provider/src/test_utils/blocks.rs b/crates/storage/provider/src/test_utils/blocks.rs index 562483b5e1..10d170421c 100644 --- a/crates/storage/provider/src/test_utils/blocks.rs +++ b/crates/storage/provider/src/test_utils/blocks.rs @@ -1,13 +1,19 @@ //! Dummy blocks and data for tests - use crate::{BundleStateWithReceipts, DatabaseProviderRW}; use alloy_rlp::Decodable; use reth_db::{database::Database, models::StoredBlockBodyIndices, tables}; use reth_primitives::{ - b256, hex_literal::hex, Account, Address, BlockNumber, Bytes, Header, Log, Receipt, Receipts, - SealedBlock, SealedBlockWithSenders, StorageEntry, TxType, Withdrawal, B256, U256, + b256, + hex_literal::hex, + proofs::{state_root_unhashed, storage_root_unhashed}, + revm::compat::into_reth_acc, + Address, BlockNumber, Bytes, Header, Log, Receipt, Receipts, SealedBlock, + SealedBlockWithSenders, TxType, Withdrawal, B256, U256, +}; +use revm::{ + db::BundleState, + primitives::{AccountInfo, HashMap}, }; -use std::collections::HashMap; /// Assert genesis block pub fn assert_genesis_block(provider: &DatabaseProviderRW, g: SealedBlock) { @@ -47,6 +53,8 @@ pub fn assert_genesis_block(provider: &DatabaseProviderRW, g: // SyncStage is not updated in tests } +const BLOCK_RLP: [u8; 610] = hex!("f9025ff901f7a0c86e8cc0310ae7c531c758678ddbfd16fc51c8cef8cec650b032de9869e8b94fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942adc25665018aa1fe0e6bc666dac8fc2697ff9baa050554882fbbda2c2fd93fdc466db9946ea262a67f7a76cc169e714f105ab583da00967f09ef1dfed20c0eacfaa94d5cd4002eda3242ac47eae68972d07b106d192a0e3c8b47fbfc94667ef4cceb17e5cc21e3b1eebd442cebb27f07562b33836290db90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001830f42408238108203e800a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f862f860800a83061a8094095e7baea6a6c7c4c2dfeb977efac326af552d8780801ba072ed817487b84ba367d15d2f039b5fc5f087d0a8882fbdf73e8cb49357e1ce30a0403d800545b8fc544f92ce8124e2255f8c3c6af93f28243a120585d4c4c6a2a3c0"); + /// Test chain with genesis, blocks, execution results /// that have valid changesets. #[derive(Debug)] @@ -59,18 +67,18 @@ pub struct BlockChainTestData { impl BlockChainTestData { /// Create test data with two blocks that are connected, specifying their block numbers. - pub fn default_with_numbers(one: BlockNumber, two: BlockNumber) -> Self { - let one = block1(one); - let hash = one.0.hash; - Self { genesis: genesis(), blocks: vec![one, block2(two, hash)] } + pub fn default_from_number(first: BlockNumber) -> Self { + let one = block1(first); + let two = block2(first + 1, one.0.hash, &one.1); + Self { genesis: genesis(), blocks: vec![one, two] } } } impl Default for BlockChainTestData { fn default() -> Self { let one = block1(1); - let hash = one.0.hash; - Self { genesis: genesis(), blocks: vec![one, block2(2, hash)] } + let two = block2(2, one.0.hash, &one.1); + Self { genesis: genesis(), blocks: vec![one, two] } } } @@ -85,49 +93,41 @@ pub fn genesis() -> SealedBlock { } } +fn bundle_state_root(state: &BundleStateWithReceipts) -> B256 { + state_root_unhashed(state.bundle_accounts_iter().filter_map(|(address, account)| { + account.info.as_ref().map(|info| { + ( + address, + ( + into_reth_acc(info.clone()), + storage_root_unhashed( + account + .storage + .iter() + .map(|(slot, value)| ((*slot).into(), value.present_value)), + ), + ), + ) + }) + })) +} + /// Block one that points to genesis fn block1(number: BlockNumber) -> (SealedBlockWithSenders, BundleStateWithReceipts) { - let mut block_rlp = hex!("f9025ff901f7a0c86e8cc0310ae7c531c758678ddbfd16fc51c8cef8cec650b032de9869e8b94fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942adc25665018aa1fe0e6bc666dac8fc2697ff9baa050554882fbbda2c2fd93fdc466db9946ea262a67f7a76cc169e714f105ab583da00967f09ef1dfed20c0eacfaa94d5cd4002eda3242ac47eae68972d07b106d192a0e3c8b47fbfc94667ef4cceb17e5cc21e3b1eebd442cebb27f07562b33836290db90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001830f42408238108203e800a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f862f860800a83061a8094095e7baea6a6c7c4c2dfeb977efac326af552d8780801ba072ed817487b84ba367d15d2f039b5fc5f087d0a8882fbdf73e8cb49357e1ce30a0403d800545b8fc544f92ce8124e2255f8c3c6af93f28243a120585d4c4c6a2a3c0").as_slice(); - let mut block = SealedBlock::decode(&mut block_rlp).unwrap(); - block.withdrawals = Some(vec![Withdrawal::default()]); - let mut header = block.header.clone().unseal(); - header.number = number; - header.state_root = b256!("5d035ccb3e75a9057452ff060b773b213ec1fc353426174068edfc3971a0b6bd"); - header.parent_hash = B256::ZERO; - block.header = header.seal_slow(); - // block changes let account1: Address = [0x60; 20].into(); let account2: Address = [0x61; 20].into(); - let slot: B256 = B256::with_last_byte(5); + let slot = U256::from(5); + let info = AccountInfo { nonce: 1, balance: U256::from(10), ..Default::default() }; - let bundle = BundleStateWithReceipts::new_init( - HashMap::from([ - ( - account1, - ( - None, - Some(Account { nonce: 1, balance: U256::from(10), bytecode_hash: None }), - HashMap::from([(slot, (U256::from(0), U256::from(10)))]), - ), - ), - ( - account2, - ( - None, - Some(Account { nonce: 1, balance: U256::from(10), bytecode_hash: None }), - HashMap::from([]), - ), - ), - ]), - HashMap::from([( - number, - HashMap::from([ - (account1, (Some(None), vec![StorageEntry::new(slot, U256::from(0))])), - (account2, (Some(None), vec![])), - ]), - )]), - vec![], + let bundle = BundleStateWithReceipts::new( + BundleState::builder(number..=number) + .state_present_account_info(account1, info.clone()) + .revert_account_info(number, account1, Some(None)) + .state_present_account_info(account2, info) + .revert_account_info(number, account2, Some(None)) + .state_storage(account1, HashMap::from([(slot, (U256::ZERO, U256::from(10)))])) + .build(), Receipts::from_vec(vec![vec![Some(Receipt { tx_type: TxType::EIP2930, success: true, @@ -145,6 +145,20 @@ fn block1(number: BlockNumber) -> (SealedBlockWithSenders, BundleStateWithReceip number, ); + let state_root = bundle_state_root(&bundle); + assert_eq!( + state_root, + b256!("5d035ccb3e75a9057452ff060b773b213ec1fc353426174068edfc3971a0b6bd") + ); + + let mut block = SealedBlock::decode(&mut BLOCK_RLP.as_slice()).unwrap(); + block.withdrawals = Some(vec![Withdrawal::default()]); + let mut header = block.header.clone().unseal(); + header.number = number; + header.state_root = state_root; + header.parent_hash = B256::ZERO; + block.header = header.seal_slow(); + (SealedBlockWithSenders { block, senders: vec![Address::new([0x30; 20])] }, bundle) } @@ -152,41 +166,26 @@ fn block1(number: BlockNumber) -> (SealedBlockWithSenders, BundleStateWithReceip fn block2( number: BlockNumber, parent_hash: B256, + prev_state: &BundleStateWithReceipts, ) -> (SealedBlockWithSenders, BundleStateWithReceipts) { - let mut block_rlp = hex!("f9025ff901f7a0c86e8cc0310ae7c531c758678ddbfd16fc51c8cef8cec650b032de9869e8b94fa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942adc25665018aa1fe0e6bc666dac8fc2697ff9baa050554882fbbda2c2fd93fdc466db9946ea262a67f7a76cc169e714f105ab583da00967f09ef1dfed20c0eacfaa94d5cd4002eda3242ac47eae68972d07b106d192a0e3c8b47fbfc94667ef4cceb17e5cc21e3b1eebd442cebb27f07562b33836290db90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001830f42408238108203e800a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f862f860800a83061a8094095e7baea6a6c7c4c2dfeb977efac326af552d8780801ba072ed817487b84ba367d15d2f039b5fc5f087d0a8882fbdf73e8cb49357e1ce30a0403d800545b8fc544f92ce8124e2255f8c3c6af93f28243a120585d4c4c6a2a3c0").as_slice(); - let mut block = SealedBlock::decode(&mut block_rlp).unwrap(); - block.withdrawals = Some(vec![Withdrawal::default()]); - let mut header = block.header.clone().unseal(); - header.number = number; - header.state_root = b256!("90101a13dd059fa5cca99ed93d1dc23657f63626c5b8f993a2ccbdf7446b64f8"); - // parent_hash points to block1 hash - header.parent_hash = parent_hash; - block.header = header.seal_slow(); - // block changes let account: Address = [0x60; 20].into(); - let slot: B256 = B256::with_last_byte(5); + let slot = U256::from(5); - let bundle = BundleStateWithReceipts::new_init( - HashMap::from([( - account, - ( - None, - Some(Account { nonce: 3, balance: U256::from(20), bytecode_hash: None }), - HashMap::from([(slot, (U256::from(0), U256::from(15)))]), - ), - )]), - HashMap::from([( - number, - HashMap::from([( + let bundle = BundleStateWithReceipts::new( + BundleState::builder(number..=number) + .state_present_account_info( account, - ( - Some(Some(Account { nonce: 1, balance: U256::from(10), bytecode_hash: None })), - vec![StorageEntry::new(slot, U256::from(10))], - ), - )]), - )]), - vec![], + AccountInfo { nonce: 3, balance: U256::from(20), ..Default::default() }, + ) + .state_storage(account, HashMap::from([(slot, (U256::ZERO, U256::from(15)))])) + .revert_account_info( + number, + account, + Some(Some(AccountInfo { nonce: 1, balance: U256::from(10), ..Default::default() })), + ) + .revert_storage(number, account, Vec::from([(slot, U256::from(10))])) + .build(), Receipts::from_vec(vec![vec![Some(Receipt { tx_type: TxType::EIP1559, success: false, @@ -203,5 +202,23 @@ fn block2( })]]), number, ); + + let mut extended = prev_state.clone(); + extended.extend(bundle.clone()); + let state_root = bundle_state_root(&extended); + assert_eq!( + state_root, + b256!("90101a13dd059fa5cca99ed93d1dc23657f63626c5b8f993a2ccbdf7446b64f8") + ); + + let mut block = SealedBlock::decode(&mut BLOCK_RLP.as_slice()).unwrap(); + block.withdrawals = Some(vec![Withdrawal::default()]); + let mut header = block.header.clone().unseal(); + header.number = number; + header.state_root = state_root; + // parent_hash points to block1 hash + header.parent_hash = parent_hash; + block.header = header.seal_slow(); + (SealedBlockWithSenders { block, senders: vec![Address::new([0x31; 20])] }, bundle) }