mirror of
https://github.com/dashpay/dash.git
synced 2024-12-26 12:32:48 +01:00
aaf55d25c6
It turns out that some miners have been staying with old versions of Bitcoin Core because their software behaves poorly with persistent connections and the Bitcoin Core thread and connection limits. What happens is that underlying HTTP libraries leave connections open invisibly to their users and then the user runs into the default four thread limit. This looks like Bitcoin Core is unresponsive to RPC. There are many things that should be improved in Bitcoin Core's behavior here, e.g. supporting more concurrent connections, not tying up threads for idle connections, disconnecting kept-alive connections when limits are reached, etc. All are fairly big, risky changes. Disabling keep-alive is a simple workaround. It's often not easy to turn off the keep-alive support in the client where it may be buried in some platform library. If you are one of the few who really needs persistent connections you probably know that you want them and can find a switch; while if you don't and the misbehavior is hitting you it is hard to discover the source of your problems is keepalive related. Given that it is best to default to off until they're handled better. Github-Merge: #5655 Rebased-From:16a5c18cea
56c1093dae
1dd8ee72af
143 lines
4.6 KiB
Python
Executable File
143 lines
4.6 KiB
Python
Executable File
#!/usr/bin/env python2
|
|
# Copyright (c) 2014 The Bitcoin Core developers
|
|
# Distributed under the MIT software license, see the accompanying
|
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
# Base class for RPC testing
|
|
|
|
# Add python-bitcoinrpc to module search path:
|
|
import os
|
|
import sys
|
|
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), "python-bitcoinrpc"))
|
|
|
|
import shutil
|
|
import tempfile
|
|
import traceback
|
|
|
|
from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
|
|
from util import *
|
|
|
|
|
|
class BitcoinTestFramework(object):
|
|
|
|
# These may be over-ridden by subclasses:
|
|
def run_test(self):
|
|
for node in self.nodes:
|
|
assert_equal(node.getblockcount(), 200)
|
|
assert_equal(node.getbalance(), 25*50)
|
|
|
|
def add_options(self, parser):
|
|
pass
|
|
|
|
def setup_chain(self):
|
|
print("Initializing test directory "+self.options.tmpdir)
|
|
initialize_chain(self.options.tmpdir)
|
|
|
|
def setup_nodes(self):
|
|
return start_nodes(4, self.options.tmpdir)
|
|
|
|
def setup_network(self, split = False):
|
|
self.nodes = self.setup_nodes()
|
|
|
|
# Connect the nodes as a "chain". This allows us
|
|
# to split the network between nodes 1 and 2 to get
|
|
# two halves that can work on competing chains.
|
|
|
|
# If we joined network halves, connect the nodes from the joint
|
|
# on outward. This ensures that chains are properly reorganised.
|
|
if not split:
|
|
connect_nodes_bi(self.nodes, 1, 2)
|
|
sync_blocks(self.nodes[1:3])
|
|
sync_mempools(self.nodes[1:3])
|
|
|
|
connect_nodes_bi(self.nodes, 0, 1)
|
|
connect_nodes_bi(self.nodes, 2, 3)
|
|
self.is_network_split = split
|
|
self.sync_all()
|
|
|
|
def split_network(self):
|
|
"""
|
|
Split the network of four nodes into nodes 0/1 and 2/3.
|
|
"""
|
|
assert not self.is_network_split
|
|
stop_nodes(self.nodes)
|
|
wait_bitcoinds()
|
|
self.setup_network(True)
|
|
|
|
def sync_all(self):
|
|
if self.is_network_split:
|
|
sync_blocks(self.nodes[:2])
|
|
sync_blocks(self.nodes[2:])
|
|
sync_mempools(self.nodes[:2])
|
|
sync_mempools(self.nodes[2:])
|
|
else:
|
|
sync_blocks(self.nodes)
|
|
sync_mempools(self.nodes)
|
|
|
|
def join_network(self):
|
|
"""
|
|
Join the (previously split) network halves together.
|
|
"""
|
|
assert self.is_network_split
|
|
stop_nodes(self.nodes)
|
|
wait_bitcoinds()
|
|
self.setup_network(False)
|
|
|
|
def main(self):
|
|
import optparse
|
|
|
|
parser = optparse.OptionParser(usage="%prog [options]")
|
|
parser.add_option("--nocleanup", dest="nocleanup", default=False, action="store_true",
|
|
help="Leave bitcoinds and test.* datadir on exit or error")
|
|
parser.add_option("--srcdir", dest="srcdir", default="../../src",
|
|
help="Source directory containing bitcoind/bitcoin-cli (default: %default%)")
|
|
parser.add_option("--tmpdir", dest="tmpdir", default=tempfile.mkdtemp(prefix="test"),
|
|
help="Root directory for datadirs")
|
|
parser.add_option("--tracerpc", dest="trace_rpc", default=False, action="store_true",
|
|
help="Print out all RPC calls as they are made")
|
|
self.add_options(parser)
|
|
(self.options, self.args) = parser.parse_args()
|
|
|
|
if self.options.trace_rpc:
|
|
import logging
|
|
logging.basicConfig(level=logging.DEBUG)
|
|
|
|
os.environ['PATH'] = self.options.srcdir+":"+os.environ['PATH']
|
|
|
|
check_json_precision()
|
|
|
|
success = False
|
|
try:
|
|
if not os.path.isdir(self.options.tmpdir):
|
|
os.makedirs(self.options.tmpdir)
|
|
self.setup_chain()
|
|
|
|
self.setup_network()
|
|
|
|
self.run_test()
|
|
|
|
success = True
|
|
|
|
except JSONRPCException as e:
|
|
print("JSONRPC error: "+e.error['message'])
|
|
traceback.print_tb(sys.exc_info()[2])
|
|
except AssertionError as e:
|
|
print("Assertion failed: "+e.message)
|
|
traceback.print_tb(sys.exc_info()[2])
|
|
except Exception as e:
|
|
print("Unexpected exception caught during testing: "+str(e))
|
|
traceback.print_tb(sys.exc_info()[2])
|
|
|
|
if not self.options.nocleanup:
|
|
print("Cleaning up")
|
|
stop_nodes(self.nodes)
|
|
wait_bitcoinds()
|
|
shutil.rmtree(self.options.tmpdir)
|
|
|
|
if success:
|
|
print("Tests successful")
|
|
sys.exit(0)
|
|
else:
|
|
print("Failed")
|
|
sys.exit(1)
|