use amplify::confinement::MediumOrdMap;
use amplify::num::u5;
use amplify::{Bytes32, FromSliceError, Wrapper};
use sha2::Sha256;
use strict_encoding::StrictDumb;
use crate::merkle::MerkleHash;
use crate::{CommitmentId, DigestExt};
pub const MPC_MINIMAL_DEPTH: u5 = u5::with(3);
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, Default)]
#[display(lowercase)]
#[derive(StrictType, StrictEncode, StrictDecode)]
#[strict_type(lib = crate::LIB_NAME_COMMIT_VERIFY, tags = repr, try_from_u8, into_u8)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))]
#[repr(u8)]
pub enum Method {
#[default]
Sha256t = 0,
}
pub type MessageMap = MediumOrdMap<ProtocolId, Message>;
#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From, Default)]
#[wrapper(Deref, BorrowSlice, Display, FromStr, Hex, Index, RangeOps)]
#[derive(StrictType, StrictEncode, StrictDecode)]
#[strict_type(lib = crate::LIB_NAME_COMMIT_VERIFY)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(transparent))]
pub struct ProtocolId(
#[from]
#[from([u8; 32])]
Bytes32,
);
impl ProtocolId {
pub fn copy_from_slice(slice: &[u8]) -> Result<Self, FromSliceError> {
Bytes32::copy_from_slice(slice).map(Self)
}
}
#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From, Default)]
#[wrapper(Deref, BorrowSlice, Display, FromStr, Hex, Index, RangeOps)]
#[derive(StrictType, StrictEncode, StrictDecode)]
#[strict_type(lib = crate::LIB_NAME_COMMIT_VERIFY)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(transparent))]
pub struct Message(
#[from]
#[from([u8; 32])]
Bytes32,
);
impl Message {
pub fn copy_from_slice(slice: &[u8]) -> Result<Self, FromSliceError> {
Bytes32::copy_from_slice(slice).map(Self)
}
}
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, From)]
#[derive(StrictType, StrictEncode, StrictDecode)]
#[strict_type(lib = crate::LIB_NAME_COMMIT_VERIFY, tags = custom)]
#[derive(CommitEncode)]
#[commit_encode(crate = crate, strategy = strict, id = MerkleHash)]
pub enum Leaf {
#[strict_type(tag = 0x10)]
Inhabited {
protocol: ProtocolId,
message: Message,
},
#[strict_type(tag = 0x11)]
Entropy {
entropy: u64,
pos: u32,
},
}
impl Leaf {
pub fn entropy(entropy: u64, pos: u32) -> Self { Self::Entropy { entropy, pos } }
pub fn inhabited(protocol: ProtocolId, message: Message) -> Self {
Self::Inhabited { protocol, message }
}
}
impl StrictDumb for Leaf {
fn strict_dumb() -> Self { Self::Entropy { entropy: 0, pos: 0 } }
}
#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)]
#[wrapper(Deref, BorrowSlice, Display, FromStr, Hex, Index, RangeOps)]
#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
#[strict_type(lib = crate::LIB_NAME_COMMIT_VERIFY)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(transparent))]
pub struct Commitment(
#[from]
#[from([u8; 32])]
Bytes32,
);
impl CommitmentId for Commitment {
const TAG: &'static str = "urn:ubideco:mpc:commitment#2024-01-31";
}
impl Commitment {
pub fn copy_from_slice(slice: &[u8]) -> Result<Self, FromSliceError> {
Bytes32::copy_from_slice(slice).map(Self)
}
}
impl From<Sha256> for Commitment {
fn from(hasher: Sha256) -> Self { hasher.finish().into() }
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct MultiSource {
pub method: Method,
pub min_depth: u5,
pub messages: MessageMap,
pub static_entropy: Option<u64>,
}
impl Default for MultiSource {
#[inline]
fn default() -> Self {
MultiSource {
method: Default::default(),
min_depth: MPC_MINIMAL_DEPTH,
messages: Default::default(),
static_entropy: None,
}
}
}
impl MultiSource {
#[inline]
pub fn with_static_entropy(static_entropy: u64) -> Self {
MultiSource {
static_entropy: Some(static_entropy),
..default!()
}
}
}