Compare commits
16 Commits
release/0.
...
release/0.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f6f736609f | ||
|
|
5cb0726780 | ||
|
|
8781599740 | ||
|
|
ee8b992f8b | ||
|
|
a2e26f1b57 | ||
|
|
5f5744e897 | ||
|
|
e106136227 | ||
|
|
b638039655 | ||
|
|
7e085a86dd | ||
|
|
59f795f176 | ||
|
|
2da10382e7 | ||
|
|
6d18502733 | ||
|
|
81b263f235 | ||
|
|
2f38d3e526 | ||
|
|
2ee125655b | ||
|
|
8c21bcf40a |
4
.github/workflows/cont_integration.yml
vendored
4
.github/workflows/cont_integration.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
rust:
|
||||
- 1.53.0 # STABLE
|
||||
- 1.56.0 # STABLE
|
||||
- 1.46.0 # MSRV
|
||||
features:
|
||||
- default
|
||||
@@ -135,7 +135,7 @@ jobs:
|
||||
- run: sudo apt-get update || exit 1
|
||||
- run: sudo apt-get install -y libclang-common-10-dev clang-10 libc6-dev-i386 || exit 1
|
||||
- name: Set default toolchain
|
||||
run: rustup default 1.53.0 # STABLE
|
||||
run: rustup default 1.56.0 # STABLE
|
||||
- name: Set profile
|
||||
run: rustup set profile minimal
|
||||
- name: Add target wasm32
|
||||
|
||||
@@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [v0.13.0] - [v0.12.0]
|
||||
|
||||
- Exposed `get_tx()` method from `Database` to `Wallet`.
|
||||
|
||||
## [v0.12.0] - [v0.11.0]
|
||||
|
||||
@@ -384,4 +387,5 @@ final transaction is created by calling `finish` on the builder.
|
||||
[v0.9.0]: https://github.com/bitcoindevkit/bdk/compare/v0.8.0...v0.9.0
|
||||
[v0.10.0]: https://github.com/bitcoindevkit/bdk/compare/v0.9.0...v0.10.0
|
||||
[v0.11.0]: https://github.com/bitcoindevkit/bdk/compare/v0.10.0...v0.11.0
|
||||
[v0.12.0]: https://github.com/bitcoindevkit/bdk/compare/v0.11.0...v0.12.0
|
||||
[v0.12.0]: https://github.com/bitcoindevkit/bdk/compare/v0.11.0...v0.12.0
|
||||
[v0.13.0]: https://github.com/bitcoindevkit/bdk/compare/v0.12.0...v0.13.0
|
||||
20
Cargo.toml
20
Cargo.toml
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bdk"
|
||||
version = "0.12.1-dev"
|
||||
version = "0.13.1-dev"
|
||||
edition = "2018"
|
||||
authors = ["Alekos Filini <alekos.filini@gmail.com>", "Riccardo Casatta <riccardo@casatta.it>"]
|
||||
homepage = "https://bitcoindevkit.org"
|
||||
@@ -24,8 +24,9 @@ rand = "^0.7"
|
||||
sled = { version = "0.34", optional = true }
|
||||
electrum-client = { version = "0.8", optional = true }
|
||||
rusqlite = { version = "0.25.3", optional = true }
|
||||
ahash = { version = "=0.7.4", optional = true }
|
||||
reqwest = { version = "0.11", optional = true, features = ["json"] }
|
||||
ureq = { version = "2.1", features = ["json"], optional = true }
|
||||
ureq = { version = "~2.2.0", features = ["json"], optional = true }
|
||||
futures = { version = "0.3", optional = true }
|
||||
async-trait = { version = "0.1", optional = true }
|
||||
rocksdb = { version = "0.14", default-features = false, features = ["snappy"], optional = true }
|
||||
@@ -37,11 +38,14 @@ lazy_static = { version = "1.4", optional = true }
|
||||
# MSRV is 1.46, to fix this until we update our MSRV or replace the tiny-bip39
|
||||
# dependency https://github.com/bitcoindevkit/bdk/issues/399 we can only use an older version
|
||||
tiny-bip39 = { version = "< 0.8", optional = true }
|
||||
# backtrace > 0.3.61 includes object v0.27 which doesn't compile on 1.46. this is used by
|
||||
# tiny-bip39
|
||||
backtrace = { version = "=0.3.61", optional = true }
|
||||
|
||||
bitcoinconsensus = { version = "0.19.0-3", optional = true }
|
||||
|
||||
# Needed by bdk_blockchain_tests macro
|
||||
core-rpc = { version = "0.14", optional = true }
|
||||
bitcoincore-rpc = { version = "0.14", optional = true }
|
||||
|
||||
# Platform-specific dependencies
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
@@ -57,12 +61,12 @@ minimal = []
|
||||
compiler = ["miniscript/compiler"]
|
||||
verify = ["bitcoinconsensus"]
|
||||
default = ["key-value-db", "electrum"]
|
||||
sqlite = ["rusqlite"]
|
||||
sqlite = ["rusqlite", "ahash"]
|
||||
compact_filters = ["rocksdb", "socks", "lazy_static", "cc"]
|
||||
key-value-db = ["sled"]
|
||||
all-keys = ["keys-bip39"]
|
||||
keys-bip39 = ["tiny-bip39"]
|
||||
rpc = ["core-rpc"]
|
||||
keys-bip39 = ["tiny-bip39", "backtrace"]
|
||||
rpc = ["bitcoincore-rpc"]
|
||||
|
||||
# We currently provide mulitple implementations of `Blockchain`, all are
|
||||
# blocking except for the `EsploraBlockchain` which can be either async or
|
||||
@@ -87,7 +91,7 @@ esplora = []
|
||||
|
||||
|
||||
# Debug/Test features
|
||||
test-blockchains = ["core-rpc", "electrum-client"]
|
||||
test-blockchains = ["bitcoincore-rpc", "electrum-client"]
|
||||
test-electrum = ["electrum", "electrsd/electrs_0_8_10", "test-blockchains"]
|
||||
test-rpc = ["rpc", "electrsd/electrs_0_8_10", "test-blockchains"]
|
||||
test-esplora = ["electrsd/legacy", "electrsd/esplora_a33e97e1", "test-blockchains"]
|
||||
@@ -97,7 +101,7 @@ test-md-docs = ["electrum"]
|
||||
lazy_static = "1.4"
|
||||
env_logger = "0.7"
|
||||
clap = "2.33"
|
||||
electrsd = { version= "0.10", features = ["trigger", "bitcoind_0_21_1"] }
|
||||
electrsd = { version= "0.12", features = ["trigger", "bitcoind_0_21_1"] }
|
||||
|
||||
[[example]]
|
||||
name = "address_validator"
|
||||
|
||||
@@ -70,7 +70,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
let policy_str = matches.value_of("POLICY").unwrap();
|
||||
info!("Compiling policy: {}", policy_str);
|
||||
|
||||
let policy = Concrete::<String>::from_str(&policy_str)?;
|
||||
let policy = Concrete::<String>::from_str(policy_str)?;
|
||||
|
||||
let descriptor = match matches.value_of("TYPE").unwrap() {
|
||||
"sh" => Descriptor::new_sh(policy.compile()?)?,
|
||||
|
||||
@@ -254,7 +254,7 @@ impl Blockchain for CompactFiltersBlockchain {
|
||||
let total_cost = headers_cost + filters_cost + PROCESS_BLOCKS_COST;
|
||||
|
||||
if let Some(snapshot) = sync::sync_headers(
|
||||
Arc::clone(&first_peer),
|
||||
Arc::clone(first_peer),
|
||||
Arc::clone(&self.headers),
|
||||
|new_height| {
|
||||
let local_headers_cost =
|
||||
@@ -275,7 +275,7 @@ impl Blockchain for CompactFiltersBlockchain {
|
||||
let buried_height = synced_height.saturating_sub(sync::BURIED_CONFIRMATIONS);
|
||||
info!("Synced headers to height: {}", synced_height);
|
||||
|
||||
cf_sync.prepare_sync(Arc::clone(&first_peer))?;
|
||||
cf_sync.prepare_sync(Arc::clone(first_peer))?;
|
||||
|
||||
let all_scripts = Arc::new(
|
||||
database
|
||||
@@ -294,7 +294,7 @@ impl Blockchain for CompactFiltersBlockchain {
|
||||
let mut threads = Vec::with_capacity(self.peers.len());
|
||||
for peer in &self.peers {
|
||||
let cf_sync = Arc::clone(&cf_sync);
|
||||
let peer = Arc::clone(&peer);
|
||||
let peer = Arc::clone(peer);
|
||||
let headers = Arc::clone(&self.headers);
|
||||
let all_scripts = Arc::clone(&all_scripts);
|
||||
let last_synced_block = Arc::clone(&last_synced_block);
|
||||
|
||||
@@ -262,7 +262,7 @@ impl Peer {
|
||||
let message_resp = {
|
||||
let mut lock = responses.write().unwrap();
|
||||
let message_resp = lock.entry(wait_for).or_default();
|
||||
Arc::clone(&message_resp)
|
||||
Arc::clone(message_resp)
|
||||
};
|
||||
|
||||
let (lock, cvar) = &*message_resp;
|
||||
@@ -379,7 +379,7 @@ impl Peer {
|
||||
let message_resp = {
|
||||
let mut lock = reader_thread_responses.write().unwrap();
|
||||
let message_resp = lock.entry(in_message.cmd()).or_default();
|
||||
Arc::clone(&message_resp)
|
||||
Arc::clone(message_resp)
|
||||
};
|
||||
|
||||
let (lock, cvar) = &*message_resp;
|
||||
|
||||
@@ -760,7 +760,7 @@ impl CfStore {
|
||||
let cf_headers: Vec<FilterHeader> = filter_hashes
|
||||
.into_iter()
|
||||
.scan(checkpoint, |prev_header, filter_hash| {
|
||||
let filter_header = filter_hash.filter_header(&prev_header);
|
||||
let filter_header = filter_hash.filter_header(prev_header);
|
||||
*prev_header = filter_header;
|
||||
|
||||
Some(filter_header)
|
||||
@@ -801,7 +801,7 @@ impl CfStore {
|
||||
.zip(headers.into_iter())
|
||||
.scan(checkpoint, |prev_header, ((_, filter_content), header)| {
|
||||
let filter = BlockFilter::new(&filter_content);
|
||||
if header != filter.filter_header(&prev_header) {
|
||||
if header != filter.filter_header(prev_header) {
|
||||
return Some(Err(CompactFiltersError::InvalidFilter));
|
||||
}
|
||||
*prev_header = header;
|
||||
|
||||
@@ -205,7 +205,7 @@ impl CfSync {
|
||||
let block_hash = self.headers_store.get_block_hash(height)?.unwrap();
|
||||
|
||||
// TODO: also download random blocks?
|
||||
if process(&block_hash, &BlockFilter::new(&filter))? {
|
||||
if process(&block_hash, &BlockFilter::new(filter))? {
|
||||
log::debug!("Downloading block {}", block_hash);
|
||||
|
||||
let block = peer
|
||||
|
||||
@@ -38,13 +38,13 @@ use crate::database::{BatchDatabase, DatabaseUtils};
|
||||
use crate::descriptor::{get_checksum, IntoWalletDescriptor};
|
||||
use crate::wallet::utils::SecpCtx;
|
||||
use crate::{ConfirmationTime, Error, FeeRate, KeychainKind, LocalUtxo, TransactionDetails};
|
||||
use core_rpc::json::{
|
||||
use bitcoincore_rpc::json::{
|
||||
GetAddressInfoResultLabel, ImportMultiOptions, ImportMultiRequest,
|
||||
ImportMultiRequestScriptPubkey, ImportMultiRescanSince,
|
||||
};
|
||||
use core_rpc::jsonrpc::serde_json::Value;
|
||||
use core_rpc::Auth as RpcAuth;
|
||||
use core_rpc::{Client, RpcApi};
|
||||
use bitcoincore_rpc::jsonrpc::serde_json::Value;
|
||||
use bitcoincore_rpc::Auth as RpcAuth;
|
||||
use bitcoincore_rpc::{Client, RpcApi};
|
||||
use log::debug;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
@@ -82,7 +82,7 @@ pub struct RpcConfig {
|
||||
pub skip_blocks: Option<u32>,
|
||||
}
|
||||
|
||||
/// This struct is equivalent to [core_rpc::Auth] but it implements [serde::Serialize]
|
||||
/// 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), see [rust-bitcoincore-rpc/pull/181](https://github.com/rust-bitcoin/rust-bitcoincore-rpc/pull/181)
|
||||
#[derive(Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
|
||||
@@ -156,7 +156,7 @@ impl Blockchain for RpcBlockchain {
|
||||
.iter()
|
||||
.map(|s| ImportMultiRequest {
|
||||
timestamp: ImportMultiRescanSince::Timestamp(0),
|
||||
script_pubkey: Some(ImportMultiRequestScriptPubkey::Script(&s)),
|
||||
script_pubkey: Some(ImportMultiRequestScriptPubkey::Script(s)),
|
||||
watchonly: Some(true),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -238,7 +238,7 @@ impl Blockchain for RpcBlockchain {
|
||||
txid, confirmation_time
|
||||
);
|
||||
known_tx.confirmation_time = confirmation_time;
|
||||
db.set_tx(&known_tx)?;
|
||||
db.set_tx(known_tx)?;
|
||||
}
|
||||
} else {
|
||||
//TODO check there is already the raw tx in db?
|
||||
@@ -427,13 +427,13 @@ where
|
||||
{
|
||||
//TODO check descriptors contains only public keys
|
||||
let descriptor = descriptor
|
||||
.into_wallet_descriptor(&secp, network)?
|
||||
.into_wallet_descriptor(secp, network)?
|
||||
.0
|
||||
.to_string();
|
||||
let mut wallet_name = get_checksum(&descriptor[..descriptor.find('#').unwrap()])?;
|
||||
if let Some(change_descriptor) = change_descriptor {
|
||||
let change_descriptor = change_descriptor
|
||||
.into_wallet_descriptor(&secp, network)?
|
||||
.into_wallet_descriptor(secp, network)?
|
||||
.0
|
||||
.to_string();
|
||||
wallet_name.push_str(
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
//! This module defines an in-memory database type called [`MemoryDatabase`] that is based on a
|
||||
//! [`BTreeMap`].
|
||||
|
||||
use std::any::Any;
|
||||
use std::collections::BTreeMap;
|
||||
use std::ops::Bound::{Excluded, Included};
|
||||
|
||||
@@ -110,7 +111,7 @@ fn after(key: &[u8]) -> Vec<u8> {
|
||||
/// [`database`]: crate::database
|
||||
#[derive(Debug, Default)]
|
||||
pub struct MemoryDatabase {
|
||||
map: BTreeMap<Vec<u8>, Box<dyn std::any::Any>>,
|
||||
map: BTreeMap<Vec<u8>, Box<dyn Any + Send + Sync>>,
|
||||
deleted_keys: Vec<Vec<u8>>,
|
||||
}
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ pub enum Error {
|
||||
Sled(sled::Error),
|
||||
#[cfg(feature = "rpc")]
|
||||
/// Rpc client error
|
||||
Rpc(core_rpc::Error),
|
||||
Rpc(bitcoincore_rpc::Error),
|
||||
#[cfg(feature = "sqlite")]
|
||||
/// Rusqlite client error
|
||||
Rusqlite(rusqlite::Error),
|
||||
@@ -196,7 +196,7 @@ impl_error!(electrum_client::Error, Electrum);
|
||||
#[cfg(feature = "key-value-db")]
|
||||
impl_error!(sled::Error, Sled);
|
||||
#[cfg(feature = "rpc")]
|
||||
impl_error!(core_rpc::Error, Rpc);
|
||||
impl_error!(bitcoincore_rpc::Error, Rpc);
|
||||
#[cfg(feature = "sqlite")]
|
||||
impl_error!(rusqlite::Error, Rusqlite);
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ pub type MnemonicWithPassphrase = (Mnemonic, Option<String>);
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
|
||||
impl<Ctx: ScriptContext> DerivableKey<Ctx> for Seed {
|
||||
fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
|
||||
Ok(bip32::ExtendedPrivKey::new_master(Network::Bitcoin, &self.as_bytes())?.into())
|
||||
Ok(bip32::ExtendedPrivKey::new_master(Network::Bitcoin, self.as_bytes())?.into())
|
||||
}
|
||||
|
||||
fn into_descriptor_key(
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
//! interact with the bitcoin P2P network.
|
||||
//!
|
||||
//! ```toml
|
||||
//! bdk = "0.12.0"
|
||||
//! bdk = "0.13.0"
|
||||
//! ```
|
||||
#![cfg_attr(
|
||||
feature = "electrum",
|
||||
@@ -236,7 +236,7 @@ extern crate bdk_macros;
|
||||
extern crate lazy_static;
|
||||
|
||||
#[cfg(feature = "rpc")]
|
||||
pub extern crate core_rpc;
|
||||
pub extern crate bitcoincore_rpc;
|
||||
|
||||
#[cfg(feature = "electrum")]
|
||||
pub extern crate electrum_client;
|
||||
|
||||
@@ -3,11 +3,11 @@ use bitcoin::consensus::encode::{deserialize, serialize};
|
||||
use bitcoin::hashes::hex::{FromHex, ToHex};
|
||||
use bitcoin::hashes::sha256d;
|
||||
use bitcoin::{Address, Amount, Script, Transaction, Txid};
|
||||
pub use bitcoincore_rpc::bitcoincore_rpc_json::AddressType;
|
||||
pub use bitcoincore_rpc::{Auth, Client as RpcClient, RpcApi};
|
||||
use core::str::FromStr;
|
||||
pub use core_rpc::core_rpc_json::AddressType;
|
||||
pub use core_rpc::{Auth, Client as RpcClient, RpcApi};
|
||||
use electrsd::bitcoind::BitcoinD;
|
||||
use electrsd::{bitcoind, Conf, ElectrsD};
|
||||
use electrsd::{bitcoind, ElectrsD};
|
||||
pub use electrum_client::{Client as ElectrumClient, ElectrumApi};
|
||||
#[allow(unused_imports)]
|
||||
use log::{debug, error, info, log_enabled, trace, Level};
|
||||
@@ -24,19 +24,15 @@ pub struct TestClient {
|
||||
impl TestClient {
|
||||
pub fn new(bitcoind_exe: String, electrs_exe: String) -> Self {
|
||||
debug!("launching {} and {}", &bitcoind_exe, &electrs_exe);
|
||||
let conf = bitcoind::Conf {
|
||||
view_stdout: log_enabled!(Level::Debug),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let mut conf = bitcoind::Conf::default();
|
||||
conf.view_stdout = log_enabled!(Level::Debug);
|
||||
let bitcoind = BitcoinD::with_conf(bitcoind_exe, &conf).unwrap();
|
||||
|
||||
let http_enabled = cfg!(feature = "test-esplora");
|
||||
let mut conf = electrsd::Conf::default();
|
||||
conf.view_stderr = log_enabled!(Level::Debug);
|
||||
conf.http_enabled = cfg!(feature = "test-esplora");
|
||||
|
||||
let conf = Conf {
|
||||
http_enabled,
|
||||
view_stderr: log_enabled!(Level::Debug),
|
||||
..Default::default()
|
||||
};
|
||||
let electrsd = ElectrsD::with_conf(electrs_exe, &bitcoind, &conf).unwrap();
|
||||
|
||||
let node_address = bitcoind.client.get_new_address(None, None).unwrap();
|
||||
|
||||
@@ -323,7 +323,7 @@ where
|
||||
|
||||
/// Return the list of unspent outputs of this wallet
|
||||
///
|
||||
/// Note that this methods only operate on the internal database, which first needs to be
|
||||
/// Note that this method only operates on the internal database, which first needs to be
|
||||
/// [`Wallet::sync`] manually.
|
||||
pub fn list_unspent(&self) -> Result<Vec<LocalUtxo>, Error> {
|
||||
self.database.borrow().iter_utxos()
|
||||
@@ -335,6 +335,21 @@ where
|
||||
self.database.borrow().get_utxo(&outpoint)
|
||||
}
|
||||
|
||||
/// Return a single transactions made and received by the wallet
|
||||
///
|
||||
/// Optionally fill the [`TransactionDetails::transaction`] field with the raw transaction if
|
||||
/// `include_raw` is `true`.
|
||||
///
|
||||
/// Note that this method only operates on the internal database, which first needs to be
|
||||
/// [`Wallet::sync`] manually.
|
||||
pub fn get_tx(
|
||||
&self,
|
||||
txid: &Txid,
|
||||
include_raw: bool,
|
||||
) -> Result<Option<TransactionDetails>, Error> {
|
||||
self.database.borrow().get_tx(txid, include_raw)
|
||||
}
|
||||
|
||||
/// Return the list of transactions made and received by the wallet
|
||||
///
|
||||
/// Optionally fill the [`TransactionDetails::transaction`] field with the raw transaction if
|
||||
|
||||
Reference in New Issue
Block a user