Skip to content

Commit

Permalink
Depend on the new bitcoind-json-rpc group of crates
Browse files Browse the repository at this point in the history
There is an effort to improve the state of affairs in regards to
integration testing extensively against multiple versions of Bitcoin
Core. As part of this do:

- Depend on the new `rust-bitcoind-json-rpc` crates
- Run the integration tests against most versions of Core since 0.17.1

(Note the latest supported version is currently 26.0)

This patch effects integration testing only and should hopefully help
with our upgrade process because I will personally make sure the new
crates are ready and tested during the rust-bitcoin RC cycle.
  • Loading branch information
tcharding committed Jun 20, 2024
1 parent 9e1b3cd commit aab9e32
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 68 deletions.
45 changes: 31 additions & 14 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,39 @@ jobs:
DO_LINT: true
run: ./contrib/test.sh

Int-tests:
name: Integration tests
Integration: # 1 job for each bitcoind version we support.
name: Integration tests - stable toolchain
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
feature:
[
"26_0",
"25_2",
"25_1",
"25_0",
"24_2",
"24_1",
"24_0_1",
"23_2",
"23_1",
"23_0",
"22_1",
"22_0",
"0_21_2",
"0_20_2",
"0_19_1",
"0_18_1",
"0_17_1",
]
steps:
- name: Checkout Crate
uses: actions/checkout@v2
- name: Checkout Toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- name: Running integration tests
env:
DO_BITCOIND_TESTS: true
run: ./contrib/test.sh
- name: "Checkout repo"
uses: actions/checkout@v4
- name: "Select toolchain"
uses: dtolnay/rust-toolchain@stable
- name: "Run integration tests"
run: cd bitcoind-tests && cargo test --features=${{ matrix.feature }}

Tests:
name: Tests
Expand Down
22 changes: 21 additions & 1 deletion bitcoind-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,26 @@ publish = false

[dependencies]
miniscript = {path = "../"}
bitcoind = { version = "0.36.0" }
bitcoind = { package = "bitcoind-json-rpc-regtest", version = "0.3.0" }
actual-rand = { package = "rand", version = "0.8.4"}
secp256k1 = {version = "0.29.0", features = ["rand-std"]}

[features]
# Enable the same feature in `bitcoind`.
"26_0" = ["bitcoind/26_0"]
"25_2" = ["bitcoind/25_2"]
"25_1" = ["bitcoind/25_1"]
"25_0" = ["bitcoind/25_0"]
"24_2" = ["bitcoind/24_2"]
"24_1" = ["bitcoind/24_1"]
"24_0_1" = ["bitcoind/24_0_1"]
"23_2" = ["bitcoind/23_2"]
"23_1" = ["bitcoind/23_1"]
"23_0" = ["bitcoind/23_0"]
"22_1" = ["bitcoind/22_1"]
"22_0" = ["bitcoind/22_0"]
"0_21_2" = ["bitcoind/0_21_2"]
"0_20_2" = ["bitcoind/0_20_2"]
"0_19_1" = ["bitcoind/0_19_1"]
"0_18_1" = ["bitcoind/0_18_1"]
"0_17_1" = ["bitcoind/0_17_1"]
19 changes: 11 additions & 8 deletions bitcoind-tests/tests/setup/mod.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
extern crate miniscript;

use bitcoind::bitcoincore_rpc::RpcApi;
use bitcoind::BitcoinD;
use miniscript::bitcoin;
use bitcoind::client::bitcoin;

pub mod test_util;

// Launch an instance of bitcoind with
pub fn setup() -> BitcoinD {
pub fn setup() -> bitcoind::BitcoinD {
// Create env var BITCOIND_EXE_PATH to point to the ../bitcoind/bin/bitcoind binary
let key = "BITCOIND_EXE";
if std::env::var(key).is_err() {
Expand All @@ -29,13 +27,18 @@ pub fn setup() -> BitcoinD {
let bitcoind = bitcoind::BitcoinD::new(exe_path).unwrap();
let cl = &bitcoind.client;
// generate to an address by the wallet. And wait for funds to mature
let addr = cl.get_new_address(None, None).unwrap().assume_checked();
let addr = cl.new_address().unwrap();
let blks = cl.generate_to_address(101, &addr).unwrap();
assert_eq!(blks.len(), 101);
assert_eq!(blks.0.len(), 101);

let balance = cl
.get_balance()
.expect("failed to get balance")
.balance()
.unwrap();
assert_eq!(
cl.get_balance(Some(1) /*min conf*/, None).unwrap(),
bitcoin::Amount::from_sat(100_000_000 * 50)
balance,
bitcoin::Amount::from_sat(100_000_000 * 50),
);
bitcoind
}
49 changes: 22 additions & 27 deletions bitcoind-tests/tests/test_cpp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use bitcoin::psbt::Psbt;
use bitcoin::{
psbt, secp256k1, transaction, Amount, OutPoint, Sequence, Transaction, TxIn, TxOut, Txid,
};
use bitcoind::bitcoincore_rpc::{json, Client, RpcApi};
use bitcoind::{Client, AddressType};
use miniscript::bitcoin::absolute;
use miniscript::psbt::PsbtExt;
use miniscript::{bitcoin, DefiniteDescriptorKey, Descriptor};
Expand Down Expand Up @@ -52,11 +52,12 @@ fn btc<F: Into<f64>>(btc: F) -> Amount { Amount::from_btc(btc.into()).unwrap() }
// Ideally, we should find by scriptPubkey, but this
// works for temp test case
fn get_vout(cl: &Client, txid: Txid, value: Amount) -> (OutPoint, TxOut) {
let tx = cl
.get_transaction(&txid, None)
.unwrap()
.transaction()
.unwrap();
let model = cl.get_transaction(txid)
.expect("rpc call failed")
.into_model()
.expect("conversion to model type failed");
let tx = model.tx;

for (i, txout) in tx.output.into_iter().enumerate() {
if txout.value == value {
return (OutPoint::new(txid, i as u32), txout);
Expand All @@ -72,32 +73,25 @@ pub fn test_from_cpp_ms(cl: &Client, testdata: &TestData) {
let pks = &testdata.pubdata.pks;
// Generate some blocks
let blocks = cl
.generate_to_address(500, &cl.get_new_address(None, None).unwrap().assume_checked())
.generate_to_address(500, &cl.new_address().unwrap())
.unwrap();
assert_eq!(blocks.len(), 500);
assert_eq!(blocks.0.len(), 500);

// Next send some btc to each address corresponding to the miniscript
let mut txids = vec![];
for wsh in desc_vec.iter() {
let txid = cl
.send_to_address(
&wsh.address(bitcoin::Network::Regtest).unwrap(),
btc(1),
None,
None,
None,
None,
None,
None,
)
.unwrap();
.send_to_address(&wsh.address(bitcoin::Network::Regtest).unwrap(), btc(1))
.expect("rpc call failed")
.txid()
.expect("conversion to model failed");
txids.push(txid);
}
// Wait for the funds to mature.
let blocks = cl
.generate_to_address(50, &cl.get_new_address(None, None).unwrap().assume_checked())
.generate_to_address(50, &cl.new_address().unwrap())
.unwrap();
assert_eq!(blocks.len(), 50);
assert_eq!(blocks.0.len(), 50);
// Create a PSBT for each transaction.
// Spend one input and spend one output for simplicity.
let mut psbts = vec![];
Expand Down Expand Up @@ -131,9 +125,8 @@ pub fn test_from_cpp_ms(cl: &Client, testdata: &TestData) {
// the node wallet tracks the receiving transaction
// and we can check it by gettransaction RPC.
let addr = cl
.get_new_address(None, Some(json::AddressType::Bech32))
.unwrap()
.assume_checked();
.new_address_with_type(AddressType::Bech32)
.unwrap();
psbt.unsigned_tx.output.push(TxOut {
value: Amount::from_sat(99_999_000),
script_pubkey: addr.script_pubkey(),
Expand Down Expand Up @@ -215,19 +208,21 @@ pub fn test_from_cpp_ms(cl: &Client, testdata: &TestData) {
// Check whether the node accepts the transactions
let txid = cl
.send_raw_transaction(&tx)
.unwrap_or_else(|_| panic!("{} send tx failed for ms {}", i, ms));
.unwrap_or_else(|_| panic!("{} send tx failed for ms {}", i, ms))
.txid()
.expect("conversion to model failed");
spend_txids.push(txid);
}
}
// Finally mine the blocks and await confirmations
let _blocks = cl
.generate_to_address(10, &cl.get_new_address(None, None).unwrap().assume_checked())
.generate_to_address(10, &cl.new_address().unwrap())
.unwrap();
// Get the required transactions from the node mined in the blocks.
for txid in spend_txids {
// Check whether the transaction is mined in blocks
// Assert that the confirmations are > 0.
let num_conf = cl.get_transaction(&txid, None).unwrap().info.confirmations;
let num_conf = cl.get_transaction(txid).unwrap().confirmations;
assert!(num_conf > 0);
}
}
Expand Down
40 changes: 22 additions & 18 deletions bitcoind-tests/tests/test_desc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use bitcoin::{
absolute, psbt, secp256k1, sighash, transaction, Amount, OutPoint, Sequence, Transaction, TxIn,
TxOut, Txid,
};
use bitcoind::bitcoincore_rpc::{json, Client, RpcApi};
use bitcoind::{Client, AddressType};
use miniscript::bitcoin::{self, ecdsa, taproot, ScriptBuf};
use miniscript::psbt::{PsbtExt, PsbtInputExt};
use miniscript::{Descriptor, Miniscript, ScriptContext, ToPublicKey};
Expand All @@ -30,11 +30,12 @@ fn btc<F: Into<f64>>(btc: F) -> Amount { Amount::from_btc(btc.into()).unwrap() }

// Find the Outpoint by spk
fn get_vout(cl: &Client, txid: Txid, value: Amount, spk: ScriptBuf) -> (OutPoint, TxOut) {
let tx = cl
.get_transaction(&txid, None)
.unwrap()
.transaction()
.unwrap();
let model = cl.get_transaction(txid)
.expect("rpc call failed")
.into_model()
.expect("conversion to model type failed");
let tx = model.tx;

for (i, txout) in tx.output.into_iter().enumerate() {
if txout.value == value && spk == txout.script_pubkey {
return (OutPoint::new(txid, i as u32), txout);
Expand Down Expand Up @@ -77,9 +78,9 @@ pub fn test_desc_satisfy(
let x_only_pks = &testdata.pubdata.x_only_pks;
// Generate some blocks
let blocks = cl
.generate_to_address(1, &cl.get_new_address(None, None).unwrap().assume_checked())
.generate_to_address(1, &cl.new_address().unwrap())
.unwrap();
assert_eq!(blocks.len(), 1);
assert_eq!(blocks.0.len(), 1);

let definite_desc = test_util::parse_test_desc(descriptor, &testdata.pubdata)
.map_err(|_| DescError::DescParseError)?
Expand All @@ -92,13 +93,15 @@ pub fn test_desc_satisfy(

// Next send some btc to each address corresponding to the miniscript
let txid = cl
.send_to_address(&desc_address, btc(1), None, None, None, None, None, None)
.unwrap();
.send_to_address(&desc_address, btc(1))
.expect("rpc call failed")
.txid()
.expect("conversion to model failed");
// Wait for the funds to mature.
let blocks = cl
.generate_to_address(2, &cl.get_new_address(None, None).unwrap().assume_checked())
.generate_to_address(2, &cl.new_address().unwrap())
.unwrap();
assert_eq!(blocks.len(), 2);
assert_eq!(blocks.0.len(), 2);
// Create a PSBT for each transaction.
// Spend one input and spend one output for simplicity.
let mut psbt = Psbt {
Expand Down Expand Up @@ -130,9 +133,8 @@ pub fn test_desc_satisfy(
// the node wallet tracks the receiving transaction
// and we can check it by gettransaction RPC.
let addr = cl
.get_new_address(None, Some(json::AddressType::Bech32))
.unwrap()
.assume_checked();
.new_address_with_type(AddressType::Bech32)
.unwrap();
// Had to decrease 'value', so that fees can be increased
// (Was getting insufficient fees error, for deep script trees)
psbt.unsigned_tx
Expand Down Expand Up @@ -287,16 +289,18 @@ pub fn test_desc_satisfy(
// Check whether the node accepts the transactions
let txid = cl
.send_raw_transaction(&tx)
.unwrap_or_else(|_| panic!("send tx failed for desc {}", definite_desc));
.unwrap_or_else(|_| panic!("send tx failed for desc {}", definite_desc))
.txid()
.expect("conversion to model failed");

// Finally mine the blocks and await confirmations
let _blocks = cl
.generate_to_address(1, &cl.get_new_address(None, None).unwrap().assume_checked())
.generate_to_address(1, &cl.new_address().unwrap())
.unwrap();
// Get the required transactions from the node mined in the blocks.
// Check whether the transaction is mined in blocks
// Assert that the confirmations are > 0.
let num_conf = cl.get_transaction(&txid, None).unwrap().info.confirmations;
let num_conf = cl.get_transaction(txid).unwrap().confirmations;
assert!(num_conf > 0);
Ok(tx.input[0].witness.clone())
}
Expand Down

0 comments on commit aab9e32

Please sign in to comment.