Skip to content

Commit 88b557c

Browse files
Copilotrichardkiss
andcommitted
Add P2TR (taproot) address generation to ku utility
Co-authored-by: richardkiss <5336+richardkiss@users.noreply.github.com>
1 parent ed977c0 commit 88b557c

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

pycoin/key/Key.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,3 +271,14 @@ def ku_output_for_address(self):
271271

272272
p2sh_script_hex = b2h(p2sh_script)
273273
yield ("p2sh_segwit_script", p2sh_script_hex, " corresponding p2sh script")
274+
275+
# generate P2TR (taproot) address if the network supports it
276+
if hash160_c and hasattr(self._network.address, "for_p2tr"):
277+
# P2TR uses the x-only public key (32 bytes)
278+
public_pair = self.public_pair()
279+
if public_pair:
280+
x_only = to_bytes_32(public_pair[0])
281+
address_taproot = self._network.address.for_p2tr(x_only)
282+
if address_taproot:
283+
yield ("address_taproot", address_taproot, "%s taproot address" % self._network.network_name)
284+
yield ("%s_address_taproot" % self._network.symbol, address_taproot, "legacy")

tests/key_test.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,36 @@ def do_test(exp_hex, wif, c_wif, public_pair_sec, c_public_pair_sec, address_b58
9393
"18fKPR8s1MQeckAsgya1sx6Z3WmFXd8wv8",
9494
"1DVJQzgnyCahXdoXdJ3tjGA3hrYVgKpvgK")
9595

96+
def test_p2tr_address(self):
97+
# Test P2TR (taproot) address generation
98+
# Using secret exponent 1, which is a known test vector
99+
private_key = network.keys.private(secret_exponent=1)
100+
101+
# Get P2TR address from ku_output_for_address
102+
p2tr_addresses = {}
103+
for k, v, text in private_key.ku_output_for_address():
104+
if 'taproot' in k:
105+
p2tr_addresses[k] = v
106+
107+
# Verify the addresses are generated
108+
self.assertIn('address_taproot', p2tr_addresses)
109+
self.assertIn('BTC_address_taproot', p2tr_addresses)
110+
111+
# Verify the expected address (from BIP 350 test vectors)
112+
expected_address = "bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqzk5jj0"
113+
self.assertEqual(p2tr_addresses['address_taproot'], expected_address)
114+
self.assertEqual(p2tr_addresses['BTC_address_taproot'], expected_address)
115+
116+
# Test with public key only
117+
public_key = private_key.public_copy()
118+
p2tr_addresses_pub = {}
119+
for k, v, text in public_key.ku_output_for_address():
120+
if 'taproot' in k:
121+
p2tr_addresses_pub[k] = v
122+
123+
# Verify public key generates the same address
124+
self.assertEqual(p2tr_addresses_pub['address_taproot'], expected_address)
125+
96126

97127
if __name__ == '__main__':
98128
unittest.main()

0 commit comments

Comments
 (0)