Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Duplicate SimApp into callbacks directory (backport #4337) #4461

Merged
merged 3 commits into from
Aug 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 45 additions & 16 deletions modules/apps/callbacks/callbacks_test.go
Original file line number Diff line number Diff line change
@@ -1,28 +1,55 @@
package ibccallbacks_test

import (
"encoding/json"
"fmt"
"testing"

"github.com/stretchr/testify/suite"

sdkmath "cosmossdk.io/math"

simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
sdk "github.com/cosmos/cosmos-sdk/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"

dbm "github.com/cometbft/cometbft-db"
"github.com/cometbft/cometbft/libs/log"

icacontrollertypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/controller/types"
icatypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/types"
feetypes "github.com/cosmos/ibc-go/v7/modules/apps/29-fee/types"
simapp "github.com/cosmos/ibc-go/v7/modules/apps/callbacks/testing/simapp"
"github.com/cosmos/ibc-go/v7/modules/apps/callbacks/types"
transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
ibctesting "github.com/cosmos/ibc-go/v7/testing"
ibcmock "github.com/cosmos/ibc-go/v7/testing/mock"
simapp "github.com/cosmos/ibc-go/v7/testing/simapp"
)

const maxCallbackGas = uint64(1000000)

func init() {
ibctesting.DefaultTestingAppInit = SetupTestingApp
}

// SetupTestingApp provides the duplicated simapp which is specific to the callbacks module on chain creation.
func SetupTestingApp() (ibctesting.TestingApp, map[string]json.RawMessage) {
db := dbm.NewMemDB()
encCdc := simapp.MakeTestEncodingConfig()
app := simapp.NewSimApp(log.NewNopLogger(), db, nil, true, simtestutil.EmptyAppOptions{})
return app, simapp.NewDefaultGenesisState(encCdc.Codec)
}

// GetSimApp returns the duplicated SimApp from within the callbacks directory.
// This must be used instead of chain.GetSimApp() for tests within this directory.
func GetSimApp(chain *ibctesting.TestChain) *simapp.SimApp {
app, ok := chain.App.(*simapp.SimApp)
if !ok {
panic("chain is not a simapp.SimApp")
}
return app
}

// CallbacksTestSuite defines the needed instances and methods to test callbacks
type CallbacksTestSuite struct {
suite.Suite
Expand All @@ -41,6 +68,10 @@ func (s *CallbacksTestSuite) setupChains() {
s.chainA = s.coordinator.GetChain(ibctesting.GetChainID(1))
s.chainB = s.coordinator.GetChain(ibctesting.GetChainID(2))
s.path = ibctesting.NewPath(s.chainA, s.chainB)

// override the SendMsgs function to not require a successful transaction
overrideSendMsg(s.chainA)
overrideSendMsg(s.chainB)
}

// SetupTransferTest sets up a transfer channel between chainA and chainB
Expand Down Expand Up @@ -105,7 +136,7 @@ func (s *CallbacksTestSuite) SetupICATest() string {
err = s.path.EndpointB.ChanOpenConfirm()
s.Require().NoError(err)

interchainAccountAddr, found := s.chainB.GetSimApp().ICAHostKeeper.GetInterchainAccountAddress(s.chainB.GetContext(), s.path.EndpointA.ConnectionID, s.path.EndpointA.ChannelConfig.PortID)
interchainAccountAddr, found := GetSimApp(s.chainB).ICAHostKeeper.GetInterchainAccountAddress(s.chainB.GetContext(), s.path.EndpointA.ConnectionID, s.path.EndpointA.ChannelConfig.PortID)
s.Require().True(found)

// fund the interchain account on chainB
Expand Down Expand Up @@ -146,8 +177,8 @@ func (s *CallbacksTestSuite) AssertHasExecutedExpectedCallback(callbackType type
expStatefulEntries = 1
}

sourceStatefulCounter := s.chainA.GetSimApp().MockContractKeeper.GetStateEntryCounter(s.chainA.GetContext())
destStatefulCounter := s.chainB.GetSimApp().MockContractKeeper.GetStateEntryCounter(s.chainB.GetContext())
sourceStatefulCounter := GetSimApp(s.chainA).MockContractKeeper.GetStateEntryCounter(s.chainA.GetContext())
destStatefulCounter := GetSimApp(s.chainB).MockContractKeeper.GetStateEntryCounter(s.chainB.GetContext())

switch callbackType {
case "none":
Expand Down Expand Up @@ -175,8 +206,8 @@ func (s *CallbacksTestSuite) AssertHasExecutedExpectedCallback(callbackType type
}

func (s *CallbacksTestSuite) AssertCallbackCounters(callbackType types.CallbackType) {
sourceCounters := s.chainA.GetSimApp().MockContractKeeper.Counters
destCounters := s.chainB.GetSimApp().MockContractKeeper.Counters
sourceCounters := GetSimApp(s.chainA).MockContractKeeper.Counters
destCounters := GetSimApp(s.chainB).MockContractKeeper.Counters

switch callbackType {
case "none":
Expand Down Expand Up @@ -232,13 +263,13 @@ func (s *CallbacksTestSuite) AssertHasExecutedExpectedCallbackWithFee(
// check forward relay balance
s.Require().Equal(
fee.RecvFee,
sdk.NewCoins(s.chainA.GetSimApp().BankKeeper.GetBalance(s.chainA.GetContext(), s.chainB.SenderAccount.GetAddress(), ibctesting.TestCoin.Denom)),
sdk.NewCoins(GetSimApp(s.chainA).BankKeeper.GetBalance(s.chainA.GetContext(), s.chainB.SenderAccount.GetAddress(), ibctesting.TestCoin.Denom)),
)

s.Require().Equal(
fee.AckFee.Add(fee.TimeoutFee...), // ack fee paid, timeout fee refunded
sdk.NewCoins(
s.chainA.GetSimApp().BankKeeper.GetBalance(
GetSimApp(s.chainA).BankKeeper.GetBalance(
s.chainA.GetContext(), s.chainA.SenderAccount.GetAddress(),
ibctesting.TestCoin.Denom),
).Sub(originalSenderBalance[0]),
Expand All @@ -247,14 +278,14 @@ func (s *CallbacksTestSuite) AssertHasExecutedExpectedCallbackWithFee(
// forward relay balance should be 0
s.Require().Equal(
sdk.NewCoin(ibctesting.TestCoin.Denom, sdkmath.ZeroInt()),
s.chainA.GetSimApp().BankKeeper.GetBalance(s.chainA.GetContext(), s.chainB.SenderAccount.GetAddress(), ibctesting.TestCoin.Denom),
GetSimApp(s.chainA).BankKeeper.GetBalance(s.chainA.GetContext(), s.chainB.SenderAccount.GetAddress(), ibctesting.TestCoin.Denom),
)

// all fees should be returned as sender is the reverse relayer
s.Require().Equal(
fee.Total(),
sdk.NewCoins(
s.chainA.GetSimApp().BankKeeper.GetBalance(
GetSimApp(s.chainA).BankKeeper.GetBalance(
s.chainA.GetContext(), s.chainA.SenderAccount.GetAddress(),
ibctesting.TestCoin.Denom),
).Sub(originalSenderBalance[0]),
Expand All @@ -263,23 +294,21 @@ func (s *CallbacksTestSuite) AssertHasExecutedExpectedCallbackWithFee(
s.AssertHasExecutedExpectedCallback(callbackType, isSuccessful)
}

// OverrideSendMsgWithAssertion overrides both chains' SendMsgsOverride function to assert whether the
// transaction is successful or not.
func OverrideSendMsgWithAssertion(chain *ibctesting.TestChain, expPass bool) {
// overrideSendMsg overrides both chains' SendMsgs function to a version that doesn't require
// that the transaction is successful.
func overrideSendMsg(chain *ibctesting.TestChain) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed because v7.3's SendMsg requires the tx to be successful, so we override it. (chain.go is not one of the copied files)

chain.SendMsgsOverride = func(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, expPass, chain.SenderPrivKey,
chain.SenderPrivKey,
)
if err != nil {
return nil, err
Expand Down
16 changes: 6 additions & 10 deletions modules/apps/callbacks/fee_transfer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,8 @@ func (s *CallbacksTestSuite) TestIncentivizedTransferCallbacks() {
fee := feetypes.NewFee(defaultRecvFee, defaultAckFee, defaultTimeoutFee)

s.ExecutePayPacketFeeMsg(fee)
preRelaySenderBalance := sdk.NewCoins(s.chainA.GetSimApp().BankKeeper.GetBalance(s.chainA.GetContext(), s.chainA.SenderAccount.GetAddress(), ibctesting.TestCoin.Denom))

expSendFailure := !tc.expSuccess && (tc.expCallback == types.CallbackTypeSendPacket)
s.ExecuteTransfer(tc.transferMemo, expSendFailure)
preRelaySenderBalance := sdk.NewCoins(GetSimApp(s.chainA).BankKeeper.GetBalance(s.chainA.GetContext(), s.chainA.SenderAccount.GetAddress(), ibctesting.TestCoin.Denom))
s.ExecuteTransfer(tc.transferMemo)
// we manually subtract the transfer amount from the preRelaySenderBalance because ExecuteTransfer
// also relays the packet, which will trigger the fee payments.
preRelaySenderBalance = preRelaySenderBalance.Sub(ibctesting.TestCoin)
Expand Down Expand Up @@ -160,10 +158,8 @@ func (s *CallbacksTestSuite) TestIncentivizedTransferTimeoutCallbacks() {
fee := feetypes.NewFee(defaultRecvFee, defaultAckFee, defaultTimeoutFee)

s.ExecutePayPacketFeeMsg(fee)
preRelaySenderBalance := sdk.NewCoins(s.chainA.GetSimApp().BankKeeper.GetBalance(s.chainA.GetContext(), s.chainA.SenderAccount.GetAddress(), ibctesting.TestCoin.Denom))

expSendFailure := !tc.expSuccess && (tc.expCallback == types.CallbackTypeSendPacket)
s.ExecuteTransferTimeout(tc.transferMemo, expSendFailure)
preRelaySenderBalance := sdk.NewCoins(GetSimApp(s.chainA).BankKeeper.GetBalance(s.chainA.GetContext(), s.chainA.SenderAccount.GetAddress(), ibctesting.TestCoin.Denom))
s.ExecuteTransferTimeout(tc.transferMemo)

// after incentivizing the packets
s.AssertHasExecutedExpectedCallbackWithFee(tc.expCallback, tc.expSuccess, true, preRelaySenderBalance, fee)
Expand All @@ -178,13 +174,13 @@ func (s *CallbacksTestSuite) ExecutePayPacketFeeMsg(fee feetypes.Fee) {
)

// fetch the account balance before fees are escrowed and assert the difference below
preEscrowBalance := s.chainA.GetSimApp().BankKeeper.GetBalance(s.chainA.GetContext(), s.chainA.SenderAccount.GetAddress(), sdk.DefaultBondDenom)
preEscrowBalance := GetSimApp(s.chainA).BankKeeper.GetBalance(s.chainA.GetContext(), s.chainA.SenderAccount.GetAddress(), sdk.DefaultBondDenom)

res, err := s.chainA.SendMsgs(msg)
s.Require().NoError(err)
s.Require().NotNil(res)

postEscrowBalance := s.chainA.GetSimApp().BankKeeper.GetBalance(s.chainA.GetContext(), s.chainA.SenderAccount.GetAddress(), sdk.DefaultBondDenom)
postEscrowBalance := GetSimApp(s.chainA).BankKeeper.GetBalance(s.chainA.GetContext(), s.chainA.SenderAccount.GetAddress(), sdk.DefaultBondDenom)
s.Require().Equal(postEscrowBalance.AddAmount(fee.Total().AmountOf(sdk.DefaultBondDenom)), preEscrowBalance)

// register counterparty address on chainB
Expand Down
12 changes: 6 additions & 6 deletions modules/apps/callbacks/ibc_middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -318,8 +318,8 @@ func (s *CallbacksTestSuite) TestOnAcknowledgementPacket() {
s.Require().ErrorIs(tc.expError, err)
}

sourceStatefulCounter := s.chainA.GetSimApp().MockContractKeeper.GetStateEntryCounter(s.chainA.GetContext())
sourceCounters := s.chainA.GetSimApp().MockContractKeeper.Counters
sourceStatefulCounter := GetSimApp(s.chainA).MockContractKeeper.GetStateEntryCounter(s.chainA.GetContext())
sourceCounters := GetSimApp(s.chainA).MockContractKeeper.Counters

switch tc.expResult {
case noExecution:
Expand Down Expand Up @@ -471,8 +471,8 @@ func (s *CallbacksTestSuite) TestOnTimeoutPacket() {
s.Require().ErrorIs(tc.expError, err)
}

sourceStatefulCounter := s.chainA.GetSimApp().MockContractKeeper.GetStateEntryCounter(s.chainA.GetContext())
sourceCounters := s.chainA.GetSimApp().MockContractKeeper.Counters
sourceStatefulCounter := GetSimApp(s.chainA).MockContractKeeper.GetStateEntryCounter(s.chainA.GetContext())
sourceCounters := GetSimApp(s.chainA).MockContractKeeper.Counters

// account for SendPacket succeeding
switch tc.expResult {
Expand Down Expand Up @@ -614,8 +614,8 @@ func (s *CallbacksTestSuite) TestOnRecvPacket() {
s.Require().Equal(tc.expAck, ack)
}

destStatefulCounter := s.chainB.GetSimApp().MockContractKeeper.GetStateEntryCounter(s.chainB.GetContext())
destCounters := s.chainB.GetSimApp().MockContractKeeper.Counters
destStatefulCounter := GetSimApp(s.chainB).MockContractKeeper.GetStateEntryCounter(s.chainB.GetContext())
destCounters := GetSimApp(s.chainB).MockContractKeeper.Counters

switch tc.expResult {
case noExecution:
Expand Down
24 changes: 6 additions & 18 deletions modules/apps/callbacks/ica_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ func (s *CallbacksTestSuite) TestICACallbacks() {
s.Run(tc.name, func() {
icaAddr := s.SetupICATest()

expSendFailure := !tc.expSuccess && (tc.expCallback == types.CallbackTypeSendPacket)
s.ExecuteICATx(icaAddr, tc.icaMemo, expSendFailure)
s.ExecuteICATx(icaAddr, tc.icaMemo)
s.AssertHasExecutedExpectedCallback(tc.expCallback, tc.expSuccess)
})
}
Expand Down Expand Up @@ -119,28 +118,22 @@ func (s *CallbacksTestSuite) TestICATimeoutCallbacks() {
s.Run(tc.name, func() {
icaAddr := s.SetupICATest()

expSendFailure := !tc.expSuccess && (tc.expCallback == types.CallbackTypeSendPacket)
s.ExecuteICATimeout(icaAddr, tc.icaMemo, expSendFailure)
s.ExecuteICATimeout(icaAddr, tc.icaMemo)
s.AssertHasExecutedExpectedCallback(tc.expCallback, tc.expSuccess)
})
}
}

// ExecuteICATx executes a stakingtypes.MsgDelegate on chainB by sending a packet containing the msg to chainB
func (s *CallbacksTestSuite) ExecuteICATx(icaAddress, memo string, expSendFailure bool) {
func (s *CallbacksTestSuite) ExecuteICATx(icaAddress, memo string) {
timeoutTimestamp := uint64(s.chainA.GetContext().BlockTime().Add(time.Minute).UnixNano())
icaOwner := s.chainA.SenderAccount.GetAddress().String()
connectionID := s.path.EndpointA.ConnectionID
// build the interchain accounts packet data
packetData := s.buildICAMsgDelegatePacketData(icaAddress, memo)
msg := icacontrollertypes.NewMsgSendTx(icaOwner, connectionID, timeoutTimestamp, packetData)

if expSendFailure {
OverrideSendMsgWithAssertion(s.chainA, false)
}

res, err := s.chainA.SendMsgs(msg)
s.chainA.SendMsgsOverride = nil // undo override
if err != nil {
return // we return if send packet is rejected
}
Expand All @@ -153,20 +146,15 @@ func (s *CallbacksTestSuite) ExecuteICATx(icaAddress, memo string, expSendFailur
}

// ExecuteICATx sends and times out an ICA tx
func (s *CallbacksTestSuite) ExecuteICATimeout(icaAddress, memo string, expSendFailure bool) {
func (s *CallbacksTestSuite) ExecuteICATimeout(icaAddress, memo string) {
relativeTimeout := uint64(1)
icaOwner := s.chainA.SenderAccount.GetAddress().String()
connectionID := s.path.EndpointA.ConnectionID
// build the interchain accounts packet data
packetData := s.buildICAMsgDelegatePacketData(icaAddress, memo)
msg := icacontrollertypes.NewMsgSendTx(icaOwner, connectionID, relativeTimeout, packetData)

if expSendFailure {
OverrideSendMsgWithAssertion(s.chainA, false)
}

res, err := s.chainA.SendMsgs(msg)
s.chainA.SendMsgsOverride = nil // undo override
if err != nil {
return // we return if send packet is rejected
}
Expand Down Expand Up @@ -194,9 +182,9 @@ func (s *CallbacksTestSuite) buildICAMsgDelegatePacketData(icaAddress string, me

// ensure chainB is allowed to execute stakingtypes.MsgDelegate
params := icahosttypes.NewParams(true, []string{sdk.MsgTypeURL(msgDelegate)})
s.chainB.GetSimApp().ICAHostKeeper.SetParams(s.chainB.GetContext(), params)
GetSimApp(s.chainB).ICAHostKeeper.SetParams(s.chainB.GetContext(), params)

data, err := icatypes.SerializeCosmosTx(s.chainA.GetSimApp().AppCodec(), []proto.Message{msgDelegate})
data, err := icatypes.SerializeCosmosTx(GetSimApp(s.chainA).AppCodec(), []proto.Message{msgDelegate})
s.Require().NoError(err)

icaPacketData := icatypes.InterchainAccountPacketData{
Expand Down
50 changes: 50 additions & 0 deletions modules/apps/callbacks/testing/simapp/ante_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package simapp

import (
errorsmod "cosmossdk.io/errors"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/ante"

ibcante "github.com/cosmos/ibc-go/v7/modules/core/ante"
ibcerrors "github.com/cosmos/ibc-go/v7/modules/core/errors"
"github.com/cosmos/ibc-go/v7/modules/core/keeper"
)

// HandlerOptions extend the SDK's AnteHandler options by requiring the IBC keeper.
type HandlerOptions struct {
ante.HandlerOptions

IBCKeeper *keeper.Keeper
}

// NewAnteHandler creates a new ante handler
func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
if options.AccountKeeper == nil {
return nil, errorsmod.Wrap(ibcerrors.ErrLogic, "account keeper is required for AnteHandler")
}
if options.BankKeeper == nil {
return nil, errorsmod.Wrap(ibcerrors.ErrLogic, "bank keeper is required for AnteHandler")
}
if options.SignModeHandler == nil {
return nil, errorsmod.Wrap(ibcerrors.ErrLogic, "sign mode handler is required for AnteHandler")
}

anteDecorators := []sdk.AnteDecorator{
ante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
ante.NewExtensionOptionsDecorator(options.ExtensionOptionChecker),
ante.NewValidateBasicDecorator(),
ante.NewTxTimeoutHeightDecorator(),
ante.NewValidateMemoDecorator(options.AccountKeeper),
ante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
ante.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper, options.TxFeeChecker),
ante.NewSetPubKeyDecorator(options.AccountKeeper), // SetPubKeyDecorator must be called before all signature verification decorators
ante.NewValidateSigCountDecorator(options.AccountKeeper),
ante.NewSigGasConsumeDecorator(options.AccountKeeper, options.SigGasConsumer),
ante.NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler),
ante.NewIncrementSequenceDecorator(options.AccountKeeper),
ibcante.NewRedundantRelayDecorator(options.IBCKeeper),
}

return sdk.ChainAnteDecorators(anteDecorators...), nil
}
Loading