Skip to content

feat(rpc): support native multisig simulation - #7239

Draft
joshieDo wants to merge 17 commits into
agent/native-multisig-activationfrom
agent/native-multisig-rpc-wallet
Draft

feat(rpc): support native multisig simulation#7239
joshieDo wants to merge 17 commits into
agent/native-multisig-activationfrom
agent/native-multisig-rpc-wallet

Conversation

@joshieDo

@joshieDo joshieDo commented Aug 19, 2026

Copy link
Copy Markdown
Member

Adds recursive request witnesses for state-aware multisig calls, gas estimation, and transaction filling. Witnesses are checked against pending state before conservative mock approvals are constructed; block-sequence witness simulation fails closed until it has position-aware preprocessing.

Stacked on #7238; reference implementation: #4069.

@github-actions

github-actions Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

✅ Changelog found on PR.

Edit changelog

@joshieDo
joshieDo force-pushed the agent/native-multisig-rpc-wallet branch 2 times, most recently from 5a15408 to 13c1bc9 Compare August 19, 2026 16:53
@joshieDo
joshieDo force-pushed the agent/native-multisig-rpc-wallet branch from 13c1bc9 to f023ebe Compare August 19, 2026 17:05
@github-actions

github-actions Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

📊 Tempo Precompiles Coverage

precompiles

Coverage: 6450/10891 lines (59.22%)

File details
File Lines Coverage
src/account_keychain/dispatch.rs 16/42 38.10%
src/account_keychain/mod.rs 315/920 34.24%
src/address_registry/dispatch.rs 21/27 77.78%
src/address_registry/mod.rs 50/60 83.33%
src/current_committee/dispatch.rs 0/9 0.00%
src/current_committee/mod.rs 0/18 0.00%
src/dispatch.rs 126/152 82.89%
src/error.rs 52/169 30.77%
src/ip_validation.rs 10/10 100.00%
src/lib.rs 131/158 82.91%
src/native_multisig/auth.rs 0/106 0.00%
src/native_multisig/dispatch.rs 0/14 0.00%
src/native_multisig/mod.rs 6/118 5.08%
src/nonce/dispatch.rs 6/7 85.71%
src/nonce/mod.rs 44/58 75.86%
src/receive_policy_guard/dispatch.rs 0/12 0.00%
src/receive_policy_guard/mod.rs 0/139 0.00%
src/signature_verifier/dispatch.rs 15/23 65.22%
src/signature_verifier/mod.rs 13/55 23.64%
src/stablecoin_dex/dispatch.rs 59/71 83.10%
src/stablecoin_dex/mod.rs 989/1097 90.15%
src/stablecoin_dex/order/mod.rs 120/154 77.92%
src/stablecoin_dex/order/storage.rs 178/249 71.49%
src/stablecoin_dex/orderbook.rs 183/242 75.62%
src/storage/actions.rs 11/90 12.22%
src/storage/evm.rs 390/440 88.64%
src/storage/hashmap.rs 0/249 0.00%
src/storage/mod.rs 27/69 39.13%
src/storage/packing.rs 68/93 73.12%
src/storage/thread_local.rs 200/300 66.67%
src/storage/types/array.rs 0/72 0.00%
src/storage/types/bytes_like.rs 135/179 75.42%
src/storage/types/cache.rs 65/122 53.28%
src/storage/types/mapping.rs 27/48 56.25%
src/storage/types/mod.rs 47/71 66.20%
src/storage/types/primitives.rs 21/24 87.50%
src/storage/types/set.rs 28/192 14.58%
src/storage/types/slot.rs 80/101 79.21%
src/storage/types/vec.rs 103/261 39.46%
src/storage_credits/accounting.rs 79/92 85.87%
src/storage_credits/dispatch.rs 16/16 100.00%
src/storage_credits/mod.rs 138/193 71.50%
src/tip20/dispatch.rs 64/73 87.67%
src/tip20/mod.rs 656/801 81.90%
src/tip20/rewards.rs 242/260 93.08%
src/tip20/roles.rs 85/88 96.59%
src/tip20_channel_reserve/dispatch.rs 0/42 0.00%
src/tip20_channel_reserve/mod.rs 3/548 0.55%
src/tip20_factory/dispatch.rs 9/11 81.82%
src/tip20_factory/mod.rs 117/140 83.57%
src/tip403_registry/dispatch.rs 29/46 63.04%
src/tip403_registry/mod.rs 347/544 63.79%
src/tip_fee_manager/amm.rs 295/465 63.44%
src/tip_fee_manager/dispatch.rs 35/37 94.59%
src/tip_fee_manager/mod.rs 57/155 36.77%
src/validator_config/dispatch.rs 18/28 64.29%
src/validator_config/mod.rs 171/227 75.33%
src/validator_config_v2/dispatch.rs 30/33 90.91%
src/validator_config_v2/mod.rs 523/581 90.02%
src/zone_factory/dispatch.rs 0/15 0.00%
src/zone_factory/mod.rs 0/215 0.00%
src/zone_factory/portal.rs 0/60 0.00%

contracts

Coverage: 1/223 lines (0.45%)

File details
File Lines Coverage
src/lib.rs 1/1 100.00%
src/precompiles/receive_policy_guard.rs 0/78 0.00%
src/precompiles/storage_credits.rs 0/7 0.00%
src/precompiles/tip20.rs 0/50 0.00%
src/precompiles/tip20_channel_reserve.rs 0/27 0.00%
src/precompiles/tip403_registry.rs 0/9 0.00%
src/precompiles/validator_config_v2.rs 0/3 0.00%
src/precompiles/zone_factory.rs 0/48 0.00%

Total: 6451/11114 lines (58.04%)

📦 Download full HTML report

@joshieDo

Copy link
Copy Markdown
Member Author

cyclops audit fast note="this belongs to the GH stack #7243 and the TIP 1061 is specified in the PR 7242. any bug not introduced by this PR should be clearly marked"

@tempoxyz-bot tempoxyz-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👁️ Cyclops Review

This change adds state-derived recursive mock approvals so RPC simulation can estimate native-multisig transactions conservatively. One verified low-severity correctness issue remains: the duplicated quorum cost model omits a real intrinsic-gas charge and can under-estimate valid nested-multisig transactions.

Reviewer Callouts
  • Simulation context boundary: ExecutionContext::Simulation skips native-multisig authorization, and empty transaction encoding can mark a transaction as RPC simulation. This behavior predates the PR, but a human should confirm no consensus or payload-building path can construct a TempoTxEnv with empty encoding or its default simulation context.
  • WebAuthn hint ranking: Explicit WebAuthn hints are ranked at maximum WebAuthn gas while mock construction uses the supplied key-data size. The node currently emits only UnknownPrimitive or Multisig, but in-process or SDK hint producers could violate the conservative-ranking invariant.
  • Signed-request round trip: From<AASigned> for TempoTransactionRequest emits multisig_signature_count while leaving from unset. Confirm no server or SDK path feeds that request back into simulation, where it now fails with multisig account cannot be zero.

@joshieDo
joshieDo force-pushed the agent/native-multisig-rpc-wallet branch from f023ebe to e575087 Compare August 19, 2026 19:08
@joshieDo
joshieDo force-pushed the agent/native-multisig-rpc-wallet branch from e575087 to 35fbe63 Compare August 19, 2026 21:02
@joshieDo

Copy link
Copy Markdown
Member Author

cyclops audit fast note="this belongs to the GH stack #7243 and the TIP 1061 is specified in the PR 7242. any bug not introduced by this PR should be clearly marked"

@tempoxyz-bot tempoxyz-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👁️ Cyclops Review

This change adds native-multisig gas modeling to Tempo RPC simulations. The state-aware call path is careful and conservative, but simulateV1 bypasses it and can understate intrinsic gas; hint derivation also adds bounded attacker-shaped work before EVM gas accounting.

Reviewer Callouts
  • Contract-creation calls from registered multisigs: Populating a hint makes has_aa_fields() true, while AA conversion requires a non-empty calls list. Verify that eth_call with no to still simulates CREATE rather than failing with empty calls list.
  • Conservative owner key assumptions: The state-derived path prices unknown owners as maximum-size WebAuthn. Confirm that this intentional overestimate does not make otherwise valid simulations fail the caller balance check.

@joshieDo
joshieDo force-pushed the agent/native-multisig-rpc-wallet branch from 35fbe63 to 04d8e75 Compare August 20, 2026 11:13
@joshieDo
joshieDo force-pushed the agent/native-multisig-rpc-wallet branch 2 times, most recently from b37ee58 to c511a17 Compare August 20, 2026 13:56
@joshieDo

Copy link
Copy Markdown
Member Author

cyclops audit fast note="this belongs to the GH stack #7243 and the TIP 1061 is specified in the PR 7242. any bug not introduced by this PR should be clearly marked"

@joshieDo
joshieDo force-pushed the agent/native-multisig-rpc-wallet branch from c511a17 to 6f64329 Compare August 20, 2026 14:31

@tempoxyz-bot tempoxyz-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👁️ Cyclops Review

Rechecked against current head 6f643292333cac24a649cc8c8d019e0e4067a466 after head drift. Three actionable findings remain.

Reviewer Callouts
  • Conservative primitive-owner pricing: State-derived hints still emit UnknownPrimitive for every non-multisig owner, pricing each as maximal WebAuthn. A common registered 1-of-1 secp256k1 estimate is inflated by about 35,720 gas; consider a way to provide exact per-owner key hints.
  • Hint-builder work bound: A state override can create the maximum nested owner graph without on-chain setup cost, causing thousands of storage reads and millions of bounded DP iterations for one RPC call. Benchmark and rate-limit this path.
  • Storage-reader invariant parity: The RPC reader uses InitMultisig::validate() while the precompile uses validate_for_account(account). Keep these readers aligned so future state sources cannot make self-owned configurations acceptable only to simulation.

Comment thread crates/node/src/rpc/mod.rs Outdated
mut request: TempoTransactionRequest,
mut db: impl Database<Error: Into<EthApiError>>,
) -> Result<TxEnvFor<Self::Evm>, Self::Error> {
populate_native_multisig_simulation_hints(&mut request, &mut db)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 [SECURITY] Block simulation bypasses state-aware multisig hint construction

This preprocessing runs only through Call::create_txn_env; eth_simulateV1 and tempo_simulateV1 resolve raw requests through TryIntoSimTx. A normal registered-multisig request therefore stays non-AA and omits the TIP-1061 surcharge, while a request with multisigSignatureCount fabricates primitive approvals without loading the stored threshold or nested owner tree. Under T11 simulation this can report success and gas for an authorization shape that cannot execute on chain.

Recommended Fix:
Run the same state-aware preprocessing for each transaction at its simulated block position before build_simulate_v1_transaction, or reject count-only registered-multisig simulation when state-aware preprocessing is unavailable.

Comment thread crates/node/src/rpc/mod.rs Outdated
Comment thread crates/alloy/src/rpc/revm_compat.rs Outdated
@joshieDo
joshieDo force-pushed the agent/native-multisig-rpc-wallet branch from 6f64329 to e8a27db Compare August 20, 2026 15:26
@joshieDo
joshieDo force-pushed the agent/native-multisig-rpc-wallet branch from 460ab98 to 5fbfbd5 Compare August 27, 2026 16:02
@joshieDo
joshieDo force-pushed the agent/native-multisig-rpc-wallet branch from 5fbfbd5 to 5f8607a Compare August 27, 2026 16:06
@joshieDo
joshieDo force-pushed the agent/native-multisig-rpc-wallet branch from 5f8607a to 5dcc3d5 Compare August 28, 2026 13:41
@joshieDo
joshieDo force-pushed the agent/native-multisig-rpc-wallet branch 2 times, most recently from 2461771 to 5d9872d Compare August 28, 2026 15:06
@joshieDo
joshieDo force-pushed the agent/native-multisig-rpc-wallet branch from 5d9872d to cf6e07c Compare August 28, 2026 15:27
@joshieDo
joshieDo force-pushed the agent/native-multisig-rpc-wallet branch from cf6e07c to a0c9d35 Compare August 28, 2026 15:47
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.

2 participants