5
5
"""Encode and decode BASE58, P2PKH and P2SH addresses."""
6
6
7
7
import enum
8
+ import unittest
8
9
9
- from .base58 import byte_to_base58
10
- from .script import hash160 , sha256 , CScript , OP_0
10
+ from .script import hash256 , hash160 , sha256 , CScript , OP_0
11
11
from .util import hex_str_to_bytes
12
12
13
13
from . import segwit_addr
14
14
15
+ from test_framework .util import assert_equal
16
+
15
17
ADDRESS_BCRT1_UNSPENDABLE = 'bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj'
16
18
ADDRESS_BCRT1_UNSPENDABLE_DESCRIPTOR = 'addr(bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj)#juyq9d97'
17
19
# Coins sent to this address can be spent with a witness stack of just OP_TRUE
@@ -23,6 +25,52 @@ class AddressType(enum.Enum):
23
25
p2sh_segwit = 'p2sh-segwit'
24
26
legacy = 'legacy' # P2PKH
25
27
28
+
29
+ chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
30
+
31
+
32
+ def byte_to_base58 (b , version ):
33
+ result = ''
34
+ str = b .hex ()
35
+ str = chr (version ).encode ('latin-1' ).hex () + str
36
+ checksum = hash256 (hex_str_to_bytes (str )).hex ()
37
+ str += checksum [:8 ]
38
+ value = int ('0x' + str ,0 )
39
+ while value > 0 :
40
+ result = chars [value % 58 ] + result
41
+ value //= 58
42
+ while (str [:2 ] == '00' ):
43
+ result = chars [0 ] + result
44
+ str = str [2 :]
45
+ return result
46
+
47
+
48
+ def base58_to_byte (s , verify_checksum = True ):
49
+ if not s :
50
+ return b''
51
+ n = 0
52
+ for c in s :
53
+ n *= 58
54
+ assert c in chars
55
+ digit = chars .index (c )
56
+ n += digit
57
+ h = '%x' % n
58
+ if len (h ) % 2 :
59
+ h = '0' + h
60
+ res = n .to_bytes ((n .bit_length () + 7 ) // 8 , 'big' )
61
+ pad = 0
62
+ for c in s :
63
+ if c == chars [0 ]:
64
+ pad += 1
65
+ else :
66
+ break
67
+ res = b'\x00 ' * pad + res
68
+ if verify_checksum :
69
+ assert_equal (hash256 (res [:- 4 ])[:4 ], res [- 4 :])
70
+
71
+ return res [1 :- 4 ], int (res [0 ])
72
+
73
+
26
74
def keyhash_to_p2pkh (hash , main = False ):
27
75
assert len (hash ) == 20
28
76
version = 0 if main else 111
@@ -80,3 +128,22 @@ def check_script(script):
80
128
if (type (script ) is bytes or type (script ) is CScript ):
81
129
return script
82
130
assert False
131
+
132
+
133
+ class TestFrameworkScript (unittest .TestCase ):
134
+ def test_base58encodedecode (self ):
135
+ def check_base58 (data , version ):
136
+ self .assertEqual (base58_to_byte (byte_to_base58 (data , version )), (data , version ))
137
+
138
+ check_base58 (b'\x1f \x8e \xa1 p*{\xd4 \x94 \x1b \xca \t A\xb8 R\xc4 \xbb \xfe \xdb .\x05 ' , 111 )
139
+ check_base58 (b':\x0b \x05 \xf4 \xd7 \xf6 l;\xa7 \x00 \x9f E50)l\x84 \\ \xc9 \xcf ' , 111 )
140
+ check_base58 (b'A\xc1 \xea \xf1 \x11 \x80 %Y\xba \xd6 \x1b `\xd6 +\x1f \x89 |c\x92 \x8a ' , 111 )
141
+ check_base58 (b'\0 A\xc1 \xea \xf1 \x11 \x80 %Y\xba \xd6 \x1b `\xd6 +\x1f \x89 |c\x92 \x8a ' , 111 )
142
+ check_base58 (b'\0 \0 A\xc1 \xea \xf1 \x11 \x80 %Y\xba \xd6 \x1b `\xd6 +\x1f \x89 |c\x92 \x8a ' , 111 )
143
+ check_base58 (b'\0 \0 \0 A\xc1 \xea \xf1 \x11 \x80 %Y\xba \xd6 \x1b `\xd6 +\x1f \x89 |c\x92 \x8a ' , 111 )
144
+ check_base58 (b'\x1f \x8e \xa1 p*{\xd4 \x94 \x1b \xca \t A\xb8 R\xc4 \xbb \xfe \xdb .\x05 ' , 0 )
145
+ check_base58 (b':\x0b \x05 \xf4 \xd7 \xf6 l;\xa7 \x00 \x9f E50)l\x84 \\ \xc9 \xcf ' , 0 )
146
+ check_base58 (b'A\xc1 \xea \xf1 \x11 \x80 %Y\xba \xd6 \x1b `\xd6 +\x1f \x89 |c\x92 \x8a ' , 0 )
147
+ check_base58 (b'\0 A\xc1 \xea \xf1 \x11 \x80 %Y\xba \xd6 \x1b `\xd6 +\x1f \x89 |c\x92 \x8a ' , 0 )
148
+ check_base58 (b'\0 \0 A\xc1 \xea \xf1 \x11 \x80 %Y\xba \xd6 \x1b `\xd6 +\x1f \x89 |c\x92 \x8a ' , 0 )
149
+ check_base58 (b'\0 \0 \0 A\xc1 \xea \xf1 \x11 \x80 %Y\xba \xd6 \x1b `\xd6 +\x1f \x89 |c\x92 \x8a ' , 0 )
0 commit comments