Accounts Refactor PR 2: Adding target_account#2771
Accounts Refactor PR 2: Adding target_account#2771citizen-stig wants to merge 8 commits intonikolai/accounts-refactor-part-1from
Conversation
1201dc0 to
5008b08
Compare
920da01 to
736575b
Compare
| state: &mut impl StateAccessor, | ||
| execution_context: ExecutionContext, | ||
| ) -> anyhow::Result<Context<S>> { | ||
| let sender = self.accounts.resolve_sender_address( | ||
| &auth_data.default_address, | ||
| &auth_data.credential_id, | ||
| state, | ||
| )?; | ||
| let sender = self.resolve_sender(auth_data, state)?; | ||
| // The tx sender & sequencer are the same entity | ||
| Ok(Context::new( | ||
| sender, |
There was a problem hiding this comment.
🚩 resolve_unregistered_context now routes through resolve_sender, changing unregistered sequencer path semantics
Before this PR, resolve_unregistered_context always called resolve_sender_address(default_address, credential_id, state). After this PR, it calls resolve_sender(auth_data, state) which, when auth_data.address is Some(X), performs a strict is_authorized check and uses X as both the sender and sequencer_rollup_address. The comment says "The tx sender & sequencer are the same entity", so using a target-routed address as the sequencer rollup address may be unintended. In practice, V0 transactions always set address: None and this path is primarily for sequencer registration, making this edge case unlikely to be triggered. But it's worth noting that the semantic contract of resolve_unregistered_context has broadened.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
The broadening is intentional. auth_data.address is a signed user declaration carried inside V1 bytes — enforcing is_authorized(X, credential_id) uniformly across resolve_context and resolve_unregistered_context keeps the V1 target_address invariant in one place. A V1 self-registering sequencer with target_address = Some(X) should still be required to prove the multisig credential is authorized for X; the alternative (skipping the check during registration only) would make the signed target_address field weaker in registration paths than in normal execution, which is a foot-gun. V0 sets address = None and is byte-identical to pre-PR behavior.
Added a doc comment above resolve_unregistered_context capturing this invariant in-code.
Description
Adds a signed target_address: Option<S::Address> field to V1 (multisig) transactions, threaded into AuthorizationData.address. resolve_context branches on it: Some(X) verifies (X, credential_id) ∈ account_owners via PR #2770 's is_authorized;
None keeps today's resolve_sender_address flow.
V0 is byte-identical. CHAIN HASH BREAKING for V1.
PR #2770 froze writes to the legacy credential_id → address map; InsertCredentialId now only marks (sender, credential) authorized, without rerouting that credential's default.
That means a rotated multisig (new keys → new credential_id.into()) has no way to keep acting as the original address. target_address is the signed channel that lets a signer declare which authorized address to execute as.
Design tradeoffs
Audit invariants
Notable side-effects
I have updatedCHANGELOG.mdwith 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.Cargo.tomlchanges before opening the PRs. (Are all new dependencies necessary? Is any module dependency leaked into the full-node (hint: it shouldn't)?)Linked Issues
sov-accountsrefactoring and extending #2772Testing
New tests are added
Docs
Updated doc-strings and comments