Skip to content

Commit f255db4

Browse files
committed
types: Clean up the ScriptPubkey type
The `ScriptPubkey` type is a type that is returned by Core in various places. It seems like the Core devs put a fair bit of effort into it (probably because of this) and when the type changed in v22 it was changed in a way that was completely backwards compatible. I failed to fully understand this when first adding the type. With this patch applied there is now only one `ScriptPubkey` type (in `libr.s`) and also we add a model type. The `ScriptPubkey` type is unusual in that its fields can be used to create `TxOut` if tx value is known - which for example in `GetTxOut` it is. So here we also remove the v22 `GetTxOut` type since it only existed because of the perceived difference in `ScriptPubkey` which no longer exists. Fix: rust-bitcoin#116
1 parent 7b2b017 commit f255db4

File tree

13 files changed

+113
-224
lines changed

13 files changed

+113
-224
lines changed

types/src/lib.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub mod model;
3535

3636
use core::fmt;
3737

38+
use bitcoin::address::{self, Address, NetworkUnchecked};
3839
use bitcoin::amount::ParseAmountError;
3940
use bitcoin::hex::{self, FromHex as _};
4041
use bitcoin::{Amount, FeeRate, ScriptBuf, Witness};
@@ -172,25 +173,43 @@ pub fn compact_size_decode(slice: &mut &[u8]) -> u64 {
172173
}
173174

174175
/// Data returned by Core for a script pubkey.
176+
///
177+
/// This is used by methods in the blockchain section and in the raw transaction section (i.e raw
178+
/// transaction and psbt methods). The shape changed in Core v22 but the new shape is fully
179+
/// backwards compatible so we only provide it not a v17 specific type. The `mtype::ScriptPubkey`
180+
/// mirrors this design (but with concrete `rust-bitcoin` types).
175181
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
176182
pub struct ScriptPubkey {
177183
/// Script assembly.
178184
pub asm: String,
179185
/// Script hex.
180186
pub hex: String,
187+
/// Number of required signatures - deprecated in Core v22.
188+
///
189+
/// Only returned before in versions prior to 22 or for version 22 onwards if
190+
/// config option `-deprecatedrpc=addresses` is passed.
181191
#[serde(rename = "reqSigs")]
182192
pub req_sigs: Option<i64>,
183193
/// The type, eg pubkeyhash.
184194
#[serde(rename = "type")]
185195
pub type_: String,
186-
/// Array of bitcoin address.
196+
/// Bitcoin address (only if a well-defined address exists).
197+
pub address: Option<String>,
198+
/// Array of bitcoin addresses - deprecated in Core v22.
199+
///
200+
/// Only returned before in versions prior to 22 or for version 22 onwards if
201+
/// config option `-deprecatedrpc=addresses` is passed.
187202
pub addresses: Option<Vec<String>>,
188203
}
189204

190205
impl ScriptPubkey {
191206
fn script_buf(&self) -> Result<ScriptBuf, hex::HexToBytesError> {
192207
ScriptBuf::from_hex(&self.hex)
193208
}
209+
210+
fn address(&self) -> Option<Result<Address<NetworkUnchecked>, address::ParseError>> {
211+
self.address.as_ref().map(|addr| addr.parse::<Address<_>>())
212+
}
194213
}
195214

196215
/// Data returned by Core for a script signature.

types/src/model/blockchain.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,9 @@ pub struct GetTxOut {
455455
/// The returned `TxOut` (strongly typed).
456456
pub tx_out: TxOut,
457457
/// Address that `tx_out` spends to.
458-
pub addresses: Vec<Address<NetworkUnchecked>>,
458+
///
459+
/// Only if a well-defined address exists.
460+
pub address: Option<Address<NetworkUnchecked>>,
459461
/// Coinbase or not.
460462
pub coinbase: bool,
461463
}

types/src/v17/blockchain/error.rs

+13-9
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,9 @@ impl From<ParseAmountError> for GetMempoolInfoError {
473473
}
474474

475475
/// Error when converting a `GetTxOut` type into the model type.
476+
///
477+
/// Note that variants in this type are not named in the usual fashion. The `ScriptBuf` and
478+
/// `Address` variants are named after the functions on [`crate::ScriptPubkey`].
476479
#[derive(Debug)]
477480
pub enum GetTxOutError {
478481
/// Conversion of numeric type to expected type failed.
@@ -481,10 +484,10 @@ pub enum GetTxOutError {
481484
BestBlock(hex::HexToArrayError),
482485
/// Conversion of the transaction `value` field failed.
483486
Value(amount::ParseAmountError),
484-
/// Conversion of the transaction `script_pubkey` field failed.
485-
ScriptPubkey(hex::HexToBytesError),
486-
/// Conversion of the transaction `addresses` field failed.
487-
Addresses(address::ParseError),
487+
/// Conversion of the `ScriptPubkey` hex to a `ScriptBuf` failed.
488+
ScriptBuf(hex::HexToBytesError),
489+
/// Conversion of the `ScriptPubkey` `address` field failed.
490+
Address(address::ParseError),
488491
}
489492

490493
impl fmt::Display for GetTxOutError {
@@ -495,9 +498,10 @@ impl fmt::Display for GetTxOutError {
495498
Numeric(ref e) => write_err!(f, "numeric"; e),
496499
BestBlock(ref e) => write_err!(f, "conversion of the `beast_block` field failed"; e),
497500
Value(ref e) => write_err!(f, "conversion of the `value` field failed"; e),
498-
ScriptPubkey(ref e) =>
499-
write_err!(f, "conversion of the `script_pubkey` field failed"; e),
500-
Addresses(ref e) => write_err!(f, "conversion of the `addresses` field failed"; e),
501+
ScriptBuf(ref e) =>
502+
write_err!(f, "conversion of the `ScriptPubkey` hex to a `ScriptBuf` failed"; e),
503+
Address(ref e) =>
504+
write_err!(f, "conversion of the `ScriptPubkey` `address` field failed"; e),
501505
}
502506
}
503507
}
@@ -511,8 +515,8 @@ impl std::error::Error for GetTxOutError {
511515
Numeric(ref e) => Some(e),
512516
BestBlock(ref e) => Some(e),
513517
Value(ref e) => Some(e),
514-
ScriptPubkey(ref e) => Some(e),
515-
Addresses(ref e) => Some(e),
518+
ScriptBuf(ref e) => Some(e),
519+
Address(ref e) => Some(e),
516520
}
517521
}
518522
}

types/src/v17/blockchain/into.rs

+3-10
Original file line numberDiff line numberDiff line change
@@ -490,23 +490,16 @@ impl GetTxOut {
490490
let best_block = self.best_block.parse::<BlockHash>().map_err(E::BestBlock)?;
491491
let tx_out = TxOut {
492492
value: Amount::from_btc(self.value).map_err(E::Value)?,
493-
script_pubkey: ScriptBuf::from_hex(&self.script_pubkey.hex).map_err(E::ScriptPubkey)?,
493+
script_pubkey: self.script_pubkey.script_buf().map_err(E::ScriptBuf)?,
494494
};
495495

496-
let addresses = match self.script_pubkey.addresses {
497-
Some(addresses) => addresses
498-
.into_iter()
499-
.map(|address| address.parse::<Address<_>>())
500-
.collect::<Result<Vec<_>, _>>()
501-
.map_err(E::Addresses)?,
502-
None => vec![],
503-
};
496+
let address = self.script_pubkey.address().transpose().map_err(E::Address)?;
504497

505498
Ok(model::GetTxOut {
506499
best_block,
507500
confirmations: self.confirmations,
508501
tx_out,
509-
addresses,
502+
address,
510503
coinbase: self.coinbase,
511504
})
512505
}

types/src/v17/blockchain/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ mod into;
1010
use alloc::collections::BTreeMap;
1111

1212
use bitcoin::hex::FromHex;
13-
use bitcoin::{Address, Amount, FeeRate, Network, ScriptBuf, TxMerkleNode, TxOut, Wtxid};
13+
use bitcoin::{Amount, FeeRate, Network, TxMerkleNode, TxOut, Wtxid};
1414
use serde::{Deserialize, Serialize};
1515

1616
// TODO: Remove wildcard, use explicit types.

types/src/v22/blockchain.rs

-130
This file was deleted.

types/src/v22/mod.rs

+15-17
Original file line numberDiff line numberDiff line change
@@ -243,14 +243,10 @@
243243
//! </details>
244244
245245
// JSON-RPC types by API section.
246-
mod blockchain;
247246
mod control;
248247

249248
#[doc(inline)]
250-
pub use self::{
251-
blockchain::{GetTxOut, GetTxOutError, ScriptPubkey},
252-
control::Logging,
253-
};
249+
pub use self::control::Logging;
254250
#[doc(inline)]
255251
pub use crate::{
256252
v17::{
@@ -271,18 +267,19 @@ pub use crate::{
271267
GetPeerInfo, GetRawChangeAddress, GetRawMempool, GetRawMempoolVerbose, GetRawTransaction,
272268
GetRawTransactionVerbose, GetRawTransactionVerboseError, GetReceivedByAddress,
273269
GetTransaction, GetTransactionDetail, GetTransactionDetailError, GetTransactionError,
274-
GetTxOutSetInfo, GetTxOutSetInfoError, GetUnconfirmedBalance, GetWalletInfo,
275-
GetWalletInfoError, GetZmqNotifications, ListAddressGroupings, ListAddressGroupingsError,
276-
ListAddressGroupingsItem, ListBanned, ListLabels, ListLockUnspent, ListLockUnspentItem,
277-
ListLockUnspentItemError, ListReceivedByAddress, ListReceivedByAddressError,
278-
ListReceivedByAddressItem, ListSinceBlock, ListSinceBlockError, ListSinceBlockTransaction,
279-
ListSinceBlockTransactionError, ListTransactions, ListTransactionsItem,
280-
ListTransactionsItemError, ListUnspent, ListUnspentItem, ListUnspentItemError, ListWallets,
281-
LoadWallet, Locked, PeerInfo, PruneBlockchain, RawTransactionError, RawTransactionInput,
282-
RawTransactionOutput, RescanBlockchain, SendMany, SendRawTransaction, SendToAddress,
283-
SignMessage, SignRawTransaction, SignRawTransactionError, SoftforkReject,
284-
TestMempoolAccept, TransactionCategory, UploadTarget, VerifyChain, VerifyTxOutProof,
285-
WalletCreateFundedPsbt, WalletCreateFundedPsbtError, WalletProcessPsbt, WitnessUtxo,
270+
GetTxOut, GetTxOutError, GetTxOutSetInfo, GetTxOutSetInfoError, GetUnconfirmedBalance,
271+
GetWalletInfo, GetWalletInfoError, GetZmqNotifications, ListAddressGroupings,
272+
ListAddressGroupingsError, ListAddressGroupingsItem, ListBanned, ListLabels,
273+
ListLockUnspent, ListLockUnspentItem, ListLockUnspentItemError, ListReceivedByAddress,
274+
ListReceivedByAddressError, ListReceivedByAddressItem, ListSinceBlock, ListSinceBlockError,
275+
ListSinceBlockTransaction, ListSinceBlockTransactionError, ListTransactions,
276+
ListTransactionsItem, ListTransactionsItemError, ListUnspent, ListUnspentItem,
277+
ListUnspentItemError, ListWallets, LoadWallet, Locked, PeerInfo, PruneBlockchain,
278+
RawTransactionError, RawTransactionInput, RawTransactionOutput, RescanBlockchain, SendMany,
279+
SendRawTransaction, SendToAddress, SignMessage, SignRawTransaction,
280+
SignRawTransactionError, SoftforkReject, TestMempoolAccept, TransactionCategory,
281+
UploadTarget, VerifyChain, VerifyTxOutProof, WalletCreateFundedPsbt,
282+
WalletCreateFundedPsbtError, WalletProcessPsbt, WitnessUtxo,
286283
},
287284
v18::{
288285
ActiveCommand, AnalyzePsbt, AnalyzePsbtError, AnalyzePsbtInput, AnalyzePsbtInputMissing,
@@ -298,4 +295,5 @@ pub use crate::{
298295
SoftforkType,
299296
},
300297
v21::UnloadWallet,
298+
ScriptPubkey,
301299
};

types/src/v23/mod.rs

+14-13
Original file line numberDiff line numberDiff line change
@@ -266,18 +266,19 @@ pub use crate::{
266266
GetPeerInfo, GetRawChangeAddress, GetRawMempool, GetRawMempoolVerbose, GetRawTransaction,
267267
GetRawTransactionVerbose, GetRawTransactionVerboseError, GetReceivedByAddress,
268268
GetTransaction, GetTransactionDetail, GetTransactionDetailError, GetTransactionError,
269-
GetTxOutSetInfo, GetTxOutSetInfoError, GetUnconfirmedBalance, GetWalletInfo,
270-
GetWalletInfoError, GetZmqNotifications, ListAddressGroupings, ListAddressGroupingsError,
271-
ListAddressGroupingsItem, ListBanned, ListLabels, ListLockUnspent, ListLockUnspentItem,
272-
ListLockUnspentItemError, ListReceivedByAddress, ListReceivedByAddressError,
273-
ListReceivedByAddressItem, ListSinceBlock, ListSinceBlockError, ListSinceBlockTransaction,
274-
ListSinceBlockTransactionError, ListTransactions, ListTransactionsItem,
275-
ListTransactionsItemError, ListUnspent, ListUnspentItem, ListUnspentItemError, ListWallets,
276-
LoadWallet, Locked, PeerInfo, PruneBlockchain, RawTransactionError, RawTransactionInput,
277-
RawTransactionOutput, RescanBlockchain, SendMany, SendRawTransaction, SendToAddress,
278-
SignMessage, SignRawTransaction, SignRawTransactionError, SoftforkReject,
279-
TestMempoolAccept, TransactionCategory, UploadTarget, VerifyChain, VerifyTxOutProof,
280-
WalletCreateFundedPsbt, WalletCreateFundedPsbtError, WalletProcessPsbt, WitnessUtxo,
269+
GetTxOut, GetTxOutError, GetTxOutSetInfo, GetTxOutSetInfoError, GetUnconfirmedBalance,
270+
GetWalletInfo, GetWalletInfoError, GetZmqNotifications, ListAddressGroupings,
271+
ListAddressGroupingsError, ListAddressGroupingsItem, ListBanned, ListLabels,
272+
ListLockUnspent, ListLockUnspentItem, ListLockUnspentItemError, ListReceivedByAddress,
273+
ListReceivedByAddressError, ListReceivedByAddressItem, ListSinceBlock, ListSinceBlockError,
274+
ListSinceBlockTransaction, ListSinceBlockTransactionError, ListTransactions,
275+
ListTransactionsItem, ListTransactionsItemError, ListUnspent, ListUnspentItem,
276+
ListUnspentItemError, ListWallets, LoadWallet, Locked, PeerInfo, PruneBlockchain,
277+
RawTransactionError, RawTransactionInput, RawTransactionOutput, RescanBlockchain, SendMany,
278+
SendRawTransaction, SendToAddress, SignMessage, SignRawTransaction,
279+
SignRawTransactionError, SoftforkReject, TestMempoolAccept, TransactionCategory,
280+
UploadTarget, VerifyChain, VerifyTxOutProof, WalletCreateFundedPsbt,
281+
WalletCreateFundedPsbtError, WalletProcessPsbt, WitnessUtxo,
281282
},
282283
v18::{
283284
ActiveCommand, AnalyzePsbt, AnalyzePsbtError, AnalyzePsbtInput, AnalyzePsbtInputMissing,
@@ -293,5 +294,5 @@ pub use crate::{
293294
SoftforkType,
294295
},
295296
v21::UnloadWallet,
296-
v22::{GetTxOut, GetTxOutError, Logging, ScriptPubkey},
297+
v22::{Logging, ScriptPubkey},
297298
};

0 commit comments

Comments
 (0)