Skip to content

Add support for bitcoin core 29.0 #131

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/rust.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ jobs:
matrix:
feature:
[
"29_0",
"28_1",
"28_0",
"27_2",
Expand Down
1 change: 1 addition & 0 deletions client/src/client_sync/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub mod v25;
pub mod v26;
pub mod v27;
pub mod v28;
pub mod v29;

use std::fs::File;
use std::io::{BufRead, BufReader};
Expand Down
33 changes: 33 additions & 0 deletions client/src/client_sync/v29/blockchain.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// SPDX-License-Identifier: CC0-1.0

//! Macros for implementing JSON-RPC methods on a client.
//!
//! Specifically this is methods found under the `== Blockchain ==` section of the
//! API docs of Bitcoin Core `v29`.
//!
//! All macros require `Client` to be in scope.
//!
//! See or use the `define_jsonrpc_minreq_client!` macro to define a `Client`.

/// Implements Bitcoin Core JSON-RPC API method `getdescriptoractivity`
#[macro_export]
macro_rules! impl_client_v29__getdescriptoractivity {
() => {
impl Client {
pub fn get_descriptor_activity(
&self,
blockhashes: &[BlockHash],
scan_objects: &[&str],
include_mempool: bool,
) -> Result<GetDescriptorActivity> {
let blockhashes_val = json!(blockhashes);
let scan_objects_val = json!(scan_objects);
let include_mempool_val = json!(include_mempool);

let params = vec![blockhashes_val, scan_objects_val, include_mempool_val];

self.call("getdescriptoractivity", &params)
Comment on lines +23 to +29
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let blockhashes_val = json!(blockhashes);
let scan_objects_val = json!(scan_objects);
let include_mempool_val = json!(include_mempool);
let params = vec![blockhashes_val, scan_objects_val, include_mempool_val];
self.call("getdescriptoractivity", &params)
self.call("getdescriptoractivity", &[])

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I do this, the method won't work, because all the parameters are required even if they contain no value, they are to be present as empty arrays, including the bool value. Running the test, we will always have this:

getdescriptoractivity: JsonRpc(Rpc(RpcError { code: -3, message: "JSON value of type null is not of expected type array", data: None }))

That is the reason why I had to be passing an empty array.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is odd, the docs say they are optional.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly, while working on it at first, I tried without including the parameters, and I kept getting this error while running the test. So I decided to try by passing in an empty array instead, only then did it work.

}
}
};
}
171 changes: 171 additions & 0 deletions client/src/client_sync/v29/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
// SPDX-License-Identifier: CC0-1.0

//! A JSON-RPC client for testing against Bitcoin Core `v29`.
//!
//! We ignore option arguments unless they effect the shape of the returned JSON data.
pub mod blockchain;

use std::collections::BTreeMap;
use std::path::Path;

use bitcoin::address::{Address, NetworkChecked};
use bitcoin::{sign_message, Amount, Block, BlockHash, PublicKey, Txid};
use serde::{Deserialize, Serialize};
use serde_json::json;

use crate::client_sync::into_json;
use crate::types::v29::*;

#[rustfmt::skip] // Keep public re-exports separate.
pub use crate::client_sync::{
v17::{Input, Output, WalletCreateFundedPsbtInput},
v23::AddressType,
};

crate::define_jsonrpc_minreq_client!("v29");
crate::impl_client_check_expected_server_version!({ [290000] });

// == Blockchain ==
crate::impl_client_v17__getbestblockhash!();
crate::impl_client_v17__getblock!();
crate::impl_client_v17__getblockchaininfo!();
crate::impl_client_v17__getblockcount!();
crate::impl_client_v19__getblockfilter!();
crate::impl_client_v17__getblockhash!();
crate::impl_client_v17__getblockheader!();
crate::impl_client_v17__getblockstats!();
crate::impl_client_v17__getchaintips!();
crate::impl_client_v17__getchaintxstats!();
crate::impl_client_v29__getdescriptoractivity!();
crate::impl_client_v17__getdifficulty!();
crate::impl_client_v17__getmempoolancestors!();
crate::impl_client_v17__getmempooldescendants!();
crate::impl_client_v17__getmempoolentry!();
crate::impl_client_v17__getmempoolinfo!();
crate::impl_client_v17__getrawmempool!();
crate::impl_client_v17__gettxout!();
crate::impl_client_v17__gettxoutproof!();
crate::impl_client_v26__gettxoutsetinfo!();
crate::impl_client_v17__preciousblock!();
crate::impl_client_v17__pruneblockchain!();
crate::impl_client_v23__savemempool!();
crate::impl_client_v17__verifychain!();
crate::impl_client_v17__verifytxoutproof!();

// == Control ==
crate::impl_client_v17__getmemoryinfo!();
crate::impl_client_v18__getrpcinfo!();
crate::impl_client_v17__help!();
crate::impl_client_v17__logging!();
crate::impl_client_v17__stop!();
crate::impl_client_v17__uptime!();

// == Generating ==
crate::impl_client_v17__generatetoaddress!();
crate::impl_client_v17__invalidateblock!();

// == Mining ==
crate::impl_client_v17__getblocktemplate!();
crate::impl_client_v17__getmininginfo!();
crate::impl_client_v17__getnetworkhashps!();
crate::impl_client_v26__get_prioritised_transactions!();
crate::impl_client_v17__prioritisetransaction!();
crate::impl_client_v17__submitblock!();

// == Network ==
crate::impl_client_v17__getaddednodeinfo!();
crate::impl_client_v17__getnettotals!();
crate::impl_client_v17__getnetworkinfo!();
crate::impl_client_v18__getnodeaddresses!();
crate::impl_client_v17__getpeerinfo!();

// == Rawtransactions ==
crate::impl_client_v18__analyzepsbt!();
crate::impl_client_v17__combinepsbt!();
crate::impl_client_v17__combinerawtransaction!();
crate::impl_client_v17__converttopsbt!();
crate::impl_client_v17__createpsbt!();
crate::impl_client_v17__createrawtransaction!();
crate::impl_client_v17__decodepsbt!();
crate::impl_client_v17__decoderawtransaction!();
crate::impl_client_v17__decodescript!();
crate::impl_client_v17__finalizepsbt!();
crate::impl_client_v17__fundrawtransaction!();
crate::impl_client_v17__getrawtransaction!();
crate::impl_client_v18__joinpsbts!();
crate::impl_client_v17__sendrawtransaction!();
crate::impl_client_v17__signrawtransaction!();
crate::impl_client_v17__signrawtransactionwithkey!();
crate::impl_client_v28__submitpackage!();
crate::impl_client_v17__testmempoolaccept!();
crate::impl_client_v18__utxoupdatepsbt!();

// == Util ==
crate::impl_client_v17__createmultisig!();
crate::impl_client_v17__estimatesmartfee!();
crate::impl_client_v17__signmessagewithprivkey!();
crate::impl_client_v17__validateaddress!();
crate::impl_client_v17__verifymessage!();

// == Wallet ==
crate::impl_client_v17__addmultisigaddress!();
crate::impl_client_v17__bumpfee!();
crate::impl_client_v23__createwallet!();
crate::impl_client_v17__dumpprivkey!();
crate::impl_client_v17__dumpwallet!();
crate::impl_client_v17__getaddressesbylabel!();
crate::impl_client_v17__getaddressinfo!();
crate::impl_client_v17__getbalance!();
crate::impl_client_v19__getbalances!();
crate::impl_client_v17__getnewaddress!();
crate::impl_client_v17__getrawchangeaddress!();
crate::impl_client_v17__getreceivedbyaddress!();
crate::impl_client_v17__gettransaction!();
crate::impl_client_v17__getunconfirmedbalance!();
crate::impl_client_v17__getwalletinfo!();
crate::impl_client_v17__listaddressgroupings!();
crate::impl_client_v17__listlabels!();
crate::impl_client_v17__listlockunspent!();
crate::impl_client_v17__listreceivedbyaddress!();
crate::impl_client_v17__listsinceblock!();
crate::impl_client_v17__listtransactions!();
crate::impl_client_v17__listunspent!();
crate::impl_client_v17__listwallets!();
crate::impl_client_v22__loadwallet!();
crate::impl_client_v17__rescanblockchain!();
crate::impl_client_v17__sendmany!();
crate::impl_client_v17__sendtoaddress!();
crate::impl_client_v17__signmessage!();
crate::impl_client_v17__signrawtransactionwithwallet!();
crate::impl_client_v21__unloadwallet!();
crate::impl_client_v17__walletcreatefundedpsbt!();
crate::impl_client_v17__walletprocesspsbt!();

/// Client side supported softfork deployment.
#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum TemplateRules {
/// SegWit v0 supported.
Segwit,
/// Signet supported.
Signet,
/// CSV supported.
Csv,
/// Taproot supported.
Taproot,
}

/// Arg for the `getblocktemplate` method. (v29+).
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
pub struct TemplateRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub mode: Option<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub capabilities: Vec<String>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub rules: Vec<TemplateRules>,
#[serde(skip_serializing_if = "Option::is_none")]
pub longpollid: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<String>,
}
1 change: 1 addition & 0 deletions contrib/run-bitcoind.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ CONFIGURATION

- Examples

v29 29.0 290 /opt/bitcoin-29.0/bin/bitcoind
v28 28.1 281 /opt/bitcoin-28.1/bin/bitcoind
v24 24.2 242 /opt/bitcoin-24.2/bin/bitcoind
v21 0.21.2 212 /opt/bitcoin-0.21.2/bin/bitcoind
Expand Down
2 changes: 2 additions & 0 deletions integration_test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ edition = "2021"
[features]
# Enable the same feature in `node` and the version feature here.
# All minor releases of the latest three versions.
29_0 = ["v29", "node/29_0"]
28_1 = ["v28", "node/28_1"]
28_0 = ["v28", "node/28_0"]
27_2 = ["v27", "node/27_2"]
Expand All @@ -34,6 +35,7 @@ edition = "2021"

# These features are just for internal use (feature gating).
# Each major version is tested with the same client.
v29 = []
v28 = []
v27 = []
v26 = []
Expand Down
11 changes: 11 additions & 0 deletions integration_test/tests/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ fn blockchain__get_block__modelled() {
// assert!(json.into_model().is_ok());
}

#[cfg(not(feature = "v29"))]
#[test]
fn blockchain__get_blockchain_info__modelled() {
let node = Node::with_wallet(Wallet::None, &[]);
Expand Down Expand Up @@ -148,6 +149,16 @@ fn blockchain__get_chain_tx_stats__modelled() {
model.unwrap();
}

#[test]
#[cfg(feature = "v29")]
fn blockchain__get_descriptor_activity__modelled() {
let node = Node::with_wallet(Wallet::None, &["-coinstatsindex=1", "-txindex=1"]);

let json: GetDescriptorActivity = node.client.get_descriptor_activity(&[], &[], false).expect("getdescriptoractivity");
let model: Result<mtype::GetDescriptorActivity, GetDescriptorActivityError> = json.into_model();
model.unwrap();
}

#[test]
fn blockchain__get_difficulty__modelled() {
let node = Node::with_wallet(Wallet::None, &[]);
Expand Down
20 changes: 15 additions & 5 deletions integration_test/tests/mining.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,22 @@ fn mining__get_block_template__modelled() {
node1.mine_a_block();
node2.mine_a_block();
node3.mine_a_block();
std::thread::sleep(std::time::Duration::from_millis(500));

let options = match () {
#[cfg(not(feature = "v29"))]
() => TemplateRequest { rules: vec![TemplateRules::Segwit] },
#[cfg(feature = "v29")]
() => TemplateRequest {
rules: vec![TemplateRules::Segwit],
mode: Some("template".to_string()),
..Default::default()
}
};

let options = TemplateRequest { rules: vec![TemplateRules::Segwit] };

let json: GetBlockTemplate = node1.client.get_block_template(&options).expect("rpc");
let model: Result<mtype::GetBlockTemplate, GetBlockTemplateError> = json.into_model();
model.unwrap();
let json: GetBlockTemplate = node1.client.get_block_template(&options)
.expect("get_block_template RPC failed");
let _: Result<mtype::GetBlockTemplate, GetBlockTemplateError> = json.into_model();
}

#[test]
Expand Down
1 change: 1 addition & 0 deletions node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ default = ["0_17_2"]
download = ["anyhow", "bitcoin_hashes", "flate2", "tar", "minreq", "zip"]

# We support all minor releases of the latest three versions.
29_0 = ["28_1"]
28_1 = ["28_0"]
28_0 = ["27_2"]
27_2 = ["27_1"]
Expand Down
2 changes: 1 addition & 1 deletion node/contrib/extra_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

set -euox pipefail

FEATURES=("28_1" "28_0" "27_1" "27_0" "26_2" "26_1" "26_0" "25_2" "24_2" \
FEATURES=("29_0" "28_1" "28_0" "27_1" "27_0" "26_2" "26_1" "26_0" "25_2" "24_2" \
"23_2" "22_1" "0_21_2" "0_20_2" "0_19_1" "0_18_1" "0_17_2")

# Use the current `Cargo.lock` file without updating it.
Expand Down
28 changes: 28 additions & 0 deletions node/sha256/bitcoin-core-29.0-SHA256SUMS
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
95da3fb840044bddcde761394597da5e2f7d7030d371c94a6b51b15db9ea6a92 bitcoin-29.0-aarch64-linux-gnu-debug.tar.gz
7922ac99363dd28f79e57ef7098581fd48ebd1119b412b07e73b1fd19fd0443f bitcoin-29.0-aarch64-linux-gnu.tar.gz
f7f5c47d5e7674b325473e8d6834ba842e280794f6d9079f3e3cc26d031b755b bitcoin-29.0-arm-linux-gnueabihf-debug.tar.gz
ea8ca24ab56d486a55289c43cb4256f9f0e66224899cc43482c9498a3f2614d1 bitcoin-29.0-arm-linux-gnueabihf.tar.gz
34431c582a0399dd42e1276d87d25306cbdde0217f6744bd55a2945986645dda bitcoin-29.0-arm64-apple-darwin.tar.gz
f660d4a968f5dabcee4d72cd31b4a50ab0d646386a9fc78c6208a9a101f8878d bitcoin-29.0-arm64-apple-darwin.zip
fc7dee914326fc734f3fd982be3e58a163c4838f056593707ff0e68123fded5c bitcoin-29.0-arm64-apple-darwin-codesigning.tar.gz
9e828fee8562c1748337182a723f5f574cec19196a36bff184d0ea346dde335d bitcoin-29.0-arm64-apple-darwin-unsigned.tar.gz
d948735aa17f01af243ee621af80b0c4073587868d6a71309b2531b9b429fed4 bitcoin-29.0-arm64-apple-darwin-unsigned.zip
bc69f1351ea6c5e88e54ad4ce93ee322066e7ec868b2b289f1544e432a799363 bitcoin-29.0-codesignatures-29.0.tar.gz
882c782c34a3bf2eacd1fae5cdc58b35b869883512f197f7d6dc8f195decfdaa bitcoin-29.0.tar.gz
9407abc574ddd52fe4ebfae4bed6c782d7701142e4096d29f08e5fb747f4a218 bitcoin-29.0-powerpc64-linux-gnu-debug.tar.gz
6cbf1056b48799f366374c12b3cdc2cc0dcd5b37dc8058433ae35bb7764d3f17 bitcoin-29.0-powerpc64-linux-gnu.tar.gz
a3e35a74e1647aec5425c5434acc28c3508c6e796382e7024b44f4c3c63c9607 bitcoin-29.0-riscv64-linux-gnu-debug.tar.gz
4b3cb5e6490354778a289cf808c0d1adb29e6a251570942b5f25c143c47fbdd0 bitcoin-29.0-riscv64-linux-gnu.tar.gz
5bb824fc86a15318d6a83a1b821ff4cd4b3d3d0e1ec3d162b805ccf7cae6fca8 bitcoin-29.0-x86_64-apple-darwin.tar.gz
3bbee3e1f006365542d5c84beb632c90a6d206fa610c1fe415f52e69febe9b0c bitcoin-29.0-x86_64-apple-darwin.zip
0ce7617e8207490fe186bef3c8dc61f6a2cd1ae192ddf1cb864ef2a58e1367d3 bitcoin-29.0-x86_64-apple-darwin-codesigning.tar.gz
783334643eca7f3e9e9d6d34a6d04f9bbeb0a8036ff9b90a990a5255370c8a62 bitcoin-29.0-x86_64-apple-darwin-unsigned.tar.gz
a15b65890537f4dc73b4af0c9b9a30e735f45dd0ae53ff45dfac9c67f05080b6 bitcoin-29.0-x86_64-apple-darwin-unsigned.zip
50d320dcea299c8ff5bd42be877b4f61a0fce290d945fe0b0b431b9c26ea1b06 bitcoin-29.0-x86_64-linux-gnu-debug.tar.gz
a681e4f6ce524c338a105f214613605bac6c33d58c31dc5135bbc02bc458bb6c bitcoin-29.0-x86_64-linux-gnu.tar.gz
f68589b8f81c670fe4850ba7c388a5da9ec9db6bfc715db2b381a17e37cc1ba4 bitcoin-29.0-win64-setup.exe
4c1780532031129fcacfc0e393c8430b3cea414c9f8c5e0c0c87ebe59a5ada1b bitcoin-29.0-win64.zip
f3a20b09dfab33b4f8ae64a55c2669520c397b5eba5fb9a5b5a4afac75337d91 bitcoin-29.0-win64-codesigning.tar.gz
d1c07f87a6d7ec3be84fb3071cbf79a0f2c1a610d0c71998e54d3d0ff543b5c3 bitcoin-29.0-win64-debug.zip
4e161b0fbe72f41124d94019e014c6e5aa87761253373fcba3926f419f861f76 bitcoin-29.0-win64-setup-unsigned.exe
8adb995aae3ff69922b4d6ab5d8fb4093bdc5984d80121a62684a37f483dccc1 bitcoin-29.0-win64-unsigned.zip
6 changes: 5 additions & 1 deletion node/src/client_versions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@

#![allow(unused_imports)] // Not all users need the json types.

#[cfg(feature = "28_1")]
#[cfg(feature = "29_0")]
pub use corepc_client::{client_sync::v29::*, types::v29 as vtype};

#[cfg(all(feature = "28_1", not(feature = "29_0")))]
pub use corepc_client::{client_sync::v28::*, types::v28 as vtype};

#[cfg(all(feature = "28_0", not(feature = "28_1")))]
Expand Down Expand Up @@ -60,6 +63,7 @@ pub use corepc_client::{client_sync::v17::*, types::v17 as vtype};
/// This is meaningless but we need it otherwise we can't get far enough into
/// the build process to trigger the `compile_error!` in `./versions.rs`.
#[cfg(all(
not(feature = "29_0"),
not(feature = "28_1"),
not(feature = "28_0"),
not(feature = "27_2"),
Expand Down
7 changes: 6 additions & 1 deletion node/src/versions.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// An explicit version of Bitcoin Core must be selected by enabling some feature.
// We check this here instead of in `lib.rs` because this file is included in `build.rs`.
#[cfg(all(
not(feature = "29_0"),
not(feature = "28_1"),
not(feature = "28_0"),
not(feature = "27_2"),
Expand All @@ -21,8 +22,11 @@
))]
compile_error!("enable a feature in order to select the version of Bitcoin Core to use");

#[cfg(feature = "28_1")]
#[cfg(feature = "29_0")]
#[allow(dead_code)] // Triggers in --all-features builds.
pub const VERSION: &str = "29.0";

#[cfg(all(feature = "28_1", not(feature = "29_0")))]
pub const VERSION: &str = "28.1";

#[cfg(all(feature = "28_0", not(feature = "28_1")))]
Expand Down Expand Up @@ -76,6 +80,7 @@ pub const VERSION: &str = "0.17.2";
/// This is meaningless but we need it otherwise we can't get far enough into
/// the build process to trigger the `compile_error!` in `./versions.rs`.
#[cfg(all(
not(feature = "29_0"),
not(feature = "28_1"),
not(feature = "28_0"),
not(feature = "27_2"),
Expand Down
Loading