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