Skip to content
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

Merged
merged 1 commit into from Jan 16, 2024

Conversation

maaku
Copy link
Contributor

@maaku maaku commented Nov 4, 2023

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 have nTx = 1).

Recommend for backport to 26.x

@DrahtBot
Copy link
Contributor

DrahtBot commented Nov 4, 2023

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Code Coverage

For detailed information about the code coverage, see the test coverage report.

Reviews

See the guideline for information on the review process.

Type Reviewers
ACK pablomartin4btc, fjahr, achow101

If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

@fanquake
Copy link
Member

fanquake commented Nov 6, 2023

cc @pablomartin4btc

@ajtowns ajtowns added the Bug label Nov 6, 2023
@pablomartin4btc
Copy link
Member

I'll check this soon.

@luke-jr
Copy link
Member

luke-jr commented Nov 8, 2023

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.
Copy link
Member

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)

Copy link
Contributor Author

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.

Copy link
Member

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)

@maflcko maflcko mentioned this pull request Nov 8, 2023
@maaku
Copy link
Contributor Author

maaku commented Nov 9, 2023

@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.

Copy link
Member

@pablomartin4btc pablomartin4btc left a 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.
Copy link
Member

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)

@maaku
Copy link
Contributor Author

maaku commented Nov 9, 2023 via email

@fjahr
Copy link
Contributor

fjahr commented Jan 13, 2024

utACK cdc6ac4

This seems to be the best solution for this issue.

@achow101
Copy link
Member

ACK cdc6ac4

@achow101 achow101 merged commit a3fb1f8 into bitcoin:master Jan 16, 2024
16 checks passed
@achow101 achow101 mentioned this pull request Jan 16, 2024
@jamesob
Copy link
Member

jamesob commented Jan 16, 2024

Post-merge ACK cdc6ac4

glozow pushed a commit to glozow/bitcoin that referenced this pull request Jan 18, 2024
glozow pushed a commit to glozow/bitcoin that referenced this pull request Jan 18, 2024
glozow pushed a commit to glozow/bitcoin that referenced this pull request Jan 19, 2024
@fanquake
Copy link
Member

fanquake commented Feb 1, 2024

Backported to 26 in #29209.

fanquake added a commit that referenced this pull request Feb 16, 2024
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

10 participants