aboutsummaryrefslogtreecommitdiff
path: root/test/functional
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional')
-rw-r--r--test/functional/README.md22
-rwxr-xr-xtest/functional/create_cache.py3
-rwxr-xr-xtest/functional/deprecated_rpc.py23
-rwxr-xr-xtest/functional/example_test.py14
-rwxr-xr-xtest/functional/feature_assumevalid.py (renamed from test/functional/assumevalid.py)22
-rwxr-xr-xtest/functional/feature_bip68_sequence.py (renamed from test/functional/bip68-sequence.py)5
-rwxr-xr-xtest/functional/feature_bip9_softforks.py (renamed from test/functional/bip9-softforks.py)8
-rwxr-xr-xtest/functional/feature_block.py (renamed from test/functional/p2p-fullblocktest.py)12
-rwxr-xr-xtest/functional/feature_cltv.py (renamed from test/functional/bip65-cltv-p2p.py)4
-rwxr-xr-xtest/functional/feature_config_args.py49
-rwxr-xr-xtest/functional/feature_csv_activation.py (renamed from test/functional/bip68-112-113-p2p.py)8
-rwxr-xr-xtest/functional/feature_dbcrash.py (renamed from test/functional/dbcrash.py)0
-rwxr-xr-xtest/functional/feature_dersig.py (renamed from test/functional/bipdersig-p2p.py)4
-rwxr-xr-xtest/functional/feature_fee_estimation.py (renamed from test/functional/smartfees.py)163
-rwxr-xr-xtest/functional/feature_maxuploadtarget.py (renamed from test/functional/maxuploadtarget.py)6
-rwxr-xr-xtest/functional/feature_minchainwork.py (renamed from test/functional/minchainwork.py)0
-rwxr-xr-xtest/functional/feature_notifications.py (renamed from test/functional/notifications.py)2
-rwxr-xr-xtest/functional/feature_nulldummy.py (renamed from test/functional/nulldummy.py)12
-rwxr-xr-xtest/functional/feature_proxy.py (renamed from test/functional/proxy_test.py)2
-rwxr-xr-xtest/functional/feature_pruning.py (renamed from test/functional/pruning.py)2
-rwxr-xr-xtest/functional/feature_rbf.py (renamed from test/functional/replace-by-fee.py)2
-rwxr-xr-xtest/functional/feature_reindex.py (renamed from test/functional/reindex.py)2
-rwxr-xr-xtest/functional/feature_segwit.py (renamed from test/functional/segwit.py)147
-rwxr-xr-xtest/functional/feature_uacomment.py (renamed from test/functional/uacomment.py)2
-rwxr-xr-xtest/functional/feature_versionbits_warning.py112
-rwxr-xr-xtest/functional/interface_bitcoin_cli.py (renamed from test/functional/bitcoin_cli.py)2
-rwxr-xr-xtest/functional/interface_http.py (renamed from test/functional/httpbasics.py)2
-rwxr-xr-xtest/functional/interface_rest.py (renamed from test/functional/rest.py)2
-rwxr-xr-xtest/functional/interface_zmq.py (renamed from test/functional/zmq_test.py)2
-rwxr-xr-xtest/functional/invalidtxrequest.py73
-rwxr-xr-xtest/functional/mempool_limit.py14
-rwxr-xr-xtest/functional/mempool_packages.py2
-rwxr-xr-xtest/functional/mempool_persist.py9
-rwxr-xr-xtest/functional/mempool_reorg.py2
-rwxr-xr-xtest/functional/mempool_resurrect.py (renamed from test/functional/mempool_resurrect_test.py)2
-rwxr-xr-xtest/functional/mempool_spend_coinbase.py (renamed from test/functional/mempool_spendcoinbase.py)2
-rwxr-xr-xtest/functional/mining_basic.py (renamed from test/functional/mining.py)2
-rwxr-xr-xtest/functional/mining_getblocktemplate_longpoll.py (renamed from test/functional/getblocktemplate_longpoll.py)2
-rwxr-xr-xtest/functional/mining_prioritisetransaction.py (renamed from test/functional/prioritise_transaction.py)21
-rwxr-xr-xtest/functional/node_network_limited.py81
-rwxr-xr-xtest/functional/p2p-versionbits-warning.py121
-rwxr-xr-xtest/functional/p2p_compactblocks.py (renamed from test/functional/p2p-compactblocks.py)6
-rwxr-xr-xtest/functional/p2p_disconnect_ban.py (renamed from test/functional/disconnect_ban.py)2
-rwxr-xr-xtest/functional/p2p_feefilter.py (renamed from test/functional/p2p-feefilter.py)4
-rwxr-xr-xtest/functional/p2p_fingerprint.py (renamed from test/functional/p2p-fingerprint.py)6
-rwxr-xr-xtest/functional/p2p_invalid_block.py (renamed from test/functional/invalidblockrequest.py)5
-rwxr-xr-xtest/functional/p2p_invalid_tx.py55
-rwxr-xr-xtest/functional/p2p_leak.py (renamed from test/functional/p2p-leaktests.py)8
-rwxr-xr-xtest/functional/p2p_mempool.py (renamed from test/functional/p2p-mempool.py)4
-rwxr-xr-xtest/functional/p2p_node_network_limited.py57
-rwxr-xr-xtest/functional/p2p_segwit.py (renamed from test/functional/p2p-segwit.py)20
-rwxr-xr-xtest/functional/p2p_sendheaders.py (renamed from test/functional/sendheaders.py)6
-rwxr-xr-xtest/functional/p2p_timeouts.py (renamed from test/functional/p2p-timeouts.py)4
-rwxr-xr-xtest/functional/p2p_unrequested_blocks.py (renamed from test/functional/p2p-acceptblock.py)12
-rwxr-xr-xtest/functional/rpc_bind.py (renamed from test/functional/rpcbind_test.py)2
-rwxr-xr-xtest/functional/rpc_blockchain.py (renamed from test/functional/blockchain.py)17
-rwxr-xr-xtest/functional/rpc_decodescript.py (renamed from test/functional/decodescript.py)2
-rwxr-xr-xtest/functional/rpc_deprecated.py27
-rwxr-xr-xtest/functional/rpc_fundrawtransaction.py (renamed from test/functional/fundrawtransaction.py)26
-rwxr-xr-xtest/functional/rpc_getchaintips.py (renamed from test/functional/getchaintips.py)2
-rwxr-xr-xtest/functional/rpc_invalidateblock.py (renamed from test/functional/invalidateblock.py)2
-rwxr-xr-xtest/functional/rpc_listtransactions.py (renamed from test/functional/listtransactions.py)5
-rwxr-xr-xtest/functional/rpc_named_arguments.py (renamed from test/functional/rpcnamedargs.py)2
-rwxr-xr-xtest/functional/rpc_net.py (renamed from test/functional/net.py)0
-rwxr-xr-xtest/functional/rpc_preciousblock.py (renamed from test/functional/preciousblock.py)2
-rwxr-xr-xtest/functional/rpc_rawtransaction.py (renamed from test/functional/rawtransactions.py)91
-rwxr-xr-xtest/functional/rpc_signmessage.py (renamed from test/functional/signmessages.py)3
-rwxr-xr-xtest/functional/rpc_signrawtransaction.py (renamed from test/functional/signrawtransactions.py)2
-rwxr-xr-xtest/functional/rpc_txoutproof.py (renamed from test/functional/merkle_blocks.py)2
-rwxr-xr-xtest/functional/rpc_uptime.py (renamed from test/functional/uptime.py)0
-rwxr-xr-xtest/functional/rpc_users.py (renamed from test/functional/multi_rpc.py)2
-rw-r--r--test/functional/test_framework/address.py2
-rw-r--r--test/functional/test_framework/blockstore.py2
-rw-r--r--test/functional/test_framework/blocktools.py66
-rwxr-xr-xtest/functional/test_framework/comptool.py2
-rw-r--r--test/functional/test_framework/coverage.py2
-rw-r--r--test/functional/test_framework/messages.py35
-rwxr-xr-xtest/functional/test_framework/mininode.py191
-rw-r--r--test/functional/test_framework/netutil.py2
-rw-r--r--test/functional/test_framework/script.py4
-rw-r--r--test/functional/test_framework/siphash.py2
-rw-r--r--test/functional/test_framework/socks5.py2
-rwxr-xr-xtest/functional/test_framework/test_framework.py32
-rwxr-xr-xtest/functional/test_framework/test_node.py88
-rw-r--r--test/functional/test_framework/util.py7
-rwxr-xr-xtest/functional/test_runner.py199
-rwxr-xr-xtest/functional/wallet_abandonconflict.py (renamed from test/functional/abandonconflict.py)10
-rwxr-xr-xtest/functional/wallet_accounts.py (renamed from test/functional/wallet-accounts.py)4
-rwxr-xr-xtest/functional/wallet_address_types.py294
-rwxr-xr-xtest/functional/wallet_backup.py (renamed from test/functional/walletbackup.py)2
-rwxr-xr-xtest/functional/wallet_basic.py (renamed from test/functional/wallet.py)13
-rwxr-xr-xtest/functional/wallet_bumpfee.py (renamed from test/functional/bumpfee.py)20
-rwxr-xr-xtest/functional/wallet_disable.py (renamed from test/functional/disablewallet.py)2
-rwxr-xr-xtest/functional/wallet_dump.py (renamed from test/functional/wallet-dump.py)62
-rwxr-xr-xtest/functional/wallet_encryption.py (renamed from test/functional/wallet-encryption.py)21
-rwxr-xr-xtest/functional/wallet_hd.py (renamed from test/functional/wallet-hd.py)2
-rwxr-xr-xtest/functional/wallet_import_rescan.py (renamed from test/functional/import-rescan.py)4
-rwxr-xr-xtest/functional/wallet_importmulti.py (renamed from test/functional/importmulti.py)11
-rwxr-xr-xtest/functional/wallet_importprunedfunds.py (renamed from test/functional/importprunedfunds.py)2
-rwxr-xr-xtest/functional/wallet_keypool.py (renamed from test/functional/keypool.py)2
-rwxr-xr-xtest/functional/wallet_keypool_topup.py (renamed from test/functional/keypool-topup.py)0
-rwxr-xr-xtest/functional/wallet_listreceivedby.py (renamed from test/functional/receivedby.py)2
-rwxr-xr-xtest/functional/wallet_listsinceblock.py (renamed from test/functional/listsinceblock.py)0
-rwxr-xr-xtest/functional/wallet_multiwallet.py (renamed from test/functional/multiwallet.py)68
-rwxr-xr-xtest/functional/wallet_resendwallettransactions.py (renamed from test/functional/resendwallettransactions.py)0
-rwxr-xr-xtest/functional/wallet_txn_clone.py (renamed from test/functional/txn_clone.py)17
-rwxr-xr-xtest/functional/wallet_txn_doublespend.py (renamed from test/functional/txn_doublespend.py)2
-rwxr-xr-xtest/functional/wallet_zapwallettxes.py (renamed from test/functional/zapwallettxes.py)5
108 files changed, 1678 insertions, 842 deletions
diff --git a/test/functional/README.md b/test/functional/README.md
index 193ca947bc..662b4b44d5 100644
--- a/test/functional/README.md
+++ b/test/functional/README.md
@@ -17,7 +17,7 @@ don't have test cases for.
#### Style guidelines
-- Where possible, try to adhere to [PEP-8 guidelines]([https://www.python.org/dev/peps/pep-0008/)
+- Where possible, try to adhere to [PEP-8 guidelines](https://www.python.org/dev/peps/pep-0008/)
- Use a python linter like flake8 before submitting PRs to catch common style
nits (eg trailing whitespace, unused imports, etc)
- Avoid wildcard imports where possible
@@ -27,6 +27,20 @@ don't have test cases for.
`set_test_params()`, `add_options()` and `setup_xxxx()` methods at the top of
the subclass, then locally-defined helper methods, then the `run_test()` method.
+#### Naming guidelines
+
+- Name the test `<area>_test.py`, where area can be one of the following:
+ - `feature` for tests for full features that aren't wallet/mining/mempool, eg `feature_rbf.py`
+ - `interface` for tests for other interfaces (REST, ZMQ, etc), eg `interface_rest.py`
+ - `mempool` for tests for mempool behaviour, eg `mempool_reorg.py`
+ - `mining` for tests for mining features, eg `mining_prioritisetransaction.py`
+ - `p2p` for tests that explicitly test the p2p interface, eg `p2p_disconnect_ban.py`
+ - `rpc` for tests for individual RPC methods or features, eg `rpc_listtransactions.py`
+ - `wallet` for tests for wallet features, eg `wallet_keypool.py`
+- use an underscore to separate words
+ - exception: for tests for specific RPCs or command line options which don't include underscores, name the test after the exact RPC or argument name, eg `rpc_decodescript.py`, not `rpc_decode_script.py`
+- Don't use the redundant word `test` in the name, eg `interface_zmq.py`, not `interface_zmq_test.py`
+
#### General test-writing advice
- Set `self.num_nodes` to the minimum number of nodes necessary for the test.
@@ -68,12 +82,12 @@ contains the higher level logic for processing P2P payloads and connecting to
the Bitcoin Core node application logic. For custom behaviour, subclass the
P2PInterface object and override the callback methods.
-- Call `NetworkThread.start()` after all `P2PInterface` objects are created to
+- Call `network_thread_start()` after all `P2PInterface` objects are created to
start the networking thread. (Continue with the test logic in your existing
thread.)
- Can be used to write tests where specific P2P protocol behavior is tested.
-Examples tests are `p2p-accept-block.py`, `p2p-compactblocks.py`.
+Examples tests are `p2p_unrequested_blocks.py`, `p2p_compactblocks.py`.
#### Comptool
@@ -119,7 +133,7 @@ Each `TestInstance` consists of:
acceptance is tested against the given outcome.
- For examples of tests written in this framework, see
- `invalidblockrequest.py` and `p2p-fullblocktest.py`.
+ `p2p_invalid_block.py` and `feature_block.py`.
### test-framework modules
diff --git a/test/functional/create_cache.py b/test/functional/create_cache.py
index 7d4d1a529b..9665c50a92 100755
--- a/test/functional/create_cache.py
+++ b/test/functional/create_cache.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2016 The Bitcoin Core developers
+# Copyright (c) 2016-2017 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Create a blockchain cache.
@@ -16,6 +16,7 @@ class CreateCache(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 0
+ self.supports_cli = True
def setup_network(self):
pass
diff --git a/test/functional/deprecated_rpc.py b/test/functional/deprecated_rpc.py
deleted file mode 100755
index 19fd24edb9..0000000000
--- a/test/functional/deprecated_rpc.py
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) 2017 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 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=estimatefee"]]
-
- def run_test(self):
- self.log.info("estimatefee: Shows deprecated message")
- assert_raises_rpc_error(-32, 'estimatefee is deprecated', self.nodes[0].estimatefee, 1)
-
- self.log.info("Using -deprecatedrpc=estimatefee bypasses the error")
- self.nodes[1].estimatefee(1)
-
-if __name__ == '__main__':
- DeprecatedRpcTest().main()
diff --git a/test/functional/example_test.py b/test/functional/example_test.py
index 35a6bd2673..12be685ecf 100755
--- a/test/functional/example_test.py
+++ b/test/functional/example_test.py
@@ -17,11 +17,12 @@ from collections import defaultdict
from test_framework.blocktools import (create_block, create_coinbase)
from test_framework.mininode import (
CInv,
- NetworkThread,
P2PInterface,
mininode_lock,
msg_block,
msg_getdata,
+ network_thread_join,
+ network_thread_start,
)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
@@ -131,12 +132,12 @@ class ExampleTest(BitcoinTestFramework):
def run_test(self):
"""Main test logic"""
- # Create a P2P connection to one of the nodes
+ # Create P2P connections to two of the nodes
self.nodes[0].add_p2p_connection(BaseNode())
# Start up network handling in another thread. This needs to be called
# after the P2P connections have been created.
- NetworkThread().start()
+ network_thread_start()
# wait_for_verack ensures that the P2P connection is fully up.
self.nodes[0].p2p.wait_for_verack()
@@ -188,7 +189,14 @@ class ExampleTest(BitcoinTestFramework):
connect_nodes(self.nodes[1], 2)
self.log.info("Add P2P connection to node2")
+ # We can't add additional P2P connections once the network thread has started. Disconnect the connection
+ # to node0, wait for the network thread to terminate, then connect to node2. This is specific to
+ # the current implementation of the network thread and may be improved in future.
+ self.nodes[0].disconnect_p2ps()
+ network_thread_join()
+
self.nodes[2].add_p2p_connection(BaseNode())
+ network_thread_start()
self.nodes[2].p2p.wait_for_verack()
self.log.info("Wait for node2 reach current tip. Test that it has propagated all the blocks to us")
diff --git a/test/functional/assumevalid.py b/test/functional/feature_assumevalid.py
index 13104f71bc..5a09142412 100755
--- a/test/functional/assumevalid.py
+++ b/test/functional/feature_assumevalid.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 logic for skipping signature validation on old blocks.
@@ -38,7 +38,8 @@ from test_framework.mininode import (CBlockHeader,
CTransaction,
CTxIn,
CTxOut,
- NetworkThread,
+ network_thread_join,
+ network_thread_start,
P2PInterface,
msg_block,
msg_headers)
@@ -98,7 +99,7 @@ class AssumeValidTest(BitcoinTestFramework):
# Connect to node0
p2p0 = self.nodes[0].add_p2p_connection(BaseNode())
- NetworkThread().start() # Start up network handling in another thread
+ network_thread_start()
self.nodes[0].p2p.wait_for_verack()
# Build the blockchain
@@ -159,13 +160,22 @@ class AssumeValidTest(BitcoinTestFramework):
self.block_time += 1
height += 1
+ # We're adding new connections so terminate the network thread
+ self.nodes[0].disconnect_p2ps()
+ network_thread_join()
+
# Start node1 and node2 with assumevalid so they accept a block with a bad signature.
self.start_node(1, extra_args=["-assumevalid=" + hex(block102.sha256)])
- p2p1 = self.nodes[1].add_p2p_connection(BaseNode())
- p2p1.wait_for_verack()
-
self.start_node(2, extra_args=["-assumevalid=" + hex(block102.sha256)])
+
+ p2p0 = self.nodes[0].add_p2p_connection(BaseNode())
+ p2p1 = self.nodes[1].add_p2p_connection(BaseNode())
p2p2 = self.nodes[2].add_p2p_connection(BaseNode())
+
+ network_thread_start()
+
+ p2p0.wait_for_verack()
+ p2p1.wait_for_verack()
p2p2.wait_for_verack()
# send header lists to all three nodes
diff --git a/test/functional/bip68-sequence.py b/test/functional/feature_bip68_sequence.py
index 5f8f21701f..94b13653b9 100755
--- a/test/functional/bip68-sequence.py
+++ b/test/functional/feature_bip68_sequence.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test BIP68 implementation."""
@@ -362,9 +362,10 @@ class BIP68Test(BitcoinTestFramework):
block.vtx.extend([tx1, tx2, tx3])
block.hashMerkleRoot = block.calc_merkle_root()
block.rehash()
+ add_witness_commitment(block)
block.solve()
- self.nodes[0].submitblock(ToHex(block))
+ self.nodes[0].submitblock(bytes_to_hex_str(block.serialize(True)))
assert_equal(self.nodes[0].getbestblockhash(), block.hash)
def activateCSV(self):
diff --git a/test/functional/bip9-softforks.py b/test/functional/feature_bip9_softforks.py
index ec4d1d9365..ae92e9f07c 100755
--- a/test/functional/bip9-softforks.py
+++ b/test/functional/feature_bip9_softforks.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2016 The Bitcoin Core developers
+# Copyright (c) 2015-2017 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 BIP 9 soft forks.
@@ -22,7 +22,7 @@ import itertools
from test_framework.test_framework import ComparisonTestFramework
from test_framework.util import *
-from test_framework.mininode import CTransaction, NetworkThread
+from test_framework.mininode import CTransaction, network_thread_start
from test_framework.blocktools import create_coinbase, create_block
from test_framework.comptool import TestInstance, TestManager
from test_framework.script import CScript, OP_1NEGATE, OP_CHECKSEQUENCEVERIFY, OP_DROP
@@ -36,7 +36,7 @@ class BIP9SoftForksTest(ComparisonTestFramework):
def run_test(self):
self.test = TestManager(self, self.options.tmpdir)
self.test.add_all_connections(self.nodes)
- NetworkThread().start() # Start up network handling in another thread
+ network_thread_start()
self.test.run()
def create_transaction(self, node, coinbase, to_address, amount):
@@ -245,7 +245,7 @@ class BIP9SoftForksTest(ComparisonTestFramework):
self.setup_chain()
self.setup_network()
self.test.add_all_connections(self.nodes)
- NetworkThread().start()
+ network_thread_start()
self.test.p2p_connections[0].wait_for_verack()
def get_tests(self):
diff --git a/test/functional/p2p-fullblocktest.py b/test/functional/feature_block.py
index f19b845a32..fe9bbda14b 100755
--- a/test/functional/p2p-fullblocktest.py
+++ b/test/functional/feature_block.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2016 The Bitcoin Core developers
+# Copyright (c) 2015-2017 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test block processing.
@@ -18,6 +18,7 @@ from test_framework.blocktools import *
import time
from test_framework.key import CECKey
from test_framework.script import *
+from test_framework.mininode import network_thread_start
import struct
class PreviousSpendableOutput():
@@ -35,12 +36,15 @@ class CBrokenBlock(CBlock):
self.vtx = copy.deepcopy(base_block.vtx)
self.hashMerkleRoot = self.calc_merkle_root()
- def serialize(self):
+ def serialize(self, with_witness=False):
r = b""
r += super(CBlock, self).serialize()
r += struct.pack("<BQ", 255, len(self.vtx))
for tx in self.vtx:
- r += tx.serialize()
+ if with_witness:
+ r += tx.serialize_with_witness()
+ else:
+ r += tx.serialize_without_witness()
return r
def normal_serialize(self):
@@ -68,7 +72,7 @@ class FullBlockTest(ComparisonTestFramework):
def run_test(self):
self.test = TestManager(self, self.options.tmpdir)
self.test.add_all_connections(self.nodes)
- NetworkThread().start() # Start up network handling in another thread
+ network_thread_start()
self.test.run()
def add_transactions_to_block(self, block, tx_list):
diff --git a/test/functional/bip65-cltv-p2p.py b/test/functional/feature_cltv.py
index 2af5eb275f..f62ae31654 100755
--- a/test/functional/bip65-cltv-p2p.py
+++ b/test/functional/feature_cltv.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2016 The Bitcoin Core developers
+# Copyright (c) 2015-2017 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 BIP65 (CHECKLOCKTIMEVERIFY).
@@ -68,7 +68,7 @@ class BIP65Test(BitcoinTestFramework):
def run_test(self):
self.nodes[0].add_p2p_connection(P2PInterface())
- NetworkThread().start() # Start up network handling in another thread
+ network_thread_start()
# wait_for_verack ensures that the P2P connection is fully up.
self.nodes[0].p2p.wait_for_verack()
diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py
new file mode 100755
index 0000000000..61abba8082
--- /dev/null
+++ b/test/functional/feature_config_args.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python3
+# Copyright (c) 2017 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 various command line arguments and configuration file parameters."""
+
+import os
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import get_datadir_path
+
+class ConfArgsTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.setup_clean_chain = True
+ self.num_nodes = 1
+
+ def run_test(self):
+ self.stop_node(0)
+ # Remove the -datadir argument so it doesn't override the config file
+ self.nodes[0].args = [arg for arg in self.nodes[0].args if not arg.startswith("-datadir")]
+
+ default_data_dir = get_datadir_path(self.options.tmpdir, 0)
+ new_data_dir = os.path.join(default_data_dir, 'newdatadir')
+ new_data_dir_2 = os.path.join(default_data_dir, 'newdatadir2')
+
+ # Check that using -datadir argument on non-existent directory fails
+ self.nodes[0].datadir = new_data_dir
+ self.assert_start_raises_init_error(0, ['-datadir='+new_data_dir], 'Error: Specified data directory "' + new_data_dir + '" does not exist.')
+
+ # 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:
+ f.write("datadir=" + new_data_dir + "\n")
+ self.assert_start_raises_init_error(0, ['-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
+ os.mkdir(new_data_dir)
+ self.start_node(0, ['-conf='+conf_file, '-wallet=w1'])
+ self.stop_node(0)
+ assert os.path.isfile(os.path.join(new_data_dir, 'regtest', 'wallets', 'w1'))
+
+ # Ensure command line argument overrides datadir in conf
+ os.mkdir(new_data_dir_2)
+ self.nodes[0].datadir = new_data_dir_2
+ self.start_node(0, ['-datadir='+new_data_dir_2, '-conf='+conf_file, '-wallet=w2'])
+ assert os.path.isfile(os.path.join(new_data_dir_2, 'regtest', 'wallets', 'w2'))
+
+if __name__ == '__main__':
+ ConfArgsTest().main()
diff --git a/test/functional/bip68-112-113-p2p.py b/test/functional/feature_csv_activation.py
index 7e6a4f4408..82aa0ff891 100755
--- a/test/functional/bip68-112-113-p2p.py
+++ b/test/functional/feature_csv_activation.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2016 The Bitcoin Core developers
+# Copyright (c) 2015-2017 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 activation of the first version bits soft fork.
@@ -45,7 +45,7 @@ bip112tx_special - test negative argument to OP_CSV
from test_framework.test_framework import ComparisonTestFramework
from test_framework.util import *
-from test_framework.mininode import ToHex, CTransaction, NetworkThread
+from test_framework.mininode import ToHex, CTransaction, network_thread_start
from test_framework.blocktools import create_coinbase, create_block
from test_framework.comptool import TestInstance, TestManager
from test_framework.script import *
@@ -95,12 +95,12 @@ class BIP68_112_113Test(ComparisonTestFramework):
def set_test_params(self):
self.num_nodes = 1
self.setup_clean_chain = True
- self.extra_args = [['-whitelist=127.0.0.1', '-blockversion=4']]
+ self.extra_args = [['-whitelist=127.0.0.1', '-blockversion=4', '-addresstype=legacy']]
def run_test(self):
test = TestManager(self, self.options.tmpdir)
test.add_all_connections(self.nodes)
- NetworkThread().start() # Start up network handling in another thread
+ network_thread_start()
test.run()
def send_generic_input_tx(self, node, coinbases):
diff --git a/test/functional/dbcrash.py b/test/functional/feature_dbcrash.py
index 24b9765b4e..24b9765b4e 100755
--- a/test/functional/dbcrash.py
+++ b/test/functional/feature_dbcrash.py
diff --git a/test/functional/bipdersig-p2p.py b/test/functional/feature_dersig.py
index 7a3e565e2c..3414571678 100755
--- a/test/functional/bipdersig-p2p.py
+++ b/test/functional/feature_dersig.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2016 The Bitcoin Core developers
+# Copyright (c) 2015-2017 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 BIP66 (DER SIG).
@@ -56,7 +56,7 @@ class BIP66Test(BitcoinTestFramework):
def run_test(self):
self.nodes[0].add_p2p_connection(P2PInterface())
- NetworkThread().start() # Start up network handling in another thread
+ network_thread_start()
# wait_for_verack ensures that the P2P connection is fully up.
self.nodes[0].p2p.wait_for_verack()
diff --git a/test/functional/smartfees.py b/test/functional/feature_fee_estimation.py
index 986f4546a8..e1263414bd 100755
--- a/test/functional/smartfees.py
+++ b/test/functional/feature_fee_estimation.py
@@ -1,41 +1,49 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 fee estimation code."""
+from decimal import Decimal
+import random
-from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import *
-from test_framework.script import CScript, OP_1, OP_DROP, OP_2, OP_HASH160, OP_EQUAL, hash160, OP_TRUE
from test_framework.mininode import CTransaction, CTxIn, CTxOut, COutPoint, ToHex, COIN
+from test_framework.script import CScript, OP_1, OP_DROP, OP_2, OP_HASH160, OP_EQUAL, hash160, OP_TRUE
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (
+ assert_equal,
+ assert_greater_than,
+ assert_greater_than_or_equal,
+ connect_nodes,
+ satoshi_round,
+ sync_blocks,
+ sync_mempools,
+)
# Construct 2 trivial P2SH's and the ScriptSigs that spend them
# So we can create many transactions without needing to spend
# time signing.
-redeem_script_1 = CScript([OP_1, OP_DROP])
-redeem_script_2 = CScript([OP_2, OP_DROP])
-P2SH_1 = CScript([OP_HASH160, hash160(redeem_script_1), OP_EQUAL])
-P2SH_2 = CScript([OP_HASH160, hash160(redeem_script_2), OP_EQUAL])
+REDEEM_SCRIPT_1 = CScript([OP_1, OP_DROP])
+REDEEM_SCRIPT_2 = CScript([OP_2, OP_DROP])
+P2SH_1 = CScript([OP_HASH160, hash160(REDEEM_SCRIPT_1), OP_EQUAL])
+P2SH_2 = CScript([OP_HASH160, hash160(REDEEM_SCRIPT_2), OP_EQUAL])
# Associated ScriptSig's to spend satisfy P2SH_1 and P2SH_2
-SCRIPT_SIG = [CScript([OP_TRUE, redeem_script_1]), CScript([OP_TRUE, redeem_script_2])]
-
-global log
+SCRIPT_SIG = [CScript([OP_TRUE, REDEEM_SCRIPT_1]), CScript([OP_TRUE, REDEEM_SCRIPT_2])]
def small_txpuzzle_randfee(from_node, conflist, unconflist, amount, min_fee, fee_increment):
- """
- Create and send a transaction with a random fee.
+ """Create and send a transaction with a random fee.
+
The transaction pays to a trivial P2SH script, and assumes that its inputs
are of the same form.
The function takes a list of confirmed outputs and unconfirmed outputs
and attempts to use the confirmed list first for its inputs.
It adds the newly created outputs to the unconfirmed list.
- Returns (raw transaction, fee)
- """
+ Returns (raw transaction, fee)."""
+
# It's best to exponentially distribute our random fees
# because the buckets are exponentially spaced.
# Exponentially distributed from 1-128 * fee_increment
- rand_fee = float(fee_increment)*(1.1892**random.randint(0,28))
+ rand_fee = float(fee_increment) * (1.1892 ** random.randint(0, 28))
# Total fee ranges from min_fee to min_fee + 127*fee_increment
fee = min_fee - fee_increment + satoshi_round(rand_fee)
tx = CTransaction()
@@ -50,95 +58,69 @@ def small_txpuzzle_randfee(from_node, conflist, unconflist, amount, min_fee, fee
total_in += t["amount"]
tx.vin.append(CTxIn(COutPoint(int(t["txid"], 16), t["vout"]), b""))
if total_in <= amount + fee:
- raise RuntimeError("Insufficient funds: need %d, have %d"%(amount+fee, total_in))
- tx.vout.append(CTxOut(int((total_in - amount - fee)*COIN), P2SH_1))
- tx.vout.append(CTxOut(int(amount*COIN), P2SH_2))
+ raise RuntimeError("Insufficient funds: need %d, have %d" % (amount + fee, total_in))
+ tx.vout.append(CTxOut(int((total_in - amount - fee) * COIN), P2SH_1))
+ tx.vout.append(CTxOut(int(amount * COIN), P2SH_2))
# These transactions don't need to be signed, but we still have to insert
# the ScriptSig that will satisfy the ScriptPubKey.
for inp in tx.vin:
inp.scriptSig = SCRIPT_SIG[inp.prevout.n]
txid = from_node.sendrawtransaction(ToHex(tx), True)
- unconflist.append({ "txid" : txid, "vout" : 0 , "amount" : total_in - amount - fee})
- unconflist.append({ "txid" : txid, "vout" : 1 , "amount" : amount})
+ unconflist.append({"txid": txid, "vout": 0, "amount": total_in - amount - fee})
+ unconflist.append({"txid": txid, "vout": 1, "amount": amount})
return (ToHex(tx), fee)
-def split_inputs(from_node, txins, txouts, initial_split = False):
- """
- We need to generate a lot of inputs so we can generate a ton of transactions.
+def split_inputs(from_node, txins, txouts, initial_split=False):
+ """Generate a lot of inputs so we can generate a ton of transactions.
+
This function takes an input from txins, and creates and sends a transaction
which splits the value into 2 outputs which are appended to txouts.
Previously this was designed to be small inputs so they wouldn't have
- a high coin age when the notion of priority still existed.
- """
+ a high coin age when the notion of priority still existed."""
+
prevtxout = txins.pop()
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(int(prevtxout["txid"], 16), prevtxout["vout"]), b""))
- half_change = satoshi_round(prevtxout["amount"]/2)
- rem_change = prevtxout["amount"] - half_change - Decimal("0.00001000")
- tx.vout.append(CTxOut(int(half_change*COIN), P2SH_1))
- tx.vout.append(CTxOut(int(rem_change*COIN), P2SH_2))
+ half_change = satoshi_round(prevtxout["amount"] / 2)
+ rem_change = prevtxout["amount"] - half_change - Decimal("0.00001000")
+ tx.vout.append(CTxOut(int(half_change * COIN), P2SH_1))
+ tx.vout.append(CTxOut(int(rem_change * COIN), P2SH_2))
# If this is the initial split we actually need to sign the transaction
# Otherwise we just need to insert the proper ScriptSig
- if (initial_split) :
+ if (initial_split):
completetx = from_node.signrawtransaction(ToHex(tx))["hex"]
- else :
+ else:
tx.vin[0].scriptSig = SCRIPT_SIG[prevtxout["vout"]]
completetx = ToHex(tx)
txid = from_node.sendrawtransaction(completetx, True)
- txouts.append({ "txid" : txid, "vout" : 0 , "amount" : half_change})
- txouts.append({ "txid" : txid, "vout" : 1 , "amount" : rem_change})
+ txouts.append({"txid": txid, "vout": 0, "amount": half_change})
+ txouts.append({"txid": txid, "vout": 1, "amount": rem_change})
-def check_estimates(node, fees_seen, max_invalid, print_estimates = True):
- """
- This function calls estimatefee and verifies that the estimates
- meet certain invariants.
- """
- all_estimates = [ node.estimatefee(i) for i in range(1,26) ]
- if print_estimates:
- log.info([str(all_estimates[e-1]) for e in [1,2,3,6,15,25]])
- delta = 1.0e-6 # account for rounding error
- last_e = max(fees_seen)
- for e in [x for x in all_estimates if x >= 0]:
- # Estimates should be within the bounds of what transactions fees actually were:
- if float(e)+delta < min(fees_seen) or float(e)-delta > max(fees_seen):
+def check_estimates(node, fees_seen, max_invalid):
+ """Call estimatesmartfee and verify that the estimates meet certain invariants."""
+
+ delta = 1.0e-6 # account for rounding error
+ last_feerate = float(max(fees_seen))
+ all_smart_estimates = [node.estimatesmartfee(i) for i in range(1, 26)]
+ for i, e in enumerate(all_smart_estimates): # estimate is for i+1
+ feerate = float(e["feerate"])
+ assert_greater_than(feerate, 0)
+
+ if feerate + delta < min(fees_seen) or feerate - delta > max(fees_seen):
raise AssertionError("Estimated fee (%f) out of range (%f,%f)"
- %(float(e), min(fees_seen), max(fees_seen)))
- # Estimates should be monotonically decreasing
- if float(e)-delta > last_e:
+ % (feerate, min(fees_seen), max(fees_seen)))
+ if feerate - delta > last_feerate:
raise AssertionError("Estimated fee (%f) larger than last fee (%f) for lower number of confirms"
- %(float(e),float(last_e)))
- last_e = e
- valid_estimate = False
- invalid_estimates = 0
- for i,e in enumerate(all_estimates): # estimate is for i+1
- if e >= 0:
- valid_estimate = True
- if i >= 13: # for n>=14 estimatesmartfee(n/2) should be at least as high as estimatefee(n)
- assert(node.estimatesmartfee((i+1)//2)["feerate"] > float(e) - delta)
+ % (feerate, last_feerate))
+ last_feerate = feerate
+ if i == 0:
+ assert_equal(e["blocks"], 2)
else:
- invalid_estimates += 1
-
- # estimatesmartfee should still be valid
- approx_estimate = node.estimatesmartfee(i+1)["feerate"]
- answer_found = node.estimatesmartfee(i+1)["blocks"]
- assert(approx_estimate > 0)
- assert(answer_found > i+1)
-
- # Once we're at a high enough confirmation count that we can give an estimate
- # We should have estimates for all higher confirmation counts
- if valid_estimate:
- raise AssertionError("Invalid estimate appears at higher confirm count than valid estimate")
-
- # Check on the expected number of different confirmation counts
- # that we might not have valid estimates for
- if invalid_estimates > max_invalid:
- raise AssertionError("More than (%d) invalid estimates"%(max_invalid))
- return all_estimates
-
+ assert_greater_than_or_equal(i + 1, e["blocks"])
class EstimateFeeTest(BitcoinTestFramework):
def set_test_params(self):
@@ -151,7 +133,7 @@ class EstimateFeeTest(BitcoinTestFramework):
which we will use to generate our transactions.
"""
self.add_nodes(3, extra_args=[["-maxorphantx=1000", "-whitelist=127.0.0.1"],
- ["-blockmaxsize=17000", "-maxorphantx=1000", "-deprecatedrpc=estimatefee"],
+ ["-blockmaxsize=17000", "-maxorphantx=1000"],
["-blockmaxsize=8000", "-maxorphantx=1000"]])
# Use node0 to mine blocks for input splitting
# Node1 mines small blocks but that are bigger than the expected transaction rate.
@@ -160,7 +142,6 @@ class EstimateFeeTest(BitcoinTestFramework):
# Node2 is a stingy miner, that
# produces too small blocks (room for only 55 or so transactions)
-
def transact_and_mine(self, numblocks, mining_node):
min_fee = Decimal("0.00001")
# We will now mine numblocks blocks generating on average 100 transactions between each block
@@ -169,14 +150,14 @@ class EstimateFeeTest(BitcoinTestFramework):
# resorting to tx's that depend on the mempool when those run out
for i in range(numblocks):
random.shuffle(self.confutxo)
- for j in range(random.randrange(100-50,100+50)):
- from_index = random.randint(1,2)
+ for j in range(random.randrange(100 - 50, 100 + 50)):
+ from_index = random.randint(1, 2)
(txhex, fee) = small_txpuzzle_randfee(self.nodes[from_index], self.confutxo,
self.memutxo, Decimal("0.005"), min_fee, min_fee)
tx_kbytes = (len(txhex) // 2) / 1000.0
- self.fees_per_kb.append(float(fee)/tx_kbytes)
+ self.fees_per_kb.append(float(fee) / tx_kbytes)
sync_mempools(self.nodes[0:3], wait=.1)
- mined = mining_node.getblock(mining_node.generate(1)[0],True)["tx"]
+ mined = mining_node.getblock(mining_node.generate(1)[0], True)["tx"]
sync_blocks(self.nodes[0:3], wait=.1)
# update which txouts are confirmed
newmem = []
@@ -191,10 +172,6 @@ class EstimateFeeTest(BitcoinTestFramework):
self.log.info("This test is time consuming, please be patient")
self.log.info("Splitting inputs so we can generate tx's")
- # Make log handler available to helper functions
- global log
- log = self.log
-
# Start node0
self.start_node(0)
self.txouts = []
@@ -210,13 +187,13 @@ class EstimateFeeTest(BitcoinTestFramework):
# Use txouts to monitor the available utxo, since these won't be tracked in wallet
reps = 0
while (reps < 5):
- #Double txouts to txouts2
- while (len(self.txouts)>0):
+ # Double txouts to txouts2
+ while (len(self.txouts) > 0):
split_inputs(self.nodes[0], self.txouts, self.txouts2)
while (len(self.nodes[0].getrawmempool()) > 0):
self.nodes[0].generate(1)
- #Double txouts2 to txouts
- while (len(self.txouts2)>0):
+ # Double txouts2 to txouts
+ while (len(self.txouts2) > 0):
split_inputs(self.nodes[0], self.txouts2, self.txouts)
while (len(self.nodes[0].getrawmempool()) > 0):
self.nodes[0].generate(1)
@@ -235,7 +212,7 @@ class EstimateFeeTest(BitcoinTestFramework):
self.fees_per_kb = []
self.memutxo = []
- self.confutxo = self.txouts # Start with the set of confirmed txouts after splitting
+ self.confutxo = self.txouts # Start with the set of confirmed txouts after splitting
self.log.info("Will output estimates for 1/2/3/6/15/25 blocks")
for i in range(2):
diff --git a/test/functional/maxuploadtarget.py b/test/functional/feature_maxuploadtarget.py
index 5ef71c93cf..45336ee801 100755
--- a/test/functional/maxuploadtarget.py
+++ b/test/functional/feature_maxuploadtarget.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2016 The Bitcoin Core developers
+# Copyright (c) 2015-2017 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 behavior of -maxuploadtarget.
@@ -57,7 +57,7 @@ class MaxUploadTest(BitcoinTestFramework):
for _ in range(3):
p2p_conns.append(self.nodes[0].add_p2p_connection(TestNode()))
- NetworkThread().start() # Start up network handling in another thread
+ network_thread_start()
for p2pc in p2p_conns:
p2pc.wait_for_verack()
@@ -149,7 +149,7 @@ class MaxUploadTest(BitcoinTestFramework):
# Reconnect to self.nodes[0]
self.nodes[0].add_p2p_connection(TestNode())
- NetworkThread().start() # Start up network handling in another thread
+ network_thread_start()
self.nodes[0].p2p.wait_for_verack()
#retrieve 20 blocks which should be enough to break the 1MB limit
diff --git a/test/functional/minchainwork.py b/test/functional/feature_minchainwork.py
index 90a3de0e0d..90a3de0e0d 100755
--- a/test/functional/minchainwork.py
+++ b/test/functional/feature_minchainwork.py
diff --git a/test/functional/notifications.py b/test/functional/feature_notifications.py
index c88972ab91..980bef5fc8 100755
--- a/test/functional/notifications.py
+++ b/test/functional/feature_notifications.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 the -alertnotify, -blocknotify and -walletnotify options."""
diff --git a/test/functional/nulldummy.py b/test/functional/feature_nulldummy.py
index 7bc7c168f4..e4f413cc2a 100755
--- a/test/functional/nulldummy.py
+++ b/test/functional/feature_nulldummy.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2016 The Bitcoin Core developers
+# Copyright (c) 2016-2017 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 NULLDUMMY softfork.
@@ -15,7 +15,7 @@ Generate 427 more blocks.
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
-from test_framework.mininode import CTransaction, NetworkThread
+from test_framework.mininode import CTransaction, network_thread_start
from test_framework.blocktools import create_coinbase, create_block, add_witness_commitment
from test_framework.script import CScript
from io import BytesIO
@@ -42,15 +42,15 @@ class NULLDUMMYTest(BitcoinTestFramework):
self.setup_clean_chain = True
# This script tests NULLDUMMY activation, which is part of the 'segwit' deployment, so we go through
# normal segwit activation here (and don't use the default always-on behaviour).
- self.extra_args = [['-whitelist=127.0.0.1', '-walletprematurewitness', '-vbparams=segwit:0:999999999999']]
+ self.extra_args = [['-whitelist=127.0.0.1', '-walletprematurewitness', '-vbparams=segwit:0:999999999999', '-addresstype=legacy', "-deprecatedrpc=addwitnessaddress"]]
def run_test(self):
self.address = self.nodes[0].getnewaddress()
- self.ms_address = self.nodes[0].addmultisigaddress(1,[self.address])
+ self.ms_address = self.nodes[0].addmultisigaddress(1,[self.address])['address']
self.wit_address = self.nodes[0].addwitnessaddress(self.address)
- self.wit_ms_address = self.nodes[0].addwitnessaddress(self.ms_address)
+ self.wit_ms_address = self.nodes[0].addmultisigaddress(1, [self.address], '', 'p2sh-segwit')['address']
- NetworkThread().start() # Start up network handling in another thread
+ network_thread_start()
self.coinbase_blocks = self.nodes[0].generate(2) # Block 2
coinbase_txid = []
for i in self.coinbase_blocks:
diff --git a/test/functional/proxy_test.py b/test/functional/feature_proxy.py
index 81b99d1bf4..2eb1be47a5 100755
--- a/test/functional/proxy_test.py
+++ b/test/functional/feature_proxy.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2016 The Bitcoin Core developers
+# Copyright (c) 2015-2017 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 bitcoind with different proxy configuration.
diff --git a/test/functional/pruning.py b/test/functional/feature_pruning.py
index 0101f61185..49ad7f838c 100755
--- a/test/functional/pruning.py
+++ b/test/functional/feature_pruning.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 the pruning code.
diff --git a/test/functional/replace-by-fee.py b/test/functional/feature_rbf.py
index 815e964848..6b7ab0f43e 100755
--- a/test/functional/replace-by-fee.py
+++ b/test/functional/feature_rbf.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 the RBF code."""
diff --git a/test/functional/reindex.py b/test/functional/feature_reindex.py
index 1f684a1afe..ac67e6e9ba 100755
--- a/test/functional/reindex.py
+++ b/test/functional/feature_reindex.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 running bitcoind with -reindex and -reindex-chainstate options.
diff --git a/test/functional/segwit.py b/test/functional/feature_segwit.py
index 338fa1bc52..7db05077c9 100755
--- a/test/functional/segwit.py
+++ b/test/functional/feature_segwit.py
@@ -1,13 +1,21 @@
#!/usr/bin/env python3
-# Copyright (c) 2016 The Bitcoin Core developers
+# Copyright (c) 2016-2017 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 the SegWit changeover logic."""
+from test_framework.address import (
+ key_to_p2sh_p2wpkh,
+ key_to_p2wpkh,
+ program_to_witness,
+ script_to_p2sh_p2wsh,
+ script_to_p2wsh,
+)
+from test_framework.blocktools import witness_script, send_to_witness
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, key_to_p2sh_p2wpkh, key_to_p2wpkh, script_to_p2sh_p2wsh, script_to_p2wsh, program_to_witness
+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 io import BytesIO
@@ -16,71 +24,27 @@ NODE_2 = 2
WIT_V0 = 0
WIT_V1 = 1
-# 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):
- # P2WPKH instead
- pubkeyhash = hash160(hex_str_to_bytes(pubkey))
- pkscript = CScript([OP_0, pubkeyhash])
- else:
- # 1-of-1 multisig
- witness_program = CScript([OP_1, hex_str_to_bytes(pubkey), OP_1, OP_CHECKMULTISIG])
- scripthash = sha256(witness_program)
- 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):
- 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)
- else:
- addr = key_to_p2sh_p2wpkh(pubkey) if encode_p2sh else key_to_p2wpkh(pubkey)
- if not encode_p2sh:
- assert_equal(node.validateaddress(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=""):
- tx_to_witness = create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount)
- if (sign):
- signed = node.signrawtransaction(tx_to_witness)
- assert("errors" not in signed or len(["errors"]) == 0)
- return node.sendrawtransaction(signed["hex"])
- else:
- if (insert_redeem_script):
- tx = FromHex(CTransaction(), tx_to_witness)
- tx.vin[0].scriptSig += CScript([hex_str_to_bytes(insert_redeem_script)])
- tx_to_witness = ToHex(tx)
-
- return node.sendrawtransaction(tx_to_witness)
-
def getutxo(txid):
utxo = {}
utxo["vout"] = 0
utxo["txid"] = txid
return utxo
-def find_unspent(node, min_value):
- for utxo in node.listunspent():
- if utxo['amount'] >= min_value:
+def find_spendable_utxo(node, min_value):
+ for utxo in node.listunspent(query_options={'minimumAmount': min_value}):
+ if utxo['spendable']:
return utxo
+ raise AssertionError("Unspent output equal or higher than %s not found" % min_value)
+
class SegWitTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 3
# This test tests SegWit both pre and post-activation, so use the normal BIP9 activation.
- self.extra_args = [["-walletprematurewitness", "-rpcserialversion=0", "-vbparams=segwit:0:999999999999"],
- ["-blockversion=4", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness", "-rpcserialversion=1", "-vbparams=segwit:0:999999999999"],
- ["-blockversion=536870915", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness", "-vbparams=segwit:0:999999999999"]]
+ self.extra_args = [["-walletprematurewitness", "-rpcserialversion=0", "-vbparams=segwit:0:999999999999", "-addresstype=legacy", "-deprecatedrpc=addwitnessaddress"],
+ ["-blockversion=4", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness", "-rpcserialversion=1", "-vbparams=segwit:0:999999999999", "-addresstype=legacy", "-deprecatedrpc=addwitnessaddress"],
+ ["-blockversion=536870915", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness", "-vbparams=segwit:0:999999999999", "-addresstype=legacy", "-deprecatedrpc=addwitnessaddress"]]
def setup_network(self):
super().setup_network()
@@ -133,12 +97,11 @@ class SegWitTest(BitcoinTestFramework):
for i in range(3):
newaddress = self.nodes[i].getnewaddress()
self.pubkey.append(self.nodes[i].validateaddress(newaddress)["pubkey"])
- multiaddress = self.nodes[i].addmultisigaddress(1, [self.pubkey[-1]])
multiscript = CScript([OP_1, hex_str_to_bytes(self.pubkey[-1]), OP_1, OP_CHECKMULTISIG])
- p2sh_addr = self.nodes[i].addwitnessaddress(newaddress, True)
+ p2sh_addr = self.nodes[i].addwitnessaddress(newaddress)
bip173_addr = self.nodes[i].addwitnessaddress(newaddress, False)
- p2sh_ms_addr = self.nodes[i].addwitnessaddress(multiaddress, True)
- bip173_ms_addr = self.nodes[i].addwitnessaddress(multiaddress, False)
+ p2sh_ms_addr = self.nodes[i].addmultisigaddress(1, [self.pubkey[-1]], '', 'p2sh-segwit')['address']
+ bip173_ms_addr = self.nodes[i].addmultisigaddress(1, [self.pubkey[-1]], '', 'bech32')['address']
assert_equal(p2sh_addr, key_to_p2sh_p2wpkh(self.pubkey[-1]))
assert_equal(bip173_addr, key_to_p2wpkh(self.pubkey[-1]))
assert_equal(p2sh_ms_addr, script_to_p2sh_p2wsh(multiscript))
@@ -152,8 +115,8 @@ class SegWitTest(BitcoinTestFramework):
for i in range(5):
for n in range(3):
for v in range(2):
- wit_ids[n][v].append(send_to_witness(v, self.nodes[0], find_unspent(self.nodes[0], 50), self.pubkey[n], False, Decimal("49.999")))
- p2sh_ids[n][v].append(send_to_witness(v, self.nodes[0], find_unspent(self.nodes[0], 50), self.pubkey[n], True, Decimal("49.999")))
+ wit_ids[n][v].append(send_to_witness(v, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[n], False, Decimal("49.999")))
+ p2sh_ids[n][v].append(send_to_witness(v, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[n], True, Decimal("49.999")))
self.nodes[0].generate(1) #block 163
sync_blocks(self.nodes)
@@ -248,7 +211,7 @@ class SegWitTest(BitcoinTestFramework):
# tx2 (segwit input, paying to a non-segwit output) ->
# tx3 (non-segwit input, paying to a non-segwit output).
# tx1 is allowed to appear in the block, but no others.
- txid1 = send_to_witness(1, self.nodes[0], find_unspent(self.nodes[0], 50), self.pubkey[0], False, Decimal("49.996"))
+ txid1 = send_to_witness(1, self.nodes[0], find_spendable_utxo(self.nodes[0], 50), self.pubkey[0], False, Decimal("49.996"))
hex_tx = self.nodes[0].gettransaction(txid)['hex']
tx = FromHex(CTransaction(), hex_tx)
assert(tx.wit.is_null()) # This should not be a segwit input
@@ -328,19 +291,19 @@ class SegWitTest(BitcoinTestFramework):
solvable_anytime = [] # These outputs should be solvable after importpubkey
unseen_anytime = [] # These outputs should never be seen
- uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], compressed_spendable_address[0]]))
- uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], uncompressed_spendable_address[0]]))
- compressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_spendable_address[0]]))
- uncompressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], uncompressed_solvable_address[0]]))
- compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_solvable_address[0]]))
- compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_solvable_address[0], compressed_solvable_address[1]]))
+ uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], compressed_spendable_address[0]])['address'])
+ uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], uncompressed_spendable_address[0]])['address'])
+ compressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_spendable_address[0]])['address'])
+ uncompressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], uncompressed_solvable_address[0]])['address'])
+ compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_solvable_address[0]])['address'])
+ compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_solvable_address[0], compressed_solvable_address[1]])['address'])
unknown_address = ["mtKKyoHabkk6e4ppT7NaM7THqPUt7AzPrT", "2NDP3jLWAFT8NDAiUa9qiE6oBt2awmMq7Dx"]
# Test multisig_without_privkey
# We have 2 public keys without private keys, use addmultisigaddress to add to wallet.
# Money sent to P2SH of multisig of this should only be seen after importaddress with the BASE58 P2SH address.
- multisig_without_privkey_address = self.nodes[0].addmultisigaddress(2, [pubkeys[3], pubkeys[4]])
+ multisig_without_privkey_address = self.nodes[0].addmultisigaddress(2, [pubkeys[3], pubkeys[4]])['address']
script = CScript([OP_2, hex_str_to_bytes(pubkeys[3]), hex_str_to_bytes(pubkeys[4]), OP_2, OP_CHECKMULTISIG])
solvable_after_importaddress.append(CScript([OP_HASH160, hash160(script), OP_EQUAL]))
@@ -356,8 +319,10 @@ class SegWitTest(BitcoinTestFramework):
[p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v)
# normal P2PKH and P2PK with compressed keys should always be spendable
spendable_anytime.extend([p2pkh, p2pk])
- # P2SH_P2PK, P2SH_P2PKH, and witness with compressed keys are spendable after direct importaddress
- spendable_after_importaddress.extend([p2wpkh, p2sh_p2wpkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh])
+ # P2SH_P2PK, P2SH_P2PKH with compressed keys are spendable after direct importaddress
+ spendable_after_importaddress.extend([p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh])
+ # P2WPKH and P2SH_P2WPKH with compressed keys should always be spendable
+ spendable_anytime.extend([p2wpkh, p2sh_p2wpkh])
for i in uncompressed_spendable_address:
v = self.nodes[0].validateaddress(i)
@@ -373,7 +338,7 @@ class SegWitTest(BitcoinTestFramework):
spendable_anytime.extend([p2pkh, p2pk])
# P2SH_P2PK and P2SH_P2PKH are spendable after direct importaddress
spendable_after_importaddress.extend([p2sh_p2pk, p2sh_p2pkh])
- # witness with uncompressed keys are never seen
+ # Witness output types with uncompressed keys are never seen
unseen_anytime.extend([p2wpkh, p2sh_p2wpkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh])
for i in compressed_solvable_address:
@@ -384,10 +349,10 @@ class SegWitTest(BitcoinTestFramework):
solvable_after_importaddress.extend([bare, p2sh, p2wsh, p2sh_p2wsh])
else:
[p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v)
- # normal P2PKH and P2PK with compressed keys should always be seen
- solvable_anytime.extend([p2pkh, p2pk])
- # P2SH_P2PK, P2SH_P2PKH, and witness with compressed keys are seen after direct importaddress
- solvable_after_importaddress.extend([p2wpkh, p2sh_p2wpkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh])
+ # normal P2PKH, P2PK, P2WPKH and P2SH_P2WPKH with compressed keys should always be seen
+ solvable_anytime.extend([p2pkh, p2pk, p2wpkh, p2sh_p2wpkh])
+ # P2SH_P2PK, P2SH_P2PKH with compressed keys are seen after direct importaddress
+ solvable_after_importaddress.extend([p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh])
for i in uncompressed_solvable_address:
v = self.nodes[0].validateaddress(i)
@@ -403,7 +368,7 @@ class SegWitTest(BitcoinTestFramework):
solvable_anytime.extend([p2pkh, p2pk])
# P2SH_P2PK, P2SH_P2PKH with uncompressed keys are seen after direct importaddress
solvable_after_importaddress.extend([p2sh_p2pk, p2sh_p2pkh])
- # witness with uncompressed keys are never seen
+ # Witness output types with uncompressed keys are never seen
unseen_anytime.extend([p2wpkh, p2sh_p2wpkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh])
op1 = CScript([OP_1])
@@ -496,12 +461,14 @@ class SegWitTest(BitcoinTestFramework):
spendable_after_addwitnessaddress = [] # These outputs should be seen after importaddress
solvable_after_addwitnessaddress=[] # These outputs should be seen after importaddress but not spendable
unseen_anytime = [] # These outputs should never be seen
+ solvable_anytime = [] # These outputs should be solvable after importpubkey
+ unseen_anytime = [] # These outputs should never be seen
- uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], compressed_spendable_address[0]]))
- uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], uncompressed_spendable_address[0]]))
- compressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_spendable_address[0]]))
- uncompressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_solvable_address[0], uncompressed_solvable_address[0]]))
- compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_solvable_address[0]]))
+ uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], compressed_spendable_address[0]])['address'])
+ uncompressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [uncompressed_spendable_address[0], uncompressed_spendable_address[0]])['address'])
+ compressed_spendable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_spendable_address[0]])['address'])
+ uncompressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_solvable_address[0], uncompressed_solvable_address[0]])['address'])
+ compressed_solvable_address.append(self.nodes[0].addmultisigaddress(2, [compressed_spendable_address[0], compressed_solvable_address[0]])['address'])
premature_witaddress = []
@@ -514,9 +481,8 @@ class SegWitTest(BitcoinTestFramework):
premature_witaddress.append(script_to_p2sh(p2wsh))
else:
[p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v)
- # P2WPKH, P2SH_P2WPKH are spendable after addwitnessaddress
- spendable_after_addwitnessaddress.extend([p2wpkh, p2sh_p2wpkh])
- premature_witaddress.append(script_to_p2sh(p2wpkh))
+ # P2WPKH, P2SH_P2WPKH are always spendable
+ spendable_anytime.extend([p2wpkh, p2sh_p2wpkh])
for i in uncompressed_spendable_address + uncompressed_solvable_address:
v = self.nodes[0].validateaddress(i)
@@ -538,10 +504,11 @@ class SegWitTest(BitcoinTestFramework):
premature_witaddress.append(script_to_p2sh(p2wsh))
else:
[p2wpkh, p2sh_p2wpkh, p2pk, p2pkh, p2sh_p2pk, p2sh_p2pkh, p2wsh_p2pk, p2wsh_p2pkh, p2sh_p2wsh_p2pk, p2sh_p2wsh_p2pkh] = self.p2pkh_address_to_script(v)
- # P2SH_P2PK, P2SH_P2PKH with compressed keys are seen after addwitnessaddress
- solvable_after_addwitnessaddress.extend([p2wpkh, p2sh_p2wpkh])
- premature_witaddress.append(script_to_p2sh(p2wpkh))
+ # P2SH_P2PK, P2SH_P2PKH with compressed keys are always solvable
+ solvable_anytime.extend([p2wpkh, p2sh_p2wpkh])
+ self.mine_and_test_listunspent(spendable_anytime, 2)
+ self.mine_and_test_listunspent(solvable_anytime, 1)
self.mine_and_test_listunspent(spendable_after_addwitnessaddress + solvable_after_addwitnessaddress + unseen_anytime, 0)
# addwitnessaddress should refuse to return a witness address if an uncompressed key is used
@@ -558,8 +525,8 @@ class SegWitTest(BitcoinTestFramework):
witaddress = self.nodes[0].addwitnessaddress(i)
assert_equal(witaddress, self.nodes[0].addwitnessaddress(witaddress))
- spendable_txid.append(self.mine_and_test_listunspent(spendable_after_addwitnessaddress, 2))
- solvable_txid.append(self.mine_and_test_listunspent(solvable_after_addwitnessaddress, 1))
+ spendable_txid.append(self.mine_and_test_listunspent(spendable_after_addwitnessaddress + spendable_anytime, 2))
+ solvable_txid.append(self.mine_and_test_listunspent(solvable_after_addwitnessaddress + solvable_anytime, 1))
self.mine_and_test_listunspent(unseen_anytime, 0)
# Check that createrawtransaction/decoderawtransaction with non-v0 Bech32 works
@@ -605,7 +572,7 @@ class SegWitTest(BitcoinTestFramework):
assert_equal(self.nodes[1].listtransactions("*", 1, 0, True)[0]["txid"], txid)
def mine_and_test_listunspent(self, script_list, ismine):
- utxo = find_unspent(self.nodes[0], 50)
+ utxo = find_spendable_utxo(self.nodes[0], 50)
tx = CTransaction()
tx.vin.append(CTxIn(COutPoint(int('0x'+utxo['txid'],0), utxo['vout'])))
for i in script_list:
diff --git a/test/functional/uacomment.py b/test/functional/feature_uacomment.py
index 0b2c64ab69..bc3791508a 100755
--- a/test/functional/uacomment.py
+++ b/test/functional/feature_uacomment.py
@@ -23,7 +23,7 @@ class UacommentTest(BitcoinTestFramework):
self.log.info("test -uacomment max length")
self.stop_node(0)
- expected = "Total length of network version string (286) exceeds maximum length (256). Reduce the number or size of uacomments."
+ expected = "exceeds maximum length (256). Reduce the number or size of uacomments."
self.assert_start_raises_init_error(0, ["-uacomment=" + 'a' * 256], expected)
self.log.info("test -uacomment unsafe characters")
diff --git a/test/functional/feature_versionbits_warning.py b/test/functional/feature_versionbits_warning.py
new file mode 100755
index 0000000000..2985569a8f
--- /dev/null
+++ b/test/functional/feature_versionbits_warning.py
@@ -0,0 +1,112 @@
+#!/usr/bin/env python3
+# Copyright (c) 2016-2017 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 version bits warning system.
+
+Generate chains with block versions that appear to be signalling unknown
+soft-forks, and test that warning alerts are generated.
+"""
+import os
+import re
+
+from test_framework.blocktools import create_block, create_coinbase
+from test_framework.messages import msg_block
+from test_framework.mininode import P2PInterface, network_thread_start, mininode_lock
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import wait_until
+
+VB_PERIOD = 144 # versionbits period length for regtest
+VB_THRESHOLD = 108 # versionbits activation threshold for regtest
+VB_TOP_BITS = 0x20000000
+VB_UNKNOWN_BIT = 27 # Choose a bit unassigned to any deployment
+VB_UNKNOWN_VERSION = VB_TOP_BITS | (1 << VB_UNKNOWN_BIT)
+
+WARN_UNKNOWN_RULES_MINED = "Unknown block versions being mined! It's possible unknown rules are in effect"
+WARN_UNKNOWN_RULES_ACTIVE = "unknown new rules activated (versionbit {})".format(VB_UNKNOWN_BIT)
+VB_PATTERN = re.compile("Warning: unknown new rules activated.*versionbit")
+
+class VersionBitsWarningTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.setup_clean_chain = True
+ self.num_nodes = 1
+
+ def setup_network(self):
+ self.alert_filename = os.path.join(self.options.tmpdir, "alert.txt")
+ # Open and close to create zero-length file
+ with open(self.alert_filename, 'w', encoding='utf8'):
+ pass
+ self.extra_args = [["-alertnotify=echo %s >> \"" + self.alert_filename + "\""]]
+ self.setup_nodes()
+
+ def send_blocks_with_version(self, peer, numblocks, version):
+ """Send numblocks blocks to peer with version set"""
+ tip = self.nodes[0].getbestblockhash()
+ height = self.nodes[0].getblockcount()
+ block_time = self.nodes[0].getblockheader(tip)["time"] + 1
+ tip = int(tip, 16)
+
+ for _ in range(numblocks):
+ block = create_block(tip, create_coinbase(height + 1), block_time)
+ block.nVersion = version
+ block.solve()
+ peer.send_message(msg_block(block))
+ block_time += 1
+ height += 1
+ tip = block.sha256
+ peer.sync_with_ping()
+
+ def versionbits_in_alert_file(self):
+ """Test that the versionbits warning has been written to the alert file."""
+ alert_text = open(self.alert_filename, 'r', encoding='utf8').read()
+ return VB_PATTERN.search(alert_text) is not None
+
+ def run_test(self):
+ # Handy alias
+ node = self.nodes[0]
+ node.add_p2p_connection(P2PInterface())
+ network_thread_start()
+ node.p2p.wait_for_verack()
+
+ # Mine one period worth of blocks
+ node.generate(VB_PERIOD)
+
+ self.log.info("Check that there is no warning if previous VB_BLOCKS have <VB_THRESHOLD blocks with unknown versionbits version.")
+ # Build one period of blocks with < VB_THRESHOLD blocks signaling some unknown bit
+ self.send_blocks_with_version(node.p2p, VB_THRESHOLD - 1, VB_UNKNOWN_VERSION)
+ node.generate(VB_PERIOD - VB_THRESHOLD + 1)
+
+ # Check that we're not getting any versionbit-related errors in get*info()
+ assert(not VB_PATTERN.match(node.getmininginfo()["warnings"]))
+ assert(not VB_PATTERN.match(node.getnetworkinfo()["warnings"]))
+
+ self.log.info("Check that there is a warning if >50 blocks in the last 100 were an unknown version")
+ # Build one period of blocks with VB_THRESHOLD blocks signaling some unknown bit
+ self.send_blocks_with_version(node.p2p, VB_THRESHOLD, VB_UNKNOWN_VERSION)
+ node.generate(VB_PERIOD - VB_THRESHOLD)
+
+ # Check that get*info() shows the 51/100 unknown block version error.
+ assert(WARN_UNKNOWN_RULES_MINED in node.getmininginfo()["warnings"])
+ assert(WARN_UNKNOWN_RULES_MINED in node.getnetworkinfo()["warnings"])
+
+ self.log.info("Check that there is a warning if previous VB_BLOCKS have >=VB_THRESHOLD blocks with unknown versionbits version.")
+ # Mine a period worth of expected blocks so the generic block-version warning
+ # is cleared. This will move the versionbit state to ACTIVE.
+ node.generate(VB_PERIOD)
+
+ # Stop-start the node. This is required because bitcoind will only warn once about unknown versions or unknown rules activating.
+ self.restart_node(0)
+
+ # Generating one block guarantees that we'll get out of IBD
+ node.generate(1)
+ wait_until(lambda: not node.getblockchaininfo()['initialblockdownload'], timeout=10, lock=mininode_lock)
+ # Generating one more block will be enough to generate an error.
+ node.generate(1)
+ # Check that get*info() shows the versionbits unknown rules warning
+ assert(WARN_UNKNOWN_RULES_ACTIVE in node.getmininginfo()["warnings"])
+ assert(WARN_UNKNOWN_RULES_ACTIVE in node.getnetworkinfo()["warnings"])
+ # Check that the alert file shows the versionbits unknown rules warning
+ wait_until(lambda: self.versionbits_in_alert_file(), timeout=60)
+
+if __name__ == '__main__':
+ VersionBitsWarningTest().main()
diff --git a/test/functional/bitcoin_cli.py b/test/functional/interface_bitcoin_cli.py
index d1cd3b3620..d8c80ab34f 100755
--- a/test/functional/bitcoin_cli.py
+++ b/test/functional/interface_bitcoin_cli.py
@@ -39,7 +39,7 @@ class TestBitcoinCli(BitcoinTestFramework):
assert_raises_process_error(1, "-getinfo takes no arguments", self.nodes[0].cli('-getinfo').help)
self.log.info("Compare responses from `bitcoin-cli -getinfo` and the RPCs data is retrieved from.")
- cli_get_info = self.nodes[0].cli().send_cli('-getinfo')
+ cli_get_info = self.nodes[0].cli('-getinfo').send_cli()
wallet_info = self.nodes[0].getwalletinfo()
network_info = self.nodes[0].getnetworkinfo()
blockchain_info = self.nodes[0].getblockchaininfo()
diff --git a/test/functional/httpbasics.py b/test/functional/interface_http.py
index c7682cb49d..cd6d744545 100755
--- a/test/functional/httpbasics.py
+++ b/test/functional/interface_http.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 the RPC HTTP basics."""
diff --git a/test/functional/rest.py b/test/functional/interface_rest.py
index 437111a4d7..9006e27cbe 100755
--- a/test/functional/rest.py
+++ b/test/functional/interface_rest.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 the REST API."""
diff --git a/test/functional/zmq_test.py b/test/functional/interface_zmq.py
index fa30318416..86ccea4394 100755
--- a/test/functional/zmq_test.py
+++ b/test/functional/interface_zmq.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2016 The Bitcoin Core developers
+# Copyright (c) 2015-2017 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 the ZMQ notification interface."""
diff --git a/test/functional/invalidtxrequest.py b/test/functional/invalidtxrequest.py
deleted file mode 100755
index a22bd8f8cd..0000000000
--- a/test/functional/invalidtxrequest.py
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) 2015-2016 The Bitcoin Core developers
-# Distributed under the MIT software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-"""Test node responses to invalid transactions.
-
-In this test we connect to one node over p2p, and test tx requests.
-"""
-
-from test_framework.test_framework import ComparisonTestFramework
-from test_framework.comptool import TestManager, TestInstance, RejectResult
-from test_framework.blocktools import *
-import time
-
-
-
-# Use the ComparisonTestFramework with 1 node: only use --testbinary.
-class InvalidTxRequestTest(ComparisonTestFramework):
-
- ''' Can either run this test as 1 node with expected answers, or two and compare them.
- Change the "outcome" variable from each TestInstance object to only do the comparison. '''
- def set_test_params(self):
- self.num_nodes = 1
- self.setup_clean_chain = True
-
- def run_test(self):
- test = TestManager(self, self.options.tmpdir)
- test.add_all_connections(self.nodes)
- self.tip = None
- self.block_time = None
- NetworkThread().start() # Start up network handling in another thread
- test.run()
-
- def get_tests(self):
- if self.tip is None:
- self.tip = int("0x" + self.nodes[0].getbestblockhash(), 0)
- self.block_time = int(time.time())+1
-
- '''
- Create a new block with an anyone-can-spend coinbase
- '''
- height = 1
- block = create_block(self.tip, create_coinbase(height), self.block_time)
- self.block_time += 1
- block.solve()
- # Save the coinbase for later
- self.block1 = block
- self.tip = block.sha256
- height += 1
- yield TestInstance([[block, True]])
-
- '''
- Now we need that block to mature so we can spend the coinbase.
- '''
- test = TestInstance(sync_every_block=False)
- for i in range(100):
- block = create_block(self.tip, create_coinbase(height), self.block_time)
- block.solve()
- self.tip = block.sha256
- self.block_time += 1
- test.blocks_and_transactions.append([block, True])
- height += 1
- yield test
-
- # b'\x64' is OP_NOTIF
- # Transaction will be rejected with code 16 (REJECT_INVALID)
- tx1 = create_transaction(self.block1.vtx[0], 0, b'\x64', 50 * COIN - 12000)
- yield TestInstance([[tx1, RejectResult(16, b'mandatory-script-verify-flag-failed')]])
-
- # TODO: test further transactions...
-
-if __name__ == '__main__':
- InvalidTxRequestTest().main()
diff --git a/test/functional/mempool_limit.py b/test/functional/mempool_limit.py
index e24dc5a464..e7ce3820d2 100755
--- a/test/functional/mempool_limit.py
+++ b/test/functional/mempool_limit.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test mempool limiting together/eviction with the wallet."""
@@ -17,10 +17,14 @@ class MempoolLimitTest(BitcoinTestFramework):
txouts = gen_return_txouts()
relayfee = self.nodes[0].getnetworkinfo()['relayfee']
+ self.log.info('Check that mempoolminfee is minrelytxfee')
+ assert_equal(self.nodes[0].getmempoolinfo()['minrelaytxfee'], Decimal('0.00001000'))
+ assert_equal(self.nodes[0].getmempoolinfo()['mempoolminfee'], Decimal('0.00001000'))
+
txids = []
utxos = create_confirmed_utxos(relayfee, self.nodes[0], 91)
- #create a mempool tx that will be evicted
+ self.log.info('Create a mempool tx that will be evicted')
us0 = utxos.pop()
inputs = [{ "txid" : us0["txid"], "vout" : us0["vout"]}]
outputs = {self.nodes[0].getnewaddress() : 0.0001}
@@ -37,10 +41,14 @@ class MempoolLimitTest(BitcoinTestFramework):
txids.append([])
txids[i] = create_lots_of_big_transactions(self.nodes[0], txouts, utxos[30*i:30*i+30], 30, (i+1)*base_fee)
- # by now, the tx should be evicted, check confirmation state
+ self.log.info('The tx should be evicted by now')
assert(txid not in self.nodes[0].getrawmempool())
txdata = self.nodes[0].gettransaction(txid)
assert(txdata['confirmations'] == 0) #confirmation should still be 0
+ self.log.info('Check that mempoolminfee is larger than minrelytxfee')
+ assert_equal(self.nodes[0].getmempoolinfo()['minrelaytxfee'], Decimal('0.00001000'))
+ assert_greater_than(self.nodes[0].getmempoolinfo()['mempoolminfee'], Decimal('0.00001000'))
+
if __name__ == '__main__':
MempoolLimitTest().main()
diff --git a/test/functional/mempool_packages.py b/test/functional/mempool_packages.py
index b845c75681..a3e872a8c6 100755
--- a/test/functional/mempool_packages.py
+++ b/test/functional/mempool_packages.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 descendant package tracking code."""
diff --git a/test/functional/mempool_persist.py b/test/functional/mempool_persist.py
index 31a96ec60e..17f0967219 100755
--- a/test/functional/mempool_persist.py
+++ b/test/functional/mempool_persist.py
@@ -66,16 +66,17 @@ class MempoolPersistTest(BitcoinTestFramework):
self.log.debug("Stop-start the nodes. Verify that node0 has the transactions in its mempool and node1 does not. Verify that node2 calculates its balance correctly after loading wallet transactions.")
self.stop_nodes()
+ self.start_node(1) # Give this one a head-start, so we can be "extra-sure" that it didn't load anything later
self.start_node(0)
- self.start_node(1)
self.start_node(2)
# Give bitcoind a second to reload the mempool
- time.sleep(1)
- wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5)
- wait_until(lambda: len(self.nodes[2].getrawmempool()) == 5)
+ wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5, timeout=1)
+ wait_until(lambda: len(self.nodes[2].getrawmempool()) == 5, timeout=1)
+ # The others have loaded their mempool. If node_1 loaded anything, we'd probably notice by now:
assert_equal(len(self.nodes[1].getrawmempool()), 0)
# Verify accounting of mempool transactions after restart is correct
+ self.nodes[2].syncwithvalidationinterfacequeue() # Flush mempool to wallet
assert_equal(node2_balance, self.nodes[2].getbalance())
self.log.debug("Stop-start node0 with -persistmempool=0. Verify that it doesn't load its mempool.dat file.")
diff --git a/test/functional/mempool_reorg.py b/test/functional/mempool_reorg.py
index 2803371f5b..d6bb292a58 100755
--- a/test/functional/mempool_reorg.py
+++ b/test/functional/mempool_reorg.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test mempool re-org scenarios.
diff --git a/test/functional/mempool_resurrect_test.py b/test/functional/mempool_resurrect.py
index 1263c9306b..83e84da4bc 100755
--- a/test/functional/mempool_resurrect_test.py
+++ b/test/functional/mempool_resurrect.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 resurrection of mined transactions when the blockchain is re-organized."""
diff --git a/test/functional/mempool_spendcoinbase.py b/test/functional/mempool_spend_coinbase.py
index 6e8a635a76..db0738c08a 100755
--- a/test/functional/mempool_spendcoinbase.py
+++ b/test/functional/mempool_spend_coinbase.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 spending coinbase transactions.
diff --git a/test/functional/mining.py b/test/functional/mining_basic.py
index 9aee06864e..569bf71933 100755
--- a/test/functional/mining.py
+++ b/test/functional/mining_basic.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 mining RPCs
diff --git a/test/functional/getblocktemplate_longpoll.py b/test/functional/mining_getblocktemplate_longpoll.py
index 89768bd2fb..252ff4dbff 100755
--- a/test/functional/getblocktemplate_longpoll.py
+++ b/test/functional/mining_getblocktemplate_longpoll.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 longpolling with getblocktemplate."""
diff --git a/test/functional/prioritise_transaction.py b/test/functional/mining_prioritisetransaction.py
index bb56db9b40..57954ce321 100755
--- a/test/functional/prioritise_transaction.py
+++ b/test/functional/mining_prioritisetransaction.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2016 The Bitcoin Core developers
+# Copyright (c) 2015-2017 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 the prioritisetransaction mining RPC."""
@@ -15,6 +15,25 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
self.extra_args = [["-printpriority=1"], ["-printpriority=1"]]
def run_test(self):
+ # Test `prioritisetransaction` required parameters
+ assert_raises_rpc_error(-1, "prioritisetransaction", self.nodes[0].prioritisetransaction)
+ assert_raises_rpc_error(-1, "prioritisetransaction", self.nodes[0].prioritisetransaction, '')
+ assert_raises_rpc_error(-1, "prioritisetransaction", self.nodes[0].prioritisetransaction, '', 0)
+
+ # Test `prioritisetransaction` invalid extra parameters
+ assert_raises_rpc_error(-1, "prioritisetransaction", self.nodes[0].prioritisetransaction, '', 0, 0, 0)
+
+ # Test `prioritisetransaction` invalid `txid`
+ assert_raises_rpc_error(-1, "txid must be hexadecimal string", self.nodes[0].prioritisetransaction, txid='foo', fee_delta=0)
+
+ # Test `prioritisetransaction` invalid `dummy`
+ txid = '1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000'
+ assert_raises_rpc_error(-1, "JSON value is not a number as expected", self.nodes[0].prioritisetransaction, txid, 'foo', 0)
+ assert_raises_rpc_error(-8, "Priority is no longer supported, dummy argument to prioritisetransaction must be 0.", self.nodes[0].prioritisetransaction, txid, 1, 0)
+
+ # Test `prioritisetransaction` invalid `fee_delta`
+ assert_raises_rpc_error(-1, "JSON value is not an integer as expected", self.nodes[0].prioritisetransaction, txid=txid, fee_delta='foo')
+
self.txouts = gen_return_txouts()
self.relayfee = self.nodes[0].getnetworkinfo()['relayfee']
diff --git a/test/functional/node_network_limited.py b/test/functional/node_network_limited.py
deleted file mode 100755
index 6d1bf7ced2..0000000000
--- a/test/functional/node_network_limited.py
+++ /dev/null
@@ -1,81 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) 2017 The Bitcoin Core developers
-# Distributed under the MIT software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import *
-from test_framework.mininode import *
-
-class BaseNode(P2PInterface):
- nServices = 0
- firstAddrnServices = 0
- def on_version(self, message):
- self.nServices = message.nServices
-
-class NodeNetworkLimitedTest(BitcoinTestFramework):
- def set_test_params(self):
- self.setup_clean_chain = True
- self.num_nodes = 1
- self.extra_args = [['-prune=550']]
-
- def getSignaledServiceFlags(self):
- node = self.nodes[0].add_p2p_connection(BaseNode())
- NetworkThread().start()
- node.wait_for_verack()
- services = node.nServices
- self.nodes[0].disconnect_p2ps()
- node.wait_for_disconnect()
- return services
-
- def tryGetBlockViaGetData(self, blockhash, must_disconnect):
- node = self.nodes[0].add_p2p_connection(BaseNode())
- NetworkThread().start()
- node.wait_for_verack()
- node.send_message(msg_verack())
- getdata_request = msg_getdata()
- getdata_request.inv.append(CInv(2, int(blockhash, 16)))
- node.send_message(getdata_request)
-
- if (must_disconnect):
- #ensure we get disconnected
- node.wait_for_disconnect(5)
- else:
- # check if the peer sends us the requested block
- node.wait_for_block(int(blockhash, 16), 3)
- self.nodes[0].disconnect_p2ps()
- node.wait_for_disconnect()
-
- def run_test(self):
- #NODE_BLOOM & NODE_WITNESS & NODE_NETWORK_LIMITED must now be signaled
- assert_equal(self.getSignaledServiceFlags(), 1036) #1036 == 0x40C == 0100 0000 1100
-# | ||
-# | |^--- NODE_BLOOM
-# | ^---- NODE_WITNESS
-# ^-- NODE_NETWORK_LIMITED
-
- #now mine some blocks over the NODE_NETWORK_LIMITED + 2(racy buffer ext.) target
- firstblock = self.nodes[0].generate(1)[0]
- blocks = self.nodes[0].generate(292)
- blockWithinLimitedRange = blocks[-1]
-
- #make sure we can max retrive block at tip-288
- #requesting block at height 2 (tip-289) must fail (ignored)
- self.tryGetBlockViaGetData(firstblock, True) #first block must lead to disconnect
- self.tryGetBlockViaGetData(blocks[1], False) #last block in valid range
- self.tryGetBlockViaGetData(blocks[0], True) #first block outside of the 288+2 limit
-
- #NODE_NETWORK_LIMITED must still be signaled after restart
- self.restart_node(0)
- assert_equal(self.getSignaledServiceFlags(), 1036)
-
- #test the RPC service flags
- assert_equal(self.nodes[0].getnetworkinfo()['localservices'], "000000000000040c")
-
- # getdata a block above the NODE_NETWORK_LIMITED threshold must be possible
- self.tryGetBlockViaGetData(blockWithinLimitedRange, False)
-
- # getdata a block below the NODE_NETWORK_LIMITED threshold must be ignored
- self.tryGetBlockViaGetData(firstblock, True)
-
-if __name__ == '__main__':
- NodeNetworkLimitedTest().main()
diff --git a/test/functional/p2p-versionbits-warning.py b/test/functional/p2p-versionbits-warning.py
deleted file mode 100755
index be137381d0..0000000000
--- a/test/functional/p2p-versionbits-warning.py
+++ /dev/null
@@ -1,121 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) 2016 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 version bits warning system.
-
-Generate chains with block versions that appear to be signalling unknown
-soft-forks, and test that warning alerts are generated.
-"""
-
-from test_framework.mininode import *
-from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import *
-import re
-from test_framework.blocktools import create_block, create_coinbase
-
-VB_PERIOD = 144 # versionbits period length for regtest
-VB_THRESHOLD = 108 # versionbits activation threshold for regtest
-VB_TOP_BITS = 0x20000000
-VB_UNKNOWN_BIT = 27 # Choose a bit unassigned to any deployment
-
-WARN_UNKNOWN_RULES_MINED = "Unknown block versions being mined! It's possible unknown rules are in effect"
-WARN_UNKNOWN_RULES_ACTIVE = "unknown new rules activated (versionbit {})".format(VB_UNKNOWN_BIT)
-VB_PATTERN = re.compile("^Warning.*versionbit")
-
-class TestNode(P2PInterface):
- def on_inv(self, message):
- pass
-
-class VersionBitsWarningTest(BitcoinTestFramework):
- def set_test_params(self):
- self.setup_clean_chain = True
- self.num_nodes = 1
-
- def setup_network(self):
- self.alert_filename = os.path.join(self.options.tmpdir, "alert.txt")
- # Open and close to create zero-length file
- with open(self.alert_filename, 'w', encoding='utf8') as _:
- pass
- self.extra_args = [["-alertnotify=echo %s >> \"" + self.alert_filename + "\""]]
- self.setup_nodes()
-
- # Send numblocks blocks via peer with nVersionToUse set.
- def send_blocks_with_version(self, peer, numblocks, nVersionToUse):
- tip = self.nodes[0].getbestblockhash()
- height = self.nodes[0].getblockcount()
- block_time = self.nodes[0].getblockheader(tip)["time"]+1
- tip = int(tip, 16)
-
- for _ in range(numblocks):
- block = create_block(tip, create_coinbase(height+1), block_time)
- block.nVersion = nVersionToUse
- block.solve()
- peer.send_message(msg_block(block))
- block_time += 1
- height += 1
- tip = block.sha256
- peer.sync_with_ping()
-
- def test_versionbits_in_alert_file(self):
- with open(self.alert_filename, 'r', encoding='utf8') as f:
- alert_text = f.read()
- assert(VB_PATTERN.match(alert_text))
-
- def run_test(self):
- # Setup the p2p connection and start up the network thread.
- self.nodes[0].add_p2p_connection(TestNode())
-
- NetworkThread().start() # Start up network handling in another thread
-
- # Test logic begins here
- self.nodes[0].p2p.wait_for_verack()
-
- # 1. Have the node mine one period worth of blocks
- self.nodes[0].generate(VB_PERIOD)
-
- # 2. Now build one period of blocks on the tip, with < VB_THRESHOLD
- # blocks signaling some unknown bit.
- nVersion = VB_TOP_BITS | (1<<VB_UNKNOWN_BIT)
- self.send_blocks_with_version(self.nodes[0].p2p, VB_THRESHOLD-1, nVersion)
-
- # Fill rest of period with regular version blocks
- self.nodes[0].generate(VB_PERIOD - VB_THRESHOLD + 1)
- # Check that we're not getting any versionbit-related errors in
- # get*info()
- assert(not VB_PATTERN.match(self.nodes[0].getmininginfo()["warnings"]))
- assert(not VB_PATTERN.match(self.nodes[0].getnetworkinfo()["warnings"]))
-
- # 3. Now build one period of blocks with >= VB_THRESHOLD blocks signaling
- # some unknown bit
- self.send_blocks_with_version(self.nodes[0].p2p, VB_THRESHOLD, nVersion)
- self.nodes[0].generate(VB_PERIOD - VB_THRESHOLD)
- # Might not get a versionbits-related alert yet, as we should
- # have gotten a different alert due to more than 51/100 blocks
- # being of unexpected version.
- # Check that get*info() shows some kind of error.
- assert(WARN_UNKNOWN_RULES_MINED in self.nodes[0].getmininginfo()["warnings"])
- assert(WARN_UNKNOWN_RULES_MINED in self.nodes[0].getnetworkinfo()["warnings"])
-
- # Mine a period worth of expected blocks so the generic block-version warning
- # is cleared, and restart the node. This should move the versionbit state
- # to ACTIVE.
- self.nodes[0].generate(VB_PERIOD)
- self.stop_nodes()
- # Empty out the alert file
- with open(self.alert_filename, 'w', encoding='utf8') as _:
- pass
- self.start_nodes()
-
- # Connecting one block should be enough to generate an error.
- self.nodes[0].generate(1)
- assert(WARN_UNKNOWN_RULES_ACTIVE in self.nodes[0].getmininginfo()["warnings"])
- assert(WARN_UNKNOWN_RULES_ACTIVE in self.nodes[0].getnetworkinfo()["warnings"])
- self.stop_nodes()
- self.test_versionbits_in_alert_file()
-
- # Test framework expects the node to still be running...
- self.start_nodes()
-
-if __name__ == '__main__':
- VersionBitsWarningTest().main()
diff --git a/test/functional/p2p-compactblocks.py b/test/functional/p2p_compactblocks.py
index c43744328c..d9f461a049 100755
--- a/test/functional/p2p-compactblocks.py
+++ b/test/functional/p2p_compactblocks.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2016 The Bitcoin Core developers
+# Copyright (c) 2016-2017 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 compact blocks (BIP 152).
@@ -95,7 +95,7 @@ class CompactBlocksTest(BitcoinTestFramework):
self.num_nodes = 2
# This test was written assuming SegWit is activated using BIP9 at height 432 (3x confirmation window).
# TODO: Rewrite this test to support SegWit being always active.
- self.extra_args = [["-vbparams=segwit:0:0"], ["-vbparams=segwit:0:999999999999", "-txindex"]]
+ self.extra_args = [["-vbparams=segwit:0:0"], ["-vbparams=segwit:0:999999999999", "-txindex", "-deprecatedrpc=addwitnessaddress"]]
self.utxos = []
def build_block_on_tip(self, node, segwit=False):
@@ -792,7 +792,7 @@ class CompactBlocksTest(BitcoinTestFramework):
self.segwit_node = self.nodes[1].add_p2p_connection(TestNode(), services=NODE_NETWORK|NODE_WITNESS)
self.old_node = self.nodes[1].add_p2p_connection(TestNode(), services=NODE_NETWORK)
- NetworkThread().start() # Start up network handling in another thread
+ network_thread_start()
self.test_node.wait_for_verack()
diff --git a/test/functional/disconnect_ban.py b/test/functional/p2p_disconnect_ban.py
index 59655d37fb..c6067befb2 100755
--- a/test/functional/disconnect_ban.py
+++ b/test/functional/p2p_disconnect_ban.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test node disconnect and ban behavior"""
diff --git a/test/functional/p2p-feefilter.py b/test/functional/p2p_feefilter.py
index ac55336e3d..47d9c55160 100755
--- a/test/functional/p2p-feefilter.py
+++ b/test/functional/p2p_feefilter.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2016 The Bitcoin Core developers
+# Copyright (c) 2016-2017 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 processing of feefilter messages."""
@@ -49,7 +49,7 @@ class FeeFilterTest(BitcoinTestFramework):
# Setup the p2p connections and start up the network thread.
self.nodes[0].add_p2p_connection(TestNode())
- NetworkThread().start()
+ network_thread_start()
self.nodes[0].p2p.wait_for_verack()
# Test that invs are received for all txs at feerate of 20 sat/byte
diff --git a/test/functional/p2p-fingerprint.py b/test/functional/p2p_fingerprint.py
index 209c789f22..516ce8555b 100755
--- a/test/functional/p2p-fingerprint.py
+++ b/test/functional/p2p_fingerprint.py
@@ -4,7 +4,7 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test various fingerprinting protections.
-If an stale block more than a month old or its header are requested by a peer,
+If a stale block more than a month old or its header are requested by a peer,
the node should pretend that it does not have it to avoid fingerprinting.
"""
@@ -13,12 +13,12 @@ import time
from test_framework.blocktools import (create_block, create_coinbase)
from test_framework.mininode import (
CInv,
- NetworkThread,
P2PInterface,
msg_headers,
msg_block,
msg_getdata,
msg_getheaders,
+ network_thread_start,
wait_until,
)
from test_framework.test_framework import BitcoinTestFramework
@@ -77,7 +77,7 @@ class P2PFingerprintTest(BitcoinTestFramework):
def run_test(self):
node0 = self.nodes[0].add_p2p_connection(P2PInterface())
- NetworkThread().start()
+ network_thread_start()
node0.wait_for_verack()
# Set node time to 60 days ago
diff --git a/test/functional/invalidblockrequest.py b/test/functional/p2p_invalid_block.py
index 9f44b44927..edcade63c1 100755
--- a/test/functional/invalidblockrequest.py
+++ b/test/functional/p2p_invalid_block.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2016 The Bitcoin Core developers
+# Copyright (c) 2015-2017 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test node responses to invalid blocks.
@@ -15,6 +15,7 @@ from test_framework.test_framework import ComparisonTestFramework
from test_framework.util import *
from test_framework.comptool import TestManager, TestInstance, RejectResult
from test_framework.blocktools import *
+from test_framework.mininode import network_thread_start
import copy
import time
@@ -32,7 +33,7 @@ class InvalidBlockRequestTest(ComparisonTestFramework):
test.add_all_connections(self.nodes)
self.tip = None
self.block_time = None
- NetworkThread().start() # Start up network handling in another thread
+ network_thread_start()
test.run()
def get_tests(self):
diff --git a/test/functional/p2p_invalid_tx.py b/test/functional/p2p_invalid_tx.py
new file mode 100755
index 0000000000..64fada38e2
--- /dev/null
+++ b/test/functional/p2p_invalid_tx.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python3
+# Copyright (c) 2015-2017 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test node responses to invalid transactions.
+
+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.test_framework import 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 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()
+
+ best_block = self.nodes[0].getbestblockhash()
+ tip = int(best_block, 16)
+ best_block_time = self.nodes[0].getblock(best_block)['time']
+ block_time = best_block_time + 1
+
+ self.log.info("Create a new block with an anyone-can-spend coinbase.")
+ height = 1
+ block = create_block(tip, create_coinbase(height), block_time)
+ block_time += 1
+ block.solve()
+ # Save the coinbase for later
+ block1 = block
+ tip = block.sha256
+ height += 1
+ node.p2p.send_blocks_and_test([block], node, success=True)
+
+ self.log.info("Mature the block.")
+ self.nodes[0].generate(100)
+
+ # 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)')
+
+ # TODO: test further transactions...
+
+if __name__ == '__main__':
+ InvalidTxRequestTest().main()
diff --git a/test/functional/p2p-leaktests.py b/test/functional/p2p_leak.py
index b469a9a47a..ce4e6e9144 100755
--- a/test/functional/p2p-leaktests.py
+++ b/test/functional/p2p_leak.py
@@ -103,7 +103,7 @@ class P2PLeakTest(BitcoinTestFramework):
unsupported_service_bit5_node = self.nodes[0].add_p2p_connection(CLazyNode(), services=NODE_NETWORK|NODE_UNSUPPORTED_SERVICE_BIT_5)
unsupported_service_bit7_node = self.nodes[0].add_p2p_connection(CLazyNode(), services=NODE_NETWORK|NODE_UNSUPPORTED_SERVICE_BIT_7)
- NetworkThread().start() # Start up network handling in another thread
+ network_thread_start()
wait_until(lambda: no_version_bannode.ever_connected, timeout=10, lock=mininode_lock)
wait_until(lambda: no_version_idlenode.ever_connected, timeout=10, lock=mininode_lock)
@@ -126,8 +126,9 @@ class P2PLeakTest(BitcoinTestFramework):
self.nodes[0].disconnect_p2ps()
- # Wait until all connections are closed
+ # Wait until all connections are closed and the network thread has terminated
wait_until(lambda: len(self.nodes[0].getpeerinfo()) == 0)
+ network_thread_join()
# Make sure no unexpected messages came in
assert(no_version_bannode.unexpected_msg == False)
@@ -142,7 +143,8 @@ class P2PLeakTest(BitcoinTestFramework):
allowed_service_bit5_node = self.nodes[0].add_p2p_connection(P2PInterface(), services=NODE_NETWORK|NODE_UNSUPPORTED_SERVICE_BIT_5)
allowed_service_bit7_node = self.nodes[0].add_p2p_connection(P2PInterface(), services=NODE_NETWORK|NODE_UNSUPPORTED_SERVICE_BIT_7)
- NetworkThread().start() # Network thread stopped when all previous P2PInterfaces disconnected. Restart it
+ # Network thread stopped when all previous P2PInterfaces disconnected. Restart it
+ network_thread_start()
wait_until(lambda: allowed_service_bit5_node.message_count["verack"], lock=mininode_lock)
wait_until(lambda: allowed_service_bit7_node.message_count["verack"], lock=mininode_lock)
diff --git a/test/functional/p2p-mempool.py b/test/functional/p2p_mempool.py
index d24dbac51d..485a8af3d0 100755
--- a/test/functional/p2p-mempool.py
+++ b/test/functional/p2p_mempool.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2016 The Bitcoin Core developers
+# Copyright (c) 2015-2017 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 p2p mempool message.
@@ -21,7 +21,7 @@ class P2PMempoolTests(BitcoinTestFramework):
def run_test(self):
# Add a p2p connection
self.nodes[0].add_p2p_connection(P2PInterface())
- NetworkThread().start()
+ network_thread_start()
self.nodes[0].p2p.wait_for_verack()
#request mempool
diff --git a/test/functional/p2p_node_network_limited.py b/test/functional/p2p_node_network_limited.py
new file mode 100755
index 0000000000..70415e0168
--- /dev/null
+++ b/test/functional/p2p_node_network_limited.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python3
+# Copyright (c) 2017 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 NODE_NETWORK_LIMITED.
+
+Tests that a node configured with -prune=550 signals NODE_NETWORK_LIMITED correctly
+and that it responds to getdata requests for blocks correctly:
+ - send a block within 288 + 2 of the tip
+ - disconnect peers who request blocks older than that."""
+from test_framework.messages import CInv, msg_getdata
+from test_framework.mininode import NODE_BLOOM, NODE_NETWORK_LIMITED, NODE_WITNESS, NetworkThread, P2PInterface
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import assert_equal
+
+class P2PIgnoreInv(P2PInterface):
+ def on_inv(self, message):
+ # The node will send us invs for other blocks. Ignore them.
+ pass
+
+ def send_getdata_for_block(self, blockhash):
+ getdata_request = msg_getdata()
+ getdata_request.inv.append(CInv(2, int(blockhash, 16)))
+ self.send_message(getdata_request)
+
+class NodeNetworkLimitedTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.setup_clean_chain = True
+ self.num_nodes = 1
+ self.extra_args = [['-prune=550']]
+
+ def run_test(self):
+ node = self.nodes[0].add_p2p_connection(P2PIgnoreInv())
+ NetworkThread().start()
+ node.wait_for_verack()
+
+ expected_services = NODE_BLOOM | NODE_WITNESS | NODE_NETWORK_LIMITED
+
+ self.log.info("Check that node has signalled expected services.")
+ assert_equal(node.nServices, expected_services)
+
+ self.log.info("Check that the localservices is as expected.")
+ assert_equal(int(self.nodes[0].getnetworkinfo()['localservices'], 16), expected_services)
+
+ self.log.info("Mine enough blocks to reach the NODE_NETWORK_LIMITED range.")
+ blocks = self.nodes[0].generate(292)
+
+ self.log.info("Make sure we can max retrive block at tip-288.")
+ node.send_getdata_for_block(blocks[1]) # last block in valid range
+ node.wait_for_block(int(blocks[1], 16), timeout=3)
+
+ self.log.info("Requesting block at height 2 (tip-289) must fail (ignored).")
+ node.send_getdata_for_block(blocks[0]) # first block outside of the 288+2 limit
+ node.wait_for_disconnect(5)
+
+if __name__ == '__main__':
+ NodeNetworkLimitedTest().main()
diff --git a/test/functional/p2p-segwit.py b/test/functional/p2p_segwit.py
index a240d79013..20e4805df0 100755
--- a/test/functional/p2p-segwit.py
+++ b/test/functional/p2p_segwit.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2016 The Bitcoin Core developers
+# Copyright (c) 2016-2017 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 segwit transactions and blocks on P2P network."""
@@ -25,7 +25,7 @@ MAX_SIGOP_COST = 80000
# Calculate the virtual size of a witness block:
# (base + witness/4)
def get_virtual_size(witness_block):
- base_size = len(witness_block.serialize())
+ base_size = len(witness_block.serialize(with_witness=False))
total_size = len(witness_block.serialize(with_witness=True))
# the "+3" is so we round up
vsize = int((3*base_size + total_size + 3)/4)
@@ -1396,18 +1396,20 @@ class SegWitTest(BitcoinTestFramework):
temp_utxos.pop(0)
- # Update self.utxos for later tests. Just spend everything in
- # temp_utxos to a corresponding entry in self.utxos
+ # Update self.utxos for later tests by creating two outputs
+ # that consolidate all the coins in temp_utxos.
+ output_value = sum(i.nValue for i in temp_utxos) // 2
+
tx = CTransaction()
index = 0
+ # Just spend to our usual anyone-can-spend output
+ tx.vout = [CTxOut(output_value, CScript([OP_TRUE]))] * 2
for i in temp_utxos:
- # Just spend to our usual anyone-can-spend output
- # Use SIGHASH_SINGLE|SIGHASH_ANYONECANPAY so we can build up
+ # Use SIGHASH_ALL|SIGHASH_ANYONECANPAY so we can build up
# the signatures as we go.
tx.vin.append(CTxIn(COutPoint(i.sha256, i.n), b""))
- tx.vout.append(CTxOut(i.nValue, CScript([OP_TRUE])))
tx.wit.vtxinwit.append(CTxInWitness())
- sign_P2PK_witness_input(witness_program, tx, index, SIGHASH_SINGLE|SIGHASH_ANYONECANPAY, i.nValue, key)
+ sign_P2PK_witness_input(witness_program, tx, index, SIGHASH_ALL|SIGHASH_ANYONECANPAY, i.nValue, key)
index += 1
block = self.build_next_block()
self.update_witness_block_with_transactions(block, [tx])
@@ -1882,7 +1884,7 @@ class SegWitTest(BitcoinTestFramework):
# self.std_node is for testing node1 (fRequireStandard=true)
self.std_node = self.nodes[1].add_p2p_connection(TestNode(), services=NODE_NETWORK|NODE_WITNESS)
- NetworkThread().start() # Start up network handling in another thread
+ network_thread_start()
# Keep a place to store utxo's that can be used in later tests
self.utxo = []
diff --git a/test/functional/sendheaders.py b/test/functional/p2p_sendheaders.py
index 99b7f6b99e..8869aeaaea 100755
--- a/test/functional/sendheaders.py
+++ b/test/functional/p2p_sendheaders.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 behavior of headers messages to announce blocks.
@@ -90,7 +90,7 @@ from test_framework.mininode import (
CBlockHeader,
CInv,
NODE_WITNESS,
- NetworkThread,
+ network_thread_start,
P2PInterface,
mininode_lock,
msg_block,
@@ -238,7 +238,7 @@ class SendHeadersTest(BitcoinTestFramework):
# will occur outside of direct fetching
test_node = self.nodes[0].add_p2p_connection(BaseNode(), services=NODE_WITNESS)
- NetworkThread().start() # Start up network handling in another thread
+ network_thread_start()
# Test logic begins here
inv_node.wait_for_verack()
diff --git a/test/functional/p2p-timeouts.py b/test/functional/p2p_timeouts.py
index b2f3a861cf..6d21095cc6 100755
--- a/test/functional/p2p-timeouts.py
+++ b/test/functional/p2p_timeouts.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2016 The Bitcoin Core developers
+# Copyright (c) 2016-2017 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 various net timeouts.
@@ -43,7 +43,7 @@ class TimeoutsTest(BitcoinTestFramework):
no_version_node = self.nodes[0].add_p2p_connection(TestNode(), send_version=False)
no_send_node = self.nodes[0].add_p2p_connection(TestNode(), send_version=False)
- NetworkThread().start() # Start up network handling in another thread
+ network_thread_start()
sleep(1)
diff --git a/test/functional/p2p-acceptblock.py b/test/functional/p2p_unrequested_blocks.py
index d9d7c24416..672626f15b 100755
--- a/test/functional/p2p-acceptblock.py
+++ b/test/functional/p2p_unrequested_blocks.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2016 The Bitcoin Core developers
+# Copyright (c) 2015-2017 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 processing of unrequested blocks.
@@ -83,7 +83,7 @@ class AcceptBlockTest(BitcoinTestFramework):
# min_work_node connects to node1 (whitelisted)
min_work_node = self.nodes[1].add_p2p_connection(P2PInterface())
- NetworkThread().start() # Start up network handling in another thread
+ network_thread_start()
# Test logic begins here
test_node.wait_for_verack()
@@ -207,9 +207,13 @@ class AcceptBlockTest(BitcoinTestFramework):
# disconnect/reconnect first
self.nodes[0].disconnect_p2ps()
- test_node = self.nodes[0].add_p2p_connection(P2PInterface())
+ self.nodes[1].disconnect_p2ps()
+ network_thread_join()
+ test_node = self.nodes[0].add_p2p_connection(P2PInterface())
+ network_thread_start()
test_node.wait_for_verack()
+
test_node.send_message(msg_block(block_h1f))
test_node.sync_with_ping()
@@ -294,7 +298,7 @@ class AcceptBlockTest(BitcoinTestFramework):
self.nodes[0].disconnect_p2ps()
test_node = self.nodes[0].add_p2p_connection(P2PInterface())
- NetworkThread().start() # Start up network handling in another thread
+ network_thread_start()
test_node.wait_for_verack()
# We should have failed reorg and switched back to 290 (but have block 291)
diff --git a/test/functional/rpcbind_test.py b/test/functional/rpc_bind.py
index 0e8c3fa209..05433c7e24 100755
--- a/test/functional/rpcbind_test.py
+++ b/test/functional/rpc_bind.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 running bitcoind with the -rpcbind and -rpcallowip options."""
diff --git a/test/functional/blockchain.py b/test/functional/rpc_blockchain.py
index 49fafbc9aa..7cf2abe6f0 100755
--- a/test/functional/blockchain.py
+++ b/test/functional/rpc_blockchain.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 RPCs related to blockchainstate.
@@ -100,6 +100,8 @@ class BlockchainTest(BitcoinTestFramework):
assert_greater_than(res['size_on_disk'], 0)
def _test_getchaintxstats(self):
+ self.log.info("Test getchaintxstats")
+
chaintxstats = self.nodes[0].getchaintxstats(1)
# 200 txs plus genesis tx
assert_equal(chaintxstats['txcount'], 201)
@@ -107,21 +109,25 @@ class BlockchainTest(BitcoinTestFramework):
# we have to round because of binary math
assert_equal(round(chaintxstats['txrate'] * 600, 10), Decimal(1))
- b1 = self.nodes[0].getblock(self.nodes[0].getblockhash(1))
- b200 = self.nodes[0].getblock(self.nodes[0].getblockhash(200))
+ b1_hash = self.nodes[0].getblockhash(1)
+ b1 = self.nodes[0].getblock(b1_hash)
+ b200_hash = self.nodes[0].getblockhash(200)
+ b200 = self.nodes[0].getblock(b200_hash)
time_diff = b200['mediantime'] - b1['mediantime']
chaintxstats = self.nodes[0].getchaintxstats()
assert_equal(chaintxstats['time'], b200['time'])
assert_equal(chaintxstats['txcount'], 201)
+ assert_equal(chaintxstats['window_final_block_hash'], b200_hash)
assert_equal(chaintxstats['window_block_count'], 199)
assert_equal(chaintxstats['window_tx_count'], 199)
assert_equal(chaintxstats['window_interval'], time_diff)
assert_equal(round(chaintxstats['txrate'] * time_diff, 10), Decimal(199))
- chaintxstats = self.nodes[0].getchaintxstats(blockhash=b1['hash'])
+ chaintxstats = self.nodes[0].getchaintxstats(blockhash=b1_hash)
assert_equal(chaintxstats['time'], b1['time'])
assert_equal(chaintxstats['txcount'], 2)
+ assert_equal(chaintxstats['window_final_block_hash'], b1_hash)
assert_equal(chaintxstats['window_block_count'], 0)
assert('window_tx_count' not in chaintxstats)
assert('window_interval' not in chaintxstats)
@@ -173,8 +179,7 @@ class BlockchainTest(BitcoinTestFramework):
def _test_getblockheader(self):
node = self.nodes[0]
- assert_raises_rpc_error(-5, "Block not found",
- node.getblockheader, "nonsense")
+ assert_raises_rpc_error(-5, "Block not found", node.getblockheader, "nonsense")
besthash = node.getbestblockhash()
secondbesthash = node.getblockhash(199)
diff --git a/test/functional/decodescript.py b/test/functional/rpc_decodescript.py
index 6611da8831..1ffc570437 100755
--- a/test/functional/decodescript.py
+++ b/test/functional/rpc_decodescript.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2016 The Bitcoin Core developers
+# Copyright (c) 2015-2017 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 decoding scripts via decodescript RPC command."""
diff --git a/test/functional/rpc_deprecated.py b/test/functional/rpc_deprecated.py
new file mode 100755
index 0000000000..90183474bb
--- /dev/null
+++ b/test/functional/rpc_deprecated.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python3
+# Copyright (c) 2017 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 deprecation of RPC calls."""
+from test_framework.test_framework import BitcoinTestFramework
+
+class DeprecatedRpcTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.num_nodes = 2
+ self.setup_clean_chain = True
+ self.extra_args = [[], []]
+
+ def run_test(self):
+ # This test should be used to verify correct behaviour of deprecated
+ # RPC methods with and without the -deprecatedrpc flags. For example:
+ #
+ # self.log.info("Make sure that -deprecatedrpc=createmultisig allows it to take addresses")
+ # assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 1, [self.nodes[0].getnewaddress()])
+ # self.nodes[1].createmultisig(1, [self.nodes[1].getnewaddress()])
+ #
+ # There are currently no deprecated RPC methods in master, so this
+ # test is currently empty.
+ pass
+
+if __name__ == '__main__':
+ DeprecatedRpcTest().main()
diff --git a/test/functional/fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py
index d446f56d0e..4d3be18516 100755
--- a/test/functional/fundrawtransaction.py
+++ b/test/functional/rpc_fundrawtransaction.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 the fundrawtransaction RPC."""
@@ -181,6 +181,9 @@ class RawTransactionsTest(BitcoinTestFramework):
assert_raises_rpc_error(-3, "Unexpected key foo", self.nodes[2].fundrawtransaction, rawtx, {'foo':'bar'})
+ # reserveChangeKey was deprecated and is now removed
+ assert_raises_rpc_error(-3, "Unexpected key reserveChangeKey", lambda: self.nodes[2].fundrawtransaction(hexstring=rawtx, options={'reserveChangeKey': True}))
+
############################################################
# test a fundrawtransaction with an invalid change address #
############################################################
@@ -212,6 +215,19 @@ class RawTransactionsTest(BitcoinTestFramework):
out = dec_tx['vout'][0]
assert_equal(change, out['scriptPubKey']['addresses'][0])
+ #########################################################
+ # test a fundrawtransaction with a provided change type #
+ #########################################################
+ utx = get_unspent(self.nodes[2].listunspent(), 5)
+
+ inputs = [ {'txid' : utx['txid'], 'vout' : utx['vout']} ]
+ 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': ''})
+ 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'])
#########################################################################
# test a fundrawtransaction with a VIN smaller than the required amount #
@@ -358,7 +374,7 @@ class RawTransactionsTest(BitcoinTestFramework):
addr1Obj = self.nodes[1].validateaddress(addr1)
addr2Obj = self.nodes[1].validateaddress(addr2)
- mSigObj = self.nodes[1].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])
+ mSigObj = self.nodes[1].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
inputs = []
outputs = {mSigObj:1.1}
@@ -391,7 +407,7 @@ class RawTransactionsTest(BitcoinTestFramework):
addr4Obj = self.nodes[1].validateaddress(addr4)
addr5Obj = self.nodes[1].validateaddress(addr5)
- mSigObj = self.nodes[1].addmultisigaddress(4, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey'], addr4Obj['pubkey'], addr5Obj['pubkey']])
+ mSigObj = self.nodes[1].addmultisigaddress(4, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey'], addr4Obj['pubkey'], addr5Obj['pubkey']])['address']
inputs = []
outputs = {mSigObj:1.1}
@@ -418,7 +434,7 @@ class RawTransactionsTest(BitcoinTestFramework):
addr1Obj = self.nodes[2].validateaddress(addr1)
addr2Obj = self.nodes[2].validateaddress(addr2)
- mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])
+ mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
# send 1.2 BTC to msig addr
@@ -663,7 +679,7 @@ class RawTransactionsTest(BitcoinTestFramework):
self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2*min_relay_tx_fee}),
self.nodes[3].fundrawtransaction(rawtx, {"feeRate": 2*min_relay_tx_fee, "subtractFeeFromOutputs": [0]})]
- dec_tx = [self.nodes[3].decoderawtransaction(tx['hex']) for tx in result]
+ dec_tx = [self.nodes[3].decoderawtransaction(tx_['hex']) for tx_ in result]
output = [d['vout'][1 - r['changepos']]['value'] for d, r in zip(dec_tx, result)]
change = [d['vout'][r['changepos']]['value'] for d, r in zip(dec_tx, result)]
diff --git a/test/functional/getchaintips.py b/test/functional/rpc_getchaintips.py
index 21b67bfc64..277930bb1a 100755
--- a/test/functional/getchaintips.py
+++ b/test/functional/rpc_getchaintips.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 the getchaintips RPC.
diff --git a/test/functional/invalidateblock.py b/test/functional/rpc_invalidateblock.py
index dd3daf1e07..b037c2431d 100755
--- a/test/functional/invalidateblock.py
+++ b/test/functional/rpc_invalidateblock.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 the invalidateblock RPC."""
diff --git a/test/functional/listtransactions.py b/test/functional/rpc_listtransactions.py
index e4522cc3b5..ba71ac0967 100755
--- a/test/functional/listtransactions.py
+++ b/test/functional/rpc_listtransactions.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 the listtransactions API."""
@@ -81,7 +81,8 @@ class ListTransactionsTest(BitcoinTestFramework):
{"category":"receive","amount":Decimal("0.44")},
{"txid":txid, "account" : "toself"} )
- multisig = self.nodes[1].createmultisig(1, [self.nodes[1].getnewaddress()])
+ pubkey = self.nodes[1].validateaddress(self.nodes[1].getnewaddress())['pubkey']
+ multisig = self.nodes[1].createmultisig(1, [pubkey])
self.nodes[0].importaddress(multisig["redeemScript"], "watchonly", False, True)
txid = self.nodes[1].sendtoaddress(multisig["address"], 0.1)
self.nodes[1].generate(1)
diff --git a/test/functional/rpcnamedargs.py b/test/functional/rpc_named_arguments.py
index c47212bddb..97bee39614 100755
--- a/test/functional/rpcnamedargs.py
+++ b/test/functional/rpc_named_arguments.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2016 The Bitcoin Core developers
+# Copyright (c) 2016-2017 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 using named arguments for RPCs."""
diff --git a/test/functional/net.py b/test/functional/rpc_net.py
index 16e4f6adb4..16e4f6adb4 100755
--- a/test/functional/net.py
+++ b/test/functional/rpc_net.py
diff --git a/test/functional/preciousblock.py b/test/functional/rpc_preciousblock.py
index 1466f901c0..960cd0ad12 100755
--- a/test/functional/preciousblock.py
+++ b/test/functional/rpc_preciousblock.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2016 The Bitcoin Core developers
+# Copyright (c) 2015-2017 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 the preciousblock RPC."""
diff --git a/test/functional/rawtransactions.py b/test/functional/rpc_rawtransaction.py
index 79f2a2834e..92126ef4b7 100755
--- a/test/functional/rawtransactions.py
+++ b/test/functional/rpc_rawtransaction.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 the rawtransaction RPCs.
@@ -15,11 +15,31 @@ Test the following RPCs:
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
+
+class multidict(dict):
+ """Dictionary that allows duplicate keys.
+
+ Constructed with a list of (key, value) tuples. When dumped by the json module,
+ will output invalid json with repeated keys, eg:
+ >>> json.dumps(multidict([(1,2),(1,2)])
+ '{"1": 2, "1": 2}'
+
+ Used to test calls to rpc methods with repeated keys in the json object."""
+
+ def __init__(self, x):
+ dict.__init__(self, x)
+ self.x = x
+
+ def items(self):
+ return self.x
+
+
# Create one-input, one-output, no-fee transaction:
class RawTransactionsTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 3
+ self.extra_args = [["-addresstype=legacy"], ["-addresstype=legacy"], ["-addresstype=legacy"]]
def setup_network(self, split=False):
super().setup_network()
@@ -39,6 +59,45 @@ class RawTransactionsTest(BitcoinTestFramework):
self.nodes[0].generate(5)
self.sync_all()
+ # Test getrawtransaction on genesis block coinbase returns an error
+ block = self.nodes[0].getblock(self.nodes[0].getblockhash(0))
+ assert_raises_rpc_error(-5, "The genesis block coinbase is not considered an ordinary transaction", self.nodes[0].getrawtransaction, block['merkleroot'])
+
+ # Test `createrawtransaction` required parameters
+ assert_raises_rpc_error(-1, "createrawtransaction", self.nodes[0].createrawtransaction)
+ assert_raises_rpc_error(-1, "createrawtransaction", self.nodes[0].createrawtransaction, [])
+
+ # Test `createrawtransaction` invalid extra parameters
+ assert_raises_rpc_error(-1, "createrawtransaction", self.nodes[0].createrawtransaction, [], {}, 0, False, 'foo')
+
+ # Test `createrawtransaction` invalid `inputs`
+ txid = '1d1d4e24ed99057e84c3f80fd8fbec79ed9e1acee37da269356ecea000000000'
+ assert_raises_rpc_error(-3, "Expected type array", self.nodes[0].createrawtransaction, 'foo', {})
+ assert_raises_rpc_error(-1, "JSON value is not an object as expected", self.nodes[0].createrawtransaction, ['foo'], {})
+ assert_raises_rpc_error(-8, "txid must be hexadecimal string", self.nodes[0].createrawtransaction, [{}], {})
+ assert_raises_rpc_error(-8, "txid must be hexadecimal string", self.nodes[0].createrawtransaction, [{'txid': 'foo'}], {})
+ assert_raises_rpc_error(-8, "Invalid parameter, missing vout key", self.nodes[0].createrawtransaction, [{'txid': txid}], {})
+ assert_raises_rpc_error(-8, "Invalid parameter, missing vout key", self.nodes[0].createrawtransaction, [{'txid': txid, 'vout': 'foo'}], {})
+ assert_raises_rpc_error(-8, "Invalid parameter, vout must be positive", self.nodes[0].createrawtransaction, [{'txid': txid, 'vout': -1}], {})
+ assert_raises_rpc_error(-8, "Invalid parameter, sequence number is out of range", self.nodes[0].createrawtransaction, [{'txid': txid, 'vout': 0, 'sequence': -1}], {})
+
+ # Test `createrawtransaction` invalid `outputs`
+ address = self.nodes[0].getnewaddress()
+ assert_raises_rpc_error(-3, "Expected type object", self.nodes[0].createrawtransaction, [], 'foo')
+ assert_raises_rpc_error(-8, "Data must be hexadecimal string", self.nodes[0].createrawtransaction, [], {'data': 'foo'})
+ assert_raises_rpc_error(-5, "Invalid Bitcoin address", self.nodes[0].createrawtransaction, [], {'foo': 0})
+ assert_raises_rpc_error(-3, "Invalid amount", self.nodes[0].createrawtransaction, [], {address: 'foo'})
+ assert_raises_rpc_error(-3, "Amount out of range", self.nodes[0].createrawtransaction, [], {address: -1})
+ assert_raises_rpc_error(-8, "Invalid parameter, duplicated address: %s" % address, self.nodes[0].createrawtransaction, [], multidict([(address, 1), (address, 1)]))
+
+ # Test `createrawtransaction` invalid `locktime`
+ assert_raises_rpc_error(-3, "Expected type number", self.nodes[0].createrawtransaction, [], {}, 'foo')
+ assert_raises_rpc_error(-8, "Invalid parameter, locktime out of range", self.nodes[0].createrawtransaction, [], {}, -1)
+ assert_raises_rpc_error(-8, "Invalid parameter, locktime out of range", self.nodes[0].createrawtransaction, [], {}, 4294967296)
+
+ # Test `createrawtransaction` invalid `replaceable`
+ assert_raises_rpc_error(-3, "Expected type bool", self.nodes[0].createrawtransaction, [], {}, 0, 'foo')
+
#########################################
# sendrawtransaction with missing input #
#########################################
@@ -90,7 +149,12 @@ class RawTransactionsTest(BitcoinTestFramework):
addr1Obj = self.nodes[2].validateaddress(addr1)
addr2Obj = self.nodes[2].validateaddress(addr2)
- mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])
+ # Tests for createmultisig and addmultisigaddress
+ assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 1, ["01020304"])
+ self.nodes[0].createmultisig(2, [addr1Obj['pubkey'], addr2Obj['pubkey']]) # createmultisig can only take public keys
+ assert_raises_rpc_error(-5, "Invalid public key", self.nodes[0].createmultisig, 2, [addr1Obj['pubkey'], addr1]) # addmultisigaddress can take both pubkeys and addresses so long as they are in the wallet, which is tested here.
+
+ mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr1])['address']
#use balance deltas instead of absolute values
bal = self.nodes[2].getbalance()
@@ -113,7 +177,7 @@ class RawTransactionsTest(BitcoinTestFramework):
addr2Obj = self.nodes[2].validateaddress(addr2)
addr3Obj = self.nodes[2].validateaddress(addr3)
- mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey']])
+ mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey'], addr3Obj['pubkey']])['address']
txId = self.nodes[0].sendtoaddress(mSigObj, 2.2)
decTx = self.nodes[0].gettransaction(txId)
@@ -122,7 +186,7 @@ class RawTransactionsTest(BitcoinTestFramework):
self.nodes[0].generate(1)
self.sync_all()
- #THIS IS A INCOMPLETE FEATURE
+ #THIS IS AN INCOMPLETE FEATURE
#NODE2 HAS TWO OF THREE KEY AND THE FUNDS SHOULD BE SPENDABLE AND COUNT AT BALANCE CALCULATION
assert_equal(self.nodes[2].getbalance(), bal) #for now, assume the funds of a 2of3 multisig tx are not marked as spendable
@@ -135,7 +199,7 @@ class RawTransactionsTest(BitcoinTestFramework):
break
bal = self.nodes[0].getbalance()
- inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex']}]
+ inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "amount" : vout['value']}]
outputs = { self.nodes[0].getnewaddress() : 2.19 }
rawTx = self.nodes[2].createrawtransaction(inputs, outputs)
rawTxPartialSigned = self.nodes[1].signrawtransaction(rawTx, inputs)
@@ -158,8 +222,8 @@ class RawTransactionsTest(BitcoinTestFramework):
addr1Obj = self.nodes[1].validateaddress(addr1)
addr2Obj = self.nodes[2].validateaddress(addr2)
- self.nodes[1].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])
- mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])
+ self.nodes[1].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
+ mSigObj = self.nodes[2].addmultisigaddress(2, [addr1Obj['pubkey'], addr2Obj['pubkey']])['address']
mSigObjValid = self.nodes[2].validateaddress(mSigObj)
txId = self.nodes[0].sendtoaddress(mSigObj, 2.2)
@@ -180,7 +244,7 @@ class RawTransactionsTest(BitcoinTestFramework):
break
bal = self.nodes[0].getbalance()
- inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "redeemScript" : mSigObjValid['hex']}]
+ inputs = [{ "txid" : txId, "vout" : vout['n'], "scriptPubKey" : vout['scriptPubKey']['hex'], "redeemScript" : mSigObjValid['hex'], "amount" : vout['value']}]
outputs = { self.nodes[0].getnewaddress() : 2.19 }
rawTx2 = self.nodes[2].createrawtransaction(inputs, outputs)
rawTxPartialSigned1 = self.nodes[1].signrawtransaction(rawTx2, inputs)
@@ -199,6 +263,17 @@ class RawTransactionsTest(BitcoinTestFramework):
self.sync_all()
assert_equal(self.nodes[0].getbalance(), bal+Decimal('50.00000000')+Decimal('2.19000000')) #block reward + tx
+ # decoderawtransaction tests
+ # witness transaction
+ encrawtx = "010000000001010000000000000072c1a6a246ae63f74f931e8365e15a089c68d61900000000000000000000ffffffff0100e1f50500000000000000000000"
+ decrawtx = self.nodes[0].decoderawtransaction(encrawtx, True) # decode as witness transaction
+ assert_equal(decrawtx['vout'][0]['value'], Decimal('1.00000000'))
+ assert_raises_rpc_error(-22, 'TX decode failed', self.nodes[0].decoderawtransaction, encrawtx, False) # force decode as non-witness transaction
+ # non-witness transaction
+ encrawtx = "01000000010000000000000072c1a6a246ae63f74f931e8365e15a089c68d61900000000000000000000ffffffff0100e1f505000000000000000000"
+ decrawtx = self.nodes[0].decoderawtransaction(encrawtx, False) # decode as non-witness transaction
+ assert_equal(decrawtx['vout'][0]['value'], Decimal('1.00000000'))
+
# getrawtransaction tests
# 1. valid parameters - only supply txid
txHash = rawTx["hash"]
diff --git a/test/functional/signmessages.py b/test/functional/rpc_signmessage.py
index 52ba6a5ad7..5b6935ceea 100755
--- a/test/functional/signmessages.py
+++ b/test/functional/rpc_signmessage.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2016 The Bitcoin Core developers
+# Copyright (c) 2016-2017 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test RPC commands for signing and verifying messages."""
@@ -11,6 +11,7 @@ class SignMessagesTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 1
+ self.extra_args = [["-addresstype=legacy"]]
def run_test(self):
message = 'This is just a test message'
diff --git a/test/functional/signrawtransactions.py b/test/functional/rpc_signrawtransaction.py
index 9a45d53cb8..dd0fa6c02c 100755
--- a/test/functional/signrawtransactions.py
+++ b/test/functional/rpc_signrawtransaction.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2016 The Bitcoin Core developers
+# Copyright (c) 2015-2017 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 transaction signing using the signrawtransaction RPC."""
diff --git a/test/functional/merkle_blocks.py b/test/functional/rpc_txoutproof.py
index b3989a4c54..50e0371fdf 100755
--- a/test/functional/merkle_blocks.py
+++ b/test/functional/rpc_txoutproof.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 gettxoutproof and verifytxoutproof RPCs."""
diff --git a/test/functional/uptime.py b/test/functional/rpc_uptime.py
index 78236b2393..78236b2393 100755
--- a/test/functional/uptime.py
+++ b/test/functional/rpc_uptime.py
diff --git a/test/functional/multi_rpc.py b/test/functional/rpc_users.py
index a2b346f274..01f68344ae 100755
--- a/test/functional/multi_rpc.py
+++ b/test/functional/rpc_users.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2016 The Bitcoin Core developers
+# Copyright (c) 2015-2017 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 multiple RPC users."""
diff --git a/test/functional/test_framework/address.py b/test/functional/test_framework/address.py
index 2e2db5ffb2..b076c9dd43 100644
--- a/test/functional/test_framework/address.py
+++ b/test/functional/test_framework/address.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2016 The Bitcoin Core developers
+# Copyright (c) 2016-2017 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Encode and decode BASE58, P2PKH and P2SH addresses."""
diff --git a/test/functional/test_framework/blockstore.py b/test/functional/test_framework/blockstore.py
index 051c57a6c7..6067a407cc 100644
--- a/test/functional/test_framework/blockstore.py
+++ b/test/functional/test_framework/blockstore.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2016 The Bitcoin Core developers
+# Copyright (c) 2015-2017 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""BlockStore and TxStore helper classes."""
diff --git a/test/functional/test_framework/blocktools.py b/test/functional/test_framework/blocktools.py
index 5dcf516dc6..642ef98a27 100644
--- a/test/functional/test_framework/blocktools.py
+++ b/test/functional/test_framework/blocktools.py
@@ -1,11 +1,27 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2016 The Bitcoin Core developers
+# Copyright (c) 2015-2017 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Utilities for manipulating blocks and transactions."""
+from .address import (
+ key_to_p2sh_p2wpkh,
+ key_to_p2wpkh,
+ script_to_p2sh_p2wsh,
+ script_to_p2wsh,
+)
from .mininode import *
-from .script import CScript, OP_TRUE, OP_CHECKSIG, OP_RETURN
+from .script import (
+ CScript,
+ OP_0,
+ OP_1,
+ OP_CHECKMULTISIG,
+ OP_CHECKSIG,
+ OP_RETURN,
+ OP_TRUE,
+ hash160,
+)
+from .util import assert_equal
# Create a block (with regtest difficulty)
def create_block(hashprev, coinbase, nTime=None):
@@ -108,3 +124,49 @@ def get_legacy_sigopcount_tx(tx, fAccurate=True):
# scriptSig might be of type bytes, so convert to CScript for the moment
count += CScript(j.scriptSig).GetSigOpCount(fAccurate)
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):
+ # P2WPKH instead
+ pubkeyhash = hash160(hex_str_to_bytes(pubkey))
+ pkscript = CScript([OP_0, pubkeyhash])
+ else:
+ # 1-of-1 multisig
+ witness_program = CScript([OP_1, hex_str_to_bytes(pubkey), OP_1, OP_CHECKMULTISIG])
+ scripthash = sha256(witness_program)
+ 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):
+ 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)
+ else:
+ addr = key_to_p2sh_p2wpkh(pubkey) if encode_p2sh else key_to_p2wpkh(pubkey)
+ if not encode_p2sh:
+ assert_equal(node.validateaddress(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=""):
+ tx_to_witness = create_witness_tx(node, use_p2wsh, utxo, pubkey, encode_p2sh, amount)
+ if (sign):
+ signed = node.signrawtransaction(tx_to_witness)
+ assert("errors" not in signed or len(["errors"]) == 0)
+ return node.sendrawtransaction(signed["hex"])
+ else:
+ if (insert_redeem_script):
+ tx = FromHex(CTransaction(), tx_to_witness)
+ tx.vin[0].scriptSig += CScript([hex_str_to_bytes(insert_redeem_script)])
+ tx_to_witness = ToHex(tx)
+
+ return node.sendrawtransaction(tx_to_witness)
diff --git a/test/functional/test_framework/comptool.py b/test/functional/test_framework/comptool.py
index f0f5c847ca..61ea2280e2 100755
--- a/test/functional/test_framework/comptool.py
+++ b/test/functional/test_framework/comptool.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2016 The Bitcoin Core developers
+# Copyright (c) 2015-2017 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Compare two or more bitcoinds to each other.
diff --git a/test/functional/test_framework/coverage.py b/test/functional/test_framework/coverage.py
index ddc3c515b2..f8761f2bb3 100644
--- a/test/functional/test_framework/coverage.py
+++ b/test/functional/test_framework/coverage.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2016 The Bitcoin Core developers
+# Copyright (c) 2015-2017 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Utilities for doing coverage analysis on the RPC interface.
diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py
index 2ab1bdac0f..46ef7521e0 100644
--- a/test/functional/test_framework/messages.py
+++ b/test/functional/test_framework/messages.py
@@ -38,10 +38,16 @@ COIN = 100000000 # 1 btc in satoshis
NODE_NETWORK = (1 << 0)
# NODE_GETUTXO = (1 << 1)
-# NODE_BLOOM = (1 << 2)
+NODE_BLOOM = (1 << 2)
NODE_WITNESS = (1 << 3)
NODE_UNSUPPORTED_SERVICE_BIT_5 = (1 << 5)
NODE_UNSUPPORTED_SERVICE_BIT_7 = (1 << 7)
+NODE_NETWORK_LIMITED = (1 << 10)
+
+MSG_TX = 1
+MSG_BLOCK = 2
+MSG_WITNESS_FLAG = 1 << 30
+MSG_TYPE_MASK = 0xffffffff >> 2
# Serialization/deserialization tools
def sha256(s):
@@ -203,8 +209,6 @@ class CAddress():
return "CAddress(nServices=%i ip=%s port=%i)" % (self.nServices,
self.ip, self.port)
-MSG_WITNESS_FLAG = 1<<30
-
class CInv():
typemap = {
0: "Error",
@@ -452,10 +456,10 @@ class CTransaction():
r += struct.pack("<I", self.nLockTime)
return r
- # Regular serialization is without witness -- must explicitly
- # call serialize_with_witness to include witness data.
+ # Regular serialization is with witness -- must explicitly
+ # call serialize_without_witness to exclude witness data.
def serialize(self):
- return self.serialize_without_witness()
+ return self.serialize_with_witness()
# Recalculate the txid (transaction hash without witness)
def rehash(self):
@@ -471,7 +475,7 @@ class CTransaction():
if self.sha256 is None:
self.sha256 = uint256_from_str(hash256(self.serialize_without_witness()))
- self.hash = encode(hash256(self.serialize())[::-1], 'hex_codec').decode('ascii')
+ self.hash = encode(hash256(self.serialize_without_witness())[::-1], 'hex_codec').decode('ascii')
def is_valid(self):
self.calc_sha256()
@@ -568,7 +572,7 @@ class CBlock(CBlockHeader):
if with_witness:
r += ser_vector(self.vtx, "serialize_with_witness")
else:
- r += ser_vector(self.vtx)
+ r += ser_vector(self.vtx, "serialize_without_witness")
return r
# Calculate the merkle root given a vector of transaction hashes
@@ -635,7 +639,7 @@ class PrefilledTransaction():
self.tx = CTransaction()
self.tx.deserialize(f)
- def serialize(self, with_witness=False):
+ def serialize(self, with_witness=True):
r = b""
r += ser_compact_size(self.index)
if with_witness:
@@ -644,6 +648,9 @@ class PrefilledTransaction():
r += self.tx.serialize_without_witness()
return r
+ def serialize_without_witness(self):
+ return self.serialize(with_witness=False)
+
def serialize_with_witness(self):
return self.serialize(with_witness=True)
@@ -683,7 +690,7 @@ class P2PHeaderAndShortIDs():
if with_witness:
r += ser_vector(self.prefilled_txn, "serialize_with_witness")
else:
- r += ser_vector(self.prefilled_txn)
+ r += ser_vector(self.prefilled_txn, "serialize_without_witness")
return r
def __repr__(self):
@@ -814,13 +821,13 @@ class BlockTransactions():
self.blockhash = deser_uint256(f)
self.transactions = deser_vector(f, CTransaction)
- def serialize(self, with_witness=False):
+ def serialize(self, with_witness=True):
r = b""
r += ser_uint256(self.blockhash)
if with_witness:
r += ser_vector(self.transactions, "serialize_with_witness")
else:
- r += ser_vector(self.transactions)
+ r += ser_vector(self.transactions, "serialize_without_witness")
return r
def __repr__(self):
@@ -1020,7 +1027,7 @@ class msg_block():
self.block.deserialize(f)
def serialize(self):
- return self.block.serialize()
+ return self.block.serialize(with_witness=False)
def __repr__(self):
return "msg_block(block=%s)" % (repr(self.block))
@@ -1291,7 +1298,7 @@ class msg_blocktxn():
def serialize(self):
r = b""
- r += self.block_transactions.serialize()
+ r += self.block_transactions.serialize(with_witness=False)
return r
def __repr__(self):
diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py
index 9e92a70da1..99d0abc3f9 100755
--- a/test/functional/test_framework/mininode.py
+++ b/test/functional/test_framework/mininode.py
@@ -1,16 +1,18 @@
#!/usr/bin/env python3
# Copyright (c) 2010 ArtForz -- public domain half-a-node
# Copyright (c) 2012 Jeff Garzik
-# Copyright (c) 2010-2016 The Bitcoin Core developers
+# Copyright (c) 2010-2017 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Bitcoin P2P network half-a-node.
-This python code was modified from ArtForz' public domain half-a-node, as
+This python code was modified from ArtForz' public domain half-a-node, as
found in the mini-node branch of http://github.com/jgarzik/pynode.
P2PConnection: A low-level connection object to a node's P2P interface
-P2PInterface: A high-level interface object for communicating to a node over P2P"""
+P2PInterface: A high-level interface object for communicating to a node over P2P
+P2PDataStore: A p2p interface class that keeps a store of transactions and blocks
+ and can respond correctly to getdata and getheaders messages"""
import asyncore
from collections import defaultdict
from io import BytesIO
@@ -18,7 +20,7 @@ import logging
import socket
import struct
import sys
-from threading import RLock, Thread
+import threading
from test_framework.messages import *
from test_framework.util import wait_until
@@ -69,6 +71,10 @@ class P2PConnection(asyncore.dispatcher):
sub-classed and the on_message() callback overridden."""
def __init__(self):
+ # All P2PConnections must be created before starting the NetworkThread.
+ # assert that the network thread is not running.
+ assert not network_thread_running()
+
super().__init__(map=mininode_socket_map)
def peer_connect(self, dstaddr, dstport, net="regtest"):
@@ -82,7 +88,7 @@ class P2PConnection(asyncore.dispatcher):
self.network = net
self.disconnect = False
- logger.info('Connecting to Bitcoin Node: %s:%d' % (self.dstaddr, self.dstport))
+ logger.debug('Connecting to Bitcoin Node: %s:%d' % (self.dstaddr, self.dstport))
try:
self.connect((dstaddr, dstport))
@@ -352,10 +358,22 @@ class P2PInterface(P2PConnection):
wait_until(test_function, timeout=timeout, lock=mininode_lock)
def wait_for_getdata(self, timeout=60):
+ """Waits for a getdata message.
+
+ Receiving any getdata message will satisfy the predicate. the last_message["getdata"]
+ value must be explicitly cleared before calling this method, or this will return
+ immediately with success. TODO: change this method to take a hash value and only
+ return true if the correct block/tx has been requested."""
test_function = lambda: self.last_message.get("getdata")
wait_until(test_function, timeout=timeout, lock=mininode_lock)
def wait_for_getheaders(self, timeout=60):
+ """Waits for a getheaders message.
+
+ Receiving any getheaders message will satisfy the predicate. the last_message["getheaders"]
+ value must be explicitly cleared before calling this method, or this will return
+ immediately with success. TODO: change this method to take a hash value and only
+ return true if the correct block header has been requested."""
test_function = lambda: self.last_message.get("getheaders")
wait_until(test_function, timeout=timeout, lock=mininode_lock)
@@ -397,9 +415,12 @@ mininode_socket_map = dict()
# and whenever adding anything to the send buffer (in send_message()). This
# lock should be acquired in the thread running the test logic to synchronize
# access to any data shared with the P2PInterface or P2PConnection.
-mininode_lock = RLock()
+mininode_lock = threading.RLock()
+
+class NetworkThread(threading.Thread):
+ def __init__(self):
+ super().__init__(name="NetworkThread")
-class NetworkThread(Thread):
def run(self):
while mininode_socket_map:
# We check for whether to disconnect outside of the asyncore
@@ -412,3 +433,159 @@ class NetworkThread(Thread):
[obj.handle_close() for obj in disconnected]
asyncore.loop(0.1, use_poll=True, map=mininode_socket_map, count=1)
logger.debug("Network thread closing")
+
+def network_thread_start():
+ """Start the network thread."""
+ # Only one network thread may run at a time
+ assert not network_thread_running()
+
+ NetworkThread().start()
+
+def network_thread_running():
+ """Return whether the network thread is running."""
+ return any([thread.name == "NetworkThread" for thread in threading.enumerate()])
+
+def network_thread_join(timeout=10):
+ """Wait timeout seconds for the network thread to terminate.
+
+ Throw if the network thread doesn't terminate in timeout seconds."""
+ network_threads = [thread for thread in threading.enumerate() if thread.name == "NetworkThread"]
+ assert len(network_threads) <= 1
+ for thread in network_threads:
+ thread.join(timeout)
+ assert not thread.is_alive()
+
+class P2PDataStore(P2PInterface):
+ """A P2P data store class.
+
+ Keeps a block and transaction store and responds correctly to getdata and getheaders requests."""
+
+ def __init__(self):
+ super().__init__()
+ self.reject_code_received = None
+ self.reject_reason_received = None
+ # store of blocks. key is block hash, value is a CBlock object
+ self.block_store = {}
+ self.last_block_hash = ''
+ # store of txs. key is txid, value is a CTransaction object
+ self.tx_store = {}
+ self.getdata_requests = []
+
+ def on_getdata(self, message):
+ """Check for the tx/block in our stores and if found, reply with an inv message."""
+ for inv in message.inv:
+ self.getdata_requests.append(inv.hash)
+ if (inv.type & MSG_TYPE_MASK) == MSG_TX and inv.hash in self.tx_store.keys():
+ self.send_message(msg_tx(self.tx_store[inv.hash]))
+ elif (inv.type & MSG_TYPE_MASK) == MSG_BLOCK and inv.hash in self.block_store.keys():
+ self.send_message(msg_block(self.block_store[inv.hash]))
+ else:
+ logger.debug('getdata message type {} received.'.format(hex(inv.type)))
+
+ def on_getheaders(self, message):
+ """Search back through our block store for the locator, and reply with a headers message if found."""
+
+ locator, hash_stop = message.locator, message.hashstop
+
+ # Assume that the most recent block added is the tip
+ if not self.block_store:
+ return
+
+ headers_list = [self.block_store[self.last_block_hash]]
+ maxheaders = 2000
+ while headers_list[-1].sha256 not in locator.vHave:
+ # Walk back through the block store, adding headers to headers_list
+ # as we go.
+ prev_block_hash = headers_list[-1].hashPrevBlock
+ if prev_block_hash in self.block_store:
+ prev_block_header = self.block_store[prev_block_hash]
+ headers_list.append(prev_block_header)
+ if prev_block_header.sha256 == hash_stop:
+ # if this is the hashstop header, stop here
+ break
+ else:
+ logger.debug('block hash {} not found in block store'.format(hex(prev_block_hash)))
+ break
+
+ # Truncate the list if there are too many headers
+ headers_list = headers_list[:-maxheaders - 1:-1]
+ response = msg_headers(headers_list)
+
+ if response is not None:
+ self.send_message(response)
+
+ def on_reject(self, message):
+ """Store reject reason and code for testing."""
+ self.reject_code_received = message.code
+ self.reject_reason_received = message.reason
+
+ def send_blocks_and_test(self, blocks, rpc, success=True, request_block=True, reject_code=None, reject_reason=None, timeout=60):
+ """Send blocks to test node and test whether the tip advances.
+
+ - add all blocks to our block_store
+ - send a headers message for the final block
+ - the on_getheaders handler will ensure that any getheaders are responded to
+ - if request_block is True: wait for getdata for each of the blocks. The on_getdata handler will
+ ensure that any getdata messages are responded to
+ - if success is True: assert that the node's tip advances to the most recent block
+ - if success is False: assert that the node's tip doesn't advance
+ - if reject_code and reject_reason are set: assert that the correct reject message is received"""
+
+ with mininode_lock:
+ self.reject_code_received = None
+ self.reject_reason_received = None
+
+ for block in blocks:
+ self.block_store[block.sha256] = block
+ self.last_block_hash = block.sha256
+
+ self.send_message(msg_headers([blocks[-1]]))
+
+ if request_block:
+ wait_until(lambda: blocks[-1].sha256 in self.getdata_requests, timeout=timeout, lock=mininode_lock)
+
+ if success:
+ wait_until(lambda: rpc.getbestblockhash() == blocks[-1].hash, timeout=timeout)
+ else:
+ assert rpc.getbestblockhash() != blocks[-1].hash
+
+ if reject_code is not None:
+ wait_until(lambda: self.reject_code_received == reject_code, lock=mininode_lock)
+ 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):
+ """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 reject_code and reject_reason are set: assert that the correct reject message is received."""
+
+ with mininode_lock:
+ self.reject_code_received = None
+ self.reject_reason_received = None
+
+ for tx in txs:
+ self.tx_store[tx.sha256] = tx
+
+ for tx in txs:
+ self.send_message(msg_tx(tx))
+
+ self.sync_with_ping()
+
+ raw_mempool = rpc.getrawmempool()
+ if success:
+ # Check that all txs are now in the mempool
+ for tx in txs:
+ assert tx.hash in raw_mempool, "{} not found in mempool".format(tx.hash)
+ else:
+ # Check that none of the txs are now in the mempool
+ for tx in txs:
+ assert tx.hash not in raw_mempool, "{} tx found in mempool".format(tx.hash)
+
+ if reject_code is not None:
+ wait_until(lambda: self.reject_code_received == reject_code, lock=mininode_lock)
+ if reject_reason is not None:
+ wait_until(lambda: self.reject_reason_received == reject_reason, lock=mininode_lock)
diff --git a/test/functional/test_framework/netutil.py b/test/functional/test_framework/netutil.py
index e5d415788f..96fe283347 100644
--- a/test/functional/test_framework/netutil.py
+++ b/test/functional/test_framework/netutil.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Linux network utilities.
diff --git a/test/functional/test_framework/script.py b/test/functional/test_framework/script.py
index a4c046bd3d..dae8a4e569 100644
--- a/test/functional/test_framework/script.py
+++ b/test/functional/test_framework/script.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2016 The Bitcoin Core developers
+# Copyright (c) 2015-2017 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Functionality to build scripts, as well as SignatureHash().
@@ -641,7 +641,7 @@ def SignatureHash(script, txTo, inIdx, hashtype):
txtmp.vin = []
txtmp.vin.append(tmp)
- s = txtmp.serialize()
+ s = txtmp.serialize_without_witness()
s += struct.pack(b"<I", hashtype)
hash = hash256(s)
diff --git a/test/functional/test_framework/siphash.py b/test/functional/test_framework/siphash.py
index f68ecad36b..6ffc982cea 100644
--- a/test/functional/test_framework/siphash.py
+++ b/test/functional/test_framework/siphash.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2016 The Bitcoin Core developers
+# Copyright (c) 2016-2017 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Specialized SipHash-2-4 implementations.
diff --git a/test/functional/test_framework/socks5.py b/test/functional/test_framework/socks5.py
index 7b40c47fbf..4721809a3b 100644
--- a/test/functional/test_framework/socks5.py
+++ b/test/functional/test_framework/socks5.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2016 The Bitcoin Core developers
+# Copyright (c) 2015-2017 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Dummy Socks5 server for testing."""
diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py
index a46312d62c..a5e66bd959 100755
--- a/test/functional/test_framework/test_framework.py
+++ b/test/functional/test_framework/test_framework.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Base class for RPC testing."""
@@ -62,6 +62,7 @@ class BitcoinTestFramework():
self.setup_clean_chain = False
self.nodes = []
self.mocktime = 0
+ self.supports_cli = False
self.set_test_params()
assert hasattr(self, "num_nodes"), "Test must set self.num_nodes in set_test_params()"
@@ -91,12 +92,16 @@ class BitcoinTestFramework():
help="Location of the test framework config file")
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",
+ help="use bitcoin-cli instead of RPC for all commands")
self.add_options(parser)
(self.options, self.args) = parser.parse_args()
PortSeed.n = self.options.port_seed
- os.environ['PATH'] = self.options.srcdir + ":" + self.options.srcdir + "/qt:" + os.environ['PATH']
+ os.environ['PATH'] = self.options.srcdir + os.pathsep + \
+ self.options.srcdir + os.path.sep + "qt" + os.pathsep + \
+ os.environ['PATH']
check_json_precision()
@@ -113,6 +118,8 @@ class BitcoinTestFramework():
success = TestStatus.FAILED
try:
+ if self.options.usecli and not self.supports_cli:
+ raise SkipTest("--usecli specified but test does not support using CLI")
self.setup_chain()
self.setup_network()
self.run_test()
@@ -143,10 +150,11 @@ class BitcoinTestFramework():
self.log.info("Note: bitcoinds were not stopped and may still be running")
if not self.options.nocleanup and not self.options.noshutdown and success != TestStatus.FAILED:
- self.log.info("Cleaning up")
- shutil.rmtree(self.options.tmpdir)
+ self.log.info("Cleaning up {} on exit".format(self.options.tmpdir))
+ cleanup_tree_on_exit = True
else:
self.log.warning("Not cleaning up dir %s" % self.options.tmpdir)
+ cleanup_tree_on_exit = False
if success == TestStatus.PASSED:
self.log.info("Tests successful")
@@ -159,6 +167,8 @@ class BitcoinTestFramework():
self.log.error("Hint: Call {} '{}' to consolidate all logs".format(os.path.normpath(os.path.dirname(os.path.realpath(__file__)) + "/../combine_logs.py"), self.options.tmpdir))
exit_code = TEST_EXIT_FAILED
logging.shutdown()
+ if cleanup_tree_on_exit:
+ shutil.rmtree(self.options.tmpdir)
sys.exit(exit_code)
# Methods to override in subclass test scripts.
@@ -213,20 +223,20 @@ class BitcoinTestFramework():
assert_equal(len(extra_args), num_nodes)
assert_equal(len(binary), num_nodes)
for i in range(num_nodes):
- self.nodes.append(TestNode(i, self.options.tmpdir, extra_args[i], rpchost, timewait=timewait, binary=binary[i], stderr=None, mocktime=self.mocktime, coverage_dir=self.options.coveragedir))
+ self.nodes.append(TestNode(i, self.options.tmpdir, extra_args[i], rpchost, timewait=timewait, binary=binary[i], stderr=None, mocktime=self.mocktime, coverage_dir=self.options.coveragedir, use_cli=self.options.usecli))
- def start_node(self, i, extra_args=None, stderr=None):
+ def start_node(self, i, *args, **kwargs):
"""Start a bitcoind"""
node = self.nodes[i]
- node.start(extra_args, stderr)
+ node.start(*args, **kwargs)
node.wait_for_rpc_connection()
if self.options.coveragedir is not None:
coverage.write_all_rpc_commands(self.options.coveragedir, node.rpc)
- def start_nodes(self, extra_args=None):
+ def start_nodes(self, extra_args=None, *args, **kwargs):
"""Start multiple bitcoinds"""
if extra_args is None:
@@ -234,7 +244,7 @@ class BitcoinTestFramework():
assert_equal(len(extra_args), self.num_nodes)
try:
for i, node in enumerate(self.nodes):
- node.start(extra_args[i])
+ node.start(extra_args[i], *args, **kwargs)
for node in self.nodes:
node.wait_for_rpc_connection()
except:
@@ -266,10 +276,10 @@ class BitcoinTestFramework():
self.stop_node(i)
self.start_node(i, extra_args)
- def assert_start_raises_init_error(self, i, extra_args=None, expected_msg=None):
+ def assert_start_raises_init_error(self, i, extra_args=None, expected_msg=None, *args, **kwargs):
with tempfile.SpooledTemporaryFile(max_size=2**16) as log_stderr:
try:
- self.start_node(i, extra_args, stderr=log_stderr)
+ self.start_node(i, extra_args, stderr=log_stderr, *args, **kwargs)
self.stop_node(i)
except Exception as e:
assert 'bitcoind exited' in str(e) # node must have shutdown
diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py
index a9248c764e..1054e6d028 100755
--- a/test/functional/test_framework/test_node.py
+++ b/test/functional/test_framework/test_node.py
@@ -10,6 +10,7 @@ import http.client
import json
import logging
import os
+import re
import subprocess
import time
@@ -22,6 +23,9 @@ from .util import (
p2p_port,
)
+# For Python 3.4 compatibility
+JSONDecodeError = getattr(json, "JSONDecodeError", ValueError)
+
BITCOIND_PROC_WAIT_TIMEOUT = 60
class TestNode():
@@ -38,7 +42,7 @@ class TestNode():
To make things easier for the test writer, any unrecognised messages will
be dispatched to the RPC connection."""
- def __init__(self, i, dirname, extra_args, rpchost, timewait, binary, stderr, mocktime, coverage_dir):
+ def __init__(self, i, dirname, extra_args, rpchost, timewait, binary, stderr, mocktime, coverage_dir, use_cli=False):
self.index = i
self.datadir = os.path.join(dirname, "node" + str(i))
self.rpchost = rpchost
@@ -58,6 +62,7 @@ class TestNode():
self.args = [self.binary, "-datadir=" + self.datadir, "-server", "-keypool=1", "-discover=0", "-rest", "-logtimemicros", "-debug", "-debugexclude=libevent", "-debugexclude=leveldb", "-mocktime=" + str(mocktime), "-uacomment=testnode%d" % i]
self.cli = TestNodeCLI(os.getenv("BITCOINCLI", "bitcoin-cli"), self.datadir)
+ self.use_cli = use_cli
self.running = False
self.process = None
@@ -69,17 +74,20 @@ class TestNode():
self.p2ps = []
def __getattr__(self, name):
- """Dispatches any unrecognised messages to the RPC connection."""
- assert self.rpc_connected and self.rpc is not None, "Error: no RPC connection"
- return getattr(self.rpc, name)
+ """Dispatches any unrecognised messages to the RPC connection or a CLI instance."""
+ if self.use_cli:
+ return getattr(self.cli, name)
+ else:
+ assert self.rpc_connected and self.rpc is not None, "Error: no RPC connection"
+ return getattr(self.rpc, name)
- def start(self, extra_args=None, stderr=None):
+ def start(self, extra_args=None, stderr=None, *args, **kwargs):
"""Start the node."""
if extra_args is None:
extra_args = self.extra_args
if stderr is None:
stderr = self.stderr
- self.process = subprocess.Popen(self.args + extra_args, stderr=stderr)
+ self.process = subprocess.Popen(self.args + extra_args, stderr=stderr, *args, **kwargs)
self.running = True
self.log.debug("bitcoind started, waiting for RPC to come up")
@@ -110,10 +118,13 @@ class TestNode():
raise AssertionError("Unable to connect to bitcoind")
def get_wallet_rpc(self, wallet_name):
- assert self.rpc_connected
- assert self.rpc
- wallet_path = "wallet/%s" % wallet_name
- return self.rpc / wallet_path
+ if self.use_cli:
+ return self.cli("-rpcwallet={}".format(wallet_name))
+ else:
+ assert self.rpc_connected
+ assert self.rpc
+ wallet_path = "wallet/%s" % wallet_name
+ return self.rpc / wallet_path
def stop_node(self):
"""Stop the node."""
@@ -187,41 +198,70 @@ class TestNode():
p.peer_disconnect()
del self.p2ps[:]
+class TestNodeCLIAttr:
+ def __init__(self, cli, command):
+ self.cli = cli
+ self.command = command
+
+ def __call__(self, *args, **kwargs):
+ return self.cli.send_cli(self.command, *args, **kwargs)
+
+ def get_request(self, *args, **kwargs):
+ return lambda: self(*args, **kwargs)
class TestNodeCLI():
"""Interface to bitcoin-cli for an individual node"""
def __init__(self, binary, datadir):
- self.args = []
+ self.options = []
self.binary = binary
self.datadir = datadir
self.input = None
+ self.log = logging.getLogger('TestFramework.bitcoincli')
- def __call__(self, *args, input=None):
- # TestNodeCLI is callable with bitcoin-cli command-line args
- self.args = [str(arg) for arg in args]
- self.input = input
- return self
+ def __call__(self, *options, input=None):
+ # TestNodeCLI is callable with bitcoin-cli command-line options
+ cli = TestNodeCLI(self.binary, self.datadir)
+ cli.options = [str(o) for o in options]
+ cli.input = input
+ return cli
def __getattr__(self, command):
- def dispatcher(*args, **kwargs):
- return self.send_cli(command, *args, **kwargs)
- return dispatcher
-
- def send_cli(self, command, *args, **kwargs):
+ return TestNodeCLIAttr(self, command)
+
+ def batch(self, requests):
+ results = []
+ for request in requests:
+ try:
+ results.append(dict(result=request()))
+ except JSONRPCException as e:
+ results.append(dict(error=e))
+ return results
+
+ def send_cli(self, command=None, *args, **kwargs):
"""Run bitcoin-cli command. Deserializes returned string as python object."""
pos_args = [str(arg) for arg in args]
named_args = [str(key) + "=" + str(value) for (key, value) in kwargs.items()]
assert not (pos_args and named_args), "Cannot use positional arguments and named arguments in the same bitcoin-cli call"
- p_args = [self.binary, "-datadir=" + self.datadir] + self.args
+ p_args = [self.binary, "-datadir=" + self.datadir] + self.options
if named_args:
p_args += ["-named"]
- p_args += [command] + pos_args + named_args
+ if command is not None:
+ p_args += [command]
+ p_args += pos_args + named_args
+ self.log.debug("Running bitcoin-cli command: %s" % command)
process = subprocess.Popen(p_args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
cli_stdout, cli_stderr = process.communicate(input=self.input)
returncode = process.poll()
if returncode:
+ match = re.match(r'error code: ([-0-9]+)\nerror message:\n(.*)', cli_stderr)
+ if match:
+ code, message = match.groups()
+ raise JSONRPCException(dict(code=int(code), message=message))
# Ignore cli_stdout, raise with cli_stderr
raise subprocess.CalledProcessError(returncode, self.binary, output=cli_stderr)
- return json.loads(cli_stdout, parse_float=decimal.Decimal)
+ try:
+ return json.loads(cli_stdout, parse_float=decimal.Decimal)
+ except JSONDecodeError:
+ return cli_stdout.rstrip("\n")
diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py
index 102c903018..7fdc171332 100644
--- a/test/functional/test_framework/util.py
+++ b/test/functional/test_framework/util.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Helpful routines for regression testing."""
@@ -390,7 +390,7 @@ def sync_chain(rpc_connections, *, wait=1, timeout=60):
timeout -= wait
raise AssertionError("Chain sync failed: Best block hashes don't match")
-def sync_mempools(rpc_connections, *, wait=1, timeout=60):
+def sync_mempools(rpc_connections, *, wait=1, timeout=60, flush_scheduler=True):
"""
Wait until everybody has the same transactions in their memory
pools
@@ -402,6 +402,9 @@ def sync_mempools(rpc_connections, *, wait=1, timeout=60):
if set(rpc_connections[i].getrawmempool()) == pool:
num_match = num_match + 1
if num_match == len(rpc_connections):
+ if flush_scheduler:
+ for r in rpc_connections:
+ r.syncwithvalidationinterfacequeue()
return
time.sleep(wait)
timeout -= wait
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index 58faec521d..0cf3424c71 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Run regression test suite.
@@ -55,108 +55,114 @@ TEST_EXIT_SKIPPED = 77
BASE_SCRIPTS= [
# Scripts that are run by the travis build process.
# Longest test should go first, to favor running tests in parallel
- 'wallet-hd.py',
- 'walletbackup.py',
+ 'wallet_hd.py',
+ 'wallet_backup.py',
# vv Tests less than 5m vv
- 'p2p-fullblocktest.py',
- 'fundrawtransaction.py',
- 'p2p-compactblocks.py',
- 'segwit.py',
+ 'feature_block.py',
+ 'rpc_fundrawtransaction.py',
+ 'p2p_compactblocks.py',
+ 'feature_segwit.py',
# vv Tests less than 2m vv
- 'wallet.py',
- 'wallet-accounts.py',
- 'p2p-segwit.py',
- 'wallet-dump.py',
- 'listtransactions.py',
+ 'wallet_basic.py',
+ 'wallet_accounts.py',
+ 'p2p_segwit.py',
+ 'wallet_dump.py',
+ 'rpc_listtransactions.py',
# vv Tests less than 60s vv
- 'sendheaders.py',
- 'zapwallettxes.py',
- 'importmulti.py',
+ 'p2p_sendheaders.py',
+ 'wallet_zapwallettxes.py',
+ 'wallet_importmulti.py',
'mempool_limit.py',
- 'merkle_blocks.py',
- 'receivedby.py',
- 'abandonconflict.py',
- 'bip68-112-113-p2p.py',
- 'rawtransactions.py',
- 'reindex.py',
+ 'rpc_txoutproof.py',
+ 'wallet_listreceivedby.py',
+ 'wallet_abandonconflict.py',
+ 'feature_csv_activation.py',
+ 'rpc_rawtransaction.py',
+ 'wallet_address_types.py',
+ 'feature_reindex.py',
# vv Tests less than 30s vv
- 'keypool-topup.py',
- 'zmq_test.py',
- 'bitcoin_cli.py',
- 'mempool_resurrect_test.py',
- 'txn_doublespend.py --mineblock',
- 'txn_clone.py',
- 'getchaintips.py',
- 'rest.py',
- 'mempool_spendcoinbase.py',
+ 'wallet_keypool_topup.py',
+ 'interface_zmq.py',
+ 'interface_bitcoin_cli.py',
+ 'mempool_resurrect.py',
+ 'wallet_txn_doublespend.py --mineblock',
+ 'wallet_txn_clone.py',
+ 'wallet_txn_clone.py --segwit',
+ 'rpc_getchaintips.py',
+ 'interface_rest.py',
+ 'mempool_spend_coinbase.py',
'mempool_reorg.py',
'mempool_persist.py',
- 'multiwallet.py',
- 'httpbasics.py',
- 'multi_rpc.py',
- 'proxy_test.py',
- 'signrawtransactions.py',
- 'disconnect_ban.py',
- 'decodescript.py',
- 'blockchain.py',
- 'deprecated_rpc.py',
- 'disablewallet.py',
- 'net.py',
- 'keypool.py',
- 'p2p-mempool.py',
- 'prioritise_transaction.py',
- 'invalidblockrequest.py',
- 'invalidtxrequest.py',
- 'p2p-versionbits-warning.py',
- 'preciousblock.py',
- 'importprunedfunds.py',
- 'signmessages.py',
- 'nulldummy.py',
- 'import-rescan.py',
- 'mining.py',
- 'bumpfee.py',
- 'rpcnamedargs.py',
- 'listsinceblock.py',
- 'p2p-leaktests.py',
- 'wallet-encryption.py',
- 'bipdersig-p2p.py',
- 'bip65-cltv-p2p.py',
- 'uptime.py',
- 'resendwallettransactions.py',
- 'minchainwork.py',
- 'p2p-fingerprint.py',
- 'uacomment.py',
- 'p2p-acceptblock.py',
+ 'wallet_multiwallet.py',
+ 'wallet_multiwallet.py --usecli',
+ 'interface_http.py',
+ 'rpc_users.py',
+ 'feature_proxy.py',
+ 'rpc_signrawtransaction.py',
+ 'p2p_disconnect_ban.py',
+ 'rpc_decodescript.py',
+ 'rpc_blockchain.py',
+ 'rpc_deprecated.py',
+ 'wallet_disable.py',
+ 'rpc_net.py',
+ 'wallet_keypool.py',
+ 'p2p_mempool.py',
+ 'mining_prioritisetransaction.py',
+ 'p2p_invalid_block.py',
+ 'p2p_invalid_tx.py',
+ 'feature_versionbits_warning.py',
+ 'rpc_preciousblock.py',
+ 'wallet_importprunedfunds.py',
+ 'rpc_signmessage.py',
+ 'feature_nulldummy.py',
+ 'wallet_import_rescan.py',
+ 'mining_basic.py',
+ 'wallet_bumpfee.py',
+ 'rpc_named_arguments.py',
+ 'wallet_listsinceblock.py',
+ 'p2p_leak.py',
+ 'wallet_encryption.py',
+ 'feature_dersig.py',
+ 'feature_cltv.py',
+ 'rpc_uptime.py',
+ 'wallet_resendwallettransactions.py',
+ 'feature_minchainwork.py',
+ 'p2p_fingerprint.py',
+ 'feature_uacomment.py',
+ 'p2p_unrequested_blocks.py',
'feature_logging.py',
- 'node_network_limited.py',
+ 'p2p_node_network_limited.py',
+ 'feature_config_args.py',
+ # Don't append tests at the end to avoid merge conflicts
+ # Put them in a random line within the section that fits their approximate run-time
]
EXTENDED_SCRIPTS = [
# These tests are not run by the travis build process.
# Longest test should go first, to favor running tests in parallel
- 'pruning.py',
+ 'feature_pruning.py',
# vv Tests less than 20m vv
- 'smartfees.py',
+ 'feature_fee_estimation.py',
# vv Tests less than 5m vv
- 'maxuploadtarget.py',
+ 'feature_maxuploadtarget.py',
'mempool_packages.py',
- 'dbcrash.py',
+ 'feature_dbcrash.py',
# vv Tests less than 2m vv
- 'bip68-sequence.py',
- 'getblocktemplate_longpoll.py',
- 'p2p-timeouts.py',
+ 'feature_bip68_sequence.py',
+ 'mining_getblocktemplate_longpoll.py',
+ 'p2p_timeouts.py',
# vv Tests less than 60s vv
- 'bip9-softforks.py',
- 'p2p-feefilter.py',
- 'rpcbind_test.py',
+ 'feature_bip9_softforks.py',
+ 'p2p_feefilter.py',
+ 'rpc_bind.py',
# vv Tests less than 30s vv
- 'assumevalid.py',
+ 'feature_assumevalid.py',
'example_test.py',
- 'txn_doublespend.py',
- 'txn_clone.py --mineblock',
- 'notifications.py',
- 'invalidateblock.py',
- 'replace-by-fee.py',
+ 'wallet_txn_doublespend.py',
+ 'wallet_txn_clone.py --mineblock',
+ 'feature_notifications.py',
+ 'rpc_invalidateblock.py',
+ 'feature_rbf.py',
]
# Place EXTENDED_SCRIPTS first since it has the 3 longest running tests
@@ -262,10 +268,11 @@ def main():
if args.help:
# Print help for test_runner.py, then print help of the first script (with args removed) and exit.
parser.print_help()
- subprocess.check_call([(config["environment"]["SRCDIR"] + '/test/functional/' + test_list[0].split()[0])] + ['-h'])
+ subprocess.check_call([sys.executable, os.path.join(config["environment"]["SRCDIR"], 'test', 'functional', test_list[0].split()[0]), '-h'])
sys.exit(0)
check_script_list(config["environment"]["SRCDIR"])
+ check_script_prefixes()
if not args.keepcache:
shutil.rmtree("%s/test/cache" % config["environment"]["BUILDDIR"], ignore_errors=True)
@@ -305,10 +312,10 @@ def run_tests(test_list, src_dir, build_dir, exeext, tmpdir, jobs=1, enable_cove
if len(test_list) > 1 and jobs > 1:
# Populate cache
try:
- subprocess.check_output([tests_dir + 'create_cache.py'] + flags + ["--tmpdir=%s/cache" % tmpdir])
- except Exception as e:
- print(e.output)
- raise e
+ subprocess.check_output([sys.executable, tests_dir + 'create_cache.py'] + flags + ["--tmpdir=%s/cache" % tmpdir])
+ except subprocess.CalledProcessError as e:
+ sys.stdout.buffer.write(e.output)
+ raise
#Run Tests
job_queue = TestHandler(jobs, tests_dir, tmpdir, test_list, flags)
@@ -335,7 +342,7 @@ def run_tests(test_list, src_dir, build_dir, exeext, tmpdir, jobs=1, enable_cove
print('\n============')
print('{}Combined log for {}:{}'.format(BOLD[1], testdir, BOLD[0]))
print('============\n')
- combined_logs, _ = subprocess.Popen([os.path.join(tests_dir, 'combine_logs.py'), '-c', testdir], universal_newlines=True, stdout=subprocess.PIPE).communicate()
+ combined_logs, _ = subprocess.Popen([sys.executble, 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)))
print_results(test_results, max_len_name, (int(time.time() - time0)))
@@ -405,7 +412,7 @@ class TestHandler:
tmpdir_arg = ["--tmpdir={}".format(testdir)]
self.jobs.append((t,
time.time(),
- subprocess.Popen([self.tests_dir + test_argv[0]] + test_argv[1:] + self.flags + portseed_arg + tmpdir_arg,
+ subprocess.Popen([sys.executable, self.tests_dir + test_argv[0]] + test_argv[1:] + self.flags + portseed_arg + tmpdir_arg,
universal_newlines=True,
stdout=log_stdout,
stderr=log_stderr),
@@ -464,6 +471,18 @@ class TestResult():
return self.status != "Failed"
+def check_script_prefixes():
+ """Check that test scripts start with one of the allowed name prefixes."""
+
+ good_prefixes_re = re.compile("(example|feature|interface|mempool|mining|p2p|rpc|wallet)_")
+ bad_script_names = [script for script in ALL_SCRIPTS if good_prefixes_re.match(script) is None]
+
+ if bad_script_names:
+ print("%sERROR:%s %d tests not meeting naming conventions:" % (BOLD[1], BOLD[0], len(bad_script_names)))
+ print(" %s" % ("\n ".join(sorted(bad_script_names))))
+ raise AssertionError("Some tests are not following naming convention!")
+
+
def check_script_list(src_dir):
"""Check scripts directory.
diff --git a/test/functional/abandonconflict.py b/test/functional/wallet_abandonconflict.py
index e8dbc86469..8fb860cd7e 100755
--- a/test/functional/abandonconflict.py
+++ b/test/functional/wallet_abandonconflict.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 the abandontransaction RPC.
@@ -8,11 +8,12 @@
descendants as abandoned which allows their inputs to be respent. It can be
used to replace "stuck" or evicted transactions. It only works on transactions
which are not included in a block and are not currently in the mempool. It has
- no effect on transactions which are already conflicted or abandoned.
+ no effect on transactions which are already abandoned.
"""
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
+
class AbandonConflictTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
@@ -28,6 +29,11 @@ class AbandonConflictTest(BitcoinTestFramework):
sync_mempools(self.nodes)
self.nodes[1].generate(1)
+ # Can not abandon non-wallet transaction
+ assert_raises_rpc_error(-5, 'Invalid or non-wallet transaction id', lambda: self.nodes[0].abandontransaction(txid='ff' * 32))
+ # Can not abandon confirmed transaction
+ assert_raises_rpc_error(-5, 'Transaction not eligible for abandonment', lambda: self.nodes[0].abandontransaction(txid=txA))
+
sync_blocks(self.nodes)
newbalance = self.nodes[0].getbalance()
assert(balance - newbalance < Decimal("0.001")) #no more than fees lost
diff --git a/test/functional/wallet-accounts.py b/test/functional/wallet_accounts.py
index bc1efaee15..ecd1cfc82b 100755
--- a/test/functional/wallet-accounts.py
+++ b/test/functional/wallet_accounts.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2016 The Bitcoin Core developers
+# Copyright (c) 2016-2017 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 account RPCs.
@@ -126,7 +126,7 @@ class WalletAccountsTest(BitcoinTestFramework):
addresses = []
for x in range(10):
addresses.append(node.getnewaddress())
- multisig_address = node.addmultisigaddress(5, addresses, account.name)
+ multisig_address = node.addmultisigaddress(5, addresses, account.name)['address']
account.add_address(multisig_address)
account.verify(node)
node.sendfrom("", multisig_address, 50)
diff --git a/test/functional/wallet_address_types.py b/test/functional/wallet_address_types.py
new file mode 100755
index 0000000000..38a3425214
--- /dev/null
+++ b/test/functional/wallet_address_types.py
@@ -0,0 +1,294 @@
+#!/usr/bin/env python3
+# Copyright (c) 2017 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 that the wallet can send and receive using all combinations of address types.
+
+There are 5 nodes-under-test:
+ - node0 uses legacy addresses
+ - node1 uses p2sh/segwit addresses
+ - node2 uses p2sh/segwit addresses and bech32 addresses for change
+ - node3 uses bech32 addresses
+ - node4 uses a p2sh/segwit addresses for change
+
+node5 exists to generate new blocks.
+
+## Multisig address test
+
+Test that adding a multisig address with:
+ - an uncompressed pubkey always gives a legacy address
+ - only compressed pubkeys gives the an `-addresstype` address
+
+## Sending to address types test
+
+A series of tests, iterating over node0-node4. In each iteration of the test, one node sends:
+ - 10/101th of its balance to itself (using getrawchangeaddress for single key addresses)
+ - 20/101th to the next node
+ - 30/101th to the node after that
+ - 40/101th to the remaining node
+ - 1/101th remains as fee+change
+
+Iterate over each node for single key addresses, and then over each node for
+multisig addresses.
+
+Repeat test, but with explicit address_type parameters passed to getnewaddress
+and getrawchangeaddress:
+ - node0 and node3 send to p2sh.
+ - node1 sends to bech32.
+ - node2 sends to legacy.
+
+As every node sends coins after receiving, this also
+verifies that spending coins sent to all these address types works.
+
+## Change type test
+
+Test that the nodes generate the correct change address type:
+ - node0 always uses a legacy change address.
+ - node1 uses a bech32 addresses for change if any destination address is bech32.
+ - node2 always uses a bech32 address for change
+ - node3 always uses a bech32 address for change
+ - node4 always uses p2sh/segwit output for change.
+"""
+
+from decimal import Decimal
+import itertools
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import (
+ assert_equal,
+ assert_greater_than,
+ assert_raises_rpc_error,
+ connect_nodes_bi,
+ sync_blocks,
+ sync_mempools,
+)
+
+class AddressTypeTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.num_nodes = 6
+ self.extra_args = [
+ ["-addresstype=legacy"],
+ ["-addresstype=p2sh-segwit"],
+ ["-addresstype=p2sh-segwit", "-changetype=bech32"],
+ ["-addresstype=bech32"],
+ ["-changetype=p2sh-segwit"],
+ []
+ ]
+
+ def setup_network(self):
+ self.setup_nodes()
+
+ # Fully mesh-connect nodes for faster mempool sync
+ for i, j in itertools.product(range(self.num_nodes), repeat=2):
+ if i > j:
+ connect_nodes_bi(self.nodes, i, j)
+ self.sync_all()
+
+ def get_balances(self, confirmed=True):
+ """Return a list of confirmed or unconfirmed balances."""
+ if confirmed:
+ return [self.nodes[i].getbalance() for i in range(4)]
+ else:
+ return [self.nodes[i].getunconfirmedbalance() for i in range(4)]
+
+ def test_address(self, node, address, multisig, typ):
+ """Run sanity checks on an address."""
+ info = self.nodes[node].validateaddress(address)
+ assert(info['isvalid'])
+ if not multisig and typ == 'legacy':
+ # P2PKH
+ assert(not info['isscript'])
+ assert(not info['iswitness'])
+ assert('pubkey' in info)
+ elif not multisig and typ == 'p2sh-segwit':
+ # P2SH-P2WPKH
+ assert(info['isscript'])
+ assert(not info['iswitness'])
+ assert_equal(info['script'], 'witness_v0_keyhash')
+ assert('pubkey' in info)
+ elif not multisig and typ == 'bech32':
+ # P2WPKH
+ assert(not info['isscript'])
+ assert(info['iswitness'])
+ assert_equal(info['witness_version'], 0)
+ assert_equal(len(info['witness_program']), 40)
+ assert('pubkey' in info)
+ elif typ == 'legacy':
+ # P2SH-multisig
+ assert(info['isscript'])
+ assert_equal(info['script'], 'multisig')
+ assert(not info['iswitness'])
+ assert('pubkeys' in info)
+ elif typ == 'p2sh-segwit':
+ # P2SH-P2WSH-multisig
+ assert(info['isscript'])
+ assert_equal(info['script'], 'witness_v0_scripthash')
+ assert(not info['iswitness'])
+ assert(info['embedded']['isscript'])
+ assert_equal(info['embedded']['script'], 'multisig')
+ assert(info['embedded']['iswitness'])
+ assert_equal(info['embedded']['witness_version'], 0)
+ assert_equal(len(info['embedded']['witness_program']), 64)
+ assert('pubkeys' in info['embedded'])
+ elif typ == 'bech32':
+ # P2WSH-multisig
+ assert(info['isscript'])
+ assert_equal(info['script'], 'multisig')
+ assert(info['iswitness'])
+ assert_equal(info['witness_version'], 0)
+ assert_equal(len(info['witness_program']), 64)
+ assert('pubkeys' in info)
+ else:
+ # Unknown type
+ assert(False)
+
+ def test_change_output_type(self, node_sender, destinations, expected_type):
+ txid = self.nodes[node_sender].sendmany(fromaccount="", amounts=dict.fromkeys(destinations, 0.001))
+ raw_tx = self.nodes[node_sender].getrawtransaction(txid)
+ tx = self.nodes[node_sender].decoderawtransaction(raw_tx)
+
+ # Make sure the transaction has change:
+ assert_equal(len(tx["vout"]), len(destinations) + 1)
+
+ # Make sure the destinations are included, and remove them:
+ output_addresses = [vout['scriptPubKey']['addresses'][0] for vout in tx["vout"]]
+ change_addresses = [d for d in output_addresses if d not in destinations]
+ assert_equal(len(change_addresses), 1)
+
+ self.log.debug("Check if change address " + change_addresses[0] + " is " + expected_type)
+ self.test_address(node_sender, change_addresses[0], multisig=False, typ=expected_type)
+
+ def run_test(self):
+ # Mine 101 blocks on node5 to bring nodes out of IBD and make sure that
+ # no coinbases are maturing for the nodes-under-test during the test
+ self.nodes[5].generate(101)
+ sync_blocks(self.nodes)
+
+ uncompressed_1 = "0496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858ee"
+ uncompressed_2 = "047211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073dee6c89064984f03385237d92167c13e236446b417ab79a0fcae412ae3316b77"
+ compressed_1 = "0296b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52"
+ compressed_2 = "037211a824f55b505228e4c3d5194c1fcfaa15a456abdf37f9b9d97a4040afc073"
+
+ # addmultisigaddress with at least 1 uncompressed key should return a legacy address.
+ for node in range(4):
+ self.test_address(node, self.nodes[node].addmultisigaddress(2, [uncompressed_1, uncompressed_2])['address'], True, 'legacy')
+ self.test_address(node, self.nodes[node].addmultisigaddress(2, [compressed_1, uncompressed_2])['address'], True, 'legacy')
+ self.test_address(node, self.nodes[node].addmultisigaddress(2, [uncompressed_1, compressed_2])['address'], True, 'legacy')
+ # addmultisigaddress with all compressed keys should return the appropriate address type (even when the keys are not ours).
+ self.test_address(0, self.nodes[0].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'legacy')
+ self.test_address(1, self.nodes[1].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'p2sh-segwit')
+ self.test_address(2, self.nodes[2].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'p2sh-segwit')
+ self.test_address(3, self.nodes[3].addmultisigaddress(2, [compressed_1, compressed_2])['address'], True, 'bech32')
+
+ for explicit_type, multisig, from_node in itertools.product([False, True], [False, True], range(4)):
+ address_type = None
+ if explicit_type and not multisig:
+ if from_node == 1:
+ address_type = 'bech32'
+ elif from_node == 0 or from_node == 3:
+ address_type = 'p2sh-segwit'
+ else:
+ address_type = 'legacy'
+ self.log.info("Sending from node {} ({}) with{} multisig using {}".format(from_node, self.extra_args[from_node], "" if multisig else "out", "default" if address_type is None else address_type))
+ old_balances = self.get_balances()
+ self.log.debug("Old balances are {}".format(old_balances))
+ to_send = (old_balances[from_node] / 101).quantize(Decimal("0.00000001"))
+ sends = {}
+
+ self.log.debug("Prepare sends")
+ for n, to_node in enumerate(range(from_node, from_node + 4)):
+ to_node %= 4
+ change = False
+ if not multisig:
+ if from_node == to_node:
+ # When sending non-multisig to self, use getrawchangeaddress
+ address = self.nodes[to_node].getrawchangeaddress(address_type=address_type)
+ change = True
+ else:
+ address = self.nodes[to_node].getnewaddress(address_type=address_type)
+ else:
+ addr1 = self.nodes[to_node].getnewaddress()
+ addr2 = self.nodes[to_node].getnewaddress()
+ address = self.nodes[to_node].addmultisigaddress(2, [addr1, addr2])['address']
+
+ # Do some sanity checking on the created address
+ if address_type is not None:
+ typ = address_type
+ elif to_node == 0:
+ typ = 'legacy'
+ elif to_node == 1 or (to_node == 2 and not change):
+ typ = 'p2sh-segwit'
+ else:
+ typ = 'bech32'
+ self.test_address(to_node, address, multisig, typ)
+
+ # Output entry
+ sends[address] = to_send * 10 * (1 + n)
+
+ self.log.debug("Sending: {}".format(sends))
+ self.nodes[from_node].sendmany("", sends)
+ sync_mempools(self.nodes)
+
+ unconf_balances = self.get_balances(False)
+ self.log.debug("Check unconfirmed balances: {}".format(unconf_balances))
+ assert_equal(unconf_balances[from_node], 0)
+ for n, to_node in enumerate(range(from_node + 1, from_node + 4)):
+ to_node %= 4
+ assert_equal(unconf_balances[to_node], to_send * 10 * (2 + n))
+
+ # node5 collects fee and block subsidy to keep accounting simple
+ self.nodes[5].generate(1)
+ sync_blocks(self.nodes)
+
+ new_balances = self.get_balances()
+ self.log.debug("Check new balances: {}".format(new_balances))
+ # We don't know what fee was set, so we can only check bounds on the balance of the sending node
+ assert_greater_than(new_balances[from_node], to_send * 10)
+ assert_greater_than(to_send * 11, new_balances[from_node])
+ for n, to_node in enumerate(range(from_node + 1, from_node + 4)):
+ to_node %= 4
+ assert_equal(new_balances[to_node], old_balances[to_node] + to_send * 10 * (2 + n))
+
+ # Get one p2sh/segwit address from node2 and two bech32 addresses from node3:
+ to_address_p2sh = self.nodes[2].getnewaddress()
+ to_address_bech32_1 = self.nodes[3].getnewaddress()
+ to_address_bech32_2 = self.nodes[3].getnewaddress()
+
+ # Fund node 4:
+ self.nodes[5].sendtoaddress(self.nodes[4].getnewaddress(), Decimal("1"))
+ self.nodes[5].generate(1)
+ sync_blocks(self.nodes)
+ assert_equal(self.nodes[4].getbalance(), 1)
+
+ self.log.info("Nodes with addresstype=legacy never use a P2WPKH change output")
+ self.test_change_output_type(0, [to_address_bech32_1], 'legacy')
+
+ self.log.info("Nodes with addresstype=p2sh-segwit only use a P2WPKH change output if any destination address is bech32:")
+ self.test_change_output_type(1, [to_address_p2sh], 'p2sh-segwit')
+ self.test_change_output_type(1, [to_address_bech32_1], 'bech32')
+ self.test_change_output_type(1, [to_address_p2sh, to_address_bech32_1], 'bech32')
+ self.test_change_output_type(1, [to_address_bech32_1, to_address_bech32_2], 'bech32')
+
+ self.log.info("Nodes with change_type=bech32 always use a P2WPKH change output:")
+ self.test_change_output_type(2, [to_address_bech32_1], 'bech32')
+ self.test_change_output_type(2, [to_address_p2sh], 'bech32')
+
+ self.log.info("Nodes with addresstype=bech32 always use a P2WPKH change output (unless changetype is set otherwise):")
+ self.test_change_output_type(3, [to_address_bech32_1], 'bech32')
+ self.test_change_output_type(3, [to_address_p2sh], 'bech32')
+
+ 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')
+ 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")
+ self.test_change_output_type(4, [to_address_bech32_1], 'p2sh-segwit')
+ self.test_address(4, self.nodes[4].getrawchangeaddress(), multisig=False, typ='p2sh-segwit')
+ self.log.info("Except for getrawchangeaddress if specified:")
+ self.test_address(4, self.nodes[4].getrawchangeaddress(), multisig=False, typ='p2sh-segwit')
+ self.test_address(4, self.nodes[4].getrawchangeaddress('bech32'), multisig=False, typ='bech32')
+
+if __name__ == '__main__':
+ AddressTypeTest().main()
diff --git a/test/functional/walletbackup.py b/test/functional/wallet_backup.py
index 8ef5620cd8..b4be7debb5 100755
--- a/test/functional/walletbackup.py
+++ b/test/functional/wallet_backup.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 the wallet backup features.
diff --git a/test/functional/wallet.py b/test/functional/wallet_basic.py
index db60df18ed..a90dbc8adf 100755
--- a/test/functional/wallet.py
+++ b/test/functional/wallet_basic.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 the wallet."""
@@ -27,6 +27,9 @@ class WalletTest(BitcoinTestFramework):
assert_fee_amount(fee, tx_size, fee_per_byte * 1000)
return curr_balance
+ def get_vsize(self, txn):
+ return self.nodes[0].decoderawtransaction(txn)['vsize']
+
def run_test(self):
# Check that there's no UTXO on none of the nodes
assert_equal(len(self.nodes[0].listunspent()), 0)
@@ -162,7 +165,7 @@ class WalletTest(BitcoinTestFramework):
txid = self.nodes[2].sendtoaddress(address, 10, "", "", False)
self.nodes[2].generate(1)
self.sync_all([self.nodes[0:3]])
- node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), Decimal('84'), fee_per_byte, count_bytes(self.nodes[2].getrawtransaction(txid)))
+ node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), Decimal('84'), fee_per_byte, self.get_vsize(self.nodes[2].getrawtransaction(txid)))
assert_equal(self.nodes[0].getbalance(), Decimal('10'))
# Send 10 BTC with subtract fee from amount
@@ -171,14 +174,14 @@ class WalletTest(BitcoinTestFramework):
self.sync_all([self.nodes[0:3]])
node_2_bal -= Decimal('10')
assert_equal(self.nodes[2].getbalance(), node_2_bal)
- node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), Decimal('20'), fee_per_byte, count_bytes(self.nodes[2].getrawtransaction(txid)))
+ 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, "", [])
self.nodes[2].generate(1)
self.sync_all([self.nodes[0:3]])
node_0_bal += Decimal('10')
- node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), node_2_bal - Decimal('10'), fee_per_byte, count_bytes(self.nodes[2].getrawtransaction(txid)))
+ node_2_bal = self.check_fee_amount(self.nodes[2].getbalance(), node_2_bal - Decimal('10'), fee_per_byte, self.get_vsize(self.nodes[2].getrawtransaction(txid)))
assert_equal(self.nodes[0].getbalance(), node_0_bal)
# Sendmany 10 BTC with subtract fee from amount
@@ -187,7 +190,7 @@ class WalletTest(BitcoinTestFramework):
self.sync_all([self.nodes[0:3]])
node_2_bal -= Decimal('10')
assert_equal(self.nodes[2].getbalance(), node_2_bal)
- node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), node_0_bal + Decimal('10'), fee_per_byte, count_bytes(self.nodes[2].getrawtransaction(txid)))
+ node_0_bal = self.check_fee_amount(self.nodes[0].getbalance(), node_0_bal + Decimal('10'), fee_per_byte, self.get_vsize(self.nodes[2].getrawtransaction(txid)))
# Test ResendWalletTransactions:
# Create a couple of transactions, then start up a fourth
diff --git a/test/functional/bumpfee.py b/test/functional/wallet_bumpfee.py
index 008e83d5b2..f621d41b4e 100755
--- a/test/functional/bumpfee.py
+++ b/test/functional/wallet_bumpfee.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2016 The Bitcoin Core developers
+# Copyright (c) 2016-2017 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 the bumpfee RPC.
@@ -14,7 +14,7 @@ added in the future, they should try to follow the same convention and not
make assumptions about execution order.
"""
-from segwit import send_to_witness
+from test_framework.blocktools import send_to_witness
from test_framework.test_framework import BitcoinTestFramework
from test_framework import blocktools
from test_framework.mininode import CTransaction
@@ -33,7 +33,7 @@ class BumpFeeTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
self.setup_clean_chain = True
- self.extra_args = [["-prematurewitness", "-walletprematurewitness", "-walletrbf={}".format(i)]
+ self.extra_args = [["-prematurewitness", "-walletprematurewitness", "-deprecatedrpc=addwitnessaddress", "-walletrbf={}".format(i)]
for i in range(self.num_nodes)]
def run_test(self):
@@ -194,7 +194,7 @@ def test_settxfee(rbf_node, dest_address):
requested_feerate = Decimal("0.00025000")
rbf_node.settxfee(requested_feerate)
bumped_tx = rbf_node.bumpfee(rbfid)
- actual_feerate = bumped_tx["fee"] * 1000 / rbf_node.getrawtransaction(bumped_tx["txid"], True)["size"]
+ actual_feerate = bumped_tx["fee"] * 1000 / rbf_node.getrawtransaction(bumped_tx["txid"], True)["vsize"]
# Assert that the difference between the requested feerate and the actual
# feerate of the bumped transaction is small.
assert_greater_than(Decimal("0.00001000"), abs(requested_feerate - actual_feerate))
@@ -231,13 +231,16 @@ def test_unconfirmed_not_spendable(rbf_node, rbf_node_address):
assert_equal([t for t in rbf_node.listunspent(minconf=0, include_unsafe=False) if t["txid"] == bumpid], [])
# submit a block with the rbf tx to clear the bump tx out of the mempool,
- # then call abandon to make sure the wallet doesn't attempt to resubmit the
- # bump tx, then invalidate the block so the rbf tx will be put back in the
- # mempool. this makes it possible to check whether the rbf tx outputs are
+ # then invalidate the block so the rbf tx will be put back in the mempool.
+ # This makes it possible to check whether the rbf tx outputs are
# spendable before the rbf tx is confirmed.
block = submit_block_with_tx(rbf_node, rbftx)
- rbf_node.abandontransaction(bumpid)
+ # Can not abandon conflicted tx
+ assert_raises_rpc_error(-5, 'Transaction not eligible for abandonment', lambda: rbf_node.abandontransaction(txid=bumpid))
rbf_node.invalidateblock(block.hash)
+ # Call abandon to make sure the wallet doesn't attempt to resubmit
+ # the bump tx and hope the wallet does not rebroadcast before we call.
+ rbf_node.abandontransaction(bumpid)
assert bumpid not in rbf_node.getrawmempool()
assert rbfid in rbf_node.getrawmempool()
@@ -290,6 +293,7 @@ def submit_block_with_tx(node, tx):
block.vtx.append(ctx)
block.rehash()
block.hashMerkleRoot = block.calc_merkle_root()
+ blocktools.add_witness_commitment(block)
block.solve()
node.submitblock(bytes_to_hex_str(block.serialize(True)))
return block
diff --git a/test/functional/disablewallet.py b/test/functional/wallet_disable.py
index c75ef9b9f1..b0627d88ac 100755
--- a/test/functional/disablewallet.py
+++ b/test/functional/wallet_disable.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2016 The Bitcoin Core developers
+# Copyright (c) 2015-2017 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 a node with the -disablewallet option.
diff --git a/test/functional/wallet-dump.py b/test/functional/wallet_dump.py
index 47de8777a6..5e943d048d 100755
--- a/test/functional/wallet-dump.py
+++ b/test/functional/wallet_dump.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2016 The Bitcoin Core developers
+# Copyright (c) 2016-2017 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 the dumpwallet RPC."""
@@ -10,15 +10,17 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (assert_equal, assert_raises_rpc_error)
-def read_dump(file_name, addrs, hd_master_addr_old):
+def read_dump(file_name, addrs, script_addrs, hd_master_addr_old):
"""
Read the given dump, count the addrs that match, count change and reserve.
Also check that the old hd_master is inactive
"""
with open(file_name, encoding='utf8') as inputfile:
found_addr = 0
+ found_script_addr = 0
found_addr_chg = 0
found_addr_rsv = 0
+ witness_addr_ret = None
hd_master_addr_ret = None
for line in inputfile:
# only read non comment lines
@@ -38,12 +40,22 @@ def read_dump(file_name, addrs, hd_master_addr_old):
# ensure we have generated a new hd master key
assert(hd_master_addr_old != addr)
hd_master_addr_ret = addr
+ elif keytype == "script=1":
+ # scripts don't have keypaths
+ keypath = None
else:
keypath = addr_keypath.rstrip().split("hdkeypath=")[1]
# count key types
for addrObj in addrs:
- if addrObj['address'] == addr and addrObj['hdkeypath'] == keypath and keytype == "label=":
+ if addrObj['address'] == addr.split(",")[0] and addrObj['hdkeypath'] == keypath and keytype == "label=":
+ # a labled entry in the wallet should contain both a native address
+ # and the p2sh-p2wpkh address that was added at wallet setup
+ if len(addr.split(",")) == 2:
+ addr_list = addr.split(",")
+ # the entry should be of the first key in the wallet
+ assert_equal(addrs[0]['address'], addr_list[0])
+ witness_addr_ret = addr_list[1]
found_addr += 1
break
elif keytype == "change=1":
@@ -52,13 +64,20 @@ def read_dump(file_name, addrs, hd_master_addr_old):
elif keytype == "reserve=1":
found_addr_rsv += 1
break
- return found_addr, found_addr_chg, found_addr_rsv, hd_master_addr_ret
+
+ # count scripts
+ for script_addr in script_addrs:
+ if script_addr == addr.rstrip() and keytype == "script=1":
+ found_script_addr += 1
+ break
+
+ return found_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_ret, witness_addr_ret
class WalletDumpTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
- self.extra_args = [["-keypool=90"]]
+ self.extra_args = [["-keypool=90", "-addresstype=legacy", "-deprecatedrpc=addwitnessaddress"]]
def setup_network(self, split=False):
# Use 1 minute timeout because the initial getnewaddress RPC can take
@@ -72,6 +91,8 @@ class WalletDumpTest(BitcoinTestFramework):
tmpdir = self.options.tmpdir
# generate 20 addresses to compare against the dump
+ # but since we add a p2sh-p2wpkh address for the first pubkey in the
+ # wallet, we will expect 21 addresses in the dump
test_addr_count = 20
addrs = []
for i in range(0,test_addr_count):
@@ -81,15 +102,22 @@ class WalletDumpTest(BitcoinTestFramework):
# Should be a no-op:
self.nodes[0].keypoolrefill()
+ # Test scripts dump by adding a P2SH witness and a 1-of-1 multisig address
+ witness_addr = self.nodes[0].addwitnessaddress(addrs[0]["address"], True)
+ multisig_addr = self.nodes[0].addmultisigaddress(1, [addrs[1]["address"]])["address"]
+ script_addrs = [witness_addr, multisig_addr]
+
# dump unencrypted wallet
result = self.nodes[0].dumpwallet(tmpdir + "/node0/wallet.unencrypted.dump")
assert_equal(result['filename'], os.path.abspath(tmpdir + "/node0/wallet.unencrypted.dump"))
- found_addr, found_addr_chg, found_addr_rsv, hd_master_addr_unenc = \
- read_dump(tmpdir + "/node0/wallet.unencrypted.dump", addrs, None)
+ found_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_unenc, witness_addr_ret = \
+ read_dump(tmpdir + "/node0/wallet.unencrypted.dump", addrs, script_addrs, None)
assert_equal(found_addr, test_addr_count) # all keys must be in the dump
+ assert_equal(found_script_addr, 2) # all scripts must be in the dump
assert_equal(found_addr_chg, 50) # 50 blocks where mined
assert_equal(found_addr_rsv, 90*2) # 90 keys plus 100% internal keys
+ assert_equal(witness_addr_ret, witness_addr) # p2sh-p2wsh address added to the first key
#encrypt wallet, restart, unlock and dump
self.nodes[0].node_encrypt_wallet('test')
@@ -99,14 +127,30 @@ class WalletDumpTest(BitcoinTestFramework):
self.nodes[0].keypoolrefill()
self.nodes[0].dumpwallet(tmpdir + "/node0/wallet.encrypted.dump")
- found_addr, found_addr_chg, found_addr_rsv, _ = \
- read_dump(tmpdir + "/node0/wallet.encrypted.dump", addrs, hd_master_addr_unenc)
+ found_addr, found_script_addr, found_addr_chg, found_addr_rsv, _, witness_addr_ret = \
+ read_dump(tmpdir + "/node0/wallet.encrypted.dump", addrs, script_addrs, hd_master_addr_unenc)
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(witness_addr_ret, witness_addr)
# Overwriting should fail
assert_raises_rpc_error(-8, "already exists", self.nodes[0].dumpwallet, tmpdir + "/node0/wallet.unencrypted.dump")
+ # Restart node with new wallet, and test importwallet
+ self.stop_node(0)
+ self.start_node(0, ['-wallet=w2'])
+
+ # Make sure the address is not IsMine before import
+ result = self.nodes[0].validateaddress(multisig_addr)
+ assert(result['ismine'] == False)
+
+ self.nodes[0].importwallet(os.path.abspath(tmpdir + "/node0/wallet.unencrypted.dump"))
+
+ # Now check IsMine is true
+ result = self.nodes[0].validateaddress(multisig_addr)
+ assert(result['ismine'] == True)
+
if __name__ == '__main__':
WalletDumpTest().main ()
diff --git a/test/functional/wallet-encryption.py b/test/functional/wallet_encryption.py
index db62e1e30f..3c927ee484 100755
--- a/test/functional/wallet-encryption.py
+++ b/test/functional/wallet_encryption.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2016 The Bitcoin Core developers
+# Copyright (c) 2016-2017 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 Wallet encryption"""
@@ -10,6 +10,8 @@ from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
assert_raises_rpc_error,
+ assert_greater_than,
+ assert_greater_than_or_equal,
)
class WalletEncryptionTest(BitcoinTestFramework):
@@ -56,6 +58,23 @@ class WalletEncryptionTest(BitcoinTestFramework):
assert_raises_rpc_error(-14, "wallet passphrase entered was incorrect", self.nodes[0].walletpassphrase, passphrase, 10)
self.nodes[0].walletpassphrase(passphrase2, 10)
assert_equal(privkey, self.nodes[0].dumpprivkey(address))
+ self.nodes[0].walletlock()
+
+ # Test timeout bounds
+ assert_raises_rpc_error(-8, "Timeout cannot be negative.", self.nodes[0].walletpassphrase, passphrase2, -10)
+ # Check the timeout
+ # Check a time less than the limit
+ expected_time = int(time.time()) + (1 << 30) - 600
+ self.nodes[0].walletpassphrase(passphrase2, (1 << 30) - 600)
+ actual_time = self.nodes[0].getwalletinfo()['unlocked_until']
+ assert_greater_than_or_equal(actual_time, expected_time)
+ assert_greater_than(expected_time + 5, actual_time) # 5 second buffer
+ # Check a time greater than the limit
+ expected_time = int(time.time()) + (1 << 30) - 1
+ self.nodes[0].walletpassphrase(passphrase2, (1 << 33))
+ actual_time = self.nodes[0].getwalletinfo()['unlocked_until']
+ assert_greater_than_or_equal(actual_time, expected_time)
+ assert_greater_than(expected_time + 5, actual_time) # 5 second buffer
if __name__ == '__main__':
WalletEncryptionTest().main()
diff --git a/test/functional/wallet-hd.py b/test/functional/wallet_hd.py
index d21656a971..9f0e9acb47 100755
--- a/test/functional/wallet-hd.py
+++ b/test/functional/wallet_hd.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2016 The Bitcoin Core developers
+# Copyright (c) 2016-2017 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 Hierarchical Deterministic wallet function."""
diff --git a/test/functional/import-rescan.py b/test/functional/wallet_import_rescan.py
index 6807fa6696..d193a99d5b 100755
--- a/test/functional/import-rescan.py
+++ b/test/functional/wallet_import_rescan.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 wallet import RPCs.
@@ -119,7 +119,7 @@ class ImportRescanTest(BitcoinTestFramework):
self.num_nodes = 2 + len(IMPORT_NODES)
def setup_network(self):
- extra_args = [[] for _ in range(self.num_nodes)]
+ extra_args = [["-addresstype=legacy"] for _ in range(self.num_nodes)]
for i, import_node in enumerate(IMPORT_NODES, 2):
if import_node.prune:
extra_args[i] += ["-prune=1"]
diff --git a/test/functional/importmulti.py b/test/functional/wallet_importmulti.py
index a691595f15..be9be83839 100755
--- a/test/functional/importmulti.py
+++ b/test/functional/wallet_importmulti.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 the importmulti RPC."""
@@ -9,6 +9,7 @@ from test_framework.util import *
class ImportMultiTest (BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
+ self.extra_args = [["-addresstype=legacy"], ["-addresstype=legacy"]]
self.setup_clean_chain = True
def setup_network(self):
@@ -227,7 +228,7 @@ class ImportMultiTest (BitcoinTestFramework):
sig_address_1 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
sig_address_2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
sig_address_3 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
- multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['address'], sig_address_2['address'], sig_address_3['pubkey']])
+ multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']])
self.nodes[1].generate(100)
transactionid = self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00)
self.nodes[1].generate(1)
@@ -254,7 +255,7 @@ class ImportMultiTest (BitcoinTestFramework):
sig_address_1 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
sig_address_2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
sig_address_3 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
- multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['address'], sig_address_2['address'], sig_address_3['pubkey']])
+ multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']])
self.nodes[1].generate(100)
transactionid = self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00)
self.nodes[1].generate(1)
@@ -281,7 +282,7 @@ class ImportMultiTest (BitcoinTestFramework):
sig_address_1 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
sig_address_2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
sig_address_3 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
- multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['address'], sig_address_2['address'], sig_address_3['pubkey']])
+ multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']])
self.nodes[1].generate(100)
transactionid = self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00)
self.nodes[1].generate(1)
@@ -308,7 +309,7 @@ class ImportMultiTest (BitcoinTestFramework):
sig_address_1 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
sig_address_2 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
sig_address_3 = self.nodes[0].validateaddress(self.nodes[0].getnewaddress())
- multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['address'], sig_address_2['address'], sig_address_3['pubkey']])
+ multi_sig_script = self.nodes[0].createmultisig(2, [sig_address_1['pubkey'], sig_address_2['pubkey'], sig_address_3['pubkey']])
self.nodes[1].generate(100)
transactionid = self.nodes[1].sendtoaddress(multi_sig_script['address'], 10.00)
self.nodes[1].generate(1)
diff --git a/test/functional/importprunedfunds.py b/test/functional/wallet_importprunedfunds.py
index 068052409a..6b2919b5ae 100755
--- a/test/functional/importprunedfunds.py
+++ b/test/functional/wallet_importprunedfunds.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 the importprunedfunds and removeprunedfunds RPCs."""
diff --git a/test/functional/keypool.py b/test/functional/wallet_keypool.py
index f2701c36bd..45a5eed8ec 100755
--- a/test/functional/keypool.py
+++ b/test/functional/wallet_keypool.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 the wallet keypool and interaction with wallet encryption/locking."""
diff --git a/test/functional/keypool-topup.py b/test/functional/wallet_keypool_topup.py
index e7af3c3987..e7af3c3987 100755
--- a/test/functional/keypool-topup.py
+++ b/test/functional/wallet_keypool_topup.py
diff --git a/test/functional/receivedby.py b/test/functional/wallet_listreceivedby.py
index 97da19546f..1f2b3c8aa7 100755
--- a/test/functional/receivedby.py
+++ b/test/functional/wallet_listreceivedby.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 the listreceivedbyaddress RPC."""
diff --git a/test/functional/listsinceblock.py b/test/functional/wallet_listsinceblock.py
index 67e7744bf8..67e7744bf8 100755
--- a/test/functional/listsinceblock.py
+++ b/test/functional/wallet_listsinceblock.py
diff --git a/test/functional/multiwallet.py b/test/functional/wallet_multiwallet.py
index 06409b6f31..b07e451667 100755
--- a/test/functional/multiwallet.py
+++ b/test/functional/wallet_multiwallet.py
@@ -15,59 +15,75 @@ from test_framework.util import assert_equal, assert_raises_rpc_error
class MultiWalletTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
- self.num_nodes = 1
- self.extra_args = [['-wallet=w1', '-wallet=w2', '-wallet=w3', '-wallet=w']]
+ self.num_nodes = 2
+ self.extra_args = [['-wallet=w1', '-wallet=w2', '-wallet=w3', '-wallet=w'], []]
+ self.supports_cli = True
def run_test(self):
- assert_equal(set(self.nodes[0].listwallets()), {"w1", "w2", "w3", "w"})
+ node = self.nodes[0]
- self.stop_node(0)
+ data_dir = lambda *p: os.path.join(node.datadir, 'regtest', *p)
+ wallet_dir = lambda *p: data_dir('wallets', *p)
+ wallet = lambda name: node.get_wallet_rpc(name)
+
+ assert_equal(set(node.listwallets()), {"w1", "w2", "w3", "w"})
+
+ self.stop_nodes()
+
+ self.assert_start_raises_init_error(0, ['-walletdir=wallets'], 'Error: Specified -walletdir "wallets" does not exist')
+ self.assert_start_raises_init_error(0, ['-walletdir=wallets'], 'Error: Specified -walletdir "wallets" is a relative path', cwd=data_dir())
+ self.assert_start_raises_init_error(0, ['-walletdir=debug.log'], 'Error: Specified -walletdir "debug.log" is not a directory', cwd=data_dir())
# should not initialize if there are duplicate wallets
self.assert_start_raises_init_error(0, ['-wallet=w1', '-wallet=w1'], 'Error loading wallet w1. Duplicate -wallet filename specified.')
# should not initialize if wallet file is a directory
- wallet_dir = os.path.join(self.options.tmpdir, 'node0', 'regtest', 'wallets')
- os.mkdir(os.path.join(wallet_dir, 'w11'))
+ os.mkdir(wallet_dir('w11'))
self.assert_start_raises_init_error(0, ['-wallet=w11'], 'Error loading wallet w11. -wallet filename must be a regular file.')
# should not initialize if one wallet is a copy of another
- shutil.copyfile(os.path.join(wallet_dir, 'w2'), os.path.join(wallet_dir, 'w22'))
+ shutil.copyfile(wallet_dir('w2'), wallet_dir('w22'))
self.assert_start_raises_init_error(0, ['-wallet=w2', '-wallet=w22'], 'duplicates fileid')
# should not initialize if wallet file is a symlink
- os.symlink(os.path.join(wallet_dir, 'w1'), os.path.join(wallet_dir, 'w12'))
+ os.symlink(wallet_dir('w1'), wallet_dir('w12'))
self.assert_start_raises_init_error(0, ['-wallet=w12'], 'Error loading wallet w12. -wallet filename must be a regular file.')
# should not initialize if the specified walletdir does not exist
- self.assert_start_raises_init_error(0, ['-walletdir=bad'], 'Error: Specified wallet directory "bad" does not exist.')
+ self.assert_start_raises_init_error(0, ['-walletdir=bad'], 'Error: Specified -walletdir "bad" does not exist')
+ # should not initialize if the specified walletdir is not a directory
+ not_a_dir = wallet_dir('notadir')
+ open(not_a_dir, 'a').close()
+ self.assert_start_raises_init_error(0, ['-walletdir=' + not_a_dir], 'Error: Specified -walletdir "' + not_a_dir + '" is not a directory')
# if wallets/ doesn't exist, datadir should be the default wallet dir
- wallet_dir2 = os.path.join(self.options.tmpdir, 'node0', 'regtest', 'walletdir')
- os.rename(wallet_dir, wallet_dir2)
+ wallet_dir2 = data_dir('walletdir')
+ os.rename(wallet_dir(), wallet_dir2)
self.start_node(0, ['-wallet=w4', '-wallet=w5'])
- assert_equal(set(self.nodes[0].listwallets()), {"w4", "w5"})
- w5 = self.nodes[0].get_wallet_rpc("w5")
+ assert_equal(set(node.listwallets()), {"w4", "w5"})
+ w5 = wallet("w5")
w5.generate(1)
- self.stop_node(0)
# now if wallets/ exists again, but the rootdir is specified as the walletdir, w4 and w5 should still be loaded
- os.rename(wallet_dir2, wallet_dir)
- self.start_node(0, ['-wallet=w4', '-wallet=w5', '-walletdir=' + os.path.join(self.options.tmpdir, 'node0', 'regtest')])
- assert_equal(set(self.nodes[0].listwallets()), {"w4", "w5"})
- w5 = self.nodes[0].get_wallet_rpc("w5")
+ os.rename(wallet_dir2, wallet_dir())
+ self.restart_node(0, ['-wallet=w4', '-wallet=w5', '-walletdir=' + data_dir()])
+ assert_equal(set(node.listwallets()), {"w4", "w5"})
+ w5 = wallet("w5")
w5_info = w5.getwalletinfo()
assert_equal(w5_info['immature_balance'], 50)
- self.stop_node(0)
+ competing_wallet_dir = os.path.join(self.options.tmpdir, 'competing_walletdir')
+ os.mkdir(competing_wallet_dir)
+ self.restart_node(0, ['-walletdir='+competing_wallet_dir])
+ self.assert_start_raises_init_error(1, ['-walletdir='+competing_wallet_dir], 'Error initializing wallet database environment')
- self.start_node(0, self.extra_args[0])
+ self.restart_node(0, self.extra_args[0])
- w1 = self.nodes[0].get_wallet_rpc("w1")
- w2 = self.nodes[0].get_wallet_rpc("w2")
- w3 = self.nodes[0].get_wallet_rpc("w3")
- w4 = self.nodes[0].get_wallet_rpc("w")
- wallet_bad = self.nodes[0].get_wallet_rpc("bad")
+ w1 = wallet("w1")
+ w2 = wallet("w2")
+ w3 = wallet("w3")
+ w4 = wallet("w")
+ wallet_bad = wallet("bad")
w1.generate(1)
@@ -75,7 +91,7 @@ class MultiWalletTest(BitcoinTestFramework):
assert_raises_rpc_error(-18, "Requested wallet does not exist or is not loaded", wallet_bad.getwalletinfo)
# accessing wallet RPC without using wallet endpoint fails
- assert_raises_rpc_error(-19, "Wallet file not specified", self.nodes[0].getwalletinfo)
+ assert_raises_rpc_error(-19, "Wallet file not specified", node.getwalletinfo)
# check w1 wallet balance
w1_info = w1.getwalletinfo()
diff --git a/test/functional/resendwallettransactions.py b/test/functional/wallet_resendwallettransactions.py
index d959bb4c38..d959bb4c38 100755
--- a/test/functional/resendwallettransactions.py
+++ b/test/functional/wallet_resendwallettransactions.py
diff --git a/test/functional/txn_clone.py b/test/functional/wallet_txn_clone.py
index 740bb2d4c5..ce26d6e0ee 100755
--- a/test/functional/txn_clone.py
+++ b/test/functional/wallet_txn_clone.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 the wallet accounts properly when there are cloned transactions with malleated scriptsigs."""
@@ -14,6 +14,8 @@ class TxnMallTest(BitcoinTestFramework):
def add_options(self, parser):
parser.add_option("--mineblock", dest="mine_block", default=False, action="store_true",
help="Test double-spend of 1-confirmed transaction")
+ parser.add_option("--segwit", dest="segwit", default=False, action="store_true",
+ help="Test behaviour with SegWit txn (which should fail")
def setup_network(self):
# Start with split network:
@@ -22,6 +24,11 @@ class TxnMallTest(BitcoinTestFramework):
disconnect_nodes(self.nodes[2], 1)
def run_test(self):
+ if self.options.segwit:
+ output_type="p2sh-segwit"
+ else:
+ output_type="legacy"
+
# All nodes should start with 1,250 BTC:
starting_balance = 1250
for i in range(4):
@@ -31,11 +38,11 @@ class TxnMallTest(BitcoinTestFramework):
# Assign coins to foo and bar accounts:
self.nodes[0].settxfee(.001)
- node0_address_foo = self.nodes[0].getnewaddress("foo")
+ 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_address_bar = self.nodes[0].getnewaddress("bar")
+ 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)
@@ -106,6 +113,10 @@ class TxnMallTest(BitcoinTestFramework):
# Send clone and its parent to miner
self.nodes[2].sendrawtransaction(fund_foo_tx["hex"])
txid1_clone = self.nodes[2].sendrawtransaction(tx1_clone["hex"])
+ if self.options.segwit:
+ assert_equal(txid1, txid1_clone)
+ return
+
# ... mine a block...
self.nodes[2].generate(1)
diff --git a/test/functional/txn_doublespend.py b/test/functional/wallet_txn_doublespend.py
index 69629ef951..01129f3817 100755
--- a/test/functional/txn_doublespend.py
+++ b/test/functional/wallet_txn_doublespend.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 the wallet accounts properly when there is a double-spend conflict."""
diff --git a/test/functional/zapwallettxes.py b/test/functional/wallet_zapwallettxes.py
index 8cd622dc8e..87f44b2737 100755
--- a/test/functional/zapwallettxes.py
+++ b/test/functional/wallet_zapwallettxes.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2014-2016 The Bitcoin Core developers
+# Copyright (c) 2014-2017 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 the zapwallettxes functionality.
@@ -10,7 +10,7 @@
transactions are still available.
- restart node 0 with zapwallettxes and persistmempool, and verify that both
the confirmed and the unconfirmed transactions are still available.
-- restart node 0 with just zapwallettxed and verify that the confirmed
+- restart node 0 with just zapwallettxes and verify that the confirmed
transactions are still available, but that the unconfirmed transaction has
been zapped.
"""
@@ -59,6 +59,7 @@ class ZapWalletTXesTest (BitcoinTestFramework):
self.start_node(0, ["-persistmempool=1", "-zapwallettxes=2"])
wait_until(lambda: self.nodes[0].getmempoolinfo()['size'] == 1, timeout=3)
+ self.nodes[0].syncwithvalidationinterfacequeue() # Flush mempool to wallet
assert_equal(self.nodes[0].gettransaction(txid1)['txid'], txid1)
assert_equal(self.nodes[0].gettransaction(txid2)['txid'], txid2)