rgbcore/validation/
commitments.rs

1// RGB Consensus Library: consensus layer for RGB smart contracts.
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// Copyright (C) 2019-2024 Dr Maxim Orlovsky. All rights reserved.
10//
11// Licensed under the Apache License, Version 2.0 (the "License");
12// you may not use this file except in compliance with the License.
13// You may obtain a copy of the License at
14//
15//     http://www.apache.org/licenses/LICENSE-2.0
16//
17// Unless required by applicable law or agreed to in writing, software
18// distributed under the License is distributed on an "AS IS" BASIS,
19// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20// See the License for the specific language governing permissions and
21// limitations under the License.
22
23use bp::dbc::opret::{OpretError, OpretProof};
24use bp::dbc::tapret::TapretProof;
25use bp::dbc::Method;
26use bp::{dbc, Tx};
27use commit_verify::mpc::Commitment;
28use commit_verify::{ConvolveVerifyError, EmbedVerifyError};
29use strict_encoding::{StrictDeserialize, StrictDumb, StrictSerialize};
30
31use crate::LIB_NAME_RGB_LOGIC;
32
33#[derive(Copy, Clone, Eq, PartialEq, Debug, Display, Error)]
34#[cfg_attr(
35    feature = "serde",
36    derive(Serialize, Deserialize),
37    serde(crate = "serde_crate", rename_all = "camelCase")
38)]
39#[display(doc_comments)]
40pub enum DbcError {
41    /// transaction doesn't contain OP_RETURN output.
42    NoOpretOutput,
43
44    /// first OP_RETURN output inside the transaction already contains some
45    /// data.
46    InvalidOpretScript,
47
48    /// commitment doesn't match the message.
49    CommitmentMismatch,
50
51    /// the proof is invalid and the commitment can't be verified since the
52    /// original container can't be restored from it.
53    UnrestorableProof,
54
55    /// the proof does not match to the proof generated for the same message
56    /// during the verification.
57    ProofMismatch,
58
59    /// the message is invalid since a valid commitment to it can't be created.
60    ImpossibleMessage,
61
62    /// the proof is invalid and the commitment can't be verified.
63    InvalidProof,
64}
65
66#[derive(Clone, Eq, PartialEq, Debug, From)]
67#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
68#[strict_type(lib = LIB_NAME_RGB_LOGIC, tags = custom, dumb = Self::Tapret(strict_dumb!()))]
69#[cfg_attr(
70    feature = "serde",
71    derive(Serialize, Deserialize),
72    serde(crate = "serde_crate", rename_all = "camelCase", untagged)
73)]
74pub enum DbcProof {
75    #[from]
76    #[strict_type(tag = 0x01)]
77    Tapret(TapretProof),
78
79    #[from]
80    #[strict_type(tag = 0x02)]
81    Opret(OpretProof),
82}
83
84impl StrictSerialize for DbcProof {}
85impl StrictDeserialize for DbcProof {}
86
87impl dbc::Proof for DbcProof {
88    type Error = DbcError;
89
90    fn method(&self) -> Method {
91        match self {
92            DbcProof::Tapret(_) => Method::TapretFirst,
93            DbcProof::Opret(_) => Method::OpretFirst,
94        }
95    }
96
97    fn verify(&self, msg: &Commitment, tx: &Tx) -> Result<(), Self::Error> {
98        match self {
99            DbcProof::Tapret(tapret) => tapret.verify(msg, tx).map_err(|err| match err {
100                ConvolveVerifyError::CommitmentMismatch => DbcError::CommitmentMismatch,
101                ConvolveVerifyError::ImpossibleMessage => DbcError::ImpossibleMessage,
102                ConvolveVerifyError::InvalidProof => DbcError::InvalidProof,
103            }),
104            DbcProof::Opret(opret) => opret.verify(msg, tx).map_err(|err| match err {
105                EmbedVerifyError::CommitmentMismatch => DbcError::CommitmentMismatch,
106                EmbedVerifyError::InvalidMessage(OpretError::NoOpretOutput) => {
107                    DbcError::NoOpretOutput
108                }
109                EmbedVerifyError::InvalidMessage(OpretError::InvalidOpretScript) => {
110                    DbcError::InvalidOpretScript
111                }
112                EmbedVerifyError::InvalidProof => DbcError::UnrestorableProof,
113                EmbedVerifyError::ProofMismatch => DbcError::ProofMismatch,
114            }),
115        }
116    }
117}
118
119/// Anchor which DBC proof is either Tapret or Opret.
120pub type EAnchor = dbc::Anchor<DbcProof>;