From f5a1a0e7f114670f3d224255c9d6651dbe737ede Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 30 Dec 2023 00:14:11 +0100 Subject: [PATCH 01/11] epic: update secret seals to be cross-chain --- Cargo.lock | 51 +++++-------- Cargo.toml | 4 + invoice/src/invoice.rs | 4 +- invoice/src/parse.rs | 32 ++++---- src/accessors/assignments.rs | 12 +-- src/accessors/bundle.rs | 6 +- src/containers/consignment.rs | 7 +- src/containers/indexed.rs | 32 +++++--- src/containers/mod.rs | 2 +- src/containers/partials.rs | 21 ++++-- src/containers/seal.rs | 106 ++++---------------------- src/containers/transfer.rs | 11 ++- src/containers/util.rs | 48 +----------- src/containers/validate.rs | 4 +- src/interface/builder.rs | 2 + src/interface/contract.rs | 44 +++++------ src/persistence/hoard.rs | 7 +- src/persistence/inventory.rs | 135 +++++++++++++++++++--------------- src/persistence/stock.rs | 42 +++++++---- src/stl/stl.rs | 2 +- stl/RGBStd@0.1.0.sty | 10 +-- 21 files changed, 248 insertions(+), 334 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 99d557ab..c75820af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -218,20 +218,7 @@ dependencies = [ [[package]] name = "bp-consensus" version = "0.11.0-beta.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190ac89a2a3c79d5bfb677f48e5393691832c540973341831572edaffdce0881" -dependencies = [ - "amplify", - "chrono", - "commit_verify", - "secp256k1 0.28.0", - "strict_encoding", -] - -[[package]] -name = "bp-consensus" -version = "0.11.0-beta.3" -source = "git+https://github.com/BP-WG/bp-core?branch=v0.11#50630d40828c522f78066c6ca473f0f3291b977d" +source = "git+https://github.com/BP-WG/bp-core?branch=v0.11#cbc896d075772a7b4eb620cd8c76cae86ff331c1" dependencies = [ "amplify", "chrono", @@ -245,10 +232,10 @@ dependencies = [ [[package]] name = "bp-core" version = "0.11.0-beta.2" -source = "git+https://github.com/BP-WG/bp-core?branch=v0.11#50630d40828c522f78066c6ca473f0f3291b977d" +source = "git+https://github.com/BP-WG/bp-core?branch=v0.11#cbc896d075772a7b4eb620cd8c76cae86ff331c1" dependencies = [ "amplify", - "bp-consensus 0.11.0-beta.3 (git+https://github.com/BP-WG/bp-core?branch=v0.11)", + "bp-consensus", "bp-dbc", "bp-seals", "commit_verify", @@ -261,11 +248,11 @@ dependencies = [ [[package]] name = "bp-dbc" version = "0.11.0-beta.2" -source = "git+https://github.com/BP-WG/bp-core?branch=v0.11#50630d40828c522f78066c6ca473f0f3291b977d" +source = "git+https://github.com/BP-WG/bp-core?branch=v0.11#cbc896d075772a7b4eb620cd8c76cae86ff331c1" dependencies = [ "amplify", "base85", - "bp-consensus 0.11.0-beta.3 (git+https://github.com/BP-WG/bp-core?branch=v0.11)", + "bp-consensus", "commit_verify", "secp256k1 0.28.0", "serde", @@ -281,17 +268,17 @@ dependencies = [ "amplify", "bech32", "bitcoin_hashes", - "bp-consensus 0.11.0-beta.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bp-consensus", ] [[package]] name = "bp-seals" version = "0.11.0-beta.2" -source = "git+https://github.com/BP-WG/bp-core?branch=v0.11#50630d40828c522f78066c6ca473f0f3291b977d" +source = "git+https://github.com/BP-WG/bp-core?branch=v0.11#cbc896d075772a7b4eb620cd8c76cae86ff331c1" dependencies = [ "amplify", "baid58", - "bp-consensus 0.11.0-beta.3 (git+https://github.com/BP-WG/bp-core?branch=v0.11)", + "bp-consensus", "bp-dbc", "commit_verify", "rand", @@ -344,8 +331,7 @@ dependencies = [ [[package]] name = "commit_encoding_derive" version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00033f14d67c4169d588f085ea2faeb7b610cf03a74d42ea09eeba31abef2047" +source = "git+https://github.com/LNP-BP/client_side_validation?branch=v0.11#2d3a0a2981409c493067edfc94338088884b1aa7" dependencies = [ "amplify", "amplify_syn", @@ -357,8 +343,7 @@ dependencies = [ [[package]] name = "commit_verify" version = "0.11.0-beta.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5598661b1d90b149f0b944faef8c1d1d131f847678a6c450b9540b629ac11291" +source = "git+https://github.com/LNP-BP/client_side_validation?branch=v0.11#2d3a0a2981409c493067edfc94338088884b1aa7" dependencies = [ "amplify", "commit_encoding_derive", @@ -560,9 +545,9 @@ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "mime" @@ -664,7 +649,7 @@ dependencies = [ [[package]] name = "rgb-core" version = "0.11.0-beta.3" -source = "git+https://github.com/RGB-WG/rgb-core?branch=v0.11#7eb443b87745d2a05030f556d8a33ba8dbed0f0a" +source = "git+https://github.com/RGB-WG/rgb-core?branch=v0.11#50cd4191f2b92a86e8d79b1a2d15aa94bd50c367" dependencies = [ "aluvm", "amplify", @@ -898,8 +883,7 @@ dependencies = [ [[package]] name = "strict_encoding" version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab7b75b4af0aff9dd97b68df262bf0e807b7d007cc860fa217943f898a05a5ab" +source = "git+https://github.com/strict-types/strict-encoding?branch=phantom#2123237a512bbe28e8e419e7d4f899dfedfa758c" dependencies = [ "amplify", "half", @@ -910,8 +894,7 @@ dependencies = [ [[package]] name = "strict_encoding_derive" version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37064ec285e2a633465eb525c8698eea51373dee889fe310e0d32df8343e7f4f" +source = "git+https://github.com/strict-types/strict-encoding?branch=phantom#2123237a512bbe28e8e419e7d4f899dfedfa758c" dependencies = [ "amplify_syn", "heck", @@ -1224,9 +1207,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.5.30" +version = "0.5.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b5c3db89721d50d0e2a673f5043fc4722f76dcc352d7b1ab8b8288bed4ed2c5" +checksum = "97a4882e6b134d6c28953a387571f1acdd3496830d5e36c5e3a1075580ea641c" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 15203284..1b04e577 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,6 +64,7 @@ base85 = "=2.0.0" chrono = "0.4.31" indexmap = { workspace = true } serde_crate = { workspace = true, optional = true } +rand = "0.8.5" [features] default = [] @@ -92,6 +93,9 @@ wasm-bindgen-test = "0.3" features = [ "all" ] [patch.crates-io] +strict_encoding = { git = "https://github.com/strict-types/strict-encoding", branch = "phantom" } +commit_verify = { git = "https://github.com/LNP-BP/client_side_validation", branch = "v0.11" } +bp-consensus = { git = "https://github.com/BP-WG/bp-core", branch = "v0.11" } bp-dbc = { git = "https://github.com/BP-WG/bp-core", branch = "v0.11" } bp-seals = { git = "https://github.com/BP-WG/bp-core", branch = "v0.11" } bp-core = { git = "https://github.com/BP-WG/bp-core", branch = "v0.11" } diff --git a/invoice/src/invoice.rs b/invoice/src/invoice.rs index 14d15684..fd64165e 100644 --- a/invoice/src/invoice.rs +++ b/invoice/src/invoice.rs @@ -21,7 +21,7 @@ use indexmap::IndexMap; use invoice::{Address, Network}; -use rgb::{AttachId, ContractId, Layer1, SecretSeal}; +use rgb::{AttachId, ContractId, Layer1, SecretSeal, XChain}; use strict_encoding::{FieldName, TypeName}; #[derive(Clone, Eq, PartialEq, Hash, Debug)] @@ -52,7 +52,7 @@ pub enum Beneficiary { // Move Baid58 encoding from BP seals to here. Use utxob1 for bitcoin, and use // utxol1 for liquid. #[from] - BlindedSeal(SecretSeal), + BlindedSeal(XChain), #[from] WitnessVoutBitcoin(Address), // TODO: Add support for Liquid beneficiaries diff --git a/invoice/src/parse.rs b/invoice/src/parse.rs index 02a3e48b..295f5ada 100644 --- a/invoice/src/parse.rs +++ b/invoice/src/parse.rs @@ -28,7 +28,7 @@ use fluent_uri::Uri; use indexmap::IndexMap; use invoice::{Address, AddressNetwork, Network, UnknownNetwork}; use percent_encoding::{utf8_percent_encode, AsciiSet, CONTROLS}; -use rgb::{ContractId, SecretSeal}; +use rgb::{ContractId, SecretSeal, XChain}; use strict_encoding::{InvalidIdent, TypeName}; use super::{Beneficiary, InvoiceState, RgbInvoice, RgbTransport}; @@ -304,20 +304,22 @@ impl FromStr for RgbInvoice { _ => unreachable!(), }; - let beneficiary = - match (SecretSeal::from_str(beneficiary_str), Address::from_str(beneficiary_str)) { - (Ok(seal), Err(_)) => Beneficiary::BlindedSeal(seal), - (Err(_), Ok(addr)) => { - address_network = Some(addr.network); - Beneficiary::WitnessVoutBitcoin(addr) - } - (Err(_), Err(_)) => { - return Err(InvoiceParseError::Beneficiary(beneficiary_str.to_owned())); - } - (Ok(_), Ok(_)) => { - panic!("found a string which is both valid bitcoin address and UTXO blind seal") - } - }; + let beneficiary = match ( + XChain::::from_str(beneficiary_str), + Address::from_str(beneficiary_str), + ) { + (Ok(seal), Err(_)) => Beneficiary::BlindedSeal(seal), + (Err(_), Ok(addr)) => { + address_network = Some(addr.network); + Beneficiary::WitnessVoutBitcoin(addr) + } + (Err(_), Err(_)) => { + return Err(InvoiceParseError::Beneficiary(beneficiary_str.to_owned())); + } + (Ok(_), Ok(_)) => { + panic!("found a string which is both valid bitcoin address and UTXO blind seal") + } + }; let mut query_params = map_query_params(&uri)?; diff --git a/src/accessors/assignments.rs b/src/accessors/assignments.rs index 08ca488b..3c813df3 100644 --- a/src/accessors/assignments.rs +++ b/src/accessors/assignments.rs @@ -23,20 +23,20 @@ use amplify::confinement::SmallVec; use commit_verify::Conceal; use rgb::{ Assign, AssignAttach, AssignData, AssignFungible, AssignRights, ExposedSeal, ExposedState, - TypedAssigns, XSeal, + TypedAssigns, XChain, }; pub trait TypedAssignsExt { - fn reveal_seal(&mut self, seal: XSeal); + fn reveal_seal(&mut self, seal: XChain); - fn filter_revealed_seals(&self) -> Vec>; + fn filter_revealed_seals(&self) -> Vec>; } impl TypedAssignsExt for TypedAssigns { - fn reveal_seal(&mut self, seal: XSeal) { + fn reveal_seal(&mut self, seal: XChain) { fn reveal( vec: &mut SmallVec>, - revealed: XSeal, + revealed: XChain, ) { for assign in vec.iter_mut() { match assign { @@ -65,7 +65,7 @@ impl TypedAssignsExt for TypedAssigns { } } - fn filter_revealed_seals(&self) -> Vec> { + fn filter_revealed_seals(&self) -> Vec> { match self { TypedAssigns::Declarative(s) => { s.iter().filter_map(AssignRights::revealed_seal).collect() diff --git a/src/accessors/bundle.rs b/src/accessors/bundle.rs index 3318598f..980500b8 100644 --- a/src/accessors/bundle.rs +++ b/src/accessors/bundle.rs @@ -19,7 +19,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use rgb::{GraphSeal, OpId, Operation, Transition, TransitionBundle, XSeal}; +use rgb::{GraphSeal, OpId, Operation, Transition, TransitionBundle, XChain}; use crate::accessors::TypedAssignsExt; @@ -32,7 +32,7 @@ pub enum RevealError { pub trait BundleExt { /// Ensures that the seal is revealed inside the bundle. - fn reveal_seal(&mut self, seal: XSeal); + fn reveal_seal(&mut self, seal: XChain); /// Ensures that the transition is revealed inside the bundle. /// @@ -44,7 +44,7 @@ pub trait BundleExt { } impl BundleExt for TransitionBundle { - fn reveal_seal(&mut self, seal: XSeal) { + fn reveal_seal(&mut self, seal: XChain) { for (_, transition) in self.known_transitions.keyed_values_mut() { for (_, assign) in transition.assignments.keyed_values_mut() { assign.reveal_seal(seal) diff --git a/src/containers/consignment.rs b/src/containers/consignment.rs index a0965e1d..46ac4639 100644 --- a/src/containers/consignment.rs +++ b/src/containers/consignment.rs @@ -26,7 +26,8 @@ use amplify::confinement::{LargeVec, MediumBlob, SmallOrdMap, TinyOrdMap, TinyOr use rgb::validation::{self}; use rgb::{ AnchoredBundle, AssetTag, AssignmentType, AttachId, BundleId, ContractHistory, ContractId, - Extension, Genesis, GraphSeal, OpId, Operation, Schema, SchemaId, SubSchema, Transition, XSeal, + Extension, Genesis, GraphSeal, OpId, Operation, Schema, SchemaId, SubSchema, Transition, + XChain, }; use strict_encoding::{StrictDeserialize, StrictDumb, StrictSerialize}; @@ -89,7 +90,7 @@ pub struct Consignment { pub genesis: Genesis, /// Set of seals which are history terminals. - pub terminals: SmallOrdMap, + pub terminals: SmallOrdMap>, /// Data on all anchored state transitions contained in the consignments. pub bundles: LargeVec, @@ -226,7 +227,7 @@ impl Consignment { Ok(history) } - pub fn reveal_bundle_seal(&mut self, bundle_id: BundleId, revealed: XSeal) { + pub fn reveal_bundle_seal(&mut self, bundle_id: BundleId, revealed: XChain) { for anchored_bundle in &mut self.bundles { if anchored_bundle.bundle.bundle_id() == bundle_id { anchored_bundle.bundle.reveal_seal(revealed); diff --git a/src/containers/indexed.rs b/src/containers/indexed.rs index eeafe38a..68ae147c 100644 --- a/src/containers/indexed.rs +++ b/src/containers/indexed.rs @@ -24,11 +24,12 @@ use std::ops::Deref; use std::rc::Rc; use std::vec; +use amplify::confinement::Collection; use commit_verify::Conceal; use rgb::validation::ConsignmentApi; use rgb::{ AnchoredBundle, AssetTag, AssignmentType, BundleId, Genesis, OpId, OpRef, Operation, SubSchema, - WitnessId, + WitnessId, XChain, }; use super::Consignment; @@ -52,7 +53,7 @@ impl<'c, const TYPE: bool> IndexedConsignment<'c, TYPE> { let mut op_witness_ids = BTreeMap::new(); for ab in &consignment.bundles { for opid in ab.bundle.known_transitions.keys() { - op_witness_ids.insert(*opid, ab.anchor.witness_id()); + op_witness_ids.insert(*opid, ab.anchor.witness_id_unchecked()); } } Self { @@ -81,16 +82,23 @@ impl<'c, const TYPE: bool> ConsignmentApi for IndexedConsignment<'c, TYPE> { fn genesis(&self) -> &Genesis { &self.genesis } - fn terminals(&self) -> BTreeSet<(BundleId, SecretSeal)> { - self.terminals - .iter() - .flat_map(|(bundle_id, terminal)| { - terminal - .seals - .iter() - .map(|seal| (*bundle_id, seal.conceal())) - }) - .collect() + fn terminals(&self) -> BTreeSet<(BundleId, XChain)> { + let mut set = BTreeSet::new(); + for (bundle_id, terminal) in &self.terminals { + match terminal { + XChain::Bitcoin(term) => { + for seal in &term.seals { + set.push((*bundle_id, XChain::Bitcoin(seal.conceal()))); + } + } + XChain::Liquid(term) => { + for seal in &term.seals { + set.push((*bundle_id, XChain::Liquid(seal.conceal()))); + } + } + } + } + set } fn bundle_ids<'a>(&self) -> Self::Iter<'a> { BundleIdIter(self.bundles.clone().into_iter()) } diff --git a/src/containers/mod.rs b/src/containers/mod.rs index eea20c8e..057daffc 100644 --- a/src/containers/mod.rs +++ b/src/containers/mod.rs @@ -46,4 +46,4 @@ pub use disclosure::Disclosure; pub use indexed::IndexedConsignment; pub use partials::{Batch, CloseMethodSet, Fascia, TransitionInfo}; pub use seal::{BuilderSeal, TerminalSeal, VoutSeal}; -pub use util::{ContainerVer, Terminal, XchainOutpoint}; +pub use util::{ContainerVer, Terminal, XOutpoint}; diff --git a/src/containers/partials.rs b/src/containers/partials.rs index 354e2726..96363219 100644 --- a/src/containers/partials.rs +++ b/src/containers/partials.rs @@ -28,11 +28,14 @@ use std::vec; use amplify::confinement; use amplify::confinement::{Confined, U24}; use bp::seals::txout::CloseMethod; +use bp::Outpoint; use commit_verify::mpc; -use rgb::{ContractId, OpId, Operation, OutputSeal, Transition, TransitionBundle, XAnchor}; +use rgb::{ + ContractId, OpId, Operation, Transition, TransitionBundle, TxoSeal, XAnchor, XOutputSeal, +}; use strict_encoding::{StrictDeserialize, StrictDumb, StrictSerialize}; -use crate::containers::XchainOutpoint; +use crate::containers::XOutpoint; use crate::LIB_NAME_RGB_STD; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] @@ -92,8 +95,8 @@ impl BitOrAssign for CloseMethodSet { fn bitor_assign(&mut self, rhs: Self) { *self = self.bitor(rhs); } } -impl From for CloseMethodSet { - fn from(seal: OutputSeal) -> Self { seal.method().into() } +impl From for CloseMethodSet { + fn from(seal: XOutputSeal) -> Self { seal.method().into() } } impl From for CloseMethodSet { @@ -120,7 +123,7 @@ impl CloseMethodSet { )] pub struct TransitionInfo { pub id: OpId, - pub inputs: Confined, 1, U24>, + pub inputs: Confined, 1, U24>, pub transition: Transition, pub methods: CloseMethodSet, } @@ -148,10 +151,14 @@ impl Hash for TransitionInfo { impl TransitionInfo { pub fn new( transition: Transition, - seals: impl AsRef<[OutputSeal]>, + seals: impl AsRef<[XOutputSeal]>, ) -> Result { let inputs = Confined::, 1, U24>::try_from_iter( - seals.as_ref().iter().copied().map(XchainOutpoint::from), + seals + .as_ref() + .iter() + .copied() + .map(|seal| seal.map(Outpoint::from)), )?; let methods = seals .as_ref() diff --git a/src/containers/seal.rs b/src/containers/seal.rs index ee7f5edd..6839c6b8 100644 --- a/src/containers/seal.rs +++ b/src/containers/seal.rs @@ -21,15 +21,11 @@ #![doc = include_str!("seals.md")] -use std::fmt::{self, Display, Formatter}; -use std::str::FromStr; - -use bp::seals::txout::blind::ParseError; -use bp::seals::txout::{CloseMethod, TxPtr}; +use bp::seals::txout::CloseMethod; use bp::secp256k1::rand::{thread_rng, RngCore}; -use bp::{Outpoint, Vout}; +use bp::Vout; use commit_verify::Conceal; -use rgb::{ExposedSeal, GenesisSeal, GraphSeal, SecretSeal, XSeal}; +use rgb::{GraphSeal, SecretSeal, TxoSeal, XChain}; use crate::LIB_NAME_RGB_STD; @@ -107,7 +103,9 @@ impl VoutSeal { } impl From for GraphSeal { - fn from(seal: VoutSeal) -> Self { Self::with_vout(seal.method, seal.vout, seal.blinding) } + fn from(seal: VoutSeal) -> Self { + Self::with_blinded_vout(seal.method, seal.vout, seal.blinding) + } } /// Seal endpoint is a confidential seal which may be linked to the witness @@ -135,66 +133,22 @@ pub enum TerminalSeal { ConcealedUtxo(SecretSeal), /// Seal contained within the witness transaction + #[from] #[strict_type(tag = 1)] - BitcoinWitnessVout(VoutSeal), - - /// Seal contained within the witness transaction - #[strict_type(tag = 2)] - LiquidWitnessVout(VoutSeal), -} - -impl From for TerminalSeal { - fn from(seal: GraphSeal) -> Self { - match seal.txid { - TxPtr::WitnessTx => TerminalSeal::BitcoinWitnessVout(VoutSeal::with( - seal.method, - seal.vout, - seal.blinding, - )), - TxPtr::Txid(_) => TerminalSeal::ConcealedUtxo(seal.conceal()), - } - } -} - -impl From> for TerminalSeal { - fn from(seal: XSeal) -> Self { - match seal { - XSeal::Bitcoin( - seal @ GraphSeal { - txid: TxPtr::WitnessTx, - .. - }, - ) => TerminalSeal::BitcoinWitnessVout(VoutSeal::with( - seal.method, - seal.vout, - seal.blinding, - )), - XSeal::Liquid( - seal @ GraphSeal { - txid: TxPtr::WitnessTx, - .. - }, - ) => TerminalSeal::LiquidWitnessVout(VoutSeal::with( - seal.method, - seal.vout, - seal.blinding, - )), - _ => TerminalSeal::ConcealedUtxo(seal.conceal()), - } - } + WitnessVout(VoutSeal), } impl TerminalSeal { /// Constructs [`TerminalSeal`] for the witness transaction. Uses /// `thread_rng` to initialize blinding factor. pub fn new_vout(method: CloseMethod, vout: impl Into) -> TerminalSeal { - TerminalSeal::BitcoinWitnessVout(VoutSeal::new(method, vout)) + TerminalSeal::WitnessVout(VoutSeal::new(method, vout)) } pub fn secret_seal(&self) -> Option { match self { TerminalSeal::ConcealedUtxo(seal) => Some(*seal), - TerminalSeal::BitcoinWitnessVout(_) | TerminalSeal::LiquidWitnessVout(_) => None, + TerminalSeal::WitnessVout(_) => None, } } } @@ -205,47 +159,15 @@ impl Conceal for TerminalSeal { fn conceal(&self) -> Self::Concealed { match *self { TerminalSeal::ConcealedUtxo(hash) => hash, - TerminalSeal::BitcoinWitnessVout(seal) => { - XSeal::Bitcoin(GraphSeal::from(seal)).conceal() - } - TerminalSeal::LiquidWitnessVout(seal) => XSeal::Liquid(GraphSeal::from(seal)).conceal(), + TerminalSeal::WitnessVout(seal) => GraphSeal::from(seal).conceal(), } } } -impl Display for TerminalSeal { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match *self { - TerminalSeal::ConcealedUtxo(ref seal) => Display::fmt(seal, f), - TerminalSeal::BitcoinWitnessVout(seal) => Display::fmt(&GraphSeal::from(seal), f), - TerminalSeal::LiquidWitnessVout(seal) => Display::fmt(&GraphSeal::from(seal), f), - } - } -} - -impl FromStr for TerminalSeal { - type Err = ParseError; - - fn from_str(s: &str) -> Result { - SecretSeal::from_str(s) - .map(TerminalSeal::from) - .or_else(|_| GraphSeal::from_str(s).map(TerminalSeal::from)) - } -} - /// Seal used by operation builder which can be either revealed or concealed. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, From)] -pub enum BuilderSeal { - #[from] - Revealed(XSeal), +pub enum BuilderSeal { + Revealed(XChain), #[from] - Concealed(SecretSeal), -} - -impl From for BuilderSeal { - fn from(outpoint: Outpoint) -> Self { BuilderSeal::Revealed(XSeal::Bitcoin(outpoint.into())) } -} - -impl From for BuilderSeal { - fn from(outpoint: Outpoint) -> Self { BuilderSeal::Revealed(XSeal::Bitcoin(outpoint.into())) } + Concealed(XChain), } diff --git a/src/containers/transfer.rs b/src/containers/transfer.rs index 7f1283e7..35ef4a02 100644 --- a/src/containers/transfer.rs +++ b/src/containers/transfer.rs @@ -73,9 +73,14 @@ impl CommitEncode for Transfer { writer = self.contract_id().strict_encode(writer)?; for (bundle_id, terminal) in &self.terminals { writer = bundle_id.strict_encode(writer)?; - let seals = - SmallOrdSet::try_from_iter(terminal.seals.iter().map(TerminalSeal::conceal)) - .expect("same size iterator"); + let seals = SmallOrdSet::try_from_iter( + terminal + .as_reduced_unsafe() + .seals + .iter() + .map(TerminalSeal::conceal), + ) + .expect("same size iterator"); writer = seals.strict_encode(writer)?; } for attach_id in self.attachments.keys() { diff --git a/src/containers/util.rs b/src/containers/util.rs index 6eee4fca..80cb4c6b 100644 --- a/src/containers/util.rs +++ b/src/containers/util.rs @@ -20,9 +20,8 @@ // limitations under the License. use amplify::confinement::SmallOrdSet; -use bp::seals::txout::ExplicitSeal; -use bp::{Outpoint, Tx, Txid}; -use rgb::{OutputSeal, XSeal}; +use bp::{Outpoint, Tx}; +use rgb::XChain; use super::TerminalSeal; use crate::LIB_NAME_RGB_STD; @@ -72,45 +71,4 @@ pub enum ContainerVer { V2 = 2, } -#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] -#[derive(StrictType, StrictDumb, StrictEncode, StrictDecode)] -#[strict_type(lib = LIB_NAME_RGB_STD, tags = custom, dumb = Self::Bitcoin(strict_dumb!()))] -#[cfg_attr( - feature = "serde", - derive(Serialize, Deserialize), - serde(crate = "serde_crate", rename_all = "camelCase") -)] -#[non_exhaustive] -pub enum XchainOutpoint { - #[strict_type(tag = 0x00)] - #[display("bitcoin:{0}", alt = "{0}")] - Bitcoin(Outpoint), - - #[strict_type(tag = 0x01)] - #[display("liquid:{0}")] - Liquid(Outpoint), - /* - #[strict_type(tag = 0x10)] - Abraxas, - #[strict_type(tag = 0x11)] - Prime, - */ -} - -impl From for XchainOutpoint { - fn from(seal: OutputSeal) -> Self { - match seal { - OutputSeal::Bitcoin(s) => XchainOutpoint::Bitcoin(s.into()), - OutputSeal::Liquid(s) => XchainOutpoint::Liquid(s.into()), - } - } -} - -impl From for XSeal> { - fn from(outpoint: XchainOutpoint) -> Self { - match outpoint { - XchainOutpoint::Bitcoin(outpoint) => XSeal::Bitcoin(outpoint.into()), - XchainOutpoint::Liquid(outpoint) => XSeal::Liquid(outpoint.into()), - } - } -} +pub type XOutpoint = XChain; diff --git a/src/containers/validate.rs b/src/containers/validate.rs index 94adff5e..b402e9f8 100644 --- a/src/containers/validate.rs +++ b/src/containers/validate.rs @@ -19,12 +19,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -use rgb::validation::{ResolveTx, Validator, Validity, Warning}; +use rgb::validation::{ResolveWitness, Validator, Validity, Warning}; use super::{Consignment, IndexedConsignment}; impl Consignment { - pub fn validate( + pub fn validate( mut self, resolver: &mut R, testnet: bool, diff --git a/src/interface/builder.rs b/src/interface/builder.rs index a843efc3..9d4cdff0 100644 --- a/src/interface/builder.rs +++ b/src/interface/builder.rs @@ -319,6 +319,8 @@ impl TransitionBuilder { }) } + pub fn transition_type(&self) -> TransitionType { self.transition_type } + #[inline] pub fn add_asset_tag( mut self, diff --git a/src/interface/contract.rs b/src/interface/contract.rs index d1113bb5..a8bfa751 100644 --- a/src/interface/contract.rs +++ b/src/interface/contract.rs @@ -26,13 +26,13 @@ use amplify::confinement::{LargeOrdMap, LargeVec, SmallVec}; use bp::Outpoint; use rgb::{ AssetTag, AssignmentType, AttachId, BlindingFactor, ContractId, ContractState, FungibleOutput, - MediaType, OutputSeal, RevealedAttach, RevealedData, WitnessId, + MediaType, RevealedAttach, RevealedData, WitnessId, XOutputSeal, }; use strict_encoding::FieldName; use strict_types::typify::TypedVal; use strict_types::{decode, StrictVal}; -use crate::containers::XchainOutpoint; +use crate::containers::XOutpoint; use crate::interface::{IfaceId, IfaceImpl}; #[derive(Clone, Eq, PartialEq, Debug, Display, Error, From)] @@ -105,7 +105,7 @@ impl From> for AllocationWitness { // TODO: Consider removing type in favour of `FungibleOutput` #[derive(Copy, Clone, Eq, PartialEq, Debug)] pub struct FungibleAllocation { - pub owner: OutputSeal, + pub owner: XOutputSeal, pub witness: AllocationWitness, pub value: u64, } @@ -125,26 +125,26 @@ impl From<&FungibleOutput> for FungibleAllocation { } pub trait OutpointFilter { - fn include_output(&self, output: impl Into) -> bool; + fn include_output(&self, output: impl Into) -> bool; } pub struct FilterIncludeAll; pub struct FilterExclude(pub T); impl OutpointFilter for &T { - fn include_output(&self, output: impl Into) -> bool { + fn include_output(&self, output: impl Into) -> bool { (*self).include_output(output) } } impl OutpointFilter for &mut T { - fn include_output(&self, output: impl Into) -> bool { + fn include_output(&self, output: impl Into) -> bool { self.deref().include_output(output) } } impl OutpointFilter for Option { - fn include_output(&self, output: impl Into) -> bool { + fn include_output(&self, output: impl Into) -> bool { self.as_ref() .map(|filter| filter.include_output(output)) .unwrap_or(true) @@ -152,37 +152,29 @@ impl OutpointFilter for Option { } impl OutpointFilter for FilterIncludeAll { - fn include_output(&self, _: impl Into) -> bool { true } + fn include_output(&self, _: impl Into) -> bool { true } } impl OutpointFilter for FilterExclude { - fn include_output(&self, output: impl Into) -> bool { + fn include_output(&self, output: impl Into) -> bool { !self.0.include_output(output.into()) } } -impl OutpointFilter for &[XchainOutpoint] { - fn include_output(&self, output: impl Into) -> bool { - self.contains(&output.into()) - } +impl OutpointFilter for &[XOutpoint] { + fn include_output(&self, output: impl Into) -> bool { self.contains(&output.into()) } } -impl OutpointFilter for Vec { - fn include_output(&self, output: impl Into) -> bool { - self.contains(&output.into()) - } +impl OutpointFilter for Vec { + fn include_output(&self, output: impl Into) -> bool { self.contains(&output.into()) } } -impl OutpointFilter for HashSet { - fn include_output(&self, output: impl Into) -> bool { - self.contains(&output.into()) - } +impl OutpointFilter for HashSet { + fn include_output(&self, output: impl Into) -> bool { self.contains(&output.into()) } } -impl OutpointFilter for BTreeSet { - fn include_output(&self, output: impl Into) -> bool { - self.contains(&output.into()) - } +impl OutpointFilter for BTreeSet { + fn include_output(&self, output: impl Into) -> bool { self.contains(&output.into()) } } /// Contract state is an in-memory structure providing API to read structured @@ -241,7 +233,7 @@ impl ContractIface { .fungibles() .iter() .filter(|outp| outp.opout.ty == type_id) - .filter(|outp| filter.include_output(outp.seal)) + .filter(|outp| filter.include_output(outp.seal.map(Outpoint::from))) .map(FungibleAllocation::from); Ok(LargeVec::try_from_iter(state).expect("same or smaller collection size")) } diff --git a/src/persistence/hoard.rs b/src/persistence/hoard.rs index 12b2965f..4ee3270a 100644 --- a/src/persistence/hoard.rs +++ b/src/persistence/hoard.rs @@ -48,6 +48,9 @@ pub enum ConsumeError { #[from] Anchor(mpc::InvalidProof), + #[display("anchor set {0} contains inconsistent information on witness id")] + AnchorInconsistent(WitnessId), + #[from] Merge(MergeError), @@ -213,7 +216,9 @@ impl Hoard { &mut self, anchor: XAnchor, ) -> Result<(), ConsumeError> { - let witness_id = anchor.witness_id(); + let witness_id = anchor + .witness_id() + .ok_or_else(|| ConsumeError::AnchorInconsistent(anchor.witness_id_unchecked()))?; match self.anchors.get_mut(&witness_id) { Some(a) => *a = a.clone().merge_reveal(anchor)?, None => { diff --git a/src/persistence/inventory.rs b/src/persistence/inventory.rs index 0aeab433..4ea35eb7 100644 --- a/src/persistence/inventory.rs +++ b/src/persistence/inventory.rs @@ -25,22 +25,22 @@ use std::error::Error; use std::ops::Deref; use amplify::confinement::{self, Confined, MediumVec, U24}; -use bp::seals::txout::{CloseMethod, ExplicitSeal}; +use bp::seals::txout::CloseMethod; use bp::{Txid, Vout}; use chrono::Utc; use commit_verify::{mpc, Conceal}; use invoice::{Beneficiary, InvoiceState, RgbInvoice}; use rgb::{ - validation, AnchoredBundle, AssignmentType, BlindingFactor, BundleId, ContractId, ExposedSeal, - GraphSeal, OpId, Operation, Opout, OutputSeal, SchemaId, SecretSeal, SubSchema, Transition, - TransitionBundle, WitnessId, XAnchor, XSeal, + validation, AnchoredBundle, AssignmentType, BlindingFactor, BundleId, ContractId, GraphSeal, + OpId, Operation, Opout, SchemaId, SecretSeal, SubSchema, Transition, TransitionBundle, + WitnessId, XAnchor, XChain, XOutputSeal, }; use strict_encoding::TypeName; use crate::accessors::{BundleExt, MergeRevealError, RevealError}; use crate::containers::{ - Batch, Bindle, BuilderSeal, Cert, Consignment, ContentId, Contract, Fascia, Terminal, Transfer, - TransitionInfo, + Batch, Bindle, BuilderSeal, Cert, Consignment, ContentId, Contract, Fascia, Terminal, + TerminalSeal, Transfer, TransitionInfo, }; use crate::interface::{ BuilderError, ContractIface, Iface, IfaceId, IfaceImpl, IfacePair, IfaceWrapper, @@ -216,7 +216,7 @@ pub enum DataError { Merge(MergeRevealError), /// outpoint {0} is not part of the contract {1}. - OutpointUnknown(OutputSeal, ContractId), + OutpointUnknown(XOutputSeal, ContractId), #[from] #[display(inner)] @@ -358,7 +358,9 @@ pub trait Inventory: Deref { /// Must be called before the consignment is created, when witness /// transaction is not yet mined. fn consume(&mut self, fascia: Fascia) -> Result<(), InventoryError> { - let witness_id = fascia.anchor.witness_id(); + let witness_id = fascia.anchor.witness_id().ok_or_else(|| { + ConsumeError::AnchorInconsistent(fascia.anchor.witness_id_unchecked()) + })?; unsafe { self.consume_anchor(fascia.anchor)? }; for (contract_id, bundle) in fascia.bundles { let ids1 = bundle @@ -519,7 +521,7 @@ pub trait Inventory: Deref { fn contracts_by_outputs( &self, - outputs: impl IntoIterator>, + outputs: impl IntoIterator>, ) -> Result, InventoryError>; fn public_opouts( @@ -530,27 +532,27 @@ pub trait Inventory: Deref { fn opouts_by_outputs( &self, contract_id: ContractId, - outputs: impl IntoIterator>, + outputs: impl IntoIterator>, ) -> Result, InventoryError>; fn opouts_by_terminals( &self, - terminals: impl IntoIterator, + terminals: impl IntoIterator>, ) -> Result, InventoryError>; #[allow(clippy::type_complexity)] fn state_for_outputs( &self, contract_id: ContractId, - outputs: impl IntoIterator>, - ) -> Result, InventoryError>; + outputs: impl IntoIterator>, + ) -> Result, InventoryError>; fn store_seal_secret( &mut self, - seal: XSeal, + seal: XChain, ) -> Result<(), InventoryError>; - fn seal_secrets(&self) -> Result>, InventoryError>; + fn seal_secrets(&self) -> Result>, InventoryError>; #[allow(clippy::type_complexity)] fn export_contract( @@ -560,8 +562,7 @@ pub trait Inventory: Deref { Bindle, ConsignerError::Target as Stash>::Error>, > { - let mut consignment = - self.consign::(contract_id, [] as [XSeal; 0])?; + let mut consignment = self.consign::(contract_id, [], [])?; consignment.transfer = false; Ok(consignment.into()) // TODO: Add known sigs to the bindle @@ -571,43 +572,42 @@ pub trait Inventory: Deref { fn transfer( &self, contract_id: ContractId, - seals: impl IntoIterator>>>, + outputs: impl AsRef<[XOutputSeal]>, + secret_seals: impl AsRef<[XChain]>, ) -> Result< Bindle, ConsignerError::Target as Stash>::Error>, > { - let mut consignment = self.consign(contract_id, seals)?; + let mut consignment = self.consign(contract_id, outputs, secret_seals)?; consignment.transfer = true; Ok(consignment.into()) // TODO: Add known sigs to the bindle } - fn consign( + fn consign( &self, contract_id: ContractId, - seals: impl IntoIterator>>, + outputs: impl AsRef<[XOutputSeal]>, + secret_seals: impl AsRef<[XChain]>, ) -> Result< Consignment, ConsignerError::Target as Stash>::Error>, > { + let outputs = outputs.as_ref(); + let secret_seals = secret_seals.as_ref(); + // 1. Collect initial set of anchored bundles + // 1.1. Get all public outputs let mut opouts = self.public_opouts(contract_id)?; - let (outpoint_seals, terminal_seals) = seals - .into_iter() - .map(|seal| match seal.into() { - BuilderSeal::Revealed(seal) => (seal.to_output_seal(), seal.conceal()), - BuilderSeal::Concealed(seal) => (None, seal), - }) - .unzip::<_, _, Vec<_>, Vec<_>>(); - opouts.extend(self.opouts_by_outputs(contract_id, outpoint_seals.into_iter().flatten())?); - opouts.extend(self.opouts_by_terminals(terminal_seals.iter().copied())?); - - // 1.1. Get all public transitions - // 1.2. Collect all state transitions assigning state to the provided - // outpoints + + // 1.2. Add outputs requested by the caller + opouts.extend(self.opouts_by_outputs(contract_id, outputs.iter().copied())?); + opouts.extend(self.opouts_by_terminals(secret_seals.iter().copied())?); + + // 1.3. Collect all state transitions assigning state to the provided outpoints let mut anchored_bundles = BTreeMap::::new(); let mut transitions = BTreeMap::::new(); - let mut terminals = BTreeMap::::new(); + let mut terminals = BTreeMap::>::new(); for opout in opouts { if opout.op == contract_id { continue; // we skip genesis since it will be present anywhere @@ -622,14 +622,20 @@ pub trait Inventory: Deref { for (type_id, typed_assignments) in transition.assignments.iter() { for index in 0..typed_assignments.len_u16() { let seal = typed_assignments.to_confidential_seals()[index as usize]; - if terminal_seals.contains(&seal) { - terminals.insert(bundle_id, Terminal::new(seal.into())); + if secret_seals.contains(&seal) { + terminals + .insert(bundle_id, seal.map(TerminalSeal::from).map(Terminal::new)); } else if opout.no == index && opout.ty == *type_id { if let Some(seal) = typed_assignments .revealed_seal_at(index) .expect("index exists") { - terminals.insert(bundle_id, Terminal::new(seal.into())); + terminals.insert( + bundle_id, + seal.map(|s| s.conceal()) + .map(TerminalSeal::from) + .map(Terminal::new), + ); } else { return Err(ConsignerError::ConcealedPublicState(opout)); } @@ -640,7 +646,7 @@ pub trait Inventory: Deref { anchored_bundles.insert(opout.op, anchored_bundle.clone()); } - // 3. Collect all state transitions between terminals and genesis + // 2. Collect all state transitions between terminals and genesis let mut ids = vec![]; for transition in transitions.values() { ids.extend(transition.inputs().iter().map(|input| input.prev_out.op)); @@ -688,7 +694,7 @@ pub trait Inventory: Deref { fn compose( &self, invoice: &RgbInvoice, - prev_outputs: impl IntoIterator>, + prev_outputs: impl IntoIterator>, method: CloseMethod, beneficiary_vout: Option>, allocator: impl Fn(ContractId, AssignmentType, VelocityHint) -> Option, @@ -703,6 +709,7 @@ pub trait Inventory: Deref { beneficiary_vout, allocator, |_, _| BlindingFactor::random(), + |_, _| rand::random(), ) } @@ -712,11 +719,12 @@ pub trait Inventory: Deref { fn compose_deterministic( &self, invoice: &RgbInvoice, - prev_outputs: impl IntoIterator>, + prev_outputs: impl IntoIterator>, method: CloseMethod, beneficiary_vout: Option>, allocator: impl Fn(ContractId, AssignmentType, VelocityHint) -> Option, - blinder: impl Fn(ContractId, AssignmentType) -> BlindingFactor, + pedersen_blinder: impl Fn(ContractId, AssignmentType) -> BlindingFactor, + seal_blinder: impl Fn(ContractId, AssignmentType) -> u64, ) -> Result::Target as Stash>::Error>> where Self::Error: From<::Error>, @@ -725,7 +733,7 @@ pub trait Inventory: Deref { let prev_outputs = prev_outputs .into_iter() .map(|o| o.into()) - .collect::>(); + .collect::>(); #[allow(clippy::type_complexity)] let output_for_assignment = |id: ContractId, @@ -741,8 +749,9 @@ pub trait Inventory: Deref { .unwrap_or_default(); let vout = allocator(id, assignment_type, velocity) .ok_or(ComposeError::NoBlankOrChange(velocity, assignment_type))?; - let seal = GraphSeal::new_vout(method, vout); - Ok(BuilderSeal::Revealed(XSeal::with(layer1, seal))) + let seal = + GraphSeal::with_blinded_vout(method, vout, seal_blinder(id, assignment_type)); + Ok(BuilderSeal::Revealed(XChain::with(layer1, seal))) }; // 1. Prepare the data @@ -755,11 +764,24 @@ pub trait Inventory: Deref { let iface = invoice.iface.as_ref().ok_or(ComposeError::NoIface)?; let mut main_builder = self.transition_builder(contract_id, iface.clone(), invoice.operation.clone())?; + let assignment_name = invoice + .assignment + .as_ref() + .or_else(|| main_builder.default_assignment().ok()) + .ok_or(BuilderError::NoDefaultAssignment)? + .clone(); + let assignment_id = main_builder + .assignments_type(&assignment_name) + .ok_or(BuilderError::InvalidStateField(assignment_name.clone()))?; let beneficiary = match (invoice.beneficiary, beneficiary_vout) { (Beneficiary::BlindedSeal(seal), _) => BuilderSeal::Concealed(seal), (Beneficiary::WitnessVoutBitcoin(_), Some(vout)) => { - BuilderSeal::Revealed(XSeal::Bitcoin(GraphSeal::new_vout(method, vout.into()))) + BuilderSeal::Revealed(XChain::Bitcoin(GraphSeal::with_blinded_vout( + method, + vout, + seal_blinder(contract_id, assignment_id), + ))) } (Beneficiary::WitnessVoutBitcoin(_), None) => { return Err(ComposeError::NoBeneficiaryOutput); @@ -767,16 +789,7 @@ pub trait Inventory: Deref { }; // 2. Prepare transition - let mut main_inputs = MediumVec::::new(); - let assignment_name = invoice - .assignment - .as_ref() - .or_else(|| main_builder.default_assignment().ok()) - .ok_or(BuilderError::NoDefaultAssignment)? - .clone(); - let assignment_id = main_builder - .assignments_type(&assignment_name) - .ok_or(BuilderError::InvalidStateField(assignment_name.clone()))?; + let mut main_inputs = MediumVec::::new(); let mut sum_inputs = 0u64; for ((opout, output), mut state) in self.state_for_outputs(contract_id, prev_outputs.iter().cloned())? @@ -785,7 +798,7 @@ pub trait Inventory: Deref { main_inputs.push(output)?; if opout.ty != assignment_id { let seal = output_for_assignment(contract_id, opout.ty)?; - state.update_blinding(blinder(contract_id, assignment_id)); + state.update_blinding(pedersen_blinder(contract_id, assignment_id)); main_builder = main_builder.add_owned_state_raw(opout.ty, seal, state)?; } else if let TypedState::Amount(value, _, _) = state { sum_inputs += value; @@ -801,7 +814,7 @@ pub trait Inventory: Deref { assignment_id, seal, sum_inputs - amt, - blinder(contract_id, assignment_id), + pedersen_blinder(contract_id, assignment_id), )?; } Ordering::Less => return Err(ComposeError::InsufficientState), @@ -812,7 +825,7 @@ pub trait Inventory: Deref { assignment_id, beneficiary, amt, - blinder(contract_id, assignment_id), + pedersen_blinder(contract_id, assignment_id), )? .complete_transition(contract_id)? } @@ -824,7 +837,7 @@ pub trait Inventory: Deref { // 3. Prepare other transitions // Enumerate state let mut spent_state = - HashMap::>::new(); + HashMap::>::new(); for output in prev_outputs { for id in self.contracts_by_outputs([output])? { if id == contract_id { @@ -845,7 +858,7 @@ pub trait Inventory: Deref { let seal = output_for_assignment(id, opout.ty)?; outputs.push(output); if let TypedState::Amount(_, ref mut blinding, _) = state { - *blinding = blinder(id, opout.ty); + *blinding = pedersen_blinder(id, opout.ty); } blank_builder = blank_builder .add_input(opout, state.clone())? diff --git a/src/persistence/stock.rs b/src/persistence/stock.rs index b48d95e0..82097323 100644 --- a/src/persistence/stock.rs +++ b/src/persistence/stock.rs @@ -29,8 +29,8 @@ use rgb::validation::{Status, Validity, Warning}; use rgb::{ validation, AnchoredBundle, Assign, AssignmentType, BundleId, ContractHistory, ContractId, ContractState, ExposedState, Extension, Genesis, GenesisSeal, GraphSeal, OpId, Operation, - Opout, OutputSeal, SecretSeal, SubSchema, Transition, TransitionBundle, TypedAssigns, - WitnessAnchor, WitnessId, XAnchor, XSeal, + Opout, SecretSeal, SubSchema, Transition, TransitionBundle, TypedAssigns, WitnessAnchor, + WitnessId, XAnchor, XChain, XOutputSeal, }; use strict_encoding::{StrictDeserialize, StrictSerialize}; @@ -38,6 +38,7 @@ use crate::containers::{Bindle, Cert, Consignment, ContentId, Contract, Terminal use crate::interface::{ ContractIface, Iface, IfaceId, IfaceImpl, IfacePair, SchemaIfaces, TypedState, }; +use crate::persistence::hoard::ConsumeError; use crate::persistence::inventory::{DataError, IfaceImplError, InventoryInconsistency}; use crate::persistence::{ Hoard, Inventory, InventoryDataError, InventoryError, Stash, StashInconsistency, @@ -55,7 +56,7 @@ pub struct IndexedBundle(ContractId, BundleId); #[strict_type(lib = LIB_NAME_RGB_STD)] pub struct ContractIndex { public_opouts: MediumOrdSet, - outpoint_opouts: MediumOrdMap>, + outpoint_opouts: MediumOrdMap>, } /// Stock is an in-memory inventory (stash, index, contract state) useful for @@ -75,9 +76,9 @@ pub struct Stock { bundle_op_index: MediumOrdMap, anchor_bundle_index: MediumOrdMap, contract_index: TinyOrdMap, - terminal_index: MediumOrdMap, + terminal_index: MediumOrdMap, Opout>, // secrets - seal_secrets: MediumOrdSet>, + seal_secrets: MediumOrdSet>, } impl Default for Stock { @@ -152,7 +153,14 @@ impl Stock { // clone needed due to borrow checker for (bundle_id, terminal) in consignment.terminals.clone() { - for secret in terminal.seals.iter().filter_map(TerminalSeal::secret_seal) { + let layer1 = terminal.layer1(); + for secret in terminal + .as_reduced_unsafe() + .seals + .iter() + .filter_map(TerminalSeal::secret_seal) + { + let secret = XChain::with(layer1, secret); if let Some(seal) = self.seal_secrets.iter().find(|s| s.conceal() == secret) { consignment.reveal_bundle_seal(bundle_id, *seal); } @@ -175,7 +183,9 @@ impl Stock { } for AnchoredBundle { anchor, bundle } in &mut consignment.bundles { let bundle_id = bundle.bundle_id(); - let witness_id = anchor.witness_id(); + let witness_id = anchor + .witness_id() + .ok_or_else(|| ConsumeError::AnchorInconsistent(anchor.witness_id_unchecked()))?; self.anchor_bundle_index.insert(bundle_id, witness_id)?; self.index_bundle(contract_id, bundle, witness_id)?; } @@ -466,7 +476,9 @@ impl Inventory for Stock { &mut self, anchor: XAnchor, ) -> Result<(), InventoryError> { - let witness_id = anchor.witness_id(); + let witness_id = anchor + .witness_id() + .ok_or_else(|| ConsumeError::AnchorInconsistent(anchor.witness_id_unchecked()))?; for (bundle_id, _) in anchor.known_bundle_ids() { self.anchor_bundle_index.insert(bundle_id, witness_id)?; } @@ -568,7 +580,7 @@ impl Inventory for Stock { fn contracts_by_outputs( &self, - outputs: impl IntoIterator>, + outputs: impl IntoIterator>, ) -> Result, InventoryError> { let outputs = outputs .into_iter() @@ -599,7 +611,7 @@ impl Inventory for Stock { fn opouts_by_outputs( &self, contract_id: ContractId, - outputs: impl IntoIterator>, + outputs: impl IntoIterator>, ) -> Result, InventoryError> { let index = self .contract_index @@ -618,7 +630,7 @@ impl Inventory for Stock { fn opouts_by_terminals( &self, - terminals: impl IntoIterator, + terminals: impl IntoIterator>, ) -> Result, InventoryError> { let terminals = terminals.into_iter().collect::>(); Ok(self @@ -632,8 +644,8 @@ impl Inventory for Stock { fn state_for_outputs( &self, contract_id: ContractId, - outputs: impl IntoIterator>, - ) -> Result, InventoryError> { + outputs: impl IntoIterator>, + ) -> Result, InventoryError> { let outputs = outputs .into_iter() .map(|o| o.into()) @@ -685,13 +697,13 @@ impl Inventory for Stock { fn store_seal_secret( &mut self, - seal: XSeal, + seal: XChain, ) -> Result<(), InventoryError> { self.seal_secrets.push(seal)?; Ok(()) } - fn seal_secrets(&self) -> Result>, InventoryError> { + fn seal_secrets(&self) -> Result>, InventoryError> { Ok(self.seal_secrets.to_inner()) } } diff --git a/src/stl/stl.rs b/src/stl/stl.rs index d494bc5b..2bf405f8 100644 --- a/src/stl/stl.rs +++ b/src/stl/stl.rs @@ -44,7 +44,7 @@ pub const LIB_ID_RGB_CONTRACT: &str = /// Strict types id for the library representing of RGB StdLib data types. pub const LIB_ID_RGB_STD: &str = - "urn:ubideco:stl:FjdM8g7HN2S8hfKB17GuwsnKRzFM9up8bJ4uBNzWAPDL#aloha-olivia-rider"; + "urn:ubideco:stl:452BoxLkej33Myvj2ygScjX72Nphpm4tbtiHwP4ET7Xw#proxy-james-scratch"; fn _rgb_std_stl() -> Result { LibBuilder::new(libname!(LIB_NAME_RGB_STD), tiny_bset! { diff --git a/stl/RGBStd@0.1.0.sty b/stl/RGBStd@0.1.0.sty index 95a5bc23..5ccfa082 100644 --- a/stl/RGBStd@0.1.0.sty +++ b/stl/RGBStd@0.1.0.sty @@ -65,7 +65,7 @@ import urn:ubideco:stl:EZiZRCHpyqJakmTU1zkwczq5YKMbapfMhVLhS8DbkpwC#premium-hone -- AltLayer1Set := urn:ubideco:semid:3Sruah3S3s7c8XRpD8bN7c8rnSKemwvnxhocQzHy5D9m#manual-cycle-circus -- VoidState := urn:ubideco:semid:49HkbZvGaJE3phHjLBMQCR3NK1sGA462HJr5BkqQ6YQr#nectar-ceramic-driver -- AnchorSet := urn:ubideco:semid:4GL38RVDhs4JkL5phqyF6pguwL6Av8qTUWCVNfGeWdUg#history-joel-ivory --- XSealBlindSealTxPtr := urn:ubideco:semid:4Nr4GNjqYM4KpeLkWEFjy8FxYs1jVV6CCum7CMftHCm9#studio-evening-camera +-- XChainBlindSealTxPtr := urn:ubideco:semid:4Nr4GNjqYM4KpeLkWEFjy8FxYs1jVV6CCum7CMftHCm9#studio-evening-camera -- TransitionType := urn:ubideco:semid:4XEmzMLZTXc4XB3njvemMq5qdMmx5EKJPAXpJaBPrqCb#puma-joshua-evita -- Occurrences := urn:ubideco:semid:4gjtVBchJQ5f1aAzoyxYWeGp6qZi9dPudJCbWKYKhw1a#unicorn-empire-mama -- StateSchema := urn:ubideco:semid:4pgZ5NMvRK6Jf2ua7H3TCF8bMNHhZR7PuUJawqq1X4uG#yoga-arizona-flex @@ -75,7 +75,7 @@ import urn:ubideco:stl:EZiZRCHpyqJakmTU1zkwczq5YKMbapfMhVLhS8DbkpwC#premium-hone -- GlobalValues := urn:ubideco:semid:5j3xo5bTKFzcKayBQELdAVzUEnuPPAVd8etsBPG1EgZ3#volcano-expand-paper -- ValencyType := urn:ubideco:semid:5mswXMrudHpJEnuoLA86YY2VHN5iL56hmKcmh5k1h3e5#palma-exit-pupil -- PedersenCommitment := urn:ubideco:semid:5twbh2U5hyaowidwum1iRNCqebBLxTuZTuNPt3SaRT13#nepal-delta-earth --- XSealExplicitSeal := urn:ubideco:semid:5yxE75Qk7ScEuNdG4NXGASsGkpyUVQB3FVaxm3q8w1zK#carbon-network-hilton +-- XChainExplicitSeal := urn:ubideco:semid:5yxE75Qk7ScEuNdG4NXGASsGkpyUVQB3FVaxm3q8w1zK#carbon-network-hilton -- AssignRevealedValueBlindSealTxid := urn:ubideco:semid:6McV9ZYuRYX11q6DnALBt7uYo6yxoFjDWocYeXnsEUJc#cotton-david-edition -- ExtensionType := urn:ubideco:semid:7m9MHRdHSXnhYiheDeXybxnHAxPRgs84USnVELFH98Cd#mission-salsa-parole -- Transition := urn:ubideco:semid:7pNXtZVVpUHTSZi9UiyPWWRDvKsRzdyByntYcyytnwVy#data-wedding-night @@ -90,7 +90,7 @@ import urn:ubideco:stl:EZiZRCHpyqJakmTU1zkwczq5YKMbapfMhVLhS8DbkpwC#premium-hone -- BlindingFactor := urn:ubideco:semid:9zzp5XyDaLvZSGhCEWtey1Y7xdD1soEYdGaimjyZexyf#agenda-ivory-blast -- AssignmentType := urn:ubideco:semid:A9sThAqgwKPfuJcR4GDfTQHUAbbS5sbEXG5XVk7FZHEg#hunter-hello-retro -- AssignVoidStateBlindSealTxPtr := urn:ubideco:semid:ACfDgeTtorFy3NqZWw6CuWHNKT3hpuXpwFHV9DpjLoT1#campus-front-carpet --- XSealBlindSealTxid := urn:ubideco:semid:Age9RPnuptagg4d8Q6wixptyT6y6yRFvTSWEkrT6H6Vc#ford-guitar-tonight +-- XChainBlindSealTxid := urn:ubideco:semid:Age9RPnuptagg4d8Q6wixptyT6y6yRFvTSWEkrT6H6Vc#ford-guitar-tonight -- AssignmentsBlindSealTxid := urn:ubideco:semid:AkbqFDMkiwdiUVmhPaBmq2D4RkeGqb4bB7jq5JTA3AQV#radio-sherman-cabinet -- Opout := urn:ubideco:semid:Au5jXjVgXjeE2n7dFQnPQwjLRQJ3eoGygRvt8ppzXrfx#india-joshua-adam -- SchemaId := urn:ubideco:semid:AyzbMn4ux89LLU8ho1L4pQa5TXsmRdHd79oh6SXdrCmd#garcia-smoke-ozone @@ -225,7 +225,7 @@ data ContentId :: schema RGB.SchemaId {- urn:ubideco:semid:AyzbMn4ux89LLU -- urn:ubideco:semid:72v5XvfiTB7HJinscrxy5ZTa4PwubG9YCtkK8JQt7F5B#denver-almanac-cobalt data ContentSigs :: {Cert ^ 1..0xa} -- urn:ubideco:semid:EFPmZdw9YNzrqSdx9buUBvoUmXAzEho94rfP9phgpTx5#license-infant-bicycle -data ContractIndex :: publicOpouts {RGB.Opout {- urn:ubideco:semid:Au5jXjVgXjeE2n7dFQnPQwjLRQJ3eoGygRvt8ppzXrfx#india-joshua-adam -} ^ ..0xffffff}, outpointOpouts {RGB.XSealExplicitSeal -> ^ ..0xffffff {RGB.Opout {- urn:ubideco:semid:Au5jXjVgXjeE2n7dFQnPQwjLRQJ3eoGygRvt8ppzXrfx#india-joshua-adam -} ^ ..0xffffff}} +data ContractIndex :: publicOpouts {RGB.Opout {- urn:ubideco:semid:Au5jXjVgXjeE2n7dFQnPQwjLRQJ3eoGygRvt8ppzXrfx#india-joshua-adam -} ^ ..0xffffff}, outpointOpouts {RGB.XChainExplicitSeal -> ^ ..0xffffff {RGB.Opout {- urn:ubideco:semid:Au5jXjVgXjeE2n7dFQnPQwjLRQJ3eoGygRvt8ppzXrfx#india-joshua-adam -} ^ ..0xffffff}} -- urn:ubideco:semid:3WPrDGfcJCVwN9ZtFUf1w6SqsutP7xuJ8wRdby9VgPHF#slang-mars-belgium data ContractSuppl :: contractId RGB.ContractId {- urn:ubideco:semid:Bho42Xw8wPy2nWxgz6H51rNdBBusaPyrVQT8VypvpZ3w#alarm-danube-vampire -} , ticker TickerSuppl @@ -338,7 +338,7 @@ data Stock :: hoard Hoard , anchorBundleIndex {RGB.BundleId -> ^ ..0xffffff RGB.WitnessId {- urn:ubideco:semid:EEYT7goTNgX2nNFoKosg6FKx1CDSyFWHKNK1TRySs6gr#axiom-gyro-album -}} , contractIndex {RGB.ContractId -> ^ ..0xff ContractIndex} , terminalIndex {BPCore.SecretSeal -> ^ ..0xffffff RGB.Opout {- urn:ubideco:semid:Au5jXjVgXjeE2n7dFQnPQwjLRQJ3eoGygRvt8ppzXrfx#india-joshua-adam -}} - , sealSecrets {RGB.XSealBlindSealTxPtr {- urn:ubideco:semid:4Nr4GNjqYM4KpeLkWEFjy8FxYs1jVV6CCum7CMftHCm9#studio-evening-camera -} ^ ..0xffffff} + , sealSecrets {RGB.XChainBlindSealTxPtr {- urn:ubideco:semid:4Nr4GNjqYM4KpeLkWEFjy8FxYs1jVV6CCum7CMftHCm9#studio-evening-camera -} ^ ..0xffffff} -- urn:ubideco:semid:7wqgZas6f6Y7jWyDzLNxCeGEM8NXppB1f1gZNvNHJD72#partner-austin-dinner data SupplId :: [Byte ^ 32] -- urn:ubideco:semid:CXGPwRETAtPV783GHQKZmnpvrtbUzELpBP74ScXDBP22#system-billy-polaris From 2aa64af7425de8916d60ae258e60f4531293aaa6 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 30 Dec 2023 01:09:55 +0100 Subject: [PATCH 02/11] invoice: update beneficiary to include multiple chains and testnets --- invoice/src/builder.rs | 16 ++-- invoice/src/invoice.rs | 133 ++++++++++++++++++++++------ invoice/src/parse.rs | 166 ++++++++++++++++++++--------------- src/persistence/inventory.rs | 18 ++-- 4 files changed, 218 insertions(+), 115 deletions(-) diff --git a/invoice/src/builder.rs b/invoice/src/builder.rs index b786635c..fa5aa69c 100644 --- a/invoice/src/builder.rs +++ b/invoice/src/builder.rs @@ -21,17 +21,17 @@ use std::str::FromStr; -use invoice::Network; use rgb::ContractId; use super::{Beneficiary, InvoiceState, Precision, RgbInvoice, RgbTransport, TransportParseError}; +use crate::invoice::XChainNet; #[derive(Clone, Eq, PartialEq, Debug)] pub struct RgbInvoiceBuilder(RgbInvoice); #[allow(clippy::result_large_err)] impl RgbInvoiceBuilder { - pub fn new(beneficiary: impl Into) -> Self { + pub fn new(beneficiary: impl Into>) -> Self { Self(RgbInvoice { transports: vec![RgbTransport::UnspecifiedMeans], contract: None, @@ -40,21 +40,20 @@ impl RgbInvoiceBuilder { assignment: None, beneficiary: beneficiary.into(), owned_state: InvoiceState::Void, - network: None, expiry: None, unknown_query: none!(), }) } - pub fn with(contract_id: ContractId, beneficiary: impl Into) -> Self { + pub fn with(contract_id: ContractId, beneficiary: impl Into>) -> Self { Self::new(beneficiary).set_contract(contract_id) } - pub fn rgb20(contract_id: ContractId, beneficiary: impl Into) -> Self { + pub fn rgb20(contract_id: ContractId, beneficiary: impl Into>) -> Self { Self::with(contract_id, beneficiary).set_interface("RGB20") } - pub fn rgb20_anything(beneficiary: impl Into) -> Self { + pub fn rgb20_anything(beneficiary: impl Into>) -> Self { Self::new(beneficiary).set_interface("RGB20") } @@ -119,11 +118,6 @@ impl RgbInvoiceBuilder { self.set_amount(coins as u64, cents as u64, precision) } - pub fn set_network(mut self, network: impl Into) -> Self { - self.0.network = Some(network.into()); - self - } - pub fn set_expiry_timestamp(mut self, expiry: i64) -> Self { self.0.expiry = Some(expiry); self diff --git a/invoice/src/invoice.rs b/invoice/src/invoice.rs index fd64165e..8a36028e 100644 --- a/invoice/src/invoice.rs +++ b/invoice/src/invoice.rs @@ -20,11 +20,12 @@ // limitations under the License. use indexmap::IndexMap; -use invoice::{Address, Network}; -use rgb::{AttachId, ContractId, Layer1, SecretSeal, XChain}; +use invoice::{AddressNetwork, AddressPayload}; +use rgb::{AttachId, ContractId, Layer1, SecretSeal}; use strict_encoding::{FieldName, TypeName}; #[derive(Clone, Eq, PartialEq, Hash, Debug)] +#[non_exhaustive] pub enum RgbTransport { JsonRpc { tls: bool, host: String }, RestHttp { tls: bool, host: String }, @@ -45,50 +46,130 @@ pub enum InvoiceState { Attach(AttachId), } -#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Display, From)] -#[display(inner)] -pub enum Beneficiary { - // TODO: Create wrapping type for SecretSeal to cover/commit to a specific layer1. - // Move Baid58 encoding from BP seals to here. Use utxob1 for bitcoin, and use - // utxol1 for liquid. - #[from] - BlindedSeal(XChain), - #[from] - WitnessVoutBitcoin(Address), - // TODO: Add support for Liquid beneficiaries - //#[from] - //WitnessVoutLiquid(Address), +#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)] +#[non_exhaustive] +pub enum ChainNet { + #[display("bc")] + BitcoinMainnet, + #[display("tb")] + BitcoinTestnet, + #[display("sb")] + BitcoinSignet, + #[display("bcrt")] + BitcoinRegtest, + #[display("lq")] + LiquidMainnet, + #[display("tl")] + LiquidTestnet, } -impl Beneficiary { +impl ChainNet { pub fn layer1(&self) -> Layer1 { match self { - // TODO: Fix supporting liquid - Beneficiary::BlindedSeal(_) => Layer1::Bitcoin, - Beneficiary::WitnessVoutBitcoin(_) => Layer1::Bitcoin, + ChainNet::BitcoinMainnet | + ChainNet::BitcoinTestnet | + ChainNet::BitcoinSignet | + ChainNet::BitcoinRegtest => Layer1::Bitcoin, + ChainNet::LiquidMainnet | ChainNet::LiquidTestnet => Layer1::Liquid, + } + } + + pub fn is_prod(&self) -> bool { + match self { + ChainNet::BitcoinMainnet | ChainNet::LiquidMainnet => true, + + ChainNet::BitcoinTestnet | + ChainNet::BitcoinSignet | + ChainNet::BitcoinRegtest | + ChainNet::LiquidTestnet => false, + } + } + + pub(crate) fn address_network(&self) -> AddressNetwork { + match self { + ChainNet::BitcoinMainnet => AddressNetwork::Mainnet, + ChainNet::BitcoinTestnet | ChainNet::BitcoinSignet => AddressNetwork::Testnet, + ChainNet::BitcoinRegtest => AddressNetwork::Regtest, + ChainNet::LiquidMainnet => AddressNetwork::Mainnet, + ChainNet::LiquidTestnet => AddressNetwork::Testnet, } } } +#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug)] +#[non_exhaustive] +pub enum XChainNet { + BitcoinMainnet(T), + BitcoinTestnet(T), + BitcoinSignet(T), + BitcoinRegtest(T), + LiquidMainnet(T), + LiquidTestnet(T), +} + +impl XChainNet { + pub fn with(cn: ChainNet, data: T) -> Self { + match cn { + ChainNet::BitcoinMainnet => XChainNet::BitcoinMainnet(data), + ChainNet::BitcoinTestnet => XChainNet::BitcoinTestnet(data), + ChainNet::BitcoinSignet => XChainNet::BitcoinSignet(data), + ChainNet::BitcoinRegtest => XChainNet::BitcoinRegtest(data), + ChainNet::LiquidMainnet => XChainNet::LiquidMainnet(data), + ChainNet::LiquidTestnet => XChainNet::LiquidTestnet(data), + } + } + + pub fn chain_network(&self) -> ChainNet { + match self { + XChainNet::BitcoinMainnet(_) => ChainNet::BitcoinMainnet, + XChainNet::BitcoinTestnet(_) => ChainNet::BitcoinTestnet, + XChainNet::BitcoinSignet(_) => ChainNet::BitcoinSignet, + XChainNet::BitcoinRegtest(_) => ChainNet::BitcoinRegtest, + XChainNet::LiquidMainnet(_) => ChainNet::LiquidMainnet, + XChainNet::LiquidTestnet(_) => ChainNet::LiquidTestnet, + } + } + + pub fn into_inner(self) -> T { + match self { + XChainNet::BitcoinMainnet(inner) | + XChainNet::BitcoinTestnet(inner) | + XChainNet::BitcoinSignet(inner) | + XChainNet::BitcoinRegtest(inner) | + XChainNet::LiquidMainnet(inner) | + XChainNet::LiquidTestnet(inner) => inner, + } + } + + pub fn layer1(&self) -> Layer1 { self.chain_network().layer1() } + pub fn is_prod(&self) -> bool { self.chain_network().is_prod() } +} + +#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, From)] +pub enum Beneficiary { + #[from] + BlindedSeal(SecretSeal), + #[from] + WitnessVout(AddressPayload), +} + #[derive(Clone, Eq, PartialEq, Debug)] +#[non_exhaustive] pub struct RgbInvoice { pub transports: Vec, pub contract: Option, pub iface: Option, pub operation: Option, pub assignment: Option, - pub beneficiary: Beneficiary, + pub beneficiary: XChainNet, pub owned_state: InvoiceState, - pub network: Option, /// UTC unix timestamp pub expiry: Option, pub unknown_query: IndexMap, } impl RgbInvoice { - pub fn layer1(&self) -> Layer1 { - match self.beneficiary { - Beneficiary::BlindedSeal(_) | Beneficiary::WitnessVoutBitcoin(_) => Layer1::Bitcoin, - } - } + pub fn chain_network(&self) -> ChainNet { self.beneficiary.chain_network() } + pub fn layer1(&self) -> Layer1 { self.beneficiary.layer1() } + pub fn is_prod(&self) -> bool { self.beneficiary.is_prod() } } diff --git a/invoice/src/parse.rs b/invoice/src/parse.rs index 295f5ada..e05a98b9 100644 --- a/invoice/src/parse.rs +++ b/invoice/src/parse.rs @@ -26,16 +26,16 @@ use std::str::FromStr; use fluent_uri::enc::EStr; use fluent_uri::Uri; use indexmap::IndexMap; -use invoice::{Address, AddressNetwork, Network, UnknownNetwork}; +use invoice::{Address, UnknownNetwork}; use percent_encoding::{utf8_percent_encode, AsciiSet, CONTROLS}; -use rgb::{ContractId, SecretSeal, XChain}; +use rgb::{ContractId, SecretSeal}; use strict_encoding::{InvalidIdent, TypeName}; use super::{Beneficiary, InvoiceState, RgbInvoice, RgbTransport}; +use crate::invoice::{ChainNet, XChainNet}; const OMITTED: &str = "~"; const EXPIRY: &str = "expiry"; -const NETWORK: &str = "network"; const ENDPOINTS: &str = "endpoints"; const TRANSPORT_SEP: char = ','; const TRANSPORT_HOST_SEP: &str = "://"; @@ -103,10 +103,6 @@ pub enum InvoiceParseError { #[from] InvalidNetwork(UnknownNetwork), - /// address network `{0:#?}` doesn't match network `{1}` specified in the - /// invoice. - NetworkMismatch(AddressNetwork, Network), - /// invalid query parameter {0}. InvalidQueryParam(String), @@ -114,8 +110,8 @@ pub enum InvoiceParseError { #[display(inner)] Id(baid58::Baid58ParseError), - /// can't recognize beneficiary "": it should be either a bitcoin address or - /// a blinded UTXO seal. + /// can't recognize beneficiary "{0}": it should be either a bitcoin address + /// or a blinded UTXO seal. Beneficiary(String), #[from] @@ -202,6 +198,67 @@ impl FromStr for RgbTransport { } } +impl Display for XChainNet { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "{}:", self.chain_network())?; + match self.into_inner() { + Beneficiary::BlindedSeal(seal) => Display::fmt(&seal, f), + Beneficiary::WitnessVout(payload) => { + let addr = Address::new(payload, self.chain_network().address_network()); + let s = addr.to_string(); + let s = s + .trim_start_matches("bc1") + .trim_start_matches("tb1") + .trim_start_matches("bcrt1"); + // 26 27 34 42 62 -- 14..72 + // TODO: Do address chunking + f.write_str(&s) + } + } + } +} + +impl FromStr for ChainNet { + type Err = InvoiceParseError; + + fn from_str(s: &str) -> Result { + match s.to_lowercase() { + x if ChainNet::BitcoinMainnet.to_string() == x => Ok(ChainNet::BitcoinMainnet), + x if ChainNet::BitcoinTestnet.to_string() == x => Ok(ChainNet::BitcoinTestnet), + x if ChainNet::BitcoinSignet.to_string() == x => Ok(ChainNet::BitcoinSignet), + x if ChainNet::BitcoinRegtest.to_string() == x => Ok(ChainNet::BitcoinRegtest), + x if ChainNet::LiquidMainnet.to_string() == x => Ok(ChainNet::BitcoinMainnet), + x if ChainNet::LiquidTestnet.to_string() == x => Ok(ChainNet::LiquidTestnet), + _ => Err(InvoiceParseError::Beneficiary(s.to_owned())), + } + } +} + +impl FromStr for XChainNet { + type Err = InvoiceParseError; + + fn from_str(s: &str) -> Result { + let Some((cn, beneficiary)) = s.split_once(':') else { + return Err(InvoiceParseError::Beneficiary(s.to_owned())); + }; + let cn = ChainNet::from_str(cn)?; + if let Ok(seal) = SecretSeal::from_str(beneficiary) { + return Ok(XChainNet::with(cn, Beneficiary::BlindedSeal(seal))); + } + + let prefix = match cn { + ChainNet::BitcoinMainnet | ChainNet::LiquidMainnet => "bc", + ChainNet::BitcoinTestnet | ChainNet::BitcoinSignet | ChainNet::LiquidTestnet => "tb", + ChainNet::BitcoinRegtest => "bcrt", + }; + let addr = format!("{prefix}1{beneficiary}"); + let payload = Address::from_str(&addr) + .map_err(|_| InvoiceParseError::Beneficiary(s.to_owned()))? + .payload; + Ok(XChainNet::with(cn, Beneficiary::WitnessVout(payload))) + } +} + impl Display for RgbInvoice { fn fmt(&self, f: &mut Formatter) -> fmt::Result { let amt = self.owned_state.to_string(); @@ -263,9 +320,6 @@ impl FromStr for RgbInvoice { let mut path = uri.path().segments(); - let mut network = None; - let mut address_network = None; - let Some(contract_id_str) = path.next() else { return Err(InvoiceParseError::ContractMissed); }; @@ -304,22 +358,7 @@ impl FromStr for RgbInvoice { _ => unreachable!(), }; - let beneficiary = match ( - XChain::::from_str(beneficiary_str), - Address::from_str(beneficiary_str), - ) { - (Ok(seal), Err(_)) => Beneficiary::BlindedSeal(seal), - (Err(_), Ok(addr)) => { - address_network = Some(addr.network); - Beneficiary::WitnessVoutBitcoin(addr) - } - (Err(_), Err(_)) => { - return Err(InvoiceParseError::Beneficiary(beneficiary_str.to_owned())); - } - (Ok(_), Ok(_)) => { - panic!("found a string which is both valid bitcoin address and UTXO blind seal") - } - }; + let beneficiary = XChainNet::::from_str(beneficiary_str)?; let mut query_params = map_query_params(&uri)?; @@ -345,21 +384,6 @@ impl FromStr for RgbInvoice { expiry = Some(timestamp); } - if let Some(nw) = query_params.remove(NETWORK) { - let nw = Network::from_str(&nw)?; - if let Some(an) = address_network { - if an.is_testnet() != nw.is_testnet() { - return Err(InvoiceParseError::NetworkMismatch(an, nw)); - } - } - } else if let Some(an) = address_network { - network = Some(match an { - AddressNetwork::Mainnet => Network::Mainnet, - AddressNetwork::Testnet => Network::Testnet3, - AddressNetwork::Regtest => Network::Regtest, - }) - } - Ok(RgbInvoice { transports, contract, @@ -368,7 +392,6 @@ impl FromStr for RgbInvoice { assignment: None, beneficiary, owned_state: value, - network, expiry, unknown_query: query_params, }) @@ -406,30 +429,30 @@ mod test { fn parse() { // all path parameters let invoice_str = "rgb:2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/RGB20/\ - 100+utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb"; + 100+bc:utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb"; let invoice = RgbInvoice::from_str(invoice_str).unwrap(); assert_eq!(invoice.to_string(), invoice_str); assert_eq!(format!("{invoice:#}"), invoice_str.replace('-', "")); // no amount - let invoice_str = "rgb:2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/RGB20/\ + let invoice_str = "rgb:2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/RGB20/bc:\ utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb"; let invoice = RgbInvoice::from_str(invoice_str).unwrap(); assert_eq!(invoice.to_string(), invoice_str); // no contract ID let invoice_str = - "rgb:~/RGB20/utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb"; + "rgb:~/RGB20/bc:utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb"; let invoice = RgbInvoice::from_str(invoice_str).unwrap(); assert_eq!(invoice.to_string(), invoice_str); // no contract ID nor iface - let invoice_str = "rgb:~/~/utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb"; + let invoice_str = "rgb:~/~/bc:utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb"; let invoice = RgbInvoice::from_str(invoice_str).unwrap(); assert_eq!(invoice.to_string(), invoice_str); // contract ID provided but no iface - let invoice_str = "rgb:2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/~/utxob:\ + let invoice_str = "rgb:2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/~/bc:utxob:\ egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb"; let result = RgbInvoice::from_str(invoice_str); assert!(matches!(result, Err(InvoiceParseError::ContractIdNoIface))); @@ -437,7 +460,7 @@ mod test { // invalid contract ID let invalid_contract_id = "invalid"; let invoice_str = format!( - "rgb:{invalid_contract_id}/RGB20/utxob:\ + "rgb:{invalid_contract_id}/RGB20/bc:utxob:\ egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb" ); let result = RgbInvoice::from_str(&invoice_str); @@ -446,48 +469,49 @@ mod test { // with expiration let invoice_str = "rgb:2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/RGB20/\ - 100+utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ + 100+bc:utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ expiry=1682086371"; let invoice = RgbInvoice::from_str(invoice_str).unwrap(); assert_eq!(invoice.to_string(), invoice_str); // bad expiration let invoice_str = "rgb:2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/RGB20/\ - 100+utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ + 100+bc:utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ expiry=six"; let result = RgbInvoice::from_str(invoice_str); assert!(matches!(result, Err(InvoiceParseError::InvalidExpiration(_)))); // with bad query parameter let invoice_str = "rgb:2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/RGB20/\ - 100+utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?expiry"; + 100+bc:utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ + expiry"; let result = RgbInvoice::from_str(invoice_str); assert!(matches!(result, Err(InvoiceParseError::InvalidQueryParam(_)))); // with an unknown query parameter let invoice_str = "rgb:2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/RGB20/\ - 100+utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ + 100+bc:utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ unknown=new"; let invoice = RgbInvoice::from_str(invoice_str).unwrap(); assert_eq!(invoice.to_string(), invoice_str); // with two unknown query parameters let invoice_str = "rgb:2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/RGB20/\ - 100+utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ + 100+bc:utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ unknown=new&another=new"; let invoice = RgbInvoice::from_str(invoice_str).unwrap(); assert_eq!(invoice.to_string(), invoice_str); // with expiration and an unknown query parameter let invoice_str = "rgb:2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/RGB20/\ - 100+utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ + 100+bc:utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ expiry=1682086371&unknown=new"; let invoice = RgbInvoice::from_str(invoice_str).unwrap(); assert_eq!(invoice.to_string(), invoice_str); // with an unknown query parameter containing percent-encoded text let invoice_base = "rgb:2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/RGB20/\ - 100+utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?"; + 100+bc:utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?"; let query_key_encoded = ":@-%20%23"; let query_key_decoded = ":@- #"; let query_val_encoded = "?/.%26%3D"; @@ -503,41 +527,41 @@ mod test { ); // no scheme - let invoice_str = "2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/~/utxob:\ + let invoice_str = "2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/~/bc:utxob:\ egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb"; let result = RgbInvoice::from_str(invoice_str); assert!(matches!(result, Err(InvoiceParseError::Invalid))); // invalid scheme - let invoice_str = "bad:2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/~/utxob:\ + let invoice_str = "bad:2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/~/bc:utxob:\ egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb"; let result = RgbInvoice::from_str(invoice_str); assert!(matches!(result, Err(InvoiceParseError::InvalidScheme(_)))); // empty transport endpoint specification let invoice_str = "rgb:2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/RGB20/\ - 100+utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ + 100+bc:utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ endpoints="; let result = RgbInvoice::from_str(invoice_str); assert!(matches!(result, Err(InvoiceParseError::InvalidQueryParam(_)))); // invalid transport endpoint specification let invoice_str = "rgb:2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/RGB20/\ - 100+utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ + 100+bc:utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ endpoints=bad"; let result = RgbInvoice::from_str(invoice_str); assert!(matches!(result, Err(InvoiceParseError::InvalidQueryParam(_)))); // invalid transport variant let invoice_str = "rgb:2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/RGB20/\ - 100+utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ + 100+bc:utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ endpoints=rpca://host.example.com"; let result = RgbInvoice::from_str(invoice_str); assert!(matches!(result, Err(InvoiceParseError::InvalidQueryParam(_)))); // rgb-rpc variant let invoice_str = "rgb:2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/RGB20/\ - 100+utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ + 100+bc:utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ endpoints=rpc://host.example.com"; let invoice = RgbInvoice::from_str(invoice_str).unwrap(); assert_eq!(invoice.transports, vec![RgbTransport::JsonRpc { @@ -548,7 +572,7 @@ mod test { // rgb-rpc variant, host containing authentication, "-" characters and port let invoice_str = "rgb:2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/RGB20/\ - 100+utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ + 100+bc:utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ endpoints=rpcs://user:pass@host-1.ex-ample.com:1234"; let invoice = RgbInvoice::from_str(invoice_str).unwrap(); assert_eq!(invoice.transports, vec![RgbTransport::JsonRpc { @@ -559,7 +583,7 @@ mod test { // rgb-rpc variant, IPv6 host let invoice_str = "rgb:2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/RGB20/\ - 100+utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ + 100+bc:utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ endpoints=rpcs://%5B2001:db8::1%5D:1234"; let invoice = RgbInvoice::from_str(invoice_str).unwrap(); assert_eq!(invoice.transports, vec![RgbTransport::JsonRpc { @@ -570,21 +594,21 @@ mod test { // rgb-rpc variant with missing host let invoice_str = "rgb:2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/RGB20/\ - 100+utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ + 100+bc:utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ endpoints=rpc://"; let result = RgbInvoice::from_str(invoice_str); assert!(matches!(result, Err(InvoiceParseError::InvalidQueryParam(_)))); // rgb-rpc variant with invalid separator let invoice_str = "rgb:2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/RGB20/\ - 100+utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ + 100+bc:utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ endpoints=rpc/host.example.com"; let result = RgbInvoice::from_str(invoice_str); assert!(matches!(result, Err(InvoiceParseError::InvalidQueryParam(_)))); // rgb-rpc variant with invalid transport host specification let invoice_str = "rgb:2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/RGB20/\ - 100+utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ + 100+bc:utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ endpoints=rpc://ho]t"; let result = RgbInvoice::from_str(invoice_str); assert!(matches!(result, Err(InvoiceParseError::Uri(_)))); @@ -592,7 +616,7 @@ mod test { // rgb+http variant let invoice_str = "rgb:\ 2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/RGB20/\ - 100+utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?endpoints=https://\ + 100+bc:utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?endpoints=https://\ host.example.com"; let invoice = RgbInvoice::from_str(invoice_str).unwrap(); let transports = vec![RgbTransport::RestHttp { @@ -604,7 +628,7 @@ mod test { // rgb+ws variant let invoice_str = "rgb:2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/RGB20/\ - 100+utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ + 100+bc:utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?\ endpoints=wss://host.example.com"; let invoice = RgbInvoice::from_str(invoice_str).unwrap(); let transports = vec![RgbTransport::WebSockets { @@ -619,7 +643,7 @@ mod test { // multiple transports let invoice_str = "rgb:\ 2WBcas9-yjzEvGufY-9GEgnyMj7-beMNMWA8r-sPHtV1nPU-TMsGMQX/RGB20/\ - 100+utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?endpoints=rpcs://\ + 100+bc:utxob:egXsFnw-5Eud7WKYn-7DVQvcPbc-rR69YmgmG-veacwmUFo-uMFKFb?endpoints=rpcs://\ host1.example.com,http://host2.example.com,ws://host3.example.com"; let invoice = RgbInvoice::from_str(invoice_str).unwrap(); let transports = vec![ diff --git a/src/persistence/inventory.rs b/src/persistence/inventory.rs index 4ea35eb7..9c85930c 100644 --- a/src/persistence/inventory.rs +++ b/src/persistence/inventory.rs @@ -774,16 +774,20 @@ pub trait Inventory: Deref { .assignments_type(&assignment_name) .ok_or(BuilderError::InvalidStateField(assignment_name.clone()))?; - let beneficiary = match (invoice.beneficiary, beneficiary_vout) { - (Beneficiary::BlindedSeal(seal), _) => BuilderSeal::Concealed(seal), - (Beneficiary::WitnessVoutBitcoin(_), Some(vout)) => { - BuilderSeal::Revealed(XChain::Bitcoin(GraphSeal::with_blinded_vout( + let layer1 = invoice.beneficiary.chain_network().layer1(); + let beneficiary = match (invoice.beneficiary.into_inner(), beneficiary_vout) { + (Beneficiary::BlindedSeal(seal), _) => { + BuilderSeal::Concealed(XChain::with(layer1, seal)) + } + (Beneficiary::WitnessVout(_), Some(vout)) => BuilderSeal::Revealed(XChain::with( + layer1, + GraphSeal::with_blinded_vout( method, vout, seal_blinder(contract_id, assignment_id), - ))) - } - (Beneficiary::WitnessVoutBitcoin(_), None) => { + ), + )), + (Beneficiary::WitnessVout(_), None) => { return Err(ComposeError::NoBeneficiaryOutput); } }; From 1c4749ad6aa780930063e54e2e8385af83521b34 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 30 Dec 2023 01:33:25 +0100 Subject: [PATCH 03/11] chore: simplify converting output seals to outpoints --- Cargo.lock | 10 +++++----- src/containers/partials.rs | 7 +------ src/interface/contract.rs | 2 +- src/persistence/inventory.rs | 10 +++++----- src/persistence/stock.rs | 16 +++++++++------- 5 files changed, 21 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c75820af..e0333a13 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -218,7 +218,7 @@ dependencies = [ [[package]] name = "bp-consensus" version = "0.11.0-beta.3" -source = "git+https://github.com/BP-WG/bp-core?branch=v0.11#cbc896d075772a7b4eb620cd8c76cae86ff331c1" +source = "git+https://github.com/BP-WG/bp-core?branch=v0.11#1d7b50834dc40d84b093ede000de9ad38a9e0996" dependencies = [ "amplify", "chrono", @@ -232,7 +232,7 @@ dependencies = [ [[package]] name = "bp-core" version = "0.11.0-beta.2" -source = "git+https://github.com/BP-WG/bp-core?branch=v0.11#cbc896d075772a7b4eb620cd8c76cae86ff331c1" +source = "git+https://github.com/BP-WG/bp-core?branch=v0.11#1d7b50834dc40d84b093ede000de9ad38a9e0996" dependencies = [ "amplify", "bp-consensus", @@ -248,7 +248,7 @@ dependencies = [ [[package]] name = "bp-dbc" version = "0.11.0-beta.2" -source = "git+https://github.com/BP-WG/bp-core?branch=v0.11#cbc896d075772a7b4eb620cd8c76cae86ff331c1" +source = "git+https://github.com/BP-WG/bp-core?branch=v0.11#1d7b50834dc40d84b093ede000de9ad38a9e0996" dependencies = [ "amplify", "base85", @@ -274,7 +274,7 @@ dependencies = [ [[package]] name = "bp-seals" version = "0.11.0-beta.2" -source = "git+https://github.com/BP-WG/bp-core?branch=v0.11#cbc896d075772a7b4eb620cd8c76cae86ff331c1" +source = "git+https://github.com/BP-WG/bp-core?branch=v0.11#1d7b50834dc40d84b093ede000de9ad38a9e0996" dependencies = [ "amplify", "baid58", @@ -649,7 +649,7 @@ dependencies = [ [[package]] name = "rgb-core" version = "0.11.0-beta.3" -source = "git+https://github.com/RGB-WG/rgb-core?branch=v0.11#50cd4191f2b92a86e8d79b1a2d15aa94bd50c367" +source = "git+https://github.com/RGB-WG/rgb-core?branch=v0.11#d598eee90dfa21ef9a34a8376342cffa43dbd4e9" dependencies = [ "aluvm", "amplify", diff --git a/src/containers/partials.rs b/src/containers/partials.rs index 96363219..58abb90a 100644 --- a/src/containers/partials.rs +++ b/src/containers/partials.rs @@ -28,7 +28,6 @@ use std::vec; use amplify::confinement; use amplify::confinement::{Confined, U24}; use bp::seals::txout::CloseMethod; -use bp::Outpoint; use commit_verify::mpc; use rgb::{ ContractId, OpId, Operation, Transition, TransitionBundle, TxoSeal, XAnchor, XOutputSeal, @@ -154,11 +153,7 @@ impl TransitionInfo { seals: impl AsRef<[XOutputSeal]>, ) -> Result { let inputs = Confined::, 1, U24>::try_from_iter( - seals - .as_ref() - .iter() - .copied() - .map(|seal| seal.map(Outpoint::from)), + seals.as_ref().iter().copied().map(XOutpoint::from), )?; let methods = seals .as_ref() diff --git a/src/interface/contract.rs b/src/interface/contract.rs index a8bfa751..f2eec52a 100644 --- a/src/interface/contract.rs +++ b/src/interface/contract.rs @@ -233,7 +233,7 @@ impl ContractIface { .fungibles() .iter() .filter(|outp| outp.opout.ty == type_id) - .filter(|outp| filter.include_output(outp.seal.map(Outpoint::from))) + .filter(|outp| filter.include_output(outp.seal)) .map(FungibleAllocation::from); Ok(LargeVec::try_from_iter(state).expect("same or smaller collection size")) } diff --git a/src/persistence/inventory.rs b/src/persistence/inventory.rs index 9c85930c..f9ed2d82 100644 --- a/src/persistence/inventory.rs +++ b/src/persistence/inventory.rs @@ -40,7 +40,7 @@ use strict_encoding::TypeName; use crate::accessors::{BundleExt, MergeRevealError, RevealError}; use crate::containers::{ Batch, Bindle, BuilderSeal, Cert, Consignment, ContentId, Contract, Fascia, Terminal, - TerminalSeal, Transfer, TransitionInfo, + TerminalSeal, Transfer, TransitionInfo, XOutpoint, }; use crate::interface::{ BuilderError, ContractIface, Iface, IfaceId, IfaceImpl, IfacePair, IfaceWrapper, @@ -541,10 +541,10 @@ pub trait Inventory: Deref { ) -> Result, InventoryError>; #[allow(clippy::type_complexity)] - fn state_for_outputs( + fn state_for_outpoints( &self, contract_id: ContractId, - outputs: impl IntoIterator>, + outpoints: impl IntoIterator>, ) -> Result, InventoryError>; fn store_seal_secret( @@ -796,7 +796,7 @@ pub trait Inventory: Deref { let mut main_inputs = MediumVec::::new(); let mut sum_inputs = 0u64; for ((opout, output), mut state) in - self.state_for_outputs(contract_id, prev_outputs.iter().cloned())? + self.state_for_outpoints(contract_id, prev_outputs.iter().cloned())? { main_builder = main_builder.add_input(opout, state.clone())?; main_inputs.push(output)?; @@ -850,7 +850,7 @@ pub trait Inventory: Deref { spent_state .entry(id) .or_default() - .extend(self.state_for_outputs(id, [output])?); + .extend(self.state_for_outpoints(id, [output])?); } } // Construct blank transitions diff --git a/src/persistence/stock.rs b/src/persistence/stock.rs index 82097323..2f566273 100644 --- a/src/persistence/stock.rs +++ b/src/persistence/stock.rs @@ -34,7 +34,9 @@ use rgb::{ }; use strict_encoding::{StrictDeserialize, StrictSerialize}; -use crate::containers::{Bindle, Cert, Consignment, ContentId, Contract, TerminalSeal, Transfer}; +use crate::containers::{ + Bindle, Cert, Consignment, ContentId, Contract, TerminalSeal, Transfer, XOutpoint, +}; use crate::interface::{ ContractIface, Iface, IfaceId, IfaceImpl, IfacePair, SchemaIfaces, TypedState, }; @@ -641,10 +643,10 @@ impl Inventory for Stock { .collect()) } - fn state_for_outputs( + fn state_for_outpoints( &self, contract_id: ContractId, - outputs: impl IntoIterator>, + outputs: impl IntoIterator>, ) -> Result, InventoryError> { let outputs = outputs .into_iter() @@ -659,7 +661,7 @@ impl Inventory for Stock { let mut res = BTreeMap::new(); for item in history.fungibles() { - if outputs.contains(&item.seal) { + if outputs.contains(&item.seal.into()) { res.insert( (item.opout, item.seal), TypedState::Amount( @@ -672,19 +674,19 @@ impl Inventory for Stock { } for item in history.data() { - if outputs.contains(&item.seal) { + if outputs.contains(&item.seal.into()) { res.insert((item.opout, item.seal), TypedState::Data(item.state.clone())); } } for item in history.rights() { - if outputs.contains(&item.seal) { + if outputs.contains(&item.seal.into()) { res.insert((item.opout, item.seal), TypedState::Void); } } for item in history.attach() { - if outputs.contains(&item.seal) { + if outputs.contains(&item.seal.into()) { res.insert( (item.opout, item.seal), TypedState::Attachment(item.state.clone().into()), From bbe724bc18a92884cf16cb874645ec9b935a56d5 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 30 Dec 2023 01:44:41 +0100 Subject: [PATCH 04/11] invoice: add Beneficiary address_network methods --- invoice/src/invoice.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/invoice/src/invoice.rs b/invoice/src/invoice.rs index 8a36028e..36041558 100644 --- a/invoice/src/invoice.rs +++ b/invoice/src/invoice.rs @@ -85,7 +85,7 @@ impl ChainNet { } } - pub(crate) fn address_network(&self) -> AddressNetwork { + pub fn address_network(&self) -> AddressNetwork { match self { ChainNet::BitcoinMainnet => AddressNetwork::Mainnet, ChainNet::BitcoinTestnet | ChainNet::BitcoinSignet => AddressNetwork::Testnet, @@ -142,6 +142,7 @@ impl XChainNet { } pub fn layer1(&self) -> Layer1 { self.chain_network().layer1() } + pub fn address_network(&self) -> AddressNetwork { self.chain_network().address_network() } pub fn is_prod(&self) -> bool { self.chain_network().is_prod() } } @@ -170,6 +171,7 @@ pub struct RgbInvoice { impl RgbInvoice { pub fn chain_network(&self) -> ChainNet { self.beneficiary.chain_network() } + pub fn address_network(&self) -> AddressNetwork { self.beneficiary.address_network() } pub fn layer1(&self) -> Layer1 { self.beneficiary.layer1() } pub fn is_prod(&self) -> bool { self.beneficiary.is_prod() } } From 43d72c6d005b954c4207028758d6d9a5d27f72f2 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 30 Dec 2023 01:47:20 +0100 Subject: [PATCH 05/11] invoice: export chain types --- invoice/src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/invoice/src/lib.rs b/invoice/src/lib.rs index 20a79a10..e0dfdffb 100644 --- a/invoice/src/lib.rs +++ b/invoice/src/lib.rs @@ -39,6 +39,8 @@ pub use amount::{Amount, CoinAmount, Precision}; pub use builder::RgbInvoiceBuilder; pub use parse::{InvoiceParseError, TransportParseError}; -pub use crate::invoice::{Beneficiary, InvoiceState, RgbInvoice, RgbTransport}; +pub use crate::invoice::{ + Beneficiary, ChainNet, InvoiceState, RgbInvoice, RgbTransport, XChainNet, +}; pub const LIB_NAME_RGB_CONTRACT: &str = "RGBContract"; From 1ce497f56201404a7af1f666c2869fa853baf0dd Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 30 Dec 2023 01:49:26 +0100 Subject: [PATCH 06/11] invoice: add XCjainNet::bitcoin constructor --- invoice/src/invoice.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/invoice/src/invoice.rs b/invoice/src/invoice.rs index 36041558..08ac103f 100644 --- a/invoice/src/invoice.rs +++ b/invoice/src/invoice.rs @@ -20,7 +20,7 @@ // limitations under the License. use indexmap::IndexMap; -use invoice::{AddressNetwork, AddressPayload}; +use invoice::{AddressNetwork, AddressPayload, Network}; use rgb::{AttachId, ContractId, Layer1, SecretSeal}; use strict_encoding::{FieldName, TypeName}; @@ -119,6 +119,15 @@ impl XChainNet { } } + pub fn bitcoin(network: Network, data: T) -> Self { + match network { + Network::Mainnet => Self::BitcoinMainnet(data), + Network::Testnet3 => Self::BitcoinTestnet(data), + Network::Signet => Self::BitcoinSignet(data), + Network::Regtest => Self::BitcoinRegtest(data), + } + } + pub fn chain_network(&self) -> ChainNet { match self { XChainNet::BitcoinMainnet(_) => ChainNet::BitcoinMainnet, From cfa4f7af871092308269d6e7f5d1d5877b025e5e Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 30 Dec 2023 02:09:08 +0100 Subject: [PATCH 07/11] invoice: improve type name API by builder --- invoice/src/builder.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/invoice/src/builder.rs b/invoice/src/builder.rs index fa5aa69c..b25d338a 100644 --- a/invoice/src/builder.rs +++ b/invoice/src/builder.rs @@ -22,6 +22,7 @@ use std::str::FromStr; use rgb::ContractId; +use strict_encoding::{FieldName, TypeName}; use super::{Beneficiary, InvoiceState, Precision, RgbInvoice, RgbTransport, TransportParseError}; use crate::invoice::XChainNet; @@ -62,18 +63,18 @@ impl RgbInvoiceBuilder { self } - pub fn set_interface(mut self, name: &'static str) -> Self { - self.0.iface = Some(tn!(name)); + pub fn set_interface(mut self, name: impl Into) -> Self { + self.0.iface = Some(name.into()); self } - pub fn set_operation(mut self, name: &'static str) -> Self { - self.0.operation = Some(tn!(name)); + pub fn set_operation(mut self, name: impl Into) -> Self { + self.0.operation = Some(name.into()); self } - pub fn set_assignment(mut self, name: &'static str) -> Self { - self.0.assignment = Some(fname!(name)); + pub fn set_assignment(mut self, name: impl Into) -> Self { + self.0.assignment = Some(name.into()); self } From 8ebb68f7297907220b94e48350037ab4153a569b Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 30 Dec 2023 08:41:35 +0100 Subject: [PATCH 08/11] chore: update dependencies --- Cargo.lock | 40 +++++++++++++++++++++--------------- Cargo.toml | 6 ------ src/containers/mod.rs | 2 +- src/containers/partials.rs | 4 ++-- src/containers/util.rs | 5 +---- src/interface/contract.rs | 3 +-- src/persistence/inventory.rs | 4 ++-- src/persistence/stock.rs | 6 ++---- 8 files changed, 33 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e0333a13..7f4f7b64 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -218,7 +218,8 @@ dependencies = [ [[package]] name = "bp-consensus" version = "0.11.0-beta.3" -source = "git+https://github.com/BP-WG/bp-core?branch=v0.11#1d7b50834dc40d84b093ede000de9ad38a9e0996" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190ac89a2a3c79d5bfb677f48e5393691832c540973341831572edaffdce0881" dependencies = [ "amplify", "chrono", @@ -231,8 +232,9 @@ dependencies = [ [[package]] name = "bp-core" -version = "0.11.0-beta.2" -source = "git+https://github.com/BP-WG/bp-core?branch=v0.11#1d7b50834dc40d84b093ede000de9ad38a9e0996" +version = "0.11.0-beta.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69269d27e32d784e37f7ca7cdf964fe5e30c5bff1ca2e229a118c84c8efdd179" dependencies = [ "amplify", "bp-consensus", @@ -247,8 +249,9 @@ dependencies = [ [[package]] name = "bp-dbc" -version = "0.11.0-beta.2" -source = "git+https://github.com/BP-WG/bp-core?branch=v0.11#1d7b50834dc40d84b093ede000de9ad38a9e0996" +version = "0.11.0-beta.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cef9a98c7ae4f1bb333ad8e55c9d8a91f071c347d35b62e19959faa07572b11" dependencies = [ "amplify", "base85", @@ -273,8 +276,9 @@ dependencies = [ [[package]] name = "bp-seals" -version = "0.11.0-beta.2" -source = "git+https://github.com/BP-WG/bp-core?branch=v0.11#1d7b50834dc40d84b093ede000de9ad38a9e0996" +version = "0.11.0-beta.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d211bb77e320abf4bba6c272fc85d73e5203140ca39e299271f4714d8b6029fe" dependencies = [ "amplify", "baid58", @@ -331,7 +335,8 @@ dependencies = [ [[package]] name = "commit_encoding_derive" version = "0.10.0" -source = "git+https://github.com/LNP-BP/client_side_validation?branch=v0.11#2d3a0a2981409c493067edfc94338088884b1aa7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00033f14d67c4169d588f085ea2faeb7b610cf03a74d42ea09eeba31abef2047" dependencies = [ "amplify", "amplify_syn", @@ -342,8 +347,9 @@ dependencies = [ [[package]] name = "commit_verify" -version = "0.11.0-beta.2" -source = "git+https://github.com/LNP-BP/client_side_validation?branch=v0.11#2d3a0a2981409c493067edfc94338088884b1aa7" +version = "0.11.0-beta.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85e001679b9be6a5df24facdae179e6ba1cffb503c875d691eac024db8d0f8d1" dependencies = [ "amplify", "commit_encoding_derive", @@ -649,7 +655,7 @@ dependencies = [ [[package]] name = "rgb-core" version = "0.11.0-beta.3" -source = "git+https://github.com/RGB-WG/rgb-core?branch=v0.11#d598eee90dfa21ef9a34a8376342cffa43dbd4e9" +source = "git+https://github.com/RGB-WG/rgb-core?branch=v0.11#744560f68518b19eab7ae8135571910282e72e58" dependencies = [ "aluvm", "amplify", @@ -873,17 +879,18 @@ dependencies = [ [[package]] name = "single_use_seals" -version = "0.11.0-beta.2" +version = "0.11.0-beta.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c30647a1342641c45ca7c1dcd5ae7db16533b86744e827c84cfed875db2de3fe" +checksum = "1b14ebe6be1e12070208a6f2ceb49f946d835b1f7dfb809a4db025de8f5ffe0a" dependencies = [ "amplify_derive", ] [[package]] name = "strict_encoding" -version = "2.6.1" -source = "git+https://github.com/strict-types/strict-encoding?branch=phantom#2123237a512bbe28e8e419e7d4f899dfedfa758c" +version = "2.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa76decc8ac190a56ba7857c023b69ed52b781ed974c5a181eac62cdbfc99521" dependencies = [ "amplify", "half", @@ -894,7 +901,8 @@ dependencies = [ [[package]] name = "strict_encoding_derive" version = "2.0.1" -source = "git+https://github.com/strict-types/strict-encoding?branch=phantom#2123237a512bbe28e8e419e7d4f899dfedfa758c" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37064ec285e2a633465eb525c8698eea51373dee889fe310e0d32df8343e7f4f" dependencies = [ "amplify_syn", "heck", diff --git a/Cargo.toml b/Cargo.toml index 1b04e577..351cbee2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -93,10 +93,4 @@ wasm-bindgen-test = "0.3" features = [ "all" ] [patch.crates-io] -strict_encoding = { git = "https://github.com/strict-types/strict-encoding", branch = "phantom" } -commit_verify = { git = "https://github.com/LNP-BP/client_side_validation", branch = "v0.11" } -bp-consensus = { git = "https://github.com/BP-WG/bp-core", branch = "v0.11" } -bp-dbc = { git = "https://github.com/BP-WG/bp-core", branch = "v0.11" } -bp-seals = { git = "https://github.com/BP-WG/bp-core", branch = "v0.11" } -bp-core = { git = "https://github.com/BP-WG/bp-core", branch = "v0.11" } rgb-core = { git = "https://github.com/RGB-WG/rgb-core", branch = "v0.11" } diff --git a/src/containers/mod.rs b/src/containers/mod.rs index 057daffc..c53bcbd1 100644 --- a/src/containers/mod.rs +++ b/src/containers/mod.rs @@ -46,4 +46,4 @@ pub use disclosure::Disclosure; pub use indexed::IndexedConsignment; pub use partials::{Batch, CloseMethodSet, Fascia, TransitionInfo}; pub use seal::{BuilderSeal, TerminalSeal, VoutSeal}; -pub use util::{ContainerVer, Terminal, XOutpoint}; +pub use util::{ContainerVer, Terminal}; diff --git a/src/containers/partials.rs b/src/containers/partials.rs index 58abb90a..1b0c5704 100644 --- a/src/containers/partials.rs +++ b/src/containers/partials.rs @@ -30,11 +30,11 @@ use amplify::confinement::{Confined, U24}; use bp::seals::txout::CloseMethod; use commit_verify::mpc; use rgb::{ - ContractId, OpId, Operation, Transition, TransitionBundle, TxoSeal, XAnchor, XOutputSeal, + ContractId, OpId, Operation, Transition, TransitionBundle, TxoSeal, XAnchor, XOutpoint, + XOutputSeal, }; use strict_encoding::{StrictDeserialize, StrictDumb, StrictSerialize}; -use crate::containers::XOutpoint; use crate::LIB_NAME_RGB_STD; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] diff --git a/src/containers/util.rs b/src/containers/util.rs index 80cb4c6b..c0063130 100644 --- a/src/containers/util.rs +++ b/src/containers/util.rs @@ -20,8 +20,7 @@ // limitations under the License. use amplify::confinement::SmallOrdSet; -use bp::{Outpoint, Tx}; -use rgb::XChain; +use bp::Tx; use super::TerminalSeal; use crate::LIB_NAME_RGB_STD; @@ -70,5 +69,3 @@ pub enum ContainerVer { #[default] V2 = 2, } - -pub type XOutpoint = XChain; diff --git a/src/interface/contract.rs b/src/interface/contract.rs index f2eec52a..e001ac4f 100644 --- a/src/interface/contract.rs +++ b/src/interface/contract.rs @@ -26,13 +26,12 @@ use amplify::confinement::{LargeOrdMap, LargeVec, SmallVec}; use bp::Outpoint; use rgb::{ AssetTag, AssignmentType, AttachId, BlindingFactor, ContractId, ContractState, FungibleOutput, - MediaType, RevealedAttach, RevealedData, WitnessId, XOutputSeal, + MediaType, RevealedAttach, RevealedData, WitnessId, XOutpoint, XOutputSeal, }; use strict_encoding::FieldName; use strict_types::typify::TypedVal; use strict_types::{decode, StrictVal}; -use crate::containers::XOutpoint; use crate::interface::{IfaceId, IfaceImpl}; #[derive(Clone, Eq, PartialEq, Debug, Display, Error, From)] diff --git a/src/persistence/inventory.rs b/src/persistence/inventory.rs index f9ed2d82..4ca06e7d 100644 --- a/src/persistence/inventory.rs +++ b/src/persistence/inventory.rs @@ -33,14 +33,14 @@ use invoice::{Beneficiary, InvoiceState, RgbInvoice}; use rgb::{ validation, AnchoredBundle, AssignmentType, BlindingFactor, BundleId, ContractId, GraphSeal, OpId, Operation, Opout, SchemaId, SecretSeal, SubSchema, Transition, TransitionBundle, - WitnessId, XAnchor, XChain, XOutputSeal, + WitnessId, XAnchor, XChain, XOutpoint, XOutputSeal, }; use strict_encoding::TypeName; use crate::accessors::{BundleExt, MergeRevealError, RevealError}; use crate::containers::{ Batch, Bindle, BuilderSeal, Cert, Consignment, ContentId, Contract, Fascia, Terminal, - TerminalSeal, Transfer, TransitionInfo, XOutpoint, + TerminalSeal, Transfer, TransitionInfo, }; use crate::interface::{ BuilderError, ContractIface, Iface, IfaceId, IfaceImpl, IfacePair, IfaceWrapper, diff --git a/src/persistence/stock.rs b/src/persistence/stock.rs index 2f566273..cf7a1483 100644 --- a/src/persistence/stock.rs +++ b/src/persistence/stock.rs @@ -30,13 +30,11 @@ use rgb::{ validation, AnchoredBundle, Assign, AssignmentType, BundleId, ContractHistory, ContractId, ContractState, ExposedState, Extension, Genesis, GenesisSeal, GraphSeal, OpId, Operation, Opout, SecretSeal, SubSchema, Transition, TransitionBundle, TypedAssigns, WitnessAnchor, - WitnessId, XAnchor, XChain, XOutputSeal, + WitnessId, XAnchor, XChain, XOutpoint, XOutputSeal, }; use strict_encoding::{StrictDeserialize, StrictSerialize}; -use crate::containers::{ - Bindle, Cert, Consignment, ContentId, Contract, TerminalSeal, Transfer, XOutpoint, -}; +use crate::containers::{Bindle, Cert, Consignment, ContentId, Contract, TerminalSeal, Transfer}; use crate::interface::{ ContractIface, Iface, IfaceId, IfaceImpl, IfacePair, SchemaIfaces, TypedState, }; From 2880822daadd3ab9fbbe7ac5ec091a71fd367cfb Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 30 Dec 2023 08:44:53 +0100 Subject: [PATCH 09/11] containers: add BuilderSeal converter from BlindSeal --- src/containers/seal.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/containers/seal.rs b/src/containers/seal.rs index 6839c6b8..ad0c0ea5 100644 --- a/src/containers/seal.rs +++ b/src/containers/seal.rs @@ -21,7 +21,7 @@ #![doc = include_str!("seals.md")] -use bp::seals::txout::CloseMethod; +use bp::seals::txout::{BlindSeal, CloseMethod, SealTxid}; use bp::secp256k1::rand::{thread_rng, RngCore}; use bp::Vout; use commit_verify::Conceal; @@ -171,3 +171,7 @@ pub enum BuilderSeal { #[from] Concealed(XChain), } + +impl From>> for BuilderSeal> { + fn from(seal: XChain>) -> Self { BuilderSeal::Revealed(seal) } +} From ff65e47c761621ecb0e9167ae285d21c20603806 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 30 Dec 2023 08:58:15 +0100 Subject: [PATCH 10/11] chore: update dependencies --- Cargo.lock | 11 ++++++----- Cargo.toml | 15 ++++++--------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7f4f7b64..b603d856 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -654,8 +654,9 @@ dependencies = [ [[package]] name = "rgb-core" -version = "0.11.0-beta.3" -source = "git+https://github.com/RGB-WG/rgb-core?branch=v0.11#744560f68518b19eab7ae8135571910282e72e58" +version = "0.11.0-beta.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb0581f9bc33b509400aa9225d2308dfd45af413a4fe38f7c4b823a7e09e6036" dependencies = [ "aluvm", "amplify", @@ -674,7 +675,7 @@ dependencies = [ [[package]] name = "rgb-invoice" -version = "0.11.0-beta.3" +version = "0.11.0-beta.4" dependencies = [ "amplify", "baid58", @@ -691,7 +692,7 @@ dependencies = [ [[package]] name = "rgb-std" -version = "0.11.0-beta.3" +version = "0.11.0-beta.4" dependencies = [ "amplify", "baid58", @@ -713,7 +714,7 @@ dependencies = [ [[package]] name = "rgb-stl" -version = "0.11.0-beta.3" +version = "0.11.0-beta.4" dependencies = [ "rgb-std", "strict_types", diff --git a/Cargo.toml b/Cargo.toml index 351cbee2..a0617dc1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ default-members = [ resolver = "2" [workspace.package] -version = "0.11.0-beta.3" +version = "0.11.0-beta.4" authors = ["Dr Maxim Orlovsky "] homepage = "https://github.com/RGB-WG" repository = "https://github.com/RGB-WG/rgb-wallet" @@ -24,12 +24,12 @@ license = "Apache-2.0" [workspace.dependencies] amplify = "4.5.0" baid58 = "0.4.4" -strict_encoding = "2.6.1" +strict_encoding = "2.6.2" strict_types = "1.6.3" -commit_verify = { version = "0.11.0-beta.2", features = ["stl"] } -bp-core = { version = "0.11.0-beta.2", features = ["stl"] } +commit_verify = { version = "0.11.0-beta.3", features = ["stl"] } +bp-core = { version = "0.11.0-beta.3", features = ["stl"] } bp-invoice = { version = "0.11.0-beta.3" } -rgb-core = { version = "0.11.0-beta.3", features = ["stl"] } +rgb-core = { version = "0.11.0-beta.4", features = ["stl"] } indexmap = "2.0.2" serde_crate = { package = "serde", version = "1", features = ["derive"] } @@ -58,7 +58,7 @@ strict_types = { workspace = true } commit_verify = { workspace = true } bp-core = { workspace = true } rgb-core = { workspace = true } -rgb-invoice = { version = "0.11.0-beta.3", path = "invoice" } +rgb-invoice = { version = "0.11.0-beta.4", path = "invoice" } baid58 = { workspace = true } base85 = "=2.0.0" chrono = "0.4.31" @@ -91,6 +91,3 @@ wasm-bindgen-test = "0.3" [package.metadata.docs.rs] features = [ "all" ] - -[patch.crates-io] -rgb-core = { git = "https://github.com/RGB-WG/rgb-core", branch = "v0.11" } From 099c5873dc726893341028b0663a0d18c12e9fe2 Mon Sep 17 00:00:00 2001 From: Dr Maxim Orlovsky Date: Sat, 30 Dec 2023 08:59:35 +0100 Subject: [PATCH 11/11] chore: fix clippy lints --- invoice/src/parse.rs | 2 +- src/persistence/inventory.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/invoice/src/parse.rs b/invoice/src/parse.rs index e05a98b9..ad9a888b 100644 --- a/invoice/src/parse.rs +++ b/invoice/src/parse.rs @@ -212,7 +212,7 @@ impl Display for XChainNet { .trim_start_matches("bcrt1"); // 26 27 34 42 62 -- 14..72 // TODO: Do address chunking - f.write_str(&s) + f.write_str(s) } } } diff --git a/src/persistence/inventory.rs b/src/persistence/inventory.rs index 4ca06e7d..b2fab589 100644 --- a/src/persistence/inventory.rs +++ b/src/persistence/inventory.rs @@ -716,6 +716,7 @@ pub trait Inventory: Deref { /// Composes a batch of state transitions updating state for the provided /// set of previous outputs, satisfying requirements of the invoice, paying /// the change back and including the necessary blank state transitions. + #[allow(clippy::too_many_arguments)] fn compose_deterministic( &self, invoice: &RgbInvoice,