Skip to content

Commit

Permalink
runtime, cli: payment workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-orlovsky committed Dec 18, 2023
1 parent e03adc6 commit 7ad91e6
Show file tree
Hide file tree
Showing 10 changed files with 223 additions and 112 deletions.
64 changes: 27 additions & 37 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ bp-esplora = "0.11.0-beta.1"
descriptors = "0.11.0-beta.1"
psbt = { version = "0.11.0-beta.1", features = ["client-side-validation"] }
rgb-std = { version = "0.11.0-beta.2", features = ["fs"] }
rgb-psbt = { version = "0.11.0-alpha.2", path = "psbt" }
indexmap = "2.0.2"
chrono = "0.4.31"
serde_crate = { package = "serde", version = "1", features = ["derive"] }
Expand Down Expand Up @@ -70,8 +71,8 @@ bp-std = { workspace = true }
bp-wallet = { workspace = true, features = ["fs"] }
bp-esplora = { workspace = true, optional = true }
descriptors = { workspace = true }
psbt = { workspace = true }
rgb-std = { workspace = true }
rgb-psbt = { workspace = true }
rgb-persist-fs = { version = "0.11.0-alpha", path = "fs" }
indexmap = { workspace = true }
chrono = { workspace = true }
Expand Down
76 changes: 43 additions & 33 deletions cli/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,22 @@
// limitations under the License.

use std::fs;
use std::fs::File;
use std::path::PathBuf;
use std::str::FromStr;

use amplify::confinement::U16;
use bp_util::{Config, Exec};
use bpstd::{Sats, Txid};
use bpwallet::{Invoice, TxParams};
use rgb_rt::{DescriptorRgb, RgbDescr, RgbKeychain, RuntimeError};
use psbt::PsbtVer;
use rgb_rt::{DescriptorRgb, RgbDescr, RgbKeychain, RuntimeError, TransferParams};
use rgbstd::containers::{Bindle, Transfer, UniversalBindle};
use rgbstd::contract::{ContractId, GenesisSeal, GraphSeal, StateType};
use rgbstd::interface::{ContractBuilder, FilterExclude, IfaceId, SchemaIfaces};
use rgbstd::invoice::{Beneficiary, InvoiceState, RgbInvoice, RgbTransport};
use rgbstd::persistence::{Inventory, Stash};
use rgbstd::schema::SchemaId;
use rgbstd::SealDefinition;
use rgbstd::XSeal;
use seals::txout::{CloseMethod, ExplicitSeal};
use strict_types::encoding::{FieldName, TypeName};
use strict_types::StrictVal;
Expand Down Expand Up @@ -139,10 +140,19 @@ pub enum Command {
/// Transfer RGB assets
#[display("transfer")]
Transfer {
/// Encode PSBT as V2
#[clap(short = '2')]
v2: bool,

/// Method for single-use-seals
#[clap(long, default_value = "tapret1st")]
method: CloseMethod,

/// Amount of satoshis which should be paid to the address-based
/// beneficiary
#[clap(long, default_value = "2000")]
sats: Sats,

/// Invoice data
invoice: RgbInvoice,

Expand Down Expand Up @@ -295,7 +305,7 @@ impl Exec for RgbArgs {
contract,
file,
} => {
let mut runtime = self.rgb_runtime(&config)?;
let runtime = self.rgb_runtime(&config)?;
let bindle = runtime
.export_contract(*contract)
.map_err(|err| err.to_string())?;
Expand Down Expand Up @@ -471,7 +481,7 @@ impl Exec for RgbArgs {
.expect("seal must be a string");
let seal =
ExplicitSeal::<Txid>::from_str(seal).expect("invalid seal definition");
let seal = GenesisSeal::from(seal);
let seal = XSeal::Bitcoin(GenesisSeal::from(seal));

// Workaround for borrow checker:
let field_name =
Expand Down Expand Up @@ -537,15 +547,15 @@ impl Exec for RgbArgs {
.next()
.expect("no addresses left")
.addr;
Beneficiary::WitnessUtxo(addr)
Beneficiary::WitnessVoutBitcoin(addr)
}
(_, Some(outpoint)) => {
let seal = GraphSeal::new(
runtime.wallet().seal_close_method(),
outpoint.txid,
outpoint.vout,
);
runtime.store_seal_secret(SealDefinition::Bitcoin(seal))?;
runtime.store_seal_secret(XSeal::Bitcoin(seal))?;
Beneficiary::BlindedSeal(seal.to_concealed_seal())
}
};
Expand All @@ -565,40 +575,36 @@ impl Exec for RgbArgs {
}
#[allow(unused_variables)]
Command::Transfer {
v2,
method,
invoice,
fee,
psbt: psbt_filename,
sats,
psbt: psbt_file,
consignment: out_file,
} => {
// 1. BP Wallet: Do coin selection (using Layer2 components)
// 2. BP Wallet: Construct PSBT prototype (no state transitions)
// ... complete PSBT structure updates in multi-party protocols
// 3. RGB Std: Prepare stencil - main state transition and blank state
// transitions
// 4. RGB PSBT: Embed stencil into PSBT
// ... complete PSBT client-side updates in multi-party protocols
// 5. RGB PSBT: Anchorize PSBT, extract disclosure
// 6. RGB Std: Merge disclosure into the stash, cache and index
// 7. RGB Std: Prepare consignment

let mut runtime = self.rgb_runtime(&config)?;

// TODO: Support lock time and RBFs
let params = TxParams::with(*fee);
let params = TransferParams::with(*fee, *sats);

eprint!("Constructing PSBT ... ");
let mut psbt = runtime
.wallet_mut()
.construct_psbt(coins, Invoice, params)?;
eprintln!("success");

eprint!("Constructing transfer consignment ... ");
let transfer = runtime
.pay(invoice, &mut psbt, method)
let (psbt, meta, transfer) = runtime
.pay(invoice, *method, params)
.map_err(|err| err.to_string())?;

transfer.save(&out_file)?;
eprintln!("success");

let ver = if *v2 { PsbtVer::V2 } else { PsbtVer::V0 };
eprintln!("{}", serde_yaml::to_string(&psbt).unwrap());
match psbt_file {
Some(file_name) => {
let mut psbt_file = File::create(file_name)?;
psbt.encode(ver, &mut psbt_file)?;
}
None => match ver {
PsbtVer::V0 => println!("{psbt}"),
PsbtVer::V2 => println!("{psbt:#}"),
},
}
}
Command::Inspect { file, format } => {
let bindle = UniversalBindle::load_file(file)?;
Expand Down Expand Up @@ -651,7 +657,11 @@ impl Exec for RgbArgs {
format!("{root_dir}/stash/geneses/{id}.yaml"),
serde_yaml::to_string(runtime.genesis(id)?)?,
)?;
for (no, suppl) in runtime.contract_suppl(id).into_iter().flatten().enumerate()
for (no, suppl) in runtime
.contract_suppl_all(id)
.into_iter()
.flatten()
.enumerate()
{
fs::write(
format!("{root_dir}/stash/geneses/{id}.suppl.{no:03}.yaml"),
Expand All @@ -665,7 +675,7 @@ impl Exec for RgbArgs {
serde_yaml::to_string(runtime.bundle(id)?)?,
)?;
}
for id in runtime.anchor_ids()? {
for id in runtime.witness_ids()? {
fs::write(
format!("{root_dir}/stash/anchors/{id}.yaml"),
serde_yaml::to_string(runtime.anchor(id)?)?,
Expand Down
10 changes: 5 additions & 5 deletions cli/src/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,20 @@ use std::convert::Infallible;
use bpstd::{Tx, Txid};
use rgbstd::resolvers::ResolveHeight;
use rgbstd::validation::{ResolveTx, TxResolverError};
use rgbstd::{Anchor, Layer1, WitnessAnchor};
use rgbstd::{Layer1, WitnessAnchor, XAnchor};

use crate::RgbArgs;

// TODO: Embed in contract issuance builder
pub struct PanickingResolver;
impl ResolveHeight for PanickingResolver {
type Error = Infallible;
fn resolve_anchor(&mut self, _: &Anchor) -> Result<WitnessAnchor, Self::Error> {
fn resolve_anchor(&mut self, _: &XAnchor) -> Result<WitnessAnchor, Self::Error> {
unreachable!("PanickingResolver must be used only for newly issued contract validation")
}
}
impl ResolveTx for PanickingResolver {
fn resolve_tx(&self, _: Layer1, _: Txid) -> Result<Tx, TxResolverError> {
fn resolve_bp_tx(&self, _: Layer1, _: Txid) -> Result<Tx, TxResolverError> {
unreachable!("PanickingResolver must be used only for newly issued contract validation")
}
}
Expand All @@ -48,12 +48,12 @@ impl RgbArgs {
struct DumbResolver();
impl ResolveHeight for DumbResolver {
type Error = Infallible;
fn resolve_anchor(&mut self, _: &Anchor) -> Result<WitnessAnchor, Self::Error> {
fn resolve_anchor(&mut self, _: &XAnchor) -> Result<WitnessAnchor, Self::Error> {
todo!()
}
}
impl ResolveTx for DumbResolver {
fn resolve_tx(&self, _: Layer1, _: Txid) -> Result<Tx, TxResolverError> { todo!() }
fn resolve_bp_tx(&self, _: Layer1, _: Txid) -> Result<Tx, TxResolverError> { todo!() }
}
DumbResolver::default()
}
Expand Down
2 changes: 1 addition & 1 deletion psbt/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "psbt-rgb"
name = "rgb-psbt"
version = { workspace = true }
description = "Partially signed bitcoin transaction RGB extensions"
keywords = ["bitcoin", "invoices", "rgb", "smart-contracts", "psbt"]
Expand Down
2 changes: 1 addition & 1 deletion psbt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ mod rgb;

use bp::dbc::opret::OpretProof;
use bp::dbc::tapret::TapretProof;
use psbt::{DbcPsbtError, Psbt};
pub use psbt::*;

Check failure on line 29 in psbt/src/lib.rs

View workflow job for this annotation

GitHub Actions / testing

multiple candidates for `rlib` dependency `psbt` found

Check failure on line 29 in psbt/src/lib.rs

View workflow job for this annotation

GitHub Actions / codecov

multiple candidates for `rlib` dependency `psbt` found
use rgbstd::containers::{Batch, Fascia, XchainOutpoint};
use rgbstd::{AnchorSet, XAnchor};

Expand Down
Loading

0 comments on commit 7ad91e6

Please sign in to comment.