55"""Encode and decode BASE58, P2PKH and P2SH addresses."""
66
77import enum
8+ import unittest
89
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
1111from .util import hex_str_to_bytes
1212
1313from . import segwit_addr
1414
15+ from test_framework .util import assert_equal
16+
1517ADDRESS_BCRT1_UNSPENDABLE = 'bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj'
1618ADDRESS_BCRT1_UNSPENDABLE_DESCRIPTOR = 'addr(bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj)#juyq9d97'
1719# Coins sent to this address can be spent with a witness stack of just OP_TRUE
@@ -23,6 +25,52 @@ class AddressType(enum.Enum):
2325 p2sh_segwit = 'p2sh-segwit'
2426 legacy = 'legacy' # P2PKH
2527
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+
2674def keyhash_to_p2pkh (hash , main = False ):
2775 assert len (hash ) == 20
2876 version = 0 if main else 111
@@ -80,3 +128,22 @@ def check_script(script):
80128 if (type (script ) is bytes or type (script ) is CScript ):
81129 return script
82130 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