miden_protocol/note/
mod.rs1use miden_crypto::Word;
2
3use crate::account::AccountId;
4use crate::errors::NoteError;
5use crate::utils::serde::{
6 ByteReader,
7 ByteWriter,
8 Deserializable,
9 DeserializationError,
10 Serializable,
11};
12use crate::{Felt, Hasher, ZERO};
13
14mod assets;
15pub use assets::NoteAssets;
16
17mod details;
18pub use details::NoteDetails;
19
20mod header;
21pub use header::NoteHeader;
22
23mod storage;
24pub use storage::NoteStorage;
25
26mod metadata;
27pub use metadata::{NoteMetadata, PartialNoteMetadata};
28
29mod attachment;
30pub use attachment::{
31 NoteAttachment,
32 NoteAttachmentContent,
33 NoteAttachmentHeader,
34 NoteAttachmentScheme,
35 NoteAttachments,
36};
37
38mod note_id;
39pub use note_id::NoteId;
40
41mod note_details_commitment;
42pub use note_details_commitment::NoteDetailsCommitment;
43
44mod note_tag;
45pub use note_tag::NoteTag;
46
47mod note_type;
48pub use note_type::NoteType;
49
50mod nullifier;
51pub use nullifier::Nullifier;
52
53mod location;
54pub use location::{NoteInclusionProof, NoteLocation};
55
56mod partial;
57pub use partial::PartialNote;
58
59mod recipient;
60pub use recipient::NoteRecipient;
61
62mod script;
63pub use script::{NoteScript, NoteScriptRoot};
64
65#[derive(Clone, Debug, PartialEq, Eq)]
91pub struct Note {
92 header: NoteHeader,
93 details: NoteDetails,
94 attachments: NoteAttachments,
95
96 nullifier: Nullifier,
97}
98
99impl Note {
100 pub fn new(
105 assets: NoteAssets,
106 partial_metadata: PartialNoteMetadata,
107 recipient: NoteRecipient,
108 ) -> Self {
109 Self::with_attachments(assets, partial_metadata, recipient, NoteAttachments::default())
110 }
111
112 pub fn with_attachments(
114 assets: NoteAssets,
115 partial_metadata: PartialNoteMetadata,
116 recipient: NoteRecipient,
117 attachments: NoteAttachments,
118 ) -> Self {
119 let details = NoteDetails::new(assets, recipient);
120 let metadata = NoteMetadata::new(partial_metadata, &attachments);
121 let header = NoteHeader::new(details.commitment(), metadata);
122 let nullifier = Nullifier::from_details_and_metadata(&details, &metadata);
123
124 Self { header, details, attachments, nullifier }
125 }
126
127 pub fn header(&self) -> &NoteHeader {
132 &self.header
133 }
134
135 pub fn id(&self) -> NoteId {
139 self.header.id()
140 }
141
142 pub fn details_commitment(&self) -> NoteDetailsCommitment {
144 self.header.details_commitment()
145 }
146
147 pub fn details(&self) -> &NoteDetails {
149 &self.details
150 }
151
152 pub fn assets(&self) -> &NoteAssets {
154 self.details.assets()
155 }
156
157 pub fn serial_num(&self) -> Word {
159 self.details.serial_num()
160 }
161
162 pub fn script(&self) -> &NoteScript {
164 self.details.script()
165 }
166
167 pub fn storage(&self) -> &NoteStorage {
169 self.details.storage()
170 }
171
172 pub fn recipient(&self) -> &NoteRecipient {
174 self.details.recipient()
175 }
176
177 pub fn nullifier(&self) -> Nullifier {
181 self.nullifier
182 }
183
184 pub fn attachments(&self) -> &NoteAttachments {
186 &self.attachments
187 }
188
189 pub fn has_attachments(&self) -> bool {
191 !self.attachments.is_empty()
192 }
193
194 pub fn metadata(&self) -> &NoteMetadata {
196 self.header.metadata()
197 }
198
199 pub fn clear_debug_info(&mut self) {
204 self.details.clear_debug_info();
205 }
206
207 pub fn into_parts(self) -> (NoteAssets, NoteMetadata, NoteRecipient, NoteAttachments) {
209 let (assets, recipient) = self.details.into_parts();
210 let metadata = self.header.into_metadata();
211 (assets, metadata, recipient, self.attachments)
212 }
213}
214
215impl AsRef<NoteRecipient> for Note {
219 fn as_ref(&self) -> &NoteRecipient {
220 self.recipient()
221 }
222}
223
224impl From<Note> for NoteHeader {
228 fn from(note: Note) -> Self {
229 note.header
230 }
231}
232
233impl From<&Note> for NoteDetails {
234 fn from(note: &Note) -> Self {
235 note.details.clone()
236 }
237}
238
239impl From<Note> for NoteDetails {
240 fn from(note: Note) -> Self {
241 note.details
242 }
243}
244
245impl From<Note> for PartialNote {
246 fn from(note: Note) -> Self {
247 let (assets, recipient, ..) = note.details.into_parts();
248 PartialNote::new(
249 note.header.into_metadata().into_partial_metadata(),
250 recipient.digest(),
251 assets,
252 note.attachments,
253 )
254 }
255}
256
257impl From<&Note> for NoteHeader {
258 fn from(note: &Note) -> Self {
259 note.header
260 }
261}
262
263impl Serializable for Note {
267 fn write_into<W: ByteWriter>(&self, target: &mut W) {
268 let Self {
269 header,
270 details,
271 attachments,
272
273 nullifier: _,
275 } = self;
276
277 header.metadata().partial_metadata().write_into(target);
280 details.write_into(target);
281 attachments.write_into(target);
282 }
283
284 fn get_size_hint(&self) -> usize {
285 self.header.metadata().partial_metadata().get_size_hint()
286 + self.details.get_size_hint()
287 + self.attachments.get_size_hint()
288 }
289}
290
291impl Deserializable for Note {
292 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
293 let partial_metadata = PartialNoteMetadata::read_from(source)?;
294 let details = NoteDetails::read_from(source)?;
295 let attachments = NoteAttachments::read_from(source)?;
296 let (assets, recipient) = details.into_parts();
297
298 Ok(Self::with_attachments(assets, partial_metadata, recipient, attachments))
299 }
300}
301
302#[cfg(test)]
303mod tests {
304 use assert_matches::assert_matches;
305
306 use super::*;
307 use crate::utils::serde::{Deserializable, DeserializationError};
308
309 #[test]
310 fn note_deserialization_rejects_unsupported_version() {
311 let error = Note::read_from_bytes(&[0]).unwrap_err();
312
313 assert_matches!(error, DeserializationError::InvalidValue(message) => {
314 assert!(message.contains("note version is 0"));
315 });
316 }
317}