use alloc::vec;
use alloc::vec::Vec;
use miden_core::{Felt, Word};
use miden_protocol::account::AccountId;
use miden_protocol::crypto::SequentialCommit;
use miden_protocol::crypto::rand::FeltRng;
use miden_protocol::errors::NoteError;
use miden_protocol::note::{
Note,
NoteAssets,
NoteAttachment,
NoteAttachments,
NoteRecipient,
NoteScript,
NoteScriptRoot,
NoteStorage,
NoteType,
PartialNoteMetadata,
};
use miden_standards::interop::eth::{EthAddress, EthAmount};
use miden_standards::note::costs::NoteConsumptionCost;
use miden_standards::note::{MintNote, NetworkAccountTarget, NoteExecutionHint};
use miden_utils_sync::LazyLock;
use crate::costs::CLAIM_CONSUMPTION_CYCLES;
use crate::utils::Keccak256Output;
use crate::{GlobalIndex, MetadataHash, note_script};
const CLAIM_SCRIPT_PATH: &str = "::agglayer::notes::claim::main";
static CLAIM_SCRIPT: LazyLock<NoteScript> = LazyLock::new(|| note_script(CLAIM_SCRIPT_PATH));
pub struct ClaimNote;
impl ClaimNote {
pub fn script() -> NoteScript {
CLAIM_SCRIPT.clone()
}
pub fn script_root() -> NoteScriptRoot {
CLAIM_SCRIPT.root()
}
pub fn create<R: FeltRng>(
storage: ClaimNoteStorage,
target_bridge_id: AccountId,
sender_account_id: AccountId,
rng: &mut R,
) -> Result<Note, NoteError> {
let note_storage = NoteStorage::try_from(storage)?;
let attachment = NetworkAccountTarget::new(target_bridge_id, NoteExecutionHint::Always)
.map_err(|error| {
NoteError::other_with_source("failed to create claim network account target", error)
})?;
let attachments = NoteAttachments::from(NoteAttachment::from(attachment));
let metadata = PartialNoteMetadata::new(sender_account_id, NoteType::Public);
let recipient = NoteRecipient::new(rng.draw_word(), Self::script(), note_storage);
let assets = NoteAssets::new(vec![])?;
Ok(Note::with_attachments(assets, metadata, recipient, attachments))
}
}
pub type SmtNode = Keccak256Output;
pub type ExitRoot = Keccak256Output;
pub type LeafValue = Keccak256Output;
pub type CgiChainHash = Keccak256Output;
#[derive(Clone)]
pub struct ProofData {
pub smt_proof_local_exit_root: [SmtNode; 32],
pub smt_proof_rollup_exit_root: [SmtNode; 32],
pub global_index: GlobalIndex,
pub mainnet_exit_root: ExitRoot,
pub rollup_exit_root: ExitRoot,
}
impl SequentialCommit for ProofData {
type Commitment = Word;
fn to_elements(&self) -> Vec<Felt> {
const PROOF_DATA_ELEMENT_COUNT: usize = 536; let mut elements = Vec::with_capacity(PROOF_DATA_ELEMENT_COUNT);
for node in self.smt_proof_local_exit_root.iter() {
elements.extend(node.to_elements());
}
for node in self.smt_proof_rollup_exit_root.iter() {
elements.extend(node.to_elements());
}
elements.extend(self.global_index.to_elements());
elements.extend(self.mainnet_exit_root.to_elements());
elements.extend(self.rollup_exit_root.to_elements());
elements
}
}
#[derive(Clone)]
pub struct LeafData {
pub origin_network: u32,
pub origin_token_address: EthAddress,
pub destination_network: u32,
pub destination_address: EthAddress,
pub amount: EthAmount,
pub metadata_hash: MetadataHash,
}
impl SequentialCommit for LeafData {
type Commitment = Word;
fn to_elements(&self) -> Vec<Felt> {
const LEAF_DATA_ELEMENT_COUNT: usize = 32; let mut elements = Vec::with_capacity(LEAF_DATA_ELEMENT_COUNT);
elements.push(Felt::ZERO);
let origin_network = u32::from_le_bytes(self.origin_network.to_be_bytes());
elements.push(Felt::from(origin_network));
elements.extend(self.origin_token_address.to_elements());
let destination_network = u32::from_le_bytes(self.destination_network.to_be_bytes());
elements.push(Felt::from(destination_network));
elements.extend(self.destination_address.to_elements());
elements.extend(self.amount.to_elements());
elements.extend(self.metadata_hash.to_elements());
elements.extend(vec![Felt::ZERO; 3]);
elements
}
}
#[derive(Clone)]
pub struct ClaimNoteStorage {
pub proof_data: ProofData,
pub leaf_data: LeafData,
pub miden_claim_amount: Felt,
}
impl TryFrom<ClaimNoteStorage> for NoteStorage {
type Error = NoteError;
fn try_from(storage: ClaimNoteStorage) -> Result<Self, Self::Error> {
let mut claim_storage = Vec::with_capacity(569);
claim_storage.extend(storage.proof_data.to_elements());
claim_storage.extend(storage.leaf_data.to_elements());
claim_storage.push(storage.miden_claim_amount);
NoteStorage::new(claim_storage)
}
}
impl NoteConsumptionCost for ClaimNote {
fn consumption_cycles() -> u32 {
CLAIM_CONSUMPTION_CYCLES
}
fn created_notes() -> Vec<NoteScriptRoot> {
vec![MintNote::script_root()]
}
}