diff --git a/app/consumer-democracy/app.go b/app/consumer-democracy/app.go index 4aa85e258c..809710e20c 100644 --- a/app/consumer-democracy/app.go +++ b/app/consumer-democracy/app.go @@ -87,8 +87,8 @@ import ( porttypes "github.com/cosmos/ibc-go/v7/modules/core/05-port/types" ibchost "github.com/cosmos/ibc-go/v7/modules/core/exported" ibckeeper "github.com/cosmos/ibc-go/v7/modules/core/keeper" - ibctestingcore "github.com/cosmos/interchain-security/legacy_ibc_testing/core" - ibctesting "github.com/cosmos/interchain-security/legacy_ibc_testing/testing" + ibctesting "github.com/cosmos/ibc-go/v7/testing" + ibctestingtypes "github.com/cosmos/ibc-go/v7/testing/types" "github.com/gorilla/mux" "github.com/rakyll/statik/fs" "github.com/spf13/cast" @@ -929,7 +929,7 @@ func (app *App) GetBaseApp() *baseapp.BaseApp { } // GetStakingKeeper implements the TestingApp interface. -func (app *App) GetStakingKeeper() ibctestingcore.StakingKeeper { +func (app *App) GetStakingKeeper() ibctestingtypes.StakingKeeper { return app.ConsumerKeeper } diff --git a/app/consumer-democracy/proposals_whitelisting_test.go b/app/consumer-democracy/proposals_whitelisting_test.go index 1cf5a6e83b..eea113666e 100644 --- a/app/consumer-democracy/proposals_whitelisting_test.go +++ b/app/consumer-democracy/proposals_whitelisting_test.go @@ -3,15 +3,17 @@ package app_test import ( "testing" + ibctesting "github.com/cosmos/ibc-go/v7/testing" appConsumer "github.com/cosmos/interchain-security/app/consumer-democracy" - ibctesting "github.com/cosmos/interchain-security/legacy_ibc_testing/testing" icstestingutils "github.com/cosmos/interchain-security/testutil/ibc_testing" + testutil "github.com/cosmos/interchain-security/testutil/integration" "github.com/stretchr/testify/require" ) func TestDemocracyGovernanceWhitelistingKeys(t *testing.T) { - chain := ibctesting.NewTestChain(t, ibctesting.NewCoordinator(t, 0), - icstestingutils.DemocracyConsumerAppIniter, "test") + _, valUpdates, _ := testutil.CreateValidators(t, 4) + ibctesting.DefaultTestingAppInit = icstestingutils.DemocracyConsumerAppIniter(valUpdates) + chain := ibctesting.NewTestChain(t, ibctesting.NewCoordinator(t, 0), "test") paramKeeper := chain.App.(*appConsumer.App).ParamsKeeper for paramKey := range appConsumer.LegacyWhitelistedParams { ss, ok := paramKeeper.GetSubspace(paramKey.Subspace) diff --git a/app/consumer/app.go b/app/consumer/app.go index a63c50304e..a38ca8bcb9 100644 --- a/app/consumer/app.go +++ b/app/consumer/app.go @@ -82,9 +82,9 @@ import ( porttypes "github.com/cosmos/ibc-go/v7/modules/core/05-port/types" ibchost "github.com/cosmos/ibc-go/v7/modules/core/exported" ibckeeper "github.com/cosmos/ibc-go/v7/modules/core/keeper" + ibctesting "github.com/cosmos/ibc-go/v7/testing" + ibctestingtypes "github.com/cosmos/ibc-go/v7/testing/types" appparams "github.com/cosmos/interchain-security/app/params" - ibctestingcore "github.com/cosmos/interchain-security/legacy_ibc_testing/core" - ibctesting "github.com/cosmos/interchain-security/legacy_ibc_testing/testing" "github.com/gorilla/mux" "github.com/rakyll/statik/fs" "github.com/spf13/cast" @@ -735,7 +735,7 @@ func (app *App) GetBaseApp() *baseapp.BaseApp { } // GetStakingKeeper implements the TestingApp interface. -func (app *App) GetStakingKeeper() ibctestingcore.StakingKeeper { +func (app *App) GetStakingKeeper() ibctestingtypes.StakingKeeper { return app.ConsumerKeeper } diff --git a/app/provider/app.go b/app/provider/app.go index b6c3f36dc1..1f4e943467 100644 --- a/app/provider/app.go +++ b/app/provider/app.go @@ -93,8 +93,8 @@ import ( ibchost "github.com/cosmos/ibc-go/v7/modules/core/exported" ibckeeper "github.com/cosmos/ibc-go/v7/modules/core/keeper" tendermint "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" - ibctestingcore "github.com/cosmos/interchain-security/legacy_ibc_testing/core" - ibctesting "github.com/cosmos/interchain-security/legacy_ibc_testing/testing" + ibctesting "github.com/cosmos/ibc-go/v7/testing" + ibctestingtypes "github.com/cosmos/ibc-go/v7/testing/types" dbm "github.com/cometbft/cometbft-db" abci "github.com/cometbft/cometbft/abci/types" @@ -820,7 +820,7 @@ func (app *App) GetBaseApp() *baseapp.BaseApp { } // GetStakingKeeper implements the TestingApp interface. -func (app *App) GetStakingKeeper() ibctestingcore.StakingKeeper { +func (app *App) GetStakingKeeper() ibctestingtypes.StakingKeeper { return app.StakingKeeper } diff --git a/legacy_ibc_testing/README.md b/legacy_ibc_testing/README.md deleted file mode 100644 index 1337ec1412..0000000000 --- a/legacy_ibc_testing/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Legacy IBC Testing - -### `legacy_ibc_testing` is imported from [Informal Systems fork of ibc-go](https://github.com/informalsystems/ibc-go). It contains modifications to canonical ibc-go `v3.4.0` for testing purposes only. - -Crucially, Informal's fork contained changes to the [StakingKeeper interface](https://github.com/informalsystems/ibc-go/blob/interchain-security-v3.4.0/modules/core/02-client/types/expected_keepers.go#L12) that both consumer and providers would be expected to return from the testing method `GetStakingKeeper`. For consumer apps, this method would return and IBCKeeper type. This change could not be back-ported to `v3.4.0` of ibc-go as it would be api breaking. Instead, the relevant changes made to ibc-go were consolidated and copied directly into `interchain-security`. Once ICS upgrades ibc-go to a version that supports this change, `v5` at the earliest, this test helper directory can be removed. - -**Directory** -- Core - - Contains changes made in ibc-go `core/`, but do not contain any logic requiring they live in that directory. Includes an interface definition and a testing helper method. -- Simapp - - Includes test helper substitutions for ibc-go's `simapp/` used in the Diff tests. -- Testing - - Replaces ibc-go's `testing/` directory to facilitate ibc's `TestApp`'s implementation of `GetStakingKeeper` returning the relevant `StakingKeeper` interface enhanced in Informal's ibc-go fork. \ No newline at end of file diff --git a/legacy_ibc_testing/core/events.go b/legacy_ibc_testing/core/events.go deleted file mode 100644 index daabc92d54..0000000000 --- a/legacy_ibc_testing/core/events.go +++ /dev/null @@ -1,48 +0,0 @@ -package core - -import ( - "strconv" - - abci "github.com/cometbft/cometbft/abci/types" - - clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" - "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" -) - -/* -TODO: Remove after upgrading to ibc-go v5 -legacy_ibc_testing is temporarily copied into the interchain-security repository for the purpose of testing only. -The integration test suites rely on modifications to ibc-go's test framework that cannot be back-ported to the canonical version that ics will rely on. -These files will be deprecated once ICS is able to upgrade to ibc-go v5. -*/ - -// ReconstructPacketFromEvent recreates a packet from an appropriate provided event -func ReconstructPacketFromEvent(event abci.Event) (packet types.Packet, err error) { - attrMap := make(map[string][]byte) - for _, attr := range event.Attributes { - attrMap[string(attr.Key)] = []byte(attr.Value) - } - - sequence, err := strconv.Atoi(string(attrMap[string(types.AttributeKeySequence)])) - if err != nil { - return packet, err - } - timeoutTimestamp, err := strconv.Atoi(string(attrMap[string(types.AttributeKeyTimeoutTimestamp)])) - if err != nil { - return packet, err - } - timeoutHeight, err := clienttypes.ParseHeight(string(attrMap[string(types.AttributeKeyTimeoutHeight)])) - if err != nil { - return packet, err - } - return types.NewPacket( - attrMap[string(types.AttributeKeyData)], // data - uint64(sequence), - string(attrMap[string(types.AttributeKeySrcPort)]), // sourcePort, - string(attrMap[string(types.AttributeKeySrcChannel)]), // sourceChannel, - string(attrMap[string(types.AttributeKeyDstPort)]), // destinationPort, - string(attrMap[string(types.AttributeKeyDstChannel)]), // destinationChannel string, - timeoutHeight, - uint64(timeoutTimestamp), - ), nil -} diff --git a/legacy_ibc_testing/core/expected_keepers.go b/legacy_ibc_testing/core/expected_keepers.go deleted file mode 100644 index 90a9d40f3c..0000000000 --- a/legacy_ibc_testing/core/expected_keepers.go +++ /dev/null @@ -1,20 +0,0 @@ -package core - -import ( - "time" - - sdk "github.com/cosmos/cosmos-sdk/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" -) - -/* -TODO: Remove after upgrading to ibc-go v5 -legacy_ibc_testing is temporarily copied into the interchain-security repository for the purpose of testing only. -The integration test suites rely on modifications to ibc-go's test framework that cannot be back-ported to the canonical version that ics will rely on. -These files will be deprecated once ICS is able to upgrade to ibc-go v5. -*/ - -type StakingKeeper interface { - GetHistoricalInfo(ctx sdk.Context, height int64) (stakingtypes.HistoricalInfo, bool) - UnbondingTime(ctx sdk.Context) time.Duration -} diff --git a/legacy_ibc_testing/simapp/helpers/test_helpers.go b/legacy_ibc_testing/simapp/helpers/test_helpers.go deleted file mode 100644 index b3e5c80d5e..0000000000 --- a/legacy_ibc_testing/simapp/helpers/test_helpers.go +++ /dev/null @@ -1,85 +0,0 @@ -package helpers - -import ( - "math/rand" - - "github.com/cosmos/cosmos-sdk/client" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/simulation" - "github.com/cosmos/cosmos-sdk/types/tx/signing" - authsign "github.com/cosmos/cosmos-sdk/x/auth/signing" -) - -/* -TODO: Remove after upgrading to ibc-go v5 -legacy_ibc_testing is temporarily copied into the interchain-security repository for the purpose of testing only. -The integration test suites rely on modifications to ibc-go's test framework that cannot be back-ported to the canonical version that ics will rely on. -These files will be deprecated once ICS is able to upgrade to ibc-go v5. -*/ - -// SimAppChainID hardcoded chainID for simulation -const ( - DefaultGenTxGas = 1000000 -) - -// GenTx generates a signed mock transaction. -func GenTx(gen client.TxConfig, msgs []sdk.Msg, feeAmt sdk.Coins, gas uint64, chainID string, accNums, accSeqs []uint64, priv ...cryptotypes.PrivKey) (sdk.Tx, error) { - sigs := make([]signing.SignatureV2, len(priv)) - - // create a random length memo - r := rand.New(rand.NewSource(rand.Int63())) - - memo := simulation.RandStringOfLength(r, simulation.RandIntBetween(r, 0, 100)) - - signMode := gen.SignModeHandler().DefaultMode() - - // 1st round: set SignatureV2 with empty signatures, to set correct - // signer infos. - for i, p := range priv { - sigs[i] = signing.SignatureV2{ - PubKey: p.PubKey(), - Data: &signing.SingleSignatureData{ - SignMode: signMode, - }, - Sequence: accSeqs[i], - } - } - - tx := gen.NewTxBuilder() - err := tx.SetMsgs(msgs...) - if err != nil { - return nil, err - } - err = tx.SetSignatures(sigs...) - if err != nil { - return nil, err - } - tx.SetMemo(memo) - tx.SetFeeAmount(feeAmt) - tx.SetGasLimit(gas) - - // 2nd round: once all signer infos are set, every signer can sign. - for i, p := range priv { - signerData := authsign.SignerData{ - ChainID: chainID, - AccountNumber: accNums[i], - Sequence: accSeqs[i], - } - signBytes, err := gen.SignModeHandler().GetSignBytes(signMode, signerData, tx.GetTx()) - if err != nil { - panic(err) - } - sig, err := p.Sign(signBytes) - if err != nil { - panic(err) - } - sigs[i].Data.(*signing.SingleSignatureData).Signature = sig - err = tx.SetSignatures(sigs...) - if err != nil { - panic(err) - } - } - - return tx.GetTx(), nil -} diff --git a/legacy_ibc_testing/simapp/test_helpers.go b/legacy_ibc_testing/simapp/test_helpers.go deleted file mode 100644 index 91846ab674..0000000000 --- a/legacy_ibc_testing/simapp/test_helpers.go +++ /dev/null @@ -1,154 +0,0 @@ -package simapp - -import ( - "bytes" - "encoding/hex" - "fmt" - "strconv" - "testing" - "time" - - tmproto "github.com/cometbft/cometbft/proto/tendermint/types" - tmtypes "github.com/cometbft/cometbft/types" - bam "github.com/cosmos/cosmos-sdk/baseapp" - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/stretchr/testify/require" - - "github.com/cosmos/interchain-security/legacy_ibc_testing/simapp/helpers" -) - -/* -TODO: Remove after upgrading to ibc-go v5 -legacy_ibc_testing is temporarily copied into the interchain-security repository for the purpose of testing only. -The integration test suites rely on modifications to ibc-go's test framework that cannot be back-ported to the canonical version that ics will rely on. -These files will be deprecated once ICS is able to upgrade to ibc-go v5. -*/ - -// DefaultConsensusParams defines the default Tendermint consensus params used in -// SimApp testing. -var DefaultConsensusParams = &tmproto.ConsensusParams{ - Block: &tmproto.BlockParams{ - MaxBytes: 200000, - MaxGas: 2000000, - }, - Evidence: &tmproto.EvidenceParams{ - MaxAgeNumBlocks: 302400, - MaxAgeDuration: 504 * time.Hour, // 3 weeks is the max duration - MaxBytes: 10000, - }, - Validator: &tmproto.ValidatorParams{ - PubKeyTypes: []string{ - tmtypes.ABCIPubKeyTypeEd25519, - }, - }, -} - -type GenerateAccountStrategy func(int) []sdk.AccAddress - -// ConvertAddrsToValAddrs converts the provided addresses to ValAddress. -func ConvertAddrsToValAddrs(addrs []sdk.AccAddress) []sdk.ValAddress { - valAddrs := make([]sdk.ValAddress, len(addrs)) - - for i, addr := range addrs { - valAddrs[i] = sdk.ValAddress(addr) - } - - return valAddrs -} - -func TestAddr(addr string, bech string) (sdk.AccAddress, error) { - res, err := sdk.AccAddressFromHexUnsafe(addr) - if err != nil { - return nil, err - } - bechexpected := res.String() - if bech != bechexpected { - return nil, fmt.Errorf("bech encoding doesn't match reference") - } - - bechres, err := sdk.AccAddressFromBech32(bech) - if err != nil { - return nil, err - } - if !bytes.Equal(bechres, res) { - return nil, err - } - - return res, nil -} - -// SignAndDeliver signs and delivers a transaction. No simulation occurs as the -// ibc testing package causes checkState and deliverState to diverge in block time. -// -// CONTRACT: BeginBlock must be called before this function. -func SignAndDeliver( - t *testing.T, txCfg client.TxConfig, app *bam.BaseApp, header tmproto.Header, msgs []sdk.Msg, - chainID string, accNums, accSeqs []uint64, expSimPass, expPass bool, priv ...cryptotypes.PrivKey, -) (sdk.GasInfo, *sdk.Result, error) { - t.Helper() - tx, err := helpers.GenTx( - txCfg, - msgs, - sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 0)}, - helpers.DefaultGenTxGas, - chainID, - accNums, - accSeqs, - priv..., - ) - require.NoError(t, err) - - // Simulate a sending a transaction - gInfo, res, err := app.SimDeliver(txCfg.TxEncoder(), tx) - - if expPass { - require.NoError(t, err) - require.NotNil(t, res) - } else { - require.Error(t, err) - require.Nil(t, res) - } - - return gInfo, res, err -} - -// CreateTestPubKeys returns a total of numPubKeys public keys in ascending order. -func CreateTestPubKeys(numPubKeys int) []cryptotypes.PubKey { - var publicKeys []cryptotypes.PubKey - var buffer bytes.Buffer - - // start at 10 to avoid changing 1 to 01, 2 to 02, etc - for i := 100; i < (numPubKeys + 100); i++ { - numString := strconv.Itoa(i) - buffer.WriteString("0B485CFC0EECC619440448436F8FC9DF40566F2369E72400281454CB552AF") // base pubkey string - buffer.WriteString(numString) // adding on final two digits to make pubkeys unique - publicKeys = append(publicKeys, NewPubKeyFromHex(buffer.String())) - buffer.Reset() - } - - return publicKeys -} - -// NewPubKeyFromHex returns a PubKey from a hex string. -func NewPubKeyFromHex(pk string) (res cryptotypes.PubKey) { - pkBytes, err := hex.DecodeString(pk) - if err != nil { - panic(err) - } - if len(pkBytes) != ed25519.PubKeySize { - panic(errors.Wrap(errors.ErrInvalidPubKey, "invalid pubkey size")) - } - return &ed25519.PubKey{Key: pkBytes} -} - -// EmptyAppOptions is a stub implementing AppOptions -type EmptyAppOptions struct{} - -// Get implements AppOptions -func (ao EmptyAppOptions) Get(o string) interface{} { - return nil -} diff --git a/legacy_ibc_testing/testing/app.go b/legacy_ibc_testing/testing/app.go deleted file mode 100644 index 792316ca1e..0000000000 --- a/legacy_ibc_testing/testing/app.go +++ /dev/null @@ -1,173 +0,0 @@ -package testing - -import ( - "encoding/json" - "testing" - "time" - - "cosmossdk.io/math" - "github.com/cosmos/interchain-security/legacy_ibc_testing/core" - - abci "github.com/cometbft/cometbft/abci/types" - tmproto "github.com/cometbft/cometbft/proto/tendermint/types" - tmtypes "github.com/cometbft/cometbft/types" - "github.com/cosmos/cosmos-sdk/baseapp" - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" - storetypes "github.com/cosmos/cosmos-sdk/store/types" - sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/stretchr/testify/require" - - "github.com/cosmos/ibc-go/v7/modules/core/keeper" - - "github.com/cosmos/interchain-security/legacy_ibc_testing/simapp" - consumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" -) - -/* -TODO: Remove after upgrading to ibc-go v5 -legacy_ibc_testing is temporarily copied into the interchain-security repository for the purpose of testing only. -The integration test suites rely on modifications to ibc-go's test framework that cannot be back-ported to the canonical version that ics will rely on. -These files will be deprecated once ICS is able to upgrade to ibc-go v5. -*/ - -type AppIniter func() (TestingApp, map[string]json.RawMessage) - -var DefaultTestingAppInit AppIniter - -type TestingApp interface { - abci.Application - - // ibc-go additions - GetBaseApp() *baseapp.BaseApp - GetStakingKeeper() core.StakingKeeper - GetIBCKeeper() *keeper.Keeper - GetScopedIBCKeeper() capabilitykeeper.ScopedKeeper - GetTxConfig() client.TxConfig - - // Implemented by SimApp - AppCodec() codec.Codec - - // Implemented by BaseApp - LastCommitID() storetypes.CommitID - LastBlockHeight() int64 -} - -// SetupWithGenesisValSet initializes a new SimApp with a validator set and genesis accounts -// that also act as delegators. For simplicity, each validator is bonded with a delegation -// of one consensus engine unit (10^6) in the default token of the simapp from first genesis -// account. A Nop logger is set in SimApp. -func SetupWithGenesisValSet(t *testing.T, appIniter AppIniter, valSet *tmtypes.ValidatorSet, genAccs []authtypes.GenesisAccount, chainID string, powerReduction math.Int, balances ...banktypes.Balance) TestingApp { - t.Helper() - app, genesisState := appIniter() - baseapp.SetChainID(chainID)(app.GetBaseApp()) - - // set genesis accounts - authGenesis := authtypes.NewGenesisState(authtypes.DefaultParams(), genAccs) - genesisState[authtypes.ModuleName] = app.AppCodec().MustMarshalJSON(authGenesis) - - validators := make([]stakingtypes.Validator, 0, len(valSet.Validators)) - delegations := make([]stakingtypes.Delegation, 0, len(valSet.Validators)) - - bondAmt := sdk.TokensFromConsensusPower(1, powerReduction) - - initValPowers := []abci.ValidatorUpdate{} - for _, val := range valSet.Validators { - pk, err := cryptocodec.FromTmPubKeyInterface(val.PubKey) - require.NoError(t, err) - pkAny, err := codectypes.NewAnyWithValue(pk) - require.NoError(t, err) - validator := stakingtypes.Validator{ - OperatorAddress: sdk.ValAddress(val.Address).String(), - ConsensusPubkey: pkAny, - Jailed: false, - Status: stakingtypes.Bonded, - Tokens: bondAmt, - DelegatorShares: sdk.OneDec(), - Description: stakingtypes.Description{}, - UnbondingHeight: int64(0), - UnbondingTime: time.Unix(0, 0).UTC(), - Commission: stakingtypes.NewCommission(sdk.ZeroDec(), sdk.ZeroDec(), sdk.ZeroDec()), - MinSelfDelegation: sdk.ZeroInt(), - } - - validators = append(validators, validator) - delegations = append(delegations, stakingtypes.NewDelegation(genAccs[0].GetAddress(), val.Address.Bytes(), sdk.OneDec())) - - pub, _ := val.ToProto() - initValPowers = append(initValPowers, abci.ValidatorUpdate{ - Power: val.VotingPower, - PubKey: pub.PubKey, - }) - } - - // set validators and delegations - var ( - stakingGenesis stakingtypes.GenesisState - consumerGenesis consumertypes.GenesisState - bondDenom string - ) - if genesisState[stakingtypes.ModuleName] != nil { - app.AppCodec().MustUnmarshalJSON(genesisState[stakingtypes.ModuleName], &stakingGenesis) - bondDenom = stakingGenesis.Params.BondDenom - } else { - bondDenom = sdk.DefaultBondDenom - } - - // add bonded amount to bonded pool module account - balances = append(balances, banktypes.Balance{ - Address: authtypes.NewModuleAddress(stakingtypes.BondedPoolName).String(), - Coins: sdk.Coins{sdk.NewCoin(bondDenom, bondAmt.Mul(sdk.NewInt(int64(len(valSet.Validators)))))}, - }) - - // set validators and delegations - stakingGenesis = *stakingtypes.NewGenesisState(stakingGenesis.Params, validators, delegations) - genesisState[stakingtypes.ModuleName] = app.AppCodec().MustMarshalJSON(&stakingGenesis) - - // update total supply - bankGenesis := banktypes.NewGenesisState(banktypes.DefaultGenesisState().Params, balances, sdk.NewCoins(), []banktypes.Metadata{}, []banktypes.SendEnabled{}) - genesisState[banktypes.ModuleName] = app.AppCodec().MustMarshalJSON(bankGenesis) - - if genesisState[consumertypes.ModuleName] != nil { - app.AppCodec().MustUnmarshalJSON(genesisState[consumertypes.ModuleName], &consumerGenesis) - consumerGenesis.InitialValSet = initValPowers - consumerGenesis.Params.Enabled = true - genesisState[consumertypes.ModuleName] = app.AppCodec().MustMarshalJSON(&consumerGenesis) - } - - stateBytes, err := json.MarshalIndent(genesisState, "", " ") - require.NoError(t, err) - - // init chain will set the validator set and initialize the genesis accounts - app.InitChain( - abci.RequestInitChain{ - ChainId: chainID, - Validators: []abci.ValidatorUpdate{}, - ConsensusParams: simapp.DefaultConsensusParams, - AppStateBytes: stateBytes, - }, - ) - - // commit genesis changes - app.Commit() - - app.BeginBlock( - abci.RequestBeginBlock{ - Header: tmproto.Header{ - ChainID: chainID, - Height: app.LastBlockHeight() + 1, - AppHash: app.LastCommitID().Hash, - ValidatorsHash: valSet.Hash(), - NextValidatorsHash: valSet.Hash(), - }, - }, - ) - - return app -} diff --git a/legacy_ibc_testing/testing/chain.go b/legacy_ibc_testing/testing/chain.go deleted file mode 100644 index 48b6c21bd4..0000000000 --- a/legacy_ibc_testing/testing/chain.go +++ /dev/null @@ -1,652 +0,0 @@ -package testing - -import ( - "bytes" - "fmt" - "testing" - "time" - - sdkerrors "cosmossdk.io/errors" - abci "github.com/cometbft/cometbft/abci/types" - "github.com/cometbft/cometbft/crypto/tmhash" - tmproto "github.com/cometbft/cometbft/proto/tendermint/types" - tmprotoversion "github.com/cometbft/cometbft/proto/tendermint/version" - tmtypes "github.com/cometbft/cometbft/types" - tmversion "github.com/cometbft/cometbft/version" - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - teststaking "github.com/cosmos/cosmos-sdk/x/staking/testutil" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" - "github.com/stretchr/testify/require" - - clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" - channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" - commitmenttypes "github.com/cosmos/ibc-go/v7/modules/core/23-commitment/types" - host "github.com/cosmos/ibc-go/v7/modules/core/24-host" - "github.com/cosmos/ibc-go/v7/modules/core/exported" - "github.com/cosmos/ibc-go/v7/modules/core/types" - ibctmtypes "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" - "github.com/cosmos/ibc-go/v7/testing/mock" - ibctestingcore "github.com/cosmos/interchain-security/legacy_ibc_testing/core" - "github.com/cosmos/interchain-security/legacy_ibc_testing/simapp" -) - -/* -TODO: Remove after upgrading to ibc-go v5 -legacy_ibc_testing is temporarily copied into the interchain-security repository for the purpose of testing only. -The integration test suites rely on modifications to ibc-go's test framework that cannot be back-ported to the canonical version that ics will rely on. -These files will be deprecated once ICS is able to upgrade to ibc-go v5. -*/ - -var MaxAccounts = 10 - -type SenderAccount struct { - SenderPrivKey cryptotypes.PrivKey - SenderAccount authtypes.AccountI -} - -// TestChain is a testing struct that wraps a simapp with the last TM Header, the current ABCI -// header and the validators of the TestChain. It also contains a field called ChainID. This -// is the clientID that *other* chains use to refer to this TestChain. The SenderAccount -// is used for delivering transactions through the application state. -// NOTE: the actual application uses an empty chain-id for ease of testing. -type TestChain struct { - *testing.T - - Coordinator *Coordinator - App TestingApp - ChainID string - LastHeader *ibctmtypes.Header // header for last block height committed - CurrentHeader tmproto.Header // header for current block height - QueryServer types.QueryServer - TxConfig client.TxConfig - Codec codec.BinaryCodec - - Vals *tmtypes.ValidatorSet - NextVals *tmtypes.ValidatorSet - - // Signers is a map from validator address to the PrivValidator - // The map is converted into an array that is the same order as the validators right before signing commit - // This ensures that signers will always be in correct order even as validator powers change. - // If a test adds a new validator after chain creation, then the signer map must be updated to include - // the new PrivValidator entry. - Signers map[string]tmtypes.PrivValidator - - // SentPackets is a map from packet sequences to sent packets, - // reconstructed from emitted events of type SendPacketEvent - SentPackets map[string]channeltypes.Packet - - // autogenerated sender private key - SenderPrivKey cryptotypes.PrivKey - SenderAccount authtypes.AccountI - - SenderAccounts []SenderAccount -} - -// NewTestChainWithValSet initializes a new TestChain instance with the given validator set -// and signer array. It also initializes 10 Sender accounts with a balance of 10000000000000000000 coins of -// bond denom to use for tests. -// -// The first block height is committed to state in order to allow for client creations on -// counterparty chains. The TestChain will return with a block height starting at 2. -// -// Time management is handled by the Coordinator in order to ensure synchrony between chains. -// Each update of any chain increments the block header time for all chains by 5 seconds. -// -// NOTE: to use a custom sender privkey and account for testing purposes, replace and modify this -// constructor function. -// -// CONTRACT: Validator array must be provided in the order expected by Tendermint. -// i.e. sorted first by power and then lexicographically by address. -func NewTestChainWithValSet(t *testing.T, coord *Coordinator, appIniter AppIniter, chainID string, valSet *tmtypes.ValidatorSet, signers map[string]tmtypes.PrivValidator) *TestChain { - t.Helper() - genAccs := []authtypes.GenesisAccount{} - genBals := []banktypes.Balance{} - senderAccs := []SenderAccount{} - - // generate genesis accounts - for i := 0; i < MaxAccounts; i++ { - senderPrivKey := secp256k1.GenPrivKey() - acc := authtypes.NewBaseAccount(senderPrivKey.PubKey().Address().Bytes(), senderPrivKey.PubKey(), uint64(i), 0) - amount, ok := sdk.NewIntFromString("10000000000000000000") - require.True(t, ok) - - balance := banktypes.Balance{ - Address: acc.GetAddress().String(), - Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, amount)), - } - - genAccs = append(genAccs, acc) - genBals = append(genBals, balance) - - senderAcc := SenderAccount{ - SenderAccount: acc, - SenderPrivKey: senderPrivKey, - } - - senderAccs = append(senderAccs, senderAcc) - } - - app := SetupWithGenesisValSet(t, appIniter, valSet, genAccs, chainID, sdk.DefaultPowerReduction, genBals...) - - // create current header and call begin block - header := tmproto.Header{ - ChainID: chainID, - Height: 1, - Time: coord.CurrentTime.UTC(), - } - - txConfig := app.GetTxConfig() - - // create an account to send transactions from - chain := &TestChain{ - T: t, - Coordinator: coord, - ChainID: chainID, - App: app, - CurrentHeader: header, - QueryServer: app.GetIBCKeeper(), - TxConfig: txConfig, - Codec: app.AppCodec(), - Vals: valSet, - NextVals: valSet, - Signers: signers, - SentPackets: make(map[string]channeltypes.Packet), - SenderPrivKey: senderAccs[0].SenderPrivKey, - SenderAccount: senderAccs[0].SenderAccount, - SenderAccounts: senderAccs, - } - - coord.CommitBlock(chain) - - return chain -} - -// NewTestChain initializes a new test chain with a default of 4 validators -// Use this function if the tests do not need custom control over the validator set -func NewTestChain(t *testing.T, coord *Coordinator, appIniter AppIniter, chainID string) *TestChain { - t.Helper() - // generate validators private/public key - var ( - validatorsPerChain = 4 - validators []*tmtypes.Validator - signersByAddress = make(map[string]tmtypes.PrivValidator, validatorsPerChain) - ) - - for i := 0; i < validatorsPerChain; i++ { - privVal := mock.NewPV() - pubKey, err := privVal.GetPubKey() - require.NoError(t, err) - validators = append(validators, tmtypes.NewValidator(pubKey, 1)) - signersByAddress[pubKey.Address().String()] = privVal - } - - // construct validator set; - // Note that the validators are sorted by voting power - // or, if equal, by address lexical order - valSet := tmtypes.NewValidatorSet(validators) - - return NewTestChainWithValSet(t, coord, appIniter, chainID, valSet, signersByAddress) -} - -// GetContext returns the current context for the application. -func (chain *TestChain) GetContext() sdk.Context { - return chain.App.GetBaseApp().NewContext(false, chain.CurrentHeader) -} - -// QueryProof performs an abci query with the given key and returns the proto encoded merkle proof -// for the query and the height at which the proof will succeed on a tendermint verifier. -func (chain *TestChain) QueryProof(key []byte) ([]byte, clienttypes.Height) { - return chain.QueryProofAtHeight(key, chain.App.LastBlockHeight()) -} - -// QueryProof performs an abci query with the given key and returns the proto encoded merkle proof -// for the query and the height at which the proof will succeed on a tendermint verifier. -func (chain *TestChain) QueryProofAtHeight(key []byte, height int64) ([]byte, clienttypes.Height) { - res := chain.App.Query(abci.RequestQuery{ - Path: fmt.Sprintf("store/%s/key", exported.StoreKey), - Height: height - 1, - Data: key, - Prove: true, - }) - - merkleProof, err := commitmenttypes.ConvertProofs(res.ProofOps) - require.NoError(chain.T, err) - - proof, err := chain.App.AppCodec().Marshal(&merkleProof) - require.NoError(chain.T, err) - - revision := clienttypes.ParseChainID(chain.ChainID) - - // proof height + 1 is returned as the proof created corresponds to the height the proof - // was created in the IAVL tree. Tendermint and subsequently the clients that rely on it - // have heights 1 above the IAVL tree. Thus we return proof height + 1 - return proof, clienttypes.NewHeight(revision, uint64(res.Height)+1) -} - -// QueryUpgradeProof performs an abci query with the given key and returns the proto encoded merkle proof -// for the query and the height at which the proof will succeed on a tendermint verifier. -func (chain *TestChain) QueryUpgradeProof(key []byte, height uint64) ([]byte, clienttypes.Height) { - res := chain.App.Query(abci.RequestQuery{ - Path: "store/upgrade/key", - Height: int64(height - 1), - Data: key, - Prove: true, - }) - - merkleProof, err := commitmenttypes.ConvertProofs(res.ProofOps) - require.NoError(chain.T, err) - - proof, err := chain.App.AppCodec().Marshal(&merkleProof) - require.NoError(chain.T, err) - - revision := clienttypes.ParseChainID(chain.ChainID) - - // proof height + 1 is returned as the proof created corresponds to the height the proof - // was created in the IAVL tree. Tendermint and subsequently the clients that rely on it - // have heights 1 above the IAVL tree. Thus we return proof height + 1 - return proof, clienttypes.NewHeight(revision, uint64(res.Height+1)) -} - -// QueryConsensusStateProof performs an abci query for a consensus state -// stored on the given clientID. The proof and consensusHeight are returned. -func (chain *TestChain) QueryConsensusStateProof(clientID string) ([]byte, clienttypes.Height) { - clientState := chain.GetClientState(clientID) - - consensusHeight := clientState.GetLatestHeight().(clienttypes.Height) - consensusKey := host.FullConsensusStateKey(clientID, consensusHeight) - proofConsensus, _ := chain.QueryProof(consensusKey) - - return proofConsensus, consensusHeight -} - -// GetSentPacketKey returns a key for accessing a sent packet, -// given an ibc sequence number and the channel ID for the source endpoint. -func GetSentPacketKey(sequence uint64, channelID string) string { - return fmt.Sprintf("%s-%d", channelID, sequence) -} - -// GetSentPacket returns the sent packet with `sequence` (if any), -// reconstructed from emitted events of type SendPacketEvent -func (chain *TestChain) GetSentPacket(sequence uint64, channelID string) (packet channeltypes.Packet, found bool) { - sentPacketKey := GetSentPacketKey(sequence, channelID) - packet, found = chain.SentPackets[sentPacketKey] - return -} - -// setSentPacketsFromEvents stores the sent packet reconstructed -// from emitted events of type SendPacketEvent -func (chain *TestChain) setSentPacketsFromEvents(events []abci.Event) { - for _, event := range events { - if event.Type == channeltypes.EventTypeSendPacket { - packet, err := ibctestingcore.ReconstructPacketFromEvent(event) - require.NoError(chain.T, err) - sentPacketKey := GetSentPacketKey(packet.GetSequence(), packet.GetSourceChannel()) - chain.SentPackets[sentPacketKey] = packet - } - } -} - -// NextBlock sets the last header to the current header and increments the current header to be -// at the next block height. It does not update the time as that is handled by the Coordinator. -// It will call Endblock and Commit and apply the validator set changes to the next validators -// of the next block being created. This follows the Tendermint protocol of applying valset changes -// returned on block `n` to the validators of block `n+2`. -// It calls BeginBlock with the new block created before returning. -func (chain *TestChain) NextBlock() (abci.ResponseEndBlock, abci.ResponseCommit, abci.ResponseBeginBlock) { - ebRes := chain.App.EndBlock(abci.RequestEndBlock{Height: chain.CurrentHeader.Height}) - // store packets sent during EndBlock - chain.setSentPacketsFromEvents(ebRes.Events) - - cRes := chain.App.Commit() - - // val set changes returned from previous block get applied to the next validators - // of this block. See tendermint spec for details. - chain.Vals = chain.NextVals - chain.NextVals = ApplyValSetChanges(chain.T, chain.Vals, ebRes.ValidatorUpdates) - - // set the last header to the current header - // use nil trusted fields - chain.LastHeader = chain.CurrentTMClientHeader() - - // increment the current header - chain.CurrentHeader = tmproto.Header{ - ChainID: chain.ChainID, - Height: chain.App.LastBlockHeight() + 1, - AppHash: chain.App.LastCommitID().Hash, - // NOTE: the time is increased by the coordinator to maintain time synchrony amongst - // chains. - Time: chain.CurrentHeader.Time, - ValidatorsHash: chain.Vals.Hash(), - NextValidatorsHash: chain.NextVals.Hash(), - } - - bbRes := chain.App.BeginBlock(abci.RequestBeginBlock{Header: chain.CurrentHeader}) - // store packets sent during BeginBlock - chain.setSentPacketsFromEvents(bbRes.Events) - - return ebRes, cRes, bbRes -} - -// sendMsgs delivers a transaction through the application without returning the result. -func (chain *TestChain) sendMsgs(msgs ...sdk.Msg) error { - _, err := chain.SendMsgs(msgs...) - return err -} - -// SendMsgs delivers a transaction through the application. It updates the senders sequence -// number and updates the TestChain's headers. It returns the result and error if one -// occurred. -func (chain *TestChain) SendMsgs(msgs ...sdk.Msg) (*sdk.Result, error) { - // ensure the chain has the latest time - chain.Coordinator.UpdateTimeForChain(chain) - - _, r, err := simapp.SignAndDeliver( - chain.T, - chain.TxConfig, - chain.App.GetBaseApp(), - chain.GetContext().BlockHeader(), - msgs, - chain.ChainID, - []uint64{chain.SenderAccount.GetAccountNumber()}, - []uint64{chain.SenderAccount.GetSequence()}, - true, true, chain.SenderPrivKey, - ) - if err != nil { - return nil, err - } - // store packets sent during the execution of this transaction - chain.setSentPacketsFromEvents(r.Events) - - // NextBlock calls app.Commit() - chain.NextBlock() - - // increment sequence for successful transaction execution - err = chain.SenderAccount.SetSequence(chain.SenderAccount.GetSequence() + 1) - if err != nil { - return nil, err - } - - chain.Coordinator.IncrementTime() - - return r, nil -} - -// GetClientState retrieves the client state for the provided clientID. The client is -// expected to exist otherwise testing will fail. -func (chain *TestChain) GetClientState(clientID string) exported.ClientState { - clientState, found := chain.App.GetIBCKeeper().ClientKeeper.GetClientState(chain.GetContext(), clientID) - require.True(chain.T, found) - - return clientState -} - -// GetConsensusState retrieves the consensus state for the provided clientID and height. -// It will return a success boolean depending on if consensus state exists or not. -func (chain *TestChain) GetConsensusState(clientID string, height exported.Height) (exported.ConsensusState, bool) { - return chain.App.GetIBCKeeper().ClientKeeper.GetClientConsensusState(chain.GetContext(), clientID, height) -} - -// GetValsAtHeight will return the validator set of the chain at a given height. It will return -// a success boolean depending on if the validator set exists or not at that height. -func (chain *TestChain) GetValsAtHeight(height int64) (*tmtypes.ValidatorSet, bool) { - histInfo, ok := chain.App.GetStakingKeeper().GetHistoricalInfo(chain.GetContext(), height) - if !ok { - return nil, false - } - - valSet := stakingtypes.Validators(histInfo.Valset) - - tmValidators, err := teststaking.ToTmValidators(valSet, sdk.DefaultPowerReduction) - if err != nil { - panic(err) - } - return tmtypes.NewValidatorSet(tmValidators), true -} - -// GetAcknowledgement retrieves an acknowledgement for the provided packet. If the -// acknowledgement does not exist then testing will fail. -func (chain *TestChain) GetAcknowledgement(packet exported.PacketI) []byte { - ack, found := chain.App.GetIBCKeeper().ChannelKeeper.GetPacketAcknowledgement(chain.GetContext(), packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - require.True(chain.T, found) - - return ack -} - -// GetPrefix returns the prefix for used by a chain in connection creation -func (chain *TestChain) GetPrefix() commitmenttypes.MerklePrefix { - return commitmenttypes.NewMerklePrefix(chain.App.GetIBCKeeper().ConnectionKeeper.GetCommitmentPrefix().Bytes()) -} - -// ConstructUpdateTMClientHeader will construct a valid 07-tendermint Header to update the -// light client on the source chain. -func (chain *TestChain) ConstructUpdateTMClientHeader(counterparty *TestChain, clientID string) (*ibctmtypes.Header, error) { - return chain.ConstructUpdateTMClientHeaderWithTrustedHeight(counterparty, clientID, clienttypes.ZeroHeight()) -} - -// ConstructUpdateTMClientHeader will construct a valid 07-tendermint Header to update the -// light client on the source chain. -func (chain *TestChain) ConstructUpdateTMClientHeaderWithTrustedHeight(counterparty *TestChain, clientID string, trustedHeight clienttypes.Height) (*ibctmtypes.Header, error) { - header := counterparty.LastHeader - // Relayer must query for LatestHeight on client to get TrustedHeight if the trusted height is not set - if trustedHeight.IsZero() { - trustedHeight = chain.GetClientState(clientID).GetLatestHeight().(clienttypes.Height) - } - var ( - tmTrustedVals *tmtypes.ValidatorSet - ok bool - ) - // Once we get TrustedHeight from client, we must query the validators from the counterparty chain - // If the LatestHeight == LastHeader.Height, then TrustedValidators are current validators - // If LatestHeight < LastHeader.Height, we can query the historical validator set from HistoricalInfo - if trustedHeight == counterparty.LastHeader.GetHeight() { - tmTrustedVals = counterparty.Vals - } else { - // NOTE: We need to get validators from counterparty at height: trustedHeight+1 - // since the last trusted validators for a header at height h - // is the NextValidators at h+1 committed to in header h by - // NextValidatorsHash - tmTrustedVals, ok = counterparty.GetValsAtHeight(int64(trustedHeight.RevisionHeight + 1)) - if !ok { - return nil, sdkerrors.Wrapf(ibctmtypes.ErrInvalidHeaderHeight, "could not retrieve trusted validators at trustedHeight: %d", trustedHeight) - } - } - // inject trusted fields into last header - // for now assume revision number is 0 - header.TrustedHeight = trustedHeight - - trustedVals, err := tmTrustedVals.ToProto() - if err != nil { - return nil, err - } - header.TrustedValidators = trustedVals - - return header, nil -} - -// ExpireClient fast forwards the chain's block time by the provided amount of time which will -// expire any clients with a trusting period less than or equal to this amount of time. -func (chain *TestChain) ExpireClient(amount time.Duration) { - chain.Coordinator.IncrementTimeBy(amount) -} - -// CurrentTMClientHeader creates a TM header using the current header parameters -// on the chain. The trusted fields in the header are set to nil. -func (chain *TestChain) CurrentTMClientHeader() *ibctmtypes.Header { - return chain.CreateTMClientHeader(chain.ChainID, chain.CurrentHeader.Height, clienttypes.Height{}, chain.CurrentHeader.Time, chain.Vals, chain.NextVals, nil, chain.Signers) -} - -// CreateTMClientHeader creates a TM header to update the TM client. Args are passed in to allow -// caller flexibility to use params that differ from the chain. -func (chain *TestChain) CreateTMClientHeader(chainID string, blockHeight int64, trustedHeight clienttypes.Height, timestamp time.Time, tmValSet, nextVals, tmTrustedVals *tmtypes.ValidatorSet, signers map[string]tmtypes.PrivValidator) *ibctmtypes.Header { - var ( - valSet *tmproto.ValidatorSet - trustedVals *tmproto.ValidatorSet - ) - - if tmValSet == nil { - panic("tmValSet cannot be nil") - } - - vsetHash := tmValSet.Hash() - nextValHash := nextVals.Hash() - - tmHeader := tmtypes.Header{ - Version: tmprotoversion.Consensus{Block: tmversion.BlockProtocol, App: 2}, - ChainID: chainID, - Height: blockHeight, - Time: timestamp, - LastBlockID: MakeBlockID(make([]byte, tmhash.Size), 10000, make([]byte, tmhash.Size)), - LastCommitHash: chain.App.LastCommitID().Hash, - DataHash: tmhash.Sum([]byte("data_hash")), - ValidatorsHash: vsetHash, - NextValidatorsHash: nextValHash, - ConsensusHash: tmhash.Sum([]byte("consensus_hash")), - AppHash: chain.CurrentHeader.AppHash, - LastResultsHash: tmhash.Sum([]byte("last_results_hash")), - EvidenceHash: tmhash.Sum([]byte("evidence_hash")), - ProposerAddress: tmValSet.Proposer.Address, - } - - hhash := tmHeader.Hash() - blockID := MakeBlockID(hhash, 3, tmhash.Sum([]byte("part_set"))) - voteSet := tmtypes.NewVoteSet(chainID, blockHeight, 1, tmproto.PrecommitType, tmValSet) - - // MakeCommit expects a signer array in the same order as the validator array. - // Thus we iterate over the ordered validator set and construct a signer array - // from the signer map in the same order. - var signerArr []tmtypes.PrivValidator - - for _, v := range tmValSet.Validators { - if v == nil { - panic("validator in tmValSet cannot be nil") - } - signerArr = append(signerArr, signers[v.Address.String()]) - } - - commit, err := tmtypes.MakeCommit(blockID, blockHeight, 1, voteSet, signerArr, timestamp) - require.NoError(chain.T, err) - - signedHeader := &tmproto.SignedHeader{ - Header: tmHeader.ToProto(), - Commit: commit.ToProto(), - } - - if tmValSet != nil { - valSet, err = tmValSet.ToProto() - require.NoError(chain.T, err) - } - - if tmTrustedVals != nil { - trustedVals, err = tmTrustedVals.ToProto() - require.NoError(chain.T, err) - } - - // The trusted fields may be nil. They may be filled before relaying messages to a client. - // The relayer is responsible for querying client and injecting appropriate trusted fields. - return &ibctmtypes.Header{ - SignedHeader: signedHeader, - ValidatorSet: valSet, - TrustedHeight: trustedHeight, - TrustedValidators: trustedVals, - } -} - -// MakeBlockID copied unimported test functions from tmtypes to use them here -func MakeBlockID(hash []byte, partSetSize uint32, partSetHash []byte) tmtypes.BlockID { - return tmtypes.BlockID{ - Hash: hash, - PartSetHeader: tmtypes.PartSetHeader{ - Total: partSetSize, - Hash: partSetHash, - }, - } -} - -// CreateSortedSignerArray takes two PrivValidators, and the corresponding Validator structs -// (including voting power). It returns a signer array of PrivValidators that matches the -// sorting of ValidatorSet. -// The sorting is first by .VotingPower (descending), with secondary index of .Address (ascending). -func CreateSortedSignerArray(altPrivVal, suitePrivVal tmtypes.PrivValidator, - altVal, suiteVal *tmtypes.Validator, -) []tmtypes.PrivValidator { - switch { - case altVal.VotingPower > suiteVal.VotingPower: - return []tmtypes.PrivValidator{altPrivVal, suitePrivVal} - case altVal.VotingPower < suiteVal.VotingPower: - return []tmtypes.PrivValidator{suitePrivVal, altPrivVal} - default: - if bytes.Compare(altVal.Address, suiteVal.Address) == -1 { - return []tmtypes.PrivValidator{altPrivVal, suitePrivVal} - } - return []tmtypes.PrivValidator{suitePrivVal, altPrivVal} - } -} - -// CreatePortCapability binds and claims a capability for the given portID if it does not -// already exist. This function will fail testing on any resulting error. -// NOTE: only creation of a capability for a transfer or mock port is supported -// Other applications must bind to the port in InitGenesis or modify this code. -func (chain *TestChain) CreatePortCapability(scopedKeeper capabilitykeeper.ScopedKeeper, portID string) { - // check if the portId is already binded, if not bind it - _, ok := chain.App.GetScopedIBCKeeper().GetCapability(chain.GetContext(), host.PortPath(portID)) - if !ok { - // create capability using the IBC capability keeper - cap, err := chain.App.GetScopedIBCKeeper().NewCapability(chain.GetContext(), host.PortPath(portID)) - require.NoError(chain.T, err) - - // claim capability using the scopedKeeper - err = scopedKeeper.ClaimCapability(chain.GetContext(), cap, host.PortPath(portID)) - require.NoError(chain.T, err) - } - - chain.NextBlock() -} - -// GetPortCapability returns the port capability for the given portID. The capability must -// exist, otherwise testing will fail. -func (chain *TestChain) GetPortCapability(portID string) *capabilitytypes.Capability { - cap, ok := chain.App.GetScopedIBCKeeper().GetCapability(chain.GetContext(), host.PortPath(portID)) - require.True(chain.T, ok) - - return cap -} - -// CreateChannelCapability binds and claims a capability for the given portID and channelID -// if it does not already exist. This function will fail testing on any resulting error. The -// scoped keeper passed in will claim the new capability. -func (chain *TestChain) CreateChannelCapability(scopedKeeper capabilitykeeper.ScopedKeeper, portID, channelID string) { - capName := host.ChannelCapabilityPath(portID, channelID) - // check if the portId is already binded, if not bind it - _, ok := chain.App.GetScopedIBCKeeper().GetCapability(chain.GetContext(), capName) - if !ok { - cap, err := chain.App.GetScopedIBCKeeper().NewCapability(chain.GetContext(), capName) - require.NoError(chain.T, err) - err = scopedKeeper.ClaimCapability(chain.GetContext(), cap, capName) - require.NoError(chain.T, err) - } - - chain.NextBlock() -} - -// GetChannelCapability returns the channel capability for the given portID and channelID. -// The capability must exist, otherwise testing will fail. -func (chain *TestChain) GetChannelCapability(portID, channelID string) *capabilitytypes.Capability { - cap, ok := chain.App.GetScopedIBCKeeper().GetCapability(chain.GetContext(), host.ChannelCapabilityPath(portID, channelID)) - require.True(chain.T, ok) - - return cap -} - -// GetTimeoutHeight is a convenience function which returns a IBC packet timeout height -// to be used for testing. It returns the current IBC height + 100 blocks -func (chain *TestChain) GetTimeoutHeight() clienttypes.Height { - return clienttypes.NewHeight(clienttypes.ParseChainID(chain.ChainID), uint64(chain.GetContext().BlockHeight())+100) -} diff --git a/legacy_ibc_testing/testing/config.go b/legacy_ibc_testing/testing/config.go deleted file mode 100644 index dffe01053f..0000000000 --- a/legacy_ibc_testing/testing/config.go +++ /dev/null @@ -1,72 +0,0 @@ -package testing - -import ( - "time" - - connectiontypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types" - channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" - "github.com/cosmos/ibc-go/v7/modules/core/exported" - ibctmtypes "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" - "github.com/cosmos/ibc-go/v7/testing/mock" -) - -/* -TODO: Remove after upgrading to ibc-go v5 -legacy_ibc_testing is temporarily copied into the interchain-security repository for the purpose of testing only. -The integration test suites rely on modifications to ibc-go's test framework that cannot be back-ported to the canonical version that ics will rely on. -These files will be deprecated once ICS is able to upgrade to ibc-go v5. -*/ - -type ClientConfig interface { - GetClientType() string -} - -type TendermintConfig struct { - TrustLevel ibctmtypes.Fraction - TrustingPeriod time.Duration - UnbondingPeriod time.Duration - MaxClockDrift time.Duration - AllowUpdateAfterExpiry bool - AllowUpdateAfterMisbehaviour bool -} - -func NewTendermintConfig() *TendermintConfig { - return &TendermintConfig{ - TrustLevel: DefaultTrustLevel, - TrustingPeriod: TrustingPeriod, - UnbondingPeriod: UnbondingPeriod, - MaxClockDrift: MaxClockDrift, - AllowUpdateAfterExpiry: false, - AllowUpdateAfterMisbehaviour: false, - } -} - -func (tmcfg *TendermintConfig) GetClientType() string { - return exported.Tendermint -} - -type ConnectionConfig struct { - DelayPeriod uint64 - Version *connectiontypes.Version -} - -func NewConnectionConfig() *ConnectionConfig { - return &ConnectionConfig{ - DelayPeriod: DefaultDelayPeriod, - Version: ConnectionVersion, - } -} - -type ChannelConfig struct { - PortID string - Version string - Order channeltypes.Order -} - -func NewChannelConfig() *ChannelConfig { - return &ChannelConfig{ - PortID: mock.PortID, - Version: DefaultChannelVersion, - Order: channeltypes.UNORDERED, - } -} diff --git a/legacy_ibc_testing/testing/coordinator.go b/legacy_ibc_testing/testing/coordinator.go deleted file mode 100644 index 4aee8f8923..0000000000 --- a/legacy_ibc_testing/testing/coordinator.go +++ /dev/null @@ -1,252 +0,0 @@ -package testing - -import ( - "fmt" - "strconv" - "testing" - "time" - - abci "github.com/cometbft/cometbft/abci/types" - "github.com/stretchr/testify/require" -) - -/* -TODO: Remove after upgrading to ibc-go v5 -legacy_ibc_testing is temporarily copied into the interchain-security repository for the purpose of testing only. -The integration test suites rely on modifications to ibc-go's test framework that cannot be back-ported to the canonical version that ics will rely on. -These files will be deprecated once ICS is able to upgrade to ibc-go v5. -*/ - -var ( - ChainIDPrefix = "testchain" - GlobalStartTime = time.Date(2020, 1, 2, 0, 0, 0, 0, time.UTC) - TimeIncrement = time.Second * 5 -) - -// Coordinator is a testing struct which contains N TestChain's. It handles keeping all chains -// in sync with regards to time. -type Coordinator struct { - *testing.T - - CurrentTime time.Time - Chains map[string]*TestChain -} - -// NewCoordinator initializes Coordinator with N TestChain's -func NewCoordinator(t *testing.T, n int) *Coordinator { - t.Helper() - chains := make(map[string]*TestChain) - coord := &Coordinator{ - T: t, - CurrentTime: GlobalStartTime, - } - - for i := 1; i <= n; i++ { - chainID := GetChainID(i) - chains[chainID] = NewTestChain(t, coord, DefaultTestingAppInit, chainID) - } - coord.Chains = chains - - return coord -} - -// IncrementTime iterates through all the TestChain's and increments their current header time -// by 5 seconds. -// -// CONTRACT: this function must be called after every Commit on any TestChain. -func (coord *Coordinator) IncrementTime() { - coord.IncrementTimeBy(TimeIncrement) -} - -// IncrementTimeBy iterates through all the TestChain's and increments their current header time -// by specified time. -func (coord *Coordinator) IncrementTimeBy(increment time.Duration) { - coord.CurrentTime = coord.CurrentTime.Add(increment).UTC() - coord.UpdateTime() -} - -// UpdateTime updates all clocks for the TestChains to the current global time. -func (coord *Coordinator) UpdateTime() { - for _, chain := range coord.Chains { - coord.UpdateTimeForChain(chain) - } -} - -// UpdateTimeForChain updates the clock for a specific chain. -func (coord *Coordinator) UpdateTimeForChain(chain *TestChain) { - chain.CurrentHeader.Time = coord.CurrentTime.UTC() - chain.App.BeginBlock(abci.RequestBeginBlock{Header: chain.CurrentHeader}) -} - -// Setup constructs a TM client, connection, and channel on both chains provided. It will -// fail if any error occurs. The clientID's, TestConnections, and TestChannels are returned -// for both chains. The channels created are connected to the ibc-transfer application. -func (coord *Coordinator) Setup(path *Path) { - coord.SetupConnections(path) - - // channels can also be referenced through the returned connections - coord.CreateChannels(path) -} - -// SetupClients is a helper function to create clients on both chains. It assumes the -// caller does not anticipate any errors. -func (coord *Coordinator) SetupClients(path *Path) { - err := path.EndpointA.CreateClient() - require.NoError(coord.T, err) - - err = path.EndpointB.CreateClient() - require.NoError(coord.T, err) -} - -// SetupClientConnections is a helper function to create clients and the appropriate -// connections on both the source and counterparty chain. It assumes the caller does not -// anticipate any errors. -func (coord *Coordinator) SetupConnections(path *Path) { - coord.SetupClients(path) - - coord.CreateConnections(path) -} - -// CreateConnection constructs and executes connection handshake messages in order to create -// OPEN channels on chainA and chainB. The connection information of for chainA and chainB -// are returned within a TestConnection struct. The function expects the connections to be -// successfully opened otherwise testing will fail. -func (coord *Coordinator) CreateConnections(path *Path) { - err := path.EndpointA.ConnOpenInit() - require.NoError(coord.T, err) - - err = path.EndpointB.ConnOpenTry() - require.NoError(coord.T, err) - - err = path.EndpointA.ConnOpenAck() - require.NoError(coord.T, err) - - err = path.EndpointB.ConnOpenConfirm() - require.NoError(coord.T, err) - - // ensure counterparty is up to date - err = path.EndpointA.UpdateClient() - require.NoError(coord.T, err) -} - -// CreateMockChannels constructs and executes channel handshake messages to create OPEN -// channels that use a mock application module that returns nil on all callbacks. This -// function is expects the channels to be successfully opened otherwise testing will -// fail. -func (coord *Coordinator) CreateMockChannels(path *Path) { - path.EndpointA.ChannelConfig.PortID = MockPort - path.EndpointB.ChannelConfig.PortID = MockPort - - coord.CreateChannels(path) -} - -// CreateTransferChannels constructs and executes channel handshake messages to create OPEN -// ibc-transfer channels on chainA and chainB. The function expects the channels to be -// successfully opened otherwise testing will fail. -func (coord *Coordinator) CreateTransferChannels(path *Path) { - path.EndpointA.ChannelConfig.PortID = TransferPort - path.EndpointB.ChannelConfig.PortID = TransferPort - - coord.CreateChannels(path) -} - -// CreateChannel constructs and executes channel handshake messages in order to create -// OPEN channels on chainA and chainB. The function expects the channels to be successfully -// opened otherwise testing will fail. -func (coord *Coordinator) CreateChannels(path *Path) { - err := path.EndpointA.ChanOpenInit() - require.NoError(coord.T, err) - - err = path.EndpointB.ChanOpenTry() - require.NoError(coord.T, err) - - err = path.EndpointA.ChanOpenAck() - require.NoError(coord.T, err) - - err = path.EndpointB.ChanOpenConfirm() - require.NoError(coord.T, err) - - // ensure counterparty is up to date - err = path.EndpointA.UpdateClient() - require.NoError(coord.T, err) -} - -// GetChain returns the TestChain using the given chainID and returns an error if it does -// not exist. -func (coord *Coordinator) GetChain(chainID string) *TestChain { - chain, found := coord.Chains[chainID] - require.True(coord.T, found, fmt.Sprintf("%s chain does not exist", chainID)) - return chain -} - -// GetChainID returns the chainID used for the provided index. -func GetChainID(index int) string { - return ChainIDPrefix + strconv.Itoa(index) -} - -// CommitBlock commits a block on the provided indexes and then increments the global time. -// -// CONTRACT: the passed in list of indexes must not contain duplicates -func (coord *Coordinator) CommitBlock(chains ...*TestChain) { - for _, chain := range chains { - // NextBlock calls app.Commit() - chain.NextBlock() - } - coord.IncrementTime() -} - -// CommitNBlocks commits n blocks to state and updates the block height by 1 for each commit. -func (coord *Coordinator) CommitNBlocks(chain *TestChain, n uint64) { - for i := uint64(0); i < n; i++ { - chain.NextBlock() - coord.IncrementTime() - } -} - -// CommitBlockGetResponses commits a block and provides abci responses -func (coord *Coordinator) CommitBlockGetResponses(chain *TestChain) ( - abci.ResponseEndBlock, abci.ResponseCommit, abci.ResponseBeginBlock, -) { - ebRes, cRes, bbResp := chain.NextBlock() - coord.IncrementTime() - return ebRes, cRes, bbResp -} - -// ConnOpenInitOnBothChains initializes a connection on both endpoints with the state INIT -// using the OpenInit handshake call. -func (coord *Coordinator) ConnOpenInitOnBothChains(path *Path) error { - if err := path.EndpointA.ConnOpenInit(); err != nil { - return err - } - - if err := path.EndpointB.ConnOpenInit(); err != nil { - return err - } - - if err := path.EndpointA.UpdateClient(); err != nil { - return err - } - - return path.EndpointB.UpdateClient() -} - -// ChanOpenInitOnBothChains initializes a channel on the source chain and counterparty chain -// with the state INIT using the OpenInit handshake call. -func (coord *Coordinator) ChanOpenInitOnBothChains(path *Path) error { - // NOTE: only creation of a capability for a transfer or mock port is supported - // Other applications must bind to the port in InitGenesis or modify this code. - - if err := path.EndpointA.ChanOpenInit(); err != nil { - return err - } - - if err := path.EndpointB.ChanOpenInit(); err != nil { - return err - } - - if err := path.EndpointA.UpdateClient(); err != nil { - return err - } - - return path.EndpointB.UpdateClient() -} diff --git a/legacy_ibc_testing/testing/endpoint.go b/legacy_ibc_testing/testing/endpoint.go deleted file mode 100644 index c3f2ac9abb..0000000000 --- a/legacy_ibc_testing/testing/endpoint.go +++ /dev/null @@ -1,581 +0,0 @@ -package testing - -import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/stretchr/testify/require" - - clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" - connectiontypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types" - channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" - commitmenttypes "github.com/cosmos/ibc-go/v7/modules/core/23-commitment/types" - host "github.com/cosmos/ibc-go/v7/modules/core/24-host" - "github.com/cosmos/ibc-go/v7/modules/core/exported" - ibctmtypes "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" -) - -/* -TODO: Remove after upgrading to ibc-go v5 -legacy_ibc_testing is temporarily copied into the interchain-security repository for the purpose of testing only. -The integration test suites rely on modifications to ibc-go's test framework that cannot be back-ported to the canonical version that ics will rely on. -These files will be deprecated once ICS is able to upgrade to ibc-go v5. -*/ - -// Endpoint is a which represents a channel endpoint and its associated -// client and connections. It contains client, connection, and channel -// configuration parameters. Endpoint functions will utilize the parameters -// set in the configuration structs when executing IBC messages. -type Endpoint struct { - Chain *TestChain - Counterparty *Endpoint - ClientID string - ConnectionID string - ChannelID string - - ClientConfig ClientConfig - ConnectionConfig *ConnectionConfig - ChannelConfig *ChannelConfig -} - -// NewDefaultEndpoint constructs a new endpoint using default values. -// CONTRACT: the counterparty endpoitn must be set by the caller. -func NewDefaultEndpoint(chain *TestChain) *Endpoint { - return &Endpoint{ - Chain: chain, - ClientConfig: NewTendermintConfig(), - ConnectionConfig: NewConnectionConfig(), - ChannelConfig: NewChannelConfig(), - } -} - -// QueryProof queries proof associated with this endpoint using the lastest client state -// height on the counterparty chain. -func (endpoint *Endpoint) QueryProof(key []byte) ([]byte, clienttypes.Height) { - // obtain the counterparty client representing the chain associated with the endpoint - clientState := endpoint.Counterparty.Chain.GetClientState(endpoint.Counterparty.ClientID) - - // query proof on the counterparty using the latest height of the IBC client - return endpoint.QueryProofAtHeight(key, clientState.GetLatestHeight().GetRevisionHeight()) -} - -// QueryProofAtHeight queries proof associated with this endpoint using the proof height -// provided -func (endpoint *Endpoint) QueryProofAtHeight(key []byte, height uint64) ([]byte, clienttypes.Height) { - // query proof on the counterparty using the latest height of the IBC client - return endpoint.Chain.QueryProofAtHeight(key, int64(height)) -} - -// CreateClient creates an IBC client on the endpoint. It will update the -// clientID for the endpoint if the message is successfully executed. -// NOTE: a solo machine client will be created with an empty diversifier. -func (endpoint *Endpoint) CreateClient() (err error) { - // ensure counterparty has committed state - endpoint.Chain.Coordinator.CommitBlock(endpoint.Counterparty.Chain) - - var ( - clientState exported.ClientState - consensusState exported.ConsensusState - ) - - switch endpoint.ClientConfig.GetClientType() { - case exported.Tendermint: - tmConfig, ok := endpoint.ClientConfig.(*TendermintConfig) - require.True(endpoint.Chain.T, ok) - - height := endpoint.Counterparty.Chain.LastHeader.GetHeight().(clienttypes.Height) - clientState = ibctmtypes.NewClientState( - endpoint.Counterparty.Chain.ChainID, tmConfig.TrustLevel, tmConfig.TrustingPeriod, tmConfig.UnbondingPeriod, tmConfig.MaxClockDrift, - height, commitmenttypes.GetSDKSpecs(), UpgradePath, - ) - consensusState = endpoint.Counterparty.Chain.LastHeader.ConsensusState() - case exported.Solomachine: - // TODO - // solo := NewSolomachine(endpoint.Chain.T, endpoint.Chain.Codec, clientID, "", 1) - // clientState = solo.ClientState() - // consensusState = solo.ConsensusState() - - default: - err = fmt.Errorf("client type %s is not supported", endpoint.ClientConfig.GetClientType()) - } - - if err != nil { - return err - } - - msg, err := clienttypes.NewMsgCreateClient( - clientState, consensusState, endpoint.Chain.SenderAccount.GetAddress().String(), - ) - require.NoError(endpoint.Chain.T, err) - - res, err := endpoint.Chain.SendMsgs(msg) - if err != nil { - return err - } - - endpoint.ClientID, err = ParseClientIDFromEvents(res.GetEvents()) - require.NoError(endpoint.Chain.T, err) - - return nil -} - -// UpdateClient updates the IBC client associated with the endpoint. -func (endpoint *Endpoint) UpdateClient() (err error) { - // ensure counterparty has committed state - endpoint.Chain.Coordinator.CommitBlock(endpoint.Counterparty.Chain) - - var header *ibctmtypes.Header - - switch endpoint.ClientConfig.GetClientType() { - case exported.Tendermint: - header, err = endpoint.Chain.ConstructUpdateTMClientHeader(endpoint.Counterparty.Chain, endpoint.ClientID) - - default: - err = fmt.Errorf("client type %s is not supported", endpoint.ClientConfig.GetClientType()) - } - - if err != nil { - return err - } - - msg, err := clienttypes.NewMsgUpdateClient( - endpoint.ClientID, header, - endpoint.Chain.SenderAccount.GetAddress().String(), - ) - require.NoError(endpoint.Chain.T, err) - - return endpoint.Chain.sendMsgs(msg) -} - -// ConnOpenInit will construct and execute a MsgConnectionOpenInit on the associated endpoint. -func (endpoint *Endpoint) ConnOpenInit() error { - msg := connectiontypes.NewMsgConnectionOpenInit( - endpoint.ClientID, - endpoint.Counterparty.ClientID, - endpoint.Counterparty.Chain.GetPrefix(), DefaultOpenInitVersion, endpoint.ConnectionConfig.DelayPeriod, - endpoint.Chain.SenderAccount.GetAddress().String(), - ) - res, err := endpoint.Chain.SendMsgs(msg) - if err != nil { - return err - } - - endpoint.ConnectionID, err = ParseConnectionIDFromEvents(res.GetEvents()) - require.NoError(endpoint.Chain.T, err) - - return nil -} - -// ConnOpenTry will construct and execute a MsgConnectionOpenTry on the associated endpoint. -func (endpoint *Endpoint) ConnOpenTry() error { - err := endpoint.UpdateClient() - require.NoError(endpoint.Chain.T, err) - - counterpartyClient, proofClient, proofConsensus, consensusHeight, proofInit, proofHeight := endpoint.QueryConnectionHandshakeProof() - - msg := connectiontypes.NewMsgConnectionOpenTry( - endpoint.ClientID, // does not support handshake continuation - endpoint.Counterparty.ConnectionID, - endpoint.Counterparty.ClientID, - counterpartyClient, - endpoint.Counterparty.Chain.GetPrefix(), - []*connectiontypes.Version{ConnectionVersion}, - endpoint.ConnectionConfig.DelayPeriod, - proofInit, proofClient, proofConsensus, - proofHeight, consensusHeight, - endpoint.Chain.SenderAccount.GetAddress().String(), - ) - res, err := endpoint.Chain.SendMsgs(msg) - if err != nil { - return err - } - - if endpoint.ConnectionID == "" { - endpoint.ConnectionID, err = ParseConnectionIDFromEvents(res.GetEvents()) - require.NoError(endpoint.Chain.T, err) - } - - return nil -} - -// ConnOpenAck will construct and execute a MsgConnectionOpenAck on the associated endpoint. -func (endpoint *Endpoint) ConnOpenAck() error { - err := endpoint.UpdateClient() - require.NoError(endpoint.Chain.T, err) - - counterpartyClient, proofClient, proofConsensus, consensusHeight, proofTry, proofHeight := endpoint.QueryConnectionHandshakeProof() - - msg := connectiontypes.NewMsgConnectionOpenAck( - endpoint.ConnectionID, endpoint.Counterparty.ConnectionID, counterpartyClient, // testing doesn't use flexible selection - proofTry, proofClient, proofConsensus, - proofHeight, consensusHeight, - ConnectionVersion, - endpoint.Chain.SenderAccount.GetAddress().String(), - ) - return endpoint.Chain.sendMsgs(msg) -} - -// ConnOpenConfirm will construct and execute a MsgConnectionOpenConfirm on the associated endpoint. -func (endpoint *Endpoint) ConnOpenConfirm() error { - err := endpoint.UpdateClient() - require.NoError(endpoint.Chain.T, err) - - connectionKey := host.ConnectionKey(endpoint.Counterparty.ConnectionID) - proof, height := endpoint.Counterparty.Chain.QueryProof(connectionKey) - - msg := connectiontypes.NewMsgConnectionOpenConfirm( - endpoint.ConnectionID, - proof, height, - endpoint.Chain.SenderAccount.GetAddress().String(), - ) - return endpoint.Chain.sendMsgs(msg) -} - -// QueryConnectionHandshakeProof returns all the proofs necessary to execute OpenTry or Open Ack of -// the connection handshakes. It returns the counterparty client state, proof of the counterparty -// client state, proof of the counterparty consensus state, the consensus state height, proof of -// the counterparty connection, and the proof height for all the proofs returned. -func (endpoint *Endpoint) QueryConnectionHandshakeProof() ( - clientState exported.ClientState, proofClient, - proofConsensus []byte, consensusHeight clienttypes.Height, - proofConnection []byte, proofHeight clienttypes.Height, -) { - // obtain the client state on the counterparty chain - clientState = endpoint.Counterparty.Chain.GetClientState(endpoint.Counterparty.ClientID) - - // query proof for the client state on the counterparty - clientKey := host.FullClientStateKey(endpoint.Counterparty.ClientID) - proofClient, proofHeight = endpoint.Counterparty.QueryProof(clientKey) - - consensusHeight = clientState.GetLatestHeight().(clienttypes.Height) - - // query proof for the consensus state on the counterparty - consensusKey := host.FullConsensusStateKey(endpoint.Counterparty.ClientID, consensusHeight) - proofConsensus, _ = endpoint.Counterparty.QueryProofAtHeight(consensusKey, proofHeight.GetRevisionHeight()) - - // query proof for the connection on the counterparty - connectionKey := host.ConnectionKey(endpoint.Counterparty.ConnectionID) - proofConnection, _ = endpoint.Counterparty.QueryProofAtHeight(connectionKey, proofHeight.GetRevisionHeight()) - - return -} - -// ChanOpenInit will construct and execute a MsgChannelOpenInit on the associated endpoint. -func (endpoint *Endpoint) ChanOpenInit() error { - msg := channeltypes.NewMsgChannelOpenInit( - endpoint.ChannelConfig.PortID, - endpoint.ChannelConfig.Version, endpoint.ChannelConfig.Order, []string{endpoint.ConnectionID}, - endpoint.Counterparty.ChannelConfig.PortID, - endpoint.Chain.SenderAccount.GetAddress().String(), - ) - res, err := endpoint.Chain.SendMsgs(msg) - if err != nil { - return err - } - - endpoint.ChannelID, err = ParseChannelIDFromEvents(res.GetEvents()) - require.NoError(endpoint.Chain.T, err) - - return nil -} - -// ChanOpenTry will construct and execute a MsgChannelOpenTry on the associated endpoint. -func (endpoint *Endpoint) ChanOpenTry() error { - err := endpoint.UpdateClient() - require.NoError(endpoint.Chain.T, err) - - channelKey := host.ChannelKey(endpoint.Counterparty.ChannelConfig.PortID, endpoint.Counterparty.ChannelID) - proof, height := endpoint.Counterparty.Chain.QueryProof(channelKey) - - msg := channeltypes.NewMsgChannelOpenTry( - endpoint.ChannelConfig.PortID, // does not support handshake continuation - endpoint.ChannelConfig.Version, - endpoint.ChannelConfig.Order, - []string{endpoint.ConnectionID}, - endpoint.Counterparty.ChannelConfig.PortID, - endpoint.Counterparty.ChannelID, - endpoint.Counterparty.ChannelConfig.Version, - proof, height, - endpoint.Chain.SenderAccount.GetAddress().String(), - ) - res, err := endpoint.Chain.SendMsgs(msg) - if err != nil { - return err - } - - if endpoint.ChannelID == "" { - endpoint.ChannelID, err = ParseChannelIDFromEvents(res.GetEvents()) - require.NoError(endpoint.Chain.T, err) - } - - // update version to selected app version - // NOTE: this update must be performed after the endpoint channelID is set - endpoint.ChannelConfig.Version = endpoint.GetChannel().Version - - return nil -} - -// ChanOpenAck will construct and execute a MsgChannelOpenAck on the associated endpoint. -func (endpoint *Endpoint) ChanOpenAck() error { - err := endpoint.UpdateClient() - require.NoError(endpoint.Chain.T, err) - - channelKey := host.ChannelKey(endpoint.Counterparty.ChannelConfig.PortID, endpoint.Counterparty.ChannelID) - proof, height := endpoint.Counterparty.Chain.QueryProof(channelKey) - - msg := channeltypes.NewMsgChannelOpenAck( - endpoint.ChannelConfig.PortID, endpoint.ChannelID, - endpoint.Counterparty.ChannelID, endpoint.Counterparty.ChannelConfig.Version, // testing doesn't use flexible selection - proof, height, - endpoint.Chain.SenderAccount.GetAddress().String(), - ) - return endpoint.Chain.sendMsgs(msg) -} - -// ChanOpenConfirm will construct and execute a MsgChannelOpenConfirm on the associated endpoint. -func (endpoint *Endpoint) ChanOpenConfirm() error { - err := endpoint.UpdateClient() - require.NoError(endpoint.Chain.T, err) - - channelKey := host.ChannelKey(endpoint.Counterparty.ChannelConfig.PortID, endpoint.Counterparty.ChannelID) - proof, height := endpoint.Counterparty.Chain.QueryProof(channelKey) - - msg := channeltypes.NewMsgChannelOpenConfirm( - endpoint.ChannelConfig.PortID, endpoint.ChannelID, - proof, height, - endpoint.Chain.SenderAccount.GetAddress().String(), - ) - return endpoint.Chain.sendMsgs(msg) -} - -// ChanCloseInit will construct and execute a MsgChannelCloseInit on the associated endpoint. -// -// NOTE: does not work with ibc-transfer module -func (endpoint *Endpoint) ChanCloseInit() error { - msg := channeltypes.NewMsgChannelCloseInit( - endpoint.ChannelConfig.PortID, endpoint.ChannelID, - endpoint.Chain.SenderAccount.GetAddress().String(), - ) - return endpoint.Chain.sendMsgs(msg) -} - -// SendPacket sends a packet through the channel keeper using the associated endpoint -// The counterparty client is updated so proofs can be sent to the counterparty chain. -func (endpoint *Endpoint) SendPacket(packet exported.PacketI) error { - channelCap := endpoint.Chain.GetChannelCapability(packet.GetSourcePort(), packet.GetSourceChannel()) - - timeoutHeight := clienttypes.Height{ - RevisionNumber: packet.GetTimeoutHeight().GetRevisionNumber(), - RevisionHeight: packet.GetTimeoutHeight().GetRevisionHeight(), - } - - // no need to send message, acting as a module - _, err := endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.SendPacket(endpoint.Chain.GetContext(), - channelCap, packet.GetSourcePort(), - packet.GetSourceChannel(), - timeoutHeight, - packet.GetTimeoutTimestamp(), - packet.GetData()) - if err != nil { - return err - } - - // commit changes since no message was sent - endpoint.Chain.Coordinator.CommitBlock(endpoint.Chain) - - return endpoint.Counterparty.UpdateClient() -} - -// RecvPacket receives a packet on the associated endpoint. -// The counterparty client is updated. -func (endpoint *Endpoint) RecvPacket(packet channeltypes.Packet) error { - _, err := endpoint.RecvPacketWithResult(packet) - if err != nil { - return err - } - - return nil -} - -// RecvPacketWithResult receives a packet on the associated endpoint and the result -// of the transaction is returned. The counterparty client is updated. -func (endpoint *Endpoint) RecvPacketWithResult(packet channeltypes.Packet) (*sdk.Result, error) { - // get proof of packet commitment on source - packetKey := host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - proof, proofHeight := endpoint.Counterparty.Chain.QueryProof(packetKey) - - recvMsg := channeltypes.NewMsgRecvPacket(packet, proof, proofHeight, endpoint.Chain.SenderAccount.GetAddress().String()) - - // receive on counterparty and update source client - res, err := endpoint.Chain.SendMsgs(recvMsg) - if err != nil { - return nil, err - } - - if err := endpoint.Counterparty.UpdateClient(); err != nil { - return nil, err - } - - return res, nil -} - -// WriteAcknowledgement writes an acknowledgement on the channel associated with the endpoint. -// The counterparty client is updated. -func (endpoint *Endpoint) WriteAcknowledgement(ack exported.Acknowledgement, packet exported.PacketI) error { - channelCap := endpoint.Chain.GetChannelCapability(packet.GetDestPort(), packet.GetDestChannel()) - - // no need to send message, acting as a handler - err := endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.WriteAcknowledgement(endpoint.Chain.GetContext(), channelCap, packet, ack) - if err != nil { - return err - } - - // commit changes since no message was sent - endpoint.Chain.Coordinator.CommitBlock(endpoint.Chain) - - return endpoint.Counterparty.UpdateClient() -} - -// AcknowledgePacket sends a MsgAcknowledgement to the channel associated with the endpoint. -func (endpoint *Endpoint) AcknowledgePacket(packet channeltypes.Packet, ack []byte) error { - // get proof of acknowledgement on counterparty - packetKey := host.PacketAcknowledgementKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - proof, proofHeight := endpoint.Counterparty.QueryProof(packetKey) - - ackMsg := channeltypes.NewMsgAcknowledgement(packet, ack, proof, proofHeight, endpoint.Chain.SenderAccount.GetAddress().String()) - - return endpoint.Chain.sendMsgs(ackMsg) -} - -// TimeoutPacket sends a MsgTimeout to the channel associated with the endpoint. -func (endpoint *Endpoint) TimeoutPacket(packet channeltypes.Packet) error { - // get proof for timeout based on channel order - var packetKey []byte - - switch endpoint.ChannelConfig.Order { - case channeltypes.ORDERED: - packetKey = host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel()) - case channeltypes.UNORDERED: - packetKey = host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - default: - return fmt.Errorf("unsupported order type %s", endpoint.ChannelConfig.Order) - } - - proof, proofHeight := endpoint.Counterparty.QueryProof(packetKey) - nextSeqRecv, found := endpoint.Counterparty.Chain.App.GetIBCKeeper().ChannelKeeper.GetNextSequenceRecv(endpoint.Counterparty.Chain.GetContext(), endpoint.ChannelConfig.PortID, endpoint.ChannelID) - require.True(endpoint.Chain.T, found) - - timeoutMsg := channeltypes.NewMsgTimeout( - packet, nextSeqRecv, - proof, proofHeight, endpoint.Chain.SenderAccount.GetAddress().String(), - ) - - return endpoint.Chain.sendMsgs(timeoutMsg) -} - -// TimeoutOnClose sends a MsgTimeoutOnClose to the channel associated with the endpoint. -func (endpoint *Endpoint) TimeoutOnClose(packet channeltypes.Packet) error { - // get proof for timeout based on channel order - var packetKey []byte - - switch endpoint.ChannelConfig.Order { - case channeltypes.ORDERED: - packetKey = host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel()) - case channeltypes.UNORDERED: - packetKey = host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - default: - return fmt.Errorf("unsupported order type %s", endpoint.ChannelConfig.Order) - } - - proof, proofHeight := endpoint.Counterparty.QueryProof(packetKey) - - channelKey := host.ChannelKey(packet.GetDestPort(), packet.GetDestChannel()) - proofClosed, _ := endpoint.Counterparty.QueryProof(channelKey) - - nextSeqRecv, found := endpoint.Counterparty.Chain.App.GetIBCKeeper().ChannelKeeper.GetNextSequenceRecv(endpoint.Counterparty.Chain.GetContext(), endpoint.ChannelConfig.PortID, endpoint.ChannelID) - require.True(endpoint.Chain.T, found) - - timeoutOnCloseMsg := channeltypes.NewMsgTimeoutOnClose( - packet, nextSeqRecv, - proof, proofClosed, proofHeight, endpoint.Chain.SenderAccount.GetAddress().String(), - ) - - return endpoint.Chain.sendMsgs(timeoutOnCloseMsg) -} - -// SetChannelClosed sets a channel state to CLOSED. -func (endpoint *Endpoint) SetChannelClosed() error { - channel := endpoint.GetChannel() - - channel.State = channeltypes.CLOSED - endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.SetChannel(endpoint.Chain.GetContext(), endpoint.ChannelConfig.PortID, endpoint.ChannelID, channel) - - endpoint.Chain.Coordinator.CommitBlock(endpoint.Chain) - - return endpoint.Counterparty.UpdateClient() -} - -// GetClientState retrieves the Client State for this endpoint. The -// client state is expected to exist otherwise testing will fail. -func (endpoint *Endpoint) GetClientState() exported.ClientState { - return endpoint.Chain.GetClientState(endpoint.ClientID) -} - -// SetClientState sets the client state for this endpoint. -func (endpoint *Endpoint) SetClientState(clientState exported.ClientState) { - endpoint.Chain.App.GetIBCKeeper().ClientKeeper.SetClientState(endpoint.Chain.GetContext(), endpoint.ClientID, clientState) -} - -// GetConsensusState retrieves the Consensus State for this endpoint at the provided height. -// The consensus state is expected to exist otherwise testing will fail. -func (endpoint *Endpoint) GetConsensusState(height exported.Height) exported.ConsensusState { - consensusState, found := endpoint.Chain.GetConsensusState(endpoint.ClientID, height) - require.True(endpoint.Chain.T, found) - - return consensusState -} - -// SetConsensusState sets the consensus state for this endpoint. -func (endpoint *Endpoint) SetConsensusState(consensusState exported.ConsensusState, height exported.Height) { - endpoint.Chain.App.GetIBCKeeper().ClientKeeper.SetClientConsensusState(endpoint.Chain.GetContext(), endpoint.ClientID, height, consensusState) -} - -// GetConnection retrieves an IBC Connection for the endpoint. The -// connection is expected to exist otherwise testing will fail. -func (endpoint *Endpoint) GetConnection() connectiontypes.ConnectionEnd { - connection, found := endpoint.Chain.App.GetIBCKeeper().ConnectionKeeper.GetConnection(endpoint.Chain.GetContext(), endpoint.ConnectionID) - require.True(endpoint.Chain.T, found) - - return connection -} - -// SetConnection sets the connection for this endpoint. -func (endpoint *Endpoint) SetConnection(connection connectiontypes.ConnectionEnd) { - endpoint.Chain.App.GetIBCKeeper().ConnectionKeeper.SetConnection(endpoint.Chain.GetContext(), endpoint.ConnectionID, connection) -} - -// GetChannel retrieves an IBC Channel for the endpoint. The channel -// is expected to exist otherwise testing will fail. -func (endpoint *Endpoint) GetChannel() channeltypes.Channel { - channel, found := endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.GetChannel(endpoint.Chain.GetContext(), endpoint.ChannelConfig.PortID, endpoint.ChannelID) - require.True(endpoint.Chain.T, found) - - return channel -} - -// SetChannel sets the channel for this endpoint. -func (endpoint *Endpoint) SetChannel(channel channeltypes.Channel) { - endpoint.Chain.App.GetIBCKeeper().ChannelKeeper.SetChannel(endpoint.Chain.GetContext(), endpoint.ChannelConfig.PortID, endpoint.ChannelID, channel) -} - -// QueryClientStateProof performs and abci query for a client stat associated -// with this endpoint and returns the ClientState along with the proof. -func (endpoint *Endpoint) QueryClientStateProof() (exported.ClientState, []byte) { - // retrieve client state to provide proof for - clientState := endpoint.GetClientState() - - clientKey := host.FullClientStateKey(endpoint.ClientID) - proofClient, _ := endpoint.QueryProof(clientKey) - - return clientState, proofClient -} diff --git a/legacy_ibc_testing/testing/events.go b/legacy_ibc_testing/testing/events.go deleted file mode 100644 index 763199a695..0000000000 --- a/legacy_ibc_testing/testing/events.go +++ /dev/null @@ -1,79 +0,0 @@ -package testing - -import ( - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" - - clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" - connectiontypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types" - channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" -) - -/* -TODO: Remove after upgrading to ibc-go v5 -legacy_ibc_testing is temporarily copied into the interchain-security repository for the purpose of testing only. -The integration test suites rely on modifications to ibc-go's test framework that cannot be back-ported to the canonical version that ics will rely on. -These files will be deprecated once ICS is able to upgrade to ibc-go v5. -*/ - -// ParseClientIDFromEvents parses events emitted from a MsgCreateClient and returns the -// client identifier. -func ParseClientIDFromEvents(events sdk.Events) (string, error) { - for _, ev := range events { - if ev.Type == clienttypes.EventTypeCreateClient { - for _, attr := range ev.Attributes { - if string(attr.Key) == clienttypes.AttributeKeyClientID { - return string(attr.Value), nil - } - } - } - } - return "", fmt.Errorf("client identifier event attribute not found") -} - -// ParseConnectionIDFromEvents parses events emitted from a MsgConnectionOpenInit or -// MsgConnectionOpenTry and returns the connection identifier. -func ParseConnectionIDFromEvents(events sdk.Events) (string, error) { - for _, ev := range events { - if ev.Type == connectiontypes.EventTypeConnectionOpenInit || - ev.Type == connectiontypes.EventTypeConnectionOpenTry { - for _, attr := range ev.Attributes { - if string(attr.Key) == connectiontypes.AttributeKeyConnectionID { - return string(attr.Value), nil - } - } - } - } - return "", fmt.Errorf("connection identifier event attribute not found") -} - -// ParseChannelIDFromEvents parses events emitted from a MsgChannelOpenInit or -// MsgChannelOpenTry and returns the channel identifier. -func ParseChannelIDFromEvents(events sdk.Events) (string, error) { - for _, ev := range events { - if ev.Type == channeltypes.EventTypeChannelOpenInit || ev.Type == channeltypes.EventTypeChannelOpenTry { - for _, attr := range ev.Attributes { - if string(attr.Key) == channeltypes.AttributeKeyChannelID { - return string(attr.Value), nil - } - } - } - } - return "", fmt.Errorf("channel identifier event attribute not found") -} - -// ParseAckFromEvents parses events emitted from a MsgRecvPacket and returns the -// acknowledgement. -func ParseAckFromEvents(events sdk.Events) ([]byte, error) { - for _, ev := range events { - if ev.Type == channeltypes.EventTypeWriteAck { - for _, attr := range ev.Attributes { - if string(attr.Key) == channeltypes.AttributeKeyAck { - return []byte(attr.Value), nil - } - } - } - } - return nil, fmt.Errorf("acknowledgement event attribute not found") -} diff --git a/legacy_ibc_testing/testing/path.go b/legacy_ibc_testing/testing/path.go deleted file mode 100644 index 31efe8215d..0000000000 --- a/legacy_ibc_testing/testing/path.go +++ /dev/null @@ -1,99 +0,0 @@ -package testing - -import ( - "bytes" - "fmt" - - channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" -) - -/* -TODO: Remove after upgrading to ibc-go v5 -legacy_ibc_testing is temporarily copied into the interchain-security repository for the purpose of testing only. -The integration test suites rely on modifications to ibc-go's test framework that cannot be back-ported to the canonical version that ics will rely on. -These files will be deprecated once ICS is able to upgrade to ibc-go v5. -*/ - -// Path contains two endpoints representing two chains connected over IBC -type Path struct { - EndpointA *Endpoint - EndpointB *Endpoint -} - -// NewPath constructs an endpoint for each chain using the default values -// for the endpoints. Each endpoint is updated to have a pointer to the -// counterparty endpoint. -func NewPath(chainA, chainB *TestChain) *Path { - endpointA := NewDefaultEndpoint(chainA) - endpointB := NewDefaultEndpoint(chainB) - - endpointA.Counterparty = endpointB - endpointB.Counterparty = endpointA - - return &Path{ - EndpointA: endpointA, - EndpointB: endpointB, - } -} - -// SetChannelOrdered sets the channel order for both endpoints to ORDERED. -func (path *Path) SetChannelOrdered() { - path.EndpointA.ChannelConfig.Order = channeltypes.ORDERED - path.EndpointB.ChannelConfig.Order = channeltypes.ORDERED -} - -// RelayPacket attempts to relay the packet first on EndpointA and then on EndpointB -// if EndpointA does not contain a packet commitment for that packet. An error is returned -// if a relay step fails or the packet commitment does not exist on either endpoint. -func (path *Path) RelayPacket(packet channeltypes.Packet) error { - pc := path.EndpointA.Chain.App.GetIBCKeeper().ChannelKeeper.GetPacketCommitment(path.EndpointA.Chain.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - if bytes.Equal(pc, channeltypes.CommitPacket(path.EndpointA.Chain.App.AppCodec(), packet)) { - - // packet found, relay from A to B - if err := path.EndpointB.UpdateClient(); err != nil { - return err - } - - res, err := path.EndpointB.RecvPacketWithResult(packet) - if err != nil { - return err - } - - ack, err := ParseAckFromEvents(res.GetEvents()) - if err != nil { - return err - } - - if err := path.EndpointA.AcknowledgePacket(packet, ack); err != nil { - return err - } - - return nil - } - - pc = path.EndpointB.Chain.App.GetIBCKeeper().ChannelKeeper.GetPacketCommitment(path.EndpointB.Chain.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - if bytes.Equal(pc, channeltypes.CommitPacket(path.EndpointB.Chain.App.AppCodec(), packet)) { - - // packet found, relay B to A - if err := path.EndpointA.UpdateClient(); err != nil { - return err - } - - res, err := path.EndpointA.RecvPacketWithResult(packet) - if err != nil { - return err - } - - ack, err := ParseAckFromEvents(res.GetEvents()) - if err != nil { - return err - } - - if err := path.EndpointB.AcknowledgePacket(packet, ack); err != nil { - return err - } - return nil - } - - return fmt.Errorf("packet commitment does not exist on either endpoint for provided packet") -} diff --git a/legacy_ibc_testing/testing/utils.go b/legacy_ibc_testing/testing/utils.go deleted file mode 100644 index 885958f25e..0000000000 --- a/legacy_ibc_testing/testing/utils.go +++ /dev/null @@ -1,31 +0,0 @@ -package testing - -import ( - "testing" - - abci "github.com/cometbft/cometbft/abci/types" - tmtypes "github.com/cometbft/cometbft/types" - "github.com/stretchr/testify/require" -) - -/* -TODO: Remove after upgrading to ibc-go v5 -legacy_ibc_testing is temporarily copied into the interchain-security repository for the purpose of testing only. -The integration test suites rely on modifications to ibc-go's test framework that cannot be back-ported to the canonical version that ics will rely on. -These files will be deprecated once ICS is able to upgrade to ibc-go v5. -*/ - -// ApplyValSetChanges takes in tmtypes.ValidatorSet and []abci.ValidatorUpdate and will return a new tmtypes.ValidatorSet which has the -// provided validator updates applied to the provided validator set. -func ApplyValSetChanges(t *testing.T, valSet *tmtypes.ValidatorSet, valUpdates []abci.ValidatorUpdate) *tmtypes.ValidatorSet { - t.Helper() - updates, err := tmtypes.PB2TM.ValidatorUpdates(valUpdates) - require.NoError(t, err) - - // must copy since validator set will mutate with UpdateWithChangeSet - newVals := valSet.Copy() - err = newVals.UpdateWithChangeSet(updates) - require.NoError(t, err) - - return newVals -} diff --git a/legacy_ibc_testing/testing/values.go b/legacy_ibc_testing/testing/values.go deleted file mode 100644 index 579d00cea4..0000000000 --- a/legacy_ibc_testing/testing/values.go +++ /dev/null @@ -1,53 +0,0 @@ -package testing - -import ( - "time" - - ibctransfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" - connectiontypes "github.com/cosmos/ibc-go/v7/modules/core/03-connection/types" - ibctmtypes "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" - "github.com/cosmos/ibc-go/v7/testing/mock" -) - -/* -TODO: Remove after upgrading to ibc-go v5 -legacy_ibc_testing is temporarily copied into the interchain-security repository for the purpose of testing only. -The integration test suites rely on modifications to ibc-go's test framework that cannot be back-ported to the canonical version that ics will rely on. -These files will be deprecated once ICS is able to upgrade to ibc-go v5. -*/ - -const ( - FirstChannelID = "channel-0" - FirstConnectionID = "connection-0" - - // Default params constants used to create a TM client - TrustingPeriod time.Duration = time.Hour * 24 * 7 * 2 - UnbondingPeriod time.Duration = time.Hour * 24 * 7 * 3 - MaxClockDrift time.Duration = time.Second * 10 - DefaultDelayPeriod uint64 = 0 - - DefaultChannelVersion = mock.Version - InvalidID = "IDisInvalid" - - // Application Ports - TransferPort = ibctransfertypes.ModuleName - MockPort = mock.ModuleName - - // used for testing proposals - Title = "title" - Description = "description" -) - -var ( - DefaultOpenInitVersion *connectiontypes.Version - - // Default params variables used to create a TM client - DefaultTrustLevel ibctmtypes.Fraction = ibctmtypes.DefaultTrustLevel - - UpgradePath = []string{"upgrade", "upgradedIBCState"} - - ConnectionVersion = connectiontypes.ExportedVersionsToProto(connectiontypes.GetCompatibleVersions())[0] - - MockAcknowledgement = mock.MockAcknowledgement.Acknowledgement() - MockPacketData = mock.MockPacketData -) diff --git a/tests/difference/core/driver/core_test.go b/tests/difference/core/driver/core_test.go index bf9afc09fc..747ca7ffa8 100644 --- a/tests/difference/core/driver/core_test.go +++ b/tests/difference/core/driver/core_test.go @@ -8,9 +8,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/suite" - channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" - ibctestingcore "github.com/cosmos/interchain-security/legacy_ibc_testing/core" - ibctesting "github.com/cosmos/interchain-security/legacy_ibc_testing/testing" + ibctesting "github.com/cosmos/ibc-go/v7/testing" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -187,13 +185,10 @@ func (s *CoreSuite) consumerSlash(val sdk.ConsAddress, h int64, isDowntime bool) before := len(ctx.EventManager().Events()) s.consumerKeeper().SlashWithInfractionReason(ctx, val, h, 0, sdk.Dec{}, kind) // consumer module emits packets on slash, so these must be collected. - evts := ctx.EventManager().ABCIEvents() - for _, e := range evts[before:] { - if e.Type == channeltypes.EventTypeSendPacket { - packet, err := ibctestingcore.ReconstructPacketFromEvent(e) - s.Require().NoError(err) - s.simibc.Outboxes.AddPacket(s.chainID(C), packet) - } + evts := ctx.EventManager().Events() + packets := simibc.ParsePacketsFromEvents(evts[before:]) + if len(packets) > 0 { + s.simibc.Outboxes.AddPacket(s.chainID(C), packets[0]) } } diff --git a/tests/difference/core/driver/setup.go b/tests/difference/core/driver/setup.go index dec5e3203e..e996670826 100644 --- a/tests/difference/core/driver/setup.go +++ b/tests/difference/core/driver/setup.go @@ -19,7 +19,7 @@ import ( "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" - ibctesting "github.com/cosmos/interchain-security/legacy_ibc_testing/testing" + ibctesting "github.com/cosmos/ibc-go/v7/testing" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -36,6 +36,7 @@ import ( appConsumer "github.com/cosmos/interchain-security/app/consumer" appProvider "github.com/cosmos/interchain-security/app/provider" icstestingutils "github.com/cosmos/interchain-security/testutil/ibc_testing" + testutil "github.com/cosmos/interchain-security/testutil/integration" simibc "github.com/cosmos/interchain-security/testutil/simibc" consumerkeeper "github.com/cosmos/interchain-security/x/ccv/consumer/keeper" consumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" @@ -254,7 +255,7 @@ func (b *Builder) getAppBytesAndSenders( func (b *Builder) newChain( coord *ibctesting.Coordinator, - appInit ibctesting.AppIniter, + appInit icstestingutils.AppIniter, chainID string, validators *tmtypes.ValidatorSet, signers map[string]tmtypes.PrivValidator, @@ -351,7 +352,8 @@ func (b *Builder) createProviderAndConsumer() { // Create provider coordinator.Chains[ibctesting.GetChainID(0)] = b.newChain(coordinator, icstestingutils.ProviderAppIniter, ibctesting.GetChainID(0), validators, signers) // Create consumer, using the same validators. - coordinator.Chains[ibctesting.GetChainID(1)] = b.newChain(coordinator, icstestingutils.ConsumerAppIniter, ibctesting.GetChainID(1), validators, signers) + valUpdates := testutil.ToValidatorUpdates(b.suite.T(), validators) + coordinator.Chains[ibctesting.GetChainID(1)] = b.newChain(coordinator, icstestingutils.ConsumerAppIniter(valUpdates), ibctesting.GetChainID(1), validators, signers) b.coordinator = coordinator b.valAddresses = addresses diff --git a/tests/integration/common.go b/tests/integration/common.go index bd62e5785c..817eb9d11a 100644 --- a/tests/integration/common.go +++ b/tests/integration/common.go @@ -16,7 +16,7 @@ import ( commitmenttypes "github.com/cosmos/ibc-go/v7/modules/core/23-commitment/types" "github.com/cosmos/ibc-go/v7/modules/core/exported" ibctm "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" - ibctesting "github.com/cosmos/interchain-security/legacy_ibc_testing/testing" + ibctesting "github.com/cosmos/ibc-go/v7/testing" icstestingutils "github.com/cosmos/interchain-security/testutil/ibc_testing" testutil "github.com/cosmos/interchain-security/testutil/integration" providertypes "github.com/cosmos/interchain-security/x/ccv/provider/types" @@ -212,19 +212,33 @@ func redelegate(s *CCVTestSuite, delAddr sdk.AccAddress, valSrcAddr sdk.ValAddre } // sendOnProviderRecvOnConsumer sends a packet from the provider chain and receives it on the consumer chain -func sendOnProviderRecvOnConsumer(s *CCVTestSuite, path *ibctesting.Path, packet channeltypes.Packet) { - err := path.EndpointB.SendPacket(packet) +func sendOnProviderRecvOnConsumer(s *CCVTestSuite, path *ibctesting.Path, timeoutHeight clienttypes.Height, timeoutTimestamp uint64, data []byte) channeltypes.Packet { + sequence, err := path.EndpointB.SendPacket(timeoutHeight, timeoutTimestamp, data) s.Require().NoError(err) + + packet := channeltypes.NewPacket(data, sequence, + path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, + path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, + timeoutHeight, timeoutTimestamp) + err = path.EndpointA.RecvPacket(packet) s.Require().NoError(err) + return packet } // sendOnConsumerRecvOnProvider sends a packet from the consumer chain and receives it on the provider chain -func sendOnConsumerRecvOnProvider(s *CCVTestSuite, path *ibctesting.Path, packet channeltypes.Packet) { - err := path.EndpointA.SendPacket(packet) +func sendOnConsumerRecvOnProvider(s *CCVTestSuite, path *ibctesting.Path, timeoutHeight clienttypes.Height, timeoutTimestamp uint64, data []byte) channeltypes.Packet { + sequence, err := path.EndpointA.SendPacket(timeoutHeight, timeoutTimestamp, data) s.Require().NoError(err) + + packet := channeltypes.NewPacket(data, sequence, + path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, + path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, + timeoutHeight, timeoutTimestamp) + err = path.EndpointB.RecvPacket(packet) s.Require().NoError(err) + return packet } // relayAllCommittedPackets relays all committed packets from `srcChain` on `path` @@ -252,7 +266,7 @@ func relayAllCommittedPackets( // relay all packets from srcChain to counterparty for _, commitment := range commitments { // - get packets - packet, found := srcChain.GetSentPacket(commitment.Sequence, srcChannelID) + packet, found := s.getSentPacket(srcChain, commitment.Sequence, srcChannelID) s.Require().True( found, fmt.Sprintf("did not find sent packet; %s", msgAndArgs...), @@ -274,7 +288,7 @@ func relayAllCommittedPackets( // to be one day larger than the consumer unbonding period. func incrementTimeByUnbondingPeriod(s *CCVTestSuite, chainType ChainType) { // Get unboding periods - providerUnbondingPeriod := s.providerApp.GetStakingKeeper().UnbondingTime(s.providerCtx()) + providerUnbondingPeriod := s.providerApp.GetTestStakingKeeper().UnbondingTime(s.providerCtx()) consumerUnbondingPeriod := s.consumerApp.GetConsumerKeeper().GetUnbondingPeriod(s.consumerCtx()) var jumpPeriod time.Duration if chainType == Provider { @@ -370,14 +384,7 @@ func (suite *CCVTestSuite) SendEmptyVSCPacket() { nil, ) - seq, ok := suite.providerApp.GetIBCKeeper().ChannelKeeper.GetNextSequenceSend( - suite.providerChain.GetContext(), ccv.ProviderPortID, suite.path.EndpointB.ChannelID) - suite.Require().True(ok) - - packet := channeltypes.NewPacket(pd.GetBytes(), seq, ccv.ProviderPortID, suite.path.EndpointB.ChannelID, - ccv.ConsumerPortID, suite.path.EndpointA.ChannelID, clienttypes.Height{}, timeout) - - sendOnProviderRecvOnConsumer(suite, suite.getFirstBundle().Path, packet) + sendOnProviderRecvOnConsumer(suite, suite.getFirstBundle().Path, clienttypes.Height{}, timeout, pd.GetBytes()) } // commitSlashPacket returns a commit hash for the given slash packet data @@ -408,8 +415,8 @@ func (suite *CCVTestSuite) commitConsumerPacket(ctx sdk.Context, packetData ccv. // constructSlashPacketFromConsumer constructs an IBC packet embedding // slash packet data to be sent from consumer to provider func (s *CCVTestSuite) constructSlashPacketFromConsumer(bundle icstestingutils.ConsumerBundle, - tmVal tmtypes.Validator, infractionType stakingtypes.Infraction, ibcSeqNum uint64, -) channeltypes.Packet { + tmVal tmtypes.Validator, infractionType stakingtypes.Infraction, +) []byte { valsetUpdateId := bundle.GetKeeper().GetHeightValsetUpdateID( bundle.GetCtx(), uint64(bundle.GetCtx().BlockHeight())) @@ -426,23 +433,12 @@ func (s *CCVTestSuite) constructSlashPacketFromConsumer(bundle icstestingutils.C }, }, } - - return channeltypes.NewPacket(data.GetBytes(), - ibcSeqNum, - ccv.ConsumerPortID, // Src port - bundle.Path.EndpointA.ChannelID, // Src channel - ccv.ProviderPortID, // Dst port - bundle.Path.EndpointB.ChannelID, // Dst channel - clienttypes.Height{}, - uint64(bundle.GetCtx().BlockTime().Add(ccv.DefaultCCVTimeoutPeriod).UnixNano()), - ) + return data.GetBytes() } // constructVSCMaturedPacketFromConsumer constructs an IBC packet embedding // VSC Matured packet data to be sent from consumer to provider -func (s *CCVTestSuite) constructVSCMaturedPacketFromConsumer(bundle icstestingutils.ConsumerBundle, - ibcSeqNum uint64, -) channeltypes.Packet { +func (s *CCVTestSuite) constructVSCMaturedPacketFromConsumer(bundle icstestingutils.ConsumerBundle) []byte { valsetUpdateId := bundle.GetKeeper().GetHeightValsetUpdateID( bundle.GetCtx(), uint64(bundle.GetCtx().BlockHeight())) @@ -452,16 +448,7 @@ func (s *CCVTestSuite) constructVSCMaturedPacketFromConsumer(bundle icstestingut VscMaturedPacketData: &ccv.VSCMaturedPacketData{ValsetUpdateId: valsetUpdateId}, }, } - - return channeltypes.NewPacket(data.GetBytes(), - ibcSeqNum, - ccv.ConsumerPortID, // Src port - bundle.Path.EndpointA.ChannelID, // Src channel - ccv.ProviderPortID, // Dst port - bundle.Path.EndpointB.ChannelID, // Dst channel - clienttypes.Height{}, - uint64(bundle.GetCtx().BlockTime().Add(ccv.DefaultCCVTimeoutPeriod).UnixNano()), - ) + return data.GetBytes() } // incrementTime increments the overall time by jumpPeriod diff --git a/tests/integration/democracy.go b/tests/integration/democracy.go index 7587350209..aab9c32cff 100644 --- a/tests/integration/democracy.go +++ b/tests/integration/democracy.go @@ -1,12 +1,11 @@ package integration import ( - "testing" "time" "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" - ibctesting "github.com/cosmos/interchain-security/legacy_ibc_testing/testing" + ibctesting "github.com/cosmos/ibc-go/v7/testing" icstestingutils "github.com/cosmos/interchain-security/testutil/ibc_testing" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -29,22 +28,22 @@ type ConsumerDemocracyTestSuite struct { // NewCCVTestSuite returns a new instance of ConsumerDemocracyTestSuite, // ready to be tested against using suite.Run(). func NewConsumerDemocracyTestSuite[T testutil.DemocConsumerApp]( - democConsumerAppIniter ibctesting.AppIniter, + democConsumerAppIniter icstestingutils.ValSetAppIniter, ) *ConsumerDemocracyTestSuite { democSuite := new(ConsumerDemocracyTestSuite) - democSuite.setupCallback = func(t *testing.T) ( + democSuite.setupCallback = func(s *suite.Suite) ( *ibctesting.Coordinator, *ibctesting.TestChain, testutil.DemocConsumerApp, ) { - t.Helper() + s.T().Helper() // Instantiate the test coordinator - coordinator := ibctesting.NewCoordinator(t, 0) + coordinator := ibctesting.NewCoordinator(s.T(), 0) // Add single democracy consumer to coordinator, store returned test chain and app. democConsumer, democConsumerApp := icstestingutils.AddDemocracyConsumer[T]( - t, coordinator, democConsumerAppIniter) + coordinator, s, democConsumerAppIniter) // Pass variables to suite. return coordinator, democConsumer, democConsumerApp @@ -54,7 +53,7 @@ func NewConsumerDemocracyTestSuite[T testutil.DemocConsumerApp]( // Callback for instantiating a new coordinator, consumer test chain, and consumer app // before every test defined on the suite. -type DemocSetupCallback func(t *testing.T) ( +type DemocSetupCallback func(s *suite.Suite) ( coord *ibctesting.Coordinator, consumerChain *ibctesting.TestChain, consumerApp testutil.DemocConsumerApp, @@ -64,7 +63,7 @@ type DemocSetupCallback func(t *testing.T) ( func (suite *ConsumerDemocracyTestSuite) SetupTest() { // Instantiate new test utils using callback suite.coordinator, suite.consumerChain, - suite.consumerApp = suite.setupCallback(suite.T()) + suite.consumerApp = suite.setupCallback(&suite.Suite) } func (s *ConsumerDemocracyTestSuite) TestDemocracyRewardsDistribution() { diff --git a/tests/integration/expired_client.go b/tests/integration/expired_client.go index 1963f293c4..178be35ac7 100644 --- a/tests/integration/expired_client.go +++ b/tests/integration/expired_client.go @@ -10,7 +10,7 @@ import ( clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" ibctm "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" - ibctesting "github.com/cosmos/interchain-security/legacy_ibc_testing/testing" + ibctesting "github.com/cosmos/ibc-go/v7/testing" ccv "github.com/cosmos/interchain-security/x/ccv/types" ) diff --git a/tests/integration/setup.go b/tests/integration/setup.go index ce597efb36..8f6f30965c 100644 --- a/tests/integration/setup.go +++ b/tests/integration/setup.go @@ -1,13 +1,20 @@ package integration import ( + "context" + "fmt" + "sync" "testing" + abci "github.com/cometbft/cometbft/abci/types" tmencoding "github.com/cometbft/cometbft/crypto/encoding" + "github.com/cosmos/cosmos-sdk/baseapp" + store "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" ibctmtypes "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" "github.com/cosmos/ibc-go/v7/testing/mock" testutil "github.com/cosmos/interchain-security/testutil/integration" + "github.com/cosmos/interchain-security/testutil/simibc" icstestingutils "github.com/cosmos/interchain-security/testutil/ibc_testing" consumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" @@ -15,7 +22,7 @@ import ( transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" - ibctesting "github.com/cosmos/interchain-security/legacy_ibc_testing/testing" + ibctesting "github.com/cosmos/ibc-go/v7/testing" "github.com/stretchr/testify/suite" ) @@ -59,11 +66,16 @@ type CCVTestSuite struct { // The preferred way to access chains, apps, and paths when designing tests around multiple consumers. consumerBundles map[string]*icstestingutils.ConsumerBundle skippedTests map[string]bool + + // packetSniffers maps a chain and a packetSniffer + packetSniffers map[*ibctesting.TestChain]*packetSniffer } // NewCCVTestSuite returns a new instance of CCVTestSuite, ready to be tested against using suite.Run(). func NewCCVTestSuite[Tp testutil.ProviderApp, Tc testutil.ConsumerApp]( - providerAppIniter, consumerAppIniter ibctesting.AppIniter, skippedTests []string, + providerAppIniter icstestingutils.AppIniter, + consumerAppIniter icstestingutils.ValSetAppIniter, + skippedTests []string, ) *CCVTestSuite { ccvSuite := new(CCVTestSuite) @@ -108,9 +120,12 @@ func (suite *CCVTestSuite) BeforeTest(suiteName, testName string) { // SetupTest sets up in-mem state before every test func (suite *CCVTestSuite) SetupTest() { + suite.packetSniffers = make(map[*ibctesting.TestChain]*packetSniffer) + // Instantiate new coordinator and provider chain using callback suite.coordinator, suite.providerChain, suite.providerApp = suite.setupProviderCallback(suite.T()) + suite.registerPacketSniffer(suite.providerChain) providerKeeper := suite.providerApp.GetProviderKeeper() // re-assign all validator keys for the first consumer chain @@ -122,6 +137,7 @@ func (suite *CCVTestSuite) SetupTest() { for i := 0; i < numConsumers; i++ { bundle := suite.setupConsumerCallback(&suite.Suite, suite.coordinator, i) suite.consumerBundles[bundle.Chain.ChainID] = bundle + suite.registerPacketSniffer(bundle.Chain) } // initialize each consumer chain with it's corresponding genesis state @@ -148,6 +164,21 @@ func (suite *CCVTestSuite) SetupTest() { } } +func (s *CCVTestSuite) registerPacketSniffer(chain *ibctesting.TestChain) { + if s.packetSniffers == nil { + s.packetSniffers = make(map[*ibctesting.TestChain]*packetSniffer) + } + p := newPacketSniffer() + chain.App.GetBaseApp().SetStreamingService(p) + s.packetSniffers[chain] = p +} + +func (s *CCVTestSuite) getSentPacket(chain *ibctesting.TestChain, sequence uint64, channelID string) (packet channeltypes.Packet, found bool) { + key := getSentPacketKey(sequence, channelID) + packet, found = s.packetSniffers[chain].packets[key] + return +} + // initConsumerChain initializes a consumer chain given a genesis state func initConsumerChain( s *CCVTestSuite, @@ -293,7 +324,7 @@ func (suite *CCVTestSuite) SetupTransferChannel() { func (s CCVTestSuite) validateEndpointsClientConfig(consumerBundle icstestingutils.ConsumerBundle) { //nolint:govet // this is a test so we can copy locks consumerKeeper := consumerBundle.GetKeeper() - providerStakingKeeper := s.providerApp.GetStakingKeeper() + providerStakingKeeper := s.providerApp.GetTestStakingKeeper() consumerUnbondingPeriod := consumerKeeper.GetUnbondingPeriod(consumerBundle.GetCtx()) cs, ok := s.providerApp.GetIBCKeeper().ClientKeeper.GetClientState(s.providerCtx(), @@ -343,3 +374,46 @@ func preProposalKeyAssignment(s *CCVTestSuite, chainID string) { s.Require().NoError(err) } } + +// packetSniffer implements the StreamingService interface. +// Implements ListenEndBlock to record packets from events. +type packetSniffer struct { + packets map[string]channeltypes.Packet +} + +var _ baseapp.StreamingService = &packetSniffer{} + +func newPacketSniffer() *packetSniffer { + return &packetSniffer{ + packets: make(map[string]channeltypes.Packet), + } +} + +func (ps *packetSniffer) ListenEndBlock(ctx context.Context, req abci.RequestEndBlock, res abci.ResponseEndBlock) error { + packets := simibc.ParsePacketsFromEvents(simibc.ABCIToSDKEvents(res.GetEvents())) + for _, packet := range packets { + ps.packets[getSentPacketKey(packet.Sequence, packet.SourceChannel)] = packet + } + return nil +} + +// getSentPacketKey returns a key for accessing a sent packet, +// given an ibc sequence number and the channel ID for the source endpoint. +func getSentPacketKey(sequence uint64, channelID string) string { + return fmt.Sprintf("%s-%d", channelID, sequence) +} + +func (*packetSniffer) ListenBeginBlock(ctx context.Context, req abci.RequestBeginBlock, res abci.ResponseBeginBlock) error { + return nil +} + +func (*packetSniffer) ListenCommit(ctx context.Context, res abci.ResponseCommit) error { + return nil +} + +func (*packetSniffer) ListenDeliverTx(ctx context.Context, req abci.RequestDeliverTx, res abci.ResponseDeliverTx) error { + return nil +} +func (*packetSniffer) Close() error { return nil } +func (*packetSniffer) Listeners() map[store.StoreKey][]store.WriteListener { return nil } +func (*packetSniffer) Stream(wg *sync.WaitGroup) error { return nil } diff --git a/tests/integration/slashing.go b/tests/integration/slashing.go index b6ec62f75f..6eed97b215 100644 --- a/tests/integration/slashing.go +++ b/tests/integration/slashing.go @@ -67,8 +67,12 @@ func (s *CCVTestSuite) TestRelayAndApplyDowntimePacket() { s.setDefaultValSigningInfo(*tmtypes.NewValidator(tmPk, stakingVal.ConsensusPower(sdk.DefaultPowerReduction))) // Send slash packet from the first consumer chain - packet := s.constructSlashPacketFromConsumer(s.getFirstBundle(), *tmVal, stakingtypes.Infraction_INFRACTION_DOWNTIME, 1) - err = s.getFirstBundle().Path.EndpointA.SendPacket(packet) + var ( + timeoutHeight = clienttypes.Height{} + timeoutTimestamp = uint64(s.getFirstBundle().GetCtx().BlockTime().Add(ccv.DefaultCCVTimeoutPeriod).UnixNano()) + ) + data := s.constructSlashPacketFromConsumer(s.getFirstBundle(), *tmVal, stakingtypes.Infraction_INFRACTION_DOWNTIME) + sequence, err := s.getFirstBundle().Path.EndpointA.SendPacket(timeoutHeight, timeoutTimestamp, data) s.Require().NoError(err) // Set outstanding slashing flag for first consumer, it's important to use the consumer's cons addr here @@ -85,6 +89,10 @@ func (s *CCVTestSuite) TestRelayAndApplyDowntimePacket() { valsetUpdateIdN := providerKeeper.GetValidatorSetUpdateId(s.providerCtx()) // receive the slash packet on the provider chain. RecvPacket() calls the provider endblocker twice + packet := channeltypes.NewPacket(data, sequence, + s.getFirstBundle().Path.EndpointA.ChannelConfig.PortID, s.getFirstBundle().Path.EndpointA.ChannelID, + s.getFirstBundle().Path.EndpointB.ChannelConfig.PortID, s.getFirstBundle().Path.EndpointB.ChannelID, + timeoutHeight, timeoutTimestamp) err = s.path.EndpointB.RecvPacket(packet) s.Require().NoError(err) @@ -195,13 +203,12 @@ func (s *CCVTestSuite) TestRelayAndApplyDoubleSignPacket() { s.setDefaultValSigningInfo(*tmtypes.NewValidator(tmPk, stakingVal.ConsensusPower(sdk.DefaultPowerReduction))) // Send slash packet from the first consumer chain - packet := s.constructSlashPacketFromConsumer(s.getFirstBundle(), *tmVal, stakingtypes.Infraction_INFRACTION_DOUBLE_SIGN, 1) - err = s.getFirstBundle().Path.EndpointA.SendPacket(packet) - s.Require().NoError(err) - - // receive the slash packet on the provider chain. RecvPacket() advances two blocks - err = s.path.EndpointB.RecvPacket(packet) - s.Require().NoError(err) + var ( + timeoutHeight = clienttypes.Height{} + timeoutTimestamp = uint64(s.getFirstBundle().GetCtx().BlockTime().Add(ccv.DefaultCCVTimeoutPeriod).UnixNano()) + ) + data := s.constructSlashPacketFromConsumer(s.getFirstBundle(), *tmVal, stakingtypes.Infraction_INFRACTION_DOUBLE_SIGN) + packet := sendOnConsumerRecvOnProvider(s, s.getFirstBundle().Path, timeoutHeight, timeoutTimestamp, data) // Advance a few more blocks to make sure any voting power changes would be reflected s.providerChain.NextBlock() diff --git a/tests/integration/throttle.go b/tests/integration/throttle.go index 693fc064b6..7d0ed1239d 100644 --- a/tests/integration/throttle.go +++ b/tests/integration/throttle.go @@ -6,9 +6,11 @@ import ( tmtypes "github.com/cometbft/cometbft/types" sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" icstestingutils "github.com/cosmos/interchain-security/testutil/ibc_testing" providertypes "github.com/cosmos/interchain-security/x/ccv/provider/types" + ccv "github.com/cosmos/interchain-security/x/ccv/types" ccvtypes "github.com/cosmos/interchain-security/x/ccv/types" ) @@ -53,12 +55,16 @@ func (s *CCVTestSuite) TestBasicSlashPacketThrottling() { for _, val := range vals { s.Require().False(val.IsJailed()) } + var ( + timeoutHeight = clienttypes.Height{} + timeoutTimestamp = uint64(s.getFirstBundle().GetCtx().BlockTime().Add(ccv.DefaultCCVTimeoutPeriod).UnixNano()) + ) // Send a slash packet from consumer to provider s.setDefaultValSigningInfo(*s.providerChain.Vals.Validators[0]) tmVal := s.providerChain.Vals.Validators[0] - packet := s.constructSlashPacketFromConsumer(s.getFirstBundle(), *tmVal, stakingtypes.Infraction_INFRACTION_DOWNTIME, 1) - sendOnConsumerRecvOnProvider(s, s.getFirstBundle().Path, packet) + data := s.constructSlashPacketFromConsumer(s.getFirstBundle(), *tmVal, stakingtypes.Infraction_INFRACTION_DOWNTIME) + sendOnConsumerRecvOnProvider(s, s.getFirstBundle().Path, timeoutHeight, timeoutTimestamp, data) // Assert validator 0 is jailed and has no power vals = providerStakingKeeper.GetAllValidators(s.providerCtx()) @@ -76,8 +82,8 @@ func (s *CCVTestSuite) TestBasicSlashPacketThrottling() { // Now send a second slash packet from consumer to provider for a different validator. s.setDefaultValSigningInfo(*s.providerChain.Vals.Validators[2]) tmVal = s.providerChain.Vals.Validators[2] - packet = s.constructSlashPacketFromConsumer(s.getFirstBundle(), *tmVal, stakingtypes.Infraction_INFRACTION_DOWNTIME, 2) - sendOnConsumerRecvOnProvider(s, s.getFirstBundle().Path, packet) + data = s.constructSlashPacketFromConsumer(s.getFirstBundle(), *tmVal, stakingtypes.Infraction_INFRACTION_DOWNTIME) + sendOnConsumerRecvOnProvider(s, s.getFirstBundle().Path, timeoutHeight, timeoutTimestamp, data) // Require that slash packet has not been handled vals = providerStakingKeeper.GetAllValidators(s.providerCtx()) @@ -157,11 +163,15 @@ func (s *CCVTestSuite) TestMultiConsumerSlashPacketThrottling() { // when no slash packets are sent. // Send 2 VSC matured packets from every consumer to provider + var ( + timeoutHeight = clienttypes.Height{} + timeoutTimestamp = uint64(s.getFirstBundle().GetCtx().BlockTime().Add(ccv.DefaultCCVTimeoutPeriod).UnixNano()) + ) for consumerChainID, bundle := range s.consumerBundles { - packet := s.constructVSCMaturedPacketFromConsumer(*bundle, 1) // use sequence 1 - sendOnConsumerRecvOnProvider(s, bundle.Path, packet) - packet = s.constructVSCMaturedPacketFromConsumer(*bundle, 2) // use sequence 2 - sendOnConsumerRecvOnProvider(s, bundle.Path, packet) + data := s.constructVSCMaturedPacketFromConsumer(*bundle) + sendOnConsumerRecvOnProvider(s, bundle.Path, timeoutHeight, timeoutTimestamp, data) + data = s.constructVSCMaturedPacketFromConsumer(*bundle) + sendOnConsumerRecvOnProvider(s, bundle.Path, timeoutHeight, timeoutTimestamp, data) // Confirm packets were not queued on provider for this consumer s.Require().Equal(uint64(0), providerKeeper.GetThrottledPacketDataSize(s.providerCtx(), consumerChainID)) @@ -190,19 +200,18 @@ func (s *CCVTestSuite) TestMultiConsumerSlashPacketThrottling() { // Send downtime slash packet from consumer to provider tmVal := s.providerChain.Vals.Validators[idx] valsToSlash = append(valsToSlash, *tmVal) - packet := s.constructSlashPacketFromConsumer( + data := s.constructSlashPacketFromConsumer( *bundle, *tmVal, stakingtypes.Infraction_INFRACTION_DOWNTIME, - 3, // use sequence 3, 1 and 2 are used above. ) - sendOnConsumerRecvOnProvider(s, bundle.Path, packet) + sendOnConsumerRecvOnProvider(s, bundle.Path, timeoutHeight, timeoutTimestamp, data) // Send two trailing VSC matured packets from consumer to provider - packet = s.constructVSCMaturedPacketFromConsumer(*bundle, 4) // use sequence 4 - sendOnConsumerRecvOnProvider(s, bundle.Path, packet) - packet = s.constructVSCMaturedPacketFromConsumer(*bundle, 5) // use sequence 5 - sendOnConsumerRecvOnProvider(s, bundle.Path, packet) + data = s.constructVSCMaturedPacketFromConsumer(*bundle) + sendOnConsumerRecvOnProvider(s, bundle.Path, timeoutHeight, timeoutTimestamp, data) + data = s.constructVSCMaturedPacketFromConsumer(*bundle) + sendOnConsumerRecvOnProvider(s, bundle.Path, timeoutHeight, timeoutTimestamp, data) idx++ } @@ -281,8 +290,8 @@ func (s *CCVTestSuite) TestPacketSpam() { providerKeeper.SetParams(s.providerCtx(), params) providerKeeper.InitializeSlashMeter(s.providerCtx()) - // The packets to be recv in a single block, ordered as they will be recv. - packets := []channeltypes.Packet{} + // The packets data to be recv in a single block, ordered as they will be recv. + var packetsData [][]byte firstBundle := s.getFirstBundle() @@ -306,13 +315,21 @@ func (s *CCVTestSuite) TestPacketSpam() { infractionType = stakingtypes.Infraction_INFRACTION_DOUBLE_SIGN } valToJail := s.providerChain.Vals.Validators[ibcSeqNum%3] - packets = append(packets, s.constructSlashPacketFromConsumer(firstBundle, *valToJail, infractionType, ibcSeqNum)) + packetsData = append(packetsData, s.constructSlashPacketFromConsumer(firstBundle, *valToJail, infractionType)) } // Recv 500 packets from consumer to provider in same block - for _, packet := range packets { + var ( + timeoutHeight = clienttypes.Height{} + timeoutTimestamp = uint64(firstBundle.GetCtx().BlockTime().Add(ccv.DefaultCCVTimeoutPeriod).UnixNano()) + ) + for sequence, data := range packetsData { consumerPacketData := ccvtypes.ConsumerPacketData{} - ccvtypes.ModuleCdc.MustUnmarshalJSON(packet.GetData(), &consumerPacketData) + ccvtypes.ModuleCdc.MustUnmarshalJSON(data, &consumerPacketData) + packet := channeltypes.NewPacket(data, uint64(sequence), + firstBundle.Path.EndpointA.ChannelConfig.PortID, firstBundle.Path.EndpointA.ChannelID, + firstBundle.Path.EndpointB.ChannelConfig.PortID, firstBundle.Path.EndpointB.ChannelID, + timeoutHeight, timeoutTimestamp) providerKeeper.OnRecvSlashPacket(s.providerCtx(), packet, *consumerPacketData.GetSlashPacketData()) } @@ -343,8 +360,8 @@ func (s *CCVTestSuite) TestDoubleSignDoesNotAffectThrottling() { providerKeeper.SetParams(s.providerCtx(), params) providerKeeper.InitializeSlashMeter(s.providerCtx()) - // The packets to be recv in a single block, ordered as they will be recv. - packets := []channeltypes.Packet{} + // The packetsData to be recv in a single block, ordered as they will be recv. + var packetsData [][]byte firstBundle := s.getFirstBundle() @@ -360,13 +377,21 @@ func (s *CCVTestSuite) TestDoubleSignDoesNotAffectThrottling() { // Increment ibc seq num for each packet (starting at 1) ibcSeqNum++ valToJail := s.providerChain.Vals.Validators[ibcSeqNum%3] - packets = append(packets, s.constructSlashPacketFromConsumer(firstBundle, *valToJail, stakingtypes.Infraction_INFRACTION_DOUBLE_SIGN, ibcSeqNum)) + packetsData = append(packetsData, s.constructSlashPacketFromConsumer(firstBundle, *valToJail, stakingtypes.Infraction_INFRACTION_DOUBLE_SIGN)) } // Recv 500 packets from consumer to provider in same block - for _, packet := range packets { + var ( + timeoutHeight = clienttypes.Height{} + timeoutTimestamp = uint64(firstBundle.GetCtx().BlockTime().Add(ccv.DefaultCCVTimeoutPeriod).UnixNano()) + ) + for sequence, data := range packetsData { consumerPacketData := ccvtypes.ConsumerPacketData{} - ccvtypes.ModuleCdc.MustUnmarshalJSON(packet.GetData(), &consumerPacketData) + ccvtypes.ModuleCdc.MustUnmarshalJSON(data, &consumerPacketData) + packet := channeltypes.NewPacket(data, uint64(sequence), + firstBundle.Path.EndpointA.ChannelConfig.PortID, firstBundle.Path.EndpointA.ChannelID, + firstBundle.Path.EndpointB.ChannelConfig.PortID, firstBundle.Path.EndpointB.ChannelID, + timeoutHeight, timeoutTimestamp) providerKeeper.OnRecvSlashPacket(s.providerCtx(), packet, *consumerPacketData.GetSlashPacketData()) } @@ -432,7 +457,7 @@ func (s *CCVTestSuite) TestQueueOrdering() { providerKeeper.InitializeSlashMeter(s.providerCtx()) // The packets to be recv in a single block, ordered as they will be recv. - packets := []channeltypes.Packet{} + var packetsData [][]byte firstBundle := s.getFirstBundle() @@ -442,27 +467,39 @@ func (s *CCVTestSuite) TestQueueOrdering() { s.setDefaultValSigningInfo(*s.providerChain.Vals.Validators[2]) // Track and increment ibc seq num for each packet, since these need to be unique. - ibcSeqNum := uint64(4) + var ( + ibcSeqNum = uint64(4) + ibcSeqs []uint64 + ) for ibcSeqNum < 504 { // Increment ibc seq num for each packet (starting at 5) ibcSeqNum++ + ibcSeqs = append(ibcSeqs, ibcSeqNum) // Instantiate a vsc matured packet every 10th packet if ibcSeqNum%10 == 0 { - packets = append(packets, s.constructVSCMaturedPacketFromConsumer(firstBundle, ibcSeqNum)) + packetsData = append(packetsData, s.constructVSCMaturedPacketFromConsumer(firstBundle)) continue } // Else instantiate a slash packet valToJail := s.providerChain.Vals.Validators[ibcSeqNum%3] - packets = append(packets, s.constructSlashPacketFromConsumer(firstBundle, *valToJail, stakingtypes.Infraction_INFRACTION_DOWNTIME, ibcSeqNum)) + packetsData = append(packetsData, s.constructSlashPacketFromConsumer(firstBundle, *valToJail, stakingtypes.Infraction_INFRACTION_DOWNTIME)) } // Recv 500 packets from consumer to provider in same block - for i, packet := range packets { + var ( + timeoutHeight = clienttypes.Height{} + timeoutTimestamp = uint64(firstBundle.GetCtx().BlockTime().Add(ccv.DefaultCCVTimeoutPeriod).UnixNano()) + ) + for i, data := range packetsData { consumerPacketData := ccvtypes.ConsumerPacketData{} - ccvtypes.ModuleCdc.MustUnmarshalJSON(packet.GetData(), &consumerPacketData) + ccvtypes.ModuleCdc.MustUnmarshalJSON(data, &consumerPacketData) + packet := channeltypes.NewPacket(data, ibcSeqs[i], + firstBundle.Path.EndpointA.ChannelConfig.PortID, firstBundle.Path.EndpointA.ChannelID, + firstBundle.Path.EndpointB.ChannelConfig.PortID, firstBundle.Path.EndpointB.ChannelID, + timeoutHeight, timeoutTimestamp) // Type depends on index packets were appended from above if (i+5)%10 == 0 { vscMaturedPacketData := consumerPacketData.GetVscMaturedPacketData() @@ -587,15 +624,19 @@ func (s *CCVTestSuite) TestSlashingSmallValidators() { s.setDefaultValSigningInfo(*s.providerChain.Vals.Validators[3]) // Send slash packets from consumer to provider for small validators. + var ( + timeoutHeight = clienttypes.Height{} + timeoutTimestamp = uint64(s.getFirstBundle().GetCtx().BlockTime().Add(ccv.DefaultCCVTimeoutPeriod).UnixNano()) + ) tmval1 := s.providerChain.Vals.Validators[1] tmval2 := s.providerChain.Vals.Validators[2] tmval3 := s.providerChain.Vals.Validators[3] - packet1 := s.constructSlashPacketFromConsumer(s.getFirstBundle(), *tmval1, stakingtypes.Infraction_INFRACTION_DOWNTIME, 1) - packet2 := s.constructSlashPacketFromConsumer(s.getFirstBundle(), *tmval2, stakingtypes.Infraction_INFRACTION_DOWNTIME, 2) - packet3 := s.constructSlashPacketFromConsumer(s.getFirstBundle(), *tmval3, stakingtypes.Infraction_INFRACTION_DOWNTIME, 3) - sendOnConsumerRecvOnProvider(s, s.getFirstBundle().Path, packet1) - sendOnConsumerRecvOnProvider(s, s.getFirstBundle().Path, packet2) - sendOnConsumerRecvOnProvider(s, s.getFirstBundle().Path, packet3) + data1 := s.constructSlashPacketFromConsumer(s.getFirstBundle(), *tmval1, stakingtypes.Infraction_INFRACTION_DOWNTIME) + data2 := s.constructSlashPacketFromConsumer(s.getFirstBundle(), *tmval2, stakingtypes.Infraction_INFRACTION_DOWNTIME) + data3 := s.constructSlashPacketFromConsumer(s.getFirstBundle(), *tmval3, stakingtypes.Infraction_INFRACTION_DOWNTIME) + sendOnConsumerRecvOnProvider(s, s.getFirstBundle().Path, timeoutHeight, timeoutTimestamp, data1) + sendOnConsumerRecvOnProvider(s, s.getFirstBundle().Path, timeoutHeight, timeoutTimestamp, data2) + sendOnConsumerRecvOnProvider(s, s.getFirstBundle().Path, timeoutHeight, timeoutTimestamp, data3) // Default slash meter replenish fraction is 0.05, so all sent packets should be handled immediately. vals = providerStakingKeeper.GetAllValidators(s.providerCtx()) @@ -664,19 +705,27 @@ func (s *CCVTestSuite) TestSlashSameValidator() { s.setDefaultValSigningInfo(*tmval2) s.setDefaultValSigningInfo(*tmval3) - packets := []channeltypes.Packet{ - s.constructSlashPacketFromConsumer(s.getFirstBundle(), *tmval1, stakingtypes.Infraction_INFRACTION_DOWNTIME, 1), - s.constructSlashPacketFromConsumer(s.getFirstBundle(), *tmval2, stakingtypes.Infraction_INFRACTION_DOWNTIME, 2), - s.constructSlashPacketFromConsumer(s.getFirstBundle(), *tmval3, stakingtypes.Infraction_INFRACTION_DOWNTIME, 3), - s.constructSlashPacketFromConsumer(s.getFirstBundle(), *tmval1, stakingtypes.Infraction_INFRACTION_DOWNTIME, 4), - s.constructSlashPacketFromConsumer(s.getFirstBundle(), *tmval2, stakingtypes.Infraction_INFRACTION_DOWNTIME, 5), - s.constructSlashPacketFromConsumer(s.getFirstBundle(), *tmval3, stakingtypes.Infraction_INFRACTION_DOWNTIME, 6), + packetsData := [][]byte{ + s.constructSlashPacketFromConsumer(s.getFirstBundle(), *tmval1, stakingtypes.Infraction_INFRACTION_DOWNTIME), + s.constructSlashPacketFromConsumer(s.getFirstBundle(), *tmval2, stakingtypes.Infraction_INFRACTION_DOWNTIME), + s.constructSlashPacketFromConsumer(s.getFirstBundle(), *tmval3, stakingtypes.Infraction_INFRACTION_DOWNTIME), + s.constructSlashPacketFromConsumer(s.getFirstBundle(), *tmval1, stakingtypes.Infraction_INFRACTION_DOWNTIME), + s.constructSlashPacketFromConsumer(s.getFirstBundle(), *tmval2, stakingtypes.Infraction_INFRACTION_DOWNTIME), + s.constructSlashPacketFromConsumer(s.getFirstBundle(), *tmval3, stakingtypes.Infraction_INFRACTION_DOWNTIME), } // Recv and queue all slash packets. - for _, packet := range packets { + var ( + timeoutHeight = clienttypes.Height{} + timeoutTimestamp = uint64(s.getFirstBundle().GetCtx().BlockTime().Add(ccv.DefaultCCVTimeoutPeriod).UnixNano()) + ) + for i, data := range packetsData { consumerPacketData := ccvtypes.ConsumerPacketData{} - ccvtypes.ModuleCdc.MustUnmarshalJSON(packet.GetData(), &consumerPacketData) + ccvtypes.ModuleCdc.MustUnmarshalJSON(data, &consumerPacketData) + packet := channeltypes.NewPacket(data, uint64(i), + s.getFirstBundle().Path.EndpointA.ChannelConfig.PortID, s.getFirstBundle().Path.EndpointA.ChannelID, + s.getFirstBundle().Path.EndpointB.ChannelConfig.PortID, s.getFirstBundle().Path.EndpointB.ChannelID, + timeoutHeight, timeoutTimestamp) providerKeeper.OnRecvSlashPacket(s.providerCtx(), packet, *consumerPacketData.GetSlashPacketData()) } @@ -711,7 +760,7 @@ func (s CCVTestSuite) TestSlashAllValidators() { //nolint:govet // this is a tes providerKeeper.InitializeSlashMeter(s.providerCtx()) // The packets to be recv in a single block, ordered as they will be recv. - packets := []channeltypes.Packet{} + var packetsData [][]byte // Track and increment ibc seq num for each packet, since these need to be unique. ibcSeqNum := uint64(1) @@ -720,24 +769,32 @@ func (s CCVTestSuite) TestSlashAllValidators() { //nolint:govet // this is a tes // these first 4 packets should jail 100% of the total power. for _, val := range s.providerChain.Vals.Validators { s.setDefaultValSigningInfo(*val) - packets = append(packets, s.constructSlashPacketFromConsumer( - s.getFirstBundle(), *val, stakingtypes.Infraction_INFRACTION_DOWNTIME, ibcSeqNum)) + packetsData = append(packetsData, s.constructSlashPacketFromConsumer( + s.getFirstBundle(), *val, stakingtypes.Infraction_INFRACTION_DOWNTIME)) ibcSeqNum++ } // add 5 more slash packets for each validator, that will be handled in the same block. for _, val := range s.providerChain.Vals.Validators { for i := 0; i < 5; i++ { - packets = append(packets, s.constructSlashPacketFromConsumer( - s.getFirstBundle(), *val, stakingtypes.Infraction_INFRACTION_DOWNTIME, ibcSeqNum)) + packetsData = append(packetsData, s.constructSlashPacketFromConsumer( + s.getFirstBundle(), *val, stakingtypes.Infraction_INFRACTION_DOWNTIME)) ibcSeqNum++ } } // Recv and queue all slash packets. - for _, packet := range packets { + var ( + timeoutHeight = clienttypes.Height{} + timeoutTimestamp = uint64(s.getFirstBundle().GetCtx().BlockTime().Add(ccv.DefaultCCVTimeoutPeriod).UnixNano()) + ) + for i, data := range packetsData { consumerPacketData := ccvtypes.ConsumerPacketData{} - ccvtypes.ModuleCdc.MustUnmarshalJSON(packet.GetData(), &consumerPacketData) + ccvtypes.ModuleCdc.MustUnmarshalJSON(data, &consumerPacketData) + packet := channeltypes.NewPacket(data, uint64(i), + s.getFirstBundle().Path.EndpointA.ChannelConfig.PortID, s.getFirstBundle().Path.EndpointA.ChannelID, + s.getFirstBundle().Path.EndpointB.ChannelConfig.PortID, s.getFirstBundle().Path.EndpointB.ChannelID, + timeoutHeight, timeoutTimestamp) providerKeeper.OnRecvSlashPacket(s.providerCtx(), packet, *consumerPacketData.GetSlashPacketData()) } @@ -766,12 +823,20 @@ func (s *CCVTestSuite) TestLeadingVSCMaturedAreDequeued() { providerKeeper := s.providerApp.GetProviderKeeper() // Queue up 50 vsc matured packets for each consumer + var ( + timeoutHeight = clienttypes.Height{} + timeoutTimestamp = uint64(s.getFirstBundle().GetCtx().BlockTime().Add(ccv.DefaultCCVTimeoutPeriod).UnixNano()) + ) for _, bundle := range s.consumerBundles { for i := 0; i < 50; i++ { ibcSeqNum := uint64(i) - packet := s.constructVSCMaturedPacketFromConsumer(*bundle, ibcSeqNum) + data := s.constructVSCMaturedPacketFromConsumer(*bundle) packetData := ccvtypes.ConsumerPacketData{} - ccvtypes.ModuleCdc.MustUnmarshalJSON(packet.GetData(), &packetData) + ccvtypes.ModuleCdc.MustUnmarshalJSON(data, &packetData) + packet := channeltypes.NewPacket(data, ibcSeqNum, + ccv.ConsumerPortID, bundle.Path.EndpointA.ChannelID, + ccv.ProviderPortID, bundle.Path.EndpointB.ChannelID, + timeoutHeight, timeoutTimestamp) providerKeeper.OnRecvVSCMaturedPacket(s.providerCtx(), packet, *packetData.GetVscMaturedPacketData()) } @@ -781,10 +846,14 @@ func (s *CCVTestSuite) TestLeadingVSCMaturedAreDequeued() { for _, bundle := range s.consumerBundles { for i := 0; i < 50; i++ { ibcSeqNum := uint64(i) - packet := s.constructSlashPacketFromConsumer(*bundle, - *s.providerChain.Vals.Validators[0], stakingtypes.Infraction_INFRACTION_DOWNTIME, ibcSeqNum) + data := s.constructSlashPacketFromConsumer(*bundle, + *s.providerChain.Vals.Validators[0], stakingtypes.Infraction_INFRACTION_DOWNTIME) packetData := ccvtypes.ConsumerPacketData{} - ccvtypes.ModuleCdc.MustUnmarshalJSON(packet.GetData(), &packetData) + ccvtypes.ModuleCdc.MustUnmarshalJSON(data, &packetData) + packet := channeltypes.NewPacket(data, ibcSeqNum, + ccv.ConsumerPortID, bundle.Path.EndpointA.ChannelID, + ccv.ProviderPortID, bundle.Path.EndpointB.ChannelID, + timeoutHeight, timeoutTimestamp) providerKeeper.OnRecvSlashPacket(s.providerCtx(), packet, *packetData.GetSlashPacketData()) } @@ -794,9 +863,13 @@ func (s *CCVTestSuite) TestLeadingVSCMaturedAreDequeued() { for _, bundle := range s.consumerBundles { for i := 0; i < 50; i++ { ibcSeqNum := uint64(i) - packet := s.constructVSCMaturedPacketFromConsumer(*bundle, ibcSeqNum) + data := s.constructVSCMaturedPacketFromConsumer(*bundle) packetData := ccvtypes.ConsumerPacketData{} - ccvtypes.ModuleCdc.MustUnmarshalJSON(packet.GetData(), &packetData) + ccvtypes.ModuleCdc.MustUnmarshalJSON(data, &packetData) + packet := channeltypes.NewPacket(data, ibcSeqNum, + ccv.ConsumerPortID, bundle.Path.EndpointA.ChannelID, + ccv.ProviderPortID, bundle.Path.EndpointB.ChannelID, + timeoutHeight, timeoutTimestamp) providerKeeper.OnRecvVSCMaturedPacket(s.providerCtx(), packet, *packetData.GetVscMaturedPacketData()) } diff --git a/testutil/ibc_testing/generic_setup.go b/testutil/ibc_testing/generic_setup.go index 66f2098f6f..b0c41a3ed9 100644 --- a/testutil/ibc_testing/generic_setup.go +++ b/testutil/ibc_testing/generic_setup.go @@ -1,31 +1,46 @@ package ibc_testing import ( + "encoding/json" "fmt" "testing" sdk "github.com/cosmos/cosmos-sdk/types" clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" - ibctesting "github.com/cosmos/interchain-security/legacy_ibc_testing/testing" + ibctesting "github.com/cosmos/ibc-go/v7/testing" testutil "github.com/cosmos/interchain-security/testutil/integration" testkeeper "github.com/cosmos/interchain-security/testutil/keeper" consumerkeeper "github.com/cosmos/interchain-security/x/ccv/consumer/keeper" "github.com/stretchr/testify/suite" + "github.com/cometbft/cometbft/abci/types" tmencoding "github.com/cometbft/cometbft/crypto/encoding" tmtypes "github.com/cometbft/cometbft/types" ) +type ( + AppIniter func() (ibctesting.TestingApp, map[string]json.RawMessage) + ValSetAppIniter func([]types.ValidatorUpdate) AppIniter +) + // Contains generic setup code for running integration tests against a provider, consumer, // and/or democracy consumer app.go implementation. You should not need to modify or replicate this file // to run integration tests against your app.go implementations! var ( + FirstConsumerChainID string + provChainID string + democConsumerChainID string +) + +func init() { + // Disable revision format + ibctesting.ChainIDSuffix = "" FirstConsumerChainID = ibctesting.GetChainID(2) - provChainID = ibctesting.GetChainID(1) + provChainID = ibctesting.GetChainID(1) democConsumerChainID = ibctesting.GetChainID(5000) -) +} // ConsumerBundle serves as a way to store useful in-mem consumer app chain state // and relevant IBC paths in the context of CCV integration testing. @@ -47,11 +62,12 @@ func (cb ConsumerBundle) GetKeeper() consumerkeeper.Keeper { } // AddProvider adds a new provider chain to the coordinator and returns the test chain and app type -func AddProvider[T testutil.ProviderApp](t *testing.T, coordinator *ibctesting.Coordinator, appIniter ibctesting.AppIniter) ( +func AddProvider[T testutil.ProviderApp](t *testing.T, coordinator *ibctesting.Coordinator, appIniter AppIniter) ( *ibctesting.TestChain, T, ) { t.Helper() - provider := ibctesting.NewTestChain(t, coordinator, appIniter, provChainID) + ibctesting.DefaultTestingAppInit = appIniter + provider := ibctesting.NewTestChain(t, coordinator, provChainID) coordinator.Chains[provChainID] = provider providerToReturn, ok := provider.App.(T) @@ -63,11 +79,18 @@ func AddProvider[T testutil.ProviderApp](t *testing.T, coordinator *ibctesting.C } // AddDemocracyConsumer adds a new democ consumer chain to the coordinator and returns the test chain and app type -func AddDemocracyConsumer[T testutil.DemocConsumerApp](t *testing.T, coordinator *ibctesting.Coordinator, - appIniter ibctesting.AppIniter, +func AddDemocracyConsumer[T testutil.DemocConsumerApp]( + coordinator *ibctesting.Coordinator, + s *suite.Suite, + appIniter ValSetAppIniter, ) (*ibctesting.TestChain, T) { - t.Helper() - democConsumer := ibctesting.NewTestChain(t, coordinator, appIniter, democConsumerChainID) + s.T().Helper() + + // generate validators private/public key + valSet, valUpdates, signers := testutil.CreateValidators(s.T(), 4) + + ibctesting.DefaultTestingAppInit = appIniter(valUpdates) + democConsumer := ibctesting.NewTestChainWithValSet(s.T(), coordinator, democConsumerChainID, valSet, signers) coordinator.Chains[democConsumerChainID] = democConsumer democConsumerToReturn, ok := democConsumer.App.(T) @@ -88,7 +111,7 @@ func AddConsumer[Tp testutil.ProviderApp, Tc testutil.ConsumerApp]( coordinator *ibctesting.Coordinator, s *suite.Suite, index int, - appIniter ibctesting.AppIniter, + appIniter ValSetAppIniter, ) *ConsumerBundle { // consumer chain ID chainID := ibctesting.GetChainID(index + 2) @@ -134,8 +157,9 @@ func AddConsumer[Tp testutil.ProviderApp, Tc testutil.ConsumerApp]( } // create and instantiate consumer chain - testChain := ibctesting.NewTestChainWithValSet(s.T(), coordinator, - appIniter, chainID, tmtypes.NewValidatorSet(valz), providerChain.Signers) + ibctesting.DefaultTestingAppInit = appIniter(consumerGenesisState.InitialValSet) + testChain := ibctesting.NewTestChainWithValSet(s.T(), coordinator, chainID, + tmtypes.NewValidatorSet(valz), providerChain.Signers) coordinator.Chains[chainID] = testChain consumerToReturn, ok := testChain.App.(Tc) diff --git a/testutil/ibc_testing/specific_setup.go b/testutil/ibc_testing/specific_setup.go index 5a85c108e3..075c3bd0d8 100644 --- a/testutil/ibc_testing/specific_setup.go +++ b/testutil/ibc_testing/specific_setup.go @@ -8,14 +8,24 @@ import ( "encoding/json" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - ibctesting "github.com/cosmos/interchain-security/legacy_ibc_testing/testing" + sdk "github.com/cosmos/cosmos-sdk/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + ibctesting "github.com/cosmos/ibc-go/v7/testing" tmdb "github.com/cometbft/cometbft-db" + "github.com/cometbft/cometbft/abci/types" "github.com/cometbft/cometbft/libs/log" appConsumer "github.com/cosmos/interchain-security/app/consumer" appConsumerDemocracy "github.com/cosmos/interchain-security/app/consumer-democracy" appProvider "github.com/cosmos/interchain-security/app/provider" + consumertypes "github.com/cosmos/interchain-security/x/ccv/consumer/types" +) + +var ( + _ AppIniter = ProviderAppIniter + _ ValSetAppIniter = ConsumerAppIniter + _ ValSetAppIniter = DemocracyConsumerAppIniter ) // ProviderAppIniter implements ibctesting.AppIniter for a provider app @@ -25,16 +35,44 @@ func ProviderAppIniter() (ibctesting.TestingApp, map[string]json.RawMessage) { return testApp, appProvider.NewDefaultGenesisState(encoding.Codec) } -// ConsumerAppIniter implements ibctesting.AppIniter for a consumer app -func ConsumerAppIniter() (ibctesting.TestingApp, map[string]json.RawMessage) { - encoding := appConsumer.MakeTestEncodingConfig() - testApp := appConsumer.New(log.NewNopLogger(), tmdb.NewMemDB(), nil, true, simtestutil.EmptyAppOptions{}) - return testApp, appConsumer.NewDefaultGenesisState(encoding.Codec) +// ConsumerAppIniter returns a ibctesting.ValSetAppIniter for a consumer app +func ConsumerAppIniter(initValPowers []types.ValidatorUpdate) AppIniter { + return func() (ibctesting.TestingApp, map[string]json.RawMessage) { + encoding := appConsumer.MakeTestEncodingConfig() + testApp := appConsumer.New(log.NewNopLogger(), tmdb.NewMemDB(), nil, true, simtestutil.EmptyAppOptions{}) + genesisState := appConsumer.NewDefaultGenesisState(encoding.Codec) + // NOTE ibc-go/v7/testing.SetupWithGenesisValSet requires a staking module + // genesisState or it panics. Feed a minimum one. + genesisState[stakingtypes.ModuleName] = encoding.Codec.MustMarshalJSON( + &stakingtypes.GenesisState{ + Params: stakingtypes.Params{BondDenom: sdk.DefaultBondDenom}, + }, + ) + // Feed consumer genesis with provider validators + var consumerGenesis consumertypes.GenesisState + encoding.Codec.MustUnmarshalJSON(genesisState[consumertypes.ModuleName], &consumerGenesis) + consumerGenesis.InitialValSet = initValPowers + consumerGenesis.Params.Enabled = true + genesisState[consumertypes.ModuleName] = encoding.Codec.MustMarshalJSON(&consumerGenesis) + + return testApp, genesisState + } } -// DemocracyConsumerAppIniter implements ibctesting.AppIniter for a democracy consumer app -func DemocracyConsumerAppIniter() (ibctesting.TestingApp, map[string]json.RawMessage) { - encoding := appConsumerDemocracy.MakeTestEncodingConfig() - testApp := appConsumerDemocracy.New(log.NewNopLogger(), tmdb.NewMemDB(), nil, true, simtestutil.EmptyAppOptions{}) - return testApp, appConsumerDemocracy.NewDefaultGenesisState(encoding.Codec) +// DemocracyConsumerAppIniter implements ibctesting.ValSetAppIniter for a democracy consumer app +func DemocracyConsumerAppIniter(initValPowers []types.ValidatorUpdate) AppIniter { + return func() (ibctesting.TestingApp, map[string]json.RawMessage) { + encoding := appConsumerDemocracy.MakeTestEncodingConfig() + testApp := appConsumerDemocracy.New(log.NewNopLogger(), tmdb.NewMemDB(), nil, true, simtestutil.EmptyAppOptions{}) + genesisState := appConsumerDemocracy.NewDefaultGenesisState(encoding.Codec) + // Feed consumer genesis with provider validators + // TODO See if useful for democracy + var consumerGenesis consumertypes.GenesisState + encoding.Codec.MustUnmarshalJSON(genesisState[consumertypes.ModuleName], &consumerGenesis) + consumerGenesis.InitialValSet = initValPowers + consumerGenesis.Params.Enabled = true + genesisState[consumertypes.ModuleName] = encoding.Codec.MustMarshalJSON(&consumerGenesis) + + return testApp, genesisState + } } diff --git a/testutil/integration/interfaces.go b/testutil/integration/interfaces.go index f4e366db50..abf6cf2f38 100644 --- a/testutil/integration/interfaces.go +++ b/testutil/integration/interfaces.go @@ -15,7 +15,7 @@ import ( paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" "github.com/cosmos/cosmos-sdk/x/staking/types" - ibctesting "github.com/cosmos/interchain-security/legacy_ibc_testing/testing" + ibctesting "github.com/cosmos/ibc-go/v7/testing" consumerkeeper "github.com/cosmos/interchain-security/x/ccv/consumer/keeper" providerkeeper "github.com/cosmos/interchain-security/x/ccv/provider/keeper" ccvtypes "github.com/cosmos/interchain-security/x/ccv/types" diff --git a/testutil/integration/validators.go b/testutil/integration/validators.go new file mode 100644 index 0000000000..9859bb55f1 --- /dev/null +++ b/testutil/integration/validators.go @@ -0,0 +1,46 @@ +package integration + +import ( + "testing" + + "github.com/cometbft/cometbft/abci/types" + tmencoding "github.com/cometbft/cometbft/crypto/encoding" + tmtypes "github.com/cometbft/cometbft/types" + "github.com/cosmos/cosmos-sdk/testutil/mock" + "github.com/stretchr/testify/require" +) + +func CreateValidators(t *testing.T, n int) ( + *tmtypes.ValidatorSet, []types.ValidatorUpdate, map[string]tmtypes.PrivValidator, +) { + // generate validators private/public key + var ( + validators []*tmtypes.Validator + signersByAddress = make(map[string]tmtypes.PrivValidator, n) + ) + for i := 0; i < n; i++ { + privVal := mock.NewPV() + pubKey, err := privVal.GetPubKey() + require.NoError(t, err) + val := tmtypes.NewValidator(pubKey, 1) + validators = append(validators, val) + signersByAddress[pubKey.Address().String()] = privVal + } + // construct validator set; + // Note that the validators are sorted by voting power + // or, if equal, by address lexical order + valSet := tmtypes.NewValidatorSet(validators) + return valSet, ToValidatorUpdates(t, valSet), signersByAddress +} + +func ToValidatorUpdates(t *testing.T, valSet *tmtypes.ValidatorSet) (valUpdates []types.ValidatorUpdate) { + for _, val := range valSet.Validators { + protoPubKey, err := tmencoding.PubKeyToProto(val.PubKey) + require.NoError(t, err) + valUpdates = append(valUpdates, types.ValidatorUpdate{ + PubKey: protoPubKey, + Power: val.VotingPower, + }) + } + return +} diff --git a/testutil/simibc/chain_util.go b/testutil/simibc/chain_util.go index 0c3f9aff52..64b0e913b2 100644 --- a/testutil/simibc/chain_util.go +++ b/testutil/simibc/chain_util.go @@ -5,10 +5,10 @@ import ( abci "github.com/cometbft/cometbft/abci/types" tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + sdk "github.com/cosmos/cosmos-sdk/types" channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" ibctmtypes "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" - ibctestingcore "github.com/cosmos/interchain-security/legacy_ibc_testing/core" - ibctesting "github.com/cosmos/interchain-security/legacy_ibc_testing/testing" + ibctesting "github.com/cosmos/ibc-go/v7/testing" ) // BeginBlock updates the current header and calls the app.BeginBlock method. @@ -54,14 +54,37 @@ func EndBlock(c *ibctesting.TestChain, preCommitCallback func()) (*ibctmtypes.He c.LastHeader = c.CurrentTMClientHeader() - packets := []channeltypes.Packet{} + sdkEvts := ABCIToSDKEvents(ebRes.Events) + packets := ParsePacketsFromEvents(sdkEvts) - for _, e := range ebRes.Events { - if e.Type == channeltypes.EventTypeSendPacket { - packet, _ := ibctestingcore.ReconstructPacketFromEvent(e) + return c.LastHeader, packets +} + +// ParsePacketsFromEvents returns all packets found in events. +func ParsePacketsFromEvents(events []sdk.Event) (packets []channeltypes.Packet) { + for i, ev := range events { + if ev.Type == channeltypes.EventTypeSendPacket { + packet, err := ibctesting.ParsePacketFromEvents(events[i:]) + if err != nil { + panic(err) + } packets = append(packets, packet) } } + return +} - return c.LastHeader, packets +// ABCIToSDKEvents converts a list of ABCI events to Cosmos SDK events. +func ABCIToSDKEvents(abciEvents []abci.Event) sdk.Events { + var events sdk.Events + for _, evt := range abciEvents { + var attributes []sdk.Attribute + for _, attr := range evt.GetAttributes() { + attributes = append(attributes, sdk.NewAttribute(attr.Key, attr.Value)) + } + + events = events.AppendEvent(sdk.NewEvent(evt.GetType(), attributes...)) + } + + return events } diff --git a/testutil/simibc/relay_util.go b/testutil/simibc/relay_util.go index b3ac7bcd93..705cfc8874 100644 --- a/testutil/simibc/relay_util.go +++ b/testutil/simibc/relay_util.go @@ -8,8 +8,8 @@ import ( channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" host "github.com/cosmos/ibc-go/v7/modules/core/24-host" ibctmtypes "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" - simapp "github.com/cosmos/interchain-security/legacy_ibc_testing/simapp" - ibctesting "github.com/cosmos/interchain-security/legacy_ibc_testing/testing" + ibctesting "github.com/cosmos/ibc-go/v7/testing" + simapp "github.com/cosmos/ibc-go/v7/testing/simapp" "github.com/stretchr/testify/require" ) diff --git a/testutil/simibc/relayed_path.go b/testutil/simibc/relayed_path.go index 82be53f68a..daf32f0c84 100644 --- a/testutil/simibc/relayed_path.go +++ b/testutil/simibc/relayed_path.go @@ -5,7 +5,7 @@ import ( "time" ibctmtypes "github.com/cosmos/ibc-go/v7/modules/light-clients/07-tendermint" - ibctesting "github.com/cosmos/interchain-security/legacy_ibc_testing/testing" + ibctesting "github.com/cosmos/ibc-go/v7/testing" ) // RelayedPath is a wrapper around ibctesting.Path gives fine-grained diff --git a/x/ccv/provider/keeper/keeper_test.go b/x/ccv/provider/keeper/keeper_test.go index 8ec7902130..10be3b4ed5 100644 --- a/x/ccv/provider/keeper/keeper_test.go +++ b/x/ccv/provider/keeper/keeper_test.go @@ -8,7 +8,7 @@ import ( cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" - ibcsimapp "github.com/cosmos/interchain-security/legacy_ibc_testing/simapp" + ibctesting "github.com/cosmos/ibc-go/v7/testing" abci "github.com/cometbft/cometbft/abci/types" tmprotocrypto "github.com/cometbft/cometbft/proto/tendermint/crypto" @@ -156,7 +156,7 @@ func TestPendingVSCs(t *testing.T) { pending := providerKeeper.GetPendingVSCPackets(ctx, chainID) require.Len(t, pending, 0) - pks := ibcsimapp.CreateTestPubKeys(4) + _, pks, _ := ibctesting.GenerateKeys(t, 4) var ppks [4]tmprotocrypto.PublicKey for i, pk := range pks { ppks[i], _ = cryptocodec.ToTmProtoPublicKey(pk) diff --git a/x/ccv/provider/keeper/relay_test.go b/x/ccv/provider/keeper/relay_test.go index d5c6cb4f6d..241b489fd1 100644 --- a/x/ccv/provider/keeper/relay_test.go +++ b/x/ccv/provider/keeper/relay_test.go @@ -11,7 +11,7 @@ import ( clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" exported "github.com/cosmos/ibc-go/v7/modules/core/exported" - ibcsimapp "github.com/cosmos/interchain-security/legacy_ibc_testing/simapp" + ibctesting "github.com/cosmos/ibc-go/v7/testing" cryptotestutil "github.com/cosmos/interchain-security/testutil/crypto" testkeeper "github.com/cosmos/interchain-security/testutil/keeper" "github.com/cosmos/interchain-security/x/ccv/provider/keeper" @@ -24,7 +24,7 @@ import ( // TestQueueVSCPackets tests queueing validator set updates. func TestQueueVSCPackets(t *testing.T) { - key := ibcsimapp.CreateTestPubKeys(1)[0] + _, _, key := ibctesting.GenerateKeys(t, 1) tmPubKey, _ := cryptocodec.ToTmProtoPublicKey(key) testCases := []struct { diff --git a/x/ccv/types/utils_test.go b/x/ccv/types/utils_test.go index dc3a5bba18..8413f464b5 100644 --- a/x/ccv/types/utils_test.go +++ b/x/ccv/types/utils_test.go @@ -5,13 +5,13 @@ import ( abci "github.com/cometbft/cometbft/abci/types" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" - ibcsimapp "github.com/cosmos/interchain-security/legacy_ibc_testing/simapp" + ibctesting "github.com/cosmos/ibc-go/v7/testing" "github.com/cosmos/interchain-security/x/ccv/types" "github.com/stretchr/testify/require" ) func TestAccumulateChanges(t *testing.T) { - testKeys := ibcsimapp.CreateTestPubKeys(2) + _, testKeys, _ := ibctesting.GenerateKeys(t, 2) tmPubKey, _ := cryptocodec.ToTmProtoPublicKey(testKeys[0]) tmPubKey2, _ := cryptocodec.ToTmProtoPublicKey(testKeys[1])