From dcf4761940c7e82995d25b49ad912150367be2d1 Mon Sep 17 00:00:00 2001 From: Dave Hrycyszyn Date: Fri, 26 Jul 2024 15:27:32 +0100 Subject: [PATCH] Refactored bitcoin driver programs --- side-node/src/bitcoin/driver.rs | 93 ------------------- side-node/src/bitcoin/driver/htlc.rs | 40 ++++++++ side-node/src/bitcoin/driver/mod.rs | 35 +++++++ .../src/bitcoin/driver/simple_transfer.rs | 28 ++++++ .../src/bitcoin/driver/transfer_policy.rs | 7 ++ side-node/src/bitcoin/htlc.rs | 24 ----- side-node/src/cli/mod.rs | 3 + side-node/src/lib.rs | 8 +- 8 files changed, 119 insertions(+), 119 deletions(-) delete mode 100644 side-node/src/bitcoin/driver.rs create mode 100644 side-node/src/bitcoin/driver/htlc.rs create mode 100644 side-node/src/bitcoin/driver/mod.rs create mode 100644 side-node/src/bitcoin/driver/simple_transfer.rs create mode 100644 side-node/src/bitcoin/driver/transfer_policy.rs diff --git a/side-node/src/bitcoin/driver.rs b/side-node/src/bitcoin/driver.rs deleted file mode 100644 index ab181f6..0000000 --- a/side-node/src/bitcoin/driver.rs +++ /dev/null @@ -1,93 +0,0 @@ -use bdk::bitcoin::Network; -use bdk::wallet::AddressIndex; -use bdk::SignOptions; -use tracing_subscriber::filter::EnvFilter; -use tracing_subscriber::util::SubscriberInitExt; -use tracing_subscriber::{fmt, layer::SubscriberExt}; - -use super::client::BitcoinClient; - -async fn setup() -> Result<(BitcoinClient, BitcoinClient), anyhow::Error> { - tracing_setup(); - let dave = BitcoinClient::create("dave", Network::Signet)?; - let sammy = BitcoinClient::create("sammy", Network::Signet)?; - - dave.sync()?; - let _ = dave.wallet.get_balance(); - - sammy.sync()?; - let _ = sammy.wallet.get_balance(); - - Ok((dave, sammy)) -} - -pub(crate) async fn simple_transfer() -> Result<(), anyhow::Error> { - let (mut dave, sammy) = setup().await?; - - let send_amount = 500; - let _ = ensure_enough_sats(&dave, send_amount); - - let sammy_address = sammy.wallet.get_address(AddressIndex::New)?; - let tx = dave.build_and_sign_send_tx(sammy_address, send_amount)?; - dave.broadcast(&tx)?; - - Ok(()) -} - -pub(crate) async fn htlc() -> anyhow::Result<()> { - tracing::info!("starting htlc flow"); - let (dave, sammy) = setup().await?; - - // format a new commitment transaction like in Lightning - let mut commitment_builder = dave.wallet.build_tx(); - let amount = 500; - let recipient = sammy.wallet.get_address(AddressIndex::New)?.script_pubkey(); - commitment_builder.add_recipient(recipient, amount); - commitment_builder.enable_rbf(); - let (psbt, _) = commitment_builder - .finish() - .expect("unable to build commitment"); - - // sign the commitment transaction - let mut dave_psbt = dave.sign(&mut psbt.clone(), false)?; - let sammy_psbt = sammy.sign(&mut psbt.clone(), false)?; - - dave_psbt - .combine(sammy_psbt) - .expect("problem combining bitcoin PSBTs"); // these guys love mutability - - let finalized = dave - .wallet - .finalize_psbt(&mut dave_psbt, SignOptions::default()) - .expect("couldn't finalize"); - - assert!(finalized); - let tx = dave_psbt.extract_tx(); - - let _ = dave.broadcast(&tx)?; - - let _ = sammy.sync(); - let _ = sammy.wallet.get_balance(); - Ok(()) -} - -fn tracing_setup() { - tracing_subscriber::registry() - .with(fmt::layer()) - .with(EnvFilter::from_default_env()) - .init(); - - tracing::info!("Tracing initialized."); -} - -/// Exit if the wallet does not have enough sats to send. -fn ensure_enough_sats(wallet: &BitcoinClient, send_amount: u64) -> anyhow::Result<()> { - if wallet.wallet.get_balance()?.get_total() < send_amount { - tracing::error!( - "Please send at least {} sats to the receiving address. Exiting.", - send_amount - ); - std::process::exit(0); - } - Ok(()) -} diff --git a/side-node/src/bitcoin/driver/htlc.rs b/side-node/src/bitcoin/driver/htlc.rs new file mode 100644 index 0000000..5874ed4 --- /dev/null +++ b/side-node/src/bitcoin/driver/htlc.rs @@ -0,0 +1,40 @@ +use crate::bitcoin::driver; +use bdk::wallet::AddressIndex; +use bdk::SignOptions; + +pub(crate) async fn run() -> anyhow::Result<()> { + tracing::info!("starting htlc flow"); + let (dave, sammy) = driver::setup().await?; + + // format a new commitment transaction like in Lightning + let mut commitment_builder = dave.wallet.build_tx(); + let amount = 500; + let recipient = sammy.wallet.get_address(AddressIndex::New)?.script_pubkey(); + commitment_builder.add_recipient(recipient, amount); + commitment_builder.enable_rbf(); + let (psbt, _) = commitment_builder + .finish() + .expect("unable to build commitment"); + + // sign the commitment transaction + let mut dave_psbt = dave.sign(&mut psbt.clone(), false)?; + let sammy_psbt = sammy.sign(&mut psbt.clone(), false)?; + + dave_psbt + .combine(sammy_psbt) + .expect("problem combining bitcoin PSBTs"); // these guys love mutability + + let finalized = dave + .wallet + .finalize_psbt(&mut dave_psbt, SignOptions::default()) + .expect("couldn't finalize"); + + assert!(finalized); + let tx = dave_psbt.extract_tx(); + + let _ = dave.broadcast(&tx)?; + + let _ = sammy.sync(); + let _ = sammy.wallet.get_balance(); + Ok(()) +} diff --git a/side-node/src/bitcoin/driver/mod.rs b/side-node/src/bitcoin/driver/mod.rs new file mode 100644 index 0000000..dfa3347 --- /dev/null +++ b/side-node/src/bitcoin/driver/mod.rs @@ -0,0 +1,35 @@ +use bdk::bitcoin::Network; +use bdk::wallet::AddressIndex; +use bdk::SignOptions; +use tracing_subscriber::filter::EnvFilter; +use tracing_subscriber::util::SubscriberInitExt; +use tracing_subscriber::{fmt, layer::SubscriberExt}; + +use super::client::BitcoinClient; + +pub mod htlc; +pub mod simple_transfer; +pub mod transfer_policy; + +async fn setup() -> Result<(BitcoinClient, BitcoinClient), anyhow::Error> { + tracing_setup(); + let dave = BitcoinClient::create("dave", Network::Signet)?; + let sammy = BitcoinClient::create("sammy", Network::Signet)?; + + dave.sync()?; + let _ = dave.wallet.get_balance(); + + sammy.sync()?; + let _ = sammy.wallet.get_balance(); + + Ok((dave, sammy)) +} + +fn tracing_setup() { + tracing_subscriber::registry() + .with(fmt::layer()) + .with(EnvFilter::from_default_env()) + .init(); + + tracing::info!("Tracing initialized."); +} diff --git a/side-node/src/bitcoin/driver/simple_transfer.rs b/side-node/src/bitcoin/driver/simple_transfer.rs new file mode 100644 index 0000000..e9dddd7 --- /dev/null +++ b/side-node/src/bitcoin/driver/simple_transfer.rs @@ -0,0 +1,28 @@ +use crate::bitcoin::client::BitcoinClient; +use crate::bitcoin::driver; +use bdk::wallet::AddressIndex; + +pub async fn run() -> Result<(), anyhow::Error> { + let (mut dave, sammy) = driver::setup().await?; + + let send_amount = 500; + let _ = ensure_enough_sats(&dave, send_amount); + + let sammy_address = sammy.wallet.get_address(AddressIndex::New)?; + let tx = dave.build_and_sign_send_tx(sammy_address, send_amount)?; + dave.broadcast(&tx)?; + + Ok(()) +} + +/// Exit if the wallet does not have enough sats to send. +fn ensure_enough_sats(wallet: &BitcoinClient, send_amount: u64) -> anyhow::Result<()> { + if wallet.wallet.get_balance()?.get_total() < send_amount { + tracing::error!( + "Please send at least {} sats to the receiving address. Exiting.", + send_amount + ); + std::process::exit(0); + } + Ok(()) +} diff --git a/side-node/src/bitcoin/driver/transfer_policy.rs b/side-node/src/bitcoin/driver/transfer_policy.rs new file mode 100644 index 0000000..4edca58 --- /dev/null +++ b/side-node/src/bitcoin/driver/transfer_policy.rs @@ -0,0 +1,7 @@ +use crate::bitcoin; + +pub(crate) async fn run() -> anyhow::Result<()> { + bitcoin::driver::setup().await?; + tracing::info!("starting transfer policy flow"); + Ok(()) +} diff --git a/side-node/src/bitcoin/htlc.rs b/side-node/src/bitcoin/htlc.rs index 39eba46..6a847c0 100644 --- a/side-node/src/bitcoin/htlc.rs +++ b/side-node/src/bitcoin/htlc.rs @@ -54,28 +54,4 @@ impl Htlc { ) .expect("Resource limits") } - - /// Translate the HTLC to Bitcoin op_codes. - pub(crate) fn to_script(&self) -> String { - format!( - "OP_IF - OP_SHA256 - {} - OP_EQUALVERIFY - OP_DUP - OP_HASH160 - {} - OP_ELSE - {} - OP_CHECKLOCKTIMEVERIFY - OP_DROP - OP_DUP - OP_HASH160 - {} - OP_ENDIF - OP_EQUALVERIFY - OP_CHECKSIG", - self.hashlock, self.redeem_identity, self.refund_timelock, self.refund_indentiy - ) - } } diff --git a/side-node/src/cli/mod.rs b/side-node/src/cli/mod.rs index eda4b17..6e2234d 100644 --- a/side-node/src/cli/mod.rs +++ b/side-node/src/cli/mod.rs @@ -20,6 +20,9 @@ pub(crate) enum Commands { /// transfers bitcoin between two wallets using a driver program BtcTransfer {}, + /// transfers bitcoin but this time uses a Miniscript policy + BtcTransferPolicy {}, + /// sets up a Bitcoin HTLC BtcHtlc {}, diff --git a/side-node/src/lib.rs b/side-node/src/lib.rs index 3451d02..122375a 100644 --- a/side-node/src/lib.rs +++ b/side-node/src/lib.rs @@ -29,11 +29,15 @@ pub async fn run() { node.start().await; } Some(Commands::BtcTransfer {}) => { - let _ = bitcoin::driver::simple_transfer().await; + let _ = bitcoin::driver::simple_transfer::run().await; + } + + Some(Commands::BtcTransferPolicy {}) => { + let _ = bitcoin::driver::transfer_policy::run().await; } Some(Commands::BtcHtlc {}) => { - let _ = bitcoin::driver::htlc().await; + let _ = bitcoin::driver::htlc::run().await; } None => println!("No command provided. Exiting. See --help for more information."),