mirror of
https://github.com/aljazceru/clArk.git
synced 2025-12-17 21:24:19 +01:00
Fix bug when doing multiple payments
This commit is contained in:
@@ -225,14 +225,14 @@ pub async fn run_round_scheduler(
|
||||
b.ordering(bdk::wallet::tx_builder::TxOrdering::Untouched);
|
||||
b.add_recipient(vtxos_spec.cosign_spk(), vtxos_spec.total_required_value().to_sat());
|
||||
b.add_recipient(connector_output.script_pubkey, connector_output.value);
|
||||
b.fee_rate(bdk::FeeRate::from_sat_per_vb(100.0)); //TODO(stevenroose) fix
|
||||
b.fee_rate(bdk::FeeRate::from_sat_per_vb(10.0)); //TODO(stevenroose) fix
|
||||
b.finish().context("bdk failed to create round tx")?
|
||||
};
|
||||
let round_tx = round_tx_psbt.clone().extract_tx();
|
||||
let vtxos_utxo = OutPoint::new(round_tx.txid(), 0);
|
||||
let conns_utxo = OutPoint::new(round_tx.txid(), 1);
|
||||
|
||||
// Generate nonces and combine with user's nonces.
|
||||
// Generate vtxo nonces and combine with user's nonces.
|
||||
let (sec_vtxo_nonces, pub_vtxo_nonces) = {
|
||||
let mut secs = Vec::with_capacity(nb_nodes);
|
||||
let mut pubs = Vec::with_capacity(nb_nodes);
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use bitcoin::Amount;
|
||||
use anyhow::Context;
|
||||
use bitcoin::{address, Address, Amount};
|
||||
use bitcoin::secp256k1::PublicKey;
|
||||
use clap::Parser;
|
||||
|
||||
@@ -45,6 +46,11 @@ enum Command {
|
||||
amount: Amount,
|
||||
},
|
||||
#[command()]
|
||||
SendOnchain {
|
||||
address: Address<address::NetworkUnchecked>,
|
||||
amount: Amount,
|
||||
},
|
||||
#[command()]
|
||||
Send {
|
||||
pubkey: PublicKey,
|
||||
amount: Amount,
|
||||
@@ -59,8 +65,7 @@ enum Command {
|
||||
DropVtxos {},
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
async fn inner_main() -> anyhow::Result<()> {
|
||||
env_logger::builder()
|
||||
.filter_module("sled", log::LevelFilter::Off)
|
||||
.filter_module("bitcoincore_rpc", log::LevelFilter::Trace)
|
||||
@@ -72,42 +77,44 @@ async fn main() {
|
||||
//TODO(stevenroose) somehow pass this in
|
||||
let mut cfg = Config {
|
||||
network: bitcoin::Network::Regtest,
|
||||
datadir: cli.datadir.canonicalize().expect("canonicalizing path"),
|
||||
datadir: cli.datadir.canonicalize().context("canonicalizing path")?,
|
||||
asp_address: "http://[::1]:35035".parse().unwrap(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// Handle create command differently.
|
||||
if let Command::Create { ref datadir, force } = cli.command {
|
||||
let datadir = if let Some(datadir) = datadir {
|
||||
fs::create_dir_all(&datadir).context("failed to create datadir")?;
|
||||
datadir
|
||||
} else {
|
||||
&cli.datadir
|
||||
}.canonicalize().context("error canonicalizing datadir")?;
|
||||
|
||||
if force {
|
||||
fs::remove_dir_all(&datadir)?;
|
||||
}
|
||||
|
||||
fs::create_dir_all(&datadir).context("failed to create datadir")?;
|
||||
cfg.datadir = datadir;
|
||||
let mut w = Wallet::create(cfg).await.context("error creating wallet")?;
|
||||
info!("Onchain address: {}", w.get_new_onchain_address()?);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut w = Wallet::open(cfg.clone()).await.context("error opening wallet")?;
|
||||
match cli.command {
|
||||
Command::Create { datadir, force } => {
|
||||
let datadir = if let Some(datadir) = datadir {
|
||||
fs::create_dir_all(&datadir).expect("failed to create datadir");
|
||||
datadir
|
||||
} else {
|
||||
cli.datadir
|
||||
}.canonicalize().expect("error canonicalizing datadir");
|
||||
|
||||
if force {
|
||||
fs::remove_dir_all(&datadir).unwrap();
|
||||
}
|
||||
|
||||
fs::create_dir_all(&datadir).expect("failed to create datadir");
|
||||
cfg.datadir = datadir;
|
||||
let mut w = Wallet::create(cfg).await.expect("error creating wallet");
|
||||
info!("Onchain address: {}", w.get_new_onchain_address().unwrap());
|
||||
},
|
||||
Command::Create { .. } => unreachable!(),
|
||||
Command::GetAddress { } => {
|
||||
let mut w = Wallet::open(cfg).await.unwrap();
|
||||
info!("Onchain address: {}", w.get_new_onchain_address().unwrap());
|
||||
info!("Onchain address: {}", w.get_new_onchain_address()?);
|
||||
},
|
||||
Command::GetVtxoPubkey { } => {
|
||||
let w = Wallet::open(cfg).await.unwrap();
|
||||
info!("Vtxo pubkey: {}", w.vtxo_pubkey());
|
||||
}
|
||||
Command::Balance { } => {
|
||||
let mut w = Wallet::open(cfg).await.unwrap();
|
||||
info!("Onchain balance: {}", w.onchain_balance().unwrap());
|
||||
info!("Offchain balance: {}", w.offchain_balance().await.unwrap());
|
||||
let (claimable, unclaimable) = w.unclaimed_exits().await.unwrap();
|
||||
info!("Onchain balance: {}", w.onchain_balance()?);
|
||||
info!("Offchain balance: {}", w.offchain_balance().await?);
|
||||
let (claimable, unclaimable) = w.unclaimed_exits().await?;
|
||||
if !claimable.is_empty() {
|
||||
let sum = claimable.iter().map(|i| i.spec.amount).sum::<Amount>();
|
||||
info!("Got {} claimable exits with total value of {}", claimable.len(), sum);
|
||||
@@ -118,29 +125,39 @@ async fn main() {
|
||||
}
|
||||
},
|
||||
Command::Onboard { amount } => {
|
||||
let mut w = Wallet::open(cfg).await.unwrap();
|
||||
w.onboard(amount).await.unwrap();
|
||||
w.onboard(amount).await?;
|
||||
},
|
||||
Command::SendOnchain { address, amount } => {
|
||||
let addr = address.require_network(cfg.network).with_context(|| {
|
||||
format!("address is not valid for configured network {}", cfg.network)
|
||||
})?;
|
||||
w.send_onchain(addr, amount)?;
|
||||
},
|
||||
Command::Send { pubkey, amount } => {
|
||||
let mut w = Wallet::open(cfg).await.unwrap();
|
||||
let dest = Destination { pubkey, amount };
|
||||
w.send_payment(dest).await.unwrap();
|
||||
w.send_payment(dest).await?;
|
||||
},
|
||||
Command::StartExit { } => {
|
||||
let mut w = Wallet::open(cfg).await.unwrap();
|
||||
w.start_unilateral_exit().await.unwrap();
|
||||
w.start_unilateral_exit().await?;
|
||||
},
|
||||
Command::ClaimExit { } => {
|
||||
let mut w = Wallet::open(cfg).await.unwrap();
|
||||
w.claim_unilateral_exit().await.unwrap();
|
||||
w.claim_unilateral_exit().await?;
|
||||
},
|
||||
|
||||
// dev commands
|
||||
|
||||
Command::DropVtxos { } => {
|
||||
let w = Wallet::open(cfg).await.unwrap();
|
||||
w.drop_vtxos().await.unwrap();
|
||||
w.drop_vtxos().await?;
|
||||
info!("Dropped all vtxos");
|
||||
},
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
if let Err(e) = inner_main().await {
|
||||
eprintln!("An error occurred: {}", e);
|
||||
eprintln!("Backtrace: {:?}", e.backtrace());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::io;
|
||||
use std::collections::HashSet;
|
||||
|
||||
use anyhow::Context;
|
||||
use bitcoin::{secp256k1, sighash, taproot, OutPoint, Witness};
|
||||
use bitcoin::{secp256k1, sighash, taproot, Amount, OutPoint, Witness};
|
||||
|
||||
use ark::{Vtxo, VtxoSpec};
|
||||
|
||||
@@ -170,8 +170,9 @@ impl Wallet {
|
||||
info!("No inputs we can claim.");
|
||||
return Ok(());
|
||||
}
|
||||
debug!("Claiming the following exits: {:?}",
|
||||
inputs.iter().map(|i| i.utxo.to_string()).collect::<Vec<_>>(),
|
||||
let total_amount = inputs.iter().map(|i| i.spec.amount).sum::<Amount>();
|
||||
debug!("Claiming the following exits with total value of {}: {:?}",
|
||||
total_amount, inputs.iter().map(|i| i.utxo.to_string()).collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
let mut psbt = self.onchain.create_exit_claim_tx(&inputs)?;
|
||||
@@ -223,6 +224,8 @@ impl Wallet {
|
||||
// Then update the database and only set the remaining inputs as to do.
|
||||
self.db.store_claim_inputs(&remaining).context("failed db update")?;
|
||||
|
||||
info!("Successfully claimed total value of {}", total_amount);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ pub struct ArkInfo {
|
||||
pub vtxo_exit_delta: u16,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Config {
|
||||
pub network: Network,
|
||||
pub datadir: PathBuf,
|
||||
@@ -181,7 +182,6 @@ impl Wallet {
|
||||
|
||||
// We ask the ASP to cosign our onboard unlock tx.
|
||||
let (user_part, priv_user_part) = ark::onboard::new_user(spec, utxo);
|
||||
trace!("User part for onboard: {:#?}", user_part);
|
||||
let asp_part = {
|
||||
let res = self.asp.request_onboard_cosign(arkd_rpc_client::OnboardCosignRequest {
|
||||
user_part: {
|
||||
@@ -284,6 +284,10 @@ impl Wallet {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn send_onchain(&mut self, addr: Address, amount: Amount) -> anyhow::Result<Txid> {
|
||||
Ok(self.onchain.send_money(addr, amount)?)
|
||||
}
|
||||
|
||||
pub async fn send_payment(&mut self, destination: Destination) -> anyhow::Result<()> {
|
||||
self.sync_ark().await.context("ark sync error")?;
|
||||
|
||||
@@ -340,7 +344,8 @@ impl Wallet {
|
||||
};
|
||||
|
||||
// The round has now started. We can submit our payment.
|
||||
trace!("Submitting payment request");
|
||||
trace!("Submitting payment request with {} inputs and {} outputs",
|
||||
input_vtxos.len(), 1 + change.is_some() as usize);
|
||||
self.asp.submit_payment(rpc::SubmitPaymentRequest {
|
||||
cosign_pubkey: cosign_key.public_key().serialize().to_vec(),
|
||||
input_vtxos: input_vtxos.iter().map(|v| v.encode()).collect(),
|
||||
@@ -405,7 +410,9 @@ impl Wallet {
|
||||
|
||||
// Make forfeit signatures.
|
||||
let connectors = ConnectorChain::new(
|
||||
forfeit_nonces.len(), conns_utxo, self.ark_info.asp_pubkey,
|
||||
forfeit_nonces.values().next().unwrap().len(),
|
||||
conns_utxo,
|
||||
self.ark_info.asp_pubkey,
|
||||
);
|
||||
let forfeit_signatures = input_vtxos.iter().map(|v| {
|
||||
let sigs = connectors.connectors().enumerate().map(|(i, conn)| {
|
||||
@@ -429,7 +436,7 @@ impl Wallet {
|
||||
|
||||
// Make vtxo signatures from top to bottom, just like sighashes are returned.
|
||||
let sighashes = vtxo_tree.sighashes(vtxos_utxo);
|
||||
trace!("sighashes: {:?}", sighashes);
|
||||
trace!("vtxo sighashes: {:?}", sighashes);
|
||||
assert_eq!(sighashes.len(), vtxo_agg_nonces.len());
|
||||
let signatures = iter::zip(sec_nonces.into_iter(), iter::zip(sighashes, vtxo_agg_nonces))
|
||||
.map(|(sec_nonce, (sighash, agg_nonce))| {
|
||||
@@ -443,7 +450,6 @@ impl Wallet {
|
||||
None,
|
||||
).0
|
||||
}).collect::<Vec<_>>();
|
||||
trace!("Sending signatures to ASP");
|
||||
self.asp.provide_signatures(rpc::RoundSignatures {
|
||||
forfeit: forfeit_signatures.into_iter().map(|(id, sigs)| {
|
||||
rpc::ForfeitSignatures {
|
||||
|
||||
Reference in New Issue
Block a user