From 97081ecf4f21fd0bbe98cb79c021d05ce9e126f3 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 1 May 2024 12:55:42 +1000 Subject: [PATCH 1/4] CI: Fix pinning MSRV build just broke because of a bunch of dependencies. I did not investigate why I just found a set of versions that builds. --- contrib/test.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contrib/test.sh b/contrib/test.sh index e308ce3c..2aa5a279 100755 --- a/contrib/test.sh +++ b/contrib/test.sh @@ -16,7 +16,10 @@ fi # Test pinned versions. if cargo --version | grep ${MSRV}; then cargo update -p tempfile --precise 3.3.0 + cargo update -p cc --precise 1.0.79 cargo update -p log --precise 0.4.18 + cargo update -p serde_json --precise 1.0.96 + cargo update -p serde --precise 1.0.156 fi # Integration test. From 40d91e1ab5eae7e1612c0dbf1c18234b6da77607 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 1 May 2024 12:17:39 +1000 Subject: [PATCH 2/4] Add verifymessage feature In #326 we changed a function to use `bitcoin::sign_message::MessageSignature` but doing so requires the "base64" feature to be on for `bitcoin`. This did not get caught by CI but improvements to CI in #338 will now catch this. Add a feature to `json` and `client` that allows enabling "base64" if the `verifymessage` RPC call is required. --- client/Cargo.toml | 10 ++++++++++ client/src/client.rs | 1 + integration_test/Cargo.toml | 2 +- json/Cargo.toml | 3 +++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/client/Cargo.toml b/client/Cargo.toml index cb2573d1..4f1f67ea 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -18,6 +18,9 @@ edition = "2018" name = "bitcoincore_rpc" path = "src/lib.rs" +[features] +verifymessage = ["bitcoincore-rpc-json/verifymessage"] + [dependencies] bitcoincore-rpc-json = { version = "0.18.0", path = "../json" } @@ -31,3 +34,10 @@ serde_json = "1" [dev-dependencies] tempfile = "3.3.0" +[[example]] +name = "retry_client" +required-features = ["verifymessage"] + +[[example]] +name = "test_against_node" +required-features = [] diff --git a/client/src/client.rs b/client/src/client.rs index 5a917903..4e1e5a49 100644 --- a/client/src/client.rs +++ b/client/src/client.rs @@ -871,6 +871,7 @@ pub trait RpcApi: Sized { self.call("stop", &[]) } + #[cfg(feature = "verifymessage")] fn verify_message( &self, address: &Address, diff --git a/integration_test/Cargo.toml b/integration_test/Cargo.toml index 8ad6c1b5..9b4a8b5e 100644 --- a/integration_test/Cargo.toml +++ b/integration_test/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Steven Roose "] edition = "2018" [dependencies] -bitcoincore-rpc = { path = "../client" } +bitcoincore-rpc = { path = "../client", features = ["verifymessage"] } bitcoin = { version = "0.31.0", features = ["serde", "rand", "base64"]} lazy_static = "1.4.0" log = "0.4" diff --git a/json/Cargo.toml b/json/Cargo.toml index 8f3d67cc..ebf2f1d0 100644 --- a/json/Cargo.toml +++ b/json/Cargo.toml @@ -19,6 +19,9 @@ rust-version = "1.56.1" name = "bitcoincore_rpc_json" path = "src/lib.rs" +[features] +verifymessage = ["bitcoin/base64"] + [dependencies] serde = { version = "1", features = [ "derive" ] } serde_json = "1" From 57840772d8ef8ef1a4a502628c32f05f0c042295 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 2 May 2024 08:12:58 +1000 Subject: [PATCH 3/4] Run the formatter Currently in CI the formatter is being run with `--check` but a non-zero return status is not causing the script to fail so failure is not causing any CI job to fail. Inn preparation for correctly running the formatter in CI manually run it using `cargo fmt`. --- client/src/client.rs | 15 +++-- integration_test/src/main.rs | 116 +++++++++++++++++++++++++---------- json/src/lib.rs | 21 ++++--- 3 files changed, 106 insertions(+), 46 deletions(-) diff --git a/client/src/client.rs b/client/src/client.rs index 4e1e5a49..30a6d35c 100644 --- a/client/src/client.rs +++ b/client/src/client.rs @@ -21,12 +21,12 @@ use jsonrpc; use serde; use serde_json; -use crate::bitcoin::address::{NetworkUnchecked, NetworkChecked}; +use crate::bitcoin::address::{NetworkChecked, NetworkUnchecked}; use crate::bitcoin::hashes::hex::FromHex; -use bitcoin::sign_message::MessageSignature; use crate::bitcoin::{ Address, Amount, Block, OutPoint, PrivateKey, PublicKey, Script, Transaction, }; +use bitcoin::sign_message::MessageSignature; use log::Level::{Debug, Trace, Warn}; use crate::error::*; @@ -892,7 +892,10 @@ pub trait RpcApi: Sized { } /// Generate new address for receiving change - fn get_raw_change_address(&self, address_type: Option) -> Result> { + fn get_raw_change_address( + &self, + address_type: Option, + ) -> Result> { self.call("getrawchangeaddress", &[opt_into_json(address_type)?]) } @@ -1183,7 +1186,11 @@ pub trait RpcApi: Sized { self.call("finalizepsbt", handle_defaults(&mut args, &[true.into()])) } - fn derive_addresses(&self, descriptor: &str, range: Option<[u32; 2]>) -> Result>> { + fn derive_addresses( + &self, + descriptor: &str, + range: Option<[u32; 2]>, + ) -> Result>> { let mut args = [into_json(descriptor)?, opt_into_json(range)?]; self.call("deriveaddresses", handle_defaults(&mut args, &[null()])) } diff --git a/integration_test/src/main.rs b/integration_test/src/main.rs index 6105a4d9..3da4fddc 100644 --- a/integration_test/src/main.rs +++ b/integration_test/src/main.rs @@ -27,7 +27,7 @@ use bitcoin::consensus::encode::{deserialize, serialize_hex}; use bitcoin::hashes::hex::FromHex; use bitcoin::hashes::Hash; use bitcoin::sign_message::MessageSignature; -use bitcoin::{secp256k1, ScriptBuf, sighash}; +use bitcoin::{secp256k1, sighash, ScriptBuf}; use bitcoin::{ transaction, Address, Amount, Network, OutPoint, PrivateKey, Sequence, SignedAmount, Transaction, TxIn, TxOut, Txid, Witness, @@ -252,7 +252,8 @@ fn test_get_new_address(cl: &Client) { let addr = cl.get_new_address(None, Some(json::AddressType::Bech32)).unwrap().assume_checked(); assert_eq!(addr.address_type(), Some(bitcoin::AddressType::P2wpkh)); - let addr = cl.get_new_address(None, Some(json::AddressType::P2shSegwit)).unwrap().assume_checked(); + let addr = + cl.get_new_address(None, Some(json::AddressType::P2shSegwit)).unwrap().assume_checked(); assert_eq!(addr.address_type(), Some(bitcoin::AddressType::P2sh)); } @@ -263,7 +264,8 @@ fn test_get_raw_change_address(cl: &Client) { let addr = cl.get_raw_change_address(Some(json::AddressType::Bech32)).unwrap().assume_checked(); assert_eq!(addr.address_type(), Some(bitcoin::AddressType::P2wpkh)); - let addr = cl.get_raw_change_address(Some(json::AddressType::P2shSegwit)).unwrap().assume_checked(); + let addr = + cl.get_raw_change_address(Some(json::AddressType::P2shSegwit)).unwrap().assume_checked(); assert_eq!(addr.address_type(), Some(bitcoin::AddressType::P2sh)); } @@ -293,7 +295,9 @@ fn test_generate(cl: &Client) { fn test_get_balance_generate_to_address(cl: &Client) { let initial = cl.get_balance(None, None).unwrap(); - let blocks = cl.generate_to_address(500, &cl.get_new_address(None, None).unwrap().assume_checked()).unwrap(); + let blocks = cl + .generate_to_address(500, &cl.get_new_address(None, None).unwrap().assume_checked()) + .unwrap(); assert_eq!(blocks.len(), 500); assert_ne!(cl.get_balance(None, None).unwrap(), initial); } @@ -302,7 +306,9 @@ fn test_get_balances_generate_to_address(cl: &Client) { if version() >= 190000 { let initial = cl.get_balances().unwrap(); - let blocks = cl.generate_to_address(500, &cl.get_new_address(None, None).unwrap().assume_checked()).unwrap(); + let blocks = cl + .generate_to_address(500, &cl.get_new_address(None, None).unwrap().assume_checked()) + .unwrap(); assert_eq!(blocks.len(), 500); assert_ne!(cl.get_balances().unwrap(), initial); } @@ -378,7 +384,8 @@ fn test_get_address_info(cl: &Client) { let info = cl.get_address_info(&addr).unwrap(); assert!(!info.witness_program.unwrap().is_empty()); - let addr = cl.get_new_address(None, Some(json::AddressType::P2shSegwit)).unwrap().assume_checked(); + let addr = + cl.get_new_address(None, Some(json::AddressType::P2shSegwit)).unwrap().assume_checked(); let info = cl.get_address_info(&addr).unwrap(); assert!(!info.hex.unwrap().is_empty()); } @@ -434,7 +441,9 @@ fn test_get_received_by_address(cl: &Client) { let _ = cl.send_to_address(&addr, btc(1), None, None, None, None, None, None).unwrap(); assert_eq!(cl.get_received_by_address(&addr, Some(0)).unwrap(), btc(1)); assert_eq!(cl.get_received_by_address(&addr, Some(1)).unwrap(), btc(0)); - let _ = cl.generate_to_address(7, &cl.get_new_address(None, None).unwrap().assume_checked()).unwrap(); + let _ = cl + .generate_to_address(7, &cl.get_new_address(None, None).unwrap().assume_checked()) + .unwrap(); assert_eq!(cl.get_received_by_address(&addr, Some(6)).unwrap(), btc(1)); assert_eq!(cl.get_received_by_address(&addr, None).unwrap(), btc(1)); } @@ -442,19 +451,23 @@ fn test_get_received_by_address(cl: &Client) { fn test_list_unspent(cl: &Client) { let addr = cl.get_new_address(None, None).unwrap(); let addr_checked = addr.clone().assume_checked(); - let txid = cl.send_to_address(&addr.clone().assume_checked(), btc(1), None, None, None, None, None, None).unwrap(); - let unspent = cl.list_unspent(Some(0), None, Some(&[ &addr_checked]), None, None).unwrap(); + let txid = cl + .send_to_address(&addr.clone().assume_checked(), btc(1), None, None, None, None, None, None) + .unwrap(); + let unspent = cl.list_unspent(Some(0), None, Some(&[&addr_checked]), None, None).unwrap(); assert_eq!(unspent[0].txid, txid); assert_eq!(unspent[0].address.as_ref(), Some(&addr)); assert_eq!(unspent[0].amount, btc(1)); - let txid = cl.send_to_address(&addr_checked, btc(7), None, None, None, None, None, None).unwrap(); + let txid = + cl.send_to_address(&addr_checked, btc(7), None, None, None, None, None, None).unwrap(); let options = json::ListUnspentQueryOptions { minimum_amount: Some(btc(7)), maximum_amount: Some(btc(7)), ..Default::default() }; - let unspent = cl.list_unspent(Some(0), None, Some(&[&addr_checked]), None, Some(options)).unwrap(); + let unspent = + cl.list_unspent(Some(0), None, Some(&[&addr_checked]), None, Some(options)).unwrap(); assert_eq!(unspent.len(), 1); assert_eq!(unspent[0].txid, txid); assert_eq!(unspent[0].address.as_ref(), Some(&addr)); @@ -480,7 +493,9 @@ fn test_get_raw_transaction(cl: &Client) { let info = cl.get_raw_transaction_info(&txid, None).unwrap(); assert_eq!(info.txid, txid); - let blocks = cl.generate_to_address(7, &cl.get_new_address(None, None).unwrap().assume_checked()).unwrap(); + let blocks = cl + .generate_to_address(7, &cl.get_new_address(None, None).unwrap().assume_checked()) + .unwrap(); let _ = cl.get_raw_transaction_info(&txid, Some(&blocks[0])).unwrap(); } @@ -536,7 +551,9 @@ fn test_get_tx_out_proof(cl: &Client) { cl.send_to_address(&RANDOM_ADDRESS, btc(1), None, None, None, None, None, None).unwrap(); let txid2 = cl.send_to_address(&RANDOM_ADDRESS, btc(1), None, None, None, None, None, None).unwrap(); - let blocks = cl.generate_to_address(7, &cl.get_new_address(None, None).unwrap().assume_checked()).unwrap(); + let blocks = cl + .generate_to_address(7, &cl.get_new_address(None, None).unwrap().assume_checked()) + .unwrap(); let proof = cl.get_tx_out_proof(&[txid1, txid2], Some(&blocks[0])).unwrap(); assert!(!proof.is_empty()); } @@ -563,7 +580,9 @@ fn test_lock_unspent_unlock_unspent(cl: &Client) { } fn test_get_block_filter(cl: &Client) { - let blocks = cl.generate_to_address(7, &cl.get_new_address(None, None).unwrap().assume_checked()).unwrap(); + let blocks = cl + .generate_to_address(7, &cl.get_new_address(None, None).unwrap().assume_checked()) + .unwrap(); if version() >= 190000 { let _ = cl.get_block_filter(&blocks[0]).unwrap(); } else { @@ -634,7 +653,12 @@ fn test_sign_raw_transaction_with_send_raw_transaction(cl: &Client) { }; let res = cl - .sign_raw_transaction_with_key(&tx, &[sk], None, Some(sighash::EcdsaSighashType::All.into())) + .sign_raw_transaction_with_key( + &tx, + &[sk], + None, + Some(sighash::EcdsaSighashType::All.into()), + ) .unwrap(); assert!(res.complete); let _ = cl.send_raw_transaction(&res.transaction().unwrap()).unwrap(); @@ -1283,9 +1307,7 @@ fn test_getblocktemplate(cl: &Client) { fn test_unloadwallet(cl: &Client) { cl.create_wallet("testunloadwallet", None, None, None, None).unwrap(); - let res = new_wallet_client("testunloadwallet") - .unload_wallet(None) - .unwrap(); + let res = new_wallet_client("testunloadwallet").unload_wallet(None).unwrap(); if version() >= 210000 { assert!(res.is_some()); @@ -1324,7 +1346,13 @@ fn test_wait_for_new_block(cl: &Client) { let hash = cl.get_block_hash(height).unwrap(); assert!(cl.wait_for_new_block(std::u64::MAX).is_err()); // JSON integer out of range - assert_eq!(cl.wait_for_new_block(100).unwrap(), json::BlockRef{hash, height}); + assert_eq!( + cl.wait_for_new_block(100).unwrap(), + json::BlockRef { + hash, + height + } + ); } fn test_wait_for_block(cl: &Client) { @@ -1332,12 +1360,23 @@ fn test_wait_for_block(cl: &Client) { let hash = cl.get_block_hash(height).unwrap(); assert!(cl.wait_for_block(&hash, std::u64::MAX).is_err()); // JSON integer out of range - assert_eq!(cl.wait_for_block(&hash, 0).unwrap(), json::BlockRef{hash, height}); + assert_eq!( + cl.wait_for_block(&hash, 0).unwrap(), + json::BlockRef { + hash, + height + } + ); } fn test_get_descriptor_info(cl: &Client) { - let res = cl.get_descriptor_info(r"pkh(cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR)").unwrap(); - assert_eq!(res.descriptor, r"pkh(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c)#62k9sn4x"); + let res = cl + .get_descriptor_info(r"pkh(cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR)") + .unwrap(); + assert_eq!( + res.descriptor, + r"pkh(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c)#62k9sn4x" + ); assert_eq!(res.is_range, false); assert_eq!(res.is_solvable, true); assert_eq!(res.has_private_keys, true); @@ -1355,29 +1394,40 @@ fn test_get_descriptor_info(cl: &Client) { fn test_add_multisig_address(cl: &Client) { let addr1 = cl.get_new_address(None, Some(json::AddressType::Bech32)).unwrap().assume_checked(); let addr2 = cl.get_new_address(None, Some(json::AddressType::Bech32)).unwrap().assume_checked(); - let addresses = [ - json::PubKeyOrAddress::Address(&addr1), - json::PubKeyOrAddress::Address(&addr2), - ]; + let addresses = + [json::PubKeyOrAddress::Address(&addr1), json::PubKeyOrAddress::Address(&addr2)]; assert!(cl.add_multisig_address(addresses.len(), &addresses, None, None).is_ok()); assert!(cl.add_multisig_address(addresses.len() - 1, &addresses, None, None).is_ok()); assert!(cl.add_multisig_address(addresses.len() + 1, &addresses, None, None).is_err()); assert!(cl.add_multisig_address(0, &addresses, None, None).is_err()); assert!(cl.add_multisig_address(addresses.len(), &addresses, Some("test_label"), None).is_ok()); - assert!(cl.add_multisig_address(addresses.len(), &addresses, None, Some(json::AddressType::Legacy)).is_ok()); - assert!(cl.add_multisig_address(addresses.len(), &addresses, None, Some(json::AddressType::P2shSegwit)).is_ok()); - assert!(cl.add_multisig_address(addresses.len(), &addresses, None, Some(json::AddressType::Bech32)).is_ok()); + assert!(cl + .add_multisig_address(addresses.len(), &addresses, None, Some(json::AddressType::Legacy)) + .is_ok()); + assert!(cl + .add_multisig_address( + addresses.len(), + &addresses, + None, + Some(json::AddressType::P2shSegwit) + ) + .is_ok()); + assert!(cl + .add_multisig_address(addresses.len(), &addresses, None, Some(json::AddressType::Bech32)) + .is_ok()); } fn test_verify_message_with_messagesignature(cl: &Client) { - let addr: Address = Address::from_str("mm68FdwbpxkVcqjU3fu7iiBGEwrsC6Hk66").unwrap().assume_checked(); + let addr: Address = + Address::from_str("mm68FdwbpxkVcqjU3fu7iiBGEwrsC6Hk66").unwrap().assume_checked(); let signature = MessageSignature::from_base64( - "H3X+ic7axKtHGIsKiqDq0TmP9HIAkONwunln17ROlvB4SOVVUoG5e79EwAz94x2eERPwqcGJ5rLuWRhIu85pEwE=",) - .expect("a valid signature"); + "H3X+ic7axKtHGIsKiqDq0TmP9HIAkONwunln17ROlvB4SOVVUoG5e79EwAz94x2eERPwqcGJ5rLuWRhIu85pEwE=", + ) + .expect("a valid signature"); let message = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"; - assert!(cl.verify_message(&addr, &signature, message).expect("a valid signature")); + assert!(cl.verify_message(&addr, &signature, message).expect("a valid signature")); } #[rustfmt::skip] diff --git a/json/src/lib.rs b/json/src/lib.rs index bc3468f4..808cd39c 100644 --- a/json/src/lib.rs +++ b/json/src/lib.rs @@ -24,13 +24,15 @@ extern crate serde_json; use std::collections::HashMap; - use bitcoin::address::NetworkUnchecked; use bitcoin::block::Version; use bitcoin::consensus::encode; use bitcoin::hashes::hex::FromHex; use bitcoin::hashes::sha256; -use bitcoin::{Address, Amount, PrivateKey, PublicKey, SignedAmount, Transaction, ScriptBuf, Script, bip158, bip32, Network}; +use bitcoin::{ + bip158, bip32, Address, Amount, Network, PrivateKey, PublicKey, Script, ScriptBuf, + SignedAmount, Transaction, +}; use serde::de::Error as SerdeError; use serde::{Deserialize, Serialize}; use std::fmt; @@ -1880,10 +1882,7 @@ pub struct FundRawTransactionOptions { /// The fee rate to pay per kvB. NB. This field is converted to camelCase /// when serialized, so it is receeived by fundrawtransaction as `feeRate`, /// which fee rate per kvB, and *not* `fee_rate`, which is per vB. - #[serde( - with = "bitcoin::amount::serde::as_btc::opt", - skip_serializing_if = "Option::is_none" - )] + #[serde(with = "bitcoin::amount::serde::as_btc::opt", skip_serializing_if = "Option::is_none")] pub fee_rate: Option, #[serde(skip_serializing_if = "Option::is_none")] pub subtract_fee_from_outputs: Option>, @@ -2183,7 +2182,7 @@ where /// deserialize_bip70_network deserializes a Bitcoin Core network according to BIP70 /// The accepted input variants are: {"main", "test", "signet", "regtest"} -fn deserialize_bip70_network<'de, D>(deserializer: D) -> Result +fn deserialize_bip70_network<'de, D>(deserializer: D) -> Result where D: serde::Deserializer<'de>, { @@ -2192,8 +2191,12 @@ where type Value = Network; fn visit_str(self, s: &str) -> Result { - Network::from_core_arg(s) - .map_err(|_| E::invalid_value(serde::de::Unexpected::Str(s), &"bitcoin network encoded as a string")) + Network::from_core_arg(s).map_err(|_| { + E::invalid_value( + serde::de::Unexpected::Str(s), + &"bitcoin network encoded as a string", + ) + }) } fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { From 980e0b32c88ef474266bfdb2b51d9b3ebeece15b Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Tue, 30 Apr 2024 08:56:32 +1000 Subject: [PATCH 4/4] Re-write CI Re-write CI in a similar manner to what we did in `rust-bitcoin` recently. Some benefits: - The `contrib/run_task.sh` can be used from the command line. - GitHub action is dumber i.e., all the logic is in the shell script instead of spread between the action and the script. - The action yaml is [hopefully] a bit cleaner. Covearge is the same, three toolchains, linter, integration tests for various Core versions. Includes a bunch of pinning for MSRV that seems to currently be broken, I'm not exactly sure when it broke. --- .github/workflows/rust.yml | 139 ++++++++++++++++++++-------------- client/Cargo.toml | 6 +- contrib/run_task.sh | 149 +++++++++++++++++++++++++++++++++++++ json/Cargo.toml | 4 +- 4 files changed, 236 insertions(+), 62 deletions(-) create mode 100755 contrib/run_task.sh diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 2e7d3d3a..97ee2a9c 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -1,62 +1,87 @@ -on: [push, pull_request] +on: + push: + branches: + - master + - 'test-ci/**' + pull_request: name: Continuous integration jobs: - tests: - name: Tests - runs-on: ubuntu-latest - strategy: - matrix: - include: - - rust: stable - env: - RUSTFMTCHK: true - - rust: nightly - env: - RUSTFMTCHK: false - - rust: 1.56.1 - env: - RUSTFMTCHK: false - steps: - - name: Checkout Crate - uses: actions/checkout@v2 - - name: Checkout Toolchain - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: ${{ matrix.rust }} - override: true - - name: Running test script - env: ${{ matrix.env }} - run: ./contrib/test.sh + Stable: + name: Test - stable toolchain + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - name: "Checkout repo" + uses: actions/checkout@v4 + - name: "Select toolchain" + uses: dtolnay/rust-toolchain@stable + - name: "Run test script" + run: ./contrib/run_task.sh stable - integrations-tests: - name: Integration Tests - runs-on: ubuntu-latest - strategy: - matrix: - rust: [stable] - bitcoinversion: - [ - "0.18.0", - "0.18.1", - "0.19.0.1", - "0.19.1", - "0.20.0", - "0.20.1", - "0.21.0", - ] - steps: - - name: Checkout Crate - uses: actions/checkout@v2 - - name: Checkout Toolchain - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: ${{ matrix.rust }} - override: true - - name: Running test script - env: - BITCOINVERSION: ${{ matrix.bitcoinversion }} - run: ./contrib/test.sh + Nightly: + name: Test - nightly toolchain + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - name: "Checkout repo" + uses: actions/checkout@v4 + - name: "Select toolchain" + uses: dtolnay/rust-toolchain@nightly + - name: "Run test script" + run: ./contrib/run_task.sh nightly + + MSRV: + name: Test - 1.56.1 toolchain + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - name: "Checkout repo" + uses: actions/checkout@v4 + - name: "Select toolchain" + uses: dtolnay/rust-toolchain@stable + with: + toolchain: "1.56.1" + - name: "Run test script" + run: ./contrib/run_task.sh msrv + + Format: + name: Format - stable toolchain + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - name: "Checkout repo" + uses: actions/checkout@v4 + - name: "Select toolchain" + uses: dtolnay/rust-toolchain@stable + - name: "Check formatting" + run: cargo fmt --all -- --check + + Integration: + name: Integration Tests - stable toolchain + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + bitcoin_version: + [ + "0.18.0", + "0.18.1", + "0.19.0.1", + "0.19.1", + "0.20.0", + "0.20.1", + "0.21.0", + ] + steps: + - name: "Checkout repo" + uses: actions/checkout@v4 + - name: "Select toolchain" + uses: dtolnay/rust-toolchain@stable + - name: Running test script + run: ./contrib/run_task.sh integration ${{ matrix.bitcoin_version }} diff --git a/client/Cargo.toml b/client/Cargo.toml index 4f1f67ea..3f1e01f4 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -28,11 +28,11 @@ log = "0.4.5" jsonrpc = "0.14.0" # Used for deserialization of JSON. -serde = "1" -serde_json = "1" +serde = "1.0.156" +serde_json = "1.0.96" [dev-dependencies] -tempfile = "3.3.0" +tempfile = "3.6.0" [[example]] name = "retry_client" diff --git a/contrib/run_task.sh b/contrib/run_task.sh new file mode 100755 index 00000000..97d3dde0 --- /dev/null +++ b/contrib/run_task.sh @@ -0,0 +1,149 @@ +#!/usr/bin/env bash +# +# Run CI task, called by the `rust.yml` GitHub action. + +set -euo pipefail + +REPO_DIR=$(git rev-parse --show-toplevel) +MSRV="1.56.1" + +usage() { + cat < /dev/null; + + cargo "$toolchain" build + cargo "$toolchain" test + + popd > /dev/null + done +} + +# Pin dependencies to get the MSRV build to work. +do_msrv_pins() { + cargo update -p tempfile --precise 3.6.0 + cargo update -p cc --precise 1.0.79 + cargo update -p log --precise 0.4.18 + cargo update -p serde_json --precise 1.0.96 + cargo update -p serde --precise 1.0.156 +} + +# Check the workspace formatting. +do_fmt() { + cargo +stable fmt --all --check +} + +# Pulls down Bitcoin Core binary and runs the integration tests. +integration() { + local core_version="$1" + + cd "$REPO_DIR" + + if [ "$core_version" != "none" ]; then + wget "https://bitcoincore.org/bin/bitcoin-core-$bitcoin_version/bitcoin-$bitcoin_version-x86_64-linux-gnu.tar.gz" + tar -xzvf "bitcoin-$bitcoin_version-x86_64-linux-gnu.tar.gz" + export PATH=$PATH:"$REPO_DIR/bitcoin-$bitcoin_version/bin" + fi + + need_cmd "bitcoind" + + cd "$REPO_DIR/integration_test" + ./run.sh +} + +# Check all the commands we use are present in the current environment. +check_required_commands() { + need_cmd cargo + need_cmd rustc +} + +need_cmd() { + if ! command -v "$1" > /dev/null 2>&1 + then err "need '$1' (command not found)" + fi +} + +err() { + echo "$1" >&2 + exit 1 +} + +# +# Main script +# +main "$@" +exit 0 diff --git a/json/Cargo.toml b/json/Cargo.toml index ebf2f1d0..4ac8ab3f 100644 --- a/json/Cargo.toml +++ b/json/Cargo.toml @@ -23,7 +23,7 @@ path = "src/lib.rs" verifymessage = ["bitcoin/base64"] [dependencies] -serde = { version = "1", features = [ "derive" ] } -serde_json = "1" +serde = { version = "1.0.156", features = [ "derive" ] } +serde_json = "1.0.96" bitcoin = { version = "0.31.0", features = ["serde", "rand-std"]}