Changeset View
Changeset View
Standalone View
Standalone View
contrib/devtools/update-chainparams.py
- This file was added.
Property | Old Value | New Value |
---|---|---|
File Mode | null | 100755 |
#!/usr/bin/env python3 | |||||
# Copyright (c) 2019 The Bitcoin developers | |||||
# Distributed under the MIT software license, see the accompanying | |||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php. | |||||
import argparse | |||||
import json | |||||
import re | |||||
import subprocess | |||||
import sys | |||||
parser = argparse.ArgumentParser(description=( | |||||
"Fetch a block from the bitcoin HTTP RPC to update chainparams" | |||||
"(nMinimumChainWork and defaultAssumeValid).\n\n" | |||||
"NOTE: bitcoind must have `--rest=1` set (either as a cli argument or in" | |||||
"the config)!"), formatter_class=argparse.RawTextHelpFormatter) | |||||
parser.add_argument('--hostaddr', '-a', | |||||
default="localhost", | |||||
help="Host address of the HTTP RPC bitcoind server to call" | |||||
"for fetching chain info. (defaults to `localhost`)") | |||||
parser.add_argument('--hostport', '-p', | |||||
help="Host port of the HTTP RPC bitcoind server to call" | |||||
"for fetching chain info. (defaults to 8332 on mainnet and 18332 on testnet)") | |||||
parser.add_argument('--testnet', '-t', action="store_true", | |||||
help="If set, testnet chainparams will be updated instead" | |||||
"of mainnet chainparams. If testnet is set, but hostport is not set, hostport will default to 18332.") | |||||
parser.add_argument('--blockhash', '-b', | |||||
help="(optional) The block hash to update chainparams" | |||||
"with. If not specified, bestblockhash is used.") | |||||
args = parser.parse_args() | |||||
def curl(url): | |||||
# Call bitcoin HTTP RPC using curl | |||||
print("Fetching URL: {}".format(url)) | |||||
curlArgs = ['curl', '-s', url] | |||||
p = subprocess.Popen('curl -s ' + url, stdout=subprocess.PIPE, shell=True) | |||||
output = p.communicate()[0] | |||||
status = p.wait() | |||||
if status != 0: | |||||
print("curl error status: {}\nSee https://curl.haxx.se/libcurl/c/libcurl-errors.html for error descriptions.".format(status)) | |||||
exit(1) | |||||
output = output.decode('utf-8') | |||||
try: | |||||
return json.loads(output) | |||||
except: | |||||
print("Error while parsing JSON:\n{}".format(sys.exc_info())) | |||||
print("Output from HTTP RPC call:\n{}".format(output)) | |||||
exit(2) | |||||
port = args.hostport | |||||
if not port: | |||||
port = '18332' if args.testnet else '8332' | |||||
url = args.hostaddr + ':' + port | |||||
# Get best block hash and chainwork | |||||
chaininfo = curl(url + '/rest/chaininfo.json') | |||||
if (args.testnet is True and chaininfo['chain'] != 'test') or (args.testnet is False and chaininfo['chain'] != 'main'): | |||||
print("The chain network specified did not match the one given by the host node!") | |||||
print("Did you mean to call with a different `--hostaddr` or `--hostport`, or with `--testnet` set?") | |||||
exit(3) | |||||
blockhash = chaininfo['bestblockhash'] | |||||
chainwork = chaininfo['chainwork'] | |||||
if args.blockhash: | |||||
blockhash = args.blockhash | |||||
print("Fetching chainwork for block {}".format(blockhash)) | |||||
block = curl(url + '/rest/block/' + blockhash + '.json') | |||||
chainwork = block['chainwork'] | |||||
chainParamsClass = 'TestNetParams' if args.testnet else 'MainParams' | |||||
# Get top-level path for the project | |||||
p = subprocess.Popen('git rev-parse --show-toplevel', | |||||
stdout=subprocess.PIPE, shell=True) | |||||
toplevel = p.communicate()[0] | |||||
p.wait() | |||||
# Read-write to chainparams.cpp | |||||
f = open(toplevel.decode('utf-8').rstrip() + '/src/chainparams.cpp', 'r+') | |||||
chainParamsContents = f.read() | |||||
# Replace chainparams with the new values for the specified chainparams class | |||||
chainParamsContents = re.sub('(' + chainParamsClass + '.*?nMinimumChainWork.*?")([0-9a-z]+)("\);)', | |||||
'\g<1>' + chainwork + '\g<3>', chainParamsContents, flags=re.MULTILINE | re.DOTALL) | |||||
chainParamsContents = re.sub('(' + chainParamsClass + '.*?defaultAssumeValid.*?")([0-9a-z]+)("\);)', | |||||
'\g<1>' + blockhash + '\g<3>', chainParamsContents, flags=re.MULTILINE | re.DOTALL) | |||||
f.seek(0) | |||||
f.write(chainParamsContents) | |||||
f.close() |