diff --git a/packages/evm/core/src/account.rs b/packages/evm/core/src/account.rs index 785492c36..5ef65dca1 100644 --- a/packages/evm/core/src/account.rs +++ b/packages/evm/core/src/account.rs @@ -53,3 +53,60 @@ impl From for AccountInfo { } } } + +#[cfg(test)] +mod tests { + use crate::{account::AccountInfoExtended, legacy::LegacyAccountAttributes}; + use alloy_primitives::{U256, address, b256}; + use revm::state::AccountInfo; + + #[test] + fn test_account_info_parts() { + let info = AccountInfo { + balance: U256::ONE, + nonce: 1, + code_hash: b256!("0000000000000000000000000000000000000000000000000000000000000001"), + account_id: None, + code: None, + }; + + let attributes = LegacyAccountAttributes { + legacy_nonce: Some(0), + second_public_key: Some("key".into()), + multi_signature: None, + }; + + let account_info = AccountInfoExtended { + address: address!("0000000000000000000000000000000000000001"), + info: info.clone(), + legacy_attributes: attributes.clone(), + }; + + let (address, info_part, legacy_attributes) = account_info.into_parts(); + + assert_eq!( + address, + address!("0000000000000000000000000000000000000001") + ); + assert_eq!(info, info_part); + assert_eq!(legacy_attributes, Some(attributes)); + + let account_info = AccountInfoExtended { + address: address!("0000000000000000000000000000000000000001"), + info: info.clone(), + legacy_attributes: LegacyAccountAttributes { + legacy_nonce: None, + second_public_key: None, + multi_signature: None, + }, + }; + + let (address, info_part, legacy_attributes) = account_info.into_parts(); + assert_eq!( + address, + address!("0000000000000000000000000000000000000001") + ); + assert_eq!(info, info_part); + assert_eq!(legacy_attributes, None); + } +} diff --git a/packages/evm/core/src/bytecode.rs b/packages/evm/core/src/bytecode.rs index b994e633e..164beafb9 100644 --- a/packages/evm/core/src/bytecode.rs +++ b/packages/evm/core/src/bytecode.rs @@ -22,3 +22,18 @@ impl TryFrom for Bytecode { Bytecode::new_raw_checked(stored.raw) } } + +#[cfg(test)] +mod tests { + use crate::bytecode::StoredBytecode; + use alloy_primitives::Bytes; + use revm::state::Bytecode; + + #[test] + fn test_bytecode() { + let raw_bytecode = Bytecode::new_raw(Bytes::from_static(&[1, 2, 3, 4])); + let stored = StoredBytecode::from(raw_bytecode); + + assert_eq!(stored.raw, Bytes::from_static(&[1, 2, 3, 4])); + } +} diff --git a/packages/evm/core/src/db.rs b/packages/evm/core/src/db.rs index d4b611eb0..96c56ee5b 100644 --- a/packages/evm/core/src/db.rs +++ b/packages/evm/core/src/db.rs @@ -1286,6 +1286,21 @@ fn test_open_db() { assert!(PersistentDB::new(PersistentDBOptions::new(tmp.path().to_path_buf())).is_ok()); } +#[test] +fn test_open_db_with_logger() { + let tmp = tempfile::Builder::new() + .prefix("evm.mdb") + .tempdir() + .unwrap(); + + assert!( + PersistentDB::new( + PersistentDBOptions::new(tmp.path().to_path_buf()).with_logger(Logger::new(None)) + ) + .is_ok() + ); +} + #[test] fn test_commit_changes() { let path = tempfile::Builder::new() @@ -1708,88 +1723,181 @@ fn test_read_accounts() { assert_eq!(read, addresses.len()); } -#[test] -fn test_read_receipts() { - let path = tempfile::Builder::new() - .prefix("evm.mdb") - .tempdir() - .unwrap(); +#[cfg(test)] +mod tests { + use crate::{ + compression::CompressedBincode, + db::{ + CommitKey, CommitReceipts, LegacyAddressWrapper, PendingCommit, PersistentDB, + PersistentDBOptions, StaticStringWrapper, StringWrapper, + }, + legacy::{LegacyAccountAttributes, LegacyAddress}, + receipt::TxReceipt, + }; + use alloy_primitives::{B256, U256, address, b256}; + use revm::{primitives::HashMap, state::AccountInfo}; - let db = - PersistentDB::new(PersistentDBOptions::new(path.path().to_path_buf())).expect("database"); + use heed::{BytesDecode, BytesEncode}; - let target_block = 100; - let mut total_receipts = 0; + #[test] + fn test_legacy_address_wrapper() { + let legacy_address: LegacyAddress = + "DJmvhhiQFSrEQCq9FUxvcLcpcBjx7K3yLt".try_into().unwrap(); - { - let mut wtxn = db.env.write_txn().unwrap(); + let wrapper = LegacyAddressWrapper(legacy_address); + let serialized = ::bytes_encode(&wrapper).expect("ok"); - fn random_b256(seed: u64, offset: u64) -> B256 { - use std::collections::hash_map::DefaultHasher; - use std::hash::{Hash, Hasher}; - let mut hasher = DefaultHasher::new(); - seed.hash(&mut hasher); + let deserialized = + ::bytes_decode(&serialized).expect("ok"); + assert_eq!(legacy_address, deserialized.0); + } - B256::from(U256::from(hasher.finish() + offset)) - } + #[test] + fn test_string_wrapper() { + let string = "test".to_owned(); - for i in 0..target_block { - let block_number = (i + 1) as u64; + let wrapper = StringWrapper(string); + let serialized = ::bytes_encode(&wrapper).expect("ok"); + let deserialized = ::bytes_decode(&serialized).expect("ok"); - let receipts: HashMap = [ - (random_b256(block_number, 0), TxReceipt::default()), - (random_b256(block_number, 1), TxReceipt::default()), - (random_b256(block_number, 2), TxReceipt::default()), - (random_b256(block_number, 3), TxReceipt::default()), - ] - .into_iter() - .collect(); + assert_eq!("test", deserialized.0); + } - total_receipts += receipts.len(); + #[test] + fn test_static_string_wrapper() { + let string = "test"; - db.inner - .borrow_mut() - .commits - .put( - &mut wtxn, - &block_number, - &CompressedBincode(&CommitReceipts { - tx_receipts: receipts, - ..Default::default() - }), - ) - .unwrap(); - } - wtxn.commit().unwrap(); + let wrapper = StaticStringWrapper(string); + let serialized = ::bytes_encode(&wrapper).expect("ok"); + + assert_eq!(serialized, &b"test"[..]); } - const LIMIT: u64 = 7; - let mut offset = 0; + #[test] + fn test_commit_key() { + let key = CommitKey(0, 0, B256::ZERO); + let mut pending = PendingCommit::new(key); + + let info = AccountInfo { + balance: U256::ONE, + nonce: 1, + code_hash: b256!("0000000000000000000000000000000000000000000000000000000000000001"), + account_id: None, + code: None, + }; - let mut read_block_number = 0; - let mut read_receipts = 0; + let attributes = LegacyAccountAttributes { + legacy_nonce: Some(0), + second_public_key: Some("key".into()), + multi_signature: None, + }; - loop { - let (next, items) = db.get_receipts(offset, LIMIT).unwrap(); - for (block_number, receipts) in items { - read_block_number = block_number; - read_receipts += receipts.len(); - } + pending.import_account( + address!("0000000000000000000000000000000000000001"), + info, + Some(attributes), + ); - if next.is_none() { - break; + let info = AccountInfo { + balance: U256::ZERO, + nonce: 0, + code_hash: B256::ZERO, + account_id: None, + code: None, + }; + pending.import_account( + address!("0000000000000000000000000000000000000002"), + info, + None, + ); + + assert_eq!(pending.transitions.transitions.len(), 2); + assert_eq!(pending.legacy_attributes.len(), 1); + } + + #[test] + fn test_read_receipts() { + let path = tempfile::Builder::new() + .prefix("evm.mdb") + .tempdir() + .unwrap(); + + let db = PersistentDB::new(PersistentDBOptions::new(path.path().to_path_buf())) + .expect("database"); + + let target_block = 100; + let mut total_receipts = 0; + + { + let mut wtxn = db.env.write_txn().unwrap(); + + fn random_b256(seed: u64, offset: u64) -> B256 { + use std::collections::hash_map::DefaultHasher; + use std::hash::{Hash, Hasher}; + let mut hasher = DefaultHasher::new(); + seed.hash(&mut hasher); + + B256::from(U256::from(hasher.finish() + offset)) + } + + for i in 0..target_block { + let block_number = (i + 1) as u64; + + let receipts: HashMap = [ + (random_b256(block_number, 0), TxReceipt::default()), + (random_b256(block_number, 1), TxReceipt::default()), + (random_b256(block_number, 2), TxReceipt::default()), + (random_b256(block_number, 3), TxReceipt::default()), + ] + .into_iter() + .collect(); + + total_receipts += receipts.len(); + + db.inner + .borrow_mut() + .commits + .put( + &mut wtxn, + &block_number, + &CompressedBincode(&CommitReceipts { + tx_receipts: receipts, + ..Default::default() + }), + ) + .unwrap(); + } + wtxn.commit().unwrap(); } - match next { - Some(next) => { - offset = next; + const LIMIT: u64 = 7; + let mut offset = 0; + + let mut read_block_number = 0; + let mut read_receipts = 0; + + loop { + let (next, items) = db.get_receipts(offset, LIMIT).unwrap(); + for (block_number, receipts) in items { + read_block_number = block_number; + read_receipts += receipts.len(); } - None => { + + if next.is_none() { break; } + + match next { + Some(next) => { + offset = next; + } + None => { + break; + } + } } - } - assert_eq!(read_block_number, target_block); - assert_eq!(read_receipts, total_receipts); + assert_eq!(read_block_number, target_block); + assert_eq!(read_receipts, total_receipts); + } } diff --git a/packages/evm/core/src/logger.rs b/packages/evm/core/src/logger.rs index aeb149edb..fe4cf61fd 100644 --- a/packages/evm/core/src/logger.rs +++ b/packages/evm/core/src/logger.rs @@ -46,3 +46,53 @@ impl std::fmt::Display for LogLevel { write!(f, "{}", uppercase) } } + +#[cfg(test)] +mod tests { + use std::{sync::mpsc::channel, time::Duration}; + + use crate::logger::{LogLevel, Logger}; + + #[test] + fn test_logger_sends_log_message_through_channel() { + let (tx, rx) = channel(); + let logger = Logger::new(Some(tx)); + + logger.log(LogLevel::Info, "hello world".to_string()); + + let (level, message) = rx.recv_timeout(Duration::from_millis(100)).unwrap(); + assert_eq!(level.to_string(), "INFO"); + assert_eq!(message, "hello world"); + } + + #[test] + fn test_logger_without_sender_does_not_panic() { + let logger = Logger::new(None); + + logger.log(LogLevel::Warn, "printed to stdout".to_string()); + } + + #[test] + fn test_logger_with_disconnected_channel_does_not_panic() { + let (tx, rx) = channel(); + drop(rx); + + let logger = Logger::new(Some(tx)); + logger.log(LogLevel::Alert, "this will fail to send".to_string()); + } + + #[test] + fn test_log_level_display_format() { + let cases = [ + (LogLevel::Info, "INFO"), + (LogLevel::Debug, "DEBUG"), + (LogLevel::Notice, "NOTICE"), + (LogLevel::Alert, "ALERT"), + (LogLevel::Warn, "WARN"), + ]; + + for (level, expected) in cases { + assert_eq!(level.to_string(), expected); + } + } +} diff --git a/packages/evm/core/src/receipt.rs b/packages/evm/core/src/receipt.rs index 437529586..67f4f0964 100644 --- a/packages/evm/core/src/receipt.rs +++ b/packages/evm/core/src/receipt.rs @@ -59,3 +59,95 @@ pub fn map_execution_result(result: ExecutionResult, cumulative_gas_used: u64) - }, } } + +#[cfg(test)] +mod tests { + use crate::receipt::map_execution_result; + use alloy_primitives::address; + use bytes::Bytes; + use revm::context::result::{ExecutionResult, HaltReason, Output, ResultGas, SuccessReason}; + + #[test] + fn test_map_execution_result_call() { + let result = ExecutionResult::Success { + reason: SuccessReason::Stop, + gas: ResultGas::new(30000, 25000, 2100, 0, 0), + logs: vec![], + output: Output::Call(alloy_primitives::Bytes(Bytes::new())), + }; + + let output = map_execution_result(result, 0); + + assert_eq!(output.contract_address, None); + assert_eq!(output.gas_used, 22900); + assert_eq!(output.cumulative_gas_used, 0); + assert_eq!(output.gas_refunded, 2100); + assert_eq!(output.logs, Some(vec![])); + assert_eq!(output.output, Some(alloy_primitives::Bytes(Bytes::new()))); + assert_eq!(output.success, 1); + } + + #[test] + fn test_map_execution_result_create() { + let result = ExecutionResult::Success { + reason: SuccessReason::Stop, + gas: ResultGas::new(1_000_000, 355_000, 0, 0, 0), + logs: vec![], + output: Output::Create( + alloy_primitives::Bytes(Bytes::new()), + Some(address!("0000000000000000000000000000000000000001")), + ), + }; + + let output = map_execution_result(result, 0); + + assert_eq!( + output.contract_address, + Some(address!("0000000000000000000000000000000000000001").to_string()) + ); + assert_eq!(output.gas_used, 355_000); + assert_eq!(output.cumulative_gas_used, 0); + assert_eq!(output.gas_refunded, 0); + assert_eq!(output.logs, Some(vec![])); + assert_eq!(output.output, Some(alloy_primitives::Bytes(Bytes::new()))); + assert_eq!(output.success, 1); + } + + #[test] + fn test_map_execution_result_revert() { + let result = ExecutionResult::Revert { + gas: ResultGas::new(30000, 30000, 0, 0, 0), + logs: vec![], + output: alloy_primitives::Bytes(Bytes::new()), + }; + + let output = map_execution_result(result, 0); + + assert_eq!(output.contract_address, None); + assert_eq!(output.gas_used, 30000); + assert_eq!(output.cumulative_gas_used, 0); + assert_eq!(output.gas_refunded, 0); + assert_eq!(output.logs, None); + assert_eq!(output.output, Some(alloy_primitives::Bytes(Bytes::new()))); + assert_eq!(output.success, 0); + } + + #[test] + fn test_map_execution_result_halt() { + let result = ExecutionResult::Halt { + reason: HaltReason::StackOverflow, + gas: ResultGas::new(30000, 30000, 0, 0, 0), + logs: vec![], + }; + + let output = map_execution_result(result, 0); + + assert_eq!(output.contract_address, None); + assert_eq!(output.gas_used, 30000); + assert_eq!(output.cumulative_gas_used, 0); + assert_eq!(output.gas_refunded, 0); + assert_eq!(output.logs, None); + assert_eq!(output.output, None); + assert_eq!(output.success, 0); + } +} diff --git a/packages/evm/core/src/state_changes.rs b/packages/evm/core/src/state_changes.rs index 2e25450f6..3b7d25882 100644 --- a/packages/evm/core/src/state_changes.rs +++ b/packages/evm/core/src/state_changes.rs @@ -37,7 +37,7 @@ pub struct StorageChangeset { pub storage: Vec<(U256, StorageSlot)>, } -#[derive(Default, Debug)] +#[derive(Default, Debug, PartialEq, Eq)] pub struct AccountUpdate { pub address: Address, pub balance: U256, @@ -54,7 +54,7 @@ pub struct AccountUpdate { pub merge_info: Option, } -#[derive(Default, Debug)] +#[derive(Default, Debug, PartialEq, Eq)] pub struct AccountMergeInfo { pub legacy_address: LegacyAddress, pub transaction_hash: B256, diff --git a/packages/evm/core/src/state_commit.rs b/packages/evm/core/src/state_commit.rs index e951f43e4..294639770 100644 --- a/packages/evm/core/src/state_commit.rs +++ b/packages/evm/core/src/state_commit.rs @@ -152,7 +152,7 @@ fn collect_dirty_accounts( Some(account) }); - break; + continue; } // Attempt to decode the log as a Unvoted event @@ -168,7 +168,7 @@ fn collect_dirty_accounts( Some(account) }); - break; + continue; } } _ if log.address == info.username_contract => { @@ -181,7 +181,7 @@ fn collect_dirty_accounts( account.username_resigned = false; // cancel out any previous resignation if one happened in same commit Some(account) }); - break; + continue; } // Attempt to decode log as a UsernameResigned event @@ -192,7 +192,7 @@ fn collect_dirty_accounts( account.username_resigned = true; Some(account) }); - break; + continue; } } _ => (), // ignore @@ -209,64 +209,276 @@ fn collect_dirty_accounts( dirty_accounts.into_values().collect() } -#[test] -fn test_apply_rewards() { - let path = tempfile::Builder::new() - .prefix("evm.mdb") - .tempdir() - .unwrap(); - - let mut db = PersistentDB::new(crate::db::PersistentDBOptions::new( - path.path().to_path_buf(), - )) - .expect("database"); - let mut pending = PendingCommit::default(); - - let account1 = revm::primitives::address!("bd6f65c58a46427af4b257cbe231d0ed69ed5508"); - let account2 = revm::primitives::address!("ad6f65c58a46427af4b257cbe231d0ed69ed5508"); - - let mut rewards = HashMap::::default(); - rewards.insert(account1, 1234); - rewards.insert(account2, 0); - - let result = self::apply_rewards(&mut db, &mut pending, rewards); - assert!(result.is_ok()); - - let cache_account1 = pending.cache.accounts.get(&account1).expect("account1"); - assert!(cache_account1.account.is_some()); - assert_eq!( - cache_account1.status, - revm::database::AccountStatus::InMemoryChange - ); - - let cache_account2 = pending.cache.accounts.get(&account2).expect("account2"); - assert!(cache_account2.account.is_none()); - assert_eq!( - cache_account2.status, - revm::database::AccountStatus::Destroyed - ); - - let transition_account1 = pending - .transitions - .transitions - .get(&account1) - .expect("transition_account1"); - assert!(transition_account1.info.is_some()); - assert_eq!( - transition_account1.status, - revm::database::AccountStatus::InMemoryChange - ); - assert_eq!(transition_account1.storage_was_destroyed, false); - - let transition_account2 = pending - .transitions - .transitions - .get(&account2) - .expect("transition_account2"); - assert!(transition_account2.info.is_none()); - assert_eq!( - transition_account2.status, - revm::database::AccountStatus::Destroyed - ); - assert_eq!(transition_account2.storage_was_destroyed, true); +#[cfg(test)] +mod tests { + use std::collections::BTreeMap; + + use crate::{ + db::{GenesisInfo, PendingCommit, PersistentDB}, + events, + state_changes::{AccountMergeInfo, AccountUpdate, StateChangeset}, + state_commit::{StateCommit, apply_rewards, collect_dirty_accounts}, + }; + use crate::{ + legacy::{LegacyAccountAttributes, LegacyAddress}, + state_changes::StorageChangeset, + }; + use alloy_primitives::{Address, Log, U256, address}; + use alloy_primitives::{B256, b256}; + use alloy_sol_types::SolEvent; + use bytes::Bytes; + use revm::{ + context::result::{ExecutionResult, Output, ResultGas, SuccessReason}, + primitives::HashMap, + }; + use revm::{database::states::StorageSlot, state::AccountInfo}; + + #[test] + fn test_collect_dirty_accounts() { + let mut change_set = StateChangeset::default(); + change_set.accounts.push(( + address!("0000000000000000000000000000000000000001"), + Some(AccountInfo::from_balance(U256::from(1))), + )); + change_set.accounts.push(( + address!("0000000000000000000000000000000000000002"), + Some(AccountInfo::from_balance(U256::from(1))), + )); + + let genesis_info = GenesisInfo { + account: address!("0000000000000000000000000000000000000001"), + deployer_account: address!("0000000000000000000000000000000000000002"), + validator_contract: address!("0000000000000000000000000000000000000003"), + username_contract: address!("0000000000000000000000000000000000000004"), + initial_block_number: 0, + initial_supply: U256::from(1_000_000), + }; + + let storage = vec![ + ( + U256::from(1), + StorageSlot::new_changed(U256::ZERO, U256::from(1234)), + ), + ( + U256::from(2), + StorageSlot::new_changed(U256::ZERO, U256::from(5678)), + ), + ]; + + change_set.storage.push(StorageChangeset { + address: address!("0000000000000000000000000000000000000002"), + storage, + ..Default::default() + }); + + change_set.legacy_attributes.insert( + address!("0000000000000000000000000000000000000001"), + LegacyAccountAttributes { + legacy_nonce: Some(5), + second_public_key: Some("".into()), + ..Default::default() + }, + ); + + let legacy_address: LegacyAddress = + "DJmvhhiQFSrEQCq9FUxvcLcpcBjx7K3yLt".try_into().unwrap(); + change_set.legacy_cold_wallets.insert( + legacy_address.clone(), + crate::legacy::LegacyColdWallet { + address: legacy_address.clone(), + balance: U256::from(255), + legacy_attributes: LegacyAccountAttributes { + legacy_nonce: Some(3), + ..Default::default() + }, + ..Default::default() + }, + ); + + change_set.merged_legacy_cold_wallets.insert( + address!("0000000000000000000000000000000000000001"), + ( + b256!("0000000000000000000000000000000000000000000000000000000000000001"), + legacy_address, + ), + ); + + let mut results = BTreeMap::::new(); + + results.insert( + b256!("0000000000000000000000000000000000000000000000000000000000000001"), + ( + ExecutionResult::Success { + reason: SuccessReason::Stop, + gas: ResultGas::new(30000, 30000, 0, 0, 0), + logs: vec![ + Log { + address: genesis_info.validator_contract, + data: events::Voted { + validator: address!("0000000000000000000000000000000000000002"), + voter: address!("0000000000000000000000000000000000000001"), + } + .encode_log_data(), + }, + Log { + address: genesis_info.validator_contract, + data: events::Unvoted { + validator: address!("0000000000000000000000000000000000000004"), + voter: address!("0000000000000000000000000000000000000002"), + } + .encode_log_data(), + }, + Log { + address: genesis_info.username_contract, + data: events::UsernameRegistered { + addr: address!("0000000000000000000000000000000000000001"), + username: "test".into(), + previousUsername: "".into(), + } + .encode_log_data(), + }, + Log { + address: genesis_info.username_contract, + data: events::UsernameResigned { + addr: address!("0000000000000000000000000000000000000002"), + username: "resigned".into(), + } + .encode_log_data(), + }, + Log { + address: genesis_info.validator_contract, + ..Default::default() + }, + Log { + address: genesis_info.username_contract, + ..Default::default() + }, + Log { + address: address!("0000000000000000000000000000000000000000"), + ..Default::default() + }, + ], + output: Output::Create( + alloy_primitives::Bytes(Bytes::new()), + Some(address!("0000000000000000000000000000000000000001")), + ), + }, + 0, + ), + ); + + results.insert( + b256!("0000000000000000000000000000000000000000000000000000000000000002"), + ( + ExecutionResult::Revert { + gas: ResultGas::new(30000, 30000, 0, 0, 0), + logs: vec![], + output: alloy_primitives::Bytes(Bytes::new()), + }, + 0, + ), + ); + + let state = StateCommit { + change_set, + results, + ..Default::default() + }; + + let mut account_updates = collect_dirty_accounts(state, &Some(genesis_info)); + account_updates.sort_by_key(|k| k.address); + + assert_eq!( + account_updates, + vec![ + AccountUpdate { + address: address!("0000000000000000000000000000000000000001"), + balance: U256::ONE, + nonce: 0, + vote: Some(address!("0000000000000000000000000000000000000002")), + unvote: None, + username: Some("test".into()), + username_resigned: false, + merge_info: Some(AccountMergeInfo { + legacy_address: "DJmvhhiQFSrEQCq9FUxvcLcpcBjx7K3yLt".try_into().unwrap(), + transaction_hash: b256!( + "0000000000000000000000000000000000000000000000000000000000000001" + ) + }) + }, + AccountUpdate { + address: address!("0000000000000000000000000000000000000002"), + balance: U256::ONE, + nonce: 0, + vote: None, + unvote: Some(address!("0000000000000000000000000000000000000004")), + username: None, + username_resigned: true, + merge_info: None + } + ] + ); + } + + #[test] + fn test_apply_rewards() { + let path = tempfile::Builder::new() + .prefix("evm.mdb") + .tempdir() + .unwrap(); + + let mut db = PersistentDB::new(crate::db::PersistentDBOptions::new( + path.path().to_path_buf(), + )) + .expect("database"); + let mut pending = PendingCommit::default(); + + let account1 = revm::primitives::address!("bd6f65c58a46427af4b257cbe231d0ed69ed5508"); + let account2 = revm::primitives::address!("ad6f65c58a46427af4b257cbe231d0ed69ed5508"); + + let mut rewards = HashMap::::default(); + rewards.insert(account1, 1234); + rewards.insert(account2, 0); + + let result = apply_rewards(&mut db, &mut pending, rewards); + assert!(result.is_ok()); + + let cache_account1 = pending.cache.accounts.get(&account1).expect("account1"); + assert!(cache_account1.account.is_some()); + assert_eq!( + cache_account1.status, + revm::database::AccountStatus::InMemoryChange + ); + + let cache_account2 = pending.cache.accounts.get(&account2).expect("account2"); + assert!(cache_account2.account.is_none()); + assert_eq!( + cache_account2.status, + revm::database::AccountStatus::Destroyed + ); + + let transition_account1 = pending + .transitions + .transitions + .get(&account1) + .expect("transition_account1"); + assert!(transition_account1.info.is_some()); + assert_eq!( + transition_account1.status, + revm::database::AccountStatus::InMemoryChange + ); + assert_eq!(transition_account1.storage_was_destroyed, false); + + let transition_account2 = pending + .transitions + .transitions + .get(&account2) + .expect("transition_account2"); + assert!(transition_account2.info.is_none()); + assert_eq!( + transition_account2.status, + revm::database::AccountStatus::Destroyed + ); + assert_eq!(transition_account2.storage_was_destroyed, true); + } } diff --git a/packages/evm/core/src/state_root.rs b/packages/evm/core/src/state_root.rs index 7fb1279ce..259518dc1 100644 --- a/packages/evm/core/src/state_root.rs +++ b/packages/evm/core/src/state_root.rs @@ -121,7 +121,8 @@ fn prepare(state: &mut StateCommit) { #[cfg(test)] mod tests { use crate::{ - db::{GenesisInfo, PersistentDB, PersistentDBOptions}, + db::{GenesisInfo, PendingCommit, PersistentDB, PersistentDBOptions}, + legacy::LegacyAddress, state_changes::StateChangeset, state_commit::{StateCommit, build_commit}, state_root::{calculate, calculate_state_root}, @@ -268,7 +269,17 @@ mod tests { ) ); - let mut pending_commit = Default::default(); + let mut pending_commit = PendingCommit::default(); + let legacy_address: LegacyAddress = + "DJmvhhiQFSrEQCq9FUxvcLcpcBjx7K3yLt".try_into().unwrap(); + pending_commit.merged_legacy_cold_wallets.insert( + address!("0000000000000000000000000000000000000001"), + Some(( + b256!("0000000000000000000000000000000000000000000000000000000000000001"), + legacy_address, + )), + ); + let state_commit = build_commit(&mut pending_commit).expect("ok"); pending_commit.built_commit = Some(state_commit); @@ -282,7 +293,7 @@ mod tests { assert_eq!( result, revm::primitives::b256!( - "8f8b7e90288fa24167aa9507f219efa7b6bde941ec68ef8a4b66a3a922a12afa" + "5ca756d93a56e6c15c9e182ff236bd5db21bcde81c2c438d58a32bbd16b4ec3a" ) ); }