use alloc::string::ToString;
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, NoteMetadata, NoteRecipient, NoteStorage, NoteType};
use miden_standards::note::{NetworkAccountTarget, NoteExecutionHint};
use crate::utils::Keccak256Output;
use crate::{EthAddress, EthAmount, GlobalIndex, MetadataHash, claim_script};
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)
}
}
pub fn create_claim_note<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.clone())?;
let attachment = NetworkAccountTarget::new(target_bridge_id, NoteExecutionHint::Always)
.map_err(|e| NoteError::other(e.to_string()))?
.into();
let metadata =
NoteMetadata::new(sender_account_id, NoteType::Public).with_attachment(attachment);
let recipient = NoteRecipient::new(rng.draw_word(), claim_script(), note_storage);
let assets = NoteAssets::new(vec![])?;
Ok(Note::new(assets, metadata, recipient))
}