Merge rust-bitcoin/rust-bitcoin#2445: Add API functions `p2wpkh_script_code`

3c62f74684 Add public functions p2wpkh_script_code (Tobin C. Harding)
a246dc98a4 Run sighash example in CI (Tobin C. Harding)

Pull request description:

  This was done to fix #1920, it may be of questionable value though.

  - Patch 1 is definitely useful, its a CI fix.
  - Patch 2 adds two new API functions.

  Fix: #1920

ACKs for top commit:
  Kixunil:
    ACK 3c62f74684
  apoelstra:
    ACK 3c62f74684

Tree-SHA512: 58743612c48e392f9ac0a94477588aee959c5fe9191dd04405bbb71aed7b0730b5927ad98f9da34dc93caaaac939617348c3f71318cc7e65c2c154b0f3897b89
This commit is contained in:
Andrew Poelstra 2024-02-06 13:59:46 +00:00
commit 530899ae38
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
5 changed files with 34 additions and 10 deletions

View File

@ -75,3 +75,6 @@ required-features = ["std", "rand-std"]
[[example]]
name = "taproot-psbt"
required-features = ["std", "rand-std", "bitcoinconsensus"]
[[example]]
name = "sighash"

View File

@ -7,4 +7,4 @@ FEATURES_WITH_STD="rand-std serde secp-recovery bitcoinconsensus-std base64 orde
FEATURES_WITHOUT_STD="rand serde secp-recovery bitcoinconsensus base64 ordered"
# Run and lint these examples.
EXAMPLES="ecdsa-psbt:std,bitcoinconsensus sign-tx-segwit-v0:rand-std sign-tx-taproot:rand-std taproot-psbt:bitcoinconsensus,rand-std"
EXAMPLES="ecdsa-psbt:std,bitcoinconsensus sign-tx-segwit-v0:rand-std sign-tx-taproot:rand-std taproot-psbt:bitcoinconsensus,rand-std sighash:std"

View File

@ -19,7 +19,7 @@ use crate::blockdata::script::{
ScriptHash, WScriptHash,
};
use crate::consensus::Encodable;
use crate::key::{PublicKey, UntweakedPublicKey};
use crate::key::{PublicKey, UntweakedPublicKey, WPubkeyHash};
use crate::policy::DUST_RELAY_TX_FEE;
use crate::prelude::*;
use crate::taproot::{LeafVersion, TapLeafHash, TapNodeHash};
@ -385,14 +385,8 @@ impl Script {
/// [BIP143]: <https://github.com/bitcoin/bips/blob/99701f68a88ce33b2d0838eb84e115cef505b4c2/bip-0143.mediawiki>
pub fn p2wpkh_script_code(&self) -> Option<ScriptBuf> {
self.p2wpkh().map(|wpkh| {
Builder::new()
.push_opcode(OP_DUP)
.push_opcode(OP_HASH160)
// The `self` script is 0x00, 0x14, <pubkey_hash>
.push_slice(wpkh)
.push_opcode(OP_EQUALVERIFY)
.push_opcode(OP_CHECKSIG)
.into_script()
let wpkh = WPubkeyHash::from_slice(wpkh).expect("checked in p2wpkh()");
ScriptBuf::p2wpkh_script_code(wpkh)
})
}

View File

@ -151,6 +151,21 @@ impl ScriptBuf {
Builder::new().push_opcode(version.into()).push_slice(program).into_script()
}
/// Creates the script code used for spending a P2WPKH output.
///
/// The `scriptCode` is described in [BIP143].
///
/// [BIP143]: <https://github.com/bitcoin/bips/blob/99701f68a88ce33b2d0838eb84e115cef505b4c2/bip-0143.mediawiki>
pub fn p2wpkh_script_code(wpkh: WPubkeyHash) -> ScriptBuf {
Builder::new()
.push_opcode(OP_DUP)
.push_opcode(OP_HASH160)
.push_slice(wpkh)
.push_opcode(OP_EQUALVERIFY)
.push_opcode(OP_CHECKSIG)
.into_script()
}
/// Generates OP_RETURN-type of scriptPubkey for the given data.
pub fn new_op_return<T: AsRef<PushBytes>>(data: T) -> Self {
Builder::new().push_opcode(OP_RETURN).push_slice(data).into_script()

View File

@ -15,6 +15,7 @@ use internals::array_vec::ArrayVec;
use internals::write_err;
use io::{Read, Write};
use crate::blockdata::script::ScriptBuf;
use crate::crypto::ecdsa;
use crate::internal_macros::impl_asref_push_bytes;
use crate::network::NetworkKind;
@ -71,6 +72,12 @@ impl PublicKey {
}
}
/// Returns the script code used to spend a P2WPKH input.
pub fn p2wpkh_script_code(&self) -> Result<ScriptBuf, UncompressedPubkeyError> {
let key = CompressedPublicKey::try_from(*self)?;
Ok(key.p2wpkh_script_code())
}
/// Write the public key into a writer
pub fn write_into<W: Write + ?Sized>(&self, writer: &mut W) -> Result<(), io::Error> {
self.with_serialized(|bytes| writer.write_all(bytes))
@ -266,6 +273,11 @@ impl CompressedPublicKey {
WPubkeyHash::from_byte_array(hash160::Hash::hash(&self.to_bytes()).to_byte_array())
}
/// Returns the script code used to spend a P2WPKH input.
pub fn p2wpkh_script_code(&self) -> ScriptBuf {
ScriptBuf::p2wpkh_script_code(self.wpubkey_hash())
}
/// Write the public key into a writer
pub fn write_into<W: io::Write + ?Sized>(&self, writer: &mut W) -> Result<(), io::Error> {
writer.write_all(&self.to_bytes())