aboutsummaryrefslogtreecommitdiff
path: root/qa
diff options
context:
space:
mode:
Diffstat (limited to 'qa')
-rwxr-xr-xqa/pull-tester/rpc-tests.sh35
-rw-r--r--qa/rpc-tests/README.md28
-rwxr-xr-xqa/rpc-tests/bipdersig-p2p.py12
-rwxr-xr-xqa/rpc-tests/bipdersig.py5
-rwxr-xr-xqa/rpc-tests/conflictedbalance.sh2
-rwxr-xr-xqa/rpc-tests/forknotify.py5
-rwxr-xr-xqa/rpc-tests/fundrawtransaction.py556
-rwxr-xr-xqa/rpc-tests/getblocktemplate_longpoll.py5
-rwxr-xr-xqa/rpc-tests/getblocktemplate_proposals.py5
-rwxr-xr-xqa/rpc-tests/getchaintips.py4
-rwxr-xr-xqa/rpc-tests/httpbasics.py38
-rwxr-xr-xqa/rpc-tests/invalidateblock.py5
-rwxr-xr-xqa/rpc-tests/invalidblockrequest.py10
-rwxr-xr-xqa/rpc-tests/keypool.py4
-rwxr-xr-xqa/rpc-tests/listtransactions.py5
-rwxr-xr-xqa/rpc-tests/maxblocksinflight.py6
-rwxr-xr-xqa/rpc-tests/mempool_coinbase_spends.py5
-rwxr-xr-xqa/rpc-tests/mempool_resurrect_test.py6
-rwxr-xr-xqa/rpc-tests/mempool_spendcoinbase.py5
-rwxr-xr-xqa/rpc-tests/merkle_blocks.py5
-rwxr-xr-xqa/rpc-tests/nodehandling.py69
-rwxr-xr-xqa/rpc-tests/p2p-acceptblock.py226
-rwxr-xr-xqa/rpc-tests/proxy_test.py68
-rwxr-xr-xqa/rpc-tests/pruning.py24
-rw-r--r--qa/rpc-tests/python-bitcoinrpc/bitcoinrpc/.gitignore1
-rw-r--r--qa/rpc-tests/python-bitcoinrpc/setup.py15
-rwxr-xr-xqa/rpc-tests/rawtransactions.py4
-rwxr-xr-xqa/rpc-tests/receivedby.py5
-rwxr-xr-xqa/rpc-tests/reindex.py5
-rwxr-xr-xqa/rpc-tests/rest.py117
-rwxr-xr-xqa/rpc-tests/rpcbind_test.py6
-rwxr-xr-xqa/rpc-tests/script_test.py14
-rwxr-xr-xqa/rpc-tests/signrawtransactions.py4
-rwxr-xr-xqa/rpc-tests/smartfees.py286
-rw-r--r--qa/rpc-tests/test_framework/__init__.py (renamed from qa/rpc-tests/python-bitcoinrpc/bitcoinrpc/__init__.py)0
-rw-r--r--qa/rpc-tests/test_framework/authproxy.py (renamed from qa/rpc-tests/python-bitcoinrpc/bitcoinrpc/authproxy.py)0
-rw-r--r--qa/rpc-tests/test_framework/bignum.py (renamed from qa/rpc-tests/bignum.py)0
-rw-r--r--qa/rpc-tests/test_framework/blockstore.py (renamed from qa/rpc-tests/blockstore.py)0
-rw-r--r--qa/rpc-tests/test_framework/blocktools.py (renamed from qa/rpc-tests/blocktools.py)0
-rwxr-xr-xqa/rpc-tests/test_framework/comptool.py (renamed from qa/rpc-tests/comptool.py)0
-rwxr-xr-xqa/rpc-tests/test_framework/mininode.py (renamed from qa/rpc-tests/mininode.py)0
-rw-r--r--qa/rpc-tests/test_framework/netutil.py (renamed from qa/rpc-tests/netutil.py)0
-rw-r--r--qa/rpc-tests/test_framework/script.py (renamed from qa/rpc-tests/script.py)4
-rw-r--r--qa/rpc-tests/test_framework/socks5.py (renamed from qa/rpc-tests/socks5.py)0
-rwxr-xr-xqa/rpc-tests/test_framework/test_framework.py (renamed from qa/rpc-tests/test_framework.py)3
-rw-r--r--qa/rpc-tests/test_framework/util.py (renamed from qa/rpc-tests/util.py)11
-rwxr-xr-xqa/rpc-tests/txn_doublespend.py5
-rwxr-xr-xqa/rpc-tests/wallet.py5
-rwxr-xr-xqa/rpc-tests/walletbackup.py4
-rwxr-xr-xqa/rpc-tests/zapwallettxes.py4
50 files changed, 1342 insertions, 284 deletions
diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh
index ecde45059b..d9a72fae2d 100755
--- a/qa/pull-tester/rpc-tests.sh
+++ b/qa/pull-tester/rpc-tests.sh
@@ -30,19 +30,50 @@ testScripts=(
'zapwallettxes.py'
'proxy_test.py'
'merkle_blocks.py'
+ 'fundrawtransaction.py'
'signrawtransactions.py'
+ 'walletbackup.py'
+ 'nodehandling.py'
+);
+testScriptsExt=(
+ 'bipdersig-p2p.py'
+ 'bipdersig.py'
+ 'getblocktemplate_longpoll.py'
+ 'getblocktemplate_proposals.py'
+ 'pruning.py'
+ 'forknotify.py'
+ 'invalidateblock.py'
+ 'keypool.py'
+ 'receivedby.py'
+ 'reindex.py'
+ 'rpcbind_test.py'
+# 'script_test.py'
+ 'smartfees.py'
'maxblocksinflight.py'
'invalidblockrequest.py'
'rawtransactions.py'
# 'forknotify.py'
+ 'p2p-acceptblock.py'
);
+
+extArg="-extended"
+passOn=${@#$extArg}
+
if [ "x${ENABLE_BITCOIND}${ENABLE_UTILS}${ENABLE_WALLET}" = "x111" ]; then
for (( i = 0; i < ${#testScripts[@]}; i++ ))
do
- if [ -z "$1" ] || [ "$1" == "${testScripts[$i]}" ] || [ "$1.py" == "${testScripts[$i]}" ]
+ if [ -z "$1" ] || [ "${1:0:1}" == "-" ] || [ "$1" == "${testScripts[$i]}" ] || [ "$1.py" == "${testScripts[$i]}" ]
then
echo -e "Running testscript \033[1m${testScripts[$i]}...\033[0m"
- ${BUILDDIR}/qa/rpc-tests/${testScripts[$i]} --srcdir "${BUILDDIR}/src"
+ ${BUILDDIR}/qa/rpc-tests/${testScripts[$i]} --srcdir "${BUILDDIR}/src" ${passOn}
+ fi
+ done
+ for (( i = 0; i < ${#testScriptsExt[@]}; i++ ))
+ do
+ if [ "$1" == $extArg ] || [ "$1" == "${testScriptsExt[$i]}" ] || [ "$1.py" == "${testScriptsExt[$i]}" ]
+ then
+ echo -e "Running \033[1m2nd level\033[0m testscript \033[1m${testScriptsExt[$i]}...\033[0m"
+ ${BUILDDIR}/qa/rpc-tests/${testScriptsExt[$i]} --srcdir "${BUILDDIR}/src" ${passOn}
fi
done
else
diff --git a/qa/rpc-tests/README.md b/qa/rpc-tests/README.md
index d9fbb109e8..efc81e7a97 100644
--- a/qa/rpc-tests/README.md
+++ b/qa/rpc-tests/README.md
@@ -6,25 +6,37 @@ Git subtree of [https://github.com/jgarzik/python-bitcoinrpc](https://github.com
Changes to python-bitcoinrpc should be made upstream, and then
pulled here using git subtree.
-### [test_framework.py](test_framework.py)
+### [test_framework/test_framework.py](test_framework/test_framework.py)
Base class for new regression tests.
-### [listtransactions.py](listtransactions.py)
-Tests for the listtransactions RPC call.
-
-### [util.py](util.py)
+### [test_framework/util.py](test_framework/util.py)
Generally useful functions.
Bash-based tests, to be ported to Python:
-----------------------------------------
-- wallet.sh : Exercise wallet send/receive code.
-- walletbackup.sh : Exercise wallet backup / dump / import
-- txnmall.sh : Test proper accounting of malleable transactions
- conflictedbalance.sh : More testing of malleable transaction handling
Notes
=====
+You can run a single test by calling `qa/pull-tester/rpc-tests.sh <testname>`.
+
+Run all possible tests with `qa/pull-tester/rpc-tests.sh -extended`.
+
+Possible options:
+
+```
+-h, --help show this help message and exit
+ --nocleanup Leave bitcoinds and test.* datadir on exit or error
+ --noshutdown Don't stop bitcoinds after the test execution
+ --srcdir=SRCDIR Source directory containing bitcoind/bitcoin-cli (default:
+ ../../src)
+ --tmpdir=TMPDIR Root directory for datadirs
+ --tracerpc Print out all RPC calls as they are made
+```
+
+If you set the environment variable `PYTHON_DEBUG=1` you will get some debug output (example: `PYTHON_DEBUG=1 qa/pull-tester/rpc-tests.sh wallet`).
+
A 200-block -regtest blockchain and wallets for four nodes
is created the first time a regression test is run and
is stored in the cache/ directory. Each node has 25 mature
diff --git a/qa/rpc-tests/bipdersig-p2p.py b/qa/rpc-tests/bipdersig-p2p.py
index ff0c878898..41717377b2 100755
--- a/qa/rpc-tests/bipdersig-p2p.py
+++ b/qa/rpc-tests/bipdersig-p2p.py
@@ -4,14 +4,14 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
#
-from test_framework import ComparisonTestFramework
-from util import *
-from mininode import CTransaction, NetworkThread
-from blocktools import create_coinbase, create_block
+from test_framework.test_framework import ComparisonTestFramework
+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
from binascii import hexlify, unhexlify
import cStringIO
-from comptool import TestInstance, TestManager
-from script import CScript
import time
# A canonical signature consists of:
diff --git a/qa/rpc-tests/bipdersig.py b/qa/rpc-tests/bipdersig.py
index 2c43bba865..243f816f65 100755
--- a/qa/rpc-tests/bipdersig.py
+++ b/qa/rpc-tests/bipdersig.py
@@ -7,9 +7,8 @@
# Test the BIP66 changeover logic
#
-from test_framework import BitcoinTestFramework
-from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
-from util import *
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
import os
import shutil
diff --git a/qa/rpc-tests/conflictedbalance.sh b/qa/rpc-tests/conflictedbalance.sh
index 3b6c8dc318..7e44097374 100755
--- a/qa/rpc-tests/conflictedbalance.sh
+++ b/qa/rpc-tests/conflictedbalance.sh
@@ -49,7 +49,7 @@ B2ARGS="-datadir=$D2 -debug=mempool"
$BITCOIND $B2ARGS &
B2PID=$!
-# Wait until all four nodes are at the same block number
+# Wait until both nodes are at the same block number
function WaitBlocks {
while :
do
diff --git a/qa/rpc-tests/forknotify.py b/qa/rpc-tests/forknotify.py
index af22ffb1a5..0acef8e30b 100755
--- a/qa/rpc-tests/forknotify.py
+++ b/qa/rpc-tests/forknotify.py
@@ -7,9 +7,8 @@
# Test -alertnotify
#
-from test_framework import BitcoinTestFramework
-from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
-from util import *
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
import os
import shutil
diff --git a/qa/rpc-tests/fundrawtransaction.py b/qa/rpc-tests/fundrawtransaction.py
new file mode 100755
index 0000000000..e859b26433
--- /dev/null
+++ b/qa/rpc-tests/fundrawtransaction.py
@@ -0,0 +1,556 @@
+#!/usr/bin/env python2
+# Copyright (c) 2014 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+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):
+
+ def setup_chain(self):
+ print("Initializing test directory "+self.options.tmpdir)
+ initialize_chain_clean(self.options.tmpdir, 3)
+
+ def setup_network(self, split=False):
+ self.nodes = start_nodes(3, self.options.tmpdir)
+
+ connect_nodes_bi(self.nodes,0,1)
+ connect_nodes_bi(self.nodes,1,2)
+ connect_nodes_bi(self.nodes,0,2)
+
+ self.is_network_split=False
+ self.sync_all()
+
+ def run_test(self):
+ print "Mining blocks..."
+ feeTolerance = Decimal(0.00000002) #if the fee's positive delta is higher than this value tests will fail, neg. delta always fail the tests
+
+ self.nodes[2].generate(1)
+ 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.sync_all()
+ self.nodes[0].generate(1)
+ self.sync_all()
+
+ ###############
+ # simple test #
+ ###############
+ inputs = [ ]
+ outputs = { self.nodes[0].getnewaddress() : 1.0 }
+ rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
+ dec_tx = self.nodes[2].decoderawtransaction(rawtx)
+
+ rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
+ fee = rawtxfund['fee']
+ dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
+ totalOut = 0
+ for out in dec_tx['vout']:
+ totalOut += out['value']
+
+ assert_equal(len(dec_tx['vin']), 1) #one vin coin
+ assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '')
+ assert_equal(fee + totalOut, 1.5) #the 1.5BTC coin must be taken
+
+ ##############################
+ # simple test with two coins #
+ ##############################
+ inputs = [ ]
+ outputs = { self.nodes[0].getnewaddress() : 2.2 }
+ rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
+ dec_tx = self.nodes[2].decoderawtransaction(rawtx)
+
+ rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
+ fee = rawtxfund['fee']
+ dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
+ totalOut = 0
+ for out in dec_tx['vout']:
+ totalOut += out['value']
+
+ assert_equal(len(dec_tx['vin']), 2) #one vin coin
+ assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '')
+ assert_equal(dec_tx['vin'][1]['scriptSig']['hex'], '')
+ assert_equal(fee + totalOut, 2.5) #the 1.5BTC+1.0BTC coins must have be taken
+
+ ##############################
+ # simple test with two coins #
+ ##############################
+ inputs = [ ]
+ outputs = { self.nodes[0].getnewaddress() : 2.6 }
+ rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
+ dec_tx = self.nodes[2].decoderawtransaction(rawtx)
+
+ rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
+ fee = rawtxfund['fee']
+ dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
+ totalOut = 0
+ for out in dec_tx['vout']:
+ totalOut += out['value']
+
+ assert_equal(len(dec_tx['vin']), 1) #one vin coin
+ assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '')
+ assert_equal(fee + totalOut, 5.0) #the 5.0BTC coin must have be taken
+
+
+ ################################
+ # simple test with two outputs #
+ ################################
+ inputs = [ ]
+ outputs = { self.nodes[0].getnewaddress() : 2.6, self.nodes[1].getnewaddress() : 2.5 }
+ rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
+ dec_tx = self.nodes[2].decoderawtransaction(rawtx)
+
+ rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
+ fee = rawtxfund['fee']
+ dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
+ totalOut = 0
+ for out in dec_tx['vout']:
+ totalOut += out['value']
+
+ assert_equal(len(dec_tx['vin']), 2) #one vin coin
+ assert_equal(dec_tx['vin'][0]['scriptSig']['hex'], '')
+ assert_equal(dec_tx['vin'][1]['scriptSig']['hex'], '')
+ assert_equal(fee + totalOut, 6.0) #the 5.0BTC + 1.0BTC coins must have be taken
+
+
+
+ #########################################################################
+ # test a fundrawtransaction with a VIN greater than the required amount #
+ #########################################################################
+ utx = False
+ listunspent = self.nodes[2].listunspent()
+ for aUtx in listunspent:
+ if aUtx['amount'] == 5.0:
+ utx = aUtx
+ break;
+
+ assert_equal(utx!=False, True)
+
+ inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}]
+ outputs = { self.nodes[0].getnewaddress() : 1.0 }
+ rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
+ dec_tx = self.nodes[2].decoderawtransaction(rawtx)
+ assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
+
+ rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
+ fee = rawtxfund['fee']
+ dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
+ totalOut = 0
+ for out in dec_tx['vout']:
+ totalOut += out['value']
+
+ assert_equal(fee + totalOut, utx['amount']) #compare vin total and totalout+fee
+
+
+
+ #####################################################################
+ # test a fundrawtransaction with which will not get a change output #
+ #####################################################################
+ utx = False
+ listunspent = self.nodes[2].listunspent()
+ for aUtx in listunspent:
+ if aUtx['amount'] == 5.0:
+ utx = aUtx
+ break;
+
+ assert_equal(utx!=False, True)
+
+ inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}]
+ outputs = { self.nodes[0].getnewaddress() : Decimal(5.0) - fee - feeTolerance }
+ rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
+ dec_tx = self.nodes[2].decoderawtransaction(rawtx)
+ assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
+
+ rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
+ fee = rawtxfund['fee']
+ dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
+ totalOut = 0
+ for out in dec_tx['vout']:
+ totalOut += out['value']
+
+ assert_equal(rawtxfund['changepos'], -1)
+ assert_equal(fee + totalOut, utx['amount']) #compare vin total and totalout+fee
+
+
+
+ #########################################################################
+ # test a fundrawtransaction with a VIN smaller than the required amount #
+ #########################################################################
+ utx = False
+ listunspent = self.nodes[2].listunspent()
+ for aUtx in listunspent:
+ if aUtx['amount'] == 1.0:
+ utx = aUtx
+ break;
+
+ assert_equal(utx!=False, True)
+
+ inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']}]
+ outputs = { self.nodes[0].getnewaddress() : 1.0 }
+ rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
+
+ # 4-byte version + 1-byte vin count + 36-byte prevout then script_len
+ rawtx = rawtx[:82] + "0100" + rawtx[84:]
+
+ dec_tx = self.nodes[2].decoderawtransaction(rawtx)
+ assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
+ assert_equal("00", dec_tx['vin'][0]['scriptSig']['hex'])
+
+ rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
+ fee = rawtxfund['fee']
+ dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
+ totalOut = 0
+ matchingOuts = 0
+ for i, out in enumerate(dec_tx['vout']):
+ totalOut += out['value']
+ if outputs.has_key(out['scriptPubKey']['addresses'][0]):
+ matchingOuts+=1
+ else:
+ assert_equal(i, rawtxfund['changepos'])
+
+ assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
+ assert_equal("00", dec_tx['vin'][0]['scriptSig']['hex'])
+
+ assert_equal(matchingOuts, 1)
+ assert_equal(len(dec_tx['vout']), 2)
+
+ assert_equal(fee + totalOut, 2.5) #this tx must use the 1.0BTC and the 1.5BTC coin
+
+
+ ###########################################
+ # test a fundrawtransaction with two VINs #
+ ###########################################
+ utx = False
+ utx2 = False
+ listunspent = self.nodes[2].listunspent()
+ for aUtx in listunspent:
+ if aUtx['amount'] == 1.0:
+ utx = aUtx
+ if aUtx['amount'] == 5.0:
+ utx2 = aUtx
+
+
+ assert_equal(utx!=False, True)
+
+ inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']},{'txid' : utx2['txid'], 'vout' : utx2['vout']} ]
+ outputs = { self.nodes[0].getnewaddress() : 6.0 }
+ rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
+ dec_tx = self.nodes[2].decoderawtransaction(rawtx)
+ assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
+
+ rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
+ fee = rawtxfund['fee']
+ dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
+ totalOut = 0
+ matchingOuts = 0
+ for out in dec_tx['vout']:
+ totalOut += out['value']
+ if outputs.has_key(out['scriptPubKey']['addresses'][0]):
+ matchingOuts+=1
+
+ assert_equal(matchingOuts, 1)
+ assert_equal(len(dec_tx['vout']), 2)
+
+ matchingIns = 0
+ for vinOut in dec_tx['vin']:
+ for vinIn in inputs:
+ if vinIn['txid'] == vinOut['txid']:
+ matchingIns+=1
+
+ assert_equal(matchingIns, 2) #we now must see two vins identical to vins given as params
+ assert_equal(fee + totalOut, 7.5) #this tx must use the 1.0BTC and the 1.5BTC coin
+
+
+ #########################################################
+ # test a fundrawtransaction with two VINs and two vOUTs #
+ #########################################################
+ utx = False
+ utx2 = False
+ listunspent = self.nodes[2].listunspent()
+ for aUtx in listunspent:
+ if aUtx['amount'] == 1.0:
+ utx = aUtx
+ if aUtx['amount'] == 5.0:
+ utx2 = aUtx
+
+
+ assert_equal(utx!=False, True)
+
+ inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']},{'txid' : utx2['txid'], 'vout' : utx2['vout']} ]
+ outputs = { self.nodes[0].getnewaddress() : 6.0, self.nodes[0].getnewaddress() : 1.0 }
+ rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
+ dec_tx = self.nodes[2].decoderawtransaction(rawtx)
+ assert_equal(utx['txid'], dec_tx['vin'][0]['txid'])
+
+ rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
+ fee = rawtxfund['fee']
+ dec_tx = self.nodes[2].decoderawtransaction(rawtxfund['hex'])
+ totalOut = 0
+ matchingOuts = 0
+ for out in dec_tx['vout']:
+ totalOut += out['value']
+ if outputs.has_key(out['scriptPubKey']['addresses'][0]):
+ matchingOuts+=1
+
+ assert_equal(matchingOuts, 2)
+ assert_equal(len(dec_tx['vout']), 3)
+ assert_equal(fee + totalOut, 7.5) #this tx must use the 1.0BTC and the 1.5BTC coin
+
+
+ ##############################################
+ # test a fundrawtransaction with invalid vin #
+ ##############################################
+ listunspent = self.nodes[2].listunspent()
+ inputs = [ {'txid' : "1c7f966dab21119bac53213a2bc7532bff1fa844c124fd750a7d0b1332440bd1", 'vout' : 0} ] #invalid vin!
+ outputs = { self.nodes[0].getnewaddress() : 1.0}
+ rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
+ dec_tx = self.nodes[2].decoderawtransaction(rawtx)
+
+ errorString = ""
+ try:
+ rawtxfund = self.nodes[2].fundrawtransaction(rawtx)
+ except JSONRPCException,e:
+ errorString = e.error['message']
+
+ assert_equal("Insufficient" in errorString, True);
+
+
+
+ ############################################################
+ #compare fee of a standard pubkeyhash transaction
+ inputs = []
+ outputs = {self.nodes[1].getnewaddress():1.1}
+ rawTx = self.nodes[0].createrawtransaction(inputs, outputs)
+ fundedTx = self.nodes[0].fundrawtransaction(rawTx)
+
+ #create same transaction over sendtoaddress
+ 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);
+ assert(feeDelta >= 0 and feeDelta <= feeTolerance)
+ ############################################################
+
+ ############################################################
+ #compare fee of a standard pubkeyhash transaction with multiple outputs
+ inputs = []
+ outputs = {self.nodes[1].getnewaddress():1.1,self.nodes[1].getnewaddress():1.2,self.nodes[1].getnewaddress():0.1,self.nodes[1].getnewaddress():1.3,self.nodes[1].getnewaddress():0.2,self.nodes[1].getnewaddress():0.3}
+ rawTx = self.nodes[0].createrawtransaction(inputs, outputs)
+ fundedTx = self.nodes[0].fundrawtransaction(rawTx)
+ #create same transaction over sendtoaddress
+ txId = self.nodes[0].sendmany("", outputs);
+ signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']
+
+ #compare fee
+ feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee);
+ assert(feeDelta >= 0 and feeDelta <= feeTolerance)
+ ############################################################
+
+
+ ############################################################
+ #compare fee of a 2of2 multisig p2sh transaction
+
+ # create 2of2 addr
+ addr1 = self.nodes[1].getnewaddress()
+ addr2 = self.nodes[1].getnewaddress()
+
+ addr1Obj = self.nodes[1].validateaddress(addr1)
+ addr2Obj = self.nodes[1].validateaddress(addr2)
+
+ mSigObj = self.nodes[1].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])
+
+ inputs = []
+ outputs = {mSigObj:1.1}
+ rawTx = self.nodes[0].createrawtransaction(inputs, outputs)
+ fundedTx = self.nodes[0].fundrawtransaction(rawTx)
+
+ #create same transaction over sendtoaddress
+ txId = self.nodes[0].sendtoaddress(mSigObj, 1.1);
+ signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']
+
+ #compare fee
+ feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee);
+ assert(feeDelta >= 0 and feeDelta <= feeTolerance)
+ ############################################################
+
+
+ ############################################################
+ #compare fee of a standard pubkeyhash transaction
+
+ # create 4of5 addr
+ addr1 = self.nodes[1].getnewaddress()
+ addr2 = self.nodes[1].getnewaddress()
+ addr3 = self.nodes[1].getnewaddress()
+ addr4 = self.nodes[1].getnewaddress()
+ addr5 = self.nodes[1].getnewaddress()
+
+ addr1Obj = self.nodes[1].validateaddress(addr1)
+ addr2Obj = self.nodes[1].validateaddress(addr2)
+ addr3Obj = self.nodes[1].validateaddress(addr3)
+ addr4Obj = self.nodes[1].validateaddress(addr4)
+ addr5Obj = self.nodes[1].validateaddress(addr5)
+
+ mSigObj = self.nodes[1].addmultisigaddress(4, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey'], addr4Obj['pubkey'], addr5Obj['pubkey']])
+
+ inputs = []
+ outputs = {mSigObj:1.1}
+ rawTx = self.nodes[0].createrawtransaction(inputs, outputs)
+ fundedTx = self.nodes[0].fundrawtransaction(rawTx)
+
+ #create same transaction over sendtoaddress
+ txId = self.nodes[0].sendtoaddress(mSigObj, 1.1);
+ signedFee = self.nodes[0].getrawmempool(True)[txId]['fee']
+
+ #compare fee
+ feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee);
+ assert(feeDelta >= 0 and feeDelta <= feeTolerance)
+ ############################################################
+
+
+ ############################################################
+ # spend a 2of2 multisig transaction over fundraw
+
+ # create 2of2 addr
+ addr1 = self.nodes[2].getnewaddress()
+ addr2 = self.nodes[2].getnewaddress()
+
+ addr1Obj = self.nodes[2].validateaddress(addr1)
+ addr2Obj = self.nodes[2].validateaddress(addr2)
+
+ mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])
+
+
+ # send 1.2 BTC to msig addr
+ txId = self.nodes[0].sendtoaddress(mSigObj, 1.2);
+ self.sync_all()
+ self.nodes[1].generate(1)
+ self.sync_all()
+
+ oldBalance = self.nodes[1].getbalance()
+ inputs = []
+ outputs = {self.nodes[1].getnewaddress():1.1}
+ rawTx = self.nodes[2].createrawtransaction(inputs, outputs)
+ fundedTx = self.nodes[2].fundrawtransaction(rawTx)
+
+ signedTx = self.nodes[2].signrawtransaction(fundedTx['hex'])
+ txId = self.nodes[2].sendrawtransaction(signedTx['hex'])
+ self.sync_all()
+ self.nodes[1].generate(1)
+ self.sync_all()
+
+ # make sure funds are received at node1
+ assert_equal(oldBalance+Decimal('1.10000000'), self.nodes[1].getbalance())
+
+ ############################################################
+ # locked wallet test
+ self.nodes[1].encryptwallet("test")
+ self.nodes.pop(1)
+ stop_nodes(self.nodes)
+ wait_bitcoinds()
+
+ self.nodes = start_nodes(3, self.options.tmpdir)
+
+ connect_nodes_bi(self.nodes,0,1)
+ connect_nodes_bi(self.nodes,1,2)
+ connect_nodes_bi(self.nodes,0,2)
+ self.is_network_split=False
+ self.sync_all()
+
+ error = False
+ try:
+ self.nodes[1].sendtoaddress(self.nodes[0].getnewaddress(), 1.2);
+ except:
+ error = True
+ assert(error)
+
+ oldBalance = self.nodes[0].getbalance()
+
+ inputs = []
+ outputs = {self.nodes[0].getnewaddress():1.1}
+ rawTx = self.nodes[1].createrawtransaction(inputs, outputs)
+ fundedTx = self.nodes[1].fundrawtransaction(rawTx)
+
+ #now we need to unlock
+ self.nodes[1].walletpassphrase("test", 100)
+ signedTx = self.nodes[1].signrawtransaction(fundedTx['hex'])
+ txId = self.nodes[1].sendrawtransaction(signedTx['hex'])
+ self.sync_all()
+ self.nodes[1].generate(1)
+ self.sync_all()
+
+ # make sure funds are received at node1
+ assert_equal(oldBalance+Decimal('51.10000000'), self.nodes[0].getbalance())
+
+
+
+ ###############################################
+ # multiple (~19) inputs tx test | Compare fee #
+ ###############################################
+
+ #empty node1, send some small coins from node0 to node1
+ 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.sync_all()
+ self.nodes[0].generate(1)
+ self.sync_all()
+
+ #fund a tx with ~20 small inputs
+ inputs = []
+ outputs = {self.nodes[0].getnewaddress():0.15,self.nodes[0].getnewaddress():0.04}
+ rawTx = self.nodes[1].createrawtransaction(inputs, outputs)
+ fundedTx = self.nodes[1].fundrawtransaction(rawTx)
+
+ #create same transaction over sendtoaddress
+ txId = self.nodes[1].sendmany("", outputs);
+ signedFee = self.nodes[1].getrawmempool(True)[txId]['fee']
+
+ #compare fee
+ feeDelta = Decimal(fundedTx['fee']) - Decimal(signedFee);
+ assert(feeDelta >= 0 and feeDelta <= feeTolerance*19) #~19 inputs
+
+
+ #############################################
+ # multiple (~19) inputs tx test | sign/send #
+ #############################################
+
+ #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.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.sync_all()
+ self.nodes[0].generate(1)
+ self.sync_all()
+
+ #fund a tx with ~20 small inputs
+ oldBalance = self.nodes[0].getbalance()
+
+ inputs = []
+ outputs = {self.nodes[0].getnewaddress():0.15,self.nodes[0].getnewaddress():0.04}
+ rawTx = self.nodes[1].createrawtransaction(inputs, outputs)
+ fundedTx = self.nodes[1].fundrawtransaction(rawTx)
+ fundedAndSignedTx = self.nodes[1].signrawtransaction(fundedTx['hex'])
+ txId = self.nodes[1].sendrawtransaction(fundedAndSignedTx['hex'])
+ self.sync_all()
+ self.nodes[0].generate(1)
+ self.sync_all()
+ assert_equal(oldBalance+Decimal('50.19000000'), self.nodes[0].getbalance()) #0.19+block reward
+
+
+if __name__ == '__main__':
+ RawTransactionsTest().main()
diff --git a/qa/rpc-tests/getblocktemplate_longpoll.py b/qa/rpc-tests/getblocktemplate_longpoll.py
index 64fe49b835..aab4562422 100755
--- a/qa/rpc-tests/getblocktemplate_longpoll.py
+++ b/qa/rpc-tests/getblocktemplate_longpoll.py
@@ -3,9 +3,8 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-from test_framework import BitcoinTestFramework
-from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
-from util import *
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
def check_array_result(object_array, to_match, expected):
diff --git a/qa/rpc-tests/getblocktemplate_proposals.py b/qa/rpc-tests/getblocktemplate_proposals.py
index a63f456d6b..aca0cd7495 100755
--- a/qa/rpc-tests/getblocktemplate_proposals.py
+++ b/qa/rpc-tests/getblocktemplate_proposals.py
@@ -3,9 +3,8 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-from test_framework import BitcoinTestFramework
-from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
-from util import *
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
from binascii import a2b_hex, b2a_hex
from hashlib import sha256
diff --git a/qa/rpc-tests/getchaintips.py b/qa/rpc-tests/getchaintips.py
index 83a9537285..6a2bcb2969 100755
--- a/qa/rpc-tests/getchaintips.py
+++ b/qa/rpc-tests/getchaintips.py
@@ -7,8 +7,8 @@
# on chains of different lengths, and join the network together again.
# This gives us two tips, verify that it works.
-from test_framework import BitcoinTestFramework
-from util import assert_equal
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import assert_equal
class GetChainTipsTest (BitcoinTestFramework):
diff --git a/qa/rpc-tests/httpbasics.py b/qa/rpc-tests/httpbasics.py
index 24533741e5..8ccb821286 100755
--- a/qa/rpc-tests/httpbasics.py
+++ b/qa/rpc-tests/httpbasics.py
@@ -4,11 +4,11 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
#
-# Test REST interface
+# Test rpc http basics
#
-from test_framework import BitcoinTestFramework
-from util import *
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
import base64
try:
@@ -20,83 +20,83 @@ try:
except ImportError:
import urlparse
-class HTTPBasicsTest (BitcoinTestFramework):
+class HTTPBasicsTest (BitcoinTestFramework):
def setup_nodes(self):
return start_nodes(4, self.options.tmpdir, extra_args=[['-rpckeepalive=1'], ['-rpckeepalive=0'], [], []])
- def run_test(self):
-
+ def run_test(self):
+
#################################################
# lowlevel check for http persistent connection #
#################################################
url = urlparse.urlparse(self.nodes[0].url)
authpair = url.username + ':' + url.password
headers = {"Authorization": "Basic " + base64.b64encode(authpair)}
-
+
conn = httplib.HTTPConnection(url.hostname, url.port)
conn.connect()
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
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();
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()
-
+
#same should be if we add keep-alive because this should be the std. behaviour
headers = {"Authorization": "Basic " + base64.b64encode(authpair), "Connection": "keep-alive"}
-
+
conn = httplib.HTTPConnection(url.hostname, url.port)
conn.connect()
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
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();
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()
-
+
#now do the same with "Connection: close"
headers = {"Authorization": "Basic " + base64.b64encode(authpair), "Connection":"close"}
-
+
conn = httplib.HTTPConnection(url.hostname, url.port)
conn.connect()
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
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
-
+ assert_equal(conn.sock!=None, False) #now the connection must be closed after the response
+
#node1 (2nd node) is running with disabled keep-alive option
urlNode1 = urlparse.urlparse(self.nodes[1].url)
authpair = urlNode1.username + ':' + urlNode1.password
headers = {"Authorization": "Basic " + base64.b64encode(authpair)}
-
+
conn = httplib.HTTPConnection(urlNode1.hostname, urlNode1.port)
conn.connect()
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
out1 = conn.getresponse().read();
assert_equal('"error":null' in out1, True)
assert_equal(conn.sock!=None, False) #connection must be closed because keep-alive was set to false
-
+
#node2 (third node) is running with standard keep-alive parameters which means keep-alive is off
urlNode2 = urlparse.urlparse(self.nodes[2].url)
authpair = urlNode2.username + ':' + urlNode2.password
headers = {"Authorization": "Basic " + base64.b64encode(authpair)}
-
+
conn = httplib.HTTPConnection(urlNode2.hostname, urlNode2.port)
conn.connect()
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
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
-
+
if __name__ == '__main__':
HTTPBasicsTest ().main ()
diff --git a/qa/rpc-tests/invalidateblock.py b/qa/rpc-tests/invalidateblock.py
index fd8a8e5785..2b9c8154e0 100755
--- a/qa/rpc-tests/invalidateblock.py
+++ b/qa/rpc-tests/invalidateblock.py
@@ -7,9 +7,8 @@
# Test InvalidateBlock code
#
-from test_framework import BitcoinTestFramework
-from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
-from util import *
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
class InvalidateTest(BitcoinTestFramework):
diff --git a/qa/rpc-tests/invalidblockrequest.py b/qa/rpc-tests/invalidblockrequest.py
index 8b685ed9b2..64b8e26395 100755
--- a/qa/rpc-tests/invalidblockrequest.py
+++ b/qa/rpc-tests/invalidblockrequest.py
@@ -4,11 +4,11 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
#
-from test_framework import ComparisonTestFramework
-from util import *
-from comptool import TestManager, TestInstance
-from mininode import *
-from blocktools import *
+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.blocktools import *
import logging
import copy
import time
diff --git a/qa/rpc-tests/keypool.py b/qa/rpc-tests/keypool.py
index 3840ea39d3..aee29a596a 100755
--- a/qa/rpc-tests/keypool.py
+++ b/qa/rpc-tests/keypool.py
@@ -8,7 +8,6 @@
# Add python-bitcoinrpc to module search path:
import os
import sys
-sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), "python-bitcoinrpc"))
import json
import shutil
@@ -16,8 +15,7 @@ import subprocess
import tempfile
import traceback
-from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
-from util import *
+from test_framework.util import *
def check_array_result(object_array, to_match, expected):
diff --git a/qa/rpc-tests/listtransactions.py b/qa/rpc-tests/listtransactions.py
index 11e3635c04..eeae2d2fa2 100755
--- a/qa/rpc-tests/listtransactions.py
+++ b/qa/rpc-tests/listtransactions.py
@@ -5,9 +5,8 @@
# Exercise the listtransactions API
-from test_framework import BitcoinTestFramework
-from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
-from util import *
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
def check_array_result(object_array, to_match, expected):
diff --git a/qa/rpc-tests/maxblocksinflight.py b/qa/rpc-tests/maxblocksinflight.py
index 87c80cd97e..a601147ce8 100755
--- a/qa/rpc-tests/maxblocksinflight.py
+++ b/qa/rpc-tests/maxblocksinflight.py
@@ -4,9 +4,9 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
#
-from mininode import *
-from test_framework import BitcoinTestFramework
-from util import *
+from test_framework.mininode import *
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
import logging
'''
diff --git a/qa/rpc-tests/mempool_coinbase_spends.py b/qa/rpc-tests/mempool_coinbase_spends.py
index 853d031de4..c64a15b9f5 100755
--- a/qa/rpc-tests/mempool_coinbase_spends.py
+++ b/qa/rpc-tests/mempool_coinbase_spends.py
@@ -8,9 +8,8 @@
# that spend (directly or indirectly) coinbase transactions.
#
-from test_framework import BitcoinTestFramework
-from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
-from util import *
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
import os
import shutil
diff --git a/qa/rpc-tests/mempool_resurrect_test.py b/qa/rpc-tests/mempool_resurrect_test.py
index 6f7f577e36..19c74bb751 100755
--- a/qa/rpc-tests/mempool_resurrect_test.py
+++ b/qa/rpc-tests/mempool_resurrect_test.py
@@ -8,9 +8,8 @@
# the blockchain is re-organized.
#
-from test_framework import BitcoinTestFramework
-from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
-from util import *
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
import os
import shutil
@@ -34,7 +33,6 @@ class MempoolCoinbaseTest(BitcoinTestFramework):
def run_test(self):
node0_address = self.nodes[0].getnewaddress()
-
# Spend block 1/2/3's coinbase transactions
# Mine a block.
# Create three more transactions, spending the spends
diff --git a/qa/rpc-tests/mempool_spendcoinbase.py b/qa/rpc-tests/mempool_spendcoinbase.py
index ab5817c869..fc17c50692 100755
--- a/qa/rpc-tests/mempool_spendcoinbase.py
+++ b/qa/rpc-tests/mempool_spendcoinbase.py
@@ -13,9 +13,8 @@
# but less mature coinbase spends are NOT.
#
-from test_framework import BitcoinTestFramework
-from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
-from util import *
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
import os
import shutil
diff --git a/qa/rpc-tests/merkle_blocks.py b/qa/rpc-tests/merkle_blocks.py
index a143d21a21..72a80ce6ca 100755
--- a/qa/rpc-tests/merkle_blocks.py
+++ b/qa/rpc-tests/merkle_blocks.py
@@ -7,9 +7,8 @@
# Test merkleblock fetch/validation
#
-from test_framework import BitcoinTestFramework
-from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
-from util import *
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
import os
import shutil
diff --git a/qa/rpc-tests/nodehandling.py b/qa/rpc-tests/nodehandling.py
new file mode 100755
index 0000000000..9a77bd97e8
--- /dev/null
+++ b/qa/rpc-tests/nodehandling.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python2
+# Copyright (c) 2014 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#
+# Test node handling
+#
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
+import base64
+
+try:
+ import http.client as httplib
+except ImportError:
+ import httplib
+try:
+ import urllib.parse as urlparse
+except ImportError:
+ import urlparse
+
+class NodeHandlingTest (BitcoinTestFramework):
+ def run_test(self):
+ ###########################
+ # setban/listbanned tests #
+ ###########################
+ assert_equal(len(self.nodes[2].getpeerinfo()), 4) #we should have 4 nodes at this point
+ self.nodes[2].setban("127.0.0.1", "add")
+ time.sleep(3) #wait till the nodes are disconected
+ assert_equal(len(self.nodes[2].getpeerinfo()), 0) #all nodes must be disconnected at this point
+ assert_equal(len(self.nodes[2].listbanned()), 1)
+ self.nodes[2].clearbanned()
+ assert_equal(len(self.nodes[2].listbanned()), 0)
+ self.nodes[2].setban("127.0.0.0/24", "add")
+ assert_equal(len(self.nodes[2].listbanned()), 1)
+ try:
+ self.nodes[2].setban("127.0.0.1", "add") #throws exception because 127.0.0.1 is within range 127.0.0.0/24
+ except:
+ pass
+ assert_equal(len(self.nodes[2].listbanned()), 1) #still only one banned ip because 127.0.0.1 is within the range of 127.0.0.0/24
+ try:
+ self.nodes[2].setban("127.0.0.1", "remove")
+ except:
+ pass
+ assert_equal(len(self.nodes[2].listbanned()), 1)
+ self.nodes[2].setban("127.0.0.0/24", "remove")
+ assert_equal(len(self.nodes[2].listbanned()), 0)
+ self.nodes[2].clearbanned()
+ assert_equal(len(self.nodes[2].listbanned()), 0)
+
+ ###########################
+ # RPC disconnectnode test #
+ ###########################
+ url = urlparse.urlparse(self.nodes[1].url)
+ self.nodes[0].disconnectnode(url.hostname+":"+str(p2p_port(1)))
+ time.sleep(2) #disconnecting a node needs a little bit of time
+ for node in self.nodes[0].getpeerinfo():
+ assert(node['addr'] != url.hostname+":"+str(p2p_port(1)))
+
+ connect_nodes_bi(self.nodes,0,1) #reconnect the node
+ found = False
+ for node in self.nodes[0].getpeerinfo():
+ if node['addr'] == url.hostname+":"+str(p2p_port(1)):
+ found = True
+ assert(found)
+
+if __name__ == '__main__':
+ NodeHandlingTest ().main ()
diff --git a/qa/rpc-tests/p2p-acceptblock.py b/qa/rpc-tests/p2p-acceptblock.py
new file mode 100755
index 0000000000..fcdd1e1b99
--- /dev/null
+++ b/qa/rpc-tests/p2p-acceptblock.py
@@ -0,0 +1,226 @@
+#!/usr/bin/env python2
+#
+# Distributed under the MIT/X11 software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#
+
+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
+
+'''
+AcceptBlockTest -- test processing of unrequested blocks.
+
+Since behavior differs when receiving unrequested blocks from whitelisted peers
+versus non-whitelisted peers, this tests the behavior of both (effectively two
+separate tests running in parallel).
+
+Setup: two nodes, node0 and node1, not connected to each other. Node0 does not
+whitelist localhost, but node1 does. They will each be on their own chain for
+this test.
+
+We have one NodeConn connection to each, test_node and white_node respectively.
+
+The test:
+1. Generate one block on each node, to leave IBD.
+
+2. Mine a new block on each tip, and deliver to each node from node's peer.
+ The tip should advance.
+
+3. Mine a block that forks the previous block, and deliver to each node from
+ corresponding peer.
+ Node0 should not process this block (just accept the header), because it is
+ unrequested and doesn't have more work than the tip.
+ Node1 should process because this is coming from a whitelisted peer.
+
+4. Send another block that builds on the forking block.
+ Node0 should process this block but be stuck on the shorter chain, because
+ it's missing an intermediate block.
+ Node1 should reorg to this longer chain.
+
+5. Send a duplicate of the block in #3 to Node0.
+ Node0 should not process the block because it is unrequested, and stay on
+ the shorter chain.
+
+6. Send Node0 an inv for the height 3 block produced in #4 above.
+ Node0 should figure out that Node0 has the missing height 2 block and send a
+ getdata.
+
+7. Send Node0 the missing block again.
+ Node0 should process and the tip should advance.
+'''
+
+# TestNode: bare-bones "peer". Used mostly as a conduit for a test to sending
+# p2p messages to a node, generating the messages in the main testing logic.
+class TestNode(NodeConnCB):
+ def __init__(self):
+ NodeConnCB.__init__(self)
+ self.create_callback_map()
+ self.connection = None
+
+ def add_connection(self, conn):
+ self.connection = conn
+
+ # Track the last getdata message we receive (used in the test)
+ def on_getdata(self, conn, message):
+ self.last_getdata = message
+
+ # Spin until verack message is received from the node.
+ # We use this to signal that our test can begin. This
+ # is called from the testing thread, so it needs to acquire
+ # the global lock.
+ def wait_for_verack(self):
+ while True:
+ with mininode_lock:
+ if self.verack_received:
+ return
+ time.sleep(0.05)
+
+ # Wrapper for the NodeConn's send_message function
+ def send_message(self, message):
+ self.connection.send_message(message)
+
+class AcceptBlockTest(BitcoinTestFramework):
+ def add_options(self, parser):
+ parser.add_option("--testbinary", dest="testbinary",
+ default=os.getenv("BITCOIND", "bitcoind"),
+ help="bitcoind binary to test")
+
+ def setup_chain(self):
+ initialize_chain_clean(self.options.tmpdir, 2)
+
+ def setup_network(self):
+ # Node0 will be used to test behavior of processing unrequested blocks
+ # from peers which are not whitelisted, while Node1 will be used for
+ # the whitelisted case.
+ self.nodes = []
+ self.nodes.append(start_node(0, self.options.tmpdir, ["-debug"],
+ binary=self.options.testbinary))
+ self.nodes.append(start_node(1, self.options.tmpdir,
+ ["-debug", "-whitelist=127.0.0.1"],
+ binary=self.options.testbinary))
+
+ def run_test(self):
+ # Setup the p2p connections and start up the network thread.
+ test_node = TestNode() # connects to node0 (not whitelisted)
+ white_node = TestNode() # connects to node1 (whitelisted)
+
+ connections = []
+ connections.append(NodeConn('127.0.0.1', p2p_port(0), self.nodes[0], test_node))
+ connections.append(NodeConn('127.0.0.1', p2p_port(1), self.nodes[1], white_node))
+ test_node.add_connection(connections[0])
+ white_node.add_connection(connections[1])
+
+ NetworkThread().start() # Start up network handling in another thread
+
+ # Test logic begins here
+ test_node.wait_for_verack()
+ white_node.wait_for_verack()
+
+ # 1. Have both nodes mine a block (leave IBD)
+ [ n.generate(1) for n in self.nodes ]
+ tips = [ int ("0x" + n.getbestblockhash() + "L", 0) for n in self.nodes ]
+
+ # 2. Send one block that builds on each tip.
+ # This should be accepted.
+ blocks_h2 = [] # the height 2 blocks on each node's chain
+ for i in xrange(2):
+ blocks_h2.append(create_block(tips[i], create_coinbase(), time.time()+1))
+ blocks_h2[i].solve()
+ test_node.send_message(msg_block(blocks_h2[0]))
+ white_node.send_message(msg_block(blocks_h2[1]))
+
+ time.sleep(1)
+ assert_equal(self.nodes[0].getblockcount(), 2)
+ assert_equal(self.nodes[1].getblockcount(), 2)
+ print "First height 2 block accepted by both nodes"
+
+ # 3. Send another block that builds on the original tip.
+ blocks_h2f = [] # Blocks at height 2 that fork off the main chain
+ for i in xrange(2):
+ blocks_h2f.append(create_block(tips[i], create_coinbase(), blocks_h2[i].nTime+1))
+ blocks_h2f[i].solve()
+ test_node.send_message(msg_block(blocks_h2f[0]))
+ white_node.send_message(msg_block(blocks_h2f[1]))
+
+ time.sleep(1) # Give time to process the block
+ for x in self.nodes[0].getchaintips():
+ if x['hash'] == blocks_h2f[0].hash:
+ assert_equal(x['status'], "headers-only")
+
+ for x in self.nodes[1].getchaintips():
+ if x['hash'] == blocks_h2f[1].hash:
+ assert_equal(x['status'], "valid-headers")
+
+ print "Second height 2 block accepted only from whitelisted peer"
+
+ # 4. Now send another block that builds on the forking chain.
+ blocks_h3 = []
+ for i in xrange(2):
+ blocks_h3.append(create_block(blocks_h2f[i].sha256, create_coinbase(), blocks_h2f[i].nTime+1))
+ blocks_h3[i].solve()
+ test_node.send_message(msg_block(blocks_h3[0]))
+ white_node.send_message(msg_block(blocks_h3[1]))
+
+ time.sleep(1)
+ # Since the earlier block was not processed by node0, the new block
+ # can't be fully validated.
+ for x in self.nodes[0].getchaintips():
+ if x['hash'] == blocks_h3[0].hash:
+ assert_equal(x['status'], "headers-only")
+
+ # But this block should be accepted by node0 since it has more work.
+ try:
+ self.nodes[0].getblock(blocks_h3[0].hash)
+ print "Unrequested more-work block accepted from non-whitelisted peer"
+ except:
+ raise AssertionError("Unrequested more work block was not processed")
+
+ # Node1 should have accepted and reorged.
+ assert_equal(self.nodes[1].getblockcount(), 3)
+ print "Successfully reorged to length 3 chain from whitelisted peer"
+
+ # 5. Test handling of unrequested block on the node that didn't process
+ # Should still not be processed (even though it has a child that has more
+ # work).
+ test_node.send_message(msg_block(blocks_h2f[0]))
+
+ # Here, if the sleep is too short, the test could falsely succeed (if the
+ # node hasn't processed the block by the time the sleep returns, and then
+ # the node processes it and incorrectly advances the tip).
+ # But this would be caught later on, when we verify that an inv triggers
+ # a getdata request for this block.
+ time.sleep(1)
+ assert_equal(self.nodes[0].getblockcount(), 2)
+ print "Unrequested block that would complete more-work chain was ignored"
+
+ # 6. Try to get node to request the missing block.
+ # Poke the node with an inv for block at height 3 and see if that
+ # triggers a getdata on block 2 (it should if block 2 is missing).
+ with mininode_lock:
+ # Clear state so we can check the getdata request
+ test_node.last_getdata = None
+ test_node.send_message(msg_inv([CInv(2, blocks_h3[0].sha256)]))
+
+ time.sleep(1)
+ with mininode_lock:
+ getdata = test_node.last_getdata
+
+ # Check that the getdata is for the right block
+ assert_equal(len(getdata.inv), 1)
+ assert_equal(getdata.inv[0].hash, blocks_h2f[0].sha256)
+ print "Inv at tip triggered getdata for unprocessed block"
+
+ # 7. Send the missing block for the third time (now it is requested)
+ test_node.send_message(msg_block(blocks_h2f[0]))
+
+ time.sleep(1)
+ assert_equal(self.nodes[0].getblockcount(), 3)
+ print "Successfully reorged to length 3 chain from non-whitelisted peer"
+
+ [ c.disconnect_node() for c in connections ]
+
+if __name__ == '__main__':
+ AcceptBlockTest().main()
diff --git a/qa/rpc-tests/proxy_test.py b/qa/rpc-tests/proxy_test.py
index d6d9e6725b..3623c16162 100755
--- a/qa/rpc-tests/proxy_test.py
+++ b/qa/rpc-tests/proxy_test.py
@@ -7,9 +7,9 @@ import traceback, sys
from binascii import hexlify
import time, os
-from socks5 import Socks5Configuration, Socks5Command, Socks5Server, AddressType
-from test_framework import BitcoinTestFramework
-from util import *
+from test_framework.socks5 import Socks5Configuration, Socks5Command, Socks5Server, AddressType
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
'''
Test plan:
- Start bitcoind's with different proxy configurations
@@ -68,10 +68,10 @@ class ProxyTest(BitcoinTestFramework):
['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf1.addr),'-proxyrandomize=1'],
['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf1.addr),'-onion=%s:%i' % (self.conf2.addr),'-proxyrandomize=0'],
['-listen', '-debug=net', '-debug=proxy', '-proxy=%s:%i' % (self.conf2.addr),'-proxyrandomize=1'],
- ['-listen', '-debug=net', '-debug=proxy', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0']
+ ['-listen', '-debug=net', '-debug=proxy', '-proxy=[%s]:%i' % (self.conf3.addr),'-proxyrandomize=0', '-noonion']
])
- def node_test(self, node, proxies, auth):
+ def node_test(self, node, proxies, auth, test_onion=True):
rv = []
# Test: outgoing IPv4 connection through node
node.addnode("15.61.23.23:1234", "onetry")
@@ -99,17 +99,18 @@ class ProxyTest(BitcoinTestFramework):
assert_equal(cmd.password, None)
rv.append(cmd)
- # Test: outgoing onion connection through node
- node.addnode("bitcoinostk4e4re.onion:8333", "onetry")
- cmd = proxies[2].queue.get()
- assert(isinstance(cmd, Socks5Command))
- assert_equal(cmd.atyp, AddressType.DOMAINNAME)
- assert_equal(cmd.addr, "bitcoinostk4e4re.onion")
- assert_equal(cmd.port, 8333)
- if not auth:
- assert_equal(cmd.username, None)
- assert_equal(cmd.password, None)
- rv.append(cmd)
+ if test_onion:
+ # Test: outgoing onion connection through node
+ node.addnode("bitcoinostk4e4re.onion:8333", "onetry")
+ cmd = proxies[2].queue.get()
+ assert(isinstance(cmd, Socks5Command))
+ assert_equal(cmd.atyp, AddressType.DOMAINNAME)
+ assert_equal(cmd.addr, "bitcoinostk4e4re.onion")
+ assert_equal(cmd.port, 8333)
+ if not auth:
+ assert_equal(cmd.username, None)
+ assert_equal(cmd.password, None)
+ rv.append(cmd)
# Test: outgoing DNS name connection through node
node.addnode("node.noumenon:8333", "onetry")
@@ -139,8 +140,41 @@ class ProxyTest(BitcoinTestFramework):
assert_equal(len(credentials), 4)
# proxy on IPv6 localhost
- self.node_test(self.nodes[3], [self.serv3, self.serv3, self.serv3, self.serv3], False)
+ self.node_test(self.nodes[3], [self.serv3, self.serv3, self.serv3, self.serv3], False, False)
+
+ def networks_dict(d):
+ r = {}
+ for x in d['networks']:
+ r[x['name']] = x
+ return r
+
+ # test RPC getnetworkinfo
+ n0 = networks_dict(self.nodes[0].getnetworkinfo())
+ for net in ['ipv4','ipv6','onion']:
+ assert_equal(n0[net]['proxy'], '%s:%i' % (self.conf1.addr))
+ assert_equal(n0[net]['proxy_randomize_credentials'], True)
+ assert_equal(n0['onion']['reachable'], True)
+
+ n1 = networks_dict(self.nodes[1].getnetworkinfo())
+ for net in ['ipv4','ipv6']:
+ assert_equal(n1[net]['proxy'], '%s:%i' % (self.conf1.addr))
+ assert_equal(n1[net]['proxy_randomize_credentials'], False)
+ assert_equal(n1['onion']['proxy'], '%s:%i' % (self.conf2.addr))
+ assert_equal(n1['onion']['proxy_randomize_credentials'], False)
+ assert_equal(n1['onion']['reachable'], True)
+ n2 = networks_dict(self.nodes[2].getnetworkinfo())
+ for net in ['ipv4','ipv6','onion']:
+ assert_equal(n2[net]['proxy'], '%s:%i' % (self.conf2.addr))
+ assert_equal(n2[net]['proxy_randomize_credentials'], True)
+ assert_equal(n2['onion']['reachable'], True)
+
+ n3 = networks_dict(self.nodes[3].getnetworkinfo())
+ for net in ['ipv4','ipv6']:
+ assert_equal(n3[net]['proxy'], '[%s]:%i' % (self.conf3.addr))
+ assert_equal(n3[net]['proxy_randomize_credentials'], False)
+ assert_equal(n3['onion']['reachable'], False)
+
if __name__ == '__main__':
ProxyTest().main()
diff --git a/qa/rpc-tests/pruning.py b/qa/rpc-tests/pruning.py
index f26cbee1e2..2824c51ce7 100755
--- a/qa/rpc-tests/pruning.py
+++ b/qa/rpc-tests/pruning.py
@@ -7,12 +7,12 @@
# Test pruning code
# ********
# WARNING:
-# This test uses 4GB of disk space and takes in excess of 30 mins to run
+# This test uses 4GB of disk space.
+# This test takes 30 mins or more (up to 2 hours)
# ********
-from test_framework import BitcoinTestFramework
-from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
-from util import *
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
import os.path
def calc_usage(blockdir):
@@ -51,11 +51,11 @@ class PruneTest(BitcoinTestFramework):
self.is_network_split = False
# Create nodes 0 and 1 to mine
- self.nodes.append(start_node(0, self.options.tmpdir, ["-debug","-maxreceivebuffer=20000","-blockmaxsize=999000", "-checkblocks=5"], timewait=300))
- self.nodes.append(start_node(1, self.options.tmpdir, ["-debug","-maxreceivebuffer=20000","-blockmaxsize=999000", "-checkblocks=5"], timewait=300))
+ self.nodes.append(start_node(0, self.options.tmpdir, ["-debug","-maxreceivebuffer=20000","-blockmaxsize=999000", "-checkblocks=5"], timewait=900))
+ self.nodes.append(start_node(1, self.options.tmpdir, ["-debug","-maxreceivebuffer=20000","-blockmaxsize=999000", "-checkblocks=5"], timewait=900))
# Create node 2 to test pruning
- self.nodes.append(start_node(2, self.options.tmpdir, ["-debug","-maxreceivebuffer=20000","-prune=550"], timewait=300))
+ self.nodes.append(start_node(2, self.options.tmpdir, ["-debug","-maxreceivebuffer=20000","-prune=550"], timewait=900))
self.prunedir = self.options.tmpdir+"/node2/regtest/blocks/"
self.address[0] = self.nodes[0].getnewaddress()
@@ -108,7 +108,7 @@ class PruneTest(BitcoinTestFramework):
# Node 2 stays connected, so it hears about the stale blocks and then reorg's when node0 reconnects
# Stopping node 0 also clears its mempool, so it doesn't have node1's transactions to accidentally mine
stop_node(self.nodes[0],0)
- self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug","-maxreceivebuffer=20000","-blockmaxsize=999000", "-checkblocks=5"], timewait=300)
+ self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug","-maxreceivebuffer=20000","-blockmaxsize=999000", "-checkblocks=5"], timewait=900)
# Mine 24 blocks in node 1
self.utxo = self.nodes[1].listunspent()
for i in xrange(24):
@@ -135,7 +135,7 @@ class PruneTest(BitcoinTestFramework):
# Reboot node 1 to clear its mempool (hopefully make the invalidate faster)
# Lower the block max size so we don't keep mining all our big mempool transactions (from disconnected blocks)
stop_node(self.nodes[1],1)
- self.nodes[1]=start_node(1, self.options.tmpdir, ["-debug","-maxreceivebuffer=20000","-blockmaxsize=5000", "-checkblocks=5", "-disablesafemode"], timewait=300)
+ self.nodes[1]=start_node(1, self.options.tmpdir, ["-debug","-maxreceivebuffer=20000","-blockmaxsize=5000", "-checkblocks=5", "-disablesafemode"], timewait=900)
height = self.nodes[1].getblockcount()
print "Current block height:", height
@@ -158,7 +158,7 @@ class PruneTest(BitcoinTestFramework):
# Reboot node1 to clear those giant tx's from mempool
stop_node(self.nodes[1],1)
- self.nodes[1]=start_node(1, self.options.tmpdir, ["-debug","-maxreceivebuffer=20000","-blockmaxsize=5000", "-checkblocks=5", "-disablesafemode"], timewait=300)
+ self.nodes[1]=start_node(1, self.options.tmpdir, ["-debug","-maxreceivebuffer=20000","-blockmaxsize=5000", "-checkblocks=5", "-disablesafemode"], timewait=900)
print "Generating new longer chain of 300 more blocks"
self.nodes[1].generate(300)
@@ -223,7 +223,7 @@ class PruneTest(BitcoinTestFramework):
waitstart = time.time()
while self.nodes[2].getblockcount() < goalbestheight:
time.sleep(0.1)
- if time.time() - waitstart > 300:
+ if time.time() - waitstart > 900:
raise AssertionError("Node 2 didn't reorg to proper height")
assert(self.nodes[2].getbestblockhash() == goalbesthash)
# Verify we can now have the data for a block previously pruned
@@ -256,7 +256,7 @@ class PruneTest(BitcoinTestFramework):
def run_test(self):
- print "Warning! This test requires 4GB of disk space and takes over 30 mins"
+ print "Warning! This test requires 4GB of disk space and takes over 30 mins (up to 2 hours)"
print "Mining a big blockchain of 995 blocks"
self.create_big_chain()
# Chain diagram key:
diff --git a/qa/rpc-tests/python-bitcoinrpc/bitcoinrpc/.gitignore b/qa/rpc-tests/python-bitcoinrpc/bitcoinrpc/.gitignore
deleted file mode 100644
index 0d20b6487c..0000000000
--- a/qa/rpc-tests/python-bitcoinrpc/bitcoinrpc/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*.pyc
diff --git a/qa/rpc-tests/python-bitcoinrpc/setup.py b/qa/rpc-tests/python-bitcoinrpc/setup.py
deleted file mode 100644
index 43cdb1c038..0000000000
--- a/qa/rpc-tests/python-bitcoinrpc/setup.py
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env python2
-
-from distutils.core import setup
-
-setup(name='python-bitcoinrpc',
- version='0.1',
- description='Enhanced version of python-jsonrpc for use with Bitcoin',
- long_description=open('README').read(),
- author='Jeff Garzik',
- author_email='<jgarzik@exmulti.com>',
- maintainer='Jeff Garzik',
- maintainer_email='<jgarzik@exmulti.com>',
- url='http://www.github.com/jgarzik/python-bitcoinrpc',
- packages=['bitcoinrpc'],
- classifiers=['License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)', 'Operating System :: OS Independent'])
diff --git a/qa/rpc-tests/rawtransactions.py b/qa/rpc-tests/rawtransactions.py
index 3d80c97d74..1378514c84 100755
--- a/qa/rpc-tests/rawtransactions.py
+++ b/qa/rpc-tests/rawtransactions.py
@@ -8,8 +8,8 @@
# that spend (directly or indirectly) coinbase transactions.
#
-from test_framework import BitcoinTestFramework
-from util import *
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
from pprint import pprint
from time import sleep
diff --git a/qa/rpc-tests/receivedby.py b/qa/rpc-tests/receivedby.py
index 1a681e1aae..16d6bd4cf1 100755
--- a/qa/rpc-tests/receivedby.py
+++ b/qa/rpc-tests/receivedby.py
@@ -5,9 +5,8 @@
# Exercise the listreceivedbyaddress API
-from test_framework import BitcoinTestFramework
-from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
-from util import *
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
def get_sub_array_from_array(object_array, to_match):
diff --git a/qa/rpc-tests/reindex.py b/qa/rpc-tests/reindex.py
index fe767586bb..f2e3f248ea 100755
--- a/qa/rpc-tests/reindex.py
+++ b/qa/rpc-tests/reindex.py
@@ -6,9 +6,8 @@
#
# Test -reindex with CheckBlockIndex
#
-from test_framework import BitcoinTestFramework
-from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
-from util import *
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
import os.path
class ReindexTest(BitcoinTestFramework):
diff --git a/qa/rpc-tests/rest.py b/qa/rpc-tests/rest.py
index 9f0d049fe9..6c51b2fcd9 100755
--- a/qa/rpc-tests/rest.py
+++ b/qa/rpc-tests/rest.py
@@ -7,8 +7,9 @@
# Test REST interface
#
-from test_framework import BitcoinTestFramework
-from util import *
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
from struct import *
import binascii
import json
@@ -54,78 +55,78 @@ class RESTTest (BitcoinTestFramework):
connect_nodes_bi(self.nodes,0,2)
self.is_network_split=False
self.sync_all()
-
+
def run_test(self):
url = urlparse.urlparse(self.nodes[0].url)
print "Mining blocks..."
-
+
self.nodes[0].generate(1)
self.sync_all()
self.nodes[2].generate(100)
self.sync_all()
-
+
assert_equal(self.nodes[0].getbalance(), 50)
-
+
txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
self.sync_all()
self.nodes[2].generate(1)
self.sync_all()
bb_hash = self.nodes[0].getbestblockhash()
-
+
assert_equal(self.nodes[1].getbalance(), Decimal("0.1")) #balance now should be 0.1 on node 1
-
+
# load the latest 0.1 tx over the REST API
json_string = http_get_call(url.hostname, url.port, '/rest/tx/'+txid+self.FORMAT_SEPARATOR+"json")
json_obj = json.loads(json_string)
vintx = json_obj['vin'][0]['txid'] # get the vin to later check for utxo (should be spent by then)
- # get n of 0.1 outpoint
+ # get n of 0.1 outpoint
n = 0
for vout in json_obj['vout']:
if vout['value'] == 0.1:
n = vout['n']
-
-
+
+
######################################
# GETUTXOS: query a unspent outpoint #
######################################
- json_request = '{"checkmempool":true,"outpoints":[{"txid":"'+txid+'","n":'+str(n)+'}]}'
- json_string = http_get_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'json', json_request)
+ json_request = '/checkmempool/'+txid+'-'+str(n)
+ json_string = http_get_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json')
json_obj = json.loads(json_string)
-
+
#check chainTip response
assert_equal(json_obj['chaintipHash'], bb_hash)
-
+
#make sure there is one utxo
assert_equal(len(json_obj['utxos']), 1)
assert_equal(json_obj['utxos'][0]['value'], 0.1)
-
-
+
+
################################################
# GETUTXOS: now query a already spent outpoint #
################################################
- json_request = '{"checkmempool":true,"outpoints":[{"txid":"'+vintx+'","n":0}]}'
- json_string = http_get_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'json', json_request)
+ json_request = '/checkmempool/'+vintx+'-0'
+ json_string = http_get_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json')
json_obj = json.loads(json_string)
-
+
#check chainTip response
assert_equal(json_obj['chaintipHash'], bb_hash)
#make sure there is no utox in the response because this oupoint has been spent
assert_equal(len(json_obj['utxos']), 0)
-
+
#check bitmap
assert_equal(json_obj['bitmap'], "0")
-
-
+
+
##################################################
# GETUTXOS: now check both with the same request #
##################################################
- json_request = '{"checkmempool":true,"outpoints":[{"txid":"'+txid+'","n":'+str(n)+'},{"txid":"'+vintx+'","n":0}]}'
- json_string = http_get_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'json', json_request)
+ json_request = '/checkmempool/'+txid+'-'+str(n)+'/'+vintx+'-0'
+ json_string = http_get_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json')
json_obj = json.loads(json_string)
assert_equal(len(json_obj['utxos']), 1)
assert_equal(json_obj['bitmap'], "10")
-
+
#test binary response
bb_hash = self.nodes[0].getbestblockhash()
@@ -134,19 +135,18 @@ class RESTTest (BitcoinTestFramework):
binaryRequest += pack("i", n);
binaryRequest += binascii.unhexlify(vintx);
binaryRequest += pack("i", 0);
-
+
bin_response = http_get_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'bin', binaryRequest)
-
output = StringIO.StringIO()
output.write(bin_response)
output.seek(0)
chainHeight = unpack("i", output.read(4))[0]
hashFromBinResponse = hex(deser_uint256(output))[2:].zfill(65).rstrip("L")
-
+
assert_equal(bb_hash, hashFromBinResponse) #check if getutxo's chaintip during calculation was fine
assert_equal(chainHeight, 102) #chain height must be 102
-
-
+
+
############################
# GETUTXOS: mempool checks #
############################
@@ -156,55 +156,56 @@ class RESTTest (BitcoinTestFramework):
json_string = http_get_call(url.hostname, url.port, '/rest/tx/'+txid+self.FORMAT_SEPARATOR+"json")
json_obj = json.loads(json_string)
vintx = json_obj['vin'][0]['txid'] # get the vin to later check for utxo (should be spent by then)
- # get n of 0.1 outpoint
+ # get n of 0.1 outpoint
n = 0
for vout in json_obj['vout']:
if vout['value'] == 0.1:
n = vout['n']
-
- json_request = '{"checkmempool":false,"outpoints":[{"txid":"'+txid+'","n":'+str(n)+'}]}'
- json_string = http_get_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'json', json_request)
+
+ json_request = '/'+txid+'-'+str(n)
+ json_string = http_get_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json')
json_obj = json.loads(json_string)
assert_equal(len(json_obj['utxos']), 0) #there should be a outpoint because it has just added to the mempool
-
- json_request = '{"checkmempool":true,"outpoints":[{"txid":"'+txid+'","n":'+str(n)+'}]}'
- json_string = http_get_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'json', json_request)
+
+ json_request = '/checkmempool/'+txid+'-'+str(n)
+ json_string = http_get_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json')
json_obj = json.loads(json_string)
assert_equal(len(json_obj['utxos']), 1) #there should be a outpoint because it has just added to the mempool
-
+
#do some invalid requests
json_request = '{"checkmempool'
response = http_get_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'json', json_request, True)
assert_equal(response.status, 500) #must be a 500 because we send a invalid json request
-
+
json_request = '{"checkmempool'
response = http_get_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'bin', json_request, True)
assert_equal(response.status, 500) #must be a 500 because we send a invalid bin request
-
+
+ response = http_get_call(url.hostname, url.port, '/rest/getutxos/checkmempool'+self.FORMAT_SEPARATOR+'bin', '', True)
+ assert_equal(response.status, 500) #must be a 500 because we send a invalid bin request
+
#test limits
- json_request = '{"checkmempool":true,"outpoints":['
- for x in range(0, 200):
- json_request += '{"txid":"'+txid+'","n":'+str(n)+'},'
- json_request = json_request.rstrip(",")
- json_request+="]}";
- response = http_get_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'json', json_request, True)
+ json_request = '/checkmempool/'
+ for x in range(0, 20):
+ json_request += txid+'-'+str(n)+'/'
+ json_request = json_request.rstrip("/")
+ response = http_get_call(url.hostname, url.port, '/rest/getutxos'+json_request+self.FORMAT_SEPARATOR+'json', '', True)
assert_equal(response.status, 500) #must be a 500 because we exceeding the limits
-
- json_request = '{"checkmempool":true,"outpoints":['
- for x in range(0, 90):
- json_request += '{"txid":"'+txid+'","n":'+str(n)+'},'
- json_request = json_request.rstrip(",")
- json_request+="]}";
- response = http_get_call(url.hostname, url.port, '/rest/getutxos'+self.FORMAT_SEPARATOR+'json', json_request, True)
+
+ json_request = '/checkmempool/'
+ for x in range(0, 15):
+ json_request += txid+'-'+str(n)+'/'
+ json_request = json_request.rstrip("/");
+ response = http_get_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
self.nodes[0].generate(1) #generate block to not affect upcomming tests
self.sync_all()
-
+
################
# /rest/block/ #
################
-
+
# check binary format
response = http_get_call(url.hostname, url.port, '/rest/block/'+bb_hash+self.FORMAT_SEPARATOR+"bin", "", True)
assert_equal(response.status, 200)
@@ -248,7 +249,7 @@ class RESTTest (BitcoinTestFramework):
hex_string = http_get_call(url.hostname, url.port, '/rest/tx/'+tx_hash+self.FORMAT_SEPARATOR+"hex", "", True)
assert_equal(hex_string.status, 200)
assert_greater_than(int(response.getheader('content-length')), 10)
-
+
# check block tx details
@@ -278,7 +279,7 @@ class RESTTest (BitcoinTestFramework):
#test rest bestblock
bb_hash = self.nodes[0].getbestblockhash()
-
+
json_string = http_get_call(url.hostname, url.port, '/rest/chaininfo.json')
json_obj = json.loads(json_string)
assert_equal(json_obj['bestblockhash'], bb_hash)
diff --git a/qa/rpc-tests/rpcbind_test.py b/qa/rpc-tests/rpcbind_test.py
index 655e00b6e7..04110c2831 100755
--- a/qa/rpc-tests/rpcbind_test.py
+++ b/qa/rpc-tests/rpcbind_test.py
@@ -8,7 +8,6 @@
# Add python-bitcoinrpc to module search path:
import os
import sys
-sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), "python-bitcoinrpc"))
import json
import shutil
@@ -16,9 +15,8 @@ import subprocess
import tempfile
import traceback
-from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
-from util import *
-from netutil import *
+from test_framework.util import *
+from test_framework.netutil import *
def run_bind_test(tmpdir, allow_ips, connect_to, addresses, expected):
'''
diff --git a/qa/rpc-tests/script_test.py b/qa/rpc-tests/script_test.py
index 1ba3a478a8..860fa56b64 100755
--- a/qa/rpc-tests/script_test.py
+++ b/qa/rpc-tests/script_test.py
@@ -19,12 +19,12 @@ that flag, we use a block time before the switchover date).
NOTE: This test is very slow and may take more than 40 minutes to run.
'''
-from test_framework import ComparisonTestFramework
-from util import *
-from comptool import TestInstance, TestManager
-from mininode import *
-from blocktools import *
-from script import *
+from test_framework.test_framework import ComparisonTestFramework
+from test_framework.util import *
+from test_framework.comptool import TestInstance, TestManager
+from test_framework.mininode import *
+from test_framework.blocktools import *
+from test_framework.script import *
import logging
import copy
import json
@@ -42,7 +42,7 @@ class ScriptTestFile(object):
def load_files(self):
for f in self.files:
- self.data.extend(json.loads(open(f).read()))
+ self.data.extend(json.loads(open(os.path.dirname(os.path.abspath(__file__))+"/"+f).read()))
# Skip over records that are not long enough to be tests
def get_records(self):
diff --git a/qa/rpc-tests/signrawtransactions.py b/qa/rpc-tests/signrawtransactions.py
index 943634bd19..d51d6ee610 100755
--- a/qa/rpc-tests/signrawtransactions.py
+++ b/qa/rpc-tests/signrawtransactions.py
@@ -3,8 +3,8 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-from test_framework import BitcoinTestFramework
-from util import *
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
class SignRawTransactionsTest(BitcoinTestFramework):
diff --git a/qa/rpc-tests/smartfees.py b/qa/rpc-tests/smartfees.py
index 4eb8bb4842..c15c5fda09 100755
--- a/qa/rpc-tests/smartfees.py
+++ b/qa/rpc-tests/smartfees.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,86 +7,252 @@
# Test fee estimation code
#
-from test_framework import BitcoinTestFramework
-from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
-from util import *
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
+
+# Construct 2 trivial P2SH's and the ScriptSigs that spend them
+# So we can create many many transactions without needing to spend
+# time signing.
+P2SH_1 = "2MySexEGVzZpRgNQ1JdjdP5bRETznm3roQ2" # P2SH of "OP_1 OP_DROP"
+P2SH_2 = "2NBdpwq8Aoo1EEKEXPNrKvr5xQr3M9UfcZA" # P2SH of "OP_2 OP_DROP"
+# Associated ScriptSig's to spend satisfy P2SH_1 and P2SH_2
+# 4 bytes of OP_TRUE and push 2-byte redeem script of "OP_1 OP_DROP" or "OP_2 OP_DROP"
+SCRIPT_SIG = ["0451025175", "0451025275"]
+
+def satoshi_round(amount):
+ return Decimal(amount).quantize(Decimal('0.00000001'), rounding=ROUND_DOWN)
+
+def small_txpuzzle_randfee(from_node, conflist, unconflist, amount, min_fee, fee_increment):
+ '''
+ Create and send a transaction with a random fee.
+ The transaction pays to a trival P2SH script, and assumes that its inputs
+ are of the same form.
+ The function takes a list of confirmed outputs and unconfirmed outputs
+ and attempts to use the confirmed list first for its inputs.
+ It adds the newly created outputs to the unconfirmed list.
+ Returns (raw transaction, fee)
+ '''
+ # It's best to exponentially distribute our random fees
+ # because the buckets are exponentially spaced.
+ # Exponentially distributed from 1-128 * fee_increment
+ rand_fee = float(fee_increment)*(1.1892**random.randint(0,28))
+ # Total fee ranges from min_fee to min_fee + 127*fee_increment
+ fee = min_fee - fee_increment + satoshi_round(rand_fee)
+ inputs = []
+ total_in = Decimal("0.00000000")
+ while total_in <= (amount + fee) and len(conflist) > 0:
+ t = conflist.pop(0)
+ total_in += t["amount"]
+ inputs.append({ "txid" : t["txid"], "vout" : t["vout"]} )
+ if total_in <= amount + fee:
+ while total_in <= (amount + fee) and len(unconflist) > 0:
+ t = unconflist.pop(0)
+ total_in += t["amount"]
+ inputs.append({ "txid" : t["txid"], "vout" : t["vout"]} )
+ if total_in <= amount + fee:
+ raise RuntimeError("Insufficient funds: need %d, have %d"%(amount+fee, total_in))
+ outputs = {}
+ outputs[P2SH_1] = total_in - amount - fee
+ outputs[P2SH_2] = amount
+ rawtx = from_node.createrawtransaction(inputs, outputs)
+ # Createrawtransaction constructions a transaction that is ready to be signed
+ # These transactions don't need to be signed, but we still have to insert the ScriptSig
+ # that will satisfy the ScriptPubKey.
+ completetx = rawtx[0:10]
+ inputnum = 0
+ for inp in inputs:
+ completetx += rawtx[10+82*inputnum:82+82*inputnum]
+ completetx += SCRIPT_SIG[inp["vout"]]
+ completetx += rawtx[84+82*inputnum:92+82*inputnum]
+ inputnum += 1
+ completetx += rawtx[10+82*inputnum:]
+ txid = from_node.sendrawtransaction(completetx, True)
+ unconflist.append({ "txid" : txid, "vout" : 0 , "amount" : total_in - amount - fee})
+ unconflist.append({ "txid" : txid, "vout" : 1 , "amount" : amount})
+
+ return (completetx, fee)
+
+def split_inputs(from_node, txins, txouts, initial_split = False):
+ '''
+ We need to generate a lot of very small inputs so we can generate a ton of transactions
+ and they will have low priority.
+ This function takes an input from txins, and creates and sends a transaction
+ which splits the value into 2 outputs which are appended to txouts.
+ '''
+ prevtxout = txins.pop()
+ inputs = []
+ outputs = {}
+ inputs.append({ "txid" : prevtxout["txid"], "vout" : prevtxout["vout"] })
+ half_change = satoshi_round(prevtxout["amount"]/2)
+ rem_change = prevtxout["amount"] - half_change - Decimal("0.00001000")
+ outputs[P2SH_1] = half_change
+ outputs[P2SH_2] = rem_change
+ rawtx = from_node.createrawtransaction(inputs, outputs)
+ # If this is the initial split we actually need to sign the transaction
+ # Otherwise we just need to insert the property ScriptSig
+ if (initial_split) :
+ completetx = from_node.signrawtransaction(rawtx)["hex"]
+ else :
+ completetx = rawtx[0:82] + SCRIPT_SIG[prevtxout["vout"]] + rawtx[84:]
+ txid = from_node.sendrawtransaction(completetx, True)
+ txouts.append({ "txid" : txid, "vout" : 0 , "amount" : half_change})
+ txouts.append({ "txid" : txid, "vout" : 1 , "amount" : rem_change})
+
+def check_estimates(node, fees_seen, max_invalid, print_estimates = True):
+ '''
+ This function calls estimatefee and verifies that the estimates
+ meet certain invariants.
+ '''
+ all_estimates = [ node.estimatefee(i) for i in range(1,26) ]
+ if print_estimates:
+ print([str(all_estimates[e-1]) for e in [1,2,3,6,15,25]])
+ delta = 1.0e-6 # account for rounding error
+ last_e = max(fees_seen)
+ for e in filter(lambda x: x >= 0, all_estimates):
+ # Estimates should be within the bounds of what transactions fees actually were:
+ if float(e)+delta < min(fees_seen) or float(e)-delta > max(fees_seen):
+ raise AssertionError("Estimated fee (%f) out of range (%f,%f)"
+ %(float(e), min(fees_seen), max(fees_seen)))
+ # Estimates should be monotonically decreasing
+ if float(e)-delta > last_e:
+ raise AssertionError("Estimated fee (%f) larger than last fee (%f) for lower number of confirms"
+ %(float(e),float(last_e)))
+ last_e = e
+ valid_estimate = False
+ invalid_estimates = 0
+ for e in all_estimates:
+ if e >= 0:
+ valid_estimate = True
+ else:
+ invalid_estimates += 1
+ # Once we're at a high enough confirmation count that we can give an estimate
+ # We should have estimates for all higher confirmation counts
+ if valid_estimate and e < 0:
+ raise AssertionError("Invalid estimate appears at higher confirm count than valid estimate")
+ # Check on the expected number of different confirmation counts
+ # that we might not have valid estimates for
+ if invalid_estimates > max_invalid:
+ raise AssertionError("More than (%d) invalid estimates"%(max_invalid))
+ return all_estimates
+
class EstimateFeeTest(BitcoinTestFramework):
def setup_network(self):
+ '''
+ We'll setup the network to have 3 nodes that all mine with different parameters.
+ But first we need to use one node to create a lot of small low priority outputs
+ which we will use to generate our transactions.
+ '''
self.nodes = []
- self.nodes.append(start_node(0, self.options.tmpdir,
- ["-debug=mempool", "-debug=estimatefee", "-relaypriority=0"]))
- # Node1 mines small-but-not-tiny blocks, and allows free transactions.
+ # Use node0 to mine blocks for input splitting
+ self.nodes.append(start_node(0, self.options.tmpdir, ["-maxorphantx=1000",
+ "-relaypriority=0", "-whitelist=127.0.0.1"]))
+
+ print("This test is time consuming, please be patient")
+ print("Splitting inputs to small size so we can generate low priority tx's")
+ self.txouts = []
+ self.txouts2 = []
+ # Split a coinbase into two transaction puzzle outputs
+ split_inputs(self.nodes[0], self.nodes[0].listunspent(0), self.txouts, True)
+
+ # Mine
+ while (len(self.nodes[0].getrawmempool()) > 0):
+ self.nodes[0].generate(1)
+
+ # Repeatedly split those 2 outputs, doubling twice for each rep
+ # Use txouts to monitor the available utxo, since these won't be tracked in wallet
+ reps = 0
+ while (reps < 5):
+ #Double txouts to txouts2
+ while (len(self.txouts)>0):
+ split_inputs(self.nodes[0], self.txouts, self.txouts2)
+ while (len(self.nodes[0].getrawmempool()) > 0):
+ self.nodes[0].generate(1)
+ #Double txouts2 to txouts
+ while (len(self.txouts2)>0):
+ split_inputs(self.nodes[0], self.txouts2, self.txouts)
+ while (len(self.nodes[0].getrawmempool()) > 0):
+ self.nodes[0].generate(1)
+ reps += 1
+ print("Finished splitting")
+
+ # Now we can connect the other nodes, didn't want to connect them earlier
+ # so the estimates would not be affected by the splitting transactions
+ # Node1 mines small blocks but that are bigger than the expected transaction rate,
+ # and allows free transactions.
# NOTE: the CreateNewBlock code starts counting block size at 1,000 bytes,
- # so blockmaxsize of 2,000 is really just 1,000 bytes (room enough for
- # 6 or 7 transactions)
+ # (17k is room enough for 110 or so transactions)
self.nodes.append(start_node(1, self.options.tmpdir,
- ["-blockprioritysize=1500", "-blockmaxsize=2000",
- "-debug=mempool", "-debug=estimatefee", "-relaypriority=0"]))
+ ["-blockprioritysize=1500", "-blockmaxsize=18000",
+ "-maxorphantx=1000", "-relaypriority=0", "-debug=estimatefee"]))
connect_nodes(self.nodes[1], 0)
# Node2 is a stingy miner, that
- # produces very small blocks (room for only 3 or so transactions)
- node2args = [ "-blockprioritysize=0", "-blockmaxsize=1500",
- "-debug=mempool", "-debug=estimatefee", "-relaypriority=0"]
+ # produces too small blocks (room for only 70 or so transactions)
+ node2args = ["-blockprioritysize=0", "-blockmaxsize=12000", "-maxorphantx=1000", "-relaypriority=0"]
+
self.nodes.append(start_node(2, self.options.tmpdir, node2args))
- connect_nodes(self.nodes[2], 0)
+ connect_nodes(self.nodes[0], 2)
+ connect_nodes(self.nodes[2], 1)
self.is_network_split = False
self.sync_all()
-
+
+ def transact_and_mine(self, numblocks, mining_node):
+ min_fee = Decimal("0.00001")
+ # We will now mine numblocks blocks generating on average 100 transactions between each block
+ # We shuffle our confirmed txout set before each set of transactions
+ # small_txpuzzle_randfee will use the transactions that have inputs already in the chain when possible
+ # resorting to tx's that depend on the mempool when those run out
+ for i in range(numblocks):
+ random.shuffle(self.confutxo)
+ for j in range(random.randrange(100-50,100+50)):
+ from_index = random.randint(1,2)
+ (txhex, fee) = small_txpuzzle_randfee(self.nodes[from_index], self.confutxo,
+ self.memutxo, Decimal("0.005"), min_fee, min_fee)
+ tx_kbytes = (len(txhex)/2)/1000.0
+ self.fees_per_kb.append(float(fee)/tx_kbytes)
+ sync_mempools(self.nodes[0:3],.1)
+ mined = mining_node.getblock(mining_node.generate(1)[0],True)["tx"]
+ sync_blocks(self.nodes[0:3],.1)
+ #update which txouts are confirmed
+ newmem = []
+ for utx in self.memutxo:
+ if utx["txid"] in mined:
+ self.confutxo.append(utx)
+ else:
+ newmem.append(utx)
+ self.memutxo = newmem
def run_test(self):
- # Prime the memory pool with pairs of transactions
- # (high-priority, random fee and zero-priority, random fee)
- min_fee = Decimal("0.001")
- fees_per_kb = [];
- for i in range(12):
- (txid, txhex, fee) = random_zeropri_transaction(self.nodes, Decimal("1.1"),
- min_fee, min_fee, 20)
- tx_kbytes = (len(txhex)/2)/1000.0
- fees_per_kb.append(float(fee)/tx_kbytes)
-
- # Mine blocks with node2 until the memory pool clears:
- count_start = self.nodes[2].getblockcount()
- while len(self.nodes[2].getrawmempool()) > 0:
- self.nodes[2].generate(1)
- self.sync_all()
-
- all_estimates = [ self.nodes[0].estimatefee(i) for i in range(1,20) ]
- print("Fee estimates, super-stingy miner: "+str([str(e) for e in all_estimates]))
+ self.fees_per_kb = []
+ self.memutxo = []
+ self.confutxo = self.txouts # Start with the set of confirmed txouts after splitting
+ print("Checking estimates for 1/2/3/6/15/25 blocks")
+ print("Creating transactions and mining them with a huge block size")
+ # Create transactions and mine 20 big blocks with node 0 such that the mempool is always emptied
+ self.transact_and_mine(30, self.nodes[0])
+ check_estimates(self.nodes[1], self.fees_per_kb, 1)
- # Estimates should be within the bounds of what transactions fees actually were:
- delta = 1.0e-6 # account for rounding error
- for e in filter(lambda x: x >= 0, all_estimates):
- if float(e)+delta < min(fees_per_kb) or float(e)-delta > max(fees_per_kb):
- raise AssertionError("Estimated fee (%f) out of range (%f,%f)"%(float(e), min_fee_kb, max_fee_kb))
-
- # Generate transactions while mining 30 more blocks, this time with node1:
- for i in range(30):
- for j in range(random.randrange(6-4,6+4)):
- (txid, txhex, fee) = random_transaction(self.nodes, Decimal("1.1"),
- Decimal("0.0"), min_fee, 20)
- tx_kbytes = (len(txhex)/2)/1000.0
- fees_per_kb.append(float(fee)/tx_kbytes)
- self.nodes[1].generate(1)
- self.sync_all()
+ print("Creating transactions and mining them with a block size that can't keep up")
+ # Create transactions and mine 30 small blocks with node 2, but create txs faster than we can mine
+ self.transact_and_mine(20, self.nodes[2])
+ check_estimates(self.nodes[1], self.fees_per_kb, 3)
- all_estimates = [ self.nodes[0].estimatefee(i) for i in range(1,20) ]
- print("Fee estimates, more generous miner: "+str([ str(e) for e in all_estimates]))
- for e in filter(lambda x: x >= 0, all_estimates):
- if float(e)+delta < min(fees_per_kb) or float(e)-delta > max(fees_per_kb):
- raise AssertionError("Estimated fee (%f) out of range (%f,%f)"%(float(e), min_fee_kb, max_fee_kb))
+ print("Creating transactions and mining them at a block size that is just big enough")
+ # Generate transactions while mining 40 more blocks, this time with node1
+ # which mines blocks with capacity just above the rate that transactions are being created
+ self.transact_and_mine(40, self.nodes[1])
+ check_estimates(self.nodes[1], self.fees_per_kb, 2)
# Finish by mining a normal-sized block:
- while len(self.nodes[0].getrawmempool()) > 0:
- self.nodes[0].generate(1)
- self.sync_all()
-
- final_estimates = [ self.nodes[0].estimatefee(i) for i in range(1,20) ]
- print("Final fee estimates: "+str([ str(e) for e in final_estimates]))
+ while len(self.nodes[1].getrawmempool()) > 0:
+ self.nodes[1].generate(1)
+ sync_blocks(self.nodes[0:3],.1)
+ print("Final estimates after emptying mempools")
+ check_estimates(self.nodes[1], self.fees_per_kb, 2)
if __name__ == '__main__':
EstimateFeeTest().main()
diff --git a/qa/rpc-tests/python-bitcoinrpc/bitcoinrpc/__init__.py b/qa/rpc-tests/test_framework/__init__.py
index e69de29bb2..e69de29bb2 100644
--- a/qa/rpc-tests/python-bitcoinrpc/bitcoinrpc/__init__.py
+++ b/qa/rpc-tests/test_framework/__init__.py
diff --git a/qa/rpc-tests/python-bitcoinrpc/bitcoinrpc/authproxy.py b/qa/rpc-tests/test_framework/authproxy.py
index bc7d655fdf..bc7d655fdf 100644
--- a/qa/rpc-tests/python-bitcoinrpc/bitcoinrpc/authproxy.py
+++ b/qa/rpc-tests/test_framework/authproxy.py
diff --git a/qa/rpc-tests/bignum.py b/qa/rpc-tests/test_framework/bignum.py
index b0c58ccd47..b0c58ccd47 100644
--- a/qa/rpc-tests/bignum.py
+++ b/qa/rpc-tests/test_framework/bignum.py
diff --git a/qa/rpc-tests/blockstore.py b/qa/rpc-tests/test_framework/blockstore.py
index c57b6df81b..c57b6df81b 100644
--- a/qa/rpc-tests/blockstore.py
+++ b/qa/rpc-tests/test_framework/blockstore.py
diff --git a/qa/rpc-tests/blocktools.py b/qa/rpc-tests/test_framework/blocktools.py
index f397fe7cd6..f397fe7cd6 100644
--- a/qa/rpc-tests/blocktools.py
+++ b/qa/rpc-tests/test_framework/blocktools.py
diff --git a/qa/rpc-tests/comptool.py b/qa/rpc-tests/test_framework/comptool.py
index 23a979250c..23a979250c 100755
--- a/qa/rpc-tests/comptool.py
+++ b/qa/rpc-tests/test_framework/comptool.py
diff --git a/qa/rpc-tests/mininode.py b/qa/rpc-tests/test_framework/mininode.py
index b7d78e74fa..b7d78e74fa 100755
--- a/qa/rpc-tests/mininode.py
+++ b/qa/rpc-tests/test_framework/mininode.py
diff --git a/qa/rpc-tests/netutil.py b/qa/rpc-tests/test_framework/netutil.py
index b30a88a4f7..b30a88a4f7 100644
--- a/qa/rpc-tests/netutil.py
+++ b/qa/rpc-tests/test_framework/netutil.py
diff --git a/qa/rpc-tests/script.py b/qa/rpc-tests/test_framework/script.py
index 03695b8635..e37ab5d45a 100644
--- a/qa/rpc-tests/script.py
+++ b/qa/rpc-tests/test_framework/script.py
@@ -14,7 +14,7 @@ Functionality to build scripts, as well as SignatureHash().
from __future__ import absolute_import, division, print_function, unicode_literals
-from mininode import CTransaction, CTxOut, hash256
+from test_framework.mininode import CTransaction, CTxOut, hash256
import sys
bchr = chr
@@ -27,7 +27,7 @@ if sys.version > '3':
import copy
import struct
-import bignum
+import test_framework.bignum
MAX_SCRIPT_SIZE = 10000
MAX_SCRIPT_ELEMENT_SIZE = 520
diff --git a/qa/rpc-tests/socks5.py b/qa/rpc-tests/test_framework/socks5.py
index 1dbfb98d5d..1dbfb98d5d 100644
--- a/qa/rpc-tests/socks5.py
+++ b/qa/rpc-tests/test_framework/socks5.py
diff --git a/qa/rpc-tests/test_framework.py b/qa/rpc-tests/test_framework/test_framework.py
index 15a357a340..5671431f6e 100755
--- a/qa/rpc-tests/test_framework.py
+++ b/qa/rpc-tests/test_framework/test_framework.py
@@ -8,13 +8,12 @@
# Add python-bitcoinrpc to module search path:
import os
import sys
-sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), "python-bitcoinrpc"))
import shutil
import tempfile
import traceback
-from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
+from authproxy import AuthServiceProxy, JSONRPCException
from util import *
diff --git a/qa/rpc-tests/util.py b/qa/rpc-tests/test_framework/util.py
index 3b4a10e46b..c236ec2602 100644
--- a/qa/rpc-tests/util.py
+++ b/qa/rpc-tests/test_framework/util.py
@@ -8,7 +8,6 @@
# Add python-bitcoinrpc to module search path:
import os
import sys
-sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), "python-bitcoinrpc"))
from decimal import Decimal, ROUND_DOWN
import json
@@ -18,7 +17,7 @@ import subprocess
import time
import re
-from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
+from authproxy import AuthServiceProxy, JSONRPCException
from util import *
def p2p_port(n):
@@ -33,7 +32,7 @@ def check_json_precision():
if satoshis != 2000000000000003:
raise RuntimeError("JSON encode/decode loses precision")
-def sync_blocks(rpc_connections):
+def sync_blocks(rpc_connections, wait=1):
"""
Wait until everybody has the same block count
"""
@@ -41,9 +40,9 @@ def sync_blocks(rpc_connections):
counts = [ x.getblockcount() for x in rpc_connections ]
if counts == [ counts[0] ]*len(counts):
break
- time.sleep(1)
+ time.sleep(wait)
-def sync_mempools(rpc_connections):
+def sync_mempools(rpc_connections, wait=1):
"""
Wait until everybody has the same transactions in their memory
pools
@@ -56,7 +55,7 @@ def sync_mempools(rpc_connections):
num_match = num_match+1
if num_match == len(rpc_connections):
break
- time.sleep(1)
+ time.sleep(wait)
bitcoind_processes = {}
diff --git a/qa/rpc-tests/txn_doublespend.py b/qa/rpc-tests/txn_doublespend.py
index fe9168944b..99dcdae552 100755
--- a/qa/rpc-tests/txn_doublespend.py
+++ b/qa/rpc-tests/txn_doublespend.py
@@ -7,10 +7,9 @@
# Test proper accounting with malleable transactions
#
-from test_framework import BitcoinTestFramework
-from bitcoinrpc.authproxy import AuthServiceProxy, JSONRPCException
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
from decimal import Decimal
-from util import *
import os
import shutil
diff --git a/qa/rpc-tests/wallet.py b/qa/rpc-tests/wallet.py
index b8965b3662..46dc7765b6 100755
--- a/qa/rpc-tests/wallet.py
+++ b/qa/rpc-tests/wallet.py
@@ -19,9 +19,8 @@
# k) test ResendWalletTransactions - create transactions, startup fourth node, make sure it syncs
#
-from test_framework import BitcoinTestFramework
-from util import *
-
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
class WalletTest (BitcoinTestFramework):
diff --git a/qa/rpc-tests/walletbackup.py b/qa/rpc-tests/walletbackup.py
index b9fc862234..da100d7fc0 100755
--- a/qa/rpc-tests/walletbackup.py
+++ b/qa/rpc-tests/walletbackup.py
@@ -33,8 +33,8 @@ Shutdown again, restore using importwallet,
and confirm again balances are correct.
"""
-from test_framework import BitcoinTestFramework
-from util import *
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
from random import randint
import logging
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.INFO)
diff --git a/qa/rpc-tests/zapwallettxes.py b/qa/rpc-tests/zapwallettxes.py
index 045614e94c..0ec8ec5364 100755
--- a/qa/rpc-tests/zapwallettxes.py
+++ b/qa/rpc-tests/zapwallettxes.py
@@ -3,8 +3,8 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-from test_framework import BitcoinTestFramework
-from util import *
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
class ZapWalletTXesTest (BitcoinTestFramework):