1use amplify::confinement::MediumOrdMap;
27use amplify::num::u5;
28use amplify::{Bytes32, FromSliceError, Wrapper};
29use sha2::Sha256;
30use strict_encoding::StrictDumb;
31
32use crate::merkle::MerkleHash;
33use crate::{CommitmentId, DigestExt};
34
35pub const MPC_MINIMAL_DEPTH: u5 = u5::with(3);
37
38#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, Default)]
46#[display(lowercase)]
47#[derive(StrictType, StrictEncode, StrictDecode)]
48#[strict_type(lib = crate::LIB_NAME_COMMIT_VERIFY, tags = repr, try_from_u8, into_u8)]
49#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))]
50#[repr(u8)]
51pub enum Method {
52 #[default]
54 Sha256t = 0,
55}
56
57pub type MessageMap = MediumOrdMap<ProtocolId, Message>;
59
60#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From, Default)]
65#[wrapper(Deref, BorrowSlice, Display, FromStr, Hex, Index, RangeOps)]
66#[derive(StrictType, StrictEncode, StrictDecode)]
67#[strict_type(lib = crate::LIB_NAME_COMMIT_VERIFY)]
68#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(transparent))]
69pub struct ProtocolId(
70 #[from]
71 #[from([u8; 32])]
72 Bytes32,
73);
74
75impl ProtocolId {
76 pub fn copy_from_slice(slice: &[u8]) -> Result<Self, FromSliceError> {
79 Bytes32::copy_from_slice(slice).map(Self)
80 }
81}
82
83#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From, Default)]
87#[wrapper(Deref, BorrowSlice, Display, FromStr, Hex, Index, RangeOps)]
88#[derive(StrictType, StrictEncode, StrictDecode)]
89#[strict_type(lib = crate::LIB_NAME_COMMIT_VERIFY)]
90#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(transparent))]
91pub struct Message(
92 #[from]
93 #[from([u8; 32])]
94 Bytes32,
95);
96
97impl Message {
98 pub fn copy_from_slice(slice: &[u8]) -> Result<Self, FromSliceError> {
101 Bytes32::copy_from_slice(slice).map(Self)
102 }
103}
104
105#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, From)]
107#[derive(StrictType, StrictEncode, StrictDecode)]
108#[strict_type(lib = crate::LIB_NAME_COMMIT_VERIFY, tags = custom)]
109#[derive(CommitEncode)]
110#[commit_encode(crate = crate, strategy = strict, id = MerkleHash)]
111pub enum Leaf {
112 #[strict_type(tag = 0x10)]
115 Inhabited {
116 protocol: ProtocolId,
118 message: Message,
120 },
121
122 #[strict_type(tag = 0x11)]
125 Entropy {
126 entropy: u64,
128 pos: u32,
130 },
131}
132
133impl Leaf {
134 pub fn entropy(entropy: u64, pos: u32) -> Self { Self::Entropy { entropy, pos } }
136
137 pub fn inhabited(protocol: ProtocolId, message: Message) -> Self {
139 Self::Inhabited { protocol, message }
140 }
141}
142
143impl StrictDumb for Leaf {
144 fn strict_dumb() -> Self { Self::Entropy { entropy: 0, pos: 0 } }
145}
146
147#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)]
154#[wrapper(Deref, BorrowSlice, Display, FromStr, Hex, Index, RangeOps)]
155#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
156#[strict_type(lib = crate::LIB_NAME_COMMIT_VERIFY)]
157#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(transparent))]
158pub struct Commitment(
159 #[from]
160 #[from([u8; 32])]
161 Bytes32,
162);
163
164impl CommitmentId for Commitment {
165 const TAG: &'static str = "urn:ubideco:mpc:commitment#2024-01-31";
166}
167
168impl Commitment {
169 pub fn copy_from_slice(slice: &[u8]) -> Result<Self, FromSliceError> {
172 Bytes32::copy_from_slice(slice).map(Self)
173 }
174}
175
176impl From<Sha256> for Commitment {
177 fn from(hasher: Sha256) -> Self { hasher.finish().into() }
178}
179
180#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
182pub struct MultiSource {
183 pub method: Method,
185 pub min_depth: u5,
187 pub messages: MessageMap,
189 pub static_entropy: Option<u64>,
194}
195
196impl Default for MultiSource {
197 #[inline]
198 fn default() -> Self {
199 MultiSource {
200 method: Default::default(),
201 min_depth: MPC_MINIMAL_DEPTH,
202 messages: Default::default(),
203 static_entropy: None,
204 }
205 }
206}
207
208impl MultiSource {
209 #[inline]
210 pub fn with_static_entropy(static_entropy: u64) -> Self {
213 MultiSource {
214 static_entropy: Some(static_entropy),
215 ..default!()
216 }
217 }
218}