Skip to content

Accounts Refactor PR 1: Adding account -> [credential_id] mapping#2770

Open
citizen-stig wants to merge 7 commits intotheodore/multisig-upgradefrom
nikolai/accounts-refactor-part-1
Open

Accounts Refactor PR 1: Adding account -> [credential_id] mapping#2770
citizen-stig wants to merge 7 commits intotheodore/multisig-upgradefrom
nikolai/accounts-refactor-part-1

Conversation

@citizen-stig
Copy link
Copy Markdown
Member

@citizen-stig citizen-stig commented Apr 21, 2026

Description

PR 1 of the accounts refactor series. Introduces a new account_owners authorization set alongside the existing accounts map and stops writing to the legacy map from every code path. The legacy map remains readable so pre-upgrade state keeps routing.

What changed

  • New state: account_owners: StateMap<(address, credential_id), bool>.
  • InsertCredentialId now writes account_owners, not accounts.
  • Genesis writes authorizations to account_owners.
  • resolve_sender_address becomes read-only (no auto-create on miss).
  • New capabilities: is_authorized(addr, cred) and is_authorized_for(addr, cred).
  • accounts map kept purely as a read-only legacy fallback. No new writers.
  • hyperlane-solana-register migrated from resolve_sender_address to is_authorized_for.
  • Map uses boolean instead of unit type () because of limitations of rockbound: Refactoring for more explicit sentinel values handling rockbound#50

Trade-offs / behavioral deltas

  • InsertCredentialId(X) from sender A no longer makes X route to A. It only authorizes X for A in account_owners. When X later signs a V0 tx, the resolver returns X.into() (stateless default), unless a pre-upgrade entry exists in legacy accounts. Fund the canonical address (or rely on a pre-upgrade entry) if you need X to draw gas from A.
  • The "no hijacking" guard is narrower. exit_if_credential_exists now checks (sender, credential) in account_owners instead of global credential uniqueness in accounts. Authorizing someone else's credential for your own address now succeeds — harmless, since they still need the private key to sign.
  • get_account(credential_id) returns AccountEmpty for post-PR credentials. New writes don't land in accounts. A get_addresses_for_credential query for the new model ships in a follow-up; tooling owners should plan accordingly.
  • is_authorized_for gives legacy mappings exclusive priority. If a credential has a legacy accounts entry, only that address is authorized (canonical match and account_owners are not consulted). Doc updated to reflect this; code relies on the invariant that no code path writes both maps for the same credential.

Backward compatibility

  • On-chain state: pre-upgrade accounts entries keep routing until explicitly migrated.
  • Wire: AccountConfig, CallMessage, and tx schema unchanged.
  • Client-visible regression: get_account (see above).

Known gaps / deferred

  • DrainLegacyAccounts migration and get_addresses_for_credential query land in a later PR.
  • resolve_sender_address is now pure-read but still takes &mut self and StateAccessor, duplicating resolve_sender_address_read_only. Two callers in sov-capabilities need migration before the mutable variant can be deleted — deferred.
  • is_authorized_for legacy-first precedence is not enforced in code; relies on "no writer touches both maps for the same credential". Fine today, brittle if a future migration ever violates it.

  • Will be done when merging to dev I have updated CHANGELOG.md with a new entry if my PR makes any breaking changes or fixes a bug. If my PR removes a feature or changes its behavior, I provide help for users on how to migrate to the new behavior.
  • I have carefully reviewed all my Cargo.toml changes before opening the PRs. (Are all new dependencies necessary? Is any module dependency leaked into the full-node (hint: it shouldn't)?)

Linked Issues

Testing

New tests added in sov-accounts integration tests (test_setup_multisig_and_act, test_resolve_address_with_multi_credential_ownership, etc.). Existing test_multisig_signature_verification in auth_eip712 updated to seed the multisig's canonical address at genesis under the new model.

Docs

sov-accounts/README.md expanded with the three-relation model (legacy mapping / stateless canonical / explicit authorization). Function docstrings updated.

@citizen-stig citizen-stig changed the title PR 1: Adding account -> [credential_id] mapping Accounts Refactor PR 1: Adding account -> [credential_id] mapping Apr 22, 2026
Comment thread crates/module-system/module-implementations/sov-accounts/src/call.rs Outdated
Comment thread crates/module-system/module-implementations/sov-accounts/src/call.rs Outdated
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

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