Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(x/ecocredit): add basket state migration #1397

Merged
merged 10 commits into from
Aug 25, 2022
9 changes: 9 additions & 0 deletions app/stable_appconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,21 @@ import (
"github.com/cosmos/cosmos-sdk/x/auth/ante"
"github.com/cosmos/cosmos-sdk/x/group"
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"

"github.com/regen-network/regen-ledger/x/data"
"github.com/regen-network/regen-ledger/x/ecocredit"
)

func (app *RegenApp) registerUpgradeHandlers() {
upgradeName := "v5.0"
app.UpgradeKeeper.SetUpgradeHandler(upgradeName,
func(ctx sdk.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {

// set regen module consensus version
fromVM[ecocredit.ModuleName] = 2
fromVM[data.ModuleName] = 1
app.UpgradeKeeper.SetModuleVersionMap(ctx, fromVM)

// transfer module consensus version has been bumped to 2
return app.mm.RunMigrations(ctx, app.configurator, fromVM)
})
Expand Down
40 changes: 40 additions & 0 deletions x/ecocredit/migrations/v3/state.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package v3

import (
basev1beta1 "github.com/cosmos/cosmos-sdk/api/cosmos/base/v1beta1"
sdk "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"

basketapi "github.com/regen-network/regen-ledger/api/regen/ecocredit/basket/v1"
api "github.com/regen-network/regen-ledger/api/regen/ecocredit/v1"
"github.com/regen-network/regen-ledger/x/ecocredit/core"
)

// MigrateState performs in-place store migrations from ConsensusVersion 2 to 3.
func MigrateState(sdkCtx sdk.Context, ss api.StateStore, basketStore basketapi.StateStore, subspace paramtypes.Subspace) error {
// TODO: migrate core params

// migrate basket params
var params core.Params
subspace.GetParamSet(sdkCtx, &params)

// verify basket fee is valid
if err := params.BasketFee.Validate(); err != nil {
return err
}

basketFees := []*basev1beta1.Coin{}
for _, coin := range params.BasketFee {
basketFees = append(basketFees, &basev1beta1.Coin{
Denom: coin.Denom,
Amount: coin.Amount.String(),
})
}
if err := basketStore.BasketFeesTable().Save(sdkCtx, &basketapi.BasketFees{
Fees: basketFees,
}); err != nil {
return err
}

return nil
}
73 changes: 73 additions & 0 deletions x/ecocredit/migrations/v3/state_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package v3_test

import (
"testing"

"github.com/cosmos/cosmos-sdk/orm/model/ormdb"
"github.com/cosmos/cosmos-sdk/orm/model/ormtable"
"github.com/cosmos/cosmos-sdk/orm/testing/ormtest"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/store"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
dbm "github.com/tendermint/tm-db"
"gotest.tools/v3/assert"

basketapi "github.com/regen-network/regen-ledger/api/regen/ecocredit/basket/v1"
api "github.com/regen-network/regen-ledger/api/regen/ecocredit/v1"
"github.com/regen-network/regen-ledger/x/ecocredit"
"github.com/regen-network/regen-ledger/x/ecocredit/core"
v3 "github.com/regen-network/regen-ledger/x/ecocredit/migrations/v3"
)

func TestMigrations(t *testing.T) {

ecocreditKey := sdk.NewKVStoreKey("ecocredit")
tecocreditKey := sdk.NewTransientStoreKey("transient_test")
encCfg := simapp.MakeTestEncodingConfig()
paramStore := paramtypes.NewSubspace(encCfg.Codec, encCfg.Amino, ecocreditKey, tecocreditKey, ecocredit.ModuleName)

db := dbm.NewMemDB()
cms := store.NewCommitMultiStore(db)
cms.MountStoreWithDB(ecocreditKey, storetypes.StoreTypeIAVL, db)
cms.MountStoreWithDB(tecocreditKey, storetypes.StoreTypeTransient, db)
assert.NilError(t, cms.LoadLatestVersion())
ormCtx := ormtable.WrapContextDefault(ormtest.NewMemoryBackend())
sdkCtx := sdk.NewContext(cms, tmproto.Header{}, false, log.NewNopLogger()).WithContext(ormCtx)

paramStore.WithKeyTable(core.ParamKeyTable())

// initialize params
paramStore.SetParamSet(sdkCtx, &core.Params{
CreditClassFee: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10))),
BasketFee: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10)), sdk.NewCoin("uregen", sdk.NewInt(2000000))),
AllowedClassCreators: []string{},
AllowlistEnabled: true,
})

var params core.Params
paramStore.GetParamSet(sdkCtx, &params)

ormdb, err := ormdb.NewModuleDB(&ecocredit.ModuleSchema, ormdb.ModuleDBOptions{})
assert.NilError(t, err)
coreStore, err := api.NewStateStore(ormdb)
assert.NilError(t, err)

basketStore, err := basketapi.NewStateStore(ormdb)
assert.NilError(t, err)

assert.NilError(t, v3.MigrateState(sdkCtx, coreStore, basketStore, paramStore))

// verify basket params migrated to orm table
basketFees, err := basketStore.BasketFeesTable().Get(sdkCtx)
assert.NilError(t, err)

assert.Equal(t, len(basketFees.Fees), 2)
assert.Equal(t, basketFees.Fees[0].Denom, sdk.DefaultBondDenom)
assert.Equal(t, basketFees.Fees[0].Amount, "10")
assert.Equal(t, basketFees.Fees[1].Denom, "uregen")
assert.Equal(t, basketFees.Fees[1].Amount, "2000000")
}
38 changes: 22 additions & 16 deletions x/ecocredit/module/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,13 @@ var (
)

type Module struct {
key storetypes.StoreKey
paramSpace paramtypes.Subspace
accountKeeper ecocredit.AccountKeeper
bankKeeper ecocredit.BankKeeper
Keeper server.Keeper
authority sdk.AccAddress
key storetypes.StoreKey
// legacySubspace is used solely for migration of x/ecocredit managed parameters
legacySubspace paramtypes.Subspace
accountKeeper ecocredit.AccountKeeper
bankKeeper ecocredit.BankKeeper
Keeper server.Keeper
authority sdk.AccAddress
}

func (a Module) InitGenesis(s sdk.Context, jsonCodec codec.JSONCodec, message json.RawMessage) []abci.ValidatorUpdate {
Expand Down Expand Up @@ -85,21 +86,21 @@ func (a Module) LegacyQuerierHandler(amino *codec.LegacyAmino) sdk.Querier { ret
// NewModule returns a new Module object.
func NewModule(
storeKey storetypes.StoreKey,
paramSpace paramtypes.Subspace,
legacySubspace paramtypes.Subspace,
accountKeeper ecocredit.AccountKeeper,
bankKeeper ecocredit.BankKeeper,
authority sdk.AccAddress,
) *Module {
if !paramSpace.HasKeyTable() {
paramSpace = paramSpace.WithKeyTable(coretypes.ParamKeyTable())
if !legacySubspace.HasKeyTable() {
legacySubspace = legacySubspace.WithKeyTable(coretypes.ParamKeyTable())
}

return &Module{
key: storeKey,
paramSpace: paramSpace,
bankKeeper: bankKeeper,
accountKeeper: accountKeeper,
authority: authority,
key: storeKey,
legacySubspace: legacySubspace,
bankKeeper: bankKeeper,
accountKeeper: accountKeeper,
authority: authority,
}
}

Expand All @@ -120,7 +121,7 @@ func (a Module) RegisterInterfaces(registry types.InterfaceRegistry) {
}

func (a *Module) RegisterServices(cfg module.Configurator) {
svr := server.NewServer(a.key, a.paramSpace, a.accountKeeper, a.bankKeeper, a.authority)
svr := server.NewServer(a.key, a.legacySubspace, a.accountKeeper, a.bankKeeper, a.authority)
coretypes.RegisterMsgServer(cfg.MsgServer(), svr.CoreKeeper)
coretypes.RegisterQueryServer(cfg.QueryServer(), svr.CoreKeeper)

Expand All @@ -129,6 +130,11 @@ func (a *Module) RegisterServices(cfg module.Configurator) {

marketplacetypes.RegisterMsgServer(cfg.MsgServer(), svr.MarketplaceKeeper)
marketplacetypes.RegisterQueryServer(cfg.QueryServer(), svr.MarketplaceKeeper)

m := server.NewMigrator(svr, a.legacySubspace)
if err := cfg.RegisterMigration(ecocredit.ModuleName, 2, m.Migrate2to3); err != nil {
panic(err)
}
a.Keeper = svr
}

Expand Down Expand Up @@ -220,7 +226,7 @@ func (a Module) GetTxCmd() *cobra.Command {
}

// ConsensusVersion implements AppModule/ConsensusVersion.
func (Module) ConsensusVersion() uint64 { return 2 }
func (Module) ConsensusVersion() uint64 { return 3 }

/**** DEPRECATED ****/
func (a Module) RegisterRESTRoutes(sdkclient.Context, *mux.Router) {}
Expand Down
4 changes: 4 additions & 0 deletions x/ecocredit/server/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/tendermint/tendermint/abci/types"

basketapi "github.com/regen-network/regen-ledger/api/regen/ecocredit/basket/v1"
marketplaceapi "github.com/regen-network/regen-ledger/api/regen/ecocredit/marketplace/v1"
api "github.com/regen-network/regen-ledger/api/regen/ecocredit/v1"
"github.com/regen-network/regen-ledger/x/ecocredit/basket"
"github.com/regen-network/regen-ledger/x/ecocredit/core"
"github.com/regen-network/regen-ledger/x/ecocredit/marketplace"
Expand All @@ -21,4 +24,5 @@ type Keeper interface {
InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) ([]types.ValidatorUpdate, error)
ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) (json.RawMessage, error)
QueryServers() (core.QueryServer, basket.QueryServer, marketplace.QueryServer)
GetStateStores() (api.StateStore, basketapi.StateStore, marketplaceapi.StateStore)
}
4 changes: 2 additions & 2 deletions x/ecocredit/server/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func (s serverImpl) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.
}
}

s.paramSpace.SetParamSet(ctx, &params)
s.legacySubspace.SetParamSet(ctx, &params)

return []abci.ValidatorUpdate{}, nil
}
Expand All @@ -58,7 +58,7 @@ func (s serverImpl) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.
func (s serverImpl) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) (json.RawMessage, error) {
// Get Params from the store and put them in the genesis state
var params core.Params
s.paramSpace.GetParamSet(ctx, &params)
s.legacySubspace.GetParamSet(ctx, &params)

jsonTarget := ormjson.NewRawMessageTarget()
err := s.db.ExportJSON(sdk.WrapSDKContext(ctx), jsonTarget)
Expand Down
26 changes: 24 additions & 2 deletions x/ecocredit/server/migrations.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,32 @@
package server

import (
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
v3 "github.com/regen-network/regen-ledger/x/ecocredit/migrations/v3"
)

func (s serverImpl) RunMigrations(ctx sdk.Context, cdc codec.Codec) error {
// Migrator is a struct for handling in-place store migrations.
type Migrator struct {
keeper Keeper
legacySubspace paramtypes.Subspace
}

// NewMigrator returns a new Migrator.
func NewMigrator(keeper Keeper, legacySubspace paramtypes.Subspace) Migrator {
return Migrator{
keeper: keeper,
legacySubspace: legacySubspace,
}
}

// Migrate2to3 migrates from version 2 to 3.
func (m Migrator) Migrate2to3(ctx sdk.Context) error {

coreStore, basketStore, _ := m.keeper.GetStateStores()
if err := v3.MigrateState(ctx, coreStore, basketStore, m.legacySubspace); err != nil {
return err
}

return nil
}
30 changes: 18 additions & 12 deletions x/ecocredit/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,27 @@ import (
)

type serverImpl struct {
paramSpace paramtypes.Subspace
bankKeeper ecocredit.BankKeeper
accountKeeper ecocredit.AccountKeeper
legacySubspace paramtypes.Subspace
bankKeeper ecocredit.BankKeeper
accountKeeper ecocredit.AccountKeeper

CoreKeeper core.Keeper
BasketKeeper basket.Keeper
MarketplaceKeeper marketplace.Keeper

db ormdb.ModuleDB
stateStore api.StateStore
basketStore basketapi.StateStore
db ormdb.ModuleDB
stateStore api.StateStore
basketStore basketapi.StateStore
marketplaceStore marketApi.StateStore
}

//nolint:revive
func NewServer(storeKey storetypes.StoreKey, paramSpace paramtypes.Subspace,
func NewServer(storeKey storetypes.StoreKey, legacySubspace paramtypes.Subspace,
accountKeeper ecocredit.AccountKeeper, bankKeeper ecocredit.BankKeeper, authority sdk.AccAddress) serverImpl {
s := serverImpl{
paramSpace: paramSpace,
bankKeeper: bankKeeper,
accountKeeper: accountKeeper,
legacySubspace: legacySubspace,
bankKeeper: bankKeeper,
accountKeeper: accountKeeper,
}

// ensure ecocredit module account is set
Expand All @@ -65,9 +66,10 @@ func NewServer(storeKey storetypes.StoreKey, paramSpace paramtypes.Subspace,
coreStore, basketStore, marketStore := getStateStores(s.db)
s.stateStore = coreStore
s.basketStore = basketStore
s.marketplaceStore = marketStore
s.CoreKeeper = core.NewKeeper(coreStore, bankKeeper, coreAddr, basketStore, authority)
s.BasketKeeper = basket.NewKeeper(basketStore, coreStore, bankKeeper, s.paramSpace, basketAddr, authority)
s.MarketplaceKeeper = marketplace.NewKeeper(marketStore, coreStore, bankKeeper, s.paramSpace, authority)
s.BasketKeeper = basket.NewKeeper(basketStore, coreStore, bankKeeper, s.legacySubspace, basketAddr, authority)
s.MarketplaceKeeper = marketplace.NewKeeper(marketStore, coreStore, bankKeeper, s.legacySubspace, authority)

return s
}
Expand All @@ -91,3 +93,7 @@ func getStateStores(db ormdb.ModuleDB) (api.StateStore, basketapi.StateStore, ma
func (s serverImpl) QueryServers() (coretypes.QueryServer, baskettypes.QueryServer, marketplacetypes.QueryServer) {
return s.CoreKeeper, s.BasketKeeper, s.MarketplaceKeeper
}

func (s serverImpl) GetStateStores() (api.StateStore, basketapi.StateStore, marketApi.StateStore) {
return s.stateStore, s.basketStore, s.marketplaceStore
}