mithril-common 0.7.14

Common types, interfaces, and utilities for Mithril nodes.
use serde::{Deserialize, Serialize};

use crate::entities::{
    BlockHash, BlockNumber, CardanoBlock, CardanoTransaction, IntoMKTreeNode, MkSetProof,
    SlotNumber,
};
use crate::{
    StdError, StdResult,
    crypto_helper::ProtocolMkProof,
    entities::{HexEncodedKey, TransactionHash},
};

#[cfg(target_family = "wasm")]
use wasm_bindgen::prelude::*;

/// A cryptographic proof that a set of items is included in a Merkle tree
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct MkSetProofMessagePart<T> {
    /// Items certified by the proof
    pub items: Vec<T>,

    /// Proof of the items
    pub proof: HexEncodedKey,
}

impl<T: Clone> MkSetProofMessagePart<T> {
    /// Verify this proof by converting to `MkSetProof<U>` and validating
    pub fn verify<U>(&self) -> StdResult<MkSetProof<U>>
    where
        U: IntoMKTreeNode + Clone + From<T>,
    {
        let mk_set_proof: MkSetProof<U> = self.clone().try_into()?;
        mk_set_proof.verify()?;
        Ok(mk_set_proof)
    }
}

impl<T, U: Into<T> + IntoMKTreeNode + Clone> TryFrom<MkSetProof<U>> for MkSetProofMessagePart<T> {
    type Error = StdError;

    fn try_from(value: MkSetProof<U>) -> Result<Self, Self::Error> {
        Ok(Self {
            items: value.items.into_iter().map(Into::into).collect(),
            proof: value.proof.to_bytes_hex()?,
        })
    }
}

impl<T: IntoMKTreeNode + Clone, U: Into<T>> TryFrom<MkSetProofMessagePart<U>> for MkSetProof<T> {
    type Error = StdError;

    fn try_from(value: MkSetProofMessagePart<U>) -> Result<Self, Self::Error> {
        Ok(Self {
            items: value.items.into_iter().map(Into::into).collect(),
            proof: ProtocolMkProof::from_bytes_hex(&value.proof)?,
        })
    }
}

/// Cardano block message representation
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(target_family = "wasm", wasm_bindgen(js_name = "CardanoBlock"))]
pub struct CardanoBlockMessagePart {
    /// Block hash
    #[cfg_attr(target_family = "wasm", wasm_bindgen(getter_with_clone))]
    pub block_hash: BlockHash,
    /// Block number
    #[cfg_attr(target_family = "wasm", wasm_bindgen(skip))]
    pub block_number: BlockNumber,
    /// Slot number of the block
    #[cfg_attr(target_family = "wasm", wasm_bindgen(skip))]
    pub slot_number: SlotNumber,
}

impl CardanoBlockMessagePart {
    /// CardanoBlockMessagePart factory
    pub fn new<U: Into<BlockHash>>(
        block_hash: U,
        block_number: BlockNumber,
        slot_number: SlotNumber,
    ) -> Self {
        Self {
            block_hash: block_hash.into(),
            block_number,
            slot_number,
        }
    }
}

#[cfg(target_family = "wasm")]
#[wasm_bindgen(js_class = "CardanoBlock")]
impl CardanoBlockMessagePart {
    /// Block number
    #[wasm_bindgen(getter)]
    pub fn block_number(&self) -> u64 {
        *self.block_number
    }

    /// Block number
    #[wasm_bindgen(getter)]
    pub fn slot_number(&self) -> u64 {
        *self.slot_number
    }
}

impl From<CardanoBlock> for CardanoBlockMessagePart {
    fn from(block: CardanoBlock) -> Self {
        Self {
            block_hash: block.block_hash,
            block_number: block.block_number,
            slot_number: block.slot_number,
        }
    }
}

impl From<CardanoBlockMessagePart> for CardanoBlock {
    fn from(block: CardanoBlockMessagePart) -> Self {
        Self {
            block_hash: block.block_hash,
            block_number: block.block_number,
            slot_number: block.slot_number,
        }
    }
}

/// Cardano transaction message representation
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
#[cfg_attr(target_family = "wasm", wasm_bindgen(js_name = "CardanoTransaction"))]
pub struct CardanoTransactionMessagePart {
    /// Unique hash of the transaction
    #[cfg_attr(target_family = "wasm", wasm_bindgen(getter_with_clone))]
    pub transaction_hash: TransactionHash,

    /// Block number of the transaction
    #[cfg_attr(target_family = "wasm", wasm_bindgen(skip))]
    pub block_number: BlockNumber,

    /// Slot number of the transaction
    #[cfg_attr(target_family = "wasm", wasm_bindgen(skip))]
    pub slot_number: SlotNumber,

    /// Block hash of the transaction
    #[cfg_attr(target_family = "wasm", wasm_bindgen(getter_with_clone))]
    pub block_hash: BlockHash,
}

impl CardanoTransactionMessagePart {
    /// CardanoTransactionMessagePart factory
    pub fn new<T: Into<TransactionHash>, U: Into<BlockHash>>(
        hash: T,
        block_number: BlockNumber,
        slot_number: SlotNumber,
        block_hash: U,
    ) -> Self {
        Self {
            transaction_hash: hash.into(),
            block_number,
            slot_number,
            block_hash: block_hash.into(),
        }
    }
}

#[cfg(target_family = "wasm")]
#[wasm_bindgen(js_class = "CardanoTransaction")]
impl CardanoTransactionMessagePart {
    /// Block number
    #[wasm_bindgen(getter)]
    pub fn block_number(&self) -> u64 {
        *self.block_number
    }

    /// Block number
    #[wasm_bindgen(getter)]
    pub fn slot_number(&self) -> u64 {
        *self.slot_number
    }
}

impl From<CardanoTransaction> for CardanoTransactionMessagePart {
    fn from(transaction: CardanoTransaction) -> Self {
        Self {
            transaction_hash: transaction.transaction_hash,
            block_number: transaction.block_number,
            slot_number: transaction.slot_number,
            block_hash: transaction.block_hash,
        }
    }
}

impl From<CardanoTransactionMessagePart> for CardanoTransaction {
    fn from(transaction: CardanoTransactionMessagePart) -> Self {
        Self {
            transaction_hash: transaction.transaction_hash,
            block_number: transaction.block_number,
            slot_number: transaction.slot_number,
            block_hash: transaction.block_hash,
        }
    }
}