Skip to content

Commit

Permalink
refactor: update memory tests, extend the main test
Browse files Browse the repository at this point in the history
  • Loading branch information
Fumuran committed Nov 18, 2024
1 parent 8defcc4 commit 6678418
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 45 deletions.
7 changes: 4 additions & 3 deletions miden-tx/src/testing/mock_host.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// MOCK HOST
// ================================================================================================

use alloc::{rc::Rc, string::ToString, sync::Arc};
use alloc::{rc::Rc, string::ToString, sync::Arc, vec::Vec};

use miden_lib::transaction::TransactionEvent;
use miden_objects::{
Expand Down Expand Up @@ -34,10 +34,11 @@ impl MockHost {
account: AccountHeader,
advice_inputs: AdviceInputs,
mast_store: Rc<TransactionMastStore>,
mut foreign_code_commitments: Vec<Digest>,
) -> 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(),
Expand Down
11 changes: 8 additions & 3 deletions miden-tx/src/testing/tx_context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
144 changes: 105 additions & 39 deletions miden-tx/src/tests/kernel_tests/test_tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -625,41 +624,69 @@ 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(),
)
.nonce(ONE)
.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!(
"
Expand All @@ -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}
Expand All @@ -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!(
Expand All @@ -720,7 +742,6 @@ fn test_fpi_memory() {
use.kernel::prologue
use.miden::tx
use.miden::account
begin
exec.prologue::prepare_transaction
Expand All @@ -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}
Expand All @@ -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();
Expand Down Expand Up @@ -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}
Expand All @@ -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}
Expand All @@ -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();
Expand All @@ -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
Expand All @@ -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();
Expand Down Expand Up @@ -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)]
Expand All @@ -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 =
Expand Down Expand Up @@ -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]
(
Expand All @@ -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<MockHost>) {
Expand Down

0 comments on commit 6678418

Please sign in to comment.