Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions seals/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,3 @@ pub mod txout;
mod secret;

pub use secret::SecretSeal;

/// Method for closing BP single-use-seals.
pub trait SealCloseMethod: dbc::DbcMethod {}

impl SealCloseMethod for dbc::Method {}
255 changes: 87 additions & 168 deletions seals/src/txout/blind.rs

Large diffs are not rendered by default.

3 changes: 0 additions & 3 deletions seals/src/txout/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@ use bc::Outpoint;
serde(crate = "serde_crate", rename_all = "camelCase")
)]
pub enum VerifyError<E: Error> {
/// seals provided for a batch verification have inconsistent close method.
InconsistentCloseMethod,

/// the provided witness transaction does not closes seal {0}.
WitnessNotClosingSeal(Outpoint),

Expand Down
67 changes: 21 additions & 46 deletions seals/src/txout/explicit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,9 @@ use std::str::FromStr;

use amplify::hex;
use bc::{Outpoint, Txid, Vout};
use dbc::MethodParseError;

use crate::txout::seal::{SealTxid, TxPtr};
use crate::txout::{CloseMethod, TxoSeal, WitnessVoutError};
use crate::SealCloseMethod;
use crate::txout::{TxoSeal, WitnessVoutError};

/// Revealed seal definition which may point to a witness transactions and does
/// not contain blinding data.
Expand All @@ -42,11 +40,7 @@ use crate::SealCloseMethod;
#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
#[strict_type(lib = dbc::LIB_NAME_BPCORE)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(crate = "serde_crate"))]
pub struct ExplicitSeal<Id: SealTxid, M: SealCloseMethod = CloseMethod> {
/// Commitment to the specific seal close method [`CloseMethod`] which must
/// be used to close this seal.
pub method: M,

pub struct ExplicitSeal<Id: SealTxid> {
/// Txid of the seal definition.
///
/// It may be missed in situations when ID of a transaction is not known,
Expand All @@ -59,36 +53,33 @@ pub struct ExplicitSeal<Id: SealTxid, M: SealCloseMethod = CloseMethod> {
pub vout: Vout,
}

impl<M: SealCloseMethod> TryFrom<&ExplicitSeal<TxPtr, M>> for Outpoint {
impl TryFrom<&ExplicitSeal<TxPtr>> for Outpoint {
type Error = WitnessVoutError;

#[inline]
fn try_from(reveal: &ExplicitSeal<TxPtr, M>) -> Result<Self, Self::Error> {
fn try_from(reveal: &ExplicitSeal<TxPtr>) -> Result<Self, Self::Error> {
reveal.txid.map_to_outpoint(reveal.vout).ok_or(WitnessVoutError)
}
}

impl<M: SealCloseMethod> TryFrom<ExplicitSeal<TxPtr, M>> for Outpoint {
impl TryFrom<ExplicitSeal<TxPtr>> for Outpoint {
type Error = WitnessVoutError;

#[inline]
fn try_from(reveal: ExplicitSeal<TxPtr, M>) -> Result<Self, Self::Error> {
fn try_from(reveal: ExplicitSeal<TxPtr>) -> Result<Self, Self::Error> {
Outpoint::try_from(&reveal)
}
}

impl<M: SealCloseMethod> From<&ExplicitSeal<Txid, M>> for Outpoint {
fn from(seal: &ExplicitSeal<Txid, M>) -> Self { Outpoint::new(seal.txid, seal.vout) }
impl From<&ExplicitSeal<Txid>> for Outpoint {
fn from(seal: &ExplicitSeal<Txid>) -> Self { Outpoint::new(seal.txid, seal.vout) }
}

impl<M: SealCloseMethod> From<ExplicitSeal<Txid, M>> for Outpoint {
fn from(seal: ExplicitSeal<Txid, M>) -> Self { Outpoint::from(&seal) }
impl From<ExplicitSeal<Txid>> for Outpoint {
fn from(seal: ExplicitSeal<Txid>) -> Self { Outpoint::from(&seal) }
}

impl<Id: SealTxid, M: SealCloseMethod> TxoSeal<M> for ExplicitSeal<Id, M> {
#[inline]
fn method(&self) -> M { self.method }

impl<Id: SealTxid> TxoSeal for ExplicitSeal<Id> {
#[inline]
fn txid(&self) -> Option<Txid> { self.txid.txid() }

Expand All @@ -107,29 +98,27 @@ impl<Id: SealTxid, M: SealCloseMethod> TxoSeal<M> for ExplicitSeal<Id, M> {
}
}

impl<Id: SealTxid, M: SealCloseMethod> ExplicitSeal<Id, M> {
impl<Id: SealTxid> ExplicitSeal<Id> {
/// Constructs seal for the provided outpoint and seal closing method.
#[inline]
pub fn new(method: M, outpoint: Outpoint) -> ExplicitSeal<Id, M> {
pub fn new(outpoint: Outpoint) -> ExplicitSeal<Id> {
Self {
method,
txid: Id::from(outpoint.txid),
vout: outpoint.vout,
}
}

/// Constructs seal.
#[inline]
pub fn with(method: M, txid: Id, vout: impl Into<Vout>) -> ExplicitSeal<Id, M> {
pub fn with(txid: Id, vout: impl Into<Vout>) -> ExplicitSeal<Id> {
ExplicitSeal {
method,
txid,
vout: vout.into(),
}
}
}

impl<M: SealCloseMethod> ExplicitSeal<Txid, M> {
impl ExplicitSeal<Txid> {
/// Converts seal into a transaction outpoint.
#[inline]
pub fn to_outpoint(&self) -> Outpoint { Outpoint::new(self.txid, self.vout) }
Expand All @@ -140,17 +129,9 @@ impl<M: SealCloseMethod> ExplicitSeal<Txid, M> {
#[derive(Clone, PartialEq, Eq, Debug, Display, Error, From)]
#[display(doc_comments)]
pub enum ParseError {
/// single-use-seal must start with method name (e.g. 'tapret1st' etc)
MethodRequired,

/// full transaction id is required for the seal specification
TxidRequired,

/// wrong seal close method id
#[display(inner)]
#[from]
WrongMethod(MethodParseError),

/// unable to parse transaction id value; it must be 64-character
/// hexadecimal string, however {0}
WrongTxid(hex::Error),
Expand All @@ -163,18 +144,14 @@ pub enum ParseError {
WrongStructure,
}

impl<Id: SealTxid, M: SealCloseMethod> FromStr for ExplicitSeal<Id, M>
where M: FromStr<Err = MethodParseError>
{
impl<Id: SealTxid> FromStr for ExplicitSeal<Id> {
type Err = ParseError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut split = s.split(&[':', '#'][..]);
match (split.next(), split.next(), split.next(), split.next()) {
(Some("~"), ..) | (Some(""), ..) => Err(ParseError::MethodRequired),
(Some(_), Some(""), ..) => Err(ParseError::TxidRequired),
(Some(method), Some(txid), Some(vout), None) => Ok(ExplicitSeal {
method: method.parse()?,
match (split.next(), split.next(), split.next()) {
(Some(""), ..) => Err(ParseError::TxidRequired),
(Some(txid), Some(vout), None) => Ok(ExplicitSeal {
txid: Id::from_str(txid).map_err(ParseError::WrongTxid)?,
vout: vout.parse().map_err(|_| ParseError::WrongVout)?,
}),
Expand All @@ -183,10 +160,8 @@ where M: FromStr<Err = MethodParseError>
}
}

impl<Id: SealTxid, M: SealCloseMethod> Display for ExplicitSeal<Id, M>
where M: Display
{
impl<Id: SealTxid> Display for ExplicitSeal<Id> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}:{}:{}", self.method, self.txid, self.vout,)
write!(f, "{}:{}", self.txid, self.vout,)
}
}
7 changes: 1 addition & 6 deletions seals/src/txout/seal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,11 @@ use amplify::hex;
use bc::{Outpoint, Txid, Vout};
use strict_encoding::{StrictDecode, StrictDumb, StrictEncode};

use crate::SealCloseMethod;

/// Method for closing single-use-seals.
pub type CloseMethod = dbc::Method;

/// Methods common for all transaction-output based seal types.
pub trait TxoSeal<M: SealCloseMethod = CloseMethod> {
/// Returns method which must be used for seal closing.
fn method(&self) -> M;

pub trait TxoSeal {
/// Returns [`Txid`] part of the seal definition, if known.
fn txid(&self) -> Option<Txid>;

Expand Down
28 changes: 7 additions & 21 deletions seals/src/txout/witness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,14 @@ use std::marker::PhantomData;

use bc::{Tx, Txid};
use commit_verify::mpc;
use dbc::{DbcMethod, Method};
use single_use_seals::SealWitness;

use crate::txout::{TxoSeal, VerifyError};
use crate::SealCloseMethod;

/// Witness of a bitcoin-based seal being closed. Includes both transaction and
/// extra-transaction data.
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct Witness<D: dbc::Proof<M>, M: DbcMethod = Method> {
pub struct Witness<D: dbc::Proof> {
/// Witness transaction: transaction which contains commitment to the
/// message over which the seal is closed.
pub tx: Tx,
Expand All @@ -44,13 +42,13 @@ pub struct Witness<D: dbc::Proof<M>, M: DbcMethod = Method> {
pub proof: D,

#[doc(hidden)]
pub _phantom: PhantomData<M>,
pub _phantom: PhantomData<D>,
}

impl<D: dbc::Proof<M>, M: DbcMethod> Witness<D, M> {
impl<D: dbc::Proof> Witness<D> {
/// Constructs witness from a witness transaction and extra-transaction
/// proof, taken from an anchor.
pub fn with(tx: Tx, dbc: D) -> Witness<D, M> {
pub fn with(tx: Tx, dbc: D) -> Witness<D> {
Witness {
txid: tx.txid(),
tx,
Expand All @@ -60,9 +58,7 @@ impl<D: dbc::Proof<M>, M: DbcMethod> Witness<D, M> {
}
}

impl<Seal: TxoSeal<M>, Dbc: dbc::Proof<M>, M: SealCloseMethod> SealWitness<Seal>
for Witness<Dbc, M>
{
impl<Seal: TxoSeal, Dbc: dbc::Proof> SealWitness<Seal> for Witness<Dbc> {
type Message = mpc::Commitment;
type Error = VerifyError<Dbc::Error>;

Expand All @@ -85,25 +81,15 @@ impl<Seal: TxoSeal<M>, Dbc: dbc::Proof<M>, M: SealCloseMethod> SealWitness<Seal>
where
Seal: 'seal,
{
let mut method = None;
for seal in seals {
// 1. All seals must have the same closing method
if let Some(method) = method {
if method != seal.method() {
return Err(VerifyError::InconsistentCloseMethod);
}
} else {
method = Some(seal.method());
}

// 2. Each seal must match tx inputs
// 1. Each seal must match tx inputs
let outpoint = seal.outpoint().ok_or(VerifyError::NoWitnessTxid)?;
if !self.tx.inputs.iter().any(|txin| txin.prev_output == outpoint) {
return Err(VerifyError::WitnessNotClosingSeal(outpoint));
}
}

// 3. Verify DBC with the giving closing method
// 2. Verify DBC with the giving closing method
self.proof.verify(msg, &self.tx).map_err(VerifyError::Dbc)
}
}
6 changes: 3 additions & 3 deletions src/bin/bpcore-stl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use bc::stl::{bp_consensus_stl, bp_tx_stl};
use bp::stl::bp_core_stl;
use commit_verify::stl::commit_verify_stl;
use commit_verify::CommitmentLayout;
use seals::txout::{ChainBlindSeal, CloseMethod, SingleBlindSeal};
use seals::txout::{ChainBlindSeal, SingleBlindSeal};
use strict_encoding::libname;
use strict_types::stl::std_stl;
use strict_types::{parse_args, SystemBuilder};
Expand Down Expand Up @@ -113,9 +113,9 @@ Seals vesper lexicon=types+commitments
"
)
.unwrap();
let layout = SingleBlindSeal::<CloseMethod>::commitment_layout();
let layout = SingleBlindSeal::commitment_layout();
writeln!(file, "{layout}").unwrap();
let layout = ChainBlindSeal::<CloseMethod>::commitment_layout();
let layout = ChainBlindSeal::commitment_layout();
writeln!(file, "{layout}").unwrap();
let tt = sys.type_tree("BPCore.BlindSealTxid").unwrap();
writeln!(file, "{tt}").unwrap();
Expand Down
12 changes: 6 additions & 6 deletions src/stl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ use bc::Txid;
use commit_verify::mpc;
use dbc::opret::OpretProof;
use dbc::tapret::TapretProof;
use dbc::{Method, LIB_NAME_BPCORE};
use dbc::LIB_NAME_BPCORE;
use seals::txout::TxPtr;
use strict_types::{CompileError, LibBuilder, TypeLib};

/// Strict types id for the library providing data types from [`dbc`] and
/// [`seals`] crates.
pub const LIB_ID_BPCORE: &str =
"stl:VhPW19SH-c5lzr1y-TLIsx8z-Z5nB!$Q-IgwrAQA-OqXLwUg#austin-story-retro";
"stl:IXCrofWg-Kg2!RIk-Hzlc5GO-7tH2hNB-YeBTdmN-$HZ0tPw#symbol-tropic-grand";

fn _bp_core_stl() -> Result<TypeLib, CompileError> {
LibBuilder::new(libname!(LIB_NAME_BPCORE), tiny_bset! {
Expand All @@ -46,11 +46,11 @@ fn _bp_core_stl() -> Result<TypeLib, CompileError> {
.transpile::<dbc::Anchor<mpc::MerkleTree, OpretProof>>()
.transpile::<dbc::Anchor<mpc::MerkleBlock, OpretProof>>()
.transpile::<dbc::Anchor<mpc::MerkleProof, OpretProof>>()
.transpile::<seals::txout::ExplicitSeal<TxPtr, Method>>()
.transpile::<seals::txout::ExplicitSeal<Txid, Method>>()
.transpile::<seals::txout::ExplicitSeal<TxPtr>>()
.transpile::<seals::txout::ExplicitSeal<Txid>>()
.transpile::<seals::SecretSeal>()
.transpile::<seals::txout::BlindSeal<TxPtr, Method>>()
.transpile::<seals::txout::BlindSeal<Txid, Method>>()
.transpile::<seals::txout::BlindSeal<TxPtr>>()
.transpile::<seals::txout::BlindSeal<Txid>>()
.compile()
}

Expand Down
Loading