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.

SVG Image

For signing a P2WPKH input, we need to generate the scriptCode

The scriptCode template for P2WPKH is:

text
    scriptCode = OP_DUP OP_HASH160 <20-byte-pubkey-hash> OP_EQUALVERIFY OP_CHECKSIG

In hex format:

text
    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:

SVG Image

P2WPKH ScriptCode Structure

For P2WPKH inputs, the scriptCode is equivalent to the script in a legacy P2PKH output:

  • 19: Length (25 bytes)
  • 76: OP_DUP
  • a9: OP_HASH160
  • 14: Push 20 bytes
  • 1d0f172a0ecb48aee1be1f2687d2963ae33f71a1: 20-byte public key hash from witness program
  • 88: OP_EQUALVERIFY
  • ac: OP_CHECKSIG

Code Implementation

Here's how you can generate the ScriptCode from a P2WPKH scriptPubKey:

python
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.

Suggest Edits
View our public visitor count
Built with 🧡 by the Bitcoin Dev Project
We'd love to hear your feedback on this project?Give Feedback