Skip to content

Commit 9b7f019

Browse files
committed
Implement scantxoutset method and test
1 parent c51b9f7 commit 9b7f019

File tree

31 files changed

+442
-26
lines changed

31 files changed

+442
-26
lines changed

client/src/client_sync/v17/blockchain.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,30 @@ macro_rules! impl_client_v17__savemempool {
318318
};
319319
}
320320

321+
/// Implements Bitcoin Core JSON-RPC API method `scantxoutset`
322+
#[macro_export]
323+
macro_rules! impl_client_v17__scantxoutset {
324+
() => {
325+
impl Client {
326+
pub fn scan_tx_out_set(
327+
&self,
328+
action: ScanAction,
329+
scan_objects: &[ScanObject],
330+
) -> Result<ScanTxOutSet> {
331+
let params = match action {
332+
ScanAction::Start => {
333+
vec![into_json(action)?, into_json(scan_objects)?]
334+
}
335+
ScanAction::Abort | ScanAction::Status => {
336+
vec![into_json(action)?]
337+
}
338+
};
339+
self.call("scantxoutset", &params)
340+
}
341+
}
342+
};
343+
}
344+
321345
/// Implements Bitcoin Core JSON-RPC API method `verifychain`
322346
#[macro_export]
323347
macro_rules! impl_client_v17__verifychain {

client/src/client_sync/v17/mod.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ crate::impl_client_v17__gettxoutsetinfo!();
4747
crate::impl_client_v17__preciousblock!();
4848
crate::impl_client_v17__pruneblockchain!();
4949
crate::impl_client_v17__savemempool!();
50+
crate::impl_client_v17__scantxoutset!();
5051
crate::impl_client_v17__verifychain!();
5152
crate::impl_client_v17__verifytxoutproof!();
5253

@@ -206,3 +207,24 @@ pub struct WalletCreateFundedPsbtInput {
206207
txid: Txid,
207208
vout: u32,
208209
}
210+
211+
/// Args for the `scantxoutset`
212+
///
213+
/// Represents the action for the `scantxoutset` RPC call.
214+
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
215+
#[serde(rename_all = "lowercase")]
216+
pub enum ScanAction {
217+
Start,
218+
Abort,
219+
Status,
220+
}
221+
222+
/// Represents a scan object for scantxoutset (descriptor string or object).
223+
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
224+
#[serde(untagged)]
225+
pub enum ScanObject {
226+
/// Plain descriptor string
227+
Descriptor(String),
228+
/// Object containing descriptor and optional range
229+
WithDesc { desc: String },
230+
}

client/src/client_sync/v18/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ use crate::types::v18::*;
1919

2020
#[rustfmt::skip] // Keep public re-exports separate.
2121
pub use crate::client_sync::{
22-
v17::{AddressType, Input, Output, TemplateRequest, TemplateRules, WalletCreateFundedPsbtInput},
22+
v17::{
23+
AddressType, Input, Output, ScanAction, ScanObject, TemplateRequest,
24+
TemplateRules, WalletCreateFundedPsbtInput
25+
},
2326
};
2427

2528
// This publicly re-exports `Client`.
@@ -48,6 +51,7 @@ crate::impl_client_v17__gettxoutsetinfo!();
4851
crate::impl_client_v17__preciousblock!();
4952
crate::impl_client_v17__pruneblockchain!();
5053
crate::impl_client_v17__savemempool!();
54+
crate::impl_client_v17__scantxoutset!();
5155
crate::impl_client_v17__verifychain!();
5256
crate::impl_client_v17__verifytxoutproof!();
5357

client/src/client_sync/v19/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ use crate::types::v19::*;
1818

1919
#[rustfmt::skip] // Keep public re-exports separate.
2020
pub use crate::client_sync::{
21-
v17::{AddressType, Input, Output, TemplateRequest, TemplateRules, WalletCreateFundedPsbtInput},
21+
v17::{
22+
AddressType, Input, Output, ScanAction, ScanObject, TemplateRequest,
23+
TemplateRules, WalletCreateFundedPsbtInput
24+
},
2225
};
2326

2427
crate::define_jsonrpc_minreq_client!("v19");
@@ -47,6 +50,7 @@ crate::impl_client_v17__gettxoutsetinfo!();
4750
crate::impl_client_v17__preciousblock!();
4851
crate::impl_client_v17__pruneblockchain!();
4952
crate::impl_client_v17__savemempool!();
53+
crate::impl_client_v17__scantxoutset!();
5054
crate::impl_client_v17__verifychain!();
5155
crate::impl_client_v17__verifytxoutproof!();
5256

client/src/client_sync/v20.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ use crate::types::v20::*;
1515

1616
#[rustfmt::skip] // Keep public re-exports separate.
1717
pub use crate::client_sync::{
18-
v17::{AddressType, Input, Output, TemplateRequest, TemplateRules, WalletCreateFundedPsbtInput},
18+
v17::{
19+
AddressType, Input, Output, ScanAction, ScanObject, TemplateRequest,
20+
TemplateRules, WalletCreateFundedPsbtInput
21+
},
1922
};
2023

2124
crate::define_jsonrpc_minreq_client!("v20");
@@ -44,6 +47,7 @@ crate::impl_client_v17__gettxoutsetinfo!();
4447
crate::impl_client_v17__preciousblock!();
4548
crate::impl_client_v17__pruneblockchain!();
4649
crate::impl_client_v17__savemempool!();
50+
crate::impl_client_v17__scantxoutset!();
4751
crate::impl_client_v17__verifychain!();
4852
crate::impl_client_v17__verifytxoutproof!();
4953

client/src/client_sync/v21/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ use crate::types::v21::*;
1717

1818
#[rustfmt::skip] // Keep public re-exports separate.
1919
pub use crate::client_sync::{
20-
v17::{AddressType, Input, Output, TemplateRequest, TemplateRules, WalletCreateFundedPsbtInput},
20+
v17::{
21+
AddressType, Input, Output, ScanAction, ScanObject, TemplateRequest,
22+
TemplateRules, WalletCreateFundedPsbtInput
23+
},
2124
};
2225

2326
crate::define_jsonrpc_minreq_client!("v21");
@@ -46,6 +49,7 @@ crate::impl_client_v17__gettxoutsetinfo!();
4649
crate::impl_client_v17__preciousblock!();
4750
crate::impl_client_v17__pruneblockchain!();
4851
crate::impl_client_v17__savemempool!();
52+
crate::impl_client_v17__scantxoutset!();
4953
crate::impl_client_v17__verifychain!();
5054
crate::impl_client_v17__verifytxoutproof!();
5155

client/src/client_sync/v22/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ use crate::types::v22::*;
1717

1818
#[rustfmt::skip] // Keep public re-exports separate.
1919
pub use crate::client_sync::{
20-
v17::{AddressType, Input, Output, TemplateRequest, TemplateRules, WalletCreateFundedPsbtInput},
20+
v17::{
21+
AddressType, Input, Output, ScanAction, ScanObject, TemplateRequest,
22+
TemplateRules, WalletCreateFundedPsbtInput
23+
},
2124
};
2225

2326
crate::define_jsonrpc_minreq_client!("v22");
@@ -46,6 +49,7 @@ crate::impl_client_v17__gettxoutsetinfo!();
4649
crate::impl_client_v17__preciousblock!();
4750
crate::impl_client_v17__pruneblockchain!();
4851
crate::impl_client_v17__savemempool!();
52+
crate::impl_client_v17__scantxoutset!();
4953
crate::impl_client_v17__verifychain!();
5054
crate::impl_client_v17__verifytxoutproof!();
5155

client/src/client_sync/v23/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ use crate::types::v23::*;
1919

2020
#[rustfmt::skip] // Keep public re-exports separate.
2121
pub use crate::client_sync::{
22-
v17::{Input, Output, TemplateRequest, TemplateRules, WalletCreateFundedPsbtInput},
22+
v17::{
23+
Input, Output, ScanAction, ScanObject, TemplateRequest,
24+
TemplateRules, WalletCreateFundedPsbtInput
25+
},
2326
};
2427

2528
crate::define_jsonrpc_minreq_client!("v23");
@@ -48,6 +51,7 @@ crate::impl_client_v17__gettxoutsetinfo!();
4851
crate::impl_client_v17__preciousblock!();
4952
crate::impl_client_v17__pruneblockchain!();
5053
crate::impl_client_v23__savemempool!();
54+
crate::impl_client_v17__scantxoutset!();
5155
crate::impl_client_v17__verifychain!();
5256
crate::impl_client_v17__verifytxoutproof!();
5357

client/src/client_sync/v24.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ use crate::types::v24::*;
1515

1616
#[rustfmt::skip] // Keep public re-exports separate.
1717
pub use crate::client_sync::{
18-
v17::{Input, Output, TemplateRequest, TemplateRules, WalletCreateFundedPsbtInput},
18+
v17::{
19+
Input, Output, ScanAction, ScanObject, TemplateRequest, TemplateRules,
20+
WalletCreateFundedPsbtInput
21+
},
1922
v23::AddressType,
2023
};
2124

@@ -45,6 +48,7 @@ crate::impl_client_v17__gettxoutsetinfo!();
4548
crate::impl_client_v17__preciousblock!();
4649
crate::impl_client_v17__pruneblockchain!();
4750
crate::impl_client_v23__savemempool!();
51+
crate::impl_client_v17__scantxoutset!();
4852
crate::impl_client_v17__verifychain!();
4953
crate::impl_client_v17__verifytxoutproof!();
5054

client/src/client_sync/v25.rs renamed to client/src/client_sync/v25/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ use crate::types::v25::*;
1515

1616
#[rustfmt::skip] // Keep public re-exports separate.
1717
pub use crate::client_sync::{
18-
v17::{Input, Output, TemplateRequest, TemplateRules, WalletCreateFundedPsbtInput},
18+
v17::{
19+
Input, Output, ScanAction, ScanObject, TemplateRequest, TemplateRules,
20+
WalletCreateFundedPsbtInput
21+
},
1922
v23::AddressType,
2023
};
2124

@@ -45,6 +48,7 @@ crate::impl_client_v17__gettxoutsetinfo!();
4548
crate::impl_client_v17__preciousblock!();
4649
crate::impl_client_v17__pruneblockchain!();
4750
crate::impl_client_v23__savemempool!();
51+
crate::impl_client_v17__scantxoutset!();
4852
crate::impl_client_v17__verifychain!();
4953
crate::impl_client_v17__verifytxoutproof!();
5054

client/src/client_sync/v26/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ use crate::types::v26::*;
1919

2020
#[rustfmt::skip] // Keep public re-exports separate.
2121
pub use crate::client_sync::{
22-
v17::{Input, Output, TemplateRequest, TemplateRules, WalletCreateFundedPsbtInput},
22+
v17::{
23+
Input, Output, ScanAction, ScanObject, TemplateRequest,
24+
TemplateRules, WalletCreateFundedPsbtInput
25+
},
2326
v23::AddressType,
2427
};
2528

@@ -49,6 +52,7 @@ crate::impl_client_v26__gettxoutsetinfo!();
4952
crate::impl_client_v17__preciousblock!();
5053
crate::impl_client_v17__pruneblockchain!();
5154
crate::impl_client_v23__savemempool!();
55+
crate::impl_client_v17__scantxoutset!();
5256
crate::impl_client_v17__verifychain!();
5357
crate::impl_client_v17__verifytxoutproof!();
5458

client/src/client_sync/v27.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ use crate::types::v27::*;
1515

1616
#[rustfmt::skip] // Keep public re-exports separate.
1717
pub use crate::client_sync::{
18-
v17::{Input, Output, TemplateRequest, TemplateRules, WalletCreateFundedPsbtInput},
18+
v17::{
19+
Input, Output, ScanAction, ScanObject, TemplateRequest, TemplateRules,
20+
WalletCreateFundedPsbtInput
21+
},
1922
v23::AddressType,
2023
};
2124

@@ -45,6 +48,7 @@ crate::impl_client_v26__gettxoutsetinfo!();
4548
crate::impl_client_v17__preciousblock!();
4649
crate::impl_client_v17__pruneblockchain!();
4750
crate::impl_client_v23__savemempool!();
51+
crate::impl_client_v17__scantxoutset!();
4852
crate::impl_client_v17__verifychain!();
4953
crate::impl_client_v17__verifytxoutproof!();
5054

client/src/client_sync/v28/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ use crate::types::v28::*;
1717

1818
#[rustfmt::skip] // Keep public re-exports separate.
1919
pub use crate::client_sync::{
20-
v17::{Input, Output, TemplateRequest, TemplateRules, WalletCreateFundedPsbtInput},
20+
v17::{
21+
Input, Output, ScanAction, ScanObject, TemplateRequest,
22+
TemplateRules, WalletCreateFundedPsbtInput
23+
},
2124
v23::AddressType,
2225
};
2326

@@ -47,6 +50,7 @@ crate::impl_client_v26__gettxoutsetinfo!();
4750
crate::impl_client_v17__preciousblock!();
4851
crate::impl_client_v17__pruneblockchain!();
4952
crate::impl_client_v23__savemempool!();
53+
crate::impl_client_v17__scantxoutset!();
5054
crate::impl_client_v17__verifychain!();
5155
crate::impl_client_v17__verifytxoutproof!();
5256

integration_test/tests/blockchain.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,35 @@ fn blockchain__savemempool() {
307307
}
308308
}
309309

310+
#[test]
311+
fn blockchain__scan_tx_out_set_modelled() {
312+
#[cfg(any(
313+
feature = "v17",
314+
feature = "v18",
315+
feature = "v19",
316+
feature = "v20",
317+
feature = "v21"
318+
))]
319+
let node = Node::with_wallet(Wallet::None, &[]);
320+
321+
#[cfg(not(any(
322+
feature = "v17",
323+
feature = "v18",
324+
feature = "v19",
325+
feature = "v20",
326+
feature = "v21"
327+
)))]
328+
let node = Node::with_wallet(Wallet::None, &["-coinstatsindex=1"]);
329+
330+
let dummy_pubkey_hex = "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798";
331+
let scan_desc = format!("pkh({})", dummy_pubkey_hex);
332+
333+
let scan_objects: node::ScanObject = node::ScanObject::Descriptor(scan_desc);
334+
let action: node::ScanAction = node::ScanAction::Start;
335+
336+
let _: Result<ScanTxOutSet, _> = node.client.scan_tx_out_set(action, &[scan_objects]);
337+
}
338+
310339
#[test]
311340
fn blockchain__verify_tx_out_proof__modelled() {
312341
let node = Node::with_wallet(Wallet::Default, &[]);

types/src/v17/blockchain/mod.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,53 @@ pub struct PruneBlockchain(
650650
pub i64,
651651
);
652652

653+
/// Result of JSON-RPC method `scantxoutset`.
654+
///
655+
/// > scantxoutset "action" ( [scanobjects,...] )
656+
/// >
657+
/// > Arguments:
658+
/// > 1. "action" (string, required) The action to execute
659+
/// > 2. "scanobjects" (array, required) Array of scan objects
660+
#[derive(Deserialize, Debug, Clone, PartialEq)]
661+
#[serde(untagged)]
662+
pub enum ScanTxOutSet {
663+
/// Returns after scan completes
664+
Start(ScanTxOutSetStart),
665+
/// True (scan will be aborted), False (no scan to abort)
666+
Abort(bool),
667+
/// Scan in progress or Completed
668+
Status(Option<ScanTxOutSetStatus>),
669+
}
670+
671+
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
672+
pub struct ScanTxOutSetStart {
673+
/// The unspents
674+
pub unspents: Vec<ScanTxOutSetUnspent>,
675+
/// The total amount of all found unspent outputs in BTC
676+
pub total_amount: f64,
677+
}
678+
679+
#[derive(Deserialize, Debug, Clone, PartialEq)]
680+
pub struct ScanTxOutSetStatus {
681+
/// Approximate percent complete
682+
pub progress: f64,
683+
}
684+
685+
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
686+
pub struct ScanTxOutSetUnspent {
687+
/// The transaction id
688+
pub txid: String,
689+
/// The vout value
690+
pub vout: u32,
691+
/// The script key
692+
#[serde(rename = "scriptPubKey")]
693+
pub script_pubkey: String,
694+
/// The total amount in BTC of unspent output
695+
pub amount: f64,
696+
/// Height of the unspent transaction output
697+
pub height: u64,
698+
}
699+
653700
/// Result of JSON-RPC method `verifychain`.
654701
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
655702
pub struct VerifyChain(pub bool);

types/src/v17/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,9 @@ pub use self::{
243243
GetMempoolDescendantsVerbose, GetMempoolEntry, GetMempoolInfo, GetMempoolInfoError,
244244
GetRawMempool, GetRawMempoolVerbose, GetTxOut, GetTxOutError, GetTxOutSetInfo,
245245
GetTxOutSetInfoError, MapMempoolEntryError, MempoolEntry, MempoolEntryError,
246-
MempoolEntryFees, MempoolEntryFeesError, PruneBlockchain, Softfork, SoftforkReject,
247-
VerifyChain, VerifyTxOutProof,
246+
MempoolEntryFees, MempoolEntryFeesError, PruneBlockchain, ScanTxOutSet, ScanTxOutSetStart,
247+
ScanTxOutSetStatus, ScanTxOutSetUnspent, Softfork, SoftforkReject, VerifyChain,
248+
VerifyTxOutProof,
248249
},
249250
control::{GetMemoryInfoStats, Locked, Logging},
250251
generating::{Generate, GenerateToAddress},

0 commit comments

Comments
 (0)