miden_objects/note/
location.rs

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