use crate::StdResult;
use crate::crypto_helper::{MKMapProof, ProtocolMkProof};
use crate::entities::TransactionHash;
use super::BlockRange;
#[derive(Clone, Debug, PartialEq)]
pub struct CardanoTransactionsSetProof {
pub(crate) transactions_hashes: Vec<TransactionHash>,
pub(crate) transactions_proof: ProtocolMkProof,
}
impl CardanoTransactionsSetProof {
pub fn new<T: Into<MKMapProof<BlockRange>>>(
transactions_hashes: Vec<TransactionHash>,
transactions_proof: T,
) -> Self {
Self {
transactions_hashes,
transactions_proof: ProtocolMkProof::new(transactions_proof.into()),
}
}
pub fn merkle_root(&self) -> String {
self.transactions_proof.compute_root().to_hex()
}
pub fn transactions_hashes(&self) -> &[TransactionHash] {
&self.transactions_hashes
}
pub fn verify(&self) -> StdResult<()> {
self.transactions_proof.verify()?;
for hash in &self.transactions_hashes {
self.transactions_proof.contains(&hash.to_owned().into())?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use crate::crypto_helper::MKTreeStoreInMemory;
use crate::entities::BlockNumber;
use crate::test::entities_extensions::CardanoTransactionsSetProofTestExtension;
use super::*;
#[test]
fn should_verify_where_all_hashes_are_contained_in_the_proof() {
let leaves = vec![
(BlockNumber(0), "tx-1".to_string()),
(BlockNumber(1), "tx-2".to_string()),
(BlockNumber(1), "tx-3".to_string()),
(BlockNumber(10), "tx-4".to_string()),
(BlockNumber(20), "tx-5".to_string()),
(BlockNumber(22), "tx-6".to_string()),
];
let proof =
CardanoTransactionsSetProof::from_leaves::<MKTreeStoreInMemory>(&leaves).unwrap();
proof.verify().expect("The proof should be valid");
}
#[test]
fn shouldnt_verify_where_at_least_one_hash_is_not_contained_in_the_proof() {
let leaves = vec![
(BlockNumber(0), "tx-1".to_string()),
(BlockNumber(1), "tx-2".to_string()),
(BlockNumber(1), "tx-3".to_string()),
(BlockNumber(10), "tx-4".to_string()),
(BlockNumber(20), "tx-5".to_string()),
(BlockNumber(22), "tx-6".to_string()),
];
let proof =
CardanoTransactionsSetProof::from_leaves::<MKTreeStoreInMemory>(&leaves).unwrap();
let mut transactions_hashes_tampered = proof.transactions_hashes().to_vec();
transactions_hashes_tampered.push("tx-123".to_string());
let proof = CardanoTransactionsSetProof {
transactions_hashes: transactions_hashes_tampered,
..proof
};
proof.verify().expect_err("The proof should be invalid");
}
}