Skip to content

[DO NOT MERGE YET] Remove the authz module behind the v6.9 upgrade - #4569

Open
alexander-sei wants to merge 3 commits into
mainfrom
alex/remove-authz-module
Open

alexander-sei wants to merge 3 commits into
mainfrom
alex/remove-authz-module

Conversation

@alexander-sei

@alexander-sei alexander-sei commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Authz is still a fully live module on main. Accounts can grant, execute and revoke authorizations, two ante checks reject a MsgExec that wraps an EVM message or nests more than five levels deep, the authz precompile at 0x…100E serves grant queries, and the staking, gov, distribution and slashing precompiles carry 18 scoped authorization methods that execute through the authz keeper. This removes the module outright behind the v6.9 upgrade, the same way #4319 and #4536 removed oracle and tokenfactory behind v6.8.

x/authz and its protos are deleted, along with the Go behaviour of bank's SendAuthorization and staking's StakeAuthorization (their generated types stay) and giga's unused copy of SendAuthorization. The module is unwired from app.New, the sei-wasmd test app and keys.MemIAVLStoreKeys. app/tags gains v6.9, and retiredauthz.ModuleName is the only entry in the new v69DeletedStores, so the store loader deletes the authz store at the upgrade height, taking every outstanding grant with it, and the v6.9 handler drops its version-map entry. MsgGrant, MsgExec and MsgRevoke move to a decode-only app/retiredauthz package with the same type URLs, which also keeps the three authorization types registered because RejectUnknownFields resolves the Any inside a historical MsgGrant. Their ValidateBasic returns ErrDeprecated (codespace authz, code 2, because code 3 keeps its historical meaning), so a new authz transaction is refused in CheckTx and in a block before any fee is charged, and retiredauthz_test.go pins encodings and amino sign bytes captured from the removed module and decodes two real pacific-1 transactions. The ante checks go with the module, since a MsgExec no longer passes ValidateBasic.

The store loader deletes the authz store only when upgrade-info.json names v6.9 at startup, but the handler runs either way, so a node that reached the upgrade height without that file would drop the version-map entry, keep the authz tree and fork its AppHash. #4538 made v6.8 halt in that case. The stores each upgrade deletes now live in deletedStoresByUpgrade, which the store loader reads and every upgrade handler checks first, so v6.8 keeps its halt and v6.9 gains the same one, with the same recovery: write {"name":"v6.9","height":H} to data/upgrade-info.json and restart.

The authz precompile stays registered as a tombstone: its three grant queries keep their ABI, but every call reverts with authz precompile is retired; authz grant queries are disabled, and Authz.sol is deleted. The authorization methods leave the staking, gov, distribution and slashing precompiles (Go, abi.json and the Solidity interfaces), so calling one reverts as an unknown selector, which TestAuthorizationMethodsAreRetired checks for all 18. The direct paths behave as before: delegate, redelegate and undelegate call the staking keeper directly, and the distribution withdrawals keep their scoped panic recovery. The docker cluster's authz YAML suites are deleted, authz.spec.ts asserts the retirement, and the other precompile specs drop their authorization cases.

This is app-hash breaking at the v6.9 height. From then on authz transactions are refused and grants are gone, so REStake-style auto-compounding stops (pacific-1 has 174 MsgExec and 17 MsgGrant transactions). Because #4551 removed the height-versioned precompile copies, a trace or call on this binary at a pre-v6.9 height that reaches the authz precompile or an authorization method reverts; #4551 already requires operators to route those heights to frozen nodes running the release that executed them. memiavl refuses to delete a tree it does not have, so the upgrade relies on every network carrying an authz tree, which holds because v6.8 mounts it and pacific-1 and atlantic-2 gained it in the 3.0.6 store upgrade.

Spamming grants before the upgrade height doesn't make the deletion slower: the store loader drops the authz memiavl tree in one step whatever its size, and unlike v6.8 the handler runs no deleteByPrefix prune, so there is nothing for a RetiredPrefixDeleteLimit-style cap to bound. That holds only while authz lives in memiavl. v6.8 sets MigrateCosmosEnabled, so once NumKeysToMigratePerBlock is raised and the EVM migration completes, auto nodes enter migrate_cosmos, which on v6.8 moves every store but evm into FlatKV, authz included. In migrate_cosmos or flatkv_only the composite store refuses the delete and MayHoldStore reports authz as present, so no node in either mode gets past the v6.9 height, and FlatKV has no store-level delete to fall back on. v6.9 therefore requires every network to be at evm_migrated or earlier at its upgrade height: governance has to keep NumKeysToMigratePerBlock at 0 until v6.9 activates, or set MigrateCosmosEnabled back to false before raising it. As of 2026-10-26 pacific-1 and atlantic-2 have the rate at 0 and have not applied v6.8, and no upgrade_v69 test runs with a non-zero rate.

The upgrade_v69 tests require authz to be the only module version the upgrade removes, in process, offline and on a live chain. Validated by CI at c73def9: make upgrade-test and make upgrade-test-vet, the persisted offline boundary from release/v6.8 (clean, crash-replay and halt-then-recover target paths, then a reopen that v6.8 must refuse), the cross-version boundary from release/v6.8 with a send grant on chain, the sharded Go tests, golangci-lint with golangci-lint fmt --diff, and the full docker integration matrix.

@github-actions

github-actions Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

The latest Buf updates on your PR. Results from workflow Buf / buf (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed✅ passed✅ passed✅ passedOct 27, 2026, 5:36 PM

@alexander-sei alexander-sei changed the title Remove the authz module behind the v6.8 upgrade Remove the authz module behind the v6.9 upgrade Oct 20, 2026
@codecov

codecov Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.11111% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 59.87%. Comparing base (1186580) to head (c73def9).
⚠️ Report is 13 commits behind head on main.

Files with missing lines Patch % Lines
app/app.go 33.33% 2 Missing ⚠️
app/retiredauthz/msgs.go 92.59% 2 Missing ⚠️
app/upgrades.go 77.77% 2 Missing ⚠️
precompiles/authz/authz.go 80.00% 2 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #4569      +/-   ##
==========================================
+ Coverage   59.47%   59.87%   +0.39%     
==========================================
  Files        2040     2022      -18     
  Lines      160200   157778    -2422     
==========================================
- Hits        95278    94463     -815     
+ Misses      64917    63310    -1607     
  Partials        5        5              
Flag Coverage Δ
sei-chain 57.86% <91.11%> (+0.40%) ⬆️
sei-db 75.17% <ø> (ø)
sei-db-state-db 80.68% <ø> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
app/ante.go 81.81% <ø> (-0.33%) ⬇️
app/ante/cosmos_checktx.go 10.24% <ø> (+0.77%) ⬆️
app/encoding.go 100.00% <100.00%> (ø)
app/precompiles.go 97.87% <ø> (-0.17%) ⬇️
app/retiredauthz/codec.go 100.00% <100.00%> (ø)
precompiles/distribution/distribution.go 70.85% <100.00%> (-1.71%) ⬇️
precompiles/gov/gov.go 81.74% <100.00%> (+0.37%) ⬆️
precompiles/slashing/slashing.go 87.15% <ø> (+6.20%) ⬆️
precompiles/staking/staking.go 87.30% <100.00%> (+1.45%) ⬆️
precompiles/utils/expected_keepers.go 0.00% <ø> (ø)
... and 8 more

... and 36 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Delete x/authz, its protos and the Go behaviour of the bank
SendAuthorization and staking StakeAuthorization types, and unwire the
module from the app, the sei-wasmd test app, the tools and the sei-db
store keys. app/tags gains v6.9: its store loader deletes the authz
store and its handler drops the authz version-map entry. The v6.8
handler is unchanged.

MsgGrant, MsgExec and MsgRevoke move to a decode-only app/retiredauthz
package with the same type URLs, so historical blocks still decode.
Their ValidateBasic returns ErrDeprecated, so new authz transactions are
refused before any fee is charged.

The authz precompile becomes a tombstone that always reverts, and the
authorization methods leave the staking, gov, distribution and slashing
precompiles. The ante checks on messages nested in MsgExec go with the
module.

The v6.8 -> v6.9 boundary tests cover the handler, the refusal of every
authz message, the persisted deletion of a store holding a grant, and a
live chain upgraded with a grant on it.

Co-authored-by: Cursor <cursoragent@cursor.com>
@alexander-sei
alexander-sei force-pushed the alex/remove-authz-module branch from 328b6d0 to e571657 Compare October 23, 2026 22:36
alexander-sei and others added 2 commits October 24, 2026 18:51
The store loader deletes the authz store only when upgrade-info.json
names v6.9 at startup, but the handler runs either way, so a node that
reaches the upgrade height without that file would drop the authz
version-map entry, keep the authz tree and fork its AppHash. #4538 made
the v6.8 handler halt in that case.

deletedStoresByUpgrade now holds the stores each upgrade deletes. The
store loader reads it, and every upgrade handler first requires those
stores to be gone, so v6.8 keeps its check, v6.9 gains it, and a later
upgrade that deletes stores gets both by adding one entry.

The offline v6.9 target phase covers the halt by dropping
upgrade-info.json and checks that the recovery the error names reaches
the clean upgrade's hash. The snapshot subtest now writes the file
before applying the upgrade.

Co-authored-by: Cursor <cursoragent@cursor.com>
@alexander-sei
alexander-sei marked this pull request as ready for review October 24, 2026 17:09
@cursor

cursor Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

PR Summary

High Risk
App-hash-breaking upgrade that deletes authz state and disables grant-based delegation, CLI queries, and EVM authorization flows operators may still rely on.

Overview
Removes the live x/authz module behind the v6.9 upgrade, deleting the keeper, ante checks that blocked nested MsgExec / EVM-in-authz, and authz wiring from precompile keepers. At upgrade height the store loader drops the authz KV store (via deletedStoresByUpgrade) and the handler removes only the authz module-version entry; outstanding grants disappear with the store.

Adds app/retiredauthz so historical txs still decode: MsgGrant, MsgExec, and MsgRevoke keep their type URLs and sign bytes, but ValidateBasic always returns ErrDeprecated (refused at CheckTx without fees). Encoding registers the retired message and authorization types.

Retires EVM authz surfaces: the 0x…100E precompile always reverts with an explicit retirement reason; shared precompiles/common authz grant/exec helpers and *WithAuthorization / grant-revoke methods on staking, gov, distribution, and slashing precompiles are removed from current Solidity/Go. Integration coverage drops authz YAML suites and narrows precompile specs to retirement assertions.

Tests add v6.9 unit, offline upgrade, and cross-version paths plus retiredauthz compatibility tests (including real pacific-1 txs).

Reviewed by Cursor Bugbot for commit c73def9. Bugbot is set up for automated code reviews on this repo. Configure here.

@alexander-sei alexander-sei removed the on-hold Ticket is on hold label Oct 24, 2026

@seidroid seidroid Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Removes the authz module behind the v6.9 upgrade. The store is deleted at the upgrade height, the version-map entry is dropped, MsgGrant/MsgExec/MsgRevoke stay decodable through a retiredauthz package that fails ValidateBasic before any fee is charged, the authz precompile becomes a revert-only tombstone, and the authorization methods are removed from the staking, gov, distribution and slashing precompiles. I approve: the inlined direct staking and distribution paths match the removed code, ValidateBasic still rejects authz messages in the CosmosStatelessChecks path of both CheckTx and DeliverTx, and RunMigrations rebuilds the version map from registered modules only, so DeleteModuleVersion holds. Codex's reading found nothing, which matches mine apart from the stale-description note; I had nothing of theirs to keep or drop.

Non-blocking

  • The PR description no longer matches the diff. It describes a v6.8 upgrade using v68DeletedStores, edits to legacy/v67 and legacy/v68, and a hold on #4551. The code targets v6.9 with v69DeletedStores and deletedStoresByUpgrade and touches no legacy precompile copies. Reviewers and release notes that rely on the description will get the wrong upgrade name.

seidroid review · decision approve · session c4c47111e74844bd8304b6adec8f160b · turn resp_claude_3b0d7aef3e8222b7559930e836fad751 · item 11ec0e0edb2d556e8656ec8683151604

Findings: 0 blocking | 1 non-blocking | 0 posted inline

@alexander-sei alexander-sei changed the title Remove the authz module behind the v6.9 upgrade [DO NOT MERGE YET] Remove the authz module behind the v6.9 upgrade Oct 27, 2026
@alexander-sei alexander-sei added the on-hold Ticket is on hold label Oct 27, 2026
revofusion pushed a commit to revofusion/sei-chain that referenced this pull request Oct 28, 2026
`MultiTree.ApplyUpgrades` drops a deleted tree by swapping it past the
end of `t.trees` and never closes it, so its snapshot stays mapped with
its three files open, and the vacated slot in the backing array keeps
the tree reachable. Changelog replay makes it worse. `Catchup` hands
every tree a background writer through `ApplyChangeSetAsync`, and its
closing loop only stops the writers of trees still listed, so a tree
deleted mid-replay keeps a goroutine blocked on its channel, and that
goroutine pins the tree, its mappings and its file descriptors for the
life of the process. This came up in review on sei-protocol#4569, whose v6.9 upgrade
deletes the `authz` tree.

Every node hits this at the upgrade height, and again on each restart or
snapshot reload that replays from a snapshot taken before it. It becomes
repeatable on nodes that read past heights from state commitment, which
are nodes with `sc-enable-state-proof` on and nodes with SS off. There a
query at a past height opens a fresh read-only memiavl through
`LoadVersion(version, true)` and replays the changelog from the nearest
snapshot, so every query at a height past the upgrade that is served
from a pre-upgrade snapshot leaks one goroutine and three mapped files
per deleted tree, until that snapshot is pruned 10,000 to 20,000 blocks
later with the default snapshot settings. The historical-proof limit,
one query per second by default, slows that without bounding it, and
with six trees deleted at v6.8 each such query there can leak up to 18
mappings and 18 file descriptors. Nodes on the default configuration
reject state proofs and serve past heights from SS, so they only see the
upgrade-height and replay cases. v5.8.0 and v6.3.0 went through the same
path with one store each.

`ApplyUpgrades` now deletes through `deleteTree`, which clears the
vacated slot, waits for the tree's background writer and closes it. The
wait comes first because `Tree.Close` closes the writer's channel
without waiting for it, and a replay can leave the writer mid-changeset.
A failure to close is logged rather than returned, so the change can
only release resources and can never fail a store loader at an upgrade
height. Anything else holding the tree's snapshot keeps it, since
snapshots are reference-counted and `Tree.Copy` takes its own reference.

Nothing persisted changes, neither state nor hashes nor changelog
entries, so this is not app-hash breaking. It is labeled for backport to
`release/v6.8` because the v6.8 binary is the one that replays v6.8's
six deletions after its upgrade height, and a fix that only lands on
main first ships in v6.9. `TestCatchupReleasesTreeDeletedByUpgrade`
replays a changelog through a delete and requires the deleted tree's
writer to have stopped, its snapshot to be closed and the multitree to
hold no reference to it; it fails on main. A scratch run of 50 read-only
loads past a delete leaked 50 goroutines and 150 open files before this
change and none after. Validated with the memiavl, composite, migration
and `sei-cosmos/storev2` packages under `-race`, golangci-lint,
`golangci-lint fmt --diff`, `go vet`, and the three
`upgrade-test-offline` phases from `release/v6.7` against this commit,
whose target phase applies v6.8's six deletions through the store
loader, including after a simulated crash, and reopens each result by
replaying the changelog through them.

Co-authored-by: Cursor <cursoragent@cursor.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants