dash: self-derived MN-set checkpoint dump (--dump-mn-checkpoint H FILE) - #1268
Closed
frstrtr wants to merge 1 commit into
Closed
Conversation
Serialize a --replay-bulk DML fold's REGISTERED masternode set at a target height H to the checkpoint .inc payload (mn_checkpoint.hpp), SELF-DERIVED from the fold's own root-checked ReplayMNState -- no dashd RPC, no trusted protx snapshot (operator decision 2026-08-17). scriptPayout is taken verbatim from the ProRegTx/ProUpRegTx the fold replayed; nLastPaidHeight from the payee bookkeeping the fold already keeps (dashd BuildNewListFromBlock parity). Reward-safety is by REUSE: the 17-field order + conversions are the same the runtime parser reads and gen_mn_checkpoint.py writes; the digest is the shared mn_checkpoint_digest(); write_mn_checkpoint_inc() re-parses its own output through parse_mn_checkpoint() before writing, so it can never emit a file the runtime cold-start would refuse. REGISTERED, not valid- filtered: PoSe-banned MNs are emitted carrying poseBanHeight (isValid is re-derived as poseBanHeight==0). Load-bearing byte-order split preserved: proTxHash/collateralHash via GetHex (display), keyIDOwner/keyIDVoting via forward LE-limb bytes (matching hex_to_uint160), lines sorted by proTxHash display hex (matching the generator, NOT std::map internal order). - new src/impl/dash/coin/mn_checkpoint_dump.hpp: emit_mn_checkpoint_dump / emit_mn_record_line / write_mn_checkpoint_inc - replay_fold_consumer.hpp: one-shot set_dump_hook(H, fn), fired after the successful fold whose cursor first reaches H (separate from the W4 post_fold seam so both coexist) - main_dash.cpp: --dump-mn-checkpoint H FILE arms the hook on the --replay-fold consumer path; source line names the self-derived provenance - test_dash_mn_checkpoint.cpp: DashMnCheckpointDump round-trip KAT -- a replayed set dumps and parses back FIELD-IDENTICAL through parse_mn_checkpoint() (mirror of CheckpointSetIsFieldIdenticalToRpcSeed), plus sort-order, determinism, digest, .inc file, and fail-closed (empty / payee-less) cases Build: C2POOL_DASH_BLS=REAL. 173/173 in the checkpoint test target green.
Owner
Author
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.
Self-derived MN-set checkpoint DUMP (
--dump-mn-checkpoint H FILE)DRAFT — do not merge. Stacked on #1267 (
dash/mn-diff-store-straddle-memberset-assemble). DASHD-CUT, operator decision 2026-08-17.What this adds
A capability to serialize the
--replay-bulkDML fold's REGISTERED masternode set at a target height H to the checkpoint.incpayload format (mn_checkpoint.hpp), self-derived from the fold's own root-checked state — no dashd RPC, no trustedprotx listsnapshot.scriptPayoutis taken verbatim from the ProRegTx/ProUpRegTx the fold replayed;nLastPaidHeightfrom the payee bookkeeping the fold already keeps (dashdBuildNewListFromBlockparity). This is the emitter the operator's decision requires: the two fields not on the DIP-4 wire and not committed inmerkleRootMNListcome from the chain-replayed fold, not from a snapshot dashd never consumes.Reward-safety is by REUSE, not new code
mn_checkpoint.hpp) andgen_mn_checkpoint.pywrites.mn_checkpoint_digest().write_mn_checkpoint_inc()re-parses its own output throughparse_mn_checkpoint()(with the engine's network) before writing — it can never emit a file the runtime cold-start would refuse.poseBanHeight;isValidis re-derived asposeBanHeight==0.proTxHash/collateralHashviaGetHex(display),keyIDOwner/keyIDVotingvia forward LE-limb bytes (matchinghex_to_uint160), and lines sorted by proTxHash display hex (matching the generator, NOTstd::mapinternal order).merkleRootMNListself-check is the safety net — a diverged/poisoned fold never reaches the dump).Files
src/impl/dash/coin/mn_checkpoint_dump.hpp—emit_mn_checkpoint_dump/emit_mn_record_line/write_mn_checkpoint_incsrc/impl/dash/coin/replay_fold_consumer.hpp— one-shotset_dump_hook(H, fn), separate from the W4post_foldseam so both coexistsrc/c2pool/main_dash.cpp—--dump-mn-checkpoint H FILEarms the hook on the--replay-foldconsumer path; thesourceline names the self-derived provenancetest/test_dash_mn_checkpoint.cpp—DashMnCheckpointDumpround-trip KAT: a replayed set dumps and parses back field-identical throughparse_mn_checkpoint()(the replay-dumped analog ofCheckpointSetIsFieldIdenticalToRpcSeed), plus sort-order, determinism, digest,.incfile, and fail-closed (empty / payee-less) casesVerification (vm905, C2POOL_DASH_BLS=REAL, dashd ABSENT)
DashMnCheckpointDump.ReplayDumpedSetRoundTripsFieldIdenticalToParser,DashMnCheckpointDump.EmptyEngineAndPayeelessRefuse.test_dash_node_reception_wire: 173/173 passed.c2pool-dashbinary builds; runtime bannerDASH BLS backend: REAL;--dump-mn-checkpoint H FILEpresent in usage.How the integrator runs the long detached self-derive
The dump fires at H for any
--replay-foldrun that reaches H. The full DIP3→H replay (~1.49M blocks) is not run in-agent. See the workflow report for the exact background command, resume/capture dir, and the one remaining enabling note (a from-empty-DIP3 cold seed is separate arming infrastructure the prestate loader does not yet supply).