Use Bech32m encoding for v1+ segwit addresses · ElementsProject/elements@b3df66f

@@ -15,7 +15,7 @@

1515

from itertools import islice

1616

from base58 import b58encode_chk, b58decode_chk, b58chars

1717

import random

18-

from segwit_addr import bech32_encode, decode_segwit_address, convertbits, CHARSET

18+

from segwit_addr import bech32_encode, decode_segwit_address, convertbits, CHARSET, Encoding

19192020

# key types

2121

PUBKEY_ADDRESS = 0

@@ -32,6 +32,7 @@

3232

OP_0 = 0x00

3333

OP_1 = 0x51

3434

OP_2 = 0x52

35+

OP_3 = 0x53

3536

OP_16 = 0x60

3637

OP_DUP = 0x76

3738

OP_EQUAL = 0x87

@@ -44,6 +45,7 @@

4445

script_suffix = (OP_EQUAL,)

4546

p2wpkh_prefix = (OP_0, 20)

4647

p2wsh_prefix = (OP_0, 32)

48+

p2tr_prefix = (OP_1, 32)

47494850

metadata_keys = ['isPrivkey', 'chain', 'isCompressed', 'tryCaseFlip']

4951

# templates for valid sequences

@@ -65,29 +67,39 @@

6567

]

6668

# templates for valid bech32 sequences

6769

bech32_templates = [

68-

# hrp, version, witprog_size, metadata, output_prefix

69-

('bc', 0, 20, (False, 'main', None, True), p2wpkh_prefix),

70-

('bc', 0, 32, (False, 'main', None, True), p2wsh_prefix),

71-

('bc', 1, 2, (False, 'main', None, True), (OP_1, 2)),

72-

('tb', 0, 20, (False, 'test', None, True), p2wpkh_prefix),

73-

('tb', 0, 32, (False, 'test', None, True), p2wsh_prefix),

74-

('tb', 2, 16, (False, 'test', None, True), (OP_2, 16)),

75-

('bcrt', 0, 20, (False, 'regtest', None, True), p2wpkh_prefix),

76-

('bcrt', 0, 32, (False, 'regtest', None, True), p2wsh_prefix),

77-

('bcrt', 16, 40, (False, 'regtest', None, True), (OP_16, 40))

70+

# hrp, version, witprog_size, metadata, encoding, output_prefix

71+

('bc', 0, 20, (False, 'main', None, True), Encoding.BECH32, p2wpkh_prefix),

72+

('bc', 0, 32, (False, 'main', None, True), Encoding.BECH32, p2wsh_prefix),

73+

('bc', 1, 32, (False, 'main', None, True), Encoding.BECH32M, p2tr_prefix),

74+

('bc', 2, 2, (False, 'main', None, True), Encoding.BECH32M, (OP_2, 2)),

75+

('tb', 0, 20, (False, 'test', None, True), Encoding.BECH32, p2wpkh_prefix),

76+

('tb', 0, 32, (False, 'test', None, True), Encoding.BECH32, p2wsh_prefix),

77+

('tb', 1, 32, (False, 'test', None, True), Encoding.BECH32M, p2tr_prefix),

78+

('tb', 3, 16, (False, 'test', None, True), Encoding.BECH32M, (OP_3, 16)),

79+

('bcrt', 0, 20, (False, 'regtest', None, True), Encoding.BECH32, p2wpkh_prefix),

80+

('bcrt', 0, 32, (False, 'regtest', None, True), Encoding.BECH32, p2wsh_prefix),

81+

('bcrt', 1, 32, (False, 'regtest', None, True), Encoding.BECH32M, p2tr_prefix),

82+

('bcrt', 16, 40, (False, 'regtest', None, True), Encoding.BECH32M, (OP_16, 40))

7883

]

7984

# templates for invalid bech32 sequences

8085

bech32_ng_templates = [

81-

# hrp, version, witprog_size, invalid_bech32, invalid_checksum, invalid_char

82-

('tc', 0, 20, False, False, False),

83-

('tb', 17, 32, False, False, False),

84-

('bcrt', 3, 1, False, False, False),

85-

('bc', 15, 41, False, False, False),

86-

('tb', 0, 16, False, False, False),

87-

('bcrt', 0, 32, True, False, False),

88-

('bc', 0, 16, True, False, False),

89-

('tb', 0, 32, False, True, False),

90-

('bcrt', 0, 20, False, False, True)

86+

# hrp, version, witprog_size, encoding, invalid_bech32, invalid_checksum, invalid_char

87+

('tc', 0, 20, Encoding.BECH32, False, False, False),

88+

('bt', 1, 32, Encoding.BECH32M, False, False, False),

89+

('tb', 17, 32, Encoding.BECH32M, False, False, False),

90+

('bcrt', 3, 1, Encoding.BECH32M, False, False, False),

91+

('bc', 15, 41, Encoding.BECH32M, False, False, False),

92+

('tb', 0, 16, Encoding.BECH32, False, False, False),

93+

('bcrt', 0, 32, Encoding.BECH32, True, False, False),

94+

('bc', 0, 16, Encoding.BECH32, True, False, False),

95+

('tb', 0, 32, Encoding.BECH32, False, True, False),

96+

('bcrt', 0, 20, Encoding.BECH32, False, False, True),

97+

('bc', 0, 20, Encoding.BECH32M, False, False, False),

98+

('tb', 0, 32, Encoding.BECH32M, False, False, False),

99+

('bcrt', 0, 20, Encoding.BECH32M, False, False, False),

100+

('bc', 1, 32, Encoding.BECH32, False, False, False),

101+

('tb', 2, 16, Encoding.BECH32, False, False, False),

102+

('bcrt', 16, 20, Encoding.BECH32, False, False, False),

91103

]

9210493105

def is_valid(v):

@@ -127,8 +139,9 @@ def gen_valid_bech32_vector(template):

127139

hrp = template[0]

128140

witver = template[1]

129141

witprog = bytearray(os.urandom(template[2]))

130-

dst_prefix = bytearray(template[4])

131-

rv = bech32_encode(hrp, [witver] + convertbits(witprog, 8, 5))

142+

encoding = template[4]

143+

dst_prefix = bytearray(template[5])

144+

rv = bech32_encode(hrp, [witver] + convertbits(witprog, 8, 5), encoding)

132145

return rv, dst_prefix + witprog

133146134147

def gen_valid_vectors():

@@ -186,22 +199,23 @@ def gen_invalid_bech32_vector(template):

186199

hrp = template[0]

187200

witver = template[1]

188201

witprog = bytearray(os.urandom(template[2]))

202+

encoding = template[3]

189203190204

if no_data:

191-

rv = bech32_encode(hrp, [])

205+

rv = bech32_encode(hrp, [], encoding)

192206

else:

193207

data = [witver] + convertbits(witprog, 8, 5)

194-

if template[3] and not no_data:

208+

if template[4] and not no_data:

195209

if template[2] % 5 in {2, 4}:

196210

data[-1] |= 1

197211

else:

198212

data.append(0)

199-

rv = bech32_encode(hrp, data)

213+

rv = bech32_encode(hrp, data, encoding)

200214201-

if template[4]:

215+

if template[5]:

202216

i = len(rv) - random.randrange(1, 7)

203217

rv = rv[:i] + random.choice(CHARSET.replace(rv[i], '')) + rv[i + 1:]

204-

if template[5]:

218+

if template[6]:

205219

i = len(hrp) + 1 + random.randrange(0, len(rv) - len(hrp) - 4)

206220

rv = rv[:i] + rv[i:i + 4].upper() + rv[i + 4:]

207221