Skip to main content

miden_agglayer/
update_ger_note.rs

1//! UPDATE_GER note creation utilities.
2//!
3//! This module provides helpers for creating UPDATE_GER notes,
4//! which are used to update the Global Exit Root in the bridge account.
5
6extern crate alloc;
7
8use alloc::string::ToString;
9use alloc::vec;
10
11use miden_assembly::Library;
12use miden_assembly::serde::Deserializable;
13use miden_protocol::account::AccountId;
14use miden_protocol::crypto::rand::FeltRng;
15use miden_protocol::errors::NoteError;
16use miden_protocol::note::{
17    Note,
18    NoteAssets,
19    NoteAttachment,
20    NoteAttachments,
21    NoteRecipient,
22    NoteScript,
23    NoteScriptRoot,
24    NoteStorage,
25    NoteType,
26    PartialNoteMetadata,
27};
28use miden_standards::note::{NetworkAccountTarget, NoteExecutionHint};
29use miden_utils_sync::LazyLock;
30
31use crate::ExitRoot;
32
33// NOTE SCRIPT
34// ================================================================================================
35
36// Initialize the UPDATE_GER note script only once
37static UPDATE_GER_SCRIPT: LazyLock<NoteScript> = LazyLock::new(|| {
38    let bytes = include_bytes!(concat!(env!("OUT_DIR"), "/assets/note_scripts/update_ger.masl"));
39    let library =
40        Library::read_from_bytes(bytes).expect("shipped UPDATE_GER script library is well-formed");
41    NoteScript::from_library(&library).expect("shipped UPDATE_GER script is well-formed")
42});
43
44// UPDATE_GER NOTE
45// ================================================================================================
46
47/// UPDATE_GER note.
48///
49/// This note is used to update the Global Exit Root (GER) in the bridge account.
50/// It carries the new GER data and is always public.
51pub struct UpdateGerNote;
52
53impl UpdateGerNote {
54    // CONSTANTS
55    // --------------------------------------------------------------------------------------------
56
57    /// Expected number of storage items for an UPDATE_GER note.
58    pub const NUM_STORAGE_ITEMS: usize = 8;
59
60    // PUBLIC ACCESSORS
61    // --------------------------------------------------------------------------------------------
62
63    /// Returns the UPDATE_GER note script.
64    pub fn script() -> NoteScript {
65        UPDATE_GER_SCRIPT.clone()
66    }
67
68    /// Returns the UPDATE_GER note script root.
69    pub fn script_root() -> NoteScriptRoot {
70        UPDATE_GER_SCRIPT.root()
71    }
72
73    // BUILDERS
74    // --------------------------------------------------------------------------------------------
75
76    /// Creates an UPDATE_GER note with the given GER (Global Exit Root) data.
77    ///
78    /// The note storage contains 8 felts: GER[0..7]
79    ///
80    /// # Parameters
81    /// - `ger`: The Global Exit Root data
82    /// - `sender_account_id`: The account ID of the note creator
83    /// - `target_account_id`: The account ID that will consume this note (bridge account)
84    /// - `rng`: Random number generator for creating the note serial number
85    ///
86    /// # Errors
87    /// Returns an error if note creation fails.
88    pub fn create<R: FeltRng>(
89        ger: ExitRoot,
90        sender_account_id: AccountId,
91        target_account_id: AccountId,
92        rng: &mut R,
93    ) -> Result<Note, NoteError> {
94        // Create note storage with 8 felts: GER[0..7]
95        let storage_values = ger.to_elements().to_vec();
96
97        let note_storage = NoteStorage::new(storage_values)?;
98
99        // Generate a serial number for the note
100        let serial_num = rng.draw_word();
101
102        let recipient = NoteRecipient::new(serial_num, Self::script(), note_storage);
103
104        let attachment = NetworkAccountTarget::new(target_account_id, NoteExecutionHint::Always)
105            .map_err(|e| NoteError::other(e.to_string()))?;
106        let attachments = NoteAttachments::from(NoteAttachment::from(attachment));
107        let metadata = PartialNoteMetadata::new(sender_account_id, NoteType::Public);
108
109        // UPDATE_GER notes don't carry assets
110        let assets = NoteAssets::new(vec![])?;
111
112        Ok(Note::with_attachments(assets, metadata, recipient, attachments))
113    }
114}