aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/config.ini.in1
-rwxr-xr-xtest/functional/feature_bip68_sequence.py12
-rwxr-xr-xtest/functional/feature_block.py31
-rwxr-xr-xtest/functional/feature_config_args.py7
-rwxr-xr-xtest/functional/feature_includeconf.py75
-rwxr-xr-xtest/functional/feature_logging.py21
-rwxr-xr-xtest/functional/feature_maxuploadtarget.py4
-rwxr-xr-xtest/functional/feature_proxy.py8
-rwxr-xr-xtest/functional/feature_pruning.py4
-rwxr-xr-xtest/functional/feature_rbf.py46
-rwxr-xr-xtest/functional/feature_segwit.py28
-rwxr-xr-xtest/functional/interface_rest.py4
-rwxr-xr-xtest/functional/interface_zmq.py3
-rwxr-xr-xtest/functional/mempool_packages.py7
-rwxr-xr-xtest/functional/mining_prioritisetransaction.py2
-rwxr-xr-xtest/functional/p2p_compactblocks.py5
-rwxr-xr-xtest/functional/p2p_feefilter.py2
-rwxr-xr-xtest/functional/p2p_invalid_tx.py112
-rwxr-xr-xtest/functional/p2p_mempool.py2
-rwxr-xr-xtest/functional/p2p_segwit.py131
-rwxr-xr-xtest/functional/p2p_sendheaders.py96
-rwxr-xr-xtest/functional/p2p_unrequested_blocks.py6
-rwxr-xr-xtest/functional/rpc_bind.py104
-rwxr-xr-xtest/functional/rpc_decodescript.py60
-rwxr-xr-xtest/functional/rpc_deprecated.py87
-rwxr-xr-xtest/functional/rpc_fundrawtransaction.py22
-rwxr-xr-xtest/functional/rpc_rawtransaction.py23
-rwxr-xr-xtest/functional/rpc_users.py47
-rw-r--r--test/functional/test_framework/blocktools.py112
-rw-r--r--test/functional/test_framework/key.py8
-rwxr-xr-xtest/functional/test_framework/mininode.py11
-rw-r--r--test/functional/test_framework/script.py31
-rw-r--r--test/functional/test_framework/socks5.py12
-rwxr-xr-xtest/functional/test_framework/test_framework.py35
-rwxr-xr-xtest/functional/test_framework/test_node.py94
-rw-r--r--test/functional/test_framework/util.py24
-rwxr-xr-xtest/functional/test_runner.py51
-rwxr-xr-xtest/functional/wallet_address_types.py5
-rwxr-xr-xtest/functional/wallet_basic.py182
-rwxr-xr-xtest/functional/wallet_dump.py2
-rwxr-xr-xtest/functional/wallet_hd.py35
-rwxr-xr-xtest/functional/wallet_import_rescan.py42
-rwxr-xr-xtest/functional/wallet_importprunedfunds.py32
-rwxr-xr-xtest/functional/wallet_keypool.py2
-rwxr-xr-xtest/functional/wallet_keypool_topup.py2
-rwxr-xr-xtest/functional/wallet_labels.py57
-rwxr-xr-xtest/functional/wallet_listreceivedby.py42
-rwxr-xr-xtest/functional/wallet_listsinceblock.py16
-rwxr-xr-xtest/functional/wallet_listtransactions.py (renamed from test/functional/rpc_listtransactions.py)120
-rwxr-xr-xtest/functional/wallet_multiwallet.py20
-rwxr-xr-xtest/functional/wallet_txn_clone.py96
-rwxr-xr-xtest/functional/wallet_txn_doublespend.py69
-rw-r--r--test/util/data/blanktxv1.json1
-rw-r--r--test/util/data/blanktxv2.json1
-rw-r--r--test/util/data/tt-delin1-out.json1
-rw-r--r--test/util/data/tt-delout1-out.json1
-rw-r--r--test/util/data/tt-locktime317000-out.json1
-rw-r--r--test/util/data/txcreate1.json1
-rw-r--r--test/util/data/txcreate2.json1
-rw-r--r--test/util/data/txcreatedata1.json1
-rw-r--r--test/util/data/txcreatedata2.json1
-rw-r--r--test/util/data/txcreatedata_seq0.json1
-rw-r--r--test/util/data/txcreatedata_seq1.json1
-rw-r--r--test/util/data/txcreatemultisig1.json1
-rw-r--r--test/util/data/txcreatemultisig2.json1
-rw-r--r--test/util/data/txcreatemultisig3.json1
-rw-r--r--test/util/data/txcreatemultisig4.json1
-rw-r--r--test/util/data/txcreatemultisig5.json1
-rw-r--r--test/util/data/txcreateoutpubkey1.json1
-rw-r--r--test/util/data/txcreateoutpubkey2.json1
-rw-r--r--test/util/data/txcreateoutpubkey3.json1
-rw-r--r--test/util/data/txcreatescript1.json1
-rw-r--r--test/util/data/txcreatescript2.json1
-rw-r--r--test/util/data/txcreatescript3.json1
-rw-r--r--test/util/data/txcreatescript4.json1
-rw-r--r--test/util/data/txcreatesignv1.json1
-rwxr-xr-xtest/util/rpcauth-test.py48
77 files changed, 1436 insertions, 686 deletions
diff --git a/test/config.ini.in b/test/config.ini.in
index 35ee092be4..a1119dc739 100644
--- a/test/config.ini.in
+++ b/test/config.ini.in
@@ -9,6 +9,7 @@
SRCDIR=@abs_top_srcdir@
BUILDDIR=@abs_top_builddir@
EXEEXT=@EXEEXT@
+RPCAUTH=@abs_top_srcdir@/share/rpcauth/rpcauth.py
[components]
# Which components are enabled. These are commented out by `configure` if they were disabled when running config.
diff --git a/test/functional/feature_bip68_sequence.py b/test/functional/feature_bip68_sequence.py
index e5db9e18c7..d8521550b5 100755
--- a/test/functional/feature_bip68_sequence.py
+++ b/test/functional/feature_bip68_sequence.py
@@ -67,7 +67,7 @@ class BIP68Test(BitcoinTestFramework):
# If sequence locks were used, this would require 1 block for the
# input to mature.
sequence_value = SEQUENCE_LOCKTIME_DISABLE_FLAG | 1
- tx1.vin = [CTxIn(COutPoint(int(utxo["txid"], 16), utxo["vout"]), nSequence=sequence_value)]
+ tx1.vin = [CTxIn(COutPoint(int(utxo["txid"], 16), utxo["vout"]), nSequence=sequence_value)]
tx1.vout = [CTxOut(value, CScript([b'a']))]
tx1_signed = self.nodes[0].signrawtransactionwithwallet(ToHex(tx1))["hex"]
@@ -80,7 +80,7 @@ class BIP68Test(BitcoinTestFramework):
tx2.nVersion = 2
sequence_value = sequence_value & 0x7fffffff
tx2.vin = [CTxIn(COutPoint(tx1_id, 0), nSequence=sequence_value)]
- tx2.vout = [CTxOut(int(value-self.relayfee*COIN), CScript([b'a']))]
+ tx2.vout = [CTxOut(int(value - self.relayfee * COIN), CScript([b'a' * 35]))]
tx2.rehash()
assert_raises_rpc_error(-26, NOT_FINAL_ERROR, self.nodes[0].sendrawtransaction, ToHex(tx2))
@@ -129,7 +129,7 @@ class BIP68Test(BitcoinTestFramework):
# Track whether any sequence locks used should fail
should_pass = True
-
+
# Track whether this transaction was built with sequence locks
using_sequence_locks = False
@@ -222,7 +222,7 @@ class BIP68Test(BitcoinTestFramework):
tx = CTransaction()
tx.nVersion = 2
tx.vin = [CTxIn(COutPoint(orig_tx.sha256, 0), nSequence=sequence_value)]
- tx.vout = [CTxOut(int(orig_tx.vout[0].nValue - relayfee*COIN), CScript([b'a']))]
+ tx.vout = [CTxOut(int(orig_tx.vout[0].nValue - relayfee * COIN), CScript([b'a' * 35]))]
tx.rehash()
if (orig_tx.hash in node.getrawmempool()):
@@ -343,14 +343,14 @@ class BIP68Test(BitcoinTestFramework):
tx2.rehash()
self.nodes[0].sendrawtransaction(ToHex(tx2))
-
+
# Now make an invalid spend of tx2 according to BIP68
sequence_value = 100 # 100 block relative locktime
tx3 = CTransaction()
tx3.nVersion = 2
tx3.vin = [CTxIn(COutPoint(tx2.sha256, 0), nSequence=sequence_value)]
- tx3.vout = [CTxOut(int(tx2.vout[0].nValue - self.relayfee*COIN), CScript([b'a']))]
+ tx3.vout = [CTxOut(int(tx2.vout[0].nValue - self.relayfee * COIN), CScript([b'a' * 35]))]
tx3.rehash()
assert_raises_rpc_error(-26, NOT_FINAL_ERROR, self.nodes[0].sendrawtransaction, ToHex(tx3))
diff --git a/test/functional/feature_block.py b/test/functional/feature_block.py
index 181c7f3369..f943fdf176 100755
--- a/test/functional/feature_block.py
+++ b/test/functional/feature_block.py
@@ -32,6 +32,7 @@ from test_framework.script import (
OP_ELSE,
OP_ENDIF,
OP_EQUAL,
+ OP_DROP,
OP_FALSE,
OP_HASH160,
OP_IF,
@@ -82,10 +83,7 @@ class FullBlockTest(BitcoinTestFramework):
def run_test(self):
node = self.nodes[0] # convenience reference to the node
- # reconnect_p2p() expects the network thread to be running
- network_thread_start()
-
- self.reconnect_p2p()
+ self.bootstrap_p2p() # Add one p2p connection to the node
self.block_heights = {}
self.coinbase_key = CECKey()
@@ -1218,7 +1216,7 @@ class FullBlockTest(BitcoinTestFramework):
block.vtx.extend(tx_list)
# this is a little handier to use than the version in blocktools.py
- def create_tx(self, spend_tx, n, value, script=CScript([OP_TRUE])):
+ def create_tx(self, spend_tx, n, value, script=CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])):
return create_transaction(spend_tx, n, b"", value, script)
# sign a transaction, using the key we know about
@@ -1296,17 +1294,28 @@ class FullBlockTest(BitcoinTestFramework):
self.blocks[block_number] = block
return block
- def reconnect_p2p(self):
+ def bootstrap_p2p(self):
"""Add a P2P connection to the node.
+ Helper to connect and wait for version handshake."""
+ self.nodes[0].add_p2p_connection(P2PDataStore())
+ network_thread_start()
+ # We need to wait for the initial getheaders from the peer before we
+ # start populating our blockstore. If we don't, then we may run ahead
+ # to the next subtest before we receive the getheaders. We'd then send
+ # an INV for the next block and receive two getheaders - one for the
+ # IBD and one for the INV. We'd respond to both and could get
+ # unexpectedly disconnected if the DoS score for that error is 50.
+ self.nodes[0].p2p.wait_for_getheaders(timeout=5)
+
+ def reconnect_p2p(self):
+ """Tear down and bootstrap the P2P connection to the node.
+
The node gets disconnected several times in this test. This helper
method reconnects the p2p and restarts the network thread."""
-
- network_thread_join()
self.nodes[0].disconnect_p2ps()
- self.nodes[0].add_p2p_connection(P2PDataStore())
- network_thread_start()
- self.nodes[0].p2p.wait_for_verack()
+ network_thread_join()
+ self.bootstrap_p2p()
def sync_blocks(self, blocks, success=True, reject_code=None, reject_reason=None, request_block=True, reconnect=False, timeout=60):
"""Sends blocks to test node. Syncs and verifies that tip has advanced to most recent block.
diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py
index a1d22191af..e9924451d1 100755
--- a/test/functional/feature_config_args.py
+++ b/test/functional/feature_config_args.py
@@ -29,8 +29,13 @@ class ConfArgsTest(BitcoinTestFramework):
# Check that using non-existent datadir in conf file fails
conf_file = os.path.join(default_data_dir, "bitcoin.conf")
- with open(conf_file, 'a', encoding='utf8') as f:
+
+ # datadir needs to be set before [regtest] section
+ conf_file_contents = open(conf_file, encoding='utf8').read()
+ with open(conf_file, 'w', encoding='utf8') as f:
f.write("datadir=" + new_data_dir + "\n")
+ f.write(conf_file_contents)
+
self.nodes[0].assert_start_raises_init_error(['-conf=' + conf_file], 'Error reading configuration file: specified data directory "' + new_data_dir + '" does not exist.')
# Create the directory and ensure the config file now works
diff --git a/test/functional/feature_includeconf.py b/test/functional/feature_includeconf.py
new file mode 100755
index 0000000000..9ccb89af43
--- /dev/null
+++ b/test/functional/feature_includeconf.py
@@ -0,0 +1,75 @@
+#!/usr/bin/env python3
+# Copyright (c) 2018 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Tests the includeconf argument
+
+Verify that:
+
+1. adding includeconf to the configuration file causes the includeconf
+ file to be loaded in the correct order.
+2. includeconf cannot be used as a command line argument.
+3. includeconf cannot be used recursively (ie includeconf can only
+ be used from the base config file).
+4. multiple includeconf arguments can be specified in the main config
+ file.
+"""
+import os
+
+from test_framework.test_framework import BitcoinTestFramework
+
+class IncludeConfTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.setup_clean_chain = False
+ self.num_nodes = 1
+
+ def setup_chain(self):
+ super().setup_chain()
+ # Create additional config files
+ # - tmpdir/node0/relative.conf
+ with open(os.path.join(self.options.tmpdir, "node0", "relative.conf"), "w", encoding="utf8") as f:
+ f.write("uacomment=relative\n")
+ # - tmpdir/node0/relative2.conf
+ with open(os.path.join(self.options.tmpdir, "node0", "relative2.conf"), "w", encoding="utf8") as f:
+ f.write("uacomment=relative2\n")
+ with open(os.path.join(self.options.tmpdir, "node0", "bitcoin.conf"), "a", encoding='utf8') as f:
+ f.write("uacomment=main\nincludeconf=relative.conf\n")
+
+ def run_test(self):
+ self.log.info("-includeconf works from config file. subversion should end with 'main; relative)/'")
+
+ subversion = self.nodes[0].getnetworkinfo()["subversion"]
+ assert subversion.endswith("main; relative)/")
+
+ self.log.info("-includeconf cannot be used as command-line arg. subversion should still end with 'main; relative)/'")
+ self.stop_node(0)
+
+ self.start_node(0, extra_args=["-includeconf=relative2.conf"])
+
+ subversion = self.nodes[0].getnetworkinfo()["subversion"]
+ assert subversion.endswith("main; relative)/")
+ self.stop_node(0, expected_stderr="warning: -includeconf cannot be used from commandline; ignoring -includeconf=relative2.conf")
+
+ self.log.info("-includeconf cannot be used recursively. subversion should end with 'main; relative)/'")
+ with open(os.path.join(self.options.tmpdir, "node0", "relative.conf"), "a", encoding="utf8") as f:
+ f.write("includeconf=relative2.conf\n")
+ self.start_node(0)
+
+ subversion = self.nodes[0].getnetworkinfo()["subversion"]
+ assert subversion.endswith("main; relative)/")
+ self.stop_node(0, expected_stderr="warning: -includeconf cannot be used from included files; ignoring -includeconf=relative2.conf")
+
+ self.log.info("multiple -includeconf args can be used from the base config file. subversion should end with 'main; relative; relative2)/'")
+ with open(os.path.join(self.options.tmpdir, "node0", "relative.conf"), "w", encoding="utf8") as f:
+ f.write("uacomment=relative\n")
+
+ with open(os.path.join(self.options.tmpdir, "node0", "bitcoin.conf"), "a", encoding='utf8') as f:
+ f.write("includeconf=relative2.conf\n")
+
+ self.start_node(0)
+
+ subversion = self.nodes[0].getnetworkinfo()["subversion"]
+ assert subversion.endswith("main; relative; relative2)/")
+
+if __name__ == '__main__':
+ IncludeConfTest().main()
diff --git a/test/functional/feature_logging.py b/test/functional/feature_logging.py
index 3c7aecf10a..166f8f8694 100755
--- a/test/functional/feature_logging.py
+++ b/test/functional/feature_logging.py
@@ -15,13 +15,17 @@ class LoggingTest(BitcoinTestFramework):
self.num_nodes = 1
self.setup_clean_chain = True
+ def relative_log_path(self, name):
+ return os.path.join(self.nodes[0].datadir, "regtest", name)
+
def run_test(self):
# test default log file name
- assert os.path.isfile(os.path.join(self.nodes[0].datadir, "regtest", "debug.log"))
+ default_log_path = self.relative_log_path("debug.log")
+ assert os.path.isfile(default_log_path)
# test alternative log file name in datadir
self.restart_node(0, ["-debuglogfile=foo.log"])
- assert os.path.isfile(os.path.join(self.nodes[0].datadir, "regtest", "foo.log"))
+ assert os.path.isfile(self.relative_log_path("foo.log"))
# test alternative log file name outside datadir
tempname = os.path.join(self.options.tmpdir, "foo.log")
@@ -29,7 +33,7 @@ class LoggingTest(BitcoinTestFramework):
assert os.path.isfile(tempname)
# check that invalid log (relative) will cause error
- invdir = os.path.join(self.nodes[0].datadir, "regtest", "foo")
+ invdir = self.relative_log_path("foo")
invalidname = os.path.join("foo", "foo.log")
self.stop_node(0)
exp_stderr = "Error: Could not open debug log file \S+$"
@@ -55,6 +59,17 @@ class LoggingTest(BitcoinTestFramework):
self.start_node(0, ["-debuglogfile=%s" % (invalidname)])
assert os.path.isfile(os.path.join(invdir, "foo.log"))
+ # check that -nodebuglogfile disables logging
+ self.stop_node(0)
+ os.unlink(default_log_path)
+ assert not os.path.isfile(default_log_path)
+ self.start_node(0, ["-nodebuglogfile"])
+ assert not os.path.isfile(default_log_path)
+
+ # just sanity check no crash here
+ self.stop_node(0)
+ self.start_node(0, ["-debuglogfile=%s" % os.devnull])
+
if __name__ == '__main__':
LoggingTest().main()
diff --git a/test/functional/feature_maxuploadtarget.py b/test/functional/feature_maxuploadtarget.py
index ce6ec76c61..0946f27b90 100755
--- a/test/functional/feature_maxuploadtarget.py
+++ b/test/functional/feature_maxuploadtarget.py
@@ -30,7 +30,7 @@ class TestP2PConn(P2PInterface):
self.block_receive_map[message.block.sha256] += 1
class MaxUploadTest(BitcoinTestFramework):
-
+
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 1
@@ -100,7 +100,7 @@ class MaxUploadTest(BitcoinTestFramework):
assert_equal(p2p_conns[0].block_receive_map[big_old_block], i+1)
assert_equal(len(self.nodes[0].getpeerinfo()), 3)
- # At most a couple more tries should succeed (depending on how long
+ # At most a couple more tries should succeed (depending on how long
# the test has been running so far).
for i in range(3):
p2p_conns[0].send_message(getdata_request)
diff --git a/test/functional/feature_proxy.py b/test/functional/feature_proxy.py
index 2eb1be47a5..2d10c547e2 100755
--- a/test/functional/feature_proxy.py
+++ b/test/functional/feature_proxy.py
@@ -79,9 +79,9 @@ class ProxyTest(BitcoinTestFramework):
# Note: proxies are not used to connect to local nodes
# this is because the proxy to use is based on CService.GetNetwork(), which return NET_UNROUTABLE for localhost
args = [
- ['-listen', '-proxy=%s:%i' % (self.conf1.addr),'-proxyrandomize=1'],
- ['-listen', '-proxy=%s:%i' % (self.conf1.addr),'-onion=%s:%i' % (self.conf2.addr),'-proxyrandomize=0'],
- ['-listen', '-proxy=%s:%i' % (self.conf2.addr),'-proxyrandomize=1'],
+ ['-listen', '-proxy=%s:%i' % (self.conf1.addr),'-proxyrandomize=1'],
+ ['-listen', '-proxy=%s:%i' % (self.conf1.addr),'-onion=%s:%i' % (self.conf2.addr),'-proxyrandomize=0'],
+ ['-listen', '-proxy=%s:%i' % (self.conf2.addr),'-proxyrandomize=1'],
[]
]
if self.have_ipv6:
@@ -182,7 +182,7 @@ class ProxyTest(BitcoinTestFramework):
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))
diff --git a/test/functional/feature_pruning.py b/test/functional/feature_pruning.py
index 3adde8dd73..11a52b9ee2 100755
--- a/test/functional/feature_pruning.py
+++ b/test/functional/feature_pruning.py
@@ -124,7 +124,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)
self.stop_node(1)
- self.start_node(1, extra_args=["-maxreceivebuffer=20000","-blockmaxweight=20000", "-checkblocks=5", "-disablesafemode"])
+ self.start_node(1, extra_args=["-maxreceivebuffer=20000","-blockmaxweight=20000", "-checkblocks=5"])
height = self.nodes[1].getblockcount()
self.log.info("Current block height: %d" % height)
@@ -147,7 +147,7 @@ class PruneTest(BitcoinTestFramework):
# Reboot node1 to clear those giant tx's from mempool
self.stop_node(1)
- self.start_node(1, extra_args=["-maxreceivebuffer=20000","-blockmaxweight=20000", "-checkblocks=5", "-disablesafemode"])
+ self.start_node(1, extra_args=["-maxreceivebuffer=20000","-blockmaxweight=20000", "-checkblocks=5"])
self.log.info("Generating new longer chain of 300 more blocks")
self.nodes[1].generate(300)
diff --git a/test/functional/feature_rbf.py b/test/functional/feature_rbf.py
index d6ab5ecc37..c087960782 100755
--- a/test/functional/feature_rbf.py
+++ b/test/functional/feature_rbf.py
@@ -123,7 +123,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
tx1a = CTransaction()
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- tx1a.vout = [CTxOut(1*COIN, CScript([b'a']))]
+ tx1a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))]
tx1a_hex = txToHex(tx1a)
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
@@ -132,7 +132,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# Should fail because we haven't changed the fee
tx1b = CTransaction()
tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- tx1b.vout = [CTxOut(1*COIN, CScript([b'b']))]
+ tx1b.vout = [CTxOut(1 * COIN, CScript([b'b' * 35]))]
tx1b_hex = txToHex(tx1b)
# This will raise an exception due to insufficient fee
@@ -143,7 +143,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# Extra 0.1 BTC fee
tx1b = CTransaction()
tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- tx1b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))]
+ tx1b.vout = [CTxOut(int(0.9 * COIN), CScript([b'b' * 35]))]
tx1b_hex = txToHex(tx1b)
# Replacement still disabled even with "enough fee"
assert_raises_rpc_error(-26, "txn-mempool-conflict", self.nodes[1].sendrawtransaction, tx1b_hex, True)
@@ -175,7 +175,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
remaining_value -= 1*COIN
tx = CTransaction()
tx.vin = [CTxIn(prevout, nSequence=0)]
- tx.vout = [CTxOut(remaining_value, CScript([1]))]
+ tx.vout = [CTxOut(remaining_value, CScript([1, OP_DROP] * 15 + [1]))]
tx_hex = txToHex(tx)
txid = self.nodes[0].sendrawtransaction(tx_hex, True)
chain_txids.append(txid)
@@ -185,7 +185,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# child fees - 40 BTC - so this attempt is rejected.
dbl_tx = CTransaction()
dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- dbl_tx.vout = [CTxOut(initial_nValue - 30*COIN, CScript([1]))]
+ dbl_tx.vout = [CTxOut(initial_nValue - 30 * COIN, CScript([1] * 35))]
dbl_tx_hex = txToHex(dbl_tx)
# This will raise an exception due to insufficient fee
@@ -194,7 +194,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# Accepted with sufficient fee
dbl_tx = CTransaction()
dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- dbl_tx.vout = [CTxOut(1*COIN, CScript([1]))]
+ dbl_tx.vout = [CTxOut(1 * COIN, CScript([1] * 35))]
dbl_tx_hex = txToHex(dbl_tx)
self.nodes[0].sendrawtransaction(dbl_tx_hex, True)
@@ -247,7 +247,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# Attempt double-spend, will fail because too little fee paid
dbl_tx = CTransaction()
dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- dbl_tx.vout = [CTxOut(initial_nValue - fee*n, CScript([1]))]
+ dbl_tx.vout = [CTxOut(initial_nValue - fee * n, CScript([1] * 35))]
dbl_tx_hex = txToHex(dbl_tx)
# This will raise an exception due to insufficient fee
assert_raises_rpc_error(-26, "insufficient fee", self.nodes[0].sendrawtransaction, dbl_tx_hex, True)
@@ -255,7 +255,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# 1 BTC fee is enough
dbl_tx = CTransaction()
dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- dbl_tx.vout = [CTxOut(initial_nValue - fee*n - 1*COIN, CScript([1]))]
+ dbl_tx.vout = [CTxOut(initial_nValue - fee * n - 1 * COIN, CScript([1] * 35))]
dbl_tx_hex = txToHex(dbl_tx)
self.nodes[0].sendrawtransaction(dbl_tx_hex, True)
@@ -275,7 +275,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
dbl_tx = CTransaction()
dbl_tx.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- dbl_tx.vout = [CTxOut(initial_nValue - 2*fee*n, CScript([1]))]
+ dbl_tx.vout = [CTxOut(initial_nValue - 2 * fee * n, CScript([1] * 35))]
dbl_tx_hex = txToHex(dbl_tx)
# This will raise an exception
assert_raises_rpc_error(-26, "too many potential replacements", self.nodes[0].sendrawtransaction, dbl_tx_hex, True)
@@ -290,7 +290,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
tx1a = CTransaction()
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- tx1a.vout = [CTxOut(1*COIN, CScript([b'a']))]
+ tx1a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))]
tx1a_hex = txToHex(tx1a)
self.nodes[0].sendrawtransaction(tx1a_hex, True)
@@ -311,7 +311,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
tx1a = CTransaction()
tx1a.vin = [CTxIn(utxo1, nSequence=0)]
- tx1a.vout = [CTxOut(int(1.1*COIN), CScript([b'a']))]
+ tx1a.vout = [CTxOut(int(1.1 * COIN), CScript([b'a' * 35]))]
tx1a_hex = txToHex(tx1a)
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
@@ -330,7 +330,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# Spend tx1a's output to test the indirect case.
tx1b = CTransaction()
tx1b.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0)]
- tx1b.vout = [CTxOut(1*COIN, CScript([b'a']))]
+ tx1b.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))]
tx1b_hex = txToHex(tx1b)
tx1b_txid = self.nodes[0].sendrawtransaction(tx1b_hex, True)
tx1b_txid = int(tx1b_txid, 16)
@@ -351,7 +351,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
tx1 = CTransaction()
tx1.vin = [CTxIn(confirmed_utxo)]
- tx1.vout = [CTxOut(1*COIN, CScript([b'a']))]
+ tx1.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))]
tx1_hex = txToHex(tx1)
self.nodes[0].sendrawtransaction(tx1_hex, True)
@@ -390,7 +390,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
for i in range(MAX_REPLACEMENT_LIMIT+1):
tx_i = CTransaction()
tx_i.vin = [CTxIn(COutPoint(txid, i), nSequence=0)]
- tx_i.vout = [CTxOut(split_value-fee, CScript([b'a']))]
+ tx_i.vout = [CTxOut(split_value - fee, CScript([b'a' * 35]))]
tx_i_hex = txToHex(tx_i)
self.nodes[0].sendrawtransaction(tx_i_hex, True)
@@ -423,14 +423,14 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# Create a non-opting in transaction
tx1a = CTransaction()
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0xffffffff)]
- tx1a.vout = [CTxOut(1*COIN, CScript([b'a']))]
+ tx1a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))]
tx1a_hex = txToHex(tx1a)
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
# Shouldn't be able to double-spend
tx1b = CTransaction()
tx1b.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- tx1b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))]
+ tx1b.vout = [CTxOut(int(0.9 * COIN), CScript([b'b' * 35]))]
tx1b_hex = txToHex(tx1b)
# This will raise an exception
@@ -441,14 +441,14 @@ class ReplaceByFeeTest(BitcoinTestFramework):
# Create a different non-opting in transaction
tx2a = CTransaction()
tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0xfffffffe)]
- tx2a.vout = [CTxOut(1*COIN, CScript([b'a']))]
+ tx2a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))]
tx2a_hex = txToHex(tx2a)
tx2a_txid = self.nodes[0].sendrawtransaction(tx2a_hex, True)
# Still shouldn't be able to double-spend
tx2b = CTransaction()
tx2b.vin = [CTxIn(tx1_outpoint, nSequence=0)]
- tx2b.vout = [CTxOut(int(0.9*COIN), CScript([b'b']))]
+ tx2b.vout = [CTxOut(int(0.9 * COIN), CScript([b'b' * 35]))]
tx2b_hex = txToHex(tx2b)
# This will raise an exception
@@ -471,12 +471,12 @@ class ReplaceByFeeTest(BitcoinTestFramework):
tx3b = CTransaction()
tx3b.vin = [CTxIn(COutPoint(tx1a_txid, 0), nSequence=0)]
- tx3b.vout = [CTxOut(int(0.5*COIN), CScript([b'e']))]
+ tx3b.vout = [CTxOut(int(0.5 * COIN), CScript([b'e' * 35]))]
tx3b_hex = txToHex(tx3b)
tx3c = CTransaction()
tx3c.vin = [CTxIn(COutPoint(tx2a_txid, 0), nSequence=0)]
- tx3c.vout = [CTxOut(int(0.5*COIN), CScript([b'f']))]
+ tx3c.vout = [CTxOut(int(0.5 * COIN), CScript([b'f' * 35]))]
tx3c_hex = txToHex(tx3c)
self.nodes[0].sendrawtransaction(tx3b_hex, True)
@@ -493,7 +493,7 @@ class ReplaceByFeeTest(BitcoinTestFramework):
tx1a = CTransaction()
tx1a.vin = [CTxIn(tx0_outpoint, nSequence=0)]
- tx1a.vout = [CTxOut(1*COIN, CScript([b'a']))]
+ tx1a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))]
tx1a_hex = txToHex(tx1a)
tx1a_txid = self.nodes[0].sendrawtransaction(tx1a_hex, True)
@@ -519,14 +519,14 @@ class ReplaceByFeeTest(BitcoinTestFramework):
tx2a = CTransaction()
tx2a.vin = [CTxIn(tx1_outpoint, nSequence=0)]
- tx2a.vout = [CTxOut(1*COIN, CScript([b'a']))]
+ tx2a.vout = [CTxOut(1 * COIN, CScript([b'a' * 35]))]
tx2a_hex = txToHex(tx2a)
self.nodes[0].sendrawtransaction(tx2a_hex, True)
# Lower fee, but we'll prioritise it
tx2b = CTransaction()
tx2b.vin = [CTxIn(tx1_outpoint, nSequence=0)]
- tx2b.vout = [CTxOut(int(1.01*COIN), CScript([b'a']))]
+ tx2b.vout = [CTxOut(int(1.01 * COIN), CScript([b'a' * 35]))]
tx2b.rehash()
tx2b_hex = txToHex(tx2b)
diff --git a/test/functional/feature_segwit.py b/test/functional/feature_segwit.py
index fa1732c4c5..3622e1834a 100755
--- a/test/functional/feature_segwit.py
+++ b/test/functional/feature_segwit.py
@@ -16,7 +16,7 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
from test_framework.mininode import sha256, CTransaction, CTxIn, COutPoint, CTxOut, COIN, ToHex, FromHex
from test_framework.address import script_to_p2sh, key_to_p2pkh
-from test_framework.script import CScript, OP_HASH160, OP_CHECKSIG, OP_0, hash160, OP_EQUAL, OP_DUP, OP_EQUALVERIFY, OP_1, OP_2, OP_CHECKMULTISIG, OP_TRUE
+from test_framework.script import CScript, OP_HASH160, OP_CHECKSIG, OP_0, hash160, OP_EQUAL, OP_DUP, OP_EQUALVERIFY, OP_1, OP_2, OP_CHECKMULTISIG, OP_TRUE, OP_DROP
from io import BytesIO
NODE_0 = 0
@@ -150,19 +150,11 @@ class SegWitTest(BitcoinTestFramework):
self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][0], True) #block 426
self.skip_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][0], True) #block 427
- # TODO: An old node would see these txs without witnesses and be able to mine them
-
- self.log.info("Verify unsigned bare witness txs in versionbits-setting blocks are valid before the fork")
- self.success_mine(self.nodes[2], wit_ids[NODE_2][WIT_V0][1], False) #block 428
- self.success_mine(self.nodes[2], wit_ids[NODE_2][WIT_V1][1], False) #block 429
-
self.log.info("Verify unsigned p2sh witness txs without a redeem script are invalid")
self.fail_accept(self.nodes[2], "mandatory-script-verify-flag", p2sh_ids[NODE_2][WIT_V0][1], False)
self.fail_accept(self.nodes[2], "mandatory-script-verify-flag", p2sh_ids[NODE_2][WIT_V1][1], False)
- self.log.info("Verify unsigned p2sh witness txs with a redeem script in versionbits-settings blocks are valid before the fork")
- self.success_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V0][1], False, witness_script(False, self.pubkey[2])) #block 430
- self.success_mine(self.nodes[2], p2sh_ids[NODE_2][WIT_V1][1], False, witness_script(True, self.pubkey[2])) #block 431
+ self.nodes[2].generate(4) # blocks 428-431
self.log.info("Verify previous witness txs skipped for mining can now be mined")
assert_equal(len(self.nodes[2].getrawmempool()), 4)
@@ -220,7 +212,7 @@ class SegWitTest(BitcoinTestFramework):
# Now create tx2, which will spend from txid1.
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(int(txid1, 16), 0), b''))
- tx.vout.append(CTxOut(int(49.99*COIN), CScript([OP_TRUE])))
+ tx.vout.append(CTxOut(int(49.99 * COIN), CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])))
tx2_hex = self.nodes[0].signrawtransactionwithwallet(ToHex(tx))['hex']
txid2 = self.nodes[0].sendrawtransaction(tx2_hex)
tx = FromHex(CTransaction(), tx2_hex)
@@ -229,7 +221,7 @@ class SegWitTest(BitcoinTestFramework):
# Now create tx3, which will spend from txid2
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(int(txid2, 16), 0), b""))
- tx.vout.append(CTxOut(int(49.95*COIN), CScript([OP_TRUE]))) # Huge fee
+ tx.vout.append(CTxOut(int(49.95 * COIN), CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))) # Huge fee
tx.calc_sha256()
txid3 = self.nodes[0].sendrawtransaction(ToHex(tx))
assert(tx.wit.is_null())
@@ -311,8 +303,10 @@ class SegWitTest(BitcoinTestFramework):
v = self.nodes[0].getaddressinfo(i)
if (v['isscript']):
[bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v)
- # bare and p2sh multisig with compressed keys should always be spendable
- spendable_anytime.extend([bare, p2sh])
+ # p2sh multisig with compressed keys should always be spendable
+ spendable_anytime.extend([p2sh])
+ # bare multisig can be watched and signed, but is not treated as ours
+ solvable_after_importaddress.extend([bare])
# P2WSH and P2SH(P2WSH) multisig with compressed keys are spendable after direct importaddress
spendable_after_importaddress.extend([p2wsh, p2sh_p2wsh])
else:
@@ -328,8 +322,10 @@ class SegWitTest(BitcoinTestFramework):
v = self.nodes[0].getaddressinfo(i)
if (v['isscript']):
[bare, p2sh, p2wsh, p2sh_p2wsh] = self.p2sh_address_to_script(v)
- # bare and p2sh multisig with uncompressed keys should always be spendable
- spendable_anytime.extend([bare, p2sh])
+ # p2sh multisig with uncompressed keys should always be spendable
+ spendable_anytime.extend([p2sh])
+ # bare multisig can be watched and signed, but is not treated as ours
+ solvable_after_importaddress.extend([bare])
# P2WSH and P2SH(P2WSH) multisig with uncompressed keys are never seen
unseen_anytime.extend([p2wsh, p2sh_p2wsh])
else:
diff --git a/test/functional/interface_rest.py b/test/functional/interface_rest.py
index 2ee33aa869..a48939d2e0 100755
--- a/test/functional/interface_rest.py
+++ b/test/functional/interface_rest.py
@@ -186,10 +186,10 @@ class RESTTest (BitcoinTestFramework):
self.test_rest_request("/getutxos/checkmempool", http_method='POST', req_type=ReqType.JSON, status=400, ret_type=RetType.OBJ)
# Test limits
- long_uri = '/'.join(["{}-{}".format(txid, n) for n in range(20)])
+ long_uri = '/'.join(["{}-{}".format(txid, n_) for n_ in range(20)])
self.test_rest_request("/getutxos/checkmempool/{}".format(long_uri), http_method='POST', status=400, ret_type=RetType.OBJ)
- long_uri = '/'.join(['{}-{}'.format(txid, n) for n in range(15)])
+ long_uri = '/'.join(['{}-{}'.format(txid, n_) for n_ in range(15)])
self.test_rest_request("/getutxos/checkmempool/{}".format(long_uri), http_method='POST', status=200)
self.nodes[0].generate(1) # generate block to not affect upcoming tests
diff --git a/test/functional/interface_zmq.py b/test/functional/interface_zmq.py
index 86ccea4394..af2e752b7a 100755
--- a/test/functional/interface_zmq.py
+++ b/test/functional/interface_zmq.py
@@ -4,7 +4,6 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the ZMQ notification interface."""
import configparser
-import os
import struct
from test_framework.test_framework import BitcoinTestFramework, SkipTest
@@ -47,8 +46,6 @@ class ZMQTest (BitcoinTestFramework):
# Check that bitcoin has been built with ZMQ enabled.
config = configparser.ConfigParser()
- if not self.options.configfile:
- self.options.configfile = os.path.abspath(os.path.join(os.path.dirname(__file__), "../config.ini"))
config.read_file(open(self.options.configfile))
if not config["components"].getboolean("ENABLE_ZMQ"):
diff --git a/test/functional/mempool_packages.py b/test/functional/mempool_packages.py
index 8880db8002..79cf159f43 100755
--- a/test/functional/mempool_packages.py
+++ b/test/functional/mempool_packages.py
@@ -70,7 +70,10 @@ class MempoolPackagesTest(BitcoinTestFramework):
assert_equal(mempool[x]['descendantcount'], descendant_count)
descendant_fees += mempool[x]['fee']
assert_equal(mempool[x]['modifiedfee'], mempool[x]['fee'])
+ assert_equal(mempool[x]['fees']['base'], mempool[x]['fee'])
+ assert_equal(mempool[x]['fees']['modified'], mempool[x]['modifiedfee'])
assert_equal(mempool[x]['descendantfees'], descendant_fees * COIN)
+ assert_equal(mempool[x]['fees']['descendant'], descendant_fees)
descendant_size += mempool[x]['size']
assert_equal(mempool[x]['descendantsize'], descendant_size)
descendant_count += 1
@@ -132,6 +135,7 @@ class MempoolPackagesTest(BitcoinTestFramework):
ancestor_fees = 0
for x in chain:
ancestor_fees += mempool[x]['fee']
+ assert_equal(mempool[x]['fees']['ancestor'], ancestor_fees + Decimal('0.00001'))
assert_equal(mempool[x]['ancestorfees'], ancestor_fees * COIN + 1000)
# Undo the prioritisetransaction for later tests
@@ -145,6 +149,7 @@ class MempoolPackagesTest(BitcoinTestFramework):
descendant_fees = 0
for x in reversed(chain):
descendant_fees += mempool[x]['fee']
+ assert_equal(mempool[x]['fees']['descendant'], descendant_fees + Decimal('0.00001'))
assert_equal(mempool[x]['descendantfees'], descendant_fees * COIN + 1000)
# Adding one more transaction on to the chain should fail.
@@ -170,7 +175,9 @@ class MempoolPackagesTest(BitcoinTestFramework):
descendant_fees += mempool[x]['fee']
if (x == chain[-1]):
assert_equal(mempool[x]['modifiedfee'], mempool[x]['fee']+satoshi_round(0.00002))
+ assert_equal(mempool[x]['fees']['modified'], mempool[x]['fee']+satoshi_round(0.00002))
assert_equal(mempool[x]['descendantfees'], descendant_fees * COIN + 2000)
+ assert_equal(mempool[x]['fees']['descendant'], descendant_fees+satoshi_round(0.00002))
# TODO: check that node1's mempool is as expected
diff --git a/test/functional/mining_prioritisetransaction.py b/test/functional/mining_prioritisetransaction.py
index e754dd31ad..85f1af6682 100755
--- a/test/functional/mining_prioritisetransaction.py
+++ b/test/functional/mining_prioritisetransaction.py
@@ -120,7 +120,7 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
tx_id = self.nodes[0].decoderawtransaction(tx_hex)["txid"]
# This will raise an exception due to min relay fee not being met
- assert_raises_rpc_error(-26, "min relay fee not met (code 66)", self.nodes[0].sendrawtransaction, tx_hex)
+ assert_raises_rpc_error(-26, "min relay fee not met", self.nodes[0].sendrawtransaction, tx_hex)
assert(tx_id not in self.nodes[0].getrawmempool())
# This is a less than 1000-byte transaction, so just set the fee
diff --git a/test/functional/p2p_compactblocks.py b/test/functional/p2p_compactblocks.py
index 1657d97281..cb4c9867a3 100755
--- a/test/functional/p2p_compactblocks.py
+++ b/test/functional/p2p_compactblocks.py
@@ -12,7 +12,8 @@ from test_framework.mininode import *
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
from test_framework.blocktools import create_block, create_coinbase, add_witness_commitment
-from test_framework.script import CScript, OP_TRUE
+from test_framework.script import CScript, OP_TRUE, OP_DROP
+
# TestP2PConn: A peer we use to send messages to bitcoind, and store responses.
class TestP2PConn(P2PInterface):
@@ -423,7 +424,7 @@ class CompactBlocksTest(BitcoinTestFramework):
for i in range(num_transactions):
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(utxo[0], utxo[1]), b''))
- tx.vout.append(CTxOut(utxo[2] - 1000, CScript([OP_TRUE])))
+ tx.vout.append(CTxOut(utxo[2] - 1000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])))
tx.rehash()
utxo = [tx.sha256, 0, tx.vout[0].nValue]
block.vtx.append(tx)
diff --git a/test/functional/p2p_feefilter.py b/test/functional/p2p_feefilter.py
index 7c954cdca2..c304bbba85 100755
--- a/test/functional/p2p_feefilter.py
+++ b/test/functional/p2p_feefilter.py
@@ -69,7 +69,7 @@ class FeeFilterTest(BitcoinTestFramework):
# Change tx fee rate to 10 sat/byte and test they are no longer received
node1.settxfee(Decimal("0.00010000"))
[node1.sendtoaddress(node1.getnewaddress(), 1) for x in range(3)]
- sync_mempools(self.nodes) # must be sure node 0 has received all txs
+ sync_mempools(self.nodes) # must be sure node 0 has received all txs
# Send one transaction from node0 that should be received, so that we
# we can sync the test on receipt (if node1's txs were relayed, they'd
diff --git a/test/functional/p2p_invalid_tx.py b/test/functional/p2p_invalid_tx.py
index 69ce529ad6..a12c1d6023 100755
--- a/test/functional/p2p_invalid_tx.py
+++ b/test/functional/p2p_invalid_tx.py
@@ -6,24 +6,48 @@
In this test we connect to one node over p2p, and test tx requests."""
from test_framework.blocktools import create_block, create_coinbase, create_transaction
-from test_framework.messages import COIN
-from test_framework.mininode import network_thread_start, P2PDataStore
+from test_framework.messages import (
+ COIN,
+ COutPoint,
+ CTransaction,
+ CTxIn,
+ CTxOut,
+)
+from test_framework.mininode import network_thread_start, P2PDataStore, network_thread_join
from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (
+ assert_equal,
+ wait_until,
+)
-class InvalidTxRequestTest(BitcoinTestFramework):
+class InvalidTxRequestTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
self.setup_clean_chain = True
- self.extra_args = [["-whitelist=127.0.0.1"]]
+
+ def bootstrap_p2p(self, *, num_connections=1):
+ """Add a P2P connection to the node.
+
+ Helper to connect and wait for version handshake."""
+ for _ in range(num_connections):
+ self.nodes[0].add_p2p_connection(P2PDataStore())
+ network_thread_start()
+ self.nodes[0].p2p.wait_for_verack()
+
+ def reconnect_p2p(self, **kwargs):
+ """Tear down and bootstrap the P2P connection to the node.
+
+ The node gets disconnected several times in this test. This helper
+ method reconnects the p2p and restarts the network thread."""
+ self.nodes[0].disconnect_p2ps()
+ network_thread_join()
+ self.bootstrap_p2p(**kwargs)
def run_test(self):
- # Add p2p connection to node0
node = self.nodes[0] # convenience reference to the node
- node.add_p2p_connection(P2PDataStore())
- network_thread_start()
- node.p2p.wait_for_verack()
+ self.bootstrap_p2p() # Add one p2p connection to the node
best_block = self.nodes[0].getbestblockhash()
tip = int(best_block, 16)
@@ -44,12 +68,74 @@ class InvalidTxRequestTest(BitcoinTestFramework):
# b'\x64' is OP_NOTIF
# Transaction will be rejected with code 16 (REJECT_INVALID)
- tx1 = create_transaction(block1.vtx[0], 0, b'\x64', 50 * COIN - 12000)
- node.p2p.send_txs_and_test([tx1], node, success=False, reject_code=16, reject_reason=b'mandatory-script-verify-flag-failed (Invalid OP_IF construction)')
+ # and we get disconnected immediately
+ self.log.info('Test a transaction that is rejected')
+ tx1 = create_transaction(block1.vtx[0], 0, b'\x64' * 35, 50 * COIN - 12000)
+ node.p2p.send_txs_and_test([tx1], node, success=False, expect_disconnect=True)
+
+ # Make two p2p connections to provide the node with orphans
+ # * p2ps[0] will send valid orphan txs (one with low fee)
+ # * p2ps[1] will send an invalid orphan tx (and is later disconnected for that)
+ self.reconnect_p2p(num_connections=2)
+
+ self.log.info('Test orphan transaction handling ... ')
+ # Create a root transaction that we withold until all dependend transactions
+ # are sent out and in the orphan cache
+ SCRIPT_PUB_KEY_OP_TRUE = b'\x51\x75' * 15 + b'\x51'
+ tx_withhold = CTransaction()
+ tx_withhold.vin.append(CTxIn(outpoint=COutPoint(block1.vtx[0].sha256, 0)))
+ tx_withhold.vout.append(CTxOut(nValue=50 * COIN - 12000, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
+ tx_withhold.calc_sha256()
+
+ # Our first orphan tx with some outputs to create further orphan txs
+ tx_orphan_1 = CTransaction()
+ tx_orphan_1.vin.append(CTxIn(outpoint=COutPoint(tx_withhold.sha256, 0)))
+ tx_orphan_1.vout = [CTxOut(nValue=10 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE)] * 3
+ tx_orphan_1.calc_sha256()
+
+ # A valid transaction with low fee
+ tx_orphan_2_no_fee = CTransaction()
+ tx_orphan_2_no_fee.vin.append(CTxIn(outpoint=COutPoint(tx_orphan_1.sha256, 0)))
+ tx_orphan_2_no_fee.vout.append(CTxOut(nValue=10 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
+
+ # A valid transaction with sufficient fee
+ tx_orphan_2_valid = CTransaction()
+ tx_orphan_2_valid.vin.append(CTxIn(outpoint=COutPoint(tx_orphan_1.sha256, 1)))
+ tx_orphan_2_valid.vout.append(CTxOut(nValue=10 * COIN - 12000, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
+ tx_orphan_2_valid.calc_sha256()
+
+ # An invalid transaction with negative fee
+ tx_orphan_2_invalid = CTransaction()
+ tx_orphan_2_invalid.vin.append(CTxIn(outpoint=COutPoint(tx_orphan_1.sha256, 2)))
+ tx_orphan_2_invalid.vout.append(CTxOut(nValue=11 * COIN, scriptPubKey=SCRIPT_PUB_KEY_OP_TRUE))
+
+ self.log.info('Send the orphans ... ')
+ # Send valid orphan txs from p2ps[0]
+ node.p2p.send_txs_and_test([tx_orphan_1, tx_orphan_2_no_fee, tx_orphan_2_valid], node, success=False)
+ # Send invalid tx from p2ps[1]
+ node.p2ps[1].send_txs_and_test([tx_orphan_2_invalid], node, success=False)
+
+ assert_equal(0, node.getmempoolinfo()['size']) # Mempool should be empty
+ assert_equal(2, len(node.getpeerinfo())) # p2ps[1] is still connected
+
+ self.log.info('Send the withhold tx ... ')
+ node.p2p.send_txs_and_test([tx_withhold], node, success=True)
+
+ # Transactions that should end up in the mempool
+ expected_mempool = {
+ t.hash
+ for t in [
+ tx_withhold, # The transaction that is the root for all orphans
+ tx_orphan_1, # The orphan transaction that splits the coins
+ tx_orphan_2_valid, # The valid transaction (with sufficient fee)
+ ]
+ }
+ # Transactions that do not end up in the mempool
+ # tx_orphan_no_fee, because it has too low fee (p2ps[0] is not disconnected for relaying that tx)
+ # tx_orphan_invaid, because it has negative fee (p2ps[1] is disconnected for relaying that tx)
- # Verify valid transaction
- tx1 = create_transaction(block1.vtx[0], 0, b'', 50 * COIN - 12000)
- node.p2p.send_txs_and_test([tx1], node, success=True)
+ wait_until(lambda: 1 == len(node.getpeerinfo()), timeout=12) # p2ps[1] is no longer connected
+ assert_equal(expected_mempool, set(node.getrawmempool()))
if __name__ == '__main__':
diff --git a/test/functional/p2p_mempool.py b/test/functional/p2p_mempool.py
index 485a8af3d0..e54843b26f 100755
--- a/test/functional/p2p_mempool.py
+++ b/test/functional/p2p_mempool.py
@@ -30,6 +30,6 @@ class P2PMempoolTests(BitcoinTestFramework):
#mininode must be disconnected at this point
assert_equal(len(self.nodes[0].getpeerinfo()), 0)
-
+
if __name__ == '__main__':
P2PMempoolTests().main()
diff --git a/test/functional/p2p_segwit.py b/test/functional/p2p_segwit.py
index 5546bf6b29..e80a764477 100755
--- a/test/functional/p2p_segwit.py
+++ b/test/functional/p2p_segwit.py
@@ -10,6 +10,7 @@ from test_framework.util import *
from test_framework.script import *
from test_framework.blocktools import create_block, create_coinbase, add_witness_commitment, get_witness_script, WITNESS_COMMITMENT_HEADER
from test_framework.key import CECKey, CPubKey
+import math
import time
import random
from binascii import hexlify
@@ -47,7 +48,7 @@ def test_transaction_acceptance(rpc, p2p, tx, with_witness, accepted, reason=Non
with mininode_lock:
assert_equal(p2p.last_message["reject"].reason, reason)
-def test_witness_block(rpc, p2p, block, accepted, with_witness=True):
+def test_witness_block(rpc, p2p, block, accepted, with_witness=True, reason=None):
"""Send a block to the node and check that it's accepted
- Submit the block over the p2p interface
@@ -58,6 +59,10 @@ def test_witness_block(rpc, p2p, block, accepted, with_witness=True):
p2p.send_message(msg_block(block))
p2p.sync_with_ping()
assert_equal(rpc.getbestblockhash() == block.hash, accepted)
+ if (reason != None and not accepted):
+ # Check the rejection reason as well.
+ with mininode_lock:
+ assert_equal(p2p.last_message["reject"].reason, reason)
class TestP2PConn(P2PInterface):
def __init__(self):
@@ -68,11 +73,15 @@ class TestP2PConn(P2PInterface):
for inv in message.inv:
self.getdataset.add(inv.hash)
- def announce_tx_and_wait_for_getdata(self, tx, timeout=60):
+ def announce_tx_and_wait_for_getdata(self, tx, timeout=60, success=True):
with mininode_lock:
self.last_message.pop("getdata", None)
self.send_message(msg_inv(inv=[CInv(1, tx.sha256)]))
- self.wait_for_getdata(timeout)
+ if success:
+ self.wait_for_getdata(timeout)
+ else:
+ time.sleep(timeout)
+ assert not self.last_message.get("getdata")
def announce_block_and_wait_for_getdata(self, block, use_header, timeout=60):
with mininode_lock:
@@ -168,7 +177,7 @@ class SegWitTest(BitcoinTestFramework):
# Create a transaction that spends the coinbase
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(txid, 0), b""))
- tx.vout.append(CTxOut(49*100000000, CScript([OP_TRUE])))
+ tx.vout.append(CTxOut(49 * 100000000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])))
tx.calc_sha256()
# Check that serializing it with or without witness is the same
@@ -259,7 +268,7 @@ class SegWitTest(BitcoinTestFramework):
# Now create a new anyone-can-spend utxo for the next test.
tx4 = CTransaction()
tx4.vin.append(CTxIn(COutPoint(tx3.sha256, 0), CScript([p2sh_program])))
- tx4.vout.append(CTxOut(tx3.vout[0].nValue-1000, CScript([OP_TRUE])))
+ tx4.vout.append(CTxOut(tx3.vout[0].nValue - 1000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])))
tx4.rehash()
test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx3, False, True)
test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx4, False, True)
@@ -271,6 +280,80 @@ class SegWitTest(BitcoinTestFramework):
self.utxo.pop(0)
self.utxo.append(UTXO(tx4.sha256, 0, tx4.vout[0].nValue))
+ # ~6 months after segwit activation, the SCRIPT_VERIFY_WITNESS flag was
+ # backdated so that it applies to all blocks, going back to the genesis
+ # block.
+ #
+ # Consequently, version 0 witness outputs are never spendable without
+ # witness, and so can't be spent before segwit activation (the point at which
+ # blocks are permitted to contain witnesses).
+ def test_v0_outputs_arent_spendable(self):
+ self.log.info("Testing that v0 witness program outputs aren't spendable before activation")
+
+ assert len(self.utxo), "self.utxo is empty"
+
+ # Create two outputs, a p2wsh and p2sh-p2wsh
+ witness_program = CScript([OP_TRUE])
+ witness_hash = sha256(witness_program)
+ scriptPubKey = CScript([OP_0, witness_hash])
+
+ p2sh_pubkey = hash160(scriptPubKey)
+ p2sh_scriptPubKey = CScript([OP_HASH160, p2sh_pubkey, OP_EQUAL])
+
+ value = self.utxo[0].nValue // 3
+
+ tx = CTransaction()
+ tx.vin = [CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b'')]
+ tx.vout = [CTxOut(value, scriptPubKey), CTxOut(value, p2sh_scriptPubKey)]
+ tx.vout.append(CTxOut(value, CScript([OP_TRUE])))
+ tx.rehash()
+ txid = tx.sha256
+
+ # Add it to a block
+ block = self.build_next_block()
+ self.update_witness_block_with_transactions(block, [tx])
+ # Verify that segwit isn't activated. A block serialized with witness
+ # should be rejected prior to activation.
+ test_witness_block(self.nodes[0], self.test_node, block, accepted=False, with_witness=True, reason = b'unexpected-witness')
+ # Now send the block without witness. It should be accepted
+ test_witness_block(self.nodes[0], self.test_node, block, accepted=True, with_witness=False)
+
+ # Now try to spend the outputs. This should fail since SCRIPT_VERIFY_WITNESS is always enabled.
+ p2wsh_tx = CTransaction()
+ p2wsh_tx.vin = [CTxIn(COutPoint(txid, 0), b'')]
+ p2wsh_tx.vout = [CTxOut(value, CScript([OP_TRUE]))]
+ p2wsh_tx.wit.vtxinwit.append(CTxInWitness())
+ p2wsh_tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([OP_TRUE])]
+ p2wsh_tx.rehash()
+
+ p2sh_p2wsh_tx = CTransaction()
+ p2sh_p2wsh_tx.vin = [CTxIn(COutPoint(txid, 1), CScript([scriptPubKey]))]
+ p2sh_p2wsh_tx.vout = [CTxOut(value, CScript([OP_TRUE]))]
+ p2sh_p2wsh_tx.wit.vtxinwit.append(CTxInWitness())
+ p2sh_p2wsh_tx.wit.vtxinwit[0].scriptWitness.stack = [CScript([OP_TRUE])]
+ p2sh_p2wsh_tx.rehash()
+
+ for tx in [p2wsh_tx, p2sh_p2wsh_tx]:
+
+ block = self.build_next_block()
+ self.update_witness_block_with_transactions(block, [tx])
+
+ # When the block is serialized with a witness, the block will be rejected because witness
+ # data isn't allowed in blocks that don't commit to witness data.
+ test_witness_block(self.nodes[0], self.test_node, block, accepted=False, with_witness=True, reason=b'unexpected-witness')
+
+ # When the block is serialized without witness, validation fails because the transaction is
+ # invalid (transactions are always validated with SCRIPT_VERIFY_WITNESS so a segwit v0 transaction
+ # without a witness is invalid).
+ # Note: The reject reason for this failure could be
+ # 'block-validation-failed' (if script check threads > 1) or
+ # 'non-mandatory-script-verify-flag (Witness program was passed an
+ # empty witness)' (otherwise).
+ # TODO: support multiple acceptable reject reasons.
+ test_witness_block(self.nodes[0], self.test_node, block, accepted=False, with_witness=False)
+
+ self.utxo.pop(0)
+ self.utxo.append(UTXO(txid, 2, value))
# Mine enough blocks for segwit's vb state to be 'started'.
def advance_to_segwit_started(self):
@@ -450,7 +533,7 @@ class SegWitTest(BitcoinTestFramework):
block = self.build_next_block()
assert(len(self.utxo) > 0)
-
+
# Create a P2WSH transaction.
# The witness program will be a bunch of OP_2DROP's, followed by OP_TRUE.
# This should give us plenty of room to tweak the spending tx's
@@ -562,7 +645,7 @@ class SegWitTest(BitcoinTestFramework):
self.log.info("Testing extra witness data in tx")
assert(len(self.utxo) > 0)
-
+
block = self.build_next_block()
witness_program = CScript([OP_DROP, OP_TRUE])
@@ -730,7 +813,7 @@ class SegWitTest(BitcoinTestFramework):
witness_program = CScript([OP_DROP, OP_TRUE])
witness_hash = sha256(witness_program)
scriptPubKey = CScript([OP_0, witness_hash])
-
+
# Create a transaction that splits our utxo into many outputs
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
@@ -814,7 +897,7 @@ class SegWitTest(BitcoinTestFramework):
assert(len(self.utxo))
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
- tx.vout.append(CTxOut(self.utxo[0].nValue-1000, CScript([OP_TRUE])))
+ tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])))
tx.wit.vtxinwit.append(CTxInWitness())
tx.wit.vtxinwit[0].scriptWitness.stack = [ b'a' ]
tx.rehash()
@@ -829,12 +912,7 @@ class SegWitTest(BitcoinTestFramework):
# Since we haven't delivered the tx yet, inv'ing the same tx from
# a witness transaction ought not result in a getdata.
- try:
- self.test_node.announce_tx_and_wait_for_getdata(tx, timeout=2)
- self.log.error("Error: duplicate tx getdata!")
- assert(False)
- except AssertionError:
- pass
+ self.test_node.announce_tx_and_wait_for_getdata(tx, timeout=2, success=False)
# Delivering this transaction with witness should fail (no matter who
# its from)
@@ -866,7 +944,7 @@ class SegWitTest(BitcoinTestFramework):
assert(len(self.utxo))
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(self.utxo[0].sha256, self.utxo[0].n), b""))
- tx.vout.append(CTxOut(self.utxo[0].nValue-1000, CScript([OP_TRUE])))
+ tx.vout.append(CTxOut(self.utxo[0].nValue - 1000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE])))
tx.wit.vtxinwit.append(CTxInWitness())
tx.wit.vtxinwit[0].scriptWitness.stack = [ b'a' ]
tx.rehash()
@@ -910,7 +988,7 @@ class SegWitTest(BitcoinTestFramework):
test_transaction_acceptance(self.nodes[1].rpc, self.std_node, tx3, True, False, b'tx-size')
# Remove witness stuffing, instead add extra witness push on stack
- tx3.vout[0] = CTxOut(tx2.vout[0].nValue-1000, CScript([OP_TRUE]))
+ tx3.vout[0] = CTxOut(tx2.vout[0].nValue - 1000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))
tx3.wit.vtxinwit[0].scriptWitness.stack = [CScript([CScriptNum(1)]), witness_program ]
tx3.rehash()
@@ -930,8 +1008,10 @@ class SegWitTest(BitcoinTestFramework):
raw_tx = self.nodes[0].getrawtransaction(tx3.hash, 1)
assert_equal(int(raw_tx["hash"], 16), tx3.calc_sha256(True))
assert_equal(raw_tx["size"], len(tx3.serialize_with_witness()))
- vsize = (len(tx3.serialize_with_witness()) + 3*len(tx3.serialize_without_witness()) + 3) / 4
+ weight = len(tx3.serialize_with_witness()) + 3*len(tx3.serialize_without_witness())
+ vsize = math.ceil(weight / 4)
assert_equal(raw_tx["vsize"], vsize)
+ assert_equal(raw_tx["weight"], weight)
assert_equal(len(raw_tx["vin"][0]["txinwitness"]), 1)
assert_equal(raw_tx["vin"][0]["txinwitness"][0], hexlify(witness_program).decode('ascii'))
assert(vsize != raw_tx["size"])
@@ -1096,7 +1176,7 @@ class SegWitTest(BitcoinTestFramework):
# P2PKH output; just send tx's first output back to an anyone-can-spend.
sync_mempools([self.nodes[0], self.nodes[1]])
tx3.vin = [CTxIn(COutPoint(tx.sha256, 0), b"")]
- tx3.vout = [CTxOut(tx.vout[0].nValue-1000, CScript([OP_TRUE]))]
+ tx3.vout = [CTxOut(tx.vout[0].nValue - 1000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))]
tx3.wit.vtxinwit.append(CTxInWitness())
tx3.wit.vtxinwit[0].scriptWitness.stack = [witness_program]
tx3.rehash()
@@ -1104,7 +1184,7 @@ class SegWitTest(BitcoinTestFramework):
else:
# tx and tx2 didn't go anywhere; just clean up the p2sh_tx output.
tx3.vin = [CTxIn(COutPoint(p2sh_tx.sha256, 0), CScript([witness_program]))]
- tx3.vout = [CTxOut(p2sh_tx.vout[0].nValue-1000, witness_program)]
+ tx3.vout = [CTxOut(p2sh_tx.vout[0].nValue - 1000, CScript([OP_TRUE, OP_DROP] * 15 + [OP_TRUE]))]
tx3.rehash()
test_transaction_acceptance(self.nodes[0].rpc, self.test_node, tx3, with_witness=True, accepted=True)
@@ -1476,9 +1556,10 @@ class SegWitTest(BitcoinTestFramework):
block = self.build_next_block()
self.update_witness_block_with_transactions(block, [spend_tx])
- # If we're before activation, then sending this without witnesses
- # should be valid. If we're after activation, then sending this with
- # witnesses should be valid.
+ # If we're after activation, then sending this with witnesses should be valid.
+ # This no longer works before activation, because SCRIPT_VERIFY_WITNESS
+ # is always set.
+ # TODO: rewrite this test to make clear that it only works after activation.
if segwit_activated:
test_witness_block(self.nodes[0].rpc, self.test_node, block, accepted=True)
else:
@@ -1577,7 +1658,7 @@ class SegWitTest(BitcoinTestFramework):
tx2.wit.vtxinwit.append(CTxInWitness())
tx2.wit.vtxinwit[-1].scriptWitness.stack = [ witness_program ]
total_value += tx.vout[i].nValue
- tx2.wit.vtxinwit[-1].scriptWitness.stack = [ witness_program_toomany ]
+ tx2.wit.vtxinwit[-1].scriptWitness.stack = [ witness_program_toomany ]
tx2.vout.append(CTxOut(total_value, CScript([OP_TRUE])))
tx2.rehash()
@@ -1897,6 +1978,7 @@ class SegWitTest(BitcoinTestFramework):
self.test_witness_services() # Verifies NODE_WITNESS
self.test_non_witness_transaction() # non-witness tx's are accepted
self.test_unnecessary_witness_before_segwit_activation()
+ self.test_v0_outputs_arent_spendable()
self.test_block_relay(segwit_activated=False)
# Advance to segwit being 'started'
@@ -1914,7 +1996,6 @@ class SegWitTest(BitcoinTestFramework):
self.test_unnecessary_witness_before_segwit_activation()
self.test_witness_tx_relay_before_segwit_activation()
self.test_block_relay(segwit_activated=False)
- self.test_p2sh_witness(segwit_activated=False)
self.test_standardness_v0(segwit_activated=False)
sync_blocks(self.nodes)
diff --git a/test/functional/p2p_sendheaders.py b/test/functional/p2p_sendheaders.py
index 4c7d5e65c5..095cc4b734 100755
--- a/test/functional/p2p_sendheaders.py
+++ b/test/functional/p2p_sendheaders.py
@@ -116,6 +116,7 @@ class BaseNode(P2PInterface):
self.block_announced = False
self.last_blockhash_announced = None
+ self.recent_headers_announced = []
def send_get_data(self, block_hashes):
"""Request data for a list of block hashes."""
@@ -163,40 +164,45 @@ class BaseNode(P2PInterface):
def on_headers(self, message):
if len(message.headers):
self.block_announced = True
- message.headers[-1].calc_sha256()
+ for x in message.headers:
+ x.calc_sha256()
+ # append because headers may be announced over multiple messages.
+ self.recent_headers_announced.append(x.sha256)
self.last_blockhash_announced = message.headers[-1].sha256
- def clear_last_announcement(self):
+ def clear_block_announcements(self):
with mininode_lock:
self.block_announced = False
self.last_message.pop("inv", None)
self.last_message.pop("headers", None)
+ self.recent_headers_announced = []
- def check_last_announcement(self, headers=None, inv=None):
- """Test whether the last announcement received had the right header or the right inv.
- inv and headers should be lists of block hashes."""
+ def check_last_headers_announcement(self, headers):
+ """Test whether the last headers announcements received are right.
+ Headers may be announced across more than one message."""
+ test_function = lambda: (len(self.recent_headers_announced) >= len(headers))
+ wait_until(test_function, timeout=60, lock=mininode_lock)
+ with mininode_lock:
+ assert_equal(self.recent_headers_announced, headers)
+ self.block_announced = False
+ self.last_message.pop("headers", None)
+ self.recent_headers_announced = []
+
+ def check_last_inv_announcement(self, inv):
+ """Test whether the last announcement received had the right inv.
+ inv should be a list of block hashes."""
test_function = lambda: self.block_announced
wait_until(test_function, timeout=60, lock=mininode_lock)
with mininode_lock:
- self.block_announced = False
-
compare_inv = []
if "inv" in self.last_message:
compare_inv = [x.hash for x in self.last_message["inv"].inv]
- if inv is not None:
- assert_equal(compare_inv, inv)
-
- compare_headers = []
- if "headers" in self.last_message:
- compare_headers = [x.sha256 for x in self.last_message["headers"].headers]
- if headers is not None:
- assert_equal(compare_headers, headers)
-
+ assert_equal(compare_inv, inv)
+ self.block_announced = False
self.last_message.pop("inv", None)
- self.last_message.pop("headers", None)
class SendHeadersTest(BitcoinTestFramework):
def set_test_params(self):
@@ -206,8 +212,8 @@ class SendHeadersTest(BitcoinTestFramework):
def mine_blocks(self, count):
"""Mine count blocks and return the new tip."""
- # Clear out last block announcement from each p2p listener
- [x.clear_last_announcement() for x in self.nodes[0].p2ps]
+ # Clear out block announcements from each p2p listener
+ [x.clear_block_announcements() for x in self.nodes[0].p2ps]
self.nodes[0].generate(count)
return int(self.nodes[0].getbestblockhash(), 16)
@@ -222,7 +228,7 @@ class SendHeadersTest(BitcoinTestFramework):
sync_blocks(self.nodes, wait=0.1)
for x in self.nodes[0].p2ps:
x.wait_for_block_announcement(int(self.nodes[0].getbestblockhash(), 16))
- x.clear_last_announcement()
+ x.clear_block_announcements()
tip_height = self.nodes[1].getblockcount()
hash_to_invalidate = self.nodes[1].getblockhash(tip_height - (length - 1))
@@ -255,25 +261,25 @@ class SendHeadersTest(BitcoinTestFramework):
tip = self.nodes[0].getblockheader(self.nodes[0].generate(1)[0])
tip_hash = int(tip["hash"], 16)
- inv_node.check_last_announcement(inv=[tip_hash], headers=[])
- test_node.check_last_announcement(inv=[tip_hash], headers=[])
+ inv_node.check_last_inv_announcement(inv=[tip_hash])
+ test_node.check_last_inv_announcement(inv=[tip_hash])
self.log.info("Verify getheaders with null locator and valid hashstop returns headers.")
- test_node.clear_last_announcement()
+ test_node.clear_block_announcements()
test_node.send_get_headers(locator=[], hashstop=tip_hash)
- test_node.check_last_announcement(headers=[tip_hash])
+ test_node.check_last_headers_announcement(headers=[tip_hash])
self.log.info("Verify getheaders with null locator and invalid hashstop does not return headers.")
block = create_block(int(tip["hash"], 16), create_coinbase(tip["height"] + 1), tip["mediantime"] + 1)
block.solve()
test_node.send_header_for_blocks([block])
- test_node.clear_last_announcement()
+ test_node.clear_block_announcements()
test_node.send_get_headers(locator=[], hashstop=int(block.hash, 16))
test_node.sync_with_ping()
assert_equal(test_node.block_announced, False)
- inv_node.clear_last_announcement()
+ inv_node.clear_block_announcements()
test_node.send_message(msg_block(block))
- inv_node.check_last_announcement(inv=[int(block.hash, 16)], headers=[])
+ inv_node.check_last_inv_announcement(inv=[int(block.hash, 16)])
def test_nonnull_locators(self, test_node, inv_node):
tip = int(self.nodes[0].getbestblockhash(), 16)
@@ -284,8 +290,8 @@ class SendHeadersTest(BitcoinTestFramework):
for i in range(4):
old_tip = tip
tip = self.mine_blocks(1)
- inv_node.check_last_announcement(inv=[tip], headers=[])
- test_node.check_last_announcement(inv=[tip], headers=[])
+ inv_node.check_last_inv_announcement(inv=[tip])
+ test_node.check_last_inv_announcement(inv=[tip])
# Try a few different responses; none should affect next announcement
if i == 0:
# first request the block
@@ -296,7 +302,7 @@ class SendHeadersTest(BitcoinTestFramework):
test_node.send_get_headers(locator=[old_tip], hashstop=tip)
test_node.send_get_data([tip])
test_node.wait_for_block(tip)
- test_node.clear_last_announcement() # since we requested headers...
+ test_node.clear_block_announcements() # since we requested headers...
elif i == 2:
# this time announce own block via headers
height = self.nodes[0].getblockcount()
@@ -308,8 +314,8 @@ class SendHeadersTest(BitcoinTestFramework):
test_node.wait_for_getdata([new_block.sha256])
test_node.send_message(msg_block(new_block))
test_node.sync_with_ping() # make sure this block is processed
- inv_node.clear_last_announcement()
- test_node.clear_last_announcement()
+ inv_node.clear_block_announcements()
+ test_node.clear_block_announcements()
self.log.info("Part 1: success!")
self.log.info("Part 2: announce blocks with headers after sendheaders message...")
@@ -323,8 +329,8 @@ class SendHeadersTest(BitcoinTestFramework):
# Now that we've synced headers, headers announcements should work
tip = self.mine_blocks(1)
- inv_node.check_last_announcement(inv=[tip], headers=[])
- test_node.check_last_announcement(headers=[tip])
+ inv_node.check_last_inv_announcement(inv=[tip])
+ test_node.check_last_headers_announcement(headers=[tip])
height = self.nodes[0].getblockcount() + 1
block_time += 10 # Advance far enough ahead
@@ -368,8 +374,8 @@ class SendHeadersTest(BitcoinTestFramework):
assert "inv" not in inv_node.last_message
assert "headers" not in inv_node.last_message
tip = self.mine_blocks(1)
- inv_node.check_last_announcement(inv=[tip], headers=[])
- test_node.check_last_announcement(headers=[tip])
+ inv_node.check_last_inv_announcement(inv=[tip])
+ test_node.check_last_headers_announcement(headers=[tip])
height += 1
block_time += 1
@@ -383,16 +389,16 @@ class SendHeadersTest(BitcoinTestFramework):
# First try mining a reorg that can propagate with header announcement
new_block_hashes = self.mine_reorg(length=7)
tip = new_block_hashes[-1]
- inv_node.check_last_announcement(inv=[tip], headers=[])
- test_node.check_last_announcement(headers=new_block_hashes)
+ inv_node.check_last_inv_announcement(inv=[tip])
+ test_node.check_last_headers_announcement(headers=new_block_hashes)
block_time += 8
# Mine a too-large reorg, which should be announced with a single inv
new_block_hashes = self.mine_reorg(length=8)
tip = new_block_hashes[-1]
- inv_node.check_last_announcement(inv=[tip], headers=[])
- test_node.check_last_announcement(inv=[tip], headers=[])
+ inv_node.check_last_inv_announcement(inv=[tip])
+ test_node.check_last_inv_announcement(inv=[tip])
block_time += 9
@@ -401,15 +407,15 @@ class SendHeadersTest(BitcoinTestFramework):
# Use getblocks/getdata
test_node.send_getblocks(locator=[fork_point])
- test_node.check_last_announcement(inv=new_block_hashes, headers=[])
+ test_node.check_last_inv_announcement(inv=new_block_hashes)
test_node.send_get_data(new_block_hashes)
test_node.wait_for_block(new_block_hashes[-1])
for i in range(3):
# Mine another block, still should get only an inv
tip = self.mine_blocks(1)
- inv_node.check_last_announcement(inv=[tip], headers=[])
- test_node.check_last_announcement(inv=[tip], headers=[])
+ inv_node.check_last_inv_announcement(inv=[tip])
+ test_node.check_last_inv_announcement(inv=[tip])
if i == 0:
self.log.debug("Just get the data -- shouldn't cause headers announcements to resume")
test_node.send_get_data([tip])
@@ -431,8 +437,8 @@ class SendHeadersTest(BitcoinTestFramework):
test_node.sync_with_ping()
# New blocks should now be announced with header
tip = self.mine_blocks(1)
- inv_node.check_last_announcement(inv=[tip], headers=[])
- test_node.check_last_announcement(headers=[tip])
+ inv_node.check_last_inv_announcement(inv=[tip])
+ test_node.check_last_headers_announcement(headers=[tip])
self.log.info("Part 3: success!")
diff --git a/test/functional/p2p_unrequested_blocks.py b/test/functional/p2p_unrequested_blocks.py
index 53b2856eb5..49c619a4ce 100755
--- a/test/functional/p2p_unrequested_blocks.py
+++ b/test/functional/p2p_unrequested_blocks.py
@@ -57,12 +57,8 @@ from test_framework.util import *
import time
from test_framework.blocktools import create_block, create_coinbase, create_transaction
-class AcceptBlockTest(BitcoinTestFramework):
- def add_options(self, parser):
- parser.add_option("--testbinary", dest="testbinary",
- default=os.getenv("BITCOIND", "bitcoind"),
- help="bitcoind binary to test")
+class AcceptBlockTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 2
diff --git a/test/functional/rpc_bind.py b/test/functional/rpc_bind.py
index 5b50520d3f..343e162058 100755
--- a/test/functional/rpc_bind.py
+++ b/test/functional/rpc_bind.py
@@ -4,7 +4,6 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test running bitcoind with the -rpcbind and -rpcallowip options."""
-import socket
import sys
from test_framework.test_framework import BitcoinTestFramework, SkipTest
@@ -20,6 +19,11 @@ class RPCBindTest(BitcoinTestFramework):
def setup_network(self):
self.add_nodes(self.num_nodes, None)
+ def add_options(self, parser):
+ parser.add_option("--ipv4", action='store_true', dest="run_ipv4", help="Run ipv4 tests only", default=False)
+ parser.add_option("--ipv6", action='store_true', dest="run_ipv6", help="Run ipv6 tests only", default=False)
+ parser.add_option("--nonloopback", action='store_true', dest="run_nonloopback", help="Run non-loopback tests only", default=False)
+
def run_bind_test(self, allow_ips, connect_to, addresses, expected):
'''
Start a node with requested rpcallowip and rpcbind parameters,
@@ -54,55 +58,69 @@ class RPCBindTest(BitcoinTestFramework):
def run_test(self):
# due to OS-specific network stats queries, this test works only on Linux
+ if sum([self.options.run_ipv4, self.options.run_ipv6, self.options.run_nonloopback]) > 1:
+ raise AssertionError("Only one of --ipv4, --ipv6 and --nonloopback can be set")
+
+ self.log.info("Check for linux")
if not sys.platform.startswith('linux'):
- raise SkipTest("This test can only be run on Linux.")
- # find the first non-loopback interface for testing
- non_loopback_ip = None
+ raise SkipTest("This test can only be run on linux.")
+
+ self.log.info("Check for ipv6")
+ have_ipv6 = test_ipv6_local()
+ if not have_ipv6 and not self.options.run_ipv4:
+ raise SkipTest("This test requires ipv6 support.")
+
+ self.log.info("Check for non-loopback interface")
+ self.non_loopback_ip = None
for name,ip in all_interfaces():
if ip != '127.0.0.1':
- non_loopback_ip = ip
+ self.non_loopback_ip = ip
break
- if non_loopback_ip is None:
- raise SkipTest("This test requires at least one non-loopback IPv4 interface.")
- try:
- s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
- s.connect(("::1",1))
- s.close
- except OSError:
- raise SkipTest("This test requires IPv6 support.")
-
- self.log.info("Using interface %s for testing" % non_loopback_ip)
-
- defaultport = rpc_port(0)
-
- # check default without rpcallowip (IPv4 and IPv6 localhost)
- self.run_bind_test(None, '127.0.0.1', [],
- [('127.0.0.1', defaultport), ('::1', defaultport)])
- # check default with rpcallowip (IPv6 any)
- self.run_bind_test(['127.0.0.1'], '127.0.0.1', [],
- [('::0', defaultport)])
- # check only IPv4 localhost (explicit)
- self.run_bind_test(['127.0.0.1'], '127.0.0.1', ['127.0.0.1'],
- [('127.0.0.1', defaultport)])
- # check only IPv4 localhost (explicit) with alternative port
- self.run_bind_test(['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171'],
- [('127.0.0.1', 32171)])
- # check only IPv4 localhost (explicit) with multiple alternative ports on same host
- self.run_bind_test(['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171', '127.0.0.1:32172'],
- [('127.0.0.1', 32171), ('127.0.0.1', 32172)])
- # check only IPv6 localhost (explicit)
- self.run_bind_test(['[::1]'], '[::1]', ['[::1]'],
- [('::1', defaultport)])
- # check both IPv4 and IPv6 localhost (explicit)
- self.run_bind_test(['127.0.0.1'], '127.0.0.1', ['127.0.0.1', '[::1]'],
- [('127.0.0.1', defaultport), ('::1', defaultport)])
+ if self.non_loopback_ip is None and self.options.run_nonloopback:
+ raise SkipTest("This test requires a non-loopback ip address.")
+
+ self.defaultport = rpc_port(0)
+
+ if not self.options.run_nonloopback:
+ self._run_loopback_tests()
+ if not self.options.run_ipv4 and not self.options.run_ipv6:
+ self._run_nonloopback_tests()
+
+ def _run_loopback_tests(self):
+ if self.options.run_ipv4:
+ # check only IPv4 localhost (explicit)
+ self.run_bind_test(['127.0.0.1'], '127.0.0.1', ['127.0.0.1'],
+ [('127.0.0.1', self.defaultport)])
+ # check only IPv4 localhost (explicit) with alternative port
+ self.run_bind_test(['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171'],
+ [('127.0.0.1', 32171)])
+ # check only IPv4 localhost (explicit) with multiple alternative ports on same host
+ self.run_bind_test(['127.0.0.1'], '127.0.0.1:32171', ['127.0.0.1:32171', '127.0.0.1:32172'],
+ [('127.0.0.1', 32171), ('127.0.0.1', 32172)])
+ else:
+ # check default without rpcallowip (IPv4 and IPv6 localhost)
+ self.run_bind_test(None, '127.0.0.1', [],
+ [('127.0.0.1', self.defaultport), ('::1', self.defaultport)])
+ # check default with rpcallowip (IPv6 any)
+ self.run_bind_test(['127.0.0.1'], '127.0.0.1', [],
+ [('::0', self.defaultport)])
+ # check only IPv6 localhost (explicit)
+ self.run_bind_test(['[::1]'], '[::1]', ['[::1]'],
+ [('::1', self.defaultport)])
+ # check both IPv4 and IPv6 localhost (explicit)
+ self.run_bind_test(['127.0.0.1'], '127.0.0.1', ['127.0.0.1', '[::1]'],
+ [('127.0.0.1', self.defaultport), ('::1', self.defaultport)])
+
+ def _run_nonloopback_tests(self):
+ self.log.info("Using interface %s for testing" % self.non_loopback_ip)
+
# check only non-loopback interface
- self.run_bind_test([non_loopback_ip], non_loopback_ip, [non_loopback_ip],
- [(non_loopback_ip, defaultport)])
+ self.run_bind_test([self.non_loopback_ip], self.non_loopback_ip, [self.non_loopback_ip],
+ [(self.non_loopback_ip, self.defaultport)])
# Check that with invalid rpcallowip, we are denied
- self.run_allowip_test([non_loopback_ip], non_loopback_ip, defaultport)
- assert_raises_rpc_error(-342, "non-JSON HTTP response with '403 Forbidden' from server", self.run_allowip_test, ['1.1.1.1'], non_loopback_ip, defaultport)
+ self.run_allowip_test([self.non_loopback_ip], self.non_loopback_ip, self.defaultport)
+ assert_raises_rpc_error(-342, "non-JSON HTTP response with '403 Forbidden' from server", self.run_allowip_test, ['1.1.1.1'], self.non_loopback_ip, self.defaultport)
if __name__ == '__main__':
RPCBindTest().main()
diff --git a/test/functional/rpc_decodescript.py b/test/functional/rpc_decodescript.py
index 1ffc570437..d588151768 100755
--- a/test/functional/rpc_decodescript.py
+++ b/test/functional/rpc_decodescript.py
@@ -50,8 +50,11 @@ class DecodeScriptTest(BitcoinTestFramework):
def decodescript_script_pub_key(self):
public_key = '03b0da749730dc9b4b1f4a14d6902877a92541f5368778853d9c4a0cb7802dcfb2'
push_public_key = '21' + public_key
- public_key_hash = '11695b6cd891484c2d49ec5aa738ec2b2f897777'
+ public_key_hash = '5dd1d3a048119c27b28293056724d9522f26d945'
push_public_key_hash = '14' + public_key_hash
+ uncompressed_public_key = '04b0da749730dc9b4b1f4a14d6902877a92541f5368778853d9c4a0cb7802dcfb25e01fc8fde47c96c98a4f3a8123e33a38a50cf9025cc8c4494a518f991792bb7'
+ push_uncompressed_public_key = '41' + uncompressed_public_key
+ p2wsh_p2pk_script_hash = 'd8590cf8ea0674cf3d49fd7ca249b85ef7485dea62c138468bddeb20cd6519f7'
# below are test cases for all of the standard transaction types
@@ -59,18 +62,26 @@ class DecodeScriptTest(BitcoinTestFramework):
# <pubkey> OP_CHECKSIG
rpc_result = self.nodes[0].decodescript(push_public_key + 'ac')
assert_equal(public_key + ' OP_CHECKSIG', rpc_result['asm'])
+ # P2PK is translated to P2WPKH
+ assert_equal('0 ' + public_key_hash, rpc_result['segwit']['asm'])
# 2) P2PKH scriptPubKey
# OP_DUP OP_HASH160 <PubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
rpc_result = self.nodes[0].decodescript('76a9' + push_public_key_hash + '88ac')
assert_equal('OP_DUP OP_HASH160 ' + public_key_hash + ' OP_EQUALVERIFY OP_CHECKSIG', rpc_result['asm'])
+ # P2PKH is translated to P2WPKH
+ assert_equal('0 ' + public_key_hash, rpc_result['segwit']['asm'])
# 3) multisig scriptPubKey
# <m> <A pubkey> <B pubkey> <C pubkey> <n> OP_CHECKMULTISIG
# just imagine that the pub keys used below are different.
# for our purposes here it does not matter that they are the same even though it is unrealistic.
- rpc_result = self.nodes[0].decodescript('52' + push_public_key + push_public_key + push_public_key + '53ae')
+ multisig_script = '52' + push_public_key + push_public_key + push_public_key + '53ae'
+ rpc_result = self.nodes[0].decodescript(multisig_script)
assert_equal('2 ' + public_key + ' ' + public_key + ' ' + public_key + ' 3 OP_CHECKMULTISIG', rpc_result['asm'])
+ # multisig in P2WSH
+ multisig_script_hash = bytes_to_hex_str(sha256(hex_str_to_bytes(multisig_script)))
+ assert_equal('0 ' + multisig_script_hash, rpc_result['segwit']['asm'])
# 4) P2SH scriptPubKey
# OP_HASH160 <Hash160(redeemScript)> OP_EQUAL.
@@ -78,6 +89,8 @@ class DecodeScriptTest(BitcoinTestFramework):
# but this works the same for purposes of this test.
rpc_result = self.nodes[0].decodescript('a9' + push_public_key_hash + '87')
assert_equal('OP_HASH160 ' + public_key_hash + ' OP_EQUAL', rpc_result['asm'])
+ # P2SH does not work in segwit secripts. decodescript should not return a result for it.
+ assert 'segwit' not in rpc_result
# 5) null data scriptPubKey
# use a signature look-alike here to make sure that we do not decode random data as a signature.
@@ -101,8 +114,49 @@ class DecodeScriptTest(BitcoinTestFramework):
# <sender-pubkey> OP_CHECKSIG
#
# lock until block 500,000
- rpc_result = self.nodes[0].decodescript('63' + push_public_key + 'ad670320a107b17568' + push_public_key + 'ac')
+ cltv_script = '63' + push_public_key + 'ad670320a107b17568' + push_public_key + 'ac'
+ rpc_result = self.nodes[0].decodescript(cltv_script)
assert_equal('OP_IF ' + public_key + ' OP_CHECKSIGVERIFY OP_ELSE 500000 OP_CHECKLOCKTIMEVERIFY OP_DROP OP_ENDIF ' + public_key + ' OP_CHECKSIG', rpc_result['asm'])
+ # CLTV script in P2WSH
+ cltv_script_hash = bytes_to_hex_str(sha256(hex_str_to_bytes(cltv_script)))
+ assert_equal('0 ' + cltv_script_hash, rpc_result['segwit']['asm'])
+
+ # 7) P2PK scriptPubKey
+ # <pubkey> OP_CHECKSIG
+ rpc_result = self.nodes[0].decodescript(push_uncompressed_public_key + 'ac')
+ assert_equal(uncompressed_public_key + ' OP_CHECKSIG', rpc_result['asm'])
+ # uncompressed pubkeys are invalid for checksigs in segwit scripts.
+ # decodescript should not return a P2WPKH equivalent.
+ assert 'segwit' not in rpc_result
+
+ # 8) multisig scriptPubKey with an uncompressed pubkey
+ # <m> <A pubkey> <B pubkey> <n> OP_CHECKMULTISIG
+ # just imagine that the pub keys used below are different.
+ # the purpose of this test is to check that a segwit script is not returned for bare multisig scripts
+ # with an uncompressed pubkey in them.
+ rpc_result = self.nodes[0].decodescript('52' + push_public_key + push_uncompressed_public_key +'52ae')
+ assert_equal('2 ' + public_key + ' ' + uncompressed_public_key + ' 2 OP_CHECKMULTISIG', rpc_result['asm'])
+ # uncompressed pubkeys are invalid for checksigs in segwit scripts.
+ # decodescript should not return a P2WPKH equivalent.
+ assert 'segwit' not in rpc_result
+
+ # 9) P2WPKH scriptpubkey
+ # 0 <PubKeyHash>
+ rpc_result = self.nodes[0].decodescript('00' + push_public_key_hash)
+ assert_equal('0 ' + public_key_hash, rpc_result['asm'])
+ # segwit scripts do not work nested into each other.
+ # a nested segwit script should not be returned in the results.
+ assert 'segwit' not in rpc_result
+
+ # 10) P2WSH scriptpubkey
+ # 0 <ScriptHash>
+ # even though this hash is of a P2PK script which is better used as bare P2WPKH, it should not matter
+ # for the purpose of this test.
+ rpc_result = self.nodes[0].decodescript('0020' + p2wsh_p2pk_script_hash)
+ assert_equal('0 ' + p2wsh_p2pk_script_hash, rpc_result['asm'])
+ # segwit scripts do not work nested into each other.
+ # a nested segwit script should not be returned in the results.
+ assert 'segwit' not in rpc_result
def decoderawtransaction_asm_sighashtype(self):
"""Test decoding scripts via RPC command "decoderawtransaction".
diff --git a/test/functional/rpc_deprecated.py b/test/functional/rpc_deprecated.py
index b94b9d8fae..2e0500e7c4 100755
--- a/test/functional/rpc_deprecated.py
+++ b/test/functional/rpc_deprecated.py
@@ -4,12 +4,13 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test deprecation of RPC calls."""
from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import assert_raises_rpc_error
class DeprecatedRpcTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
self.setup_clean_chain = True
- self.extra_args = [[], ["-deprecatedrpc=validateaddress"]]
+ self.extra_args = [[], ["-deprecatedrpc=validateaddress", "-deprecatedrpc=accounts"]]
def run_test(self):
# This test should be used to verify correct behaviour of deprecated
@@ -20,11 +21,93 @@ class DeprecatedRpcTest(BitcoinTestFramework):
# self.nodes[1].createmultisig(1, [self.nodes[1].getnewaddress()])
self.log.info("Test validateaddress deprecation")
- SOME_ADDRESS = "mnvGjUy3NMj67yJ6gkK5o9e5RS33Z2Vqcu" # This is just some random address to pass as a parameter to validateaddress
+ SOME_ADDRESS = "mnvGjUy3NMj67yJ6gkK5o9e5RS33Z2Vqcu" # This is just some random address to pass as a parameter to validateaddress
dep_validate_address = self.nodes[0].validateaddress(SOME_ADDRESS)
assert "ismine" not in dep_validate_address
not_dep_val = self.nodes[1].validateaddress(SOME_ADDRESS)
assert "ismine" in not_dep_val
+ self.log.info("Test accounts deprecation")
+ # The following account RPC methods are deprecated:
+ # - getaccount
+ # - getaccountaddress
+ # - getaddressesbyaccount
+ # - getreceivedbyaccount
+ # - listaccouts
+ # - listreceivedbyaccount
+ # - move
+ # - setaccount
+ #
+ # The following 'label' RPC methods are usable both with and without the
+ # -deprecatedrpc=accounts switch enabled.
+ # - getlabeladdress
+ # - getaddressesbylabel
+ # - getreceivedbylabel
+ # - listlabels
+ # - listreceivedbylabel
+ # - setlabel
+ #
+ address0 = self.nodes[0].getnewaddress()
+ self.nodes[0].generatetoaddress(101, address0)
+ self.sync_all()
+ address1 = self.nodes[1].getnewaddress()
+ self.nodes[1].generatetoaddress(101, address1)
+
+ self.log.info("- getaccount")
+ assert_raises_rpc_error(-32, "getaccount is deprecated", self.nodes[0].getaccount, address0)
+ self.nodes[1].getaccount(address1)
+
+ self.log.info("- setaccount")
+ assert_raises_rpc_error(-32, "setaccount is deprecated", self.nodes[0].setaccount, address0, "label0")
+ self.nodes[1].setaccount(address1, "label1")
+
+ self.log.info("- setlabel")
+ self.nodes[0].setlabel(address0, "label0")
+ self.nodes[1].setlabel(address1, "label1")
+
+ self.log.info("- getaccountaddress")
+ assert_raises_rpc_error(-32, "getaccountaddress is deprecated", self.nodes[0].getaccountaddress, "label0")
+ self.nodes[1].getaccountaddress("label1")
+
+ self.log.info("- getlabeladdress")
+ self.nodes[0].getlabeladdress("label0")
+ self.nodes[1].getlabeladdress("label1")
+
+ self.log.info("- getaddressesbyaccount")
+ assert_raises_rpc_error(-32, "getaddressesbyaccount is deprecated", self.nodes[0].getaddressesbyaccount, "label0")
+ self.nodes[1].getaddressesbyaccount("label1")
+
+ self.log.info("- getaddressesbylabel")
+ self.nodes[0].getaddressesbylabel("label0")
+ self.nodes[1].getaddressesbylabel("label1")
+
+ self.log.info("- getreceivedbyaccount")
+ assert_raises_rpc_error(-32, "getreceivedbyaccount is deprecated", self.nodes[0].getreceivedbyaccount, "label0")
+ self.nodes[1].getreceivedbyaccount("label1")
+
+ self.log.info("- getreceivedbylabel")
+ self.nodes[0].getreceivedbylabel("label0")
+ self.nodes[1].getreceivedbylabel("label1")
+
+ self.log.info("- listaccounts")
+ assert_raises_rpc_error(-32, "listaccounts is deprecated", self.nodes[0].listaccounts)
+ self.nodes[1].listaccounts()
+
+ self.log.info("- listlabels")
+ self.nodes[0].listlabels()
+ self.nodes[1].listlabels()
+
+ self.log.info("- listreceivedbyaccount")
+ assert_raises_rpc_error(-32, "listreceivedbyaccount is deprecated", self.nodes[0].listreceivedbyaccount)
+ self.nodes[1].listreceivedbyaccount()
+
+ self.log.info("- listreceivedbylabel")
+ self.nodes[0].listreceivedbylabel()
+ self.nodes[1].listreceivedbylabel()
+
+ self.log.info("- move")
+ assert_raises_rpc_error(-32, "move is deprecated", self.nodes[0].move, "label0", "label0b", 10)
+ self.nodes[1].move("label1", "label1b", 10)
+
if __name__ == '__main__':
DeprecatedRpcTest().main()
diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py
index 5fb9a361d9..1e91cf598c 100755
--- a/test/functional/rpc_fundrawtransaction.py
+++ b/test/functional/rpc_fundrawtransaction.py
@@ -4,8 +4,18 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the fundrawtransaction RPC."""
+from decimal import Decimal
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import *
+from test_framework.util import (
+ assert_equal,
+ assert_fee_amount,
+ assert_greater_than,
+ assert_greater_than_or_equal,
+ assert_raises_rpc_error,
+ connect_nodes_bi,
+ count_bytes,
+ find_vout_for_address,
+)
def get_unspent(listunspent, amount):
@@ -57,6 +67,11 @@ class RawTransactionsTest(BitcoinTestFramework):
watchonly_amount = Decimal(200)
self.nodes[3].importpubkey(watchonly_pubkey, "", True)
watchonly_txid = self.nodes[0].sendtoaddress(watchonly_address, watchonly_amount)
+
+ # Lock UTXO so nodes[0] doesn't accidentally spend it
+ watchonly_vout = find_vout_for_address(self.nodes[0], watchonly_txid, watchonly_address)
+ self.nodes[0].lockunspent(False, [{"txid": watchonly_txid, "vout": watchonly_vout}])
+
self.nodes[0].sendtoaddress(self.nodes[3].getnewaddress(), watchonly_amount / 10)
self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1.5)
@@ -224,7 +239,7 @@ class RawTransactionsTest(BitcoinTestFramework):
outputs = { self.nodes[0].getnewaddress() : Decimal(4.0) }
rawtx = self.nodes[2].createrawtransaction(inputs, outputs)
assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[2].fundrawtransaction, rawtx, {'change_type': None})
- assert_raises_rpc_error(-5, "Unknown change type", self.nodes[2].fundrawtransaction, rawtx, {'change_type': ''})
+ assert_raises_rpc_error(-5, "Unknown change type ''", self.nodes[2].fundrawtransaction, rawtx, {'change_type': ''})
rawtx = self.nodes[2].fundrawtransaction(rawtx, {'change_type': 'bech32'})
dec_tx = self.nodes[2].decoderawtransaction(rawtx['hex'])
assert_equal('witness_v0_keyhash', dec_tx['vout'][rawtx['changepos']]['scriptPubKey']['type'])
@@ -475,6 +490,9 @@ class RawTransactionsTest(BitcoinTestFramework):
connect_nodes_bi(self.nodes,1,2)
connect_nodes_bi(self.nodes,0,2)
connect_nodes_bi(self.nodes,0,3)
+ # Again lock the watchonly UTXO or nodes[0] may spend it, because
+ # lockunspent is memory-only and thus lost on restart
+ self.nodes[0].lockunspent(False, [{"txid": watchonly_txid, "vout": watchonly_vout}])
self.sync_all()
# drain the keypool
diff --git a/test/functional/rpc_rawtransaction.py b/test/functional/rpc_rawtransaction.py
index 658782e82a..48b4a4a9db 100755
--- a/test/functional/rpc_rawtransaction.py
+++ b/test/functional/rpc_rawtransaction.py
@@ -14,13 +14,10 @@ Test the following RPCs:
from collections import OrderedDict
from io import BytesIO
+from test_framework.messages import CTransaction, ToHex
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.messages import (
- CTransaction,
-)
from test_framework.util import *
-
class multidict(dict):
"""Dictionary that allows duplicate keys.
@@ -363,5 +360,23 @@ class RawTransactionsTest(BitcoinTestFramework):
decrawtx= self.nodes[0].decoderawtransaction(rawtx)
assert_equal(decrawtx['vin'][0]['sequence'], 4294967294)
+ ####################################
+ # TRANSACTION VERSION NUMBER TESTS #
+ ####################################
+
+ # Test the minimum transaction version number that fits in a signed 32-bit integer.
+ tx = CTransaction()
+ tx.nVersion = -0x80000000
+ rawtx = ToHex(tx)
+ decrawtx = self.nodes[0].decoderawtransaction(rawtx)
+ assert_equal(decrawtx['version'], -0x80000000)
+
+ # Test the maximum transaction version number that fits in a signed 32-bit integer.
+ tx = CTransaction()
+ tx.nVersion = 0x7fffffff
+ rawtx = ToHex(tx)
+ decrawtx = self.nodes[0].decoderawtransaction(rawtx)
+ assert_equal(decrawtx['version'], 0x7fffffff)
+
if __name__ == '__main__':
RawTransactionsTest().main()
diff --git a/test/functional/rpc_users.py b/test/functional/rpc_users.py
index 0ce412f74a..1ef59da5ad 100755
--- a/test/functional/rpc_users.py
+++ b/test/functional/rpc_users.py
@@ -14,6 +14,10 @@ from test_framework.util import (
import os
import http.client
import urllib.parse
+import subprocess
+from random import SystemRandom
+import string
+import configparser
class HTTPBasicsTest(BitcoinTestFramework):
@@ -27,9 +31,20 @@ class HTTPBasicsTest(BitcoinTestFramework):
rpcauth2 = "rpcauth=rt2:f8607b1a88861fac29dfccf9b52ff9f$ff36a0c23c8c62b4846112e50fa888416e94c17bfd4c42f88fd8f55ec6a3137e"
rpcuser = "rpcuser=rpcuser💻"
rpcpassword = "rpcpassword=rpcpassword🔑"
+
+ self.user = ''.join(SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(10))
+ config = configparser.ConfigParser()
+ config.read_file(open(self.options.configfile))
+ gen_rpcauth = config['environment']['RPCAUTH']
+ p = subprocess.Popen([gen_rpcauth, self.user], stdout=subprocess.PIPE, universal_newlines=True)
+ lines = p.stdout.read().splitlines()
+ rpcauth3 = lines[1]
+ self.password = lines[3]
+
with open(os.path.join(get_datadir_path(self.options.tmpdir, 0), "bitcoin.conf"), 'a', encoding='utf8') as f:
f.write(rpcauth+"\n")
f.write(rpcauth2+"\n")
+ f.write(rpcauth3+"\n")
with open(os.path.join(get_datadir_path(self.options.tmpdir, 1), "bitcoin.conf"), 'a', encoding='utf8') as f:
f.write(rpcuser+"\n")
f.write(rpcpassword+"\n")
@@ -51,6 +66,7 @@ class HTTPBasicsTest(BitcoinTestFramework):
password2 = "8/F3uMDw4KSEbw96U3CA1C4X05dkHDN2BPFjTgZW4KI="
authpairnew = "rt:"+password
+ self.log.info('Correct...')
headers = {"Authorization": "Basic " + str_to_b64str(authpair)}
conn = http.client.HTTPConnection(url.hostname, url.port)
@@ -61,6 +77,7 @@ class HTTPBasicsTest(BitcoinTestFramework):
conn.close()
#Use new authpair to confirm both work
+ self.log.info('Correct...')
headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)}
conn = http.client.HTTPConnection(url.hostname, url.port)
@@ -71,6 +88,7 @@ class HTTPBasicsTest(BitcoinTestFramework):
conn.close()
#Wrong login name with rt's password
+ self.log.info('Wrong...')
authpairnew = "rtwrong:"+password
headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)}
@@ -82,6 +100,7 @@ class HTTPBasicsTest(BitcoinTestFramework):
conn.close()
#Wrong password for rt
+ self.log.info('Wrong...')
authpairnew = "rt:"+password+"wrong"
headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)}
@@ -93,6 +112,7 @@ class HTTPBasicsTest(BitcoinTestFramework):
conn.close()
#Correct for rt2
+ self.log.info('Correct...')
authpairnew = "rt2:"+password2
headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)}
@@ -104,6 +124,7 @@ class HTTPBasicsTest(BitcoinTestFramework):
conn.close()
#Wrong password for rt2
+ self.log.info('Wrong...')
authpairnew = "rt2:"+password2+"wrong"
headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)}
@@ -114,12 +135,37 @@ class HTTPBasicsTest(BitcoinTestFramework):
assert_equal(resp.status, 401)
conn.close()
+ #Correct for randomly generated user
+ self.log.info('Correct...')
+ authpairnew = self.user+":"+self.password
+ headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)}
+
+ conn = http.client.HTTPConnection(url.hostname, url.port)
+ conn.connect()
+ conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
+ resp = conn.getresponse()
+ assert_equal(resp.status, 200)
+ conn.close()
+
+ #Wrong password for randomly generated user
+ self.log.info('Wrong...')
+ authpairnew = self.user+":"+self.password+"Wrong"
+ headers = {"Authorization": "Basic " + str_to_b64str(authpairnew)}
+
+ conn = http.client.HTTPConnection(url.hostname, url.port)
+ conn.connect()
+ conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
+ resp = conn.getresponse()
+ assert_equal(resp.status, 401)
+ conn.close()
+
###############################################################
# Check correctness of the rpcuser/rpcpassword config options #
###############################################################
url = urllib.parse.urlparse(self.nodes[1].url)
# rpcuser and rpcpassword authpair
+ self.log.info('Correct...')
rpcuserauthpair = "rpcuser💻:rpcpassword🔑"
headers = {"Authorization": "Basic " + str_to_b64str(rpcuserauthpair)}
@@ -143,6 +189,7 @@ class HTTPBasicsTest(BitcoinTestFramework):
conn.close()
#Wrong password for rpcuser
+ self.log.info('Wrong...')
rpcuserauthpair = "rpcuser:rpcpasswordwrong"
headers = {"Authorization": "Basic " + str_to_b64str(rpcuserauthpair)}
diff --git a/test/functional/test_framework/blocktools.py b/test/functional/test_framework/blocktools.py
index 43982cd09a..5c2b1815e5 100644
--- a/test/functional/test_framework/blocktools.py
+++ b/test/functional/test_framework/blocktools.py
@@ -10,7 +10,24 @@ from .address import (
script_to_p2sh_p2wsh,
script_to_p2wsh,
)
-from .mininode import *
+from .messages import (
+ CBlock,
+ COIN,
+ COutPoint,
+ CTransaction,
+ CTxIn,
+ CTxInWitness,
+ CTxOut,
+ FromHex,
+ ToHex,
+ bytes_to_hex_str,
+ hash256,
+ hex_str_to_bytes,
+ ser_string,
+ ser_uint256,
+ sha256,
+ uint256_from_str,
+)
from .script import (
CScript,
OP_0,
@@ -23,34 +40,34 @@ from .script import (
)
from .util import assert_equal
-# Create a block (with regtest difficulty)
-def create_block(hashprev, coinbase, nTime=None):
+# From BIP141
+WITNESS_COMMITMENT_HEADER = b"\xaa\x21\xa9\xed"
+
+def create_block(hashprev, coinbase, ntime=None):
+ """Create a block (with regtest difficulty)."""
block = CBlock()
- if nTime is None:
+ if ntime is None:
import time
- block.nTime = int(time.time()+600)
+ block.nTime = int(time.time() + 600)
else:
- block.nTime = nTime
+ block.nTime = ntime
block.hashPrevBlock = hashprev
- block.nBits = 0x207fffff # Will break after a difficulty adjustment...
+ block.nBits = 0x207fffff # difficulty retargeting is disabled in REGTEST chainparams
block.vtx.append(coinbase)
block.hashMerkleRoot = block.calc_merkle_root()
block.calc_sha256()
return block
-# From BIP141
-WITNESS_COMMITMENT_HEADER = b"\xaa\x21\xa9\xed"
-
-
def get_witness_script(witness_root, witness_nonce):
- witness_commitment = uint256_from_str(hash256(ser_uint256(witness_root)+ser_uint256(witness_nonce)))
+ witness_commitment = uint256_from_str(hash256(ser_uint256(witness_root) + ser_uint256(witness_nonce)))
output_data = WITNESS_COMMITMENT_HEADER + ser_uint256(witness_commitment)
return CScript([OP_RETURN, output_data])
-
-# According to BIP141, blocks with witness rules active must commit to the
-# hash of all in-block transactions including witness.
def add_witness_commitment(block, nonce=0):
+ """Add a witness commitment to the block's coinbase transaction.
+
+ According to BIP141, blocks with witness rules active must commit to the
+ hash of all in-block transactions including witness."""
# First calculate the merkle root of the block's
# transactions, with witnesses.
witness_nonce = nonce
@@ -65,7 +82,6 @@ def add_witness_commitment(block, nonce=0):
block.hashMerkleRoot = block.calc_merkle_root()
block.rehash()
-
def serialize_script_num(value):
r = bytearray(0)
if value == 0:
@@ -81,55 +97,59 @@ def serialize_script_num(value):
r[-1] |= 0x80
return r
-# Create a coinbase transaction, assuming no miner fees.
-# If pubkey is passed in, the coinbase output will be a P2PK output;
-# otherwise an anyone-can-spend output.
-def create_coinbase(height, pubkey = None):
+def create_coinbase(height, pubkey=None):
+ """Create a coinbase transaction, assuming no miner fees.
+
+ If pubkey is passed in, the coinbase output will be a P2PK output;
+ otherwise an anyone-can-spend output."""
coinbase = CTransaction()
- coinbase.vin.append(CTxIn(COutPoint(0, 0xffffffff),
- ser_string(serialize_script_num(height)), 0xffffffff))
+ coinbase.vin.append(CTxIn(COutPoint(0, 0xffffffff),
+ ser_string(serialize_script_num(height)), 0xffffffff))
coinbaseoutput = CTxOut()
coinbaseoutput.nValue = 50 * COIN
- halvings = int(height/150) # regtest
+ halvings = int(height / 150) # regtest
coinbaseoutput.nValue >>= halvings
- if (pubkey != None):
+ if (pubkey is not None):
coinbaseoutput.scriptPubKey = CScript([pubkey, OP_CHECKSIG])
else:
coinbaseoutput.scriptPubKey = CScript([OP_TRUE])
- coinbase.vout = [ coinbaseoutput ]
+ coinbase.vout = [coinbaseoutput]
coinbase.calc_sha256()
return coinbase
-# Create a transaction.
-# If the scriptPubKey is not specified, make it anyone-can-spend.
-def create_transaction(prevtx, n, sig, value, scriptPubKey=CScript()):
+def create_transaction(prevtx, n, sig, value, script_pub_key=CScript()):
+ """Create a transaction.
+
+ If the script_pub_key is not specified, make it anyone-can-spend."""
tx = CTransaction()
assert(n < len(prevtx.vout))
tx.vin.append(CTxIn(COutPoint(prevtx.sha256, n), sig, 0xffffffff))
- tx.vout.append(CTxOut(value, scriptPubKey))
+ tx.vout.append(CTxOut(value, script_pub_key))
tx.calc_sha256()
return tx
-def get_legacy_sigopcount_block(block, fAccurate=True):
+def get_legacy_sigopcount_block(block, accurate=True):
count = 0
for tx in block.vtx:
- count += get_legacy_sigopcount_tx(tx, fAccurate)
+ count += get_legacy_sigopcount_tx(tx, accurate)
return count
-def get_legacy_sigopcount_tx(tx, fAccurate=True):
+def get_legacy_sigopcount_tx(tx, accurate=True):
count = 0
for i in tx.vout:
- count += i.scriptPubKey.GetSigOpCount(fAccurate)
+ count += i.scriptPubKey.GetSigOpCount(accurate)
for j in tx.vin:
# scriptSig might be of type bytes, so convert to CScript for the moment
- count += CScript(j.scriptSig).GetSigOpCount(fAccurate)
+ count += CScript(j.scriptSig).GetSigOpCount(accurate)
return count
-# Create a scriptPubKey corresponding to either a P2WPKH output for the
-# given pubkey, or a P2WSH output of a 1-of-1 multisig for the given
-# pubkey. Returns the hex encoding of the scriptPubKey.
def witness_script(use_p2wsh, pubkey):
- if (use_p2wsh == False):
+ """Create a scriptPubKey for a pay-to-wtiness TxOut.
+
+ This is either a P2WPKH output for the given pubkey, or a P2WSH output of a
+ 1-of-1 multisig for the given pubkey. Returns the hex encoding of the
+ scriptPubKey."""
+ if not use_p2wsh:
# P2WPKH instead
pubkeyhash = hash160(hex_str_to_bytes(pubkey))
pkscript = CScript([OP_0, pubkeyhash])
@@ -140,9 +160,10 @@ def witness_script(use_p2wsh, pubkey):
pkscript = CScript([OP_0, scripthash])
return bytes_to_hex_str(pkscript)
-# Return a transaction (in hex) that spends the given utxo to a segwit output,
-# optionally wrapping the segwit output using P2SH.
def create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount):
+ """Return a transaction (in hex) that spends the given utxo to a segwit output.
+
+ Optionally wrap the segwit output using P2SH."""
if use_p2wsh:
program = CScript([OP_1, hex_str_to_bytes(pubkey), OP_1, OP_CHECKMULTISIG])
addr = script_to_p2sh_p2wsh(program) if encode_p2sh else script_to_p2wsh(program)
@@ -152,12 +173,13 @@ def create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount):
assert_equal(node.getaddressinfo(addr)['scriptPubKey'], witness_script(use_p2wsh, pubkey))
return node.createrawtransaction([utxo], {addr: amount})
-# Create a transaction spending a given utxo to a segwit output corresponding
-# to the given pubkey: use_p2wsh determines whether to use P2WPKH or P2WSH;
-# encode_p2sh determines whether to wrap in P2SH.
-# sign=True will have the given node sign the transaction.
-# insert_redeem_script will be added to the scriptSig, if given.
def send_to_witness(use_p2wsh, node, utxo, pubkey, encode_p2sh, amount, sign=True, insert_redeem_script=""):
+ """Create a transaction spending a given utxo to a segwit output.
+
+ The output corresponds to the given pubkey: use_p2wsh determines whether to
+ use P2WPKH or P2WSH; encode_p2sh determines whether to wrap in P2SH.
+ sign=True will have the given node sign the transaction.
+ insert_redeem_script will be added to the scriptSig, if given."""
tx_to_witness = create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount)
if (sign):
signed = node.signrawtransactionwithwallet(tx_to_witness)
diff --git a/test/functional/test_framework/key.py b/test/functional/test_framework/key.py
index aa91fb5b0d..1b3e510dc4 100644
--- a/test/functional/test_framework/key.py
+++ b/test/functional/test_framework/key.py
@@ -10,7 +10,6 @@ This file is modified from python-bitcoinlib.
import ctypes
import ctypes.util
import hashlib
-import sys
ssl = ctypes.cdll.LoadLibrary(ctypes.util.find_library ('ssl') or 'libeay32')
@@ -223,10 +222,5 @@ class CPubKey(bytes):
return repr(self)
def __repr__(self):
- # Always have represent as b'<secret>' so test cases don't have to
- # change for py2/3
- if sys.version > '3':
- return '%s(%s)' % (self.__class__.__name__, super(CPubKey, self).__repr__())
- else:
- return '%s(b%s)' % (self.__class__.__name__, super(CPubKey, self).__repr__())
+ return '%s(%s)' % (self.__class__.__name__, super(CPubKey, self).__repr__())
diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py
index aba2841682..7c2125a177 100755
--- a/test/functional/test_framework/mininode.py
+++ b/test/functional/test_framework/mininode.py
@@ -554,13 +554,13 @@ class P2PDataStore(P2PInterface):
if reject_reason is not None:
wait_until(lambda: self.reject_reason_received == reject_reason, lock=mininode_lock)
- def send_txs_and_test(self, txs, rpc, success=True, reject_code=None, reject_reason=None):
+ def send_txs_and_test(self, txs, rpc, success=True, expect_disconnect=False, reject_code=None, reject_reason=None):
"""Send txs to test node and test whether they're accepted to the mempool.
- add all txs to our tx_store
- send tx messages for all txs
- - if success is True: assert that the tx is accepted to the mempool
- - if success is False: assert that the tx is not accepted to the mempool
+ - if success is True/False: assert that the txs are/are not accepted to the mempool
+ - if expect_disconnect is True: Skip the sync with ping
- if reject_code and reject_reason are set: assert that the correct reject message is received."""
with mininode_lock:
@@ -573,7 +573,10 @@ class P2PDataStore(P2PInterface):
for tx in txs:
self.send_message(msg_tx(tx))
- self.sync_with_ping()
+ if expect_disconnect:
+ self.wait_for_disconnect()
+ else:
+ self.sync_with_ping()
raw_mempool = rpc.getrawmempool()
if success:
diff --git a/test/functional/test_framework/script.py b/test/functional/test_framework/script.py
index 6fe0b445da..44650d7584 100644
--- a/test/functional/test_framework/script.py
+++ b/test/functional/test_framework/script.py
@@ -10,15 +10,6 @@ This file is modified from python-bitcoinlib.
from .mininode import CTransaction, CTxOut, sha256, hash256, uint256_from_str, ser_uint256, ser_string
from binascii import hexlify
import hashlib
-
-import sys
-bchr = chr
-bord = ord
-if sys.version > '3':
- long = int
- bchr = lambda x: bytes([x])
- bord = lambda x: x
-
import struct
from .bignum import bn2vch
@@ -40,9 +31,9 @@ class CScriptOp(int):
def encode_op_pushdata(d):
"""Encode a PUSHDATA op, returning bytes"""
if len(d) < 0x4c:
- return b'' + bchr(len(d)) + d # OP_PUSHDATA
+ return b'' + bytes([len(d)]) + d # OP_PUSHDATA
elif len(d) <= 0xff:
- return b'\x4c' + bchr(len(d)) + d # OP_PUSHDATA1
+ return b'\x4c' + bytes([len(d)]) + d # OP_PUSHDATA1
elif len(d) <= 0xffff:
return b'\x4d' + struct.pack(b'<H', len(d)) + d # OP_PUSHDATA2
elif len(d) <= 0xffffffff:
@@ -388,7 +379,7 @@ class CScriptNum():
r.append(0x80 if neg else 0)
elif neg:
r[-1] |= 0x80
- return bytes(bchr(len(r)) + r)
+ return bytes([len(r)]) + r
class CScript(bytes):
@@ -405,17 +396,17 @@ class CScript(bytes):
def __coerce_instance(cls, other):
# Coerce other into bytes
if isinstance(other, CScriptOp):
- other = bchr(other)
+ other = bytes([other])
elif isinstance(other, CScriptNum):
if (other.value == 0):
- other = bchr(CScriptOp(OP_0))
+ other = bytes([CScriptOp(OP_0)])
else:
other = CScriptNum.encode(other)
elif isinstance(other, int):
if 0 <= other <= 16:
- other = bytes(bchr(CScriptOp.encode_op_n(other)))
+ other = bytes([CScriptOp.encode_op_n(other)])
elif other == -1:
- other = bytes(bchr(OP_1NEGATE))
+ other = bytes([OP_1NEGATE])
else:
other = CScriptOp.encode_op_pushdata(bn2vch(other))
elif isinstance(other, (bytes, bytearray)):
@@ -458,7 +449,7 @@ class CScript(bytes):
i = 0
while i < len(self):
sop_idx = i
- opcode = bord(self[i])
+ opcode = self[i]
i += 1
if opcode > OP_PUSHDATA4:
@@ -474,21 +465,21 @@ class CScript(bytes):
pushdata_type = 'PUSHDATA1'
if i >= len(self):
raise CScriptInvalidError('PUSHDATA1: missing data length')
- datasize = bord(self[i])
+ datasize = self[i]
i += 1
elif opcode == OP_PUSHDATA2:
pushdata_type = 'PUSHDATA2'
if i + 1 >= len(self):
raise CScriptInvalidError('PUSHDATA2: missing data length')
- datasize = bord(self[i]) + (bord(self[i+1]) << 8)
+ datasize = self[i] + (self[i+1] << 8)
i += 2
elif opcode == OP_PUSHDATA4:
pushdata_type = 'PUSHDATA4'
if i + 3 >= len(self):
raise CScriptInvalidError('PUSHDATA4: missing data length')
- datasize = bord(self[i]) + (bord(self[i+1]) << 8) + (bord(self[i+2]) << 16) + (bord(self[i+3]) << 24)
+ datasize = self[i] + (self[i+1] << 8) + (self[i+2] << 16) + (self[i+3] << 24)
i += 4
else:
diff --git a/test/functional/test_framework/socks5.py b/test/functional/test_framework/socks5.py
index 4721809a3b..581de0ed5d 100644
--- a/test/functional/test_framework/socks5.py
+++ b/test/functional/test_framework/socks5.py
@@ -4,12 +4,14 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Dummy Socks5 server for testing."""
-import socket, threading, queue
+import socket
+import threading
+import queue
import logging
logger = logging.getLogger("TestFramework.socks5")
-### Protocol constants
+# Protocol constants
class Command:
CONNECT = 0x01
@@ -18,7 +20,7 @@ class AddressType:
DOMAINNAME = 0x03
IPV6 = 0x04
-### Utility functions
+# Utility functions
def recvall(s, n):
"""Receive n bytes from a socket, or fail."""
rv = bytearray()
@@ -30,7 +32,7 @@ def recvall(s, n):
n -= len(d)
return rv
-### Implementation classes
+# Implementation classes
class Socks5Configuration():
"""Proxy configuration."""
def __init__(self):
@@ -141,7 +143,7 @@ class Socks5Server():
thread = threading.Thread(None, conn.handle)
thread.daemon = True
thread.start()
-
+
def start(self):
assert(not self.running)
self.running = True
diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py
index 54ff9eb038..b842e6ef4e 100755
--- a/test/functional/test_framework/test_framework.py
+++ b/test/functional/test_framework/test_framework.py
@@ -4,6 +4,7 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Base class for RPC testing."""
+import configparser
from enum import Enum
import logging
import optparse
@@ -97,10 +98,8 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
help="Leave bitcoinds and test.* datadir on exit or error")
parser.add_option("--noshutdown", dest="noshutdown", default=False, action="store_true",
help="Don't stop bitcoinds after the test execution")
- parser.add_option("--srcdir", dest="srcdir", default=os.path.normpath(os.path.dirname(os.path.realpath(__file__)) + "/../../../src"),
- help="Source directory containing bitcoind/bitcoin-cli (default: %default)")
- parser.add_option("--cachedir", dest="cachedir", default=os.path.normpath(os.path.dirname(os.path.realpath(__file__)) + "/../../cache"),
- help="Directory for caching pregenerated datadirs")
+ parser.add_option("--cachedir", dest="cachedir", default=os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/../../cache"),
+ help="Directory for caching pregenerated datadirs (default: %default)")
parser.add_option("--tmpdir", dest="tmpdir", help="Root directory for datadirs")
parser.add_option("-l", "--loglevel", dest="loglevel", default="INFO",
help="log events at this level and higher to the console. Can be set to DEBUG, INFO, WARNING, ERROR or CRITICAL. Passing --loglevel DEBUG will output all logs to console. Note that logs at all levels are always written to the test_framework.log file in the temporary test directory.")
@@ -111,7 +110,8 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
parser.add_option("--coveragedir", dest="coveragedir",
help="Write tested RPC commands into this directory")
parser.add_option("--configfile", dest="configfile",
- help="Location of the test framework config file")
+ default=os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/../../config.ini"),
+ help="Location of the test framework config file (default: %default)")
parser.add_option("--pdbonfailure", dest="pdbonfailure", default=False, action="store_true",
help="Attach a python debugger if test fails")
parser.add_option("--usecli", dest="usecli", default=False, action="store_true",
@@ -121,14 +121,19 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
PortSeed.n = self.options.port_seed
- os.environ['PATH'] = self.options.srcdir + os.pathsep + \
- self.options.srcdir + os.path.sep + "qt" + os.pathsep + \
- os.environ['PATH']
-
check_json_precision()
self.options.cachedir = os.path.abspath(self.options.cachedir)
+ config = configparser.ConfigParser()
+ config.read_file(open(self.options.configfile))
+ self.options.bitcoind = os.getenv("BITCOIND", default=config["environment"]["BUILDDIR"] + '/src/bitcoind' + config["environment"]["EXEEXT"])
+ self.options.bitcoincli = os.getenv("BITCOINCLI", default=config["environment"]["BUILDDIR"] + '/src/bitcoin-cli' + config["environment"]["EXEEXT"])
+
+ os.environ['PATH'] = config['environment']['BUILDDIR'] + os.pathsep + \
+ config['environment']['BUILDDIR'] + os.path.sep + "qt" + os.pathsep + \
+ os.environ['PATH']
+
# Set up temp directory and start logging
if self.options.tmpdir:
self.options.tmpdir = os.path.abspath(self.options.tmpdir)
@@ -246,12 +251,12 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
if extra_args is None:
extra_args = [[]] * num_nodes
if binary is None:
- binary = [None] * num_nodes
+ binary = [self.options.bitcoind] * num_nodes
assert_equal(len(extra_confs), num_nodes)
assert_equal(len(extra_args), num_nodes)
assert_equal(len(binary), num_nodes)
for i in range(num_nodes):
- self.nodes.append(TestNode(i, get_datadir_path(self.options.tmpdir, i), rpchost=rpchost, timewait=timewait, binary=binary[i], stderr=None, mocktime=self.mocktime, coverage_dir=self.options.coveragedir, extra_conf=extra_confs[i], extra_args=extra_args[i], use_cli=self.options.usecli))
+ self.nodes.append(TestNode(i, get_datadir_path(self.options.tmpdir, i), rpchost=rpchost, timewait=timewait, bitcoind=binary[i], bitcoin_cli=self.options.bitcoincli, mocktime=self.mocktime, coverage_dir=self.options.coveragedir, extra_conf=extra_confs[i], extra_args=extra_args[i], use_cli=self.options.usecli))
def start_node(self, i, *args, **kwargs):
"""Start a bitcoind"""
@@ -284,9 +289,9 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
for node in self.nodes:
coverage.write_all_rpc_commands(self.options.coveragedir, node.rpc)
- def stop_node(self, i):
+ def stop_node(self, i, expected_stderr=''):
"""Stop a bitcoind test node"""
- self.nodes[i].stop_node()
+ self.nodes[i].stop_node(expected_stderr)
self.nodes[i].wait_until_stopped()
def stop_nodes(self):
@@ -399,10 +404,10 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
# Create cache directories, run bitcoinds:
for i in range(MAX_NODES):
datadir = initialize_datadir(self.options.cachedir, i)
- args = [os.getenv("BITCOIND", "bitcoind"), "-datadir=" + datadir]
+ args = [self.options.bitcoind, "-datadir=" + datadir]
if i > 0:
args.append("-connect=127.0.0.1:" + str(p2p_port(0)))
- self.nodes.append(TestNode(i, get_datadir_path(self.options.cachedir, i), extra_conf=["bind=127.0.0.1"], extra_args=[],rpchost=None, timewait=None, binary=None, stderr=None, mocktime=self.mocktime, coverage_dir=None))
+ self.nodes.append(TestNode(i, get_datadir_path(self.options.cachedir, i), extra_conf=["bind=127.0.0.1"], extra_args=[], rpchost=None, timewait=None, bitcoind=self.options.bitcoind, bitcoin_cli=self.options.bitcoincli, mocktime=self.mocktime, coverage_dir=None))
self.nodes[i].args = args
self.start_node(i)
diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py
index 0f0d031f35..0353fc0712 100755
--- a/test/functional/test_framework/test_node.py
+++ b/test/functional/test_framework/test_node.py
@@ -19,7 +19,6 @@ import time
from .authproxy import JSONRPCException
from .util import (
append_config,
- assert_equal,
delete_cookie_file,
get_rpc_proxy,
rpc_url,
@@ -57,20 +56,18 @@ class TestNode():
To make things easier for the test writer, any unrecognised messages will
be dispatched to the RPC connection."""
- def __init__(self, i, datadir, rpchost, timewait, binary, stderr, mocktime, coverage_dir, extra_conf=None, extra_args=None, use_cli=False):
+ def __init__(self, i, datadir, rpchost, timewait, bitcoind, bitcoin_cli, mocktime, coverage_dir, extra_conf=None, extra_args=None, use_cli=False):
self.index = i
self.datadir = datadir
+ self.stdout_dir = os.path.join(self.datadir, "stdout")
+ self.stderr_dir = os.path.join(self.datadir, "stderr")
self.rpchost = rpchost
if timewait:
self.rpc_timeout = timewait
else:
# Wait for up to 60 seconds for the RPC server to respond
self.rpc_timeout = 60
- if binary is None:
- self.binary = os.getenv("BITCOIND", "bitcoind")
- else:
- self.binary = binary
- self.stderr = stderr
+ self.binary = bitcoind
self.coverage_dir = coverage_dir
if extra_conf != None:
append_config(datadir, extra_conf)
@@ -78,9 +75,18 @@ class TestNode():
# For those callers that need more flexibility, they can just set the args property directly.
# Note that common args are set in the config file (see initialize_datadir)
self.extra_args = extra_args
- self.args = [self.binary, "-datadir=" + self.datadir, "-logtimemicros", "-debug", "-debugexclude=libevent", "-debugexclude=leveldb", "-mocktime=" + str(mocktime), "-uacomment=testnode%d" % i]
-
- self.cli = TestNodeCLI(os.getenv("BITCOINCLI", "bitcoin-cli"), self.datadir)
+ self.args = [
+ self.binary,
+ "-datadir=" + self.datadir,
+ "-logtimemicros",
+ "-debug",
+ "-debugexclude=libevent",
+ "-debugexclude=leveldb",
+ "-mocktime=" + str(mocktime),
+ "-uacomment=testnode%d" % i
+ ]
+
+ self.cli = TestNodeCLI(bitcoin_cli, self.datadir)
self.use_cli = use_cli
self.running = False
@@ -93,6 +99,14 @@ class TestNode():
self.p2ps = []
+ def _node_msg(self, msg: str) -> str:
+ """Return a modified msg that identifies this node by its index as a debugging aid."""
+ return "[node %d] %s" % (self.index, msg)
+
+ def _raise_assertion_error(self, msg: str):
+ """Raise an AssertionError with msg modified to identify this node."""
+ raise AssertionError(self._node_msg(msg))
+
def __del__(self):
# Ensure that we don't leave any bitcoind processes lying around after
# the test ends
@@ -100,7 +114,7 @@ class TestNode():
# Should only happen on test failure
# Avoid using logger, as that may have already been shutdown when
# this destructor is called.
- print("Cleaning up leftover process")
+ print(self._node_msg("Cleaning up leftover process"))
self.process.kill()
def __getattr__(self, name):
@@ -108,20 +122,32 @@ class TestNode():
if self.use_cli:
return getattr(self.cli, name)
else:
- assert self.rpc_connected and self.rpc is not None, "Error: no RPC connection"
+ assert self.rpc_connected and self.rpc is not None, self._node_msg("Error: no RPC connection")
return getattr(self.rpc, name)
- def start(self, extra_args=None, stderr=None, *args, **kwargs):
+ def start(self, extra_args=None, stdout=None, stderr=None, *args, **kwargs):
"""Start the node."""
if extra_args is None:
extra_args = self.extra_args
+
+ # Add a new stdout and stderr file each time bitcoind is started
if stderr is None:
- stderr = self.stderr
+ stderr = tempfile.NamedTemporaryFile(dir=self.stderr_dir, delete=False)
+ if stdout is None:
+ stdout = tempfile.NamedTemporaryFile(dir=self.stdout_dir, delete=False)
+ self.stderr = stderr
+ self.stdout = stdout
+
# Delete any existing cookie file -- if such a file exists (eg due to
# unclean shutdown), it will get overwritten anyway by bitcoind, and
# potentially interfere with our attempt to authenticate
delete_cookie_file(self.datadir)
- self.process = subprocess.Popen(self.args + extra_args, stderr=stderr, *args, **kwargs)
+
+ # add environment variable LIBC_FATAL_STDERR_=1 so that libc errors are written to stderr and not the terminal
+ subp_env = dict(os.environ, LIBC_FATAL_STDERR_="1")
+
+ self.process = subprocess.Popen(self.args + extra_args, env=subp_env, stdout=stdout, stderr=stderr, *args, **kwargs)
+
self.running = True
self.log.debug("bitcoind started, waiting for RPC to come up")
@@ -131,7 +157,8 @@ class TestNode():
poll_per_s = 4
for _ in range(poll_per_s * self.rpc_timeout):
if self.process.poll() is not None:
- raise FailedToStartError('bitcoind exited with status {} during initialization'.format(self.process.returncode))
+ raise FailedToStartError(self._node_msg(
+ 'bitcoind exited with status {} during initialization'.format(self.process.returncode)))
try:
self.rpc = get_rpc_proxy(rpc_url(self.datadir, self.index, self.rpchost), self.index, timeout=self.rpc_timeout, coveragedir=self.coverage_dir)
self.rpc.getblockcount()
@@ -150,18 +177,17 @@ class TestNode():
if "No RPC credentials" not in str(e):
raise
time.sleep(1.0 / poll_per_s)
- raise AssertionError("Unable to connect to bitcoind")
+ self._raise_assertion_error("Unable to connect to bitcoind")
def get_wallet_rpc(self, wallet_name):
if self.use_cli:
return self.cli("-rpcwallet={}".format(wallet_name))
else:
- assert self.rpc_connected
- assert self.rpc
+ assert self.rpc_connected and self.rpc, self._node_msg("RPC not connected")
wallet_path = "wallet/%s" % wallet_name
return self.rpc / wallet_path
- def stop_node(self):
+ def stop_node(self, expected_stderr=''):
"""Stop the node."""
if not self.running:
return
@@ -170,6 +196,13 @@ class TestNode():
self.stop()
except http.client.CannotSendRequest:
self.log.exception("Unable to stop node.")
+
+ # Check that stderr is as expected
+ self.stderr.seek(0)
+ stderr = self.stderr.read().decode('utf-8').strip()
+ if stderr != expected_stderr:
+ raise AssertionError("Unexpected stderr {} != {}".format(stderr, expected_stderr))
+
del self.p2ps[:]
def is_node_stopped(self):
@@ -184,7 +217,8 @@ class TestNode():
return False
# process has stopped. Assert that it didn't return an error code.
- assert_equal(return_code, 0)
+ assert return_code == 0, self._node_msg(
+ "Node returned non-zero exit code (%d) when stopping" % return_code)
self.running = False
self.process = None
self.rpc_connected = False
@@ -203,9 +237,10 @@ class TestNode():
Will throw if bitcoind starts without an error.
Will throw if an expected_msg is provided and it does not match bitcoind's stdout."""
- with tempfile.SpooledTemporaryFile(max_size=2**16) as log_stderr:
+ with tempfile.NamedTemporaryFile(dir=self.stderr_dir, delete=False) as log_stderr, \
+ tempfile.NamedTemporaryFile(dir=self.stdout_dir, delete=False) as log_stdout:
try:
- self.start(extra_args, stderr=log_stderr, *args, **kwargs)
+ self.start(extra_args, stdout=log_stdout, stderr=log_stderr, *args, **kwargs)
self.wait_for_rpc_connection()
self.stop_node()
self.wait_until_stopped()
@@ -219,19 +254,22 @@ class TestNode():
stderr = log_stderr.read().decode('utf-8').strip()
if match == ErrorMatch.PARTIAL_REGEX:
if re.search(expected_msg, stderr, flags=re.MULTILINE) is None:
- raise AssertionError('Expected message "{}" does not partially match stderr:\n"{}"'.format(expected_msg, stderr))
+ self._raise_assertion_error(
+ 'Expected message "{}" does not partially match stderr:\n"{}"'.format(expected_msg, stderr))
elif match == ErrorMatch.FULL_REGEX:
if re.fullmatch(expected_msg, stderr) is None:
- raise AssertionError('Expected message "{}" does not fully match stderr:\n"{}"'.format(expected_msg, stderr))
+ self._raise_assertion_error(
+ 'Expected message "{}" does not fully match stderr:\n"{}"'.format(expected_msg, stderr))
elif match == ErrorMatch.FULL_TEXT:
if expected_msg != stderr:
- raise AssertionError('Expected message "{}" does not fully match stderr:\n"{}"'.format(expected_msg, stderr))
+ self._raise_assertion_error(
+ 'Expected message "{}" does not fully match stderr:\n"{}"'.format(expected_msg, stderr))
else:
if expected_msg is None:
assert_msg = "bitcoind should have exited with an error"
else:
assert_msg = "bitcoind should have exited with expected error " + expected_msg
- raise AssertionError(assert_msg)
+ self._raise_assertion_error(assert_msg)
def node_encrypt_wallet(self, passphrase):
""""Encrypts the wallet.
@@ -262,7 +300,7 @@ class TestNode():
Convenience property - most tests only use a single p2p connection to each
node, so this saves having to write node.p2ps[0] many times."""
- assert self.p2ps, "No p2p connection"
+ assert self.p2ps, self._node_msg("No p2p connection")
return self.p2ps[0]
def disconnect_p2ps(self):
diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py
index f22322fbbc..e016148f70 100644
--- a/test/functional/test_framework/util.py
+++ b/test/functional/test_framework/util.py
@@ -294,12 +294,16 @@ def initialize_datadir(dirname, n):
os.makedirs(datadir)
with open(os.path.join(datadir, "bitcoin.conf"), 'w', encoding='utf8') as f:
f.write("regtest=1\n")
+ f.write("[regtest]\n")
f.write("port=" + str(p2p_port(n)) + "\n")
f.write("rpcport=" + str(rpc_port(n)) + "\n")
f.write("server=1\n")
f.write("keypool=1\n")
f.write("discover=0\n")
f.write("listenonion=0\n")
+ f.write("printtoconsole=0\n")
+ os.makedirs(os.path.join(datadir, 'stderr'), exist_ok=True)
+ os.makedirs(os.path.join(datadir, 'stdout'), exist_ok=True)
return datadir
def get_datadir_path(dirname, n):
@@ -348,7 +352,14 @@ def set_node_times(nodes, t):
def disconnect_nodes(from_connection, node_num):
for peer_id in [peer['id'] for peer in from_connection.getpeerinfo() if "testnode%d" % node_num in peer['subver']]:
- from_connection.disconnectnode(nodeid=peer_id)
+ try:
+ from_connection.disconnectnode(nodeid=peer_id)
+ except JSONRPCException as e:
+ # If this node is disconnected between calculating the peer id
+ # and issuing the disconnect, don't worry about it.
+ # This avoids a race condition if we're mass-disconnecting peers.
+ if e.error['code'] != -29: # RPC_CLIENT_NODE_NOT_CONNECTED
+ raise
# wait to disconnect
wait_until(lambda: [peer['id'] for peer in from_connection.getpeerinfo() if "testnode%d" % node_num in peer['subver']] == [], timeout=5)
@@ -555,3 +566,14 @@ def mine_large_block(node, utxos=None):
fee = 100 * node.getnetworkinfo()["relayfee"]
create_lots_of_big_transactions(node, txouts, utxos, num, fee=fee)
node.generate(1)
+
+def find_vout_for_address(node, txid, addr):
+ """
+ Locate the vout index of the given transaction sending to the
+ given address. Raises runtime error exception if not found.
+ """
+ tx = node.getrawtransaction(txid, True)
+ for i in range(len(tx["vout"])):
+ if any([addr == a for a in tx["vout"][i]["scriptPubKey"]["addresses"]]):
+ return i
+ raise RuntimeError("Vout not found for address: txid=%s, addr=%s" % (txid, addr))
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index 518c16b5f1..dfa8c33728 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -70,7 +70,7 @@ BASE_SCRIPTS = [
'wallet_labels.py',
'p2p_segwit.py',
'wallet_dump.py',
- 'rpc_listtransactions.py',
+ 'wallet_listtransactions.py',
# vv Tests less than 60s vv
'p2p_sendheaders.py',
'wallet_zapwallettxes.py',
@@ -120,6 +120,9 @@ BASE_SCRIPTS = [
'feature_nulldummy.py',
'mempool_accept.py',
'wallet_import_rescan.py',
+ 'rpc_bind.py --ipv4',
+ 'rpc_bind.py --ipv6',
+ 'rpc_bind.py --nonloopback',
'mining_basic.py',
'wallet_bumpfee.py',
'rpc_named_arguments.py',
@@ -135,6 +138,7 @@ BASE_SCRIPTS = [
'p2p_fingerprint.py',
'feature_uacomment.py',
'p2p_unrequested_blocks.py',
+ 'feature_includeconf.py',
'feature_logging.py',
'p2p_node_network_limited.py',
'feature_blocksdir.py',
@@ -160,7 +164,6 @@ EXTENDED_SCRIPTS = [
'p2p_timeouts.py',
# vv Tests less than 60s vv
'p2p_feefilter.py',
- 'rpc_bind.py',
# vv Tests less than 30s vv
'feature_assumevalid.py',
'example_test.py',
@@ -199,6 +202,7 @@ def main():
parser.add_argument('--keepcache', '-k', action='store_true', help='the default behavior is to flush the cache directory on startup. --keepcache retains the cache from the previous testrun.')
parser.add_argument('--quiet', '-q', action='store_true', help='only print results summary and failure logs')
parser.add_argument('--tmpdirprefix', '-t', default=tempfile.gettempdir(), help="Root directory for datadirs")
+ parser.add_argument('--failfast', action='store_true', help='stop execution after the first test failure')
args, unknown_args = parser.parse_known_args()
# args to be passed on always start with two dashes; tests are the remaining unknown args
@@ -281,9 +285,21 @@ def main():
if not args.keepcache:
shutil.rmtree("%s/test/cache" % config["environment"]["BUILDDIR"], ignore_errors=True)
- run_tests(test_list, config["environment"]["SRCDIR"], config["environment"]["BUILDDIR"], config["environment"]["EXEEXT"], tmpdir, args.jobs, args.coverage, passon_args, args.combinedlogslen)
+ run_tests(
+ test_list,
+ config["environment"]["SRCDIR"],
+ config["environment"]["BUILDDIR"],
+ tmpdir,
+ jobs=args.jobs,
+ enable_coverage=args.coverage,
+ args=passon_args,
+ combined_logs_len=args.combinedlogslen,
+ failfast=args.failfast,
+ )
+
+def run_tests(test_list, src_dir, build_dir, tmpdir, jobs=1, enable_coverage=False, args=None, combined_logs_len=0, failfast=False):
+ args = args or []
-def run_tests(test_list, src_dir, build_dir, exeext, tmpdir, jobs=1, enable_coverage=False, args=[], combined_logs_len=0):
# Warn if bitcoind is already running (unix only)
try:
if subprocess.check_output(["pidof", "bitcoind"]) is not None:
@@ -296,15 +312,9 @@ def run_tests(test_list, src_dir, build_dir, exeext, tmpdir, jobs=1, enable_cove
if os.path.isdir(cache_dir):
print("%sWARNING!%s There is a cache directory here: %s. If tests fail unexpectedly, try deleting the cache directory." % (BOLD[1], BOLD[0], cache_dir))
- #Set env vars
- if "BITCOIND" not in os.environ:
- os.environ["BITCOIND"] = build_dir + '/src/bitcoind' + exeext
- os.environ["BITCOINCLI"] = build_dir + '/src/bitcoin-cli' + exeext
-
tests_dir = src_dir + '/test/functional/'
- flags = ["--srcdir={}/src".format(build_dir)] + args
- flags.append("--cachedir=%s" % cache_dir)
+ flags = ['--cachedir={}'.format(cache_dir)] + args
if enable_coverage:
coverage = RPCCoverage()
@@ -349,6 +359,10 @@ def run_tests(test_list, src_dir, build_dir, exeext, tmpdir, jobs=1, enable_cove
combined_logs, _ = subprocess.Popen([sys.executable, os.path.join(tests_dir, 'combine_logs.py'), '-c', testdir], universal_newlines=True, stdout=subprocess.PIPE).communicate()
print("\n".join(deque(combined_logs.splitlines(), combined_logs_len)))
+ if failfast:
+ logging.debug("Early exiting after test failure")
+ break
+
print_results(test_results, max_len_name, (int(time.time() - start_time)))
if coverage:
@@ -363,6 +377,10 @@ def run_tests(test_list, src_dir, build_dir, exeext, tmpdir, jobs=1, enable_cove
all_passed = all(map(lambda test_result: test_result.was_successful, test_results))
+ # This will be a no-op unless failfast is True in which case there may be dangling
+ # processes which need to be killed.
+ job_queue.kill_and_join()
+
sys.exit(not all_passed)
def print_results(test_results, max_len_name, runtime):
@@ -453,6 +471,17 @@ class TestHandler:
return TestResult(name, status, int(time.time() - start_time)), testdir, stdout, stderr
print('.', end='', flush=True)
+ def kill_and_join(self):
+ """Send SIGKILL to all jobs and block until all have ended."""
+ procs = [i[2] for i in self.jobs]
+
+ for proc in procs:
+ proc.kill()
+
+ for proc in procs:
+ proc.wait()
+
+
class TestResult():
def __init__(self, name, status, time):
self.name = name
diff --git a/test/functional/wallet_address_types.py b/test/functional/wallet_address_types.py
index 5d2428e6ef..7658d78383 100755
--- a/test/functional/wallet_address_types.py
+++ b/test/functional/wallet_address_types.py
@@ -280,7 +280,10 @@ class AddressTypeTest(BitcoinTestFramework):
self.log.info('getrawchangeaddress defaults to addresstype if -changetype is not set and argument is absent')
self.test_address(3, self.nodes[3].getrawchangeaddress(), multisig=False, typ='bech32')
- self.log.info('getrawchangeaddress fails with invalid changetype argument')
+ self.log.info('test invalid address type arguments')
+ assert_raises_rpc_error(-5, "Unknown address type ''", self.nodes[3].addmultisigaddress, 2, [compressed_1, compressed_2], None, '')
+ assert_raises_rpc_error(-5, "Unknown address type ''", self.nodes[3].getnewaddress, None, '')
+ assert_raises_rpc_error(-5, "Unknown address type ''", self.nodes[3].getrawchangeaddress, '')
assert_raises_rpc_error(-5, "Unknown address type 'bech23'", self.nodes[3].getrawchangeaddress, 'bech23')
self.log.info("Nodes with changetype=p2sh-segwit never use a P2WPKH change output")
diff --git a/test/functional/wallet_basic.py b/test/functional/wallet_basic.py
index 0436aca6a4..9c58b84819 100755
--- a/test/functional/wallet_basic.py
+++ b/test/functional/wallet_basic.py
@@ -3,8 +3,20 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the wallet."""
+from decimal import Decimal
+import time
+
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import *
+from test_framework.util import (
+ assert_array_result,
+ assert_equal,
+ assert_fee_amount,
+ assert_raises_rpc_error,
+ connect_nodes_bi,
+ sync_blocks,
+ sync_mempools,
+ wait_until,
+)
class WalletTest(BitcoinTestFramework):
def set_test_params(self):
@@ -16,9 +28,9 @@ class WalletTest(BitcoinTestFramework):
self.start_node(0)
self.start_node(1)
self.start_node(2)
- connect_nodes_bi(self.nodes,0,1)
- connect_nodes_bi(self.nodes,1,2)
- connect_nodes_bi(self.nodes,0,2)
+ connect_nodes_bi(self.nodes, 0, 1)
+ connect_nodes_bi(self.nodes, 1, 2)
+ connect_nodes_bi(self.nodes, 0, 2)
self.sync_all([self.nodes[0:3]])
def check_fee_amount(self, curr_balance, balance_with_fee, fee_per_byte, tx_size):
@@ -111,11 +123,11 @@ class WalletTest(BitcoinTestFramework):
self.nodes[2].lockunspent(True, [unspent_0])
assert_equal(len(self.nodes[2].listlockunspent()), 0)
assert_raises_rpc_error(-8, "Invalid parameter, unknown transaction",
- self.nodes[2].lockunspent, False,
- [{"txid": "0000000000000000000000000000000000", "vout": 0}])
+ self.nodes[2].lockunspent, False,
+ [{"txid": "0000000000000000000000000000000000", "vout": 0}])
assert_raises_rpc_error(-8, "Invalid parameter, vout index out of bounds",
- self.nodes[2].lockunspent, False,
- [{"txid": unspent_0["txid"], "vout": 999}])
+ self.nodes[2].lockunspent, False,
+ [{"txid": unspent_0["txid"], "vout": 999}])
# Have node1 generate 100 blocks (so node0 can recover the fee)
self.nodes[1].generate(100)
@@ -123,7 +135,7 @@ class WalletTest(BitcoinTestFramework):
# node0 should end up with 100 btc in block rewards plus fees, but
# minus the 21 plus fees sent to node2
- assert_equal(self.nodes[0].getbalance(), 100-21)
+ assert_equal(self.nodes[0].getbalance(), 100 - 21)
assert_equal(self.nodes[2].getbalance(), 21)
# Node0 should have two unspent outputs.
@@ -137,8 +149,8 @@ class WalletTest(BitcoinTestFramework):
for utxo in node0utxos:
inputs = []
outputs = {}
- inputs.append({ "txid" : utxo["txid"], "vout" : utxo["vout"]})
- outputs[self.nodes[2].getnewaddress("from1")] = utxo["amount"] - 3
+ inputs.append({"txid": utxo["txid"], "vout": utxo["vout"]})
+ outputs[self.nodes[2].getnewaddress()] = utxo["amount"] - 3
raw_tx = self.nodes[0].createrawtransaction(inputs, outputs)
txns_to_send.append(self.nodes[0].signrawtransactionwithwallet(raw_tx))
@@ -152,7 +164,6 @@ class WalletTest(BitcoinTestFramework):
assert_equal(self.nodes[0].getbalance(), 0)
assert_equal(self.nodes[2].getbalance(), 94)
- assert_equal(self.nodes[2].getbalance("from1"), 94-21)
# Verify that a spent output cannot be locked anymore
spent_0 = {"txid": node0utxos[0]["txid"], "vout": node0utxos[0]["vout"]}
@@ -177,7 +188,7 @@ class WalletTest(BitcoinTestFramework):
node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), Decimal('20'), fee_per_byte, self.get_vsize(self.nodes[2].getrawtransaction(txid)))
# Sendmany 10 BTC
- txid = self.nodes[2].sendmany('from1', {address: 10}, 0, "", [])
+ txid = self.nodes[2].sendmany('', {address: 10}, 0, "", [])
self.nodes[2].generate(1)
self.sync_all([self.nodes[0:3]])
node_0_bal += Decimal('10')
@@ -185,7 +196,7 @@ class WalletTest(BitcoinTestFramework):
assert_equal(self.nodes[0].getbalance(), node_0_bal)
# Sendmany 10 BTC with subtract fee from amount
- txid = self.nodes[2].sendmany('from1', {address: 10}, 0, "", [address])
+ txid = self.nodes[2].sendmany('', {address: 10}, 0, "", [address])
self.nodes[2].generate(1)
self.sync_all([self.nodes[0:3]])
node_2_bal -= Decimal('10')
@@ -214,91 +225,90 @@ class WalletTest(BitcoinTestFramework):
assert_equal(self.nodes[0].getwalletinfo()["unconfirmed_balance"], 1)
assert_equal(self.nodes[0].getunconfirmedbalance(), 1)
- #check if we can list zero value tx as available coins
- #1. create rawtx
- #2. hex-changed one output to 0.0
- #3. sign and send
- #4. check if recipient (node0) can list the zero value tx
+ # check if we can list zero value tx as available coins
+ # 1. create raw_tx
+ # 2. hex-changed one output to 0.0
+ # 3. sign and send
+ # 4. check if recipient (node0) can list the zero value tx
usp = self.nodes[1].listunspent()
- inputs = [{"txid":usp[0]['txid'], "vout":usp[0]['vout']}]
+ inputs = [{"txid": usp[0]['txid'], "vout": usp[0]['vout']}]
outputs = {self.nodes[1].getnewaddress(): 49.998, self.nodes[0].getnewaddress(): 11.11}
- rawTx = self.nodes[1].createrawtransaction(inputs, outputs).replace("c0833842", "00000000") #replace 11.11 with 0.0 (int32)
- decRawTx = self.nodes[1].decoderawtransaction(rawTx)
- signedRawTx = self.nodes[1].signrawtransactionwithwallet(rawTx)
- decRawTx = self.nodes[1].decoderawtransaction(signedRawTx['hex'])
- zeroValueTxid= decRawTx['txid']
- self.nodes[1].sendrawtransaction(signedRawTx['hex'])
+ raw_tx = self.nodes[1].createrawtransaction(inputs, outputs).replace("c0833842", "00000000") # replace 11.11 with 0.0 (int32)
+ signed_raw_tx = self.nodes[1].signrawtransactionwithwallet(raw_tx)
+ decoded_raw_tx = self.nodes[1].decoderawtransaction(signed_raw_tx['hex'])
+ zero_value_txid = decoded_raw_tx['txid']
+ self.nodes[1].sendrawtransaction(signed_raw_tx['hex'])
self.sync_all()
- self.nodes[1].generate(1) #mine a block
+ self.nodes[1].generate(1) # mine a block
self.sync_all()
- unspentTxs = self.nodes[0].listunspent() #zero value tx must be in listunspents output
+ unspent_txs = self.nodes[0].listunspent() # zero value tx must be in listunspents output
found = False
- for uTx in unspentTxs:
- if uTx['txid'] == zeroValueTxid:
+ for uTx in unspent_txs:
+ if uTx['txid'] == zero_value_txid:
found = True
assert_equal(uTx['amount'], Decimal('0'))
assert(found)
- #do some -walletbroadcast tests
+ # do some -walletbroadcast tests
self.stop_nodes()
self.start_node(0, ["-walletbroadcast=0"])
self.start_node(1, ["-walletbroadcast=0"])
self.start_node(2, ["-walletbroadcast=0"])
- connect_nodes_bi(self.nodes,0,1)
- connect_nodes_bi(self.nodes,1,2)
- connect_nodes_bi(self.nodes,0,2)
+ connect_nodes_bi(self.nodes, 0, 1)
+ connect_nodes_bi(self.nodes, 1, 2)
+ connect_nodes_bi(self.nodes, 0, 2)
self.sync_all([self.nodes[0:3]])
- txIdNotBroadcasted = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2)
- txObjNotBroadcasted = self.nodes[0].gettransaction(txIdNotBroadcasted)
- self.nodes[1].generate(1) #mine a block, tx should not be in there
+ txid_not_broadcast = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2)
+ tx_obj_not_broadcast = self.nodes[0].gettransaction(txid_not_broadcast)
+ self.nodes[1].generate(1) # mine a block, tx should not be in there
self.sync_all([self.nodes[0:3]])
- assert_equal(self.nodes[2].getbalance(), node_2_bal) #should not be changed because tx was not broadcasted
+ assert_equal(self.nodes[2].getbalance(), node_2_bal) # should not be changed because tx was not broadcasted
- #now broadcast from another node, mine a block, sync, and check the balance
- self.nodes[1].sendrawtransaction(txObjNotBroadcasted['hex'])
+ # now broadcast from another node, mine a block, sync, and check the balance
+ self.nodes[1].sendrawtransaction(tx_obj_not_broadcast['hex'])
self.nodes[1].generate(1)
self.sync_all([self.nodes[0:3]])
node_2_bal += 2
- txObjNotBroadcasted = self.nodes[0].gettransaction(txIdNotBroadcasted)
+ tx_obj_not_broadcast = self.nodes[0].gettransaction(txid_not_broadcast)
assert_equal(self.nodes[2].getbalance(), node_2_bal)
- #create another tx
- txIdNotBroadcasted = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2)
+ # create another tx
+ self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 2)
- #restart the nodes with -walletbroadcast=1
+ # restart the nodes with -walletbroadcast=1
self.stop_nodes()
self.start_node(0)
self.start_node(1)
self.start_node(2)
- connect_nodes_bi(self.nodes,0,1)
- connect_nodes_bi(self.nodes,1,2)
- connect_nodes_bi(self.nodes,0,2)
+ connect_nodes_bi(self.nodes, 0, 1)
+ connect_nodes_bi(self.nodes, 1, 2)
+ connect_nodes_bi(self.nodes, 0, 2)
sync_blocks(self.nodes[0:3])
self.nodes[0].generate(1)
sync_blocks(self.nodes[0:3])
node_2_bal += 2
- #tx should be added to balance because after restarting the nodes tx should be broadcast
+ # tx should be added to balance because after restarting the nodes tx should be broadcast
assert_equal(self.nodes[2].getbalance(), node_2_bal)
- #send a tx with value in a string (PR#6380 +)
- txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "2")
- txObj = self.nodes[0].gettransaction(txId)
- assert_equal(txObj['amount'], Decimal('-2'))
+ # send a tx with value in a string (PR#6380 +)
+ txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "2")
+ tx_obj = self.nodes[0].gettransaction(txid)
+ assert_equal(tx_obj['amount'], Decimal('-2'))
- txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "0.0001")
- txObj = self.nodes[0].gettransaction(txId)
- assert_equal(txObj['amount'], Decimal('-0.0001'))
+ txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "0.0001")
+ tx_obj = self.nodes[0].gettransaction(txid)
+ assert_equal(tx_obj['amount'], Decimal('-0.0001'))
- #check if JSON parser can handle scientific notation in strings
- txId = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "1e-4")
- txObj = self.nodes[0].gettransaction(txId)
- assert_equal(txObj['amount'], Decimal('-0.0001'))
+ # check if JSON parser can handle scientific notation in strings
+ txid = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), "1e-4")
+ tx_obj = self.nodes[0].gettransaction(txid)
+ assert_equal(tx_obj['amount'], Decimal('-0.0001'))
# This will raise an exception because the amount type is wrong
assert_raises_rpc_error(-3, "Invalid amount", self.nodes[0].sendtoaddress, self.nodes[2].getnewaddress(), "1f-4")
@@ -321,8 +331,8 @@ class WalletTest(BitcoinTestFramework):
# 4. Check that the unspents after import are not spendable
assert_array_result(self.nodes[1].listunspent(),
- {"address": address_to_import},
- {"spendable": False})
+ {"address": address_to_import},
+ {"spendable": False})
# 5. Import private key of the previously imported address on node1
priv_key = self.nodes[2].dumpprivkey(address_to_import)
@@ -330,17 +340,17 @@ class WalletTest(BitcoinTestFramework):
# 6. Check that the unspents are now spendable on node1
assert_array_result(self.nodes[1].listunspent(),
- {"address": address_to_import},
- {"spendable": True})
+ {"address": address_to_import},
+ {"spendable": True})
# Mine a block from node0 to an address from node1
- cbAddr = self.nodes[1].getnewaddress()
- blkHash = self.nodes[0].generatetoaddress(1, cbAddr)[0]
- cbTxId = self.nodes[0].getblock(blkHash)['tx'][0]
+ coinbase_addr = self.nodes[1].getnewaddress()
+ block_hash = self.nodes[0].generatetoaddress(1, coinbase_addr)[0]
+ coinbase_txid = self.nodes[0].getblock(block_hash)['tx'][0]
self.sync_all([self.nodes[0:3]])
# Check that the txid and balance is found by node1
- self.nodes[1].gettransaction(cbTxId)
+ self.nodes[1].gettransaction(coinbase_txid)
# check if wallet or blockchain maintenance changes the balance
self.sync_all([self.nodes[0:3]])
@@ -353,14 +363,14 @@ class WalletTest(BitcoinTestFramework):
# - True: unicode escaped as \u....
# - False: unicode directly as UTF-8
for mode in [True, False]:
- self.nodes[0].ensure_ascii = mode
+ self.nodes[0].rpc.ensure_ascii = mode
# unicode check: Basic Multilingual Plane, Supplementary Plane respectively
- for s in [u'рыба', u'𝅘𝅥𝅯']:
- addr = self.nodes[0].getaccountaddress(s)
- label = self.nodes[0].getaccount(addr)
- assert_equal(label, s)
- assert(s in self.nodes[0].listaccounts().keys())
- self.nodes[0].ensure_ascii = True # restore to default
+ for label in [u'рыба', u'𝅘𝅥𝅯']:
+ addr = self.nodes[0].getnewaddress()
+ self.nodes[0].setlabel(addr, label)
+ assert_equal(self.nodes[0].getaddressinfo(addr)['label'], label)
+ assert(label in self.nodes[0].listlabels())
+ self.nodes[0].rpc.ensure_ascii = True # restore to default
# maintenance tests
maintenance = [
@@ -376,9 +386,9 @@ class WalletTest(BitcoinTestFramework):
self.log.info("check " + m)
self.stop_nodes()
# set lower ancestor limit for later
- self.start_node(0, [m, "-limitancestorcount="+str(chainlimit)])
- self.start_node(1, [m, "-limitancestorcount="+str(chainlimit)])
- self.start_node(2, [m, "-limitancestorcount="+str(chainlimit)])
+ self.start_node(0, [m, "-limitancestorcount=" + str(chainlimit)])
+ self.start_node(1, [m, "-limitancestorcount=" + str(chainlimit)])
+ self.start_node(2, [m, "-limitancestorcount=" + str(chainlimit)])
if m == '-reindex':
# reindex will leave rpc warm up "early"; Wait for it to finish
wait_until(lambda: [block_count] * 3 == [self.nodes[i].getblockcount() for i in range(3)])
@@ -399,7 +409,7 @@ class WalletTest(BitcoinTestFramework):
self.nodes[0].generate(1)
node0_balance = self.nodes[0].getbalance()
# Split into two chains
- rawtx = self.nodes[0].createrawtransaction([{"txid":singletxid, "vout":0}], {chain_addrs[0]:node0_balance/2-Decimal('0.01'), chain_addrs[1]:node0_balance/2-Decimal('0.01')})
+ rawtx = self.nodes[0].createrawtransaction([{"txid": singletxid, "vout": 0}], {chain_addrs[0]: node0_balance / 2 - Decimal('0.01'), chain_addrs[1]: node0_balance / 2 - Decimal('0.01')})
signedtx = self.nodes[0].signrawtransactionwithwallet(rawtx)
singletxid = self.nodes[0].sendrawtransaction(signedtx["hex"])
self.nodes[0].generate(1)
@@ -410,10 +420,10 @@ class WalletTest(BitcoinTestFramework):
# So we should be able to generate exactly chainlimit txs for each original output
sending_addr = self.nodes[1].getnewaddress()
txid_list = []
- for i in range(chainlimit*2):
+ for i in range(chainlimit * 2):
txid_list.append(self.nodes[0].sendtoaddress(sending_addr, Decimal('0.0001')))
- assert_equal(self.nodes[0].getmempoolinfo()['size'], chainlimit*2)
- assert_equal(len(txid_list), chainlimit*2)
+ assert_equal(self.nodes[0].getmempoolinfo()['size'], chainlimit * 2)
+ assert_equal(len(txid_list), chainlimit * 2)
# Without walletrejectlongchains, we will still generate a txid
# The tx will be stored in the wallet but not accepted to the mempool
@@ -421,26 +431,26 @@ class WalletTest(BitcoinTestFramework):
assert(extra_txid not in self.nodes[0].getrawmempool())
assert(extra_txid in [tx["txid"] for tx in self.nodes[0].listtransactions()])
self.nodes[0].abandontransaction(extra_txid)
- total_txs = len(self.nodes[0].listtransactions("*",99999))
+ total_txs = len(self.nodes[0].listtransactions("*", 99999))
# Try with walletrejectlongchains
# Double chain limit but require combining inputs, so we pass SelectCoinsMinConf
self.stop_node(0)
- self.start_node(0, extra_args=["-walletrejectlongchains", "-limitancestorcount="+str(2*chainlimit)])
+ self.start_node(0, extra_args=["-walletrejectlongchains", "-limitancestorcount=" + str(2 * chainlimit)])
# wait for loadmempool
timeout = 10
- while (timeout > 0 and len(self.nodes[0].getrawmempool()) < chainlimit*2):
+ while (timeout > 0 and len(self.nodes[0].getrawmempool()) < chainlimit * 2):
time.sleep(0.5)
timeout -= 0.5
- assert_equal(len(self.nodes[0].getrawmempool()), chainlimit*2)
+ assert_equal(len(self.nodes[0].getrawmempool()), chainlimit * 2)
node0_balance = self.nodes[0].getbalance()
# With walletrejectlongchains we will not create the tx and store it in our wallet.
assert_raises_rpc_error(-4, "Transaction has too long of a mempool chain", self.nodes[0].sendtoaddress, sending_addr, node0_balance - Decimal('0.01'))
# Verify nothing new in wallet
- assert_equal(total_txs, len(self.nodes[0].listtransactions("*",99999)))
+ assert_equal(total_txs, len(self.nodes[0].listtransactions("*", 99999)))
# Test getaddressinfo. Note that these addresses are taken from disablewallet.py
assert_raises_rpc_error(-5, "Invalid address", self.nodes[0].getaddressinfo, "3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy")
diff --git a/test/functional/wallet_dump.py b/test/functional/wallet_dump.py
index 997f67ec7e..01d27dabe7 100755
--- a/test/functional/wallet_dump.py
+++ b/test/functional/wallet_dump.py
@@ -136,7 +136,7 @@ class WalletDumpTest(BitcoinTestFramework):
assert_equal(found_addr, test_addr_count)
assert_equal(found_script_addr, 2)
assert_equal(found_addr_chg, 90*2 + 50) # old reserve keys are marked as change now
- assert_equal(found_addr_rsv, 90*2)
+ assert_equal(found_addr_rsv, 90*2)
assert_equal(witness_addr_ret, witness_addr)
# Overwriting should fail
diff --git a/test/functional/wallet_hd.py b/test/functional/wallet_hd.py
index 8c754807e6..97a945721f 100755
--- a/test/functional/wallet_hd.py
+++ b/test/functional/wallet_hd.py
@@ -11,6 +11,7 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
connect_nodes_bi,
+ assert_raises_rpc_error
)
@@ -120,5 +121,39 @@ class WalletHDTest(BitcoinTestFramework):
assert_equal(keypath[0:7], "m/0'/1'")
+ # Generate a new HD seed on node 1 and make sure it is set
+ orig_masterkeyid = self.nodes[1].getwalletinfo()['hdmasterkeyid']
+ self.nodes[1].sethdseed()
+ new_masterkeyid = self.nodes[1].getwalletinfo()['hdmasterkeyid']
+ assert orig_masterkeyid != new_masterkeyid
+ addr = self.nodes[1].getnewaddress()
+ assert_equal(self.nodes[1].getaddressinfo(addr)['hdkeypath'], 'm/0\'/0\'/0\'') # Make sure the new address is the first from the keypool
+ self.nodes[1].keypoolrefill(1) # Fill keypool with 1 key
+
+ # Set a new HD seed on node 1 without flushing the keypool
+ new_seed = self.nodes[0].dumpprivkey(self.nodes[0].getnewaddress())
+ orig_masterkeyid = new_masterkeyid
+ self.nodes[1].sethdseed(False, new_seed)
+ new_masterkeyid = self.nodes[1].getwalletinfo()['hdmasterkeyid']
+ assert orig_masterkeyid != new_masterkeyid
+ addr = self.nodes[1].getnewaddress()
+ assert_equal(orig_masterkeyid, self.nodes[1].getaddressinfo(addr)['hdmasterkeyid'])
+ assert_equal(self.nodes[1].getaddressinfo(addr)['hdkeypath'], 'm/0\'/0\'/1\'') # Make sure the new address continues previous keypool
+
+ # Check that the next address is from the new seed
+ self.nodes[1].keypoolrefill(1)
+ next_addr = self.nodes[1].getnewaddress()
+ assert_equal(new_masterkeyid, self.nodes[1].getaddressinfo(next_addr)['hdmasterkeyid'])
+ assert_equal(self.nodes[1].getaddressinfo(next_addr)['hdkeypath'], 'm/0\'/0\'/0\'') # Make sure the new address is not from previous keypool
+ assert next_addr != addr
+
+ # Sethdseed parameter validity
+ assert_raises_rpc_error(-1, 'sethdseed', self.nodes[0].sethdseed, False, new_seed, 0)
+ assert_raises_rpc_error(-5, "Invalid private key", self.nodes[1].sethdseed, False, "not_wif")
+ assert_raises_rpc_error(-1, "JSON value is not a boolean as expected", self.nodes[1].sethdseed, "Not_bool")
+ assert_raises_rpc_error(-1, "JSON value is not a string as expected", self.nodes[1].sethdseed, False, True)
+ assert_raises_rpc_error(-5, "Already have this key", self.nodes[1].sethdseed, False, new_seed)
+ assert_raises_rpc_error(-5, "Already have this key", self.nodes[1].sethdseed, False, self.nodes[1].dumpprivkey(self.nodes[1].getnewaddress()))
+
if __name__ == '__main__':
WalletHDTest().main ()
diff --git a/test/functional/wallet_import_rescan.py b/test/functional/wallet_import_rescan.py
index b66e9b5d91..4c0ffb938b 100755
--- a/test/functional/wallet_import_rescan.py
+++ b/test/functional/wallet_import_rescan.py
@@ -42,16 +42,15 @@ class Variant(collections.namedtuple("Variant", "call data rescan prune")):
def do_import(self, timestamp):
"""Call one key import RPC."""
+ rescan = self.rescan == Rescan.yes
if self.call == Call.single:
if self.data == Data.address:
- response = self.try_rpc(self.node.importaddress, self.address["address"], self.label,
- self.rescan == Rescan.yes)
+ response = self.try_rpc(self.node.importaddress, address=self.address["address"], rescan=rescan)
elif self.data == Data.pub:
- response = self.try_rpc(self.node.importpubkey, self.address["pubkey"], self.label,
- self.rescan == Rescan.yes)
+ response = self.try_rpc(self.node.importpubkey, pubkey=self.address["pubkey"], rescan=rescan)
elif self.data == Data.priv:
- response = self.try_rpc(self.node.importprivkey, self.key, self.label, self.rescan == Rescan.yes)
+ response = self.try_rpc(self.node.importprivkey, privkey=self.key, rescan=rescan)
assert_equal(response, None)
elif self.call == Call.multi:
@@ -62,30 +61,22 @@ class Variant(collections.namedtuple("Variant", "call data rescan prune")):
"timestamp": timestamp + TIMESTAMP_WINDOW + (1 if self.rescan == Rescan.late_timestamp else 0),
"pubkeys": [self.address["pubkey"]] if self.data == Data.pub else [],
"keys": [self.key] if self.data == Data.priv else [],
- "label": self.label,
"watchonly": self.data != Data.priv
}], {"rescan": self.rescan in (Rescan.yes, Rescan.late_timestamp)})
assert_equal(response, [{"success": True}])
def check(self, txid=None, amount=None, confirmations=None):
- """Verify that getbalance/listtransactions return expected values."""
+ """Verify that listreceivedbyaddress returns expected values."""
- balance = self.node.getbalance(self.label, 0, True)
- assert_equal(balance, self.expected_balance)
-
- txs = self.node.listtransactions(self.label, 10000, 0, True)
- assert_equal(len(txs), self.expected_txs)
+ addresses = self.node.listreceivedbyaddress(minconf=0, include_watchonly=True, address_filter=self.address['address'])
+ if self.expected_txs:
+ assert_equal(len(addresses[0]["txids"]), self.expected_txs)
if txid is not None:
- tx, = [tx for tx in txs if tx["txid"] == txid]
- assert_equal(tx["label"], self.label)
- assert_equal(tx["address"], self.address["address"])
- assert_equal(tx["amount"], amount)
- assert_equal(tx["category"], "receive")
- assert_equal(tx["label"], self.label)
- assert_equal(tx["txid"], txid)
- assert_equal(tx["confirmations"], confirmations)
- assert_equal("trusted" not in tx, True)
+ address, = [ad for ad in addresses if txid in ad["txids"]]
+ assert_equal(address["address"], self.address["address"])
+ assert_equal(address["amount"], self.expected_balance)
+ assert_equal(address["confirmations"], confirmations)
# Verify the transaction is correctly marked watchonly depending on
# whether the transaction pays to an imported public key or
# imported private key. The test setup ensures that transaction
@@ -93,9 +84,9 @@ class Variant(collections.namedtuple("Variant", "call data rescan prune")):
# involvesWatchonly will be true if either the transaction output
# or inputs are watchonly).
if self.data != Data.priv:
- assert_equal(tx["involvesWatchonly"], True)
+ assert_equal(address["involvesWatchonly"], True)
else:
- assert_equal("involvesWatchonly" not in tx, True)
+ assert_equal("involvesWatchonly" not in address, True)
# List of Variants for each way a key or address could be imported.
@@ -130,11 +121,10 @@ class ImportRescanTest(BitcoinTestFramework):
connect_nodes(self.nodes[i], 0)
def run_test(self):
- # Create one transaction on node 0 with a unique amount and label for
+ # Create one transaction on node 0 with a unique amount for
# each possible type of wallet import RPC.
for i, variant in enumerate(IMPORT_VARIANTS):
- variant.label = "label {} {}".format(i, variant)
- variant.address = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress(variant.label))
+ variant.address = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress())
variant.key = self.nodes[1].dumpprivkey(variant.address["address"])
variant.initial_amount = 10 - (i + 1) / 4.0
variant.initial_txid = self.nodes[0].sendtoaddress(variant.address["address"], variant.initial_amount)
diff --git a/test/functional/wallet_importprunedfunds.py b/test/functional/wallet_importprunedfunds.py
index 4d349db23f..9cee9aa49a 100755
--- a/test/functional/wallet_importprunedfunds.py
+++ b/test/functional/wallet_importprunedfunds.py
@@ -3,38 +3,44 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the importprunedfunds and removeprunedfunds RPCs."""
+from decimal import Decimal
+
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import *
+from test_framework.util import (
+ assert_equal,
+ assert_raises_rpc_error,
+)
class ImportPrunedFundsTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 2
+ self.extra_args = [['-deprecatedrpc=accounts']] * 2
def run_test(self):
self.log.info("Mining blocks...")
self.nodes[0].generate(101)
self.sync_all()
-
+
# address
address1 = self.nodes[0].getnewaddress()
# pubkey
address2 = self.nodes[0].getnewaddress()
# privkey
address3 = self.nodes[0].getnewaddress()
- address3_privkey = self.nodes[0].dumpprivkey(address3) # Using privkey
+ address3_privkey = self.nodes[0].dumpprivkey(address3) # Using privkey
- #Check only one address
+ # Check only one address
address_info = self.nodes[0].getaddressinfo(address1)
assert_equal(address_info['ismine'], True)
self.sync_all()
- #Node 1 sync test
- assert_equal(self.nodes[1].getblockcount(),101)
+ # Node 1 sync test
+ assert_equal(self.nodes[1].getblockcount(), 101)
- #Address Test - before import
+ # Address Test - before import
address_info = self.nodes[1].getaddressinfo(address1)
assert_equal(address_info['iswatchonly'], False)
assert_equal(address_info['ismine'], False)
@@ -47,7 +53,7 @@ class ImportPrunedFundsTest(BitcoinTestFramework):
assert_equal(address_info['iswatchonly'], False)
assert_equal(address_info['ismine'], False)
- #Send funds to self
+ # Send funds to self
txnid1 = self.nodes[0].sendtoaddress(address1, 0.1)
self.nodes[0].generate(1)
rawtxn1 = self.nodes[0].gettransaction(txnid1)['hex']
@@ -65,19 +71,19 @@ class ImportPrunedFundsTest(BitcoinTestFramework):
self.sync_all()
- #Import with no affiliated address
+ # Import with no affiliated address
assert_raises_rpc_error(-5, "No addresses", self.nodes[1].importprunedfunds, rawtxn1, proof1)
balance1 = self.nodes[1].getbalance("", 0, True)
assert_equal(balance1, Decimal(0))
- #Import with affiliated address with no rescan
+ # Import with affiliated address with no rescan
self.nodes[1].importaddress(address2, "add2", False)
self.nodes[1].importprunedfunds(rawtxn2, proof2)
balance2 = self.nodes[1].getbalance("add2", 0, True)
assert_equal(balance2, Decimal('0.05'))
- #Import with private key with no rescan
+ # Import with private key with no rescan
self.nodes[1].importprivkey(privkey=address3_privkey, label="add3", rescan=False)
self.nodes[1].importprunedfunds(rawtxn3, proof3)
balance3 = self.nodes[1].getbalance("add3", 0, False)
@@ -85,7 +91,7 @@ class ImportPrunedFundsTest(BitcoinTestFramework):
balance3 = self.nodes[1].getbalance("*", 0, True)
assert_equal(balance3, Decimal('0.075'))
- #Addresses Test - after import
+ # Addresses Test - after import
address_info = self.nodes[1].getaddressinfo(address1)
assert_equal(address_info['iswatchonly'], False)
assert_equal(address_info['ismine'], False)
@@ -96,7 +102,7 @@ class ImportPrunedFundsTest(BitcoinTestFramework):
assert_equal(address_info['iswatchonly'], False)
assert_equal(address_info['ismine'], True)
- #Remove transactions
+ # Remove transactions
assert_raises_rpc_error(-8, "Transaction does not exist in wallet.", self.nodes[1].removeprunedfunds, txnid1)
balance1 = self.nodes[1].getbalance("*", 0, True)
diff --git a/test/functional/wallet_keypool.py b/test/functional/wallet_keypool.py
index 9825e4d894..505014e48f 100755
--- a/test/functional/wallet_keypool.py
+++ b/test/functional/wallet_keypool.py
@@ -17,7 +17,7 @@ class KeyPoolTest(BitcoinTestFramework):
addr_before_encrypting_data = nodes[0].getaddressinfo(addr_before_encrypting)
wallet_info_old = nodes[0].getwalletinfo()
assert(addr_before_encrypting_data['hdmasterkeyid'] == wallet_info_old['hdmasterkeyid'])
-
+
# Encrypt wallet and wait to terminate
nodes[0].node_encrypt_wallet('test')
# Restart node 0
diff --git a/test/functional/wallet_keypool_topup.py b/test/functional/wallet_keypool_topup.py
index 30a0c9a760..d657dc30c4 100755
--- a/test/functional/wallet_keypool_topup.py
+++ b/test/functional/wallet_keypool_topup.py
@@ -25,7 +25,7 @@ class KeypoolRestoreTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 2
- self.extra_args = [[], ['-keypool=100', '-keypoolmin=20']]
+ self.extra_args = [[], ['-keypool=100']]
def run_test(self):
wallet_path = os.path.join(self.nodes[1].datadir, "regtest", "wallets", "wallet.dat")
diff --git a/test/functional/wallet_labels.py b/test/functional/wallet_labels.py
index 90eefc0438..705dd8985e 100755
--- a/test/functional/wallet_labels.py
+++ b/test/functional/wallet_labels.py
@@ -6,25 +6,38 @@
RPCs tested are:
- getlabeladdress
- - getaddressesbyaccount
+ - getaddressesbyaccount/getaddressesbylabel
- listaddressgroupings
- setlabel
- sendfrom (with account arguments)
- move (with account arguments)
+
+Run the test twice - once using the accounts API and once using the labels API.
+The accounts API test can be removed in V0.18.
"""
from collections import defaultdict
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import assert_equal
+from test_framework.util import assert_equal, assert_raises_rpc_error
class WalletLabelsTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
- self.num_nodes = 1
- self.extra_args = [[]]
+ self.num_nodes = 2
+ self.extra_args = [['-deprecatedrpc=accounts'], []]
+
+ def setup_network(self):
+ """Don't connect nodes."""
+ self.setup_nodes()
def run_test(self):
- node = self.nodes[0]
+ """Run the test twice - once using the accounts API and once using the labels API."""
+ self.log.info("Test accounts API")
+ self._run_subtest(True, self.nodes[0])
+ self.log.info("Test labels API")
+ self._run_subtest(False, self.nodes[1])
+
+ def _run_subtest(self, accounts_api, node):
# Check that there's no UTXO on any of the nodes
assert_equal(len(node.listunspent()), 0)
@@ -77,7 +90,7 @@ class WalletLabelsTest(BitcoinTestFramework):
# Create labels and make sure subsequent label API calls
# recognize the label/address associations.
- labels = [Label(name) for name in ("a", "b", "c", "d", "e")]
+ labels = [Label(name, accounts_api) for name in ("a", "b", "c", "d", "e")]
for label in labels:
label.add_receive_address(node.getlabeladdress(label=label.name, force=True))
label.verify(node)
@@ -101,21 +114,23 @@ class WalletLabelsTest(BitcoinTestFramework):
# Check that sendfrom label reduces listaccounts balances.
for i, label in enumerate(labels):
- to_label = labels[(i+1) % len(labels)]
+ to_label = labels[(i + 1) % len(labels)]
node.sendfrom(label.name, to_label.receive_address, amount_to_send)
node.generate(1)
for label in labels:
label.add_receive_address(node.getlabeladdress(label.name))
label.verify(node)
assert_equal(node.getreceivedbylabel(label.name), 2)
- node.move(label.name, "", node.getbalance(label.name))
+ if accounts_api:
+ node.move(label.name, "", node.getbalance(label.name))
label.verify(node)
node.generate(101)
expected_account_balances = {"": 5200}
for label in labels:
expected_account_balances[label.name] = 0
- assert_equal(node.listaccounts(), expected_account_balances)
- assert_equal(node.getbalance(""), 5200)
+ if accounts_api:
+ assert_equal(node.listaccounts(), expected_account_balances)
+ assert_equal(node.getbalance(""), 5200)
# Check that setlabel can assign a label to a new unused address.
for label in labels:
@@ -123,7 +138,10 @@ class WalletLabelsTest(BitcoinTestFramework):
node.setlabel(address, label.name)
label.add_address(address)
label.verify(node)
- assert(address not in node.getaddressesbyaccount(""))
+ if accounts_api:
+ assert(address not in node.getaddressesbyaccount(""))
+ else:
+ assert_raises_rpc_error(-11, "No addresses with label", node.getaddressesbylabel, "")
# Check that addmultisigaddress can assign labels.
for label in labels:
@@ -136,8 +154,9 @@ class WalletLabelsTest(BitcoinTestFramework):
label.verify(node)
node.sendfrom("", multisig_address, 50)
node.generate(101)
- for label in labels:
- assert_equal(node.getbalance(label.name), 50)
+ if accounts_api:
+ for label in labels:
+ assert_equal(node.getbalance(label.name), 50)
# Check that setlabel can change the label of an address from a
# different label.
@@ -156,9 +175,10 @@ class WalletLabelsTest(BitcoinTestFramework):
change_label(node, labels[2].receive_address, labels[2], labels[2])
class Label:
- def __init__(self, name):
+ def __init__(self, name, accounts_api):
# Label name
self.name = name
+ self.accounts_api = accounts_api
# Current receiving address associated with this label.
self.receive_address = None
# List of all addresses assigned with this label
@@ -184,13 +204,16 @@ class Label:
node.getaddressinfo(address)['labels'][0],
{"name": self.name,
"purpose": self.purpose[address]})
- assert_equal(node.getaccount(address), self.name)
+ if self.accounts_api:
+ assert_equal(node.getaccount(address), self.name)
+ else:
+ assert_equal(node.getaddressinfo(address)['label'], self.name)
assert_equal(
node.getaddressesbylabel(self.name),
{address: {"purpose": self.purpose[address]} for address in self.addresses})
- assert_equal(
- set(node.getaddressesbyaccount(self.name)), set(self.addresses))
+ if self.accounts_api:
+ assert_equal(set(node.getaddressesbyaccount(self.name)), set(self.addresses))
def change_label(node, address, old_label, new_label):
diff --git a/test/functional/wallet_listreceivedby.py b/test/functional/wallet_listreceivedby.py
index 7b34febddc..7447211296 100755
--- a/test/functional/wallet_listreceivedby.py
+++ b/test/functional/wallet_listreceivedby.py
@@ -50,37 +50,37 @@ class ReceivedByTest(BitcoinTestFramework):
{"address": empty_addr},
{"address": empty_addr, "label": "", "amount": 0, "confirmations": 0, "txids": []})
- #Test Address filtering
- #Only on addr
- expected = {"address":addr, "label":"", "amount":Decimal("0.1"), "confirmations":10, "txids":[txid,]}
+ # Test Address filtering
+ # Only on addr
+ expected = {"address": addr, "label": "", "amount": Decimal("0.1"), "confirmations": 10, "txids": [txid, ]}
res = self.nodes[1].listreceivedbyaddress(minconf=0, include_empty=True, include_watchonly=True, address_filter=addr)
- assert_array_result(res, {"address":addr}, expected)
+ assert_array_result(res, {"address": addr}, expected)
assert_equal(len(res), 1)
- #Error on invalid address
+ # Error on invalid address
assert_raises_rpc_error(-4, "address_filter parameter was invalid", self.nodes[1].listreceivedbyaddress, minconf=0, include_empty=True, include_watchonly=True, address_filter="bamboozling")
- #Another address receive money
+ # Another address receive money
res = self.nodes[1].listreceivedbyaddress(0, True, True)
- assert_equal(len(res), 2) #Right now 2 entries
+ assert_equal(len(res), 2) # Right now 2 entries
other_addr = self.nodes[1].getnewaddress()
txid2 = self.nodes[0].sendtoaddress(other_addr, 0.1)
self.nodes[0].generate(1)
self.sync_all()
- #Same test as above should still pass
- expected = {"address":addr, "label":"", "amount":Decimal("0.1"), "confirmations":11, "txids":[txid,]}
+ # Same test as above should still pass
+ expected = {"address": addr, "label": "", "amount": Decimal("0.1"), "confirmations": 11, "txids": [txid, ]}
res = self.nodes[1].listreceivedbyaddress(0, True, True, addr)
- assert_array_result(res, {"address":addr}, expected)
+ assert_array_result(res, {"address": addr}, expected)
assert_equal(len(res), 1)
- #Same test as above but with other_addr should still pass
- expected = {"address":other_addr, "label":"", "amount":Decimal("0.1"), "confirmations":1, "txids":[txid2,]}
+ # Same test as above but with other_addr should still pass
+ expected = {"address": other_addr, "label": "", "amount": Decimal("0.1"), "confirmations": 1, "txids": [txid2, ]}
res = self.nodes[1].listreceivedbyaddress(0, True, True, other_addr)
- assert_array_result(res, {"address":other_addr}, expected)
+ assert_array_result(res, {"address": other_addr}, expected)
assert_equal(len(res), 1)
- #Should be two entries though without filter
+ # Should be two entries though without filter
res = self.nodes[1].listreceivedbyaddress(0, True, True)
- assert_equal(len(res), 3) #Became 3 entries
+ assert_equal(len(res), 3) # Became 3 entries
- #Not on random addr
- other_addr = self.nodes[0].getnewaddress() # note on node[0]! just a random addr
+ # Not on random addr
+ other_addr = self.nodes[0].getnewaddress() # note on node[0]! just a random addr
res = self.nodes[1].listreceivedbyaddress(0, True, True, other_addr)
assert_equal(len(res), 0)
@@ -111,8 +111,9 @@ class ReceivedByTest(BitcoinTestFramework):
self.log.info("listreceivedbylabel + getreceivedbylabel Test")
# set pre-state
- addrArr = self.nodes[1].getnewaddress()
- label = self.nodes[1].getaccount(addrArr)
+ label = ''
+ address = self.nodes[1].getnewaddress()
+ assert_equal(self.nodes[1].getaddressinfo(address)['label'], label)
received_by_label_json = [r for r in self.nodes[1].listreceivedbylabel() if r["label"] == label][0]
balance_by_label = self.nodes[1].getreceivedbylabel(label)
@@ -140,7 +141,8 @@ class ReceivedByTest(BitcoinTestFramework):
assert_equal(balance, balance_by_label + Decimal("0.1"))
# Create a new label named "mynewlabel" that has a 0 balance
- self.nodes[1].getlabeladdress(label="mynewlabel", force=True)
+ address = self.nodes[1].getnewaddress()
+ self.nodes[1].setlabel(address, "mynewlabel")
received_by_label_json = [r for r in self.nodes[1].listreceivedbylabel(0, True) if r["label"] == "mynewlabel"][0]
# Test includeempty of listreceivedbylabel
diff --git a/test/functional/wallet_listsinceblock.py b/test/functional/wallet_listsinceblock.py
index 0f2434ff0d..63c179411c 100755
--- a/test/functional/wallet_listsinceblock.py
+++ b/test/functional/wallet_listsinceblock.py
@@ -149,26 +149,26 @@ class ListSinceBlockTest (BitcoinTestFramework):
# send from nodes[1] using utxo to nodes[0]
change = '%.8f' % (float(utxo['amount']) - 1.0003)
- recipientDict = {
+ recipient_dict = {
self.nodes[0].getnewaddress(): 1,
self.nodes[1].getnewaddress(): change,
}
- utxoDicts = [{
+ utxo_dicts = [{
'txid': utxo['txid'],
'vout': utxo['vout'],
}]
txid1 = self.nodes[1].sendrawtransaction(
self.nodes[1].signrawtransactionwithwallet(
- self.nodes[1].createrawtransaction(utxoDicts, recipientDict))['hex'])
+ self.nodes[1].createrawtransaction(utxo_dicts, recipient_dict))['hex'])
# send from nodes[2] using utxo to nodes[3]
- recipientDict2 = {
+ recipient_dict2 = {
self.nodes[3].getnewaddress(): 1,
self.nodes[2].getnewaddress(): change,
}
self.nodes[2].sendrawtransaction(
self.nodes[2].signrawtransactionwithwallet(
- self.nodes[2].createrawtransaction(utxoDicts, recipientDict2))['hex'])
+ self.nodes[2].createrawtransaction(utxo_dicts, recipient_dict2))['hex'])
# generate on both sides
lastblockhash = self.nodes[1].generate(3)[2]
@@ -224,16 +224,16 @@ class ListSinceBlockTest (BitcoinTestFramework):
utxos = self.nodes[2].listunspent()
utxo = utxos[0]
change = '%.8f' % (float(utxo['amount']) - 1.0003)
- recipientDict = {
+ recipient_dict = {
self.nodes[0].getnewaddress(): 1,
self.nodes[2].getnewaddress(): change,
}
- utxoDicts = [{
+ utxo_dicts = [{
'txid': utxo['txid'],
'vout': utxo['vout'],
}]
signedtxres = self.nodes[2].signrawtransactionwithwallet(
- self.nodes[2].createrawtransaction(utxoDicts, recipientDict))
+ self.nodes[2].createrawtransaction(utxo_dicts, recipient_dict))
assert signedtxres['complete']
signedtx = signedtxres['hex']
diff --git a/test/functional/rpc_listtransactions.py b/test/functional/wallet_listtransactions.py
index 0dd7372e6b..7cf2e456cf 100755
--- a/test/functional/rpc_listtransactions.py
+++ b/test/functional/wallet_listtransactions.py
@@ -3,13 +3,20 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the listtransactions API."""
-
-from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import *
-from test_framework.mininode import CTransaction, COIN
+from decimal import Decimal
from io import BytesIO
-def txFromHex(hexstring):
+from test_framework.mininode import CTransaction, COIN
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (
+ assert_array_result,
+ assert_equal,
+ bytes_to_hex_str,
+ hex_str_to_bytes,
+ sync_mempools,
+)
+
+def tx_from_hex(hexstring):
tx = CTransaction()
f = BytesIO(hex_str_to_bytes(hexstring))
tx.deserialize(f)
@@ -25,61 +32,61 @@ class ListTransactionsTest(BitcoinTestFramework):
txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
self.sync_all()
assert_array_result(self.nodes[0].listtransactions(),
- {"txid":txid},
- {"category":"send","account":"","amount":Decimal("-0.1"),"confirmations":0})
+ {"txid": txid},
+ {"category": "send", "amount": Decimal("-0.1"), "confirmations": 0})
assert_array_result(self.nodes[1].listtransactions(),
- {"txid":txid},
- {"category":"receive","account":"","amount":Decimal("0.1"),"confirmations":0})
+ {"txid": txid},
+ {"category": "receive", "amount": Decimal("0.1"), "confirmations": 0})
# mine a block, confirmations should change:
self.nodes[0].generate(1)
self.sync_all()
assert_array_result(self.nodes[0].listtransactions(),
- {"txid":txid},
- {"category":"send","account":"","amount":Decimal("-0.1"),"confirmations":1})
+ {"txid": txid},
+ {"category": "send", "amount": Decimal("-0.1"), "confirmations": 1})
assert_array_result(self.nodes[1].listtransactions(),
- {"txid":txid},
- {"category":"receive","account":"","amount":Decimal("0.1"),"confirmations":1})
+ {"txid": txid},
+ {"category": "receive", "amount": Decimal("0.1"), "confirmations": 1})
# send-to-self:
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 0.2)
assert_array_result(self.nodes[0].listtransactions(),
- {"txid":txid, "category":"send"},
- {"amount":Decimal("-0.2")})
+ {"txid": txid, "category": "send"},
+ {"amount": Decimal("-0.2")})
assert_array_result(self.nodes[0].listtransactions(),
- {"txid":txid, "category":"receive"},
- {"amount":Decimal("0.2")})
+ {"txid": txid, "category": "receive"},
+ {"amount": Decimal("0.2")})
# sendmany from node1: twice to self, twice to node2:
- send_to = { self.nodes[0].getnewaddress() : 0.11,
- self.nodes[1].getnewaddress() : 0.22,
- self.nodes[0].getaccountaddress("from1") : 0.33,
- self.nodes[1].getaccountaddress("toself") : 0.44 }
+ send_to = {self.nodes[0].getnewaddress(): 0.11,
+ self.nodes[1].getnewaddress(): 0.22,
+ self.nodes[0].getnewaddress(): 0.33,
+ self.nodes[1].getnewaddress(): 0.44}
txid = self.nodes[1].sendmany("", send_to)
self.sync_all()
assert_array_result(self.nodes[1].listtransactions(),
- {"category":"send","amount":Decimal("-0.11")},
- {"txid":txid} )
+ {"category": "send", "amount": Decimal("-0.11")},
+ {"txid": txid})
assert_array_result(self.nodes[0].listtransactions(),
- {"category":"receive","amount":Decimal("0.11")},
- {"txid":txid} )
+ {"category": "receive", "amount": Decimal("0.11")},
+ {"txid": txid})
assert_array_result(self.nodes[1].listtransactions(),
- {"category":"send","amount":Decimal("-0.22")},
- {"txid":txid} )
+ {"category": "send", "amount": Decimal("-0.22")},
+ {"txid": txid})
assert_array_result(self.nodes[1].listtransactions(),
- {"category":"receive","amount":Decimal("0.22")},
- {"txid":txid} )
+ {"category": "receive", "amount": Decimal("0.22")},
+ {"txid": txid})
assert_array_result(self.nodes[1].listtransactions(),
- {"category":"send","amount":Decimal("-0.33")},
- {"txid":txid} )
+ {"category": "send", "amount": Decimal("-0.33")},
+ {"txid": txid})
assert_array_result(self.nodes[0].listtransactions(),
- {"category":"receive","amount":Decimal("0.33")},
- {"txid":txid, "account" : "from1"} )
+ {"category": "receive", "amount": Decimal("0.33")},
+ {"txid": txid})
assert_array_result(self.nodes[1].listtransactions(),
- {"category":"send","amount":Decimal("-0.44")},
- {"txid":txid, "account" : ""} )
+ {"category": "send", "amount": Decimal("-0.44")},
+ {"txid": txid})
assert_array_result(self.nodes[1].listtransactions(),
- {"category":"receive","amount":Decimal("0.44")},
- {"txid":txid, "account" : "toself"} )
+ {"category": "receive", "amount": Decimal("0.44")},
+ {"txid": txid})
pubkey = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress())['pubkey']
multisig = self.nodes[1].createmultisig(1, [pubkey])
@@ -87,10 +94,9 @@ class ListTransactionsTest(BitcoinTestFramework):
txid = self.nodes[1].sendtoaddress(multisig["address"], 0.1)
self.nodes[1].generate(1)
self.sync_all()
- assert(len(self.nodes[0].listtransactions("watchonly", 100, 0, False)) == 0)
- assert_array_result(self.nodes[0].listtransactions("watchonly", 100, 0, True),
- {"category":"receive","amount":Decimal("0.1")},
- {"txid":txid, "account" : "watchonly"} )
+ assert not [tx for tx in self.nodes[0].listtransactions(dummy="*", count=100, skip=0, include_watchonly=False) if "label" in tx and tx["label"] == "watchonly"]
+ txs = [tx for tx in self.nodes[0].listtransactions(dummy="*", count=100, skip=0, include_watchonly=True) if "label" in tx and tx['label'] == 'watchonly']
+ assert_array_result(txs, {"category": "receive", "amount": Decimal("0.1")}, {"txid": txid})
self.run_rbf_opt_in_test()
@@ -116,9 +122,9 @@ class ListTransactionsTest(BitcoinTestFramework):
# 1. Chain a few transactions that don't opt-in.
txid_1 = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 1)
assert(not is_opt_in(self.nodes[0], txid_1))
- assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"})
+ assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_1}, {"bip125-replaceable": "no"})
sync_mempools(self.nodes)
- assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_1}, {"bip125-replaceable":"no"})
+ assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_1}, {"bip125-replaceable": "no"})
# Tx2 will build off txid_1, still not opting in to RBF.
utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[0], txid_1)
@@ -128,7 +134,7 @@ class ListTransactionsTest(BitcoinTestFramework):
assert_equal(utxo_to_use["safe"], False)
# Create tx2 using createrawtransaction
- inputs = [{"txid":utxo_to_use["txid"], "vout":utxo_to_use["vout"]}]
+ inputs = [{"txid": utxo_to_use["txid"], "vout": utxo_to_use["vout"]}]
outputs = {self.nodes[0].getnewaddress(): 0.999}
tx2 = self.nodes[1].createrawtransaction(inputs, outputs)
tx2_signed = self.nodes[1].signrawtransactionwithwallet(tx2)["hex"]
@@ -136,51 +142,51 @@ class ListTransactionsTest(BitcoinTestFramework):
# ...and check the result
assert(not is_opt_in(self.nodes[1], txid_2))
- assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"})
+ assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_2}, {"bip125-replaceable": "no"})
sync_mempools(self.nodes)
- assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_2}, {"bip125-replaceable":"no"})
+ assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_2}, {"bip125-replaceable": "no"})
# Tx3 will opt-in to RBF
utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[0], txid_2)
- inputs = [{"txid": txid_2, "vout":utxo_to_use["vout"]}]
+ inputs = [{"txid": txid_2, "vout": utxo_to_use["vout"]}]
outputs = {self.nodes[1].getnewaddress(): 0.998}
tx3 = self.nodes[0].createrawtransaction(inputs, outputs)
- tx3_modified = txFromHex(tx3)
+ tx3_modified = tx_from_hex(tx3)
tx3_modified.vin[0].nSequence = 0
tx3 = bytes_to_hex_str(tx3_modified.serialize())
tx3_signed = self.nodes[0].signrawtransactionwithwallet(tx3)['hex']
txid_3 = self.nodes[0].sendrawtransaction(tx3_signed)
assert(is_opt_in(self.nodes[0], txid_3))
- assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"})
+ assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_3}, {"bip125-replaceable": "yes"})
sync_mempools(self.nodes)
- assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_3}, {"bip125-replaceable":"yes"})
+ assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_3}, {"bip125-replaceable": "yes"})
# Tx4 will chain off tx3. Doesn't signal itself, but depends on one
# that does.
utxo_to_use = get_unconfirmed_utxo_entry(self.nodes[1], txid_3)
- inputs = [{"txid": txid_3, "vout":utxo_to_use["vout"]}]
+ inputs = [{"txid": txid_3, "vout": utxo_to_use["vout"]}]
outputs = {self.nodes[0].getnewaddress(): 0.997}
tx4 = self.nodes[1].createrawtransaction(inputs, outputs)
tx4_signed = self.nodes[1].signrawtransactionwithwallet(tx4)["hex"]
txid_4 = self.nodes[1].sendrawtransaction(tx4_signed)
assert(not is_opt_in(self.nodes[1], txid_4))
- assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"})
+ assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable": "yes"})
sync_mempools(self.nodes)
- assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"yes"})
+ assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable": "yes"})
# Replace tx3, and check that tx4 becomes unknown
tx3_b = tx3_modified
- tx3_b.vout[0].nValue -= int(Decimal("0.004") * COIN) # bump the fee
+ tx3_b.vout[0].nValue -= int(Decimal("0.004") * COIN) # bump the fee
tx3_b = bytes_to_hex_str(tx3_b.serialize())
tx3_b_signed = self.nodes[0].signrawtransactionwithwallet(tx3_b)['hex']
txid_3b = self.nodes[0].sendrawtransaction(tx3_b_signed, True)
assert(is_opt_in(self.nodes[0], txid_3b))
- assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"})
+ assert_array_result(self.nodes[0].listtransactions(), {"txid": txid_4}, {"bip125-replaceable": "unknown"})
sync_mempools(self.nodes)
- assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable":"unknown"})
+ assert_array_result(self.nodes[1].listtransactions(), {"txid": txid_4}, {"bip125-replaceable": "unknown"})
# Check gettransaction as well:
for n in self.nodes[0:2]:
@@ -196,7 +202,5 @@ class ListTransactionsTest(BitcoinTestFramework):
assert_equal(self.nodes[0].gettransaction(txid_3b)["bip125-replaceable"], "no")
assert_equal(self.nodes[0].gettransaction(txid_4)["bip125-replaceable"], "unknown")
-
if __name__ == '__main__':
ListTransactionsTest().main()
-
diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py
index 0a24d34398..e0571ea8f9 100755
--- a/test/functional/wallet_multiwallet.py
+++ b/test/functional/wallet_multiwallet.py
@@ -91,6 +91,19 @@ class MultiWalletTest(BitcoinTestFramework):
open(not_a_dir, 'a').close()
self.nodes[0].assert_start_raises_init_error(['-walletdir=' + not_a_dir], 'Error: Specified -walletdir "' + not_a_dir + '" is not a directory')
+ self.log.info("Do not allow -zapwallettxes with multiwallet")
+ self.nodes[0].assert_start_raises_init_error(['-zapwallettxes', '-wallet=w1', '-wallet=w2'], "Error: -zapwallettxes is only allowed with a single wallet file")
+ self.nodes[0].assert_start_raises_init_error(['-zapwallettxes=1', '-wallet=w1', '-wallet=w2'], "Error: -zapwallettxes is only allowed with a single wallet file")
+ self.nodes[0].assert_start_raises_init_error(['-zapwallettxes=2', '-wallet=w1', '-wallet=w2'], "Error: -zapwallettxes is only allowed with a single wallet file")
+
+ self.log.info("Do not allow -salvagewallet with multiwallet")
+ self.nodes[0].assert_start_raises_init_error(['-salvagewallet', '-wallet=w1', '-wallet=w2'], "Error: -salvagewallet is only allowed with a single wallet file")
+ self.nodes[0].assert_start_raises_init_error(['-salvagewallet=1', '-wallet=w1', '-wallet=w2'], "Error: -salvagewallet is only allowed with a single wallet file")
+
+ self.log.info("Do not allow -upgradewallet with multiwallet")
+ self.nodes[0].assert_start_raises_init_error(['-upgradewallet', '-wallet=w1', '-wallet=w2'], "Error: -upgradewallet is only allowed with a single wallet file")
+ self.nodes[0].assert_start_raises_init_error(['-upgradewallet=1', '-wallet=w1', '-wallet=w2'], "Error: -upgradewallet is only allowed with a single wallet file")
+
# if wallets/ doesn't exist, datadir should be the default wallet dir
wallet_dir2 = data_dir('walletdir')
os.rename(wallet_dir(), wallet_dir2)
@@ -150,5 +163,12 @@ class MultiWalletTest(BitcoinTestFramework):
assert_equal(batch[0]["result"]["chain"], "regtest")
assert_equal(batch[1]["result"]["walletname"], "w1")
+ self.log.info('Check for per-wallet settxfee call')
+ assert_equal(w1.getwalletinfo()['paytxfee'], 0)
+ assert_equal(w2.getwalletinfo()['paytxfee'], 0)
+ w2.settxfee(4.0)
+ assert_equal(w1.getwalletinfo()['paytxfee'], 0)
+ assert_equal(w2.getwalletinfo()['paytxfee'], 4.0)
+
if __name__ == '__main__':
MultiWalletTest().main()
diff --git a/test/functional/wallet_txn_clone.py b/test/functional/wallet_txn_clone.py
index d742ec4618..72ae2d5db7 100755
--- a/test/functional/wallet_txn_clone.py
+++ b/test/functional/wallet_txn_clone.py
@@ -5,7 +5,12 @@
"""Test the wallet accounts properly when there are cloned transactions with malleated scriptsigs."""
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import *
+from test_framework.util import (
+ assert_equal,
+ connect_nodes,
+ disconnect_nodes,
+ sync_blocks,
+)
class TxnMallTest(BitcoinTestFramework):
def set_test_params(self):
@@ -25,55 +30,53 @@ class TxnMallTest(BitcoinTestFramework):
def run_test(self):
if self.options.segwit:
- output_type="p2sh-segwit"
+ output_type = "p2sh-segwit"
else:
- output_type="legacy"
+ output_type = "legacy"
# All nodes should start with 1,250 BTC:
starting_balance = 1250
for i in range(4):
assert_equal(self.nodes[i].getbalance(), starting_balance)
- self.nodes[i].getnewaddress("") # bug workaround, coins generated assigned to first getnewaddress!
+ self.nodes[i].getnewaddress() # bug workaround, coins generated assigned to first getnewaddress!
- # Assign coins to foo and bar accounts:
self.nodes[0].settxfee(.001)
- node0_address_foo = self.nodes[0].getnewaddress("foo", output_type)
- fund_foo_txid = self.nodes[0].sendfrom("", node0_address_foo, 1219)
- fund_foo_tx = self.nodes[0].gettransaction(fund_foo_txid)
+ node0_address1 = self.nodes[0].getnewaddress(address_type=output_type)
+ node0_txid1 = self.nodes[0].sendtoaddress(node0_address1, 1219)
+ node0_tx1 = self.nodes[0].gettransaction(node0_txid1)
- node0_address_bar = self.nodes[0].getnewaddress("bar", output_type)
- fund_bar_txid = self.nodes[0].sendfrom("", node0_address_bar, 29)
- fund_bar_tx = self.nodes[0].gettransaction(fund_bar_txid)
+ node0_address2 = self.nodes[0].getnewaddress(address_type=output_type)
+ node0_txid2 = self.nodes[0].sendtoaddress(node0_address2, 29)
+ node0_tx2 = self.nodes[0].gettransaction(node0_txid2)
- assert_equal(self.nodes[0].getbalance(""),
- starting_balance - 1219 - 29 + fund_foo_tx["fee"] + fund_bar_tx["fee"])
+ assert_equal(self.nodes[0].getbalance(),
+ starting_balance + node0_tx1["fee"] + node0_tx2["fee"])
# Coins are sent to node1_address
- node1_address = self.nodes[1].getnewaddress("from0")
+ node1_address = self.nodes[1].getnewaddress()
- # Send tx1, and another transaction tx2 that won't be cloned
- txid1 = self.nodes[0].sendfrom("foo", node1_address, 40, 0)
- txid2 = self.nodes[0].sendfrom("bar", node1_address, 20, 0)
+ # Send tx1, and another transaction tx2 that won't be cloned
+ txid1 = self.nodes[0].sendtoaddress(node1_address, 40)
+ txid2 = self.nodes[0].sendtoaddress(node1_address, 20)
- # Construct a clone of tx1, to be malleated
- rawtx1 = self.nodes[0].getrawtransaction(txid1,1)
- clone_inputs = [{"txid":rawtx1["vin"][0]["txid"],"vout":rawtx1["vin"][0]["vout"]}]
- clone_outputs = {rawtx1["vout"][0]["scriptPubKey"]["addresses"][0]:rawtx1["vout"][0]["value"],
- rawtx1["vout"][1]["scriptPubKey"]["addresses"][0]:rawtx1["vout"][1]["value"]}
+ # Construct a clone of tx1, to be malleated
+ rawtx1 = self.nodes[0].getrawtransaction(txid1, 1)
+ clone_inputs = [{"txid": rawtx1["vin"][0]["txid"], "vout": rawtx1["vin"][0]["vout"]}]
+ clone_outputs = {rawtx1["vout"][0]["scriptPubKey"]["addresses"][0]: rawtx1["vout"][0]["value"],
+ rawtx1["vout"][1]["scriptPubKey"]["addresses"][0]: rawtx1["vout"][1]["value"]}
clone_locktime = rawtx1["locktime"]
clone_raw = self.nodes[0].createrawtransaction(clone_inputs, clone_outputs, clone_locktime)
# createrawtransaction randomizes the order of its outputs, so swap them if necessary.
# output 0 is at version+#inputs+input+sigstub+sequence+#outputs
# 40 BTC serialized is 00286bee00000000
- pos0 = 2*(4+1+36+1+4+1)
+ pos0 = 2 * (4 + 1 + 36 + 1 + 4 + 1)
hex40 = "00286bee00000000"
- output_len = 16 + 2 + 2 * int("0x" + clone_raw[pos0 + 16 : pos0 + 16 + 2], 0)
- if (rawtx1["vout"][0]["value"] == 40 and clone_raw[pos0 : pos0 + 16] != hex40 or
- rawtx1["vout"][0]["value"] != 40 and clone_raw[pos0 : pos0 + 16] == hex40):
- output0 = clone_raw[pos0 : pos0 + output_len]
- output1 = clone_raw[pos0 + output_len : pos0 + 2 * output_len]
+ output_len = 16 + 2 + 2 * int("0x" + clone_raw[pos0 + 16:pos0 + 16 + 2], 0)
+ if (rawtx1["vout"][0]["value"] == 40 and clone_raw[pos0:pos0 + 16] != hex40 or rawtx1["vout"][0]["value"] != 40 and clone_raw[pos0:pos0 + 16] == hex40):
+ output0 = clone_raw[pos0:pos0 + output_len]
+ output1 = clone_raw[pos0 + output_len:pos0 + 2 * output_len]
clone_raw = clone_raw[:pos0] + output1 + output0 + clone_raw[pos0 + 2 * output_len:]
# Use a different signature hash type to sign. This creates an equivalent but malleated clone.
@@ -91,27 +94,22 @@ class TxnMallTest(BitcoinTestFramework):
# Node0's balance should be starting balance, plus 50BTC for another
# matured block, minus tx1 and tx2 amounts, and minus transaction fees:
- expected = starting_balance + fund_foo_tx["fee"] + fund_bar_tx["fee"]
- if self.options.mine_block: expected += 50
+ expected = starting_balance + node0_tx1["fee"] + node0_tx2["fee"]
+ if self.options.mine_block:
+ expected += 50
expected += tx1["amount"] + tx1["fee"]
expected += tx2["amount"] + tx2["fee"]
assert_equal(self.nodes[0].getbalance(), expected)
- # foo and bar accounts should be debited:
- assert_equal(self.nodes[0].getbalance("foo", 0), 1219 + tx1["amount"] + tx1["fee"])
- assert_equal(self.nodes[0].getbalance("bar", 0), 29 + tx2["amount"] + tx2["fee"])
-
if self.options.mine_block:
assert_equal(tx1["confirmations"], 1)
assert_equal(tx2["confirmations"], 1)
- # Node1's "from0" balance should be both transaction amounts:
- assert_equal(self.nodes[1].getbalance("from0"), -(tx1["amount"] + tx2["amount"]))
else:
assert_equal(tx1["confirmations"], 0)
assert_equal(tx2["confirmations"], 0)
# Send clone and its parent to miner
- self.nodes[2].sendrawtransaction(fund_foo_tx["hex"])
+ self.nodes[2].sendrawtransaction(node0_tx1["hex"])
txid1_clone = self.nodes[2].sendrawtransaction(tx1_clone["hex"])
if self.options.segwit:
assert_equal(txid1, txid1_clone)
@@ -122,7 +120,7 @@ class TxnMallTest(BitcoinTestFramework):
# Reconnect the split network, and sync chain:
connect_nodes(self.nodes[1], 2)
- self.nodes[2].sendrawtransaction(fund_bar_tx["hex"])
+ self.nodes[2].sendrawtransaction(node0_tx2["hex"])
self.nodes[2].sendrawtransaction(tx2["hex"])
self.nodes[2].generate(1) # Mine another block to make sure we sync
sync_blocks(self.nodes)
@@ -131,7 +129,7 @@ class TxnMallTest(BitcoinTestFramework):
tx1 = self.nodes[0].gettransaction(txid1)
tx1_clone = self.nodes[0].gettransaction(txid1_clone)
tx2 = self.nodes[0].gettransaction(txid2)
-
+
# Verify expected confirmations
assert_equal(tx1["confirmations"], -2)
assert_equal(tx1_clone["confirmations"], 2)
@@ -140,27 +138,9 @@ class TxnMallTest(BitcoinTestFramework):
# Check node0's total balance; should be same as before the clone, + 100 BTC for 2 matured,
# less possible orphaned matured subsidy
expected += 100
- if (self.options.mine_block):
+ if (self.options.mine_block):
expected -= 50
assert_equal(self.nodes[0].getbalance(), expected)
- assert_equal(self.nodes[0].getbalance("*", 0), expected)
-
- # Check node0's individual account balances.
- # "foo" should have been debited by the equivalent clone of tx1
- assert_equal(self.nodes[0].getbalance("foo"), 1219 + tx1["amount"] + tx1["fee"])
- # "bar" should have been debited by (possibly unconfirmed) tx2
- assert_equal(self.nodes[0].getbalance("bar", 0), 29 + tx2["amount"] + tx2["fee"])
- # "" should have starting balance, less funding txes, plus subsidies
- assert_equal(self.nodes[0].getbalance("", 0), starting_balance
- - 1219
- + fund_foo_tx["fee"]
- - 29
- + fund_bar_tx["fee"]
- + 100)
-
- # Node1's "from0" account balance
- assert_equal(self.nodes[1].getbalance("from0", 0), -(tx1["amount"] + tx2["amount"]))
if __name__ == '__main__':
TxnMallTest().main()
-
diff --git a/test/functional/wallet_txn_doublespend.py b/test/functional/wallet_txn_doublespend.py
index f16756eeaa..7ee60d5611 100755
--- a/test/functional/wallet_txn_doublespend.py
+++ b/test/functional/wallet_txn_doublespend.py
@@ -3,9 +3,16 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the wallet accounts properly when there is a double-spend conflict."""
+from decimal import Decimal
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import *
+from test_framework.util import (
+ assert_equal,
+ connect_nodes,
+ disconnect_nodes,
+ find_output,
+ sync_blocks,
+)
class TxnMallTest(BitcoinTestFramework):
def set_test_params(self):
@@ -27,21 +34,21 @@ class TxnMallTest(BitcoinTestFramework):
for i in range(4):
assert_equal(self.nodes[i].getbalance(), starting_balance)
self.nodes[i].getnewaddress("") # bug workaround, coins generated assigned to first getnewaddress!
-
- # Assign coins to foo and bar accounts:
- node0_address_foo = self.nodes[0].getnewaddress("foo")
- fund_foo_txid = self.nodes[0].sendfrom("", node0_address_foo, 1219)
+
+ # Assign coins to foo and bar addresses:
+ node0_address_foo = self.nodes[0].getnewaddress()
+ fund_foo_txid = self.nodes[0].sendtoaddress(node0_address_foo, 1219)
fund_foo_tx = self.nodes[0].gettransaction(fund_foo_txid)
- node0_address_bar = self.nodes[0].getnewaddress("bar")
- fund_bar_txid = self.nodes[0].sendfrom("", node0_address_bar, 29)
+ node0_address_bar = self.nodes[0].getnewaddress()
+ fund_bar_txid = self.nodes[0].sendtoaddress(node0_address_bar, 29)
fund_bar_tx = self.nodes[0].gettransaction(fund_bar_txid)
- assert_equal(self.nodes[0].getbalance(""),
- starting_balance - 1219 - 29 + fund_foo_tx["fee"] + fund_bar_tx["fee"])
+ assert_equal(self.nodes[0].getbalance(),
+ starting_balance + fund_foo_tx["fee"] + fund_bar_tx["fee"])
# Coins are sent to node1_address
- node1_address = self.nodes[1].getnewaddress("from0")
+ node1_address = self.nodes[1].getnewaddress()
# First: use raw transaction API to send 1240 BTC to node1_address,
# but don't broadcast:
@@ -62,9 +69,9 @@ class TxnMallTest(BitcoinTestFramework):
assert_equal(doublespend["complete"], True)
# Create two spends using 1 50 BTC coin each
- txid1 = self.nodes[0].sendfrom("foo", node1_address, 40, 0)
- txid2 = self.nodes[0].sendfrom("bar", node1_address, 20, 0)
-
+ txid1 = self.nodes[0].sendtoaddress(node1_address, 40)
+ txid2 = self.nodes[0].sendtoaddress(node1_address, 20)
+
# Have node0 mine a block:
if (self.options.mine_block):
self.nodes[0].generate(1)
@@ -76,24 +83,21 @@ class TxnMallTest(BitcoinTestFramework):
# Node0's balance should be starting balance, plus 50BTC for another
# matured block, minus 40, minus 20, and minus transaction fees:
expected = starting_balance + fund_foo_tx["fee"] + fund_bar_tx["fee"]
- if self.options.mine_block: expected += 50
+ if self.options.mine_block:
+ expected += 50
expected += tx1["amount"] + tx1["fee"]
expected += tx2["amount"] + tx2["fee"]
assert_equal(self.nodes[0].getbalance(), expected)
- # foo and bar accounts should be debited:
- assert_equal(self.nodes[0].getbalance("foo", 0), 1219+tx1["amount"]+tx1["fee"])
- assert_equal(self.nodes[0].getbalance("bar", 0), 29+tx2["amount"]+tx2["fee"])
-
if self.options.mine_block:
assert_equal(tx1["confirmations"], 1)
assert_equal(tx2["confirmations"], 1)
- # Node1's "from0" balance should be both transaction amounts:
- assert_equal(self.nodes[1].getbalance("from0"), -(tx1["amount"]+tx2["amount"]))
+ # Node1's balance should be both transaction amounts:
+ assert_equal(self.nodes[1].getbalance(), starting_balance - tx1["amount"] - tx2["amount"])
else:
assert_equal(tx1["confirmations"], 0)
assert_equal(tx2["confirmations"], 0)
-
+
# Now give doublespend and its parents to miner:
self.nodes[2].sendrawtransaction(fund_foo_tx["hex"])
self.nodes[2].sendrawtransaction(fund_bar_tx["hex"])
@@ -115,29 +119,14 @@ class TxnMallTest(BitcoinTestFramework):
assert_equal(tx1["confirmations"], -2)
assert_equal(tx2["confirmations"], -2)
- # Node0's total balance should be starting balance, plus 100BTC for
+ # Node0's total balance should be starting balance, plus 100BTC for
# two more matured blocks, minus 1240 for the double-spend, plus fees (which are
# negative):
expected = starting_balance + 100 - 1240 + fund_foo_tx["fee"] + fund_bar_tx["fee"] + doublespend_fee
assert_equal(self.nodes[0].getbalance(), expected)
- assert_equal(self.nodes[0].getbalance("*"), expected)
-
- # Final "" balance is starting_balance - amount moved to accounts - doublespend + subsidies +
- # fees (which are negative)
- assert_equal(self.nodes[0].getbalance("foo"), 1219)
- assert_equal(self.nodes[0].getbalance("bar"), 29)
- assert_equal(self.nodes[0].getbalance(""), starting_balance
- -1219
- - 29
- -1240
- + 100
- + fund_foo_tx["fee"]
- + fund_bar_tx["fee"]
- + doublespend_fee)
-
- # Node1's "from0" account balance should be just the doublespend:
- assert_equal(self.nodes[1].getbalance("from0"), 1240)
+
+ # Node1's balance should be its initial balance (1250 for 25 block rewards) plus the doublespend:
+ assert_equal(self.nodes[1].getbalance(), 1250 + 1240)
if __name__ == '__main__':
TxnMallTest().main()
-
diff --git a/test/util/data/blanktxv1.json b/test/util/data/blanktxv1.json
index 9fe2de649b..3d5a1cccae 100644
--- a/test/util/data/blanktxv1.json
+++ b/test/util/data/blanktxv1.json
@@ -4,6 +4,7 @@
"version": 1,
"size": 10,
"vsize": 10,
+ "weight": 40,
"locktime": 0,
"vin": [
],
diff --git a/test/util/data/blanktxv2.json b/test/util/data/blanktxv2.json
index e97626e421..8374a34adc 100644
--- a/test/util/data/blanktxv2.json
+++ b/test/util/data/blanktxv2.json
@@ -4,6 +4,7 @@
"version": 2,
"size": 10,
"vsize": 10,
+ "weight": 40,
"locktime": 0,
"vin": [
],
diff --git a/test/util/data/tt-delin1-out.json b/test/util/data/tt-delin1-out.json
index de647f98b6..9fc2ddc376 100644
--- a/test/util/data/tt-delin1-out.json
+++ b/test/util/data/tt-delin1-out.json
@@ -4,6 +4,7 @@
"version": 1,
"size": 3040,
"vsize": 3040,
+ "weight": 12160,
"locktime": 0,
"vin": [
{
diff --git a/test/util/data/tt-delout1-out.json b/test/util/data/tt-delout1-out.json
index 067ffe74e7..922d048900 100644
--- a/test/util/data/tt-delout1-out.json
+++ b/test/util/data/tt-delout1-out.json
@@ -4,6 +4,7 @@
"version": 1,
"size": 3155,
"vsize": 3155,
+ "weight": 12620,
"locktime": 0,
"vin": [
{
diff --git a/test/util/data/tt-locktime317000-out.json b/test/util/data/tt-locktime317000-out.json
index af7903d1dd..c97206f1ea 100644
--- a/test/util/data/tt-locktime317000-out.json
+++ b/test/util/data/tt-locktime317000-out.json
@@ -4,6 +4,7 @@
"version": 1,
"size": 3189,
"vsize": 3189,
+ "weight": 12756,
"locktime": 317000,
"vin": [
{
diff --git a/test/util/data/txcreate1.json b/test/util/data/txcreate1.json
index 83a86649e0..ca9eacd546 100644
--- a/test/util/data/txcreate1.json
+++ b/test/util/data/txcreate1.json
@@ -4,6 +4,7 @@
"version": 2,
"size": 201,
"vsize": 201,
+ "weight": 804,
"locktime": 0,
"vin": [
{
diff --git a/test/util/data/txcreate2.json b/test/util/data/txcreate2.json
index cca00f752b..ee9b9c3c17 100644
--- a/test/util/data/txcreate2.json
+++ b/test/util/data/txcreate2.json
@@ -4,6 +4,7 @@
"version": 2,
"size": 19,
"vsize": 19,
+ "weight": 76,
"locktime": 0,
"vin": [
],
diff --git a/test/util/data/txcreatedata1.json b/test/util/data/txcreatedata1.json
index 15a4246ae5..39909c2e3f 100644
--- a/test/util/data/txcreatedata1.json
+++ b/test/util/data/txcreatedata1.json
@@ -4,6 +4,7 @@
"version": 1,
"size": 176,
"vsize": 176,
+ "weight": 704,
"locktime": 0,
"vin": [
{
diff --git a/test/util/data/txcreatedata2.json b/test/util/data/txcreatedata2.json
index cb93c27971..2958006e58 100644
--- a/test/util/data/txcreatedata2.json
+++ b/test/util/data/txcreatedata2.json
@@ -4,6 +4,7 @@
"version": 2,
"size": 176,
"vsize": 176,
+ "weight": 704,
"locktime": 0,
"vin": [
{
diff --git a/test/util/data/txcreatedata_seq0.json b/test/util/data/txcreatedata_seq0.json
index 4b5a7cab4a..a6656b5ad5 100644
--- a/test/util/data/txcreatedata_seq0.json
+++ b/test/util/data/txcreatedata_seq0.json
@@ -4,6 +4,7 @@
"version": 2,
"size": 85,
"vsize": 85,
+ "weight": 340,
"locktime": 0,
"vin": [
{
diff --git a/test/util/data/txcreatedata_seq1.json b/test/util/data/txcreatedata_seq1.json
index dea48ba373..e5980427b1 100644
--- a/test/util/data/txcreatedata_seq1.json
+++ b/test/util/data/txcreatedata_seq1.json
@@ -4,6 +4,7 @@
"version": 1,
"size": 126,
"vsize": 126,
+ "weight": 504,
"locktime": 0,
"vin": [
{
diff --git a/test/util/data/txcreatemultisig1.json b/test/util/data/txcreatemultisig1.json
index 72e20c8691..c32e755db1 100644
--- a/test/util/data/txcreatemultisig1.json
+++ b/test/util/data/txcreatemultisig1.json
@@ -4,6 +4,7 @@
"version": 1,
"size": 124,
"vsize": 124,
+ "weight": 496,
"locktime": 0,
"vin": [
],
diff --git a/test/util/data/txcreatemultisig2.json b/test/util/data/txcreatemultisig2.json
index 7d94ce7396..f97d265894 100644
--- a/test/util/data/txcreatemultisig2.json
+++ b/test/util/data/txcreatemultisig2.json
@@ -4,6 +4,7 @@
"version": 1,
"size": 42,
"vsize": 42,
+ "weight": 168,
"locktime": 0,
"vin": [
],
diff --git a/test/util/data/txcreatemultisig3.json b/test/util/data/txcreatemultisig3.json
index 6c5b49d876..b355d7b191 100644
--- a/test/util/data/txcreatemultisig3.json
+++ b/test/util/data/txcreatemultisig3.json
@@ -4,6 +4,7 @@
"version": 1,
"size": 53,
"vsize": 53,
+ "weight": 212,
"locktime": 0,
"vin": [
],
diff --git a/test/util/data/txcreatemultisig4.json b/test/util/data/txcreatemultisig4.json
index 9a5d2f4a06..a00dbe3f5d 100644
--- a/test/util/data/txcreatemultisig4.json
+++ b/test/util/data/txcreatemultisig4.json
@@ -4,6 +4,7 @@
"version": 1,
"size": 42,
"vsize": 42,
+ "weight": 168,
"locktime": 0,
"vin": [
],
diff --git a/test/util/data/txcreatemultisig5.json b/test/util/data/txcreatemultisig5.json
index 20e9bb077b..ea07822ddd 100644
--- a/test/util/data/txcreatemultisig5.json
+++ b/test/util/data/txcreatemultisig5.json
@@ -4,6 +4,7 @@
"version": 2,
"size": 42,
"vsize": 42,
+ "weight": 168,
"locktime": 0,
"vin": [
],
diff --git a/test/util/data/txcreateoutpubkey1.json b/test/util/data/txcreateoutpubkey1.json
index 2704ed7673..32097b3ebe 100644
--- a/test/util/data/txcreateoutpubkey1.json
+++ b/test/util/data/txcreateoutpubkey1.json
@@ -4,6 +4,7 @@
"version": 1,
"size": 54,
"vsize": 54,
+ "weight": 216,
"locktime": 0,
"vin": [
],
diff --git a/test/util/data/txcreateoutpubkey2.json b/test/util/data/txcreateoutpubkey2.json
index 4ba5dcb282..c0ee181ede 100644
--- a/test/util/data/txcreateoutpubkey2.json
+++ b/test/util/data/txcreateoutpubkey2.json
@@ -4,6 +4,7 @@
"version": 1,
"size": 41,
"vsize": 41,
+ "weight": 164,
"locktime": 0,
"vin": [
],
diff --git a/test/util/data/txcreateoutpubkey3.json b/test/util/data/txcreateoutpubkey3.json
index 0a5d489e15..4d904df3c8 100644
--- a/test/util/data/txcreateoutpubkey3.json
+++ b/test/util/data/txcreateoutpubkey3.json
@@ -4,6 +4,7 @@
"version": 1,
"size": 42,
"vsize": 42,
+ "weight": 168,
"locktime": 0,
"vin": [
],
diff --git a/test/util/data/txcreatescript1.json b/test/util/data/txcreatescript1.json
index 5072452fed..af1c4c35e2 100644
--- a/test/util/data/txcreatescript1.json
+++ b/test/util/data/txcreatescript1.json
@@ -4,6 +4,7 @@
"version": 1,
"size": 20,
"vsize": 20,
+ "weight": 80,
"locktime": 0,
"vin": [
],
diff --git a/test/util/data/txcreatescript2.json b/test/util/data/txcreatescript2.json
index 94b669ffb6..32dd644579 100644
--- a/test/util/data/txcreatescript2.json
+++ b/test/util/data/txcreatescript2.json
@@ -4,6 +4,7 @@
"version": 1,
"size": 42,
"vsize": 42,
+ "weight": 168,
"locktime": 0,
"vin": [
],
diff --git a/test/util/data/txcreatescript3.json b/test/util/data/txcreatescript3.json
index 31b6459214..b9192d9a82 100644
--- a/test/util/data/txcreatescript3.json
+++ b/test/util/data/txcreatescript3.json
@@ -4,6 +4,7 @@
"version": 1,
"size": 53,
"vsize": 53,
+ "weight": 212,
"locktime": 0,
"vin": [
],
diff --git a/test/util/data/txcreatescript4.json b/test/util/data/txcreatescript4.json
index eecdf858b7..2271ecfa0a 100644
--- a/test/util/data/txcreatescript4.json
+++ b/test/util/data/txcreatescript4.json
@@ -4,6 +4,7 @@
"version": 1,
"size": 42,
"vsize": 42,
+ "weight": 168,
"locktime": 0,
"vin": [
],
diff --git a/test/util/data/txcreatesignv1.json b/test/util/data/txcreatesignv1.json
index 92a3f76a07..64e5137f4b 100644
--- a/test/util/data/txcreatesignv1.json
+++ b/test/util/data/txcreatesignv1.json
@@ -4,6 +4,7 @@
"version": 1,
"size": 224,
"vsize": 224,
+ "weight": 896,
"locktime": 0,
"vin": [
{
diff --git a/test/util/rpcauth-test.py b/test/util/rpcauth-test.py
new file mode 100755
index 0000000000..2456feb102
--- /dev/null
+++ b/test/util/rpcauth-test.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python3
+# Copyright (c) 2015-2018 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 share/rpcauth/rpcauth.py
+"""
+import base64
+import configparser
+import hmac
+import importlib
+import os
+import sys
+import unittest
+
+class TestRPCAuth(unittest.TestCase):
+ def setUp(self):
+ config = configparser.ConfigParser()
+ config_path = os.path.abspath(
+ os.path.join(os.sep, os.path.abspath(os.path.dirname(__file__)),
+ "../config.ini"))
+ with open(config_path) as config_file:
+ config.read_file(config_file)
+ sys.path.insert(0, os.path.dirname(config['environment']['RPCAUTH']))
+ self.rpcauth = importlib.import_module('rpcauth')
+
+ def test_generate_salt(self):
+ self.assertLessEqual(len(self.rpcauth.generate_salt()), 32)
+ self.assertGreaterEqual(len(self.rpcauth.generate_salt()), 16)
+
+ def test_generate_password(self):
+ password = self.rpcauth.generate_password()
+ expected_password = base64.urlsafe_b64encode(
+ base64.urlsafe_b64decode(password)).decode('utf-8')
+ self.assertEqual(expected_password, password)
+
+ def test_check_password_hmac(self):
+ salt = self.rpcauth.generate_salt()
+ password = self.rpcauth.generate_password()
+ password_hmac = self.rpcauth.password_to_hmac(salt, password)
+
+ m = hmac.new(bytearray(salt, 'utf-8'),
+ bytearray(password, 'utf-8'), 'SHA256')
+ expected_password_hmac = m.hexdigest()
+
+ self.assertEqual(expected_password_hmac, password_hmac)
+
+if __name__ == '__main__':
+ unittest.main()