chore!: remove bank & genutil legacy migrations (#17818)
This commit is contained in:
parent
825e09ab77
commit
5987d0003a
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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`)
|
||||
|
||||
@ -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)
|
||||
|
||||
4
docs/build/building-modules/00-intro.md
vendored
4
docs/build/building-modules/00-intro.md
vendored
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
10
docs/build/building-modules/14-simulator.md
vendored
10
docs/build/building-modules/14-simulator.md
vendored
@ -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
|
||||
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)),
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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())
|
||||
|
||||
|
||||
@ -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{
|
||||
|
||||
@ -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{
|
||||
|
||||
@ -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)
|
||||
}
|
||||
)
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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{},
|
||||
)
|
||||
}
|
||||
@ -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,
|
||||
}
|
||||
}
|
||||
@ -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))
|
||||
}
|
||||
@ -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...)
|
||||
}
|
||||
@ -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...)
|
||||
}
|
||||
@ -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.
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
@ -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)...)
|
||||
}
|
||||
@ -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())
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
@ -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)
|
||||
})
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
@ -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}
|
||||
}
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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) {},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user