Problem: Connecting a block already on disk requires reading and deserializing it. Doing this on the validation thread stalls validation and slows reindexing and initial block download.
This is a follow-up to #35295, which parallelized input prevout fetching during block connection.
Fix: Add a Chainstate-owned block fetcher that reads later blocks from disk while the current block is connected.
Start with synchronous 1-block read-ahead, then move reads to an eagerly started worker pool that persists across activations.
Keep caller-provided blocks on the direct path and refill a sliding read-ahead window.
During reorgs, start reading the first sibling while disconnecting the old tip.
Retry speculative failures synchronously when the block is needed.
-blockfetchthreads=<n> selects readers per chainstate, with a default of 2 and a cap of 16.
Setting it to 0 disables read-ahead. The window retains up to two blocks per reader, giving 4 by default.
Measurements favor 2 readers with a window of 4 or 8 blocks, so the default uses the smaller window.
Credit: The idea comes from bitcoindev1337, who had already implemented a similar design and reported comparable results.
<details><summary>Benchmark results</summary>
---- reindex-chainstate ----
1d6656c6b0 refactor: prepare block fetcher wiring
3547915bfb doc: add block read-ahead release note
2026-09-02 | reindex-chainstate | 964469 blocks | dbcache 2000 | i7-hdd | x86_64 | Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz | 8 threads | 62Gi RAM | HDD
Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=964469 -dbcache=2000 -reindex-chainstate -assumevalid=00000000000000000000ccebd6d74d9194d8dcdc1d177c478e094bfad51ba5ac -blocksonly -disablewallet -connect=0 -listen=0 -dnsseed=0 -printtoconsole=0 (COMMIT = 1d6656c6b024578db910f45f4a131f18d75a2ed0)
Time (abs ≡): 30017.350 s [User: 44516.820 s, System: 1392.820 s]
Benchmark 2: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=964469 -dbcache=2000 -reindex-chainstate -assumevalid=00000000000000000000ccebd6d74d9194d8dcdc1d177c478e094bfad51ba5ac -blocksonly -disablewallet -connect=0 -listen=0 -dnsseed=0 -printtoconsole=0 (COMMIT = 3547915bfb240f280188954c7c5b60ec90145ac5)
Time (abs ≡): 19609.006 s [User: 46710.915 s, System: 1466.050 s]
Relative speed comparison
1.53 COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=964469 -dbcache=2000 -reindex-chainstate -assumevalid=00000000000000000000ccebd6d74d9194d8dcdc1d177c478e094bfad51ba5ac -blocksonly -disablewallet -connect=0 -listen=0 -dnsseed=0 -printtoconsole=0 (COMMIT = 1d6656c6b024578db910f45f4a131f18d75a2ed0)
1.00 COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=964469 -dbcache=2000 -reindex-chainstate -assumevalid=00000000000000000000ccebd6d74d9194d8dcdc1d177c478e094bfad51ba5ac -blocksonly -disablewallet -connect=0 -listen=0 -dnsseed=0 -printtoconsole=0 (COMMIT = 3547915bfb240f280188954c7c5b60ec90145ac5)
ed7dd7cf4e Merge bitcoin/bitcoin#34371: wallet: allow importprunedfunds for spending transactions
c5aafe2557 doc: add block read-ahead release note
2026-09-29 | reindex-chainstate | 968869 blocks | dbcache 2000 | ssd-ryzen | x86_64 | AMD Ryzen 7 3700X 8-Core Processor | 16 threads | 62Gi RAM | SSD
Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=968869 -dbcache=2000 -reindex-chainstate -assumevalid=00000000000000000000ccebd6d74d9194d8dcdc1d177c478e094bfad51ba5ac -blocksonly -disablewallet -connect=0 -listen=0 -dnsseed=0 -printtoconsole=0 (COMMIT = ed7dd7cf4e1561a97edf72eba29a67b14e28c717)
Time (abs ≡): 12430.900 s [User: 36689.125 s, System: 2521.533 s]
Benchmark 2: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=968869 -dbcache=2000 -reindex-chainstate -assumevalid=00000000000000000000ccebd6d74d9194d8dcdc1d177c478e094bfad51ba5ac -blocksonly -disablewallet -connect=0 -listen=0 -dnsseed=0 -printtoconsole=0 (COMMIT = c5aafe25576d341451d679816ae0d1f8c8405c7e)
Time (abs ≡): 9562.801 s [User: 37275.991 s, System: 2185.462 s]
Relative speed comparison
1.30 COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=968869 -dbcache=2000 -reindex-chainstate -assumevalid=00000000000000000000ccebd6d74d9194d8dcdc1d177c478e094bfad51ba5ac -blocksonly -disablewallet -connect=0 -listen=0 -dnsseed=0 -printtoconsole=0 (COMMIT = ed7dd7cf4e1561a97edf72eba29a67b14e28c717)
1.00 COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=968869 -dbcache=2000 -reindex-chainstate -assumevalid=00000000000000000000ccebd6d74d9194d8dcdc1d177c478e094bfad51ba5ac -blocksonly -disablewallet -connect=0 -listen=0 -dnsseed=0 -printtoconsole=0 (COMMIT = c5aafe25576d341451d679816ae0d1f8c8405c7e)
---- IBD ----
ed7dd7cf4e Merge bitcoin/bitcoin#34371: wallet: allow importprunedfunds for spending transactions
7c4efd1174 doc: add block read-ahead release note
2026-09-29 | IBD | 968869 blocks | dbcache 4000 | ssd-ryzen | x86_64 | AMD Ryzen 7 3700X 8-Core Processor | 16 threads | 62Gi RAM | ext4 | SSD
Benchmark 1: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=968869 -dbcache=4000 -blocksonly -assumevalid=00000000000000000000748969ec33043c0e52a763c6dd5193861f559f2c72e3 -printtoconsole=0 (COMMIT = ed7dd7cf4e1561a97edf72eba29a67b14e28c717)
Time (mean ± σ): 19273.259 s ± 504.339 s [User: 25801.170 s, System: 3635.246 s]
Range (min … max): 18916.638 s … 19629.881 s 2 runs
Benchmark 2: COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=968869 -dbcache=4000 -blocksonly -assumevalid=00000000000000000000748969ec33043c0e52a763c6dd5193861f559f2c72e3 -printtoconsole=0 (COMMIT = 7c4efd1174070eba967fb0803c2080500b77ee10)
Time (mean ± σ): 16766.243 s ± 323.458 s [User: 25575.079 s, System: 2691.147 s]
Range (min … max): 16537.523 s … 16994.962 s 2 runs
Relative speed comparison
1.15 ± 0.04 COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=968869 -dbcache=4000 -blocksonly -assumevalid=00000000000000000000748969ec33043c0e52a763c6dd5193861f559f2c72e3 -printtoconsole=0 (COMMIT = ed7dd7cf4e1561a97edf72eba29a67b14e28c717)
1.00 COMPILER=gcc ./build/bin/bitcoind -datadir=/mnt/my_storage/BitcoinData -stopatheight=968869 -dbcache=4000 -blocksonly -assumevalid=00000000000000000000748969ec33043c0e52a763c6dd5193861f559f2c72e3 -printtoconsole=0 (COMMIT = 7c4efd1174070eba967fb0803c2080500b77ee10)
</details>