From 056549263daaf004c0be23854ed1bbd7b1116434 Mon Sep 17 00:00:00 2001 From: Andrey Date: Mon, 18 Nov 2024 16:23:10 +0300 Subject: [PATCH] refactor: update memory tests, extend the main test --- miden-tx/src/testing/mock_host.rs | 6 +- miden-tx/src/testing/tx_context/mod.rs | 11 +- miden-tx/src/tests/kernel_tests/test_tx.rs | 144 +++++++++++++++------ 3 files changed, 117 insertions(+), 44 deletions(-) diff --git a/miden-tx/src/testing/mock_host.rs b/miden-tx/src/testing/mock_host.rs index 582d33a05..e4c7db542 100644 --- a/miden-tx/src/testing/mock_host.rs +++ b/miden-tx/src/testing/mock_host.rs @@ -2,6 +2,7 @@ // ================================================================================================ use alloc::{rc::Rc, string::ToString, sync::Arc}; +use std::vec::Vec; use miden_lib::transaction::TransactionEvent; use miden_objects::{ @@ -34,10 +35,11 @@ impl MockHost { account: AccountHeader, advice_inputs: AdviceInputs, mast_store: Rc, + mut foreign_code_commitments: Vec, ) -> Self { + foreign_code_commitments.push(account.code_commitment()); let adv_provider: MemAdviceProvider = advice_inputs.into(); - let proc_index_map = - AccountProcedureIndexMap::new([account.code_commitment()], &adv_provider); + let proc_index_map = AccountProcedureIndexMap::new(foreign_code_commitments, &adv_provider); Self { adv_provider, acct_procedure_index_map: proc_index_map.unwrap(), diff --git a/miden-tx/src/testing/tx_context/mod.rs b/miden-tx/src/testing/tx_context/mod.rs index 3611d42a1..85ab62fb7 100644 --- a/miden-tx/src/testing/tx_context/mod.rs +++ b/miden-tx/src/testing/tx_context/mod.rs @@ -73,9 +73,14 @@ impl TransactionContext { mast_store.load_transaction_code(&self.tx_inputs, &self.tx_args); - CodeExecutor::new(MockHost::new(self.tx_inputs.account().into(), advice_inputs, mast_store)) - .stack_inputs(stack_inputs) - .execute_program(program) + CodeExecutor::new(MockHost::new( + self.tx_inputs.account().into(), + advice_inputs, + mast_store, + self.foreign_codes.iter().map(|code| code.commitment()).collect(), + )) + .stack_inputs(stack_inputs) + .execute_program(program) } /// Executes the transaction through a [TransactionExecutor] diff --git a/miden-tx/src/tests/kernel_tests/test_tx.rs b/miden-tx/src/tests/kernel_tests/test_tx.rs index f33f93f80..81023d10a 100644 --- a/miden-tx/src/tests/kernel_tests/test_tx.rs +++ b/miden-tx/src/tests/kernel_tests/test_tx.rs @@ -16,12 +16,11 @@ use miden_objects::{ accounts::{ account_id::testing::{ ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN, ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_2, - ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_ON_CHAIN, }, - Account, AccountBuilder, AccountComponent, AccountId, AccountProcedureInfo, AccountStorage, + Account, AccountBuilder, AccountComponent, AccountProcedureInfo, AccountStorage, StorageSlot, }, - assets::{AssetVault, NonFungibleAsset}, + assets::NonFungibleAsset, notes::{ Note, NoteAssets, NoteExecutionHint, NoteInputs, NoteMetadata, NoteRecipient, NoteTag, NoteType, @@ -625,12 +624,46 @@ fn test_fpi_memory() { // Prepare the test data let storage_slots = vec![AccountStorage::mock_item_0().slot, AccountStorage::mock_item_2().slot]; + let foreign_account_code_source = " + use.miden::account + + export.get_item_foreign + # make this foreign procedure unique to make sure that we invoke the procedure of the + # foreign account, not the native one + push.1 drop + exec.account::get_item + + # truncate the stack + movup.6 movup.6 movup.6 drop drop drop + end + + export.get_map_item_foreign + # make this foreign procedure unique to make sure that we invoke the procedure of the + # foreign account, not the native one + push.2 drop + exec.account::get_map_item + end + "; + let foreign_account_component = AccountComponent::compile( + foreign_account_code_source, + TransactionKernel::testing_assembler(), + storage_slots.clone(), + ) + .unwrap() + .with_supports_all_types(); let (foreign_account, _) = AccountBuilder::new() + .init_seed(ChaCha20Rng::from_entropy().gen()) + .with_component(foreign_account_component) + .nonce(ONE) + .build_testing() + .unwrap(); + + let (native_account, _) = AccountBuilder::new() .init_seed(ChaCha20Rng::from_entropy().gen()) .with_component( AccountMockComponent::new_with_slots( TransactionKernel::testing_assembler(), - storage_slots.clone(), + vec![AccountStorage::mock_item_2().slot], ) .unwrap(), ) @@ -638,28 +671,22 @@ fn test_fpi_memory() { .build_testing() .unwrap(); - // We deliberately create a native account which has the same code as the foreign account to be - // able to use `TransactionContext` instead of `TransactionExecutor` -- it allows us to get the - // `process` of the transaction and check the state of the memory. - let native_account_id = - AccountId::try_from(ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_ON_CHAIN).unwrap(); - let native_account = Account::from_parts( - native_account_id, - AssetVault::mock(), - foreign_account.storage().clone(), - foreign_account.code().clone(), - ONE, - ); - let foreign_account_id = foreign_account.id(); let mut mock_chain = MockChain::with_accounts(&[native_account.clone(), foreign_account.clone()]); mock_chain.seal_block(None); let advice_inputs = get_mock_fpi_adv_inputs(&foreign_account, &mock_chain); + let tx_context = mock_chain + .build_tx_context(native_account.id(), &[], &[]) + .foreign_account_codes(vec![foreign_account.code().clone()]) + .advice_inputs(advice_inputs.clone()) + .build(); + // GET ITEM // -------------------------------------------------------------------------------------------- - // Check the correctness of the memory layout after `get_item` account procedure invocation + // Check the correctness of the memory layout after `get_item_foreign` account procedure + // invocation let code = format!( " @@ -678,8 +705,8 @@ fn test_fpi_memory() { # push the index of desired storage item push.0 - # get the hash of the `get_item` account procedure - procref.::test::account::get_item + # get the hash of the `get_item_foreign` procedure of the foreign account + push.{get_item_foreign_hash} # push the foreign account id push.{foreign_account_id} @@ -692,14 +719,9 @@ fn test_fpi_memory() { exec.sys::truncate_stack end ", + get_item_foreign_hash = foreign_account.code().procedures()[0].mast_root(), ); - let tx_context = mock_chain - .build_tx_context(native_account_id, &[], &[]) - .foreign_account_codes(vec![foreign_account.code().clone()]) - .advice_inputs(advice_inputs.clone()) - .build(); - let process = tx_context.execute_code(&code).unwrap(); assert_eq!( @@ -720,7 +742,6 @@ fn test_fpi_memory() { use.kernel::prologue use.miden::tx - use.miden::account begin exec.prologue::prepare_transaction @@ -735,8 +756,8 @@ fn test_fpi_memory() { # push the index of desired storage item push.1 - # get the hash of the `get_map_item` account procedure - procref.account::get_map_item + # get the hash of the `get_map_item_foreign` account procedure + push.{get_map_item_foreign_hash} # push the foreign account id push.{foreign_account_id} @@ -750,6 +771,7 @@ fn test_fpi_memory() { end ", map_key = STORAGE_LEAVES_2[0].0, + get_map_item_foreign_hash = foreign_account.code().procedures()[1].mast_root(), ); let process = tx_context.execute_code(&code).unwrap(); @@ -786,8 +808,8 @@ fn test_fpi_memory() { # push the index of desired storage item push.0 - # get the hash of the `get_item` account procedure - procref.::test::account::get_item + # get the hash of the `get_item_foreign` procedure of the foreign account + push.{get_item_foreign_hash} # push the foreign account id push.{foreign_account_id} @@ -804,8 +826,8 @@ fn test_fpi_memory() { # push the index of desired storage item push.0 - # get the hash of the `get_item` account procedure - procref.::test::account::get_item + # get the hash of the `get_item_foreign` procedure of the foreign account + push.{get_item_foreign_hash} # push the foreign account id push.{foreign_account_id} @@ -817,6 +839,7 @@ fn test_fpi_memory() { exec.sys::truncate_stack end ", + get_item_foreign_hash = foreign_account.code().procedures()[0].mast_root(), ); let process = tx_context.execute_code(&code).unwrap(); @@ -841,6 +864,9 @@ fn test_fpi_memory() { /// obtain the data from the foreign account's storage slot. #[test] fn test_fpi_execute_foreign_procedure() { + // Prepare the test data + let storage_slots = + vec![AccountStorage::mock_item_0().slot, AccountStorage::mock_item_2().slot]; let foreign_account_code_source = " use.miden::account @@ -861,11 +887,10 @@ fn test_fpi_execute_foreign_procedure() { exec.account::get_map_item end "; - let storage_slot = AccountStorage::mock_item_0().slot; let foreign_account_component = AccountComponent::compile( foreign_account_code_source, TransactionKernel::testing_assembler(), - vec![storage_slot], + storage_slots, ) .unwrap() .with_supports_all_types(); @@ -899,6 +924,7 @@ fn test_fpi_execute_foreign_procedure() { use.miden::tx begin + # get the storage item at index 0 # pad the stack for the `execute_foreign_procedure`execution padw padw padw push.0.0 # => [pad(14)] @@ -914,17 +940,45 @@ fn test_fpi_execute_foreign_procedure() { # => [foreign_account_id, FOREIGN_PROC_ROOT, storage_item_index, pad(14)] exec.tx::execute_foreign_procedure + # => [STORAGE_VALUE] # assert the correctness of the obtained value push.1.2.3.4 assert_eqw + # => [] + + # get the storage map at index 1 + # pad the stack for the `execute_foreign_procedure` execution + padw padw push.0.0 + # => [pad(10)] + + # push the key of desired storage item + push.{map_key} + + # push the index of desired storage item + push.1 + + # get the hash of the `get_map_item_foreign` account procedure + push.{get_map_item_foreign_hash} + + # push the foreign account id + push.{foreign_account_id} + # => [foreign_account_id, FOREIGN_PROC_ROOT, storage_item_index, MAP_ITEM_KEY, pad(10)] + + exec.tx::execute_foreign_procedure + # => [MAP_VALUE] + + # assert the correctness of the obtained value + push.1.2.3.4 assert_eqw + # => [] # truncate the stack exec.sys::truncate_stack end ", - // `get_item` procedure has index 0 - get_item_foreign_hash = foreign_account.code().procedures()[0].mast_root(), foreign_account_id = foreign_account.id(), + get_item_foreign_hash = foreign_account.code().procedures()[0].mast_root(), + get_map_item_foreign_hash = foreign_account.code().procedures()[1].mast_root(), + map_key = STORAGE_LEAVES_2[0].0, ); let tx_script = @@ -973,7 +1027,7 @@ fn get_mock_fpi_adv_inputs(foreign_account: &Account, mock_chain: &MockChain) -> let foreign_storage_root = foreign_account.storage().commitment(); let foreign_code_root = foreign_account.code().commitment(); - AdviceInputs::default() + let mut inputs = AdviceInputs::default() .with_map([ // ACCOUNT_ID |-> [ID_AND_NONCE, VAULT_ROOT, STORAGE_ROOT, CODE_ROOT] ( @@ -991,7 +1045,19 @@ fn get_mock_fpi_adv_inputs(foreign_account: &Account, mock_chain: &MockChain) -> // CODE_ROOT |-> [[ACCOUNT_PROCEDURE_DATA]] (foreign_code_root, foreign_account.code().as_elements()), ]) - .with_merkle_store(mock_chain.accounts().into()) + .with_merkle_store(mock_chain.accounts().into()); + + for slot in foreign_account.storage().slots() { + // if there are storage maps, we populate the merkle store and advice map + if let StorageSlot::Map(map) = slot { + // extend the merkle store and map with the storage maps + inputs.extend_merkle_store(map.inner_nodes()); + // populate advice map with Sparse Merkle Tree leaf nodes + inputs.extend_map(map.leaves().map(|(_, leaf)| (leaf.hash(), leaf.to_elements()))); + } + } + + inputs } fn foreign_account_data_memory_assertions(foreign_account: &Account, process: &Process) {