|
| 1 | +[](https://github.com/RCasatta/bitcoind/blob/master/LICENSE) |
| 2 | +[](https://crates.io/crates/bitcoind) |
| 3 | +[](https://docs.rs/bitcoind) |
| 4 | + |
| 5 | +# Bitcoind |
| 6 | + |
| 7 | +Utility to run a regtest bitcoind process, useful in integration testing environment. |
| 8 | + |
| 9 | +When the auto-download feature is selected by activating one of the version feature, such as `25_1` |
| 10 | +for bitcoin core 25.1, starting a regtest node is as simple as that: |
| 11 | + |
| 12 | +```rust |
| 13 | +// the download feature is enabled whenever a specific version is enabled, for example `25_1` or `24_0_1` |
| 14 | +#[cfg(feature = "download")] |
| 15 | +{ |
| 16 | + use bitcoincore_rpc::RpcApi; |
| 17 | + let bitcoind = bitcoind::BitcoinD::from_downloaded().unwrap(); |
| 18 | + assert_eq!(0, bitcoind.client.get_blockchain_info().unwrap().blocks); |
| 19 | +} |
| 20 | +``` |
| 21 | + |
| 22 | +The build script will automatically download the bitcoin core version 25.1 from [bitcoin core](https://bitcoincore.org), |
| 23 | +verify the hashes and place it in the build directory for this crate. If you wish to download from an |
| 24 | +alternate location, for example locally for CI, use the `BITCOIND_DOWNLOAD_ENDPOINT` env var. |
| 25 | + |
| 26 | +When you don't use the auto-download feature you have the following options: |
| 27 | + |
| 28 | +* have `bitcoind` executable in the `PATH` |
| 29 | +* provide the `bitcoind` executable via the `BITCOIND_EXE` env var |
| 30 | + |
| 31 | +```rust |
| 32 | +use bitcoincore_rpc::RpcApi; |
| 33 | +if let Ok(exe_path) = bitcoind::exe_path() { |
| 34 | + let bitcoind = bitcoind::BitcoinD::new(exe_path).unwrap(); |
| 35 | + assert_eq!(0, bitcoind.client.get_blockchain_info().unwrap().blocks); |
| 36 | +} |
| 37 | +``` |
| 38 | + |
| 39 | +Startup options could be configured via the [`Conf`] struct using [`BitcoinD::with_conf`] or |
| 40 | +[`BitcoinD::from_downloaded_with_conf`] |
| 41 | + |
| 42 | +## Issues with traditional approach |
| 43 | + |
| 44 | +I used integration testing based on external bash script launching needed external processes, there |
| 45 | +are many issues with this approach like: |
| 46 | + |
| 47 | +* External script may interfere with local development environment [1](https://github.com/rust-bitcoin/rust-bitcoincore-rpc/blob/200fc8247c1896709a673b82a89ca0da5e7aa2ce/integration_test/run.sh#L9) |
| 48 | +* Use of a single huge test to test everything [2](https://github.com/rust-bitcoin/rust-bitcoincore-rpc/blob/200fc8247c1896709a673b82a89ca0da5e7aa2ce/integration_test/src/main.rs#L122-L203) |
| 49 | +* If test are separated, a failing test may fail to leave a clean situation, causing other test to |
| 50 | +fail (because of the initial situation, not a real failure) |
| 51 | +* bash script are hard, especially support different OS and versions |
| 52 | + |
| 53 | +## Features |
| 54 | + |
| 55 | + * It waits until bitcoind daemon become ready to accept RPC commands |
| 56 | + * `bitcoind` use a temporary directory as datadir. You can specify the root of your temp directories |
| 57 | + so that you have node's datadir in a RAM disk (eg `/dev/shm`) |
| 58 | + * Free ports are asked to the OS. Since you can't reserve the given port, a low probability race |
| 59 | + condition is still possible, for this reason the process is tried to be spawn 3 times with different |
| 60 | + ports. |
| 61 | + * The process is killed when the struct goes out of scope no matter how the test finishes |
| 62 | + * Allows easy spawning of dependent processes like: |
| 63 | + - [electrs](https://github.com/RCasatta/electrsd) |
| 64 | + - [cln](https://github.com/RCasatta/lightningd) |
| 65 | + - [elements](https://github.com/RCasatta/elementsd) |
| 66 | + |
| 67 | +Thanks to these features every `#[test]` could easily run isolated with its own environment. |
| 68 | + |
| 69 | +## Doc |
| 70 | + |
| 71 | +To build docs: |
| 72 | + |
| 73 | +```sh |
| 74 | +RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --features download,doc --open |
| 75 | +``` |
| 76 | + |
| 77 | +## MSRV |
| 78 | + |
| 79 | +The MSRV is 1.56.1 for version 0.35.* |
| 80 | + |
| 81 | +Note: to respect 1.56.1 MSRV you need to use and older version of some dependencies, in CI the below |
| 82 | +dependency versions are pinned: |
| 83 | + |
| 84 | +```sh |
| 85 | +cargo update |
| 86 | +cargo update -p tempfile --precise 3.3.0 |
| 87 | +cargo update -p log --precise 0.4.18 |
| 88 | +``` |
| 89 | + |
| 90 | +Pinning in `Cargo.toml` is avoided because it could cause |
| 91 | +compilation issues downstream. |
| 92 | + |
| 93 | +## Nix |
| 94 | + |
| 95 | +For reproducibility reasons, Nix build scripts cannot hit the internet, but the |
| 96 | +auto-download feature does exactly that. To successfully build under Nix the |
| 97 | +user must provide the tarball locally and specify its location via the |
| 98 | +`BITCOIND_TARBALL_FILE` env var. |
| 99 | + |
| 100 | +Another option is to specify the `BITCOIND_SKIP_DOWNLOAD` env var and provide the |
| 101 | +executable via the `PATH`. |
| 102 | + |
| 103 | +Alternatively, use the dep without auto-download feature. |
| 104 | + |
| 105 | +## Used by |
| 106 | + |
| 107 | +* [firma](https://github.com/RCasatta/firma/) |
| 108 | +* [payjoin](https://github.com/Kixunil/payjoin) |
| 109 | +* [rust-miniscript](https://github.com/rust-bitcoin/rust-miniscript/tree/4a3ba11c2fd5063be960741d557f3f7a28041e1f/bitcoind-tests) |
| 110 | + |
| 111 | +### Via bdk dependency |
| 112 | + |
| 113 | +* [gun](https://github.com/LLFourn/gun) |
| 114 | + |
| 115 | +### Via electrsd dependency: |
| 116 | + |
| 117 | +* [bdk](https://github.com/bitcoindevkit/bdk) |
| 118 | +* [BEWallet](https://github.com/LeoComandini/BEWallet) |
| 119 | +* [gdk rust](https://github.com/Blockstream/gdk/blob/master/subprojects/gdk_rust/) |
0 commit comments