Merge commit 'refs/pull/407/head' of github.com:bitcoindevkit/bdk

This commit is contained in:
Alekos Filini 2021-07-28 11:34:41 +02:00
commit 2b0c4f0817
No known key found for this signature in database
GPG Key ID: 431401E4A4530061
4 changed files with 74 additions and 9 deletions

View File

@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
- Added `RpcBlockchain` in the `AnyBlockchain` struct to allow using Rpc backend where `AnyBlockchain` is used (eg `bdk-cli`)
### Wallet ### Wallet
- Removed and replaced `set_single_recipient` with more general `drain_to` and replaced `maintain_single_recipient` with `allow_shrinking`. - Removed and replaced `set_single_recipient` with more general `drain_to` and replaced `maintain_single_recipient` with `allow_shrinking`.

View File

@ -94,6 +94,8 @@ macro_rules! impl_inner_method {
AnyBlockchain::Esplora(inner) => inner.$name( $($args, )* ), AnyBlockchain::Esplora(inner) => inner.$name( $($args, )* ),
#[cfg(feature = "compact_filters")] #[cfg(feature = "compact_filters")]
AnyBlockchain::CompactFilters(inner) => inner.$name( $($args, )* ), AnyBlockchain::CompactFilters(inner) => inner.$name( $($args, )* ),
#[cfg(feature = "rpc")]
AnyBlockchain::Rpc(inner) => inner.$name( $($args, )* ),
} }
} }
} }
@ -116,6 +118,10 @@ pub enum AnyBlockchain {
#[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))] #[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))]
/// Compact filters client /// Compact filters client
CompactFilters(compact_filters::CompactFiltersBlockchain), CompactFilters(compact_filters::CompactFiltersBlockchain),
#[cfg(feature = "rpc")]
#[cfg_attr(docsrs, doc(cfg(feature = "rpc")))]
/// RPC client
Rpc(rpc::RpcBlockchain),
} }
#[maybe_async] #[maybe_async]
@ -157,6 +163,7 @@ impl Blockchain for AnyBlockchain {
impl_from!(electrum::ElectrumBlockchain, AnyBlockchain, Electrum, #[cfg(feature = "electrum")]); impl_from!(electrum::ElectrumBlockchain, AnyBlockchain, Electrum, #[cfg(feature = "electrum")]);
impl_from!(esplora::EsploraBlockchain, AnyBlockchain, Esplora, #[cfg(feature = "esplora")]); impl_from!(esplora::EsploraBlockchain, AnyBlockchain, Esplora, #[cfg(feature = "esplora")]);
impl_from!(compact_filters::CompactFiltersBlockchain, AnyBlockchain, CompactFilters, #[cfg(feature = "compact_filters")]); impl_from!(compact_filters::CompactFiltersBlockchain, AnyBlockchain, CompactFilters, #[cfg(feature = "compact_filters")]);
impl_from!(rpc::RpcBlockchain, AnyBlockchain, Rpc, #[cfg(feature = "rpc")]);
/// 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
/// ///
@ -206,6 +213,10 @@ pub enum AnyBlockchainConfig {
#[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))] #[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))]
/// Compact filters client /// Compact filters client
CompactFilters(compact_filters::CompactFiltersBlockchainConfig), CompactFilters(compact_filters::CompactFiltersBlockchainConfig),
#[cfg(feature = "rpc")]
#[cfg_attr(docsrs, doc(cfg(feature = "rpc")))]
/// RPC client configuration
Rpc(rpc::RpcConfig),
} }
impl ConfigurableBlockchain for AnyBlockchain { impl ConfigurableBlockchain for AnyBlockchain {
@ -225,6 +236,10 @@ impl ConfigurableBlockchain for AnyBlockchain {
AnyBlockchainConfig::CompactFilters(inner) => AnyBlockchain::CompactFilters( AnyBlockchainConfig::CompactFilters(inner) => AnyBlockchain::CompactFilters(
compact_filters::CompactFiltersBlockchain::from_config(inner)?, compact_filters::CompactFiltersBlockchain::from_config(inner)?,
), ),
#[cfg(feature = "rpc")]
AnyBlockchainConfig::Rpc(inner) => {
AnyBlockchain::Rpc(rpc::RpcBlockchain::from_config(inner)?)
}
}) })
} }
} }
@ -232,3 +247,4 @@ impl ConfigurableBlockchain for AnyBlockchain {
impl_from!(electrum::ElectrumBlockchainConfig, AnyBlockchainConfig, Electrum, #[cfg(feature = "electrum")]); impl_from!(electrum::ElectrumBlockchainConfig, AnyBlockchainConfig, Electrum, #[cfg(feature = "electrum")]);
impl_from!(esplora::EsploraBlockchainConfig, AnyBlockchainConfig, Esplora, #[cfg(feature = "esplora")]); impl_from!(esplora::EsploraBlockchainConfig, AnyBlockchainConfig, Esplora, #[cfg(feature = "esplora")]);
impl_from!(compact_filters::CompactFiltersBlockchainConfig, AnyBlockchainConfig, CompactFilters, #[cfg(feature = "compact_filters")]); impl_from!(compact_filters::CompactFiltersBlockchainConfig, AnyBlockchainConfig, CompactFilters, #[cfg(feature = "compact_filters")]);
impl_from!(rpc::RpcConfig, AnyBlockchainConfig, Rpc, #[cfg(feature = "rpc")]);

View File

@ -30,9 +30,19 @@ use crate::FeeRate;
#[cfg(any(feature = "electrum", feature = "esplora"))] #[cfg(any(feature = "electrum", feature = "esplora"))]
pub(crate) mod utils; pub(crate) mod utils;
#[cfg(any(feature = "electrum", feature = "esplora", feature = "compact_filters"))] #[cfg(any(
feature = "electrum",
feature = "esplora",
feature = "compact_filters",
feature = "rpc"
))]
pub mod any; pub mod any;
#[cfg(any(feature = "electrum", feature = "esplora", feature = "compact_filters"))] #[cfg(any(
feature = "electrum",
feature = "esplora",
feature = "compact_filters",
feature = "rpc"
))]
pub use any::{AnyBlockchain, AnyBlockchainConfig}; pub use any::{AnyBlockchain, AnyBlockchainConfig};
#[cfg(feature = "electrum")] #[cfg(feature = "electrum")]

View File

@ -18,10 +18,12 @@
//! ## Example //! ## Example
//! //!
//! ```no_run //! ```no_run
//! # use bdk::blockchain::{RpcConfig, RpcBlockchain, ConfigurableBlockchain}; //! # use bdk::blockchain::{RpcConfig, RpcBlockchain, ConfigurableBlockchain, rpc::Auth};
//! let config = RpcConfig { //! let config = RpcConfig {
//! url: "127.0.0.1:18332".to_string(), //! url: "127.0.0.1:18332".to_string(),
//! auth: bitcoincore_rpc::Auth::CookieFile("/home/user/.bitcoin/.cookie".into()), //! auth: Auth::Cookie {
//! file: "/home/user/.bitcoin/.cookie".into(),
//! },
//! network: bdk::bitcoin::Network::Testnet, //! network: bdk::bitcoin::Network::Testnet,
//! wallet_name: "wallet_name".to_string(), //! wallet_name: "wallet_name".to_string(),
//! skip_blocks: None, //! skip_blocks: None,
@ -41,10 +43,12 @@ use bitcoincore_rpc::json::{
ImportMultiRequestScriptPubkey, ImportMultiRescanSince, ImportMultiRequestScriptPubkey, ImportMultiRescanSince,
}; };
use bitcoincore_rpc::jsonrpc::serde_json::Value; use bitcoincore_rpc::jsonrpc::serde_json::Value;
use bitcoincore_rpc::{Auth, Client, RpcApi}; use bitcoincore_rpc::Auth as RpcAuth;
use bitcoincore_rpc::{Client, RpcApi};
use log::debug; use log::debug;
use serde::Deserialize; use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::path::PathBuf;
use std::str::FromStr; use std::str::FromStr;
/// The main struct for RPC backend implementing the [crate::blockchain::Blockchain] trait /// The main struct for RPC backend implementing the [crate::blockchain::Blockchain] trait
@ -64,7 +68,7 @@ pub struct RpcBlockchain {
} }
/// RpcBlockchain configuration options /// RpcBlockchain configuration options
#[derive(Debug)] #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct RpcConfig { pub struct RpcConfig {
/// The bitcoin node url /// The bitcoin node url
pub url: String, pub url: String,
@ -78,6 +82,39 @@ pub struct RpcConfig {
pub skip_blocks: Option<u32>, pub skip_blocks: Option<u32>,
} }
/// This struct is equivalent to [bitcoincore_rpc::Auth] but it implements [serde::Serialize]
/// To be removed once upstream equivalent is implementing Serialize (json serialization format
/// should be the same) https://github.com/rust-bitcoin/rust-bitcoincore-rpc/pull/181
#[derive(Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
#[serde(untagged)]
pub enum Auth {
/// None 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: PathBuf,
},
}
impl From<Auth> for RpcAuth {
fn from(auth: Auth) -> Self {
match auth {
Auth::None => RpcAuth::None,
Auth::UserPass { username, password } => RpcAuth::UserPass(username, password),
Auth::Cookie { file } => RpcAuth::CookieFile(file),
}
}
}
impl RpcBlockchain { impl RpcBlockchain {
fn get_node_synced_height(&self) -> Result<u32, Error> { fn get_node_synced_height(&self) -> Result<u32, Error> {
let info = self.client.get_address_info(&self._storage_address)?; let info = self.client.get_address_info(&self._storage_address)?;
@ -320,7 +357,7 @@ impl ConfigurableBlockchain for RpcBlockchain {
let wallet_url = format!("{}/wallet/{}", config.url, &wallet_name); let wallet_url = format!("{}/wallet/{}", config.url, &wallet_name);
debug!("connecting to {} auth:{:?}", wallet_url, config.auth); debug!("connecting to {} auth:{:?}", wallet_url, config.auth);
let client = Client::new(wallet_url, config.auth.clone())?; let client = Client::new(wallet_url, config.auth.clone().into())?;
let loaded_wallets = client.list_wallets()?; let loaded_wallets = client.list_wallets()?;
if loaded_wallets.contains(&wallet_name) { if loaded_wallets.contains(&wallet_name) {
debug!("wallet already loaded {:?}", wallet_name); debug!("wallet already loaded {:?}", wallet_name);
@ -427,7 +464,7 @@ crate::bdk_blockchain_tests! {
fn test_instance(test_client: &TestClient) -> RpcBlockchain { fn test_instance(test_client: &TestClient) -> RpcBlockchain {
let config = RpcConfig { let config = RpcConfig {
url: test_client.bitcoind.rpc_url(), url: test_client.bitcoind.rpc_url(),
auth: Auth::CookieFile(test_client.bitcoind.params.cookie_file.clone()), auth: Auth::Cookie { file: test_client.bitcoind.params.cookie_file.clone() },
network: Network::Regtest, network: Network::Regtest,
wallet_name: format!("client-wallet-test-{:?}", std::time::SystemTime::now() ), wallet_name: format!("client-wallet-test-{:?}", std::time::SystemTime::now() ),
skip_blocks: None, skip_blocks: None,