Skip to content

feat(accounts): support multisig key authorizations - #7236

Draft
joshieDo wants to merge 5 commits into
agent/native-multisig-primitivesfrom
agent/native-multisig-key-auth
Draft

feat(accounts): support multisig key authorizations#7236
joshieDo wants to merge 5 commits into
agent/native-multisig-primitivesfrom
agent/native-multisig-key-auth

Conversation

@joshieDo

Copy link
Copy Markdown
Member

Expands signed key authorizations to TempoSignature while preserving primitive wire compatibility and wallet-store decoding. Multisig execution remains inactive until the later activation layer.

Stacked on #7234; extracted from #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-key-auth branch from 274e6cb to a724637 Compare August 19, 2026 15:29
@joshieDo
joshieDo force-pushed the agent/native-multisig-key-auth branch from a724637 to e9cbf83 Compare August 19, 2026 15:33
@joshieDo
joshieDo force-pushed the agent/native-multisig-key-auth branch from e9cbf83 to d6b533d Compare August 19, 2026 16:53
@github-actions

github-actions Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

📊 Tempo Precompiles Coverage

precompiles

Coverage: 6437/10593 lines (60.77%)

File details
File Lines Coverage
src/account_keychain/dispatch.rs 16/42 38.10%
src/account_keychain/mod.rs 310/896 34.60%
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/166 31.33%
src/ip_validation.rs 10/10 100.00%
src/lib.rs 127/143 88.81%
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/437 89.24%
src/storage/hashmap.rs 0/241 0.00%
src/storage/mod.rs 27/69 39.13%
src/storage/packing.rs 68/93 73.12%
src/storage/thread_local.rs 200/296 67.57%
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 139/193 72.02%
src/tip20/dispatch.rs 64/73 87.67%
src/tip20/mod.rs 657/801 82.02%
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/57 0.00%

contracts

Coverage: 1/202 lines (0.50%)

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/27 0.00%

Total: 6438/10795 lines (59.64%)

📦 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 safely widens signed key authorizations to TempoSignature, but the stacked native-multisig support contains one verified medium-severity denial-of-service risk.

🚨 [SECURITY] Multisig authorization-list signatures bypass signature-byte gas metering

Severity: Medium
Location: crates/revm/src/signature_gas.rs:44 and crates/revm/src/handler.rs:1833-1837 (the root-cause line and missing authorization-list guard are not changed lines in this PR)

tempo_signature_verification_gas() charges zero for TempoSignature::Multisig on the assumption that native multisig is rejected before intrinsic-gas calculation. validate_env does not reject multisig in tempo_authorization_list; recovery instead marks the entry invalid and authorization application skips it without rejecting the transaction. An attacker can therefore attach roughly 128 KiB of nested multisig/WebAuthn data to a mineable transaction without paying signature-byte gas, amplifying block bandwidth, decoding, propagation, and storage costs.

Recommended Fix: Reject multisig in the tempo_authorization_list validation loop before activation. When it becomes valid there, replace the zero-gas arm with TIP-1061's size/owner-based formula in the same fork.

Reviewer Callouts
  • Future consensus panic (crates/revm/src/handler.rs:1373-1378): The new .expect() depends on a validation guard that T11 is expected to relax. Replace it with verified multisig handling or a typed error before activation.
  • Unauthenticated multisig signer (crates/primitives/src/transaction/key_authorization.rs:445-456): recover_signer() caches a claimed multisig account without checking approvals or threshold, and the transaction pool consumes it. Return RecoveryError until stateful verification is wired in.
  • Permanent-invalid encoding classified as transient (crates/revm/src/error.rs:329-334): Keychain-encoded key authorizations are deterministic invalid forms but KeychainValidationFailed is classified as non-bad/state-dependent.

@joshieDo
joshieDo force-pushed the agent/native-multisig-key-auth branch from d6b533d to 6ecd1a2 Compare August 19, 2026 19:08
@joshieDo
joshieDo force-pushed the agent/native-multisig-key-auth branch from 6ecd1a2 to 5a29cf1 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 preserves primitive wire compatibility and rejects keychain and native-multisig key-authorization signatures during current validation. One defense-in-depth issue remains: the widened primitive API itself no longer guarantees that signer recovery authenticates the returned root account.

Reviewer Callouts
  • T11 activation path: Before removing the current multisig rejection, require stateful owner/threshold verification with the key-authorization digest and remove the block-execution expect().
  • Mutable cached inputs: authorization and signature remain public while the recovered signer is cached in a OnceLock; in-place mutation can leave stale signer state.
  • Pre-T11 decoding: Confirm that newly decodable but permanently rejected variants intentionally avoid bad-transaction peer penalties and caching.

@joshieDo
joshieDo force-pushed the agent/native-multisig-key-auth branch 2 times, most recently from 298e910 to 7602c6d Compare August 20, 2026 13:40
@joshieDo
joshieDo force-pushed the agent/native-multisig-key-auth branch from 7602c6d to fd7322d 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"

@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 safely preserves primitive key-authorization behavior and keeps native multisig execution disabled, but one low-severity defense-in-depth issue should be fixed before activation.

Reviewer Callouts
  • Native multisig activation path: Re-check validate_against_state_and_deduct_caller when replacing recover_signer() with recover_authorizing_account(); the latter returns a claimed multisig account without verifying its owner quorum.

Comment thread crates/revm/src/handler.rs
@joshieDo
joshieDo force-pushed the agent/native-multisig-key-auth branch from fd7322d to 45938c2 Compare August 20, 2026 15:26
@joshieDo
joshieDo force-pushed the agent/native-multisig-key-auth branch from 45938c2 to 6baa8af Compare August 20, 2026 16:28
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