use serde::{Deserialize, Serialize};
use crate::entities::{BlockHash, BlockNumber, BlockNumberOffset, CardanoBlock};
use crate::messages::proof_v2::ProofMessageVerifier;
use crate::messages::{CardanoBlockMessagePart, MkSetProofMessagePart, VerifyProofsV2Error};
#[cfg(target_family = "wasm")]
use wasm_bindgen::prelude::*;
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[cfg_attr(
target_family = "wasm",
wasm_bindgen(getter_with_clone, js_name = "CardanoBlocksProofs")
)]
pub struct CardanoBlocksProofsMessage {
pub certificate_hash: String,
#[cfg_attr(target_family = "wasm", wasm_bindgen(skip))]
pub certified_blocks: Option<MkSetProofMessagePart<CardanoBlockMessagePart>>,
pub non_certified_blocks: Vec<String>,
#[cfg_attr(target_family = "wasm", wasm_bindgen(skip))]
pub latest_block_number: BlockNumber,
#[cfg_attr(target_family = "wasm", wasm_bindgen(skip))]
pub security_parameter: BlockNumberOffset,
}
#[cfg_attr(target_family = "wasm", wasm_bindgen(js_class = "CardanoBlocksProofs"))]
impl CardanoBlocksProofsMessage {
#[cfg_attr(target_family = "wasm", wasm_bindgen(getter))]
pub fn blocks_hashes(&self) -> Vec<BlockHash> {
self.certified_blocks
.as_ref()
.map(|cbs| cbs.items.iter().map(|cb| cb.block_hash.clone()).collect())
.unwrap_or_default()
}
}
#[cfg(target_family = "wasm")]
#[wasm_bindgen(js_class = "CardanoBlocksProofs")]
impl CardanoBlocksProofsMessage {
#[wasm_bindgen(getter)]
pub fn certified_blocks(&self) -> Vec<CardanoBlockMessagePart> {
self.certified_blocks
.as_ref()
.map(|cbs| cbs.items.clone())
.unwrap_or_default()
}
#[wasm_bindgen(getter)]
pub fn latest_block_number(&self) -> u64 {
*self.latest_block_number
}
#[wasm_bindgen(getter)]
pub fn security_parameter(&self) -> u64 {
*self.latest_block_number
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct VerifiedCardanoBlocks {
certificate_hash: String,
merkle_root: String,
certified_blocks: Vec<CardanoBlockMessagePart>,
latest_block_number: BlockNumber,
security_parameter: BlockNumberOffset,
}
impl VerifiedCardanoBlocks {
pub fn certificate_hash(&self) -> &str {
&self.certificate_hash
}
pub fn certified_merkle_root(&self) -> &str {
&self.merkle_root
}
pub fn certified_blocks(&self) -> &[CardanoBlockMessagePart] {
&self.certified_blocks
}
pub fn certified_blocks_hashes(&self) -> Vec<BlockHash> {
self.certified_blocks.iter().map(|b| b.block_hash.clone()).collect()
}
pub fn latest_certified_block_number(&self) -> BlockNumber {
self.latest_block_number
}
pub fn security_parameter(&self) -> BlockNumberOffset {
self.security_parameter
}
}
impl CardanoBlocksProofsMessage {
pub fn new(
certificate_hash: &str,
certified_blocks: Option<MkSetProofMessagePart<CardanoBlockMessagePart>>,
non_certified_blocks: Vec<String>,
latest_block_number: BlockNumber,
security_parameter: BlockNumberOffset,
) -> Self {
Self {
certificate_hash: certificate_hash.to_string(),
certified_blocks,
non_certified_blocks,
latest_block_number,
security_parameter,
}
}
pub fn verify(&self) -> Result<VerifiedCardanoBlocks, VerifyProofsV2Error> {
const SUBJECT: &str = "Cardano blocks";
let certified_blocks = self
.certified_blocks
.as_ref()
.ok_or(VerifyProofsV2Error::NoCertifiedItem(SUBJECT))?;
let merkle_root =
ProofMessageVerifier::<_, CardanoBlock>::new(SUBJECT, |block| block.block_hash.clone())
.verify(certified_blocks)?;
Ok(VerifiedCardanoBlocks {
certificate_hash: self.certificate_hash.clone(),
merkle_root,
certified_blocks: certified_blocks.items.clone(),
latest_block_number: self.latest_block_number,
security_parameter: self.security_parameter,
})
}
}