miden_agglayer/
claim_note.rs1use alloc::vec;
2use alloc::vec::Vec;
3
4use miden_core::{Felt, Word};
5use miden_protocol::account::AccountId;
6use miden_protocol::crypto::SequentialCommit;
7use miden_protocol::crypto::rand::FeltRng;
8use miden_protocol::errors::NoteError;
9use miden_protocol::note::{
10 Note,
11 NoteAssets,
12 NoteAttachment,
13 NoteAttachments,
14 NoteRecipient,
15 NoteScript,
16 NoteScriptRoot,
17 NoteStorage,
18 NoteType,
19 PartialNoteMetadata,
20};
21use miden_standards::interop::eth::{EthAddress, EthAmount};
22use miden_standards::note::costs::NoteConsumptionCost;
23use miden_standards::note::{MintNote, NetworkAccountTarget, NoteExecutionHint};
24use miden_utils_sync::LazyLock;
25
26use crate::costs::CLAIM_CONSUMPTION_CYCLES;
27use crate::utils::Keccak256Output;
28use crate::{GlobalIndex, MetadataHash, note_script};
29
30const CLAIM_SCRIPT_PATH: &str = "::agglayer::notes::claim::main";
35
36static CLAIM_SCRIPT: LazyLock<NoteScript> = LazyLock::new(|| note_script(CLAIM_SCRIPT_PATH));
38
39pub struct ClaimNote;
47
48impl ClaimNote {
49 pub fn script() -> NoteScript {
54 CLAIM_SCRIPT.clone()
55 }
56
57 pub fn script_root() -> NoteScriptRoot {
59 CLAIM_SCRIPT.root()
60 }
61
62 pub fn create<R: FeltRng>(
78 storage: ClaimNoteStorage,
79 target_bridge_id: AccountId,
80 sender_account_id: AccountId,
81 rng: &mut R,
82 ) -> Result<Note, NoteError> {
83 let note_storage = NoteStorage::try_from(storage)?;
84
85 let attachment = NetworkAccountTarget::new(target_bridge_id, NoteExecutionHint::Always)
86 .map_err(|error| {
87 NoteError::other_with_source("failed to create claim network account target", error)
88 })?;
89 let attachments = NoteAttachments::from(NoteAttachment::from(attachment));
90
91 let metadata = PartialNoteMetadata::new(sender_account_id, NoteType::Public);
92
93 let recipient = NoteRecipient::new(rng.draw_word(), Self::script(), note_storage);
94 let assets = NoteAssets::new(vec![])?;
95
96 Ok(Note::with_attachments(assets, metadata, recipient, attachments))
97 }
98}
99
100pub type SmtNode = Keccak256Output;
105
106pub type ExitRoot = Keccak256Output;
108
109pub type LeafValue = Keccak256Output;
111
112pub type CgiChainHash = Keccak256Output;
114
115#[derive(Clone)]
118pub struct ProofData {
119 pub smt_proof_local_exit_root: [SmtNode; 32],
121 pub smt_proof_rollup_exit_root: [SmtNode; 32],
123 pub global_index: GlobalIndex,
125 pub mainnet_exit_root: ExitRoot,
127 pub rollup_exit_root: ExitRoot,
129}
130
131impl SequentialCommit for ProofData {
132 type Commitment = Word;
133
134 fn to_elements(&self) -> Vec<Felt> {
135 const PROOF_DATA_ELEMENT_COUNT: usize = 536; let mut elements = Vec::with_capacity(PROOF_DATA_ELEMENT_COUNT);
137
138 for node in self.smt_proof_local_exit_root.iter() {
140 elements.extend(node.to_elements());
141 }
142
143 for node in self.smt_proof_rollup_exit_root.iter() {
144 elements.extend(node.to_elements());
145 }
146
147 elements.extend(self.global_index.to_elements());
149
150 elements.extend(self.mainnet_exit_root.to_elements());
152 elements.extend(self.rollup_exit_root.to_elements());
153
154 elements
155 }
156}
157
158#[derive(Clone)]
161pub struct LeafData {
162 pub origin_network: u32,
164 pub origin_token_address: EthAddress,
166 pub destination_network: u32,
168 pub destination_address: EthAddress,
170 pub amount: EthAmount,
172 pub metadata_hash: MetadataHash,
174}
175
176impl SequentialCommit for LeafData {
177 type Commitment = Word;
178
179 fn to_elements(&self) -> Vec<Felt> {
180 const LEAF_DATA_ELEMENT_COUNT: usize = 32; let mut elements = Vec::with_capacity(LEAF_DATA_ELEMENT_COUNT);
182
183 elements.push(Felt::ZERO);
187
188 let origin_network = u32::from_le_bytes(self.origin_network.to_be_bytes());
190 elements.push(Felt::from(origin_network));
191
192 elements.extend(self.origin_token_address.to_elements());
194
195 let destination_network = u32::from_le_bytes(self.destination_network.to_be_bytes());
197 elements.push(Felt::from(destination_network));
198
199 elements.extend(self.destination_address.to_elements());
201
202 elements.extend(self.amount.to_elements());
204
205 elements.extend(self.metadata_hash.to_elements());
207
208 elements.extend(vec![Felt::ZERO; 3]);
210
211 elements
212 }
213}
214
215#[derive(Clone)]
220pub struct ClaimNoteStorage {
221 pub proof_data: ProofData,
223 pub leaf_data: LeafData,
225 pub miden_claim_amount: Felt,
227}
228
229impl TryFrom<ClaimNoteStorage> for NoteStorage {
230 type Error = NoteError;
231
232 fn try_from(storage: ClaimNoteStorage) -> Result<Self, Self::Error> {
233 let mut claim_storage = Vec::with_capacity(569);
236
237 claim_storage.extend(storage.proof_data.to_elements());
238 claim_storage.extend(storage.leaf_data.to_elements());
239 claim_storage.push(storage.miden_claim_amount);
240
241 NoteStorage::new(claim_storage)
242 }
243}
244
245impl NoteConsumptionCost for ClaimNote {
249 fn consumption_cycles() -> u32 {
250 CLAIM_CONSUMPTION_CYCLES
251 }
252
253 fn created_notes() -> Vec<NoteScriptRoot> {
256 vec![MintNote::script_root()]
257 }
258}