Skip to content

Commit

Permalink
Add bitcoind-tests crate
Browse files Browse the repository at this point in the history
Add a crate for testing against Bitcoin Core using `bitcoind`. Only
includes basic infrastructure.
  • Loading branch information
tcharding committed Feb 6, 2024
1 parent 5bbcff6 commit 85040b4
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 1 deletion.
13 changes: 13 additions & 0 deletions bitcoind-tests/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "bitcoind-tests"
version = "0.1.0"
authors = ["Tobin C. Harding <[email protected]>"]
license = "CC0-1.0"
edition = "2021"

# This crate is only used for testing, no features or dependencies.

[dev-dependencies]
anyhow = "1"
bitcoind = { version = "0.34.1", features = ["25_1"] }
psbt-v2 = { path = "..", features = ["std"] }
3 changes: 3 additions & 0 deletions bitcoind-tests/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
println!("\nTo run the tests use cargo test instead of cargo run.\n");
}
70 changes: 70 additions & 0 deletions bitcoind-tests/tests/client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
use bitcoind::bitcoincore_rpc::bitcoincore_rpc_json::{AddressType, GetBlockchainInfoResult};
use bitcoind::bitcoincore_rpc::RpcApi;
use bitcoind::BitcoinD;
use psbt_v2::bitcoin::{Address, Amount, Network, Txid};

const NETWORK: Network = Network::Regtest;

/// A custom bitcoind client.
pub struct Client {
bitcoind: BitcoinD,
}

impl Client {
/// Creates a new [`Client`].
pub fn new() -> anyhow::Result<Self> {
let bitcoind = BitcoinD::from_downloaded()?;
let client = Client { bitcoind };

Ok(client)
}

/// Calls through to bitcoincore_rpc client.
pub fn get_blockchain_info(&self) -> anyhow::Result<GetBlockchainInfoResult> {
let client = &self.bitcoind.client;
Ok(client.get_blockchain_info()?)
}

/// Gets an address controlled by the currently loaded Bitcoin Core wallet (via `bitcoind`).
pub fn core_wallet_controlled_address(&self) -> anyhow::Result<Address> {
let client = &self.bitcoind.client;
let label = None;
let address_type = Some(AddressType::Bech32m);
let address = client.get_new_address(label, address_type)?.require_network(NETWORK)?;
Ok(address)
}

/// Funds the bitcoind wallet with a spendable 50 BTC utxo.
pub fn fund(&self) -> anyhow::Result<()> {
let client = &self.bitcoind.client;
// Generate to an address controlled by the bitcoind wallet and wait for funds to mature.
let address = self.core_wallet_controlled_address()?;
let _ = client.generate_to_address(101, &address)?;

Ok(())
}

/// Send `amount` to `address` setting all other `bitcoincore_prc::send_to_address` args to `None`.
pub fn send(&self, amount: Amount, address: &Address) -> anyhow::Result<Txid> {
let client = &self.bitcoind.client;

let comment = None;
let comment_to = None;
let subtract_fee = None;
let replacable = None;
let confirmation_target = None;
let estimate_mode = None;

let txid = client.send_to_address(
address,
amount,
comment,
comment_to,
subtract_fee,
replacable,
confirmation_target,
estimate_mode,
)?;
Ok(txid)
}
}
40 changes: 40 additions & 0 deletions bitcoind-tests/tests/infrastructure.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//! Test the bitcoind infrastructure.

mod client;

use client::Client;
use psbt_v2::bitcoin::Amount;

#[track_caller]
fn client() -> Client {
let client = Client::new().expect("failed to create client");
// Sanity check.
assert_eq!(0, client.get_blockchain_info().unwrap().blocks);

client.fund().expect("failed to fund client");
client
}

#[test]
fn bitcoind_get_core_wallet_controlled_address() {
let client = client();
let address = client.core_wallet_controlled_address().expect("get_new_address failed");
println!("address: {}", address);
}

#[test]
fn bitcoind_fund_core_controlled_wallet() {
let client = client();
assert!(client.fund().is_ok())
}

#[test]
fn bitcoind_send() {
let client = client();

let address = client.core_wallet_controlled_address().expect("get_new_address failed");
let amount = Amount::ONE_BTC;

let txid = client.send(amount, &address).expect("send failed");
println!("txid: {}", txid);
}
3 changes: 2 additions & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ build:

# Cargo test everything.
test:
cargo test --all --all-targets --all-features
cargo test --all-targets --all-features
cd bitcoind-tests; cargo test

# Lint everything.
lint:
Expand Down

0 comments on commit 85040b4

Please sign in to comment.