backport: assumeutxo M5 — loadtxoutset end-to-end (bitcoin#27596 + cluster + E2E)#54
Open
PastaPastaPasta wants to merge 26 commits into
Open
backport: assumeutxo M5 — loadtxoutset end-to-end (bitcoin#27596 + cluster + E2E)#54PastaPastaPasta wants to merge 26 commits into
PastaPastaPasta wants to merge 26 commits into
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
4 tasks
PastaPastaPasta
force-pushed
the
assumeutxo/m4-evo-snapshot
branch
from
July 12, 2026 14:29
52a0371 to
ed610de
Compare
PastaPastaPasta
force-pushed
the
assumeutxo/m5-loadtxoutset
branch
from
July 12, 2026 14:37
a0dd520 to
5737704
Compare
PastaPastaPasta
force-pushed
the
assumeutxo/m4-evo-snapshot
branch
from
July 12, 2026 16:01
ed610de to
609b604
Compare
PastaPastaPasta
force-pushed
the
assumeutxo/m5-loadtxoutset
branch
from
July 12, 2026 16:03
5737704 to
da6888b
Compare
PastaPastaPasta
force-pushed
the
assumeutxo/m4-evo-snapshot
branch
from
July 13, 2026 22:45
609b604 to
11d1fb7
Compare
PastaPastaPasta
force-pushed
the
assumeutxo/m5-loadtxoutset
branch
from
July 13, 2026 22:45
da6888b to
6ac9425
Compare
PastaPastaPasta
force-pushed
the
assumeutxo/m4-evo-snapshot
branch
from
July 14, 2026 05:10
11d1fb7 to
022d3e6
Compare
PastaPastaPasta
force-pushed
the
assumeutxo/m5-loadtxoutset
branch
from
July 14, 2026 05:10
6ac9425 to
4048e5c
Compare
This backports the first commit of bitcoin#25494, which introduces kernel/chain.{h,cpp}, interfaces::BlockInfo, and kernel::MakeBlockInfo. The remaining index refactoring commits are intentionally excluded. Upstream commit: a0b5b4a
This is an early partial pick of bitcoin#27596; the remainder will be backported later. Upstream commit: c6af23c
5d227a6 rpc: Use Ensure(Any)Chainman in assumeutxo related RPCs (Fabian Jahr) 710e5db doc: Drop references to assumevalid in assumeutxo docs (Fabian Jahr) 1ff1c34 test: Rename wait_until_helper to wait_until_helper_internal (Fabian Jahr) a482f86 chain: Rename HaveTxsDownloaded to HaveNumChainTxs (Fabian Jahr) 82e48d2 blockstorage: Let FlushChainstateBlockFile return true in case of missing cursor (Fabian Jahr) 73700fb validation, test: Improve and document nChainTx check for testability (Fabian Jahr) 2c9354f doc: Add snapshot chainstate removal warning to reindexing documentation (Fabian Jahr) 4e915e9 test: Improvements of feature_assumeutxo (Fabian Jahr) a47fbe7 doc: Add and edit some comments around assumeutxo (Fabian Jahr) 0a39b8c validation: remove unused mempool param in DetectSnapshotChainstate (Fabian Jahr) Pull request description: Addressing what I consider to be non- or not-too-controversial comments from bitcoin#27596. Let me know if I missed anything among the many comments that can be easily included here. ACKs for top commit: ryanofsky: Code review ACK 5d227a6. Just suggested doc change and new EnsureChainman RPC cleanup commit since last review. Tree-SHA512: 6f7c762100e18f82946b881676db23e67da7dc3a8bf04e4999a183e90b4f150a0b1202bcb95920ba937a358867bbf2eca300bd84b9b1776c7c490410e707c267
7e40032 tests: assumeutxo: accept final height from either chainstate (James O'Beirne) 5bd2010 test: assumeutxo: avoid race in functional test (James O'Beirne) 7005a01 test: add wait_for_connect to BitcoinTestFramework.connect_nodes (James O'Beirne) Pull request description: Fixes bitcoin#28585. Fixes a few races within the assumeutxo tests: - In general, `-stopatheight` can't be used with `connect_nodes` safely because the latter performs blocking assertions that are racy with the stopatheight triggering. - Now that the snapshot chainstate is listed as `normal` after background validation, accept the final height from either chainstate. ACKs for top commit: MarcoFalke: lgtm ACK 7e40032 fjahr: Code review ACK 7e40032 achow101: ACK 7e40032 ryanofsky: Code review ACK 7e40032 Tree-SHA512: 8cbd2a0ca8643f94baa0ae3561dcf68c3519d5ba851c6049e1768f28cae6434f47ffc28d404bf38ed11030ce3f00aae0a8be3f6d563e6ae6680d83c928a173d8
…a list of chainstates a9ef702 assumeutxo: change getchainstates RPC to return a list of chainstates (Ryan Ofsky) Pull request description: Current `getchainstates` RPC returns "normal" and "snapshot" fields which are not ideal because it requires new "normal" and "snapshot" terms to be defined, and the definitions are not really consistent with internal code. (In the RPC interface, the "snapshot" chainstate becomes the "normal" chainstate after it is validated, while in internal code there is no "normal chainstate" and the "snapshot chainstate" is still called that temporarily after it is validated). The current `getchainstates` RPC is also awkward to use if you to want information about the most-work chainstate, because you have to look at the "snapshot" field if it exists, and otherwise fall back to the "normal" field. Fix these issues by having `getchainstates` just return a flat list of chainstates ordered by work, and adding a new chainstate "validated" field alongside the existing "snapshot_blockhash" field so it is explicit if a chainstate was originally loaded from a snapshot, and whether the snapshot has been validated. This change was motivated by comment thread in bitcoin#28562 (comment) ACKs for top commit: Sjors: re-ACK a9ef702 jamesob: re-ACK a9ef702 achow101: ACK a9ef702 Tree-SHA512: b364e2e96675fb7beaaee60c4dff4b69e6bc2d8a30dea1ba094265633d1cddf9dbf1c5ce20c07d6e23222cf1e92a195acf6227e4901f3962e81a1e53a43490aa
03f8208 doc: assumeutxo prune and index notes (Sjors Provoost) Pull request description: Based on recent comments on bitcoin#27596. ACKs for top commit: pablomartin4btc: re ACK 03f8208 ryanofsky: ACK 03f8208. Nice changes, these seem like very helpful notes Tree-SHA512: fe651b49f4d667400a3655899f27a96dd1eaf67cf9215fb35db5f44fb8c0313e7d541518be6791fec93392df24b909793f3886adb808e53228ed2a291165639d
…ssumeUTXO parameters fails 2e31250 test: check that loading snapshot not matching AssumeUTXO parameters fails (Sebastian Falbesoner) Pull request description: This PR adds test coverage for the failed loading of an AssumeUTXO snapshot in case the referenced block hash doesn't match the parameters in the chainparams. Right now, I expect this would be the most common error-case for `loadtxoutset` out in the wild, as for mainnet the `m_assumeutxo_data` map is empty and this error condition would obviously always be triggered for any (otherwise valid, correctly encoded) snapshot. Note that this test-case is the simplest scenario and doesn't cover any of the TODO ideas mentioned at the top of the functional test yet. ACKs for top commit: jamesob: ACK bitcoin@2e31250 Sjors: utACK 2e31250 achow101: ACK 2e31250 Tree-SHA512: 8bcb2d525c95fbc95f87d3e978ad717d95bddb1ff67cbe7d3b06e4783f0f1ffba32b17ef451468c39c23bc1b3ef1150baa71148c145275c386f2d4822d790d39
fa68571 test: Add assumeutxo test for wrong hash (MarcoFalke) Pull request description: Also: * Update test TODOs * Fix off-by-4 typo in test, remove `struct` import ACKs for top commit: fjahr: utACK fa68571 theStack: Code-review re-ACK fa68571 pablomartin4btc: re ACK fa68571 ryanofsky: Code review ACK fa68571 Tree-SHA512: 877653010efe4e20018827e8ec2801d036e1344457401f0c9e5d55907b817724201dd2e3f0f29505bbff619882c0c2cd731ecdcd209258bcefe11b86ff0205dd
…esn't match AssumeUTXO parameters 9620cb4 assumeutxo: fail early if snapshot block hash doesn't match AssumeUTXO parameters (Sebastian Falbesoner) Pull request description: Right now the `loadtxoutset` RPC call treats literally all files with a minimum size of 40 bytes (=size of metadata) as potential valid snapshot candidates and the waiting loop for seeing the metadata block hash in the headers chain is always entered, e.g.: ``` $ ./src/bitcoin-cli loadtxoutset ~/.vimrc <wait> bitcoind log: ... 2023-10-15T14:55:45Z [snapshot] waiting to see blockheader 626174207465730a7265626d756e207465730a656c62616e65207861746e7973 in headers chain before snapshot activation ... ``` There is no point in doing any further action though if we already know from the start that the UTXO snapshot loading won't be successful. This PR adds an assumeutxo parameter check immediately after the metadata is read in, so we can fail immediately on a mismatch: ``` $ ./src/bitcoin-cli loadtxoutset ~/.vimrc error code: -32603 error message: Unable to load UTXO snapshot, assumeutxo block hash in snapshot metadata not recognized (626174207465730a7265626d756e207465730a656c62616e 65207861746e7973) ``` This way, users who mistakenly try to load files that are not snapshots don't have to wait 10 minutes (=the block header waiting timeout) anymore to get a negative response. If a file is loaded which is a valid snapshot (referencing to an existing block hash), but one which doesn't match the parameters, the feedback is also faster, as we don't have to wait anymore to see the hash in the headers chain before getting an error. This is also partially fixes bitcoin#28621. ACKs for top commit: maflcko: lgtm ACK 9620cb4 ryanofsky: Code review ACK 9620cb4. This should fix an annoyance and bad UX. pablomartin4btc: tACK 9620cb4 Tree-SHA512: f88b865e9d46254858e57c024463f389cd9d8760a7cb30c190aa1723a931e159987dfc2263a733825d700fa612e7416691e4d8aab64058f1aeb0a7fa9233ac9c
621db2f test: assumeutxo file with unknown block hash (Fabian Jahr) Pull request description: Takes care of one of the open Todos in the assumeutxo functional test. Since an unknown block could be any hash, I simply chose one placeholder, it could also be a random string though. ACKs for top commit: maflcko: lgtm ACK 621db2f pablomartin4btc: cr ACK 621db2f theStack: ACK 621db2f ryanofsky: Code review ACK 621db2f Tree-SHA512: ee0438ce619f7348c6f88e39b0ea7ddddb8832956d9034ecc795c6033d5d905c09d11b7d0d5afc38231b2fd091ea7c1bd0a0be99d9c32c4e6357a25d76294142
… index + de-duplications d322368 test: De-dublicate/optimize assumeutxo test for further extensions (Fabian Jahr) 0a576d6 test: check au file with changed outpoint index (Fabian Jahr) Pull request description: Also doing some de-duplications. I kept the second commit separate for now as I am not 100% if this is overdoing it and makes it harder to reason about. But it also makes it easier to add more cases where we change more data. ACKs for top commit: maflcko: lgtm ACK d322368 achow101: ACK d322368 Tree-SHA512: be950a34b0ed50cb58459df47cff6513df19d834bf81815572cd26b10dee26e6f80866f0c44023cf246aafbbd256e62d23ce903e8b07fdff2297bc7065799bb8
…ulation Regenerate Dash regtest AssumeutxoData commitments after switching to the corrected per-coin hash_serialized_3 serialization. Procedure: build the post-change dashd/test_dash; run validation_chainstatemanager_tests snapshot activation cases for heights 110 and 200; run feature_assumeutxo.py to dump the deterministic height-299 snapshot; run rpc_dumptxoutset.py and feature_utxo_set_hash.py to refresh their deterministic golden values. Independently decode the preserved snapshot metadata/coins and hash outpoint || uint32_le((height << 1) + coinbase) || CTxOut with SHA256d to cross-check the three AssumeutxoData values. AssumeutxoData hash_serialized changes: height 110 9b2a277a3e3b979f1a539d57e949495d7f8247312dbc32bce6619128c192b44b -> ffb210087e1ed14526c0c08a3ec3a7c8e288079eaa68acb87d3d4d9fd746079f; height 200 8a5bdd92252fc6b24663244bbe958c947bb036dc1f94ccd15439f48d8d1cb4e3 -> 16e00a64db4fa48dd989dce86d8677f41797d52044e5fc86021aa88cc22b665b; height 299 2618646eb7f9b17a1982e206f94e8feec3efb3b7e7e97ade16b658eef7636519 -> d7f46f9830ea11f1bfc565b08f63b66f09e1403b54c988ede40461cf0846fcba. Also refresh rpc_dumptxoutset txoutset_hash to 3baec1b74f1f02749a2b519655f84326aa903ed00bca049950efffb927ac2b1d, its deterministic snapshot-file checksum from e8b1b739921ea48cc87021cd47adc711bf864c28fe82a0d1b3a139f32fe377b3 to 3ee2d4e678f0bcb73e28648434e4b32b5f6ffa600625905ad18fae2a02f42b26, and feature_utxo_set_hash to 8d439ff1e8fdffcdc5006e9b50c9ec5a33cf839313ab63401e6862a9c48bf093. evo_hash is unaffected and remains f2ccd3fef604df58a0c174489821e16912c9332969a267650cd040e85fb2adde at height 299. Verified that evo::GetEvoSnapshotHash hashes canonical CEvoSnapshot serialization with its own CSHA256 path and does not use coinstats TxOutSer, ApplyCoinHash, or ComputeUTXOStats.
…nvalid hash 811067c test: add coverage for snapshot chainstate not matching AssumeUTXO parameters (pablomartin4btc) 4a5be10 assumeutxo, blockstorage: prevent core dump on invalid hash (pablomartin4btc) Pull request description: While reviewing bitcoin#27596 (ran `loadtxoutset` in `mainnet` before `m_assumeutxo_data` is empty as [currently](https://github.com/jamesob/bitcoin/blob/434495a8c1496ca23fe35b84499f3daf668d76b8/src/kernel/chainparams.cpp#L175-L177) in master - back to 1b1d711), got a `core dumped`, so it seems there's a potential issue if new releases ever remove snapshot details or a semi-experienced user performs a `loadtxoutset` on a different "customised" binary version (not sure if this is a real use case). ``` 2023-10-18T17:42:52Z [init] Using obfuscation key for /tmp/.test_utxo_2/blocks/index: 0000000000000000 node/blockstorage.cpp:390 LoadBlockIndex: Assertion `GetParams().AssumeutxoForBlockhash(*snapshot_blockhash)' failed. Aborted (core dumped) ``` <details> <summary>This is also happening before IBD is completed (<code>background validation</code> still being performed as it can be seen in rpc <code>getchainstates</code>)</summary> ``` /src/bitcoin-cli -datadir=${AU_DATADIR} getchainstates { "headers": 813097, "chainstates": [ { "blocks": 368249, "bestblockhash": "00000000000000000b7a08224a1cb00d337100ba7a46c03d04b2c2d8964efc37", "difficulty": 52278304845.59168, "verificationprogress": 0.086288278873286, "coins_db_cache_bytes": 7969177, "coins_tip_cache_bytes": 14908338995, "validated": true }, { "blocks": 813097, "bestblockhash": "0000000000000000000270c9fdce7b17db64cca91f90106964b58e33a4d91089", "difficulty": 61030681983175.59, "verificationprogress": 0.999997140098457, "coins_db_cache_bytes": 419430, "coins_tip_cache_bytes": 784649420, "snapshot_blockhash": "00000000000000000002a7c4c1e48d76c5a37902165a270156b7a8d72728a054", "validated": false } ] } ``` </details> <details> <summary>Steps to reproduce the core dump error and its output:</summary> 1. Perform a `loadtxoutset` in `mainnet` on compiled `bitcoind` adding the block hash from Sjors's [commit](Sjors@24deb20). 2. Once step 1 finishes, remove the added code from step 1 and compile again or just compile `master` without any changes on top. 3. Run `bitcoind`, soon it'll crash with: ``` 2023-10-18T17:42:52Z [init] init message: Loading block index… 2023-10-18T17:42:52Z [init] Assuming ancestors of block 00000000000000000001a0a448d6cf2546b06801389cc030b2b18c6491266815 have valid signatures. 2023-10-18T17:42:52Z [init] Setting nMinimumChainWork=000000000000000000000000000000000000000052b2559353df4117b7348b64 2023-10-18T17:42:52Z [init] Prune configured to target 3000 MiB on disk for block and undo files. 2023-10-18T17:42:52Z [init] [snapshot] detected active snapshot chainstate (/tmp/.test_utxo_2/chainstate_snapshot) - loading 2023-10-18T17:42:52Z [init] [snapshot] switching active chainstate to Chainstate [snapshot] @ height -1 (null) 2023-10-18T17:42:52Z [init] Opening LevelDB in /tmp/.test_utxo_2/blocks/index 2023-10-18T17:42:52Z [init] Opened LevelDB successfully 2023-10-18T17:42:52Z [init] Using obfuscation key for /tmp/.test_utxo_2/blocks/index: 0000000000000000 node/blockstorage.cpp:390 LoadBlockIndex: Assertion `GetParams().AssumeutxoForBlockhash(*snapshot_blockhash)' failed. Aborted (core dumped) ``` </details> <details> <summary>After original change, error message output:</summary> ``` 2023-10-20T15:49:12Z [init] init message: Loading block index… 2023-10-20T15:49:12Z [init] Assuming ancestors of block 00000000000000000001a0a448d6cf2546b06801389cc030b2b18c6491266815 have valid signatures. 2023-10-20T15:49:12Z [init] Setting nMinimumChainWork=000000000000000000000000000000000000000052b2559353df4117b7348b64 2023-10-20T15:49:12Z [init] Prune configured to target 3000 MiB on disk for block and undo files. 2023-10-20T15:49:12Z [init] [snapshot] detected active snapshot chainstate (/tmp/.test_utxo_2/chainstate_snapshot) - loading 2023-10-20T15:49:12Z [init] [snapshot] switching active chainstate to Chainstate [snapshot] @ height -1 (null) 2023-10-20T15:49:12Z [init] Opening LevelDB in /tmp/.test_utxo_2/blocks/index 2023-10-20T15:49:12Z [init] Opened LevelDB successfully 2023-10-20T15:49:12Z [init] Using obfuscation key for /tmp/.test_utxo_2/blocks/index: 0000000000000000 2023-10-20T15:49:13Z [init] *** Assumeutxo data not found for the given blockhash '00000000000000000002a7c4c1e48d76c5a37902165a270156b7a8d72728a054'. 2023-10-20T15:49:13Z [init] Error: Assumeutxo data not found for the given blockhash '00000000000000000002a7c4c1e48d76c5a37902165a270156b7a8d72728a054'. Error: Assumeutxo data not found for the given blockhash '00000000000000000002a7c4c1e48d76c5a37902165a270156b7a8d72728a054'. 2023-10-20T15:49:13Z [init] Shutdown requested. Exiting. 2023-10-20T15:49:13Z [init] Shutdown: In progress... 2023-10-20T15:49:13Z [scheduler] scheduler thread exit 2023-10-20T15:49:13Z [shutoff] Flushed fee estimates to fee_estimates.dat. 2023-10-20T15:49:13Z [shutoff] Shutdown: done ``` </details> <details> <summary>Alternative on error handling using <code>return error()</code> instead of <code>return FatalError()</code> used in this PR, which produces a different output and perhaps confusing:</summary> ``` 2023-10-20T21:45:58Z [init] Using obfuscation key for /tmp/.test_utxo_2/blocks/index: 0000000000000000 2023-10-20T21:45:59Z [init] ERROR: Assumeutxo data not found for the given blockhash '00000000000000000002a7c4c1e48d76c5a37902165a270156b7a8d72728a054'. 2023-10-20T21:45:59Z [init] : Error loading block database. Please restart with -reindex or -reindex-chainstate to recover. : Error loading block database. Please restart with -reindex or -reindex-chainstate to recover. 2023-10-20T21:45:59Z [init] Aborted block database rebuild. Exiting. 2023-10-20T21:45:59Z [init] Shutdown: In progress... 2023-10-20T21:45:59Z [scheduler] scheduler thread exit 2023-10-20T21:45:59Z [shutoff] Flushed fee estimates to fee_estimates.dat. 2023-10-20T21:45:59Z [shutoff] Shutdown: done ``` </details> <details> <summary>Current state (including ryanofsky <a href="https://github.com/bitcoin/bitcoin/pull/28698#discussion_r1368635965">suggestion</a>), after code change, error message output:</summary> ``` 2023-10-25T02:29:57Z [init] Using obfuscation key for /home/pablo/.test_utxo_2/regtest/blocks/index: 0000000000000000 2023-10-25T02:29:57Z [init] *** Assumeutxo data not found for the given blockhash 'f09b5835f3f8b39481f2af3257bbc2e82845552d4d2d6d31cf520fc24263ed5b'. 2023-10-25T02:29:57Z [init] Error: A fatal internal error occurred, see debug.log for details Error: A fatal internal error occurred, see debug.log for details 2023-10-25T02:29:57Z [init] Shutdown requested. Exiting. 2023-10-25T02:29:57Z [init] Shutdown: In progress... 2023-10-25T02:29:57Z [scheduler] scheduler thread exit 2023-10-25T02:29:57Z [shutoff] Flushed fee estimates to fee_estimates.dat. 2023-10-25T02:29:57Z [shutoff] Shutdown: done ``` </details> ACKs for top commit: naumenkogs: ACK 811067c theStack: ACK 811067c ryanofsky: Code review ACK 811067c. Tree-SHA512: cfc137b0a4f638b99fd7dac2c35cc729ef71ae1166a2a8960a91055ec90841cb33aed589834012cfe0e157937e2a76a88d1020ea1df2bc98e1114eb1fc8eaae4
…on the assumeutxo invalid hash dump - follow-up bitcoin#28698 7de7685 test, assumeutxo: Use assert_debug_log for error details (pablomartin4btc) Pull request description: This is a follow-up on the invalid hash dump fix bitcoin#28698, [suggested](bitcoin#28698 (review)) by theStack and agreed by Sjors and ryanofsky. ACKs for top commit: Sjors: ACK 7de7685 maflcko: lgtm ACK 7de7685 Tree-SHA512: 036b3cef3084e3ead8923e8dcabe4fa7ebe97fb514d223aa38bc38df10337e3fe3113e42322178b58fb03fcd4511af4b5b56bceecbb7ded5b9758842c70db3f2
997b9a7 test: add assumeutxo wallet test (Sjors Provoost) Pull request description: Extracted from bitcoin#28616, this adds a (very) basic wallet test for assume utxo. It checks some circumstances where a backup can and can't be loaded. ACKs for top commit: maflcko: lgtm ACK 997b9a7 achow101: ACK 997b9a7 theStack: Code-review ACK 997b9a7 Tree-SHA512: 69474e56c6a46bb4f30fc54f8e5844766ac2a5f8226bb0b168d11ae1e3d4eae58570c1f1b4cc2b2f6f51b5d0e055bbe2bbd11684265215e01d4eb81ab4b7b0bb
PastaPastaPasta
force-pushed
the
assumeutxo/m4-evo-snapshot
branch
from
July 14, 2026 17:01
022d3e6 to
590e34b
Compare
PastaPastaPasta
force-pushed
the
assumeutxo/m5-loadtxoutset
branch
from
July 14, 2026 17:01
4048e5c to
02e40f9
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue being fixed or feature implemented
M1–M4 (#50, #51, #52, #53) built the persistence, role, and evo
snapshot-format machinery; this milestone exposes it end to end via
loadtxoutset. This is milestone 5/7, the largest unit of the whole series(43 files in the core RPC unit alone). The execution plan and per-unit ledger
(M5 section) are tracked outside the repo in a private gist, not checked in:
https://gist.github.com/PastaPastaPasta/aa52b1f89fb74a0566ba3b5e15afab6a
PR 5/7 in the stacked series — base is M4 (
assumeutxo/m4-evo-snapshot).What was done?
bitcoin#25494to introduceBlockInfo,MakeBlockInfo, and kernel/chain.{h,cpp}, followed by theChainstateRoleportion ofbitcoin#27596. These are the directprerequisites for the role-tagged notification work below.
bitcoin#27596(22 upstream commits) —loadtxoutsetandgetchainstatesRPCs;
AssumeutxoDatamodernization preservingevo_hash; role-taggednotifications replace the M2
BlockConnected/ChainStateFlushedsuppression guards (17-subscriber audit table in review docs; Dash-only
MN-list/UI notifications stay active-gated;
UpdatedBlockTip/BlockDisconnectedstay active-only per upstream); net_processingbackground-chain download; blockfile segmentation + multi-chainstate
pruning; mempool swap on activation;
feature_assumeutxo.pyported.Round 1 review found two issues: a height-200 regtest entry retaining a
null blockhash (caused a
LoadBlockIndexassert abort on restart) and anomitted upstream test hunk — both fixed with deterministic fixture hashes
and restart coverage.
bitcoin#28562..#28838(13 PRs). Gate1 raised anobjection confirmed by gate2 review: the initial Dash adaptation had
globally weakened
CheckBlockIndex's exact parent-sumnChainTxassert topaper over off-by-one regtest
AssumeutxoDatavalues — rejected as aworkaround; fixed by restoring the upstream assert byte-identical and
correcting the params instead.
#28685regenerated regtesthash_serialized_3vectors (evo_hash independently verified unaffected);#28698routes an upstreamAssertthrough Dash'sAbortNodefatal path;wallet_assumeutxo.pyported;#28852skipped as superseded by#29553in M6.
feature_assumeutxo_dash.pyplus regtest-assumeutxodataauthorization. Full lifecycle across 8 MNs/EvoNodes past DIP3/DIP8/DIP0024/
v19/v20, rotated + non-rotated quorums, dump→loadtxoutset→deep-state
verify, ChainLock/InstantSend verification pre-completion, signing/MN-mode
refusals, background completion with evo comparisons, 4-phase restarts
(exercising M3's crash recovery), and UTXO-only/tampered-evo rejection.
Round 1 review found the equality checks compared identifiers rather than
deterministic state — fixed with normalized ProTx + per-quorum
member/key/commitment comparison. New regtest-only
-assumeutxodata=<h>:<utxo_hash>:<evo_hash>:<nchaintx>:<blockhash>(neededbecause MN fixtures aren't deterministic across runs); ignored on
non-regtest, duplicates/collisions rejected. Four production fixes were
flushed out by the full lifecycle run.
-prune=550(upstream clamped targets toMIN_DISK_SPACE_FOR_BLOCK_FILES,breaking supported sub-minimum targets — fixed while keeping the
multi-chainstate division);
interfaces::BlockInfomoved tokernel/chain.hto break a circular dependency.Runtime activation is supported for ordinary nodes;
loadtxoutsetREFUSESmasternode mode (live signing contexts aren't rebindable yet — documented
follow-up for a later series, not this one).
How Has This Been Tested?
make check: exit 0, 0 failures (final tree).feature_assumeutxo,feature_assumeutxo_dashE2E ~128s,wallet_assumeutxo),rpc_dumptxoutset, dip3 ×2, llmq signing ×2/rotation/chainlocks, mnehf,asset_locks, init, reindex, pruning, txindex — all passed.
milestone gate PASS on 2026-07-11.
Breaking Changes
loadtxoutsetandgetchainstatesare now reachable RPCs (previouslyunexposed on Dash). No prior Dash release exposed these, so no compatibility
break for existing users.
dumptxoutsetoutput now includes the v3 evosection from M4; snapshots taken before this series are not loadable (assumeutxo
is unreleased on Dash).
Checklist: