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}