aboutsummaryrefslogtreecommitdiff
path: root/test/functional/minchainwork.py
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2017-11-03 15:32:02 -0700
committerPieter Wuille <pieter.wuille@gmail.com>2017-11-03 15:42:50 -0700
commitf518d9ae6aa525c4cd360a16f07a9272cbef558d (patch)
tree335ee53ff19753f10dfd40b42570e0419701e183 /test/functional/minchainwork.py
parentf224cbc3d8f4478d30e121126658c2ab22c6fb90 (diff)
parent8195cb0d7fc4f8699b35aff7a43ed2fb3013608c (diff)
Merge #11592: 0.15: Backportsv0.15.1rc1
8195cb0d7 rpc: further constrain the libevent workaround (Cory Fields) 34153a7e4 rpc: work-around an upstream libevent bug (Cory Fields) fc308a6cd Add unit test for stale tip checking (Suhas Daftuar) 2ed0647ac Add CConnmanTest to mutate g_connman in tests (João Barbosa) a607a95d8 Connect to an extra outbound peer if our tip is stale (Suhas Daftuar) 459f2db42 Track tip update time and last new block announcement from each peer (Suhas Daftuar) 49bf09018 net: Allow connecting to extra outbound peers (Suhas Daftuar) bb83fe190 Add release notes describing blockmaxweight deprecation (Matt Corallo) 4c82cea99 Use a sensible default for blockmaxweight (Matt Corallo) 7871a7d3b Deprecate confusing blockmaxsize, fix getmininginfo output (Matt Corallo) 6baa317b5 Fix minchainwork test for 0.15 backport (Suhas Daftuar) 55b7abfa8 Make p2p-acceptablock not an extended test (Matt Corallo) 5bec7744d [qa] test that invalid blocks on an invalid chain get a disconnect (Matt Corallo) 92d6105c4 Reject headers building on invalid chains by tracking invalidity (Matt Corallo) 51001d684 Accept unrequested blocks with work equal to our tip (Matt Corallo) c6e4d0ce8 Stop always storing blocks from whitelisted peers (Matt Corallo) e976c36dd Rewrite p2p-acceptblock in preparation for slight behavior changes (Matt Corallo) ec8dedff4 net: Add missing lock in ProcessHeadersMessage(...) (practicalswift) 59b210d9a Disconnect outbound peers relaying invalid headers (Suhas Daftuar) fc966bbd2 moveonly: factor out headers processing into separate function (Suhas Daftuar) e3272242e Add unit test for outbound peer eviction (Suhas Daftuar) 9961abf9e Permit disconnection of outbound peers on bad/slow chains (Suhas Daftuar) bf191a718 Disconnecting from bad outbound peers in IBD (Suhas Daftuar) d570aa429 Fix uninitialized g_connman crash in Shutdown() (MeshCollider) 0a5477c7e net: stop both net/net_processing before destroying them (Cory Fields) b4136f21c net: drop unused connman param (Cory Fields) dc897e53d net: use an interface class rather than signals for message processing (Cory Fields) 8aee55af3 net: pass CConnman via pointer rather than reference (Cory Fields) 6f279652b Rename fAddnode to a more-descriptive "manual_connection" (Matt Corallo) ffb6ea4e5 Add comment explaining forced processing of compact blocks (Suhas Daftuar) 2df65eeb9 qa: add test for minchainwork use in acceptblock (Suhas Daftuar) 3acec3878 Don't process unrequested, low-work blocks (Suhas Daftuar) 0e9d04bf0 [qa] Test nMinimumChainWork (Suhas Daftuar) da4908c3a Allow setting nMinimumChainWork on command line (Suhas Daftuar) 41088795d qa: Remove never used return value of sync_with_ping (MarcoFalke) f3457d0e8 qa: Make tmpdir option an absolute path (MarcoFalke) 9c8006dc3 Avoid opening copied wallet databases simultaneously (Russell Yanofsky) de7053f11 [wallet] Fix leak in CDB constructor (João Barbosa) fd79ed6b2 Ensure backupwallet fails when attempting to backup to source file (Tomas van der Wansem) d94fc336c scripted-diff: rename assert_raises_jsonrpc to assert_raises_rpc error (John Newbery) 623de0acb [tests] do not allow assert_raises_message to be called with JSONRPCException (John Newbery) 5b728c8e9 [tests] remove direct testing on JSONRPCException from individual test cases (John Newbery) Pull request description: Tree-SHA512: 9fdb5c47844a899271023d8d445f7fc728e3ad71916490cd9783464684967594b07cda05dd644b722bfcea9fade74d06cfc501e1a68abf118d6d03fbbf7d7707
Diffstat (limited to 'test/functional/minchainwork.py')
-rwxr-xr-xtest/functional/minchainwork.py93
1 files changed, 93 insertions, 0 deletions
diff --git a/test/functional/minchainwork.py b/test/functional/minchainwork.py
new file mode 100755
index 0000000000..e136dc2b7c
--- /dev/null
+++ b/test/functional/minchainwork.py
@@ -0,0 +1,93 @@
+#!/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")
+
+ # Because nodes in regtest are all manual connections (eg using
+ # addnode), node1 should not have disconnected node0. If not for that,
+ # we'd expect node1 to have disconnected node0 for serving an
+ # insufficient work chain, in which case we'd need to reconnect them to
+ # continue the test.
+ # NOTE: before commit 44407100ff9b478d6131a1c38ee993b50b1830df, regtest
+ # connections were not manual, so the reconnect is necessary.
+ if (len(self.nodes[0].getpeerinfo()) == 0):
+ connect_nodes(self.nodes[1], 0)
+
+ self.sync_all()
+ self.log.info("Blockcounts: %s", [n.getblockcount() for n in self.nodes])
+
+if __name__ == '__main__':
+ MinimumChainWorkTest().main()