1#![deny(
28 unsafe_code,
29 dead_code,
30 missing_docs,
31 unused_variables,
32 unused_mut,
33 unused_imports,
34 non_upper_case_globals,
35 non_camel_case_types,
36 non_snake_case
37)]
38#![cfg_attr(docsrs, feature(doc_auto_cfg))]
39#![cfg_attr(coverage_nightly, feature(coverage_attribute))]
40
41#[macro_use]
46extern crate amplify;
47#[macro_use]
48extern crate strict_encoding;
49#[macro_use]
50extern crate commit_encoding_derive;
51#[cfg(feature = "serde")]
52#[macro_use]
53extern crate serde;
54
55#[cfg(feature = "derive")]
56pub use commit_encoding_derive::CommitEncode;
57
58mod commit;
59mod conceal;
60mod convolve;
61mod embed;
62mod id;
63#[cfg(feature = "stl")]
64pub mod stl;
65
66pub mod merkle;
67pub mod mpc;
68mod digest;
69#[cfg(feature = "vesper")]
70pub mod vesper;
71
72pub use commit::{CommitVerify, TryCommitVerify, VerifyError};
73pub use conceal::Conceal;
74pub use convolve::{ConvolveCommit, ConvolveCommitProof, ConvolveVerifyError};
75pub use digest::{Digest, DigestExt, Ripemd160, Sha256};
76pub use embed::{EmbedCommitProof, EmbedCommitVerify, EmbedVerifyError, VerifyEq};
77pub use id::{
78 CommitColType, CommitEncode, CommitEngine, CommitId, CommitLayout, CommitStep, CommitmentId,
79 CommitmentLayout, StrictHash,
80};
81pub use merkle::{MerkleBuoy, MerkleHash, MerkleLeaves, MerkleNode, NodeBranching};
82
83pub const LIB_NAME_COMMIT_VERIFY: &str = "CommitVerify";
85
86pub trait CommitmentProtocol {}
97
98pub struct UntaggedProtocol;
101impl CommitmentProtocol for UntaggedProtocol {}
102
103#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)]
105#[display("reserved")]
106#[derive(StrictType, StrictEncode)]
107#[strict_type(lib = LIB_NAME_COMMIT_VERIFY)]
108pub struct ReservedBytes<const LEN: usize, const VAL: u8 = 0>([u8; LEN]);
109
110impl<const LEN: usize, const VAL: u8> Default for ReservedBytes<LEN, VAL> {
111 fn default() -> Self { Self([VAL; LEN]) }
112}
113
114impl<const LEN: usize, const VAL: u8> From<[u8; LEN]> for ReservedBytes<LEN, VAL> {
115 fn from(value: [u8; LEN]) -> Self {
116 assert_eq!(value, [VAL; LEN]);
117 Self(value)
118 }
119}
120
121impl<const LEN: usize, const VAL: u8> ReservedBytes<LEN, VAL> {
122 pub const fn new() -> Self { Self([VAL; LEN]) }
124}
125
126mod _reserved {
127 use strict_encoding::{DecodeError, ReadTuple, StrictDecode, TypedRead};
128
129 use crate::{CommitEncode, CommitEngine, ReservedBytes, StrictHash};
130
131 impl<const LEN: usize, const VAL: u8> CommitEncode for ReservedBytes<LEN, VAL> {
132 type CommitmentId = StrictHash;
133
134 fn commit_encode(&self, e: &mut CommitEngine) { e.commit_to_serialized(self) }
135 }
136
137 impl<const LEN: usize, const VAL: u8> StrictDecode for ReservedBytes<LEN, VAL> {
138 fn strict_decode(reader: &mut impl TypedRead) -> Result<Self, DecodeError> {
139 let reserved = reader.read_tuple(|r| r.read_field().map(Self))?;
140 if reserved != ReservedBytes::<LEN, VAL>::default() {
141 Err(DecodeError::DataIntegrityError(format!(
142 "unsupported reserved byte value indicating a future RGB version. Please \
143 update your software, or, if the problem persists, contact your vendor \
144 providing the following version information: {reserved}"
145 )))
146 } else {
147 Ok(reserved)
148 }
149 }
150 }
151
152 #[cfg(feature = "serde")]
153 mod _serde {
154 use amplify::hex::{FromHex, ToHex};
155 use serde::de::Error;
156 use serde::{Deserialize, Deserializer, Serialize, Serializer};
157
158 use super::*;
159
160 impl<const LEN: usize, const VAL: u8> Serialize for ReservedBytes<LEN, VAL> {
161 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
162 where S: Serializer {
163 if serializer.is_human_readable() {
164 serializer.serialize_str(&self.0.to_hex())
165 } else {
166 serializer.serialize_bytes(self.0.as_ref())
167 }
168 }
169 }
170
171 impl<'de, const LEN: usize, const VAL: u8> Deserialize<'de> for ReservedBytes<LEN, VAL> {
172 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
173 where D: Deserializer<'de> {
174 let v = if deserializer.is_human_readable() {
175 let s = String::deserialize(deserializer)?;
176 Vec::<u8>::from_hex(&s)
177 .map_err(|_| D::Error::custom("invalid reserved value"))?
178 } else {
179 Vec::<u8>::deserialize(deserializer)?
180 };
181
182 if v != [VAL; LEN] {
183 return Err(Error::custom("invalid reserved value"));
184 }
185
186 Ok(default!())
187 }
188 }
189 }
190}
191
192#[cfg(test)]
194pub mod test_helpers {
195 #![cfg_attr(coverage_nightly, coverage(off))]
196
197 use amplify::confinement::SmallVec;
198 use amplify::hex::FromHex;
199
200 pub use super::commit::test_helpers::*;
201 pub use super::embed::test_helpers::*;
202 use super::*;
203
204 pub fn gen_messages() -> Vec<SmallVec<u8>> {
209 vec![
210 b"".to_vec(),
212 b"\x00".to_vec(),
214 b"test".to_vec(),
216 b"test*".to_vec(),
218 Vec::from_hex("deadbeef").unwrap(),
220 Vec::from_hex("deadbeef00").unwrap(),
222 Vec::from_hex("00deadbeef").unwrap(),
224 b"0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798".to_vec(),
226 Vec::from_hex("0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798")
228 .unwrap(),
229 Vec::from_hex("02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9")
231 .unwrap(),
232 ]
233 .into_iter()
234 .map(|v| SmallVec::try_from(v).unwrap())
235 .collect()
236 }
237}