diff options
Diffstat (limited to 'qa')
-rwxr-xr-x | qa/pull-tester/build-tests.sh.in | 102 | ||||
-rwxr-xr-x | qa/pull-tester/pull-tester.py | 193 | ||||
-rwxr-xr-x | qa/pull-tester/pull-tester.sh | 22 | ||||
-rwxr-xr-x | qa/pull-tester/rpc-tests.sh | 26 | ||||
-rwxr-xr-x | qa/pull-tester/run-bitcoin-cli | 13 | ||||
-rwxr-xr-x | qa/pull-tester/tests-config.sh.in | 16 | ||||
-rwxr-xr-x | qa/rpc-tests/conflictedbalance.sh | 5 | ||||
-rwxr-xr-x | qa/rpc-tests/forknotify.py | 2 | ||||
-rwxr-xr-x | qa/rpc-tests/test_framework.py | 8 | ||||
-rwxr-xr-x | qa/rpc-tests/txn_doublespend.py | 120 | ||||
-rwxr-xr-x | qa/rpc-tests/txnmall.sh | 151 | ||||
-rw-r--r-- | qa/rpc-tests/util.py | 67 | ||||
-rwxr-xr-x | qa/rpc-tests/wallet.py | 100 | ||||
-rwxr-xr-x | qa/rpc-tests/wallet.sh | 117 | ||||
-rwxr-xr-x | qa/rpc-tests/walletbackup.sh | 5 | ||||
-rwxr-xr-x | qa/rpc-tests/zapwallettxes.sh | 5 |
16 files changed, 332 insertions, 620 deletions
diff --git a/qa/pull-tester/build-tests.sh.in b/qa/pull-tester/build-tests.sh.in deleted file mode 100755 index f5c5f0bf70..0000000000 --- a/qa/pull-tester/build-tests.sh.in +++ /dev/null @@ -1,102 +0,0 @@ -#!/bin/bash -# Copyright (c) 2013-2014 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -# -# Param1: The prefix to mingw staging -# Param2: Path to java comparison tool -# Param3: Number of make jobs. Defaults to 1. - -# Exit immediately if anything fails: -set -e -set -o xtrace - -MINGWPREFIX=$1 -JAVA_COMPARISON_TOOL=$2 -RUN_EXPENSIVE_TESTS=$3 -JOBS=${4-1} -OUT_DIR=${5-} - -if [ $# -lt 2 ]; then - echo "Usage: $0 [mingw-prefix] [java-comparison-tool] <make jobs> <save output dir>" - exit 1 -fi - -DISTDIR=@PACKAGE@-@VERSION@ - -# Cross-compile for windows first (breaking the mingw/windows build is most common) -cd @abs_top_srcdir@ -make distdir -mkdir -p win32-build -rsync -av $DISTDIR/ win32-build/ -rm -r $DISTDIR -cd win32-build - -if [ $RUN_EXPENSIVE_TESTS = 1 ]; then - ./configure --disable-silent-rules --disable-ccache --prefix=$MINGWPREFIX --host=i586-mingw32msvc --with-qt-bindir=$MINGWPREFIX/host/bin --with-qt-plugindir=$MINGWPREFIX/plugins --with-qt-incdir=$MINGWPREFIX/include --with-boost=$MINGWPREFIX --with-protoc-bindir=$MINGWPREFIX/host/bin CPPFLAGS=-I$MINGWPREFIX/include LDFLAGS=-L$MINGWPREFIX/lib --with-comparison-tool="$JAVA_COMPARISON_TOOL" -else - ./configure --disable-silent-rules --disable-ccache --prefix=$MINGWPREFIX --host=i586-mingw32msvc --with-qt-bindir=$MINGWPREFIX/host/bin --with-qt-plugindir=$MINGWPREFIX/plugins --with-qt-incdir=$MINGWPREFIX/include --with-boost=$MINGWPREFIX --with-protoc-bindir=$MINGWPREFIX/host/bin CPPFLAGS=-I$MINGWPREFIX/include LDFLAGS=-L$MINGWPREFIX/lib -fi -make -j$JOBS - -# And compile for Linux: -cd @abs_top_srcdir@ -make distdir -mkdir -p linux-build -rsync -av $DISTDIR/ linux-build/ -rm -r $DISTDIR -cd linux-build -if [ $RUN_EXPENSIVE_TESTS = 1 ]; then - ./configure --disable-silent-rules --disable-ccache --with-comparison-tool="$JAVA_COMPARISON_TOOL" --enable-comparison-tool-reorg-tests -else - ./configure --disable-silent-rules --disable-ccache --with-comparison-tool="$JAVA_COMPARISON_TOOL" -fi -make -j$JOBS - -# link interesting binaries to parent out/ directory, if it exists. Do this before -# running unit tests (we want bad binaries to be easy to find) -if [ -d "$OUT_DIR" -a -w "$OUT_DIR" ]; then - set +e - # Windows: - cp @abs_top_srcdir@/win32-build/src/bitcoind.exe $OUT_DIR/bitcoind.exe - cp @abs_top_srcdir@/win32-build/src/test/test_bitcoin.exe $OUT_DIR/test_bitcoin.exe - cp @abs_top_srcdir@/win32-build/src/qt/bitcoind-qt.exe $OUT_DIR/bitcoin-qt.exe - # Linux: - cp @abs_top_srcdir@/linux-build/src/bitcoind $OUT_DIR/bitcoind - cp @abs_top_srcdir@/linux-build/src/test/test_bitcoin $OUT_DIR/test_bitcoin - cp @abs_top_srcdir@/linux-build/src/qt/bitcoind-qt $OUT_DIR/bitcoin-qt - set -e -fi - -# Run unit tests and blockchain-tester on Linux: -cd @abs_top_srcdir@/linux-build -make check - -# Run RPC integration test on Linux: -@abs_top_srcdir@/qa/rpc-tests/wallet.sh @abs_top_srcdir@/linux-build/src -@abs_top_srcdir@/qa/rpc-tests/listtransactions.py --srcdir @abs_top_srcdir@/linux-build/src -@abs_top_srcdir@/qa/rpc-tests/forknotify.py --srcdir @abs_top_srcdir@/linux-build/src -# Clean up cache/ directory that the python regression tests create -rm -rf cache - -if [ $RUN_EXPENSIVE_TESTS = 1 ]; then - # Run unit tests and blockchain-tester on Windows: - cd @abs_top_srcdir@/win32-build - make check -fi - -# Clean up builds (pull-tester machine doesn't have infinite disk space) -cd @abs_top_srcdir@/linux-build -make clean -cd @abs_top_srcdir@/win32-build -make clean - -# TODO: Fix code coverage builds on pull-tester machine -# # Test code coverage -# cd @abs_top_srcdir@ -# make distdir -# mv $DISTDIR linux-coverage-build -# cd linux-coverage-build -# ./configure --enable-lcov --disable-silent-rules --disable-ccache --with-comparison-tool="$JAVA_COMPARISON_TOOL" -# make -j$JOBS -# make cov diff --git a/qa/pull-tester/pull-tester.py b/qa/pull-tester/pull-tester.py deleted file mode 100755 index 66688dd4b5..0000000000 --- a/qa/pull-tester/pull-tester.py +++ /dev/null @@ -1,193 +0,0 @@ -#!/usr/bin/python -# Copyright (c) 2013-2014 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -# -import json -from urllib import urlopen -import requests -import getpass -from string import Template -import sys -import os -import subprocess - -class RunError(Exception): - def __init__(self, value): - self.value = value - def __str__(self): - return repr(self.value) - -def run(command, **kwargs): - fail_hard = kwargs.pop("fail_hard", True) - # output to /dev/null by default: - kwargs.setdefault("stdout", open('/dev/null', 'w')) - kwargs.setdefault("stderr", open('/dev/null', 'w')) - command = Template(command).substitute(os.environ) - if "TRACE" in os.environ: - if 'cwd' in kwargs: - print("[cwd=%s] %s"%(kwargs['cwd'], command)) - else: print(command) - try: - process = subprocess.Popen(command.split(' '), **kwargs) - process.wait() - except KeyboardInterrupt: - process.terminate() - raise - if process.returncode != 0 and fail_hard: - raise RunError("Failed: "+command) - return process.returncode - -def checkout_pull(clone_url, commit, out): - # Init - build_dir=os.environ["BUILD_DIR"] - run("umount ${CHROOT_COPY}/proc", fail_hard=False) - run("rsync --delete -apv ${CHROOT_MASTER}/ ${CHROOT_COPY}") - run("rm -rf ${CHROOT_COPY}${SCRIPTS_DIR}") - run("cp -a ${SCRIPTS_DIR} ${CHROOT_COPY}${SCRIPTS_DIR}") - # Merge onto upstream/master - run("rm -rf ${BUILD_DIR}") - run("mkdir -p ${BUILD_DIR}") - run("git clone ${CLONE_URL} ${BUILD_DIR}") - run("git remote add pull "+clone_url, cwd=build_dir, stdout=out, stderr=out) - run("git fetch pull", cwd=build_dir, stdout=out, stderr=out) - if run("git merge "+ commit, fail_hard=False, cwd=build_dir, stdout=out, stderr=out) != 0: - return False - run("chown -R ${BUILD_USER}:${BUILD_GROUP} ${BUILD_DIR}", stdout=out, stderr=out) - run("mount --bind /proc ${CHROOT_COPY}/proc") - return True - -def commentOn(commentUrl, success, inMerge, needTests, linkUrl): - common_message = """ -This test script verifies pulls every time they are updated. It, however, dies sometimes and fails to test properly. If you are waiting on a test, please check timestamps to verify that the test.log is moving at http://jenkins.bluematt.me/pull-tester/current/ -Contact BlueMatt on freenode if something looks broken.""" - - # Remove old BitcoinPullTester comments (I'm being lazy and not paginating here) - recentcomments = requests.get(commentUrl+"?sort=created&direction=desc", - auth=(os.environ['GITHUB_USER'], os.environ["GITHUB_AUTH_TOKEN"])).json - for comment in recentcomments: - if comment["user"]["login"] == os.environ["GITHUB_USER"] and common_message in comment["body"]: - requests.delete(comment["url"], - auth=(os.environ['GITHUB_USER'], os.environ["GITHUB_AUTH_TOKEN"])) - - if success == True: - if needTests: - message = "Automatic sanity-testing: PLEASE ADD TEST-CASES, though technically passed. See " + linkUrl + " for binaries and test log." - else: - message = "Automatic sanity-testing: PASSED, see " + linkUrl + " for binaries and test log." - - post_data = { "body" : message + common_message} - elif inMerge: - post_data = { "body" : "Automatic sanity-testing: FAILED MERGE, see " + linkUrl + " for test log." + """ - -This pull does not merge cleanly onto current master""" + common_message} - else: - post_data = { "body" : "Automatic sanity-testing: FAILED BUILD/TEST, see " + linkUrl + " for binaries and test log." + """ - -This could happen for one of several reasons: -1. It chanages changes build scripts in a way that made them incompatible with the automated testing scripts (please tweak those patches in qa/pull-tester) -2. It adds/modifies tests which test network rules (thanks for doing that), which conflicts with a patch applied at test time -3. It does not build on either Linux i386 or Win32 (via MinGW cross compile) -4. The test suite fails on either Linux i386 or Win32 -5. The block test-cases failed (lookup the first bNN identifier which failed in https://github.com/TheBlueMatt/test-scripts/blob/master/FullBlockTestGenerator.java) - -If you believe this to be in error, please ping BlueMatt on freenode or TheBlueMatt here. -""" + common_message} - - resp = requests.post(commentUrl, json.dumps(post_data), auth=(os.environ['GITHUB_USER'], os.environ["GITHUB_AUTH_TOKEN"])) - -def testpull(number, comment_url, clone_url, commit): - print("Testing pull %d: %s : %s"%(number, clone_url,commit)) - - dir = os.environ["RESULTS_DIR"] + "/" + commit + "/" - print(" ouput to %s"%dir) - if os.path.exists(dir): - os.system("rm -r " + dir) - os.makedirs(dir) - currentdir = os.environ["RESULTS_DIR"] + "/current" - os.system("rm -r "+currentdir) - os.system("ln -s " + dir + " " + currentdir) - out = open(dir + "test.log", 'w+') - - resultsurl = os.environ["RESULTS_URL"] + commit - checkedout = checkout_pull(clone_url, commit, out) - if checkedout != True: - print("Failed to test pull - sending comment to: " + comment_url) - commentOn(comment_url, False, True, False, resultsurl) - open(os.environ["TESTED_DB"], "a").write(commit + "\n") - return - - run("rm -rf ${CHROOT_COPY}/${OUT_DIR}", fail_hard=False); - run("mkdir -p ${CHROOT_COPY}/${OUT_DIR}", fail_hard=False); - run("chown -R ${BUILD_USER}:${BUILD_GROUP} ${CHROOT_COPY}/${OUT_DIR}", fail_hard=False) - - script = os.environ["BUILD_PATH"]+"/qa/pull-tester/pull-tester.sh" - script += " ${BUILD_PATH} ${MINGW_DEPS_DIR} ${SCRIPTS_DIR}/BitcoindComparisonTool_jar/BitcoindComparisonTool.jar 0 6 ${OUT_DIR}" - returncode = run("chroot ${CHROOT_COPY} sudo -u ${BUILD_USER} -H timeout ${TEST_TIMEOUT} "+script, - fail_hard=False, stdout=out, stderr=out) - - run("mv ${CHROOT_COPY}/${OUT_DIR} " + dir) - run("mv ${BUILD_DIR} " + dir) - - if returncode == 42: - print("Successfully tested pull (needs tests) - sending comment to: " + comment_url) - commentOn(comment_url, True, False, True, resultsurl) - elif returncode != 0: - print("Failed to test pull - sending comment to: " + comment_url) - commentOn(comment_url, False, False, False, resultsurl) - else: - print("Successfully tested pull - sending comment to: " + comment_url) - commentOn(comment_url, True, False, False, resultsurl) - open(os.environ["TESTED_DB"], "a").write(commit + "\n") - -def environ_default(setting, value): - if not setting in os.environ: - os.environ[setting] = value - -if getpass.getuser() != "root": - print("Run me as root!") - sys.exit(1) - -if "GITHUB_USER" not in os.environ or "GITHUB_AUTH_TOKEN" not in os.environ: - print("GITHUB_USER and/or GITHUB_AUTH_TOKEN environment variables not set") - sys.exit(1) - -environ_default("CLONE_URL", "https://github.com/bitcoin/bitcoin.git") -environ_default("MINGW_DEPS_DIR", "/mnt/w32deps") -environ_default("SCRIPTS_DIR", "/mnt/test-scripts") -environ_default("CHROOT_COPY", "/mnt/chroot-tmp") -environ_default("CHROOT_MASTER", "/mnt/chroot") -environ_default("OUT_DIR", "/mnt/out") -environ_default("BUILD_PATH", "/mnt/bitcoin") -os.environ["BUILD_DIR"] = os.environ["CHROOT_COPY"] + os.environ["BUILD_PATH"] -environ_default("RESULTS_DIR", "/mnt/www/pull-tester") -environ_default("RESULTS_URL", "http://jenkins.bluematt.me/pull-tester/") -environ_default("GITHUB_REPO", "bitcoin/bitcoin") -environ_default("TESTED_DB", "/mnt/commits-tested.txt") -environ_default("BUILD_USER", "matt") -environ_default("BUILD_GROUP", "matt") -environ_default("TEST_TIMEOUT", str(60*60*2)) - -print("Optional usage: pull-tester.py 2112") - -f = open(os.environ["TESTED_DB"]) -tested = set( line.rstrip() for line in f.readlines() ) -f.close() - -if len(sys.argv) > 1: - pull = requests.get("https://api.github.com/repos/"+os.environ["GITHUB_REPO"]+"/pulls/"+sys.argv[1], - auth=(os.environ['GITHUB_USER'], os.environ["GITHUB_AUTH_TOKEN"])).json - testpull(pull["number"], pull["_links"]["comments"]["href"], - pull["head"]["repo"]["clone_url"], pull["head"]["sha"]) - -else: - for page in range(1,100): - result = requests.get("https://api.github.com/repos/"+os.environ["GITHUB_REPO"]+"/pulls?state=open&page=%d"%(page,), - auth=(os.environ['GITHUB_USER'], os.environ["GITHUB_AUTH_TOKEN"])).json - if len(result) == 0: break; - for pull in result: - if pull["head"]["sha"] in tested: - print("Pull %d already tested"%(pull["number"],)) - continue - testpull(pull["number"], pull["_links"]["comments"]["href"], - pull["head"]["repo"]["clone_url"], pull["head"]["sha"]) diff --git a/qa/pull-tester/pull-tester.sh b/qa/pull-tester/pull-tester.sh deleted file mode 100755 index 3fe4a05c76..0000000000 --- a/qa/pull-tester/pull-tester.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh -# Copyright (c) 2013-2014 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. -# -# Helper script for pull-tester. -#Param 1: path to bitcoin srcroot -#Param ...: arguments for build-test.sh - -if [ $# -lt 1 ]; then - echo "usage: $0 [bitcoin srcroot] build-test arguments..." -fi - -killall -q bitcoin-cli -killall -q bitcoind - -cd $1 -shift - -./autogen.sh -./configure -./qa/pull-tester/build-tests.sh "$@" diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh new file mode 100755 index 0000000000..e01e870390 --- /dev/null +++ b/qa/pull-tester/rpc-tests.sh @@ -0,0 +1,26 @@ +#!/bin/bash +set -e + +CURDIR=$(cd $(dirname "$0"); pwd) +# Get BUILDDIR and REAL_BITCOIND +. "${CURDIR}/tests-config.sh" + +export BITCOINCLI=${BUILDDIR}/qa/pull-tester/run-bitcoin-cli +export BITCOIND=${REAL_BITCOIND} + +if [ "x${EXEEXT}" = "x.exe" ]; then + echo "Win tests currently disabled" + exit 0 +fi + +#Run the tests + +if [ "x${ENABLE_BITCOIND}${ENABLE_UTILS}${ENABLE_WALLET}" = "x111" ]; then + ${BUILDDIR}/qa/rpc-tests/wallet.py --srcdir "${BUILDDIR}/src" + ${BUILDDIR}/qa/rpc-tests/listtransactions.py --srcdir "${BUILDDIR}/src" + ${BUILDDIR}/qa/rpc-tests/txn_doublespend.py --srcdir "${BUILDDIR}/src" + ${BUILDDIR}/qa/rpc-tests/txn_doublespend.py --mineblock --srcdir "${BUILDDIR}/src" + #${BUILDDIR}/qa/rpc-tests/forknotify.py --srcdir "${BUILDDIR}/src" +else + echo "No rpc tests to run. Wallet, utils, and bitcoind must all be enabled" +fi diff --git a/qa/pull-tester/run-bitcoin-cli b/qa/pull-tester/run-bitcoin-cli new file mode 100755 index 0000000000..93c25bb9fc --- /dev/null +++ b/qa/pull-tester/run-bitcoin-cli @@ -0,0 +1,13 @@ +#!/bin/bash + +# This is a thin wrapper around bitcoin-cli that strips the Windows-style EOLs +# from the output if present. It is necessary when using bitcoin-cli.exe on +# Linux since shells will interpret the line-endings as part of the result. + +CURDIR=$(cd $(dirname "$0"); pwd) +# Get BUILDDIR and REAL_BITCOIND + +# Grab the value of $REAL_BITCOINCLI which may be bitcoin-cli.exe. +. "${CURDIR}/tests-config.sh" + +"${REAL_BITCOINCLI}" "$@" | sed 's/\r//' diff --git a/qa/pull-tester/tests-config.sh.in b/qa/pull-tester/tests-config.sh.in new file mode 100755 index 0000000000..10f4d33e47 --- /dev/null +++ b/qa/pull-tester/tests-config.sh.in @@ -0,0 +1,16 @@ +#!/bin/bash +# Copyright (c) 2013-2014 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +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 + +REAL_BITCOIND="$BUILDDIR/src/bitcoind${EXEEXT}" +REAL_BITCOINCLI="$BUILDDIR/src/bitcoin-cli${EXEEXT}" + diff --git a/qa/rpc-tests/conflictedbalance.sh b/qa/rpc-tests/conflictedbalance.sh index 71761321ed..a112244c74 100755 --- a/qa/rpc-tests/conflictedbalance.sh +++ b/qa/rpc-tests/conflictedbalance.sh @@ -18,13 +18,14 @@ if [ $# -lt 1 ]; then echo "Usage: $0 path_to_binaries" echo "e.g. $0 ../../src" + echo "Env vars BITCOIND and BITCOINCLI may be used to specify the exact binaries used" exit 1 fi set -f -BITCOIND=${1}/bitcoind -CLI=${1}/bitcoin-cli +BITCOIND=${BITCOIND:-${1}/bitcoind} +CLI=${BITCOINCLI:-${1}/bitcoin-cli} DIR="${BASH_SOURCE%/*}" SENDANDWAIT="${DIR}/send.sh" diff --git a/qa/rpc-tests/forknotify.py b/qa/rpc-tests/forknotify.py index a4c2dc944e..1d2c4a9966 100755 --- a/qa/rpc-tests/forknotify.py +++ b/qa/rpc-tests/forknotify.py @@ -23,7 +23,7 @@ class ForkNotifyTest(BitcoinTestFramework): with open(self.alert_filename, 'w') as f: pass # Just open then close to create zero-length file self.nodes.append(start_node(0, self.options.tmpdir, - ["-blockversion=2", "-alertnotify=echo %s >> '" + self.alert_filename + "'"])) + ["-blockversion=2", "-alertnotify=echo %s >> \"" + self.alert_filename + "\""])) # Node1 mines block.version=211 blocks self.nodes.append(start_node(1, self.options.tmpdir, ["-blockversion=211"])) diff --git a/qa/rpc-tests/test_framework.py b/qa/rpc-tests/test_framework.py index c3396a5a83..9591c024fb 100755 --- a/qa/rpc-tests/test_framework.py +++ b/qa/rpc-tests/test_framework.py @@ -44,8 +44,8 @@ class BitcoinTestFramework(object): # on outward. This ensures that chains are properly reorganised. if not split: connect_nodes_bi(self.nodes, 1, 2) - sync_blocks(self.nodes[1:2]) - sync_mempools(self.nodes[1:2]) + sync_blocks(self.nodes[1:3]) + sync_mempools(self.nodes[1:3]) connect_nodes_bi(self.nodes, 0, 1) connect_nodes_bi(self.nodes, 2, 3) @@ -63,9 +63,9 @@ class BitcoinTestFramework(object): def sync_all(self): if self.is_network_split: - sync_blocks(self.nodes[:1]) + sync_blocks(self.nodes[:2]) sync_blocks(self.nodes[2:]) - sync_mempools(self.nodes[:1]) + sync_mempools(self.nodes[:2]) sync_mempools(self.nodes[2:]) else: sync_blocks(self.nodes) diff --git a/qa/rpc-tests/txn_doublespend.py b/qa/rpc-tests/txn_doublespend.py new file mode 100755 index 0000000000..6125147ebc --- /dev/null +++ b/qa/rpc-tests/txn_doublespend.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python +# Copyright (c) 2014 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# +# Test proper accounting with malleable transactions +# + +from test_framework import BitcoinTestFramework +from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException +from decimal import Decimal +from util import * +import os +import shutil + +class TxnMallTest(BitcoinTestFramework): + + 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") + + def setup_network(self): + # Start with split network: + return super(TxnMallTest, self).setup_network(True) + + def run_test(self): + # All nodes should start with 1,250 BTC: + starting_balance = 1250 + for i in range(4): + assert_equal(self.nodes[i].getbalance(), starting_balance) + self.nodes[i].getnewaddress("") # bug workaround, coins generated assigned to first getnewaddress! + + # Assign coins to foo and bar accounts: + self.nodes[0].move("", "foo", 1220) + self.nodes[0].move("", "bar", 30) + assert_equal(self.nodes[0].getbalance(""), 0) + + # Coins are sent to node1_address + node1_address = self.nodes[1].getnewaddress("from0") + + # First: use raw transaction API to send 1210 BTC to node1_address, + # but don't broadcast: + (total_in, inputs) = gather_inputs(self.nodes[0], 1210) + change_address = self.nodes[0].getnewaddress("foo") + outputs = {} + outputs[change_address] = 40 + outputs[node1_address] = 1210 + rawtx = self.nodes[0].createrawtransaction(inputs, outputs) + doublespend = self.nodes[0].signrawtransaction(rawtx) + assert_equal(doublespend["complete"], True) + + # Create two transaction from node[0] to node[1]; the + # second must spend change from the first because the first + # spends all mature inputs: + txid1 = self.nodes[0].sendfrom("foo", node1_address, 1210, 0) + txid2 = self.nodes[0].sendfrom("bar", node1_address, 20, 0) + + # Have node0 mine a block: + if (self.options.mine_block): + self.nodes[0].setgenerate(True, 1) + sync_blocks(self.nodes[0:2]) + + tx1 = self.nodes[0].gettransaction(txid1) + tx2 = self.nodes[0].gettransaction(txid2) + + # Node0's balance should be starting balance, plus 50BTC for another + # matured block, minus 1210, minus 20, and minus transaction fees: + expected = starting_balance + if self.options.mine_block: expected += 50 + expected += tx1["amount"] + tx1["fee"] + expected += tx2["amount"] + tx2["fee"] + assert_equal(self.nodes[0].getbalance(), expected) + + # foo and bar accounts should be debited: + assert_equal(self.nodes[0].getbalance("foo"), 1220+tx1["amount"]+tx1["fee"]) + assert_equal(self.nodes[0].getbalance("bar"), 30+tx2["amount"]+tx2["fee"]) + + if self.options.mine_block: + assert_equal(tx1["confirmations"], 1) + assert_equal(tx2["confirmations"], 1) + # Node1's "from0" balance should be both transaction amounts: + assert_equal(self.nodes[1].getbalance("from0"), -(tx1["amount"]+tx2["amount"])) + else: + assert_equal(tx1["confirmations"], 0) + assert_equal(tx2["confirmations"], 0) + + # Now give doublespend to miner: + mutated_txid = self.nodes[2].sendrawtransaction(doublespend["hex"]) + # ... mine a block... + self.nodes[2].setgenerate(True, 1) + + # Reconnect the split network, and sync chain: + connect_nodes(self.nodes[1], 2) + self.nodes[2].setgenerate(True, 1) # Mine another block to make sure we sync + sync_blocks(self.nodes) + + # Re-fetch transaction info: + tx1 = self.nodes[0].gettransaction(txid1) + tx2 = self.nodes[0].gettransaction(txid2) + + # Both transactions should be conflicted + assert_equal(tx1["confirmations"], -1) + assert_equal(tx2["confirmations"], -1) + + # Node0's total balance should be starting balance, plus 100BTC for + # two more matured blocks, minus 1210 for the double-spend: + expected = starting_balance + 100 - 1210 + assert_equal(self.nodes[0].getbalance(), expected) + assert_equal(self.nodes[0].getbalance("*"), expected) + + # foo account should be debited, but bar account should not: + assert_equal(self.nodes[0].getbalance("foo"), 1220-1210) + assert_equal(self.nodes[0].getbalance("bar"), 30) + + # Node1's "from" account balance should be just the mutated send: + assert_equal(self.nodes[1].getbalance("from0"), 1210) + +if __name__ == '__main__': + TxnMallTest().main() diff --git a/qa/rpc-tests/txnmall.sh b/qa/rpc-tests/txnmall.sh deleted file mode 100755 index 035e7ee15f..0000000000 --- a/qa/rpc-tests/txnmall.sh +++ /dev/null @@ -1,151 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) 2014 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. - -# Test proper accounting with malleable transactions - -if [ $# -lt 1 ]; then - echo "Usage: $0 path_to_binaries" - echo "e.g. $0 ../../src" - exit 1 -fi - -set -f - -BITCOIND=${1}/bitcoind -CLI=${1}/bitcoin-cli - -DIR="${BASH_SOURCE%/*}" -SENDANDWAIT="${DIR}/send.sh" -if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi -. "$DIR/util.sh" - -D=$(mktemp -d test.XXXXX) - -# Two nodes; one will play the part of merchant, the -# other an evil transaction-mutating miner. - -D1=${D}/node1 -CreateDataDir $D1 port=11000 rpcport=11001 -B1ARGS="-datadir=$D1" -$BITCOIND $B1ARGS & -B1PID=$! - -D2=${D}/node2 -CreateDataDir $D2 port=11010 rpcport=11011 -B2ARGS="-datadir=$D2" -$BITCOIND $B2ARGS & -B2PID=$! - -# Wait until both nodes are at the same block number -function WaitBlocks { - while : - do - sleep 1 - declare -i BLOCKS1=$( GetBlocks $B1ARGS ) - declare -i BLOCKS2=$( GetBlocks $B2ARGS ) - if (( BLOCKS1 == BLOCKS2 )) - then - break - fi - done -} - -# Wait until node has $N peers -function WaitPeers { - while : - do - declare -i PEERS=$( $CLI $1 getconnectioncount ) - if (( PEERS == "$2" )) - then - break - fi - sleep 1 - done -} - -echo "Generating test blockchain..." - -# Start with B2 connected to B1: -$CLI $B2ARGS addnode 127.0.0.1:11000 onetry -WaitPeers "$B1ARGS" 1 - -# 1 block, 50 XBT each == 50 XBT -$CLI $B1ARGS setgenerate true 1 - -WaitBlocks -# 100 blocks, 0 mature == 0 XBT -$CLI $B2ARGS setgenerate true 100 -WaitBlocks - -CheckBalance "$B1ARGS" 50 -CheckBalance "$B2ARGS" 0 - -# restart B2 with no connection -$CLI $B2ARGS stop > /dev/null 2>&1 -wait $B2PID -$BITCOIND $B2ARGS & -B2PID=$! - -B2ADDRESS=$( $CLI $B2ARGS getaccountaddress "from1" ) - -# Have B1 create two transactions; second will -# spend change from first, since B1 starts with only a single -# 50 bitcoin output: -$CLI $B1ARGS move "" "foo" 10.0 > /dev/null -$CLI $B1ARGS move "" "bar" 10.0 > /dev/null -TXID1=$( $CLI $B1ARGS sendfrom foo $B2ADDRESS 1.0 0) -TXID2=$( $CLI $B1ARGS sendfrom bar $B2ADDRESS 2.0 0) - -# Mutate TXID1 and add it to B2's memory pool: -RAWTX1=$( $CLI $B1ARGS getrawtransaction $TXID1 ) -# RAWTX1 is hex-encoded, serialized transaction. So each -# byte is two characters; we'll prepend the first -# "push" in the scriptsig with OP_PUSHDATA1 (0x4c), -# and add one to the length of the signature. -# Fields are fixed; from the beginning: -# 4-byte version -# 1-byte varint number-of inputs (one in this case) -# 32-byte previous txid -# 4-byte previous output -# 1-byte varint length-of-scriptsig -# 1-byte PUSH this many bytes onto stack -# ... etc -# So: to mutate, we want to get byte 41 (hex characters 82-83), -# increment it, and insert 0x4c after it. -L=${RAWTX1:82:2} -NEWLEN=$( printf "%x" $(( 16#$L + 1 )) ) -MUTATEDTX1=${RAWTX1:0:82}${NEWLEN}4c${RAWTX1:84} -# ... give mutated tx1 to B2: -MUTATEDTXID=$( $CLI $B2ARGS sendrawtransaction $MUTATEDTX1 ) - -echo "TXID1: " $TXID1 -echo "Mutated: " $MUTATEDTXID - -# Re-connect nodes, and have B2 mine a block -# containing the mutant: -$CLI $B2ARGS addnode 127.0.0.1:11000 onetry -$CLI $B2ARGS setgenerate true 1 -WaitBlocks - -# B1 should have 49 BTC; the 2 BTC send is -# conflicted, and should not count in -# balances. -CheckBalance "$B1ARGS" 49 -CheckBalance "$B1ARGS" 49 "*" -CheckBalance "$B1ARGS" 9 "foo" -CheckBalance "$B1ARGS" 10 "bar" - -# B2 should have 51 BTC -CheckBalance "$B2ARGS" 51 -CheckBalance "$B2ARGS" 1 "from1" - -$CLI $B2ARGS stop > /dev/null 2>&1 -wait $B2PID -$CLI $B1ARGS stop > /dev/null 2>&1 -wait $B1PID - -echo "Tests successful, cleaning up" -rm -rf $D -exit 0 diff --git a/qa/rpc-tests/util.py b/qa/rpc-tests/util.py index 6d0b21c927..bed7fed8ca 100644 --- a/qa/rpc-tests/util.py +++ b/qa/rpc-tests/util.py @@ -57,12 +57,11 @@ def sync_mempools(rpc_connections): if num_match == len(rpc_connections): break time.sleep(1) - bitcoind_processes = {} -def initialize_datadir(dir, n): - datadir = os.path.join(dir, "node"+str(n)) +def initialize_datadir(dirname, n): + datadir = os.path.join(dirname, "node"+str(n)) if not os.path.isdir(datadir): os.makedirs(datadir) with open(os.path.join(datadir, "bitcoin.conf"), 'w') as f: @@ -85,11 +84,11 @@ def initialize_chain(test_dir): # Create cache directories, run bitcoinds: for i in range(4): datadir=initialize_datadir("cache", i) - args = [ "bitcoind", "-keypool=1", "-datadir="+datadir, "-discover=0" ] + args = [ os.getenv("BITCOIND", "bitcoind"), "-keypool=1", "-datadir="+datadir, "-discover=0" ] if i > 0: args.append("-connect=127.0.0.1:"+str(p2p_port(0))) bitcoind_processes[i] = subprocess.Popen(args) - subprocess.check_call([ "bitcoin-cli", "-datadir="+datadir, + subprocess.check_call([ os.getenv("BITCOINCLI", "bitcoin-cli"), "-datadir="+datadir, "-rpcwait", "getblockcount"], stdout=devnull) devnull.close() rpcs = [] @@ -103,12 +102,17 @@ def initialize_chain(test_dir): # Create a 200-block-long chain; each of the 4 nodes # gets 25 mature blocks and 25 immature. - for i in range(4): - rpcs[i].setgenerate(True, 25) - sync_blocks(rpcs) - for i in range(4): - rpcs[i].setgenerate(True, 25) - sync_blocks(rpcs) + # blocks are created with timestamps 10 minutes apart, starting + # at 1 Jan 2014 + block_time = 1388534400 + for i in range(2): + for peer in range(4): + for j in range(25): + set_node_times(rpcs, block_time) + rpcs[peer].setgenerate(True, 1) + block_time += 10*60 + # Must sync before next peer starts generating blocks + sync_blocks(rpcs) # Shut them down, and clean up cache directories: stop_nodes(rpcs) @@ -125,6 +129,15 @@ def initialize_chain(test_dir): shutil.copytree(from_dir, to_dir) initialize_datadir(test_dir, i) # Overwrite port/rpcport in bitcoin.conf +def initialize_chain_clean(test_dir, num_nodes): + """ + Create an empty blockchain and num_nodes wallets. + Useful if a test case wants complete control over initialization. + """ + for i in range(num_nodes): + datadir=initialize_datadir(test_dir, i) + + def _rpchost_to_args(rpchost): '''Convert optional IP:port spec to rpcconnect/rpcport args''' if rpchost is None: @@ -145,16 +158,16 @@ def _rpchost_to_args(rpchost): rv += ['-rpcport=' + rpcport] return rv -def start_node(i, dir, extra_args=None, rpchost=None): +def start_node(i, dirname, extra_args=None, rpchost=None): """ Start a bitcoind and return RPC connection to it """ - datadir = os.path.join(dir, "node"+str(i)) - args = [ "bitcoind", "-datadir="+datadir, "-keypool=1", "-discover=0" ] + datadir = os.path.join(dirname, "node"+str(i)) + args = [ os.getenv("BITCOIND", "bitcoind"), "-datadir="+datadir, "-keypool=1", "-discover=0" ] if extra_args is not None: args.extend(extra_args) bitcoind_processes[i] = subprocess.Popen(args) devnull = open("/dev/null", "w+") - subprocess.check_call([ "bitcoin-cli", "-datadir="+datadir] + + subprocess.check_call([ os.getenv("BITCOINCLI", "bitcoin-cli"), "-datadir="+datadir] + _rpchost_to_args(rpchost) + ["-rpcwait", "getblockcount"], stdout=devnull) devnull.close() @@ -163,15 +176,15 @@ def start_node(i, dir, extra_args=None, rpchost=None): proxy.url = url # store URL on proxy for info return proxy -def start_nodes(num_nodes, dir, extra_args=None, rpchost=None): +def start_nodes(num_nodes, dirname, extra_args=None, rpchost=None): """ Start multiple bitcoinds, return RPC connections to them """ if extra_args is None: extra_args = [ None for i in range(num_nodes) ] - return [ start_node(i, dir, extra_args[i], rpchost) for i in range(num_nodes) ] + return [ start_node(i, dirname, extra_args[i], rpchost) for i in range(num_nodes) ] -def log_filename(dir, n_node, logname): - return os.path.join(dir, "node"+str(n_node), "regtest", logname) +def log_filename(dirname, n_node, logname): + return os.path.join(dirname, "node"+str(n_node), "regtest", logname) def stop_node(node, i): node.stop() @@ -179,10 +192,14 @@ def stop_node(node, i): del bitcoind_processes[i] def stop_nodes(nodes): - for i in range(len(nodes)): - nodes[i].stop() + for node in nodes: + node.stop() del nodes[:] # Emptying array closes connections as a side effect +def set_node_times(nodes, t): + for node in nodes: + node.setmocktime(t) + def wait_bitcoinds(): # Wait for all bitcoinds to cleanly exit for bitcoind in bitcoind_processes.values(): @@ -212,11 +229,13 @@ def find_output(node, txid, amount): return i raise RuntimeError("find_output txid %s : %s not found"%(txid,str(amount))) -def gather_inputs(from_node, amount_needed): + +def gather_inputs(from_node, amount_needed, confirmations_required=1): """ Return a random set of unspent txouts that are enough to pay amount_needed """ - utxo = from_node.listunspent(1) + assert(confirmations_required >=0) + utxo = from_node.listunspent(confirmations_required) random.shuffle(utxo) inputs = [] total_in = Decimal("0.00000000") @@ -225,7 +244,7 @@ def gather_inputs(from_node, amount_needed): total_in += t["amount"] inputs.append({ "txid" : t["txid"], "vout" : t["vout"], "address" : t["address"] } ) if total_in < amount_needed: - raise RuntimeError("Insufficient funds: need %d, have %d"%(amount+fee*2, total_in)) + raise RuntimeError("Insufficient funds: need %d, have %d"%(amount_needed, total_in)) return (total_in, inputs) def make_change(from_node, amount_in, amount_out, fee): diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py new file mode 100755 index 0000000000..4271d96be7 --- /dev/null +++ b/qa/rpc-tests/wallet.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python +# Copyright (c) 2014 The Bitcoin Core developers +# Distributed under the MIT/X11 software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# +# Exercise the wallet. Ported from wallet.sh. +# Does the following: +# a) creates 3 nodes, with an empty chain (no blocks). +# b) node0 mines a block +# c) node1 mines 101 blocks, so now nodes 0 and 1 have 50btc, node2 has none. +# d) node0 sends 21 btc to node2, in two transactions (11 btc, then 10 btc). +# e) node0 mines a block, collects the fee on the second transaction +# f) node1 mines 100 blocks, to mature node0's just-mined block +# g) check that node0 has 100-21, node2 has 21 +# h) node0 should now have 2 unspent outputs; send these to node2 via raw tx broadcast by node1 +# i) have node1 mine a block +# j) check balances - node0 should have 0, node2 should have 100 +# + +from test_framework import BitcoinTestFramework +from util import * + + +class WalletTest (BitcoinTestFramework): + + def setup_chain(self): + print("Initializing test directory "+self.options.tmpdir) + initialize_chain_clean(self.options.tmpdir, 3) + + def setup_network(self, split=False): + self.nodes = start_nodes(3, self.options.tmpdir) + connect_nodes_bi(self.nodes,0,1) + connect_nodes_bi(self.nodes,1,2) + connect_nodes_bi(self.nodes,0,2) + self.is_network_split=False + self.sync_all() + + def run_test (self): + print "Mining blocks..." + + self.nodes[0].setgenerate(True, 1) + + self.sync_all() + self.nodes[1].setgenerate(True, 101) + self.sync_all() + + assert_equal(self.nodes[0].getbalance(), 50) + assert_equal(self.nodes[1].getbalance(), 50) + assert_equal(self.nodes[2].getbalance(), 0) + + # Send 21 BTC from 0 to 2 using sendtoaddress call. + # Second transaction will be child of first, and will require a fee + self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 11) + self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 10) + + # Have node0 mine a block, thus he will collect his own fee. + self.nodes[0].setgenerate(True, 1) + self.sync_all() + + # Have node1 generate 100 blocks (so node0 can recover the fee) + self.nodes[1].setgenerate(True, 100) + self.sync_all() + + # node0 should end up with 100 btc in block rewards plus fees, but + # minus the 21 plus fees sent to node2 + assert_equal(self.nodes[0].getbalance(), 100-21) + assert_equal(self.nodes[2].getbalance(), 21) + + # Node0 should have two unspent outputs. + # Create a couple of transactions to send them to node2, submit them through + # node1, and make sure both node0 and node2 pick them up properly: + node0utxos = self.nodes[0].listunspent(1) + assert_equal(len(node0utxos), 2) + + # create both transactions + txns_to_send = [] + for utxo in node0utxos: + inputs = [] + outputs = {} + inputs.append({ "txid" : utxo["txid"], "vout" : utxo["vout"]}) + outputs[self.nodes[2].getnewaddress("from1")] = utxo["amount"] + raw_tx = self.nodes[0].createrawtransaction(inputs, outputs) + txns_to_send.append(self.nodes[0].signrawtransaction(raw_tx)) + + # Have node 1 (miner) send the transactions + self.nodes[1].sendrawtransaction(txns_to_send[0]["hex"], True) + self.nodes[1].sendrawtransaction(txns_to_send[1]["hex"], True) + + # Have node1 mine a block to confirm transactions: + self.nodes[1].setgenerate(True, 1) + self.sync_all() + + assert_equal(self.nodes[0].getbalance(), 0) + assert_equal(self.nodes[2].getbalance(), 100) + assert_equal(self.nodes[2].getbalance("from1"), 100-21) + + +if __name__ == '__main__': + WalletTest ().main () diff --git a/qa/rpc-tests/wallet.sh b/qa/rpc-tests/wallet.sh deleted file mode 100755 index bb5f34f590..0000000000 --- a/qa/rpc-tests/wallet.sh +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) 2013-2014 The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. - -# Test block generation and basic wallet sending - -if [ $# -lt 1 ]; then - echo "Usage: $0 path_to_binaries" - echo "e.g. $0 ../../src" - exit 1 -fi - -set -f - -BITCOIND=${1}/bitcoind -CLI=${1}/bitcoin-cli - -DIR="${BASH_SOURCE%/*}" -SENDANDWAIT="${DIR}/send.sh" -if [[ ! -d "$DIR" ]]; then DIR="$PWD"; fi -. "$DIR/util.sh" - -D=$(mktemp -d test.XXXXX) - -D1=${D}/node1 -CreateDataDir "$D1" port=11000 rpcport=11001 -B1ARGS="-datadir=$D1" -$BITCOIND $B1ARGS & -B1PID=$! - -D2=${D}/node2 -CreateDataDir "$D2" port=11010 rpcport=11011 connect=127.0.0.1:11000 -B2ARGS="-datadir=$D2" -$BITCOIND $B2ARGS & -B2PID=$! - -D3=${D}/node3 -CreateDataDir "$D3" port=11020 rpcport=11021 connect=127.0.0.1:11000 -B3ARGS="-datadir=$D3" -$BITCOIND $BITCOINDARGS $B3ARGS & -B3PID=$! - -# Wait until all three nodes are at the same block number -function WaitBlocks { - while : - do - sleep 1 - declare -i BLOCKS1=$( GetBlocks $B1ARGS ) - declare -i BLOCKS2=$( GetBlocks $B2ARGS ) - declare -i BLOCKS3=$( GetBlocks $B3ARGS ) - if (( BLOCKS1 == BLOCKS2 && BLOCKS2 == BLOCKS3 )) - then - break - fi - done -} - -echo "Generating test blockchain..." - -# 1 block, 50 XBT each == 50 XBT -$CLI $B1ARGS setgenerate true 1 -WaitBlocks -# 101 blocks, 1 mature == 50 XBT -$CLI $B2ARGS setgenerate true 101 -WaitBlocks - -CheckBalance "$B1ARGS" 50 -CheckBalance "$B2ARGS" 50 - -# Send 21 XBT from 1 to 3. Second -# transaction will be child of first, and -# will require a fee -Send $B1ARGS $B3ARGS 11 -Send $B1ARGS $B3ARGS 10 - -# Have B1 mine a new block, and mature it -# to recover transaction fees -$CLI $B1ARGS setgenerate true 1 -WaitBlocks - -# Have B2 mine 100 blocks so B1's block is mature: -$CLI $B2ARGS setgenerate true 100 -WaitBlocks - -# B1 should end up with 100 XBT in block rewards plus fees, -# minus the 21 XBT sent to B3: -CheckBalance "$B1ARGS" "100-21" -CheckBalance "$B3ARGS" "21" - -# B1 should have two unspent outputs; create a couple -# of raw transactions to send them to B3, submit them through -# B2, and make sure both B1 and B3 pick them up properly: -RAW1=$(CreateTxn1 $B1ARGS 1 $(Address $B3ARGS "from1" ) ) -RAW2=$(CreateTxn1 $B1ARGS 2 $(Address $B3ARGS "from1" ) ) -RAWTXID1=$(SendRawTxn "$B2ARGS" $RAW1) -RAWTXID2=$(SendRawTxn "$B2ARGS" $RAW2) - -# Have B2 mine a block to confirm transactions: -$CLI $B2ARGS setgenerate true 1 -WaitBlocks - -# Check balances after confirmation -CheckBalance "$B1ARGS" 0 -CheckBalance "$B3ARGS" 100 -CheckBalance "$B3ARGS" "100-21" "from1" - -$CLI $B3ARGS stop > /dev/null 2>&1 -wait $B3PID -$CLI $B2ARGS stop > /dev/null 2>&1 -wait $B2PID -$CLI $B1ARGS stop > /dev/null 2>&1 -wait $B1PID - -echo "Tests successful, cleaning up" -rm -rf $D -exit 0 diff --git a/qa/rpc-tests/walletbackup.sh b/qa/rpc-tests/walletbackup.sh index ee11418bef..4af3d97f35 100755 --- a/qa/rpc-tests/walletbackup.sh +++ b/qa/rpc-tests/walletbackup.sh @@ -36,11 +36,12 @@ if [ $# -lt 1 ]; then echo "Usage: $0 path_to_binaries" echo "e.g. $0 ../../src" + echo "Env vars BITCOIND and BITCOINCLI may be used to specify the exact binaries used" exit 1 fi -BITCOIND=${1}/bitcoind -CLI=${1}/bitcoin-cli +BITCOIND=${BITCOIND:-${1}/bitcoind} +CLI=${BITCOINCLI:-${1}/bitcoin-cli} DIR="${BASH_SOURCE%/*}" SENDANDWAIT="${DIR}/send.sh" diff --git a/qa/rpc-tests/zapwallettxes.sh b/qa/rpc-tests/zapwallettxes.sh index e6d490cccc..4312d84e94 100755 --- a/qa/rpc-tests/zapwallettxes.sh +++ b/qa/rpc-tests/zapwallettxes.sh @@ -8,13 +8,14 @@ if [ $# -lt 1 ]; then echo "Usage: $0 path_to_binaries" echo "e.g. $0 ../../src" + echo "Env vars BITCOIND and BITCOINCLI may be used to specify the exact binaries used" exit 1 fi set -f -BITCOIND=${1}/bitcoind -CLI=${1}/bitcoin-cli +BITCOIND=${BITCOIND:-${1}/bitcoind} +CLI=${BITCOINCLI:-${1}/bitcoin-cli} DIR="${BASH_SOURCE%/*}" SENDANDWAIT="${DIR}/send.sh" |