diff options
author | Ryan Ofsky <ryan@ofsky.org> | 2024-02-02 10:59:24 -0500 |
---|---|---|
committer | Ryan Ofsky <ryan@ofsky.org> | 2024-03-18 11:28:40 -0500 |
commit | 0391458d767b842a7925785a7053400c0e1cb55a (patch) | |
tree | 2559d852d988ef312c4f113601ba309dddf5b442 | |
parent | ef29c8b662309a438121a83f27fd7bdd1779700c (diff) |
test: assumeutxo stale block CheckBlockIndex crash test
Add a test for a CheckBlockIndex crash that would happen before previous
"assumeutxo: Get rid of faked nTx and nChainTx values" commit.
The crash was an assert failure in the (pindex->nChainTx == pindex->nTx +
prev_chain_tx) check that would previously happen if a snapshot was loaded, and
a block was submitted which forked from the chain before the snapshot block and
after the last downloaded background chain block. This block would not be
marked assumed-valid because it would not be an ancestor of the snapshot, and
it would have nTx set, nChainTx unset, and prev->nChainTx set with a fake
value, so the assert would fail. After the fix, prev->nChainTx is unset instead
of being set to a fake value, so the assert succeeds. This test was originally
posted by maflcko in
https://github.com/bitcoin/bitcoin/issues/29261#issuecomment-1918947945
Co-authored-by: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz>
-rwxr-xr-x | test/functional/feature_assumeutxo.py | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/test/functional/feature_assumeutxo.py b/test/functional/feature_assumeutxo.py index 27910c3909..04de8b299e 100755 --- a/test/functional/feature_assumeutxo.py +++ b/test/functional/feature_assumeutxo.py @@ -186,6 +186,14 @@ class AssumeutxoTest(BitcoinTestFramework): height = n0.getblockcount() hash = n0.getbestblockhash() blocks[height] = Block(hash, block_tx, blocks[height-1].chain_tx + block_tx) + if i == 4: + # Create a stale block that forks off the main chain before the snapshot. + temp_invalid = n0.getbestblockhash() + n0.invalidateblock(temp_invalid) + stale_hash = self.generateblock(n0, output="raw(aaaa)", transactions=[], sync_fun=self.no_op)["hash"] + n0.invalidateblock(stale_hash) + n0.reconsiderblock(temp_invalid) + stale_block = n0.getblock(stale_hash, 0) self.log.info("-- Testing assumeutxo + some indexes + pruning") @@ -270,6 +278,15 @@ class AssumeutxoTest(BitcoinTestFramework): assert_equal(n1.getblockchaininfo()["blocks"], SNAPSHOT_BASE_HEIGHT) + self.log.info("Submit a stale block that forked off the chain before the snapshot") + # Normally a block like this would not be downloaded, but if it is + # submitted early before the background chain catches up to the fork + # point, it winds up in m_blocks_unlinked and triggers a corner case + # that previously crashed CheckBlockIndex. + n1.submitblock(stale_block) + n1.getchaintips() + n1.getblock(stale_hash) + self.log.info("Submit a spending transaction for a snapshot chainstate coin to the mempool") # spend the coinbase output of the first block that is not available on node1 spend_coin_blockhash = n1.getblockhash(START_HEIGHT + 1) |