use core::convert::Infallible;
use core::fmt::{self, Display, Formatter};
use core::str::FromStr;
use amplify::confinement::TinyVec;
use amplify::{ByteArray, Bytes32};
use baid64::{Baid64ParseError, DisplayBaid64, FromBaid64Str};
use commit_verify::{CommitmentId, DigestExt, MerkleHash, Sha256};
use single_use_seals::{ClientSideWitness, PublishedWitness, SealWitness, SingleUseSeal};
use crate::{impl_serde_baid64, PrimeHeader, PrimeId, SealsHash, LIB_NAME_PRIME};
#[derive(Wrapper, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)]
#[wrapper(Deref, BorrowSlice, Hex, Index, RangeOps)]
#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
#[strict_type(lib = LIB_NAME_PRIME)]
#[derive(CommitEncode)]
#[commit_encode(strategy = strict, id = MerkleHash)]
pub struct PrimeSeal(
#[from]
#[from([u8; 32])]
Bytes32,
);
impl DisplayBaid64 for PrimeSeal {
const HRI: &'static str = "seal";
const CHUNKING: bool = true;
const PREFIX: bool = true;
const EMBED_CHECKSUM: bool = false;
const MNEMONIC: bool = false;
fn to_baid64_payload(&self) -> [u8; 32] { self.to_byte_array() }
}
impl FromBaid64Str for PrimeSeal {}
impl FromStr for PrimeSeal {
type Err = Baid64ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> { Self::from_baid64_str(s) }
}
impl Display for PrimeSeal {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { self.fmt_baid64(f) }
}
impl_serde_baid64!(PrimeSeal);
impl From<Sha256> for PrimeSeal {
fn from(hasher: Sha256) -> Self { hasher.finish().into() }
}
impl CommitmentId for PrimeSeal {
const TAG: &'static str = "urn:ultraviolet:prime:seal#2024-11-15";
}
impl SingleUseSeal for PrimeSeal {
type Message = SealsHash;
type PubWitness = PrimeHeader;
type CliWitness = InclProof;
fn is_included(&self, _: &SealWitness<Self>) -> bool { true }
}
impl PublishedWitness<PrimeSeal> for PrimeHeader {
type PubId = PrimeId;
type Error = InvalidProof;
fn pub_id(&self) -> Self::PubId { self.prime_id() }
fn verify_commitment(&self, msg: SealsHash) -> Result<(), Self::Error> {
if msg == self.seals_root {
Ok(())
} else {
Err(InvalidProof)
}
}
}
#[derive(Clone, Eq, PartialEq, Hash, Debug, From)]
#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
#[strict_type(lib = LIB_NAME_PRIME)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))]
pub struct MerklePathItem {
pub inverse: bool,
pub pair: MerkleHash,
}
#[derive(Clone, Eq, PartialEq, Hash, Debug, From, Default)]
#[derive(StrictType, StrictEncode, StrictDecode)]
#[strict_type(lib = LIB_NAME_PRIME)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))]
pub struct InclProof {
#[from]
pub merkle_path: TinyVec<MerklePathItem>,
}
impl ClientSideWitness for InclProof {
type Message = Bytes32;
type Seal = PrimeSeal;
type Error = Infallible;
fn convolve_commit(&self, _msg: Bytes32) -> Result<SealsHash, Self::Error> {
todo!();
}
}
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Display, Error, From)]
#[display("the provided proof is not valid for the given prime header")]
pub struct InvalidProof;