Script Validation (P2PKH-lite)

Implementation-first walk through of a strict, minimal script engine.

1 / 12

Module outcomes

  • Parse script bytes safely (pushdata vs opcode).
  • Execute stack ops with exact pop order.
  • Build deterministic simplified sighash.
  • Verify DER ECDSA signatures on P-256 keys.
  • Fail closed on malformed input.
2 / 12

Scope in this pack

  • Hash op: HASH256 (double SHA-256)
  • Curve: P-256 (toy stand-in)
  • Opcodes only:
    • 0x76 DUP
    • 0xAA HASH256
    • 0x88 EQUALVERIFY
    • 0xAC CHECKSIG

Anything else is invalid.

3 / 12

Script encoding rule

At byte script[i]:

  • 1..75 => pushdata length n, then push next n bytes
  • otherwise => opcode

Malformed push length => fail immediately.

4 / 12

P2PKH flow in this module

Execute:

  1. scriptSig (push signature + pubkey)
  2. scriptPubKey (DUP HASH256 <hash> EQUALVERIFY CHECKSIG)

Single shared stack across both scripts.

5 / 12

Stack contract by opcode

  • DUP: duplicate top
  • HASH256: replace top with hash
  • EQUALVERIFY: pop 2, compare, fail if mismatch
  • CHECKSIG: pop pubkey then signature, verify, push 1/0

Any underflow => fail.

6 / 12

CHECKSIG details

  • Pubkey encoding: 0x04 || X(32) || Y(32)
  • Require 65 bytes and point on P-256 curve
  • Signature format: ASN.1 DER
  • Verification API: ecdsa.VerifyASN1
7 / 12

Simplified sighash

S = HASH256(tx.ID || uint32_le(inputIndex) || scriptPubKey)

Gotchas:

  • input index is little-endian
  • include full scriptPubKey bytes
  • hash twice
8 / 12

End condition

Script succeeds iff:

  • stack non-empty
  • top item is truthy (not all-zero bytes)

Otherwise fail.

9 / 12

Hidden-test style failures

Must return false on:

  • bad opcode
  • malformed pushdata
  • stack underflow
  • bad pubkey length/prefix/curve point
  • hash mismatch at EQUALVERIFY
  • invalid signature
  • out-of-range input index
10 / 12

Suggested build order

  1. parser + pushdata bounds checks
  2. DUP/HASH256/EQUALVERIFY
  3. sighash and pubkey parse
  4. CHECKSIG + truthiness
  5. failure-path hardening
11 / 12

Debug checklist

  • token decoding index i
  • stack depth after each opcode
  • CHECKSIG pop order
  • sighash byte order
  • final truthiness check
12 / 12
Use arrow keys or click edges to navigate. Press H to toggle help, F for fullscreen.