diff --git a/radix-engine-stores/src/rocks_db_with_merkle_tree/mod.rs b/radix-engine-stores/src/rocks_db_with_merkle_tree/mod.rs index 3b00d11f1aa..0b3acc10997 100644 --- a/radix-engine-stores/src/rocks_db_with_merkle_tree/mod.rs +++ b/radix-engine-stores/src/rocks_db_with_merkle_tree/mod.rs @@ -16,7 +16,7 @@ use std::path::PathBuf; mod state_tree; use crate::rocks_db::{decode_from_rocksdb_bytes, encode_to_rocksdb_bytes}; -use state_tree::*; +pub use state_tree::*; const META_CF: &str = "meta"; const SUBSTATES_CF: &str = "substates"; diff --git a/simulator/src/replay/cmd_alloc_dump.rs b/simulator/src/replay/cmd_alloc_dump.rs index 277a640aaf5..040216119fd 100644 --- a/simulator/src/replay/cmd_alloc_dump.rs +++ b/simulator/src/replay/cmd_alloc_dump.rs @@ -50,6 +50,10 @@ pub struct TxnAllocDump { /// Include round update type of transactions in output data #[clap(short = 'r', long)] pub include_round_update_transaction: bool, + + /// Trace transaction execution + #[clap(long)] + pub trace: bool, } impl TxnAllocDump { @@ -116,6 +120,7 @@ impl TxnAllocDump { self.include_generic_transaction, self.include_round_update_transaction, ); + let trace = self.trace; let txn_write_thread_handle = thread::spawn(move || { let scrypto_vm = ScryptoVm::::default(); let iter = rx.iter(); @@ -130,6 +135,7 @@ impl TxnAllocDump { &scrypto_vm, &network, &prepared, + trace, ); let (heap_allocations_sum, heap_current_level, heap_peak_memory) = diff --git a/simulator/src/replay/cmd_execute.rs b/simulator/src/replay/cmd_execute.rs index 74fe7860aea..46a70902526 100644 --- a/simulator/src/replay/cmd_execute.rs +++ b/simulator/src/replay/cmd_execute.rs @@ -31,6 +31,10 @@ pub struct TxnExecute { /// The max version to execute #[clap(short, long)] pub max_version: Option, + + /// Trace transaction execution + #[clap(long)] + pub trace: bool, } impl TxnExecute { @@ -69,12 +73,18 @@ impl TxnExecute { // txn executor let mut database = RocksDBWithMerkleTreeSubstateStore::standard(self.database_dir.clone()); + let trace = self.trace; let txn_write_thread_handle = thread::spawn(move || { let scrypto_vm = ScryptoVm::::default(); let iter = rx.iter(); for tx_payload in iter { - let state_updates = - execute_ledger_transaction(&database, &scrypto_vm, &network, &tx_payload); + let state_updates = execute_ledger_transaction( + &database, + &scrypto_vm, + &network, + &tx_payload, + trace, + ); let database_updates = state_updates.create_database_updates::(); database.commit(&database_updates); diff --git a/simulator/src/replay/cmd_execute_in_memory.rs b/simulator/src/replay/cmd_execute_in_memory.rs index 1f8d35de48c..ab094cbb260 100644 --- a/simulator/src/replay/cmd_execute_in_memory.rs +++ b/simulator/src/replay/cmd_execute_in_memory.rs @@ -34,6 +34,10 @@ pub struct TxnExecuteInMemory { /// State hash breakpoints, in format of comma separated `:` #[clap(short, long)] pub breakpoints: Option, + + /// Trace transaction execution + #[clap(long)] + pub trace: bool, } impl TxnExecuteInMemory { @@ -81,12 +85,18 @@ impl TxnExecuteInMemory { // txn executor let substate_database = InMemorySubstateDatabase::standard(); let mut database = HashTreeUpdatingDatabase::new(substate_database); + let trace = self.trace; let txn_write_thread_handle = thread::spawn(move || { let scrypto_vm = ScryptoVm::::default(); let iter = rx.iter(); for tx_payload in iter { - let state_updates = - execute_ledger_transaction(&database, &scrypto_vm, &network, &tx_payload); + let state_updates = execute_ledger_transaction( + &database, + &scrypto_vm, + &network, + &tx_payload, + trace, + ); let database_updates = state_updates.create_database_updates::(); database.commit(&database_updates); diff --git a/simulator/src/replay/cmd_measure.rs b/simulator/src/replay/cmd_measure.rs index 46fec6d318a..21c9333da87 100644 --- a/simulator/src/replay/cmd_measure.rs +++ b/simulator/src/replay/cmd_measure.rs @@ -38,6 +38,10 @@ pub struct TxnMeasure { /// The max version to execute #[clap(short, long)] pub max_version: Option, + + /// Trace transaction execution + #[clap(long)] + pub trace: bool, } impl TxnMeasure { @@ -91,6 +95,7 @@ impl TxnMeasure { .map_err(Error::IOError)?; } + let trace = self.trace; let txn_write_thread_handle = thread::spawn(move || { let scrypto_vm = ScryptoVm::::default(); let iter = rx.iter(); @@ -102,6 +107,7 @@ impl TxnMeasure { &scrypto_vm, &network, &prepared, + trace, ); let execution_cost_units = receipt .fee_summary() diff --git a/simulator/src/replay/cmd_sync.rs b/simulator/src/replay/cmd_sync.rs index a302c1d3991..fd4d52a5a82 100644 --- a/simulator/src/replay/cmd_sync.rs +++ b/simulator/src/replay/cmd_sync.rs @@ -33,6 +33,10 @@ pub struct TxnSync { /// The max version to execute #[clap(short, long)] pub max_version: Option, + + /// Trace transaction execution + #[clap(long)] + pub trace: bool, } impl TxnSync { @@ -62,25 +66,37 @@ impl TxnSync { // txn executor let mut database = RocksDBWithMerkleTreeSubstateStore::standard(self.database_dir.clone()); + let trace = self.trace; let txn_write_thread_handle = thread::spawn(move || { let scrypto_vm = ScryptoVm::::default(); let iter = rx.iter(); for (tx_payload, expected_state_root_hash) in iter { - let state_updates = - execute_ledger_transaction(&database, &scrypto_vm, &network, &tx_payload); + let state_updates = execute_ledger_transaction( + &database, + &scrypto_vm, + &network, + &tx_payload, + trace, + ); let database_updates = state_updates.create_database_updates::(); - database.commit(&database_updates); - - let new_state_root_hash = database.get_current_root_hash(); - let new_version = database.get_current_version(); + let current_version = database.get_current_version(); + let new_version = current_version + 1; + // TODO: avoid redundant computation? + let (_, new_state_root_hash) = + radix_engine_stores::rocks_db_with_merkle_tree::compute_state_tree_update( + &database, + current_version, + &database_updates, + ); if new_state_root_hash != expected_state_root_hash { panic!( "State hash mismatch at version {}. Expected {} Actual {}", new_version, expected_state_root_hash, new_state_root_hash ); } + database.commit(&database_updates); // print progress if new_version < 1000 || new_version % 1000 == 0 { diff --git a/simulator/src/replay/ledger_transaction_execution.rs b/simulator/src/replay/ledger_transaction_execution.rs index 86a3c64ad58..17465b9838b 100644 --- a/simulator/src/replay/ledger_transaction_execution.rs +++ b/simulator/src/replay/ledger_transaction_execution.rs @@ -43,9 +43,10 @@ pub fn execute_ledger_transaction( scrypto_vm: &ScryptoVm, network: &NetworkDefinition, tx_payload: &[u8], + trace: bool, ) -> StateUpdates { let prepared = prepare_ledger_transaction(tx_payload); - execute_prepared_ledger_transaction(database, scrypto_vm, network, &prepared) + execute_prepared_ledger_transaction(database, scrypto_vm, network, &prepared, trace) .into_state_updates() } @@ -63,6 +64,7 @@ pub fn execute_prepared_ledger_transaction( scrypto_vm: &ScryptoVm, network: &NetworkDefinition, prepared: &PreparedLedgerTransaction, + trace: bool, ) -> LedgerTransactionReceipt { match &prepared.inner { PreparedLedgerTransactionInner::Genesis(prepared_genesis_tx) => { @@ -79,7 +81,9 @@ pub fn execute_prepared_ledger_transaction( native_vm: DefaultNativeVm::new(), }, &CostingParameters::default(), - &ExecutionConfig::for_genesis_transaction(network.clone()), + &ExecutionConfig::for_genesis_transaction(network.clone()) + .with_kernel_trace(trace) + .with_cost_breakdown(trace), &tx.get_executable(btreeset!(AuthAddresses::system_role())), ); LedgerTransactionReceipt::Standard(receipt) @@ -94,7 +98,9 @@ pub fn execute_prepared_ledger_transaction( native_vm: DefaultNativeVm::new(), }, &CostingParameters::default(), - &ExecutionConfig::for_notarized_transaction(network.clone()), + &ExecutionConfig::for_notarized_transaction(network.clone()) + .with_kernel_trace(trace) + .with_cost_breakdown(trace), &NotarizedTransactionValidator::new(ValidationConfig::default(network.id)) .validate(tx.as_ref().clone()) .expect("Transaction validation failure") @@ -110,7 +116,9 @@ pub fn execute_prepared_ledger_transaction( native_vm: DefaultNativeVm::new(), }, &CostingParameters::default(), - &ExecutionConfig::for_system_transaction(network.clone()), + &ExecutionConfig::for_system_transaction(network.clone()) + .with_kernel_trace(trace) + .with_cost_breakdown(trace), &tx.get_executable(), ); LedgerTransactionReceipt::Standard(receipt)