Page MenuHomePhabricator

D6511.diff
No OneTemporary

D6511.diff

diff --git a/src/validation.cpp b/src/validation.cpp
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -2085,7 +2085,7 @@
std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
CBlock &block = *pblock;
if (!ReadBlockFromDisk(block, pindexDelete, consensusParams)) {
- return AbortNode(state, "Failed to read block");
+ return error("DisconnectTip(): Failed to read block");
}
// Apply the block atomically to the chain state.
@@ -2630,6 +2630,12 @@
// This is likely a fatal error, but keep the mempool consistent,
// just in case. Only remove from the mempool in this case.
disconnectpool.updateMempoolForReorg(config, false);
+
+ // If we're unable to disconnect a block during normal operation,
+ // then that is a failure of our local system -- we should abort
+ // rather than stay on a less work chain.
+ AbortNode(state,
+ "Failed to disconnect block; see debug.log for details");
return false;
}
diff --git a/test/functional/feature_abortnode.py b/test/functional/feature_abortnode.py
new file mode 100755
--- /dev/null
+++ b/test/functional/feature_abortnode.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python3
+# Copyright (c) 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 bitcoind aborts if can't disconnect a block.
+
+- Start a single node and generate 3 blocks.
+- Delete the undo data.
+- Mine a fork that requires disconnecting the tip.
+- Verify that bitcoind AbortNode's.
+"""
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import wait_until, get_datadir_path, connect_nodes
+import os
+
+
+class AbortNodeTest(BitcoinTestFramework):
+
+ def set_test_params(self):
+ self.setup_clean_chain = True
+ self.num_nodes = 2
+ self.extra_args = [["-noparkdeepreorg"], []]
+
+ def setup_network(self):
+ self.setup_nodes()
+ # We'll connect the nodes later
+
+ def run_test(self):
+ self.nodes[0].generate(3)
+ datadir = get_datadir_path(self.options.tmpdir, 0)
+
+ # Deleting the undo file will result in reorg failure
+ os.unlink(os.path.join(datadir, 'regtest', 'blocks', 'rev00000.dat'))
+
+ # Connecting to a node with a more work chain will trigger a reorg
+ # attempt.
+ self.nodes[1].generate(3)
+ with self.nodes[0].assert_debug_log(["Failed to disconnect block"]):
+ connect_nodes(self.nodes[0], self.nodes[1])
+ self.nodes[1].generate(1)
+
+ # Check that node0 aborted
+ self.log.info("Waiting for crash")
+ wait_until(lambda: self.nodes[0].is_node_stopped(), timeout=60)
+ self.log.info("Node crashed - now verifying restart fails")
+ self.nodes[0].assert_start_raises_init_error()
+
+
+if __name__ == '__main__':
+ AbortNodeTest().main()

File Metadata

Mime Type
text/plain
Expires
Sat, Mar 1, 12:11 (44 m, 42 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5187800
Default Alt Text
D6511.diff (3 KB)

Event Timeline