files: #!/usr/bin/env python3
  # Copyright (c) 2014-2015 The Bitcoin Core developers
  # Copyright (c) 2015-2017 The Bitcoin Unlimited developers
  # Distributed under the MIT software license, see the accompanying
  # file COPYING or http://www.opensource.org/licenses/mit-license.php.
  
  """
  Run Regression Test Suite
  
  This module calls down into individual test cases via subprocess. It will
  forward all unrecognized arguments onto the individual test scripts, other
  than:
  
      - `-h` or '--help': print help about all options
      - `-extended`: run the "extended" test suite in addition to the basic one.
      - `-extended-only`: run ONLY the "extended" test suite
      - `-list`: only list the test scripts, do not run. Works in combination
        with '-extended' and '-extended-only' too, to print subsets.
      - `-win`: signal that this is running in a Windows environment, and we
        should run the tests.
      - `--coverage`: this generates a basic coverage report for the RPC
        interface.
  
  For more detailed help on options, run with '--help'.
  
  For a description of arguments recognized by test scripts, see
  `qa/pull-tester/test_framework/test_framework.py:BitcoinTestFramework.main`.
  
  """
  import pdb
  import os
  import time
  import shutil
  import sys
  import subprocess
  import tempfile
  import re
  
  sys.path.append("qa/pull-tester/")
  from tests_config import *
  from test_classes import RpcTest, Disabled, Skip
  
  BOLD = ("","")
  if os.name == 'posix':
      # primitive formatting on supported
      # terminal via ANSI escape sequences:
      BOLD = ('\033[0m', '\033[1m')
  
  RPC_TESTS_DIR = SRCDIR + '/qa/rpc-tests/'
  
  #If imported values are not defined then set to zero (or disabled)
  if 'ENABLE_WALLET' not in vars():
      ENABLE_WALLET=0
  if 'ENABLE_BITCOIND' not in vars():
      ENABLE_BITCOIND=0
  if 'ENABLE_UTILS' not in vars():
      ENABLE_UTILS=0
  if 'ENABLE_ZMQ' not in vars():
      ENABLE_ZMQ=0
  
  ENABLE_COVERAGE=0
  
  #Create a set to store arguments and create the passOn string
  opts = set()
  double_opts = set()  # BU: added for checking validity of -- opts
  passOn = ""
  showHelp = False  # if we need to print help
  p = re.compile("^--")
  # some of the single-dash options applicable only to this runner script
  # are also allowed in double-dash format (but are not passed on to the
  # test scripts themselves)
  private_single_opts = ('-h',
                         '-f',    # equivalent to -force-enable
                         '-help',
                         '-list',
                         '-extended',
                         '-extended-only',
                         '-only-extended',
                         '-force-enable',
                         '-win')
  private_double_opts = ('--list',
                         '--extended',
                         '--extended-only',
                         '--only-extended',
                         '--force-enable',
                         '--win')
  framework_opts = ('--tracerpc',
                    '--help',
                    '--noshutdown',
                    '--nocleanup',
                    '--srcdir',
                    '--tmpdir',
                    '--coveragedir',
                    '--randomseed',
                    '--testbinary',
                    '--refbinary')
  test_script_opts = ('--mineblock',
                      '--extensive')
  
  def option_passed(option_without_dashes):
      """check if option was specified in single-dash or double-dash format"""
      return ('-' + option_without_dashes in opts
              or '--' + option_without_dashes in double_opts)
  
  bold = ("","")
  if (os.name == 'posix'):
      bold = ('\033[0m', '\033[1m')
  
  for arg in sys.argv[1:]:
      if arg == '--coverage':
          ENABLE_COVERAGE = 1
      elif (p.match(arg) or arg in ('-h', '-help')):
          if arg not in private_double_opts:
              if arg == '--help' or arg == '-help' or arg == '-h':
                  passOn = '--help'
                  showHelp = True
              else:
                  if passOn is not '--help':
                      passOn += " " + arg
          # add it to double_opts only for validation
          double_opts.add(arg)
      else:
          # this is for single-dash options only
          # they are interpreted only by this script
          opts.add(arg)
  
  # check for unrecognized options
  bad_opts_found = []
  bad_opt_str="Unrecognized option: %s"
  for o in opts | double_opts:
      if o.startswith('--'):
          if o not in framework_opts + test_script_opts + private_double_opts:
              print(bad_opt_str % o)
              bad_opts_found.append(o)
      elif o.startswith('-'):
          if o not in private_single_opts:
              print(bad_opt_str % o)
              bad_opts_found.append(o)
              print("Run with -h to get help on usage.")
              sys.exit(1)
  
  #Set env vars
  if "BITCOIND" not in os.environ:
      os.environ["BITCOIND"] = BUILDDIR + '/src/bitcoind' + EXEEXT
  if "BITCOINCLI" not in os.environ:
      os.environ["BITCOINCLI"] = BUILDDIR + '/src/bitcoin-cli' + EXEEXT
  
  #Disable Windows tests by default
  if EXEEXT == ".exe" and not option_passed('win'):
      print("Win tests currently disabled.  Use -win option to enable")
      sys.exit(0)
  
  if not (ENABLE_WALLET == 1 and ENABLE_UTILS == 1 and ENABLE_BITCOIND == 1):
      print("No rpc tests to run. Wallet, utils, and bitcoind must all be enabled")
      sys.exit(0)
  
  # python3-zmq may not be installed. Handle this gracefully and with some helpful info
  if ENABLE_ZMQ:
      try:
          import zmq
      except ImportError as e:
          print("ERROR: \"import zmq\" failed. Set ENABLE_ZMQ=0 or " \
              "to run zmq tests, see dependency info in /qa/README.md.")
          raise e
  
  #Tests
  testScripts = [ RpcTest(t) for t in [
      'bip68-112-113-p2p',
      'validateblocktemplate',
      'parallel',
      'wallet',
      'excessive',
      'listtransactions',
      'receivedby',
      'mempool_resurrect_test',
      'txn_doublespend --mineblock',
      'txn_clone',
      'getchaintips',
      'rawtransactions',
      'rest',
      'mempool_spendcoinbase',
      'mempool_reorg',
      Disabled('mempool_limit', "mempool priority changes causes create_lots_of_big_transactions to fail"),
      'httpbasics',
      'multi_rpc',
      'zapwallettxes',
      'proxy_test',
      'merkle_blocks',
      'fundrawtransaction',
      'signrawtransactions',
      'walletbackup',
      'nodehandling',
      'reindex',
      'decodescript',
      Disabled('p2p-fullblocktest', "TODO"),
      'blockchain',
      'disablewallet',
      'sendheaders',
      'keypool',
      Disabled('prioritise_transaction', "TODO"),
      Disabled('invalidblockrequest', "TODO"),
      'invalidtxrequest',
      'abandonconflict',
      'p2p-versionbits-warning',
      'importprunedfunds',
      'thinblocks'
  ] ]
  
  testScriptsExt = [ RpcTest(t) for t in [
      'txPerf',
      'excessive --extensive',
      'parallel --extensive',
      'bip9-softforks',
      'bip65-cltv',
      'bip65-cltv-p2p',
      'bip68-sequence',
      'bipdersig-p2p',
      'bipdersig',
      'getblocktemplate_longpoll',
      'getblocktemplate_proposals',
      'txn_doublespend',
      'txn_clone --mineblock',
      Disabled('pruning', "too much disk"),
      'forknotify',
      'invalidateblock',
      Disabled('rpcbind_test', "temporary, bug in libevent, see #6655"),
      'smartfees',
      'maxblocksinflight',
      'p2p-acceptblock',
      'mempool_packages',
      'maxuploadtarget',
      Disabled('replace-by-fee', "disabled while Replace By Fee is disabled in code")
  ] ]
  
  #Enable ZMQ tests
  if ENABLE_ZMQ == 1:
      testScripts.append(RpcTest('zmq_test'))
  
  
  def show_wrapper_options():
      """ print command line options specific to wrapper """
      print("Wrapper options:")
      print()
      print("  -extended/--extended  run the extended set of tests")
      print("  -only-extended / -extended-only\n" + \
            "  --only-extended / --extended-only\n" + \
            "                        run ONLY the extended tests")
      print("  -list / --list        only list test names")
      print("  -win / --win          signal running on Windows and run those tests")
      print("  -f / -force-enable / --force-enable\n" + \
            "                        attempt to run disabled/skipped tests")
      print("  -h / -help / --help   print this help")
  
  def runtests():
      global passOn
      coverage = None
      execution_time = {}
      test_passed = {}
      test_failure_info = {}
      disabled = []
      skipped = []
      tests_to_run = []
  
      force_enable = option_passed('force-enable') or '-f' in opts
      run_only_extended = option_passed('only-extended') or option_passed('extended-only')
  
      if option_passed('list'):
          if run_only_extended:
              for t in testScriptsExt:
                  print(t)
          else:
              for t in testScripts:
                  print(t)
              if option_passed('extended'):
                  for t in testScriptsExt:
                      print(t)
          sys.exit(0)
  
      if ENABLE_COVERAGE:
          coverage = RPCCoverage()
          print("Initializing coverage directory at %s\n" % coverage.dir)
  
      if(ENABLE_WALLET == 1 and ENABLE_UTILS == 1 and ENABLE_BITCOIND == 1):
          rpcTestDir = RPC_TESTS_DIR
          buildDir   = BUILDDIR
          run_extended = option_passed('extended') or run_only_extended
          cov_flag = coverage.flag if coverage else ''
          flags = " --srcdir %s/src %s %s" % (buildDir, cov_flag, passOn)
  
          # compile the list of tests to check
  
          # check for explicit tests
          if showHelp:
              tests_to_run = [ testScripts[0] ]
          else:
              for o in opts:
                  if not o.startswith('-'):
                      found = False
                      for t in testScripts + testScriptsExt:
                          t_rep = str(t).split(' ')
                          if (t_rep[0] == o or t_rep[0] == o + '.py') and len(t_rep) > 1:
                              # it is a test with args - check all args match what was passed, otherwise don't add this test
                              t_args = t_rep[1:]
                              all_args_found = True
                              for targ in t_args:
                                  if not targ in passOn.split(' '):
                                      all_args_found = False
                              if all_args_found:
                                  tests_to_run.append(t)
                                  found = True
                          elif t_rep[0] == o or t_rep[0] == o + '.py':
                              passOnSplit = [x for x in passOn.split(' ') if x != '']
                              found_non_framework_opt = False
                              for p in passOnSplit:
                                  if p in test_script_opts:
                                      found_non_framework_opt = True
                              if not found_non_framework_opt:
                                  tests_to_run.append(t)
                                  found = True
                      if not found:
                          print("Error: %s is not a known test." % o)
                          sys.exit(1)
  
          # if no explicit tests specified, use the lists
          if not len(tests_to_run):
              if run_only_extended:
                  tests_to_run = testScriptsExt
              else:
                  tests_to_run += testScripts
                  if run_extended:
                      tests_to_run += testScriptsExt
  
          # weed out the disabled / skipped tests and print them beforehand
          # this allows earlier intervention in case a test is unexpectedly
          # skipped
          if not force_enable:
              trimmed_tests_to_run = []
              for t in tests_to_run:
                  if t.is_disabled():
                      print("Disabled testscript %s%s%s (reason: %s)" % (bold[1], t, bold[0], t.reason))
                      disabled.append(str(t))
                  elif t.is_skipped():
                      print("Skipping testscript %s%s%s on this platform (reason: %s)" % (bold[1], t, bold[0], t.reason))
                      skipped.append(str(t))
                  else:
                      trimmed_tests_to_run.append(t)
              tests_to_run = trimmed_tests_to_run
  
          # now run the tests
          p = re.compile(" -h| --help| -help")
          for t in tests_to_run:
              scriptname=re.sub(".py$", "", str(t).split(' ')[0])
              fullscriptcmd=str(t)
  
              # print the wrapper-specific help options
              if showHelp:
                  show_wrapper_options()
  
              if bad_opts_found:
                  if not ' --
  
  [... the rest is omitted ...]
files: qa/pull-tester/rpc-tests.py
files: #!/usr/bin/env python3
  # Copyright (c) 2014-2015 The Bitcoin Core developers
  # Copyright (c) 2015-2017 The Bitcoin Unlimited developers
  # Distributed under the MIT software license, see the accompanying
  # file COPYING or http://www.opensource.org/licenses/mit-license.php.
  
  """
  Run Regression Test Suite
  
  This module calls down into individual test cases via subprocess. It will
  forward all unrecognized arguments onto the individual test scripts, other
  than:
  
      - `-h` or '--help': print help about all options
      - `-extended`: run the "extended" test suite in addition to the basic one.
      - `-extended-only`: run ONLY the "extended" test suite
      - `-list`: only list the test scripts, do not run. Works in combination
        with '-extended' and '-extended-only' too, to print subsets.
      - `-win`: signal that this is running in a Windows environment, and we
        should run the tests.
      - `--coverage`: this generates a basic coverage report for the RPC
        interface.
  
  For more detailed help on options, run with '--help'.
  
  For a description of arguments recognized by test scripts, see
  `qa/pull-tester/test_framework/test_framework.py:BitcoinTestFramework.main`.
  
  """
  import pdb
  import os
  import time
  import shutil
  import sys
  import subprocess
  import tempfile
  import re
  
  sys.path.append("qa/pull-tester/")
  from tests_config import *
  from test_classes import RpcTest, Disabled, Skip
  
  BOLD = ("","")
  if os.name == 'posix':
      # primitive formatting on supported
      # terminal via ANSI escape sequences:
      BOLD = ('\033[0m', '\033[1m')
  
  RPC_TESTS_DIR = SRCDIR + '/qa/rpc-tests/'
  
  #If imported values are not defined then set to zero (or disabled)
  if 'ENABLE_WALLET' not in vars():
      ENABLE_WALLET=0
  if 'ENABLE_BITCOIND' not in vars():
      ENABLE_BITCOIND=0
  if 'ENABLE_UTILS' not in vars():
      ENABLE_UTILS=0
  if 'ENABLE_ZMQ' not in vars():
      ENABLE_ZMQ=0
  
  ENABLE_COVERAGE=0
  
  #Create a set to store arguments and create the passOn string
  opts = set()
  double_opts = set()  # BU: added for checking validity of -- opts
  passOn = ""
  showHelp = False  # if we need to print help
  p = re.compile("^--")
  # some of the single-dash options applicable only to this runner script
  # are also allowed in double-dash format (but are not passed on to the
  # test scripts themselves)
  private_single_opts = ('-h',
                         '-f',    # equivalent to -force-enable
                         '-help',
                         '-list',
                         '-extended',
                         '-extended-only',
                         '-only-extended',
                         '-force-enable',
                         '-win')
  private_double_opts = ('--list',
                         '--extended',
                         '--extended-only',
                         '--only-extended',
                         '--force-enable',
                         '--win')
  framework_opts = ('--tracerpc',
                    '--help',
                    '--noshutdown',
                    '--nocleanup',
                    '--srcdir',
                    '--tmpdir',
                    '--coveragedir',
                    '--randomseed',
                    '--testbinary',
                    '--refbinary')
  test_script_opts = ('--mineblock',
                      '--extensive')
  
  def option_passed(option_without_dashes):
      """check if option was specified in single-dash or double-dash format"""
      return ('-' + option_without_dashes in opts
              or '--' + option_without_dashes in double_opts)
  
  bold = ("","")
  if (os.name == 'posix'):
      bold = ('\033[0m', '\033[1m')
  
  for arg in sys.argv[1:]:
      if arg == '--coverage':
          ENABLE_COVERAGE = 1
      elif (p.match(arg) or arg in ('-h', '-help')):
          if arg not in private_double_opts:
              if arg == '--help' or arg == '-help' or arg == '-h':
                  passOn = '--help'
                  showHelp = True
              else:
                  if passOn is not '--help':
                      passOn += " " + arg
          # add it to double_opts only for validation
          double_opts.add(arg)
      else:
          # this is for single-dash options only
          # they are interpreted only by this script
          opts.add(arg)
  
  # check for unrecognized options
  bad_opts_found = []
  bad_opt_str="Unrecognized option: %s"
  for o in opts | double_opts:
      if o.startswith('--'):
          if o not in framework_opts + test_script_opts + private_double_opts:
              print(bad_opt_str % o)
              bad_opts_found.append(o)
      elif o.startswith('-'):
          if o not in private_single_opts:
              print(bad_opt_str % o)
              bad_opts_found.append(o)
              print("Run with -h to get help on usage.")
              sys.exit(1)
  
  #Set env vars
  if "BITCOIND" not in os.environ:
      os.environ["BITCOIND"] = BUILDDIR + '/src/bitcoind' + EXEEXT
  if "BITCOINCLI" not in os.environ:
      os.environ["BITCOINCLI"] = BUILDDIR + '/src/bitcoin-cli' + EXEEXT
  
  #Disable Windows tests by default
  if EXEEXT == ".exe" and not option_passed('win'):
      print("Win tests currently disabled.  Use -win option to enable")
      sys.exit(0)
  
  if not (ENABLE_WALLET == 1 and ENABLE_UTILS == 1 and ENABLE_BITCOIND == 1):
      print("No rpc tests to run. Wallet, utils, and bitcoind must all be enabled")
      sys.exit(0)
  
  # python3-zmq may not be installed. Handle this gracefully and with some helpful info
  if ENABLE_ZMQ:
      try:
          import zmq
      except ImportError as e:
          print("ERROR: \"import zmq\" failed. Set ENABLE_ZMQ=0 or " \
              "to run zmq tests, see dependency info in /qa/README.md.")
          raise e
  
  #Tests
  testScripts = [ RpcTest(t) for t in [
      'bip68-112-113-p2p',
      'validateblocktemplate',
      'parallel',
      'wallet',
      'excessive',
      'listtransactions',
      'receivedby',
      'mempool_resurrect_test',
      'txn_doublespend --mineblock',
      'txn_clone',
      'getchaintips',
      'rawtransactions',
      'rest',
      'mempool_spendcoinbase',
      'mempool_reorg',
      Disabled('mempool_limit', "mempool priority changes causes create_lots_of_big_transactions to fail"),
      'httpbasics',
      'multi_rpc',
      'zapwallettxes',
      'proxy_test',
      'merkle_blocks',
      'fundrawtransaction',
      'signrawtransactions',
      'walletbackup',
      'nodehandling',
      'reindex',
      'decodescript',
      Disabled('p2p-fullblocktest', "TODO"),
      'blockchain',
      'disablewallet',
      'sendheaders',
      'keypool',
      Disabled('prioritise_transaction', "TODO"),
      Disabled('invalidblockrequest', "TODO"),
      'invalidtxrequest',
      'abandonconflict',
      'p2p-versionbits-warning',
      'importprunedfunds',
      'thinblocks'
  ] ]
  
  testScriptsExt = [ RpcTest(t) for t in [
      'txPerf',
      'excessive --extensive',
      'bip9-softforks',
      'bip65-cltv',
      'bip65-cltv-p2p',
      'bip68-sequence',
      'bipdersig-p2p',
      'bipdersig',
      'getblocktemplate_longpoll',
      'getblocktemplate_proposals',
      'txn_doublespend',
      'txn_clone --mineblock',
      Disabled('pruning', "too much disk"),
      'forknotify',
      'invalidateblock',
      Disabled('rpcbind_test', "temporary, bug in libevent, see #6655"),
      'smartfees',
      'maxblocksinflight',
      'p2p-acceptblock',
      'mempool_packages',
      'maxuploadtarget',
      Disabled('replace-by-fee', "disabled while Replace By Fee is disabled in code")
  ] ]
  
  #Enable ZMQ tests
  if ENABLE_ZMQ == 1:
      testScripts.append(RpcTest('zmq_test'))
  
  
  def show_wrapper_options():
      """ print command line options specific to wrapper """
      print("Wrapper options:")
      print()
      print("  -extended/--extended  run the extended set of tests")
      print("  -only-extended / -extended-only\n" + \
            "  --only-extended / --extended-only\n" + \
            "                        run ONLY the extended tests")
      print("  -list / --list        only list test names")
      print("  -win / --win          signal running on Windows and run those tests")
      print("  -f / -force-enable / --force-enable\n" + \
            "                        attempt to run disabled/skipped tests")
      print("  -h / -help / --help   print this help")
  
  def runtests():
      global passOn
      coverage = None
      execution_time = {}
      test_passed = {}
      test_failure_info = {}
      disabled = []
      skipped = []
      tests_to_run = []
  
      force_enable = option_passed('force-enable') or '-f' in opts
      run_only_extended = option_passed('only-extended') or option_passed('extended-only')
  
      if option_passed('list'):
          if run_only_extended:
              for t in testScriptsExt:
                  print(t)
          else:
              for t in testScripts:
                  print(t)
              if option_passed('extended'):
                  for t in testScriptsExt:
                      print(t)
          sys.exit(0)
  
      if ENABLE_COVERAGE:
          coverage = RPCCoverage()
          print("Initializing coverage directory at %s\n" % coverage.dir)
  
      if(ENABLE_WALLET == 1 and ENABLE_UTILS == 1 and ENABLE_BITCOIND == 1):
          rpcTestDir = RPC_TESTS_DIR
          buildDir   = BUILDDIR
          run_extended = option_passed('extended') or run_only_extended
          cov_flag = coverage.flag if coverage else ''
          flags = " --srcdir %s/src %s %s" % (buildDir, cov_flag, passOn)
  
          # compile the list of tests to check
  
          # check for explicit tests
          if showHelp:
              tests_to_run = [ testScripts[0] ]
          else:
              for o in opts:
                  if not o.startswith('-'):
                      found = False
                      for t in testScripts + testScriptsExt:
                          t_rep = str(t).split(' ')
                          if (t_rep[0] == o or t_rep[0] == o + '.py') and len(t_rep) > 1:
                              # it is a test with args - check all args match what was passed, otherwise don't add this test
                              t_args = t_rep[1:]
                              all_args_found = True
                              for targ in t_args:
                                  if not targ in passOn.split(' '):
                                      all_args_found = False
                              if all_args_found:
                                  tests_to_run.append(t)
                                  found = True
                          elif t_rep[0] == o or t_rep[0] == o + '.py':
                              passOnSplit = [x for x in passOn.split(' ') if x != '']
                              found_non_framework_opt = False
                              for p in passOnSplit:
                                  if p in test_script_opts:
                                      found_non_framework_opt = True
                              if not found_non_framework_opt:
                                  tests_to_run.append(t)
                                  found = True
                      if not found:
                          print("Error: %s is not a known test." % o)
                          sys.exit(1)
  
          # if no explicit tests specified, use the lists
          if not len(tests_to_run):
              if run_only_extended:
                  tests_to_run = testScriptsExt
              else:
                  tests_to_run += testScripts
                  if run_extended:
                      tests_to_run += testScriptsExt
  
          # weed out the disabled / skipped tests and print them beforehand
          # this allows earlier intervention in case a test is unexpectedly
          # skipped
          if not force_enable:
              trimmed_tests_to_run = []
              for t in tests_to_run:
                  if t.is_disabled():
                      print("Disabled testscript %s%s%s (reason: %s)" % (bold[1], t, bold[0], t.reason))
                      disabled.append(str(t))
                  elif t.is_skipped():
                      print("Skipping testscript %s%s%s on this platform (reason: %s)" % (bold[1], t, bold[0], t.reason))
                      skipped.append(str(t))
                  else:
                      trimmed_tests_to_run.append(t)
              tests_to_run = trimmed_tests_to_run
  
          # now run the tests
          p = re.compile(" -h| --help| -help")
          for t in tests_to_run:
              scriptname=re.sub(".py$", "", str(t).split(' ')[0])
              fullscriptcmd=str(t)
  
              # print the wrapper-specific help options
              if showHelp:
                  show_wrapper_options()
  
              if bad_opts_found:
                  if not ' --help' in passOn:
                     
  
  [... the rest is omitted ...]
files: qa/pull-tester/rpc-tests.py
files: #!/usr/bin/env python3
  # Copyright (c) 2014-2015 The Bitcoin Core developers
  # Copyright (c) 2015-2016 The Bitcoin Unlimited developers
  # Distributed under the MIT software license, see the accompanying
  # file COPYING or http://www.opensource.org/licenses/mit-license.php.
  
  
  from test_framework.test_framework import BitcoinTestFramework
  from test_framework.util import *
  
  class ParallelTest (BitcoinTestFramework):
      def __init__(self):
        self.rep = False
        #self.extensive = False
        BitcoinTestFramework.__init__(self)
  
      def setup_chain(self):
          print ("Initializing test directory "+self.options.tmpdir)
          initialize_chain_clean(self.options.tmpdir, 6)
  
      def setup_network(self, split=False):
          self.nodes = []
          self.nodes.append(start_node(0, self.options.tmpdir, ["-parallel=0", "-rpcservertimeout=0", "-debug", "-use-thinblocks=0", "-excessiveblocksize=6000000", "-blockprioritysize=6000000", "-blockmaxsize=6000000"]))
          self.nodes.append(start_node(1, self.options.tmpdir, ["-parallel=0", "-rpcservertimeout=0", "-debug", "-use-thinblocks=0", "-excessiveblocksize=6000000", "-blockprioritysize=6000000", "-blockmaxsize=6000000"]))
          self.nodes.append(start_node(2, self.options.tmpdir, ["-parallel=0", "-rpcservertimeout=0", "-debug", "-use-thinblocks=0", "-excessiveblocksize=6000000", "-blockprioritysize=6000000", "-blockmaxsize=6000000"]))
          self.nodes.append(start_node(3, self.options.tmpdir, ["-parallel=0", "-rpcservertimeout=0", "-debug", "-use-thinblocks=0", "-excessiveblocksize=6000000", "-blockprioritysize=6000000", "-blockmaxsize=6000000"]))
          interconnect_nodes(self.nodes)
          self.is_network_split=False
          self.sync_all()
  
      def repetitiveTest(self):
          # get some coins
          self.nodeLookup = {}
          i = 0
          for n in self.nodes:
            print("Node %d is %s" % (i,n.url))
            print ("generating coins for node")  
            n.generate(200)
            self.sync_all()
            i += 1
            
          for i in range(0,200):
            # Create many utxo's
            print ("round %d: Generating txns..." % i)
            for n in self.nodes:  
              send_to = {}
              n.keypoolrefill(100)
              n.keypoolrefill(100)
              for i in range(200):
                send_to[n.getnewaddress()] = Decimal("0.01")
              n.sendmany("", send_to)
  
              self.sync_all()
            print ("  generating blocks...")
            i = 0
            for n in self.nodes:
              try:
                  n.generate(1)
              except JSONRPCException as e:
                  print (e)
                  print ("Node ", i, " ", n.url)
                  pdb.set_trace()
              i += 1
            print ("  syncing...")
            self.sync_all()
                      
      def run_test (self):
          if self.rep:
              self.repetitiveTest()
              return
  
          print ("Mining blocks with PV off...")
  
          # Mine some blocks on node2 which we will need at the end to generate a few transactions from that node
          # in order to create the small block with just a few transactions in it.
          self.nodes[2].generate(1)
          self.sync_all()
  
          # Mine the rest on node0 where we will generate the bigger block.
          self.nodes[0].generate(100)
          self.sync_all()
  
          self.nodes[0].generate(100)
          self.sync_all()
  
          # Create many utxo's
          print ("Generating txns...")
          send_to = {}
          self.nodes[0].keypoolrefill(100)
          self.nodes[0].keypoolrefill(100)
          for i in range(200):
              send_to[self.nodes[0].getnewaddress()] = Decimal("0.01")
          self.nodes[0].sendmany("", send_to)
          self.nodes[0].keypoolrefill(100)
          self.nodes[0].keypoolrefill(100)
          for i in range(200):
              send_to[self.nodes[0].getnewaddress()] = Decimal("0.01")
          self.nodes[0].sendmany("", send_to)
          self.nodes[0].keypoolrefill(100)
          self.nodes[0].keypoolrefill(100)
          for i in range(200):
              send_to[self.nodes[0].getnewaddress()] = Decimal("0.01")
          self.nodes[0].sendmany("", send_to)
          self.nodes[0].keypoolrefill(100)
          self.nodes[0].keypoolrefill(100)
          for i in range(200):
              send_to[self.nodes[0].getnewaddress()] = Decimal("0.01")
          self.nodes[0].sendmany("", send_to)
          self.nodes[0].keypoolrefill(100)
          self.nodes[0].keypoolrefill(100)
          for i in range(200):
              send_to[self.nodes[0].getnewaddress()] = Decimal("0.01")
          self.nodes[0].sendmany("", send_to)
          self.nodes[0].keypoolrefill(100)
          self.nodes[0].keypoolrefill(100)
          for i in range(200):
              send_to[self.nodes[0].getnewaddress()] = Decimal("0.01")
          self.nodes[0].sendmany("", send_to)
          self.nodes[0].keypoolrefill(100)
          self.nodes[0].keypoolrefill(100)
          for i in range(200):
              send_to[self.nodes[0].getnewaddress()] = Decimal("0.01")
          self.nodes[0].sendmany("", send_to)
          self.nodes[0].keypoolrefill(100)
          self.nodes[0].keypoolrefill(100)
          for i in range(200):
              send_to[self.nodes[0].getnewaddress()] = Decimal("0.01")
          self.nodes[0].sendmany("", send_to)
          self.nodes[0].keypoolrefill(100)
          self.nodes[0].keypoolrefill(100)
          for i in range(200):
              send_to[self.nodes[0].getnewaddress()] = Decimal("0.01")
          self.nodes[0].sendmany("", send_to)
  
          # Mine a block so that the utxos are now spendable
          print ("mine a block")
          self.nodes[0].generate(1)
  
          connect_nodes(self.nodes[0],1)
          connect_nodes(self.nodes[0],2)
          connect_nodes(self.nodes[0],3)
          self.is_network_split=False
          self.sync_all()
  
          # Send more transactions
          print ("Generating more txns...")
          output_total = Decimal(0)
          j = 0
          self.utxo = self.nodes[0].listunspent()
          utxo = self.utxo.pop()
          txns_to_send = []
          num_txns = 700
          while j <= num_txns:
              inputs = []
              outputs = {}
              utxo = self.utxo.pop()
              if utxo["amount"] > Decimal("0.0100000") or utxo["amount"] < Decimal("0.0100000"):
                  continue
              if utxo["spendable"] is True:
                  j = j + 1
                  inputs.append({ "txid" : utxo["txid"], "vout" : utxo["vout"]})
                  outputs[self.nodes[0].getnewaddress()] = utxo["amount"] - Decimal("0.000010000")
                  raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
                  txns_to_send.append(self.nodes[0].signrawtransaction(raw_tx))
  
                  # send the transaction
          for i in range(num_txns):
              self.nodes[0].sendrawtransaction(txns_to_send[i]["hex"], True)
          while self.nodes[0].getmempoolinfo()['size'] < num_txns:
              time.sleep(1)
  
          self.nodes[0].generate(1)
          self.sync_all()
  
  
          #stop and restart nodes
          stop_nodes(self.nodes)
          wait_bitcoinds()
  
          self.nodes = []
          self.nodes.append(start_node(0, self.options.tmpdir, ["-par=1","-rpcservertimeout=0","-debug", "-debug=parallel", "-debug=parallel_2", "-use-thinblocks=0", "-excessiveblocksize=6000000", "-blockprioritysize=6000000", "-blockmaxsize=6000000"]))
          self.nodes.append(start_node(1, self.options.tmpdir, ["-par=1", "-rpcservertimeout=0","-debug", "-debug=parallel", "-debug=parallel_2", "-use-thinblocks=0", "-excessiveblocksize=6000000", "-blockprioritysize=6000000", "-blockmaxsize=6000000"]))
          self.nodes.append(start_node(2, self.options.tmpdir, ["-par=1", "-rpcservertimeout=0","-debug", "-debug=parallel", "-debug=parallel_2", "-use-thinblocks=0", "-excessiveblocksize=6000000", "-blockprioritysize=6000000", "-blockmaxsize=6000000"]))
          self.nodes.append(start_node(3, self.options.tmpdir, ["-par=1", "-rpcservertimeout=0","-debug", "-debug=parallel", "-debug=parallel_2", "-use-thinblocks=0", "-excessiveblocksize=6000000", "-blockprioritysize=6000000", "-blockmaxsize=6000000"]))
  
  
          # create transactions with many inputs
          print ("Generating even more txns...")
          num_txns2 = 5
          self.utxo = self.nodes[0].listunspent()
          for i in range(num_txns2):
              inputs = []
              outputs = {}
              output_total = Decimal(0)
              j = 1
              print ("utxo length " + str(len(self.utxo)))
              txns_to_send = []
              while j < 600:
                  utxo = self.utxo.pop()
                  if utxo["amount"] > Decimal("0.0100000") or utxo["amount"] < Decimal("0.0100000"):
                      continue
                  j = j + 1
                  inputs.append({ "txid" : utxo["txid"], "vout" : utxo["vout"]})
                  output_total = output_total + utxo["amount"]
              outputs[self.nodes[0].getnewaddress()] = output_total/2 - Decimal("0.001")
              outputs[self.nodes[0].getnewaddress()] = output_total/2 - Decimal("0.001")
              raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
              txns_to_send.append(self.nodes[0].signrawtransaction(raw_tx))
      
              # send the transactions
              self.nodes[0].sendrawtransaction(txns_to_send[0]["hex"], True)
  
          # Send big tx's which will now have many inputs
          num_range = 50
          for i in range(num_range):
              self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
  
          while self.nodes[0].getmempoolinfo()['size'] < (num_txns2 + num_range):
              time.sleep(1)
  
          # Send a few transactions from node2 that will get mined so that we will have at least
          # a few inputs to check when the two competing blocks enter parallel validation.
          for i in range(10):
              self.nodes[2].sendtoaddress(self.nodes[2].getnewaddress(), "0.01")
  
          # Have node0 and node2 mine the same block which will compete to advance the chaintip when
          # The nodes are connected back together.
          print ("Mine two competing blocks...")
          self.nodes[0].generate(1)
          self.nodes[2].generate(1)
          print ("Connect nodes...")
          connect_nodes(self.nodes[0],1)
          #time.sleep(1.2) #add this time in if you have compiled with --enable-debug since you need some extra time for the block to propagate due to the slowness of the build.
          connect_nodes(self.nodes[1],2)
          sync_blocks(self.nodes[0:3])
  
          # Wait here to make sure a re-org does not happen on node0 so we want to give it some time.  If the 
          # memory pool on node 0 does not change within 5 seconds then we assume a reorg is not occurring
          # because a reorg would cause transactions to be placed in the mempool from the old block on node 0.
          old_mempoolbytes = self.nodes[0].getmempoolinfo()["bytes"]
          for i in range(5):
              mempoolbytes = self.nodes[0].getmempoolinfo()["bytes"]
              if old_mempoolbytes != mempoolbytes:
                  assert("Reorg happened when it should not - Mempoolbytes has changed")
              old_mempoolbytes = mempoolbytes
              # node0 has the bigger block and was sent and began processing first, however the block from node2
              # should have come in after and beaten node0's block.  Therefore the blockhash from chaintip from 
              # node2 should now match the blockhash from the chaintip on node1; and node0 and node1 should not match.
              print ("check for re-org " + str(i+1))
              assert_equal(self.nodes[1].getbestblockhash(), self.nodes[2].getbestblockhash())
              assert_not_equal(self.nodes[0].getbestblockhash(), self.nodes[1].getbestblockhash())
              time.sleep(1)
  
  
          # mine a block on
  
  [... the rest is omitted ...]
files: qa/rpc-tests/parallel.py
files: #!/usr/bin/env python3
  # Copyright (c) 2014-2015 The Bitcoin Core developers
  # Copyright (c) 2015-2016 The Bitcoin Unlimited developers
  # Distributed under the MIT software license, see the accompanying
  # file COPYING or http://www.opensource.org/licenses/mit-license.php.
  
  
  from test_framework.test_framework import BitcoinTestFramework
  from test_framework.util import *
  
  class ParallelTest (BitcoinTestFramework):
      def __init__(self):
        self.rep = False
        BitcoinTestFramework.__init__(self)
  
      def setup_chain(self):
          print ("Initializing test directory "+self.options.tmpdir)
          initialize_chain_clean(self.options.tmpdir, 6)
  
      def setup_network(self, split=False):
          self.nodes = []
          self.nodes.append(start_node(0, self.options.tmpdir, ["-parallel=0", "-rpcservertimeout=0", "-debug", "-use-thinblocks=0", "-excessiveblocksize=6000000", "-blockprioritysize=6000000", "-blockmaxsize=6000000"]))
          self.nodes.append(start_node(1, self.options.tmpdir, ["-parallel=0", "-rpcservertimeout=0", "-debug", "-use-thinblocks=0", "-excessiveblocksize=6000000", "-blockprioritysize=6000000", "-blockmaxsize=6000000"]))
          self.nodes.append(start_node(2, self.options.tmpdir, ["-parallel=0", "-rpcservertimeout=0", "-debug", "-use-thinblocks=0", "-excessiveblocksize=6000000", "-blockprioritysize=6000000", "-blockmaxsize=6000000"]))
          self.nodes.append(start_node(3, self.options.tmpdir, ["-parallel=0", "-rpcservertimeout=0", "-debug", "-use-thinblocks=0", "-excessiveblocksize=6000000", "-blockprioritysize=6000000", "-blockmaxsize=6000000"]))
          interconnect_nodes(self.nodes)
          self.is_network_split=False
          self.sync_all()
  
      def repetitiveTest(self):
          # get some coins
          self.nodeLookup = {}
          i = 0
          for n in self.nodes:
            print("Node %d is %s" % (i,n.url))
            print ("generating coins for node")  
            n.generate(200)
            self.sync_all()
            i += 1
            
          for i in range(0,200):
            # Create many utxo's
            print ("round %d: Generating txns..." % i)
            for n in self.nodes:  
              send_to = {}
              n.keypoolrefill(100)
              n.keypoolrefill(100)
              for i in range(200):
                send_to[n.getnewaddress()] = Decimal("0.01")
              n.sendmany("", send_to)
  
              self.sync_all()
            print ("  generating blocks...")
            i = 0
            for n in self.nodes:
              try:
                  n.generate(1)
              except JSONRPCException as e:
                  print (e)
                  print ("Node ", i, " ", n.url)
                  pdb.set_trace()
              i += 1
            print ("  syncing...")
            self.sync_all()
                      
      def run_test (self):
          if self.rep:
              self.repetitiveTest()
              return
          
          print ("Mining blocks with PV off...")
  
          # Mine some blocks on node2 which we will need at the end to generate a few transactions from that node
          # in order to create the small block with just a few transactions in it.
          self.nodes[2].generate(1)
          self.sync_all()
  
          # Mine the rest on node0 where we will generate the bigger block.
          self.nodes[0].generate(100)
          self.sync_all()
  
          self.nodes[0].generate(100)
          self.sync_all()
  
          # Create many utxo's
          print ("Generating txns...")
          send_to = {}
          self.nodes[0].keypoolrefill(100)
          self.nodes[0].keypoolrefill(100)
          for i in range(200):
              send_to[self.nodes[0].getnewaddress()] = Decimal("0.01")
          self.nodes[0].sendmany("", send_to)
          self.nodes[0].keypoolrefill(100)
          self.nodes[0].keypoolrefill(100)
          for i in range(200):
              send_to[self.nodes[0].getnewaddress()] = Decimal("0.01")
          self.nodes[0].sendmany("", send_to)
          self.nodes[0].keypoolrefill(100)
          self.nodes[0].keypoolrefill(100)
          for i in range(200):
              send_to[self.nodes[0].getnewaddress()] = Decimal("0.01")
          self.nodes[0].sendmany("", send_to)
          self.nodes[0].keypoolrefill(100)
          self.nodes[0].keypoolrefill(100)
          for i in range(200):
              send_to[self.nodes[0].getnewaddress()] = Decimal("0.01")
          self.nodes[0].sendmany("", send_to)
          self.nodes[0].keypoolrefill(100)
          self.nodes[0].keypoolrefill(100)
          for i in range(200):
              send_to[self.nodes[0].getnewaddress()] = Decimal("0.01")
          self.nodes[0].sendmany("", send_to)
          self.nodes[0].keypoolrefill(100)
          self.nodes[0].keypoolrefill(100)
          for i in range(200):
              send_to[self.nodes[0].getnewaddress()] = Decimal("0.01")
          self.nodes[0].sendmany("", send_to)
          self.nodes[0].keypoolrefill(100)
          self.nodes[0].keypoolrefill(100)
          for i in range(200):
              send_to[self.nodes[0].getnewaddress()] = Decimal("0.01")
          self.nodes[0].sendmany("", send_to)
          self.nodes[0].keypoolrefill(100)
          self.nodes[0].keypoolrefill(100)
          for i in range(200):
              send_to[self.nodes[0].getnewaddress()] = Decimal("0.01")
          self.nodes[0].sendmany("", send_to)
          self.nodes[0].keypoolrefill(100)
          self.nodes[0].keypoolrefill(100)
          for i in range(200):
              send_to[self.nodes[0].getnewaddress()] = Decimal("0.01")
          self.nodes[0].sendmany("", send_to)
  
          # Mine a block so that the utxos are now spendable
          print ("mine a block")
          self.nodes[0].generate(1)
  
          connect_nodes(self.nodes[0],1)
          connect_nodes(self.nodes[0],2)
          connect_nodes(self.nodes[0],3)
          self.is_network_split=False
          self.sync_all()
  
          # Send more transactions
          print ("Generating more txns...")
          output_total = Decimal(0)
          j = 0
          self.utxo = self.nodes[0].listunspent()
          utxo = self.utxo.pop()
          txns_to_send = []
          num_txns = 700
          while j <= num_txns:
              inputs = []
              outputs = {}
              utxo = self.utxo.pop()
              if utxo["amount"] > Decimal("0.0100000") or utxo["amount"] < Decimal("0.0100000"):
                  continue
              if utxo["spendable"] is True:
                  j = j + 1
                  inputs.append({ "txid" : utxo["txid"], "vout" : utxo["vout"]})
                  outputs[self.nodes[0].getnewaddress()] = utxo["amount"] - Decimal("0.000010000")
                  raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
                  txns_to_send.append(self.nodes[0].signrawtransaction(raw_tx))
  
                  # send the transaction
          for i in range(num_txns):
              self.nodes[0].sendrawtransaction(txns_to_send[i]["hex"], True)
          while self.nodes[0].getmempoolinfo()['size'] < num_txns:
              time.sleep(1)
  
          self.nodes[0].generate(1)
          self.sync_all()
  
  
          #stop and restart nodes
          stop_nodes(self.nodes)
          wait_bitcoinds()
  
          self.nodes = []
          self.nodes.append(start_node(0, self.options.tmpdir, ["-par=1","-rpcservertimeout=0","-debug", "-debug=parallel", "-debug=parallel_2", "-use-thinblocks=0", "-excessiveblocksize=6000000", "-blockprioritysize=6000000", "-blockmaxsize=6000000"]))
          self.nodes.append(start_node(1, self.options.tmpdir, ["-par=1", "-rpcservertimeout=0","-debug", "-debug=parallel", "-debug=parallel_2", "-use-thinblocks=0", "-excessiveblocksize=6000000", "-blockprioritysize=6000000", "-blockmaxsize=6000000"]))
          self.nodes.append(start_node(2, self.options.tmpdir, ["-par=1", "-rpcservertimeout=0","-debug", "-debug=parallel", "-debug=parallel_2", "-use-thinblocks=0", "-excessiveblocksize=6000000", "-blockprioritysize=6000000", "-blockmaxsize=6000000"]))
          self.nodes.append(start_node(3, self.options.tmpdir, ["-par=1", "-rpcservertimeout=0","-debug", "-debug=parallel", "-debug=parallel_2", "-use-thinblocks=0", "-excessiveblocksize=6000000", "-blockprioritysize=6000000", "-blockmaxsize=6000000"]))
  
  
          # create transactions with many inputs
          print ("Generating even more txns...")
          num_txns2 = 5
          self.utxo = self.nodes[0].listunspent()
          for i in range(num_txns2):
              inputs = []
              outputs = {}
              output_total = Decimal(0)
              j = 1
              print ("utxo length " + str(len(self.utxo)))
              txns_to_send = []
              while j < 600:
                  utxo = self.utxo.pop()
                  if utxo["amount"] > Decimal("0.0100000") or utxo["amount"] < Decimal("0.0100000"):
                      continue
                  j = j + 1
                  inputs.append({ "txid" : utxo["txid"], "vout" : utxo["vout"]})
                  output_total = output_total + utxo["amount"]
              outputs[self.nodes[0].getnewaddress()] = output_total/2 - Decimal("0.001")
              outputs[self.nodes[0].getnewaddress()] = output_total/2 - Decimal("0.001")
              raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
              txns_to_send.append(self.nodes[0].signrawtransaction(raw_tx))
      
              # send the transactions
              self.nodes[0].sendrawtransaction(txns_to_send[0]["hex"], True)
  
          # Send big tx's which will now have many inputs
          num_range = 50
          for i in range(num_range):
              self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
  
          while self.nodes[0].getmempoolinfo()['size'] < (num_txns2 + num_range):
              time.sleep(1)
  
          # Send a few transactions from node2 that will get mined so that we will have at least
          # a few inputs to check when the two competing blocks enter parallel validation.
          for i in range(10):
              self.nodes[2].sendtoaddress(self.nodes[2].getnewaddress(), "0.01")
  
          # Have node0 and node2 mine the same block which will compete to advance the chaintip when
          # The nodes are connected back together.
          print ("Mine two competing blocks...")
          self.nodes[0].generate(1)
          self.nodes[2].generate(1)
          print ("Connect nodes...")
          connect_nodes(self.nodes[0],1)
          #time.sleep(1.2) #add this time in if you have compiled with --enable-debug since you need some extra time for the block to propagate due to the slowness of the build.
          connect_nodes(self.nodes[1],2)
          sync_blocks(self.nodes[0:3])
  
          # Wait here to make sure a re-org does not happen on node0 so we want to give it some time.  If the 
          # memory pool on node 0 does not change within 5 seconds then we assume a reorg is not occurring
          # because a reorg would cause transactions to be placed in the mempool from the old block on node 0.
          old_mempoolbytes = self.nodes[0].getmempoolinfo()["bytes"]
          for i in range(5):
              mempoolbytes = self.nodes[0].getmempoolinfo()["bytes"]
              if old_mempoolbytes != mempoolbytes:
                  assert("Reorg happened when it should not - Mempoolbytes has changed")
              old_mempoolbytes = mempoolbytes
              # node0 has the bigger block and was sent and began processing first, however the block from node2
              # should have come in after and beaten node0's block.  Therefore the blockhash from chaintip from 
              # node2 should now match the blockhash from the chaintip on node1; and node0 and node1 should not match.
              print ("check for re-org " + str(i+1))
              assert_equal(self.nodes[1].getbestblockhash(), self.nodes[2].getbestblockhash())
              assert_not_equal(self.nodes[0].getbestblockhash(), self.nodes[1].getbestblockhash())
              time.sleep(1)
  
  
          # mine a block on node3 and then connect to the others
  
  [... the rest is omitted ...]
files: qa/rpc-tests/parallel.py
files: // Copyright (c) 2017 Stephen McCarthy
  // Copyright (c) 2017 The Bitcoin Unlimited developers
  // Distributed under the MIT software license, see the accompanying
  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  
  #include <set>
  
  #include "allowed_args.h"
  #include "chainparams.h"
  #include "dosman.h"
  #include "httpserver.h"
  #include "init.h"
  #include "main.h"
  #include "miner.h"
  #include "netbase.h"
  #include "policy/policy.h"
  #include "qt/guiconstants.h"
  #include "requestManager.h"
  #include "script/sigcache.h"
  #include "tinyformat.h"
  #include "torcontrol.h"
  #include "tweak.h"
  #include "txdb.h"
  #include "util.h"
  #include "utilmoneystr.h"
  #include "utilstrencodings.h"
  
  #ifdef ENABLE_WALLET
  #include "wallet/wallet.h"
  #endif
  
  // These globals are needed here so bitcoin-cli can link
  const std::string CURRENCY_UNIT = "BTC";
  const std::string DEFAULT_TOR_CONTROL = "127.0.0.1:9051";
  const char DEFAULT_RPCCONNECT[] = "127.0.0.1";
  
  // Variables for traffic shaping.  Needed here so bitcoin-cli can link
  /** Default value for the maximum amount of data that can be received in a burst */
  const int64_t DEFAULT_MAX_RECV_BURST = std::numeric_limits<int64_t>::max();
  /** Default value for the maximum amount of data that can be sent in a burst */
  const int64_t DEFAULT_MAX_SEND_BURST = std::numeric_limits<int64_t>::max();
  /** Default value for the average amount of data received per second */
  const int64_t DEFAULT_AVE_RECV = std::numeric_limits<int64_t>::max();
  /** Default value for the average amount of data sent per second */
  const int64_t DEFAULT_AVE_SEND = std::numeric_limits<int64_t>::max();
  
  namespace AllowedArgs
  {
  enum HelpMessageMode
  {
      HMM_BITCOIND,
      HMM_BITCOIN_QT
  };
  
  static const int screenWidth = 79;
  static const int optIndent = 2;
  static const int msgIndent = 7;
  
  std::string HelpMessageGroup(const std::string &message) { return std::string(message) + std::string("\n\n"); }
  std::string HelpMessageOpt(const std::string &option, const std::string &message)
  {
      return std::string(optIndent, ' ') + std::string(option) + std::string("\n") + std::string(msgIndent, ' ') +
             FormatParagraph(message, screenWidth - msgIndent, msgIndent) + std::string("\n\n");
  }
  
  AllowedArgs::AllowedArgs(bool permit_unrecognized) : m_permit_unrecognized(permit_unrecognized) {}
  AllowedArgs &AllowedArgs::addHeader(const std::string &strHeader, bool debug)
  {
      m_helpList.push_back(HelpComponent{strHeader + "\n\n", debug});
      return *this;
  }
  
  AllowedArgs &AllowedArgs::addDebugArg(const std::string &strArgsDefinition,
      CheckValueFunc checkValueFunc,
      const std::string &strHelp)
  {
      return addArg(strArgsDefinition, checkValueFunc, strHelp, true);
  }
  
  AllowedArgs &AllowedArgs::addArg(const std::string &strArgsDefinition,
      CheckValueFunc checkValueFunc,
      const std::string &strHelp,
      bool debug)
  {
      std::string strArgs = strArgsDefinition;
      std::string strExampleValue;
      size_t is_index = strArgsDefinition.find('=');
      if (is_index != std::string::npos)
      {
          strExampleValue = strArgsDefinition.substr(is_index + 1);
          strArgs = strArgsDefinition.substr(0, is_index);
      }
  
      if (strArgs == "")
          strArgs = ",";
  
      std::stringstream streamArgs(strArgs);
      std::string strArg;
      bool firstArg = true;
      while (std::getline(streamArgs, strArg, ','))
      {
          m_args[strArg] = checkValueFunc;
  
          std::string optionText = std::string(optIndent, ' ') + "-" + strArg;
          if (!strExampleValue.empty())
              optionText += "=" + strExampleValue;
          optionText += "\n";
          m_helpList.push_back(HelpComponent{optionText, debug || !firstArg});
  
          firstArg = false;
      }
  
      std::string helpText =
          std::string(msgIndent, ' ') + FormatParagraph(strHelp, screenWidth - msgIndent, msgIndent) + "\n\n";
      m_helpList.push_back(HelpComponent{helpText, debug});
  
      return *this;
  }
  
  void AllowedArgs::checkArg(const std::string &strArg, const std::string &strValue) const
  {
      if (!m_args.count(strArg))
      {
          if (m_permit_unrecognized)
              return;
          throw std::runtime_error(strprintf(_("unrecognized option '%s'"), strArg));
      }
  
      if (!m_args.at(strArg)(strValue))
          throw std::runtime_error(strprintf(_("invalid value '%s' for option '%s'"), strValue, strArg));
  }
  
  std::string AllowedArgs::helpMessage() const
  {
      const bool showDebug = GetBoolArg("-help-debug", false);
      std::string helpMessage;
  
      for (HelpComponent helpComponent : m_helpList)
          if (showDebug || !helpComponent.debug)
              helpMessage += helpComponent.text;
  
      return helpMessage;
  }
  
  //////////////////////////////////////////////////////////////////////////////
  //
  // CheckValueFunc functions
  //
  
  static const std::set<std::string> boolStrings{"", "1", "0", "t", "f", "y", "n", "true", "false", "yes", "no"};
  static const std::set<char> intChars{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
  static const std::set<char> amountChars{'.', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
  
  static bool validateString(const std::string &str, const std::set<char> &validChars)
  {
      for (const char &c : str)
          if (!validChars.count(c))
              return false;
      return true;
  }
  
  static bool optionalBool(const std::string &str) { return (boolStrings.count(str) != 0); }
  static bool requiredStr(const std::string &str) { return !str.empty(); }
  static bool optionalStr(const std::string &str) { return true; }
  static bool requiredInt(const std::string &str)
  {
      if (str.empty() || str == "-")
          return false;
  
      // Allow the first character to be '-', to allow negative numbers.
      return validateString(str[0] == '-' ? str.substr(1) : str, intChars);
  }
  
  static bool optionalInt(const std::string &str)
  {
      if (str.empty())
          return true;
      return requiredInt(str);
  }
  
  static bool requiredAmount(const std::string &str)
  {
      if (str.empty())
          return false;
      return validateString(str, amountChars);
  }
  
  //////////////////////////////////////////////////////////////////////////////
  //
  // Argument definitions
  //
  
  // When adding new arguments to a category, please keep alphabetical ordering,
  // where appropriate. Do not translate _(...) addDebugArg help text: there are
  // many technical terms, and only a very small audience, so it would be an
  // unnecessary stress to translators.
  
  static void addHelpOptions(AllowedArgs &allowedArgs)
  {
      allowedArgs.addHeader(_("Help options:"))
          .addArg("?,h,help", optionalBool, _("This help message"))
          .addArg("version", optionalBool, _("Print version and exit"))
          .addArg("help-debug", optionalBool, _("Show all debugging options (usage: --help -help-debug)"));
  }
  
  static void addChainSelectionOptions(AllowedArgs &allowedArgs)
  {
      allowedArgs.addHeader(_("Chain selection options:"))
          .addArg("chain_nol", optionalBool, _("Use the no-limit blockchain"))
          .addArg("testnet", optionalBool, _("Use the test chain"))
          .addDebugArg("regtest", optionalBool,
              "Enter regression test mode, which uses a special chain in which blocks can be solved instantly. "
              "This is intended for regression testing tools and app development.");
  }
  
  static void addConfigurationLocationOptions(AllowedArgs &allowedArgs)
  {
      allowedArgs.addHeader(_("Configuration location options:"))
          .addArg(
              "conf=<file>", requiredStr, strprintf(_("Specify configuration file (default: %s)"), BITCOIN_CONF_FILENAME))
          .addArg("datadir=<dir>", requiredStr, _("Specify data directory"));
  }
  
  static void addGeneralOptions(AllowedArgs &allowedArgs, HelpMessageMode mode)
  {
      allowedArgs.addHeader(_("General options:"))
          .addArg("alertnotify=<cmd>", requiredStr, _("Execute command when a relevant alert is received or we see a "
                                                      "really long fork (%s in cmd is replaced by message)"))
          .addArg("blocknotify=<cmd>", requiredStr,
              _("Execute command when the best block changes (%s in cmd is replaced by block hash)"))
          .addDebugArg("blocksonly", optionalBool,
              strprintf(_("Whether to operate in a blocks only mode (default: %u)"), DEFAULT_BLOCKSONLY))
          .addArg("checkblocks=<n>", requiredInt,
              strprintf(_("How many blocks to check at startup (default: %u, 0 = all)"), DEFAULT_CHECKBLOCKS))
          .addArg("checklevel=<n>", requiredInt,
              strprintf(_("How thorough the block verification of -checkblocks is (0-4, default: %u)"),
                      DEFAULT_CHECKLEVEL));
  
  #ifndef WIN32
      if (mode == HMM_BITCOIND)
          allowedArgs.addArg("daemon", optionalBool, _("Run in the background as a daemon and accept commands"));
  #endif
  
      allowedArgs
          .addArg("dbcache=<n>", requiredInt, strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"),
                                                  nMinDbCache, nMaxDbCache, nDefaultDbCache))
          .addArg("loadblock=<file>", requiredStr, _("Imports blocks from external blk000??.dat file on startup"))
          .addArg("maxorphantx=<n>", requiredInt,
              strprintf(_("Keep at most <n> unconnectable transactions in memory (default: %u)"),
                      DEFAULT_MAX_ORPHAN_TRANSACTIONS))
          .addArg("maxmempool=<n>", requiredInt,
              strprintf(
                      _("Keep the transaction memory pool below <n> megabytes (default: %u)"), DEFAULT_MAX_MEMPOOL_SIZE))
          .addArg("mempoolexpiry=<n>", requiredInt,
              strprintf(_("Do not keep transactions in the mempool longer than <n> hours (default: %u)"),
                      DEFAULT_MEMPOOL_EXPIRY))
          .addArg("orphanpoolexpiry=<n>", requiredInt,
              strprintf(_("Do not keep transactions in the orphanpool longer than <n> hours (default: %u)"),
                      DEFAULT_ORPHANPOOL_EXPIRY))
          .addArg("par=<n>", requiredInt, strprintf(_("Set the number of script verification threads (%u to %d, 0 = "
                                                      "auto, <0 = leave that many cores free, default: %d)"),
                                              -GetNumCores(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS))
          .addArg("parallel=<n>", optionalBool, strprintf(_("Turn Parallel Block Validation on or off (default: %u)"), 1))
  #ifndef WIN32
          .addArg("pid=<file>", requiredStr, strprintf(_("Specify pid file (default: %s)"), BITCOIN_PID_FILENAME))
  #endif
          .addArg("prune=<n>", requiredInt,
              strprintf(_("Reduce storage requirements by pruning (deleting) old blocks. This mode is incompatible with "
                          "-txindex and -rescan. "
                          "Warning: Reverting this setting requires re-downloading the entire blockchain. "
                          "(default: 0 = disable pruning blocks, >%u = target size in MiB to use for block files)"),
                      MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024))
          .addArg("reindex", optionalBool, _("Rebuild block chain index from current blk000??.dat files on startup"))
          .addArg("txindex", optionalBool,
              strprintf(_("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)"),
                      DEFAULT_TXINDEX));
  }
  
  static void addConnectionOptions(AllowedArgs &allowedArgs)
  {
      allowedArgs.addHeader(_("Connection options:"))
          .addArg("addnode=<ip>", requiredStr, _("Add a node to connect to and attempt to keep the connection open"))
          .addArg("banscore=<n>", requiredInt,
              strprintf(_("Threshold for disconnecting misbehaving peers (default: %u)"), DEFAULT_BANSCORE_THRESHOLD))
          .addArg("bantime=<n>", requiredInt,
              strprintf(_("Number of seconds to keep misbehaving peers from reconnecting (default: %u)"),
                      DEFAULT_MISBEHAVING_BANTIME))
          .addArg("bind=<addr>", requiredStr,
              _("Bind to given address and always listen on it. Use [host]:port notation for IPv6"))
          .addArg("bitnodes", optionalBool,
              _("Query for peer addresses via Bitnodes API, if low on addresses (default: 1 unless -connect)"))
          .addArg("blkretryinterval", requiredInt,
              strprintf(_("Time to wait before requesting a block from a different peer, in microseconds (default: %u)"),
                      DEFAULT_MIN_BLK_REQUEST_RETRY_INTERVAL))
          .addArg("connect=<ip>", optionalStr, _("Connect only to the specified node(s)"))
          .addArg("connect-thin
  
  [... the rest is omitted ...]
files: src/allowed_args.cpp
files: // Copyright (c) 2017 Stephen McCarthy
  // Copyright (c) 2017 The Bitcoin Unlimited developers
  // Distributed under the MIT software license, see the accompanying
  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  
  #include <set>
  
  #include "allowed_args.h"
  #include "chainparams.h"
  #include "dosman.h"
  #include "httpserver.h"
  #include "init.h"
  #include "main.h"
  #include "miner.h"
  #include "netbase.h"
  #include "policy/policy.h"
  #include "qt/guiconstants.h"
  #include "requestManager.h"
  #include "script/sigcache.h"
  #include "tinyformat.h"
  #include "torcontrol.h"
  #include "tweak.h"
  #include "txdb.h"
  #include "util.h"
  #include "utilmoneystr.h"
  #include "utilstrencodings.h"
  
  #ifdef ENABLE_WALLET
  #include "wallet/wallet.h"
  #endif
  
  // These globals are needed here so bitcoin-cli can link
  const std::string CURRENCY_UNIT = "BTC";
  const std::string DEFAULT_TOR_CONTROL = "127.0.0.1:9051";
  const char DEFAULT_RPCCONNECT[] = "127.0.0.1";
  
  // Variables for traffic shaping.  Needed here so bitcoin-cli can link
  /** Default value for the maximum amount of data that can be received in a burst */
  const int64_t DEFAULT_MAX_RECV_BURST = std::numeric_limits<int64_t>::max();
  /** Default value for the maximum amount of data that can be sent in a burst */
  const int64_t DEFAULT_MAX_SEND_BURST = std::numeric_limits<int64_t>::max();
  /** Default value for the average amount of data received per second */
  const int64_t DEFAULT_AVE_RECV = std::numeric_limits<int64_t>::max();
  /** Default value for the average amount of data sent per second */
  const int64_t DEFAULT_AVE_SEND = std::numeric_limits<int64_t>::max();
  
  namespace AllowedArgs
  {
  enum HelpMessageMode
  {
      HMM_BITCOIND,
      HMM_BITCOIN_QT
  };
  
  static const int screenWidth = 79;
  static const int optIndent = 2;
  static const int msgIndent = 7;
  
  std::string HelpMessageGroup(const std::string &message) { return std::string(message) + std::string("\n\n"); }
  std::string HelpMessageOpt(const std::string &option, const std::string &message)
  {
      return std::string(optIndent, ' ') + std::string(option) + std::string("\n") + std::string(msgIndent, ' ') +
             FormatParagraph(message, screenWidth - msgIndent, msgIndent) + std::string("\n\n");
  }
  
  AllowedArgs::AllowedArgs(bool permit_unrecognized) : m_permit_unrecognized(permit_unrecognized) {}
  AllowedArgs &AllowedArgs::addHeader(const std::string &strHeader, bool debug)
  {
      m_helpList.push_back(HelpComponent{strHeader + "\n\n", debug});
      return *this;
  }
  
  AllowedArgs &AllowedArgs::addDebugArg(const std::string &strArgsDefinition,
      CheckValueFunc checkValueFunc,
      const std::string &strHelp)
  {
      return addArg(strArgsDefinition, checkValueFunc, strHelp, true);
  }
  
  AllowedArgs &AllowedArgs::addArg(const std::string &strArgsDefinition,
      CheckValueFunc checkValueFunc,
      const std::string &strHelp,
      bool debug)
  {
      std::string strArgs = strArgsDefinition;
      std::string strExampleValue;
      size_t is_index = strArgsDefinition.find('=');
      if (is_index != std::string::npos)
      {
          strExampleValue = strArgsDefinition.substr(is_index + 1);
          strArgs = strArgsDefinition.substr(0, is_index);
      }
  
      if (strArgs == "")
          strArgs = ",";
  
      std::stringstream streamArgs(strArgs);
      std::string strArg;
      bool firstArg = true;
      while (std::getline(streamArgs, strArg, ','))
      {
          m_args[strArg] = checkValueFunc;
  
          std::string optionText = std::string(optIndent, ' ') + "-" + strArg;
          if (!strExampleValue.empty())
              optionText += "=" + strExampleValue;
          optionText += "\n";
          m_helpList.push_back(HelpComponent{optionText, debug || !firstArg});
  
          firstArg = false;
      }
  
      std::string helpText =
          std::string(msgIndent, ' ') + FormatParagraph(strHelp, screenWidth - msgIndent, msgIndent) + "\n\n";
      m_helpList.push_back(HelpComponent{helpText, debug});
  
      return *this;
  }
  
  void AllowedArgs::checkArg(const std::string &strArg, const std::string &strValue) const
  {
      if (!m_args.count(strArg))
      {
          if (m_permit_unrecognized)
              return;
          throw std::runtime_error(strprintf(_("unrecognized option '%s'"), strArg));
      }
  
      if (!m_args.at(strArg)(strValue))
          throw std::runtime_error(strprintf(_("invalid value '%s' for option '%s'"), strValue, strArg));
  }
  
  std::string AllowedArgs::helpMessage() const
  {
      const bool showDebug = GetBoolArg("-help-debug", false);
      std::string helpMessage;
  
      for (HelpComponent helpComponent : m_helpList)
          if (showDebug || !helpComponent.debug)
              helpMessage += helpComponent.text;
  
      return helpMessage;
  }
  
  //////////////////////////////////////////////////////////////////////////////
  //
  // CheckValueFunc functions
  //
  
  static const std::set<std::string> boolStrings{"", "1", "0", "t", "f", "y", "n", "true", "false", "yes", "no"};
  static const std::set<char> intChars{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
  static const std::set<char> amountChars{'.', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
  
  static bool validateString(const std::string &str, const std::set<char> &validChars)
  {
      for (const char &c : str)
          if (!validChars.count(c))
              return false;
      return true;
  }
  
  static bool optionalBool(const std::string &str) { return (boolStrings.count(str) != 0); }
  static bool requiredStr(const std::string &str) { return !str.empty(); }
  static bool optionalStr(const std::string &str) { return true; }
  static bool requiredInt(const std::string &str)
  {
      if (str.empty() || str == "-")
          return false;
  
      // Allow the first character to be '-', to allow negative numbers.
      return validateString(str[0] == '-' ? str.substr(1) : str, intChars);
  }
  
  static bool optionalInt(const std::string &str)
  {
      if (str.empty())
          return true;
      return requiredInt(str);
  }
  
  static bool requiredAmount(const std::string &str)
  {
      if (str.empty())
          return false;
      return validateString(str, amountChars);
  }
  
  //////////////////////////////////////////////////////////////////////////////
  //
  // Argument definitions
  //
  
  // When adding new arguments to a category, please keep alphabetical ordering,
  // where appropriate. Do not translate _(...) addDebugArg help text: there are
  // many technical terms, and only a very small audience, so it would be an
  // unnecessary stress to translators.
  
  static void addHelpOptions(AllowedArgs &allowedArgs)
  {
      allowedArgs.addHeader(_("Help options:"))
          .addArg("?,h,help", optionalBool, _("This help message"))
          .addArg("version", optionalBool, _("Print version and exit"))
          .addArg("help-debug", optionalBool, _("Show all debugging options (usage: --help -help-debug)"));
  }
  
  static void addChainSelectionOptions(AllowedArgs &allowedArgs)
  {
      allowedArgs.addHeader(_("Chain selection options:"))
          .addArg("chain_nol", optionalBool, _("Use the no-limit blockchain"))
          .addArg("testnet", optionalBool, _("Use the test chain"))
          .addDebugArg("regtest", optionalBool,
              "Enter regression test mode, which uses a special chain in which blocks can be solved instantly. "
              "This is intended for regression testing tools and app development.");
  }
  
  static void addConfigurationLocationOptions(AllowedArgs &allowedArgs)
  {
      allowedArgs.addHeader(_("Configuration location options:"))
          .addArg(
              "conf=<file>", requiredStr, strprintf(_("Specify configuration file (default: %s)"), BITCOIN_CONF_FILENAME))
          .addArg("datadir=<dir>", requiredStr, _("Specify data directory"));
  }
  
  static void addGeneralOptions(AllowedArgs &allowedArgs, HelpMessageMode mode)
  {
      allowedArgs.addHeader(_("General options:"))
          .addArg("alertnotify=<cmd>", requiredStr, _("Execute command when a relevant alert is received or we see a "
                                                      "really long fork (%s in cmd is replaced by message)"))
          .addArg("blocknotify=<cmd>", requiredStr,
              _("Execute command when the best block changes (%s in cmd is replaced by block hash)"))
          .addDebugArg("blocksonly", optionalBool,
              strprintf(_("Whether to operate in a blocks only mode (default: %u)"), DEFAULT_BLOCKSONLY))
          .addArg("checkblocks=<n>", requiredInt,
              strprintf(_("How many blocks to check at startup (default: %u, 0 = all)"), DEFAULT_CHECKBLOCKS))
          .addArg("checklevel=<n>", requiredInt,
              strprintf(_("How thorough the block verification of -checkblocks is (0-4, default: %u)"),
                      DEFAULT_CHECKLEVEL));
  
  #ifndef WIN32
      if (mode == HMM_BITCOIND)
          allowedArgs.addArg("daemon", optionalBool, _("Run in the background as a daemon and accept commands"));
  #endif
  
      allowedArgs
          .addArg("dbcache=<n>", requiredInt, strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"),
                                                  nMinDbCache, nMaxDbCache, nDefaultDbCache))
          .addArg("loadblock=<file>", requiredStr, _("Imports blocks from external blk000??.dat file on startup"))
          .addArg("maxorphantx=<n>", requiredInt,
              strprintf(_("Keep at most <n> unconnectable transactions in memory (default: %u)"),
                      DEFAULT_MAX_ORPHAN_TRANSACTIONS))
          .addArg("maxmempool=<n>", requiredInt,
              strprintf(
                      _("Keep the transaction memory pool below <n> megabytes (default: %u)"), DEFAULT_MAX_MEMPOOL_SIZE))
          .addArg("mempoolexpiry=<n>", requiredInt,
              strprintf(_("Do not keep transactions in the mempool longer than <n> hours (default: %u)"),
                      DEFAULT_MEMPOOL_EXPIRY))
          .addArg("orphanpoolexpiry=<n>", requiredInt,
              strprintf(_("Do not keep transactions in the orphanpool longer than <n> hours (default: %u)"),
                      DEFAULT_ORPHANPOOL_EXPIRY))
          .addArg("par=<n>", requiredInt, strprintf(_("Set the number of script verification threads (%u to %d, 0 = "
                                                      "auto, <0 = leave that many cores free, default: %d)"),
                                              -GetNumCores(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS))
          .addArg("parallel=<n>", optionalBool, strprintf(_("Turn Parallel Block Validation on or off (default: %u)"), 1))
  #ifndef WIN32
          .addArg("pid=<file>", requiredStr, strprintf(_("Specify pid file (default: %s)"), BITCOIN_PID_FILENAME))
  #endif
          .addArg("prune=<n>", requiredInt,
              strprintf(_("Reduce storage requirements by pruning (deleting) old blocks. This mode is incompatible with "
                          "-txindex and -rescan. "
                          "Warning: Reverting this setting requires re-downloading the entire blockchain. "
                          "(default: 0 = disable pruning blocks, >%u = target size in MiB to use for block files)"),
                      MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024))
          .addArg("reindex", optionalBool, _("Rebuild block chain index from current blk000??.dat files on startup"))
          .addArg("txindex", optionalBool,
              strprintf(_("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)"),
                      DEFAULT_TXINDEX));
  }
  
  static void addConnectionOptions(AllowedArgs &allowedArgs)
  {
      allowedArgs.addHeader(_("Connection options:"))
          .addArg("addnode=<ip>", requiredStr, _("Add a node to connect to and attempt to keep the connection open"))
          .addArg("banscore=<n>", requiredInt,
              strprintf(_("Threshold for disconnecting misbehaving peers (default: %u)"), DEFAULT_BANSCORE_THRESHOLD))
          .addArg("bantime=<n>", requiredInt,
              strprintf(_("Number of seconds to keep misbehaving peers from reconnecting (default: %u)"),
                      DEFAULT_MISBEHAVING_BANTIME))
          .addArg("bind=<addr>", requiredStr,
              _("Bind to given address and always listen on it. Use [host]:port notation for IPv6"))
          .addArg("bitnodes", optionalBool,
              _("Query for peer addresses via Bitnodes API, if low on addresses (default: 1 unless -connect)"))
          .addArg("blkretryinterval", requiredInt,
              strprintf(_("Time to wait before requesting a block from a different peer, in microseconds (default: %u)"),
                      DEFAULT_MIN_BLK_REQUEST_RETRY_INTERVAL))
          .addArg("connect=<ip>", optionalStr, _("Connect only to the specified node(s)"))
          .addArg("connect-thin
  
  [... the rest is omitted ...]
files: src/allowed_args.cpp
files: // Copyright (c) 2009-2010 Satoshi Nakamoto
  // Copyright (c) 2009-2015 The Bitcoin Core developers
  // Copyright (c) 2015-2017 The Bitcoin Unlimited developers
  // Distributed under the MIT software license, see the accompanying
  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  
  #ifndef BITCOIN_INIT_H
  #define BITCOIN_INIT_H
  
  #include <string>
  
  class CScheduler;
  class CWallet;
  
  namespace boost
  {
  class thread_group;
  } // namespace boost
  
  void StartShutdown();
  bool ShutdownRequested();
  /** Interrupt threads */
  void Interrupt(boost::thread_group& threadGroup);
  void Shutdown();
  //!Initialize the logging infrastructure
  void InitLogging();
  //!Parameter interaction: change current parameters depending on various rules
  void InitParameterInteraction();
  bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler);
  
  void MainCleanup();
  void NetCleanup();
  
  static const bool DEFAULT_PROXYRANDOMIZE = true;
  static const bool DEFAULT_REST_ENABLE = false;
  static const bool DEFAULT_DISABLE_SAFEMODE = false;
  static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false;
  static const bool DEFAULT_PV_TESTMODE = false;
  
  /** Returns licensing information (for -version) */
  std::string LicenseInfo();
  
  #endif // BITCOIN_INIT_H
  
  
  [... the rest is omitted ...]
files: src/init.h
files: // Copyright (c) 2009-2010 Satoshi Nakamoto
  // Copyright (c) 2009-2015 The Bitcoin Core developers
  // Copyright (c) 2015-2017 The Bitcoin Unlimited developers
  // Distributed under the MIT software license, see the accompanying
  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  
  #ifndef BITCOIN_INIT_H
  #define BITCOIN_INIT_H
  
  #include <string>
  
  class CScheduler;
  class CWallet;
  
  namespace boost
  {
  class thread_group;
  } // namespace boost
  
  void StartShutdown();
  bool ShutdownRequested();
  /** Interrupt threads */
  void Interrupt(boost::thread_group& threadGroup);
  void Shutdown();
  //!Initialize the logging infrastructure
  void InitLogging();
  //!Parameter interaction: change current parameters depending on various rules
  void InitParameterInteraction();
  bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler);
  
  void MainCleanup();
  void NetCleanup();
  
  static const bool DEFAULT_PROXYRANDOMIZE = true;
  static const bool DEFAULT_REST_ENABLE = false;
  static const bool DEFAULT_DISABLE_SAFEMODE = false;
  static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false;
  
  /** Returns licensing information (for -version) */
  std::string LicenseInfo();
  
  #endif // BITCOIN_INIT_H
  
  
  [... the rest is omitted ...]
files: src/init.h
files: // Copyright (c) 2009-2010 Satoshi Nakamoto
  // Copyright (c) 2009-2015 The Bitcoin Core developers
  // Copyright (c) 2015-2017 The Bitcoin Unlimited developers
  // Copyright (c) 2016 Bitcoin Unlimited developers
  // Distributed under the MIT software license, see the accompanying
  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  
  #include "main.h"
  
  #include "addrman.h"
  #include "arith_uint256.h"
  #include "chainparams.h"
  #include "checkpoints.h"
  #include "checkqueue.h"
  #include "connmgr.h"
  #include "consensus/consensus.h"
  #include "consensus/merkle.h"
  #include "consensus/validation.h"
  #include "dosman.h"
  #include "expedited.h"
  #include "hash.h"
  #include "init.h"
  #include "merkleblock.h"
  #include "net.h"
  #include "nodestate.h"
  #include "parallel.h"
  #include "policy/policy.h"
  #include "pow.h"
  #include "primitives/block.h"
  #include "primitives/transaction.h"
  #include "requestManager.h"
  #include "script/script.h"
  #include "script/sigcache.h"
  #include "script/standard.h"
  #include "thinblock.h"
  #include "tinyformat.h"
  #include "txdb.h"
  #include "txmempool.h"
  #include "ui_interface.h"
  #include "undo.h"
  #include "util.h"
  #include "utilmoneystr.h"
  #include "utilstrencodings.h"
  #include "validationinterface.h"
  #include "versionbits.h"
  
  #include <algorithm>
  #include <boost/algorithm/hex.hpp>
  #include <boost/algorithm/string/replace.hpp>
  #include <boost/filesystem.hpp>
  #include <boost/filesystem/fstream.hpp>
  #include <boost/math/distributions/poisson.hpp>
  #include <boost/scope_exit.hpp>
  #include <boost/thread.hpp>
  #include <sstream>
  
  #if defined(NDEBUG)
  #error "Bitcoin cannot be compiled without assertions."
  #endif
  
  /**
   * Global state
   */
  
  // BU variables moved to globals.cpp
  // BU moved CCriticalSection cs_main;
  
  // BU moved BlockMap mapBlockIndex;
  // BU movedCChain chainActive;
  CBlockIndex *pindexBestHeader = NULL;
  int64_t nTimeBestReceived = 0;
  // BU moved CWaitableCriticalSection csBestBlock;
  // BU moved CConditionVariable cvBlockChange;
  bool fImporting = false;
  bool fReindex = false;
  bool fTxIndex = false;
  bool fHavePruned = false;
  bool fPruneMode = false;
  bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG;
  bool fRequireStandard = true;
  unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP;
  bool fCheckBlockIndex = false;
  bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED;
  size_t nCoinCacheUsage = 5000 * 300;
  uint64_t nPruneTarget = 0;
  
  CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
  
  // BU: Move global objects to a single file
  extern CTxMemPool mempool;
  
  // BU: change locking of orphan map from using cs_main to cs_orphancache.
  // There is too much dependance on cs_main locks which are generally too
  // broad in scope.
  // Move globals to a single file
  extern CCriticalSection cs_orphancache;
  extern std::map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY(cs_orphancache);
  extern std::map<uint256, std::set<uint256> > mapOrphanTransactionsByPrev GUARDED_BY(cs_orphancache);
  
  int64_t nLastOrphanCheck = GetTime(); // Used in EraseOrphansByTime()
  static uint64_t nBytesOrphanPool = 0; // Current in memory size of the orphan pool.
  
  // BU: start block download at low numbers in case our peers are slow when we start
  /** Number of blocks that can be requested at any given time from a single peer. */
  static unsigned int MAX_BLOCKS_IN_TRANSIT_PER_PEER = 1;
  /** Size of the "block download window": how far ahead of our current height do we fetch?
   *  Larger windows tolerate larger download speed differences between peer, but increase the potential
   *  degree of disordering of blocks on disk (which make reindexing and in the future perhaps pruning
   *  harder). We'll probably want to make this a per-peer adaptive value at some point. */
  static unsigned int BLOCK_DOWNLOAD_WINDOW = 256;
  
  extern CTweak<unsigned int> maxBlocksInTransitPerPeer; // override the above
  extern CTweak<unsigned int> blockDownloadWindow;
  extern CTweak<uint64_t> reindexTypicalBlockSize;
  
  extern std::map<CNetAddr, ConnectionHistory> mapInboundConnectionTracker;
  extern CCriticalSection cs_mapInboundConnectionTracker;
  
  /** A cache to store headers that have arrived but can not yet be connected **/
  std::map<uint256, std::pair<CBlockHeader, int64_t> > mapUnConnectedHeaders;
  
  /**
   * Returns true if there are nRequired or more blocks of minVersion or above
   * in the last Consensus::Params::nMajorityWindow blocks, starting at pstart and going backwards.
   */
  static bool IsSuperMajority(int minVersion,
      const CBlockIndex *pstart,
      unsigned nRequired,
      const Consensus::Params &consensusParams);
  static void CheckBlockIndex(const Consensus::Params &consensusParams);
  
  /** Constant stuff for coinbase transactions we create: */
  CScript COINBASE_FLAGS;
  
  const std::string strMessageMagic = "Bitcoin Signed Message:\n";
  
  extern CStatHistory<uint64_t> nTxValidationTime;
  extern CStatHistory<uint64_t> nBlockValidationTime;
  extern CCriticalSection cs_blockvalidationtime;
  
  extern CCriticalSection cs_LastBlockFile;
  extern CCriticalSection cs_nBlockSequenceId;
  
  
  // Internal stuff
  namespace
  {
  struct CBlockIndexWorkComparator
  {
      bool operator()(CBlockIndex *pa, CBlockIndex *pb) const
      {
          // First sort by most total work, ...
          if (pa->nChainWork > pb->nChainWork)
              return false;
          if (pa->nChainWork < pb->nChainWork)
              return true;
  
          // ... then by earliest time received, ...
          if (pa->nSequenceId < pb->nSequenceId)
              return false;
          if (pa->nSequenceId > pb->nSequenceId)
              return true;
  
          // Use pointer address as tie breaker (should only happen with blocks
          // loaded from disk, as those all have id 0).
          if (pa < pb)
              return false;
          if (pa > pb)
              return true;
  
          // Identical blocks.
          return false;
      }
  };
  
  CBlockIndex *pindexBestInvalid;
  
  /**
   * The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS (for itself and all ancestors) and
   * as good as our current tip or better. Entries may be failed, though, and pruning nodes may be
   * missing the data for the block.
   */
  std::set<CBlockIndex *, CBlockIndexWorkComparator> setBlockIndexCandidates;
  /** Number of nodes with fSyncStarted. */
  int nSyncStarted = 0;
  /** All pairs A->B, where A (or one of its ancestors) misses transactions, but B has transactions.
   * Pruned nodes may have entries where B is missing data.
   */
  std::multimap<CBlockIndex *, CBlockIndex *> mapBlocksUnlinked;
  
  std::vector<CBlockFileInfo> vinfoBlockFile;
  int nLastBlockFile = 0;
  /** Global flag to indicate we should check to see if there are
   *  block/undo files that should be deleted.  Set on startup
   *  or if we allocate more file space when we're in prune mode
   */
  bool fCheckForPruning = false;
  
  /**
   * Every received block is assigned a unique and increasing identifier, so we
   * know which one to give priority in case of a fork.
   */
  /** Blocks loaded from disk are assigned id 0, so start the counter at 1. */
  uint32_t nBlockSequenceId = 1;
  
  /**
   * Sources of received blocks, saved to be able to send them reject
   * messages or ban them when processing happens afterwards. Protected by
   * cs_main.
   */
  std::map<uint256, NodeId> mapBlockSource;
  
  /**
   * Filter for transactions that were recently rejected by
   * AcceptToMemoryPool. These are not rerequested until the chain tip
   * changes, at which point the entire filter is reset. Protected by
   * cs_main.
   *
   * Without this filter we'd be re-requesting txs from each of our peers,
   * increasing bandwidth consumption considerably. For instance, with 100
   * peers, half of which relay a tx we don't accept, that might be a 50x
   * bandwidth increase. A flooding attacker attempting to roll-over the
   * filter using minimum-sized, 60byte, transactions might manage to send
   * 1000/sec if we have fast peers, so we pick 120,000 to give our peers a
   * two minute window to send invs to us.
   *
   * Decreasing the false positive rate is fairly cheap, so we pick one in a
   * million to make it highly unlikely for users to have issues with this
   * filter.
   *
   * Memory used: 1.7MB
   */
  boost::scoped_ptr<CRollingBloomFilter> recentRejects;
  uint256 hashRecentRejectsChainTip;
  
  /** Number of preferable block download peers. */
  int nPreferredDownload = 0;
  
  /** Dirty block index entries. */
  std::set<CBlockIndex *> setDirtyBlockIndex;
  
  /** Dirty block file entries. */
  std::set<int> setDirtyFileInfo;
  
  /** Number of peers from which we're downloading blocks. */
  int nPeersWithValidatedDownloads = 0;
  } // anon namespace
  
  
  //////////////////////////////////////////////////////////////////////////////
  //
  // Registration of network node signals.
  //
  
  namespace
  {
  int GetHeight()
  {
      LOCK(cs_main);
      return chainActive.Height();
  }
  
  void UpdatePreferredDownload(CNode *node, CNodeState *state)
  {
      nPreferredDownload -= state->fPreferredDownload;
  
      // Whether this node should be marked as a preferred download node.
      state->fPreferredDownload = (!node->fInbound || node->fWhitelisted) && !node->fOneShot && !node->fClient;
  
      nPreferredDownload += state->fPreferredDownload;
  }
  
  void InitializeNode(NodeId nodeid, const CNode *pnode)
  {
      LOCK(cs_main);
      CNodeState &state = mapNodeState.insert(std::make_pair(nodeid, CNodeState())).first->second;
      state.name = pnode->addrName;
      state.address = pnode->addr;
  }
  
  void FinalizeNode(NodeId nodeid)
  {
      LOCK(cs_main);
      CNodeState *state = State(nodeid);
  
      if (state->fSyncStarted)
          nSyncStarted--;
  
      BOOST_FOREACH (const QueuedBlock &entry, state->vBlocksInFlight)
      {
          mapBlocksInFlight.erase(entry.hash);
      }
      nPreferredDownload -= state->fPreferredDownload;
      nPeersWithValidatedDownloads -= (state->nBlocksInFlightValidHeaders != 0);
      DbgAssert(nPeersWithValidatedDownloads >= 0, nPeersWithValidatedDownloads = 0);
  
      mapNodeState.erase(nodeid);
  
      if (mapNodeState.empty())
      {
          // Do a consistency check after the last peer is removed.  Force consistent state if production code
          DbgAssert(mapBlocksInFlight.empty(), mapBlocksInFlight.clear());
          DbgAssert(nPreferredDownload == 0, nPreferredDownload = 0);
          DbgAssert(nPeersWithValidatedDownloads == 0, nPeersWithValidatedDownloads = 0);
      }
  }
  
  // Requires cs_main.
  // Returns a bool indicating whether we requested this block.
  bool MarkBlockAsReceived(const uint256 &hash)
  {
      std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator> >::iterator itInFlight =
          mapBlocksInFlight.find(hash);
      if (itInFlight != mapBlocksInFlight.end())
      {
          // BUIP010 Xtreme Thinblocks: begin section
          int64_t getdataTime = itInFlight->second.second->nTime;
          int64_t now = GetTimeMicros();
          double nResponseTime = (double)(now - getdataTime) / 1000000.0;
  
          // BU:  calculate avg block response time over last 20 blocks to be used for IBD tuning
          // start at a higher number so that we don't start jamming IBD when we restart a node sync
          static double avgResponseTime = 5;
          static uint8_t blockRange = 20;
          if (avgResponseTime > 0)
              avgResponseTime -= (avgResponseTime / blockRange);
          avgResponseTime += nResponseTime / blockRange;
          if (avgResponseTime < 0.2)
          {
              MAX_BLOCKS_IN_TRANSIT_PER_PEER = 32;
          }
          else if (avgResponseTime < 0.5)
          {
              MAX_BLOCKS_IN_TRANSIT_PER_PEER = 16;
          }
          else if (avgResponseTime < 0.9)
          {
              MAX_BLOCKS_IN_TRANSIT_PER_PEER = 8;
          }
          else if (avgResponseTime < 1.4)
          {
              MAX_BLOCKS_IN_TRANSIT_PER_PEER = 4;
          }
          else if (avgResponseTime < 2.0)
          {
              MAX_BLOCKS_IN_TRANSIT_PER_PEER = 2;
          }
          else
          {
              MAX_BLOCKS_IN_TRANSIT_PER_PEER = 1;
          }
  
          LogPrint("thin", "Received block %s in %.2f seconds\n", hash.ToString(), nResponseTime);
          LogPrint("thin", "Average block response time is %.2f seconds\n", avgResponseTime);
          if (maxBlocksInTransitPerPeer.value != 0)
          {
              MAX_BLOCKS_IN_TRANSIT_PER_PEER = maxBlocksInTransitPerPeer.value;
          }
          if (blockDownloadWindow.value != 0)
          {
              BLOCK_DOWNLOAD_WINDOW = blockDownloadWindow.value;
          }
          LogPrint("thin", "BLOCK_DOWNLOAD_WINDOW is %d MAX_BLOCKS_IN_TRANSIT_PER_PEER
  
  [... the rest is omitted ...]
files: src/main.cpp
files: // Copyright (c) 2009-2010 Satoshi Nakamoto
  // Copyright (c) 2009-2015 The Bitcoin Core developers
  // Copyright (c) 2015-2017 The Bitcoin Unlimited developers
  // Copyright (c) 2016 Bitcoin Unlimited developers
  // Distributed under the MIT software license, see the accompanying
  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  
  #include "main.h"
  
  #include "addrman.h"
  #include "arith_uint256.h"
  #include "chainparams.h"
  #include "checkpoints.h"
  #include "checkqueue.h"
  #include "connmgr.h"
  #include "consensus/consensus.h"
  #include "consensus/merkle.h"
  #include "consensus/validation.h"
  #include "dosman.h"
  #include "expedited.h"
  #include "hash.h"
  #include "init.h"
  #include "merkleblock.h"
  #include "net.h"
  #include "nodestate.h"
  #include "parallel.h"
  #include "policy/policy.h"
  #include "pow.h"
  #include "primitives/block.h"
  #include "primitives/transaction.h"
  #include "requestManager.h"
  #include "script/script.h"
  #include "script/sigcache.h"
  #include "script/standard.h"
  #include "thinblock.h"
  #include "tinyformat.h"
  #include "txdb.h"
  #include "txmempool.h"
  #include "ui_interface.h"
  #include "undo.h"
  #include "util.h"
  #include "utilmoneystr.h"
  #include "utilstrencodings.h"
  #include "validationinterface.h"
  #include "versionbits.h"
  
  #include <algorithm>
  #include <boost/algorithm/hex.hpp>
  #include <boost/algorithm/string/replace.hpp>
  #include <boost/filesystem.hpp>
  #include <boost/filesystem/fstream.hpp>
  #include <boost/math/distributions/poisson.hpp>
  #include <boost/scope_exit.hpp>
  #include <boost/thread.hpp>
  #include <sstream>
  
  #if defined(NDEBUG)
  #error "Bitcoin cannot be compiled without assertions."
  #endif
  
  /**
   * Global state
   */
  
  // BU variables moved to globals.cpp
  // BU moved CCriticalSection cs_main;
  
  // BU moved BlockMap mapBlockIndex;
  // BU movedCChain chainActive;
  CBlockIndex *pindexBestHeader = NULL;
  int64_t nTimeBestReceived = 0;
  // BU moved CWaitableCriticalSection csBestBlock;
  // BU moved CConditionVariable cvBlockChange;
  bool fImporting = false;
  bool fReindex = false;
  bool fTxIndex = false;
  bool fHavePruned = false;
  bool fPruneMode = false;
  bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG;
  bool fRequireStandard = true;
  unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP;
  bool fCheckBlockIndex = false;
  bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED;
  size_t nCoinCacheUsage = 5000 * 300;
  uint64_t nPruneTarget = 0;
  
  CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
  
  // BU: Move global objects to a single file
  extern CTxMemPool mempool;
  
  // BU: change locking of orphan map from using cs_main to cs_orphancache.
  // There is too much dependance on cs_main locks which are generally too
  // broad in scope.
  // Move globals to a single file
  extern CCriticalSection cs_orphancache;
  extern std::map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY(cs_orphancache);
  extern std::map<uint256, std::set<uint256> > mapOrphanTransactionsByPrev GUARDED_BY(cs_orphancache);
  
  int64_t nLastOrphanCheck = GetTime(); // Used in EraseOrphansByTime()
  static uint64_t nBytesOrphanPool = 0; // Current in memory size of the orphan pool.
  
  // BU: start block download at low numbers in case our peers are slow when we start
  /** Number of blocks that can be requested at any given time from a single peer. */
  static unsigned int MAX_BLOCKS_IN_TRANSIT_PER_PEER = 1;
  /** Size of the "block download window": how far ahead of our current height do we fetch?
   *  Larger windows tolerate larger download speed differences between peer, but increase the potential
   *  degree of disordering of blocks on disk (which make reindexing and in the future perhaps pruning
   *  harder). We'll probably want to make this a per-peer adaptive value at some point. */
  static unsigned int BLOCK_DOWNLOAD_WINDOW = 256;
  
  extern CTweak<unsigned int> maxBlocksInTransitPerPeer; // override the above
  extern CTweak<unsigned int> blockDownloadWindow;
  extern CTweak<uint64_t> reindexTypicalBlockSize;
  
  extern std::map<CNetAddr, ConnectionHistory> mapInboundConnectionTracker;
  extern CCriticalSection cs_mapInboundConnectionTracker;
  
  /** A cache to store headers that have arrived but can not yet be connected **/
  std::map<uint256, std::pair<CBlockHeader, int64_t> > mapUnConnectedHeaders;
  
  /**
   * Returns true if there are nRequired or more blocks of minVersion or above
   * in the last Consensus::Params::nMajorityWindow blocks, starting at pstart and going backwards.
   */
  static bool IsSuperMajority(int minVersion,
      const CBlockIndex *pstart,
      unsigned nRequired,
      const Consensus::Params &consensusParams);
  static void CheckBlockIndex(const Consensus::Params &consensusParams);
  
  /** Constant stuff for coinbase transactions we create: */
  CScript COINBASE_FLAGS;
  
  const std::string strMessageMagic = "Bitcoin Signed Message:\n";
  
  extern CStatHistory<uint64_t> nTxValidationTime;
  extern CStatHistory<uint64_t> nBlockValidationTime;
  extern CCriticalSection cs_blockvalidationtime;
  
  extern CCriticalSection cs_LastBlockFile;
  extern CCriticalSection cs_nBlockSequenceId;
  
  
  // Internal stuff
  namespace
  {
  struct CBlockIndexWorkComparator
  {
      bool operator()(CBlockIndex *pa, CBlockIndex *pb) const
      {
          // First sort by most total work, ...
          if (pa->nChainWork > pb->nChainWork)
              return false;
          if (pa->nChainWork < pb->nChainWork)
              return true;
  
          // ... then by earliest time received, ...
          if (pa->nSequenceId < pb->nSequenceId)
              return false;
          if (pa->nSequenceId > pb->nSequenceId)
              return true;
  
          // Use pointer address as tie breaker (should only happen with blocks
          // loaded from disk, as those all have id 0).
          if (pa < pb)
              return false;
          if (pa > pb)
              return true;
  
          // Identical blocks.
          return false;
      }
  };
  
  CBlockIndex *pindexBestInvalid;
  
  /**
   * The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS (for itself and all ancestors) and
   * as good as our current tip or better. Entries may be failed, though, and pruning nodes may be
   * missing the data for the block.
   */
  std::set<CBlockIndex *, CBlockIndexWorkComparator> setBlockIndexCandidates;
  /** Number of nodes with fSyncStarted. */
  int nSyncStarted = 0;
  /** All pairs A->B, where A (or one of its ancestors) misses transactions, but B has transactions.
   * Pruned nodes may have entries where B is missing data.
   */
  std::multimap<CBlockIndex *, CBlockIndex *> mapBlocksUnlinked;
  
  std::vector<CBlockFileInfo> vinfoBlockFile;
  int nLastBlockFile = 0;
  /** Global flag to indicate we should check to see if there are
   *  block/undo files that should be deleted.  Set on startup
   *  or if we allocate more file space when we're in prune mode
   */
  bool fCheckForPruning = false;
  
  /**
   * Every received block is assigned a unique and increasing identifier, so we
   * know which one to give priority in case of a fork.
   */
  /** Blocks loaded from disk are assigned id 0, so start the counter at 1. */
  uint32_t nBlockSequenceId = 1;
  
  /**
   * Sources of received blocks, saved to be able to send them reject
   * messages or ban them when processing happens afterwards. Protected by
   * cs_main.
   */
  std::map<uint256, NodeId> mapBlockSource;
  
  /**
   * Filter for transactions that were recently rejected by
   * AcceptToMemoryPool. These are not rerequested until the chain tip
   * changes, at which point the entire filter is reset. Protected by
   * cs_main.
   *
   * Without this filter we'd be re-requesting txs from each of our peers,
   * increasing bandwidth consumption considerably. For instance, with 100
   * peers, half of which relay a tx we don't accept, that might be a 50x
   * bandwidth increase. A flooding attacker attempting to roll-over the
   * filter using minimum-sized, 60byte, transactions might manage to send
   * 1000/sec if we have fast peers, so we pick 120,000 to give our peers a
   * two minute window to send invs to us.
   *
   * Decreasing the false positive rate is fairly cheap, so we pick one in a
   * million to make it highly unlikely for users to have issues with this
   * filter.
   *
   * Memory used: 1.7MB
   */
  boost::scoped_ptr<CRollingBloomFilter> recentRejects;
  uint256 hashRecentRejectsChainTip;
  
  /** Number of preferable block download peers. */
  int nPreferredDownload = 0;
  
  /** Dirty block index entries. */
  std::set<CBlockIndex *> setDirtyBlockIndex;
  
  /** Dirty block file entries. */
  std::set<int> setDirtyFileInfo;
  
  /** Number of peers from which we're downloading blocks. */
  int nPeersWithValidatedDownloads = 0;
  } // anon namespace
  
  
  //////////////////////////////////////////////////////////////////////////////
  //
  // Registration of network node signals.
  //
  
  namespace
  {
  int GetHeight()
  {
      LOCK(cs_main);
      return chainActive.Height();
  }
  
  void UpdatePreferredDownload(CNode *node, CNodeState *state)
  {
      nPreferredDownload -= state->fPreferredDownload;
  
      // Whether this node should be marked as a preferred download node.
      state->fPreferredDownload = (!node->fInbound || node->fWhitelisted) && !node->fOneShot && !node->fClient;
  
      nPreferredDownload += state->fPreferredDownload;
  }
  
  void InitializeNode(NodeId nodeid, const CNode *pnode)
  {
      LOCK(cs_main);
      CNodeState &state = mapNodeState.insert(std::make_pair(nodeid, CNodeState())).first->second;
      state.name = pnode->addrName;
      state.address = pnode->addr;
  }
  
  void FinalizeNode(NodeId nodeid)
  {
      LOCK(cs_main);
      CNodeState *state = State(nodeid);
  
      if (state->fSyncStarted)
          nSyncStarted--;
  
      BOOST_FOREACH (const QueuedBlock &entry, state->vBlocksInFlight)
      {
          mapBlocksInFlight.erase(entry.hash);
      }
      nPreferredDownload -= state->fPreferredDownload;
      nPeersWithValidatedDownloads -= (state->nBlocksInFlightValidHeaders != 0);
      DbgAssert(nPeersWithValidatedDownloads >= 0, nPeersWithValidatedDownloads = 0);
  
      mapNodeState.erase(nodeid);
  
      if (mapNodeState.empty())
      {
          // Do a consistency check after the last peer is removed.  Force consistent state if production code
          DbgAssert(mapBlocksInFlight.empty(), mapBlocksInFlight.clear());
          DbgAssert(nPreferredDownload == 0, nPreferredDownload = 0);
          DbgAssert(nPeersWithValidatedDownloads == 0, nPeersWithValidatedDownloads = 0);
      }
  }
  
  // Requires cs_main.
  // Returns a bool indicating whether we requested this block.
  bool MarkBlockAsReceived(const uint256 &hash)
  {
      std::map<uint256, std::pair<NodeId, std::list<QueuedBlock>::iterator> >::iterator itInFlight =
          mapBlocksInFlight.find(hash);
      if (itInFlight != mapBlocksInFlight.end())
      {
          // BUIP010 Xtreme Thinblocks: begin section
          int64_t getdataTime = itInFlight->second.second->nTime;
          int64_t now = GetTimeMicros();
          double nResponseTime = (double)(now - getdataTime) / 1000000.0;
  
          // BU:  calculate avg block response time over last 20 blocks to be used for IBD tuning
          // start at a higher number so that we don't start jamming IBD when we restart a node sync
          static double avgResponseTime = 5;
          static uint8_t blockRange = 20;
          if (avgResponseTime > 0)
              avgResponseTime -= (avgResponseTime / blockRange);
          avgResponseTime += nResponseTime / blockRange;
          if (avgResponseTime < 0.2)
          {
              MAX_BLOCKS_IN_TRANSIT_PER_PEER = 32;
          }
          else if (avgResponseTime < 0.5)
          {
              MAX_BLOCKS_IN_TRANSIT_PER_PEER = 16;
          }
          else if (avgResponseTime < 0.9)
          {
              MAX_BLOCKS_IN_TRANSIT_PER_PEER = 8;
          }
          else if (avgResponseTime < 1.4)
          {
              MAX_BLOCKS_IN_TRANSIT_PER_PEER = 4;
          }
          else if (avgResponseTime < 2.0)
          {
              MAX_BLOCKS_IN_TRANSIT_PER_PEER = 2;
          }
          else
          {
              MAX_BLOCKS_IN_TRANSIT_PER_PEER = 1;
          }
  
          LogPrint("thin", "Received block %s in %.2f seconds\n", hash.ToString(), nResponseTime);
          LogPrint("thin", "Average block response time is %.2f seconds\n", avgResponseTime);
          if (maxBlocksInTransitPerPeer.value != 0)
          {
              MAX_BLOCKS_IN_TRANSIT_PER_PEER = maxBlocksInTransitPerPeer.value;
          }
          if (blockDownloadWindow.value != 0)
          {
              BLOCK_DOWNLOAD_WINDOW = blockDownloadWindow.value;
          }
          LogPrint("thin", "BLOCK_DOWNLOAD_WINDOW is %d MAX_BLOCKS_IN_TRANSIT_PER_PEER
  
  [... the rest is omitted ...]
files: src/main.cpp