Skip to main content

urma_core/multipart/
proof.rs

1use super::{ChildReference, MultipartRecord};
2use crate::{
3    envelope,
4    error::{Error, ensure},
5};
6use bitcoin::{Transaction, Txid, XOnlyPublicKey};
7use sha2::{Digest, Sha256};
8
9#[derive(Clone, Debug)]
10pub struct VerifiedRecord {
11    txid: Txid,
12    author: XOnlyPublicKey,
13    record_hash: [u8; 32],
14    record: Vec<u8>,
15}
16
17impl VerifiedRecord {
18    pub fn verify(
19        expected: Txid,
20        reveal: &Transaction,
21        commit: &Transaction,
22    ) -> Result<Self, Error> {
23        ensure!(reveal.compute_txid() == expected, "candidate TXID mismatch");
24        let proof = envelope::verify_record_proof(reveal, commit)?;
25        Ok(Self {
26            txid: expected,
27            author: proof.author,
28            record_hash: Sha256::digest(&proof.record).into(),
29            record: proof.record,
30        })
31    }
32
33    pub fn txid(&self) -> Txid {
34        self.txid
35    }
36    pub fn author(&self) -> XOnlyPublicKey {
37        self.author
38    }
39    pub fn record_bytes(&self) -> &[u8] {
40        &self.record
41    }
42    pub fn decode(&self) -> Result<MultipartRecord, Error> {
43        MultipartRecord::decode(&self.record)
44    }
45    pub fn reference(&self) -> ChildReference {
46        ChildReference {
47            txid: self.txid,
48            record_hash: self.record_hash,
49        }
50    }
51}
52
53#[derive(Clone, Copy, Debug)]
54pub struct RecordRequest {
55    pub reference: ChildReference,
56}
57
58impl RecordRequest {
59    pub fn verify(
60        &self,
61        reveal: &Transaction,
62        commit: &Transaction,
63    ) -> Result<VerifiedRecord, Error> {
64        VerifiedRecord::verify(self.reference.txid, reveal, commit)
65    }
66
67    pub fn check_txid(&self, verified: &VerifiedRecord) -> Result<(), Error> {
68        ensure!(
69            verified.txid == self.reference.txid,
70            "candidate TXID mismatch"
71        );
72        Ok(())
73    }
74
75    pub fn check_hash(&self, verified: &VerifiedRecord) -> Result<(), Error> {
76        ensure!(
77            verified.record_hash == self.reference.record_hash,
78            "record hash differs from the signed manifest reference"
79        );
80        Ok(())
81    }
82}