refactor network constants
This commit is contained in:
131
lib/bitcoin.py
131
lib/bitcoin.py
@@ -36,75 +36,8 @@ from .util import bfh, bh2u, to_string
|
||||
from . import version
|
||||
from .util import print_error, InvalidPassword, assert_bytes, to_bytes, inv_dict
|
||||
from . import segwit_addr
|
||||
from . import constants
|
||||
|
||||
def read_json(filename, default):
|
||||
path = os.path.join(os.path.dirname(__file__), filename)
|
||||
try:
|
||||
with open(path, 'r') as f:
|
||||
r = json.loads(f.read())
|
||||
except:
|
||||
r = default
|
||||
return r
|
||||
|
||||
|
||||
class NetworkConstants:
|
||||
|
||||
@classmethod
|
||||
def set_mainnet(cls):
|
||||
cls.TESTNET = False
|
||||
cls.WIF_PREFIX = 0x80
|
||||
cls.ADDRTYPE_P2PKH = 0
|
||||
cls.ADDRTYPE_P2SH = 5
|
||||
cls.SEGWIT_HRP = "bc"
|
||||
cls.GENESIS = "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"
|
||||
cls.DEFAULT_PORTS = {'t': '50001', 's': '50002'}
|
||||
cls.DEFAULT_SERVERS = read_json('servers.json', {})
|
||||
cls.CHECKPOINTS = read_json('checkpoints.json', [])
|
||||
|
||||
cls.XPRV_HEADERS = {
|
||||
'standard': 0x0488ade4, # xprv
|
||||
'p2wpkh-p2sh': 0x049d7878, # yprv
|
||||
'p2wsh-p2sh': 0x0295b005, # Yprv
|
||||
'p2wpkh': 0x04b2430c, # zprv
|
||||
'p2wsh': 0x02aa7a99, # Zprv
|
||||
}
|
||||
cls.XPUB_HEADERS = {
|
||||
'standard': 0x0488b21e, # xpub
|
||||
'p2wpkh-p2sh': 0x049d7cb2, # ypub
|
||||
'p2wsh-p2sh': 0x0295b43f, # Ypub
|
||||
'p2wpkh': 0x04b24746, # zpub
|
||||
'p2wsh': 0x02aa7ed3, # Zpub
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def set_testnet(cls):
|
||||
cls.TESTNET = True
|
||||
cls.WIF_PREFIX = 0xef
|
||||
cls.ADDRTYPE_P2PKH = 111
|
||||
cls.ADDRTYPE_P2SH = 196
|
||||
cls.SEGWIT_HRP = "tb"
|
||||
cls.GENESIS = "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"
|
||||
cls.DEFAULT_PORTS = {'t':'51001', 's':'51002'}
|
||||
cls.DEFAULT_SERVERS = read_json('servers_testnet.json', {})
|
||||
cls.CHECKPOINTS = read_json('checkpoints_testnet.json', [])
|
||||
|
||||
cls.XPRV_HEADERS = {
|
||||
'standard': 0x04358394, # tprv
|
||||
'p2wpkh-p2sh': 0x044a4e28, # uprv
|
||||
'p2wsh-p2sh': 0x024285b5, # Uprv
|
||||
'p2wpkh': 0x045f18bc, # vprv
|
||||
'p2wsh': 0x02575048, # Vprv
|
||||
}
|
||||
cls.XPUB_HEADERS = {
|
||||
'standard': 0x043587cf, # tpub
|
||||
'p2wpkh-p2sh': 0x044a5262, # upub
|
||||
'p2wsh-p2sh': 0x024285ef, # Upub
|
||||
'p2wpkh': 0x045f1cf6, # vpub
|
||||
'p2wsh': 0x02575483, # Vpub
|
||||
}
|
||||
|
||||
|
||||
NetworkConstants.set_mainnet()
|
||||
|
||||
################################## transactions
|
||||
|
||||
@@ -341,16 +274,16 @@ def b58_address_to_hash160(addr):
|
||||
|
||||
|
||||
def hash160_to_p2pkh(h160):
|
||||
return hash160_to_b58_address(h160, NetworkConstants.ADDRTYPE_P2PKH)
|
||||
return hash160_to_b58_address(h160, constants.net.ADDRTYPE_P2PKH)
|
||||
|
||||
def hash160_to_p2sh(h160):
|
||||
return hash160_to_b58_address(h160, NetworkConstants.ADDRTYPE_P2SH)
|
||||
return hash160_to_b58_address(h160, constants.net.ADDRTYPE_P2SH)
|
||||
|
||||
def public_key_to_p2pkh(public_key):
|
||||
return hash160_to_p2pkh(hash_160(public_key))
|
||||
|
||||
def hash_to_segwit_addr(h):
|
||||
return segwit_addr.encode(NetworkConstants.SEGWIT_HRP, 0, h)
|
||||
return segwit_addr.encode(constants.net.SEGWIT_HRP, 0, h)
|
||||
|
||||
def public_key_to_p2wpkh(public_key):
|
||||
return hash_to_segwit_addr(hash_160(public_key))
|
||||
@@ -396,7 +329,7 @@ def script_to_address(script):
|
||||
return addr
|
||||
|
||||
def address_to_script(addr):
|
||||
witver, witprog = segwit_addr.decode(NetworkConstants.SEGWIT_HRP, addr)
|
||||
witver, witprog = segwit_addr.decode(constants.net.SEGWIT_HRP, addr)
|
||||
if witprog is not None:
|
||||
assert (0 <= witver <= 16)
|
||||
OP_n = witver + 0x50 if witver > 0 else 0
|
||||
@@ -404,11 +337,11 @@ def address_to_script(addr):
|
||||
script += push_script(bh2u(bytes(witprog)))
|
||||
return script
|
||||
addrtype, hash_160 = b58_address_to_hash160(addr)
|
||||
if addrtype == NetworkConstants.ADDRTYPE_P2PKH:
|
||||
if addrtype == constants.net.ADDRTYPE_P2PKH:
|
||||
script = '76a9' # op_dup, op_hash_160
|
||||
script += push_script(bh2u(hash_160))
|
||||
script += '88ac' # op_equalverify, op_checksig
|
||||
elif addrtype == NetworkConstants.ADDRTYPE_P2SH:
|
||||
elif addrtype == constants.net.ADDRTYPE_P2SH:
|
||||
script = 'a9' # op_hash_160
|
||||
script += push_script(bh2u(hash_160))
|
||||
script += '87' # op_equal
|
||||
@@ -526,9 +459,9 @@ SCRIPT_TYPES = {
|
||||
|
||||
def serialize_privkey(secret, compressed, txin_type, internal_use=False):
|
||||
if internal_use:
|
||||
prefix = bytes([(SCRIPT_TYPES[txin_type] + NetworkConstants.WIF_PREFIX) & 255])
|
||||
prefix = bytes([(SCRIPT_TYPES[txin_type] + constants.net.WIF_PREFIX) & 255])
|
||||
else:
|
||||
prefix = bytes([NetworkConstants.WIF_PREFIX])
|
||||
prefix = bytes([constants.net.WIF_PREFIX])
|
||||
suffix = b'\01' if compressed else b''
|
||||
vchIn = prefix + secret + suffix
|
||||
base58_wif = EncodeBase58Check(vchIn)
|
||||
@@ -552,9 +485,9 @@ def deserialize_privkey(key):
|
||||
|
||||
if txin_type is None:
|
||||
# keys exported in version 3.0.x encoded script type in first byte
|
||||
txin_type = inv_dict(SCRIPT_TYPES)[vch[0] - NetworkConstants.WIF_PREFIX]
|
||||
txin_type = inv_dict(SCRIPT_TYPES)[vch[0] - constants.net.WIF_PREFIX]
|
||||
else:
|
||||
assert vch[0] == NetworkConstants.WIF_PREFIX
|
||||
assert vch[0] == constants.net.WIF_PREFIX
|
||||
|
||||
assert len(vch) in [33, 34]
|
||||
compressed = len(vch) == 34
|
||||
@@ -590,7 +523,7 @@ def address_from_private_key(sec):
|
||||
|
||||
def is_segwit_address(addr):
|
||||
try:
|
||||
witver, witprog = segwit_addr.decode(NetworkConstants.SEGWIT_HRP, addr)
|
||||
witver, witprog = segwit_addr.decode(constants.net.SEGWIT_HRP, addr)
|
||||
except Exception as e:
|
||||
return False
|
||||
return witprog is not None
|
||||
@@ -600,7 +533,7 @@ def is_b58_address(addr):
|
||||
addrtype, h = b58_address_to_hash160(addr)
|
||||
except Exception as e:
|
||||
return False
|
||||
if addrtype not in [NetworkConstants.ADDRTYPE_P2PKH, NetworkConstants.ADDRTYPE_P2SH]:
|
||||
if addrtype not in [constants.net.ADDRTYPE_P2PKH, constants.net.ADDRTYPE_P2SH]:
|
||||
return False
|
||||
return addr == hash160_to_b58_address(h, addrtype)
|
||||
|
||||
@@ -912,25 +845,35 @@ def _CKD_pub(cK, c, s):
|
||||
return cK_n, c_n
|
||||
|
||||
|
||||
def xprv_header(xtype):
|
||||
return bfh("%08x" % NetworkConstants.XPRV_HEADERS[xtype])
|
||||
def xprv_header(xtype, *, net=None):
|
||||
if net is None:
|
||||
net = constants.net
|
||||
return bfh("%08x" % net.XPRV_HEADERS[xtype])
|
||||
|
||||
|
||||
def xpub_header(xtype):
|
||||
return bfh("%08x" % NetworkConstants.XPUB_HEADERS[xtype])
|
||||
def xpub_header(xtype, *, net=None):
|
||||
if net is None:
|
||||
net = constants.net
|
||||
return bfh("%08x" % net.XPUB_HEADERS[xtype])
|
||||
|
||||
|
||||
def serialize_xprv(xtype, c, k, depth=0, fingerprint=b'\x00'*4, child_number=b'\x00'*4):
|
||||
xprv = xprv_header(xtype) + bytes([depth]) + fingerprint + child_number + c + bytes([0]) + k
|
||||
def serialize_xprv(xtype, c, k, depth=0, fingerprint=b'\x00'*4,
|
||||
child_number=b'\x00'*4, *, net=None):
|
||||
xprv = xprv_header(xtype, net=net) \
|
||||
+ bytes([depth]) + fingerprint + child_number + c + bytes([0]) + k
|
||||
return EncodeBase58Check(xprv)
|
||||
|
||||
|
||||
def serialize_xpub(xtype, c, cK, depth=0, fingerprint=b'\x00'*4, child_number=b'\x00'*4):
|
||||
xpub = xpub_header(xtype) + bytes([depth]) + fingerprint + child_number + c + cK
|
||||
def serialize_xpub(xtype, c, cK, depth=0, fingerprint=b'\x00'*4,
|
||||
child_number=b'\x00'*4, *, net=None):
|
||||
xpub = xpub_header(xtype, net=net) \
|
||||
+ bytes([depth]) + fingerprint + child_number + c + cK
|
||||
return EncodeBase58Check(xpub)
|
||||
|
||||
|
||||
def deserialize_xkey(xkey, prv):
|
||||
def deserialize_xkey(xkey, prv, *, net=None):
|
||||
if net is None:
|
||||
net = constants.net
|
||||
xkey = DecodeBase58Check(xkey)
|
||||
if len(xkey) != 78:
|
||||
raise BaseException('Invalid length')
|
||||
@@ -939,7 +882,7 @@ def deserialize_xkey(xkey, prv):
|
||||
child_number = xkey[9:13]
|
||||
c = xkey[13:13+32]
|
||||
header = int('0x' + bh2u(xkey[0:4]), 16)
|
||||
headers = NetworkConstants.XPRV_HEADERS if prv else NetworkConstants.XPUB_HEADERS
|
||||
headers = net.XPRV_HEADERS if prv else net.XPUB_HEADERS
|
||||
if header not in headers.values():
|
||||
raise BaseException('Invalid xpub format', hex(header))
|
||||
xtype = list(headers.keys())[list(headers.values()).index(header)]
|
||||
@@ -948,11 +891,11 @@ def deserialize_xkey(xkey, prv):
|
||||
return xtype, depth, fingerprint, child_number, c, K_or_k
|
||||
|
||||
|
||||
def deserialize_xpub(xkey):
|
||||
return deserialize_xkey(xkey, False)
|
||||
def deserialize_xpub(xkey, *, net=None):
|
||||
return deserialize_xkey(xkey, False, net=net)
|
||||
|
||||
def deserialize_xprv(xkey):
|
||||
return deserialize_xkey(xkey, True)
|
||||
def deserialize_xprv(xkey, *, net=None):
|
||||
return deserialize_xkey(xkey, True, net=net)
|
||||
|
||||
def xpub_type(x):
|
||||
return deserialize_xpub(x)[0]
|
||||
|
||||
Reference in New Issue
Block a user