miden_agglayer/
claim_note.rs1use alloc::vec;
2use alloc::vec::Vec;
3
4use miden_assembly::Library;
5use miden_assembly::serde::Deserializable;
6use miden_core::{Felt, Word};
7use miden_protocol::account::AccountId;
8use miden_protocol::crypto::SequentialCommit;
9use miden_protocol::crypto::rand::FeltRng;
10use miden_protocol::errors::NoteError;
11use miden_protocol::note::{
12 Note,
13 NoteAssets,
14 NoteAttachment,
15 NoteAttachments,
16 NoteRecipient,
17 NoteScript,
18 NoteScriptRoot,
19 NoteStorage,
20 NoteType,
21 PartialNoteMetadata,
22};
23use miden_standards::note::{NetworkAccountTarget, NoteExecutionHint};
24use miden_utils_sync::LazyLock;
25
26use crate::utils::Keccak256Output;
27use crate::{EthAddress, EthAmount, GlobalIndex, MetadataHash};
28
29static CLAIM_SCRIPT: LazyLock<NoteScript> = LazyLock::new(|| {
34 let bytes = include_bytes!(concat!(env!("OUT_DIR"), "/assets/note_scripts/claim.masl"));
35 let library =
36 Library::read_from_bytes(bytes).expect("shipped CLAIM script library is well-formed");
37 NoteScript::from_library(&library).expect("shipped CLAIM script is well-formed")
38});
39
40pub struct ClaimNote;
48
49impl ClaimNote {
50 pub fn script() -> NoteScript {
55 CLAIM_SCRIPT.clone()
56 }
57
58 pub fn script_root() -> NoteScriptRoot {
60 CLAIM_SCRIPT.root()
61 }
62
63 pub fn create<R: FeltRng>(
79 storage: ClaimNoteStorage,
80 target_bridge_id: AccountId,
81 sender_account_id: AccountId,
82 rng: &mut R,
83 ) -> Result<Note, NoteError> {
84 let note_storage = NoteStorage::try_from(storage)?;
85
86 let attachment = NetworkAccountTarget::new(target_bridge_id, NoteExecutionHint::Always)
87 .map_err(|error| {
88 NoteError::other_with_source("failed to create claim network account target", error)
89 })?;
90 let attachments = NoteAttachments::from(NoteAttachment::from(attachment));
91
92 let metadata = PartialNoteMetadata::new(sender_account_id, NoteType::Public);
93
94 let recipient = NoteRecipient::new(rng.draw_word(), Self::script(), note_storage);
95 let assets = NoteAssets::new(vec![])?;
96
97 Ok(Note::with_attachments(assets, metadata, recipient, attachments))
98 }
99}
100
101pub type SmtNode = Keccak256Output;
106
107pub type ExitRoot = Keccak256Output;
109
110pub type LeafValue = Keccak256Output;
112
113pub type CgiChainHash = Keccak256Output;
115
116#[derive(Clone)]
119pub struct ProofData {
120 pub smt_proof_local_exit_root: [SmtNode; 32],
122 pub smt_proof_rollup_exit_root: [SmtNode; 32],
124 pub global_index: GlobalIndex,
126 pub mainnet_exit_root: ExitRoot,
128 pub rollup_exit_root: ExitRoot,
130}
131
132impl SequentialCommit for ProofData {
133 type Commitment = Word;
134
135 fn to_elements(&self) -> Vec<Felt> {
136 const PROOF_DATA_ELEMENT_COUNT: usize = 536; let mut elements = Vec::with_capacity(PROOF_DATA_ELEMENT_COUNT);
138
139 for node in self.smt_proof_local_exit_root.iter() {
141 elements.extend(node.to_elements());
142 }
143
144 for node in self.smt_proof_rollup_exit_root.iter() {
145 elements.extend(node.to_elements());
146 }
147
148 elements.extend(self.global_index.to_elements());
150
151 elements.extend(self.mainnet_exit_root.to_elements());
153 elements.extend(self.rollup_exit_root.to_elements());
154
155 elements
156 }
157}
158
159#[derive(Clone)]
162pub struct LeafData {
163 pub origin_network: u32,
165 pub origin_token_address: EthAddress,
167 pub destination_network: u32,
169 pub destination_address: EthAddress,
171 pub amount: EthAmount,
173 pub metadata_hash: MetadataHash,
175}
176
177impl SequentialCommit for LeafData {
178 type Commitment = Word;
179
180 fn to_elements(&self) -> Vec<Felt> {
181 const LEAF_DATA_ELEMENT_COUNT: usize = 32; let mut elements = Vec::with_capacity(LEAF_DATA_ELEMENT_COUNT);
183
184 elements.push(Felt::ZERO);
188
189 let origin_network = u32::from_le_bytes(self.origin_network.to_be_bytes());
191 elements.push(Felt::from(origin_network));
192
193 elements.extend(self.origin_token_address.to_elements());
195
196 let destination_network = u32::from_le_bytes(self.destination_network.to_be_bytes());
198 elements.push(Felt::from(destination_network));
199
200 elements.extend(self.destination_address.to_elements());
202
203 elements.extend(self.amount.to_elements());
205
206 elements.extend(self.metadata_hash.to_elements());
208
209 elements.extend(vec![Felt::ZERO; 3]);
211
212 elements
213 }
214}
215
216#[derive(Clone)]
221pub struct ClaimNoteStorage {
222 pub proof_data: ProofData,
224 pub leaf_data: LeafData,
226 pub miden_claim_amount: Felt,
228}
229
230impl TryFrom<ClaimNoteStorage> for NoteStorage {
231 type Error = NoteError;
232
233 fn try_from(storage: ClaimNoteStorage) -> Result<Self, Self::Error> {
234 let mut claim_storage = Vec::with_capacity(569);
237
238 claim_storage.extend(storage.proof_data.to_elements());
239 claim_storage.extend(storage.leaf_data.to_elements());
240 claim_storage.push(storage.miden_claim_amount);
241
242 NoteStorage::new(claim_storage)
243 }
244}