#![doc = include_str!("seals.md")]
use std::fmt::{self, Display, Formatter};
use std::str::FromStr;
use bp::seals::txout::blind::ParseError;
use bp::seals::txout::{CloseMethod, TxPtr};
use bp::secp256k1::rand::{thread_rng, RngCore};
use bp::Vout;
use commit_verify::Conceal;
use rgb::{ExposedSeal, GenesisSeal, GraphSeal, SecretSeal};
use crate::{Outpoint, LIB_NAME_RGB_STD};
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, From)]
#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
#[strict_type(lib = LIB_NAME_RGB_STD)]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
serde(crate = "serde_crate", rename_all = "camelCase")
)]
pub struct VoutSeal {
pub method: CloseMethod,
pub vout: Vout,
pub blinding: u64,
}
impl VoutSeal {
#[inline]
pub fn new(method: CloseMethod, vout: impl Into<Vout>) -> Self {
VoutSeal::with(method, vout, thread_rng().next_u64())
}
#[inline]
pub fn new_opret(vout: impl Into<Vout>) -> Self { VoutSeal::new(CloseMethod::OpretFirst, vout) }
#[inline]
pub fn new_tapret(vout: impl Into<Vout>) -> Self {
VoutSeal::new(CloseMethod::TapretFirst, vout)
}
#[inline]
pub fn with_opret(vout: impl Into<Vout>, blinding: u64) -> Self {
VoutSeal::with(CloseMethod::OpretFirst, vout, blinding)
}
#[inline]
pub fn with_tapret(vout: impl Into<Vout>, blinding: u64) -> Self {
VoutSeal::with(CloseMethod::TapretFirst, vout, blinding)
}
#[inline]
pub fn with(method: CloseMethod, vout: impl Into<Vout>, blinding: u64) -> Self {
VoutSeal {
method,
vout: vout.into(),
blinding,
}
}
}
impl From<VoutSeal> for GraphSeal {
fn from(seal: VoutSeal) -> Self { Self::with_vout(seal.method, seal.vout, seal.blinding) }
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, From)]
#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
#[strict_type(lib = LIB_NAME_RGB_STD, tags = custom, dumb = Self::ConcealedUtxo(strict_dumb!()))]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
serde(crate = "serde_crate", rename_all = "camelCase")
)]
pub enum TerminalSeal {
#[from]
#[strict_type(tag = 0)]
ConcealedUtxo(SecretSeal),
#[strict_type(tag = 1)]
WitnessVout(VoutSeal),
}
impl From<GraphSeal> for TerminalSeal {
fn from(seal: GraphSeal) -> Self {
match seal.txid {
TxPtr::WitnessTx => {
TerminalSeal::WitnessVout(VoutSeal::with(seal.method, seal.vout, seal.blinding))
}
TxPtr::Txid(_) => TerminalSeal::ConcealedUtxo(seal.conceal()),
}
}
}
impl TerminalSeal {
pub fn new_vout(method: CloseMethod, vout: impl Into<Vout>) -> TerminalSeal {
TerminalSeal::WitnessVout(VoutSeal::new(method, vout))
}
pub fn secret_seal(&self) -> Option<SecretSeal> {
match self {
TerminalSeal::ConcealedUtxo(seal) => Some(*seal),
TerminalSeal::WitnessVout(_) => None,
}
}
}
impl Conceal for TerminalSeal {
type Concealed = SecretSeal;
fn conceal(&self) -> Self::Concealed {
match *self {
TerminalSeal::ConcealedUtxo(hash) => hash,
TerminalSeal::WitnessVout(seal) => GraphSeal::from(seal).conceal(),
}
}
}
impl Display for TerminalSeal {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match *self {
TerminalSeal::ConcealedUtxo(ref seal) => Display::fmt(seal, f),
TerminalSeal::WitnessVout(seal) => Display::fmt(&GraphSeal::from(seal), f),
}
}
}
impl FromStr for TerminalSeal {
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
SecretSeal::from_str(s)
.map(TerminalSeal::from)
.or_else(|_| GraphSeal::from_str(s).map(TerminalSeal::from))
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, From)]
pub enum BuilderSeal<Seal: ExposedSeal> {
Revealed(Seal),
#[from]
Concealed(SecretSeal),
}
impl<Seal: ExposedSeal> From<Outpoint> for BuilderSeal<Seal>
where Seal: From<Outpoint>
{
fn from(seal: Outpoint) -> Self { BuilderSeal::Revealed(seal.into()) }
}
impl<Seal: ExposedSeal> From<GraphSeal> for BuilderSeal<Seal>
where Seal: From<GraphSeal>
{
fn from(seal: GraphSeal) -> Self { BuilderSeal::Revealed(seal.into()) }
}
impl<Seal: ExposedSeal> From<GenesisSeal> for BuilderSeal<Seal>
where Seal: From<GenesisSeal>
{
fn from(seal: GenesisSeal) -> Self { BuilderSeal::Revealed(seal.into()) }
}