diff --git a/CHANGELOG.md b/CHANGELOG.md index 22152cf4b..d1aca5dbb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - added `OldestFirstCoinSelection` impl to `CoinSelectionAlgorithm` - New MSRV set to `1.56` - Add traits to reuse `Blockchain`s across multiple wallets (`BlockchainFactory` and `StatelessBlockchain`). +- Upgrade to rust-bitcoin `0.28` ## [v0.18.0] - [v0.17.0] diff --git a/Cargo.toml b/Cargo.toml index 63d81e75f..bcbe43dff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,15 +14,15 @@ license = "MIT OR Apache-2.0" [dependencies] bdk-macros = "^0.6" log = "^0.4" -miniscript = { version = "^6.1", features = ["use-serde"] } -bitcoin = { version = "^0.27", features = ["use-serde", "base64"] } +miniscript = { version = "7.0", features = ["use-serde"] } +bitcoin = { version = "0.28", features = ["use-serde", "base64"] } serde = { version = "^1.0", features = ["derive"] } serde_json = { version = "^1.0" } rand = "^0.7" # Optional dependencies sled = { version = "0.34", optional = true } -electrum-client = { version = "0.8", optional = true } +electrum-client = { version = "0.10", optional = true } rusqlite = { version = "0.25.3", optional = true } ahash = { version = "=0.7.4", optional = true } reqwest = { version = "0.11", optional = true, default-features = false, features = ["json"] } @@ -37,8 +37,8 @@ lazy_static = { version = "1.4", optional = true } bip39 = { version = "1.0.1", optional = true } bitcoinconsensus = { version = "0.19.0-3", optional = true } -# Needed by bdk_blockchain_tests macro -bitcoincore-rpc = { version = "0.14", optional = true } +# Needed by bdk_blockchain_tests macro and the `rpc` feature +bitcoincore-rpc = { version = "0.15", optional = true } # Platform-specific dependencies [target.'cfg(not(target_arch = "wasm32"))'.dependencies] @@ -97,7 +97,7 @@ test-md-docs = ["electrum"] lazy_static = "1.4" env_logger = "0.7" clap = "2.33" -electrsd = { version= "0.15", features = ["trigger", "bitcoind_22_0"] } +electrsd = { version= "0.19.1", features = ["bitcoind_22_0"] } [[example]] name = "address_validator" diff --git a/src/blockchain/compact_filters/peer.rs b/src/blockchain/compact_filters/peer.rs index a8d65aa94..413ea1697 100644 --- a/src/blockchain/compact_filters/peer.rs +++ b/src/blockchain/compact_filters/peer.rs @@ -10,6 +10,7 @@ // licenses. use std::collections::HashMap; +use std::io::BufReader; use std::net::{TcpStream, ToSocketAddrs}; use std::sync::{Arc, Condvar, Mutex, RwLock}; use std::thread; @@ -19,14 +20,13 @@ use socks::{Socks5Stream, ToTargetAddr}; use rand::{thread_rng, Rng}; -use bitcoin::consensus::Encodable; +use bitcoin::consensus::{Decodable, Encodable}; use bitcoin::hash_types::BlockHash; use bitcoin::network::constants::ServiceFlags; use bitcoin::network::message::{NetworkMessage, RawNetworkMessage}; use bitcoin::network::message_blockdata::*; use bitcoin::network::message_filter::*; use bitcoin::network::message_network::VersionMessage; -use bitcoin::network::stream_reader::StreamReader; use bitcoin::network::Address; use bitcoin::{Block, Network, Transaction, Txid, Wtxid}; @@ -327,9 +327,10 @@ impl Peer { }; } - let mut reader = StreamReader::new(connection, None); + let mut reader = BufReader::new(connection); loop { - let raw_message: RawNetworkMessage = check_disconnect!(reader.read_next()); + let raw_message: RawNetworkMessage = + check_disconnect!(Decodable::consensus_decode(&mut reader)); let in_message = if raw_message.magic != network.magic() { continue; diff --git a/src/blockchain/esplora/api.rs b/src/blockchain/esplora/api.rs index 640f7a0bb..d548b5be8 100644 --- a/src/blockchain/esplora/api.rs +++ b/src/blockchain/esplora/api.rs @@ -2,7 +2,7 @@ //! //! see: use crate::BlockTime; -use bitcoin::{OutPoint, Script, Transaction, TxIn, TxOut, Txid}; +use bitcoin::{OutPoint, Script, Transaction, TxIn, TxOut, Txid, Witness}; #[derive(serde::Deserialize, Clone, Debug)] pub struct PrevOut { @@ -63,7 +63,7 @@ impl Tx { }, script_sig: vin.scriptsig, sequence: vin.sequence, - witness: vin.witness, + witness: Witness::from_vec(vin.witness), }) .collect(), output: self diff --git a/src/descriptor/derived.rs b/src/descriptor/derived.rs index b6556a0b6..585c39749 100644 --- a/src/descriptor/derived.rs +++ b/src/descriptor/derived.rs @@ -52,10 +52,10 @@ use std::hash::{Hash, Hasher}; use std::ops::Deref; use bitcoin::hashes::hash160; -use bitcoin::PublicKey; +use bitcoin::{PublicKey, XOnlyPublicKey}; -use miniscript::{descriptor::Wildcard, Descriptor, DescriptorPublicKey}; -use miniscript::{MiniscriptKey, ToPublicKey, TranslatePk}; +use miniscript::descriptor::{DescriptorSinglePub, SinglePubKey, Wildcard}; +use miniscript::{Descriptor, DescriptorPublicKey, MiniscriptKey, ToPublicKey, TranslatePk}; use crate::wallet::utils::SecpCtx; @@ -128,21 +128,44 @@ impl<'s> MiniscriptKey for DerivedDescriptorKey<'s> { fn is_uncompressed(&self) -> bool { self.0.is_uncompressed() } - fn serialized_len(&self) -> usize { - self.0.serialized_len() - } } impl<'s> ToPublicKey for DerivedDescriptorKey<'s> { fn to_public_key(&self) -> PublicKey { match &self.0 { - DescriptorPublicKey::SinglePub(ref spub) => spub.key.to_public_key(), - DescriptorPublicKey::XPub(ref xpub) => { + DescriptorPublicKey::SinglePub(DescriptorSinglePub { + key: SinglePubKey::XOnly(_), + .. + }) => panic!("Found x-only public key in non-tr descriptor"), + DescriptorPublicKey::SinglePub(DescriptorSinglePub { + key: SinglePubKey::FullKey(ref pk), + .. + }) => *pk, + DescriptorPublicKey::XPub(ref xpub) => PublicKey::new( + xpub.xkey + .derive_pub(self.1, &xpub.derivation_path) + .expect("Shouldn't fail, only normal derivations") + .public_key, + ), + } + } + + fn to_x_only_pubkey(&self) -> XOnlyPublicKey { + match &self.0 { + DescriptorPublicKey::SinglePub(DescriptorSinglePub { + key: SinglePubKey::XOnly(ref pk), + .. + }) => *pk, + DescriptorPublicKey::SinglePub(DescriptorSinglePub { + key: SinglePubKey::FullKey(ref pk), + .. + }) => XOnlyPublicKey::from(pk.inner), + DescriptorPublicKey::XPub(ref xpub) => XOnlyPublicKey::from( xpub.xkey .derive_pub(self.1, &xpub.derivation_path) .expect("Shouldn't fail, only normal derivations") - .public_key - } + .public_key, + ), } } diff --git a/src/descriptor/dsl.rs b/src/descriptor/dsl.rs index 9ba5bb52f..caee94bd2 100644 --- a/src/descriptor/dsl.rs +++ b/src/descriptor/dsl.rs @@ -1054,7 +1054,9 @@ mod test { } #[test] - #[should_panic(expected = "Miniscript(ContextError(CompressedOnly))")] + #[should_panic( + expected = "Miniscript(ContextError(CompressedOnly(\"04b4632d08485ff1df2db55b9dafd23347d1c47a457072a1e87be26896549a87378ec38ff91d43e8c2092ebda601780485263da089465619e0358a5c1be7ac91f4\")))" + )] fn test_dsl_miniscript_checks() { let mut uncompressed_pk = PrivateKey::from_wif("L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6").unwrap(); diff --git a/src/descriptor/mod.rs b/src/descriptor/mod.rs index 5b8a3babc..a6212e32d 100644 --- a/src/descriptor/mod.rs +++ b/src/descriptor/mod.rs @@ -17,9 +17,10 @@ use std::collections::{BTreeMap, HashMap, HashSet}; use std::ops::Deref; +use bitcoin::secp256k1; use bitcoin::util::bip32::{ChildNumber, DerivationPath, ExtendedPubKey, Fingerprint, KeySource}; use bitcoin::util::psbt; -use bitcoin::{Network, PublicKey, Script, TxOut}; +use bitcoin::{Network, Script, TxOut}; use miniscript::descriptor::{DescriptorType, InnerXKey}; pub use miniscript::{ @@ -58,7 +59,7 @@ pub type DerivedDescriptor<'s> = Descriptor>; /// /// [`psbt::Input`]: bitcoin::util::psbt::Input /// [`psbt::Output`]: bitcoin::util::psbt::Output -pub type HdKeyPaths = BTreeMap; +pub type HdKeyPaths = BTreeMap; /// Trait for types which can be converted into an [`ExtendedDescriptor`] and a [`KeyMap`] usable by a wallet in a specific [`Network`] pub trait IntoWalletDescriptor { @@ -306,6 +307,7 @@ pub(crate) trait DerivedDescriptorMeta { pub(crate) trait DescriptorMeta { fn is_witness(&self) -> bool; + fn is_taproot(&self) -> bool; fn get_extended_keys(&self) -> Result>, DescriptorError>; fn derive_from_hd_keypaths<'s>( &self, @@ -328,21 +330,21 @@ pub(crate) trait DescriptorScripts { impl<'s> DescriptorScripts for DerivedDescriptor<'s> { fn psbt_redeem_script(&self) -> Option