diff --git a/src/validation.cpp b/src/validation.cpp index a1c0ec853585..fb74ccb2bf93 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3412,6 +3412,17 @@ bool CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) { if (pindex->nStatus & BLOCK_FAILED_MASK) { pindex->nStatus &= ~BLOCK_FAILED_MASK; setDirtyBlockIndex.insert(pindex); + m_failed_blocks.erase(pindex); + // Mark all nearest BLOCK_FAILED_CHILD descendants (if any) as BLOCK_FAILED_VALID + auto itp = mapPrevBlockIndex.equal_range(pindex->GetBlockHash()); + for (auto jt = itp.first; jt != itp.second; ++jt) { + if (jt->second->nStatus & BLOCK_FAILED_CHILD) { + jt->second->nStatus |= BLOCK_FAILED_VALID; + m_failed_blocks.insert(jt->second); + setDirtyBlockIndex.insert(jt->second); + setBlockIndexCandidates.erase(jt->second); + } + } } pindex = pindex->pprev; } diff --git a/test/functional/rpc_invalidateblock.py b/test/functional/rpc_invalidateblock.py index a69a176d101e..5e843141c3db 100755 --- a/test/functional/rpc_invalidateblock.py +++ b/test/functional/rpc_invalidateblock.py @@ -60,5 +60,32 @@ def run_test(self): if node1height < 4: raise AssertionError("Node 1 reorged to a lower height: %d"%node1height) + self.log.info("Make sure ResetBlockFailureFlags does the job correctly") + self.restart_node(0, extra_args=["-checkblocks=5"]) + self.restart_node(1, extra_args=["-checkblocks=5"]) + connect_nodes_bi(self.nodes, 0, 1) + self.nodes[0].generate(10) + self.sync_blocks(self.nodes[0:2]) + newheight = self.nodes[0].getblockcount() + for j in range(2): + self.restart_node(0, extra_args=["-checkblocks=5"]) + tip = self.nodes[0].generate(10)[-1] + self.nodes[1].generate(9) + connect_nodes(self.nodes[0], 1) + self.sync_blocks(self.nodes[0:2]) + assert_equal(self.nodes[0].getblockcount(), newheight + 10 * (j + 1)) + assert_equal(self.nodes[1].getblockcount(), newheight + 10 * (j + 1)) + assert_equal(self.nodes[1].getbestblockhash(), tip) + + tip = self.nodes[1].getbestblockhash() + self.nodes[1].invalidateblock(self.nodes[1].getblockhash(newheight + 1)) + self.nodes[1].invalidateblock(self.nodes[1].getblockhash(newheight + 1)) + + assert_equal(self.nodes[1].getblockcount(), newheight) + self.restart_node(1, extra_args=["-checkblocks=5"]) + wait_until(lambda: self.nodes[1].getblockcount() == newheight + 20) + assert_equal(tip, self.nodes[1].getbestblockhash()) + + if __name__ == '__main__': InvalidateTest().main()