TeachMeBitcoin

Custom Python P2WPKH Auditor

From TeachMeBitcoin, the free encyclopedia Reading time: 3 min

Custom Python P2WPKH Auditor

In this final guide, we will build a Python script that parses a Native SegWit (P2WPKH) ScriptPubKey. The script will extract the 20-byte hash and convert it into a human-readable bc1q address using a simplified Bech32 implementation.

The P2WPKH Address Auditor

# Bech32 constants
CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"

def bech32_polymod(values):
 generator = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3]
 chk = 1
 for value in values:
 top = chk \u003e\u003e 25
 chk = (chk \u0026 0x1ffffff) \u003c\u003c 5 ^ value
 for i in range(5):
 chk ^= generator[i] if ((top \u003e\u003e i) \u0026 1) else 0
 return chk

def bech32_hrp_expand(hrp):
 return [ord(x) \u003e\u003e 5 for x in hrp] + [0] + [ord(x) \u0026 31 for x in hrp]

def convertbits(data, frombits, tobits, pad=True):
 acc = 0
 bits = 0
 ret = []
 maxv = (1 \u003c\u003c tobits) - 1
 for value in data:
 acc = (acc \u003c\u003c frombits) | value
 bits += frombits
 while bits \u003e= tobits:
 bits -= tobits
 ret.append((acc \u003e\u003e bits) \u0026 maxv)
 if pad:
 if bits:
 ret.append((acc \u003c\u003c (tobits - bits)) \u0026 maxv)
 return ret

def audit_p2wpkh(script_hex):
 # 1. Identify the Pattern (00 14 [20-byte hash])
 if not (script_hex.startswith("0014") and len(script_hex) == 44):
 print("[ERROR] Not a standard P2WPKH ScriptPubKey!")
 return

 pkh_hex = script_hex[4:]
 pkh_bytes = list(bytes.fromhex(pkh_hex))

 print(f"--- Native SegWit Audit ---")
 print(f"[*] ScriptPubKey: {script_hex}")
 print(f"[*] Key Hash: {pkh_hex}")

 # 2. Convert bytes to 5-bit groups for Bech32
 data = [0] + convertbits(pkh_bytes, 8, 5) # 0 is the witness version

 # 3. Calculate Checksum
 hrp = "bc"
 combined = bech32_hrp_expand(hrp) + data
 mod = bech32_polymod(combined + [0, 0, 0, 0, 0, 0]) ^ 1
 checksum = [(mod \u003e\u003e 5 * (5 - i)) \u0026 31 for i in range(6)]

 # 4. Final Encoding
 address = hrp + "1" + "".join([CHARSET[d] for d in data + checksum])
 print(f"[*] Derived Address: {address}")

# --- Simulation ---

# Case: A real-world bc1q address ScriptPubKey
# address: bc1qypmlegh4p9824mlegvlegvlegvlegvlegvleg
# (simplified test case hash)
p2wpkh_script = "001462e907b15cbf27d5425399ebf6f0fb50ebb88f18"
audit_p2wpkh(p2wpkh_script)

How to Run the Auditor

  1. Ensure you have Python 3 installed.

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

  3. Run it using python3 p2wpkh_auditor.py.

Technical Takeaways

  1. Version Zero: Notice how the first byte of the data (0) corresponds to the 'q' in the address. If this were a Version 1 (Taproot) address, the byte would be 1 and the address would start with bc1p.

  2. Bit Packing: Bech32 is more complex than Base58 because it requires converting 8-bit bytes into 5-bit chunks. This allows the alphabet to stay small and safe.

  3. Modern Footprint: At 22 bytes, P2WPKH is the smallest non-custom locking script in Bitcoin history. It represents the pinnacle of single-signature optimization.

Congratulations! You have completed the P2WPKH (Native SegWit) module. You now understand the modern standard for personal Bitcoin wallets.

☕ 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!