Skip to content

Commit 696c385

Browse files
committed
Merge #311: Address all TODO in v25
f675362 Add scanblocks method model and test (Jamil Lambert, PhD) Pull request description: Go through all the TODO in the v25 types table. Add all the missing RPCs. One missing RPC in v25, `scanblocks` which has 3 different return shapes, one each for `abort`, `start` and `status`. Create a struct for each one. `status` returns null if there is no ongoing scan, use an Option in the client macro to deal with this. ACKs for top commit: tcharding: ACK f675362 Tree-SHA512: ad3fda4a9e7427d61925b2b0cc358259d3e1e24cfb28821e0aec117750ddbd800dd93b7a783ac7018c0a634fc56a7078757c96b214b6994bde4045381959ef6f
2 parents 2d0c090 + f675362 commit 696c385

File tree

17 files changed

+196
-13
lines changed

17 files changed

+196
-13
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// SPDX-License-Identifier: CC0-1.0
2+
3+
//! Macros for implementing JSON-RPC methods on a client.
4+
//!
5+
//! Specifically this is methods found under the `== Blockchain ==` section of the
6+
//! API docs of Bitcoin Core `v25`.
7+
//!
8+
//! All macros require `Client` to be in scope.
9+
//!
10+
//! See or use the `define_jsonrpc_minreq_client!` macro to define a `Client`.
11+
12+
/// Implements Bitcoin Core JSON-RPC API method `scanblocks`
13+
#[macro_export]
14+
macro_rules! impl_client_v25__scan_blocks {
15+
() => {
16+
impl Client {
17+
/// Aborts an ongoing `scanblocks` scan.
18+
pub fn scan_blocks_abort(&self) -> Result<ScanBlocksAbort> {
19+
self.call("scanblocks", &[into_json("abort")?])
20+
}
21+
22+
/// Starts a scan of blocks for specified descriptors.
23+
pub fn scan_blocks_start(&self, scan_objects: &[&str]) -> Result<ScanBlocksStart> {
24+
self.call("scanblocks", &[into_json("start")?, into_json(scan_objects)?])
25+
}
26+
27+
/// Checks the status of an ongoing `scanblocks` scan.
28+
pub fn scan_blocks_status(&self) -> Result<Option<ScanBlocksStatus>> {
29+
self.call("scanblocks", &[into_json("status")?])
30+
}
31+
}
32+
};
33+
}

client/src/client_sync/v25/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
//!
55
//! We ignore option arguments unless they effect the shape of the returned JSON data.
66
7+
pub mod blockchain;
78
pub mod generating;
89

910
use std::collections::BTreeMap;
@@ -54,6 +55,7 @@ crate::impl_client_v24__get_tx_spending_prevout!();
5455
crate::impl_client_v17__precious_block!();
5556
crate::impl_client_v17__prune_blockchain!();
5657
crate::impl_client_v23__save_mempool!();
58+
crate::impl_client_v25__scan_blocks!();
5759
crate::impl_client_v17__verify_chain!();
5860
crate::impl_client_v17__verify_tx_out_proof!();
5961

client/src/client_sync/v26/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ crate::impl_client_v24__get_tx_spending_prevout!();
5656
crate::impl_client_v17__precious_block!();
5757
crate::impl_client_v17__prune_blockchain!();
5858
crate::impl_client_v23__save_mempool!();
59+
crate::impl_client_v25__scan_blocks!();
5960
crate::impl_client_v17__verify_chain!();
6061
crate::impl_client_v17__verify_tx_out_proof!();
6162

client/src/client_sync/v27/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ crate::impl_client_v24__get_tx_spending_prevout!();
5252
crate::impl_client_v17__precious_block!();
5353
crate::impl_client_v17__prune_blockchain!();
5454
crate::impl_client_v23__save_mempool!();
55+
crate::impl_client_v25__scan_blocks!();
5556
crate::impl_client_v17__verify_chain!();
5657
crate::impl_client_v17__verify_tx_out_proof!();
5758

client/src/client_sync/v28/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ crate::impl_client_v24__get_tx_spending_prevout!();
5454
crate::impl_client_v17__precious_block!();
5555
crate::impl_client_v17__prune_blockchain!();
5656
crate::impl_client_v23__save_mempool!();
57+
crate::impl_client_v25__scan_blocks!();
5758
crate::impl_client_v17__verify_chain!();
5859
crate::impl_client_v17__verify_tx_out_proof!();
5960

client/src/client_sync/v29/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ crate::impl_client_v24__get_tx_spending_prevout!();
5454
crate::impl_client_v17__precious_block!();
5555
crate::impl_client_v17__prune_blockchain!();
5656
crate::impl_client_v23__save_mempool!();
57+
crate::impl_client_v25__scan_blocks!();
5758
crate::impl_client_v17__verify_chain!();
5859
crate::impl_client_v17__verify_tx_out_proof!();
5960

integration_test/tests/blockchain.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,23 @@ fn blockchain__savemempool() {
373373
}
374374
}
375375

376+
#[cfg(not(feature = "v24_and_below"))]
377+
#[test]
378+
fn blockchain__scan_blocks_modelled() {
379+
let node = Node::with_wallet(Wallet::None, &["-blockfilterindex=1"]);
380+
381+
// Arbitrary scan descriptor
382+
let scan_desc = "pkh(022afc20bf379bc96a2f4e9e63ffceb8652b2b6a097f63fbee6ecec2a49a48010e)";
383+
384+
let json: ScanBlocksStart = node.client.scan_blocks_start(&[scan_desc]).expect("scanblocks start");
385+
let model: Result<mtype::ScanBlocksStart, ScanBlocksStartError> = json.into_model();
386+
model.unwrap();
387+
388+
let _: Option<ScanBlocksStatus> = node.client.scan_blocks_status().expect("scanblocks status");
389+
390+
let _: ScanBlocksAbort = node.client.scan_blocks_abort().expect("scanblocks abort");
391+
}
392+
376393
#[test]
377394
fn blockchain__verify_tx_out_proof__modelled() {
378395
let node = Node::with_wallet(Wallet::Default, &[]);

types/src/model/blockchain.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,3 +702,14 @@ pub struct ReceiveActivity {
702702
/// The ScriptPubKey.
703703
pub output_spk: ScriptPubkey,
704704
}
705+
706+
/// Models the result of the JSON-RPC method `scanblocks` start.
707+
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
708+
pub struct ScanBlocksStart {
709+
/// The height we started the scan from
710+
pub from_height: u32,
711+
/// The height we ended the scan at
712+
pub to_height: u32,
713+
/// Blocks that may have matched a scanobject
714+
pub relevant_blocks: Vec<BlockHash>,
715+
}

types/src/model/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ pub use self::{
2929
GetMempoolAncestors, GetMempoolAncestorsVerbose, GetMempoolDescendants,
3030
GetMempoolDescendantsVerbose, GetMempoolEntry, GetMempoolInfo, GetRawMempool,
3131
GetRawMempoolVerbose, GetTxOut, GetTxOutSetInfo, GetTxSpendingPrevout,
32-
GetTxSpendingPrevoutItem, MempoolEntry, MempoolEntryFees, ReceiveActivity, Softfork,
33-
SoftforkType, SpendActivity, VerifyTxOutProof,
32+
GetTxSpendingPrevoutItem, MempoolEntry, MempoolEntryFees, ReceiveActivity, ScanBlocksStart,
33+
Softfork, SoftforkType, SpendActivity, VerifyTxOutProof,
3434
},
3535
generating::{Generate, GenerateBlock, GenerateToAddress, GenerateToDescriptor},
3636
mining::{

types/src/v25/blockchain/error.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// SPDX-License-Identifier: CC0-1.0
2+
3+
use core::fmt;
4+
5+
use bitcoin::hex;
6+
7+
use crate::error::write_err;
8+
use crate::NumericError;
9+
10+
/// Error when converting a `ScanBlocksStart` type into the model type.
11+
#[derive(Debug)]
12+
pub enum ScanBlocksStartError {
13+
/// Conversion of numeric type to expected type failed.
14+
Numeric(NumericError),
15+
/// Conversion of the `relevant_blocks` field failed.
16+
RelevantBlocks(hex::HexToArrayError),
17+
}
18+
19+
impl fmt::Display for ScanBlocksStartError {
20+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
21+
use ScanBlocksStartError as E;
22+
23+
match *self {
24+
E::Numeric(ref e) => write_err!(f, "numeric"; e),
25+
E::RelevantBlocks(ref e) =>
26+
write_err!(f, "conversion of the `relevant_blocks` field failed"; e),
27+
}
28+
}
29+
}
30+
31+
#[cfg(feature = "std")]
32+
impl std::error::Error for ScanBlocksStartError {
33+
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
34+
use ScanBlocksStartError as E;
35+
36+
match *self {
37+
E::Numeric(ref e) => Some(e),
38+
E::RelevantBlocks(ref e) => Some(e),
39+
}
40+
}
41+
}
42+
43+
impl From<NumericError> for ScanBlocksStartError {
44+
fn from(e: NumericError) -> Self { Self::Numeric(e) }
45+
}

0 commit comments

Comments
 (0)