Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions client/src/client_sync/v17/hidden.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// 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.17`.
//!
//! All macros require `Client` to be in scope.
//!
//! See or use the `define_jsonrpc_minreq_client!` macro to define a `Client`.

/// Implements Bitcoin Core JSON-RPC API method `waitforblock`.
#[macro_export]
macro_rules! impl_client_v17__wait_for_block {
() => {
impl Client {
pub fn wait_for_block(&self, hash: &bitcoin::BlockHash) -> Result<WaitForBlock> {
self.call("waitforblock", &[into_json(hash)?])
}
}
};
}

/// Implements Bitcoin Core JSON-RPC API method `waitforblockheight`.
#[macro_export]
macro_rules! impl_client_v17__wait_for_block_height {
() => {
impl Client {
pub fn wait_for_block_height(&self, height: u64) -> Result<WaitForBlockHeight> {
self.call("waitforblockheight", &[into_json(height)?])
}
}
};
}

/// Implements Bitcoin Core JSON-RPC API method `waitfornewblock`.
#[macro_export]
macro_rules! impl_client_v17__wait_for_new_block {
() => {
impl Client {
pub fn wait_for_new_block(&self) -> Result<WaitForNewBlock> {
self.call("waitfornewblock", &[])
}
}
};
}
6 changes: 6 additions & 0 deletions client/src/client_sync/v17/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
pub mod blockchain;
pub mod control;
pub mod generating;
pub mod hidden;
pub mod mining;
pub mod network;
pub mod raw_transactions;
Expand Down Expand Up @@ -64,6 +65,11 @@ crate::impl_client_v17__generate_to_address!();
crate::impl_client_v17__generate!();
crate::impl_client_v17__invalidate_block!();

// == Hidden ==
crate::impl_client_v17__wait_for_block!();
crate::impl_client_v17__wait_for_block_height!();
crate::impl_client_v17__wait_for_new_block!();

// == Mining ==
crate::impl_client_v17__get_block_template!();
crate::impl_client_v17__get_mining_info!();
Expand Down
5 changes: 5 additions & 0 deletions client/src/client_sync/v18/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ crate::impl_client_v17__generate_to_address!();
crate::impl_client_v17__generate!();
crate::impl_client_v17__invalidate_block!();

// == Hidden ==
crate::impl_client_v17__wait_for_block!();
crate::impl_client_v17__wait_for_block_height!();
crate::impl_client_v17__wait_for_new_block!();

// == Mining ==
crate::impl_client_v17__get_block_template!();
crate::impl_client_v17__get_mining_info!();
Expand Down
5 changes: 5 additions & 0 deletions client/src/client_sync/v19/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ crate::impl_client_v17__uptime!();
crate::impl_client_v17__generate_to_address!();
crate::impl_client_v17__invalidate_block!();

// == Hidden ==
crate::impl_client_v17__wait_for_block!();
crate::impl_client_v17__wait_for_block_height!();
crate::impl_client_v17__wait_for_new_block!();

// == Mining ==
crate::impl_client_v17__get_block_template!();
crate::impl_client_v17__get_mining_info!();
Expand Down
5 changes: 5 additions & 0 deletions client/src/client_sync/v20/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ crate::impl_client_v17__generate_to_address!();
crate::impl_client_v20__generate_to_descriptor!();
crate::impl_client_v17__invalidate_block!();

// == Hidden ==
crate::impl_client_v17__wait_for_block!();
crate::impl_client_v17__wait_for_block_height!();
crate::impl_client_v17__wait_for_new_block!();

// == Mining ==
crate::impl_client_v17__get_block_template!();
crate::impl_client_v17__get_mining_info!();
Expand Down
2 changes: 1 addition & 1 deletion client/src/client_sync/v21/hidden.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

//! Macros for implementing JSON-RPC methods on a client.
//!
//! Specifically this is methods found under the `== Generating ==` section of the
//! Specifically this is `== Hidden ==` methods that are not listed in the
//! API docs of Bitcoin Core `v0.21`.
//!
//! All macros require `Client` to be in scope.
Expand Down
3 changes: 3 additions & 0 deletions client/src/client_sync/v21/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ crate::impl_client_v17__invalidate_block!();

// == Hidden ==
crate::impl_client_v21__add_peer_address!();
crate::impl_client_v17__wait_for_block!();
crate::impl_client_v17__wait_for_block_height!();
crate::impl_client_v17__wait_for_new_block!();

// == Mining ==
crate::impl_client_v17__get_block_template!();
Expand Down
3 changes: 3 additions & 0 deletions client/src/client_sync/v22/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ crate::impl_client_v17__invalidate_block!();

// == Hidden ==
crate::impl_client_v21__add_peer_address!();
crate::impl_client_v17__wait_for_block!();
crate::impl_client_v17__wait_for_block_height!();
crate::impl_client_v17__wait_for_new_block!();

// == Mining ==
crate::impl_client_v17__get_block_template!();
Expand Down
3 changes: 3 additions & 0 deletions client/src/client_sync/v23/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ crate::impl_client_v17__invalidate_block!();

// == Hidden ==
crate::impl_client_v21__add_peer_address!();
crate::impl_client_v17__wait_for_block!();
crate::impl_client_v17__wait_for_block_height!();
crate::impl_client_v17__wait_for_new_block!();

// == Mining ==
crate::impl_client_v17__get_block_template!();
Expand Down
3 changes: 3 additions & 0 deletions client/src/client_sync/v24/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ crate::impl_client_v17__invalidate_block!();

// == Hidden ==
crate::impl_client_v21__add_peer_address!();
crate::impl_client_v17__wait_for_block!();
crate::impl_client_v17__wait_for_block_height!();
crate::impl_client_v17__wait_for_new_block!();

// == Mining ==
crate::impl_client_v17__get_block_template!();
Expand Down
3 changes: 3 additions & 0 deletions client/src/client_sync/v25/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ crate::impl_client_v17__invalidate_block!();

// == Hidden ==
crate::impl_client_v21__add_peer_address!();
crate::impl_client_v17__wait_for_block!();
crate::impl_client_v17__wait_for_block_height!();
crate::impl_client_v17__wait_for_new_block!();

// == Mining ==
crate::impl_client_v17__get_block_template!();
Expand Down
3 changes: 3 additions & 0 deletions client/src/client_sync/v26/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ crate::impl_client_v17__invalidate_block!();

// == Hidden ==
crate::impl_client_v21__add_peer_address!();
crate::impl_client_v17__wait_for_block!();
crate::impl_client_v17__wait_for_block_height!();
crate::impl_client_v17__wait_for_new_block!();

// == Mining ==
crate::impl_client_v17__get_block_template!();
Expand Down
3 changes: 3 additions & 0 deletions client/src/client_sync/v27/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ crate::impl_client_v17__invalidate_block!();

// == Hidden ==
crate::impl_client_v21__add_peer_address!();
crate::impl_client_v17__wait_for_block!();
crate::impl_client_v17__wait_for_block_height!();
crate::impl_client_v17__wait_for_new_block!();

// == Mining ==
crate::impl_client_v17__get_block_template!();
Expand Down
3 changes: 3 additions & 0 deletions client/src/client_sync/v28/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ crate::impl_client_v17__invalidate_block!();

// == Hidden ==
crate::impl_client_v21__add_peer_address!();
crate::impl_client_v17__wait_for_block!();
crate::impl_client_v17__wait_for_block_height!();
crate::impl_client_v17__wait_for_new_block!();

// == Mining ==
crate::impl_client_v17__get_block_template!();
Expand Down
3 changes: 3 additions & 0 deletions client/src/client_sync/v29/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ crate::impl_client_v17__invalidate_block!();

// == Hidden ==
crate::impl_client_v21__add_peer_address!();
crate::impl_client_v17__wait_for_block!();
crate::impl_client_v17__wait_for_block_height!();
crate::impl_client_v17__wait_for_new_block!();

// == Mining ==
crate::impl_client_v17__get_block_template!();
Expand Down
3 changes: 3 additions & 0 deletions client/src/client_sync/v30/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ crate::impl_client_v23__save_mempool!();
crate::impl_client_v25__scan_blocks!();
crate::impl_client_v17__verify_chain!();
crate::impl_client_v17__verify_tx_out_proof!();
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!();
Expand Down
76 changes: 59 additions & 17 deletions integration_test/tests/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use bitcoin::consensus::encode;
use bitcoin::hex;
use integration_test::{Node, NodeExt as _, Wallet};
use node::client::client_sync;
use node::vtype::*; // All the version specific types.
use node::{mtype, Input, Output};

Expand Down Expand Up @@ -505,41 +504,84 @@ fn blockchain__scan_blocks_modelled() {
let _: ScanBlocksAbort = node.client.scan_blocks_abort().expect("scanblocks abort");
}

#[test]
fn blockchain__verify_chain() {
let node = Node::with_wallet(Wallet::None, &[]);

let _: Result<VerifyChain, _> = node.client.verify_chain();
}

#[test]
fn blockchain__verify_tx_out_proof__modelled() {
let node = Node::with_wallet(Wallet::Default, &[]);
node.fund_wallet();
verify_tx_out_proof(&node).unwrap();

let (_address, tx) = node.create_mined_transaction();
let txid = tx.compute_txid();

let proof = node.client.get_tx_out_proof(&[txid]).expect("gettxoutproof");

let json: VerifyTxOutProof = node.client.verify_tx_out_proof(&proof).expect("verifytxoutproof");
let model: Result<mtype::VerifyTxOutProof, hex::HexToArrayError> = json.into_model();
let txids = model.unwrap();

// sanity check
assert_eq!(txids.0.len(), 1);
}

#[test]
fn blockchain__get_tx_out_proof__modelled() {
fn blockchain__wait_for_block__modelled() {
let node = Node::with_wallet(Wallet::Default, &[]);
node.fund_wallet();
verify_tx_out_proof(&node).unwrap();
let (_address, _tx) = node.create_mined_transaction();
let block_hash = node.client.best_block_hash().expect("bestblockhash");

let json: WaitForBlock = node.client.wait_for_block(&block_hash).expect("waitforblock");
let model: Result<mtype::WaitForBlock, WaitForBlockError> = json.into_model();
let block = model.unwrap();
assert_eq!(block.hash, block_hash);
}

#[test]
fn blockchain__verify_chain() {
let node = Node::with_wallet(Wallet::None, &[]);
fn blockchain__wait_for_block_height__modelled() {
let node = Node::with_wallet(Wallet::Default, &[]);
node.fund_wallet();
let (_address, _tx) = node.create_mined_transaction();
let height = node.client.get_block_count().expect("getblockcount").0;
let block_hash = node.client.best_block_hash().expect("bestblockhash");
let target_height = height;

let _: Result<VerifyChain, _> = node.client.verify_chain();
let json: WaitForBlockHeight =
node.client.wait_for_block_height(target_height).expect("waitforblockheight");
let model: Result<mtype::WaitForBlockHeight, WaitForBlockHeightError> = json.into_model();
let block = model.unwrap();
assert_eq!(block.height, target_height as u32);
assert_eq!(block.hash, block_hash);
}

fn verify_tx_out_proof(node: &Node) -> Result<(), client_sync::Error> {
let (_address, tx) = node.create_mined_transaction();
let txid = tx.compute_txid();
#[test]
fn blockchain__wait_for_new_block__modelled() {
let (node1, node2, _node3) = integration_test::three_node_network();
node1.fund_wallet();
node1.mine_a_block();

let proof = node.client.get_tx_out_proof(&[txid])?;
let prev_hash = node1.client.best_block_hash().expect("bestblockhash");
let prev_height = node1.client.get_block_count().expect("getblockcount").0;

let json: VerifyTxOutProof = node.client.verify_tx_out_proof(&proof)?;
let model: Result<mtype::VerifyTxOutProof, hex::HexToArrayError> = json.into_model();
let txids = model.unwrap();
// Start waiting for a new block on node1 in a separate thread.
let handle = std::thread::spawn(move || {
let json: WaitForNewBlock = node1.client.wait_for_new_block().expect("waitfornewblock");
let model: Result<mtype::WaitForNewBlock, WaitForNewBlockError> = json.into_model();
model.unwrap()
});
std::thread::sleep(std::time::Duration::from_millis(200));

// sanity check
assert_eq!(txids.0.len(), 1);
// Trigger a new block on node2.
node2.mine_a_block();

Ok(())
let block = handle.join().expect("waitfornewblock thread panicked");
assert_eq!(block.height, (prev_height + 1) as u32);
assert_ne!(block.hash, prev_hash);
}

/// Create and broadcast a child transaction spending vout 0 of the given parent mempool txid.
Expand Down
27 changes: 27 additions & 0 deletions types/src/model/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -739,3 +739,30 @@ pub struct ScanBlocksStart {
/// Models the result of JSON-RPC method `verifytxoutproof`.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct VerifyTxOutProof(pub Vec<Txid>);

/// Models the result of JSON-RPC method `waitforblock`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct WaitForBlock {
/// The blockhash.
pub hash: BlockHash,
/// Block height.
pub height: u32,
}

/// Models the result of JSON-RPC method `waitforblockheight`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct WaitForBlockHeight {
/// The blockhash.
pub hash: BlockHash,
/// Block height.
pub height: u32,
}

/// Models the result of JSON-RPC method `waitfornewblock`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct WaitForNewBlock {
/// The blockhash.
pub hash: BlockHash,
/// Block height.
pub height: u32,
}
3 changes: 2 additions & 1 deletion types/src/model/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ pub use self::{
GetMempoolDescendants, GetMempoolDescendantsVerbose, GetMempoolEntry, GetMempoolInfo,
GetRawMempool, GetRawMempoolVerbose, GetTxOut, GetTxOutSetInfo, GetTxSpendingPrevout,
GetTxSpendingPrevoutItem, LoadTxOutSet, MempoolEntry, MempoolEntryFees, ReceiveActivity,
ScanBlocksStart, Softfork, SoftforkType, SpendActivity, VerifyTxOutProof,
ScanBlocksStart, Softfork, SoftforkType, SpendActivity, VerifyTxOutProof, WaitForBlock,
WaitForBlockHeight, WaitForNewBlock,
},
generating::{Generate, GenerateBlock, GenerateToAddress, GenerateToDescriptor},
mining::{
Expand Down
Loading