Skip to content

Move the whitelist from a single instance-storage Vec to per-address persistent entries #1421

Open
Tekh134/Callora-Contracts
#1

Description

@greatest0fallt1me

Summary

callora-whitelist keeps every whitelisted address in one Vec<Address> under StorageKey::WhitelistList in instance storage. Instance storage is loaded on every call to the contract, so each added address makes every call more expensive, including is_whitelisted, get_admin and the cooldown views. contains is O(n). Once the instance entry reaches the ledger-entry size limit, add_address can no longer write and the whitelist stops growing. This issue moves to O(1) per-address persistent membership, with paginated enumeration.

Background and evidence

  • contracts/whitelist/src/lib.rs:
    • The StorageKey::WhitelistList variant is at line 47.
    • add_address (lines 253–290) does instance().get::<Vec<Address>>(&WhitelistList), then list.contains(&address), then push_back, then instance().set.
    • remove_address (line 299), clear_all (line 355), is_whitelisted (line 386) and get_whitelist (line 405) all load the whole vector.
  • A related event wart in the same file: set_admin (around lines 160–173) publishes two admin_nominated events with different topic shapes, one legacy and one versioned.

Scope

In scope

  1. New storage. Add StorageKey::Member(Address) -> bool in persistent storage, with TTL extended on write and on is_whitelisted, and StorageKey::MemberCount -> u32 in instance storage.
  2. Paginated enumeration. Add get_whitelist_page(start, limit), backed by a paged index such as IndexPage(u32) (see the settlement index pattern), with a MAX_PAGE cap. Either keep get_whitelist() capped and marked deprecated, or remove it, and document the choice in docs/MIGRATION.md.
  3. clear_all. Make it bounded: clear_page(limit), or a generation counter that invalidates every member in O(1). Document the choice.
  4. Migration. Add an admin-only migrate_list(limit) that drains the legacy WhitelistList vector into persistent entries in chunks. is_whitelisted consults both stores until the migration completes.
  5. Events. Drop the duplicate legacy admin_nominated publish.

Out of scope

  • Cooldown semantics (admin::guard).
  • The vault's internal allowlist.

Design constraints

  • Bounded reads. is_whitelisted costs at most two storage reads.
  • Events: address_added and address_removed keep their current topic shape.
  • Error precedence: auth, then cooldown, then membership.
  • Budget: a before/after cost_estimate for is_whitelisted with 1, 100 and 1 000 members.

Test plan

# Scenario Expected
1 Add then is_whitelisted true; count +1
2 Add a duplicate AddressAlreadyInWhitelist
3 Remove a non-member AddressNotInWhitelist
4 1 000 members, is_whitelisted CPU flat versus the 1-member case (±10%)
5 get_whitelist_page walk every member exactly once
6 Legacy Vec with 300 entries, migrate_list(100) ×3 all migrated; the legacy key removed
7 clear_all is_whitelisted false for all; bounded cost
8 set_admin exactly one admin_nominated event
9 Member TTL extended on add and on read

Regression proof. On main, row 4 shows linear CPU growth.

Acceptance criteria

  • All test plan rows pass (cargo test -p callora-whitelist).
  • cargo fmt --all -- --check and cargo test --workspace pass, and CI is green.
  • The budget table is in the PR, and docs/MIGRATION.md is updated.
  • Coverage of lib.rs is at least 95%.

Getting started

git checkout -b perf/whitelist-persistent-membership
cargo test -p callora-whitelist

PR requirements

  • Link this issue (Closes #<n>).
  • Example commit: perf(whitelist): per-address persistent membership with paged index.

Priority rationale

Medium. Storage redesign with migration in one contract. It removes a hard scaling ceiling and per-call cost growth.

Activity

  1. YoungBoss04 commented on Oct 18, 2026

    @YoungBoss04

    @YoungBoss04 has applied to work on this issue as part of the Stellar Wave Program's 10th wave.

    Hi, I'd love to contribute to this issue and take it on. Thanks for considering my request.

    ℹ️ Repo Maintainers: To accept this application, review their application or assign @YoungBoss04 to this issue.

  2. Tekh134 commented on Oct 19, 2026

    @Tekh134
    Contributor

    @Tekh134 has applied to work on this issue as part of the Stellar Wave Program's 10th wave.

    hello maintainer, i will be glad to take up this issue . please get me assigned. thank you

    ℹ️ Repo Maintainers: To accept this application, review their application or assign @Tekh134 to this issue.

  3. drips-wave commented on Oct 19, 2026

    @drips-wave

    Congratulations, @Tekh134! 🎉 Your application was accepted by the repo's maintainers, and the issue is due on October 22, 2026.

    🧑‍💻 @Tekh134: Please resolve the issue such that the repo's maintainers have enough time to review your contribution before the due date. You'll earn Points for completing the issue on-time, which will make you eligible for a share of the Stellar Wave Program's reward pool.

    Warning

    When opening a PR, please link it to this issue to ensure it gets tracked accurately. Points are awarded when this issue is marked as completed by the maintainer.

    🤠 Repo maintainers: Please keep an eye on the contributor's progress and review their work before the due date. You can manage this issue, including adjusting its complexity and points, here.

    🌊 Happy Wave 🌊

  4. added a commit that references this issue on Oct 20, 2026
    50a6f72
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions