Skip to content

fix: reorg rollback blocked by GREATEST tip_num#157

Open
jxom wants to merge 1 commit intomainfrom
fix/reorg-tip-rollback
Open

fix: reorg rollback blocked by GREATEST tip_num#157
jxom wants to merge 1 commit intomainfrom
fix/reorg-tip-rollback

Conversation

@jxom
Copy link
Copy Markdown
Member

@jxom jxom commented Mar 31, 2026

Problem

update_tip_num uses GREATEST(sync_state.tip_num, EXCLUDED.tip_num) which makes tip_num monotonically increasing. During a chain reorganization, handle_reorg needs to roll tip_num back to the fork point so the sync engine re-fetches the canonical chain — but GREATEST prevents any decrease.

Severity: High — reorgs silently fail to update tip_num, causing the sync engine to skip re-syncing orphaned blocks with their canonical replacements.

Fix

Added rollback_tip_num() which uses a direct SET tip_num = $1 instead of GREATEST. Updated handle_reorg to use this new function. The normal forward-sync path still uses update_tip_num with GREATEST for safe monotonic advancement.

Changes

  • src/sync/writer.rs: Added rollback_tip_num() — unconditionally sets tip_num and head_num to the fork point
  • src/sync/engine.rs: handle_reorg() now calls rollback_tip_num instead of update_tip_num
  • tests/smoke_test.rs: 3 new tests:
    • test_rollback_tip_num_decreases_during_reorg — verifies tip_num can decrease
    • test_update_tip_num_still_monotonic_forward — verifies GREATEST still works for forward sync
    • test_rollback_then_forward_sync_resumes — verifies full rollback→resume cycle

Testing

cargo check  ✅
cargo test   ✅ (4/4 passed)

The update_tip_num SQL used GREATEST(current, new) which prevented
tip_num from ever decreasing. During a reorg, handle_reorg needs to
roll tip_num back to the fork point so the sync engine re-fetches
the canonical chain.

Added rollback_tip_num() that uses a direct SET instead of GREATEST,
and updated handle_reorg to use it. The normal forward-sync path
still uses update_tip_num with GREATEST for monotonic advancement.

Tests verify:
- tip_num decreases during reorg via rollback_tip_num
- tip_num still advances monotonically via update_tip_num (GREATEST)
- After rollback, forward sync resumes and advances past old tip

Amp-Thread-ID: https://ampcode.com/threads/T-019d458d-01b9-76ca-9fb1-bfbd3729d359
Co-authored-by: Amp <amp@ampcode.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant