aboutsummaryrefslogtreecommitdiff
path: root/test/functional
diff options
context:
space:
mode:
Diffstat (limited to 'test/functional')
-rw-r--r--test/functional/README.md4
-rwxr-xr-xtest/functional/deprecated_rpc.py23
-rwxr-xr-xtest/functional/feature_assumevalid.py (renamed from test/functional/assumevalid.py)0
-rwxr-xr-xtest/functional/feature_bip68_sequence.py (renamed from test/functional/bip68-sequence.py)0
-rwxr-xr-xtest/functional/feature_bip9_softforks.py (renamed from test/functional/bip9-softforks.py)0
-rwxr-xr-xtest/functional/feature_block.py (renamed from test/functional/p2p-fullblocktest.py)0
-rwxr-xr-xtest/functional/feature_cltv.py (renamed from test/functional/bip65-cltv-p2p.py)0
-rwxr-xr-xtest/functional/feature_config_args.py (renamed from test/functional/conf_args.py)0
-rwxr-xr-xtest/functional/feature_csv_activation.py (renamed from test/functional/bip68-112-113-p2p.py)0
-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)0
-rwxr-xr-xtest/functional/feature_fee_estimation.py (renamed from test/functional/smartfees.py)161
-rwxr-xr-xtest/functional/feature_maxuploadtarget.py (renamed from test/functional/maxuploadtarget.py)0
-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)0
-rwxr-xr-xtest/functional/feature_nulldummy.py (renamed from test/functional/nulldummy.py)8
-rwxr-xr-xtest/functional/feature_proxy.py (renamed from test/functional/proxy_test.py)0
-rwxr-xr-xtest/functional/feature_pruning.py (renamed from test/functional/pruning.py)0
-rwxr-xr-xtest/functional/feature_rbf.py (renamed from test/functional/replace-by-fee.py)0
-rwxr-xr-xtest/functional/feature_reindex.py (renamed from test/functional/reindex.py)0
-rwxr-xr-xtest/functional/feature_segwit.py (renamed from test/functional/segwit.py)51
-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)0
-rwxr-xr-xtest/functional/interface_rest.py (renamed from test/functional/rest.py)0
-rwxr-xr-xtest/functional/interface_zmq.py (renamed from test/functional/zmq_test.py)0
-rwxr-xr-xtest/functional/invalidtxrequest.py73
-rwxr-xr-xtest/functional/mempool_limit.py10
-rwxr-xr-xtest/functional/mempool_persist.py9
-rwxr-xr-xtest/functional/mempool_resurrect.py (renamed from test/functional/mempool_resurrect_test.py)0
-rwxr-xr-xtest/functional/mempool_spend_coinbase.py (renamed from test/functional/mempool_spendcoinbase.py)0
-rwxr-xr-xtest/functional/mining_basic.py (renamed from test/functional/mining.py)0
-rwxr-xr-xtest/functional/mining_getblocktemplate_longpoll.py (renamed from test/functional/getblocktemplate_longpoll.py)0
-rwxr-xr-xtest/functional/mining_prioritisetransaction.py (renamed from test/functional/prioritise_transaction.py)2
-rwxr-xr-xtest/functional/p2p-versionbits-warning.py121
-rwxr-xr-xtest/functional/p2p_compactblocks.py (renamed from test/functional/p2p-compactblocks.py)2
-rwxr-xr-xtest/functional/p2p_disconnect_ban.py (renamed from test/functional/disconnect_ban.py)0
-rwxr-xr-xtest/functional/p2p_feefilter.py (renamed from test/functional/p2p-feefilter.py)0
-rwxr-xr-xtest/functional/p2p_fingerprint.py (renamed from test/functional/p2p-fingerprint.py)2
-rwxr-xr-xtest/functional/p2p_invalid_block.py (renamed from test/functional/invalidblockrequest.py)0
-rwxr-xr-xtest/functional/p2p_invalid_tx.py55
-rwxr-xr-xtest/functional/p2p_leak.py (renamed from test/functional/p2p-leaktests.py)0
-rwxr-xr-xtest/functional/p2p_mempool.py (renamed from test/functional/p2p-mempool.py)0
-rwxr-xr-xtest/functional/p2p_node_network_limited.py (renamed from test/functional/node_network_limited.py)0
-rwxr-xr-xtest/functional/p2p_segwit.py (renamed from test/functional/p2p-segwit.py)0
-rwxr-xr-xtest/functional/p2p_sendheaders.py (renamed from test/functional/sendheaders.py)0
-rwxr-xr-xtest/functional/p2p_timeouts.py (renamed from test/functional/p2p-timeouts.py)0
-rwxr-xr-xtest/functional/p2p_unrequested_blocks.py (renamed from test/functional/p2p-acceptblock.py)0
-rwxr-xr-xtest/functional/rpc_bind.py (renamed from test/functional/rpcbind_test.py)0
-rwxr-xr-xtest/functional/rpc_blockchain.py (renamed from test/functional/blockchain.py)15
-rwxr-xr-xtest/functional/rpc_decodescript.py (renamed from test/functional/decodescript.py)0
-rwxr-xr-xtest/functional/rpc_deprecated.py27
-rwxr-xr-xtest/functional/rpc_fundrawtransaction.py (renamed from test/functional/fundrawtransaction.py)24
-rwxr-xr-xtest/functional/rpc_getchaintips.py (renamed from test/functional/getchaintips.py)0
-rwxr-xr-xtest/functional/rpc_invalidateblock.py (renamed from test/functional/invalidateblock.py)0
-rwxr-xr-xtest/functional/rpc_listtransactions.py (renamed from test/functional/listtransactions.py)3
-rwxr-xr-xtest/functional/rpc_named_arguments.py (renamed from test/functional/rpcnamedargs.py)0
-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)0
-rwxr-xr-xtest/functional/rpc_rawtransaction.py (renamed from test/functional/rawtransactions.py)19
-rwxr-xr-xtest/functional/rpc_signmessage.py (renamed from test/functional/signmessages.py)0
-rwxr-xr-xtest/functional/rpc_signrawtransaction.py (renamed from test/functional/signrawtransactions.py)0
-rwxr-xr-xtest/functional/rpc_txoutproof.py (renamed from test/functional/merkle_blocks.py)0
-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)0
-rw-r--r--test/functional/test_framework/messages.py7
-rwxr-xr-xtest/functional/test_framework/mininode.py155
-rwxr-xr-xtest/functional/test_framework/test_framework.py23
-rwxr-xr-xtest/functional/test_framework/test_node.py20
-rw-r--r--test/functional/test_framework/util.py5
-rwxr-xr-xtest/functional/test_runner.py204
-rwxr-xr-xtest/functional/wallet_abandonconflict.py (renamed from test/functional/abandonconflict.py)8
-rwxr-xr-xtest/functional/wallet_accounts.py (renamed from test/functional/wallet-accounts.py)2
-rwxr-xr-xtest/functional/wallet_address_types.py (renamed from test/functional/address_types.py)141
-rwxr-xr-xtest/functional/wallet_backup.py (renamed from test/functional/walletbackup.py)0
-rwxr-xr-xtest/functional/wallet_basic.py (renamed from test/functional/wallet.py)0
-rwxr-xr-xtest/functional/wallet_bumpfee.py (renamed from test/functional/bumpfee.py)13
-rwxr-xr-xtest/functional/wallet_disable.py (renamed from test/functional/disablewallet.py)0
-rwxr-xr-xtest/functional/wallet_dump.py (renamed from test/functional/wallet-dump.py)24
-rwxr-xr-xtest/functional/wallet_encryption.py (renamed from test/functional/wallet-encryption.py)19
-rwxr-xr-xtest/functional/wallet_hd.py (renamed from test/functional/wallet-hd.py)0
-rwxr-xr-xtest/functional/wallet_import_rescan.py (renamed from test/functional/import-rescan.py)0
-rwxr-xr-xtest/functional/wallet_importmulti.py (renamed from test/functional/importmulti.py)8
-rwxr-xr-xtest/functional/wallet_importprunedfunds.py (renamed from test/functional/importprunedfunds.py)0
-rwxr-xr-xtest/functional/wallet_keypool.py (renamed from test/functional/keypool.py)0
-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)0
-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)4
-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)0
-rwxr-xr-xtest/functional/wallet_txn_doublespend.py (renamed from test/functional/txn_doublespend.py)0
-rwxr-xr-xtest/functional/wallet_zapwallettxes.py (renamed from test/functional/zapwallettxes.py)3
94 files changed, 825 insertions, 536 deletions
diff --git a/test/functional/README.md b/test/functional/README.md
index d6ce490ab3..662b4b44d5 100644
--- a/test/functional/README.md
+++ b/test/functional/README.md
@@ -87,7 +87,7 @@ 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-acceptblock.py`, `p2p-compactblocks.py`.
+Examples tests are `p2p_unrequested_blocks.py`, `p2p_compactblocks.py`.
#### Comptool
@@ -133,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/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/assumevalid.py b/test/functional/feature_assumevalid.py
index 5a09142412..5a09142412 100755
--- a/test/functional/assumevalid.py
+++ b/test/functional/feature_assumevalid.py
diff --git a/test/functional/bip68-sequence.py b/test/functional/feature_bip68_sequence.py
index 94b13653b9..94b13653b9 100755
--- a/test/functional/bip68-sequence.py
+++ b/test/functional/feature_bip68_sequence.py
diff --git a/test/functional/bip9-softforks.py b/test/functional/feature_bip9_softforks.py
index ae92e9f07c..ae92e9f07c 100755
--- a/test/functional/bip9-softforks.py
+++ b/test/functional/feature_bip9_softforks.py
diff --git a/test/functional/p2p-fullblocktest.py b/test/functional/feature_block.py
index fe9bbda14b..fe9bbda14b 100755
--- a/test/functional/p2p-fullblocktest.py
+++ b/test/functional/feature_block.py
diff --git a/test/functional/bip65-cltv-p2p.py b/test/functional/feature_cltv.py
index f62ae31654..f62ae31654 100755
--- a/test/functional/bip65-cltv-p2p.py
+++ b/test/functional/feature_cltv.py
diff --git a/test/functional/conf_args.py b/test/functional/feature_config_args.py
index 61abba8082..61abba8082 100755
--- a/test/functional/conf_args.py
+++ b/test/functional/feature_config_args.py
diff --git a/test/functional/bip68-112-113-p2p.py b/test/functional/feature_csv_activation.py
index 82aa0ff891..82aa0ff891 100755
--- a/test/functional/bip68-112-113-p2p.py
+++ b/test/functional/feature_csv_activation.py
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 3414571678..3414571678 100755
--- a/test/functional/bipdersig-p2p.py
+++ b/test/functional/feature_dersig.py
diff --git a/test/functional/smartfees.py b/test/functional/feature_fee_estimation.py
index 68453e50f4..e1263414bd 100755
--- a/test/functional/smartfees.py
+++ b/test/functional/feature_fee_estimation.py
@@ -3,39 +3,47 @@
# 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 45336ee801..45336ee801 100755
--- a/test/functional/maxuploadtarget.py
+++ b/test/functional/feature_maxuploadtarget.py
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 980bef5fc8..980bef5fc8 100755
--- a/test/functional/notifications.py
+++ b/test/functional/feature_notifications.py
diff --git a/test/functional/nulldummy.py b/test/functional/feature_nulldummy.py
index 110b7a655e..740c498ce6 100755
--- a/test/functional/nulldummy.py
+++ b/test/functional/feature_nulldummy.py
@@ -21,7 +21,7 @@ from test_framework.script import CScript
from io import BytesIO
import time
-NULLDUMMY_ERROR = "64: non-mandatory-script-verify-flag (Dummy CHECKMULTISIG argument must be zero)"
+NULLDUMMY_ERROR = "non-mandatory-script-verify-flag (Dummy CHECKMULTISIG argument must be zero) (code 64)"
def trueDummy(tx):
scriptSig = CScript(tx.vin[0].scriptSig)
@@ -42,13 +42,13 @@ 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', '-addresstype=legacy']]
+ 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']
network_thread_start()
self.coinbase_blocks = self.nodes[0].generate(2) # Block 2
diff --git a/test/functional/proxy_test.py b/test/functional/feature_proxy.py
index 2eb1be47a5..2eb1be47a5 100755
--- a/test/functional/proxy_test.py
+++ b/test/functional/feature_proxy.py
diff --git a/test/functional/pruning.py b/test/functional/feature_pruning.py
index 49ad7f838c..49ad7f838c 100755
--- a/test/functional/pruning.py
+++ b/test/functional/feature_pruning.py
diff --git a/test/functional/replace-by-fee.py b/test/functional/feature_rbf.py
index 6b7ab0f43e..6b7ab0f43e 100755
--- a/test/functional/replace-by-fee.py
+++ b/test/functional/feature_rbf.py
diff --git a/test/functional/reindex.py b/test/functional/feature_reindex.py
index ac67e6e9ba..ac67e6e9ba 100755
--- a/test/functional/reindex.py
+++ b/test/functional/feature_reindex.py
diff --git a/test/functional/segwit.py b/test/functional/feature_segwit.py
index 7d5c760ad9..7db05077c9 100755
--- a/test/functional/segwit.py
+++ b/test/functional/feature_segwit.py
@@ -30,19 +30,21 @@ def getutxo(txid):
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", "-addresstype=legacy"],
- ["-blockversion=4", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness", "-rpcserialversion=1", "-vbparams=segwit:0:999999999999", "-addresstype=legacy"],
- ["-blockversion=536870915", "-promiscuousmempoolflags=517", "-prematurewitness", "-walletprematurewitness", "-vbparams=segwit:0:999999999999", "-addresstype=legacy"]]
+ 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()
@@ -95,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)
bip173_addr = self.nodes[i].addwitnessaddress(newaddress, False)
- p2sh_ms_addr = self.nodes[i].addwitnessaddress(multiaddress)
- 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))
@@ -114,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)
@@ -210,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
@@ -290,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]))
@@ -463,11 +464,11 @@ 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_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 = []
@@ -571,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 cd6d744545..cd6d744545 100755
--- a/test/functional/httpbasics.py
+++ b/test/functional/interface_http.py
diff --git a/test/functional/rest.py b/test/functional/interface_rest.py
index 9006e27cbe..9006e27cbe 100755
--- a/test/functional/rest.py
+++ b/test/functional/interface_rest.py
diff --git a/test/functional/zmq_test.py b/test/functional/interface_zmq.py
index 86ccea4394..86ccea4394 100755
--- a/test/functional/zmq_test.py
+++ b/test/functional/interface_zmq.py
diff --git a/test/functional/invalidtxrequest.py b/test/functional/invalidtxrequest.py
deleted file mode 100755
index 9c1100e070..0000000000
--- a/test/functional/invalidtxrequest.py
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/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.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
- network_thread_start()
- 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 e7ce3820d2..7e01663c96 100755
--- a/test/functional/mempool_limit.py
+++ b/test/functional/mempool_limit.py
@@ -50,5 +50,15 @@ class MempoolLimitTest(BitcoinTestFramework):
assert_equal(self.nodes[0].getmempoolinfo()['minrelaytxfee'], Decimal('0.00001000'))
assert_greater_than(self.nodes[0].getmempoolinfo()['mempoolminfee'], Decimal('0.00001000'))
+ self.log.info('Create a mempool tx that will not pass mempoolminfee')
+ us0 = utxos.pop()
+ inputs = [{ "txid" : us0["txid"], "vout" : us0["vout"]}]
+ outputs = {self.nodes[0].getnewaddress() : 0.0001}
+ tx = self.nodes[0].createrawtransaction(inputs, outputs)
+ # specifically fund this tx with a fee < mempoolminfee, >= than minrelaytxfee
+ txF = self.nodes[0].fundrawtransaction(tx, {'feeRate': relayfee})
+ txFS = self.nodes[0].signrawtransaction(txF['hex'])
+ assert_raises_rpc_error(-26, "mempool min fee not met, 166 < 411 (code 66)", self.nodes[0].sendrawtransaction, txFS['hex'])
+
if __name__ == '__main__':
MempoolLimitTest().main()
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_resurrect_test.py b/test/functional/mempool_resurrect.py
index 83e84da4bc..83e84da4bc 100755
--- a/test/functional/mempool_resurrect_test.py
+++ b/test/functional/mempool_resurrect.py
diff --git a/test/functional/mempool_spendcoinbase.py b/test/functional/mempool_spend_coinbase.py
index db0738c08a..db0738c08a 100755
--- a/test/functional/mempool_spendcoinbase.py
+++ b/test/functional/mempool_spend_coinbase.py
diff --git a/test/functional/mining.py b/test/functional/mining_basic.py
index 569bf71933..569bf71933 100755
--- a/test/functional/mining.py
+++ b/test/functional/mining_basic.py
diff --git a/test/functional/getblocktemplate_longpoll.py b/test/functional/mining_getblocktemplate_longpoll.py
index 252ff4dbff..252ff4dbff 100755
--- a/test/functional/getblocktemplate_longpoll.py
+++ b/test/functional/mining_getblocktemplate_longpoll.py
diff --git a/test/functional/prioritise_transaction.py b/test/functional/mining_prioritisetransaction.py
index 57954ce321..8cea9c2783 100755
--- a/test/functional/prioritise_transaction.py
+++ b/test/functional/mining_prioritisetransaction.py
@@ -120,7 +120,7 @@ class PrioritiseTransactionTest(BitcoinTestFramework):
tx_id = self.nodes[0].decoderawtransaction(tx_hex)["txid"]
# This will raise an exception due to min relay fee not being met
- assert_raises_rpc_error(-26, "66: min relay fee not met", self.nodes[0].sendrawtransaction, tx_hex)
+ assert_raises_rpc_error(-26, "min relay fee not met (code 66)", self.nodes[0].sendrawtransaction, tx_hex)
assert(tx_id not in self.nodes[0].getrawmempool())
# This is a less than 1000-byte transaction, so just set the fee
diff --git a/test/functional/p2p-versionbits-warning.py b/test/functional/p2p-versionbits-warning.py
deleted file mode 100755
index 0bfe94622f..0000000000
--- a/test/functional/p2p-versionbits-warning.py
+++ /dev/null
@@ -1,121 +0,0 @@
-#!/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.
-"""
-
-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())
-
- network_thread_start()
-
- # 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 e98ae31a89..d9f461a049 100755
--- a/test/functional/p2p-compactblocks.py
+++ b/test/functional/p2p_compactblocks.py
@@ -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):
diff --git a/test/functional/disconnect_ban.py b/test/functional/p2p_disconnect_ban.py
index c6067befb2..c6067befb2 100755
--- a/test/functional/disconnect_ban.py
+++ b/test/functional/p2p_disconnect_ban.py
diff --git a/test/functional/p2p-feefilter.py b/test/functional/p2p_feefilter.py
index 47d9c55160..47d9c55160 100755
--- a/test/functional/p2p-feefilter.py
+++ b/test/functional/p2p_feefilter.py
diff --git a/test/functional/p2p-fingerprint.py b/test/functional/p2p_fingerprint.py
index 93ef73e25e..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.
"""
diff --git a/test/functional/invalidblockrequest.py b/test/functional/p2p_invalid_block.py
index edcade63c1..edcade63c1 100755
--- a/test/functional/invalidblockrequest.py
+++ b/test/functional/p2p_invalid_block.py
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 ce4e6e9144..ce4e6e9144 100755
--- a/test/functional/p2p-leaktests.py
+++ b/test/functional/p2p_leak.py
diff --git a/test/functional/p2p-mempool.py b/test/functional/p2p_mempool.py
index 485a8af3d0..485a8af3d0 100755
--- a/test/functional/p2p-mempool.py
+++ b/test/functional/p2p_mempool.py
diff --git a/test/functional/node_network_limited.py b/test/functional/p2p_node_network_limited.py
index 70415e0168..70415e0168 100755
--- a/test/functional/node_network_limited.py
+++ b/test/functional/p2p_node_network_limited.py
diff --git a/test/functional/p2p-segwit.py b/test/functional/p2p_segwit.py
index 20e4805df0..20e4805df0 100755
--- a/test/functional/p2p-segwit.py
+++ b/test/functional/p2p_segwit.py
diff --git a/test/functional/sendheaders.py b/test/functional/p2p_sendheaders.py
index 8869aeaaea..8869aeaaea 100755
--- a/test/functional/sendheaders.py
+++ b/test/functional/p2p_sendheaders.py
diff --git a/test/functional/p2p-timeouts.py b/test/functional/p2p_timeouts.py
index 6d21095cc6..6d21095cc6 100755
--- a/test/functional/p2p-timeouts.py
+++ b/test/functional/p2p_timeouts.py
diff --git a/test/functional/p2p-acceptblock.py b/test/functional/p2p_unrequested_blocks.py
index 672626f15b..672626f15b 100755
--- a/test/functional/p2p-acceptblock.py
+++ b/test/functional/p2p_unrequested_blocks.py
diff --git a/test/functional/rpcbind_test.py b/test/functional/rpc_bind.py
index 05433c7e24..05433c7e24 100755
--- a/test/functional/rpcbind_test.py
+++ b/test/functional/rpc_bind.py
diff --git a/test/functional/blockchain.py b/test/functional/rpc_blockchain.py
index 11acff4be1..7cf2abe6f0 100755
--- a/test/functional/blockchain.py
+++ b/test/functional/rpc_blockchain.py
@@ -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 1ffc570437..1ffc570437 100755
--- a/test/functional/decodescript.py
+++ b/test/functional/rpc_decodescript.py
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 4739e73c39..4d3be18516 100755
--- a/test/functional/fundrawtransaction.py
+++ b/test/functional/rpc_fundrawtransaction.py
@@ -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 277930bb1a..277930bb1a 100755
--- a/test/functional/getchaintips.py
+++ b/test/functional/rpc_getchaintips.py
diff --git a/test/functional/invalidateblock.py b/test/functional/rpc_invalidateblock.py
index b037c2431d..b037c2431d 100755
--- a/test/functional/invalidateblock.py
+++ b/test/functional/rpc_invalidateblock.py
diff --git a/test/functional/listtransactions.py b/test/functional/rpc_listtransactions.py
index cbed065928..ba71ac0967 100755
--- a/test/functional/listtransactions.py
+++ b/test/functional/rpc_listtransactions.py
@@ -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 97bee39614..97bee39614 100755
--- a/test/functional/rpcnamedargs.py
+++ b/test/functional/rpc_named_arguments.py
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 960cd0ad12..960cd0ad12 100755
--- a/test/functional/preciousblock.py
+++ b/test/functional/rpc_preciousblock.py
diff --git a/test/functional/rawtransactions.py b/test/functional/rpc_rawtransaction.py
index fe749adb49..92126ef4b7 100755
--- a/test/functional/rawtransactions.py
+++ b/test/functional/rpc_rawtransaction.py
@@ -59,6 +59,10 @@ 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, [])
@@ -145,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()
@@ -168,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)
@@ -177,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
@@ -213,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)
diff --git a/test/functional/signmessages.py b/test/functional/rpc_signmessage.py
index 5b6935ceea..5b6935ceea 100755
--- a/test/functional/signmessages.py
+++ b/test/functional/rpc_signmessage.py
diff --git a/test/functional/signrawtransactions.py b/test/functional/rpc_signrawtransaction.py
index dd0fa6c02c..dd0fa6c02c 100755
--- a/test/functional/signrawtransactions.py
+++ b/test/functional/rpc_signrawtransaction.py
diff --git a/test/functional/merkle_blocks.py b/test/functional/rpc_txoutproof.py
index 50e0371fdf..50e0371fdf 100755
--- a/test/functional/merkle_blocks.py
+++ b/test/functional/rpc_txoutproof.py
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 01f68344ae..01f68344ae 100755
--- a/test/functional/multi_rpc.py
+++ b/test/functional/rpc_users.py
diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py
index a54a0299c7..46ef7521e0 100644
--- a/test/functional/test_framework/messages.py
+++ b/test/functional/test_framework/messages.py
@@ -44,6 +44,11 @@ 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):
return hashlib.new('sha256', s).digest()
@@ -204,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",
diff --git a/test/functional/test_framework/mininode.py b/test/functional/test_framework/mininode.py
index fe14591139..99d0abc3f9 100755
--- a/test/functional/test_framework/mininode.py
+++ b/test/functional/test_framework/mininode.py
@@ -6,11 +6,13 @@
# 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
@@ -86,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))
@@ -356,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)
@@ -440,3 +454,138 @@ def network_thread_join(timeout=10):
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/test_framework.py b/test/functional/test_framework/test_framework.py
index 5d4f8e6720..a5e66bd959 100755
--- a/test/functional/test_framework/test_framework.py
+++ b/test/functional/test_framework/test_framework.py
@@ -99,7 +99,9 @@ class BitcoinTestFramework():
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()
@@ -148,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")
@@ -164,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.
@@ -220,18 +225,18 @@ class BitcoinTestFramework():
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, 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:
@@ -239,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:
@@ -271,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 589a8f3969..1054e6d028 100755
--- a/test/functional/test_framework/test_node.py
+++ b/test/functional/test_framework/test_node.py
@@ -81,13 +81,13 @@ class TestNode():
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")
@@ -213,16 +213,16 @@ 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
+ def __call__(self, *options, input=None):
+ # TestNodeCLI is callable with bitcoin-cli command-line options
cli = TestNodeCLI(self.binary, self.datadir)
- cli.args = [str(arg) for arg in args]
+ cli.options = [str(o) for o in options]
cli.input = input
return cli
@@ -238,16 +238,18 @@ class TestNodeCLI():
results.append(dict(error=e))
return results
- def send_cli(self, command, *args, **kwargs):
+ 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)
diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py
index 62c4e46af1..8bf75ca1ae 100644
--- a/test/functional/test_framework/util.py
+++ b/test/functional/test_framework/util.py
@@ -391,7 +391,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
@@ -403,6 +403,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 72ad300e7e..945f645eac 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -55,84 +55,84 @@ 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',
- 'address_types.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',
- 'txn_clone.py --segwit',
- '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',
- 'multiwallet.py --usecli',
- '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',
- 'conf_args.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
]
@@ -140,29 +140,29 @@ BASE_SCRIPTS= [
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
@@ -268,7 +268,7 @@ 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"])
@@ -312,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)
@@ -342,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.executable, os.path.join(tests_dir, 'combine_logs.py'), '-c', testdir], universal_newlines=True, stdout=subprocess.PIPE).communicate()
print("\n".join(deque(combined_logs.splitlines(), combined_logs_len)))
print_results(test_results, max_len_name, (int(time.time() - time0)))
@@ -412,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),
@@ -472,25 +472,15 @@ class TestResult():
def check_script_prefixes():
- """Check that no more than `EXPECTED_VIOLATION_COUNT` of the
- test scripts don't start with one of the allowed name prefixes."""
- EXPECTED_VIOLATION_COUNT = 77
-
- # LEEWAY is provided as a transition measure, so that pull-requests
- # that introduce new tests that don't conform with the naming
- # convention don't immediately cause the tests to fail.
- LEEWAY = 10
+ """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 len(bad_script_names) < EXPECTED_VIOLATION_COUNT:
- print("{}HURRAY!{} Number of functional tests violating naming convention reduced!".format(BOLD[1], BOLD[0]))
- print("Consider reducing EXPECTED_VIOLATION_COUNT from %d to %d" % (EXPECTED_VIOLATION_COUNT, len(bad_script_names)))
- elif len(bad_script_names) > EXPECTED_VIOLATION_COUNT:
- print("INFO: %d tests not meeting naming conventions (expected %d):" % (len(bad_script_names), EXPECTED_VIOLATION_COUNT))
+ 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))))
- assert len(bad_script_names) <= EXPECTED_VIOLATION_COUNT + LEEWAY, "Too many tests not following naming convention! (%d found, expected: <= %d)" % (len(bad_script_names), EXPECTED_VIOLATION_COUNT)
+ raise AssertionError("Some tests are not following naming convention!")
def check_script_list(src_dir):
diff --git a/test/functional/abandonconflict.py b/test/functional/wallet_abandonconflict.py
index 14964438af..8fb860cd7e 100755
--- a/test/functional/abandonconflict.py
+++ b/test/functional/wallet_abandonconflict.py
@@ -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 287436877f..ecd1cfc82b 100755
--- a/test/functional/wallet-accounts.py
+++ b/test/functional/wallet_accounts.py
@@ -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/address_types.py b/test/functional/wallet_address_types.py
index cb119c04b0..38a3425214 100755
--- a/test/functional/address_types.py
+++ b/test/functional/wallet_address_types.py
@@ -4,16 +4,24 @@
# 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 4 nodes-under-test:
+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
-node4 exists to generate new blocks.
+node5 exists to generate new blocks.
-The script is a series of tests, iterating over the 4 nodes. In each iteration
-of the test, one node sends:
+## 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
@@ -21,21 +29,51 @@ of the test, one node sends:
- 1/101th remains as fee+change
Iterate over each node for single key addresses, and then over each node for
-multisig addresses. In a second iteration, the same is done, but with explicit address_type
-parameters passed to getnewaddress and getrawchangeaddress. Node0 and node3 send to p2sh,
-node 1 sends to bech32, and node2 sends to legacy. As every node sends coins after receiving,
-this also verifies that spending coins sent to all these address types works."""
+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, connect_nodes_bi, sync_blocks, sync_mempools
+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 = 5
- self.extra_args = [["-addresstype=legacy"], ["-addresstype=p2sh-segwit"], ["-addresstype=p2sh-segwit", "-changetype=bech32"], ["-addresstype=bech32"], []]
+ 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()
@@ -104,10 +142,26 @@ class AddressTypeTest(BitcoinTestFramework):
# 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 node4 to bring nodes out of IBD and make sure that
+ # 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[4].generate(101)
+ self.nodes[5].generate(101)
sync_blocks(self.nodes)
uncompressed_1 = "0496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858ee"
@@ -117,14 +171,14 @@ class AddressTypeTest(BitcoinTestFramework):
# 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]), True, 'legacy')
- self.test_address(node, self.nodes[node].addmultisigaddress(2, [compressed_1, uncompressed_2]), True, 'legacy')
- self.test_address(node, self.nodes[node].addmultisigaddress(2, [uncompressed_1, compressed_2]), True, 'legacy')
+ 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]), True, 'legacy')
- self.test_address(1, self.nodes[1].addmultisigaddress(2, [compressed_1, compressed_2]), True, 'p2sh-segwit')
- self.test_address(2, self.nodes[2].addmultisigaddress(2, [compressed_1, compressed_2]), True, 'p2sh-segwit')
- self.test_address(3, self.nodes[3].addmultisigaddress(2, [compressed_1, compressed_2]), True, 'bech32')
+ 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
@@ -155,7 +209,7 @@ class AddressTypeTest(BitcoinTestFramework):
else:
addr1 = self.nodes[to_node].getnewaddress()
addr2 = self.nodes[to_node].getnewaddress()
- address = self.nodes[to_node].addmultisigaddress(2, [addr1, addr2])
+ address = self.nodes[to_node].addmultisigaddress(2, [addr1, addr2])['address']
# Do some sanity checking on the created address
if address_type is not None:
@@ -182,8 +236,8 @@ class AddressTypeTest(BitcoinTestFramework):
to_node %= 4
assert_equal(unconf_balances[to_node], to_send * 10 * (2 + n))
- # node4 collects fee and block subsidy to keep accounting simple
- self.nodes[4].generate(1)
+ # node5 collects fee and block subsidy to keep accounting simple
+ self.nodes[5].generate(1)
sync_blocks(self.nodes)
new_balances = self.get_balances()
@@ -195,5 +249,46 @@ class AddressTypeTest(BitcoinTestFramework):
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 b4be7debb5..b4be7debb5 100755
--- a/test/functional/walletbackup.py
+++ b/test/functional/wallet_backup.py
diff --git a/test/functional/wallet.py b/test/functional/wallet_basic.py
index a90dbc8adf..a90dbc8adf 100755
--- a/test/functional/wallet.py
+++ b/test/functional/wallet_basic.py
diff --git a/test/functional/bumpfee.py b/test/functional/wallet_bumpfee.py
index 1e5620736b..f621d41b4e 100755
--- a/test/functional/bumpfee.py
+++ b/test/functional/wallet_bumpfee.py
@@ -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):
@@ -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()
diff --git a/test/functional/disablewallet.py b/test/functional/wallet_disable.py
index b0627d88ac..b0627d88ac 100755
--- a/test/functional/disablewallet.py
+++ b/test/functional/wallet_disable.py
diff --git a/test/functional/wallet-dump.py b/test/functional/wallet_dump.py
index 8b81c81ba8..5e943d048d 100755
--- a/test/functional/wallet-dump.py
+++ b/test/functional/wallet_dump.py
@@ -20,6 +20,7 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old):
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
@@ -47,7 +48,14 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old):
# 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":
@@ -63,13 +71,13 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old):
found_script_addr += 1
break
- return found_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_ret
+ 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", "-addresstype=legacy"]]
+ 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
@@ -83,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):
@@ -94,19 +104,20 @@ class WalletDumpTest(BitcoinTestFramework):
# 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"]])
+ 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_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_unenc = \
+ 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')
@@ -116,12 +127,13 @@ class WalletDumpTest(BitcoinTestFramework):
self.nodes[0].keypoolrefill()
self.nodes[0].dumpwallet(tmpdir + "/node0/wallet.encrypted.dump")
- found_addr, found_script_addr, found_addr_chg, found_addr_rsv, _ = \
+ 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")
diff --git a/test/functional/wallet-encryption.py b/test/functional/wallet_encryption.py
index 452e8ec291..3c927ee484 100755
--- a/test/functional/wallet-encryption.py
+++ b/test/functional/wallet_encryption.py
@@ -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 9f0e9acb47..9f0e9acb47 100755
--- a/test/functional/wallet-hd.py
+++ b/test/functional/wallet_hd.py
diff --git a/test/functional/import-rescan.py b/test/functional/wallet_import_rescan.py
index d193a99d5b..d193a99d5b 100755
--- a/test/functional/import-rescan.py
+++ b/test/functional/wallet_import_rescan.py
diff --git a/test/functional/importmulti.py b/test/functional/wallet_importmulti.py
index ab4ca48e48..be9be83839 100755
--- a/test/functional/importmulti.py
+++ b/test/functional/wallet_importmulti.py
@@ -228,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)
@@ -255,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)
@@ -282,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)
@@ -309,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 6b2919b5ae..6b2919b5ae 100755
--- a/test/functional/importprunedfunds.py
+++ b/test/functional/wallet_importprunedfunds.py
diff --git a/test/functional/keypool.py b/test/functional/wallet_keypool.py
index 45a5eed8ec..45a5eed8ec 100755
--- a/test/functional/keypool.py
+++ b/test/functional/wallet_keypool.py
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 1f2b3c8aa7..1f2b3c8aa7 100755
--- a/test/functional/receivedby.py
+++ b/test/functional/wallet_listreceivedby.py
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 0891829127..b07e451667 100755
--- a/test/functional/multiwallet.py
+++ b/test/functional/wallet_multiwallet.py
@@ -30,6 +30,10 @@ class MultiWalletTest(BitcoinTestFramework):
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.')
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 ce26d6e0ee..ce26d6e0ee 100755
--- a/test/functional/txn_clone.py
+++ b/test/functional/wallet_txn_clone.py
diff --git a/test/functional/txn_doublespend.py b/test/functional/wallet_txn_doublespend.py
index 01129f3817..01129f3817 100755
--- a/test/functional/txn_doublespend.py
+++ b/test/functional/wallet_txn_doublespend.py
diff --git a/test/functional/zapwallettxes.py b/test/functional/wallet_zapwallettxes.py
index 0471f2afb3..87f44b2737 100755
--- a/test/functional/zapwallettxes.py
+++ b/test/functional/wallet_zapwallettxes.py
@@ -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)