From d0cd3b0f389c10610ad58a999d42b4b7ca39ba6c Mon Sep 17 00:00:00 2001 From: Steve Myers Date: Tue, 29 Nov 2022 18:16:27 -0800 Subject: [PATCH 1/2] Add Auth, RpcSyncParams, and RpcConfig --- Cargo.lock | 46 +++++++++++++++++++++++++ bdk-ffi/Cargo.toml | 2 +- bdk-ffi/src/bdk.udl | 24 +++++++++++++ bdk-ffi/src/lib.rs | 84 ++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 154 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a24fb7e..4a8d953 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,6 +107,15 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[package]] +name = "base64-compat" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a8d4d2746f89841e49230dd26917df1876050f95abafafbe34f47cb534b88d7" +dependencies = [ + "byteorder", +] + [[package]] name = "bdk" version = "0.25.0" @@ -118,6 +127,7 @@ dependencies = [ "bdk-macros", "bip39", "bitcoin", + "bitcoincore-rpc", "electrum-client", "esplora-client", "getrandom", @@ -218,6 +228,30 @@ dependencies = [ "serde", ] +[[package]] +name = "bitcoincore-rpc" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0261b2bb7617e0c91b452a837bbd1291fd34ad6990cb8e3ffc28239cc045b5ca" +dependencies = [ + "bitcoincore-rpc-json", + "jsonrpc", + "log", + "serde", + "serde_json", +] + +[[package]] +name = "bitcoincore-rpc-json" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c231bea28e314879c5aef240f6052e8a72a369e3c9f9b20d9bfbb33ad18029b2" +dependencies = [ + "bitcoin", + "serde", + "serde_json", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -567,6 +601,18 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "jsonrpc" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f8423b78fc94d12ef1a4a9d13c348c9a78766dda0cc18817adf0faf77e670c8" +dependencies = [ + "base64-compat", + "serde", + "serde_derive", + "serde_json", +] + [[package]] name = "lazy_static" version = "1.4.0" diff --git a/bdk-ffi/Cargo.toml b/bdk-ffi/Cargo.toml index bd750b0..501de9d 100644 --- a/bdk-ffi/Cargo.toml +++ b/bdk-ffi/Cargo.toml @@ -10,7 +10,7 @@ crate-type = ["staticlib", "cdylib"] name = "bdkffi" [dependencies] -bdk = { version = "0.25", features = ["all-keys", "use-esplora-ureq", "sqlite-bundled"] } +bdk = { version = "0.25", features = ["all-keys", "use-esplora-ureq", "sqlite-bundled", "rpc"] } uniffi_macros = { version = "0.21.0", features = ["builtin-bindgen"] } uniffi = { version = "0.21.0", features = ["builtin-bindgen"] } diff --git a/bdk-ffi/src/bdk.udl b/bdk-ffi/src/bdk.udl index 2a53dd4..f79aa16 100644 --- a/bdk-ffi/src/bdk.udl +++ b/bdk-ffi/src/bdk.udl @@ -45,6 +45,7 @@ enum BdkError { "Esplora", "Sled", "Rusqlite", + "Rpc", }; dictionary AddressInfo { @@ -126,10 +127,33 @@ dictionary EsploraConfig { u64? timeout; }; +[Enum] +interface Auth { + None(); + UserPass(string username, string password); + Cookie(string file); +}; + +dictionary RpcSyncParams { + u64 start_script_count; + u64 start_time; + boolean force_start_time; + u64 poll_rate_sec; +}; + +dictionary RpcConfig { + string url; + Auth auth; + Network network; + string wallet_name; + RpcSyncParams? sync_params; +}; + [Enum] interface BlockchainConfig { Electrum(ElectrumConfig config); Esplora(EsploraConfig config); + Rpc(RpcConfig config); }; interface Blockchain { diff --git a/bdk-ffi/src/lib.rs b/bdk-ffi/src/lib.rs index 1bb5364..8beae71 100644 --- a/bdk-ffi/src/lib.rs +++ b/bdk-ffi/src/lib.rs @@ -7,10 +7,12 @@ use bdk::bitcoin::util::psbt::PartiallySignedTransaction as BdkPartiallySignedTr use bdk::bitcoin::Sequence; use bdk::bitcoin::{Address as BdkAddress, Network, OutPoint as BdkOutPoint, Txid}; use bdk::blockchain::any::{AnyBlockchain, AnyBlockchainConfig}; +use bdk::blockchain::rpc::Auth as BdkAuth; use bdk::blockchain::GetBlockHash; use bdk::blockchain::GetHeight; use bdk::blockchain::{ - electrum::ElectrumBlockchainConfig, esplora::EsploraBlockchainConfig, ConfigurableBlockchain, + electrum::ElectrumBlockchainConfig, esplora::EsploraBlockchainConfig, + rpc::RpcConfig as BdkRpcConfig, rpc::RpcSyncParams as BdkRpcSyncParams, ConfigurableBlockchain, }; use bdk::blockchain::{Blockchain as BdkBlockchain, Progress as BdkProgress}; use bdk::database::any::{AnyDatabase, SledDbConfiguration, SqliteDbConfiguration}; @@ -34,6 +36,7 @@ use std::collections::HashSet; use std::convert::{From, TryFrom}; use std::fmt; use std::ops::Deref; +use std::path::PathBuf; use std::str::FromStr; use std::sync::{Arc, Mutex, MutexGuard}; @@ -134,12 +137,84 @@ pub struct EsploraConfig { pub timeout: Option, } +pub enum Auth { + /// No authentication + None, + /// Authentication with username and password, usually [Auth::Cookie] should be preferred + UserPass { + /// Username + username: String, + /// Password + password: String, + }, + /// Authentication with a cookie file + Cookie { + /// Cookie file + file: String, + }, +} + +impl From for BdkAuth { + fn from(auth: Auth) -> Self { + match auth { + Auth::None => BdkAuth::None, + Auth::UserPass { username, password } => BdkAuth::UserPass { username, password }, + Auth::Cookie { file } => BdkAuth::Cookie { + file: PathBuf::from(file), + }, + } + } +} + +/// Sync parameters for Bitcoin Core RPC. +/// +/// In general, BDK tries to sync `scriptPubKey`s cached in `Database` with +/// `scriptPubKey`s imported in the Bitcoin Core Wallet. These parameters are used for determining +/// how the `importdescriptors` RPC calls are to be made. +pub struct RpcSyncParams { + /// The minimum number of scripts to scan for on initial sync. + pub start_script_count: u64, + /// Time in unix seconds in which initial sync will start scanning from (0 to start from genesis). + pub start_time: u64, + /// Forces every sync to use `start_time` as import timestamp. + pub force_start_time: bool, + /// RPC poll rate (in seconds) to get state updates. + pub poll_rate_sec: u64, +} + +impl From for BdkRpcSyncParams { + fn from(params: RpcSyncParams) -> Self { + BdkRpcSyncParams { + start_script_count: params.start_script_count as usize, + start_time: params.start_time, + force_start_time: params.force_start_time, + poll_rate_sec: params.poll_rate_sec, + } + } +} + +/// RpcBlockchain configuration options +pub struct RpcConfig { + /// The bitcoin node url + pub url: String, + /// The bitcoin node authentication mechanism + pub auth: Auth, + /// The network we are using (it will be checked the bitcoin node network matches this) + pub network: Network, + /// The wallet name in the bitcoin node, consider using [crate::wallet::wallet_name_from_descriptor] for this + pub wallet_name: String, + /// Sync parameters + pub sync_params: Option, +} + /// Type that can contain any of the blockchain configurations defined by the library. pub enum BlockchainConfig { /// Electrum client Electrum { config: ElectrumConfig }, /// Esplora client Esplora { config: EsploraConfig }, + /// Bitcoin Core RPC client + Rpc { config: RpcConfig }, } /// A wallet transaction @@ -200,6 +275,13 @@ impl Blockchain { timeout: config.timeout, }) } + BlockchainConfig::Rpc { config } => AnyBlockchainConfig::Rpc(BdkRpcConfig { + url: config.url, + auth: config.auth.into(), + network: config.network, + wallet_name: config.wallet_name, + sync_params: config.sync_params.map(|p| p.into()), + }), }; let blockchain = AnyBlockchain::from_config(&any_blockchain_config)?; Ok(Self { From 4ed6e364e68648a3b5cf6773e8d74b74d922b315 Mon Sep 17 00:00:00 2001 From: thunderbiscuit Date: Fri, 16 Dec 2022 10:36:32 -0500 Subject: [PATCH 2/2] Add API docs for RPC blockchain config and auth --- .../src/main/kotlin/org/bitcoindevkit/bdk.kt | 57 ++++++++++++++++++- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/api-docs/kotlin/src/main/kotlin/org/bitcoindevkit/bdk.kt b/api-docs/kotlin/src/main/kotlin/org/bitcoindevkit/bdk.kt index 91422b8..f97fd09 100644 --- a/api-docs/kotlin/src/main/kotlin/org/bitcoindevkit/bdk.kt +++ b/api-docs/kotlin/src/main/kotlin/org/bitcoindevkit/bdk.kt @@ -123,7 +123,7 @@ data class SledDbConfiguration( * * @sample org.bitcoindevkit.electrumBlockchainConfigSample */ -data class ElectrumConfig ( +data class ElectrumConfig( var url: String, var socks5: String?, var retry: UByte, @@ -142,7 +142,7 @@ data class ElectrumConfig ( * * @sample org.bitcoindevkit.esploraBlockchainConfigSample */ -data class EsploraConfig ( +data class EsploraConfig( var baseUrl: String, var proxy: String?, var concurrency: UByte?, @@ -150,6 +150,56 @@ data class EsploraConfig ( var timeout: ULong? ) +/** + * Authentication mechanism for RPC connection to full node + */ +sealed class Auth { + /** No authentication */ + object None: Auth() + + /** Authentication with username and password, usually [Auth.Cookie] should be preferred */ + data class UserPass(val username: String, val password: String): Auth() + + /** Authentication with a cookie file */ + data class Cookie(val file: String): Auth() +} + +/** + * Sync parameters for Bitcoin Core RPC. + * + * In general, BDK tries to sync `scriptPubKey`s cached in `Database` with + * `scriptPubKey`s imported in the Bitcoin Core Wallet. These parameters are used for determining + * how the `importdescriptors` RPC calls are to be made. + * + * @property startScriptCount The minimum number of scripts to scan for on initial sync. + * @property startTime Time in unix seconds in which initial sync will start scanning from (0 to start from genesis). + * @property forceStartTime Forces every sync to use `start_time` as import timestamp. + * @property pollRateSec RPC poll rate (in seconds) to get state updates. + */ +data class RcpSyncParams( + val startScriptCount: ULong, + val startTime: Ulong, + val forceStartTime: Boolean, + val pollRateSec: ULong, +) + +/** + * RpcBlockchain configuration options + * + * @property url The bitcoin node url. + * @property auth The bicoin node authentication mechanism. + * @property network The network we are using (it will be checked the bitcoin node network matches this). + * @property walletName The wallet name in the bitcoin node. + * @property syncParams Sync parameters. + */ +data class RpcConfig( + val url: String, + val auth: Auth, + val network: Network, + val walletName: String, + val syncParams: RcpSyncParams?, +) + /** * Type that can contain any of the blockchain configurations defined by the library. * @@ -161,6 +211,9 @@ sealed class BlockchainConfig { /** Esplora client. */ data class Esplora(val config: EsploraConfig) : BlockchainConfig() + + /** Bitcoin Core RPC client. */ + data class Rpc(val config: RpcConfig) : BlockchainConfig() } /**