diff --git a/bench-tx/src/main.rs b/bench-tx/src/main.rs index c0f2c0d0a..00bf47625 100644 --- a/bench-tx/src/main.rs +++ b/bench-tx/src/main.rs @@ -13,15 +13,16 @@ use miden_objects::{ assets::{Asset, FungibleAsset}, crypto::{dsa::rpo_falcon512::SecretKey, rand::RpoRandomCoin}, notes::NoteType, + testing::notes::AssetPreservationStatus, transaction::TransactionArgs, Felt, }; use miden_tx::{ - auth::BasicAuthenticator, testing::data_store::MockDataStore, utils::Serializable, + auth::BasicAuthenticator, testing::TransactionContextBuilder, utils::Serializable, TransactionExecutor, TransactionHost, TransactionProgress, }; use rand::rngs::StdRng; -use vm_processor::{ExecutionOptions, RecAdviceProvider, Word}; +use vm_processor::{ExecutionOptions, RecAdviceProvider, Word, ONE}; mod utils; use utils::{ @@ -66,23 +67,28 @@ fn main() -> Result<(), String> { /// Runs the default transaction with empty transaction script and two default notes. pub fn benchmark_default_tx() -> Result { - let data_store = MockDataStore::default(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .with_mock_notes(AssetPreservationStatus::Preserved) + .build(); let mut executor: TransactionExecutor<_, ()> = - TransactionExecutor::new(data_store.clone(), None).with_tracing(); + TransactionExecutor::new(tx_context.clone(), None).with_tracing(); - let account_id = data_store.account().id(); + let account_id = tx_context.account().id(); executor.load_account(account_id).map_err(|e| e.to_string())?; - let block_ref = data_store.block_header().block_num(); - let note_ids = data_store - .tx_inputs + let block_ref = tx_context.tx_inputs().block_header().block_num(); + let note_ids = tx_context + .tx_inputs() .input_notes() .iter() .map(|note| note.id()) .collect::>(); let transaction = executor - .prepare_transaction(account_id, block_ref, ¬e_ids, data_store.tx_args.clone()) + .prepare_transaction(account_id, block_ref, ¬e_ids, tx_context.tx_args().clone()) .map_err(|e| e.to_string())?; let (stack_inputs, advice_inputs) = transaction.get_kernel_inputs(); @@ -132,16 +138,17 @@ pub fn benchmark_p2id() -> Result { ) .unwrap(); - let data_store = - MockDataStore::with_existing(Some(target_account.clone()), Some(vec![note.clone()])); + let tx_context = TransactionContextBuilder::new(target_account.clone()) + .input_notes(vec![note.clone()]) + .build(); let mut executor: TransactionExecutor<_, ()> = - TransactionExecutor::new(data_store.clone(), None).with_tracing(); + TransactionExecutor::new(tx_context.clone(), None).with_tracing(); executor.load_account(target_account_id).unwrap(); - let block_ref = data_store.block_header().block_num(); - let note_ids = data_store - .tx_inputs + let block_ref = tx_context.tx_inputs().block_header().block_num(); + let note_ids = tx_context + .tx_inputs() .input_notes() .iter() .map(|note| note.id()) diff --git a/miden-tx/Cargo.toml b/miden-tx/Cargo.toml index f6d41d7ce..31e7ed756 100644 --- a/miden-tx/Cargo.toml +++ b/miden-tx/Cargo.toml @@ -21,8 +21,7 @@ async = ["winter-maybe-async/async"] concurrent = ["miden-lib/concurrent", "miden-objects/concurrent", "miden-prover/concurrent", "std"] default = ["std"] std = ["miden-lib/std", "miden-objects/std", "miden-prover/std", "miden-verifier/std", "vm-processor/std"] -testing = ["miden-objects/testing", "miden-lib/testing", "vm-processor/internals"] -async = ["winter-maybe-async/async"] +testing = ["miden-objects/testing", "miden-lib/testing", "vm-processor/internals", "dep:rand_chacha"] [dependencies] miden-lib = { path = "../miden-lib", version = "0.4", default-features = false } @@ -30,9 +29,9 @@ miden-objects = { path = "../objects", version = "0.4", default-features = false miden-prover = { workspace = true } miden-verifier = { workspace = true } rand = { workspace = true } -winter-maybe-async = "0.10.0" +rand_chacha = { version = "0.3", default-features = false, optional = true } vm-processor = { workspace = true } -winter-maybe-async = { version = "0.10.0" } +winter-maybe-async = { version = "0.10" } [dev-dependencies] rand_chacha = { version = "0.3", default-features = false } diff --git a/miden-tx/src/testing/chain_data.rs b/miden-tx/src/testing/chain_data.rs deleted file mode 100644 index 9d761d8eb..000000000 --- a/miden-tx/src/testing/chain_data.rs +++ /dev/null @@ -1,79 +0,0 @@ -use alloc::vec::Vec; - -use miden_objects::{ - crypto::merkle::{LeafIndex, Mmr, PartialMmr}, - notes::{Note, NoteInclusionProof}, - transaction::{ChainMmr, InputNote}, - BlockHeader, NOTE_TREE_DEPTH, -}; -use vm_processor::crypto::SimpleSmt; - -pub fn mock_chain_data(consumed_notes: Vec) -> (ChainMmr, Vec) { - let mut note_trees = Vec::new(); - - // TODO: Consider how to better represent note authentication data. - // we use the index for both the block number and the leaf index in the note tree - for (index, note) in consumed_notes.iter().enumerate() { - let smt_entries = vec![(index as u64, note.authentication_hash().into())]; - let smt = SimpleSmt::::with_leaves(smt_entries).unwrap(); - note_trees.push(smt); - } - - let mut note_tree_iter = note_trees.iter(); - - // create a dummy chain of block headers - let block_chain = vec![ - BlockHeader::mock(0, None, note_tree_iter.next().map(|x| x.root()), &[]), - BlockHeader::mock(1, None, note_tree_iter.next().map(|x| x.root()), &[]), - BlockHeader::mock(2, None, note_tree_iter.next().map(|x| x.root()), &[]), - BlockHeader::mock(3, None, note_tree_iter.next().map(|x| x.root()), &[]), - ]; - - // instantiate and populate MMR - let mut mmr = Mmr::default(); - for block_header in block_chain.iter() { - mmr.add(block_header.hash()) - } - let chain_mmr = mmr_to_chain_mmr(&mmr, &block_chain); - - // set origin for consumed notes using chain and block data - let recorded_notes = consumed_notes - .into_iter() - .enumerate() - .map(|(index, note)| { - let block_header = &block_chain[index]; - let auth_index = LeafIndex::new(index as u64).unwrap(); - - InputNote::authenticated( - note, - NoteInclusionProof::new( - block_header.block_num(), - block_header.sub_hash(), - block_header.note_root(), - index as u64, - note_trees[index].open(&auth_index).path, - ) - .unwrap(), - ) - }) - .collect::>(); - - (chain_mmr, recorded_notes) -} - -// HELPER FUNCTIONS -// ================================================================================================ - -/// Converts the MMR into partial MMR by copying all leaves from MMR to partial MMR. -fn mmr_to_chain_mmr(mmr: &Mmr, blocks: &[BlockHeader]) -> ChainMmr { - let num_leaves = mmr.forest(); - let mut partial_mmr = PartialMmr::from_peaks(mmr.peaks(mmr.forest()).unwrap()); - - for i in 0..num_leaves { - let node = mmr.get(i).unwrap(); - let path = mmr.open(i, mmr.forest()).unwrap().merkle_path; - partial_mmr.track(i, node, &path).unwrap(); - } - - ChainMmr::new(partial_mmr, blocks.to_vec()).unwrap() -} diff --git a/miden-tx/src/testing/data_store.rs b/miden-tx/src/testing/data_store.rs deleted file mode 100644 index 6b412acbd..000000000 --- a/miden-tx/src/testing/data_store.rs +++ /dev/null @@ -1,91 +0,0 @@ -// MOCK DATA STORE -// ================================================================================================ - -use alloc::vec::Vec; - -use miden_objects::{ - accounts::{Account, AccountId}, - assembly::ModuleAst, - notes::{Note, NoteId}, - testing::{account::MockAccountType, notes::AssetPreservationStatus}, - transaction::{InputNote, InputNotes, TransactionArgs, TransactionInputs}, - BlockHeader, -}; -use winter_maybe_async::maybe_async; - -use super::TransactionContextBuilder; -use crate::{DataStore, DataStoreError}; - -#[derive(Clone)] -pub struct MockDataStore { - pub tx_inputs: TransactionInputs, - pub tx_args: TransactionArgs, -} - -impl MockDataStore { - pub fn new(asset_preservation_status: AssetPreservationStatus) -> Self { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting) - .with_mock_notes(asset_preservation_status) - .build(); - let (_, _, tx_args, tx_inputs) = tx_context.into_parts(); - Self { tx_inputs, tx_args } - } - - pub fn with_existing(account: Option, input_notes: Option>) -> Self { - let tx_context = if let Some(acc) = account { - TransactionContextBuilder::new(acc) - } else { - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting) - }; - - let tx_context = if let Some(notes) = input_notes { - tx_context.input_notes(notes) - } else { - tx_context.with_mock_notes(AssetPreservationStatus::Preserved) - }; - let (_, _, tx_args, tx_inputs) = tx_context.build().into_parts(); - - Self { tx_inputs, tx_args } - } - - pub fn input_notes(&self) -> &InputNotes { - self.tx_inputs.input_notes() - } - - pub fn block_header(&self) -> &BlockHeader { - self.tx_inputs.block_header() - } - - pub fn account(&self) -> &Account { - self.tx_inputs.account() - } -} - -impl Default for MockDataStore { - fn default() -> Self { - Self::new(AssetPreservationStatus::Preserved) - } -} - -impl DataStore for MockDataStore { - #[maybe_async] - fn get_transaction_inputs( - &self, - account_id: AccountId, - block_num: u32, - notes: &[NoteId], - ) -> Result { - assert_eq!(account_id, self.tx_inputs.account().id()); - assert_eq!(block_num, self.block_header().block_num()); - assert_eq!(notes.len(), self.tx_inputs.input_notes().num_notes()); - - Ok(self.tx_inputs.clone()) - } - - #[maybe_async] - fn get_account_code(&self, account_id: AccountId) -> Result { - assert_eq!(account_id, self.tx_inputs.account().id()); - Ok(self.tx_inputs.account().code().module().clone()) - } -} diff --git a/miden-tx/src/testing/executor.rs b/miden-tx/src/testing/executor.rs index cd12c0499..c4acb6662 100644 --- a/miden-tx/src/testing/executor.rs +++ b/miden-tx/src/testing/executor.rs @@ -2,8 +2,7 @@ use miden_lib::transaction::TransactionKernel; #[cfg(feature = "std")] use vm_processor::{ - AdviceInputs, AdviceProvider, DefaultHost, ExecutionError, ExecutionOptions, Host, Process, - Program, StackInputs, + AdviceInputs, AdviceProvider, DefaultHost, ExecutionError, Host, Process, Program, StackInputs, }; // MOCK CODE EXECUTOR @@ -43,18 +42,17 @@ impl CodeExecutor { /// `code` before execution. /// Otherwise, `self.imports` and `code` will be concatenated and the result will be executed. pub fn run(self, code: &str) -> Result, ExecutionError> { - let assembler = TransactionKernel::assembler(); + let assembler = TransactionKernel::assembler().with_debug_mode(true); let program = assembler.compile(code).unwrap(); self.execute_program(program) } pub fn execute_program(self, program: Program) -> Result, ExecutionError> { - let mut process = Process::new( + let mut process = Process::new_debug( program.kernel().clone(), self.stack_inputs.unwrap_or_default(), self.host, - ExecutionOptions::default(), ); process.execute(&program)?; diff --git a/miden-tx/src/testing/mod.rs b/miden-tx/src/testing/mod.rs index 64748901c..9d8cf2670 100644 --- a/miden-tx/src/testing/mod.rs +++ b/miden-tx/src/testing/mod.rs @@ -1,5 +1,4 @@ mod account_procs; -pub mod data_store; pub mod executor; pub use mock_host::MockHost; diff --git a/miden-tx/src/testing/tx_context.rs b/miden-tx/src/testing/tx_context.rs index aedaf3fc2..3c787e4fe 100644 --- a/miden-tx/src/testing/tx_context.rs +++ b/miden-tx/src/testing/tx_context.rs @@ -1,30 +1,45 @@ -// TRANSACTION CONTEXT -// ================================================================================================ - use alloc::vec::Vec; use miden_lib::transaction::{ToTransactionKernelInputs, TransactionKernel}; use miden_objects::{ accounts::{ - account_id::testing::ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, Account, - AccountCode, + account_id::testing::{ + ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_1, ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_2, + ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_3, ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, + ACCOUNT_ID_SENDER, + }, + Account, AccountCode, AccountId, }, - assembly::Assembler, - notes::{Note, NoteId}, + assembly::{Assembler, ModuleAst}, + assets::{Asset, FungibleAsset}, + notes::{Note, NoteId, NoteType}, testing::{ - account::MockAccountType, - block::MockChain, - notes::{mock_notes, AssetPreservationStatus}, + account_code::{ACCOUNT_ADD_ASSET_TO_NOTE_MAST_ROOT, ACCOUNT_CREATE_NOTE_MAST_ROOT}, + block::{MockChain, MockChainBuilder}, + constants::{ + CONSUMED_ASSET_1_AMOUNT, CONSUMED_ASSET_2_AMOUNT, CONSUMED_ASSET_3_AMOUNT, + NON_FUNGIBLE_ASSET_DATA_2, + }, + notes::{AssetPreservationStatus, NoteBuilder}, + prepare_word, + storage::prepare_assets, }, transaction::{ InputNote, InputNotes, OutputNote, PreparedTransaction, TransactionArgs, TransactionInputs, }, - FieldElement, }; +use rand::SeedableRng; +use rand_chacha::ChaCha20Rng; use vm_processor::{AdviceInputs, ExecutionError, Felt, Process, Word}; +use winter_maybe_async::maybe_async; -use super::{executor::CodeExecutor, utils::create_test_chain, MockHost}; +use super::{executor::CodeExecutor, MockHost}; +use crate::{DataStore, DataStoreError}; + +// TRANSACTION CONTEXT +// ================================================================================================ +#[derive(Debug, Clone)] pub struct TransactionContext { mock_chain: MockChain, expected_output_notes: Vec, @@ -35,7 +50,9 @@ pub struct TransactionContext { impl TransactionContext { pub fn execute_code(&self, code: &str) -> Result, ExecutionError> { - let tx = self.get_prepared_transaction(code); + let assembler = TransactionKernel::assembler().with_debug_mode(true); + let program = assembler.compile(code).unwrap(); + let tx = PreparedTransaction::new(program, self.tx_inputs.clone(), self.tx_args.clone()); let (stack_inputs, mut advice_inputs) = tx.get_kernel_inputs(); advice_inputs.extend(self.advice_inputs.clone()); @@ -44,31 +61,10 @@ impl TransactionContext { .run(code) } - pub fn execute_transaction( - &self, - tx: &PreparedTransaction, - ) -> Result, ExecutionError> { - let (stack_inputs, advice_inputs) = tx.get_kernel_inputs(); - - CodeExecutor::new(MockHost::new(tx.account().into(), advice_inputs)) - .stack_inputs(stack_inputs) - .execute_program(tx.program().clone()) - } - - pub fn get_prepared_transaction(&self, code: &str) -> PreparedTransaction { - let assembler = TransactionKernel::assembler(); - let program = assembler.compile(code).unwrap(); - PreparedTransaction::new(program, self.tx_inputs.clone(), self.tx_args.clone()) - } - pub fn account(&self) -> &Account { self.tx_inputs.account() } - pub fn account_seed(&self) -> Option { - self.tx_inputs.account_seed() - } - pub fn expected_output_notes(&self) -> &[Note] { &self.expected_output_notes } @@ -92,9 +88,27 @@ impl TransactionContext { pub fn tx_inputs(&self) -> &TransactionInputs { &self.tx_inputs } +} - pub fn into_parts(self) -> (MockChain, Vec, TransactionArgs, TransactionInputs) { - (self.mock_chain, self.expected_output_notes, self.tx_args, self.tx_inputs) +impl DataStore for TransactionContext { + #[maybe_async] + fn get_transaction_inputs( + &self, + account_id: AccountId, + block_num: u32, + notes: &[NoteId], + ) -> Result { + assert_eq!(account_id, self.tx_inputs.account().id()); + assert_eq!(block_num, self.tx_inputs.block_header().block_num()); + assert_eq!(notes.len(), self.tx_inputs.input_notes().num_notes()); + + Ok(self.tx_inputs.clone()) + } + + #[maybe_async] + fn get_account_code(&self, account_id: AccountId) -> Result { + assert_eq!(account_id, self.tx_inputs.account().id()); + Ok(self.tx_inputs.account().code().module().clone()) } } @@ -125,25 +139,9 @@ impl TransactionContextBuilder { } } - pub fn with_acc_type(account_type: MockAccountType) -> Self { + pub fn with_standard_account(account_id: u64, nonce: Felt) -> Self { let assembler = TransactionKernel::assembler().with_debug_mode(true); - let account = match account_type { - MockAccountType::StandardNew { account_id } => { - let code = AccountCode::mock_wallet(&assembler); - Account::mock(account_id, Felt::ZERO, code) - }, - MockAccountType::StandardExisting => Account::mock( - ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, - Felt::ONE, - AccountCode::mock_wallet(&assembler), - ), - MockAccountType::FungibleFaucet { acct_id, nonce, empty_reserved_slot } => { - Account::mock_fungible_faucet(acct_id, nonce, empty_reserved_slot, &assembler) - }, - MockAccountType::NonFungibleFaucet { acct_id, nonce, empty_reserved_slot } => { - Account::mock_non_fungible_faucet(acct_id, nonce, empty_reserved_slot, &assembler) - }, - }; + let account = Account::mock(account_id, nonce, AccountCode::mock_wallet(&assembler)); Self { assembler, @@ -156,13 +154,39 @@ impl TransactionContextBuilder { } } - pub fn account_seed(mut self, account_seed: Word) -> Self { - self.account_seed = Some(account_seed); - self + pub fn with_fungible_faucet(acct_id: u64, nonce: Felt, initial_balance: Felt) -> Self { + let assembler = TransactionKernel::assembler().with_debug_mode(true); + let account = Account::mock_fungible_faucet(acct_id, nonce, initial_balance, &assembler); + + Self { + assembler, + account, + account_seed: None, + input_notes: Vec::new(), + expected_output_notes: Vec::new(), + tx_args: TransactionArgs::default(), + advice_inputs: None, + } } - pub fn assembler(mut self, assembler: Assembler) -> Self { - self.assembler = assembler; + pub fn with_non_fungible_faucet(acct_id: u64, nonce: Felt, empty_reserved_slot: bool) -> Self { + let assembler = TransactionKernel::assembler().with_debug_mode(true); + let account = + Account::mock_non_fungible_faucet(acct_id, nonce, empty_reserved_slot, &assembler); + + Self { + assembler, + account, + account_seed: None, + input_notes: Vec::new(), + expected_output_notes: Vec::new(), + tx_args: TransactionArgs::default(), + advice_inputs: None, + } + } + + pub fn account_seed(mut self, account_seed: Word) -> Self { + self.account_seed = Some(account_seed); self } @@ -176,16 +200,6 @@ impl TransactionContextBuilder { self } - pub fn add_input_note(mut self, input_note: Note) -> Self { - self.input_notes.extend(vec![input_note]); - self - } - - pub fn tx_args(mut self, tx_args: TransactionArgs) -> Self { - self.tx_args = tx_args; - self - } - pub fn expected_notes(mut self, output_notes: Vec) -> Self { let output_notes = output_notes.into_iter().filter_map(|n| match n { OutputNote::Full(note) => Some(note), @@ -197,21 +211,41 @@ impl TransactionContextBuilder { self } - pub fn add_expected_output_note(mut self, output_note: OutputNote) -> Self { - if let OutputNote::Full(note) = output_note { - self.expected_output_notes.extend([note]); - } - self - } - - /// Populates input and expected notes with the results from [mock_notes()] + /// Populates input and expected notes. pub fn with_mock_notes(self, asset_preservation: AssetPreservationStatus) -> Self { - let (notes, output_notes) = mock_notes(&self.assembler, &asset_preservation); + let (mut input_notes, output_notes) = mock_notes(&self.assembler); + + let consumed_note_5 = input_notes.pop().unwrap(); + let consumed_note_4 = input_notes.pop().unwrap(); + let consumed_note_3 = input_notes.pop().unwrap(); + let consumed_note_2 = input_notes.pop().unwrap(); + let consumed_note_1 = input_notes.pop().unwrap(); + + let notes = match asset_preservation { + AssetPreservationStatus::TooFewInput => vec![consumed_note_1], + AssetPreservationStatus::Preserved => { + vec![consumed_note_1, consumed_note_2] + }, + AssetPreservationStatus::PreservedWithAccountVaultDelta => { + vec![consumed_note_1, consumed_note_2, consumed_note_5] + }, + AssetPreservationStatus::TooManyFungibleInput => { + vec![consumed_note_1, consumed_note_2, consumed_note_3] + }, + AssetPreservationStatus::TooManyNonFungibleInput => { + vec![consumed_note_1, consumed_note_2, consumed_note_4] + }, + }; + self.input_notes(notes).expected_notes(output_notes) } pub fn build(mut self) -> TransactionContext { - let mock_chain = create_test_chain(self.input_notes.clone()); + let mut mock_chain = MockChainBuilder::new().notes(self.input_notes.clone()).build(); + mock_chain.seal_block(); + mock_chain.seal_block(); + mock_chain.seal_block(); + let input_note_ids: Vec = mock_chain.available_notes().iter().map(|n| n.id()).collect(); @@ -232,3 +266,200 @@ impl TransactionContextBuilder { } } } + +fn mock_notes(assembler: &Assembler) -> (Vec, Vec) { + // ACCOUNT IDS + // -------------------------------------------------------------------------------------------- + let sender = AccountId::try_from(ACCOUNT_ID_SENDER).unwrap(); + let faucet_id_1 = AccountId::try_from(ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_1).unwrap(); + let faucet_id_2 = AccountId::try_from(ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_2).unwrap(); + let faucet_id_3 = AccountId::try_from(ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_3).unwrap(); + + // ASSETS + // -------------------------------------------------------------------------------------------- + let fungible_asset_1: Asset = + FungibleAsset::new(faucet_id_1, CONSUMED_ASSET_1_AMOUNT).unwrap().into(); + let fungible_asset_2: Asset = + FungibleAsset::new(faucet_id_2, CONSUMED_ASSET_2_AMOUNT).unwrap().into(); + let fungible_asset_3: Asset = + FungibleAsset::new(faucet_id_3, CONSUMED_ASSET_3_AMOUNT).unwrap().into(); + + // CREATED NOTES + // -------------------------------------------------------------------------------------------- + let seed = [0_u8; 32]; + let mut rng = ChaCha20Rng::from_seed(seed); + let created_note_1 = NoteBuilder::new(sender, ChaCha20Rng::from_rng(&mut rng).unwrap()) + .note_inputs([1u32.into()]) + .unwrap() + .add_asset(fungible_asset_1) + .build(assembler) + .unwrap(); + + let created_note_2 = NoteBuilder::new(sender, ChaCha20Rng::from_rng(&mut rng).unwrap()) + .note_inputs([2u32.into()]) + .unwrap() + .add_asset(fungible_asset_2) + .build(assembler) + .unwrap(); + + let created_note_3 = NoteBuilder::new(sender, ChaCha20Rng::from_rng(&mut rng).unwrap()) + .note_inputs([3u32.into()]) + .unwrap() + .add_asset(fungible_asset_3) + .build(assembler) + .unwrap(); + + // CONSUMED NOTES + // -------------------------------------------------------------------------------------------- + + let note_1_script_src = format!( + "\ + begin + # create note 0 + push.{recipient0} + push.{PUBLIC_NOTE} + push.{aux0} + push.{tag0} + # MAST root of the `create_note` mock account procedure + call.{ACCOUNT_CREATE_NOTE_MAST_ROOT} + + push.{asset0} movup.4 + call.{ACCOUNT_ADD_ASSET_TO_NOTE_MAST_ROOT} + dropw dropw dropw + + # create note 1 + push.{recipient1} + push.{PUBLIC_NOTE} + push.{aux1} + push.{tag1} + # MAST root of the `create_note` mock account procedure + call.{ACCOUNT_CREATE_NOTE_MAST_ROOT} + + push.{asset1} movup.4 + call.{ACCOUNT_ADD_ASSET_TO_NOTE_MAST_ROOT} + dropw dropw dropw + end + ", + PUBLIC_NOTE = NoteType::Public as u8, + recipient0 = prepare_word(&created_note_1.recipient().digest()), + aux0 = created_note_1.metadata().aux(), + tag0 = created_note_1.metadata().tag(), + asset0 = prepare_assets(created_note_1.assets())[0], + recipient1 = prepare_word(&created_note_2.recipient().digest()), + aux1 = created_note_2.metadata().aux(), + tag1 = created_note_2.metadata().tag(), + asset1 = prepare_assets(created_note_2.assets())[0], + ); + + let consumed_note_1 = NoteBuilder::new(sender, ChaCha20Rng::from_rng(&mut rng).unwrap()) + .note_inputs([1u32.into()]) + .unwrap() + .add_asset(fungible_asset_1) + .code(note_1_script_src) + .build(assembler) + .unwrap(); + + let note_2_script_src = format!( + "\ + begin + # create note 2 + push.{recipient} + push.{PUBLIC_NOTE} + push.{aux} + push.{tag} + # MAST root of the `create_note` mock account procedure + call.{ACCOUNT_CREATE_NOTE_MAST_ROOT} + + push.{asset} movup.4 + call.{ACCOUNT_ADD_ASSET_TO_NOTE_MAST_ROOT} + dropw dropw dropw + end + ", + PUBLIC_NOTE = NoteType::Public as u8, + recipient = prepare_word(&created_note_3.recipient().digest()), + aux = created_note_3.metadata().aux(), + tag = created_note_3.metadata().tag(), + asset = prepare_assets(created_note_3.assets())[0], + ); + + let consumed_note_2 = NoteBuilder::new(sender, ChaCha20Rng::from_rng(&mut rng).unwrap()) + .note_inputs([2u32.into()]) + .unwrap() + .add_asset(fungible_asset_2) + .add_asset(fungible_asset_3) + .code(note_2_script_src) + .build(assembler) + .unwrap(); + + let consumed_note_3 = NoteBuilder::new(sender, ChaCha20Rng::from_rng(&mut rng).unwrap()) + .note_inputs([2u32.into()]) + .unwrap() + .add_asset(fungible_asset_2) + .add_asset(fungible_asset_3) + .build(assembler) + .unwrap(); + + let consumed_note_4 = NoteBuilder::new(sender, ChaCha20Rng::from_rng(&mut rng).unwrap()) + .note_inputs([1u32.into()]) + .unwrap() + .add_asset(Asset::mock_non_fungible( + ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, + &NON_FUNGIBLE_ASSET_DATA_2, + )) + .build(assembler) + .unwrap(); + + // note that changes the account vault + let note_5_script_src = "\ + use.miden::note + use.miden::contracts::wallets::basic->wallet + + begin + # read the assets to memory + push.0 exec.note::get_assets + # => [num_assets, dest_ptr] + + # assert the number of assets is 3 + push.3 assert_eq + # => [dest_ptr] + + # add the first asset to the vault + padw dup.4 mem_loadw call.wallet::receive_asset dropw + # => [dest_ptr] + + # add the second asset to the vault + push.1 add padw dup.4 mem_loadw call.wallet::receive_asset dropw + # => [dest_ptr+1] + + # add the third asset to the vault + push.1 add padw movup.4 mem_loadw call.wallet::receive_asset dropw + # => [] + end + "; + + let consumed_note_5 = NoteBuilder::new(sender, ChaCha20Rng::from_rng(&mut rng).unwrap()) + .add_asset(fungible_asset_1) + .add_asset(fungible_asset_3) + .add_asset(Asset::mock_non_fungible( + ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, + &NON_FUNGIBLE_ASSET_DATA_2, + )) + .code(note_5_script_src) + .build(assembler) + .unwrap(); + + let consumed_notes = vec![ + consumed_note_1, + consumed_note_2, + consumed_note_3, + consumed_note_4, + consumed_note_5, + ]; + let output_notes = vec![ + OutputNote::Full(created_note_1), + OutputNote::Full(created_note_2), + OutputNote::Full(created_note_3), + ]; + + (consumed_notes, output_notes) +} diff --git a/miden-tx/src/testing/utils.rs b/miden-tx/src/testing/utils.rs index 1f4d63025..e7a6e776d 100644 --- a/miden-tx/src/testing/utils.rs +++ b/miden-tx/src/testing/utils.rs @@ -1,5 +1,3 @@ -use alloc::vec::Vec; - use miden_lib::transaction::memory; #[cfg(not(target_family = "wasm"))] use miden_lib::transaction::TransactionKernel; @@ -10,16 +8,11 @@ use miden_objects::{ account_id::testing::ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, Account, AccountCode, AccountDelta, }, - notes::Note, - testing::{ - block::{MockChain, MockChainBuilder}, - notes::AssetPreservationStatus, - }, + testing::notes::AssetPreservationStatus, transaction::{ExecutedTransaction, OutputNote, OutputNotes, TransactionOutputs}, - vm::CodeBlock, FieldElement, }; -use vm_processor::{AdviceInputs, Operation, Program, ZERO}; +use vm_processor::AdviceInputs; use super::TransactionContextBuilder; @@ -31,26 +24,28 @@ pub fn consumed_note_data_ptr(note_idx: u32) -> memory::MemoryAddress { } pub fn mock_executed_tx(asset_preservation: AssetPreservationStatus) -> ExecutedTransaction { - let assembler = TransactionKernel::assembler(); + let assembler = TransactionKernel::assembler().with_debug_mode(true); + + // use empty main program to produce the mock transaction + let program = assembler.compile("begin push.0 drop end").unwrap(); + + // simulate a transaction that modifies the account state, and increases the nonce by one + let initial_nonce = Felt::ONE; + let final_nonce = initial_nonce + Felt::ONE; - let initial_account = Account::mock( + let tx_context = TransactionContextBuilder::with_standard_account( ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, - Felt::ONE, - AccountCode::mock_wallet(&assembler), - ); + initial_nonce, + ) + .with_mock_notes(asset_preservation) + .build(); - // nonce incremented by 1 let final_account = Account::mock( ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, - Felt::new(2), - initial_account.code().clone(), + final_nonce, + AccountCode::mock_wallet(&assembler), ); - let tx_context = TransactionContextBuilder::new(initial_account) - .assembler(assembler) - .with_mock_notes(asset_preservation) - .build(); - let output_notes = tx_context .expected_output_notes() .iter() @@ -63,7 +58,6 @@ pub fn mock_executed_tx(asset_preservation: AssetPreservationStatus) -> Executed output_notes: OutputNotes::new(output_notes).unwrap(), }; - let program = build_dummy_tx_program(); let account_delta = AccountDelta::default(); let advice_witness = AdviceInputs::default(); @@ -76,18 +70,3 @@ pub fn mock_executed_tx(asset_preservation: AssetPreservationStatus) -> Executed advice_witness, ) } - -pub fn create_test_chain(created_notes: Vec) -> MockChain { - let mut mock_chain = MockChainBuilder::new().notes(created_notes).build(); - mock_chain.seal_block(); - mock_chain.seal_block(); - mock_chain.seal_block(); - - mock_chain -} - -pub fn build_dummy_tx_program() -> Program { - let operations = vec![Operation::Push(ZERO), Operation::Drop]; - let span = CodeBlock::new_span(operations); - Program::new(span) -} diff --git a/miden-tx/src/tests/kernel_tests/mod.rs b/miden-tx/src/tests/kernel_tests/mod.rs index 3f6c0c438..46238b5b5 100644 --- a/miden-tx/src/tests/kernel_tests/mod.rs +++ b/miden-tx/src/tests/kernel_tests/mod.rs @@ -12,7 +12,7 @@ use miden_objects::{ vm::StackInputs, Felt, Hasher, Word, ONE, ZERO, }; -use vm_processor::{ContextId, MemAdviceProvider, Process, ProcessState}; +use vm_processor::{ContextId, Host, MemAdviceProvider, Process, ProcessState}; const TX_KERNEL_DIR: &str = "miden/kernels/tx"; @@ -28,6 +28,10 @@ mod test_tx; // HELPER FUNCTIONS // ================================================================================================ +pub fn read_root_mem_value(process: &Process, addr: u32) -> Word { + process.get_mem_value(ContextId::root(), addr).unwrap() +} + fn build_module_path(dir: &str, file: &str) -> PathBuf { [env!("CARGO_MANIFEST_DIR"), "..", "miden-lib", "asm", dir, file] .iter() @@ -64,53 +68,53 @@ pub fn output_notes_data_procedure(notes: &OutputNotes) -> String { format!( " - proc.create_mock_notes - # remove padding from prologue - dropw dropw dropw dropw + proc.create_mock_notes + # remove padding from prologue + dropw dropw dropw dropw - # populate note 0 - push.{note_0_metadata} - push.{CREATED_NOTE_SECTION_OFFSET}.{CREATED_NOTE_METADATA_OFFSET} add mem_storew dropw + # populate note 0 + push.{note_0_metadata} + push.{CREATED_NOTE_SECTION_OFFSET}.{CREATED_NOTE_METADATA_OFFSET} add mem_storew dropw - push.{note_0_recipient} - push.{CREATED_NOTE_SECTION_OFFSET}.{CREATED_NOTE_RECIPIENT_OFFSET} add mem_storew dropw + push.{note_0_recipient} + push.{CREATED_NOTE_SECTION_OFFSET}.{CREATED_NOTE_RECIPIENT_OFFSET} add mem_storew dropw - push.{note_0_num_assets} - push.{CREATED_NOTE_SECTION_OFFSET}.{CREATED_NOTE_NUM_ASSETS_OFFSET} add mem_store + push.{note_0_num_assets} + push.{CREATED_NOTE_SECTION_OFFSET}.{CREATED_NOTE_NUM_ASSETS_OFFSET} add mem_store - push.{} - push.{CREATED_NOTE_SECTION_OFFSET}.{CREATED_NOTE_ASSETS_OFFSET} add mem_storew dropw + push.{} + push.{CREATED_NOTE_SECTION_OFFSET}.{CREATED_NOTE_ASSETS_OFFSET} add mem_storew dropw - # populate note 1 - push.{note_1_metadata} - push.{CREATED_NOTE_SECTION_OFFSET}.{NOTE_1_OFFSET}.{CREATED_NOTE_METADATA_OFFSET} add add mem_storew dropw + # populate note 1 + push.{note_1_metadata} + push.{CREATED_NOTE_SECTION_OFFSET}.{NOTE_1_OFFSET}.{CREATED_NOTE_METADATA_OFFSET} add add mem_storew dropw - push.{note_1_recipient} - push.{CREATED_NOTE_SECTION_OFFSET}.{NOTE_1_OFFSET}.{CREATED_NOTE_RECIPIENT_OFFSET} add add mem_storew dropw + push.{note_1_recipient} + push.{CREATED_NOTE_SECTION_OFFSET}.{NOTE_1_OFFSET}.{CREATED_NOTE_RECIPIENT_OFFSET} add add mem_storew dropw - push.{note_1_num_assets} - push.{CREATED_NOTE_SECTION_OFFSET}.{NOTE_1_OFFSET}.{CREATED_NOTE_NUM_ASSETS_OFFSET} add add mem_store + push.{note_1_num_assets} + push.{CREATED_NOTE_SECTION_OFFSET}.{NOTE_1_OFFSET}.{CREATED_NOTE_NUM_ASSETS_OFFSET} add add mem_store - push.{} - push.{CREATED_NOTE_SECTION_OFFSET}.{NOTE_1_OFFSET}.{CREATED_NOTE_ASSETS_OFFSET} add add mem_storew dropw + push.{} + push.{CREATED_NOTE_SECTION_OFFSET}.{NOTE_1_OFFSET}.{CREATED_NOTE_ASSETS_OFFSET} add add mem_storew dropw - # populate note 2 - push.{note_2_metadata} - push.{CREATED_NOTE_SECTION_OFFSET}.{NOTE_2_OFFSET}.{CREATED_NOTE_METADATA_OFFSET} add add mem_storew dropw + # populate note 2 + push.{note_2_metadata} + push.{CREATED_NOTE_SECTION_OFFSET}.{NOTE_2_OFFSET}.{CREATED_NOTE_METADATA_OFFSET} add add mem_storew dropw - push.{note_2_recipient} - push.{CREATED_NOTE_SECTION_OFFSET}.{NOTE_2_OFFSET}.{CREATED_NOTE_RECIPIENT_OFFSET} add add mem_storew dropw + push.{note_2_recipient} + push.{CREATED_NOTE_SECTION_OFFSET}.{NOTE_2_OFFSET}.{CREATED_NOTE_RECIPIENT_OFFSET} add add mem_storew dropw - push.{note_2_num_assets} - push.{CREATED_NOTE_SECTION_OFFSET}.{NOTE_2_OFFSET}.{CREATED_NOTE_NUM_ASSETS_OFFSET} add add mem_store + push.{note_2_num_assets} + push.{CREATED_NOTE_SECTION_OFFSET}.{NOTE_2_OFFSET}.{CREATED_NOTE_NUM_ASSETS_OFFSET} add add mem_store - push.{} - push.{CREATED_NOTE_SECTION_OFFSET}.{NOTE_2_OFFSET}.{CREATED_NOTE_ASSETS_OFFSET} add add mem_storew dropw + push.{} + push.{CREATED_NOTE_SECTION_OFFSET}.{NOTE_2_OFFSET}.{CREATED_NOTE_ASSETS_OFFSET} add add mem_storew dropw - # set num created notes - push.{}.{NUM_CREATED_NOTES_PTR} mem_store - end - ", + # set num created notes + push.{}.{NUM_CREATED_NOTES_PTR} mem_store + end + ", note_0_assets[0], note_1_assets[0], note_2_assets[0], diff --git a/miden-tx/src/tests/kernel_tests/test_account.rs b/miden-tx/src/tests/kernel_tests/test_account.rs index fbed9af92..49f6b72df 100644 --- a/miden-tx/src/tests/kernel_tests/test_account.rs +++ b/miden-tx/src/tests/kernel_tests/test_account.rs @@ -13,19 +13,16 @@ use miden_objects::{ AccountId, AccountStorage, AccountType, StorageSlotType, }, crypto::{hash::rpo::RpoDigest, merkle::LeafIndex}, - testing::{ - account::MockAccountType, notes::AssetPreservationStatus, prepare_word, - storage::STORAGE_LEAVES_2, - }, + testing::{notes::AssetPreservationStatus, prepare_word, storage::STORAGE_LEAVES_2}, }; -use vm_processor::{ContextId, Felt, MemAdviceProvider}; +use vm_processor::{Felt, MemAdviceProvider}; use super::{ProcessState, StackInputs, Word, ONE, ZERO}; use crate::{ testing::{ executor::CodeExecutor, utils::mock_executed_tx, MockHost, TransactionContextBuilder, }, - tests::kernel_tests::output_notes_data_procedure, + tests::kernel_tests::{output_notes_data_procedure, read_root_mem_value}, }; // ACCOUNT CODE TESTS @@ -33,8 +30,11 @@ use crate::{ #[test] pub fn test_set_code_is_not_immediate() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let code = " use.miden::kernels::tx::prologue use.miden::account @@ -46,16 +46,17 @@ pub fn test_set_code_is_not_immediate() { "; let process = tx_context.execute_code(code).unwrap(); - // assert the code root is not changed + assert_eq!( - process.get_mem_value(ContextId::root(), ACCT_CODE_ROOT_PTR).unwrap(), - tx_context.account().code().root().as_elements() + read_root_mem_value(&process, ACCT_CODE_ROOT_PTR), + tx_context.account().code().root().as_elements(), + "the code root must not change immediatelly", ); - // assert the new code root is cached assert_eq!( - process.get_mem_value(ContextId::root(), ACCT_NEW_CODE_ROOT_PTR).unwrap(), - [ONE, Felt::new(2), Felt::new(3), Felt::new(4)] + read_root_mem_value(&process, ACCT_NEW_CODE_ROOT_PTR), + [ONE, Felt::new(2), Felt::new(3), Felt::new(4)], + "the code root must be cached", ); } @@ -93,10 +94,10 @@ pub fn test_set_code_succeeds() { let host = MockHost::new(executed_transaction.initial_account().into(), advice_inputs); let process = CodeExecutor::new(host).stack_inputs(stack_inputs).run(&code).unwrap(); - // assert the code root is changed after the epilogue assert_eq!( - process.get_mem_value(ContextId::root(), ACCT_CODE_ROOT_PTR).unwrap(), - [ZERO, ONE, Felt::new(2), Felt::new(3)] + read_root_mem_value(&process, ACCT_CODE_ROOT_PTR), + [ZERO, ONE, Felt::new(2), Felt::new(3)], + "the code root must change after the epilogue", ); } @@ -142,12 +143,10 @@ pub fn test_account_type() { .run(&code) .unwrap(); - let expected_result = if account_id.account_type() == expected_type { - has_type = true; - ONE - } else { - ZERO - }; + let type_matches = account_id.account_type() == expected_type; + let expected_result = Felt::from(type_matches); + has_type |= type_matches; + assert_eq!( process.stack.get(0), expected_result, @@ -193,19 +192,15 @@ fn test_is_faucet_procedure() { for account_id in test_cases.iter() { let account_id = AccountId::try_from(*account_id).unwrap(); - // assembly codes that checks if an account is a faucet let code = format!( " - use.miden::kernels::tx::account - - begin - # push the account id on to the stack - push.{account_id} + use.miden::kernels::tx::account - # execute is_faucet procedure - exec.account::is_faucet - end - ", + begin + push.{account_id} + exec.account::is_faucet + end + ", account_id = account_id, ); @@ -229,29 +224,29 @@ fn test_is_faucet_procedure() { #[test] fn test_get_item() { for storage_item in [AccountStorage::mock_item_0(), AccountStorage::mock_item_1()] { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let code = format!( " - use.miden::account - use.miden::kernels::tx::prologue - - - begin - # prepare the transaction - exec.prologue::prepare_transaction + use.miden::account + use.miden::kernels::tx::prologue - # push the account storage item index - push.{item_index} + begin + exec.prologue::prepare_transaction - # get the item - exec.account::get_item + # push the account storage item index + push.{item_index} - # assert the item value is correct - push.{item_value} assert_eqw - end - ", + # assert the item value is correct + exec.account::get_item + push.{item_value} + assert_eqw + end + ", item_index = storage_item.index, item_value = prepare_word(&storage_item.slot.value) ); @@ -262,8 +257,11 @@ fn test_get_item() { #[test] fn test_set_item() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); // copy the initial account slots (SMT) let mut account_smt = tx_context.account().storage().slots().clone(); @@ -277,33 +275,26 @@ fn test_set_item() { let code = format!( " - use.miden::account - use.miden::kernels::tx::memory - use.miden::kernels::tx::prologue - - begin - # prepare the transaction - exec.prologue::prepare_transaction - - # push the new storage item onto the stack - push.{new_value} - - # push the account storage item index - push.{new_item_index} + use.miden::account + use.miden::kernels::tx::memory + use.miden::kernels::tx::prologue - # get the item - exec.account::set_item + begin + exec.prologue::prepare_transaction - # assert empty old value - padw assert_eqw + # set the storage item + push.{new_value} + push.{new_item_index} + exec.account::set_item - # get the new storage root - exec.memory::get_acct_storage_root + # assert old value was empty + padw assert_eqw - # assert the item value is correct - push.{new_root} assert_eqw - end - ", + # assert the new item value is properly stored + exec.memory::get_acct_storage_root + push.{new_root} assert_eqw + end + ", new_value = prepare_word(&new_item_value), new_item_index = new_item_index.value(), new_root = prepare_word(&account_smt.root()), @@ -320,26 +311,27 @@ fn test_get_storage_data_type() { AccountStorage::mock_item_1(), AccountStorage::mock_item_2(), ] { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let code = format!( " - use.miden::kernels::tx::account - use.miden::kernels::tx::prologue - - begin - # prepare the transaction - exec.prologue::prepare_transaction + use.miden::kernels::tx::account + use.miden::kernels::tx::prologue - # push the account storage item index - push.{item_index} + begin + exec.prologue::prepare_transaction - # get the data type of the respective storage slot - exec.account::get_storage_slot_type_info + # push the account storage item index + push.{item_index} - end - ", + # get the data type of the respective storage slot + exec.account::get_storage_slot_type_info + end + ", item_index = storage_item.index, ); @@ -351,22 +343,31 @@ fn test_get_storage_data_type() { StorageSlotType::Array { value_arity, depth } => (value_arity, depth), }; - assert_eq!(process.get_stack_item(0), Felt::from(storage_slot_data_type.0)); - assert_eq!(process.get_stack_item(1), Felt::from(storage_slot_data_type.1)); - - // check that the rest of the stack is empty - assert_eq!(process.get_stack_item(2), ZERO); - assert_eq!(process.get_stack_item(3), ZERO); - assert_eq!(Word::default(), process.get_stack_word(1)); - assert_eq!(Word::default(), process.get_stack_word(2)); - assert_eq!(Word::default(), process.get_stack_word(3)); + assert_eq!( + process.get_stack_item(0), + Felt::from(storage_slot_data_type.0), + "Arity must match", + ); + assert_eq!( + process.get_stack_item(1), + Felt::from(storage_slot_data_type.1), + "Depth must match", + ); + assert_eq!(process.get_stack_item(2), ZERO, "the rest of the stack is empty"); + assert_eq!(process.get_stack_item(3), ZERO, "the rest of the stack is empty"); + assert_eq!(Word::default(), process.get_stack_word(1), "the rest of the stack is empty"); + assert_eq!(Word::default(), process.get_stack_word(2), "the rest of the stack is empty"); + assert_eq!(Word::default(), process.get_stack_word(3), "the rest of the stack is empty"); } } #[test] fn test_get_map_item() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let storage_item = AccountStorage::mock_item_2(); for (key, value) in STORAGE_LEAVES_2 { @@ -376,31 +377,39 @@ fn test_get_map_item() { use.miden::kernels::tx::prologue begin - # prepare the transaction exec.prologue::prepare_transaction - # push the item's KEY + # get the map item push.{map_key} - - # push the account storage item index push.{item_index} - - # get the map item exec.account::get_map_item - end ", item_index = storage_item.index, map_key = prepare_word(&key), ); - let process = tx_context.execute_code(&code).unwrap(); - assert_eq!(value, process.get_stack_word(0)); - // check that the rest of the stack is empty - assert_eq!(Word::default(), process.get_stack_word(1)); - assert_eq!(Word::default(), process.get_stack_word(2)); - assert_eq!(Word::default(), process.get_stack_word(3)); + assert_eq!( + value, + process.get_stack_word(0), + "get_map_item result doesn't match the expected value", + ); + assert_eq!( + Word::default(), + process.get_stack_word(1), + "The the rest of the stack must be cleared", + ); + assert_eq!( + Word::default(), + process.get_stack_word(2), + "The the rest of the stack must be cleared", + ); + assert_eq!( + Word::default(), + process.get_stack_word(3), + "The the rest of the stack must be cleared", + ); } } @@ -411,8 +420,11 @@ fn test_set_map_item() { [Felt::new(9_u64), Felt::new(10_u64), Felt::new(11_u64), Felt::new(12_u64)], ); - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let storage_item = AccountStorage::mock_item_2(); @@ -422,25 +434,17 @@ fn test_set_map_item() { use.miden::kernels::tx::prologue begin - # prepare the transaction exec.prologue::prepare_transaction - # push the new VALUE + # set the map item push.{new_value} - - # push the new KEY push.{new_key} - - # push the account storage item index push.{item_index} - - # set the map item exec.account::set_map_item # double check that on storage slot is indeed the new map push.{item_index} exec.account::get_item - end ", item_index = storage_item.index, @@ -453,11 +457,16 @@ fn test_set_map_item() { let mut new_storage_map = AccountStorage::mock_map_2(); new_storage_map.insert(new_key, new_value); - // check the new storage root in the process state is what we expect - assert_eq!(new_storage_map.root(), RpoDigest::from(process.get_stack_word(0))); - - // check the old storage root in the process state is what we expect - assert_eq!(storage_item.slot.value, process.get_stack_word(1)); + assert_eq!( + new_storage_map.root(), + RpoDigest::from(process.get_stack_word(0)), + "get_item must return the new updated value", + ); + assert_eq!( + storage_item.slot.value, + process.get_stack_word(1), + "The original value stored in the map doesn't match the expected value", + ); } // ACCOUNT VAULT TESTS @@ -465,25 +474,27 @@ fn test_set_map_item() { #[test] fn test_get_vault_commitment() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let account = tx_context.account(); let code = format!( " - use.miden::account - use.miden::kernels::tx::prologue - - begin - # prepare the transaction - exec.prologue::prepare_transaction - - # push the new storage item onto the stack - exec.account::get_vault_commitment - push.{expected_vault_commitment} - assert_eqw - end - ", + use.miden::account + use.miden::kernels::tx::prologue + + begin + exec.prologue::prepare_transaction + + # push the new storage item onto the stack + exec.account::get_vault_commitment + push.{expected_vault_commitment} + assert_eqw + end + ", expected_vault_commitment = prepare_word(&account.vault().commitment()), ); @@ -495,8 +506,11 @@ fn test_get_vault_commitment() { #[test] fn test_authenticate_procedure() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let account = tx_context.tx_inputs().account(); let proc0_index = LeafIndex::new(0).unwrap(); @@ -509,33 +523,33 @@ fn test_authenticate_procedure() { ]; for (root, valid) in test_cases.into_iter() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let code = format!( - "\ + " use.miden::kernels::tx::account use.miden::kernels::tx::prologue begin - # prepare the transaction exec.prologue::prepare_transaction - # push test procedure root onto stack - push.{root} - # authenticate procedure + push.{root} exec.account::authenticate_procedure end - ", + ", root = prepare_word(&root) ); let process = tx_context.execute_code(&code); match valid { - true => assert!(process.is_ok()), - false => assert!(process.is_err()), + true => assert!(process.is_ok(), "A valid procedure must successfully authenticate"), + false => assert!(process.is_err(), "An invalid procedure must fail to authenticate"), } } } diff --git a/miden-tx/src/tests/kernel_tests/test_asset.rs b/miden-tx/src/tests/kernel_tests/test_asset.rs index 4a023b89f..e22e65a28 100644 --- a/miden-tx/src/tests/kernel_tests/test_asset.rs +++ b/miden-tx/src/tests/kernel_tests/test_asset.rs @@ -4,23 +4,25 @@ use miden_objects::{ }, assets::Asset, testing::{ - account::MockAccountType, - constants::{FUNGIBLE_ASSET_AMOUNT, NON_FUNGIBLE_ASSET_DATA}, + constants::{ + FUNGIBLE_ASSET_AMOUNT, FUNGIBLE_FAUCET_INITIAL_BALANCE, NON_FUNGIBLE_ASSET_DATA, + }, prepare_word, }, }; +use vm_processor::ProcessState; -use super::{Felt, Hasher, ProcessState, Word, ONE}; +use super::{Felt, Hasher, Word, ONE}; use crate::testing::TransactionContextBuilder; #[test] fn test_create_fungible_asset_succeeds() { - let acc_type = MockAccountType::FungibleFaucet { - acct_id: ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN, - nonce: ONE, - empty_reserved_slot: false, - }; - let tx_context = TransactionContextBuilder::with_acc_type(acc_type).build(); + let tx_context = TransactionContextBuilder::with_fungible_faucet( + ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN, + ONE, + Felt::new(FUNGIBLE_FAUCET_INITIAL_BALANCE), + ) + .build(); let code = format!( " @@ -28,13 +30,10 @@ fn test_create_fungible_asset_succeeds() { use.miden::asset begin - # prepare the transaction exec.prologue::prepare_transaction - # push asset amount onto stack - push.{FUNGIBLE_ASSET_AMOUNT} - # create fungible asset + push.{FUNGIBLE_ASSET_AMOUNT} exec.asset::create_fungible_asset end " @@ -55,12 +54,12 @@ fn test_create_fungible_asset_succeeds() { #[test] fn test_create_non_fungible_asset_succeeds() { - let acc_type = MockAccountType::NonFungibleFaucet { - acct_id: ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, - nonce: ONE, - empty_reserved_slot: false, - }; - let tx_context = TransactionContextBuilder::with_acc_type(acc_type).build(); + let tx_context = TransactionContextBuilder::with_non_fungible_faucet( + ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, + ONE, + false, + ) + .build(); let non_fungible_asset = Asset::mock_non_fungible(ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, &NON_FUNGIBLE_ASSET_DATA); @@ -71,7 +70,6 @@ fn test_create_non_fungible_asset_succeeds() { use.miden::asset begin - # prepare the transaction exec.prologue::prepare_transaction # push non-fungible asset data hash onto the stack @@ -89,12 +87,12 @@ fn test_create_non_fungible_asset_succeeds() { #[test] fn test_validate_non_fungible_asset() { - let acc_type = MockAccountType::NonFungibleFaucet { - acct_id: ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, - nonce: ONE, - empty_reserved_slot: false, - }; - let tx_context = TransactionContextBuilder::with_acc_type(acc_type).build(); + let tx_context = TransactionContextBuilder::with_non_fungible_faucet( + ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, + ONE, + false, + ) + .build(); let non_fungible_asset = Asset::mock_non_fungible(ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, &[1, 2, 3]); diff --git a/miden-tx/src/tests/kernel_tests/test_asset_vault.rs b/miden-tx/src/tests/kernel_tests/test_asset_vault.rs index c1fdd2625..3cda16280 100644 --- a/miden-tx/src/tests/kernel_tests/test_asset_vault.rs +++ b/miden-tx/src/tests/kernel_tests/test_asset_vault.rs @@ -4,25 +4,28 @@ use miden_objects::{ account_id::testing::{ ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN, ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN_1, + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, }, AccountId, }, assets::{Asset, FungibleAsset, NonFungibleAsset, NonFungibleAssetDetails}, testing::{ - account::MockAccountType, constants::{FUNGIBLE_ASSET_AMOUNT, NON_FUNGIBLE_ASSET_DATA}, prepare_word, }, AssetVaultError, }; -use super::{ContextId, Felt, ProcessState, Word, ONE, ZERO}; -use crate::testing::TransactionContextBuilder; +use super::{Felt, Word, ONE, ZERO}; +use crate::{testing::TransactionContextBuilder, tests::kernel_tests::read_root_mem_value}; #[test] fn test_get_balance() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let faucet_id: AccountId = ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN.try_into().unwrap(); let code = format!( @@ -35,7 +38,7 @@ fn test_get_balance() { push.{ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN} exec.account::get_balance end - " + " ); let process = tx_context.execute_code(&code).unwrap(); @@ -48,10 +51,13 @@ fn test_get_balance() { #[test] fn test_get_balance_non_fungible_fails() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let code = format!( - r#" + " use.miden::kernels::tx::prologue use.miden::account @@ -60,7 +66,7 @@ fn test_get_balance_non_fungible_fails() { push.{ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN} exec.account::get_balance end - "# + " ); let process = tx_context.execute_code(&code); @@ -70,8 +76,11 @@ fn test_get_balance_non_fungible_fails() { #[test] fn test_has_non_fungible_asset() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let non_fungible_asset = tx_context.account().vault().assets().next().unwrap(); let code = format!( @@ -84,7 +93,7 @@ fn test_has_non_fungible_asset() { push.{non_fungible_asset_key} exec.account::has_non_fungible_asset end - ", + ", non_fungible_asset_key = prepare_word(&non_fungible_asset.vault_key()) ); @@ -95,8 +104,11 @@ fn test_has_non_fungible_asset() { #[test] fn test_add_fungible_asset_success() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let mut account_vault = tx_context.account().vault().clone(); let faucet_id: AccountId = ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN.try_into().unwrap(); let amount = FungibleAsset::MAX_AMOUNT - FUNGIBLE_ASSET_AMOUNT; @@ -113,7 +125,7 @@ fn test_add_fungible_asset_success() { push.{FUNGIBLE_ASSET} exec.account::add_asset end - ", + ", FUNGIBLE_ASSET = prepare_word(&add_fungible_asset.into()) ); @@ -125,15 +137,18 @@ fn test_add_fungible_asset_success() { ); assert_eq!( - process.get_mem_value(ContextId::root(), memory::ACCT_VAULT_ROOT_PTR).unwrap(), + read_root_mem_value(&process, memory::ACCT_VAULT_ROOT_PTR), *account_vault.commitment() ); } #[test] fn test_add_non_fungible_asset_fail_overflow() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let mut account_vault = tx_context.account().vault().clone(); let faucet_id: AccountId = ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN.try_into().unwrap(); @@ -151,7 +166,7 @@ fn test_add_non_fungible_asset_fail_overflow() { push.{FUNGIBLE_ASSET} exec.account::add_asset end - ", + ", FUNGIBLE_ASSET = prepare_word(&add_fungible_asset.into()) ); @@ -163,8 +178,11 @@ fn test_add_non_fungible_asset_fail_overflow() { #[test] fn test_add_non_fungible_asset_success() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let faucet_id: AccountId = ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN.try_into().unwrap(); let mut account_vault = tx_context.account().vault().clone(); let add_non_fungible_asset = Asset::NonFungible( @@ -184,7 +202,7 @@ fn test_add_non_fungible_asset_success() { push.{FUNGIBLE_ASSET} exec.account::add_asset end - ", + ", FUNGIBLE_ASSET = prepare_word(&add_non_fungible_asset.into()) ); @@ -196,15 +214,18 @@ fn test_add_non_fungible_asset_success() { ); assert_eq!( - process.get_mem_value(ContextId::root(), memory::ACCT_VAULT_ROOT_PTR).unwrap(), + read_root_mem_value(&process, memory::ACCT_VAULT_ROOT_PTR), *account_vault.commitment() ); } #[test] fn test_add_non_fungible_asset_fail_duplicate() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let faucet_id: AccountId = ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN.try_into().unwrap(); let mut account_vault = tx_context.account().vault().clone(); let non_fungible_asset_details = @@ -222,7 +243,7 @@ fn test_add_non_fungible_asset_fail_duplicate() { push.{NON_FUNGIBLE_ASSET} exec.account::add_asset end - ", + ", NON_FUNGIBLE_ASSET = prepare_word(&non_fungible_asset.into()) ); @@ -234,8 +255,11 @@ fn test_add_non_fungible_asset_fail_duplicate() { #[test] fn test_remove_fungible_asset_success_no_balance_remaining() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let mut account_vault = tx_context.account().vault().clone(); let faucet_id: AccountId = ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN.try_into().unwrap(); @@ -253,7 +277,7 @@ fn test_remove_fungible_asset_success_no_balance_remaining() { push.{FUNGIBLE_ASSET} exec.account::remove_asset end - ", + ", FUNGIBLE_ASSET = prepare_word(&remove_fungible_asset.into()) ); @@ -265,15 +289,18 @@ fn test_remove_fungible_asset_success_no_balance_remaining() { ); assert_eq!( - process.get_mem_value(ContextId::root(), memory::ACCT_VAULT_ROOT_PTR).unwrap(), + read_root_mem_value(&process, memory::ACCT_VAULT_ROOT_PTR), *account_vault.commitment() ); } #[test] fn test_remove_fungible_asset_fail_remove_too_much() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let faucet_id: AccountId = ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN.try_into().unwrap(); let amount = FUNGIBLE_ASSET_AMOUNT + 1; let remove_fungible_asset = @@ -289,7 +316,7 @@ fn test_remove_fungible_asset_fail_remove_too_much() { push.{FUNGIBLE_ASSET} exec.account::remove_asset end - ", + ", FUNGIBLE_ASSET = prepare_word(&remove_fungible_asset.into()) ); @@ -300,8 +327,11 @@ fn test_remove_fungible_asset_fail_remove_too_much() { #[test] fn test_remove_fungible_asset_success_balance_remaining() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let mut account_vault = tx_context.account().vault().clone(); let faucet_id: AccountId = ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN.try_into().unwrap(); @@ -319,7 +349,7 @@ fn test_remove_fungible_asset_success_balance_remaining() { push.{FUNGIBLE_ASSET} exec.account::remove_asset end - ", + ", FUNGIBLE_ASSET = prepare_word(&remove_fungible_asset.into()) ); @@ -331,15 +361,18 @@ fn test_remove_fungible_asset_success_balance_remaining() { ); assert_eq!( - process.get_mem_value(ContextId::root(), memory::ACCT_VAULT_ROOT_PTR).unwrap(), + read_root_mem_value(&process, memory::ACCT_VAULT_ROOT_PTR), *account_vault.commitment() ); } #[test] fn test_remove_inexisting_non_fungible_asset_fails() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let faucet_id: AccountId = ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN_1.try_into().unwrap(); let mut account_vault = tx_context.account().vault().clone(); @@ -364,7 +397,7 @@ fn test_remove_inexisting_non_fungible_asset_fails() { push.{FUNGIBLE_ASSET} exec.account::remove_asset end - ", + ", FUNGIBLE_ASSET = prepare_word(&non_existent_non_fungible_asset.into()) ); @@ -380,8 +413,11 @@ fn test_remove_inexisting_non_fungible_asset_fails() { #[test] fn test_remove_non_fungible_asset_success() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let faucet_id: AccountId = ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN.try_into().unwrap(); let mut account_vault = tx_context.account().vault().clone(); let non_fungible_asset_details = @@ -399,7 +435,7 @@ fn test_remove_non_fungible_asset_success() { push.{FUNGIBLE_ASSET} exec.account::remove_asset end - ", + ", FUNGIBLE_ASSET = prepare_word(&non_fungible_asset.into()) ); @@ -411,7 +447,7 @@ fn test_remove_non_fungible_asset_success() { ); assert_eq!( - process.get_mem_value(ContextId::root(), memory::ACCT_VAULT_ROOT_PTR).unwrap(), + read_root_mem_value(&process, memory::ACCT_VAULT_ROOT_PTR), *account_vault.commitment() ); } diff --git a/miden-tx/src/tests/kernel_tests/test_epilogue.rs b/miden-tx/src/tests/kernel_tests/test_epilogue.rs index 89404b03d..763cb42dc 100644 --- a/miden-tx/src/tests/kernel_tests/test_epilogue.rs +++ b/miden-tx/src/tests/kernel_tests/test_epilogue.rs @@ -5,13 +5,14 @@ use miden_lib::transaction::{ ToTransactionKernelInputs, }; use miden_objects::testing::notes::AssetPreservationStatus; -use vm_processor::ProcessState; use super::{ - build_module_path, output_notes_data_procedure, ContextId, MemAdviceProvider, TX_KERNEL_DIR, - ZERO, + build_module_path, output_notes_data_procedure, MemAdviceProvider, TX_KERNEL_DIR, ZERO, +}; +use crate::{ + testing::{executor::CodeExecutor, utils::mock_executed_tx}, + tests::kernel_tests::read_root_mem_value, }; -use crate::testing::{executor::CodeExecutor, utils::mock_executed_tx}; const EPILOGUE_FILE: &str = "epilogue.masm"; @@ -88,13 +89,13 @@ fn test_compute_created_note_id() { let imports = "use.miden::kernels::tx::prologue\n"; let test = format!( " - {output_notes_data_procedure} - begin - exec.prologue::prepare_transaction - exec.create_mock_notes - exec.finalize_transaction - end - " + {output_notes_data_procedure} + begin + exec.prologue::prepare_transaction + exec.create_mock_notes + exec.finalize_transaction + end + " ); let (stack_inputs, advice_inputs) = executed_transaction.get_kernel_inputs(); @@ -105,21 +106,25 @@ fn test_compute_created_note_id() { .run(&test) .unwrap(); - // assert the note asset hash is correct let expected_asset_hash = note.assets().expect("Output note should be full note").commitment(); let asset_hash_memory_address = CREATED_NOTE_SECTION_OFFSET + i * NOTE_MEM_SIZE + CREATED_NOTE_ASSET_HASH_OFFSET; - let actual_asset_hash = - process.get_mem_value(ContextId::root(), asset_hash_memory_address).unwrap(); - assert_eq!(expected_asset_hash.as_elements(), actual_asset_hash); + let actual_asset_hash = read_root_mem_value(&process, asset_hash_memory_address); + assert_eq!( + expected_asset_hash.as_elements(), + actual_asset_hash, + "Asset hash didn't match expected value" + ); - // assert the note ID is correct let expected_id = note.id(); let note_id_memory_address = CREATED_NOTE_SECTION_OFFSET + i * NOTE_MEM_SIZE; - let actual_note_id = - process.get_mem_value(ContextId::root(), note_id_memory_address).unwrap(); - assert_eq!(&actual_note_id, expected_id.as_elements()); + let actual_note_id = read_root_mem_value(&process, note_id_memory_address); + assert_eq!( + &actual_note_id, + expected_id.as_elements(), + "note id didn't match expected value" + ); } } @@ -137,14 +142,15 @@ fn test_epilogue_asset_preservation_violation() { let imports = "use.miden::kernels::tx::prologue\n"; let code = format!( " - {output_notes_data_procedure} - begin - exec.prologue::prepare_transaction - exec.create_mock_notes - push.1 exec.account::incr_nonce - exec.finalize_transaction - end - " + {output_notes_data_procedure} + begin + exec.prologue::prepare_transaction + exec.create_mock_notes + push.1 + exec.account::incr_nonce + exec.finalize_transaction + end + " ); let (stack_inputs, advice_inputs) = executed_transaction.get_kernel_inputs(); @@ -154,8 +160,7 @@ fn test_epilogue_asset_preservation_violation() { .stack_inputs(stack_inputs) .run(&code); - // assert the process results in error - assert!(process.is_err()); + assert!(process.is_err(), "Violating asset preservation must result in a failure"); } } @@ -172,9 +177,17 @@ fn test_epilogue_increment_nonce_success() { {output_notes_data_procedure} begin exec.prologue::prepare_transaction + exec.create_mock_notes - push.1.2.3.4 push.0 exec.account::set_item dropw - push.1 exec.account::incr_nonce + + push.1.2.3.4 + push.0 + exec.account::set_item + dropw + + push.1 + exec.account::incr_nonce + exec.finalize_transaction end " @@ -202,8 +215,14 @@ fn test_epilogue_increment_nonce_violation() { {output_notes_data_procedure} begin exec.prologue::prepare_transaction + exec.create_mock_notes - push.1.2.3.4 push.0 exec.account::set_item dropw + + push.1.2.3.4 + push.0 + exec.account::set_item + dropw + exec.finalize_transaction end " diff --git a/miden-tx/src/tests/kernel_tests/test_faucet.rs b/miden-tx/src/tests/kernel_tests/test_faucet.rs index b0a850717..3abfe3c41 100644 --- a/miden-tx/src/tests/kernel_tests/test_faucet.rs +++ b/miden-tx/src/tests/kernel_tests/test_faucet.rs @@ -2,10 +2,10 @@ use miden_objects::{ accounts::account_id::testing::{ ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN, ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_1, ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN_1, + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, }, assets::{Asset, FungibleAsset}, testing::{ - account::MockAccountType, constants::{ CONSUMED_ASSET_1_AMOUNT, FUNGIBLE_ASSET_AMOUNT, FUNGIBLE_FAUCET_INITIAL_BALANCE, NON_FUNGIBLE_ASSET_DATA, NON_FUNGIBLE_ASSET_DATA_2, @@ -15,19 +15,21 @@ use miden_objects::{ storage::FAUCET_STORAGE_DATA_SLOT, }, }; +use vm_processor::Felt; use super::ONE; use crate::testing::TransactionContextBuilder; + // FUNGIBLE FAUCET MINT TESTS // ================================================================================================ #[test] fn test_mint_fungible_asset_succeeds() { - let tx_context = TransactionContextBuilder::with_acc_type(MockAccountType::FungibleFaucet { - acct_id: ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN, - nonce: ONE, - empty_reserved_slot: false, - }) + let tx_context = TransactionContextBuilder::with_fungible_faucet( + ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN, + ONE, + Felt::new(FUNGIBLE_FAUCET_INITIAL_BALANCE), + ) .build(); let code = format!( @@ -69,15 +71,18 @@ fn test_mint_fungible_asset_succeeds() { #[test] fn test_mint_fungible_asset_fails_not_faucet_account() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); + let code = format!( " use.miden::kernels::tx::prologue use.miden::faucet begin - # mint asset exec.prologue::prepare_transaction push.{FUNGIBLE_ASSET_AMOUNT}.0.0.{ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN} exec.faucet::mint @@ -92,8 +97,11 @@ fn test_mint_fungible_asset_fails_not_faucet_account() { #[test] fn test_mint_fungible_asset_inconsistent_faucet_id() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let code = format!( " @@ -101,7 +109,6 @@ fn test_mint_fungible_asset_inconsistent_faucet_id() { use.miden::faucet begin - # mint asset exec.prologue::prepare_transaction push.{FUNGIBLE_ASSET_AMOUNT}.0.0.{ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_1} exec.faucet::mint @@ -116,8 +123,11 @@ fn test_mint_fungible_asset_inconsistent_faucet_id() { #[test] fn test_mint_fungible_asset_fails_saturate_max_amount() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let code = format!( " @@ -125,7 +135,6 @@ fn test_mint_fungible_asset_fails_saturate_max_amount() { use.miden::faucet begin - # mint asset exec.prologue::prepare_transaction push.{saturating_amount}.0.0.{ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN} exec.faucet::mint @@ -146,13 +155,13 @@ fn test_mint_fungible_asset_fails_saturate_max_amount() { #[ignore] #[test] fn test_mint_non_fungible_asset_succeeds() { - let acc_type = MockAccountType::NonFungibleFaucet { - acct_id: ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, - nonce: ONE, - empty_reserved_slot: false, - }; + let tx_context = TransactionContextBuilder::with_non_fungible_faucet( + ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, + ONE, + false, + ) + .build(); - let tx_context = TransactionContextBuilder::with_acc_type(acc_type).build(); let non_fungible_asset = Asset::mock_non_fungible(ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, &NON_FUNGIBLE_ASSET_DATA); @@ -199,8 +208,11 @@ fn test_mint_non_fungible_asset_succeeds() { #[test] fn test_mint_non_fungible_asset_fails_not_faucet_account() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let non_fungible_asset = Asset::mock_non_fungible(ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, &[1, 2, 3, 4]); @@ -211,7 +223,6 @@ fn test_mint_non_fungible_asset_fails_not_faucet_account() { use.miden::faucet begin - # mint asset exec.prologue::prepare_transaction push.{non_fungible_asset} exec.faucet::mint @@ -227,8 +238,11 @@ fn test_mint_non_fungible_asset_fails_not_faucet_account() { #[test] fn test_mint_non_fungible_asset_fails_inconsistent_faucet_id() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let non_fungible_asset = Asset::mock_non_fungible(ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN_1, &[1, 2, 3, 4]); @@ -239,7 +253,6 @@ fn test_mint_non_fungible_asset_fails_inconsistent_faucet_id() { use.miden::faucet begin - # mint asset exec.prologue::prepare_transaction push.{non_fungible_asset} exec.faucet::mint @@ -255,13 +268,12 @@ fn test_mint_non_fungible_asset_fails_inconsistent_faucet_id() { #[test] fn test_mint_non_fungible_asset_fails_asset_already_exists() { - let acc_type = MockAccountType::NonFungibleFaucet { - acct_id: ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, - nonce: ONE, - empty_reserved_slot: false, - }; - - let tx_context = TransactionContextBuilder::with_acc_type(acc_type).build(); + let tx_context = TransactionContextBuilder::with_non_fungible_faucet( + ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, + ONE, + false, + ) + .build(); let non_fungible_asset = Asset::mock_non_fungible( ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, @@ -274,7 +286,6 @@ fn test_mint_non_fungible_asset_fails_asset_already_exists() { use.miden::faucet begin - # mint asset exec.prologue::prepare_transaction push.{non_fungible_asset} exec.faucet::mint @@ -293,15 +304,13 @@ fn test_mint_non_fungible_asset_fails_asset_already_exists() { #[test] fn test_burn_fungible_asset_succeeds() { - let acc_type = MockAccountType::FungibleFaucet { - acct_id: ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_1, - nonce: ONE, - empty_reserved_slot: false, - }; - - let tx_context = TransactionContextBuilder::with_acc_type(acc_type) - .with_mock_notes(AssetPreservationStatus::Preserved) - .build(); + let tx_context = TransactionContextBuilder::with_fungible_faucet( + ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_1, + ONE, + Felt::new(FUNGIBLE_FAUCET_INITIAL_BALANCE), + ) + .with_mock_notes(AssetPreservationStatus::Preserved) + .build(); let code = format!( " @@ -343,8 +352,11 @@ fn test_burn_fungible_asset_succeeds() { #[test] fn test_burn_fungible_asset_fails_not_faucet_account() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let code = format!( " @@ -352,7 +364,6 @@ fn test_burn_fungible_asset_fails_not_faucet_account() { use.miden::faucet begin - # mint asset exec.prologue::prepare_transaction push.{FUNGIBLE_ASSET_AMOUNT}.0.0.{ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_1} exec.faucet::burn @@ -367,13 +378,12 @@ fn test_burn_fungible_asset_fails_not_faucet_account() { #[test] fn test_burn_fungible_asset_inconsistent_faucet_id() { - let acc_type = MockAccountType::NonFungibleFaucet { - acct_id: ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN, - nonce: ONE, - empty_reserved_slot: false, - }; - - let tx_context = TransactionContextBuilder::with_acc_type(acc_type).build(); + let tx_context = TransactionContextBuilder::with_non_fungible_faucet( + ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN, + ONE, + false, + ) + .build(); let code = format!( " @@ -381,7 +391,6 @@ fn test_burn_fungible_asset_inconsistent_faucet_id() { use.miden::faucet begin - # mint asset exec.prologue::prepare_transaction push.{FUNGIBLE_ASSET_AMOUNT}.0.0.{ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_1} exec.faucet::burn @@ -395,13 +404,12 @@ fn test_burn_fungible_asset_inconsistent_faucet_id() { #[test] fn test_burn_fungible_asset_insufficient_input_amount() { - let acc_type = MockAccountType::NonFungibleFaucet { - acct_id: ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_1, - nonce: ONE, - empty_reserved_slot: false, - }; - - let tx_context = TransactionContextBuilder::with_acc_type(acc_type).build(); + let tx_context = TransactionContextBuilder::with_non_fungible_faucet( + ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_1, + ONE, + false, + ) + .build(); let code = format!( " @@ -409,7 +417,6 @@ fn test_burn_fungible_asset_insufficient_input_amount() { use.miden::faucet begin - # mint asset exec.prologue::prepare_transaction push.{saturating_amount}.0.0.{ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_1} exec.faucet::burn @@ -430,13 +437,12 @@ fn test_burn_fungible_asset_insufficient_input_amount() { #[ignore] #[test] fn test_burn_non_fungible_asset_succeeds() { - let acc_type = MockAccountType::NonFungibleFaucet { - acct_id: ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, - nonce: ONE, - empty_reserved_slot: false, - }; - - let tx_context = TransactionContextBuilder::with_acc_type(acc_type).build(); + let tx_context = TransactionContextBuilder::with_non_fungible_faucet( + ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, + ONE, + false, + ) + .build(); let non_fungible_asset_burnt = Asset::mock_non_fungible(ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, &[1, 2, 3]); @@ -452,7 +458,7 @@ fn test_burn_non_fungible_asset_succeeds() { use.miden::faucet begin - # mint asset + # burn asset exec.prologue::prepare_transaction push.{non_fungible_asset} exec.faucet::burn @@ -484,13 +490,12 @@ fn test_burn_non_fungible_asset_succeeds() { #[test] fn test_burn_non_fungible_asset_fails_does_not_exist() { - let acc_type = MockAccountType::NonFungibleFaucet { - acct_id: ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, - nonce: ONE, - empty_reserved_slot: false, - }; - - let tx_context = TransactionContextBuilder::with_acc_type(acc_type).build(); + let tx_context = TransactionContextBuilder::with_non_fungible_faucet( + ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, + ONE, + false, + ) + .build(); let non_fungible_asset_burnt = Asset::mock_non_fungible(ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, &[1, 2, 3]); @@ -506,7 +511,7 @@ fn test_burn_non_fungible_asset_fails_does_not_exist() { use.miden::faucet begin - # mint asset + # burn asset exec.prologue::prepare_transaction push.{non_fungible_asset} exec.faucet::burn @@ -522,8 +527,11 @@ fn test_burn_non_fungible_asset_fails_does_not_exist() { #[test] fn test_burn_non_fungible_asset_fails_not_faucet_account() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let non_fungible_asset_burnt = Asset::mock_non_fungible(ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, &[1, 2, 3]); @@ -539,7 +547,7 @@ fn test_burn_non_fungible_asset_fails_not_faucet_account() { use.miden::faucet begin - # mint asset + # burn asset exec.prologue::prepare_transaction push.{non_fungible_asset} exec.faucet::burn @@ -555,13 +563,12 @@ fn test_burn_non_fungible_asset_fails_not_faucet_account() { #[test] fn test_burn_non_fungible_asset_fails_inconsistent_faucet_id() { - let acc_type = MockAccountType::NonFungibleFaucet { - acct_id: ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, - nonce: ONE, - empty_reserved_slot: false, - }; - - let tx_context = TransactionContextBuilder::with_acc_type(acc_type).build(); + let tx_context = TransactionContextBuilder::with_non_fungible_faucet( + ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, + ONE, + false, + ) + .build(); let non_fungible_asset_burnt = Asset::mock_non_fungible(ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN_1, &[1, 2, 3]); @@ -577,7 +584,7 @@ fn test_burn_non_fungible_asset_fails_inconsistent_faucet_id() { use.miden::faucet begin - # mint asset + # burn asset exec.prologue::prepare_transaction push.{non_fungible_asset} exec.faucet::burn @@ -596,32 +603,30 @@ fn test_burn_non_fungible_asset_fails_inconsistent_faucet_id() { #[test] fn test_get_total_issuance_succeeds() { - let acc_type = MockAccountType::FungibleFaucet { - acct_id: ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN, - nonce: ONE, - empty_reserved_slot: false, - }; - - let tx_context = TransactionContextBuilder::with_acc_type(acc_type).build(); + let tx_context = TransactionContextBuilder::with_fungible_faucet( + ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN, + ONE, + Felt::new(FUNGIBLE_FAUCET_INITIAL_BALANCE), + ) + .build(); let code = format!( - "\ - use.miden::kernels::tx::prologue - use.miden::faucet - - begin - # prepare the transaction - exec.prologue::prepare_transaction - - # get the fungible faucet balance - exec.faucet::get_total_issuance - # => [total_issuance] - - # assert the correct balance is returned - push.{FUNGIBLE_FAUCET_INITIAL_BALANCE} assert_eq - # => [] - end - ", + " + use.miden::kernels::tx::prologue + use.miden::faucet + + begin + exec.prologue::prepare_transaction + + # get the fungible faucet balance + exec.faucet::get_total_issuance + # => [total_issuance] + + # assert the correct balance is returned + push.{FUNGIBLE_FAUCET_INITIAL_BALANCE} assert_eq + # => [] + end + ", ); tx_context.execute_code(&code).unwrap(); diff --git a/miden-tx/src/tests/kernel_tests/test_note.rs b/miden-tx/src/tests/kernel_tests/test_note.rs index 0b6a6b95e..e117c3a52 100644 --- a/miden-tx/src/tests/kernel_tests/test_note.rs +++ b/miden-tx/src/tests/kernel_tests/test_note.rs @@ -2,20 +2,29 @@ use alloc::{collections::BTreeMap, string::String}; use miden_lib::transaction::memory::CURRENT_CONSUMED_NOTE_PTR; use miden_objects::{ + accounts::account_id::testing::ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, notes::Note, - testing::{account::MockAccountType, notes::AssetPreservationStatus, prepare_word}, - transaction::{PreparedTransaction, TransactionArgs}, + testing::{notes::AssetPreservationStatus, prepare_word}, + transaction::TransactionArgs, WORD_SIZE, }; -use vm_processor::EMPTY_WORD; - -use super::{ContextId, Felt, Process, ProcessState, ZERO}; -use crate::testing::{utils::consumed_note_data_ptr, MockHost, TransactionContextBuilder}; +use vm_processor::{EMPTY_WORD, ONE}; + +use super::{Felt, Process, ZERO}; +use crate::{ + testing::{ + utils::consumed_note_data_ptr, MockHost, TransactionContext, TransactionContextBuilder, + }, + tests::kernel_tests::read_root_mem_value, +}; #[test] fn test_get_sender_no_sender() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); // calling get_sender should return sender let code = " use.miden::kernels::tx::memory @@ -40,9 +49,12 @@ fn test_get_sender_no_sender() { #[test] fn test_get_sender() { - let tx_context = TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting) - .with_mock_notes(AssetPreservationStatus::Preserved) - .build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .with_mock_notes(AssetPreservationStatus::Preserved) + .build(); // calling get_sender should return sender let code = " @@ -66,9 +78,12 @@ fn test_get_sender() { #[test] fn test_get_vault_data() { - let tx_context = TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting) - .with_mock_notes(AssetPreservationStatus::Preserved) - .build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .with_mock_notes(AssetPreservationStatus::Preserved) + .build(); let notes = tx_context.input_notes(); @@ -115,9 +130,12 @@ fn test_get_vault_data() { } #[test] fn test_get_assets() { - let tx_context = TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting) - .with_mock_notes(AssetPreservationStatus::Preserved) - .build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .with_mock_notes(AssetPreservationStatus::Preserved) + .build(); let notes = tx_context.input_notes(); @@ -222,9 +240,12 @@ fn test_get_assets() { #[test] fn test_get_inputs() { - let tx_context = TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting) - .with_mock_notes(AssetPreservationStatus::Preserved) - .build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .with_mock_notes(AssetPreservationStatus::Preserved) + .build(); let notes = tx_context.mock_chain().available_notes(); @@ -293,9 +314,12 @@ fn test_get_inputs() { #[test] fn test_note_setup() { - let tx_context = TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting) - .with_mock_notes(AssetPreservationStatus::Preserved) - .build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .with_mock_notes(AssetPreservationStatus::Preserved) + .build(); let code = " use.miden::kernels::tx::prologue @@ -307,10 +331,9 @@ fn test_note_setup() { end "; - let prepared_tx = tx_context.get_prepared_transaction(code); let process = tx_context.execute_code(code).unwrap(); - note_setup_stack_assertions(&process, &prepared_tx); + note_setup_stack_assertions(&process, &tx_context); note_setup_memory_assertions(&process); } @@ -321,10 +344,12 @@ fn test_note_script_and_note_args() { [Felt::new(92), Felt::new(92), Felt::new(92), Felt::new(92)], ]; - let mut tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting) - .with_mock_notes(AssetPreservationStatus::Preserved) - .build(); + let mut tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .with_mock_notes(AssetPreservationStatus::Preserved) + .build(); let code = " use.miden::kernels::tx::prologue @@ -356,7 +381,7 @@ fn test_note_script_and_note_args() { assert_eq!(process.stack.get_word(1), note_args[1]); } -fn note_setup_stack_assertions(process: &Process, inputs: &PreparedTransaction) { +fn note_setup_stack_assertions(process: &Process, inputs: &TransactionContext) { let mut expected_stack = [ZERO; 16]; // replace the top four elements with the tx script root @@ -371,16 +396,19 @@ fn note_setup_stack_assertions(process: &Process, inputs: &PreparedTra fn note_setup_memory_assertions(process: &Process) { // assert that the correct pointer is stored in bookkeeping memory assert_eq!( - process.get_mem_value(ContextId::root(), CURRENT_CONSUMED_NOTE_PTR).unwrap()[0], + read_root_mem_value(process, CURRENT_CONSUMED_NOTE_PTR)[0], Felt::from(consumed_note_data_ptr(0)) ); } #[test] fn test_get_note_serial_number() { - let tx_context = TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting) - .with_mock_notes(AssetPreservationStatus::Preserved) - .build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .with_mock_notes(AssetPreservationStatus::Preserved) + .build(); // calling get_serial_number should return the serial number of the note let code = " diff --git a/miden-tx/src/tests/kernel_tests/test_prologue.rs b/miden-tx/src/tests/kernel_tests/test_prologue.rs index 408b57911..bd54824f1 100644 --- a/miden-tx/src/tests/kernel_tests/test_prologue.rs +++ b/miden-tx/src/tests/kernel_tests/test_prologue.rs @@ -17,19 +17,25 @@ use miden_lib::transaction::{ TransactionKernel, }; use miden_objects::{ + accounts::account_id::testing::ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, assembly::ProgramAst, testing::{ - account::MockAccountType, + constants::FUNGIBLE_FAUCET_INITIAL_BALANCE, notes::AssetPreservationStatus, storage::{generate_account_seed, AccountSeedType}, }, - transaction::{PreparedTransaction, TransactionArgs, TransactionScript}, + transaction::{TransactionArgs, TransactionScript}, Digest, FieldElement, }; -use vm_processor::AdviceInputs; +use vm_processor::{AdviceInputs, ONE}; -use super::{build_module_path, ContextId, Felt, Process, ProcessState, Word, TX_KERNEL_DIR, ZERO}; -use crate::testing::{utils::consumed_note_data_ptr, MockHost, TransactionContextBuilder}; +use super::{build_module_path, Felt, Process, Word, TX_KERNEL_DIR, ZERO}; +use crate::{ + testing::{ + utils::consumed_note_data_ptr, MockHost, TransactionContext, TransactionContextBuilder, + }, + tests::kernel_tests::read_root_mem_value, +}; const PROLOGUE_FILE: &str = "prologue.masm"; @@ -53,10 +59,12 @@ fn insert_prologue(code: &str) -> String { #[test] fn test_transaction_prologue() { - let mut tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting) - .with_mock_notes(AssetPreservationStatus::Preserved) - .build(); + let mut tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .with_mock_notes(AssetPreservationStatus::Preserved) + .build(); let code = " begin @@ -69,12 +77,15 @@ fn test_transaction_prologue() { begin push.1.2.3.4 dropw end - ", + ", + ) + .unwrap(); + let (tx_script, _) = TransactionScript::new( + mock_tx_script_code, + vec![], + &TransactionKernel::assembler().with_debug_mode(true), ) .unwrap(); - let (tx_script, _) = - TransactionScript::new(mock_tx_script_code, vec![], &TransactionKernel::assembler()) - .unwrap(); let code = insert_prologue(code); @@ -95,20 +106,19 @@ fn test_transaction_prologue() { ); tx_context.set_tx_args(tx_args); - let transaction = tx_context.get_prepared_transaction(&code); - let process = tx_context.execute_transaction(&transaction).unwrap(); - - global_input_memory_assertions(&process, &transaction); - block_data_memory_assertions(&process, &transaction); - chain_mmr_memory_assertions(&process, &transaction); - account_data_memory_assertions(&process, &transaction); - consumed_notes_memory_assertions(&process, &transaction, ¬e_args); + let process = tx_context.execute_code(&code).unwrap(); + + global_input_memory_assertions(&process, &tx_context); + block_data_memory_assertions(&process, &tx_context); + chain_mmr_memory_assertions(&process, &tx_context); + account_data_memory_assertions(&process, &tx_context); + consumed_notes_memory_assertions(&process, &tx_context, ¬e_args); } -fn global_input_memory_assertions(process: &Process, inputs: &PreparedTransaction) { +fn global_input_memory_assertions(process: &Process, inputs: &TransactionContext) { assert_eq!( read_root_mem_value(process, BLK_HASH_PTR), - inputs.block_header().hash().as_elements(), + inputs.tx_inputs().block_header().hash().as_elements(), "The block hash should be stored at the BLK_HASH_PTR" ); @@ -143,75 +153,75 @@ fn global_input_memory_assertions(process: &Process, inputs: &Prepared ); } -fn block_data_memory_assertions(process: &Process, inputs: &PreparedTransaction) { +fn block_data_memory_assertions(process: &Process, inputs: &TransactionContext) { assert_eq!( read_root_mem_value(process, BLK_HASH_PTR), - inputs.block_header().hash().as_elements(), + inputs.tx_inputs().block_header().hash().as_elements(), "The block hash should be stored at the BLK_HASH_PTR" ); assert_eq!( read_root_mem_value(process, PREV_BLOCK_HASH_PTR), - inputs.block_header().prev_hash().as_elements(), + inputs.tx_inputs().block_header().prev_hash().as_elements(), "The previous block hash should be stored at the PREV_BLK_HASH_PTR" ); assert_eq!( read_root_mem_value(process, CHAIN_ROOT_PTR), - inputs.block_header().chain_root().as_elements(), + inputs.tx_inputs().block_header().chain_root().as_elements(), "The chain root should be stored at the CHAIN_ROOT_PTR" ); assert_eq!( read_root_mem_value(process, ACCT_DB_ROOT_PTR), - inputs.block_header().account_root().as_elements(), + inputs.tx_inputs().block_header().account_root().as_elements(), "The account db root should be stored at the ACCT_DB_ROOT_PRT" ); assert_eq!( read_root_mem_value(process, NULLIFIER_DB_ROOT_PTR), - inputs.block_header().nullifier_root().as_elements(), + inputs.tx_inputs().block_header().nullifier_root().as_elements(), "The nullifier db root should be stored at the NULLIFIER_DB_ROOT_PTR" ); assert_eq!( read_root_mem_value(process, TX_HASH_PTR), - inputs.block_header().tx_hash().as_elements(), + inputs.tx_inputs().block_header().tx_hash().as_elements(), "The TX hash should be stored at the TX_HASH_PTR" ); assert_eq!( read_root_mem_value(process, NOTE_ROOT_PTR), - inputs.block_header().note_root().as_elements(), + inputs.tx_inputs().block_header().note_root().as_elements(), "The note root should be stored at the NOTE_ROOT_PTR" ); assert_eq!( read_root_mem_value(process, PROOF_HASH_PTR), - inputs.block_header().proof_hash().as_elements(), + inputs.tx_inputs().block_header().proof_hash().as_elements(), "The proof hash should be stored at the PROOF_HASH_PTR" ); assert_eq!( read_root_mem_value(process, BLOCK_METADATA_PTR)[BLOCK_NUMBER_IDX], - inputs.block_header().block_num().into(), + inputs.tx_inputs().block_header().block_num().into(), "The block number should be stored at BLOCK_METADATA_PTR[BLOCK_NUMBER_IDX]" ); assert_eq!( read_root_mem_value(process, BLOCK_METADATA_PTR)[PROTOCOL_VERSION_IDX], - inputs.block_header().version().into(), + inputs.tx_inputs().block_header().version().into(), "The protocol version should be stored at BLOCK_METADATA_PTR[PROTOCOL_VERSION_IDX]" ); assert_eq!( read_root_mem_value(process, BLOCK_METADATA_PTR)[TIMESTAMP_IDX], - inputs.block_header().timestamp().into(), + inputs.tx_inputs().block_header().timestamp().into(), "The timestamp should be stored at BLOCK_METADATA_PTR[TIMESTAMP_IDX]" ); } -fn chain_mmr_memory_assertions(process: &Process, prepared_tx: &PreparedTransaction) { +fn chain_mmr_memory_assertions(process: &Process, prepared_tx: &TransactionContext) { // update the chain MMR to point to the block against which this transaction is being executed let mut chain_mmr = prepared_tx.tx_inputs().block_chain().clone(); chain_mmr.add_block(*prepared_tx.tx_inputs().block_header(), true); @@ -231,7 +241,7 @@ fn chain_mmr_memory_assertions(process: &Process, prepared_tx: &Prepar } } -fn account_data_memory_assertions(process: &Process, inputs: &PreparedTransaction) { +fn account_data_memory_assertions(process: &Process, inputs: &TransactionContext) { assert_eq!( read_root_mem_value(process, ACCT_ID_AND_NONCE_PTR), [inputs.account().id().into(), ZERO, ZERO, inputs.account().nonce()], @@ -273,7 +283,7 @@ fn account_data_memory_assertions(process: &Process, inputs: &Prepared fn consumed_notes_memory_assertions( process: &Process, - inputs: &PreparedTransaction, + inputs: &TransactionContext, note_args: &[[Felt; 4]], ) { assert_eq!( @@ -354,13 +364,12 @@ fn consumed_notes_memory_assertions( pub fn test_prologue_create_account() { let (acct_id, account_seed) = generate_account_seed( AccountSeedType::RegularAccountUpdatableCodeOnChain, - &TransactionKernel::assembler(), + &TransactionKernel::assembler().with_debug_mode(true), ); - let tx_context = TransactionContextBuilder::with_acc_type(MockAccountType::StandardNew { - account_id: acct_id.into(), - }) - .account_seed(account_seed) - .build(); + let tx_context = TransactionContextBuilder::with_standard_account(acct_id.into(), ZERO) + .account_seed(account_seed) + .build(); + let code = " use.miden::kernels::tx::prologue @@ -377,16 +386,13 @@ pub fn test_prologue_create_account() { pub fn test_prologue_create_account_valid_fungible_faucet_reserved_slot() { let (acct_id, account_seed) = generate_account_seed( AccountSeedType::FungibleFaucetValidInitialBalance, - &TransactionKernel::assembler(), + &TransactionKernel::assembler().with_debug_mode(true), ); - let tx_context = TransactionContextBuilder::with_acc_type(MockAccountType::FungibleFaucet { - acct_id: acct_id.into(), - nonce: Felt::ZERO, - empty_reserved_slot: true, - }) - .account_seed(account_seed) - .build(); + let tx_context = + TransactionContextBuilder::with_fungible_faucet(acct_id.into(), Felt::ZERO, ZERO) + .account_seed(account_seed) + .build(); let code = " use.miden::kernels::tx::prologue @@ -405,14 +411,14 @@ pub fn test_prologue_create_account_valid_fungible_faucet_reserved_slot() { pub fn test_prologue_create_account_invalid_fungible_faucet_reserved_slot() { let (acct_id, account_seed) = generate_account_seed( AccountSeedType::FungibleFaucetInvalidInitialBalance, - &TransactionKernel::assembler(), + &TransactionKernel::assembler().with_debug_mode(true), ); - let tx_context = TransactionContextBuilder::with_acc_type(MockAccountType::FungibleFaucet { - acct_id: acct_id.into(), - nonce: Felt::ZERO, - empty_reserved_slot: false, - }) + let tx_context = TransactionContextBuilder::with_fungible_faucet( + acct_id.into(), + Felt::ZERO, + Felt::new(FUNGIBLE_FAUCET_INITIAL_BALANCE), + ) .account_seed(account_seed) .build(); @@ -433,16 +439,13 @@ pub fn test_prologue_create_account_invalid_fungible_faucet_reserved_slot() { pub fn test_prologue_create_account_valid_non_fungible_faucet_reserved_slot() { let (acct_id, account_seed) = generate_account_seed( AccountSeedType::NonFungibleFaucetValidReservedSlot, - &TransactionKernel::assembler(), + &TransactionKernel::assembler().with_debug_mode(true), ); - let tx_context = TransactionContextBuilder::with_acc_type(MockAccountType::NonFungibleFaucet { - acct_id: acct_id.into(), - nonce: Felt::ZERO, - empty_reserved_slot: true, - }) - .account_seed(account_seed) - .build(); + let tx_context = + TransactionContextBuilder::with_non_fungible_faucet(acct_id.into(), Felt::ZERO, true) + .account_seed(account_seed) + .build(); let code = " use.miden::kernels::tx::prologue @@ -462,16 +465,13 @@ pub fn test_prologue_create_account_valid_non_fungible_faucet_reserved_slot() { pub fn test_prologue_create_account_invalid_non_fungible_faucet_reserved_slot() { let (acct_id, account_seed) = generate_account_seed( AccountSeedType::NonFungibleFaucetInvalidReservedSlot, - &TransactionKernel::assembler(), + &TransactionKernel::assembler().with_debug_mode(true), ); - let tx_context = TransactionContextBuilder::with_acc_type(MockAccountType::NonFungibleFaucet { - acct_id: acct_id.into(), - nonce: Felt::ZERO, - empty_reserved_slot: false, - }) - .account_seed(account_seed) - .build(); + let tx_context = + TransactionContextBuilder::with_non_fungible_faucet(acct_id.into(), Felt::ZERO, false) + .account_seed(account_seed) + .build(); let code = " use.miden::kernels::tx::prologue @@ -491,7 +491,7 @@ pub fn test_prologue_create_account_invalid_non_fungible_faucet_reserved_slot() pub fn test_prologue_create_account_invalid_seed() { let (acct_id, account_seed) = generate_account_seed( AccountSeedType::RegularAccountUpdatableCodeOnChain, - &TransactionKernel::assembler(), + &TransactionKernel::assembler().with_debug_mode(true), ); let code = " @@ -507,12 +507,10 @@ pub fn test_prologue_create_account_invalid_seed() { let adv_inputs = AdviceInputs::default().with_map([(Digest::from(account_seed_key), vec![ZERO; 4])]); - let tx_context = TransactionContextBuilder::with_acc_type(MockAccountType::StandardNew { - account_id: acct_id.into(), - }) - .account_seed(account_seed) - .advice_inputs(adv_inputs) - .build(); + let tx_context = TransactionContextBuilder::with_standard_account(acct_id.into(), ZERO) + .account_seed(account_seed) + .advice_inputs(adv_inputs) + .build(); let process = tx_context.execute_code(code); assert!(process.is_err()); @@ -520,8 +518,11 @@ pub fn test_prologue_create_account_invalid_seed() { #[test] fn test_get_blk_version() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let code = " use.miden::kernels::tx::memory use.miden::kernels::tx::prologue @@ -539,8 +540,11 @@ fn test_get_blk_version() { #[test] fn test_get_blk_timestamp() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let code = " use.miden::kernels::tx::memory use.miden::kernels::tx::prologue @@ -559,10 +563,6 @@ fn test_get_blk_timestamp() { // HELPER FUNCTIONS // ================================================================================================ -fn read_root_mem_value(process: &Process, addr: u32) -> Word { - process.get_mem_value(ContextId::root(), addr).unwrap() -} - fn read_note_element(process: &Process, note_idx: u32, offset: MemoryOffset) -> Word { read_root_mem_value(process, consumed_note_data_ptr(note_idx) + offset) } diff --git a/miden-tx/src/tests/kernel_tests/test_tx.rs b/miden-tx/src/tests/kernel_tests/test_tx.rs index e897b785b..637420953 100644 --- a/miden-tx/src/tests/kernel_tests/test_tx.rs +++ b/miden-tx/src/tests/kernel_tests/test_tx.rs @@ -8,23 +8,27 @@ use miden_objects::{ accounts::account_id::testing::{ ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN, ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_2, ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, }, assets::Asset, notes::{Note, NoteAssets, NoteInputs, NoteMetadata, NoteRecipient, NoteType}, - testing::{ - account::MockAccountType, constants::NON_FUNGIBLE_ASSET_DATA_2, - notes::AssetPreservationStatus, prepare_word, - }, + testing::{constants::NON_FUNGIBLE_ASSET_DATA_2, notes::AssetPreservationStatus, prepare_word}, transaction::{OutputNote, OutputNotes}, }; -use vm_processor::Process; -use super::{ContextId, Felt, MemAdviceProvider, ProcessState, Word, ONE, ZERO}; -use crate::testing::{executor::CodeExecutor, MockHost, TransactionContextBuilder}; +use super::{Felt, MemAdviceProvider, ProcessState, Word, ONE, ZERO}; +use crate::{ + testing::{executor::CodeExecutor, TransactionContextBuilder}, + tests::kernel_tests::read_root_mem_value, +}; + #[test] fn test_create_note() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let account_id = tx_context.account().id(); let recipient = [ZERO, ONE, Felt::new(2), Felt::new(3)]; @@ -33,20 +37,20 @@ fn test_create_note() { let code = format!( " - use.miden::kernels::tx::prologue - use.miden::tx + use.miden::kernels::tx::prologue + use.miden::tx - begin - exec.prologue::prepare_transaction + begin + exec.prologue::prepare_transaction - push.{recipient} - push.{PUBLIC_NOTE} - push.{aux} - push.{tag} + push.{recipient} + push.{PUBLIC_NOTE} + push.{aux} + push.{tag} - exec.tx::create_note - end - ", + exec.tx::create_note + end + ", recipient = prepare_word(&recipient), PUBLIC_NOTE = NoteType::Public as u8, tag = tag, @@ -55,7 +59,7 @@ fn test_create_note() { let process = tx_context.execute_code(&code).unwrap(); assert_eq!( - process.get_mem_value(ContextId::root(), NUM_CREATED_NOTES_PTR).unwrap(), + read_root_mem_value(&process, NUM_CREATED_NOTES_PTR), [ONE, ZERO, ZERO, ZERO], "number of created notes must increment by 1", ); @@ -81,27 +85,30 @@ fn test_create_note() { #[test] fn test_create_note_with_invalid_tag() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let recipient = [ZERO, ONE, Felt::new(2), Felt::new(3)]; let tag = Felt::new((NoteType::Public as u64) << 62); let code = format!( " - use.miden::kernels::tx::prologue - use.miden::tx + use.miden::kernels::tx::prologue + use.miden::tx - begin - exec.prologue::prepare_transaction + begin + exec.prologue::prepare_transaction - push.{recipient} - push.{PUBLIC_NOTE} - push.{tag} + push.{recipient} + push.{PUBLIC_NOTE} + push.{tag} - exec.tx::create_note - end - ", + exec.tx::create_note + end + ", recipient = prepare_word(&recipient), PUBLIC_NOTE = NoteType::Public as u8, tag = tag, @@ -119,21 +126,21 @@ fn test_create_note_too_many_notes() { let code = format!( " - use.miden::kernels::tx::constants - use.miden::kernels::tx::memory - use.miden::tx + use.miden::kernels::tx::constants + use.miden::kernels::tx::memory + use.miden::tx - begin - exec.constants::get_max_num_created_notes - exec.memory::set_num_created_notes + begin + exec.constants::get_max_num_created_notes + exec.memory::set_num_created_notes - push.{recipient} - push.{PUBLIC_NOTE} - push.{tag} + push.{recipient} + push.{PUBLIC_NOTE} + push.{tag} - exec.tx::create_note - end - ", + exec.tx::create_note + end + ", recipient = prepare_word(&recipient), tag = tag, PUBLIC_NOTE = NoteType::Public as u8, @@ -147,9 +154,12 @@ fn test_create_note_too_many_notes() { #[test] fn test_get_output_notes_hash() { - let tx_context = TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting) - .with_mock_notes(AssetPreservationStatus::Preserved) - .build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .with_mock_notes(AssetPreservationStatus::Preserved) + .build(); // extract input note data let input_note_1 = tx_context.tx_inputs().input_notes().get_note(0).note(); @@ -197,48 +207,48 @@ fn test_get_output_notes_hash() { let code = format!( " - use.miden::kernels::tx::prologue - use.miden::tx - - begin - # => [BH, acct_id, IAH, NC] - exec.prologue::prepare_transaction - # => [] - - # create output note 1 - push.{recipient_1} - push.{PUBLIC_NOTE} - push.{aux_1} - push.{tag_1} - exec.tx::create_note - # => [note_idx] - - push.{asset_1} movup.4 - exec.tx::add_asset_to_note - - - drop - # => [] - - # create output note 2 - push.{recipient_2} - push.{PUBLIC_NOTE} - push.{aux_2} - push.{tag_2} - exec.tx::create_note - # => [note_idx] - - push.{asset_2} movup.4 - exec.tx::add_asset_to_note - - drop - # => [] - - # compute the output notes hash - exec.tx::get_output_notes_hash - # => [COMM] - end - ", + use.miden::kernels::tx::prologue + use.miden::tx + + begin + # => [BH, acct_id, IAH, NC] + exec.prologue::prepare_transaction + # => [] + + # create output note 1 + push.{recipient_1} + push.{PUBLIC_NOTE} + push.{aux_1} + push.{tag_1} + exec.tx::create_note + # => [note_idx] + + push.{asset_1} movup.4 + exec.tx::add_asset_to_note + + + drop + # => [] + + # create output note 2 + push.{recipient_2} + push.{PUBLIC_NOTE} + push.{aux_2} + push.{tag_2} + exec.tx::create_note + # => [note_idx] + + push.{asset_2} movup.4 + exec.tx::add_asset_to_note + + drop + # => [] + + # compute the output notes hash + exec.tx::get_output_notes_hash + # => [COMM] + end + ", PUBLIC_NOTE = NoteType::Public as u8, recipient_1 = prepare_word(&output_note_1.recipient().digest()), tag_1 = output_note_1.metadata().tag(), @@ -257,24 +267,26 @@ fn test_get_output_notes_hash() { let process = tx_context.execute_code(&code).unwrap(); assert_eq!( - process.get_mem_value(ContextId::root(), NUM_CREATED_NOTES_PTR), - Some([Felt::new(2), ZERO, ZERO, ZERO]), + read_root_mem_value(&process, NUM_CREATED_NOTES_PTR), + [Felt::new(2), ZERO, ZERO, ZERO], "The test creates two notes", ); assert_eq!( - process.get_mem_value( - ContextId::root(), + NoteMetadata::try_from(read_root_mem_value( + &process, CREATED_NOTE_SECTION_OFFSET + CREATED_NOTE_METADATA_OFFSET - ), - Some(output_note_1.metadata().into()), + )) + .unwrap(), + *output_note_1.metadata(), "Validate the output note 1 metadata", ); assert_eq!( - process.get_mem_value( - ContextId::root(), + NoteMetadata::try_from(read_root_mem_value( + &process, CREATED_NOTE_SECTION_OFFSET + CREATED_NOTE_METADATA_OFFSET + NOTE_MEM_SIZE - ), - Some(output_note_2.metadata().into()), + )) + .unwrap(), + *output_note_2.metadata(), "Validate the output note 1 metadata", ); @@ -283,8 +295,11 @@ fn test_get_output_notes_hash() { #[test] fn test_create_note_and_add_asset() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let recipient = [ZERO, ONE, Felt::new(2), Felt::new(3)]; let aux = Felt::new(27); @@ -293,26 +308,26 @@ fn test_create_note_and_add_asset() { let code = format!( " - use.miden::kernels::tx::prologue - use.miden::tx - use.miden::kernels::tx::memory + use.miden::kernels::tx::prologue + use.miden::tx + use.miden::kernels::tx::memory - begin - exec.prologue::prepare_transaction + begin + exec.prologue::prepare_transaction - push.{recipient} - push.{PUBLIC_NOTE} - push.{aux} - push.{tag} + push.{recipient} + push.{PUBLIC_NOTE} + push.{aux} + push.{tag} - exec.tx::create_note - # => [note_idx] + exec.tx::create_note + # => [note_idx] - push.{asset} movup.4 - exec.tx::add_asset_to_note + push.{asset} movup.4 + exec.tx::add_asset_to_note - end - ", + end + ", recipient = prepare_word(&recipient), PUBLIC_NOTE = NoteType::Public as u8, tag = tag, @@ -336,8 +351,11 @@ fn test_create_note_and_add_asset() { #[test] fn test_create_note_and_add_multiple_assets() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let recipient = [ZERO, ONE, Felt::new(2), Felt::new(3)]; let aux = Felt::new(27); @@ -355,37 +373,37 @@ fn test_create_note_and_add_multiple_assets() { let code = format!( " - use.miden::kernels::tx::prologue - use.miden::tx + use.miden::kernels::tx::prologue + use.miden::tx - begin - exec.prologue::prepare_transaction + begin + exec.prologue::prepare_transaction - push.{recipient} - push.{PUBLIC_NOTE} - push.{aux} - push.{tag} + push.{recipient} + push.{PUBLIC_NOTE} + push.{aux} + push.{tag} - exec.tx::create_note - # => [note_idx] + exec.tx::create_note + # => [note_idx] - push.{asset} movup.4 - exec.tx::add_asset_to_note - # => [note_idx] + push.{asset} movup.4 + exec.tx::add_asset_to_note + # => [note_idx] - push.{asset_2} movup.4 - exec.tx::add_asset_to_note - # => [note_idx] + push.{asset_2} movup.4 + exec.tx::add_asset_to_note + # => [note_idx] - push.{asset_3} movup.4 - exec.tx::add_asset_to_note - # => [note_idx] + push.{asset_3} movup.4 + exec.tx::add_asset_to_note + # => [note_idx] - push.{nft} movup.4 - exec.tx::add_asset_to_note - # => [note_idx] - end - ", + push.{nft} movup.4 + exec.tx::add_asset_to_note + # => [note_idx] + end + ", recipient = prepare_word(&recipient), PUBLIC_NOTE = NoteType::Public as u8, tag = tag, @@ -424,8 +442,11 @@ fn test_create_note_and_add_multiple_assets() { #[test] fn test_create_note_and_add_same_nft_twice() { - let tx_context = - TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting).build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .build(); let recipient = [ZERO, ONE, Felt::new(2), Felt::new(3)]; let tag = Felt::new(4); @@ -435,25 +456,25 @@ fn test_create_note_and_add_same_nft_twice() { let code = format!( " - use.miden::kernels::tx::prologue - use.miden::tx + use.miden::kernels::tx::prologue + use.miden::tx - begin - exec.prologue::prepare_transaction + begin + exec.prologue::prepare_transaction - push.{recipient} - push.{PUBLIC_NOTE} - push.{tag} - push.{nft} + push.{recipient} + push.{PUBLIC_NOTE} + push.{tag} + push.{nft} - exec.tx::create_note - # => [note_idx] + exec.tx::create_note + # => [note_idx] - push.{nft} movup.4 - exec.tx::add_asset_to_note - # => [note_idx] - end - ", + push.{nft} movup.4 + exec.tx::add_asset_to_note + # => [note_idx] + end + ", recipient = prepare_word(&recipient), PUBLIC_NOTE = NoteType::Public as u8, tag = tag, @@ -470,9 +491,12 @@ fn test_create_note_and_add_same_nft_twice() { #[test] fn test_build_recipient_hash() { - let tx_context = TransactionContextBuilder::with_acc_type(MockAccountType::StandardExisting) - .with_mock_notes(AssetPreservationStatus::Preserved) - .build(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .with_mock_notes(AssetPreservationStatus::Preserved) + .build(); let input_note_1 = tx_context.tx_inputs().input_notes().get_note(0).note(); @@ -487,24 +511,24 @@ fn test_build_recipient_hash() { let recipient = NoteRecipient::new(output_serial_no, input_note_1.script().clone(), inputs); let code = format!( " - use.miden::kernels::tx::prologue - use.miden::tx - begin - exec.prologue::prepare_transaction - # input - push.{input_hash} - # SCRIPT_HASH - push.{script_hash} - # SERIAL_NUM - push.{output_serial_no} - exec.tx::build_recipient_hash - - push.{PUBLIC_NOTE} - push.{aux} - push.{tag} - exec.tx::create_note - end - ", + use.miden::kernels::tx::prologue + use.miden::tx + begin + exec.prologue::prepare_transaction + # input + push.{input_hash} + # SCRIPT_HASH + push.{script_hash} + # SERIAL_NUM + push.{output_serial_no} + exec.tx::build_recipient_hash + + push.{PUBLIC_NOTE} + push.{aux} + push.{tag} + exec.tx::create_note + end + ", input_hash = input_hash, script_hash = input_note_1.script().clone().hash(), output_serial_no = prepare_word(&output_serial_no), @@ -516,7 +540,7 @@ fn test_build_recipient_hash() { let process = tx_context.execute_code(&code).unwrap(); assert_eq!( - process.get_mem_value(ContextId::root(), NUM_CREATED_NOTES_PTR).unwrap(), + read_root_mem_value(&process, NUM_CREATED_NOTES_PTR), [ONE, ZERO, ZERO, ZERO], "number of created notes must increment by 1", ); @@ -529,10 +553,3 @@ fn test_build_recipient_hash() { "recipient hash not correct", ); } - -// HELPER FUNCTIONS -// ================================================================================================ - -fn read_root_mem_value(process: &Process, addr: u32) -> Word { - process.get_mem_value(ContextId::root(), addr).unwrap() -} diff --git a/miden-tx/src/tests/mod.rs b/miden-tx/src/tests/mod.rs index e01f6916a..de6318740 100644 --- a/miden-tx/src/tests/mod.rs +++ b/miden-tx/src/tests/mod.rs @@ -7,6 +7,7 @@ use miden_objects::{ ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN, ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_2, ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, ACCOUNT_ID_REGULAR_ACCOUNT_IMMUTABLE_CODE_ON_CHAIN, + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, }, AccountCode, }, @@ -23,7 +24,7 @@ use miden_objects::{ ACCOUNT_SET_CODE_MAST_ROOT, ACCOUNT_SET_ITEM_MAST_ROOT, ACCOUNT_SET_MAP_ITEM_MAST_ROOT, }, constants::{FUNGIBLE_ASSET_AMOUNT, NON_FUNGIBLE_ASSET_DATA}, - notes::AssetPreservationStatus, + notes::{AssetPreservationStatus, DEFAULT_NOTE_CODE}, prepare_word, storage::{STORAGE_INDEX_0, STORAGE_INDEX_2}, }, @@ -33,12 +34,12 @@ use miden_objects::{ use miden_prover::ProvingOptions; use vm_processor::{ utils::{Deserializable, Serializable}, - Digest, MemAdviceProvider, + Digest, MemAdviceProvider, ONE, }; use winter_maybe_async::maybe_async; use super::{TransactionExecutor, TransactionHost, TransactionProver, TransactionVerifier}; -use crate::testing::data_store::MockDataStore; +use crate::testing::TransactionContextBuilder; mod kernel_tests; @@ -47,23 +48,28 @@ mod kernel_tests; #[test] fn transaction_executor_witness() { - let data_store = MockDataStore::default(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .with_mock_notes(AssetPreservationStatus::Preserved) + .build(); let mut executor: TransactionExecutor<_, ()> = - TransactionExecutor::new(data_store.clone(), None); + TransactionExecutor::new(tx_context.clone(), None); - let account_id = data_store.account().id(); + let account_id = tx_context.account().id(); executor.load_account(account_id).unwrap(); - let block_ref = data_store.block_header().block_num(); - let note_ids = data_store - .tx_inputs + let block_ref = tx_context.tx_inputs().block_header().block_num(); + let note_ids = tx_context + .tx_inputs() .input_notes() .iter() .map(|note| note.id()) .collect::>(); let executed_transaction = executor - .execute_transaction(account_id, block_ref, ¬e_ids, data_store.tx_args) + .execute_transaction(account_id, block_ref, ¬e_ids, tx_context.tx_args().clone()) .unwrap(); let tx_witness: TransactionWitness = executed_transaction.clone().into(); @@ -92,10 +98,16 @@ fn transaction_executor_witness() { #[test] fn executed_transaction_account_delta() { - let data_store = MockDataStore::new(AssetPreservationStatus::PreservedWithAccountVaultDelta); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .with_mock_notes(AssetPreservationStatus::PreservedWithAccountVaultDelta) + .build(); + let mut executor: TransactionExecutor<_, ()> = - TransactionExecutor::new(data_store.clone(), None); - let account_id = data_store.account().id(); + TransactionExecutor::new(tx_context.clone(), None); + let account_id = tx_context.tx_inputs().account().id(); executor.load_account(account_id).unwrap(); let new_acct_code_src = "\ @@ -281,11 +293,11 @@ fn executed_transaction_account_delta() { let tx_script_code = ProgramAst::parse(&tx_script).unwrap(); let tx_script = executor.compile_tx_script(tx_script_code, vec![], vec![]).unwrap(); let tx_args = - TransactionArgs::new(Some(tx_script), None, data_store.tx_args.advice_map().clone()); + TransactionArgs::new(Some(tx_script), None, tx_context.tx_args().advice_map().clone()); - let block_ref = data_store.block_header().block_num(); - let note_ids = data_store - .tx_inputs + let block_ref = tx_context.tx_inputs().block_header().block_num(); + let note_ids = tx_context + .tx_inputs() .input_notes() .iter() .map(|note| note.id()) @@ -327,8 +339,8 @@ fn executed_transaction_account_delta() { // vault delta // -------------------------------------------------------------------------------------------- // assert that added assets are tracked - let added_assets = data_store - .tx_inputs + let added_assets = tx_context + .tx_inputs() .input_notes() .iter() .find(|n| n.note().assets().num_assets() == 3) @@ -365,10 +377,16 @@ fn executed_transaction_account_delta() { #[test] fn executed_transaction_output_notes() { - let data_store = MockDataStore::new(AssetPreservationStatus::PreservedWithAccountVaultDelta); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .with_mock_notes(AssetPreservationStatus::PreservedWithAccountVaultDelta) + .build(); + let mut executor: TransactionExecutor<_, ()> = - TransactionExecutor::new(data_store.clone(), None).with_debug_mode(true); - let account_id = data_store.account().id(); + TransactionExecutor::new(tx_context.clone(), None).with_debug_mode(true); + let account_id = tx_context.tx_inputs().account().id(); executor.load_account(account_id).unwrap(); // removed assets @@ -423,11 +441,10 @@ fn executed_transaction_output_notes() { assert_eq!(tag3.validate(note_type3), Ok(tag3)); // In this test we create 3 notes. Note 1 is private, Note 2 is public and Note 3 is public without assets. - // However, the MockDataStore always creates 3 notes as well. // Create the expected output note for Note 2 which is public let serial_num_2 = Word::from([Felt::new(1), Felt::new(2), Felt::new(3), Felt::new(4)]); - let note_program_ast_2 = ProgramAst::parse("begin push.1 drop end").unwrap(); + let note_program_ast_2 = ProgramAst::parse(DEFAULT_NOTE_CODE).unwrap(); let (note_script_2, _) = NoteScript::new(note_program_ast_2, &Assembler::default()).unwrap(); let inputs_2 = NoteInputs::new(vec![]).unwrap(); let metadata_2 = NoteMetadata::new(account_id, note_type2, tag2, aux2).unwrap(); @@ -437,7 +454,7 @@ fn executed_transaction_output_notes() { // Create the expected output note for Note 3 which is public let serial_num_3 = Word::from([Felt::new(5), Felt::new(6), Felt::new(7), Felt::new(8)]); - let note_program_ast_3 = ProgramAst::parse("begin push.1 drop end").unwrap(); + let note_program_ast_3 = ProgramAst::parse(DEFAULT_NOTE_CODE).unwrap(); let (note_script_3, _) = NoteScript::new(note_program_ast_3, &Assembler::default()).unwrap(); let inputs_3 = NoteInputs::new(vec![]).unwrap(); let metadata_3 = NoteMetadata::new(account_id, note_type3, tag3, aux3).unwrap(); @@ -551,13 +568,18 @@ fn executed_transaction_output_notes() { let tx_script_code = ProgramAst::parse(&tx_script).unwrap(); let tx_script = executor.compile_tx_script(tx_script_code, vec![], vec![]).unwrap(); let mut tx_args = - TransactionArgs::new(Some(tx_script), None, data_store.tx_args.advice_map().clone()); + TransactionArgs::new(Some(tx_script), None, tx_context.tx_args().advice_map().clone()); tx_args.add_expected_output_note(&expected_output_note_2); tx_args.add_expected_output_note(&expected_output_note_3); - let block_ref = data_store.block_header().block_num(); - let note_ids = data_store.input_notes().iter().map(|note| note.id()).collect::>(); + let block_ref = tx_context.tx_inputs().block_header().block_num(); + let note_ids = tx_context + .tx_inputs() + .input_notes() + .iter() + .map(|note| note.id()) + .collect::>(); // expected delta // -------------------------------------------------------------------------------------------- // execute the transaction and get the witness @@ -569,8 +591,7 @@ fn executed_transaction_output_notes() { let output_notes = executed_transaction.output_notes(); // assert that the expected output note is present - // for some reason we always create 3 output notes when we use the MockDataStore - // there is already an issue to change that + // NOTE: the mock state already contains 3 output notes assert_eq!(output_notes.num_notes(), 6); let created_note_id_3 = executed_transaction.output_notes().get_note(3).id(); @@ -593,23 +614,28 @@ fn executed_transaction_output_notes() { #[test] fn prove_witness_and_verify() { - let data_store = MockDataStore::default(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .with_mock_notes(AssetPreservationStatus::Preserved) + .build(); let mut executor: TransactionExecutor<_, ()> = - TransactionExecutor::new(data_store.clone(), None); + TransactionExecutor::new(tx_context.clone(), None); - let account_id = data_store.tx_inputs.account().id(); + let account_id = tx_context.tx_inputs().account().id(); executor.load_account(account_id).unwrap(); - let block_ref = data_store.block_header().block_num(); - let note_ids = data_store - .tx_inputs + let block_ref = tx_context.tx_inputs().block_header().block_num(); + let note_ids = tx_context + .tx_inputs() .input_notes() .iter() .map(|note| note.id()) .collect::>(); let executed_transaction = executor - .execute_transaction(account_id, block_ref, ¬e_ids, data_store.tx_args) + .execute_transaction(account_id, block_ref, ¬e_ids, tx_context.tx_args().clone()) .unwrap(); let executed_transaction_id = executed_transaction.id(); @@ -630,16 +656,21 @@ fn prove_witness_and_verify() { #[test] fn test_tx_script() { - let data_store = MockDataStore::default(); + let tx_context = TransactionContextBuilder::with_standard_account( + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + ONE, + ) + .with_mock_notes(AssetPreservationStatus::Preserved) + .build(); let mut executor: TransactionExecutor<_, ()> = - TransactionExecutor::new(data_store.clone(), None); + TransactionExecutor::new(tx_context.clone(), None); - let account_id = data_store.tx_inputs.account().id(); + let account_id = tx_context.tx_inputs().account().id(); executor.load_account(account_id).unwrap(); - let block_ref = data_store.block_header().block_num(); - let note_ids = data_store - .tx_inputs + let block_ref = tx_context.tx_inputs().block_header().block_num(); + let note_ids = tx_context + .tx_inputs() .input_notes() .iter() .map(|note| note.id()) @@ -672,7 +703,7 @@ fn test_tx_script() { ) .unwrap(); let tx_args = - TransactionArgs::new(Some(tx_script), None, data_store.tx_args.advice_map().clone()); + TransactionArgs::new(Some(tx_script), None, tx_context.tx_args().advice_map().clone()); let executed_transaction = executor.execute_transaction(account_id, block_ref, ¬e_ids, tx_args); diff --git a/miden-tx/tests/integration/main.rs b/miden-tx/tests/integration/main.rs index 69877eebd..71dfd04a6 100644 --- a/miden-tx/tests/integration/main.rs +++ b/miden-tx/tests/integration/main.rs @@ -78,7 +78,7 @@ pub fn get_account_with_default_account_code( use miden_objects::testing::account_code::DEFAULT_ACCOUNT_CODE; let account_code_src = DEFAULT_ACCOUNT_CODE; let account_code_ast = ModuleAst::parse(account_code_src).unwrap(); - let account_assembler = TransactionKernel::assembler(); + let account_assembler = TransactionKernel::assembler().with_debug_mode(true); let account_code = AccountCode::new(account_code_ast.clone(), &account_assembler).unwrap(); let account_storage = @@ -97,7 +97,7 @@ pub fn get_note_with_fungible_asset_and_script( fungible_asset: FungibleAsset, note_script: ProgramAst, ) -> Note { - let note_assembler = TransactionKernel::assembler(); + let note_assembler = TransactionKernel::assembler().with_debug_mode(true); let (note_script, _) = NoteScript::new(note_script, ¬e_assembler).unwrap(); const SERIAL_NUM: Word = [Felt::new(1), Felt::new(2), Felt::new(3), Felt::new(4)]; let sender_id = AccountId::try_from(ACCOUNT_ID_SENDER).unwrap(); diff --git a/miden-tx/tests/integration/scripts/faucet.rs b/miden-tx/tests/integration/scripts/faucet.rs index e9f317845..7dd56230c 100644 --- a/miden-tx/tests/integration/scripts/faucet.rs +++ b/miden-tx/tests/integration/scripts/faucet.rs @@ -20,7 +20,7 @@ use miden_objects::{ transaction::TransactionArgs, Felt, Word, ZERO, }; -use miden_tx::{testing::data_store::MockDataStore, TransactionExecutor}; +use miden_tx::{testing::TransactionContextBuilder, TransactionExecutor}; use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng}; use crate::{ @@ -39,14 +39,14 @@ fn prove_faucet_contract_mint_fungible_asset_succeeds() { // CONSTRUCT AND EXECUTE TX (Success) // -------------------------------------------------------------------------------------------- - let data_store = MockDataStore::with_existing(Some(faucet_account.clone()), Some(vec![])); + let tx_context = TransactionContextBuilder::new(faucet_account.clone()).build(); - let mut executor = TransactionExecutor::new(data_store.clone(), Some(falcon_auth.clone())); + let mut executor = TransactionExecutor::new(tx_context.clone(), Some(falcon_auth.clone())); executor.load_account(faucet_account.id()).unwrap(); - let block_ref = data_store.block_header().block_num(); - let note_ids = data_store - .tx_inputs + let block_ref = tx_context.tx_inputs().block_header().block_num(); + let note_ids = tx_context + .tx_inputs() .input_notes() .iter() .map(|note| note.id()) @@ -121,14 +121,14 @@ fn faucet_contract_mint_fungible_asset_fails_exceeds_max_supply() { // CONSTRUCT AND EXECUTE TX (Failure) // -------------------------------------------------------------------------------------------- - let data_store = MockDataStore::with_existing(Some(faucet_account.clone()), Some(vec![])); + let tx_context = TransactionContextBuilder::new(faucet_account.clone()).build(); - let mut executor = TransactionExecutor::new(data_store.clone(), Some(falcon_auth.clone())); + let mut executor = TransactionExecutor::new(tx_context.clone(), Some(falcon_auth.clone())); executor.load_account(faucet_account.id()).unwrap(); - let block_ref = data_store.block_header().block_num(); - let note_ids = data_store - .tx_inputs + let block_ref = tx_context.tx_inputs().block_header().block_num(); + let note_ids = tx_context + .tx_inputs() .input_notes() .iter() .map(|note| note.id()) @@ -218,15 +218,16 @@ fn prove_faucet_contract_burn_fungible_asset_succeeds() { // CONSTRUCT AND EXECUTE TX (Success) // -------------------------------------------------------------------------------------------- - let data_store = - MockDataStore::with_existing(Some(faucet_account.clone()), Some(vec![note.clone()])); + let tx_context = TransactionContextBuilder::new(faucet_account.clone()) + .input_notes(vec![note.clone()]) + .build(); - let mut executor = TransactionExecutor::new(data_store.clone(), Some(falcon_auth.clone())); + let mut executor = TransactionExecutor::new(tx_context.clone(), Some(falcon_auth.clone())); executor.load_account(faucet_account.id()).unwrap(); - let block_ref = data_store.block_header().block_num(); - let note_ids = data_store - .tx_inputs + let block_ref = tx_context.tx_inputs().block_header().block_num(); + let note_ids = tx_context + .tx_inputs() .input_notes() .iter() .map(|note| note.id()) @@ -234,7 +235,12 @@ fn prove_faucet_contract_burn_fungible_asset_succeeds() { // Execute the transaction and get the witness let executed_transaction = executor - .execute_transaction(faucet_account.id(), block_ref, ¬e_ids, data_store.tx_args) + .execute_transaction( + faucet_account.id(), + block_ref, + ¬e_ids, + tx_context.tx_args().clone(), + ) .unwrap(); // Prove, serialize/deserialize and verify the transaction @@ -291,7 +297,7 @@ fn faucet_contract_creation() { let exp_faucet_account_code_src = include_str!("../../../../miden-lib/asm/miden/contracts/faucets/basic_fungible.masm"); let exp_faucet_account_code_ast = ModuleAst::parse(exp_faucet_account_code_src).unwrap(); - let account_assembler = TransactionKernel::assembler(); + let account_assembler = TransactionKernel::assembler().with_debug_mode(true); let exp_faucet_account_code = AccountCode::new(exp_faucet_account_code_ast.clone(), &account_assembler).unwrap(); @@ -308,7 +314,7 @@ fn get_faucet_account_with_max_supply_and_total_issuance( let faucet_account_code_src = include_str!("../../../../miden-lib/asm/miden/contracts/faucets/basic_fungible.masm"); let faucet_account_code_ast = ModuleAst::parse(faucet_account_code_src).unwrap(); - let account_assembler = TransactionKernel::assembler(); + let account_assembler = TransactionKernel::assembler().with_debug_mode(true); let faucet_account_code = AccountCode::new(faucet_account_code_ast.clone(), &account_assembler).unwrap(); diff --git a/miden-tx/tests/integration/scripts/p2id.rs b/miden-tx/tests/integration/scripts/p2id.rs index 802fef1e5..6474b59a7 100644 --- a/miden-tx/tests/integration/scripts/p2id.rs +++ b/miden-tx/tests/integration/scripts/p2id.rs @@ -13,11 +13,11 @@ use miden_objects::{ assets::{Asset, AssetVault, FungibleAsset}, crypto::rand::RpoRandomCoin, notes::{NoteScript, NoteType}, - testing::account_code::DEFAULT_AUTH_SCRIPT, + testing::{account_code::DEFAULT_AUTH_SCRIPT, notes::DEFAULT_NOTE_CODE}, transaction::TransactionArgs, Felt, }; -use miden_tx::{testing::data_store::MockDataStore, TransactionExecutor}; +use miden_tx::{testing::TransactionContextBuilder, TransactionExecutor}; use crate::{ get_account_with_default_account_code, get_new_pk_and_authenticator, @@ -57,15 +57,16 @@ fn prove_p2id_script() { // CONSTRUCT AND EXECUTE TX (Success) // -------------------------------------------------------------------------------------------- - let data_store = - MockDataStore::with_existing(Some(target_account.clone()), Some(vec![note.clone()])); + let tx_context = TransactionContextBuilder::new(target_account.clone()) + .input_notes(vec![note.clone()]) + .build(); - let mut executor = TransactionExecutor::new(data_store.clone(), Some(falcon_auth.clone())); + let mut executor = TransactionExecutor::new(tx_context.clone(), Some(falcon_auth.clone())); executor.load_account(target_account_id).unwrap(); - let block_ref = data_store.block_header().block_num(); - let note_ids = data_store - .tx_inputs + let block_ref = tx_context.tx_inputs().block_header().block_num(); + let note_ids = tx_context + .tx_inputs() .input_notes() .iter() .map(|note| note.id()) @@ -105,17 +106,18 @@ fn prove_p2id_script() { let malicious_account = get_account_with_default_account_code(malicious_account_id, malicious_pub_key, None); - let data_store_malicious_account = - MockDataStore::with_existing(Some(malicious_account), Some(vec![note])); + let tx_context_malicious_account = TransactionContextBuilder::new(malicious_account) + .input_notes(vec![note]) + .build(); let mut executor_2 = - TransactionExecutor::new(data_store_malicious_account.clone(), Some(malicious_falcon_auth)); + TransactionExecutor::new(tx_context_malicious_account.clone(), Some(malicious_falcon_auth)); executor_2.load_account(malicious_account_id).unwrap(); let tx_script_malicious = executor.compile_tx_script(tx_script_code, vec![], vec![]).unwrap(); let tx_args_malicious = TransactionArgs::with_tx_script(tx_script_malicious); - let block_ref = data_store_malicious_account.block_header().block_num(); - let note_ids = data_store_malicious_account + let block_ref = tx_context_malicious_account.tx_inputs().block_header().block_num(); + let note_ids = tx_context_malicious_account .input_notes() .iter() .map(|note| note.id()) @@ -167,15 +169,16 @@ fn p2id_script_multiple_assets() { // CONSTRUCT AND EXECUTE TX (Success) // -------------------------------------------------------------------------------------------- - let data_store = - MockDataStore::with_existing(Some(target_account.clone()), Some(vec![note.clone()])); + let tx_context = TransactionContextBuilder::new(target_account.clone()) + .input_notes(vec![note.clone()]) + .build(); - let mut executor = TransactionExecutor::new(data_store.clone(), Some(falcon_auth)); + let mut executor = TransactionExecutor::new(tx_context.clone(), Some(falcon_auth)); executor.load_account(target_account_id).unwrap(); - let block_ref = data_store.block_header().block_num(); - let note_ids = data_store - .tx_inputs + let block_ref = tx_context.tx_inputs().block_header().block_num(); + let note_ids = tx_context + .tx_inputs() .input_notes() .iter() .map(|note| note.id()) @@ -212,17 +215,18 @@ fn p2id_script_multiple_assets() { let malicious_account = get_account_with_default_account_code(malicious_account_id, malicious_pub_key, None); - let data_store_malicious_account = - MockDataStore::with_existing(Some(malicious_account), Some(vec![note])); + let tx_context_malicious_account = TransactionContextBuilder::new(malicious_account) + .input_notes(vec![note]) + .build(); let mut executor_2 = - TransactionExecutor::new(data_store_malicious_account.clone(), Some(malicious_falcon_auth)); + TransactionExecutor::new(tx_context_malicious_account.clone(), Some(malicious_falcon_auth)); executor_2.load_account(malicious_account_id).unwrap(); let tx_script_malicious = executor.compile_tx_script(tx_script_code.clone(), vec![], vec![]).unwrap(); let tx_args_malicious = TransactionArgs::with_tx_script(tx_script_malicious); - let block_ref = data_store_malicious_account.block_header().block_num(); - let note_origins = data_store_malicious_account + let block_ref = tx_context_malicious_account.tx_inputs().block_header().block_num(); + let note_origins = tx_context_malicious_account .input_notes() .iter() .map(|note| note.id()) @@ -242,9 +246,9 @@ fn p2id_script_multiple_assets() { #[test] fn test_note_script_to_from_felt() { - let assembler = TransactionKernel::assembler(); + let assembler = TransactionKernel::assembler().with_debug_mode(true); - let note_program_ast = ProgramAst::parse("begin push.1 drop end").unwrap(); + let note_program_ast = ProgramAst::parse(DEFAULT_NOTE_CODE).unwrap(); let (note_script, _) = NoteScript::new(note_program_ast, &assembler).unwrap(); let encoded: Vec = (¬e_script).into(); diff --git a/miden-tx/tests/integration/scripts/p2idr.rs b/miden-tx/tests/integration/scripts/p2idr.rs index ccbbcb339..b89cd580d 100644 --- a/miden-tx/tests/integration/scripts/p2idr.rs +++ b/miden-tx/tests/integration/scripts/p2idr.rs @@ -16,7 +16,7 @@ use miden_objects::{ transaction::TransactionArgs, Felt, }; -use miden_tx::{testing::data_store::MockDataStore, TransactionExecutor}; +use miden_tx::{testing::TransactionContextBuilder, TransactionExecutor}; use crate::{get_account_with_default_account_code, get_new_pk_and_authenticator}; @@ -91,17 +91,16 @@ fn p2idr_script() { // -------------------------------------------------------------------------------------------- // CONSTRUCT AND EXECUTE TX (Case "in time" - Target Account Execution Success) // -------------------------------------------------------------------------------------------- - let data_store_1 = MockDataStore::with_existing( - Some(target_account.clone()), - Some(vec![note_in_time.clone()]), - ); + let tx_context_1 = TransactionContextBuilder::new(target_account.clone()) + .input_notes(vec![note_in_time.clone()]) + .build(); let mut executor_1 = - TransactionExecutor::new(data_store_1.clone(), Some(target_falcon_auth.clone())); + TransactionExecutor::new(tx_context_1.clone(), Some(target_falcon_auth.clone())); executor_1.load_account(target_account_id).unwrap(); - let block_ref_1 = data_store_1.block_header().block_num(); - let note_ids = data_store_1.input_notes().iter().map(|note| note.id()).collect::>(); + let block_ref_1 = tx_context_1.tx_inputs().block_header().block_num(); + let note_ids = tx_context_1.input_notes().iter().map(|note| note.id()).collect::>(); let tx_script_code = ProgramAst::parse(DEFAULT_AUTH_SCRIPT).unwrap(); let tx_script_target = @@ -125,19 +124,18 @@ fn p2idr_script() { // CONSTRUCT AND EXECUTE TX (Case "in time" - Sender Account Execution Failure) // -------------------------------------------------------------------------------------------- - let data_store_2 = MockDataStore::with_existing( - Some(sender_account.clone()), - Some(vec![note_in_time.clone()]), - ); + let tx_context_2 = TransactionContextBuilder::new(sender_account.clone()) + .input_notes(vec![note_in_time.clone()]) + .build(); let mut executor_2 = - TransactionExecutor::new(data_store_2.clone(), Some(sender_falcon_auth.clone())); + TransactionExecutor::new(tx_context_2.clone(), Some(sender_falcon_auth.clone())); executor_2.load_account(sender_account_id).unwrap(); let tx_script_sender = executor_2.compile_tx_script(tx_script_code.clone(), vec![], vec![]).unwrap(); let tx_args_sender = TransactionArgs::with_tx_script(tx_script_sender); - let block_ref_2 = data_store_2.block_header().block_num(); - let note_ids_2 = data_store_2.input_notes().iter().map(|note| note.id()).collect::>(); + let block_ref_2 = tx_context_2.tx_inputs().block_header().block_num(); + let note_ids_2 = tx_context_2.input_notes().iter().map(|note| note.id()).collect::>(); // Execute the transaction and get the witness let executed_transaction_2 = executor_2.execute_transaction( @@ -153,18 +151,17 @@ fn p2idr_script() { // CONSTRUCT AND EXECUTE TX (Case "in time" - Malicious Target Account Failure) // -------------------------------------------------------------------------------------------- - let data_store_3 = MockDataStore::with_existing( - Some(malicious_account.clone()), - Some(vec![note_in_time.clone()]), - ); + let tx_context_3 = TransactionContextBuilder::new(malicious_account.clone()) + .input_notes(vec![note_in_time.clone()]) + .build(); let mut executor_3 = - TransactionExecutor::new(data_store_3.clone(), Some(malicious_falcon_auth.clone())); + TransactionExecutor::new(tx_context_3.clone(), Some(malicious_falcon_auth.clone())); executor_3.load_account(malicious_account_id).unwrap(); let tx_script_malicious = executor_3.compile_tx_script(tx_script_code, vec![], vec![]).unwrap(); let tx_args_malicious = TransactionArgs::with_tx_script(tx_script_malicious); - let block_ref_3 = data_store_3.block_header().block_num(); - let note_ids_3 = data_store_3.input_notes().iter().map(|note| note.id()).collect::>(); + let block_ref_3 = tx_context_3.tx_inputs().block_header().block_num(); + let note_ids_3 = tx_context_3.input_notes().iter().map(|note| note.id()).collect::>(); // Execute the transaction and get the witness let executed_transaction_3 = executor_3.execute_transaction( @@ -180,15 +177,14 @@ fn p2idr_script() { // CONSTRUCT AND EXECUTE TX (Case "reclaimable" - Execution Target Account Success) // -------------------------------------------------------------------------------------------- - let data_store_4 = MockDataStore::with_existing( - Some(target_account.clone()), - Some(vec![note_reclaimable.clone()]), - ); - let mut executor_4 = TransactionExecutor::new(data_store_4.clone(), Some(target_falcon_auth)); + let tx_context_4 = TransactionContextBuilder::new(target_account.clone()) + .input_notes(vec![note_reclaimable.clone()]) + .build(); + let mut executor_4 = TransactionExecutor::new(tx_context_4.clone(), Some(target_falcon_auth)); executor_4.load_account(target_account_id).unwrap(); - let block_ref_4 = data_store_4.block_header().block_num(); - let note_ids_4 = data_store_4.input_notes().iter().map(|note| note.id()).collect::>(); + let block_ref_4 = tx_context_4.tx_inputs().block_header().block_num(); + let note_ids_4 = tx_context_4.input_notes().iter().map(|note| note.id()).collect::>(); // Execute the transaction and get the witness let executed_transaction_4 = executor_4 @@ -212,16 +208,15 @@ fn p2idr_script() { // CONSTRUCT AND EXECUTE TX (Case "too late" - Execution Sender Account Success) // -------------------------------------------------------------------------------------------- - let data_store_5 = MockDataStore::with_existing( - Some(sender_account.clone()), - Some(vec![note_reclaimable.clone()]), - ); - let mut executor_5 = TransactionExecutor::new(data_store_5.clone(), Some(sender_falcon_auth)); + let tx_context_5 = TransactionContextBuilder::new(sender_account.clone()) + .input_notes(vec![note_reclaimable.clone()]) + .build(); + let mut executor_5 = TransactionExecutor::new(tx_context_5.clone(), Some(sender_falcon_auth)); executor_5.load_account(sender_account_id).unwrap(); - let block_ref_5 = data_store_5.block_header().block_num(); - let note_ids_5 = data_store_5.input_notes().iter().map(|note| note.id()).collect::>(); + let block_ref_5 = tx_context_5.tx_inputs().block_header().block_num(); + let note_ids_5 = tx_context_5.input_notes().iter().map(|note| note.id()).collect::>(); // Execute the transaction and get the witness let executed_transaction_5 = executor_5 @@ -244,17 +239,18 @@ fn p2idr_script() { // CONSTRUCT AND EXECUTE TX (Case "too late" - Malicious Account Failure) // -------------------------------------------------------------------------------------------- - let data_store_6 = MockDataStore::with_existing( - Some(malicious_account.clone()), - Some(vec![note_reclaimable.clone()]), - ); + + let tx_context_6 = TransactionContextBuilder::new(malicious_account.clone()) + .input_notes(vec![note_reclaimable.clone()]) + .build(); + let mut executor_6 = - TransactionExecutor::new(data_store_6.clone(), Some(malicious_falcon_auth)); + TransactionExecutor::new(tx_context_6.clone(), Some(malicious_falcon_auth)); executor_6.load_account(malicious_account_id).unwrap(); - let block_ref_6 = data_store_6.block_header().block_num(); - let note_ids_6 = data_store_6.input_notes().iter().map(|note| note.id()).collect::>(); + let block_ref_6 = tx_context_6.tx_inputs().block_header().block_num(); + let note_ids_6 = tx_context_6.input_notes().iter().map(|note| note.id()).collect::>(); // Execute the transaction and get the witness let executed_transaction_6 = executor_6.execute_transaction( diff --git a/miden-tx/tests/integration/scripts/swap.rs b/miden-tx/tests/integration/scripts/swap.rs index a420228f8..1f569f35d 100644 --- a/miden-tx/tests/integration/scripts/swap.rs +++ b/miden-tx/tests/integration/scripts/swap.rs @@ -15,7 +15,7 @@ use miden_objects::{ transaction::TransactionArgs, Felt, ZERO, }; -use miden_tx::{testing::data_store::MockDataStore, TransactionExecutor}; +use miden_tx::{testing::TransactionContextBuilder, TransactionExecutor}; use crate::{ get_account_with_default_account_code, get_new_pk_and_authenticator, @@ -60,16 +60,17 @@ fn prove_swap_script() { // CONSTRUCT AND EXECUTE TX (Success) // -------------------------------------------------------------------------------------------- - let data_store = - MockDataStore::with_existing(Some(target_account.clone()), Some(vec![note.clone()])); + let tx_context = TransactionContextBuilder::new(target_account.clone()) + .input_notes(vec![note.clone()]) + .build(); let mut executor = - TransactionExecutor::new(data_store.clone(), Some(target_falcon_auth.clone())); + TransactionExecutor::new(tx_context.clone(), Some(target_falcon_auth.clone())); executor.load_account(target_account_id).unwrap(); - let block_ref = data_store.block_header().block_num(); - let note_ids = data_store - .tx_inputs + let block_ref = tx_context.tx_inputs().block_header().block_num(); + let note_ids = tx_context + .tx_inputs() .input_notes() .iter() .map(|note| note.id()) diff --git a/miden-tx/tests/integration/wallet/mod.rs b/miden-tx/tests/integration/wallet/mod.rs index b29ee9fb8..7e4be695a 100644 --- a/miden-tx/tests/integration/wallet/mod.rs +++ b/miden-tx/tests/integration/wallet/mod.rs @@ -17,7 +17,7 @@ use miden_objects::{ transaction::TransactionArgs, Felt, Word, ONE, ZERO, }; -use miden_tx::{testing::data_store::MockDataStore, TransactionExecutor}; +use miden_tx::{testing::TransactionContextBuilder, TransactionExecutor}; use rand_chacha::{rand_core::SeedableRng, ChaCha20Rng}; use crate::{ @@ -62,15 +62,17 @@ fn prove_receive_asset_via_wallet() { // CONSTRUCT AND EXECUTE TX (Success) // -------------------------------------------------------------------------------------------- - let data_store = MockDataStore::with_existing(Some(target_account.clone()), Some(vec![note])); + let tx_context = TransactionContextBuilder::new(target_account.clone()) + .input_notes(vec![note]) + .build(); let mut executor = - TransactionExecutor::new(data_store.clone(), Some(target_falcon_auth.clone())); + TransactionExecutor::new(tx_context.clone(), Some(target_falcon_auth.clone())); executor.load_account(target_account.id()).unwrap(); - let block_ref = data_store.block_header().block_num(); - let note_ids = data_store - .tx_inputs + let block_ref = tx_context.tx_inputs().block_header().block_num(); + let note_ids = tx_context + .tx_inputs() .input_notes() .iter() .map(|note| note.id()) @@ -123,15 +125,15 @@ fn prove_send_asset_via_wallet() { // CONSTRUCT AND EXECUTE TX (Success) // -------------------------------------------------------------------------------------------- - let data_store = MockDataStore::with_existing(Some(sender_account.clone()), Some(vec![])); + let tx_context = TransactionContextBuilder::new(sender_account.clone()).build(); let mut executor = - TransactionExecutor::new(data_store.clone(), Some(sender_falcon_auth.clone())); + TransactionExecutor::new(tx_context.clone(), Some(sender_falcon_auth.clone())); executor.load_account(sender_account.id()).unwrap(); - let block_ref = data_store.block_header().block_num(); - let note_ids = data_store - .tx_inputs + let block_ref = tx_context.tx_inputs().block_header().block_num(); + let note_ids = tx_context + .tx_inputs() .input_notes() .iter() .map(|note| note.id()) @@ -183,7 +185,7 @@ fn prove_send_asset_via_wallet() { // vault delta let sender_account_after: Account = Account::from_parts( - data_store.account().id(), + tx_context.account().id(), AssetVault::new(&[]).unwrap(), sender_account_storage, sender_account_code, diff --git a/objects/src/notes/file.rs b/objects/src/notes/file.rs index eec4fbdb2..c34d879a4 100644 --- a/objects/src/notes/file.rs +++ b/objects/src/notes/file.rs @@ -108,6 +108,7 @@ mod tests { Note, NoteAssets, NoteFile, NoteInclusionProof, NoteInputs, NoteMetadata, NoteRecipient, NoteScript, NoteTag, NoteType, }, + testing::notes::DEFAULT_NOTE_CODE, }; fn create_example_note() -> Note { @@ -117,7 +118,7 @@ mod tests { )); let serial_num = [Felt::new(0), Felt::new(1), Felt::new(2), Felt::new(3)]; - let note_program_ast = ProgramAst::parse("begin push.1 drop end").unwrap(); + let note_program_ast = ProgramAst::parse(DEFAULT_NOTE_CODE).unwrap(); let (script, _) = NoteScript::new(note_program_ast, &Assembler::default()).unwrap(); let note_inputs = NoteInputs::new(vec![target.into()]).unwrap(); let recipient = NoteRecipient::new(serial_num, script, note_inputs); diff --git a/objects/src/testing/account.rs b/objects/src/testing/account.rs index 673e6d8d4..a28489663 100644 --- a/objects/src/testing/account.rs +++ b/objects/src/testing/account.rs @@ -13,9 +13,7 @@ use vm_core::FieldElement; use super::{ account_code::DEFAULT_ACCOUNT_CODE, account_id::{str_to_account_code, AccountIdBuilder}, - constants::{ - self, FUNGIBLE_ASSET_AMOUNT, FUNGIBLE_FAUCET_INITIAL_BALANCE, NON_FUNGIBLE_ASSET_DATA, - }, + constants::{self, FUNGIBLE_ASSET_AMOUNT, NON_FUNGIBLE_ASSET_DATA}, storage::{AccountStorageBuilder, FAUCET_STORAGE_DATA_SLOT}, }; use crate::{ @@ -178,7 +176,7 @@ impl std::error::Error for AccountBuilderError {} // ================================================================================================ impl Account { - /// Creates a mock account with a defined number of assets and storage + /// Creates a mock account with a defined number of assets and storage pub fn mock(account_id: u64, nonce: Felt, account_code: AccountCode) -> Self { let account_storage = AccountStorage::mock(); @@ -195,14 +193,9 @@ impl Account { pub fn mock_fungible_faucet( account_id: u64, nonce: Felt, - empty_reserved_slot: bool, + initial_balance: Felt, assembler: &Assembler, ) -> Self { - let initial_balance = if empty_reserved_slot { - ZERO - } else { - Felt::new(FUNGIBLE_FAUCET_INITIAL_BALANCE) - }; let account_storage = AccountStorage::new( vec![SlotItem { index: FAUCET_STORAGE_DATA_SLOT, @@ -281,21 +274,3 @@ impl AssetVault { .unwrap() } } - -#[derive(Debug, PartialEq)] -pub enum MockAccountType { - StandardNew { - account_id: u64, - }, - StandardExisting, - FungibleFaucet { - acct_id: u64, - nonce: Felt, - empty_reserved_slot: bool, - }, - NonFungibleFaucet { - acct_id: u64, - nonce: Felt, - empty_reserved_slot: bool, - }, -} diff --git a/objects/src/testing/account_code.rs b/objects/src/testing/account_code.rs index 77aa057ac..ed3081299 100644 --- a/objects/src/testing/account_code.rs +++ b/objects/src/testing/account_code.rs @@ -29,14 +29,14 @@ pub const ACCOUNT_ACCOUNT_PROCEDURE_1_MAST_ROOT: &str = MASTS[9]; pub const ACCOUNT_ACCOUNT_PROCEDURE_2_MAST_ROOT: &str = MASTS[10]; pub const CODE: &str = " - export.foo - push.1 push.2 mul - end + export.foo + push.1 push.2 mul + end - export.bar - push.1 push.2 add - end - "; + export.bar + push.1 push.2 add + end +"; // ACCOUNT ASSEMBLY CODE // ================================================================================================ diff --git a/objects/src/testing/notes.rs b/objects/src/testing/notes.rs index a71e59a46..5298d294d 100644 --- a/objects/src/testing/notes.rs +++ b/objects/src/testing/notes.rs @@ -6,35 +6,18 @@ use alloc::{ use assembly::Assembler; use rand::Rng; -use super::{ - account_code::{ACCOUNT_ADD_ASSET_TO_NOTE_MAST_ROOT, ACCOUNT_CREATE_NOTE_MAST_ROOT}, - constants::{ - CONSUMED_ASSET_1_AMOUNT, CONSUMED_ASSET_2_AMOUNT, CONSUMED_ASSET_3_AMOUNT, - NON_FUNGIBLE_ASSET_DATA_2, - }, - prepare_word, - storage::prepare_assets, -}; use crate::{ - accounts::{ - account_id::testing::{ - ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_1, ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_2, - ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_3, ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, - ACCOUNT_ID_SENDER, - }, - AccountId, - }, + accounts::AccountId, assembly::ProgramAst, - assets::{Asset, FungibleAsset}, + assets::Asset, notes::{ Note, NoteAssets, NoteInclusionProof, NoteInputs, NoteMetadata, NoteRecipient, NoteScript, NoteTag, NoteType, }, - transaction::OutputNote, Felt, NoteError, Word, ZERO, }; -const DEFAULT_NOTE_CODE: &str = "\ +pub const DEFAULT_NOTE_CODE: &str = "\ begin end "; @@ -74,9 +57,10 @@ impl NoteBuilder { } } - pub fn note_inputs(mut self, inputs: Vec) -> Result { + pub fn note_inputs(mut self, inputs: impl AsRef<[Felt]>) -> Result { + let inputs = inputs.as_ref(); NoteInputs::new(inputs.to_vec())?; - self.inputs = inputs; + self.inputs = inputs.to_vec(); Ok(self) } @@ -105,9 +89,9 @@ impl NoteBuilder { self } - pub fn build(self, assembler: Assembler) -> Result { + pub fn build(self, assembler: &Assembler) -> Result { let note_ast = ProgramAst::parse(&self.code).unwrap(); - let (note_script, _) = NoteScript::new(note_ast, &assembler)?; + let (note_script, _) = NoteScript::new(note_ast, assembler)?; let vault = NoteAssets::new(self.assets)?; let metadata = NoteMetadata::new(self.sender, self.note_type, self.tag, self.aux)?; let inputs = NoteInputs::new(self.inputs)?; @@ -126,239 +110,3 @@ pub enum AssetPreservationStatus { TooManyFungibleInput, TooManyNonFungibleInput, } - -pub fn mock_notes( - assembler: &Assembler, - asset_preservation: &AssetPreservationStatus, -) -> (Vec, Vec) { - let mut serial_num_gen = SerialNumGenerator::new(); - - // ACCOUNT IDS - // -------------------------------------------------------------------------------------------- - let sender = AccountId::try_from(ACCOUNT_ID_SENDER).unwrap(); - let faucet_id_1 = AccountId::try_from(ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_1).unwrap(); - let faucet_id_2 = AccountId::try_from(ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_2).unwrap(); - let faucet_id_3 = AccountId::try_from(ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_3).unwrap(); - - // ASSETS - // -------------------------------------------------------------------------------------------- - let fungible_asset_1: Asset = - FungibleAsset::new(faucet_id_1, CONSUMED_ASSET_1_AMOUNT).unwrap().into(); - let fungible_asset_2: Asset = - FungibleAsset::new(faucet_id_2, CONSUMED_ASSET_2_AMOUNT).unwrap().into(); - let fungible_asset_3: Asset = - FungibleAsset::new(faucet_id_3, CONSUMED_ASSET_3_AMOUNT).unwrap().into(); - - // CREATED NOTES - // -------------------------------------------------------------------------------------------- - let note_program_ast = ProgramAst::parse("begin push.1 drop end").unwrap(); - let (note_script, _) = NoteScript::new(note_program_ast, assembler).unwrap(); - - let inputs = NoteInputs::new(vec![Felt::new(1)]).unwrap(); - let vault = NoteAssets::new(vec![fungible_asset_1]).unwrap(); - let metadata = NoteMetadata::new(sender, NoteType::Public, 0.into(), ZERO).unwrap(); - let recipient = NoteRecipient::new(serial_num_gen.next(), note_script.clone(), inputs); - let created_note_1 = Note::new(vault, metadata, recipient); - - let inputs = NoteInputs::new(vec![Felt::new(2)]).unwrap(); - let vault = NoteAssets::new(vec![fungible_asset_2]).unwrap(); - let metadata = NoteMetadata::new(sender, NoteType::Public, 0.into(), ZERO).unwrap(); - let recipient = NoteRecipient::new(serial_num_gen.next(), note_script.clone(), inputs); - let created_note_2 = Note::new(vault, metadata, recipient); - - let inputs = NoteInputs::new(vec![Felt::new(3)]).unwrap(); - let vault = NoteAssets::new(vec![fungible_asset_3]).unwrap(); - let metadata = NoteMetadata::new(sender, NoteType::Public, 0.into(), ZERO).unwrap(); - let recipient = NoteRecipient::new(serial_num_gen.next(), note_script.clone(), inputs); - let created_note_3 = Note::new(vault, metadata, recipient); - - // CONSUMED NOTES - // -------------------------------------------------------------------------------------------- - - let note_1_script_src = format!( - "\ - begin - # create note 0 - push.{recipient0} - push.{PUBLIC_NOTE} - push.{aux0} - push.{tag0} - # MAST root of the `create_note` mock account procedure - call.{ACCOUNT_CREATE_NOTE_MAST_ROOT} - - push.{asset0} movup.4 - call.{ACCOUNT_ADD_ASSET_TO_NOTE_MAST_ROOT} - dropw dropw dropw - - # create note 1 - push.{recipient1} - push.{PUBLIC_NOTE} - push.{aux1} - push.{tag1} - # MAST root of the `create_note` mock account procedure - call.{ACCOUNT_CREATE_NOTE_MAST_ROOT} - - push.{asset1} movup.4 - call.{ACCOUNT_ADD_ASSET_TO_NOTE_MAST_ROOT} - dropw dropw dropw - end - ", - PUBLIC_NOTE = NoteType::Public as u8, - recipient0 = prepare_word(&created_note_1.recipient().digest()), - aux0 = created_note_1.metadata().aux(), - tag0 = created_note_1.metadata().tag(), - asset0 = prepare_assets(created_note_1.assets())[0], - recipient1 = prepare_word(&created_note_2.recipient().digest()), - aux1 = created_note_2.metadata().aux(), - tag1 = created_note_2.metadata().tag(), - asset1 = prepare_assets(created_note_2.assets())[0], - ); - let note_1_script_ast = ProgramAst::parse(¬e_1_script_src).unwrap(); - let (note_1_script, _) = NoteScript::new(note_1_script_ast, assembler).unwrap(); - let metadata = NoteMetadata::new(sender, NoteType::Public, 0.into(), ZERO).unwrap(); - let vault = NoteAssets::new(vec![fungible_asset_1]).unwrap(); - let inputs = NoteInputs::new(vec![Felt::new(1)]).unwrap(); - let recipient = NoteRecipient::new(serial_num_gen.next(), note_1_script, inputs); - let consumed_note_1 = Note::new(vault, metadata, recipient); - - let note_2_script_src = format!( - "\ - begin - # create note 2 - push.{recipient} - push.{PUBLIC_NOTE} - push.{aux} - push.{tag} - # MAST root of the `create_note` mock account procedure - call.{ACCOUNT_CREATE_NOTE_MAST_ROOT} - - push.{asset} movup.4 - call.{ACCOUNT_ADD_ASSET_TO_NOTE_MAST_ROOT} - dropw dropw dropw - end - ", - PUBLIC_NOTE = NoteType::Public as u8, - recipient = prepare_word(&created_note_3.recipient().digest()), - aux = created_note_3.metadata().aux(), - tag = created_note_3.metadata().tag(), - asset = prepare_assets(created_note_3.assets())[0], - ); - let note_2_script_ast = ProgramAst::parse(¬e_2_script_src).unwrap(); - let (note_2_script, _) = NoteScript::new(note_2_script_ast, assembler).unwrap(); - let metadata = NoteMetadata::new(sender, NoteType::Public, 0.into(), ZERO).unwrap(); - let vault = NoteAssets::new(vec![fungible_asset_2, fungible_asset_3]).unwrap(); - let inputs = NoteInputs::new(vec![Felt::new(2)]).unwrap(); - let recipient = NoteRecipient::new(serial_num_gen.next(), note_2_script, inputs); - let consumed_note_2 = Note::new(vault, metadata, recipient); - - let note_3_script_ast = ProgramAst::parse("begin push.1 drop end").unwrap(); - let (note_3_script, _) = NoteScript::new(note_3_script_ast, assembler).unwrap(); - let metadata = NoteMetadata::new(sender, NoteType::Public, 0.into(), ZERO).unwrap(); - let vault = NoteAssets::new(vec![fungible_asset_2, fungible_asset_3]).unwrap(); - let inputs = NoteInputs::new(vec![Felt::new(2)]).unwrap(); - let recipient = NoteRecipient::new(serial_num_gen.next(), note_3_script, inputs); - let consumed_note_3 = Note::new(vault, metadata, recipient); - - let note_4_script_ast = ProgramAst::parse("begin push.1 drop end").unwrap(); - let (note_4_script, _) = NoteScript::new(note_4_script_ast, assembler).unwrap(); - let metadata = NoteMetadata::new(sender, NoteType::Public, 0.into(), ZERO).unwrap(); - let vault = NoteAssets::new(vec![Asset::mock_non_fungible( - ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, - &NON_FUNGIBLE_ASSET_DATA_2, - )]) - .unwrap(); - let inputs = NoteInputs::new(vec![Felt::new(1)]).unwrap(); - let recipient = NoteRecipient::new(serial_num_gen.next(), note_4_script, inputs); - let consumed_note_4 = Note::new(vault, metadata, recipient); - - // note that changes the account vault - let note_5_script_ast = ProgramAst::parse( - "\ - use.miden::note - use.miden::contracts::wallets::basic->wallet - - begin - # read the assets to memory - push.0 exec.note::get_assets - # => [num_assets, dest_ptr] - - # assert the number of assets is 3 - push.3 assert_eq - # => [dest_ptr] - - # add the first asset to the vault - padw dup.4 mem_loadw call.wallet::receive_asset dropw - # => [dest_ptr] - - # add the second asset to the vault - push.1 add padw dup.4 mem_loadw call.wallet::receive_asset dropw - # => [dest_ptr+1] - - # add the third asset to the vault - push.1 add padw movup.4 mem_loadw call.wallet::receive_asset dropw - # => [] - end - ", - ) - .unwrap(); - let (note_5_script, _) = NoteScript::new(note_5_script_ast, assembler).unwrap(); - - let metadata = NoteMetadata::new(sender, NoteType::Public, 0.into(), ZERO).unwrap(); - let vault = NoteAssets::new(vec![ - fungible_asset_1, - fungible_asset_3, - Asset::mock_non_fungible( - ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, - &NON_FUNGIBLE_ASSET_DATA_2, - ), - ]) - .unwrap(); - - let inputs = NoteInputs::new(vec![]).unwrap(); - let recipient = NoteRecipient::new(serial_num_gen.next(), note_5_script, inputs); - let consumed_note_5 = Note::new(vault, metadata, recipient); - - let consumed_notes = match asset_preservation { - AssetPreservationStatus::TooFewInput => vec![consumed_note_1], - AssetPreservationStatus::Preserved => { - vec![consumed_note_1, consumed_note_2] - }, - AssetPreservationStatus::PreservedWithAccountVaultDelta => { - vec![consumed_note_1, consumed_note_2, consumed_note_5] - }, - AssetPreservationStatus::TooManyFungibleInput => { - vec![consumed_note_1, consumed_note_2, consumed_note_3] - }, - AssetPreservationStatus::TooManyNonFungibleInput => { - vec![consumed_note_1, consumed_note_2, consumed_note_4] - }, - }; - let created_notes = vec![ - OutputNote::Full(created_note_1), - OutputNote::Full(created_note_2), - OutputNote::Full(created_note_3), - ]; - - (consumed_notes, created_notes) -} - -struct SerialNumGenerator { - state: u64, -} - -impl SerialNumGenerator { - pub fn new() -> Self { - Self { state: 0 } - } - - pub fn next(&mut self) -> Word { - let serial_num = [ - Felt::new(self.state), - Felt::new(self.state + 1), - Felt::new(self.state + 2), - Felt::new(self.state + 3), - ]; - self.state += 4; - serial_num - } -} diff --git a/objects/src/testing/storage.rs b/objects/src/testing/storage.rs index 2bff6725a..a20d8aabc 100644 --- a/objects/src/testing/storage.rs +++ b/objects/src/testing/storage.rs @@ -4,7 +4,7 @@ use assembly::Assembler; use vm_core::{Felt, FieldElement, Word, ZERO}; use vm_processor::Digest; -use super::prepare_word; +use super::{constants::FUNGIBLE_FAUCET_INITIAL_BALANCE, prepare_word}; use crate::{ accounts::{ account_id::testing::{ @@ -148,7 +148,7 @@ pub fn generate_account_seed( Account::mock_fungible_faucet( ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_ON_CHAIN, ZERO, - false, + Felt::new(FUNGIBLE_FAUCET_INITIAL_BALANCE), assembler, ), AccountType::FungibleFaucet, @@ -157,7 +157,7 @@ pub fn generate_account_seed( Account::mock_fungible_faucet( ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_ON_CHAIN, ZERO, - true, + ZERO, assembler, ), AccountType::FungibleFaucet,