|
| 1 | +[](https://github.com/RCasatta/electrsd/blob/master/LICENSE) |
| 2 | +[](https://crates.io/crates/electrsd) |
| 3 | + |
| 4 | +# Electrsd |
| 5 | + |
| 6 | +Utility to run a regtest [electrs](https://github.com/romanz/electrs/) process connected to a given [bitcoind](https://github.com/RCasatta/bitcoind) instance, |
| 7 | +useful in integration testing environment. |
| 8 | + |
| 9 | +```rust |
| 10 | +let bitcoind = bitcoind::BitcoinD::new("/usr/local/bin/bitcoind").unwrap(); |
| 11 | +let electrsd = electrsd::ElectrsD::new("/usr/local/bin/electrs", bitcoind).unwrap(); |
| 12 | +let header = electrsd.client.block_headers_subscribe().unwrap(); |
| 13 | +assert_eq!(header.height, 0); |
| 14 | +``` |
| 15 | + |
| 16 | +## Automatic binaries download |
| 17 | + |
| 18 | +In your project Cargo.toml, activate the following features |
| 19 | + |
| 20 | +```yml |
| 21 | +electrsd = { version= "0.23", features = ["corepc-node_23_1", "electrs_0_9_1"] } |
| 22 | +``` |
| 23 | + |
| 24 | +Then use it: |
| 25 | + |
| 26 | +```rust |
| 27 | +let bitcoind_exe = bitcoind::downloaded_exe_path().expect("bitcoind version feature must be enabled"); |
| 28 | +let bitcoind = bitcoind::BitcoinD::new(bitcoind_exe).unwrap(); |
| 29 | +let electrs_exe = electrsd::downloaded_exe_path().expect("electrs version feature must be enabled"); |
| 30 | +let electrsd = electrsd::ElectrsD::new(electrs_exe, bitcoind).unwrap(); |
| 31 | +``` |
| 32 | + |
| 33 | +When the `ELECTRSD_DOWNLOAD_ENDPOINT`/`BITCOIND_DOWNLOAD_ENDPOINT` environment variables are set, |
| 34 | +`electrsd`/`bitcoind` will try to download the binaries from the given endpoints. |
| 35 | + |
| 36 | +When you don't use the auto-download feature you have the following options: |
| 37 | + |
| 38 | +- have `electrs` executable in the `PATH` |
| 39 | +- provide the `electrs` executable via the `ELECTRS_EXEC` env var |
| 40 | + |
| 41 | +```rust |
| 42 | +if let Ok(exe_path) = electrsd::exe_path() { |
| 43 | + let electrsd = electrsd::electrsD::new(exe_path).unwrap(); |
| 44 | +} |
| 45 | +``` |
| 46 | + |
| 47 | +Startup options could be configured via the `Conf` struct using `electrsD::with_conf` or `electrsD::from_downloaded_with_conf`. |
| 48 | + |
| 49 | +## Nix |
| 50 | + |
| 51 | +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). |
| 52 | + |
| 53 | +## Issues with traditional approach |
| 54 | + |
| 55 | +I used integration testing based on external bash script launching needed external processes, there are many issues with this approach like: |
| 56 | + |
| 57 | +* External script may interfere with local development environment https://github.com/rust-bitcoin/rust-bitcoincore-rpc/blob/200fc8247c1896709a673b82a89ca0da5e7aa2ce/integration_test/run.sh#L9 |
| 58 | +* 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 |
| 59 | +* 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) |
| 60 | +* bash script are hard, especially support different OS and versions |
| 61 | + |
| 62 | +## Features |
| 63 | + |
| 64 | + * electrsd use a temporary directory as db dir |
| 65 | + * A free port is asked to the OS (a very low probability race condition is still possible) |
| 66 | + * The process is killed when the struct goes out of scope no matter how the test finishes |
| 67 | + * 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: |
| 68 | + * [electrs 0.10.6](https://github.com/romanz/electrs/releases/tag/v0.10.6) (feature=electrs_0_10_6) |
| 69 | + * [electrs 0.9.11](https://github.com/romanz/electrs/releases/tag/v0.9.11) (feature=electrs_0_9_11) |
| 70 | + * [electrs 0.9.1](https://github.com/romanz/electrs/releases/tag/v0.9.1) (feature=electrs_0_9_1) |
| 71 | + * [electrs 0.8.10](https://github.com/romanz/electrs/releases/tag/v0.8.10) (feature=electrs_0_8_10) |
| 72 | + * [electrs esplora](https://github.com/Blockstream/electrs/tree/a33e97e1a1fc63fa9c20a116bb92579bbf43b254) (feature=esplora_a33e97e1) |
| 73 | + |
| 74 | +Thanks to these features every `#[test]` could easily run isolated with its own environment |
| 75 | + |
| 76 | +## Deprecations |
| 77 | + |
| 78 | +- Starting from version `0.26` the env var `ELECTRS_EXE` is deprecated in favor of `ELECTRS_EXEC`. |
| 79 | + |
| 80 | + |
| 81 | +## Used by |
| 82 | + |
| 83 | + * [bdk](https://github.com/bitcoindevkit/bdk) |
| 84 | + * [BEWallet](https://github.com/LeoComandini/BEWallet) |
| 85 | + * [gdk rust](https://github.com/Blockstream/gdk/blob/master/subprojects/gdk_rust/) |
| 86 | + * [lwk](https://github.com/Blockstream/lwk) |
0 commit comments