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

deps: upgrade capability to sdk v0.50 and remove ibc-go dependency (backport #4068) #4083

Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 76 additions & 53 deletions modules/capability/capability_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,101 +3,124 @@ package capability_test
import (
"testing"

abci "github.com/cometbft/cometbft/abci/types"
tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
"github.com/stretchr/testify/suite"

"cosmossdk.io/log"
"cosmossdk.io/store"
"cosmossdk.io/store/metrics"
storetypes "cosmossdk.io/store/types"

dbm "github.com/cosmos/cosmos-db"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/stretchr/testify/suite"

"github.com/cosmos/ibc-go/v7/testing/simapp"
tmproto "github.com/cometbft/cometbft/proto/tendermint/types"

"github.com/cosmos/ibc-go/modules/capability"
"github.com/cosmos/ibc-go/modules/capability/keeper"
"github.com/cosmos/ibc-go/modules/capability/types"
)

const memStoreKey = "memory:mock"
const mockMemStoreKey = "memory:mock"

type CapabilityTestSuite struct {
suite.Suite
cdc codec.Codec
ctx sdk.Context
app *simapp.SimApp

cdc codec.Codec
ctx sdk.Context

keeper *keeper.Keeper
module module.AppModule

storeKey *storetypes.KVStoreKey
memStoreKey *storetypes.MemoryStoreKey
mockMemStoreKey *storetypes.MemoryStoreKey
}

func (suite *CapabilityTestSuite) SetupTest() {
checkTx := false
app := simapp.Setup(checkTx)
cdc := app.AppCodec()

// create new keeper so we can define custom scoping before init and seal
keeper := keeper.NewKeeper(cdc, app.GetKey(types.StoreKey), app.GetMemKey(types.MemStoreKey))

suite.app = app
suite.ctx = app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1})
suite.keeper = keeper
suite.cdc = cdc
suite.module = capability.NewAppModule(cdc, *keeper, false)
encodingCfg := moduletestutil.MakeTestEncodingConfig(capability.AppModuleBasic{})
suite.cdc = encodingCfg.Codec

suite.storeKey = storetypes.NewKVStoreKey(types.StoreKey)
suite.memStoreKey = storetypes.NewMemoryStoreKey(types.MemStoreKey)
suite.mockMemStoreKey = storetypes.NewMemoryStoreKey(mockMemStoreKey)

suite.ctx = suite.NewTestContext()
suite.keeper = keeper.NewKeeper(suite.cdc, suite.storeKey, suite.memStoreKey)
}

func (suite *CapabilityTestSuite) NewTestContext() sdk.Context {
db := dbm.NewMemDB()
cms := store.NewCommitMultiStore(db, log.NewNopLogger(), metrics.NewNoOpMetrics())
cms.MountStoreWithDB(suite.storeKey, storetypes.StoreTypeIAVL, db)
cms.MountStoreWithDB(suite.memStoreKey, storetypes.StoreTypeMemory, db)
cms.MountStoreWithDB(suite.mockMemStoreKey, storetypes.StoreTypeMemory, db)

err := cms.LoadLatestVersion()
suite.Require().NoError(err)

return sdk.NewContext(cms, tmproto.Header{}, false, log.NewNopLogger())
}

// The following test case mocks a specific bug discovered in https://github.com/cosmos/cosmos-sdk/issues/9800
// and ensures that the current code successfully fixes the issue.
// This test emulates statesync by firstly populating persisted state by creating a new scoped keeper and capability.
// In-memory storage is then discarded by creating a new capability keeper and app module using a mock memstore key.
// BeginBlock is then called to populate the new in-memory store using the persisted state.
func (suite *CapabilityTestSuite) TestInitializeMemStore() {
sk1 := suite.keeper.ScopeToModule(banktypes.ModuleName)
// create a scoped keeper and instantiate a new capability to populate state
scopedKeeper := suite.keeper.ScopeToModule(banktypes.ModuleName)

cap1, err := sk1.NewCapability(suite.ctx, "transfer")
cap1, err := scopedKeeper.NewCapability(suite.ctx, "transfer")
suite.Require().NoError(err)
suite.Require().NotNil(cap1)

// mock statesync by creating new keeper that shares persistent state but loses in-memory map
newKeeper := keeper.NewKeeper(suite.cdc, suite.app.GetKey(types.StoreKey), suite.app.GetMemKey(memStoreKey))
newSk1 := newKeeper.ScopeToModule(banktypes.ModuleName)
// mock statesync by creating a new keeper and module that shares persisted state
// but discards in-memory map by using a mock memstore key
newKeeper := keeper.NewKeeper(suite.cdc, suite.storeKey, suite.mockMemStoreKey)
newModule := capability.NewAppModule(suite.cdc, *newKeeper, true)

// Mock App startup
ctx := suite.app.BaseApp.NewUncachedContext(false, tmproto.Header{})
// reassign the scoped keeper, this will inherit the the mock memstore key used above
scopedKeeper = newKeeper.ScopeToModule(banktypes.ModuleName)

// seal the new keeper and ensure the in-memory store is not initialized
newKeeper.Seal()
suite.Require().False(newKeeper.IsInitialized(ctx), "memstore initialized flag set before BeginBlock")
suite.Require().False(newKeeper.IsInitialized(suite.ctx), "memstore initialized flag set before BeginBlock")

cap1, ok := scopedKeeper.GetCapability(suite.ctx, "transfer")
suite.Require().False(ok)
suite.Require().Nil(cap1)

// Mock app beginblock and ensure that no gas has been consumed and memstore is initialized
ctx = suite.app.BaseApp.NewContext(false, tmproto.Header{}).WithBlockGasMeter(sdk.NewGasMeter(50))
// add a new block gas meter to the context
ctx := suite.ctx.WithBlockGasMeter(storetypes.NewGasMeter(50))

prevGas := ctx.GasMeter().GasConsumed()
prevBlockGas := ctx.BlockGasMeter().GasConsumed()
prevGas := ctx.BlockGasMeter().GasConsumed()

restartedModule := capability.NewAppModule(suite.cdc, *newKeeper, true)
restartedModule.BeginBlock(ctx, abci.RequestBeginBlock{})
gasUsed := ctx.GasMeter().GasConsumed()
// call app module BeginBlock and ensure that no gas has been consumed
newModule.BeginBlock(ctx)

suite.Require().True(newKeeper.IsInitialized(ctx), "memstore initialized flag not set")
gasUsed := ctx.GasMeter().GasConsumed()
blockGasUsed := ctx.BlockGasMeter().GasConsumed()

suite.Require().Equal(prevBlockGas, blockGasUsed, "ensure beginblocker consumed no block gas during execution")
suite.Require().Equal(prevGas, gasUsed, "ensure beginblocker consumed no gas during execution")

// Mock the first transaction getting capability and subsequently failing
// by using a cached context and discarding all cached writes.
cacheCtx, _ := ctx.CacheContext()
capability, ok := newSk1.GetCapability(cacheCtx, "transfer")
suite.Require().NotNil(capability)
suite.Require().True(ok)

// Ensure that the second transaction can still receive capability even if first tx fails.
ctx = suite.app.BaseApp.NewContext(false, tmproto.Header{})
// assert that the in-memory store is now initialized
suite.Require().True(newKeeper.IsInitialized(ctx), "memstore initialized flag not set")

cap1, ok = newSk1.GetCapability(ctx, "transfer")
// ensure that BeginBlock has populated the new in-memory store (using the mock memstore key) and initialized capabilities
cap1, ok = scopedKeeper.GetCapability(ctx, "transfer")
suite.Require().True(ok)
suite.Require().NotNil(cap1)

// Ensure the capabilities don't get reinitialized on next BeginBlock
// by testing to see if capability returns same pointer
// also check that initialized flag is still set
restartedModule.BeginBlock(ctx, abci.RequestBeginBlock{})
recap, ok := newSk1.GetCapability(ctx, "transfer")
// ensure capabilities do not get reinitialized on next BeginBlock by comparing capability pointers
// and assert that the in-memory store is still initialized
newModule.BeginBlock(ctx)
refreshedCap, ok := scopedKeeper.GetCapability(ctx, "transfer")
suite.Require().True(ok)
suite.Require().Equal(cap1, recap, "capabilities got reinitialized after second BeginBlock")
suite.Require().Equal(cap1, refreshedCap, "capabilities got reinitialized after second BeginBlock")
suite.Require().True(newKeeper.IsInitialized(ctx), "memstore initialized flag not set")
}

Expand Down
19 changes: 5 additions & 14 deletions modules/capability/genesis_test.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
package capability_test

import (
dbm "github.com/cometbft/cometbft-db"
"github.com/cometbft/cometbft/libs/log"
tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
sdk "github.com/cosmos/cosmos-sdk/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/cosmos/ibc-go/v7/testing/simapp"

"github.com/cosmos/ibc-go/modules/capability"
"github.com/cosmos/ibc-go/modules/capability/keeper"
"github.com/cosmos/ibc-go/modules/capability/types"
)

func (suite *CapabilityTestSuite) TestGenesis() {
// InitGenesis must be called in order to set the intial index to 1.
capability.InitGenesis(suite.ctx, *suite.keeper, *types.DefaultGenesis())

sk1 := suite.keeper.ScopeToModule(banktypes.ModuleName)
sk2 := suite.keeper.ScopeToModule(stakingtypes.ModuleName)

Expand All @@ -32,16 +29,10 @@ func (suite *CapabilityTestSuite) TestGenesis() {

genState := capability.ExportGenesis(suite.ctx, *suite.keeper)

// create new app that does not share persistent or in-memory state
// and initialize app from exported genesis state above.
db := dbm.NewMemDB()
encCdc := simapp.MakeTestEncodingConfig()
newApp := simapp.NewSimApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, simapp.DefaultNodeHome, 5, encCdc, simtestutil.EmptyAppOptions{})

newKeeper := keeper.NewKeeper(suite.cdc, newApp.GetKey(types.StoreKey), newApp.GetMemKey(types.MemStoreKey))
newKeeper := keeper.NewKeeper(suite.cdc, suite.storeKey, suite.memStoreKey)
newSk1 := newKeeper.ScopeToModule(banktypes.ModuleName)
newSk2 := newKeeper.ScopeToModule(stakingtypes.ModuleName)
deliverCtx, _ := newApp.BaseApp.NewUncachedContext(false, tmproto.Header{}).WithBlockGasMeter(sdk.NewInfiniteGasMeter()).CacheContext()
deliverCtx := suite.NewTestContext()

capability.InitGenesis(deliverCtx, *newKeeper, *genState)

Expand Down
Loading