miden_agglayer/config_note.rs
1//! CONFIG_AGG_BRIDGE note creation utilities.
2//!
3//! This module provides helpers for creating CONFIG_AGG_BRIDGE notes,
4//! which are used to register faucets in the bridge's faucet registry.
5
6extern crate alloc;
7
8use alloc::string::ToString;
9use alloc::vec;
10use alloc::vec::Vec;
11
12use miden_assembly::serde::Deserializable;
13use miden_core::{Felt, Word};
14use miden_protocol::account::AccountId;
15use miden_protocol::crypto::rand::FeltRng;
16use miden_protocol::errors::NoteError;
17use miden_protocol::note::{
18 Note,
19 NoteAssets,
20 NoteAttachment,
21 NoteMetadata,
22 NoteRecipient,
23 NoteScript,
24 NoteStorage,
25 NoteType,
26};
27use miden_protocol::vm::Program;
28use miden_standards::note::{NetworkAccountTarget, NoteExecutionHint};
29use miden_utils_sync::LazyLock;
30
31use crate::EthAddress;
32
33// NOTE SCRIPT
34// ================================================================================================
35
36// Initialize the CONFIG_AGG_BRIDGE note script only once
37static CONFIG_AGG_BRIDGE_SCRIPT: LazyLock<NoteScript> = LazyLock::new(|| {
38 let bytes =
39 include_bytes!(concat!(env!("OUT_DIR"), "/assets/note_scripts/CONFIG_AGG_BRIDGE.masb"));
40 let program =
41 Program::read_from_bytes(bytes).expect("shipped CONFIG_AGG_BRIDGE script is well-formed");
42 NoteScript::new(program)
43});
44
45// CONFIG_AGG_BRIDGE NOTE
46// ================================================================================================
47
48/// CONFIG_AGG_BRIDGE note.
49///
50/// This note is used to register a faucet in the bridge's faucet and token registries.
51/// It carries the origin token address and faucet account ID, and is always public.
52pub struct ConfigAggBridgeNote;
53
54impl ConfigAggBridgeNote {
55 // CONSTANTS
56 // --------------------------------------------------------------------------------------------
57
58 /// Expected number of storage items for a CONFIG_AGG_BRIDGE note.
59 /// Layout: [origin_token_addr(5), faucet_id_suffix, faucet_id_prefix]
60 pub const NUM_STORAGE_ITEMS: usize = 7;
61
62 // PUBLIC ACCESSORS
63 // --------------------------------------------------------------------------------------------
64
65 /// Returns the CONFIG_AGG_BRIDGE note script.
66 pub fn script() -> NoteScript {
67 CONFIG_AGG_BRIDGE_SCRIPT.clone()
68 }
69
70 /// Returns the CONFIG_AGG_BRIDGE note script root.
71 pub fn script_root() -> Word {
72 CONFIG_AGG_BRIDGE_SCRIPT.root()
73 }
74
75 // BUILDERS
76 // --------------------------------------------------------------------------------------------
77
78 /// Creates a CONFIG_AGG_BRIDGE note to register a faucet in the bridge's registry.
79 ///
80 /// The note storage contains 7 felts:
81 /// - `origin_token_addr[0..5]`: The 5 u32 felts of the origin EVM token address
82 /// - `faucet_id_suffix`: The suffix of the faucet account ID
83 /// - `faucet_id_prefix`: The prefix of the faucet account ID
84 ///
85 /// # Parameters
86 /// - `faucet_account_id`: The account ID of the faucet to register
87 /// - `origin_token_address`: The origin EVM token address for the token registry
88 /// - `sender_account_id`: The account ID of the note creator
89 /// - `target_account_id`: The bridge account ID that will consume this note
90 /// - `rng`: Random number generator for creating the note serial number
91 ///
92 /// # Errors
93 /// Returns an error if note creation fails.
94 pub fn create<R: FeltRng>(
95 faucet_account_id: AccountId,
96 origin_token_address: &EthAddress,
97 sender_account_id: AccountId,
98 target_account_id: AccountId,
99 rng: &mut R,
100 ) -> Result<Note, NoteError> {
101 // Create note storage with 7 felts: [origin_token_addr(5), faucet_id_suffix,
102 // faucet_id_prefix]
103 let addr_elements = origin_token_address.to_elements();
104 let mut storage_values: Vec<Felt> = addr_elements;
105 storage_values.push(faucet_account_id.suffix());
106 storage_values.push(faucet_account_id.prefix().as_felt());
107
108 let note_storage = NoteStorage::new(storage_values)?;
109
110 // Generate a serial number for the note
111 let serial_num = rng.draw_word();
112
113 let recipient = NoteRecipient::new(serial_num, Self::script(), note_storage);
114
115 let attachment = NoteAttachment::from(
116 NetworkAccountTarget::new(target_account_id, NoteExecutionHint::Always)
117 .map_err(|e| NoteError::other(e.to_string()))?,
118 );
119 let metadata =
120 NoteMetadata::new(sender_account_id, NoteType::Public).with_attachment(attachment);
121
122 // CONFIG_AGG_BRIDGE notes don't carry assets
123 let assets = NoteAssets::new(vec![])?;
124
125 Ok(Note::new(assets, metadata, recipient))
126 }
127}