Step 3: Generating the ScriptCode
When signing a P2WPKH (Segregated Witness) input, the signature and public key will be placed in the witness
field.
This is different from legacy transactions where signatures are placed directly in the scriptSig
. The witness field starts empty and gets populated during the signing process.
For signing a P2WPKH input, we need to generate the scriptCode
The scriptCode template for P2WPKH is:
scriptCode = OP_DUP OP_HASH160 <20-byte-pubkey-hash> OP_EQUALVERIFY OP_CHECKSIG
In hex format:
scriptCode = 1976a914 {20-byte-pubkey-hash} 88ac
The way we get the pubkey hash
is by extracting the 20-byte hash from previous transaction scriptPubKey.
For our test vector:
P2WPKH ScriptCode Structure
For P2WPKH inputs, the scriptCode is equivalent to the script in a legacy P2PKH output:
19
: Length (25 bytes)76
: OP_DUPa9
: OP_HASH16014
: Push 20 bytes1d0f172a0ecb48aee1be1f2687d2963ae33f71a1
: 20-byte public key hash from witness program88
: OP_EQUALVERIFYac
: OP_CHECKSIG
Code Implementation
Here's how you can generate the ScriptCode from a P2WPKH scriptPubKey:
def get_p2wpkh_scriptcode(script_pubkey: bytes) -> bytes:
if not script_pubkey.startswith(b'\x00\x14'):
raise ValueError("Not a P2WPKH scriptPubKey")
# Extract the 20-byte pubkey hash (skip the version and length bytes)
pubkey_hash = script_pubkey[2:]
# Construct P2PKH script: OP_DUP OP_HASH160 <pubkey_hash> OP_EQUALVERIFY OP_CHECKSIG
return (
bytes.fromhex('1976a914') + # OP_DUP OP_HASH160 PUSH20
pubkey_hash + # 20-byte pubkey hash
bytes.fromhex('88ac') # OP_EQUALVERIFY OP_CHECKSIG
)
Test Vector from BIP143
Let's now test our implementation against the BIP143 test vectors.
If you check the official BIP143 proposal, you'll find that the scriptCode we generate matches exactly with the test vectors provided there.
Next Step: With the scriptCode ready, we can move on to calculating the transaction digest components (hashPrevouts, hashSequence, hashOutputs) required by BIP143.