use core::str::FromStr;
use bp::seals::mmb;
use single_use_seals::SingleUseSeal;
use ultrasonic::AuthToken;
pub trait SealAuthToken {
fn auth_token(&self) -> AuthToken;
}
pub trait RgbSeal: SingleUseSeal<Message = mmb::Message> + SealAuthToken {}
#[cfg(feature = "bitcoin")]
pub const BITCOIN_OPRET: u32 = 0x0001_0001_u32;
#[cfg(feature = "bitcoin")]
pub const BITCOIN_TAPRET: u32 = 0x0001_0002_u32;
#[cfg(feature = "liquid")]
pub const LIQUID_OPRET: u32 = 0x0002_0001_u32;
#[cfg(feature = "liquid")]
pub const LIQUID_TAPRET: u32 = 0x0002_0002_u32;
#[cfg(feature = "prime")]
pub const PRIME_SEALS: u32 = 0x0010_0001_u32;
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[repr(u32)]
pub enum SealType {
#[cfg(feature = "bitcoin")]
#[display("bcor")]
BitcoinOpret = BITCOIN_OPRET,
#[cfg(feature = "bitcoin")]
#[display("bctr")]
BitcoinTapret = BITCOIN_TAPRET,
#[cfg(feature = "liquid")]
#[display("lqor")]
LiquidOpret = LIQUID_OPRET,
#[cfg(feature = "liquid")]
#[display("lqtr")]
LiquidTapret = LIQUID_TAPRET,
#[cfg(feature = "prime")]
#[display("prime")]
Prime = PRIME_SEALS,
}
#[derive(Clone, Eq, PartialEq, Debug, Display, Error)]
#[display("unknown seal type `{0}`")]
pub struct UnknownType(String);
impl FromStr for SealType {
type Err = UnknownType;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
#[cfg(feature = "bitcoin")]
"bcor" => Ok(SealType::BitcoinOpret),
#[cfg(feature = "bitcoin")]
"bctr" => Ok(SealType::BitcoinTapret),
#[cfg(feature = "liquid")]
"lqtr" => Ok(SealType::LiquidTapret),
#[cfg(feature = "prime")]
"prime" => Ok(SealType::Prime),
_ => Err(UnknownType(s.to_string())),
}
}
}
impl TryFrom<u32> for SealType {
type Error = UnknownType;
fn try_from(caps: u32) -> Result<Self, Self::Error> {
Ok(match caps {
#[cfg(feature = "bitcoin")]
BITCOIN_OPRET => Self::BitcoinOpret,
#[cfg(feature = "bitcoin")]
BITCOIN_TAPRET => Self::BitcoinTapret,
#[cfg(feature = "liquid")]
LIQUID_TAPRET => Self::LiquidTapret,
#[cfg(feature = "prime")]
PRIME_SEALS => Self::Prime,
unknown => return Err(UnknownType(format!("unknown seal type {unknown:#10x}"))),
})
}
}
#[cfg(any(feature = "bitcoin", feature = "liquid"))]
pub mod bitcoin {
use bp::dbc;
use bp::dbc::opret::OpretProof;
use bp::dbc::tapret::TapretProof;
use bp::seals::{TxoSeal, TxoSealDef};
use commit_verify::CommitId;
use super::*;
pub type OpretSeal = TxoSeal<OpretProof>;
pub type TapretSeal = TxoSeal<TapretProof>;
impl<D: dbc::Proof> SealAuthToken for TxoSeal<D> {
fn auth_token(&self) -> AuthToken { self.to_definition().auth_token() }
}
impl<D: dbc::Proof> RgbSeal for TxoSeal<D> {}
impl SealAuthToken for TxoSealDef {
fn auth_token(&self) -> AuthToken {
let id = self.commit_id().to_byte_array();
let mut shortened_id = [0u8; 30];
shortened_id.copy_from_slice(&id[0..30]);
AuthToken::from_byte_array(shortened_id)
}
}
}