TeachMeBitcoin

Custom Python P2TR Auditor

From TeachMeBitcoin, the free encyclopedia Reading time: 3 min

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

  1. Ensure you have Python 3 installed.

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

  3. Run it using python3 p2tr_auditor.py.

Technical Takeaways

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

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

  3. Witness Version 1: The first character after the 1 is always p for mainnet Taproot. This is because 1 (version) maps to p in the Bech32 alphabet.

Congratulations! You have completed the P2TR (Pay-to-Taproot) module. You are now at the cutting edge of Bitcoin technical scripting!

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