Skip to content

Commit 947c25e

Browse files
committed
Merge #12431: Only call NotifyBlockTip when chainActive changes
f98b543 Only call NotifyBlockTip when the active chain changes (James O'Beirne) 152b7fb [tests] Add a (failing) test for waitforblockheight (James O'Beirne) Pull request description: This is a subset of the more controversial bitcoin/bitcoin#12407, but this also adds a test demonstrating the bug. In InvalidateBlock, we're calling NotifyBlockTip with the now-invalid block's prev regardless of what chain the ancestor block is on. This could create numerous issues, but it at least screws up `waitforblockheight` (or anything else relying on `rpc/blockchain.cpp:latestblock`) when InvalidateBlock is called on a block not in chainActive, which can happen via RPC. Only call NotifyBlockTip when the block being marked invalid is on the active chain. Tree-SHA512: 9a54fe5e8c7eb489daf5df4483c0986129e871e2ca931a456ba869ecb5d5a8d4f7bd27ccc9e711e9292c9ed79ddef896c85d0e81fc76883503e327995b0e914f
2 parents e057589 + f98b543 commit 947c25e

File tree

2 files changed

+62
-1
lines changed

2 files changed

+62
-1
lines changed

src/validation.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2780,7 +2780,11 @@ bool CChainState::InvalidateBlock(CValidationState& state, const CChainParams& c
27802780
}
27812781

27822782
InvalidChainFound(pindex);
2783-
uiInterface.NotifyBlockTip(IsInitialBlockDownload(), pindex->pprev);
2783+
2784+
// Only notify about a new block tip if the active chain was modified.
2785+
if (pindex_was_in_chain) {
2786+
uiInterface.NotifyBlockTip(IsInitialBlockDownload(), pindex->pprev);
2787+
}
27842788
return true;
27852789
}
27862790
bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex) {

test/functional/rpc_blockchain.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,18 @@
3232
assert_is_hex_string,
3333
assert_is_hash_string,
3434
)
35+
from test_framework.blocktools import (
36+
create_block,
37+
create_coinbase,
38+
)
39+
from test_framework.messages import (
40+
msg_block,
41+
)
42+
from test_framework.mininode import (
43+
P2PInterface,
44+
network_thread_start,
45+
)
46+
3547

3648
class BlockchainTest(BitcoinTestFramework):
3749
def set_test_params(self):
@@ -46,6 +58,7 @@ def run_test(self):
4658
self._test_getdifficulty()
4759
self._test_getnetworkhashps()
4860
self._test_stopatheight()
61+
self._test_waitforblockheight()
4962
assert self.nodes[0].verifychain(4, 0)
5063

5164
def _test_getblockchaininfo(self):
@@ -241,6 +254,50 @@ def _test_stopatheight(self):
241254
self.start_node(0)
242255
assert_equal(self.nodes[0].getblockcount(), 207)
243256

257+
def _test_waitforblockheight(self):
258+
self.log.info("Test waitforblockheight")
259+
260+
node = self.nodes[0]
261+
262+
# Start a P2P connection since we'll need to create some blocks.
263+
node.add_p2p_connection(P2PInterface())
264+
network_thread_start()
265+
node.p2p.wait_for_verack()
266+
267+
current_height = node.getblock(node.getbestblockhash())['height']
268+
269+
# Create a fork somewhere below our current height, invalidate the tip
270+
# of that fork, and then ensure that waitforblockheight still
271+
# works as expected.
272+
#
273+
# (Previously this was broken based on setting
274+
# `rpc/blockchain.cpp:latestblock` incorrectly.)
275+
#
276+
b20hash = node.getblockhash(20)
277+
b20 = node.getblock(b20hash)
278+
279+
def solve_and_send_block(prevhash, height, time):
280+
b = create_block(prevhash, create_coinbase(height), time)
281+
b.solve()
282+
node.p2p.send_message(msg_block(b))
283+
node.p2p.sync_with_ping()
284+
return b
285+
286+
b21f = solve_and_send_block(int(b20hash, 16), 21, b20['time'] + 1)
287+
b22f = solve_and_send_block(b21f.sha256, 22, b21f.nTime + 1)
288+
289+
node.invalidateblock(b22f.hash)
290+
291+
def assert_waitforheight(height, timeout=2):
292+
assert_equal(
293+
node.waitforblockheight(height, timeout)['height'],
294+
current_height)
295+
296+
assert_waitforheight(0)
297+
assert_waitforheight(current_height - 1)
298+
assert_waitforheight(current_height)
299+
assert_waitforheight(current_height + 1)
300+
244301

245302
if __name__ == '__main__':
246303
BlockchainTest().main()

0 commit comments

Comments
 (0)