Merge bitcoindevkit/bdk-ffi#125: Add RpcConfig, BlockchainConfig::Rpc, and Auth
4ed6e364e68648a3b5cf6773e8d74b74d922b315 Add API docs for RPC blockchain config and auth (thunderbiscuit)
d0cd3b0f389c10610ad58a999d42b4b7ca39ba6c Add Auth, RpcSyncParams, and RpcConfig (Steve Myers)
Pull request description:
  Fixes #117. This adds the RPC blockchain config but I don't currently have a way to test it as part of the `bdk-kotlin` or `bdk-swift` automated testing, which would need to be able to spin up a local regtest bitcoind for the tests.
  For now this will only be manually tested.
ACKs for top commit:
  thunderbiscuit:
    ACK [4ed6e36](4ed6e364e6).
Tree-SHA512: 2f114753a683c32ec957b26e23918eb3c1de07073fd0293e06fb960f8226f09d4d9ebf89f8d04f9da5cd459619f224d732b81e21c2173afeccb8ce56cc558582
			
			
This commit is contained in:
		
						commit
						41fdadb09c
					
				
							
								
								
									
										46
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										46
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @ -107,6 +107,15 @@ version = "0.13.1" | |||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" | 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]] | [[package]] | ||||||
| name = "bdk" | name = "bdk" | ||||||
| version = "0.25.0" | version = "0.25.0" | ||||||
| @ -118,6 +127,7 @@ dependencies = [ | |||||||
|  "bdk-macros", |  "bdk-macros", | ||||||
|  "bip39", |  "bip39", | ||||||
|  "bitcoin", |  "bitcoin", | ||||||
|  |  "bitcoincore-rpc", | ||||||
|  "electrum-client", |  "electrum-client", | ||||||
|  "esplora-client", |  "esplora-client", | ||||||
|  "getrandom", |  "getrandom", | ||||||
| @ -218,6 +228,30 @@ dependencies = [ | |||||||
|  "serde", |  "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]] | [[package]] | ||||||
| name = "bitflags" | name = "bitflags" | ||||||
| version = "1.3.2" | version = "1.3.2" | ||||||
| @ -567,6 +601,18 @@ dependencies = [ | |||||||
|  "wasm-bindgen", |  "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]] | [[package]] | ||||||
| name = "lazy_static" | name = "lazy_static" | ||||||
| version = "1.4.0" | version = "1.4.0" | ||||||
|  | |||||||
| @ -123,7 +123,7 @@ data class SledDbConfiguration( | |||||||
|  * |  * | ||||||
|  * @sample org.bitcoindevkit.electrumBlockchainConfigSample |  * @sample org.bitcoindevkit.electrumBlockchainConfigSample | ||||||
|  */ |  */ | ||||||
| data class ElectrumConfig ( | data class ElectrumConfig( | ||||||
|     var url: String, |     var url: String, | ||||||
|     var socks5: String?, |     var socks5: String?, | ||||||
|     var retry: UByte, |     var retry: UByte, | ||||||
| @ -142,7 +142,7 @@ data class ElectrumConfig ( | |||||||
|  * |  * | ||||||
|  * @sample org.bitcoindevkit.esploraBlockchainConfigSample |  * @sample org.bitcoindevkit.esploraBlockchainConfigSample | ||||||
|  */ |  */ | ||||||
| data class EsploraConfig ( | data class EsploraConfig( | ||||||
|     var baseUrl: String, |     var baseUrl: String, | ||||||
|     var proxy: String?, |     var proxy: String?, | ||||||
|     var concurrency: UByte?, |     var concurrency: UByte?, | ||||||
| @ -150,6 +150,56 @@ data class EsploraConfig ( | |||||||
|     var timeout: ULong? |     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. |  * Type that can contain any of the blockchain configurations defined by the library. | ||||||
|  * |  * | ||||||
| @ -161,6 +211,9 @@ sealed class BlockchainConfig { | |||||||
| 
 | 
 | ||||||
|     /** Esplora client. */ |     /** Esplora client. */ | ||||||
|     data class Esplora(val config: EsploraConfig) : BlockchainConfig() |     data class Esplora(val config: EsploraConfig) : BlockchainConfig() | ||||||
|  | 
 | ||||||
|  |     /** Bitcoin Core RPC client. */ | ||||||
|  |     data class Rpc(val config: RpcConfig) : BlockchainConfig() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  | |||||||
| @ -10,7 +10,7 @@ crate-type = ["staticlib", "cdylib"] | |||||||
| name = "bdkffi" | name = "bdkffi" | ||||||
| 
 | 
 | ||||||
| [dependencies] | [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_macros = { version = "0.21.0", features = ["builtin-bindgen"] } | ||||||
| uniffi = { version = "0.21.0", features = ["builtin-bindgen"] } | uniffi = { version = "0.21.0", features = ["builtin-bindgen"] } | ||||||
|  | |||||||
| @ -45,6 +45,7 @@ enum BdkError { | |||||||
|   "Esplora", |   "Esplora", | ||||||
|   "Sled", |   "Sled", | ||||||
|   "Rusqlite", |   "Rusqlite", | ||||||
|  |   "Rpc", | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| dictionary AddressInfo { | dictionary AddressInfo { | ||||||
| @ -126,10 +127,33 @@ dictionary EsploraConfig { | |||||||
|   u64? timeout; |   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] | [Enum] | ||||||
| interface BlockchainConfig { | interface BlockchainConfig { | ||||||
|   Electrum(ElectrumConfig config); |   Electrum(ElectrumConfig config); | ||||||
|   Esplora(EsploraConfig config); |   Esplora(EsploraConfig config); | ||||||
|  |   Rpc(RpcConfig config); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| interface Blockchain { | interface Blockchain { | ||||||
|  | |||||||
| @ -7,10 +7,12 @@ use bdk::bitcoin::util::psbt::PartiallySignedTransaction as BdkPartiallySignedTr | |||||||
| use bdk::bitcoin::Sequence; | use bdk::bitcoin::Sequence; | ||||||
| use bdk::bitcoin::{Address as BdkAddress, Network, OutPoint as BdkOutPoint, Txid}; | use bdk::bitcoin::{Address as BdkAddress, Network, OutPoint as BdkOutPoint, Txid}; | ||||||
| use bdk::blockchain::any::{AnyBlockchain, AnyBlockchainConfig}; | use bdk::blockchain::any::{AnyBlockchain, AnyBlockchainConfig}; | ||||||
|  | use bdk::blockchain::rpc::Auth as BdkAuth; | ||||||
| use bdk::blockchain::GetBlockHash; | use bdk::blockchain::GetBlockHash; | ||||||
| use bdk::blockchain::GetHeight; | use bdk::blockchain::GetHeight; | ||||||
| use bdk::blockchain::{ | 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::blockchain::{Blockchain as BdkBlockchain, Progress as BdkProgress}; | ||||||
| use bdk::database::any::{AnyDatabase, SledDbConfiguration, SqliteDbConfiguration}; | use bdk::database::any::{AnyDatabase, SledDbConfiguration, SqliteDbConfiguration}; | ||||||
| @ -34,6 +36,7 @@ use std::collections::HashSet; | |||||||
| use std::convert::{From, TryFrom}; | use std::convert::{From, TryFrom}; | ||||||
| use std::fmt; | use std::fmt; | ||||||
| use std::ops::Deref; | use std::ops::Deref; | ||||||
|  | use std::path::PathBuf; | ||||||
| use std::str::FromStr; | use std::str::FromStr; | ||||||
| use std::sync::{Arc, Mutex, MutexGuard}; | use std::sync::{Arc, Mutex, MutexGuard}; | ||||||
| 
 | 
 | ||||||
| @ -134,12 +137,84 @@ pub struct EsploraConfig { | |||||||
|     pub timeout: Option<u64>, |     pub timeout: Option<u64>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 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<Auth> 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<RpcSyncParams> 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<RpcSyncParams>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /// Type that can contain any of the blockchain configurations defined by the library.
 | /// Type that can contain any of the blockchain configurations defined by the library.
 | ||||||
| pub enum BlockchainConfig { | pub enum BlockchainConfig { | ||||||
|     /// Electrum client
 |     /// Electrum client
 | ||||||
|     Electrum { config: ElectrumConfig }, |     Electrum { config: ElectrumConfig }, | ||||||
|     /// Esplora client
 |     /// Esplora client
 | ||||||
|     Esplora { config: EsploraConfig }, |     Esplora { config: EsploraConfig }, | ||||||
|  |     /// Bitcoin Core RPC client
 | ||||||
|  |     Rpc { config: RpcConfig }, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// A wallet transaction
 | /// A wallet transaction
 | ||||||
| @ -200,6 +275,13 @@ impl Blockchain { | |||||||
|                     timeout: config.timeout, |                     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)?; |         let blockchain = AnyBlockchain::from_config(&any_blockchain_config)?; | ||||||
|         Ok(Self { |         Ok(Self { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user