Skip to main content

miden_protocol/note/
mod.rs

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