Refactored bitcoin driver programs

This commit is contained in:
Dave Hrycyszyn
2024-07-26 15:27:32 +01:00
parent 0edfbfaab1
commit dcf4761940
8 changed files with 119 additions and 119 deletions

View File

@@ -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(())
}

View File

@@ -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(())
}

View File

@@ -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.");
}

View File

@@ -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(())
}

View File

@@ -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(())
}

View File

@@ -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
)
}
}

View File

@@ -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 {},

View File

@@ -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."),