urma-core 0.3.0

Canonical URMA V0 codecs, crypto and proof validation without I/O
Documentation
use super::{ChildReference, MultipartRecord};
use crate::{
    envelope,
    error::{Error, ensure},
};
use bitcoin::{Transaction, Txid, XOnlyPublicKey};
use sha2::{Digest, Sha256};

#[derive(Clone, Debug)]
pub struct VerifiedRecord {
    txid: Txid,
    author: XOnlyPublicKey,
    record_hash: [u8; 32],
    record: Vec<u8>,
}

impl VerifiedRecord {
    pub fn verify(
        expected: Txid,
        reveal: &Transaction,
        commit: &Transaction,
    ) -> Result<Self, Error> {
        ensure!(reveal.compute_txid() == expected, "candidate TXID mismatch");
        let proof = envelope::verify_record_proof(reveal, commit)?;
        Ok(Self {
            txid: expected,
            author: proof.author,
            record_hash: Sha256::digest(&proof.record).into(),
            record: proof.record,
        })
    }

    pub fn txid(&self) -> Txid {
        self.txid
    }
    pub fn author(&self) -> XOnlyPublicKey {
        self.author
    }
    pub fn record_bytes(&self) -> &[u8] {
        &self.record
    }
    pub fn decode(&self) -> Result<MultipartRecord, Error> {
        MultipartRecord::decode(&self.record)
    }
    pub fn reference(&self) -> ChildReference {
        ChildReference {
            txid: self.txid,
            record_hash: self.record_hash,
        }
    }
}

#[derive(Clone, Copy, Debug)]
pub struct RecordRequest {
    pub reference: ChildReference,
}

impl RecordRequest {
    pub fn verify(
        &self,
        reveal: &Transaction,
        commit: &Transaction,
    ) -> Result<VerifiedRecord, Error> {
        VerifiedRecord::verify(self.reference.txid, reveal, commit)
    }

    pub fn check_txid(&self, verified: &VerifiedRecord) -> Result<(), Error> {
        ensure!(
            verified.txid == self.reference.txid,
            "candidate TXID mismatch"
        );
        Ok(())
    }

    pub fn check_hash(&self, verified: &VerifiedRecord) -> Result<(), Error> {
        ensure!(
            verified.record_hash == self.reference.record_hash,
            "record hash differs from the signed manifest reference"
        );
        Ok(())
    }
}