v0.54.x to v0.55.x of Cosmos SDK. If you are upgrading directly from v0.53.x, see Upgrading from v0.53.x after reading the breaking changes below.
For a full list of changes, see the Changelog.
The headline changes in this release are the removal of three legacy surfaces (x/params, x/protocolpool, and SIGN_MODE_TEXTUAL), a reworked app-side mempool interface, and validator consensus key rotation in x/staking. Key rotation ships enabled for every chain that upgrades — see Validator Consensus Key Rotation — and requires one line of wiring in app.go. Everything else in the new-features list (ML-DSA-65 keys, secp256k1eth keys, config-driven Block-STM wiring) is opt-in.
Table of Contents
- Breaking Changes
- Upgrading from v0.53.x
- New Features and Non-Breaking Changes
- Behavior Changes Affecting Dapps and Indexers
Breaking Changes
CometBFT Upgrade
Cosmos SDK v0.55 requires CometBFTv0.40.0 (the v0.54.x line shipped with v0.39.x, ending at v0.39.3 in v0.54.3). Bump your app’s go.mod to match the SDK’s pin. Relevant changes in CometBFT v0.40.0:
- Expanded
MaxSignatureSizeand per-validatorMaxCommitSigBytesto accommodate post-quantum (ML-DSA-65) signatures. - A fix for the application-side mempool (
mempool.type = "app", supported since CometBFT v0.39.2 / SDK v0.54.3): the default socket transport was missing theInsertTx/ReapTxscases, causing node self-kill (cometbft#5958). Chains using an app-side mempool over the socket transport need v0.40.0. - Updated
DefaultBlockParams(cometbft#5987). This changes defaults for new chains only; existing chains keep their on-chain consensus params.
Removed: x/params
#25546 removes thex/params module entirely (only a tombstone README remains). Module parameters have been managed by each module since v0.47; v0.55 removes the leftover machinery:
-
If your app still imports
x/params(aparamskeeper.Keeper, per-moduleSubspaces, or the legacy gov proposal handler), remove that wiring. If theparamsstore is still mounted, delete it in your store upgrades (see Upgrade Handler and Store Migrations). Chains that have not yet migrated legacy subspace params to module-managed params must complete that migration before upgrading to v0.55 — the migration code is gone. -
Drop the trailing
exported.Subspaceargument (typically passed asnil) from the module constructors that carried it for legacy migrations:
mint.NewAppModule retains its deprecated InflationCalculationFn parameter; only the subspace argument is removed.)
Removed: x/protocolpool
#26421 removes thex/protocolpool module and its proto/API surface from the SDK. The distrkeeper.WithExternalCommunityPool extension point is removed with it — x/distribution always uses its internal FeePool community pool again, and MsgFundCommunityPool / MsgCommunityPoolSpend operate on it directly.
Required action if your app wired x/protocolpool (the v0.54 SimApp default):
- Remove all
protocolpoolwiring fromapp.go: the imports, theProtocolPoolKeeperfield and itsNewKeepercall, theprotocolpooltypes.ModuleNameandprotocolpooltypes.ProtocolPoolEscrowAccountentries inmaccPerms, the module manager entry, and its entries in the begin-block, end-block, init-genesis, and export orders. - Remove
distrkeeper.WithExternalCommunityPool(app.ProtocolPoolKeeper)from yourdistrkeeper.NewKeepercall. - Delete the
protocolpoolstore in your store upgrades (see Upgrade Handler and Store Migrations). - Balances held by the protocolpool module accounts are bank state and are not migrated automatically. Decide where those funds go and move them in your upgrade handler — e.g. transfer them to the
x/distributioncommunity pool so community-pool spend proposals keep working.
x/protocolpool, no action is needed beyond not being able to import it.
Removed: SIGN_MODE_TEXTUAL
SIGN_MODE_TEXTUAL (proto enum value 2) and its entire implementation have been removed (#26456):
x/tx/signing/textual/— all renderers, the CBOR encoder, test data, and internal protosx/auth/tx/textual.goandConfigOptions.TextualCoinMetadataQueryFn- Ledger + SIGN_MODE_TEXTUAL integration in
client/flags and tx factory
2 and string "SIGN_MODE_TEXTUAL" are reserved to prevent future reuse. ADR-050 is archived.
Required action if your app enabled SIGN_MODE_TEXTUAL:
-
Remove
TextualCoinMetadataQueryFnfrom yourtx.ConfigOptions: -
Remove any
SIGN_MODE_TEXTUALcases from signing mode handler switch statements. -
Remove Ledger wiring that depended on
SIGN_MODE_TEXTUAL. Client-side root command wiring that constructed a textual-enabled tx config for online mode (as v0.54 SimApp did insimd/cmd/root.go) should be deleted as well.
Mempool Interface Changes
#25338 changes thetypes/mempool interfaces so the mempool stores the gas wanted reported by the ante handler at CheckTx time, and block selection uses that value instead of the tx-declared gas limit.
Required action if you implement a custom mempool (chains using the SDK’s built-in mempools or no app-side mempool just recompile):
Insertgains anInsertOptionparameter carrying the ante-reported gas:Insert(context.Context, sdk.Tx, InsertOption) error.Iterator.Tx()now returns aPooledTx({Tx sdk.Tx; GasWanted uint64}) instead ofsdk.Tx.ExtMempool.SelectBy’s callback now receives aPooledTx:SelectBy(context.Context, [][]byte, func(PooledTx) bool).ExtMempool.RemoveWithReasonand theRemoveReasontype, introduced in v0.54, are unchanged.
PrepareProposal handlers that iterate the mempool should read gas from PooledTx.GasWanted rather than re-deriving it from the tx.
Staking: Key Rotation Wiring and Interface Changes
x/staking now requires a key_rotation_fee_pool module account with burn permissions — the staking keeper panics at construction if it is missing (x/staking/keeper/keeper.go). Add it to your maccPerms:
- The
StakingHooksinterface gainsAfterValidatorConsKeyUpdated(ctx context.Context, oldConsAddr, newConsAddr sdk.ConsAddress, valAddr sdk.ValAddress) error, called when a rotation is applied. CustomStakingHooksimplementations must add this method (returningnilis fine if you don’t need the notification). - The staking keeper adds
ValidatorByHistoricalConsAddr(ctx, consAddr), which resolves a validator from a consensus address it used before a rotation. Modules that map consensus addresses to validators can no longer assume that mapping is immutable — see Validator Consensus Key Rotation.
genutil: ExportGenesisFileWithTime Signature
#26468 consolidatesExportGenesisFileWithTime’s arguments so the exported file preserves consensus params (previously they were rebuilt from defaults, dropping the caller’s values):
Upgrade Handler and Store Migrations
Module Migrations
Two module consensus-version bumps ship in this release and run automatically viaRunMigrations in your upgrade handler:
x/staking5 → 6: adds thekey_rotation_feeparam, defaulting to1000000of the bond denom (#26485).Params.Validaterequires the fee denom to equalbond_denom(#26613).x/auth6 → 7: adds theSigVerifyCostMlDsa65param with its default value (#26472).
Reference Upgrade Handler
A reference upgrade handler for this release (seesimapp/upgrades.go):
"params" to Deleted as well if your app still had the x/params store mounted.
Upgrading from v0.53.x
Skipping v0.54 and upgrading directly fromv0.53.x to v0.55.x is supported as a single coordinated upgrade: one binary swap, one upgrade handler, one halt height. Work through the v0.53.x → v0.54.x upgrade reference first — all of its required changes still apply — then apply this guide on top. The v0.54 hop’s highlights, so you know what you’re signing up for:
- CometBFT
v0.38.x→v0.39.x(LibP2P,AdaptiveSync); from v0.53 you jump straight to thev0.40.0release v0.55 pins. - Consolidation of
cosmossdk.io/x/*vanity modules intogithub.com/cosmos/cosmos-sdk/x/*, plus the Log v2 and Store v2 moves. x/govkeeper-initialization andGovHooksinterface changes,x/epochsandx/bankwiring updates, and thex/circuit/x/nft/x/crisisdeprecations.- IBC v11 (if your chain uses IBC).
- Skip transient wiring. Don’t adopt v0.54 reference-app wiring that v0.55 removes in the same hop: the SIGN_MODE_TEXTUAL tx-config setup,
x/protocolpool(if your v0.53 app didn’t already wire it), anddistrkeeper.WithExternalCommunityPool. Go straight to the v0.55 forms shown in this guide. - Module constructors. v0.54’s constructor signatures still carried the legacy
exported.Subspacearguments; use the v0.55 signatures from Removed: x/params directly. - Custom mempools. Implement the v0.55
Mempoolinterface (Mempool Interface Changes) directly; don’t bother with the v0.54 shape. - Module migrations are cumulative.
RunMigrationswalks each module from its v0.53 consensus version to the v0.55 target in one pass (x/auth5 → 6 → 7,x/staking5 → 6). No manual intervention is needed beyond the standard upgrade handler. - Store upgrades. The v0.53 → v0.54 hop required no store additions or deletions, so the combined store upgrade is exactly the snippet in Upgrade Handler and Store Migrations: delete
protocolpoolonly if your v0.53 app had wired it, andparamsif its store was still mounted (more likely on a v0.53-era app). Use a single upgrade name, e.g.v053-to-v055.
New Features and Non-Breaking Changes
These changes are optional to adopt during the upgrade; they are not required for a successful migration. The exception is key rotation, which is active on every v0.55 chain once the required wiring above is in place.Validator Consensus Key Rotation
v0.55 adds consensus key rotation tox/staking (#26440): a validator operator can submit MsgRotateConsPubKey (wired into the CLI, #26461) to replace their consensus key without unbonding. Key properties:
- Fee. Each rotation charges the
key_rotation_feestaking param (default1000000of the bond denom) from the operator account; the fee is burned via thekey_rotation_fee_poolmodule account. - Rate limit. One rotation per validator per unbonding period.
- Applied in the end blocker. The rotation is scheduled by the msg server and applied at the end of the block; CometBFT is informed through a validator-set update.
- Evidence and slashing. Equivocation evidence against a rotated-away (historical) consensus address remains attributable to the validator until the evidence is no longer admissible — i.e. until both
evidence.max_age_num_blocksandevidence.max_age_durationhave elapsed since the rotation, which can be later than the unbonding time (#26481, #26616). Slashing signing info is migrated to the active consensus key. Governance changes that extend the evidence-age params after a rotation’s expiry has been computed are not retroactively applied; chains should account for this when tuning evidence params. - Genesis. Rotation history and pending-rotation state are included in staking genesis import/export (#26471); genesis export tooling that parses staking genesis JSON should expect the new fields.
- Events.
rotate_cons_pubkeyis emitted when a rotation is scheduled (including apply height, maturity time, evidence-expiry time/height, and the burned fee) andapply_cons_pubkey_rotationwhen it is applied (validator, old and new consensus addresses) (#26619).
keeper.ValidatorByHistoricalConsAddr resolves a validator from a rotated-away consensus address.
Chains built on the enterprise x/poa module have their own MsgRotateConsPubKey with different semantics — no fee, no rate limit, an admin override, and a same-block swap with no rotation history. Because the old consensus address is gone immediately, modules that attribute LastCommit signatures or vote extensions by consensus address need extra care across the swap; see the PoA guide below for the caveats and the operator runbook.
For an overview of key rotation and the operator procedures, see Key rotation, Rotate a consensus key, Staking, and Rotate a consensus key, PoA.
ML-DSA-65 Validator Consensus Keys
Cosmos SDK v0.55 registers the NIST ML-DSA-65 (FIPS 204) post-quantum signature scheme as a supported validator consensus key type (#26436). The newcosmos.crypto.mldsa65.PubKey / PrivKey proto messages, Amino routes (cometbft/PubKeyMlDsa65, cometbft/PrivKeyMlDsa65), interface-registry registration, multisig amino route, and hd.MlDsa65Type constant are all enabled by default.
Action required: none. Existing chains continue to accept only the consensus key types listed in genesis.consensus_params.validator.pub_key_types (still ["ed25519"] by default). No state-machine-relevant behavior changes for chains that do not opt in.
To opt in (new chains): set genesis.consensus_params.validator.pub_key_types to ["ml_dsa_65"] (or a list including it). Validators must then submit MsgCreateValidator with a mldsa65.PubKey. The init and testnet commands accept --consensus-key-algo ml_dsa_65 to generate matching validator files (#26604). Test harnesses can use the new testutil/network.Config.ValidatorConsensusKeyType field together with genutil.InitializeNodeValidatorFilesFromMnemonicWithKeyType to spin up an in-process testnet pinned to ML-DSA-65.
Operational considerations: ML-DSA-65 keys and signatures are substantially larger than ed25519 (pubkey 1952 bytes vs 32, signature 3309 bytes vs 64). Chains enabling this key type should review consensus_params.block.max_bytes and gossip framing limits accordingly. The cometbft commit lift in this release expanded MaxSignatureSize and the per-validator MaxCommitSigBytes to accommodate the larger signatures; downstream applications relying on the previous fixed values may need to be re-examined.
Warning — IBC counterparties must upgrade first. IBC light clients on counterparty chains verify your validator set’s commit signatures using the counterparty’s own compiled-in crypto. A counterparty running a stack that predates ML-DSA-65 support cannot verify signatures from the new key type: once validators holding sufficient voting power sign with it, your headers fail verification there, IBC packet flow with that chain stops, and the client eventually expires. Before enabling a new consensus key type on a chain with live IBC connections, coordinate so every counterparty chain is running a CometBFT/SDK stack that can verify it — the counterparty only needs the verification code on its nodes, not the key type in its own pub_key_types.
Existing chains can combine this with key rotation to move validators to post-quantum keys: add ml_dsa_65 to pub_key_types via a consensus-params update, then have validators rotate.
For the concepts and operator guides, see Post-quantum keys, Enable ML-DSA keys, and Migrate a validator to ML-DSA.
ML-DSA-65 Account Keys
#26472 extends ML-DSA-65 support to user account keys: keyring creation and mnemonic recovery (--algo ml_dsa_65), transaction signing and verification, and a new ante-handler gas cost param SigVerifyCostMlDsa65 (added to x/auth params by the automatic 6 → 7 migration). No action is required; accounts using existing key types are unaffected.
See Create an ML-DSA account and Post-quantum keys.
secp256k1eth Validator Consensus Keys
#26615 addscrypto/keys/secp256k1eth, wrapping CometBFT’s Ethereum-style secp256k1 consensus key implementation with SDK codec registration. Intended for EVM-compatible chains that want validator consensus addresses derived the Ethereum way; opt in via genesis.consensus_params.validator.pub_key_types.
The IBC counterparty warning from the ML-DSA-65 section applies here too: counterparty chains must run a stack that can verify secp256k1eth signatures before your validators adopt the key type, or IBC connections with them will break.
See Post-quantum keys for how the consensus key types compare.
Block-STM Configuration
Block-STM parallel execution itself is not new — the engine (baseapp/txnrunner) and the SetBlockSTMTxRunner hook shipped in v0.54.x, wired programmatically per chain. v0.55 adds standard operator-facing configuration (#26208): block-executor ("sequential", the default, or "block-stm"), block-stm-workers, and block-stm-pre-estimate in app.toml, plus a baseapp/blockexec helper that resolves them and installs the runner. Chains that already call SetBlockSTMTxRunner directly can keep that wiring or switch to the helper.
To adopt the config-driven wiring, call blockexec.Apply after creating your store keys (see simapp/app.go):
Apply resolves the executor from app.toml/flags and installs the corresponding TxRunner; with the default sequential executor it preserves today’s behavior, so the wiring is safe to add unconditionally. Block-STM is incompatible with the block gas meter (disabled by default since v0.54): Apply disables the meter automatically when block-stm is selected, but chains wiring SetBlockSTMTxRunner directly must call SetDisableBlockGasMeter(true) first or the runner installation panics.
Switching a running chain’s executor is a per-node setting with identical state-transition results, but treat the first enablement as an operational rollout: test with your workload before flipping validators.
Behavior Changes Affecting Dapps and Indexers
Observable changes between v0.54.x and v0.55.x that don’t require code changes but may affect downstream consumers:- Block selection uses ante-reported gas. Proposals are packed using the gas wanted returned by the ante handler at
CheckTxtime rather than the tx-declared gas limit (#25338). Block composition can differ for txs whose ante-reported gas diverges from their declared limit. - Staking emits key-rotation events (
rotate_cons_pubkey,apply_cons_pubkey_rotation), and validator consensus addresses can change over time (#26619). x/govproposal_messagesevent attribute no longer has a leading comma (#26353).x/authzprunes at most 200 expired grants per begin block (#26588); mass-expiry cleanup now spreads across blocks.x/distributionreward withdrawals to blocked addresses during begin/end block fall back to the delegator/validator owner and then the community pool instead of failing (#26406). User-initiated withdrawals to blocked addresses still returnErrUnauthorized.x/feegrantAllowancesandAllowancesByGranterqueries now honorPageRequest.offsetandcount_totalcorrectly (#26596); clients that compensated for the old off-by-page results should re-check.