diff options
author | MarcoFalke <falke.marco@gmail.com> | 2018-01-24 20:42:46 -0500 |
---|---|---|
committer | MarcoFalke <falke.marco@gmail.com> | 2018-01-24 20:43:13 -0500 |
commit | 6970b30c6f1d2be7947295fe18f2390649b17a4b (patch) | |
tree | 6d8c8226f05a765483eff94aedfccd8cf483cf55 /test/functional/feature_versionbits_warning.py | |
parent | f359afcc410432ed5d30001acda0c66741ee8935 (diff) | |
parent | 6f881cc8809e2c0d0150c47494bc37f2eb05ec66 (diff) |
Merge #11774: [tests] Rename functional tests
6f881cc880 [tests] Remove EXPECTED_VIOLATION_COUNT (Anthony Towns)
3150b3fea7 [tests] Rename misc functional tests. (Anthony Towns)
81b79f2c39 [tests] Rename rpc_* functional tests. (Anthony Towns)
61b8f7f273 [tests] Rename p2p_* functional tests. (Anthony Towns)
90600bc7db [tests] Rename wallet_* functional tests. (Anthony Towns)
ca6523d0c8 [tests] Rename feature_* functional tests. (Anthony Towns)
Pull request description:
This PR changes the functional tests to have a consistent naming scheme:
tests for individual RPC methods are named rpc_...
tests for interfaces (REST, ZMQ, RPC features) are named interface_...
tests that explicitly test the p2p interface are named p2p_...
tests for wallet features are named wallet_...
tests for mining features are named mining_...
tests for mempool behaviour are named mempool_...
tests for full features that aren't wallet/mining/mempool are named feature_...
Rationale: it's sometimes difficult for new contributors to know what's already covered by existing tests and where new tests should be added. Naming in a consistent fashion makes it easier to see what's already covered at a glance.
Tree-SHA512: 4246790552d42bbd95f6d5bdf67702b81b3b2c583ce7eaf1fe6d8e254721279b47315973c6e9ae82dad6e4c747f12188160764bf2624c0f8f3b4d39330ec8b16
Diffstat (limited to 'test/functional/feature_versionbits_warning.py')
-rwxr-xr-x | test/functional/feature_versionbits_warning.py | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/test/functional/feature_versionbits_warning.py b/test/functional/feature_versionbits_warning.py new file mode 100755 index 0000000000..0bfe94622f --- /dev/null +++ b/test/functional/feature_versionbits_warning.py @@ -0,0 +1,121 @@ +#!/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() |