ACP: ResetSyncCheckpoint asserts on fresh-datadir init when latest hardened checkpoint is genesis (mis-ported SetBestChain -> ConnectTip) #48
Labels
No labels
enhancement
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
SubGeniusFinance/Offerings-to-Cthulhu#48
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Symptom
A v2.1.0 (post-#40) daemon started against a fresh testnet datadir aborts during init:
Repro:
Offeringsd -testnet -datadir=<empty dir>on any binary containing the #40 ACP wiring. 100% reproducible.Root cause
InitBlockIndex()→CheckCheckpointPubKey()sees no stored pubkey in a fresh leveldb, treats the master key as changed, and callsResetSyncCheckpoint()(checkpoints.cpp). That function's guard:uses the status-flag
CBlockIndex::IsInMainChain()(nStatus >= BLOCK_VALID_CHAIN). During fresh init, genesis is already the active tip but has not yet been flagged chain-valid, so the branch misfires withhash= genesis (testnet's latest hardened checkpoint IS genesis) and callsConnectTip(genesis)— whose preconditionpindexNew->pprev == chainActive.Tip()cannot hold for a block with nopprevwhen the tip is genesis itself.Underlying mis-port: the ppcoin lineage called
SetBestChain(state, pindex)here — a force-reorg-to-arbitrary-block primitive that does not exist in the 0.10 codebase. The port substitutedConnectTip, which can only extend the current tip by one block. The original call is still present, commented out, one line above.Blast radius
hashPendingCheckpointpath is taken.CheckCheckpointPubKeyreturns early. This is why the #40 regtest suite never exercised the path.Fix
In
ResetSyncCheckpoint():chainActive.Contains()instead of the status-flagIsInMainChain().ConnectTipwhen the checkpoint block directly extends the current tip (pindexCkpt->pprev == chainActive.Tip()); otherwise log and leave the reorg to the normalActivateBestChainmachinery instead of asserting the daemon down.ReadBlockFromDisk(the read block was never used).Fix lands on
feat/v2.1.0-nodens-prep; fresh-testnet-datadir start becomes part of the soak checklist.Fix landed on
feat/v2.1.0-nodens-prepatcabb1162and verified against the original repro: a fresh testnet datadir now initializes cleanly (ResetSyncCheckpoint: sync-checkpoint reset to <genesis>) and syncs from its peers. Existing datadirs take the unchanged already-on-chain path. Issue closes when the branch merges to main; fresh-datadir first-start on all three networks is now a standing item on the release soak checklist.Blast-radius correction — the bug predates #40 and is in the shipped v2.0.9-Eldersign tag.
While standing up a mixed-version peer for the ACP rehearsal, a v2.0.9 (2000900) binary hit the identical assertion on a fresh testnet datadir. The mis-ported
ConnectTipand its status-flag guard are part of the dormant ppcoin checkpoint lineage that has been live in the init path since the bipsoft line — #40 did not introduce it; the v2.1.0 branch merely inherited it. Nobody had fresh-initialized a testnet datadir with an Eldersign-lineage binary until now (prior soaks used v2.0.8.7-era builds, which take a different path).Corrected scope:
No re-release of v2.0.9 is warranted — testnet-only, workaround is seeding the datadir from any initialized copy — but the fix (
cabb1162) ships in v2.1.0.ACP rehearsal result (testnet, fix in place): broadcaster with the test-fixture key returned
"checkpointmaster": true; a second Phase-2-aware node loggedProcessSyncCheckpointand accepted within seconds; a v2.0.9 peer and two v2.0.8.7 peers each logged the expectedCSyncCheckpoint::CheckSignature() : verify signature failed(stale lineage key), assigned banscore 0, stayed connected, and did not crash. Mixed-version rollout risk on mainnet: cosmetic log noise on not-yet-upgraded peers only.