Skip to content

Commit

Permalink
Add custom base58check algorithm (kyuupichan#389)
Browse files Browse the repository at this point in the history
  • Loading branch information
erasmospunk authored and Neil committed Feb 27, 2018
1 parent 2f26b73 commit 6add2e5
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 9 deletions.
10 changes: 6 additions & 4 deletions lib/coins.py
Expand Up @@ -70,6 +70,8 @@ class Coin(object):
BLOCK_PROCESSOR = BlockProcessor
XPUB_VERBYTES = bytes('????', 'utf-8')
XPRV_VERBYTES = bytes('????', 'utf-8')
ENCODE_CHECK = Base58.encode_check
DECODE_CHECK = Base58.decode_check
# Peer discovery
PEER_DEFAULT_PORTS = {'t': '50001', 's': '50002'}
PEERS = []
Expand Down Expand Up @@ -168,7 +170,7 @@ def address_to_hashX(cls, address):
def P2PKH_address_from_hash160(cls, hash160):
'''Return a P2PKH address given a public key.'''
assert len(hash160) == 20
return Base58.encode_check(cls.P2PKH_VERBYTE + hash160)
return cls.ENCODE_CHECK(cls.P2PKH_VERBYTE + hash160)

@classmethod
def P2PKH_address_from_pubkey(cls, pubkey):
Expand All @@ -179,7 +181,7 @@ def P2PKH_address_from_pubkey(cls, pubkey):
def P2SH_address_from_hash160(cls, hash160):
'''Return a coin address given a hash160.'''
assert len(hash160) == 20
return Base58.encode_check(cls.P2SH_VERBYTES[0] + hash160)
return cls.ENCODE_CHECK(cls.P2SH_VERBYTES[0] + hash160)

@classmethod
def multisig_address(cls, m, pubkeys):
Expand Down Expand Up @@ -212,7 +214,7 @@ def pay_to_address_script(cls, address):
Pass the address (either P2PKH or P2SH) in base58 form.
'''
raw = Base58.decode_check(address)
raw = cls.DECODE_CHECK(address)

# Require version byte(s) plus hash160.
verbyte = -1
Expand All @@ -233,7 +235,7 @@ def privkey_WIF(cls, privkey_bytes, compressed):
payload = bytearray(cls.WIF_BYTE) + privkey_bytes
if compressed:
payload.append(0x01)
return Base58.encode_check(payload)
return cls.ENCODE_CHECK(payload)

@classmethod
def header_hash(cls, header):
Expand Down
8 changes: 4 additions & 4 deletions lib/hash.py
Expand Up @@ -143,18 +143,18 @@ def encode(be_bytes):
return txt[::-1]

@staticmethod
def decode_check(txt):
def decode_check(txt, *, hash_fn=double_sha256):
'''Decodes a Base58Check-encoded string to a payload. The version
prefixes it.'''
be_bytes = Base58.decode(txt)
result, check = be_bytes[:-4], be_bytes[-4:]
if check != double_sha256(result)[:4]:
if check != hash_fn(result)[:4]:
raise Base58Error('invalid base 58 checksum for {}'.format(txt))
return result

@staticmethod
def encode_check(payload):
def encode_check(payload, *, hash_fn=double_sha256):
"""Encodes a payload bytearray (which includes the version byte(s))
into a Base58Check string."""
be_bytes = payload + double_sha256(payload)[:4]
be_bytes = payload + hash_fn(payload)[:4]
return Base58.encode(be_bytes)
2 changes: 1 addition & 1 deletion tests/lib/test_addresses.py
Expand Up @@ -60,7 +60,7 @@ def test_address_to_hashX(address):
def test_address_from_hash160(address):
coin, addr, hash, _ = address

raw = Base58.decode_check(addr)
raw = coin.DECODE_CHECK(addr)
verlen = len(raw) - 20
assert verlen > 0
verbyte, hash_bytes = raw[:verlen], raw[verlen:]
Expand Down
17 changes: 17 additions & 0 deletions tests/lib/test_hash.py
@@ -1,6 +1,7 @@
#
# Tests of lib/hash.py
#
from functools import partial

import pytest

Expand Down Expand Up @@ -66,3 +67,19 @@ def test_Base58_encode_check():
with pytest.raises(TypeError):
lib_hash.Base58.encode_check('foo')
assert lib_hash.Base58.encode_check(b'foo') == '4t9WKfuAB8'

def test_Base58_decode_check_custom():
decode_check_sha256 = partial(lib_hash.Base58.decode_check,
hash_fn=lib_hash.sha256)
with pytest.raises(TypeError):
decode_check_sha256(b'foo')
assert decode_check_sha256('4t9WFhKfWr') == b'foo'
with pytest.raises(lib_hash.Base58Error):
decode_check_sha256('4t9WFhKfWp')

def test_Base58_encode_check_custom():
encode_check_sha256 = partial(lib_hash.Base58.encode_check,
hash_fn=lib_hash.sha256)
with pytest.raises(TypeError):
encode_check_sha256('foo')
assert encode_check_sha256(b'foo') == '4t9WFhKfWr'

0 comments on commit 6add2e5

Please sign in to comment.