dbc/
anchor.rs

1// Deterministic bitcoin commitments library.
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Written in 2019-2024 by
6//     Dr Maxim Orlovsky <orlovsky@lnp-bp.org>
7//
8// Copyright (C) 2019-2024 LNP/BP Standards Association. All rights reserved.
9//
10// Licensed under the Apache License, Version 2.0 (the "License");
11// you may not use this file except in compliance with the License.
12// You may obtain a copy of the License at
13//
14//     http://www.apache.org/licenses/LICENSE-2.0
15//
16// Unless required by applicable law or agreed to in writing, software
17// distributed under the License is distributed on an "AS IS" BASIS,
18// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19// See the License for the specific language governing permissions and
20// limitations under the License.
21
22//! Anchors are data structures used in deterministic bitcoin commitments for
23//! keeping information about the proof of the commitment in connection to the
24//! transaction which contains the commitment, and multi-protocol merkle tree as
25//! defined by LNPBP-4.
26
27use std::error::Error;
28
29use bc::Tx;
30use commit_verify::mpc::{self, Message, ProtocolId};
31use strict_encoding::{StrictDumb, StrictEncode};
32
33use crate::LIB_NAME_BPCORE;
34
35mod dbc {
36    pub use crate::Proof;
37}
38
39/// Errors verifying anchors.
40#[derive(Clone, Eq, PartialEq, Debug, Display, Error, From)]
41#[display(inner)]
42#[cfg_attr(
43    feature = "serde",
44    derive(Serialize, Deserialize),
45    serde(crate = "serde_crate", rename_all = "camelCase")
46)]
47pub enum VerifyError<E: Error> {
48    /// Deterministic commitment error.
49    #[display(inner)]
50    Dbc(E),
51
52    /// invalid MPC proof. Details: {0}
53    #[from]
54    Mpc(mpc::InvalidProof),
55}
56
57/// Anchor is a data structure used in deterministic bitcoin commitments for
58/// keeping information about the proof of the commitment in connection to the
59/// transaction which contains the commitment, and multi-protocol merkle tree as
60/// defined by LNPBP-4.
61#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
62#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
63#[strict_type(lib = LIB_NAME_BPCORE)]
64#[cfg_attr(
65    feature = "serde",
66    derive(Serialize, Deserialize),
67    serde(crate = "serde_crate", rename_all = "camelCase")
68)]
69pub struct Anchor<D: dbc::Proof> {
70    /// Structured multi-protocol LNPBP-4 data the transaction commits to.
71    pub mpc_proof: mpc::MerkleProof,
72
73    /// Proof of the DBC commitment.
74    pub dbc_proof: D,
75}
76
77impl<D: dbc::Proof> Anchor<D> {
78    /// Constructs anchor for a given witness transaction id, MPC and DBC
79    /// proofs.
80    pub fn new(mpc_proof: mpc::MerkleProof, dbc_proof: D) -> Self {
81        Self {
82            mpc_proof,
83            dbc_proof,
84        }
85    }
86}
87
88impl<D: dbc::Proof> Anchor<D> {
89    /// Verifies that the transaction commits to the anchor and the anchor
90    /// commits to the given message under the given protocol.
91    pub fn verify(
92        &self,
93        protocol_id: impl Into<ProtocolId>,
94        message: impl Into<Message>,
95        tx: &Tx,
96    ) -> Result<mpc::Commitment, VerifyError<D::Error>> {
97        let mpc_commitment = self.convolve(protocol_id, message)?;
98        self.dbc_proof.verify(&mpc_commitment, tx).map_err(VerifyError::Dbc)?;
99        Ok(mpc_commitment)
100    }
101
102    /// Verifies that the anchor commits to the given message under the given
103    /// protocol.
104    pub fn convolve(
105        &self,
106        protocol_id: impl Into<ProtocolId>,
107        message: impl Into<Message>,
108    ) -> Result<mpc::Commitment, mpc::InvalidProof> {
109        self.mpc_proof.convolve(protocol_id.into(), message.into())
110    }
111}