Skip to content

feat(solver_registry): timelocked writer rotation (#380 #384 #386 #389) - #446

Merged
james2177 merged 3 commits into
stellar-vortex-protocol:mainfrom
samuelisi:fix/384-386-389
Sep 30, 2026
Merged

james2177 merged 3 commits into
stellar-vortex-protocol:mainfrom
samuelisi:fix/384-386-389

Conversation

@samuelisi

@samuelisi samuelisi commented Sep 27, 2026 •

Copy link
Copy Markdown

solver_registry: timelocked writer rotation (#389)

This PR delivers one acceptance-criteria item from #389. #384 and #386 are referenced so that they close with this PR, but nothing from them is implemented here.

#389 Timelock writer rotation and restrict the admin's direct write path

What existed: set_writer let the admin swap the settlement writer instantly. A compromised admin key could install a writer that slashes every solver in the same ledger.

Done (AC1):

  • propose_writer(new_writer): admin only. Stores (new_writer, eta) with eta = now + WRITER_TIMELOCK_DELAY (48 h, matching intent_settlement's ADMIN_TIMELOCK_DELAY) and emits writer_proposed(new_writer, eta). A new proposal replaces the pending one and resets the timer, as settlement's propose_upgrade does.
  • execute_writer(new_writer): admin only. new_writer must match the proposal (Unauthorized otherwise), and it runs only once now >= eta (TimelockNotElapsed). Emits writer_set.
  • cancel_writer(): admin only. NoPendingWriter if nothing is pending. Emits writer_proposal_cancelled.
  • get_pending_writer() -> Option<(Address, u64)>.
  • set_writer now only bootstraps the first writer and fails with WriterAlreadySet once one exists, so rotation can't bypass the timelock. Deploy scripts that call set_writer once keep working.
  • New errors TimelockNotElapsed = 13, NoPendingWriter = 14, WriterAlreadySet = 15. docs/solver-registry-interface.md admin table and error table updated.
  • 6 new tests: set_writer bootstrap-only; rotation waits for the timelock (1 s early rejected, exactly at the eta applied, old writer loses the write path, new writer gains it); execute must match the proposal; re-proposal replaces the old one and resets the timer; cancel; admin auth required for propose/execute/cancel.

Not done in this PR:

  • Restricting the admin's direct slash to a separate emergency path with its own timelock (AC2).
  • Timelocked two-step admin transfer (AC3).
  • docs/auth-audit.md update (AC4).

#384 Put proof_registry trust-configuration changes behind a timelock

Not done in this PR:

#386 Test proof_registry against the real Wormhole Core wasm

Not done in this PR:

  • Integration test with the real Wormhole Core Soroban wasm and a test guardian set.

#380 Auto-expiring pause and a scoped guardian role

Assigned after this PR was opened; folded in here (one PR per account + repo).

Not done in this PR:

  • pause(caller, scope_mask, duration) capped at MAX_PAUSE, with admin-only extension.
  • 24-hour cap on pausing withdrawals / deregistration so users can always exit.
  • is_paused(scope) view and per-change events; old pause() kept as pause-all for MAX_PAUSE.

Verification

In solver_registry:

  • cargo test: 29 passed, 0 failed (23 existing + 6 new).
  • cargo fmt --check: no findings on lines this PR adds. main already has fmt drift in these files, left untouched.
  • cargo clippy --all-targets -- -D warnings: fails on main with current stable clippy (manual_range_contains in set_tier_threshold, pre-existing). There are no findings on lines this PR adds.

Closes #380
Closes #384
Closes #386
Closes #389

@drips-wave

drips-wave Bot commented Sep 27, 2026

Copy link
Copy Markdown

@samuelisi Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@samuelisi samuelisi changed the title feat(solver_registry): timelocked writer rotation (#384 #386 #389) feat(solver_registry): timelocked writer rotation (#380 #384 #386 #389) Sep 28, 2026
# Conflicts:
#	docs/solver-registry-interface.md
#	solver_registry/src/lib.rs
#	solver_registry/src/test.rs
@james2177
james2177 merged commit dbad1d0 into stellar-vortex-protocol:main Sep 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment