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