primitives: split WitnessScript and WitnessScriptBuf from script
What changed, and why it matters
This commit is a large internal refactoring in the rust-bitcoin library. It introduces a new dedicated type, WitnessScript, for Segwit v0 witness scripts and uses it wherever the code previously used the generic Script type for that purpose. The change is primarily about making the type system guide users to the correct Bitcoin concepts. The commit message explicitly notes one deliberate design oddity: for BIP143 P2SH-wrapped-segwit sighash calculations, the returned object is typed as WitnessScript even though it is technically a special-case template, not a real witness script. The author calls this a 'mild abuse' and documents it. There is no bug fix for a runtime vulnerability in the diff; the security relevance is that stronger typing may help prevent future API misuse.
Treat as a normal API refactor. Review downstream code that constructs WScriptHash or calls p2wsh/p2shwsh/sighash APIs to ensure it uses the new WitnessScript/WitnessScriptBuf types. No urgent security patch is indicated by the diff itself.
Security signals we found
Type-system hardening: dedicated WitnessScript type reduces accidental misuse of script kinds
Author-documented 'mild abuse' of WitnessScript for BIP143 scriptCode template
No runtime validation or cryptographic logic changes observed
No memory-safety, overflow, or deserialization fixes present
Evidence from the diff
The patch splits WitnessScript/WitnessScriptBuf out of the generic Script hierarchy in rust-bitcoin/primitives. It re-types fields named witness_script, WScriptHash constructors, Address::p2wsh/p2shwsh, WitnessProgram::p2wsh, PSBT input/output witness_script fields, and sighash APIs to take &WitnessScript instead of &Script. It also moves wscript_hash/to_p2wsh methods to a new WitnessScriptExt trait. A special-case remains: p2wpkh_script_code returns WitnessScriptBuf because the BIP143 scriptCode is used in place of a witness script for sighash computation; doccomments warn that it is not a real witness script. The change is type-level only and does not alter serialization, hashing, or consensus logic.
Changed components
primitives/src/script/mod.rsprimitives/src/script/tag.rsbitcoin/src/blockdata/script/borrowed.rsbitcoin/src/blockdata/script/mod.rsbitcoin/src/blockdata/script/witness_program.rsbitcoin/src/blockdata/witness.rsbitcoin/src/crypto/sighash.rsbitcoin/src/address/mod.rsbitcoin/src/psbt/map/input.rsbitcoin/src/psbt/map/output.rsInspect captured patch +137 / −86
diff --git a/bitcoin/examples/script.rs b/bitcoin/examples/script.rs
index 09ecef3a..5198b58c 100644
--- a/bitcoin/examples/script.rs
+++ b/bitcoin/examples/script.rs
@@ -10,7 +10,7 @@
use bitcoin::consensus::encode;
use bitcoin::key::WPubkeyHash;
use bitcoin::script::{self, GenericScriptBufExt as _, GenericScriptExt as _};
-use bitcoin::ScriptBuf;
+use bitcoin::{ScriptBuf, WitnessScriptBuf};
fn main() {
let pk = "b472a266d0bd89c13706a4132ccfb16f7c3b9fcb".parse::<WPubkeyHash>().unwrap();
@@ -18,13 +18,13 @@ fn main() {
// TL;DR Use `to_hex_string_prefixed` and `from_hex_prefixed`.
let script_code = script::p2wpkh_script_code(pk);
let hex = script_code.to_hex_string_prefixed();
- let decoded = ScriptBuf::from_hex_prefixed(&hex).unwrap();
+ let decoded = WitnessScriptBuf::from_hex_prefixed(&hex).unwrap();
assert_eq!(decoded, script_code);
// Or if you prefer: `to_hex_string_no_length_prefix` and `from_hex_no_length_prefix`.
let script_code = script::p2wpkh_script_code(pk);
let hex = script_code.to_hex_string_no_length_prefix();
- let decoded = ScriptBuf::from_hex_no_length_prefix(&hex).unwrap();
+ let decoded = WitnessScriptBuf::from_hex_no_length_prefix(&hex).unwrap();
assert_eq!(decoded, script_code);
// Writes the script as human-readable eg, OP_DUP OP_HASH160 OP_PUSHBYTES_20 ...
@@ -42,39 +42,42 @@ fn main() {
// And so does `from_hex_prefixed`.
assert!(ScriptBuf::from_hex_prefixed(&hex_lower_hex_trait).is_err());
// But we provide an explicit constructor that does not.
- assert_eq!(ScriptBuf::from_hex_no_length_prefix(&hex_lower_hex_trait).unwrap(), script_code);
+ assert_eq!(
+ WitnessScriptBuf::from_hex_no_length_prefix(&hex_lower_hex_trait).unwrap(),
+ script_code
+ );
// This is consensus encoding i.e., includes the length prefix.
let hex_inherent = script_code.to_hex_string_prefixed(); // Defined in `ScriptExt`.
println!("hex created using inherent `to_hex_string_prefixed`: {hex_inherent}");
// The inverse of `to_hex_string_prefixed` is `from_hex_string_prefixed`.
- let decoded = ScriptBuf::from_hex_prefixed(&hex_inherent).unwrap(); // Defined in `ScriptBufExt`.
+ let decoded = WitnessScriptBuf::from_hex_prefixed(&hex_inherent).unwrap(); // Defined in `ScriptBufExt`.
assert_eq!(decoded, script_code);
// We can also parse the output of `to_hex_string_prefixed` using `deserialize_hex`.
- let decoded = encode::deserialize_hex::<ScriptBuf>(&hex_inherent).unwrap();
+ let decoded = encode::deserialize_hex::<WitnessScriptBuf>(&hex_inherent).unwrap();
assert_eq!(decoded, script_code);
// We also support encode/decode using `consensus::encode` functions.
let encoded = encode::serialize_hex(&script_code);
println!("hex created using consensus::encode::serialize_hex: {encoded}");
- let decoded: ScriptBuf = encode::deserialize_hex(&encoded).unwrap();
+ let decoded: WitnessScriptBuf = encode::deserialize_hex(&encoded).unwrap();
assert_eq!(decoded, script_code);
// And we can mix these to calls because both include the length prefix.
let encoded = encode::serialize_hex(&script_code);
- let decoded = ScriptBuf::from_hex_prefixed(&encoded).unwrap();
+ let decoded = WitnessScriptBuf::from_hex_prefixed(&encoded).unwrap();
assert_eq!(decoded, script_code);
// Encode/decode using a byte vector.
let encoded = encode::serialize(&script_code);
assert_eq!(&encoded[1..], script_code.as_bytes()); // Shows that prefix is the first byte.
- let decoded: ScriptBuf = encode::deserialize(&encoded).unwrap();
+ let decoded: WitnessScriptBuf = encode::deserialize(&encoded).unwrap();
assert_eq!(decoded, script_code);
// to/from bytes excludes the prefix, these are not encoding/decoding functions so this is sane.
let bytes = script_code.to_bytes();
- let got = ScriptBuf::from_bytes(bytes);
+ let got = WitnessScriptBuf::from_bytes(bytes);
assert_eq!(got, script_code);
}
diff --git a/bitcoin/examples/sighash.rs b/bitcoin/examples/sighash.rs
index 52f2a681..e25f267c 100644
--- a/bitcoin/examples/sighash.rs
+++ b/bitcoin/examples/sighash.rs
@@ -1,7 +1,7 @@
use bitcoin::ext::*;
use bitcoin::{
- consensus, ecdsa, sighash, Amount, CompressedPublicKey, Script, ScriptPubKey, ScriptPubKeyBuf,
- Transaction,
+ consensus, ecdsa, sighash, Amount, CompressedPublicKey, ScriptPubKey, ScriptPubKeyBuf,
+ Transaction, WitnessScript,
};
use hex_lit::hex;
@@ -112,7 +112,7 @@ fn compute_sighash_p2wsh(raw_tx: &[u8], inp_idx: usize, amount: Amount) {
//last element is called witnessScript according to BIP-0141. It supersedes scriptPubKey.
let witness_script_bytes: &[u8] = witness.last().expect("out of bounds");
- let witness_script = Script::from_bytes(witness_script_bytes);
+ let witness_script = WitnessScript::from_bytes(witness_script_bytes);
let mut cache = sighash::SighashCache::new(&tx);
//in an M of N multisig, the witness elements from 1 (0-based) to M-2 are signatures (with sighash flags as the last byte)
diff --git a/bitcoin/src/address/mod.rs b/bitcoin/src/address/mod.rs
index c73a4363..af262d55 100644
--- a/bitcoin/src/address/mod.rs
+++ b/bitcoin/src/address/mod.rs
@@ -64,9 +64,10 @@ use crate::prelude::{String, ToOwned};
use crate::script::witness_program::WitnessProgram;
use crate::script::witness_version::WitnessVersion;
use crate::script::{
- self, GenericScript, GenericScriptExt as _, RedeemScriptSizeError, Script, ScriptExt as _,
- ScriptHash, ScriptHashableTag, ScriptPubKey, ScriptPubKeyBuf, ScriptPubKeyBufExt as _,
- ScriptPubKeyExt as _, WScriptHash, WitnessScriptSizeError,
+ self, GenericScript, GenericScriptExt as _, RedeemScriptSizeError, ScriptHash,
+ ScriptHashableTag, ScriptPubKey, ScriptPubKeyBuf, ScriptPubKeyBufExt as _,
+ ScriptPubKeyExt as _, WScriptHash, WitnessScript, WitnessScriptExt as _,
+ WitnessScriptSizeError,
};
use crate::taproot::TapNodeHash;
@@ -544,7 +545,7 @@ impl Address {
/// Constructs a new pay-to-witness-script-hash (P2WSH) [`Address`] from a witness script.
pub fn p2wsh(
- witness_script: &Script,
+ witness_script: &WitnessScript,
hrp: impl Into<KnownHrp>,
) -> Result<Address, WitnessScriptSizeError> {
let program = WitnessProgram::p2wsh(witness_script)?;
@@ -562,7 +563,7 @@ impl Address {
///
/// This is a SegWit address type that looks familiar (as p2sh) to legacy clients.
pub fn p2shwsh(
- witness_script: &Script,
+ witness_script: &WitnessScript,
network: impl Into<NetworkKind>,
) -> Result<Address, WitnessScriptSizeError> {
let hash = witness_script.wscript_hash()?;
@@ -1021,7 +1022,7 @@ mod tests {
use super::*;
use crate::network::Network::{Bitcoin, Testnet};
use crate::network::{params, TestnetVersion};
- use crate::script::{GenericScriptBufExt as _, RedeemScriptBuf, ScriptBuf};
+ use crate::script::{GenericScriptBufExt as _, RedeemScriptBuf, WitnessScriptBuf};
fn roundtrips(addr: &Address, network: Network) {
assert_eq!(
@@ -1127,7 +1128,7 @@ mod tests {
#[test]
fn p2wsh() {
// stolen from Bitcoin transaction 5df912fda4becb1c29e928bec8d64d93e9ba8efa9b5b405bd683c86fd2c65667
- let script = ScriptBuf::from_hex_no_length_prefix("52210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae").unwrap();
+ let script = WitnessScriptBuf::from_hex_no_length_prefix("52210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae").unwrap();
let addr = Address::p2wsh(&script, KnownHrp::Mainnet).expect("script is valid");
assert_eq!(
&addr.to_string(),
@@ -1152,7 +1153,7 @@ mod tests {
#[test]
fn p2shwsh() {
// stolen from Bitcoin transaction f9ee2be4df05041d0e0a35d7caa3157495ca4f93b233234c9967b6901dacf7a9
- let script = ScriptBuf::from_hex_no_length_prefix("522103e5529d8eaa3d559903adb2e881eb06c86ac2574ffa503c45f4e942e2a693b33e2102e5f10fcdcdbab211e0af6a481f5532536ec61a5fdbf7183770cf8680fe729d8152ae").unwrap();
+ let script = WitnessScriptBuf::from_hex_no_length_prefix("522103e5529d8eaa3d559903adb2e881eb06c86ac2574ffa503c45f4e942e2a693b33e2102e5f10fcdcdbab211e0af6a481f5532536ec61a5fdbf7183770cf8680fe729d8152ae").unwrap();
let addr = Address::p2shwsh(&script, NetworkKind::Main).expect("script is valid");
assert_eq!(&addr.to_string(), "36EqgNnsWW94SreZgBWc1ANC6wpFZwirHr");
assert_eq!(addr.address_type(), Some(AddressType::P2sh));
diff --git a/bitcoin/src/blockdata/script/borrowed.rs b/bitcoin/src/blockdata/script/borrowed.rs
index c70de812..d69d09bd 100644
--- a/bitcoin/src/blockdata/script/borrowed.rs
+++ b/bitcoin/src/blockdata/script/borrowed.rs
@@ -11,7 +11,7 @@ use super::witness_version::WitnessVersion;
use super::{
Builder, GenericScript, Instruction, InstructionIndices, Instructions, PushBytes, RedeemScript,
RedeemScriptSizeError, Script, ScriptHash, ScriptHashableTag, ScriptPubKey, ScriptSig,
- WScriptHash, WitnessScriptSizeError,
+ WScriptHash, WitnessScript, WitnessScriptSizeError,
};
use crate::consensus::{self, Encodable};
use crate::key::{PublicKey, UntweakedPublicKey, WPubkeyHash};
@@ -21,7 +21,7 @@ use crate::policy::{DUST_RELAY_TX_FEE, MAX_OP_RETURN_RELAY};
use crate::prelude::{sink, String, ToString};
use crate::script::{self, ScriptPubKeyBufExt as _};
use crate::taproot::{LeafVersion, TapLeafHash, TapNodeHash};
-use crate::{internal_macros, Amount, FeeRate, ScriptBuf, ScriptPubKeyBuf};
+use crate::{internal_macros, Amount, FeeRate, ScriptPubKeyBuf, WitnessScriptBuf};
internal_macros::define_extension_trait! {
/// Extension functionality for the [`Script`] type.
@@ -178,8 +178,12 @@ internal_macros::define_extension_trait! {
/// Returns the script code used for spending a P2WPKH output if this script is a script pubkey
/// for a P2WPKH output. The `scriptCode` is described in [BIP-0143].
///
+ /// While the type returned is [`WitnessScriptBuf`], this is **not** a witness script and
+ /// should not be used as one. It is a special template defined in BIP 143 which is used
+ /// in place of a witness script for purposes of sighash computation.
+ ///
/// [BIP-0143]: <https://github.com/bitcoin/bips/blob/99701f68a88ce33b2d0838eb84e115cef505b4c2/bip-0143.mediawiki>
- fn p2wpkh_script_code(&self) -> Option<ScriptBuf>
+ fn p2wpkh_script_code(&self) -> Option<WitnessScriptBuf>
where T: ScriptHashableTag
{
if self.is_p2wpkh() {
@@ -249,25 +253,30 @@ internal_macros::define_extension_trait! {
internal_macros::define_extension_trait! {
/// Extension functionality for the [`Script`] type.
- pub trait ScriptExt impl for Script {
+ pub trait WitnessScriptExt impl for WitnessScript {
/// Returns 256-bit hash of the script for P2WSH outputs.
#[inline]
fn wscript_hash(&self) -> Result<WScriptHash, WitnessScriptSizeError> {
WScriptHash::from_script(self)
}
+ /// Computes the P2WSH output corresponding to this witnessScript (aka the "witness redeem
+ /// script").
+ fn to_p2wsh(&self) -> Result<ScriptPubKeyBuf, WitnessScriptSizeError> {
+ self.wscript_hash().map(ScriptPubKeyBuf::new_p2wsh)
+ }
+ }
+}
+
+crate::internal_macros::define_extension_trait! {
+ /// Extension functionality for the [`Script`] type.
+ pub trait ScriptExt impl for Script {
/// Computes leaf hash of tapscript.
#[inline]
fn tapscript_leaf_hash(&self) -> TapLeafHash {
TapLeafHash::from_script(self, LeafVersion::TapScript)
}
- /// Computes the P2WSH output corresponding to this witnessScript (aka the "witness redeem
- /// script").
- fn to_p2wsh(&self) -> Result<ScriptPubKeyBuf, WitnessScriptSizeError> {
- self.wscript_hash().map(ScriptPubKeyBuf::new_p2wsh)
- }
-
/// Computes P2TR output with a given internal key and a single script spending path equal to
/// the current script, assuming that the script is a Tapscript.
fn to_p2tr<C: Verification, K: Into<UntweakedPublicKey>>(
diff --git a/bitcoin/src/blockdata/script/mod.rs b/bitcoin/src/blockdata/script/mod.rs
index aac2d030..18895d7e 100644
--- a/bitcoin/src/blockdata/script/mod.rs
+++ b/bitcoin/src/blockdata/script/mod.rs
@@ -74,7 +74,7 @@ use crate::OutPoint;
#[rustfmt::skip] // Keep public re-exports separate.
#[doc(inline)]
pub use self::{
- borrowed::{GenericScriptExt, ScriptExt, ScriptPubKeyExt, ScriptSigExt},
+ borrowed::{GenericScriptExt, ScriptExt, ScriptPubKeyExt, WitnessScriptExt, ScriptSigExt},
builder::Builder,
instruction::{Instruction, Instructions, InstructionIndices},
owned::{GenericScriptBufExt, ScriptPubKeyBufExt},
@@ -85,7 +85,7 @@ pub use primitives::script::{
GenericScript, GenericScriptBuf, RedeemScript, RedeemScriptBuf, RedeemScriptSizeError,
RedeemScriptTag, Script, ScriptBuf, ScriptHash, ScriptHashableTag, ScriptPubKey,
ScriptPubKeyBuf, ScriptPubKeyTag, ScriptSig, ScriptSigBuf, ScriptSigTag, Tag, WScriptHash,
- Whatever, WitnessScriptSizeError,
+ Whatever, WitnessScript, WitnessScriptBuf, WitnessScriptSizeError, WitnessScriptTag,
};
pub(crate) use self::borrowed::GenericScriptExtPriv;
@@ -97,8 +97,12 @@ impl_asref_push_bytes!(ScriptHash, WScriptHash);
///
/// The `scriptCode` is described in [BIP-0143].
///
+/// While the type returned is [`WitnessScriptBuf`], this is **not** a witness script and
+/// should not be used as one. It is a special template defined in BIP-0143 which is used
+/// in place of a witness script for purposes of sighash computation.
+///
/// [BIP-0143]: <https://github.com/bitcoin/bips/blob/99701f68a88ce33b2d0838eb84e115cef505b4c2/bip-0143.mediawiki>
-pub fn p2wpkh_script_code(wpkh: WPubkeyHash) -> ScriptBuf {
+pub fn p2wpkh_script_code(wpkh: WPubkeyHash) -> WitnessScriptBuf {
Builder::new()
.push_opcode(OP_DUP)
.push_opcode(OP_HASH160)
diff --git a/bitcoin/src/blockdata/script/tests.rs b/bitcoin/src/blockdata/script/tests.rs
index f7a8245e..5a7b382c 100644
--- a/bitcoin/src/blockdata/script/tests.rs
+++ b/bitcoin/src/blockdata/script/tests.rs
@@ -246,7 +246,7 @@ fn script_generators() {
assert!(p2sh.is_p2sh());
assert_eq!(script.to_p2sh().unwrap(), p2sh);
- let script = Script::builder().push_opcode(OP_NUMEQUAL).push_verify().into_script();
+ let script = WitnessScript::builder().push_opcode(OP_NUMEQUAL).push_verify().into_script();
let wscript_hash = script.wscript_hash().expect("script is less than 10,000 bytes");
let p2wsh = ScriptPubKeyBuf::new_p2wsh(wscript_hash);
assert!(p2wsh.is_p2wsh());
@@ -402,7 +402,7 @@ fn script_hashes() {
script.script_hash().unwrap().to_string(),
"8292bcfbef1884f73c813dfe9c82fd7e814291ea"
);
- let script = ScriptBuf::from_hex_no_length_prefix("410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac").unwrap();
+ let script = WitnessScriptBuf::from_hex_no_length_prefix("410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac").unwrap();
assert_eq!(
script.wscript_hash().unwrap().to_string(),
"3e1525eb183ad4f9b3c5fa3175bdca2a52e947b135bbb90383bf9f6408e2c324"
@@ -624,7 +624,7 @@ fn script_p2pk() {
fn p2sh_p2wsh_conversion() {
// Test vectors taken from Core tests/data/script_tests.json
// bare p2wsh
- let witness_script = ScriptBuf::from_hex_no_length_prefix("410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac").unwrap();
+ let witness_script = WitnessScriptBuf::from_hex_no_length_prefix("410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac").unwrap();
let expected_without = ScriptPubKeyBuf::from_hex_no_length_prefix(
"0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64",
)
@@ -642,7 +642,7 @@ fn p2sh_p2wsh_conversion() {
assert_eq!(redeem_script.to_p2sh().unwrap(), expected_p2shout);
// p2sh-p2wsh
- let witness_script = ScriptBuf::from_hex_no_length_prefix("410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac").unwrap();
+ let witness_script = WitnessScriptBuf::from_hex_no_length_prefix("410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac").unwrap();
let expected_without = ScriptPubKeyBuf::from_hex_no_length_prefix(
"0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64",
)
diff --git a/bitcoin/src/blockdata/script/witness_program.rs b/bitcoin/src/blockdata/script/witness_program.rs
index 05c5c93c..e43e12c3 100644
--- a/bitcoin/src/blockdata/script/witness_program.rs
+++ b/bitcoin/src/blockdata/script/witness_program.rs
@@ -14,9 +14,9 @@ use internals::array_vec::ArrayVec;
use secp256k1::{Secp256k1, Verification};
use super::witness_version::WitnessVersion;
-use super::{PushBytes, Script, WScriptHash, WitnessScriptSizeError};
+use super::{PushBytes, WScriptHash, WitnessScript, WitnessScriptSizeError};
use crate::crypto::key::{CompressedPublicKey, TapTweak, TweakedPublicKey, UntweakedPublicKey};
-use crate::script::ScriptExt as _;
+use crate::script::WitnessScriptExt as _;
use crate::taproot::TapNodeHash;
/// The minimum byte size of a segregated witness program.
@@ -82,7 +82,7 @@ impl WitnessProgram {
}
/// Constructs a new [`WitnessProgram`] from `script` for a P2WSH output.
- pub fn p2wsh(script: &Script) -> Result<Self, WitnessScriptSizeError> {
+ pub fn p2wsh(script: &WitnessScript) -> Result<Self, WitnessScriptSizeError> {
script.wscript_hash().map(Self::p2wsh_from_hash)
}
diff --git a/bitcoin/src/blockdata/witness.rs b/bitcoin/src/blockdata/witness.rs
index ad820601..cb5d4dcf 100644
--- a/bitcoin/src/blockdata/witness.rs
+++ b/bitcoin/src/blockdata/witness.rs
@@ -15,7 +15,7 @@ use crate::prelude::Vec;
#[cfg(doc)]
use crate::script::ScriptExt as _;
use crate::taproot::{self, ControlBlock, LeafScript, TaprootMerkleBranch, TAPROOT_ANNEX_PREFIX};
-use crate::{internal_macros, Script};
+use crate::{internal_macros, Script, WitnessScript};
type BorrowedControlBlock<'a> = ControlBlock<&'a TaprootMerkleBranch, &'a SerializedXOnlyPublicKey>;
@@ -210,8 +210,7 @@ internal_macros::define_extension_trait! {
/// witness script: it may be a Taproot control block, annex, or some other kind
/// of object. If you are not certain whether the output being spent is Segwit v0,
/// use [`crate::script::GenericScriptExt::is_p2wsh`] on the output's script.
- fn witness_script(&self) -> Option<&Script> { self.last().map(Script::from_bytes) }
-
+ fn witness_script(&self) -> Option<&WitnessScript> { self.last().map(WitnessScript::from_bytes) }
}
}
diff --git a/bitcoin/src/crypto/key.rs b/bitcoin/src/crypto/key.rs
index 9a706347..8427a800 100644
--- a/bitcoin/src/crypto/key.rs
+++ b/bitcoin/src/crypto/key.rs
@@ -21,7 +21,7 @@ use crate::crypto::ecdsa;
use crate::internal_macros::impl_asref_push_bytes;
use crate::network::NetworkKind;
use crate::prelude::{DisplayHex, String, Vec};
-use crate::script::{self, ScriptBuf};
+use crate::script::{self, WitnessScriptBuf};
use crate::taproot::{TapNodeHash, TapTweakHash};
#[rustfmt::skip] // Keep public re-exports separate.
@@ -185,7 +185,11 @@ impl PublicKey {
}
/// Returns the script code used to spend a P2WPKH input.
- pub fn p2wpkh_script_code(&self) -> Result<ScriptBuf, UncompressedPublicKeyError> {
+ ///
+ /// While the type returned is [`WitnessScriptBuf`], this is **not** a witness script and
+ /// should not be used as one. It is a special template defined in BIP 143 which is used
+ /// in place of a witness script for purposes of sighash computation.
+ pub fn p2wpkh_script_code(&self) -> Result<WitnessScriptBuf, UncompressedPublicKeyError> {
let key = CompressedPublicKey::try_from(*self)?;
Ok(key.p2wpkh_script_code())
}
@@ -404,7 +408,11 @@ impl CompressedPublicKey {
}
/// Returns the script code used to spend a P2WPKH input.
- pub fn p2wpkh_script_code(&self) -> ScriptBuf {
+ ///
+ /// While the type returned is [`WitnessScriptBuf`], this is **not** a witness script and
+ /// should not be used as one. It is a special template defined in BIP 143 which is used
+ /// in place of a witness script for purposes of sighash computation.
+ pub fn p2wpkh_script_code(&self) -> WitnessScriptBuf {
script::p2wpkh_script_code(self.wpubkey_hash())
}
diff --git a/bitcoin/src/crypto/sighash.rs b/bitcoin/src/crypto/sighash.rs
index 53de5e26..088fe085 100644
--- a/bitcoin/src/crypto/sighash.rs
+++ b/bitcoin/src/crypto/sighash.rs
@@ -26,7 +26,9 @@ use crate::script::{GenericScriptExt as _, ScriptHashableTag};
use crate::taproot::{LeafVersion, TapLeafHash, TapLeafTag, TAPROOT_ANNEX_PREFIX};
use crate::transaction::TransactionExt as _;
use crate::witness::Witness;
-use crate::{transaction, Amount, Script, ScriptPubKey, Sequence, Transaction, TxOut};
+use crate::{
+ transaction, Amount, Script, ScriptPubKey, Sequence, Transaction, TxOut, WitnessScript,
+};
/// Used for signature hash for invalid use of SIGHASH_SINGLE.
#[rustfmt::skip]
@@ -816,7 +818,7 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
&mut self,
writer: &mut W,
input_index: usize,
- script_code: &Script,
+ script_code: &WitnessScript,
value: Amount,
sighash_type: EcdsaSighashType,
) -> Result<(), SigningDataError<transaction::InputsIndexError>> {
@@ -899,7 +901,7 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
pub fn p2wsh_signature_hash(
&mut self,
input_index: usize,
- witness_script: &Script,
+ witness_script: &WitnessScript,
value: Amount,
sighash_type: EcdsaSighashType,
) -> Result<SegwitV0Sighash, transaction::InputsIndexError> {
@@ -1537,7 +1539,9 @@ mod tests {
use super::*;
use crate::consensus::deserialize;
use crate::locktime::absolute;
- use crate::script::{GenericScriptBufExt as _, ScriptBuf, ScriptPubKey, ScriptPubKeyBuf};
+ use crate::script::{
+ GenericScriptBufExt as _, ScriptBuf, ScriptPubKey, ScriptPubKeyBuf, WitnessScriptBuf,
+ };
use crate::TxIn;
extern crate serde_json;
@@ -2170,7 +2174,7 @@ mod tests {
// Note, if you are looking at the test vectors in BIP-0143 and wondering why there is a `cf`
// prepended to all the script_code hex it is the length byte, it gets added when we consensus
// encode a script.
- fn bip143_p2wsh_nested_in_p2sh_data() -> (Transaction, ScriptBuf, Amount) {
+ fn bip143_p2wsh_nested_in_p2sh_data() -> (Transaction, WitnessScriptBuf, Amount) {
let tx = deserialize::<Transaction>(&hex!(
"010000000136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000000\
ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f\
@@ -2178,7 +2182,7 @@ mod tests {
))
.unwrap();
- let witness_script = ScriptBuf::from_hex_no_length_prefix(
+ let witness_script = WitnessScriptBuf::from_hex_no_length_prefix(
"56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28\
bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b\
9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58\
diff --git a/bitcoin/src/lib.rs b/bitcoin/src/lib.rs
index e732ff2d..66755b2b 100644
--- a/bitcoin/src/lib.rs
+++ b/bitcoin/src/lib.rs
@@ -114,7 +114,7 @@ pub mod ext {
pub use crate::{
block::{BlockUncheckedExt as _, BlockCheckedExt as _, HeaderExt as _},
pow::CompactTargetExt as _,
- script::{GenericScriptExt as _, GenericScriptBufExt as _, ScriptExt as _, ScriptPubKeyExt as _, ScriptPubKeyBufExt as _, ScriptSigExt as _},
+ script::{GenericScriptExt as _, GenericScriptBufExt as _, ScriptExt as _, ScriptPubKeyExt as _, ScriptPubKeyBufExt as _, WitnessScriptExt as _, ScriptSigExt as _},
transaction::{TxidExt as _, WtxidExt as _, OutPointExt as _, TxInExt as _, TxOutExt as _, TransactionExt as _},
witness::WitnessExt as _,
};
@@ -154,7 +154,7 @@ pub use primitives::{
pow::CompactTarget, // No `pow` module outside of `primitives`.
script::{
RedeemScript, RedeemScriptBuf, Script, ScriptBuf, ScriptPubKey, ScriptPubKeyBuf, ScriptSig,
- ScriptSigBuf,
+ ScriptSigBuf, WitnessScript, WitnessScriptBuf,
},
sequence::{self, Sequence}, // No `sequence` module outside of `primitives`.
transaction::{OutPoint, Transaction, TxIn, TxOut, Txid, Version as TransactionVersion, Wtxid},
diff --git a/bitcoin/src/psbt/map/input.rs b/bitcoin/src/psbt/map/input.rs
index 16dfa131..7675bd78 100644
--- a/bitcoin/src/psbt/map/input.rs
+++ b/bitcoin/src/psbt/map/input.rs
@@ -12,7 +12,7 @@ use crate::prelude::{btree_map, BTreeMap, Borrow, Box, ToOwned, Vec};
use crate::psbt::map::Map;
use crate::psbt::serialize::Deserialize;
use crate::psbt::{error, raw, Error};
-use crate::script::{RedeemScriptBuf, ScriptBuf, ScriptSigBuf};
+use crate::script::{RedeemScriptBuf, ScriptBuf, ScriptSigBuf, WitnessScriptBuf};
use crate::sighash::{
EcdsaSighashType, InvalidSighashTypeError, NonStandardSighashTypeError, SighashTypeParseError,
TapSighashType,
@@ -85,7 +85,7 @@ pub struct Input {
/// The redeem script for this input.
pub redeem_script: Option<RedeemScriptBuf>,
/// The witness script for this input.
- pub witness_script: Option<ScriptBuf>,
+ pub witness_script: Option<WitnessScriptBuf>,
/// A map from public keys needed to sign this input to their corresponding
/// master key fingerprints and derivation paths.
pub bip32_derivation: BTreeMap<secp256k1::PublicKey, KeySource>,
@@ -288,7 +288,7 @@ impl Input {
}
PSBT_IN_WITNESS_SCRIPT => {
impl_psbt_insert_pair! {
- self.witness_script <= <raw_key: _>|<raw_value: ScriptBuf>
+ self.witness_script <= <raw_key: _>|<raw_value: WitnessScriptBuf>
}
}
PSBT_IN_BIP32_DERIVATION => {
diff --git a/bitcoin/src/psbt/map/output.rs b/bitcoin/src/psbt/map/output.rs
index 13e5543c..ad72f242 100644
--- a/bitcoin/src/psbt/map/output.rs
+++ b/bitcoin/src/psbt/map/output.rs
@@ -5,7 +5,7 @@ use crate::crypto::key::XOnlyPublicKey;
use crate::prelude::{btree_map, BTreeMap, Vec};
use crate::psbt::map::Map;
use crate::psbt::{raw, Error};
-use crate::script::{RedeemScriptBuf, ScriptBuf};
+use crate::script::{RedeemScriptBuf, WitnessScriptBuf};
use crate::taproot::{TapLeafHash, TapTree};
/// Type: Redeem ScriptBuf PSBT_OUT_REDEEM_SCRIPT = 0x00
@@ -32,7 +32,7 @@ pub struct Output {
/// The redeem script for this output.
pub redeem_script: Option<RedeemScriptBuf>,
/// The witness script for this output.
- pub witness_script: Option<ScriptBuf>,
+ pub witness_script: Option<WitnessScriptBuf>,
/// A map from public keys needed to spend this output to their
/// corresponding master key fingerprints and derivation paths.
pub bip32_derivation: BTreeMap<secp256k1::PublicKey, KeySource>,
@@ -62,7 +62,7 @@ impl Output {
}
PSBT_OUT_WITNESS_SCRIPT => {
impl_psbt_insert_pair! {
- self.witness_script <= <raw_key: _>|<raw_value: ScriptBuf>
+ self.witness_script <= <raw_key: _>|<raw_value: WitnessScriptBuf>
}
}
PSBT_OUT_BIP32_DERIVATION => {
diff --git a/bitcoin/src/psbt/mod.rs b/bitcoin/src/psbt/mod.rs
index 8956f6ec..a3641a6c 100644
--- a/bitcoin/src/psbt/mod.rs
+++ b/bitcoin/src/psbt/mod.rs
@@ -1344,7 +1344,7 @@ mod tests {
use crate::network::NetworkKind;
use crate::psbt::serialize::{Deserialize, Serialize};
use crate::script::{
- GenericScriptBufExt as _, RedeemScriptBuf, ScriptBuf, ScriptPubKeyBuf, ScriptSigBuf,
+ GenericScriptBufExt as _, RedeemScriptBuf, ScriptPubKeyBuf, ScriptSigBuf, WitnessScriptBuf,
};
use crate::transaction::{self, OutPoint, TxIn};
use crate::witness::Witness;
@@ -1521,7 +1521,7 @@ mod tests {
.unwrap(),
),
witness_script: Some(
- ScriptBuf::from_hex_no_length_prefix(
+ WitnessScriptBuf::from_hex_no_length_prefix(
"a9143545e6e33b832c47050f24d3eeb93c9c03948bc787",
)
.unwrap(),
diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs
index 3e9523d0..7499c347 100644
--- a/primitives/src/lib.rs
+++ b/primitives/src/lib.rs
@@ -76,7 +76,7 @@ pub use self::{
},
script::{
RedeemScript, RedeemScriptBuf, Script, ScriptBuf, ScriptPubKey, ScriptPubKeyBuf, ScriptSig,
- ScriptSigBuf,
+ ScriptSigBuf, WitnessScript, WitnessScriptBuf,
},
transaction::{Transaction, TxIn, TxOut},
witness::Witness,
diff --git a/primitives/src/script/mod.rs b/primitives/src/script/mod.rs
index 11ffab1a..5c87560e 100644
--- a/primitives/src/script/mod.rs
+++ b/primitives/src/script/mod.rs
@@ -30,7 +30,7 @@ use crate::prelude::{Borrow, BorrowMut, Box, Cow, ToOwned, Vec};
pub use self::{
borrowed::GenericScript,
owned::GenericScriptBuf,
- tag::{Tag, RedeemScriptTag, ScriptPubKeyTag, ScriptSigTag, Whatever},
+ tag::{Tag, RedeemScriptTag, ScriptPubKeyTag, ScriptSigTag, Whatever, WitnessScriptTag},
};
/// Placeholder doc (will be replaced in later commit)
@@ -57,6 +57,12 @@ pub type ScriptPubKeyBuf = GenericScriptBuf<ScriptPubKeyTag>;
/// A script signature (scriptSig).
pub type ScriptSigBuf = GenericScriptBuf<ScriptSigTag>;
+/// A Segwit v0 witness script.
+pub type WitnessScriptBuf = GenericScriptBuf<WitnessScriptTag>;
+
+/// A reference to a Segwit v0 witness script.
+pub type WitnessScript = GenericScript<WitnessScriptTag>;
+
/// The maximum allowed redeem script size for a P2SH output.
pub const MAX_REDEEM_SCRIPT_SIZE: usize = 520;
/// The maximum allowed redeem script size of the witness script.
@@ -152,7 +158,7 @@ impl WScriptHash {
///
/// ref: [BIP-141](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki)
#[inline]
- pub fn from_script(witness_script: &Script) -> Result<Self, WitnessScriptSizeError> {
+ pub fn from_script(witness_script: &WitnessScript) -> Result<Self, WitnessScriptSizeError> {
if witness_script.len() > MAX_WITNESS_SCRIPT_SIZE {
return Err(WitnessScriptSizeError { size: witness_script.len() });
}
@@ -168,7 +174,7 @@ impl WScriptHash {
///
/// ref: [BIP-141](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki)
#[inline]
- pub fn from_script_unchecked(script: &Script) -> Self {
+ pub fn from_script_unchecked(script: &WitnessScript) -> Self {
WScriptHash(sha256::Hash::hash(script.as_bytes()))
}
}
@@ -200,29 +206,29 @@ impl<T: ScriptHashableTag> TryFrom<&GenericScript<T>> for ScriptHash {
}
}
-impl TryFrom<ScriptBuf> for WScriptHash {
+impl TryFrom<WitnessScriptBuf> for WScriptHash {
type Error = WitnessScriptSizeError;
#[inline]
- fn try_from(witness_script: ScriptBuf) -> Result<Self, Self::Error> {
+ fn try_from(witness_script: WitnessScriptBuf) -> Result<Self, Self::Error> {
Self::from_script(&witness_script)
}
}
-impl TryFrom<&ScriptBuf> for WScriptHash {
+impl TryFrom<&WitnessScriptBuf> for WScriptHash {
type Error = WitnessScriptSizeError;
#[inline]
- fn try_from(witness_script: &ScriptBuf) -> Result<Self, Self::Error> {
+ fn try_from(witness_script: &WitnessScriptBuf) -> Result<Self, Self::Error> {
Self::from_script(witness_script)
}
}
-impl TryFrom<&Script> for WScriptHash {
+impl TryFrom<&WitnessScript> for WScriptHash {
type Error = WitnessScriptSizeError;
#[inline]
- fn try_from(witness_script: &Script) -> Result<Self, Self::Error> {
+ fn try_from(witness_script: &WitnessScript) -> Result<Self, Self::Error> {
Self::from_script(witness_script)
}
}
@@ -767,23 +773,23 @@ mod tests {
#[test]
fn script_hash_from_script_unchecked() {
- let script = Script::from_bytes(&[0x51; 521]);
+ let script = WitnessScript::from_bytes(&[0x51; 521]);
let hash = ScriptHash::from_script_unchecked(script);
assert_eq!(hash, ScriptHash(hash160::Hash::hash(script.as_bytes())));
}
#[test]
fn wscript_hash_from_script() {
- let script = Script::from_bytes(&[0x51; 10_000]);
+ let script = WitnessScript::from_bytes(&[0x51; 10_000]);
assert!(WScriptHash::from_script(script).is_ok());
- let script = Script::from_bytes(&[0x51; 10_001]);
+ let script = WitnessScript::from_bytes(&[0x51; 10_001]);
assert!(WScriptHash::from_script(script).is_err());
}
#[test]
fn wscript_hash_from_script_unchecked() {
- let script = Script::from_bytes(&[0x51; 10_001]);
+ let script = WitnessScript::from_bytes(&[0x51; 10_001]);
let hash = WScriptHash::from_script_unchecked(script);
assert_eq!(hash, WScriptHash(sha256::Hash::hash(script.as_bytes())));
}
@@ -817,28 +823,28 @@ mod tests {
#[test]
fn try_from_scriptbuf_for_wscript_hash() {
- let script = ScriptBuf::from(vec![0x51; 10_000]);
+ let script = WitnessScriptBuf::from(vec![0x51; 10_000]);
assert!(WScriptHash::try_from(script).is_ok());
- let script = ScriptBuf::from(vec![0x51; 10_001]);
+ let script = WitnessScriptBuf::from(vec![0x51; 10_001]);
assert!(WScriptHash::try_from(script).is_err());
}
#[test]
fn try_from_scriptbuf_ref_for_wscript_hash() {
- let script = ScriptBuf::from(vec![0x51; 10_000]);
+ let script = WitnessScriptBuf::from(vec![0x51; 10_000]);
assert!(WScriptHash::try_from(&script).is_ok());
- let script = ScriptBuf::from(vec![0x51; 10_001]);
+ let script = WitnessScriptBuf::from(vec![0x51; 10_001]);
assert!(WScriptHash::try_from(&script).is_err());
}
#[test]
fn try_from_script_for_wscript_hash() {
- let script = Script::from_bytes(&[0x51; 10_000]);
+ let script = WitnessScript::from_bytes(&[0x51; 10_000]);
assert!(WScriptHash::try_from(script).is_ok());
- let script = Script::from_bytes(&[0x51; 10_001]);
+ let script = WitnessScript::from_bytes(&[0x51; 10_001]);
assert!(WScriptHash::try_from(script).is_err());
}
@@ -944,7 +950,7 @@ mod tests {
#[test]
fn witness_script_size_error() {
- let script = ScriptBuf::from(vec![0x51; 10_001]);
+ let script = WitnessScriptBuf::from(vec![0x51; 10_001]);
let result = WScriptHash::try_from(script);
let err = result.unwrap_err();
diff --git a/primitives/src/script/tag.rs b/primitives/src/script/tag.rs
index 82b71fc6..fa70f174 100644
--- a/primitives/src/script/tag.rs
+++ b/primitives/src/script/tag.rs
@@ -28,3 +28,8 @@ impl Tag for ScriptSigTag {}
#[derive(Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub enum ScriptPubKeyTag {}
impl Tag for ScriptPubKeyTag {}
+
+/// A Segwit v0 witness script.
+#[derive(Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
+pub enum WitnessScriptTag {}
+impl Tag for WitnessScriptTag {}
diff --git a/primitives/tests/api.rs b/primitives/tests/api.rs
index c572b8f6..bbb6eef0 100644
--- a/primitives/tests/api.rs
+++ b/primitives/tests/api.rs
@@ -19,7 +19,7 @@ use bitcoin_primitives::script::{self, ScriptHash, WScriptHash};
use bitcoin_primitives::{
absolute, block, merkle_tree, pow, relative, transaction, witness, OutPoint, RedeemScript,
RedeemScriptBuf, Script, ScriptBuf, ScriptPubKey, ScriptPubKeyBuf, ScriptSig, ScriptSigBuf,
- Sequence, Transaction, TxIn, TxOut, Txid, Witness, Wtxid,
+ Sequence, Transaction, TxIn, TxOut, Txid, Witness, WitnessScript, WitnessScriptBuf, Wtxid,
};
use hashes::sha256t;
@@ -48,12 +48,14 @@ struct Structs<'a> {
j1: &'a RedeemScript,
j2: &'a ScriptPubKey,
j3: &'a ScriptSig,
+ j5: &'a WitnessScript,
k: ScriptHash,
l: WScriptHash,
m: ScriptBuf,
m1: RedeemScriptBuf,
m2: ScriptPubKeyBuf,
m3: ScriptSigBuf,
+ m5: WitnessScriptBuf,
n: Sequence,
o: Transaction,
p: TxIn,
@@ -70,6 +72,7 @@ static SCRIPT: ScriptBuf = ScriptBuf::new();
static REDEEM_SCRIPT: RedeemScriptBuf = RedeemScriptBuf::new();
static SCRIPT_SIG: ScriptSigBuf = ScriptSigBuf::new();
static SCRIPT_PUB_KEY: ScriptPubKeyBuf = ScriptPubKeyBuf::new();
+static WITNESS_SCRIPT: WitnessScriptBuf = WitnessScriptBuf::new();
static BYTES: [u8; 32] = [0x00; 32];
/// Public structs that derive common traits.
@@ -92,6 +95,7 @@ struct CommonTraits {
m1: RedeemScriptBuf,
m2: ScriptPubKeyBuf,
m3: ScriptSigBuf,
+ m5: WitnessScriptBuf,
n: Sequence,
o: Transaction,
p: TxIn,
@@ -123,6 +127,7 @@ struct Clone<'a> {
m1: RedeemScriptBuf,
m2: ScriptPubKeyBuf,
m3: ScriptSigBuf,
+ m5: WitnessScriptBuf,
n: Sequence,
o: Transaction,
p: TxIn,
@@ -155,6 +160,7 @@ struct Ord {
m1: RedeemScriptBuf,
m2: ScriptPubKeyBuf,
m3: ScriptSigBuf,
+ m5: WitnessScriptBuf,
n: Sequence,
o: Transaction,
p: TxIn,
@@ -175,10 +181,12 @@ struct Default {
b1: &'static RedeemScript,
b2: &'static ScriptPubKey,
b3: &'static ScriptSig,
+ b5: &'static WitnessScript,
c: ScriptBuf,
c1: RedeemScriptBuf,
c2: ScriptPubKeyBuf,
c3: ScriptSigBuf,
+ c5: WitnessScriptBuf,
d: Sequence,
e: Witness,
}
@@ -295,12 +303,14 @@ fn api_all_non_error_types_have_non_empty_debug() {
REDEEM_SCRIPT.as_script();
SCRIPT_SIG.as_script();
SCRIPT_PUB_KEY.as_script();
+ WITNESS_SCRIPT.as_script();
ScriptHash::from_script(&REDEEM_SCRIPT).unwrap();
- WScriptHash::from_script(&SCRIPT).unwrap();
+ WScriptHash::from_script(&WITNESS_SCRIPT).unwrap();
SCRIPT.clone();
REDEEM_SCRIPT.clone();
SCRIPT_SIG.clone();
SCRIPT_PUB_KEY.clone();
+ WITNESS_SCRIPT.clone();
Sequence::arbitrary(&mut u).unwrap();
Transaction::arbitrary(&mut u).unwrap();
TxIn::arbitrary(&mut u).unwrap();
@@ -339,10 +349,12 @@ fn regression_default() {
b1: RedeemScript::from_bytes(&[]),
b2: ScriptPubKey::from_bytes(&[]),
b3: ScriptSig::from_bytes(&[]),
+ b5: WitnessScript::from_bytes(&[]),
c: ScriptBuf::from_bytes(Vec::new()),
c1: RedeemScriptBuf::from_bytes(Vec::new()),
c2: ScriptPubKeyBuf::from_bytes(Vec::new()),
c3: ScriptSigBuf::from_bytes(Vec::new()),
+ c5: WitnessScriptBuf::from_bytes(Vec::new()),
d: Sequence::MAX,
e: Witness::new(),
};
Why this scored 19/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.