diff --git a/Cargo.toml b/Cargo.toml index 666679cc6..3e10070f0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,6 @@ codegen-units = 1 lto = true [workspace.dependencies] -assembly = { package = "miden-assembly", git = "https://github.com/0xPolygonMiden/miden-vm.git", branch = "next", default-features = false } -miden-verifier = { package = "miden-verifier", git = "https://github.com/0xPolygonMiden/miden-vm.git", branch = "next", default-features = false } -vm-processor = { package = "miden-processor", git = "https://github.com/0xPolygonMiden/miden-vm.git", branch = "next", default-features = false } +assembly = { package = "miden-assembly", git = "https://github.com/0xPolygonMiden/miden-vm.git", branch = "plafer-fix-build-smt", default-features = false } +miden-verifier = { package = "miden-verifier", git = "https://github.com/0xPolygonMiden/miden-vm.git", branch = "plafer-fix-build-smt", default-features = false } +vm-processor = { package = "miden-processor", git = "https://github.com/0xPolygonMiden/miden-vm.git", branch = "plafer-fix-build-smt", default-features = false } diff --git a/miden-lib/Cargo.toml b/miden-lib/Cargo.toml index 496bf6a3c..c85c26ec9 100644 --- a/miden-lib/Cargo.toml +++ b/miden-lib/Cargo.toml @@ -20,7 +20,7 @@ testing = ["miden-objects/testing"] [dependencies] miden-objects = { package = "miden-objects", path = "../objects", default-features = false } -miden-stdlib = { package = "miden-stdlib", git = "https://github.com/0xPolygonMiden/miden-vm.git", branch = "next", default-features = false } +miden-stdlib = { package = "miden-stdlib", git = "https://github.com/0xPolygonMiden/miden-vm.git", branch = "plafer-fix-build-smt", default-features = false } [dev-dependencies] miden-objects = { package = "miden-objects", path = "../objects", default-features = false, features = ["testing" ]} diff --git a/miden-lib/src/tests/test_account.rs b/miden-lib/src/tests/test_account.rs index a732cade1..de4c0a683 100644 --- a/miden-lib/src/tests/test_account.rs +++ b/miden-lib/src/tests/test_account.rs @@ -1,7 +1,11 @@ -use miden_objects::accounts::{ - AccountId, AccountType, ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN, ACCOUNT_ID_INSUFFICIENT_ONES, - ACCOUNT_ID_NON_FUNGIBLE_FAUCET_OFF_CHAIN, ACCOUNT_ID_REGULAR_ACCOUNT_IMMUTABLE_CODE_ON_CHAIN, - ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, +use miden_objects::{ + accounts::{ + AccountId, AccountType, ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN, ACCOUNT_ID_INSUFFICIENT_ONES, + ACCOUNT_ID_NON_FUNGIBLE_FAUCET_OFF_CHAIN, + ACCOUNT_ID_REGULAR_ACCOUNT_IMMUTABLE_CODE_ON_CHAIN, + ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, + }, + crypto::merkle::LeafIndex, }; use mock::{ constants::{ @@ -264,9 +268,9 @@ fn test_set_item() { let init_root = account_smt.root(); // insert a new leaf value - const NEW_ITEM_INDEX: u64 = 12; - const NEW_ITEM_VALUE: Word = [Felt::new(91), Felt::new(92), Felt::new(93), Felt::new(94)]; - account_smt.update_leaf(NEW_ITEM_INDEX, NEW_ITEM_VALUE).unwrap(); + let new_item_index = LeafIndex::new(12).unwrap(); + let new_item_value: Word = [Felt::new(91), Felt::new(92), Felt::new(93), Felt::new(94)]; + account_smt.insert(new_item_index, new_item_value); assert_ne!(account_smt.root(), init_root); let code = format!( @@ -283,7 +287,7 @@ fn test_set_item() { push.{new_value} # push the account storage item index - push.{NEW_ITEM_INDEX} + push.{new_item_index} # get the item exec.account::set_item @@ -298,7 +302,8 @@ fn test_set_item() { push.{new_root} assert_eqw end ", - new_value = prepare_word(&NEW_ITEM_VALUE), + new_value = prepare_word(&new_item_value), + new_item_index = new_item_index.value(), new_root = prepare_word(&account_smt.root()), ); @@ -385,9 +390,12 @@ fn test_authenticate_procedure() { mock_inputs(MockAccountType::StandardExisting, AssetPreservationStatus::Preserved); let account = tx_inputs.account(); + let proc0_index = LeafIndex::new(0).unwrap(); + let proc1_index = LeafIndex::new(1).unwrap(); + let test_cases = vec![ - (account.code().procedure_tree().get_leaf(0).unwrap(), true), - (account.code().procedure_tree().get_leaf(1).unwrap(), true), + (account.code().procedure_tree().get_leaf(&proc0_index), true), + (account.code().procedure_tree().get_leaf(&proc1_index), true), ([ONE, ZERO, ONE, ZERO], false), ]; diff --git a/miden-tx/Cargo.toml b/miden-tx/Cargo.toml index 65954a18c..25a5fad70 100644 --- a/miden-tx/Cargo.toml +++ b/miden-tx/Cargo.toml @@ -19,7 +19,7 @@ std = ["miden-lib/std", "miden-objects/std", "miden-prover/std", "miden-verifier [dependencies] miden-lib = { package = "miden-lib", path = "../miden-lib", default-features = false } miden-objects = { package = "miden-objects", path = "../objects", default-features = false } -miden-prover = { package = "miden-prover", git = "https://github.com/0xPolygonMiden/miden-vm.git", branch = "next", default-features = false } +miden-prover = { package = "miden-prover", git = "https://github.com/0xPolygonMiden/miden-vm.git", branch = "plafer-fix-build-smt", default-features = false } miden-verifier = { workspace = true } vm-processor = { workspace = true } diff --git a/mock/Cargo.toml b/mock/Cargo.toml index 3d45aa7bb..ed937ad07 100644 --- a/mock/Cargo.toml +++ b/mock/Cargo.toml @@ -26,7 +26,7 @@ env_logger = { version = "0.10" } hex = "0.4" miden-lib = { path = "../miden-lib" } miden-objects = { path = "../objects" , features = ["serde", "log", "testing"]} -miden-test-utils = { package = "miden-test-utils", git = "https://github.com/0xPolygonMiden/miden-vm.git", branch = "next", default-features = false } +miden-test-utils = { package = "miden-test-utils", git = "https://github.com/0xPolygonMiden/miden-vm.git", branch = "plafer-fix-build-smt", default-features = false } postcard = { version = "1.0", features = [ "alloc" ] } rand = { version = "0.8" } rand_pcg = { version = "0.3", features = ["serde1"] } diff --git a/mock/src/mock/block.rs b/mock/src/mock/block.rs index b3cce0dcd..0c39eef01 100644 --- a/mock/src/mock/block.rs +++ b/mock/src/mock/block.rs @@ -1,6 +1,6 @@ use miden_objects::{ accounts::Account, crypto::merkle::SimpleSmt, utils::collections::Vec, BlockHeader, Digest, - Felt, StarkField, ZERO, + Felt, StarkField, ACCOUNT_TREE_DEPTH, ZERO, }; use miden_test_utils::rand; @@ -10,8 +10,7 @@ pub fn mock_block_header( note_root: Option, accts: &[Account], ) -> BlockHeader { - let acct_db = SimpleSmt::with_leaves( - 64, + let acct_db = SimpleSmt::::with_leaves( accts .iter() .flat_map(|acct| { diff --git a/mock/src/mock/chain.rs b/mock/src/mock/chain.rs index a1447aba6..86ad36112 100644 --- a/mock/src/mock/chain.rs +++ b/mock/src/mock/chain.rs @@ -3,12 +3,13 @@ use core::fmt; use miden_objects::{ accounts::{Account, AccountId, AccountType, SlotItem}, assets::Asset, - crypto::merkle::{Mmr, NodeIndex, PartialMmr, SimpleSmt, TieredSmt}, - notes::{Note, NoteInclusionProof, NOTE_LEAF_DEPTH, NOTE_TREE_DEPTH}, + crypto::merkle::{Mmr, PartialMmr, SimpleSmt, TieredSmt}, + notes::{Note, NoteInclusionProof}, transaction::{ChainMmr, InputNote}, utils::collections::Vec, - BlockHeader, Digest, Felt, FieldElement, StarkField, Word, + BlockHeader, Digest, Felt, FieldElement, Word, ACCOUNT_TREE_DEPTH, NOTE_TREE_DEPTH, }; +use miden_test_utils::crypto::LeafIndex; use rand::{Rng, SeedableRng}; use super::{ @@ -60,7 +61,7 @@ impl Objects { &mut self, pending: &mut Objects, header: BlockHeader, - notes: &SimpleSmt, + notes: &SimpleSmt, ) { self.accounts.append(&mut pending.accounts); self.fungible_faucets.append(&mut pending.fungible_faucets); @@ -76,7 +77,7 @@ impl Objects { /// The root of the tree is a commitment to all notes created in the block. The commitment /// is not for all fields of the [Note] struct, but only for note metadata + core fields of /// a note (i.e., vault, inputs, script, and serial number). - pub fn build_notes_tree(&self) -> SimpleSmt { + pub fn build_notes_tree(&self) -> SimpleSmt { let mut entries = Vec::with_capacity(self.notes.len() * 2); entries.extend(self.notes.iter().enumerate().map(|(index, note)| { @@ -88,21 +89,22 @@ impl Objects { (tree_index, note.metadata().into()) })); - SimpleSmt::with_leaves(NOTE_LEAF_DEPTH, entries).unwrap() + SimpleSmt::with_leaves(entries).unwrap() } /// Given the [BlockHeader] and its notedb's [SimpleSmt], set all the [Note]'s proof. /// /// Update the [Note]'s proof once the [BlockHeader] has been created. - fn finalize_notes(&mut self, header: BlockHeader, notes: &SimpleSmt) -> Vec { + fn finalize_notes( + &mut self, + header: BlockHeader, + notes: &SimpleSmt, + ) -> Vec { self.notes .drain(..) .enumerate() .map(|(index, note)| { - let auth_index = - NodeIndex::new(NOTE_TREE_DEPTH, index as u64).expect("index bigger than 2**20"); - let note_path = - notes.get_path(auth_index).expect("auth_index outside of SimpleSmt range"); + let auth_index = LeafIndex::new(index as u64).expect("index bigger than 2**20"); InputNote::new( note.clone(), NoteInclusionProof::new( @@ -110,7 +112,7 @@ impl Objects { header.sub_hash(), header.note_root(), index as u64, - note_path, + notes.open(&auth_index).path, ) .expect("Invalid data provided to proof constructor"), ) @@ -133,8 +135,7 @@ pub struct MockChain { nullifiers: TieredSmt, /// Tree containing the latest hash of each account. - // TODO: change this to a TieredSmt with 64bit keys. - accounts: SimpleSmt, + accounts: SimpleSmt, /// RNG used to seed builders. /// @@ -199,7 +200,7 @@ impl MockChain { chain: Mmr::default(), blocks: vec![], nullifiers: TieredSmt::default(), - accounts: SimpleSmt::new(64).expect("depth too big for SimpleSmt"), + accounts: SimpleSmt::::new().expect("depth too big for SimpleSmt"), rng, account_id_builder, objects: Objects::new(), @@ -443,12 +444,10 @@ impl MockChain { let block_num: u32 = self.blocks.len().try_into().expect("usize to u32 failed"); for (account, _seed) in self.pending_objects.accounts.iter() { - let id: Felt = account.id().into(); - self.accounts.update_leaf(id.as_int(), account.hash().into()).unwrap(); + self.accounts.insert(account.id().into(), account.hash().into()); } for (account, _seed) in self.objects.accounts.iter() { - let id: Felt = account.id().into(); - self.accounts.update_leaf(id.as_int(), account.hash().into()).unwrap(); + self.accounts.insert(account.id().into(), account.hash().into()); } // TODO: @@ -606,12 +605,8 @@ pub fn mock_chain_data(consumed_notes: Vec) -> (ChainMmr, Vec) // 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 tree_index = 2 * index; - let smt_entries = vec![ - (tree_index as u64, note.id().into()), - ((tree_index + 1) as u64, note.metadata().into()), - ]; - let smt = SimpleSmt::with_leaves(NOTE_LEAF_DEPTH, smt_entries).unwrap(); + let smt_entries = vec![(index as u64, note.authentication_hash().into())]; + let smt = SimpleSmt::::with_leaves(smt_entries).unwrap(); note_trees.push(smt); } @@ -638,7 +633,7 @@ pub fn mock_chain_data(consumed_notes: Vec) -> (ChainMmr, Vec) .enumerate() .map(|(index, note)| { let block_header = &block_chain[index]; - let auth_index = NodeIndex::new(NOTE_TREE_DEPTH, index as u64).unwrap(); + let auth_index = LeafIndex::new(index as u64).unwrap(); InputNote::new( note, NoteInclusionProof::new( @@ -646,7 +641,7 @@ pub fn mock_chain_data(consumed_notes: Vec) -> (ChainMmr, Vec) block_header.sub_hash(), block_header.note_root(), index as u64, - note_trees[index].get_path(auth_index).unwrap(), + note_trees[index].open(&auth_index).path, ) .unwrap(), ) diff --git a/objects/Cargo.toml b/objects/Cargo.toml index eecdd8e0d..c8fcd6912 100644 --- a/objects/Cargo.toml +++ b/objects/Cargo.toml @@ -34,10 +34,10 @@ testing = [] [dependencies] assembly = { workspace = true } log = { version = "0.4", optional = true } -miden-crypto = { git = "https://github.com/0xPolygonMiden/crypto", branch = "next", default-features = false } +miden-crypto = { git = "https://github.com/0xPolygonMiden/crypto", branch = "plafer-smt-trait", default-features = false } miden-verifier = { workspace = true } serde = { version = "1.0", optional = true, default-features = false, features = ["derive"] } -vm-core = { package = "miden-core", git = "https://github.com/0xPolygonMiden/miden-vm.git", branch = "next", default-features = false } +vm-core = { package = "miden-core", git = "https://github.com/0xPolygonMiden/miden-vm.git", branch = "plafer-fix-build-smt", default-features = false } vm-processor = { workspace = true } [dev-dependencies] diff --git a/objects/src/accounts/account_id.rs b/objects/src/accounts/account_id.rs index 0b52570fd..125faf822 100644 --- a/objects/src/accounts/account_id.rs +++ b/objects/src/accounts/account_id.rs @@ -4,7 +4,7 @@ use super::{ get_account_seed, Account, AccountError, ByteReader, Deserializable, DeserializationError, Digest, Felt, FieldElement, Hasher, Serializable, StarkField, String, ToString, Vec, Word, }; -use crate::utils::hex_to_bytes; +use crate::{crypto::merkle::LeafIndex, utils::hex_to_bytes, ACCOUNT_TREE_DEPTH}; // ACCOUNT ID // ================================================================================================ @@ -225,6 +225,27 @@ impl AccountId { } } +impl PartialOrd for AccountId { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for AccountId { + fn cmp(&self, other: &Self) -> core::cmp::Ordering { + self.0.as_int().cmp(&other.0.as_int()) + } +} + +impl fmt::Display for AccountId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "0x{:02x}", self.0.as_int()) + } +} + +// CONVERSIONS FROM ACCOUNT ID +// ================================================================================================ + impl From for Felt { fn from(id: AccountId) -> Self { id.0 @@ -245,6 +266,16 @@ impl From for u64 { } } +/// Account IDs are used as indexes in the account database, which is a tree of depth 64. +impl From for LeafIndex { + fn from(id: AccountId) -> Self { + LeafIndex::new_max_depth(id.0.as_int()) + } +} + +// CONVERSIONS TO ACCOUNT ID +// ================================================================================================ + impl TryFrom for AccountId { type Error = AccountError; @@ -274,24 +305,6 @@ impl TryFrom for AccountId { } } -impl fmt::Display for AccountId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "0x{:02x}", self.0.as_int()) - } -} - -impl PartialOrd for AccountId { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for AccountId { - fn cmp(&self, other: &Self) -> core::cmp::Ordering { - self.0.as_int().cmp(&other.0.as_int()) - } -} - // SERIALIZATION // ================================================================================================ diff --git a/objects/src/accounts/code.rs b/objects/src/accounts/code.rs index 9e1914547..1f12e79ba 100644 --- a/objects/src/accounts/code.rs +++ b/objects/src/accounts/code.rs @@ -14,6 +14,9 @@ use crate::crypto::merkle::SimpleSmt; /// Default serialization options for account code AST. const MODULE_SERDE_OPTIONS: AstSerdeOptions = AstSerdeOptions::new(true); +/// The depth of the Merkle tree that is used to commit to the account's public interface. +pub const PROCEDURE_TREE_DEPTH: u8 = 8; + // ACCOUNT CODE // ================================================================================================ @@ -26,7 +29,7 @@ const MODULE_SERDE_OPTIONS: AstSerdeOptions = AstSerdeOptions::new(true); pub struct AccountCode { module: ModuleAst, procedures: Vec, - procedure_tree: OnceCell, + procedure_tree: OnceCell>, } impl AccountCode { @@ -34,7 +37,7 @@ impl AccountCode { // -------------------------------------------------------------------------------------------- /// The depth of the Merkle tree that is used to commit to the account's public interface. - pub const PROCEDURE_TREE_DEPTH: u8 = 8; + pub const PROCEDURE_TREE_DEPTH: u8 = PROCEDURE_TREE_DEPTH; /// The maximum number of account interface procedures. pub const MAX_NUM_PROCEDURES: usize = 2_usize.pow(Self::PROCEDURE_TREE_DEPTH as u32); @@ -108,7 +111,7 @@ impl AccountCode { } /// Returns a reference to the procedure tree. - pub fn procedure_tree(&self) -> &SimpleSmt { + pub fn procedure_tree(&self) -> &SimpleSmt { // build procedure tree only when requested self.procedure_tree.get_or_init(|| build_procedure_tree(&self.procedures)) } @@ -178,7 +181,7 @@ impl Deserializable for AccountCode { // HELPER FUNCTIONS // ================================================================================================ -fn build_procedure_tree(procedures: &[Digest]) -> SimpleSmt { +fn build_procedure_tree(procedures: &[Digest]) -> SimpleSmt { // order the procedure digests to achieve a reproducible tree let procedures = { let mut procedures = procedures.to_vec(); @@ -186,8 +189,7 @@ fn build_procedure_tree(procedures: &[Digest]) -> SimpleSmt { procedures }; - SimpleSmt::with_leaves( - AccountCode::PROCEDURE_TREE_DEPTH, + SimpleSmt::::with_leaves( procedures .iter() .enumerate() diff --git a/objects/src/accounts/storage/mod.rs b/objects/src/accounts/storage/mod.rs index f97adb157..2e43ba499 100644 --- a/objects/src/accounts/storage/mod.rs +++ b/objects/src/accounts/storage/mod.rs @@ -5,8 +5,18 @@ use super::{ use crate::crypto::merkle::{NodeIndex, SimpleSmt}; mod slot; +use miden_crypto::{merkle::LeafIndex, ZERO}; pub use slot::StorageSlotType; +// CONSTANTS +// ================================================================================================ + +/// Depth of the storage tree. +pub const STORAGE_TREE_DEPTH: u8 = 8; + +/// TODO: should come from SimpleSmt::EMPTY_VALUE. +pub const EMPTY_VALUE: Word = [ZERO; 4]; + // TYPE ALIASES // ================================================================================================ @@ -35,7 +45,7 @@ pub type StorageSlot = (StorageSlotType, Word); /// and contains information about slot types of all other slots. #[derive(Debug, Clone, PartialEq, Eq)] pub struct AccountStorage { - slots: SimpleSmt, + slots: SimpleSmt, layout: Vec, } @@ -44,7 +54,7 @@ impl AccountStorage { // -------------------------------------------------------------------------------------------- /// Depth of the storage tree. - pub const STORAGE_TREE_DEPTH: u8 = 8; + pub const STORAGE_TREE_DEPTH: u8 = STORAGE_TREE_DEPTH; /// Total number of storage slots. pub const NUM_STORAGE_SLOTS: usize = 256; @@ -84,7 +94,7 @@ impl AccountStorage { )); // construct storage slots smt and populate the types vector. - let slots = SimpleSmt::with_leaves(Self::STORAGE_TREE_DEPTH, entires) + let slots = SimpleSmt::::with_leaves(entires) .map_err(AccountError::DuplicateStorageItems)?; Ok(Self { slots, layout }) @@ -108,7 +118,7 @@ impl AccountStorage { } /// Returns a reference to the sparse Merkle tree that backs the storage slots. - pub fn slots(&self) -> &SimpleSmt { + pub fn slots(&self) -> &SimpleSmt { &self.slots } @@ -173,10 +183,8 @@ impl AccountStorage { } // update the slot and return - let slot_value = self - .slots - .update_leaf(index as u64, value) - .expect("index is u8 - index within range"); + let index = LeafIndex::new(index as u64).expect("index is u8 - index within range"); + let slot_value = self.slots.insert(index, value); Ok(slot_value) } } @@ -208,8 +216,7 @@ impl Serializable for AccountStorage { .leaves() .filter(|(idx, &value)| { // TODO: consider checking empty values for complex types as well - value != SimpleSmt::EMPTY_VALUE - && *idx as u8 != AccountStorage::SLOT_LAYOUT_COMMITMENT_INDEX + value != EMPTY_VALUE && *idx as u8 != AccountStorage::SLOT_LAYOUT_COMMITMENT_INDEX }) .collect::>(); diff --git a/objects/src/lib.rs b/objects/src/lib.rs index 83a180f36..735faa6cd 100644 --- a/objects/src/lib.rs +++ b/objects/src/lib.rs @@ -52,3 +52,12 @@ pub mod vm { pub use vm_core::{code_blocks::CodeBlock, Program, ProgramInfo}; pub use vm_processor::{AdviceInputs, StackInputs, StackOutputs}; } + +// CONSTANTS +// ================================================================================================ + +/// Depth of the account database tree. +pub const ACCOUNT_TREE_DEPTH: u8 = 64; + +/// The depth of the Merkle tree used to commit to notes produced in a block. +pub const NOTE_TREE_DEPTH: u8 = 20; diff --git a/objects/src/notes/mod.rs b/objects/src/notes/mod.rs index 5d4b2ac1d..037d85966 100644 --- a/objects/src/notes/mod.rs +++ b/objects/src/notes/mod.rs @@ -10,7 +10,7 @@ use super::{ string::{String, ToString}, }, vm::CodeBlock, - Digest, Felt, Hasher, NoteError, Word, WORD_SIZE, ZERO, + Digest, Felt, Hasher, NoteError, Word, NOTE_TREE_DEPTH, WORD_SIZE, ZERO, }; mod envelope; @@ -40,9 +40,6 @@ pub use assets::NoteAssets; // CONSTANTS // ================================================================================================ -/// The depth of the Merkle tree used to commit to notes produced in a block. -pub const NOTE_TREE_DEPTH: u8 = 20; - /// The depth of the leafs in the note Merkle tree used to commit to notes produced in a block. /// This is equal `NOTE_TREE_DEPTH + 1`. In the kernel we do not authenticate leaf data directly /// but rather authenticate hash(left_leaf, right_leaf).