aboutsummaryrefslogtreecommitdiff
path: root/contrib/testgen/base58.py
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2012-09-29 11:13:32 +0200
committerWladimir J. van der Laan <laanwj@gmail.com>2012-10-01 04:57:26 +0200
commitd6b13283d19b3229ec1aee62bf7b4747c581ddab (patch)
tree7f7ba485f33dbd8b93a4670fa58365f2ac064f90 /contrib/testgen/base58.py
parent842a31ad1bea930c7ae2adcea929e3b8f0febfed (diff)
data-driven base58 CBitcoinAddress/CBitcoinSecret tests
Arbitrary numbers of test vectors can be generated using the script `gen_base58_test_vectors.py`.
Diffstat (limited to 'contrib/testgen/base58.py')
-rw-r--r--contrib/testgen/base58.py104
1 files changed, 104 insertions, 0 deletions
diff --git a/contrib/testgen/base58.py b/contrib/testgen/base58.py
new file mode 100644
index 0000000000..b716495145
--- /dev/null
+++ b/contrib/testgen/base58.py
@@ -0,0 +1,104 @@
+'''
+Bitcoin base58 encoding and decoding.
+
+Based on https://bitcointalk.org/index.php?topic=1026.0 (public domain)
+'''
+import hashlib
+
+# for compatibility with following code...
+class SHA256:
+ new = hashlib.sha256
+
+if str != bytes:
+ # Python 3.x
+ def ord(c):
+ return c
+ def chr(n):
+ return bytes( (n,) )
+
+__b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
+__b58base = len(__b58chars)
+b58chars = __b58chars
+
+def b58encode(v):
+ """ encode v, which is a string of bytes, to base58.
+ """
+ long_value = 0
+ for (i, c) in enumerate(v[::-1]):
+ long_value += (256**i) * ord(c)
+
+ result = ''
+ while long_value >= __b58base:
+ div, mod = divmod(long_value, __b58base)
+ result = __b58chars[mod] + result
+ long_value = div
+ result = __b58chars[long_value] + result
+
+ # Bitcoin does a little leading-zero-compression:
+ # leading 0-bytes in the input become leading-1s
+ nPad = 0
+ for c in v:
+ if c == '\0': nPad += 1
+ else: break
+
+ return (__b58chars[0]*nPad) + result
+
+def b58decode(v, length = None):
+ """ decode v into a string of len bytes
+ """
+ long_value = 0
+ for (i, c) in enumerate(v[::-1]):
+ long_value += __b58chars.find(c) * (__b58base**i)
+
+ result = bytes()
+ while long_value >= 256:
+ div, mod = divmod(long_value, 256)
+ result = chr(mod) + result
+ long_value = div
+ result = chr(long_value) + result
+
+ nPad = 0
+ for c in v:
+ if c == __b58chars[0]: nPad += 1
+ else: break
+
+ result = chr(0)*nPad + result
+ if length is not None and len(result) != length:
+ return None
+
+ return result
+
+def checksum(v):
+ """Return 32-bit checksum based on SHA256"""
+ return SHA256.new(SHA256.new(v).digest()).digest()[0:4]
+
+def b58encode_chk(v):
+ """b58encode a string, with 32-bit checksum"""
+ return b58encode(v + checksum(v))
+
+def b58decode_chk(v):
+ """decode a base58 string, check and remove checksum"""
+ result = b58decode(v)
+ if result is None:
+ return None
+ h3 = checksum(result[:-4])
+ if result[-4:] == checksum(result[:-4]):
+ return result[:-4]
+ else:
+ return None
+
+def get_bcaddress_version(strAddress):
+ """ Returns None if strAddress is invalid. Otherwise returns integer version of address. """
+ addr = b58decode_chk(strAddress)
+ if addr is None or len(addr)!=21: return None
+ version = addr[0]
+ return ord(version)
+
+if __name__ == '__main__':
+ # Test case (from http://gitorious.org/bitcoin/python-base58.git)
+ assert get_bcaddress_version('15VjRaDX9zpbA8LVnbrCAFzrVzN7ixHNsC') is 0
+ _ohai = 'o hai'.encode('ascii')
+ _tmp = b58encode(_ohai)
+ assert _tmp == 'DYB3oMS'
+ assert b58decode(_tmp, 5) == _ohai
+ print("Tests passed")