use core::cmp::Ordering;
use core::fmt::{self, Display, Formatter};
use core::str::FromStr;
use core::{iter, slice};
use amplify::confinement::{ConfinedVec, TinyBlob, TinyVec};
use amplify::{Bytes32, Wrapper};
use baid64::{Baid64ParseError, DisplayBaid64, FromBaid64Str};
use commit_verify::{CommitId, CommitmentId, DigestExt, MerkleHash, MerkleLeaves, ReservedBytes, Sha256};
use crate::{impl_serde_baid64, PrimeSeal, LIB_NAME_PRIME};
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
#[strict_type(lib = LIB_NAME_PRIME)]
#[derive(CommitEncode)]
#[commit_encode(strategy = strict, id = PrimeId)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))]
pub struct PrimeHeader {
pub version: ReservedBytes<9>,
pub diff_target: u8,
pub filters: u8,
pub tree_depth: u8,
pub nonce: u32,
pub height: u64,
pub timestamp: i64,
pub prev_header: PrimeId,
pub filters_root: FiltersHash,
pub seals_root: SealsHash,
pub public_key: Bytes32,
pub prev_secret_key: Bytes32,
pub coinbase: PrimeSeal,
pub publications: ProofsHash,
}
impl PartialOrd for PrimeHeader {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(other)) }
}
impl Ord for PrimeHeader {
fn cmp(&self, other: &Self) -> Ordering { self.prime_id().cmp(&other.prime_id()) }
}
impl PrimeHeader {
#[inline]
pub fn prime_id(&self) -> PrimeId { self.commit_id() }
}
#[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)]
pub struct PrimeId(
#[from]
#[from([u8; 32])]
Bytes32,
);
impl DisplayBaid64 for PrimeId {
const HRI: &'static str = "uv";
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 PrimeId {}
impl FromStr for PrimeId {
type Err = Baid64ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> { Self::from_baid64_str(s) }
}
impl Display for PrimeId {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { self.fmt_baid64(f) }
}
impl_serde_baid64!(PrimeId);
impl From<Sha256> for PrimeId {
fn from(hasher: Sha256) -> Self { hasher.finish().into() }
}
impl CommitmentId for PrimeId {
const TAG: &'static str = "urn:ultraviolet:prime:block#2024-11-15";
}
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
#[strict_type(lib = LIB_NAME_PRIME)]
#[derive(CommitEncode)]
#[commit_encode(strategy = merklize, id = FiltersHash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))]
pub struct FiltersBlock {
pub prime_id: PrimeId,
pub filters: ConfinedVec<BloomFilter, 0, 0x200>,
}
impl MerkleLeaves for FiltersBlock {
type Leaf = BloomFilter;
type LeafIter<'tmp>
= iter::Copied<slice::Iter<'tmp, BloomFilter>>
where Self: 'tmp;
fn merkle_leaves(&self) -> Self::LeafIter<'_> { self.filters.iter().copied() }
}
#[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)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(transparent))]
pub struct FiltersHash(
#[from]
#[from([u8; 32])]
Bytes32,
);
impl From<Sha256> for FiltersHash {
fn from(hasher: Sha256) -> Self { hasher.finish().into() }
}
impl CommitmentId for FiltersHash {
const TAG: &'static str = "urn:ultraviolet:prime:filters-block#2024-11-15";
}
#[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)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(transparent))]
pub struct BloomFilter(
#[from]
#[from([u8; 32])]
Bytes32,
);
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
#[strict_type(lib = LIB_NAME_PRIME)]
#[derive(CommitEncode)]
#[commit_encode(strategy = merklize, id = SealsHash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))]
pub struct SealsBlock {
pub prime_id: PrimeId,
pub seals: ConfinedVec<PrimeSeal, 0, 0x19000>,
}
impl MerkleLeaves for SealsBlock {
type Leaf = PrimeSeal;
type LeafIter<'tmp>
= iter::Copied<slice::Iter<'tmp, PrimeSeal>>
where Self: 'tmp;
fn merkle_leaves(&self) -> Self::LeafIter<'_> { self.seals.iter().copied() }
}
#[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)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(transparent))]
pub struct SealsHash(
#[from]
#[from([u8; 32])]
Bytes32,
);
impl From<Sha256> for SealsHash {
fn from(hasher: Sha256) -> Self { hasher.finish().into() }
}
impl CommitmentId for SealsHash {
const TAG: &'static str = "urn:ultraviolet:prime:seals-block#2024-11-15";
}
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
#[strict_type(lib = LIB_NAME_PRIME)]
#[derive(CommitEncode)]
#[commit_encode(strategy = merklize, id = ProofsHash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))]
pub struct ProofsBlock {
pub prime_id: PrimeId,
pub proofs: TinyVec<ProofOfPubl>,
}
impl MerkleLeaves for ProofsBlock {
type Leaf = ProofOfPubl;
type LeafIter<'tmp>
= iter::Cloned<slice::Iter<'tmp, ProofOfPubl>>
where Self: 'tmp;
fn merkle_leaves(&self) -> Self::LeafIter<'_> { self.proofs.iter().cloned() }
}
#[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)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(transparent))]
pub struct ProofsHash(
#[from]
#[from([u8; 32])]
Bytes32,
);
impl From<Sha256> for ProofsHash {
fn from(hasher: Sha256) -> Self { hasher.finish().into() }
}
impl CommitmentId for ProofsHash {
const TAG: &'static str = "urn:ultraviolet:prime:proofs-block#2024-11-15";
}
#[derive(Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Debug)]
#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
#[strict_type(lib = LIB_NAME_PRIME, tags = custom, dumb = Self::Custom(strict_dumb!()))]
#[derive(CommitEncode)]
#[commit_encode(strategy = strict, id = MerkleHash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(tag = "type", content = "data"))]
pub enum ProofOfPubl {
#[strict_type(tag = 0x00)]
Miner(TinyBlob),
#[strict_type(tag = 0xFF)]
Custom(TinyBlob),
}