Skip to content

Fix/stellar wave 790 791 792 793 - #934

Open
whisper011 wants to merge 7 commits into
AtomicIP:mainfrom
whisper011:fix/stellar-wave-790-791-792-793
Open

Fix/stellar wave 790 791 792 793#934
whisper011 wants to merge 7 commits into
AtomicIP:mainfrom
whisper011:fix/stellar-wave-790-791-792-793

Conversation

@whisper011

Copy link
Copy Markdown

Summary

Fixes four security/correctness gaps in ip_registry and api-server:

  • ip_registry admin is permanently set to the contract's own address — admin-only functions are bricked #790ip_registry's admin was lazily set to the contract's own address (env.current_contract_address()) on first commit_ip/batch_commit_ip/batch_commit_ip_anonymous call, which no external account can ever authorize as. This permanently bricked every admin-gated function (upgrade, set_notary_public_key, resolve_dispute, slash_stake, update_reputation, batch_update_reputation, nominate_arbitrator, open_arbitration). Added a real initialize(admin) entrypoint (callable once, requires the admin's own auth) and a set_admin(new_admin) rotation path, removed the three self-referential init blocks, and fixed upgrade's vacuous self-comparison tautology.
  • validate_upgrade only checks the WASM hash isn't zero — no real compatibility validation #791validate_upgrade only rejected a zero WASM hash; any other hash passed regardless of whether it removed exported functions, storage keys, or renumbered error codes. It now takes a candidate UpgradeManifest (functions/storage-keys/error-codes) supplied by the off-chain tooling that built the candidate WASM, and rejects any upgrade that removes something the current contract relies on or reassigns an existing error code.
  • request_queue_middleware is a literal passthrough — RequestQueue is never applied to live traffic #792request_queue_middleware was a literal passthrough; the fully-implemented RequestQueue was never constructed or wired into the app. It's now constructed in main.rs and applied as a real middleware layer, with queue-depth/wait-time metrics exposed.
  • Request signatures are an unkeyed hash — anyone can forge a valid signature #793 — Request "signatures" were an unkeyed SHA-256 checksum of public request data (the secret_key parameter was never used), and the verification middleware was never mounted on the router. Replaced with real Ed25519 verification (mirroring auth::verify_stellar_signature), added a configurable replay-protection timestamp-skew window, and mounted the middleware on the IP/swap mutating endpoints.

Test plan

No working Rust toolchain was available in this environment to run cargo test/cargo build, so these changes are unverified by compilation or test execution — please run the suite in CI before merging.

  • cargo test -p ip_registry — including new tests: non-admin rejection, real-admin success, pre-initialize rejection, double-initialize rejection, admin rotation, validate_upgrade rejecting a removed function / renumbered error code and accepting a compatible manifest
  • cargo test -p api-server — including new request_queue integration tests (serves within capacity, rejects when full) and request_signing integration tests (valid signature allowed, wrong-key/tampered-body/missing-header rejected)
  • Manual smoke test of /ip/commit, /ip/transfer, and /swap/* write endpoints with a properly signed request

Closes #790
Closes #791
Closes #792
Closes #793

@drips-wave

drips-wave Bot commented Aug 26, 2026

Copy link
Copy Markdown

@whisper011 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment