Skip to content

Commit 448feed

Browse files
author
+Sharon
committed
Add DecodeScriptSegwit struct and support in DecodeScript conversion
- Add `DecodeScriptSegwit` struct to model the `segwit` field returned by the `decodescript` RPC. - Update `DecodeScript` to include an optional `segwit` field.
1 parent c633a03 commit 448feed

File tree

7 files changed

+101
-5
lines changed

7 files changed

+101
-5
lines changed

types/src/model/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ pub use self::{
4141
raw_transactions::{
4242
AnalyzePsbt, AnalyzePsbtInput, AnalyzePsbtInputMissing, CombinePsbt, CombineRawTransaction,
4343
ConvertToPsbt, CreatePsbt, CreateRawTransaction, DecodePsbt, DecodeRawTransaction,
44-
DecodeScript, DescriptorProcessPsbt, FinalizePsbt, FundRawTransaction, GetRawTransaction,
44+
DecodeScript,DecodeScriptSegwit, DescriptorProcessPsbt, FinalizePsbt, FundRawTransaction, GetRawTransaction,
4545
GetRawTransactionVerbose, JoinPsbts, MempoolAcceptance, SendRawTransaction, SignFail,
4646
SignRawTransaction, SubmitPackage, SubmitPackageTxResult, SubmitPackageTxResultFees,
4747
TestMempoolAccept, UtxoUpdatePsbt,

types/src/model/raw_transactions.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,30 @@ pub struct DecodeScript {
116116
pub addresses: Vec<Address<NetworkUnchecked>>,
117117
/// Address of P2SH script wrapping this redeem script (not returned if the script is already a P2SH).
118118
pub p2sh: Option<Address<NetworkUnchecked>>,
119+
/// Segwit data (see `DecodeScriptSegwit` for explanation).
120+
pub segwit: Option<DecodeScriptSegwit>,
119121
/// Address of the P2SH script wrapping this witness redeem script
120122
pub p2sh_segwit: Option<String>,
123+
124+
}
125+
/// Models the `segwit` field returned by the `decodescript` RPC.
126+
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
127+
#[serde(deny_unknown_fields)]
128+
pub struct DecodeScriptSegwit {
129+
/// The witness program.
130+
pub asm: String,
131+
/// Hex-encoded script.
132+
pub hex: String,
133+
/// The output type.
134+
pub type_: String,
135+
/// Bitcoin address (only if a well-defined address exists).
136+
pub address: Option<Address<NetworkUnchecked>>,
137+
/// The required signatures.
138+
pub required_signatures: Option<u64>,
139+
/// List of bitcoin addresses.
140+
pub addresses: Vec<Address<NetworkUnchecked>>,
141+
/// Address of the P2SH script wrapping this witness redeem script.
142+
pub p2sh_segwit: Option<String>,
121143
}
122144

123145
/// Models the result of JSON-RPC method `descriptorprocesspsbt`.

types/src/v17/raw_transactions/into.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ impl DecodeScript {
310310
addresses,
311311
p2sh,
312312
p2sh_segwit: self.p2sh_segwit,
313+
segwit: None,
313314
})
314315
}
315316
}

types/src/v22/raw_transactions/error.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,20 @@ pub enum DecodeScriptError {
1717
Addresses(address::ParseError),
1818
/// Conversion of the transaction `p2sh` field failed.
1919
P2sh(address::ParseError),
20+
/// Conversion of the transaction `segwit` field failed.
21+
Segwit(DecodeScriptSegwitError),
2022
}
23+
#[derive(Debug)]
24+
pub enum DecodeScriptSegwitError {
25+
/// Conversion of the `hex` field failed.
26+
InvalidField(&'static str),
27+
/// Conversion of the transaction `address` field failed.
28+
Address(address::ParseError),
29+
30+
/// Conversion of the transaction `addresses` field failed.
31+
Addresses(address::ParseError),
32+
}
33+
2134

2235
impl fmt::Display for DecodeScriptError {
2336
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -28,6 +41,7 @@ impl fmt::Display for DecodeScriptError {
2841
E::Address(ref e) => write_err!(f, "conversion of the `address` field failed"; e),
2942
E::Addresses(ref e) => write_err!(f, "conversion of the `addresses` field failed"; e),
3043
E::P2sh(ref e) => write_err!(f, "conversion of the `p2sh` field failed"; e),
44+
E::Segwit(ref e) => write_err!(f, "conversion of the `segwit` field failed"; e),
3145
}
3246
}
3347
}
@@ -42,6 +56,26 @@ impl std::error::Error for DecodeScriptError {
4256
E::Address(ref e) => Some(e),
4357
E::Addresses(ref e) => Some(e),
4458
E::P2sh(ref e) => Some(e),
59+
E::Segwit(ref e) => Some(e),
4560
}
4661
}
4762
}
63+
64+
impl fmt::Display for DecodeScriptSegwitError {
65+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
66+
match self {
67+
DecodeScriptSegwitError::InvalidField(name) => {
68+
write!(f, "invalid or missing field `{}` in segwit", name)
69+
}
70+
DecodeScriptSegwitError::Address(err) => {
71+
write!(f, "conversion of the `address` field in segwit failed: {}", err)
72+
}
73+
DecodeScriptSegwitError::Addresses(err) => {
74+
write!(f, "conversion of the `addresses` field in segwit failed: {}", err)
75+
}
76+
}
77+
}
78+
}
79+
80+
#[cfg(feature = "std")]
81+
impl std::error::Error for DecodeScriptSegwitError {}

types/src/v22/raw_transactions/into.rs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
use bitcoin::Address;
44

5-
use super::{DecodeScript, DecodeScriptError};
5+
use super::{DecodeScript, DecodeScriptError, DecodeScriptSegwit, DecodeScriptSegwitError};
6+
67
use crate::model;
78

89
impl DecodeScript {
@@ -23,7 +24,7 @@ impl DecodeScript {
2324
None => vec![],
2425
};
2526
let p2sh = self.p2sh.map(|s| s.parse::<Address<_>>()).transpose().map_err(E::P2sh)?;
26-
27+
2728
Ok(model::DecodeScript {
2829
script_pubkey: None,
2930
type_: self.type_,
@@ -33,6 +34,42 @@ impl DecodeScript {
3334
addresses,
3435
p2sh,
3536
p2sh_segwit: self.p2sh_segwit,
37+
segwit: self.segwit.map(|s| s.into_model()).transpose().map_err(E::Segwit)?,
38+
})
39+
}
40+
}
41+
42+
impl DecodeScriptSegwit {
43+
/// Converts version specific type to a version nonspecific, more strongly typed type.
44+
pub fn into_model(self) -> Result<model::DecodeScriptSegwit, DecodeScriptSegwitError> {
45+
use DecodeScriptSegwitError as E;
46+
47+
let address = match self.address {
48+
Some(addr) => Some(addr.parse::<Address<_>>().map_err(E::Address)?),
49+
None => None,
50+
};
51+
// Convert `Option<Vec<String>>` to `Vec<Address<NetworkUnchecked>>`
52+
let addresses = match self.addresses {
53+
Some(addrs) => addrs
54+
.into_iter()
55+
.map(|s| s.parse::<Address<_>>())
56+
.collect::<Result<_, _>>()
57+
.map_err(E::Addresses)?,
58+
None => vec![],
59+
};
60+
61+
let required_signatures = self.required_signatures;
62+
let p2sh_segwit = self.p2sh_segwit;
63+
64+
Ok(model::DecodeScriptSegwit {
65+
asm: self.asm,
66+
hex: self.hex,
67+
type_: self.type_,
68+
address,
69+
required_signatures,
70+
addresses,
71+
p2sh_segwit,
3672
})
73+
3774
}
3875
}

types/src/v22/raw_transactions/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ mod into;
99

1010
use serde::{Deserialize, Serialize};
1111

12-
pub use self::error::DecodeScriptError;
12+
pub use self::error::{DecodeScriptError,DecodeScriptSegwitError};
1313

1414
/// Result of JSON-RPC method `decodescript`.
1515
///
@@ -64,5 +64,5 @@ pub struct DecodeScriptSegwit {
6464
pub addresses: Option<Vec<String>>,
6565
/// Address of P2SH script wrapping this redeem script (not returned if the script is already a P2SH).
6666
#[serde(rename = "p2sh-segwit")]
67-
pub p2sh_segtwit: Option<String>,
67+
pub p2sh_segwit: Option<String>,
6868
}

types/src/v23/raw_transactions/into.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,9 @@ impl DecodeScript {
334334
required_signatures: self.required_signatures,
335335
addresses,
336336
p2sh,
337+
segwit: self.segwit,
337338
p2sh_segwit: self.p2sh_segwit,
339+
338340
})
339341
}
340342
}

0 commit comments

Comments
 (0)