Merge pull request #3257 from SomberNight/bitcoin_network_constants
bitcoin.NetworkConstants: easier changing between testnet and mainnet
This commit is contained in:
commit
0ecb665b95
2
electrum
2
electrum
|
@ -357,7 +357,7 @@ if __name__ == '__main__':
|
||||||
cmdname = config.get('cmd')
|
cmdname = config.get('cmd')
|
||||||
|
|
||||||
if config.get('testnet'):
|
if config.get('testnet'):
|
||||||
bitcoin.set_testnet()
|
bitcoin.NetworkConstants.set_testnet()
|
||||||
|
|
||||||
# run non-RPC commands separately
|
# run non-RPC commands separately
|
||||||
if cmdname in ['create', 'restore']:
|
if cmdname in ['create', 'restore']:
|
||||||
|
|
|
@ -95,8 +95,8 @@ class ElectrumWindow(App):
|
||||||
from .uix.dialogs.choice_dialog import ChoiceDialog
|
from .uix.dialogs.choice_dialog import ChoiceDialog
|
||||||
protocol = 's'
|
protocol = 's'
|
||||||
def cb2(host):
|
def cb2(host):
|
||||||
from electrum.network import DEFAULT_PORTS
|
from electrum.bitcoin import NetworkConstants
|
||||||
pp = servers.get(host, DEFAULT_PORTS)
|
pp = servers.get(host, NetworkConstants.DEFAULT_PORTS)
|
||||||
port = pp.get(protocol, '')
|
port = pp.get(protocol, '')
|
||||||
popup.ids.host.text = host
|
popup.ids.host.text = host
|
||||||
popup.ids.port.text = port
|
popup.ids.port.text = port
|
||||||
|
|
|
@ -30,7 +30,7 @@ from PyQt5.QtCore import *
|
||||||
import PyQt5.QtCore as QtCore
|
import PyQt5.QtCore as QtCore
|
||||||
|
|
||||||
from electrum.i18n import _
|
from electrum.i18n import _
|
||||||
from electrum.network import DEFAULT_PORTS
|
from electrum.bitcoin import NetworkConstants
|
||||||
from electrum.network import serialize_server, deserialize_server
|
from electrum.network import serialize_server, deserialize_server
|
||||||
from electrum.util import print_error
|
from electrum.util import print_error
|
||||||
|
|
||||||
|
@ -397,7 +397,7 @@ class NetworkChoiceLayout(object):
|
||||||
def change_protocol(self, use_ssl):
|
def change_protocol(self, use_ssl):
|
||||||
p = 's' if use_ssl else 't'
|
p = 's' if use_ssl else 't'
|
||||||
host = self.server_host.text()
|
host = self.server_host.text()
|
||||||
pp = self.servers.get(host, DEFAULT_PORTS)
|
pp = self.servers.get(host, NetworkConstants.DEFAULT_PORTS)
|
||||||
if p not in pp.keys():
|
if p not in pp.keys():
|
||||||
p = list(pp.keys())[0]
|
p = list(pp.keys())[0]
|
||||||
port = pp[p]
|
port = pp[p]
|
||||||
|
@ -422,7 +422,7 @@ class NetworkChoiceLayout(object):
|
||||||
self.change_server(str(x.text(0)), self.protocol)
|
self.change_server(str(x.text(0)), self.protocol)
|
||||||
|
|
||||||
def change_server(self, host, protocol):
|
def change_server(self, host, protocol):
|
||||||
pp = self.servers.get(host, DEFAULT_PORTS)
|
pp = self.servers.get(host, NetworkConstants.DEFAULT_PORTS)
|
||||||
if protocol and protocol not in protocol_letters:
|
if protocol and protocol not in protocol_letters:
|
||||||
protocol = None
|
protocol = None
|
||||||
if protocol:
|
if protocol:
|
||||||
|
|
|
@ -69,36 +69,34 @@ XPUB_HEADERS = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# Bitcoin network constants
|
class NetworkConstants:
|
||||||
TESTNET = False
|
|
||||||
WIF_PREFIX = 0x80
|
|
||||||
ADDRTYPE_P2PKH = 0
|
|
||||||
ADDRTYPE_P2SH = 5
|
|
||||||
SEGWIT_HRP = "bc"
|
|
||||||
HEADERS_URL = "https://headers.electrum.org/blockchain_headers"
|
|
||||||
GENESIS = "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"
|
|
||||||
SERVERLIST = 'servers.json'
|
|
||||||
DEFAULT_PORTS = {'t':'50001', 's':'50002'}
|
|
||||||
DEFAULT_SERVERS = read_json_dict('servers.json')
|
|
||||||
|
|
||||||
def set_testnet():
|
@classmethod
|
||||||
global ADDRTYPE_P2PKH, ADDRTYPE_P2SH
|
def set_mainnet(cls):
|
||||||
global TESTNET, HEADERS_URL
|
cls.TESTNET = False
|
||||||
global GENESIS
|
cls.WIF_PREFIX = 0x80
|
||||||
global SEGWIT_HRP
|
cls.ADDRTYPE_P2PKH = 0
|
||||||
global DEFAULT_PORTS, SERVERLIST, DEFAULT_SERVERS
|
cls.ADDRTYPE_P2SH = 5
|
||||||
global WIF_PREFIX
|
cls.SEGWIT_HRP = "bc"
|
||||||
TESTNET = True
|
cls.HEADERS_URL = "https://headers.electrum.org/blockchain_headers"
|
||||||
WIF_PREFIX = 0xef
|
cls.GENESIS = "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"
|
||||||
ADDRTYPE_P2PKH = 111
|
cls.DEFAULT_PORTS = {'t': '50001', 's': '50002'}
|
||||||
ADDRTYPE_P2SH = 196
|
cls.DEFAULT_SERVERS = read_json_dict('servers.json')
|
||||||
SEGWIT_HRP = "tb"
|
|
||||||
HEADERS_URL = "https://headers.electrum.org/testnet_headers"
|
|
||||||
GENESIS = "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"
|
|
||||||
SERVERLIST = 'servers_testnet.json'
|
|
||||||
DEFAULT_PORTS = {'t':'51001', 's':'51002'}
|
|
||||||
DEFAULT_SERVERS = read_json_dict('servers_testnet.json')
|
|
||||||
|
|
||||||
|
@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.HEADERS_URL = "https://headers.electrum.org/testnet_headers"
|
||||||
|
cls.GENESIS = "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"
|
||||||
|
cls.DEFAULT_PORTS = {'t':'51001', 's':'51002'}
|
||||||
|
cls.DEFAULT_SERVERS = read_json_dict('servers_testnet.json')
|
||||||
|
|
||||||
|
|
||||||
|
NetworkConstants.set_mainnet()
|
||||||
|
|
||||||
################################## transactions
|
################################## transactions
|
||||||
|
|
||||||
|
@ -339,16 +337,16 @@ def b58_address_to_hash160(addr):
|
||||||
|
|
||||||
|
|
||||||
def hash160_to_p2pkh(h160):
|
def hash160_to_p2pkh(h160):
|
||||||
return hash160_to_b58_address(h160, ADDRTYPE_P2PKH)
|
return hash160_to_b58_address(h160, NetworkConstants.ADDRTYPE_P2PKH)
|
||||||
|
|
||||||
def hash160_to_p2sh(h160):
|
def hash160_to_p2sh(h160):
|
||||||
return hash160_to_b58_address(h160, ADDRTYPE_P2SH)
|
return hash160_to_b58_address(h160, NetworkConstants.ADDRTYPE_P2SH)
|
||||||
|
|
||||||
def public_key_to_p2pkh(public_key):
|
def public_key_to_p2pkh(public_key):
|
||||||
return hash160_to_p2pkh(hash_160(public_key))
|
return hash160_to_p2pkh(hash_160(public_key))
|
||||||
|
|
||||||
def hash_to_segwit_addr(h):
|
def hash_to_segwit_addr(h):
|
||||||
return segwit_addr.encode(SEGWIT_HRP, 0, h)
|
return segwit_addr.encode(NetworkConstants.SEGWIT_HRP, 0, h)
|
||||||
|
|
||||||
def public_key_to_p2wpkh(public_key):
|
def public_key_to_p2wpkh(public_key):
|
||||||
return hash_to_segwit_addr(hash_160(public_key))
|
return hash_to_segwit_addr(hash_160(public_key))
|
||||||
|
@ -394,7 +392,7 @@ def script_to_address(script):
|
||||||
return addr
|
return addr
|
||||||
|
|
||||||
def address_to_script(addr):
|
def address_to_script(addr):
|
||||||
witver, witprog = segwit_addr.decode(SEGWIT_HRP, addr)
|
witver, witprog = segwit_addr.decode(NetworkConstants.SEGWIT_HRP, addr)
|
||||||
if witprog is not None:
|
if witprog is not None:
|
||||||
assert (0 <= witver <= 16)
|
assert (0 <= witver <= 16)
|
||||||
OP_n = witver + 0x50 if witver > 0 else 0
|
OP_n = witver + 0x50 if witver > 0 else 0
|
||||||
|
@ -402,11 +400,11 @@ def address_to_script(addr):
|
||||||
script += push_script(bh2u(bytes(witprog)))
|
script += push_script(bh2u(bytes(witprog)))
|
||||||
return script
|
return script
|
||||||
addrtype, hash_160 = b58_address_to_hash160(addr)
|
addrtype, hash_160 = b58_address_to_hash160(addr)
|
||||||
if addrtype == ADDRTYPE_P2PKH:
|
if addrtype == NetworkConstants.ADDRTYPE_P2PKH:
|
||||||
script = '76a9' # op_dup, op_hash_160
|
script = '76a9' # op_dup, op_hash_160
|
||||||
script += push_script(bh2u(hash_160))
|
script += push_script(bh2u(hash_160))
|
||||||
script += '88ac' # op_equalverify, op_checksig
|
script += '88ac' # op_equalverify, op_checksig
|
||||||
elif addrtype == ADDRTYPE_P2SH:
|
elif addrtype == NetworkConstants.ADDRTYPE_P2SH:
|
||||||
script = 'a9' # op_hash_160
|
script = 'a9' # op_hash_160
|
||||||
script += push_script(bh2u(hash_160))
|
script += push_script(bh2u(hash_160))
|
||||||
script += '87' # op_equal
|
script += '87' # op_equal
|
||||||
|
@ -524,7 +522,7 @@ SCRIPT_TYPES = {
|
||||||
|
|
||||||
|
|
||||||
def serialize_privkey(secret, compressed, txin_type):
|
def serialize_privkey(secret, compressed, txin_type):
|
||||||
prefix = bytes([(SCRIPT_TYPES[txin_type]+WIF_PREFIX)&255])
|
prefix = bytes([(SCRIPT_TYPES[txin_type]+NetworkConstants.WIF_PREFIX)&255])
|
||||||
suffix = b'\01' if compressed else b''
|
suffix = b'\01' if compressed else b''
|
||||||
vchIn = prefix + secret + suffix
|
vchIn = prefix + secret + suffix
|
||||||
return EncodeBase58Check(vchIn)
|
return EncodeBase58Check(vchIn)
|
||||||
|
@ -536,7 +534,7 @@ def deserialize_privkey(key):
|
||||||
if is_minikey(key):
|
if is_minikey(key):
|
||||||
return 'p2pkh', minikey_to_private_key(key), True
|
return 'p2pkh', minikey_to_private_key(key), True
|
||||||
elif vch:
|
elif vch:
|
||||||
txin_type = inv_dict(SCRIPT_TYPES)[vch[0] - WIF_PREFIX]
|
txin_type = inv_dict(SCRIPT_TYPES)[vch[0] - NetworkConstants.WIF_PREFIX]
|
||||||
assert len(vch) in [33, 34]
|
assert len(vch) in [33, 34]
|
||||||
compressed = len(vch) == 34
|
compressed = len(vch) == 34
|
||||||
return txin_type, vch[1:33], compressed
|
return txin_type, vch[1:33], compressed
|
||||||
|
@ -571,7 +569,7 @@ def address_from_private_key(sec):
|
||||||
return pubkey_to_address(txin_type, public_key)
|
return pubkey_to_address(txin_type, public_key)
|
||||||
|
|
||||||
def is_segwit_address(addr):
|
def is_segwit_address(addr):
|
||||||
witver, witprog = segwit_addr.decode(SEGWIT_HRP, addr)
|
witver, witprog = segwit_addr.decode(NetworkConstants.SEGWIT_HRP, addr)
|
||||||
return witprog is not None
|
return witprog is not None
|
||||||
|
|
||||||
def is_b58_address(addr):
|
def is_b58_address(addr):
|
||||||
|
@ -579,7 +577,7 @@ def is_b58_address(addr):
|
||||||
addrtype, h = b58_address_to_hash160(addr)
|
addrtype, h = b58_address_to_hash160(addr)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return False
|
return False
|
||||||
if addrtype not in [ADDRTYPE_P2PKH, ADDRTYPE_P2SH]:
|
if addrtype not in [NetworkConstants.ADDRTYPE_P2PKH, NetworkConstants.ADDRTYPE_P2SH]:
|
||||||
return False
|
return False
|
||||||
return addr == hash160_to_b58_address(h, addrtype)
|
return addr == hash160_to_b58_address(h, addrtype)
|
||||||
|
|
||||||
|
|
|
@ -148,7 +148,7 @@ class Blockchain(util.PrintError):
|
||||||
_hash = hash_header(header)
|
_hash = hash_header(header)
|
||||||
if prev_hash != header.get('prev_block_hash'):
|
if prev_hash != header.get('prev_block_hash'):
|
||||||
raise BaseException("prev hash mismatch: %s vs %s" % (prev_hash, header.get('prev_block_hash')))
|
raise BaseException("prev hash mismatch: %s vs %s" % (prev_hash, header.get('prev_block_hash')))
|
||||||
if bitcoin.TESTNET:
|
if bitcoin.NetworkConstants.TESTNET:
|
||||||
return
|
return
|
||||||
if bits != header.get('bits'):
|
if bits != header.get('bits'):
|
||||||
raise BaseException("bits mismatch: %s vs %s" % (bits, header.get('bits')))
|
raise BaseException("bits mismatch: %s vs %s" % (bits, header.get('bits')))
|
||||||
|
@ -265,7 +265,7 @@ class Blockchain(util.PrintError):
|
||||||
return sum([self.BIP9(h-i, 2) for i in range(N)])*10000/N/100.
|
return sum([self.BIP9(h-i, 2) for i in range(N)])*10000/N/100.
|
||||||
|
|
||||||
def get_target(self, index):
|
def get_target(self, index):
|
||||||
if bitcoin.TESTNET:
|
if bitcoin.NetworkConstants.TESTNET:
|
||||||
return 0, 0
|
return 0, 0
|
||||||
if index == 0:
|
if index == 0:
|
||||||
return 0x1d00ffff, MAX_TARGET
|
return 0x1d00ffff, MAX_TARGET
|
||||||
|
@ -302,7 +302,7 @@ class Blockchain(util.PrintError):
|
||||||
if check_height and self.height() != height - 1:
|
if check_height and self.height() != height - 1:
|
||||||
return False
|
return False
|
||||||
if height == 0:
|
if height == 0:
|
||||||
return hash_header(header) == bitcoin.GENESIS
|
return hash_header(header) == bitcoin.NetworkConstants.GENESIS
|
||||||
previous_header = self.read_header(height -1)
|
previous_header = self.read_header(height -1)
|
||||||
if not previous_header:
|
if not previous_header:
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -678,7 +678,7 @@ is_bip32_key = lambda x: is_xprv(x) or is_xpub(x)
|
||||||
|
|
||||||
def bip44_derivation(account_id, segwit=False):
|
def bip44_derivation(account_id, segwit=False):
|
||||||
bip = 49 if segwit else 44
|
bip = 49 if segwit else 44
|
||||||
coin = 1 if bitcoin.TESTNET else 0
|
coin = 1 if bitcoin.NetworkConstants.TESTNET else 0
|
||||||
return "m/%d'/%d'/%d'" % (bip, coin, int(account_id))
|
return "m/%d'/%d'/%d'" % (bip, coin, int(account_id))
|
||||||
|
|
||||||
def from_seed(seed, passphrase, is_p2sh):
|
def from_seed(seed, passphrase, is_p2sh):
|
||||||
|
|
|
@ -66,7 +66,7 @@ def parse_servers(result):
|
||||||
for v in item[2]:
|
for v in item[2]:
|
||||||
if re.match("[st]\d*", v):
|
if re.match("[st]\d*", v):
|
||||||
protocol, port = v[0], v[1:]
|
protocol, port = v[0], v[1:]
|
||||||
if port == '': port = bitcoin.DEFAULT_PORTS[protocol]
|
if port == '': port = bitcoin.NetworkConstants.DEFAULT_PORTS[protocol]
|
||||||
out[protocol] = port
|
out[protocol] = port
|
||||||
elif re.match("v(.?)+", v):
|
elif re.match("v(.?)+", v):
|
||||||
version = v[1:]
|
version = v[1:]
|
||||||
|
@ -100,7 +100,7 @@ def filter_protocol(hostmap, protocol = 's'):
|
||||||
|
|
||||||
def pick_random_server(hostmap = None, protocol = 's', exclude_set = set()):
|
def pick_random_server(hostmap = None, protocol = 's', exclude_set = set()):
|
||||||
if hostmap is None:
|
if hostmap is None:
|
||||||
hostmap = bitcoin.DEFAULT_SERVERS
|
hostmap = bitcoin.NetworkConstants.DEFAULT_SERVERS
|
||||||
eligible = list(set(filter_protocol(hostmap, protocol)) - exclude_set)
|
eligible = list(set(filter_protocol(hostmap, protocol)) - exclude_set)
|
||||||
return random.choice(eligible) if eligible else None
|
return random.choice(eligible) if eligible else None
|
||||||
|
|
||||||
|
@ -363,7 +363,7 @@ class Network(util.DaemonThread):
|
||||||
return list(self.interfaces.keys())
|
return list(self.interfaces.keys())
|
||||||
|
|
||||||
def get_servers(self):
|
def get_servers(self):
|
||||||
out = bitcoin.DEFAULT_SERVERS
|
out = bitcoin.NetworkConstants.DEFAULT_SERVERS
|
||||||
if self.irc_servers:
|
if self.irc_servers:
|
||||||
out.update(filter_version(self.irc_servers.copy()))
|
out.update(filter_version(self.irc_servers.copy()))
|
||||||
else:
|
else:
|
||||||
|
@ -947,7 +947,7 @@ class Network(util.DaemonThread):
|
||||||
|
|
||||||
def init_headers_file(self):
|
def init_headers_file(self):
|
||||||
b = self.blockchains[0]
|
b = self.blockchains[0]
|
||||||
if b.get_hash(0) == bitcoin.GENESIS:
|
if b.get_hash(0) == bitcoin.NetworkConstants.GENESIS:
|
||||||
self.downloading_headers = False
|
self.downloading_headers = False
|
||||||
return
|
return
|
||||||
filename = b.path()
|
filename = b.path()
|
||||||
|
@ -955,8 +955,8 @@ class Network(util.DaemonThread):
|
||||||
try:
|
try:
|
||||||
import urllib.request, socket
|
import urllib.request, socket
|
||||||
socket.setdefaulttimeout(30)
|
socket.setdefaulttimeout(30)
|
||||||
self.print_error("downloading ", bitcoin.HEADERS_URL)
|
self.print_error("downloading ", bitcoin.NetworkConstants.HEADERS_URL)
|
||||||
urllib.request.urlretrieve(bitcoin.HEADERS_URL, filename + '.tmp')
|
urllib.request.urlretrieve(bitcoin.NetworkConstants.HEADERS_URL, filename + '.tmp')
|
||||||
os.rename(filename + '.tmp', filename)
|
os.rename(filename + '.tmp', filename)
|
||||||
self.print_error("done.")
|
self.print_error("done.")
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|
|
@ -476,7 +476,7 @@ testnet_block_explorers = {
|
||||||
|
|
||||||
def block_explorer_info():
|
def block_explorer_info():
|
||||||
from . import bitcoin
|
from . import bitcoin
|
||||||
return testnet_block_explorers if bitcoin.TESTNET else mainnet_block_explorers
|
return testnet_block_explorers if bitcoin.NetworkConstants.TESTNET else mainnet_block_explorers
|
||||||
|
|
||||||
def block_explorer(config):
|
def block_explorer(config):
|
||||||
return config.get('block_explorer', 'Blocktrail.com')
|
return config.get('block_explorer', 'Blocktrail.com')
|
||||||
|
|
|
@ -9,7 +9,7 @@ from electrum.util import bfh, bh2u
|
||||||
from electrum.bitcoin import (is_segwit_address, b58_address_to_hash160, xpub_from_pubkey,
|
from electrum.bitcoin import (is_segwit_address, b58_address_to_hash160, xpub_from_pubkey,
|
||||||
public_key_to_p2pkh, EncodeBase58Check,
|
public_key_to_p2pkh, EncodeBase58Check,
|
||||||
TYPE_ADDRESS, TYPE_SCRIPT,
|
TYPE_ADDRESS, TYPE_SCRIPT,
|
||||||
TESTNET, ADDRTYPE_P2PKH, ADDRTYPE_P2SH)
|
NetworkConstants)
|
||||||
from electrum.i18n import _
|
from electrum.i18n import _
|
||||||
from electrum.plugins import BasePlugin, hook
|
from electrum.plugins import BasePlugin, hook
|
||||||
from electrum.transaction import deserialize, Transaction
|
from electrum.transaction import deserialize, Transaction
|
||||||
|
@ -142,7 +142,7 @@ class TrezorCompatiblePlugin(HW_PluginBase):
|
||||||
return client
|
return client
|
||||||
|
|
||||||
def get_coin_name(self):
|
def get_coin_name(self):
|
||||||
return "Testnet" if TESTNET else "Bitcoin"
|
return "Testnet" if NetworkConstants.TESTNET else "Bitcoin"
|
||||||
|
|
||||||
def initialize_device(self, device_id, wizard, handler):
|
def initialize_device(self, device_id, wizard, handler):
|
||||||
# Initialization method
|
# Initialization method
|
||||||
|
|
Loading…
Reference in New Issue