From 0c0c0f30d7bdaffadc571fe494b4f2517f066199 Mon Sep 17 00:00:00 2001 From: RenatoBrittoAraujo Date: Wed, 14 Jan 2026 14:58:39 -0300 Subject: [PATCH 1/8] feat(client): add syncwithvalidationinterfacequeue RPC --- client/src/client_sync/v17/hidden.rs | 12 ++++++++++++ client/src/client_sync/v17/mod.rs | 1 + client/src/client_sync/v18/mod.rs | 1 + client/src/client_sync/v19/mod.rs | 1 + client/src/client_sync/v20/mod.rs | 1 + client/src/client_sync/v21/mod.rs | 1 + client/src/client_sync/v22/mod.rs | 1 + client/src/client_sync/v23/mod.rs | 1 + client/src/client_sync/v24/mod.rs | 1 + client/src/client_sync/v25/mod.rs | 1 + client/src/client_sync/v26/mod.rs | 1 + client/src/client_sync/v27/mod.rs | 1 + client/src/client_sync/v28/mod.rs | 1 + client/src/client_sync/v29/mod.rs | 1 + client/src/client_sync/v30/mod.rs | 1 + 15 files changed, 26 insertions(+) diff --git a/client/src/client_sync/v17/hidden.rs b/client/src/client_sync/v17/hidden.rs index d3b400fd..5e222dc9 100644 --- a/client/src/client_sync/v17/hidden.rs +++ b/client/src/client_sync/v17/hidden.rs @@ -56,3 +56,15 @@ macro_rules! impl_client_v17__wait_for_new_block { } }; } + +/// Implements Bitcoin Core JSON-RPC API method `syncwithvalidationinterfacequeue`. +#[macro_export] +macro_rules! impl_client_v17__sync_with_validation_interface_queue { + () => { + impl Client { + pub fn sync_with_validation_interface_queue(&self) -> Result<()> { + self.call("syncwithvalidationinterfacequeue", &[]) + } + } + }; +} diff --git a/client/src/client_sync/v17/mod.rs b/client/src/client_sync/v17/mod.rs index 7ad22305..54ebda4d 100644 --- a/client/src/client_sync/v17/mod.rs +++ b/client/src/client_sync/v17/mod.rs @@ -70,6 +70,7 @@ 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!(); +crate::impl_client_v17__sync_with_validation_interface_queue!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v18/mod.rs b/client/src/client_sync/v18/mod.rs index cb3d9e47..868dfb1d 100644 --- a/client/src/client_sync/v18/mod.rs +++ b/client/src/client_sync/v18/mod.rs @@ -75,6 +75,7 @@ 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!(); +crate::impl_client_v17__sync_with_validation_interface_queue!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v19/mod.rs b/client/src/client_sync/v19/mod.rs index dfc00400..7d5c6b37 100644 --- a/client/src/client_sync/v19/mod.rs +++ b/client/src/client_sync/v19/mod.rs @@ -70,6 +70,7 @@ 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!(); +crate::impl_client_v17__sync_with_validation_interface_queue!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v20/mod.rs b/client/src/client_sync/v20/mod.rs index 40c2eed6..5a33d155 100644 --- a/client/src/client_sync/v20/mod.rs +++ b/client/src/client_sync/v20/mod.rs @@ -70,6 +70,7 @@ 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!(); +crate::impl_client_v17__sync_with_validation_interface_queue!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v21/mod.rs b/client/src/client_sync/v21/mod.rs index f532abdb..1f7a76c0 100644 --- a/client/src/client_sync/v21/mod.rs +++ b/client/src/client_sync/v21/mod.rs @@ -76,6 +76,7 @@ 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!(); +crate::impl_client_v17__sync_with_validation_interface_queue!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v22/mod.rs b/client/src/client_sync/v22/mod.rs index 1e0b542b..67fa54b0 100644 --- a/client/src/client_sync/v22/mod.rs +++ b/client/src/client_sync/v22/mod.rs @@ -76,6 +76,7 @@ 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!(); +crate::impl_client_v17__sync_with_validation_interface_queue!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v23/mod.rs b/client/src/client_sync/v23/mod.rs index aba9cd2b..11b28782 100644 --- a/client/src/client_sync/v23/mod.rs +++ b/client/src/client_sync/v23/mod.rs @@ -78,6 +78,7 @@ 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!(); +crate::impl_client_v17__sync_with_validation_interface_queue!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v24/mod.rs b/client/src/client_sync/v24/mod.rs index 617dba69..097ea27b 100644 --- a/client/src/client_sync/v24/mod.rs +++ b/client/src/client_sync/v24/mod.rs @@ -79,6 +79,7 @@ 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!(); +crate::impl_client_v17__sync_with_validation_interface_queue!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v25/mod.rs b/client/src/client_sync/v25/mod.rs index b17d955d..bd977030 100644 --- a/client/src/client_sync/v25/mod.rs +++ b/client/src/client_sync/v25/mod.rs @@ -80,6 +80,7 @@ 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!(); +crate::impl_client_v17__sync_with_validation_interface_queue!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v26/mod.rs b/client/src/client_sync/v26/mod.rs index b1f021a3..56119489 100644 --- a/client/src/client_sync/v26/mod.rs +++ b/client/src/client_sync/v26/mod.rs @@ -86,6 +86,7 @@ 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!(); +crate::impl_client_v17__sync_with_validation_interface_queue!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v27/mod.rs b/client/src/client_sync/v27/mod.rs index 385a122a..4a59bb7e 100644 --- a/client/src/client_sync/v27/mod.rs +++ b/client/src/client_sync/v27/mod.rs @@ -82,6 +82,7 @@ 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!(); +crate::impl_client_v17__sync_with_validation_interface_queue!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v28/mod.rs b/client/src/client_sync/v28/mod.rs index 422ad4e0..7f624124 100644 --- a/client/src/client_sync/v28/mod.rs +++ b/client/src/client_sync/v28/mod.rs @@ -83,6 +83,7 @@ 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!(); +crate::impl_client_v17__sync_with_validation_interface_queue!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v29/mod.rs b/client/src/client_sync/v29/mod.rs index 851c2c2a..c3446d27 100644 --- a/client/src/client_sync/v29/mod.rs +++ b/client/src/client_sync/v29/mod.rs @@ -87,6 +87,7 @@ 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!(); +crate::impl_client_v17__sync_with_validation_interface_queue!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v30/mod.rs b/client/src/client_sync/v30/mod.rs index 7acb8cbd..44db6ac1 100644 --- a/client/src/client_sync/v30/mod.rs +++ b/client/src/client_sync/v30/mod.rs @@ -83,6 +83,7 @@ crate::impl_client_v29__get_orphan_txs_verbosity_1!(); crate::impl_client_v29__get_orphan_txs!(); crate::impl_client_v27__add_connection!(); crate::impl_client_v21__add_peer_address!(); +crate::impl_client_v17__sync_with_validation_interface_queue!(); // == Mining == crate::impl_client_v17__get_block_template!(); From 865d332e33b9f3b462fe4a05c9930f5b6e006968 Mon Sep 17 00:00:00 2001 From: RenatoBrittoAraujo Date: Wed, 14 Jan 2026 15:03:06 -0300 Subject: [PATCH 2/8] test(blockchain): test syncwithvalidationinterfacequeue RPC --- integration_test/tests/blockchain.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/integration_test/tests/blockchain.rs b/integration_test/tests/blockchain.rs index eac27c39..a22a8708 100644 --- a/integration_test/tests/blockchain.rs +++ b/integration_test/tests/blockchain.rs @@ -613,3 +613,18 @@ fn create_child_spending_parent(node: &Node, parent_txid: bitcoin::Txid) -> bitc child_txid } + +#[test] +fn blockchain__sync_with_validation_interface_queue__modelled() { + let node = Node::with_wallet(Wallet::Default, &[]); + node.fund_wallet(); + + // Create activity that causes validation callbacks. + let (_address, _txid) = node.create_mempool_transaction(); + + let _: () = node + .client + .sync_with_validation_interface_queue() + .expect("syncwithvalidationinterfacequeue"); +} + From af55bf2610c887c3d0278066bbf3637a9b192a30 Mon Sep 17 00:00:00 2001 From: RenatoBrittoAraujo Date: Wed, 14 Jan 2026 15:05:18 -0300 Subject: [PATCH 3/8] feat(client): add reconsiderblock hidden RPC for all client versions --- client/src/client_sync/v17/hidden.rs | 12 ++++++++++++ client/src/client_sync/v17/mod.rs | 1 + client/src/client_sync/v18/mod.rs | 1 + client/src/client_sync/v19/mod.rs | 1 + client/src/client_sync/v20/mod.rs | 1 + client/src/client_sync/v21/mod.rs | 1 + client/src/client_sync/v22/mod.rs | 1 + client/src/client_sync/v23/mod.rs | 1 + client/src/client_sync/v24/mod.rs | 1 + client/src/client_sync/v25/mod.rs | 1 + client/src/client_sync/v26/mod.rs | 1 + client/src/client_sync/v27/mod.rs | 1 + client/src/client_sync/v28/mod.rs | 1 + client/src/client_sync/v29/mod.rs | 1 + client/src/client_sync/v30/mod.rs | 1 + 15 files changed, 26 insertions(+) diff --git a/client/src/client_sync/v17/hidden.rs b/client/src/client_sync/v17/hidden.rs index 5e222dc9..3bc2afea 100644 --- a/client/src/client_sync/v17/hidden.rs +++ b/client/src/client_sync/v17/hidden.rs @@ -68,3 +68,15 @@ macro_rules! impl_client_v17__sync_with_validation_interface_queue { } }; } + +/// Implements Bitcoin Core JSON-RPC API method `reconsiderblock`. +#[macro_export] +macro_rules! impl_client_v17__reconsider_block { + () => { + impl Client { + pub fn reconsider_block(&self, blockhash: bitcoin::BlockHash) -> Result<()> { + self.call("reconsiderblock", &[into_json(blockhash)?]) + } + } + }; +} diff --git a/client/src/client_sync/v17/mod.rs b/client/src/client_sync/v17/mod.rs index 54ebda4d..fd599518 100644 --- a/client/src/client_sync/v17/mod.rs +++ b/client/src/client_sync/v17/mod.rs @@ -71,6 +71,7 @@ crate::impl_client_v17__wait_for_block!(); crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); crate::impl_client_v17__sync_with_validation_interface_queue!(); +crate::impl_client_v17__reconsider_block!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v18/mod.rs b/client/src/client_sync/v18/mod.rs index 868dfb1d..5a5a35f4 100644 --- a/client/src/client_sync/v18/mod.rs +++ b/client/src/client_sync/v18/mod.rs @@ -76,6 +76,7 @@ crate::impl_client_v17__wait_for_block!(); crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); crate::impl_client_v17__sync_with_validation_interface_queue!(); +crate::impl_client_v17__reconsider_block!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v19/mod.rs b/client/src/client_sync/v19/mod.rs index 7d5c6b37..0fc52e41 100644 --- a/client/src/client_sync/v19/mod.rs +++ b/client/src/client_sync/v19/mod.rs @@ -71,6 +71,7 @@ crate::impl_client_v17__wait_for_block!(); crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); crate::impl_client_v17__sync_with_validation_interface_queue!(); +crate::impl_client_v17__reconsider_block!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v20/mod.rs b/client/src/client_sync/v20/mod.rs index 5a33d155..5cac6cf7 100644 --- a/client/src/client_sync/v20/mod.rs +++ b/client/src/client_sync/v20/mod.rs @@ -71,6 +71,7 @@ crate::impl_client_v17__wait_for_block!(); crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); crate::impl_client_v17__sync_with_validation_interface_queue!(); +crate::impl_client_v17__reconsider_block!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v21/mod.rs b/client/src/client_sync/v21/mod.rs index 1f7a76c0..132b53fa 100644 --- a/client/src/client_sync/v21/mod.rs +++ b/client/src/client_sync/v21/mod.rs @@ -77,6 +77,7 @@ crate::impl_client_v17__wait_for_block!(); crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); crate::impl_client_v17__sync_with_validation_interface_queue!(); +crate::impl_client_v17__reconsider_block!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v22/mod.rs b/client/src/client_sync/v22/mod.rs index 67fa54b0..d168e054 100644 --- a/client/src/client_sync/v22/mod.rs +++ b/client/src/client_sync/v22/mod.rs @@ -77,6 +77,7 @@ crate::impl_client_v17__wait_for_block!(); crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); crate::impl_client_v17__sync_with_validation_interface_queue!(); +crate::impl_client_v17__reconsider_block!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v23/mod.rs b/client/src/client_sync/v23/mod.rs index 11b28782..6bbab2f0 100644 --- a/client/src/client_sync/v23/mod.rs +++ b/client/src/client_sync/v23/mod.rs @@ -79,6 +79,7 @@ crate::impl_client_v17__wait_for_block!(); crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); crate::impl_client_v17__sync_with_validation_interface_queue!(); +crate::impl_client_v17__reconsider_block!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v24/mod.rs b/client/src/client_sync/v24/mod.rs index 097ea27b..989ca745 100644 --- a/client/src/client_sync/v24/mod.rs +++ b/client/src/client_sync/v24/mod.rs @@ -80,6 +80,7 @@ crate::impl_client_v17__wait_for_block!(); crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); crate::impl_client_v17__sync_with_validation_interface_queue!(); +crate::impl_client_v17__reconsider_block!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v25/mod.rs b/client/src/client_sync/v25/mod.rs index bd977030..a9563fa8 100644 --- a/client/src/client_sync/v25/mod.rs +++ b/client/src/client_sync/v25/mod.rs @@ -81,6 +81,7 @@ crate::impl_client_v17__wait_for_block!(); crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); crate::impl_client_v17__sync_with_validation_interface_queue!(); +crate::impl_client_v17__reconsider_block!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v26/mod.rs b/client/src/client_sync/v26/mod.rs index 56119489..8bb89687 100644 --- a/client/src/client_sync/v26/mod.rs +++ b/client/src/client_sync/v26/mod.rs @@ -87,6 +87,7 @@ crate::impl_client_v17__wait_for_block!(); crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); crate::impl_client_v17__sync_with_validation_interface_queue!(); +crate::impl_client_v17__reconsider_block!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v27/mod.rs b/client/src/client_sync/v27/mod.rs index 4a59bb7e..cafcd9cf 100644 --- a/client/src/client_sync/v27/mod.rs +++ b/client/src/client_sync/v27/mod.rs @@ -83,6 +83,7 @@ crate::impl_client_v17__wait_for_block!(); crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); crate::impl_client_v17__sync_with_validation_interface_queue!(); +crate::impl_client_v17__reconsider_block!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v28/mod.rs b/client/src/client_sync/v28/mod.rs index 7f624124..bd0f1e51 100644 --- a/client/src/client_sync/v28/mod.rs +++ b/client/src/client_sync/v28/mod.rs @@ -84,6 +84,7 @@ crate::impl_client_v17__wait_for_block!(); crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); crate::impl_client_v17__sync_with_validation_interface_queue!(); +crate::impl_client_v17__reconsider_block!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v29/mod.rs b/client/src/client_sync/v29/mod.rs index c3446d27..3e4194ed 100644 --- a/client/src/client_sync/v29/mod.rs +++ b/client/src/client_sync/v29/mod.rs @@ -88,6 +88,7 @@ crate::impl_client_v17__wait_for_block!(); crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); crate::impl_client_v17__sync_with_validation_interface_queue!(); +crate::impl_client_v17__reconsider_block!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v30/mod.rs b/client/src/client_sync/v30/mod.rs index 44db6ac1..e807b16a 100644 --- a/client/src/client_sync/v30/mod.rs +++ b/client/src/client_sync/v30/mod.rs @@ -84,6 +84,7 @@ crate::impl_client_v29__get_orphan_txs!(); crate::impl_client_v27__add_connection!(); crate::impl_client_v21__add_peer_address!(); crate::impl_client_v17__sync_with_validation_interface_queue!(); +crate::impl_client_v17__reconsider_block!(); // == Mining == crate::impl_client_v17__get_block_template!(); From 1846d7d7565567fd67b55443c98a6b1ab50f695c Mon Sep 17 00:00:00 2001 From: RenatoBrittoAraujo Date: Wed, 14 Jan 2026 15:11:52 -0300 Subject: [PATCH 4/8] test(blockchain): test reconsiderblock hidden RPC --- integration_test/tests/blockchain.rs | 42 ++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/integration_test/tests/blockchain.rs b/integration_test/tests/blockchain.rs index a22a8708..a9572fbd 100644 --- a/integration_test/tests/blockchain.rs +++ b/integration_test/tests/blockchain.rs @@ -628,3 +628,45 @@ fn blockchain__sync_with_validation_interface_queue__modelled() { .expect("syncwithvalidationinterfacequeue"); } +#[test] +fn blockchain__reconsider_block__modelled() { + let node = Node::with_wallet(Wallet::Default, &[]); + node.fund_wallet(); + + node.mine_a_block(); + node.mine_a_block(); + + let tip_before = node.client.best_block_hash().expect("bestblockhash"); + let height_before = node.client.get_block_count().expect("getblockcount").0; + + node.client.invalidate_block(tip_before).expect("invalidateblock"); + + let tip_after_invalidate = + node.client.best_block_hash().expect("bestblockhash after invalidate"); + let height_after_invalidate = node.client.get_block_count().expect("getblockcount").0; + + assert_ne!( + tip_after_invalidate, tip_before, + "tip should change after invalidating the tip block" + ); + assert_eq!( + height_after_invalidate, + height_before - 1, + "height should decrease by 1 after invalidating the tip block" + ); + + node.client.reconsider_block(tip_before).expect("reconsiderblock"); + + let tip_after_reconsider = + node.client.best_block_hash().expect("bestblockhash after reconsider"); + let height_after_reconsider = node.client.get_block_count().expect("getblockcount").0; + + assert_eq!( + tip_after_reconsider, tip_before, + "tip should return to the previously invalidated block after reconsiderblock" + ); + assert_eq!( + height_after_reconsider, height_before, + "height should return to the original height after reconsiderblock" + ); +} From e1bd874acf0abf4bd451b51525f767f602659a65 Mon Sep 17 00:00:00 2001 From: RenatoBrittoAraujo Date: Wed, 14 Jan 2026 15:12:23 -0300 Subject: [PATCH 5/8] feat(client): add mockscheduler hidden RPC --- client/src/client_sync/v20/hidden.rs | 22 ++++++++++++++++++++++ client/src/client_sync/v20/mod.rs | 2 ++ client/src/client_sync/v21/mod.rs | 1 + client/src/client_sync/v22/mod.rs | 1 + client/src/client_sync/v23/mod.rs | 1 + client/src/client_sync/v24/mod.rs | 1 + client/src/client_sync/v25/mod.rs | 1 + client/src/client_sync/v26/mod.rs | 1 + client/src/client_sync/v27/mod.rs | 1 + client/src/client_sync/v28/mod.rs | 1 + client/src/client_sync/v29/mod.rs | 1 + client/src/client_sync/v30/mod.rs | 1 + 12 files changed, 34 insertions(+) create mode 100644 client/src/client_sync/v20/hidden.rs diff --git a/client/src/client_sync/v20/hidden.rs b/client/src/client_sync/v20/hidden.rs new file mode 100644 index 00000000..84702d76 --- /dev/null +++ b/client/src/client_sync/v20/hidden.rs @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: CC0-1.0 + +//! Macros for implementing JSON-RPC methods on a client. +//! +//! Specifically this is `== Hidden ==` methods that are not listed in the +//! API docs of Bitcoin Core `v0.20`. +//! +//! 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 `mockscheduler`. +#[macro_export] +macro_rules! impl_client_v20__mock_scheduler { + () => { + impl Client { + pub fn mock_scheduler(&self, delta_time: u64) -> Result<()> { + self.call("mockscheduler", &[into_json(delta_time)?]) + } + } + }; +} diff --git a/client/src/client_sync/v20/mod.rs b/client/src/client_sync/v20/mod.rs index 5cac6cf7..afa1ff2f 100644 --- a/client/src/client_sync/v20/mod.rs +++ b/client/src/client_sync/v20/mod.rs @@ -5,6 +5,7 @@ //! We ignore option arguments unless they effect the shape of the returned JSON data. pub mod generating; +pub mod hidden; use std::collections::BTreeMap; use std::path::Path; @@ -72,6 +73,7 @@ crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); crate::impl_client_v17__sync_with_validation_interface_queue!(); crate::impl_client_v17__reconsider_block!(); +crate::impl_client_v20__mock_scheduler!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v21/mod.rs b/client/src/client_sync/v21/mod.rs index 132b53fa..fcad23a7 100644 --- a/client/src/client_sync/v21/mod.rs +++ b/client/src/client_sync/v21/mod.rs @@ -78,6 +78,7 @@ crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); crate::impl_client_v17__sync_with_validation_interface_queue!(); crate::impl_client_v17__reconsider_block!(); +crate::impl_client_v20__mock_scheduler!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v22/mod.rs b/client/src/client_sync/v22/mod.rs index d168e054..3353051b 100644 --- a/client/src/client_sync/v22/mod.rs +++ b/client/src/client_sync/v22/mod.rs @@ -78,6 +78,7 @@ crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); crate::impl_client_v17__sync_with_validation_interface_queue!(); crate::impl_client_v17__reconsider_block!(); +crate::impl_client_v20__mock_scheduler!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v23/mod.rs b/client/src/client_sync/v23/mod.rs index 6bbab2f0..739bf59c 100644 --- a/client/src/client_sync/v23/mod.rs +++ b/client/src/client_sync/v23/mod.rs @@ -80,6 +80,7 @@ crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); crate::impl_client_v17__sync_with_validation_interface_queue!(); crate::impl_client_v17__reconsider_block!(); +crate::impl_client_v20__mock_scheduler!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v24/mod.rs b/client/src/client_sync/v24/mod.rs index 989ca745..36ef55a8 100644 --- a/client/src/client_sync/v24/mod.rs +++ b/client/src/client_sync/v24/mod.rs @@ -81,6 +81,7 @@ crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); crate::impl_client_v17__sync_with_validation_interface_queue!(); crate::impl_client_v17__reconsider_block!(); +crate::impl_client_v20__mock_scheduler!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v25/mod.rs b/client/src/client_sync/v25/mod.rs index a9563fa8..b916340b 100644 --- a/client/src/client_sync/v25/mod.rs +++ b/client/src/client_sync/v25/mod.rs @@ -82,6 +82,7 @@ crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); crate::impl_client_v17__sync_with_validation_interface_queue!(); crate::impl_client_v17__reconsider_block!(); +crate::impl_client_v20__mock_scheduler!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v26/mod.rs b/client/src/client_sync/v26/mod.rs index 8bb89687..c201c8f3 100644 --- a/client/src/client_sync/v26/mod.rs +++ b/client/src/client_sync/v26/mod.rs @@ -88,6 +88,7 @@ crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); crate::impl_client_v17__sync_with_validation_interface_queue!(); crate::impl_client_v17__reconsider_block!(); +crate::impl_client_v20__mock_scheduler!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v27/mod.rs b/client/src/client_sync/v27/mod.rs index cafcd9cf..909987ac 100644 --- a/client/src/client_sync/v27/mod.rs +++ b/client/src/client_sync/v27/mod.rs @@ -84,6 +84,7 @@ crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); crate::impl_client_v17__sync_with_validation_interface_queue!(); crate::impl_client_v17__reconsider_block!(); +crate::impl_client_v20__mock_scheduler!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v28/mod.rs b/client/src/client_sync/v28/mod.rs index bd0f1e51..e41f05b0 100644 --- a/client/src/client_sync/v28/mod.rs +++ b/client/src/client_sync/v28/mod.rs @@ -85,6 +85,7 @@ crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); crate::impl_client_v17__sync_with_validation_interface_queue!(); crate::impl_client_v17__reconsider_block!(); +crate::impl_client_v20__mock_scheduler!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v29/mod.rs b/client/src/client_sync/v29/mod.rs index 3e4194ed..e39f57f9 100644 --- a/client/src/client_sync/v29/mod.rs +++ b/client/src/client_sync/v29/mod.rs @@ -89,6 +89,7 @@ crate::impl_client_v17__wait_for_block_height!(); crate::impl_client_v17__wait_for_new_block!(); crate::impl_client_v17__sync_with_validation_interface_queue!(); crate::impl_client_v17__reconsider_block!(); +crate::impl_client_v20__mock_scheduler!(); // == Mining == crate::impl_client_v17__get_block_template!(); diff --git a/client/src/client_sync/v30/mod.rs b/client/src/client_sync/v30/mod.rs index e807b16a..61d6e32b 100644 --- a/client/src/client_sync/v30/mod.rs +++ b/client/src/client_sync/v30/mod.rs @@ -85,6 +85,7 @@ crate::impl_client_v27__add_connection!(); crate::impl_client_v21__add_peer_address!(); crate::impl_client_v17__sync_with_validation_interface_queue!(); crate::impl_client_v17__reconsider_block!(); +crate::impl_client_v20__mock_scheduler!(); // == Mining == crate::impl_client_v17__get_block_template!(); From 3e1400697da639f3677f3c60982f0781864be2c6 Mon Sep 17 00:00:00 2001 From: RenatoBrittoAraujo Date: Wed, 14 Jan 2026 15:12:36 -0300 Subject: [PATCH 6/8] test(blockchain): test mockscheduler hidden RPC --- integration_test/tests/blockchain.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/integration_test/tests/blockchain.rs b/integration_test/tests/blockchain.rs index a9572fbd..c26de41a 100644 --- a/integration_test/tests/blockchain.rs +++ b/integration_test/tests/blockchain.rs @@ -670,3 +670,11 @@ fn blockchain__reconsider_block__modelled() { "height should return to the original height after reconsiderblock" ); } + +#[test] +#[cfg(not(feature = "v19_and_below"))] +fn blockchain__mock_scheduler__modelled() { + let node = Node::with_wallet(Wallet::Default, &[]); + + let _: () = node.client.mock_scheduler(1).expect("mockscheduler"); +} From 7756c423b4f44d56447d17f01dd68bc764a21889 Mon Sep 17 00:00:00 2001 From: RenatoBrittoAraujo Date: Wed, 14 Jan 2026 15:12:43 -0300 Subject: [PATCH 7/8] fix(mining): correct docs API version to v30 --- types/src/v30/mining/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/types/src/v30/mining/mod.rs b/types/src/v30/mining/mod.rs index 9e149471..a16ecc04 100644 --- a/types/src/v30/mining/mod.rs +++ b/types/src/v30/mining/mod.rs @@ -1,6 +1,6 @@ // SPDX-License-Identifier: CC0-1.0 -//! The JSON-RPC API for Bitcoin Core `v29` - mining. +//! The JSON-RPC API for Bitcoin Core `v30` - mining. //! //! Types for methods found under the `== Mining ==` section of the API docs. From bab46472327ecefb3b49e3ce42de927cfd35072b Mon Sep 17 00:00:00 2001 From: RenatoBrittoAraujo Date: Thu, 15 Jan 2026 18:59:11 -0300 Subject: [PATCH 8/8] fix(tests): move hidden RPC tests, fix modelled suffixes --- integration_test/tests/blockchain.rs | 65 ---------------------------- integration_test/tests/hidden.rs | 65 ++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 65 deletions(-) diff --git a/integration_test/tests/blockchain.rs b/integration_test/tests/blockchain.rs index c26de41a..eac27c39 100644 --- a/integration_test/tests/blockchain.rs +++ b/integration_test/tests/blockchain.rs @@ -613,68 +613,3 @@ fn create_child_spending_parent(node: &Node, parent_txid: bitcoin::Txid) -> bitc child_txid } - -#[test] -fn blockchain__sync_with_validation_interface_queue__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); - node.fund_wallet(); - - // Create activity that causes validation callbacks. - let (_address, _txid) = node.create_mempool_transaction(); - - let _: () = node - .client - .sync_with_validation_interface_queue() - .expect("syncwithvalidationinterfacequeue"); -} - -#[test] -fn blockchain__reconsider_block__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); - node.fund_wallet(); - - node.mine_a_block(); - node.mine_a_block(); - - let tip_before = node.client.best_block_hash().expect("bestblockhash"); - let height_before = node.client.get_block_count().expect("getblockcount").0; - - node.client.invalidate_block(tip_before).expect("invalidateblock"); - - let tip_after_invalidate = - node.client.best_block_hash().expect("bestblockhash after invalidate"); - let height_after_invalidate = node.client.get_block_count().expect("getblockcount").0; - - assert_ne!( - tip_after_invalidate, tip_before, - "tip should change after invalidating the tip block" - ); - assert_eq!( - height_after_invalidate, - height_before - 1, - "height should decrease by 1 after invalidating the tip block" - ); - - node.client.reconsider_block(tip_before).expect("reconsiderblock"); - - let tip_after_reconsider = - node.client.best_block_hash().expect("bestblockhash after reconsider"); - let height_after_reconsider = node.client.get_block_count().expect("getblockcount").0; - - assert_eq!( - tip_after_reconsider, tip_before, - "tip should return to the previously invalidated block after reconsiderblock" - ); - assert_eq!( - height_after_reconsider, height_before, - "height should return to the original height after reconsiderblock" - ); -} - -#[test] -#[cfg(not(feature = "v19_and_below"))] -fn blockchain__mock_scheduler__modelled() { - let node = Node::with_wallet(Wallet::Default, &[]); - - let _: () = node.client.mock_scheduler(1).expect("mockscheduler"); -} diff --git a/integration_test/tests/hidden.rs b/integration_test/tests/hidden.rs index 77ce3609..8aa3aa8b 100644 --- a/integration_test/tests/hidden.rs +++ b/integration_test/tests/hidden.rs @@ -173,3 +173,68 @@ fn hidden__get_orphan_txs__modelled() { } } } + +#[test] +fn hidden__sync_with_validation_interface_queue() { + let node = Node::with_wallet(Wallet::Default, &[]); + node.fund_wallet(); + + // Create activity that causes validation callbacks. + let (_address, _txid) = node.create_mempool_transaction(); + + let _: () = node + .client + .sync_with_validation_interface_queue() + .expect("syncwithvalidationinterfacequeue"); +} + +#[test] +fn hidden__reconsider_block() { + let node = Node::with_wallet(Wallet::Default, &[]); + node.fund_wallet(); + + node.mine_a_block(); + node.mine_a_block(); + + let tip_before = node.client.best_block_hash().expect("bestblockhash"); + let height_before = node.client.get_block_count().expect("getblockcount").0; + + node.client.invalidate_block(tip_before).expect("invalidateblock"); + + let tip_after_invalidate = + node.client.best_block_hash().expect("bestblockhash after invalidate"); + let height_after_invalidate = node.client.get_block_count().expect("getblockcount").0; + + assert_ne!( + tip_after_invalidate, tip_before, + "tip should change after invalidating the tip block" + ); + assert_eq!( + height_after_invalidate, + height_before - 1, + "height should decrease by 1 after invalidating the tip block" + ); + + node.client.reconsider_block(tip_before).expect("reconsiderblock"); + + let tip_after_reconsider = + node.client.best_block_hash().expect("bestblockhash after reconsider"); + let height_after_reconsider = node.client.get_block_count().expect("getblockcount").0; + + assert_eq!( + tip_after_reconsider, tip_before, + "tip should return to the previously invalidated block after reconsiderblock" + ); + assert_eq!( + height_after_reconsider, height_before, + "height should return to the original height after reconsiderblock" + ); +} + +#[test] +#[cfg(not(feature = "v19_and_below"))] +fn hidden__mock_scheduler() { + let node = Node::with_wallet(Wallet::Default, &[]); + + let _: () = node.client.mock_scheduler(1).expect("mockscheduler"); +}