Repository navigation
feat(tempo): sync configurable accounts with Tempo main #518
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
b126168
chore: add configurable accounts Tempo sync plan
claude f52be77
feat(tempo): sync configurable accounts with Tempo main
claude cf0b920
test(tempo): run configurable account e2e against the pr-8486 image
claude 67871a5
test(tempo): update zod account operation hash for the new domains
claude 88a0e8d
fix(tempo): accept configurable key grants without an account binding
claude 8051c5f
ci: pin browser tests to ubuntu-24.04
claude f5158e7
fix(tempo): reject configurable admin grants in the zod schemas
claude 121d138
fix(tempo): reject admin grants of configurable account keys
claude e7be197
feat(tempo): sync configurable accounts with the T14 devnet checkpoint
claude File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,202 @@ | ||
| # Plan: sync ox configurable accounts with Tempo main | ||
|
|
||
| Status: in progress · Owner: jxom · Last reviewed: 2026-10-20 | ||
|
|
||
| Progress: | ||
| - Phases 1, 2, 3 and 4b are done. Phase 2 shipped as `AccountConfig.fromUpgrade` only; the salt is | ||
| available as `fromUpgrade(...).salt`, so a separate `getUpgradeSalt` was not added. | ||
| - Phase 4a is done: `account` is no longer required for configurable key grants, and no new | ||
| requirement was added for `isAdmin` grants, since viem's root-signed admin grants omit it and | ||
| TIP-1049 allows that. | ||
| - Phase 3 is reversed. The node on `joshie/configurable-t14-devnet-checkpoint` still allows admin keys at | ||
| T14, including configurable accounts as admin delegates and as admin-grant authorizers (test | ||
| `configurable_account_admin_can_sign_inline_grant`), and has no TIP-1137 code. ox no longer rejects | ||
| those grants. Revisit if TIP-1137 lands in the node. | ||
| - Phase 5: the e2e runs against `sha-04e67d3`, built from `liam/t14-checkpoint-recovery-factory` | ||
| (the devnet checkpoint plus a recovery-factory genesis option). | ||
| - Phase 6 wire names are done: the key type is `configurableAccount` and the request field is | ||
| `configurableAccountSimulation`; the simulation spec gained the optional grant `signer`. | ||
| - Not done, from the checkpoint audit: ox still accepts a keychain nested in a keychain and a | ||
| configurable signature in a Tempo authorization list, which the node rejects or skips. Both | ||
| predate this work. | ||
|
|
||
| Bring `ox/tempo` configurable-account APIs up to date with Tempo main and the | ||
| current TIP cluster, and add TIP-1113 in-place migration helpers. viem depends | ||
| on this work (`ox@0.14.56`), so ox goes first and every fix ships on both | ||
| `main` (1.x) and `0.x`. | ||
|
|
||
| ## Sources of truth | ||
|
|
||
| Newest first. When they disagree, prefer the spec and main over the open | ||
| implementation PRs. | ||
|
|
||
| | Source | What it settles | | ||
| | --- | --- | | ||
| | [tempoxyz/tempo#7510](https://github.com/tempoxyz/tempo/pull/7510) (TIP-1107–1114) | Spec: domains, encodings, migration, T14 gate | | ||
| | Tempo main `20c4412` ([#8502](https://github.com/tempoxyz/tempo/pull/8502), [#8497](https://github.com/tempoxyz/tempo/pull/8497)) | Rust constants and test vectors under the new names | | ||
| | `crates/primitives/src/transaction/configurable_account/mod.rs` | Domain constants, limits, `CONFIGURABLE_ACCOUNT_UPGRADE_DOMAIN` | | ||
| | `crates/primitives/tests/configurable_account.rs` (`configurable_account_hashes_follow_vectors_and_documented_layout`) | Byte-exact vectors to pin in ox tests | | ||
| | `crates/contracts/src/precompiles/configurable_account.rs` | `IConfigurableAccount` ABI, including `upgradeAccount` / `AccountUpgraded` | | ||
| | [tempoxyz/tempo#8204](https://github.com/tempoxyz/tempo/pull/8204) (TIP-1137) | Admin access keys removed at T14 | | ||
| | Open impl PRs [#7577](https://github.com/tempoxyz/tempo/pull/7577), [#7579](https://github.com/tempoxyz/tempo/pull/7579), [#7581](https://github.com/tempoxyz/tempo/pull/7581), [#7894](https://github.com/tempoxyz/tempo/pull/7894), [#8183](https://github.com/tempoxyz/tempo/pull/8183) | RPC wire names. These still use "multisig" naming and have not been rebased onto #8502. | | ||
| | [#8486](https://github.com/tempoxyz/tempo/pull/8486) | The precompile. Stacked on #8502, so it uses the new domains, but it does not accept configurable signatures in transactions. | | ||
|
|
||
| ## Current state | ||
|
|
||
| - ox was last synced in `42a84e6` (#508, Oct 12). That predates Tempo's | ||
| domain and ABI renames (Oct 20). | ||
| - The byte layouts, limits, `0x05` envelope, CREATE2 derivation and init-code | ||
| hash all match main. The domain strings are the only hashing difference. | ||
| - ox has no TIP-1113 migration support. | ||
|
|
||
| ## Phase 1: hashing domains (breaking) | ||
|
|
||
| `src/tempo/AccountConfig.ts:36,39,46` uses `tempo:multisig:{account,config,signature}`. | ||
| Main uses `tempo:configurable-account:{account,config,signature}`. Every | ||
| `getAddress`, `getCommitment`, `getSignPayload` and `AccountOperation.getHash` | ||
| result is wrong against the node. | ||
|
|
||
| Tasks: | ||
| - Rename `accountDomain`, `configDomain` and `signatureDomain` to the | ||
| `tempo:configurable-account:*` strings. | ||
| - Update the TSDoc preimage descriptions at `AccountConfig.ts:439` and `:490`. | ||
| - Rename `recoveryWalletInitCodeHash` (`:42`) to `accountProxyInitCodeHash`. Keep | ||
| the value `0x583cc6…`, and note that it is a placeholder until TIP-1110 | ||
| fixes the canonical account proxy. | ||
| - Replace the commitment, address and digest snapshots in `AccountConfig.test.ts` | ||
| and `AccountOperation.test.ts`. Also add a test that pins the Rust vectors | ||
| (factory `0x99…99`, owner `0x11…11`, weight 1, threshold 1, zero salt): | ||
| - account salt `0x641ad6eccc3adf35fac828d5cbb727e2489c904a905420e794e8275b6150bfe1` | ||
| - address `0x87c346a9029d675f296db533b12e146439cf20d5` | ||
| - v0 commitment `0x79cc3a5fcbe18cb8cbbd2b41393750ccf3bbc20533a846755767fa10068ae01d` | ||
| - v0 digest (inner `0x42…42`, account `0x91847576f406d0842ad7c1a0c97c22a122e64278`) | ||
| `0xe6fa513b5ab32da6f116443f13191096bce77b4850f4d51f3aa436fa7650c964` | ||
| - v1 digest `0x285c850cb2803beb10f2f212dac73784a1a03b3991ba79081b24bfa91beb9182` | ||
| - v1 commitment `0xee570a0f26f17b41cdf0952a04ee01ea23495b0c0a59f9c904b0d60cb76453c3` | ||
| - 48 owners of weight 1, threshold 8 → `0x7a4279bb3f1b8b54d703484317f64eae6814e827` | ||
| - Add a changeset. Use `patch`, following #508's precedent for breaking | ||
| configurable-account changes. It must say that addresses, commitments and | ||
| approval digests change. | ||
|
|
||
| Done when: the new vector test passes, and | ||
| `pnpm test --project tempo-unit --bail=1` and `pnpm check:types` are green. | ||
|
|
||
| ## Phase 2: TIP-1113 migration helpers (new API) | ||
|
|
||
| Migration needs no new signature format. The root key signs an ordinary `0x76` | ||
| transaction whose only call is | ||
| `upgradeAccount(uint8 threshold, (address owner, uint8 weight)[] owners)` on | ||
| `0xAACC000000000000000000000000000000000000`. The resulting account config is | ||
| `{ salt: keccak256("tempo:configurable-account:upgrade" || account), version: 1, threshold, owners }`. | ||
|
|
||
| Tasks in `src/tempo/AccountConfig.ts`: | ||
| - Add a private `upgradeDomain = 'tempo:configurable-account:upgrade'`. | ||
| - Add `getUpgradeSalt(account)`, which returns `keccak256(upgradeDomain || account20)`. | ||
| - Add `fromUpgrade(account, { owners, threshold })`, which returns | ||
| `from({ salt: getUpgradeSalt(account), version: 1n, owners, threshold })` | ||
| with owners sorted and validated. The root may appear as an owner, because | ||
| self-ownership is only rejected at version 0. | ||
| - Add TSDoc examples. Add tests that cross-check the salt and commitment | ||
| against #8183's node test `crates/node/tests/it/tempo_transaction/multisig/migration.rs`, | ||
| after re-deriving them with the new domains. | ||
|
|
||
| Optional in `src/tempo/TxEnvelopeTempo.ts` or `TransactionRequest.ts`: | ||
| - Add `assertUpgrade(envelope)`, which checks the transaction is valid for | ||
| migration: exactly one call to `0xAACC…` with selector `0x5f5fdc31`, no | ||
| `keyAuthorization`, an empty `authorizationList`, and, if signed, a | ||
| primitive signature (`secp256k1`, `p256` or `webAuthn`). A fee payer is | ||
| allowed. | ||
|
|
||
| Out of scope for ox: the ABI and the actions. Those belong in viem. | ||
|
|
||
| Done when: the new exports have TSDoc and tests, `pnpm zile examples:check` | ||
| passes, and a changeset exists (`patch`, following #508, which added | ||
| `AccountConfig.update` as a patch). | ||
|
|
||
| ## Phase 3: TIP-1137 admin access keys | ||
|
|
||
| At T14, `is_admin = true` and admin-signed `key_authorization` are invalid. | ||
| Configurable accounts only exist from T14, so they can never use admin keys. | ||
|
|
||
| Tasks: | ||
| - `KeyAuthorization.ts:50,116`: document `isAdmin` as removed from T14 per | ||
| TIP-1137. Do not tag it `@deprecated`: admin keys are still valid before | ||
| T14, and TIP-1137 is a draft. Leave encode and decode in place for pre-T14 | ||
| chains. | ||
| - Add a check that rejects `isAdmin: true` when the authorizing account is | ||
| configurable, wherever ox can tell (a sign payload with a configurable | ||
| `account` binding). | ||
|
|
||
| ## Phase 4: correctness nits against the node | ||
|
|
||
| - **Configurable grants without `account`:** `KeyAuthorization.ts:1218-1223` | ||
| (reached from `deserialize`) and zod `KeyAuthorization.ts:50` throw | ||
| `MissingAccountError` for a configurable `keyType` with no `account`. The | ||
| node only checks the binding when one is present, so ox should accept these | ||
| grants. Checked against #7894: the node requires `account` only for | ||
| admin-signed grants (signer != caller), never for a configurable key type. | ||
| Not changed yet, because relaxing it also drops a signing-side guard. | ||
| Decide whether to relax decoding only, or both directions. | ||
| - **Simulation `keyData`:** `AccountSimulation.ts:170-174` (`shimKeyData`) passes | ||
| any value up to 4 bytes through unchanged. The node rejects owner-approval | ||
| hints that are not 1, 2 or 4 bytes. Throw `InvalidSimulationError` for 0 | ||
| or 3 bytes. | ||
|
|
||
| ## Phase 5: e2e infrastructure | ||
|
|
||
| - `test/tempo/setup.global.configurableAccounts.ts:19`: rename the genesis key | ||
| `multisigRecoveryFactory` to `configurableAccountRecoveryFactory`. | ||
| - `test/tempo/configurableAccounts.genesis.json`: add `t14Time`. | ||
| - `test/tempo/configurableAccounts.ts:3`: replace image `sha-83f3ccd` with a | ||
| build that has the new domains and T14 integration. | ||
|
|
||
| **Blocked:** neither main nor #8486 accepts configurable-account signatures | ||
| in transactions yet. The only integration branches, #7581 and #7894, still | ||
| use the old domains. Until one of them rebases onto #8502, the e2e suite cannot | ||
| pass with Phase 1 applied. Either skip the configurable e2e project in CI | ||
| with a link to the tracking PR, or build a local image from a rebased | ||
| integration branch. Do not reintroduce the old domains to keep e2e green. | ||
|
|
||
| ## Phase 6: deferred until the Tempo PRs rebase | ||
|
|
||
| Track these. Do not change them before the node does. | ||
|
|
||
| - **RPC key type name:** ox maps `configurable` to the wire value `'multisig'` | ||
| (`TransactionRequest.ts:73-75,150,295`; `KeyAuthorization.ts:119-120,554,1011`; | ||
| zod `TransactionRequest.ts:29-34`, `KeyAuthorization.ts:40,50`). TIP-1111 | ||
| names it `ConfigurableAccount = 3`, and #8502 says there will be no aliases. | ||
| Expect the wire value to become `configurableAccount`. When it does, decide | ||
| whether to accept both values for one release. | ||
| - **Simulation field:** `multisigSimulation` is likely to become | ||
| `configurableAccountSimulation` or `accountSimulation`. | ||
| - **Account proxy hash:** the init-code hash will change when TIP-1110 is | ||
| final, which changes every derived address again. | ||
| - **Reserved-address checks:** TIP-1110 also rejects derived addresses that are | ||
| virtual addresses, active precompiles, TIP-20 or ZonePortal addresses. Main | ||
| leaves this to callers, so it is low priority. Consider an | ||
| `AccountConfig.getAddress` option or a separate `assertAddress`. | ||
| - **TIP-1108 account `extension`:** add an optional `extension` | ||
| (`0x00 || configHash`, 33 bytes) to the `eth_getAccount` / | ||
| `eth_getAccountInfo` schemas once the RPC lands. | ||
| - **TIP-1142 passport signers:** owner approvals may need to accept the | ||
| TIP-1131 ZK signature type (`SignatureEnvelope.ts:735-736`). | ||
|
|
||
| ## Release and backport | ||
|
|
||
| 1. Land Phases 1–4 on `main` (1.x) in one PR, or as Phase 1 followed by | ||
| Phases 2–4. | ||
| 2. Cherry-pick the same commits onto `0.x` in a `jxom/<topic>-v0` branch | ||
| (following the existing `*-v0` convention) and release `0.14.57`. | ||
| 3. Hand off to the viem plan (`viem/.agents/plans/configurable-accounts-tempo-sync.md`), | ||
| which bumps to that release. | ||
|
|
||
| ## Open questions | ||
|
|
||
| - Activation: #7510 says T14. #8182 and #8183 add a separate | ||
| `accountMigrationTime` and a `MigrationNotActive` error. ox should not encode | ||
| availability. Confirm which one Tempo keeps. | ||
| - Wire names: confirm the final `keyType` and simulation field names with | ||
| joshieDo before Phase 6. | ||
| - Whether ox should ship the `IConfigurableAccount` ABI and address constant, | ||
| or leave them to viem (today they only appear inline in | ||
| `configurableAccounts.e2e.test.ts`). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "ox": patch | ||
| --- | ||
|
|
||
| Added `AccountConfig.fromUpgrade` for deriving the version-one config an account installs when it migrates in place with `upgradeAccount` (TIP-1113). | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "ox": patch | ||
| --- | ||
|
|
||
| Fixed `AccountSimulation.toRpc` passing through empty and 3-byte `keyData`, which the Tempo node rejects, by shimming them into a 2-byte length hint. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "ox": patch | ||
| --- | ||
|
|
||
| Renamed the Tempo configurable account hash domains from `tempo:multisig:*` to `tempo:configurable-account:*` to match Tempo main (tempoxyz/tempo#8502), which changes every `AccountConfig.getAddress`, `AccountConfig.getCommitment`, and `AccountConfig.getSignPayload` result. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| --- | ||
| "ox": patch | ||
| --- | ||
|
|
||
| Renamed the configurable account RPC key type from `multisig` to `configurableAccount` and `TransactionRequest.multisigSimulation` to `configurableAccountSimulation`, and added the optional `AccountSimulation` grant `signer`, to match the Tempo node. | ||
|
|
||
| ```diff | ||
| - { keyType: 'multisig', multisigSimulation: spec } | ||
| + { keyType: 'configurableAccount', configurableAccountSimulation: spec } | ||
| ``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "ox": patch | ||
| --- | ||
|
|
||
| Stopped requiring an `account` binding on configurable account key grants, so `KeyAuthorization` and its zod schemas accept every grant the Tempo node accepts, and deprecated `KeyAuthorization.MissingAccountError`, which is no longer thrown. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.