From ff62e0230ab269567f6dccf3a644d51cc8ee1fc6 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 9 Apr 2026 07:55:58 +1000 Subject: [PATCH 01/12] Import electrsd This repository already has `corepc-node` (formerly `bitcoind`) for integration testing. BDK users do integration testing with `electrsd` as well and the two crates are coupled but during migration of `bitcoind` here I did not realise this. In an attempt to remedy this mistake import `electrsd` here as well. Next we will revert the name change of `corepc-node` back to `bitcoind`. Details of import: repository: https://github.com/RCasatta/electrsd commit: `d2fd8af upgrade electrs esplora` full hash: d2fd8afc3b5b79304dd669250df325a54024f374 Import excludes the `.git` and `.github` directories. Which means git history and CI. CI will be re-added manually. Note crate is excluded from the workspace in this patch. --- .gitignore | 4 + Cargo.toml | 2 +- electrsd/Cargo.toml | 58 +++++ electrsd/LICENSE | 21 ++ electrsd/README.md | 86 +++++++ electrsd/build.rs | 83 +++++++ electrsd/sha256 | 10 + electrsd/src/error.rs | 75 ++++++ electrsd/src/ext.rs | 97 ++++++++ electrsd/src/lib.rs | 500 +++++++++++++++++++++++++++++++++++++++ electrsd/src/versions.rs | 44 ++++ 11 files changed, 979 insertions(+), 1 deletion(-) create mode 100644 electrsd/Cargo.toml create mode 100644 electrsd/LICENSE create mode 100644 electrsd/README.md create mode 100644 electrsd/build.rs create mode 100644 electrsd/sha256 create mode 100644 electrsd/src/error.rs create mode 100644 electrsd/src/ext.rs create mode 100644 electrsd/src/lib.rs create mode 100644 electrsd/src/versions.rs diff --git a/.gitignore b/.gitignore index 01626769f..a7afd665e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,7 @@ Cargo.lock **/target + +# Copied from electsd repo during import. +.idea/ +bin/ diff --git a/Cargo.toml b/Cargo.toml index 7400e46a2..3a64cbfc4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace] members = [ "bitreq", "client", "fuzz", "jsonrpc", "node", "types"] -exclude = ["integration_test", "verify"] +exclude = ["integration_test", "verify", "electrsd"] resolver = "2" rust-version = "1.75.0" diff --git a/electrsd/Cargo.toml b/electrsd/Cargo.toml new file mode 100644 index 000000000..a93453dac --- /dev/null +++ b/electrsd/Cargo.toml @@ -0,0 +1,58 @@ +[package] +name = "electrsd" +version = "0.36.1" +authors = ["Riccardo Casatta "] +description = "Utility to run a regtest electrs process, useful in integration testing environment" +repository = "https://github.com/RCasatta/electrsd" +documentation = "https://docs.rs/elecrtsd/" +license = "MIT" +edition = "2018" +categories = ["cryptography::cryptocurrencies", "development-tools::testing"] + +[dependencies] +corepc-node = { version = "0.10.0" } +corepc-client = { version = "0.10.0" } +electrum-client = { version = "0.24.0", default-features = false } +log = { version = "0.4" } + +[target.'cfg(not(windows))'.dependencies] +nix = { version = "0.25.0" } + +[dev-dependencies] +env_logger = { version = "0.10" } + +[build-dependencies] +bitcoin_hashes = { version = "0.14", optional = true } +zip = { version = "0.6", default-features = false, optional = true, features = [ + "bzip2", + "deflate", +] } +minreq = { version = "2.9.0", default-features = false, optional = true, features = [ + "https", +] } + +[features] +legacy = [] + +# download is not supposed to be used directly only through selecting one of the version feature +download = ["bitcoin_hashes", "zip", "minreq"] + +esplora_a33e97e1 = ["download", "legacy"] +electrs_0_8_10 = ["download"] +electrs_0_9_1 = ["download"] +electrs_0_9_11 = ["download"] +electrs_0_10_6 = ["download"] + +corepc-node_29_0 = ["corepc-node/download", "corepc-node/29_0"] +corepc-node_28_2 = ["corepc-node/download", "corepc-node/28_2"] +corepc-node_27_2 = ["corepc-node/download", "corepc-node/27_2"] +corepc-node_26_2 = ["corepc-node/download", "corepc-node/26_2"] +corepc-node_25_2 = ["corepc-node/download", "corepc-node/25_2"] +corepc-node_24_2 = ["corepc-node/download", "corepc-node/24_2"] +corepc-node_23_1 = ["corepc-node/download", "corepc-node/23_2"] +corepc-node_22_1 = ["corepc-node/download", "corepc-node/22_1"] +corepc-node_0_21_2 = ["corepc-node/download", "corepc-node/0_21_2"] +corepc-node_0_20_2 = ["corepc-node/download", "corepc-node/0_20_2"] +corepc-node_0_19_1 = ["corepc-node/download", "corepc-node/0_19_1"] +corepc-node_0_18_1 = ["corepc-node/download", "corepc-node/0_18_1"] +corepc-node_0_17_2 = ["corepc-node/download", "corepc-node/0_17_2"] diff --git a/electrsd/LICENSE b/electrsd/LICENSE new file mode 100644 index 000000000..6a083901b --- /dev/null +++ b/electrsd/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Riccardo Casatta + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/electrsd/README.md b/electrsd/README.md new file mode 100644 index 000000000..e4c64f7d3 --- /dev/null +++ b/electrsd/README.md @@ -0,0 +1,86 @@ +[![MIT license](https://img.shields.io/github/license/RCasatta/electrsd)](https://github.com/RCasatta/electrsd/blob/master/LICENSE) +[![Crates](https://img.shields.io/crates/v/electrsd.svg)](https://crates.io/crates/electrsd) + +# Electrsd + +Utility to run a regtest [electrs](https://github.com/romanz/electrs/) process connected to a given [bitcoind](https://github.com/RCasatta/bitcoind) instance, +useful in integration testing environment. + +```rust +let bitcoind = bitcoind::BitcoinD::new("/usr/local/bin/bitcoind").unwrap(); +let electrsd = electrsd::ElectrsD::new("/usr/local/bin/electrs", bitcoind).unwrap(); +let header = electrsd.client.block_headers_subscribe().unwrap(); +assert_eq!(header.height, 0); +``` + +## Automatic binaries download + +In your project Cargo.toml, activate the following features + +```yml +electrsd = { version= "0.23", features = ["corepc-node_23_1", "electrs_0_9_1"] } +``` + +Then use it: + +```rust +let bitcoind_exe = bitcoind::downloaded_exe_path().expect("bitcoind version feature must be enabled"); +let bitcoind = bitcoind::BitcoinD::new(bitcoind_exe).unwrap(); +let electrs_exe = electrsd::downloaded_exe_path().expect("electrs version feature must be enabled"); +let electrsd = electrsd::ElectrsD::new(electrs_exe, bitcoind).unwrap(); +``` + +When the `ELECTRSD_DOWNLOAD_ENDPOINT`/`BITCOIND_DOWNLOAD_ENDPOINT` environment variables are set, +`electrsd`/`bitcoind` will try to download the binaries from the given endpoints. + +When you don't use the auto-download feature you have the following options: + +- have `electrs` executable in the `PATH` +- provide the `electrs` executable via the `ELECTRS_EXEC` env var + +```rust +if let Ok(exe_path) = electrsd::exe_path() { + let electrsd = electrsd::electrsD::new(exe_path).unwrap(); +} +``` + +Startup options could be configured via the `Conf` struct using `electrsD::with_conf` or `electrsD::from_downloaded_with_conf`. + +## Nix + +For determinisim, in nix you cannot hit the internet within the `build.rs`. Moreover, some downstream crates cannot remove the auto-download feature from their dev-deps. In this case you can set the `ELECTRSD_SKIP_DOWNLOAD` env var and provide the electrs executable in the `PATH` (or skip the test execution). + +## Issues with traditional approach + +I used integration testing based on external bash script launching needed external processes, there are many issues with this approach like: + +* External script may interfere with local development environment https://github.com/rust-bitcoin/rust-bitcoincore-rpc/blob/200fc8247c1896709a673b82a89ca0da5e7aa2ce/integration_test/run.sh#L9 +* Use of a single huge test to test everything https://github.com/rust-bitcoin/rust-bitcoincore-rpc/blob/200fc8247c1896709a673b82a89ca0da5e7aa2ce/integration_test/src/main.rs#L122-L203 +* If test are separated, a failing test may fail to leave a clean situation, causing other test to fail (because of the initial situation, not a real failure) +* bash script are hard, especially support different OS and versions + +## Features + + * electrsd use a temporary directory as db dir + * A free port is asked to the OS (a very low probability race condition is still possible) + * The process is killed when the struct goes out of scope no matter how the test finishes + * Automatically download `electrs` executable with enabled features. Since there are no official binaries, they are built using the [manual workflow](.github/workflows/build_electrs.yml) under this project. Supported version are: + * [electrs 0.10.6](https://github.com/romanz/electrs/releases/tag/v0.10.6) (feature=electrs_0_10_6) + * [electrs 0.9.11](https://github.com/romanz/electrs/releases/tag/v0.9.11) (feature=electrs_0_9_11) + * [electrs 0.9.1](https://github.com/romanz/electrs/releases/tag/v0.9.1) (feature=electrs_0_9_1) + * [electrs 0.8.10](https://github.com/romanz/electrs/releases/tag/v0.8.10) (feature=electrs_0_8_10) + * [electrs esplora](https://github.com/Blockstream/electrs/tree/a33e97e1a1fc63fa9c20a116bb92579bbf43b254) (feature=esplora_a33e97e1) + +Thanks to these features every `#[test]` could easily run isolated with its own environment + +## Deprecations + +- Starting from version `0.26` the env var `ELECTRS_EXE` is deprecated in favor of `ELECTRS_EXEC`. + + +## Used by + + * [bdk](https://github.com/bitcoindevkit/bdk) + * [BEWallet](https://github.com/LeoComandini/BEWallet) + * [gdk rust](https://github.com/Blockstream/gdk/blob/master/subprojects/gdk_rust/) + * [lwk](https://github.com/Blockstream/lwk) diff --git a/electrsd/build.rs b/electrsd/build.rs new file mode 100644 index 000000000..727a13963 --- /dev/null +++ b/electrsd/build.rs @@ -0,0 +1,83 @@ +#[cfg(not(feature = "download"))] +fn main() {} + +#[cfg(feature = "download")] +fn main() { + download::download() +} + +#[cfg(feature = "download")] +mod download { + use bitcoin_hashes::{sha256, Hash}; + use std::fs::File; + use std::io::{BufRead, BufReader, Cursor}; + use std::os::unix::fs::PermissionsExt; + use std::path::Path; + use std::str::FromStr; + + include!("src/versions.rs"); + + const GITHUB_URL: &str = + "https://github.com/RCasatta/electrsd/releases/download/electrs_releases"; + + fn get_expected_sha256(filename: &str) -> Result { + let file = File::open("sha256").map_err(|_| ())?; + for line in BufReader::new(file).lines().flatten() { + let tokens: Vec<_> = line.split(" ").collect(); + if tokens.len() == 2 && filename == tokens[1] { + return sha256::Hash::from_str(tokens[0]).map_err(|_| ()); + } + } + Err(()) + } + + pub fn download() { + if std::env::var_os("ELECTRSD_SKIP_DOWNLOAD").is_some() { + return; + } + + if !HAS_FEATURE { + return; + } + let download_filename_without_extension = electrs_name(); + let download_filename = format!("{}.zip", download_filename_without_extension); + dbg!(&download_filename); + let expected_hash = get_expected_sha256(&download_filename).unwrap(); + let out_dir = std::env::var_os("OUT_DIR").unwrap(); + let electrs_exe_home = Path::new(&out_dir).join("electrs"); + let destination_filename = electrs_exe_home + .join(&download_filename_without_extension) + .join("electrs"); + + dbg!(&destination_filename); + + if !destination_filename.exists() { + println!( + "filename:{} version:{} hash:{}", + download_filename, VERSION, expected_hash + ); + + let download_endpoint = + std::env::var("ELECTRSD_DOWNLOAD_ENDPOINT").unwrap_or(GITHUB_URL.to_string()); + let url = format!("{}/{}", download_endpoint, download_filename); + + let downloaded_bytes = minreq::get(url).send().unwrap().into_bytes(); + + let downloaded_hash = sha256::Hash::hash(&downloaded_bytes); + assert_eq!(expected_hash, downloaded_hash); + let cursor = Cursor::new(downloaded_bytes); + + let mut archive = zip::ZipArchive::new(cursor).unwrap(); + let mut file = archive.by_index(0).unwrap(); + std::fs::create_dir_all(destination_filename.parent().unwrap()).unwrap(); + let mut outfile = std::fs::File::create(&destination_filename).unwrap(); + + std::io::copy(&mut file, &mut outfile).unwrap(); + std::fs::set_permissions( + &destination_filename, + std::fs::Permissions::from_mode(0o755), + ) + .unwrap(); + } + } +} diff --git a/electrsd/sha256 b/electrsd/sha256 new file mode 100644 index 000000000..a8941189e --- /dev/null +++ b/electrsd/sha256 @@ -0,0 +1,10 @@ +2d5ff149e8a2482d3658e9b386830dfc40c8fbd7c175ca7cbac58240a9505bcd electrs_macos_esplora_a33e97e1a1fc63fa9c20a116bb92579bbf43b254.zip +865e26a96e8df77df01d96f2f569dcf9622fc87a8d99a9b8fe30861a4db9ddf1 electrs_linux_esplora_a33e97e1a1fc63fa9c20a116bb92579bbf43b254.zip +0459d493d399bdb9ef145c84125c3cd26c1993a48efe59fa9d3fa13a03b2f555 electrs_linux_v0.8.10.zip +48c857ca953ea66ee31c4da5a801298c85815e792ab57291107e77a4871d5421 electrs_macos_v0.8.10.zip +fee5cc9b6c8bbd3adc45c63c881844d948c1b4dd6817f99ee087a0ccc4ba3be0 electrs_linux_v0.9.1.zip +10f468e9e617bfe8f9f4897fa4cbbb92fe809d977b747e4326f4c8e5dc1b3a51 electrs_macos_v0.9.1.zip +2b2f8aef35cd8e16e109b948a903d010aa472f6cdf2147d47e01fd95cd1785da electrs_linux_v0.9.11.zip +b794287a5d98e590deadf07a3eb391cc1a53ef160c8cdcb8e6b14d856c7b181d electrs_macos_v0.9.11.zip +448693f42fa2e310bd86ba9a7304c9ab464854a3c7e4c3eaa8c774efeb0fbdd1 electrs_linux_v0.10.6.zip +016ad9ef227c12ae6096ada1db09179d3330a4062ba2ab65390d6988f659be05 electrs_macos_v0.10.6.zip diff --git a/electrsd/src/error.rs b/electrsd/src/error.rs new file mode 100644 index 000000000..c8dc5240b --- /dev/null +++ b/electrsd/src/error.rs @@ -0,0 +1,75 @@ +/// All the possible error in this crate +#[derive(Debug)] +pub enum Error { + /// Wrapper of io Error + Io(std::io::Error), + + /// Wrapper of bitcoind Error + Bitcoind(corepc_node::Error), + + /// Wrapper of electrum_client Error + ElectrumClient(electrum_client::Error), + + /// Wrapper of nix Error + #[cfg(not(target_os = "windows"))] + Nix(nix::Error), + + /// Wrapper of early exit status + EarlyExit(std::process::ExitStatus), + + /// Returned when both tmpdir and staticdir is specified in `Conf` options + BothDirsSpecified, + + /// Returned when calling methods requiring the bitcoind executable but none is found + /// (no feature, no `ELECTRS_EXEC`, no `electrs` in `PATH` ) + NoElectrsExecutableFound, + + /// Returned if both env vars `ELECTRS_EXEC` and `ELECTRS_EXE` are found + BothEnvVars, +} + +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Error::Io(e) => Some(e), + Error::Bitcoind(e) => Some(e), + Error::ElectrumClient(e) => Some(e), + // Error::BitcoinCoreRpc(e) => Some(e), + #[cfg(not(target_os = "windows"))] + Error::Nix(e) => Some(e), + + _ => None, + } + } +} + +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self) + } +} + +impl From for Error { + fn from(e: std::io::Error) -> Self { + Error::Io(e) + } +} + +impl From for Error { + fn from(e: corepc_node::Error) -> Self { + Error::Bitcoind(e) + } +} + +impl From for Error { + fn from(e: electrum_client::Error) -> Self { + Error::ElectrumClient(e) + } +} + +#[cfg(not(target_os = "windows"))] +impl From for Error { + fn from(e: nix::Error) -> Self { + Error::Nix(e) + } +} diff --git a/electrsd/src/ext.rs b/electrsd/src/ext.rs new file mode 100644 index 000000000..147bd413d --- /dev/null +++ b/electrsd/src/ext.rs @@ -0,0 +1,97 @@ +//! Extra functions for the electrs rpc +//! + +use std::thread; +use std::time::Duration; + +use electrum_client::{bitcoin::Txid, ElectrumApi}; + +use crate::ElectrsD; + +impl ElectrsD { + #[cfg(not(feature = "electrs_0_8_10"))] + /// wait up to a minute the electrum server has indexed up to the given height. + pub fn wait_height(&self, height: usize) { + for _ in 0..600 { + match self.client.block_header_raw(height) { + Ok(_) => break, + Err(_) => thread::sleep(Duration::from_millis(100)), + } + } + } + + /// wait up to a minute the electrum server has indexed the given transaction + pub fn wait_tx(&self, txid: &Txid) { + 'main_loop: for _ in 0..600 { + match self.client.transaction_get(txid) { + Ok(tx) => { + // having the raw tx doesn't mean the scripts has been indexed + let txid = tx.compute_txid(); + if let Some(output) = tx.output.first() { + let history = self + .client + .script_get_history(&output.script_pubkey) + .unwrap(); + for el in history { + if el.tx_hash == txid { + // the tx has to be updated atomically, so founding one is enough + return; + } + } + // the tx output has not been yet found + continue 'main_loop; + } + // the tx has 0 ouptut, no need to ensure script_pubkey are indexed + return; + } + Err(_) => thread::sleep(Duration::from_millis(100)), + } + } + } +} + +#[cfg(test)] +mod test { + use crate::test::setup_nodes; + use electrum_client::{bitcoin::Amount, ElectrumApi}; + + #[cfg(not(feature = "electrs_0_8_10"))] + #[test] + fn test_wait_height() { + let (_, bitcoind, electrsd) = setup_nodes(); + let header = electrsd.client.block_headers_subscribe().unwrap(); + assert_eq!(header.height, 1); + let address = bitcoind.client.new_address().unwrap(); + bitcoind.client.generate_to_address(100, &address).unwrap(); + electrsd.wait_height(101); + let header = electrsd.client.block_headers_subscribe().unwrap(); + assert_eq!(header.height, 101); + } + + #[test] + fn test_wait_tx() { + let (_, bitcoind, electrsd) = setup_nodes(); + let header = electrsd.client.block_headers_subscribe().unwrap(); + assert_eq!(header.height, 1); + let generate_address = bitcoind.client.new_address().unwrap(); + bitcoind + .client + .generate_to_address(100, &generate_address) + .unwrap(); + + let address = bitcoind.client.new_address().unwrap(); + let txid = bitcoind + .client + .send_to_address(&address, Amount::from_sat(10000)) + .unwrap() + .txid() + .unwrap(); + + electrsd.wait_tx(&txid); + let history = electrsd + .client + .script_get_history(&address.script_pubkey()) + .unwrap(); + assert_eq!(history.len(), 1); + } +} diff --git a/electrsd/src/lib.rs b/electrsd/src/lib.rs new file mode 100644 index 000000000..9936b5971 --- /dev/null +++ b/electrsd/src/lib.rs @@ -0,0 +1,500 @@ +#![warn(missing_docs)] + +//! +//! Electrsd +//! +//! Utility to run a regtest electrsd process, useful in integration testing environment +//! + +mod error; +mod ext; +mod versions; + +use corepc_node::anyhow::Context; +use corepc_node::get_available_port; +use corepc_node::serde_json::Value; +use corepc_node::tempfile::TempDir; +use corepc_node::{anyhow, Node}; +use electrum_client::raw_client::{ElectrumPlaintextStream, RawClient}; +use log::{debug, error, warn}; +use std::env; +use std::ffi::OsStr; +use std::path::PathBuf; +use std::process::{Child, Command, Stdio}; +use std::time::Duration; + +// re-export corepc_node +pub use corepc_node; +// re-export corepc_client +pub use corepc_client; +// re-export electrum_client because calling RawClient methods requires the ElectrumApi trait +pub use electrum_client; + +pub use error::Error; + +/// Electrs configuration parameters, implements a convenient [Default] for most common use. +/// +/// Default values: +/// ``` +/// let mut conf = electrsd::Conf::default(); +/// conf.view_stderr = false; +/// conf.http_enabled = false; +/// conf.network = "regtest"; +/// conf.tmpdir = None; +/// conf.staticdir = None; +/// assert_eq!(conf, electrsd::Conf::default()); +/// ``` +#[derive(Debug, PartialEq, Eq, Clone)] +#[non_exhaustive] +pub struct Conf<'a> { + /// Electrsd command line arguments + /// note that `db-dir`, `cookie`, `cookie-file`, `daemon-rpc-addr`, `jsonrpc-import`, `electrum-rpc-addr`, `monitoring-addr`, `http-addr` cannot be used cause they are automatically initialized. + pub args: Vec<&'a str>, + + /// if `true` electrsd log output will not be suppressed + pub view_stderr: bool, + + /// if `true` electrsd exposes an esplora endpoint + pub http_enabled: bool, + + /// Must match bitcoind network + pub network: &'a str, + + /// Optionally specify a temporary or persistent working directory for the electrs. + /// electrs index files will be stored in this path. + /// The following two parameters can be configured to simulate desired working directory configuration. + /// + /// tmpdir is Some() && staticdir is Some() : Error. Cannot be enabled at same time. + /// tmpdir is Some(temp_path) && staticdir is None : Create temporary directory at `tmpdir` path. + /// tmpdir is None && staticdir is Some(work_path) : Create persistent directory at `staticdir` path. + /// tmpdir is None && staticdir is None: Creates a temporary directory in OS default temporary directory (eg /tmp) or `TEMPDIR_ROOT` env variable path. + /// + /// Temporary directory path + pub tmpdir: Option, + + /// Persistent directory path + pub staticdir: Option, + + /// Try to spawn the process `attempt` time + /// + /// The OS is giving available ports to use, however, they aren't booked, so it could rarely + /// happen they are used at the time the process is spawn. When retrying other available ports + /// are returned reducing the probability of conflicts to negligible. + attempts: u8, +} + +impl Default for Conf<'_> { + fn default() -> Self { + let args = if cfg!(feature = "electrs_0_9_1") + || cfg!(feature = "electrs_0_8_10") + || cfg!(feature = "esplora_a33e97e1") + || cfg!(feature = "legacy") + { + vec!["-vvv"] + } else { + vec![] + }; + + Conf { + args, + view_stderr: false, + http_enabled: false, + network: "regtest", + tmpdir: None, + staticdir: None, + attempts: 3, + } + } +} + +/// Struct representing the electrs process with related information +pub struct ElectrsD { + /// Process child handle, used to terminate the process when this struct is dropped + process: Child, + /// Electrum client connected to the electrs process + pub client: RawClient, + /// Work directory, where the electrs stores indexes and other stuffs. + work_dir: DataDir, + /// Url to connect to the electrum protocol (tcp) + pub electrum_url: String, + /// Url to connect to esplora protocol (http) + pub esplora_url: Option, +} + +/// The DataDir struct defining the kind of data directory electrs will use. +/// /// Data directory can be either persistent, or temporary. +pub enum DataDir { + /// Persistent Data Directory + Persistent(PathBuf), + /// Temporary Data Directory + Temporary(TempDir), +} + +impl DataDir { + /// Return the data directory path + fn path(&self) -> PathBuf { + match self { + Self::Persistent(path) => path.to_owned(), + Self::Temporary(tmp_dir) => tmp_dir.path().to_path_buf(), + } + } +} + +impl ElectrsD { + /// Create a new electrs process connected with the given bitcoind and default args. + pub fn new>(exe: S, bitcoind: &Node) -> anyhow::Result { + ElectrsD::with_conf(exe, bitcoind, &Conf::default()) + } + + /// Create a new electrs process using given [Conf] connected with the given bitcoind + pub fn with_conf>( + exe: S, + bitcoind: &Node, + conf: &Conf, + ) -> anyhow::Result { + let response = bitcoind.client.call::("getblockchaininfo", &[])?; + if response + .get("initialblockdownload") + .and_then(|v| v.as_bool()) + .unwrap_or(false) + { + // electrum will remain idle until bitcoind is in IBD + // bitcoind will remain in IBD if doesn't see a block from a long time, thus adding a block + let node_address = bitcoind.client.call::("getnewaddress", &[])?; + bitcoind + .client + .call::("generatetoaddress", &[1.into(), node_address]) + .unwrap(); + } + + let mut args = conf.args.clone(); + + let work_dir = match (&conf.tmpdir, &conf.staticdir) { + (Some(_), Some(_)) => return Err(Error::BothDirsSpecified.into()), + (Some(tmpdir), None) => DataDir::Temporary(TempDir::new_in(tmpdir)?), + (None, Some(workdir)) => { + std::fs::create_dir_all(workdir)?; + DataDir::Persistent(workdir.to_owned()) + } + (None, None) => match env::var("TEMPDIR_ROOT").map(PathBuf::from) { + Ok(path) => DataDir::Temporary(TempDir::new_in(path)?), + Err(_) => DataDir::Temporary(TempDir::new()?), + }, + }; + + let db_dir = format!("{}", work_dir.path().display()); + args.push("--db-dir"); + args.push(&db_dir); + + args.push("--network"); + args.push(conf.network); + + #[cfg(not(feature = "legacy"))] + let cookie_file; + #[cfg(not(feature = "legacy"))] + { + args.push("--cookie-file"); + cookie_file = format!("{}", bitcoind.params.cookie_file.display()); + args.push(&cookie_file); + } + + #[cfg(feature = "legacy")] + let mut cookie_value; + #[cfg(feature = "legacy")] + { + use std::io::Read; + args.push("--cookie"); + let mut cookie = std::fs::File::open(&bitcoind.params.cookie_file)?; + cookie_value = String::new(); + cookie.read_to_string(&mut cookie_value)?; + args.push(&cookie_value); + } + + args.push("--daemon-rpc-addr"); + let rpc_socket = bitcoind.params.rpc_socket.to_string(); + args.push(&rpc_socket); + + let p2p_socket; + if cfg!(feature = "electrs_0_8_10") + || cfg!(feature = "esplora_a33e97e1") + || cfg!(feature = "legacy") + { + args.push("--jsonrpc-import"); + } else { + args.push("--daemon-p2p-addr"); + p2p_socket = bitcoind + .params + .p2p_socket + .expect("electrs_0_9_1 requires bitcoind with p2p port open") + .to_string(); + args.push(&p2p_socket); + } + + let electrum_url = format!("0.0.0.0:{}", get_available_port()?); + args.push("--electrum-rpc-addr"); + args.push(&electrum_url); + + // would be better to disable it, didn't found a flag + let monitoring = format!("0.0.0.0:{}", get_available_port()?); + args.push("--monitoring-addr"); + args.push(&monitoring); + + let esplora_url_string; + let esplora_url = if conf.http_enabled { + esplora_url_string = format!("0.0.0.0:{}", get_available_port()?); + args.push("--http-addr"); + args.push(&esplora_url_string); + #[allow(clippy::redundant_clone)] + Some(esplora_url_string.clone()) + } else { + None + }; + + let view_stderr = if conf.view_stderr { + Stdio::inherit() + } else { + Stdio::null() + }; + + debug!("args: {:?}", args); + let mut process = Command::new(&exe) + .args(args) + .stderr(view_stderr) + .spawn() + .with_context(|| format!("Error while executing {:?}", exe.as_ref()))?; + + let client = loop { + if let Some(status) = process.try_wait()? { + if conf.attempts > 0 { + warn!("early exit with: {:?}. Trying to launch again ({} attempts remaining), maybe some other process used our available port", status, conf.attempts); + let mut conf = conf.clone(); + conf.attempts -= 1; + return Self::with_conf(exe, bitcoind, &conf) + .with_context(|| format!("Remaining attempts {}", conf.attempts)); + } else { + error!("early exit with: {:?}", status); + return Err(Error::EarlyExit(status).into()); + } + } + match RawClient::new(&electrum_url, None) { + Ok(client) => break client, + Err(_) => std::thread::sleep(Duration::from_millis(500)), + } + }; + + Ok(ElectrsD { + process, + client, + work_dir, + electrum_url, + esplora_url, + }) + } + + /// triggers electrs sync by sending the `SIGUSR1` signal, useful to call after a block for example + #[cfg(not(target_os = "windows"))] + pub fn trigger(&self) -> anyhow::Result<()> { + Ok(nix::sys::signal::kill( + nix::unistd::Pid::from_raw(self.process.id() as i32), + nix::sys::signal::SIGUSR1, + )?) + } + + #[cfg(target_os = "windows")] + pub fn trigger(&self) -> anyhow::Result<()> { + Ok(()) + } + + /// Return the current workdir path of the running electrs + pub fn workdir(&self) -> PathBuf { + self.work_dir.path() + } + + /// terminate the electrs process + pub fn kill(&mut self) -> anyhow::Result<()> { + match self.work_dir { + DataDir::Persistent(_) => { + self.inner_kill()?; + // Wait for the process to exit + match self.process.wait() { + Ok(_) => Ok(()), + Err(e) => Err(e.into()), + } + } + DataDir::Temporary(_) => Ok(self.process.kill()?), + } + } + + #[cfg(not(target_os = "windows"))] + fn inner_kill(&mut self) -> anyhow::Result<()> { + // Send SIGINT signal to electrsd + Ok(nix::sys::signal::kill( + nix::unistd::Pid::from_raw(self.process.id() as i32), + nix::sys::signal::SIGINT, + )?) + } + + #[cfg(target_os = "windows")] + fn inner_kill(&mut self) -> anyhow::Result<()> { + Ok(self.process.kill()?) + } +} + +impl Drop for ElectrsD { + fn drop(&mut self) { + let _ = self.kill(); + } +} + +/// Provide the electrs executable path if a version feature has been specified and `ELECTRSD_SKIP_DOWNLOAD` is not set. +pub fn downloaded_exe_path() -> Option { + if versions::HAS_FEATURE && std::env::var_os("ELECTRSD_SKIP_DOWNLOAD").is_none() { + Some(format!( + "{}/electrs/{}/electrs", + env!("OUT_DIR"), + versions::electrs_name(), + )) + } else { + None + } +} + +/// Returns the daemon `electrs` executable with the following precedence: +/// +/// 1) If it's specified in the `ELECTRS_EXEC` or in `ELECTRS_EXE` env var (errors if both env vars are present) +/// 2) If there is no env var but an auto-download feature such as `electrs_0_9_11` is enabled, returns the path of the downloaded executabled +/// 3) If neither of the precedent are available, the `electrs` executable is searched in the `PATH` +pub fn exe_path() -> anyhow::Result { + if let (Ok(_), Ok(_)) = (std::env::var("ELECTRS_EXEC"), std::env::var("ELECTRS_EXE")) { + return Err(error::Error::BothEnvVars.into()); + } + if let Ok(path) = std::env::var("ELECTRS_EXEC") { + return Ok(path); + } + if let Ok(path) = std::env::var("ELECTRS_EXE") { + return Ok(path); + } + if let Some(path) = downloaded_exe_path() { + return Ok(path); + } + // Manually search for electrs in PATH + let path_var = env::var("PATH").map_err(|_| Error::NoElectrsExecutableFound)?; + + #[cfg(target_os = "windows")] + let path_separator = ';'; + #[cfg(not(target_os = "windows"))] + let path_separator = ':'; + + for path_dir in path_var.split(path_separator) { + let mut candidate = PathBuf::from(path_dir); + candidate.push("electrs"); + + #[cfg(target_os = "windows")] + { + // On Windows, try with .exe extension + candidate.set_extension("exe"); + } + + if candidate.is_file() { + // Check if the file is executable + #[cfg(not(target_os = "windows"))] + { + use std::os::unix::fs::PermissionsExt; + if let Ok(metadata) = std::fs::metadata(&candidate) { + let permissions = metadata.permissions(); + if permissions.mode() & 0o111 != 0 { + return Ok(candidate.display().to_string()); + } + } + } + + #[cfg(target_os = "windows")] + { + return Ok(candidate.display().to_string()); + } + } + } + + Err(Error::NoElectrsExecutableFound.into()) +} + +#[cfg(test)] +mod test { + use crate::exe_path; + use crate::ElectrsD; + use corepc_node::P2P; + use electrum_client::ElectrumApi; + use log::{debug, log_enabled, Level}; + use std::env; + + #[test] + #[ignore] // launch singularly since env are globals + fn test_both_env_vars() { + env::set_var("ELECTRS_EXEC", "placeholder"); + env::set_var("ELECTRS_EXE", "placeholder"); + assert!(exe_path().is_err()); + // unsetting because this errors everything in mod test! + env::remove_var("ELECTRS_EXEC"); + env::remove_var("ELECTRS_EXE"); + } + + #[test] + fn test_electrsd() { + let (electrs_exe, bitcoind, electrsd) = setup_nodes(); + let header = electrsd.client.block_headers_subscribe().unwrap(); + assert_eq!(header.height, 1); + let address = bitcoind.client.new_address().unwrap(); + bitcoind.client.generate_to_address(100, &address).unwrap(); + + electrsd.trigger().unwrap(); + + let header = loop { + std::thread::sleep(std::time::Duration::from_millis(100)); + let header = electrsd.client.block_headers_subscribe().unwrap(); + if header.height > 100 { + break header; + } + }; + assert_eq!(header.height, 101); + + // launch another instance to check there are no fixed port used + let electrsd = ElectrsD::new(&electrs_exe, &bitcoind).unwrap(); + let header = electrsd.client.block_headers_subscribe().unwrap(); + assert_eq!(header.height, 101); + } + + #[test] + fn test_kill() { + let (_, bitcoind, mut electrsd) = setup_nodes(); + let _ = bitcoind.client.get_network_info().unwrap(); // without using bitcoind, it is dropped and all the rest fails. + let _ = electrsd.client.ping().unwrap(); + assert!(electrsd.client.ping().is_ok()); + electrsd.kill().unwrap(); + assert!(electrsd.client.ping().is_err()); + } + + pub(crate) fn setup_nodes() -> (String, corepc_node::Node, ElectrsD) { + let (bitcoind_exe, electrs_exe) = init(); + debug!("bitcoind: {}", &bitcoind_exe); + debug!("electrs: {}", &electrs_exe); + let mut conf = corepc_node::Conf::default(); + conf.view_stdout = log_enabled!(Level::Debug); + if !cfg!(feature = "electrs_0_8_10") && !cfg!(feature = "esplora_a33e97e1") { + conf.p2p = P2P::Yes; + } + let bitcoind = corepc_node::Node::with_conf(&bitcoind_exe, &conf).unwrap(); + let electrs_conf = crate::Conf { + view_stderr: log_enabled!(Level::Debug), + ..Default::default() + }; + let electrsd = ElectrsD::with_conf(&electrs_exe, &bitcoind, &electrs_conf).unwrap(); + (electrs_exe, bitcoind, electrsd) + } + + fn init() -> (String, String) { + let _ = env_logger::try_init(); + let bitcoind_exe_path = corepc_node::exe_path().unwrap(); + let electrs_exe_path = exe_path().unwrap(); + (bitcoind_exe_path, electrs_exe_path) + } +} diff --git a/electrsd/src/versions.rs b/electrsd/src/versions.rs new file mode 100644 index 000000000..999c39d6d --- /dev/null +++ b/electrsd/src/versions.rs @@ -0,0 +1,44 @@ +#[cfg(target_os = "macos")] +const OS: &str = "macos"; + +#[cfg(target_os = "linux")] +const OS: &str = "linux"; + +#[cfg(not(any(target_os = "linux", target_os = "macos")))] +const OS: &str = "undefined"; + +#[cfg(feature = "electrs_0_8_10")] +const VERSION: &str = "v0.8.10"; + +#[cfg(feature = "esplora_a33e97e1")] +const VERSION: &str = "esplora_a33e97e1a1fc63fa9c20a116bb92579bbf43b254"; + +#[cfg(feature = "electrs_0_9_1")] +const VERSION: &str = "v0.9.1"; + +#[cfg(feature = "electrs_0_9_11")] +const VERSION: &str = "v0.9.11"; + +#[cfg(feature = "electrs_0_10_6")] +const VERSION: &str = "v0.10.6"; + +#[cfg(not(any( + feature = "electrs_0_8_10", + feature = "electrs_0_9_1", + feature = "electrs_0_9_11", + feature = "electrs_0_10_6", + feature = "esplora_a33e97e1", +)))] +const VERSION: &str = "NA"; + +pub const HAS_FEATURE: bool = cfg!(any( + feature = "electrs_0_8_10", + feature = "electrs_0_9_1", + feature = "electrs_0_9_11", + feature = "electrs_0_10_6", + feature = "esplora_a33e97e1", +)); + +pub fn electrs_name() -> String { + format!("electrs_{}_{}", OS, VERSION) +} From 8062f29fb9c539289ed261f4202e10989b4bde0b Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 9 Apr 2026 08:29:48 +1000 Subject: [PATCH 02/12] electrs: Upgrade to v0.12.0 deps using path `corepc-node` and `corepc-client` `v0.12.0` were just released, use them. While we are at it use `path` dependency. --- electrsd/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/electrsd/Cargo.toml b/electrsd/Cargo.toml index a93453dac..f87aeb397 100644 --- a/electrsd/Cargo.toml +++ b/electrsd/Cargo.toml @@ -10,8 +10,8 @@ edition = "2018" categories = ["cryptography::cryptocurrencies", "development-tools::testing"] [dependencies] -corepc-node = { version = "0.10.0" } -corepc-client = { version = "0.10.0" } +corepc-node = { version = "0.12.0", path = "../node" } +corepc-client = { version = "0.12.0", path = "../client" } electrum-client = { version = "0.24.0", default-features = false } log = { version = "0.4" } From 7ebc5b12a772e1ccca15feebbb6d6447627a2fc5 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 9 Apr 2026 08:58:35 +1000 Subject: [PATCH 03/12] CI: Copy jobs from electrsd repo Copy the CI jobs from the old `electrsd` repository. Modify the calls to `cargo` to first `cd electsd`. This is a dirty hack but we have a re-write of CI to use `cargo rbmt` in flight anyways. --- .github/workflows/rust.yaml | 58 +++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/.github/workflows/rust.yaml b/.github/workflows/rust.yaml index b26ef5451..5a221b2d9 100644 --- a/.github/workflows/rust.yaml +++ b/.github/workflows/rust.yaml @@ -162,3 +162,61 @@ jobs: env: BITCOIND_DOWNLOAD_DIR: ${{ github.workspace }}/.cache/corepc/bitcoind run: cd integration_test && cargo test --features=${{ matrix.version }},download + + # The jobs below copied from electrsd repo during import. Not too + # much further thought given to it. + test-electrs: + name: Test Electrs + runs-on: ubuntu-24.04 + env: + CARGO_TERM_COLOR: always + RUST_LOG: debug + strategy: + matrix: + features: + - corepc-node_22_1,electrs_0_8_10 + - corepc-node_22_1,electrs_0_9_1 + - corepc-node_22_1,electrs_0_9_11 + - corepc-node_22_1,electrs_0_10_6 + fail-fast: false + + steps: + - uses: actions/checkout@v3 + - uses: Swatinem/rust-cache@v2 + - uses: dtolnay/rust-toolchain@stable + - run: cd electrsd && cargo test --features ${{ matrix.features }} + + + test-electrs-esplora: + name: Test Electrs Esplora + runs-on: ubuntu-24.04 + env: + CARGO_TERM_COLOR: always + strategy: + matrix: + features: ["corepc-node_22_1,legacy,esplora_a33e97e1"] + + steps: + - uses: actions/checkout@v3 + - uses: Swatinem/rust-cache@v2 + - uses: dtolnay/rust-toolchain@stable + - run: cd electrsd && cargo test --features ${{ matrix.features }} + + test-electrs-no-download: + name: Test Electrs no auto-download features + runs-on: ubuntu-24.04 + env: + CARGO_TERM_COLOR: always + ELECTRS_EXEC: "/home/runner/.cargo-install/electrs/bin/electrs" + steps: + - uses: dtolnay/rust-toolchain@stable + - name: Install electrs + # Automatically cache installed binaries to avoid compiling them each run + uses: baptiste0928/cargo-install@v2 + with: + crate: electrs + - run: "echo $ELECTRS_EXEC" + - name: Checkout Crate + uses: actions/checkout@v3 + - uses: Swatinem/rust-cache@v2 + - run: cargo test --features 'corepc-node_25_2' From af4fe0e6750b6d1c629d16ff6737ad7514ea7c22 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 9 Apr 2026 09:03:53 +1000 Subject: [PATCH 04/12] electrsd: Add support for Core 30.2 Add a feature to use `node` Core 30.2 support. --- electrsd/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/electrsd/Cargo.toml b/electrsd/Cargo.toml index f87aeb397..d3396b880 100644 --- a/electrsd/Cargo.toml +++ b/electrsd/Cargo.toml @@ -43,6 +43,7 @@ electrs_0_9_1 = ["download"] electrs_0_9_11 = ["download"] electrs_0_10_6 = ["download"] +corepc-node_30_2 = ["corepc-node/download", "corepc-node/30_2"] corepc-node_29_0 = ["corepc-node/download", "corepc-node/29_0"] corepc-node_28_2 = ["corepc-node/download", "corepc-node/28_2"] corepc-node_27_2 = ["corepc-node/download", "corepc-node/27_2"] From c308f59fd69f0ff0c31ae97c27c2075099d76fd7 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 9 Apr 2026 09:06:47 +1000 Subject: [PATCH 05/12] Rename corepc-node to bitcoind When the `corepc-` nomenclature was adopted we renamed `bitcoind` to `corepc-node` (and the main type from `BitcoinD` to `Node`). In hindsight this was a bad move because it broke the API uniformity between `bitcoind` and `electrsd` and hurt users that used both. Revert the name changes back to `bitcoind` and `BitcoinD`. While we are at it bump the version number to `0.37.0` ready for release. --- .github/workflows/rust.yaml | 12 +- Cargo-minimal.lock | 36 ++-- Cargo-recent.lock | 36 ++-- Cargo.toml | 6 +- {node => bitcoind}/CHANGELOG.md | 0 {node => bitcoind}/Cargo.toml | 6 +- {node => bitcoind}/LICENSE | 0 {node => bitcoind}/README.md | 4 +- {node => bitcoind}/build.rs | 0 {node => bitcoind}/contrib/extra_tests.sh | 0 {node => bitcoind}/contrib/test_vars.sh | 0 .../sha256/bitcoin-core-0.17.2-SHA256SUMS.asc | 0 .../sha256/bitcoin-core-0.18.1-SHA256SUMS.asc | 0 .../sha256/bitcoin-core-0.19.1-SHA256SUMS.asc | 0 .../sha256/bitcoin-core-0.20.2-SHA256SUMS.asc | 0 .../sha256/bitcoin-core-0.21.2-SHA256SUMS.asc | 0 .../sha256/bitcoin-core-22.0-SHA256SUMS | 0 .../sha256/bitcoin-core-22.1-SHA256SUMS | 0 .../sha256/bitcoin-core-23.0-SHA256SUMS | 0 .../sha256/bitcoin-core-23.1-SHA256SUMS | 0 .../sha256/bitcoin-core-23.2-SHA256SUMS | 0 .../sha256/bitcoin-core-24.0.1-SHA256SUMS | 0 .../sha256/bitcoin-core-24.1-SHA256SUMS | 0 .../sha256/bitcoin-core-24.2-SHA256SUMS | 0 .../sha256/bitcoin-core-25.0-SHA256SUMS | 0 .../sha256/bitcoin-core-25.1-SHA256SUMS | 0 .../sha256/bitcoin-core-25.2-SHA256SUMS | 0 .../sha256/bitcoin-core-26.0-SHA256SUMS | 0 .../sha256/bitcoin-core-26.1-SHA256SUMS | 0 .../sha256/bitcoin-core-26.2-SHA256SUMS | 0 .../sha256/bitcoin-core-27.0-SHA256SUMS | 0 .../sha256/bitcoin-core-27.1-SHA256SUMS | 0 .../sha256/bitcoin-core-27.2-SHA256SUMS | 0 .../sha256/bitcoin-core-28.0-SHA256SUMS | 0 .../sha256/bitcoin-core-28.1-SHA256SUMS | 0 .../sha256/bitcoin-core-28.2-SHA256SUMS | 0 .../sha256/bitcoin-core-29.0-SHA256SUMS | 0 .../sha256/bitcoin-core-30.0-SHA256SUMS | 0 .../sha256/bitcoin-core-30.2-SHA256SUMS | 0 {node => bitcoind}/src/client_versions.rs | 0 {node => bitcoind}/src/lib.rs | 73 ++++---- {node => bitcoind}/src/versions.rs | 0 contrib/update-lock-files.sh | 2 +- electrsd/Cargo.toml | 30 ++-- electrsd/src/error.rs | 6 +- electrsd/src/lib.rs | 28 ++-- integration_test/Cargo.toml | 48 +++--- integration_test/src/lib.rs | 34 ++-- integration_test/tests/blockchain.rs | 110 ++++++------ integration_test/tests/control.rs | 16 +- integration_test/tests/generating.rs | 16 +- integration_test/tests/hidden.rs | 18 +- integration_test/tests/mining.rs | 20 +-- integration_test/tests/network.rs | 34 ++-- integration_test/tests/raw_transactions.rs | 58 +++---- integration_test/tests/signer.rs | 10 +- integration_test/tests/util.rs | 22 +-- integration_test/tests/wallet.rs | 158 +++++++++--------- integration_test/tests/zmq.rs | 6 +- justfile | 2 +- 60 files changed, 395 insertions(+), 396 deletions(-) rename {node => bitcoind}/CHANGELOG.md (100%) rename {node => bitcoind}/Cargo.toml (96%) rename {node => bitcoind}/LICENSE (100%) rename {node => bitcoind}/README.md (96%) rename {node => bitcoind}/build.rs (100%) rename {node => bitcoind}/contrib/extra_tests.sh (100%) rename {node => bitcoind}/contrib/test_vars.sh (100%) rename {node => bitcoind}/sha256/bitcoin-core-0.17.2-SHA256SUMS.asc (100%) rename {node => bitcoind}/sha256/bitcoin-core-0.18.1-SHA256SUMS.asc (100%) rename {node => bitcoind}/sha256/bitcoin-core-0.19.1-SHA256SUMS.asc (100%) rename {node => bitcoind}/sha256/bitcoin-core-0.20.2-SHA256SUMS.asc (100%) rename {node => bitcoind}/sha256/bitcoin-core-0.21.2-SHA256SUMS.asc (100%) rename {node => bitcoind}/sha256/bitcoin-core-22.0-SHA256SUMS (100%) rename {node => bitcoind}/sha256/bitcoin-core-22.1-SHA256SUMS (100%) rename {node => bitcoind}/sha256/bitcoin-core-23.0-SHA256SUMS (100%) rename {node => bitcoind}/sha256/bitcoin-core-23.1-SHA256SUMS (100%) rename {node => bitcoind}/sha256/bitcoin-core-23.2-SHA256SUMS (100%) rename {node => bitcoind}/sha256/bitcoin-core-24.0.1-SHA256SUMS (100%) rename {node => bitcoind}/sha256/bitcoin-core-24.1-SHA256SUMS (100%) rename {node => bitcoind}/sha256/bitcoin-core-24.2-SHA256SUMS (100%) rename {node => bitcoind}/sha256/bitcoin-core-25.0-SHA256SUMS (100%) rename {node => bitcoind}/sha256/bitcoin-core-25.1-SHA256SUMS (100%) rename {node => bitcoind}/sha256/bitcoin-core-25.2-SHA256SUMS (100%) rename {node => bitcoind}/sha256/bitcoin-core-26.0-SHA256SUMS (100%) rename {node => bitcoind}/sha256/bitcoin-core-26.1-SHA256SUMS (100%) rename {node => bitcoind}/sha256/bitcoin-core-26.2-SHA256SUMS (100%) rename {node => bitcoind}/sha256/bitcoin-core-27.0-SHA256SUMS (100%) rename {node => bitcoind}/sha256/bitcoin-core-27.1-SHA256SUMS (100%) rename {node => bitcoind}/sha256/bitcoin-core-27.2-SHA256SUMS (100%) rename {node => bitcoind}/sha256/bitcoin-core-28.0-SHA256SUMS (100%) rename {node => bitcoind}/sha256/bitcoin-core-28.1-SHA256SUMS (100%) rename {node => bitcoind}/sha256/bitcoin-core-28.2-SHA256SUMS (100%) rename {node => bitcoind}/sha256/bitcoin-core-29.0-SHA256SUMS (100%) rename {node => bitcoind}/sha256/bitcoin-core-30.0-SHA256SUMS (100%) rename {node => bitcoind}/sha256/bitcoin-core-30.2-SHA256SUMS (100%) rename {node => bitcoind}/src/client_versions.rs (100%) rename {node => bitcoind}/src/lib.rs (94%) rename {node => bitcoind}/src/versions.rs (100%) diff --git a/.github/workflows/rust.yaml b/.github/workflows/rust.yaml index 5a221b2d9..d99ad3345 100644 --- a/.github/workflows/rust.yaml +++ b/.github/workflows/rust.yaml @@ -174,10 +174,10 @@ jobs: strategy: matrix: features: - - corepc-node_22_1,electrs_0_8_10 - - corepc-node_22_1,electrs_0_9_1 - - corepc-node_22_1,electrs_0_9_11 - - corepc-node_22_1,electrs_0_10_6 + - bitcoind_22_1,electrs_0_8_10 + - bitcoind_22_1,electrs_0_9_1 + - bitcoind_22_1,electrs_0_9_11 + - bitcoind_22_1,electrs_0_10_6 fail-fast: false steps: @@ -194,7 +194,7 @@ jobs: CARGO_TERM_COLOR: always strategy: matrix: - features: ["corepc-node_22_1,legacy,esplora_a33e97e1"] + features: ["bitcoind_22_1,legacy,esplora_a33e97e1"] steps: - uses: actions/checkout@v3 @@ -219,4 +219,4 @@ jobs: - name: Checkout Crate uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 - - run: cargo test --features 'corepc-node_25_2' + - run: cargo test --features 'bitcoind_25_2' diff --git a/Cargo-minimal.lock b/Cargo-minimal.lock index 2556f12b6..6794a3ae5 100644 --- a/Cargo-minimal.lock +++ b/Cargo-minimal.lock @@ -139,6 +139,24 @@ dependencies = [ "serde", ] +[[package]] +name = "bitcoind" +version = "0.37.0" +dependencies = [ + "anyhow", + "bitcoin_hashes", + "bitreq", + "corepc-client", + "env_logger", + "flate2", + "log", + "serde_json", + "tar", + "tempfile", + "which", + "zip", +] + [[package]] name = "bitflags" version = "2.10.0" @@ -248,24 +266,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "corepc-node" -version = "0.12.0" -dependencies = [ - "anyhow", - "bitcoin_hashes", - "bitreq", - "corepc-client", - "env_logger", - "flate2", - "log", - "serde_json", - "tar", - "tempfile", - "which", - "zip", -] - [[package]] name = "corepc-types" version = "0.12.0" diff --git a/Cargo-recent.lock b/Cargo-recent.lock index 2556f12b6..6794a3ae5 100644 --- a/Cargo-recent.lock +++ b/Cargo-recent.lock @@ -139,6 +139,24 @@ dependencies = [ "serde", ] +[[package]] +name = "bitcoind" +version = "0.37.0" +dependencies = [ + "anyhow", + "bitcoin_hashes", + "bitreq", + "corepc-client", + "env_logger", + "flate2", + "log", + "serde_json", + "tar", + "tempfile", + "which", + "zip", +] + [[package]] name = "bitflags" version = "2.10.0" @@ -248,24 +266,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "corepc-node" -version = "0.12.0" -dependencies = [ - "anyhow", - "bitcoin_hashes", - "bitreq", - "corepc-client", - "env_logger", - "flate2", - "log", - "serde_json", - "tar", - "tempfile", - "which", - "zip", -] - [[package]] name = "corepc-types" version = "0.12.0" diff --git a/Cargo.toml b/Cargo.toml index 3a64cbfc4..0d8bb5a07 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = [ "bitreq", "client", "fuzz", "jsonrpc", "node", "types"] +members = ["bitcoind", "bitreq", "client", "fuzz", "jsonrpc", "types"] exclude = ["integration_test", "verify", "electrsd"] resolver = "2" rust-version = "1.75.0" @@ -10,8 +10,8 @@ path = "client" [patch.crates-io.jsonrpc] path = "jsonrpc" -[patch.crates-io.corepc-node] -path = "node" +[patch.crates-io.bitcoind] +path = "bitcoind" [patch.crates-io.corepc-types] path = "types" diff --git a/node/CHANGELOG.md b/bitcoind/CHANGELOG.md similarity index 100% rename from node/CHANGELOG.md rename to bitcoind/CHANGELOG.md diff --git a/node/Cargo.toml b/bitcoind/Cargo.toml similarity index 96% rename from node/Cargo.toml rename to bitcoind/Cargo.toml index a0c1831f0..d7de50c78 100644 --- a/node/Cargo.toml +++ b/bitcoind/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "corepc-node" -version = "0.12.0" +name = "bitcoind" +version = "0.37.0" authors = ["Riccardo Casatta ", "Tobin C. Harding "] license = "MIT" repository = "https://github.com/rust-bitcoin/corepc" @@ -75,7 +75,7 @@ features = ["28_2"] rustdoc-args = ["--cfg", "docsrs"] [package.metadata.rbmt.lint] -# The node crate requires a version feature to compile; use `latest` for per-package lint. +# The bitcoind crate requires a version feature to compile; use `latest` for per-package lint. features = ["latest"] # Duplicates from build-dep/dep splits, --target=all, or upstream version conflicts. allowed_duplicates = [ diff --git a/node/LICENSE b/bitcoind/LICENSE similarity index 100% rename from node/LICENSE rename to bitcoind/LICENSE diff --git a/node/README.md b/bitcoind/README.md similarity index 96% rename from node/README.md rename to bitcoind/README.md index 975386bba..a9d42ffbf 100644 --- a/node/README.md +++ b/bitcoind/README.md @@ -23,12 +23,12 @@ When you don't use the auto-download feature you have the following options: ```rust if let Ok(exe_path) = corepc_node::exe_path() { - let node = corepc_node::Node::new(exe_path).unwrap(); + let node = corepc_node::BitcoinD::new(exe_path).unwrap(); assert_eq!(0, node.client.get_blockchain_info().unwrap().blocks); } ``` -Startup options could be configured via the [`Conf`] struct using [`Node::with_conf`] or +Startup options could be configured via the [`Conf`] struct using [`BitcoinD::with_conf`] or `Node::from_downloaded_with_conf` ## Features diff --git a/node/build.rs b/bitcoind/build.rs similarity index 100% rename from node/build.rs rename to bitcoind/build.rs diff --git a/node/contrib/extra_tests.sh b/bitcoind/contrib/extra_tests.sh similarity index 100% rename from node/contrib/extra_tests.sh rename to bitcoind/contrib/extra_tests.sh diff --git a/node/contrib/test_vars.sh b/bitcoind/contrib/test_vars.sh similarity index 100% rename from node/contrib/test_vars.sh rename to bitcoind/contrib/test_vars.sh diff --git a/node/sha256/bitcoin-core-0.17.2-SHA256SUMS.asc b/bitcoind/sha256/bitcoin-core-0.17.2-SHA256SUMS.asc similarity index 100% rename from node/sha256/bitcoin-core-0.17.2-SHA256SUMS.asc rename to bitcoind/sha256/bitcoin-core-0.17.2-SHA256SUMS.asc diff --git a/node/sha256/bitcoin-core-0.18.1-SHA256SUMS.asc b/bitcoind/sha256/bitcoin-core-0.18.1-SHA256SUMS.asc similarity index 100% rename from node/sha256/bitcoin-core-0.18.1-SHA256SUMS.asc rename to bitcoind/sha256/bitcoin-core-0.18.1-SHA256SUMS.asc diff --git a/node/sha256/bitcoin-core-0.19.1-SHA256SUMS.asc b/bitcoind/sha256/bitcoin-core-0.19.1-SHA256SUMS.asc similarity index 100% rename from node/sha256/bitcoin-core-0.19.1-SHA256SUMS.asc rename to bitcoind/sha256/bitcoin-core-0.19.1-SHA256SUMS.asc diff --git a/node/sha256/bitcoin-core-0.20.2-SHA256SUMS.asc b/bitcoind/sha256/bitcoin-core-0.20.2-SHA256SUMS.asc similarity index 100% rename from node/sha256/bitcoin-core-0.20.2-SHA256SUMS.asc rename to bitcoind/sha256/bitcoin-core-0.20.2-SHA256SUMS.asc diff --git a/node/sha256/bitcoin-core-0.21.2-SHA256SUMS.asc b/bitcoind/sha256/bitcoin-core-0.21.2-SHA256SUMS.asc similarity index 100% rename from node/sha256/bitcoin-core-0.21.2-SHA256SUMS.asc rename to bitcoind/sha256/bitcoin-core-0.21.2-SHA256SUMS.asc diff --git a/node/sha256/bitcoin-core-22.0-SHA256SUMS b/bitcoind/sha256/bitcoin-core-22.0-SHA256SUMS similarity index 100% rename from node/sha256/bitcoin-core-22.0-SHA256SUMS rename to bitcoind/sha256/bitcoin-core-22.0-SHA256SUMS diff --git a/node/sha256/bitcoin-core-22.1-SHA256SUMS b/bitcoind/sha256/bitcoin-core-22.1-SHA256SUMS similarity index 100% rename from node/sha256/bitcoin-core-22.1-SHA256SUMS rename to bitcoind/sha256/bitcoin-core-22.1-SHA256SUMS diff --git a/node/sha256/bitcoin-core-23.0-SHA256SUMS b/bitcoind/sha256/bitcoin-core-23.0-SHA256SUMS similarity index 100% rename from node/sha256/bitcoin-core-23.0-SHA256SUMS rename to bitcoind/sha256/bitcoin-core-23.0-SHA256SUMS diff --git a/node/sha256/bitcoin-core-23.1-SHA256SUMS b/bitcoind/sha256/bitcoin-core-23.1-SHA256SUMS similarity index 100% rename from node/sha256/bitcoin-core-23.1-SHA256SUMS rename to bitcoind/sha256/bitcoin-core-23.1-SHA256SUMS diff --git a/node/sha256/bitcoin-core-23.2-SHA256SUMS b/bitcoind/sha256/bitcoin-core-23.2-SHA256SUMS similarity index 100% rename from node/sha256/bitcoin-core-23.2-SHA256SUMS rename to bitcoind/sha256/bitcoin-core-23.2-SHA256SUMS diff --git a/node/sha256/bitcoin-core-24.0.1-SHA256SUMS b/bitcoind/sha256/bitcoin-core-24.0.1-SHA256SUMS similarity index 100% rename from node/sha256/bitcoin-core-24.0.1-SHA256SUMS rename to bitcoind/sha256/bitcoin-core-24.0.1-SHA256SUMS diff --git a/node/sha256/bitcoin-core-24.1-SHA256SUMS b/bitcoind/sha256/bitcoin-core-24.1-SHA256SUMS similarity index 100% rename from node/sha256/bitcoin-core-24.1-SHA256SUMS rename to bitcoind/sha256/bitcoin-core-24.1-SHA256SUMS diff --git a/node/sha256/bitcoin-core-24.2-SHA256SUMS b/bitcoind/sha256/bitcoin-core-24.2-SHA256SUMS similarity index 100% rename from node/sha256/bitcoin-core-24.2-SHA256SUMS rename to bitcoind/sha256/bitcoin-core-24.2-SHA256SUMS diff --git a/node/sha256/bitcoin-core-25.0-SHA256SUMS b/bitcoind/sha256/bitcoin-core-25.0-SHA256SUMS similarity index 100% rename from node/sha256/bitcoin-core-25.0-SHA256SUMS rename to bitcoind/sha256/bitcoin-core-25.0-SHA256SUMS diff --git a/node/sha256/bitcoin-core-25.1-SHA256SUMS b/bitcoind/sha256/bitcoin-core-25.1-SHA256SUMS similarity index 100% rename from node/sha256/bitcoin-core-25.1-SHA256SUMS rename to bitcoind/sha256/bitcoin-core-25.1-SHA256SUMS diff --git a/node/sha256/bitcoin-core-25.2-SHA256SUMS b/bitcoind/sha256/bitcoin-core-25.2-SHA256SUMS similarity index 100% rename from node/sha256/bitcoin-core-25.2-SHA256SUMS rename to bitcoind/sha256/bitcoin-core-25.2-SHA256SUMS diff --git a/node/sha256/bitcoin-core-26.0-SHA256SUMS b/bitcoind/sha256/bitcoin-core-26.0-SHA256SUMS similarity index 100% rename from node/sha256/bitcoin-core-26.0-SHA256SUMS rename to bitcoind/sha256/bitcoin-core-26.0-SHA256SUMS diff --git a/node/sha256/bitcoin-core-26.1-SHA256SUMS b/bitcoind/sha256/bitcoin-core-26.1-SHA256SUMS similarity index 100% rename from node/sha256/bitcoin-core-26.1-SHA256SUMS rename to bitcoind/sha256/bitcoin-core-26.1-SHA256SUMS diff --git a/node/sha256/bitcoin-core-26.2-SHA256SUMS b/bitcoind/sha256/bitcoin-core-26.2-SHA256SUMS similarity index 100% rename from node/sha256/bitcoin-core-26.2-SHA256SUMS rename to bitcoind/sha256/bitcoin-core-26.2-SHA256SUMS diff --git a/node/sha256/bitcoin-core-27.0-SHA256SUMS b/bitcoind/sha256/bitcoin-core-27.0-SHA256SUMS similarity index 100% rename from node/sha256/bitcoin-core-27.0-SHA256SUMS rename to bitcoind/sha256/bitcoin-core-27.0-SHA256SUMS diff --git a/node/sha256/bitcoin-core-27.1-SHA256SUMS b/bitcoind/sha256/bitcoin-core-27.1-SHA256SUMS similarity index 100% rename from node/sha256/bitcoin-core-27.1-SHA256SUMS rename to bitcoind/sha256/bitcoin-core-27.1-SHA256SUMS diff --git a/node/sha256/bitcoin-core-27.2-SHA256SUMS b/bitcoind/sha256/bitcoin-core-27.2-SHA256SUMS similarity index 100% rename from node/sha256/bitcoin-core-27.2-SHA256SUMS rename to bitcoind/sha256/bitcoin-core-27.2-SHA256SUMS diff --git a/node/sha256/bitcoin-core-28.0-SHA256SUMS b/bitcoind/sha256/bitcoin-core-28.0-SHA256SUMS similarity index 100% rename from node/sha256/bitcoin-core-28.0-SHA256SUMS rename to bitcoind/sha256/bitcoin-core-28.0-SHA256SUMS diff --git a/node/sha256/bitcoin-core-28.1-SHA256SUMS b/bitcoind/sha256/bitcoin-core-28.1-SHA256SUMS similarity index 100% rename from node/sha256/bitcoin-core-28.1-SHA256SUMS rename to bitcoind/sha256/bitcoin-core-28.1-SHA256SUMS diff --git a/node/sha256/bitcoin-core-28.2-SHA256SUMS b/bitcoind/sha256/bitcoin-core-28.2-SHA256SUMS similarity index 100% rename from node/sha256/bitcoin-core-28.2-SHA256SUMS rename to bitcoind/sha256/bitcoin-core-28.2-SHA256SUMS diff --git a/node/sha256/bitcoin-core-29.0-SHA256SUMS b/bitcoind/sha256/bitcoin-core-29.0-SHA256SUMS similarity index 100% rename from node/sha256/bitcoin-core-29.0-SHA256SUMS rename to bitcoind/sha256/bitcoin-core-29.0-SHA256SUMS diff --git a/node/sha256/bitcoin-core-30.0-SHA256SUMS b/bitcoind/sha256/bitcoin-core-30.0-SHA256SUMS similarity index 100% rename from node/sha256/bitcoin-core-30.0-SHA256SUMS rename to bitcoind/sha256/bitcoin-core-30.0-SHA256SUMS diff --git a/node/sha256/bitcoin-core-30.2-SHA256SUMS b/bitcoind/sha256/bitcoin-core-30.2-SHA256SUMS similarity index 100% rename from node/sha256/bitcoin-core-30.2-SHA256SUMS rename to bitcoind/sha256/bitcoin-core-30.2-SHA256SUMS diff --git a/node/src/client_versions.rs b/bitcoind/src/client_versions.rs similarity index 100% rename from node/src/client_versions.rs rename to bitcoind/src/client_versions.rs diff --git a/node/src/lib.rs b/bitcoind/src/lib.rs similarity index 94% rename from node/src/lib.rs rename to bitcoind/src/lib.rs index ea602b526..74755f51f 100644 --- a/node/src/lib.rs +++ b/bitcoind/src/lib.rs @@ -37,7 +37,7 @@ pub use self::{ #[derive(Debug)] /// Struct representing the bitcoind process with related information. -pub struct Node { +pub struct BitcoinD { /// Process child handle, used to terminate the process when this struct is dropped. process: Child, /// Rpc client linked to this bitcoind process. @@ -113,7 +113,7 @@ pub enum P2P { /// the node open a p2p port. Yes, /// The node open a p2p port and also connects to the url given as parameter, it's handy to - /// initialize this with [Node::p2p_connect] of another node. The `bool` parameter indicates + /// initialize this with [BitcoinD::p2p_connect] of another node. The `bool` parameter indicates /// if the node can accept connection too. Connect(SocketAddrV4, bool), } @@ -199,7 +199,6 @@ const INVALID_ARGS: [&str; 2] = ["-rpcuser", "-rpcpassword"]; /// /// Default values: /// ``` -/// use corepc_node as bitcoind; /// let mut conf = bitcoind::Conf::default(); /// conf.args = vec!["-regtest", "-fallbackfee=0.0001"]; /// conf.view_stdout = false; @@ -277,12 +276,12 @@ impl Default for Conf<'_> { } } -impl Node { +impl BitcoinD { /// Launch the bitcoind process from the given `exe` executable with default args. /// /// Waits for the node to be ready to accept connections before returning. - pub fn new>(exe: S) -> anyhow::Result { - Node::with_conf(exe, &Conf::default()) + pub fn new>(exe: S) -> anyhow::Result { + BitcoinD::with_conf(exe, &Conf::default()) } /// Launch the bitcoind process from the given `exe` executable with given [Conf] param and @@ -297,12 +296,12 @@ impl Node { /// /// # Returns /// - /// A [`Node`] instance if the node is successfully started and ready to accept connections. + /// A [`BitcoinD`] instance if the node is successfully started and ready to accept connections. /// /// # Errors /// /// If the node fails to start after the specified number of attempts. - pub fn with_conf>(exe: S, conf: &Conf) -> anyhow::Result { + pub fn with_conf>(exe: S, conf: &Conf) -> anyhow::Result { for attempt in 0..conf.attempts { let work_dir = Self::init_work_dir(conf)?; let cookie_file = work_dir.path().join(conf.network).join(".cookie"); @@ -373,7 +372,7 @@ impl Node { continue; } - return Ok(Node { + return Ok(BitcoinD { process, client, work_dir, @@ -562,17 +561,17 @@ impl Node { } #[cfg(feature = "download")] -impl Node { - /// create Node struct with the downloaded executable. - pub fn from_downloaded() -> anyhow::Result { Node::new(downloaded_exe_path()?) } +impl BitcoinD { + /// create BitcoinD struct with the downloaded executable. + pub fn from_downloaded() -> anyhow::Result { BitcoinD::new(downloaded_exe_path()?) } - /// create Node struct with the downloaded executable and given Conf. - pub fn from_downloaded_with_conf(conf: &Conf) -> anyhow::Result { - Node::with_conf(downloaded_exe_path()?, conf) + /// create BitcoinD struct with the downloaded executable and given Conf. + pub fn from_downloaded_with_conf(conf: &Conf) -> anyhow::Result { + BitcoinD::with_conf(downloaded_exe_path()?, conf) } } -impl Drop for Node { +impl Drop for BitcoinD { fn drop(&mut self) { if let DataDir::Persistent(_) = self.work_dir { let _ = self.stop(); @@ -667,7 +666,7 @@ mod test { use tempfile::TempDir; use super::*; - use crate::{exe_path, get_available_port, Conf, Node, LOCAL_IP, P2P}; + use crate::{exe_path, get_available_port, Conf, BitcoinD, LOCAL_IP, P2P}; #[test] fn test_local_ip() { @@ -680,7 +679,7 @@ mod test { #[test] fn test_node_get_blockchain_info() { let exe = init(); - let node = Node::new(exe).unwrap(); + let node = BitcoinD::new(exe).unwrap(); let info = node.client.get_blockchain_info().unwrap(); assert_eq!(0, info.blocks); } @@ -688,7 +687,7 @@ mod test { #[test] fn test_node() { let exe = init(); - let node = Node::new(exe).unwrap(); + let node = BitcoinD::new(exe).unwrap(); let info = node.client.get_blockchain_info().unwrap(); assert_eq!(0, info.blocks); @@ -704,7 +703,7 @@ mod test { let exe = init(); let mut conf = Conf::default(); conf.args.push("-txindex"); - let node = Node::with_conf(&exe, &conf).unwrap(); + let node = BitcoinD::with_conf(&exe, &conf).unwrap(); assert!( node.client.server_version().unwrap() >= 210_000, "getindexinfo requires bitcoin >0.21" @@ -720,11 +719,11 @@ mod test { let exe = init(); let conf = Conf::<'_> { p2p: P2P::Yes, ..Default::default() }; - let node = Node::with_conf(&exe, &conf).unwrap(); + let node = BitcoinD::with_conf(&exe, &conf).unwrap(); assert_eq!(peers_connected(&node.client), 0); let other_conf = Conf::<'_> { p2p: node.p2p_connect(false).unwrap(), ..Default::default() }; - let other_node = Node::with_conf(&exe, &other_conf).unwrap(); + let other_node = BitcoinD::with_conf(&exe, &other_conf).unwrap(); assert_eq!(peers_connected(&node.client), 1); assert_eq!(peers_connected(&other_node.client), 1); @@ -738,10 +737,10 @@ mod test { let datadir = TempDir::new().unwrap(); conf.staticdir = Some(datadir.path().to_path_buf()); - // Start Node with persistent db config + // Start BitcoinD with persistent db config // Generate 101 blocks // Wallet balance should be 50 - let node = Node::with_conf(exe_path().unwrap(), &conf).unwrap(); + let node = BitcoinD::with_conf(exe_path().unwrap(), &conf).unwrap(); let core_addrs = node.client.new_address().unwrap(); node.client.generate_to_address(101, &core_addrs).unwrap(); let wallet_balance_1 = node.client.get_balance().unwrap(); @@ -749,8 +748,8 @@ mod test { drop(node); - // Start a new Node with the same datadir - let node = Node::with_conf(exe_path().unwrap(), &conf).unwrap(); + // Start a new BitcoinD with the same datadir + let node = BitcoinD::with_conf(exe_path().unwrap(), &conf).unwrap(); let wallet_balance_2 = node.client.get_balance().unwrap(); let best_block_2 = node.client.get_best_block_hash().unwrap(); @@ -767,17 +766,17 @@ mod test { let exe = init(); let conf_node1 = Conf::<'_> { p2p: P2P::Yes, ..Default::default() }; - let node1 = Node::with_conf(&exe, &conf_node1).unwrap(); + let node1 = BitcoinD::with_conf(&exe, &conf_node1).unwrap(); assert_eq!(peers_connected(&node1.client), 0); - // Create Node 2 connected Node 1 + // Create BitcoinD 2 connected BitcoinD 1 let conf_node2 = Conf::<'_> { p2p: node1.p2p_connect(true).unwrap(), ..Default::default() }; - let node2 = Node::with_conf(&exe, &conf_node2).unwrap(); + let node2 = BitcoinD::with_conf(&exe, &conf_node2).unwrap(); - // Create Node 3 Connected To Node + // Create BitcoinD 3 Connected To BitcoinD let conf_node3 = Conf::<'_> { p2p: node2.p2p_connect(false).unwrap(), ..Default::default() }; - let node3 = Node::with_conf(exe_path().unwrap(), &conf_node3).unwrap(); + let node3 = BitcoinD::with_conf(exe_path().unwrap(), &conf_node3).unwrap(); // Get each nodes Peers let node1_peers = peers_connected(&node1.client); @@ -796,7 +795,7 @@ mod test { use corepc_client::bitcoin::Amount; let exe = init(); - let node = Node::new(exe).unwrap(); + let node = BitcoinD::new(exe).unwrap(); let alice = node.create_wallet("alice").unwrap(); let alice_address = alice.new_address().unwrap(); let bob = node.create_wallet("bob").unwrap(); @@ -862,7 +861,7 @@ mod test { conf.args.push("-rpcuser=bitcoind"); conf.args.push("-rpcpassword=bitcoind"); - let node = Node::with_conf(exe, &conf); + let node = BitcoinD::with_conf(exe, &conf); assert!(node.is_err()); } @@ -876,7 +875,7 @@ mod test { // this could be also added to node, example: [RpcAuth](https://github.com/testcontainers/testcontainers-rs/blob/dev/testcontainers/src/images/coblox_bitcoincore.rs#L39-L91) conf.args.push("-rpcauth=bitcoind:cccd5d7fd36e55c1b8576b8077dc1b83$60b5676a09f8518dcb4574838fb86f37700cd690d99bd2fdc2ea2bf2ab80ead6"); - let node = Node::with_conf(exe, &conf).unwrap(); + let node = BitcoinD::with_conf(exe, &conf).unwrap(); let auth = Auth::UserPass("bitcoind".to_string(), "bitcoind".to_string()); let client = Client::new_with_auth( @@ -896,7 +895,7 @@ mod test { #[test] fn test_get_cookie_user_and_pass() { let exe = init(); - let node = Node::new(exe).unwrap(); + let node = BitcoinD::new(exe).unwrap(); let user: &str = "bitcoind_user"; let password: &str = "bitcoind_password"; @@ -912,7 +911,7 @@ mod test { #[test] fn zmq_interface_enabled() { let conf = Conf::<'_> { enable_zmq: true, ..Default::default() }; - let node = Node::with_conf(exe_path().unwrap(), &conf).unwrap(); + let node = BitcoinD::with_conf(exe_path().unwrap(), &conf).unwrap(); assert!(node.params.zmq_pub_raw_tx_socket.is_some()); assert!(node.params.zmq_pub_raw_block_socket.is_some()); @@ -921,7 +920,7 @@ mod test { #[test] fn zmq_interface_disabled() { let exe = init(); - let node = Node::new(exe).unwrap(); + let node = BitcoinD::new(exe).unwrap(); assert!(node.params.zmq_pub_raw_tx_socket.is_none()); assert!(node.params.zmq_pub_raw_block_socket.is_none()); diff --git a/node/src/versions.rs b/bitcoind/src/versions.rs similarity index 100% rename from node/src/versions.rs rename to bitcoind/src/versions.rs diff --git a/contrib/update-lock-files.sh b/contrib/update-lock-files.sh index f0a68c904..672e9197b 100755 --- a/contrib/update-lock-files.sh +++ b/contrib/update-lock-files.sh @@ -10,7 +10,7 @@ REPO_DIR="$(git rev-parse --show-toplevel)" ALL_FEATURE_CRATES=(bitreq client fuzz jsonrpc types verify) # Targets with conflicting features and only speficic features are used. -SPECIFIC_FEATURES_CRATES=(integration_test node) +SPECIFIC_FEATURES_CRATES=(integration_test bitcoind) SPECIFIC_FEATURES=(latest) update_lock_files() { diff --git a/electrsd/Cargo.toml b/electrsd/Cargo.toml index d3396b880..eafe5e9a0 100644 --- a/electrsd/Cargo.toml +++ b/electrsd/Cargo.toml @@ -10,7 +10,7 @@ edition = "2018" categories = ["cryptography::cryptocurrencies", "development-tools::testing"] [dependencies] -corepc-node = { version = "0.12.0", path = "../node" } +bitcoind = { version = "0.37.0", path = "../bitcoind" } corepc-client = { version = "0.12.0", path = "../client" } electrum-client = { version = "0.24.0", default-features = false } log = { version = "0.4" } @@ -43,17 +43,17 @@ electrs_0_9_1 = ["download"] electrs_0_9_11 = ["download"] electrs_0_10_6 = ["download"] -corepc-node_30_2 = ["corepc-node/download", "corepc-node/30_2"] -corepc-node_29_0 = ["corepc-node/download", "corepc-node/29_0"] -corepc-node_28_2 = ["corepc-node/download", "corepc-node/28_2"] -corepc-node_27_2 = ["corepc-node/download", "corepc-node/27_2"] -corepc-node_26_2 = ["corepc-node/download", "corepc-node/26_2"] -corepc-node_25_2 = ["corepc-node/download", "corepc-node/25_2"] -corepc-node_24_2 = ["corepc-node/download", "corepc-node/24_2"] -corepc-node_23_1 = ["corepc-node/download", "corepc-node/23_2"] -corepc-node_22_1 = ["corepc-node/download", "corepc-node/22_1"] -corepc-node_0_21_2 = ["corepc-node/download", "corepc-node/0_21_2"] -corepc-node_0_20_2 = ["corepc-node/download", "corepc-node/0_20_2"] -corepc-node_0_19_1 = ["corepc-node/download", "corepc-node/0_19_1"] -corepc-node_0_18_1 = ["corepc-node/download", "corepc-node/0_18_1"] -corepc-node_0_17_2 = ["corepc-node/download", "corepc-node/0_17_2"] +bitcoind_30_2 = ["bitcoind/download", "bitcoind/30_2"] +bitcoind_29_0 = ["bitcoind/download", "bitcoind/29_0"] +bitcoind_28_2 = ["bitcoind/download", "bitcoind/28_2"] +bitcoind_27_2 = ["bitcoind/download", "bitcoind/27_2"] +bitcoind_26_2 = ["bitcoind/download", "bitcoind/26_2"] +bitcoind_25_2 = ["bitcoind/download", "bitcoind/25_2"] +bitcoind_24_2 = ["bitcoind/download", "bitcoind/24_2"] +bitcoind_23_1 = ["bitcoind/download", "bitcoind/23_2"] +bitcoind_22_1 = ["bitcoind/download", "bitcoind/22_1"] +bitcoind_0_21_2 = ["bitcoind/download", "bitcoind/0_21_2"] +bitcoind_0_20_2 = ["bitcoind/download", "bitcoind/0_20_2"] +bitcoind_0_19_1 = ["bitcoind/download", "bitcoind/0_19_1"] +bitcoind_0_18_1 = ["bitcoind/download", "bitcoind/0_18_1"] +bitcoind_0_17_2 = ["bitcoind/download", "bitcoind/0_17_2"] diff --git a/electrsd/src/error.rs b/electrsd/src/error.rs index c8dc5240b..ff0188ea6 100644 --- a/electrsd/src/error.rs +++ b/electrsd/src/error.rs @@ -5,7 +5,7 @@ pub enum Error { Io(std::io::Error), /// Wrapper of bitcoind Error - Bitcoind(corepc_node::Error), + Bitcoind(bitcoind::Error), /// Wrapper of electrum_client Error ElectrumClient(electrum_client::Error), @@ -55,8 +55,8 @@ impl From for Error { } } -impl From for Error { - fn from(e: corepc_node::Error) -> Self { +impl From for Error { + fn from(e: bitcoind::Error) -> Self { Error::Bitcoind(e) } } diff --git a/electrsd/src/lib.rs b/electrsd/src/lib.rs index 9936b5971..68d97f685 100644 --- a/electrsd/src/lib.rs +++ b/electrsd/src/lib.rs @@ -10,11 +10,11 @@ mod error; mod ext; mod versions; -use corepc_node::anyhow::Context; -use corepc_node::get_available_port; -use corepc_node::serde_json::Value; -use corepc_node::tempfile::TempDir; -use corepc_node::{anyhow, Node}; +use bitcoind::anyhow::Context; +use bitcoind::get_available_port; +use bitcoind::serde_json::Value; +use bitcoind::tempfile::TempDir; +use bitcoind::{anyhow, BitcoinD}; use electrum_client::raw_client::{ElectrumPlaintextStream, RawClient}; use log::{debug, error, warn}; use std::env; @@ -23,8 +23,8 @@ use std::path::PathBuf; use std::process::{Child, Command, Stdio}; use std::time::Duration; -// re-export corepc_node -pub use corepc_node; +// re-export bitcoind +pub use bitcoind; // re-export corepc_client pub use corepc_client; // re-export electrum_client because calling RawClient methods requires the ElectrumApi trait @@ -142,14 +142,14 @@ impl DataDir { impl ElectrsD { /// Create a new electrs process connected with the given bitcoind and default args. - pub fn new>(exe: S, bitcoind: &Node) -> anyhow::Result { + pub fn new>(exe: S, bitcoind: &BitcoinD) -> anyhow::Result { ElectrsD::with_conf(exe, bitcoind, &Conf::default()) } /// Create a new electrs process using given [Conf] connected with the given bitcoind pub fn with_conf>( exe: S, - bitcoind: &Node, + bitcoind: &BitcoinD, conf: &Conf, ) -> anyhow::Result { let response = bitcoind.client.call::("getblockchaininfo", &[])?; @@ -422,7 +422,7 @@ pub fn exe_path() -> anyhow::Result { mod test { use crate::exe_path; use crate::ElectrsD; - use corepc_node::P2P; + use bitcoind::P2P; use electrum_client::ElectrumApi; use log::{debug, log_enabled, Level}; use std::env; @@ -473,16 +473,16 @@ mod test { assert!(electrsd.client.ping().is_err()); } - pub(crate) fn setup_nodes() -> (String, corepc_node::Node, ElectrsD) { + pub(crate) fn setup_nodes() -> (String, bitcoind::BitcoinD, ElectrsD) { let (bitcoind_exe, electrs_exe) = init(); debug!("bitcoind: {}", &bitcoind_exe); debug!("electrs: {}", &electrs_exe); - let mut conf = corepc_node::Conf::default(); + let mut conf = bitcoind::Conf::default(); conf.view_stdout = log_enabled!(Level::Debug); if !cfg!(feature = "electrs_0_8_10") && !cfg!(feature = "esplora_a33e97e1") { conf.p2p = P2P::Yes; } - let bitcoind = corepc_node::Node::with_conf(&bitcoind_exe, &conf).unwrap(); + let bitcoind = bitcoind::BitcoinD::with_conf(&bitcoind_exe, &conf).unwrap(); let electrs_conf = crate::Conf { view_stderr: log_enabled!(Level::Debug), ..Default::default() @@ -493,7 +493,7 @@ mod test { fn init() -> (String, String) { let _ = env_logger::try_init(); - let bitcoind_exe_path = corepc_node::exe_path().unwrap(); + let bitcoind_exe_path = bitcoind::exe_path().unwrap(); let electrs_exe_path = exe_path().unwrap(); (bitcoind_exe_path, electrs_exe_path) } diff --git a/integration_test/Cargo.toml b/integration_test/Cargo.toml index 4db7386a8..2c9aa653d 100644 --- a/integration_test/Cargo.toml +++ b/integration_test/Cargo.toml @@ -11,33 +11,33 @@ edition = "2021" # - `cargo test --all-features` does not work - select a single version. # - `cargo test --no-default-features` skips all tests. [features] -download = ["node/download"] +download = ["bitcoind/download"] latest = ["30_2"] -# Enable the same feature in `node` and the version feature here. +# Enable the same feature in `bitcoind` and the version feature here. # All minor releases of the latest four versions. -30_2 = ["v30_and_below", "node/30_2"] +30_2 = ["v30_and_below", "bitcoind/30_2"] # Skip v30.1 due to wallet migration bug. -30_0 = ["v30_and_below", "node/30_0"] -29_0 = ["v29_and_below", "node/29_0"] -28_2 = ["v28_and_below", "node/28_2"] -28_1 = ["v28_and_below", "node/28_1"] -28_0 = ["v28_and_below", "node/28_0"] -27_2 = ["v27_and_below", "node/27_2"] -27_1 = ["v27_and_below", "node/27_1"] -27_0 = ["v27_and_below", "node/27_0"] +30_0 = ["v30_and_below", "bitcoind/30_0"] +29_0 = ["v29_and_below", "bitcoind/29_0"] +28_2 = ["v28_and_below", "bitcoind/28_2"] +28_1 = ["v28_and_below", "bitcoind/28_1"] +28_0 = ["v28_and_below", "bitcoind/28_0"] +27_2 = ["v27_and_below", "bitcoind/27_2"] +27_1 = ["v27_and_below", "bitcoind/27_1"] +27_0 = ["v27_and_below", "bitcoind/27_0"] # Only the latest minor version for older versions. -26_2 = ["v26_and_below", "node/26_2"] -25_2 = ["v25_and_below", "node/25_2"] -24_2 = ["v24_and_below", "node/24_2"] -23_2 = ["v23_and_below", "node/23_2"] -22_1 = ["v22_and_below", "node/22_1"] -0_21_2 = ["v21_and_below", "node/0_21_2"] -0_20_2 = ["v20_and_below", "node/0_20_2"] -0_19_1 = ["v19_and_below", "node/0_19_1"] -0_18_1 = ["v18_and_below", "node/0_18_1"] -0_17_2 = ["v17", "node/0_17_2"] +26_2 = ["v26_and_below", "bitcoind/26_2"] +25_2 = ["v25_and_below", "bitcoind/25_2"] +24_2 = ["v24_and_below", "bitcoind/24_2"] +23_2 = ["v23_and_below", "bitcoind/23_2"] +22_1 = ["v22_and_below", "bitcoind/22_1"] +0_21_2 = ["v21_and_below", "bitcoind/0_21_2"] +0_20_2 = ["v20_and_below", "bitcoind/0_20_2"] +0_19_1 = ["v19_and_below", "bitcoind/0_19_1"] +0_18_1 = ["v18_and_below", "bitcoind/0_18_1"] +0_17_2 = ["v17", "bitcoind/0_17_2"] # These features are just for internal use (feature gating). # Each major version is tested with the same client. @@ -63,7 +63,7 @@ TODO = [] # This is a dirty hack while writing the tests. [dependencies] bitcoin = { version = "0.32.0", default-features = false, features = ["std", "serde"] } env_logger = "0.9.0" -node = { package = "corepc-node", version = "0.12.0", path = "../node", default-features = false } +bitcoind = { package = "bitcoind", version = "0.37.0", path = "../bitcoind", default-features = false } rand = "0.8.5" # Just so we can enable the feature. types = { package = "corepc-types", version = "0.12.0", path = "../types", features = ["serde-deny-unknown-fields"] } @@ -77,8 +77,8 @@ path = "../client" [patch.crates-io.jsonrpc] path = "../jsonrpc" -[patch.crates-io.corepc-node] -path = "../node" +[patch.crates-io.bitcoind] +path = "../bitcoind" [patch.crates-io.corepc-types] path = "../types" diff --git a/integration_test/src/lib.rs b/integration_test/src/lib.rs index 63f4da29a..22d733b60 100644 --- a/integration_test/src/lib.rs +++ b/integration_test/src/lib.rs @@ -5,12 +5,12 @@ use std::path::PathBuf; use bitcoin::bip32::{Fingerprint, Xpriv, Xpub}; use bitcoin::secp256k1::{Secp256k1, XOnlyPublicKey}; use bitcoin::Network; -use node::{Conf, P2P}; +use bitcoind::{Conf, P2P}; use rand::distributions::Alphanumeric; use rand::Rng; #[rustfmt::skip] // Keep public re-exports separate. -pub use node::Node; // Re-export this to make test imports more terse. +pub use bitcoind::BitcoinD; // Re-export this to make test imports more terse. /// Initialize a logger (configure with `RUST_LOG=trace cargo test`). #[allow(dead_code)] // Not all tests use this function. @@ -27,9 +27,9 @@ pub enum Wallet { None, } -pub trait NodeExt { +pub trait BitcoinDExt { /// Returns a handle to a `bitcoind` instance after leading wallet if present. - fn with_wallet(wallet: Wallet, args: &[&str]) -> Node; + fn with_wallet(wallet: Wallet, args: &[&str]) -> BitcoinD; /// Generates 101 blocks to an address controlled by the loaded wallet. fn fund_wallet(&self); @@ -57,11 +57,11 @@ pub trait NodeExt { fn peers_connected(&self) -> usize; } -impl NodeExt for Node { - fn with_wallet(wallet: Wallet, args: &[&str]) -> Node { - let exe = node::exe_path().expect("failed to get bitcoind executable"); +impl BitcoinDExt for BitcoinD { + fn with_wallet(wallet: Wallet, args: &[&str]) -> BitcoinD { + let exe = bitcoind::exe_path().expect("failed to get bitcoind executable"); - let mut conf = node::Conf::default(); + let mut conf = bitcoind::Conf::default(); match wallet { Wallet::Default => {} // conf.wallet = Some("default") Wallet::Load(w) => conf.wallet = Some(w.to_owned()), @@ -72,7 +72,7 @@ impl NodeExt for Node { conf.args.push(arg); } - Node::with_conf(exe, &conf).expect("failed to create node") + BitcoinD::with_conf(exe, &conf).expect("failed to create node") } fn fund_wallet(&self) { @@ -126,27 +126,27 @@ pub fn random_tmp_file() -> PathBuf { } /// Creates a Bitcoin network with three connected nodes. -pub fn three_node_network() -> (Node, Node, Node) { - let exe = node::exe_path().expect("failed to get bitcoind executable"); +pub fn three_node_network() -> (BitcoinD, BitcoinD, BitcoinD) { + let exe = bitcoind::exe_path().expect("failed to get bitcoind executable"); - // Create Node 1 and listen for p2p connections. + // Create BitcoinD 1 and listen for p2p connections. let mut conf_node1 = Conf::default(); conf_node1.p2p = P2P::Yes; - let node1 = Node::with_conf(&exe, &conf_node1).unwrap(); + let node1 = BitcoinD::with_conf(&exe, &conf_node1).unwrap(); assert_eq!(node1.peers_connected(), 0); - // Create Node 2 connected Node 1. + // Create BitcoinD 2 connected BitcoinD 1. let mut conf_node2 = Conf::default(); conf_node2.p2p = node1.p2p_connect(true).unwrap(); - let node2 = Node::with_conf(&exe, &conf_node2).unwrap(); + let node2 = BitcoinD::with_conf(&exe, &conf_node2).unwrap(); assert_eq!(node2.peers_connected(), 1); // For some reason using only two nodes still errors. - // Create Node 3 connected Node 2. + // Create BitcoinD 3 connected BitcoinD 2. let mut conf_node3 = Conf::default(); conf_node3.p2p = node2.p2p_connect(true).unwrap(); - let node3 = Node::with_conf(&exe, &conf_node3).unwrap(); + let node3 = BitcoinD::with_conf(&exe, &conf_node3).unwrap(); assert!(node3.peers_connected() >= 1); // FIXME: Why not 2? (node1, node2, node3) diff --git a/integration_test/tests/blockchain.rs b/integration_test/tests/blockchain.rs index 92f57ad93..b66f55129 100644 --- a/integration_test/tests/blockchain.rs +++ b/integration_test/tests/blockchain.rs @@ -6,14 +6,14 @@ use bitcoin::consensus::encode; use bitcoin::hex; -use integration_test::{Node, NodeExt as _, Wallet}; -use node::vtype::*; // All the version specific types. -use node::{mtype, Input, Output}; +use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; +use bitcoind::vtype::*; // All the version specific types. +use bitcoind::{mtype, Input, Output}; #[test] #[cfg(not(feature = "v25_and_below"))] fn blockchain__dump_tx_out_set__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let (_address, _tx) = node.create_mined_transaction(); @@ -59,18 +59,18 @@ fn blockchain__load_tx_out_set__modelled() { let coinbase_descriptor = "pk(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)"; - let exe = node::exe_path().expect("failed to get bitcoind executable"); - let mut conf_a = node::Conf::default(); - conf_a.p2p = node::P2P::Yes; - let node_a = Node::with_conf(&exe, &conf_a).expect("failed to create miner node"); + let exe = bitcoind::exe_path().expect("failed to get bitcoind executable"); + let mut conf_a = bitcoind::Conf::default(); + conf_a.p2p = bitcoind::P2P::Yes; + let node_a = BitcoinD::with_conf(&exe, &conf_a).expect("failed to create miner node"); // TestChain100Setup mocktime matched to the exact const MOCK_TIME_START: u64 = 1598887952; for i in 0..snapshot_height { let mock_time = MOCK_TIME_START + i; - let _: node::serde_json::Value = node_a + let _: bitcoind::serde_json::Value = node_a .client - .call("setmocktime", &[node::serde_json::json!(mock_time)]) + .call("setmocktime", &[bitcoind::serde_json::json!(mock_time)]) .expect("setmocktime"); node_a.client.generate_to_descriptor(1, coinbase_descriptor).expect("generatetodescriptor"); } @@ -99,10 +99,10 @@ fn blockchain__load_tx_out_set__modelled() { let _: DumpTxOutSet = node_a.client.dump_tx_out_set(dump_path, "latest").expect("dumptxoutset"); } - let mut conf_b = node::Conf::default(); + let mut conf_b = bitcoind::Conf::default(); conf_b.wallet = None; - conf_b.p2p = node::P2P::No; - let node_b = Node::with_conf(&exe, &conf_b).expect("failed to create loader node"); + conf_b.p2p = bitcoind::P2P::No; + let node_b = BitcoinD::with_conf(&exe, &conf_b).expect("failed to create loader node"); for h in 1..=snapshot_height { let bh = node_a @@ -132,7 +132,7 @@ fn blockchain__load_tx_out_set__modelled() { #[test] fn blockchain__get_best_block_hash__modelled() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let json: GetBestBlockHash = node.client.get_best_block_hash().expect("getbestblockhash"); let model: Result = json.into_model(); @@ -141,7 +141,7 @@ fn blockchain__get_best_block_hash__modelled() { #[test] fn blockchain__get_block__modelled() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let block_hash = node.client.best_block_hash().expect("best_block_hash failed"); let json: GetBlockVerboseZero = @@ -156,7 +156,7 @@ fn blockchain__get_block__modelled() { #[cfg(not(feature = "v28_and_below"))] { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let (_address, mined_tx) = node.create_mined_transaction(); let block_hash = node.client.best_block_hash().expect("best_block_hash failed"); @@ -206,7 +206,7 @@ fn blockchain__get_block__modelled() { #[test] fn blockchain__get_blockchain_info__modelled() { - let node = Node::with_wallet(Wallet::None, &["-prune=10000"]); + let node = BitcoinD::with_wallet(Wallet::None, &["-prune=10000"]); let json: GetBlockchainInfo = node.client.get_blockchain_info().expect("rpc"); let model: Result = json.into_model(); @@ -215,7 +215,7 @@ fn blockchain__get_blockchain_info__modelled() { #[test] fn blockchain__get_block_count__modelled() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let json: GetBlockCount = node.client.get_block_count().unwrap(); let _: mtype::GetBlockCount = json.into_model(); @@ -224,7 +224,7 @@ fn blockchain__get_block_count__modelled() { #[test] #[cfg(not(feature = "v18_and_below"))] fn blockchain__get_block_filter__modelled() { - let node = Node::with_wallet(Wallet::Default, &["-blockfilterindex"]); + let node = BitcoinD::with_wallet(Wallet::Default, &["-blockfilterindex"]); node.mine_a_block(); let hash = node.client.best_block_hash().expect("best_block_hash failed"); @@ -266,7 +266,7 @@ fn blockchain__get_block_from_peer() { #[test] fn blockchain__get_block_hash__modelled() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let json: GetBlockHash = node.client.get_block_hash(0).expect("getblockhash"); let model: Result = json.into_model(); @@ -275,7 +275,7 @@ fn blockchain__get_block_hash__modelled() { #[test] fn blockchain__get_block_header__modelled() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let block_hash = node.client.best_block_hash().expect("best_block_hash failed"); // verbose = false @@ -295,9 +295,9 @@ fn blockchain__get_block_stats__modelled() { // Version 17 and 18 cannot call `getblockstats` if `-txindex` is not enabled. // newer versions do not. let node = if cfg!(feature = "v18_and_below") { - Node::with_wallet(Wallet::Default, &["-txindex"]) + BitcoinD::with_wallet(Wallet::Default, &["-txindex"]) } else { - Node::with_wallet(Wallet::Default, &[]) + BitcoinD::with_wallet(Wallet::Default, &[]) }; node.fund_wallet(); @@ -306,7 +306,7 @@ fn blockchain__get_block_stats__modelled() { get_block_stats_with_stats(&node); } -fn get_block_stats_by_height(node: &Node) { +fn get_block_stats_by_height(node: &BitcoinD) { let json: GetBlockStats = node.client.get_block_stats_by_height(101, None).expect("getblockstats"); @@ -317,7 +317,7 @@ fn get_block_stats_by_height(node: &Node) { assert!(model.block_hash.is_some()); } -fn get_block_stats_by_block_hash(node: &Node) { +fn get_block_stats_by_block_hash(node: &BitcoinD) { let block_hash = node.client.best_block_hash().expect("best_block_hash failed"); let json: GetBlockStats = node.client.get_block_stats_by_block_hash(&block_hash, None).expect("getblockstats"); @@ -328,7 +328,7 @@ fn get_block_stats_by_block_hash(node: &Node) { assert!(model.height.is_some()); } -fn get_block_stats_with_stats(node: &Node) { +fn get_block_stats_with_stats(node: &BitcoinD) { let json: GetBlockStats = node .client .get_block_stats_by_height(101, Some(&["minfeerate", "avgfeerate"])) @@ -345,7 +345,7 @@ fn get_block_stats_with_stats(node: &Node) { #[test] #[cfg(not(feature = "v25_and_below"))] fn blockchain__get_chain_states__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let (_address, _tx) = node.create_mined_transaction(); @@ -358,7 +358,7 @@ fn blockchain__get_chain_states__modelled() { #[test] fn blockchain__get_chain_tips__modelled() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let json: GetChainTips = node.client.get_chain_tips().expect("getchaintips"); let model: Result = json.into_model(); @@ -367,7 +367,7 @@ fn blockchain__get_chain_tips__modelled() { #[test] fn blockchain__get_chain_tx_stats__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let (_address, _tx) = node.create_mined_transaction(); @@ -381,7 +381,7 @@ fn blockchain__get_chain_tx_stats__modelled() { #[test] #[cfg(not(feature = "v22_and_below"))] fn blockchain__get_deployment_info__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); node.mine_a_block(); node.mine_a_block(); @@ -411,7 +411,7 @@ fn blockchain__get_deployment_info__modelled() { #[test] #[cfg(not(feature = "v28_and_below"))] fn blockchain__get_descriptor_activity__modelled() { - let node = Node::with_wallet(Wallet::None, &["-coinstatsindex=1", "-txindex=1"]); + let node = BitcoinD::with_wallet(Wallet::None, &["-coinstatsindex=1", "-txindex=1"]); // In Core v30, `getdescriptoractivity` requires `blockhashes` and `scanobjects` arguments. // Older versions accepted omitting them. @@ -438,7 +438,7 @@ fn blockchain__get_descriptor_activity__modelled() { #[test] fn blockchain__get_difficulty__modelled() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let json: GetDifficulty = node.client.get_difficulty().expect("getdifficulty"); let _: mtype::GetDifficulty = json.into_model(); @@ -446,7 +446,7 @@ fn blockchain__get_difficulty__modelled() { #[test] fn blockchain__get_mempool_ancestors__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let (_address, parent_txid) = node.create_mempool_transaction(); let child_txid = create_child_spending_parent(&node, parent_txid); @@ -461,7 +461,7 @@ fn blockchain__get_mempool_ancestors__modelled() { #[test] fn blockchain__get_mempool_ancestors_verbose__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let (_address, parent_txid) = node.create_mempool_transaction(); let child_txid = create_child_spending_parent(&node, parent_txid); @@ -476,7 +476,7 @@ fn blockchain__get_mempool_ancestors_verbose__modelled() { #[test] fn blockchain__get_mempool_descendants__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let (_address, parent_txid) = node.create_mempool_transaction(); let child_txid = create_child_spending_parent(&node, parent_txid); @@ -491,7 +491,7 @@ fn blockchain__get_mempool_descendants__modelled() { #[test] fn blockchain__get_mempool_descendants_verbose__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let (_address, parent_txid) = node.create_mempool_transaction(); let child_txid = create_child_spending_parent(&node, parent_txid); @@ -509,7 +509,7 @@ fn blockchain__get_mempool_descendants_verbose__modelled() { #[test] fn blockchain__get_mempool_entry__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let (_address, txid) = node.create_mempool_transaction(); @@ -520,7 +520,7 @@ fn blockchain__get_mempool_entry__modelled() { #[test] fn blockchain__get_mempool_info__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let (_address, _txid) = node.create_mempool_transaction(); @@ -534,7 +534,7 @@ fn blockchain__get_mempool_info__modelled() { #[test] fn blockchain__get_raw_mempool__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let (_address, _txid) = node.create_mempool_transaction(); @@ -567,7 +567,7 @@ fn blockchain__get_raw_mempool__modelled() { #[test] fn blockchain__get_tx_out__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let (_address, tx) = node.create_mined_transaction(); let txid = tx.compute_txid(); @@ -580,7 +580,7 @@ fn blockchain__get_tx_out__modelled() { #[test] fn blockchain__get_tx_out_proof() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let (_address, tx) = node.create_mined_transaction(); let txid = tx.compute_txid(); @@ -590,7 +590,7 @@ fn blockchain__get_tx_out_proof() { #[test] fn blockchain__get_tx_out_set_info__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let (_address, _tx) = node.create_mined_transaction(); @@ -602,7 +602,7 @@ fn blockchain__get_tx_out_set_info__modelled() { #[test] #[cfg(not(feature = "v23_and_below"))] fn blockchain__get_tx_spending_prevout__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let (_address1, txid_1) = node.create_mempool_transaction(); @@ -626,7 +626,7 @@ fn blockchain__get_tx_spending_prevout__modelled() { #[test] #[cfg(not(feature = "v25_and_below"))] fn blockchain__import_mempool() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let (_address, _tx) = node.create_mined_transaction(); @@ -637,7 +637,7 @@ fn blockchain__import_mempool() { #[test] fn blockchain__precious_block() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.mine_a_block(); let hash = node.client.best_block_hash().expect("best_block_hash failed"); node.mine_a_block(); @@ -649,7 +649,7 @@ fn blockchain__precious_block() { fn blockchain__prune_blockchain() { const NBLOCKS: usize = 1; - let node = Node::with_wallet(Wallet::Default, &["-prune=550"]); + let node = BitcoinD::with_wallet(Wallet::Default, &["-prune=550"]); let address = node.client.new_address().expect("Failed to get new address"); let gen_result = node @@ -669,7 +669,7 @@ fn blockchain__prune_blockchain() { #[test] fn blockchain__savemempool() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let (_addr, _txid) = node.create_mempool_transaction(); @@ -687,7 +687,7 @@ fn blockchain__savemempool() { #[test] #[cfg(not(feature = "v24_and_below"))] fn blockchain__scan_blocks_modelled() { - let node = Node::with_wallet(Wallet::None, &["-blockfilterindex=1"]); + let node = BitcoinD::with_wallet(Wallet::None, &["-blockfilterindex=1"]); // Arbitrary scan descriptor let scan_desc = "pkh(022afc20bf379bc96a2f4e9e63ffceb8652b2b6a097f63fbee6ecec2a49a48010e)"; @@ -713,9 +713,9 @@ fn blockchain__scan_blocks_modelled() { fn blockchain__scan_tx_out_set_modelled() { let node = match () { #[cfg(feature = "v21_and_below")] - () => Node::with_wallet(Wallet::None, &[]), + () => BitcoinD::with_wallet(Wallet::None, &[]), #[cfg(not(feature = "v21_and_below"))] - () => Node::with_wallet(Wallet::None, &["-coinstatsindex=1"]), + () => BitcoinD::with_wallet(Wallet::None, &["-coinstatsindex=1"]), }; let dummy_pubkey_hex = "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"; @@ -734,14 +734,14 @@ fn blockchain__scan_tx_out_set_modelled() { #[test] fn blockchain__verify_chain() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let _: Result = node.client.verify_chain(); } #[test] fn blockchain__verify_tx_out_proof__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let (_address, tx) = node.create_mined_transaction(); @@ -759,7 +759,7 @@ fn blockchain__verify_tx_out_proof__modelled() { #[test] fn blockchain__wait_for_block__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let (_address, _tx) = node.create_mined_transaction(); let block_hash = node.client.best_block_hash().expect("bestblockhash"); @@ -772,7 +772,7 @@ fn blockchain__wait_for_block__modelled() { #[test] fn blockchain__wait_for_block_height__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let (_address, _tx) = node.create_mined_transaction(); let height = node.client.get_block_count().expect("getblockcount").0; @@ -814,7 +814,7 @@ fn blockchain__wait_for_new_block__modelled() { /// Create and broadcast a child transaction spending vout 0 of the given parent mempool txid. /// Returns the child's txid. -fn create_child_spending_parent(node: &Node, parent_txid: bitcoin::Txid) -> bitcoin::Txid { +fn create_child_spending_parent(node: &BitcoinD, parent_txid: bitcoin::Txid) -> bitcoin::Txid { let inputs = vec![Input { txid: parent_txid, vout: 0, sequence: None }]; let spend_address = node.client.new_address().expect("newaddress"); let outputs = vec![Output::new(spend_address, bitcoin::Amount::from_sat(100_000))]; diff --git a/integration_test/tests/control.rs b/integration_test/tests/control.rs index 4020d1510..a45beea36 100644 --- a/integration_test/tests/control.rs +++ b/integration_test/tests/control.rs @@ -4,42 +4,42 @@ #![allow(non_snake_case)] // Test names intentionally use double underscore. -use integration_test::{Node, NodeExt as _, Wallet}; -use node::vtype::*; // All the version specific types. +use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; +use bitcoind::vtype::*; // All the version specific types. #[test] fn control__get_memory_info() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let _: GetMemoryInfoStats = node.client.get_memory_info().unwrap(); } #[test] #[cfg(not(feature = "v17"))] fn control__get_rpc_info() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let _ = node.client.get_rpc_info().unwrap(); } #[test] fn control__help() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let _ = node.client.help().unwrap(); } #[test] fn control__logging() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let _: Logging = node.client.logging().unwrap(); } #[test] fn control__stop() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let _ = node.client.stop().unwrap(); } #[test] fn control__uptime() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let _ = node.client.uptime().unwrap(); } diff --git a/integration_test/tests/generating.rs b/integration_test/tests/generating.rs index 9c6989879..788dd6dc7 100644 --- a/integration_test/tests/generating.rs +++ b/integration_test/tests/generating.rs @@ -5,14 +5,14 @@ #![allow(non_snake_case)] // Test names intentionally use double underscore. use bitcoin::hex; -use integration_test::{Node, NodeExt as _, Wallet}; -use node::mtype; -use node::vtype::*; // All the version specific types. +use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; +use bitcoind::mtype; +use bitcoind::vtype::*; // All the version specific types. #[test] #[cfg(not(feature = "v20_and_below"))] fn generating__generate_block__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let mining_addr = node.client.new_address().expect("failed to get new address"); let dest_addr = node.client.new_address().expect("failed to get new address"); @@ -53,7 +53,7 @@ fn generating__generate_block__modelled() { #[cfg(feature = "v17")] fn generating__generate__modelled() { const NBLOCKS: usize = 10; - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); let json: Generate = node.client.generate(NBLOCKS).expect("generate"); @@ -65,7 +65,7 @@ fn generating__generate__modelled() { fn generating__generate_to_address__modelled() { const NBLOCKS: usize = 1; - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); let address = node.client.new_address().expect("failed to get new address"); let json: GenerateToAddress = @@ -80,7 +80,7 @@ fn generating__generate_to_address__modelled() { fn generating__generate_to_descriptor__modelled() { const NBLOCKS: usize = 1; - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); let address = node.client.new_address().expect("failed to get new address"); let descriptor = format!("addr({})", address); @@ -95,7 +95,7 @@ fn generating__generate_to_descriptor__modelled() { fn generating__invalidate_block() { const NBLOCKS: usize = 1; - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); let address = node.client.new_address().expect("failed to get new address"); let old_best_block = diff --git a/integration_test/tests/hidden.rs b/integration_test/tests/hidden.rs index c7bb6caac..ad21a7315 100644 --- a/integration_test/tests/hidden.rs +++ b/integration_test/tests/hidden.rs @@ -16,11 +16,11 @@ use bitcoin::{ absolute, consensus, transaction, Amount, OutPoint, ScriptBuf, Sequence, Transaction, TxIn, TxOut, Txid, Witness, }; -use integration_test::{Node, NodeExt as _, Wallet}; -use node::mtype; -use node::vtype::*; // All the version specific types. +use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; +use bitcoind::mtype; +use bitcoind::vtype::*; // All the version specific types. #[cfg(not(feature = "v21_and_below"))] -use node::P2P; +use bitcoind::P2P; #[test] #[cfg(not(feature = "v21_and_below"))] @@ -54,7 +54,7 @@ fn hidden__add_connection() { #[test] fn hidden__estimate_raw_fee__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); @@ -200,7 +200,7 @@ fn hidden__get_orphan_txs__modelled() { #[test] fn hidden__sync_with_validation_interface_queue() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); // Create activity that causes validation callbacks. @@ -214,7 +214,7 @@ fn hidden__sync_with_validation_interface_queue() { #[test] fn hidden__reconsider_block() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); node.mine_a_block(); @@ -258,7 +258,7 @@ fn hidden__reconsider_block() { #[test] #[cfg(not(feature = "v19_and_below"))] fn hidden__mock_scheduler() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); let _: () = node.client.mock_scheduler(1).expect("mockscheduler"); } @@ -266,7 +266,7 @@ fn hidden__mock_scheduler() { #[test] #[cfg(not(feature = "v25_and_below"))] fn hidden__get_raw_addrman() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); // Add a peer address so the address manager has something. let peer_address = "1.2.3.4"; diff --git a/integration_test/tests/mining.rs b/integration_test/tests/mining.rs index bcc3bf66f..238dc175b 100644 --- a/integration_test/tests/mining.rs +++ b/integration_test/tests/mining.rs @@ -5,9 +5,9 @@ #![allow(non_snake_case)] // Test names intentionally use double underscore. use bitcoin::SignedAmount; -use integration_test::{Node, NodeExt as _, Wallet}; -use node::vtype::*; -use node::{mtype, TemplateRequest, TemplateRules}; // All the version specific types. +use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; +use bitcoind::vtype::*; +use bitcoind::{mtype, TemplateRequest, TemplateRules}; // All the version specific types. #[test] fn mining__get_block_template__modelled() { @@ -38,7 +38,7 @@ fn mining__get_block_template__modelled() { #[test] fn mining__get_mining_info() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let json: GetMiningInfo = node.client.get_mining_info().expect("rpc"); @@ -58,7 +58,7 @@ fn mining__get_mining_info() { #[test] fn mining__get_network_hash_ps() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let _ = node.client.get_network_hash_ps().expect("rpc"); } @@ -66,7 +66,7 @@ fn mining__get_network_hash_ps() { #[test] #[cfg(not(feature = "v25_and_below"))] fn mining__get_prioritised_transactions() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let _ = node.client.get_prioritised_transactions().expect("getprioritisedtransactions"); @@ -74,7 +74,7 @@ fn mining__get_prioritised_transactions() { #[test] fn mining__prioritise_transaction() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let (_addr, txid) = node.create_mempool_transaction(); @@ -106,7 +106,7 @@ fn mining__submit_block() { // Code copied from BDK - thanks! // FIXME: Submitting this block sometimes works and sometimes returns 'inconclusive'. #[allow(dead_code)] -fn submit_empty_block(node: &Node, bt: &mtype::GetBlockTemplate) { +fn submit_empty_block(node: &BitcoinD, bt: &mtype::GetBlockTemplate) { use bitcoin::hashes::Hash as _; use bitcoin::{ absolute, block, transaction, Amount, Block, OutPoint, ScriptBuf, ScriptHash, Sequence, @@ -161,7 +161,7 @@ fn submit_empty_block(node: &Node, bt: &mtype::GetBlockTemplate) { // FIXME: Submitting this block returns 'inconclusive'. #[allow(dead_code)] -fn mining__submit_block_with_dummy_coinbase(node: &Node, bt: &mtype::GetBlockTemplate) { +fn mining__submit_block_with_dummy_coinbase(node: &BitcoinD, bt: &mtype::GetBlockTemplate) { use bitcoin::hashes::Hash as _; use bitcoin::{ absolute, block, transaction, Amount, Block, OutPoint, ScriptBuf, Sequence, Transaction, @@ -220,7 +220,7 @@ fn mining__submit_block_with_dummy_coinbase(node: &Node, bt: &mtype::GetBlockTem #[test] #[cfg(not(feature = "v17"))] fn mining__submit_header() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); node.mine_a_block(); diff --git a/integration_test/tests/network.rs b/integration_test/tests/network.rs index 45d0649eb..da4d96e08 100644 --- a/integration_test/tests/network.rs +++ b/integration_test/tests/network.rs @@ -4,17 +4,17 @@ #![allow(non_snake_case)] // Test names intentionally use double underscore. -use integration_test::{Node, NodeExt as _, Wallet}; -use node::vtype::*; // All the version specific types. -use node::{mtype, AddNodeCommand, SetBanCommand}; +use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; +use bitcoind::vtype::*; // All the version specific types. +use bitcoind::{mtype, AddNodeCommand, SetBanCommand}; #[test] fn network__add_node() { let node = match () { #[cfg(feature = "v25_and_below")] - () => Node::with_wallet(Wallet::None, &[]), + () => BitcoinD::with_wallet(Wallet::None, &[]), #[cfg(not(feature = "v25_and_below"))] - () => Node::with_wallet(Wallet::None, &["-v2transport"]), + () => BitcoinD::with_wallet(Wallet::None, &["-v2transport"]), }; let dummy_peer = "192.0.2.1:8333"; @@ -26,7 +26,7 @@ fn network__add_node() { #[test] fn network__clear_banned() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let dummy_subnet = "192.0.2.2"; let _: () = node.client.set_ban(dummy_subnet, SetBanCommand::Add).expect("setban add"); @@ -45,14 +45,14 @@ fn network__disconnect_node() { #[test] fn network__get_added_node_info() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let _: GetAddedNodeInfo = node.client.get_added_node_info().expect("getaddednodeinfo"); } #[test] #[cfg(not(feature = "v25_and_below"))] fn network__get_addr_man_info() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let json: GetAddrManInfo = node.client.get_addr_man_info().expect("getaddrmaninfo"); assert!(!json.0.is_empty()); @@ -64,19 +64,19 @@ fn network__get_addr_man_info() { #[test] fn network__get_connection_count() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let _: GetConnectionCount = node.client.get_connection_count().expect("getconnectioncount"); } #[test] fn network__get_net_totals() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let _: GetNetTotals = node.client.get_net_totals().expect("getnettotals"); } #[test] fn network__get_network_info__modelled() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let json: GetNetworkInfo = node.client.get_network_info().expect("getnetworkinfo"); let model: Result = json.into_model(); model.unwrap(); @@ -88,7 +88,7 @@ fn network__get_network_info__modelled() { #[test] #[cfg(not(feature = "v17"))] fn network__get_node_addresses() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); #[cfg(feature = "v20_and_below")] { @@ -114,7 +114,7 @@ fn network__get_peer_info() { } fn get_peer_info_one_node_network() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let json: GetPeerInfo = node.client.get_peer_info().expect("getpeerinfo"); assert_eq!(json.0.len(), 0); } @@ -139,7 +139,7 @@ fn get_peer_info_three_node_network() { #[test] fn network__list_banned() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let dummy_subnet = "192.0.2.5/32"; node.client.set_ban(dummy_subnet, SetBanCommand::Add).expect("setban add"); @@ -153,13 +153,13 @@ fn network__list_banned() { #[test] fn network__ping() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let _: () = node.client.ping().expect("ping"); } #[test] fn network__set_ban() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let dummy_subnet = "192.0.2.3"; let _: () = node.client.set_ban(dummy_subnet, SetBanCommand::Add).expect("setban add"); @@ -168,7 +168,7 @@ fn network__set_ban() { #[test] fn network__set_network_active() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let json: SetNetworkActive = node.client.set_network_active(false).expect("setnetworkactive false"); assert!(!json.0); diff --git a/integration_test/tests/raw_transactions.rs b/integration_test/tests/raw_transactions.rs index 70332037e..6a756a97f 100644 --- a/integration_test/tests/raw_transactions.rs +++ b/integration_test/tests/raw_transactions.rs @@ -12,14 +12,14 @@ use bitcoin::opcodes::all::*; use bitcoin::{ absolute, consensus, hex, psbt, script, transaction, Amount, ScriptBuf, Transaction, TxOut, }; -use integration_test::{test_keys, Node, NodeExt as _, Wallet}; -use node::vtype::*; -use node::{mtype, Input, Output}; // All the version specific types. +use integration_test::{test_keys, BitcoinD, BitcoinDExt as _, Wallet}; +use bitcoind::vtype::*; +use bitcoind::{mtype, Input, Output}; // All the version specific types. #[test] #[cfg(not(feature = "v17"))] // analyzepsbt was added in v0.18. fn raw_transactions__analyze_psbt__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let psbt = create_a_psbt(&node); @@ -30,7 +30,7 @@ fn raw_transactions__analyze_psbt__modelled() { #[test] fn raw_transactions__combine_psbt__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let (_addr, txid) = node.create_mempool_transaction(); // A million sats. @@ -83,7 +83,7 @@ fn raw_transactions__combine_psbt__modelled() { #[test] fn raw_transactions__combine_raw_transaction__modelled() { - let node = Node::with_wallet(Wallet::Default, &["-txindex"]); + let node = BitcoinD::with_wallet(Wallet::Default, &["-txindex"]); node.fund_wallet(); let (_, txid) = node.create_mempool_transaction(); @@ -104,7 +104,7 @@ fn raw_transactions__combine_raw_transaction__modelled() { #[test] fn raw_transactions__convert_to_psbt__modelled() { - let node = Node::with_wallet(Wallet::Default, &["-txindex"]); + let node = BitcoinD::with_wallet(Wallet::Default, &["-txindex"]); node.fund_wallet(); let tx = create_a_raw_transaction(&node); @@ -116,14 +116,14 @@ fn raw_transactions__convert_to_psbt__modelled() { #[test] fn raw_transactions__create_psbt__modelled() { - let node = Node::with_wallet(Wallet::Default, &["-txindex"]); + let node = BitcoinD::with_wallet(Wallet::Default, &["-txindex"]); node.fund_wallet(); let _ = create_a_psbt(&node); } #[test] fn raw_transactions__create_raw_transaction__modelled() { - let node = Node::with_wallet(Wallet::Default, &["-txindex"]); + let node = BitcoinD::with_wallet(Wallet::Default, &["-txindex"]); node.fund_wallet(); create_sign_send(&node); } @@ -132,7 +132,7 @@ fn raw_transactions__create_raw_transaction__modelled() { // Version-specific assertions are gated below. #[test] fn raw_transactions__decode_psbt__modelled() { - let node = Node::with_wallet(Wallet::Default, &["-txindex"]); + let node = BitcoinD::with_wallet(Wallet::Default, &["-txindex"]); node.fund_wallet(); // v17: utxoupdatepsbt unavailable @@ -183,7 +183,7 @@ fn raw_transactions__decode_psbt__modelled() { #[test] fn raw_transactions__decode_raw_transaction__modelled() { - let node = Node::with_wallet(Wallet::Default, &["-txindex"]); + let node = BitcoinD::with_wallet(Wallet::Default, &["-txindex"]); node.fund_wallet(); let (_, txid) = node.create_mempool_transaction(); @@ -199,7 +199,7 @@ fn raw_transactions__decode_raw_transaction__modelled() { #[test] // FIXME: Seems the returned fields are different depending on the script. Needs more thorough testing. fn raw_transactions__decode_script__modelled() { - let node = Node::with_wallet(Wallet::Default, &["-txindex"]); + let node = BitcoinD::with_wallet(Wallet::Default, &["-txindex"]); node.fund_wallet(); let p2pkh = arbitrary_p2pkh_script(); @@ -248,7 +248,7 @@ fn arbitrary_multisig_script() -> ScriptBuf { #[test] fn raw_transactions__finalize_psbt__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); // Create a PSBT and call finalizepsbt directly without signing. @@ -264,21 +264,21 @@ fn raw_transactions__finalize_psbt__modelled() { #[test] fn raw_transactions__fund_raw_transaction__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); create_fund_sign_send(&node); } #[test] fn raw_transactions__send_raw_transaction__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); create_sign_send(&node); // Calls `sendrawtransaction`. } #[test] fn raw_transactions__get_raw_transaction__modelled() { - let node = Node::with_wallet(Wallet::Default, &["-txindex"]); + let node = BitcoinD::with_wallet(Wallet::Default, &["-txindex"]); node.fund_wallet(); // Get raw transaction using a mined transaction and verbose = false. @@ -311,7 +311,7 @@ fn raw_transactions__get_raw_transaction__modelled() { #[test] #[cfg(not(feature = "v17"))] fn raw_transactions__join_psbts__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let psbt1 = create_a_psbt(&node); @@ -327,7 +327,7 @@ fn raw_transactions__join_psbts__modelled() { #[test] fn raw_transactions__sign_raw_transaction__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); create_sign_send(&node); } @@ -336,7 +336,7 @@ fn raw_transactions__sign_raw_transaction__modelled() { #[test] #[cfg(feature = "v22_and_below")] // In v23 dumpprivkey no longer works. fn raw_transactions__sign_raw_transaction_with_key__modelled() { - let node = Node::with_wallet(Wallet::Default, &["-txindex"]); + let node = BitcoinD::with_wallet(Wallet::Default, &["-txindex"]); node.fund_wallet(); create_sign_with_key_send(&node) } @@ -345,7 +345,7 @@ fn raw_transactions__sign_raw_transaction_with_key__modelled() { #[test] #[cfg(all(feature = "v27_and_below", not(feature = "v26_and_below")))] fn raw_transactions__submit_package__modelled() { - let node = Node::with_wallet(Wallet::Default, &["-txindex"]); + let node = BitcoinD::with_wallet(Wallet::Default, &["-txindex"]); // Submitting the empty package should simply fail. assert!(node.client.submit_package(&[]).is_err()); @@ -371,7 +371,7 @@ fn raw_transactions__submit_package__modelled() { #[test] #[cfg(not(feature = "v27_and_below"))] fn raw_transactions__submit_package__modelled() { - let node = Node::with_wallet(Wallet::Default, &["-txindex"]); + let node = BitcoinD::with_wallet(Wallet::Default, &["-txindex"]); // Submitting the empty package should simply fail. assert!(node.client.submit_package(&[], None, None).is_err()); @@ -395,7 +395,7 @@ fn raw_transactions__submit_package__modelled() { #[test] fn raw_transactions__test_mempool_accept__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let tx = create_a_raw_transaction(&node); @@ -425,7 +425,7 @@ fn raw_transactions__test_mempool_accept__modelled() { #[test] #[cfg(not(feature = "v17"))] fn raw_transactions__utxo_update_psbt__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let psbt = create_a_psbt(&node); @@ -442,7 +442,7 @@ fn raw_transactions__utxo_update_psbt__modelled() { // - create_raw_transaction // - sign_raw_transaction_with_wallet // - send_raw_transaction -fn create_sign_send(node: &Node) { +fn create_sign_send(node: &BitcoinD) { let (_addr, _tx, txid, tx_out, vout) = create_utxo(node); // Assumes tx_out has a million sats in it. @@ -500,7 +500,7 @@ fn create_sign_send(node: &Node) { // // TODO: Work out how to get a private key without using `dumpprivkey`. #[cfg(feature = "v22_and_below")] // In v23 dumpprivkey no longer works. -fn create_sign_with_key_send(node: &Node) { +fn create_sign_with_key_send(node: &BitcoinD) { let (addr, _tx, txid, tx_out, vout) = create_utxo(node); // Assumes tx_out has a million sats in it. @@ -557,7 +557,7 @@ fn create_sign_with_key_send(node: &Node) { // - sign_raw_transaction_with_wallet (sign_raw_transaction was deprecated in v0.17). // - send_raw_transaction #[allow(clippy::inconsistent_digit_grouping)] // Sats to btc is a common use case. -fn create_fund_sign_send(node: &Node) { +fn create_fund_sign_send(node: &BitcoinD) { let (_addr, _tx, txid, _tx_out, vout) = create_utxo(node); // We need to add an input so that transaction is consensus encoded to hex correctly (because of @@ -598,7 +598,7 @@ fn create_fund_sign_send(node: &Node) { } // Creates a transaction using client to do RPC call `create_raw_transaction`. -fn create_a_raw_transaction(node: &Node) -> Transaction { +fn create_a_raw_transaction(node: &BitcoinD) -> Transaction { let (_addr, _tx, txid, tx_out, vout) = create_utxo(node); // Assumes tx_out has a million sats in it. @@ -634,7 +634,7 @@ fn create_a_raw_transaction(node: &Node) -> Transaction { // Sends a transaction, mines a block then grabs a million sat UTXO from the mined transaction. fn create_utxo( - node: &Node, + node: &BitcoinD, ) -> (bitcoin::Address, bitcoin::Transaction, bitcoin::Txid, bitcoin::TxOut, u64) { // TODO: We should probably pass this into `create_mined_transaction`. const MILLION_SATS: bitcoin::Amount = bitcoin::Amount::from_sat(1000000); @@ -668,7 +668,7 @@ fn create_utxo( } // Creates a PSBT using client to do RPC call `create_psbt`. -fn create_a_psbt(node: &Node) -> bitcoin::Psbt { +fn create_a_psbt(node: &BitcoinD) -> bitcoin::Psbt { let (_addr, _tx, txid, tx_out, vout) = create_utxo(node); // Assumes tx_out has a million sats in it. diff --git a/integration_test/tests/signer.rs b/integration_test/tests/signer.rs index ad26684fa..f6a40fb4f 100644 --- a/integration_test/tests/signer.rs +++ b/integration_test/tests/signer.rs @@ -7,9 +7,9 @@ use bitcoin::address::{NetworkUnchecked, ParseError}; use bitcoin::Address; -use integration_test::{Node, NodeExt as _, Wallet}; -use node::vtype::*; -use node::{mtype, Input, Output}; // All the version specific types. +use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; +use bitcoind::vtype::*; +use bitcoind::{mtype, Input, Output}; // All the version specific types. #[test] #[cfg(unix)] @@ -29,7 +29,7 @@ fn signer__enumerate_signers() { std::fs::set_permissions(&script_path, std::fs::Permissions::from_mode(0o755)).expect("chmod"); let signer_arg = format!("-signer={}", script_path.to_str().unwrap()); - let node = Node::with_wallet(Wallet::None, &[&signer_arg]); + let node = BitcoinD::with_wallet(Wallet::None, &[&signer_arg]); let json: EnumerateSigners = node.client.enumerate_signers().expect("enumeratesigners"); let first_tx = json.signers.first().expect("no signers found"); @@ -69,7 +69,7 @@ esac std::fs::set_permissions(&script_path, std::fs::Permissions::from_mode(0o755)).expect("chmod"); let signer_arg = format!("-signer={}", script_path.to_str().unwrap()); - let node = Node::with_wallet(Wallet::None, &[&signer_arg]); + let node = BitcoinD::with_wallet(Wallet::None, &[&signer_arg]); let _: CreateWallet = node .client diff --git a/integration_test/tests/util.rs b/integration_test/tests/util.rs index 838b79a42..d3202ef53 100644 --- a/integration_test/tests/util.rs +++ b/integration_test/tests/util.rs @@ -6,9 +6,9 @@ #![allow(unused_imports)] // Because of feature gated tests. use bitcoin::{address, amount, sign_message, PrivateKey, PublicKey}; -use integration_test::{Node, NodeExt as _, Wallet}; -use node::vtype::*; -use node::{mtype, FeeEstimateMode}; +use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; +use bitcoind::vtype::*; +use bitcoind::{mtype, FeeEstimateMode}; #[test] fn util__create_multisig__modelled() { @@ -22,7 +22,7 @@ fn util__create_multisig__modelled() { .parse::() .unwrap(); - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); let json: CreateMultisig = node.client.create_multisig(nrequired, vec![pubkey1, pubkey2]).expect("createmultisig"); let model: Result = json.into_model(); @@ -32,7 +32,7 @@ fn util__create_multisig__modelled() { #[test] #[cfg(not(feature = "v17"))] fn util__derive_addresses__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); // Use a valid, deterministic public key from the pubkey_sort test vectors and the checksum for it. let descriptor = @@ -65,7 +65,7 @@ fn util__derive_addresses__modelled() { #[test] fn util__estimate_smart_fee__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let json: EstimateSmartFee = node.client.estimate_smart_fee(6).expect("estimatesmartfee"); @@ -75,7 +75,7 @@ fn util__estimate_smart_fee__modelled() { #[test] fn util__estimate_smart_fee_with_mode__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); const MODES: [FeeEstimateMode; 3] = @@ -91,7 +91,7 @@ fn util__estimate_smart_fee_with_mode__modelled() { #[test] #[cfg(not(feature = "v17"))] fn util__get_descriptor_info() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); // Use a valid, deterministic public key from the pubkey_sort test vectors let descriptor = "pkh(02ff12471208c14bd580709cb2358d98975247d8765f92bc25eab3b2763ed605f8)"; @@ -102,7 +102,7 @@ fn util__get_descriptor_info() { #[test] #[cfg(not(feature = "v20_and_below"))] fn util__get_index_info() { - let node = Node::with_wallet(Wallet::Default, &["-txindex"]); + let node = BitcoinD::with_wallet(Wallet::Default, &["-txindex"]); let index_info: GetIndexInfo = node.client.get_index_info().expect("getindexinfo"); let txindex_info = index_info.0.get("txindex").unwrap(); @@ -114,7 +114,7 @@ fn util__get_index_info() { #[test] fn util__sign_message_with_priv_key__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let privkey = @@ -141,7 +141,7 @@ fn util__sign_message_with_priv_key__modelled() { #[test] fn util__validate_address__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let addr = node.client.new_address().expect("new_address"); diff --git a/integration_test/tests/wallet.rs b/integration_test/tests/wallet.rs index 6831c5892..ca8627d9b 100644 --- a/integration_test/tests/wallet.rs +++ b/integration_test/tests/wallet.rs @@ -15,18 +15,18 @@ use bitcoin::{ amount, hex, key, psbt, secp256k1, sign_message, Amount, CompressedPublicKey, FeeRate, Network, PrivateKey, PublicKey, }; -use integration_test::{Node, NodeExt as _, Wallet}; -use node::vtype::*; // All the version specific types. +use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; +use bitcoind::vtype::*; // All the version specific types. #[cfg(not(feature = "v20_and_below"))] -use node::ImportDescriptorsRequest; -use node::{ +use bitcoind::ImportDescriptorsRequest; +use bitcoind::{ mtype, AddressType, ImportMultiRequest, ImportMultiScriptPubKey, ImportMultiTimestamp, WalletCreateFundedPsbtInput, }; #[test] fn wallet__abandon_transaction() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); let mining_addr = node.client.new_address().expect("newaddress"); let json: GenerateToAddress = @@ -52,7 +52,7 @@ fn wallet__abandon_transaction() { #[test] fn wallet__abort_rescan() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); let json: AbortRescan = node.client.abort_rescan().expect("abortrescan"); assert!(!json.0); // No rescan running, abort should return false @@ -65,10 +65,10 @@ fn wallet__add_multisig_address__modelled() { let node = match () { #[cfg(feature = "v22_and_below")] - () => Node::with_wallet(Wallet::Default, &[]), + () => BitcoinD::with_wallet(Wallet::Default, &[]), #[cfg(not(feature = "v22_and_below"))] () => { - let node = Node::with_wallet(Wallet::None, &["-deprecatedrpc=create_bdb"]); + let node = BitcoinD::with_wallet(Wallet::None, &["-deprecatedrpc=create_bdb"]); node.client.create_legacy_wallet("wallet_name").expect("createlegacywallet"); node } @@ -90,7 +90,7 @@ fn wallet__add_multisig_address__modelled() { fn wallet__backup_wallet() { backup_and_restore_wallet() } fn backup_and_restore_wallet() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); let file_path = integration_test::random_tmp_file(); let _: () = node.client.backup_wallet(&file_path).expect("backupwallet"); @@ -101,7 +101,7 @@ fn backup_and_restore_wallet() { #[cfg(not(feature = "v22_and_below"))] { let wallet_name = "test_wallet"; - let node2 = Node::with_wallet(Wallet::None, &[]); + let node2 = BitcoinD::with_wallet(Wallet::None, &[]); let restored_wallet: RestoreWallet = node2.client.restore_wallet(wallet_name, &file_path).expect("restorewallet"); assert_eq!(restored_wallet.name, wallet_name); @@ -112,7 +112,7 @@ fn backup_and_restore_wallet() { #[test] fn wallet__bump_fee__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); let address = node.client.new_address().expect("failed to create new address"); let _ = node.client.generate_to_address(101, &address).expect("generatetoaddress"); @@ -131,13 +131,13 @@ fn wallet__bump_fee__modelled() { #[test] fn wallet__create_wallet__modelled() { // Implicitly tests `createwallet` because we create the default wallet. - let _ = Node::with_wallet(Wallet::Default, &[]); + let _ = BitcoinD::with_wallet(Wallet::Default, &[]); } #[test] #[cfg(not(feature = "v27_and_below"))] fn wallet__create_wallet_descriptor() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); // BIP32 HD xprv/xpub for the creation of a descriptor with a private key that is in the wallet. let secp = secp256k1::Secp256k1::new(); @@ -175,7 +175,7 @@ fn wallet__dump_priv_key__modelled() { // support dumping private keys. Legacy wallets are supported upto v25 it seems. #[cfg(all(feature = "v25_and_below", not(feature = "v22_and_below")))] { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); node.client.create_legacy_wallet("legacy_wallet").expect("legacy create_wallet"); let address = node @@ -192,7 +192,7 @@ fn wallet__dump_priv_key__modelled() { #[cfg(feature = "v22_and_below")] { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); let address = node.client.new_address().expect("failed to get new address"); let json: DumpPrivKey = node.client.dump_priv_key(&address).expect("dumpprivkey"); @@ -208,7 +208,7 @@ fn wallet__dump_wallet() { // support dumping private keys. Legacy wallets are supported upto v25 it seems. #[cfg(all(feature = "v25_and_below", not(feature = "v22_and_below")))] { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); node.client.create_legacy_wallet("legacy_wallet").expect("legacy create_wallet"); let out = integration_test::random_tmp_file(); @@ -218,7 +218,7 @@ fn wallet__dump_wallet() { #[cfg(feature = "v22_and_below")] { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); let out = integration_test::random_tmp_file(); let _: DumpWallet = node.client.dump_wallet(&out).expect("dumpwallet"); @@ -227,14 +227,14 @@ fn wallet__dump_wallet() { #[test] fn wallet__encrypt_wallet() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); let _: EncryptWallet = node.client.encrypt_wallet("test-passphrase").expect("encryptwallet"); } #[test] fn wallet__get_addresses_by_label__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); let label = "some-label"; let addr = node.client.new_address_with_label(label).expect("failed to get new address"); @@ -250,7 +250,7 @@ fn wallet__get_addresses_by_label__modelled() { #[test] fn wallet__get_address_info__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); // Test an address with a label. let label_name = "test-label"; @@ -283,7 +283,7 @@ fn wallet__get_address_info__modelled() { #[test] fn wallet__get_balance__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); let json: GetBalance = node.client.get_balance().expect("getbalance"); let model: Result = json.into_model(); @@ -299,7 +299,7 @@ fn wallet__get_balance__modelled() { #[test] #[cfg(not(feature = "v18_and_below"))] fn wallet__get_balances() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let json: GetBalances = node.client.get_balances().expect("getbalances"); @@ -310,7 +310,7 @@ fn wallet__get_balances() { #[test] #[cfg(not(feature = "v27_and_below"))] fn wallet__get_hd_keys__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); let json: GetHdKeys = node.client.get_hd_keys().expect("gethdkeys"); let model: Result = json.into_model(); @@ -322,7 +322,7 @@ fn wallet__get_hd_keys__modelled() { #[test] fn wallet__get_new_address__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); // Implicitly tests `getnewaddress`. let _ = node.client.new_address().unwrap(); @@ -335,7 +335,7 @@ fn wallet__get_new_address__modelled() { #[test] fn wallet__get_raw_change_address__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); let json: GetRawChangeAddress = node.client.get_raw_change_address().expect("getrawchangeaddress"); let model: Result = json.into_model(); @@ -346,7 +346,7 @@ fn wallet__get_raw_change_address__modelled() { fn wallet__get_received_by_address__modelled() { let amount = Amount::from_sat(10_000); - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let address = node.client.new_address().expect("failed to create new address"); @@ -365,7 +365,7 @@ fn wallet__get_received_by_address__modelled() { #[test] #[cfg(not(feature = "v17"))] fn wallet__get_received_by_label__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let label = "test-label"; @@ -384,7 +384,7 @@ fn wallet__get_received_by_label__modelled() { #[test] fn wallet__get_transaction__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let address = node.client.new_address().expect("failed to create new address"); @@ -403,7 +403,7 @@ fn wallet__get_transaction__modelled() { #[test] #[cfg(feature = "v29_and_below")] fn wallet__get_unconfirmed_balance__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); let json: GetUnconfirmedBalance = node.client.get_unconfirmed_balance().expect("getunconfirmedbalance"); let model: Result = json.into_model(); @@ -412,7 +412,7 @@ fn wallet__get_unconfirmed_balance__modelled() { #[test] fn wallet__get_wallet_info__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.mine_a_block(); let json: GetWalletInfo = node.client.get_wallet_info().expect("getwalletinfo"); @@ -441,10 +441,10 @@ fn wallet__get_wallet_info__modelled() { fn wallet__import_address() { let node = match () { #[cfg(feature = "v22_and_below")] - () => Node::with_wallet(Wallet::Default, &[]), + () => BitcoinD::with_wallet(Wallet::Default, &[]), #[cfg(not(feature = "v22_and_below"))] () => { - let node = Node::with_wallet(Wallet::None, &["-deprecatedrpc=create_bdb"]); + let node = BitcoinD::with_wallet(Wallet::None, &["-deprecatedrpc=create_bdb"]); node.client.create_legacy_wallet("wallet_name").expect("createlegacywallet"); node } @@ -464,7 +464,7 @@ fn wallet__import_address() { #[test] #[cfg(not(feature = "v20_and_below"))] fn wallet__import_descriptors() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let wallet_name = "desc_wallet"; #[cfg(feature = "v22_and_below")] @@ -508,7 +508,7 @@ fn wallet__import_descriptors() { #[test] fn wallet__import_pruned_funds() { - let node = Node::with_wallet(Wallet::Default, &["-txindex"]); + let node = BitcoinD::with_wallet(Wallet::Default, &["-txindex"]); node.fund_wallet(); let (_, tx) = node.create_mined_transaction(); @@ -526,10 +526,10 @@ fn wallet__import_pruned_funds() { fn wallet__import_wallet() { let node = match () { #[cfg(feature = "v22_and_below")] - () => Node::with_wallet(Wallet::Default, &[]), + () => BitcoinD::with_wallet(Wallet::Default, &[]), #[cfg(not(feature = "v22_and_below"))] () => { - let node = Node::with_wallet(Wallet::None, &["-deprecatedrpc=create_bdb"]); + let node = BitcoinD::with_wallet(Wallet::None, &["-deprecatedrpc=create_bdb"]); node.client.create_legacy_wallet("wallet_name").expect("createlegacywallet"); node } @@ -546,14 +546,14 @@ fn wallet__import_wallet() { #[test] fn wallet__keypool_refill() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); let _: () = node.client.key_pool_refill().expect("keypoolrefill"); } #[test] fn wallet__list_address_groupings__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let address = node.client.new_address().expect("failed to create new address"); @@ -571,7 +571,7 @@ fn wallet__list_address_groupings__modelled() { #[test] fn wallet__list_labels__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); let label = "list-label-test"; let _ = node.client.new_address_with_label(label).expect("newaddress"); @@ -583,7 +583,7 @@ fn wallet__list_labels__modelled() { #[test] #[cfg(not(feature = "v17"))] fn wallet__list_received_by_label__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let label = "test-label"; @@ -602,7 +602,7 @@ fn wallet__list_received_by_label__modelled() { #[test] fn wallet__list_received_by_address__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let address = node.client.new_address().expect("failed to create new address"); let amount = Amount::from_sat(10_000); @@ -620,7 +620,7 @@ fn wallet__list_received_by_address__modelled() { #[test] fn wallet__list_since_block__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let addr = node.client.new_address().expect("newaddress"); let amount = Amount::from_sat(5_000); @@ -637,7 +637,7 @@ fn wallet__list_since_block__modelled() { #[test] fn wallet__list_transactions__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let addr = node.client.new_address().expect("newaddress"); @@ -658,10 +658,10 @@ fn wallet__list_transactions__modelled() { fn wallet__import_multi() { let node = match () { #[cfg(feature = "v22_and_below")] - () => Node::with_wallet(Wallet::Default, &[]), + () => BitcoinD::with_wallet(Wallet::Default, &[]), #[cfg(not(feature = "v22_and_below"))] () => { - let node = Node::with_wallet(Wallet::None, &["-deprecatedrpc=create_bdb"]); + let node = BitcoinD::with_wallet(Wallet::None, &["-deprecatedrpc=create_bdb"]); node.client.create_legacy_wallet("wallet_name").expect("createlegacywallet"); node } @@ -722,10 +722,10 @@ fn wallet__import_multi() { fn wallet__import_privkey() { let node = match () { #[cfg(feature = "v22_and_below")] - () => Node::with_wallet(Wallet::Default, &[]), + () => BitcoinD::with_wallet(Wallet::Default, &[]), #[cfg(not(feature = "v22_and_below"))] () => { - let node = Node::with_wallet(Wallet::None, &["-deprecatedrpc=create_bdb"]); + let node = BitcoinD::with_wallet(Wallet::None, &["-deprecatedrpc=create_bdb"]); node.client.create_legacy_wallet("wallet_name").expect("createlegacywallet"); node } @@ -742,10 +742,10 @@ fn wallet__import_privkey() { fn wallet__import_pubkey() { let node = match () { #[cfg(feature = "v22_and_below")] - () => Node::with_wallet(Wallet::Default, &[]), + () => BitcoinD::with_wallet(Wallet::Default, &[]), #[cfg(not(feature = "v22_and_below"))] () => { - let node = Node::with_wallet(Wallet::None, &["-deprecatedrpc=create_bdb"]); + let node = BitcoinD::with_wallet(Wallet::None, &["-deprecatedrpc=create_bdb"]); node.client.create_legacy_wallet("wallet_name").expect("createlegacywallet"); node } @@ -761,7 +761,7 @@ fn wallet__import_pubkey() { #[test] #[cfg(not(feature = "v21_and_below"))] fn wallet__list_descriptors() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let wallet_name = "desc_wallet"; #[cfg(feature = "v22_and_below")] @@ -781,7 +781,7 @@ fn wallet__list_descriptors() { #[test] fn wallet__list_lock_unspent__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let json: ListUnspent = node.client.list_unspent().expect("listunspent"); @@ -801,9 +801,9 @@ fn wallet__list_lock_unspent__modelled() { fn wallet__list_unspent__modelled() { let node = match () { #[cfg(feature = "v17")] - () => Node::with_wallet(Wallet::Default, &["-deprecatedrpc=accounts"]), + () => BitcoinD::with_wallet(Wallet::Default, &["-deprecatedrpc=accounts"]), #[cfg(not(feature = "v17"))] - () => Node::with_wallet(Wallet::Default, &[]), + () => BitcoinD::with_wallet(Wallet::Default, &[]), }; node.fund_wallet(); @@ -817,7 +817,7 @@ fn wallet__list_unspent__modelled() { #[cfg(not(feature = "v17"))] fn wallet__list_wallet_dir() { let wallet_name = "test-wallet"; - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); node.client.create_wallet(wallet_name).expect("failed to create wallet"); let wallet_dir = node.client.list_wallet_dir().expect("listwalletdir"); @@ -828,7 +828,7 @@ fn wallet__list_wallet_dir() { #[test] fn wallet__list_wallets__modelled() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let wallet_1 = "test_wallet_1"; let wallet_2 = "test_wallet_2"; @@ -846,7 +846,7 @@ fn wallet__load_wallet__modelled() { create_load_unload_wallet(); } #[test] fn wallet__lock_unspent() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let json: ListUnspent = node.client.list_unspent().expect("listunspent"); @@ -866,7 +866,7 @@ fn wallet__lock_unspent() { fn wallet__migrate_wallet() { // In v30 it is no longer possible to create a legacy wallet. // It is tested in v29 and has no documented changes in v30. - let node = Node::with_wallet(Wallet::None, &["-deprecatedrpc=create_bdb"]); + let node = BitcoinD::with_wallet(Wallet::None, &["-deprecatedrpc=create_bdb"]); let wallet_name = "legacy_wallet"; node.client.create_legacy_wallet(wallet_name).expect("createlegacywallet"); @@ -878,7 +878,7 @@ fn wallet__migrate_wallet() { #[test] #[cfg(all(feature = "v29_and_below", not(feature = "v22_and_below")))] fn wallet__new_keypool() { - let node = Node::with_wallet(Wallet::None, &["-deprecatedrpc=create_bdb"]); + let node = BitcoinD::with_wallet(Wallet::None, &["-deprecatedrpc=create_bdb"]); node.client.create_legacy_wallet("legacy_wallet").expect("createlegacywallet"); let _: () = node.client.new_keypool().expect("newkeypool"); } @@ -886,7 +886,7 @@ fn wallet__new_keypool() { #[test] #[cfg(not(feature = "v20_and_below"))] fn wallet__psbt_bump_fee__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); let address = node.client.new_address().expect("failed to create new address"); let _ = node.client.generate_to_address(101, &address).expect("generatetoaddress"); @@ -904,7 +904,7 @@ fn wallet__psbt_bump_fee__modelled() { #[test] fn wallet__remove_pruned_funds() { - let node = Node::with_wallet(Wallet::Default, &["-txindex"]); + let node = BitcoinD::with_wallet(Wallet::Default, &["-txindex"]); node.fund_wallet(); let (_, tx) = node.create_mined_transaction(); @@ -921,7 +921,7 @@ fn wallet__remove_pruned_funds() { #[test] fn wallet__rescan_blockchain__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); let mining_addr = node.client.new_address().expect("newaddress"); let _ = node.client.generate_to_address(3, &mining_addr).expect("generatetoaddress"); @@ -947,7 +947,7 @@ fn wallet__unload_wallet() { create_load_unload_wallet(); } #[test] fn wallet__send_many__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let addr1 = node.client.new_address().expect("newaddress"); @@ -976,7 +976,7 @@ fn wallet__send_many__modelled() { fn wallet__send__modelled() { use std::collections::BTreeMap; - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let address = node.client.new_address().expect("failed to create new address"); @@ -991,7 +991,7 @@ fn wallet__send__modelled() { #[test] #[cfg(not(feature = "v23_and_below"))] fn wallet__send_all__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let address = node.client.new_address().expect("failed to create new address"); @@ -1002,7 +1002,7 @@ fn wallet__send_all__modelled() { #[test] fn wallet__send_to_address__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let address = node.client.new_address().expect("failed to create new address"); @@ -1016,9 +1016,9 @@ fn wallet__send_to_address__modelled() { #[cfg(feature = "v30_and_below")] fn wallet__set_tx_fee() { #[cfg(feature = "v29_and_below")] - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); #[cfg(not(feature = "v29_and_below"))] - let node = Node::with_wallet(Wallet::Default, &["-deprecatedrpc=settxfee"]); + let node = BitcoinD::with_wallet(Wallet::Default, &["-deprecatedrpc=settxfee"]); let fee_rate = FeeRate::from_sat_per_vb(2).expect("2 sat/vb is valid"); @@ -1029,7 +1029,7 @@ fn wallet__set_tx_fee() { #[test] #[cfg(not(feature = "v18_and_below"))] fn wallet__set_wallet_flag() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); let json: SetWalletFlag = node.client.set_wallet_flag("avoid_reuse").expect("setwalletflag"); assert_eq!(json.flag_name, "avoid_reuse"); @@ -1041,10 +1041,10 @@ fn wallet__set_wallet_flag() { fn wallet__set_hd_seed() { let node = match () { #[cfg(feature = "v22_and_below")] - () => Node::with_wallet(Wallet::Default, &[]), + () => BitcoinD::with_wallet(Wallet::Default, &[]), #[cfg(not(feature = "v22_and_below"))] () => { - let node = Node::with_wallet(Wallet::None, &["-deprecatedrpc=create_bdb"]); + let node = BitcoinD::with_wallet(Wallet::None, &["-deprecatedrpc=create_bdb"]); node.client.create_legacy_wallet("wallet_name").expect("createlegacywallet"); node } @@ -1057,7 +1057,7 @@ fn wallet__set_hd_seed() { #[test] fn wallet__sign_message__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let address = node.client.new_address_with_type(AddressType::Legacy).unwrap(); @@ -1072,7 +1072,7 @@ fn wallet__sign_message__modelled() { #[test] #[cfg(not(feature = "v23_and_below"))] fn wallet__simulate_raw_transaction() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let address = node.client.new_address().expect("failed to create new address"); @@ -1100,7 +1100,7 @@ fn wallet__simulate_raw_transaction() { #[test] fn wallet__wallet_create_funded_psbt__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let addr = node.client.new_address().expect("newaddress"); @@ -1119,7 +1119,7 @@ fn wallet__wallet_create_funded_psbt__modelled() { #[test] fn wallet__wallet_process_psbt__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); let addr = node.client.new_address().expect("newaddress"); @@ -1145,7 +1145,7 @@ fn wallet__wallet_process_psbt__modelled() { #[test] fn wallet__wallet_lock() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.client.create_wallet("wallet_name").expect("createwallet"); node.client.encrypt_wallet("passphrase").expect("encryptwallet"); @@ -1155,7 +1155,7 @@ fn wallet__wallet_lock() { #[test] fn wallet__wallet_passphrase() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.client.create_wallet("wallet_name").expect("createwallet"); node.client.encrypt_wallet("passphrase").expect("encryptwallet"); @@ -1166,7 +1166,7 @@ fn wallet__wallet_passphrase() { #[test] fn wallet__wallet_passphrase_change() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.client.create_wallet("wallet name").expect("createwallet"); node.client.encrypt_wallet("old passphrase").expect("encryptwallet"); @@ -1178,7 +1178,7 @@ fn wallet__wallet_passphrase_change() { } fn create_load_unload_wallet() { - let node = Node::with_wallet(Wallet::None, &[]); + let node = BitcoinD::with_wallet(Wallet::None, &[]); let wallet = format!("wallet-{}", rand::random::()).to_string(); node.client.create_wallet(&wallet).expect("failed to create wallet"); @@ -1200,7 +1200,7 @@ fn create_load_unload_wallet() { #[test] #[cfg(all(feature = "v29_and_below", not(feature = "v20_and_below")))] fn wallet__upgrade_wallet() { - let node = Node::with_wallet(Wallet::Default, &[]); + let node = BitcoinD::with_wallet(Wallet::Default, &[]); let _: UpgradeWallet = node.client.upgrade_wallet().expect("upgradewallet"); } diff --git a/integration_test/tests/zmq.rs b/integration_test/tests/zmq.rs index 71be726de..22fd46bc8 100644 --- a/integration_test/tests/zmq.rs +++ b/integration_test/tests/zmq.rs @@ -5,15 +5,15 @@ #![allow(non_snake_case)] // Test names intentionally use double underscore. #![allow(unused_imports)] // Because of feature gated tests. -use integration_test::{Node, NodeExt as _, Wallet}; -use node::vtype::*; // All the version specific types. +use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; +use bitcoind::vtype::*; // All the version specific types. #[test] #[cfg(not(feature = "v17"))] fn zmq__get_zmq_notifications__modelled() { // Start node with a ZMQ notification enabled so we have at least one entry. // Using hashblock as it is lightweight. - let node = Node::with_wallet(Wallet::Default, &["-zmqpubhashblock=tcp://127.0.0.1:29000"]); + let node = BitcoinD::with_wallet(Wallet::Default, &["-zmqpubhashblock=tcp://127.0.0.1:29000"]); let list: Vec = node.client.get_zmq_notifications().expect("getzmqnotifications"); diff --git a/justfile b/justfile index 72c048680..702445609 100644 --- a/justfile +++ b/justfile @@ -6,7 +6,7 @@ REPO_DIR := `git rev-parse --show-toplevel` ALL_FEATURE_CRATES := "bitreq client fuzz jsonrpc types verify" # Targets with conflicting features and only `SPECIFIC_FEATURES` are used. -SPECIFIC_FEATURES_CRATES := "integration_test node" +SPECIFIC_FEATURES_CRATES := "integration_test bitcoind" SPECIFIC_FEATURES := "latest" alias ulf := update-lock-files From 68665285c20f3421f4d6698e56932062f916cb7a Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 9 Apr 2026 09:18:19 +1000 Subject: [PATCH 06/12] Remove patch sections We use `path =` in all the manifests to pick up local deps. No need for the `patch` section anymore. --- Cargo.toml | 12 ------------ integration_test/Cargo.toml | 13 ------------- 2 files changed, 25 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0d8bb5a07..c005b0344 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,18 +4,6 @@ exclude = ["integration_test", "verify", "electrsd"] resolver = "2" rust-version = "1.75.0" -[patch.crates-io.corepc-client] -path = "client" - -[patch.crates-io.jsonrpc] -path = "jsonrpc" - -[patch.crates-io.bitcoind] -path = "bitcoind" - -[patch.crates-io.corepc-types] -path = "types" - [workspace.metadata.rbmt.toolchains] nightly = "nightly-2025-09-12" stable = "1.94.1" diff --git a/integration_test/Cargo.toml b/integration_test/Cargo.toml index 2c9aa653d..c44a1bfb7 100644 --- a/integration_test/Cargo.toml +++ b/integration_test/Cargo.toml @@ -69,16 +69,3 @@ rand = "0.8.5" types = { package = "corepc-types", version = "0.12.0", path = "../types", features = ["serde-deny-unknown-fields"] } [dev-dependencies] - - -[patch.crates-io.corepc-client] -path = "../client" - -[patch.crates-io.jsonrpc] -path = "../jsonrpc" - -[patch.crates-io.bitcoind] -path = "../bitcoind" - -[patch.crates-io.corepc-types] -path = "../types" From f6d37fcebf912c0bf7b7b63692fa82ae1d432f8b Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 9 Apr 2026 09:21:39 +1000 Subject: [PATCH 07/12] electrsd: Bump version to 0.37.0 In preparation for release bump the version. FWIW the version of `bitcoind` has already been bumped to `0.37.0` also. --- electrsd/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/electrsd/Cargo.toml b/electrsd/Cargo.toml index eafe5e9a0..113186d40 100644 --- a/electrsd/Cargo.toml +++ b/electrsd/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "electrsd" -version = "0.36.1" +version = "0.37.0" authors = ["Riccardo Casatta "] description = "Utility to run a regtest electrs process, useful in integration testing environment" repository = "https://github.com/RCasatta/electrsd" From 186b3b624d41b563373e84392b60cda6f9364b12 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 9 Apr 2026 09:29:06 +1000 Subject: [PATCH 08/12] electsd: Set correct repository --- electrsd/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/electrsd/Cargo.toml b/electrsd/Cargo.toml index 113186d40..57e175890 100644 --- a/electrsd/Cargo.toml +++ b/electrsd/Cargo.toml @@ -3,7 +3,7 @@ name = "electrsd" version = "0.37.0" authors = ["Riccardo Casatta "] description = "Utility to run a regtest electrs process, useful in integration testing environment" -repository = "https://github.com/RCasatta/electrsd" +repository = "https://github.com/rust-bitcoin/corepc" documentation = "https://docs.rs/elecrtsd/" license = "MIT" edition = "2018" From d6a5162a2b566aa7b2f469512b93a0a27cbc2f3b Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 9 Apr 2026 09:30:22 +1000 Subject: [PATCH 09/12] CI: Tie elects into CI correctly For `electrs` to build in CI it needs a `contrib` directory. --- electrsd/Cargo.toml | 1 + electrsd/contrib/test_vars.sh | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 electrsd/contrib/test_vars.sh diff --git a/electrsd/Cargo.toml b/electrsd/Cargo.toml index 57e175890..d60ee29df 100644 --- a/electrsd/Cargo.toml +++ b/electrsd/Cargo.toml @@ -8,6 +8,7 @@ documentation = "https://docs.rs/elecrtsd/" license = "MIT" edition = "2018" categories = ["cryptography::cryptocurrencies", "development-tools::testing"] +exclude = ["tests", "contrib"] [dependencies] bitcoind = { version = "0.37.0", path = "../bitcoind" } diff --git a/electrsd/contrib/test_vars.sh b/electrsd/contrib/test_vars.sh new file mode 100644 index 000000000..207969ad1 --- /dev/null +++ b/electrsd/contrib/test_vars.sh @@ -0,0 +1,18 @@ +# No shebang, this file should not be executed. +# shellcheck disable=SC2148 +# +# disable verify unused vars, despite the fact that they are used when sourced +# shellcheck disable=SC2034 + +# Test all these features with "std" enabled. +FEATURES_WITH_STD="" + +# Test all these features without "std" or "alloc" enabled. +FEATURES_WITHOUT_STD="" + +# Run these examples. +EXAMPLES="" + +# Just check the latest minor version of the last three supported Core versions. +# This is mainly for docs and MSRV - integration tests will catch any other errors. +EXACT_FEATURES=("bitcoind_30_2,elects_0_10_6" "29_0_2,elects_0_10_6" "28_2,elects_0_10_6") From 89765dd625d1737f1a2c58065febc501ed62469a Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 9 Apr 2026 09:35:15 +1000 Subject: [PATCH 10/12] electrsd: Bump MSRV to 1.75 No code changes required. Just document it in the manifest. This is the same MSRV as the rest of the repository. Includes usage of `bitreq` instead of `minreq` because `bitreq` is on the same MSRV (and it lives in this repo). FTR `bitreq` is our fork of `minreq`. --- electrsd/Cargo.toml | 7 ++++--- electrsd/build.rs | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/electrsd/Cargo.toml b/electrsd/Cargo.toml index d60ee29df..4db552578 100644 --- a/electrsd/Cargo.toml +++ b/electrsd/Cargo.toml @@ -6,7 +6,8 @@ description = "Utility to run a regtest electrs process, useful in integration t repository = "https://github.com/rust-bitcoin/corepc" documentation = "https://docs.rs/elecrtsd/" license = "MIT" -edition = "2018" +edition = "2021" +rust-version = "1.75.0" categories = ["cryptography::cryptocurrencies", "development-tools::testing"] exclude = ["tests", "contrib"] @@ -28,7 +29,7 @@ zip = { version = "0.6", default-features = false, optional = true, features = [ "bzip2", "deflate", ] } -minreq = { version = "2.9.0", default-features = false, optional = true, features = [ +bitreq = { version = "0.3.4", path = "../bitreq", default-features = false, optional = true, features = [ "https", ] } @@ -36,7 +37,7 @@ minreq = { version = "2.9.0", default-features = false, optional = true, feature legacy = [] # download is not supposed to be used directly only through selecting one of the version feature -download = ["bitcoin_hashes", "zip", "minreq"] +download = ["bitcoin_hashes", "zip", "bitreq"] esplora_a33e97e1 = ["download", "legacy"] electrs_0_8_10 = ["download"] diff --git a/electrsd/build.rs b/electrsd/build.rs index 727a13963..ee31ddf56 100644 --- a/electrsd/build.rs +++ b/electrsd/build.rs @@ -61,7 +61,7 @@ mod download { std::env::var("ELECTRSD_DOWNLOAD_ENDPOINT").unwrap_or(GITHUB_URL.to_string()); let url = format!("{}/{}", download_endpoint, download_filename); - let downloaded_bytes = minreq::get(url).send().unwrap().into_bytes(); + let downloaded_bytes = bitreq::get(url).send().unwrap().into_bytes(); let downloaded_hash = sha256::Hash::hash(&downloaded_bytes); assert_eq!(expected_hash, downloaded_hash); From 980ef98ed505e936b3785b1ab4ae036abd815bdc Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 9 Apr 2026 09:36:04 +1000 Subject: [PATCH 11/12] Run the formatter --- bitcoind/src/lib.rs | 2 +- integration_test/tests/blockchain.rs | 2 +- integration_test/tests/control.rs | 4 ++-- integration_test/tests/generating.rs | 4 ++-- integration_test/tests/hidden.rs | 2 +- integration_test/tests/mining.rs | 4 ++-- integration_test/tests/network.rs | 2 +- integration_test/tests/raw_transactions.rs | 4 ++-- integration_test/tests/signer.rs | 4 ++-- integration_test/tests/util.rs | 2 +- integration_test/tests/wallet.rs | 2 +- integration_test/tests/zmq.rs | 4 ++-- 12 files changed, 18 insertions(+), 18 deletions(-) diff --git a/bitcoind/src/lib.rs b/bitcoind/src/lib.rs index 74755f51f..b5ef9a9cc 100644 --- a/bitcoind/src/lib.rs +++ b/bitcoind/src/lib.rs @@ -666,7 +666,7 @@ mod test { use tempfile::TempDir; use super::*; - use crate::{exe_path, get_available_port, Conf, BitcoinD, LOCAL_IP, P2P}; + use crate::{exe_path, get_available_port, BitcoinD, Conf, LOCAL_IP, P2P}; #[test] fn test_local_ip() { diff --git a/integration_test/tests/blockchain.rs b/integration_test/tests/blockchain.rs index b66f55129..1eb4e4741 100644 --- a/integration_test/tests/blockchain.rs +++ b/integration_test/tests/blockchain.rs @@ -6,9 +6,9 @@ use bitcoin::consensus::encode; use bitcoin::hex; -use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; use bitcoind::vtype::*; // All the version specific types. use bitcoind::{mtype, Input, Output}; +use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; #[test] #[cfg(not(feature = "v25_and_below"))] diff --git a/integration_test/tests/control.rs b/integration_test/tests/control.rs index a45beea36..d4f104454 100644 --- a/integration_test/tests/control.rs +++ b/integration_test/tests/control.rs @@ -4,8 +4,8 @@ #![allow(non_snake_case)] // Test names intentionally use double underscore. -use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; -use bitcoind::vtype::*; // All the version specific types. +use bitcoind::vtype::*; +use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; // All the version specific types. #[test] fn control__get_memory_info() { diff --git a/integration_test/tests/generating.rs b/integration_test/tests/generating.rs index 788dd6dc7..90880dad7 100644 --- a/integration_test/tests/generating.rs +++ b/integration_test/tests/generating.rs @@ -5,9 +5,9 @@ #![allow(non_snake_case)] // Test names intentionally use double underscore. use bitcoin::hex; -use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; use bitcoind::mtype; -use bitcoind::vtype::*; // All the version specific types. +use bitcoind::vtype::*; +use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; // All the version specific types. #[test] #[cfg(not(feature = "v20_and_below"))] diff --git a/integration_test/tests/hidden.rs b/integration_test/tests/hidden.rs index ad21a7315..5909589d6 100644 --- a/integration_test/tests/hidden.rs +++ b/integration_test/tests/hidden.rs @@ -16,11 +16,11 @@ use bitcoin::{ absolute, consensus, transaction, Amount, OutPoint, ScriptBuf, Sequence, Transaction, TxIn, TxOut, Txid, Witness, }; -use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; use bitcoind::mtype; use bitcoind::vtype::*; // All the version specific types. #[cfg(not(feature = "v21_and_below"))] use bitcoind::P2P; +use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; #[test] #[cfg(not(feature = "v21_and_below"))] diff --git a/integration_test/tests/mining.rs b/integration_test/tests/mining.rs index 238dc175b..0875e5398 100644 --- a/integration_test/tests/mining.rs +++ b/integration_test/tests/mining.rs @@ -5,9 +5,9 @@ #![allow(non_snake_case)] // Test names intentionally use double underscore. use bitcoin::SignedAmount; -use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; use bitcoind::vtype::*; -use bitcoind::{mtype, TemplateRequest, TemplateRules}; // All the version specific types. +use bitcoind::{mtype, TemplateRequest, TemplateRules}; +use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; // All the version specific types. #[test] fn mining__get_block_template__modelled() { diff --git a/integration_test/tests/network.rs b/integration_test/tests/network.rs index da4d96e08..345a7ec5a 100644 --- a/integration_test/tests/network.rs +++ b/integration_test/tests/network.rs @@ -4,9 +4,9 @@ #![allow(non_snake_case)] // Test names intentionally use double underscore. -use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; use bitcoind::vtype::*; // All the version specific types. use bitcoind::{mtype, AddNodeCommand, SetBanCommand}; +use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; #[test] fn network__add_node() { diff --git a/integration_test/tests/raw_transactions.rs b/integration_test/tests/raw_transactions.rs index 6a756a97f..c1cf05029 100644 --- a/integration_test/tests/raw_transactions.rs +++ b/integration_test/tests/raw_transactions.rs @@ -12,9 +12,9 @@ use bitcoin::opcodes::all::*; use bitcoin::{ absolute, consensus, hex, psbt, script, transaction, Amount, ScriptBuf, Transaction, TxOut, }; -use integration_test::{test_keys, BitcoinD, BitcoinDExt as _, Wallet}; use bitcoind::vtype::*; -use bitcoind::{mtype, Input, Output}; // All the version specific types. +use bitcoind::{mtype, Input, Output}; +use integration_test::{test_keys, BitcoinD, BitcoinDExt as _, Wallet}; // All the version specific types. #[test] #[cfg(not(feature = "v17"))] // analyzepsbt was added in v0.18. diff --git a/integration_test/tests/signer.rs b/integration_test/tests/signer.rs index f6a40fb4f..6e832a9cc 100644 --- a/integration_test/tests/signer.rs +++ b/integration_test/tests/signer.rs @@ -7,9 +7,9 @@ use bitcoin::address::{NetworkUnchecked, ParseError}; use bitcoin::Address; -use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; use bitcoind::vtype::*; -use bitcoind::{mtype, Input, Output}; // All the version specific types. +use bitcoind::{mtype, Input, Output}; +use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; // All the version specific types. #[test] #[cfg(unix)] diff --git a/integration_test/tests/util.rs b/integration_test/tests/util.rs index d3202ef53..2bdba85e2 100644 --- a/integration_test/tests/util.rs +++ b/integration_test/tests/util.rs @@ -6,9 +6,9 @@ #![allow(unused_imports)] // Because of feature gated tests. use bitcoin::{address, amount, sign_message, PrivateKey, PublicKey}; -use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; use bitcoind::vtype::*; use bitcoind::{mtype, FeeEstimateMode}; +use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; #[test] fn util__create_multisig__modelled() { diff --git a/integration_test/tests/wallet.rs b/integration_test/tests/wallet.rs index ca8627d9b..5b88a0a62 100644 --- a/integration_test/tests/wallet.rs +++ b/integration_test/tests/wallet.rs @@ -15,7 +15,6 @@ use bitcoin::{ amount, hex, key, psbt, secp256k1, sign_message, Amount, CompressedPublicKey, FeeRate, Network, PrivateKey, PublicKey, }; -use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; use bitcoind::vtype::*; // All the version specific types. #[cfg(not(feature = "v20_and_below"))] use bitcoind::ImportDescriptorsRequest; @@ -23,6 +22,7 @@ use bitcoind::{ mtype, AddressType, ImportMultiRequest, ImportMultiScriptPubKey, ImportMultiTimestamp, WalletCreateFundedPsbtInput, }; +use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; #[test] fn wallet__abandon_transaction() { diff --git a/integration_test/tests/zmq.rs b/integration_test/tests/zmq.rs index 22fd46bc8..372bd5f44 100644 --- a/integration_test/tests/zmq.rs +++ b/integration_test/tests/zmq.rs @@ -5,8 +5,8 @@ #![allow(non_snake_case)] // Test names intentionally use double underscore. #![allow(unused_imports)] // Because of feature gated tests. -use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; -use bitcoind::vtype::*; // All the version specific types. +use bitcoind::vtype::*; +use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; // All the version specific types. #[test] #[cfg(not(feature = "v17"))] From 4b080fcb56284e36815f5860db602e1473657688 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Fri, 10 Apr 2026 11:53:57 +1000 Subject: [PATCH 12/12] CI: Fix test-electrs-no-download Install LLVM and Clang as suggested by an LLM. --- .github/workflows/rust.yaml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/.github/workflows/rust.yaml b/.github/workflows/rust.yaml index d99ad3345..9738b3259 100644 --- a/.github/workflows/rust.yaml +++ b/.github/workflows/rust.yaml @@ -210,6 +210,23 @@ jobs: ELECTRS_EXEC: "/home/runner/.cargo-install/electrs/bin/electrs" steps: - uses: dtolnay/rust-toolchain@stable + - name: Install LLVM and Clang + run: | + sudo apt-get update -y + sudo apt-get install -y clang libclang-dev llvm-dev + + llvm_config="$(command -v llvm-config || true)" + if [[ -z "$llvm_config" ]]; then + llvm_config="$(command -v llvm-config-18 || true)" + fi + + if [[ -z "$llvm_config" ]]; then + echo "llvm-config not found after installing LLVM packages" >&2 + exit 1 + fi + + echo "LLVM_CONFIG_PATH=$llvm_config" >> "$GITHUB_ENV" + echo "LIBCLANG_PATH=$($llvm_config --libdir)" >> "$GITHUB_ENV" - name: Install electrs # Automatically cache installed binaries to avoid compiling them each run uses: baptiste0928/cargo-install@v2 @@ -219,4 +236,4 @@ jobs: - name: Checkout Crate uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 - - run: cargo test --features 'bitcoind_25_2' + - run: cd electrsd && cargo test --features 'bitcoind_25_2'