address.py raw
1 #!/usr/bin/env python3
2 # Copyright (c) 2016-present The Bitcoin Core developers
3 # Distributed under the MIT software license, see the accompanying
4 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 """Encode and decode Bitcoin addresses.
6
7 - base58 P2PKH and P2SH addresses.
8 - bech32 segwit v0 P2WPKH and P2WSH addresses.
9 - bech32m segwit v1 P2TR addresses."""
10
11 import unittest
12
13 from .script import (
14 CScript,
15 OP_0,
16 OP_TRUE,
17 hash160,
18 hash256,
19 sha256,
20 taproot_construct,
21 )
22 from .util import assert_equal
23 from test_framework.script_util import (
24 keyhash_to_p2pkh_script,
25 program_to_witness_script,
26 scripthash_to_p2sh_script,
27 )
28 from test_framework.segwit_addr import (
29 decode_segwit_address,
30 encode_segwit_address,
31 )
32
33
34 ADDRESS_BCRT1_UNSPENDABLE = 'bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj'
35 ADDRESS_BCRT1_UNSPENDABLE_DESCRIPTOR = 'addr(bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj)#juyq9d97'
36 # Coins sent to this address can be spent with a witness stack of just OP_TRUE
37 ADDRESS_BCRT1_P2WSH_OP_TRUE = 'bcrt1qft5p2uhsdcdc3l2ua4ap5qqfg4pjaqlp250x7us7a8qqhrxrxfsqseac85'
38
39 b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
40
41
42 def create_deterministic_address_bcrt1_p2tr_op_true(explicit_internal_key=None):
43 """
44 Generates a deterministic bech32m address (segwit v1 output) that
45 can be spent with a witness stack of OP_TRUE and the control block
46 with internal public key (script-path spending).
47
48 Returns a tuple with the generated address and the TaprootInfo object.
49 """
50 internal_key = explicit_internal_key or (1).to_bytes(32, 'big')
51 taproot_info = taproot_construct(internal_key, [("only-path", CScript([OP_TRUE]))])
52 address = output_key_to_p2tr(taproot_info.output_pubkey)
53 if explicit_internal_key is None:
54 assert_equal(address, 'bcrt1p9yfmy5h72durp7zrhlw9lf7jpwjgvwdg0jr0lqmmjtgg83266lqsekaqka')
55 return (address, taproot_info)
56
57
58 def byte_to_base58(b, version):
59 if isinstance(version, int):
60 version = bytes([version])
61 b = version + b # prepend version
62 b += hash256(b)[:4] # append checksum
63 value = int.from_bytes(b, 'big')
64 result = ''
65 while value > 0:
66 result = b58chars[value % 58] + result
67 value //= 58
68 while b[0] == 0:
69 result = b58chars[0] + result
70 b = b[1:]
71 return result
72
73
74 def base58_to_byte(s):
75 """Converts a base58-encoded string to its data and version.
76
77 Throws if the base58 checksum is invalid."""
78 if not s:
79 return b''
80 n = 0
81 for c in s:
82 n *= 58
83 assert c in b58chars
84 digit = b58chars.index(c)
85 n += digit
86 h = '%x' % n
87 if len(h) % 2:
88 h = '0' + h
89 res = n.to_bytes((n.bit_length() + 7) // 8, 'big')
90 pad = 0
91 for c in s:
92 if c == b58chars[0]:
93 pad += 1
94 else:
95 break
96 res = b'\x00' * pad + res
97
98 if hash256(res[:-4])[:4] != res[-4:]:
99 raise ValueError('Invalid Base58Check checksum')
100
101 return res[1:-4], int(res[0])
102
103
104 def keyhash_to_p2pkh(hash, main=False):
105 assert_equal(len(hash), 20)
106 version = 0 if main else 111
107 return byte_to_base58(hash, version)
108
109 def scripthash_to_p2sh(hash, main=False):
110 assert_equal(len(hash), 20)
111 version = 5 if main else 196
112 return byte_to_base58(hash, version)
113
114 def key_to_p2pkh(key, main=False):
115 key = check_key(key)
116 return keyhash_to_p2pkh(hash160(key), main)
117
118 def script_to_p2sh(script, main=False):
119 script = check_script(script)
120 return scripthash_to_p2sh(hash160(script), main)
121
122 def key_to_p2sh_p2wpkh(key, main=False):
123 key = check_key(key)
124 p2shscript = CScript([OP_0, hash160(key)])
125 return script_to_p2sh(p2shscript, main)
126
127 def program_to_witness(version, program, main=False):
128 if (type(program) is str):
129 program = bytes.fromhex(program)
130 assert 0 <= version <= 16
131 assert 2 <= len(program) <= 40
132 assert version > 0 or len(program) in [20, 32]
133 return encode_segwit_address("bc" if main else "bcrt", version, program)
134
135 def script_to_p2wsh(script, main=False):
136 script = check_script(script)
137 return program_to_witness(0, sha256(script), main)
138
139 def key_to_p2wpkh(key, main=False):
140 key = check_key(key)
141 return program_to_witness(0, hash160(key), main)
142
143 def script_to_p2sh_p2wsh(script, main=False):
144 script = check_script(script)
145 p2shscript = CScript([OP_0, sha256(script)])
146 return script_to_p2sh(p2shscript, main)
147
148 def output_key_to_p2tr(key, main=False):
149 assert_equal(len(key), 32)
150 return program_to_witness(1, key, main)
151
152 def p2a(main=False):
153 return program_to_witness(1, "4e73", main)
154
155 def check_key(key):
156 if (type(key) is str):
157 key = bytes.fromhex(key) # Assuming this is hex string
158 if (type(key) is bytes and (len(key) == 33 or len(key) == 65)):
159 return key
160 assert False
161
162 def check_script(script):
163 if (type(script) is str):
164 script = bytes.fromhex(script) # Assuming this is hex string
165 if (type(script) is bytes or type(script) is CScript):
166 return script
167 assert False
168
169
170 def bech32_to_bytes(address):
171 hrp = address.split('1')[0]
172 if hrp not in ['bc', 'tb', 'bcrt']:
173 return (None, None)
174 version, payload = decode_segwit_address(hrp, address)
175 if version is None:
176 return (None, None)
177 return version, bytearray(payload)
178
179
180 def address_to_scriptpubkey(address):
181 """Converts a given address to the corresponding output script (scriptPubKey)."""
182 version, payload = bech32_to_bytes(address)
183 if version is not None:
184 return program_to_witness_script(version, payload) # testnet segwit scriptpubkey
185 payload, version = base58_to_byte(address)
186 if version == 111: # testnet pubkey hash
187 return keyhash_to_p2pkh_script(payload)
188 elif version == 196: # testnet script hash
189 return scripthash_to_p2sh_script(payload)
190 raise ValueError(f"Unsupported address type: {address}")
191
192
193 class TestFrameworkScript(unittest.TestCase):
194 def test_base58encodedecode(self):
195 def check_base58(data, version):
196 self.assertEqual(base58_to_byte(byte_to_base58(data, version)), (data, version))
197
198 check_base58(bytes.fromhex('1f8ea1702a7bd4941bca0941b852c4bbfedb2e05'), 111)
199 check_base58(bytes.fromhex('3a0b05f4d7f66c3ba7009f453530296c845cc9cf'), 111)
200 check_base58(bytes.fromhex('41c1eaf111802559bad61b60d62b1f897c63928a'), 111)
201 check_base58(bytes.fromhex('0041c1eaf111802559bad61b60d62b1f897c63928a'), 111)
202 check_base58(bytes.fromhex('000041c1eaf111802559bad61b60d62b1f897c63928a'), 111)
203 check_base58(bytes.fromhex('00000041c1eaf111802559bad61b60d62b1f897c63928a'), 111)
204 check_base58(bytes.fromhex('1f8ea1702a7bd4941bca0941b852c4bbfedb2e05'), 0)
205 check_base58(bytes.fromhex('3a0b05f4d7f66c3ba7009f453530296c845cc9cf'), 0)
206 check_base58(bytes.fromhex('41c1eaf111802559bad61b60d62b1f897c63928a'), 0)
207 check_base58(bytes.fromhex('0041c1eaf111802559bad61b60d62b1f897c63928a'), 0)
208 check_base58(bytes.fromhex('000041c1eaf111802559bad61b60d62b1f897c63928a'), 0)
209 check_base58(bytes.fromhex('00000041c1eaf111802559bad61b60d62b1f897c63928a'), 0)
210
211
212 def test_bech32_decode(self):
213 def check_bech32_decode(payload, version):
214 hrp = "tb"
215 self.assertEqual(bech32_to_bytes(encode_segwit_address(hrp, version, payload)), (version, payload))
216
217 check_bech32_decode(bytes.fromhex('36e3e2a33f328de12e4b43c515a75fba2632ecc3'), 0)
218 check_bech32_decode(bytes.fromhex('823e9790fc1d1782321140d4f4aa61aabd5e045b'), 0)
219 check_bech32_decode(bytes.fromhex('79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), 1)
220 check_bech32_decode(bytes.fromhex('39cf8ebd95134f431c39db0220770bd127f5dd3cc103c988b7dcd577ae34e354'), 1)
221 check_bech32_decode(bytes.fromhex('708244006d27c757f6f1fc6f853b6ec26268b727866f7ce632886e34eb5839a3'), 1)
222 check_bech32_decode(bytes.fromhex('616211ab00dffe0adcb6ce258d6d3fd8cbd901e2'), 0)
223 check_bech32_decode(bytes.fromhex('b6a7c98b482d7fb21c9fa8e65692a0890410ff22'), 0)
224 check_bech32_decode(bytes.fromhex('f0c2109cb1008cfa7b5a09cc56f7267cd8e50929'), 0)
225