primitives: split ScriptPubKey and ScriptPubKeyBuf from generic 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, ScriptPubKey, for the scripts that appear in transaction outputs, and updates many examples and internal functions to use it. The change is described by the author as a step toward preventing confusion between scriptPubKeys and redeemScripts. It is not a security patch for an exploitable bug; it is a type-system cleanup that may reduce future misuse but does not by itself fix any vulnerability.
Treat as a normal library refactoring commit. Review downstream code for API breakage due to the new ScriptPubKey/ScriptPubKeyBuf types. No urgent security action is required based on this commit alone.
Security signals we found
Large API refactor introducing ScriptPubKey/ScriptPubKeyBuf types
Author notes confusion between scriptPubKeys and redeemScripts as motivation
Several methods temporarily loosened to GenericScript<T> with intent to tighten later
No new bounds checks, no validation changes, no consensus rule changes
No mention of CVE, advisory, bug bounty, or external report
Evidence from the diff
The commit splits ScriptPubKey and ScriptPubKeyBuf out of the existing generic Script/ScriptBuf types using a new ScriptPubKeyTag marker. It updates TxOut::script_pubkey, Address::script_pubkey, sighash helpers, block filter APIs, and many examples/tests to use the new types. Several methods that conceptually belong only on ScriptPubKey/RedeemScript are temporarily implemented for all generic script types and will be tightened later. The commit message explicitly frames this as a type-safety improvement, not a security fix.
Changed components
primitives/src/script/mod.rsprimitives/src/script/tag.rsprimitives/src/transaction.rsbitcoin/src/blockdata/script/borrowed.rsbitcoin/src/blockdata/script/owned.rsbitcoin/src/blockdata/script/mod.rsbitcoin/src/address/mod.rsbitcoin/src/crypto/sighash.rsbitcoin/src/consensus_validation.rsbitcoin/src/bip158.rsInspect captured patch +405 / −342
diff --git a/bitcoin/examples/ecdsa-psbt-simple.rs b/bitcoin/examples/ecdsa-psbt-simple.rs
index a2160c03..f5a61d16 100644
--- a/bitcoin/examples/ecdsa-psbt-simple.rs
+++ b/bitcoin/examples/ecdsa-psbt-simple.rs
@@ -32,7 +32,7 @@ use bitcoin::psbt::Input;
use bitcoin::secp256k1::{Secp256k1, Signing};
use bitcoin::{
consensus, transaction, Address, Amount, EcdsaSighashType, Network, OutPoint, Psbt, ScriptBuf,
- ScriptSigBuf, Sequence, Transaction, TxIn, TxOut, Txid, Witness,
+ ScriptPubKeyBuf, ScriptSigBuf, Sequence, Transaction, TxIn, TxOut, Txid, Witness,
};
// The master xpriv, from which we derive the keys we control.
@@ -169,7 +169,7 @@ fn main() {
// The change output is locked to a key controlled by us.
let change = TxOut {
value: CHANGE_AMOUNT,
- script_pubkey: ScriptBuf::new_p2wpkh(pk_change.wpubkey_hash()), // Change comes back to us.
+ script_pubkey: ScriptPubKeyBuf::new_p2wpkh(pk_change.wpubkey_hash()), // Change comes back to us.
};
// The transaction we want to sign and broadcast.
diff --git a/bitcoin/examples/ecdsa-psbt.rs b/bitcoin/examples/ecdsa-psbt.rs
index 50948d1d..0909c211 100644
--- a/bitcoin/examples/ecdsa-psbt.rs
+++ b/bitcoin/examples/ecdsa-psbt.rs
@@ -38,8 +38,8 @@ use bitcoin::locktime::absolute;
use bitcoin::psbt::{self, Input, Psbt, PsbtSighashType};
use bitcoin::secp256k1::{Secp256k1, Signing, Verification};
use bitcoin::{
- transaction, Address, Amount, CompressedPublicKey, Network, OutPoint, ScriptBuf, ScriptSigBuf,
- Sequence, Transaction, TxIn, TxOut, Witness,
+ transaction, Address, Amount, CompressedPublicKey, Network, OutPoint, ScriptBuf,
+ ScriptPubKeyBuf, ScriptSigBuf, Sequence, Transaction, TxIn, TxOut, Witness,
};
type Result<T> = std::result::Result<T, Error>;
@@ -274,7 +274,7 @@ fn input_derivation_path() -> Result<DerivationPath> {
}
fn previous_output() -> TxOut {
- let script_pubkey = ScriptBuf::from_hex_no_length_prefix(INPUT_UTXO_SCRIPT_PUBKEY)
+ let script_pubkey = ScriptPubKeyBuf::from_hex_no_length_prefix(INPUT_UTXO_SCRIPT_PUBKEY)
.expect("failed to parse input utxo scriptPubkey");
let amount = INPUT_UTXO_VALUE.parse::<Amount>().expect("failed to parse input utxo value");
diff --git a/bitcoin/examples/script.rs b/bitcoin/examples/script.rs
index e23b5f40..09ecef3a 100644
--- a/bitcoin/examples/script.rs
+++ b/bitcoin/examples/script.rs
@@ -9,7 +9,7 @@
use bitcoin::consensus::encode;
use bitcoin::key::WPubkeyHash;
-use bitcoin::script::{self, GenericScriptBufExt, ScriptExt};
+use bitcoin::script::{self, GenericScriptBufExt as _, GenericScriptExt as _};
use bitcoin::ScriptBuf;
fn main() {
diff --git a/bitcoin/examples/sighash.rs b/bitcoin/examples/sighash.rs
index bd54913d..bac1fb94 100644
--- a/bitcoin/examples/sighash.rs
+++ b/bitcoin/examples/sighash.rs
@@ -1,6 +1,6 @@
use bitcoin::ext::*;
use bitcoin::{
- consensus, ecdsa, sighash, Amount, CompressedPublicKey, Script, ScriptBuf, Transaction,
+ consensus, ecdsa, sighash, Amount, CompressedPublicKey, Script, ScriptPubKeyBuf, Transaction,
};
use hex_lit::hex;
@@ -38,7 +38,7 @@ fn compute_sighash_p2wpkh(raw_tx: &[u8], inp_idx: usize, amount: Amount) {
let pk = CompressedPublicKey::from_slice(pk_bytes).expect("failed to parse pubkey");
let wpkh = pk.wpubkey_hash();
println!("Script pubkey hash: {wpkh:x}");
- let spk = ScriptBuf::new_p2wpkh(wpkh);
+ let spk = ScriptPubKeyBuf::new_p2wpkh(wpkh);
let mut cache = sighash::SighashCache::new(&tx);
let sighash = cache
diff --git a/bitcoin/examples/sign-tx-segwit-v0.rs b/bitcoin/examples/sign-tx-segwit-v0.rs
index 5e514b12..2c347f97 100644
--- a/bitcoin/examples/sign-tx-segwit-v0.rs
+++ b/bitcoin/examples/sign-tx-segwit-v0.rs
@@ -8,7 +8,7 @@ use bitcoin::locktime::absolute;
use bitcoin::secp256k1::{rand, Message, Secp256k1, SecretKey, Signing};
use bitcoin::sighash::{EcdsaSighashType, SighashCache};
use bitcoin::{
- transaction, Address, Amount, Network, OutPoint, ScriptBuf, ScriptSigBuf, Sequence,
+ transaction, Address, Amount, Network, OutPoint, ScriptPubKeyBuf, ScriptSigBuf, Sequence,
Transaction, TxIn, TxOut, Txid, Witness,
};
@@ -44,7 +44,7 @@ fn main() {
// The change output is locked to a key controlled by us.
let change = TxOut {
value: CHANGE_AMOUNT,
- script_pubkey: ScriptBuf::new_p2wpkh(wpkh), // Change comes back to us.
+ script_pubkey: ScriptPubKeyBuf::new_p2wpkh(wpkh), // Change comes back to us.
};
// The transaction we want to sign and broadcast.
@@ -117,7 +117,7 @@ fn receivers_address() -> Address {
/// This output is locked to keys that we control, in a real application this would be a valid
/// output taken from a transaction that appears in the chain.
fn dummy_unspent_transaction_output(wpkh: WPubkeyHash) -> (OutPoint, TxOut) {
- let script_pubkey = ScriptBuf::new_p2wpkh(wpkh);
+ let script_pubkey = ScriptPubKeyBuf::new_p2wpkh(wpkh);
let out_point = OutPoint {
txid: Txid::from_byte_array([0xFF; 32]), // Arbitrary invalid dummy value.
diff --git a/bitcoin/examples/sign-tx-taproot.rs b/bitcoin/examples/sign-tx-taproot.rs
index 883aa353..71d7026c 100644
--- a/bitcoin/examples/sign-tx-taproot.rs
+++ b/bitcoin/examples/sign-tx-taproot.rs
@@ -8,7 +8,7 @@ use bitcoin::locktime::absolute;
use bitcoin::secp256k1::{rand, Secp256k1, SecretKey, Signing, Verification};
use bitcoin::sighash::{Prevouts, SighashCache, TapSighashType};
use bitcoin::{
- transaction, Address, Amount, Network, OutPoint, ScriptBuf, ScriptSigBuf, Sequence,
+ transaction, Address, Amount, Network, OutPoint, ScriptPubKeyBuf, ScriptSigBuf, Sequence,
Transaction, TxIn, TxOut, Txid, Witness,
};
@@ -44,7 +44,7 @@ fn main() {
// The change output is locked to a key controlled by us.
let change = TxOut {
value: CHANGE_AMOUNT,
- script_pubkey: ScriptBuf::new_p2tr(&secp, internal_key, None), // Change comes back to us.
+ script_pubkey: ScriptPubKeyBuf::new_p2tr(&secp, internal_key, None), // Change comes back to us.
};
// The transaction we want to sign and broadcast.
@@ -116,7 +116,7 @@ fn dummy_unspent_transaction_output<C: Verification, K: Into<UntweakedPublicKey>
internal_key: K,
) -> (OutPoint, TxOut) {
let internal_key = internal_key.into();
- let script_pubkey = ScriptBuf::new_p2tr(secp, internal_key, None);
+ let script_pubkey = ScriptPubKeyBuf::new_p2tr(secp, internal_key, None);
let out_point = OutPoint {
txid: Txid::from_byte_array([0xFF; 32]), // Arbitrary invalid dummy value.
diff --git a/bitcoin/examples/taproot-psbt-simple.rs b/bitcoin/examples/taproot-psbt-simple.rs
index e252af60..0ba490e1 100644
--- a/bitcoin/examples/taproot-psbt-simple.rs
+++ b/bitcoin/examples/taproot-psbt-simple.rs
@@ -29,8 +29,9 @@ use bitcoin::locktime::absolute;
use bitcoin::psbt::Input;
use bitcoin::secp256k1::{Secp256k1, Signing};
use bitcoin::{
- consensus, transaction, Address, Amount, Network, OutPoint, Psbt, ScriptBuf, ScriptSigBuf,
- Sequence, TapLeafHash, TapSighashType, Transaction, TxIn, TxOut, Txid, Witness, XOnlyPublicKey,
+ consensus, transaction, Address, Amount, Network, OutPoint, Psbt, ScriptPubKeyBuf,
+ ScriptSigBuf, Sequence, TapLeafHash, TapSighashType, Transaction, TxIn, TxOut, Txid, Witness,
+ XOnlyPublicKey,
};
// The master xpriv, from which we derive the keys we control.
@@ -189,7 +190,7 @@ fn main() {
// The change output is locked to a key controlled by us.
let change = TxOut {
value: CHANGE_AMOUNT,
- script_pubkey: ScriptBuf::new_p2tr(&secp, pk_change, None), // Change comes back to us.
+ script_pubkey: ScriptPubKeyBuf::new_p2tr(&secp, pk_change, None), // Change comes back to us.
};
// The transaction we want to sign and broadcast.
diff --git a/bitcoin/examples/taproot-psbt.rs b/bitcoin/examples/taproot-psbt.rs
index a5e34d97..21d3c056 100644
--- a/bitcoin/examples/taproot-psbt.rs
+++ b/bitcoin/examples/taproot-psbt.rs
@@ -87,8 +87,8 @@ use bitcoin::secp256k1::Secp256k1;
use bitcoin::sighash::{self, SighashCache, TapSighash, TapSighashType};
use bitcoin::taproot::{self, LeafVersion, TapLeafHash, TaprootBuilder, TaprootSpendInfo};
use bitcoin::{
- absolute, script, transaction, Address, Amount, Network, OutPoint, ScriptBuf, ScriptSigBuf,
- Transaction, TxIn, TxOut, Witness,
+ absolute, script, transaction, Address, Amount, Network, OutPoint, ScriptBuf, ScriptPubKeyBuf,
+ ScriptSigBuf, Transaction, TxIn, TxOut, Witness,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
@@ -254,8 +254,9 @@ fn generate_bip86_key_spend_tx(
let mut input = Input {
witness_utxo: {
- let script_pubkey = ScriptBuf::from_hex_no_length_prefix(input_utxo.script_pubkey)
- .expect("failed to parse input utxo scriptPubkey");
+ let script_pubkey =
+ ScriptPubKeyBuf::from_hex_no_length_prefix(input_utxo.script_pubkey)
+ .expect("failed to parse input utxo scriptPubkey");
Some(TxOut { value: from_amount, script_pubkey })
},
tap_key_origins: origins,
@@ -272,7 +273,7 @@ fn generate_bip86_key_spend_tx(
for input in [&input_utxo].iter() {
input_txouts.push(TxOut {
value: input.amount,
- script_pubkey: ScriptBuf::from_hex_no_length_prefix(input.script_pubkey)?,
+ script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix(input.script_pubkey)?,
});
}
@@ -330,7 +331,8 @@ fn generate_bip86_key_spend_tx(
tx.verify(|_| {
Some(TxOut {
value: from_amount,
- script_pubkey: ScriptBuf::from_hex_no_length_prefix(input_utxo.script_pubkey).unwrap(),
+ script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix(input_utxo.script_pubkey)
+ .unwrap(),
})
})
.expect("failed to verify transaction");
@@ -407,7 +409,7 @@ impl BenefactorWallet {
.finalize(&self.secp, internal_keypair.x_only_public_key().0)
.expect("should be finalizable");
self.current_spend_info = Some(taproot_spend_info.clone());
- let script_pubkey = ScriptBuf::new_p2tr(
+ let script_pubkey = ScriptPubKeyBuf::new_p2tr(
&self.secp,
taproot_spend_info.internal_key(),
taproot_spend_info.merkle_root(),
@@ -507,7 +509,7 @@ impl BenefactorWallet {
.expect("should be finalizable");
self.current_spend_info = Some(taproot_spend_info.clone());
let prevout_script_pubkey = input.witness_utxo.as_ref().unwrap().script_pubkey.clone();
- let output_script_pubkey = ScriptBuf::new_p2tr(
+ let output_script_pubkey = ScriptPubKeyBuf::new_p2tr(
&self.secp,
taproot_spend_info.internal_key(),
taproot_spend_info.merkle_root(),
diff --git a/bitcoin/src/address/mod.rs b/bitcoin/src/address/mod.rs
index 76b92eb2..66e997d8 100644
--- a/bitcoin/src/address/mod.rs
+++ b/bitcoin/src/address/mod.rs
@@ -64,8 +64,9 @@ use crate::prelude::{String, ToOwned};
use crate::script::witness_program::WitnessProgram;
use crate::script::witness_version::WitnessVersion;
use crate::script::{
- self, RedeemScriptSizeError, Script, ScriptBuf, ScriptBufExt as _, ScriptExt as _, ScriptHash,
- WScriptHash, WitnessScriptSizeError,
+ self, GenericScriptExt as _, RedeemScriptSizeError, Script, ScriptExt as _, ScriptHash,
+ ScriptPubKey, ScriptPubKeyBuf, ScriptPubKeyBufExt as _, ScriptPubKeyExt as _, WScriptHash,
+ WitnessScriptSizeError,
};
use crate::taproot::TapNodeHash;
@@ -536,7 +537,7 @@ impl Address {
///
/// This is a SegWit address type that looks familiar (as p2sh) to legacy clients.
pub fn p2shwpkh(pk: CompressedPublicKey, network: impl Into<NetworkKind>) -> Address {
- let builder = script::Builder::new().push_int_unchecked(0).push_slice(pk.wpubkey_hash());
+ let builder = ScriptPubKey::builder().push_int_unchecked(0).push_slice(pk.wpubkey_hash());
let script_hash = builder.as_script().script_hash().expect("script is less than 520 bytes");
Address::p2sh_from_hash(script_hash, network)
}
@@ -565,7 +566,7 @@ impl Address {
network: impl Into<NetworkKind>,
) -> Result<Address, WitnessScriptSizeError> {
let hash = witness_script.wscript_hash()?;
- let builder = script::Builder::new().push_int_unchecked(0).push_slice(hash);
+ let builder = ScriptPubKey::builder().push_int_unchecked(0).push_slice(hash);
let script_hash = builder.as_script().script_hash().expect("script is less than 520 bytes");
Ok(Address::p2sh_from_hash(script_hash, network))
}
@@ -680,7 +681,7 @@ impl Address {
/// Constructs a new [`Address`] from an output script (`scriptPubkey`).
pub fn from_script(
- script: &Script,
+ script: &ScriptPubKey,
params: impl AsRef<Params>,
) -> Result<Address, FromScriptError> {
let network = params.as_ref().network;
@@ -704,11 +705,11 @@ impl Address {
}
/// Generates a script pubkey spending to this address.
- pub fn script_pubkey(&self) -> ScriptBuf {
+ pub fn script_pubkey(&self) -> ScriptPubKeyBuf {
use AddressInner::*;
match *self.inner() {
- P2pkh { hash, network: _ } => ScriptBuf::new_p2pkh(hash),
- P2sh { hash, network: _ } => ScriptBuf::new_p2sh(hash),
+ P2pkh { hash, network: _ } => ScriptPubKeyBuf::new_p2pkh(hash),
+ P2sh { hash, network: _ } => ScriptPubKeyBuf::new_p2sh(hash),
Segwit { ref program, hrp: _ } => {
let prog = program.program();
let version = program.version();
@@ -771,7 +772,7 @@ impl Address {
/// Returns true if the address creates a particular script
/// This function doesn't make any allocations.
- pub fn matches_script_pubkey(&self, script: &Script) -> bool {
+ pub fn matches_script_pubkey(&self, script: &ScriptPubKey) -> bool {
use AddressInner::*;
match *self.inner() {
P2pkh { ref hash, network: _ } if script.is_p2pkh() =>
@@ -947,7 +948,7 @@ impl Address<NetworkUnchecked> {
}
}
-impl From<Address> for ScriptBuf {
+impl From<Address> for ScriptPubKeyBuf {
fn from(a: Address) -> Self { a.script_pubkey() }
}
@@ -1020,7 +1021,7 @@ mod tests {
use super::*;
use crate::network::Network::{Bitcoin, Testnet};
use crate::network::{params, TestnetVersion};
- use crate::script::GenericScriptBufExt as _;
+ use crate::script::{GenericScriptBufExt as _, ScriptBuf};
fn roundtrips(addr: &Address, network: Network) {
assert_eq!(
@@ -1053,7 +1054,7 @@ mod tests {
assert_eq!(
addr.script_pubkey(),
- ScriptBuf::from_hex_no_length_prefix(
+ ScriptPubKeyBuf::from_hex_no_length_prefix(
"76a914162c5ea71c0b23f5b9022ef047c4a86470a5b07088ac"
)
.unwrap()
@@ -1085,8 +1086,10 @@ mod tests {
assert_eq!(
addr.script_pubkey(),
- ScriptBuf::from_hex_no_length_prefix("a914162c5ea71c0b23f5b9022ef047c4a86470a5b07087")
- .unwrap(),
+ ScriptPubKeyBuf::from_hex_no_length_prefix(
+ "a914162c5ea71c0b23f5b9022ef047c4a86470a5b07087"
+ )
+ .unwrap(),
);
assert_eq!(&addr.to_string(), "33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k");
assert_eq!(addr.address_type(), Some(AddressType::P2sh));
@@ -1238,7 +1241,7 @@ mod tests {
assert_eq!(addr.to_string(), into.to_string());
assert_eq!(
into.script_pubkey(),
- ScriptBuf::from_hex_no_length_prefix(
+ ScriptPubKeyBuf::from_hex_no_length_prefix(
"76a914162c5ea71c0b23f5b9022ef047c4a86470a5b07088ac"
)
.unwrap()
@@ -1255,8 +1258,10 @@ mod tests {
assert_eq!(addr.to_string(), into.to_string());
assert_eq!(
into.script_pubkey(),
- ScriptBuf::from_hex_no_length_prefix("a914162c5ea71c0b23f5b9022ef047c4a86470a5b07087")
- .unwrap()
+ ScriptPubKeyBuf::from_hex_no_length_prefix(
+ "a914162c5ea71c0b23f5b9022ef047c4a86470a5b07087"
+ )
+ .unwrap()
);
let addr: Address<NetworkUnchecked> =
@@ -1286,7 +1291,7 @@ mod tests {
assert_eq!(addr.to_string(), into.to_string());
assert_eq!(
into.script_pubkey(),
- ScriptBuf::from_hex_no_length_prefix(
+ ScriptPubKeyBuf::from_hex_no_length_prefix(
"00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262"
)
.unwrap()
@@ -1305,8 +1310,10 @@ mod tests {
assert_eq!(addr.to_string(), into.to_string());
assert_eq!(
into.script_pubkey(),
- ScriptBuf::from_hex_no_length_prefix("001454d26dddb59c7073c6a197946ea1841951fa7a74")
- .unwrap()
+ ScriptPubKeyBuf::from_hex_no_length_prefix(
+ "001454d26dddb59c7073c6a197946ea1841951fa7a74"
+ )
+ .unwrap()
);
}
@@ -1485,15 +1492,17 @@ mod tests {
fn fail_address_from_script() {
use crate::witness_program;
- let bad_p2wpkh =
- ScriptBuf::from_hex_no_length_prefix("15000014dbc5b0a8f9d4353b4b54c3db48846bb15abfec")
- .unwrap();
- let bad_p2wsh = ScriptBuf::from_hex_no_length_prefix(
+ let bad_p2wpkh = ScriptPubKeyBuf::from_hex_no_length_prefix(
+ "15000014dbc5b0a8f9d4353b4b54c3db48846bb15abfec",
+ )
+ .unwrap();
+ let bad_p2wsh = ScriptPubKeyBuf::from_hex_no_length_prefix(
"00202d4fa2eb233d008cc83206fa2f4f2e60199000f5b857a835e3172323385623",
)
.unwrap();
let invalid_segwitv0_script =
- ScriptBuf::from_hex_no_length_prefix("001161458e330389cd0437ee9fe3641d70cc18").unwrap();
+ ScriptPubKeyBuf::from_hex_no_length_prefix("001161458e330389cd0437ee9fe3641d70cc18")
+ .unwrap();
let expected = Err(FromScriptError::UnrecognizedScript);
assert_eq!(Address::from_script(&bad_p2wpkh, Network::Bitcoin), expected);
@@ -1582,7 +1591,7 @@ mod tests {
// This test-vector is borrowed from the bitcoin source code.
let address_str = "bcrt1pfeesnyr2tx";
- let script = ScriptBuf::new_p2a();
+ let script = ScriptPubKeyBuf::new_p2a();
let address_unchecked = address_str.parse().unwrap();
let address = Address::from_script(&script, Network::Regtest).unwrap();
assert_eq!(address.as_unchecked(), &address_unchecked);
diff --git a/bitcoin/src/bip152.rs b/bitcoin/src/bip152.rs
index fd969eef..f8b10aa3 100644
--- a/bitcoin/src/bip152.rs
+++ b/bitcoin/src/bip152.rs
@@ -460,7 +460,7 @@ mod test {
use crate::merkle_tree::TxMerkleNode;
use crate::transaction::OutPointExt;
use crate::{
- transaction, Amount, BlockChecked, BlockTime, CompactTarget, OutPoint, ScriptBuf,
+ transaction, Amount, BlockChecked, BlockTime, CompactTarget, OutPoint, ScriptPubKeyBuf,
ScriptSigBuf, Sequence, TxIn, TxOut, Txid, Witness,
};
@@ -475,7 +475,7 @@ mod test {
sequence: Sequence(1),
witness: Witness::new(),
}],
- outputs: vec![TxOut { value: Amount::ONE_SAT, script_pubkey: ScriptBuf::new() }],
+ outputs: vec![TxOut { value: Amount::ONE_SAT, script_pubkey: ScriptPubKeyBuf::new() }],
}
}
diff --git a/bitcoin/src/bip158.rs b/bitcoin/src/bip158.rs
index 9360308e..69bd2e9b 100644
--- a/bitcoin/src/bip158.rs
+++ b/bitcoin/src/bip158.rs
@@ -19,7 +19,7 @@
//! # Examples
//!
//! ```ignore
-//! fn get_script_for_coin(coin: &OutPoint) -> Result<ScriptBuf, BlockFilterError> {
+//! fn get_script_for_coin(coin: &OutPoint) -> Result<ScriptPubKeyBuf, BlockFilterError> {
//! // get utxo ...
//! }
//!
@@ -31,7 +31,7 @@
//!
//! // read and evaluate a filter
//!
-//! let query: Iterator<Item=ScriptBuf> = // .. some scripts you care about
+//! let query: Iterator<Item=ScriptPubKeyBuf> = // .. some scripts you care about
//! if filter.match_any(&block_hash, &mut query.map(|s| s.as_bytes())) {
//! // get this block
//! }
@@ -52,7 +52,7 @@ use crate::block::{Block, BlockHash, Checked};
use crate::consensus::{ReadExt, WriteExt};
use crate::internal_macros;
use crate::prelude::{BTreeSet, Borrow, Vec};
-use crate::script::{Script, ScriptExt as _};
+use crate::script::{ScriptPubKey, ScriptPubKeyExt as _};
use crate::transaction::OutPoint;
/// Golomb encoding parameter as in BIP-0158, see also https://gist.github.com/sipa/576d5f09c3b86c3b1b75598d799fc845
@@ -142,7 +142,7 @@ impl BlockFilter {
) -> Result<BlockFilter, Error>
where
M: Fn(&OutPoint) -> Result<S, Error>,
- S: Borrow<Script>,
+ S: Borrow<ScriptPubKey>,
{
let mut out = Vec::new();
let mut writer = BlockFilterWriter::new(&mut out, block);
@@ -219,7 +219,7 @@ impl<'a, W: Write> BlockFilterWriter<'a, W> {
pub fn add_input_scripts<M, S>(&mut self, script_for_coin: M) -> Result<(), Error>
where
M: Fn(&OutPoint) -> Result<S, Error>,
- S: Borrow<Script>,
+ S: Borrow<ScriptPubKey>,
{
for script in self
.block
@@ -599,7 +599,7 @@ mod test {
use super::*;
use crate::consensus::encode::deserialize;
- use crate::ScriptBuf;
+ use crate::ScriptPubKeyBuf;
#[test]
fn blockfilters() {
@@ -627,7 +627,7 @@ mod test {
for input in tx.inputs.iter() {
txmap.insert(
input.previous_output,
- ScriptBuf::from(hex(si.next().unwrap().as_str().unwrap())),
+ ScriptPubKeyBuf::from(hex(si.next().unwrap().as_str().unwrap())),
);
}
}
diff --git a/bitcoin/src/blockdata/block.rs b/bitcoin/src/blockdata/block.rs
index 60087d35..daf8aa79 100644
--- a/bitcoin/src/blockdata/block.rs
+++ b/bitcoin/src/blockdata/block.rs
@@ -535,7 +535,7 @@ mod tests {
use super::*;
use crate::consensus::encode::{deserialize, serialize};
use crate::pow::test_utils::{u128_to_work, u64_to_work};
- use crate::script::{ScriptBuf, ScriptSigBuf};
+ use crate::script::{ScriptPubKeyBuf, ScriptSigBuf};
use crate::transaction::{OutPoint, Transaction, TxIn, TxOut, Txid};
use crate::{block, Amount, CompactTarget, Network, Sequence, TestnetVersion, Witness};
@@ -815,7 +815,7 @@ mod tests {
sequence: Sequence::ENABLE_LOCKTIME_AND_RBF,
witness: Witness::new(),
}],
- outputs: vec![TxOut { value: Amount::ONE_BTC, script_pubkey: ScriptBuf::new() }],
+ outputs: vec![TxOut { value: Amount::ONE_BTC, script_pubkey: ScriptPubKeyBuf::new() }],
};
let transactions = vec![non_coinbase_tx];
@@ -891,7 +891,7 @@ mod tests {
sequence: Sequence::ENABLE_LOCKTIME_AND_RBF,
witness: Witness::new(),
}],
- outputs: vec![TxOut { value: Amount::ONE_BTC, script_pubkey: ScriptBuf::new() }],
+ outputs: vec![TxOut { value: Amount::ONE_BTC, script_pubkey: ScriptPubKeyBuf::new() }],
};
let invalid_coinbase_result = Block::new_checked(header, vec![non_coinbase_tx]);
diff --git a/bitcoin/src/blockdata/script/borrowed.rs b/bitcoin/src/blockdata/script/borrowed.rs
index f460d698..ffb345c9 100644
--- a/bitcoin/src/blockdata/script/borrowed.rs
+++ b/bitcoin/src/blockdata/script/borrowed.rs
@@ -10,7 +10,8 @@ use secp256k1::{Secp256k1, Verification};
use super::witness_version::WitnessVersion;
use super::{
Builder, GenericScript, Instruction, InstructionIndices, Instructions, PushBytes,
- RedeemScriptSizeError, Script, ScriptHash, ScriptSig, WScriptHash, WitnessScriptSizeError,
+ RedeemScriptSizeError, Script, ScriptHash, ScriptPubKey, ScriptSig, WScriptHash,
+ WitnessScriptSizeError,
};
use crate::consensus::{self, Encodable};
use crate::key::{PublicKey, UntweakedPublicKey, WPubkeyHash};
@@ -18,9 +19,9 @@ use crate::opcodes::all::*;
use crate::opcodes::{self, Opcode};
use crate::policy::{DUST_RELAY_TX_FEE, MAX_OP_RETURN_RELAY};
use crate::prelude::{sink, String, ToString};
-use crate::script::{self, ScriptBufExt as _};
+use crate::script::{self, ScriptPubKeyBufExt as _};
use crate::taproot::{LeafVersion, TapLeafHash, TapNodeHash};
-use crate::{internal_macros, Amount, FeeRate, ScriptBuf};
+use crate::{internal_macros, Amount, FeeRate, ScriptBuf, ScriptPubKeyBuf};
internal_macros::define_extension_trait! {
/// Extension functionality for the [`Script`] type.
@@ -123,52 +124,52 @@ internal_macros::define_extension_trait! {
InstructionIndices::from_instructions(self.instructions_minimal())
}
- }
-}
-
-crate::internal_macros::define_extension_trait! {
- /// Extension functionality for the [`Script`] type.
- pub trait ScriptExt impl for Script {
- /// Returns 160-bit hash of the script for P2SH outputs.
- #[inline]
- fn script_hash(&self) -> Result<ScriptHash, RedeemScriptSizeError> {
- ScriptHash::from_script(self)
+ /// Writes the human-readable assembly representation of the script to the formatter.
+ #[deprecated(since = "TBD", note = "use the script's `Display` impl instead")]
+ fn fmt_asm(&self, f: &mut dyn fmt::Write) -> fmt::Result {
+ write!(f, "{}", self)
}
- /// Returns 256-bit hash of the script for P2WSH outputs.
- #[inline]
- fn wscript_hash(&self) -> Result<WScriptHash, WitnessScriptSizeError> {
- WScriptHash::from_script(self)
- }
+ /// Returns the human-readable assembly representation of the script.
+ #[deprecated(since = "TBD", note = "use `to_string()` instead")]
+ fn to_asm_string(&self) -> String { self.to_string() }
- /// Computes leaf hash of tapscript.
- #[inline]
- fn tapscript_leaf_hash(&self) -> TapLeafHash {
- TapLeafHash::from_script(self, LeafVersion::TapScript)
+ /// Consensus encodes the script as lower-case hex.
+ #[deprecated(since = "TBD", note = "use `to_hex_string_no_length_prefix` instead")]
+ fn to_hex_string(&self) -> String { self.to_hex_string_no_length_prefix() }
+
+ /// Consensus encodes the script as lower-case hex.
+ ///
+ /// Consensus encoding includes a length prefix. To hex encode without the length prefix use
+ /// `to_hex_string_no_length_prefix`.
+ fn to_hex_string_prefixed(&self) -> String { consensus::encode::serialize_hex(self) }
+
+ /// Encodes the script as lower-case hex.
+ ///
+ /// This is **not** consensus encoding. The returned hex string will not include the length
+ /// prefix. See `to_hex_string_prefixed`.
+ fn to_hex_string_no_length_prefix(&self) -> String {
+ self.as_bytes().to_lower_hex_string()
}
- /// Computes the P2WSH output corresponding to this witnessScript (aka the "witness redeem
- /// script").
- fn to_p2wsh(&self) -> Result<ScriptBuf, WitnessScriptSizeError> {
- self.wscript_hash().map(ScriptBuf::new_p2wsh)
+ /// Returns the first opcode of the script (if there is any).
+ fn first_opcode(&self) -> Option<Opcode> {
+ self.as_bytes().first().copied().map(From::from)
}
- /// 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>>(
- &self,
- secp: &Secp256k1<C>,
- internal_key: K,
- ) -> ScriptBuf {
- let internal_key = internal_key.into();
- let leaf_hash = self.tapscript_leaf_hash();
- let merkle_root = TapNodeHash::from(leaf_hash);
- ScriptBuf::new_p2tr(secp, internal_key, Some(merkle_root))
+ // These methods should exist for only ScriptPubKey and RedeemScript. When we
+ // introduce RedeemScript we'll also introduce another marker trait to limit
+ // them. For now just put them on every Script type.
+
+ /// Returns 160-bit hash of the script for P2SH outputs.
+ #[inline]
+ fn script_hash(&self) -> Result<ScriptHash, RedeemScriptSizeError> {
+ ScriptHash::from_script(self)
}
/// Computes the P2SH output corresponding to this redeem script.
- fn to_p2sh(&self) -> Result<ScriptBuf, RedeemScriptSizeError> {
- self.script_hash().map(ScriptBuf::new_p2sh)
+ fn to_p2sh(&self) -> Result<ScriptPubKeyBuf, RedeemScriptSizeError> {
+ self.script_hash().map(ScriptPubKeyBuf::new_p2sh)
}
/// Returns the script code used for spending a P2WPKH output if this script is a script pubkey
@@ -186,21 +187,6 @@ crate::internal_macros::define_extension_trait! {
}
}
- /// Checks whether a script pubkey is a P2PK output.
- ///
- /// You can obtain the public key, if its valid,
- /// by calling [`p2pk_public_key()`](Self::p2pk_public_key)
- fn is_p2pk(&self) -> bool { self.p2pk_pubkey_bytes().is_some() }
-
- /// Returns the public key if this script is P2PK with a **valid** public key.
- ///
- /// This may return `None` even when [`is_p2pk()`](Self::is_p2pk) returns true.
- /// This happens when the public key is invalid (e.g. the point not being on the curve).
- /// In this situation the script is unspendable.
- fn p2pk_public_key(&self) -> Option<PublicKey> {
- PublicKey::from_slice(self.p2pk_pubkey_bytes()?).ok()
- }
-
/// Returns witness version of the script, if any, assuming the script is a `scriptPubkey`.
///
/// # Returns
@@ -232,6 +218,78 @@ crate::internal_macros::define_extension_trait! {
WitnessVersion::try_from(ver_opcode).ok()
}
+ /// Checks whether a script pubkey is a P2WSH output.
+ #[inline]
+ fn is_p2wsh(&self) -> bool {
+ self.len() == 34
+ && self.witness_version() == Some(WitnessVersion::V0)
+ && self.as_bytes()[1] == OP_PUSHBYTES_32.to_u8()
+ }
+
+ /// Checks whether a script pubkey is a P2WPKH output.
+ #[inline]
+ fn is_p2wpkh(&self) -> bool {
+ self.len() == 22
+ && self.witness_version() == Some(WitnessVersion::V0)
+ && self.as_bytes()[1] == OP_PUSHBYTES_20.to_u8()
+ }
+ }
+}
+
+internal_macros::define_extension_trait! {
+ /// Extension functionality for the [`Script`] type.
+ pub trait ScriptExt impl for Script {
+ /// Returns 256-bit hash of the script for P2WSH outputs.
+ #[inline]
+ fn wscript_hash(&self) -> Result<WScriptHash, WitnessScriptSizeError> {
+ WScriptHash::from_script(self)
+ }
+
+ /// 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>>(
+ &self,
+ secp: &Secp256k1<C>,
+ internal_key: K,
+ ) -> ScriptPubKeyBuf {
+ let internal_key = internal_key.into();
+ let leaf_hash = self.tapscript_leaf_hash();
+ let merkle_root = TapNodeHash::from(leaf_hash);
+ ScriptPubKeyBuf::new_p2tr(secp, internal_key, Some(merkle_root))
+ }
+ }
+}
+
+internal_macros::define_extension_trait! {
+ /// Extension functionality for the [`Script`] type.
+ pub trait ScriptPubKeyExt impl for ScriptPubKey {
+ /// Checks whether a script pubkey is a P2PK output.
+ ///
+ /// You can obtain the public key, if its valid,
+ /// by calling [`p2pk_public_key()`](Self::p2pk_public_key)
+ fn is_p2pk(&self) -> bool { self.p2pk_pubkey_bytes().is_some() }
+
+ /// Returns the public key if this script is P2PK with a **valid** public key.
+ ///
+ /// This may return `None` even when [`is_p2pk()`](Self::is_p2pk) returns true.
+ /// This happens when the public key is invalid (e.g. the point not being on the curve).
+ /// In this situation the script is unspendable.
+ fn p2pk_public_key(&self) -> Option<PublicKey> {
+ PublicKey::from_slice(self.p2pk_pubkey_bytes()?).ok()
+ }
+
/// Checks whether a script pubkey is a P2SH output.
#[inline]
fn is_p2sh(&self) -> bool {
@@ -309,22 +367,6 @@ crate::internal_macros::define_extension_trait! {
#[inline]
fn is_witness_program(&self) -> bool { self.witness_version().is_some() }
- /// Checks whether a script pubkey is a P2WSH output.
- #[inline]
- fn is_p2wsh(&self) -> bool {
- self.len() == 34
- && self.witness_version() == Some(WitnessVersion::V0)
- && self.as_bytes()[1] == OP_PUSHBYTES_32.to_u8()
- }
-
- /// Checks whether a script pubkey is a P2WPKH output.
- #[inline]
- fn is_p2wpkh(&self) -> bool {
- self.len() == 22
- && self.witness_version() == Some(WitnessVersion::V0)
- && self.as_bytes()[1] == OP_PUSHBYTES_20.to_u8()
- }
-
/// Checks whether a script pubkey is a P2TR output.
#[inline]
fn is_p2tr(&self) -> bool {
@@ -405,39 +447,6 @@ crate::internal_macros::define_extension_trait! {
fn minimal_non_dust_custom(&self, dust_relay: FeeRate) -> Option<Amount> {
self.minimal_non_dust_internal(dust_relay.to_sat_per_kvb_ceil())
}
-
- /// Writes the human-readable assembly representation of the script to the formatter.
- #[deprecated(since = "TBD", note = "use the script's `Display` impl instead")]
- fn fmt_asm(&self, f: &mut dyn fmt::Write) -> fmt::Result {
- write!(f, "{}", self)
- }
-
- /// Returns the human-readable assembly representation of the script.
- #[deprecated(since = "TBD", note = "use `to_string()` instead")]
- fn to_asm_string(&self) -> String { self.to_string() }
-
- /// Consensus encodes the script as lower-case hex.
- #[deprecated(since = "TBD", note = "use `to_hex_string_no_length_prefix` instead")]
- fn to_hex_string(&self) -> String { self.to_hex_string_no_length_prefix() }
-
- /// Consensus encodes the script as lower-case hex.
- ///
- /// Consensus encoding includes a length prefix. To hex encode without the length prefix use
- /// `to_hex_string_no_length_prefix`.
- fn to_hex_string_prefixed(&self) -> String { consensus::encode::serialize_hex(self) }
-
- /// Encodes the script as lower-case hex.
- ///
- /// This is **not** consensus encoding. The returned hex string will not include the length
- /// prefix. See `to_hex_string_prefixed`.
- fn to_hex_string_no_length_prefix(&self) -> String {
- self.as_bytes().to_lower_hex_string()
- }
-
- /// Returns the first opcode of the script (if there is any).
- fn first_opcode(&self) -> Option<Opcode> {
- self.as_bytes().first().copied().map(From::from)
- }
}
}
@@ -514,7 +523,7 @@ internal_macros::define_extension_trait! {
}
internal_macros::define_extension_trait! {
- pub(crate) trait ScriptExtPriv impl for Script {
+ pub(crate) trait ScriptPubKeyExtPriv impl for ScriptPubKey {
/// Returns the bytes of the (possibly invalid) public key if this script is P2PK.
fn p2pk_pubkey_bytes(&self) -> Option<&[u8]> {
if let Ok(bytes) = <&[u8; 67]>::try_from(self.as_bytes()) {
diff --git a/bitcoin/src/blockdata/script/mod.rs b/bitcoin/src/blockdata/script/mod.rs
index e530223f..9aee65c2 100644
--- a/bitcoin/src/blockdata/script/mod.rs
+++ b/bitcoin/src/blockdata/script/mod.rs
@@ -74,16 +74,17 @@ use crate::OutPoint;
#[rustfmt::skip] // Keep public re-exports separate.
#[doc(inline)]
pub use self::{
- borrowed::{GenericScriptExt, ScriptExt, ScriptSigExt},
+ borrowed::{GenericScriptExt, ScriptExt, ScriptPubKeyExt, ScriptSigExt},
builder::Builder,
instruction::{Instruction, Instructions, InstructionIndices},
- owned::{GenericScriptBufExt, ScriptBufExt},
+ owned::{GenericScriptBufExt, ScriptPubKeyBufExt},
push_bytes::{PushBytes, PushBytesBuf, PushBytesError, PushBytesErrorReport},
};
#[doc(inline)]
pub use primitives::script::{
GenericScript, GenericScriptBuf, RedeemScriptSizeError, Script, ScriptBuf, ScriptHash,
- ScriptSig, ScriptSigBuf, ScriptSigTag, Tag, WScriptHash, Whatever, WitnessScriptSizeError,
+ ScriptPubKey, ScriptPubKeyBuf, ScriptPubKeyTag, ScriptSig, ScriptSigBuf, ScriptSigTag, Tag,
+ WScriptHash, Whatever, WitnessScriptSizeError,
};
pub(crate) use self::borrowed::GenericScriptExtPriv;
@@ -198,10 +199,10 @@ fn opcode_to_verify(opcode: Option<Opcode>) -> Option<Opcode> {
/// Does not do any checks on version or program length.
///
/// Convenience method used by `new_p2a`, `new_p2wpkh`, `new_p2wsh`, `new_p2tr`, and `new_p2tr_tweaked`.
-pub(crate) fn new_witness_program_unchecked<T: AsRef<PushBytes>>(
+pub(crate) fn new_witness_program_unchecked<T: AsRef<PushBytes>, Tg>(
version: WitnessVersion,
program: T,
-) -> ScriptBuf {
+) -> GenericScriptBuf<Tg> {
let program = program.as_ref();
debug_assert!(program.len() >= 2 && program.len() <= 40);
// In SegWit v0, the program must be either 20 bytes (P2WPKH) or 32 bytes (P2WSH) long.
diff --git a/bitcoin/src/blockdata/script/owned.rs b/bitcoin/src/blockdata/script/owned.rs
index 81610337..c2ed73a9 100644
--- a/bitcoin/src/blockdata/script/owned.rs
+++ b/bitcoin/src/blockdata/script/owned.rs
@@ -9,7 +9,7 @@ use secp256k1::{Secp256k1, Verification};
use super::{
opcode_to_verify, Builder, GenericScriptBuf, GenericScriptExtPriv as _, Instruction, PushBytes,
- ScriptBuf,
+ ScriptBuf, ScriptPubKeyBuf,
};
use crate::key::{
PubkeyHash, PublicKey, TapTweak, TweakedPublicKey, UntweakedPublicKey, WPubkeyHash,
@@ -122,12 +122,20 @@ internal_macros::define_extension_trait! {
let v = Vec::from_hex(s)?;
Ok(Self::from_bytes(v))
}
+
+ // This belongs only on RedeemScript and ScriptPubKey
+ /// Generates P2WPKH-type of scriptPubkey.
+ fn new_p2wpkh(pubkey_hash: WPubkeyHash) -> Self {
+ // pubkey hash is 20 bytes long, so it's safe to use `new_witness_program_unchecked` (Segwitv0)
+ script::new_witness_program_unchecked(WitnessVersion::V0, pubkey_hash)
+ }
+
}
}
crate::internal_macros::define_extension_trait! {
/// Extension functionality for the [`ScriptBuf`] type.
- pub trait ScriptBufExt impl for ScriptBuf {
+ pub trait ScriptPubKeyBufExt impl for ScriptPubKeyBuf {
/// Generates OP_RETURN-type of scriptPubkey for the given data.
fn new_op_return<T: AsRef<PushBytes>>(data: T) -> Self {
Builder::new().push_opcode(OP_RETURN).push_slice(data).into_script()
@@ -158,12 +166,6 @@ crate::internal_macros::define_extension_trait! {
.into_script()
}
- /// Generates P2WPKH-type of scriptPubkey.
- fn new_p2wpkh(pubkey_hash: WPubkeyHash) -> Self {
- // pubkey hash is 20 bytes long, so it's safe to use `new_witness_program_unchecked` (Segwitv0)
- script::new_witness_program_unchecked(WitnessVersion::V0, pubkey_hash)
- }
-
/// Generates P2WSH-type of scriptPubkey with a given hash of the redeem script.
fn new_p2wsh(script_hash: WScriptHash) -> Self {
// script hash is 32 bytes long, so it's safe to use `new_witness_program_unchecked` (Segwitv0)
diff --git a/bitcoin/src/blockdata/script/tests.rs b/bitcoin/src/blockdata/script/tests.rs
index cfb52d16..bc6afc6d 100644
--- a/bitcoin/src/blockdata/script/tests.rs
+++ b/bitcoin/src/blockdata/script/tests.rs
@@ -5,7 +5,7 @@ use hex_lit::hex;
use super::*;
use crate::consensus::encode::{deserialize, serialize};
use crate::crypto::key::{PublicKey, XOnlyPublicKey};
-use crate::script::borrowed::ScriptExtPriv as _;
+use crate::script::borrowed::{ScriptExt as _, ScriptPubKeyExt as _, ScriptPubKeyExtPriv as _};
use crate::script::witness_program::WitnessProgram;
use crate::script::witness_version::WitnessVersion;
use crate::{opcodes, Amount, FeeRate};
@@ -71,7 +71,7 @@ fn script() {
fn p2pk_pubkey_bytes_valid_key_and_valid_script_returns_expected_key() {
let key_str = "0411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3";
let key = key_str.parse::<PublicKey>().unwrap();
- let p2pk = Script::builder().push_key(key).push_opcode(OP_CHECKSIG).into_script();
+ let p2pk = ScriptPubKey::builder().push_key(key).push_opcode(OP_CHECKSIG).into_script();
let actual = p2pk.p2pk_pubkey_bytes().unwrap();
assert_eq!(actual.to_vec(), key.to_vec());
}
@@ -80,20 +80,20 @@ fn p2pk_pubkey_bytes_valid_key_and_valid_script_returns_expected_key() {
fn p2pk_pubkey_bytes_no_checksig_returns_none() {
let key_str = "0411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3";
let key = key_str.parse::<PublicKey>().unwrap();
- let no_checksig = Script::builder().push_key(key).into_script();
+ let no_checksig = ScriptPubKey::builder().push_key(key).into_script();
assert_eq!(no_checksig.p2pk_pubkey_bytes(), None);
}
#[test]
fn p2pk_pubkey_bytes_empty_script_returns_none() {
- let empty_script = Script::builder().into_script();
+ let empty_script = ScriptPubKey::builder().into_script();
assert!(empty_script.p2pk_pubkey_bytes().is_none());
}
#[test]
fn p2pk_pubkey_bytes_no_key_returns_none() {
// scripts with no key should return None
- let no_push_bytes = Script::builder().push_opcode(OP_CHECKSIG).into_script();
+ let no_push_bytes = ScriptPubKey::builder().push_opcode(OP_CHECKSIG).into_script();
assert!(no_push_bytes.p2pk_pubkey_bytes().is_none());
}
@@ -101,7 +101,7 @@ fn p2pk_pubkey_bytes_no_key_returns_none() {
fn p2pk_pubkey_bytes_different_op_code_returns_none() {
let key_str = "0411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3";
let key = key_str.parse::<PublicKey>().unwrap();
- let different_op_code = Script::builder().push_key(key).push_opcode(OP_NOP).into_script();
+ let different_op_code = ScriptPubKey::builder().push_key(key).push_opcode(OP_NOP).into_script();
assert!(different_op_code.p2pk_pubkey_bytes().is_none());
}
@@ -110,7 +110,7 @@ fn p2pk_pubkey_bytes_incorrect_key_size_returns_none() {
// 63 byte key
let malformed_key = b"21032e58afe51f9ed8ad3cc7897f634d881fdbe49816429ded8156bebd2ffd1";
let invalid_p2pk_script =
- Script::builder().push_slice(malformed_key).push_opcode(OP_CHECKSIG).into_script();
+ ScriptPubKey::builder().push_slice(malformed_key).push_opcode(OP_CHECKSIG).into_script();
assert!(invalid_p2pk_script.p2pk_pubkey_bytes().is_none());
}
@@ -118,7 +118,7 @@ fn p2pk_pubkey_bytes_incorrect_key_size_returns_none() {
fn p2pk_pubkey_bytes_invalid_key_returns_some() {
let malformed_key = b"21032e58afe51f9ed8ad3cc7897f634d881fdbe49816429ded8156bebd2ffd1ux";
let invalid_key_script =
- Script::builder().push_slice(malformed_key).push_opcode(OP_CHECKSIG).into_script();
+ ScriptPubKey::builder().push_slice(malformed_key).push_opcode(OP_CHECKSIG).into_script();
assert!(invalid_key_script.p2pk_pubkey_bytes().is_some());
}
@@ -126,7 +126,7 @@ fn p2pk_pubkey_bytes_invalid_key_returns_some() {
fn p2pk_pubkey_bytes_compressed_key_returns_expected_key() {
let compressed_key_str = "0311db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c";
let key = compressed_key_str.parse::<PublicKey>().unwrap();
- let p2pk = Script::builder().push_key(key).push_opcode(OP_CHECKSIG).into_script();
+ let p2pk = ScriptPubKey::builder().push_key(key).push_opcode(OP_CHECKSIG).into_script();
let actual = p2pk.p2pk_pubkey_bytes().unwrap();
assert_eq!(actual.to_vec(), key.to_vec());
}
@@ -135,7 +135,7 @@ fn p2pk_pubkey_bytes_compressed_key_returns_expected_key() {
fn p2pk_public_key_valid_key_and_valid_script_returns_expected_key() {
let key_str = "0411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3";
let key = key_str.parse::<PublicKey>().unwrap();
- let p2pk = Script::builder().push_key(key).push_opcode(OP_CHECKSIG).into_script();
+ let p2pk = ScriptPubKey::builder().push_key(key).push_opcode(OP_CHECKSIG).into_script();
let actual = p2pk.p2pk_public_key().unwrap();
assert_eq!(actual, key);
}
@@ -144,19 +144,19 @@ fn p2pk_public_key_valid_key_and_valid_script_returns_expected_key() {
fn p2pk_public_key_no_checksig_returns_none() {
let key_str = "0411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3";
let key = key_str.parse::<PublicKey>().unwrap();
- let no_checksig = Script::builder().push_key(key).into_script();
+ let no_checksig = ScriptPubKey::builder().push_key(key).into_script();
assert_eq!(no_checksig.p2pk_public_key(), None);
}
#[test]
fn p2pk_public_key_empty_script_returns_none() {
- let empty_script = Script::builder().into_script();
+ let empty_script = ScriptPubKey::builder().into_script();
assert!(empty_script.p2pk_public_key().is_none());
}
#[test]
fn p2pk_public_key_no_key_returns_none() {
- let no_push_bytes = Script::builder().push_opcode(OP_CHECKSIG).into_script();
+ let no_push_bytes = ScriptPubKey::builder().push_opcode(OP_CHECKSIG).into_script();
assert!(no_push_bytes.p2pk_public_key().is_none());
}
@@ -164,7 +164,7 @@ fn p2pk_public_key_no_key_returns_none() {
fn p2pk_public_key_different_op_code_returns_none() {
let key_str = "0411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3";
let key = key_str.parse::<PublicKey>().unwrap();
- let different_op_code = Script::builder().push_key(key).push_opcode(OP_NOP).into_script();
+ let different_op_code = ScriptPubKey::builder().push_key(key).push_opcode(OP_NOP).into_script();
assert!(different_op_code.p2pk_public_key().is_none());
}
@@ -172,7 +172,7 @@ fn p2pk_public_key_different_op_code_returns_none() {
fn p2pk_public_key_incorrect_size_returns_none() {
let malformed_key = b"21032e58afe51f9ed8ad3cc7897f634d881fdbe49816429ded8156bebd2ffd1";
let malformed_key_script =
- Script::builder().push_slice(malformed_key).push_opcode(OP_CHECKSIG).into_script();
+ ScriptPubKey::builder().push_slice(malformed_key).push_opcode(OP_CHECKSIG).into_script();
assert!(malformed_key_script.p2pk_public_key().is_none());
}
@@ -180,7 +180,7 @@ fn p2pk_public_key_incorrect_size_returns_none() {
fn p2pk_public_key_invalid_key_returns_none() {
let malformed_key = b"21032e58afe51f9ed8ad3cc7897f634d881fdbe49816429ded8156bebd2ffd1ux";
let invalid_key_script =
- Script::builder().push_slice(malformed_key).push_opcode(OP_CHECKSIG).into_script();
+ ScriptPubKey::builder().push_slice(malformed_key).push_opcode(OP_CHECKSIG).into_script();
assert!(invalid_key_script.p2pk_public_key().is_none());
}
@@ -188,7 +188,7 @@ fn p2pk_public_key_invalid_key_returns_none() {
fn p2pk_public_key_compressed_key_returns_some() {
let compressed_key_str = "0311db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c";
let key = compressed_key_str.parse::<PublicKey>().unwrap();
- let p2pk = Script::builder().push_key(key).push_opcode(OP_CHECKSIG).into_script();
+ let p2pk = ScriptPubKey::builder().push_key(key).push_opcode(OP_CHECKSIG).into_script();
let actual = p2pk.p2pk_public_key().unwrap();
assert_eq!(actual, key);
}
@@ -207,7 +207,7 @@ fn script_x_only_key() {
#[test]
fn script_builder() {
// from txid 3bb5e6434c11fb93f64574af5d116736510717f2c595eb45b52c28e31622dfff which was in my mempool when I wrote the test
- let script = Script::builder()
+ let script = ScriptPubKey::builder()
.push_opcode(OP_DUP)
.push_opcode(OP_HASH160)
.push_slice(hex!("16e1ae70ff0fa102905d4af297f6912bda6cce19"))
@@ -232,29 +232,29 @@ fn script_generators() {
let pubkey = "0234e6a79c5359c613762d537e0e19d86c77c1666d8c9ab050f23acd198e97f93e"
.parse::<PublicKey>()
.unwrap();
- assert!(ScriptBuf::new_p2pk(pubkey).is_p2pk());
+ assert!(ScriptPubKeyBuf::new_p2pk(pubkey).is_p2pk());
let pubkey_hash = pubkey.pubkey_hash();
- assert!(ScriptBuf::new_p2pkh(pubkey_hash).is_p2pkh());
+ assert!(ScriptPubKeyBuf::new_p2pkh(pubkey_hash).is_p2pkh());
let wpubkey_hash = pubkey.wpubkey_hash().unwrap();
- assert!(ScriptBuf::new_p2wpkh(wpubkey_hash).is_p2wpkh());
+ assert!(ScriptPubKeyBuf::new_p2wpkh(wpubkey_hash).is_p2wpkh());
let script = Builder::new().push_opcode(OP_NUMEQUAL).push_verify().into_script();
let script_hash = script.script_hash().expect("script is less than 520 bytes");
- let p2sh = ScriptBuf::new_p2sh(script_hash);
+ let p2sh = ScriptPubKeyBuf::new_p2sh(script_hash);
assert!(p2sh.is_p2sh());
assert_eq!(script.to_p2sh().unwrap(), p2sh);
let wscript_hash = script.wscript_hash().expect("script is less than 10,000 bytes");
- let p2wsh = ScriptBuf::new_p2wsh(wscript_hash);
+ let p2wsh = ScriptPubKeyBuf::new_p2wsh(wscript_hash);
assert!(p2wsh.is_p2wsh());
assert_eq!(script.to_p2wsh().unwrap(), p2wsh);
// Test data are taken from the second output of
// 2ccb3a1f745eb4eefcf29391460250adda5fab78aaddb902d25d3cd97d9d8e61 transaction
let data = hex!("aa21a9ed20280f53f2d21663cac89e6bd2ad19edbabb048cda08e73ed19e9268d0afea2a");
- let op_return = ScriptBuf::new_op_return(data);
+ let op_return = ScriptPubKeyBuf::new_op_return(data);
assert!(op_return.is_op_return());
assert_eq!(
op_return.to_hex_string_no_length_prefix(),
@@ -264,6 +264,8 @@ fn script_generators() {
#[test]
fn script_builder_verify() {
+ type Builder = super::Builder<primitives::script::ScriptPubKeyTag>;
+
let simple = Builder::new().push_verify().into_script();
assert_eq!(simple.to_hex_string_no_length_prefix(), "69");
let simple2 = Builder::from(vec![]).push_verify().into_script();
@@ -417,15 +419,15 @@ fn script_hashes() {
#[test]
fn provably_unspendable() {
// p2pk
- assert!(!ScriptBuf::from_hex_no_length_prefix("410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac").unwrap().is_op_return());
- assert!(!ScriptBuf::from_hex_no_length_prefix("4104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac").unwrap().is_op_return());
+ assert!(!ScriptPubKeyBuf::from_hex_no_length_prefix("410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac").unwrap().is_op_return());
+ assert!(!ScriptPubKeyBuf::from_hex_no_length_prefix("4104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac").unwrap().is_op_return());
// p2pkhash
- assert!(!ScriptBuf::from_hex_no_length_prefix(
+ assert!(!ScriptPubKeyBuf::from_hex_no_length_prefix(
"76a914ee61d57ab51b9d212335b1dba62794ac20d2bcf988ac"
)
.unwrap()
.is_op_return());
- assert!(ScriptBuf::from_hex_no_length_prefix(
+ assert!(ScriptPubKeyBuf::from_hex_no_length_prefix(
"6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87"
)
.unwrap()
@@ -434,33 +436,33 @@ fn provably_unspendable() {
#[test]
fn op_return() {
- assert!(ScriptBuf::from_hex_no_length_prefix(
+ assert!(ScriptPubKeyBuf::from_hex_no_length_prefix(
"6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87"
)
.unwrap()
.is_op_return());
- assert!(!ScriptBuf::from_hex_no_length_prefix(
+ assert!(!ScriptPubKeyBuf::from_hex_no_length_prefix(
"76a914ee61d57ab51b9d212335b1dba62794ac20d2bcf988ac"
)
.unwrap()
.is_op_return());
- assert!(!ScriptBuf::from_hex_no_length_prefix("").unwrap().is_op_return());
+ assert!(!ScriptPubKeyBuf::from_hex_no_length_prefix("").unwrap().is_op_return());
}
#[test]
fn standard_op_return() {
- assert!(ScriptBuf::from_hex_no_length_prefix(
+ assert!(ScriptPubKeyBuf::from_hex_no_length_prefix(
"6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87"
)
.unwrap()
.is_standard_op_return());
- assert!(ScriptBuf::from_hex_no_length_prefix("6a48656c6c6f2c2074686973206973206d7920666972737420636f6e747269627574696f6e20746f207275737420626974636f696e2e20506c6561736520617070726f7665206d79205052206672656e")
+ assert!(ScriptPubKeyBuf::from_hex_no_length_prefix("6a48656c6c6f2c2074686973206973206d7920666972737420636f6e747269627574696f6e20746f207275737420626974636f696e2e20506c6561736520617070726f7665206d79205052206672656e")
.unwrap()
.is_standard_op_return());
- assert!(ScriptBuf::from_hex_no_length_prefix("6a48656c6c6f2c2074686973206973206d7920666972737420636f6e747269627574696f6e20746f207275737420626974636f696e2e20506c6561736520617070726f7665206d79205052206672656e21")
+ assert!(ScriptPubKeyBuf::from_hex_no_length_prefix("6a48656c6c6f2c2074686973206973206d7920666972737420636f6e747269627574696f6e20746f207275737420626974636f696e2e20506c6561736520617070726f7665206d79205052206672656e21")
.unwrap()
.is_standard_op_return());
- assert!(!ScriptBuf::from_hex_no_length_prefix("6a48656c6c6f2c2074686973206973206d7920666972737420636f6e747269627574696f6e20746f207275737420626974636f696e2e20506c6561736520617070726f7665206d79205052206672656e21524f42")
+ assert!(!ScriptPubKeyBuf::from_hex_no_length_prefix("6a48656c6c6f2c2074686973206973206d7920666972737420636f6e747269627574696f6e20746f207275737420626974636f696e2e20506c6561736520617070726f7665206d79205052206672656e21524f42")
.unwrap()
.is_standard_op_return());
}
@@ -470,44 +472,44 @@ fn multisig() {
// First multisig? 1-of-2
// In block 164467, txid 60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1
assert!(
- ScriptBuf::from_hex_no_length_prefix("514104cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4410461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af52ae")
+ ScriptPubKeyBuf::from_hex_no_length_prefix("514104cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4410461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af52ae")
.unwrap()
.is_multisig()
);
// 2-of-2
assert!(
- ScriptBuf::from_hex_no_length_prefix("5221021c4ac2ecebc398e390e07f045aac5cc421f82f0739c1ce724d3d53964dc6537d21023a2e9155e0b62f76737605504819a2b4e5ce20653f6c397d7a178ae42ba702f452ae")
+ ScriptPubKeyBuf::from_hex_no_length_prefix("5221021c4ac2ecebc398e390e07f045aac5cc421f82f0739c1ce724d3d53964dc6537d21023a2e9155e0b62f76737605504819a2b4e5ce20653f6c397d7a178ae42ba702f452ae")
.unwrap()
.is_multisig()
);
// Extra opcode after OP_CHECKMULTISIG
assert!(
- !ScriptBuf::from_hex_no_length_prefix("5221021c4ac2ecebc398e390e07f045aac5cc421f82f0739c1ce724d3d53964dc6537d21023a2e9155e0b62f76737605504819a2b4e5ce20653f6c397d7a178ae42ba702f452ae52")
+ !ScriptPubKeyBuf::from_hex_no_length_prefix("5221021c4ac2ecebc398e390e07f045aac5cc421f82f0739c1ce724d3d53964dc6537d21023a2e9155e0b62f76737605504819a2b4e5ce20653f6c397d7a178ae42ba702f452ae52")
.unwrap()
.is_multisig()
);
// Required sigs > num pubkeys
assert!(
- !ScriptBuf::from_hex_no_length_prefix("5321021c4ac2ecebc398e390e07f045aac5cc421f82f0739c1ce724d3d53964dc6537d21023a2e9155e0b62f76737605504819a2b4e5ce20653f6c397d7a178ae42ba702f452ae")
+ !ScriptPubKeyBuf::from_hex_no_length_prefix("5321021c4ac2ecebc398e390e07f045aac5cc421f82f0739c1ce724d3d53964dc6537d21023a2e9155e0b62f76737605504819a2b4e5ce20653f6c397d7a178ae42ba702f452ae")
.unwrap()
.is_multisig()
);
// Num pubkeys != pushnum
assert!(
- !ScriptBuf::from_hex_no_length_prefix("5221021c4ac2ecebc398e390e07f045aac5cc421f82f0739c1ce724d3d53964dc6537d21023a2e9155e0b62f76737605504819a2b4e5ce20653f6c397d7a178ae42ba702f453ae")
+ !ScriptPubKeyBuf::from_hex_no_length_prefix("5221021c4ac2ecebc398e390e07f045aac5cc421f82f0739c1ce724d3d53964dc6537d21023a2e9155e0b62f76737605504819a2b4e5ce20653f6c397d7a178ae42ba702f453ae")
.unwrap()
.is_multisig()
);
// Taproot hash from another test
- assert!(!ScriptBuf::from_hex_no_length_prefix(
+ assert!(!ScriptPubKeyBuf::from_hex_no_length_prefix(
"20d85a959b0290bf19bb89ed43c916be835475d013da4b362117393e25a48229b8ac"
)
.unwrap()
.is_multisig());
// OP_RETURN from another test
- assert!(!ScriptBuf::from_hex_no_length_prefix(
+ assert!(!ScriptPubKeyBuf::from_hex_no_length_prefix(
"6aa9149eb21980dc9d413d8eac27314938b9da920ee53e87"
)
.unwrap()
@@ -573,31 +575,33 @@ fn script_buf_collect() {
#[test]
fn script_p2sh_p2p2k_template() {
// random outputs I picked out of the mempool
- assert!(ScriptBuf::from_hex_no_length_prefix(
+ assert!(ScriptPubKeyBuf::from_hex_no_length_prefix(
"76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac"
)
.unwrap()
.is_p2pkh());
- assert!(!ScriptBuf::from_hex_no_length_prefix(
+ assert!(!ScriptPubKeyBuf::from_hex_no_length_prefix(
"76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac"
)
.unwrap()
.is_p2sh());
- assert!(!ScriptBuf::from_hex_no_length_prefix(
+ assert!(!ScriptPubKeyBuf::from_hex_no_length_prefix(
"76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ad"
)
.unwrap()
.is_p2pkh());
- assert!(!ScriptBuf::from_hex_no_length_prefix("").unwrap().is_p2pkh());
- assert!(ScriptBuf::from_hex_no_length_prefix("a914acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87")
- .unwrap()
- .is_p2sh());
- assert!(!ScriptBuf::from_hex_no_length_prefix(
+ assert!(!ScriptPubKeyBuf::from_hex_no_length_prefix("").unwrap().is_p2pkh());
+ assert!(ScriptPubKeyBuf::from_hex_no_length_prefix(
+ "a914acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87"
+ )
+ .unwrap()
+ .is_p2sh());
+ assert!(!ScriptPubKeyBuf::from_hex_no_length_prefix(
"a914acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87"
)
.unwrap()
.is_p2pkh());
- assert!(!ScriptBuf::from_hex_no_length_prefix(
+ assert!(!ScriptPubKeyBuf::from_hex_no_length_prefix(
"a314acc91e6fef5c7f24e5c8b3f11a664aa8f1352ffd87"
)
.unwrap()
@@ -606,12 +610,12 @@ fn script_p2sh_p2p2k_template() {
#[test]
fn script_p2pk() {
- assert!(ScriptBuf::from_hex_no_length_prefix(
+ assert!(ScriptPubKeyBuf::from_hex_no_length_prefix(
"21021aeaf2f8638a129a3156fbe7e5ef635226b0bafd495ff03afe2c843d7e3a4b51ac"
)
.unwrap()
.is_p2pk());
- assert!(ScriptBuf::from_hex_no_length_prefix("410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac").unwrap().is_p2pk());
+ assert!(ScriptPubKeyBuf::from_hex_no_length_prefix("410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac").unwrap().is_p2pk());
}
#[test]
@@ -619,7 +623,7 @@ 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 expected_without = ScriptBuf::from_hex_no_length_prefix(
+ let expected_without = ScriptPubKeyBuf::from_hex_no_length_prefix(
"0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64",
)
.unwrap();
@@ -628,21 +632,23 @@ fn p2sh_p2wsh_conversion() {
// p2sh
let redeem_script = ScriptBuf::from_hex_no_length_prefix("0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8").unwrap();
- let expected_p2shout =
- ScriptBuf::from_hex_no_length_prefix("a91491b24bf9f5288532960ac687abb035127b1d28a587")
- .unwrap();
+ let expected_p2shout = ScriptPubKeyBuf::from_hex_no_length_prefix(
+ "a91491b24bf9f5288532960ac687abb035127b1d28a587",
+ )
+ .unwrap();
assert!(redeem_script.to_p2sh().unwrap().is_p2sh());
assert_eq!(redeem_script.to_p2sh().unwrap(), expected_p2shout);
// p2sh-p2wsh
let witness_script = ScriptBuf::from_hex_no_length_prefix("410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8ac").unwrap();
- let expected_without = ScriptBuf::from_hex_no_length_prefix(
+ let expected_without = ScriptPubKeyBuf::from_hex_no_length_prefix(
"0020b95237b48faaa69eb078e1170be3b5cbb3fddf16d0a991e14ad274f7b33a4f64",
)
.unwrap();
- let expected_out =
- ScriptBuf::from_hex_no_length_prefix("a914f386c2ba255cc56d20cfa6ea8b062f8b5994551887")
- .unwrap();
+ let expected_out = ScriptPubKeyBuf::from_hex_no_length_prefix(
+ "a914f386c2ba255cc56d20cfa6ea8b062f8b5994551887",
+ )
+ .unwrap();
assert!(witness_script.to_p2sh().unwrap().is_p2sh());
assert_eq!(witness_script.to_p2wsh().unwrap(), expected_without);
assert_eq!(witness_script.to_p2wsh().unwrap().to_p2sh().unwrap(), expected_out);
@@ -736,11 +742,11 @@ fn script_ord() {
#[test]
#[cfg(feature = "bitcoinconsensus")]
fn bitcoinconsensus() {
- use crate::consensus_validation::ScriptExt as _;
+ use crate::consensus_validation::ScriptPubKeyExt as _;
// a random SegWit transaction from the blockchain using native SegWit
let spent_bytes = hex!("0020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d");
- let spent = Script::from_bytes(&spent_bytes);
+ let spent = ScriptPubKey::from_bytes(&spent_bytes);
let spending = hex!("010000000001011f97548fbbe7a0db7588a66e18d803d0089315aa7d4cc28360b6ec50ef36718a0100000000ffffffff02df1776000000000017a9146c002a686959067f4866b8fb493ad7970290ab728757d29f0000000000220020701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d04004730440220565d170eed95ff95027a69b313758450ba84a01224e1f7f130dda46e94d13f8602207bdd20e307f062594022f12ed5017bbf4a055a06aea91c10110a0e3bb23117fc014730440220647d2dc5b15f60bc37dc42618a370b2a1490293f9e5c8464f53ec4fe1dfe067302203598773895b4b16d37485cbe21b337f4e4b650739880098c592553add7dd4355016952210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae00000000");
spent.verify(0, Amount::from_sat_u32(18393430), &spending).unwrap();
}
@@ -994,7 +1000,7 @@ fn shortest_witness_program() {
let version = WitnessVersion::V15; // Arbitrary version number, intentionally not 0 or 1.
let p = WitnessProgram::new(version, &bytes).expect("failed to create witness program");
- let script = ScriptBuf::new_witness_program(&p);
+ let script = ScriptPubKeyBuf::new_witness_program(&p);
assert_eq!(script.witness_version(), Some(version));
}
@@ -1005,7 +1011,7 @@ fn longest_witness_program() {
let version = WitnessVersion::V16; // Arbitrary version number, intentionally not 0 or 1.
let p = WitnessProgram::new(version, &bytes).expect("failed to create witness program");
- let script = ScriptBuf::new_witness_program(&p);
+ let script = ScriptPubKeyBuf::new_witness_program(&p);
assert_eq!(script.witness_version(), Some(version));
}
diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs
index b61b7ac9..0b067b16 100644
--- a/bitcoin/src/blockdata/transaction.rs
+++ b/bitcoin/src/blockdata/transaction.rs
@@ -22,7 +22,8 @@ use crate::consensus::{self, encode, Decodable, Encodable};
use crate::locktime::absolute::{self, Height, MedianTimePast};
use crate::prelude::{Borrow, Vec};
use crate::script::{
- GenericScriptExt as _, GenericScriptExtPriv as _, Script, ScriptBuf, ScriptExt as _,
+ GenericScriptExt as _, GenericScriptExtPriv as _, Script, ScriptPubKey, ScriptPubKeyBuf,
+ ScriptPubKeyExt as _,
};
#[cfg(doc)]
use crate::sighash::{EcdsaSighashType, TapSighashType};
@@ -184,7 +185,7 @@ internal_macros::define_extension_trait! {
/// To use a custom value, use [`minimal_non_dust_custom`].
///
/// [`minimal_non_dust_custom`]: TxOut::minimal_non_dust_custom
- fn minimal_non_dust(script_pubkey: ScriptBuf) -> TxOut {
+ fn minimal_non_dust(script_pubkey: ScriptPubKeyBuf) -> TxOut {
TxOut { value: script_pubkey.minimal_non_dust(), script_pubkey }
}
@@ -199,14 +200,14 @@ internal_macros::define_extension_trait! {
/// To use the default Bitcoin Core value, use [`minimal_non_dust`].
///
/// [`minimal_non_dust`]: TxOut::minimal_non_dust
- fn minimal_non_dust_custom(script_pubkey: ScriptBuf, dust_relay_fee: FeeRate) -> Option<TxOut> {
+ fn minimal_non_dust_custom(script_pubkey: ScriptPubKeyBuf, dust_relay_fee: FeeRate) -> Option<TxOut> {
Some(TxOut { value: script_pubkey.minimal_non_dust_custom(dust_relay_fee)?, script_pubkey })
}
}
}
/// Returns the total number of bytes that this script pubkey would contribute to a transaction.
-fn size_from_script_pubkey(script_pubkey: &Script) -> usize {
+fn size_from_script_pubkey(script_pubkey: &ScriptPubKey) -> usize {
let len = script_pubkey.len();
Amount::SIZE + compact_size::encoded_size(len) + len
}
@@ -511,7 +512,10 @@ impl TransactionExtPriv for Transaction {
where
S: FnMut(&OutPoint) -> Option<TxOut>,
{
- fn count_sigops_with_witness_program(witness: &Witness, witness_program: &Script) -> usize {
+ fn count_sigops_with_witness_program(
+ witness: &Witness,
+ witness_program: &ScriptPubKey,
+ ) -> usize {
if witness_program.is_p2wpkh() {
1
} else if witness_program.is_p2wsh() {
@@ -530,9 +534,11 @@ impl TransactionExtPriv for Transaction {
&prevout.script_pubkey
} else if prevout.script_pubkey.is_p2sh() && script_sig.is_push_only() {
// If prevout is P2SH and scriptSig is push only
- // then we wrap the last push (redeemScript) in a Script
+ // then we wrap the last push (redeemScript) in a Script; we use a ScriptPubKey to keep our types
+ // consistent although strictly speaking it should
+ // be a RedeemScript.
if let Some(push_bytes) = script_sig.last_pushdata() {
- Script::from_bytes(push_bytes.as_bytes())
+ ScriptPubKey::from_bytes(push_bytes.as_bytes())
} else {
return 0;
}
@@ -1494,7 +1500,7 @@ mod tests {
tx.inputs[0].script_sig = ScriptSigBuf::new();
assert_eq!(old_ntxid, tx.compute_ntxid());
// changing pks does
- tx.outputs[0].script_pubkey = ScriptBuf::new();
+ tx.outputs[0].script_pubkey = ScriptPubKeyBuf::new();
assert!(old_ntxid != tx.compute_ntxid());
}
diff --git a/bitcoin/src/blockdata/witness.rs b/bitcoin/src/blockdata/witness.rs
index d4de1db1..ad820601 100644
--- a/bitcoin/src/blockdata/witness.rs
+++ b/bitcoin/src/blockdata/witness.rs
@@ -209,7 +209,7 @@ internal_macros::define_extension_trait! {
/// Unlike the Taproot case, we do no validation to determine whether this is a
/// 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 [`Script::is_p2wsh`] on the output's script.
+ /// use [`crate::script::GenericScriptExt::is_p2wsh`] on the output's script.
fn witness_script(&self) -> Option<&Script> { self.last().map(Script::from_bytes) }
}
diff --git a/bitcoin/src/consensus_validation.rs b/bitcoin/src/consensus_validation.rs
index aee97852..9d1c0beb 100644
--- a/bitcoin/src/consensus_validation.rs
+++ b/bitcoin/src/consensus_validation.rs
@@ -14,7 +14,7 @@ use crate::consensus::encode;
#[cfg(doc)]
use crate::consensus_validation;
use crate::internal_macros::define_extension_trait;
-use crate::script::Script;
+use crate::script::ScriptPubKey;
use crate::transaction::{OutPoint, Transaction, TxOut};
/// Verifies spend of an input script.
@@ -30,7 +30,7 @@ use crate::transaction::{OutPoint, Transaction, TxOut};
///
/// [`bitcoinconsensus::VERIFY_ALL_PRE_TAPROOT`]: https://docs.rs/bitcoinconsensus/0.106.0+26.0/bitcoinconsensus/constant.VERIFY_ALL_PRE_TAPROOT.html
pub fn verify_script(
- script: &Script,
+ script: &ScriptPubKey,
index: usize,
amount: Amount,
spending_tx: &[u8],
@@ -55,7 +55,7 @@ pub fn verify_script(
///
/// [`bitcoinconsensus::VERIFY_ALL_PRE_TAPROOT`]: https://docs.rs/bitcoinconsensus/0.106.0+26.0/bitcoinconsensus/constant.VERIFY_ALL_PRE_TAPROOT.html
pub fn verify_script_with_flags<F: Into<u32>>(
- script: &Script,
+ script: &ScriptPubKey,
index: usize,
amount: Amount,
spending_tx: &[u8],
@@ -118,8 +118,8 @@ where
}
define_extension_trait! {
- /// Extension functionality to add validation support to the [`Script`] type.
- pub trait ScriptExt impl for Script {
+ /// Extension functionality to add validation support to the [`ScriptPubKey`] type.
+ pub trait ScriptPubKeyExt impl for ScriptPubKey {
/// Verifies spend of an input script.
///
/// Shorthand for [`Self::verify_with_flags`] with flag [`bitcoinconsensus::VERIFY_ALL_PRE_TAPROOT`].
@@ -203,7 +203,7 @@ impl TransactionExt for Transaction {
mod sealed {
pub trait Sealed {}
- impl Sealed for super::Script {}
+ impl Sealed for super::ScriptPubKey {}
impl Sealed for super::Transaction {}
}
diff --git a/bitcoin/src/crypto/ecdsa.rs b/bitcoin/src/crypto/ecdsa.rs
index e6d012f7..62be3299 100644
--- a/bitcoin/src/crypto/ecdsa.rs
+++ b/bitcoin/src/crypto/ecdsa.rs
@@ -17,7 +17,7 @@ use io::Write;
use crate::prelude::{DisplayHex, Vec};
use crate::script::PushBytes;
#[cfg(doc)]
-use crate::script::ScriptBufExt as _;
+use crate::script::ScriptPubKeyBufExt as _;
use crate::sighash::{EcdsaSighashType, NonStandardSighashTypeError};
const MAX_SIG_LEN: usize = 73;
diff --git a/bitcoin/src/crypto/sighash.rs b/bitcoin/src/crypto/sighash.rs
index 6cecddcb..92d060c8 100644
--- a/bitcoin/src/crypto/sighash.rs
+++ b/bitcoin/src/crypto/sighash.rs
@@ -22,11 +22,11 @@ use io::Write;
use crate::consensus::{encode, Encodable};
use crate::prelude::{Borrow, BorrowMut, String, ToOwned};
-use crate::script::ScriptExt as _;
+use crate::script::GenericScriptExt as _;
use crate::taproot::{LeafVersion, TapLeafHash, TapLeafTag, TAPROOT_ANNEX_PREFIX};
use crate::transaction::TransactionExt as _;
use crate::witness::Witness;
-use crate::{transaction, Amount, Script, Sequence, Transaction, TxOut};
+use crate::{transaction, Amount, Script, ScriptPubKey, Sequence, Transaction, TxOut};
/// Used for signature hash for invalid use of SIGHASH_SINGLE.
#[rustfmt::skip]
@@ -871,10 +871,10 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
///
/// `script_pubkey` is the `scriptPubkey` (native SegWit) of the spend transaction
/// ([`TxOut::script_pubkey`]) or the `redeemScript` (wrapped SegWit).
- pub fn p2wpkh_signature_hash(
+ pub fn p2wpkh_signature_hash<T>(
&mut self,
input_index: usize,
- script_pubkey: &Script,
+ script_pubkey: &crate::script::GenericScript<T>,
value: Amount,
sighash_type: EcdsaSighashType,
) -> Result<SegwitV0Sighash, P2wpkhError> {
@@ -937,11 +937,11 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
///
/// This function can't handle the SIGHASH_SINGLE bug internally, so it returns [`EncodeSigningDataResult`]
/// that must be handled by the caller (see [`EncodeSigningDataResult::is_sighash_single_bug`]).
- pub fn legacy_encode_signing_data_to<W: Write + ?Sized, U: Into<u32>>(
+ pub fn legacy_encode_signing_data_to<W: Write + ?Sized, U: Into<u32>, T>(
&self,
writer: &mut W,
input_index: usize,
- script_pubkey: &Script,
+ script_pubkey: &crate::script::GenericScript<T>,
sighash_type: U,
) -> EncodeSigningDataResult<SigningDataError<transaction::InputsIndexError>> {
// Validate input_index.
@@ -962,11 +962,11 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
return EncodeSigningDataResult::SighashSingleBug;
}
- fn encode_signing_data_to_inner<W: Write + ?Sized>(
+ fn encode_signing_data_to_inner<W: Write + ?Sized, T>(
self_: &Transaction,
writer: &mut W,
input_index: usize,
- script_pubkey: &Script,
+ script_pubkey: &crate::script::GenericScript<T>,
sighash_type: u32,
) -> Result<(), io::Error> {
use crate::consensus::encode::WriteExt;
@@ -988,7 +988,7 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
if n == input_index {
script_pubkey.consensus_encode(writer)?;
} else {
- Script::new().consensus_encode(writer)?;
+ ScriptPubKey::new().consensus_encode(writer)?;
}
if n != input_index
&& (sighash == EcdsaSighashType::Single
@@ -1058,10 +1058,10 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
/// Does NOT attempt to support OP_CODESEPARATOR. In general this would require evaluating
/// `script_pubkey` to determine which separators get evaluated and which don't, which we don't
/// have the information to determine.
- pub fn legacy_signature_hash(
+ pub fn legacy_signature_hash<T>(
&self,
input_index: usize,
- script_pubkey: &Script,
+ script_pubkey: &crate::script::GenericScript<T>,
sighash_type: u32,
) -> Result<LegacySighash, transaction::InputsIndexError> {
let mut engine = LegacySighash::engine();
@@ -1537,12 +1537,12 @@ mod tests {
use super::*;
use crate::consensus::deserialize;
use crate::locktime::absolute;
- use crate::script::{GenericScriptBufExt as _, ScriptBuf};
+ use crate::script::{GenericScriptBufExt as _, ScriptBuf, ScriptPubKey, ScriptPubKeyBuf};
use crate::TxIn;
extern crate serde_json;
- const DUMMY_TXOUT: TxOut = TxOut { value: Amount::MIN, script_pubkey: ScriptBuf::new() };
+ const DUMMY_TXOUT: TxOut = TxOut { value: Amount::MIN, script_pubkey: ScriptPubKeyBuf::new() };
#[test]
fn sighash_single_bug() {
@@ -1553,7 +1553,7 @@ mod tests {
inputs: vec![TxIn::EMPTY_COINBASE, TxIn::EMPTY_COINBASE],
outputs: vec![DUMMY_TXOUT],
};
- let script = ScriptBuf::new();
+ let script = ScriptPubKeyBuf::new();
let cache = SighashCache::new(&tx);
let sighash_single = 3;
@@ -1583,7 +1583,7 @@ mod tests {
expected_result: &str,
) {
let tx: Transaction = deserialize(&Vec::from_hex(tx).unwrap()[..]).unwrap();
- let script = ScriptBuf::from(Vec::from_hex(script).unwrap());
+ let script = ScriptPubKeyBuf::from(Vec::from_hex(script).unwrap());
let mut raw_expected = Vec::from_hex(expected_result).unwrap();
raw_expected.reverse();
let bytes = <[u8; 32]>::try_from(&raw_expected[..]).unwrap();
@@ -1790,7 +1790,7 @@ mod tests {
}))
);
assert_eq!(
- c.legacy_signature_hash(10, Script::new(), 0u32),
+ c.legacy_signature_hash(10, ScriptPubKey::new(), 0u32),
Err(InputsIndexError(IndexOutOfBoundsError {
index: 10,
length: 1
@@ -1886,7 +1886,7 @@ mod tests {
#[derive(serde::Deserialize)]
struct UtxoSpent {
#[serde(rename = "scriptPubKey")]
- script_pubkey: ScriptBuf,
+ script_pubkey: ScriptPubKeyBuf,
#[serde(rename = "amountSats")]
#[serde(with = "crate::amount::serde::as_sat")]
value: Amount,
@@ -2091,9 +2091,10 @@ mod tests {
),
).unwrap();
- let spk =
- ScriptBuf::from_hex_no_length_prefix("00141d0f172a0ecb48aee1be1f2687d2963ae33f71a1")
- .unwrap();
+ let spk = ScriptPubKeyBuf::from_hex_no_length_prefix(
+ "00141d0f172a0ecb48aee1be1f2687d2963ae33f71a1",
+ )
+ .unwrap();
let value = Amount::from_sat_u32(600_000_000);
let mut cache = SighashCache::new(&tx);
@@ -2133,14 +2134,15 @@ mod tests {
),
).unwrap();
- let redeem_script =
- ScriptBuf::from_hex_no_length_prefix("001479091972186c449eb1ded22b78e40d009bdf0089")
- .unwrap();
+ let spk = ScriptPubKeyBuf::from_hex_no_length_prefix(
+ "001479091972186c449eb1ded22b78e40d009bdf0089",
+ )
+ .unwrap();
let value = Amount::from_sat_u32(1_000_000_000);
let mut cache = SighashCache::new(&tx);
assert_eq!(
- cache.p2wpkh_signature_hash(0, &redeem_script, value, EcdsaSighashType::All).unwrap(),
+ cache.p2wpkh_signature_hash(0, &spk, value, EcdsaSighashType::All).unwrap(),
"64f3b0f4dd2bb3aa1ce8566d220cc74dda9df97d8490cc81d89d735c92e59fb6"
.parse::<SegwitV0Sighash>()
.unwrap(),
diff --git a/bitcoin/src/lib.rs b/bitcoin/src/lib.rs
index e8d5afd7..dcdb1ea4 100644
--- a/bitcoin/src/lib.rs
+++ b/bitcoin/src/lib.rs
@@ -114,12 +114,12 @@ pub mod ext {
pub use crate::{
block::{BlockUncheckedExt as _, BlockCheckedExt as _, HeaderExt as _},
pow::CompactTargetExt as _,
- script::{GenericScriptExt as _, GenericScriptBufExt as _, ScriptExt as _, ScriptBufExt as _, ScriptSigExt as _},
+ script::{GenericScriptExt as _, GenericScriptBufExt as _, ScriptExt as _, ScriptPubKeyExt as _, ScriptPubKeyBufExt as _, ScriptSigExt as _},
transaction::{TxidExt as _, WtxidExt as _, OutPointExt as _, TxInExt as _, TxOutExt as _, TransactionExt as _},
witness::WitnessExt as _,
};
#[cfg(feature = "bitcoinconsensus")]
- pub use crate::consensus_validation::{ScriptExt as _, TransactionExt as _};
+ pub use crate::consensus_validation::{ScriptPubKeyExt as _, TransactionExt as _};
}
#[macro_use]
pub mod address;
@@ -152,7 +152,7 @@ pub use primitives::{
},
merkle_tree::{TxMerkleNode, WitnessMerkleNode},
pow::CompactTarget, // No `pow` module outside of `primitives`.
- script::{Script, ScriptBuf, ScriptSig, ScriptSigBuf},
+ script::{Script, ScriptBuf, ScriptPubKey, ScriptPubKeyBuf, ScriptSig, ScriptSigBuf},
sequence::{self, Sequence}, // No `sequence` module outside of `primitives`.
transaction::{OutPoint, Transaction, TxIn, TxOut, Txid, Version as TransactionVersion, Wtxid},
witness::Witness,
diff --git a/bitcoin/src/psbt/mod.rs b/bitcoin/src/psbt/mod.rs
index a0daffe9..5ad068fa 100644
--- a/bitcoin/src/psbt/mod.rs
+++ b/bitcoin/src/psbt/mod.rs
@@ -26,7 +26,7 @@ use crate::crypto::key::{PrivateKey, PublicKey};
use crate::crypto::{ecdsa, taproot};
use crate::key::{TapTweak, XOnlyPublicKey};
use crate::prelude::{btree_map, BTreeMap, BTreeSet, Borrow, Box, Vec};
-use crate::script::ScriptExt as _;
+use crate::script::{GenericScriptExt as _, ScriptPubKeyExt as _};
use crate::sighash::{self, EcdsaSighashType, Prevouts, SighashCache};
use crate::transaction::{self, Transaction, TransactionExt as _, TxOut};
use crate::{Amount, FeeRate, TapLeafHash, TapSighash, TapSighashType};
@@ -1332,7 +1332,7 @@ mod tests {
use {
crate::bip32::Fingerprint,
crate::locktime,
- crate::script::ScriptBufExt as _,
+ crate::script::ScriptPubKeyBufExt as _,
crate::witness_version::WitnessVersion,
crate::WitnessProgram,
secp256k1::{All, SecretKey},
@@ -1343,7 +1343,7 @@ mod tests {
use crate::locktime::absolute;
use crate::network::NetworkKind;
use crate::psbt::serialize::{Deserialize, Serialize};
- use crate::script::{GenericScriptBufExt as _, ScriptBuf, ScriptSigBuf};
+ use crate::script::{GenericScriptBufExt as _, ScriptBuf, ScriptPubKeyBuf, ScriptSigBuf};
use crate::transaction::{self, OutPoint, TxIn};
use crate::witness::Witness;
use crate::Sequence;
@@ -1376,7 +1376,7 @@ mod tests {
}],
outputs: vec![TxOut {
value: Amount::from_sat(output).unwrap(),
- script_pubkey: ScriptBuf::from_hex_no_length_prefix(
+ script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix(
"a9143545e6e33b832c47050f24d3eeb93c9c03948bc787",
)
.unwrap(),
@@ -1390,7 +1390,7 @@ mod tests {
inputs: vec![Input {
witness_utxo: Some(TxOut {
value: Amount::from_sat(input).unwrap(),
- script_pubkey: ScriptBuf::from_hex_no_length_prefix(
+ script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix(
"a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587",
)
.unwrap(),
@@ -1553,14 +1553,14 @@ mod tests {
outputs: vec![
TxOut {
value: Amount::from_sat_u32(99_999_699),
- script_pubkey: ScriptBuf::from_hex_no_length_prefix(
+ script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix(
"76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac",
)
.unwrap(),
},
TxOut {
value: Amount::from_sat_u32(100_000_000),
- script_pubkey: ScriptBuf::from_hex_no_length_prefix(
+ script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix(
"a9143545e6e33b832c47050f24d3eeb93c9c03948bc787",
)
.unwrap(),
@@ -1628,7 +1628,7 @@ mod tests {
}],
outputs: vec![TxOut {
value: Amount::from_sat(190_303_501_938).unwrap(),
- script_pubkey: ScriptBuf::from_hex_no_length_prefix(
+ script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix(
"a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587",
)
.unwrap(),
@@ -1680,7 +1680,7 @@ mod tests {
non_witness_utxo: Some(tx),
witness_utxo: Some(TxOut {
value: Amount::from_sat(190_303_501_938).unwrap(),
- script_pubkey: ScriptBuf::from_hex_no_length_prefix("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(),
+ script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(),
}),
sighash_type: Some("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY".parse::<PsbtSighashType>().unwrap()),
redeem_script: Some(vec![0x51].into()),
@@ -1805,11 +1805,11 @@ mod tests {
outputs: vec![
TxOut {
value: Amount::from_sat_u32(99_999_699),
- script_pubkey: ScriptBuf::from_hex_no_length_prefix("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap(),
+ script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap(),
},
TxOut {
value: Amount::from_sat_u32(100_000_000),
- script_pubkey: ScriptBuf::from_hex_no_length_prefix("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(),
+ script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(),
},
],
},
@@ -1852,11 +1852,11 @@ mod tests {
outputs: vec![
TxOut {
value: Amount::from_sat_u32(200_000_000),
- script_pubkey: ScriptBuf::from_hex_no_length_prefix("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac").unwrap(),
+ script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac").unwrap(),
},
TxOut {
value: Amount::from_sat(190_303_501_938).unwrap(),
- script_pubkey: ScriptBuf::from_hex_no_length_prefix("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(),
+ script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(),
},
],
}),
@@ -1897,7 +1897,7 @@ mod tests {
assert!(&psbt.inputs[0].final_script_sig.is_some());
let redeem_script = psbt.inputs[1].redeem_script.as_ref().unwrap();
- let expected_out = ScriptBuf::from_hex_no_length_prefix(
+ let expected_out = ScriptPubKeyBuf::from_hex_no_length_prefix(
"a9143545e6e33b832c47050f24d3eeb93c9c03948bc787",
)
.unwrap();
@@ -1945,7 +1945,7 @@ mod tests {
assert!(&psbt.inputs[1].final_script_sig.is_none());
let redeem_script = psbt.inputs[1].redeem_script.as_ref().unwrap();
- let expected_out = ScriptBuf::from_hex_no_length_prefix(
+ let expected_out = ScriptPubKeyBuf::from_hex_no_length_prefix(
"a9143545e6e33b832c47050f24d3eeb93c9c03948bc787",
)
.unwrap();
@@ -1972,7 +1972,7 @@ mod tests {
assert!(&psbt.inputs[0].final_script_sig.is_none());
let redeem_script = psbt.inputs[0].redeem_script.as_ref().unwrap();
- let expected_out = ScriptBuf::from_hex_no_length_prefix(
+ let expected_out = ScriptPubKeyBuf::from_hex_no_length_prefix(
"a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87",
)
.unwrap();
@@ -2166,11 +2166,11 @@ mod tests {
outputs: vec![
TxOut {
value: Amount::from_sat_u32(99_999_699),
- script_pubkey: ScriptBuf::from_hex_no_length_prefix("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap(),
+ script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap(),
},
TxOut {
value: Amount::from_sat_u32(100_000_000),
- script_pubkey: ScriptBuf::from_hex_no_length_prefix("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(),
+ script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(),
},
],
},
@@ -2213,11 +2213,11 @@ mod tests {
outputs: vec![
TxOut {
value: Amount::from_sat_u32(200_000_000),
- script_pubkey: ScriptBuf::from_hex_no_length_prefix("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac").unwrap(),
+ script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac").unwrap(),
},
TxOut {
value: Amount::from_sat(190_303_501_938).unwrap(),
- script_pubkey: ScriptBuf::from_hex_no_length_prefix("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(),
+ script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(),
},
],
}),
@@ -2464,11 +2464,11 @@ mod tests {
outputs: vec![
TxOut {
value: output_0_val,
- script_pubkey: ScriptBuf::new()
+ script_pubkey: ScriptPubKeyBuf::new()
},
TxOut {
value: output_1_val,
- script_pubkey: ScriptBuf::new()
+ script_pubkey: ScriptPubKeyBuf::new()
},
],
},
@@ -2503,11 +2503,11 @@ mod tests {
outputs: vec![
TxOut {
value: prev_output_val,
- script_pubkey: ScriptBuf::new()
+ script_pubkey: ScriptPubKeyBuf::new()
},
TxOut {
value: Amount::from_sat(190_303_501_938).unwrap(),
- script_pubkey: ScriptBuf::new()
+ script_pubkey: ScriptPubKeyBuf::new()
},
],
}),
@@ -2553,14 +2553,14 @@ mod tests {
version: transaction::Version::TWO,
lock_time: locktime::absolute::LockTime::ZERO,
inputs: vec![TxIn::EMPTY_COINBASE],
- outputs: vec![TxOut { value: Amount::ZERO, script_pubkey: ScriptBuf::new() }],
+ outputs: vec![TxOut { value: Amount::ZERO, script_pubkey: ScriptPubKeyBuf::new() }],
};
let mut psbt = Psbt::from_unsigned_tx(tx).unwrap();
psbt.inputs[0].tap_internal_key = Some(internal_key);
psbt.inputs[0].witness_utxo = Some(transaction::TxOut {
value: Amount::from_sat_u32(10),
- script_pubkey: ScriptBuf::new_p2tr(&secp, internal_key, None),
+ script_pubkey: ScriptPubKeyBuf::new_p2tr(&secp, internal_key, None),
});
let mut key_map: HashMap<PublicKey, PrivateKey> = HashMap::new();
@@ -2586,14 +2586,14 @@ mod tests {
version: transaction::Version::TWO,
lock_time: locktime::absolute::LockTime::ZERO,
inputs: vec![TxIn::EMPTY_COINBASE],
- outputs: vec![TxOut { value: Amount::ZERO, script_pubkey: ScriptBuf::new() }],
+ outputs: vec![TxOut { value: Amount::ZERO, script_pubkey: ScriptPubKeyBuf::new() }],
};
let mut psbt = Psbt::from_unsigned_tx(tx).unwrap();
psbt.inputs[0].tap_internal_key = Some(internal_key);
psbt.inputs[0].witness_utxo = Some(transaction::TxOut {
value: Amount::from_sat_u32(10),
- script_pubkey: ScriptBuf::new_p2tr(&secp, internal_key, None),
+ script_pubkey: ScriptPubKeyBuf::new_p2tr(&secp, internal_key, None),
});
let mut xonly_key_map: HashMap<XOnlyPublicKey, PrivateKey> = HashMap::new();
@@ -2616,7 +2616,7 @@ mod tests {
version: transaction::Version::TWO,
lock_time: absolute::LockTime::ZERO,
inputs: vec![TxIn::EMPTY_COINBASE, TxIn::EMPTY_COINBASE],
- outputs: vec![TxOut { value: Amount::ZERO, script_pubkey: ScriptBuf::new() }],
+ outputs: vec![TxOut { value: Amount::ZERO, script_pubkey: ScriptPubKeyBuf::new() }],
};
let mut psbt = Psbt::from_unsigned_tx(unsigned_tx).unwrap();
@@ -2630,7 +2630,7 @@ mod tests {
// First input we can spend. See comment above on key_map for why we use defaults here.
let txout_wpkh = TxOut {
value: Amount::from_sat_u32(10),
- script_pubkey: ScriptBuf::new_p2wpkh(pk.wpubkey_hash().unwrap()),
+ script_pubkey: ScriptPubKeyBuf::new_p2wpkh(pk.wpubkey_hash().unwrap()),
};
psbt.inputs[0].witness_utxo = Some(txout_wpkh);
@@ -2642,7 +2642,7 @@ mod tests {
let unknown_prog = WitnessProgram::new(WitnessVersion::V4, &[0xaa; 34]).unwrap();
let txout_unknown_future = TxOut {
value: Amount::from_sat_u32(10),
- script_pubkey: ScriptBuf::new_witness_program(&unknown_prog),
+ script_pubkey: ScriptPubKeyBuf::new_witness_program(&unknown_prog),
};
psbt.inputs[1].witness_utxo = Some(txout_unknown_future);
diff --git a/bitcoin/src/taproot/mod.rs b/bitcoin/src/taproot/mod.rs
index 1e622200..57fa88cd 100644
--- a/bitcoin/src/taproot/mod.rs
+++ b/bitcoin/src/taproot/mod.rs
@@ -1695,7 +1695,7 @@ mod test {
use super::*;
use crate::script::GenericScriptBufExt as _;
use crate::sighash::TapSighashTag;
- use crate::{Address, KnownHrp};
+ use crate::{Address, KnownHrp, ScriptPubKeyBuf};
extern crate serde_json;
#[cfg(feature = "serde")]
@@ -2095,7 +2095,7 @@ mod test {
.unwrap();
let expected_tweak =
arr["intermediary"]["tweak"].as_str().unwrap().parse::<TapTweakHash>().unwrap();
- let expected_spk = ScriptBuf::from_hex_no_length_prefix(
+ let expected_spk = ScriptPubKeyBuf::from_hex_no_length_prefix(
arr["expected"]["scriptPubKey"].as_str().unwrap(),
)
.unwrap();
diff --git a/bitcoin/tests/bip_174.rs b/bitcoin/tests/bip_174.rs
index 730140db..3a34f996 100644
--- a/bitcoin/tests/bip_174.rs
+++ b/bitcoin/tests/bip_174.rs
@@ -13,7 +13,7 @@ use bitcoin::script::{GenericScriptBufExt as _, PushBytes};
use bitcoin::secp256k1::Secp256k1;
use bitcoin::{
absolute, script, transaction, NetworkKind, OutPoint, PrivateKey, PublicKey, ScriptBuf,
- ScriptSigBuf, Sequence, Transaction, TxIn, TxOut, Witness,
+ ScriptPubKeyBuf, ScriptSigBuf, Sequence, Transaction, TxIn, TxOut, Witness,
};
#[track_caller]
@@ -184,13 +184,13 @@ fn create_transaction() -> Transaction {
TxOut {
value: Amount::from_str_in(output_0.amount, Denomination::Bitcoin)
.expect("failed to parse amount"),
- script_pubkey: ScriptBuf::from_hex_no_length_prefix(output_0.script_pubkey)
+ script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix(output_0.script_pubkey)
.expect("failed to parse script"),
},
TxOut {
value: Amount::from_str_in(output_1.amount, Denomination::Bitcoin)
.expect("failed to parse amount"),
- script_pubkey: ScriptBuf::from_hex_no_length_prefix(output_1.script_pubkey)
+ script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix(output_1.script_pubkey)
.expect("failed to parse script"),
},
],
diff --git a/bitcoin/tests/serde.rs b/bitcoin/tests/serde.rs
index efa6ab00..2810f193 100644
--- a/bitcoin/tests/serde.rs
+++ b/bitcoin/tests/serde.rs
@@ -33,7 +33,7 @@ use bitcoin::taproot::{self, ControlBlock, LeafVersion, TapTree, TaprootBuilder}
use bitcoin::witness::Witness;
use bitcoin::{
ecdsa, transaction, Address, Amount, NetworkKind, OutPoint, PrivateKey, PublicKey, ScriptBuf,
- ScriptSigBuf, Sequence, Target, Transaction, TxIn, TxOut, Txid, Work,
+ ScriptPubKeyBuf, ScriptSigBuf, Sequence, Target, Transaction, TxIn, TxOut, Txid, Work,
};
#[test]
@@ -215,7 +215,7 @@ fn serde_regression_psbt() {
}],
outputs: vec![TxOut {
value: Amount::from_sat(190_303_501_938).unwrap(),
- script_pubkey: ScriptBuf::from_hex_no_length_prefix(
+ script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix(
"a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587",
)
.unwrap(),
@@ -265,7 +265,7 @@ fn serde_regression_psbt() {
non_witness_utxo: Some(tx),
witness_utxo: Some(TxOut {
value: Amount::from_sat(190_303_501_938).unwrap(),
- script_pubkey: ScriptBuf::from_hex_no_length_prefix("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(),
+ script_pubkey: ScriptPubKeyBuf::from_hex_no_length_prefix("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(),
}),
sighash_type: Some(PsbtSighashType::from("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY".parse::<EcdsaSighashType>().unwrap())),
redeem_script: Some(vec![0x51].into()),
diff --git a/fuzz/fuzz_targets/bitcoin/deserialize_script.rs b/fuzz/fuzz_targets/bitcoin/deserialize_script.rs
index e077fa13..d42b5914 100644
--- a/fuzz/fuzz_targets/bitcoin/deserialize_script.rs
+++ b/fuzz/fuzz_targets/bitcoin/deserialize_script.rs
@@ -1,6 +1,6 @@
use bitcoin::address::Address;
use bitcoin::consensus::encode;
-use bitcoin::script::{self, GenericScriptExt as _, ScriptExt as _};
+use bitcoin::script::{self, GenericScriptExt as _, ScriptPubKeyExt as _};
use bitcoin::{FeeRate, Network};
use bitcoin_fuzz::fuzz_utils::{consume_random_bytes, consume_u32};
use honggfuzz::fuzz;
@@ -8,7 +8,7 @@ use honggfuzz::fuzz;
fn do_test(data: &[u8]) {
let mut new_data = data;
let bytes = consume_random_bytes(&mut new_data);
- let s: Result<script::ScriptBuf, _> = encode::deserialize(bytes);
+ let s: Result<script::ScriptPubKeyBuf, _> = encode::deserialize(bytes);
if let Ok(script) = s {
let _: Result<Vec<script::Instruction>, script::Error> = script.instructions().collect();
diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs
index 1f4a31ba..e0516195 100644
--- a/primitives/src/lib.rs
+++ b/primitives/src/lib.rs
@@ -74,7 +74,7 @@ pub use self::{
block::{
Block, Checked as BlockChecked, Unchecked as BlockUnchecked, Validation as BlockValidation,
},
- script::{Script, ScriptBuf, ScriptSig, ScriptSigBuf},
+ script::{Script, ScriptBuf, ScriptPubKey, ScriptPubKeyBuf, ScriptSig, ScriptSigBuf},
transaction::{Transaction, TxIn, TxOut},
witness::Witness,
};
diff --git a/primitives/src/script/mod.rs b/primitives/src/script/mod.rs
index 80c16861..6ba0fb9b 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, ScriptSigTag, Whatever},
+ tag::{Tag, ScriptPubKeyTag, ScriptSigTag, Whatever},
};
/// Placeholder doc (will be replaced in later commit)
@@ -39,9 +39,15 @@ pub type Script = GenericScript<Whatever>;
/// Placeholder doc (will be replaced in later commit)
pub type ScriptBuf = GenericScriptBuf<Whatever>;
+/// A reference to a script public key (scriptPubKey).
+pub type ScriptPubKey = GenericScript<ScriptPubKeyTag>;
+
/// A reference to a script signature (scriptSig).
pub type ScriptSig = GenericScript<ScriptSigTag>;
+/// A script public key (scriptPubKey).
+pub type ScriptPubKeyBuf = GenericScriptBuf<ScriptPubKeyTag>;
+
/// A script signature (scriptSig).
pub type ScriptSigBuf = GenericScriptBuf<ScriptSigTag>;
@@ -85,7 +91,7 @@ impl ScriptHash {
///
/// ref: [BIP-16](https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki#user-content-520byte_limitation_on_serialized_script_size)
#[inline]
- pub fn from_script(redeem_script: &Script) -> Result<Self, RedeemScriptSizeError> {
+ pub fn from_script<T>(redeem_script: &GenericScript<T>) -> Result<Self, RedeemScriptSizeError> {
if redeem_script.len() > MAX_REDEEM_SCRIPT_SIZE {
return Err(RedeemScriptSizeError { size: redeem_script.len() });
}
@@ -101,7 +107,7 @@ impl ScriptHash {
///
/// [BIP-16]: <https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki#user-content-520byte_limitation_on_serialized_script_size>
#[inline]
- pub fn from_script_unchecked(script: &Script) -> Self {
+ pub fn from_script_unchecked<T>(script: &GenericScript<T>) -> Self {
ScriptHash(hash160::Hash::hash(script.as_bytes()))
}
}
diff --git a/primitives/src/script/tag.rs b/primitives/src/script/tag.rs
index 94eadec3..f4e2f977 100644
--- a/primitives/src/script/tag.rs
+++ b/primitives/src/script/tag.rs
@@ -18,3 +18,8 @@ impl Tag for Whatever {}
#[derive(Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub enum ScriptSigTag {}
impl Tag for ScriptSigTag {}
+
+/// A script public key (scriptPubKey).
+#[derive(Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
+pub enum ScriptPubKeyTag {}
+impl Tag for ScriptPubKeyTag {}
diff --git a/primitives/src/transaction.rs b/primitives/src/transaction.rs
index 621bd449..0152f7ed 100644
--- a/primitives/src/transaction.rs
+++ b/primitives/src/transaction.rs
@@ -36,7 +36,7 @@ use units::{Amount, Weight};
#[cfg(feature = "alloc")]
use crate::prelude::Vec;
#[cfg(feature = "alloc")]
-use crate::script::{ScriptBuf, ScriptSigBuf};
+use crate::script::{ScriptPubKeyBuf, ScriptSigBuf};
#[cfg(feature = "alloc")]
use crate::witness::Witness;
@@ -350,7 +350,7 @@ pub struct TxOut {
/// The value of the output, in satoshis.
pub value: Amount,
/// The script which must be satisfied for the output to be spent.
- pub script_pubkey: ScriptBuf,
+ pub script_pubkey: ScriptPubKeyBuf,
}
/// A reference to a transaction output.
@@ -616,7 +616,7 @@ impl<'a> Arbitrary<'a> for TxIn {
#[cfg(feature = "alloc")]
impl<'a> Arbitrary<'a> for TxOut {
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
- Ok(TxOut { value: Amount::arbitrary(u)?, script_pubkey: ScriptBuf::arbitrary(u)? })
+ Ok(TxOut { value: Amount::arbitrary(u)?, script_pubkey: ScriptPubKeyBuf::arbitrary(u)? })
}
}
@@ -691,7 +691,7 @@ mod tests {
let txout = TxOut {
value: Amount::from_sat(123_456_789).unwrap(),
- script_pubkey: ScriptBuf::new(),
+ script_pubkey: ScriptPubKeyBuf::new(),
};
let tx_orig = Transaction {
diff --git a/primitives/tests/api.rs b/primitives/tests/api.rs
index 2bb22e36..9a65e501 100644
--- a/primitives/tests/api.rs
+++ b/primitives/tests/api.rs
@@ -18,7 +18,8 @@ use bitcoin_primitives::block::{Checked, Unchecked};
use bitcoin_primitives::script::{self, ScriptHash, WScriptHash};
use bitcoin_primitives::{
absolute, block, merkle_tree, pow, relative, transaction, witness, OutPoint, Script, ScriptBuf,
- ScriptSig, ScriptSigBuf, Sequence, Transaction, TxIn, TxOut, Txid, Witness, Wtxid,
+ ScriptPubKey, ScriptPubKeyBuf, ScriptSig, ScriptSigBuf, Sequence, Transaction, TxIn, TxOut,
+ Txid, Witness, Wtxid,
};
use hashes::sha256t;
@@ -44,10 +45,12 @@ struct Structs<'a> {
h: merkle_tree::WitnessMerkleNode,
i: pow::CompactTarget,
j: &'a Script,
+ j2: &'a ScriptPubKey,
j3: &'a ScriptSig,
k: ScriptHash,
l: WScriptHash,
m: ScriptBuf,
+ m2: ScriptPubKeyBuf,
m3: ScriptSigBuf,
n: Sequence,
o: Transaction,
@@ -63,6 +66,7 @@ struct Structs<'a> {
static SCRIPT: ScriptBuf = ScriptBuf::new();
static SCRIPT_SIG: ScriptSigBuf = ScriptSigBuf::new();
+static SCRIPT_PUB_KEY: ScriptPubKeyBuf = ScriptPubKeyBuf::new();
static BYTES: [u8; 32] = [0x00; 32];
/// Public structs that derive common traits.
@@ -82,6 +86,7 @@ struct CommonTraits {
k: ScriptHash,
l: WScriptHash,
m: ScriptBuf,
+ m2: ScriptPubKeyBuf,
m3: ScriptSigBuf,
n: Sequence,
o: Transaction,
@@ -111,6 +116,7 @@ struct Clone<'a> {
k: ScriptHash,
l: WScriptHash,
m: ScriptBuf,
+ m2: ScriptPubKeyBuf,
m3: ScriptSigBuf,
n: Sequence,
o: Transaction,
@@ -141,6 +147,7 @@ struct Ord {
k: ScriptHash,
l: WScriptHash,
m: ScriptBuf,
+ m2: ScriptPubKeyBuf,
m3: ScriptSigBuf,
n: Sequence,
o: Transaction,
@@ -159,8 +166,10 @@ struct Ord {
struct Default {
a: block::Version,
b: &'static Script,
+ b2: &'static ScriptPubKey,
b3: &'static ScriptSig,
c: ScriptBuf,
+ c2: ScriptPubKeyBuf,
c3: ScriptSigBuf,
d: Sequence,
e: Witness,
@@ -217,8 +226,9 @@ fn api_can_use_modules_from_crate_root() {
fn api_can_use_types_from_crate_root() {
use bitcoin_primitives::{
Block, BlockHash, BlockHeader, BlockVersion, CompactTarget, OutPoint, Script, ScriptBuf,
- ScriptSig, ScriptSigBuf, Sequence, Transaction, TransactionVersion, TxIn, TxMerkleNode,
- TxOut, Txid, Witness, WitnessCommitment, WitnessMerkleNode, Wtxid,
+ ScriptPubKey, ScriptPubKeyBuf, ScriptSig, ScriptSigBuf, Sequence, Transaction,
+ TransactionVersion, TxIn, TxMerkleNode, TxOut, Txid, Witness, WitnessCommitment,
+ WitnessMerkleNode, Wtxid,
};
}
@@ -234,8 +244,8 @@ fn api_can_use_all_types_from_module_locktime() {
#[test]
fn api_can_use_all_types_from_module_script() {
use bitcoin_primitives::script::{
- RedeemScriptSizeError, Script, ScriptBuf, ScriptHash, ScriptSig, ScriptSigBuf, WScriptHash,
- WitnessScriptSizeError,
+ RedeemScriptSizeError, Script, ScriptBuf, ScriptHash, ScriptPubKey, ScriptPubKeyBuf,
+ ScriptSig, ScriptSigBuf, WScriptHash, WitnessScriptSizeError,
};
}
@@ -275,10 +285,12 @@ fn api_all_non_error_types_have_non_empty_debug() {
pow::CompactTarget::from_consensus(0x1d00_ffff);
SCRIPT.as_script();
SCRIPT_SIG.as_script();
+ SCRIPT_PUB_KEY.as_script();
ScriptHash::from_script(&SCRIPT).unwrap();
WScriptHash::from_script(&SCRIPT).unwrap();
SCRIPT.clone();
SCRIPT_SIG.clone();
+ SCRIPT_PUB_KEY.clone();
Sequence::arbitrary(&mut u).unwrap();
Transaction::arbitrary(&mut u).unwrap();
TxIn::arbitrary(&mut u).unwrap();
@@ -314,8 +326,10 @@ fn regression_default() {
let want = Default {
a: block::Version::NO_SOFT_FORK_SIGNALLING,
b: Script::from_bytes(&[]),
+ b2: ScriptPubKey::from_bytes(&[]),
b3: ScriptSig::from_bytes(&[]),
c: ScriptBuf::from_bytes(Vec::new()),
+ c2: ScriptPubKeyBuf::from_bytes(Vec::new()),
c3: ScriptSigBuf::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.