From b506688f75b79880e243437cbee7af19db070053 Mon Sep 17 00:00:00 2001 From: Renato Britto Date: Wed, 29 Apr 2026 13:19:32 -0300 Subject: [PATCH 1/8] electrsd: apply clippy lint error fix --- electrsd/build.rs | 2 +- electrsd/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/electrsd/build.rs b/electrsd/build.rs index ee31ddf5..bcf154e5 100644 --- a/electrsd/build.rs +++ b/electrsd/build.rs @@ -22,7 +22,7 @@ mod download { fn get_expected_sha256(filename: &str) -> Result { let file = File::open("sha256").map_err(|_| ())?; - for line in BufReader::new(file).lines().flatten() { + for line in BufReader::new(file).lines().map_while(Result::ok) { let tokens: Vec<_> = line.split(" ").collect(); if tokens.len() == 2 && filename == tokens[1] { return sha256::Hash::from_str(tokens[0]).map_err(|_| ()); diff --git a/electrsd/src/lib.rs b/electrsd/src/lib.rs index 68d97f68..255f97a8 100644 --- a/electrsd/src/lib.rs +++ b/electrsd/src/lib.rs @@ -467,7 +467,7 @@ mod 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(); + electrsd.client.ping().unwrap(); assert!(electrsd.client.ping().is_ok()); electrsd.kill().unwrap(); assert!(electrsd.client.ping().is_err()); From 84528875f4ba4d4da0309d94c655e7ab0e294268 Mon Sep 17 00:00:00 2001 From: Renato Britto Date: Wed, 29 Apr 2026 13:11:58 -0300 Subject: [PATCH 2/8] electrsd: apply rustfmt cleanup --- electrsd/build.rs | 24 ++++------- electrsd/src/error.rs | 20 +++------ electrsd/src/ext.rs | 23 +++++------ electrsd/src/lib.rs | 87 ++++++++++++---------------------------- electrsd/src/versions.rs | 4 +- 5 files changed, 49 insertions(+), 109 deletions(-) diff --git a/electrsd/build.rs b/electrsd/build.rs index bcf154e5..1c320b95 100644 --- a/electrsd/build.rs +++ b/electrsd/build.rs @@ -2,19 +2,18 @@ fn main() {} #[cfg(feature = "download")] -fn main() { - download::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; + use bitcoin_hashes::{sha256, Hash}; + include!("src/versions.rs"); const GITHUB_URL: &str = @@ -45,17 +44,13 @@ mod download { 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"); + 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 - ); + println!("filename:{} version:{} hash:{}", download_filename, VERSION, expected_hash); let download_endpoint = std::env::var("ELECTRSD_DOWNLOAD_ENDPOINT").unwrap_or(GITHUB_URL.to_string()); @@ -73,11 +68,8 @@ mod download { 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(); + std::fs::set_permissions(&destination_filename, std::fs::Permissions::from_mode(0o755)) + .unwrap(); } } } diff --git a/electrsd/src/error.rs b/electrsd/src/error.rs index ff0188ea..aa2abf83 100644 --- a/electrsd/src/error.rs +++ b/electrsd/src/error.rs @@ -44,32 +44,22 @@ impl std::error::Error for Error { } impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", self) - } + 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) - } + fn from(e: std::io::Error) -> Self { Error::Io(e) } } impl From for Error { - fn from(e: bitcoind::Error) -> Self { - Error::Bitcoind(e) - } + fn from(e: bitcoind::Error) -> Self { Error::Bitcoind(e) } } impl From for Error { - fn from(e: electrum_client::Error) -> Self { - Error::ElectrumClient(e) - } + 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) - } + fn from(e: nix::Error) -> Self { Error::Nix(e) } } diff --git a/electrsd/src/ext.rs b/electrsd/src/ext.rs index 147bd413..6320bde8 100644 --- a/electrsd/src/ext.rs +++ b/electrsd/src/ext.rs @@ -4,7 +4,8 @@ use std::thread; use std::time::Duration; -use electrum_client::{bitcoin::Txid, ElectrumApi}; +use electrum_client::bitcoin::Txid; +use electrum_client::ElectrumApi; use crate::ElectrsD; @@ -28,10 +29,8 @@ impl ElectrsD { // 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(); + 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 @@ -52,8 +51,10 @@ impl ElectrsD { #[cfg(test)] mod test { + use electrum_client::bitcoin::Amount; + use electrum_client::ElectrumApi; + use crate::test::setup_nodes; - use electrum_client::{bitcoin::Amount, ElectrumApi}; #[cfg(not(feature = "electrs_0_8_10"))] #[test] @@ -74,10 +75,7 @@ mod test { 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(); + bitcoind.client.generate_to_address(100, &generate_address).unwrap(); let address = bitcoind.client.new_address().unwrap(); let txid = bitcoind @@ -88,10 +86,7 @@ mod test { .unwrap(); electrsd.wait_tx(&txid); - let history = electrsd - .client - .script_get_history(&address.script_pubkey()) - .unwrap(); + 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 index 255f97a8..7f5399e0 100644 --- a/electrsd/src/lib.rs +++ b/electrsd/src/lib.rs @@ -1,6 +1,3 @@ -#![warn(missing_docs)] - -//! //! Electrsd //! //! Utility to run a regtest electrsd process, useful in integration testing environment @@ -10,26 +7,24 @@ mod error; mod ext; mod versions; -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}; +pub extern crate bitcoind; +pub extern crate corepc_client; +pub extern crate electrum_client; + use std::env; use std::ffi::OsStr; use std::path::PathBuf; use std::process::{Child, Command, Stdio}; use std::time::Duration; -// 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 -pub use electrum_client; +use bitcoind::anyhow::Context; +use bitcoind::serde_json::Value; +use bitcoind::tempfile::TempDir; +use bitcoind::{anyhow, get_available_port, BitcoinD}; +use electrum_client::raw_client::{ElectrumPlaintextStream, RawClient}; +use log::{debug, error, warn}; +#[rustfmt::skip] // Keep public re-exports separate. pub use error::Error; /// Electrs configuration parameters, implements a convenient [Default] for most common use. @@ -153,18 +148,11 @@ impl ElectrsD { conf: &Conf, ) -> anyhow::Result { let response = bitcoind.client.call::("getblockchaininfo", &[])?; - if response - .get("initialblockdownload") - .and_then(|v| v.as_bool()) - .unwrap_or(false) - { + 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(); + bitcoind.client.call::("generatetoaddress", &[1.into(), node_address]).unwrap(); } let mut args = conf.args.clone(); @@ -250,11 +238,7 @@ impl ElectrsD { None }; - let view_stderr = if conf.view_stderr { - Stdio::inherit() - } else { - Stdio::null() - }; + let view_stderr = if conf.view_stderr { Stdio::inherit() } else { Stdio::null() }; debug!("args: {:?}", args); let mut process = Command::new(&exe) @@ -282,13 +266,7 @@ impl ElectrsD { } }; - Ok(ElectrsD { - process, - client, - work_dir, - electrum_url, - esplora_url, - }) + 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 @@ -301,14 +279,10 @@ impl ElectrsD { } #[cfg(target_os = "windows")] - pub fn trigger(&self) -> anyhow::Result<()> { - Ok(()) - } + 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() - } + pub fn workdir(&self) -> PathBuf { self.work_dir.path() } /// terminate the electrs process pub fn kill(&mut self) -> anyhow::Result<()> { @@ -335,25 +309,17 @@ impl ElectrsD { } #[cfg(target_os = "windows")] - fn inner_kill(&mut self) -> anyhow::Result<()> { - Ok(self.process.kill()?) - } + fn inner_kill(&mut self) -> anyhow::Result<()> { Ok(self.process.kill()?) } } impl Drop for ElectrsD { - fn drop(&mut self) { - let _ = self.kill(); - } + 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(), - )) + Some(format!("{}/electrs/{}/electrs", env!("OUT_DIR"), versions::electrs_name(),)) } else { None } @@ -420,12 +386,13 @@ pub fn exe_path() -> anyhow::Result { #[cfg(test)] mod test { - use crate::exe_path; - use crate::ElectrsD; + use std::env; + use bitcoind::P2P; use electrum_client::ElectrumApi; use log::{debug, log_enabled, Level}; - use std::env; + + use crate::{exe_path, ElectrsD}; #[test] #[ignore] // launch singularly since env are globals @@ -483,10 +450,8 @@ mod test { conf.p2p = P2P::Yes; } let bitcoind = bitcoind::BitcoinD::with_conf(&bitcoind_exe, &conf).unwrap(); - let electrs_conf = crate::Conf { - view_stderr: log_enabled!(Level::Debug), - ..Default::default() - }; + 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) } diff --git a/electrsd/src/versions.rs b/electrsd/src/versions.rs index 999c39d6..504da5c1 100644 --- a/electrsd/src/versions.rs +++ b/electrsd/src/versions.rs @@ -39,6 +39,4 @@ pub const HAS_FEATURE: bool = cfg!(any( feature = "esplora_a33e97e1", )); -pub fn electrs_name() -> String { - format!("electrs_{}_{}", OS, VERSION) -} +pub fn electrs_name() -> String { format!("electrs_{}_{}", OS, VERSION) } From 9c0f13fbc7dbc26c5c515493a997d292c904279a Mon Sep 17 00:00:00 2001 From: Renato Britto Date: Wed, 29 Apr 2026 13:19:44 -0300 Subject: [PATCH 3/8] electrsd: add rbmt lint configuration --- electrsd/Cargo.toml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/electrsd/Cargo.toml b/electrsd/Cargo.toml index b2bebee8..7d1a7aaf 100644 --- a/electrsd/Cargo.toml +++ b/electrsd/Cargo.toml @@ -59,3 +59,19 @@ bitcoind_0_20_2 = ["bitcoind/0_20_2"] bitcoind_0_19_1 = ["bitcoind/0_19_1"] bitcoind_0_18_1 = ["bitcoind/0_18_1"] bitcoind_0_17_2 = ["bitcoind/0_17_2"] + +[package.metadata.rbmt.lint] +# The electrsd crate requires a version feature to compile +features = ["electrs_0_10_6"] +# Duplicates from build-dep/dep splits, --target=all, or upstream version conflicts. +allowed_duplicates = [ + "anyhow", # build-dep and regular dep, same version + "base64", # upstream version conflicts + "bitcoin_hashes", # build-dep (download) and transitive dep, same version + "bitflags", # upstream version conflicts + "bitreq", # build-dep (download) and regular dep, same version + "libc", # same version, appears twice under --target=all + "linux-raw-sys", # same version, appears twice under --target=all + "rustix", # same version, appears twice under --target=all + "windows-sys", # upstream version conflicts +] From 71e757b3f9e7c99a4990eeacbad83b444c760169 Mon Sep 17 00:00:00 2001 From: Renato Britto Date: Wed, 13 May 2026 18:23:29 -0300 Subject: [PATCH 4/8] electrsd: fix all-features test version conflicts Introducing electrsd in workspace cause --all-features tests to enable all electrsd feature flags, this commit creates a new test-only feature that is only enabled on these particular tests. Version compiler constant gets appropriately gates through the new flag so only the latest electsd version is activated. It introduces flag to all version specific call sites. --- electrsd/Cargo.toml | 3 ++ electrsd/src/lib.rs | 65 ++++++++++++++++++---------------------- electrsd/src/versions.rs | 19 ++++++------ 3 files changed, 42 insertions(+), 45 deletions(-) diff --git a/electrsd/Cargo.toml b/electrsd/Cargo.toml index 7d1a7aaf..558d419e 100644 --- a/electrsd/Cargo.toml +++ b/electrsd/Cargo.toml @@ -60,6 +60,9 @@ bitcoind_0_19_1 = ["bitcoind/0_19_1"] bitcoind_0_18_1 = ["bitcoind/0_18_1"] bitcoind_0_17_2 = ["bitcoind/0_17_2"] +# This flag should never be manually set. Used to handle `--all-features` was used. +all_features = [] + [package.metadata.rbmt.lint] # The electrsd crate requires a version feature to compile features = ["electrs_0_10_6"] diff --git a/electrsd/src/lib.rs b/electrsd/src/lib.rs index 7f5399e0..00a6a631 100644 --- a/electrsd/src/lib.rs +++ b/electrsd/src/lib.rs @@ -27,6 +27,8 @@ use log::{debug, error, warn}; #[rustfmt::skip] // Keep public re-exports separate. pub use error::Error; +const IS_ALL_FEATURES_BUILD: bool = cfg!(feature = "all_features"); + /// Electrs configuration parameters, implements a convenient [Default] for most common use. /// /// Default values: @@ -80,15 +82,14 @@ pub struct Conf<'a> { 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![] - }; + #[allow(unused_mut)] + let mut args = vec![]; + + let should_version_use_verbose_flag = + cfg!(any(feature = "electrs_0_9_1", feature = "electrs_0_8_10", feature = "legacy")); + if !IS_ALL_FEATURES_BUILD && should_version_use_verbose_flag { + args.push("-vvv"); + } Conf { args, @@ -177,43 +178,33 @@ impl ElectrsD { 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); - } + let cookie_flag; + let cookie_val = if !IS_ALL_FEATURES_BUILD && cfg!(feature = "legacy") { + cookie_flag = "--cookie"; + std::fs::read_to_string(&bitcoind.params.cookie_file)? + } else { + cookie_flag = "--cookie-file"; + bitcoind.params.cookie_file.display().to_string() + }; + args.push(cookie_flag); + args.push(&cookie_val); 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") - { + + let should_version_use_jsonrpc_import = + cfg!(any(feature = "electrs_0_8_10", feature = "esplora_a33e97e1", feature = "legacy")); + if !IS_ALL_FEATURES_BUILD && should_version_use_jsonrpc_import { 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") + .expect("electrs needs bitcoind with p2p port open") .to_string(); args.push(&p2p_socket); } @@ -392,7 +383,7 @@ mod test { use electrum_client::ElectrumApi; use log::{debug, log_enabled, Level}; - use crate::{exe_path, ElectrsD}; + use crate::{exe_path, ElectrsD, IS_ALL_FEATURES_BUILD}; #[test] #[ignore] // launch singularly since env are globals @@ -446,7 +437,9 @@ mod test { debug!("electrs: {}", &electrs_exe); let mut conf = bitcoind::Conf::default(); conf.view_stdout = log_enabled!(Level::Debug); - if !cfg!(feature = "electrs_0_8_10") && !cfg!(feature = "esplora_a33e97e1") { + let should_version_use_p2p = + !cfg!(any(feature = "electrs_0_8_10", feature = "esplora_a33e97e1")); + if IS_ALL_FEATURES_BUILD || should_version_use_p2p { conf.p2p = P2P::Yes; } let bitcoind = bitcoind::BitcoinD::with_conf(&bitcoind_exe, &conf).unwrap(); diff --git a/electrsd/src/versions.rs b/electrsd/src/versions.rs index 504da5c1..cb48770b 100644 --- a/electrsd/src/versions.rs +++ b/electrsd/src/versions.rs @@ -7,20 +7,21 @@ 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"; +// This version is used when --all-feature tests are run. +#[cfg(feature = "electrs_0_10_6")] +const VERSION: &str = "v0.10.6"; -#[cfg(feature = "esplora_a33e97e1")] -const VERSION: &str = "esplora_a33e97e1a1fc63fa9c20a116bb92579bbf43b254"; +#[cfg(all(feature = "electrs_0_9_11", not(feature = "all_features")))] +const VERSION: &str = "v0.9.11"; -#[cfg(feature = "electrs_0_9_1")] +#[cfg(all(feature = "electrs_0_9_1", not(feature = "all_features")))] const VERSION: &str = "v0.9.1"; -#[cfg(feature = "electrs_0_9_11")] -const VERSION: &str = "v0.9.11"; +#[cfg(all(feature = "electrs_0_8_10", not(feature = "all_features")))] +const VERSION: &str = "v0.8.10"; -#[cfg(feature = "electrs_0_10_6")] -const VERSION: &str = "v0.10.6"; +#[cfg(all(feature = "esplora_a33e97e1", not(feature = "all_features")))] +const VERSION: &str = "esplora_a33e97e1a1fc63fa9c20a116bb92579bbf43b254"; #[cfg(not(any( feature = "electrs_0_8_10", From 032e21e4a68a17454c34b4d60bd375322c8f22ed Mon Sep 17 00:00:00 2001 From: Renato Britto Date: Wed, 13 May 2026 19:45:41 -0300 Subject: [PATCH 5/8] ci: skip electrsd downloads select test features --- .github/workflows/rust.yaml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/rust.yaml b/.github/workflows/rust.yaml index 77f86d93..13f35b17 100644 --- a/.github/workflows/rust.yaml +++ b/.github/workflows/rust.yaml @@ -36,6 +36,7 @@ jobs: runs-on: ubuntu-latest env: BITCOIND_SKIP_DOWNLOAD: "1" + ELECTRSD_SKIP_DOWNLOAD: "1" strategy: fail-fast: false matrix: @@ -61,6 +62,7 @@ jobs: runs-on: ubuntu-latest env: BITCOIND_SKIP_DOWNLOAD: "1" + ELECTRSD_SKIP_DOWNLOAD: "1" strategy: fail-fast: false matrix: @@ -78,6 +80,7 @@ jobs: runs-on: ubuntu-latest env: BITCOIND_SKIP_DOWNLOAD: "1" + ELECTRSD_SKIP_DOWNLOAD: "1" strategy: fail-fast: false matrix: @@ -184,7 +187,7 @@ jobs: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 - uses: dtolnay/rust-toolchain@stable - - run: cd electrsd && cargo test --features ${{ matrix.features }} + - run: cd electrsd && cargo test --no-default-features --features ${{ matrix.features }} test-electrs-esplora: @@ -201,7 +204,7 @@ jobs: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 - uses: dtolnay/rust-toolchain@stable - - run: cd electrsd && cargo test --features ${{ matrix.features }} + - run: cd electrsd && cargo test --no-default-features --features ${{ matrix.features }} test-electrs-no-download: name: Test Electrs no auto-download features @@ -209,6 +212,7 @@ jobs: env: CARGO_TERM_COLOR: always RUST_LOG: debug + ELECTRSD_SKIP_DOWNLOAD: "1" ELECTRS_EXEC: "/home/runner/.cargo-install/electrs/bin/electrs" steps: - uses: dtolnay/rust-toolchain@stable @@ -234,8 +238,10 @@ jobs: uses: baptiste0928/cargo-install@v2 with: crate: electrs + version: 0.10.6 + locked: true - run: "echo $ELECTRS_EXEC" - name: Checkout Crate uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 - - run: cd electrsd && cargo test --features 'bitcoind_25_2,bitcoind_download' + - run: cd electrsd && cargo test --no-default-features --features 'bitcoind_25_2,electrs_0_10_6,bitcoind_download' From dc7dccf1c3c45ae585f42ed86cc298d105b354e3 Mon Sep 17 00:00:00 2001 From: Renato Britto Date: Wed, 13 May 2026 18:43:42 -0300 Subject: [PATCH 6/8] Include electrsd in workspace --- Cargo-minimal.lock | 166 ++++++++++++++++++++++++++++++++++++--- Cargo-recent.lock | 166 ++++++++++++++++++++++++++++++++++++--- Cargo.toml | 4 +- electrsd/Cargo.toml | 6 ++ electrsd/src/lib.rs | 2 +- electrsd/src/versions.rs | 23 +++--- 6 files changed, 337 insertions(+), 30 deletions(-) diff --git a/Cargo-minimal.lock b/Cargo-minimal.lock index 11a685de..a47a18d7 100644 --- a/Cargo-minimal.lock +++ b/Cargo-minimal.lock @@ -17,6 +17,15 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + [[package]] name = "anyhow" version = "1.0.95" @@ -147,7 +156,7 @@ dependencies = [ "bitcoin_hashes", "bitreq", "corepc-client", - "env_logger", + "env_logger 0.9.3", "flate2", "log", "serde_json", @@ -157,6 +166,12 @@ dependencies = [ "zip", ] +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.11.1" @@ -300,6 +315,33 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "electrsd" +version = "0.39.0" +dependencies = [ + "bitcoin_hashes", + "bitcoind", + "bitreq", + "corepc-client", + "electrum-client", + "env_logger 0.10.2", + "log", + "nix", + "zip", +] + +[[package]] +name = "electrum-client" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5059f13888a90486e7268bbce59b175f5f76b1c55e5b9c568ceaa42d2b8507c" +dependencies = [ + "bitcoin", + "log", + "serde", + "serde_json", +] + [[package]] name = "env_logger" version = "0.9.3" @@ -309,6 +351,19 @@ dependencies = [ "log", ] +[[package]] +name = "env_logger" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + [[package]] name = "errno" version = "0.3.10" @@ -494,6 +549,12 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + [[package]] name = "hex-conservative" version = "0.2.1" @@ -527,6 +588,12 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "humantime" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" + [[package]] name = "idna" version = "1.1.0" @@ -558,6 +625,17 @@ dependencies = [ "unicode-joining-type", ] +[[package]] +name = "is-terminal" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" +dependencies = [ + "hermit-abi 0.5.2", + "libc", + "windows-sys 0.61.2", +] + [[package]] name = "itoa" version = "1.0.11" @@ -604,7 +682,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags", + "bitflags 2.11.1", "libc", "redox_syscall", ] @@ -636,6 +714,15 @@ dependencies = [ "libc", ] +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + [[package]] name = "miniz_oxide" version = "0.8.4" @@ -651,7 +738,7 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", "wasi", "windows-sys 0.52.0", @@ -674,6 +761,20 @@ dependencies = [ "tempfile", ] +[[package]] +name = "nix" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset", + "pin-utils", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -704,7 +805,7 @@ version = "0.10.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" dependencies = [ - "bitflags", + "bitflags 2.11.1", "cfg-if", "foreign-types", "libc", @@ -760,6 +861,12 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "pkg-config" version = "0.3.31" @@ -790,7 +897,7 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bb0be07becd10686a0bb407298fb425360a5c44a663774406340c59a22de4ce" dependencies = [ - "bitflags", + "bitflags 2.11.1", "lazy_static", "num-traits", "rand", @@ -859,7 +966,30 @@ version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ - "bitflags", + "bitflags 2.11.1", +] + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", ] [[package]] @@ -903,7 +1033,7 @@ version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ - "bitflags", + "bitflags 2.11.1", "errno", "libc", "linux-raw-sys", @@ -997,7 +1127,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags", + "bitflags 2.11.1", "core-foundation 0.9.4", "core-foundation-sys", "libc", @@ -1010,7 +1140,7 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags", + "bitflags 2.11.1", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -1144,6 +1274,15 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "tiny_http" version = "0.12.0" @@ -1330,6 +1469,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/Cargo-recent.lock b/Cargo-recent.lock index 11a685de..a47a18d7 100644 --- a/Cargo-recent.lock +++ b/Cargo-recent.lock @@ -17,6 +17,15 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + [[package]] name = "anyhow" version = "1.0.95" @@ -147,7 +156,7 @@ dependencies = [ "bitcoin_hashes", "bitreq", "corepc-client", - "env_logger", + "env_logger 0.9.3", "flate2", "log", "serde_json", @@ -157,6 +166,12 @@ dependencies = [ "zip", ] +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.11.1" @@ -300,6 +315,33 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "electrsd" +version = "0.39.0" +dependencies = [ + "bitcoin_hashes", + "bitcoind", + "bitreq", + "corepc-client", + "electrum-client", + "env_logger 0.10.2", + "log", + "nix", + "zip", +] + +[[package]] +name = "electrum-client" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5059f13888a90486e7268bbce59b175f5f76b1c55e5b9c568ceaa42d2b8507c" +dependencies = [ + "bitcoin", + "log", + "serde", + "serde_json", +] + [[package]] name = "env_logger" version = "0.9.3" @@ -309,6 +351,19 @@ dependencies = [ "log", ] +[[package]] +name = "env_logger" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + [[package]] name = "errno" version = "0.3.10" @@ -494,6 +549,12 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + [[package]] name = "hex-conservative" version = "0.2.1" @@ -527,6 +588,12 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "humantime" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" + [[package]] name = "idna" version = "1.1.0" @@ -558,6 +625,17 @@ dependencies = [ "unicode-joining-type", ] +[[package]] +name = "is-terminal" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" +dependencies = [ + "hermit-abi 0.5.2", + "libc", + "windows-sys 0.61.2", +] + [[package]] name = "itoa" version = "1.0.11" @@ -604,7 +682,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags", + "bitflags 2.11.1", "libc", "redox_syscall", ] @@ -636,6 +714,15 @@ dependencies = [ "libc", ] +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + [[package]] name = "miniz_oxide" version = "0.8.4" @@ -651,7 +738,7 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", "wasi", "windows-sys 0.52.0", @@ -674,6 +761,20 @@ dependencies = [ "tempfile", ] +[[package]] +name = "nix" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset", + "pin-utils", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -704,7 +805,7 @@ version = "0.10.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" dependencies = [ - "bitflags", + "bitflags 2.11.1", "cfg-if", "foreign-types", "libc", @@ -760,6 +861,12 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "pkg-config" version = "0.3.31" @@ -790,7 +897,7 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bb0be07becd10686a0bb407298fb425360a5c44a663774406340c59a22de4ce" dependencies = [ - "bitflags", + "bitflags 2.11.1", "lazy_static", "num-traits", "rand", @@ -859,7 +966,30 @@ version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ - "bitflags", + "bitflags 2.11.1", +] + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", ] [[package]] @@ -903,7 +1033,7 @@ version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ - "bitflags", + "bitflags 2.11.1", "errno", "libc", "linux-raw-sys", @@ -997,7 +1127,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags", + "bitflags 2.11.1", "core-foundation 0.9.4", "core-foundation-sys", "libc", @@ -1010,7 +1140,7 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags", + "bitflags 2.11.1", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -1144,6 +1274,15 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "tiny_http" version = "0.12.0" @@ -1330,6 +1469,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index 50ef533c..9f9af137 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace] -members = ["bitcoind", "bitreq", "client", "fuzz", "jsonrpc", "types"] -exclude = ["integration_test", "verify", "electrsd"] +members = ["bitcoind", "bitreq", "client", "electrsd", "fuzz", "jsonrpc", "types"] +exclude = ["integration_test", "verify"] resolver = "2" [workspace.metadata.rbmt.toolchains] diff --git a/electrsd/Cargo.toml b/electrsd/Cargo.toml index 558d419e..2e00c88f 100644 --- a/electrsd/Cargo.toml +++ b/electrsd/Cargo.toml @@ -32,6 +32,8 @@ zip = { version = "0.6", default-features = false, optional = true, features = [ bitreq = { version = "0.3.5", path = "../bitreq", optional = true, features = ["https"] } [features] +default = ["electrs_0_10_6"] + legacy = [] # download is not supposed to be used directly only through selecting one of the version feature @@ -63,6 +65,10 @@ bitcoind_0_17_2 = ["bitcoind/0_17_2"] # This flag should never be manually set. Used to handle `--all-features` was used. all_features = [] +[package.metadata.docs.rs] +features = ["electrs_0_10_6"] +rustdoc-args = ["--cfg", "docsrs"] + [package.metadata.rbmt.lint] # The electrsd crate requires a version feature to compile features = ["electrs_0_10_6"] diff --git a/electrsd/src/lib.rs b/electrsd/src/lib.rs index 00a6a631..a8357314 100644 --- a/electrsd/src/lib.rs +++ b/electrsd/src/lib.rs @@ -309,7 +309,7 @@ impl Drop for ElectrsD { /// 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() { + if std::env::var_os("ELECTRSD_SKIP_DOWNLOAD").is_none() { Some(format!("{}/electrs/{}/electrs", env!("OUT_DIR"), versions::electrs_name(),)) } else { None diff --git a/electrsd/src/versions.rs b/electrsd/src/versions.rs index cb48770b..8232761e 100644 --- a/electrsd/src/versions.rs +++ b/electrsd/src/versions.rs @@ -1,3 +1,14 @@ +// An explicit version of Bitcoin Core must be selected by enabling some feature. +// We check this here instead of in `lib.rs` because this file is included in `build.rs`. +#[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", +)))] +compile_error!("enable a feature in order to select the version of electrs to use"); + #[cfg(target_os = "macos")] const OS: &str = "macos"; @@ -23,6 +34,8 @@ const VERSION: &str = "v0.8.10"; #[cfg(all(feature = "esplora_a33e97e1", not(feature = "all_features")))] const VERSION: &str = "esplora_a33e97e1a1fc63fa9c20a116bb92579bbf43b254"; +/// This is meaningless but we need it otherwise we can't get far enough into +/// the build process to trigger the `compile_error!` in `./versions.rs`. #[cfg(not(any( feature = "electrs_0_8_10", feature = "electrs_0_9_1", @@ -30,14 +43,6 @@ const VERSION: &str = "esplora_a33e97e1a1fc63fa9c20a116bb92579bbf43b254"; 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", -)); +const VERSION: &str = "never-used"; pub fn electrs_name() -> String { format!("electrs_{}_{}", OS, VERSION) } From dcbfdbfc59700f90cc6ea7ebf85ac9972d63de53 Mon Sep 17 00:00:00 2001 From: Renato Britto Date: Thu, 14 May 2026 16:25:31 -0300 Subject: [PATCH 7/8] electrsd: refactor build script with anyhow context Mirror the bitcoind build script. --- Cargo-minimal.lock | 1 + Cargo-recent.lock | 1 + electrsd/Cargo.toml | 3 ++- electrsd/build.rs | 50 ++++++++++++++++++++++----------------------- 4 files changed, 28 insertions(+), 27 deletions(-) diff --git a/Cargo-minimal.lock b/Cargo-minimal.lock index a47a18d7..154b012e 100644 --- a/Cargo-minimal.lock +++ b/Cargo-minimal.lock @@ -319,6 +319,7 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" name = "electrsd" version = "0.39.0" dependencies = [ + "anyhow", "bitcoin_hashes", "bitcoind", "bitreq", diff --git a/Cargo-recent.lock b/Cargo-recent.lock index a47a18d7..154b012e 100644 --- a/Cargo-recent.lock +++ b/Cargo-recent.lock @@ -319,6 +319,7 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" name = "electrsd" version = "0.39.0" dependencies = [ + "anyhow", "bitcoin_hashes", "bitcoind", "bitreq", diff --git a/electrsd/Cargo.toml b/electrsd/Cargo.toml index 2e00c88f..0fb6b461 100644 --- a/electrsd/Cargo.toml +++ b/electrsd/Cargo.toml @@ -24,6 +24,7 @@ nix = { version = "0.25.0" } env_logger = { version = "0.10" } [build-dependencies] +anyhow = { version = "1.0.66", default-features = false, features = ["std"], optional = true } bitcoin_hashes = { version = "0.14", optional = true } zip = { version = "0.6", default-features = false, optional = true, features = [ "bzip2", @@ -37,7 +38,7 @@ default = ["electrs_0_10_6"] legacy = [] # download is not supposed to be used directly only through selecting one of the version feature -download = ["bitcoin_hashes", "zip", "bitreq"] +download = ["anyhow", "bitcoin_hashes", "zip", "bitreq"] esplora_a33e97e1 = ["download", "legacy"] electrs_0_8_10 = ["download"] diff --git a/electrsd/build.rs b/electrsd/build.rs index 1c320b95..6c6623cf 100644 --- a/electrsd/build.rs +++ b/electrsd/build.rs @@ -1,8 +1,9 @@ -#[cfg(not(feature = "download"))] -fn main() {} +fn main() { download::start().unwrap(); } -#[cfg(feature = "download")] -fn main() { download::download() } +#[cfg(any(docsrs, not(feature = "download")))] +mod download { + pub(crate) fn start() -> Result<(), ()> { Ok(()) } +} #[cfg(feature = "download")] mod download { @@ -19,36 +20,30 @@ mod download { 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(|_| ())?; + fn get_expected_sha256(filename: &str) -> anyhow::Result { + let file = File::open("sha256")?; for line in BufReader::new(file).lines().map_while(Result::ok) { let tokens: Vec<_> = line.split(" ").collect(); if tokens.len() == 2 && filename == tokens[1] { - return sha256::Hash::from_str(tokens[0]).map_err(|_| ()); + return Ok(sha256::Hash::from_str(tokens[0]).unwrap()); } } - Err(()) + panic!("no sha256 entry for {} in electrsd/sha256", filename); } - pub fn download() { + pub(crate) fn start() -> anyhow::Result<()> { if std::env::var_os("ELECTRSD_SKIP_DOWNLOAD").is_some() { - return; + return Ok(()); } - 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 expected_hash = get_expected_sha256(&download_filename)?; 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); @@ -56,20 +51,23 @@ mod download { std::env::var("ELECTRSD_DOWNLOAD_ENDPOINT").unwrap_or(GITHUB_URL.to_string()); let url = format!("{}/{}", download_endpoint, download_filename); - let downloaded_bytes = bitreq::get(url).send().unwrap().into_bytes(); + let downloaded_bytes = bitreq::get(url.clone()).send()?.into_bytes(); let downloaded_hash = sha256::Hash::hash(&downloaded_bytes); - assert_eq!(expected_hash, downloaded_hash); + assert_eq!(expected_hash, downloaded_hash, "expected hash of {} is not matching", url); 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(); - + let mut archive = zip::ZipArchive::new(cursor)?; + let mut file = archive.by_index(0)?; + let parent = destination_filename.parent().unwrap(); + std::fs::create_dir_all(parent)?; + let mut outfile = std::fs::File::create(&destination_filename)?; std::io::copy(&mut file, &mut outfile).unwrap(); - std::fs::set_permissions(&destination_filename, std::fs::Permissions::from_mode(0o755)) - .unwrap(); + std::fs::set_permissions( + &destination_filename, + std::fs::Permissions::from_mode(0o755), + )?; } + Ok(()) } } From bfe8abc89f17b1903240765b4e32e3121e060b22 Mon Sep 17 00:00:00 2001 From: Renato Britto Date: Thu, 14 May 2026 16:34:24 -0300 Subject: [PATCH 8/8] electrsd: fix README examples The previous examples would not run. --- electrsd/README.md | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/electrsd/README.md b/electrsd/README.md index 697b69a8..141fe16b 100644 --- a/electrsd/README.md +++ b/electrsd/README.md @@ -8,7 +8,7 @@ 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 electrsd = electrsd::ElectrsD::new("/usr/local/bin/electrs", &bitcoind).unwrap(); let header = electrsd.client.block_headers_subscribe().unwrap(); assert_eq!(header.height, 0); ``` @@ -24,10 +24,19 @@ electrsd = { version= "0.23", features = ["bitcoind_30_2", "bitcoin_download", " 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(); +use bitcoind::P2P; +use electrsd::electrum_client::ElectrumApi; + +fn main() { + let bitcoind_exe = bitcoind::downloaded_exe_path().expect("bitcoind version feature must be enabled"); + let mut conf = bitcoind::Conf::default(); + conf.p2p = P2P::Yes; + let bitcoind = bitcoind::BitcoinD::with_conf(&bitcoind_exe, &conf).unwrap(); + let electrs_exe = electrsd::downloaded_exe_path().expect("electrs version feature must be enabled"); + let electrsd = electrsd::ElectrsD::new(&electrs_exe, &bitcoind).unwrap(); + let header = electrsd.client.block_headers_subscribe().unwrap(); + assert_eq!(header.height, 1); +} ``` When the `ELECTRSD_DOWNLOAD_ENDPOINT`/`BITCOIND_DOWNLOAD_ENDPOINT` environment variables are set, @@ -39,9 +48,12 @@ When you don't use the auto-download feature you have the following options: - 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(); -} +use bitcoind::P2P; + +let mut conf = bitcoind::Conf::default(); +conf.p2p = P2P::Yes; +let bitcoind = bitcoind::BitcoinD::with_conf(bitcoind::exe_path().unwrap(), &conf).unwrap(); +let electrsd = electrsd::ElectrsD::new(electrsd::exe_path().unwrap(), &bitcoind).unwrap(); ``` Startup options could be configured via the `Conf` struct using `electrsD::with_conf` or `electrsD::from_downloaded_with_conf`.