Skip to content

Add new return fields from later versions to v17 types #271

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
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
3 changes: 3 additions & 0 deletions types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ pub fn compact_size_decode(slice: &mut &[u8]) -> u64 {
pub struct ScriptPubkey {
/// Script assembly.
pub asm: String,
/// Inferred descriptor for the output. v23 and later only.
#[serde(rename = "desc")]
pub descriptor: Option<String>,
/// Script hex.
pub hex: String,
/// Number of required signatures - deprecated in Core v22.
Expand Down
12 changes: 6 additions & 6 deletions types/src/model/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,11 @@ pub use self::{
GetAddressesByLabel, GetBalance, GetBalances, GetBalancesMine, GetBalancesWatchOnly,
GetNewAddress, GetRawChangeAddress, GetReceivedByAddress, GetReceivedByLabel,
GetTransaction, GetTransactionDetail, GetUnconfirmedBalance, GetWalletInfo,
ListAddressGroupings, ListAddressGroupingsItem, ListLabels, ListLockUnspent,
ListLockUnspentItem, ListReceivedByAddress, ListReceivedByAddressItem, ListReceivedByLabel,
ListReceivedByLabelItem, ListSinceBlock, ListSinceBlockTransaction, ListTransactions,
ListTransactionsItem, ListUnspent, ListUnspentItem, ListWallets, LoadWallet,
RescanBlockchain, ScriptType, SendMany, SendToAddress, SignMessage, TransactionCategory,
UnloadWallet, WalletCreateFundedPsbt, WalletProcessPsbt,
LastProcessedBlock, ListAddressGroupings, ListAddressGroupingsItem, ListLabels,
ListLockUnspent, ListLockUnspentItem, ListReceivedByAddress, ListReceivedByAddressItem,
ListReceivedByLabel, ListReceivedByLabelItem, ListSinceBlock, ListSinceBlockTransaction,
ListTransactions, ListTransactionsItem, ListUnspent, ListUnspentItem, ListWallets,
LoadWallet, RescanBlockchain, ScriptType, SendMany, SendToAddress, SignMessage,
TransactionCategory, UnloadWallet, WalletCreateFundedPsbt, WalletProcessPsbt,
},
};
6 changes: 5 additions & 1 deletion types/src/model/raw_transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,12 @@ pub struct DecodeRawTransaction(pub Transaction);
pub struct DecodeScript {
/// The `scriptPubkey`.
pub script_pubkey: Option<ScriptBuf>,
/// Inferred descriptor for the script. v23 and later only.
pub descriptor: Option<String>,
/// The output type.
pub type_: Option<String>,
pub type_: String,
/// Bitcoin address (only if a well-defined address exists). v22 and later only.
pub address: Option<Address<NetworkUnchecked>>,
/// The required signatures.
pub required_signatures: Option<u64>,
/// List of bitcoin addresses.
Expand Down
33 changes: 33 additions & 0 deletions types/src/model/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,27 +290,51 @@ pub struct GetTransaction {
pub fee: Option<SignedAmount>,
/// The number of confirmations.
pub confirmations: i64, // Docs do not indicate what negative value means?
/// Only present if the transaction's only input is a coinbase one. v29 and later only.
pub generated: Option<bool>,
/// Whether we consider the outputs of this unconfirmed transaction safe to spend.
pub trusted: Option<bool>,
/// The block hash.
pub block_hash: Option<BlockHash>,
/// The block height containing the transaction. v29 and later only.
pub block_height: Option<u32>,
/// The index of the transaction in the block that includes it.
pub block_index: Option<u32>,
/// The time in seconds since epoch (1 Jan 1970 GMT).
pub block_time: Option<u32>,
/// The transaction id.
pub txid: Txid,
/// The hash of serialized transaction, including witness data. v29 and later only.
pub wtxid: Option<Txid>,
/// Confirmed transactions that have been detected by the wallet to conflict with this transaction.
pub wallet_conflicts: Vec<Txid>,
/// Only if 'category' is 'send'. The txid if this tx was replaced. v29 and later only.
pub replaced_by_txid: Option<Txid>,
/// Only if 'category' is 'send'. The txid if this tx replaces another. v29 and later only.
pub replaces_txid: Option<Txid>,
/// Transactions in the mempool that directly conflict with either this transaction or an ancestor transaction. v29 and later only.
pub mempool_conflicts: Option<Vec<Txid>>,
/// If a comment to is associated with the transaction. v29 and later only.
pub to: Option<String>,
/// The transaction time in seconds since epoch (1 Jan 1970 GMT).
pub time: u32,
/// The time received in seconds since epoch (1 Jan 1970 GMT).
pub time_received: u32,
/// If a comment is associated with the transaction, only present if not empty. v29 and later only.
pub comment: Option<String>,
/// Whether this transaction could be replaced due to BIP125 (replace-by-fee);
/// may be unknown for unconfirmed transactions not in the mempool
pub bip125_replaceable: Bip125Replaceable,
/// Only if 'category' is 'received'. List of parent descriptors for the output script of this coin. v29 and later only.
pub parent_descriptors: Option<Vec<String>>,
/// Transaction details.
pub details: Vec<GetTransactionDetail>,
/// Raw data for transaction. v29 and later only.
pub hex: Option<String>,
/// The decoded transaction (only present when `verbose` is passed). v29 and later only.
pub decoded: Option<Transaction>,
/// Hash and height of the block this information was generated on. v29 and later only.
pub last_processed_block: Option<LastProcessedBlock>,
/// The transaction, parsed from hex string.
pub tx: Transaction,
}
Expand Down Expand Up @@ -340,6 +364,15 @@ pub struct GetTransactionDetail {
pub abandoned: Option<bool>,
}

/// Part of the `GetTransaction`.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct LastProcessedBlock {
/// Hash of the block this information was generated on.
pub hash: BlockHash,
/// Height of the block this information was generated on.
pub height: u32,
}

/// Models the result of JSON-RPC method `getunconfirmedbalance`.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct GetUnconfirmedBalance(pub Amount);
Expand Down
41 changes: 25 additions & 16 deletions types/src/v17/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,25 +52,34 @@ pub struct Locked {
/// > Gets and sets the logging configuration.
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct Logging {
pub net: bool,
pub tor: bool,
pub mempool: bool,
pub http: bool,
pub bench: bool,
pub zmq: bool,
pub db: bool,
pub rpc: bool,
pub estimatefee: bool,
pub addrman: bool,
pub selectcoins: bool,
pub reindex: bool,
pub bench: bool,
pub blockstorage: Option<bool>, // v23 and later only
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TL;DR At this stage I don't want to make changes like this because it invalidates the whole design of the crate.

I accidentally did this same thing once but I came to the conclusion that doing so totally invalidates the whole design of the crate. The whole point of v17::Foo is that one knows that this is the exact shape of a Foo returned by Bitcoin Core v17. If one wants to not think about the version and check all the optional fields then one can first convert to a model type and do so. The central claim of this repo is that these use cases are different and keeping them separate will lead to better software. This was an intuitive leap and only time will tell if I was correct.

pub cmpctblock: bool,
pub rand: bool,
pub coindb: bool,
pub db: Option<bool>, // v22 and before only
pub estimatefee: bool,
pub http: bool,
pub i2p: Option<bool>, // v23 and later only
pub ipc: Option<bool>, // v23 and later only
pub leveldb: bool,
pub libevent: bool,
pub mempool: bool,
pub mempoolrej: bool,
pub net: bool,
pub prune: bool,
pub proxy: bool,
pub mempoolrej: bool,
pub libevent: bool,
pub coindb: bool,
pub qt: bool,
pub leveldb: bool,
pub rand: bool,
pub reindex: bool,
pub rpc: bool,
pub scan: Option<bool>, // v25 and later only
pub selectcoins: bool,
pub tor: bool,
pub txpackages: Option<bool>, // v26 and later only
pub txreconciliation: Option<bool>, // v25 and later only
pub util: Option<bool>, // v23 and later only
pub validation: Option<bool>, // v23 and later only
pub walletdb: Option<bool>, // v23 and later only
pub zmq: bool,
}
4 changes: 4 additions & 0 deletions types/src/v17/raw_transactions/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ impl std::error::Error for PsbtOutputError {
pub enum DecodeScriptError {
/// Conversion of the transaction `hex` field failed.
Hex(hex::HexToBytesError),
/// Conversion of the transaction `address` field failed.
Address(address::ParseError),
/// Conversion of the transaction `addresses` field failed.
Addresses(address::ParseError),
/// Conversion of the transaction `p2sh` field failed.
Expand All @@ -186,6 +188,7 @@ impl fmt::Display for DecodeScriptError {

match *self {
E::Hex(ref e) => write_err!(f, "conversion of the `hex` field failed"; e),
E::Address(ref e) => write_err!(f, "conversion of the `address` field failed"; e),
E::Addresses(ref e) => write_err!(f, "conversion of the `addresses` field failed"; e),
E::P2sh(ref e) => write_err!(f, "conversion of the `p2sh` field failed"; e),
}
Expand All @@ -199,6 +202,7 @@ impl std::error::Error for DecodeScriptError {

match *self {
E::Hex(ref e) => Some(e),
E::Address(ref e) => Some(e),
E::Addresses(ref e) => Some(e),
E::P2sh(ref e) => Some(e),
}
Expand Down
6 changes: 6 additions & 0 deletions types/src/v17/raw_transactions/into.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,10 @@ impl DecodeScript {
Some(hex) => Some(ScriptBuf::from_hex(&hex).map_err(E::Hex)?),
None => None,
};
let address = match self.address {
Some(addr) => Some(addr.parse::<Address<_>>().map_err(E::Address)?),
None => None,
};
let addresses = match self.addresses {
Some(addresses) => addresses
.iter()
Expand All @@ -304,6 +308,8 @@ impl DecodeScript {
Ok(model::DecodeScript {
script_pubkey,
type_: self.type_,
descriptor: self.descriptor,
address,
required_signatures: self.required_signatures,
addresses,
p2sh,
Expand Down
12 changes: 11 additions & 1 deletion types/src/v17/raw_transactions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,14 @@ pub struct DecodeScript {
pub asm: String,
/// Hex encoded public key.
pub hex: Option<String>,
/// Inferred descriptor for the script. v23 and later only.
#[serde(rename = "desc")]
pub descriptor: Option<String>,
/// The output type.
#[serde(rename = "type")]
pub type_: Option<String>,
pub type_: String,
/// Bitcoin address (only if a well-defined address exists). v22 and later only.
pub address: Option<String>,
/// The required signatures.
#[serde(rename = "reqSigs")]
pub required_signatures: Option<u64>,
Expand All @@ -235,11 +240,16 @@ pub struct DecodeScriptSegwit {
/// The output type.
#[serde(rename = "type")]
pub type_: String,
/// Bitcoin address (only if a well-defined address exists). v22 and later only.
pub address: Option<String>,
/// The required signatures.
#[serde(rename = "reqSigs")]
pub required_signatures: Option<u64>,
/// List of bitcoin addresses.
pub addresses: Option<Vec<String>>,
/// Inferred descriptor for the script. v23 and later only.
#[serde(rename = "desc")]
pub descriptor: Option<String>,
/// Address of P2SH script wrapping this redeem script (not returned if the script is already a P2SH).
#[serde(rename = "p2sh-segwit")]
pub p2sh_segtwit: Option<String>,
Expand Down
60 changes: 60 additions & 0 deletions types/src/v17/wallet/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,12 +249,22 @@ pub enum GetTransactionError {
BlockHash(hex::HexToArrayError),
/// Conversion of the `txid` field failed.
Txid(hex::HexToArrayError),
/// Conversion of the `wtxid` field failed.
Wtxid(hex::HexToArrayError),
/// Conversion of the `wallet_conflicts` field failed.
WalletConflicts(hex::HexToArrayError),
/// Conversion of the `replaced_by_txid` field failed.
ReplacedByTxid(hex::HexToArrayError),
/// Conversion of the `replaces_txid` field failed.
ReplacesTxid(hex::HexToArrayError),
/// Conversion of the `mempool_conflicts` field failed.
MempoolConflicts(hex::HexToArrayError),
/// Conversion of the transaction `hex` field failed.
Tx(encode::FromHexError),
/// Conversion of the `details` field failed.
Details(GetTransactionDetailError),
/// Conversion of the `last_processed_block` field failed.
LastProcessedBlock(LastProcessedBlockError),
}

impl fmt::Display for GetTransactionError {
Expand All @@ -267,10 +277,19 @@ impl fmt::Display for GetTransactionError {
E::Fee(ref e) => write_err!(f, "conversion of the `fee` field failed"; e),
E::BlockHash(ref e) => write_err!(f, "conversion of the `block_hash` field failed"; e),
E::Txid(ref e) => write_err!(f, "conversion of the `txid` field failed"; e),
E::Wtxid(ref e) => write_err!(f, "conversion of the `wtxid` field failed"; e),
E::WalletConflicts(ref e) =>
write_err!(f, "conversion of the `wallet_conflicts` field failed"; e),
E::ReplacedByTxid(ref e) =>
write_err!(f, "conversion of the `replaced_by_txid` field failed"; e),
E::ReplacesTxid(ref e) =>
write_err!(f, "conversion of the `replaces_txid` field failed"; e),
E::MempoolConflicts(ref e) =>
write_err!(f, "conversion of the `mempool_conflicts` field failed"; e),
E::Tx(ref e) => write_err!(f, "conversion of the `hex` field failed"; e),
E::Details(ref e) => write_err!(f, "conversion of the `details` field failed"; e),
E::LastProcessedBlock(ref e) =>
write_err!(f, "conversion of the `last_processed_block` field failed"; e),
}
}
}
Expand All @@ -286,9 +305,14 @@ impl std::error::Error for GetTransactionError {
E::Fee(ref e) => Some(e),
E::BlockHash(ref e) => Some(e),
E::Txid(ref e) => Some(e),
E::Wtxid(ref e) => Some(e),
E::WalletConflicts(ref e) => Some(e),
E::ReplacedByTxid(ref e) => Some(e),
E::ReplacesTxid(ref e) => Some(e),
E::MempoolConflicts(ref e) => Some(e),
E::Tx(ref e) => Some(e),
E::Details(ref e) => Some(e),
E::LastProcessedBlock(ref e) => Some(e),
}
}
}
Expand Down Expand Up @@ -333,6 +357,42 @@ impl std::error::Error for GetTransactionDetailError {
}
}

/// Error when converting a `LastProcessedBlock` type into the model type.
#[derive(Debug)]
pub enum LastProcessedBlockError {
/// Conversion of the `hash` field failed.
Hash(hex::HexToArrayError),
/// Conversion of the `height` field failed.
Height(NumericError),
}

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

match *self {
Hash(ref e) => write_err!(f, "conversion of the `hash` field failed"; e),
Height(ref e) => write_err!(f, "conversion of the `height` field failed"; e),
}
}
}

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

match *self {
Hash(ref e) => Some(e),
Height(ref e) => Some(e),
}
}
}

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

/// Error when converting a `GetWalletInfo` type into the model type.
#[derive(Debug)]
pub enum GetWalletInfoError {
Expand Down
Loading