Some checks failed
CodeQL / Analyze (push) Waiting to run
golangci-lint / lint (push) Waiting to run
Tests / Code Coverage / build (amd64) (push) Waiting to run
Tests / Code Coverage / build (arm64) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[additional-args:-tags="test_e2e" name:e2e path:./e2e]) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[name:08-wasm path:./modules/light-clients/08-wasm]) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[name:ibc-go path:.]) (push) Waiting to run
Docker Build & Push Simapp (main) / docker-build (push) Has been cancelled
898 lines
31 KiB
Go
898 lines
31 KiB
Go
package keeper_test
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/cosmos/gogoproto/proto"
|
|
|
|
sdkmath "cosmossdk.io/math"
|
|
|
|
"git.cw.tr/mukan-network/mukan-sdk/testutil/testdata"
|
|
sdk "git.cw.tr/mukan-network/mukan-sdk/types"
|
|
authtypes "git.cw.tr/mukan-network/mukan-sdk/x/auth/types"
|
|
banktypes "git.cw.tr/mukan-network/mukan-sdk/x/bank/types"
|
|
disttypes "git.cw.tr/mukan-network/mukan-sdk/x/distribution/types"
|
|
govtypesv1 "git.cw.tr/mukan-network/mukan-sdk/x/gov/types/v1"
|
|
stakingtypes "git.cw.tr/mukan-network/mukan-sdk/x/staking/types"
|
|
|
|
"git.cw.tr/mukan-network/mukan-ibc/modules/apps/27-interchain-accounts/host/types"
|
|
icatypes "git.cw.tr/mukan-network/mukan-ibc/modules/apps/27-interchain-accounts/types"
|
|
transfertypes "git.cw.tr/mukan-network/mukan-ibc/modules/apps/transfer/types"
|
|
channeltypes "git.cw.tr/mukan-network/mukan-ibc/modules/core/04-channel/types"
|
|
ibcerrors "git.cw.tr/mukan-network/mukan-ibc/modules/core/errors"
|
|
ibctesting "git.cw.tr/mukan-network/mukan-ibc/testing"
|
|
)
|
|
|
|
func (suite *KeeperTestSuite) TestOnRecvPacket() {
|
|
testedOrderings := []channeltypes.Order{channeltypes.UNORDERED, channeltypes.ORDERED}
|
|
testedEncodings := []string{icatypes.EncodingProtobuf, icatypes.EncodingProto3JSON}
|
|
|
|
var (
|
|
path *ibctesting.Path
|
|
packetData []byte
|
|
)
|
|
|
|
testCases := []struct {
|
|
msg string
|
|
malleate func(encoding string)
|
|
expErr error
|
|
}{
|
|
{
|
|
"interchain account successfully executes an arbitrary message type using the * (allow all message types) param",
|
|
func(encoding string) {
|
|
interchainAccountAddr, found := suite.chainB.GetSimApp().ICAHostKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), ibctesting.FirstConnectionID, path.EndpointA.ChannelConfig.PortID)
|
|
suite.Require().True(found)
|
|
|
|
proposal, err := govtypesv1.NewProposal([]sdk.Msg{getTestProposalMessage()}, govtypesv1.DefaultStartingProposalID, time.Now(), time.Now().Add(time.Hour), "test proposal", "title", "Description", sdk.AccAddress(interchainAccountAddr), false)
|
|
suite.Require().NoError(err)
|
|
|
|
err = suite.chainB.GetSimApp().GovKeeper.SetProposal(suite.chainB.GetContext(), proposal)
|
|
suite.Require().NoError(err)
|
|
err = suite.chainB.GetSimApp().GovKeeper.ActivateVotingPeriod(suite.chainB.GetContext(), proposal)
|
|
suite.Require().NoError(err)
|
|
|
|
msg := &govtypesv1.MsgVote{
|
|
ProposalId: govtypesv1.DefaultStartingProposalID,
|
|
Voter: interchainAccountAddr,
|
|
Option: govtypesv1.OptionYes,
|
|
}
|
|
|
|
data, err := icatypes.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []proto.Message{msg}, encoding)
|
|
suite.Require().NoError(err)
|
|
|
|
icaPacketData := icatypes.InterchainAccountPacketData{
|
|
Type: icatypes.EXECUTE_TX,
|
|
Data: data,
|
|
}
|
|
|
|
packetData = icaPacketData.GetBytes()
|
|
|
|
params := types.NewParams(true, []string{"*"})
|
|
suite.chainB.GetSimApp().ICAHostKeeper.SetParams(suite.chainB.GetContext(), params)
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
"interchain account successfully executes banktypes.MsgSend",
|
|
func(encoding string) {
|
|
interchainAccountAddr, found := suite.chainB.GetSimApp().ICAHostKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), ibctesting.FirstConnectionID, path.EndpointA.ChannelConfig.PortID)
|
|
suite.Require().True(found)
|
|
|
|
msg := &banktypes.MsgSend{
|
|
FromAddress: interchainAccountAddr,
|
|
ToAddress: suite.chainB.SenderAccount.GetAddress().String(),
|
|
Amount: sdk.NewCoins(ibctesting.TestCoin),
|
|
}
|
|
|
|
data, err := icatypes.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []proto.Message{msg}, encoding)
|
|
suite.Require().NoError(err)
|
|
|
|
icaPacketData := icatypes.InterchainAccountPacketData{
|
|
Type: icatypes.EXECUTE_TX,
|
|
Data: data,
|
|
}
|
|
|
|
packetData = icaPacketData.GetBytes()
|
|
|
|
params := types.NewParams(true, []string{sdk.MsgTypeURL(msg)})
|
|
suite.chainB.GetSimApp().ICAHostKeeper.SetParams(suite.chainB.GetContext(), params)
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
"interchain account successfully executes stakingtypes.MsgDelegate",
|
|
func(encoding string) {
|
|
interchainAccountAddr, found := suite.chainB.GetSimApp().ICAHostKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), ibctesting.FirstConnectionID, path.EndpointA.ChannelConfig.PortID)
|
|
suite.Require().True(found)
|
|
|
|
validatorAddr := (sdk.ValAddress)(suite.chainB.Vals.Validators[0].Address)
|
|
msg := &stakingtypes.MsgDelegate{
|
|
DelegatorAddress: interchainAccountAddr,
|
|
ValidatorAddress: validatorAddr.String(),
|
|
Amount: sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(5000)),
|
|
}
|
|
|
|
data, err := icatypes.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []proto.Message{msg}, encoding)
|
|
suite.Require().NoError(err)
|
|
|
|
icaPacketData := icatypes.InterchainAccountPacketData{
|
|
Type: icatypes.EXECUTE_TX,
|
|
Data: data,
|
|
}
|
|
|
|
packetData = icaPacketData.GetBytes()
|
|
|
|
params := types.NewParams(true, []string{sdk.MsgTypeURL(msg)})
|
|
suite.chainB.GetSimApp().ICAHostKeeper.SetParams(suite.chainB.GetContext(), params)
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
"interchain account successfully executes stakingtypes.MsgDelegate and stakingtypes.MsgUndelegate sequentially",
|
|
func(encoding string) {
|
|
interchainAccountAddr, found := suite.chainB.GetSimApp().ICAHostKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), ibctesting.FirstConnectionID, path.EndpointA.ChannelConfig.PortID)
|
|
suite.Require().True(found)
|
|
|
|
validatorAddr := (sdk.ValAddress)(suite.chainB.Vals.Validators[0].Address)
|
|
msgDelegate := &stakingtypes.MsgDelegate{
|
|
DelegatorAddress: interchainAccountAddr,
|
|
ValidatorAddress: validatorAddr.String(),
|
|
Amount: sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(5000)),
|
|
}
|
|
|
|
msgUndelegate := &stakingtypes.MsgUndelegate{
|
|
DelegatorAddress: interchainAccountAddr,
|
|
ValidatorAddress: validatorAddr.String(),
|
|
Amount: sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(5000)),
|
|
}
|
|
|
|
data, err := icatypes.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []proto.Message{msgDelegate, msgUndelegate}, encoding)
|
|
suite.Require().NoError(err)
|
|
|
|
icaPacketData := icatypes.InterchainAccountPacketData{
|
|
Type: icatypes.EXECUTE_TX,
|
|
Data: data,
|
|
}
|
|
|
|
packetData = icaPacketData.GetBytes()
|
|
|
|
params := types.NewParams(true, []string{sdk.MsgTypeURL(msgDelegate), sdk.MsgTypeURL(msgUndelegate)})
|
|
suite.chainB.GetSimApp().ICAHostKeeper.SetParams(suite.chainB.GetContext(), params)
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
"interchain account successfully executes govtypesv1.MsgSubmitProposal",
|
|
func(encoding string) {
|
|
interchainAccountAddr, found := suite.chainB.GetSimApp().ICAHostKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), ibctesting.FirstConnectionID, path.EndpointA.ChannelConfig.PortID)
|
|
suite.Require().True(found)
|
|
|
|
msg, err := govtypesv1.NewMsgSubmitProposal([]sdk.Msg{}, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(100000))), interchainAccountAddr, "metadata", "title", "summary", false)
|
|
suite.Require().NoError(err)
|
|
|
|
data, err := icatypes.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []proto.Message{msg}, encoding)
|
|
suite.Require().NoError(err)
|
|
|
|
icaPacketData := icatypes.InterchainAccountPacketData{
|
|
Type: icatypes.EXECUTE_TX,
|
|
Data: data,
|
|
}
|
|
|
|
packetData = icaPacketData.GetBytes()
|
|
|
|
params := types.NewParams(true, []string{sdk.MsgTypeURL(msg)})
|
|
suite.chainB.GetSimApp().ICAHostKeeper.SetParams(suite.chainB.GetContext(), params)
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
"interchain account successfully executes govtypesv1.MsgVote",
|
|
func(encoding string) {
|
|
interchainAccountAddr, found := suite.chainB.GetSimApp().ICAHostKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), ibctesting.FirstConnectionID, path.EndpointA.ChannelConfig.PortID)
|
|
suite.Require().True(found)
|
|
|
|
proposal, err := govtypesv1.NewProposal([]sdk.Msg{getTestProposalMessage()}, govtypesv1.DefaultStartingProposalID, time.Now(), time.Now().Add(time.Hour), "test proposal", "title", "Description", sdk.AccAddress(interchainAccountAddr), false)
|
|
suite.Require().NoError(err)
|
|
|
|
err = suite.chainB.GetSimApp().GovKeeper.SetProposal(suite.chainB.GetContext(), proposal)
|
|
suite.Require().NoError(err)
|
|
err = suite.chainB.GetSimApp().GovKeeper.ActivateVotingPeriod(suite.chainB.GetContext(), proposal)
|
|
suite.Require().NoError(err)
|
|
|
|
msg := &govtypesv1.MsgVote{
|
|
ProposalId: govtypesv1.DefaultStartingProposalID,
|
|
Voter: interchainAccountAddr,
|
|
Option: govtypesv1.OptionYes,
|
|
}
|
|
|
|
data, err := icatypes.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []proto.Message{msg}, encoding)
|
|
suite.Require().NoError(err)
|
|
|
|
icaPacketData := icatypes.InterchainAccountPacketData{
|
|
Type: icatypes.EXECUTE_TX,
|
|
Data: data,
|
|
}
|
|
|
|
packetData = icaPacketData.GetBytes()
|
|
|
|
params := types.NewParams(true, []string{sdk.MsgTypeURL(msg)})
|
|
suite.chainB.GetSimApp().ICAHostKeeper.SetParams(suite.chainB.GetContext(), params)
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
"interchain account successfully executes disttypes.MsgFundCommunityPool",
|
|
func(encoding string) {
|
|
interchainAccountAddr, found := suite.chainB.GetSimApp().ICAHostKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), ibctesting.FirstConnectionID, path.EndpointA.ChannelConfig.PortID)
|
|
suite.Require().True(found)
|
|
|
|
msg := &disttypes.MsgFundCommunityPool{
|
|
Amount: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(5000))),
|
|
Depositor: interchainAccountAddr,
|
|
}
|
|
|
|
data, err := icatypes.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []proto.Message{msg}, encoding)
|
|
suite.Require().NoError(err)
|
|
|
|
icaPacketData := icatypes.InterchainAccountPacketData{
|
|
Type: icatypes.EXECUTE_TX,
|
|
Data: data,
|
|
}
|
|
|
|
packetData = icaPacketData.GetBytes()
|
|
|
|
params := types.NewParams(true, []string{sdk.MsgTypeURL(msg)})
|
|
suite.chainB.GetSimApp().ICAHostKeeper.SetParams(suite.chainB.GetContext(), params)
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
"interchain account successfully executes icahosttypes.MsgModuleQuerySafe",
|
|
func(encoding string) {
|
|
interchainAccountAddr, found := suite.chainB.GetSimApp().ICAHostKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), ibctesting.FirstConnectionID, path.EndpointA.ChannelConfig.PortID)
|
|
suite.Require().True(found)
|
|
|
|
balanceQuery := banktypes.NewQueryBalanceRequest(suite.chainB.SenderAccount.GetAddress(), sdk.DefaultBondDenom)
|
|
queryBz, err := balanceQuery.Marshal()
|
|
suite.Require().NoError(err)
|
|
|
|
msg := types.NewMsgModuleQuerySafe(interchainAccountAddr, []types.QueryRequest{
|
|
{
|
|
Path: "/cosmos.bank.v1beta1.Query/Balance",
|
|
Data: queryBz,
|
|
},
|
|
})
|
|
|
|
data, err := icatypes.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []proto.Message{msg}, encoding)
|
|
suite.Require().NoError(err)
|
|
|
|
icaPacketData := icatypes.InterchainAccountPacketData{
|
|
Type: icatypes.EXECUTE_TX,
|
|
Data: data,
|
|
}
|
|
|
|
packetData = icaPacketData.GetBytes()
|
|
|
|
params := types.NewParams(true, []string{sdk.MsgTypeURL(msg)})
|
|
suite.chainB.GetSimApp().ICAHostKeeper.SetParams(suite.chainB.GetContext(), params)
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
"interchain account successfully executes disttypes.MsgSetWithdrawAddress",
|
|
func(encoding string) {
|
|
interchainAccountAddr, found := suite.chainB.GetSimApp().ICAHostKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), ibctesting.FirstConnectionID, path.EndpointA.ChannelConfig.PortID)
|
|
suite.Require().True(found)
|
|
|
|
msg := &disttypes.MsgSetWithdrawAddress{
|
|
DelegatorAddress: interchainAccountAddr,
|
|
WithdrawAddress: suite.chainB.SenderAccount.GetAddress().String(),
|
|
}
|
|
|
|
data, err := icatypes.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []proto.Message{msg}, encoding)
|
|
suite.Require().NoError(err)
|
|
|
|
icaPacketData := icatypes.InterchainAccountPacketData{
|
|
Type: icatypes.EXECUTE_TX,
|
|
Data: data,
|
|
}
|
|
|
|
packetData = icaPacketData.GetBytes()
|
|
|
|
params := types.NewParams(true, []string{sdk.MsgTypeURL(msg)})
|
|
suite.chainB.GetSimApp().ICAHostKeeper.SetParams(suite.chainB.GetContext(), params)
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
"interchain account successfully executes transfertypes.MsgTransfer",
|
|
func(encoding string) {
|
|
transferPath := ibctesting.NewTransferPath(suite.chainB, suite.chainC)
|
|
|
|
transferPath.Setup()
|
|
|
|
interchainAccountAddr, found := suite.chainB.GetSimApp().ICAHostKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), ibctesting.FirstConnectionID, path.EndpointA.ChannelConfig.PortID)
|
|
suite.Require().True(found)
|
|
|
|
msg := transfertypes.NewMsgTransfer(
|
|
transferPath.EndpointA.ChannelConfig.PortID,
|
|
transferPath.EndpointA.ChannelID,
|
|
ibctesting.TestCoin,
|
|
interchainAccountAddr,
|
|
suite.chainA.SenderAccount.GetAddress().String(),
|
|
suite.chainB.GetTimeoutHeight(),
|
|
0,
|
|
"",
|
|
)
|
|
|
|
data, err := icatypes.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []proto.Message{msg}, encoding)
|
|
suite.Require().NoError(err)
|
|
|
|
icaPacketData := icatypes.InterchainAccountPacketData{
|
|
Type: icatypes.EXECUTE_TX,
|
|
Data: data,
|
|
}
|
|
|
|
packetData = icaPacketData.GetBytes()
|
|
|
|
params := types.NewParams(true, []string{sdk.MsgTypeURL(msg)})
|
|
suite.chainB.GetSimApp().ICAHostKeeper.SetParams(suite.chainB.GetContext(), params)
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
"Msg fails its ValidateBasic: MsgTransfer has an empty receiver",
|
|
func(encoding string) {
|
|
transferPath := ibctesting.NewTransferPath(suite.chainB, suite.chainC)
|
|
transferPath.Setup()
|
|
|
|
interchainAccountAddr, found := suite.chainB.GetSimApp().ICAHostKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), ibctesting.FirstConnectionID, path.EndpointA.ChannelConfig.PortID)
|
|
suite.Require().True(found)
|
|
|
|
msg := transfertypes.NewMsgTransfer(
|
|
transferPath.EndpointA.ChannelConfig.PortID,
|
|
transferPath.EndpointA.ChannelID,
|
|
ibctesting.TestCoin,
|
|
interchainAccountAddr,
|
|
"",
|
|
suite.chainB.GetTimeoutHeight(),
|
|
0,
|
|
"",
|
|
)
|
|
|
|
data, err := icatypes.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []proto.Message{msg}, encoding)
|
|
suite.Require().NoError(err)
|
|
|
|
icaPacketData := icatypes.InterchainAccountPacketData{
|
|
Type: icatypes.EXECUTE_TX,
|
|
Data: data,
|
|
}
|
|
|
|
packetData = icaPacketData.GetBytes()
|
|
|
|
params := types.NewParams(true, []string{sdk.MsgTypeURL(msg)})
|
|
suite.chainB.GetSimApp().ICAHostKeeper.SetParams(suite.chainB.GetContext(), params)
|
|
},
|
|
ibcerrors.ErrInvalidAddress,
|
|
},
|
|
{
|
|
"unregistered sdk.Msg",
|
|
func(encoding string) {
|
|
msg := &banktypes.MsgSendResponse{}
|
|
|
|
data, err := icatypes.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []proto.Message{msg}, encoding)
|
|
suite.Require().NoError(err)
|
|
|
|
icaPacketData := icatypes.InterchainAccountPacketData{
|
|
Type: icatypes.EXECUTE_TX,
|
|
Data: data,
|
|
}
|
|
|
|
packetData = icaPacketData.GetBytes()
|
|
|
|
params := types.NewParams(true, []string{"/" + proto.MessageName(msg)})
|
|
suite.chainB.GetSimApp().ICAHostKeeper.SetParams(suite.chainB.GetContext(), params)
|
|
},
|
|
ibcerrors.ErrInvalidType,
|
|
},
|
|
{
|
|
"cannot unmarshal interchain account packet data",
|
|
func(encoding string) {
|
|
packetData = []byte{}
|
|
},
|
|
ibcerrors.ErrInvalidType,
|
|
},
|
|
{
|
|
"cannot deserialize interchain account packet data messages",
|
|
func(encoding string) {
|
|
data := []byte("invalid packet data")
|
|
|
|
icaPacketData := icatypes.InterchainAccountPacketData{
|
|
Type: icatypes.EXECUTE_TX,
|
|
Data: data,
|
|
}
|
|
|
|
packetData = icaPacketData.GetBytes()
|
|
},
|
|
ibcerrors.ErrInvalidType,
|
|
},
|
|
{
|
|
"invalid packet type - UNSPECIFIED",
|
|
func(encoding string) {
|
|
data, err := icatypes.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []proto.Message{&banktypes.MsgSend{}}, encoding)
|
|
suite.Require().NoError(err)
|
|
|
|
icaPacketData := icatypes.InterchainAccountPacketData{
|
|
Type: icatypes.UNSPECIFIED,
|
|
Data: data,
|
|
}
|
|
|
|
packetData = icaPacketData.GetBytes()
|
|
},
|
|
icatypes.ErrUnknownDataType,
|
|
},
|
|
{
|
|
"unauthorised: interchain account not found for controller port ID",
|
|
func(encoding string) {
|
|
path.EndpointA.ChannelConfig.PortID = "invalid-port-id" //nolint:goconst
|
|
|
|
data, err := icatypes.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []proto.Message{&banktypes.MsgSend{}}, encoding)
|
|
suite.Require().NoError(err)
|
|
|
|
icaPacketData := icatypes.InterchainAccountPacketData{
|
|
Type: icatypes.EXECUTE_TX,
|
|
Data: data,
|
|
}
|
|
|
|
packetData = icaPacketData.GetBytes()
|
|
},
|
|
icatypes.ErrInterchainAccountNotFound,
|
|
},
|
|
{
|
|
"unauthorised: message type not allowed", // NOTE: do not update params to explicitly force the error
|
|
func(encoding string) {
|
|
msg := &banktypes.MsgSend{
|
|
FromAddress: suite.chainB.SenderAccount.GetAddress().String(),
|
|
ToAddress: suite.chainB.SenderAccount.GetAddress().String(),
|
|
Amount: sdk.NewCoins(ibctesting.TestCoin),
|
|
}
|
|
|
|
data, err := icatypes.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []proto.Message{msg}, encoding)
|
|
suite.Require().NoError(err)
|
|
|
|
icaPacketData := icatypes.InterchainAccountPacketData{
|
|
Type: icatypes.EXECUTE_TX,
|
|
Data: data,
|
|
}
|
|
|
|
packetData = icaPacketData.GetBytes()
|
|
},
|
|
ibcerrors.ErrUnauthorized,
|
|
},
|
|
{
|
|
"unauthorised: signer address is not the interchain account associated with the controller portID",
|
|
func(encoding string) {
|
|
msg := &banktypes.MsgSend{
|
|
FromAddress: suite.chainB.SenderAccount.GetAddress().String(), // unexpected signer
|
|
ToAddress: suite.chainB.SenderAccount.GetAddress().String(),
|
|
Amount: sdk.NewCoins(ibctesting.TestCoin),
|
|
}
|
|
|
|
data, err := icatypes.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []proto.Message{msg}, encoding)
|
|
suite.Require().NoError(err)
|
|
|
|
icaPacketData := icatypes.InterchainAccountPacketData{
|
|
Type: icatypes.EXECUTE_TX,
|
|
Data: data,
|
|
}
|
|
|
|
packetData = icaPacketData.GetBytes()
|
|
|
|
params := types.NewParams(true, []string{sdk.MsgTypeURL(msg)})
|
|
suite.chainB.GetSimApp().ICAHostKeeper.SetParams(suite.chainB.GetContext(), params)
|
|
},
|
|
ibcerrors.ErrUnauthorized,
|
|
},
|
|
}
|
|
|
|
for _, ordering := range testedOrderings {
|
|
for _, encoding := range testedEncodings {
|
|
for _, tc := range testCases {
|
|
suite.Run(tc.msg, func() {
|
|
suite.SetupTest() // reset
|
|
|
|
path = NewICAPath(suite.chainA, suite.chainB, encoding, ordering)
|
|
path.SetupConnections()
|
|
|
|
err := SetupICAPath(path, TestOwnerAddress)
|
|
suite.Require().NoError(err)
|
|
|
|
portID, err := icatypes.NewControllerPortID(TestOwnerAddress)
|
|
suite.Require().NoError(err)
|
|
|
|
// Get the address of the interchain account stored in state during handshake step
|
|
storedAddr, found := suite.chainB.GetSimApp().ICAHostKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), ibctesting.FirstConnectionID, portID)
|
|
suite.Require().True(found)
|
|
|
|
icaAddr, err := sdk.AccAddressFromBech32(storedAddr)
|
|
suite.Require().NoError(err)
|
|
|
|
// Check if account is created
|
|
interchainAccount := suite.chainB.GetSimApp().AccountKeeper.GetAccount(suite.chainB.GetContext(), icaAddr)
|
|
suite.Require().Equal(interchainAccount.GetAddress().String(), storedAddr)
|
|
|
|
suite.fundICAWallet(suite.chainB.GetContext(), path.EndpointA.ChannelConfig.PortID, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(1000000))))
|
|
|
|
tc.malleate(encoding) // malleate mutates test data
|
|
|
|
packet := channeltypes.NewPacket(
|
|
packetData,
|
|
suite.chainA.SenderAccount.GetSequence(),
|
|
path.EndpointA.ChannelConfig.PortID,
|
|
path.EndpointA.ChannelID,
|
|
path.EndpointB.ChannelConfig.PortID,
|
|
path.EndpointB.ChannelID,
|
|
suite.chainB.GetTimeoutHeight(),
|
|
0,
|
|
)
|
|
|
|
txResponse, err := suite.chainB.GetSimApp().ICAHostKeeper.OnRecvPacket(suite.chainB.GetContext(), packet)
|
|
|
|
if tc.expErr == nil {
|
|
suite.Require().NoError(err)
|
|
suite.Require().NotNil(txResponse)
|
|
} else {
|
|
suite.Require().ErrorIs(err, tc.expErr)
|
|
suite.Require().Nil(txResponse)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (suite *KeeperTestSuite) TestJSONOnRecvPacket() {
|
|
var (
|
|
path *ibctesting.Path
|
|
packetData []byte
|
|
)
|
|
interchainAccountAddr := "cosmos15ulrf36d4wdtrtqzkgaan9ylwuhs7k7qz753uk"
|
|
|
|
testCases := []struct {
|
|
msg string
|
|
malleate func(icaAddress string)
|
|
expErr error
|
|
}{
|
|
{
|
|
"interchain account successfully executes an arbitrary message type using the * (allow all message types) param",
|
|
func(icaAddress string) {
|
|
proposal, err := govtypesv1.NewProposal([]sdk.Msg{getTestProposalMessage()}, govtypesv1.DefaultStartingProposalID, suite.chainA.GetContext().BlockTime(), suite.chainA.GetContext().BlockTime(), "test proposal", "title", "Description", sdk.AccAddress(interchainAccountAddr), false)
|
|
suite.Require().NoError(err)
|
|
|
|
err = suite.chainB.GetSimApp().GovKeeper.SetProposal(suite.chainB.GetContext(), proposal)
|
|
suite.Require().NoError(err)
|
|
err = suite.chainB.GetSimApp().GovKeeper.ActivateVotingPeriod(suite.chainB.GetContext(), proposal)
|
|
suite.Require().NoError(err)
|
|
|
|
msgBytes := []byte(`{
|
|
"messages": [
|
|
{
|
|
"@type": "/cosmos.gov.v1.MsgVote",
|
|
"voter": "` + icaAddress + `",
|
|
"proposal_id": 1,
|
|
"option": 1
|
|
}
|
|
]
|
|
}`)
|
|
// this is the way cosmwasm encodes byte arrays by default
|
|
// golang doesn't use this encoding by default, but it can still deserialize:
|
|
byteArrayString := strings.Join(strings.Fields(fmt.Sprint(msgBytes)), ",") //nolint:staticcheck
|
|
|
|
packetData = []byte(`{
|
|
"type": 1,
|
|
"data":` + byteArrayString + `
|
|
}`)
|
|
|
|
params := types.NewParams(true, []string{"*"})
|
|
suite.chainB.GetSimApp().ICAHostKeeper.SetParams(suite.chainB.GetContext(), params)
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
"interchain account successfully executes banktypes.MsgSend",
|
|
func(icaAddress string) {
|
|
msgBytes := []byte(`{
|
|
"messages": [
|
|
{
|
|
"@type": "/cosmos.bank.v1beta1.MsgSend",
|
|
"from_address": "` + icaAddress + `",
|
|
"to_address": "cosmos17dtl0mjt3t77kpuhg2edqzjpszulwhgzuj9ljs",
|
|
"amount": [{ "denom": "stake", "amount": "100" }]
|
|
}
|
|
]
|
|
}`)
|
|
byteArrayString := strings.Join(strings.Fields(fmt.Sprint(msgBytes)), ",") //nolint:staticcheck
|
|
|
|
packetData = []byte(`{
|
|
"type": 1,
|
|
"data":` + byteArrayString + `
|
|
}`)
|
|
|
|
params := types.NewParams(true, []string{sdk.MsgTypeURL((*banktypes.MsgSend)(nil))})
|
|
suite.chainB.GetSimApp().ICAHostKeeper.SetParams(suite.chainB.GetContext(), params)
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
"interchain account successfully executes govtypesv1.MsgSubmitProposal",
|
|
func(icaAddress string) {
|
|
msgBytes := []byte(`{
|
|
"messages": [
|
|
{
|
|
"@type": "/cosmos.gov.v1.MsgSubmitProposal",
|
|
"messages": [],
|
|
"metadata": "ipfs://CID",
|
|
"title": "IBC Gov Proposal",
|
|
"summary": "tokens for all!",
|
|
"expedited": false,
|
|
"initial_deposit": [{ "denom": "stake", "amount": "100000" }],
|
|
"proposer": "` + icaAddress + `"
|
|
}
|
|
]
|
|
}`)
|
|
byteArrayString := strings.Join(strings.Fields(fmt.Sprint(msgBytes)), ",") //nolint:staticcheck
|
|
|
|
packetData = []byte(`{
|
|
"type": 1,
|
|
"data":` + byteArrayString + `
|
|
}`)
|
|
|
|
params := types.NewParams(true, []string{sdk.MsgTypeURL((*govtypesv1.MsgSubmitProposal)(nil))})
|
|
suite.chainB.GetSimApp().ICAHostKeeper.SetParams(suite.chainB.GetContext(), params)
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
"interchain account successfully executes govtypesv1.MsgVote",
|
|
func(icaAddress string) {
|
|
proposal, err := govtypesv1.NewProposal([]sdk.Msg{getTestProposalMessage()}, govtypesv1.DefaultStartingProposalID, suite.chainA.GetContext().BlockTime(), suite.chainA.GetContext().BlockTime(), "test proposal", "title", "Description", sdk.AccAddress(interchainAccountAddr), false)
|
|
suite.Require().NoError(err)
|
|
|
|
err = suite.chainB.GetSimApp().GovKeeper.SetProposal(suite.chainB.GetContext(), proposal)
|
|
suite.Require().NoError(err)
|
|
err = suite.chainB.GetSimApp().GovKeeper.ActivateVotingPeriod(suite.chainB.GetContext(), proposal)
|
|
suite.Require().NoError(err)
|
|
|
|
msgBytes := []byte(`{
|
|
"messages": [
|
|
{
|
|
"@type": "/cosmos.gov.v1.MsgVote",
|
|
"voter": "` + icaAddress + `",
|
|
"proposal_id": 1,
|
|
"option": 1
|
|
}
|
|
]
|
|
}`)
|
|
byteArrayString := strings.Join(strings.Fields(fmt.Sprint(msgBytes)), ",") //nolint:staticcheck
|
|
|
|
packetData = []byte(`{
|
|
"type": 1,
|
|
"data":` + byteArrayString + `
|
|
}`)
|
|
|
|
params := types.NewParams(true, []string{sdk.MsgTypeURL((*govtypesv1.MsgVote)(nil))})
|
|
suite.chainB.GetSimApp().ICAHostKeeper.SetParams(suite.chainB.GetContext(), params)
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
"interchain account successfully executes govtypesv1.MsgSubmitProposal, govtypesv1.MsgDeposit, and then govtypesv1.MsgVote sequentially",
|
|
func(icaAddress string) {
|
|
msgBytes := []byte(`{
|
|
"messages": [
|
|
{
|
|
"@type": "/cosmos.gov.v1.MsgSubmitProposal",
|
|
"messages": [],
|
|
"metadata": "ipfs://CID",
|
|
"title": "IBC Gov Proposal",
|
|
"summary": "tokens for all!",
|
|
"expedited": false,
|
|
"initial_deposit": [{ "denom": "stake", "amount": "100000" }],
|
|
"proposer": "` + icaAddress + `"
|
|
},
|
|
{
|
|
"@type": "/cosmos.gov.v1.MsgDeposit",
|
|
"proposal_id": 1,
|
|
"depositor": "` + icaAddress + `",
|
|
"amount": [{ "denom": "stake", "amount": "10000000" }]
|
|
},
|
|
{
|
|
"@type": "/cosmos.gov.v1.MsgVote",
|
|
"voter": "` + icaAddress + `",
|
|
"proposal_id": 1,
|
|
"option": 1
|
|
}
|
|
]
|
|
}`)
|
|
byteArrayString := strings.Join(strings.Fields(fmt.Sprint(msgBytes)), ",") //nolint:staticcheck
|
|
|
|
packetData = []byte(`{
|
|
"type": 1,
|
|
"data":` + byteArrayString + `
|
|
}`)
|
|
|
|
params := types.NewParams(true, []string{sdk.MsgTypeURL((*govtypesv1.MsgSubmitProposal)(nil)), sdk.MsgTypeURL((*govtypesv1.MsgDeposit)(nil)), sdk.MsgTypeURL((*govtypesv1.MsgVote)(nil))})
|
|
suite.chainB.GetSimApp().ICAHostKeeper.SetParams(suite.chainB.GetContext(), params)
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
"interchain account successfully executes transfertypes.MsgTransfer",
|
|
func(icaAddress string) {
|
|
transferPath := ibctesting.NewTransferPath(suite.chainB, suite.chainC)
|
|
|
|
transferPath.Setup()
|
|
|
|
msgBytes := []byte(`{
|
|
"messages": [
|
|
{
|
|
"@type": "/ibc.applications.transfer.v1.MsgTransfer",
|
|
"source_port": "transfer",
|
|
"source_channel": "` + transferPath.EndpointA.ChannelID + `",
|
|
"token": { "denom": "stake", "amount": "100" },
|
|
"sender": "` + icaAddress + `",
|
|
"receiver": "cosmos15ulrf36d4wdtrtqzkgaan9ylwuhs7k7qz753uk",
|
|
"timeout_height": { "revision_number": 1, "revision_height": 100 },
|
|
"timeout_timestamp": 0,
|
|
"memo": ""
|
|
}
|
|
]
|
|
}`)
|
|
byteArrayString := strings.Join(strings.Fields(fmt.Sprint(msgBytes)), ",") //nolint:staticcheck
|
|
|
|
packetData = []byte(`{
|
|
"type": 1,
|
|
"data":` + byteArrayString + `
|
|
}`)
|
|
|
|
params := types.NewParams(true, []string{sdk.MsgTypeURL((*transfertypes.MsgTransfer)(nil))})
|
|
suite.chainB.GetSimApp().ICAHostKeeper.SetParams(suite.chainB.GetContext(), params)
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
"unregistered sdk.Msg",
|
|
func(icaAddress string) {
|
|
msgBytes := []byte(`{"messages":[{}]}`)
|
|
byteArrayString := strings.Join(strings.Fields(fmt.Sprint(msgBytes)), ",") //nolint:staticcheck
|
|
|
|
packetData = []byte(`{
|
|
"type": 1,
|
|
"data":` + byteArrayString + `
|
|
}`)
|
|
|
|
params := types.NewParams(true, []string{"*"})
|
|
suite.chainB.GetSimApp().ICAHostKeeper.SetParams(suite.chainB.GetContext(), params)
|
|
},
|
|
ibcerrors.ErrInvalidType,
|
|
},
|
|
{
|
|
"message type not allowed banktypes.MsgSend",
|
|
func(icaAddress string) {
|
|
msgBytes := []byte(`{
|
|
"messages": [
|
|
{
|
|
"@type": "/cosmos.bank.v1beta1.MsgSend",
|
|
"from_address": "` + icaAddress + `",
|
|
"to_address": "cosmos17dtl0mjt3t77kpuhg2edqzjpszulwhgzuj9ljs",
|
|
"amount": [{ "denom": "stake", "amount": "100" }]
|
|
}
|
|
]
|
|
}`)
|
|
byteArrayString := strings.Join(strings.Fields(fmt.Sprint(msgBytes)), ",") //nolint:staticcheck
|
|
|
|
packetData = []byte(`{
|
|
"type": 1,
|
|
"data":` + byteArrayString + `
|
|
}`)
|
|
|
|
params := types.NewParams(true, []string{sdk.MsgTypeURL((*transfertypes.MsgTransfer)(nil))})
|
|
suite.chainB.GetSimApp().ICAHostKeeper.SetParams(suite.chainB.GetContext(), params)
|
|
},
|
|
ibcerrors.ErrUnauthorized,
|
|
},
|
|
{
|
|
"unauthorised: signer address is not the interchain account associated with the controller portID",
|
|
func(icaAddress string) {
|
|
msgBytes := []byte(`{
|
|
"messages": [
|
|
{
|
|
"@type": "/cosmos.bank.v1beta1.MsgSend",
|
|
"from_address": "` + suite.chainB.SenderAccount.GetAddress().String() + `", // unexpected signer
|
|
"to_address": "cosmos17dtl0mjt3t77kpuhg2edqzjpszulwhgzuj9ljs",
|
|
"amount": [{ "denom": "stake", "amount": "100" }]
|
|
}
|
|
]
|
|
}`)
|
|
byteArrayString := strings.Join(strings.Fields(fmt.Sprint(msgBytes)), ",") //nolint:staticcheck
|
|
|
|
packetData = []byte(`{
|
|
"type": 1,
|
|
"data":` + byteArrayString + `
|
|
}`)
|
|
|
|
params := types.NewParams(true, []string{sdk.MsgTypeURL((*banktypes.MsgSend)(nil))})
|
|
suite.chainB.GetSimApp().ICAHostKeeper.SetParams(suite.chainB.GetContext(), params)
|
|
},
|
|
ibcerrors.ErrInvalidType,
|
|
},
|
|
}
|
|
|
|
for _, ordering := range []channeltypes.Order{channeltypes.UNORDERED, channeltypes.ORDERED} {
|
|
for _, tc := range testCases {
|
|
suite.Run(tc.msg, func() {
|
|
suite.SetupTest() // reset
|
|
|
|
path = NewICAPath(suite.chainA, suite.chainB, icatypes.EncodingProto3JSON, ordering)
|
|
path.SetupConnections()
|
|
|
|
err := SetupICAPath(path, TestOwnerAddress)
|
|
suite.Require().NoError(err)
|
|
|
|
portID, err := icatypes.NewControllerPortID(TestOwnerAddress)
|
|
suite.Require().NoError(err)
|
|
|
|
// Get the address of the interchain account stored in state during handshake step
|
|
icaAddress, found := suite.chainB.GetSimApp().ICAHostKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), ibctesting.FirstConnectionID, portID)
|
|
suite.Require().True(found)
|
|
|
|
suite.fundICAWallet(suite.chainB.GetContext(), path.EndpointA.ChannelConfig.PortID, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdkmath.NewInt(100000000))))
|
|
|
|
tc.malleate(icaAddress) // malleate mutates test data
|
|
|
|
packet := channeltypes.NewPacket(
|
|
packetData,
|
|
suite.chainA.SenderAccount.GetSequence(),
|
|
path.EndpointA.ChannelConfig.PortID,
|
|
path.EndpointA.ChannelID,
|
|
path.EndpointB.ChannelConfig.PortID,
|
|
path.EndpointB.ChannelID,
|
|
suite.chainB.GetTimeoutHeight(),
|
|
0,
|
|
)
|
|
|
|
txResponse, err := suite.chainB.GetSimApp().ICAHostKeeper.OnRecvPacket(suite.chainB.GetContext(), packet)
|
|
|
|
if tc.expErr == nil {
|
|
suite.Require().NoError(err)
|
|
suite.Require().NotNil(txResponse)
|
|
} else {
|
|
suite.Require().ErrorIs(err, tc.expErr)
|
|
suite.Require().Nil(txResponse)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
func (suite *KeeperTestSuite) fundICAWallet(ctx sdk.Context, portID string, amount sdk.Coins) {
|
|
interchainAccountAddr, found := suite.chainB.GetSimApp().ICAHostKeeper.GetInterchainAccountAddress(ctx, ibctesting.FirstConnectionID, portID)
|
|
suite.Require().True(found)
|
|
|
|
msgBankSend := &banktypes.MsgSend{
|
|
FromAddress: suite.chainB.SenderAccount.GetAddress().String(),
|
|
ToAddress: interchainAccountAddr,
|
|
Amount: amount,
|
|
}
|
|
|
|
res, err := suite.chainB.SendMsgs(msgBankSend)
|
|
suite.Require().NotEmpty(res)
|
|
suite.Require().NoError(err)
|
|
}
|
|
|
|
func getTestProposalMessage() sdk.Msg {
|
|
_, _, addr := testdata.KeyTestPubAddr()
|
|
return banktypes.NewMsgSend(authtypes.NewModuleAddress("gov"), addr, sdk.NewCoins(sdk.NewCoin("stake", sdkmath.NewInt(1000))))
|
|
}
|