New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
snapshots: don't core dump when running -checkblockindex after loadtxoutset
#28791
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code CoverageFor detailed information about the code coverage, see the test coverage report. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. |
I'll check this soon. |
Maybe snapshots should include it? |
@@ -4859,7 +4859,9 @@ void ChainstateManager::CheckBlockIndex() | |||
// For testing, allow transaction counts to be completely unset. | |||
|| (pindex->nChainTx == 0 && pindex->nTx == 0) | |||
// For testing, allow this nChainTx to be unset if previous is also unset. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For reference, this whole assert block is likely wrong, see the thread at #28562 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the entire assert block is wrong. When a snapshot is loaded, the pindex->nTx
value is set to 1. So I'm not really sure what these exceptions would be allowing through.
But since this issue affects the v26 release, I've tried to keep the code delta as small and minimally impactful as possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removing the testing assert conditions, as explained by @maflcko in the comment link provided above, even with this fix, bitcoind
still crashes.
2023-11-09T15:54:40Z [dnsseed] dnsseed thread exit
bitcoind: validation.cpp:4880: void ChainstateManager::CheckBlockIndex(): Assertion `(pindex->nChainTx == pindex->nTx + prev_chain_tx) || pindex->IsAssumedValid()' failed.
Aborted (core dumped)
@luke-jr That would require storing an integer for every historical block. That would only add a megabyte or so to the snapshot size, so it would be quite doable. But it seems kinda silly when the field isn't used (except for this assert), and nothing else about the prior block data is validated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tACK cdc6ac4
I've managed to reproduce the issue
getblockchaininfo
-IBD
not completed./src/bitcoin-cli -datadir=${AU_DATADIR} getblockchaininfo { "chain": "main", "blocks": 800000, "headers": 815917, "bestblockhash": "00000000000000000002a7c4c1e48d76c5a37902165a270156b7a8d72728a054", "difficulty": 53911173001054.59, "time": 1690168629, "mediantime": 1690165851, "verificationprogress": 0.9438294771289651, "initialblockdownload": true, "chainwork": "00000000000000000000000000000000000000004fc85ab3390629e495bf13d5", "size_on_disk": 31288815, "pruned": true, "pruneheight": 800001, "automatic_pruning": true, "prune_target_size": 20971520000, "warnings": "This is a pre-release test build - use at your own risk - do not use for mining or merchant applications" }
getchainstates
-UTXO snapshot
at 800 000./src/bitcoin-cli -datadir=${AU_DATADIR} getchainstates { "headers": 815917, "chainstates": [ { "blocks": 71968, "bestblockhash": "0000000000d485b326ff1f88f2cb66fcc24c4345d1b151fa5a4d00476f74a977", "difficulty": 244.2132230923753, "verificationprogress": 0.0001072847948972671, "coins_db_cache_bytes": 419430, "coins_tip_cache_bytes": 784649420, "validated": true }, { "blocks": 800000, "bestblockhash": "00000000000000000002a7c4c1e48d76c5a37902165a270156b7a8d72728a054", "difficulty": 53911173001054.59, "verificationprogress": 0.9438294714681589, "coins_db_cache_bytes": 7969177, "coins_tip_cache_bytes": 14908338995, "snapshot_blockhash": "00000000000000000002a7c4c1e48d76c5a37902165a270156b7a8d72728a054", "validated": false } ] }
2023-11-09T14:44:55Z [msghand] New block-relay-only v1 peer connected: version: 70016, blocks=815999, peer=1
bitcoind: validation.cpp:4879: void ChainstateManager::CheckBlockIndex(): Assertion `(pindex->nChainTx == pindex->nTx + prev_chain_tx) || (pindex->nChainTx == 0 && pindex->nTx == 0) || (pindex->nChainTx == 0 && prev_chain_tx == 0 && pindex->pprev)' failed.
Aborted (core dumped)
I've verified this PR fixes the problem.
Since we know that loaded snapshots don't know tx count (*), should we not also avoid this by not letting the user call -checkblockindex
under these circumstances and return an error? I'd also add this warning in the documentation if that makes sense.
(*) Is this also happening after background validation is completed?
@@ -4859,7 +4859,9 @@ void ChainstateManager::CheckBlockIndex() | |||
// For testing, allow transaction counts to be completely unset. | |||
|| (pindex->nChainTx == 0 && pindex->nTx == 0) | |||
// For testing, allow this nChainTx to be unset if previous is also unset. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removing the testing assert conditions, as explained by @maflcko in the comment link provided above, even with this fix, bitcoind
still crashes.
2023-11-09T15:54:40Z [dnsseed] dnsseed thread exit
bitcoind: validation.cpp:4880: void ChainstateManager::CheckBlockIndex(): Assertion `(pindex->nChainTx == pindex->nTx + prev_chain_tx) || pindex->IsAssumedValid()' failed.
Aborted (core dumped)
No, that would be likely to cause problems in various workflows. It is entirely reasonable that -checkblockindex is set in a bitcoin.conf file, just as it is done by default in the RPC tests. In that case restarting the daemon after loading a snapshot but before validation of the historical blockchain is complete will cause it to be in an unstartable state, even though there is nothing wrong with the block index.
checkblockindex is useful for checking the integrity of the database, even before the whole historical blockchain is downloaded.
|
utACK cdc6ac4 This seems to be the best solution for this issue. |
ACK cdc6ac4 |
Post-merge ACK cdc6ac4 |
…xoutset` Github-Pull: bitcoin#28791 Rebased-From: cdc6ac4
…xoutset` Github-Pull: bitcoin#28791 Rebased-From: cdc6ac4
…xoutset` Github-Pull: bitcoin#28791 Rebased-From: cdc6ac4
Backported to 26 in #29209. |
11f3a7e Use hardened runtime on macOS release builds. (Mark Friedenbach) ac1b9a5 [test] import descriptor wallet with reorged parent + IsFromMe child in mempool (glozow) ecb8ebc [test] rescan legacy wallet with reorged parent + IsFromMe child in mempool (Gloria Zhao) 438ac29 snapshots: don't core dump when running -checkblockindex after `loadtxoutset` (Mark Friedenbach) 7ec3455 [log] mempool loading (glozow) fe0f8fe net: create I2P sessions with both ECIES-X25519 and ElGamal encryption (Jon Atack) fc62271 [refactor] Add helper for iterating through mempool entries (stickies-v) Pull request description: Backports for 26.x. Includes: - 453b481 from #28391 - #29179 - #29200 - #29227 - #28791 - #29127 ACKs for top commit: stickies-v: ACK 11f3a7e Tree-SHA512: 20ef871ec768f2328056d83f958e595b36ae9b8baa8a6e8b0e1f02c3df4b16965a8e05dcb4323afbcc9ecc4bdde10931232512022c39ee7e12baf9795bf25bf1
Transaction counts aren't known for block history loaded from a snapshot. If you start with
-checkblockindex
after loading a snapshot, the bitcoin daemon will core dump. The test suite does not check for this because all the snapshots have no non-coinbase transactions (all blocks prior to the snapshot are assumed to havenTx = 1
).Recommend for backport to 26.x