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
28 changes: 27 additions & 1 deletion client/src/client_sync/v17/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,33 @@ macro_rules! impl_client_v17__save_mempool {
};
}

/// Implements Bitcoin Core JSON-RPC API method `verifychain`.
/// Implements Bitcoin Core JSON-RPC API method `scantxoutset`
#[macro_export]
macro_rules! impl_client_v17__scan_tx_out_set {
() => {
impl Client {
/// Aborts an ongoing `scantxoutset` scan.
pub fn scan_tx_out_set_abort(&self) -> Result<ScanTxOutSetAbort> {
self.call("scantxoutset", &[into_json("abort")?])
}

/// Starts a scan of the UTXO set for specified descriptors.
pub fn scan_tx_out_set_start(
&self,
scan_objects: &[&str],
) -> Result<ScanTxOutSetStart> {
self.call("scantxoutset", &[into_json("start")?, into_json(scan_objects)?])
}

/// Checks the status of an ongoing `scantxoutset` scan.
pub fn scan_tx_out_set_status(&self) -> Result<Option<ScanTxOutSetStatus>> {
self.call("scantxoutset", &[into_json("status")?])
}
}
};
}

/// Implements Bitcoin Core JSON-RPC API method `verifychain`
#[macro_export]
macro_rules! impl_client_v17__verify_chain {
() => {
Expand Down
1 change: 1 addition & 0 deletions client/src/client_sync/v17/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ crate::impl_client_v17__get_tx_out_set_info!();
crate::impl_client_v17__precious_block!();
crate::impl_client_v17__prune_blockchain!();
crate::impl_client_v17__save_mempool!();
crate::impl_client_v17__scan_tx_out_set!();
crate::impl_client_v17__verify_chain!();
crate::impl_client_v17__verify_tx_out_proof!();

Expand Down
1 change: 1 addition & 0 deletions client/src/client_sync/v18/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ crate::impl_client_v17__get_tx_out_set_info!();
crate::impl_client_v17__precious_block!();
crate::impl_client_v17__prune_blockchain!();
crate::impl_client_v17__save_mempool!();
crate::impl_client_v17__scan_tx_out_set!();
crate::impl_client_v17__verify_chain!();
crate::impl_client_v17__verify_tx_out_proof!();

Expand Down
1 change: 1 addition & 0 deletions client/src/client_sync/v19/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ crate::impl_client_v17__get_tx_out_set_info!();
crate::impl_client_v17__precious_block!();
crate::impl_client_v17__prune_blockchain!();
crate::impl_client_v17__save_mempool!();
crate::impl_client_v17__scan_tx_out_set!();
crate::impl_client_v17__verify_chain!();
crate::impl_client_v17__verify_tx_out_proof!();

Expand Down
1 change: 1 addition & 0 deletions client/src/client_sync/v20/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ crate::impl_client_v17__get_tx_out_set_info!();
crate::impl_client_v17__precious_block!();
crate::impl_client_v17__prune_blockchain!();
crate::impl_client_v17__save_mempool!();
crate::impl_client_v17__scan_tx_out_set!();
crate::impl_client_v17__verify_chain!();
crate::impl_client_v17__verify_tx_out_proof!();

Expand Down
1 change: 1 addition & 0 deletions client/src/client_sync/v21/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ crate::impl_client_v17__get_tx_out_set_info!();
crate::impl_client_v17__precious_block!();
crate::impl_client_v17__prune_blockchain!();
crate::impl_client_v17__save_mempool!();
crate::impl_client_v17__scan_tx_out_set!();
crate::impl_client_v17__verify_chain!();
crate::impl_client_v17__verify_tx_out_proof!();

Expand Down
1 change: 1 addition & 0 deletions client/src/client_sync/v22/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ crate::impl_client_v17__get_tx_out_set_info!();
crate::impl_client_v17__precious_block!();
crate::impl_client_v17__prune_blockchain!();
crate::impl_client_v17__save_mempool!();
crate::impl_client_v17__scan_tx_out_set!();
crate::impl_client_v17__verify_chain!();
crate::impl_client_v17__verify_tx_out_proof!();

Expand Down
1 change: 1 addition & 0 deletions client/src/client_sync/v23/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ crate::impl_client_v17__get_tx_out_set_info!();
crate::impl_client_v17__precious_block!();
crate::impl_client_v17__prune_blockchain!();
crate::impl_client_v23__save_mempool!();
crate::impl_client_v17__scan_tx_out_set!();
crate::impl_client_v17__verify_chain!();
crate::impl_client_v17__verify_tx_out_proof!();

Expand Down
1 change: 1 addition & 0 deletions client/src/client_sync/v24/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ crate::impl_client_v24__get_tx_spending_prevout!();
crate::impl_client_v17__precious_block!();
crate::impl_client_v17__prune_blockchain!();
crate::impl_client_v23__save_mempool!();
crate::impl_client_v17__scan_tx_out_set!();
crate::impl_client_v17__verify_chain!();
crate::impl_client_v17__verify_tx_out_proof!();

Expand Down
1 change: 1 addition & 0 deletions client/src/client_sync/v25/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ 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!();

Expand Down
1 change: 1 addition & 0 deletions client/src/client_sync/v26/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ 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!();

Expand Down
1 change: 1 addition & 0 deletions client/src/client_sync/v27/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ 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!();

Expand Down
1 change: 1 addition & 0 deletions client/src/client_sync/v28/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ 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!();

Expand Down
1 change: 1 addition & 0 deletions client/src/client_sync/v29/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ 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!();

Expand Down
1 change: 1 addition & 0 deletions client/src/client_sync/v30/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ 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__wait_for_block!();
Expand Down
23 changes: 23 additions & 0 deletions integration_test/tests/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,29 @@ fn blockchain__scan_blocks_modelled() {
let _: ScanBlocksAbort = node.client.scan_blocks_abort().expect("scanblocks abort");
}

#[test]
fn blockchain__scan_tx_out_set_modelled() {
let node = match () {
#[cfg(feature = "v21_and_below")]
() => Node::with_wallet(Wallet::None, &[]),
#[cfg(not(feature = "v21_and_below"))]
() => Node::with_wallet(Wallet::None, &["-coinstatsindex=1"]),
};

let dummy_pubkey_hex = "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798";
let scan_desc = format!("pkh({})", dummy_pubkey_hex);

let json: ScanTxOutSetStart =
node.client.scan_tx_out_set_start(&[&scan_desc]).expect("scantxoutset start");
let model: Result<mtype::ScanTxOutSetStart, ScanTxOutSetError> = json.into_model();
model.unwrap();

let _: Option<ScanTxOutSetStatus> =
node.client.scan_tx_out_set_status().expect("scantxoutset status");

let _: ScanTxOutSetAbort = node.client.scan_tx_out_set_abort().expect("scantxoutset abort");
}

#[test]
fn blockchain__verify_chain() {
let node = Node::with_wallet(Wallet::None, &[]);
Expand Down
40 changes: 40 additions & 0 deletions types/src/model/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -770,3 +770,43 @@ pub struct WaitForNewBlock {
/// Block height.
pub height: u32,
}

/// Models the result of the JSON-RPC method `scantxoutset` start.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct ScanTxOutSetStart {
/// Whether the scan was completed.
pub success: bool,
/// The number of unspent transaction outputs scanned. For v19 onwards.
pub txouts: Option<u64>,
/// The block height at which the scan was done. For v19 onwards.
pub height: Option<u64>,
/// The hash of the block at the tip of the chain. For v19 onwards.
pub bestblock: Option<BlockHash>,
/// The unspents.
pub unspents: Vec<ScanTxOutSetUnspent>,
/// The total amount of all found unspent outputs in BTC.
pub total_amount: Amount,
}

/// Unspent outputs. Part of `scantxoutset`.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct ScanTxOutSetUnspent {
/// The transaction id.
pub txid: Txid,
/// The vout value.
pub vout: u32,
/// The output script.
pub script_pubkey: ScriptBuf,
/// A specialized descriptor for the matched output script. For v18 onwards.
pub desc: Option<String>,
/// The total amount in BTC of the unspent output.
pub amount: Amount,
/// Whether this is a coinbase output. For v25 onwards.
pub coinbase: Option<bool>,
/// Height of the unspent transaction output.
pub height: u64,
/// Blockhash of the unspent transaction output. For v28 onwards.
pub blockhash: Option<BlockHash>,
/// Number of confirmations of the unspent transaction output when the scan was done. For v28 onwards.
pub confirmations: Option<u64>,
}
4 changes: 2 additions & 2 deletions types/src/model/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ pub use self::{
GetMempoolDescendants, GetMempoolDescendantsVerbose, GetMempoolEntry, GetMempoolInfo,
GetRawMempool, GetRawMempoolVerbose, GetTxOut, GetTxOutSetInfo, GetTxSpendingPrevout,
GetTxSpendingPrevoutItem, LoadTxOutSet, MempoolEntry, MempoolEntryFees, ReceiveActivity,
ScanBlocksStart, Softfork, SoftforkType, SpendActivity, VerifyTxOutProof, WaitForBlock,
WaitForBlockHeight, WaitForNewBlock,
ScanBlocksStart, ScanTxOutSetStart, ScanTxOutSetUnspent, Softfork, SoftforkType,
SpendActivity, VerifyTxOutProof, WaitForBlock, WaitForBlockHeight, WaitForNewBlock,
},
generating::{Generate, GenerateBlock, GenerateToAddress, GenerateToDescriptor},
mining::{
Expand Down
56 changes: 56 additions & 0 deletions types/src/v17/blockchain/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -522,3 +522,59 @@ impl std::error::Error for GetTxOutSetInfoError {
impl From<NumericError> for GetTxOutSetInfoError {
fn from(e: NumericError) -> Self { Self::Numeric(e) }
}

/// Error when converting a `ScanTxOutSetError` into the model type.
#[derive(Debug)]
pub enum ScanTxOutSetError {
/// Conversion of the `bestblock` field failed.
BestBlockHash(hex::HexToArrayError),
/// Conversion of the `blockhash` field failed.
BlockHash(hex::HexToArrayError),
/// Conversion of the `txid` field failed.
Txid(hex::HexToArrayError),
/// Conversion of the `scriptPubKey` field failed.
ScriptPubKey(hex::HexToBytesError),
/// Conversion of the `total_amount` field failed.
TotalAmount(amount::ParseAmountError),
/// Conversion of the `amount` field failed.
Amount(amount::ParseAmountError),
/// Conversion of numeric type to expected type failed.
Numeric(NumericError),
}

impl fmt::Display for ScanTxOutSetError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use ScanTxOutSetError::*;

match self {
BestBlockHash(e) => write_err!(f, "conversion of the `bestblock` field failed"; e),
BlockHash(e) => write_err!(f, "conversion of the `blockhash` field failed"; e),
Txid(e) => write_err!(f, "conversion of the `txid` field failed"; e),
ScriptPubKey(e) => write_err!(f, "conversion of the `scriptPubKey` field failed"; e),
TotalAmount(e) => write_err!(f, "conversion of the `total_amount` field failed"; e),
Amount(e) => write_err!(f, "conversion of the `amount` field failed"; e),
Numeric(e) => write_err!(f, "numeric"; e),
}
}
}

#[cfg(feature = "std")]
impl std::error::Error for ScanTxOutSetError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
use ScanTxOutSetError::*;

match self {
BestBlockHash(e) => Some(e),
BlockHash(e) => Some(e),
Txid(e) => Some(e),
ScriptPubKey(e) => Some(e),
TotalAmount(e) => Some(e),
Amount(e) => Some(e),
Numeric(e) => Some(e),
}
}
}

impl From<NumericError> for ScanTxOutSetError {
fn from(e: NumericError) -> Self { Self::Numeric(e) }
}
46 changes: 45 additions & 1 deletion types/src/v17/blockchain/into.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: CC0-1.0

use bitcoin::consensus::encode;
use bitcoin::{block, hex, Block, BlockHash, CompactTarget, Txid, Weight, Work};
use bitcoin::{block, hex, Block, BlockHash, CompactTarget, ScriptBuf, Txid, Weight, Work};

// TODO: Use explicit imports?
use super::*;
Expand Down Expand Up @@ -552,6 +552,50 @@ impl GetTxOutSetInfo {
}
}

impl ScanTxOutSetStart {
/// Converts version specific type to a version nonspecific, more strongly typed type.
pub fn into_model(self) -> Result<model::ScanTxOutSetStart, ScanTxOutSetError> {
use ScanTxOutSetError as E;

let unspents =
self.unspents.into_iter().map(|u| u.into_model()).collect::<Result<Vec<_>, _>>()?;

let total_amount = Amount::from_btc(self.total_amount).map_err(E::TotalAmount)?;

Ok(model::ScanTxOutSetStart {
success: self.success,
txouts: None,
height: None,
bestblock: None,
unspents,
total_amount,
})
}
}

impl ScanTxOutSetUnspent {
/// Converts version specific type to a version nonspecific, more strongly typed type.
pub fn into_model(self) -> Result<model::ScanTxOutSetUnspent, ScanTxOutSetError> {
use ScanTxOutSetError as E;

let txid = self.txid.parse::<Txid>().map_err(E::Txid)?;
let amount = Amount::from_btc(self.amount).map_err(E::Amount)?;
let script_pubkey = ScriptBuf::from_hex(&self.script_pubkey).map_err(E::ScriptPubKey)?;

Ok(model::ScanTxOutSetUnspent {
txid,
vout: self.vout,
script_pubkey,
desc: None,
amount,
coinbase: None,
height: self.height,
blockhash: None,
confirmations: None,
})
}
}

impl VerifyTxOutProof {
/// Converts version specific type to a version nonspecific, more strongly typed type.
pub fn into_model(self) -> Result<model::VerifyTxOutProof, hex::HexToArrayError> {
Expand Down
Loading