Fix migrate legacy params (#1729)
* Fix migrate legacy params * Better tests * Handle upgrade from wasmd 33 chains
This commit is contained in:
40
app/app.go
40
app/app.go
@@ -8,6 +8,7 @@ import (
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
abci "github.com/cometbft/cometbft/abci/types"
|
||||
tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
|
||||
@@ -27,10 +28,12 @@ import (
|
||||
ibcfee "github.com/cosmos/ibc-go/v8/modules/apps/29-fee"
|
||||
ibcfeekeeper "github.com/cosmos/ibc-go/v8/modules/apps/29-fee/keeper"
|
||||
ibcfeetypes "github.com/cosmos/ibc-go/v8/modules/apps/29-fee/types"
|
||||
transfer "github.com/cosmos/ibc-go/v8/modules/apps/transfer"
|
||||
"github.com/cosmos/ibc-go/v8/modules/apps/transfer"
|
||||
ibctransferkeeper "github.com/cosmos/ibc-go/v8/modules/apps/transfer/keeper"
|
||||
ibctransfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types"
|
||||
ibc "github.com/cosmos/ibc-go/v8/modules/core"
|
||||
ibcclienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" //nolint:staticcheck
|
||||
ibcconnectiontypes "github.com/cosmos/ibc-go/v8/modules/core/03-connection/types"
|
||||
porttypes "github.com/cosmos/ibc-go/v8/modules/core/05-port/types"
|
||||
ibcexported "github.com/cosmos/ibc-go/v8/modules/core/exported"
|
||||
ibckeeper "github.com/cosmos/ibc-go/v8/modules/core/keeper"
|
||||
@@ -240,6 +243,7 @@ type WasmApp struct {
|
||||
|
||||
// module configurator
|
||||
configurator module.Configurator
|
||||
once sync.Once
|
||||
}
|
||||
|
||||
// NewWasmApp returns a reference to an initialized WasmApp.
|
||||
@@ -920,6 +924,27 @@ func NewWasmApp(
|
||||
return app
|
||||
}
|
||||
|
||||
func (app *WasmApp) FinalizeBlock(req *abci.RequestFinalizeBlock) (*abci.ResponseFinalizeBlock, error) {
|
||||
// when skipping sdk 47 for sdk 50, the upgrade handler is called too late in BaseApp
|
||||
// this is a hack to ensure that the migration is executed when needed and not panics
|
||||
app.once.Do(func() {
|
||||
ctx := app.NewUncachedContext(false, tmproto.Header{})
|
||||
if _, err := app.ConsensusParamsKeeper.Params(ctx, &consensusparamtypes.QueryParamsRequest{}); err != nil {
|
||||
// prevents panic: consensus key is nil: collections: not found: key 'no_key' of type github.com/cosmos/gogoproto/tendermint.types.ConsensusParams
|
||||
// sdk 47:
|
||||
// Migrate Tendermint consensus parameters from x/params module to a dedicated x/consensus module.
|
||||
// see https://github.com/cosmos/cosmos-sdk/blob/v0.47.0/simapp/upgrades.go#L66
|
||||
baseAppLegacySS := app.GetSubspace(baseapp.Paramspace)
|
||||
err := baseapp.MigrateParams(sdk.UnwrapSDKContext(ctx), baseAppLegacySS, app.ConsensusParamsKeeper.ParamsStore)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return app.BaseApp.FinalizeBlock(req)
|
||||
}
|
||||
|
||||
func (app *WasmApp) setAnteHandler(txConfig client.TxConfig, wasmConfig wasmtypes.WasmConfig, txCounterStoreKey *storetypes.KVStoreKey) {
|
||||
anteHandler, err := NewAnteHandler(
|
||||
HandlerOptions{
|
||||
@@ -1174,10 +1199,15 @@ func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino
|
||||
paramsKeeper.Subspace(slashingtypes.ModuleName)
|
||||
paramsKeeper.Subspace(govtypes.ModuleName)
|
||||
paramsKeeper.Subspace(crisistypes.ModuleName)
|
||||
paramsKeeper.Subspace(ibctransfertypes.ModuleName)
|
||||
paramsKeeper.Subspace(ibcexported.ModuleName)
|
||||
paramsKeeper.Subspace(icahosttypes.SubModuleName)
|
||||
paramsKeeper.Subspace(icacontrollertypes.SubModuleName)
|
||||
|
||||
// register the IBC key tables for legacy param subspaces
|
||||
keyTable := ibcclienttypes.ParamKeyTable()
|
||||
keyTable.RegisterParamSet(&ibcconnectiontypes.Params{})
|
||||
paramsKeeper.Subspace(ibcexported.ModuleName).WithKeyTable(keyTable)
|
||||
paramsKeeper.Subspace(ibctransfertypes.ModuleName).WithKeyTable(ibctransfertypes.ParamKeyTable())
|
||||
paramsKeeper.Subspace(icacontrollertypes.SubModuleName).WithKeyTable(icacontrollertypes.ParamKeyTable())
|
||||
paramsKeeper.Subspace(icahosttypes.SubModuleName).WithKeyTable(icahosttypes.ParamKeyTable())
|
||||
|
||||
paramsKeeper.Subspace(wasmtypes.ModuleName)
|
||||
return paramsKeeper
|
||||
}
|
||||
|
||||
@@ -3,35 +3,49 @@ package app
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
icacontrollertypes "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/controller/types"
|
||||
icahosttypes "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/host/types"
|
||||
ibctransfertypes "github.com/cosmos/ibc-go/v8/modules/apps/transfer/types"
|
||||
ibcclienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" //nolint:staticcheck
|
||||
ibcconnectiontypes "github.com/cosmos/ibc-go/v8/modules/core/03-connection/types"
|
||||
ibcexported "github.com/cosmos/ibc-go/v8/modules/core/exported"
|
||||
|
||||
upgradetypes "cosmossdk.io/x/upgrade/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types"
|
||||
distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
|
||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
|
||||
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
|
||||
paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper"
|
||||
paramstypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
|
||||
"github.com/CosmWasm/wasmd/app/upgrades"
|
||||
"github.com/CosmWasm/wasmd/app/upgrades/noop"
|
||||
v050 "github.com/CosmWasm/wasmd/app/upgrades/v050"
|
||||
v2 "github.com/CosmWasm/wasmd/x/wasm/migrations/v2"
|
||||
wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types"
|
||||
)
|
||||
|
||||
// Upgrades list of chain upgrades
|
||||
var Upgrades = []upgrades.Upgrade{v050.Upgrade}
|
||||
|
||||
// RegisterUpgradeHandlers registers the chain upgrade handlers
|
||||
func (app WasmApp) RegisterUpgradeHandlers() {
|
||||
setupLegacyKeyTables(app.ParamsKeeper)
|
||||
func (app *WasmApp) RegisterUpgradeHandlers() {
|
||||
setupLegacyKeyTables(&app.ParamsKeeper)
|
||||
if len(Upgrades) == 0 {
|
||||
// always have a unique upgrade registered for the current version to test in system tests
|
||||
Upgrades = append(Upgrades, noop.NewUpgrade(app.Version()))
|
||||
}
|
||||
|
||||
keepers := upgrades.AppKeepers{AccountKeeper: app.AccountKeeper}
|
||||
keepers := upgrades.AppKeepers{
|
||||
AccountKeeper: &app.AccountKeeper,
|
||||
ParamsKeeper: &app.ParamsKeeper,
|
||||
ConsensusParamsKeeper: &app.ConsensusParamsKeeper,
|
||||
CapabilityKeeper: app.CapabilityKeeper,
|
||||
IBCKeeper: app.IBCKeeper,
|
||||
Codec: app.appCodec,
|
||||
GetStoreKey: app.GetKey,
|
||||
}
|
||||
app.GetStoreKeys()
|
||||
// register all upgrade handlers
|
||||
for _, upgrade := range Upgrades {
|
||||
app.UpgradeKeeper.SetUpgradeHandler(
|
||||
@@ -62,23 +76,31 @@ func (app WasmApp) RegisterUpgradeHandlers() {
|
||||
}
|
||||
}
|
||||
|
||||
func setupLegacyKeyTables(k paramskeeper.Keeper) {
|
||||
// Set param key table for params module migration
|
||||
func setupLegacyKeyTables(k *paramskeeper.Keeper) {
|
||||
for _, subspace := range k.GetSubspaces() {
|
||||
subspace := subspace
|
||||
|
||||
var keyTable paramstypes.KeyTable
|
||||
switch subspace.Name() {
|
||||
// ibc types
|
||||
case ibcexported.ModuleName:
|
||||
keyTable = ibcclienttypes.ParamKeyTable()
|
||||
keyTable.RegisterParamSet(&ibcconnectiontypes.Params{})
|
||||
case ibctransfertypes.ModuleName:
|
||||
keyTable = ibctransfertypes.ParamKeyTable()
|
||||
case icahosttypes.SubModuleName:
|
||||
keyTable = icahosttypes.ParamKeyTable()
|
||||
case icacontrollertypes.SubModuleName:
|
||||
keyTable = icacontrollertypes.ParamKeyTable()
|
||||
case authtypes.ModuleName:
|
||||
keyTable = authtypes.ParamKeyTable() //nolint:staticcheck
|
||||
case banktypes.ModuleName:
|
||||
keyTable = banktypes.ParamKeyTable() //nolint:staticcheck
|
||||
case stakingtypes.ModuleName:
|
||||
keyTable = stakingtypes.ParamKeyTable() //nolint:staticcheck
|
||||
case minttypes.ModuleName:
|
||||
keyTable = minttypes.ParamKeyTable() //nolint:staticcheck
|
||||
case distrtypes.ModuleName:
|
||||
keyTable = distrtypes.ParamKeyTable() //nolint:staticcheck
|
||||
case slashingtypes.ModuleName:
|
||||
keyTable = slashingtypes.ParamKeyTable() //nolint:staticcheck
|
||||
case govtypes.ModuleName:
|
||||
keyTable = govv1.ParamKeyTable() //nolint:staticcheck
|
||||
case crisistypes.ModuleName:
|
||||
keyTable = crisistypes.ParamKeyTable() //nolint:staticcheck
|
||||
// wasm
|
||||
case wasmtypes.ModuleName:
|
||||
keyTable = v2.ParamKeyTable() //nolint:staticcheck
|
||||
default:
|
||||
continue
|
||||
}
|
||||
@@ -87,4 +109,7 @@ func setupLegacyKeyTables(k paramskeeper.Keeper) {
|
||||
subspace.WithKeyTable(keyTable)
|
||||
}
|
||||
}
|
||||
// sdk 47
|
||||
k.Subspace(baseapp.Paramspace).
|
||||
WithKeyTable(paramstypes.ConsensusParamsKeyTable())
|
||||
}
|
||||
|
||||
@@ -3,15 +3,27 @@ package upgrades
|
||||
import (
|
||||
"context"
|
||||
|
||||
capabilitykeeper "github.com/cosmos/ibc-go/modules/capability/keeper"
|
||||
ibckeeper "github.com/cosmos/ibc-go/v8/modules/core/keeper"
|
||||
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
upgradetypes "cosmossdk.io/x/upgrade/types"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
consensusparamkeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper"
|
||||
paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper"
|
||||
)
|
||||
|
||||
type AppKeepers struct {
|
||||
authkeeper.AccountKeeper
|
||||
AccountKeeper *authkeeper.AccountKeeper
|
||||
ParamsKeeper *paramskeeper.Keeper
|
||||
ConsensusParamsKeeper *consensusparamkeeper.Keeper
|
||||
Codec codec.Codec
|
||||
GetStoreKey func(storeKey string) *storetypes.KVStoreKey
|
||||
CapabilityKeeper *capabilitykeeper.Keeper
|
||||
IBCKeeper *ibckeeper.Keeper
|
||||
}
|
||||
type ModuleManager interface {
|
||||
RunMigrations(ctx context.Context, cfg module.Configurator, fromVM module.VersionMap) (module.VersionMap, error)
|
||||
|
||||
@@ -31,6 +31,7 @@ func CreateUpgradeHandler(
|
||||
configurator module.Configurator,
|
||||
ak *upgrades.AppKeepers,
|
||||
) upgradetypes.UpgradeHandler {
|
||||
// sdk 47 to sdk 50
|
||||
return func(ctx context.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
|
||||
return mm.RunMigrations(ctx, configurator, fromVM)
|
||||
}
|
||||
|
||||
73
app/upgrades/v050/upgrades.go_wasmd_33_example.txt
Normal file
73
app/upgrades/v050/upgrades.go_wasmd_33_example.txt
Normal file
@@ -0,0 +1,73 @@
|
||||
package v050
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
capabilitytypes "github.com/cosmos/ibc-go/modules/capability/types"
|
||||
v6 "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/controller/migrations/v6"
|
||||
icacontrollertypes "github.com/cosmos/ibc-go/v8/modules/apps/27-interchain-accounts/controller/types"
|
||||
ibctmmigrations "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint/migrations"
|
||||
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
circuittypes "cosmossdk.io/x/circuit/types"
|
||||
"cosmossdk.io/x/nft"
|
||||
upgradetypes "cosmossdk.io/x/upgrade/types"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
consensusparamtypes "github.com/cosmos/cosmos-sdk/x/consensus/types"
|
||||
crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/group"
|
||||
|
||||
"github.com/CosmWasm/wasmd/app/upgrades"
|
||||
)
|
||||
|
||||
// UpgradeName defines the on-chain upgrade name
|
||||
const UpgradeName = "v0.50"
|
||||
|
||||
var Upgrade = upgrades.Upgrade{
|
||||
UpgradeName: UpgradeName,
|
||||
CreateUpgradeHandler: CreateUpgradeHandler,
|
||||
StoreUpgrades: storetypes.StoreUpgrades{
|
||||
Added: []string{
|
||||
// SDK 46
|
||||
group.ModuleName,
|
||||
nft.ModuleName,
|
||||
// SDK 47
|
||||
crisistypes.ModuleName,
|
||||
consensusparamtypes.ModuleName,
|
||||
// SDK 50
|
||||
circuittypes.ModuleName,
|
||||
},
|
||||
Deleted: []string{},
|
||||
},
|
||||
}
|
||||
|
||||
func CreateUpgradeHandler(
|
||||
mm upgrades.ModuleManager,
|
||||
configurator module.Configurator,
|
||||
ak *upgrades.AppKeepers,
|
||||
) upgradetypes.UpgradeHandler {
|
||||
return func(ctx context.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
|
||||
sdkCtx := sdk.UnwrapSDKContext(ctx)
|
||||
// ibc v6
|
||||
// NOTE: The moduleName arg of v6.CreateUpgradeHandler refers to the auth module ScopedKeeper name to which the channel capability should be migrated from.
|
||||
// This should be the same string value provided upon instantiation of the ScopedKeeper with app.CapabilityKeeper.ScopeToModule()
|
||||
const moduleName = icacontrollertypes.SubModuleName
|
||||
if err := v6.MigrateICS27ChannelCapability(sdkCtx, ak.Codec, ak.GetStoreKey(capabilitytypes.ModuleName),
|
||||
ak.CapabilityKeeper, moduleName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// ibc v7
|
||||
if _, err := ibctmmigrations.PruneExpiredConsensusStates(sdkCtx, ak.Codec, ak.IBCKeeper.ClientKeeper); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// sdk 47
|
||||
// consensus params migration is done in app.go FinalizeBlock function to prevent panic
|
||||
|
||||
// sdk 50
|
||||
return mm.RunMigrations(ctx, configurator, fromVM)
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ func NewRootCmd() *cobra.Command {
|
||||
cfg.Seal()
|
||||
// we "pre"-instantiate the application for getting the injected/configured encoding configuration
|
||||
// note, this is not necessary when using app wiring, as depinject can be directly used (see root_v2.go)
|
||||
tempApp := app.NewWasmApp(log.NewNopLogger(), dbm.NewMemDB(), nil, true, simtestutil.NewAppOptionsWithFlagHome(tempDir()), []wasmkeeper.Option{})
|
||||
tempApp := app.NewWasmApp(log.NewNopLogger(), dbm.NewMemDB(), nil, false, simtestutil.NewAppOptionsWithFlagHome(tempDir()), []wasmkeeper.Option{})
|
||||
encodingConfig := params.EncodingConfig{
|
||||
InterfaceRegistry: tempApp.InterfaceRegistry(),
|
||||
Codec: tempApp.AppCodec(),
|
||||
|
||||
@@ -3,20 +3,24 @@ package keeper_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/cometbft/cometbft/libs/rand"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
upgradetypes "cosmossdk.io/x/upgrade/types"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/address"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
|
||||
"github.com/CosmWasm/wasmd/app"
|
||||
v2 "github.com/CosmWasm/wasmd/x/wasm/migrations/v2"
|
||||
"github.com/CosmWasm/wasmd/x/wasm/types"
|
||||
)
|
||||
|
||||
func TestModuleMigrations(t *testing.T) {
|
||||
wasmApp := app.Setup(t)
|
||||
myAddress := sdk.AccAddress(rand.Bytes(address.Len))
|
||||
|
||||
upgradeHandler := func(ctx sdk.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { //nolint:unparam
|
||||
return wasmApp.ModuleManager.RunMigrations(ctx, wasmApp.Configurator(), fromVM)
|
||||
@@ -30,15 +34,15 @@ func TestModuleMigrations(t *testing.T) {
|
||||
"with legacy params migrated": {
|
||||
startVersion: 1,
|
||||
setup: func(ctx sdk.Context) {
|
||||
params := types.Params{
|
||||
CodeUploadAccess: types.AllowNobody,
|
||||
InstantiateDefaultPermission: types.AccessTypeNobody,
|
||||
params := v2.Params{
|
||||
CodeUploadAccess: v2.AccessConfig{Permission: v2.AccessTypeNobody},
|
||||
InstantiateDefaultPermission: v2.AccessTypeNobody,
|
||||
}
|
||||
|
||||
// upgrade code shipped with v0.40
|
||||
// https://github.com/CosmWasm/wasmd/blob/v0.40.0/app/upgrades.go#L66
|
||||
sp, _ := wasmApp.ParamsKeeper.GetSubspace(types.ModuleName)
|
||||
keyTable := types.ParamKeyTable()
|
||||
keyTable := v2.ParamKeyTable()
|
||||
if !sp.HasKeyTable() {
|
||||
sp.WithKeyTable(keyTable)
|
||||
}
|
||||
@@ -50,6 +54,29 @@ func TestModuleMigrations(t *testing.T) {
|
||||
InstantiateDefaultPermission: types.AccessTypeNobody,
|
||||
},
|
||||
},
|
||||
"with legacy one address type replaced": {
|
||||
startVersion: 1,
|
||||
setup: func(ctx sdk.Context) {
|
||||
params := v2.Params{
|
||||
CodeUploadAccess: v2.AccessConfig{Permission: v2.AccessTypeOnlyAddress, Address: myAddress.String()},
|
||||
InstantiateDefaultPermission: v2.AccessTypeNobody,
|
||||
}
|
||||
|
||||
// upgrade code shipped with v0.40
|
||||
// https://github.com/CosmWasm/wasmd/blob/v0.40.0/app/upgrades.go#L66
|
||||
sp, _ := wasmApp.ParamsKeeper.GetSubspace(types.ModuleName)
|
||||
keyTable := v2.ParamKeyTable()
|
||||
if !sp.HasKeyTable() {
|
||||
sp.WithKeyTable(keyTable)
|
||||
}
|
||||
|
||||
sp.SetParamSet(ctx, ¶ms)
|
||||
},
|
||||
exp: types.Params{
|
||||
CodeUploadAccess: types.AccessTypeAnyOfAddresses.With(myAddress),
|
||||
InstantiateDefaultPermission: types.AccessTypeNobody,
|
||||
},
|
||||
},
|
||||
"fresh from genesis": {
|
||||
startVersion: wasmApp.ModuleManager.GetVersionMap()[types.ModuleName], // latest
|
||||
setup: func(ctx sdk.Context) {},
|
||||
|
||||
1219
x/wasm/migrations/v2/legacy_types.go
Normal file
1219
x/wasm/migrations/v2/legacy_types.go
Normal file
File diff suppressed because it is too large
Load Diff
142
x/wasm/migrations/v2/params_legacy.go
Normal file
142
x/wasm/migrations/v2/params_legacy.go
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
NOTE: Usage of x/params to manage parameters is deprecated in favor of x/gov
|
||||
controlled execution of MsgUpdateParams messages. These types remains solely
|
||||
for migration purposes and will be removed in a future release.
|
||||
*/
|
||||
package v2
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/gogoproto/jsonpb"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||
|
||||
"github.com/CosmWasm/wasmd/x/wasm/types"
|
||||
)
|
||||
|
||||
var (
|
||||
ParamStoreKeyUploadAccess = []byte("uploadAccess")
|
||||
ParamStoreKeyInstantiateAccess = []byte("instantiateAccess")
|
||||
)
|
||||
|
||||
// Deprecated: Type declaration for parameters
|
||||
func ParamKeyTable() paramtypes.KeyTable {
|
||||
return paramtypes.NewKeyTable().RegisterParamSet(&Params{})
|
||||
}
|
||||
|
||||
// ParamSetPairs returns the parameter set pairs.
|
||||
func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs {
|
||||
return paramtypes.ParamSetPairs{
|
||||
paramtypes.NewParamSetPair(ParamStoreKeyUploadAccess, &p.CodeUploadAccess, validateAccessConfig),
|
||||
paramtypes.NewParamSetPair(ParamStoreKeyInstantiateAccess, &p.InstantiateDefaultPermission, validateAccessType),
|
||||
}
|
||||
}
|
||||
|
||||
func validateAccessConfig(i interface{}) error {
|
||||
v, ok := i.(AccessConfig)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid parameter type: %T", i)
|
||||
}
|
||||
return v.ValidateBasic()
|
||||
}
|
||||
|
||||
var AllAccessTypes = []AccessType{
|
||||
AccessTypeNobody,
|
||||
AccessTypeOnlyAddress,
|
||||
AccessTypeAnyOfAddresses,
|
||||
AccessTypeEverybody,
|
||||
}
|
||||
|
||||
func validateAccessType(i interface{}) error {
|
||||
a, ok := i.(AccessType)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid parameter type: %T", i)
|
||||
}
|
||||
if a == AccessTypeUnspecified {
|
||||
return errorsmod.Wrap(types.ErrEmpty, "type")
|
||||
}
|
||||
for _, v := range AllAccessTypes {
|
||||
if v == a {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return errorsmod.Wrapf(types.ErrInvalid, "unknown type: %q", a)
|
||||
}
|
||||
|
||||
func (a AccessConfig) ValidateBasic() error {
|
||||
switch a.Permission {
|
||||
case AccessTypeUnspecified:
|
||||
return errorsmod.Wrap(types.ErrEmpty, "type")
|
||||
case AccessTypeNobody, AccessTypeEverybody:
|
||||
return nil
|
||||
case AccessTypeOnlyAddress:
|
||||
_, err := sdk.AccAddressFromBech32(a.Address)
|
||||
return errorsmod.Wrap(err, "only address")
|
||||
case AccessTypeAnyOfAddresses:
|
||||
return errorsmod.Wrap(assertValidAddresses(a.Addresses), "addresses")
|
||||
}
|
||||
return errorsmod.Wrapf(types.ErrInvalid, "unknown type: %q", a.Permission)
|
||||
}
|
||||
|
||||
func assertValidAddresses(addrs []string) error {
|
||||
if len(addrs) == 0 {
|
||||
return types.ErrEmpty
|
||||
}
|
||||
idx := make(map[string]struct{}, len(addrs))
|
||||
for _, a := range addrs {
|
||||
if _, err := sdk.AccAddressFromBech32(a); err != nil {
|
||||
return errorsmod.Wrapf(err, "address: %s", a)
|
||||
}
|
||||
if _, exists := idx[a]; exists {
|
||||
return types.ErrDuplicate.Wrapf("address: %s", a)
|
||||
}
|
||||
idx[a] = struct{}{}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a AccessType) String() string {
|
||||
switch a {
|
||||
case AccessTypeNobody:
|
||||
return "Nobody"
|
||||
case AccessTypeOnlyAddress:
|
||||
return "OnlyAddress"
|
||||
case AccessTypeEverybody:
|
||||
return "Everybody"
|
||||
case AccessTypeAnyOfAddresses:
|
||||
return "AnyOfAddresses"
|
||||
}
|
||||
return "Unspecified"
|
||||
}
|
||||
|
||||
func (a *AccessType) UnmarshalText(text []byte) error {
|
||||
for _, v := range AllAccessTypes {
|
||||
if v.String() == string(text) {
|
||||
*a = v
|
||||
return nil
|
||||
}
|
||||
}
|
||||
*a = AccessTypeUnspecified
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a AccessType) MarshalText() ([]byte, error) {
|
||||
return []byte(a.String()), nil
|
||||
}
|
||||
|
||||
func (a *AccessType) MarshalJSONPB(_ *jsonpb.Marshaler) ([]byte, error) {
|
||||
return json.Marshal(a)
|
||||
}
|
||||
|
||||
func (a *AccessType) UnmarshalJSONPB(_ *jsonpb.Unmarshaler, data []byte) error {
|
||||
return json.Unmarshal(data, a)
|
||||
}
|
||||
|
||||
func (a AccessConfig) Equals(o AccessConfig) bool {
|
||||
return a.Permission == o.Permission && a.Address == o.Address
|
||||
}
|
||||
89
x/wasm/migrations/v2/params_legacy_test.go
Normal file
89
x/wasm/migrations/v2/params_legacy_test.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
)
|
||||
|
||||
func TestAccessTypeMarshalJson(t *testing.T) {
|
||||
specs := map[string]struct {
|
||||
src AccessType
|
||||
exp string
|
||||
}{
|
||||
"Unspecified": {src: AccessTypeUnspecified, exp: `"Unspecified"`},
|
||||
"Nobody": {src: AccessTypeNobody, exp: `"Nobody"`},
|
||||
"OnlyAddress": {src: AccessTypeOnlyAddress, exp: `"OnlyAddress"`},
|
||||
"AccessTypeAnyOfAddresses": {src: AccessTypeAnyOfAddresses, exp: `"AnyOfAddresses"`},
|
||||
"Everybody": {src: AccessTypeEverybody, exp: `"Everybody"`},
|
||||
"unknown": {src: 999, exp: `"Unspecified"`},
|
||||
}
|
||||
for msg, spec := range specs {
|
||||
t.Run(msg, func(t *testing.T) {
|
||||
got, err := json.Marshal(spec.src)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, []byte(spec.exp), got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAccessTypeUnmarshalJson(t *testing.T) {
|
||||
specs := map[string]struct {
|
||||
src string
|
||||
exp AccessType
|
||||
}{
|
||||
"Unspecified": {src: `"Unspecified"`, exp: AccessTypeUnspecified},
|
||||
"Nobody": {src: `"Nobody"`, exp: AccessTypeNobody},
|
||||
"OnlyAddress": {src: `"OnlyAddress"`, exp: AccessTypeOnlyAddress},
|
||||
"AnyOfAddresses": {src: `"AnyOfAddresses"`, exp: AccessTypeAnyOfAddresses},
|
||||
"Everybody": {src: `"Everybody"`, exp: AccessTypeEverybody},
|
||||
"unknown": {src: `""`, exp: AccessTypeUnspecified},
|
||||
}
|
||||
for msg, spec := range specs {
|
||||
t.Run(msg, func(t *testing.T) {
|
||||
var got AccessType
|
||||
err := json.Unmarshal([]byte(spec.src), &got)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, spec.exp, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParamsUnmarshalJson(t *testing.T) {
|
||||
specs := map[string]struct {
|
||||
src string
|
||||
exp Params
|
||||
}{
|
||||
"defaults": {
|
||||
src: `{"code_upload_access": {"permission": "Everybody"},
|
||||
"instantiate_default_permission": "Everybody"}`,
|
||||
exp: Params{
|
||||
CodeUploadAccess: AccessConfig{Permission: AccessTypeEverybody},
|
||||
InstantiateDefaultPermission: AccessTypeEverybody,
|
||||
},
|
||||
},
|
||||
"legacy type": {
|
||||
src: `{"code_upload_access": {"permission": "OnlyAddress", "address": "wasm1lq3q55r9sqwqyrfmlp6xy8ufhayt96lmcttthz", "addresses": [] },
|
||||
"instantiate_default_permission": "Nobody"}`,
|
||||
exp: Params{
|
||||
CodeUploadAccess: AccessConfig{
|
||||
Permission: AccessTypeOnlyAddress, Address: "wasm1lq3q55r9sqwqyrfmlp6xy8ufhayt96lmcttthz", Addresses: nil,
|
||||
},
|
||||
InstantiateDefaultPermission: AccessTypeNobody,
|
||||
},
|
||||
},
|
||||
}
|
||||
for msg, spec := range specs {
|
||||
t.Run(msg, func(t *testing.T) {
|
||||
var val Params
|
||||
marshaler := codec.NewLegacyAmino()
|
||||
err := marshaler.UnmarshalJSON([]byte(spec.src), &val)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, spec.exp, val)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -16,13 +16,8 @@ import (
|
||||
// module state.
|
||||
func MigrateStore(ctx sdk.Context, storeService corestoretypes.KVStoreService, legacySubspace exported.Subspace, cdc codec.BinaryCodec) error {
|
||||
store := storeService.OpenKVStore(ctx)
|
||||
var currParams types.Params
|
||||
var currParams Params
|
||||
legacySubspace.GetParamSet(ctx, &currParams)
|
||||
|
||||
if err := currParams.ValidateBasic(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bz, err := cdc.Marshal(&currParams)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -3,6 +3,8 @@ package v2_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/cometbft/cometbft/libs/rand"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
@@ -10,38 +12,90 @@ import (
|
||||
"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"
|
||||
paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper"
|
||||
paramstypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||
|
||||
"github.com/CosmWasm/wasmd/x/wasm"
|
||||
"github.com/CosmWasm/wasmd/x/wasm/exported"
|
||||
v2 "github.com/CosmWasm/wasmd/x/wasm/migrations/v2"
|
||||
"github.com/CosmWasm/wasmd/x/wasm/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) {
|
||||
cdc := moduletestutil.MakeTestEncodingConfig(wasm.AppModuleBasic{}).Codec
|
||||
storeKey := storetypes.NewKVStoreKey(types.StoreKey)
|
||||
tKey := storetypes.NewTransientStoreKey("transient_test")
|
||||
ctx := testutil.DefaultContext(storeKey, tKey)
|
||||
store := ctx.KVStore(storeKey)
|
||||
cfg := moduletestutil.MakeTestEncodingConfig(wasm.AppModuleBasic{})
|
||||
cdc := cfg.Codec
|
||||
var (
|
||||
wasmStoreKey = storetypes.NewKVStoreKey(types.StoreKey)
|
||||
paramsStoreKey = storetypes.NewKVStoreKey(paramstypes.StoreKey)
|
||||
paramsTStoreKey = storetypes.NewTransientStoreKey(paramstypes.TStoreKey)
|
||||
myAddress = sdk.AccAddress(rand.Bytes(address.Len))
|
||||
)
|
||||
specs := map[string]struct {
|
||||
src v2.Params
|
||||
}{
|
||||
"one address": {
|
||||
src: v2.Params{
|
||||
CodeUploadAccess: v2.AccessConfig{
|
||||
Permission: v2.AccessTypeOnlyAddress,
|
||||
Address: myAddress.String(),
|
||||
},
|
||||
InstantiateDefaultPermission: v2.AccessTypeNobody,
|
||||
},
|
||||
},
|
||||
"multiple addresses": {
|
||||
src: v2.Params{
|
||||
CodeUploadAccess: v2.AccessConfig{
|
||||
Permission: v2.AccessTypeAnyOfAddresses,
|
||||
Addresses: []string{myAddress.String(), sdk.AccAddress(rand.Bytes(address.Len)).String()},
|
||||
},
|
||||
InstantiateDefaultPermission: v2.AccessTypeEverybody,
|
||||
},
|
||||
},
|
||||
"everybody": {
|
||||
src: v2.Params{
|
||||
CodeUploadAccess: v2.AccessConfig{
|
||||
Permission: v2.AccessTypeEverybody,
|
||||
},
|
||||
InstantiateDefaultPermission: v2.AccessTypeEverybody,
|
||||
},
|
||||
},
|
||||
"nobody": {
|
||||
src: v2.Params{
|
||||
CodeUploadAccess: v2.AccessConfig{
|
||||
Permission: v2.AccessTypeNobody,
|
||||
},
|
||||
InstantiateDefaultPermission: v2.AccessTypeNobody,
|
||||
},
|
||||
},
|
||||
}
|
||||
for name, spec := range specs {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
paramsKeeper := paramskeeper.NewKeeper(cdc, cfg.Amino, paramsStoreKey, paramsTStoreKey)
|
||||
ctx := testutil.DefaultContextWithKeys(
|
||||
map[string]*storetypes.KVStoreKey{
|
||||
paramstypes.StoreKey: paramsStoreKey,
|
||||
types.StoreKey: wasmStoreKey,
|
||||
},
|
||||
map[string]*storetypes.TransientStoreKey{
|
||||
paramstypes.TStoreKey: paramsTStoreKey,
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
legacySubspace := newMockSubspace(types.DefaultParams())
|
||||
require.NoError(t, v2.MigrateStore(ctx, runtime.NewKVStoreService(storeKey), legacySubspace, cdc))
|
||||
// register legacy parameters
|
||||
params := spec.src
|
||||
subspace := paramsKeeper.Subspace(types.ModuleName)
|
||||
subspace.WithKeyTable(v2.ParamKeyTable())
|
||||
subspace.SetParamSet(ctx, ¶ms)
|
||||
|
||||
var res types.Params
|
||||
bz := store.Get(types.ParamsKey)
|
||||
// when
|
||||
require.NoError(t, v2.MigrateStore(ctx, runtime.NewKVStoreService(wasmStoreKey), subspace, cdc))
|
||||
|
||||
var res v2.Params
|
||||
bz := ctx.KVStore(wasmStoreKey).Get(types.ParamsKey)
|
||||
require.NoError(t, cdc.Unmarshal(bz, &res))
|
||||
require.Equal(t, legacySubspace.ps, res)
|
||||
assert.Equal(t, params, res)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,19 +27,20 @@ import (
|
||||
"github.com/CosmWasm/wasmd/x/wasm/exported"
|
||||
"github.com/CosmWasm/wasmd/x/wasm/keeper"
|
||||
"github.com/CosmWasm/wasmd/x/wasm/keeper/testdata"
|
||||
v2 "github.com/CosmWasm/wasmd/x/wasm/migrations/v2"
|
||||
"github.com/CosmWasm/wasmd/x/wasm/types"
|
||||
)
|
||||
|
||||
type mockSubspace struct {
|
||||
ps types.Params
|
||||
ps v2.Params
|
||||
}
|
||||
|
||||
func newMockSubspace(ps types.Params) mockSubspace {
|
||||
func newMockSubspace(ps v2.Params) mockSubspace {
|
||||
return mockSubspace{ps: ps}
|
||||
}
|
||||
|
||||
func (ms mockSubspace) GetParamSet(ctx sdk.Context, ps exported.ParamSet) {
|
||||
*ps.(*types.Params) = ms.ps
|
||||
*ps.(*v2.Params) = ms.ps
|
||||
}
|
||||
|
||||
type testData struct {
|
||||
@@ -57,6 +58,11 @@ type testData struct {
|
||||
|
||||
func setupTest(t *testing.T) testData {
|
||||
t.Helper()
|
||||
DefaultParams := v2.Params{
|
||||
CodeUploadAccess: v2.AccessConfig{Permission: v2.AccessTypeEverybody},
|
||||
InstantiateDefaultPermission: v2.AccessTypeEverybody,
|
||||
}
|
||||
|
||||
ctx, keepers := keeper.CreateTestInput(t, false, "iterator,staking,stargate,cosmwasm_1_1,cosmwasm_1_2,cosmwasm_1_3,cosmwasm_1_4")
|
||||
encConf := keeper.MakeEncodingConfig(t)
|
||||
queryRouter := baseapp.NewGRPCQueryRouter()
|
||||
@@ -64,7 +70,7 @@ func setupTest(t *testing.T) testData {
|
||||
queryRouter.SetInterfaceRegistry(encConf.InterfaceRegistry)
|
||||
serviceRouter.SetInterfaceRegistry(encConf.InterfaceRegistry)
|
||||
data := testData{
|
||||
module: NewAppModule(encConf.Codec, keepers.WasmKeeper, keepers.StakingKeeper, keepers.AccountKeeper, keepers.BankKeeper, nil, newMockSubspace(types.DefaultParams())),
|
||||
module: NewAppModule(encConf.Codec, keepers.WasmKeeper, keepers.StakingKeeper, keepers.AccountKeeper, keepers.BankKeeper, nil, newMockSubspace(DefaultParams)),
|
||||
ctx: ctx,
|
||||
acctKeeper: keepers.AccountKeeper,
|
||||
keeper: *keepers.WasmKeeper,
|
||||
|
||||
@@ -2,7 +2,6 @@ package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/gogoproto/jsonpb"
|
||||
"github.com/pkg/errors"
|
||||
@@ -104,25 +103,13 @@ func (p Params) ValidateBasic() error {
|
||||
if err := validateAccessType(p.InstantiateDefaultPermission); err != nil {
|
||||
return errors.Wrap(err, "instantiate default permission")
|
||||
}
|
||||
if err := validateAccessConfig(p.CodeUploadAccess); err != nil {
|
||||
if err := p.CodeUploadAccess.ValidateBasic(); err != nil {
|
||||
return errors.Wrap(err, "upload access")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateAccessConfig(i interface{}) error {
|
||||
v, ok := i.(AccessConfig)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid parameter type: %T", i)
|
||||
}
|
||||
return v.ValidateBasic()
|
||||
}
|
||||
|
||||
func validateAccessType(i interface{}) error {
|
||||
a, ok := i.(AccessType)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid parameter type: %T", i)
|
||||
}
|
||||
func validateAccessType(a AccessType) error {
|
||||
if a == AccessTypeUnspecified {
|
||||
return errorsmod.Wrap(ErrEmpty, "type")
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
NOTE: Usage of x/params to manage parameters is deprecated in favor of x/gov
|
||||
controlled execution of MsgUpdateParams messages. These types remains solely
|
||||
for migration purposes and will be removed in a future release.
|
||||
*/
|
||||
package types
|
||||
|
||||
import paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||
|
||||
var (
|
||||
ParamStoreKeyUploadAccess = []byte("uploadAccess")
|
||||
ParamStoreKeyInstantiateAccess = []byte("instantiateAccess")
|
||||
)
|
||||
|
||||
// Deprecated: Type declaration for parameters
|
||||
func ParamKeyTable() paramtypes.KeyTable {
|
||||
return paramtypes.NewKeyTable().RegisterParamSet(&Params{})
|
||||
}
|
||||
|
||||
// ParamSetPairs returns the parameter set pairs.
|
||||
func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs {
|
||||
return paramtypes.ParamSetPairs{
|
||||
paramtypes.NewParamSetPair(ParamStoreKeyUploadAccess, &p.CodeUploadAccess, validateAccessConfig),
|
||||
paramtypes.NewParamSetPair(ParamStoreKeyInstantiateAccess, &p.InstantiateDefaultPermission, validateAccessType),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user