Skip to content
Merged
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
8 changes: 1 addition & 7 deletions client/src/client_sync/v31/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,14 @@ macro_rules! impl_client_v31__get_tx_spending_prevout {
pub fn get_tx_spending_prevout(
&self,
outputs: &[bitcoin::OutPoint],
mempool_only: bool,
return_spending_tx: bool,
) -> Result<GetTxSpendingPrevout> {
let json_outputs: Vec<_> = outputs.iter().map(|out| {
serde_json::json!({
"txid": out.txid.to_string(),
"vout": out.vout,
})
}).collect();
let options = serde_json::json!({
"mempool_only": mempool_only,
"return_spending_tx": return_spending_tx,
});
self.call("gettxspendingprevout", &[json_outputs.into(), options])
self.call("gettxspendingprevout", &[json_outputs.into()])
}
}
};
Expand Down
9 changes: 7 additions & 2 deletions integration_test/tests/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,7 @@ fn blockchain__get_tx_spending_prevout__modelled() {
node.client.get_tx_spending_prevout(&inputs).expect("gettxspendingprevout");
#[cfg(not(feature = "v30_and_below"))]
let json: GetTxSpendingPrevout =
node.client.get_tx_spending_prevout(&inputs, true, false).expect("gettxspendingprevout");
node.client.get_tx_spending_prevout(&inputs).expect("gettxspendingprevout");
let model: Result<mtype::GetTxSpendingPrevout, GetTxSpendingPrevoutError> = json.into_model();
let spending_prevout = model.unwrap();

Expand All @@ -703,9 +703,14 @@ fn blockchain__get_tx_spending_prevout_spending_tx_and_block_hash__modelled() {
let (_address, tx) = node.create_mined_transaction();
let outpoint = tx.input[0].previous_output;

let outputs = bitcoind::serde_json::json!([{
"txid": outpoint.txid.to_string(),
"vout": outpoint.vout,
}]);
let options = bitcoind::serde_json::json!({ "return_spending_tx": true });
let json: GetTxSpendingPrevout = node
.client
.get_tx_spending_prevout(&[outpoint], false, true)
.call("gettxspendingprevout", &[outputs, options])
.expect("gettxspendingprevout");
let item = &json.0[0];
assert!(item.spending_txid.is_some());
Expand Down
3 changes: 1 addition & 2 deletions integration_test/tests/blockchain_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,7 @@ fn get_tx_spending_prevout_for_unspent_output() {
#[cfg(feature = "v30_and_below")]
let json: GetTxSpendingPrevout = node.client.get_tx_spending_prevout(&outpoints).unwrap();
#[cfg(not(feature = "v30_and_below"))]
let json: GetTxSpendingPrevout =
node.client.get_tx_spending_prevout(&outpoints, true, false).unwrap();
let json: GetTxSpendingPrevout = node.client.get_tx_spending_prevout(&outpoints).unwrap();

assert_eq!(json.0.len(), 1);
assert_eq!(json.0[0].txid, txid.to_string());
Expand Down
5 changes: 1 addition & 4 deletions integration_test/tests/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,7 @@ fn control__help() {
#[test]
fn control__logging() {
let node = BitcoinD::with_wallet(Wallet::None, &[]);
let logging: Logging = node.client.logging().unwrap();
#[cfg(not(feature = "v30_and_below"))]
let _ = (logging.kernel, logging.privatebroadcast);
let _ = logging;
let _: Logging = node.client.logging().unwrap();
}

#[test]
Expand Down
37 changes: 18 additions & 19 deletions types/src/model/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ use alloc::collections::BTreeMap;
use bitcoin::address::NetworkUnchecked;
use bitcoin::hashes::sha256;
use bitcoin::{
block, Address, Amount, Block, BlockHash, CompactTarget, FeeRate, Network, OutPoint, ScriptBuf,
Target, Transaction, TxMerkleNode, TxOut, Txid, Weight, Work, Wtxid,
absolute, block, transaction, Address, Amount, Block, BlockHash, CompactTarget, FeeRate,
Network, OutPoint, ScriptBuf, Sequence, Target, Transaction, TxMerkleNode, TxOut, Txid, Weight,
Witness, Work, Wtxid,
};
use serde::{Deserialize, Serialize};

Expand Down Expand Up @@ -42,23 +43,6 @@ pub struct GetBestBlockHash(pub BlockHash);
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct GetBlockVerboseZero(pub Block);

/// The coinbase transaction of a block. Part of `getblock` at verbosity 1, 2 and 3.
///
/// Introduced in Bitcoin Core v31.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct CoinbaseTransaction {
/// The coinbase transaction version.
pub version: i32,
/// The coinbase transaction's locktime.
pub locktime: u32,
/// The coinbase input's sequence number (nSequence).
pub sequence: u32,
/// The coinbase input's script.
pub coinbase: String,
/// The coinbase input's first (and only) witness stack element, if present.
pub witness: Option<String>,
}

/// Models the result of JSON-RPC method `getblock` with verbosity set to 1.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct GetBlockVerboseOne {
Expand Down Expand Up @@ -203,6 +187,21 @@ pub struct GetBlockVerboseThree {
pub next_block_hash: Option<BlockHash>,
}

/// Coinbase transaction metadata. Part of `getblock`.
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct CoinbaseTransaction {
/// The coinbase transaction version.
pub version: transaction::Version,
/// The coinbase transaction's locktime
pub locktime: absolute::LockTime,
/// The coinbase input's sequence number (nSequence).
pub sequence: Sequence,
/// The coinbase input's script.
pub coinbase: ScriptBuf,
/// The coinbase input's first (and only) witness stack element, if present.
pub witness: Option<Witness>,
}

/// A transaction entry for `getblock` verbosity 3.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct GetBlockVerboseThreeTransaction {
Expand Down
243 changes: 243 additions & 0 deletions types/src/v31/blockchain/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ use core::fmt;

use bitcoin::amount::ParseAmountError;
use bitcoin::consensus::encode;
use bitcoin::error::UnprefixedHexError;
use bitcoin::hex;

use crate::error::write_err;
use crate::v17::GetRawTransactionVerboseError;
use crate::NumericError;

/// Error when converting a `GetMempoolCluster` type into the model type.
Expand Down Expand Up @@ -220,3 +222,244 @@ impl std::error::Error for GetTxSpendingPrevoutError {
}
}
}

/// Error when converting a `CoinbaseTransaction` type into the model type.
#[derive(Debug)]
pub enum CoinbaseTransactionError {
/// Conversion of the `coinbase` field failed.
Coinbase(hex::HexToBytesError),
/// Conversion of the `witness` field failed.
Witness(hex::HexToBytesError),
}

impl fmt::Display for CoinbaseTransactionError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Self::Coinbase(ref e) => write_err!(f, "conversion of the `coinbase` field failed"; e),
Self::Witness(ref e) => write_err!(f, "conversion of the `witness` field failed"; e),
}
}
}

#[cfg(feature = "std")]
impl std::error::Error for CoinbaseTransactionError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match *self {
Self::Coinbase(ref e) => Some(e),
Self::Witness(ref e) => Some(e),
}
}
}

/// Error when converting a `GetBlockVerboseOne` type into the model type.
#[derive(Debug)]
pub enum GetBlockVerboseOneError {
/// Conversion of numeric type to expected type failed.
Numeric(NumericError),
/// Conversion of the transaction `hash` field failed.
Hash(hex::HexToArrayError),
/// Conversion of the transaction `merkle_root` field failed.
MerkleRoot(hex::HexToArrayError),
/// Conversion of the transaction `bits` field failed.
Bits(UnprefixedHexError),
/// Conversion of the `target` field failed.
Target(UnprefixedHexError),
/// Conversion of the transaction `chain_work` field failed.
ChainWork(UnprefixedHexError),
/// Conversion of the transaction `previous_block_hash` field failed.
PreviousBlockHash(hex::HexToArrayError),
/// Conversion of the transaction `next_block_hash` field failed.
NextBlockHash(hex::HexToArrayError),
/// Conversion of the `coinbase_tx` field failed.
CoinbaseTx(CoinbaseTransactionError),
}

impl fmt::Display for GetBlockVerboseOneError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Self::Numeric(ref e) => write_err!(f, "numeric"; e),
Self::Hash(ref e) => write_err!(f, "conversion of the `hash` field failed"; e),
Self::MerkleRoot(ref e) =>
write_err!(f, "conversion of the `merkle_root` field failed"; e),
Self::Bits(ref e) => write_err!(f, "conversion of the `bits` field failed"; e),
Self::Target(ref e) => write_err!(f, "conversion of the `target` field failed"; e),
Self::ChainWork(ref e) =>
write_err!(f, "conversion of the `chain_work` field failed"; e),
Self::PreviousBlockHash(ref e) =>
write_err!(f, "conversion of the `previous_block_hash` field failed"; e),
Self::NextBlockHash(ref e) =>
write_err!(f, "conversion of the `next_block_hash` field failed"; e),
Self::CoinbaseTx(ref e) =>
write_err!(f, "conversion of the `coinbase_tx` field failed"; e),
}
}
}

#[cfg(feature = "std")]
impl std::error::Error for GetBlockVerboseOneError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match *self {
Self::Numeric(ref e) => Some(e),
Self::Hash(ref e) => Some(e),
Self::MerkleRoot(ref e) => Some(e),
Self::Bits(ref e) => Some(e),
Self::Target(ref e) => Some(e),
Self::ChainWork(ref e) => Some(e),
Self::PreviousBlockHash(ref e) => Some(e),
Self::NextBlockHash(ref e) => Some(e),
Self::CoinbaseTx(ref e) => Some(e),
}
}
}

impl From<NumericError> for GetBlockVerboseOneError {
fn from(e: NumericError) -> Self { Self::Numeric(e) }
}

/// Error when converting a `GetBlockVerboseTwo` type into the model type.
#[derive(Debug)]
pub enum GetBlockVerboseTwoError {
/// Conversion of numeric type to expected type failed.
Numeric(NumericError),
/// Conversion of the transaction `hash` field failed.
Hash(hex::HexToArrayError),
/// Conversion of the transaction `merkle_root` field failed.
MerkleRoot(hex::HexToArrayError),
/// Conversion of the transaction `bits` field failed.
Bits(UnprefixedHexError),
/// Conversion of the `target` field failed.
Target(UnprefixedHexError),
/// Conversion of the transaction `chain_work` field failed.
ChainWork(UnprefixedHexError),
/// Conversion of the transaction `previous_block_hash` field failed.
PreviousBlockHash(hex::HexToArrayError),
/// Conversion of the transaction `next_block_hash` field failed.
NextBlockHash(hex::HexToArrayError),
/// Conversion of a transaction entry failed.
Transaction(GetRawTransactionVerboseError),
/// Conversion of the transaction `fee` field failed.
Fee(ParseAmountError),
/// Conversion of the `coinbase_tx` field failed.
CoinbaseTx(CoinbaseTransactionError),
}

impl fmt::Display for GetBlockVerboseTwoError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Self::Numeric(ref e) => write_err!(f, "numeric"; e),
Self::Hash(ref e) => write_err!(f, "conversion of the `hash` field failed"; e),
Self::MerkleRoot(ref e) =>
write_err!(f, "conversion of the `merkle_root` field failed"; e),
Self::Bits(ref e) => write_err!(f, "conversion of the `bits` field failed"; e),
Self::Target(ref e) => write_err!(f, "conversion of the `target` field failed"; e),
Self::ChainWork(ref e) =>
write_err!(f, "conversion of the `chain_work` field failed"; e),
Self::PreviousBlockHash(ref e) =>
write_err!(f, "conversion of the `previous_block_hash` field failed"; e),
Self::NextBlockHash(ref e) =>
write_err!(f, "conversion of the `next_block_hash` field failed"; e),
Self::Transaction(ref e) =>
write_err!(f, "conversion of a transaction entry failed"; e),
Self::Fee(ref e) => write_err!(f, "conversion of the `fee` field failed"; e),
Self::CoinbaseTx(ref e) =>
write_err!(f, "conversion of the `coinbase_tx` field failed"; e),
}
}
}

#[cfg(feature = "std")]
impl std::error::Error for GetBlockVerboseTwoError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match *self {
Self::Numeric(ref e) => Some(e),
Self::Hash(ref e) => Some(e),
Self::MerkleRoot(ref e) => Some(e),
Self::Bits(ref e) => Some(e),
Self::Target(ref e) => Some(e),
Self::ChainWork(ref e) => Some(e),
Self::PreviousBlockHash(ref e) => Some(e),
Self::NextBlockHash(ref e) => Some(e),
Self::Transaction(ref e) => Some(e),
Self::Fee(ref e) => Some(e),
Self::CoinbaseTx(ref e) => Some(e),
}
}
}

impl From<NumericError> for GetBlockVerboseTwoError {
fn from(e: NumericError) -> Self { Self::Numeric(e) }
}

/// Error when converting a `GetBlockVerboseThree` type into the model type.
#[derive(Debug)]
pub enum GetBlockVerboseThreeError {
/// Conversion of numeric type to expected type failed.
Numeric(NumericError),
/// Conversion of the transaction `hash` field failed.
Hash(hex::HexToArrayError),
/// Conversion of the transaction `merkle_root` field failed.
MerkleRoot(hex::HexToArrayError),
/// Conversion of the transaction `bits` field failed.
Bits(UnprefixedHexError),
/// Conversion of the `target` field failed.
Target(UnprefixedHexError),
/// Conversion of the transaction `chain_work` field failed.
ChainWork(UnprefixedHexError),
/// Conversion of the transaction `previous_block_hash` field failed.
PreviousBlockHash(hex::HexToArrayError),
/// Conversion of the transaction `next_block_hash` field failed.
NextBlockHash(hex::HexToArrayError),
/// Conversion of a transaction entry failed.
Transaction(crate::v29::GetBlockVerboseThreeError),
/// Conversion of the transaction `fee` field failed.
Fee(ParseAmountError),
/// Conversion of the `coinbase_tx` field failed.
CoinbaseTx(CoinbaseTransactionError),
}

impl fmt::Display for GetBlockVerboseThreeError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Self::Numeric(ref e) => write_err!(f, "numeric"; e),
Self::Hash(ref e) => write_err!(f, "conversion of the `hash` field failed"; e),
Self::MerkleRoot(ref e) =>
write_err!(f, "conversion of the `merkle_root` field failed"; e),
Self::Bits(ref e) => write_err!(f, "conversion of the `bits` field failed"; e),
Self::Target(ref e) => write_err!(f, "conversion of the `target` field failed"; e),
Self::ChainWork(ref e) =>
write_err!(f, "conversion of the `chain_work` field failed"; e),
Self::PreviousBlockHash(ref e) =>
write_err!(f, "conversion of the `previous_block_hash` field failed"; e),
Self::NextBlockHash(ref e) =>
write_err!(f, "conversion of the `next_block_hash` field failed"; e),
Self::Transaction(ref e) =>
write_err!(f, "conversion of a transaction entry failed"; e),
Self::Fee(ref e) => write_err!(f, "conversion of the `fee` field failed"; e),
Self::CoinbaseTx(ref e) =>
write_err!(f, "conversion of the `coinbase_tx` field failed"; e),
}
}
}

#[cfg(feature = "std")]
impl std::error::Error for GetBlockVerboseThreeError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match *self {
Self::Numeric(ref e) => Some(e),
Self::Hash(ref e) => Some(e),
Self::MerkleRoot(ref e) => Some(e),
Self::Bits(ref e) => Some(e),
Self::Target(ref e) => Some(e),
Self::ChainWork(ref e) => Some(e),
Self::PreviousBlockHash(ref e) => Some(e),
Self::NextBlockHash(ref e) => Some(e),
Self::Transaction(ref e) => Some(e),
Self::Fee(ref e) => Some(e),
Self::CoinbaseTx(ref e) => Some(e),
}
}
}

impl From<NumericError> for GetBlockVerboseThreeError {
fn from(e: NumericError) -> Self { Self::Numeric(e) }
}
Loading
Loading