chore!: remove bank & genutil legacy migrations (#17818)

This commit is contained in:
Marko 2023-09-21 12:33:14 +02:00 committed by GitHub
parent 825e09ab77
commit 5987d0003a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 41 additions and 1312 deletions

View File

@ -423,6 +423,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (snapshots) [14048](https://github.com/cosmos/cosmos-sdk/pull/14048) Move the Snapshot package to the store package. This is done in an effort group all storage related logic under one package.
* (signing) [#13701](https://github.com/cosmos/cosmos-sdk/pull/) Add `context.Context` as an argument `x/auth/signing.VerifySignature`.
* (store) [#11825](https://github.com/cosmos/cosmos-sdk/pull/11825) Make extension snapshotter interface safer to use, renamed the util function `WriteExtensionItem` to `WriteExtensionPayload`.
* (x/bank) [#17818](https://github.com/cosmos/cosmos-sdk/pull/17818) Remove params requirement from `NewAppModule`
### Client Breaking Changes

View File

@ -622,7 +622,7 @@ Here are the following replacements that you need to perform on your proto files
Please also check that in your own app's proto files that there are no single-word names for those two proto annotations. If so, then replace them with fully-qualified names, even though those names don't actually resolve to an actual protobuf entity.
For more information, see the [encoding guide](https://github.com/cosmos/cosmos-sdk/blob/main/docs/docs/develop/advanced/05-encoding.md).
For more information, see the [encoding guide](https://github.com/cosmos/cosmos-sdk/blob/main/docs/learn/advanced/05-encoding.md).
### Transactions

View File

@ -17,7 +17,7 @@ evidence can be submitted, evaluated and verified resulting in some agreed upon
penalty for any misbehavior committed by a validator, such as equivocation (double-voting),
signing when unbonded, signing an incorrect state transition (in the future), etc.
Furthermore, such a mechanism is paramount for any
[IBC](https://github.com/cosmos/ics/blob/master/ibc/2_IBC_ARCHITECTURE.md) or
[IBC](https://github.com/cosmos/ibc) or
cross-chain validation protocol implementation in order to support the ability
for any misbehavior to be relayed back from a collateralized chain to a primary
chain so that the equivocating validator(s) can be slashed.
@ -178,5 +178,5 @@ type GenesisState struct {
## References
* [ICS](https://github.com/cosmos/ics)
* [IBC Architecture](https://github.com/cosmos/ics/blob/master/ibc/1_IBC_ARCHITECTURE.md)
* [IBC Architecture](https://github.com/cosmos/ibc/blob/main/spec/ics-001-ics-standard/README.md)
* [Tendermint Fork Accountability](https://github.com/tendermint/spec/blob/7b3138e69490f410768d9b1ffc7a17abc23ea397/spec/consensus/fork-accountability.md)

View File

@ -424,6 +424,7 @@ way that requires duplication and differing sets of design principles (protobuf
while golang APIs would forbid it).
Other downsides to this approach are:
* no clear roadmap to supporting modules in other languages like Rust
* doesn't get us any closer to proper object capability security (one of the goals of ADR 033)
* ADR 033 needs to be done properly anyway for the set of use cases which do need it
@ -446,7 +447,8 @@ languages, possibly executed within a WASM VM.
### Minor API Revisions
To declare minor API revisions of proto files, we propose the following guidelines (which were already documented
in [cosmos.app.v1alpha module options](../proto/cosmos/app/v1alpha1/module.proto)):
in [cosmos.app.v1alpha module options](../../proto/cosmos/app/v1alpha1/module.proto)):
* proto packages which are revised from their initial version (considered revision `0`) should include a `package`
* comment in some .proto file containing the test `Revision N` at the start of a comment line where `N` is the current
revision number.
@ -522,6 +524,7 @@ func ProtoImage(protoImage []byte) Option {}
```
This approach allows us to support several ways protobuf files might be generated:
* proto files generated internally to a module (use `ProtoFiles`)
* the API module approach with pinned file descriptors (use `ProtoImage`)
* gogo proto (use `GzippedProtoFiles`)

View File

@ -56,7 +56,7 @@ Tests which exercise a whole module's function with dependencies mocked, are *jo
These are almost like integration tests in that they exercise many things together but still
use mocks.
Example 1 journey vs illustrative tests - [depinject's BDD style tests](https://github.com/cosmos/cosmos-sdk/blob/main/depinject/features/bindings.feature), show how we can
Example 1 journey vs illustrative tests - depinject's BDD style tests, show how we can
rapidly build up many illustrative cases demonstrating behavioral rules without [very much code](https://github.com/cosmos/cosmos-sdk/blob/main/depinject/binding_test.go) while maintaining high level readability.
Example 2 [depinject table driven tests](https://github.com/cosmos/cosmos-sdk/blob/main/depinject/provider_desc_test.go)

View File

@ -74,8 +74,8 @@ As a result of this architecture, building a Cosmos SDK application usually revo
While there are no definitive guidelines for writing modules, here are some important design principles developers should keep in mind when building them:
* **Composability**: Cosmos SDK applications are almost always composed of multiple modules. This means developers need to carefully consider the integration of their module not only with the core of the Cosmos SDK, but also with other modules. The former is achieved by following standard design patterns outlined [here](#main-components-of-sdk-modules), while the latter is achieved by properly exposing the store(s) of the module via the [`keeper`](./06-keeper.md).
* **Specialization**: A direct consequence of the **composability** feature is that modules should be **specialized**. Developers should carefully establish the scope of their module and not batch multiple functionalities into the same module. This separation of concerns enables modules to be re-used in other projects and improves the upgradability of the application. **Specialization** also plays an important role in the [object-capabilities model](../../learn/advanced/10-ocap.md) of the Cosmos SDK.
* **Composability**: Cosmos SDK applications are almost always composed of multiple modules. This means developers need to carefully consider the integration of their module not only with the core of the Cosmos SDK, but also with other modules. The former is achieved by following standard design patterns outlined [here](#main-components-of-cosmos-sdk-modules), while the latter is achieved by properly exposing the store(s) of the module via the [`keeper`](./06-keeper.md).
* **Specialization**: A direct consequence of the **composability** feature is that modules should be **specialized**. Developers should carefully establish the scope of their module and not batch multiple functionalities into the same module. This separation of concerns enables modules to be re-used in other projects and improves the upgradability of the application. **Specialization** also plays an important role in the [object-capabilities model](../../develop/advanced/10-ocap.md) of the Cosmos SDK.
* **Capabilities**: Most modules need to read and/or write to the store(s) of other modules. However, in an open-source environment, it is possible for some modules to be malicious. That is why module developers need to carefully think not only about how their module interacts with other modules, but also about how to give access to the module's store(s). The Cosmos SDK takes a capabilities-oriented approach to inter-module security. This means that each store defined by a module is accessed by a `key`, which is held by the module's [`keeper`](./06-keeper.md). This `keeper` defines how to access the store(s) and under what conditions. Access to the module's store(s) is done by passing a reference to the module's `keeper`.
## Main Components of Cosmos SDK Modules

View File

@ -43,7 +43,7 @@ In general, the getter function does the following:
* If applicable, the command's arguments are parsed. In this example, the arguments `[to_address]` and `[amount]` are both parsed.
* A [message](./02-messages-and-queries.md) is created using the parsed arguments and information from the `clientCtx`. The constructor function of the message type is called directly. In this case, `types.NewMsgSend(fromAddr, toAddr, amount)`. Its good practice to call, if possible, the necessary [message validation methods](../building-modules/03-msg-services.md#Validation) before broadcasting the message.
* Depending on what the user wants, the transaction is either generated offline or signed and broadcasted to the preconfigured node using `tx.GenerateOrBroadcastTxCLI(clientCtx, flags, msg)`.
* **Adds transaction flags:** All transaction commands must add a set of transaction [flags](#flags). The transaction flags are used to collect additional information from the user (e.g. the amount of fees the user is willing to pay). The transaction flags are added to the constructed command using `AddTxFlagsToCmd(cmd)`.
* **Adds transaction flags:** All transaction commands must add a set of transaction flags. The transaction flags are used to collect additional information from the user (e.g. the amount of fees the user is willing to pay). The transaction flags are added to the constructed command using `AddTxFlagsToCmd(cmd)`.
* **Returns the command:** Finally, the transaction command is returned.
Each module can implement `NewTxCmd()`, which aggregates all of the transaction commands of the module. Here is an example from the `x/bank` module:
@ -159,6 +159,7 @@ Modules that want to expose REST queries should add `google.api.http` annotation
https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/proto/cosmos/auth/v1beta1/query.proto#L14-L89
```
<!-- markdown-link-check-disable -->
gRPC gateway is started in-process along with the application and CometBFT. It can be enabled or disabled by setting gRPC Configuration `enable` in [`app.toml`](../run-node/01-run-node.md#configuring-the-node-using-apptoml-and-configtoml).
The Cosmos SDK provides a command for generating [Swagger](https://swagger.io/) documentation (`protoc-gen-swagger`). Setting `swagger` in [`app.toml`](../run-node/01-run-node.md#configuring-the-node-using-apptoml-and-configtoml) defines if swagger documentation should be automatically registered.

View File

@ -37,7 +37,7 @@ for the key-value pairs from the stores to be decoded (_i.e_ unmarshalled)
to their corresponding types. In particular, it matches the key to a concrete type
and then unmarshals the value from the `KVPair` to the type provided.
You can use the example [here](https://github.com/cosmos/cosmos-sdk/blob/v/x/distribution/simulation/decoder.go) from the distribution module to implement your store decoders.
You can use the example [here](https://github.com/cosmos/cosmos-sdk/blob/main/x/distribution/simulation/decoder.go) from the distribution module to implement your store decoders.
### Randomized genesis
@ -48,13 +48,7 @@ Once the module genesis parameter are generated randomly (or with the key and
values defined in a `params` file), they are marshaled to JSON format and added
to the app genesis JSON to use it on the simulations.
You can check an example on how to create the randomized genesis [here](https://github.com/cosmos/cosmos-sdk/blob/v/x/staking/simulation/genesis.go).
### Randomized parameter changes
The simulator is able to test parameter changes at random. The simulator package from each module must contain a `RandomizedParams` func that will simulate parameter changes of the module throughout the simulations lifespan.
You can see how an example of what is needed to fully test parameter changes [here](https://github.com/cosmos/cosmos-sdk/blob/v/x/staking/simulation/params.go)
You can check an example on how to create the randomized genesis [here](https://github.com/cosmos/cosmos-sdk/blob/main/x/staking/simulation/genesis.go).
### Random weighted operations

View File

@ -89,7 +89,7 @@ must equal the constant `"message"`. The `@type` field corresponds to the type o
structure the user will be signing in an application. For now, a user is only
allowed to sign bytes of valid ASCII text ([see here](https://github.com/cometbft/cometbft/blob/v0.37.0/libs/strings/string.go#L35-L64)).
However, this will change and evolve to support additional application-specific
structures that are human-readable and machine-verifiable ([see Future Adaptations](#futureadaptations)).
structures that are human-readable and machine-verifiable.
Thus, we can have a canonical JSON structure for signing Cosmos messages using
the [JSON schema](http://json-schema.org/) specification as such:

View File

@ -277,9 +277,9 @@ func CacheWrap(
```
### Implementation details
<!-- markdown-link-check-disable -->
The inter-block cache implementation uses a fixed-sized adaptive replacement cache (ARC) as cache. [The ARC implementation](https://github.com/hashicorp/golang-lru/blob/master/arc.go) is thread-safe. ARC is an enhancement over the standard LRU cache in that tracks both frequency and recency of use. This avoids a burst in access to new entries from evicting the frequently used older entries. It adds some additional tracking overhead to a standard LRU cache, computationally it is roughly `2x` the cost, and the extra memory overhead is linear with the size of the cache. The default cache size is `1000`.
<!-- markdown-link-check-enable -->
## History
Dec 20, 2022 - Initial draft finished and submitted as a PR

View File

@ -385,7 +385,7 @@ func NewSimApp(
),
auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, app.GetSubspace(authtypes.ModuleName)),
vesting.NewAppModule(app.AccountKeeper, app.BankKeeper),
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, app.GetSubspace(banktypes.ModuleName)),
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper),
crisis.NewAppModule(app.CrisisKeeper, skipGenesisInvariants, app.GetSubspace(crisistypes.ModuleName)),
feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(govtypes.ModuleName)),

View File

@ -100,7 +100,7 @@ func initDeterministicFixture(t *testing.T) *deterministicFixture {
)
authModule := auth.NewAppModule(cdc, accountKeeper, authsims.RandomGenesisAccounts, nil)
bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper, nil)
bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper)
integrationApp := integration.NewIntegrationApp(newCtx, logger, keys, cdc, map[string]appmodule.AppModule{
authtypes.ModuleName: authModule,

View File

@ -107,7 +107,7 @@ func initFixture(tb testing.TB) *fixture {
)
authModule := auth.NewAppModule(cdc, accountKeeper, authsims.RandomGenesisAccounts, nil)
bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper, nil)
bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper)
stakingModule := staking.NewAppModule(cdc, stakingKeeper, accountKeeper, bankKeeper, nil)
distrModule := distribution.NewAppModule(cdc, distrKeeper, accountKeeper, bankKeeper, stakingKeeper, nil)

View File

@ -132,7 +132,7 @@ func initFixture(tb testing.TB) *fixture {
evidenceKeeper.SetRouter(router)
authModule := auth.NewAppModule(cdc, accountKeeper, authsims.RandomGenesisAccounts, nil)
bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper, nil)
bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper)
stakingModule := staking.NewAppModule(cdc, stakingKeeper, accountKeeper, bankKeeper, nil)
slashingModule := slashing.NewAppModule(cdc, slashingKeeper, accountKeeper, bankKeeper, stakingKeeper, nil, cdc.InterfaceRegistry())
evidenceModule := evidence.NewAppModule(*evidenceKeeper)

View File

@ -124,7 +124,7 @@ func initFixture(tb testing.TB) *fixture {
assert.NilError(tb, err)
authModule := auth.NewAppModule(cdc, accountKeeper, authsims.RandomGenesisAccounts, nil)
bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper, nil)
bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper)
stakingModule := staking.NewAppModule(cdc, stakingKeeper, accountKeeper, bankKeeper, nil)
distrModule := distribution.NewAppModule(cdc, distrKeeper, accountKeeper, bankKeeper, stakingKeeper, nil)
govModule := gov.NewAppModule(cdc, govKeeper, accountKeeper, bankKeeper, nil)

View File

@ -95,7 +95,7 @@ func initFixture(tb testing.TB) *fixture {
slashingKeeper := slashingkeeper.NewKeeper(cdc, &codec.LegacyAmino{}, runtime.NewKVStoreService(keys[slashingtypes.StoreKey]), stakingKeeper, authority.String())
bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper, nil)
bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper)
stakingModule := staking.NewAppModule(cdc, stakingKeeper, accountKeeper, bankKeeper, nil)
slashingModule := slashing.NewAppModule(cdc, slashingKeeper, accountKeeper, bankKeeper, stakingKeeper, nil, cdc.InterfaceRegistry())

View File

@ -138,7 +138,7 @@ func initFixture(tb testing.TB) *fixture {
stakingKeeper := stakingkeeper.NewKeeper(cdc, runtime.NewKVStoreService(keys[types.StoreKey]), accountKeeper, bankKeeper, authority.String(), addresscodec.NewBech32Codec(sdk.Bech32PrefixValAddr), addresscodec.NewBech32Codec(sdk.Bech32PrefixConsAddr))
authModule := auth.NewAppModule(cdc, accountKeeper, authsims.RandomGenesisAccounts, nil)
bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper, nil)
bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper)
stakingModule := staking.NewAppModule(cdc, stakingKeeper, accountKeeper, bankKeeper, nil)
integrationApp := integration.NewIntegrationApp(newCtx, logger, keys, cdc, map[string]appmodule.AppModule{

View File

@ -109,7 +109,7 @@ func initDeterministicFixture(t *testing.T) *deterministicFixture {
stakingKeeper := stakingkeeper.NewKeeper(cdc, runtime.NewKVStoreService(keys[stakingtypes.StoreKey]), accountKeeper, bankKeeper, authority.String(), addresscodec.NewBech32Codec(sdk.Bech32PrefixValAddr), addresscodec.NewBech32Codec(sdk.Bech32PrefixConsAddr))
authModule := auth.NewAppModule(cdc, accountKeeper, authsims.RandomGenesisAccounts, nil)
bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper, nil)
bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper)
stakingModule := staking.NewAppModule(cdc, stakingKeeper, accountKeeper, bankKeeper, nil)
integrationApp := integration.NewIntegrationApp(newCtx, logger, keys, cdc, map[string]appmodule.AppModule{

View File

@ -2,7 +2,6 @@ package exported
import (
sdk "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
)
// GenesisBalance defines a genesis balance interface that allows for account
@ -11,15 +10,3 @@ type GenesisBalance interface {
GetAddress() string
GetCoins() sdk.Coins
}
type (
ParamSet = paramtypes.ParamSet
// Subspace defines an interface that implements the legacy x/params Subspace
// type.
//
// NOTE: This is used solely for migration of x/params managed parameters.
Subspace interface {
GetParamSet(ctx sdk.Context, ps ParamSet)
}
)

View File

@ -32,7 +32,6 @@ import (
"github.com/cosmos/cosmos-sdk/types/query"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
vesting "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
"github.com/cosmos/cosmos-sdk/x/bank/exported"
"github.com/cosmos/cosmos-sdk/x/bank/keeper"
banktestutil "github.com/cosmos/cosmos-sdk/x/bank/testutil"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
@ -2343,66 +2342,6 @@ func (suite *KeeperTestSuite) TestGetAllSendEnabledEntries() {
})
}
type mockSubspace struct {
ps banktypes.Params
}
func (ms mockSubspace) GetParamSet(ctx sdk.Context, ps exported.ParamSet) {
*ps.(*banktypes.Params) = ms.ps
}
func (suite *KeeperTestSuite) TestMigrator_Migrate3to4() {
bankKeeper := suite.bankKeeper
ctx := sdk.UnwrapSDKContext(suite.ctx)
require := suite.Require()
for _, def := range []bool{true, false} {
params := banktypes.Params{DefaultSendEnabled: def}
require.NoError(bankKeeper.SetParams(ctx, params))
suite.T().Run(fmt.Sprintf("default %t does not change", def), func(t *testing.T) {
legacySubspace := func(ps banktypes.Params) mockSubspace {
return mockSubspace{ps: ps}
}(banktypes.NewParams(def))
migrator := keeper.NewMigrator(bankKeeper, legacySubspace)
require.NoError(migrator.Migrate3to4(ctx))
actual := bankKeeper.GetParams(ctx)
require.Equal(params.DefaultSendEnabled, actual.DefaultSendEnabled)
})
}
for _, def := range []bool{true, false} {
params := banktypes.Params{
SendEnabled: []*banktypes.SendEnabled{
{Denom: fmt.Sprintf("truecoin%t", def), Enabled: true},
{Denom: fmt.Sprintf("falsecoin%t", def), Enabled: false},
},
}
require.NoError(bankKeeper.SetParams(ctx, params))
suite.T().Run(fmt.Sprintf("default %t send enabled info moved to store", def), func(t *testing.T) {
legacySubspace := func(ps banktypes.Params) mockSubspace {
return mockSubspace{ps: ps}
}(banktypes.NewParams(def))
migrator := keeper.NewMigrator(bankKeeper, legacySubspace)
require.NoError(migrator.Migrate3to4(ctx))
newParams := bankKeeper.GetParams(ctx)
require.Len(newParams.SendEnabled, 0) //nolint:staticcheck // we're testing the old way here
require.Equal(def, newParams.DefaultSendEnabled)
for _, se := range params.SendEnabled {
actual := bankKeeper.IsSendEnabledDenom(ctx, se.Denom)
require.Equal(se.Enabled, actual, se.Denom)
}
})
}
}
func (suite *KeeperTestSuite) TestSetParams() {
ctx, bankKeeper := suite.ctx, suite.bankKeeper
require := suite.Require()

View File

@ -2,34 +2,29 @@ package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/bank/exported"
v2 "github.com/cosmos/cosmos-sdk/x/bank/migrations/v2"
v3 "github.com/cosmos/cosmos-sdk/x/bank/migrations/v3"
v4 "github.com/cosmos/cosmos-sdk/x/bank/migrations/v4"
)
// Migrator is a struct for handling in-place store migrations.
type Migrator struct {
keeper BaseKeeper
legacySubspace exported.Subspace
keeper BaseKeeper
}
// NewMigrator returns a new Migrator.
func NewMigrator(keeper BaseKeeper, legacySubspace exported.Subspace) Migrator {
return Migrator{keeper: keeper, legacySubspace: legacySubspace}
func NewMigrator(keeper BaseKeeper) Migrator {
return Migrator{keeper: keeper}
}
// Migrate1to2 migrates from version 1 to 2.
func (m Migrator) Migrate1to2(ctx sdk.Context) error {
return v2.MigrateStore(ctx, m.keeper.storeService, m.keeper.cdc)
return nil
}
// Migrate2to3 migrates x/bank storage from version 2 to 3.
func (m Migrator) Migrate2to3(ctx sdk.Context) error {
return v3.MigrateStore(ctx, m.keeper.storeService, m.keeper.cdc)
return nil
}
// Migrate3to4 migrates x/bank storage from version 3 to 4.
func (m Migrator) Migrate3to4(ctx sdk.Context) error {
return v4.MigrateStore(ctx, m.keeper.storeService, m.legacySubspace, m.keeper.cdc)
return nil
}

View File

@ -1,71 +0,0 @@
package v1
import (
"github.com/golang/protobuf/proto"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/kv"
v1auth "github.com/cosmos/cosmos-sdk/x/auth/migrations/v1"
"github.com/cosmos/cosmos-sdk/x/bank/types"
)
const (
// ModuleName defines the module name
ModuleName = "bank"
// StoreKey defines the primary module store key
StoreKey = ModuleName
// RouterKey defines the module's message routing key
RouterKey = ModuleName
// QuerierRoute defines the module's query routing key
QuerierRoute = ModuleName
)
// KVStore keys
var (
BalancesPrefix = []byte("balances")
SupplyKey = []byte{0x00}
DenomMetadataPrefix = []byte{0x1}
)
// DenomMetadataKey returns the denomination metadata key.
func DenomMetadataKey(denom string) []byte {
d := []byte(denom)
return append(DenomMetadataPrefix, d...)
}
// AddressFromBalancesStore returns an account address from a balances prefix
// store. The key must not contain the perfix BalancesPrefix as the prefix store
// iterator discards the actual prefix.
func AddressFromBalancesStore(key []byte) sdk.AccAddress {
kv.AssertKeyAtLeastLength(key, 1+v1auth.AddrLen)
addr := key[:v1auth.AddrLen]
kv.AssertKeyLength(addr, v1auth.AddrLen)
return sdk.AccAddress(addr)
}
// SupplyI defines an inflationary supply interface for modules that handle
// token supply.
// It is copy-pasted from:
// https://github.com/cosmos/cosmos-sdk/blob/v0.42.3/x/bank/exported/exported.go
// where we stripped off the unnecessary methods.
//
// It is used in the migration script, because we save this interface as an Any
// in the supply state.
//
// Deprecated.
type SupplyI interface {
proto.Message
}
// RegisterInterfaces registers interfaces required for the v1 migrations.
func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
registry.RegisterInterface(
"cosmos.bank.v1beta1.SupplyI",
(*SupplyI)(nil),
&types.Supply{},
)
}

View File

@ -1,32 +0,0 @@
package v2
import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/bank/types"
)
// pruneZeroBalancesJSON removes the zero balance addresses from exported genesis.
func pruneZeroBalancesJSON(oldBalances []types.Balance) []types.Balance {
var balances []types.Balance
for _, b := range oldBalances {
if !b.Coins.IsZero() {
b.Coins = sdk.NewCoins(b.Coins...) // prunes zero denom.
balances = append(balances, b)
}
}
return balances
}
// MigrateJSON accepts exported v0.40 x/bank genesis state and migrates it to
// v0.43 x/bank genesis state. The migration includes:
// - Prune balances & supply with zero coins (ref: https://github.com/cosmos/cosmos-sdk/pull/9229)
func MigrateJSON(oldState *types.GenesisState) *types.GenesisState {
return &types.GenesisState{
Params: oldState.Params,
Balances: pruneZeroBalancesJSON(oldState.Balances),
Supply: sdk.NewCoins(oldState.Supply...), // NewCoins used here to remove zero coin denoms from supply.
DenomMetadata: oldState.DenomMetadata,
}
}

View File

@ -1,96 +0,0 @@
package v2_test
import (
"encoding/json"
"testing"
"github.com/stretchr/testify/require"
sdkmath "cosmossdk.io/math"
"github.com/cosmos/cosmos-sdk/client"
sdk "github.com/cosmos/cosmos-sdk/types"
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
v2bank "github.com/cosmos/cosmos-sdk/x/bank/migrations/v2"
"github.com/cosmos/cosmos-sdk/x/bank/types"
)
func TestMigrateJSON(t *testing.T) {
encodingConfig := moduletestutil.MakeTestEncodingConfig()
clientCtx := client.Context{}.
WithInterfaceRegistry(encodingConfig.InterfaceRegistry).
WithTxConfig(encodingConfig.TxConfig).
WithCodec(encodingConfig.Codec)
voter, err := sdk.AccAddressFromBech32("cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh")
require.NoError(t, err)
bankGenState := &types.GenesisState{
Balances: []types.Balance{
{
Address: voter.String(),
Coins: sdk.Coins{
sdk.NewCoin("foo", sdkmath.NewInt(10)),
sdk.NewCoin("bar", sdkmath.NewInt(20)),
sdk.NewCoin("foobar", sdkmath.NewInt(0)),
},
},
},
Supply: sdk.Coins{
sdk.NewCoin("foo", sdkmath.NewInt(10)),
sdk.NewCoin("bar", sdkmath.NewInt(20)),
sdk.NewCoin("foobar", sdkmath.NewInt(0)),
sdk.NewCoin("barfoo", sdkmath.NewInt(0)),
},
}
migrated := v2bank.MigrateJSON(bankGenState)
bz, err := clientCtx.Codec.MarshalJSON(migrated)
require.NoError(t, err)
// Indent the JSON bz correctly.
var jsonObj map[string]interface{}
err = json.Unmarshal(bz, &jsonObj)
require.NoError(t, err)
indentedBz, err := json.MarshalIndent(jsonObj, "", "\t")
require.NoError(t, err)
// Make sure about:
// - zero coin balances pruned.
// - zero supply denoms pruned.
expected := `{
"balances": [
{
"address": "cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh",
"coins": [
{
"amount": "20",
"denom": "bar"
},
{
"amount": "10",
"denom": "foo"
}
]
}
],
"denom_metadata": [],
"params": {
"default_send_enabled": false,
"send_enabled": []
},
"send_enabled": [],
"supply": [
{
"amount": "20",
"denom": "bar"
},
{
"amount": "10",
"denom": "foo"
}
]
}`
require.Equal(t, expected, string(indentedBz))
}

View File

@ -1,45 +0,0 @@
package v2
import (
"errors"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
)
const (
ModuleName = "bank"
)
var (
SupplyKey = []byte{0x00}
BalancesPrefix = []byte{0x02}
DenomMetadataPrefix = []byte{0x1}
ErrInvalidKey = errors.New("invalid key")
)
func CreateAccountBalancesPrefix(addr []byte) []byte {
return append(BalancesPrefix, address.MustLengthPrefix(addr)...)
}
func AddressFromBalancesStore(key []byte) (sdk.AccAddress, error) {
if len(key) == 0 {
return nil, ErrInvalidKey
}
addrLen := key[0]
bound := int(addrLen)
if len(key)-1 < bound {
return nil, ErrInvalidKey
}
return key[1 : bound+1], nil
}
// DenomMetadataKey returns the denomination metadata key.
func DenomMetadataKey(denom string) []byte {
d := []byte(denom)
return append(DenomMetadataPrefix, d...)
}

View File

@ -1,143 +0,0 @@
package v2
import (
"cosmossdk.io/core/store"
"cosmossdk.io/log"
"cosmossdk.io/math"
"cosmossdk.io/store/prefix"
storetypes "cosmossdk.io/store/types"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/runtime"
sdk "github.com/cosmos/cosmos-sdk/types"
v1auth "github.com/cosmos/cosmos-sdk/x/auth/migrations/v1"
v1 "github.com/cosmos/cosmos-sdk/x/bank/migrations/v1"
"github.com/cosmos/cosmos-sdk/x/bank/types"
)
// migrateSupply migrates the supply to be stored by denom key instead in a
// single blob.
// ref: https://github.com/cosmos/cosmos-sdk/issues/7092
func migrateSupply(store storetypes.KVStore, cdc codec.BinaryCodec) error {
// Old supply was stored as a single blob under the SupplyKey.
var oldSupplyI v1.SupplyI
err := cdc.UnmarshalInterface(store.Get(v1.SupplyKey), &oldSupplyI)
if err != nil {
return err
}
// We delete the single key holding the whole blob.
store.Delete(v1.SupplyKey)
if oldSupplyI == nil {
return nil
}
// We add a new key for each denom
supplyStore := prefix.NewStore(store, SupplyKey)
// We're sure that SupplyI is a Supply struct, there's no other
// implementation.
oldSupply := oldSupplyI.(*types.Supply)
for i := range oldSupply.Total {
coin := oldSupply.Total[i]
coinBz, err := coin.Amount.Marshal()
if err != nil {
return err
}
supplyStore.Set([]byte(coin.Denom), coinBz)
}
return nil
}
// migrateBalanceKeys migrate the balances keys to cater for variable-length
// addresses.
func migrateBalanceKeys(store storetypes.KVStore, logger log.Logger) {
// old key is of format:
// prefix ("balances") || addrBytes (20 bytes) || denomBytes
// new key is of format
// prefix (0x02) || addrLen (1 byte) || addrBytes || denomBytes
oldStore := prefix.NewStore(store, v1.BalancesPrefix)
oldStoreIter := oldStore.Iterator(nil, nil)
defer sdk.LogDeferred(logger, func() error { return oldStoreIter.Close() })
for ; oldStoreIter.Valid(); oldStoreIter.Next() {
addr := v1.AddressFromBalancesStore(oldStoreIter.Key())
denom := oldStoreIter.Key()[v1auth.AddrLen:]
newStoreKey := CreatePrefixedAccountStoreKey(addr, denom)
// Set new key on store. Values don't change.
store.Set(newStoreKey, oldStoreIter.Value())
oldStore.Delete(oldStoreIter.Key())
}
}
// MigrateStore performs in-place store migrations from v0.40 to v0.43. The
// migration includes:
//
// - Change addresses to be length-prefixed.
// - Change balances prefix to 1 byte
// - Change supply to be indexed by denom
// - Prune balances & supply with zero coins (ref: https://github.com/cosmos/cosmos-sdk/pull/9229)
func MigrateStore(ctx sdk.Context, storeService store.KVStoreService, cdc codec.BinaryCodec) error {
store := runtime.KVStoreAdapter(storeService.OpenKVStore(ctx))
migrateBalanceKeys(store, ctx.Logger())
if err := pruneZeroBalances(store, cdc); err != nil {
return err
}
if err := migrateSupply(store, cdc); err != nil {
return err
}
return pruneZeroSupply(store)
}
// pruneZeroBalances removes the zero balance addresses from balances store.
func pruneZeroBalances(store storetypes.KVStore, cdc codec.BinaryCodec) error {
balancesStore := prefix.NewStore(store, BalancesPrefix)
iterator := balancesStore.Iterator(nil, nil)
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
var balance sdk.Coin
if err := cdc.Unmarshal(iterator.Value(), &balance); err != nil {
return err
}
if balance.IsZero() {
balancesStore.Delete(iterator.Key())
}
}
return nil
}
// pruneZeroSupply removes zero balance denom from supply store.
func pruneZeroSupply(store storetypes.KVStore) error {
supplyStore := prefix.NewStore(store, SupplyKey)
iterator := supplyStore.Iterator(nil, nil)
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
var amount math.Int
if err := amount.Unmarshal(iterator.Value()); err != nil {
return err
}
if amount.IsZero() {
supplyStore.Delete(iterator.Key())
}
}
return nil
}
// CreatePrefixedAccountStoreKey returns the key for the given account and denomination.
// This method can be used when performing an ABCI query for the balance of an account.
func CreatePrefixedAccountStoreKey(addr, denom []byte) []byte {
return append(CreateAccountBalancesPrefix(addr), denom...)
}

View File

@ -1,109 +0,0 @@
package v2_test
import (
"testing"
"github.com/stretchr/testify/require"
"cosmossdk.io/math"
"cosmossdk.io/store/prefix"
storetypes "cosmossdk.io/store/types"
"github.com/cosmos/cosmos-sdk/runtime"
"github.com/cosmos/cosmos-sdk/testutil"
"github.com/cosmos/cosmos-sdk/testutil/testdata"
sdk "github.com/cosmos/cosmos-sdk/types"
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
v1bank "github.com/cosmos/cosmos-sdk/x/bank/migrations/v1"
v2bank "github.com/cosmos/cosmos-sdk/x/bank/migrations/v2"
"github.com/cosmos/cosmos-sdk/x/bank/types"
)
func TestSupplyMigration(t *testing.T) {
encCfg := moduletestutil.MakeTestEncodingConfig()
bankKey := storetypes.NewKVStoreKey("bank")
storeService := runtime.NewKVStoreService(bankKey)
ctx := testutil.DefaultContext(bankKey, storetypes.NewTransientStoreKey("transient_test"))
store := runtime.KVStoreAdapter(storeService.OpenKVStore(ctx))
v1bank.RegisterInterfaces(encCfg.InterfaceRegistry)
oldFooCoin := sdk.NewCoin("foo", math.NewInt(100))
oldBarCoin := sdk.NewCoin("bar", math.NewInt(200))
oldFooBarCoin := sdk.NewCoin("foobar", math.NewInt(0)) // to ensure the zero denom coins pruned.
// Old supply was stored as a single blob under the `SupplyKey`.
oldSupply := &types.Supply{Total: sdk.Coins{oldFooCoin, oldBarCoin, oldFooBarCoin}}
oldSupplyBz, err := encCfg.Codec.MarshalInterface(oldSupply)
require.NoError(t, err)
store.Set(v1bank.SupplyKey, oldSupplyBz)
// Run migration.
err = v2bank.MigrateStore(ctx, storeService, encCfg.Codec)
require.NoError(t, err)
// New supply is indexed by denom.
supplyStore := prefix.NewStore(store, types.SupplyKey)
bz := supplyStore.Get([]byte("foo"))
var amount math.Int
err = amount.Unmarshal(bz)
require.NoError(t, err)
newFooCoin := sdk.Coin{
Denom: "foo",
Amount: amount,
}
require.Equal(t, oldFooCoin, newFooCoin)
bz = supplyStore.Get([]byte("bar"))
err = amount.Unmarshal(bz)
require.NoError(t, err)
newBarCoin := sdk.Coin{
Denom: "bar",
Amount: amount,
}
require.Equal(t, oldBarCoin, newBarCoin)
// foobar shouldn't be existed in the store.
bz = supplyStore.Get([]byte("foobar"))
require.Nil(t, bz)
}
func TestBalanceKeysMigration(t *testing.T) {
encCfg := moduletestutil.MakeTestEncodingConfig()
bankKey := storetypes.NewKVStoreKey("bank")
storeService := runtime.NewKVStoreService(bankKey)
ctx := testutil.DefaultContext(bankKey, storetypes.NewTransientStoreKey("transient_test"))
store := runtime.KVStoreAdapter(storeService.OpenKVStore(ctx))
_, _, addr := testdata.KeyTestPubAddr()
// set 10 foo coin
fooCoin := sdk.NewCoin("foo", math.NewInt(10))
oldFooKey := append(append(v1bank.BalancesPrefix, addr...), []byte(fooCoin.Denom)...)
fooBz, err := encCfg.Codec.Marshal(&fooCoin)
require.NoError(t, err)
store.Set(oldFooKey, fooBz)
// set 0 foobar coin
fooBarCoin := sdk.NewCoin("foobar", math.NewInt(0))
oldKeyFooBar := append(append(v1bank.BalancesPrefix, addr...), []byte(fooBarCoin.Denom)...)
fooBarBz, err := encCfg.Codec.Marshal(&fooBarCoin)
require.NoError(t, err)
store.Set(oldKeyFooBar, fooBarBz)
require.NotNil(t, store.Get(oldKeyFooBar)) // before store migation zero values can also exist in store.
err = v2bank.MigrateStore(ctx, storeService, encCfg.Codec)
require.NoError(t, err)
newKey := v2bank.CreatePrefixedAccountStoreKey(addr, []byte(fooCoin.Denom))
// -7 because we replaced "balances" with 0x02,
// +1 because we added length-prefix to address.
require.Equal(t, len(oldFooKey)-7+1, len(newKey))
require.Nil(t, store.Get(oldFooKey))
require.Equal(t, fooBz, store.Get(newKey))
newKeyFooBar := v2bank.CreatePrefixedAccountStoreKey(addr, []byte(fooBarCoin.Denom))
require.Nil(t, store.Get(newKeyFooBar)) // after migration zero balances pruned from store.
}

View File

@ -1,14 +0,0 @@
package v3
var DenomAddressPrefix = []byte{0x03}
// CreateDenomAddressPrefix creates a prefix for a reverse index of denomination
// to account balance for that denomination.
func CreateDenomAddressPrefix(denom string) []byte {
// we add a "zero" byte at the end - null byte terminator, to allow prefix denom prefix
// scan. Setting it is not needed (key[last] = 0) - because this is the default.
key := make([]byte, len(DenomAddressPrefix)+len(denom)+1)
copy(key, DenomAddressPrefix)
copy(key[len(DenomAddressPrefix):], denom)
return key
}

View File

@ -1,103 +0,0 @@
package v3
import (
"cosmossdk.io/core/store"
"cosmossdk.io/log"
"cosmossdk.io/store/prefix"
storetypes "cosmossdk.io/store/types"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/runtime"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
v2 "github.com/cosmos/cosmos-sdk/x/bank/migrations/v2"
"github.com/cosmos/cosmos-sdk/x/bank/types"
)
// MigrateStore performs in-place store migrations from v0.43 to v0.45. The
// migration includes:
//
// - Migrate coin storage to save only amount.
// - Add an additional reverse index from denomination to address.
// - Remove duplicate denom from denom metadata store key.
func MigrateStore(ctx sdk.Context, storeService store.KVStoreService, cdc codec.BinaryCodec) error {
store := runtime.KVStoreAdapter(storeService.OpenKVStore(ctx))
err := addDenomReverseIndex(store, cdc, ctx.Logger())
if err != nil {
return err
}
return migrateDenomMetadata(store, ctx.Logger())
}
func addDenomReverseIndex(store storetypes.KVStore, cdc codec.BinaryCodec, logger log.Logger) error {
oldBalancesStore := prefix.NewStore(store, v2.BalancesPrefix)
oldBalancesIter := oldBalancesStore.Iterator(nil, nil)
defer sdk.LogDeferred(logger, func() error { return oldBalancesIter.Close() })
denomPrefixStores := make(map[string]prefix.Store) // memoize prefix stores
for ; oldBalancesIter.Valid(); oldBalancesIter.Next() {
var balance sdk.Coin
if err := cdc.Unmarshal(oldBalancesIter.Value(), &balance); err != nil {
return err
}
addr, err := v2.AddressFromBalancesStore(oldBalancesIter.Key())
if err != nil {
return err
}
var coin sdk.DecCoin
if err := cdc.Unmarshal(oldBalancesIter.Value(), &coin); err != nil {
return err
}
bz, err := coin.Amount.Marshal()
if err != nil {
return err
}
newStore := prefix.NewStore(store, CreateAccountBalancesPrefix(addr))
newStore.Set([]byte(coin.Denom), bz)
denomPrefixStore, ok := denomPrefixStores[balance.Denom]
if !ok {
denomPrefixStore = prefix.NewStore(store, CreateDenomAddressPrefix(balance.Denom))
denomPrefixStores[balance.Denom] = denomPrefixStore
}
// Store a reverse index from denomination to account address with a
// sentinel value.
denomPrefixStore.Set(address.MustLengthPrefix(addr), []byte{0})
}
return nil
}
func migrateDenomMetadata(store storetypes.KVStore, logger log.Logger) error {
oldDenomMetaDataStore := prefix.NewStore(store, v2.DenomMetadataPrefix)
oldDenomMetaDataIter := oldDenomMetaDataStore.Iterator(nil, nil)
defer sdk.LogDeferred(logger, func() error { return oldDenomMetaDataIter.Close() })
for ; oldDenomMetaDataIter.Valid(); oldDenomMetaDataIter.Next() {
oldKey := oldDenomMetaDataIter.Key()
l := len(oldKey) / 2
newKey := make([]byte, len(types.DenomMetadataPrefix)+l)
// old key: prefix_bytes | denom_bytes | denom_bytes
copy(newKey, types.DenomMetadataPrefix)
copy(newKey[len(types.DenomMetadataPrefix):], oldKey[:l])
store.Set(newKey, oldDenomMetaDataIter.Value())
oldDenomMetaDataStore.Delete(oldKey)
}
return nil
}
// CreateAccountBalancesPrefix creates the prefix for an account's balances.
func CreateAccountBalancesPrefix(addr []byte) []byte {
return append(types.BalancesPrefix.Bytes(), address.MustLengthPrefix(addr)...)
}

View File

@ -1,136 +0,0 @@
package v3_test
import (
"testing"
"github.com/stretchr/testify/require"
"cosmossdk.io/math"
"cosmossdk.io/store/prefix"
storetypes "cosmossdk.io/store/types"
"github.com/cosmos/cosmos-sdk/runtime"
"github.com/cosmos/cosmos-sdk/testutil"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/address"
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
v2 "github.com/cosmos/cosmos-sdk/x/bank/migrations/v2"
v3 "github.com/cosmos/cosmos-sdk/x/bank/migrations/v3"
"github.com/cosmos/cosmos-sdk/x/bank/types"
)
func TestMigrateStore(t *testing.T) {
encCfg := moduletestutil.MakeTestEncodingConfig()
bankKey := storetypes.NewKVStoreKey("bank")
storeService := runtime.NewKVStoreService(bankKey)
ctx := testutil.DefaultContext(bankKey, storetypes.NewTransientStoreKey("transient_test"))
store := runtime.KVStoreAdapter(storeService.OpenKVStore(ctx))
addr := sdk.AccAddress([]byte("addr________________"))
prefixAccStore := prefix.NewStore(store, v2.CreateAccountBalancesPrefix(addr))
balances := sdk.NewCoins(
sdk.NewCoin("foo", math.NewInt(10000)),
sdk.NewCoin("bar", math.NewInt(20000)),
)
for _, b := range balances {
bz, err := encCfg.Codec.Marshal(&b) //nolint:gosec // G601: Implicit memory aliasing in for loop.
require.NoError(t, err)
prefixAccStore.Set([]byte(b.Denom), bz)
}
require.NoError(t, v3.MigrateStore(ctx, storeService, encCfg.Codec))
for _, b := range balances {
addrPrefixStore := prefix.NewStore(store, v3.CreateAccountBalancesPrefix(addr))
bz := addrPrefixStore.Get([]byte(b.Denom))
var expected math.Int
require.NoError(t, expected.Unmarshal(bz))
require.Equal(t, expected, b.Amount)
}
for _, b := range balances {
denomPrefixStore := prefix.NewStore(store, v3.CreateDenomAddressPrefix(b.Denom))
bz := denomPrefixStore.Get(address.MustLengthPrefix(addr))
require.NotNil(t, bz)
}
}
func TestMigrateDenomMetaData(t *testing.T) {
encCfg := moduletestutil.MakeTestEncodingConfig()
bankKey := storetypes.NewKVStoreKey("bank")
storeService := runtime.NewKVStoreService(bankKey)
ctx := testutil.DefaultContext(bankKey, storetypes.NewTransientStoreKey("transient_test"))
store := runtime.KVStoreAdapter(storeService.OpenKVStore(ctx))
metaData := []types.Metadata{
{
Name: "Cosmos Hub Atom",
Symbol: "ATOM",
Description: "The native staking token of the Cosmos Hub.",
DenomUnits: []*types.DenomUnit{
{Denom: "uatom", Exponent: uint32(0), Aliases: []string{"microatom"}},
{Denom: "matom", Exponent: uint32(3), Aliases: []string{"milliatom"}},
{Denom: "atom", Exponent: uint32(6), Aliases: nil},
},
Base: "uatom",
Display: "atom",
},
{
Name: "Token",
Symbol: "TOKEN",
Description: "The native staking token of the Token Hub.",
DenomUnits: []*types.DenomUnit{
{Denom: "1token", Exponent: uint32(5), Aliases: []string{"decitoken"}},
{Denom: "2token", Exponent: uint32(4), Aliases: []string{"centitoken"}},
{Denom: "3token", Exponent: uint32(7), Aliases: []string{"dekatoken"}},
},
Base: "utoken",
Display: "token",
},
}
denomMetadataStore := prefix.NewStore(store, v2.DenomMetadataPrefix)
for i := range []int{0, 1} {
// keys before 0.45 had denom two times in the key
key := append([]byte{}, []byte(metaData[i].Base)...)
key = append(key, []byte(metaData[i].Base)...)
bz, err := encCfg.Codec.Marshal(&metaData[i])
require.NoError(t, err)
denomMetadataStore.Set(key, bz)
}
require.NoError(t, v3.MigrateStore(ctx, storeService, encCfg.Codec))
denomMetadataStore = prefix.NewStore(store, v2.DenomMetadataPrefix)
denomMetadataIter := denomMetadataStore.Iterator(nil, nil)
defer denomMetadataIter.Close()
for i := 0; denomMetadataIter.Valid(); denomMetadataIter.Next() {
var result types.Metadata
newKey := denomMetadataIter.Key()
// make sure old entry is deleted
oldKey := append(newKey, newKey[0:]...)
bz := denomMetadataStore.Get(oldKey)
require.Nil(t, bz)
require.Equal(t, string(newKey), metaData[i].Base, "idx: %d", i)
bz = denomMetadataStore.Get(denomMetadataIter.Key())
require.NotNil(t, bz)
err := encCfg.Codec.Unmarshal(bz, &result)
require.NoError(t, err)
assertMetaDataEqual(t, metaData[i], result)
i++
}
}
func assertMetaDataEqual(t *testing.T, expected, actual types.Metadata) {
t.Helper()
require.Equal(t, expected.GetBase(), actual.GetBase())
require.Equal(t, expected.GetDisplay(), actual.GetDisplay())
require.Equal(t, expected.GetDescription(), actual.GetDescription())
require.Equal(t, expected.GetDenomUnits()[1].GetDenom(), actual.GetDenomUnits()[1].GetDenom())
require.Equal(t, expected.GetDenomUnits()[1].GetExponent(), actual.GetDenomUnits()[1].GetExponent())
require.Equal(t, expected.GetDenomUnits()[1].GetAliases(), actual.GetDenomUnits()[1].GetAliases())
}

View File

@ -1,14 +0,0 @@
package v4
import (
"github.com/cosmos/cosmos-sdk/x/bank/types"
)
// MigrateGenState accepts exported v0.43 x/bank genesis state and migrates it to
// v0.47 x/bank genesis state. The migration includes:
// - Move the SendEnabled entries from Params to the new GenesisState.SendEnabled field.
func MigrateGenState(oldState *types.GenesisState) *types.GenesisState {
newState := *oldState
newState.MigrateSendEnabled()
return &newState
}

View File

@ -1,161 +0,0 @@
package v4_test
import (
"testing"
"github.com/stretchr/testify/assert"
sdkmath "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
v4 "github.com/cosmos/cosmos-sdk/x/bank/migrations/v4"
"github.com/cosmos/cosmos-sdk/x/bank/types"
)
func TestMigrateGenState(t *testing.T) {
tests := []struct {
name string
oldState *types.GenesisState
newState *types.GenesisState
}{
{
name: "Balances supply metadata all unchanged",
oldState: &types.GenesisState{
Params: types.Params{},
Balances: []types.Balance{{
Address: "balance1",
Coins: sdk.Coins{sdk.NewCoin("balance1coin", sdkmath.NewInt(8))},
}},
Supply: sdk.Coins{sdk.NewCoin("supplycoin", sdkmath.NewInt(800))},
DenomMetadata: []types.Metadata{{
Description: "metadesk",
DenomUnits: nil,
Base: "meta",
Display: "meta",
Name: "foo",
Symbol: "META",
URI: "",
URIHash: "",
}},
SendEnabled: []types.SendEnabled{},
},
newState: &types.GenesisState{
Params: types.Params{},
Balances: []types.Balance{{
Address: "balance1",
Coins: sdk.Coins{sdk.NewCoin("balance1coin", sdkmath.NewInt(8))},
}},
Supply: sdk.Coins{sdk.NewCoin("supplycoin", sdkmath.NewInt(800))},
DenomMetadata: []types.Metadata{{
Description: "metadesk",
DenomUnits: nil,
Base: "meta",
Display: "meta",
Name: "foo",
Symbol: "META",
URI: "",
URIHash: "",
}},
SendEnabled: []types.SendEnabled{},
},
},
{
name: "default send enabled true not changed",
oldState: &types.GenesisState{
Params: types.Params{DefaultSendEnabled: true},
},
newState: &types.GenesisState{
Params: types.Params{DefaultSendEnabled: true},
},
},
{
name: "default send enabled false not changed",
oldState: &types.GenesisState{
Params: types.Params{DefaultSendEnabled: false, SendEnabled: []*types.SendEnabled{}},
},
newState: &types.GenesisState{
Params: types.Params{DefaultSendEnabled: false},
},
},
{
name: "send enabled entries moved",
oldState: &types.GenesisState{
Params: types.Params{
SendEnabled: []*types.SendEnabled{
{Denom: "movecointrue", Enabled: true},
{Denom: "movecoinfalse", Enabled: false},
},
},
},
newState: &types.GenesisState{
Params: types.Params{},
SendEnabled: []types.SendEnabled{
{Denom: "movecointrue", Enabled: true},
{Denom: "movecoinfalse", Enabled: false},
},
},
},
{
name: "params entries added to existing",
oldState: &types.GenesisState{
Params: types.Params{
SendEnabled: []*types.SendEnabled{
{Denom: "movecointrue", Enabled: true},
{Denom: "movecoinfalse", Enabled: false},
},
},
SendEnabled: []types.SendEnabled{
{Denom: "staycoin", Enabled: true},
},
},
newState: &types.GenesisState{
Params: types.Params{},
SendEnabled: []types.SendEnabled{
{Denom: "staycoin", Enabled: true},
{Denom: "movecointrue", Enabled: true},
{Denom: "movecoinfalse", Enabled: false},
},
},
},
{
name: "conflicting params ignored",
oldState: &types.GenesisState{
Params: types.Params{
SendEnabled: []*types.SendEnabled{
{Denom: "staycoin", Enabled: false},
},
},
SendEnabled: []types.SendEnabled{
{Denom: "staycoin", Enabled: true},
},
},
newState: &types.GenesisState{
Params: types.Params{},
SendEnabled: []types.SendEnabled{
{Denom: "staycoin", Enabled: true},
},
},
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
actual := v4.MigrateGenState(tc.oldState)
assert.Equal(t, tc.newState, actual)
})
}
t.Run("ensure original not changed", func(t *testing.T) {
origState := types.GenesisState{
Params: types.Params{
SendEnabled: []*types.SendEnabled{
{Denom: "movecointrue", Enabled: true},
{Denom: "movecoinfalse", Enabled: false},
},
},
}
_ = v4.MigrateGenState(&origState)
assert.Len(t, origState.Params.SendEnabled, 2)
})
}

View File

@ -1,35 +0,0 @@
package v4
import (
"cosmossdk.io/core/store"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/bank/exported"
"github.com/cosmos/cosmos-sdk/x/bank/types"
)
const ModuleName = "bank"
var ParamsKey = []byte{0x05}
// MigrateStore migrates the x/bank module state from the consensus version 3 to
// version 4. Specifically, it takes the parameters that are currently stored
// and managed by the x/params module and stores them directly into the x/bank
// module state.
func MigrateStore(ctx sdk.Context, storeService store.KVStoreService, legacySubspace exported.Subspace, cdc codec.BinaryCodec) error {
var currParams types.Params
legacySubspace.GetParamSet(ctx, &currParams)
if err := currParams.Validate(); err != nil {
return err
}
bz, err := cdc.Marshal(&currParams)
if err != nil {
return err
}
store := storeService.OpenKVStore(ctx)
return store.Set(ParamsKey, bz)
}

View File

@ -1,51 +0,0 @@
package v4_test
import (
"testing"
"github.com/stretchr/testify/require"
storetypes "cosmossdk.io/store/types"
"github.com/cosmos/cosmos-sdk/runtime"
"github.com/cosmos/cosmos-sdk/testutil"
sdk "github.com/cosmos/cosmos-sdk/types"
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
"github.com/cosmos/cosmos-sdk/x/bank"
"github.com/cosmos/cosmos-sdk/x/bank/exported"
v4 "github.com/cosmos/cosmos-sdk/x/bank/migrations/v4"
"github.com/cosmos/cosmos-sdk/x/bank/types"
)
type mockSubspace struct {
ps types.Params
}
func newMockSubspace(ps types.Params) mockSubspace {
return mockSubspace{ps: ps}
}
func (ms mockSubspace) GetParamSet(ctx sdk.Context, ps exported.ParamSet) {
*ps.(*types.Params) = ms.ps
}
func TestMigrate(t *testing.T) {
encCfg := moduletestutil.MakeTestEncodingConfig(bank.AppModuleBasic{})
cdc := encCfg.Codec
storeKey := storetypes.NewKVStoreKey(v4.ModuleName)
tKey := storetypes.NewTransientStoreKey("transient_test")
ctx := testutil.DefaultContext(storeKey, tKey)
storeService := runtime.NewKVStoreService(storeKey)
legacySubspace := newMockSubspace(types.DefaultParams())
require.NoError(t, v4.MigrateStore(ctx, storeService, legacySubspace, cdc))
var res types.Params
store := storeService.OpenKVStore(ctx)
bz, err := store.Get(v4.ParamsKey)
require.NoError(t, err)
require.NoError(t, cdc.Unmarshal(bz, &res))
require.Equal(t, legacySubspace.ps, res)
}

View File

@ -25,9 +25,7 @@ import (
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/bank/client/cli"
"github.com/cosmos/cosmos-sdk/x/bank/exported"
"github.com/cosmos/cosmos-sdk/x/bank/keeper"
v1bank "github.com/cosmos/cosmos-sdk/x/bank/migrations/v1"
"github.com/cosmos/cosmos-sdk/x/bank/simulation"
"github.com/cosmos/cosmos-sdk/x/bank/types"
)
@ -90,9 +88,6 @@ func (ab AppModuleBasic) GetTxCmd() *cobra.Command {
// RegisterInterfaces registers interfaces and implementations of the bank module.
func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) {
types.RegisterInterfaces(registry)
// Register legacy interfaces for migration scripts.
v1bank.RegisterInterfaces(registry)
}
// AppModule implements an application module for the bank module.
@ -101,9 +96,6 @@ type AppModule struct {
keeper keeper.Keeper
accountKeeper types.AccountKeeper
// legacySubspace is used solely for migration of x/params managed parameters
legacySubspace exported.Subspace
}
// IsOnePerModuleType implements the depinject.OnePerModuleType interface.
@ -117,7 +109,8 @@ func (am AppModule) RegisterServices(cfg module.Configurator) {
types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper))
types.RegisterQueryServer(cfg.QueryServer(), am.keeper)
m := keeper.NewMigrator(am.keeper.(keeper.BaseKeeper), am.legacySubspace)
m := keeper.NewMigrator(am.keeper.(keeper.BaseKeeper))
if err := cfg.RegisterMigration(types.ModuleName, 1, m.Migrate1to2); err != nil {
panic(fmt.Sprintf("failed to migrate x/bank from version 1 to 2: %v", err))
}
@ -132,12 +125,11 @@ func (am AppModule) RegisterServices(cfg module.Configurator) {
}
// NewAppModule creates a new AppModule object
func NewAppModule(cdc codec.Codec, keeper keeper.Keeper, accountKeeper types.AccountKeeper, ss exported.Subspace) AppModule {
func NewAppModule(cdc codec.Codec, keeper keeper.Keeper, accountKeeper types.AccountKeeper) AppModule {
return AppModule{
AppModuleBasic: AppModuleBasic{cdc: cdc, ac: accountKeeper.AddressCodec()},
keeper: keeper,
accountKeeper: accountKeeper,
legacySubspace: ss,
}
}
@ -211,9 +203,6 @@ type ModuleInputs struct {
Logger log.Logger
AccountKeeper types.AccountKeeper
// LegacySubspace is used solely for migration of x/params managed parameters
LegacySubspace exported.Subspace `optional:"true"`
}
type ModuleOutputs struct {
@ -253,7 +242,7 @@ func ProvideModule(in ModuleInputs) ModuleOutputs {
authority.String(),
in.Logger,
)
m := NewAppModule(in.Cdc, bankKeeper, in.AccountKeeper, in.LegacySubspace)
m := NewAppModule(in.Cdc, bankKeeper, in.AccountKeeper)
return ModuleOutputs{BankKeeper: bankKeeper, Module: m}
}

View File

@ -13,20 +13,13 @@ import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/version"
v043 "github.com/cosmos/cosmos-sdk/x/genutil/migrations/v043"
v046 "github.com/cosmos/cosmos-sdk/x/genutil/migrations/v046"
v047 "github.com/cosmos/cosmos-sdk/x/genutil/migrations/v047"
"github.com/cosmos/cosmos-sdk/x/genutil/types"
)
const flagGenesisTime = "genesis-time"
// MigrationMap is a map of SDK versions to their respective genesis migration functions.
var MigrationMap = types.MigrationMap{
"v0.43": v043.Migrate, // NOTE: v0.43, v0.44 and v0.45 are genesis compatible.
"v0.46": v046.Migrate,
"v0.47": v047.Migrate,
}
var MigrationMap = types.MigrationMap{}
// MigrateGenesisCmd returns a command to execute genesis state migration.
// Applications should pass their own migration map to this function.

View File

@ -22,12 +22,6 @@ func TestMigrateGenesis(t *testing.T) {
expErrMsg string
check func(jsonOut string)
}{
{
"migrate 0.37 to 0.43",
v037Exported,
"v0.43",
true, "make sure that you have correctly migrated all CometBFT consensus params", func(_ string) {},
},
{
"invalid target version",
func() string {
@ -37,7 +31,8 @@ func TestMigrateGenesis(t *testing.T) {
return string(bz)
}(),
"v0.10",
true, "unknown migration function for version: v0.10 (supported versions v0.43, v0.46, v0.47)", func(_ string) {},
true,
"unknown migration function for version: v0.10", func(_ string) {},
},
{
"invalid target version",
@ -48,7 +43,8 @@ func TestMigrateGenesis(t *testing.T) {
return string(bz)
}(),
"v0.10",
true, "unknown migration function for version: v0.10 (supported versions v0.43, v0.46, v0.47)", func(_ string) {},
true,
"unknown migration function for version: v0.10", func(_ string) {},
},
}

View File

@ -1,44 +0,0 @@
package v043
import (
"github.com/cosmos/cosmos-sdk/client"
v1bank "github.com/cosmos/cosmos-sdk/x/bank/migrations/v1"
v2bank "github.com/cosmos/cosmos-sdk/x/bank/migrations/v2"
bank "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/genutil/types"
v1gov "github.com/cosmos/cosmos-sdk/x/gov/migrations/v1"
v2gov "github.com/cosmos/cosmos-sdk/x/gov/migrations/v2"
gov "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
)
// Migrate migrates exported state from v0.40 to a v0.43 genesis state.
func Migrate(appState types.AppMap, clientCtx client.Context) (types.AppMap, error) {
// Migrate x/gov.
if appState[v1gov.ModuleName] != nil {
// unmarshal relative source genesis application state
var oldGovState gov.GenesisState
clientCtx.Codec.MustUnmarshalJSON(appState[v1gov.ModuleName], &oldGovState)
// delete deprecated x/gov genesis state
delete(appState, v1gov.ModuleName)
// Migrate relative source genesis application state and marshal it into
// the respective key.
appState[v2gov.ModuleName] = clientCtx.Codec.MustMarshalJSON(v2gov.MigrateJSON(&oldGovState))
}
if appState[v1bank.ModuleName] != nil {
// unmarshal relative source genesis application state
var oldBankState bank.GenesisState
clientCtx.Codec.MustUnmarshalJSON(appState[v1bank.ModuleName], &oldBankState)
// delete deprecated x/bank genesis state
delete(appState, v1bank.ModuleName)
// Migrate relative source genesis application state and marshal it into
// the respective key.
appState[v2bank.ModuleName] = clientCtx.Codec.MustMarshalJSON(v2bank.MigrateJSON(&oldBankState))
}
return appState, nil
}

View File

@ -1,53 +0,0 @@
package v046
import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/x/genutil/types"
v2gov "github.com/cosmos/cosmos-sdk/x/gov/migrations/v2"
v3gov "github.com/cosmos/cosmos-sdk/x/gov/migrations/v3"
govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
stakingv2 "github.com/cosmos/cosmos-sdk/x/staking/migrations/v2"
stakingv3 "github.com/cosmos/cosmos-sdk/x/staking/migrations/v3"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)
// Migrate migrates exported state from v0.43 to a v0.46 genesis state.
func Migrate(appState types.AppMap, clientCtx client.Context) (types.AppMap, error) {
// Migrate x/gov.
if appState[v2gov.ModuleName] != nil {
// unmarshal relative source genesis application state
var old govv1beta1.GenesisState
clientCtx.Codec.MustUnmarshalJSON(appState[v2gov.ModuleName], &old)
// delete deprecated x/gov genesis state
delete(appState, v2gov.ModuleName)
// Migrate relative source genesis application state and marshal it into
// the respective key.
new, err := v3gov.MigrateJSON(&old)
if err != nil {
return nil, err
}
appState[v3gov.ModuleName] = clientCtx.Codec.MustMarshalJSON(new)
}
// Migrate x/staking.
if appState[stakingv2.ModuleName] != nil {
// unmarshal relative source genesis application state
var old stakingtypes.GenesisState
clientCtx.Codec.MustUnmarshalJSON(appState[stakingv2.ModuleName], &old)
// delete deprecated x/staking genesis state
delete(appState, stakingv2.ModuleName)
// Migrate relative source genesis application state and marshal it into
// the respective key.
new, err := stakingv3.MigrateJSON(old)
if err != nil {
return nil, err
}
appState[stakingv3.ModuleName] = clientCtx.Codec.MustMarshalJSON(&new)
}
return appState, nil
}

View File

@ -1,62 +0,0 @@
package v047
import (
"github.com/cosmos/cosmos-sdk/client"
v1auth "github.com/cosmos/cosmos-sdk/x/auth/migrations/v1"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
bankv4 "github.com/cosmos/cosmos-sdk/x/bank/migrations/v4"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
v1distr "github.com/cosmos/cosmos-sdk/x/distribution/migrations/v1"
v3distr "github.com/cosmos/cosmos-sdk/x/distribution/migrations/v3"
distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
"github.com/cosmos/cosmos-sdk/x/genutil/types"
v4gov "github.com/cosmos/cosmos-sdk/x/gov/migrations/v4"
govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
groupv2 "github.com/cosmos/cosmos-sdk/x/group/migrations/v2"
)
// Migrate migrates exported state from v0.46 to a v0.47 genesis state.
func Migrate(appState types.AppMap, clientCtx client.Context) (types.AppMap, error) {
// Migrate x/bank.
bankState := appState[banktypes.ModuleName]
if len(bankState) > 0 {
var oldBankState banktypes.GenesisState
clientCtx.Codec.MustUnmarshalJSON(bankState, &oldBankState)
newBankState := bankv4.MigrateGenState(&oldBankState)
appState[banktypes.ModuleName] = clientCtx.Codec.MustMarshalJSON(newBankState)
}
if govOldState, ok := appState[v4gov.ModuleName]; ok {
// unmarshal relative source genesis application state
var old govv1.GenesisState
clientCtx.Codec.MustUnmarshalJSON(govOldState, &old)
// delete deprecated x/gov genesis state
delete(appState, v4gov.ModuleName)
// set the x/gov genesis state with new state.
new, err := v4gov.MigrateJSON(&old)
if err != nil {
return nil, err
}
appState[v4gov.ModuleName] = clientCtx.Codec.MustMarshalJSON(new)
}
// Migrate x/auth group policy accounts
if authOldState, ok := appState[v1auth.ModuleName]; ok {
var old authtypes.GenesisState
clientCtx.Codec.MustUnmarshalJSON(authOldState, &old)
newAuthState := groupv2.MigrateGenState(&old)
appState[v1auth.ModuleName] = clientCtx.Codec.MustMarshalJSON(newAuthState)
}
// Migrate x/distribution params (reset unused)
if oldDistState, ok := appState[v1distr.ModuleName]; ok {
var old distrtypes.GenesisState
clientCtx.Codec.MustUnmarshalJSON(oldDistState, &old)
newDistState := v3distr.MigrateJSON(&old)
appState[v1distr.ModuleName] = clientCtx.Codec.MustMarshalJSON(newDistState)
}
return appState, nil
}