Skip to content

Commit a9d3723

Browse files
author
+Sharon
committed
Add DecodeScriptSegwit into_model to v17 and refactor error handling
- Add `into_model` implementation for `DecodeScriptSegwit` in v17. - Return `segwit` in v17, as it is present in RPC output despite not being documented until v19. - Add `DecodeScriptSegwitError` enum in v17, as `address` is sometimes `None` and error handling is needed. - Remove duplicate `DecodeScriptSegwitError` from v23 and reuse the one from v22 via import. - Move `descriptor` field in `DecodeScriptSegwit` model struct to match the field order in Bitcoin Core's `decodescript` RPC response.
1 parent 88db7fe commit a9d3723

File tree

9 files changed

+86
-52
lines changed

9 files changed

+86
-52
lines changed

types/src/model/raw_transactions.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,6 @@ pub struct DecodeScriptSegwit {
129129
pub asm: String,
130130
/// The raw output script bytes, hex-encoded.
131131
pub hex: ScriptBuf,
132-
/// Inferred descriptor for the script. v23 and later only.
133-
pub descriptor: Option<String>,
134132
/// The output type (e.g. nonstandard, anchor, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_scripthash, witness_v0_keyhash, witness_v1_taproot, witness_unknown).
135133
pub type_: String,
136134
/// Bitcoin address (only if a well-defined address exists)v22 and later only.
@@ -139,6 +137,8 @@ pub struct DecodeScriptSegwit {
139137
pub required_signatures: Option<u64>,
140138
/// List of bitcoin addresses.
141139
pub addresses: Vec<Address<NetworkUnchecked>>,
140+
/// Inferred descriptor for the script. v23 and later only.
141+
pub descriptor: Option<String>,
142142
/// Address of the P2SH script wrapping this witness redeem script.
143143
pub p2sh_segwit: Option<Address<NetworkUnchecked>>,
144144
}

types/src/v17/raw_transactions/error.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ pub enum DecodeScriptError {
178178
Addresses(address::ParseError),
179179
/// Conversion of the transaction `p2sh` field failed.
180180
P2sh(address::ParseError),
181+
/// Conversion of the transaction `segwit` field failed.
182+
Segwit(DecodeScriptSegwitError),
181183
}
182184

183185
impl fmt::Display for DecodeScriptError {
@@ -188,6 +190,7 @@ impl fmt::Display for DecodeScriptError {
188190
E::Hex(ref e) => write_err!(f, "conversion of the `hex` field failed"; e),
189191
E::Addresses(ref e) => write_err!(f, "conversion of the `addresses` field failed"; e),
190192
E::P2sh(ref e) => write_err!(f, "conversion of the `p2sh` field failed"; e),
193+
E::Segwit(ref e) => write_err!(f, "conversion of the `segwit` field failed"; e),
191194
}
192195
}
193196
}
@@ -201,6 +204,34 @@ impl std::error::Error for DecodeScriptError {
201204
E::Hex(ref e) => Some(e),
202205
E::Addresses(ref e) => Some(e),
203206
E::P2sh(ref e) => Some(e),
207+
E::Segwit(ref e) => Some(e),
208+
}
209+
}
210+
}
211+
212+
/// Error when converting a `DecodeScriptSegwit` type into the model type.
213+
#[derive(Debug)]
214+
pub enum DecodeScriptSegwitError {
215+
/// Conversion of the transaction `addresses` field failed.
216+
Addresses(address::ParseError),
217+
}
218+
219+
impl fmt::Display for DecodeScriptSegwitError {
220+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
221+
use DecodeScriptSegwitError as E;
222+
match *self {
223+
E::Addresses(ref e) =>
224+
write_err!(f, "conversion of the `addresses` field in `segwit` failed"; e),
225+
}
226+
}
227+
}
228+
229+
#[cfg(feature = "std")]
230+
impl std::error::Error for DecodeScriptSegwitError {
231+
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
232+
use DecodeScriptSegwitError as E;
233+
match *self {
234+
E::Addresses(ref e) => Some(e),
204235
}
205236
}
206237
}

types/src/v17/raw_transactions/into.rs

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ use super::{
1414
FinalizePsbt, FinalizePsbtError, FundRawTransaction, FundRawTransactionError,
1515
GetRawTransaction, GetRawTransactionVerbose, GetRawTransactionVerboseError, MempoolAcceptance,
1616
PsbtInput, PsbtInputError, PsbtOutput, PsbtOutputError, SendRawTransaction, SignFail,
17-
SignFailError, SignRawTransaction, SignRawTransactionError, TestMempoolAccept,
17+
SignFailError, SignRawTransaction, SignRawTransactionError, TestMempoolAccept,DecodeScriptSegwit,
18+
DecodeScriptSegwitError,
1819
};
1920
use crate::model;
2021
use crate::psbt::RawTransactionError;
@@ -310,7 +311,38 @@ impl DecodeScript {
310311
addresses,
311312
p2sh,
312313
p2sh_segwit: self.p2sh_segwit,
313-
segwit: None,
314+
segwit: self.segwit.map(|s| s.into_model()).transpose().map_err(E::Segwit)?,
315+
})
316+
}
317+
}
318+
319+
impl DecodeScriptSegwit {
320+
/// Converts version specific type to a version nonspecific, more strongly typed type.
321+
pub fn into_model(self) -> Result<model::DecodeScriptSegwit, DecodeScriptSegwitError> {
322+
use DecodeScriptSegwitError as E;
323+
324+
// Convert `Option<Vec<String>>` to `Vec<Address<NetworkUnchecked>>`
325+
let addresses = match self.addresses {
326+
Some(addrs) => addrs
327+
.into_iter()
328+
.map(|s| s.parse::<Address<_>>())
329+
.collect::<Result<_, _>>()
330+
.map_err(E::Addresses)?,
331+
None => vec![],
332+
};
333+
334+
let required_signatures = self.required_signatures;
335+
let p2sh_segwit = self.p2sh_segwit;
336+
337+
Ok(model::DecodeScriptSegwit {
338+
asm: self.asm,
339+
hex: self.hex,
340+
descriptor: None,
341+
address:None,
342+
type_: self.type_,
343+
required_signatures,
344+
addresses,
345+
p2sh_segwit,
314346
})
315347
}
316348
}

types/src/v17/raw_transactions/mod.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use crate::ScriptSig;
1919
pub use self::error::{
2020
DecodePsbtError, DecodeScriptError, FundRawTransactionError, GetRawTransactionVerboseError,
2121
PsbtInputError, PsbtOutputError, SignFailError, SignRawTransactionError, FinalizePsbtError,
22+
DecodeScriptSegwitError,
2223
};
2324
// Re-export types that appear in the public API of this module.
2425
pub use crate::psbt::{
@@ -215,11 +216,11 @@ pub struct DecodeRawTransaction(pub RawTransaction);
215216
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
216217
#[serde(deny_unknown_fields)]
217218
pub struct DecodeScript {
218-
/// Disassembly of the script.
219+
/// Script public key.
219220
pub asm: String,
220-
/// The raw output script bytes, hex-encoded.
221+
/// Hex encoded public key.
221222
pub hex: Option<String>,
222-
/// The type of the output script (e.g. witness_v0_keyhash or witness_v0_scripthash).
223+
/// The output type.
223224
#[serde(rename = "type")]
224225
pub type_: String,
225226
/// The required signatures.
@@ -255,7 +256,7 @@ pub struct DecodeScriptSegwit {
255256
pub addresses: Option<Vec<String>>,
256257
/// Address of the P2SH script wrapping this witness redeem script.
257258
#[serde(rename = "p2sh-segwit")]
258-
pub p2sh_segtwit: Option<Address<NetworkUnchecked>>,
259+
pub p2sh_segwit: Option<Address<NetworkUnchecked>>,
259260
}
260261

261262
/// Result of JSON-RPC method `finalizepsbt`.

types/src/v22/raw_transactions/error.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ pub enum DecodeScriptError {
1515
Address(address::ParseError),
1616
/// Conversion of the transaction `addresses` field failed.
1717
Addresses(address::ParseError),
18-
/// Conversion of the transaction `segwit` field failed.
19-
Segwit(DecodeScriptSegwitError),
2018
/// Conversion of the transaction `p2sh` field failed.
2119
P2sh(address::ParseError),
20+
/// Conversion of the transaction `segwit` field failed.
21+
Segwit(DecodeScriptSegwitError),
2222
}
2323

2424
impl fmt::Display for DecodeScriptError {
@@ -29,8 +29,8 @@ impl fmt::Display for DecodeScriptError {
2929
E::Hex(ref e) => write_err!(f, "conversion of the `hex` field failed"; e),
3030
E::Address(ref e) => write_err!(f, "conversion of the `address` field failed"; e),
3131
E::Addresses(ref e) => write_err!(f, "conversion of the `addresses` field failed"; e),
32-
E::Segwit(ref e) => write_err!(f, "conversion of the `segwit` field failed"; e),
3332
E::P2sh(ref e) => write_err!(f, "conversion of the `p2sh` field failed"; e),
33+
E::Segwit(ref e) => write_err!(f, "conversion of the `segwit` field failed"; e),
3434
}
3535
}
3636
}
@@ -44,8 +44,8 @@ impl std::error::Error for DecodeScriptError {
4444
E::Hex(ref e) => Some(e),
4545
E::Address(ref e) => Some(e),
4646
E::Addresses(ref e) => Some(e),
47-
E::Segwit(ref e) => Some(e),
4847
E::P2sh(ref e) => Some(e),
48+
E::Segwit(ref e) => Some(e),
4949
}
5050
}
5151
}

types/src/v22/raw_transactions/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ pub use self::error::{DecodeScriptError, DecodeScriptSegwitError};
2525
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
2626
#[serde(deny_unknown_fields)]
2727
pub struct DecodeScript {
28-
/// Disassembly of the script.
28+
/// Script public key.
2929
pub asm: String,
30-
/// The output type (e.g. nonstandard, anchor, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_scripthash, witness_v0_keyhash, witness_v1_taproot, witness_unknown).
30+
/// The output type
3131
#[serde(rename = "type")]
3232
pub type_: String,
3333
/// Bitcoin address (only if a well-defined address exists). v22 and later only.

types/src/v23/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ pub use self::{
250250
network::GetPeerInfo,
251251
raw_transactions::{
252252
DecodePsbt, DecodePsbtError, DecodeScript, DecodeScriptError, DecodeScriptSegwit,
253-
DecodeScriptSegwitError, GlobalXpub, Proprietary, PsbtInput, PsbtOutput,
253+
GlobalXpub, Proprietary, PsbtInput, PsbtOutput,
254254
},
255255
util::CreateMultisig,
256256
wallet::{GetTransaction, GetTransactionError},
@@ -310,5 +310,5 @@ pub use crate::{
310310
ImportDescriptors, ImportDescriptorsResult, PsbtBumpFee, PsbtBumpFeeError, Send, SendError,
311311
UnloadWallet, UpgradeWallet,
312312
},
313-
v22::{Banned, GetMempoolInfo, ListBanned, ScriptPubkey},
313+
v22::{Banned, GetMempoolInfo, ListBanned, ScriptPubkey,},
314314
};

types/src/v23/raw_transactions/error.rs

Lines changed: 2 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use bitcoin::{address, bip32, hex, sighash};
66

77
use crate::error::write_err;
88
use crate::v17::{Bip32DerivError, PartialSignatureError, RawTransactionError, WitnessUtxoError};
9+
use crate::v22::DecodeScriptSegwitError;
910

1011
/// Error when converting a `DecodePsbt` type into the model type.
1112
#[derive(Debug)]
@@ -298,36 +299,4 @@ impl std::error::Error for DecodeScriptError {
298299
E::P2sh(ref e) => Some(e),
299300
}
300301
}
301-
}
302-
303-
/// Error when converting a `DecodeScriptSegwit` type into the model type.
304-
#[derive(Debug)]
305-
pub enum DecodeScriptSegwitError {
306-
/// Conversion of the transaction `address` field failed.
307-
Address(address::ParseError),
308-
/// Conversion of the transaction `addresses` field failed.
309-
Addresses(address::ParseError),
310-
}
311-
312-
impl fmt::Display for DecodeScriptSegwitError {
313-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
314-
use DecodeScriptSegwitError as E;
315-
match *self {
316-
E::Address(ref e) =>
317-
write_err!(f, "conversion of the `address` field in `segwit` failed"; e),
318-
E::Addresses(ref e) =>
319-
write_err!(f, "conversion of the `addresses` field in `segwit` failed"; e),
320-
}
321-
}
322-
}
323-
324-
#[cfg(feature = "std")]
325-
impl std::error::Error for DecodeScriptSegwitError {
326-
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
327-
use DecodeScriptSegwitError as E;
328-
match *self {
329-
E::Address(ref e) => Some(e),
330-
E::Addresses(ref e) => Some(e),
331-
}
332-
}
333-
}
302+
}

types/src/v23/raw_transactions/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ use serde::{Deserialize, Serialize};
1616
use crate::ScriptSig;
1717

1818
#[rustfmt::skip] // Keep public re-exports separate.
19-
pub use self::error::{DecodePsbtError, DecodeScriptError, GlobalXpubError, PsbtInputError, PsbtOutputError,DecodeScriptSegwitError};
19+
pub use self::error::{DecodePsbtError, DecodeScriptError, GlobalXpubError, PsbtInputError, PsbtOutputError};
2020
// Re-export types that appear in the public API of this module.
2121
pub use crate::psbt::{Bip32Deriv, PsbtScript, RawTransaction, WitnessUtxo};
22+
pub use crate::v22::DecodeScriptSegwitError;
2223

2324
/// Result of JSON-RPC method `decodepsbt`.
2425
///
@@ -141,12 +142,12 @@ pub struct PsbtOutput {
141142
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
142143
#[serde(deny_unknown_fields)]
143144
pub struct DecodeScript {
144-
/// Disassembly of the script.
145+
/// Script public key.
145146
pub asm: String,
146147
/// Inferred descriptor for the script. v23 and later only.
147148
#[serde(rename = "desc")]
148149
pub descriptor: Option<String>,
149-
/// The output type (e.g. nonstandard, anchor, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_scripthash, witness_v0_keyhash, witness_v1_taproot, witness_unknown).
150+
/// The output type
150151
#[serde(rename = "type")]
151152
pub type_: String,
152153
/// Bitcoin address (only if a well-defined address exists). v22 and later only.

0 commit comments

Comments
 (0)