Auto merge of #4874 - str4d:rpc-tests-py, r=str4d
Backport migration from rpc-tests.sh to rpc-tests.py Cherry-picked from the following upstream PRs: - bitcoin/bitcoin#6567 - bitcoin/bitcoin#6523 - bitcoin/bitcoin#6616 - bitcoin/bitcoin#6788 - Only the commit fixing `rpc-tests.py` - bitcoin/bitcoin#6791 - Only the fix to `qa/rpc-tests/README.md` - bitcoin/bitcoin#6827 - bitcoin/bitcoin#6930 - bitcoin/bitcoin#6804 - bitcoin/bitcoin#7029 - bitcoin/bitcoin#7028 - bitcoin/bitcoin#7027 - bitcoin/bitcoin#7135 - bitcoin/bitcoin#7209 - bitcoin/bitcoin#7635 - bitcoin/bitcoin#7778 - bitcoin/bitcoin#7851 - bitcoin/bitcoin#7814 - Only the changes to the new .py files in this PR. - bitcoin/bitcoin#7971 - bitcoin/bitcoin#7972 - bitcoin/bitcoin#8056 - Only the first commit. - bitcoin/bitcoin#8098 - bitcoin/bitcoin#8104 - bitcoin/bitcoin#8133 - Only the `rpc-tests.py` commit. - bitcoin/bitcoin#8066 - bitcoin/bitcoin#8216 - Only the last two commits. - bitcoin/bitcoin#8254 - bitcoin/bitcoin#8400 - bitcoin/bitcoin#8482 - Excluding the first commit (only affects RPC tests we don't have). - bitcoin/bitcoin#8551 - bitcoin/bitcoin#8607 - Only the pull-tester commit, for conflict removal. - bitcoin/bitcoin#8625 - bitcoin/bitcoin#8713 - bitcoin/bitcoin#8750 - bitcoin/bitcoin#8789 - bitcoin/bitcoin#9098 - bitcoin/bitcoin#9276 - Excluding the second commit (we don't have the changes it requires). - bitcoin/bitcoin#9657 - bitcoin/bitcoin#9807 - bitcoin/bitcoin#9766 - bitcoin/bitcoin#9823
This commit is contained in:
commit
c8896f9907
|
@ -104,10 +104,9 @@ afl-temp
|
|||
linux-coverage-build
|
||||
linux-build
|
||||
win32-build
|
||||
qa/pull-tester/run-bitcoind-for-test.sh
|
||||
qa/pull-tester/tests-config.sh
|
||||
qa/pull-tester/cache/*
|
||||
qa/pull-tester/test.*/*
|
||||
qa/pull-tester/tests_config.py
|
||||
qa/pull-tester/tests_config.ini
|
||||
qa/cache/*
|
||||
|
||||
!src/leveldb*/Makefile
|
||||
|
||||
|
|
|
@ -147,7 +147,7 @@ dist_noinst_SCRIPTS = autogen.sh zcutil/build-debian-package.sh zcutil/build.sh
|
|||
|
||||
RUST_DIST = $(top_srcdir)/.cargo $(top_srcdir)/Cargo.toml $(top_srcdir)/Cargo.lock rust-toolchain
|
||||
|
||||
EXTRA_DIST = $(top_srcdir)/share/genbuild.sh qa/pull-tester/rpc-tests.sh qa/rpc-tests qa/zcash $(DIST_DOCS) $(BIN_CHECKS) $(RUST_DIST)
|
||||
EXTRA_DIST = $(top_srcdir)/share/genbuild.sh qa/pull-tester/rpc-tests.py qa/rpc-tests qa/zcash $(DIST_DOCS) $(BIN_CHECKS) $(RUST_DIST)
|
||||
|
||||
install-exec-hook:
|
||||
mv $(DESTDIR)$(bindir)/fetch-params.sh $(DESTDIR)$(bindir)/zcash-fetch-params
|
||||
|
@ -159,6 +159,7 @@ DISTCHECK_CONFIGURE_FLAGS = --enable-man
|
|||
clean-local:
|
||||
rm -rf test_bitcoin.coverage/ zcash-gtest.coverage/ total.coverage/
|
||||
rm -rf afl-temp
|
||||
rm -rf qa/pull-tester/__pycache__
|
||||
|
||||
distclean-local:
|
||||
rm -f zcutil/bin/db_*
|
||||
|
|
13
configure.ac
13
configure.ac
|
@ -968,8 +968,8 @@ AC_SUBST(EVENT_PTHREADS_LIBS)
|
|||
AC_SUBST(ZMQ_LIBS)
|
||||
AC_SUBST(LIBZCASH_LIBS)
|
||||
AC_CONFIG_FILES([Makefile src/Makefile doc/man/Makefile src/test/buildenv.py])
|
||||
AC_CONFIG_FILES([qa/pull-tester/run-bitcoind-for-test.sh],[chmod +x qa/pull-tester/run-bitcoind-for-test.sh])
|
||||
AC_CONFIG_FILES([qa/pull-tester/tests-config.sh],[chmod +x qa/pull-tester/tests-config.sh])
|
||||
AC_CONFIG_FILES([qa/pull-tester/tests_config.ini],[chmod +x qa/pull-tester/tests_config.ini])
|
||||
AC_CONFIG_LINKS([qa/pull-tester/rpc-tests.py:qa/pull-tester/rpc-tests.py])
|
||||
|
||||
dnl boost's m4 checks do something really nasty: they export these vars. As a
|
||||
dnl result, they leak into secp256k1's configure and crazy things happen.
|
||||
|
@ -1010,6 +1010,15 @@ case $host in
|
|||
;;
|
||||
esac
|
||||
|
||||
dnl Replace the BUILDDIR path with the correct Windows path if compiling on Native Windows
|
||||
case ${OS} in
|
||||
*Windows*)
|
||||
sed 's/BUILDDIR="\/\([[a-z]]\)/BUILDDIR="\1:/' qa/pull-tester/tests_config.py > qa/pull-tester/tests_config-2.py
|
||||
mv qa/pull-tester/tests_config-2.py qa/pull-tester/tests_config.py
|
||||
chmod +x qa/pull-tester/tests_config.py
|
||||
;;
|
||||
esac
|
||||
|
||||
echo
|
||||
echo "Options used to compile and link:"
|
||||
echo " with wallet = $enable_wallet"
|
||||
|
|
|
@ -40,7 +40,7 @@ Typically, it is packaged by distributions as something like
|
|||
*libzmq5-dev*. The C++ wrapper for ZeroMQ is *not* needed.
|
||||
|
||||
In order to run the example Python client scripts in contrib/ one must
|
||||
also install *python-zmq*, though this is not necessary for daemon
|
||||
also install *python3-zmq*, though this is not necessary for daemon
|
||||
operation.
|
||||
|
||||
## Security WARNING
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
The [pull-tester](/qa/pull-tester/) folder contains a script to call
|
||||
multiple tests from the [rpc-tests](/qa/rpc-tests/) folder.
|
||||
|
||||
Every pull request to the zcash repository is built and run through
|
||||
the regression test suite. You can also run all or only individual
|
||||
tests locally.
|
||||
|
||||
Test dependencies
|
||||
=================
|
||||
Before running the tests, the following must be installed.
|
||||
|
||||
Unix
|
||||
----
|
||||
The python3-zmq library is required. On Ubuntu or Debian it can be installed via:
|
||||
```
|
||||
sudo apt-get install python3-zmq
|
||||
```
|
||||
|
||||
OS X
|
||||
------
|
||||
```
|
||||
pip3 install pyzmq
|
||||
```
|
||||
|
||||
Running tests
|
||||
=============
|
||||
|
||||
You can run any single test by calling
|
||||
|
||||
qa/pull-tester/rpc-tests.py <testname>
|
||||
|
||||
Or you can run any combination of tests by calling
|
||||
|
||||
qa/pull-tester/rpc-tests.py <testname1> <testname2> <testname3> ...
|
||||
|
||||
Run the regression test suite with
|
||||
|
||||
qa/pull-tester/rpc-tests.py
|
||||
|
||||
Run all possible tests with
|
||||
|
||||
qa/pull-tester/rpc-tests.py --extended
|
||||
|
||||
By default, tests will be run in parallel. To specify how many jobs to run,
|
||||
append `--jobs=n` (default n=4).
|
||||
|
||||
If you want to create a basic coverage report for the RPC test suite, append `--coverage`.
|
||||
|
||||
Possible options, which apply to each individual test run:
|
||||
|
||||
```
|
||||
-h, --help show this help message and exit
|
||||
--nocleanup Leave zcashds and test.* datadir on exit or error
|
||||
--noshutdown Don't stop zcashds after the test execution
|
||||
--srcdir=SRCDIR Source directory containing zcashd/zcash-cli
|
||||
(default: ../../src)
|
||||
--tmpdir=TMPDIR Root directory for datadirs
|
||||
--tracerpc Print out all RPC calls as they are made
|
||||
--coveragedir=COVERAGEDIR
|
||||
Write tested RPC commands into this directory
|
||||
```
|
||||
|
||||
If you set the environment variable `PYTHON_DEBUG=1` you will get some debug
|
||||
output (example: `PYTHON_DEBUG=1 qa/pull-tester/rpc-tests.py wallet`).
|
||||
|
||||
A 200-block -regtest blockchain and wallets for four nodes
|
||||
is created the first time a regression test is run and
|
||||
is stored in the cache/ directory. Each node has the miner
|
||||
subsidy from 25 mature blocks (25*10=250 ZEC) in its wallet.
|
||||
|
||||
After the first run, the cache/ blockchain and wallets are
|
||||
copied into a temporary directory and used as the initial
|
||||
test state.
|
||||
|
||||
If you get into a bad state, you should be able
|
||||
to recover with:
|
||||
|
||||
```bash
|
||||
rm -rf cache
|
||||
killall zcashd
|
||||
```
|
||||
|
||||
Writing tests
|
||||
=============
|
||||
You are encouraged to write tests for new or existing features.
|
||||
Further information about the test framework and individual RPC
|
||||
tests is found in [qa/rpc-tests](/qa/rpc-tests).
|
|
@ -0,0 +1,428 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
"""
|
||||
rpc-tests.py - 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.
|
||||
|
||||
RPC tests are disabled on Windows by default. Use --force to run them anyway.
|
||||
|
||||
For a description of arguments recognized by test scripts, see
|
||||
`qa/pull-tester/test_framework/test_framework.py:BitcoinTestFramework.main`.
|
||||
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import configparser
|
||||
import os
|
||||
import time
|
||||
import shutil
|
||||
import sys
|
||||
import subprocess
|
||||
import tempfile
|
||||
import re
|
||||
|
||||
SERIAL_SCRIPTS = [
|
||||
# These tests involve enough shielded spends (consuming all CPU
|
||||
# cores) that we can't run them in parallel.
|
||||
'mergetoaddress_sapling.py',
|
||||
'mergetoaddress_sprout.py',
|
||||
'wallet_shieldingcoinbase.py',
|
||||
]
|
||||
|
||||
BASE_SCRIPTS= [
|
||||
# Scripts that are run by the travis build process
|
||||
# Longest test should go first, to favor running tests in parallel
|
||||
# vv Tests less than 5m vv
|
||||
'wallet.py',
|
||||
'wallet_shieldcoinbase_sprout.py',
|
||||
'sprout_sapling_migration.py',
|
||||
'remove_sprout_shielding.py',
|
||||
'zcjoinsplitdoublespend.py',
|
||||
# vv Tests less than 2m vv
|
||||
'zcjoinsplit.py',
|
||||
'mergetoaddress_mixednotes.py',
|
||||
'wallet_shieldcoinbase_sapling.py',
|
||||
'turnstile.py',
|
||||
'walletbackup.py',
|
||||
'zkey_import_export.py',
|
||||
'prioritisetransaction.py',
|
||||
'wallet_changeaddresses.py',
|
||||
'wallet_listreceived.py',
|
||||
'mempool_tx_expiry.py',
|
||||
'finalsaplingroot.py',
|
||||
'wallet_overwintertx.py',
|
||||
'wallet_persistence.py',
|
||||
'wallet_listnotes.py',
|
||||
# vv Tests less than 60s vv
|
||||
'fundrawtransaction.py',
|
||||
'reorg_limit.py',
|
||||
'mempool_limit.py',
|
||||
'p2p-fullblocktest.py',
|
||||
'paymentdisclosure.py',
|
||||
# vv Tests less than 30s vv
|
||||
'wallet_1941.py',
|
||||
'wallet_addresses.py',
|
||||
'wallet_anchorfork.py',
|
||||
'wallet_changeindicator.py',
|
||||
'wallet_import_export.py',
|
||||
'wallet_nullifiers.py',
|
||||
'wallet_sapling.py',
|
||||
'wallet_sendmany_any_taddr.py',
|
||||
'wallet_treestate.py',
|
||||
'listtransactions.py',
|
||||
'mempool_resurrect_test.py',
|
||||
'txn_doublespend.py',
|
||||
'txn_doublespend.py --mineblock',
|
||||
'getchaintips.py',
|
||||
'rawtransactions.py',
|
||||
'getrawtransaction_insight.py',
|
||||
'rest.py',
|
||||
'mempool_spendcoinbase.py',
|
||||
'mempool_reorg.py',
|
||||
'mempool_nu_activation.py',
|
||||
'httpbasics.py',
|
||||
'multi_rpc.py',
|
||||
'zapwallettxes.py',
|
||||
'proxy_test.py',
|
||||
'merkle_blocks.py',
|
||||
'signrawtransactions.py',
|
||||
'signrawtransaction_offline.py',
|
||||
'key_import_export.py',
|
||||
'nodehandling.py',
|
||||
'reindex.py',
|
||||
'addressindex.py',
|
||||
'spentindex.py',
|
||||
'timestampindex.py',
|
||||
'decodescript.py',
|
||||
'blockchain.py',
|
||||
'disablewallet.py',
|
||||
'keypool.py',
|
||||
'getblocktemplate.py',
|
||||
'bip65-cltv-p2p.py',
|
||||
'bipdersig-p2p.py',
|
||||
'p2p_nu_peer_management.py',
|
||||
'rewind_index.py',
|
||||
'p2p_txexpiry_dos.py',
|
||||
'p2p_txexpiringsoon.py',
|
||||
'p2p_node_bloom.py',
|
||||
'regtest_signrawtransaction.py',
|
||||
'shorter_block_times.py',
|
||||
'mining_shielded_coinbase.py',
|
||||
'coinbase_funding_streams.py',
|
||||
'framework.py',
|
||||
'sapling_rewind_check.py',
|
||||
'feature_zip221.py',
|
||||
'upgrade_golden.py',
|
||||
'post_heartwood_rollback.py',
|
||||
'feature_logging.py',
|
||||
'feature_walletfile.py',
|
||||
]
|
||||
|
||||
ZMQ_SCRIPTS = [
|
||||
# ZMQ test can only be run if bitcoin was built with zmq-enabled.
|
||||
# call rpc_tests.py with -nozmq to explicitly exclude these tests.
|
||||
"zmq_test.py"]
|
||||
|
||||
EXTENDED_SCRIPTS = [
|
||||
# These tests are not run by the travis build process.
|
||||
# Longest test should go first, to favor running tests in parallel
|
||||
'pruning.py',
|
||||
# vv Tests less than 20m vv
|
||||
'smartfees.py',
|
||||
# vv Tests less than 5m vv
|
||||
# vv Tests less than 2m vv
|
||||
'getblocktemplate_longpoll.py',
|
||||
# vv Tests less than 60s vv
|
||||
'rpcbind_test.py',
|
||||
# vv Tests less than 30s vv
|
||||
'getblocktemplate_proposals.py',
|
||||
'forknotify.py',
|
||||
'hardforkdetection.py',
|
||||
'invalidateblock.py',
|
||||
'receivedby.py',
|
||||
'maxblocksinflight.py',
|
||||
'invalidblockrequest.py',
|
||||
# 'forknotify.py',
|
||||
'p2p-acceptblock.py',
|
||||
'wallet_db_flush.py',
|
||||
]
|
||||
|
||||
ALL_SCRIPTS = SERIAL_SCRIPTS + BASE_SCRIPTS + ZMQ_SCRIPTS + EXTENDED_SCRIPTS
|
||||
|
||||
def main():
|
||||
# Parse arguments and pass through unrecognised args
|
||||
parser = argparse.ArgumentParser(add_help=False,
|
||||
usage='%(prog)s [rpc-test.py options] [script options] [scripts]',
|
||||
description=__doc__,
|
||||
epilog='''
|
||||
Help text and arguments for individual test script:''',
|
||||
formatter_class=argparse.RawTextHelpFormatter)
|
||||
parser.add_argument('--coverage', action='store_true', help='generate a basic coverage report for the RPC interface')
|
||||
parser.add_argument('--exclude', '-x', help='specify a comma-seperated-list of scripts to exclude. Do not include the .py extension in the name.')
|
||||
parser.add_argument('--extended', action='store_true', help='run the extended test suite in addition to the basic tests')
|
||||
parser.add_argument('--force', '-f', action='store_true', help='run tests even on platforms where they are disabled by default (e.g. windows).')
|
||||
parser.add_argument('--help', '-h', '-?', action='store_true', help='print help text and exit')
|
||||
parser.add_argument('--jobs', '-j', type=int, default=4, help='how many test scripts to run in parallel. Default=4.')
|
||||
parser.add_argument('--nozmq', action='store_true', help='do not run the zmq tests')
|
||||
args, unknown_args = parser.parse_known_args()
|
||||
|
||||
# Create a set to store arguments and create the passon string
|
||||
tests = set(arg for arg in unknown_args if arg[:2] != "--")
|
||||
passon_args = [arg for arg in unknown_args if arg[:2] == "--"]
|
||||
|
||||
# Read config generated by configure.
|
||||
config = configparser.ConfigParser()
|
||||
config.read_file(open(os.path.dirname(__file__) + "/tests_config.ini"))
|
||||
|
||||
enable_wallet = config["components"].getboolean("ENABLE_WALLET")
|
||||
enable_utils = config["components"].getboolean("ENABLE_UTILS")
|
||||
enable_bitcoind = config["components"].getboolean("ENABLE_BITCOIND")
|
||||
enable_zmq = config["components"].getboolean("ENABLE_ZMQ") and not args.nozmq
|
||||
|
||||
if config["environment"]["EXEEXT"] == ".exe" and not args.force:
|
||||
# https://github.com/bitcoin/bitcoin/commit/d52802551752140cf41f0d9a225a43e84404d3e9
|
||||
# https://github.com/bitcoin/bitcoin/pull/5677#issuecomment-136646964
|
||||
print("Tests currently disabled on Windows by default. Use --force option to enable")
|
||||
sys.exit(0)
|
||||
|
||||
if not (enable_wallet and enable_utils and enable_bitcoind):
|
||||
print("No rpc tests to run. Wallet, utils, and bitcoind must all be enabled")
|
||||
print("Rerun `configure` with -enable-wallet, -with-utils and -with-daemon and rerun make")
|
||||
sys.exit(0)
|
||||
|
||||
# python3-zmq may not be installed. Handle this gracefully and with some helpful info
|
||||
if enable_zmq:
|
||||
try:
|
||||
import zmq
|
||||
zmq # Silences pyflakes
|
||||
except ImportError:
|
||||
print("ERROR: \"import zmq\" failed. Use -nozmq to run without the ZMQ tests."
|
||||
"To run zmq tests, see dependency info in /qa/README.md.")
|
||||
raise
|
||||
|
||||
# Build list of tests
|
||||
if tests:
|
||||
# Individual tests have been specified. Run specified tests that exist
|
||||
# in the ALL_SCRIPTS list. Accept the name with or without .py extension.
|
||||
test_list = [t for t in ALL_SCRIPTS if
|
||||
(t in tests or re.sub(".py$", "", t) in tests)]
|
||||
else:
|
||||
# No individual tests have been specified. Run base tests, and
|
||||
# optionally ZMQ tests and extended tests.
|
||||
test_list = SERIAL_SCRIPTS + BASE_SCRIPTS
|
||||
if enable_zmq:
|
||||
test_list += ZMQ_SCRIPTS
|
||||
if args.extended:
|
||||
test_list += EXTENDED_SCRIPTS
|
||||
# TODO: BASE_SCRIPTS and EXTENDED_SCRIPTS are sorted by runtime
|
||||
# (for parallel running efficiency). This combined list will is no
|
||||
# longer sorted.
|
||||
|
||||
# Remove the test cases that the user has explicitly asked to exclude.
|
||||
if args.exclude:
|
||||
for exclude_test in args.exclude.split(','):
|
||||
if exclude_test + ".py" in test_list:
|
||||
test_list.remove(exclude_test + ".py")
|
||||
|
||||
if not test_list:
|
||||
print("No valid test scripts specified. Check that your test is in one "
|
||||
"of the test lists in rpc-tests.py, or run rpc-tests.py with no arguments to run all tests")
|
||||
sys.exit(0)
|
||||
|
||||
if args.help:
|
||||
# Print help for rpc-tests.py, then print help of the first script and exit.
|
||||
parser.print_help()
|
||||
subprocess.check_call((config["environment"]["SRCDIR"] + '/qa/rpc-tests/' + test_list[0]).split() + ['-h'])
|
||||
sys.exit(0)
|
||||
|
||||
run_tests(test_list, config["environment"]["SRCDIR"], config["environment"]["BUILDDIR"], config["environment"]["EXEEXT"], args.jobs, args.coverage, passon_args)
|
||||
|
||||
def run_tests(test_list, src_dir, build_dir, exeext, jobs=1, enable_coverage=False, args=[]):
|
||||
BOLD = ("","")
|
||||
if os.name == 'posix':
|
||||
# primitive formatting on supported
|
||||
# terminal via ANSI escape sequences:
|
||||
BOLD = ('\033[0m', '\033[1m')
|
||||
|
||||
#Set env vars
|
||||
if "BITCOIND" not in os.environ:
|
||||
os.environ["BITCOIND"] = build_dir + '/src/zcashd' + exeext
|
||||
|
||||
tests_dir = src_dir + '/qa/rpc-tests/'
|
||||
|
||||
flags = ["--srcdir={}/src".format(build_dir)] + args
|
||||
flags.append("--cachedir=%s/qa/cache" % build_dir)
|
||||
|
||||
if enable_coverage:
|
||||
coverage = RPCCoverage()
|
||||
flags.append(coverage.flag)
|
||||
print("Initializing coverage directory at %s\n" % coverage.dir)
|
||||
else:
|
||||
coverage = None
|
||||
|
||||
if len(test_list) > 1 and jobs > 1:
|
||||
# Populate cache
|
||||
subprocess.check_output([tests_dir + 'create_cache.py'] + flags)
|
||||
|
||||
#Run Tests
|
||||
all_passed = True
|
||||
time_sum = 0
|
||||
time0 = time.time()
|
||||
|
||||
job_queue = RPCTestHandler(jobs, tests_dir, test_list, flags)
|
||||
|
||||
max_len_name = len(max(test_list, key=len))
|
||||
results = BOLD[1] + "%s | %s | %s\n\n" % ("TEST".ljust(max_len_name), "PASSED", "DURATION") + BOLD[0]
|
||||
for _ in range(len(test_list)):
|
||||
(name, stdout, stderr, passed, duration) = job_queue.get_next()
|
||||
all_passed = all_passed and passed
|
||||
time_sum += duration
|
||||
|
||||
print('\n' + BOLD[1] + name + BOLD[0] + ":")
|
||||
print('' if passed else stdout + '\n', end='')
|
||||
print('' if stderr == '' else 'stderr:\n' + stderr + '\n', end='')
|
||||
print("Pass: %s%s%s, Duration: %s s\n" % (BOLD[1], passed, BOLD[0], duration))
|
||||
|
||||
results += "%s | %s | %s s\n" % (name.ljust(max_len_name), str(passed).ljust(6), duration)
|
||||
|
||||
results += BOLD[1] + "\n%s | %s | %s s (accumulated)" % ("ALL".ljust(max_len_name), str(all_passed).ljust(6), time_sum) + BOLD[0]
|
||||
print(results)
|
||||
print("\nRuntime: %s s" % (int(time.time() - time0)))
|
||||
|
||||
if coverage:
|
||||
coverage.report_rpc_coverage()
|
||||
|
||||
print("Cleaning up coverage data")
|
||||
coverage.cleanup()
|
||||
|
||||
sys.exit(not all_passed)
|
||||
|
||||
class RPCTestHandler:
|
||||
"""
|
||||
Trigger the testscrips passed in via the list.
|
||||
"""
|
||||
|
||||
def __init__(self, num_tests_parallel, tests_dir, test_list=None, flags=None):
|
||||
assert(num_tests_parallel >= 1)
|
||||
self.num_jobs = num_tests_parallel
|
||||
self.tests_dir = tests_dir
|
||||
self.test_list = test_list
|
||||
self.flags = flags
|
||||
self.num_running = 0
|
||||
# In case there is a graveyard of zombie bitcoinds, we can apply a
|
||||
# pseudorandom offset to hopefully jump over them.
|
||||
# (625 is PORT_RANGE/MAX_NODES)
|
||||
self.portseed_offset = int(time.time() * 1000) % 625
|
||||
self.jobs = []
|
||||
|
||||
def get_next(self):
|
||||
while self.num_running < self.num_jobs and self.test_list:
|
||||
# Add tests
|
||||
self.num_running += 1
|
||||
t = self.test_list.pop(0)
|
||||
port_seed = ["--portseed={}".format(len(self.test_list) + self.portseed_offset)]
|
||||
log_stdout = tempfile.SpooledTemporaryFile(max_size=2**16)
|
||||
log_stderr = tempfile.SpooledTemporaryFile(max_size=2**16)
|
||||
self.jobs.append((t,
|
||||
time.time(),
|
||||
subprocess.Popen((self.tests_dir + t).split() + self.flags + port_seed,
|
||||
universal_newlines=True,
|
||||
stdout=log_stdout,
|
||||
stderr=log_stderr),
|
||||
log_stdout,
|
||||
log_stderr))
|
||||
# Run serial scripts on their own. We always run these first,
|
||||
# so we won't have added any other jobs yet.
|
||||
if t in SERIAL_SCRIPTS:
|
||||
break
|
||||
if not self.jobs:
|
||||
raise IndexError('pop from empty list')
|
||||
while True:
|
||||
# Return first proc that finishes
|
||||
time.sleep(.5)
|
||||
for j in self.jobs:
|
||||
(name, time0, proc, log_out, log_err) = j
|
||||
if proc.poll() is not None:
|
||||
log_out.seek(0), log_err.seek(0)
|
||||
[stdout, stderr] = [l.read().decode('utf-8') for l in (log_out, log_err)]
|
||||
log_out.close(), log_err.close()
|
||||
passed = stderr == "" and proc.returncode == 0
|
||||
self.num_running -= 1
|
||||
self.jobs.remove(j)
|
||||
return name, stdout, stderr, passed, int(time.time() - time0)
|
||||
print('.', end='', flush=True)
|
||||
|
||||
|
||||
class RPCCoverage(object):
|
||||
"""
|
||||
Coverage reporting utilities for pull-tester.
|
||||
|
||||
Coverage calculation works by having each test script subprocess write
|
||||
coverage files into a particular directory. These files contain the RPC
|
||||
commands invoked during testing, as well as a complete listing of RPC
|
||||
commands per `bitcoin-cli help` (`rpc_interface.txt`).
|
||||
|
||||
After all tests complete, the commands run are combined and diff'd against
|
||||
the complete list to calculate uncovered RPC commands.
|
||||
|
||||
See also: qa/rpc-tests/test_framework/coverage.py
|
||||
|
||||
"""
|
||||
def __init__(self):
|
||||
self.dir = tempfile.mkdtemp(prefix="coverage")
|
||||
self.flag = '--coveragedir=%s' % self.dir
|
||||
|
||||
def report_rpc_coverage(self):
|
||||
"""
|
||||
Print out RPC commands that were unexercised by tests.
|
||||
|
||||
"""
|
||||
uncovered = self._get_uncovered_rpc_commands()
|
||||
|
||||
if uncovered:
|
||||
print("Uncovered RPC commands:")
|
||||
print("".join((" - %s\n" % i) for i in sorted(uncovered)))
|
||||
else:
|
||||
print("All RPC commands covered.")
|
||||
|
||||
def cleanup(self):
|
||||
return shutil.rmtree(self.dir)
|
||||
|
||||
def _get_uncovered_rpc_commands(self):
|
||||
"""
|
||||
Return a set of currently untested RPC commands.
|
||||
|
||||
"""
|
||||
# This is shared from `qa/rpc-tests/test-framework/coverage.py`
|
||||
reference_filename = 'rpc_interface.txt'
|
||||
coverage_file_prefix = 'coverage.'
|
||||
|
||||
coverage_ref_filename = os.path.join(self.dir, reference_filename)
|
||||
coverage_filenames = set()
|
||||
all_cmds = set()
|
||||
covered_cmds = set()
|
||||
|
||||
if not os.path.isfile(coverage_ref_filename):
|
||||
raise RuntimeError("No coverage reference found")
|
||||
|
||||
with open(coverage_ref_filename, 'r') as f:
|
||||
all_cmds.update([i.strip() for i in f.readlines()])
|
||||
|
||||
for root, dirs, files in os.walk(self.dir):
|
||||
for filename in files:
|
||||
if filename.startswith(coverage_file_prefix):
|
||||
coverage_filenames.add(os.path.join(root, filename))
|
||||
|
||||
for filename in coverage_filenames:
|
||||
with open(filename, 'r') as f:
|
||||
covered_cmds.update([i.strip() for i in f.readlines()])
|
||||
|
||||
return all_cmds - covered_cmds
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,179 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -e -o pipefail
|
||||
|
||||
CURDIR=$(cd $(dirname "$0"); pwd)
|
||||
# Get BUILDDIR and REAL_BITCOIND
|
||||
. "${CURDIR}/tests-config.sh"
|
||||
|
||||
export BITCOIND=${REAL_BITCOIND}
|
||||
export BITCOINCLI=${REAL_BITCOINCLI}
|
||||
|
||||
#Run the tests
|
||||
|
||||
testScripts=(
|
||||
'paymentdisclosure.py'
|
||||
'prioritisetransaction.py'
|
||||
'wallet_treestate.py'
|
||||
'wallet_anchorfork.py'
|
||||
'wallet_changeaddresses.py'
|
||||
'wallet_changeindicator.py'
|
||||
'wallet_import_export.py'
|
||||
'wallet_sendmany_any_taddr.py'
|
||||
'wallet_shieldingcoinbase.py'
|
||||
'wallet_shieldcoinbase_sprout.py'
|
||||
'wallet_shieldcoinbase_sapling.py'
|
||||
'wallet_listreceived.py'
|
||||
'wallet.py'
|
||||
'wallet_overwintertx.py'
|
||||
'wallet_persistence.py'
|
||||
'wallet_nullifiers.py'
|
||||
'wallet_1941.py'
|
||||
'wallet_addresses.py'
|
||||
'wallet_sapling.py'
|
||||
'wallet_listnotes.py'
|
||||
'mergetoaddress_sprout.py'
|
||||
'mergetoaddress_sapling.py'
|
||||
'mergetoaddress_mixednotes.py'
|
||||
'listtransactions.py'
|
||||
'mempool_resurrect_test.py'
|
||||
'txn_doublespend.py'
|
||||
'txn_doublespend.py --mineblock'
|
||||
'getchaintips.py'
|
||||
'rawtransactions.py'
|
||||
'getrawtransaction_insight.py'
|
||||
'rest.py'
|
||||
'mempool_limit.py'
|
||||
'mempool_spendcoinbase.py'
|
||||
'mempool_reorg.py'
|
||||
'mempool_nu_activation.py'
|
||||
'mempool_tx_expiry.py'
|
||||
'httpbasics.py'
|
||||
'multi_rpc.py'
|
||||
'zapwallettxes.py'
|
||||
'proxy_test.py'
|
||||
'merkle_blocks.py'
|
||||
'fundrawtransaction.py'
|
||||
'signrawtransactions.py'
|
||||
'signrawtransaction_offline.py'
|
||||
'walletbackup.py'
|
||||
'key_import_export.py'
|
||||
'nodehandling.py'
|
||||
'reindex.py'
|
||||
'addressindex.py'
|
||||
'spentindex.py'
|
||||
'timestampindex.py'
|
||||
'decodescript.py'
|
||||
'blockchain.py'
|
||||
'disablewallet.py'
|
||||
'zcjoinsplit.py'
|
||||
'zcjoinsplitdoublespend.py'
|
||||
'zkey_import_export.py'
|
||||
'reorg_limit.py'
|
||||
'getblocktemplate.py'
|
||||
'bip65-cltv-p2p.py'
|
||||
'bipdersig-p2p.py'
|
||||
'p2p_nu_peer_management.py'
|
||||
'rewind_index.py'
|
||||
'p2p_txexpiry_dos.py'
|
||||
'p2p_txexpiringsoon.py'
|
||||
'p2p_node_bloom.py'
|
||||
'regtest_signrawtransaction.py'
|
||||
'finalsaplingroot.py'
|
||||
'shorter_block_times.py'
|
||||
'sprout_sapling_migration.py'
|
||||
'turnstile.py'
|
||||
'mining_shielded_coinbase.py'
|
||||
'coinbase_funding_streams.py'
|
||||
'framework.py'
|
||||
'sapling_rewind_check.py'
|
||||
'feature_zip221.py'
|
||||
'upgrade_golden.py'
|
||||
'post_heartwood_rollback.py'
|
||||
'feature_logging.py'
|
||||
'remove_sprout_shielding.py'
|
||||
'feature_walletfile.py'
|
||||
);
|
||||
testScriptsExt=(
|
||||
'getblocktemplate_longpoll.py'
|
||||
'getblocktemplate_proposals.py'
|
||||
'pruning.py'
|
||||
'forknotify.py'
|
||||
'hardforkdetection.py'
|
||||
'invalidateblock.py'
|
||||
'keypool.py'
|
||||
'receivedby.py'
|
||||
'rpcbind_test.py'
|
||||
# 'script_test.py'
|
||||
'smartfees.py'
|
||||
'maxblocksinflight.py'
|
||||
'invalidblockrequest.py'
|
||||
# 'forknotify.py'
|
||||
'p2p-acceptblock.py'
|
||||
'wallet_db_flush.py'
|
||||
);
|
||||
|
||||
if [ "x$ENABLE_ZMQ" = "x1" ]; then
|
||||
testScripts+=('zmq_test.py')
|
||||
fi
|
||||
|
||||
extArg="-extended"
|
||||
passOn=${@#$extArg}
|
||||
|
||||
successCount=0
|
||||
declare -a failures
|
||||
|
||||
function runTestScript
|
||||
{
|
||||
local testName="$1"
|
||||
shift
|
||||
|
||||
echo -e "=== Running testscript ${testName} ==="
|
||||
|
||||
local startTime=$(date +%s)
|
||||
if eval "$@"
|
||||
then
|
||||
successCount=$(expr $successCount + 1)
|
||||
echo "--- Success: ${testName} ($(($(date +%s) - $startTime))s) ---"
|
||||
else
|
||||
failures[${#failures[@]}]="$testName"
|
||||
echo "!!! FAIL: ${testName} ($(($(date +%s) - $startTime))s) !!!"
|
||||
fi
|
||||
|
||||
echo
|
||||
}
|
||||
|
||||
if [ "x${ENABLE_BITCOIND}${ENABLE_UTILS}${ENABLE_WALLET}" = "x111" ]; then
|
||||
for (( i = 0; i < ${#testScripts[@]}; i++ ))
|
||||
do
|
||||
if [ -z "$1" ] || [ "${1:0:1}" == "-" ] || [ "$1" == "${testScripts[$i]}" ] || [ "$1.py" == "${testScripts[$i]}" ]
|
||||
then
|
||||
runTestScript \
|
||||
"${testScripts[$i]}" \
|
||||
"${BUILDDIR}/qa/rpc-tests/${testScripts[$i]}" \
|
||||
--srcdir "${BUILDDIR}/src" ${passOn}
|
||||
fi
|
||||
done
|
||||
for (( i = 0; i < ${#testScriptsExt[@]}; i++ ))
|
||||
do
|
||||
if [ "$1" == $extArg ] || [ "$1" == "${testScriptsExt[$i]}" ] || [ "$1.py" == "${testScriptsExt[$i]}" ]
|
||||
then
|
||||
runTestScript \
|
||||
"${testScriptsExt[$i]}" \
|
||||
"${BUILDDIR}/qa/rpc-tests/${testScriptsExt[$i]}" \
|
||||
--srcdir "${BUILDDIR}/src" ${passOn}
|
||||
fi
|
||||
done
|
||||
|
||||
echo -e "\n\nTests completed: $(expr $successCount + ${#failures[@]})"
|
||||
echo "successes $successCount; failures: ${#failures[@]}"
|
||||
|
||||
if [ ${#failures[@]} -gt 0 ]
|
||||
then
|
||||
echo -e "\nFailing tests: ${failures[*]}"
|
||||
exit 1
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
else
|
||||
echo "No rpc tests to run. Wallet, utils, and bitcoind must all be enabled"
|
||||
fi
|
|
@ -1,38 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Copyright (c) 2013-2014 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
#
|
||||
ZCASH_LOAD_TIMEOUT=500
|
||||
DATADIR="@abs_top_builddir@/.zcash"
|
||||
rm -rf "$DATADIR"
|
||||
mkdir -p "$DATADIR"/regtest
|
||||
touch "$DATADIR/zcash.conf"
|
||||
touch "$DATADIR/regtest/debug.log"
|
||||
tail -q -n 1 -F "$DATADIR/regtest/debug.log" | grep -m 1 -q "Done loading" &
|
||||
WAITER=$!
|
||||
PORT=`expr 10000 + $$ % 55536`
|
||||
"@abs_top_builddir@/src/zcashd@EXEEXT@" -connect=0.0.0.0 -datadir="$DATADIR" -rpcuser=user -rpcpassword=pass -listen -keypool=3 -debug -debug=net -logtimestamps -checkmempool=0 -relaypriority=0 -port=$PORT -whitelist=127.0.0.1 -regtest -rpcport=`expr $PORT + 1` &
|
||||
BITCOIND=$!
|
||||
|
||||
#Install a watchdog.
|
||||
(sleep "$ZCASH_LOAD_TIMEOUT" && kill -0 $WAITER 2>/dev/null && kill -9 $BITCOIND $$)&
|
||||
wait $WAITER
|
||||
|
||||
if [ -n "$TIMEOUT" ]; then
|
||||
timeout "$TIMEOUT"s "$@" $PORT
|
||||
RETURN=$?
|
||||
else
|
||||
"$@" $PORT
|
||||
RETURN=$?
|
||||
fi
|
||||
|
||||
(sleep "$ZCASH_LOAD_TIMEOUT" && kill -0 $BITCOIND 2>/dev/null && kill -9 $BITCOIND $$)&
|
||||
kill $BITCOIND && wait $BITCOIND
|
||||
|
||||
# timeout returns 124 on timeout, otherwise the return value of the child
|
||||
|
||||
# If $RETURN is not 0, the test failed. Dump the tail of the debug log.
|
||||
if [ $RETURN -ne 0 ]; then tail -n 200 $DATADIR/regtest/debug.log; fi
|
||||
|
||||
exit $RETURN
|
|
@ -1,17 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Copyright (c) 2013-2014 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
BUILDDIR="@abs_top_builddir@"
|
||||
EXEEXT="@EXEEXT@"
|
||||
|
||||
# These will turn into comments if they were disabled when configuring.
|
||||
@ENABLE_WALLET_TRUE@ENABLE_WALLET=1
|
||||
@BUILD_BITCOIN_UTILS_TRUE@ENABLE_UTILS=1
|
||||
@BUILD_BITCOIND_TRUE@ENABLE_BITCOIND=1
|
||||
@ENABLE_ZMQ_TRUE@ENABLE_ZMQ=1
|
||||
|
||||
REAL_BITCOIND="$BUILDDIR/src/zcashd${EXEEXT}"
|
||||
REAL_BITCOINCLI="$BUILDDIR/src/zcash-cli${EXEEXT}"
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
# Copyright (c) 2013-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
# These environment variables are set by the build process and read by
|
||||
# rpc-tests.py
|
||||
|
||||
[environment]
|
||||
SRCDIR=@abs_top_srcdir@
|
||||
BUILDDIR=@abs_top_builddir@
|
||||
EXEEXT=@EXEEXT@
|
||||
|
||||
[components]
|
||||
# Which components are enabled. These are commented out by `configure` if they were disabled when running config.
|
||||
@ENABLE_WALLET_TRUE@ENABLE_WALLET=true
|
||||
@BUILD_BITCOIN_UTILS_TRUE@ENABLE_UTILS=true
|
||||
@BUILD_BITCOIND_TRUE@ENABLE_BITCOIND=true
|
||||
@ENABLE_ZMQ_TRUE@ENABLE_ZMQ=true
|
|
@ -1,5 +1,5 @@
|
|||
Regression tests of RPC interface
|
||||
=================================
|
||||
Regression tests
|
||||
================
|
||||
|
||||
### [test_framework/test_framework.py](test_framework/test_framework.py)
|
||||
Base class for RPC regression tests.
|
||||
|
@ -7,40 +7,102 @@ Base class for RPC regression tests.
|
|||
### [test_framework/util.py](test_framework/util.py)
|
||||
Generally useful functions.
|
||||
|
||||
Notes
|
||||
=====
|
||||
### [test_framework/mininode.py](test_framework/mininode.py)
|
||||
Basic code to support p2p connectivity to a bitcoind.
|
||||
|
||||
You can run a single test by calling `qa/pull-tester/rpc-tests.sh <testname>`.
|
||||
### [test_framework/comptool.py](test_framework/comptool.py)
|
||||
Framework for comparison-tool style, p2p tests.
|
||||
|
||||
Run all possible tests with `qa/pull-tester/rpc-tests.sh -extended`.
|
||||
### [test_framework/script.py](test_framework/script.py)
|
||||
Utilities for manipulating transaction scripts (originally from python-bitcoinlib)
|
||||
|
||||
Possible options:
|
||||
### [test_framework/blockstore.py](test_framework/blockstore.py)
|
||||
Implements disk-backed block and tx storage.
|
||||
|
||||
```
|
||||
-h, --help show this help message and exit
|
||||
--nocleanup Leave zcashds and test.* datadir on exit or error
|
||||
--noshutdown Don't stop bitcoinds after the test execution
|
||||
--srcdir=SRCDIR Source directory containing zcashd/zcash-cli (default:
|
||||
../../src)
|
||||
--tmpdir=TMPDIR Root directory for datadirs
|
||||
--tracerpc Print out all RPC calls as they are made
|
||||
```
|
||||
### [test_framework/key.py](test_framework/key.py)
|
||||
Wrapper around OpenSSL EC_Key (originally from python-bitcoinlib)
|
||||
|
||||
If you set the environment variable `PYTHON_DEBUG=1` you will get some debug output (example: `PYTHON_DEBUG=1 qa/pull-tester/rpc-tests.sh wallet`).
|
||||
### [test_framework/bignum.py](test_framework/bignum.py)
|
||||
Helpers for script.py
|
||||
|
||||
A 200-block -regtest blockchain and wallets for four nodes
|
||||
is created the first time a regression test is run and
|
||||
is stored in the cache/ directory. Each node has the miner
|
||||
subsidy from 25 mature blocks (25*10=250 ZEC) in its wallet.
|
||||
### [test_framework/blocktools.py](test_framework/blocktools.py)
|
||||
Helper functions for creating blocks and transactions.
|
||||
|
||||
After the first run, the cache/ blockchain and wallets are
|
||||
copied into a temporary directory and used as the initial
|
||||
test state.
|
||||
P2P test design notes
|
||||
---------------------
|
||||
|
||||
If you get into a bad state, you should be able
|
||||
to recover with:
|
||||
## Mininode
|
||||
|
||||
* ```mininode.py``` contains all the definitions for objects that pass
|
||||
over the network (```CBlock```, ```CTransaction```, etc, along with the network-level
|
||||
wrappers for them, ```msg_block```, ```msg_tx```, etc).
|
||||
|
||||
* P2P tests have two threads. One thread handles all network communication
|
||||
with the bitcoind(s) being tested (using python's asyncore package); the other
|
||||
implements the test logic.
|
||||
|
||||
* ```NodeConn``` is the class used to connect to a bitcoind. If you implement
|
||||
a callback class that derives from ```NodeConnCB``` and pass that to the
|
||||
```NodeConn``` object, your code will receive the appropriate callbacks when
|
||||
events of interest arrive. NOTE: be sure to call
|
||||
```self.create_callback_map()``` in your derived classes' ```__init__```
|
||||
function, so that the correct mappings are set up between p2p messages and your
|
||||
callback functions.
|
||||
|
||||
* You can pass the same handler to multiple ```NodeConn```'s if you like, or pass
|
||||
different ones to each -- whatever makes the most sense for your test.
|
||||
|
||||
* Call ```NetworkThread.start()``` after all ```NodeConn``` objects are created to
|
||||
start the networking thread. (Continue with the test logic in your existing
|
||||
thread.)
|
||||
|
||||
* RPC calls are available in p2p tests.
|
||||
|
||||
* Can be used to write free-form tests, where specific p2p-protocol behavior
|
||||
is tested. Examples: ```p2p-accept-block.py```, ```maxblocksinflight.py```.
|
||||
|
||||
## Comptool
|
||||
|
||||
* Testing framework for writing tests that compare the block/tx acceptance
|
||||
behavior of a bitcoind against 1 or more other bitcoind instances, or against
|
||||
known outcomes, or both.
|
||||
|
||||
* Set the ```num_nodes``` variable (defined in ```ComparisonTestFramework```) to start up
|
||||
1 or more nodes. If using 1 node, then ```--testbinary``` can be used as a command line
|
||||
option to change the bitcoind binary used by the test. If using 2 or more nodes,
|
||||
then ```--refbinary``` can be optionally used to change the bitcoind that will be used
|
||||
on nodes 2 and up.
|
||||
|
||||
* Implement a (generator) function called ```get_tests()``` which yields ```TestInstance```s.
|
||||
Each ```TestInstance``` consists of:
|
||||
- a list of ```[object, outcome, hash]``` entries
|
||||
* ```object``` is a ```CBlock```, ```CTransaction```, or
|
||||
```CBlockHeader```. ```CBlock```'s and ```CTransaction```'s are tested for
|
||||
acceptance. ```CBlockHeader```s can be used so that the test runner can deliver
|
||||
complete headers-chains when requested from the bitcoind, to allow writing
|
||||
tests where blocks can be delivered out of order but still processed by
|
||||
headers-first bitcoind's.
|
||||
* ```outcome``` is ```True```, ```False```, or ```None```. If ```True```
|
||||
or ```False```, the tip is compared with the expected tip -- either the
|
||||
block passed in, or the hash specified as the optional 3rd entry. If
|
||||
```None``` is specified, then the test will compare all the bitcoind's
|
||||
being tested to see if they all agree on what the best tip is.
|
||||
* ```hash``` is the block hash of the tip to compare against. Optional to
|
||||
specify; if left out then the hash of the block passed in will be used as
|
||||
the expected tip. This allows for specifying an expected tip while testing
|
||||
the handling of either invalid blocks or blocks delivered out of order,
|
||||
which complete a longer chain.
|
||||
- ```sync_every_block```: ```True/False```. If ```False```, then all blocks
|
||||
are inv'ed together, and the test runner waits until the node receives the
|
||||
last one, and tests only the last block for tip acceptance using the
|
||||
outcome and specified tip. If ```True```, then each block is tested in
|
||||
sequence and synced (this is slower when processing many blocks).
|
||||
- ```sync_every_transaction```: ```True/False```. Analogous to
|
||||
```sync_every_block```, except if the outcome on the last tx is "None",
|
||||
then the contents of the entire mempool are compared across all bitcoind
|
||||
connections. If ```True``` or ```False```, then only the last tx's
|
||||
acceptance is tested against the given outcome.
|
||||
|
||||
* For examples of tests written in this framework, see
|
||||
```invalidblockrequest.py``` and ```p2p-fullblocktest.py```.
|
||||
|
||||
```bash
|
||||
rm -rf cache
|
||||
killall zcashd
|
||||
```
|
||||
|
|
|
@ -18,7 +18,6 @@ from test_framework.test_framework import BitcoinTestFramework
|
|||
|
||||
from test_framework.util import (
|
||||
assert_equal,
|
||||
initialize_chain_clean,
|
||||
start_nodes,
|
||||
stop_nodes,
|
||||
connect_nodes,
|
||||
|
@ -44,16 +43,17 @@ from binascii import hexlify, unhexlify
|
|||
|
||||
class AddressIndexTest(BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 4)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 4
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def setup_network(self):
|
||||
# -insightexplorer causes addressindex to be enabled (fAddressIndex = true)
|
||||
args_insight = ('-debug', '-txindex', '-experimentalfeatures', '-insightexplorer')
|
||||
# -lightwallet also causes addressindex to be enabled
|
||||
args_lightwallet = ('-debug', '-txindex', '-experimentalfeatures', '-lightwalletd')
|
||||
self.nodes = start_nodes(4, self.options.tmpdir, [args_insight] * 3 + [args_lightwallet])
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [args_insight] * 3 + [args_lightwallet])
|
||||
|
||||
connect_nodes(self.nodes[0], 1)
|
||||
connect_nodes(self.nodes[0], 2)
|
||||
|
@ -237,7 +237,7 @@ class AddressIndexTest(BitcoinTestFramework):
|
|||
|
||||
# Test DisconnectBlock() by invalidating the most recent mined block
|
||||
tip = self.nodes[1].getchaintips()[0]
|
||||
for i in range(3):
|
||||
for i in range(self.num_nodes):
|
||||
node = self.nodes[i]
|
||||
# the value 4 UTXO is no longer in our balance
|
||||
check_balance(i, addr1, (expected - 4) * COIN, expected * COIN)
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2015-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
#
|
||||
|
||||
from test_framework.test_framework import ComparisonTestFramework
|
||||
from test_framework.util import start_nodes
|
||||
|
@ -26,10 +25,11 @@ TODO: factor out common code from {bipdersig-p2p,bip65-cltv-p2p}.py.
|
|||
class BIP65Test(ComparisonTestFramework):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 1
|
||||
|
||||
def setup_network(self):
|
||||
self.nodes = start_nodes(1, self.options.tmpdir,
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
|
||||
extra_args=[['-debug', '-whitelist=127.0.0.1']],
|
||||
binary=[self.options.testbinary])
|
||||
self.is_network_split = False
|
||||
|
@ -63,6 +63,7 @@ class BIP65Test(ComparisonTestFramework):
|
|||
def get_tests(self):
|
||||
self.coinbase_blocks = self.nodes[0].generate(1)
|
||||
self.nodes[0].generate(100)
|
||||
height = 102 # height of the next block to build
|
||||
hashTip = self.nodes[0].getbestblockhash()
|
||||
hashFinalSaplingRoot = int("0x" + self.nodes[0].getblock(hashTip)['finalsaplingroot'] , 0)
|
||||
self.tip = int("0x" + hashTip , 0)
|
||||
|
@ -81,7 +82,7 @@ class BIP65Test(ComparisonTestFramework):
|
|||
self.block_time = gbt["mintime"] + 1
|
||||
self.block_bits = int("0x" + gbt["bits"], 0)
|
||||
|
||||
block = create_block(self.tip, create_coinbase(101),
|
||||
block = create_block(self.tip, create_coinbase(height),
|
||||
self.block_time, self.block_bits,
|
||||
hashFinalSaplingRoot)
|
||||
block.nVersion = 4
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2015-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
#
|
||||
|
||||
from test_framework.test_framework import ComparisonTestFramework
|
||||
from test_framework.util import start_nodes
|
||||
|
@ -11,7 +10,7 @@ from test_framework.blocktools import create_coinbase, create_block
|
|||
from test_framework.comptool import TestInstance, TestManager
|
||||
from test_framework.script import CScript
|
||||
from binascii import unhexlify
|
||||
import io
|
||||
from io import BytesIO
|
||||
|
||||
|
||||
'''
|
||||
|
@ -26,10 +25,11 @@ TODO: factor out common code from {bipdersig-p2p,bip65-cltv-p2p}.py.
|
|||
class BIP66Test(ComparisonTestFramework):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 1
|
||||
|
||||
def setup_network(self):
|
||||
self.nodes = start_nodes(1, self.options.tmpdir,
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
|
||||
extra_args=[['-debug', '-whitelist=127.0.0.1']],
|
||||
binary=[self.options.testbinary])
|
||||
self.is_network_split = False
|
||||
|
@ -47,7 +47,7 @@ class BIP66Test(ComparisonTestFramework):
|
|||
rawtx = node.createrawtransaction(inputs, outputs)
|
||||
signresult = node.signrawtransaction(rawtx)
|
||||
tx = CTransaction()
|
||||
f = io.BytesIO(unhexlify(signresult['hex']))
|
||||
f = BytesIO(unhexlify(signresult['hex']))
|
||||
tx.deserialize(f)
|
||||
return tx
|
||||
|
||||
|
@ -71,6 +71,7 @@ class BIP66Test(ComparisonTestFramework):
|
|||
def get_tests(self):
|
||||
self.coinbase_blocks = self.nodes[0].generate(1)
|
||||
self.nodes[0].generate(100)
|
||||
height = 102 # height of the next block to build
|
||||
hashTip = self.nodes[0].getbestblockhash()
|
||||
hashFinalSaplingRoot = int("0x" + self.nodes[0].getblock(hashTip)['finalsaplingroot'], 0)
|
||||
self.tip = int("0x"+hashTip , 0)
|
||||
|
@ -89,7 +90,7 @@ class BIP66Test(ComparisonTestFramework):
|
|||
self.block_time = gbt["mintime"] + 1
|
||||
self.block_bits = int("0x" + gbt["bits"], 0)
|
||||
|
||||
block = create_block(self.tip, create_coinbase(101),
|
||||
block = create_block(self.tip, create_coinbase(height),
|
||||
self.block_time, self.block_bits,
|
||||
hashFinalSaplingRoot)
|
||||
block.nVersion = 4
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
@ -12,7 +12,6 @@ import decimal
|
|||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import (
|
||||
initialize_chain,
|
||||
assert_equal,
|
||||
start_nodes,
|
||||
connect_nodes_bi,
|
||||
|
@ -26,12 +25,13 @@ class BlockchainTest(BitcoinTestFramework):
|
|||
|
||||
"""
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory " + self.options.tmpdir)
|
||||
initialize_chain(self.options.tmpdir)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setup_clean_chain = False
|
||||
self.num_nodes = 2
|
||||
|
||||
def setup_network(self, split=False):
|
||||
self.nodes = start_nodes(2, self.options.tmpdir)
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
|
||||
connect_nodes_bi(self.nodes, 0, 1)
|
||||
self.is_network_split = False
|
||||
self.sync_all()
|
||||
|
|
|
@ -12,7 +12,6 @@ from test_framework.util import (
|
|||
assert_equal,
|
||||
bitcoind_processes,
|
||||
connect_nodes,
|
||||
initialize_chain_clean,
|
||||
start_node,
|
||||
BLOSSOM_BRANCH_ID,
|
||||
HEARTWOOD_BRANCH_ID,
|
||||
|
@ -20,9 +19,10 @@ from test_framework.util import (
|
|||
)
|
||||
|
||||
class CoinbaseFundingStreamsTest (BitcoinTestFramework):
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 4)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 2
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def start_node_with(self, index, extra_args=[]):
|
||||
args = [
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#
|
||||
# Helper script to create the cache
|
||||
# (see BitcoinTestFramework.setup_chain)
|
||||
#
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
|
||||
class CreateCache(BitcoinTestFramework):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
# Test network and test nodes are not required:
|
||||
self.num_nodes = 0
|
||||
self.nodes = []
|
||||
|
||||
def setup_network(self):
|
||||
pass
|
||||
|
||||
def run_test(self):
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
CreateCache().main()
|
|
@ -1,10 +1,10 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2015 The Bitcoin Core developers
|
||||
# Copyright (c) 2015-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_equal, initialize_chain_clean, \
|
||||
from test_framework.util import assert_equal, \
|
||||
start_nodes, hex_str_to_bytes, bytes_to_hex_str
|
||||
from test_framework.mininode import CTransaction
|
||||
from io import BytesIO
|
||||
|
@ -13,12 +13,13 @@ from io import BytesIO
|
|||
class DecodeScriptTest(BitcoinTestFramework):
|
||||
"""Tests decoding scripts via RPC command "decodescript"."""
|
||||
|
||||
def setup_chain(self):
|
||||
print('Initializing test directory ' + self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 1)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 1
|
||||
|
||||
def setup_network(self, split=False):
|
||||
self.nodes = start_nodes(1, self.options.tmpdir)
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
|
||||
self.is_network_split = False
|
||||
|
||||
def decodescript_script_sig(self):
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2015-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
@ -8,17 +8,18 @@
|
|||
#
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import initialize_chain_clean, start_nodes
|
||||
from test_framework.util import start_nodes
|
||||
|
||||
|
||||
class DisableWalletTest (BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 1)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 1
|
||||
|
||||
def setup_network(self, split=False):
|
||||
self.nodes = start_nodes(1, self.options.tmpdir, [['-disablewallet']])
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [['-disablewallet']])
|
||||
self.is_network_split = False
|
||||
self.sync_all()
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ from test_framework.util import (
|
|||
assert_equal,
|
||||
bytes_to_hex_str,
|
||||
hex_str_to_bytes,
|
||||
initialize_chain_clean,
|
||||
start_nodes,
|
||||
)
|
||||
|
||||
|
@ -24,16 +23,17 @@ CHAIN_HISTORY_ROOT_VERSION = 2010200
|
|||
# Verify block header field 'hashLightClientRoot' is set correctly for Heartwood blocks.
|
||||
class Zip221Test(BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 4)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 4
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def setup_nodes(self):
|
||||
return start_nodes(4, self.options.tmpdir, extra_args=[[
|
||||
return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[
|
||||
'-nuparams=2bb40e60:1', # Blossom
|
||||
'-nuparams=f5b9230b:10', # Heartwood
|
||||
'-nurejectoldversions=false',
|
||||
]] * 4)
|
||||
]] * self.num_nodes)
|
||||
|
||||
def node_for_block(self, height):
|
||||
block_header = CBlockHeader()
|
||||
|
|
|
@ -9,7 +9,6 @@ from test_framework.util import (
|
|||
assert_equal,
|
||||
connect_nodes_bi,
|
||||
get_coinbase_address,
|
||||
initialize_chain_clean,
|
||||
start_nodes,
|
||||
wait_and_assert_operationid_status,
|
||||
)
|
||||
|
@ -24,14 +23,15 @@ NULL_FIELD = "0000000000000000000000000000000000000000000000000000000000000000"
|
|||
# is updated when Sapling transactions with outputs (commitments) are mined into a block.
|
||||
class FinalSaplingRootTest(BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 4)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 4
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def setup_network(self, split=False):
|
||||
self.nodes = start_nodes(4, self.options.tmpdir, extra_args=[[
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[
|
||||
'-txindex' # Avoid JSONRPC error: No information available about transaction
|
||||
]] * 4 )
|
||||
]] * self.num_nodes)
|
||||
connect_nodes_bi(self.nodes,0,1)
|
||||
connect_nodes_bi(self.nodes,1,2)
|
||||
connect_nodes_bi(self.nodes,0,2)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
@ -14,6 +14,11 @@ import os
|
|||
|
||||
class ForkNotifyTest(BitcoinTestFramework):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 2
|
||||
self.setup_clean_chain = False
|
||||
|
||||
alert_filename = None # Set by setup_network
|
||||
|
||||
def setup_network(self):
|
||||
|
|
|
@ -7,16 +7,16 @@ from test_framework.test_framework import BitcoinTestFramework
|
|||
from test_framework.util import (
|
||||
assert_raises,
|
||||
connect_nodes,
|
||||
initialize_chain_clean,
|
||||
start_node,
|
||||
check_node_log,
|
||||
)
|
||||
|
||||
class FrameworkTest (BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 4)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 2
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def start_node_with(self, index, extra_args=[]):
|
||||
args = []
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.authproxy import JSONRPCException
|
||||
from test_framework.util import assert_equal, assert_greater_than, \
|
||||
initialize_chain_clean, start_nodes, connect_nodes_bi, stop_nodes, \
|
||||
start_nodes, connect_nodes_bi, stop_nodes, \
|
||||
wait_bitcoinds
|
||||
|
||||
from decimal import Decimal
|
||||
|
@ -14,12 +14,13 @@ from decimal import Decimal
|
|||
# Create one-input, one-output, no-fee transaction:
|
||||
class RawTransactionsTest(BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 4)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 4
|
||||
|
||||
def setup_network(self, split=False):
|
||||
self.nodes = start_nodes(4, self.options.tmpdir,
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
|
||||
extra_args=[['-experimentalfeatures', '-developerencryptwallet']] * 4)
|
||||
|
||||
connect_nodes_bi(self.nodes,0,1)
|
||||
|
@ -32,7 +33,15 @@ class RawTransactionsTest(BitcoinTestFramework):
|
|||
|
||||
def run_test(self):
|
||||
print("Mining blocks...")
|
||||
feeTolerance = Decimal("0.00000002") #if the fee's positive delta is higher than this value tests will fail, neg. delta always fail the tests
|
||||
|
||||
min_relay_tx_fee = self.nodes[0].getnetworkinfo()['relayfee']
|
||||
# if the fee's positive delta is higher than this value tests will fail,
|
||||
# neg. delta always fail the tests.
|
||||
# The size of the signature of every input may be at most 2 bytes larger
|
||||
# than a minimum sized signature.
|
||||
|
||||
# = 2 bytes * minRelayTxFeePerByte
|
||||
feeTolerance = max(2 * min_relay_tx_fee/1000, Decimal("0.00000001"))
|
||||
|
||||
self.nodes[2].generate(1)
|
||||
self.sync_all()
|
||||
|
@ -41,7 +50,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
|||
|
||||
watchonly_address = self.nodes[0].getnewaddress()
|
||||
watchonly_pubkey = self.nodes[0].validateaddress(watchonly_address)["pubkey"]
|
||||
watchonly_amount = 200
|
||||
watchonly_amount = Decimal(200)
|
||||
self.nodes[3].importpubkey(watchonly_pubkey, "", True)
|
||||
watchonly_txid = self.nodes[0].sendtoaddress(watchonly_address, watchonly_amount)
|
||||
self.nodes[0].sendtoaddress(self.nodes[3].getnewaddress(), watchonly_amount / 10)
|
||||
|
@ -442,7 +451,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
|||
stop_nodes(self.nodes)
|
||||
wait_bitcoinds()
|
||||
|
||||
self.nodes = start_nodes(4, self.options.tmpdir)
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
|
||||
|
||||
connect_nodes_bi(self.nodes,0,1)
|
||||
connect_nodes_bi(self.nodes,1,2)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_equal, connect_nodes_bi, \
|
||||
initialize_chain_clean, start_nodes
|
||||
start_nodes
|
||||
|
||||
|
||||
class GetBlockTemplateTest(BitcoinTestFramework):
|
||||
|
@ -13,12 +13,13 @@ class GetBlockTemplateTest(BitcoinTestFramework):
|
|||
Test getblocktemplate.
|
||||
'''
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 4)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 2
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def setup_network(self, split=False):
|
||||
self.nodes = start_nodes(2, self.options.tmpdir)
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
|
||||
connect_nodes_bi(self.nodes,0,1)
|
||||
self.is_network_split=False
|
||||
self.sync_all()
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
@ -49,6 +49,11 @@ class GetBlockTemplateLPTest(BitcoinTestFramework):
|
|||
Test longpolling with getblocktemplate.
|
||||
'''
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 4
|
||||
self.setup_clean_chain = False
|
||||
|
||||
def run_test(self):
|
||||
print("Warning: this test will take about 70 seconds in the best case. Be patient.")
|
||||
self.nodes[0].generate(10)
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.authproxy import JSONRPCException
|
||||
from test_framework.util import connect_nodes_bi
|
||||
|
||||
from binascii import a2b_hex, b2a_hex
|
||||
from hashlib import sha256
|
||||
|
@ -68,7 +69,7 @@ def genmrklroot(leaflist):
|
|||
cur = n
|
||||
return cur[0]
|
||||
|
||||
def template_to_bytes(tmpl, txlist):
|
||||
def template_to_bytearray(tmpl, txlist):
|
||||
blkver = pack('<L', tmpl['version'])
|
||||
mrklroot = genmrklroot(list(dblsha(a) for a in txlist))
|
||||
reserved = b'\0'*32
|
||||
|
@ -79,10 +80,10 @@ def template_to_bytes(tmpl, txlist):
|
|||
blk += varlenEncode(len(txlist))
|
||||
for tx in txlist:
|
||||
blk += tx
|
||||
return blk
|
||||
return bytearray(blk)
|
||||
|
||||
def template_to_hex(tmpl, txlist):
|
||||
return b2x(template_to_bytes(tmpl, txlist))
|
||||
return b2x(template_to_bytearray(tmpl, txlist))
|
||||
|
||||
def assert_template(node, tmpl, txlist, expect):
|
||||
rsp = node.getblocktemplate({'data':template_to_hex(tmpl, txlist),'mode':'proposal'})
|
||||
|
@ -94,6 +95,15 @@ class GetBlockTemplateProposalTest(BitcoinTestFramework):
|
|||
Test block proposals with getblocktemplate.
|
||||
'''
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 2
|
||||
self.setup_clean_chain = False
|
||||
|
||||
def setup_network(self):
|
||||
self.nodes = self.setup_nodes()
|
||||
connect_nodes_bi(self.nodes, 0, 1)
|
||||
|
||||
def run_test(self):
|
||||
node = self.nodes[0]
|
||||
node.generate(1) # Mine a block to leave initial block download
|
||||
|
@ -159,7 +169,7 @@ class GetBlockTemplateProposalTest(BitcoinTestFramework):
|
|||
tmpl['bits'] = realbits
|
||||
|
||||
# Test 9: Bad merkle root
|
||||
rawtmpl = template_to_bytes(tmpl, txlist)
|
||||
rawtmpl = template_to_bytearray(tmpl, txlist)
|
||||
rawtmpl[4+32] = (rawtmpl[4+32] + 1) % 0x100
|
||||
rsp = node.getblocktemplate({'data':b2x(rawtmpl),'mode':'proposal'})
|
||||
if rsp != 'bad-txnmrklroot':
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
@ -12,9 +12,12 @@ from test_framework.test_framework import BitcoinTestFramework
|
|||
from test_framework.util import assert_equal
|
||||
|
||||
class GetChainTipsTest (BitcoinTestFramework):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 4
|
||||
self.setup_clean_chain = False
|
||||
|
||||
def run_test (self):
|
||||
BitcoinTestFramework.run_test (self)
|
||||
|
||||
tips = self.nodes[0].getchaintips ()
|
||||
assert_equal (len (tips), 1)
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
from test_framework.test_framework import BitcoinTestFramework
|
||||
|
||||
from test_framework.util import assert_equal
|
||||
from test_framework.util import initialize_chain_clean
|
||||
from test_framework.util import start_nodes, stop_nodes, connect_nodes
|
||||
from test_framework.util import wait_bitcoinds
|
||||
|
||||
|
@ -20,15 +19,16 @@ from test_framework.mininode import COIN
|
|||
|
||||
class GetrawtransactionTest(BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 4)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 3
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def setup_network(self):
|
||||
# -insightexplorer causes spentindex to be enabled (fSpentIndex = true)
|
||||
|
||||
self.nodes = start_nodes(3, self.options.tmpdir,
|
||||
[['-debug', '-txindex', '-experimentalfeatures', '-insightexplorer']]*3)
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
|
||||
[['-debug', '-txindex', '-experimentalfeatures', '-insightexplorer']] * self.num_nodes)
|
||||
connect_nodes(self.nodes[0], 1)
|
||||
connect_nodes(self.nodes[0], 2)
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
@ -8,25 +8,30 @@
|
|||
#
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_equal, start_nodes, str_to_b64str
|
||||
from test_framework.util import assert_equal, str_to_b64str
|
||||
|
||||
from http.client import HTTPConnection, BAD_REQUEST, NOT_FOUND
|
||||
from urllib.parse import urlparse
|
||||
import http.client
|
||||
import urllib.parse
|
||||
|
||||
class HTTPBasicsTest (BitcoinTestFramework):
|
||||
def setup_nodes(self):
|
||||
return start_nodes(4, self.options.tmpdir)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 3
|
||||
self.setup_clean_chain = False
|
||||
|
||||
def setup_network(self):
|
||||
self.nodes = self.setup_nodes()
|
||||
|
||||
def run_test(self):
|
||||
|
||||
#################################################
|
||||
# lowlevel check for http persistent connection #
|
||||
#################################################
|
||||
url = urlparse(self.nodes[0].url)
|
||||
url = urllib.parse.urlparse(self.nodes[0].url)
|
||||
authpair = url.username + ':' + url.password
|
||||
headers = {"Authorization": "Basic " + str_to_b64str(authpair)}
|
||||
|
||||
conn = HTTPConnection(url.hostname, url.port)
|
||||
conn = http.client.HTTPConnection(url.hostname, url.port)
|
||||
conn.connect()
|
||||
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
|
||||
out1 = conn.getresponse().read()
|
||||
|
@ -43,7 +48,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
|
|||
# same should be if we add keep-alive because this should be the std. behaviour
|
||||
headers = {"Authorization": "Basic " + str_to_b64str(authpair), "Connection": "keep-alive"}
|
||||
|
||||
conn = HTTPConnection(url.hostname, url.port)
|
||||
conn = http.client.HTTPConnection(url.hostname, url.port)
|
||||
conn.connect()
|
||||
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
|
||||
out1 = conn.getresponse().read()
|
||||
|
@ -60,7 +65,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
|
|||
# now do the same with "Connection: close"
|
||||
headers = {"Authorization": "Basic " + str_to_b64str(authpair), "Connection":"close"}
|
||||
|
||||
conn = HTTPConnection(url.hostname, url.port)
|
||||
conn = http.client.HTTPConnection(url.hostname, url.port)
|
||||
conn.connect()
|
||||
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
|
||||
out1 = conn.getresponse().read()
|
||||
|
@ -68,22 +73,22 @@ class HTTPBasicsTest (BitcoinTestFramework):
|
|||
assert_equal(conn.sock!=None, False) # now the connection must be closed after the response
|
||||
|
||||
# node1 (2nd node) is running with disabled keep-alive option
|
||||
urlNode1 = urlparse(self.nodes[1].url)
|
||||
urlNode1 = urllib.parse.urlparse(self.nodes[1].url)
|
||||
authpair = urlNode1.username + ':' + urlNode1.password
|
||||
headers = {"Authorization": "Basic " + str_to_b64str(authpair)}
|
||||
|
||||
conn = HTTPConnection(urlNode1.hostname, urlNode1.port)
|
||||
conn = http.client.HTTPConnection(urlNode1.hostname, urlNode1.port)
|
||||
conn.connect()
|
||||
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
|
||||
out1 = conn.getresponse().read()
|
||||
assert_equal(b'"error":null' in out1, True)
|
||||
|
||||
# node2 (third node) is running with standard keep-alive parameters which means keep-alive is on
|
||||
urlNode2 = urlparse(self.nodes[2].url)
|
||||
urlNode2 = urllib.parse.urlparse(self.nodes[2].url)
|
||||
authpair = urlNode2.username + ':' + urlNode2.password
|
||||
headers = {"Authorization": "Basic " + str_to_b64str(authpair)}
|
||||
|
||||
conn = HTTPConnection(urlNode2.hostname, urlNode2.port)
|
||||
conn = http.client.HTTPConnection(urlNode2.hostname, urlNode2.port)
|
||||
conn.connect()
|
||||
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
|
||||
out1 = conn.getresponse().read()
|
||||
|
@ -91,17 +96,17 @@ class HTTPBasicsTest (BitcoinTestFramework):
|
|||
assert_equal(conn.sock!=None, True) # connection must be closed because bitcoind should use keep-alive by default
|
||||
|
||||
# Check excessive request size
|
||||
conn = HTTPConnection(urlNode2.hostname, urlNode2.port)
|
||||
conn = http.client.HTTPConnection(urlNode2.hostname, urlNode2.port)
|
||||
conn.connect()
|
||||
conn.request('GET', '/' + ('x'*1000), '', headers)
|
||||
out1 = conn.getresponse()
|
||||
assert_equal(out1.status, NOT_FOUND)
|
||||
assert_equal(out1.status, http.client.NOT_FOUND)
|
||||
|
||||
conn = HTTPConnection(urlNode2.hostname, urlNode2.port)
|
||||
conn = http.client.HTTPConnection(urlNode2.hostname, urlNode2.port)
|
||||
conn.connect()
|
||||
conn.request('GET', '/' + ('x'*10000), '', headers)
|
||||
out1 = conn.getresponse()
|
||||
assert_equal(out1.status, BAD_REQUEST)
|
||||
assert_equal(out1.status, http.client.BAD_REQUEST)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
@ -8,15 +8,16 @@
|
|||
#
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import initialize_chain_clean, start_node, \
|
||||
from test_framework.util import start_node, \
|
||||
connect_nodes_bi, sync_blocks
|
||||
|
||||
import time
|
||||
|
||||
class InvalidateTest(BitcoinTestFramework):
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 3)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 3
|
||||
|
||||
def setup_network(self):
|
||||
self.nodes = []
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2015-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
#
|
||||
|
||||
from test_framework.test_framework import ComparisonTestFramework
|
||||
from test_framework.util import assert_equal
|
||||
|
@ -28,6 +27,7 @@ class InvalidBlockRequestTest(ComparisonTestFramework):
|
|||
''' Can either run this test as 1 node with expected answers, or two and compare them.
|
||||
Change the "outcome" variable from each TestInstance object to only do the comparison. '''
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 1
|
||||
|
||||
def run_test(self):
|
||||
|
@ -40,18 +40,20 @@ class InvalidBlockRequestTest(ComparisonTestFramework):
|
|||
|
||||
def get_tests(self):
|
||||
if self.tip is None:
|
||||
self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0)
|
||||
self.tip = int("0x" + self.nodes[0].getbestblockhash(), 0)
|
||||
self.block_time = int(time.time())+1
|
||||
|
||||
'''
|
||||
Create a new block with an anyone-can-spend coinbase
|
||||
'''
|
||||
block = create_block(self.tip, create_coinbase(), self.block_time)
|
||||
height = 1
|
||||
block = create_block(self.tip, create_coinbase(height), self.block_time)
|
||||
self.block_time += 1
|
||||
block.solve()
|
||||
# Save the coinbase for later
|
||||
self.block1 = block
|
||||
self.tip = block.sha256
|
||||
height += 1
|
||||
yield TestInstance([[block, True]])
|
||||
|
||||
'''
|
||||
|
@ -59,11 +61,12 @@ class InvalidBlockRequestTest(ComparisonTestFramework):
|
|||
'''
|
||||
test = TestInstance(sync_every_block=False)
|
||||
for i in range(100):
|
||||
block = create_block(self.tip, create_coinbase(), self.block_time)
|
||||
block = create_block(self.tip, create_coinbase(height), self.block_time)
|
||||
block.solve()
|
||||
self.tip = block.sha256
|
||||
self.block_time += 1
|
||||
test.blocks_and_transactions.append([block, True])
|
||||
height += 1
|
||||
yield test
|
||||
|
||||
'''
|
||||
|
@ -73,7 +76,7 @@ class InvalidBlockRequestTest(ComparisonTestFramework):
|
|||
coinbase, spend of that spend). Duplicate the 3rd transaction to
|
||||
leave merkle root and blockheader unchanged but invalidate the block.
|
||||
'''
|
||||
block2 = create_block(self.tip, create_coinbase(), self.block_time)
|
||||
block2 = create_block(self.tip, create_coinbase(height), self.block_time)
|
||||
self.block_time += 1
|
||||
|
||||
# chr(81) is OP_TRUE
|
||||
|
@ -95,11 +98,12 @@ class InvalidBlockRequestTest(ComparisonTestFramework):
|
|||
|
||||
self.tip = block2.sha256
|
||||
yield TestInstance([[block2, False], [block2_orig, True]])
|
||||
height += 1
|
||||
|
||||
'''
|
||||
Make sure that a totally screwed up block is not valid.
|
||||
'''
|
||||
block3 = create_block(self.tip, create_coinbase(), self.block_time)
|
||||
block3 = create_block(self.tip, create_coinbase(height), self.block_time)
|
||||
self.block_time += 1
|
||||
block3.vtx[0].vout[0].nValue = 100*100000000 # Too high!
|
||||
block3.vtx[0].sha256=None
|
||||
|
|
|
@ -6,21 +6,23 @@
|
|||
from decimal import Decimal
|
||||
from functools import reduce
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_equal, assert_greater_than, start_nodes, initialize_chain_clean, connect_nodes_bi
|
||||
from test_framework.util import assert_equal, assert_greater_than, start_nodes, connect_nodes_bi
|
||||
|
||||
import logging
|
||||
import sys
|
||||
|
||||
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.INFO)
|
||||
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO, stream=sys.stdout)
|
||||
|
||||
|
||||
class KeyImportExportTest (BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 4)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 4
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def setup_network(self, split=False):
|
||||
self.nodes = start_nodes(4, self.options.tmpdir )
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir )
|
||||
connect_nodes_bi(self.nodes,0,1)
|
||||
connect_nodes_bi(self.nodes,1,2)
|
||||
connect_nodes_bi(self.nodes,0,2)
|
||||
|
|
|
@ -1,21 +1,14 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
# Exercise the wallet keypool, and interaction with wallet encryption/locking
|
||||
|
||||
# Add python-bitcoinrpc to module search path:
|
||||
|
||||
from test_framework.authproxy import JSONRPCException
|
||||
from test_framework.util import check_json_precision, initialize_chain, \
|
||||
start_nodes, start_node, stop_nodes, wait_bitcoinds, bitcoind_processes
|
||||
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import tempfile
|
||||
import traceback
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_equal, \
|
||||
start_nodes, start_node, bitcoind_processes
|
||||
|
||||
def check_array_result(object_array, to_match, expected):
|
||||
"""
|
||||
|
@ -38,12 +31,15 @@ def check_array_result(object_array, to_match, expected):
|
|||
if num_matched == 0:
|
||||
raise AssertionError("No objects matched %s"%(str(to_match)))
|
||||
|
||||
def run_test(nodes, tmpdir):
|
||||
class KeyPoolTest(BitcoinTestFramework):
|
||||
|
||||
def run_test(self):
|
||||
nodes = self.nodes
|
||||
# Encrypt wallet and wait to terminate
|
||||
nodes[0].encryptwallet('test')
|
||||
bitcoind_processes[0].wait()
|
||||
# Restart node 0
|
||||
nodes[0] = start_node(0, tmpdir)
|
||||
nodes[0] = start_node(0, self.options.tmpdir)
|
||||
# Keep creating keys
|
||||
addr = nodes[0].getnewaddress()
|
||||
try:
|
||||
|
@ -72,58 +68,29 @@ def run_test(nodes, tmpdir):
|
|||
except JSONRPCException as e:
|
||||
assert(e.error['code']==-12)
|
||||
|
||||
# refill keypool with three new addresses
|
||||
nodes[0].walletpassphrase('test', 12000)
|
||||
nodes[0].keypoolrefill(3)
|
||||
nodes[0].walletlock()
|
||||
|
||||
def main():
|
||||
import optparse
|
||||
|
||||
parser = optparse.OptionParser(usage="%prog [options]")
|
||||
parser.add_option("--nocleanup", dest="nocleanup", default=False, action="store_true",
|
||||
help="Leave bitcoinds and test.* datadir on exit or error")
|
||||
parser.add_option("--srcdir", dest="srcdir", default="../../src",
|
||||
help="Source directory containing bitcoind/bitcoin-cli (default: %default%)")
|
||||
parser.add_option("--tmpdir", dest="tmpdir", default=tempfile.mkdtemp(prefix="test"),
|
||||
help="Root directory for datadirs")
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
os.environ['PATH'] = options.srcdir+":"+os.environ['PATH']
|
||||
|
||||
check_json_precision()
|
||||
|
||||
success = False
|
||||
nodes = []
|
||||
# drain them by mining
|
||||
nodes[0].generate(1)
|
||||
nodes[0].generate(1)
|
||||
nodes[0].generate(1)
|
||||
nodes[0].generate(1)
|
||||
try:
|
||||
print("Initializing test directory "+options.tmpdir)
|
||||
if not os.path.isdir(options.tmpdir):
|
||||
os.makedirs(options.tmpdir)
|
||||
initialize_chain(options.tmpdir)
|
||||
|
||||
nodes = start_nodes(1, options.tmpdir, extra_args=[['-experimentalfeatures', '-developerencryptwallet']])
|
||||
|
||||
run_test(nodes, options.tmpdir)
|
||||
|
||||
success = True
|
||||
|
||||
except AssertionError as e:
|
||||
print("Assertion failed: "+e.message)
|
||||
nodes[0].generate(1)
|
||||
raise AssertionError('Keypool should be exhausted after three addesses')
|
||||
except JSONRPCException as e:
|
||||
print("JSONRPC error: "+e.error['message'])
|
||||
traceback.print_tb(sys.exc_info()[2])
|
||||
except Exception as e:
|
||||
print("Unexpected exception caught during testing: ", e.error['message'], str(sys.exc_info()[0]))
|
||||
traceback.print_tb(sys.exc_info()[2])
|
||||
assert_equal(e.error['code'], -12)
|
||||
|
||||
if not options.nocleanup:
|
||||
print("Cleaning up")
|
||||
stop_nodes(nodes)
|
||||
wait_bitcoinds()
|
||||
shutil.rmtree(options.tmpdir)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setup_clean_chain = False
|
||||
self.num_nodes = 1
|
||||
|
||||
if success:
|
||||
print("Tests successful")
|
||||
sys.exit(0)
|
||||
else:
|
||||
print("Failed")
|
||||
sys.exit(1)
|
||||
def setup_network(self):
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[['-experimentalfeatures', '-developerencryptwallet']])
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
KeyPoolTest().main()
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
@ -31,6 +31,10 @@ def check_array_result(object_array, to_match, expected):
|
|||
raise AssertionError("No objects matched %s"%(str(to_match)))
|
||||
|
||||
class ListTransactionsTest(BitcoinTestFramework):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 4
|
||||
self.setup_clean_chain = False
|
||||
|
||||
def run_test(self):
|
||||
# Simple send, 0 to 1:
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2015-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
#
|
||||
|
||||
from test_framework.mininode import NodeConn, NodeConnCB, NetworkThread, \
|
||||
EarlyDisconnectError, CInv, msg_inv, mininode_lock
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import initialize_chain_clean, start_nodes, \
|
||||
p2p_port
|
||||
from test_framework.util import start_nodes, p2p_port
|
||||
|
||||
import os
|
||||
import time
|
||||
|
@ -87,12 +85,13 @@ class MaxBlocksInFlightTest(BitcoinTestFramework):
|
|||
default=os.getenv("BITCOIND", "bitcoind"),
|
||||
help="Binary to test max block requests behavior")
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 1)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 1
|
||||
|
||||
def setup_network(self):
|
||||
self.nodes = start_nodes(1, self.options.tmpdir,
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir,
|
||||
extra_args=[['-debug', '-whitelist=127.0.0.1']],
|
||||
binary=[self.options.testbinary])
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2019 The Zcash developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
@ -8,7 +8,6 @@ from test_framework.util import (
|
|||
assert_equal,
|
||||
get_coinbase_address,
|
||||
fail,
|
||||
initialize_chain_clean,
|
||||
start_nodes,
|
||||
wait_and_assert_operationid_status,
|
||||
)
|
||||
|
@ -18,10 +17,6 @@ from time import sleep
|
|||
|
||||
# Test wallet behaviour with Sapling addresses
|
||||
class MempoolLimit(BitcoinTestFramework):
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory " + self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 4)
|
||||
|
||||
def setup_nodes(self):
|
||||
extra_args = [
|
||||
["-debug=mempool", '-mempooltxcostlimit=8000'], # 2 transactions at min cost
|
||||
|
@ -30,17 +25,22 @@ class MempoolLimit(BitcoinTestFramework):
|
|||
# Let node 3 hold one more transaction
|
||||
["-debug=mempool", '-mempooltxcostlimit=12000'], # 3 transactions at min cost
|
||||
]
|
||||
return start_nodes(4, self.options.tmpdir, extra_args)
|
||||
return start_nodes(self.num_nodes, self.options.tmpdir, extra_args)
|
||||
|
||||
def check_mempool_sizes(self, expected_size, check_node3=True):
|
||||
for i in range(4 if check_node3 else 3):
|
||||
for i in range(self.num_nodes if check_node3 else self.num_nodes - 1):
|
||||
mempool = self.nodes[i].getrawmempool()
|
||||
if len(mempool) != expected_size:
|
||||
# print all nodes' mempools before failing
|
||||
for i in range(4):
|
||||
for i in range(self.num_nodes):
|
||||
print("Mempool for node {}: {}".format(i, mempool))
|
||||
fail("Fail: Mempool for node {}: size={}, expected={}".format(i, len(mempool), expected_size))
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 4
|
||||
|
||||
def run_test(self):
|
||||
print("Mining blocks...")
|
||||
self.sync_all()
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import (
|
||||
assert_equal, assert_true, initialize_chain_clean,
|
||||
assert_equal, assert_true,
|
||||
start_node, connect_nodes, wait_and_assert_operationid_status,
|
||||
get_coinbase_address
|
||||
)
|
||||
|
@ -17,6 +17,11 @@ class MempoolUpgradeActivationTest(BitcoinTestFramework):
|
|||
|
||||
alert_filename = None # Set by setup_network
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 2
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def setup_network(self):
|
||||
args = ["-checkmempool", "-debug=mempool", "-blockmaxsize=4000",
|
||||
"-nuparams=2bb40e60:200", # Blossom
|
||||
|
@ -28,10 +33,6 @@ class MempoolUpgradeActivationTest(BitcoinTestFramework):
|
|||
self.is_network_split = False
|
||||
self.sync_all
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 2)
|
||||
|
||||
def run_test(self):
|
||||
self.nodes[1].generate(100)
|
||||
self.sync_all()
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
@ -15,6 +15,10 @@ from test_framework.util import assert_equal, assert_raises, start_node, connect
|
|||
|
||||
# Create one-input, one-output, no-fee transaction:
|
||||
class MempoolCoinbaseTest(BitcoinTestFramework):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 2
|
||||
self.setup_clean_chain = False
|
||||
|
||||
alert_filename = None # Set by setup_network
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
@ -15,6 +15,11 @@ from test_framework.util import assert_equal, start_node
|
|||
# Create one-input, one-output, no-fee transaction:
|
||||
class MempoolCoinbaseTest(BitcoinTestFramework):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 1
|
||||
self.setup_clean_chain = False
|
||||
|
||||
def setup_network(self):
|
||||
# Just need one node for this test
|
||||
args = ["-checkmempool", "-debug=mempool"]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
@ -22,6 +22,11 @@ from test_framework.util import assert_equal, assert_greater_than, assert_raises
|
|||
# Create one-input, one-output, no-fee transaction:
|
||||
class MempoolSpendCoinbaseTest(BitcoinTestFramework):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 1
|
||||
self.setup_clean_chain = False
|
||||
|
||||
def setup_network(self):
|
||||
# Just need one node for this test
|
||||
args = ["-checkmempool", "-debug=mempool"]
|
||||
|
|
|
@ -21,11 +21,11 @@ TX_EXPIRY_DELTA = 10
|
|||
class MempoolTxExpiryTest(BitcoinTestFramework):
|
||||
|
||||
def setup_nodes(self):
|
||||
return start_nodes(4, self.options.tmpdir,
|
||||
return start_nodes(self.num_nodes, self.options.tmpdir,
|
||||
[[
|
||||
"-txexpirydelta=%d" % TX_EXPIRY_DELTA,
|
||||
"-debug=mempool"
|
||||
]] * 4)
|
||||
]] * self.num_nodes)
|
||||
|
||||
# Test before, at, and after expiry block
|
||||
# chain is at block height 199 when run_test executes
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
@ -11,14 +11,15 @@ import string
|
|||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.authproxy import JSONRPCException
|
||||
from test_framework.util import assert_equal, assert_raises, \
|
||||
initialize_chain_clean, start_node, connect_nodes
|
||||
start_node, connect_nodes
|
||||
|
||||
|
||||
class MerkleBlockTest(BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 4)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 4
|
||||
|
||||
def setup_network(self):
|
||||
self.nodes = []
|
||||
|
|
|
@ -14,7 +14,6 @@ from test_framework.util import (
|
|||
assert_raises,
|
||||
bitcoind_processes,
|
||||
connect_nodes,
|
||||
initialize_chain_clean,
|
||||
start_node,
|
||||
wait_and_assert_operationid_status,
|
||||
check_node_log,
|
||||
|
@ -22,9 +21,10 @@ from test_framework.util import (
|
|||
|
||||
class ShieldCoinbaseTest (BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 4)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 4
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def start_node_with(self, index, extra_args=[]):
|
||||
args = [
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2015 The Bitcoin Core developers
|
||||
# Copyright (c) 2015-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
@ -8,23 +8,21 @@
|
|||
#
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import (
|
||||
assert_equal,
|
||||
initialize_chain,
|
||||
start_nodes,
|
||||
str_to_b64str,
|
||||
)
|
||||
from test_framework.util import str_to_b64str, assert_equal
|
||||
|
||||
import os
|
||||
from http.client import HTTPConnection
|
||||
from urllib.parse import urlparse
|
||||
import http.client
|
||||
import urllib.parse
|
||||
|
||||
class HTTPBasicsTest (BitcoinTestFramework):
|
||||
def setup_nodes(self):
|
||||
return start_nodes(4, self.options.tmpdir)
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setup_clean_chain = False
|
||||
self.num_nodes = 1
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain(self.options.tmpdir)
|
||||
super().setup_chain()
|
||||
#Append rpcauth to zcash.conf before initialization
|
||||
rpcauth = "rpcauth=rt:93648e835a54c573682c2eb19f882535$7681e9c5b74bdd85e78166031d2058e1069b3ed7ed967c93fc63abba06f31144"
|
||||
rpcauth2 = "rpcauth=rt2:f8607b1a88861fac29dfccf9b52ff9f$ff36a0c23c8c62b4846112e50fa888416e94c17bfd4c42f88fd8f55ec6a3137e"
|
||||
|
@ -32,12 +30,15 @@ class HTTPBasicsTest (BitcoinTestFramework):
|
|||
f.write(rpcauth+"\n")
|
||||
f.write(rpcauth2+"\n")
|
||||
|
||||
def setup_network(self):
|
||||
self.nodes = self.setup_nodes()
|
||||
|
||||
def run_test(self):
|
||||
|
||||
##################################################
|
||||
# Check correctness of the rpcauth config option #
|
||||
##################################################
|
||||
url = urlparse(self.nodes[0].url)
|
||||
url = urllib.parse.urlparse(self.nodes[0].url)
|
||||
|
||||
#Old authpair
|
||||
authpair = url.username + ':' + url.password
|
||||
|
@ -53,7 +54,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
|
|||
|
||||
headers = {"Authorization": "Basic " + str_to_b64str(authpair)}
|
||||
|
||||
conn = HTTPConnection(url.hostname, url.port)
|
||||
conn = http.client.HTTPConnection(url.hostname, url.port)
|
||||
conn.connect()
|
||||
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
|
||||
resp = conn.getresponse()
|
||||
|
@ -63,7 +64,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
|
|||
#Use new authpair to confirm both work
|
||||
headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)}
|
||||
|
||||
conn = HTTPConnection(url.hostname, url.port)
|
||||
conn = http.client.HTTPConnection(url.hostname, url.port)
|
||||
conn.connect()
|
||||
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
|
||||
resp = conn.getresponse()
|
||||
|
@ -74,7 +75,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
|
|||
authpairnew = "rtwrong:"+password
|
||||
headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)}
|
||||
|
||||
conn = HTTPConnection(url.hostname, url.port)
|
||||
conn = http.client.HTTPConnection(url.hostname, url.port)
|
||||
conn.connect()
|
||||
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
|
||||
resp = conn.getresponse()
|
||||
|
@ -85,7 +86,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
|
|||
authpairnew = "rt:"+password+"wrong"
|
||||
headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)}
|
||||
|
||||
conn = HTTPConnection(url.hostname, url.port)
|
||||
conn = http.client.HTTPConnection(url.hostname, url.port)
|
||||
conn.connect()
|
||||
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
|
||||
resp = conn.getresponse()
|
||||
|
@ -96,7 +97,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
|
|||
authpairnew = "rt2:"+password2
|
||||
headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)}
|
||||
|
||||
conn = HTTPConnection(url.hostname, url.port)
|
||||
conn = http.client.HTTPConnection(url.hostname, url.port)
|
||||
conn.connect()
|
||||
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
|
||||
resp = conn.getresponse()
|
||||
|
@ -107,7 +108,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
|
|||
authpairnew = "rt2:"+password2+"wrong"
|
||||
headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)}
|
||||
|
||||
conn = HTTPConnection(url.hostname, url.port)
|
||||
conn = http.client.HTTPConnection(url.hostname, url.port)
|
||||
conn.connect()
|
||||
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
|
||||
resp = conn.getresponse()
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
@ -11,9 +11,15 @@ from test_framework.test_framework import BitcoinTestFramework
|
|||
from test_framework.util import assert_equal, connect_nodes_bi, p2p_port
|
||||
|
||||
import time
|
||||
from urllib.parse import urlparse
|
||||
import urllib.parse
|
||||
|
||||
class NodeHandlingTest (BitcoinTestFramework):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 4
|
||||
self.setup_clean_chain = False
|
||||
|
||||
def run_test(self):
|
||||
###########################
|
||||
# setban/listbanned tests #
|
||||
|
@ -45,7 +51,7 @@ class NodeHandlingTest (BitcoinTestFramework):
|
|||
###########################
|
||||
# RPC disconnectnode test #
|
||||
###########################
|
||||
url = urlparse(self.nodes[1].url)
|
||||
url = urllib.parse.urlparse(self.nodes[1].url)
|
||||
self.nodes[0].disconnectnode(url.hostname+":"+str(p2p_port(1)))
|
||||
time.sleep(2) #disconnecting a node needs a little bit of time
|
||||
for node in self.nodes[0].getpeerinfo():
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2015-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
#
|
||||
|
||||
from test_framework.mininode import CBlockHeader, CInv, NodeConn, NodeConnCB, \
|
||||
NetworkThread, msg_block, msg_headers, msg_inv, msg_ping, msg_pong, \
|
||||
mininode_lock
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_equal, initialize_chain_clean, \
|
||||
from test_framework.util import assert_equal, \
|
||||
start_node, p2p_port
|
||||
from test_framework.blocktools import create_block, create_coinbase
|
||||
|
||||
|
@ -118,8 +117,10 @@ class AcceptBlockTest(BitcoinTestFramework):
|
|||
default=os.getenv("BITCOIND", "bitcoind"),
|
||||
help="bitcoind binary to test")
|
||||
|
||||
def setup_chain(self):
|
||||
initialize_chain_clean(self.options.tmpdir, 2)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 2
|
||||
|
||||
def setup_network(self):
|
||||
# Node0 will be used to test behavior of processing unrequested blocks
|
||||
|
@ -156,9 +157,9 @@ class AcceptBlockTest(BitcoinTestFramework):
|
|||
# 2. Send one block that builds on each tip.
|
||||
# This should be accepted.
|
||||
blocks_h2 = [] # the height 2 blocks on each node's chain
|
||||
block_time = time.time() + 1
|
||||
block_time = int(time.time()) + 1
|
||||
for i in range(2):
|
||||
blocks_h2.append(create_block(tips[i], create_coinbase(), block_time))
|
||||
blocks_h2.append(create_block(tips[i], create_coinbase(2), block_time))
|
||||
blocks_h2[i].solve()
|
||||
block_time += 1
|
||||
test_node.send_message(msg_block(blocks_h2[0]))
|
||||
|
@ -172,7 +173,7 @@ class AcceptBlockTest(BitcoinTestFramework):
|
|||
# 3. Send another block that builds on the original tip.
|
||||
blocks_h2f = [] # Blocks at height 2 that fork off the main chain
|
||||
for i in range(2):
|
||||
blocks_h2f.append(create_block(tips[i], create_coinbase(), blocks_h2[i].nTime+1))
|
||||
blocks_h2f.append(create_block(tips[i], create_coinbase(2), blocks_h2[i].nTime+1))
|
||||
blocks_h2f[i].solve()
|
||||
test_node.send_message(msg_block(blocks_h2f[0]))
|
||||
white_node.send_message(msg_block(blocks_h2f[1]))
|
||||
|
@ -191,7 +192,7 @@ class AcceptBlockTest(BitcoinTestFramework):
|
|||
# 4. Now send another block that builds on the forking chain.
|
||||
blocks_h3 = []
|
||||
for i in range(2):
|
||||
blocks_h3.append(create_block(blocks_h2f[i].sha256, create_coinbase(), blocks_h2f[i].nTime+1))
|
||||
blocks_h3.append(create_block(blocks_h2f[i].sha256, create_coinbase(3), blocks_h2f[i].nTime+1))
|
||||
blocks_h3[i].solve()
|
||||
test_node.send_message(msg_block(blocks_h3[0]))
|
||||
white_node.send_message(msg_block(blocks_h3[1]))
|
||||
|
@ -222,7 +223,7 @@ class AcceptBlockTest(BitcoinTestFramework):
|
|||
all_blocks = [] # node0's blocks
|
||||
for j in range(2):
|
||||
for i in range(288):
|
||||
next_block = create_block(tips[j].sha256, create_coinbase(), tips[j].nTime+1)
|
||||
next_block = create_block(tips[j].sha256, create_coinbase(i + 4), tips[j].nTime+1)
|
||||
next_block.solve()
|
||||
if j==0:
|
||||
test_node.send_message(msg_block(next_block))
|
||||
|
|
|
@ -0,0 +1,283 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2015-2016 The Bitcoin Core 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 ComparisonTestFramework
|
||||
from test_framework.blocktools import (create_block, create_coinbase)
|
||||
from test_framework.comptool import TestManager, TestInstance
|
||||
from test_framework.key import CECKey
|
||||
from test_framework.mininode import (
|
||||
CBlockHeader,
|
||||
COutPoint,
|
||||
CTransaction,
|
||||
CTxIn,
|
||||
CTxOut,
|
||||
NetworkThread,
|
||||
)
|
||||
from test_framework.script import CScript, SignatureHash, SIGHASH_ALL, OP_CHECKSIG, OP_TRUE
|
||||
from test_framework.util import SAPLING_BRANCH_ID
|
||||
import random
|
||||
import time
|
||||
|
||||
class PreviousSpendableOutput(object):
|
||||
def __init__(self, tx = CTransaction(), n = -1):
|
||||
self.tx = tx
|
||||
self.n = n # the output we're spending
|
||||
|
||||
'''
|
||||
This reimplements tests from the bitcoinj/FullBlockTestGenerator used
|
||||
by the pull-tester.
|
||||
|
||||
We use the testing framework in which we expect a particular answer from
|
||||
each test.
|
||||
'''
|
||||
|
||||
class FullBlockTest(ComparisonTestFramework):
|
||||
|
||||
''' Can either run this test as 1 node with expected answers, or two and compare them.
|
||||
Change the "outcome" variable from each TestInstance object to only do the comparison. '''
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 1
|
||||
self.block_heights = {}
|
||||
self.coinbase_key = CECKey()
|
||||
self.coinbase_key.set_secretbytes(b"horsebattery")
|
||||
self.coinbase_pubkey = self.coinbase_key.get_pubkey()
|
||||
self.block_time = int(time.time())+1
|
||||
self.tip = None
|
||||
self.blocks = {}
|
||||
|
||||
def run_test(self):
|
||||
test = TestManager(self, self.options.tmpdir)
|
||||
test.add_all_connections(self.nodes)
|
||||
NetworkThread().start() # Start up network handling in another thread
|
||||
test.run()
|
||||
|
||||
def add_transactions_to_block(self, block, tx_list):
|
||||
[ tx.rehash() for tx in tx_list ]
|
||||
block.vtx.extend(tx_list)
|
||||
block.hashMerkleRoot = block.calc_merkle_root()
|
||||
block.rehash()
|
||||
return block
|
||||
|
||||
# Create a block on top of self.tip, and advance self.tip to point to the new block
|
||||
# if spend is specified, then 1 satoshi will be spent from that to an anyone-can-spend output,
|
||||
# and rest will go to fees.
|
||||
def next_block(self, number, spend=None, additional_coinbase_value=0, script=None):
|
||||
if self.tip == None:
|
||||
base_block_hash = self.genesis_hash
|
||||
else:
|
||||
base_block_hash = self.tip.sha256
|
||||
# First create the coinbase
|
||||
height = self.block_heights[base_block_hash] + 1
|
||||
coinbase = create_coinbase(height, self.coinbase_pubkey)
|
||||
coinbase.vout[0].nValue += additional_coinbase_value
|
||||
if (spend != None):
|
||||
coinbase.vout[0].nValue += spend.tx.vout[spend.n].nValue - 1 # all but one satoshi to fees
|
||||
coinbase.rehash()
|
||||
block = create_block(base_block_hash, coinbase, self.block_time)
|
||||
if (spend != None):
|
||||
tx = CTransaction()
|
||||
tx.vin.append(CTxIn(COutPoint(spend.tx.sha256, spend.n), "", 0xffffffff)) # no signature yet
|
||||
# This copies the java comparison tool testing behavior: the first
|
||||
# txout has a garbage scriptPubKey, "to make sure we're not
|
||||
# pre-verifying too much" (?)
|
||||
tx.vout.append(CTxOut(0, CScript([random.randint(0,255), height & 255])))
|
||||
if script == None:
|
||||
tx.vout.append(CTxOut(1, CScript([OP_TRUE])))
|
||||
else:
|
||||
tx.vout.append(CTxOut(1, script))
|
||||
# Now sign it if necessary
|
||||
scriptSig = ""
|
||||
scriptPubKey = bytearray(spend.tx.vout[spend.n].scriptPubKey)
|
||||
if (scriptPubKey[0] == OP_TRUE): # looks like an anyone-can-spend
|
||||
scriptSig = CScript([OP_TRUE])
|
||||
else:
|
||||
# We have to actually sign it
|
||||
(sighash, err) = SignatureHash(
|
||||
spend.tx.vout[spend.n].scriptPubKey,
|
||||
tx,
|
||||
0,
|
||||
SIGHASH_ALL,
|
||||
spend.tx.vout[spend.n].nValue,
|
||||
SAPLING_BRANCH_ID,
|
||||
)
|
||||
scriptSig = CScript([self.coinbase_key.sign(sighash) + bytes(bytearray([SIGHASH_ALL]))])
|
||||
tx.vin[0].scriptSig = scriptSig
|
||||
# Now add the transaction to the block
|
||||
block = self.add_transactions_to_block(block, [tx])
|
||||
block.solve()
|
||||
self.tip = block
|
||||
self.block_heights[block.sha256] = height
|
||||
self.block_time += 1
|
||||
assert number not in self.blocks
|
||||
self.blocks[number] = block
|
||||
return block
|
||||
|
||||
def get_tests(self):
|
||||
self.genesis_hash = int(self.nodes[0].getbestblockhash(), 16)
|
||||
self.block_heights[self.genesis_hash] = 0
|
||||
spendable_outputs = []
|
||||
|
||||
# save the current tip so it can be spent by a later block
|
||||
def save_spendable_output():
|
||||
spendable_outputs.append(self.tip)
|
||||
|
||||
# get an output that we previous marked as spendable
|
||||
def get_spendable_output():
|
||||
return PreviousSpendableOutput(spendable_outputs.pop(0).vtx[0], 0)
|
||||
|
||||
# returns a test case that asserts that the current tip was accepted
|
||||
def accepted():
|
||||
return TestInstance([[self.tip, True]])
|
||||
|
||||
# returns a test case that asserts that the current tip was rejected
|
||||
def rejected():
|
||||
return TestInstance([[self.tip, False]])
|
||||
|
||||
# move the tip back to a previous block
|
||||
def tip(number):
|
||||
self.tip = self.blocks[number]
|
||||
|
||||
# creates a new block and advances the tip to that block
|
||||
block = self.next_block
|
||||
|
||||
|
||||
# Create a new block
|
||||
block(0)
|
||||
save_spendable_output()
|
||||
yield accepted()
|
||||
|
||||
|
||||
# Now we need that block to mature so we can spend the coinbase.
|
||||
test = TestInstance(sync_every_block=False)
|
||||
for i in range(100):
|
||||
block(1000 + i)
|
||||
test.blocks_and_transactions.append([self.tip, True])
|
||||
save_spendable_output()
|
||||
yield test
|
||||
|
||||
|
||||
# Start by bulding a couple of blocks on top (which output is spent is in parentheses):
|
||||
# genesis -> b1 (0) -> b2 (1)
|
||||
out0 = get_spendable_output()
|
||||
block(1, spend=out0)
|
||||
save_spendable_output()
|
||||
yield accepted()
|
||||
|
||||
out1 = get_spendable_output()
|
||||
block(2, spend=out1)
|
||||
# Inv again, then deliver twice (shouldn't break anything).
|
||||
yield accepted()
|
||||
|
||||
|
||||
# so fork like this:
|
||||
#
|
||||
# genesis -> b1 (0) -> b2 (1)
|
||||
# \-> b3 (1)
|
||||
#
|
||||
# Nothing should happen at this point. We saw b2 first so it takes priority.
|
||||
tip(1)
|
||||
block(3, spend=out1)
|
||||
# Deliver twice (should still not break anything)
|
||||
yield rejected()
|
||||
|
||||
|
||||
# Now we add another block to make the alternative chain longer.
|
||||
#
|
||||
# genesis -> b1 (0) -> b2 (1)
|
||||
# \-> b3 (1) -> b4 (2)
|
||||
out2 = get_spendable_output()
|
||||
block(4, spend=out2)
|
||||
yield accepted()
|
||||
|
||||
|
||||
# ... and back to the first chain.
|
||||
# genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
|
||||
# \-> b3 (1) -> b4 (2)
|
||||
tip(2)
|
||||
block(5, spend=out2)
|
||||
save_spendable_output()
|
||||
yield rejected()
|
||||
|
||||
out3 = get_spendable_output()
|
||||
block(6, spend=out3)
|
||||
yield accepted()
|
||||
|
||||
|
||||
# Try to create a fork that double-spends
|
||||
# genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
|
||||
# \-> b7 (2) -> b8 (4)
|
||||
# \-> b3 (1) -> b4 (2)
|
||||
tip(5)
|
||||
block(7, spend=out2)
|
||||
yield rejected()
|
||||
|
||||
out4 = get_spendable_output()
|
||||
block(8, spend=out4)
|
||||
yield rejected()
|
||||
|
||||
|
||||
# Try to create a block that has too much fee
|
||||
# genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
|
||||
# \-> b9 (4)
|
||||
# \-> b3 (1) -> b4 (2)
|
||||
tip(6)
|
||||
block(9, spend=out4, additional_coinbase_value=1)
|
||||
yield rejected()
|
||||
|
||||
|
||||
# Create a fork that ends in a block with too much fee (the one that causes the reorg)
|
||||
# genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
|
||||
# \-> b10 (3) -> b11 (4)
|
||||
# \-> b3 (1) -> b4 (2)
|
||||
tip(5)
|
||||
block(10, spend=out3)
|
||||
yield rejected()
|
||||
|
||||
block(11, spend=out4, additional_coinbase_value=1)
|
||||
yield rejected()
|
||||
|
||||
|
||||
# Try again, but with a valid fork first
|
||||
# genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
|
||||
# \-> b12 (3) -> b13 (4) -> b14 (5)
|
||||
# (b12 added last)
|
||||
# \-> b3 (1) -> b4 (2)
|
||||
tip(5)
|
||||
b12 = block(12, spend=out3)
|
||||
save_spendable_output()
|
||||
#yield TestInstance([[b12, False]])
|
||||
b13 = block(13, spend=out4)
|
||||
# Deliver the block header for b12, and the block b13.
|
||||
# b13 should be accepted but the tip won't advance until b12 is delivered.
|
||||
yield TestInstance([[CBlockHeader(b12), None], [b13, False]])
|
||||
|
||||
save_spendable_output()
|
||||
out5 = get_spendable_output()
|
||||
# b14 is invalid, but the node won't know that until it tries to connect
|
||||
# Tip still can't advance because b12 is missing
|
||||
block(14, spend=out5, additional_coinbase_value=1)
|
||||
yield rejected()
|
||||
|
||||
yield TestInstance([[b12, True, b13.sha256]]) # New tip should be b13.
|
||||
|
||||
|
||||
# Test that a block with a lot of checksigs is okay
|
||||
lots_of_checksigs = CScript([OP_CHECKSIG] * (1000000 // 50 - 1))
|
||||
tip(13)
|
||||
block(15, spend=out5, script=lots_of_checksigs)
|
||||
yield accepted()
|
||||
|
||||
|
||||
# Test that a block with too many checksigs is rejected
|
||||
out6 = get_spendable_output()
|
||||
too_many_checksigs = CScript([OP_CHECKSIG] * (1000000 // 50))
|
||||
block(16, spend=out6, script=too_many_checksigs)
|
||||
yield rejected()
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
FullBlockTest().main()
|
|
@ -8,18 +8,19 @@ from test_framework.mininode import NodeConn, NetworkThread, CInv, \
|
|||
msg_mempool, msg_getdata, msg_tx, mininode_lock, SAPLING_PROTO_VERSION
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_equal, connect_nodes_bi, fail, \
|
||||
initialize_chain_clean, p2p_port, start_nodes, sync_blocks, sync_mempools
|
||||
p2p_port, start_nodes, sync_blocks, sync_mempools
|
||||
from tx_expiry_helper import TestNode, create_transaction
|
||||
|
||||
|
||||
class TxExpiringSoonTest(BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory " + self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 3)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 3
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def setup_network(self):
|
||||
self.nodes = start_nodes(3, self.options.tmpdir)
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
|
||||
connect_nodes_bi(self.nodes, 0, 1)
|
||||
# We don't connect node 2
|
||||
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
from test_framework.mininode import NodeConn, NetworkThread, \
|
||||
msg_tx, SAPLING_PROTO_VERSION
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import initialize_chain_clean, start_nodes, \
|
||||
p2p_port, assert_equal
|
||||
from test_framework.util import start_nodes, p2p_port, assert_equal
|
||||
from tx_expiry_helper import TestNode, create_transaction
|
||||
|
||||
import time
|
||||
|
@ -15,12 +14,13 @@ import time
|
|||
|
||||
class TxExpiryDoSTest(BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory " + self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 1)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 1
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def setup_network(self):
|
||||
self.nodes = start_nodes(1, self.options.tmpdir)
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
|
||||
|
||||
def run_test(self):
|
||||
test_node = TestNode()
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.authproxy import JSONRPCException
|
||||
from test_framework.util import assert_equal, initialize_chain_clean, \
|
||||
from test_framework.util import assert_equal, \
|
||||
start_node, connect_nodes_bi, wait_and_assert_operationid_status, \
|
||||
get_coinbase_address
|
||||
|
||||
|
@ -13,9 +13,10 @@ from decimal import Decimal
|
|||
|
||||
class PaymentDisclosureTest (BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 4)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 3
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def setup_network(self, split=False):
|
||||
args = ['-debug=zrpcunsafe,paymentdisclosure', '-experimentalfeatures', '-paymentdisclosure', '-txindex=1']
|
||||
|
|
|
@ -12,7 +12,6 @@ from test_framework.util import (
|
|||
assert_equal,
|
||||
bitcoind_processes,
|
||||
connect_nodes_bi,
|
||||
initialize_chain,
|
||||
nuparams,
|
||||
start_node,
|
||||
start_nodes,
|
||||
|
@ -29,12 +28,8 @@ NO_CANOPY = [nuparams(BLOSSOM_BRANCH_ID, 205), nuparams(HEARTWOOD_BRANCH_ID, 21
|
|||
|
||||
class PostHeartwoodRollbackTest (BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain(self.options.tmpdir)
|
||||
|
||||
def setup_nodes(self):
|
||||
return start_nodes(4, self.options.tmpdir, extra_args=[
|
||||
return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[
|
||||
HAS_CANOPY,
|
||||
HAS_CANOPY,
|
||||
NO_CANOPY,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2015 The Bitcoin Core developers
|
||||
# Copyright (c) 2015-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
@ -36,6 +36,10 @@ addnode connect to generic DNS name
|
|||
|
||||
class ProxyTest(BitcoinTestFramework):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 4
|
||||
self.setup_clean_chain = False
|
||||
|
||||
self.have_ipv6 = test_ipv6_local()
|
||||
# Create two proxies on different ports
|
||||
# ... one unauthenticated
|
||||
|
@ -77,7 +81,7 @@ class ProxyTest(BitcoinTestFramework):
|
|||
]
|
||||
if self.have_ipv6:
|
||||
args[3] = ['-listen', '-debug=net', '-debug=proxy', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0', '-noonion']
|
||||
return start_nodes(4, self.options.tmpdir, extra_args=args)
|
||||
return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=args)
|
||||
|
||||
def node_test(self, node, proxies, auth, test_onion=True):
|
||||
rv = []
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
@ -13,18 +13,22 @@
|
|||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.authproxy import JSONRPCException
|
||||
from test_framework.util import initialize_chain_clean, start_node, \
|
||||
from test_framework.util import start_node, \
|
||||
connect_nodes, stop_node, sync_blocks
|
||||
|
||||
import os.path
|
||||
import time
|
||||
|
||||
def calc_usage(blockdir):
|
||||
return sum(os.path.getsize(blockdir+f) for f in os.listdir(blockdir) if os.path.isfile(blockdir+f))/(1024*1024)
|
||||
return sum(os.path.getsize(blockdir+f) for f in os.listdir(blockdir) if os.path.isfile(blockdir+f)) / (1024. * 1024.)
|
||||
|
||||
class PruneTest(BitcoinTestFramework):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 3
|
||||
|
||||
self.utxo = []
|
||||
self.address = ["",""]
|
||||
|
||||
|
@ -46,10 +50,6 @@ class PruneTest(BitcoinTestFramework):
|
|||
self.txouts = self.txouts + script_pubkey
|
||||
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 3)
|
||||
|
||||
def setup_network(self):
|
||||
self.nodes = []
|
||||
self.is_network_split = False
|
||||
|
@ -78,7 +78,7 @@ class PruneTest(BitcoinTestFramework):
|
|||
self.nodes[1].generate(200)
|
||||
sync_blocks(self.nodes[0:2])
|
||||
self.nodes[0].generate(150)
|
||||
# Then mine enough full blocks to create more than 550MB of data
|
||||
# Then mine enough full blocks to create more than 550MiB of data
|
||||
for i in range(645):
|
||||
self.mine_full_block(self.nodes[0], self.address[0])
|
||||
|
||||
|
@ -88,7 +88,7 @@ class PruneTest(BitcoinTestFramework):
|
|||
if not os.path.isfile(self.prunedir+"blk00000.dat"):
|
||||
raise AssertionError("blk00000.dat is missing, pruning too early")
|
||||
print("Success")
|
||||
print("Though we're already using more than 550MB, current usage:", calc_usage(self.prunedir))
|
||||
print("Though we're already using more than 550MiB, current usage:", calc_usage(self.prunedir))
|
||||
print("Mining 25 more blocks should cause the first block file to be pruned")
|
||||
# Pruning doesn't run until we're allocating another chunk, 20 full blocks past the height cutoff will ensure this
|
||||
for i in range(25):
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
|||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.authproxy import JSONRPCException
|
||||
from test_framework.util import assert_equal, initialize_chain_clean, \
|
||||
from test_framework.util import assert_equal, \
|
||||
start_nodes, connect_nodes_bi, assert_raises
|
||||
|
||||
from decimal import Decimal
|
||||
|
@ -18,12 +18,13 @@ from decimal import Decimal
|
|||
# Create one-input, one-output, no-fee transaction:
|
||||
class RawTransactionsTest(BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 3)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 3
|
||||
|
||||
def setup_network(self, split=False):
|
||||
self.nodes = start_nodes(3, self.options.tmpdir)
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
|
||||
|
||||
#connect to a local machine for debugging
|
||||
#url = "http://bitcoinrpc:DP6DvqZtqXarpeNWyN3LZTFchCCyCUuHwNF7E8pX99x1@%s:%d" % ('127.0.0.1', 18232)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
@ -53,6 +53,11 @@ def check_array_result(object_array, to_match, expected, should_not_find = False
|
|||
|
||||
class ReceivedByTest(BitcoinTestFramework):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 4
|
||||
self.setup_clean_chain = False
|
||||
|
||||
def run_test(self):
|
||||
'''
|
||||
listreceivedbyaddress Test
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
@ -8,15 +8,16 @@
|
|||
#
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_equal, initialize_chain_clean, \
|
||||
from test_framework.util import assert_equal, \
|
||||
start_node, stop_node, wait_bitcoinds
|
||||
|
||||
|
||||
class ReindexTest(BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 1)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 1
|
||||
|
||||
def setup_network(self):
|
||||
self.nodes = []
|
||||
|
|
|
@ -8,7 +8,6 @@ from test_framework.authproxy import JSONRPCException
|
|||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import (
|
||||
assert_equal,
|
||||
initialize_chain,
|
||||
start_nodes, get_coinbase_address,
|
||||
wait_and_assert_operationid_status,
|
||||
nuparams, BLOSSOM_BRANCH_ID, HEARTWOOD_BRANCH_ID, CANOPY_BRANCH_ID
|
||||
|
@ -23,12 +22,8 @@ HAS_CANOPY = ['-nurejectoldversions=false',
|
|||
]
|
||||
class RemoveSproutShieldingTest (BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain(self.options.tmpdir)
|
||||
|
||||
def setup_nodes(self):
|
||||
return start_nodes(4, self.options.tmpdir, extra_args=[HAS_CANOPY]*4)
|
||||
return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[HAS_CANOPY] * self.num_nodes)
|
||||
|
||||
def run_test (self):
|
||||
|
||||
|
|
|
@ -11,8 +11,11 @@ from test_framework.test_framework import BitcoinTestFramework
|
|||
from test_framework.util import (
|
||||
check_node,
|
||||
connect_nodes_bi,
|
||||
start_node,
|
||||
sync_blocks,
|
||||
)
|
||||
|
||||
import tempfile
|
||||
from time import sleep
|
||||
|
||||
def check_stopped(i, timeout=10):
|
||||
|
@ -28,6 +31,17 @@ def check_stopped(i, timeout=10):
|
|||
|
||||
class ReorgLimitTest(BitcoinTestFramework):
|
||||
|
||||
def setup_nodes(self):
|
||||
self.log_stderr = tempfile.SpooledTemporaryFile(max_size=2**16)
|
||||
|
||||
nodes = []
|
||||
nodes.append(start_node(0, self.options.tmpdir, stderr=self.log_stderr))
|
||||
nodes.append(start_node(1, self.options.tmpdir))
|
||||
nodes.append(start_node(2, self.options.tmpdir))
|
||||
nodes.append(start_node(3, self.options.tmpdir))
|
||||
|
||||
return nodes
|
||||
|
||||
def run_test(self):
|
||||
assert(self.nodes[0].getblockcount() == 200)
|
||||
assert(self.nodes[2].getblockcount() == 200)
|
||||
|
@ -66,6 +80,7 @@ class ReorgLimitTest(BitcoinTestFramework):
|
|||
assert(self.nodes[0].getblockcount() == 400)
|
||||
assert(self.nodes[2].getblockcount() == 401)
|
||||
|
||||
try:
|
||||
print("Sync nodes to force a reorg")
|
||||
connect_nodes_bi(self.nodes, 0, 2)
|
||||
self.is_network_split = False
|
||||
|
@ -77,6 +92,14 @@ class ReorgLimitTest(BitcoinTestFramework):
|
|||
print("Check Node 0 is no longer running")
|
||||
assert(check_stopped(0))
|
||||
|
||||
# Check that node 0 stopped for the expected reason.
|
||||
self.log_stderr.seek(0)
|
||||
stderr = self.log_stderr.read().decode('utf-8')
|
||||
expected_msg = "A block chain reorganization has been detected that would roll back 100 blocks!"
|
||||
if expected_msg not in stderr:
|
||||
raise AssertionError("Expected error \"" + expected_msg + "\" not found in:\n" + stderr)
|
||||
finally:
|
||||
self.log_stderr.close()
|
||||
# Dummy stop to enable the test to tear down
|
||||
self.nodes[0].stop = lambda: True
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
@ -9,18 +9,17 @@
|
|||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_equal, assert_greater_than, \
|
||||
initialize_chain_clean, start_nodes, connect_nodes_bi
|
||||
start_nodes, connect_nodes_bi
|
||||
|
||||
import struct
|
||||
import binascii
|
||||
import json
|
||||
import io
|
||||
from io import BytesIO
|
||||
from codecs import encode
|
||||
from decimal import Decimal
|
||||
|
||||
from http.client import HTTPConnection
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import http.client
|
||||
import urllib.parse
|
||||
|
||||
def deser_uint256(f):
|
||||
r = 0
|
||||
|
@ -31,7 +30,7 @@ def deser_uint256(f):
|
|||
|
||||
# allows simple http get calls
|
||||
def http_get_call(host, port, path, response_object = 0):
|
||||
conn = HTTPConnection(host, port)
|
||||
conn = http.client.HTTPConnection(host, port)
|
||||
conn.request('GET', path)
|
||||
|
||||
if response_object:
|
||||
|
@ -41,7 +40,7 @@ def http_get_call(host, port, path, response_object = 0):
|
|||
|
||||
# allows simple http post calls with a request body
|
||||
def http_post_call(host, port, path, requestdata = '', response_object = 0):
|
||||
conn = HTTPConnection(host, port)
|
||||
conn = http.client.HTTPConnection(host, port)
|
||||
conn.request('POST', path, requestdata)
|
||||
|
||||
if response_object:
|
||||
|
@ -52,12 +51,13 @@ def http_post_call(host, port, path, requestdata = '', response_object = 0):
|
|||
class RESTTest (BitcoinTestFramework):
|
||||
FORMAT_SEPARATOR = "."
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 3)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 3
|
||||
|
||||
def setup_network(self, split=False):
|
||||
self.nodes = start_nodes(3, self.options.tmpdir)
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
|
||||
connect_nodes_bi(self.nodes,0,1)
|
||||
connect_nodes_bi(self.nodes,1,2)
|
||||
connect_nodes_bi(self.nodes,0,2)
|
||||
|
@ -65,7 +65,7 @@ class RESTTest (BitcoinTestFramework):
|
|||
self.sync_all()
|
||||
|
||||
def run_test(self):
|
||||
url = urlparse(self.nodes[0].url)
|
||||
url = urllib.parse.urlparse(self.nodes[0].url)
|
||||
print("Mining blocks...")
|
||||
|
||||
self.nodes[0].generate(1)
|
||||
|
@ -145,7 +145,7 @@ class RESTTest (BitcoinTestFramework):
|
|||
binaryRequest += struct.pack("i", 0);
|
||||
|
||||
bin_response = http_post_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'bin', binaryRequest)
|
||||
output = io.BytesIO()
|
||||
output = BytesIO()
|
||||
output.write(bin_response)
|
||||
output.seek(0)
|
||||
chainHeight = struct.unpack("i", output.read(4))[0]
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_equal, initialize_chain_clean, \
|
||||
from test_framework.util import assert_equal, \
|
||||
start_nodes, start_node, connect_nodes_bi, bitcoind_processes, \
|
||||
nuparams, OVERWINTER_BRANCH_ID, SAPLING_BRANCH_ID
|
||||
nuparams, sync_blocks, OVERWINTER_BRANCH_ID, SAPLING_BRANCH_ID
|
||||
|
||||
import time
|
||||
|
||||
|
@ -15,15 +15,16 @@ FAKE_OVERWINTER = [nuparams(OVERWINTER_BRANCH_ID, 10), nuparams(SAPLING_BRANCH_I
|
|||
|
||||
class RewindBlockIndexTest (BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 3)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 3
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def setup_network(self, split=False):
|
||||
# Node 0 - Overwinter, then Sprout, then Overwinter again
|
||||
# Node 1 - Sprout
|
||||
# Node 2 - Overwinter
|
||||
self.nodes = start_nodes(3, self.options.tmpdir, extra_args=[
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[
|
||||
FAKE_OVERWINTER,
|
||||
FAKE_SPROUT,
|
||||
FAKE_OVERWINTER,
|
||||
|
@ -47,7 +48,7 @@ class RewindBlockIndexTest (BitcoinTestFramework):
|
|||
print("Mining diverging blocks")
|
||||
block10s = self.nodes[1].generate(1)[0]
|
||||
block10o = self.nodes[2].generate(1)[0]
|
||||
self.sync_all()
|
||||
sync_blocks(self.nodes, allow_different_tips=True)
|
||||
|
||||
assert_equal(self.nodes[0].getbestblockhash(), block10o)
|
||||
assert_equal(self.nodes[1].getbestblockhash(), block10s)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
@ -7,26 +7,37 @@
|
|||
|
||||
# Dependency: python-bitcoinrpc
|
||||
|
||||
from test_framework.authproxy import JSONRPCException
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import (
|
||||
assert_equal,
|
||||
bitcoind_processes,
|
||||
check_json_precision,
|
||||
get_rpc_proxy,
|
||||
initialize_chain,
|
||||
rpc_port,
|
||||
rpc_url,
|
||||
start_nodes,
|
||||
stop_nodes,
|
||||
wait_bitcoinds,
|
||||
)
|
||||
from test_framework.netutil import addr_to_hex, get_bind_addrs, all_interfaces
|
||||
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import tempfile
|
||||
import traceback
|
||||
|
||||
def run_bind_test(tmpdir, allow_ips, connect_to, addresses, expected):
|
||||
|
||||
class RPCBindTest(BitcoinTestFramework):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 1
|
||||
|
||||
def setup_network(self):
|
||||
pass
|
||||
|
||||
def setup_nodes(self):
|
||||
pass
|
||||
|
||||
def run_bind_test(self, allow_ips, connect_to, addresses, expected):
|
||||
'''
|
||||
Start a node with requested rpcallowip and rpcbind parameters,
|
||||
then try to connect, and check if the set of bound addresses
|
||||
|
@ -37,34 +48,33 @@ def run_bind_test(tmpdir, allow_ips, connect_to, addresses, expected):
|
|||
if allow_ips:
|
||||
base_args += ['-rpcallowip=' + x for x in allow_ips]
|
||||
binds = ['-rpcbind='+addr for addr in addresses]
|
||||
nodes = start_nodes(1, tmpdir, [base_args + binds], connect_to)
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [base_args + binds], connect_to)
|
||||
try:
|
||||
pid = bitcoind_processes[0].pid
|
||||
assert_equal(set(get_bind_addrs(pid)), set(expected))
|
||||
finally:
|
||||
stop_nodes(nodes)
|
||||
stop_nodes(self.nodes)
|
||||
wait_bitcoinds()
|
||||
|
||||
def run_allowip_test(tmpdir, allow_ips, rpchost, rpcport):
|
||||
def run_allowip_test(self, allow_ips, rpchost, rpcport):
|
||||
'''
|
||||
Start a node with rpcwallow IP, and request getinfo
|
||||
at a non-localhost IP.
|
||||
'''
|
||||
base_args = ['-disablewallet', '-nolisten'] + ['-rpcallowip='+x for x in allow_ips]
|
||||
nodes = start_nodes(1, tmpdir, [base_args])
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, [base_args])
|
||||
try:
|
||||
# connect to node through non-loopback interface
|
||||
url = "http://rt:rt@%s:%d" % (rpchost, rpcport,)
|
||||
node = get_rpc_proxy(url, 1)
|
||||
node = get_rpc_proxy(rpc_url(0, "%s:%d" % (rpchost, rpcport)), 0)
|
||||
node.getinfo()
|
||||
finally:
|
||||
node = None # make sure connection will be garbage collected and closed
|
||||
stop_nodes(nodes)
|
||||
stop_nodes(self.nodes)
|
||||
wait_bitcoinds()
|
||||
|
||||
|
||||
def run_test(tmpdir):
|
||||
assert(sys.platform.startswith('linux')) # due to OS-specific network stats queries, this test works only on Linux
|
||||
def run_test(self):
|
||||
# due to OS-specific network stats queries, this test works only on Linux
|
||||
assert(sys.platform.startswith('linux'))
|
||||
# find the first non-loopback interface for testing
|
||||
non_loopback_ip = None
|
||||
for name,ip in all_interfaces():
|
||||
|
@ -78,82 +88,37 @@ def run_test(tmpdir):
|
|||
defaultport = rpc_port(0)
|
||||
|
||||
# check default without rpcallowip (IPv4 and IPv6 localhost)
|
||||
run_bind_test(tmpdir, None, '127.0.0.1', [],
|
||||
self.run_bind_test(None, '127.0.0.1', [],
|
||||
[('127.0.0.1', defaultport), ('::1', defaultport)])
|
||||
# check default with rpcallowip (IPv6 any)
|
||||
run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1', [],
|
||||
self.run_bind_test(['127.0.0.1'], '127.0.0.1', [],
|
||||
[('::0', defaultport)])
|
||||
# check only IPv4 localhost (explicit)
|
||||
run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1', ['127.0.0.1'],
|
||||
self.run_bind_test(['127.0.0.1'], '127.0.0.1', ['127.0.0.1'],
|
||||
[('127.0.0.1', defaultport)])
|
||||
# check only IPv4 localhost (explicit) with alternative port
|
||||
run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171'],
|
||||
self.run_bind_test(['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171'],
|
||||
[('127.0.0.1', 32171)])
|
||||
# check only IPv4 localhost (explicit) with multiple alternative ports on same host
|
||||
run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171', '127.0.0.1:32172'],
|
||||
self.run_bind_test(['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171', '127.0.0.1:32172'],
|
||||
[('127.0.0.1', 32171), ('127.0.0.1', 32172)])
|
||||
# check only IPv6 localhost (explicit)
|
||||
run_bind_test(tmpdir, ['[::1]'], '[::1]', ['[::1]'],
|
||||
self.run_bind_test(['[::1]'], '[::1]', ['[::1]'],
|
||||
[('::1', defaultport)])
|
||||
# check both IPv4 and IPv6 localhost (explicit)
|
||||
run_bind_test(tmpdir, ['127.0.0.1'], '127.0.0.1', ['127.0.0.1', '[::1]'],
|
||||
self.run_bind_test(['127.0.0.1'], '127.0.0.1', ['127.0.0.1', '[::1]'],
|
||||
[('127.0.0.1', defaultport), ('::1', defaultport)])
|
||||
# check only non-loopback interface
|
||||
run_bind_test(tmpdir, [non_loopback_ip], non_loopback_ip, [non_loopback_ip],
|
||||
self.run_bind_test([non_loopback_ip], non_loopback_ip, [non_loopback_ip],
|
||||
[(non_loopback_ip, defaultport)])
|
||||
|
||||
# Check that with invalid rpcallowip, we are denied
|
||||
run_allowip_test(tmpdir, [non_loopback_ip], non_loopback_ip, defaultport)
|
||||
self.run_allowip_test([non_loopback_ip], non_loopback_ip, defaultport)
|
||||
try:
|
||||
run_allowip_test(tmpdir, ['1.1.1.1'], non_loopback_ip, defaultport)
|
||||
self.run_allowip_test(['1.1.1.1'], non_loopback_ip, defaultport)
|
||||
assert(not 'Connection not denied by rpcallowip as expected')
|
||||
except ValueError:
|
||||
except JSONRPCException:
|
||||
pass
|
||||
|
||||
def main():
|
||||
import optparse
|
||||
|
||||
parser = optparse.OptionParser(usage="%prog [options]")
|
||||
parser.add_option("--nocleanup", dest="nocleanup", default=False, action="store_true",
|
||||
help="Leave bitcoinds and test.* datadir on exit or error")
|
||||
parser.add_option("--srcdir", dest="srcdir", default="../../src",
|
||||
help="Source directory containing bitcoind/bitcoin-cli (default: %default%)")
|
||||
parser.add_option("--tmpdir", dest="tmpdir", default=tempfile.mkdtemp(prefix="test"),
|
||||
help="Root directory for datadirs")
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
os.environ['PATH'] = options.srcdir+":"+os.environ['PATH']
|
||||
|
||||
check_json_precision()
|
||||
|
||||
success = False
|
||||
try:
|
||||
print("Initializing test directory "+options.tmpdir)
|
||||
if not os.path.isdir(options.tmpdir):
|
||||
os.makedirs(options.tmpdir)
|
||||
initialize_chain(options.tmpdir)
|
||||
|
||||
run_test(options.tmpdir)
|
||||
|
||||
success = True
|
||||
|
||||
except AssertionError as e:
|
||||
print("Assertion failed: "+e.message)
|
||||
except Exception as e:
|
||||
print("Unexpected exception caught during testing: "+str(e))
|
||||
traceback.print_tb(sys.exc_info()[2])
|
||||
|
||||
if not options.nocleanup:
|
||||
print("Cleaning up")
|
||||
wait_bitcoinds()
|
||||
shutil.rmtree(options.tmpdir)
|
||||
|
||||
if success:
|
||||
print("Tests successful")
|
||||
sys.exit(0)
|
||||
else:
|
||||
print("Failed")
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
RPCBindTest().main()
|
||||
|
|
|
@ -28,25 +28,29 @@ length computation (40b5d5e3ea4b602c34c4efaba0b9f6171dddfef5) corrects the issue
|
|||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import (assert_equal, assert_true,
|
||||
initialize_chain_clean, start_nodes, start_node, connect_nodes_bi,
|
||||
assert_start_raises_init_error,
|
||||
start_nodes, start_node, connect_nodes_bi,
|
||||
bitcoind_processes,
|
||||
nuparams, OVERWINTER_BRANCH_ID, SAPLING_BRANCH_ID)
|
||||
|
||||
import re
|
||||
import logging
|
||||
import sys
|
||||
|
||||
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO, stream=sys.stdout)
|
||||
|
||||
HAS_SAPLING = [nuparams(OVERWINTER_BRANCH_ID, 10), nuparams(SAPLING_BRANCH_ID, 15)]
|
||||
NO_SAPLING = [nuparams(OVERWINTER_BRANCH_ID, 10), nuparams(SAPLING_BRANCH_ID, 150)]
|
||||
|
||||
class SaplingRewindTest(BitcoinTestFramework):
|
||||
def setup_chain(self):
|
||||
logging.info("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 4)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 3
|
||||
self.setup_clean_chain = True
|
||||
|
||||
# This mirrors how the network was setup in the bash test
|
||||
def setup_network(self, split=False):
|
||||
logging.info("Initializing the network in "+self.options.tmpdir)
|
||||
self.nodes = start_nodes(3, self.options.tmpdir, extra_args=[
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[
|
||||
HAS_SAPLING, # The first two nodes have a correct view of the network,
|
||||
HAS_SAPLING, # the third will rewind after upgrading.
|
||||
NO_SAPLING
|
||||
|
@ -91,35 +95,15 @@ class SaplingRewindTest(BitcoinTestFramework):
|
|||
|
||||
# Restart the nodes, reconnect, and sync the network. This succeeds if "-reindex" is passed.
|
||||
logging.info("Reconnecting the network...")
|
||||
try:
|
||||
|
||||
# expect an exception; the node will refuse to fully start because its last point of
|
||||
# agreement with the rest of the network was prior to the network upgrade activation
|
||||
self.nodes[2] = start_node(2, self.options.tmpdir, extra_args=HAS_SAPLING) # + ["-reindex"])
|
||||
except:
|
||||
logpath = self.options.tmpdir + "/node2/regtest/debug.log"
|
||||
found = False
|
||||
with open(logpath, 'r', encoding='utf8') as f:
|
||||
for line in f:
|
||||
# Search for the rollback message in the debug log, and ensure that it has the
|
||||
# correct expected rollback length.
|
||||
m = re.search(r'roll back ([0-9]+)', line)
|
||||
if m is None:
|
||||
continue
|
||||
elif m.group(1) == "120":
|
||||
found = True
|
||||
break
|
||||
else:
|
||||
raise AssertionError("Incorrect rollback length %s found, expected 120." %(m.group(1)))
|
||||
|
||||
if not found:
|
||||
raise AssertionError("Expected rollback message not found in log file.")
|
||||
assert_start_raises_init_error(2, self.options.tmpdir, HAS_SAPLING, "roll back 120")
|
||||
|
||||
# restart the node with -reindex to allow the test to complete gracefully,
|
||||
# otherwise the node shutdown call in test cleanup will throw an error since
|
||||
# it can't connect
|
||||
self.nodes[2] = start_node(2, self.options.tmpdir, extra_args=NO_SAPLING + ["-reindex"])
|
||||
else:
|
||||
raise AssertionError("Expected node to halt due to excessive rewind length.")
|
||||
|
||||
if __name__ == '__main__':
|
||||
SaplingRewindTest().main()
|
||||
|
|
|
@ -1,250 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
#
|
||||
|
||||
'''
|
||||
Test notes:
|
||||
This test uses the script_valid and script_invalid tests from the unittest
|
||||
framework to do end-to-end testing where we compare that two nodes agree on
|
||||
whether blocks containing a given test script are valid.
|
||||
|
||||
We generally ignore the script flags associated with each test (since we lack
|
||||
the precision to test each script using those flags in this framework), but
|
||||
for tests with SCRIPT_VERIFY_P2SH, we can use a block time after the BIP16
|
||||
switchover date to try to test with that flag enabled (and for tests without
|
||||
that flag, we use a block time before the switchover date).
|
||||
|
||||
NOTE: This test is very slow and may take more than 40 minutes to run.
|
||||
'''
|
||||
|
||||
from test_framework.test_framework import ComparisonTestFramework
|
||||
from test_framework.comptool import TestInstance, TestManager
|
||||
from test_framework.mininode import NetworkThread
|
||||
from test_framework.blocktools import create_block, create_coinbase, create_transaction
|
||||
from test_framework.script import CScript, CScriptOp, CScriptNum, OPCODES_BY_NAME
|
||||
|
||||
import os
|
||||
import json
|
||||
|
||||
script_valid_file = "../../src/test/data/script_valid.json"
|
||||
script_invalid_file = "../../src/test/data/script_invalid.json"
|
||||
|
||||
# Pass in a set of json files to open.
|
||||
class ScriptTestFile(object):
|
||||
|
||||
def __init__(self, files):
|
||||
self.files = files
|
||||
self.index = -1
|
||||
self.data = []
|
||||
|
||||
def load_files(self):
|
||||
for f in self.files:
|
||||
self.data.extend(json.loads(open(os.path.dirname(os.path.abspath(__file__))+"/"+f).read()))
|
||||
|
||||
# Skip over records that are not long enough to be tests
|
||||
def get_records(self):
|
||||
while (self.index < len(self.data)):
|
||||
if len(self.data[self.index]) >= 3:
|
||||
yield self.data[self.index]
|
||||
self.index += 1
|
||||
|
||||
|
||||
# Helper for parsing the flags specified in the .json files
|
||||
SCRIPT_VERIFY_NONE = 0
|
||||
SCRIPT_VERIFY_P2SH = 1
|
||||
SCRIPT_VERIFY_STRICTENC = 1 << 1
|
||||
SCRIPT_VERIFY_LOW_S = 1 << 3
|
||||
SCRIPT_VERIFY_NULLDUMMY = 1 << 4
|
||||
SCRIPT_VERIFY_SIGPUSHONLY = 1 << 5
|
||||
SCRIPT_VERIFY_MINIMALDATA = 1 << 6
|
||||
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS = 1 << 7
|
||||
SCRIPT_VERIFY_CLEANSTACK = 1 << 8
|
||||
|
||||
flag_map = {
|
||||
"": SCRIPT_VERIFY_NONE,
|
||||
"NONE": SCRIPT_VERIFY_NONE,
|
||||
"P2SH": SCRIPT_VERIFY_P2SH,
|
||||
"STRICTENC": SCRIPT_VERIFY_STRICTENC,
|
||||
"LOW_S": SCRIPT_VERIFY_LOW_S,
|
||||
"NULLDUMMY": SCRIPT_VERIFY_NULLDUMMY,
|
||||
"SIGPUSHONLY": SCRIPT_VERIFY_SIGPUSHONLY,
|
||||
"MINIMALDATA": SCRIPT_VERIFY_MINIMALDATA,
|
||||
"DISCOURAGE_UPGRADABLE_NOPS": SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS,
|
||||
"CLEANSTACK": SCRIPT_VERIFY_CLEANSTACK,
|
||||
}
|
||||
|
||||
def ParseScriptFlags(flag_string):
|
||||
flags = 0
|
||||
for x in flag_string.split(","):
|
||||
if x in flag_map:
|
||||
flags |= flag_map[x]
|
||||
else:
|
||||
print("Error: unrecognized script flag: ", x)
|
||||
return flags
|
||||
|
||||
'''
|
||||
Given a string that is a scriptsig or scriptpubkey from the .json files above,
|
||||
convert it to a CScript()
|
||||
'''
|
||||
# Replicates behavior from core_read.cpp
|
||||
def ParseScript(json_script):
|
||||
script = json_script.split(" ")
|
||||
parsed_script = CScript()
|
||||
for x in script:
|
||||
if len(x) == 0:
|
||||
# Empty string, ignore.
|
||||
pass
|
||||
elif x.isdigit() or (len(x) >= 1 and x[0] == "-" and x[1:].isdigit()):
|
||||
# Number
|
||||
n = int(x, 0)
|
||||
if (n == -1) or (n >= 1 and n <= 16):
|
||||
parsed_script = CScript(bytes(parsed_script) + bytes(CScript([n])))
|
||||
else:
|
||||
parsed_script += CScriptNum(int(x, 0))
|
||||
elif x.startswith("0x"):
|
||||
# Raw hex data, inserted NOT pushed onto stack:
|
||||
for i in range(2, len(x), 2):
|
||||
parsed_script = CScript(bytes(parsed_script) + bytes(chr(int(x[i:i+2],16))))
|
||||
elif x.startswith("'") and x.endswith("'") and len(x) >= 2:
|
||||
# Single-quoted string, pushed as data.
|
||||
parsed_script += CScript([x[1:-1]])
|
||||
else:
|
||||
# opcode, e.g. OP_ADD or ADD:
|
||||
tryopname = "OP_" + x
|
||||
if tryopname in OPCODES_BY_NAME:
|
||||
parsed_script += CScriptOp(OPCODES_BY_NAME["OP_" + x])
|
||||
else:
|
||||
print("ParseScript: error parsing '%s'" % x)
|
||||
return ""
|
||||
return parsed_script
|
||||
|
||||
class TestBuilder(object):
|
||||
def create_credit_tx(self, scriptPubKey):
|
||||
# self.tx1 is a coinbase transaction, modeled after the one created by script_tests.cpp
|
||||
# This allows us to reuse signatures created in the unit test framework.
|
||||
self.tx1 = create_coinbase() # this has a bip34 scriptsig,
|
||||
self.tx1.vin[0].scriptSig = CScript([0, 0]) # but this matches the unit tests
|
||||
self.tx1.vout[0].nValue = 0
|
||||
self.tx1.vout[0].scriptPubKey = scriptPubKey
|
||||
self.tx1.rehash()
|
||||
def create_spend_tx(self, scriptSig):
|
||||
self.tx2 = create_transaction(self.tx1, 0, CScript(), 0)
|
||||
self.tx2.vin[0].scriptSig = scriptSig
|
||||
self.tx2.vout[0].scriptPubKey = CScript()
|
||||
self.tx2.rehash()
|
||||
def rehash(self):
|
||||
self.tx1.rehash()
|
||||
self.tx2.rehash()
|
||||
|
||||
# This test uses the (default) two nodes provided by ComparisonTestFramework,
|
||||
# specified on the command line with --testbinary and --refbinary.
|
||||
# See comptool.py
|
||||
class ScriptTest(ComparisonTestFramework):
|
||||
|
||||
def run_test(self):
|
||||
# Set up the comparison tool TestManager
|
||||
test = TestManager(self, self.options.tmpdir)
|
||||
test.add_all_connections(self.nodes)
|
||||
|
||||
# Load scripts
|
||||
self.scripts = ScriptTestFile([script_valid_file, script_invalid_file])
|
||||
self.scripts.load_files()
|
||||
|
||||
# Some variables we re-use between test instances (to build blocks)
|
||||
self.tip = None
|
||||
self.block_time = None
|
||||
|
||||
NetworkThread().start() # Start up network handling in another thread
|
||||
test.run()
|
||||
|
||||
def generate_test_instance(self, pubkeystring, scriptsigstring):
|
||||
scriptpubkey = ParseScript(pubkeystring)
|
||||
scriptsig = ParseScript(scriptsigstring)
|
||||
|
||||
test = TestInstance(sync_every_block=False)
|
||||
test_build = TestBuilder()
|
||||
test_build.create_credit_tx(scriptpubkey)
|
||||
test_build.create_spend_tx(scriptsig)
|
||||
test_build.rehash()
|
||||
|
||||
block = create_block(self.tip, test_build.tx1, self.block_time)
|
||||
self.block_time += 1
|
||||
block.solve()
|
||||
self.tip = block.sha256
|
||||
test.blocks_and_transactions = [[block, True]]
|
||||
|
||||
for i in range(100):
|
||||
block = create_block(self.tip, create_coinbase(), self.block_time)
|
||||
self.block_time += 1
|
||||
block.solve()
|
||||
self.tip = block.sha256
|
||||
test.blocks_and_transactions.append([block, True])
|
||||
|
||||
block = create_block(self.tip, create_coinbase(), self.block_time)
|
||||
self.block_time += 1
|
||||
block.vtx.append(test_build.tx2)
|
||||
block.hashMerkleRoot = block.calc_merkle_root()
|
||||
block.rehash()
|
||||
block.solve()
|
||||
test.blocks_and_transactions.append([block, None])
|
||||
return test
|
||||
|
||||
# This generates the tests for TestManager.
|
||||
def get_tests(self):
|
||||
self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0)
|
||||
self.block_time = 1333230000 # before the BIP16 switchover
|
||||
|
||||
'''
|
||||
Create a new block with an anyone-can-spend coinbase
|
||||
'''
|
||||
block = create_block(self.tip, create_coinbase(), self.block_time)
|
||||
self.block_time += 1
|
||||
block.solve()
|
||||
self.tip = block.sha256
|
||||
yield TestInstance(objects=[[block, True]])
|
||||
|
||||
'''
|
||||
Build out to 100 blocks total, maturing the coinbase.
|
||||
'''
|
||||
test = TestInstance(objects=[], sync_every_block=False, sync_every_tx=False)
|
||||
for i in range(100):
|
||||
b = create_block(self.tip, create_coinbase(), self.block_time)
|
||||
b.solve()
|
||||
test.blocks_and_transactions.append([b, True])
|
||||
self.tip = b.sha256
|
||||
self.block_time += 1
|
||||
yield test
|
||||
|
||||
''' Iterate through script tests. '''
|
||||
counter = 0
|
||||
for script_test in self.scripts.get_records():
|
||||
''' Reset the blockchain to genesis block + 100 blocks. '''
|
||||
if self.nodes[0].getblockcount() > 101:
|
||||
self.nodes[0].invalidateblock(self.nodes[0].getblockhash(102))
|
||||
self.nodes[1].invalidateblock(self.nodes[1].getblockhash(102))
|
||||
|
||||
self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0)
|
||||
|
||||
[scriptsig, scriptpubkey, flags] = script_test[0:3]
|
||||
flags = ParseScriptFlags(flags)
|
||||
|
||||
# We can use block time to determine whether the nodes should be
|
||||
# enforcing BIP16.
|
||||
#
|
||||
# We intentionally let the block time grow by 1 each time.
|
||||
# This forces the block hashes to differ between tests, so that
|
||||
# a call to invalidateblock doesn't interfere with a later test.
|
||||
if (flags & SCRIPT_VERIFY_P2SH):
|
||||
self.block_time = 1333238400 + counter # Advance to enforcing BIP16
|
||||
else:
|
||||
self.block_time = 1333230000 + counter # Before the BIP16 switchover
|
||||
|
||||
print("Script test: [%s]" % script_test)
|
||||
|
||||
yield self.generate_test_instance(scriptpubkey, scriptsig)
|
||||
counter += 1
|
||||
|
||||
if __name__ == '__main__':
|
||||
ScriptTest().main()
|
|
@ -8,21 +8,21 @@ from test_framework.test_framework import BitcoinTestFramework
|
|||
from test_framework.util import (
|
||||
assert_equal,
|
||||
get_coinbase_address,
|
||||
initialize_chain_clean,
|
||||
start_nodes,
|
||||
wait_and_assert_operationid_status,
|
||||
)
|
||||
|
||||
|
||||
class ShorterBlockTimes(BitcoinTestFramework):
|
||||
def setup_nodes(self):
|
||||
return start_nodes(4, self.options.tmpdir, [[
|
||||
'-nuparams=2bb40e60:106', # Blossom
|
||||
]] * 4)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 4
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory " + self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 4)
|
||||
def setup_nodes(self):
|
||||
return start_nodes(self.num_nodes, self.options.tmpdir, [[
|
||||
'-nuparams=2bb40e60:106', # Blossom
|
||||
]] * self.num_nodes)
|
||||
|
||||
def run_test(self):
|
||||
print("Mining blocks...")
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2015 The Bitcoin Core developers
|
||||
# Copyright (c) 2015-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_equal, initialize_chain_clean, \
|
||||
start_nodes
|
||||
from test_framework.util import assert_equal, start_nodes
|
||||
|
||||
|
||||
class SignRawTransactionsTest(BitcoinTestFramework):
|
||||
"""Tests transaction signing via RPC command "signrawtransaction"."""
|
||||
|
||||
def setup_chain(self):
|
||||
print('Initializing test directory ' + self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 1)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 1
|
||||
|
||||
def setup_network(self, split=False):
|
||||
self.nodes = start_nodes(1, self.options.tmpdir)
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
|
||||
self.is_network_split = False
|
||||
|
||||
def successful_signing_test(self):
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014-2015 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
@ -112,7 +112,7 @@ def check_estimates(node, fees_seen, max_invalid, print_estimates = True):
|
|||
print([str(all_estimates[e-1]) for e in [1,2,3,6,15,25]])
|
||||
delta = 1.0e-6 # account for rounding error
|
||||
last_e = max(fees_seen)
|
||||
for e in filter(lambda x: x >= 0, all_estimates):
|
||||
for e in [x for x in all_estimates if x >= 0]:
|
||||
# Estimates should be within the bounds of what transactions fees actually were:
|
||||
if float(e)+delta < min(fees_seen) or float(e)-delta > max(fees_seen):
|
||||
raise AssertionError("Estimated fee (%f) out of range (%f,%f)"
|
||||
|
@ -142,6 +142,11 @@ def check_estimates(node, fees_seen, max_invalid, print_estimates = True):
|
|||
|
||||
class EstimateFeeTest(BitcoinTestFramework):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 3
|
||||
self.setup_clean_chain = False
|
||||
|
||||
def setup_network(self):
|
||||
'''
|
||||
We'll setup the network to have 3 nodes that all mine with different parameters.
|
||||
|
@ -215,7 +220,7 @@ class EstimateFeeTest(BitcoinTestFramework):
|
|||
from_index = random.randint(1,2)
|
||||
(txhex, fee) = small_txpuzzle_randfee(self.nodes[from_index], self.confutxo,
|
||||
self.memutxo, Decimal("0.005"), min_fee, min_fee)
|
||||
tx_kbytes = (len(txhex)/2)/1000.0
|
||||
tx_kbytes = (len(txhex) // 2) / 1000.0
|
||||
self.fees_per_kb.append(float(fee)/tx_kbytes)
|
||||
sync_mempools(self.nodes[0:3],.1)
|
||||
mined = mining_node.getblock(mining_node.generate(1)[0],True)["tx"]
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
from decimal import Decimal
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.util import assert_equal, assert_true, get_coinbase_address, \
|
||||
initialize_chain_clean, start_nodes, wait_and_assert_operationid_status, \
|
||||
start_nodes, wait_and_assert_operationid_status, \
|
||||
wait_and_assert_operationid_status_result
|
||||
|
||||
SAPLING_ADDR = 'zregtestsapling1ssqj3f3majnl270985gqcdqedd9t4nlttjqskccwevj2v20sc25deqspv3masufnwcdy67cydyy'
|
||||
|
@ -49,9 +49,14 @@ def check_migration_status(node, destination_address, migration_state):
|
|||
|
||||
|
||||
class SproutSaplingMigration(BitcoinTestFramework):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 4
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def setup_nodes(self):
|
||||
extra_args = [[
|
||||
]] * 4
|
||||
]] * self.num_nodes
|
||||
# Add migration parameters to nodes[0]
|
||||
extra_args[0] = extra_args[0] + [
|
||||
'-migration',
|
||||
|
@ -60,11 +65,7 @@ class SproutSaplingMigration(BitcoinTestFramework):
|
|||
]
|
||||
assert_equal(3, len(extra_args[0]))
|
||||
assert_equal(0, len(extra_args[1]))
|
||||
return start_nodes(4, self.options.tmpdir, extra_args)
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory " + self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 4)
|
||||
return start_nodes(self.num_nodes, self.options.tmpdir, extra_args)
|
||||
|
||||
def run_migration_test(self, node, sproutAddr, saplingAddr, target_height):
|
||||
# Make sure we are in a good state to run the test
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# bignum.py
|
||||
#
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#!/usr/bin/env python3
|
||||
# BlockStore: a helper class that keeps a map of blocks and implements
|
||||
# helper functions for responding to getheaders and getdata,
|
||||
# and for constructing a getheaders message
|
||||
|
@ -6,13 +7,14 @@
|
|||
from .mininode import CBlock, CBlockHeader, CBlockLocator, CTransaction, msg_block, msg_headers, msg_tx
|
||||
|
||||
import sys
|
||||
import io
|
||||
import dbm.dumb as dbm
|
||||
from io import BytesIO
|
||||
import dbm.ndbm
|
||||
|
||||
class BlockStore():
|
||||
def __init__(self, datadir):
|
||||
self.blockDB = dbm.open(datadir + "/blocks", 'c')
|
||||
self.blockDB = dbm.ndbm.open(datadir + "/blocks", 'c')
|
||||
self.currentBlock = 0
|
||||
self.headers_map = dict()
|
||||
|
||||
def close(self):
|
||||
self.blockDB.close()
|
||||
|
@ -23,30 +25,36 @@ class BlockStore():
|
|||
serialized_block = self.blockDB[repr(blockhash)]
|
||||
except KeyError:
|
||||
return None
|
||||
f = io.BytesIO(serialized_block)
|
||||
f = BytesIO(serialized_block)
|
||||
ret = CBlock()
|
||||
ret.deserialize(f)
|
||||
ret.calc_sha256()
|
||||
return ret
|
||||
|
||||
def get_header(self, blockhash):
|
||||
try:
|
||||
return self.headers_map[blockhash]
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
# Note: this pulls full blocks out of the database just to retrieve
|
||||
# the headers -- perhaps we could keep a separate data structure
|
||||
# to avoid this overhead.
|
||||
def headers_for(self, locator, hash_stop, current_tip=None):
|
||||
if current_tip is None:
|
||||
current_tip = self.currentBlock
|
||||
current_block = self.get(current_tip)
|
||||
if current_block is None:
|
||||
current_block_header = self.get_header(current_tip)
|
||||
if current_block_header is None:
|
||||
return None
|
||||
|
||||
response = msg_headers()
|
||||
headersList = [ CBlockHeader(current_block) ]
|
||||
headersList = [ current_block_header ]
|
||||
maxheaders = 2000
|
||||
while (headersList[0].sha256 not in locator.vHave):
|
||||
prevBlockHash = headersList[0].hashPrevBlock
|
||||
prevBlock = self.get(prevBlockHash)
|
||||
if prevBlock is not None:
|
||||
headersList.insert(0, CBlockHeader(prevBlock))
|
||||
prevBlockHeader = self.get_header(prevBlockHash)
|
||||
if prevBlockHeader is not None:
|
||||
headersList.insert(0, prevBlockHeader)
|
||||
else:
|
||||
break
|
||||
headersList = headersList[:maxheaders] # truncate if we have too many
|
||||
|
@ -64,6 +72,10 @@ class BlockStore():
|
|||
except TypeError as e:
|
||||
print("Unexpected error: ", sys.exc_info()[0], e.args)
|
||||
self.currentBlock = block.sha256
|
||||
self.headers_map[block.sha256] = CBlockHeader(block)
|
||||
|
||||
def add_header(self, header):
|
||||
self.headers_map[header.sha256] = header
|
||||
|
||||
def get_blocks(self, inv):
|
||||
responses = []
|
||||
|
@ -96,7 +108,7 @@ class BlockStore():
|
|||
|
||||
class TxStore(object):
|
||||
def __init__(self, datadir):
|
||||
self.txDB = dbm.open(datadir + "/transactions", 'c')
|
||||
self.txDB = dbm.ndbm.open(datadir + "/transactions", 'c')
|
||||
|
||||
def close(self):
|
||||
self.txDB.close()
|
||||
|
@ -107,7 +119,7 @@ class TxStore(object):
|
|||
serialized_tx = self.txDB[repr(txhash)]
|
||||
except KeyError:
|
||||
return None
|
||||
f = io.BytesIO(serialized_tx)
|
||||
f = BytesIO(serialized_tx)
|
||||
ret = CTransaction()
|
||||
ret.deserialize(f)
|
||||
ret.calc_sha256()
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#!/usr/bin/env python3
|
||||
# blocktools.py - utilities for manipulating blocks and transactions
|
||||
#
|
||||
# Copyright (c) 2015-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
#
|
||||
|
||||
from .mininode import CBlock, CTransaction, CTxIn, CTxOut, COutPoint
|
||||
from .script import CScript, OP_0, OP_EQUAL, OP_HASH160
|
||||
from .script import CScript, OP_0, OP_EQUAL, OP_HASH160, OP_TRUE, OP_CHECKSIG
|
||||
|
||||
# Create a block (with regtest difficulty)
|
||||
def create_block(hashprev, coinbase, nTime=None, nBits=None, hashFinalSaplingRoot=None):
|
||||
|
@ -44,19 +44,21 @@ def serialize_script_num(value):
|
|||
r[-1] |= 0x80
|
||||
return r
|
||||
|
||||
counter=1
|
||||
# Create an anyone-can-spend coinbase transaction, assuming no miner fees
|
||||
def create_coinbase(heightAdjust = 0):
|
||||
global counter
|
||||
# Create a coinbase transaction, assuming no miner fees.
|
||||
# If pubkey is passed in, the coinbase output will be a P2PK output;
|
||||
# otherwise an anyone-can-spend output.
|
||||
def create_coinbase(height, pubkey = None):
|
||||
coinbase = CTransaction()
|
||||
coinbase.vin.append(CTxIn(COutPoint(0, 0xffffffff),
|
||||
CScript([counter+heightAdjust, OP_0]), 0xffffffff))
|
||||
counter += 1
|
||||
CScript([height, OP_0]), 0xffffffff))
|
||||
coinbaseoutput = CTxOut()
|
||||
coinbaseoutput.nValue = int(12.5*100000000)
|
||||
halvings = int((counter+heightAdjust)/150) # regtest
|
||||
halvings = int(height/150) # regtest
|
||||
coinbaseoutput.nValue >>= halvings
|
||||
coinbaseoutput.scriptPubKey = b""
|
||||
if (pubkey != None):
|
||||
coinbaseoutput.scriptPubKey = CScript([pubkey, OP_CHECKSIG])
|
||||
else:
|
||||
coinbaseoutput.scriptPubKey = CScript([OP_TRUE])
|
||||
coinbase.vout = [ coinbaseoutput ]
|
||||
if halvings == 0: # regtest
|
||||
froutput = CTxOut()
|
||||
|
|
|
@ -1,12 +1,24 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2015-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
#
|
||||
|
||||
from .mininode import CBlock, CTransaction, CInv, NodeConn, NodeConnCB, \
|
||||
msg_inv, msg_getheaders, msg_ping, msg_mempool, mininode_lock, MAX_INV_SZ
|
||||
from .blockstore import BlockStore, TxStore
|
||||
from .mininode import (
|
||||
CBlock,
|
||||
CBlockHeader,
|
||||
CTransaction,
|
||||
CInv,
|
||||
msg_block,
|
||||
msg_getheaders,
|
||||
msg_inv,
|
||||
msg_mempool,
|
||||
msg_ping,
|
||||
mininode_lock,
|
||||
MAX_INV_SZ,
|
||||
NodeConn,
|
||||
NodeConnCB,
|
||||
)
|
||||
from .util import p2p_port
|
||||
|
||||
import time
|
||||
|
@ -123,12 +135,19 @@ class TestNode(NodeConnCB):
|
|||
# Instances of these are generated by the test generator, and fed into the
|
||||
# comptool.
|
||||
#
|
||||
# "blocks_and_transactions" should be an array of [obj, True/False/None]:
|
||||
# - obj is either a CBlock or a CTransaction, and
|
||||
# "blocks_and_transactions" should be an array of
|
||||
# [obj, True/False/None, hash/None]:
|
||||
# - obj is either a CBlock, CBlockHeader, or a CTransaction, and
|
||||
# - the second value indicates whether the object should be accepted
|
||||
# into the blockchain or mempool (for tests where we expect a certain
|
||||
# answer), or "None" if we don't expect a certain answer and are just
|
||||
# comparing the behavior of the nodes being tested.
|
||||
# - the third value is the hash to test the tip against (if None or omitted,
|
||||
# use the hash of the block)
|
||||
# - NOTE: if a block header, no test is performed; instead the header is
|
||||
# just added to the block_store. This is to facilitate block delivery
|
||||
# when communicating with headers-first clients (when withholding an
|
||||
# intermediate block).
|
||||
# sync_every_block: if True, then each block will be inv'ed, synced, and
|
||||
# nodes will be tested based on the outcome for the block. If False,
|
||||
# then inv's accumulate until all blocks are processed (or max inv size
|
||||
|
@ -195,7 +214,6 @@ class TestManager(object):
|
|||
if not wait_until(blocks_requested, attempts=20*num_blocks):
|
||||
# print [ c.cb.block_request_map for c in self.connections ]
|
||||
raise AssertionError("Not all nodes requested block")
|
||||
# --> Answer request (we did this inline!)
|
||||
|
||||
# Send getheaders message
|
||||
[ c.cb.send_getheaders() for c in self.connections ]
|
||||
|
@ -218,7 +236,6 @@ class TestManager(object):
|
|||
if not wait_until(transaction_requested, attempts=20*num_events):
|
||||
# print [ c.cb.tx_request_map for c in self.connections ]
|
||||
raise AssertionError("Not all nodes requested transaction")
|
||||
# --> Answer request (we did this inline!)
|
||||
|
||||
# Get the mempool
|
||||
[ c.cb.send_mempool() for c in self.connections ]
|
||||
|
@ -272,29 +289,55 @@ class TestManager(object):
|
|||
# We use these variables to keep track of the last block
|
||||
# and last transaction in the tests, which are used
|
||||
# if we're not syncing on every block or every tx.
|
||||
[ block, block_outcome ] = [ None, None ]
|
||||
[ block, block_outcome, tip ] = [ None, None, None ]
|
||||
[ tx, tx_outcome ] = [ None, None ]
|
||||
invqueue = []
|
||||
|
||||
for b_or_t, outcome in test_instance.blocks_and_transactions:
|
||||
for test_obj in test_instance.blocks_and_transactions:
|
||||
b_or_t = test_obj[0]
|
||||
outcome = test_obj[1]
|
||||
# Determine if we're dealing with a block or tx
|
||||
if isinstance(b_or_t, CBlock): # Block test runner
|
||||
block = b_or_t
|
||||
block_outcome = outcome
|
||||
tip = block.sha256
|
||||
# each test_obj can have an optional third argument
|
||||
# to specify the tip we should compare with
|
||||
# (default is to use the block being tested)
|
||||
if len(test_obj) >= 3:
|
||||
tip = test_obj[2]
|
||||
|
||||
# Add to shared block_store, set as current block
|
||||
# If there was an open getdata request for the block
|
||||
# previously, and we didn't have an entry in the
|
||||
# block_store, then immediately deliver, because the
|
||||
# node wouldn't send another getdata request while
|
||||
# the earlier one is outstanding.
|
||||
first_block_with_hash = True
|
||||
if self.block_store.get(block.sha256) is not None:
|
||||
first_block_with_hash = False
|
||||
with mininode_lock:
|
||||
self.block_store.add_block(block)
|
||||
for c in self.connections:
|
||||
if first_block_with_hash and block.sha256 in c.cb.block_request_map and c.cb.block_request_map[block.sha256] == True:
|
||||
# There was a previous request for this block hash
|
||||
# Most likely, we delivered a header for this block
|
||||
# but never had the block to respond to the getdata
|
||||
c.send_message(msg_block(block))
|
||||
else:
|
||||
c.cb.block_request_map[block.sha256] = False
|
||||
# Either send inv's to each node and sync, or add
|
||||
# to invqueue for later inv'ing.
|
||||
if (test_instance.sync_every_block):
|
||||
[ c.cb.send_inv(block) for c in self.connections ]
|
||||
self.sync_blocks(block.sha256, 1)
|
||||
if (not self.check_results(block.sha256, outcome)):
|
||||
if (not self.check_results(tip, outcome)):
|
||||
raise AssertionError("Test failed at test %d" % test_number)
|
||||
else:
|
||||
invqueue.append(CInv(2, block.sha256))
|
||||
elif isinstance(b_or_t, CBlockHeader):
|
||||
block_header = b_or_t
|
||||
self.block_store.add_header(block_header)
|
||||
else: # Tx test runner
|
||||
assert(isinstance(b_or_t, CTransaction))
|
||||
tx = b_or_t
|
||||
|
@ -322,9 +365,8 @@ class TestManager(object):
|
|||
if len(invqueue) > 0:
|
||||
[ c.send_message(msg_inv(invqueue)) for c in self.connections ]
|
||||
invqueue = []
|
||||
self.sync_blocks(block.sha256,
|
||||
len(test_instance.blocks_and_transactions))
|
||||
if (not self.check_results(block.sha256, block_outcome)):
|
||||
self.sync_blocks(block.sha256, len(test_instance.blocks_and_transactions))
|
||||
if (not self.check_results(tip, block_outcome)):
|
||||
raise AssertionError("Block test failed at test %d" % test_number)
|
||||
if (not test_instance.sync_every_tx and tx is not None):
|
||||
if len(invqueue) > 0:
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2015-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
"""
|
||||
This module contains utilities for doing coverage analysis on the RPC
|
||||
interface.
|
||||
|
|
|
@ -0,0 +1,215 @@
|
|||
# Copyright (c) 2011 Sam Rushing
|
||||
#
|
||||
# key.py - OpenSSL wrapper
|
||||
#
|
||||
# This file is modified from python-bitcoinlib.
|
||||
#
|
||||
|
||||
"""ECC secp256k1 crypto routines
|
||||
|
||||
WARNING: This module does not mlock() secrets; your private keys may end up on
|
||||
disk in swap! Use with caution!
|
||||
"""
|
||||
|
||||
import ctypes
|
||||
import ctypes.util
|
||||
import hashlib
|
||||
import sys
|
||||
|
||||
ssl = ctypes.cdll.LoadLibrary(ctypes.util.find_library ('ssl') or 'libeay32')
|
||||
|
||||
ssl.BN_new.restype = ctypes.c_void_p
|
||||
ssl.BN_new.argtypes = []
|
||||
|
||||
ssl.BN_bin2bn.restype = ctypes.c_void_p
|
||||
ssl.BN_bin2bn.argtypes = [ctypes.c_char_p, ctypes.c_int, ctypes.c_void_p]
|
||||
|
||||
ssl.BN_CTX_free.restype = None
|
||||
ssl.BN_CTX_free.argtypes = [ctypes.c_void_p]
|
||||
|
||||
ssl.BN_CTX_new.restype = ctypes.c_void_p
|
||||
ssl.BN_CTX_new.argtypes = []
|
||||
|
||||
ssl.ECDH_compute_key.restype = ctypes.c_int
|
||||
ssl.ECDH_compute_key.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p]
|
||||
|
||||
ssl.ECDSA_sign.restype = ctypes.c_int
|
||||
ssl.ECDSA_sign.argtypes = [ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
|
||||
|
||||
ssl.ECDSA_verify.restype = ctypes.c_int
|
||||
ssl.ECDSA_verify.argtypes = [ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p]
|
||||
|
||||
ssl.EC_KEY_free.restype = None
|
||||
ssl.EC_KEY_free.argtypes = [ctypes.c_void_p]
|
||||
|
||||
ssl.EC_KEY_new_by_curve_name.restype = ctypes.c_void_p
|
||||
ssl.EC_KEY_new_by_curve_name.argtypes = [ctypes.c_int]
|
||||
|
||||
ssl.EC_KEY_get0_group.restype = ctypes.c_void_p
|
||||
ssl.EC_KEY_get0_group.argtypes = [ctypes.c_void_p]
|
||||
|
||||
ssl.EC_KEY_get0_public_key.restype = ctypes.c_void_p
|
||||
ssl.EC_KEY_get0_public_key.argtypes = [ctypes.c_void_p]
|
||||
|
||||
ssl.EC_KEY_set_private_key.restype = ctypes.c_int
|
||||
ssl.EC_KEY_set_private_key.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
|
||||
|
||||
ssl.EC_KEY_set_conv_form.restype = None
|
||||
ssl.EC_KEY_set_conv_form.argtypes = [ctypes.c_void_p, ctypes.c_int]
|
||||
|
||||
ssl.EC_KEY_set_public_key.restype = ctypes.c_int
|
||||
ssl.EC_KEY_set_public_key.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
|
||||
|
||||
ssl.i2o_ECPublicKey.restype = ctypes.c_void_p
|
||||
ssl.i2o_ECPublicKey.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
|
||||
|
||||
ssl.EC_POINT_new.restype = ctypes.c_void_p
|
||||
ssl.EC_POINT_new.argtypes = [ctypes.c_void_p]
|
||||
|
||||
ssl.EC_POINT_free.restype = None
|
||||
ssl.EC_POINT_free.argtypes = [ctypes.c_void_p]
|
||||
|
||||
ssl.EC_POINT_mul.restype = ctypes.c_int
|
||||
ssl.EC_POINT_mul.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
|
||||
|
||||
# this specifies the curve used with ECDSA.
|
||||
NID_secp256k1 = 714 # from openssl/obj_mac.h
|
||||
|
||||
# Thx to Sam Devlin for the ctypes magic 64-bit fix.
|
||||
def _check_result(val, func, args):
|
||||
if val == 0:
|
||||
raise ValueError
|
||||
else:
|
||||
return ctypes.c_void_p (val)
|
||||
|
||||
ssl.EC_KEY_new_by_curve_name.restype = ctypes.c_void_p
|
||||
ssl.EC_KEY_new_by_curve_name.errcheck = _check_result
|
||||
|
||||
class CECKey(object):
|
||||
"""Wrapper around OpenSSL's EC_KEY"""
|
||||
|
||||
POINT_CONVERSION_COMPRESSED = 2
|
||||
POINT_CONVERSION_UNCOMPRESSED = 4
|
||||
|
||||
def __init__(self):
|
||||
self.k = ssl.EC_KEY_new_by_curve_name(NID_secp256k1)
|
||||
|
||||
def __del__(self):
|
||||
if ssl:
|
||||
ssl.EC_KEY_free(self.k)
|
||||
self.k = None
|
||||
|
||||
def set_secretbytes(self, secret):
|
||||
priv_key = ssl.BN_bin2bn(secret, 32, ssl.BN_new())
|
||||
group = ssl.EC_KEY_get0_group(self.k)
|
||||
pub_key = ssl.EC_POINT_new(group)
|
||||
ctx = ssl.BN_CTX_new()
|
||||
if not ssl.EC_POINT_mul(group, pub_key, priv_key, None, None, ctx):
|
||||
raise ValueError("Could not derive public key from the supplied secret.")
|
||||
ssl.EC_POINT_mul(group, pub_key, priv_key, None, None, ctx)
|
||||
ssl.EC_KEY_set_private_key(self.k, priv_key)
|
||||
ssl.EC_KEY_set_public_key(self.k, pub_key)
|
||||
ssl.EC_POINT_free(pub_key)
|
||||
ssl.BN_CTX_free(ctx)
|
||||
return self.k
|
||||
|
||||
def set_privkey(self, key):
|
||||
self.mb = ctypes.create_string_buffer(key)
|
||||
return ssl.d2i_ECPrivateKey(ctypes.byref(self.k), ctypes.byref(ctypes.pointer(self.mb)), len(key))
|
||||
|
||||
def set_pubkey(self, key):
|
||||
self.mb = ctypes.create_string_buffer(key)
|
||||
return ssl.o2i_ECPublicKey(ctypes.byref(self.k), ctypes.byref(ctypes.pointer(self.mb)), len(key))
|
||||
|
||||
def get_privkey(self):
|
||||
size = ssl.i2d_ECPrivateKey(self.k, 0)
|
||||
mb_pri = ctypes.create_string_buffer(size)
|
||||
ssl.i2d_ECPrivateKey(self.k, ctypes.byref(ctypes.pointer(mb_pri)))
|
||||
return mb_pri.raw
|
||||
|
||||
def get_pubkey(self):
|
||||
size = ssl.i2o_ECPublicKey(self.k, 0)
|
||||
mb = ctypes.create_string_buffer(size)
|
||||
ssl.i2o_ECPublicKey(self.k, ctypes.byref(ctypes.pointer(mb)))
|
||||
return mb.raw
|
||||
|
||||
def get_raw_ecdh_key(self, other_pubkey):
|
||||
ecdh_keybuffer = ctypes.create_string_buffer(32)
|
||||
r = ssl.ECDH_compute_key(ctypes.pointer(ecdh_keybuffer), 32,
|
||||
ssl.EC_KEY_get0_public_key(other_pubkey.k),
|
||||
self.k, 0)
|
||||
if r != 32:
|
||||
raise Exception('CKey.get_ecdh_key(): ECDH_compute_key() failed')
|
||||
return ecdh_keybuffer.raw
|
||||
|
||||
def get_ecdh_key(self, other_pubkey, kdf=lambda k: hashlib.sha256(k).digest()):
|
||||
# FIXME: be warned it's not clear what the kdf should be as a default
|
||||
r = self.get_raw_ecdh_key(other_pubkey)
|
||||
return kdf(r)
|
||||
|
||||
def sign(self, hash):
|
||||
# FIXME: need unit tests for below cases
|
||||
if not isinstance(hash, bytes):
|
||||
raise TypeError('Hash must be bytes instance; got %r' % hash.__class__)
|
||||
if len(hash) != 32:
|
||||
raise ValueError('Hash must be exactly 32 bytes long')
|
||||
|
||||
sig_size0 = ctypes.c_uint32()
|
||||
sig_size0.value = ssl.ECDSA_size(self.k)
|
||||
mb_sig = ctypes.create_string_buffer(sig_size0.value)
|
||||
result = ssl.ECDSA_sign(0, hash, len(hash), mb_sig, ctypes.byref(sig_size0), self.k)
|
||||
assert 1 == result
|
||||
return mb_sig.raw[:sig_size0.value]
|
||||
|
||||
def verify(self, hash, sig):
|
||||
"""Verify a DER signature"""
|
||||
return ssl.ECDSA_verify(0, hash, len(hash), sig, len(sig), self.k) == 1
|
||||
|
||||
def set_compressed(self, compressed):
|
||||
if compressed:
|
||||
form = self.POINT_CONVERSION_COMPRESSED
|
||||
else:
|
||||
form = self.POINT_CONVERSION_UNCOMPRESSED
|
||||
ssl.EC_KEY_set_conv_form(self.k, form)
|
||||
|
||||
|
||||
class CPubKey(bytes):
|
||||
"""An encapsulated public key
|
||||
|
||||
Attributes:
|
||||
|
||||
is_valid - Corresponds to CPubKey.IsValid()
|
||||
is_fullyvalid - Corresponds to CPubKey.IsFullyValid()
|
||||
is_compressed - Corresponds to CPubKey.IsCompressed()
|
||||
"""
|
||||
|
||||
def __new__(cls, buf, _cec_key=None):
|
||||
self = super(CPubKey, cls).__new__(cls, buf)
|
||||
if _cec_key is None:
|
||||
_cec_key = CECKey()
|
||||
self._cec_key = _cec_key
|
||||
self.is_fullyvalid = _cec_key.set_pubkey(self) != 0
|
||||
return self
|
||||
|
||||
@property
|
||||
def is_valid(self):
|
||||
return len(self) > 0
|
||||
|
||||
@property
|
||||
def is_compressed(self):
|
||||
return len(self) == 33
|
||||
|
||||
def verify(self, hash, sig):
|
||||
return self._cec_key.verify(hash, sig)
|
||||
|
||||
def __str__(self):
|
||||
return repr(self)
|
||||
|
||||
def __repr__(self):
|
||||
# Always have represent as b'<secret>' so test cases don't have to
|
||||
# change for py2/3
|
||||
if sys.version > '3':
|
||||
return '%s(%s)' % (self.__class__.__name__, super(CPubKey, self).__repr__())
|
||||
else:
|
||||
return '%s(b%s)' % (self.__class__.__name__, super(CPubKey, self).__repr__())
|
||||
|
|
@ -1,7 +1,12 @@
|
|||
# mininode.py - Bitcoin P2P network half-a-node
|
||||
#
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2010 ArtForz -- public domain half-a-node
|
||||
# Copyright (c) 2012 Jeff Garzik
|
||||
# Copyright (c) 2010-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
#
|
||||
# mininode.py - Bitcoin P2P network half-a-node
|
||||
#
|
||||
# This python code was modified from ArtForz' public domain half-a-node, as
|
||||
# found in the mini-node branch of http://github.com/jgarzik/pynode.
|
||||
|
@ -46,7 +51,7 @@ OVERWINTER_PROTO_VERSION = 170003
|
|||
SAPLING_PROTO_VERSION = 170006
|
||||
BLOSSOM_PROTO_VERSION = 170008
|
||||
|
||||
MY_SUBVERSION = b"/python-mininode-tester:0.0.1/"
|
||||
MY_SUBVERSION = b"/python-mininode-tester:0.0.3/"
|
||||
|
||||
SPROUT_VERSION_GROUP_ID = 0x00000000
|
||||
OVERWINTER_VERSION_GROUP_ID = 0x03C48270
|
||||
|
@ -757,9 +762,8 @@ class CTransaction(object):
|
|||
self.calc_sha256()
|
||||
|
||||
def calc_sha256(self):
|
||||
serialized = self.serialize()
|
||||
if self.sha256 is None:
|
||||
self.sha256 = uint256_from_str(hash256(serialized))
|
||||
self.sha256 = uint256_from_str(hash256(self.serialize()))
|
||||
self.hash = hash256(self.serialize())[::-1].hex()
|
||||
|
||||
def is_valid(self):
|
||||
|
@ -1607,6 +1611,7 @@ class NodeConn(asyncore.dispatcher):
|
|||
self.sendbuf = self.sendbuf[sent:]
|
||||
|
||||
def got_data(self):
|
||||
try:
|
||||
while True:
|
||||
if len(self.recvbuf) < 4:
|
||||
return
|
||||
|
@ -1644,6 +1649,10 @@ class NodeConn(asyncore.dispatcher):
|
|||
else:
|
||||
self.show_debug_msg("Unknown command: '" + command + "' " +
|
||||
repr(msg))
|
||||
except Exception as e:
|
||||
print('got_data:', repr(e))
|
||||
# import traceback
|
||||
# traceback.print_tb(sys.exc_info()[2])
|
||||
|
||||
def send_message(self, message, pushbuf=False):
|
||||
if self.state != b"connected" and not pushbuf:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2015-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
#
|
||||
# script.py
|
||||
#
|
||||
# This file is modified from python-bitcoinlib.
|
||||
#
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
#
|
||||
|
||||
"""Scripts
|
||||
|
||||
|
@ -22,7 +25,7 @@ if sys.version > '3':
|
|||
from pyblake2 import blake2b
|
||||
import struct
|
||||
|
||||
from test_framework import bignum
|
||||
from test_framework.bignum import bn2vch
|
||||
from test_framework.mininode import (CTransaction, CTxOut, hash256, ser_string, ser_uint256)
|
||||
|
||||
MAX_SCRIPT_SIZE = 10000
|
||||
|
@ -659,7 +662,7 @@ class CScript(bytes):
|
|||
elif other == -1:
|
||||
other = bytes([OP_1NEGATE])
|
||||
else:
|
||||
other = CScriptOp.encode_op_pushdata(bignum.bn2vch(other))
|
||||
other = CScriptOp.encode_op_pushdata(bn2vch(other))
|
||||
elif isinstance(other, (bytes, bytearray)):
|
||||
other = bytes(CScriptOp.encode_op_pushdata(other))
|
||||
return other
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2015 The Bitcoin Core developers
|
||||
# Copyright (c) 2015-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
'''
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
# Base class for RPC testing
|
||||
|
||||
# Add python-bitcoinrpc to module search path:
|
||||
import logging
|
||||
import optparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
import shutil
|
||||
import tempfile
|
||||
import traceback
|
||||
|
@ -16,7 +16,6 @@ import traceback
|
|||
from .authproxy import JSONRPCException
|
||||
from .util import (
|
||||
initialize_chain,
|
||||
assert_equal,
|
||||
start_nodes,
|
||||
connect_nodes_bi,
|
||||
sync_blocks,
|
||||
|
@ -26,26 +25,32 @@ from .util import (
|
|||
enable_coverage,
|
||||
check_json_precision,
|
||||
initialize_chain_clean,
|
||||
PortSeed,
|
||||
)
|
||||
|
||||
|
||||
class BitcoinTestFramework(object):
|
||||
|
||||
# These may be over-ridden by subclasses:
|
||||
def __init__(self):
|
||||
self.num_nodes = 4
|
||||
self.setup_clean_chain = False
|
||||
self.nodes = None
|
||||
|
||||
def run_test(self):
|
||||
for node in self.nodes:
|
||||
assert_equal(node.getblockcount(), 200)
|
||||
assert_equal(node.getbalance(), 25*10)
|
||||
raise NotImplementedError
|
||||
|
||||
def add_options(self, parser):
|
||||
pass
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain(self.options.tmpdir)
|
||||
if self.setup_clean_chain:
|
||||
initialize_chain_clean(self.options.tmpdir, self.num_nodes)
|
||||
else:
|
||||
initialize_chain(self.options.tmpdir, self.num_nodes, self.options.cachedir)
|
||||
|
||||
def setup_nodes(self):
|
||||
return start_nodes(4, self.options.tmpdir)
|
||||
return start_nodes(self.num_nodes, self.options.tmpdir)
|
||||
|
||||
def setup_network(self, split = False):
|
||||
self.nodes = self.setup_nodes()
|
||||
|
@ -95,7 +100,6 @@ class BitcoinTestFramework(object):
|
|||
self.setup_network(False)
|
||||
|
||||
def main(self):
|
||||
import optparse
|
||||
|
||||
parser = optparse.OptionParser(usage="%prog [options]")
|
||||
parser.add_option("--nocleanup", dest="nocleanup", default=False, action="store_true",
|
||||
|
@ -104,38 +108,40 @@ class BitcoinTestFramework(object):
|
|||
help="Don't stop bitcoinds after the test execution")
|
||||
parser.add_option("--srcdir", dest="srcdir", default="../../src",
|
||||
help="Source directory containing bitcoind/bitcoin-cli (default: %default)")
|
||||
parser.add_option("--cachedir", dest="cachedir", default=os.path.normpath(os.path.dirname(os.path.realpath(__file__))+"/../../cache"),
|
||||
help="Directory for caching pregenerated datadirs")
|
||||
parser.add_option("--tmpdir", dest="tmpdir", default=tempfile.mkdtemp(prefix="test"),
|
||||
help="Root directory for datadirs")
|
||||
parser.add_option("--tracerpc", dest="trace_rpc", default=False, action="store_true",
|
||||
help="Print out all RPC calls as they are made")
|
||||
parser.add_option("--portseed", dest="port_seed", default=os.getpid(), type='int',
|
||||
help="The seed to use for assigning port numbers (default: current process id)")
|
||||
parser.add_option("--coveragedir", dest="coveragedir",
|
||||
help="Write tested RPC commands into this directory")
|
||||
self.add_options(parser)
|
||||
(self.options, self.args) = parser.parse_args()
|
||||
|
||||
self.options.tmpdir += '/' + str(self.options.port_seed)
|
||||
|
||||
if self.options.trace_rpc:
|
||||
import logging
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
logging.basicConfig(level=logging.DEBUG, stream=sys.stdout)
|
||||
|
||||
if self.options.coveragedir:
|
||||
enable_coverage(self.options.coveragedir)
|
||||
|
||||
PortSeed.n = self.options.port_seed
|
||||
|
||||
os.environ['PATH'] = self.options.srcdir+":"+os.environ['PATH']
|
||||
|
||||
check_json_precision()
|
||||
|
||||
success = False
|
||||
try:
|
||||
if not os.path.isdir(self.options.tmpdir):
|
||||
os.makedirs(self.options.tmpdir)
|
||||
os.makedirs(self.options.tmpdir, exist_ok=False)
|
||||
self.setup_chain()
|
||||
|
||||
self.setup_network()
|
||||
|
||||
self.run_test()
|
||||
|
||||
success = True
|
||||
|
||||
except JSONRPCException as e:
|
||||
print("JSONRPC error: "+e.error['message'])
|
||||
traceback.print_tb(sys.exc_info()[2])
|
||||
|
@ -148,6 +154,8 @@ class BitcoinTestFramework(object):
|
|||
except Exception as e:
|
||||
print("Unexpected exception caught during testing: "+str(e))
|
||||
traceback.print_tb(sys.exc_info()[2])
|
||||
except KeyboardInterrupt as e:
|
||||
print("Exiting after " + repr(e))
|
||||
|
||||
if not self.options.noshutdown:
|
||||
print("Stopping nodes")
|
||||
|
@ -176,9 +184,10 @@ class BitcoinTestFramework(object):
|
|||
|
||||
class ComparisonTestFramework(BitcoinTestFramework):
|
||||
|
||||
# Can override the num_nodes variable to indicate how many nodes to run.
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 2
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def add_options(self, parser):
|
||||
parser.add_option("--testbinary", dest="testbinary",
|
||||
|
@ -188,10 +197,6 @@ class ComparisonTestFramework(BitcoinTestFramework):
|
|||
default=os.getenv("BITCOIND", "bitcoind"),
|
||||
help="bitcoind binary to use for reference nodes (if any)")
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, self.num_nodes)
|
||||
|
||||
def setup_network(self):
|
||||
self.nodes = start_nodes(
|
||||
self.num_nodes, self.options.tmpdir,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
@ -7,7 +8,6 @@
|
|||
# Helpful routines for regression testing
|
||||
#
|
||||
|
||||
# Add python-bitcoinrpc to module search path:
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
@ -15,6 +15,7 @@ from binascii import hexlify, unhexlify
|
|||
from base64 import b64encode
|
||||
from decimal import Decimal, ROUND_DOWN
|
||||
import json
|
||||
import http.client
|
||||
import random
|
||||
import shutil
|
||||
import subprocess
|
||||
|
@ -37,6 +38,18 @@ BLOSSOM_BRANCH_ID = 0x2BB40E60
|
|||
HEARTWOOD_BRANCH_ID = 0xF5B9230B
|
||||
CANOPY_BRANCH_ID = 0xE9FF75A6
|
||||
|
||||
# The maximum number of nodes a single test can spawn
|
||||
MAX_NODES = 8
|
||||
# Don't assign rpc or p2p ports lower than this
|
||||
PORT_MIN = 11000
|
||||
# The number of ports to "reserve" for p2p and rpc, each
|
||||
PORT_RANGE = 5000
|
||||
|
||||
|
||||
class PortSeed:
|
||||
# Must be initialized with a unique integer for each process
|
||||
n = None
|
||||
|
||||
def enable_coverage(dirname):
|
||||
"""Maintain a log of which RPC calls are made during testing."""
|
||||
global COVERAGE_DIR
|
||||
|
@ -70,9 +83,11 @@ def get_rpc_proxy(url, node_number, timeout=None):
|
|||
|
||||
|
||||
def p2p_port(n):
|
||||
return 11000 + n + os.getpid()%999
|
||||
assert(n <= MAX_NODES)
|
||||
return PORT_MIN + n + (MAX_NODES * PortSeed.n) % (PORT_RANGE - 1 - MAX_NODES)
|
||||
|
||||
def rpc_port(n):
|
||||
return 12000 + n + os.getpid()%999
|
||||
return PORT_MIN + PORT_RANGE + n + (MAX_NODES * PortSeed.n) % (PORT_RANGE - 1 - MAX_NODES)
|
||||
|
||||
def check_json_precision():
|
||||
"""Make sure json library being used does not lose precision converting BTC values"""
|
||||
|
@ -90,31 +105,41 @@ def hex_str_to_bytes(hex_str):
|
|||
def str_to_b64str(string):
|
||||
return b64encode(string.encode('utf-8')).decode('ascii')
|
||||
|
||||
def sync_blocks(rpc_connections, wait=1):
|
||||
def sync_blocks(rpc_connections, wait=0.125, timeout=60, allow_different_tips=False):
|
||||
"""
|
||||
Wait until everybody has the same block count, and has notified
|
||||
all internal listeners of them
|
||||
Wait until everybody has the same tip, and has notified
|
||||
all internal listeners of them.
|
||||
|
||||
If allow_different_tips is True, waits until everyone has
|
||||
the same block count.
|
||||
"""
|
||||
while True:
|
||||
counts = [ x.getblockcount() for x in rpc_connections ]
|
||||
if counts == [ counts[0] ]*len(counts):
|
||||
while timeout > 0:
|
||||
if allow_different_tips:
|
||||
tips = [ x.getblockcount() for x in rpc_connections ]
|
||||
else:
|
||||
tips = [ x.getbestblockhash() for x in rpc_connections ]
|
||||
if tips == [ tips[0] ]*len(tips):
|
||||
break
|
||||
time.sleep(wait)
|
||||
timeout -= wait
|
||||
|
||||
# Now that the block counts are in sync, wait for the internal
|
||||
# notifications to finish
|
||||
while True:
|
||||
while timeout > 0:
|
||||
notified = [ x.getblockchaininfo()['fullyNotified'] for x in rpc_connections ]
|
||||
if notified == [ True ] * len(notified):
|
||||
break
|
||||
return True
|
||||
time.sleep(wait)
|
||||
timeout -= wait
|
||||
|
||||
def sync_mempools(rpc_connections, wait=1):
|
||||
raise AssertionError("Block sync failed")
|
||||
|
||||
def sync_mempools(rpc_connections, wait=0.5, timeout=60):
|
||||
"""
|
||||
Wait until everybody has the same transactions in their memory
|
||||
pools, and has notified all internal listeners of them
|
||||
"""
|
||||
while True:
|
||||
while timeout > 0:
|
||||
pool = set(rpc_connections[0].getrawmempool())
|
||||
num_match = 1
|
||||
for i in range(1, len(rpc_connections)):
|
||||
|
@ -123,14 +148,18 @@ def sync_mempools(rpc_connections, wait=1):
|
|||
if num_match == len(rpc_connections):
|
||||
break
|
||||
time.sleep(wait)
|
||||
timeout -= wait
|
||||
|
||||
# Now that the mempools are in sync, wait for the internal
|
||||
# notifications to finish
|
||||
while True:
|
||||
while timeout > 0:
|
||||
notified = [ x.getmempoolinfo()['fullyNotified'] for x in rpc_connections ]
|
||||
if notified == [ True ] * len(notified):
|
||||
break
|
||||
return True
|
||||
time.sleep(wait)
|
||||
timeout -= wait
|
||||
|
||||
raise AssertionError("Mempool sync failed")
|
||||
|
||||
bitcoind_processes = {}
|
||||
|
||||
|
@ -138,18 +167,31 @@ def initialize_datadir(dirname, n):
|
|||
datadir = os.path.join(dirname, "node"+str(n))
|
||||
if not os.path.isdir(datadir):
|
||||
os.makedirs(datadir)
|
||||
rpc_u, rpc_p = rpc_auth_pair(n)
|
||||
with open(os.path.join(datadir, "zcash.conf"), 'w', encoding='utf8') as f:
|
||||
f.write("regtest=1\n")
|
||||
f.write("showmetrics=0\n")
|
||||
f.write("rpcuser=rt\n")
|
||||
f.write("rpcpassword=rt\n")
|
||||
f.write("rpcuser=" + rpc_u + "\n")
|
||||
f.write("rpcpassword=" + rpc_p + "\n")
|
||||
f.write("port="+str(p2p_port(n))+"\n")
|
||||
f.write("rpcport="+str(rpc_port(n))+"\n")
|
||||
f.write("listenonion=0\n")
|
||||
return datadir
|
||||
|
||||
def rpc_auth_pair(n):
|
||||
return 'rpcuser💻' + str(n), 'rpcpass🔑' + str(n)
|
||||
|
||||
def rpc_url(i, rpchost=None):
|
||||
return "http://rt:rt@%s:%d" % (rpchost or '127.0.0.1', rpc_port(i))
|
||||
rpc_u, rpc_p = rpc_auth_pair(i)
|
||||
host = '127.0.0.1'
|
||||
port = rpc_port(i)
|
||||
if rpchost:
|
||||
parts = rpchost.split(':')
|
||||
if len(parts) == 2:
|
||||
host, port = parts
|
||||
else:
|
||||
host = rpchost
|
||||
return "http://%s:%s@%s:%d" % (rpc_u, rpc_p, host, int(port))
|
||||
|
||||
def wait_for_bitcoind_start(process, url, i):
|
||||
'''
|
||||
|
@ -171,10 +213,10 @@ def wait_for_bitcoind_start(process, url, i):
|
|||
raise # unknown JSON RPC exception
|
||||
time.sleep(0.25)
|
||||
|
||||
def initialize_chain(test_dir):
|
||||
def initialize_chain(test_dir, num_nodes, cachedir):
|
||||
"""
|
||||
Create (or copy from cache) a 200-block-long chain and
|
||||
4 wallets.
|
||||
Create a cache of a 200-block-long chain (with wallet) for MAX_NODES
|
||||
Afterward, create num_nodes copies from the cache
|
||||
"""
|
||||
|
||||
# Due to the consensus change fix for the timejacking attack, we need to
|
||||
|
@ -193,24 +235,28 @@ def initialize_chain(test_dir):
|
|||
# default). Therefore, if the logic between the completion of any two
|
||||
# adjacent calls to `generate` within a test takes longer than 2.5 minutes,
|
||||
# the excess will subtract from the slack.
|
||||
if os.path.isdir(os.path.join("cache", "node0")):
|
||||
if os.stat("cache").st_mtime + (60 * 60) < time.time():
|
||||
if os.path.isdir(os.path.join(cachedir, "node0")):
|
||||
if os.stat(cachedir).st_mtime + (60 * 60) < time.time():
|
||||
print("initialize_chain(): Removing stale cache")
|
||||
shutil.rmtree("cache")
|
||||
shutil.rmtree(cachedir)
|
||||
|
||||
if (not os.path.isdir(os.path.join("cache","node0"))
|
||||
or not os.path.isdir(os.path.join("cache","node1"))
|
||||
or not os.path.isdir(os.path.join("cache","node2"))
|
||||
or not os.path.isdir(os.path.join("cache","node3"))):
|
||||
assert num_nodes <= MAX_NODES
|
||||
create_cache = False
|
||||
for i in range(MAX_NODES):
|
||||
if not os.path.isdir(os.path.join(cachedir, 'node'+str(i))):
|
||||
create_cache = True
|
||||
break
|
||||
|
||||
if create_cache:
|
||||
|
||||
#find and delete old cache directories if any exist
|
||||
for i in range(4):
|
||||
if os.path.isdir(os.path.join("cache","node"+str(i))):
|
||||
shutil.rmtree(os.path.join("cache","node"+str(i)))
|
||||
for i in range(MAX_NODES):
|
||||
if os.path.isdir(os.path.join(cachedir,"node"+str(i))):
|
||||
shutil.rmtree(os.path.join(cachedir,"node"+str(i)))
|
||||
|
||||
# Create cache directories, run bitcoinds:
|
||||
for i in range(4):
|
||||
datadir=initialize_datadir("cache", i)
|
||||
for i in range(MAX_NODES):
|
||||
datadir=initialize_datadir(cachedir, i)
|
||||
args = [ os.getenv("BITCOIND", "bitcoind"), "-keypool=1", "-datadir="+datadir, "-discover=0" ]
|
||||
args.extend([
|
||||
'-nuparams=5ba81b19:1', # Overwinter
|
||||
|
@ -226,15 +272,18 @@ def initialize_chain(test_dir):
|
|||
print("initialize_chain: RPC successfully started")
|
||||
|
||||
rpcs = []
|
||||
for i in range(4):
|
||||
for i in range(MAX_NODES):
|
||||
try:
|
||||
rpcs.append(get_rpc_proxy(rpc_url(i), i))
|
||||
except:
|
||||
sys.stderr.write("Error connecting to "+rpc_url(i)+"\n")
|
||||
sys.exit(1)
|
||||
|
||||
# Create a 200-block-long chain; each of the 4 nodes
|
||||
# Create a 200-block-long chain; each of the 4 first nodes
|
||||
# gets 25 mature blocks and 25 immature.
|
||||
# Note: To preserve compatibility with older versions of
|
||||
# initialize_chain, only 4 nodes will generate coins.
|
||||
#
|
||||
# Blocks are created with timestamps 2.5 minutes apart (matching the
|
||||
# chain defaulting above to Sapling active), starting 200 * 2.5 minutes
|
||||
# before the current time.
|
||||
|
@ -253,14 +302,14 @@ def initialize_chain(test_dir):
|
|||
# Shut them down, and clean up cache directories:
|
||||
stop_nodes(rpcs)
|
||||
wait_bitcoinds()
|
||||
for i in range(4):
|
||||
os.remove(log_filename("cache", i, "debug.log"))
|
||||
os.remove(log_filename("cache", i, "db.log"))
|
||||
os.remove(log_filename("cache", i, "peers.dat"))
|
||||
os.remove(log_filename("cache", i, "fee_estimates.dat"))
|
||||
for i in range(MAX_NODES):
|
||||
os.remove(log_filename(cachedir, i, "debug.log"))
|
||||
os.remove(log_filename(cachedir, i, "db.log"))
|
||||
os.remove(log_filename(cachedir, i, "peers.dat"))
|
||||
os.remove(log_filename(cachedir, i, "fee_estimates.dat"))
|
||||
|
||||
for i in range(4):
|
||||
from_dir = os.path.join("cache", "node"+str(i))
|
||||
for i in range(num_nodes):
|
||||
from_dir = os.path.join(cachedir, "node"+str(i))
|
||||
to_dir = os.path.join(test_dir, "node"+str(i))
|
||||
shutil.copytree(from_dir, to_dir)
|
||||
initialize_datadir(test_dir, i) # Overwrite port/rpcport in zcash.conf
|
||||
|
@ -344,8 +393,8 @@ def start_nodes(num_nodes, dirname, extra_args=None, rpchost=None, binary=None):
|
|||
"""
|
||||
Start multiple bitcoinds, return RPC connections to them
|
||||
"""
|
||||
if extra_args is None: extra_args = [ None for i in range(num_nodes) ]
|
||||
if binary is None: binary = [ None for i in range(num_nodes) ]
|
||||
if extra_args is None: extra_args = [ None for _ in range(num_nodes) ]
|
||||
if binary is None: binary = [ None for _ in range(num_nodes) ]
|
||||
rpcs = []
|
||||
try:
|
||||
for i in range(num_nodes):
|
||||
|
@ -363,13 +412,19 @@ def check_node(i):
|
|||
return bitcoind_processes[i].returncode
|
||||
|
||||
def stop_node(node, i):
|
||||
try:
|
||||
node.stop()
|
||||
except http.client.CannotSendRequest as e:
|
||||
print("WARN: Unable to stop node: " + repr(e))
|
||||
bitcoind_processes[i].wait()
|
||||
del bitcoind_processes[i]
|
||||
|
||||
def stop_nodes(nodes):
|
||||
for node in nodes:
|
||||
try:
|
||||
node.stop()
|
||||
except http.client.CannotSendRequest as e:
|
||||
print("WARN: Unable to stop node: " + repr(e))
|
||||
del nodes[:] # Emptying array closes connections as a side effect
|
||||
|
||||
def set_node_times(nodes, t):
|
||||
|
|
|
@ -32,7 +32,7 @@ from test_framework.util import (
|
|||
get_coinbase_address,
|
||||
start_node, start_nodes,
|
||||
sync_blocks, sync_mempools,
|
||||
initialize_chain_clean, connect_nodes_bi,
|
||||
connect_nodes_bi,
|
||||
wait_and_assert_operationid_status,
|
||||
bitcoind_processes,
|
||||
check_node_log
|
||||
|
@ -44,12 +44,13 @@ TURNSTILE_ARGS = ['-experimentalfeatures',
|
|||
|
||||
class TurnstileTest (BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory " + self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 3)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 3
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def setup_network(self, split=False):
|
||||
self.nodes = start_nodes(3, self.options.tmpdir)
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
|
||||
connect_nodes_bi(self.nodes,0,1)
|
||||
connect_nodes_bi(self.nodes,1,2)
|
||||
self.is_network_split=False
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
@ -14,6 +14,11 @@ from test_framework.util import assert_equal, connect_nodes, \
|
|||
|
||||
class TxnMallTest(BitcoinTestFramework):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 4
|
||||
self.setup_clean_chain = False
|
||||
|
||||
def add_options(self, parser):
|
||||
parser.add_option("--mineblock", dest="mine_block", default=False, action="store_true",
|
||||
help="Test double-spend of 1-confirmed transaction")
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.authproxy import JSONRPCException
|
||||
from test_framework.util import assert_equal, assert_greater_than, \
|
||||
initialize_chain_clean, start_nodes, start_node, connect_nodes_bi, \
|
||||
start_nodes, start_node, connect_nodes_bi, \
|
||||
stop_nodes, sync_blocks, sync_mempools, wait_and_assert_operationid_status, \
|
||||
wait_bitcoinds
|
||||
|
||||
|
@ -14,9 +14,10 @@ from decimal import Decimal
|
|||
|
||||
class WalletTest (BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 4)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 4
|
||||
|
||||
def setup_network(self, split=False):
|
||||
self.nodes = start_nodes(3, self.options.tmpdir)
|
||||
|
|
|
@ -13,8 +13,8 @@ from decimal import Decimal
|
|||
class WalletNullifiersTest (BitcoinTestFramework):
|
||||
|
||||
def setup_nodes(self):
|
||||
return start_nodes(4, self.options.tmpdir,
|
||||
extra_args=[['-experimentalfeatures', '-developerencryptwallet']] * 4)
|
||||
return start_nodes(self.num_nodes, self.options.tmpdir,
|
||||
extra_args=[['-experimentalfeatures', '-developerencryptwallet']] * self.num_nodes)
|
||||
|
||||
def run_test (self):
|
||||
# add zaddr to node 0
|
||||
|
|
|
@ -9,7 +9,6 @@ from test_framework.util import (
|
|||
assert_greater_than,
|
||||
connect_nodes_bi,
|
||||
get_coinbase_address,
|
||||
initialize_chain_clean,
|
||||
start_nodes,
|
||||
wait_and_assert_operationid_status,
|
||||
)
|
||||
|
@ -19,16 +18,17 @@ from decimal import Decimal
|
|||
|
||||
class WalletOverwinterTxTest (BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 4)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 4
|
||||
self.setup_clean_chain = True
|
||||
|
||||
def setup_network(self, split=False):
|
||||
self.nodes = start_nodes(4, self.options.tmpdir, extra_args=[[
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[[
|
||||
"-nuparams=2bb40e60:200",
|
||||
"-debug=zrpcunsafe",
|
||||
"-txindex",
|
||||
]] * 4 )
|
||||
]] * self.num_nodes)
|
||||
connect_nodes_bi(self.nodes,0,1)
|
||||
connect_nodes_bi(self.nodes,1,2)
|
||||
connect_nodes_bi(self.nodes,0,2)
|
||||
|
|
|
@ -8,7 +8,6 @@ from test_framework.authproxy import JSONRPCException
|
|||
from test_framework.util import (
|
||||
assert_equal,
|
||||
get_coinbase_address,
|
||||
start_nodes,
|
||||
wait_and_assert_operationid_status,
|
||||
)
|
||||
|
||||
|
@ -17,9 +16,6 @@ from decimal import Decimal
|
|||
# Test wallet behaviour with Sapling addresses
|
||||
class WalletSaplingTest(BitcoinTestFramework):
|
||||
|
||||
def setup_nodes(self):
|
||||
return start_nodes(4, self.options.tmpdir)
|
||||
|
||||
def run_test(self):
|
||||
# Sanity-check the test harness
|
||||
assert_equal(self.nodes[0].getblockcount(), 200)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
@ -35,7 +35,7 @@ and confirm again balances are correct.
|
|||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.authproxy import JSONRPCException
|
||||
from test_framework.util import assert_equal, initialize_chain_clean, \
|
||||
from test_framework.util import assert_equal, \
|
||||
start_nodes, start_node, connect_nodes, stop_node, \
|
||||
sync_blocks, sync_mempools
|
||||
|
||||
|
@ -44,14 +44,16 @@ import shutil
|
|||
from random import randint
|
||||
from decimal import Decimal
|
||||
import logging
|
||||
import sys
|
||||
|
||||
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.INFO)
|
||||
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO, stream=sys.stdout)
|
||||
|
||||
class WalletBackupTest(BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
logging.info("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 4)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 4
|
||||
|
||||
# This mirrors how the network was setup in the bash test
|
||||
def setup_network(self, split=False):
|
||||
|
@ -62,7 +64,7 @@ class WalletBackupTest(BitcoinTestFramework):
|
|||
|
||||
# nodes 1, 2,3 are spenders, let's give them a keypool=100
|
||||
extra_args = [["-keypool=100", ed0], ["-keypool=100", ed1], ["-keypool=100", ed2], []]
|
||||
self.nodes = start_nodes(4, self.options.tmpdir, extra_args)
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir, extra_args)
|
||||
connect_nodes(self.nodes[0], 3)
|
||||
connect_nodes(self.nodes[1], 3)
|
||||
connect_nodes(self.nodes[2], 3)
|
||||
|
|
|
@ -1,22 +1,23 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2014 The Bitcoin Core developers
|
||||
# Copyright (c) 2014-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
from test_framework.authproxy import JSONRPCException
|
||||
from test_framework.util import assert_equal, initialize_chain_clean, \
|
||||
from test_framework.util import assert_equal, \
|
||||
start_nodes, start_node, connect_nodes_bi, bitcoind_processes
|
||||
|
||||
|
||||
class ZapWalletTXesTest (BitcoinTestFramework):
|
||||
|
||||
def setup_chain(self):
|
||||
print("Initializing test directory "+self.options.tmpdir)
|
||||
initialize_chain_clean(self.options.tmpdir, 3)
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.setup_clean_chain = True
|
||||
self.num_nodes = 3
|
||||
|
||||
def setup_network(self, split=False):
|
||||
self.nodes = start_nodes(3, self.options.tmpdir)
|
||||
self.nodes = start_nodes(self.num_nodes, self.options.tmpdir)
|
||||
connect_nodes_bi(self.nodes,0,1)
|
||||
connect_nodes_bi(self.nodes,1,2)
|
||||
connect_nodes_bi(self.nodes,0,2)
|
||||
|
|
|
@ -10,6 +10,10 @@ from test_framework.util import assert_equal, start_node, \
|
|||
|
||||
|
||||
class JoinSplitTest(BitcoinTestFramework):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 1
|
||||
|
||||
def setup_network(self):
|
||||
self.nodes = []
|
||||
self.is_network_split = False
|
||||
|
|
|
@ -9,8 +9,9 @@ from test_framework.util import assert_equal, assert_greater_than, start_nodes,\
|
|||
initialize_chain_clean, connect_nodes_bi, wait_and_assert_operationid_status
|
||||
from functools import reduce
|
||||
import logging
|
||||
import sys
|
||||
|
||||
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.INFO)
|
||||
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO, stream=sys.stdout)
|
||||
|
||||
fee = Decimal('0.0001') # constant (but can be changed within reason)
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2015 The Bitcoin Core developers
|
||||
# Copyright (c) 2015-2016 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or https://www.opensource.org/licenses/mit-license.php .
|
||||
|
||||
|
@ -15,6 +15,10 @@ import struct
|
|||
|
||||
class ZMQTest(BitcoinTestFramework):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.num_nodes = 4
|
||||
|
||||
port = 28332
|
||||
|
||||
def setup_nodes(self):
|
||||
|
@ -23,7 +27,7 @@ class ZMQTest(BitcoinTestFramework):
|
|||
self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashblock")
|
||||
self.zmqSubSocket.setsockopt(zmq.SUBSCRIBE, b"hashtx")
|
||||
self.zmqSubSocket.connect("tcp://127.0.0.1:%i" % self.port)
|
||||
return start_nodes(4, self.options.tmpdir, extra_args=[
|
||||
return start_nodes(self.num_nodes, self.options.tmpdir, extra_args=[
|
||||
['-zmqpubhashtx=tcp://127.0.0.1:'+str(self.port), '-zmqpubhashblock=tcp://127.0.0.1:'+str(self.port)],
|
||||
[],
|
||||
[],
|
||||
|
|
|
@ -182,7 +182,7 @@ STAGE_COMMANDS = {
|
|||
'util-test': util_test,
|
||||
'secp256k1': ['make', '-C', repofile('src/secp256k1'), 'check'],
|
||||
'univalue': ['make', '-C', repofile('src/univalue'), 'check'],
|
||||
'rpc': [repofile('qa/pull-tester/rpc-tests.sh')],
|
||||
'rpc': [repofile('qa/pull-tester/rpc-tests.py')],
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -116,10 +116,6 @@ void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams,
|
|||
}
|
||||
}
|
||||
|
||||
bool IsValidMinerAddress(const MinerAddress& minerAddr) {
|
||||
return minerAddr.which() != 0;
|
||||
}
|
||||
|
||||
class AddFundingStreamValueToTx : public boost::static_visitor<bool>
|
||||
{
|
||||
private:
|
||||
|
@ -742,7 +738,7 @@ void static BitcoinMiner(const CChainParams& chainparams)
|
|||
|
||||
try {
|
||||
// Throw an error if no address valid for mining was provided.
|
||||
if (!IsValidMinerAddress(minerAddress)) {
|
||||
if (!boost::apply_visitor(IsValidMinerAddress(), minerAddress)) {
|
||||
throw std::runtime_error("No miner address available (mining requires a wallet or -mineraddress)");
|
||||
}
|
||||
|
||||
|
|
19
src/miner.h
19
src/miner.h
|
@ -41,7 +41,24 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
bool IsValidMinerAddress(const MinerAddress& minerAddr);
|
||||
class IsValidMinerAddress : public boost::static_visitor<bool>
|
||||
{
|
||||
public:
|
||||
IsValidMinerAddress() {}
|
||||
|
||||
bool operator()(const InvalidMinerAddress &invalid) const {
|
||||
return false;
|
||||
}
|
||||
bool operator()(const libzcash::SaplingPaymentAddress &pa) const {
|
||||
return true;
|
||||
}
|
||||
bool operator()(const boost::shared_ptr<CReserveScript> &coinbaseScript) const {
|
||||
// Return false if no script was provided. This can happen
|
||||
// due to some internal error but also if the keypool is empty.
|
||||
// In the latter case, already the pointer is NULL.
|
||||
return coinbaseScript.get() && !coinbaseScript->reserveScript.empty();
|
||||
}
|
||||
};
|
||||
|
||||
struct CBlockTemplate
|
||||
{
|
||||
|
|
|
@ -188,8 +188,14 @@ UniValue generate(const UniValue& params, bool fHelp)
|
|||
MinerAddress minerAddress;
|
||||
GetMainSignals().AddressForMining(minerAddress);
|
||||
|
||||
// If the keypool is exhausted, no script is returned at all. Catch this.
|
||||
auto resv = boost::get<boost::shared_ptr<CReserveScript>>(&minerAddress);
|
||||
if (resv && !resv->get()) {
|
||||
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
|
||||
}
|
||||
|
||||
// Throw an error if no address valid for mining was provided.
|
||||
if (!IsValidMinerAddress(minerAddress)) {
|
||||
if (!boost::apply_visitor(IsValidMinerAddress(), minerAddress)) {
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "No miner address available (mining requires a wallet or -mineraddress)");
|
||||
}
|
||||
|
||||
|
@ -622,7 +628,7 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
|
|||
GetMainSignals().AddressForMining(minerAddress);
|
||||
|
||||
// Throw an error if no address valid for mining was provided.
|
||||
if (!IsValidMinerAddress(minerAddress)) {
|
||||
if (!boost::apply_visitor(IsValidMinerAddress(), minerAddress)) {
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "No miner address available (mining requires a wallet or -mineraddress)");
|
||||
}
|
||||
|
||||
|
|
|
@ -4418,8 +4418,12 @@ void CWallet::GetAddressForMining(MinerAddress &minerAddress)
|
|||
|
||||
boost::shared_ptr<CReserveKey> rKey(new CReserveKey(this));
|
||||
CPubKey pubkey;
|
||||
if (!rKey->GetReservedKey(pubkey))
|
||||
if (!rKey->GetReservedKey(pubkey)) {
|
||||
// Explicitly return nullptr to indicate that the keypool is empty.
|
||||
rKey = nullptr;
|
||||
minerAddress = rKey;
|
||||
return;
|
||||
}
|
||||
|
||||
rKey->reserveScript = CScript() << OP_DUP << OP_HASH160 << ToByteVector(pubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
|
||||
minerAddress = rKey;
|
||||
|
|
Loading…
Reference in New Issue