Start a round if we are at genesis#12152
Conversation
|
Claude finished @ak88's task in 2m 59s —— View job Code Review: Start a round if we are at genesis
SummaryA clean, well-scoped fix. The previous guard in I verified the bootstrap state matches what I also traced the resulting No Critical / High / Medium issues found. Good test coverage with both a positive (leader proposes) and negative (non-leader stays quiet) case. Findings (all Low)
One thing worth a sanity check (not a blocker): because the trigger only fires once in |
| /// <summary> | ||
| /// True when this node is the round-1 leader on a freshly bootstrapped chain where | ||
| /// <see cref="IsSynced"/> is false only because genesis counts as syncing. | ||
| /// </summary> | ||
| private bool IsBootstrapFirstProposer() | ||
| { | ||
| if (_blockTree.Head?.Header is not XdcBlockHeader head || _xdcContext.CurrentRound != 1) | ||
| return false; | ||
|
|
||
| BlockRoundInfo qc = _xdcContext.HighestQC.ProposedBlockInfo; | ||
| if (qc.Round != 0 || qc.BlockNumber != head.Number || qc.Hash != head.Hash) | ||
| return false; | ||
|
|
||
| IXdcReleaseSpec spec = _specProvider.GetXdcSpec(head, 1); | ||
| return _epochSwitchManager.GetEpochSwitchInfo(head) is { Masternodes.Length: > 0 } | ||
| && IsMyTurn(head, 1, spec); | ||
| } |
There was a problem hiding this comment.
Minor: the doc summary says "freshly bootstrapped chain where IsSynced is false only because genesis counts as syncing", but QuorumCertificateManager.Initialize produces the identical state (HighestQC = round-0 QC pointing at head, SetNewRound(1)) for both genesis and the V2 SwitchBlock. So this method also returns true at the consensus activation block, not only at genesis. That's arguably correct (first V2 proposer), but the summary/IsBootstrapFirstProposer naming implies genesis-only — consider broadening the wording to avoid future confusion.
Also a small consistency nit: line 411 dereferences _xdcContext.HighestQC.ProposedBlockInfo directly, whereas the rest of the class (e.g. line 214) defensively null-checks HighestQC before use. HighestQC is non-nullable and always constructor-initialized, so this won't NRE in practice — just inconsistent with the surrounding defensive style.
|
@claude again |
|
Claude finished @ak88's task in 2m 2s —— View job Re-review: Start a round if we are at genesis
Since my last review (06-26) the branch grew three more commits: Core change — still correct ✅
New:
|
|
Claude finished @ak88's task in 2m 33s —— View job Re-review: Start a round if we are at genesis
Since the last pass (06-30) the branch added two commits: ✅ Basefee regression test addedThe ✅
|
|
Claude finished @ak88's task in 1m 18s —— View job Re-review: Start a round if we are at genesis
Since my last pass (06-30) two commits landed: ✅
|
|
Claude finished @ak88's task in 2m 28s —— View job Re-review: Start a round if we are at genesis
Since the last pass (07-01) one new commit landed: 🔴 Medium — a special-tx test still sets the old flag and will now fail
// SpecialTransactionsTests.cs:771
spec.IsTIPXDCXMiner = true; // IsTIPXDCXReceiver left at its default: falseThat test sends txs to
With Fix: set the receiver flag in the test setup (keep the miner flag too if you want to prove they're independent): spec.IsTIPXDCXMiner = true;
spec.IsTIPXDCXReceiver = true;
🟡 Low — the unused flag just swapped identityBefore this commit Core genesis-proposer logic — unchanged & still correct ✅
VerdictOne Medium: the new receiver-flag change breaks |
|
@claude again |
|
Claude finished @ak88's task in 1m 15s —— View job Re-review: Start a round if we are at genesis
Since the last pass (07-01 14:09, at ✅ Prior Medium resolved —
|
| bool bootstrapFirstProposer = IsBootstrapFirstProposer(); | ||
| if (IsSynced() || bootstrapFirstProposer) | ||
| { | ||
| if (!IsSynced() && bootstrapFirstProposer) |
There was a problem hiding this comment.
nit: we could cache IsSynced() in a local (like bootstrapFirstProposer) and simplify the inner condition to if (!isSynced), unless the second call was intentional. IsSynced() reads live block-tree state, so it could theoretically flip between the outer and inner checks.
Fixes a special case where we are the very first proposer in XDC, and we would otherwise not propose anything.
Also make sure that we start a timeout timer.