miden_objects/note/
mod.rs

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