aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/README.md3
-rw-r--r--test/functional/data/invalid_txs.py180
-rwxr-xr-xtest/functional/feature_assumevalid.py2
-rwxr-xr-xtest/functional/feature_block.py107
-rwxr-xr-xtest/functional/feature_config_args.py8
-rwxr-xr-xtest/functional/feature_dbcrash.py2
-rwxr-xr-xtest/functional/feature_pruning.py4
-rwxr-xr-xtest/functional/mempool_accept.py2
-rwxr-xr-xtest/functional/p2p_invalid_locator.py2
-rwxr-xr-xtest/functional/p2p_invalid_tx.py24
-rwxr-xr-xtest/functional/rpc_bind.py2
-rwxr-xr-xtest/functional/rpc_fundrawtransaction.py2
-rwxr-xr-xtest/functional/rpc_invalidateblock.py69
-rwxr-xr-xtest/functional/rpc_net.py4
-rwxr-xr-xtest/functional/rpc_rawtransaction.py2
-rw-r--r--test/functional/test_framework/blocktools.py5
-rwxr-xr-xtest/functional/test_framework/test_framework.py40
-rwxr-xr-xtest/functional/test_framework/wallet_util.py99
-rwxr-xr-xtest/functional/wallet_backup.py2
-rwxr-xr-xtest/functional/wallet_dump.py2
-rwxr-xr-xtest/functional/wallet_groups.py2
-rwxr-xr-xtest/functional/wallet_import_with_label.py77
-rwxr-xr-xtest/functional/wallet_importmulti.py547
-rwxr-xr-xtest/functional/wallet_listtransactions.py3
-rwxr-xr-xtest/lint/lint-includes.sh1
-rwxr-xr-xtest/lint/lint-locale-dependence.sh13
-rwxr-xr-xtest/lint/lint-python-dead-code.sh2
-rw-r--r--test/sanitizer_suppressions/ubsan1
28 files changed, 766 insertions, 441 deletions
diff --git a/test/README.md b/test/README.md
index 680f9bf9a6..b5cbe1aff3 100644
--- a/test/README.md
+++ b/test/README.md
@@ -18,7 +18,8 @@ request is opened. All sets of tests can also be run locally.
# Running tests locally
-Build for your system first. Be sure to enable wallet, utils and daemon when you configure. Tests will not run otherwise.
+Before tests can be run locally, Bitcoin Core must be built. See the [building instructions](/doc#building) for help.
+
### Functional tests
diff --git a/test/functional/data/invalid_txs.py b/test/functional/data/invalid_txs.py
new file mode 100644
index 0000000000..02deae92f3
--- /dev/null
+++ b/test/functional/data/invalid_txs.py
@@ -0,0 +1,180 @@
+#!/usr/bin/env python3
+# Copyright (c) 2015-2018 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""
+Templates for constructing various sorts of invalid transactions.
+
+These templates (or an iterator over all of them) can be reused in different
+contexts to test using a number of invalid transaction types.
+
+Hopefully this makes it easier to get coverage of a full variety of tx
+validation checks through different interfaces (AcceptBlock, AcceptToMemPool,
+etc.) without repeating ourselves.
+
+Invalid tx cases not covered here can be found by running:
+
+ $ diff \
+ <(grep -IREho "bad-txns[a-zA-Z-]+" src | sort -u) \
+ <(grep -IEho "bad-txns[a-zA-Z-]+" test/functional/data/invalid_txs.py | sort -u)
+
+"""
+import abc
+
+from test_framework.messages import CTransaction, CTxIn, CTxOut, COutPoint
+from test_framework import script as sc
+from test_framework.blocktools import create_tx_with_script, MAX_BLOCK_SIGOPS
+
+basic_p2sh = sc.CScript([sc.OP_HASH160, sc.hash160(sc.CScript([sc.OP_0])), sc.OP_EQUAL])
+
+
+class BadTxTemplate:
+ """Allows simple construction of a certain kind of invalid tx. Base class to be subclassed."""
+ __metaclass__ = abc.ABCMeta
+
+ # The expected error code given by bitcoind upon submission of the tx.
+ reject_reason = ""
+
+ # Only specified if it differs from mempool acceptance error.
+ block_reject_reason = ""
+
+ # Do we expect to be disconnected after submitting this tx?
+ expect_disconnect = False
+
+ # Is this tx considered valid when included in a block, but not for acceptance into
+ # the mempool (i.e. does it violate policy but not consensus)?
+ valid_in_block = False
+
+ def __init__(self, *, spend_tx=None, spend_block=None):
+ self.spend_tx = spend_block.vtx[0] if spend_block else spend_tx
+ self.spend_avail = sum(o.nValue for o in self.spend_tx.vout)
+ self.valid_txin = CTxIn(COutPoint(self.spend_tx.sha256, 0), b"", 0xffffffff)
+
+ @abc.abstractmethod
+ def get_tx(self, *args, **kwargs):
+ """Return a CTransaction that is invalid per the subclass."""
+ pass
+
+
+class OutputMissing(BadTxTemplate):
+ reject_reason = "bad-txns-vout-empty"
+ expect_disconnect = False
+
+ def get_tx(self):
+ tx = CTransaction()
+ tx.vin.append(self.valid_txin)
+ tx.calc_sha256()
+ return tx
+
+
+class InputMissing(BadTxTemplate):
+ reject_reason = "bad-txns-vin-empty"
+ expect_disconnect = False
+
+ def get_tx(self):
+ tx = CTransaction()
+ tx.vout.append(CTxOut(0, sc.CScript([sc.OP_TRUE] * 100)))
+ tx.calc_sha256()
+ return tx
+
+
+class SizeTooSmall(BadTxTemplate):
+ reject_reason = "tx-size-small"
+ expect_disconnect = False
+ valid_in_block = True
+
+ def get_tx(self):
+ tx = CTransaction()
+ tx.vin.append(self.valid_txin)
+ tx.vout.append(CTxOut(0, sc.CScript([sc.OP_TRUE])))
+ tx.calc_sha256()
+ return tx
+
+
+class BadInputOutpointIndex(BadTxTemplate):
+ # Won't be rejected - nonexistent outpoint index is treated as an orphan since the coins
+ # database can't distinguish between spent outpoints and outpoints which never existed.
+ reject_reason = None
+ expect_disconnect = False
+
+ def get_tx(self):
+ num_indices = len(self.spend_tx.vin)
+ bad_idx = num_indices + 100
+
+ tx = CTransaction()
+ tx.vin.append(CTxIn(COutPoint(self.spend_tx.sha256, bad_idx), b"", 0xffffffff))
+ tx.vout.append(CTxOut(0, basic_p2sh))
+ tx.calc_sha256()
+ return tx
+
+
+class DuplicateInput(BadTxTemplate):
+ reject_reason = 'bad-txns-inputs-duplicate'
+ expect_disconnect = True
+
+ def get_tx(self):
+ tx = CTransaction()
+ tx.vin.append(self.valid_txin)
+ tx.vin.append(self.valid_txin)
+ tx.vout.append(CTxOut(1, basic_p2sh))
+ tx.calc_sha256()
+ return tx
+
+
+class NonexistentInput(BadTxTemplate):
+ reject_reason = None # Added as an orphan tx.
+ expect_disconnect = False
+
+ def get_tx(self):
+ tx = CTransaction()
+ tx.vin.append(CTxIn(COutPoint(self.spend_tx.sha256 + 1, 0), b"", 0xffffffff))
+ tx.vin.append(self.valid_txin)
+ tx.vout.append(CTxOut(1, basic_p2sh))
+ tx.calc_sha256()
+ return tx
+
+
+class SpendTooMuch(BadTxTemplate):
+ reject_reason = 'bad-txns-in-belowout'
+ expect_disconnect = True
+
+ def get_tx(self):
+ return create_tx_with_script(
+ self.spend_tx, 0, script_pub_key=basic_p2sh, amount=(self.spend_avail + 1))
+
+
+class SpendNegative(BadTxTemplate):
+ reject_reason = 'bad-txns-vout-negative'
+ expect_disconnect = True
+
+ def get_tx(self):
+ return create_tx_with_script(self.spend_tx, 0, amount=-1)
+
+
+class InvalidOPIFConstruction(BadTxTemplate):
+ reject_reason = "mandatory-script-verify-flag-failed (Invalid OP_IF construction)"
+ expect_disconnect = True
+ valid_in_block = True
+
+ def get_tx(self):
+ return create_tx_with_script(
+ self.spend_tx, 0, script_sig=b'\x64' * 35,
+ amount=(self.spend_avail // 2))
+
+
+class TooManySigops(BadTxTemplate):
+ reject_reason = "bad-txns-too-many-sigops"
+ block_reject_reason = "bad-blk-sigops, out-of-bounds SigOpCount"
+ expect_disconnect = False
+
+ def get_tx(self):
+ lotsa_checksigs = sc.CScript([sc.OP_CHECKSIG] * (MAX_BLOCK_SIGOPS))
+ return create_tx_with_script(
+ self.spend_tx, 0,
+ script_pub_key=lotsa_checksigs,
+ amount=1)
+
+
+def iter_all_templates():
+ """Iterate through all bad transaction template types."""
+ return BadTxTemplate.__subclasses__()
diff --git a/test/functional/feature_assumevalid.py b/test/functional/feature_assumevalid.py
index 3d0467038d..12a4ce9aff 100755
--- a/test/functional/feature_assumevalid.py
+++ b/test/functional/feature_assumevalid.py
@@ -180,7 +180,7 @@ class AssumeValidTest(BitcoinTestFramework):
for i in range(2202):
p2p1.send_message(msg_block(self.blocks[i]))
# Syncing 2200 blocks can take a while on slow systems. Give it plenty of time to sync.
- p2p1.sync_with_ping(120)
+ p2p1.sync_with_ping(150)
assert_equal(self.nodes[1].getblock(self.nodes[1].getbestblockhash())['height'], 2202)
# Send blocks to node2. Block 102 will be rejected.
diff --git a/test/functional/feature_block.py b/test/functional/feature_block.py
index b741339351..5253ff7aaa 100755
--- a/test/functional/feature_block.py
+++ b/test/functional/feature_block.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2018 The Bitcoin Core developers
+# Copyright (c) 2015-2019 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test block processing."""
@@ -7,7 +7,13 @@ import copy
import struct
import time
-from test_framework.blocktools import create_block, create_coinbase, create_tx_with_script, get_legacy_sigopcount_block
+from test_framework.blocktools import (
+ create_block,
+ create_coinbase,
+ create_tx_with_script,
+ get_legacy_sigopcount_block,
+ MAX_BLOCK_SIGOPS,
+)
from test_framework.key import CECKey
from test_framework.messages import (
CBlock,
@@ -45,8 +51,7 @@ from test_framework.script import (
)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal
-
-MAX_BLOCK_SIGOPS = 20000
+from data import invalid_txs
# Use this class for tests that require behavior other than normal "mininode" behavior.
# For now, it is used to serialize a bloated varint (b64).
@@ -95,16 +100,21 @@ class FullBlockTest(BitcoinTestFramework):
self.save_spendable_output()
self.sync_blocks([b0])
+ # These constants chosen specifically to trigger an immature coinbase spend
+ # at a certain time below.
+ NUM_BUFFER_BLOCKS_TO_GENERATE = 99
+ NUM_OUTPUTS_TO_COLLECT = 33
+
# Allow the block to mature
blocks = []
- for i in range(99):
- blocks.append(self.next_block(5000 + i))
+ for i in range(NUM_BUFFER_BLOCKS_TO_GENERATE):
+ blocks.append(self.next_block("maturitybuffer.{}".format(i)))
self.save_spendable_output()
self.sync_blocks(blocks)
# collect spendable outputs now to avoid cluttering the code later on
out = []
- for i in range(33):
+ for i in range(NUM_OUTPUTS_TO_COLLECT):
out.append(self.get_spendable_output())
# Start by building a couple of blocks on top (which output is spent is
@@ -116,7 +126,48 @@ class FullBlockTest(BitcoinTestFramework):
b2 = self.next_block(2, spend=out[1])
self.save_spendable_output()
- self.sync_blocks([b1, b2])
+ self.sync_blocks([b1, b2], timeout=4)
+
+ # Select a txn with an output eligible for spending. This won't actually be spent,
+ # since we're testing submission of a series of blocks with invalid txns.
+ attempt_spend_tx = out[2]
+
+ # Submit blocks for rejection, each of which contains a single transaction
+ # (aside from coinbase) which should be considered invalid.
+ for TxTemplate in invalid_txs.iter_all_templates():
+ template = TxTemplate(spend_tx=attempt_spend_tx)
+
+ if template.valid_in_block:
+ continue
+
+ self.log.info("Reject block with invalid tx: %s", TxTemplate.__name__)
+ blockname = "for_invalid.%s" % TxTemplate.__name__
+ badblock = self.next_block(blockname)
+ badtx = template.get_tx()
+ if TxTemplate != invalid_txs.InputMissing:
+ self.sign_tx(badtx, attempt_spend_tx)
+ else:
+ # Segwit is active in regtest at this point, so to deserialize a
+ # transaction without any inputs correctly, we set the outputs
+ # to an empty list. This is a hack, as the serialization of an
+ # empty list of outputs is deserialized as flags==0 and thus
+ # deserialization of the outputs is skipped.
+ # A policy check requires "loose" txs to be of a minimum size,
+ # so vtx is not set to be empty in the TxTemplate class and we
+ # only apply the workaround where txs are not "loose", i.e. in
+ # blocks.
+ #
+ # The workaround has the purpose that both sides calculate
+ # the same tx hash in the merkle tree
+ badtx.vout = []
+ badtx.rehash()
+ badblock = self.update_block(blockname, [badtx])
+ self.sync_blocks(
+ [badblock], success=False,
+ reject_reason=(template.block_reject_reason or template.reject_reason),
+ reconnect=True, timeout=2)
+
+ self.move_tip(2)
# Fork like this:
#
@@ -874,7 +925,7 @@ class FullBlockTest(BitcoinTestFramework):
# \-> b67 (20)
#
#
- self.log.info("Reject a block with a transaction double spending a transaction creted in the same block")
+ self.log.info("Reject a block with a transaction double spending a transaction created in the same block")
self.move_tip(65)
b67 = self.next_block(67)
tx1 = self.create_and_sign_transaction(out[20], out[20].vout[0].nValue)
@@ -1169,7 +1220,7 @@ class FullBlockTest(BitcoinTestFramework):
blocks = []
spend = out[32]
for i in range(89, LARGE_REORG_SIZE + 89):
- b = self.next_block(i, spend)
+ b = self.next_block(i, spend, version=4)
tx = CTransaction()
script_length = MAX_BLOCK_BASE_SIZE - len(b.serialize()) - 69
script_output = CScript([b'\x00' * script_length])
@@ -1188,20 +1239,32 @@ class FullBlockTest(BitcoinTestFramework):
self.move_tip(88)
blocks2 = []
for i in range(89, LARGE_REORG_SIZE + 89):
- blocks2.append(self.next_block("alt" + str(i)))
+ blocks2.append(self.next_block("alt" + str(i), version=4))
self.sync_blocks(blocks2, False, force_send=True)
# extend alt chain to trigger re-org
- block = self.next_block("alt" + str(chain1_tip + 1))
+ block = self.next_block("alt" + str(chain1_tip + 1), version=4)
self.sync_blocks([block], True, timeout=480)
# ... and re-org back to the first chain
self.move_tip(chain1_tip)
- block = self.next_block(chain1_tip + 1)
+ block = self.next_block(chain1_tip + 1, version=4)
self.sync_blocks([block], False, force_send=True)
- block = self.next_block(chain1_tip + 2)
+ block = self.next_block(chain1_tip + 2, version=4)
self.sync_blocks([block], True, timeout=480)
+ self.log.info("Reject a block with an invalid block header version")
+ b_v1 = self.next_block('b_v1', version=1)
+ self.sync_blocks([b_v1], success=False, force_send=True, reject_reason='bad-version(0x00000001)')
+
+ self.move_tip(chain1_tip + 2)
+ b_cb34 = self.next_block('b_cb34', version=4)
+ b_cb34.vtx[0].vin[0].scriptSig = b_cb34.vtx[0].vin[0].scriptSig[:-1]
+ b_cb34.vtx[0].rehash()
+ b_cb34.hashMerkleRoot = b_cb34.calc_merkle_root()
+ b_cb34.solve()
+ self.sync_blocks([b_cb34], success=False, reject_reason='bad-cb-height', reconnect=True)
+
# Helper methods
################
@@ -1229,7 +1292,7 @@ class FullBlockTest(BitcoinTestFramework):
tx.rehash()
return tx
- def next_block(self, number, spend=None, additional_coinbase_value=0, script=CScript([OP_TRUE]), solve=True):
+ def next_block(self, number, spend=None, additional_coinbase_value=0, script=CScript([OP_TRUE]), solve=True, *, version=1):
if self.tip is None:
base_block_hash = self.genesis_hash
block_time = int(time.time()) + 1
@@ -1242,11 +1305,11 @@ class FullBlockTest(BitcoinTestFramework):
coinbase.vout[0].nValue += additional_coinbase_value
coinbase.rehash()
if spend is None:
- block = create_block(base_block_hash, coinbase, block_time)
+ block = create_block(base_block_hash, coinbase, block_time, version=version)
else:
coinbase.vout[0].nValue += spend.vout[0].nValue - 1 # all but one satoshi to fees
coinbase.rehash()
- block = create_block(base_block_hash, coinbase, block_time)
+ block = create_block(base_block_hash, coinbase, block_time, version=version)
tx = self.create_tx(spend, 0, 1, script) # spend 1 satoshi
self.sign_tx(tx, spend)
self.add_transactions_to_block(block, [tx])
@@ -1288,7 +1351,7 @@ class FullBlockTest(BitcoinTestFramework):
self.blocks[block_number] = block
return block
- def bootstrap_p2p(self):
+ def bootstrap_p2p(self, timeout=10):
"""Add a P2P connection to the node.
Helper to connect and wait for version handshake."""
@@ -1299,15 +1362,15 @@ class FullBlockTest(BitcoinTestFramework):
# an INV for the next block and receive two getheaders - one for the
# IBD and one for the INV. We'd respond to both and could get
# unexpectedly disconnected if the DoS score for that error is 50.
- self.nodes[0].p2p.wait_for_getheaders(timeout=5)
+ self.nodes[0].p2p.wait_for_getheaders(timeout=timeout)
- def reconnect_p2p(self):
+ def reconnect_p2p(self, timeout=60):
"""Tear down and bootstrap the P2P connection to the node.
The node gets disconnected several times in this test. This helper
method reconnects the p2p and restarts the network thread."""
self.nodes[0].disconnect_p2ps()
- self.bootstrap_p2p()
+ self.bootstrap_p2p(timeout=timeout)
def sync_blocks(self, blocks, success=True, reject_reason=None, force_send=False, reconnect=False, timeout=60):
"""Sends blocks to test node. Syncs and verifies that tip has advanced to most recent block.
@@ -1316,7 +1379,7 @@ class FullBlockTest(BitcoinTestFramework):
self.nodes[0].p2p.send_blocks_and_test(blocks, self.nodes[0], success=success, reject_reason=reject_reason, force_send=force_send, timeout=timeout, expect_disconnect=reconnect)
if reconnect:
- self.reconnect_p2p()
+ self.reconnect_p2p(timeout=timeout)
if __name__ == '__main__':
diff --git a/test/functional/feature_config_args.py b/test/functional/feature_config_args.py
index d87eabaa6d..4b3f6603a2 100755
--- a/test/functional/feature_config_args.py
+++ b/test/functional/feature_config_args.py
@@ -34,6 +34,14 @@ class ConfArgsTest(BitcoinTestFramework):
self.nodes[0].assert_start_raises_init_error(expected_msg='Error reading configuration file: parse error on line 3, using # in rpcpassword can be ambiguous and should be avoided')
with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
+ conf.write('server=1\nrpcuser=someuser\nmain.rpcpassword=some#pass')
+ self.nodes[0].assert_start_raises_init_error(expected_msg='Error reading configuration file: parse error on line 3, using # in rpcpassword can be ambiguous and should be avoided')
+
+ with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
+ conf.write('server=1\nrpcuser=someuser\n[main]\nrpcpassword=some#pass')
+ self.nodes[0].assert_start_raises_init_error(expected_msg='Error reading configuration file: parse error on line 4, using # in rpcpassword can be ambiguous and should be avoided')
+
+ with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
conf.write('testnot.datadir=1\n[testnet]\n')
self.restart_node(0)
self.nodes[0].stop_node(expected_stderr='Warning: Section [testnet] is not recognized.' + os.linesep + 'Warning: Section [testnot] is not recognized.')
diff --git a/test/functional/feature_dbcrash.py b/test/functional/feature_dbcrash.py
index 70d67aa53a..8b06cc7372 100755
--- a/test/functional/feature_dbcrash.py
+++ b/test/functional/feature_dbcrash.py
@@ -46,7 +46,7 @@ class ChainstateWriteCrashTest(BitcoinTestFramework):
self.num_nodes = 4
self.setup_clean_chain = False
# Need a bit of extra time for the nodes to start up for this test
- self.rpc_timewait = 90
+ self.rpc_timeout = 90
# Set -maxmempool=0 to turn off mempool memory sharing with dbcache
# Set -rpcservertimeout=900 to reduce socket disconnects in this
diff --git a/test/functional/feature_pruning.py b/test/functional/feature_pruning.py
index c162f46d63..9a3f4fae45 100755
--- a/test/functional/feature_pruning.py
+++ b/test/functional/feature_pruning.py
@@ -29,7 +29,7 @@ class PruneTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 6
- self.rpc_timewait = 900
+ self.rpc_timeout = 900
# Create nodes 0 and 1 to mine.
# Create node 2 to test pruning.
@@ -191,6 +191,8 @@ class PruneTest(BitcoinTestFramework):
def reorg_back(self):
# Verify that a block on the old main chain fork has been pruned away
assert_raises_rpc_error(-1, "Block not available (pruned data)", self.nodes[2].getblock, self.forkhash)
+ with self.nodes[2].assert_debug_log(expected_msgs=['block verification stopping at height', '(pruning, no data)']):
+ self.nodes[2].verifychain(checklevel=4, nblocks=0)
self.log.info("Will need to redownload block %d" % self.forkheight)
# Verify that we have enough history to reorg back to the fork point
diff --git a/test/functional/mempool_accept.py b/test/functional/mempool_accept.py
index 02f1cc4391..e2a219b85a 100755
--- a/test/functional/mempool_accept.py
+++ b/test/functional/mempool_accept.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2017 The Bitcoin Core developers
+# Copyright (c) 2017-2018 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test mempool acceptance of raw transactions."""
diff --git a/test/functional/p2p_invalid_locator.py b/test/functional/p2p_invalid_locator.py
index c8c752d1f7..33b7060060 100755
--- a/test/functional/p2p_invalid_locator.py
+++ b/test/functional/p2p_invalid_locator.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-# Copyright (c) 2015-2017 The Bitcoin Core developers
+# Copyright (c) 2015-2018 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test node responses to invalid locators.
diff --git a/test/functional/p2p_invalid_tx.py b/test/functional/p2p_invalid_tx.py
index 58e129b57d..1b18dd3e58 100755
--- a/test/functional/p2p_invalid_tx.py
+++ b/test/functional/p2p_invalid_tx.py
@@ -5,7 +5,7 @@
"""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_tx_with_script
+from test_framework.blocktools import create_block, create_coinbase
from test_framework.messages import (
COIN,
COutPoint,
@@ -19,6 +19,7 @@ from test_framework.util import (
assert_equal,
wait_until,
)
+from data import invalid_txs
class InvalidTxRequestTest(BitcoinTestFramework):
@@ -63,12 +64,21 @@ class InvalidTxRequestTest(BitcoinTestFramework):
self.log.info("Mature the block.")
self.nodes[0].generatetoaddress(100, self.nodes[0].get_deterministic_priv_key().address)
- # b'\x64' is OP_NOTIF
- # Transaction will be rejected with code 16 (REJECT_INVALID)
- # and we get disconnected immediately
- self.log.info('Test a transaction that is rejected')
- tx1 = create_tx_with_script(block1.vtx[0], 0, script_sig=b'\x64' * 35, amount=50 * COIN - 12000)
- node.p2p.send_txs_and_test([tx1], node, success=False, expect_disconnect=True)
+ # Iterate through a list of known invalid transaction types, ensuring each is
+ # rejected. Some are consensus invalid and some just violate policy.
+ for BadTxTemplate in invalid_txs.iter_all_templates():
+ self.log.info("Testing invalid transaction: %s", BadTxTemplate.__name__)
+ template = BadTxTemplate(spend_block=block1)
+ tx = template.get_tx()
+ node.p2p.send_txs_and_test(
+ [tx], node, success=False,
+ expect_disconnect=template.expect_disconnect,
+ reject_reason=template.reject_reason,
+ )
+
+ if template.expect_disconnect:
+ self.log.info("Reconnecting to peer")
+ self.reconnect_p2p()
# Make two p2p connections to provide the node with orphans
# * p2ps[0] will send valid orphan txs (one with low fee)
diff --git a/test/functional/rpc_bind.py b/test/functional/rpc_bind.py
index c23aa13685..3938ca98dd 100755
--- a/test/functional/rpc_bind.py
+++ b/test/functional/rpc_bind.py
@@ -70,7 +70,7 @@ class RPCBindTest(BitcoinTestFramework):
self.log.info("Check for ipv6")
have_ipv6 = test_ipv6_local()
- if not have_ipv6 and not self.options.run_ipv4:
+ if not have_ipv6 and not (self.options.run_ipv4 or self.options.run_nonloopback):
raise SkipTest("This test requires ipv6 support.")
self.log.info("Check for non-loopback interface")
diff --git a/test/functional/rpc_fundrawtransaction.py b/test/functional/rpc_fundrawtransaction.py
index 0c61e9ab62..4f350953b2 100755
--- a/test/functional/rpc_fundrawtransaction.py
+++ b/test/functional/rpc_fundrawtransaction.py
@@ -32,7 +32,7 @@ class RawTransactionsTest(BitcoinTestFramework):
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
- def setup_network(self, split=False):
+ def setup_network(self):
self.setup_nodes()
connect_nodes_bi(self.nodes, 0, 1)
diff --git a/test/functional/rpc_invalidateblock.py b/test/functional/rpc_invalidateblock.py
index d8ecdd573a..d8a1deb2a3 100755
--- a/test/functional/rpc_invalidateblock.py
+++ b/test/functional/rpc_invalidateblock.py
@@ -4,10 +4,15 @@
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the invalidateblock RPC."""
-import time
-
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import assert_equal, connect_nodes_bi, sync_blocks
+from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE
+from test_framework.util import (
+ assert_equal,
+ connect_nodes_bi,
+ sync_blocks,
+ wait_until,
+)
+
class InvalidateTest(BitcoinTestFramework):
def set_test_params(self):
@@ -21,46 +26,66 @@ class InvalidateTest(BitcoinTestFramework):
self.log.info("Make sure we repopulate setBlockIndexCandidates after InvalidateBlock:")
self.log.info("Mine 4 blocks on Node 0")
self.nodes[0].generatetoaddress(4, self.nodes[0].get_deterministic_priv_key().address)
- assert(self.nodes[0].getblockcount() == 4)
- besthash = self.nodes[0].getbestblockhash()
+ assert_equal(self.nodes[0].getblockcount(), 4)
+ besthash_n0 = self.nodes[0].getbestblockhash()
self.log.info("Mine competing 6 blocks on Node 1")
self.nodes[1].generatetoaddress(6, self.nodes[1].get_deterministic_priv_key().address)
- assert(self.nodes[1].getblockcount() == 6)
+ assert_equal(self.nodes[1].getblockcount(), 6)
self.log.info("Connect nodes to force a reorg")
- connect_nodes_bi(self.nodes,0,1)
+ connect_nodes_bi(self.nodes, 0, 1)
sync_blocks(self.nodes[0:2])
- assert(self.nodes[0].getblockcount() == 6)
+ assert_equal(self.nodes[0].getblockcount(), 6)
badhash = self.nodes[1].getblockhash(2)
self.log.info("Invalidate block 2 on node 0 and verify we reorg to node 0's original chain")
self.nodes[0].invalidateblock(badhash)
- newheight = self.nodes[0].getblockcount()
- newhash = self.nodes[0].getbestblockhash()
- if (newheight != 4 or newhash != besthash):
- raise AssertionError("Wrong tip for node0, hash %s, height %d"%(newhash,newheight))
+ assert_equal(self.nodes[0].getblockcount(), 4)
+ assert_equal(self.nodes[0].getbestblockhash(), besthash_n0)
self.log.info("Make sure we won't reorg to a lower work chain:")
- connect_nodes_bi(self.nodes,1,2)
+ connect_nodes_bi(self.nodes, 1, 2)
self.log.info("Sync node 2 to node 1 so both have 6 blocks")
sync_blocks(self.nodes[1:3])
- assert(self.nodes[2].getblockcount() == 6)
+ assert_equal(self.nodes[2].getblockcount(), 6)
self.log.info("Invalidate block 5 on node 1 so its tip is now at 4")
self.nodes[1].invalidateblock(self.nodes[1].getblockhash(5))
- assert(self.nodes[1].getblockcount() == 4)
+ assert_equal(self.nodes[1].getblockcount(), 4)
self.log.info("Invalidate block 3 on node 2, so its tip is now 2")
self.nodes[2].invalidateblock(self.nodes[2].getblockhash(3))
- assert(self.nodes[2].getblockcount() == 2)
+ assert_equal(self.nodes[2].getblockcount(), 2)
self.log.info("..and then mine a block")
self.nodes[2].generatetoaddress(1, self.nodes[2].get_deterministic_priv_key().address)
self.log.info("Verify all nodes are at the right height")
- time.sleep(5)
- assert_equal(self.nodes[2].getblockcount(), 3)
- assert_equal(self.nodes[0].getblockcount(), 4)
- node1height = self.nodes[1].getblockcount()
- if node1height < 4:
- raise AssertionError("Node 1 reorged to a lower height: %d"%node1height)
+ wait_until(lambda: self.nodes[2].getblockcount() == 3, timeout=5)
+ wait_until(lambda: self.nodes[0].getblockcount() == 4, timeout=5)
+ wait_until(lambda: self.nodes[1].getblockcount() == 4, timeout=5)
+
+ self.log.info("Verify that we reconsider all ancestors as well")
+ blocks = self.nodes[1].generatetoaddress(10, ADDRESS_BCRT1_UNSPENDABLE)
+ assert_equal(self.nodes[1].getbestblockhash(), blocks[-1])
+ # Invalidate the two blocks at the tip
+ self.nodes[1].invalidateblock(blocks[-1])
+ self.nodes[1].invalidateblock(blocks[-2])
+ assert_equal(self.nodes[1].getbestblockhash(), blocks[-3])
+ # Reconsider only the previous tip
+ self.nodes[1].reconsiderblock(blocks[-1])
+ # Should be back at the tip by now
+ assert_equal(self.nodes[1].getbestblockhash(), blocks[-1])
+
+ self.log.info("Verify that we reconsider all descendants")
+ blocks = self.nodes[1].generatetoaddress(10, ADDRESS_BCRT1_UNSPENDABLE)
+ assert_equal(self.nodes[1].getbestblockhash(), blocks[-1])
+ # Invalidate the two blocks at the tip
+ self.nodes[1].invalidateblock(blocks[-2])
+ self.nodes[1].invalidateblock(blocks[-4])
+ assert_equal(self.nodes[1].getbestblockhash(), blocks[-5])
+ # Reconsider only the previous tip
+ self.nodes[1].reconsiderblock(blocks[-4])
+ # Should be back at the tip by now
+ assert_equal(self.nodes[1].getbestblockhash(), blocks[-1])
+
if __name__ == '__main__':
InvalidateTest().main()
diff --git a/test/functional/rpc_net.py b/test/functional/rpc_net.py
index 0affddcf05..b12eb1d9ec 100755
--- a/test/functional/rpc_net.py
+++ b/test/functional/rpc_net.py
@@ -67,8 +67,8 @@ class NetTest(BitcoinTestFramework):
peer_info_after_ping = self.nodes[0].getpeerinfo()
for before, after in zip(peer_info, peer_info_after_ping):
- assert_greater_than_or_equal(after['bytesrecv_per_msg']['pong'], before['bytesrecv_per_msg']['pong'] + 32)
- assert_greater_than_or_equal(after['bytessent_per_msg']['ping'], before['bytessent_per_msg']['ping'] + 32)
+ assert_greater_than_or_equal(after['bytesrecv_per_msg'].get('pong', 0), before['bytesrecv_per_msg'].get('pong', 0) + 32)
+ assert_greater_than_or_equal(after['bytessent_per_msg'].get('ping', 0), before['bytessent_per_msg'].get('ping', 0) + 32)
def _test_getnetworkinginfo(self):
assert_equal(self.nodes[0].getnetworkinfo()['networkactive'], True)
diff --git a/test/functional/rpc_rawtransaction.py b/test/functional/rpc_rawtransaction.py
index fc012e6e3a..5b9dbef68d 100755
--- a/test/functional/rpc_rawtransaction.py
+++ b/test/functional/rpc_rawtransaction.py
@@ -47,7 +47,7 @@ class RawTransactionsTest(BitcoinTestFramework):
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
- def setup_network(self, split=False):
+ def setup_network(self):
super().setup_network()
connect_nodes_bi(self.nodes, 0, 2)
diff --git a/test/functional/test_framework/blocktools.py b/test/functional/test_framework/blocktools.py
index 81cce1167b..6b47cae4c3 100644
--- a/test/functional/test_framework/blocktools.py
+++ b/test/functional/test_framework/blocktools.py
@@ -41,12 +41,15 @@ from .script import (
from .util import assert_equal
from io import BytesIO
+MAX_BLOCK_SIGOPS = 20000
+
# From BIP141
WITNESS_COMMITMENT_HEADER = b"\xaa\x21\xa9\xed"
-def create_block(hashprev, coinbase, ntime=None):
+def create_block(hashprev, coinbase, ntime=None, *, version=1):
"""Create a block (with regtest difficulty)."""
block = CBlock()
+ block.nVersion = version
if ntime is None:
import time
block.nTime = int(time.time() + 600)
diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py
index 21bf35597e..352fa32b5b 100755
--- a/test/functional/test_framework/test_framework.py
+++ b/test/functional/test_framework/test_framework.py
@@ -95,7 +95,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
self.nodes = []
self.network_thread = None
self.mocktime = 0
- self.rpc_timewait = 60 # Wait for up to 60 seconds for the RPC server to respond
+ self.rpc_timeout = 60 # Wait for up to 60 seconds for the RPC server to respond
self.supports_cli = False
self.bind_to_localhost_only = True
self.set_test_params()
@@ -301,7 +301,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
i,
get_datadir_path(self.options.tmpdir, i),
rpchost=rpchost,
- timewait=self.rpc_timewait,
+ timewait=self.rpc_timeout,
bitcoind=binary[i],
bitcoin_cli=self.options.bitcoincli,
mocktime=self.mocktime,
@@ -388,21 +388,6 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
sync_blocks(group)
sync_mempools(group)
- def enable_mocktime(self):
- """Enable mocktime for the script.
-
- mocktime may be needed for scripts that use the cached version of the
- blockchain. If the cached version of the blockchain is used without
- mocktime then the mempools will not sync due to IBD.
-
- For backward compatibility of the python scripts with previous
- versions of the cache, this helper function sets mocktime to Jan 1,
- 2014 + (201 * 10 * 60)"""
- self.mocktime = 1388534400 + (201 * 10 * 60)
-
- def disable_mocktime(self):
- self.mocktime = 0
-
# Private helper methods. These should not be accessed by the subclass test scripts.
def _start_logging(self):
@@ -460,7 +445,18 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
args = [self.options.bitcoind, "-datadir=" + datadir, '-disablewallet']
if i > 0:
args.append("-connect=127.0.0.1:" + str(p2p_port(0)))
- self.nodes.append(TestNode(i, get_datadir_path(self.options.cachedir, i), extra_conf=["bind=127.0.0.1"], extra_args=[], rpchost=None, timewait=self.rpc_timewait, bitcoind=self.options.bitcoind, bitcoin_cli=self.options.bitcoincli, mocktime=self.mocktime, coverage_dir=None))
+ self.nodes.append(TestNode(
+ i,
+ get_datadir_path(self.options.cachedir, i),
+ extra_conf=["bind=127.0.0.1"],
+ extra_args=[],
+ rpchost=None,
+ timewait=self.rpc_timeout,
+ bitcoind=self.options.bitcoind,
+ bitcoin_cli=self.options.bitcoincli,
+ mocktime=self.mocktime,
+ coverage_dir=None,
+ ))
self.nodes[i].args = args
self.start_node(i)
@@ -468,6 +464,11 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
for node in self.nodes:
node.wait_for_rpc_connection()
+ # For backward compatibility of the python scripts with previous
+ # versions of the cache, set mocktime to Jan 1,
+ # 2014 + (201 * 10 * 60)"""
+ self.mocktime = 1388534400 + (201 * 10 * 60)
+
# Create a 200-block-long chain; each of the 4 first nodes
# gets 25 mature blocks and 25 immature.
# Note: To preserve compatibility with older versions of
@@ -475,7 +476,6 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
#
# blocks are created with timestamps 10 minutes apart
# starting from 2010 minutes in the past
- self.enable_mocktime()
block_time = self.mocktime - (201 * 10 * 60)
for i in range(2):
for peer in range(4):
@@ -489,7 +489,7 @@ class BitcoinTestFramework(metaclass=BitcoinTestMetaClass):
# Shut them down, and clean up cache directories:
self.stop_nodes()
self.nodes = []
- self.disable_mocktime()
+ self.mocktime = 0
def cache_path(n, *paths):
return os.path.join(get_datadir_path(self.options.cachedir, n), "regtest", *paths)
diff --git a/test/functional/test_framework/wallet_util.py b/test/functional/test_framework/wallet_util.py
new file mode 100755
index 0000000000..c0dfa4c3f0
--- /dev/null
+++ b/test/functional/test_framework/wallet_util.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python3
+# Copyright (c) 2018 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Useful util functions for testing the wallet"""
+from collections import namedtuple
+
+from test_framework.address import (
+ key_to_p2pkh,
+ key_to_p2sh_p2wpkh,
+ key_to_p2wpkh,
+ script_to_p2sh,
+ script_to_p2sh_p2wsh,
+ script_to_p2wsh,
+)
+from test_framework.script import (
+ CScript,
+ OP_0,
+ OP_2,
+ OP_3,
+ OP_CHECKMULTISIG,
+ OP_CHECKSIG,
+ OP_DUP,
+ OP_EQUAL,
+ OP_EQUALVERIFY,
+ OP_HASH160,
+ hash160,
+ sha256,
+)
+from test_framework.util import hex_str_to_bytes
+
+Key = namedtuple('Key', ['privkey',
+ 'pubkey',
+ 'p2pkh_script',
+ 'p2pkh_addr',
+ 'p2wpkh_script',
+ 'p2wpkh_addr',
+ 'p2sh_p2wpkh_script',
+ 'p2sh_p2wpkh_redeem_script',
+ 'p2sh_p2wpkh_addr'])
+
+Multisig = namedtuple('Multisig', ['privkeys',
+ 'pubkeys',
+ 'p2sh_script',
+ 'p2sh_addr',
+ 'redeem_script',
+ 'p2wsh_script',
+ 'p2wsh_addr',
+ 'p2sh_p2wsh_script',
+ 'p2sh_p2wsh_addr'])
+
+def get_key(node):
+ """Generate a fresh key on node
+
+ Returns a named tuple of privkey, pubkey and all address and scripts."""
+ addr = node.getnewaddress()
+ pubkey = node.getaddressinfo(addr)['pubkey']
+ pkh = hash160(hex_str_to_bytes(pubkey))
+ return Key(privkey=node.dumpprivkey(addr),
+ pubkey=pubkey,
+ p2pkh_script=CScript([OP_DUP, OP_HASH160, pkh, OP_EQUALVERIFY, OP_CHECKSIG]).hex(),
+ p2pkh_addr=key_to_p2pkh(pubkey),
+ p2wpkh_script=CScript([OP_0, pkh]).hex(),
+ p2wpkh_addr=key_to_p2wpkh(pubkey),
+ p2sh_p2wpkh_script=CScript([OP_HASH160, hash160(CScript([OP_0, pkh])), OP_EQUAL]).hex(),
+ p2sh_p2wpkh_redeem_script=CScript([OP_0, pkh]).hex(),
+ p2sh_p2wpkh_addr=key_to_p2sh_p2wpkh(pubkey))
+
+def get_multisig(node):
+ """Generate a fresh 2-of-3 multisig on node
+
+ Returns a named tuple of privkeys, pubkeys and all address and scripts."""
+ addrs = []
+ pubkeys = []
+ for _ in range(3):
+ addr = node.getaddressinfo(node.getnewaddress())
+ addrs.append(addr['address'])
+ pubkeys.append(addr['pubkey'])
+ script_code = CScript([OP_2] + [hex_str_to_bytes(pubkey) for pubkey in pubkeys] + [OP_3, OP_CHECKMULTISIG])
+ witness_script = CScript([OP_0, sha256(script_code)])
+ return Multisig(privkeys=[node.dumpprivkey(addr) for addr in addrs],
+ pubkeys=pubkeys,
+ p2sh_script=CScript([OP_HASH160, hash160(script_code), OP_EQUAL]).hex(),
+ p2sh_addr=script_to_p2sh(script_code),
+ redeem_script=script_code.hex(),
+ p2wsh_script=witness_script.hex(),
+ p2wsh_addr=script_to_p2wsh(script_code),
+ p2sh_p2wsh_script=CScript([OP_HASH160, witness_script, OP_EQUAL]).hex(),
+ p2sh_p2wsh_addr=script_to_p2sh_p2wsh(script_code))
+
+def test_address(node, address, **kwargs):
+ """Get address info for `address` and test whether the returned values are as expected."""
+ addr_info = node.getaddressinfo(address)
+ for key, value in kwargs.items():
+ if value is None:
+ if key in addr_info.keys():
+ raise AssertionError("key {} unexpectedly returned in getaddressinfo.".format(key))
+ elif addr_info[key] != value:
+ raise AssertionError("key {} value {} did not match expected value {}".format(key, addr_info[key], value))
diff --git a/test/functional/wallet_backup.py b/test/functional/wallet_backup.py
index 32ec385fa1..dd3750203a 100755
--- a/test/functional/wallet_backup.py
+++ b/test/functional/wallet_backup.py
@@ -48,7 +48,7 @@ class WalletBackupTest(BitcoinTestFramework):
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
- def setup_network(self, split=False):
+ def setup_network(self):
self.setup_nodes()
connect_nodes(self.nodes[0], 3)
connect_nodes(self.nodes[1], 3)
diff --git a/test/functional/wallet_dump.py b/test/functional/wallet_dump.py
index 20cb816ee8..3f39654bb8 100755
--- a/test/functional/wallet_dump.py
+++ b/test/functional/wallet_dump.py
@@ -94,7 +94,7 @@ class WalletDumpTest(BitcoinTestFramework):
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
- def setup_network(self, split=False):
+ def setup_network(self):
self.add_nodes(self.num_nodes, extra_args=self.extra_args)
self.start_nodes()
diff --git a/test/functional/wallet_groups.py b/test/functional/wallet_groups.py
index 9d61483868..5452433acf 100755
--- a/test/functional/wallet_groups.py
+++ b/test/functional/wallet_groups.py
@@ -21,7 +21,7 @@ class WalletGroupTest(BitcoinTestFramework):
self.setup_clean_chain = True
self.num_nodes = 3
self.extra_args = [[], [], ['-avoidpartialspends']]
- self.rpc_timewait = 120
+ self.rpc_timeout = 120
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
diff --git a/test/functional/wallet_import_with_label.py b/test/functional/wallet_import_with_label.py
index 95acaa752e..a623b75606 100755
--- a/test/functional/wallet_import_with_label.py
+++ b/test/functional/wallet_import_with_label.py
@@ -11,7 +11,7 @@ with and without a label.
"""
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import assert_equal
+from test_framework.wallet_util import test_address
class ImportWithLabel(BitcoinTestFramework):
@@ -32,11 +32,11 @@ class ImportWithLabel(BitcoinTestFramework):
address = self.nodes[0].getnewaddress()
label = "Test Label"
self.nodes[1].importaddress(address, label)
- address_assert = self.nodes[1].getaddressinfo(address)
-
- assert_equal(address_assert["iswatchonly"], True)
- assert_equal(address_assert["ismine"], False)
- assert_equal(address_assert["label"], label)
+ test_address(self.nodes[1],
+ address,
+ iswatchonly=True,
+ ismine=False,
+ label=label)
self.log.info(
"Import the watch-only address's private key without a "
@@ -45,7 +45,9 @@ class ImportWithLabel(BitcoinTestFramework):
priv_key = self.nodes[0].dumpprivkey(address)
self.nodes[1].importprivkey(priv_key)
- assert_equal(label, self.nodes[1].getaddressinfo(address)["label"])
+ test_address(self.nodes[1],
+ address,
+ label=label)
self.log.info(
"Test importaddress without label and importprivkey with label."
@@ -53,11 +55,11 @@ class ImportWithLabel(BitcoinTestFramework):
self.log.info("Import a watch-only address without a label.")
address2 = self.nodes[0].getnewaddress()
self.nodes[1].importaddress(address2)
- address_assert2 = self.nodes[1].getaddressinfo(address2)
-
- assert_equal(address_assert2["iswatchonly"], True)
- assert_equal(address_assert2["ismine"], False)
- assert_equal(address_assert2["label"], "")
+ test_address(self.nodes[1],
+ address2,
+ iswatchonly=True,
+ ismine=False,
+ label="")
self.log.info(
"Import the watch-only address's private key with a "
@@ -67,18 +69,20 @@ class ImportWithLabel(BitcoinTestFramework):
label2 = "Test Label 2"
self.nodes[1].importprivkey(priv_key2, label2)
- assert_equal(label2, self.nodes[1].getaddressinfo(address2)["label"])
+ test_address(self.nodes[1],
+ address2,
+ label=label2)
self.log.info("Test importaddress with label and importprivkey with label.")
self.log.info("Import a watch-only address with a label.")
address3 = self.nodes[0].getnewaddress()
label3_addr = "Test Label 3 for importaddress"
self.nodes[1].importaddress(address3, label3_addr)
- address_assert3 = self.nodes[1].getaddressinfo(address3)
-
- assert_equal(address_assert3["iswatchonly"], True)
- assert_equal(address_assert3["ismine"], False)
- assert_equal(address_assert3["label"], label3_addr)
+ test_address(self.nodes[1],
+ address3,
+ iswatchonly=True,
+ ismine=False,
+ label=label3_addr)
self.log.info(
"Import the watch-only address's private key with a "
@@ -88,7 +92,9 @@ class ImportWithLabel(BitcoinTestFramework):
label3_priv = "Test Label 3 for importprivkey"
self.nodes[1].importprivkey(priv_key3, label3_priv)
- assert_equal(label3_priv, self.nodes[1].getaddressinfo(address3)["label"])
+ test_address(self.nodes[1],
+ address3,
+ label=label3_priv)
self.log.info(
"Test importprivkey won't label new dests with the same "
@@ -98,15 +104,12 @@ class ImportWithLabel(BitcoinTestFramework):
address4 = self.nodes[0].getnewaddress()
label4_addr = "Test Label 4 for importaddress"
self.nodes[1].importaddress(address4, label4_addr)
- address_assert4 = self.nodes[1].getaddressinfo(address4)
-
- assert_equal(address_assert4["iswatchonly"], True)
- assert_equal(address_assert4["ismine"], False)
- assert_equal(address_assert4["label"], label4_addr)
-
- self.log.info("Asserts address has no embedded field with dests.")
-
- assert_equal(address_assert4.get("embedded"), None)
+ test_address(self.nodes[1],
+ address4,
+ iswatchonly=True,
+ ismine=False,
+ label=label4_addr,
+ embedded=None)
self.log.info(
"Import the watch-only address's private key without a "
@@ -116,16 +119,14 @@ class ImportWithLabel(BitcoinTestFramework):
)
priv_key4 = self.nodes[0].dumpprivkey(address4)
self.nodes[1].importprivkey(priv_key4)
- address_assert4 = self.nodes[1].getaddressinfo(address4)
-
- assert address_assert4.get("embedded")
-
- bcaddress_assert = self.nodes[1].getaddressinfo(
- address_assert4["embedded"]["address"]
- )
-
- assert_equal(address_assert4["label"], label4_addr)
- assert_equal(bcaddress_assert["label"], "")
+ embedded_addr = self.nodes[1].getaddressinfo(address4)['embedded']['address']
+
+ test_address(self.nodes[1],
+ embedded_addr,
+ label="")
+ test_address(self.nodes[1],
+ address4,
+ label=label4_addr)
self.stop_nodes()
diff --git a/test/functional/wallet_importmulti.py b/test/functional/wallet_importmulti.py
index a163f7018c..f122f19e3a 100755
--- a/test/functional/wallet_importmulti.py
+++ b/test/functional/wallet_importmulti.py
@@ -14,30 +14,10 @@ variants.
success, and (if unsuccessful) test the error code and error message returned.
- `test_address()` is called to call getaddressinfo for an address on node1
and test the values returned."""
-from collections import namedtuple
-
-from test_framework.address import (
- key_to_p2pkh,
- key_to_p2sh_p2wpkh,
- key_to_p2wpkh,
- script_to_p2sh,
- script_to_p2sh_p2wsh,
- script_to_p2wsh,
-)
+
from test_framework.script import (
CScript,
- OP_0,
- OP_2,
- OP_3,
- OP_CHECKMULTISIG,
- OP_CHECKSIG,
- OP_DUP,
- OP_EQUAL,
- OP_EQUALVERIFY,
- OP_HASH160,
OP_NOP,
- hash160,
- sha256,
)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
@@ -45,28 +25,12 @@ from test_framework.util import (
assert_greater_than,
assert_raises_rpc_error,
bytes_to_hex_str,
- hex_str_to_bytes
)
-
-Key = namedtuple('Key', ['privkey',
- 'pubkey',
- 'p2pkh_script',
- 'p2pkh_addr',
- 'p2wpkh_script',
- 'p2wpkh_addr',
- 'p2sh_p2wpkh_script',
- 'p2sh_p2wpkh_redeem_script',
- 'p2sh_p2wpkh_addr'])
-
-Multisig = namedtuple('Multisig', ['privkeys',
- 'pubkeys',
- 'p2sh_script',
- 'p2sh_addr',
- 'redeem_script',
- 'p2wsh_script',
- 'p2wsh_addr',
- 'p2sh_p2wsh_script',
- 'p2sh_p2wsh_addr'])
+from test_framework.wallet_util import (
+ get_key,
+ get_multisig,
+ test_address,
+)
class ImportMultiTest(BitcoinTestFramework):
def set_test_params(self):
@@ -80,63 +44,18 @@ class ImportMultiTest(BitcoinTestFramework):
def setup_network(self):
self.setup_nodes()
- def get_key(self):
- """Generate a fresh key on node0
-
- Returns a named tuple of privkey, pubkey and all address and scripts."""
- addr = self.nodes[0].getnewaddress()
- pubkey = self.nodes[0].getaddressinfo(addr)['pubkey']
- pkh = hash160(hex_str_to_bytes(pubkey))
- return Key(self.nodes[0].dumpprivkey(addr),
- pubkey,
- CScript([OP_DUP, OP_HASH160, pkh, OP_EQUALVERIFY, OP_CHECKSIG]).hex(), # p2pkh
- key_to_p2pkh(pubkey), # p2pkh addr
- CScript([OP_0, pkh]).hex(), # p2wpkh
- key_to_p2wpkh(pubkey), # p2wpkh addr
- CScript([OP_HASH160, hash160(CScript([OP_0, pkh])), OP_EQUAL]).hex(), # p2sh-p2wpkh
- CScript([OP_0, pkh]).hex(), # p2sh-p2wpkh redeem script
- key_to_p2sh_p2wpkh(pubkey)) # p2sh-p2wpkh addr
-
- def get_multisig(self):
- """Generate a fresh multisig on node0
-
- Returns a named tuple of privkeys, pubkeys and all address and scripts."""
- addrs = []
- pubkeys = []
- for _ in range(3):
- addr = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())
- addrs.append(addr['address'])
- pubkeys.append(addr['pubkey'])
- script_code = CScript([OP_2] + [hex_str_to_bytes(pubkey) for pubkey in pubkeys] + [OP_3, OP_CHECKMULTISIG])
- witness_script = CScript([OP_0, sha256(script_code)])
- return Multisig([self.nodes[0].dumpprivkey(addr) for addr in addrs],
- pubkeys,
- CScript([OP_HASH160, hash160(script_code), OP_EQUAL]).hex(), # p2sh
- script_to_p2sh(script_code), # p2sh addr
- script_code.hex(), # redeem script
- witness_script.hex(), # p2wsh
- script_to_p2wsh(script_code), # p2wsh addr
- CScript([OP_HASH160, witness_script, OP_EQUAL]).hex(), # p2sh-p2wsh
- script_to_p2sh_p2wsh(script_code)) # p2sh-p2wsh addr
-
- def test_importmulti(self, req, success, error_code=None, error_message=None):
+ def test_importmulti(self, req, success, error_code=None, error_message=None, warnings=[]):
"""Run importmulti and assert success"""
result = self.nodes[1].importmulti([req])
+ observed_warnings = []
+ if 'warnings' in result[0]:
+ observed_warnings = result[0]['warnings']
+ assert_equal("\n".join(sorted(warnings)), "\n".join(sorted(observed_warnings)))
assert_equal(result[0]['success'], success)
if error_code is not None:
assert_equal(result[0]['error']['code'], error_code)
assert_equal(result[0]['error']['message'], error_message)
- def test_address(self, address, **kwargs):
- """Get address info for `address` and test whether the returned values are as expected."""
- addr_info = self.nodes[1].getaddressinfo(address)
- for key, value in kwargs.items():
- if value is None:
- if key in addr_info.keys():
- raise AssertionError("key {} unexpectedly returned in getaddressinfo.".format(key))
- elif addr_info[key] != value:
- raise AssertionError("key {} value {} did not match expected value {}".format(key, addr_info[key], value))
-
def run_test(self):
self.log.info("Mining blocks...")
self.nodes[0].generate(1)
@@ -160,176 +79,178 @@ class ImportMultiTest(BitcoinTestFramework):
# Bitcoin Address (implicit non-internal)
self.log.info("Should import an address")
- key = self.get_key()
- address = key.p2pkh_addr
- self.test_importmulti({"scriptPubKey": {"address": address},
+ key = get_key(self.nodes[0])
+ self.test_importmulti({"scriptPubKey": {"address": key.p2pkh_addr},
"timestamp": "now"},
- True)
- self.test_address(address,
- iswatchonly=True,
- ismine=False,
- timestamp=timestamp,
- ischange=False)
- watchonly_address = address
+ success=True)
+ test_address(self.nodes[1],
+ key.p2pkh_addr,
+ iswatchonly=True,
+ ismine=False,
+ timestamp=timestamp,
+ ischange=False)
+ watchonly_address = key.p2pkh_addr
watchonly_timestamp = timestamp
self.log.info("Should not import an invalid address")
self.test_importmulti({"scriptPubKey": {"address": "not valid address"},
"timestamp": "now"},
- False,
+ success=False,
error_code=-5,
- error_message='Invalid address')
+ error_message='Invalid address \"not valid address\"')
# ScriptPubKey + internal
self.log.info("Should import a scriptPubKey with internal flag")
- key = self.get_key()
+ key = get_key(self.nodes[0])
self.test_importmulti({"scriptPubKey": key.p2pkh_script,
"timestamp": "now",
"internal": True},
- True)
- self.test_address(key.p2pkh_addr,
- iswatchonly=True,
- ismine=False,
- timestamp=timestamp,
- ischange=True)
+ success=True)
+ test_address(self.nodes[1],
+ key.p2pkh_addr,
+ iswatchonly=True,
+ ismine=False,
+ timestamp=timestamp,
+ ischange=True)
# ScriptPubKey + internal + label
self.log.info("Should not allow a label to be specified when internal is true")
- key = self.get_key()
+ key = get_key(self.nodes[0])
self.test_importmulti({"scriptPubKey": key.p2pkh_script,
"timestamp": "now",
"internal": True,
"label": "Example label"},
- False,
+ success=False,
error_code=-8,
error_message='Internal addresses should not have a label')
# Nonstandard scriptPubKey + !internal
self.log.info("Should not import a nonstandard scriptPubKey without internal flag")
nonstandardScriptPubKey = key.p2pkh_script + bytes_to_hex_str(CScript([OP_NOP]))
- key = self.get_key()
- address = key.p2pkh_addr
+ key = get_key(self.nodes[0])
self.test_importmulti({"scriptPubKey": nonstandardScriptPubKey,
"timestamp": "now"},
- False,
+ success=False,
error_code=-8,
error_message='Internal must be set to true for nonstandard scriptPubKey imports.')
- self.test_address(address,
- iswatchonly=False,
- ismine=False,
- timestamp=None)
+ test_address(self.nodes[1],
+ key.p2pkh_addr,
+ iswatchonly=False,
+ ismine=False,
+ timestamp=None)
# Address + Public key + !Internal(explicit)
self.log.info("Should import an address with public key")
- key = self.get_key()
- address = key.p2pkh_addr
- self.test_importmulti({"scriptPubKey": {"address": address},
+ key = get_key(self.nodes[0])
+ self.test_importmulti({"scriptPubKey": {"address": key.p2pkh_addr},
"timestamp": "now",
"pubkeys": [key.pubkey],
"internal": False},
- True)
- self.test_address(address,
- iswatchonly=True,
- ismine=False,
- timestamp=timestamp)
+ success=True,
+ warnings=["Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."])
+ test_address(self.nodes[1],
+ key.p2pkh_addr,
+ iswatchonly=True,
+ ismine=False,
+ timestamp=timestamp)
# ScriptPubKey + Public key + internal
self.log.info("Should import a scriptPubKey with internal and with public key")
- key = self.get_key()
- address = key.p2pkh_addr
+ key = get_key(self.nodes[0])
self.test_importmulti({"scriptPubKey": key.p2pkh_script,
"timestamp": "now",
"pubkeys": [key.pubkey],
"internal": True},
- True)
- self.test_address(address,
- iswatchonly=True,
- ismine=False,
- timestamp=timestamp)
+ success=True,
+ warnings=["Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."])
+ test_address(self.nodes[1],
+ key.p2pkh_addr,
+ iswatchonly=True,
+ ismine=False,
+ timestamp=timestamp)
# Nonstandard scriptPubKey + Public key + !internal
self.log.info("Should not import a nonstandard scriptPubKey without internal and with public key")
- key = self.get_key()
- address = key.p2pkh_addr
+ key = get_key(self.nodes[0])
self.test_importmulti({"scriptPubKey": nonstandardScriptPubKey,
"timestamp": "now",
"pubkeys": [key.pubkey]},
- False,
+ success=False,
error_code=-8,
error_message='Internal must be set to true for nonstandard scriptPubKey imports.')
- self.test_address(address,
- iswatchonly=False,
- ismine=False,
- timestamp=None)
+ test_address(self.nodes[1],
+ key.p2pkh_addr,
+ iswatchonly=False,
+ ismine=False,
+ timestamp=None)
# Address + Private key + !watchonly
self.log.info("Should import an address with private key")
- key = self.get_key()
- address = key.p2pkh_addr
- self.test_importmulti({"scriptPubKey": {"address": address},
+ key = get_key(self.nodes[0])
+ self.test_importmulti({"scriptPubKey": {"address": key.p2pkh_addr},
"timestamp": "now",
"keys": [key.privkey]},
- True)
- self.test_address(address,
- iswatchonly=False,
- ismine=True,
- timestamp=timestamp)
+ success=True)
+ test_address(self.nodes[1],
+ key.p2pkh_addr,
+ iswatchonly=False,
+ ismine=True,
+ timestamp=timestamp)
self.log.info("Should not import an address with private key if is already imported")
- self.test_importmulti({"scriptPubKey": {"address": address},
+ self.test_importmulti({"scriptPubKey": {"address": key.p2pkh_addr},
"timestamp": "now",
"keys": [key.privkey]},
- False,
+ success=False,
error_code=-4,
error_message='The wallet already contains the private key for this address or script')
# Address + Private key + watchonly
- self.log.info("Should not import an address with private key and with watchonly")
- key = self.get_key()
- address = key.p2pkh_addr
- self.test_importmulti({"scriptPubKey": {"address": address},
+ self.log.info("Should import an address with private key and with watchonly")
+ key = get_key(self.nodes[0])
+ self.test_importmulti({"scriptPubKey": {"address": key.p2pkh_addr},
"timestamp": "now",
"keys": [key.privkey],
"watchonly": True},
- False,
- error_code=-8,
- error_message='Watch-only addresses should not include private keys')
- self.test_address(address,
- iswatchonly=False,
- ismine=False,
- timestamp=None)
+ success=True,
+ warnings=["All private keys are provided, outputs will be considered spendable. If this is intentional, do not specify the watchonly flag."])
+ test_address(self.nodes[1],
+ key.p2pkh_addr,
+ iswatchonly=False,
+ ismine=True,
+ timestamp=timestamp)
# ScriptPubKey + Private key + internal
self.log.info("Should import a scriptPubKey with internal and with private key")
- key = self.get_key()
- address = key.p2pkh_addr
+ key = get_key(self.nodes[0])
self.test_importmulti({"scriptPubKey": key.p2pkh_script,
"timestamp": "now",
"keys": [key.privkey],
"internal": True},
- True)
- self.test_address(address,
- iswatchonly=False,
- ismine=True,
- timestamp=timestamp)
+ success=True)
+ test_address(self.nodes[1],
+ key.p2pkh_addr,
+ iswatchonly=False,
+ ismine=True,
+ timestamp=timestamp)
# Nonstandard scriptPubKey + Private key + !internal
self.log.info("Should not import a nonstandard scriptPubKey without internal and with private key")
- key = self.get_key()
- address = key.p2pkh_addr
+ key = get_key(self.nodes[0])
self.test_importmulti({"scriptPubKey": nonstandardScriptPubKey,
"timestamp": "now",
"keys": [key.privkey]},
- False,
+ success=False,
error_code=-8,
error_message='Internal must be set to true for nonstandard scriptPubKey imports.')
- self.test_address(address,
- iswatchonly=False,
- ismine=False,
- timestamp=None)
+ test_address(self.nodes[1],
+ key.p2pkh_addr,
+ iswatchonly=False,
+ ismine=False,
+ timestamp=None)
# P2SH address
- multisig = self.get_multisig()
+ multisig = get_multisig(self.nodes[0])
self.nodes[1].generate(100)
self.nodes[1].sendtoaddress(multisig.p2sh_addr, 10.00)
self.nodes[1].generate(1)
@@ -338,17 +259,18 @@ class ImportMultiTest(BitcoinTestFramework):
self.log.info("Should import a p2sh")
self.test_importmulti({"scriptPubKey": {"address": multisig.p2sh_addr},
"timestamp": "now"},
- True)
- self.test_address(multisig.p2sh_addr,
- isscript=True,
- iswatchonly=True,
- timestamp=timestamp)
+ success=True)
+ test_address(self.nodes[1],
+ multisig.p2sh_addr,
+ isscript=True,
+ iswatchonly=True,
+ timestamp=timestamp)
p2shunspent = self.nodes[1].listunspent(0, 999999, [multisig.p2sh_addr])[0]
assert_equal(p2shunspent['spendable'], False)
assert_equal(p2shunspent['solvable'], False)
# P2SH + Redeem script
- multisig = self.get_multisig()
+ multisig = get_multisig(self.nodes[0])
self.nodes[1].generate(100)
self.nodes[1].sendtoaddress(multisig.p2sh_addr, 10.00)
self.nodes[1].generate(1)
@@ -358,15 +280,17 @@ class ImportMultiTest(BitcoinTestFramework):
self.test_importmulti({"scriptPubKey": {"address": multisig.p2sh_addr},
"timestamp": "now",
"redeemscript": multisig.redeem_script},
- True)
- self.test_address(multisig.p2sh_addr, timestamp=timestamp)
+ success=True,
+ warnings=["Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."])
+ test_address(self.nodes[1],
+ multisig.p2sh_addr, timestamp=timestamp, iswatchonly=True, ismine=False, solvable=True)
p2shunspent = self.nodes[1].listunspent(0, 999999, [multisig.p2sh_addr])[0]
assert_equal(p2shunspent['spendable'], False)
assert_equal(p2shunspent['solvable'], True)
# P2SH + Redeem script + Private Keys + !Watchonly
- multisig = self.get_multisig()
+ multisig = get_multisig(self.nodes[0])
self.nodes[1].generate(100)
self.nodes[1].sendtoaddress(multisig.p2sh_addr, 10.00)
self.nodes[1].generate(1)
@@ -377,16 +301,21 @@ class ImportMultiTest(BitcoinTestFramework):
"timestamp": "now",
"redeemscript": multisig.redeem_script,
"keys": multisig.privkeys[0:2]},
- True)
- self.test_address(multisig.p2sh_addr,
- timestamp=timestamp)
+ success=True,
+ warnings=["Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."])
+ test_address(self.nodes[1],
+ multisig.p2sh_addr,
+ timestamp=timestamp,
+ ismine=False,
+ iswatchonly=True,
+ solvable=True)
p2shunspent = self.nodes[1].listunspent(0, 999999, [multisig.p2sh_addr])[0]
assert_equal(p2shunspent['spendable'], False)
assert_equal(p2shunspent['solvable'], True)
# P2SH + Redeem script + Private Keys + Watchonly
- multisig = self.get_multisig()
+ multisig = get_multisig(self.nodes[0])
self.nodes[1].generate(100)
self.nodes[1].sendtoaddress(multisig.p2sh_addr, 10.00)
self.nodes[1].generate(1)
@@ -398,95 +327,101 @@ class ImportMultiTest(BitcoinTestFramework):
"redeemscript": multisig.redeem_script,
"keys": multisig.privkeys[0:2],
"watchonly": True},
- False,
- error_code=-8,
- error_message='Watch-only addresses should not include private keys')
+ success=True)
+ test_address(self.nodes[1],
+ multisig.p2sh_addr,
+ iswatchonly=True,
+ ismine=False,
+ solvable=True,
+ timestamp=timestamp)
# Address + Public key + !Internal + Wrong pubkey
- self.log.info("Should not import an address with a wrong public key")
- key = self.get_key()
- address = key.p2pkh_addr
- wrong_key = self.get_key().pubkey
- self.test_importmulti({"scriptPubKey": {"address": address},
+ self.log.info("Should not import an address with the wrong public key as non-solvable")
+ key = get_key(self.nodes[0])
+ wrong_key = get_key(self.nodes[0]).pubkey
+ self.test_importmulti({"scriptPubKey": {"address": key.p2pkh_addr},
"timestamp": "now",
"pubkeys": [wrong_key]},
- False,
- error_code=-5,
- error_message='Key does not match address destination')
- self.test_address(address,
- iswatchonly=False,
- ismine=False,
- timestamp=None)
+ success=True,
+ warnings=["Importing as non-solvable: some required keys are missing. If this is intentional, don't provide any keys, pubkeys, witnessscript, or redeemscript.", "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."])
+ test_address(self.nodes[1],
+ key.p2pkh_addr,
+ iswatchonly=True,
+ ismine=False,
+ solvable=False,
+ timestamp=timestamp)
# ScriptPubKey + Public key + internal + Wrong pubkey
- self.log.info("Should not import a scriptPubKey with internal and with a wrong public key")
- key = self.get_key()
- address = key.p2pkh_addr
- wrong_key = self.get_key().pubkey
+ self.log.info("Should import a scriptPubKey with internal and with a wrong public key as non-solvable")
+ key = get_key(self.nodes[0])
+ wrong_key = get_key(self.nodes[0]).pubkey
self.test_importmulti({"scriptPubKey": key.p2pkh_script,
"timestamp": "now",
"pubkeys": [wrong_key],
"internal": True},
- False,
- error_code=-5,
- error_message='Key does not match address destination')
- self.test_address(address,
- iswatchonly=False,
- ismine=False,
- timestamp=None)
+ success=True,
+ warnings=["Importing as non-solvable: some required keys are missing. If this is intentional, don't provide any keys, pubkeys, witnessscript, or redeemscript.", "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."])
+ test_address(self.nodes[1],
+ key.p2pkh_addr,
+ iswatchonly=True,
+ ismine=False,
+ solvable=False,
+ timestamp=timestamp)
# Address + Private key + !watchonly + Wrong private key
- self.log.info("Should not import an address with a wrong private key")
- key = self.get_key()
- address = key.p2pkh_addr
- wrong_privkey = self.get_key().privkey
- self.test_importmulti({"scriptPubKey": {"address": address},
+ self.log.info("Should import an address with a wrong private key as non-solvable")
+ key = get_key(self.nodes[0])
+ wrong_privkey = get_key(self.nodes[0]).privkey
+ self.test_importmulti({"scriptPubKey": {"address": key.p2pkh_addr},
"timestamp": "now",
"keys": [wrong_privkey]},
- False,
- error_code=-5,
- error_message='Key does not match address destination')
- self.test_address(address,
- iswatchonly=False,
- ismine=False,
- timestamp=None)
+ success=True,
+ warnings=["Importing as non-solvable: some required keys are missing. If this is intentional, don't provide any keys, pubkeys, witnessscript, or redeemscript.", "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."])
+ test_address(self.nodes[1],
+ key.p2pkh_addr,
+ iswatchonly=True,
+ ismine=False,
+ solvable=False,
+ timestamp=timestamp)
# ScriptPubKey + Private key + internal + Wrong private key
- self.log.info("Should not import a scriptPubKey with internal and with a wrong private key")
- key = self.get_key()
- address = key.p2pkh_addr
- wrong_privkey = self.get_key().privkey
+ self.log.info("Should import a scriptPubKey with internal and with a wrong private key as non-solvable")
+ key = get_key(self.nodes[0])
+ wrong_privkey = get_key(self.nodes[0]).privkey
self.test_importmulti({"scriptPubKey": key.p2pkh_script,
"timestamp": "now",
"keys": [wrong_privkey],
"internal": True},
- False,
- error_code=-5,
- error_message='Key does not match address destination')
- self.test_address(address,
- iswatchonly=False,
- ismine=False,
- timestamp=None)
+ success=True,
+ warnings=["Importing as non-solvable: some required keys are missing. If this is intentional, don't provide any keys, pubkeys, witnessscript, or redeemscript.", "Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."])
+ test_address(self.nodes[1],
+ key.p2pkh_addr,
+ iswatchonly=True,
+ ismine=False,
+ solvable=False,
+ timestamp=timestamp)
# Importing existing watch only address with new timestamp should replace saved timestamp.
assert_greater_than(timestamp, watchonly_timestamp)
self.log.info("Should replace previously saved watch only timestamp.")
self.test_importmulti({"scriptPubKey": {"address": watchonly_address},
"timestamp": "now"},
- True)
- self.test_address(watchonly_address,
- iswatchonly=True,
- ismine=False,
- timestamp=timestamp)
+ success=True)
+ test_address(self.nodes[1],
+ watchonly_address,
+ iswatchonly=True,
+ ismine=False,
+ timestamp=timestamp)
watchonly_timestamp = timestamp
# restart nodes to check for proper serialization/deserialization of watch only address
self.stop_nodes()
self.start_nodes()
- self.test_address(watchonly_address,
- iswatchonly=True,
- ismine=False,
- timestamp=watchonly_timestamp)
+ test_address(self.nodes[1],
+ watchonly_address,
+ iswatchonly=True,
+ ismine=False,
+ timestamp=watchonly_timestamp)
# Bad or missing timestamps
self.log.info("Should throw on invalid or missing timestamp values")
@@ -500,47 +435,49 @@ class ImportMultiTest(BitcoinTestFramework):
# Import P2WPKH address as watch only
self.log.info("Should import a P2WPKH address as watch only")
- key = self.get_key()
- address = key.p2wpkh_addr
- self.test_importmulti({"scriptPubKey": {"address": address},
+ key = get_key(self.nodes[0])
+ self.test_importmulti({"scriptPubKey": {"address": key.p2wpkh_addr},
"timestamp": "now"},
- True)
- self.test_address(address,
- iswatchonly=True,
- solvable=False)
+ success=True)
+ test_address(self.nodes[1],
+ key.p2wpkh_addr,
+ iswatchonly=True,
+ solvable=False)
# Import P2WPKH address with public key but no private key
self.log.info("Should import a P2WPKH address and public key as solvable but not spendable")
- key = self.get_key()
- address = key.p2wpkh_addr
- self.test_importmulti({"scriptPubKey": {"address": address},
+ key = get_key(self.nodes[0])
+ self.test_importmulti({"scriptPubKey": {"address": key.p2wpkh_addr},
"timestamp": "now",
"pubkeys": [key.pubkey]},
- True)
- self.test_address(address,
- ismine=False,
- solvable=True)
+ success=True,
+ warnings=["Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."])
+ test_address(self.nodes[1],
+ key.p2wpkh_addr,
+ ismine=False,
+ solvable=True)
# Import P2WPKH address with key and check it is spendable
self.log.info("Should import a P2WPKH address with key")
- key = self.get_key()
- address = key.p2wpkh_addr
- self.test_importmulti({"scriptPubKey": {"address": address},
+ key = get_key(self.nodes[0])
+ self.test_importmulti({"scriptPubKey": {"address": key.p2wpkh_addr},
"timestamp": "now",
"keys": [key.privkey]},
- True)
- self.test_address(address,
- iswatchonly=False,
- ismine=True)
+ success=True)
+ test_address(self.nodes[1],
+ key.p2wpkh_addr,
+ iswatchonly=False,
+ ismine=True)
# P2WSH multisig address without scripts or keys
- multisig = self.get_multisig()
+ multisig = get_multisig(self.nodes[0])
self.log.info("Should import a p2wsh multisig as watch only without respective redeem script and private keys")
self.test_importmulti({"scriptPubKey": {"address": multisig.p2wsh_addr},
"timestamp": "now"},
- True)
- self.test_address(multisig.p2sh_addr,
- solvable=False)
+ success=True)
+ test_address(self.nodes[1],
+ multisig.p2sh_addr,
+ solvable=False)
# Same P2WSH multisig address as above, but now with witnessscript + private keys
self.log.info("Should import a p2wsh with respective witness script and private keys")
@@ -548,57 +485,63 @@ class ImportMultiTest(BitcoinTestFramework):
"timestamp": "now",
"witnessscript": multisig.redeem_script,
"keys": multisig.privkeys},
- True)
- self.test_address(multisig.p2sh_addr,
- solvable=True,
- ismine=True,
- sigsrequired=2)
+ success=True)
+ test_address(self.nodes[1],
+ multisig.p2sh_addr,
+ solvable=True,
+ ismine=True,
+ sigsrequired=2)
# P2SH-P2WPKH address with no redeemscript or public or private key
- key = self.get_key()
- address = key.p2sh_p2wpkh_addr
+ key = get_key(self.nodes[0])
self.log.info("Should import a p2sh-p2wpkh without redeem script or keys")
- self.test_importmulti({"scriptPubKey": {"address": address},
+ self.test_importmulti({"scriptPubKey": {"address": key.p2sh_p2wpkh_addr},
"timestamp": "now"},
- True)
- self.test_address(address,
- solvable=False,
- ismine=False)
+ success=True)
+ test_address(self.nodes[1],
+ key.p2sh_p2wpkh_addr,
+ solvable=False,
+ ismine=False)
# P2SH-P2WPKH address + redeemscript + public key with no private key
self.log.info("Should import a p2sh-p2wpkh with respective redeem script and pubkey as solvable")
- self.test_importmulti({"scriptPubKey": {"address": address},
+ self.test_importmulti({"scriptPubKey": {"address": key.p2sh_p2wpkh_addr},
"timestamp": "now",
"redeemscript": key.p2sh_p2wpkh_redeem_script,
"pubkeys": [key.pubkey]},
- True)
- self.test_address(address,
- solvable=True,
- ismine=False)
+ success=True,
+ warnings=["Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."])
+ test_address(self.nodes[1],
+ key.p2sh_p2wpkh_addr,
+ solvable=True,
+ ismine=False)
# P2SH-P2WPKH address + redeemscript + private key
- key = self.get_key()
- address = key.p2sh_p2wpkh_addr
+ key = get_key(self.nodes[0])
self.log.info("Should import a p2sh-p2wpkh with respective redeem script and private keys")
- self.test_importmulti({"scriptPubKey": {"address": address},
+ self.test_importmulti({"scriptPubKey": {"address": key.p2sh_p2wpkh_addr},
"timestamp": "now",
"redeemscript": key.p2sh_p2wpkh_redeem_script,
"keys": [key.privkey]},
- True)
- self.test_address(address,
- solvable=True,
- ismine=True)
+ success=True)
+ test_address(self.nodes[1],
+ key.p2sh_p2wpkh_addr,
+ solvable=True,
+ ismine=True)
# P2SH-P2WSH multisig + redeemscript with no private key
- multisig = self.get_multisig()
+ multisig = get_multisig(self.nodes[0])
self.log.info("Should import a p2sh-p2wsh with respective redeem script but no private key")
self.test_importmulti({"scriptPubKey": {"address": multisig.p2sh_p2wsh_addr},
"timestamp": "now",
"redeemscript": multisig.p2wsh_script,
"witnessscript": multisig.redeem_script},
- True)
- self.test_address(address,
- solvable=True)
+ success=True,
+ warnings=["Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."])
+ test_address(self.nodes[1],
+ multisig.p2sh_p2wsh_addr,
+ solvable=True,
+ ismine=False)
if __name__ == '__main__':
ImportMultiTest().main()
diff --git a/test/functional/wallet_listtransactions.py b/test/functional/wallet_listtransactions.py
index 8ca0387268..17f044bf65 100755
--- a/test/functional/wallet_listtransactions.py
+++ b/test/functional/wallet_listtransactions.py
@@ -25,12 +25,13 @@ def tx_from_hex(hexstring):
class ListTransactionsTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 2
- self.enable_mocktime()
def skip_test_if_missing_module(self):
self.skip_if_no_wallet()
def run_test(self):
+ self.nodes[0].generate(1) # Get out of IBD
+ self.sync_all()
# Simple send, 0 to 1:
txid = self.nodes[0].sendtoaddress(self.nodes[1].getnewaddress(), 0.1)
self.sync_all()
diff --git a/test/lint/lint-includes.sh b/test/lint/lint-includes.sh
index f6d0fd382b..4b9e2615b6 100755
--- a/test/lint/lint-includes.sh
+++ b/test/lint/lint-includes.sh
@@ -50,7 +50,6 @@ EXPECTED_BOOST_INCLUDES=(
boost/algorithm/string/classification.hpp
boost/algorithm/string/replace.hpp
boost/algorithm/string/split.hpp
- boost/bind.hpp
boost/chrono/chrono.hpp
boost/date_time/posix_time/posix_time.hpp
boost/filesystem.hpp
diff --git a/test/lint/lint-locale-dependence.sh b/test/lint/lint-locale-dependence.sh
index 44170a6b5a..1534d5ef68 100755
--- a/test/lint/lint-locale-dependence.sh
+++ b/test/lint/lint-locale-dependence.sh
@@ -4,30 +4,21 @@ export LC_ALL=C
KNOWN_VIOLATIONS=(
"src/bitcoin-tx.cpp.*stoul"
"src/bitcoin-tx.cpp.*trim_right"
- "src/bitcoin-tx.cpp:.*atoi"
- "src/core_read.cpp.*is_digit"
"src/dbwrapper.cpp.*stoul"
"src/dbwrapper.cpp:.*vsnprintf"
"src/httprpc.cpp.*trim"
"src/init.cpp:.*atoi"
"src/qt/rpcconsole.cpp:.*atoi"
- "src/qt/rpcconsole.cpp:.*isdigit"
"src/rest.cpp:.*strtol"
"src/test/dbwrapper_tests.cpp:.*snprintf"
- "src/test/getarg_tests.cpp.*split"
"src/torcontrol.cpp:.*atoi"
"src/torcontrol.cpp:.*strtol"
- "src/uint256.cpp:.*tolower"
- "src/util/system.cpp:.*atoi"
- "src/util/system.cpp:.*fprintf"
- "src/util/system.cpp:.*tolower"
- "src/util/moneystr.cpp:.*isdigit"
"src/util/strencodings.cpp:.*atoi"
"src/util/strencodings.cpp:.*strtol"
- "src/util/strencodings.cpp:.*strtoll"
"src/util/strencodings.cpp:.*strtoul"
- "src/util/strencodings.cpp:.*strtoull"
"src/util/strencodings.h:.*atoi"
+ "src/util/system.cpp:.*atoi"
+ "src/util/system.cpp:.*fprintf"
)
REGEXP_IGNORE_EXTERNAL_DEPENDENCIES="^src/(crypto/ctaes/|leveldb/|secp256k1/|tinyformat.h|univalue/)"
diff --git a/test/lint/lint-python-dead-code.sh b/test/lint/lint-python-dead-code.sh
index 4561b0db30..1b897cd131 100755
--- a/test/lint/lint-python-dead-code.sh
+++ b/test/lint/lint-python-dead-code.sh
@@ -16,4 +16,4 @@ fi
vulture \
--min-confidence 60 \
--ignore-names "argtypes,connection_lost,connection_made,converter,data_received,daemon,errcheck,get_ecdh_key,get_privkey,is_compressed,is_fullyvalid,msg_generic,on_*,optionxform,restype,set_privkey" \
- $(git ls-files -- "*.py" ":(exclude)contrib/")
+ $(git ls-files -- "*.py" ":(exclude)contrib/" ":(exclude)test/functional/data/invalid_txs.py")
diff --git a/test/sanitizer_suppressions/ubsan b/test/sanitizer_suppressions/ubsan
index e90d5c2ac0..f0107f1361 100644
--- a/test/sanitizer_suppressions/ubsan
+++ b/test/sanitizer_suppressions/ubsan
@@ -29,7 +29,6 @@ unsigned-integer-overflow:policy/fees.cpp
unsigned-integer-overflow:prevector.h
unsigned-integer-overflow:script/interpreter.cpp
unsigned-integer-overflow:stl_bvector.h
-unsigned-integer-overflow:streams.h
unsigned-integer-overflow:txmempool.cpp
unsigned-integer-overflow:util/strencodings.cpp
unsigned-integer-overflow:validation.cpp