diff --git a/.github/workflows/rust.yaml b/.github/workflows/rust.yaml index 77f86d93..b6410aa4 100644 --- a/.github/workflows/rust.yaml +++ b/.github/workflows/rust.yaml @@ -128,15 +128,10 @@ jobs: version: [ "30_2", - # Don't integration test v30.0 and v30.1 as the binaries have been - # removed due to a wallet migration bug. + # No `30_0` or `30_1` because of wallet migration bug. "29_0", "28_2", - "28_1", - "28_0", "27_2", - "27_1", - "27_0", "26_2", "25_2", "24_2", diff --git a/bitcoind/Cargo.toml b/bitcoind/Cargo.toml index 85b61410..685c58b2 100644 --- a/bitcoind/Cargo.toml +++ b/bitcoind/Cargo.toml @@ -34,31 +34,28 @@ zip = { version = "0.6.6", default-features = false, features = ["bzip2", "defla # Please note, it is expected that a single version feature will be enabled however if you enable # multiple the highest version number will take precedence. # +# - `cargo test --features=latest,download` to download the latest version of Core that we support. # - `cargo test --features=27_2,download` to download Bitcoin Core binary `v27.2`. # - `cargo test --features=28_0` to use `bitcoind` from the host environment. # - `cargo test` is equivalent to `cargo test --features=0_17_2`. -# - `cargo test --all-features`: Same as using latest version. -# - `cargo test --no-default-features` does not work, you MUST enable a version feature. +# - `cargo test --all-features`: Will download latest version of Core we support. +# - `cargo test --no-default-features` does not build, you MUST enable a version feature. [features] default = ["0_17_2"] +# TODO: Set this to 31_0 after all the TODOs are cleared from `types/src/v31/mod.rs`. +latest = ["30_2"] download = ["anyhow", "bitcoin_hashes", "flate2", "tar", "bitreq", "zip"] -latest = ["30_2"] - -# We support all minor releases of the latest four versions. -30_2 = ["30_0"] -# Skip v30.1 due to wallet migration bug. -30_0 = ["29_0"] +# We support all minor releases of the latest three versions. +31_0 = ["30_2"] +30_2 = ["29_0"] +# No `30_0` or `30_1` because of wallet migration bug. 29_0 = ["28_2"] -28_2 = ["28_1"] -28_1 = ["28_0"] -28_0 = ["27_2"] -27_2 = ["27_1"] -27_1 = ["27_0"] -27_0 = ["26_2"] # We only support the latest minor version for older versions. +28_2 = ["27_2"] +27_2 = ["26_2"] 26_2 = ["25_2"] 25_2 = ["24_2"] 24_2 = ["23_2"] diff --git a/bitcoind/build.rs b/bitcoind/build.rs index dc65b55b..6ec90208 100644 --- a/bitcoind/build.rs +++ b/bitcoind/build.rs @@ -95,7 +95,7 @@ mod download { #[cfg(not(target_os = "windows"))] let cache_complete = existing_filename.exists() && version_dir.join("bin").join("bitcoin-cli").exists() - && (!cfg!(feature = "30_0") + && (!cfg!(feature = "30_2") || version_dir.join("libexec").join("bitcoin-node").exists()); #[cfg(target_os = "windows")] let cache_complete = existing_filename.exists(); diff --git a/bitcoind/sha256/bitcoin-core-31.0-SHA256SUMS b/bitcoind/sha256/bitcoin-core-31.0-SHA256SUMS new file mode 100644 index 00000000..ee4cc99f --- /dev/null +++ b/bitcoind/sha256/bitcoin-core-31.0-SHA256SUMS @@ -0,0 +1,28 @@ +91917647aaf50965fc834e048256fce17e8f5590658c7e8de2879fb66cdc9a73 bitcoin-31.0-aarch64-linux-gnu-debug.tar.gz +4de1d568dedd48604f75132421bc0abeca432639589b49a3909c81db3a813112 bitcoin-31.0-aarch64-linux-gnu.tar.gz +fc17562b66707d0c8d1863af0cd40d7c6818a8d7d7b360b8d43276b1593924d9 bitcoin-31.0-arm-linux-gnueabihf-debug.tar.gz +8c19d007bfc73502625095ea4073af3a98ceb722d500556ab173bac5bcadd0d6 bitcoin-31.0-arm-linux-gnueabihf.tar.gz +a2d7a13b4da53d4a3e4c517f3a0269e2429813417bb320d3b268993cfdc545d0 bitcoin-31.0-arm64-apple-darwin.tar.gz +fc119a34915daac57e5fbdf181c9295d862d6843d52a9380e39dc0d0ac69cf20 bitcoin-31.0-arm64-apple-darwin.zip +955563c720b4d5fc22a11d4b102940d605f1cb9eb0b564f50deb606412c631e5 bitcoin-31.0-arm64-apple-darwin-codesigning.tar.gz +48d34a140aeaacd63a4bd37c24ed1876df4b077c98a7e0dd9a4483d1032839f4 bitcoin-31.0-arm64-apple-darwin-unsigned.tar.gz +b639946d343114cca5d87b218aaece04d0d111374b725d90dffc7e2d1d3b99f5 bitcoin-31.0-arm64-apple-darwin-unsigned.zip +7e45bab1787af974307fc077e6688d3eaab6788f3ad0e3a65d8cc9e428c41219 bitcoin-31.0-codesignatures-31.0.tar.gz +0ba0ef5eea3aefd96cc1774be274c3d594812cfac0988809d706738bb067b3e3 bitcoin-31.0.tar.gz +efe3e7d0383d54e5d79ac47911be0100b99872fa5205510a2a22d1194a0212d8 bitcoin-31.0-powerpc64-linux-gnu-debug.tar.gz +1d9c865aa0ccf675fc068e79d9fa57a5a70b59132fca38bb322a7d44ce2f0ff2 bitcoin-31.0-powerpc64-linux-gnu.tar.gz +acd0e38f4bb99c7c3024e494ca218d3ae67ec4a8b3b7ae556a8292353fe308b5 bitcoin-31.0-riscv64-linux-gnu-debug.tar.gz +7ece4ea365bba9b2008b27f0717ef6a518598a572edaa2815e775faadc53c136 bitcoin-31.0-riscv64-linux-gnu.tar.gz +56824dd705bc2a3b22d42e8aa02ed53498d491ff7c2c8aa96831333871887ead bitcoin-31.0-x86_64-apple-darwin.tar.gz +8e230f36a2020072763adf742b20d95348cb20aaa0b0a918ca44ecdc83ac4efd bitcoin-31.0-x86_64-apple-darwin.zip +fccf54f31bd58a3f834add05fa5df36520313d936445c556be8f71ccf314b658 bitcoin-31.0-x86_64-apple-darwin-codesigning.tar.gz +d1d0174f07cf87d9af4318f7072350510fa0f1bf8d3d3b1ee7143ad5967b6bdf bitcoin-31.0-x86_64-apple-darwin-unsigned.tar.gz +b8d9b9915a1871ee12a3a9883fd47860028454fcd192864735f2e0d3a88b4735 bitcoin-31.0-x86_64-apple-darwin-unsigned.zip +96e3506195c5cc2ea9ca72fb2ddcbcf5246dd0db0d21d726f3c98eaf0c6b9078 bitcoin-31.0-x86_64-linux-gnu-debug.tar.gz +d3e4c58a35b1d0a97a457462c94f55501ad167c660c245cb1ffa565641c65074 bitcoin-31.0-x86_64-linux-gnu.tar.gz +1893e819d7554ca43e6e812dc642bd1fb4570a4077b07a03180ad1041e74e223 bitcoin-31.0-win64-setup.exe +82fd2c504a0f20a31d4d13bd407783d6fc7bf17622d0ce85228a9b92694e03f0 bitcoin-31.0-win64.zip +62baf547357029ac557d6fbbe91742c4ba6c1461c19ed4fab5131d4300b74d93 bitcoin-31.0-win64-codesigning.tar.gz +df3f8c2f6ce8fde8d2661d3c01f5265f90f938019d52e2f94acf2a9001af70ae bitcoin-31.0-win64-debug.zip +ad31d4d82a0ddcf1340a447575ca958ee664656ca2e77282737898e1b8209ec8 bitcoin-31.0-win64-setup-unsigned.exe +5ecd365b53a2896850178f90302375480933e6c85ef81bb8abe8675fd44e1d9c bitcoin-31.0-win64-unsigned.zip diff --git a/bitcoind/src/client_versions.rs b/bitcoind/src/client_versions.rs index 93194eb3..b5409369 100644 --- a/bitcoind/src/client_versions.rs +++ b/bitcoind/src/client_versions.rs @@ -6,31 +6,19 @@ #![allow(unused_imports)] // Not all users need the json types. -#[cfg(feature = "30_0")] +#[cfg(feature = "30_2")] pub use corepc_client::{client_sync::v30::*, types::v30 as vtype}; -#[cfg(all(feature = "29_0", not(feature = "30_0")))] +#[cfg(all(feature = "29_0", not(feature = "30_2")))] pub use corepc_client::{client_sync::v29::*, types::v29 as vtype}; #[cfg(all(feature = "28_2", not(feature = "29_0")))] pub use corepc_client::{client_sync::v28::*, types::v28 as vtype}; -#[cfg(all(feature = "28_1", not(feature = "28_2")))] -pub use corepc_client::{client_sync::v28::*, types::v28 as vtype}; - -#[cfg(all(feature = "28_0", not(feature = "28_1")))] -pub use corepc_client::{client_sync::v28::*, types::v28 as vtype}; - -#[cfg(all(feature = "27_2", not(feature = "28_0")))] -pub use corepc_client::{client_sync::v27::*, types::v27 as vtype}; - -#[cfg(all(feature = "27_1", not(feature = "27_2")))] -pub use corepc_client::{client_sync::v27::*, types::v27 as vtype}; - -#[cfg(all(feature = "27_0", not(feature = "27_1")))] +#[cfg(all(feature = "27_2", not(feature = "28_2")))] pub use corepc_client::{client_sync::v27::*, types::v27 as vtype}; -#[cfg(all(feature = "26_2", not(feature = "27_0")))] +#[cfg(all(feature = "26_2", not(feature = "27_2")))] pub use corepc_client::{client_sync::v26::*, types::v26 as vtype}; #[cfg(all(feature = "25_2", not(feature = "26_2")))] @@ -62,24 +50,5 @@ 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 = "30_0"), - not(feature = "29_0"), - not(feature = "28_2"), - not(feature = "28_1"), - not(feature = "28_0"), - not(feature = "27_2"), - not(feature = "27_1"), - not(feature = "27_0"), - not(feature = "26_2"), - not(feature = "25_2"), - not(feature = "24_2"), - not(feature = "23_2"), - not(feature = "22_1"), - not(feature = "0_21_2"), - not(feature = "0_20_2"), - not(feature = "0_19_1"), - not(feature = "0_18_1"), - not(feature = "0_17_2"), -))] +#[cfg(not(feature = "0_17_2"))] // Remember: later version features enable earlier ones. pub use corepc_client::{client_sync::v28::*, types::v28 as vtype}; diff --git a/bitcoind/src/versions.rs b/bitcoind/src/versions.rs index bebac683..4a08d91a 100644 --- a/bitcoind/src/versions.rs +++ b/bitcoind/src/versions.rs @@ -1,57 +1,25 @@ // 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 = "30_2"), - not(feature = "30_0"), - not(feature = "29_0"), - not(feature = "28_2"), - not(feature = "28_1"), - not(feature = "28_0"), - not(feature = "27_2"), - not(feature = "27_1"), - not(feature = "27_0"), - not(feature = "26_2"), - not(feature = "25_2"), - not(feature = "24_2"), - not(feature = "23_2"), - not(feature = "22_1"), - not(feature = "0_21_2"), - not(feature = "0_20_2"), - not(feature = "0_19_1"), - not(feature = "0_18_1"), - not(feature = "0_17_2") -))] +#[cfg(not(feature = "0_17_2"))] // Remember: later version features enable earlier ones. compile_error!("enable a feature in order to select the version of Bitcoin Core to use"); -#[cfg(feature = "30_2")] +#[cfg(feature = "31_0")] #[allow(dead_code)] // Triggers in --all-features builds. -pub const VERSION: &str = "30.2"; +pub const VERSION: &str = "31.0"; -#[cfg(all(feature = "30_0", not(feature = "30_2")))] -pub const VERSION: &str = "30.0"; +#[cfg(all(feature = "30_2", not(feature = "31_0")))] +pub const VERSION: &str = "30.2"; -#[cfg(all(feature = "29_0", not(feature = "30_0")))] +#[cfg(all(feature = "29_0", not(feature = "30_2")))] pub const VERSION: &str = "29.0"; #[cfg(all(feature = "28_2", not(feature = "29_0")))] pub const VERSION: &str = "28.2"; -#[cfg(all(feature = "28_1", not(feature = "28_2")))] -pub const VERSION: &str = "28.1"; - -#[cfg(all(feature = "28_0", not(feature = "28_1")))] -pub const VERSION: &str = "28.0"; - -#[cfg(all(feature = "27_2", not(feature = "28_0")))] +#[cfg(all(feature = "27_2", not(feature = "28_2")))] pub const VERSION: &str = "27.2"; -#[cfg(all(feature = "27_1", not(feature = "27_2")))] -pub const VERSION: &str = "27.1"; - -#[cfg(all(feature = "27_0", not(feature = "27_1")))] -pub const VERSION: &str = "27.0"; - -#[cfg(all(feature = "26_2", not(feature = "27_0")))] +#[cfg(all(feature = "26_2", not(feature = "27_2")))] pub const VERSION: &str = "26.2"; #[cfg(all(feature = "25_2", not(feature = "26_2")))] @@ -83,24 +51,5 @@ 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 = "30_0"), - not(feature = "29_0"), - not(feature = "28_2"), - not(feature = "28_1"), - not(feature = "28_0"), - not(feature = "27_2"), - not(feature = "27_1"), - not(feature = "27_0"), - not(feature = "26_2"), - not(feature = "25_2"), - not(feature = "24_2"), - not(feature = "23_2"), - not(feature = "22_1"), - not(feature = "0_21_2"), - not(feature = "0_20_2"), - not(feature = "0_19_1"), - not(feature = "0_18_1"), - not(feature = "0_17_2") -))] +#[cfg(not(feature = "0_17_2"))] // Remember: later version features enable earlier ones. pub const VERSION: &str = "never-used"; diff --git a/client/src/client_sync/mod.rs b/client/src/client_sync/mod.rs index baaf3f8b..38dd1170 100644 --- a/client/src/client_sync/mod.rs +++ b/client/src/client_sync/mod.rs @@ -17,6 +17,7 @@ pub mod v27; pub mod v28; pub mod v29; pub mod v30; +pub mod v31; use std::fs::File; use std::io::{BufRead, BufReader}; diff --git a/client/src/client_sync/v31/blockchain.rs b/client/src/client_sync/v31/blockchain.rs new file mode 100644 index 00000000..b8ebf41e --- /dev/null +++ b/client/src/client_sync/v31/blockchain.rs @@ -0,0 +1,22 @@ +// 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 `v31`. +//! +//! All macros require `Client` to be in scope. +//! +//! See or use the `define_jsonrpc_bitreq_client!` macro to define a `Client`. + +/// Implements Bitcoin Core JSON-RPC API method `getmempoolcluster`. +#[macro_export] +macro_rules! impl_client_v31__get_mempool_cluster { + () => { + impl Client { + pub fn get_mempool_cluster(&self, txid: Txid) -> Result { + self.call("getmempoolcluster", &[into_json(txid)?]) + } + } + }; +} diff --git a/client/src/client_sync/v31/mod.rs b/client/src/client_sync/v31/mod.rs new file mode 100644 index 00000000..41b21ddc --- /dev/null +++ b/client/src/client_sync/v31/mod.rs @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! A JSON-RPC client for testing against Bitcoin Core `v31`. +//! +//! We ignore option arguments unless they effect the shape of the returned JSON data. + +pub mod blockchain; +pub mod raw_transactions; + +use std::collections::BTreeMap; +use std::path::Path; + +use bitcoin::address::{Address, NetworkChecked}; +use bitcoin::{sign_message, Amount, Block, BlockHash, PublicKey, Txid}; +use serde_json::json; + +use crate::client_sync::into_json; +use crate::types::v31::*; + +#[rustfmt::skip] // Keep public re-exports separate. +pub use crate::client_sync::{ + v17::{ + AddNodeCommand, ImportMultiRequest, ImportMultiScriptPubKey, ImportMultiTimestamp, Input, Output, SetBanCommand, WalletCreateFundedPsbtInput, + FeeEstimateMode, + }, + v21::ImportDescriptorsRequest, + v23::AddressType, + v29::{TemplateRequest, TemplateRules} +}; + +crate::define_jsonrpc_bitreq_client!("v31"); +crate::impl_client_check_expected_server_version!({ [310000] }); + +// == Blockchain == +crate::impl_client_v29__dump_tx_out_set!(); +crate::impl_client_v17__get_best_block_hash!(); +crate::impl_client_v29__get_block!(); +crate::impl_client_v17__get_blockchain_info!(); +crate::impl_client_v17__get_block_count!(); +crate::impl_client_v19__get_block_filter!(); +crate::impl_client_v23__get_block_from_peer!(); +crate::impl_client_v17__get_block_hash!(); +crate::impl_client_v17__get_block_header!(); +crate::impl_client_v17__get_block_stats!(); +crate::impl_client_v26__get_chain_states!(); +crate::impl_client_v17__get_chain_tips!(); +crate::impl_client_v17__get_chain_tx_stats!(); +crate::impl_client_v23__get_deployment_info!(); +crate::impl_client_v30__get_descriptor_activity!(); +crate::impl_client_v17__get_difficulty!(); +crate::impl_client_v17__get_mempool_ancestors!(); +crate::impl_client_v31__get_mempool_cluster!(); +crate::impl_client_v17__get_mempool_descendants!(); +crate::impl_client_v17__get_mempool_entry!(); +crate::impl_client_v17__get_mempool_info!(); +crate::impl_client_v21__get_raw_mempool!(); +crate::impl_client_v17__get_tx_out!(); +crate::impl_client_v17__get_tx_out_proof!(); +crate::impl_client_v26__get_tx_out_set_info!(); +crate::impl_client_v24__get_tx_spending_prevout!(); +crate::impl_client_v26__import_mempool!(); +crate::impl_client_v26__load_tx_out_set!(); +crate::impl_client_v17__precious_block!(); +crate::impl_client_v17__prune_blockchain!(); +crate::impl_client_v23__save_mempool!(); +crate::impl_client_v25__scan_blocks!(); +crate::impl_client_v17__scan_tx_out_set!(); +crate::impl_client_v17__verify_chain!(); +crate::impl_client_v17__verify_tx_out_proof!(); +crate::impl_client_v17__estimate_raw_fee!(); +crate::impl_client_v17__wait_for_block!(); +crate::impl_client_v17__wait_for_block_height!(); +crate::impl_client_v17__wait_for_new_block!(); + +// == Control == +crate::impl_client_v17__get_memory_info!(); +crate::impl_client_v18__get_rpc_info!(); +crate::impl_client_v17__help!(); +crate::impl_client_v17__logging!(); +crate::impl_client_v17__stop!(); +crate::impl_client_v17__uptime!(); + +// == Generating == +crate::impl_client_v25__generate_block!(); +crate::impl_client_v17__generate_to_address!(); +crate::impl_client_v20__generate_to_descriptor!(); +crate::impl_client_v17__invalidate_block!(); + +// == Hidden == +crate::impl_client_v27__add_connection!(); +crate::impl_client_v21__add_peer_address!(); +crate::impl_client_v29__get_orphan_txs!(); +crate::impl_client_v29__get_orphan_txs_verbosity_1!(); +crate::impl_client_v29__get_orphan_txs_verbosity_2!(); +crate::impl_client_v26__get_raw_addrman!(); +crate::impl_client_v20__mock_scheduler!(); +crate::impl_client_v17__reconsider_block!(); +crate::impl_client_v17__sync_with_validation_interface_queue!(); + +// == Mining == +crate::impl_client_v17__get_block_template!(); +crate::impl_client_v17__get_mining_info!(); +crate::impl_client_v17__get_network_hashes_per_second!(); +crate::impl_client_v26__get_prioritised_transactions!(); +crate::impl_client_v17__prioritise_transaction!(); +crate::impl_client_v17__submit_block!(); +crate::impl_client_v18__submit_header!(); + +// == Network == +crate::impl_client_v17__add_node!(); +crate::impl_client_v17__clear_banned!(); +crate::impl_client_v17__disconnect_node!(); +crate::impl_client_v17__get_added_node_info!(); +crate::impl_client_v26__get_addr_man_info!(); +crate::impl_client_v17__get_connection_count!(); +crate::impl_client_v17__get_net_totals!(); +crate::impl_client_v17__get_network_info!(); +crate::impl_client_v18__get_node_addresses!(); +crate::impl_client_v17__get_peer_info!(); +crate::impl_client_v17__list_banned!(); +crate::impl_client_v17__ping!(); +crate::impl_client_v17__set_ban!(); +crate::impl_client_v17__set_network_active!(); + +// == Rawtransactions == +crate::impl_client_v31__abort_private_broadcast!(); +crate::impl_client_v18__analyze_psbt!(); +crate::impl_client_v17__combine_psbt!(); +crate::impl_client_v17__combine_raw_transaction!(); +crate::impl_client_v17__convert_to_psbt!(); +crate::impl_client_v17__create_psbt!(); +crate::impl_client_v17__create_raw_transaction!(); +crate::impl_client_v17__decode_psbt!(); +crate::impl_client_v17__decode_raw_transaction!(); +crate::impl_client_v17__decode_script!(); +crate::impl_client_v17__finalize_psbt!(); +crate::impl_client_v17__fund_raw_transaction!(); +crate::impl_client_v31__get_private_broadcast_info!(); +crate::impl_client_v17__get_raw_transaction!(); +crate::impl_client_v18__join_psbts!(); +crate::impl_client_v17__send_raw_transaction!(); +crate::impl_client_v17__sign_raw_transaction!(); +crate::impl_client_v17__sign_raw_transaction_with_key!(); +crate::impl_client_v28__submit_package!(); +crate::impl_client_v17__test_mempool_accept!(); +crate::impl_client_v18__utxo_update_psbt!(); + +// == Signer == +crate::impl_client_v22__enumerate_signers!(); + +// == Util == +crate::impl_client_v17__create_multisig!(); +crate::impl_client_v29__derive_addresses!(); +crate::impl_client_v17__estimate_smart_fee!(); +crate::impl_client_v18__get_descriptor_info!(); +crate::impl_client_v21__get_index_info!(); +crate::impl_client_v17__sign_message_with_priv_key!(); +crate::impl_client_v17__validate_address!(); +crate::impl_client_v17__verify_message!(); + +// == Wallet == +crate::impl_client_v17__abandon_transaction!(); +crate::impl_client_v17__abort_rescan!(); +crate::impl_client_v17__backup_wallet!(); +crate::impl_client_v17__bump_fee!(); +crate::impl_client_v22__create_wallet!(); +crate::impl_client_v23__create_wallet!(); +crate::impl_client_v28__create_wallet_descriptor!(); +crate::impl_client_v17__encrypt_wallet!(); +crate::impl_client_v17__get_addresses_by_label!(); +crate::impl_client_v17__get_address_info!(); +crate::impl_client_v17__get_balance!(); +crate::impl_client_v19__get_balances!(); +crate::impl_client_v28__get_hd_keys!(); +crate::impl_client_v18__get_received_by_label!(); +crate::impl_client_v17__get_new_address!(); +crate::impl_client_v17__get_raw_change_address!(); +crate::impl_client_v17__get_received_by_address!(); +crate::impl_client_v17__get_transaction!(); +crate::impl_client_v17__get_wallet_info!(); +crate::impl_client_v21__import_descriptors!(); +crate::impl_client_v17__import_pruned_funds!(); +crate::impl_client_v17__key_pool_refill!(); +crate::impl_client_v17__list_address_groupings!(); +crate::impl_client_v22__list_descriptors!(); +crate::impl_client_v18__list_received_by_label!(); +crate::impl_client_v17__list_labels!(); +crate::impl_client_v17__list_lock_unspent!(); +crate::impl_client_v17__list_received_by_address!(); +crate::impl_client_v17__list_since_block!(); +crate::impl_client_v17__list_transactions!(); +crate::impl_client_v17__list_unspent!(); +crate::impl_client_v18__list_wallet_dir!(); +crate::impl_client_v17__list_wallets!(); +crate::impl_client_v22__load_wallet!(); +crate::impl_client_v17__lock_unspent!(); +crate::impl_client_v24__migrate_wallet!(); +crate::impl_client_v21__psbt_bump_fee!(); +crate::impl_client_v17__remove_pruned_funds!(); +crate::impl_client_v17__rescan_blockchain!(); +crate::impl_client_v23__restore_wallet!(); +crate::impl_client_v21__send!(); +crate::impl_client_v24__send_all!(); +crate::impl_client_v17__send_many!(); +crate::impl_client_v21__send_many_verbose!(); +crate::impl_client_v17__send_to_address!(); +crate::impl_client_v19__set_wallet_flag!(); +crate::impl_client_v17__sign_message!(); +crate::impl_client_v17__sign_raw_transaction_with_wallet!(); +crate::impl_client_v24__simulate_raw_transaction!(); +crate::impl_client_v21__unload_wallet!(); +crate::impl_client_v17__wallet_create_funded_psbt!(); +crate::impl_client_v22__wallet_display_address!(); +crate::impl_client_v17__wallet_lock!(); +crate::impl_client_v17__wallet_passphrase!(); +crate::impl_client_v17__wallet_passphrase_change!(); +crate::impl_client_v17__wallet_process_psbt!(); + +// == Zmq == +crate::impl_client_v17__get_zmq_notifications!(); diff --git a/client/src/client_sync/v31/raw_transactions.rs b/client/src/client_sync/v31/raw_transactions.rs new file mode 100644 index 00000000..ca53487e --- /dev/null +++ b/client/src/client_sync/v31/raw_transactions.rs @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Macros for implementing JSON-RPC methods on a client. +//! +//! Specifically this is methods found under the `== Rawtransactions ==` section of the +//! API docs of Bitcoin Core `v31`. +//! +//! All macros require `Client` to be in scope. +//! +//! See or use the `define_jsonrpc_bitreq_client!` macro to define a `Client`. + +/// Implements Bitcoin Core JSON-RPC API method `abortprivatebroadcast`. +#[macro_export] +macro_rules! impl_client_v31__abort_private_broadcast { + () => { + impl Client { + pub fn abort_private_broadcast(&self, id: &str) -> Result { + self.call("abortprivatebroadcast", &[id.into()]) + } + } + }; +} + +/// Implements Bitcoin Core JSON-RPC API method `getprivatebroadcastinfo`. +#[macro_export] +macro_rules! impl_client_v31__get_private_broadcast_info { + () => { + impl Client { + pub fn get_private_broadcast_info(&self) -> Result { + self.call("getprivatebroadcastinfo", &[]) + } + } + }; +} diff --git a/integration_test/Cargo.toml b/integration_test/Cargo.toml index 48532305..d2e0ee3a 100644 --- a/integration_test/Cargo.toml +++ b/integration_test/Cargo.toml @@ -16,18 +16,14 @@ download = ["bitcoind/download"] latest = ["30_2"] # Enable the same feature in `bitcoind` and the version feature here. -# All minor releases of the latest four versions. +# All minor releases of the latest three versions. +31_0 = ["v31_and_below", "bitcoind/31_0"] 30_2 = ["v30_and_below", "bitcoind/30_2"] -# Skip v30.1 due to wallet migration bug. -30_0 = ["v30_and_below", "bitcoind/30_0"] +# No `30_0` or `30_1` because of wallet migration bug. 29_0 = ["v29_and_below", "bitcoind/29_0"] +# Only the latest minor version for older versions. 28_2 = ["v28_and_below", "bitcoind/28_2"] -28_1 = ["v28_and_below", "bitcoind/28_1"] -28_0 = ["v28_and_below", "bitcoind/28_0"] 27_2 = ["v27_and_below", "bitcoind/27_2"] -27_1 = ["v27_and_below", "bitcoind/27_1"] -27_0 = ["v27_and_below", "bitcoind/27_0"] -# Only the latest minor version for older versions. 26_2 = ["v26_and_below", "bitcoind/26_2"] 25_2 = ["v25_and_below", "bitcoind/25_2"] 24_2 = ["v24_and_below", "bitcoind/24_2"] @@ -43,7 +39,8 @@ latest = ["30_2"] # Each major version is tested with the same client. # A specific range of versions can be specified e.g. for 24-26: # #[cfg(all(feature = "v26_and_below", not(feature = "v23_and_below")))] -v30_and_below = [] +v31_and_below = [] +v30_and_below = ["v31_and_below"] v29_and_below = ["v30_and_below"] v28_and_below = ["v29_and_below"] v27_and_below = ["v28_and_below"] diff --git a/integration_test/README.md b/integration_test/README.md index 70497baa..3c66072b 100644 --- a/integration_test/README.md +++ b/integration_test/README.md @@ -32,4 +32,5 @@ alias test27='BITCOIND_EXE=/opt/bitcoin-27.2/bin/bitcoind cargo test --features= alias test28='BITCOIND_EXE=/opt/bitcoin-28.2/bin/bitcoind cargo test --features=28_2' alias test29='BITCOIND_EXE=/opt/bitcoin-29.0/bin/bitcoind cargo test --features=29_0' alias test30='BITCOIND_EXE=/opt/bitcoin-30.2/bin/bitcoind cargo test --features=30_2' +alias test31='BITCOIND_EXE=/opt/bitcoin-31.0/bin/bitcoind cargo test --features=31_0' ``` diff --git a/integration_test/tests/blockchain.rs b/integration_test/tests/blockchain.rs index 1eb4e474..a88e3bb1 100644 --- a/integration_test/tests/blockchain.rs +++ b/integration_test/tests/blockchain.rs @@ -4,6 +4,7 @@ #![allow(non_snake_case)] // Test names intentionally use double underscore. +#[cfg(feature = "v30_and_below")] use bitcoin::consensus::encode; use bitcoin::hex; use bitcoind::vtype::*; // All the version specific types. @@ -140,6 +141,7 @@ fn blockchain__get_best_block_hash__modelled() { } #[test] +#[cfg(feature = "v30_and_below")] fn blockchain__get_block__modelled() { let node = BitcoinD::with_wallet(Wallet::None, &[]); let block_hash = node.client.best_block_hash().expect("best_block_hash failed"); @@ -234,6 +236,7 @@ fn blockchain__get_block_filter__modelled() { } #[test] +#[cfg(feature = "v30_and_below")] #[cfg(not(feature = "v22_and_below"))] fn blockchain__get_block_from_peer() { use bitcoin::hashes::Hash; @@ -379,6 +382,7 @@ fn blockchain__get_chain_tx_stats__modelled() { } #[test] +#[cfg(feature = "v30_and_below")] #[cfg(not(feature = "v22_and_below"))] fn blockchain__get_deployment_info__modelled() { let node = BitcoinD::with_wallet(Wallet::Default, &[]); @@ -460,6 +464,7 @@ fn blockchain__get_mempool_ancestors__modelled() { } #[test] +#[cfg(feature = "v30_and_below")] fn blockchain__get_mempool_ancestors_verbose__modelled() { let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); @@ -490,6 +495,7 @@ fn blockchain__get_mempool_descendants__modelled() { } #[test] +#[cfg(feature = "v30_and_below")] fn blockchain__get_mempool_descendants_verbose__modelled() { let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); @@ -508,6 +514,7 @@ fn blockchain__get_mempool_descendants_verbose__modelled() { } #[test] +#[cfg(feature = "v30_and_below")] fn blockchain__get_mempool_entry__modelled() { let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); @@ -519,6 +526,7 @@ fn blockchain__get_mempool_entry__modelled() { } #[test] +#[cfg(feature = "v30_and_below")] fn blockchain__get_mempool_info__modelled() { let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); @@ -533,6 +541,7 @@ fn blockchain__get_mempool_info__modelled() { } #[test] +#[cfg(feature = "v30_and_below")] fn blockchain__get_raw_mempool__modelled() { let node = BitcoinD::with_wallet(Wallet::Default, &[]); node.fund_wallet(); @@ -788,6 +797,7 @@ fn blockchain__wait_for_block_height__modelled() { } #[test] +#[cfg(feature = "v30_and_below")] fn blockchain__wait_for_new_block__modelled() { let (node1, node2, _node3) = integration_test::three_node_network(); node1.fund_wallet(); diff --git a/integration_test/tests/control.rs b/integration_test/tests/control.rs index d4f10445..537110e9 100644 --- a/integration_test/tests/control.rs +++ b/integration_test/tests/control.rs @@ -27,6 +27,7 @@ fn control__help() { } #[test] +#[cfg(feature = "v30_and_below")] fn control__logging() { let node = BitcoinD::with_wallet(Wallet::None, &[]); let _: Logging = node.client.logging().unwrap(); diff --git a/integration_test/tests/hidden.rs b/integration_test/tests/hidden.rs index 4fe66a8a..3a6b9578 100644 --- a/integration_test/tests/hidden.rs +++ b/integration_test/tests/hidden.rs @@ -4,13 +4,17 @@ #![allow(non_snake_case)] // Test names intentionally use double underscore. +#[cfg(feature = "v30_and_below")] #[cfg(not(feature = "v28_and_below"))] use std::collections::HashMap; +#[cfg(feature = "v30_and_below")] #[cfg(not(feature = "v28_and_below"))] use bitcoin::hashes::Hash; +#[cfg(feature = "v30_and_below")] #[cfg(not(feature = "v28_and_below"))] use bitcoin::hex::DisplayHex; +#[cfg(feature = "v30_and_below")] #[cfg(not(feature = "v28_and_below"))] use bitcoin::{ absolute, consensus, transaction, Amount, OutPoint, ScriptBuf, Sequence, Transaction, TxIn, @@ -18,11 +22,13 @@ use bitcoin::{ }; use bitcoind::mtype; use bitcoind::vtype::*; // All the version specific types. +#[cfg(feature = "v30_and_below")] #[cfg(not(feature = "v21_and_below"))] use bitcoind::P2P; use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; #[test] +#[cfg(feature = "v30_and_below")] #[cfg(not(feature = "v21_and_below"))] fn hidden__add_connection() { let (listener, dialer, _node3) = integration_test::three_node_network(); @@ -98,6 +104,7 @@ fn hidden__estimate_raw_fee__modelled() { } #[test] +#[cfg(feature = "v30_and_below")] #[cfg(not(feature = "v28_and_below"))] fn hidden__get_orphan_txs__modelled() { // We use node1 to send node2 orphan transactions via a P2P `tx` message. diff --git a/integration_test/tests/mining.rs b/integration_test/tests/mining.rs index 7764345c..18d465a2 100644 --- a/integration_test/tests/mining.rs +++ b/integration_test/tests/mining.rs @@ -5,11 +5,14 @@ #![allow(non_snake_case)] // Test names intentionally use double underscore. use bitcoin::SignedAmount; +use bitcoind::mtype; use bitcoind::vtype::*; -use bitcoind::{mtype, TemplateRequest, TemplateRules}; +#[cfg(feature = "v30_and_below")] +use bitcoind::{TemplateRequest, TemplateRules}; use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; // All the version specific types. #[test] +#[cfg(feature = "v30_and_below")] fn mining__get_block_template__modelled() { // Requires connected nodes otherwise the RPC call errors. let (node1, node2, node3) = integration_test::three_node_network(); diff --git a/integration_test/tests/network.rs b/integration_test/tests/network.rs index 345a7ec5..f96e8483 100644 --- a/integration_test/tests/network.rs +++ b/integration_test/tests/network.rs @@ -4,8 +4,10 @@ #![allow(non_snake_case)] // Test names intentionally use double underscore. +#[cfg(feature = "v30_and_below")] +use bitcoind::mtype; use bitcoind::vtype::*; // All the version specific types. -use bitcoind::{mtype, AddNodeCommand, SetBanCommand}; +use bitcoind::{AddNodeCommand, SetBanCommand}; use integration_test::{BitcoinD, BitcoinDExt as _, Wallet}; #[test] @@ -34,6 +36,7 @@ fn network__clear_banned() { } #[test] +#[cfg(feature = "v30_and_below")] fn network__disconnect_node() { let (_node1, node2, _node3) = integration_test::three_node_network(); @@ -75,6 +78,7 @@ fn network__get_net_totals() { } #[test] +#[cfg(feature = "v30_and_below")] fn network__get_network_info__modelled() { let node = BitcoinD::with_wallet(Wallet::None, &[]); let json: GetNetworkInfo = node.client.get_network_info().expect("getnetworkinfo"); @@ -108,17 +112,20 @@ fn network__get_node_addresses() { } #[test] +#[cfg(feature = "v30_and_below")] fn network__get_peer_info() { get_peer_info_one_node_network(); get_peer_info_three_node_network(); } +#[cfg(feature = "v30_and_below")] fn get_peer_info_one_node_network() { let node = BitcoinD::with_wallet(Wallet::None, &[]); let json: GetPeerInfo = node.client.get_peer_info().expect("getpeerinfo"); assert_eq!(json.0.len(), 0); } +#[cfg(feature = "v30_and_below")] fn get_peer_info_three_node_network() { let (node1, node2, node3) = integration_test::three_node_network(); diff --git a/types/src/lib.rs b/types/src/lib.rs index dc5b96ec..bcaff395 100644 --- a/types/src/lib.rs +++ b/types/src/lib.rs @@ -31,6 +31,7 @@ pub mod v27; pub mod v28; pub mod v29; pub mod v30; +pub mod v31; // JSON types that model _all_ `bitcoind` versions. pub mod model; diff --git a/types/src/model/blockchain.rs b/types/src/model/blockchain.rs index ef78a689..e5d7369d 100644 --- a/types/src/model/blockchain.rs +++ b/types/src/model/blockchain.rs @@ -666,6 +666,28 @@ pub struct GetDifficulty(pub f64); #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct GetMempoolAncestors(pub Vec); +/// Models the result of JSON-RPC method `getmempoolcluster`. +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +pub struct GetMempoolCluster { + /// Total sigops-adjusted weight (as defined in BIP 141 and modified by `-bytespersigop`). + /// + pub cluster_weight: u64, + /// Number of transactions. + pub tx_count: u64, + /// Chunks in this cluster (in mining order). + pub chunks: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] +pub struct Chunk { + /// Fees of the transactions in this chunk. + pub chunk_fee: Amount, + /// Sigops-adjusted weight of all transactions in this chunk. + pub chunk_weight: u64, + /// Transactions in this chunk in mining order (txids). + pub txs: Vec, +} + /// Models the result of JSON-RPC method `getmempoolancestors` with verbose set to true. #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct GetMempoolAncestorsVerbose(pub BTreeMap); diff --git a/types/src/model/mod.rs b/types/src/model/mod.rs index d078e64b..09c4661b 100644 --- a/types/src/model/mod.rs +++ b/types/src/model/mod.rs @@ -27,15 +27,15 @@ use serde::{Deserialize, Serialize}; pub use self::{ blockchain::{ ActivityEntry, Bip9Info, Bip9SoftforkInfo, Bip9SoftforkStatistics, Bip9SoftforkStatus, - Bip9Statistics, ChainState, ChainTips, ChainTipsStatus, DeploymentInfo, DumpTxOutSet, - GetBestBlockHash, GetBlockCount, GetBlockFilter, GetBlockHash, GetBlockHeader, - GetBlockHeaderVerbose, GetBlockStats, GetBlockVerboseOne, GetBlockVerboseThree, - GetBlockVerboseThreePrevout, GetBlockVerboseThreeTransaction, GetBlockVerboseTwo, - GetBlockVerboseTwoTransaction, GetBlockVerboseZero, GetBlockchainInfo, GetChainStates, - GetChainTips, GetChainTxStats, GetDeploymentInfo, GetDescriptorActivity, GetDifficulty, - GetMempoolAncestors, GetMempoolAncestorsVerbose, GetMempoolDescendants, - GetMempoolDescendantsVerbose, GetMempoolEntry, GetMempoolInfo, GetRawMempool, - GetRawMempoolSequence, GetRawMempoolVerbose, GetTxOut, GetTxOutSetInfo, + Bip9Statistics, ChainState, ChainTips, ChainTipsStatus, Chunk, DeploymentInfo, + DumpTxOutSet, GetBestBlockHash, GetBlockCount, GetBlockFilter, GetBlockHash, + GetBlockHeader, GetBlockHeaderVerbose, GetBlockStats, GetBlockVerboseOne, + GetBlockVerboseThree, GetBlockVerboseThreePrevout, GetBlockVerboseThreeTransaction, + GetBlockVerboseTwo, GetBlockVerboseTwoTransaction, GetBlockVerboseZero, GetBlockchainInfo, + GetChainStates, GetChainTips, GetChainTxStats, GetDeploymentInfo, GetDescriptorActivity, + GetDifficulty, GetMempoolAncestors, GetMempoolAncestorsVerbose, GetMempoolCluster, + GetMempoolDescendants, GetMempoolDescendantsVerbose, GetMempoolEntry, GetMempoolInfo, + GetRawMempool, GetRawMempoolSequence, GetRawMempoolVerbose, GetTxOut, GetTxOutSetInfo, GetTxOutSetInfoBlockInfo, GetTxOutSetInfoUnspendables, GetTxSpendingPrevout, GetTxSpendingPrevoutItem, LoadTxOutSet, MempoolEntry, MempoolEntryFees, ReceiveActivity, ScanBlocksStart, ScanTxOutSetStart, ScanTxOutSetUnspent, Softfork, SoftforkType, @@ -52,12 +52,13 @@ pub use self::{ }, network::{GetNetworkInfo, GetNetworkInfoAddress, GetNetworkInfoNetwork}, raw_transactions::{ - AnalyzePsbt, AnalyzePsbtInput, AnalyzePsbtInputMissing, CombinePsbt, CombineRawTransaction, - ConvertToPsbt, CreatePsbt, CreateRawTransaction, DecodePsbt, DecodeRawTransaction, - DecodeScript, DescriptorProcessPsbt, FinalizePsbt, FundRawTransaction, GetRawTransaction, - GetRawTransactionVerbose, JoinPsbts, MempoolAcceptance, MempoolAcceptanceFees, - SendRawTransaction, SignFail, SignRawTransaction, SignRawTransactionWithKey, SubmitPackage, - SubmitPackageTxResult, SubmitPackageTxResultFees, TestMempoolAccept, UtxoUpdatePsbt, + AbortPrivateBroadcast, AnalyzePsbt, AnalyzePsbtInput, AnalyzePsbtInputMissing, CombinePsbt, + CombineRawTransaction, ConvertToPsbt, CreatePsbt, CreateRawTransaction, DecodePsbt, + DecodeRawTransaction, DecodeScript, DescriptorProcessPsbt, FinalizePsbt, + FundRawTransaction, GetPrivateBroadcastInfo, GetRawTransaction, GetRawTransactionVerbose, + JoinPsbts, MempoolAcceptance, MempoolAcceptanceFees, SendRawTransaction, SignFail, + SignRawTransaction, SignRawTransactionWithKey, SubmitPackage, SubmitPackageTxResult, + SubmitPackageTxResultFees, TestMempoolAccept, UtxoUpdatePsbt, }, util::{ CreateMultisig, DeriveAddresses, DeriveAddressesMultipath, EstimateSmartFee, diff --git a/types/src/model/raw_transactions.rs b/types/src/model/raw_transactions.rs index f5583a73..d1022493 100644 --- a/types/src/model/raw_transactions.rs +++ b/types/src/model/raw_transactions.rs @@ -12,6 +12,13 @@ use bitcoin::hashes::{hash160, sha256}; use bitcoin::{Amount, BlockHash, FeeRate, Psbt, ScriptBuf, Sequence, Transaction, Txid, Wtxid}; use serde::{Deserialize, Serialize}; +/// Models the result of JSON-RPC method `abortprivatebroadcast`. +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +pub struct AbortPrivateBroadcast { + /// The removed transactions. + pub removed_transactions: Vec, +} + /// Models the result of JSON-RPC method `analyzepsbt`. #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct AnalyzePsbt { @@ -142,6 +149,14 @@ pub struct FundRawTransaction { pub change_position: i64, } +/// Models the result of JSON-RPC method `getprivatebroadcastinfo`. +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +pub struct GetPrivateBroadcastInfo { + /// The transactions currently being broadcast. + pub transactions: Vec, + // Don't bother modelling the per-peer info. +} + /// Models the result of JSON-RPC method `getrawtransaction` with verbose set to `false`. #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct GetRawTransaction(pub Transaction); diff --git a/types/src/v31/blockchain/into.rs b/types/src/v31/blockchain/into.rs new file mode 100644 index 00000000..b2d9352f --- /dev/null +++ b/types/src/v31/blockchain/into.rs @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: CC0-1.0 + +use bitcoin::{hex, Amount, Txid}; + +use super::GetMempoolCluster; +use crate::model; + +impl GetMempoolCluster { + /// Converts version specific type to a version nonspecific, more strongly typed type. + pub fn into_model(self) -> Result { + // TODO: Use combinators. + let mut chunks = vec![]; + for chunk in self.chunks { + let txs = + chunk.txs.iter().map(|txid| txid.parse::()).collect::, _>>()?; + chunks.push(model::Chunk { + chunk_fee: Amount::from_sat(chunk.chunk_fee), + chunk_weight: chunk.chunk_weight, + txs, + }) + } + + Ok(model::GetMempoolCluster { + cluster_weight: self.cluster_weight, + tx_count: self.tx_count, + chunks, + }) + } +} diff --git a/types/src/v31/blockchain/mod.rs b/types/src/v31/blockchain/mod.rs new file mode 100644 index 00000000..e258585c --- /dev/null +++ b/types/src/v31/blockchain/mod.rs @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! The JSON-RPC API for Bitcoin Core `v31` - blockchain. +//! +//! Types for methods found under the `== Blockchain ==` section of the API docs. + +mod into; + +use serde::{Deserialize, Serialize}; + +/// Result of JSON-RPC method `getmempoolcluster`. +/// +/// > getmempoolcluster "txid" +/// > +/// > Returns mempool data for given cluster +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +#[cfg_attr(feature = "serde-deny-unknown-fields", serde(deny_unknown_fields))] +pub struct GetMempoolCluster { + /// Total sigops-adjusted weight (as defined in BIP 141 and modified by `-bytespersigop`). + #[serde(rename = "clusterweight")] + pub cluster_weight: u64, + /// Number of transactions. + #[serde(rename = "txcount")] + pub tx_count: u64, + /// Chunks in this cluster (in mining order). + pub chunks: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] +pub struct Chunk { + /// Fees of the transactions in this chunk. + #[serde(rename = "chunkfee")] + // FIXME: This is probably a float. https://github.com/rust-bitcoin/corepc/pull/598#discussion_r3283795812 + pub chunk_fee: u64, + /// Sigops-adjusted weight of all transactions in this chunk. + #[serde(rename = "chunkweight")] + pub chunk_weight: u64, + /// Transactions in this chunk in mining order (txids). + pub txs: Vec, +} diff --git a/types/src/v31/mod.rs b/types/src/v31/mod.rs new file mode 100644 index 00000000..ab70b620 --- /dev/null +++ b/types/src/v31/mod.rs @@ -0,0 +1,370 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! # JSON-RPC types for Bitcoin Core `v31` +//! +//! These structs are shaped for the JSON data returned by the JSON-RPC API. They use stdlib types +//! (or custom types) and where necessary implement an `into_model` function to convert the type to +//! a [`crate::model`] type of the same name. The types in this module are version specific. The +//! types in the `model` module are version nonspecific and are strongly typed using `rust-bitcoin`. +//! +//! ### Method name and implementation status +//! +//! Every JSON-RPC method supported by this version of Bitcoin Core is listed below along with the +//! type it returns and any implementation notes. +//! +//! Key to 'Returns' column: +//! +//! * version: method returns a version specific type but has no model type. +//! * version + model: method returns a version specific type and can be converted to a model type. +//! * returns foo: method returns a foo (e.g. string, boolean, or nothing). +//! * omitted: method intentionally unsupported with no plans of adding support. +//! +//! If a method has UNTESTED then there is no integration test yet for it. +//! +//!
+//! Methods from the == Blockchain == section +//! +//! | JSON-RPC Method Name | Returns | Notes | +//! |:-----------------------------------|:---------------:|:--------------------------------------:| +//! | dumptxoutset | version + model | | +//! | getbestblockhash | version + model | | +//! | getblock | version + model | TODO: Fields have changed since v30 | +//! | getblockchaininfo | version + model | | +//! | getblockcount | version + model | | +//! | getblockfilter | version + model | | +//! | getblockfrompeer | returns nothing | TODO: Fields have changed since v30 | +//! | getblockhash | version + model | | +//! | getblockheader | version + model | Includes additional 'verbose' type | +//! | getblockstats | version + model | | +//! | getchainstates | version + model | | +//! | getchaintips | version + model | | +//! | getchaintxstats | version + model | | +//! | getdeploymentinfo | version + model | TODO: Fields have changed since v30 | | +//! | getdescriptoractivity | version + model | | +//! | getdifficulty | version + model | | +//! | getmempoolancestors | version + model | TODO: Fields have changed since v30 | +//! | getmempoolcluster | version + model | TODO: New in v31 | +//! | getmempooldescendants | version + model | TODO: Fields have changed since v30 | +//! | getmempoolentry | version + model | TODO: Fields have changed since v30 | +//! | getmempoolinfo | version + model | TODO: Fields have changed since v30 | +//! | getrawmempool | version + model | TODO: Fields have changed since v30 | +//! | gettxout | version + model | | +//! | gettxoutproof | returns string | | +//! | gettxoutsetinfo | version + model | | +//! | gettxspendingprevout | version + model | | +//! | importmempool | returns nothing | | +//! | loadtxoutset | version + model | UNTESTED | +//! | preciousblock | returns nothing | | +//! | pruneblockchain | version | | +//! | savemempool | version | | +//! | scanblocks | version + model | | +//! | scantxoutset | version + model | API marked as experimental | +//! | verifychain | version | | +//! | verifytxoutproof | version + model | | +//! | waitforblock | version + model | | +//! | waitforblockheight | version + model | | +//! | waitfornewblock | version + model | TODO: Fields have changed since v30 | +//! +//!
+//! +//!
+//! Methods from the == Control == section +//! +//! | JSON-RPC Method Name | Returns | Notes | +//! |:-----------------------------------|:---------------:|:--------------------------------------:| +//! | getmemoryinfo | version | | +//! | getrpcinfo | version | | +//! | help | returns string | | +//! | logging | version | TODO: Fields have changed since v30 | +//! | stop | returns string | | +//! | uptime | returns numeric | | +//! +//!
+//! +//!
+//! Methods from the == Mining == section +//! +//! | JSON-RPC Method Name | Returns | Notes | +//! |:-----------------------------------|:---------------:|:--------------------------------------:| +//! | getblocktemplate | version + model | TODO: Fields have changed since v30 | +//! | getmininginfo | version + model | | +//! | getnetworkhashps | returns numeric | | +//! | getprioritisedtransactions | version + model | | +//! | prioritisetransaction | returns boolean | | +//! | submitblock | returns nothing | | +//! | submitheader | returns nothing | | +//! +//!
+//! +//!
+//! Methods from the == Network == section +//! +//! | JSON-RPC Method Name | Returns | Notes | +//! |:-----------------------------------|:---------------:|:--------------------------------------:| +//! | addnode | returns nothing | | +//! | clearbanned | returns nothing | | +//! | disconnectnode | returns nothing | TODO: Fields have changed since v30 | +//! | getaddednodeinfo | version | | +//! | getaddrmaninfo | version | | +//! | getconnectioncount | version | | +//! | getnettotals | version | | +//! | getnetworkinfo | version + model | TODO: Fields have changed since v30 | +//! | getnodeaddresses | version | | +//! | getpeerinfo | version | TODO: Fields have changed since v30 | +//! | listbanned | version | | +//! | ping | returns nothing | | +//! | setban | returns nothing | | +//! | setnetworkactive | version | | +//! +//!
+//! +//!
+//! Methods from the == Rawtransactions == section +//! +//! | JSON-RPC Method Name | Returns | Notes | +//! |:-----------------------------------|:---------------:|:--------------------------------------:| +//! | abortprivatebroadcast | version + model | TODO: New in v31 | +//! | analyzepsbt | version + model | | +//! | combinepsbt | version + model | | +//! | combinerawtransaction | version + model | | +//! | converttopsbt | version + model | | +//! | createpsbt | version + model | | +//! | createrawtransaction | version + model | | +//! | decodepsbt | version + model | Musig not modelled: not in rust-bitcoin| +//! | descriptorprocesspsbt | returns boolean | | +//! | decoderawtransaction | version + model | | +//! | decodescript | version + model | | +//! | finalizepsbt | version + model | | +//! | fundrawtransaction | version + model | | +//! | getprivatebroadcastinfo | version + model | TODO: New in v31 | +//! | getrawtransaction | version + model | Includes additional 'verbose' type | +//! | joinpsbts | version + model | | +//! | sendrawtransaction | version + model | | +//! | signrawtransactionwithkey | version + model | | +//! | submitpackage | version + model | | +//! | testmempoolaccept | version + model | | +//! | utxoupdatepsbt | version + model | | +//! +//!
+//! +//!
+//! Methods from the == Signer == section +//! +//! | JSON-RPC Method Name | Returns | Notes | +//! |:-----------------------------------|:---------------:|:--------------------------------------:| +//! | enumeratesigners | version | | +//! +//!
+//! +//!
+//! Methods from the == Util == section +//! +//! | JSON-RPC Method Name | Returns | Notes | +//! |:-----------------------------------|:---------------:|:--------------------------------------:| +//! | createmultisig | version + model | | +//! | deriveaddresses | version + model | | +//! | estimatesmartfee | version + model | | +//! | getdescriptorinfo | version | | +//! | getindexinfo | version | | +//! | signmessagewithprivkey | version + model | | +//! | validateaddress | version + model | | +//! | verifymessage | version | | +//! +//!
+//! +//!
+//! Methods from the == Wallet == section +//! +//! | JSON-RPC Method Name | Returns | Notes | +//! |:-----------------------------------|:---------------:|:--------------------------------------:| +//! | abandontransaction | returns nothing | | +//! | abortrescan | version | | +//! | backupwallet | returns nothing | | +//! | bumpfee | version + model | | +//! | createwallet | version + model | | +//! | createwalletdescriptor | version | | +//! | encryptwallet | version | | +//! | getaddressesbylabel | version + model | | +//! | getaddressinfo | version + model | | +//! | getbalance | version + model | | +//! | getbalances | version + model | | +//! | gethdkeys | version + model | | +//! | getnewaddress | version + model | | +//! | getrawchangeaddress | version + model | | +//! | getreceivedbyaddress | version + model | | +//! | getreceivedbylabel | version + model | | +//! | gettransaction | version + model | | +//! | getwalletinfo | version + model | | +//! | importdescriptors | version | | +//! | importprunedfunds | returns nothing | | +//! | keypoolrefill | returns nothing | | +//! | listaddressgroupings | version + model | | +//! | listdescriptors | version | | +//! | listlabels | version | | +//! | listlockunspent | version + model | | +//! | migratewallet | version | Untested in v30, unchanged from v29 | +//! | psbtbumpfee | version + model | | +//! | listreceivedbyaddress | version + model | | +//! | listreceivedbylabel | version + model | | +//! | listsinceblock | version + model | | +//! | listtransactions | version + model | | +//! | listunspent | version + model | | +//! | listwalletdir | version | | +//! | listwallets | version + model | | +//! | loadwallet | version + model | | +//! | lockunspent | version | | +//! | removeprunedfunds | returns nothing | | +//! | rescanblockchain | version + model | | +//! | restorewallet | version | | +//! | send | version + model | | +//! | sendall | version + model | | +//! | sendmany | version + model | | +//! | sendtoaddress | version + model | | +//! | setlabel | returns nothing | | +//! | setwalletflag | version | | +//! | signmessage | version + model | | +//! | signrawtransactionwithwallet | version + model | | +//! | simulaterawtransaction | version + model | | +//! | unloadwallet | returns nothing | | +//! | walletcreatefundedpsbt | version + model | | +//! | walletdisplayaddress | version + model | | +//! | walletlock | returns nothing | | +//! | walletpassphrase | returns nothing | | +//! | walletpassphrasechange | returns nothing | | +//! | walletprocesspsbt | version + model | | +//! +//!
+//! +//!
+//! Methods from the == Zmq == section +//! +//! | JSON-RPC Method Name | Returns | Notes | +//! |:-----------------------------------|:---------------:|:--------------------------------------:| +//! | getzmqnotifications | version | | +//! +//!
+ +mod blockchain; +mod raw_transactions; + +#[doc(inline)] +pub use self::{ + blockchain::{Chunk, GetMempoolCluster}, + raw_transactions::{ + AbortPrivateBroadcast, GetPrivateBroadcastInfo, PrivateBroadcastPeer, + PrivateBroadcastTransaction, RemovedTransaction, + }, +}; +#[doc(inline)] +pub use crate::{ + v17::{ + AbortRescan, AddedNode, AddedNodeAddress, AddressInformation, AddressPurpose, + Bip125Replaceable, Bip32DerivError, BlockTemplateTransaction, + BlockTemplateTransactionError, BumpFee, BumpFeeError, ChainTips, ChainTipsError, + ChainTipsStatus, CombinePsbt, CombineRawTransaction, ConvertToPsbt, CreateMultisigError, + CreatePsbt, CreateRawTransaction, DecodeRawTransaction, EncryptWallet, EstimateRawFee, + EstimateRawFeeError, EstimateSmartFee, FinalizePsbt, FinalizePsbtError, FundRawTransaction, + FundRawTransactionError, Generate, GenerateToAddress, GetAddedNodeInfo, + GetAddressInfoEmbeddedError, GetAddressesByLabel, GetBalance, GetBestBlockHash, + GetBlockCount, GetBlockHash, GetBlockStatsError, GetBlockTemplate, GetBlockTemplateError, + GetBlockVerboseZero, GetChainTips, GetChainTxStatsError, GetConnectionCount, GetDifficulty, + GetMemoryInfoStats, GetMempoolInfoError, GetNetTotals, GetNetworkInfoAddress, + GetNetworkInfoError, GetNetworkInfoNetwork, GetNewAddress, GetRawChangeAddress, + GetRawMempool, GetRawTransaction, GetRawTransactionVerbose, GetRawTransactionVerboseError, + GetReceivedByAddress, GetTransactionDetailError, GetTxOut, GetTxOutError, + ListAddressGroupings, ListAddressGroupingsError, ListAddressGroupingsItem, ListLabels, + ListLockUnspent, ListLockUnspentItem, ListLockUnspentItemError, ListReceivedByAddressError, + ListUnspentItemError, ListWallets, LockUnspent, Locked, NumericError, + PartialSignatureError, PruneBlockchain, RawFeeDetail, RawFeeRange, RawTransactionError, + RawTransactionInput, RawTransactionOutput, RescanBlockchain, ScanTxOutSetAbort, + ScanTxOutSetError, ScanTxOutSetStatus, ScriptType, SendRawTransaction, SendToAddress, + SetNetworkActive, SetTxFee, SignFail, SignFailError, SignMessage, SignMessageWithPrivKey, + SignRawTransaction, SignRawTransactionError, SignRawTransactionWithKey, + SignRawTransactionWithWallet, TransactionCategory, UploadTarget, ValidateAddress, + ValidateAddressError, VerifyChain, VerifyMessage, VerifyTxOutProof, WaitForBlock, + WaitForBlockError, WaitForBlockHeight, WaitForBlockHeightError, WaitForNewBlock, + WaitForNewBlockError, WalletCreateFundedPsbt, WalletCreateFundedPsbtError, WitnessUtxo, + WitnessUtxoError, + }, + v18::{ + ActiveCommand, AnalyzePsbt, AnalyzePsbtError, AnalyzePsbtInput, AnalyzePsbtInputMissing, + AnalyzePsbtInputMissingError, DeriveAddresses, GetAddressInfoError, GetReceivedByLabel, + GetZmqNotifications, JoinPsbts, JsonRpcError, ListReceivedByAddress, + ListReceivedByAddressItem, ListReceivedByLabel, ListReceivedByLabelError, + ListReceivedByLabelItem, UtxoUpdatePsbt, + }, + v19::{ + Bip9SoftforkInfo, Bip9SoftforkStatistics, Bip9SoftforkStatus, GetBalancesMine, + GetBalancesWatchOnly, GetBlockFilter, GetBlockFilterError, GetChainTxStats, GetRpcInfo, + MapMempoolEntryError, MempoolEntryError, MempoolEntryFees, MempoolEntryFeesError, + SetWalletFlag, Softfork, SoftforkType, + }, + v20::GenerateToDescriptor, + v21::{ + AddPeerAddress, GetIndexInfo, GetIndexInfoName, GetRawMempoolSequence, ImportDescriptors, + ImportDescriptorsResult, PsbtBumpFee, PsbtBumpFeeError, Send, SendError, SendMany, + SendManyVerbose, + }, + v22::{ + AddConnection, Banned, EnumerateSigners, GetNodeAddresses, ListBanned, NodeAddress, + ScriptPubKey, Signers, WalletDisplayAddress, + }, + v23::{ + Bip9Info, Bip9Statistics, CreateMultisig, DecodeScript, DecodeScriptError, + DecodeScriptSegwit, DeploymentInfo, GetDeploymentInfo, GetDeploymentInfoError, + RestoreWallet, SaveMempool, + }, + v24::{ + GetMempoolAncestors, GetMempoolAncestorsVerbose, GetMempoolDescendants, + GetMempoolDescendantsVerbose, GetMempoolEntry, GetRawMempoolVerbose, GetTransactionDetail, + GetTxSpendingPrevout, GetTxSpendingPrevoutError, GetTxSpendingPrevoutItem, ListUnspent, + ListUnspentItem, MempoolEntry, MigrateWallet, SendAll, SendAllError, + SimulateRawTransaction, + }, + v25::{ + DescriptorInfo, GenerateBlock, GenerateBlockError, GetBlockStats, ListDescriptors, + MempoolAcceptanceError, ScanBlocksAbort, ScanBlocksStartError, ScanBlocksStatus, + TestMempoolAcceptError, + }, + v26::{ + AddrManInfoNetwork, CreateWallet, DescriptorProcessPsbt, DescriptorProcessPsbtError, + DumpTxOutSet, DumpTxOutSetError, GetAddrManInfo, GetBalances, GetBalancesError, + GetPeerInfo, GetTransactionError, GetTxOutSetInfo, GetTxOutSetInfoBlockInfo, + GetTxOutSetInfoError, GetTxOutSetInfoUnspendables, LoadTxOutSet, LoadTxOutSetError, + LoadWallet, PeerInfo, ScanBlocksStart, UnloadWallet, WalletProcessPsbt, + WalletProcessPsbtError, + }, + v27::{GetPrioritisedTransactions, PrioritisedTransaction}, + v28::{ + CreateWalletDescriptor, GetAddressInfo, GetAddressInfoEmbedded, GetHdKeys, GetHdKeysError, + GetNetworkInfo, GetRawAddrMan, GetTransaction, HdKey, HdKeyDescriptor, ListSinceBlock, + ListSinceBlockError, ListTransactions, Logging, RawAddrManEntry, ScanTxOutSetStart, + ScanTxOutSetUnspent, SubmitPackage, SubmitPackageError, SubmitPackageTxResult, + SubmitPackageTxResultError, SubmitPackageTxResultFees, SubmitPackageTxResultFeesError, + TransactionItem, TransactionItemError, + }, + v29::{ + ActivityEntry, ChainState, DeriveAddressesMultipath, GetBlockHeader, GetBlockHeaderError, + GetBlockHeaderVerbose, GetBlockHeaderVerboseError, GetBlockVerboseOne, + GetBlockVerboseOneError, GetBlockVerboseThree, GetBlockVerboseThreeError, + GetBlockVerboseThreePrevout, GetBlockVerboseThreeTransaction, GetBlockVerboseTwo, + GetBlockVerboseTwoError, GetBlockVerboseTwoTransaction, GetBlockchainInfo, + GetBlockchainInfoError, GetChainStates, GetChainStatesError, GetDescriptorActivity, + GetDescriptorActivityError, GetDescriptorInfo, GetOrphanTxsError, + GetOrphanTxsVerboseOneEntryError, GetOrphanTxsVerboseTwoEntryError, + GetRawTransactionVerboseWithPrevout, MempoolAcceptance, MempoolAcceptanceFees, + NextBlockInfo, NextBlockInfoError, RawTransactionInputWithPrevout, ReceiveActivity, + SpendActivity, TestMempoolAccept, + }, + v30::{ + ControlBlocksError, DecodePsbt, DecodePsbtError, GetMempoolInfo, GetMiningInfo, + GetMiningInfoError, GetOrphanTxs, GetOrphanTxsVerboseOne, GetOrphanTxsVerboseOneEntry, + GetOrphanTxsVerboseTwo, GetOrphanTxsVerboseTwoEntry, GetWalletInfo, GetWalletInfoError, + GetWalletInfoScanning, GlobalXpub, GlobalXpubError, LastProcessedBlock, + LastProcessedBlockError, ListWalletDir, ListWalletDirWallet, Musig2PartialSig, + Musig2ParticipantPubKeys, Musig2Pubnonce, Proprietary, PsbtInput, PsbtInputError, + PsbtOutput, PsbtOutputError, TaprootBip32Deriv, TaprootBip32DerivsError, TaprootLeaf, + TaprootLeafError, TaprootScript, TaprootScriptError, TaprootScriptPathSig, + TaprootScriptPathSigError, + }, +}; diff --git a/types/src/v31/raw_transactions/into.rs b/types/src/v31/raw_transactions/into.rs new file mode 100644 index 00000000..5e66d576 --- /dev/null +++ b/types/src/v31/raw_transactions/into.rs @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: CC0-1.0 + +use bitcoin::consensus::encode; +use bitcoin::Transaction; + +use super::{AbortPrivateBroadcast, GetPrivateBroadcastInfo}; +use crate::model; + +impl AbortPrivateBroadcast { + /// Converts version specific type to a version nonspecific, more strongly typed type. + pub fn into_model(self) -> Result { + let txs = self + .removed_transactions + .iter() + .map(|removed| encode::deserialize_hex::(&removed.hex)) + .collect::, _>>()?; + + Ok(model::AbortPrivateBroadcast { removed_transactions: txs }) + } +} + +impl GetPrivateBroadcastInfo { + /// Converts version specific type to a version nonspecific, more strongly typed type. + pub fn into_model(self) -> Result { + let txs = self + .transactions + .iter() + .map(|tx| encode::deserialize_hex::(&tx.hex)) + .collect::, _>>()?; + + Ok(model::GetPrivateBroadcastInfo { transactions: txs }) + } +} diff --git a/types/src/v31/raw_transactions/mod.rs b/types/src/v31/raw_transactions/mod.rs new file mode 100644 index 00000000..da237e65 --- /dev/null +++ b/types/src/v31/raw_transactions/mod.rs @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! The JSON-RPC API for Bitcoin Core `v31` - raw transactions. +//! +//! Types for methods found under the `== Rawtransactions ==` section of the API docs. + +mod into; + +use serde::{Deserialize, Serialize}; + +/// Result of JSON-RPC method `abortprivatebroadcast`. +/// +/// > abortprivatebroadcast "id" +/// > +/// > Abort private broadcast attempts for a transaction currently being privately broadcast. +/// > The transaction will be removed from the private broadcast queue. +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +#[cfg_attr(feature = "serde-deny-unknown-fields", serde(deny_unknown_fields))] +pub struct AbortPrivateBroadcast { + /// The removed transactions. + pub removed_transactions: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] +pub struct RemovedTransaction { + /// The transaction hash in hex. + pub txid: String, + /// The transaction witness hash in hex. + pub wtxid: String, + /// The serialized, hex-encoded transaction data. + pub hex: String, +} + +/// Result of JSON-RPC method `getprivatebroadcastinfo`. +/// +/// > getprivatebroadcastinfo +/// > +/// > Returns information about transactions that are currently being privately broadcast. +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] +#[cfg_attr(feature = "serde-deny-unknown-fields", serde(deny_unknown_fields))] +pub struct GetPrivateBroadcastInfo { + /// The transactions currently being broadcast. + pub transactions: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] +pub struct PrivateBroadcastTransaction { + /// The transaction hash in hex. + pub txid: String, + /// The transaction witness hash in hex. + pub wtxid: String, + /// The serialized, hex-encoded transaction data. + pub hex: String, + /// Per-peer send and acknowledgment information for this transaction. + pub peers: Vec, +} + +#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] +pub struct PrivateBroadcastPeer { + /// The address of the peer to which the transaction was sent. + pub address: String, + /// The time this transaction was picked for sending to this peer via private + /// broadcast (seconds since epoch). + pub sent: u64, + /// The time this peer acknowledged reception of the transaction (seconds since + /// epoch). + #[serde(skip_serializing_if = "Option::is_none")] + pub received: Option, +} diff --git a/verify/rpc-api-v31.txt b/verify/rpc-api-v31.txt new file mode 100644 index 00000000..98d74f6a --- /dev/null +++ b/verify/rpc-api-v31.txt @@ -0,0 +1,168 @@ +== Blockchain == +dumptxoutset "path" ( "type" {"rollback":n,...} ) +getbestblockhash +getblock "blockhash" ( verbosity ) +getblockchaininfo +getblockcount +getblockfilter "blockhash" ( "filtertype" ) +getblockfrompeer "blockhash" peer_id +getblockhash height +getblockheader "blockhash" ( verbose ) +getblockstats hash_or_height ( stats ) +getchainstates +getchaintips +getchaintxstats ( nblocks "blockhash" ) +getdeploymentinfo ( "blockhash" ) +getdescriptoractivity ["blockhash",...] [scanobjects,...] ( include_mempool ) +getdifficulty +getmempoolancestors "txid" ( verbose ) +getmempoolcluster "txid" +getmempooldescendants "txid" ( verbose ) +getmempoolentry "txid" +getmempoolinfo +getrawmempool ( verbose mempool_sequence ) +gettxout "txid" n ( include_mempool ) +gettxoutproof ["txid",...] ( "blockhash" ) +gettxoutsetinfo ( "hash_type" hash_or_height use_index ) +gettxspendingprevout [{"txid":"hex","vout":n},...] ( {"mempool_only":bool,"return_spending_tx":bool,...} ) +importmempool "filepath" ( options ) +loadtxoutset "path" +preciousblock "blockhash" +pruneblockchain height +savemempool +scanblocks "action" ( [scanobjects,...] start_height stop_height "filtertype" options ) +scantxoutset "action" ( [scanobjects,...] ) +verifychain ( checklevel nblocks ) +verifytxoutproof "proof" +waitforblock "blockhash" ( timeout ) +waitforblockheight height ( timeout ) +waitfornewblock ( timeout "current_tip" ) + +== Control == +getmemoryinfo ( "mode" ) +getrpcinfo +help ( "command" ) +logging ( ["include_category",...] ["exclude_category",...] ) +stop +uptime + +== Mining == +getblocktemplate {"mode":"str","capabilities":["str",...],"rules":["segwit","str",...],"longpollid":"str","data":"hex"} +getmininginfo +getnetworkhashps ( nblocks height ) +getprioritisedtransactions +prioritisetransaction "txid" ( dummy ) fee_delta +submitblock "hexdata" ( "dummy" ) +submitheader "hexdata" + +== Network == +addnode "node" "command" ( v2transport ) +clearbanned +disconnectnode ( "address" nodeid ) +getaddednodeinfo ( "node" ) +getaddrmaninfo +getconnectioncount +getnettotals +getnetworkinfo +getnodeaddresses ( count "network" ) +getpeerinfo +listbanned +ping +setban "subnet" "command" ( bantime absolute ) +setnetworkactive state + +== Rawtransactions == +abortprivatebroadcast "id" +analyzepsbt "psbt" +combinepsbt ["psbt",...] +combinerawtransaction ["hexstring",...] +converttopsbt "hexstring" ( permitsigdata iswitness ) +createpsbt [{"txid":"hex","vout":n,"sequence":n},...] [{"address":amount,...},{"data":"hex"},...] ( locktime replaceable version ) +createrawtransaction [{"txid":"hex","vout":n,"sequence":n},...] [{"address":amount,...},{"data":"hex"},...] ( locktime replaceable version ) +decodepsbt "psbt" +decoderawtransaction "hexstring" ( iswitness ) +decodescript "hexstring" +descriptorprocesspsbt "psbt" ["",{"desc":"str","range":n or [n,n]},...] ( "sighashtype" bip32derivs finalize ) +finalizepsbt "psbt" ( extract ) +fundrawtransaction "hexstring" ( options iswitness ) +getprivatebroadcastinfo +getrawtransaction "txid" ( verbosity "blockhash" ) +joinpsbts ["psbt",...] +sendrawtransaction "hexstring" ( maxfeerate maxburnamount ) +signrawtransactionwithkey "hexstring" ["privatekey",...] ( [{"txid":"hex","vout":n,"scriptPubKey":"hex","redeemScript":"hex","witnessScript":"hex","amount":amount},...] "sighashtype" ) +submitpackage ["rawtx",...] ( maxfeerate maxburnamount ) +testmempoolaccept ["rawtx",...] ( maxfeerate ) +utxoupdatepsbt "psbt" ( ["",{"desc":"str","range":n or [n,n]},...] ) + +== Signer == +enumeratesigners + +== Util == +createmultisig nrequired ["key",...] ( "address_type" ) +deriveaddresses "descriptor" ( range ) +estimatesmartfee conf_target ( "estimate_mode" ) +getdescriptorinfo "descriptor" +getindexinfo ( "index_name" ) +signmessagewithprivkey "privkey" "message" +validateaddress "address" +verifymessage "address" "signature" "message" + +== Wallet == +abandontransaction "txid" +abortrescan +backupwallet "destination" +bumpfee "txid" ( options ) +createwallet "wallet_name" ( disable_private_keys blank "passphrase" avoid_reuse descriptors load_on_startup external_signer ) +createwalletdescriptor "type" ( {"internal":bool,"hdkey":"str",...} ) +encryptwallet "passphrase" +getaddressesbylabel "label" +getaddressinfo "address" +getbalance ( "dummy" minconf include_watchonly avoid_reuse ) +getbalances +gethdkeys ( {"active_only":bool,"private":bool,...} ) +getnewaddress ( "label" "address_type" ) +getrawchangeaddress ( "address_type" ) +getreceivedbyaddress "address" ( minconf include_immature_coinbase ) +getreceivedbylabel "label" ( minconf include_immature_coinbase ) +gettransaction "txid" ( include_watchonly verbose ) +getwalletinfo +importdescriptors requests +importprunedfunds "rawtransaction" "txoutproof" +keypoolrefill ( newsize ) +listaddressgroupings +listdescriptors ( private ) +listlabels ( "purpose" ) +listlockunspent +listreceivedbyaddress ( minconf include_empty include_watchonly "address_filter" include_immature_coinbase ) +listreceivedbylabel ( minconf include_empty include_watchonly include_immature_coinbase ) +listsinceblock ( "blockhash" target_confirmations include_watchonly include_removed include_change "label" ) +listtransactions ( "label" count skip include_watchonly ) +listunspent ( minconf maxconf ["address",...] include_unsafe query_options ) +listwalletdir +listwallets +loadwallet "filename" ( load_on_startup ) +lockunspent unlock ( [{"txid":"hex","vout":n},...] persistent ) +migratewallet ( "wallet_name" "passphrase" ) +psbtbumpfee "txid" ( options ) +removeprunedfunds "txid" +rescanblockchain ( start_height stop_height ) +restorewallet "wallet_name" "backup_file" ( load_on_startup ) +send [{"address":amount,...},{"data":"hex"},...] ( conf_target "estimate_mode" fee_rate options version ) +sendall ["address",{"address":amount,...},...] ( conf_target "estimate_mode" fee_rate options ) +sendmany ( "" ) {"address":amount,...} ( minconf "comment" ["address",...] replaceable conf_target "estimate_mode" fee_rate verbose ) +sendtoaddress "address" amount ( "comment" "comment_to" subtractfeefromamount replaceable conf_target "estimate_mode" avoid_reuse fee_rate verbose ) +setlabel "address" "label" +setwalletflag "flag" ( value ) +signmessage "address" "message" +signrawtransactionwithwallet "hexstring" ( [{"txid":"hex","vout":n,"scriptPubKey":"hex","redeemScript":"hex","witnessScript":"hex","amount":amount},...] "sighashtype" ) +simulaterawtransaction ( ["rawtx",...] {"include_watchonly":bool,...} ) +unloadwallet ( "wallet_name" load_on_startup ) +walletcreatefundedpsbt ( [{"txid":"hex","vout":n,"sequence":n,"weight":n},...] ) [{"address":amount,...},{"data":"hex"},...] ( locktime options bip32derivs version ) +walletdisplayaddress "address" +walletlock +walletpassphrase "passphrase" timeout +walletpassphrasechange "oldpassphrase" "newpassphrase" +walletprocesspsbt "psbt" ( sign "sighashtype" bip32derivs finalize ) + +== Zmq == +getzmqnotifications diff --git a/verify/src/lib.rs b/verify/src/lib.rs index 03c3d23f..ab921522 100644 --- a/verify/src/lib.rs +++ b/verify/src/lib.rs @@ -48,6 +48,8 @@ pub enum Version { V29, /// Bitcoin Core v30. V30, + /// Bitcoin Core v31. + V31, } impl Version { @@ -68,6 +70,7 @@ impl Version { "v28" | "28" => Ok(Version::V28), "v29" | "29" => Ok(Version::V29), "v30" | "30" => Ok(Version::V30), + "v31" | "31" => Ok(Version::V31), other => Err(anyhow::Error::msg(format!("unknown version: '{}'", other))), } } @@ -91,6 +94,7 @@ impl fmt::Display for Version { V28 => "v28", V29 => "v29", V30 => "v30", + V31 => "v31", }; fmt::Display::fmt(&s, f) } diff --git a/verify/src/main.rs b/verify/src/main.rs index fc5aa7b3..f04a1642 100644 --- a/verify/src/main.rs +++ b/verify/src/main.rs @@ -21,7 +21,7 @@ use verify::{method, model, reexports, ssot, Version}; // TODO: Enable running from any directory, currently errors if run from `src/`. // TODO: Add a --quiet option. -const VERSIONS: [Version; 14] = [ +const VERSIONS: [Version; 15] = [ Version::V17, Version::V18, Version::V19, @@ -36,6 +36,7 @@ const VERSIONS: [Version; 14] = [ Version::V28, Version::V29, Version::V30, + Version::V31, ]; fn main() -> Result<()> { diff --git a/verify/src/method/mod.rs b/verify/src/method/mod.rs index b4527afe..77ccf025 100644 --- a/verify/src/method/mod.rs +++ b/verify/src/method/mod.rs @@ -16,6 +16,7 @@ pub mod v27; pub mod v28; pub mod v29; pub mod v30; +pub mod v31; use crate::Version; @@ -38,6 +39,7 @@ pub fn all_methods(version: Version) -> Vec { V28 => v28::METHODS, V29 => v29::METHODS, V30 => v30::METHODS, + V31 => v31::METHODS, }; list.iter().map(|m| m.name.to_string()).collect() @@ -81,6 +83,7 @@ impl Method { V28 => v28::METHODS, V29 => v29::METHODS, V30 => v30::METHODS, + V31 => v31::METHODS, }; list.iter().find(|&method| method.name == name) diff --git a/verify/src/method/v31.rs b/verify/src/method/v31.rs new file mode 100644 index 00000000..6730e56f --- /dev/null +++ b/verify/src/method/v31.rs @@ -0,0 +1,224 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! JSON RPC methods provided by Bitcoin Core v31. + +use super::Method; + +/// Data for the JSON RPC methods provided by Bitcoin Core v31. +pub const METHODS: &[Method] = &[ + // blockchain + Method::new_modelled("dumptxoutset", "DumpTxOutSet", "dump_tx_out_set"), + Method::new_modelled("getbestblockhash", "GetBestBlockHash", "get_best_block_hash"), + Method::new_modelled("getblock", "GetBlockVerboseZero", "get_block"), // We only check one of the types. + Method::new_modelled("getblockchaininfo", "GetBlockchainInfo", "get_blockchain_info"), + Method::new_modelled("getblockcount", "GetBlockCount", "get_block_count"), + Method::new_modelled("getblockfilter", "GetBlockFilter", "get_block_filter"), + Method::new_nothing("getblockfrompeer", "get_block_from_peer"), + Method::new_modelled("getblockhash", "GetBlockHash", "get_block_hash"), + Method::new_modelled("getblockheader", "GetBlockHeader", "get_block_header"), + Method::new_modelled("getblockstats", "GetBlockStats", "get_block_stats"), + Method::new_modelled("getchainstates", "GetChainStates", "get_chain_states"), + Method::new_modelled("getchaintips", "GetChainTips", "get_chain_tips"), + Method::new_modelled("getchaintxstats", "GetChainTxStats", "get_chain_tx_stats"), + Method::new_modelled("getdeploymentinfo", "GetDeploymentInfo", "get_deployment_info"), + Method::new_modelled( + "getdescriptoractivity", + "GetDescriptorActivity", + "get_descriptor_activity", + ), + Method::new_modelled("getdifficulty", "GetDifficulty", "get_difficulty"), + Method::new_modelled("getmempoolancestors", "GetMempoolAncestors", "get_mempool_ancestors"), + Method::new_modelled("getmempoolcluster", "GetMempoolCluster", "get_mempool_cluster"), + Method::new_modelled( + "getmempooldescendants", + "GetMempoolDescendants", + "get_mempool_descendants", + ), + Method::new_modelled("getmempoolentry", "GetMempoolEntry", "get_mempool_entry"), + Method::new_modelled("getmempoolinfo", "GetMempoolInfo", "get_mempool_info"), + Method::new_modelled("getrawmempool", "GetRawMempool", "get_raw_mempool"), + Method::new_modelled("gettxout", "GetTxOut", "get_tx_out"), + Method::new_string("gettxoutproof", "get_tx_out_proof"), + Method::new_modelled("gettxoutsetinfo", "GetTxOutSetInfo", "get_tx_out_set_info"), + Method::new_modelled("gettxspendingprevout", "GetTxSpendingPrevout", "get_tx_spending_prevout"), + Method::new_nothing("importmempool", "import_mempool"), + Method::new_modelled("loadtxoutset", "LoadTxOutSet", "load_tx_out_set"), + Method::new_nothing("preciousblock", "precious_block"), + Method::new_no_model("pruneblockchain", "PruneBlockchain", "prune_blockchain"), + Method::new_no_model("savemempool", "SaveMempool", "save_mempool"), + Method::new_modelled("scanblocks", "ScanBlocksStart", "scan_blocks"), + Method::new_modelled("scantxoutset", "ScanTxOutSetStart", "scan_tx_out_set"), + Method::new_no_model("verifychain", "VerifyChain", "verify_chain"), + Method::new_modelled("verifytxoutproof", "VerifyTxOutProof", "verify_tx_out_proof"), + Method::new_modelled("waitforblock", "WaitForBlock", "wait_for_block"), + Method::new_modelled("waitforblockheight", "WaitForBlockHeight", "wait_for_block_height"), + Method::new_modelled("waitfornewblock", "WaitForNewBlock", "wait_for_new_block"), + // control + Method::new_no_model("getrpcinfo", "GetRpcInfo", "get_rpc_info"), + Method::new_no_model("getmemoryinfo", "GetMemoryInfoStats", "get_memory_info"), + Method::new_string("help", "help"), + Method::new_no_model("logging", "Logging", "logging"), + Method::new_nothing("stop", "stop"), + Method::new_numeric("uptime", "uptime"), + // mining + Method::new_modelled("getblocktemplate", "GetBlockTemplate", "get_block_template"), + Method::new_modelled("getmininginfo", "GetMiningInfo", "get_mining_info"), + Method::new_numeric("getnetworkhashps", "get_network_hashes_per_second"), + Method::new_modelled( + "getprioritisedtransactions", + "GetPrioritisedTransactionsREMOVEME", + "get_prioritised_transactions", + ), + Method::new_bool("prioritisetransaction", "prioritise_transaction"), + Method::new_nothing("submitblock", "submit_block"), + Method::new_nothing("submitheader", "submit_header"), + // network + Method::new_nothing("addnode", "add_node"), + Method::new_nothing("clearbanned", "clear_banned"), + Method::new_nothing("disconnectnode", "disconnect_node"), + Method::new_no_model("getaddednodeinfo", "GetAddedNodeInfo", "get_added_node_info"), + Method::new_no_model("getaddrmaninfo", "GetAddrManInfo", "get_addr_man_info"), + Method::new_no_model("getconnectioncount", "GetConnectionCount", "get_connection_count"), + Method::new_no_model("getnettotals", "GetNetTotals", "get_net_totals"), + Method::new_modelled("getnetworkinfo", "GetNetworkInfo", "get_network_info"), + Method::new_no_model("getnodeaddresses", "GetNodeAddresses", "get_node_addresses"), + Method::new_no_model("getpeerinfo", "GetPeerInfo", "get_peer_info"), + Method::new_no_model("listbanned", "ListBanned", "list_banned"), + Method::new_nothing("ping", "ping"), + Method::new_nothing("setban", "set_ban"), + Method::new_no_model("setnetworkactive", "SetNetworkActive", "set_network_active"), + // raw transactions + Method::new_modelled( + "abortprivatebroadcast", + "AbortPrivateBroadcast", + "abort_private_broadcast", + ), + Method::new_modelled("analyzepsbt", "AnalyzePsbt", "analyze_psbt"), + Method::new_modelled("combinepsbt", "CombinePsbt", "combine_psbt"), + Method::new_modelled( + "combinerawtransaction", + "CombineRawTransaction", + "combine_raw_transaction", + ), + Method::new_modelled("converttopsbt", "ConvertToPsbt", "convert_to_psbt"), + Method::new_modelled("createpsbt", "CreatePsbt", "create_psbt"), + Method::new_modelled("createrawtransaction", "CreateRawTransaction", "create_raw_transaction"), + Method::new_modelled("decodepsbt", "DecodePsbt", "decode_psbt"), + Method::new_modelled("decoderawtransaction", "DecodeRawTransaction", "decode_raw_transaction"), + Method::new_modelled("decodescript", "DecodeScript", "decode_script"), + Method::new_modelled( + "descriptorprocesspsbt", + "DescriptorProcessPsbt", + "descriptor_process_psbt", + ), + Method::new_modelled("finalizepsbt", "FinalizePsbt", "finalize_psbt"), + Method::new_modelled("fundrawtransaction", "FundRawTransaction", "fund_raw_transaction"), + Method::new_modelled( + "getprivatebroadcastinfo", + "GetPrivateBroadcastInfo", + "get_private_broadcast_info", + ), + Method::new_modelled("getrawtransaction", "GetRawTransaction", "get_raw_transaction"), + Method::new_modelled("joinpsbts", "JoinPsbts", "join_psbts"), + Method::new_modelled("sendrawtransaction", "SendRawTransaction", "send_raw_transaction"), + Method::new_modelled( + "signrawtransactionwithkey", + "SignRawTransaction", + "sign_raw_transaction_with_key", + ), + Method::new_modelled("submitpackage", "SubmitPackage", "submit_package"), + Method::new_modelled("testmempoolaccept", "TestMempoolAccept", "test_mempool_accept"), + Method::new_modelled("utxoupdatepsbt", "UtxoUpdatePsbt", "utxo_update_psbt"), + Method::new_modelled("createmultisig", "CreateMultisig", "create_multisig"), + Method::new_modelled("deriveaddresses", "DeriveAddresses", "derive_addresses"), + Method::new_modelled("estimatesmartfee", "EstimateSmartFee", "estimate_smart_fee"), + Method::new_no_model("getdescriptorinfo", "GetDescriptorInfo", "get_descriptor_info"), + Method::new_no_model("getindexinfo", "GetIndexInfo", "get_index_info"), + Method::new_modelled( + "signmessagewithprivkey", + "SignMessageWithPrivKey", + "sign_message_with_priv_key", + ), + Method::new_modelled("validateaddress", "ValidateAddress", "validate_address"), + Method::new_bool("verifymessage", "verify_message"), + // signer + Method::new_no_model("enumeratesigners", "EnumerateSigners", "enumerate_signers"), + // wallet + Method::new_nothing("abandontransaction", "abandon_transaction"), + Method::new_no_model("abortrescan", "AbortRescan", "abort_rescan"), + Method::new_nothing("backupwallet", "backup_wallet"), + Method::new_modelled("bumpfee", "BumpFee", "bump_fee"), + Method::new_modelled("createwallet", "CreateWallet", "create_wallet"), + Method::new_no_model( + "createwalletdescriptor", + "CreateWalletDescriptor", + "create_wallet_descriptor", + ), + Method::new_no_model("encryptwallet", "EncryptWallet", "encrypt_wallet"), + Method::new_modelled("getaddressesbylabel", "GetAddressesByLabel", "get_addresses_by_label"), + Method::new_modelled("getaddressinfo", "GetAddressInfo", "get_address_info"), + Method::new_modelled("getbalance", "GetBalance", "get_balance"), + Method::new_modelled("getbalances", "GetBalances", "get_balances"), + Method::new_modelled("gethdkeys", "GetHdKeys", "get_hd_keys"), + Method::new_modelled("getnewaddress", "GetNewAddress", "get_new_address"), + Method::new_modelled("getrawchangeaddress", "GetRawChangeAddress", "get_raw_change_address"), + Method::new_modelled("getreceivedbyaddress", "GetReceivedByAddress", "get_received_by_address"), + Method::new_modelled("getreceivedbylabel", "GetReceivedByLabel", "get_received_by_label"), + Method::new_modelled("gettransaction", "GetTransaction", "get_transaction"), + Method::new_modelled("getwalletinfo", "GetWalletInfo", "get_wallet_info"), + Method::new_no_model("importdescriptors", "ImportDescriptors", "import_descriptors"), + Method::new_nothing("importprunedfunds", "import_pruned_funds"), + Method::new_nothing("keypoolrefill", "keypool_refill"), + Method::new_modelled("listaddressgroupings", "ListAddressGroupings", "list_address_groupings"), + Method::new_no_model("listdescriptors", "ListDescriptors", "list_descriptors"), + Method::new_no_model("listlabels", "ListLabels", "list_labels"), + Method::new_modelled("listlockunspent", "ListLockUnspent", "list_lock_unspent"), + Method::new_no_model("migratewallet", "MigrateWallet", "migrate_wallet"), + Method::new_modelled("psbtbumpfee", "PsbtBumpFee", "psbt_bump_fee"), + Method::new_modelled( + "listreceivedbyaddress", + "ListReceivedByAddress", + "list_received_by_address", + ), + Method::new_modelled("listreceivedbylabel", "ListReceivedByLabel", "list_received_by_label"), + Method::new_modelled("listsinceblock", "ListSinceBlock", "list_since_block"), + Method::new_modelled("listtransactions", "ListTransactions", "list_transactions"), + Method::new_modelled("listunspent", "ListUnspent", "list_unspent"), + Method::new_no_model("listwalletdir", "ListWalletDir", "list_wallet_dir"), + Method::new_modelled("listwallets", "ListWallets", "list_wallets"), + Method::new_modelled("loadwallet", "LoadWallet", "load_wallet"), + Method::new_no_model("lockunspent", "LockUnspent", "lock_unspent"), + Method::new_nothing("removeprunedfunds", "remove_pruned_funds"), + Method::new_modelled("rescanblockchain", "RescanBlockchain", "rescan_blockchain"), + Method::new_no_model("restorewallet", "RestoreWallet", "restore_wallet"), + Method::new_modelled("send", "Send", "send"), + Method::new_modelled("sendall", "SendAll", "send_all"), + Method::new_modelled("sendmany", "SendMany", "send_many"), + Method::new_modelled("sendtoaddress", "SendToAddress", "send_to_address"), + Method::new_nothing("setlabel", "set_label"), + Method::new_no_model("setwalletflag", "SetWalletFlag", "set_wallet_flag"), + Method::new_modelled("signmessage", "SignMessage", "sign_message"), + Method::new_modelled( + "signrawtransactionwithwallet", + "SignRawTransaction", + "sign_raw_transaction_with_wallet", + ), + Method::new_modelled( + "simulaterawtransaction", + "SimulateRawTransaction", + "simulate_raw_transaction", + ), + Method::new_nothing("unloadwallet", "unload_wallet"), + Method::new_modelled( + "walletcreatefundedpsbt", + "WalletCreateFundedPsbt", + "wallet_create_funded_psbt", + ), + Method::new_modelled("walletdisplayaddress", "WalletDisplayAddress", "wallet_display_address"), + Method::new_nothing("walletlock", "wallet_lock"), + Method::new_nothing("walletpassphrase", "wallet_passphrase"), + Method::new_nothing("walletpassphrasechange", "wallet_passphrase_change"), + Method::new_modelled("walletprocesspsbt", "WalletProcessPsbt", "wallet_process_psbt"), + // zmq + Method::new_no_model("getzmqnotifications", "GetZmqNotifications", "get_zmq_notifications"), +];