Skip to content

Commit

Permalink
Merge branch 'dichotomies' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-orlovsky committed Oct 12, 2024
2 parents 81ab531 + 92902ce commit 08a8c95
Show file tree
Hide file tree
Showing 23 changed files with 2,090 additions and 986 deletions.
15 changes: 5 additions & 10 deletions Cargo.lock

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

7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,10 @@ wasm-bindgen-test = "0.3"

[package.metadata.docs.rs]
features = ["all"]

[patch.crates-io]
bp-consensus = { git = "https://github.com/BP-WG/bp-core", branch = "methods" }
bp-dbc = { git = "https://github.com/BP-WG/bp-core", branch = "methods" }
bp-seals = { git = "https://github.com/BP-WG/bp-core", branch = "methods" }
bp-core = { git = "https://github.com/BP-WG/bp-core", branch = "methods" }
rgb-core = { git = "https://github.com/RGB-WG/rgb-core", branch = "methods" }
274 changes: 256 additions & 18 deletions src/containers/anchors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,36 @@
// limitations under the License.

use std::cmp::Ordering;
use std::vec;

use amplify::ByteArray;
use bp::dbc::opret::OpretProof;
use bp::dbc::tapret::TapretProof;
use bp::dbc::{anchor, Anchor};
use bp::{Tx, Txid};
use bp::{dbc, Tx, Txid};
use commit_verify::mpc;
use rgb::validation::DbcProof;
use rgb::{BundleId, DiscloseHash, TransitionBundle, XChain, XWitnessId};
use rgb::validation::{DbcProof, EAnchor};
use rgb::{
BundleId, DiscloseHash, OpId, Operation, Transition, TransitionBundle, XChain, XGraphSeal,
XWitnessId,
};
use strict_encoding::StrictDumb;

use crate::{MergeReveal, MergeRevealError, LIB_NAME_RGB_STD};
use crate::containers::Dichotomy;
use crate::{MergeReveal, MergeRevealError, TypedAssignsExt, LIB_NAME_RGB_STD};

#[derive(Clone, Eq, PartialEq, Debug, Display, Error)]
#[display("state transition {0} is not a part of the bundle.")]
pub struct UnrelatedTransition(OpId, Transition);

#[derive(Copy, Clone, Eq, PartialEq, Debug, Display, Error)]
#[display(doc_comments)]
pub enum AnchoredBundleMismatch {
/// witness bundle for witness id {0} already has both opret and tapret information.
AlreadyDouble(XWitnessId),
/// the combined anchored bundles for witness id {0} are of the same type.
SameBundleType(XWitnessId),
}

#[derive(Clone, Eq, PartialEq, Debug)]
#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
Expand Down Expand Up @@ -159,36 +177,256 @@ impl PubWitness {
)]
#[derive(CommitEncode)]
#[commit_encode(strategy = strict, id = DiscloseHash)]
pub struct WitnessBundle<P: mpc::Proof + StrictDumb = mpc::MerkleProof> {
pub struct WitnessBundle {
pub pub_witness: XPubWitness,
pub anchor: Anchor<P, DbcProof>,
pub bundle: TransitionBundle,
pub anchored_bundles: AnchoredBundles,
}

impl<P: mpc::Proof + StrictDumb> PartialEq for WitnessBundle<P> {
impl PartialEq for WitnessBundle {
fn eq(&self, other: &Self) -> bool { self.pub_witness == other.pub_witness }
}

impl<P: mpc::Proof + StrictDumb> Ord for WitnessBundle<P> {
impl Ord for WitnessBundle {
fn cmp(&self, other: &Self) -> Ordering { self.pub_witness.cmp(&other.pub_witness) }
}

impl<P: mpc::Proof + StrictDumb> PartialOrd for WitnessBundle<P> {
impl PartialOrd for WitnessBundle {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(other)) }
}

impl WitnessBundle<mpc::MerkleProof> {
impl WitnessBundle {
#[inline]
pub fn with(pub_witness: XPubWitness, anchored_bundle: ClientBundle) -> Self {
Self {
pub_witness,
anchored_bundles: AnchoredBundles::from(anchored_bundle),
}
}

Check warning on line 204 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L199-L204

Added lines #L199 - L204 were not covered by tests

pub fn into_double(mut self, other: ClientBundle) -> Result<Self, AnchoredBundleMismatch> {
match (self.anchored_bundles, other.dbc_proof) {

Check warning on line 207 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L206-L207

Added lines #L206 - L207 were not covered by tests
(AnchoredBundles::Double { .. }, _) => {
return Err(AnchoredBundleMismatch::AlreadyDouble(
self.pub_witness.to_witness_id(),
));

Check warning on line 211 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L209-L211

Added lines #L209 - L211 were not covered by tests
}
(AnchoredBundles::Opret(opret), DbcProof::Tapret(tapret)) => {
self.anchored_bundles = AnchoredBundles::Double {
tapret: ClientBundle::new(other.mpc_proof, tapret, other.bundle),
opret,
}

Check warning on line 217 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L213-L217

Added lines #L213 - L217 were not covered by tests
}
(AnchoredBundles::Tapret(tapret), DbcProof::Opret(opret)) => {
self.anchored_bundles = AnchoredBundles::Double {
opret: ClientBundle::new(other.mpc_proof, opret, other.bundle),
tapret,
}

Check warning on line 223 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L219-L223

Added lines #L219 - L223 were not covered by tests
}
_ => {
return Err(AnchoredBundleMismatch::SameBundleType(
self.pub_witness.to_witness_id(),
));

Check warning on line 228 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L226-L228

Added lines #L226 - L228 were not covered by tests
}
}
Ok(self)
}

Check warning on line 232 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L231-L232

Added lines #L231 - L232 were not covered by tests

pub fn witness_id(&self) -> XWitnessId { self.pub_witness.to_witness_id() }

pub fn reveal_seal(&mut self, bundle_id: BundleId, seal: XGraphSeal) -> bool {
let bundle = match &mut self.anchored_bundles {
AnchoredBundles::Tapret(tapret) | AnchoredBundles::Double { tapret, .. }
if tapret.bundle.bundle_id() == bundle_id =>

Check warning on line 239 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L236-L239

Added lines #L236 - L239 were not covered by tests
{
Some(&mut tapret.bundle)

Check warning on line 241 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L241

Added line #L241 was not covered by tests
}
AnchoredBundles::Opret(opret) | AnchoredBundles::Double { opret, .. }
if opret.bundle.bundle_id() == bundle_id =>

Check warning on line 244 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L243-L244

Added lines #L243 - L244 were not covered by tests
{
Some(&mut opret.bundle)

Check warning on line 246 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L246

Added line #L246 was not covered by tests
}
_ => None,

Check warning on line 248 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L248

Added line #L248 was not covered by tests
};
let Some(bundle) = bundle else {
return false;

Check warning on line 251 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L250-L251

Added lines #L250 - L251 were not covered by tests
};
bundle
.known_transitions
.values_mut()
.flat_map(|t| t.assignments.values_mut())
.for_each(|a| a.reveal_seal(seal));

true
}

Check warning on line 260 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L253-L260

Added lines #L253 - L260 were not covered by tests

pub fn anchored_bundles(&self) -> impl Iterator<Item = (EAnchor, &TransitionBundle)> {
self.anchored_bundles.iter()
}

Check warning on line 264 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L262-L264

Added lines #L262 - L264 were not covered by tests

#[inline]
pub fn known_transitions(&self) -> impl Iterator<Item = &Transition> {
self.anchored_bundles
.bundles()
.flat_map(|bundle| bundle.known_transitions.values())
}

Check warning on line 271 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L267-L271

Added lines #L267 - L271 were not covered by tests
}

impl WitnessBundle {
pub fn merge_reveal(mut self, other: Self) -> Result<Self, MergeRevealError> {
self.pub_witness = self.pub_witness.merge_reveal(other.pub_witness)?;
if self.anchor != other.anchor {
return Err(MergeRevealError::AnchorsNonEqual(self.bundle.bundle_id()));
/// Keeps client-side data - a combination of client-side witness (anchor) and state (transition
/// bundle). Ensures that transition bundle uses the same DBC close method as used by the
/// client-side witness (anchor).
#[derive(Clone, PartialEq, Eq, Debug)]
#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)]
#[strict_type(lib = LIB_NAME_RGB_STD)]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),

Check warning on line 282 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L282

Added line #L282 was not covered by tests
serde(crate = "serde_crate", rename_all = "camelCase")
)]
pub struct ClientBundle<D: dbc::Proof = DbcProof> {
mpc_proof: mpc::MerkleProof,
dbc_proof: D,
bundle: TransitionBundle,
}

impl<D: dbc::Proof> ClientBundle<D> {
/// # Panics
///
/// Panics if DBC proof and bundle have different closing methods
pub fn new(mpc_proof: mpc::MerkleProof, dbc_proof: D, bundle: TransitionBundle) -> Self {
assert_eq!(dbc_proof.method(), bundle.close_method);
Self {
mpc_proof,
dbc_proof,
bundle,

Check warning on line 300 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L295-L300

Added lines #L295 - L300 were not covered by tests
}
self.bundle = self.bundle.merge_reveal(other.bundle)?;
Ok(self)
}

Check warning on line 302 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L302

Added line #L302 was not covered by tests

#[inline]
pub fn bundle_id(&self) -> BundleId { self.bundle.bundle_id() }

Check warning on line 305 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L305

Added line #L305 was not covered by tests

pub fn reveal_transition(
&mut self,
transition: Transition,
) -> Result<bool, UnrelatedTransition> {
let opid = transition.id();
if self.bundle.input_map.values().all(|id| *id != opid) {
return Err(UnrelatedTransition(opid, transition));
}
if self.bundle.known_transitions.contains_key(&opid) {
return Ok(false);
}
self.bundle
.known_transitions
.insert(opid, transition)
.expect("same size as input map");
Ok(true)
}

Check warning on line 323 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L307-L323

Added lines #L307 - L323 were not covered by tests
}

#[derive(Clone, PartialEq, Eq, Debug)]
#[derive(StrictType, StrictEncode, StrictDecode)]
#[strict_type(lib = LIB_NAME_RGB_STD, tags = custom)]
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),

Check warning on line 331 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L331

Added line #L331 was not covered by tests
serde(crate = "serde_crate", rename_all = "camelCase")
)]
pub enum AnchoredBundles {
#[strict_type(tag = 0x01)]
Tapret(ClientBundle<TapretProof>),
#[strict_type(tag = 0x02)]
Opret(ClientBundle<OpretProof>),
#[strict_type(tag = 0x03)]
Double {
tapret: ClientBundle<TapretProof>,
opret: ClientBundle<OpretProof>,
},
}

impl StrictDumb for AnchoredBundles {
fn strict_dumb() -> Self { Self::Opret(strict_dumb!()) }
}

impl From<ClientBundle> for AnchoredBundles {
fn from(ab: ClientBundle) -> Self {
match ab.dbc_proof {
DbcProof::Opret(proof) => {
Self::Opret(ClientBundle::<OpretProof>::new(ab.mpc_proof, proof, ab.bundle))

Check warning on line 354 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L351-L354

Added lines #L351 - L354 were not covered by tests
}
DbcProof::Tapret(proof) => {
Self::Tapret(ClientBundle::<TapretProof>::new(ab.mpc_proof, proof, ab.bundle))

Check warning on line 357 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L356-L357

Added lines #L356 - L357 were not covered by tests
}
}
}

Check warning on line 360 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L360

Added line #L360 was not covered by tests
}

impl AnchoredBundles {
pub fn bundles(&self) -> impl Iterator<Item = &TransitionBundle> {
match self {
AnchoredBundles::Tapret(tapret) => Dichotomy::single(&tapret.bundle),
AnchoredBundles::Opret(opret) => Dichotomy::single(&opret.bundle),
AnchoredBundles::Double { tapret, opret } => {
Dichotomy::double(&tapret.bundle, &opret.bundle)

Check warning on line 369 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L364-L369

Added lines #L364 - L369 were not covered by tests
}
}
.into_iter()
}

Check warning on line 373 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L372-L373

Added lines #L372 - L373 were not covered by tests

pub fn into_bundles(self) -> impl Iterator<Item = TransitionBundle> {
match self {
AnchoredBundles::Tapret(tapret) => Dichotomy::single(tapret.bundle),
AnchoredBundles::Opret(opret) => Dichotomy::single(opret.bundle),
AnchoredBundles::Double { tapret, opret } => {
Dichotomy::double(tapret.bundle, opret.bundle)

Check warning on line 380 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L375-L380

Added lines #L375 - L380 were not covered by tests
}
}
.into_iter()
}

Check warning on line 384 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L383-L384

Added lines #L383 - L384 were not covered by tests

pub fn iter(&self) -> impl Iterator<Item = (EAnchor, &TransitionBundle)> {
match self {
AnchoredBundles::Tapret(tapret) => {
let anchor =
EAnchor::new(tapret.mpc_proof.clone(), tapret.dbc_proof.clone().into());
Dichotomy::single((anchor, &tapret.bundle))

Check warning on line 391 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L386-L391

Added lines #L386 - L391 were not covered by tests
}
AnchoredBundles::Opret(opret) => {
let anchor = EAnchor::new(opret.mpc_proof.clone(), opret.dbc_proof.clone().into());
Dichotomy::single((anchor, &opret.bundle))

Check warning on line 395 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L393-L395

Added lines #L393 - L395 were not covered by tests
}
AnchoredBundles::Double { tapret, opret } => {
let tapret_anchor =
EAnchor::new(tapret.mpc_proof.clone(), tapret.dbc_proof.clone().into());
let opret_anchor =
EAnchor::new(opret.mpc_proof.clone(), opret.dbc_proof.clone().into());
Dichotomy::double((tapret_anchor, &tapret.bundle), (opret_anchor, &opret.bundle))

Check warning on line 402 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L397-L402

Added lines #L397 - L402 were not covered by tests
}
}
.into_iter()
}

Check warning on line 406 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L405-L406

Added lines #L405 - L406 were not covered by tests
}

impl IntoIterator for AnchoredBundles {
type Item = (EAnchor, TransitionBundle);
type IntoIter = vec::IntoIter<(EAnchor, TransitionBundle)>;

fn into_iter(self) -> Self::IntoIter {
match self {
AnchoredBundles::Tapret(tapret) => {
let anchor = EAnchor::new(tapret.mpc_proof, tapret.dbc_proof.into());
Dichotomy::single((anchor, tapret.bundle))

Check warning on line 417 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L413-L417

Added lines #L413 - L417 were not covered by tests
}
AnchoredBundles::Opret(opret) => {
let anchor = EAnchor::new(opret.mpc_proof, opret.dbc_proof.into());
Dichotomy::single((anchor, opret.bundle))

Check warning on line 421 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L419-L421

Added lines #L419 - L421 were not covered by tests
}
AnchoredBundles::Double { tapret, opret } => {
let tapret_anchor = EAnchor::new(tapret.mpc_proof, tapret.dbc_proof.into());
let opret_anchor = EAnchor::new(opret.mpc_proof, opret.dbc_proof.into());
Dichotomy::double((tapret_anchor, tapret.bundle), (opret_anchor, opret.bundle))

Check warning on line 426 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L423-L426

Added lines #L423 - L426 were not covered by tests
}
}
.into_iter()

Check warning on line 429 in src/containers/anchors.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/anchors.rs#L429

Added line #L429 was not covered by tests
}
}

Expand Down
7 changes: 2 additions & 5 deletions src/containers/consignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ use super::{
use crate::interface::{Iface, IfaceImpl};
use crate::persistence::{MemContract, MemContractState};
use crate::resolvers::ConsignmentResolver;
use crate::{BundleExt, SecretSeal, LIB_NAME_RGB_STD};
use crate::{SecretSeal, LIB_NAME_RGB_STD};

pub type Transfer = Consignment<true>;
pub type Contract = Consignment<false>;
Expand Down Expand Up @@ -296,10 +296,7 @@ impl<const TRANSFER: bool> Consignment<TRANSFER> {
for mut witness_bundle in self.bundles {
for (bundle_id, secret) in &self.terminals {
if let Some(seal) = f(*secret)? {
if witness_bundle.bundle.bundle_id() == *bundle_id {
witness_bundle.bundle.reveal_seal(seal);
break;
}
witness_bundle.reveal_seal(*bundle_id, seal);

Check warning on line 299 in src/containers/consignment.rs

View check run for this annotation

Codecov / codecov/patch

src/containers/consignment.rs#L299

Added line #L299 was not covered by tests
}
}
bundles.push(witness_bundle).ok();
Expand Down
Loading

0 comments on commit 08a8c95

Please sign in to comment.