diff options
Diffstat (limited to 'test')
-rwxr-xr-x | test/functional/blockchain.py | 4 | ||||
-rwxr-xr-x | test/functional/fundrawtransaction.py | 2 | ||||
-rwxr-xr-x | test/functional/mempool_persist.py | 28 | ||||
-rwxr-xr-x | test/functional/minchainwork.py | 81 | ||||
-rwxr-xr-x | test/functional/segwit.py | 3 | ||||
-rwxr-xr-x | test/functional/signmessages.py | 21 | ||||
-rwxr-xr-x | test/functional/test_framework/test_framework.py | 8 | ||||
-rwxr-xr-x | test/functional/test_framework/test_node.py | 30 | ||||
-rwxr-xr-x | test/functional/test_runner.py | 1 | ||||
-rwxr-xr-x | test/functional/wallet-encryption.py | 2 |
10 files changed, 150 insertions, 30 deletions
diff --git a/test/functional/blockchain.py b/test/functional/blockchain.py index 5d04de9940..50be9262e4 100755 --- a/test/functional/blockchain.py +++ b/test/functional/blockchain.py @@ -21,7 +21,7 @@ from decimal import Decimal import http.client import subprocess -from test_framework.test_framework import (BitcoinTestFramework, BITCOIND_PROC_WAIT_TIMEOUT) +from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, assert_raises, @@ -141,7 +141,7 @@ class BlockchainTest(BitcoinTestFramework): except (ConnectionError, http.client.BadStatusLine): pass # The node already shut down before response self.log.debug('Node should stop at this height...') - self.nodes[0].process.wait(timeout=BITCOIND_PROC_WAIT_TIMEOUT) + self.nodes[0].wait_until_stopped() self.start_node(0) assert_equal(self.nodes[0].getblockcount(), 207) diff --git a/test/functional/fundrawtransaction.py b/test/functional/fundrawtransaction.py index 75a0dc5f9d..71e88009b6 100755 --- a/test/functional/fundrawtransaction.py +++ b/test/functional/fundrawtransaction.py @@ -4,7 +4,7 @@ # file COPYING or http://www.opensource.org/licenses/mit-license.php. """Test the fundrawtransaction RPC.""" -from test_framework.test_framework import BitcoinTestFramework, BITCOIND_PROC_WAIT_TIMEOUT +from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * diff --git a/test/functional/mempool_persist.py b/test/functional/mempool_persist.py index 01f65b1373..149a01870d 100755 --- a/test/functional/mempool_persist.py +++ b/test/functional/mempool_persist.py @@ -28,8 +28,14 @@ Test is as follows: - Restart node0 with -persistmempool. Verify that it has 5 transactions in its mempool. This tests that -persistmempool=0 does not overwrite a previously valid mempool stored on disk. + - Remove node0 mempool.dat and verify savemempool RPC recreates it + and verify that node1 can load it and has 5 transaction in its + mempool. + - Verify that savemempool throws when the RPC is called if + node1 can't write to disk. """ +import os import time from test_framework.test_framework import BitcoinTestFramework @@ -78,5 +84,27 @@ class MempoolPersistTest(BitcoinTestFramework): self.start_node(0) wait_until(lambda: len(self.nodes[0].getrawmempool()) == 5) + mempooldat0 = os.path.join(self.options.tmpdir, 'node0', 'regtest', 'mempool.dat') + mempooldat1 = os.path.join(self.options.tmpdir, 'node1', 'regtest', 'mempool.dat') + self.log.debug("Remove the mempool.dat file. Verify that savemempool to disk via RPC re-creates it") + os.remove(mempooldat0) + self.nodes[0].savemempool() + assert os.path.isfile(mempooldat0) + + self.log.debug("Stop nodes, make node1 use mempool.dat from node0. Verify it has 5 transactions") + os.rename(mempooldat0, mempooldat1) + self.stop_nodes() + self.start_node(1, extra_args=[]) + wait_until(lambda: len(self.nodes[1].getrawmempool()) == 5) + + self.log.debug("Prevent bitcoind from writing mempool.dat to disk. Verify that `savemempool` fails") + # to test the exception we are setting bad permissions on a tmp file called mempool.dat.new + # which is an implementation detail that could change and break this test + mempooldotnew1 = mempooldat1 + '.new' + with os.fdopen(os.open(mempooldotnew1, os.O_CREAT, 0o000), 'w'): + pass + assert_raises_jsonrpc(-1, "Unable to dump mempool to disk", self.nodes[1].savemempool) + os.remove(mempooldotnew1) + if __name__ == '__main__': MempoolPersistTest().main() diff --git a/test/functional/minchainwork.py b/test/functional/minchainwork.py new file mode 100755 index 0000000000..c7579d2548 --- /dev/null +++ b/test/functional/minchainwork.py @@ -0,0 +1,81 @@ +#!/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 logic for setting nMinimumChainWork on command line. + +Nodes don't consider themselves out of "initial block download" until +their active chain has more work than nMinimumChainWork. + +Nodes don't download blocks from a peer unless the peer's best known block +has more work than nMinimumChainWork. + +While in initial block download, nodes won't relay blocks to their peers, so +test that this parameter functions as intended by verifying that block relay +only succeeds past a given node once its nMinimumChainWork has been exceeded. +""" + +import time + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import sync_blocks, connect_nodes, assert_equal + +# 2 hashes required per regtest block (with no difficulty adjustment) +REGTEST_WORK_PER_BLOCK = 2 + +class MinimumChainWorkTest(BitcoinTestFramework): + def set_test_params(self): + self.setup_clean_chain = True + self.num_nodes = 3 + self.extra_args = [[], ["-minimumchainwork=0x65"], ["-minimumchainwork=0x65"]] + self.node_min_work = [0, 101, 101] + + def setup_network(self): + # This test relies on the chain setup being: + # node0 <- node1 <- node2 + # Before leaving IBD, nodes prefer to download blocks from outbound + # peers, so ensure that we're mining on an outbound peer and testing + # block relay to inbound peers. + self.setup_nodes() + for i in range(self.num_nodes-1): + connect_nodes(self.nodes[i+1], i) + + def run_test(self): + # Start building a chain on node0. node2 shouldn't be able to sync until node1's + # minchainwork is exceeded + starting_chain_work = REGTEST_WORK_PER_BLOCK # Genesis block's work + self.log.info("Testing relay across node %d (minChainWork = %d)", 1, self.node_min_work[1]) + + starting_blockcount = self.nodes[2].getblockcount() + + num_blocks_to_generate = int((self.node_min_work[1] - starting_chain_work) / REGTEST_WORK_PER_BLOCK) + self.log.info("Generating %d blocks on node0", num_blocks_to_generate) + hashes = self.nodes[0].generate(num_blocks_to_generate) + + self.log.info("Node0 current chain work: %s", self.nodes[0].getblockheader(hashes[-1])['chainwork']) + + # Sleep a few seconds and verify that node2 didn't get any new blocks + # or headers. We sleep, rather than sync_blocks(node0, node1) because + # it's reasonable either way for node1 to get the blocks, or not get + # them (since they're below node1's minchainwork). + time.sleep(3) + + self.log.info("Verifying node 2 has no more blocks than before") + self.log.info("Blockcounts: %s", [n.getblockcount() for n in self.nodes]) + # Node2 shouldn't have any new headers yet, because node1 should not + # have relayed anything. + assert_equal(len(self.nodes[2].getchaintips()), 1) + assert_equal(self.nodes[2].getchaintips()[0]['height'], 0) + + assert self.nodes[1].getbestblockhash() != self.nodes[0].getbestblockhash() + assert_equal(self.nodes[2].getblockcount(), starting_blockcount) + + self.log.info("Generating one more block") + self.nodes[0].generate(1) + + self.log.info("Verifying nodes are all synced") + self.sync_all() + self.log.info("Blockcounts: %s", [n.getblockcount() for n in self.nodes]) + +if __name__ == '__main__': + MinimumChainWorkTest().main() diff --git a/test/functional/segwit.py b/test/functional/segwit.py index 609c592ed3..f465c1683b 100755 --- a/test/functional/segwit.py +++ b/test/functional/segwit.py @@ -279,6 +279,9 @@ class SegWitTest(BitcoinTestFramework): assert(txid2 in template_txids) assert(txid3 in template_txids) + # Check that wtxid is properly reported in mempool entry + assert_equal(int(self.nodes[0].getmempoolentry(txid3)["wtxid"], 16), tx.calc_sha256(True)) + # Mine a block to clear the gbt cache again. self.nodes[0].generate(1) diff --git a/test/functional/signmessages.py b/test/functional/signmessages.py index 5fdfeceb76..52ba6a5ad7 100755 --- a/test/functional/signmessages.py +++ b/test/functional/signmessages.py @@ -5,6 +5,7 @@ """Test RPC commands for signing and verifying messages.""" from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import assert_equal class SignMessagesTest(BitcoinTestFramework): def set_test_params(self): @@ -14,20 +15,24 @@ class SignMessagesTest(BitcoinTestFramework): def run_test(self): message = 'This is just a test message' - # Test the signing with a privkey - privKey = 'cUeKHd5orzT3mz8P9pxyREHfsWtVfgsfDjiZZBcjUBAaGk1BTj7N' + self.log.info('test signing with priv_key') + priv_key = 'cUeKHd5orzT3mz8P9pxyREHfsWtVfgsfDjiZZBcjUBAaGk1BTj7N' address = 'mpLQjfK79b7CCV4VMJWEWAj5Mpx8Up5zxB' - signature = self.nodes[0].signmessagewithprivkey(privKey, message) - - # Verify the message + expected_signature = 'INbVnW4e6PeRmsv2Qgu8NuopvrVjkcxob+sX8OcZG0SALhWybUjzMLPdAsXI46YZGb0KQTRii+wWIQzRpG/U+S0=' + signature = self.nodes[0].signmessagewithprivkey(priv_key, message) + assert_equal(expected_signature, signature) assert(self.nodes[0].verifymessage(address, signature, message)) - # Test the signing with an address with wallet + self.log.info('test signing with an address with wallet') address = self.nodes[0].getnewaddress() signature = self.nodes[0].signmessage(address, message) - - # Verify the message assert(self.nodes[0].verifymessage(address, signature, message)) + self.log.info('test verifying with another address should not work') + other_address = self.nodes[0].getnewaddress() + other_signature = self.nodes[0].signmessage(other_address, message) + assert(not self.nodes[0].verifymessage(other_address, signature, message)) + assert(not self.nodes[0].verifymessage(address, other_signature, message)) + if __name__ == '__main__': SignMessagesTest().main() diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 103651f175..a53eb51799 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -43,8 +43,6 @@ TEST_EXIT_PASSED = 0 TEST_EXIT_FAILED = 1 TEST_EXIT_SKIPPED = 77 -BITCOIND_PROC_WAIT_TIMEOUT = 60 - class BitcoinTestFramework(object): """Base class for a bitcoin test script. @@ -263,8 +261,7 @@ class BitcoinTestFramework(object): def stop_node(self, i): """Stop a bitcoind test node""" self.nodes[i].stop_node() - while not self.nodes[i].is_node_stopped(): - time.sleep(0.1) + self.nodes[i].wait_until_stopped() def stop_nodes(self): """Stop multiple bitcoind test nodes""" @@ -274,8 +271,7 @@ class BitcoinTestFramework(object): for node in self.nodes: # Wait for nodes to stop - while not node.is_node_stopped(): - time.sleep(0.1) + node.wait_until_stopped() def assert_start_raises_init_error(self, i, extra_args=None, expected_msg=None): with tempfile.SpooledTemporaryFile(max_size=2**16) as log_stderr: diff --git a/test/functional/test_framework/test_node.py b/test/functional/test_framework/test_node.py index efb3ac9d16..f58a372a14 100755 --- a/test/functional/test_framework/test_node.py +++ b/test/functional/test_framework/test_node.py @@ -17,9 +17,12 @@ from .util import ( assert_equal, get_rpc_proxy, rpc_url, + wait_until, ) from .authproxy import JSONRPCException +BITCOIND_PROC_WAIT_TIMEOUT = 60 + class TestNode(): """A class for representing a bitcoind node under test. @@ -125,14 +128,20 @@ class TestNode(): if not self.running: return True return_code = self.process.poll() - if return_code is not None: - # process has stopped. Assert that it didn't return an error code. - assert_equal(return_code, 0) - self.running = False - self.process = None - self.log.debug("Node stopped") - return True - return False + if return_code is None: + return False + + # process has stopped. Assert that it didn't return an error code. + assert_equal(return_code, 0) + self.running = False + self.process = None + self.rpc_connected = False + self.rpc = None + self.log.debug("Node stopped") + return True + + def wait_until_stopped(self, timeout=BITCOIND_PROC_WAIT_TIMEOUT): + wait_until(self.is_node_stopped, timeout=timeout) def node_encrypt_wallet(self, passphrase): """"Encrypts the wallet. @@ -140,10 +149,7 @@ class TestNode(): This causes bitcoind to shutdown, so this method takes care of cleaning up resources.""" self.encryptwallet(passphrase) - while not self.is_node_stopped(): - time.sleep(0.1) - self.rpc = None - self.rpc_connected = False + self.wait_until_stopped() class TestNodeCLI(): """Interface to bitcoin-cli for an individual node""" diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 59c236ce15..8dbe6247ee 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -121,6 +121,7 @@ BASE_SCRIPTS= [ 'bip65-cltv-p2p.py', 'uptime.py', 'resendwallettransactions.py', + 'minchainwork.py', ] EXTENDED_SCRIPTS = [ diff --git a/test/functional/wallet-encryption.py b/test/functional/wallet-encryption.py index f63bb2ea5e..ce1e7744e9 100755 --- a/test/functional/wallet-encryption.py +++ b/test/functional/wallet-encryption.py @@ -6,7 +6,7 @@ import time -from test_framework.test_framework import BitcoinTestFramework, BITCOIND_PROC_WAIT_TIMEOUT +from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, assert_raises_jsonrpc, |