miden_standards/note/
mint.rs1use alloc::vec::Vec;
2
3use miden_protocol::account::AccountId;
4use miden_protocol::assembly::Path;
5use miden_protocol::crypto::rand::FeltRng;
6use miden_protocol::errors::NoteError;
7use miden_protocol::note::{
8 Note,
9 NoteAssets,
10 NoteAttachment,
11 NoteMetadata,
12 NoteRecipient,
13 NoteScript,
14 NoteStorage,
15 NoteTag,
16 NoteType,
17};
18use miden_protocol::utils::sync::LazyLock;
19use miden_protocol::{Felt, MAX_NOTE_STORAGE_ITEMS, Word};
20
21use crate::StandardsLib;
22
23const MINT_SCRIPT_PATH: &str = "::miden::standards::notes::mint::main";
28
29static MINT_SCRIPT: LazyLock<NoteScript> = LazyLock::new(|| {
31 let standards_lib = StandardsLib::default();
32 let path = Path::new(MINT_SCRIPT_PATH);
33 NoteScript::from_library_reference(standards_lib.as_ref(), path)
34 .expect("Standards library contains MINT note script procedure")
35});
36
37pub struct MintNote;
42
43impl MintNote {
44 pub const NUM_STORAGE_ITEMS_PRIVATE: usize = 8;
49
50 pub fn script() -> NoteScript {
55 MINT_SCRIPT.clone()
56 }
57
58 pub fn script_root() -> Word {
60 MINT_SCRIPT.root()
61 }
62
63 pub fn create<R: FeltRng>(
90 faucet_id: AccountId,
91 sender: AccountId,
92 mint_storage: MintNoteStorage,
93 attachment: NoteAttachment,
94 rng: &mut R,
95 ) -> Result<Note, NoteError> {
96 let note_script = Self::script();
97 let serial_num = rng.draw_word();
98
99 let note_type = NoteType::Public;
101
102 let storage = NoteStorage::from(mint_storage);
104
105 let tag = NoteTag::with_account_target(faucet_id);
106
107 let metadata =
108 NoteMetadata::new(sender, note_type).with_tag(tag).with_attachment(attachment);
109 let assets = NoteAssets::new(vec![])?; let recipient = NoteRecipient::new(serial_num, note_script, storage);
111
112 Ok(Note::new(assets, metadata, recipient))
113 }
114}
115
116#[derive(Debug, Clone, PartialEq, Eq)]
126pub enum MintNoteStorage {
127 Private {
128 recipient_digest: Word,
129 amount: Felt,
130 tag: Felt,
131 attachment: NoteAttachment,
132 },
133 Public {
134 recipient: NoteRecipient,
135 amount: Felt,
136 tag: Felt,
137 attachment: NoteAttachment,
138 },
139}
140
141impl MintNoteStorage {
142 pub fn new_private(recipient_digest: Word, amount: Felt, tag: Felt) -> Self {
143 Self::Private {
144 recipient_digest,
145 amount,
146 tag,
147 attachment: NoteAttachment::default(),
148 }
149 }
150
151 pub fn new_public(
152 recipient: NoteRecipient,
153 amount: Felt,
154 tag: Felt,
155 ) -> Result<Self, NoteError> {
156 const FIXED_PUBLIC_STORAGE_ITEMS: usize = 16;
160 let total_storage_items =
161 FIXED_PUBLIC_STORAGE_ITEMS + recipient.storage().num_items() as usize;
162
163 if total_storage_items > MAX_NOTE_STORAGE_ITEMS {
164 return Err(NoteError::TooManyStorageItems(total_storage_items));
165 }
166
167 Ok(Self::Public {
168 recipient,
169 amount,
170 tag,
171 attachment: NoteAttachment::default(),
172 })
173 }
174
175 pub fn with_attachment(self, attachment: NoteAttachment) -> Self {
177 match self {
178 MintNoteStorage::Private {
179 recipient_digest,
180 amount,
181 tag,
182 attachment: _,
183 } => MintNoteStorage::Private {
184 recipient_digest,
185 amount,
186 tag,
187 attachment,
188 },
189 MintNoteStorage::Public { recipient, amount, tag, attachment: _ } => {
190 MintNoteStorage::Public { recipient, amount, tag, attachment }
191 },
192 }
193 }
194}
195
196impl From<MintNoteStorage> for NoteStorage {
197 fn from(mint_storage: MintNoteStorage) -> Self {
198 match mint_storage {
199 MintNoteStorage::Private {
200 recipient_digest,
201 amount,
202 tag,
203 attachment,
204 } => {
205 let attachment_scheme = Felt::from(attachment.attachment_scheme().as_u32());
206 let attachment_kind = Felt::from(attachment.attachment_kind().as_u8());
207 let attachment = attachment.content().to_word();
208
209 let mut storage_values = Vec::with_capacity(12);
210 storage_values.extend_from_slice(&[
211 tag,
212 amount,
213 attachment_kind,
214 attachment_scheme,
215 ]);
216 storage_values.extend_from_slice(attachment.as_elements());
217 storage_values.extend_from_slice(recipient_digest.as_elements());
218 NoteStorage::new(storage_values)
219 .expect("number of storage items should not exceed max storage items")
220 },
221 MintNoteStorage::Public { recipient, amount, tag, attachment } => {
222 let attachment_scheme = Felt::from(attachment.attachment_scheme().as_u32());
223 let attachment_kind = Felt::from(attachment.attachment_kind().as_u8());
224 let attachment = attachment.content().to_word();
225
226 let mut storage_values = vec![tag, amount, attachment_kind, attachment_scheme];
227 storage_values.extend_from_slice(attachment.as_elements());
228 storage_values.extend_from_slice(recipient.script().root().as_elements());
229 storage_values.extend_from_slice(recipient.serial_num().as_elements());
230 storage_values.extend_from_slice(recipient.storage().items());
231 NoteStorage::new(storage_values)
232 .expect("number of storage items should not exceed max storage items")
233 },
234 }
235 }
236}