create coinbase transaction

This commit is contained in:
4tochka 2018-03-27 00:23:26 +04:00
parent 3edac78c3e
commit 9cbec80963
13 changed files with 603 additions and 188 deletions

1
doc/addresses.md Normal file
View File

@ -0,0 +1 @@
![Address map](img/address_map.svg)

View File

@ -83,6 +83,7 @@ class Script():
self.data = b'' self.data = b''
self.type = "NON_STANDARD" self.type = "NON_STANDARD"
self.ntype = 7 self.ntype = 7
self.witness_version = None
self.op_sig_count = 0 self.op_sig_count = 0
if coinbase: if coinbase:
self.pattern = b"<coinbase>" self.pattern = b"<coinbase>"
@ -148,11 +149,13 @@ class Script():
self.type = "P2WPKH" self.type = "P2WPKH"
self.op_sig_count = 1 self.op_sig_count = 1
self.ntype = 5 self.ntype = 5
self.address.append(b"\x00"+self.script[1].data) self.witness_version = 0
self.address.append(self.script[1].data)
elif self.pattern == "OP_0 <32>": elif self.pattern == "OP_0 <32>":
self.type = "P2WSH" self.type = "P2WSH"
self.ntype = 6 self.ntype = 6
self.address.append(b"\x00"+self.script[1].data) self.witness_version = 0
self.address.append(self.script[1].data)
@ -317,6 +320,13 @@ class Transaction():
self.tx_in_count += 1 self.tx_in_count += 1
self.recalculate_txid() self.recalculate_txid()
def add_output(self, amount, script):
if type(script)==str:
script = unhexlify(script)
self.tx_out.append(Output(amount,script))
self.tx_out_count += 1
self.recalculate_txid()
def add_P2SH_output(self, amount, p2sh_address): def add_P2SH_output(self, amount, p2sh_address):
if type(p2sh_address)==str: if type(p2sh_address)==str:
p2sh_address = decode_base58(p2sh_address)[1:-4] p2sh_address = decode_base58(p2sh_address)[1:-4]

76
pybtc/constants.py Normal file
View File

@ -0,0 +1,76 @@
from secp256k1 import lib as secp256k1
from secp256k1 import ffi
import random
SIGHASH_ALL = 0x00000001
SIGHASH_NONE = 0x00000002
SIGHASH_SINGLE = 0x00000003
SIGHASH_ANYONECANPAY = 0x00000080
MAX_INT_PRIVATE_KEY = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
MAINNET_ADDRESS_BYTE_PREFIX = b'\x00'
TESTNET_ADDRESS_BYTE_PREFIX = b'\x6f'
MAINNET_SCRIPT_ADDRESS_BYTE_PREFIX = b'\x05'
TESTNET_SCRIPT_ADDRESS_BYTE_PREFIX = b'\xc4'
MAINNET_SEGWIT_ADDRESS_BYTE_PREFIX = b'\x03\x03\x00\x02\x03'
TESTNET_SEGWIT_ADDRESS_BYTE_PREFIX = b'\x03\x03\x00\x14\x02'
MAINNET_ADDRESS_PREFIX = '1'
TESTNET_ADDRESS_PREFIX = 'm'
TESTNET_ADDRESS_PREFIX_2 = 'n'
MAINNET_SCRIPT_ADDRESS_PREFIX = '3'
TESTNET_SCRIPT_ADDRESS_PREFIX = '2'
MAINNET_PRIVATE_KEY_UNCOMPRESSED_PREFIX = '5'
MAINNET_PRIVATE_KEY_COMPRESSED_PREFIX = 'K'
MAINNET_PRIVATE_KEY_COMPRESSED_PREFIX_2 = 'L'
TESTNET_PRIVATE_KEY_UNCOMPRESSED_PREFIX = '9'
TESTNET_PRIVATE_KEY_COMPRESSED_PREFIX = 'c'
ADDRESS_PREFIX_LIST = (MAINNET_ADDRESS_PREFIX,
TESTNET_ADDRESS_PREFIX,
TESTNET_ADDRESS_PREFIX_2,
MAINNET_SCRIPT_ADDRESS_PREFIX,
TESTNET_SCRIPT_ADDRESS_PREFIX)
PRIVATE_KEY_PREFIX_LIST = (MAINNET_PRIVATE_KEY_UNCOMPRESSED_PREFIX,
MAINNET_PRIVATE_KEY_COMPRESSED_PREFIX,
MAINNET_PRIVATE_KEY_COMPRESSED_PREFIX_2,
TESTNET_PRIVATE_KEY_UNCOMPRESSED_PREFIX,
TESTNET_PRIVATE_KEY_COMPRESSED_PREFIX)
MAINNET_PRIVATE_KEY_BYTE_PREFIX = b'\x80'
TESTNET_PRIVATE_KEY_BYTE_PREFIX = b'\xef'
MAINNET_SEGWIT_ADDRESS_PREFIX = 'bc'
TESTNET_SEGWIT_ADDRESS_PREFIX = 'tb'
EC_COMPRESSED = secp256k1.SECP256K1_EC_COMPRESSED
EC_UNCOMPRESSED = secp256k1.SECP256K1_EC_UNCOMPRESSED
FLAG_SIGN = secp256k1.SECP256K1_CONTEXT_SIGN
FLAG_VERIFY = secp256k1.SECP256K1_CONTEXT_VERIFY
ALL_FLAGS = FLAG_SIGN | FLAG_VERIFY
NO_FLAGS = secp256k1.SECP256K1_CONTEXT_NONE
HAS_RECOVERABLE = hasattr(secp256k1, 'secp256k1_ecdsa_sign_recoverable')
HAS_SCHNORR = hasattr(secp256k1, 'secp256k1_schnorr_sign')
HAS_ECDH = hasattr(secp256k1, 'secp256k1_ecdh')
ECDSA_CONTEXT_SIGN = secp256k1.secp256k1_context_create(FLAG_SIGN)
ECDSA_CONTEXT_VERIFY = secp256k1.secp256k1_context_create(FLAG_VERIFY)
ECDSA_CONTEXT_ALL = secp256k1.secp256k1_context_create(ALL_FLAGS)
secp256k1.secp256k1_context_randomize(ECDSA_CONTEXT_SIGN,
random.SystemRandom().randint(0,MAX_INT_PRIVATE_KEY).to_bytes(32,byteorder="big"))
SCRIPT_TYPES = { "P2PKH": 0,
"P2SH" : 1,
"PUBKEY": 2,
"NULL_DATA": 3,
"MULTISIG": 4,
"P2WPKH": 5,
"P2WSH": 6,
"NON_STANDART": 7
}

119
pybtc/encode.py Normal file
View File

@ -0,0 +1,119 @@
from binascii import hexlify, unhexlify
b58_digits = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
base32charset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
base32charset_upcase = "QPZRY9X8GF2TVDW0S3JN54KHCE6MUA7L"
int_base32_map = dict()
base32_int_map = dict()
for n, i in enumerate(base32charset):
int_base32_map[i] = n
base32_int_map[n] = ord(i)
for n, i in enumerate(base32charset_upcase):
int_base32_map[i] = n
def rebasebits(data, frombits, tobits, pad=True):
"""General power-of-2 base conversion."""
acc = 0
bits = 0
ret = bytearray()
maxv = (1 << tobits) - 1
max_acc = (1 << (frombits + tobits - 1)) - 1
for value in data:
if value < 0 or (value >> frombits):
raise Exception("invalid bytes")
acc = ((acc << frombits) | value) & max_acc
bits += frombits
while bits >= tobits:
bits -= tobits
ret.append((acc >> bits) & maxv)
if pad:
if bits:
ret.append((acc << (tobits - bits)) & maxv)
elif bits >= frombits or ((acc << (tobits - bits)) & maxv):
raise Exception("invalid padding")
return ret
def rebase_5_to_8(data, pad = True):
return rebasebits(data, 5, 8, pad)
def rebase_8_to_5(data, pad = True):
return rebasebits(data, 8, 5, pad)
def rebase_32_to_5(data):
if type(data) == bytes:
data = data.decode()
b = bytearray()
try:
for i in data:
b.append(int_base32_map[i])
except:
raise Exception("Non base32 characters")
return b
def rebase_5_to_32(data, bytes = True):
r = bytearray()
for i in data:
r.append(base32_int_map[i])
return r.decode() if not bytes else r
def bech32_polymod(values):
"""Internal function that computes the Bech32 checksum."""
generator = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3]
chk = 1
for value in values:
top = chk >> 25
chk = (chk & 0x1ffffff) << 5 ^ value
for i in range(5):
chk ^= generator[i] if ((top >> i) & 1) else 0
return chk ^ 1
def encode_base58(b):
"""Encode bytes to a base58-encoded string"""
# Convert big-endian bytes to integer
n = int('0x0' + hexlify(b).decode('utf8'), 16)
# Divide that integer into bas58
res = []
while n > 0:
n, r = divmod(n, 58)
res.append(b58_digits[r])
res = ''.join(res[::-1])
# Encode leading zeros as base58 zeros
czero = 0
pad = 0
for c in b:
if c == czero:
pad += 1
else:
break
return b58_digits[0] * pad + res
def decode_base58(s):
"""Decode a base58-encoding string, returning bytes"""
if not s:
return b''
# Convert the string to an integer
n = 0
for c in s:
n *= 58
if c not in b58_digits:
raise Exception('Character %r is not a valid base58 character' % c)
digit = b58_digits.index(c)
n += digit
# Convert the integer to bytes
h = '%x' % n
if len(h) % 2:
h = '0' + h
res = unhexlify(h.encode('utf8'))
# Add padding back.
pad = 0
for c in s[:-1]:
if c == b58_digits[0]:
pad += 1
else:
break
return b'\x00' * pad + res

43
pybtc/hash.py Normal file
View File

@ -0,0 +1,43 @@
import hashlib
import hmac
from binascii import unhexlify
def sha256(h, hex = False):
if type(h) == str:
h = unhexlify(h)
if hex:
return hashlib.sha256(h).hexdigest()
return hashlib.sha256(h).digest()
def double_sha256(h, hex = False):
if type(h) == str:
h = unhexlify(h)
if hex:
return sha256(sha256(h), 1)
return sha256(sha256(h))
def hmac_sha512(key, data, hex = False):
if hex:
return hmac.new(key, data, hashlib.sha512).hexdigest()
return hmac.new(key, data, hashlib.sha512).digest()
def ripemd160(h, hex = False):
if type(h) == str:
h = unhexlify(h)
a = hashlib.new('ripemd160')
a.update(h)
if hex:
return a.hexdigest()
return a.digest()
def hash160(h, hex = False):
if type(h) == str:
h = unhexlify(h)
if hex:
return ripemd160(sha256(h), 1)
return ripemd160(sha256(h))
#

View File

@ -1,122 +1,17 @@
import hashlib import hashlib
from binascii import hexlify, unhexlify from binascii import hexlify, unhexlify
import time import time
import random
import struct import struct
import hmac import hmac
from secp256k1 import lib as secp256k1 from .constants import *
from secp256k1 import ffi
from .opcodes import * from .opcodes import *
from .hash import *
SIGHASH_ALL = 0x00000001 from .encode import *
SIGHASH_NONE = 0x00000002
SIGHASH_SINGLE = 0x00000003
SIGHASH_ANYONECANPAY = 0x00000080
MAX_INT_PRIVATE_KEY = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
EC_COMPRESSED = secp256k1.SECP256K1_EC_COMPRESSED
EC_UNCOMPRESSED = secp256k1.SECP256K1_EC_UNCOMPRESSED
FLAG_SIGN = secp256k1.SECP256K1_CONTEXT_SIGN
FLAG_VERIFY = secp256k1.SECP256K1_CONTEXT_VERIFY
ALL_FLAGS = FLAG_SIGN | FLAG_VERIFY
NO_FLAGS = secp256k1.SECP256K1_CONTEXT_NONE
HAS_RECOVERABLE = hasattr(secp256k1, 'secp256k1_ecdsa_sign_recoverable')
HAS_SCHNORR = hasattr(secp256k1, 'secp256k1_schnorr_sign')
HAS_ECDH = hasattr(secp256k1, 'secp256k1_ecdh')
ECDSA_CONTEXT_SIGN = secp256k1.secp256k1_context_create(FLAG_SIGN)
ECDSA_CONTEXT_VERIFY = secp256k1.secp256k1_context_create(FLAG_VERIFY)
ECDSA_CONTEXT_ALL = secp256k1.secp256k1_context_create(ALL_FLAGS)
secp256k1.secp256k1_context_randomize(ECDSA_CONTEXT_SIGN,
random.SystemRandom().randint(0,MAX_INT_PRIVATE_KEY).to_bytes(32,byteorder="big"))
SCRIPT_TYPES = { "P2PKH": 0,
"P2SH" : 1,
"PUBKEY": 2,
"NULL_DATA": 3,
"MULTISIG": 4,
"NON_STANDART": 5,
"SP2PKH": 6
}
b58_digits = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
#
# Encoding functions
#
def encode_base58(b):
"""Encode bytes to a base58-encoded string"""
# Convert big-endian bytes to integer
n = int('0x0' + hexlify(b).decode('utf8'), 16)
# Divide that integer into bas58
res = []
while n > 0:
n, r = divmod(n, 58)
res.append(b58_digits[r])
res = ''.join(res[::-1])
# Encode leading zeros as base58 zeros
czero = 0
pad = 0
for c in b:
if c == czero:
pad += 1
else:
break
return b58_digits[0] * pad + res
def decode_base58(s):
"""Decode a base58-encoding string, returning bytes"""
if not s:
return b''
# Convert the string to an integer
n = 0
for c in s:
n *= 58
if c not in b58_digits:
raise Exception('Character %r is not a valid base58 character' % c)
digit = b58_digits.index(c)
n += digit
# Convert the integer to bytes
h = '%x' % n
if len(h) % 2:
h = '0' + h
res = unhexlify(h.encode('utf8'))
# Add padding back.
pad = 0
for c in s[:-1]:
if c == b58_digits[0]:
pad += 1
else:
break
return b'\x00' * pad + res
#
# Hash functions
#
def sha256(bytes):
return hashlib.sha256(bytes).digest()
def double_sha256(bytes):
return sha256(sha256(bytes))
def hmac_sha512(key, data):
return hmac.new(key, data, hashlib.sha512).digest()
def ripemd160(bytes):
h = hashlib.new('ripemd160')
h.update(bytes)
return h.digest()
def hash160(bytes):
return ripemd160(sha256(bytes))
#
# Bitcoin keys/ addresses # Bitcoin keys/ addresses
# #
def create_priv(): def create_priv(hex=False):
""" """
:return: 32 bytes private key :return: 32 bytes private key
""" """
@ -131,6 +26,8 @@ def create_priv():
else: else:
if int.from_bytes(h,byteorder="big")<MAX_INT_PRIVATE_KEY: if int.from_bytes(h,byteorder="big")<MAX_INT_PRIVATE_KEY:
break break
if hex:
return hexlify(h).decode()
return h return h
def priv_from_int(k): def priv_from_int(k):
@ -140,36 +37,56 @@ def priv_from_int(k):
def priv2WIF(h, compressed = False, testnet = False): def priv2WIF(h, compressed = False, testnet = False):
#uncompressed: 0x80 + [32-byte secret] + [4 bytes of Hash() of previous 33 bytes], base58 encoded #uncompressed: 0x80 + [32-byte secret] + [4 bytes of Hash() of previous 33 bytes], base58 encoded
#compressed: 0x80 + [32-byte secret] + 0x01 + [4 bytes of Hash() previous 34 bytes], base58 encoded #compressed: 0x80 + [32-byte secret] + 0x01 + [4 bytes of Hash() previous 34 bytes], base58 encoded
prefix = b'\x80' if type(h) == str:
h = unhexlify(h)
if testnet: if testnet:
prefix = b'\xef' h = TESTNET_PRIVATE_KEY_BYTE_PREFIX + h
h = prefix + h else:
h = MAINNET_PRIVATE_KEY_BYTE_PREFIX + h
if compressed: h += b'\x01' if compressed: h += b'\x01'
h += hashlib.sha256(hashlib.sha256(h).digest()).digest()[:4] h += double_sha256(h)[:4]
return encode_base58(h) return encode_base58(h)
def WIF2priv(h): def WIF2priv(h, hex = False, verify = 1):
if verify:
assert is_WIF_valid(h)
h = decode_base58(h) h = decode_base58(h)
if hex:
return hexlify(h[1:33]).decode()
return h[1:33] return h[1:33]
def is_WIF_valid(wif): def is_WIF_valid(wif):
if wif[0] not in ['5', 'K', 'L', '9', 'c']: if wif[0] not in PRIVATE_KEY_PREFIX_LIST:
return False
try:
h = decode_base58(wif)
except:
return False return False
h = decode_base58(wif)
if len(h) != 37: return False
checksum = h[-4:] checksum = h[-4:]
if hashlib.sha256(hashlib.sha256(h[:-4]).digest()).digest()[:4] != checksum: return False if wif[0] in (MAINNET_PRIVATE_KEY_UNCOMPRESSED_PREFIX,
TESTNET_PRIVATE_KEY_UNCOMPRESSED_PREFIX):
if len(h) != 37:
return False
elif len(h) != 38:
return False
if double_sha256(h[:-4])[:4] != checksum:
return False
return True return True
def priv2pub(private_key, compressed = True, hex = False): def priv2pub(private_key, compressed = True, hex = False):
if type(private_key)!= bytes: if type(private_key)!= bytes:
if type(private_key) == bytearray: if type(private_key) == bytearray:
private_key = bytes(private_key) private_key = bytes(private_key)
elif type(private_key) == str: elif type(private_key) == str:
private_key = unhexlify(private_key) if not is_WIF_valid(private_key):
private_key = unhexlify(private_key)
else:
if private_key[0] in (MAINNET_PRIVATE_KEY_UNCOMPRESSED_PREFIX,
TESTNET_PRIVATE_KEY_UNCOMPRESSED_PREFIX):
compressed = False
private_key = WIF2priv(private_key, verify=0)
else: else:
raise TypeError("private key must be a bytes or hex encoded string") raise TypeError("private key must be a bytes or WIF or hex encoded string")
pubkey_ptr = ffi.new('secp256k1_pubkey *') pubkey_ptr = ffi.new('secp256k1_pubkey *')
r = secp256k1.secp256k1_ec_pubkey_create(ECDSA_CONTEXT_ALL, pubkey_ptr, private_key) r = secp256k1.secp256k1_ec_pubkey_create(ECDSA_CONTEXT_ALL, pubkey_ptr, private_key)
assert r == 1 assert r == 1
@ -185,74 +102,195 @@ def priv2pub(private_key, compressed = True, hex = False):
def is_valid_pub(key): def is_valid_pub(key):
if len(key) < 33: if len(key) < 33:
return False return False
if key[0] == 0x04 and len(key) != 65: if key[0] == 0x04 and len(key) != 65:
return False return False
elif key[0] == 0x02 or key[0] == 0x03: elif key[0] == 0x02 or key[0] == 0x03:
if len(key) != 33: if len(key) != 33:
return False return False
# else: return False
return True return True
# #
# Bitcoin addresses # Bitcoin addresses
# #
def hash1602address(hash160, testnet = False, p2sh = False):
if type(hash160) == str:
hash160 = unhexlify(hash160) def hash2address(address_hash, testnet = False,
if not p2sh: script_hash = False, witness_version = 0):
prefix = b'\x6f' if testnet else b'\x00' if type(address_hash) == str:
address_hash = unhexlify(address_hash)
if not script_hash:
if witness_version is None:
assert len(address_hash) == 20
if testnet:
prefix = TESTNET_ADDRESS_BYTE_PREFIX
else:
prefix = MAINNET_ADDRESS_BYTE_PREFIX
address_hash = prefix + address_hash
address_hash += double_sha256(address_hash)[:4]
return encode_base58(address_hash)
else:
assert len(address_hash) in (20,32)
if witness_version is None:
if testnet:
prefix = TESTNET_SCRIPT_ADDRESS_BYTE_PREFIX
else:
prefix = MAINNET_SCRIPT_ADDRESS_BYTE_PREFIX
address_hash = prefix + address_hash
address_hash += double_sha256(address_hash)[:4]
return encode_base58(address_hash)
if testnet:
prefix = TESTNET_SEGWIT_ADDRESS_BYTE_PREFIX
hrp = TESTNET_SEGWIT_ADDRESS_PREFIX
else: else:
prefix = b'\xc4' if testnet else b'\x05' prefix = MAINNET_SEGWIT_ADDRESS_BYTE_PREFIX
hash160 = prefix + hash160 hrp = MAINNET_SEGWIT_ADDRESS_PREFIX
hash160 += double_sha256(hash160)[:4] address_hash = witness_version.to_bytes(1, "big") + rebase_8_to_5( address_hash)
return encode_base58(hash160) checksum = bech32_polymod(prefix + address_hash + b"\x00" * 6)
checksum = rebase_8_to_5(checksum.to_bytes(5, "big"))[2:]
return "%s1%s" % (hrp, rebase_5_to_32(address_hash + checksum).decode())
def address2hash160(address):
return decode_base58(address)[1:-4]
def address_type(address): def address2hash(address, hex = False):
if address[0] in ('2', '3'): if address[0] in ADDRESS_PREFIX_LIST:
return 'P2SH' h = decode_base58(address)[1:-4]
if address[0] in ('1', 'm', 'n'): elif address[:2] in (MAINNET_SEGWIT_ADDRESS_PREFIX,
return 'P2PKH' TESTNET_SEGWIT_ADDRESS_PREFIX):
return 'UNKNOWN' address = address.split("1")[1]
h = rebase_5_to_8(rebase_32_to_5(address)[1:-6], False)
else:
return None
if hex:
return h.hex()
else:
return h
def address_type(address, num = False):
if address[0] in (TESTNET_SCRIPT_ADDRESS_PREFIX,
MAINNET_SCRIPT_ADDRESS_PREFIX):
t = 'P2SH'
elif address[0] in (MAINNET_ADDRESS_PREFIX,
TESTNET_ADDRESS_PREFIX,
TESTNET_ADDRESS_PREFIX_2):
t = 'P2PKH'
elif address[:2] in (MAINNET_SEGWIT_ADDRESS_PREFIX,
TESTNET_SEGWIT_ADDRESS_PREFIX):
if len(address) == 42:
t = 'P2WPKH'
elif len(address) == 62:
t = 'P2WSH'
else:
return SCRIPT_TYPES['NON_STANDARD'] if num else 'UNKNOWN'
else:
return SCRIPT_TYPES['NON_STANDARD'] if num else 'UNKNOWN'
return SCRIPT_TYPES[t] if num else t
def script2hash(s, witness = False, hex = False):
if type(s) == str:
s = unhexlify(s)
if witness:
return sha256(s, hex)
else:
return hash160(s, hex)
def address2script(address): def address2script(address):
if address[0] in ('2', '3'): if address[0] in (TESTNET_SCRIPT_ADDRESS_PREFIX,
return OPCODE["OP_HASH160"] + b'\x14' + address2hash160(address) + OPCODE["OP_EQUAL"] MAINNET_SCRIPT_ADDRESS_PREFIX):
if address[0] in ('1', 'm', 'n'): return OPCODE["OP_HASH160"] + b'\x14' + address2hash(address) + OPCODE["OP_EQUAL"]
if address[0] in (MAINNET_ADDRESS_PREFIX,
TESTNET_ADDRESS_PREFIX,
TESTNET_ADDRESS_PREFIX_2):
return OPCODE["OP_DUP"] + OPCODE["OP_HASH160"] + b'\x14' + \ return OPCODE["OP_DUP"] + OPCODE["OP_HASH160"] + b'\x14' + \
address2hash160(address) + OPCODE["OP_EQUALVERIFY"] + OPCODE["OP_CHECKSIG"] address2hash(address) + OPCODE["OP_EQUALVERIFY"] + OPCODE["OP_CHECKSIG"]
if address[0] in (TESTNET_SEGWIT_ADDRESS_PREFIX,
MAINNET_SEGWIT_ADDRESS_PREFIX):
h = address2hash(address)
return OPCODE["OP_0"] + bytes([len(h)]) + h
raise Exception("Unknown address") raise Exception("Unknown address")
def pub2address(pubkey, testnet = False, p2sh = False): def pub2address(pubkey, testnet = False,
h = hash160(pubkey) inside_p2sh = False,
return hash1602address(h, testnet = testnet, p2sh = p2sh) witness_version = 0):
if type(pubkey) == str:
def pub2segwit(pubkey, testnet = False): pubkey = unhexlify(pubkey)
return hash1602address(pub2hash160segwit(pubkey), if inside_p2sh:
testnet=testnet, assert len(pubkey) == 33
p2sh=True) h = hash160(b'\x00\x14' + hash160(pubkey))
def pub2hash160segwit(pubkey):
return hash160(b'\x00\x14' + hash160(pubkey))
def is_address_valid(addr, testnet = False):
if testnet:
if addr[0] not in ('m', 'n', '2'):
return False
else: else:
if addr[0] not in ('1','3'): if witness_version is not None:
assert len(pubkey) == 33
h = hash160(pubkey)
return hash2address(h, testnet = testnet,
script_hash = inside_p2sh,
witness_version = witness_version)
# def pub2P2SH_P2WPKH_hash(pubkey):
# return hash160(b'\x00\x14' + hash160(pubkey))
#
# def pub2P2SH_P2WPKH_address(pubkey, testnet = False):
# return hash2address(pub2P2SH_P2WPKH_hash(pubkey),
# testnet=testnet,
# script_hash=True,
# witness_version=None)
def is_address_valid(address, testnet = False):
if not address or type(address) != str:
return False
if address[0] in (MAINNET_ADDRESS_PREFIX,
MAINNET_SCRIPT_ADDRESS_PREFIX,
TESTNET_ADDRESS_PREFIX,
TESTNET_ADDRESS_PREFIX_2,
TESTNET_SCRIPT_ADDRESS_PREFIX):
if testnet:
if address[0] not in (TESTNET_ADDRESS_PREFIX,
TESTNET_ADDRESS_PREFIX_2,
TESTNET_SCRIPT_ADDRESS_PREFIX):
return False
else:
if address[0] not in (MAINNET_ADDRESS_PREFIX,
MAINNET_SCRIPT_ADDRESS_PREFIX):
return False
h = decode_base58(address)
if len(h) != 25: return False
checksum = h[-4:]
if double_sha256(h[:-4])[:4] != checksum:
return False return False
h = decode_base58(addr) return True
if len(h) != 25: return False elif address[:2].lower() in (TESTNET_SEGWIT_ADDRESS_PREFIX,
checksum = h[-4:] MAINNET_SEGWIT_ADDRESS_PREFIX):
if hashlib.sha256(hashlib.sha256(h[:-4]).digest()).digest()[:4] != checksum: return False if len(address) not in (42, 62):
return True return False
prefix, payload = address.split('1')
upp = True if prefix[0].isupper() else False
for i in payload[1:]:
if upp:
if not i.isupper() or i not in base32charset_upcase:
return False
else:
if i.isupper() or i not in base32charset:
return False
payload = payload.lower()
prefix = prefix.lower()
if testnet:
if prefix != TESTNET_SEGWIT_ADDRESS_PREFIX:
return False
stripped_prefix = TESTNET_SEGWIT_ADDRESS_BYTE_PREFIX
else:
if prefix != MAINNET_SEGWIT_ADDRESS_PREFIX:
return False
stripped_prefix = MAINNET_SEGWIT_ADDRESS_BYTE_PREFIX
d = rebase_32_to_5(payload)
address_hash = d[:-6]
checksum = d[-6:]
checksum2 = bech32_polymod(stripped_prefix + address_hash + b"\x00" * 6)
checksum2 = rebase_8_to_5(checksum2.to_bytes(5, "big"))[2:]
if checksum != checksum2:
return False
return True
# #

View File

@ -1,7 +1,7 @@
# from .script_deserialize import * from .script_deserialize import *
# from .hash_functions import * from .hash_functions import *
# from .address_functions import * from .address_functions import *
# from .transaction_deserialize import * from .transaction_deserialize import *
# from .sighash import * from .sighash import *
# from .ecdsa import * from .ecdsa import *
from .block import * # from .block import *

View File

@ -1,5 +1,6 @@
import unittest import unittest
from pybtc import tools from pybtc import tools
from pybtc import OPCODE
from binascii import unhexlify from binascii import unhexlify
@ -8,7 +9,121 @@ class AddressFunctionsTests(unittest.TestCase):
def setUpClass(cls): def setUpClass(cls):
print("\nTesting address functions:\n") print("\nTesting address functions:\n")
def test_pub2segwit(self): def test_priv2WIF(self):
print("pub2segwit") p = "ceda1ae4286015d45ec5147fe3f63e9377ccd6d4e98bcf0847df9937da1944a4"
self.assertEqual(tools.pub2segwit(unhexlify("03db633162d49193d1178a5bbb90bde2f3c196ba0296f010b12a2320a7c6568582")), pcm = "L49obCXV7fGz2YRzLCSJgeZBYmGeBbKPT7xiehUeYX2S4URkPFZX"
"3PjV3gFppqmDEHjLvqDWv3Y4riLMQg7X1y") pum = "5KPPLXhtga99qqMceRo4Z6LXV3Kx6a9hRx3ez2U7EwP5KZfy2Wf"
put = "93A1vGXSGoDHotruGmgyRgtV8hgfFjgtmtuc4epcag886W9d44L"
pct = "cUWo47XLYiyFByuFicFS3y4FAza3r3R5XA7Bm7wA3dgSKDYox7h6"
self.assertEqual(tools.priv2WIF(p, compressed=1, testnet=0),pcm)
self.assertEqual(tools.priv2WIF(p, compressed=0, testnet=0),pum)
self.assertEqual(tools.priv2WIF(p, compressed=1, testnet=1),pct)
self.assertEqual(tools.priv2WIF(p, compressed=0, testnet=1),put)
def test_is_WIF_valid(self):
self.assertEqual(tools.is_WIF_valid("L49obCXV7fGz2YRzLCSJgeZBYmGeBbKPT7xiehUeYX2S4URkPFZX"),1)
self.assertEqual(tools.is_WIF_valid("5KPPLXhtga99qqMceRo4Z6LXV3Kx6a9hRx3ez2U7EwP5KZfy2Wf"),1)
self.assertEqual(tools.is_WIF_valid("5KPPLXhtga99qqMcWRo4Z6LXV3Kx6a9hRx3ez2U7EwP5KZfy2Wf"),0)
self.assertEqual(tools.is_WIF_valid("93A1vGXSGoDHotruGmgyRgtV8hgfFjgtmtuc4epcag886W9d44L"),1)
self.assertEqual(tools.is_WIF_valid("cUWo47XLYiyFByuFicFS3y4FAza3r3R5XA7Bm7wA3dgSKDYox7h6"),1)
self.assertEqual(tools.is_WIF_valid("cUWo47XLYiyByuFicFS3y4FAza3r3R5XA7Bm7wA3dgSKDYox7h6"),0)
def test_WIF2priv(self):
p = "ceda1ae4286015d45ec5147fe3f63e9377ccd6d4e98bcf0847df9937da1944a4"
self.assertEqual(tools.WIF2priv("L49obCXV7fGz2YRzLCSJgeZBYmGeBbKPT7xiehUeYX2S4URkPFZX",
hex=1),p)
self.assertEqual(tools.WIF2priv("L49obCXV7fGz2YRzLCSJgeZBYmGeBbKPT7xiehUeYX2S4URkPFZX",
hex=0),unhexlify(p))
self.assertEqual(tools.WIF2priv("5KPPLXhtga99qqMceRo4Z6LXV3Kx6a9hRx3ez2U7EwP5KZfy2Wf",
hex=1),p)
self.assertEqual(tools.WIF2priv("93A1vGXSGoDHotruGmgyRgtV8hgfFjgtmtuc4epcag886W9d44L",
hex=1),p)
self.assertEqual(tools.WIF2priv("cUWo47XLYiyFByuFicFS3y4FAza3r3R5XA7Bm7wA3dgSKDYox7h6",
hex=1),p)
def test_priv2pub(self):
p = "ceda1ae4286015d45ec5147fe3f63e9377ccd6d4e98bcf0847df9937da1944a4"
pu = "04b635dbdc16dbdf4bb9cf5b55e7d03e514fb04dcef34208155c7d3ec88e9045f4c8cbe28702911260f2a1da099a338bed4ee98f66bb8dba8031a76ab537ff6663"
pk = "03b635dbdc16dbdf4bb9cf5b55e7d03e514fb04dcef34208155c7d3ec88e9045f4"
self.assertEqual(tools.priv2pub(p, hex=1),pk)
self.assertEqual(tools.priv2pub(p, hex=0),unhexlify(pk))
self.assertEqual(tools.priv2pub(p, compressed=0, hex=1),pu)
self.assertEqual(tools.priv2pub("L49obCXV7fGz2YRzLCSJgeZBYmGeBbKPT7xiehUeYX2S4URkPFZX", hex=1),pk)
self.assertEqual(tools.priv2pub("5KPPLXhtga99qqMceRo4Z6LXV3Kx6a9hRx3ez2U7EwP5KZfy2Wf", hex=1),pu)
self.assertEqual(tools.priv2pub("93A1vGXSGoDHotruGmgyRgtV8hgfFjgtmtuc4epcag886W9d44L", hex=1),pu)
self.assertEqual(tools.priv2pub("cUWo47XLYiyFByuFicFS3y4FAza3r3R5XA7Bm7wA3dgSKDYox7h6", hex=1),pk)
def test_hash2address(self):
pc = "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"
h = tools.hash160(pc)
s = bytes([len(unhexlify(pc))])+unhexlify(pc) + OPCODE["OP_CHECKSIG"]
self.assertEqual(tools.hash2address(h), "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4")
self.assertEqual(tools.hash2address(h, testnet=1), "tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx")
h = tools.script2hash(s, 1, 1)
self.assertEqual(tools.hash2address(h), "bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3")
self.assertEqual(tools.hash2address(h, testnet=1), "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7")
pk = "03b635dbdc16dbdf4bb9cf5b55e7d03e514fb04dcef34208155c7d3ec88e9045f4"
h = tools.hash160(pk)
self.assertEqual(tools.hash2address(h, witness_version=None), "1Fs2Xqrk4P2XADaJeZWykaGXJ4HEb6RyT1")
self.assertEqual(tools.hash2address(h, witness_version=None, testnet=1), "mvNyptwisQTmwL3vN8VMaVUrA3swVCX83c")
# p2wpkh inside p2sh
p = "L32a8Mo1LgvjrVDbzcc3NkuUfkpoLsf2Y2oEWkV4t1KpQdFzuyff"
pk = tools.priv2pub(p)
script = b'\x00\x14' + tools.hash160(pk)
script_hash = tools.hash160(script)
self.assertEqual(tools.hash2address(script_hash, script_hash=1, witness_version=None), "33am12q3Bncnn3BfvLYHczyv23Sq2Wbwjw")
self.assertEqual(tools.hash2address(script_hash, script_hash=1, witness_version=None, testnet=1), "2Mu8y4mm4oF88yppDbUAAEwyBEPezrx7CLh")
def test_address2hash(self):
h = "751e76e8199196d454941c45d1b3a323f1433bd6"
self.assertEqual(tools.address2hash("bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4", 1), h)
self.assertEqual(tools.address2hash("tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx", 1), h)
h = "1863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262"
self.assertEqual(tools.address2hash("bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3", 1), h)
h = "a307d67484911deee457779b17505cedd20e1fe9"
self.assertEqual(tools.address2hash("1Fs2Xqrk4P2XADaJeZWykaGXJ4HEb6RyT1", 1), h)
self.assertEqual(tools.address2hash("mvNyptwisQTmwL3vN8VMaVUrA3swVCX83c", 1), h)
h = "14c14c8d26acbea970757b78e6429ad05a6ac6bb"
self.assertEqual(tools.address2hash("33am12q3Bncnn3BfvLYHczyv23Sq2Wbwjw", 1), h)
self.assertEqual(tools.address2hash("2Mu8y4mm4oF88yppDbUAAEwyBEPezrx7CLh", 1), h)
def test_address_type(self):
self.assertEqual(tools.address_type("bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"), 'P2WPKH')
self.assertEqual(tools.address_type("tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx"), 'P2WPKH')
self.assertEqual(tools.address_type("bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3"), 'P2WSH')
self.assertEqual(tools.address_type("tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7"), 'P2WSH')
self.assertEqual(tools.address_type("1Fs2Xqrk4P2XADaJeZWykaGXJ4HEb6RyT1"), 'P2PKH')
self.assertEqual(tools.address_type("mvNyptwisQTmwL3vN8VMaVUrA3swVCX83c"), 'P2PKH')
self.assertEqual(tools.address_type("33am12q3Bncnn3BfvLYHczyv23Sq2Wbwjw"), 'P2SH')
self.assertEqual(tools.address_type("2Mu8y4mm4oF88yppDbUAAEwyBEPezrx7CLh"), 'P2SH')
def test_pub2address(self):
pc = "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"
self.assertEqual(tools.pub2address(pc), "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4")
self.assertEqual(tools.pub2address(pc, testnet=1), "tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx")
pc = "03b635dbdc16dbdf4bb9cf5b55e7d03e514fb04dcef34208155c7d3ec88e9045f4"
self.assertEqual(tools.pub2address(pc, witness_version=None, testnet=0), "1Fs2Xqrk4P2XADaJeZWykaGXJ4HEb6RyT1")
self.assertEqual(tools.pub2address(pc, witness_version=None, testnet=1), "mvNyptwisQTmwL3vN8VMaVUrA3swVCX83c")
p = "L32a8Mo1LgvjrVDbzcc3NkuUfkpoLsf2Y2oEWkV4t1KpQdFzuyff"
pk = tools.priv2pub(p)
self.assertEqual(tools.pub2address(pk, inside_p2sh=1,witness_version=None), "33am12q3Bncnn3BfvLYHczyv23Sq2Wbwjw")
def test_is_address_valid(self):
self.assertEqual(tools.is_address_valid("bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"), 1)
self.assertEqual(tools.is_address_valid("tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx", 1), 1)
self.assertEqual(tools.is_address_valid("tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx"), 0)
self.assertEqual(tools.is_address_valid("bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3"), 1)
self.assertEqual(tools.is_address_valid("tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7", 1), 1)
self.assertEqual(tools.is_address_valid("1Fs2Xqrk4P2XADaJeZWykaGXJ4HEb6RyT1"), 1)
self.assertEqual(tools.is_address_valid("mvNyptwisQTmwL3vN8VMaVUrA3swVCX83c", 1), 1)
self.assertEqual(tools.is_address_valid("33am12q3Bncnn3BfvLYHczyv23Sq2Wbwjw"), 1)
self.assertEqual(tools.is_address_valid("2Mu8y4mm4oF88yppDbUAAEwyBEPezrx7CLh",1), 1)
self.assertEqual(tools.is_address_valid("2Mu8y4mm4oF89yppDbUAAEwyBEPezrx7CLh",1), 0)
self.assertEqual(tools.is_address_valid("bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4", 1), 0)
self.assertEqual(tools.is_address_valid("tb1qw508d6qejxtdg4W5r3zarvary0c5xw7kxpjzsx",1), 0)
self.assertEqual(tools.is_address_valid("bc1qrp33g0q5c5txsp8arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3"), 0)
self.assertEqual(tools.is_address_valid("tb1qrp23g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",1), 0)
self.assertEqual(tools.is_address_valid("1Fs2Xqrk4P2XADaJeZWykaGXJ2HEb6RyT1"), 0)
self.assertEqual(tools.is_address_valid("mvNyptwisQTkwL3vN8VMaVUrA3swVCX83c", 1), 0)
self.assertEqual(tools.is_address_valid("33am12q3Bncmn3BfvLYHczyv23Sq2Wbwjw"), 0)
self.assertEqual(tools.is_address_valid("2Mu8y4mm4oF78yppDbUAAEwyBEPezrx7CLh", 1), 0)

View File

@ -587,8 +587,10 @@ class BlockDeserializeTests(unittest.TestCase):
def setUpClass(cls): def setUpClass(cls):
print("\nTesting Block class deserialization:\n") print("\nTesting Block class deserialization:\n")
def test_block_deserialize(self): def test_block_deserialize(self):
block_c = "2000000000000000000001b7b88a5bad46d2e6707a89d7dc850441c81876cc9b7cfa6ce4c7a3304d8f487f52b6268d942f72d908a10a027ea01c3c04c93aff718bb8783e8053815a1a372b40915ae40604010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff2303c38e130068747470733a5c6170692e6269746170732e636f6d204a5948fc8a000000ffffffff02c7a2a904000000001976a914d4e49947b9f545218cd20389244c249d3520545d88ac0000000000000000266a24aa21a9ed7a2c14ed22283b657a9181f8981dc05361ca46f0b2a5c71d983326e5a73578100120000000000000000000000000000000000000000000000000000000000000000000000000010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff2303c38e130068747470733a5c6170692e6269746170732e636f6d2004b7841500000000ffffffff02c7a2a904000000001976a914d4e49947b9f545218cd20389244c249d3520545d88ac0000000000000000266a24aa21a9edcdbbce5ecb7d4878ac6828fe9284eb5616b26941d395524a95af8ea9b7b62df301200000000000000000000000000000000000000000000000000000000000000000000000000100000001f70f321af3d0cd51241b3755129298e2b389056084e7f9e716677feb7bfc823c010000006a47304402204970ddbb984e260419d78ac265af76ed427aa7789a38661e65d08535db408f1d022048f11c920753c8409b83cc5adfbfa36c19a176b502d5ea59b693dd45661db5ac012103b403539e4175cde64cc99b71d0d9cfc701c193bed1d6df17ae37b92e8506f141ffffffff0200000000000000001e6a1c504f455400000002b2dabb0c40f888bcedc5006bdf1cf3ed7bd26b0b239ede490a0000001976a9140fcc88829c46f85443edcce2150a8edbf57b48be88ac0000000001000000015bd2dcb6ec8cb4c82c2d6c59dc6390d94693d807d91f8749a5638fd925e88cd200000000fdfe000048304502210081c18398e662da86f8a8106ab78bdbd5732e456c872cc112f646070cc02f375202200ad1dd76bdf427222ce3edc73262128ecf20b0d57b328450e5fdaa7420fefc9a01483045022100ec41d289edc6bbec37560cf9f47d294c47d92a811cb67400a17e6bcd82594328022061031dd011fac9bc90bcde08eadca8143725854c502ab559270caa84c298d73b014c69522102f4dade8a5d54a904e3c7e639f397f049ab597b0859c6b486c5721344f4488f4921034b669c9a2f24d3d3d3d72358ae3f75bb257bfd3e166b404b4ff4ba8d6d0b52a821030fbf0e349acc83649bf187ba78c7764845f16cfe95c7c0287b6fac123815755753aeffffffff02a08601000000000017a914ac160ac1388194d6fe0e8e620d905e90bb3031fd87de6f850b0000000017a914d24feab4ad5431661fe18ffd158295158fe046218700000000" block_c = "2000000000000000000029a1a0390376afd72db120d698c2d8ebc41c545c7d4bc2b9033c303dd3d09d455da1c587406820a4dd77c5aa3fcc546dcceb1becc639829c4fe6535e815a1a372b405cc0829701010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff2303f88e130068747470733a5c6170692e6269746170732e636f6d20f251bec0cb000000ffffffff02c817a804000000001976a914d4e49947b9f545218cd20389244c249d3520545d88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000"
block = blockchain.Block.deserialize(block_c) block_e = "2000000000000000000029a1a0390376afd72db120d698c2d8ebc41c545c7d4bc2b9033c303dd3d09d455da1c587406820a4dd77c5aa3fcc546dcceb1becc639829c4fe65a815e531a372b405cc0829701010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff2303f88e130068747470733a5c6170692e6269746170732e636f6d20f251bec0cb000000ffffffff02c817a804000000001976a914d4e49947b9f545218cd20389244c249d3520545d88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000"
block = blockchain.Block.deserialize(block_e)
print(">>>",block.bits) print(">>>",block.bits)
print(">>>",block.hash) print(">>>",block.hash)

View File

@ -1,6 +1,6 @@
import unittest import unittest
from pybtc import tools from pybtc import tools
from binascii import unhexlify from binascii import unhexlify, hexlify
@ -13,13 +13,24 @@ class HashFunctionsTests(unittest.TestCase):
print("Double SHA256") print("Double SHA256")
self.assertEqual(tools.double_sha256(b"test double sha256"), self.assertEqual(tools.double_sha256(b"test double sha256"),
unhexlify("1ab3067efb509c48bda198f48c473f034202537c28b7b4c3b2ab2c4bf4a95c8d")) unhexlify("1ab3067efb509c48bda198f48c473f034202537c28b7b4c3b2ab2c4bf4a95c8d"))
self.assertEqual(tools.double_sha256(hexlify(b"test double sha256").decode()),
unhexlify("1ab3067efb509c48bda198f48c473f034202537c28b7b4c3b2ab2c4bf4a95c8d"))
self.assertEqual(tools.double_sha256(hexlify(b"test double sha256").decode(), 1),
"1ab3067efb509c48bda198f48c473f034202537c28b7b4c3b2ab2c4bf4a95c8d")
def test_ripemd160(self): def test_ripemd160(self):
print("RIPEMD160") print("RIPEMD160")
self.assertEqual(tools.ripemd160(b"test ripemd160"), self.assertEqual(tools.ripemd160(b"test ripemd160"),
unhexlify("45b17861a7defaac439f740d890f3dac4813cc37")) unhexlify("45b17861a7defaac439f740d890f3dac4813cc37"))
self.assertEqual(tools.ripemd160(hexlify(b"test ripemd160").decode()),
unhexlify("45b17861a7defaac439f740d890f3dac4813cc37"))
self.assertEqual(tools.ripemd160(hexlify(b"test ripemd160").decode(), 1),
"45b17861a7defaac439f740d890f3dac4813cc37")
def test_hash160(self): def test_hash160(self):
print("HASH160") print("HASH160")
self.assertEqual(tools.ripemd160(b"test hash160"), self.assertEqual(tools.ripemd160(b"test hash160"),
unhexlify("46a80bd289028559818a222eea64552d7a6a966f")) unhexlify("46a80bd289028559818a222eea64552d7a6a966f"))
self.assertEqual(tools.ripemd160(hexlify(b"test hash160").decode()),
unhexlify("46a80bd289028559818a222eea64552d7a6a966f"))
self.assertEqual(tools.ripemd160(hexlify(b"test hash160").decode(), 1),
"46a80bd289028559818a222eea64552d7a6a966f")

View File

@ -1,7 +1,7 @@
import unittest import unittest
from pybtc import blockchain from pybtc import blockchain
from binascii import unhexlify from binascii import unhexlify
from pybtc import address2hash160 from pybtc import address2hash as address2hash160
class ScriptDeserializeTests(unittest.TestCase): class ScriptDeserializeTests(unittest.TestCase):

View File

@ -1,7 +1,7 @@
import unittest import unittest
from pybtc import * from pybtc import *
from binascii import unhexlify from binascii import unhexlify
from pybtc import address2hash160 from pybtc import address2hash as address2hash160
class SighashTests(unittest.TestCase): class SighashTests(unittest.TestCase):
@classmethod @classmethod

View File

@ -1,7 +1,7 @@
import unittest import unittest
from pybtc import blockchain from pybtc import blockchain
from binascii import unhexlify from binascii import unhexlify
from pybtc import address2hash160 from pybtc import address2hash as address2hash160
class TransactionDeserializeTests(unittest.TestCase): class TransactionDeserializeTests(unittest.TestCase):