miden_objects/note/
mod.rs

1use miden_crypto::{
2    Word,
3    utils::{ByteReader, ByteWriter, Deserializable, Serializable},
4};
5use vm_processor::DeserializationError;
6
7use crate::{Digest, Felt, Hasher, NoteError, WORD_SIZE, ZERO, account::AccountId};
8
9mod assets;
10pub use assets::NoteAssets;
11
12mod details;
13pub use details::NoteDetails;
14
15mod header;
16pub use header::{NoteHeader, compute_note_commitment};
17
18mod inputs;
19pub use inputs::NoteInputs;
20
21mod metadata;
22pub use metadata::NoteMetadata;
23
24mod execution_hint;
25pub use execution_hint::{AfterBlockNumber, NoteExecutionHint};
26
27mod note_id;
28pub use note_id::NoteId;
29
30mod note_tag;
31pub use note_tag::{NoteExecutionMode, NoteTag};
32
33mod note_type;
34pub use note_type::NoteType;
35
36mod nullifier;
37pub use nullifier::Nullifier;
38
39mod location;
40pub use location::{NoteInclusionProof, NoteLocation};
41
42mod partial;
43pub use partial::PartialNote;
44
45mod recipient;
46pub use recipient::NoteRecipient;
47
48mod script;
49pub use script::NoteScript;
50
51mod file;
52pub use file::NoteFile;
53
54// NOTE
55// ================================================================================================
56
57/// A note with all the data required for it to be consumed by executing it against the transaction
58/// kernel.
59///
60/// Notes consist of note metadata and details. Note metadata is always public, but details may be
61/// either public, encrypted, or private, depending on the note type. Note details consist of note
62/// assets, script, inputs, and a serial number, the three latter grouped into a recipient object.
63///
64/// Note details can be reduced to two unique identifiers: [NoteId] and [Nullifier]. The former is
65/// publicly associated with a note, while the latter is known only to entities which have access
66/// to full note details.
67///
68/// Fungible and non-fungible asset transfers are done by moving assets to the note's assets. The
69/// note's script determines the conditions required for the note consumption, i.e. the target
70/// account of a P2ID or conditions of a SWAP, and the effects of the note. The serial number has
71/// a double duty of preventing double spend, and providing unlikability to the consumer of a note.
72/// The note's inputs allow for customization of its script.
73///
74/// To create a note, the kernel does not require all the information above, a user can create a
75/// note only with the commitment to the script, inputs, the serial number (i.e., the recipient),
76/// and the kernel only verifies the source account has the assets necessary for the note creation.
77/// See [NoteRecipient] for more details.
78#[derive(Clone, Debug, PartialEq, Eq)]
79pub struct Note {
80    header: NoteHeader,
81    details: NoteDetails,
82
83    nullifier: Nullifier,
84}
85
86impl Note {
87    // CONSTRUCTOR
88    // --------------------------------------------------------------------------------------------
89
90    /// Returns a new [Note] created with the specified parameters.
91    pub fn new(assets: NoteAssets, metadata: NoteMetadata, recipient: NoteRecipient) -> Self {
92        let details = NoteDetails::new(assets, recipient);
93        let header = NoteHeader::new(details.id(), metadata);
94        let nullifier = details.nullifier();
95
96        Self { header, details, nullifier }
97    }
98
99    // PUBLIC ACCESSORS
100    // --------------------------------------------------------------------------------------------
101
102    /// Returns the note's header.
103    pub fn header(&self) -> &NoteHeader {
104        &self.header
105    }
106
107    /// Returns the note's unique identifier.
108    ///
109    /// This value is both an unique identifier and a commitment to the note.
110    pub fn id(&self) -> NoteId {
111        self.header.id()
112    }
113
114    /// Returns the note's metadata.
115    pub fn metadata(&self) -> &NoteMetadata {
116        self.header.metadata()
117    }
118
119    /// Returns the note's assets.
120    pub fn assets(&self) -> &NoteAssets {
121        self.details.assets()
122    }
123
124    /// Returns the note's recipient serial_num, the secret required to consume the note.
125    pub fn serial_num(&self) -> Word {
126        self.details.serial_num()
127    }
128
129    /// Returns the note's recipient script which locks the assets of this note.
130    pub fn script(&self) -> &NoteScript {
131        self.details.script()
132    }
133
134    /// Returns the note's recipient inputs which customizes the script's behavior.
135    pub fn inputs(&self) -> &NoteInputs {
136        self.details.inputs()
137    }
138
139    /// Returns the note's recipient.
140    pub fn recipient(&self) -> &NoteRecipient {
141        self.details.recipient()
142    }
143
144    /// Returns the note's nullifier.
145    ///
146    /// This is public data, used to prevent double spend.
147    pub fn nullifier(&self) -> Nullifier {
148        self.nullifier
149    }
150
151    /// Returns a commitment to the note and its metadata.
152    ///
153    /// > hash(NOTE_ID || NOTE_METADATA)
154    ///
155    /// This value is used primarily for authenticating notes consumed when the are consumed
156    /// in a transaction.
157    pub fn commitment(&self) -> Digest {
158        self.header.commitment()
159    }
160}
161
162// AS REF
163// ================================================================================================
164
165impl AsRef<NoteRecipient> for Note {
166    fn as_ref(&self) -> &NoteRecipient {
167        self.recipient()
168    }
169}
170
171// CONVERSIONS FROM NOTE
172// ================================================================================================
173
174impl From<&Note> for NoteHeader {
175    fn from(note: &Note) -> Self {
176        note.header
177    }
178}
179
180impl From<Note> for NoteHeader {
181    fn from(note: Note) -> Self {
182        note.header
183    }
184}
185
186impl From<&Note> for NoteDetails {
187    fn from(note: &Note) -> Self {
188        note.details.clone()
189    }
190}
191
192impl From<Note> for NoteDetails {
193    fn from(note: Note) -> Self {
194        note.details
195    }
196}
197
198impl From<Note> for PartialNote {
199    fn from(note: Note) -> Self {
200        let (assets, recipient, ..) = note.details.into_parts();
201        PartialNote::new(*note.header.metadata(), recipient.digest(), assets)
202    }
203}
204
205impl From<&Note> for PartialNote {
206    fn from(note: &Note) -> Self {
207        PartialNote::new(
208            *note.header.metadata(),
209            note.details.recipient().digest(),
210            note.details.assets().clone(),
211        )
212    }
213}
214
215// SERIALIZATION
216// ================================================================================================
217
218impl Serializable for Note {
219    fn write_into<W: ByteWriter>(&self, target: &mut W) {
220        let Self {
221            header,
222            details,
223
224            // nullifier is not serialized as it can be computed from the rest of the data
225            nullifier: _,
226        } = self;
227
228        // only metadata is serialized as note ID can be computed from note details
229        header.metadata().write_into(target);
230        details.write_into(target);
231    }
232}
233
234impl Deserializable for Note {
235    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
236        let metadata = NoteMetadata::read_from(source)?;
237        let details = NoteDetails::read_from(source)?;
238        let (assets, recipient) = details.into_parts();
239
240        Ok(Self::new(assets, metadata, recipient))
241    }
242}