From af42659a932218c05d22b5434343c8df4b176baa Mon Sep 17 00:00:00 2001 From: polydez <155382956+polydez@users.noreply.github.com> Date: Tue, 30 Jul 2024 15:27:23 +0500 Subject: [PATCH 1/8] refactor: rename `NoteOrigin` to `NoteLocation` --- miden-lib/src/transaction/inputs.rs | 6 ++--- objects/src/errors.rs | 6 ++--- objects/src/notes/{origin.rs => location.rs} | 28 ++++++++++---------- objects/src/notes/mod.rs | 4 +-- objects/src/testing/block.rs | 4 +-- objects/src/transaction/inputs.rs | 12 ++++----- 6 files changed, 30 insertions(+), 30 deletions(-) rename objects/src/notes/{origin.rs => location.rs} (83%) diff --git a/miden-lib/src/transaction/inputs.rs b/miden-lib/src/transaction/inputs.rs index 1fd6eb51e..a68d0b9ec 100644 --- a/miden-lib/src/transaction/inputs.rs +++ b/miden-lib/src/transaction/inputs.rs @@ -326,15 +326,15 @@ fn add_input_notes_to_advice_inputs( inputs.extend_merkle_store( proof .note_path() - .inner_nodes(proof.origin().node_index.value(), note.hash()) + .inner_nodes(proof.location().node_index.value(), note.hash()) .unwrap(), ); - note_data.push(proof.origin().block_num.into()); + note_data.push(proof.location().block_num.into()); note_data.extend(*proof.sub_hash()); note_data.extend(*proof.note_root()); note_data.push( proof - .origin() + .location() .node_index .value() .try_into() diff --git a/objects/src/errors.rs b/objects/src/errors.rs index 830bc1a51..84b7e6f76 100644 --- a/objects/src/errors.rs +++ b/objects/src/errors.rs @@ -144,7 +144,7 @@ pub enum NoteError { InvalidNoteTagUseCase(u16), InvalidNoteType(NoteType), InvalidNoteTypeValue(u64), - InvalidOriginIndex(String), + InvalidLocationIndex(String), InvalidStubDataLen(usize), NetworkExecutionRequiresOnChainAccount, NetworkExecutionRequiresPublicNote(NoteType), @@ -164,8 +164,8 @@ impl NoteError { Self::DuplicateNonFungibleAsset(asset) } - pub fn invalid_origin_index(msg: String) -> Self { - Self::InvalidOriginIndex(msg) + pub fn invalid_location_index(msg: String) -> Self { + Self::InvalidLocationIndex(msg) } pub fn too_many_assets(num_assets: usize) -> Self { diff --git a/objects/src/notes/origin.rs b/objects/src/notes/location.rs similarity index 83% rename from objects/src/notes/origin.rs rename to objects/src/notes/location.rs index a23b7c10d..c88eb501e 100644 --- a/objects/src/notes/origin.rs +++ b/objects/src/notes/location.rs @@ -6,10 +6,10 @@ use super::{ }; use crate::crypto::merkle::{MerklePath, NodeIndex}; -/// Contains information about the origin of a note. +/// Contains information about the location of a note. #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] -pub struct NoteOrigin { +pub struct NoteLocation { /// The block number the note was created in. pub block_num: u32, @@ -21,8 +21,8 @@ pub struct NoteOrigin { #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct NoteInclusionProof { - /// Details about the note's origin. - origin: NoteOrigin, + /// Details about the note's location. + location: NoteLocation, /// The sub hash of the block the note was created in. sub_hash: Digest, @@ -44,9 +44,9 @@ impl NoteInclusionProof { note_path: MerklePath, ) -> Result { let node_index = NodeIndex::new(NOTE_TREE_DEPTH, index) - .map_err(|e| NoteError::invalid_origin_index(e.to_string()))?; + .map_err(|e| NoteError::invalid_location_index(e.to_string()))?; Ok(Self { - origin: NoteOrigin { block_num, node_index }, + location: NoteLocation { block_num, node_index }, sub_hash, note_root, note_path, @@ -66,9 +66,9 @@ impl NoteInclusionProof { self.note_root } - /// Returns the origin of the note. - pub fn origin(&self) -> &NoteOrigin { - &self.origin + /// Returns the location of the note. + pub fn location(&self) -> &NoteLocation { + &self.location } /// Returns the Merkle path to the note in the note Merkle tree of the block the note was @@ -81,14 +81,14 @@ impl NoteInclusionProof { // SERIALIZATION // ================================================================================================ -impl Serializable for NoteOrigin { +impl Serializable for NoteLocation { fn write_into(&self, target: &mut W) { target.write_u32(self.block_num); self.node_index.write_into(target); } } -impl Deserializable for NoteOrigin { +impl Deserializable for NoteLocation { fn read_from(source: &mut R) -> Result { let block_num = source.read_u32()?; let node_index = NodeIndex::read_from(source)?; @@ -99,7 +99,7 @@ impl Deserializable for NoteOrigin { impl Serializable for NoteInclusionProof { fn write_into(&self, target: &mut W) { - self.origin.write_into(target); + self.location.write_into(target); self.sub_hash.write_into(target); self.note_root.write_into(target); self.note_path.write_into(target); @@ -108,11 +108,11 @@ impl Serializable for NoteInclusionProof { impl Deserializable for NoteInclusionProof { fn read_from(source: &mut R) -> Result { - let origin = NoteOrigin::read_from(source)?; + let location = NoteLocation::read_from(source)?; let sub_hash = Digest::read_from(source)?; let note_root = Digest::read_from(source)?; let note_path = MerklePath::read_from(source)?; - Ok(Self { origin, sub_hash, note_root, note_path }) + Ok(Self { location, sub_hash, note_root, note_path }) } } diff --git a/objects/src/notes/mod.rs b/objects/src/notes/mod.rs index e7dd6aca6..0e312fafe 100644 --- a/objects/src/notes/mod.rs +++ b/objects/src/notes/mod.rs @@ -41,8 +41,8 @@ pub use note_type::NoteType; mod nullifier; pub use nullifier::Nullifier; -mod origin; -pub use origin::{NoteInclusionProof, NoteOrigin}; +mod location; +pub use location::{NoteInclusionProof, NoteLocation}; mod partial; pub use partial::PartialNote; diff --git a/objects/src/testing/block.rs b/objects/src/testing/block.rs index d82de7c21..5182d69ea 100644 --- a/objects/src/testing/block.rs +++ b/objects/src/testing/block.rs @@ -200,9 +200,9 @@ impl MockChain { for note in notes { let input_note = self.available_notes.get(note).unwrap().clone(); block_headers_map.insert( - input_note.origin().unwrap().block_num, + input_note.location().unwrap().block_num, self.blocks - .get(input_note.origin().unwrap().block_num as usize) + .get(input_note.location().unwrap().block_num as usize) .unwrap() .header(), ); diff --git a/objects/src/transaction/inputs.rs b/objects/src/transaction/inputs.rs index 728813d6c..6f5ac4d51 100644 --- a/objects/src/transaction/inputs.rs +++ b/objects/src/transaction/inputs.rs @@ -4,7 +4,7 @@ use core::fmt::Debug; use super::{BlockHeader, ChainMmr, Digest, Felt, Hasher, Word}; use crate::{ accounts::{Account, AccountId}, - notes::{Note, NoteId, NoteInclusionProof, NoteOrigin, Nullifier}, + notes::{Note, NoteId, NoteInclusionProof, NoteLocation, Nullifier}, utils::serde::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable}, TransactionInputError, MAX_INPUT_NOTES_PER_TX, }; @@ -60,7 +60,7 @@ impl TransactionInputs { // check the authentication paths of the input notes. for note in input_notes.iter() { if let InputNote::Authenticated { note, proof } = note { - let note_block_num = proof.origin().block_num; + let note_block_num = proof.location().block_num; let block_header = if note_block_num == block_num { &block_header @@ -369,15 +369,15 @@ impl InputNote { } } - /// Returns a reference to the origin of the note. - pub fn origin(&self) -> Option<&NoteOrigin> { - self.proof().map(|proof| proof.origin()) + /// Returns a reference to the location of the note. + pub fn location(&self) -> Option<&NoteLocation> { + self.proof().map(|proof| proof.location()) } } /// Returns true if this note belongs to the note tree of the specified block. fn is_in_block(note: &Note, proof: &NoteInclusionProof, block_header: &BlockHeader) -> bool { - let note_index = proof.origin().node_index.value(); + let note_index = proof.location().node_index.value(); let note_hash = note.hash(); proof.note_path().verify(note_index, note_hash, &block_header.note_root()) } From 8ce0a319ed07fc2b6e229eeb4e3ec1ab97025895 Mon Sep 17 00:00:00 2001 From: polydez <155382956+polydez@users.noreply.github.com> Date: Wed, 31 Jul 2024 23:21:56 +0500 Subject: [PATCH 2/8] refactor: simplify `NoteInclusionProof` --- miden-lib/src/transaction/inputs.rs | 32 ++++++++------ miden-tx/src/compiler/tests.rs | 9 +--- objects/src/block/note_tree.rs | 1 + objects/src/notes/file.rs | 9 +--- objects/src/notes/location.rs | 67 +++++++++++------------------ objects/src/testing/block.rs | 6 +-- objects/src/transaction/inputs.rs | 4 +- 7 files changed, 51 insertions(+), 77 deletions(-) diff --git a/miden-lib/src/transaction/inputs.rs b/miden-lib/src/transaction/inputs.rs index a68d0b9ec..88cb8c1ff 100644 --- a/miden-lib/src/transaction/inputs.rs +++ b/miden-lib/src/transaction/inputs.rs @@ -3,7 +3,7 @@ use alloc::vec::Vec; use miden_objects::{ accounts::Account, transaction::{ - ChainMmr, ExecutedTransaction, InputNote, InputNotes, PreparedTransaction, TransactionArgs, + ChainMmr, ExecutedTransaction, InputNote, PreparedTransaction, TransactionArgs, TransactionInputs, TransactionScript, TransactionWitness, }, vm::{AdviceInputs, StackInputs}, @@ -92,7 +92,7 @@ fn extend_advice_inputs( // build the advice map and Merkle store for relevant components add_chain_mmr_to_advice_inputs(tx_inputs.block_chain(), advice_inputs); add_account_to_advice_inputs(tx_inputs.account(), tx_inputs.account_seed(), advice_inputs); - add_input_notes_to_advice_inputs(tx_inputs.input_notes(), tx_args, advice_inputs); + add_input_notes_to_advice_inputs(tx_inputs, tx_args, advice_inputs); advice_inputs.extend(tx_args.advice_inputs().clone()); } @@ -265,29 +265,29 @@ fn add_account_to_advice_inputs( /// The advice provider is populated with: /// /// - For each note: -/// - The note's details (serial number, script root, and its' input / assets hash). +/// - The note's details (serial number, script root, and its input / assets hash). /// - The note's private arguments. /// - The note's public metadata. /// - The note's public inputs data. Prefixed by its length and padded to an even word length. /// - The note's asset padded. Prefixed by its length and padded to an even word length. -/// - For autheticated notes (determined by the `is_authenticated` flag): +/// - For authenticated notes (determined by the `is_authenticated` flag): /// - The note's authentication path against its block's note tree. /// - The block number, sub hash, note root. /// - The note's position in the note tree /// /// The data above is processed by `prologue::process_input_notes_data`. fn add_input_notes_to_advice_inputs( - notes: &InputNotes, + tx_inputs: &TransactionInputs, tx_args: &TransactionArgs, inputs: &mut AdviceInputs, ) { // if there are no input notes, nothing is added to the advice inputs - if notes.is_empty() { + if tx_inputs.input_notes().is_empty() { return; } let mut note_data = Vec::new(); - for input_note in notes.iter() { + for input_note in tx_inputs.input_notes().iter() { let note = input_note.note(); let assets = note.assets(); let recipient = note.recipient(); @@ -318,6 +318,11 @@ fn add_input_notes_to_advice_inputs( // insert note authentication path nodes into the Merkle store match input_note { InputNote::Authenticated { note, proof } => { + let note_block_header = tx_inputs + .block_chain() + .get_block(proof.location().block_num()) + .unwrap_or(tx_inputs.block_header()); + // NOTE: keep in sync with the `prologue::process_input_note` kernel procedure // Push the `is_authenticated` flag note_data.push(Felt::ONE); @@ -326,17 +331,16 @@ fn add_input_notes_to_advice_inputs( inputs.extend_merkle_store( proof .note_path() - .inner_nodes(proof.location().node_index.value(), note.hash()) + .inner_nodes(proof.location().node_index(), note.hash()) .unwrap(), ); - note_data.push(proof.location().block_num.into()); - note_data.extend(*proof.sub_hash()); - note_data.extend(*proof.note_root()); + note_data.push(proof.location().block_num().into()); + note_data.extend(note_block_header.sub_hash()); + note_data.extend(note_block_header.note_root()); note_data.push( proof .location() - .node_index - .value() + .node_index() .try_into() .expect("value is greater than or equal to the field modulus"), ); @@ -350,5 +354,5 @@ fn add_input_notes_to_advice_inputs( } // NOTE: keep map in sync with the `prologue::process_input_notes_data` kernel procedure - inputs.extend_map([(notes.commitment(), note_data)]); + inputs.extend_map([(tx_inputs.input_notes().commitment(), note_data)]); } diff --git a/miden-tx/src/compiler/tests.rs b/miden-tx/src/compiler/tests.rs index 4ddb782e0..fb496e030 100644 --- a/miden-tx/src/compiler/tests.rs +++ b/miden-tx/src/compiler/tests.rs @@ -182,14 +182,7 @@ fn test_transaction_compilation_succeeds() { let _account_code = tx_compiler.load_account(account_id, account_code_ast).unwrap(); let notes = mock_input_notes(&mut tx_compiler, account_id); - let mock_inclusion_proof = NoteInclusionProof::new( - Default::default(), - Default::default(), - Default::default(), - 0, - Default::default(), - ) - .unwrap(); + let mock_inclusion_proof = NoteInclusionProof::new(0, 0, Default::default()).unwrap(); let notes = notes .into_iter() .map(|note| InputNote::authenticated(note, mock_inclusion_proof.clone())) diff --git a/objects/src/block/note_tree.rs b/objects/src/block/note_tree.rs index b97053c06..4fb147cd0 100644 --- a/objects/src/block/note_tree.rs +++ b/objects/src/block/note_tree.rs @@ -96,6 +96,7 @@ impl BlockNoteIndex { (self.batch_idx() * MAX_NOTES_PER_BATCH + self.note_idx_in_batch()) as u64 } + /// Returns an index of the leaf containing the note. fn leaf_index(&self) -> u64 { self.to_absolute_index() * 2 } diff --git a/objects/src/notes/file.rs b/objects/src/notes/file.rs index c34d879a4..af7f3d5e1 100644 --- a/objects/src/notes/file.rs +++ b/objects/src/notes/file.rs @@ -179,14 +179,7 @@ mod tests { #[test] fn serialize_with_proof() { let note = create_example_note(); - let mock_inclusion_proof = NoteInclusionProof::new( - Default::default(), - Default::default(), - Default::default(), - 0, - Default::default(), - ) - .unwrap(); + let mock_inclusion_proof = NoteInclusionProof::new(0, 0, Default::default()).unwrap(); let file = NoteFile::NoteWithProof(note.clone(), mock_inclusion_proof.clone()); let mut buffer = Vec::new(); file.write_into(&mut buffer); diff --git a/objects/src/notes/location.rs b/objects/src/notes/location.rs index c88eb501e..4e9a2bd57 100644 --- a/objects/src/notes/location.rs +++ b/objects/src/notes/location.rs @@ -1,20 +1,30 @@ use alloc::string::ToString; +use core::num::TryFromIntError; use super::{ - ByteReader, ByteWriter, Deserializable, DeserializationError, Digest, NoteError, Serializable, - NOTE_TREE_DEPTH, + ByteReader, ByteWriter, Deserializable, DeserializationError, NoteError, Serializable, }; -use crate::crypto::merkle::{MerklePath, NodeIndex}; +use crate::crypto::merkle::MerklePath; /// Contains information about the location of a note. #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct NoteLocation { /// The block number the note was created in. - pub block_num: u32, + block_num: u32, /// The index of the note in the note Merkle tree of the block the note was created in. - pub node_index: NodeIndex, // TODO: should be a u32 because the depth is always the same + node_index_in_block: u32, +} + +impl NoteLocation { + pub fn block_num(&self) -> u32 { + self.block_num + } + + pub fn node_index(&self) -> u64 { + self.node_index_in_block as u64 + } } /// Contains the data required to prove inclusion of a note in the canonical chain. @@ -24,31 +34,20 @@ pub struct NoteInclusionProof { /// Details about the note's location. location: NoteLocation, - /// The sub hash of the block the note was created in. - sub_hash: Digest, - - /// The note root of the block the note was created in. - note_root: Digest, - /// The note's authentication Merkle path its block's the note root. note_path: MerklePath, } impl NoteInclusionProof { /// Returns a new [NoteInclusionProof]. - pub fn new( - block_num: u32, - sub_hash: Digest, - note_root: Digest, - index: u64, - note_path: MerklePath, - ) -> Result { - let node_index = NodeIndex::new(NOTE_TREE_DEPTH, index) - .map_err(|e| NoteError::invalid_location_index(e.to_string()))?; + pub fn new(block_num: u32, index: u64, note_path: MerklePath) -> Result { Ok(Self { - location: NoteLocation { block_num, node_index }, - sub_hash, - note_root, + location: NoteLocation { + block_num, + node_index_in_block: index.try_into().map_err(|err: TryFromIntError| { + NoteError::InvalidLocationIndex(err.to_string()) + })?, + }, note_path, }) } @@ -56,16 +55,6 @@ impl NoteInclusionProof { // ACCESSORS // -------------------------------------------------------------------------------------------- - /// Returns the sub hash of the block header the note was created in. - pub fn sub_hash(&self) -> Digest { - self.sub_hash - } - - /// Returns the note root of the block header the note was created in. - pub fn note_root(&self) -> Digest { - self.note_root - } - /// Returns the location of the note. pub fn location(&self) -> &NoteLocation { &self.location @@ -84,24 +73,22 @@ impl NoteInclusionProof { impl Serializable for NoteLocation { fn write_into(&self, target: &mut W) { target.write_u32(self.block_num); - self.node_index.write_into(target); + target.write_u32(self.node_index_in_block); } } impl Deserializable for NoteLocation { fn read_from(source: &mut R) -> Result { let block_num = source.read_u32()?; - let node_index = NodeIndex::read_from(source)?; + let node_index_in_block = source.read_u32()?; - Ok(Self { block_num, node_index }) + Ok(Self { block_num, node_index_in_block }) } } impl Serializable for NoteInclusionProof { fn write_into(&self, target: &mut W) { self.location.write_into(target); - self.sub_hash.write_into(target); - self.note_root.write_into(target); self.note_path.write_into(target); } } @@ -109,10 +96,8 @@ impl Serializable for NoteInclusionProof { impl Deserializable for NoteInclusionProof { fn read_from(source: &mut R) -> Result { let location = NoteLocation::read_from(source)?; - let sub_hash = Digest::read_from(source)?; - let note_root = Digest::read_from(source)?; let note_path = MerklePath::read_from(source)?; - Ok(Self { location, sub_hash, note_root, note_path }) + Ok(Self { location, note_path }) } } diff --git a/objects/src/testing/block.rs b/objects/src/testing/block.rs index 5182d69ea..f078cdb2b 100644 --- a/objects/src/testing/block.rs +++ b/objects/src/testing/block.rs @@ -200,9 +200,9 @@ impl MockChain { for note in notes { let input_note = self.available_notes.get(note).unwrap().clone(); block_headers_map.insert( - input_note.location().unwrap().block_num, + input_note.location().unwrap().block_num(), self.blocks - .get(input_note.location().unwrap().block_num as usize) + .get(input_note.location().unwrap().block_num() as usize) .unwrap() .header(), ); @@ -291,8 +291,6 @@ impl MockChain { let note_path = notes_tree.get_note_path(block_note_index).unwrap(); let note_inclusion_proof = NoteInclusionProof::new( block.header().block_num(), - block.header().sub_hash(), - block.header().note_root(), block_note_index.to_absolute_index(), note_path, ) diff --git a/objects/src/transaction/inputs.rs b/objects/src/transaction/inputs.rs index 6f5ac4d51..afecbbeea 100644 --- a/objects/src/transaction/inputs.rs +++ b/objects/src/transaction/inputs.rs @@ -60,7 +60,7 @@ impl TransactionInputs { // check the authentication paths of the input notes. for note in input_notes.iter() { if let InputNote::Authenticated { note, proof } = note { - let note_block_num = proof.location().block_num; + let note_block_num = proof.location().block_num(); let block_header = if note_block_num == block_num { &block_header @@ -377,7 +377,7 @@ impl InputNote { /// Returns true if this note belongs to the note tree of the specified block. fn is_in_block(note: &Note, proof: &NoteInclusionProof, block_header: &BlockHeader) -> bool { - let note_index = proof.location().node_index.value(); + let note_index = proof.location().node_index(); let note_hash = note.hash(); proof.note_path().verify(note_index, note_hash, &block_header.note_root()) } From eaa764d587736da9a09b5c0d0f8f3e14731571ea Mon Sep 17 00:00:00 2001 From: polydez <155382956+polydez@users.noreply.github.com> Date: Wed, 31 Jul 2024 23:29:00 +0500 Subject: [PATCH 3/8] docs: update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00e35a5d0..87eeb952e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - [BREAKING] Increase of nonce does not require changes in account state any more (#796). - Added `CHANGELOG.md` warning message on CI (#799). - Account deltas can now be merged (#797). +- Refactored and simplified `NoteOrigin` and `NoteInclusionProof` structs (#810). ## 0.4.0 (2024-07-03) From b8db6f729adf9e8ec48510df18a97074bfc7ae21 Mon Sep 17 00:00:00 2001 From: polydez <155382956+polydez@users.noreply.github.com> Date: Thu, 1 Aug 2024 18:34:01 +0500 Subject: [PATCH 4/8] fix: address review comments --- CHANGELOG.md | 2 +- miden-lib/src/transaction/inputs.rs | 13 +++++++++---- objects/src/notes/location.rs | 25 +++++++++++++++---------- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab446a841..3a7f2dc66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ - Added `CHANGELOG.md` warning message on CI (#799). - Account deltas can now be merged (#797). - Changed `AccountCode` procedures from merkle tree to sequential hash + added storage_offset support (#763). -- Refactored and simplified `NoteOrigin` and `NoteInclusionProof` structs (#810). +- [BREAKING] Refactored and simplified `NoteOrigin` and `NoteInclusionProof` structs (#810). ## 0.4.0 (2024-07-03) diff --git a/miden-lib/src/transaction/inputs.rs b/miden-lib/src/transaction/inputs.rs index 9f669a6a9..7415e4a40 100644 --- a/miden-lib/src/transaction/inputs.rs +++ b/miden-lib/src/transaction/inputs.rs @@ -320,10 +320,15 @@ fn add_input_notes_to_advice_inputs( // insert note authentication path nodes into the Merkle store match input_note { InputNote::Authenticated { note, proof } => { - let note_block_header = tx_inputs - .block_chain() - .get_block(proof.location().block_num()) - .unwrap_or(tx_inputs.block_header()); + let block_num = proof.location().block_num(); + let note_block_header = if block_num == tx_inputs.block_header().block_num() { + tx_inputs.block_header() + } else { + tx_inputs + .block_chain() + .get_block(block_num) + .expect("block not found in chain MMR") + }; // NOTE: keep in sync with the `prologue::process_input_note` kernel procedure // Push the `is_authenticated` flag diff --git a/objects/src/notes/location.rs b/objects/src/notes/location.rs index 4e9a2bd57..6b39b8fdd 100644 --- a/objects/src/notes/location.rs +++ b/objects/src/notes/location.rs @@ -4,7 +4,7 @@ use core::num::TryFromIntError; use super::{ ByteReader, ByteWriter, Deserializable, DeserializationError, NoteError, Serializable, }; -use crate::crypto::merkle::MerklePath; +use crate::{crypto::merkle::MerklePath, MAX_BATCHES_PER_BLOCK, MAX_NOTES_PER_BATCH}; /// Contains information about the location of a note. #[derive(Clone, Debug, PartialEq, Eq)] @@ -18,10 +18,12 @@ pub struct NoteLocation { } impl NoteLocation { + /// Returns the block number the note was created in. pub fn block_num(&self) -> u32 { self.block_num } + /// Returns the index of the note in the note Merkle tree of the block the note was created in. pub fn node_index(&self) -> u64 { self.node_index_in_block as u64 } @@ -41,15 +43,18 @@ pub struct NoteInclusionProof { impl NoteInclusionProof { /// Returns a new [NoteInclusionProof]. pub fn new(block_num: u32, index: u64, note_path: MerklePath) -> Result { - Ok(Self { - location: NoteLocation { - block_num, - node_index_in_block: index.try_into().map_err(|err: TryFromIntError| { - NoteError::InvalidLocationIndex(err.to_string()) - })?, - }, - note_path, - }) + const HIGHEST_INDEX: usize = MAX_BATCHES_PER_BLOCK * MAX_NOTES_PER_BATCH - 1; + let node_index_in_block = index + .try_into() + .map_err(|err: TryFromIntError| NoteError::InvalidLocationIndex(err.to_string()))?; + if node_index_in_block as usize > HIGHEST_INDEX { + return Err(NoteError::InvalidLocationIndex(format!( + "Node index ({index}) is out of bounds (0..={HIGHEST_INDEX})." + ))); + } + let location = NoteLocation { block_num, node_index_in_block }; + + Ok(Self { location, note_path }) } // ACCESSORS From 47007c7f9916d791ae2a2cfe00eb2d685917ad0c Mon Sep 17 00:00:00 2001 From: polydez <155382956+polydez@users.noreply.github.com> Date: Thu, 1 Aug 2024 19:57:00 +0500 Subject: [PATCH 5/8] refactor: make `BlockNoteTree::to_absolute_index` and `BlockNoteTree::leaf_index` return `u32` --- objects/src/block/mod.rs | 4 ++-- objects/src/block/note_tree.rs | 14 ++++++++------ objects/src/constants.rs | 14 +++++++++----- objects/src/errors.rs | 4 ++-- objects/src/notes/location.rs | 18 ++++++++---------- objects/src/notes/mod.rs | 4 ++-- 6 files changed, 31 insertions(+), 27 deletions(-) diff --git a/objects/src/block/mod.rs b/objects/src/block/mod.rs index 9a50f05e7..a49d0233c 100644 --- a/objects/src/block/mod.rs +++ b/objects/src/block/mod.rs @@ -1,6 +1,6 @@ use alloc::{collections::BTreeSet, string::ToString, vec::Vec}; -use super::{Digest, Felt, Hasher, MAX_BATCHES_PER_BLOCK, MAX_NOTES_PER_BATCH, ZERO}; +use super::{Digest, Felt, Hasher, MAX_BATCHES_PER_BLOCK, MAX_OUTPUT_NOTES_PER_BATCH, ZERO}; mod header; pub use header::BlockHeader; @@ -148,7 +148,7 @@ impl Block { } for batch in self.output_note_batches.iter() { - if batch.len() > MAX_NOTES_PER_BATCH { + if batch.len() > MAX_OUTPUT_NOTES_PER_BATCH { return Err(BlockError::TooManyNotesInBatch(batch.len())); } } diff --git a/objects/src/block/note_tree.rs b/objects/src/block/note_tree.rs index 4fb147cd0..3dd037e17 100644 --- a/objects/src/block/note_tree.rs +++ b/objects/src/block/note_tree.rs @@ -8,7 +8,7 @@ use miden_crypto::{ use crate::{ notes::NoteMetadata, utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable}, - BLOCK_OUTPUT_NOTES_TREE_DEPTH, MAX_NOTES_PER_BATCH, + BLOCK_OUTPUT_NOTES_TREE_DEPTH, MAX_OUTPUT_NOTES_PER_BATCH, MAX_OUTPUT_NOTES_PER_BLOCK, }; /// Wrapper over [SimpleSmt] for notes tree. @@ -35,7 +35,7 @@ impl BlockNoteTree { entries: impl IntoIterator, ) -> Result { let interleaved = entries.into_iter().flat_map(|(index, note_id, metadata)| { - let id_index = index.leaf_index(); + let id_index = index.leaf_index().into(); [(id_index, note_id.into()), (id_index + 1, metadata.into())] }); @@ -52,7 +52,7 @@ impl BlockNoteTree { /// The returned path is to the node which is the parent of both note and note metadata node. pub fn get_note_path(&self, index: BlockNoteIndex) -> Result { // get the path to the leaf containing the note (path len = 21) - let leaf_index = LeafIndex::new(index.leaf_index())?; + let leaf_index = LeafIndex::new(index.leaf_index().into())?; // move up the path by removing the first node, this path now points to the parent of the // note path @@ -92,12 +92,14 @@ impl BlockNoteIndex { } /// Returns an index to the node which the parent of both the note and note metadata. - pub fn to_absolute_index(&self) -> u64 { - (self.batch_idx() * MAX_NOTES_PER_BATCH + self.note_idx_in_batch()) as u64 + pub fn to_absolute_index(&self) -> u32 { + const _: () = assert!(MAX_OUTPUT_NOTES_PER_BLOCK <= u32::MAX as usize); + (self.batch_idx() * MAX_OUTPUT_NOTES_PER_BATCH + self.note_idx_in_batch()) as u32 } /// Returns an index of the leaf containing the note. - fn leaf_index(&self) -> u64 { + fn leaf_index(&self) -> u32 { + const _: () = assert!(MAX_OUTPUT_NOTES_PER_BLOCK * 2 <= u32::MAX as usize); self.to_absolute_index() * 2 } } diff --git a/objects/src/constants.rs b/objects/src/constants.rs index 84bab520a..b6b9df99e 100644 --- a/objects/src/constants.rs +++ b/objects/src/constants.rs @@ -2,7 +2,7 @@ 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; +pub const OUTPUT_NOTE_TREE_DEPTH: u8 = 20; /// The maximum number of assets that can be stored in a single note. pub const MAX_ASSETS_PER_NOTE: usize = 256; @@ -35,10 +35,11 @@ pub const BATCH_OUTPUT_NOTES_TREE_DEPTH: u8 = 13; /// /// Because the tree used in a batch has fixed depth, and each note takes two leaves, the maximum /// number of notes is the number of leaves in the tree. -pub const MAX_NOTES_PER_BATCH: usize = 2_usize.pow((BATCH_OUTPUT_NOTES_TREE_DEPTH - 1) as u32); +pub const MAX_OUTPUT_NOTES_PER_BATCH: usize = + 2_usize.pow((BATCH_OUTPUT_NOTES_TREE_DEPTH - 1) as u32); /// The maximum number of transaction in a single batch. -pub const MAX_TRANSACTIONS_PER_BATCH: usize = MAX_NOTES_PER_BATCH / MAX_OUTPUT_NOTES_PER_TX; +pub const MAX_TRANSACTIONS_PER_BATCH: usize = MAX_OUTPUT_NOTES_PER_BATCH / MAX_OUTPUT_NOTES_PER_TX; // BLOCK // ================================================================================================ @@ -48,8 +49,8 @@ pub const MAX_TRANSACTIONS_PER_BATCH: usize = MAX_NOTES_PER_BATCH / MAX_OUTPUT_N /// This value can be interpreted as: /// /// - The depth of a tree with the leaves set to a batch output note tree root. -/// - The level at which the batches create note trees are merged, creating a new tree with this many -/// additional new levels. +/// - The level at which the batches create note trees are merged, creating a new tree with this +/// many additional new levels. pub const BLOCK_OUTPUT_NOTES_BATCH_TREE_DEPTH: u8 = 8; /// The final depth of the Sparse Merkle Tree used to store all notes created in a block. @@ -59,5 +60,8 @@ pub const BLOCK_OUTPUT_NOTES_TREE_DEPTH: u8 = /// Maximum number of batches that can be inserted into a single block. pub const MAX_BATCHES_PER_BLOCK: usize = 2_usize.pow(BLOCK_OUTPUT_NOTES_BATCH_TREE_DEPTH as u32); +/// Maximum number of output notes that can be created in a single block. +pub const MAX_OUTPUT_NOTES_PER_BLOCK: usize = MAX_OUTPUT_NOTES_PER_BATCH * MAX_BATCHES_PER_BLOCK; + /// The block height of the genesis block pub const GENESIS_BLOCK: u32 = 0; diff --git a/objects/src/errors.rs b/objects/src/errors.rs index fcc138f7f..ba8575230 100644 --- a/objects/src/errors.rs +++ b/objects/src/errors.rs @@ -9,7 +9,7 @@ use super::{ assets::{Asset, FungibleAsset, NonFungibleAsset}, crypto::{hash::rpo::RpoDigest, merkle::MerkleError}, notes::NoteId, - Digest, Word, MAX_BATCHES_PER_BLOCK, MAX_NOTES_PER_BATCH, + Digest, Word, MAX_BATCHES_PER_BLOCK, MAX_OUTPUT_NOTES_PER_BATCH, }; use crate::{ accounts::{delta::AccountUpdateDetails, AccountType}, @@ -361,7 +361,7 @@ impl fmt::Display for BlockError { write!(f, "Duplicate note {id} found in the block") }, BlockError::TooManyNotesInBatch(actual) => { - write!(f, "Too many notes in a batch. Max: {MAX_NOTES_PER_BATCH}, actual: {actual}") + write!(f, "Too many notes in a batch. Max: {MAX_OUTPUT_NOTES_PER_BATCH}, actual: {actual}") }, BlockError::TooManyTransactionBatches(actual) => { write!( diff --git a/objects/src/notes/location.rs b/objects/src/notes/location.rs index 6b39b8fdd..0d502e7b2 100644 --- a/objects/src/notes/location.rs +++ b/objects/src/notes/location.rs @@ -1,10 +1,7 @@ -use alloc::string::ToString; -use core::num::TryFromIntError; - use super::{ ByteReader, ByteWriter, Deserializable, DeserializationError, NoteError, Serializable, }; -use crate::{crypto::merkle::MerklePath, MAX_BATCHES_PER_BLOCK, MAX_NOTES_PER_BATCH}; +use crate::{crypto::merkle::MerklePath, MAX_BATCHES_PER_BLOCK, MAX_OUTPUT_NOTES_PER_BATCH}; /// Contains information about the location of a note. #[derive(Clone, Debug, PartialEq, Eq)] @@ -42,14 +39,15 @@ pub struct NoteInclusionProof { impl NoteInclusionProof { /// Returns a new [NoteInclusionProof]. - pub fn new(block_num: u32, index: u64, note_path: MerklePath) -> Result { - const HIGHEST_INDEX: usize = MAX_BATCHES_PER_BLOCK * MAX_NOTES_PER_BATCH - 1; - let node_index_in_block = index - .try_into() - .map_err(|err: TryFromIntError| NoteError::InvalidLocationIndex(err.to_string()))?; + pub fn new( + block_num: u32, + node_index_in_block: u32, + note_path: MerklePath, + ) -> Result { + const HIGHEST_INDEX: usize = MAX_BATCHES_PER_BLOCK * MAX_OUTPUT_NOTES_PER_BATCH - 1; if node_index_in_block as usize > HIGHEST_INDEX { return Err(NoteError::InvalidLocationIndex(format!( - "Node index ({index}) is out of bounds (0..={HIGHEST_INDEX})." + "Node index ({node_index_in_block}) is out of bounds (0..={HIGHEST_INDEX})." ))); } let location = NoteLocation { block_num, node_index_in_block }; diff --git a/objects/src/notes/mod.rs b/objects/src/notes/mod.rs index 0e312fafe..f7e8695d2 100644 --- a/objects/src/notes/mod.rs +++ b/objects/src/notes/mod.rs @@ -11,7 +11,7 @@ use crate::{ assembly::{Assembler, AssemblyContext, ProgramAst}, assets::Asset, vm::CodeBlock, - Digest, Felt, Hasher, NoteError, NOTE_TREE_DEPTH, WORD_SIZE, ZERO, + Digest, Felt, Hasher, NoteError, OUTPUT_NOTE_TREE_DEPTH, WORD_SIZE, ZERO, }; mod assets; @@ -62,7 +62,7 @@ pub use file::NoteFile; /// 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). -pub const NOTE_LEAF_DEPTH: u8 = NOTE_TREE_DEPTH + 1; +pub const NOTE_LEAF_DEPTH: u8 = OUTPUT_NOTE_TREE_DEPTH + 1; // NOTE // ================================================================================================ From 1f58f3f195fd501fa4c34687ab8c19cfc9ca29b5 Mon Sep 17 00:00:00 2001 From: polydez <155382956+polydez@users.noreply.github.com> Date: Thu, 1 Aug 2024 22:31:43 +0500 Subject: [PATCH 6/8] refactor: remove incorrect `MAX_TRANSACTIONS_PER_BATCH` constant --- objects/src/constants.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/objects/src/constants.rs b/objects/src/constants.rs index b6b9df99e..9d8e3b5f5 100644 --- a/objects/src/constants.rs +++ b/objects/src/constants.rs @@ -38,9 +38,6 @@ pub const BATCH_OUTPUT_NOTES_TREE_DEPTH: u8 = 13; pub const MAX_OUTPUT_NOTES_PER_BATCH: usize = 2_usize.pow((BATCH_OUTPUT_NOTES_TREE_DEPTH - 1) as u32); -/// The maximum number of transaction in a single batch. -pub const MAX_TRANSACTIONS_PER_BATCH: usize = MAX_OUTPUT_NOTES_PER_BATCH / MAX_OUTPUT_NOTES_PER_TX; - // BLOCK // ================================================================================================ From 540098063d8b7b1055e61429ee3c0fd5b3e71f47 Mon Sep 17 00:00:00 2001 From: polydez <155382956+polydez@users.noreply.github.com> Date: Fri, 2 Aug 2024 08:57:52 +0500 Subject: [PATCH 7/8] refactor: address review comments --- miden-lib/src/transaction/inputs.rs | 4 ++-- objects/src/constants.rs | 2 +- objects/src/notes/location.rs | 7 ++++++- objects/src/notes/mod.rs | 4 ++-- objects/src/transaction/inputs.rs | 2 +- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/miden-lib/src/transaction/inputs.rs b/miden-lib/src/transaction/inputs.rs index 7415e4a40..9c7db604e 100644 --- a/miden-lib/src/transaction/inputs.rs +++ b/miden-lib/src/transaction/inputs.rs @@ -338,7 +338,7 @@ fn add_input_notes_to_advice_inputs( inputs.extend_merkle_store( proof .note_path() - .inner_nodes(proof.location().node_index(), note.hash()) + .inner_nodes(proof.location().node_index_in_block(), note.hash()) .unwrap(), ); note_data.push(proof.location().block_num().into()); @@ -347,7 +347,7 @@ fn add_input_notes_to_advice_inputs( note_data.push( proof .location() - .node_index() + .node_index_in_block() .try_into() .expect("value is greater than or equal to the field modulus"), ); diff --git a/objects/src/constants.rs b/objects/src/constants.rs index 9d8e3b5f5..9e283be1f 100644 --- a/objects/src/constants.rs +++ b/objects/src/constants.rs @@ -2,7 +2,7 @@ pub const ACCOUNT_TREE_DEPTH: u8 = 64; /// The depth of the Merkle tree used to commit to notes produced in a block. -pub const OUTPUT_NOTE_TREE_DEPTH: u8 = 20; +pub const NOTE_TREE_DEPTH: u8 = 20; /// The maximum number of assets that can be stored in a single note. pub const MAX_ASSETS_PER_NOTE: usize = 256; diff --git a/objects/src/notes/location.rs b/objects/src/notes/location.rs index 0d502e7b2..d094fe7a2 100644 --- a/objects/src/notes/location.rs +++ b/objects/src/notes/location.rs @@ -21,7 +21,12 @@ impl NoteLocation { } /// Returns the index of the note in the note Merkle tree of the block the note was created in. - pub fn node_index(&self) -> u64 { + /// + /// # Note + /// + /// The height of the Merkle tree is `BLOCK_OUTPUT_NOTES_TREE_DEPTH`. Thus, the maximum index + /// is `2 ^ BLOCK_OUTPUT_NOTES_TREE_DEPTH - 1`. + pub fn node_index_in_block(&self) -> u64 { self.node_index_in_block as u64 } } diff --git a/objects/src/notes/mod.rs b/objects/src/notes/mod.rs index f7e8695d2..0e312fafe 100644 --- a/objects/src/notes/mod.rs +++ b/objects/src/notes/mod.rs @@ -11,7 +11,7 @@ use crate::{ assembly::{Assembler, AssemblyContext, ProgramAst}, assets::Asset, vm::CodeBlock, - Digest, Felt, Hasher, NoteError, OUTPUT_NOTE_TREE_DEPTH, WORD_SIZE, ZERO, + Digest, Felt, Hasher, NoteError, NOTE_TREE_DEPTH, WORD_SIZE, ZERO, }; mod assets; @@ -62,7 +62,7 @@ pub use file::NoteFile; /// 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). -pub const NOTE_LEAF_DEPTH: u8 = OUTPUT_NOTE_TREE_DEPTH + 1; +pub const NOTE_LEAF_DEPTH: u8 = NOTE_TREE_DEPTH + 1; // NOTE // ================================================================================================ diff --git a/objects/src/transaction/inputs.rs b/objects/src/transaction/inputs.rs index 6d34f4a09..8378efb93 100644 --- a/objects/src/transaction/inputs.rs +++ b/objects/src/transaction/inputs.rs @@ -377,7 +377,7 @@ impl InputNote { /// Returns true if this note belongs to the note tree of the specified block. fn is_in_block(note: &Note, proof: &NoteInclusionProof, block_header: &BlockHeader) -> bool { - let note_index = proof.location().node_index(); + let note_index = proof.location().node_index_in_block(); let note_hash = note.hash(); proof.note_path().verify(note_index, note_hash, &block_header.note_root()) } From 33e93f825edb8fa7a7effc5616d15b185b62b22c Mon Sep 17 00:00:00 2001 From: polydez <155382956+polydez@users.noreply.github.com> Date: Fri, 2 Aug 2024 09:02:06 +0500 Subject: [PATCH 8/8] refactor: address review comments --- objects/src/block/mod.rs | 4 ++-- objects/src/block/note_tree.rs | 4 ++-- objects/src/constants.rs | 5 ++--- objects/src/errors.rs | 4 ++-- objects/src/notes/location.rs | 4 ++-- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/objects/src/block/mod.rs b/objects/src/block/mod.rs index a49d0233c..9a50f05e7 100644 --- a/objects/src/block/mod.rs +++ b/objects/src/block/mod.rs @@ -1,6 +1,6 @@ use alloc::{collections::BTreeSet, string::ToString, vec::Vec}; -use super::{Digest, Felt, Hasher, MAX_BATCHES_PER_BLOCK, MAX_OUTPUT_NOTES_PER_BATCH, ZERO}; +use super::{Digest, Felt, Hasher, MAX_BATCHES_PER_BLOCK, MAX_NOTES_PER_BATCH, ZERO}; mod header; pub use header::BlockHeader; @@ -148,7 +148,7 @@ impl Block { } for batch in self.output_note_batches.iter() { - if batch.len() > MAX_OUTPUT_NOTES_PER_BATCH { + if batch.len() > MAX_NOTES_PER_BATCH { return Err(BlockError::TooManyNotesInBatch(batch.len())); } } diff --git a/objects/src/block/note_tree.rs b/objects/src/block/note_tree.rs index 3dd037e17..96447e3db 100644 --- a/objects/src/block/note_tree.rs +++ b/objects/src/block/note_tree.rs @@ -8,7 +8,7 @@ use miden_crypto::{ use crate::{ notes::NoteMetadata, utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable}, - BLOCK_OUTPUT_NOTES_TREE_DEPTH, MAX_OUTPUT_NOTES_PER_BATCH, MAX_OUTPUT_NOTES_PER_BLOCK, + BLOCK_OUTPUT_NOTES_TREE_DEPTH, MAX_NOTES_PER_BATCH, MAX_OUTPUT_NOTES_PER_BLOCK, }; /// Wrapper over [SimpleSmt] for notes tree. @@ -94,7 +94,7 @@ impl BlockNoteIndex { /// Returns an index to the node which the parent of both the note and note metadata. pub fn to_absolute_index(&self) -> u32 { const _: () = assert!(MAX_OUTPUT_NOTES_PER_BLOCK <= u32::MAX as usize); - (self.batch_idx() * MAX_OUTPUT_NOTES_PER_BATCH + self.note_idx_in_batch()) as u32 + (self.batch_idx() * MAX_NOTES_PER_BATCH + self.note_idx_in_batch()) as u32 } /// Returns an index of the leaf containing the note. diff --git a/objects/src/constants.rs b/objects/src/constants.rs index 9e283be1f..81e8b614d 100644 --- a/objects/src/constants.rs +++ b/objects/src/constants.rs @@ -35,8 +35,7 @@ pub const BATCH_OUTPUT_NOTES_TREE_DEPTH: u8 = 13; /// /// Because the tree used in a batch has fixed depth, and each note takes two leaves, the maximum /// number of notes is the number of leaves in the tree. -pub const MAX_OUTPUT_NOTES_PER_BATCH: usize = - 2_usize.pow((BATCH_OUTPUT_NOTES_TREE_DEPTH - 1) as u32); +pub const MAX_NOTES_PER_BATCH: usize = 2_usize.pow((BATCH_OUTPUT_NOTES_TREE_DEPTH - 1) as u32); // BLOCK // ================================================================================================ @@ -58,7 +57,7 @@ pub const BLOCK_OUTPUT_NOTES_TREE_DEPTH: u8 = pub const MAX_BATCHES_PER_BLOCK: usize = 2_usize.pow(BLOCK_OUTPUT_NOTES_BATCH_TREE_DEPTH as u32); /// Maximum number of output notes that can be created in a single block. -pub const MAX_OUTPUT_NOTES_PER_BLOCK: usize = MAX_OUTPUT_NOTES_PER_BATCH * MAX_BATCHES_PER_BLOCK; +pub const MAX_OUTPUT_NOTES_PER_BLOCK: usize = MAX_NOTES_PER_BATCH * MAX_BATCHES_PER_BLOCK; /// The block height of the genesis block pub const GENESIS_BLOCK: u32 = 0; diff --git a/objects/src/errors.rs b/objects/src/errors.rs index ba8575230..fcc138f7f 100644 --- a/objects/src/errors.rs +++ b/objects/src/errors.rs @@ -9,7 +9,7 @@ use super::{ assets::{Asset, FungibleAsset, NonFungibleAsset}, crypto::{hash::rpo::RpoDigest, merkle::MerkleError}, notes::NoteId, - Digest, Word, MAX_BATCHES_PER_BLOCK, MAX_OUTPUT_NOTES_PER_BATCH, + Digest, Word, MAX_BATCHES_PER_BLOCK, MAX_NOTES_PER_BATCH, }; use crate::{ accounts::{delta::AccountUpdateDetails, AccountType}, @@ -361,7 +361,7 @@ impl fmt::Display for BlockError { write!(f, "Duplicate note {id} found in the block") }, BlockError::TooManyNotesInBatch(actual) => { - write!(f, "Too many notes in a batch. Max: {MAX_OUTPUT_NOTES_PER_BATCH}, actual: {actual}") + write!(f, "Too many notes in a batch. Max: {MAX_NOTES_PER_BATCH}, actual: {actual}") }, BlockError::TooManyTransactionBatches(actual) => { write!( diff --git a/objects/src/notes/location.rs b/objects/src/notes/location.rs index d094fe7a2..b1982d87e 100644 --- a/objects/src/notes/location.rs +++ b/objects/src/notes/location.rs @@ -1,7 +1,7 @@ use super::{ ByteReader, ByteWriter, Deserializable, DeserializationError, NoteError, Serializable, }; -use crate::{crypto::merkle::MerklePath, MAX_BATCHES_PER_BLOCK, MAX_OUTPUT_NOTES_PER_BATCH}; +use crate::{crypto::merkle::MerklePath, MAX_BATCHES_PER_BLOCK, MAX_NOTES_PER_BATCH}; /// Contains information about the location of a note. #[derive(Clone, Debug, PartialEq, Eq)] @@ -49,7 +49,7 @@ impl NoteInclusionProof { node_index_in_block: u32, note_path: MerklePath, ) -> Result { - const HIGHEST_INDEX: usize = MAX_BATCHES_PER_BLOCK * MAX_OUTPUT_NOTES_PER_BATCH - 1; + const HIGHEST_INDEX: usize = MAX_BATCHES_PER_BLOCK * MAX_NOTES_PER_BATCH - 1; if node_index_in_block as usize > HIGHEST_INDEX { return Err(NoteError::InvalidLocationIndex(format!( "Node index ({node_index_in_block}) is out of bounds (0..={HIGHEST_INDEX})."