use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct EthereumSealRef {
pub contract_address: [u8; 20],
pub slot_index: u64,
pub nonce: u64,
pub seal_id: [u8; 32],
}
impl EthereumSealRef {
pub fn new(contract_address: [u8; 20], slot_index: u64, nonce: u64) -> Self {
let mut seal_id = [0u8; 32];
seal_id[..20].copy_from_slice(&contract_address);
seal_id[20..28].copy_from_slice(&slot_index.to_le_bytes());
seal_id[28..].copy_from_slice(&nonce.to_le_bytes()[..4]); Self {
contract_address,
slot_index,
nonce,
seal_id,
}
}
pub fn to_vec(&self) -> Vec<u8> {
let mut out = Vec::with_capacity(20 + 8 + 8);
out.extend_from_slice(&self.contract_address);
out.extend_from_slice(&self.slot_index.to_le_bytes());
out.extend_from_slice(&self.nonce.to_le_bytes());
out
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct EthereumAnchorRef {
pub tx_hash: [u8; 32],
pub log_index: u64,
pub block_number: u64,
}
impl EthereumAnchorRef {
pub fn new(tx_hash: [u8; 32], log_index: u64, block_number: u64) -> Self {
Self {
tx_hash,
log_index,
block_number,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct EthereumInclusionProof {
pub receipt_rlp: Vec<u8>,
pub merkle_proof: Vec<u8>,
pub block_hash: [u8; 32],
pub block_number: u64,
pub log_index: u64,
}
impl EthereumInclusionProof {
pub fn new(
receipt_rlp: Vec<u8>,
merkle_proof: Vec<u8>,
block_hash: [u8; 32],
block_number: u64,
log_index: u64,
) -> Self {
Self {
receipt_rlp,
merkle_proof,
block_hash,
block_number,
log_index,
}
}
pub fn is_confirmed(&self, current_block: u64, required_depth: u64) -> bool {
self.block_number + required_depth <= current_block
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct EthereumFinalityProof {
pub confirmations: u64,
pub is_finalized: bool,
pub required_depth: u64,
}
impl EthereumFinalityProof {
pub fn new(confirmations: u64, required_depth: u64, is_finalized: bool) -> Self {
Self {
confirmations,
is_finalized,
required_depth,
}
}
pub fn is_final(&self) -> bool {
self.is_finalized || self.confirmations >= self.required_depth
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_seal_ref_creation() {
let seal = EthereumSealRef::new([1u8; 20], 42, 1);
assert_eq!(seal.slot_index, 42);
assert_eq!(seal.nonce, 1);
}
#[test]
fn test_anchor_ref_creation() {
let anchor = EthereumAnchorRef::new([2u8; 32], 5, 1000);
assert_eq!(anchor.log_index, 5);
assert_eq!(anchor.block_number, 1000);
}
#[test]
fn test_inclusion_proof_confirmed() {
let proof = EthereumInclusionProof::new(vec![], vec![], [3u8; 32], 1000, 5);
assert!(proof.is_confirmed(1015, 15));
assert!(!proof.is_confirmed(1010, 15));
}
#[test]
fn test_finality_proof() {
let proof = EthereumFinalityProof::new(15, 15, false);
assert!(proof.is_final());
let proof = EthereumFinalityProof::new(10, 15, false);
assert!(!proof.is_final());
let proof = EthereumFinalityProof::new(5, 15, true);
assert!(proof.is_final()); }
}