Skip to main content

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}