Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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 {}
261 changes: 98 additions & 163 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
Loading