Skip to content

Commit

Permalink
Merge pull request #71 from BP-WG/v0.11
Browse files Browse the repository at this point in the history
Imptove APIs from the point of multiple chain support and better determinism for blinding
  • Loading branch information
dr-orlovsky authored Dec 30, 2023
2 parents 569a36a + 4c46acd commit 04e277b
Show file tree
Hide file tree
Showing 23 changed files with 445 additions and 315 deletions.
18 changes: 9 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ default-members = [
]

[workspace.package]
version = "0.11.0-beta.2"
version = "0.11.0-beta.3"
authors = ["Dr Maxim Orlovsky <[email protected]>"]
homepage = "https://github.com/BP-WG"
repository = "https://github.com/BP-WG/bp-core"
Expand All @@ -23,13 +23,13 @@ license = "Apache-2.0"

[workspace.dependencies]
amplify = "4.5.0"
strict_encoding = "2.6.1"
strict_encoding = ">=2.6.2"
strict_types = "1.6.3"
commit_verify = "0.11.0-beta.2"
single_use_seals = "0.11.0-beta.2"
commit_verify = "0.11.0-beta.3"
single_use_seals = "0.11.0-beta.3"
bp-consensus = { version = "0.11.0-beta.3", path = "consensus" }
bp-dbc = { version = "0.11.0-beta.2", path = "./dbc" }
bp-seals = { version = "0.11.0-beta.2", path = "./seals" }
bp-dbc = { version = "0.11.0-beta.3", path = "./dbc" }
bp-seals = { version = "0.11.0-beta.3", path = "./seals" }
secp256k1 = { version = "0.28.0", features = ["global-context"] }
serde_crate = { package = "serde", version = "1", features = ["derive"] }

Expand Down
3 changes: 1 addition & 2 deletions consensus/src/coding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,7 @@ mod _serde {
})
} else {
let bytes = Vec::<u8>::deserialize(deserializer)?;
Self::try_from(bytes)
.map_err(|_| D::Error::custom("invalid script length exceeding 4GB"))
Ok(Self::from(bytes))
}
}
}
Expand Down
4 changes: 1 addition & 3 deletions consensus/src/segwit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,9 +394,7 @@ impl Witness {
}

pub fn from_consensus_stack(witness: impl IntoIterator<Item = Vec<u8>>) -> Witness {
let iter = witness.into_iter().map(|vec| {
ByteStr::try_from(vec).expect("witness stack element length exceeds 2^32 bytes")
});
let iter = witness.into_iter().map(ByteStr::from);
let stack =
VarIntArray::try_from_iter(iter).expect("witness stack size exceeds 2^32 elements");
Witness(stack)
Expand Down
23 changes: 15 additions & 8 deletions dbc/src/anchor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@
//! defined by LNPBP-4.

use std::error::Error;
use std::marker::PhantomData;

use bc::{Tx, Txid};
use commit_verify::mpc::{self, Message, ProtocolId};
use strict_encoding::{StrictDumb, StrictEncode};

use crate::LIB_NAME_BPCORE;
use crate::{DbcMethod, Method, LIB_NAME_BPCORE};

mod dbc {
pub use crate::Proof;
Expand Down Expand Up @@ -67,7 +68,7 @@ pub enum VerifyError<E: Error> {
derive(Serialize, Deserialize),
serde(crate = "serde_crate", rename_all = "camelCase")
)]
pub struct Anchor<L: mpc::Proof + StrictDumb, D: dbc::Proof> {
pub struct Anchor<L: mpc::Proof + StrictDumb, D: dbc::Proof<M>, M: DbcMethod = Method> {
/// Transaction containing deterministic bitcoin commitment.
pub txid: Txid,

Expand All @@ -76,6 +77,10 @@ pub struct Anchor<L: mpc::Proof + StrictDumb, D: dbc::Proof> {

/// Proof of the DBC commitment.
pub dbc_proof: D,

#[doc(hidden)]
#[strict_type(skip)]
pub _method: PhantomData<M>,
}

/// Error merging two [`Anchor`]s.
Expand All @@ -94,19 +99,20 @@ pub enum MergeError {
DbcMismatch,
}

impl<D: dbc::Proof> Anchor<mpc::MerkleProof, D> {
impl<D: dbc::Proof<M>, M: DbcMethod> Anchor<mpc::MerkleProof, D, M> {
/// Reconstructs anchor containing merkle block
pub fn into_merkle_block(
self,
protocol_id: impl Into<ProtocolId>,
message: impl Into<Message>,
) -> Result<Anchor<mpc::MerkleBlock, D>, mpc::InvalidProof> {
) -> Result<Anchor<mpc::MerkleBlock, D, M>, mpc::InvalidProof> {
let lnpbp4_proof =
mpc::MerkleBlock::with(&self.mpc_proof, protocol_id.into(), message.into())?;
Ok(Anchor {
txid: self.txid,
mpc_proof: lnpbp4_proof,
dbc_proof: self.dbc_proof,
_method: default!(),
})
}

Expand All @@ -115,7 +121,7 @@ impl<D: dbc::Proof> Anchor<mpc::MerkleProof, D> {
&self,
protocol_id: impl Into<ProtocolId>,
message: impl Into<Message>,
) -> Result<Anchor<mpc::MerkleBlock, D>, mpc::InvalidProof> {
) -> Result<Anchor<mpc::MerkleBlock, D, M>, mpc::InvalidProof> {
self.clone().into_merkle_block(protocol_id, message)
}

Expand Down Expand Up @@ -145,13 +151,13 @@ impl<D: dbc::Proof> Anchor<mpc::MerkleProof, D> {
}
}

impl<D: dbc::Proof> Anchor<mpc::MerkleBlock, D> {
impl<D: dbc::Proof<M>, M: DbcMethod> Anchor<mpc::MerkleBlock, D, M> {
/// Conceals all LNPBP-4 data except specific protocol and produces merkle
/// proof anchor.
pub fn to_merkle_proof(
&self,
protocol: impl Into<ProtocolId>,
) -> Result<Anchor<mpc::MerkleProof, D>, mpc::LeafNotKnown> {
) -> Result<Anchor<mpc::MerkleProof, D, M>, mpc::LeafNotKnown> {
self.clone().into_merkle_proof(protocol)
}

Expand All @@ -160,12 +166,13 @@ impl<D: dbc::Proof> Anchor<mpc::MerkleBlock, D> {
pub fn into_merkle_proof(
self,
protocol: impl Into<ProtocolId>,
) -> Result<Anchor<mpc::MerkleProof, D>, mpc::LeafNotKnown> {
) -> Result<Anchor<mpc::MerkleProof, D, M>, mpc::LeafNotKnown> {
let lnpbp4_proof = self.mpc_proof.to_merkle_proof(protocol.into())?;
Ok(Anchor {
txid: self.txid,
mpc_proof: lnpbp4_proof,
dbc_proof: self.dbc_proof,
_method: default!(),
})
}

Expand Down
2 changes: 1 addition & 1 deletion dbc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,4 @@ pub mod tapret;
mod proof;

pub use anchor::Anchor;
pub use proof::{Method, MethodParseError, Proof};
pub use proof::{DbcMethod, Method, MethodParseError, Proof};
2 changes: 1 addition & 1 deletion dbc/src/opret/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ pub struct OpretProof(());
impl StrictSerialize for OpretProof {}
impl StrictDeserialize for OpretProof {}

impl Proof for OpretProof {
impl Proof<Method> for OpretProof {
type Error = EmbedVerifyError<OpretError>;
const METHOD: Method = Method::OpretFirst;

Expand Down
19 changes: 17 additions & 2 deletions dbc/src/proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,19 @@ use strict_encoding::{StrictDecode, StrictDeserialize, StrictDumb, StrictEncode,

use crate::LIB_NAME_BPCORE;

/// Trait defining DBC method - or enumberation of allowed DBC methods used by
/// proofs, single-use-seals etc.
pub trait DbcMethod:
Copy
+ Eq
+ Ord
+ std::hash::Hash
+ strict_encoding::StrictDumb
+ strict_encoding::StrictEncode
+ strict_encoding::StrictDecode
{
}

/// wrong deterministic bitcoin commitment closing method id '{0}'.
#[derive(Clone, PartialEq, Eq, Debug, Display, Error, From)]
#[display(doc_comments)]
Expand Down Expand Up @@ -57,6 +70,8 @@ pub enum Method {
TapretFirst = 0x01,
}

impl DbcMethod for Method {}

impl FromStr for Method {
type Err = MethodParseError;

Expand All @@ -70,14 +85,14 @@ impl FromStr for Method {
}

/// Deterministic bitcoin commitment proof types.
pub trait Proof:
pub trait Proof<M: DbcMethod = Method>:
Clone + Eq + Debug + CommitEncode + StrictSerialize + StrictDeserialize + StrictDumb
{
/// Verification error.
type Error: Error;

/// Returns DBC method used by the proof.
const METHOD: Method;
const METHOD: M;

/// Verifies DBC proof against the provided transaction.
fn verify(&self, msg: &mpc::Commitment, tx: &Tx) -> Result<(), Self::Error>;
Expand Down
2 changes: 1 addition & 1 deletion dbc/src/tapret/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ impl TapretProof {
}
}

impl Proof for TapretProof {
impl Proof<Method> for TapretProof {
type Error = ConvolveVerifyError;
const METHOD: Method = Method::TapretFirst;

Expand Down
8 changes: 8 additions & 0 deletions seals/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,11 @@ extern crate serde_crate as serde;

pub mod resolver;
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 {}
93 changes: 93 additions & 0 deletions seals/src/secret.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Bitcoin protocol single-use-seals library.
//
// SPDX-License-Identifier: Apache-2.0
//
// Written in 2019-2023 by
// Dr Maxim Orlovsky <[email protected]>
//
// Copyright (C) 2019-2023 LNP/BP Standards Association. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::fmt::{self, Display, Formatter};
use std::str::FromStr;

use amplify::{Bytes32, Wrapper};
use baid58::{Baid58ParseError, Chunking, FromBaid58, ToBaid58, CHUNKING_32CHECKSUM};
use commit_verify::{CommitmentId, Conceal};

use crate::txout::{BlindSeal, SealTxid};

/// Confidential version of transaction outpoint-based single-use-seal
#[derive(Wrapper, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, From)]
#[wrapper(Index, RangeOps, BorrowSlice, Hex)]
#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
#[strict_type(lib = dbc::LIB_NAME_BPCORE)]
#[derive(CommitEncode)]
#[commit_encode(strategy = strict)]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
serde(crate = "serde_crate", transparent)
)]
pub struct SecretSeal(
#[from]
#[from([u8; 32])]
Bytes32,
);

impl<Id: SealTxid> Conceal for BlindSeal<Id> {
type Concealed = SecretSeal;

#[inline]
fn conceal(&self) -> Self::Concealed { self.commitment_id() }
}

impl ToBaid58<32> for SecretSeal {
const HRI: &'static str = "utxob";
const CHUNKING: Option<Chunking> = CHUNKING_32CHECKSUM;
fn to_baid58_payload(&self) -> [u8; 32] { self.0.into_inner() }
fn to_baid58_string(&self) -> String { self.to_string() }
}
impl FromBaid58<32> for SecretSeal {}
impl FromStr for SecretSeal {
type Err = Baid58ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
SecretSeal::from_baid58_maybe_chunked_str(s, ':', ' ')
}
}
impl Display for SecretSeal {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
if f.alternate() {
write!(f, "{::^}", self.to_baid58())
} else {
write!(f, "{::^.3}", self.to_baid58())
}
}
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn secret_seal_baid58() {
let baid58 = "utxob:2eFrirU-RjqLnqR74-AKRfdnc9M-DpvSRjmZG-mFPrw7nvu-Te1wy83";
let seal: SecretSeal = baid58.parse().unwrap();
assert_eq!(baid58, seal.to_string());
assert_eq!(baid58.replace('-', ""), format!("{seal:#}"));
assert_eq!(seal.to_string(), seal.to_baid58_string());
let reconstructed = SecretSeal::from_str(&baid58.replace('-', "")).unwrap();
assert_eq!(reconstructed, seal);
}
}
Loading

0 comments on commit 04e277b

Please sign in to comment.