Refactored bitcoin driver programs
This commit is contained in:
@@ -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(())
|
|
||||||
}
|
|
||||||
40
side-node/src/bitcoin/driver/htlc.rs
Normal file
40
side-node/src/bitcoin/driver/htlc.rs
Normal 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(())
|
||||||
|
}
|
||||||
35
side-node/src/bitcoin/driver/mod.rs
Normal file
35
side-node/src/bitcoin/driver/mod.rs
Normal 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.");
|
||||||
|
}
|
||||||
28
side-node/src/bitcoin/driver/simple_transfer.rs
Normal file
28
side-node/src/bitcoin/driver/simple_transfer.rs
Normal 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(())
|
||||||
|
}
|
||||||
7
side-node/src/bitcoin/driver/transfer_policy.rs
Normal file
7
side-node/src/bitcoin/driver/transfer_policy.rs
Normal 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(())
|
||||||
|
}
|
||||||
@@ -54,28 +54,4 @@ impl Htlc {
|
|||||||
)
|
)
|
||||||
.expect("Resource limits")
|
.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
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ pub(crate) enum Commands {
|
|||||||
/// transfers bitcoin between two wallets using a driver program
|
/// transfers bitcoin between two wallets using a driver program
|
||||||
BtcTransfer {},
|
BtcTransfer {},
|
||||||
|
|
||||||
|
/// transfers bitcoin but this time uses a Miniscript policy
|
||||||
|
BtcTransferPolicy {},
|
||||||
|
|
||||||
/// sets up a Bitcoin HTLC
|
/// sets up a Bitcoin HTLC
|
||||||
BtcHtlc {},
|
BtcHtlc {},
|
||||||
|
|
||||||
|
|||||||
@@ -29,11 +29,15 @@ pub async fn run() {
|
|||||||
node.start().await;
|
node.start().await;
|
||||||
}
|
}
|
||||||
Some(Commands::BtcTransfer {}) => {
|
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 {}) => {
|
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."),
|
None => println!("No command provided. Exiting. See --help for more information."),
|
||||||
|
|||||||
Reference in New Issue
Block a user