use crate::prelude::*;
use snarkvm_algorithms::merkle_tree::MerklePath;
use snarkvm_utilities::{FromBytes, ToBytes};
use anyhow::{anyhow, Result};
use std::io::{Read, Result as IoResult, Write};
#[derive(Clone, Debug)]
pub struct LocalProof<N: Network> {
transaction_id: N::TransactionID,
transaction_inclusion_proof: MerklePath<N::TransactionIDParameters>,
transition_id: N::TransitionID,
transition_inclusion_proof: MerklePath<N::TransitionIDParameters>,
commitment: N::Commitment,
}
impl<N: Network> LocalProof<N> {
pub fn new(
transaction_id: N::TransactionID,
transaction_inclusion_proof: MerklePath<N::TransactionIDParameters>,
transition_id: N::TransitionID,
transition_inclusion_proof: MerklePath<N::TransitionIDParameters>,
commitment: N::Commitment,
) -> Result<Self> {
if !transition_inclusion_proof.verify(&transition_id, &commitment)? {
return Err(anyhow!("Commitment {} does not belong to transition {}", commitment, transition_id));
}
if !transaction_inclusion_proof.verify(&transaction_id, &transition_id)? {
return Err(anyhow!("Transition {} does not belong to transaction {}", transition_id, transaction_id));
}
Ok(Self { transaction_id, transaction_inclusion_proof, transition_id, transition_inclusion_proof, commitment })
}
pub fn transaction_id(&self) -> N::TransactionID {
self.transaction_id
}
pub fn transaction_inclusion_proof(&self) -> &MerklePath<N::TransactionIDParameters> {
&self.transaction_inclusion_proof
}
pub fn transition_id(&self) -> N::TransitionID {
self.transition_id
}
pub fn transition_inclusion_proof(&self) -> &MerklePath<N::TransitionIDParameters> {
&self.transition_inclusion_proof
}
pub fn commitment(&self) -> N::Commitment {
self.commitment
}
}
impl<N: Network> FromBytes for LocalProof<N> {
#[inline]
fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
let transaction_id = FromBytes::read_le(&mut reader)?;
let transaction_inclusion_proof = FromBytes::read_le(&mut reader)?;
let transition_id = FromBytes::read_le(&mut reader)?;
let transition_inclusion_proof = FromBytes::read_le(&mut reader)?;
let commitment = FromBytes::read_le(&mut reader)?;
Ok(Self::new(
transaction_id,
transaction_inclusion_proof,
transition_id,
transition_inclusion_proof,
commitment,
)
.expect("Failed to deserialize a local inclusion proof"))
}
}
impl<N: Network> ToBytes for LocalProof<N> {
#[inline]
fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
self.transaction_id.write_le(&mut writer)?;
self.transaction_inclusion_proof.write_le(&mut writer)?;
self.transition_id.write_le(&mut writer)?;
self.transition_inclusion_proof.write_le(&mut writer)?;
self.commitment.write_le(&mut writer)
}
}
impl<N: Network> Default for LocalProof<N> {
fn default() -> Self {
Self {
transaction_id: Default::default(),
transaction_inclusion_proof: MerklePath::default(),
transition_id: Default::default(),
transition_inclusion_proof: MerklePath::default(),
commitment: Default::default(),
}
}
}