restore: validate sysvars before accepting snapshots - #11498
ripatel-fd with Copilot wants to merge 8 commits into
Conversation
There was a problem hiding this comment.
Copilot wasn't able to review any files in this pull request.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Co-authored-by: ripatel-fd <113896534+ripatel-fd@users.noreply.github.com>
Co-authored-by: ripatel-fd <113896534+ripatel-fd@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
Missing semantic validation can permit crashes, incorrect rent calculations, and unsafe epoch-reward state.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (3)
src/discof/restore/fd_snapin_tile.c:450
FD_SYSVAR_FLAG_VALIDonly checks that EpochRewards is structurally decodable (including thatactiveis boolean). An active record with zero/oversizednum_partitions,distributed_rewards > total_rewards, or overflowing distribution bounds still passes; reward reconstruction later casts the count touintand indexes fixedMAX_PARTITIONS_PER_EPOCHarrays, so a crafted snapshot can cause out-of-bounds access. Validate the active-reward invariants before accepting the snapshot.
for( ulong i=0UL; i<FD_SYSVAR_CACHE_ENTRY_CNT; i++ ) {
/* Agave restore requires Rent; Firedancer also requires Clock. */
if( FD_UNLIKELY( (i==FD_SYSVAR_clock_IDX || i==FD_SYSVAR_rent_IDX) &&
src/discof/restore/fd_snapin_tile.c:450
- A structurally valid Rent value can still overflow runtime rent arithmetic. For thresholds 1.0 and 2.0,
fd_rent_exempt_minimum_balancedirectly multiplieslamports_per_uint8_yearby account size, so values above the supported limits wrap and produce incorrect balances. Reject those values during snapshot verification.
if( FD_UNLIKELY( (i==FD_SYSVAR_clock_IDX || i==FD_SYSVAR_rent_IDX) &&
src/discof/restore/fd_snapin_tile.c:455
- The generic validator accepts compact SlotHashes encodings (for example, an 8-byte zero-length vector), but
fd_sysvar_slot_hashes_updatelater requires the fullFD_SYSVAR_SLOT_HASHES_BINCODE_SZbacking account and terminates otherwise. Require the full size here so a malformed snapshot is rejected gracefully instead of crashing on the first update.
if( FD_UNLIKELY( ctx->sysvars.accounts[ i ].present &&
- Files reviewed: 2/2 changed files
- Comments generated: 1
- Review effort level: Balanced
Co-authored-by: ripatel-fd <113896534+ripatel-fd@users.noreply.github.com>
ripatel-fd
left a comment
There was a problem hiding this comment.
everything looks good except asan guard, and vertical alignment for multiline ifs (off-by-one). don't fix anything else
Co-authored-by: ripatel-fd <113896534+ripatel-fd@users.noreply.github.com>
ripatel-fd
left a comment
There was a problem hiding this comment.
still 2 vertical alignment issues
Co-authored-by: ripatel-fd <113896534+ripatel-fd@users.noreply.github.com>
┌─ ⚡ PERF · 204a4ec vs main@c102002 ─────────────────────────────────
│ SUITE BASELINE NEW Δ
│ replay tps, mainnet 30,872 tps 30,918 tps · +0.15%
│ bench tps, localnet 830,926 tps 831,270 tps · +0.04%
│ snapshot load, testnet 15.16 s 15.16 s · -0.02%
│ mem total, mainnet 164.38 GiB 164.38 GiB · 0.00%
│ mem total, testnet 95.38 GiB 95.38 GiB · 0.00%
│ clean compile, firedancer 305.2 cpu·s 305.5 cpu·s · +0.07%
│ binary size, firedancer 68.42 MB 68.43 MB · +0.01%
├─────────────────────────────────────────────────────────────────────
@@ 0 REGRESSIONS · 0 WARNINGS · 0 IMPROVED · 7 NOISE @@
└─────────────────────────────────────────────────────────────────────history · 2 pushes ┌─ HISTORY · Δ vs main, per push, newest first ─────────────────────────
│ HEAD TPS BENCH SNAP MEM·M MEM·T COMPILE BINARY
│ 204a4ec +0.15% +0.04% -0.02% 0.00% 0.00% +0.07% +0.01%
│ 6a61060 -0.07% +0.16% +0.02% 0.00% 0.00% +0.23% +0.01%
└─────────────────────────────────────────────────────────────────────── |
|
@copilot fix all the issues in resolved comments they have been ignored |
Co-authored-by: ripatel-fd <113896534+ripatel-fd@users.noreply.github.com>
Addressed all resolved feedback, including removing the ASAN pragma guard, in |
|
@copilot the asan failure is too much stack usage. declare big variables as globals (static) instead of on the stack to fix it. targeted approach >1MB or so vars only not everything |
Co-authored-by: ripatel-fd <113896534+ripatel-fd@users.noreply.github.com>
Head branch was pushed to by a user without write access
Fixed in |
|
Blocked on Manik's snapshot loader refactor |
Restore validates SlotHistory but allows other malformed sysvars to reach replay assertions. Extend validation using Agave invariants and reject invalid snapshots through the existing retry protocol.
NEXT/DONE.