TeachMeBitcoin

Custom Python P2PKH Auditor

From TeachMeBitcoin, the free encyclopedia Reading time: 2 min

Custom Python P2PKH Auditor

In this final guide, we will build a Python script that takes a raw P2PKH ScriptPubKey and extracts the 20-byte hash. To make it human-readable, we will implement the Base58Check encoding to convert that hash back into a legacy "1" address.

The P2PKH Address Auditor

import hashlib

# Standard Base58 alphabet
BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"

def base58_encode(raw_bytes):
    # Convert bytes to an integer
    n = int.from_bytes(raw_bytes, 'big')
    res = ""
    while n \u003e 0:
        n, r = divmod(n, 58)
        res = BASE58_ALPHABET[r] + res
    # Handle leading zeros (which become '1' in Base58)
    pad = 0
    for b in raw_bytes:
        if b == 0: pad += 1
        else: break
    return "1" * pad + res

def decode_p2pkh(script_hex):
    # 1. Check for standard P2PKH pattern
    # 76 (DUP) a9 (HASH160) 14 (PUSH 20) ... 88 (EQUALVERIFY) ac (CHECKSIG)
    if not (script_hex.startswith("76a914") and script_hex.endswith("88ac")):
        print("[ERROR] Not a standard P2PKH script!")
        return

    # 2. Extract the 20-byte hash
    pkh_hex = script_hex[6:-4]
    pkh_bytes = bytes.fromhex(pkh_hex)

    print(f"--- P2PKH Script Audit ---")
    print(f"[*] Raw Script: {script_hex}")
    print(f"[*] Key Hash:   {pkh_hex}")

    # 3. Base58Check Encoding
    # Step A: Prepend Version Byte (0x00 for Mainnet)
    versioned_pkh = b'\\x00' + pkh_bytes

    # Step B: Double SHA256 for checksum
    first_sha = hashlib.sha256(versioned_pkh).digest()
    checksum = hashlib.sha256(first_sha).digest()[:4]

    # Step C: Append Checksum and Encode
    final_payload = versioned_pkh + checksum
    address = base58_encode(final_payload)

    print(f"[*] Final Address: {address}")

# --- Simulation ---

# Case: A real-world legacy address ScriptPubKey
# address: 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa
p2pkh_script = "76a91462e907b15cbf27d5425399ebf6f0fb50ebb88f1888ac"
decode_p2pkh(p2pkh_script)

How to Run the Auditor

  1. Ensure you have Python 3 installed.

  2. Copy the code into a file named p2pkh_auditor.py.

  3. Run it using python3 p2pkh_auditor.py.

Technical Takeaways

  1. Hashed Identity: Notice how the address is just a representation of the hash. The original public key is nowhere to be found in this script.

  2. Safety First: The checksum we calculated ensures that the address we generated is mathematically consistent. Wallets do this same check before every transaction.

  3. Efficiency: By reducing a 65-byte public key to a 20-byte hash, Bitcoin's P2PKH saved nearly 60% of the space required to define a payment destination.

Congratulations! You have completed the P2PKH (Pay-to-Public-Key-Hash) module. You now understand how legacy Bitcoin addresses work under the hood.

☕ Help support TeachMeBitcoin

TeachMeBitcoin is an ad-free, open-source educational repository curated by a passionate team of Bitcoin researchers and educators for public benefit. If you found our articles helpful, please consider supporting our hosting and ongoing content updates with a clean donation:

Ethereum: 0x578417C51783663D8A6A811B3544E1f779D39A85
Bitcoin: bc1q77k9e95rn669kpzyjr8ke9w95zhk7pa5s63qzz
Solana: 4ycT2ayqeMucixj3wS8Ay8Tq9NRDYRPKYbj3UGESyQ4J
Address copied to clipboard!