diff --git a/.github/workflows/cont_integration.yml b/.github/workflows/cont_integration.yml index e5b9e2906..27901655b 100644 --- a/.github/workflows/cont_integration.yml +++ b/.github/workflows/cont_integration.yml @@ -66,11 +66,12 @@ jobs: cargo update -p tempfile --precise "3.6.0" cargo update -p hashlink --precise "0.8.1" cargo update -p regex --precise "1.7.3" - cargo update -p zip --precise "0.6.3" - cargo update -p base64ct --precise "1.5.3" + cargo update -p zip:0.6.6 --precise "0.6.3" cargo update -p rustix --precise "0.37.23" cargo update -p tokio --precise "1.29.1" cargo update -p cc --precise "1.0.81" + cargo update -p rustls:0.21.6 --precise "0.21.1" + cargo update -p flate2:1.0.27 --precise "1.0.26" - name: Build run: cargo build --features ${{ matrix.features }} --no-default-features - name: Clippy @@ -226,10 +227,11 @@ jobs: cargo update -p tempfile --precise "3.6.0" cargo update -p hashlink --precise "0.8.1" cargo update -p regex --precise "1.7.3" - cargo update -p zip --precise "0.6.3" - cargo update -p base64ct --precise "1.5.3" + cargo update -p zip:0.6.6 --precise "0.6.3" cargo update -p rustix --precise "0.37.23" cargo update -p tokio --precise "1.29.1" cargo update -p cc --precise "1.0.81" + cargo update -p rustls:0.21.6 --precise "0.21.1" + cargo update -p flate2:1.0.27 --precise "1.0.26" - name: Test run: cargo test --features test-hardware-signer diff --git a/Cargo.toml b/Cargo.toml index d46913da9..d90974fb2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,16 +14,16 @@ license = "MIT OR Apache-2.0" [dependencies] bdk-macros = "^0.6" log = "0.4" -miniscript = { version = "9.0", default-features = false, features = ["serde"] } -bitcoin = { version = "0.29.2", default-features = false, features = ["serde", "base64", "rand"] } +miniscript = { version = "10.0", default-features = false, features = ["serde"] } +bitcoin = { version = "0.30", default-features = false, features = ["serde", "base64", "rand-std"] } serde = { version = "^1.0", features = ["derive"] } serde_json = { version = "^1.0" } rand = "^0.8" # Optional dependencies sled = { version = "0.34", optional = true } -electrum-client = { version = "0.12", optional = true } -esplora-client = { version = "0.4", default-features = false, optional = true } +electrum-client = { version = "0.18", optional = true } +esplora-client = { version = "0.6", default-features = false, optional = true } rusqlite = { version = "0.28.0", optional = true } ahash = { version = "0.7.6", optional = true } futures = { version = "0.3", optional = true } @@ -31,13 +31,13 @@ async-trait = { version = "0.1", optional = true } rocksdb = { version = "0.14", default-features = false, features = ["snappy"], optional = true } cc = { version = ">=1.0.64", optional = true } socks = { version = "0.3", optional = true } -hwi = { version = "0.5", optional = true, features = ["use-miniscript"] } +hwi = { version = "0.7", optional = true, features = ["miniscript"] } bip39 = { version = "2.0.0", optional = true } bitcoinconsensus = { version = "0.19.0-3", optional = true } # Needed by bdk_blockchain_tests macro and the `rpc` feature -bitcoincore-rpc = { version = "0.16", optional = true } +bitcoincore-rpc = { package="core-rpc", version = "0.17", optional = true } # Platform-specific dependencies [target.'cfg(not(target_arch = "wasm32"))'.dependencies] @@ -107,13 +107,11 @@ test-hardware-signer = ["hardware-signer"] dev-getrandom-wasm = ["getrandom/js"] [dev-dependencies] -miniscript = { version = "9.0", features = ["std"] } -bitcoin = { version = "0.29.2", features = ["std"] } +miniscript = { version = "10.0", features = ["std"] } +bitcoin = { version = "0.30", features = ["std"] } lazy_static = "1.4" env_logger = { version = "0.7", default-features = false } -electrsd = "0.22" -# Remove after upgrade to rust-bitcoin ^0.30 where base64 is re-exported -base64 = "^0.13" +electrsd = "0.24" assert_matches = "1.5.0" [[example]] diff --git a/README.md b/README.md index a8a3fa2b9..7eea1570a 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ use bdk::blockchain::ElectrumBlockchain; use bdk::electrum_client::Client; use bdk::wallet::AddressIndex::New; -use base64; +use bitcoin::base64; use bdk::bitcoin::consensus::serialize; use bdk::bitcoin::Network; @@ -123,7 +123,7 @@ fn main() -> Result<(), bdk::Error> { }; println!("Transaction details: {:#?}", details); - println!("Unsigned PSBT: {}", base64::encode(&serialize(&psbt))); + println!("Unsigned PSBT: {}", base64::encode(psbt.serialize())); Ok(()) } @@ -134,9 +134,9 @@ fn main() -> Result<(), bdk::Error> { ```rust,no_run use bdk::{Wallet, SignOptions, database::MemoryDatabase}; -use base64; +use bitcoin::base64; use bdk::bitcoin::consensus::deserialize; -use bdk::bitcoin::Network; +use bdk::bitcoin::{psbt::Psbt, Network}; fn main() -> Result<(), bdk::Error> { let wallet = Wallet::new( @@ -147,7 +147,7 @@ fn main() -> Result<(), bdk::Error> { )?; let psbt = "..."; - let mut psbt = deserialize(&base64::decode(psbt).unwrap())?; + let mut psbt = Psbt::deserialize(&base64::decode(psbt).unwrap())?; let _finalized = wallet.sign(&mut psbt, SignOptions::default())?; @@ -218,13 +218,15 @@ cargo update -p hashlink --precise "0.8.1" # required for compact_filters feature, regex after 1.7.3 has MSRV 1.60.0 cargo update -p regex --precise "1.7.3" # zip 0.6.3 has MSRV 1.59.0 but still works -cargo update -p zip --precise "0.6.3" -# base64ct 1.6.0 has MSRV 1.60.0 -cargo update -p base64ct --precise "1.5.3" +cargo update -p zip:0.6.6 --precise "0.6.3" # rustix 0.38.0 has MSRV 1.65.0 cargo update -p rustix --precise "0.37.23" # tokio 0.30.0 has MSRV 1.63.0 cargo update -p tokio --precise "1.29.1" # cc 1.0.82 is throwing error with rust 1.57.0, "error[E0599]: no method named `retain_mut`..." cargo update -p cc --precise "1.0.81" +# rustls 0.21.2 has MSRV 1.60.0+ +cargo update -p rustls:0.21.6 --precise "0.21.1" +# flate2 1.0.27 has MSRV 1.63.0+ +cargo update -p flate2:1.0.27 --precise "1.0.26" ``` diff --git a/examples/electrum_backend.rs b/examples/electrum_backend.rs index 5259865f3..af81eb18e 100644 --- a/examples/electrum_backend.rs +++ b/examples/electrum_backend.rs @@ -1,6 +1,6 @@ use std::str::FromStr; -use bdk::bitcoin::util::bip32::ExtendedPrivKey; +use bdk::bitcoin::bip32::ExtendedPrivKey; use bdk::bitcoin::Network; use bdk::blockchain::{Blockchain, ElectrumBlockchain}; use bdk::database::MemoryDatabase; @@ -10,7 +10,7 @@ use bdk::{KeychainKind, SyncOptions, Wallet}; use bdk::electrum_client::Client; use bdk::wallet::AddressIndex; -use bitcoin::util::bip32; +use bitcoin::bip32; pub mod utils; diff --git a/examples/esplora_backend_asynchronous.rs b/examples/esplora_backend_asynchronous.rs index 4aa149ba3..f8b8588c7 100644 --- a/examples/esplora_backend_asynchronous.rs +++ b/examples/esplora_backend_asynchronous.rs @@ -9,7 +9,7 @@ use bdk::{ KeychainKind, SyncOptions, Wallet, }; use bitcoin::{ - util::bip32::{self, ExtendedPrivKey}, + bip32::{self, ExtendedPrivKey}, Network, }; diff --git a/examples/esplora_backend_synchronous.rs b/examples/esplora_backend_synchronous.rs index 31907f836..4d2ef68c8 100644 --- a/examples/esplora_backend_synchronous.rs +++ b/examples/esplora_backend_synchronous.rs @@ -9,7 +9,7 @@ use bdk::{ KeychainKind, SyncOptions, Wallet, }; use bitcoin::{ - util::bip32::{self, ExtendedPrivKey}, + bip32::{self, ExtendedPrivKey}, Network, }; diff --git a/examples/hardware_signer.rs b/examples/hardware_signer.rs index d1c25f1ab..9773a7f0a 100644 --- a/examples/hardware_signer.rs +++ b/examples/hardware_signer.rs @@ -1,7 +1,7 @@ use bdk::bitcoin::{Address, Network}; use bdk::blockchain::{Blockchain, ElectrumBlockchain}; use bdk::database::MemoryDatabase; -use bdk::hwi::{types::HWIChain, HWIClient}; +use bdk::hwi::HWIClient; use bdk::miniscript::{Descriptor, DescriptorPublicKey}; use bdk::signer::SignerOrdering; use bdk::wallet::{hardwaresigner::HWISigner, AddressIndex}; @@ -30,7 +30,7 @@ fn main() -> Result<(), Box> { } let first_device = devices.remove(0)?; // ...and creating a client out of the first one - let client = HWIClient::get_client(&first_device, true, HWIChain::Test)?; + let client = HWIClient::get_client(&first_device, true, Network::Testnet.into())?; println!("Look what I found, a {}!", first_device.model); // Getting the HW's public descriptors @@ -41,7 +41,7 @@ fn main() -> Result<(), Box> { ); // Creating a custom signer from the device - let custom_signer = HWISigner::from_device(&first_device, HWIChain::Test)?; + let custom_signer = HWISigner::from_device(&first_device, Network::Testnet.into())?; let mut wallet = Wallet::new( descriptors.receive[0].clone(), Some(descriptors.internal[0].clone()), @@ -77,7 +77,8 @@ fn main() -> Result<(), Box> { return Ok(()); } - let return_address = Address::from_str("tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt")?; + let return_address = Address::from_str("tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt")? + .require_network(Network::Testnet)?; let (mut psbt, _details) = { let mut builder = wallet.build_tx(); builder diff --git a/examples/mnemonic_to_descriptors.rs b/examples/mnemonic_to_descriptors.rs index 0a560a528..7d2dd6013 100644 --- a/examples/mnemonic_to_descriptors.rs +++ b/examples/mnemonic_to_descriptors.rs @@ -6,8 +6,8 @@ // You may not use this file except in accordance with one or both of these // licenses. +use bdk::bitcoin::bip32::DerivationPath; use bdk::bitcoin::secp256k1::Secp256k1; -use bdk::bitcoin::util::bip32::DerivationPath; use bdk::bitcoin::Network; use bdk::descriptor; use bdk::descriptor::IntoWalletDescriptor; diff --git a/examples/psbt_signer.rs b/examples/psbt_signer.rs index 35c539dad..1a7eb34f3 100644 --- a/examples/psbt_signer.rs +++ b/examples/psbt_signer.rs @@ -92,7 +92,8 @@ fn main() -> Result<(), Box> { } } else { println!("Creating a PSBT sending 9800 SATs plus fee to the u01.net testnet faucet return address 'tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt'."); - let return_address = Address::from_str("tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt")?; + let return_address = Address::from_str("tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt")? + .require_network(Network::Testnet)?; let mut builder = watch_only_wallet.build_tx(); builder .add_recipient(return_address.script_pubkey(), 9_800) diff --git a/examples/rpcwallet.rs b/examples/rpcwallet.rs index 24a555910..7e1dcb9bc 100644 --- a/examples/rpcwallet.rs +++ b/examples/rpcwallet.rs @@ -62,7 +62,10 @@ fn main() -> Result<(), Box> { }; // Get a new core address - let core_address = bitcoind.client.get_new_address(None, None)?; + let core_address = bitcoind + .client + .get_new_address(None, None)? + .require_network(Network::Regtest)?; // Generate 101 blocks and use the above address as coinbase bitcoind.client.generate_to_address(101, &core_address)?; diff --git a/examples/utils/mod.rs b/examples/utils/mod.rs index 25249fa7e..76aa49d59 100644 --- a/examples/utils/mod.rs +++ b/examples/utils/mod.rs @@ -13,7 +13,10 @@ pub(crate) mod tx { // Create a transaction builder let mut tx_builder = wallet.build_tx(); - let to_address = Address::from_str(recipient_address).unwrap(); + let to_address = Address::from_str(recipient_address) + .unwrap() + .require_network(wallet.network()) + .unwrap(); // Set recipient of the transaction tx_builder.set_recipients(vec![(to_address.script_pubkey(), amount)]); diff --git a/src/blockchain/compact_filters/mod.rs b/src/blockchain/compact_filters/mod.rs index 7845d513d..0c13d75fd 100644 --- a/src/blockchain/compact_filters/mod.rs +++ b/src/blockchain/compact_filters/mod.rs @@ -355,7 +355,7 @@ impl WalletSync for CompactFiltersBlockchain { peer, |block_hash, filter| { if !filter - .match_any(block_hash, &mut all_scripts.iter().map(AsRef::as_ref))? + .match_any(block_hash, all_scripts.iter().map(|s| s.as_slice()))? { return Ok(false); } @@ -570,7 +570,7 @@ pub enum CompactFiltersError { /// Internal I/O error Io(std::io::Error), /// Invalid BIP158 filter - Bip158(bitcoin::util::bip158::Error), + Bip158(bitcoin::bip158::Error), /// Internal system time error Time(std::time::SystemTimeError), @@ -608,7 +608,7 @@ impl std::error::Error for CompactFiltersError {} impl_error!(rocksdb::Error, Db, CompactFiltersError); impl_error!(std::io::Error, Io, CompactFiltersError); -impl_error!(bitcoin::util::bip158::Error, Bip158, CompactFiltersError); +impl_error!(bitcoin::bip158::Error, Bip158, CompactFiltersError); impl_error!(std::time::SystemTimeError, Time, CompactFiltersError); impl From for CompactFiltersError { diff --git a/src/blockchain/compact_filters/peer.rs b/src/blockchain/compact_filters/peer.rs index 665a033d4..670472aba 100644 --- a/src/blockchain/compact_filters/peer.rs +++ b/src/blockchain/compact_filters/peer.rs @@ -27,7 +27,7 @@ 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::Address; +use bitcoin::network::{Address, Magic}; use bitcoin::{Block, Network, Transaction, Txid, Wtxid}; use super::CompactFiltersError; @@ -242,7 +242,7 @@ impl Peer { /// Send a Bitcoin network message fn _send( writer: &mut TcpStream, - magic: u32, + magic: Magic, payload: NetworkMessage, ) -> Result<(), CompactFiltersError> { log::trace!("==> {:?}", payload); diff --git a/src/blockchain/compact_filters/store.rs b/src/blockchain/compact_filters/store.rs index 6b8d4943b..373d3573a 100644 --- a/src/blockchain/compact_filters/store.rs +++ b/src/blockchain/compact_filters/store.rs @@ -21,16 +21,17 @@ use rand::{thread_rng, Rng}; use rocksdb::{Direction, IteratorMode, ReadOptions, WriteBatch, DB}; +use bitcoin::bip158::BlockFilter; +use bitcoin::block::Header; use bitcoin::blockdata::constants::genesis_block; use bitcoin::consensus::{deserialize, encode::VarInt, serialize, Decodable, Encodable}; use bitcoin::hash_types::{FilterHash, FilterHeader}; use bitcoin::hashes::Hash; -use bitcoin::util::bip158::BlockFilter; -use bitcoin::util::uint::Uint256; +use bitcoin::pow::Work; use bitcoin::Block; use bitcoin::BlockHash; -use bitcoin::BlockHeader; use bitcoin::Network; +use bitcoin::ScriptBuf; use super::CompactFiltersError; @@ -69,7 +70,7 @@ impl StoreEntry { } StoreEntry::Block(Some(height)) => prefix.extend_from_slice(&height.to_be_bytes()), StoreEntry::BlockHeaderIndex(Some(hash)) => { - prefix.extend_from_slice(&hash.into_inner()) + prefix.extend_from_slice(hash.to_raw_hash().as_ref()) } StoreEntry::CFilterTable((filter_type, bundle_index)) => { prefix.push(*filter_type); @@ -228,7 +229,7 @@ impl ChainStore { batch.put_cf( cf_handle, genesis_key, - (genesis.header, genesis.header.work()).serialize(), + (genesis.header, genesis.header.work().to_be_bytes()).serialize(), ); batch.put_cf( cf_handle, @@ -260,7 +261,7 @@ impl ChainStore { step *= 2; } - let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize( + let (header, _): (Header, [u8; 32]) = SerializeDb::deserialize( &store_read .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(index)).get_key())? .unwrap(), @@ -292,11 +293,12 @@ impl ChainStore { let cf_handle = write_store.cf_handle(&self.cf_name).unwrap(); let new_cf_handle = write_store.cf_handle(&new_cf_name).unwrap(); - let (header, work): (BlockHeader, Uint256) = SerializeDb::deserialize( + let (header, work): (Header, [u8; 32]) = SerializeDb::deserialize( &write_store .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(from)).get_key())? .ok_or(CompactFiltersError::DataCorruption)?, )?; + let work = Work::from_be_bytes(work); let mut batch = WriteBatch::default(); batch.put_cf( @@ -307,7 +309,7 @@ impl ChainStore { batch.put_cf( new_cf_handle, StoreEntry::BlockHeader(Some(from)).get_key(), - (header, work).serialize(), + (header, work.to_be_bytes()).serialize(), ); write_store.write(batch)?; @@ -381,7 +383,7 @@ impl ChainStore { opts, IteratorMode::From(&from_key, Direction::Forward), ) { - let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?; + let (header, _): (Header, [u8; 32]) = SerializeDb::deserialize(&v)?; batch.delete_cf( cf_handle, @@ -433,7 +435,7 @@ impl ChainStore { let key = StoreEntry::BlockHeader(Some(height)).get_key(); let data = read_store.get_pinned_cf(cf_handle, key)?; data.map(|data| { - let (header, _): (BlockHeader, Uint256) = + let (header, _): (Header, [u8; 32]) = deserialize(&data).map_err(|_| CompactFiltersError::DataCorruption)?; Ok::<_, CompactFiltersError>(header.block_hash()) }) @@ -496,7 +498,7 @@ impl ChainStore { } impl ChainStore { - pub fn work(&self) -> Result { + pub fn work(&self) -> Result { let read_store = self.store.read().unwrap(); let cf_handle = read_store.cf_handle(&self.cf_name).unwrap(); @@ -506,12 +508,13 @@ impl ChainStore { Ok(iterator .last() .map(|(_, v)| -> Result<_, CompactFiltersError> { - let (_, work): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?; + let (_, work): (Header, [u8; 32]) = SerializeDb::deserialize(&v)?; + let work = Work::from_be_bytes(work); Ok(work) }) .transpose()? - .unwrap_or_default()) + .unwrap_or_else(|| Work::from_be_bytes([0; 32]))) } pub fn get_height(&self) -> Result { @@ -546,7 +549,7 @@ impl ChainStore { iterator .last() .map(|(_, v)| -> Result<_, CompactFiltersError> { - let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?; + let (header, _): (Header, [u8; 32]) = SerializeDb::deserialize(&v)?; Ok(header.block_hash()) }) @@ -556,7 +559,7 @@ impl ChainStore { pub fn apply( &mut self, from: usize, - headers: Vec, + headers: Vec
, ) -> Result { let mut batch = WriteBatch::default(); @@ -566,7 +569,8 @@ impl ChainStore { let (mut last_hash, mut accumulated_work) = read_store .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(from)).get_key())? .map(|result| { - let (header, work): (BlockHeader, Uint256) = SerializeDb::deserialize(&result)?; + let (header, work): (Header, [u8; 32]) = SerializeDb::deserialize(&result)?; + let work = Work::from_be_bytes(work); Ok::<_, CompactFiltersError>((header.block_hash(), work)) }) .transpose()? @@ -589,7 +593,7 @@ impl ChainStore { batch.put_cf( cf_handle, StoreEntry::BlockHeader(Some(height)).get_key(), - (header, accumulated_work).serialize(), + (header, accumulated_work.to_be_bytes()).serialize(), ); } @@ -641,7 +645,7 @@ impl CfStore { let genesis = genesis_block(headers_store.network); let filter = BlockFilter::new_script_filter(&genesis, |utxo| { - Err(bitcoin::util::bip158::Error::UtxoMissing(*utxo)) + Err::(bitcoin::bip158::Error::UtxoMissing(*utxo)) })?; let first_key = StoreEntry::CFilterTable((filter_type, Some(0))).get_key(); @@ -653,7 +657,7 @@ impl CfStore { &first_key, ( BundleStatus::Init, - filter.filter_header(&FilterHeader::from_hash(Hash::all_zeros())), + filter.filter_header(&FilterHeader::from_raw_hash(Hash::all_zeros())), ) .serialize(), )?; diff --git a/src/blockchain/compact_filters/sync.rs b/src/blockchain/compact_filters/sync.rs index ba4e00456..1e4e36fbe 100644 --- a/src/blockchain/compact_filters/sync.rs +++ b/src/blockchain/compact_filters/sync.rs @@ -13,11 +13,11 @@ use std::collections::{BTreeMap, HashMap, VecDeque}; use std::sync::{Arc, Mutex}; use std::time::Duration; +use bitcoin::bip158::BlockFilter; use bitcoin::hash_types::{BlockHash, FilterHeader}; use bitcoin::hashes::Hash; use bitcoin::network::message::NetworkMessage; use bitcoin::network::message_blockdata::GetHeadersMessage; -use bitcoin::util::bip158::BlockFilter; use super::peer::*; use super::store::*; diff --git a/src/blockchain/electrum.rs b/src/blockchain/electrum.rs index 845bb64b5..ad7c9a534 100644 --- a/src/blockchain/electrum.rs +++ b/src/blockchain/electrum.rs @@ -325,8 +325,8 @@ impl ConfigurableBlockchain for ElectrumBlockchain { let socks5 = config.socks5.as_ref().map(Socks5Config::new); let electrum_config = ConfigBuilder::new() .retry(config.retry) - .timeout(config.timeout)? - .socks5(socks5)? + .timeout(config.timeout) + .socks5(socks5) .validate_domain(config.validate_domain) .build(); diff --git a/src/blockchain/esplora/blocking.rs b/src/blockchain/esplora/blocking.rs index e75e5456c..cfd83f2cf 100644 --- a/src/blockchain/esplora/blocking.rs +++ b/src/blockchain/esplora/blocking.rs @@ -132,7 +132,7 @@ impl WalletSync for EsploraBlockchain { let scripts = script_req .request() .take(self.concurrency as usize) - .cloned(); + .map(bitcoin::ScriptBuf::from); let mut handles = vec![]; for script in scripts { diff --git a/src/blockchain/rpc.rs b/src/blockchain/rpc.rs index da19e20c6..65456579e 100644 --- a/src/blockchain/rpc.rs +++ b/src/blockchain/rpc.rs @@ -31,18 +31,17 @@ //! let blockchain = RpcBlockchain::from_config(&config); //! ``` -use crate::bitcoin::hashes::hex::ToHex; use crate::bitcoin::{Network, OutPoint, Transaction, TxOut, Txid}; use crate::blockchain::*; use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils}; use crate::descriptor::calc_checksum; use crate::error::MissingCachedScripts; use crate::{BlockTime, Error, FeeRate, KeychainKind, LocalUtxo, TransactionDetails}; -use bitcoin::Script; +use bitcoin::{Script, ScriptBuf}; use bitcoincore_rpc::json::{ GetTransactionResultDetailCategory, ImportMultiOptions, ImportMultiRequest, - ImportMultiRequestScriptPubkey, ImportMultiRescanSince, ListTransactionResult, - ListUnspentResultEntry, ScanningDetails, + ImportMultiRequestScriptPubkey, ListTransactionResult, ListUnspentResultEntry, ScanningDetails, + Timestamp, }; use bitcoincore_rpc::jsonrpc::serde_json::{json, Value}; use bitcoincore_rpc::Auth as RpcAuth; @@ -302,8 +301,8 @@ struct DbState<'a, D> { params: &'a RpcSyncParams, prog: &'a dyn Progress, - ext_spks: Vec