aboutsummaryrefslogtreecommitdiff
path: root/qa
diff options
context:
space:
mode:
Diffstat (limited to 'qa')
-rwxr-xr-xqa/pull-tester/rpc-tests.py23
-rwxr-xr-xqa/rpc-tests/mempool_packages.py3
-rwxr-xr-xqa/rpc-tests/mempool_reorg.py (renamed from qa/rpc-tests/mempool_coinbase_spends.py)26
-rwxr-xr-xqa/rpc-tests/multi_rpc.py122
-rwxr-xr-xqa/rpc-tests/prioritise_transaction.py147
-rwxr-xr-xqa/rpc-tests/smartfees.py3
-rw-r--r--qa/rpc-tests/test_framework/util.py6
-rwxr-xr-xqa/rpc-tests/txn_clone.py2
-rwxr-xr-xqa/rpc-tests/txn_doublespend.py9
9 files changed, 317 insertions, 24 deletions
diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py
index 5004b09c18..df71e44b60 100755
--- a/qa/pull-tester/rpc-tests.py
+++ b/qa/pull-tester/rpc-tests.py
@@ -22,6 +22,7 @@ For a description of arguments recognized by test scripts, see
"""
import os
+import time
import shutil
import sys
import subprocess
@@ -47,6 +48,10 @@ opts = set()
passOn = ""
p = re.compile("^--")
+bold = ("","")
+if (os.name == 'posix'):
+ bold = ('\033[0m', '\033[1m')
+
for arg in sys.argv[1:]:
if arg == '--coverage':
ENABLE_COVERAGE = 1
@@ -77,8 +82,9 @@ testScripts = [
'rawtransactions.py',
'rest.py',
'mempool_spendcoinbase.py',
- 'mempool_coinbase_spends.py',
+ 'mempool_reorg.py',
'httpbasics.py',
+ 'multi_rpc.py',
'zapwallettxes.py',
'proxy_test.py',
'merkle_blocks.py',
@@ -92,6 +98,8 @@ testScripts = [
'blockchain.py',
'disablewallet.py',
'sendheaders.py',
+ 'keypool.py',
+ 'prioritise_transaction.py',
]
testScriptsExt = [
'bip65-cltv.py',
@@ -105,7 +113,6 @@ testScriptsExt = [
'pruning.py',
'forknotify.py',
'invalidateblock.py',
- 'keypool.py',
# 'rpcbind_test.py', #temporary, bug in libevent, see #6655
'smartfees.py',
'maxblocksinflight.py',
@@ -126,7 +133,7 @@ def runtests():
if ENABLE_COVERAGE:
coverage = RPCCoverage()
- print("Initializing coverage directory at %s" % coverage.dir)
+ print("Initializing coverage directory at %s\n" % coverage.dir)
if(ENABLE_WALLET == 1 and ENABLE_UTILS == 1 and ENABLE_BITCOIND == 1):
rpcTestDir = buildDir + '/qa/rpc-tests/'
@@ -141,10 +148,12 @@ def runtests():
or run_extended
or testScripts[i] in opts
or re.sub(".py$", "", testScripts[i]) in opts ):
- print("Running testscript " + testScripts[i] + "...")
+ print("Running testscript %s%s%s ..." % (bold[1], testScripts[i], bold[0]))
+ time0 = time.time()
subprocess.check_call(
rpcTestDir + testScripts[i] + flags, shell=True)
+ print("Duration: %s s\n" % (int(time.time() - time0)))
# exit if help is called so we print just one set of
# instructions
@@ -156,12 +165,14 @@ def runtests():
for i in range(len(testScriptsExt)):
if (run_extended or testScriptsExt[i] in opts
or re.sub(".py$", "", testScriptsExt[i]) in opts):
+
print(
"Running 2nd level testscript "
- + testScriptsExt[i] + "...")
-
+ + "%s%s%s ..." % (bold[1], testScriptsExt[i], bold[0]))
+ time0 = time.time()
subprocess.check_call(
rpcTestDir + testScriptsExt[i] + flags, shell=True)
+ print("Duration: %s s\n" % (int(time.time() - time0)))
if coverage:
coverage.report_rpc_coverage()
diff --git a/qa/rpc-tests/mempool_packages.py b/qa/rpc-tests/mempool_packages.py
index 746c26ff5e..34b316a6a3 100755
--- a/qa/rpc-tests/mempool_packages.py
+++ b/qa/rpc-tests/mempool_packages.py
@@ -8,9 +8,6 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-def satoshi_round(amount):
- return Decimal(amount).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN)
-
MAX_ANCESTORS = 25
MAX_DESCENDANTS = 25
diff --git a/qa/rpc-tests/mempool_coinbase_spends.py b/qa/rpc-tests/mempool_reorg.py
index c64a15b9f5..fdbaf689ad 100755
--- a/qa/rpc-tests/mempool_coinbase_spends.py
+++ b/qa/rpc-tests/mempool_reorg.py
@@ -52,16 +52,25 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
# 3. Indirect (coinbase and child both in chain) : spend_103 and spend_103_1
# Use invalidatblock to make all of the above coinbase spends invalid (immature coinbase),
# and make sure the mempool code behaves correctly.
- b = [ self.nodes[0].getblockhash(n) for n in range(102, 105) ]
+ b = [ self.nodes[0].getblockhash(n) for n in range(101, 105) ]
coinbase_txids = [ self.nodes[0].getblock(h)['tx'][0] for h in b ]
- spend_101_raw = self.create_tx(coinbase_txids[0], node1_address, 50)
- spend_102_raw = self.create_tx(coinbase_txids[1], node0_address, 50)
- spend_103_raw = self.create_tx(coinbase_txids[2], node0_address, 50)
+ spend_101_raw = self.create_tx(coinbase_txids[1], node1_address, 50)
+ spend_102_raw = self.create_tx(coinbase_txids[2], node0_address, 50)
+ spend_103_raw = self.create_tx(coinbase_txids[3], node0_address, 50)
+
+ # Create a block-height-locked transaction which will be invalid after reorg
+ timelock_tx = self.nodes[0].createrawtransaction([{"txid": coinbase_txids[0], "vout": 0}], {node0_address: 50})
+ # Set the time lock
+ timelock_tx = timelock_tx.replace("ffffffff", "11111111", 1)
+ timelock_tx = timelock_tx[:-8] + hex(self.nodes[0].getblockcount() + 2)[2:] + "000000"
+ timelock_tx = self.nodes[0].signrawtransaction(timelock_tx)["hex"]
+ assert_raises(JSONRPCException, self.nodes[0].sendrawtransaction, timelock_tx)
# Broadcast and mine spend_102 and 103:
spend_102_id = self.nodes[0].sendrawtransaction(spend_102_raw)
spend_103_id = self.nodes[0].sendrawtransaction(spend_103_raw)
self.nodes[0].generate(1)
+ assert_raises(JSONRPCException, self.nodes[0].sendrawtransaction, timelock_tx)
# Create 102_1 and 103_1:
spend_102_1_raw = self.create_tx(spend_102_id, node1_address, 50)
@@ -69,7 +78,8 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
# Broadcast and mine 103_1:
spend_103_1_id = self.nodes[0].sendrawtransaction(spend_103_1_raw)
- self.nodes[0].generate(1)
+ last_block = self.nodes[0].generate(1)
+ timelock_tx_id = self.nodes[0].sendrawtransaction(timelock_tx)
# ... now put spend_101 and spend_102_1 in memory pools:
spend_101_id = self.nodes[0].sendrawtransaction(spend_101_raw)
@@ -77,7 +87,11 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
self.sync_all()
- assert_equal(set(self.nodes[0].getrawmempool()), set([ spend_101_id, spend_102_1_id ]))
+ assert_equal(set(self.nodes[0].getrawmempool()), set([ spend_101_id, spend_102_1_id, timelock_tx_id ]))
+
+ for node in self.nodes:
+ node.invalidateblock(last_block[0])
+ assert_equal(set(self.nodes[0].getrawmempool()), set([ spend_101_id, spend_102_1_id, spend_103_1_id ]))
# Use invalidateblock to re-org back and make all those coinbase spends
# immature/invalid:
diff --git a/qa/rpc-tests/multi_rpc.py b/qa/rpc-tests/multi_rpc.py
new file mode 100755
index 0000000000..62071d426e
--- /dev/null
+++ b/qa/rpc-tests/multi_rpc.py
@@ -0,0 +1,122 @@
+#!/usr/bin/env python2
+# Copyright (c) 2015 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 mulitple rpc user config option rpcauth
+#
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
+import base64
+
+try:
+ import http.client as httplib
+except ImportError:
+ import httplib
+try:
+ import urllib.parse as urlparse
+except ImportError:
+ import urlparse
+
+class HTTPBasicsTest (BitcoinTestFramework):
+ def setup_nodes(self):
+ return start_nodes(4, self.options.tmpdir)
+
+ def setup_chain(self):
+ print("Initializing test directory "+self.options.tmpdir)
+ initialize_chain(self.options.tmpdir)
+ #Append rpcauth to bitcoin.conf before initialization
+ rpcauth = "rpcauth=rt:93648e835a54c573682c2eb19f882535$7681e9c5b74bdd85e78166031d2058e1069b3ed7ed967c93fc63abba06f31144"
+ rpcauth2 = "rpcauth=rt2:f8607b1a88861fac29dfccf9b52ff9f$ff36a0c23c8c62b4846112e50fa888416e94c17bfd4c42f88fd8f55ec6a3137e"
+ with open(os.path.join(self.options.tmpdir+"/node0", "bitcoin.conf"), 'a') as f:
+ f.write(rpcauth+"\n")
+ f.write(rpcauth2+"\n")
+
+ def run_test(self):
+
+ ##################################################
+ # Check correctness of the rpcauth config option #
+ ##################################################
+ url = urlparse.urlparse(self.nodes[0].url)
+
+ #Old authpair
+ authpair = url.username + ':' + url.password
+
+ #New authpair generated via contrib/rpcuser tool
+ rpcauth = "rpcauth=rt:93648e835a54c573682c2eb19f882535$7681e9c5b74bdd85e78166031d2058e1069b3ed7ed967c93fc63abba06f31144"
+ password = "cA773lm788buwYe4g4WT+05pKyNruVKjQ25x3n0DQcM="
+
+ #Second authpair with different username
+ rpcauth2 = "rpcauth=rt2:f8607b1a88861fac29dfccf9b52ff9f$ff36a0c23c8c62b4846112e50fa888416e94c17bfd4c42f88fd8f55ec6a3137e"
+ password2 = "8/F3uMDw4KSEbw96U3CA1C4X05dkHDN2BPFjTgZW4KI="
+ authpairnew = "rt:"+password
+
+ headers = {"Authorization": "Basic " + base64.b64encode(authpair)}
+
+ conn = httplib.HTTPConnection(url.hostname, url.port)
+ conn.connect()
+ conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
+ resp = conn.getresponse()
+ assert_equal(resp.status==401, False)
+ conn.close()
+
+ #Use new authpair to confirm both work
+ headers = {"Authorization": "Basic " + base64.b64encode(authpairnew)}
+
+ conn = httplib.HTTPConnection(url.hostname, url.port)
+ conn.connect()
+ conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
+ resp = conn.getresponse()
+ assert_equal(resp.status==401, False)
+ conn.close()
+
+ #Wrong login name with rt's password
+ authpairnew = "rtwrong:"+password
+ headers = {"Authorization": "Basic " + base64.b64encode(authpairnew)}
+
+ conn = httplib.HTTPConnection(url.hostname, url.port)
+ conn.connect()
+ conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
+ resp = conn.getresponse()
+ assert_equal(resp.status==401, True)
+ conn.close()
+
+ #Wrong password for rt
+ authpairnew = "rt:"+password+"wrong"
+ headers = {"Authorization": "Basic " + base64.b64encode(authpairnew)}
+
+ conn = httplib.HTTPConnection(url.hostname, url.port)
+ conn.connect()
+ conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
+ resp = conn.getresponse()
+ assert_equal(resp.status==401, True)
+ conn.close()
+
+ #Correct for rt2
+ authpairnew = "rt2:"+password2
+ headers = {"Authorization": "Basic " + base64.b64encode(authpairnew)}
+
+ conn = httplib.HTTPConnection(url.hostname, url.port)
+ conn.connect()
+ conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
+ resp = conn.getresponse()
+ assert_equal(resp.status==401, False)
+ conn.close()
+
+ #Wrong password for rt2
+ authpairnew = "rt2:"+password2+"wrong"
+ headers = {"Authorization": "Basic " + base64.b64encode(authpairnew)}
+
+ conn = httplib.HTTPConnection(url.hostname, url.port)
+ conn.connect()
+ conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
+ resp = conn.getresponse()
+ assert_equal(resp.status==401, True)
+ conn.close()
+
+
+
+if __name__ == '__main__':
+ HTTPBasicsTest ().main ()
diff --git a/qa/rpc-tests/prioritise_transaction.py b/qa/rpc-tests/prioritise_transaction.py
new file mode 100755
index 0000000000..f376ceee5e
--- /dev/null
+++ b/qa/rpc-tests/prioritise_transaction.py
@@ -0,0 +1,147 @@
+#!/usr/bin/env python2
+# Copyright (c) 2015 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 PrioritiseTransaction code
+#
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
+
+COIN = 100000000
+
+class PrioritiseTransactionTest(BitcoinTestFramework):
+
+ def __init__(self):
+ # Some pre-processing to create a bunch of OP_RETURN txouts to insert into transactions we create
+ # So we have big transactions (and therefore can't fit very many into each block)
+ # create one script_pubkey
+ script_pubkey = "6a4d0200" #OP_RETURN OP_PUSH2 512 bytes
+ for i in xrange (512):
+ script_pubkey = script_pubkey + "01"
+ # concatenate 128 txouts of above script_pubkey which we'll insert before the txout for change
+ self.txouts = "81"
+ for k in xrange(128):
+ # add txout value
+ self.txouts = self.txouts + "0000000000000000"
+ # add length of script_pubkey
+ self.txouts = self.txouts + "fd0402"
+ # add script_pubkey
+ self.txouts = self.txouts + script_pubkey
+
+ def setup_chain(self):
+ print("Initializing test directory "+self.options.tmpdir)
+ initialize_chain_clean(self.options.tmpdir, 1)
+
+ def setup_network(self):
+ self.nodes = []
+ self.is_network_split = False
+
+ self.nodes.append(start_node(0, self.options.tmpdir, ["-debug", "-printpriority=1"]))
+ self.relayfee = self.nodes[0].getnetworkinfo()['relayfee']
+
+ def create_confirmed_utxos(self, count):
+ self.nodes[0].generate(int(0.5*count)+101)
+ utxos = self.nodes[0].listunspent()
+ iterations = count - len(utxos)
+ addr1 = self.nodes[0].getnewaddress()
+ addr2 = self.nodes[0].getnewaddress()
+ if iterations <= 0:
+ return utxos
+ for i in xrange(iterations):
+ t = utxos.pop()
+ fee = self.relayfee
+ inputs = []
+ inputs.append({ "txid" : t["txid"], "vout" : t["vout"]})
+ outputs = {}
+ send_value = t['amount'] - fee
+ outputs[addr1] = satoshi_round(send_value/2)
+ outputs[addr2] = satoshi_round(send_value/2)
+ raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
+ signed_tx = self.nodes[0].signrawtransaction(raw_tx)["hex"]
+ txid = self.nodes[0].sendrawtransaction(signed_tx)
+
+ while (self.nodes[0].getmempoolinfo()['size'] > 0):
+ self.nodes[0].generate(1)
+
+ utxos = self.nodes[0].listunspent()
+ assert(len(utxos) >= count)
+ return utxos
+
+ def create_lots_of_big_transactions(self, utxos, fee):
+ addr = self.nodes[0].getnewaddress()
+ txids = []
+ for i in xrange(len(utxos)):
+ t = utxos.pop()
+ inputs = []
+ inputs.append({ "txid" : t["txid"], "vout" : t["vout"]})
+ outputs = {}
+ send_value = t['amount'] - fee
+ outputs[addr] = satoshi_round(send_value)
+ rawtx = self.nodes[0].createrawtransaction(inputs, outputs)
+ newtx = rawtx[0:92]
+ newtx = newtx + self.txouts
+ newtx = newtx + rawtx[94:]
+ signresult = self.nodes[0].signrawtransaction(newtx, None, None, "NONE")
+ txid = self.nodes[0].sendrawtransaction(signresult["hex"], True)
+ txids.append(txid)
+ return txids
+
+ def run_test(self):
+ utxos = self.create_confirmed_utxos(90)
+ base_fee = self.relayfee*100 # our transactions are smaller than 100kb
+ txids = []
+
+ # Create 3 batches of transactions at 3 different fee rate levels
+ for i in xrange(3):
+ txids.append([])
+ txids[i] = self.create_lots_of_big_transactions(utxos[30*i:30*i+30], (i+1)*base_fee)
+
+ # add a fee delta to something in the cheapest bucket and make sure it gets mined
+ # also check that a different entry in the cheapest bucket is NOT mined (lower
+ # the priority to ensure its not mined due to priority)
+ self.nodes[0].prioritisetransaction(txids[0][0], 0, int(3*base_fee*COIN))
+ self.nodes[0].prioritisetransaction(txids[0][1], -1e15, 0)
+
+ self.nodes[0].generate(1)
+
+ mempool = self.nodes[0].getrawmempool()
+ print "Assert that prioritised transasction was mined"
+ assert(txids[0][0] not in mempool)
+ assert(txids[0][1] in mempool)
+
+ high_fee_tx = None
+ for x in txids[2]:
+ if x not in mempool:
+ high_fee_tx = x
+
+ # Something high-fee should have been mined!
+ assert(high_fee_tx != None)
+
+ # Add a prioritisation before a tx is in the mempool (de-prioritising a
+ # high-fee transaction).
+ self.nodes[0].prioritisetransaction(high_fee_tx, -1e15, -int(2*base_fee*COIN))
+
+ # Add everything back to mempool
+ self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
+
+ # Check to make sure our high fee rate tx is back in the mempool
+ mempool = self.nodes[0].getrawmempool()
+ assert(high_fee_tx in mempool)
+
+ # Now verify the high feerate transaction isn't mined.
+ self.nodes[0].generate(5)
+
+ # High fee transaction should not have been mined, but other high fee rate
+ # transactions should have been.
+ mempool = self.nodes[0].getrawmempool()
+ print "Assert that de-prioritised transaction is still in mempool"
+ assert(high_fee_tx in mempool)
+ for x in txids[2]:
+ if (x != high_fee_tx):
+ assert(x not in mempool)
+
+if __name__ == '__main__':
+ PrioritiseTransactionTest().main()
diff --git a/qa/rpc-tests/smartfees.py b/qa/rpc-tests/smartfees.py
index ecfffc1b45..b209ae0c16 100755
--- a/qa/rpc-tests/smartfees.py
+++ b/qa/rpc-tests/smartfees.py
@@ -19,9 +19,6 @@ P2SH_2 = "2NBdpwq8Aoo1EEKEXPNrKvr5xQr3M9UfcZA" # P2SH of "OP_2 OP_DROP"
# 4 bytes of OP_TRUE and push 2-byte redeem script of "OP_1 OP_DROP" or "OP_2 OP_DROP"
SCRIPT_SIG = ["0451025175", "0451025275"]
-def satoshi_round(amount):
- return Decimal(amount).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN)
-
def small_txpuzzle_randfee(from_node, conflist, unconflist, amount, min_fee, fee_increment):
'''
Create and send a transaction with a random fee.
diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py
index d9d5129f21..b7e90a8a8b 100644
--- a/qa/rpc-tests/test_framework/util.py
+++ b/qa/rpc-tests/test_framework/util.py
@@ -217,7 +217,8 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=
datadir = os.path.join(dirname, "node"+str(i))
if binary is None:
binary = os.getenv("BITCOIND", "bitcoind")
- args = [ binary, "-datadir="+datadir, "-keypool=1", "-discover=0", "-rest" ]
+ # RPC tests still depend on free transactions
+ args = [ binary, "-datadir="+datadir, "-keypool=1", "-discover=0", "-rest", "-blockprioritysize=50000" ]
if extra_args is not None: args.extend(extra_args)
bitcoind_processes[i] = subprocess.Popen(args)
devnull = open(os.devnull, "w")
@@ -404,3 +405,6 @@ def assert_raises(exc, fun, *args, **kwds):
raise AssertionError("Unexpected exception raised: "+type(e).__name__)
else:
raise AssertionError("No exception raised")
+
+def satoshi_round(amount):
+ return Decimal(amount).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN)
diff --git a/qa/rpc-tests/txn_clone.py b/qa/rpc-tests/txn_clone.py
index e8ced0e5bb..b1f603a192 100755
--- a/qa/rpc-tests/txn_clone.py
+++ b/qa/rpc-tests/txn_clone.py
@@ -136,7 +136,7 @@ class TxnMallTest(BitcoinTestFramework):
tx2 = self.nodes[0].gettransaction(txid2)
# Verify expected confirmations
- assert_equal(tx1["confirmations"], -1)
+ assert_equal(tx1["confirmations"], -2)
assert_equal(tx1_clone["confirmations"], 2)
assert_equal(tx2["confirmations"], 1)
diff --git a/qa/rpc-tests/txn_doublespend.py b/qa/rpc-tests/txn_doublespend.py
index 36081127b4..d4665b3d42 100755
--- a/qa/rpc-tests/txn_doublespend.py
+++ b/qa/rpc-tests/txn_doublespend.py
@@ -99,7 +99,7 @@ class TxnMallTest(BitcoinTestFramework):
# Now give doublespend and its parents to miner:
self.nodes[2].sendrawtransaction(fund_foo_tx["hex"])
self.nodes[2].sendrawtransaction(fund_bar_tx["hex"])
- self.nodes[2].sendrawtransaction(doublespend["hex"])
+ doublespend_txid = self.nodes[2].sendrawtransaction(doublespend["hex"])
# ... mine a block...
self.nodes[2].generate(1)
@@ -107,14 +107,15 @@ class TxnMallTest(BitcoinTestFramework):
connect_nodes(self.nodes[1], 2)
self.nodes[2].generate(1) # Mine another block to make sure we sync
sync_blocks(self.nodes)
+ assert_equal(self.nodes[0].gettransaction(doublespend_txid)["confirmations"], 2)
# 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)
+ assert_equal(tx1["confirmations"], -2)
+ assert_equal(tx2["confirmations"], -2)
# Node0's total balance should be starting balance, plus 100BTC for
# two more matured blocks, minus 1240 for the double-spend, plus fees (which are