Custom Python P2TR Auditor
Custom Python P2TR Auditor
In this final guide, we will build a Python script that parses a Taproot (P2TR) ScriptPubKey. The script will extract the 32-byte public key and convert it into a human-readable bc1p address using the Bech32m encoding algorithm (BIP 350).
The P2TR Address Auditor
# Bech32m constants
CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
BECH32M_CONST = 0x2be810b1
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_p2tr(script_hex):
# 1. Identify the Pattern (51 20 [32-byte public key])
if not (script_hex.startswith("5120") and len(script_hex) == 68):
print("[ERROR] Not a standard P2TR ScriptPubKey!")
return
pubkey_hex = script_hex[4:]
pubkey_bytes = list(bytes.fromhex(pubkey_hex))
print(f"--- Taproot Native Auditor ---")
print(f"[*] ScriptPubKey: {script_hex}")
print(f"[*] Output Key: {pubkey_hex}")
# 2. Convert bytes to 5-bit groups
# The '1' at the start is the Witness Version (OP_1)
data = [1] + convertbits(pubkey_bytes, 8, 5)
# 3. Calculate Checksum (Bech32m - BIP 350)
hrp = "bc"
combined = bech32_hrp_expand(hrp) + data
mod = bech32_polymod(combined + [0, 0, 0, 0, 0, 0]) ^ BECH32M_CONST
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 standard Taproot output
# Address: bc1p5d7rx9... (example)
p2tr_script = "5120aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
audit_p2tr(p2tr_script)
How to Run the Auditor
-
Ensure you have Python 3 installed.
-
Copy the code into a file named
p2tr_auditor.py. -
Run it using
python3 p2tr_auditor.py.
Technical Takeaways
-
Bech32m vs Bech32: The only difference in the code is the
BECH32M_CONST. This constant prevents users from accidentally sending funds to a Taproot address using an old Bech32 wallet, which could cause a loss of funds. -
No RIPEMD160: Notice we didn't perform any hashing. The script directly uses the 32-byte key. This makes the address derivation simpler but requires the user to know the public key X-coordinate beforehand.
-
Witness Version 1: The first character after the
1is alwayspfor mainnet Taproot. This is because1(version) maps topin the Bech32 alphabet.
Congratulations! You have completed the P2TR (Pay-to-Taproot) module. You are now at the cutting edge of Bitcoin technical scripting!
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: