From 907540d2143b4eff4146643259a068b2f0c8696a Mon Sep 17 00:00:00 2001 From: Steve Myers Date: Wed, 20 Apr 2022 15:59:00 -0700 Subject: [PATCH 1/4] Update bdk to 0.18.0 with sqlite-bundled feature --- Cargo.toml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5392f72..6bb347f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,10 +14,7 @@ crate-type = ["staticlib", "cdylib"] name = "bdkffi" [dependencies] -bdk = { version = "0.14", features = ["all-keys", "use-esplora-ureq", "sqlite"] } - -# TODO remove when bdk "sqlite-bundled" feature added -rusqlite = { version = "0.25.3", features = ["bundled"] } +bdk = { version = "0.18", features = ["all-keys", "use-esplora-ureq", "sqlite-bundled"] } uniffi_macros = { version = "0.16.0", features = ["builtin-bindgen"] } uniffi = { version = "0.16.0", features = ["builtin-bindgen"] } From 4665c551dd67f38fe91011e41ed5d3e8de404fcf Mon Sep 17 00:00:00 2001 From: Steve Myers Date: Wed, 20 Apr 2022 23:15:14 -0700 Subject: [PATCH 2/4] Update EsploraConfig, Blockchain broadcast, Wallet sync --- src/bdk.udl | 19 +++++--- src/lib.rs | 125 +++++++++++++++++++++++++++++++++------------------- 2 files changed, 92 insertions(+), 52 deletions(-) diff --git a/src/bdk.udl b/src/bdk.udl index bce5af6..61f5f9f 100644 --- a/src/bdk.udl +++ b/src/bdk.udl @@ -101,9 +101,9 @@ dictionary ElectrumConfig { dictionary EsploraConfig { string base_url; string? proxy; - u64 timeout_read; - u64 timeout_write; + u8? concurrency; u64 stop_gap; + u64? timeout; }; [Enum] @@ -112,13 +112,20 @@ interface BlockchainConfig { Esplora(EsploraConfig config); }; -callback interface BdkProgress { +interface Blockchain { + [Throws=BdkError] + constructor(BlockchainConfig config); + [Throws=BdkError] + string broadcast([ByRef] PartiallySignedBitcoinTransaction psbt); +}; + +callback interface Progress { void update(f32 progress, string? message); }; interface Wallet { [Throws=BdkError] - constructor(string descriptor, string? change_descriptor, Network network, DatabaseConfig database_config, BlockchainConfig blockchain_config); + constructor(string descriptor, string? change_descriptor, Network network, DatabaseConfig database_config); string get_new_address(); string get_last_unused_address(); [Throws=BdkError] @@ -129,9 +136,7 @@ interface Wallet { sequence get_transactions(); Network get_network(); [Throws=BdkError] - void sync(BdkProgress progress_update, u32? max_address_param); - [Throws=BdkError] - string broadcast([ByRef] PartiallySignedBitcoinTransaction psbt); + void sync([ByRef] Blockchain blockchain, Progress? progress); }; interface PartiallySignedBitcoinTransaction { diff --git a/src/lib.rs b/src/lib.rs index f1ed9f7..e1db46c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,18 +3,22 @@ use bdk::bitcoin::secp256k1::Secp256k1; use bdk::bitcoin::util::psbt::PartiallySignedTransaction; use bdk::bitcoin::{Address, Network, Script}; use bdk::blockchain::any::{AnyBlockchain, AnyBlockchainConfig}; -use bdk::blockchain::Progress; use bdk::blockchain::{ electrum::ElectrumBlockchainConfig, esplora::EsploraBlockchainConfig, ConfigurableBlockchain, }; +use bdk::blockchain::{Blockchain as BdkBlockchain, Progress as BdkProgress}; use bdk::database::any::{AnyDatabase, SledDbConfiguration, SqliteDbConfiguration}; use bdk::database::{AnyDatabaseConfig, ConfigurableDatabase}; use bdk::keys::bip39::{Language, Mnemonic, WordCount}; use bdk::keys::{DerivableKey, ExtendedKey, GeneratableKey, GeneratedKey}; use bdk::miniscript::BareCtx; use bdk::wallet::AddressIndex; -use bdk::{BlockTime, Error, FeeRate, SignOptions, Wallet as BdkWallet}; +use bdk::{ + BlockTime, Error, FeeRate, SignOptions, SyncOptions as BdkSyncOptions, Wallet as BdkWallet, +}; use std::convert::TryFrom; +use std::fmt; +use std::ops::Deref; use std::str::FromStr; use std::sync::{Arc, Mutex, MutexGuard}; @@ -39,9 +43,9 @@ pub struct ElectrumConfig { pub struct EsploraConfig { pub base_url: String, pub proxy: Option, - pub timeout_read: u64, - pub timeout_write: u64, + pub concurrency: Option, pub stop_gap: u64, + pub timeout: Option, } pub enum BlockchainConfig { @@ -93,25 +97,76 @@ impl From<&bdk::TransactionDetails> for Transaction { } } -struct Wallet { - wallet_mutex: Mutex>, +struct Blockchain { + blockchain_mutex: Mutex, } -pub trait BdkProgress: Send + Sync { +impl Blockchain { + fn new(blockchain_config: BlockchainConfig) -> Result { + let any_blockchain_config = match blockchain_config { + BlockchainConfig::Electrum { config } => { + AnyBlockchainConfig::Electrum(ElectrumBlockchainConfig { + retry: config.retry, + socks5: config.socks5, + timeout: config.timeout, + url: config.url, + stop_gap: usize::try_from(config.stop_gap).unwrap(), + }) + } + BlockchainConfig::Esplora { config } => { + AnyBlockchainConfig::Esplora(EsploraBlockchainConfig { + base_url: config.base_url, + proxy: config.proxy, + concurrency: config.concurrency, + stop_gap: usize::try_from(config.stop_gap).unwrap(), + timeout: config.timeout, + }) + } + }; + let blockchain = AnyBlockchain::from_config(&any_blockchain_config)?; + Ok(Self { + blockchain_mutex: Mutex::new(blockchain), + }) + } + + fn get_blockchain(&self) -> MutexGuard { + self.blockchain_mutex.lock().expect("blockchain") + } + + fn broadcast(&self, psbt: &PartiallySignedBitcoinTransaction) -> Result { + let tx = psbt.internal.lock().unwrap().clone().extract_tx(); + self.get_blockchain().broadcast(&tx)?; + // TODO move txid getter to PartiallySignedBitcoinTransaction + let txid = tx.txid(); + Ok(txid.to_hex()) + } +} + +struct Wallet { + wallet_mutex: Mutex>, +} + +pub trait Progress: Send + Sync + 'static { fn update(&self, progress: f32, message: Option); } -struct BdkProgressHolder { - progress_update: Box, +struct ProgressHolder { + progress: Box, } -impl Progress for BdkProgressHolder { +impl BdkProgress for ProgressHolder { fn update(&self, progress: f32, message: Option) -> Result<(), Error> { - self.progress_update.update(progress, message); + self.progress.update(progress, message); Ok(()) } } +impl fmt::Debug for ProgressHolder { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ProgressHolder").finish_non_exhaustive() + } +} + #[derive(Debug)] struct PartiallySignedBitcoinTransaction { internal: Mutex, @@ -137,46 +192,23 @@ impl Wallet { change_descriptor: Option, network: Network, database_config: DatabaseConfig, - blockchain_config: BlockchainConfig, ) -> Result { let any_database_config = match database_config { DatabaseConfig::Memory => AnyDatabaseConfig::Memory(()), DatabaseConfig::Sled { config } => AnyDatabaseConfig::Sled(config), DatabaseConfig::Sqlite { config } => AnyDatabaseConfig::Sqlite(config), }; - let any_blockchain_config = match blockchain_config { - BlockchainConfig::Electrum { config } => { - AnyBlockchainConfig::Electrum(ElectrumBlockchainConfig { - retry: config.retry, - socks5: config.socks5, - timeout: config.timeout, - url: config.url, - stop_gap: usize::try_from(config.stop_gap).unwrap(), - }) - } - BlockchainConfig::Esplora { config } => { - AnyBlockchainConfig::Esplora(EsploraBlockchainConfig { - base_url: config.base_url, - proxy: config.proxy, - timeout_read: config.timeout_read, - timeout_write: config.timeout_write, - stop_gap: usize::try_from(config.stop_gap).unwrap(), - }) - } - }; let database = AnyDatabase::from_config(&any_database_config)?; - let blockchain = AnyBlockchain::from_config(&any_blockchain_config)?; let wallet_mutex = Mutex::new(BdkWallet::new( &descriptor, change_descriptor.as_ref(), network, database, - blockchain, )?); Ok(Wallet { wallet_mutex }) } - fn get_wallet(&self) -> MutexGuard> { + fn get_wallet(&self) -> MutexGuard> { self.wallet_mutex.lock().expect("wallet") } @@ -186,11 +218,20 @@ impl Wallet { fn sync( &self, - progress_update: Box, - max_address_param: Option, + blockchain: &Blockchain, + progress: Option>, + //progress_update: Box, + //max_address_param: Option, ) -> Result<(), BdkError> { - self.get_wallet() - .sync(BdkProgressHolder { progress_update }, max_address_param) + let bdk_sync_opts = BdkSyncOptions { + progress: progress.map(|p| { + Box::new(ProgressHolder { progress: p }) + as Box<(dyn bdk::blockchain::Progress + 'static)> + }), + }; + + let blockchain = blockchain.get_blockchain(); + self.get_wallet().sync(blockchain.deref(), bdk_sync_opts) } fn get_new_address(&self) -> String { @@ -229,12 +270,6 @@ impl Wallet { let transactions = self.get_wallet().list_transactions(true)?; Ok(transactions.iter().map(Transaction::from).collect()) } - - fn broadcast(&self, psbt: &PartiallySignedBitcoinTransaction) -> Result { - let tx = psbt.internal.lock().unwrap().clone().extract_tx(); - let txid = self.get_wallet().broadcast(&tx)?; - Ok(txid.to_hex()) - } } pub struct ExtendedKeyInfo { From 11ba16ec1bec922e5ffd7fcf3903eec9caf227e7 Mon Sep 17 00:00:00 2001 From: Steve Myers Date: Fri, 22 Apr 2022 14:10:00 -0700 Subject: [PATCH 3/4] Move txid getter to PartiallySignedBitcoinTransaction --- src/bdk.udl | 3 ++- src/lib.rs | 15 ++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/bdk.udl b/src/bdk.udl index 61f5f9f..5429127 100644 --- a/src/bdk.udl +++ b/src/bdk.udl @@ -116,7 +116,7 @@ interface Blockchain { [Throws=BdkError] constructor(BlockchainConfig config); [Throws=BdkError] - string broadcast([ByRef] PartiallySignedBitcoinTransaction psbt); + void broadcast([ByRef] PartiallySignedBitcoinTransaction psbt); }; callback interface Progress { @@ -143,6 +143,7 @@ interface PartiallySignedBitcoinTransaction { [Throws=BdkError] constructor(string psbt_base64); string serialize(); + string txid(); }; interface TxBuilder { diff --git a/src/lib.rs b/src/lib.rs index e1db46c..caa1396 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -133,12 +133,9 @@ impl Blockchain { self.blockchain_mutex.lock().expect("blockchain") } - fn broadcast(&self, psbt: &PartiallySignedBitcoinTransaction) -> Result { + fn broadcast(&self, psbt: &PartiallySignedBitcoinTransaction) -> Result<(), Error> { let tx = psbt.internal.lock().unwrap().clone().extract_tx(); - self.get_blockchain().broadcast(&tx)?; - // TODO move txid getter to PartiallySignedBitcoinTransaction - let txid = tx.txid(); - Ok(txid.to_hex()) + self.get_blockchain().broadcast(&tx) } } @@ -184,6 +181,12 @@ impl PartiallySignedBitcoinTransaction { let psbt = self.internal.lock().unwrap().clone(); psbt.to_string() } + + fn txid(&self) -> String { + let tx = self.internal.lock().unwrap().clone().extract_tx(); + let txid = tx.txid(); + txid.to_hex() + } } impl Wallet { @@ -220,8 +223,6 @@ impl Wallet { &self, blockchain: &Blockchain, progress: Option>, - //progress_update: Box, - //max_address_param: Option, ) -> Result<(), BdkError> { let bdk_sync_opts = BdkSyncOptions { progress: progress.map(|p| { From f38f4c6197ec95376beeb2f444f85bd6a8a12fbd Mon Sep 17 00:00:00 2001 From: Steve Myers Date: Mon, 2 May 2022 16:17:27 -0700 Subject: [PATCH 4/4] Update CHANGELOG --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ff8356..73fd99e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- Update BDK to version 0.18.0 + ## [v0.5.0] - Fix Wallet.broadcast function, now returns a tx id as a hex string