create coinbase transaction
This commit is contained in:
parent
3edac78c3e
commit
9cbec80963
1
doc/addresses.md
Normal file
1
doc/addresses.md
Normal file
@ -0,0 +1 @@
|
||||

|
||||
@ -83,6 +83,7 @@ class Script():
|
||||
self.data = b''
|
||||
self.type = "NON_STANDARD"
|
||||
self.ntype = 7
|
||||
self.witness_version = None
|
||||
self.op_sig_count = 0
|
||||
if coinbase:
|
||||
self.pattern = b"<coinbase>"
|
||||
@ -148,11 +149,13 @@ class Script():
|
||||
self.type = "P2WPKH"
|
||||
self.op_sig_count = 1
|
||||
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>":
|
||||
self.type = "P2WSH"
|
||||
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.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):
|
||||
if type(p2sh_address)==str:
|
||||
p2sh_address = decode_base58(p2sh_address)[1:-4]
|
||||
|
||||
76
pybtc/constants.py
Normal file
76
pybtc/constants.py
Normal 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
119
pybtc/encode.py
Normal 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
43
pybtc/hash.py
Normal 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))
|
||||
|
||||
|
||||
#
|
||||
372
pybtc/tools.py
372
pybtc/tools.py
@ -1,122 +1,17 @@
|
||||
import hashlib
|
||||
from binascii import hexlify, unhexlify
|
||||
import time
|
||||
import random
|
||||
import struct
|
||||
import hmac
|
||||
from secp256k1 import lib as secp256k1
|
||||
from secp256k1 import ffi
|
||||
from .constants import *
|
||||
from .opcodes import *
|
||||
|
||||
SIGHASH_ALL = 0x00000001
|
||||
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))
|
||||
from .hash import *
|
||||
from .encode import *
|
||||
|
||||
|
||||
#
|
||||
# Bitcoin keys/ addresses
|
||||
#
|
||||
def create_priv():
|
||||
def create_priv(hex=False):
|
||||
"""
|
||||
:return: 32 bytes private key
|
||||
"""
|
||||
@ -131,6 +26,8 @@ def create_priv():
|
||||
else:
|
||||
if int.from_bytes(h,byteorder="big")<MAX_INT_PRIVATE_KEY:
|
||||
break
|
||||
if hex:
|
||||
return hexlify(h).decode()
|
||||
return h
|
||||
|
||||
def priv_from_int(k):
|
||||
@ -140,36 +37,56 @@ def priv_from_int(k):
|
||||
def priv2WIF(h, compressed = False, testnet = False):
|
||||
#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
|
||||
prefix = b'\x80'
|
||||
if type(h) == str:
|
||||
h = unhexlify(h)
|
||||
if testnet:
|
||||
prefix = b'\xef'
|
||||
h = prefix + h
|
||||
h = TESTNET_PRIVATE_KEY_BYTE_PREFIX + h
|
||||
else:
|
||||
h = MAINNET_PRIVATE_KEY_BYTE_PREFIX + h
|
||||
if compressed: h += b'\x01'
|
||||
h += hashlib.sha256(hashlib.sha256(h).digest()).digest()[:4]
|
||||
h += double_sha256(h)[:4]
|
||||
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)
|
||||
if hex:
|
||||
return hexlify(h[1:33]).decode()
|
||||
return h[1:33]
|
||||
|
||||
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
|
||||
h = decode_base58(wif)
|
||||
if len(h) != 37: return False
|
||||
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
|
||||
|
||||
|
||||
def priv2pub(private_key, compressed = True, hex = False):
|
||||
if type(private_key)!= bytes:
|
||||
if type(private_key) == bytearray:
|
||||
private_key = bytes(private_key)
|
||||
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:
|
||||
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 *')
|
||||
r = secp256k1.secp256k1_ec_pubkey_create(ECDSA_CONTEXT_ALL, pubkey_ptr, private_key)
|
||||
assert r == 1
|
||||
@ -185,74 +102,195 @@ def priv2pub(private_key, compressed = True, hex = False):
|
||||
def is_valid_pub(key):
|
||||
if len(key) < 33:
|
||||
return False
|
||||
|
||||
if key[0] == 0x04 and len(key) != 65:
|
||||
return False
|
||||
elif key[0] == 0x02 or key[0] == 0x03:
|
||||
if len(key) != 33:
|
||||
return False
|
||||
# else: return False
|
||||
return True
|
||||
|
||||
|
||||
#
|
||||
# Bitcoin addresses
|
||||
#
|
||||
def hash1602address(hash160, testnet = False, p2sh = False):
|
||||
if type(hash160) == str:
|
||||
hash160 = unhexlify(hash160)
|
||||
if not p2sh:
|
||||
prefix = b'\x6f' if testnet else b'\x00'
|
||||
|
||||
|
||||
def hash2address(address_hash, testnet = False,
|
||||
script_hash = False, witness_version = 0):
|
||||
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:
|
||||
prefix = b'\xc4' if testnet else b'\x05'
|
||||
hash160 = prefix + hash160
|
||||
hash160 += double_sha256(hash160)[:4]
|
||||
return encode_base58(hash160)
|
||||
prefix = MAINNET_SEGWIT_ADDRESS_BYTE_PREFIX
|
||||
hrp = MAINNET_SEGWIT_ADDRESS_PREFIX
|
||||
address_hash = witness_version.to_bytes(1, "big") + rebase_8_to_5( address_hash)
|
||||
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):
|
||||
if address[0] in ('2', '3'):
|
||||
return 'P2SH'
|
||||
if address[0] in ('1', 'm', 'n'):
|
||||
return 'P2PKH'
|
||||
return 'UNKNOWN'
|
||||
def address2hash(address, hex = False):
|
||||
if address[0] in ADDRESS_PREFIX_LIST:
|
||||
h = decode_base58(address)[1:-4]
|
||||
elif address[:2] in (MAINNET_SEGWIT_ADDRESS_PREFIX,
|
||||
TESTNET_SEGWIT_ADDRESS_PREFIX):
|
||||
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):
|
||||
if address[0] in ('2', '3'):
|
||||
return OPCODE["OP_HASH160"] + b'\x14' + address2hash160(address) + OPCODE["OP_EQUAL"]
|
||||
if address[0] in ('1', 'm', 'n'):
|
||||
if address[0] in (TESTNET_SCRIPT_ADDRESS_PREFIX,
|
||||
MAINNET_SCRIPT_ADDRESS_PREFIX):
|
||||
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' + \
|
||||
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")
|
||||
|
||||
|
||||
def pub2address(pubkey, testnet = False, p2sh = False):
|
||||
h = hash160(pubkey)
|
||||
return hash1602address(h, testnet = testnet, p2sh = p2sh)
|
||||
|
||||
def pub2segwit(pubkey, testnet = False):
|
||||
return hash1602address(pub2hash160segwit(pubkey),
|
||||
testnet=testnet,
|
||||
p2sh=True)
|
||||
|
||||
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
|
||||
def pub2address(pubkey, testnet = False,
|
||||
inside_p2sh = False,
|
||||
witness_version = 0):
|
||||
if type(pubkey) == str:
|
||||
pubkey = unhexlify(pubkey)
|
||||
if inside_p2sh:
|
||||
assert len(pubkey) == 33
|
||||
h = hash160(b'\x00\x14' + hash160(pubkey))
|
||||
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
|
||||
h = decode_base58(addr)
|
||||
if len(h) != 25: return False
|
||||
checksum = h[-4:]
|
||||
if hashlib.sha256(hashlib.sha256(h[:-4]).digest()).digest()[:4] != checksum: return False
|
||||
return True
|
||||
return True
|
||||
elif address[:2].lower() in (TESTNET_SEGWIT_ADDRESS_PREFIX,
|
||||
MAINNET_SEGWIT_ADDRESS_PREFIX):
|
||||
if len(address) not in (42, 62):
|
||||
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
|
||||
|
||||
|
||||
|
||||
|
||||
#
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
# from .script_deserialize import *
|
||||
# from .hash_functions import *
|
||||
# from .address_functions import *
|
||||
# from .transaction_deserialize import *
|
||||
# from .sighash import *
|
||||
# from .ecdsa import *
|
||||
from .block import *
|
||||
from .script_deserialize import *
|
||||
from .hash_functions import *
|
||||
from .address_functions import *
|
||||
from .transaction_deserialize import *
|
||||
from .sighash import *
|
||||
from .ecdsa import *
|
||||
# from .block import *
|
||||
@ -1,5 +1,6 @@
|
||||
import unittest
|
||||
from pybtc import tools
|
||||
from pybtc import OPCODE
|
||||
from binascii import unhexlify
|
||||
|
||||
|
||||
@ -8,7 +9,121 @@ class AddressFunctionsTests(unittest.TestCase):
|
||||
def setUpClass(cls):
|
||||
print("\nTesting address functions:\n")
|
||||
|
||||
def test_pub2segwit(self):
|
||||
print("pub2segwit")
|
||||
self.assertEqual(tools.pub2segwit(unhexlify("03db633162d49193d1178a5bbb90bde2f3c196ba0296f010b12a2320a7c6568582")),
|
||||
"3PjV3gFppqmDEHjLvqDWv3Y4riLMQg7X1y")
|
||||
def test_priv2WIF(self):
|
||||
p = "ceda1ae4286015d45ec5147fe3f63e9377ccd6d4e98bcf0847df9937da1944a4"
|
||||
pcm = "L49obCXV7fGz2YRzLCSJgeZBYmGeBbKPT7xiehUeYX2S4URkPFZX"
|
||||
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)
|
||||
|
||||
@ -587,8 +587,10 @@ class BlockDeserializeTests(unittest.TestCase):
|
||||
def setUpClass(cls):
|
||||
print("\nTesting Block class deserialization:\n")
|
||||
def test_block_deserialize(self):
|
||||
block_c = "2000000000000000000001b7b88a5bad46d2e6707a89d7dc850441c81876cc9b7cfa6ce4c7a3304d8f487f52b6268d942f72d908a10a027ea01c3c04c93aff718bb8783e8053815a1a372b40915ae40604010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff2303c38e130068747470733a5c6170692e6269746170732e636f6d204a5948fc8a000000ffffffff02c7a2a904000000001976a914d4e49947b9f545218cd20389244c249d3520545d88ac0000000000000000266a24aa21a9ed7a2c14ed22283b657a9181f8981dc05361ca46f0b2a5c71d983326e5a73578100120000000000000000000000000000000000000000000000000000000000000000000000000010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff2303c38e130068747470733a5c6170692e6269746170732e636f6d2004b7841500000000ffffffff02c7a2a904000000001976a914d4e49947b9f545218cd20389244c249d3520545d88ac0000000000000000266a24aa21a9edcdbbce5ecb7d4878ac6828fe9284eb5616b26941d395524a95af8ea9b7b62df301200000000000000000000000000000000000000000000000000000000000000000000000000100000001f70f321af3d0cd51241b3755129298e2b389056084e7f9e716677feb7bfc823c010000006a47304402204970ddbb984e260419d78ac265af76ed427aa7789a38661e65d08535db408f1d022048f11c920753c8409b83cc5adfbfa36c19a176b502d5ea59b693dd45661db5ac012103b403539e4175cde64cc99b71d0d9cfc701c193bed1d6df17ae37b92e8506f141ffffffff0200000000000000001e6a1c504f455400000002b2dabb0c40f888bcedc5006bdf1cf3ed7bd26b0b239ede490a0000001976a9140fcc88829c46f85443edcce2150a8edbf57b48be88ac0000000001000000015bd2dcb6ec8cb4c82c2d6c59dc6390d94693d807d91f8749a5638fd925e88cd200000000fdfe000048304502210081c18398e662da86f8a8106ab78bdbd5732e456c872cc112f646070cc02f375202200ad1dd76bdf427222ce3edc73262128ecf20b0d57b328450e5fdaa7420fefc9a01483045022100ec41d289edc6bbec37560cf9f47d294c47d92a811cb67400a17e6bcd82594328022061031dd011fac9bc90bcde08eadca8143725854c502ab559270caa84c298d73b014c69522102f4dade8a5d54a904e3c7e639f397f049ab597b0859c6b486c5721344f4488f4921034b669c9a2f24d3d3d3d72358ae3f75bb257bfd3e166b404b4ff4ba8d6d0b52a821030fbf0e349acc83649bf187ba78c7764845f16cfe95c7c0287b6fac123815755753aeffffffff02a08601000000000017a914ac160ac1388194d6fe0e8e620d905e90bb3031fd87de6f850b0000000017a914d24feab4ad5431661fe18ffd158295158fe046218700000000"
|
||||
block = blockchain.Block.deserialize(block_c)
|
||||
block_c = "2000000000000000000029a1a0390376afd72db120d698c2d8ebc41c545c7d4bc2b9033c303dd3d09d455da1c587406820a4dd77c5aa3fcc546dcceb1becc639829c4fe6535e815a1a372b405cc0829701010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff2303f88e130068747470733a5c6170692e6269746170732e636f6d20f251bec0cb000000ffffffff02c817a804000000001976a914d4e49947b9f545218cd20389244c249d3520545d88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
block_e = "2000000000000000000029a1a0390376afd72db120d698c2d8ebc41c545c7d4bc2b9033c303dd3d09d455da1c587406820a4dd77c5aa3fcc546dcceb1becc639829c4fe65a815e531a372b405cc0829701010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff2303f88e130068747470733a5c6170692e6269746170732e636f6d20f251bec0cb000000ffffffff02c817a804000000001976a914d4e49947b9f545218cd20389244c249d3520545d88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
block = blockchain.Block.deserialize(block_e)
|
||||
|
||||
|
||||
print(">>>",block.bits)
|
||||
print(">>>",block.hash)
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import unittest
|
||||
from pybtc import tools
|
||||
from binascii import unhexlify
|
||||
from binascii import unhexlify, hexlify
|
||||
|
||||
|
||||
|
||||
@ -13,13 +13,24 @@ class HashFunctionsTests(unittest.TestCase):
|
||||
print("Double SHA256")
|
||||
self.assertEqual(tools.double_sha256(b"test double sha256"),
|
||||
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):
|
||||
print("RIPEMD160")
|
||||
self.assertEqual(tools.ripemd160(b"test ripemd160"),
|
||||
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):
|
||||
print("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")
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import unittest
|
||||
from pybtc import blockchain
|
||||
from binascii import unhexlify
|
||||
from pybtc import address2hash160
|
||||
from pybtc import address2hash as address2hash160
|
||||
|
||||
|
||||
class ScriptDeserializeTests(unittest.TestCase):
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import unittest
|
||||
from pybtc import *
|
||||
from binascii import unhexlify
|
||||
from pybtc import address2hash160
|
||||
from pybtc import address2hash as address2hash160
|
||||
|
||||
class SighashTests(unittest.TestCase):
|
||||
@classmethod
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import unittest
|
||||
from pybtc import blockchain
|
||||
from binascii import unhexlify
|
||||
from pybtc import address2hash160
|
||||
from pybtc import address2hash as address2hash160
|
||||
|
||||
|
||||
class TransactionDeserializeTests(unittest.TestCase):
|
||||
|
||||
Loading…
Reference in New Issue
Block a user