miden_objects/note/
location.rs

1use super::{
2    ByteReader, ByteWriter, Deserializable, DeserializationError, Digest, NoteError, Serializable,
3};
4use crate::{
5    MAX_BATCHES_PER_BLOCK, MAX_OUTPUT_NOTES_PER_BATCH,
6    block::BlockNumber,
7    crypto::merkle::{InnerNodeInfo, MerklePath},
8};
9
10/// Contains information about the location of a note.
11#[derive(Clone, Debug, PartialEq, Eq)]
12pub struct NoteLocation {
13    /// The block number the note was created in.
14    block_num: BlockNumber,
15
16    /// The index of the note in the note Merkle tree of the block the note was created in.
17    node_index_in_block: u16,
18}
19
20impl NoteLocation {
21    /// Returns the block number the note was created in.
22    pub fn block_num(&self) -> BlockNumber {
23        self.block_num
24    }
25
26    /// Returns the index of the note in the note Merkle tree of the block the note was created in.
27    ///
28    /// # Note
29    ///
30    /// The height of the Merkle tree is [crate::constants::BLOCK_NOTE_TREE_DEPTH].
31    /// Thus, the maximum index is `2 ^ BLOCK_NOTE_TREE_DEPTH - 1`.
32    pub fn node_index_in_block(&self) -> u16 {
33        self.node_index_in_block
34    }
35}
36
37/// Contains the data required to prove inclusion of a note in the canonical chain.
38#[derive(Clone, Debug, PartialEq, Eq)]
39pub struct NoteInclusionProof {
40    /// Details about the note's location.
41    location: NoteLocation,
42
43    /// The note's authentication Merkle path its block's the note root.
44    note_path: MerklePath,
45}
46
47impl NoteInclusionProof {
48    /// Returns a new [NoteInclusionProof].
49    pub fn new(
50        block_num: BlockNumber,
51        node_index_in_block: u16,
52        note_path: MerklePath,
53    ) -> Result<Self, NoteError> {
54        const HIGHEST_INDEX: usize = MAX_BATCHES_PER_BLOCK * MAX_OUTPUT_NOTES_PER_BATCH - 1;
55        if node_index_in_block as usize > HIGHEST_INDEX {
56            return Err(NoteError::NoteLocationIndexOutOfBounds {
57                node_index_in_block,
58                highest_index: HIGHEST_INDEX,
59            });
60        }
61
62        let location = NoteLocation { block_num, node_index_in_block };
63
64        Ok(Self { location, note_path })
65    }
66
67    // ACCESSORS
68    // --------------------------------------------------------------------------------------------
69
70    /// Returns the location of the note.
71    pub fn location(&self) -> &NoteLocation {
72        &self.location
73    }
74
75    /// Returns the Merkle path to the note in the note Merkle tree of the block the note was
76    /// created in.
77    pub fn note_path(&self) -> &MerklePath {
78        &self.note_path
79    }
80
81    /// Returns an iterator over inner nodes of this proof assuming that `note_commitment` is the
82    /// value of the node to which this proof opens.
83    pub fn inner_nodes(&self, note_commitment: Digest) -> impl Iterator<Item = InnerNodeInfo> {
84        // SAFETY: expect() is fine here because we check index consistency in the constructor
85        self.note_path
86            .inner_nodes(self.location.node_index_in_block().into(), note_commitment)
87            .expect("note index is not out of bounds")
88    }
89}
90
91// SERIALIZATION
92// ================================================================================================
93
94impl Serializable for NoteLocation {
95    fn write_into<W: ByteWriter>(&self, target: &mut W) {
96        target.write(self.block_num);
97        target.write_u16(self.node_index_in_block);
98    }
99}
100
101impl Deserializable for NoteLocation {
102    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
103        let block_num = source.read()?;
104        let node_index_in_block = source.read_u16()?;
105
106        Ok(Self { block_num, node_index_in_block })
107    }
108}
109
110impl Serializable for NoteInclusionProof {
111    fn write_into<W: ByteWriter>(&self, target: &mut W) {
112        self.location.write_into(target);
113        self.note_path.write_into(target);
114    }
115}
116
117impl Deserializable for NoteInclusionProof {
118    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
119        let location = NoteLocation::read_from(source)?;
120        let note_path = MerklePath::read_from(source)?;
121
122        Ok(Self { location, note_path })
123    }
124}