aboutsummaryrefslogtreecommitdiff
path: root/qa
diff options
context:
space:
mode:
authorLuke Dashjr <luke-jr+git@utopios.org>2016-02-27 06:11:04 +0000
committerLuke Dashjr <luke-jr+git@utopios.org>2016-02-27 06:11:37 +0000
commite5daa2e2aef61f0b9441d19f0b67015f426c6056 (patch)
tree90a095dcd23c8a74cb605f55e224a902cba75a06 /qa
parent5c70a6d6d15cc301b76558f708948c375fe63ccb (diff)
parent317462123f8e41fd7dd967ab907e59ddffb19898 (diff)
Merge branch 'master' into depends_curl
Diffstat (limited to 'qa')
-rwxr-xr-xqa/pull-tester/rpc-tests.py14
-rw-r--r--qa/rpc-tests/README.md5
-rwxr-xr-xqa/rpc-tests/abandonconflict.py153
-rwxr-xr-xqa/rpc-tests/bip65-cltv-p2p.py8
-rwxr-xr-xqa/rpc-tests/bip65-cltv.py4
-rwxr-xr-xqa/rpc-tests/bip68-sequence.py387
-rwxr-xr-xqa/rpc-tests/bipdersig-p2p.py4
-rwxr-xr-xqa/rpc-tests/bipdersig.py6
-rwxr-xr-xqa/rpc-tests/blockchain.py42
-rwxr-xr-xqa/rpc-tests/decodescript.py4
-rwxr-xr-xqa/rpc-tests/disablewallet.py3
-rwxr-xr-xqa/rpc-tests/forknotify.py4
-rwxr-xr-xqa/rpc-tests/fundrawtransaction.py61
-rwxr-xr-xqa/rpc-tests/getblocktemplate_longpoll.py2
-rwxr-xr-xqa/rpc-tests/getblocktemplate_proposals.py2
-rwxr-xr-xqa/rpc-tests/getchaintips.py6
-rwxr-xr-xqa/rpc-tests/httpbasics.py16
-rwxr-xr-xqa/rpc-tests/invalidateblock.py2
-rwxr-xr-xqa/rpc-tests/invalidblockrequest.py10
-rwxr-xr-xqa/rpc-tests/invalidtxrequest.py72
-rwxr-xr-xqa/rpc-tests/keypool.py8
-rwxr-xr-xqa/rpc-tests/listtransactions.py116
-rwxr-xr-xqa/rpc-tests/maxblocksinflight.py3
-rwxr-xr-xqa/rpc-tests/maxuploadtarget.py18
-rwxr-xr-xqa/rpc-tests/mempool_limit.py55
-rwxr-xr-xqa/rpc-tests/mempool_packages.py33
-rwxr-xr-xqa/rpc-tests/mempool_reorg.py22
-rwxr-xr-xqa/rpc-tests/mempool_resurrect_test.py8
-rwxr-xr-xqa/rpc-tests/mempool_spendcoinbase.py6
-rwxr-xr-xqa/rpc-tests/merkle_blocks.py12
-rwxr-xr-xqa/rpc-tests/nodehandling.py7
-rwxr-xr-xqa/rpc-tests/p2p-acceptblock.py3
-rwxr-xr-xqa/rpc-tests/p2p-fullblocktest.py164
-rwxr-xr-xqa/rpc-tests/prioritise_transaction.py107
-rwxr-xr-xqa/rpc-tests/proxy_test.py6
-rwxr-xr-xqa/rpc-tests/pruning.py22
-rwxr-xr-xqa/rpc-tests/rawtransactions.py18
-rwxr-xr-xqa/rpc-tests/receivedby.py7
-rwxr-xr-xqa/rpc-tests/reindex.py3
-rwxr-xr-xqa/rpc-tests/replace-by-fee.py83
-rwxr-xr-xqa/rpc-tests/rest.py16
-rwxr-xr-xqa/rpc-tests/rpcbind_test.py9
-rwxr-xr-xqa/rpc-tests/sendheaders.py26
-rw-r--r--qa/rpc-tests/test_framework/blocktools.py4
-rwxr-xr-xqa/rpc-tests/test_framework/comptool.py43
-rw-r--r--qa/rpc-tests/test_framework/coverage.py6
-rwxr-xr-xqa/rpc-tests/test_framework/mininode.py50
-rw-r--r--qa/rpc-tests/test_framework/netutil.py2
-rw-r--r--qa/rpc-tests/test_framework/script.py16
-rwxr-xr-xqa/rpc-tests/test_framework/test_framework.py4
-rw-r--r--qa/rpc-tests/test_framework/util.py127
-rwxr-xr-xqa/rpc-tests/txn_clone.py23
-rwxr-xr-xqa/rpc-tests/txn_doublespend.py5
-rwxr-xr-xqa/rpc-tests/wallet.py77
-rwxr-xr-xqa/rpc-tests/walletbackup.py2
-rwxr-xr-xqa/rpc-tests/zapwallettxes.py2
-rwxr-xr-xqa/rpc-tests/zmq_test.py7
57 files changed, 1523 insertions, 402 deletions
diff --git a/qa/pull-tester/rpc-tests.py b/qa/pull-tester/rpc-tests.py
index df71e44b60..7649c1183b 100755
--- a/qa/pull-tester/rpc-tests.py
+++ b/qa/pull-tester/rpc-tests.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
@@ -62,8 +62,10 @@ for arg in sys.argv[1:]:
#Set env vars
buildDir = BUILDDIR
-os.environ["BITCOIND"] = buildDir + '/src/bitcoind' + EXEEXT
-os.environ["BITCOINCLI"] = buildDir + '/src/bitcoin-cli' + EXEEXT
+if "BITCOIND" not in os.environ:
+ os.environ["BITCOIND"] = buildDir + '/src/bitcoind' + EXEEXT
+if "BITCOINCLI" not in os.environ:
+ os.environ["BITCOINCLI"] = buildDir + '/src/bitcoin-cli' + EXEEXT
#Disable Windows tests by default
if EXEEXT == ".exe" and "-win" not in opts:
@@ -83,6 +85,7 @@ testScripts = [
'rest.py',
'mempool_spendcoinbase.py',
'mempool_reorg.py',
+ 'mempool_limit.py',
'httpbasics.py',
'multi_rpc.py',
'zapwallettxes.py',
@@ -100,10 +103,14 @@ testScripts = [
'sendheaders.py',
'keypool.py',
'prioritise_transaction.py',
+ 'invalidblockrequest.py',
+ 'invalidtxrequest.py',
+ 'abandonconflict.py',
]
testScriptsExt = [
'bip65-cltv.py',
'bip65-cltv-p2p.py',
+ 'bip68-sequence.py',
'bipdersig-p2p.py',
'bipdersig.py',
'getblocktemplate_longpoll.py',
@@ -116,7 +123,6 @@ testScriptsExt = [
# 'rpcbind_test.py', #temporary, bug in libevent, see #6655
'smartfees.py',
'maxblocksinflight.py',
- 'invalidblockrequest.py',
'p2p-acceptblock.py',
'mempool_packages.py',
'maxuploadtarget.py',
diff --git a/qa/rpc-tests/README.md b/qa/rpc-tests/README.md
index 898931936b..651b01f18a 100644
--- a/qa/rpc-tests/README.md
+++ b/qa/rpc-tests/README.md
@@ -47,10 +47,7 @@ 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.
+events of interest arrive.
* 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.
diff --git a/qa/rpc-tests/abandonconflict.py b/qa/rpc-tests/abandonconflict.py
new file mode 100755
index 0000000000..38028df079
--- /dev/null
+++ b/qa/rpc-tests/abandonconflict.py
@@ -0,0 +1,153 @@
+#!/usr/bin/env python2
+# Copyright (c) 2014-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.
+
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
+try:
+ import urllib.parse as urlparse
+except ImportError:
+ import urlparse
+
+class AbandonConflictTest(BitcoinTestFramework):
+
+ def setup_network(self):
+ self.nodes = []
+ self.nodes.append(start_node(0, self.options.tmpdir, ["-debug","-logtimemicros","-minrelaytxfee=0.00001"]))
+ self.nodes.append(start_node(1, self.options.tmpdir, ["-debug","-logtimemicros"]))
+ connect_nodes(self.nodes[0], 1)
+
+ def run_test(self):
+ self.nodes[1].generate(100)
+ sync_blocks(self.nodes)
+ balance = self.nodes[0].getbalance()
+ txA = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), Decimal("10"))
+ txB = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), Decimal("10"))
+ txC = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), Decimal("10"))
+ sync_mempools(self.nodes)
+ self.nodes[1].generate(1)
+
+ sync_blocks(self.nodes)
+ newbalance = self.nodes[0].getbalance()
+ assert(balance - newbalance < Decimal("0.001")) #no more than fees lost
+ balance = newbalance
+
+ url = urlparse.urlparse(self.nodes[1].url)
+ self.nodes[0].disconnectnode(url.hostname+":"+str(p2p_port(1)))
+
+ # Identify the 10btc outputs
+ nA = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(txA, 1)["vout"]) if vout["value"] == Decimal("10"))
+ nB = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(txB, 1)["vout"]) if vout["value"] == Decimal("10"))
+ nC = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(txC, 1)["vout"]) if vout["value"] == Decimal("10"))
+
+ inputs =[]
+ # spend 10btc outputs from txA and txB
+ inputs.append({"txid":txA, "vout":nA})
+ inputs.append({"txid":txB, "vout":nB})
+ outputs = {}
+
+ outputs[self.nodes[0].getnewaddress()] = Decimal("14.99998")
+ outputs[self.nodes[1].getnewaddress()] = Decimal("5")
+ signed = self.nodes[0].signrawtransaction(self.nodes[0].createrawtransaction(inputs, outputs))
+ txAB1 = self.nodes[0].sendrawtransaction(signed["hex"])
+
+ # Identify the 14.99998btc output
+ nAB = next(i for i, vout in enumerate(self.nodes[0].getrawtransaction(txAB1, 1)["vout"]) if vout["value"] == Decimal("14.99998"))
+
+ #Create a child tx spending AB1 and C
+ inputs = []
+ inputs.append({"txid":txAB1, "vout":nAB})
+ inputs.append({"txid":txC, "vout":nC})
+ outputs = {}
+ outputs[self.nodes[0].getnewaddress()] = Decimal("24.9996")
+ signed2 = self.nodes[0].signrawtransaction(self.nodes[0].createrawtransaction(inputs, outputs))
+ txABC2 = self.nodes[0].sendrawtransaction(signed2["hex"])
+
+ # In mempool txs from self should increase balance from change
+ newbalance = self.nodes[0].getbalance()
+ assert(newbalance == balance - Decimal("30") + Decimal("24.9996"))
+ balance = newbalance
+
+ # Restart the node with a higher min relay fee so the parent tx is no longer in mempool
+ # TODO: redo with eviction
+ # Note had to make sure tx did not have AllowFree priority
+ stop_node(self.nodes[0],0)
+ self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug","-logtimemicros","-minrelaytxfee=0.0001"])
+
+ # Verify txs no longer in mempool
+ assert(len(self.nodes[0].getrawmempool()) == 0)
+
+ # Not in mempool txs from self should only reduce balance
+ # inputs are still spent, but change not received
+ newbalance = self.nodes[0].getbalance()
+ assert(newbalance == balance - Decimal("24.9996"))
+ balance = newbalance
+
+ # Abandon original transaction and verify inputs are available again
+ # including that the child tx was also abandoned
+ self.nodes[0].abandontransaction(txAB1)
+ newbalance = self.nodes[0].getbalance()
+ assert(newbalance == balance + Decimal("30"))
+ balance = newbalance
+
+ # Verify that even with a low min relay fee, the tx is not reaccepted from wallet on startup once abandoned
+ stop_node(self.nodes[0],0)
+ self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug","-logtimemicros","-minrelaytxfee=0.00001"])
+ assert(len(self.nodes[0].getrawmempool()) == 0)
+ assert(self.nodes[0].getbalance() == balance)
+
+ # But if its received again then it is unabandoned
+ # And since now in mempool, the change is available
+ # But its child tx remains abandoned
+ self.nodes[0].sendrawtransaction(signed["hex"])
+ newbalance = self.nodes[0].getbalance()
+ assert(newbalance == balance - Decimal("20") + Decimal("14.99998"))
+ balance = newbalance
+
+ # Send child tx again so its unabandoned
+ self.nodes[0].sendrawtransaction(signed2["hex"])
+ newbalance = self.nodes[0].getbalance()
+ assert(newbalance == balance - Decimal("10") - Decimal("14.99998") + Decimal("24.9996"))
+ balance = newbalance
+
+ # Remove using high relay fee again
+ stop_node(self.nodes[0],0)
+ self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug","-logtimemicros","-minrelaytxfee=0.0001"])
+ assert(len(self.nodes[0].getrawmempool()) == 0)
+ newbalance = self.nodes[0].getbalance()
+ assert(newbalance == balance - Decimal("24.9996"))
+ balance = newbalance
+
+ # Create a double spend of AB1 by spending again from only A's 10 output
+ # Mine double spend from node 1
+ inputs =[]
+ inputs.append({"txid":txA, "vout":nA})
+ outputs = {}
+ outputs[self.nodes[1].getnewaddress()] = Decimal("9.9999")
+ tx = self.nodes[0].createrawtransaction(inputs, outputs)
+ signed = self.nodes[0].signrawtransaction(tx)
+ self.nodes[1].sendrawtransaction(signed["hex"])
+ self.nodes[1].generate(1)
+
+ connect_nodes(self.nodes[0], 1)
+ sync_blocks(self.nodes)
+
+ # Verify that B and C's 10 BTC outputs are available for spending again because AB1 is now conflicted
+ newbalance = self.nodes[0].getbalance()
+ assert(newbalance == balance + Decimal("20"))
+ balance = newbalance
+
+ # There is currently a minor bug around this and so this test doesn't work. See Issue #7315
+ # Invalidate the block with the double spend and B's 10 BTC output should no longer be available
+ # Don't think C's should either
+ self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
+ newbalance = self.nodes[0].getbalance()
+ #assert(newbalance == balance - Decimal("10"))
+ print "If balance has not declined after invalidateblock then out of mempool wallet tx which is no longer"
+ print "conflicted has not resumed causing its inputs to be seen as spent. See Issue #7315"
+ print balance , " -> " , newbalance , " ?"
+
+if __name__ == '__main__':
+ AbandonConflictTest().main()
diff --git a/qa/rpc-tests/bip65-cltv-p2p.py b/qa/rpc-tests/bip65-cltv-p2p.py
index 9ca5c69f16..bbd518cf5f 100755
--- a/qa/rpc-tests/bip65-cltv-p2p.py
+++ b/qa/rpc-tests/bip65-cltv-p2p.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-#
+# Copyright (c) 2015 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.
#
@@ -9,8 +9,8 @@ from test_framework.util import *
from test_framework.mininode import CTransaction, NetworkThread
from test_framework.blocktools import create_coinbase, create_block
from test_framework.comptool import TestInstance, TestManager
-from test_framework.script import CScript, OP_1NEGATE, OP_NOP2, OP_DROP
-from binascii import hexlify, unhexlify
+from test_framework.script import CScript, OP_1NEGATE, OP_CHECKLOCKTIMEVERIFY, OP_DROP
+from binascii import unhexlify
import cStringIO
import time
@@ -19,7 +19,7 @@ def cltv_invalidate(tx):
Prepends -1 CLTV DROP in the scriptSig itself.
'''
- tx.vin[0].scriptSig = CScript([OP_1NEGATE, OP_NOP2, OP_DROP] +
+ tx.vin[0].scriptSig = CScript([OP_1NEGATE, OP_CHECKLOCKTIMEVERIFY, OP_DROP] +
list(CScript(tx.vin[0].scriptSig)))
'''
diff --git a/qa/rpc-tests/bip65-cltv.py b/qa/rpc-tests/bip65-cltv.py
index e90e11e6a7..f666a07c9b 100755
--- a/qa/rpc-tests/bip65-cltv.py
+++ b/qa/rpc-tests/bip65-cltv.py
@@ -9,8 +9,6 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-import os
-import shutil
class BIP65Test(BitcoinTestFramework):
@@ -46,7 +44,7 @@ class BIP65Test(BitcoinTestFramework):
self.nodes[2].generate(1)
self.sync_all()
if (self.nodes[0].getblockcount() != cnt + 851):
- raise AssertionFailure("Failed to mine a version=4 blocks")
+ raise AssertionError("Failed to mine a version=4 blocks")
# TODO: check that new CHECKLOCKTIMEVERIFY rules are enforced
diff --git a/qa/rpc-tests/bip68-sequence.py b/qa/rpc-tests/bip68-sequence.py
new file mode 100755
index 0000000000..bd61282fa1
--- /dev/null
+++ b/qa/rpc-tests/bip68-sequence.py
@@ -0,0 +1,387 @@
+#!/usr/bin/env python2
+# Copyright (c) 2014-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 BIP68 implementation (mempool only)
+#
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
+from test_framework.script import *
+from test_framework.mininode import *
+from test_framework.blocktools import *
+
+COIN = 100000000
+SEQUENCE_LOCKTIME_DISABLE_FLAG = (1<<31)
+SEQUENCE_LOCKTIME_TYPE_FLAG = (1<<22) # this means use time (0 means height)
+SEQUENCE_LOCKTIME_GRANULARITY = 9 # this is a bit-shift
+SEQUENCE_LOCKTIME_MASK = 0x0000ffff
+
+# RPC error for non-BIP68 final transactions
+NOT_FINAL_ERROR = "64: non-BIP68-final"
+
+class BIP68Test(BitcoinTestFramework):
+
+ def setup_network(self):
+ self.nodes = []
+ self.nodes.append(start_node(0, self.options.tmpdir, ["-debug", "-blockprioritysize=0"]))
+ self.is_network_split = False
+ self.relayfee = self.nodes[0].getnetworkinfo()["relayfee"]
+
+ def run_test(self):
+ # Generate some coins
+ self.nodes[0].generate(110)
+
+ print "Running test disable flag"
+ self.test_disable_flag()
+
+ print "Running test sequence-lock-confirmed-inputs"
+ self.test_sequence_lock_confirmed_inputs()
+
+ print "Running test sequence-lock-unconfirmed-inputs"
+ self.test_sequence_lock_unconfirmed_inputs()
+
+ # This test needs to change when BIP68 becomes consensus
+ print "Running test BIP68 not consensus"
+ self.test_bip68_not_consensus()
+
+ print "Passed\n"
+
+ # Test that BIP68 is not in effect if tx version is 1, or if
+ # the first sequence bit is set.
+ def test_disable_flag(self):
+ # Create some unconfirmed inputs
+ new_addr = self.nodes[0].getnewaddress()
+ self.nodes[0].sendtoaddress(new_addr, 2) # send 2 BTC
+
+ utxos = self.nodes[0].listunspent(0, 0)
+ assert(len(utxos) > 0)
+
+ utxo = utxos[0]
+
+ tx1 = CTransaction()
+ value = satoshi_round(utxo["amount"] - self.relayfee)*COIN
+
+ # Check that the disable flag disables relative locktime.
+ # If sequence locks were used, this would require 1 block for the
+ # input to mature.
+ sequence_value = SEQUENCE_LOCKTIME_DISABLE_FLAG | 1
+ tx1.vin = [CTxIn(COutPoint(int(utxo["txid"], 16), utxo["vout"]), nSequence=sequence_value)]
+ tx1.vout = [CTxOut(value, CScript([b'a']))]
+
+ tx1_signed = self.nodes[0].signrawtransaction(ToHex(tx1))["hex"]
+ tx1_id = self.nodes[0].sendrawtransaction(tx1_signed)
+ tx1_id = int(tx1_id, 16)
+
+ # This transaction will enable sequence-locks, so this transaction should
+ # fail
+ tx2 = CTransaction()
+ tx2.nVersion = 2
+ sequence_value = sequence_value & 0x7fffffff
+ tx2.vin = [CTxIn(COutPoint(tx1_id, 0), nSequence=sequence_value)]
+ tx2.vout = [CTxOut(int(value-self.relayfee*COIN), CScript([b'a']))]
+ tx2.rehash()
+
+ try:
+ self.nodes[0].sendrawtransaction(ToHex(tx2))
+ except JSONRPCException as exp:
+ assert_equal(exp.error["message"], NOT_FINAL_ERROR)
+ else:
+ assert(False)
+
+ # Setting the version back down to 1 should disable the sequence lock,
+ # so this should be accepted.
+ tx2.nVersion = 1
+
+ self.nodes[0].sendrawtransaction(ToHex(tx2))
+
+ # Calculate the median time past of a prior block ("confirmations" before
+ # the current tip).
+ def get_median_time_past(self, confirmations):
+ block_hash = self.nodes[0].getblockhash(self.nodes[0].getblockcount()-confirmations)
+ return self.nodes[0].getblockheader(block_hash)["mediantime"]
+
+ # Test that sequence locks are respected for transactions spending confirmed inputs.
+ def test_sequence_lock_confirmed_inputs(self):
+ # Create lots of confirmed utxos, and use them to generate lots of random
+ # transactions.
+ max_outputs = 50
+ addresses = []
+ while len(addresses) < max_outputs:
+ addresses.append(self.nodes[0].getnewaddress())
+ while len(self.nodes[0].listunspent()) < 200:
+ import random
+ random.shuffle(addresses)
+ num_outputs = random.randint(1, max_outputs)
+ outputs = {}
+ for i in xrange(num_outputs):
+ outputs[addresses[i]] = random.randint(1, 20)*0.01
+ self.nodes[0].sendmany("", outputs)
+ self.nodes[0].generate(1)
+
+ utxos = self.nodes[0].listunspent()
+
+ # Try creating a lot of random transactions.
+ # Each time, choose a random number of inputs, and randomly set
+ # some of those inputs to be sequence locked (and randomly choose
+ # between height/time locking). Small random chance of making the locks
+ # all pass.
+ for i in xrange(400):
+ # Randomly choose up to 10 inputs
+ num_inputs = random.randint(1, 10)
+ random.shuffle(utxos)
+
+ # Track whether any sequence locks used should fail
+ should_pass = True
+
+ # Track whether this transaction was built with sequence locks
+ using_sequence_locks = False
+
+ tx = CTransaction()
+ tx.nVersion = 2
+ value = 0
+ for j in xrange(num_inputs):
+ sequence_value = 0xfffffffe # this disables sequence locks
+
+ # 50% chance we enable sequence locks
+ if random.randint(0,1):
+ using_sequence_locks = True
+
+ # 10% of the time, make the input sequence value pass
+ input_will_pass = (random.randint(1,10) == 1)
+ sequence_value = utxos[j]["confirmations"]
+ if not input_will_pass:
+ sequence_value += 1
+ should_pass = False
+
+ # Figure out what the median-time-past was for the confirmed input
+ # Note that if an input has N confirmations, we're going back N blocks
+ # from the tip so that we're looking up MTP of the block
+ # PRIOR to the one the input appears in, as per the BIP68 spec.
+ orig_time = self.get_median_time_past(utxos[j]["confirmations"])
+ cur_time = self.get_median_time_past(0) # MTP of the tip
+
+ # can only timelock this input if it's not too old -- otherwise use height
+ can_time_lock = True
+ if ((cur_time - orig_time) >> SEQUENCE_LOCKTIME_GRANULARITY) >= SEQUENCE_LOCKTIME_MASK:
+ can_time_lock = False
+
+ # if time-lockable, then 50% chance we make this a time lock
+ if random.randint(0,1) and can_time_lock:
+ # Find first time-lock value that fails, or latest one that succeeds
+ time_delta = sequence_value << SEQUENCE_LOCKTIME_GRANULARITY
+ if input_will_pass and time_delta > cur_time - orig_time:
+ sequence_value = ((cur_time - orig_time) >> SEQUENCE_LOCKTIME_GRANULARITY)
+ elif (not input_will_pass and time_delta <= cur_time - orig_time):
+ sequence_value = ((cur_time - orig_time) >> SEQUENCE_LOCKTIME_GRANULARITY)+1
+ sequence_value |= SEQUENCE_LOCKTIME_TYPE_FLAG
+ tx.vin.append(CTxIn(COutPoint(int(utxos[j]["txid"], 16), utxos[j]["vout"]), nSequence=sequence_value))
+ value += utxos[j]["amount"]*COIN
+ # Overestimate the size of the tx - signatures should be less than 120 bytes, and leave 50 for the output
+ tx_size = len(ToHex(tx))/2 + 120*num_inputs + 50
+ tx.vout.append(CTxOut(value-self.relayfee*tx_size*COIN/1000, CScript([b'a'])))
+ rawtx = self.nodes[0].signrawtransaction(ToHex(tx))["hex"]
+
+ try:
+ self.nodes[0].sendrawtransaction(rawtx)
+ except JSONRPCException as exp:
+ assert(not should_pass and using_sequence_locks)
+ assert_equal(exp.error["message"], NOT_FINAL_ERROR)
+ else:
+ assert(should_pass or not using_sequence_locks)
+ # Recalculate utxos if we successfully sent the transaction
+ utxos = self.nodes[0].listunspent()
+
+ # Test that sequence locks on unconfirmed inputs must have nSequence
+ # height or time of 0 to be accepted.
+ # Then test that BIP68-invalid transactions are removed from the mempool
+ # after a reorg.
+ def test_sequence_lock_unconfirmed_inputs(self):
+ # Store height so we can easily reset the chain at the end of the test
+ cur_height = self.nodes[0].getblockcount()
+
+ # Create a mempool tx.
+ txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 2)
+ tx1 = FromHex(CTransaction(), self.nodes[0].getrawtransaction(txid))
+ tx1.rehash()
+
+ # Anyone-can-spend mempool tx.
+ # Sequence lock of 0 should pass.
+ tx2 = CTransaction()
+ tx2.nVersion = 2
+ tx2.vin = [CTxIn(COutPoint(tx1.sha256, 0), nSequence=0)]
+ tx2.vout = [CTxOut(int(tx1.vout[0].nValue - self.relayfee*COIN), CScript([b'a']))]
+ tx2_raw = self.nodes[0].signrawtransaction(ToHex(tx2))["hex"]
+ tx2 = FromHex(tx2, tx2_raw)
+ tx2.rehash()
+
+ self.nodes[0].sendrawtransaction(tx2_raw)
+
+ # Create a spend of the 0th output of orig_tx with a sequence lock
+ # of 1, and test what happens when submitting.
+ # orig_tx.vout[0] must be an anyone-can-spend output
+ def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock):
+ sequence_value = 1
+ if not use_height_lock:
+ sequence_value |= SEQUENCE_LOCKTIME_TYPE_FLAG
+
+ tx = CTransaction()
+ tx.nVersion = 2
+ tx.vin = [CTxIn(COutPoint(orig_tx.sha256, 0), nSequence=sequence_value)]
+ tx.vout = [CTxOut(int(orig_tx.vout[0].nValue - relayfee*COIN), CScript([b'a']))]
+ tx.rehash()
+
+ try:
+ node.sendrawtransaction(ToHex(tx))
+ except JSONRPCException as exp:
+ assert_equal(exp.error["message"], NOT_FINAL_ERROR)
+ assert(orig_tx.hash in node.getrawmempool())
+ else:
+ # orig_tx must not be in mempool
+ assert(orig_tx.hash not in node.getrawmempool())
+ return tx
+
+ test_nonzero_locks(tx2, self.nodes[0], self.relayfee, use_height_lock=True)
+ test_nonzero_locks(tx2, self.nodes[0], self.relayfee, use_height_lock=False)
+
+ # Now mine some blocks, but make sure tx2 doesn't get mined.
+ # Use prioritisetransaction to lower the effective feerate to 0
+ self.nodes[0].prioritisetransaction(tx2.hash, -1e15, int(-self.relayfee*COIN))
+ cur_time = int(time.time())
+ for i in xrange(10):
+ self.nodes[0].setmocktime(cur_time + 600)
+ self.nodes[0].generate(1)
+ cur_time += 600
+
+ assert(tx2.hash in self.nodes[0].getrawmempool())
+
+ test_nonzero_locks(tx2, self.nodes[0], self.relayfee, use_height_lock=True)
+ test_nonzero_locks(tx2, self.nodes[0], self.relayfee, use_height_lock=False)
+
+ # Mine tx2, and then try again
+ self.nodes[0].prioritisetransaction(tx2.hash, 1e15, int(self.relayfee*COIN))
+
+ # Advance the time on the node so that we can test timelocks
+ self.nodes[0].setmocktime(cur_time+600)
+ self.nodes[0].generate(1)
+ assert(tx2.hash not in self.nodes[0].getrawmempool())
+
+ # Now that tx2 is not in the mempool, a sequence locked spend should
+ # succeed
+ tx3 = test_nonzero_locks(tx2, self.nodes[0], self.relayfee, use_height_lock=False)
+ assert(tx3.hash in self.nodes[0].getrawmempool())
+
+ self.nodes[0].generate(1)
+ assert(tx3.hash not in self.nodes[0].getrawmempool())
+
+ # One more test, this time using height locks
+ tx4 = test_nonzero_locks(tx3, self.nodes[0], self.relayfee, use_height_lock=True)
+ assert(tx4.hash in self.nodes[0].getrawmempool())
+
+ # Now try combining confirmed and unconfirmed inputs
+ tx5 = test_nonzero_locks(tx4, self.nodes[0], self.relayfee, use_height_lock=True)
+ assert(tx5.hash not in self.nodes[0].getrawmempool())
+
+ utxos = self.nodes[0].listunspent()
+ tx5.vin.append(CTxIn(COutPoint(int(utxos[0]["txid"], 16), utxos[0]["vout"]), nSequence=1))
+ tx5.vout[0].nValue += int(utxos[0]["amount"]*COIN)
+ raw_tx5 = self.nodes[0].signrawtransaction(ToHex(tx5))["hex"]
+
+ try:
+ self.nodes[0].sendrawtransaction(raw_tx5)
+ except JSONRPCException as exp:
+ assert_equal(exp.error["message"], NOT_FINAL_ERROR)
+ else:
+ assert(False)
+
+ # Test mempool-BIP68 consistency after reorg
+ #
+ # State of the transactions in the last blocks:
+ # ... -> [ tx2 ] -> [ tx3 ]
+ # tip-1 tip
+ # And currently tx4 is in the mempool.
+ #
+ # If we invalidate the tip, tx3 should get added to the mempool, causing
+ # tx4 to be removed (fails sequence-lock).
+ self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
+ assert(tx4.hash not in self.nodes[0].getrawmempool())
+ assert(tx3.hash in self.nodes[0].getrawmempool())
+
+ # Now mine 2 empty blocks to reorg out the current tip (labeled tip-1 in
+ # diagram above).
+ # This would cause tx2 to be added back to the mempool, which in turn causes
+ # tx3 to be removed.
+ tip = int(self.nodes[0].getblockhash(self.nodes[0].getblockcount()-1), 16)
+ height = self.nodes[0].getblockcount()
+ for i in xrange(2):
+ block = create_block(tip, create_coinbase(height), cur_time)
+ block.nVersion = 3
+ block.rehash()
+ block.solve()
+ tip = block.sha256
+ height += 1
+ self.nodes[0].submitblock(ToHex(block))
+ cur_time += 1
+
+ mempool = self.nodes[0].getrawmempool()
+ assert(tx3.hash not in mempool)
+ assert(tx2.hash in mempool)
+
+ # Reset the chain and get rid of the mocktimed-blocks
+ self.nodes[0].setmocktime(0)
+ self.nodes[0].invalidateblock(self.nodes[0].getblockhash(cur_height+1))
+ self.nodes[0].generate(10)
+
+ # Make sure that BIP68 isn't being used to validate blocks.
+ def test_bip68_not_consensus(self):
+ txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 2)
+
+ tx1 = FromHex(CTransaction(), self.nodes[0].getrawtransaction(txid))
+ tx1.rehash()
+
+ # Make an anyone-can-spend transaction
+ tx2 = CTransaction()
+ tx2.nVersion = 1
+ tx2.vin = [CTxIn(COutPoint(tx1.sha256, 0), nSequence=0)]
+ tx2.vout = [CTxOut(int(tx1.vout[0].nValue - self.relayfee*COIN), CScript([b'a']))]
+
+ # sign tx2
+ tx2_raw = self.nodes[0].signrawtransaction(ToHex(tx2))["hex"]
+ tx2 = FromHex(tx2, tx2_raw)
+ tx2.rehash()
+
+ self.nodes[0].sendrawtransaction(ToHex(tx2))
+
+ # Now make an invalid spend of tx2 according to BIP68
+ sequence_value = 100 # 100 block relative locktime
+
+ tx3 = CTransaction()
+ tx3.nVersion = 2
+ tx3.vin = [CTxIn(COutPoint(tx2.sha256, 0), nSequence=sequence_value)]
+ tx3.vout = [CTxOut(int(tx2.vout[0].nValue - self.relayfee*COIN), CScript([b'a']))]
+ tx3.rehash()
+
+ try:
+ self.nodes[0].sendrawtransaction(ToHex(tx3))
+ except JSONRPCException as exp:
+ assert_equal(exp.error["message"], NOT_FINAL_ERROR)
+ else:
+ assert(False)
+
+ # make a block that violates bip68; ensure that the tip updates
+ tip = int(self.nodes[0].getbestblockhash(), 16)
+ block = create_block(tip, create_coinbase(self.nodes[0].getblockcount()+1))
+ block.nVersion = 3
+ block.vtx.extend([tx1, tx2, tx3])
+ block.hashMerkleRoot = block.calc_merkle_root()
+ block.rehash()
+ block.solve()
+
+ self.nodes[0].submitblock(ToHex(block))
+ assert_equal(self.nodes[0].getbestblockhash(), block.hash)
+
+
+if __name__ == '__main__':
+ BIP68Test().main()
diff --git a/qa/rpc-tests/bipdersig-p2p.py b/qa/rpc-tests/bipdersig-p2p.py
index ec1678cc2c..544e4a9670 100755
--- a/qa/rpc-tests/bipdersig-p2p.py
+++ b/qa/rpc-tests/bipdersig-p2p.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-#
+# Copyright (c) 2015 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.
#
@@ -10,7 +10,7 @@ from test_framework.mininode import CTransaction, NetworkThread
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 hexlify, unhexlify
+from binascii import unhexlify
import cStringIO
import time
diff --git a/qa/rpc-tests/bipdersig.py b/qa/rpc-tests/bipdersig.py
index 243f816f65..be9121c456 100755
--- a/qa/rpc-tests/bipdersig.py
+++ b/qa/rpc-tests/bipdersig.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
@@ -9,8 +9,6 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-import os
-import shutil
class BIP66Test(BitcoinTestFramework):
@@ -46,7 +44,7 @@ class BIP66Test(BitcoinTestFramework):
self.nodes[2].generate(1)
self.sync_all()
if (self.nodes[0].getblockcount() != cnt + 851):
- raise AssertionFailure("Failed to mine a version=3 blocks")
+ raise AssertionError("Failed to mine a version=3 blocks")
# TODO: check that new DERSIG rules are enforced
diff --git a/qa/rpc-tests/blockchain.py b/qa/rpc-tests/blockchain.py
index b7bfe36285..7045ae435c 100755
--- a/qa/rpc-tests/blockchain.py
+++ b/qa/rpc-tests/blockchain.py
@@ -1,22 +1,28 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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 RPC calls related to blockchain state.
+# Test RPC calls related to blockchain state. Tests correspond to code in
+# rpc/blockchain.cpp.
#
-import decimal
+from decimal import Decimal
from test_framework.test_framework import BitcoinTestFramework
+from test_framework.authproxy import JSONRPCException
from test_framework.util import (
initialize_chain,
assert_equal,
+ assert_raises,
+ assert_is_hex_string,
+ assert_is_hash_string,
start_nodes,
connect_nodes_bi,
)
+
class BlockchainTest(BitcoinTestFramework):
"""
Test blockchain-related RPC calls:
@@ -36,10 +42,14 @@ class BlockchainTest(BitcoinTestFramework):
self.sync_all()
def run_test(self):
+ self._test_gettxoutsetinfo()
+ self._test_getblockheader()
+
+ def _test_gettxoutsetinfo(self):
node = self.nodes[0]
res = node.gettxoutsetinfo()
- assert_equal(res[u'total_amount'], decimal.Decimal('8725.00000000'))
+ assert_equal(res[u'total_amount'], Decimal('8725.00000000'))
assert_equal(res[u'transactions'], 200)
assert_equal(res[u'height'], 200)
assert_equal(res[u'txouts'], 200)
@@ -47,6 +57,30 @@ class BlockchainTest(BitcoinTestFramework):
assert_equal(len(res[u'bestblock']), 64)
assert_equal(len(res[u'hash_serialized']), 64)
+ def _test_getblockheader(self):
+ node = self.nodes[0]
+
+ assert_raises(
+ JSONRPCException, lambda: node.getblockheader('nonsense'))
+
+ besthash = node.getbestblockhash()
+ secondbesthash = node.getblockhash(199)
+ header = node.getblockheader(besthash)
+
+ assert_equal(header['hash'], besthash)
+ assert_equal(header['height'], 200)
+ assert_equal(header['confirmations'], 1)
+ assert_equal(header['previousblockhash'], secondbesthash)
+ assert_is_hex_string(header['chainwork'])
+ assert_is_hash_string(header['hash'])
+ assert_is_hash_string(header['previousblockhash'])
+ assert_is_hash_string(header['merkleroot'])
+ assert_is_hash_string(header['bits'], length=None)
+ assert isinstance(header['time'], int)
+ assert isinstance(header['mediantime'], int)
+ assert isinstance(header['nonce'], int)
+ assert isinstance(header['version'], int)
+ assert isinstance(header['difficulty'], Decimal)
if __name__ == '__main__':
BlockchainTest().main()
diff --git a/qa/rpc-tests/decodescript.py b/qa/rpc-tests/decodescript.py
index 4bca623380..490808d49d 100755
--- a/qa/rpc-tests/decodescript.py
+++ b/qa/rpc-tests/decodescript.py
@@ -102,13 +102,13 @@ class DecodeScriptTest(BitcoinTestFramework):
# OP_IF
# <receiver-pubkey> OP_CHECKSIGVERIFY
# OP_ELSE
- # <lock-until> OP_NOP2 OP_DROP
+ # <lock-until> OP_CHECKLOCKTIMEVERIFY OP_DROP
# OP_ENDIF
# <sender-pubkey> OP_CHECKSIG
#
# lock until block 500,000
rpc_result = self.nodes[0].decodescript('63' + push_public_key + 'ad670320a107b17568' + push_public_key + 'ac')
- assert_equal('OP_IF ' + public_key + ' OP_CHECKSIGVERIFY OP_ELSE 500000 OP_NOP2 OP_DROP OP_ENDIF ' + public_key + ' OP_CHECKSIG', rpc_result['asm'])
+ assert_equal('OP_IF ' + public_key + ' OP_CHECKSIGVERIFY OP_ELSE 500000 OP_CHECKLOCKTIMEVERIFY OP_DROP OP_ENDIF ' + public_key + ' OP_CHECKSIG', rpc_result['asm'])
def decoderawtransaction_asm_sighashtype(self):
"""Tests decoding scripts via RPC command "decoderawtransaction".
diff --git a/qa/rpc-tests/disablewallet.py b/qa/rpc-tests/disablewallet.py
index 4cb01575e2..6964348d55 100755
--- a/qa/rpc-tests/disablewallet.py
+++ b/qa/rpc-tests/disablewallet.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
@@ -10,6 +10,7 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
+
class DisableWalletTest (BitcoinTestFramework):
def setup_chain(self):
diff --git a/qa/rpc-tests/forknotify.py b/qa/rpc-tests/forknotify.py
index 0acef8e30b..20e6ce9619 100755
--- a/qa/rpc-tests/forknotify.py
+++ b/qa/rpc-tests/forknotify.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
@@ -9,8 +9,6 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-import os
-import shutil
class ForkNotifyTest(BitcoinTestFramework):
diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py
index 93d13faa06..0287965b97 100755
--- a/qa/rpc-tests/fundrawtransaction.py
+++ b/qa/rpc-tests/fundrawtransaction.py
@@ -1,12 +1,10 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-from pprint import pprint
-from time import sleep
# Create one-input, one-output, no-fee transaction:
class RawTransactionsTest(BitcoinTestFramework):
@@ -30,6 +28,11 @@ class RawTransactionsTest(BitcoinTestFramework):
print "Mining blocks..."
min_relay_tx_fee = self.nodes[0].getnetworkinfo()['relayfee']
+ # This test is not meant to test fee estimation and we'd like
+ # to be sure all txs are sent at a consistent desired feerate
+ for node in self.nodes:
+ node.settxfee(min_relay_tx_fee)
+
# 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
@@ -48,11 +51,11 @@ class RawTransactionsTest(BitcoinTestFramework):
watchonly_amount = 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);
+ self.nodes[0].sendtoaddress(self.nodes[3].getnewaddress(), watchonly_amount / 10)
- self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.5);
- self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.0);
- self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),5.0);
+ self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.5)
+ self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.0)
+ self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 5.0)
self.sync_all()
self.nodes[0].generate(1)
@@ -125,7 +128,7 @@ class RawTransactionsTest(BitcoinTestFramework):
for aUtx in listunspent:
if aUtx['amount'] == 5.0:
utx = aUtx
- break;
+ break
assert_equal(utx!=False, True)
@@ -154,7 +157,7 @@ class RawTransactionsTest(BitcoinTestFramework):
for aUtx in listunspent:
if aUtx['amount'] == 5.0:
utx = aUtx
- break;
+ break
assert_equal(utx!=False, True)
@@ -184,7 +187,7 @@ class RawTransactionsTest(BitcoinTestFramework):
for aUtx in listunspent:
if aUtx['amount'] == 1.0:
utx = aUtx
- break;
+ break
assert_equal(utx!=False, True)
@@ -309,7 +312,7 @@ class RawTransactionsTest(BitcoinTestFramework):
except JSONRPCException,e:
errorString = e.error['message']
- assert_equal("Insufficient" in errorString, True);
+ assert("Insufficient" in errorString)
@@ -321,11 +324,11 @@ class RawTransactionsTest(BitcoinTestFramework):
fundedTx = self.nodes[0].fundrawtransaction(rawTx)
#create same transaction over sendtoaddress
- txId = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1.1);
+ txId = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1.1)
signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']
#compare fee
- feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee);
+ feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
assert(feeDelta >= 0 and feeDelta <= feeTolerance)
############################################################
@@ -336,11 +339,11 @@ class RawTransactionsTest(BitcoinTestFramework):
rawTx = self.nodes[0].createrawtransaction(inputs, outputs)
fundedTx = self.nodes[0].fundrawtransaction(rawTx)
#create same transaction over sendtoaddress
- txId = self.nodes[0].sendmany("", outputs);
+ txId = self.nodes[0].sendmany("", outputs)
signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']
#compare fee
- feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee);
+ feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
assert(feeDelta >= 0 and feeDelta <= feeTolerance)
############################################################
@@ -363,11 +366,11 @@ class RawTransactionsTest(BitcoinTestFramework):
fundedTx = self.nodes[0].fundrawtransaction(rawTx)
#create same transaction over sendtoaddress
- txId = self.nodes[0].sendtoaddress(mSigObj, 1.1);
+ txId = self.nodes[0].sendtoaddress(mSigObj, 1.1)
signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']
#compare fee
- feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee);
+ feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
assert(feeDelta >= 0 and feeDelta <= feeTolerance)
############################################################
@@ -396,11 +399,11 @@ class RawTransactionsTest(BitcoinTestFramework):
fundedTx = self.nodes[0].fundrawtransaction(rawTx)
#create same transaction over sendtoaddress
- txId = self.nodes[0].sendtoaddress(mSigObj, 1.1);
+ txId = self.nodes[0].sendtoaddress(mSigObj, 1.1)
signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']
#compare fee
- feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee);
+ feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
assert(feeDelta >= 0 and feeDelta <= feeTolerance)
############################################################
@@ -419,7 +422,7 @@ class RawTransactionsTest(BitcoinTestFramework):
# send 1.2 BTC to msig addr
- txId = self.nodes[0].sendtoaddress(mSigObj, 1.2);
+ txId = self.nodes[0].sendtoaddress(mSigObj, 1.2)
self.sync_all()
self.nodes[1].generate(1)
self.sync_all()
@@ -447,6 +450,10 @@ class RawTransactionsTest(BitcoinTestFramework):
wait_bitcoinds()
self.nodes = start_nodes(4, self.options.tmpdir)
+ # This test is not meant to test fee estimation and we'd like
+ # to be sure all txs are sent at a consistent desired feerate
+ for node in self.nodes:
+ node.settxfee(min_relay_tx_fee)
connect_nodes_bi(self.nodes,0,1)
connect_nodes_bi(self.nodes,1,2)
@@ -457,7 +464,7 @@ class RawTransactionsTest(BitcoinTestFramework):
error = False
try:
- self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1.2);
+ self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1.2)
except:
error = True
assert(error)
@@ -487,13 +494,13 @@ class RawTransactionsTest(BitcoinTestFramework):
###############################################
#empty node1, send some small coins from node0 to node1
- self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), self.nodes[1].getbalance(), "", "", True);
+ self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), self.nodes[1].getbalance(), "", "", True)
self.sync_all()
self.nodes[0].generate(1)
self.sync_all()
for i in range(0,20):
- self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01);
+ self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01)
self.sync_all()
self.nodes[0].generate(1)
self.sync_all()
@@ -505,11 +512,11 @@ class RawTransactionsTest(BitcoinTestFramework):
fundedTx = self.nodes[1].fundrawtransaction(rawTx)
#create same transaction over sendtoaddress
- txId = self.nodes[1].sendmany("", outputs);
+ txId = self.nodes[1].sendmany("", outputs)
signedFee = self.nodes[1].getrawmempool(True)[txId]['fee']
#compare fee
- feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee);
+ feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee)
assert(feeDelta >= 0 and feeDelta <= feeTolerance*19) #~19 inputs
@@ -518,13 +525,13 @@ class RawTransactionsTest(BitcoinTestFramework):
#############################################
#again, empty node1, send some small coins from node0 to node1
- self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), self.nodes[1].getbalance(), "", "", True);
+ self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), self.nodes[1].getbalance(), "", "", True)
self.sync_all()
self.nodes[0].generate(1)
self.sync_all()
for i in range(0,20):
- self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01);
+ self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.01)
self.sync_all()
self.nodes[0].generate(1)
self.sync_all()
diff --git a/qa/rpc-tests/getblocktemplate_longpoll.py b/qa/rpc-tests/getblocktemplate_longpoll.py
index 1ddff8a298..3e85957ae2 100755
--- a/qa/rpc-tests/getblocktemplate_longpoll.py
+++ b/qa/rpc-tests/getblocktemplate_longpoll.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
diff --git a/qa/rpc-tests/getblocktemplate_proposals.py b/qa/rpc-tests/getblocktemplate_proposals.py
index aca0cd7495..f83b5f140d 100755
--- a/qa/rpc-tests/getblocktemplate_proposals.py
+++ b/qa/rpc-tests/getblocktemplate_proposals.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
diff --git a/qa/rpc-tests/getchaintips.py b/qa/rpc-tests/getchaintips.py
index 6a2bcb2969..dd260836bb 100755
--- a/qa/rpc-tests/getchaintips.py
+++ b/qa/rpc-tests/getchaintips.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
@@ -23,8 +23,8 @@ class GetChainTipsTest (BitcoinTestFramework):
# Split the network and build two chains of different lengths.
self.split_network ()
- self.nodes[0].generate(10);
- self.nodes[2].generate(20);
+ self.nodes[0].generate(10)
+ self.nodes[2].generate(20)
self.sync_all ()
tips = self.nodes[1].getchaintips ()
diff --git a/qa/rpc-tests/httpbasics.py b/qa/rpc-tests/httpbasics.py
index 7888114c54..eb548aee9d 100755
--- a/qa/rpc-tests/httpbasics.py
+++ b/qa/rpc-tests/httpbasics.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
@@ -36,13 +36,13 @@ class HTTPBasicsTest (BitcoinTestFramework):
conn = httplib.HTTPConnection(url.hostname, url.port)
conn.connect()
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
- out1 = conn.getresponse().read();
+ out1 = conn.getresponse().read()
assert_equal('"error":null' in out1, True)
assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open!
#send 2nd request without closing connection
conn.request('POST', '/', '{"method": "getchaintips"}', headers)
- out2 = conn.getresponse().read();
+ out2 = conn.getresponse().read()
assert_equal('"error":null' in out1, True) #must also response with a correct json-rpc message
assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open!
conn.close()
@@ -53,13 +53,13 @@ class HTTPBasicsTest (BitcoinTestFramework):
conn = httplib.HTTPConnection(url.hostname, url.port)
conn.connect()
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
- out1 = conn.getresponse().read();
+ out1 = conn.getresponse().read()
assert_equal('"error":null' in out1, True)
assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open!
#send 2nd request without closing connection
conn.request('POST', '/', '{"method": "getchaintips"}', headers)
- out2 = conn.getresponse().read();
+ out2 = conn.getresponse().read()
assert_equal('"error":null' in out1, True) #must also response with a correct json-rpc message
assert_equal(conn.sock!=None, True) #according to http/1.1 connection must still be open!
conn.close()
@@ -70,7 +70,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
conn = httplib.HTTPConnection(url.hostname, url.port)
conn.connect()
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
- out1 = conn.getresponse().read();
+ out1 = conn.getresponse().read()
assert_equal('"error":null' in out1, True)
assert_equal(conn.sock!=None, False) #now the connection must be closed after the response
@@ -82,7 +82,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
conn = httplib.HTTPConnection(urlNode1.hostname, urlNode1.port)
conn.connect()
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
- out1 = conn.getresponse().read();
+ out1 = conn.getresponse().read()
assert_equal('"error":null' in out1, True)
#node2 (third node) is running with standard keep-alive parameters which means keep-alive is on
@@ -93,7 +93,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
conn = httplib.HTTPConnection(urlNode2.hostname, urlNode2.port)
conn.connect()
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
- out1 = conn.getresponse().read();
+ out1 = conn.getresponse().read()
assert_equal('"error":null' in out1, True)
assert_equal(conn.sock!=None, True) #connection must be closed because bitcoind should use keep-alive by default
diff --git a/qa/rpc-tests/invalidateblock.py b/qa/rpc-tests/invalidateblock.py
index 2b9c8154e0..0e78a3c806 100755
--- a/qa/rpc-tests/invalidateblock.py
+++ b/qa/rpc-tests/invalidateblock.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
diff --git a/qa/rpc-tests/invalidblockrequest.py b/qa/rpc-tests/invalidblockrequest.py
index 6a7980cd45..f91a8da015 100755
--- a/qa/rpc-tests/invalidblockrequest.py
+++ b/qa/rpc-tests/invalidblockrequest.py
@@ -1,15 +1,13 @@
#!/usr/bin/env python2
-#
+# Copyright (c) 2015 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.
#
from test_framework.test_framework import ComparisonTestFramework
from test_framework.util import *
-from test_framework.comptool import TestManager, TestInstance
-from test_framework.mininode import *
+from test_framework.comptool import TestManager, TestInstance, RejectResult
from test_framework.blocktools import *
-import logging
import copy
import time
@@ -97,7 +95,7 @@ class InvalidBlockRequestTest(ComparisonTestFramework):
assert(block2_orig.vtx != block2.vtx)
self.tip = block2.sha256
- yield TestInstance([[block2, False], [block2_orig, True]])
+ yield TestInstance([[block2, RejectResult(16,'bad-txns-duplicate')], [block2_orig, True]])
height += 1
'''
@@ -112,7 +110,7 @@ class InvalidBlockRequestTest(ComparisonTestFramework):
block3.rehash()
block3.solve()
- yield TestInstance([[block3, False]])
+ yield TestInstance([[block3, RejectResult(16,'bad-cb-amount')]])
if __name__ == '__main__':
diff --git a/qa/rpc-tests/invalidtxrequest.py b/qa/rpc-tests/invalidtxrequest.py
new file mode 100755
index 0000000000..c2fe4f1dff
--- /dev/null
+++ b/qa/rpc-tests/invalidtxrequest.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python2
+# Copyright (c) 2015 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.
+#
+
+from test_framework.test_framework import ComparisonTestFramework
+from test_framework.comptool import TestManager, TestInstance, RejectResult
+from test_framework.blocktools import *
+import time
+
+
+'''
+In this test we connect to one node over p2p, and test tx requests.
+'''
+
+# Use the ComparisonTestFramework with 1 node: only use --testbinary.
+class InvalidTxRequestTest(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):
+ self.num_nodes = 1
+
+ def run_test(self):
+ test = TestManager(self, self.options.tmpdir)
+ test.add_all_connections(self.nodes)
+ self.tip = None
+ self.block_time = None
+ NetworkThread().start() # Start up network handling in another thread
+ test.run()
+
+ def get_tests(self):
+ if self.tip is None:
+ self.tip = int ("0x" + self.nodes[0].getbestblockhash() + "L", 0)
+ self.block_time = int(time.time())+1
+
+ '''
+ Create a new block with an anyone-can-spend coinbase
+ '''
+ 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]])
+
+ '''
+ Now we need that block to mature so we can spend the coinbase.
+ '''
+ test = TestInstance(sync_every_block=False)
+ for i in xrange(100):
+ 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
+
+ # chr(100) is OP_NOTIF
+ # Transaction will be rejected with code 16 (REJECT_INVALID)
+ tx1 = create_transaction(self.block1.vtx[0], 0, chr(100), 50*100000000 - 12000)
+ yield TestInstance([[tx1, RejectResult(16, 'mandatory-script-verify-flag-failed')]])
+
+ # TODO: test further transactions...
+
+if __name__ == '__main__':
+ InvalidTxRequestTest().main()
diff --git a/qa/rpc-tests/keypool.py b/qa/rpc-tests/keypool.py
index 92d91e029a..95d0d6832a 100755
--- a/qa/rpc-tests/keypool.py
+++ b/qa/rpc-tests/keypool.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
@@ -70,9 +70,11 @@ class KeyPoolTest(BitcoinTestFramework):
assert(e.error['code']==-12)
# refill keypool with three new addresses
- nodes[0].walletpassphrase('test', 12000)
+ nodes[0].walletpassphrase('test', 1)
nodes[0].keypoolrefill(3)
- nodes[0].walletlock()
+ # test walletpassphrase timeout
+ time.sleep(1.1)
+ assert_equal(nodes[0].getwalletinfo()["unlocked_until"], 0)
# drain them by mining
nodes[0].generate(1)
diff --git a/qa/rpc-tests/listtransactions.py b/qa/rpc-tests/listtransactions.py
index b30a6bc9d1..45ede8f040 100755
--- a/qa/rpc-tests/listtransactions.py
+++ b/qa/rpc-tests/listtransactions.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
@@ -7,7 +7,15 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
+from test_framework.mininode import CTransaction
+import cStringIO
+import binascii
+def txFromHex(hexstring):
+ tx = CTransaction()
+ f = cStringIO.StringIO(binascii.unhexlify(hexstring))
+ tx.deserialize(f)
+ return tx
def check_array_result(object_array, to_match, expected):
"""
@@ -32,6 +40,11 @@ def check_array_result(object_array, to_match, expected):
class ListTransactionsTest(BitcoinTestFramework):
+ def setup_nodes(self):
+ #This test requires mocktime
+ enable_mocktime()
+ return start_nodes(4, self.options.tmpdir)
+
def run_test(self):
# Simple send, 0 to 1:
txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
@@ -103,6 +116,107 @@ class ListTransactionsTest(BitcoinTestFramework):
{"category":"receive","amount":Decimal("0.1")},
{"txid":txid, "account" : "watchonly"} )
+ self.run_rbf_opt_in_test()
+
+ # Check that the opt-in-rbf flag works properly, for sent and received
+ # transactions.
+ def run_rbf_opt_in_test(self):
+ # Check whether a transaction signals opt-in RBF itself
+ def is_opt_in(node, txid):
+ rawtx = node.getrawtransaction(txid, 1)
+ for x in rawtx["vin"]:
+ if x["sequence"] < 0xfffffffe:
+ return True
+ return False
+
+ # Find an unconfirmed output matching a certain txid
+ def get_unconfirmed_utxo_entry(node, txid_to_match):
+ utxo = node.listunspent(0, 0)
+ for i in utxo:
+ if i["txid"] == txid_to_match:
+ return i
+ return None
+
+ # 1. Chain a few transactions that don't opt-in.
+ txid_1 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1)
+ assert(not is_opt_in(self.nodes[0], txid_1))
+ check_array_result(self.nodes[0].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"})
+ sync_mempools(self.nodes)
+ check_array_result(self.nodes[1].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"})
+
+ # Tx2 will build off txid_1, still not opting in to RBF.
+ utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_1)
+
+ # Create tx2 using createrawtransaction
+ inputs = [{"txid":utxo_to_use["txid"], "vout":utxo_to_use["vout"]}]
+ outputs = {self.nodes[0].getnewaddress(): 0.999}
+ tx2 = self.nodes[1].createrawtransaction(inputs, outputs)
+ tx2_signed = self.nodes[1].signrawtransaction(tx2)["hex"]
+ txid_2 = self.nodes[1].sendrawtransaction(tx2_signed)
+
+ # ...and check the result
+ assert(not is_opt_in(self.nodes[1], txid_2))
+ check_array_result(self.nodes[1].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"})
+ sync_mempools(self.nodes)
+ check_array_result(self.nodes[0].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"})
+
+ # Tx3 will opt-in to RBF
+ utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[0], txid_2)
+ inputs = [{"txid": txid_2, "vout":utxo_to_use["vout"]}]
+ outputs = {self.nodes[1].getnewaddress(): 0.998}
+ tx3 = self.nodes[0].createrawtransaction(inputs, outputs)
+ tx3_modified = txFromHex(tx3)
+ tx3_modified.vin[0].nSequence = 0
+ tx3 = binascii.hexlify(tx3_modified.serialize()).decode('utf-8')
+ tx3_signed = self.nodes[0].signrawtransaction(tx3)['hex']
+ txid_3 = self.nodes[0].sendrawtransaction(tx3_signed)
+
+ assert(is_opt_in(self.nodes[0], txid_3))
+ check_array_result(self.nodes[0].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"})
+ sync_mempools(self.nodes)
+ check_array_result(self.nodes[1].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"})
+
+ # Tx4 will chain off tx3. Doesn't signal itself, but depends on one
+ # that does.
+ utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_3)
+ inputs = [{"txid": txid_3, "vout":utxo_to_use["vout"]}]
+ outputs = {self.nodes[0].getnewaddress(): 0.997}
+ tx4 = self.nodes[1].createrawtransaction(inputs, outputs)
+ tx4_signed = self.nodes[1].signrawtransaction(tx4)["hex"]
+ txid_4 = self.nodes[1].sendrawtransaction(tx4_signed)
+
+ assert(not is_opt_in(self.nodes[1], txid_4))
+ check_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"})
+ sync_mempools(self.nodes)
+ check_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"})
+
+ # Replace tx3, and check that tx4 becomes unknown
+ tx3_b = tx3_modified
+ tx3_b.vout[0].nValue -= 0.004*100000000 # bump the fee
+ tx3_b = binascii.hexlify(tx3_b.serialize()).decode('utf-8')
+ tx3_b_signed = self.nodes[0].signrawtransaction(tx3_b)['hex']
+ txid_3b = self.nodes[0].sendrawtransaction(tx3_b_signed, True)
+ assert(is_opt_in(self.nodes[0], txid_3b))
+
+ check_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"})
+ sync_mempools(self.nodes)
+ check_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"})
+
+ # Check gettransaction as well:
+ for n in self.nodes[0:2]:
+ assert_equal(n.gettransaction(txid_1)["bip125-replaceable"], "no")
+ assert_equal(n.gettransaction(txid_2)["bip125-replaceable"], "no")
+ assert_equal(n.gettransaction(txid_3)["bip125-replaceable"], "yes")
+ assert_equal(n.gettransaction(txid_3b)["bip125-replaceable"], "yes")
+ assert_equal(n.gettransaction(txid_4)["bip125-replaceable"], "unknown")
+
+ # After mining a transaction, it's no longer BIP125-replaceable
+ self.nodes[0].generate(1)
+ assert(txid_3b not in self.nodes[0].getrawmempool())
+ assert_equal(self.nodes[0].gettransaction(txid_3b)["bip125-replaceable"], "no")
+ assert_equal(self.nodes[0].gettransaction(txid_4)["bip125-replaceable"], "unknown")
+
+
if __name__ == '__main__':
ListTransactionsTest().main()
diff --git a/qa/rpc-tests/maxblocksinflight.py b/qa/rpc-tests/maxblocksinflight.py
index a601147ce8..0313bce736 100755
--- a/qa/rpc-tests/maxblocksinflight.py
+++ b/qa/rpc-tests/maxblocksinflight.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-#
+# Copyright (c) 2015 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.
#
@@ -34,7 +34,6 @@ class TestManager(NodeConnCB):
def __init__(self):
NodeConnCB.__init__(self)
self.log = logging.getLogger("BlockRelayTest")
- self.create_callback_map()
def add_new_connection(self, connection):
self.connection = connection
diff --git a/qa/rpc-tests/maxuploadtarget.py b/qa/rpc-tests/maxuploadtarget.py
index e714465db1..4d6b343f77 100755
--- a/qa/rpc-tests/maxuploadtarget.py
+++ b/qa/rpc-tests/maxuploadtarget.py
@@ -25,7 +25,6 @@ if uploadtarget has been reached.
class TestNode(NodeConnCB):
def __init__(self):
NodeConnCB.__init__(self)
- self.create_callback_map()
self.connection = None
self.ping_counter = 1
self.last_pong = msg_pong()
@@ -85,22 +84,7 @@ class TestNode(NodeConnCB):
class MaxUploadTest(BitcoinTestFramework):
def __init__(self):
self.utxo = []
-
- # Some pre-processing to create a bunch of OP_RETURN txouts to insert into transactions we create
- # So we have big transactions and full blocks to fill up our block files
- # 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
+ self.txouts = gen_return_txouts()
def add_options(self, parser):
parser.add_option("--testbinary", dest="testbinary",
diff --git a/qa/rpc-tests/mempool_limit.py b/qa/rpc-tests/mempool_limit.py
new file mode 100755
index 0000000000..7914ceea22
--- /dev/null
+++ b/qa/rpc-tests/mempool_limit.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python2
+# Copyright (c) 2014-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 mempool limiting together/eviction with the wallet
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
+
+class MempoolLimitTest(BitcoinTestFramework):
+
+ def __init__(self):
+ self.txouts = gen_return_txouts()
+
+ def setup_network(self):
+ self.nodes = []
+ self.nodes.append(start_node(0, self.options.tmpdir, ["-maxmempool=5", "-spendzeroconfchange=0", "-debug"]))
+ self.is_network_split = False
+ self.sync_all()
+ self.relayfee = self.nodes[0].getnetworkinfo()['relayfee']
+
+ def setup_chain(self):
+ print("Initializing test directory "+self.options.tmpdir)
+ initialize_chain_clean(self.options.tmpdir, 2)
+
+ def run_test(self):
+ txids = []
+ utxos = create_confirmed_utxos(self.relayfee, self.nodes[0], 90)
+
+ #create a mempool tx that will be evicted
+ us0 = utxos.pop()
+ inputs = [{ "txid" : us0["txid"], "vout" : us0["vout"]}]
+ outputs = {self.nodes[0].getnewaddress() : 0.0001}
+ tx = self.nodes[0].createrawtransaction(inputs, outputs)
+ self.nodes[0].settxfee(self.relayfee) # specifically fund this tx with low fee
+ txF = self.nodes[0].fundrawtransaction(tx)
+ self.nodes[0].settxfee(0) # return to automatic fee selection
+ txFS = self.nodes[0].signrawtransaction(txF['hex'])
+ txid = self.nodes[0].sendrawtransaction(txFS['hex'])
+ self.nodes[0].lockunspent(True, [us0])
+
+ relayfee = self.nodes[0].getnetworkinfo()['relayfee']
+ base_fee = relayfee*100
+ for i in xrange (4):
+ txids.append([])
+ txids[i] = create_lots_of_big_transactions(self.nodes[0], self.txouts, utxos[30*i:30*i+30], (i+1)*base_fee)
+
+ # by now, the tx should be evicted, check confirmation state
+ assert(txid not in self.nodes[0].getrawmempool())
+ txdata = self.nodes[0].gettransaction(txid)
+ assert(txdata['confirmations'] == 0) #confirmation should still be 0
+
+if __name__ == '__main__':
+ MempoolLimitTest().main()
diff --git a/qa/rpc-tests/mempool_packages.py b/qa/rpc-tests/mempool_packages.py
index 34b316a6a3..47c1028b9f 100755
--- a/qa/rpc-tests/mempool_packages.py
+++ b/qa/rpc-tests/mempool_packages.py
@@ -64,17 +64,50 @@ class MempoolPackagesTest(BitcoinTestFramework):
for x in reversed(chain):
assert_equal(mempool[x]['descendantcount'], descendant_count)
descendant_fees += mempool[x]['fee']
+ assert_equal(mempool[x]['modifiedfee'], mempool[x]['fee'])
assert_equal(mempool[x]['descendantfees'], SATOSHIS*descendant_fees)
descendant_size += mempool[x]['size']
assert_equal(mempool[x]['descendantsize'], descendant_size)
descendant_count += 1
+ # Check that descendant modified fees includes fee deltas from
+ # prioritisetransaction
+ self.nodes[0].prioritisetransaction(chain[-1], 0, 1000)
+ mempool = self.nodes[0].getrawmempool(True)
+
+ descendant_fees = 0
+ for x in reversed(chain):
+ descendant_fees += mempool[x]['fee']
+ assert_equal(mempool[x]['descendantfees'], SATOSHIS*descendant_fees+1000)
+
# Adding one more transaction on to the chain should fail.
try:
self.chain_transaction(self.nodes[0], txid, vout, value, fee, 1)
except JSONRPCException as e:
print "too-long-ancestor-chain successfully rejected"
+ # Check that prioritising a tx before it's added to the mempool works
+ # First clear the mempool by mining a block.
+ self.nodes[0].generate(1)
+ sync_blocks(self.nodes)
+ assert_equal(len(self.nodes[0].getrawmempool()), 0)
+ # Prioritise a transaction that has been mined, then add it back to the
+ # mempool by using invalidateblock.
+ self.nodes[0].prioritisetransaction(chain[-1], 0, 2000)
+ self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
+ # Keep node1's tip synced with node0
+ self.nodes[1].invalidateblock(self.nodes[1].getbestblockhash())
+
+ # Now check that the transaction is in the mempool, with the right modified fee
+ mempool = self.nodes[0].getrawmempool(True)
+
+ descendant_fees = 0
+ for x in reversed(chain):
+ descendant_fees += mempool[x]['fee']
+ if (x == chain[-1]):
+ assert_equal(mempool[x]['modifiedfee'], mempool[x]['fee']+satoshi_round(0.00002))
+ assert_equal(mempool[x]['descendantfees'], SATOSHIS*descendant_fees+2000)
+
# TODO: check that node1's mempool is as expected
# TODO: test ancestor size limits
diff --git a/qa/rpc-tests/mempool_reorg.py b/qa/rpc-tests/mempool_reorg.py
index fdbaf689ad..40684e7fbb 100755
--- a/qa/rpc-tests/mempool_reorg.py
+++ b/qa/rpc-tests/mempool_reorg.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
@@ -10,8 +10,6 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-import os
-import shutil
# Create one-input, one-output, no-fee transaction:
class MempoolCoinbaseTest(BitcoinTestFramework):
@@ -25,7 +23,7 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
self.nodes.append(start_node(1, self.options.tmpdir, args))
connect_nodes(self.nodes[1], 0)
self.is_network_split = False
- self.sync_all
+ self.sync_all()
def create_tx(self, from_txid, to_address, amount):
inputs = [{ "txid" : from_txid, "vout" : 0}]
@@ -54,12 +52,12 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
# and make sure the mempool code behaves correctly.
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[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)
+ spend_101_raw = self.create_tx(coinbase_txids[1], node1_address, 49.99)
+ spend_102_raw = self.create_tx(coinbase_txids[2], node0_address, 49.99)
+ spend_103_raw = self.create_tx(coinbase_txids[3], node0_address, 49.99)
# 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})
+ timelock_tx = self.nodes[0].createrawtransaction([{"txid": coinbase_txids[0], "vout": 0}], {node0_address: 49.99})
# 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"
@@ -73,8 +71,8 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
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)
- spend_103_1_raw = self.create_tx(spend_103_id, node1_address, 50)
+ spend_102_1_raw = self.create_tx(spend_102_id, node1_address, 49.98)
+ spend_103_1_raw = self.create_tx(spend_103_id, node1_address, 49.98)
# Broadcast and mine 103_1:
spend_103_1_id = self.nodes[0].sendrawtransaction(spend_103_1_raw)
@@ -87,11 +85,11 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
self.sync_all()
- assert_equal(set(self.nodes[0].getrawmempool()), set([ spend_101_id, spend_102_1_id, timelock_tx_id ]))
+ assert_equal(set(self.nodes[0].getrawmempool()), {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 ]))
+ assert_equal(set(self.nodes[0].getrawmempool()), {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/mempool_resurrect_test.py b/qa/rpc-tests/mempool_resurrect_test.py
index 19c74bb751..9fcc88a2a3 100755
--- a/qa/rpc-tests/mempool_resurrect_test.py
+++ b/qa/rpc-tests/mempool_resurrect_test.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
@@ -10,8 +10,6 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-import os
-import shutil
# Create one-input, one-output, no-fee transaction:
class MempoolCoinbaseTest(BitcoinTestFramework):
@@ -45,13 +43,13 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
b = [ self.nodes[0].getblockhash(n) for n in range(1, 4) ]
coinbase_txids = [ self.nodes[0].getblock(h)['tx'][0] for h in b ]
- spends1_raw = [ self.create_tx(txid, node0_address, 50) for txid in coinbase_txids ]
+ spends1_raw = [ self.create_tx(txid, node0_address, 49.99) for txid in coinbase_txids ]
spends1_id = [ self.nodes[0].sendrawtransaction(tx) for tx in spends1_raw ]
blocks = []
blocks.extend(self.nodes[0].generate(1))
- spends2_raw = [ self.create_tx(txid, node0_address, 49.99) for txid in spends1_id ]
+ spends2_raw = [ self.create_tx(txid, node0_address, 49.98) for txid in spends1_id ]
spends2_id = [ self.nodes[0].sendrawtransaction(tx) for tx in spends2_raw ]
blocks.extend(self.nodes[0].generate(1))
diff --git a/qa/rpc-tests/mempool_spendcoinbase.py b/qa/rpc-tests/mempool_spendcoinbase.py
index fc17c50692..16f512db38 100755
--- a/qa/rpc-tests/mempool_spendcoinbase.py
+++ b/qa/rpc-tests/mempool_spendcoinbase.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
@@ -15,8 +15,6 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-import os
-import shutil
# Create one-input, one-output, no-fee transaction:
class MempoolSpendCoinbaseTest(BitcoinTestFramework):
@@ -46,7 +44,7 @@ class MempoolSpendCoinbaseTest(BitcoinTestFramework):
# is too immature to spend.
b = [ self.nodes[0].getblockhash(n) for n in range(101, 103) ]
coinbase_txids = [ self.nodes[0].getblock(h)['tx'][0] for h in b ]
- spends_raw = [ self.create_tx(txid, node0_address, 50) for txid in coinbase_txids ]
+ spends_raw = [ self.create_tx(txid, node0_address, 49.99) for txid in coinbase_txids ]
spend_101_id = self.nodes[0].sendrawtransaction(spends_raw[0])
diff --git a/qa/rpc-tests/merkle_blocks.py b/qa/rpc-tests/merkle_blocks.py
index 72a80ce6ca..eb718f39e4 100755
--- a/qa/rpc-tests/merkle_blocks.py
+++ b/qa/rpc-tests/merkle_blocks.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
@@ -9,8 +9,6 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-import os
-import shutil
class MerkleBlockTest(BitcoinTestFramework):
@@ -44,9 +42,9 @@ class MerkleBlockTest(BitcoinTestFramework):
assert_equal(self.nodes[2].getbalance(), 0)
node0utxos = self.nodes[0].listunspent(1)
- tx1 = self.nodes[0].createrawtransaction([node0utxos.pop()], {self.nodes[1].getnewaddress(): 50})
+ tx1 = self.nodes[0].createrawtransaction([node0utxos.pop()], {self.nodes[1].getnewaddress(): 49.99})
txid1 = self.nodes[0].sendrawtransaction(self.nodes[0].signrawtransaction(tx1)["hex"])
- tx2 = self.nodes[0].createrawtransaction([node0utxos.pop()], {self.nodes[1].getnewaddress(): 50})
+ tx2 = self.nodes[0].createrawtransaction([node0utxos.pop()], {self.nodes[1].getnewaddress(): 49.99})
txid2 = self.nodes[0].sendrawtransaction(self.nodes[0].signrawtransaction(tx2)["hex"])
assert_raises(JSONRPCException, self.nodes[0].gettxoutproof, [txid1])
@@ -64,7 +62,7 @@ class MerkleBlockTest(BitcoinTestFramework):
assert_equal(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid1, txid2], blockhash)), txlist)
txin_spent = self.nodes[1].listunspent(1).pop()
- tx3 = self.nodes[1].createrawtransaction([txin_spent], {self.nodes[0].getnewaddress(): 50})
+ tx3 = self.nodes[1].createrawtransaction([txin_spent], {self.nodes[0].getnewaddress(): 49.98})
self.nodes[0].sendrawtransaction(self.nodes[1].signrawtransaction(tx3)["hex"])
self.nodes[0].generate(1)
self.sync_all()
@@ -72,7 +70,7 @@ class MerkleBlockTest(BitcoinTestFramework):
txid_spent = txin_spent["txid"]
txid_unspent = txid1 if txin_spent["txid"] != txid1 else txid2
- # We cant find the block from a fully-spent tx
+ # We can't find the block from a fully-spent tx
assert_raises(JSONRPCException, self.nodes[2].gettxoutproof, [txid_spent])
# ...but we can if we specify the block
assert_equal(self.nodes[2].verifytxoutproof(self.nodes[2].gettxoutproof([txid_spent], blockhash)), [txid_spent])
diff --git a/qa/rpc-tests/nodehandling.py b/qa/rpc-tests/nodehandling.py
index e383a3a12c..c6c8c436e9 100755
--- a/qa/rpc-tests/nodehandling.py
+++ b/qa/rpc-tests/nodehandling.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
@@ -9,7 +9,6 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-import base64
try:
import http.client as httplib
@@ -54,7 +53,7 @@ class NodeHandlingTest (BitcoinTestFramework):
self.nodes[2].setban("127.0.0.0/24", "add")
self.nodes[2].setban("192.168.0.1", "add", 1) #ban for 1 seconds
self.nodes[2].setban("2001:4d48:ac57:400:cacf:e9ff:fe1d:9c63/19", "add", 1000) #ban for 1000 seconds
- listBeforeShutdown = self.nodes[2].listbanned();
+ listBeforeShutdown = self.nodes[2].listbanned()
assert_equal("192.168.0.1/32", listBeforeShutdown[2]['address']) #must be here
time.sleep(2) #make 100% sure we expired 192.168.0.1 node time
@@ -62,7 +61,7 @@ class NodeHandlingTest (BitcoinTestFramework):
stop_node(self.nodes[2], 2)
self.nodes[2] = start_node(2, self.options.tmpdir)
- listAfterShutdown = self.nodes[2].listbanned();
+ listAfterShutdown = self.nodes[2].listbanned()
assert_equal("127.0.0.0/24", listAfterShutdown[0]['address'])
assert_equal("127.0.0.0/32", listAfterShutdown[1]['address'])
assert_equal("/19" in listAfterShutdown[2]['address'], True)
diff --git a/qa/rpc-tests/p2p-acceptblock.py b/qa/rpc-tests/p2p-acceptblock.py
index 700deab207..bf355780c1 100755
--- a/qa/rpc-tests/p2p-acceptblock.py
+++ b/qa/rpc-tests/p2p-acceptblock.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-#
+# Copyright (c) 2015 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.
#
@@ -62,7 +62,6 @@ The test:
class TestNode(NodeConnCB):
def __init__(self):
NodeConnCB.__init__(self)
- self.create_callback_map()
self.connection = None
self.ping_counter = 1
self.last_pong = msg_pong()
diff --git a/qa/rpc-tests/p2p-fullblocktest.py b/qa/rpc-tests/p2p-fullblocktest.py
index 9555940cec..b1e8ca53ee 100755
--- a/qa/rpc-tests/p2p-fullblocktest.py
+++ b/qa/rpc-tests/p2p-fullblocktest.py
@@ -1,21 +1,16 @@
#!/usr/bin/env python2
-
-#
+# Copyright (c) 2015 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.
#
from test_framework.test_framework import ComparisonTestFramework
from test_framework.util import *
-from test_framework.comptool import TestManager, TestInstance
-from test_framework.mininode import *
+from test_framework.comptool import TestManager, TestInstance, RejectResult
from test_framework.blocktools import *
-import logging
-import copy
import time
-import numbers
from test_framework.key import CECKey
-from test_framework.script import CScript, CScriptOp, SignatureHash, SIGHASH_ALL, OP_TRUE
+from test_framework.script import CScript, SignatureHash, SIGHASH_ALL, OP_TRUE, OP_FALSE
class PreviousSpendableOutput(object):
def __init__(self, tx = CTransaction(), n = -1):
@@ -122,13 +117,29 @@ class FullBlockTest(ComparisonTestFramework):
return TestInstance([[self.tip, True]])
# returns a test case that asserts that the current tip was rejected
- def rejected():
- return TestInstance([[self.tip, False]])
+ def rejected(reject = None):
+ if reject is None:
+ return TestInstance([[self.tip, False]])
+ else:
+ return TestInstance([[self.tip, reject]])
# move the tip back to a previous block
def tip(number):
self.tip = self.blocks[number]
+ # add transactions to a block produced by next_block
+ def update_block(block_number, new_transactions):
+ block = self.blocks[block_number]
+ old_hash = block.sha256
+ self.add_transactions_to_block(block, new_transactions)
+ block.solve()
+ # Update the internal state just like in next_block
+ self.tip = block
+ self.block_heights[block.sha256] = self.block_heights[old_hash]
+ del self.block_heights[old_hash]
+ self.blocks[block_number] = block
+ return block
+
# creates a new block and advances the tip to that block
block = self.next_block
@@ -141,14 +152,15 @@ class FullBlockTest(ComparisonTestFramework):
# Now we need that block to mature so we can spend the coinbase.
test = TestInstance(sync_every_block=False)
- for i in range(100):
+ for i in range(99):
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):
+ # Start by building 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)
@@ -156,8 +168,7 @@ class FullBlockTest(ComparisonTestFramework):
yield accepted()
out1 = get_spendable_output()
- block(2, spend=out1)
- # Inv again, then deliver twice (shouldn't break anything).
+ b2 = block(2, spend=out1)
yield accepted()
@@ -168,8 +179,8 @@ class FullBlockTest(ComparisonTestFramework):
#
# 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)
+ b3 = block(3, spend=out1)
+ txout_b3 = PreviousSpendableOutput(b3.vtx[1], 1)
yield rejected()
@@ -214,7 +225,7 @@ class FullBlockTest(ComparisonTestFramework):
# \-> b3 (1) -> b4 (2)
tip(6)
block(9, spend=out4, additional_coinbase_value=1)
- yield rejected()
+ yield rejected(RejectResult(16, 'bad-cb-amount'))
# Create a fork that ends in a block with too much fee (the one that causes the reorg)
@@ -226,7 +237,7 @@ class FullBlockTest(ComparisonTestFramework):
yield rejected()
block(11, spend=out4, additional_coinbase_value=1)
- yield rejected()
+ yield rejected(RejectResult(16, 'bad-cb-amount'))
# Try again, but with a valid fork first
@@ -252,6 +263,10 @@ class FullBlockTest(ComparisonTestFramework):
yield TestInstance([[b12, True, b13.sha256]]) # New tip should be b13.
+ # Add a block with MAX_BLOCK_SIGOPS and one with one more sigop
+ # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
+ # \-> b12 (3) -> b13 (4) -> b15 (5) -> b16 (6)
+ # \-> b3 (1) -> b4 (2)
# Test that a block with a lot of checksigs is okay
lots_of_checksigs = CScript([OP_CHECKSIG] * (1000000 / 50 - 1))
@@ -264,8 +279,121 @@ class FullBlockTest(ComparisonTestFramework):
out6 = get_spendable_output()
too_many_checksigs = CScript([OP_CHECKSIG] * (1000000 / 50))
block(16, spend=out6, script=too_many_checksigs)
+ yield rejected(RejectResult(16, 'bad-blk-sigops'))
+
+
+ # Attempt to spend a transaction created on a different fork
+ # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
+ # \-> b12 (3) -> b13 (4) -> b15 (5) -> b17 (b3.vtx[1])
+ # \-> b3 (1) -> b4 (2)
+ tip(15)
+ block(17, spend=txout_b3)
+ yield rejected(RejectResult(16, 'bad-txns-inputs-missingorspent'))
+
+ # Attempt to spend a transaction created on a different fork (on a fork this time)
+ # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
+ # \-> b12 (3) -> b13 (4) -> b15 (5)
+ # \-> b18 (b3.vtx[1]) -> b19 (6)
+ # \-> b3 (1) -> b4 (2)
+ tip(13)
+ block(18, spend=txout_b3)
yield rejected()
+ block(19, spend=out6)
+ yield rejected()
+
+ # Attempt to spend a coinbase at depth too low
+ # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
+ # \-> b12 (3) -> b13 (4) -> b15 (5) -> b20 (7)
+ # \-> b3 (1) -> b4 (2)
+ tip(15)
+ out7 = get_spendable_output()
+ block(20, spend=out7)
+ yield rejected(RejectResult(16, 'bad-txns-premature-spend-of-coinbase'))
+
+ # Attempt to spend a coinbase at depth too low (on a fork this time)
+ # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
+ # \-> b12 (3) -> b13 (4) -> b15 (5)
+ # \-> b21 (6) -> b22 (5)
+ # \-> b3 (1) -> b4 (2)
+ tip(13)
+ block(21, spend=out6)
+ yield rejected()
+
+ block(22, spend=out5)
+ yield rejected()
+
+ # Create a block on either side of MAX_BLOCK_SIZE and make sure its accepted/rejected
+ # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
+ # \-> b12 (3) -> b13 (4) -> b15 (5) -> b23 (6)
+ # \-> b24 (6) -> b25 (7)
+ # \-> b3 (1) -> b4 (2)
+ tip(15)
+ b23 = block(23, spend=out6)
+ old_hash = b23.sha256
+ tx = CTransaction()
+ script_length = MAX_BLOCK_SIZE - len(b23.serialize()) - 69
+ script_output = CScript([chr(0)*script_length])
+ tx.vout.append(CTxOut(0, script_output))
+ tx.vin.append(CTxIn(COutPoint(b23.vtx[1].sha256, 1)))
+ b23 = update_block(23, [tx])
+ # Make sure the math above worked out to produce a max-sized block
+ assert_equal(len(b23.serialize()), MAX_BLOCK_SIZE)
+ yield accepted()
+
+ # Make the next block one byte bigger and check that it fails
+ tip(15)
+ b24 = block(24, spend=out6)
+ script_length = MAX_BLOCK_SIZE - len(b24.serialize()) - 69
+ script_output = CScript([chr(0)*(script_length+1)])
+ tx.vout = [CTxOut(0, script_output)]
+ b24 = update_block(24, [tx])
+ assert_equal(len(b24.serialize()), MAX_BLOCK_SIZE+1)
+ yield rejected(RejectResult(16, 'bad-blk-length'))
+
+ b25 = block(25, spend=out7)
+ yield rejected()
+
+ # Create blocks with a coinbase input script size out of range
+ # genesis -> b1 (0) -> b2 (1) -> b5 (2) -> b6 (3)
+ # \-> b12 (3) -> b13 (4) -> b15 (5) -> b23 (6) -> b30 (7)
+ # \-> ... (6) -> ... (7)
+ # \-> b3 (1) -> b4 (2)
+ tip(15)
+ b26 = block(26, spend=out6)
+ b26.vtx[0].vin[0].scriptSig = chr(0)
+ b26.vtx[0].rehash()
+ # update_block causes the merkle root to get updated, even with no new
+ # transactions, and updates the required state.
+ b26 = update_block(26, [])
+ yield rejected(RejectResult(16, 'bad-cb-length'))
+
+ # Extend the b26 chain to make sure bitcoind isn't accepting b26
+ b27 = block(27, spend=out7)
+ yield rejected()
+
+ # Now try a too-large-coinbase script
+ tip(15)
+ b28 = block(28, spend=out6)
+ b28.vtx[0].vin[0].scriptSig = chr(0)*101
+ b28.vtx[0].rehash()
+ b28 = update_block(28, [])
+ yield rejected(RejectResult(16, 'bad-cb-length'))
+
+ # Extend the b28 chain to make sure bitcoind isn't accepted b28
+ b29 = block(29, spend=out7)
+ # TODO: Should get a reject message back with "bad-prevblk", except
+ # there's a bug that prevents this from being detected. Just note
+ # failure for now, and add the reject result later.
+ yield rejected()
+
+ # b30 has a max-sized coinbase scriptSig.
+ tip(23)
+ b30 = block(30)
+ b30.vtx[0].vin[0].scriptSig = chr(0)*100
+ b30.vtx[0].rehash()
+ b30 = update_block(30, [])
+ yield accepted()
if __name__ == '__main__':
diff --git a/qa/rpc-tests/prioritise_transaction.py b/qa/rpc-tests/prioritise_transaction.py
index f376ceee5e..4a79d38da0 100755
--- a/qa/rpc-tests/prioritise_transaction.py
+++ b/qa/rpc-tests/prioritise_transaction.py
@@ -15,21 +15,7 @@ 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
+ self.txouts = gen_return_txouts()
def setup_chain(self):
print("Initializing test directory "+self.options.tmpdir)
@@ -42,62 +28,15 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
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)
+ utxos = create_confirmed_utxos(self.relayfee, self.nodes[0], 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)
+ txids[i] = create_lots_of_big_transactions(self.nodes[0], self.txouts, 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
@@ -143,5 +82,45 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
if (x != high_fee_tx):
assert(x not in mempool)
+ # Create a free, low priority transaction. Should be rejected.
+ utxo_list = self.nodes[0].listunspent()
+ assert(len(utxo_list) > 0)
+ utxo = utxo_list[0]
+
+ inputs = []
+ outputs = {}
+ inputs.append({"txid" : utxo["txid"], "vout" : utxo["vout"]})
+ outputs[self.nodes[0].getnewaddress()] = utxo["amount"] - self.relayfee
+ raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
+ tx_hex = self.nodes[0].signrawtransaction(raw_tx)["hex"]
+ txid = self.nodes[0].sendrawtransaction(tx_hex)
+
+ # A tx that spends an in-mempool tx has 0 priority, so we can use it to
+ # test the effect of using prioritise transaction for mempool acceptance
+ inputs = []
+ inputs.append({"txid": txid, "vout": 0})
+ outputs = {}
+ outputs[self.nodes[0].getnewaddress()] = utxo["amount"] - self.relayfee
+ raw_tx2 = self.nodes[0].createrawtransaction(inputs, outputs)
+ tx2_hex = self.nodes[0].signrawtransaction(raw_tx2)["hex"]
+ tx2_id = self.nodes[0].decoderawtransaction(tx2_hex)["txid"]
+
+ try:
+ self.nodes[0].sendrawtransaction(tx2_hex)
+ except JSONRPCException as exp:
+ assert_equal(exp.error['code'], -26) # insufficient fee
+ assert(tx2_id not in self.nodes[0].getrawmempool())
+ else:
+ assert(False)
+
+ # This is a less than 1000-byte transaction, so just set the fee
+ # to be the minimum for a 1000 byte transaction and check that it is
+ # accepted.
+ self.nodes[0].prioritisetransaction(tx2_id, 0, int(self.relayfee*COIN))
+
+ print "Assert that prioritised free transaction is accepted to mempool"
+ assert_equal(self.nodes[0].sendrawtransaction(tx2_hex), tx2_id)
+ assert(tx2_id in self.nodes[0].getrawmempool())
+
if __name__ == '__main__':
PrioritiseTransactionTest().main()
diff --git a/qa/rpc-tests/proxy_test.py b/qa/rpc-tests/proxy_test.py
index 3623c16162..7f77e664d2 100755
--- a/qa/rpc-tests/proxy_test.py
+++ b/qa/rpc-tests/proxy_test.py
@@ -3,9 +3,6 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
import socket
-import traceback, sys
-from binascii import hexlify
-import time, os
from test_framework.socks5 import Socks5Configuration, Socks5Command, Socks5Server, AddressType
from test_framework.test_framework import BitcoinTestFramework
@@ -34,7 +31,8 @@ addnode connect to onion
addnode connect to generic DNS name
'''
-class ProxyTest(BitcoinTestFramework):
+
+class ProxyTest(BitcoinTestFramework):
def __init__(self):
# Create two proxies on different ports
# ... one unauthenticated
diff --git a/qa/rpc-tests/pruning.py b/qa/rpc-tests/pruning.py
index 21f8d69382..b0f4b88aee 100755
--- a/qa/rpc-tests/pruning.py
+++ b/qa/rpc-tests/pruning.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
@@ -13,7 +13,6 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-import os.path
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)
@@ -23,24 +22,7 @@ class PruneTest(BitcoinTestFramework):
def __init__(self):
self.utxo = []
self.address = ["",""]
-
- # Some pre-processing to create a bunch of OP_RETURN txouts to insert into transactions we create
- # So we have big transactions and full blocks to fill up our block files
-
- # 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
-
+ self.txouts = gen_return_txouts()
def setup_chain(self):
print("Initializing test directory "+self.options.tmpdir)
diff --git a/qa/rpc-tests/rawtransactions.py b/qa/rpc-tests/rawtransactions.py
index 173faf736e..dd9e5e28a5 100755
--- a/qa/rpc-tests/rawtransactions.py
+++ b/qa/rpc-tests/rawtransactions.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
@@ -10,8 +10,6 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-from pprint import pprint
-from time import sleep
# Create one-input, one-output, no-fee transaction:
class RawTransactionsTest(BitcoinTestFramework):
@@ -43,9 +41,9 @@ class RawTransactionsTest(BitcoinTestFramework):
self.sync_all()
self.nodes[0].generate(101)
self.sync_all()
- self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.5);
- self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.0);
- self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),5.0);
+ self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.5)
+ self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),1.0)
+ self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(),5.0)
self.sync_all()
self.nodes[0].generate(5)
self.sync_all()
@@ -64,7 +62,7 @@ class RawTransactionsTest(BitcoinTestFramework):
except JSONRPCException,e:
errorString = e.error['message']
- assert_equal("Missing inputs" in errorString, True);
+ assert("Missing inputs" in errorString)
#########################
# RAW TX MULTISIG TESTS #
@@ -83,7 +81,7 @@ class RawTransactionsTest(BitcoinTestFramework):
bal = self.nodes[2].getbalance()
# send 1.2 BTC to msig adr
- txId = self.nodes[0].sendtoaddress(mSigObj, 1.2);
+ txId = self.nodes[0].sendtoaddress(mSigObj, 1.2)
self.sync_all()
self.nodes[0].generate(1)
self.sync_all()
@@ -105,7 +103,7 @@ class RawTransactionsTest(BitcoinTestFramework):
mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey']])
mSigObjValid = self.nodes[2].validateaddress(mSigObj)
- txId = self.nodes[0].sendtoaddress(mSigObj, 2.2);
+ txId = self.nodes[0].sendtoaddress(mSigObj, 2.2)
decTx = self.nodes[0].gettransaction(txId)
rawTx = self.nodes[0].decoderawtransaction(decTx['hex'])
sPK = rawTx['vout'][0]['scriptPubKey']['hex']
@@ -123,7 +121,7 @@ class RawTransactionsTest(BitcoinTestFramework):
for outpoint in rawTx['vout']:
if outpoint['value'] == Decimal('2.20000000'):
vout = outpoint
- break;
+ break
bal = self.nodes[0].getbalance()
inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex']}]
diff --git a/qa/rpc-tests/receivedby.py b/qa/rpc-tests/receivedby.py
index 16d6bd4cf1..606426b394 100755
--- a/qa/rpc-tests/receivedby.py
+++ b/qa/rpc-tests/receivedby.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
@@ -53,6 +53,11 @@ def check_array_result(object_array, to_match, expected, should_not_find = False
class ReceivedByTest(BitcoinTestFramework):
+ def setup_nodes(self):
+ #This test requires mocktime
+ enable_mocktime()
+ return start_nodes(4, self.options.tmpdir)
+
def run_test(self):
'''
listreceivedbyaddress Test
diff --git a/qa/rpc-tests/reindex.py b/qa/rpc-tests/reindex.py
index f2e3f248ea..321c2fe422 100755
--- a/qa/rpc-tests/reindex.py
+++ b/qa/rpc-tests/reindex.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
@@ -8,7 +8,6 @@
#
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-import os.path
class ReindexTest(BitcoinTestFramework):
diff --git a/qa/rpc-tests/replace-by-fee.py b/qa/rpc-tests/replace-by-fee.py
index 6e9e0b304c..ba1956853a 100755
--- a/qa/rpc-tests/replace-by-fee.py
+++ b/qa/rpc-tests/replace-by-fee.py
@@ -54,8 +54,7 @@ def make_utxo(node, amount, confirmed=True, scriptPubKey=CScript([1])):
tx2.vout = [CTxOut(amount, scriptPubKey)]
tx2.rehash()
- tx2_hex = binascii.hexlify(tx2.serialize()).decode('utf-8')
- #print tx2_hex
+ binascii.hexlify(tx2.serialize()).decode('utf-8')
signed_tx = node.signrawtransaction(binascii.hexlify(tx2.serialize()).decode('utf-8'))
@@ -63,8 +62,14 @@ def make_utxo(node, amount, confirmed=True, scriptPubKey=CScript([1])):
# If requested, ensure txouts are confirmed.
if confirmed:
- while len(node.getrawmempool()):
+ mempool_size = len(node.getrawmempool())
+ while mempool_size > 0:
node.generate(1)
+ new_size = len(node.getrawmempool())
+ # Error out if we have something stuck in the mempool, as this
+ # would likely be a bug.
+ assert(new_size < mempool_size)
+ mempool_size = new_size
return COutPoint(int(txid, 16), 0)
@@ -72,7 +77,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
def setup_network(self):
self.nodes = []
- self.nodes.append(start_node(0, self.options.tmpdir, ["-maxorphantx=1000",
+ self.nodes.append(start_node(0, self.options.tmpdir, ["-maxorphantx=1000", "-debug",
"-relaypriority=0", "-whitelist=127.0.0.1",
"-limitancestorcount=50",
"-limitancestorsize=101",
@@ -108,6 +113,9 @@ class ReplaceByFeeTest(BitcoinTestFramework):
print "Running test opt-in..."
self.test_opt_in()
+ print "Running test prioritised transactions..."
+ self.test_prioritised_transactions()
+
print "Passed\n"
def test_simple_doublespend(self):
@@ -513,5 +521,72 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# but make sure it is accepted anyway
self.nodes[0].sendrawtransaction(tx3c_hex, True)
+ def test_prioritised_transactions(self):
+ # Ensure that fee deltas used via prioritisetransaction are
+ # correctly used by replacement logic
+
+ # 1. Check that feeperkb uses modified fees
+ tx0_outpoint = make_utxo(self.nodes[0], 1.1*COIN)
+
+ tx1a = CTransaction()
+ tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
+ tx1a.vout = [CTxOut(1*COIN, CScript([b'a']))]
+ tx1a_hex = txToHex(tx1a)
+ tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
+
+ # Higher fee, but the actual fee per KB is much lower.
+ tx1b = CTransaction()
+ tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
+ tx1b.vout = [CTxOut(0.001*COIN, CScript([b'a'*740000]))]
+ tx1b_hex = txToHex(tx1b)
+
+ # Verify tx1b cannot replace tx1a.
+ try:
+ tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
+ except JSONRPCException as exp:
+ assert_equal(exp.error['code'], -26)
+ else:
+ assert(False)
+
+ # Use prioritisetransaction to set tx1a's fee to 0.
+ self.nodes[0].prioritisetransaction(tx1a_txid, 0, int(-0.1*COIN))
+
+ # Now tx1b should be able to replace tx1a
+ tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
+
+ assert(tx1b_txid in self.nodes[0].getrawmempool())
+
+ # 2. Check that absolute fee checks use modified fee.
+ tx1_outpoint = make_utxo(self.nodes[0], 1.1*COIN)
+
+ tx2a = CTransaction()
+ tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0)]
+ tx2a.vout = [CTxOut(1*COIN, CScript([b'a']))]
+ tx2a_hex = txToHex(tx2a)
+ tx2a_txid = self.nodes[0].sendrawtransaction(tx2a_hex, True)
+
+ # Lower fee, but we'll prioritise it
+ tx2b = CTransaction()
+ tx2b.vin = [CTxIn(tx1_outpoint, nSequence=0)]
+ tx2b.vout = [CTxOut(1.01*COIN, CScript([b'a']))]
+ tx2b.rehash()
+ tx2b_hex = txToHex(tx2b)
+
+ # Verify tx2b cannot replace tx2a.
+ try:
+ tx2b_txid = self.nodes[0].sendrawtransaction(tx2b_hex, True)
+ except JSONRPCException as exp:
+ assert_equal(exp.error['code'], -26)
+ else:
+ assert(False)
+
+ # Now prioritise tx2b to have a higher modified fee
+ self.nodes[0].prioritisetransaction(tx2b.hash, 0, int(0.1*COIN))
+
+ # tx2b should now be accepted
+ tx2b_txid = self.nodes[0].sendrawtransaction(tx2b_hex, True)
+
+ assert(tx2b_txid in self.nodes[0].getrawmempool())
+
if __name__ == '__main__':
ReplaceByFeeTest().main()
diff --git a/qa/rpc-tests/rest.py b/qa/rpc-tests/rest.py
index e084ad55ab..8c83536501 100755
--- a/qa/rpc-tests/rest.py
+++ b/qa/rpc-tests/rest.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
@@ -12,9 +12,7 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
from struct import *
import binascii
-import json
import StringIO
-import decimal
try:
import http.client as httplib
@@ -143,9 +141,9 @@ class RESTTest (BitcoinTestFramework):
binaryRequest = b'\x01\x02'
binaryRequest += binascii.unhexlify(txid)
- binaryRequest += pack("i", n);
- binaryRequest += binascii.unhexlify(vintx);
- binaryRequest += pack("i", 0);
+ binaryRequest += pack("i", n)
+ binaryRequest += binascii.unhexlify(vintx)
+ binaryRequest += pack("i", 0)
bin_response = http_post_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'bin', binaryRequest)
output = StringIO.StringIO()
@@ -206,7 +204,7 @@ class RESTTest (BitcoinTestFramework):
json_request = '/checkmempool/'
for x in range(0, 15):
json_request += txid+'-'+str(n)+'/'
- json_request = json_request.rstrip("/");
+ json_request = json_request.rstrip("/")
response = http_post_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json', '', True)
assert_equal(response.status, 200) #must be a 500 because we exceeding the limits
@@ -254,7 +252,7 @@ class RESTTest (BitcoinTestFramework):
response_header_json = http_get_call(url.hostname, url.port, '/rest/headers/1/'+bb_hash+self.FORMAT_SEPARATOR+"json", True)
assert_equal(response_header_json.status, 200)
response_header_json_str = response_header_json.read()
- json_obj = json.loads(response_header_json_str, parse_float=decimal.Decimal)
+ json_obj = json.loads(response_header_json_str, parse_float=Decimal)
assert_equal(len(json_obj), 1) #ensure that there is one header in the json response
assert_equal(json_obj[0]['hash'], bb_hash) #request/response hash should be the same
@@ -282,7 +280,7 @@ class RESTTest (BitcoinTestFramework):
assert_equal(len(json_obj), 5) #now we should have 5 header objects
# do tx test
- tx_hash = block_json_obj['tx'][0]['txid'];
+ tx_hash = block_json_obj['tx'][0]['txid']
json_string = http_get_call(url.hostname, url.port, '/rest/tx/'+tx_hash+self.FORMAT_SEPARATOR+"json")
json_obj = json.loads(json_string)
assert_equal(json_obj['txid'], tx_hash)
diff --git a/qa/rpc-tests/rpcbind_test.py b/qa/rpc-tests/rpcbind_test.py
index 7a9da66787..10a48b5556 100755
--- a/qa/rpc-tests/rpcbind_test.py
+++ b/qa/rpc-tests/rpcbind_test.py
@@ -1,17 +1,12 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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 for -rpcbind, as well as -rpcallowip and -rpcconnect
-# Add python-bitcoinrpc to module search path:
-import os
-import sys
+# TODO extend this test from the test framework (like all other tests)
-import json
-import shutil
-import subprocess
import tempfile
import traceback
diff --git a/qa/rpc-tests/sendheaders.py b/qa/rpc-tests/sendheaders.py
index d7f4292090..2bc32584b5 100755
--- a/qa/rpc-tests/sendheaders.py
+++ b/qa/rpc-tests/sendheaders.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-#
+# Copyright (c) 2014-2015 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.
#
@@ -7,7 +7,6 @@
from test_framework.mininode import *
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-import time
from test_framework.blocktools import create_block, create_coinbase
'''
@@ -70,7 +69,6 @@ f. Announce 1 more header that builds on that fork.
class BaseNode(NodeConnCB):
def __init__(self):
NodeConnCB.__init__(self)
- self.create_callback_map()
self.connection = None
self.last_inv = None
self.last_headers = None
@@ -221,18 +219,20 @@ class SendHeadersTest(BitcoinTestFramework):
# mine count blocks and return the new tip
def mine_blocks(self, count):
+ # Clear out last block announcement from each p2p listener
+ [ x.clear_last_announcement() for x in self.p2p_connections ]
self.nodes[0].generate(count)
return int(self.nodes[0].getbestblockhash(), 16)
# mine a reorg that invalidates length blocks (replacing them with
# length+1 blocks).
- # peers is the p2p nodes we're using; we clear their state after the
+ # Note: we clear the state of our p2p connections after the
# to-be-reorged-out blocks are mined, so that we don't break later tests.
# return the list of block hashes newly mined
- def mine_reorg(self, length, peers):
+ def mine_reorg(self, length):
self.nodes[0].generate(length) # make sure all invalidated blocks are node0's
sync_blocks(self.nodes, wait=0.1)
- [x.clear_last_announcement() for x in peers]
+ [x.clear_last_announcement() for x in self.p2p_connections]
tip_height = self.nodes[1].getblockcount()
hash_to_invalidate = self.nodes[1].getblockhash(tip_height-(length-1))
@@ -246,6 +246,8 @@ class SendHeadersTest(BitcoinTestFramework):
inv_node = InvNode()
test_node = TestNode()
+ self.p2p_connections = [inv_node, test_node]
+
connections = []
connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], inv_node))
# Set nServices to 0 for test_node, so no block download will occur outside of
@@ -304,7 +306,6 @@ class SendHeadersTest(BitcoinTestFramework):
prev_tip = int(self.nodes[0].getbestblockhash(), 16)
test_node.get_headers(locator=[prev_tip], hashstop=0L)
test_node.sync_with_ping()
- test_node.clear_last_announcement() # Clear out empty headers response
# Now that we've synced headers, headers announcements should work
tip = self.mine_blocks(1)
@@ -353,8 +354,6 @@ class SendHeadersTest(BitcoinTestFramework):
# broadcast it)
assert_equal(inv_node.last_inv, None)
assert_equal(inv_node.last_headers, None)
- inv_node.clear_last_announcement()
- test_node.clear_last_announcement()
tip = self.mine_blocks(1)
assert_equal(inv_node.check_last_announcement(inv=[tip]), True)
assert_equal(test_node.check_last_announcement(headers=[tip]), True)
@@ -369,7 +368,7 @@ class SendHeadersTest(BitcoinTestFramework):
# getheaders or inv from peer.
for j in xrange(2):
# First try mining a reorg that can propagate with header announcement
- new_block_hashes = self.mine_reorg(length=7, peers=[test_node, inv_node])
+ new_block_hashes = self.mine_reorg(length=7)
tip = new_block_hashes[-1]
assert_equal(inv_node.check_last_announcement(inv=[tip]), True)
assert_equal(test_node.check_last_announcement(headers=new_block_hashes), True)
@@ -377,7 +376,7 @@ class SendHeadersTest(BitcoinTestFramework):
block_time += 8
# Mine a too-large reorg, which should be announced with a single inv
- new_block_hashes = self.mine_reorg(length=8, peers=[test_node, inv_node])
+ new_block_hashes = self.mine_reorg(length=8)
tip = new_block_hashes[-1]
assert_equal(inv_node.check_last_announcement(inv=[tip]), True)
assert_equal(test_node.check_last_announcement(inv=[tip]), True)
@@ -389,7 +388,7 @@ class SendHeadersTest(BitcoinTestFramework):
# Use getblocks/getdata
test_node.send_getblocks(locator = [fork_point])
- assert_equal(test_node.check_last_announcement(inv=new_block_hashes[0:-1]), True)
+ assert_equal(test_node.check_last_announcement(inv=new_block_hashes), True)
test_node.get_data(new_block_hashes)
test_node.wait_for_block(new_block_hashes[-1])
@@ -408,7 +407,6 @@ class SendHeadersTest(BitcoinTestFramework):
test_node.get_headers(locator=[fork_point], hashstop=new_block_hashes[1])
test_node.get_data([tip])
test_node.wait_for_block(tip)
- test_node.clear_last_announcement()
elif i == 2:
test_node.get_data([tip])
test_node.wait_for_block(tip)
@@ -446,7 +444,7 @@ class SendHeadersTest(BitcoinTestFramework):
inv_node.sync_with_ping() # Make sure blocks are processed
test_node.last_getdata = None
- test_node.send_header_for_blocks(blocks);
+ test_node.send_header_for_blocks(blocks)
test_node.sync_with_ping()
# should not have received any getdata messages
with mininode_lock:
diff --git a/qa/rpc-tests/test_framework/blocktools.py b/qa/rpc-tests/test_framework/blocktools.py
index 59aa8c15cc..7eea41b75c 100644
--- a/qa/rpc-tests/test_framework/blocktools.py
+++ b/qa/rpc-tests/test_framework/blocktools.py
@@ -1,11 +1,11 @@
# blocktools.py - utilities for manipulating blocks and transactions
-#
+# Copyright (c) 2015 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.
#
from mininode import *
-from script import CScript, CScriptOp, OP_TRUE, OP_CHECKSIG
+from script import CScript, OP_TRUE, OP_CHECKSIG
# Create a block (with regtest difficulty)
def create_block(hashprev, coinbase, nTime=None):
diff --git a/qa/rpc-tests/test_framework/comptool.py b/qa/rpc-tests/test_framework/comptool.py
index e0b3ce040d..a4cd4d0a89 100755
--- a/qa/rpc-tests/test_framework/comptool.py
+++ b/qa/rpc-tests/test_framework/comptool.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-#
+# Copyright (c) 2015 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.
#
@@ -41,17 +41,32 @@ def wait_until(predicate, attempts=float('inf'), timeout=float('inf')):
return False
+class RejectResult(object):
+ '''
+ Outcome that expects rejection of a transaction or block.
+ '''
+ def __init__(self, code, reason=''):
+ self.code = code
+ self.reason = reason
+ def match(self, other):
+ if self.code != other.code:
+ return False
+ return other.reason.startswith(self.reason)
+ def __repr__(self):
+ return '%i:%s' % (self.code,self.reason or '*')
+
class TestNode(NodeConnCB):
def __init__(self, block_store, tx_store):
NodeConnCB.__init__(self)
- self.create_callback_map()
self.conn = None
self.bestblockhash = None
self.block_store = block_store
self.block_request_map = {}
self.tx_store = tx_store
self.tx_request_map = {}
+ self.block_reject_map = {}
+ self.tx_reject_map = {}
# When the pingmap is non-empty we're waiting for
# a response
@@ -95,6 +110,12 @@ class TestNode(NodeConnCB):
except KeyError:
raise AssertionError("Got pong for unknown ping [%s]" % repr(message))
+ def on_reject(self, conn, message):
+ if message.message == 'tx':
+ self.tx_reject_map[message.data] = RejectResult(message.code, message.reason)
+ if message.message == 'block':
+ self.block_reject_map[message.data] = RejectResult(message.code, message.reason)
+
def send_inv(self, obj):
mtype = 2 if isinstance(obj, CBlock) else 1
self.conn.send_message(msg_inv([CInv(mtype, obj.sha256)]))
@@ -244,6 +265,15 @@ class TestManager(object):
if outcome is None:
if c.cb.bestblockhash != self.connections[0].cb.bestblockhash:
return False
+ elif isinstance(outcome, RejectResult): # Check that block was rejected w/ code
+ if c.cb.bestblockhash == blockhash:
+ return False
+ if blockhash not in c.cb.block_reject_map:
+ print 'Block not in reject map: %064x' % (blockhash)
+ return False
+ if not outcome.match(c.cb.block_reject_map[blockhash]):
+ print 'Block rejected with %s instead of expected %s: %064x' % (c.cb.block_reject_map[blockhash], outcome, blockhash)
+ return False
elif ((c.cb.bestblockhash == blockhash) != outcome):
# print c.cb.bestblockhash, blockhash, outcome
return False
@@ -263,6 +293,15 @@ class TestManager(object):
if c.cb.lastInv != self.connections[0].cb.lastInv:
# print c.rpc.getrawmempool()
return False
+ elif isinstance(outcome, RejectResult): # Check that tx was rejected w/ code
+ if txhash in c.cb.lastInv:
+ return False
+ if txhash not in c.cb.tx_reject_map:
+ print 'Tx not in reject map: %064x' % (txhash)
+ return False
+ if not outcome.match(c.cb.tx_reject_map[txhash]):
+ print 'Tx rejected with %s instead of expected %s: %064x' % (c.cb.tx_reject_map[txhash], outcome, txhash)
+ return False
elif ((txhash in c.cb.lastInv) != outcome):
# print c.rpc.getrawmempool(), c.cb.lastInv
return False
diff --git a/qa/rpc-tests/test_framework/coverage.py b/qa/rpc-tests/test_framework/coverage.py
index 50f066a850..d21a001b6e 100644
--- a/qa/rpc-tests/test_framework/coverage.py
+++ b/qa/rpc-tests/test_framework/coverage.py
@@ -1,3 +1,9 @@
+#!/usr/bin/env python2
+# Copyright (c) 2015 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.
+#
+
"""
This module contains utilities for doing coverage analysis on the RPC
interface.
diff --git a/qa/rpc-tests/test_framework/mininode.py b/qa/rpc-tests/test_framework/mininode.py
index 64985d58e2..81bb439cea 100755
--- a/qa/rpc-tests/test_framework/mininode.py
+++ b/qa/rpc-tests/test_framework/mininode.py
@@ -36,6 +36,7 @@ MY_VERSION = 60001 # past bip-31 for ping/pong
MY_SUBVERSION = "/python-mininode-tester:0.0.1/"
MAX_INV_SZ = 50000
+MAX_BLOCK_SIZE = 1000000
# Keep our own socket map for asyncore, so that we can track disconnects
# ourselves (to workaround an issue with closing an asyncore socket when
@@ -230,6 +231,14 @@ def ser_int_vector(l):
r += struct.pack("<i", i)
return r
+# Deserialize from a hex string representation (eg from RPC)
+def FromHex(obj, hex_string):
+ obj.deserialize(cStringIO.StringIO(binascii.unhexlify(hex_string)))
+ return obj
+
+# Convert a binary-serializable object to hex (eg for submission via RPC)
+def ToHex(obj):
+ return binascii.hexlify(obj.serialize()).decode('utf-8')
# Objects that map to bitcoind objects, which can be serialized/deserialized
@@ -535,7 +544,7 @@ class CBlock(CBlockHeader):
return True
def solve(self):
- self.calc_sha256()
+ self.rehash()
target = uint256_from_compact(self.nBits)
while self.sha256 > target:
self.nNonce += 1
@@ -1003,6 +1012,18 @@ class msg_reject(object):
class NodeConnCB(object):
def __init__(self):
self.verack_received = False
+ # deliver_sleep_time is helpful for debugging race conditions in p2p
+ # tests; it causes message delivery to sleep for the specified time
+ # before acquiring the global lock and delivering the next message.
+ self.deliver_sleep_time = None
+
+ def set_deliver_sleep_time(self, value):
+ with mininode_lock:
+ self.deliver_sleep_time = value
+
+ def get_deliver_sleep_time(self):
+ with mininode_lock:
+ return self.deliver_sleep_time
# Spin until verack message is received from the node.
# Tests may want to use this as a signal that the test can begin.
@@ -1015,32 +1036,13 @@ class NodeConnCB(object):
return
time.sleep(0.05)
- # Derived classes should call this function once to set the message map
- # which associates the derived classes' functions to incoming messages
- def create_callback_map(self):
- self.cbmap = {
- "version": self.on_version,
- "verack": self.on_verack,
- "addr": self.on_addr,
- "alert": self.on_alert,
- "inv": self.on_inv,
- "getdata": self.on_getdata,
- "getblocks": self.on_getblocks,
- "tx": self.on_tx,
- "block": self.on_block,
- "getaddr": self.on_getaddr,
- "ping": self.on_ping,
- "pong": self.on_pong,
- "headers": self.on_headers,
- "getheaders": self.on_getheaders,
- "reject": self.on_reject,
- "mempool": self.on_mempool
- }
-
def deliver(self, conn, message):
+ deliver_sleep = self.get_deliver_sleep_time()
+ if deliver_sleep is not None:
+ time.sleep(deliver_sleep)
with mininode_lock:
try:
- self.cbmap[message.command](conn, message)
+ getattr(self, 'on_' + message.command)(conn, message)
except:
print "ERROR delivering %s (%s)" % (repr(message),
sys.exc_info()[0])
diff --git a/qa/rpc-tests/test_framework/netutil.py b/qa/rpc-tests/test_framework/netutil.py
index b30a88a4f7..50daa87937 100644
--- a/qa/rpc-tests/test_framework/netutil.py
+++ b/qa/rpc-tests/test_framework/netutil.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
diff --git a/qa/rpc-tests/test_framework/script.py b/qa/rpc-tests/test_framework/script.py
index 0a78cf6fb1..bf5e25fb27 100644
--- a/qa/rpc-tests/test_framework/script.py
+++ b/qa/rpc-tests/test_framework/script.py
@@ -14,7 +14,8 @@ Functionality to build scripts, as well as SignatureHash().
from __future__ import absolute_import, division, print_function, unicode_literals
-from test_framework.mininode import CTransaction, CTxOut, hash256
+from .mininode import CTransaction, CTxOut, hash256
+from binascii import hexlify
import sys
bchr = chr
@@ -24,10 +25,9 @@ if sys.version > '3':
bchr = lambda x: bytes([x])
bord = lambda x: x
-import copy
import struct
-from test_framework.bignum import bn2vch
+from .bignum import bn2vch
MAX_SCRIPT_SIZE = 10000
MAX_SCRIPT_ELEMENT_SIZE = 520
@@ -226,7 +226,7 @@ OP_CHECKMULTISIGVERIFY = CScriptOp(0xaf)
# expansion
OP_NOP1 = CScriptOp(0xb0)
-OP_NOP2 = CScriptOp(0xb1)
+OP_CHECKLOCKTIMEVERIFY = CScriptOp(0xb1)
OP_NOP3 = CScriptOp(0xb2)
OP_NOP4 = CScriptOp(0xb3)
OP_NOP5 = CScriptOp(0xb4)
@@ -353,7 +353,7 @@ VALID_OPCODES = {
OP_CHECKMULTISIGVERIFY,
OP_NOP1,
- OP_NOP2,
+ OP_CHECKLOCKTIMEVERIFY,
OP_NOP3,
OP_NOP4,
OP_NOP5,
@@ -472,7 +472,7 @@ OPCODE_NAMES.update({
OP_CHECKMULTISIG : 'OP_CHECKMULTISIG',
OP_CHECKMULTISIGVERIFY : 'OP_CHECKMULTISIGVERIFY',
OP_NOP1 : 'OP_NOP1',
- OP_NOP2 : 'OP_NOP2',
+ OP_CHECKLOCKTIMEVERIFY : 'OP_CHECKLOCKTIMEVERIFY',
OP_NOP3 : 'OP_NOP3',
OP_NOP4 : 'OP_NOP4',
OP_NOP5 : 'OP_NOP5',
@@ -591,7 +591,7 @@ OPCODES_BY_NAME = {
'OP_CHECKMULTISIG' : OP_CHECKMULTISIG,
'OP_CHECKMULTISIGVERIFY' : OP_CHECKMULTISIGVERIFY,
'OP_NOP1' : OP_NOP1,
- 'OP_NOP2' : OP_NOP2,
+ 'OP_CHECKLOCKTIMEVERIFY' : OP_CHECKLOCKTIMEVERIFY,
'OP_NOP3' : OP_NOP3,
'OP_NOP4' : OP_NOP4,
'OP_NOP5' : OP_NOP5,
@@ -777,7 +777,7 @@ class CScript(bytes):
# need to change
def _repr(o):
if isinstance(o, bytes):
- return "x('%s')" % binascii.hexlify(o).decode('utf8')
+ return "x('%s')" % hexlify(o).decode('utf8')
else:
return repr(o)
diff --git a/qa/rpc-tests/test_framework/test_framework.py b/qa/rpc-tests/test_framework/test_framework.py
index ae2d91ab60..584f318d0b 100755
--- a/qa/rpc-tests/test_framework/test_framework.py
+++ b/qa/rpc-tests/test_framework/test_framework.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
@@ -120,7 +120,7 @@ class BitcoinTestFramework(object):
if self.options.coveragedir:
enable_coverage(self.options.coveragedir)
- os.environ['PATH'] = self.options.srcdir+":"+os.environ['PATH']
+ os.environ['PATH'] = self.options.srcdir+":"+self.options.srcdir+"/qt:"+os.environ['PATH']
check_json_precision()
diff --git a/qa/rpc-tests/test_framework/util.py b/qa/rpc-tests/test_framework/util.py
index b7e90a8a8b..8c472a518d 100644
--- a/qa/rpc-tests/test_framework/util.py
+++ b/qa/rpc-tests/test_framework/util.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
#
@@ -22,6 +22,26 @@ from .authproxy import AuthServiceProxy, JSONRPCException
COVERAGE_DIR = None
+#Set Mocktime default to OFF.
+#MOCKTIME is only needed for scripts that use the
+#cached version of the blockchain. If the cached
+#version of the blockchain is used without MOCKTIME
+#then the mempools will not sync due to IBD.
+MOCKTIME = 0
+
+def enable_mocktime():
+ #For backwared compatibility of the python scripts
+ #with previous versions of the cache, set MOCKTIME
+ #to Jan 1, 2014 + (201 * 10 * 60)
+ global MOCKTIME
+ MOCKTIME = 1388534400 + (201 * 10 * 60)
+
+def disable_mocktime():
+ global MOCKTIME
+ MOCKTIME = 0
+
+def get_mocktime():
+ return MOCKTIME
def enable_coverage(dirname):
"""Maintain a log of which RPC calls are made during testing."""
@@ -102,11 +122,12 @@ def initialize_datadir(dirname, n):
if not os.path.isdir(datadir):
os.makedirs(datadir)
with open(os.path.join(datadir, "bitcoin.conf"), 'w') as f:
- f.write("regtest=1\n");
- f.write("rpcuser=rt\n");
- f.write("rpcpassword=rt\n");
- f.write("port="+str(p2p_port(n))+"\n");
- f.write("rpcport="+str(rpc_port(n))+"\n");
+ f.write("regtest=1\n")
+ f.write("rpcuser=rt\n")
+ f.write("rpcpassword=rt\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 initialize_chain(test_dir):
@@ -130,7 +151,7 @@ def initialize_chain(test_dir):
# Create cache directories, run bitcoinds:
for i in range(4):
datadir=initialize_datadir("cache", i)
- args = [ os.getenv("BITCOIND", "bitcoind"), "-keypool=1", "-datadir="+datadir, "-discover=0" ]
+ args = [ os.getenv("BITCOIND", "bitcoind"), "-server", "-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)
@@ -154,9 +175,10 @@ def initialize_chain(test_dir):
# Create a 200-block-long chain; each of the 4 nodes
# gets 25 mature blocks and 25 immature.
- # blocks are created with timestamps 10 minutes apart, starting
- # at 1 Jan 2014
- block_time = 1388534400
+ # blocks are created with timestamps 10 minutes apart
+ # starting from 2010 minutes in the past
+ enable_mocktime()
+ block_time = get_mocktime() - (201 * 10 * 60)
for i in range(2):
for peer in range(4):
for j in range(25):
@@ -169,6 +191,7 @@ def initialize_chain(test_dir):
# Shut them down, and clean up cache directories:
stop_nodes(rpcs)
wait_bitcoinds()
+ disable_mocktime()
for i in range(4):
os.remove(log_filename("cache", i, "debug.log"))
os.remove(log_filename("cache", i, "db.log"))
@@ -217,8 +240,7 @@ 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")
- # RPC tests still depend on free transactions
- args = [ binary, "-datadir="+datadir, "-keypool=1", "-discover=0", "-rest", "-blockprioritysize=50000" ]
+ args = [ binary, "-datadir="+datadir, "-server", "-keypool=1", "-discover=0", "-rest", "-mocktime="+str(get_mocktime()) ]
if extra_args is not None: args.extend(extra_args)
bitcoind_processes[i] = subprocess.Popen(args)
devnull = open(os.devnull, "w")
@@ -406,5 +428,86 @@ def assert_raises(exc, fun, *args, **kwds):
else:
raise AssertionError("No exception raised")
+def assert_is_hex_string(string):
+ try:
+ int(string, 16)
+ except Exception as e:
+ raise AssertionError(
+ "Couldn't interpret %r as hexadecimal; raised: %s" % (string, e))
+
+def assert_is_hash_string(string, length=64):
+ if not isinstance(string, basestring):
+ raise AssertionError("Expected a string, got type %r" % type(string))
+ elif length and len(string) != length:
+ raise AssertionError(
+ "String of length %d expected; got %d" % (length, len(string)))
+ elif not re.match('[abcdef0-9]+$', string):
+ raise AssertionError(
+ "String %r contains invalid characters for a hash." % string)
+
def satoshi_round(amount):
return Decimal(amount).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN)
+
+def create_confirmed_utxos(fee, node, count):
+ node.generate(int(0.5*count)+101)
+ utxos = node.listunspent()
+ iterations = count - len(utxos)
+ addr1 = node.getnewaddress()
+ addr2 = node.getnewaddress()
+ if iterations <= 0:
+ return utxos
+ for i in xrange(iterations):
+ t = utxos.pop()
+ 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 = node.createrawtransaction(inputs, outputs)
+ signed_tx = node.signrawtransaction(raw_tx)["hex"]
+ txid = node.sendrawtransaction(signed_tx)
+
+ while (node.getmempoolinfo()['size'] > 0):
+ node.generate(1)
+
+ utxos = node.listunspent()
+ assert(len(utxos) >= count)
+ return utxos
+
+def gen_return_txouts():
+ # 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
+ txouts = "81"
+ for k in xrange(128):
+ # add txout value
+ txouts = txouts + "0000000000000000"
+ # add length of script_pubkey
+ txouts = txouts + "fd0402"
+ # add script_pubkey
+ txouts = txouts + script_pubkey
+ return txouts
+
+def create_lots_of_big_transactions(node, txouts, utxos, fee):
+ addr = node.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 = node.createrawtransaction(inputs, outputs)
+ newtx = rawtx[0:92]
+ newtx = newtx + txouts
+ newtx = newtx + rawtx[94:]
+ signresult = node.signrawtransaction(newtx, None, None, "NONE")
+ txid = node.sendrawtransaction(signresult["hex"], True)
+ txids.append(txid)
+ return txids
diff --git a/qa/rpc-tests/txn_clone.py b/qa/rpc-tests/txn_clone.py
index b1f603a192..b132aec4b6 100755
--- a/qa/rpc-tests/txn_clone.py
+++ b/qa/rpc-tests/txn_clone.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
@@ -8,11 +8,7 @@
#
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.authproxy import AuthServiceProxy, JSONRPCException
-from decimal import Decimal
from test_framework.util import *
-import os
-import shutil
class TxnMallTest(BitcoinTestFramework):
@@ -57,16 +53,10 @@ class TxnMallTest(BitcoinTestFramework):
clone_inputs = [{"txid":rawtx1["vin"][0]["txid"],"vout":rawtx1["vin"][0]["vout"]}]
clone_outputs = {rawtx1["vout"][0]["scriptPubKey"]["addresses"][0]:rawtx1["vout"][0]["value"],
rawtx1["vout"][1]["scriptPubKey"]["addresses"][0]:rawtx1["vout"][1]["value"]}
- clone_raw = self.nodes[0].createrawtransaction(clone_inputs, clone_outputs)
+ clone_locktime = rawtx1["locktime"]
+ clone_raw = self.nodes[0].createrawtransaction(clone_inputs, clone_outputs, clone_locktime)
- # 3 hex manipulations on the clone are required
-
- # manipulation 1. sequence is at version+#inputs+input+sigstub
- posseq = 2*(4+1+36+1)
- seqbe = '%08x' % rawtx1["vin"][0]["sequence"]
- clone_raw = clone_raw[:posseq] + seqbe[6:8] + seqbe[4:6] + seqbe[2:4] + seqbe[0:2] + clone_raw[posseq + 8:]
-
- # manipulation 2. createrawtransaction randomizes the order of its outputs, so swap them if necessary.
+ # createrawtransaction randomizes the order of its outputs, so swap them if necessary.
# output 0 is at version+#inputs+input+sigstub+sequence+#outputs
# 40 BTC serialized is 00286bee00000000
pos0 = 2*(4+1+36+1+4+1)
@@ -78,11 +68,6 @@ class TxnMallTest(BitcoinTestFramework):
output1 = clone_raw[pos0 + output_len : pos0 + 2 * output_len]
clone_raw = clone_raw[:pos0] + output1 + output0 + clone_raw[pos0 + 2 * output_len:]
- # manipulation 3. locktime is after outputs
- poslt = pos0 + 2 * output_len
- ltbe = '%08x' % rawtx1["locktime"]
- clone_raw = clone_raw[:poslt] + ltbe[6:8] + ltbe[4:6] + ltbe[2:4] + ltbe[0:2] + clone_raw[poslt + 8:]
-
# Use a different signature hash type to sign. This creates an equivalent but malleated clone.
# Don't send the clone anywhere yet
tx1_clone = self.nodes[0].signrawtransaction(clone_raw, None, None, "ALL|ANYONECANPAY")
diff --git a/qa/rpc-tests/txn_doublespend.py b/qa/rpc-tests/txn_doublespend.py
index d4665b3d42..8d7f6e505d 100755
--- a/qa/rpc-tests/txn_doublespend.py
+++ b/qa/rpc-tests/txn_doublespend.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
@@ -9,9 +9,6 @@
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-from decimal import Decimal
-import os
-import shutil
class TxnMallTest(BitcoinTestFramework):
diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py
index 6f6bc31895..6cd879e4a0 100755
--- a/qa/rpc-tests/wallet.py
+++ b/qa/rpc-tests/wallet.py
@@ -1,24 +1,8 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
-#
-# 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
-# k) test ResendWalletTransactions - create transactions, startup fourth node, make sure it syncs
-#
-
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
@@ -65,7 +49,6 @@ class WalletTest (BitcoinTestFramework):
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)
@@ -97,7 +80,7 @@ class WalletTest (BitcoinTestFramework):
inputs = []
outputs = {}
inputs.append({ "txid" : utxo["txid"], "vout" : utxo["vout"]})
- outputs[self.nodes[2].getnewaddress("from1")] = utxo["amount"]
+ outputs[self.nodes[2].getnewaddress("from1")] = utxo["amount"] - 3
raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
txns_to_send.append(self.nodes[0].signrawtransaction(raw_tx))
@@ -110,8 +93,8 @@ class WalletTest (BitcoinTestFramework):
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)
+ assert_equal(self.nodes[2].getbalance(), 94)
+ assert_equal(self.nodes[2].getbalance("from1"), 94-21)
# Send 10 BTC normal
address = self.nodes[0].getnewaddress("test")
@@ -120,7 +103,7 @@ class WalletTest (BitcoinTestFramework):
txid = self.nodes[2].sendtoaddress(address, 10, "", "", False)
self.nodes[2].generate(1)
self.sync_all()
- node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), Decimal('90'), fee_per_byte, count_bytes(self.nodes[2].getrawtransaction(txid)))
+ node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), Decimal('84'), fee_per_byte, count_bytes(self.nodes[2].getrawtransaction(txid)))
assert_equal(self.nodes[0].getbalance(), Decimal('10'))
# Send 10 BTC with subtract fee from amount
@@ -160,7 +143,7 @@ class WalletTest (BitcoinTestFramework):
sync_blocks(self.nodes)
relayed = self.nodes[0].resendwallettransactions()
- assert_equal(set(relayed), set([txid1, txid2]))
+ assert_equal(set(relayed), {txid1, txid2})
sync_mempools(self.nodes)
assert(txid1 in self.nodes[3].getrawmempool())
@@ -190,7 +173,7 @@ class WalletTest (BitcoinTestFramework):
for uTx in unspentTxs:
if uTx['txid'] == zeroValueTxid:
found = True
- assert_equal(uTx['amount'], Decimal('0.00000000'));
+ assert_equal(uTx['amount'], Decimal('0'))
assert(found)
#do some -walletbroadcast tests
@@ -202,21 +185,22 @@ class WalletTest (BitcoinTestFramework):
connect_nodes_bi(self.nodes,0,2)
self.sync_all()
- txIdNotBroadcasted = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2);
+ txIdNotBroadcasted = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2)
txObjNotBroadcasted = self.nodes[0].gettransaction(txIdNotBroadcasted)
self.nodes[1].generate(1) #mine a block, tx should not be in there
self.sync_all()
- assert_equal(self.nodes[2].getbalance(), node_2_bal); #should not be changed because tx was not broadcasted
+ assert_equal(self.nodes[2].getbalance(), node_2_bal) #should not be changed because tx was not broadcasted
#now broadcast from another node, mine a block, sync, and check the balance
self.nodes[1].sendrawtransaction(txObjNotBroadcasted['hex'])
self.nodes[1].generate(1)
self.sync_all()
+ node_2_bal += 2
txObjNotBroadcasted = self.nodes[0].gettransaction(txIdNotBroadcasted)
- assert_equal(self.nodes[2].getbalance(), node_2_bal + Decimal('2')); #should not be
+ assert_equal(self.nodes[2].getbalance(), node_2_bal)
#create another tx
- txIdNotBroadcasted = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2);
+ txIdNotBroadcasted = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2)
#restart the nodes with -walletbroadcast=1
stop_nodes(self.nodes)
@@ -229,23 +213,24 @@ class WalletTest (BitcoinTestFramework):
self.nodes[0].generate(1)
sync_blocks(self.nodes)
+ node_2_bal += 2
#tx should be added to balance because after restarting the nodes tx should be broadcastet
- assert_equal(self.nodes[2].getbalance(), node_2_bal + Decimal('4')); #should not be
+ assert_equal(self.nodes[2].getbalance(), node_2_bal)
#send a tx with value in a string (PR#6380 +)
txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "2")
txObj = self.nodes[0].gettransaction(txId)
- assert_equal(txObj['amount'], Decimal('-2.00000000'))
+ assert_equal(txObj['amount'], Decimal('-2'))
txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "0.0001")
txObj = self.nodes[0].gettransaction(txId)
- assert_equal(txObj['amount'], Decimal('-0.00010000'))
+ assert_equal(txObj['amount'], Decimal('-0.0001'))
#check if JSON parser can handle scientific notation in strings
txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "1e-4")
txObj = self.nodes[0].gettransaction(txId)
- assert_equal(txObj['amount'], Decimal('-0.00010000'))
+ assert_equal(txObj['amount'], Decimal('-0.0001'))
#this should fail
errorString = ""
@@ -254,7 +239,7 @@ class WalletTest (BitcoinTestFramework):
except JSONRPCException,e:
errorString = e.error['message']
- assert_equal("Invalid amount" in errorString, True);
+ assert_equal("Invalid amount" in errorString, True)
errorString = ""
try:
@@ -262,7 +247,31 @@ class WalletTest (BitcoinTestFramework):
except JSONRPCException,e:
errorString = e.error['message']
- assert_equal("not an integer" in errorString, True);
+ assert_equal("not an integer" in errorString, True)
+
+ #check if wallet or blochchain maintenance changes the balance
+ self.sync_all()
+ self.nodes[0].generate(1)
+ self.sync_all()
+ balance_nodes = [self.nodes[i].getbalance() for i in range(3)]
+
+ maintenance = [
+ '-rescan',
+ '-reindex',
+ '-zapwallettxes=1',
+ '-zapwallettxes=2',
+ '-salvagewallet',
+ ]
+ for m in maintenance:
+ print "check " + m
+ stop_nodes(self.nodes)
+ wait_bitcoinds()
+ self.nodes = start_nodes(3, self.options.tmpdir, [[m]] * 3)
+ connect_nodes_bi(self.nodes,0,1)
+ connect_nodes_bi(self.nodes,1,2)
+ connect_nodes_bi(self.nodes,0,2)
+ self.sync_all()
+ assert_equal(balance_nodes, [self.nodes[i].getbalance() for i in range(3)])
if __name__ == '__main__':
diff --git a/qa/rpc-tests/walletbackup.py b/qa/rpc-tests/walletbackup.py
index da100d7fc0..1221a09116 100755
--- a/qa/rpc-tests/walletbackup.py
+++ b/qa/rpc-tests/walletbackup.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
diff --git a/qa/rpc-tests/zapwallettxes.py b/qa/rpc-tests/zapwallettxes.py
index 0ec8ec5364..1ee0f79ac0 100755
--- a/qa/rpc-tests/zapwallettxes.py
+++ b/qa/rpc-tests/zapwallettxes.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python2
-# Copyright (c) 2014 The Bitcoin Core developers
+# Copyright (c) 2014-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.
diff --git a/qa/rpc-tests/zmq_test.py b/qa/rpc-tests/zmq_test.py
index bcb132321a..88532541ab 100755
--- a/qa/rpc-tests/zmq_test.py
+++ b/qa/rpc-tests/zmq_test.py
@@ -11,7 +11,6 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
import zmq
import binascii
-from test_framework.mininode import hash256
try:
import http.client as httplib
@@ -42,7 +41,7 @@ class ZMQTest (BitcoinTestFramework):
def run_test(self):
self.sync_all()
- genhashes = self.nodes[0].generate(1);
+ genhashes = self.nodes[0].generate(1)
self.sync_all()
print "listen..."
@@ -58,7 +57,7 @@ class ZMQTest (BitcoinTestFramework):
assert_equal(genhashes[0], blkhash) #blockhash from generate must be equal to the hash received over zmq
n = 10
- genhashes = self.nodes[1].generate(n);
+ genhashes = self.nodes[1].generate(n)
self.sync_all()
zmqHashes = []
@@ -76,7 +75,7 @@ class ZMQTest (BitcoinTestFramework):
hashRPC = self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1.0)
self.sync_all()
- #now we should receive a zmq msg because the tx was broadcastet
+ # now we should receive a zmq msg because the tx was broadcast
msg = self.zmqSubSocket.recv_multipart()
topic = str(msg[0])
body = msg[1]