remove IBC ante handler in favor of using handler (#6793)

* remove IBC ante handler, add calls to handler

* move some events upstream to handler

* remove change log entry

* move ante handler tests to handler

* fix build

* update docs

Co-authored-by: Alexander Bezobchuk <alexanderbez@users.noreply.github.com>
This commit is contained in:
colin axner 2020-07-20 17:25:57 +02:00 committed by GitHub
parent 54141887b5
commit 79fa06b26c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 136 additions and 217 deletions

View File

@ -167,7 +167,6 @@ be used to retrieve the actual proposal `Content`. Also the `NewMsgSubmitProposa
* [ICS 007 - Tendermint Client](https://github.com/cosmos/ics/blob/master/spec/ics-007-tendermint-client) subpackage
* [ICS 020 - Fungible Token Transfer](https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer) module
* [ICS 023 - Vector Commitments](https://github.com/cosmos/ics/tree/master/spec/ics-023-vector-commitments) subpackage
* (ibc/ante) Implement IBC `AnteHandler` as per [ADR 15 - IBC Packet Receiver](https://github.com/cosmos/tree/master/docs/architecture/adr-015-ibc-packet-receiver.md).
* (x/capability) [\#5828](https://github.com/cosmos/cosmos-sdk/pull/5828) Capability module integration as outlined in [ADR 3 - Dynamic Capability Store](https://github.com/cosmos/tree/master/docs/architecture/adr-003-dynamic-capability-store.md).
* (x/params) [\#6005](https://github.com/cosmos/cosmos-sdk/pull/6005) Add new CLI command for querying raw x/params parameters by subspace and key.
* (x/ibc) [\#5769](https://github.com/cosmos/cosmos-sdk/pull/5769) [ICS 009 - Loopback Client](https://github.com/cosmos/ics/tree/master/spec/ics-009-loopback-client) subpackage

View File

@ -21,7 +21,6 @@ Integrating the IBC module to your SDK-based application is straighforward. The
- Add the modules to the module `Manager`
- Add modules to `Begin/EndBlockers` and `InitGenesis`
- Update the module `SimulationManager` to enable simulations
- Add IBC `Keeper` to the `AnteHandler`
### Module `BasicManager` and `ModuleAccount` permissions
@ -244,28 +243,6 @@ func NewApp(...args) *App {
**IMPORTANT**: The capability module **must** be declared first in `SetOrderInitGenesis`
:::
### IBC AnteHandler
The IBC module defines `ProofVerificationDecorator` that handles messages that contains application
specific packet types. This is mostly to perform stateful packet execution. For more context, please
refer to [ADR 15 - IBC Packet Receiver](./../architecture/adr-015-ibc-packet-receiver.md).
```go
// app.go
func NewApp(...args) *App {
// .. continuation from above
app.SetAnteHandler(
ante.NewAnteHandler(
app.AccountKeeper, app.BankKeeper, *app.IBCKeeper, ante.DefaultSigVerificationGasConsumer,
),
)
// ...
return app
}
```
That's it! You have now wired up the IBC module and are now able to send fungible tokens across
different chains. If you want to have a broader view of the changes take a look into the SDK's
[`SimApp`](https://github.com/cosmos/cosmos-sdk/blob/master/simapp/app.go).

View File

@ -365,7 +365,7 @@ func NewSimApp(
app.SetBeginBlocker(app.BeginBlocker)
app.SetAnteHandler(
ante.NewAnteHandler(
app.AccountKeeper, app.BankKeeper, *app.IBCKeeper, ante.DefaultSigVerificationGasConsumer,
app.AccountKeeper, app.BankKeeper, ante.DefaultSigVerificationGasConsumer,
authtypes.LegacyAminoJSONHandler{},
),
)

View File

@ -4,15 +4,13 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/signing"
"github.com/cosmos/cosmos-sdk/x/auth/types"
ibcante "github.com/cosmos/cosmos-sdk/x/ibc/ante"
ibckeeper "github.com/cosmos/cosmos-sdk/x/ibc/keeper"
)
// NewAnteHandler returns an AnteHandler that checks and increments sequence
// numbers, checks signatures & account numbers, and deducts fees from the first
// signer.
func NewAnteHandler(
ak AccountKeeper, bankKeeper types.BankKeeper, ibcKeeper ibckeeper.Keeper,
ak AccountKeeper, bankKeeper types.BankKeeper,
sigGasConsumer SignatureVerificationGasConsumer,
signModeHandler signing.SignModeHandler,
) sdk.AnteHandler {
@ -28,6 +26,5 @@ func NewAnteHandler(
NewSigGasConsumeDecorator(ak, sigGasConsumer),
NewSigVerificationDecorator(ak, signModeHandler),
NewIncrementSequenceDecorator(ak),
ibcante.NewProofVerificationDecorator(ibcKeeper.ClientKeeper, ibcKeeper.ChannelKeeper), // innermost AnteDecorator
)
}

View File

@ -980,7 +980,7 @@ func (suite *AnteTestSuite) TestCustomSignatureVerificationGasConsumer() {
suite.SetupTest(true) // setup
// setup an ante handler that only accepts PubKeyEd25519
suite.anteHandler = ante.NewAnteHandler(suite.app.AccountKeeper, suite.app.BankKeeper, *suite.app.IBCKeeper, func(meter sdk.GasMeter, sig signing.SignatureV2, params types.Params) error {
suite.anteHandler = ante.NewAnteHandler(suite.app.AccountKeeper, suite.app.BankKeeper, func(meter sdk.GasMeter, sig signing.SignatureV2, params types.Params) error {
switch pubkey := sig.PubKey.(type) {
case ed25519.PubKeyEd25519:
meter.ConsumeGas(params.SigVerifyCostED25519, "ante verify: ed25519")

View File

@ -40,7 +40,7 @@ type AnteTestSuite struct {
func (suite *AnteTestSuite) SetupTest(isCheckTx bool) {
suite.app, suite.ctx = createTestApp(isCheckTx)
suite.ctx = suite.ctx.WithBlockHeight(1)
suite.anteHandler = ante.NewAnteHandler(suite.app.AccountKeeper, suite.app.BankKeeper, *suite.app.IBCKeeper, ante.DefaultSigVerificationGasConsumer, types.LegacyAminoJSONHandler{})
suite.anteHandler = ante.NewAnteHandler(suite.app.AccountKeeper, suite.app.BankKeeper, ante.DefaultSigVerificationGasConsumer, types.LegacyAminoJSONHandler{})
// set up the TxBuilder
encodingConfig := simappparams.MakeEncodingConfig()

View File

@ -76,6 +76,13 @@ func HandleMsgUpdateClient(ctx sdk.Context, k keeper.Keeper, msg exported.MsgUpd
return nil, err
}
ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
),
)
return &sdk.Result{
Events: ctx.EventManager().Events().ToABCIEvents(),
}, nil
@ -92,6 +99,18 @@ func HandlerClientMisbehaviour(k keeper.Keeper) evidencetypes.Handler {
)
}
return k.CheckMisbehaviourAndUpdateState(ctx, misbehaviour)
if err := k.CheckMisbehaviourAndUpdateState(ctx, misbehaviour); err != nil {
return sdkerrors.Wrap(err, "failed to process misbehaviour for IBC client")
}
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeSubmitMisbehaviour,
sdk.NewAttribute(types.AttributeKeyClientID, misbehaviour.GetClientID()),
sdk.NewAttribute(types.AttributeKeyClientType, misbehaviour.ClientType().String()),
sdk.NewAttribute(types.AttributeKeyConsensusHeight, fmt.Sprintf("%d", uint64(misbehaviour.GetHeight()))),
),
)
return nil
}
}

View File

@ -100,7 +100,7 @@ func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.H
k.Logger(ctx).Info(fmt.Sprintf("client %s updated to height %d", clientID, clientState.GetLatestHeight()))
// Emit events in keeper so antehandler emits them as well
// emitting events in the keeper emits for both begin block and handler client updates
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeUpdateClient,
@ -110,16 +110,6 @@ func (k Keeper) UpdateClient(ctx sdk.Context, clientID string, header exported.H
),
)
// localhost client is not updated though messages
if clientType != exported.Localhost {
ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
),
)
}
return clientState, nil
}
@ -154,14 +144,5 @@ func (k Keeper) CheckMisbehaviourAndUpdateState(ctx sdk.Context, misbehaviour ex
k.SetClientState(ctx, clientState)
k.Logger(ctx).Info(fmt.Sprintf("client %s frozen due to misbehaviour", misbehaviour.GetClientID()))
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeSubmitMisbehaviour,
sdk.NewAttribute(types.AttributeKeyClientID, misbehaviour.GetClientID()),
sdk.NewAttribute(types.AttributeKeyClientType, misbehaviour.ClientType().String()),
sdk.NewAttribute(types.AttributeKeyConsensusHeight, fmt.Sprintf("%d", consensusState.GetHeight())),
),
)
return nil
}

View File

@ -1,66 +0,0 @@
package ante
import (
sdk "github.com/cosmos/cosmos-sdk/types"
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
clientkeeper "github.com/cosmos/cosmos-sdk/x/ibc/02-client/keeper"
channelkeeper "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/keeper"
channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types"
)
// ProofVerificationDecorator handles messages that contains application specific packet types,
// including MsgPacket, MsgAcknowledgement, MsgTimeout.
// MsgUpdateClients are also handled here to perform atomic multimsg transaction
type ProofVerificationDecorator struct {
clientKeeper clientkeeper.Keeper
channelKeeper channelkeeper.Keeper
}
// NewProofVerificationDecorator constructs new ProofverificationDecorator
func NewProofVerificationDecorator(clientKeeper clientkeeper.Keeper, channelKeeper channelkeeper.Keeper) ProofVerificationDecorator {
return ProofVerificationDecorator{
clientKeeper: clientKeeper,
channelKeeper: channelKeeper,
}
}
// AnteHandle executes MsgUpdateClient, MsgPacket, MsgAcknowledgement, MsgTimeout.
// The packet execution messages are then passed to the respective application handlers.
func (pvr ProofVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
for _, msg := range tx.GetMsgs() {
var err error
switch msg := msg.(type) {
case clientexported.MsgUpdateClient:
_, err = pvr.clientKeeper.UpdateClient(ctx, msg.GetClientID(), msg.GetHeader())
case *channeltypes.MsgPacket:
err = pvr.channelKeeper.RecvPacket(ctx, msg.Packet, msg.Proof, msg.ProofHeight)
case *channeltypes.MsgAcknowledgement:
err = pvr.channelKeeper.AcknowledgePacket(ctx, msg.Packet, msg.Acknowledgement, msg.Proof, msg.ProofHeight)
case *channeltypes.MsgTimeout:
err = pvr.channelKeeper.TimeoutPacket(ctx, msg.Packet, msg.Proof, msg.ProofHeight, msg.NextSequenceRecv)
default:
// don't emit sender event for other msg types
continue
}
attributes := make([]sdk.Attribute, len(msg.GetSigners()))
for i, signer := range msg.GetSigners() {
attributes[i] = sdk.NewAttribute(sdk.AttributeKeySender, signer.String())
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
sdk.EventTypeMessage,
attributes...,
),
})
if err != nil {
return ctx, err
}
}
return next(ctx, tx, simulate)
}

View File

@ -24,9 +24,11 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
return client.HandleMsgCreateClient(ctx, k.ClientKeeper, msg)
case clientexported.MsgUpdateClient:
return &sdk.Result{}, nil
return client.HandleMsgUpdateClient(ctx, k.ClientKeeper, msg)
// IBC connection msgs
// Client Misbehaviour is handled by the evidence module
// IBC connection msgs
case *connectiontypes.MsgConnectionOpenInit:
return connection.HandleMsgConnectionOpenInit(ctx, k.ConnectionKeeper, msg)
@ -51,13 +53,14 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
if err != nil {
return nil, err
}
// Retrieve callbacks from router
cbs, ok := k.Router.GetRoute(module)
if !ok {
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
}
err = cbs.OnChanOpenInit(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortID, msg.ChannelID, cap, msg.Channel.Counterparty, msg.Channel.Version)
if err != nil {
if err = cbs.OnChanOpenInit(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortID, msg.ChannelID, cap, msg.Channel.Counterparty, msg.Channel.Version); err != nil {
return nil, sdkerrors.Wrap(err, "channel open init callback failed")
}
@ -69,17 +72,19 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
if err != nil {
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
}
res, cap, err := channel.HandleMsgChannelOpenTry(ctx, k.ChannelKeeper, portCap, msg)
if err != nil {
return nil, err
}
// Retrieve callbacks from router
cbs, ok := k.Router.GetRoute(module)
if !ok {
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
}
err = cbs.OnChanOpenTry(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortID, msg.ChannelID, cap, msg.Channel.Counterparty, msg.Channel.Version, msg.CounterpartyVersion)
if err != nil {
if err = cbs.OnChanOpenTry(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortID, msg.ChannelID, cap, msg.Channel.Counterparty, msg.Channel.Version, msg.CounterpartyVersion); err != nil {
return nil, sdkerrors.Wrap(err, "channel open try callback failed")
}
@ -91,16 +96,17 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
if err != nil {
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
}
// Retrieve callbacks from router
cbs, ok := k.Router.GetRoute(module)
if !ok {
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
}
err = cbs.OnChanOpenAck(ctx, msg.PortID, msg.ChannelID, msg.CounterpartyVersion)
if err != nil {
if err = cbs.OnChanOpenAck(ctx, msg.PortID, msg.ChannelID, msg.CounterpartyVersion); err != nil {
return nil, sdkerrors.Wrap(err, "channel open ack callback failed")
}
return channel.HandleMsgChannelOpenAck(ctx, k.ChannelKeeper, cap, msg)
case *channeltypes.MsgChannelOpenConfirm:
@ -109,16 +115,17 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
if err != nil {
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
}
// Retrieve callbacks from router
cbs, ok := k.Router.GetRoute(module)
if !ok {
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
}
err = cbs.OnChanOpenConfirm(ctx, msg.PortID, msg.ChannelID)
if err != nil {
if err = cbs.OnChanOpenConfirm(ctx, msg.PortID, msg.ChannelID); err != nil {
return nil, sdkerrors.Wrap(err, "channel open confirm callback failed")
}
return channel.HandleMsgChannelOpenConfirm(ctx, k.ChannelKeeper, cap, msg)
case *channeltypes.MsgChannelCloseInit:
@ -127,16 +134,17 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
if err != nil {
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
}
// Retrieve callbacks from router
cbs, ok := k.Router.GetRoute(module)
if !ok {
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
}
err = cbs.OnChanCloseInit(ctx, msg.PortID, msg.ChannelID)
if err != nil {
if err = cbs.OnChanCloseInit(ctx, msg.PortID, msg.ChannelID); err != nil {
return nil, sdkerrors.Wrap(err, "channel close init callback failed")
}
return channel.HandleMsgChannelCloseInit(ctx, k.ChannelKeeper, cap, msg)
case *channeltypes.MsgChannelCloseConfirm:
@ -145,16 +153,17 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
if err != nil {
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
}
// Retrieve callbacks from router
cbs, ok := k.Router.GetRoute(module)
if !ok {
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
}
err = cbs.OnChanCloseConfirm(ctx, msg.PortID, msg.ChannelID)
if err != nil {
if err = cbs.OnChanCloseConfirm(ctx, msg.PortID, msg.ChannelID); err != nil {
return nil, sdkerrors.Wrap(err, "channel close confirm callback failed")
}
return channel.HandleMsgChannelCloseConfirm(ctx, k.ChannelKeeper, cap, msg)
// IBC packet msgs get routed to the appropriate module callback
@ -171,6 +180,11 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
}
// Perform TAO verification
if err := k.ChannelKeeper.RecvPacket(ctx, msg.Packet, msg.Proof, msg.ProofHeight); err != nil {
return nil, sdkerrors.Wrap(err, "receive packet verification failed")
}
// Perform application logic callback
res, ack, err := cbs.OnRecvPacket(ctx, msg.Packet)
if err != nil {
@ -197,6 +211,11 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
}
// Perform TAO verification
if err := k.ChannelKeeper.AcknowledgePacket(ctx, msg.Packet, msg.Acknowledgement, msg.Proof, msg.ProofHeight); err != nil {
return nil, sdkerrors.Wrap(err, "acknowledge packet verification failed")
}
// Perform application logic callback
res, err := cbs.OnAcknowledgementPacket(ctx, msg.Packet, msg.Acknowledgement)
if err != nil {
@ -223,6 +242,11 @@ func NewHandler(k keeper.Keeper) sdk.Handler {
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
}
// Perform TAO verification
if err := k.ChannelKeeper.TimeoutPacket(ctx, msg.Packet, msg.Proof, msg.ProofHeight, msg.NextSequenceRecv); err != nil {
return nil, sdkerrors.Wrap(err, "timeout packet verification failed")
}
// Perform application logic callback
res, err := cbs.OnTimeoutPacket(ctx, msg.Packet)
if err != nil {

View File

@ -1,16 +1,15 @@
package ante_test
package ibc_test
import (
"testing"
"github.com/stretchr/testify/suite"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/ibc"
ibctransfertypes "github.com/cosmos/cosmos-sdk/x/ibc-transfer/types"
clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported"
channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types"
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
"github.com/cosmos/cosmos-sdk/x/ibc/ante"
ibctesting "github.com/cosmos/cosmos-sdk/x/ibc/testing"
)
@ -34,17 +33,15 @@ func (suite *HandlerTestSuite) SetupTest() {
suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(1))
}
func newTx(msg sdk.Msg) sdk.Tx {
return authtypes.StdTx{
Msgs: []sdk.Msg{msg},
}
func TestHandlerTestSuite(t *testing.T) {
suite.Run(t, new(HandlerTestSuite))
}
// tests the ante handler receiving a packet on ordered and unordered channels.
// It verifies that no state changes occur as the storing of an acknowledgement
// should occur in the 'PacketExecuted' function. It test high level properties
// like ordering and basic sanity checks. More rigorous testing of 'RecvPacket'
// can be found in the 04-channel/keeper/packet_test.go.
// tests the IBC handler receiving a packet on ordered and unordered channels.
// It verifies that the storing of an acknowledgement on success occurs. It
// tests high level properties like ordering and basic sanity checks. More
// rigorous testing of 'RecvPacket' and 'PacketExecuted' can be found in the
// 04-channel/keeper/packet_test.go.
func (suite *HandlerTestSuite) TestHandleRecvPacket() {
var (
packet channeltypes.Packet
@ -58,14 +55,14 @@ func (suite *HandlerTestSuite) TestHandleRecvPacket() {
{"success: ORDERED", func() {
_, clientB, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, clientexported.Tendermint)
channelA, channelB := suite.coordinator.CreateChannel(suite.chainA, suite.chainB, connA, connB, channeltypes.ORDERED)
packet = channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB)
suite.Require().NoError(err)
}, true},
{"success: UNORDERED", func() {
_, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB)
packet = channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB)
suite.Require().NoError(err)
@ -76,7 +73,7 @@ func (suite *HandlerTestSuite) TestHandleRecvPacket() {
// attempts to receive packet with sequence 10 without receiving packet with sequence 1
for i := uint64(1); i < 10; i++ {
packet = channeltypes.NewPacket(ibctesting.TestHash, i, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), i, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB)
suite.Require().NoError(err)
@ -88,7 +85,7 @@ func (suite *HandlerTestSuite) TestHandleRecvPacket() {
// attempts to receive packet with sequence 10 without receiving packet with sequence 1
for i := uint64(1); i < 10; i++ {
packet = channeltypes.NewPacket(ibctesting.TestHash, i, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), i, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB)
suite.Require().NoError(err)
@ -100,12 +97,12 @@ func (suite *HandlerTestSuite) TestHandleRecvPacket() {
}, false},
{"packet not sent", func() {
_, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB)
packet = channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
}, false},
{"ORDERED: packet already received (replay)", func() {
clientA, clientB, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, clientexported.Tendermint)
channelA, channelB := suite.coordinator.CreateChannel(suite.chainA, suite.chainB, connA, connB, channeltypes.ORDERED)
packet = channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB)
suite.Require().NoError(err)
@ -116,7 +113,7 @@ func (suite *HandlerTestSuite) TestHandleRecvPacket() {
{"UNORDERED: packet already received (replay)", func() {
clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB)
packet = channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB)
suite.Require().NoError(err)
@ -132,10 +129,7 @@ func (suite *HandlerTestSuite) TestHandleRecvPacket() {
suite.Run(tc.name, func() {
suite.SetupTest() // reset
handler := sdk.ChainAnteDecorators(ante.NewProofVerificationDecorator(
suite.chainB.App.IBCKeeper.ClientKeeper,
suite.chainB.App.IBCKeeper.ChannelKeeper,
))
handler := ibc.NewHandler(*suite.chainB.App.IBCKeeper)
tc.malleate()
@ -146,19 +140,19 @@ func (suite *HandlerTestSuite) TestHandleRecvPacket() {
msg := channeltypes.NewMsgPacket(packet, proof, proofHeight, suite.chainB.SenderAccount.GetAddress())
// ante-handle RecvPacket
_, err := handler(suite.chainB.GetContext(), newTx(msg), false)
_, err := handler(suite.chainB.GetContext(), msg)
if tc.expPass {
suite.Require().NoError(err)
// replay should return same result since there is no state changes
_, err := handler(suite.chainB.GetContext(), newTx(msg), false)
suite.Require().NoError(err)
// verify ack was not written
// replay should fail since state changes occur
_, err := handler(suite.chainB.GetContext(), msg)
suite.Require().Error(err)
// verify ack was written
ack, found := suite.chainB.App.IBCKeeper.ChannelKeeper.GetPacketAcknowledgement(suite.chainB.GetContext(), packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
suite.Require().Nil(ack)
suite.Require().False(found)
suite.Require().NotNil(ack)
suite.Require().True(found)
} else {
suite.Require().Error(err)
}
@ -166,12 +160,11 @@ func (suite *HandlerTestSuite) TestHandleRecvPacket() {
}
}
// tests the ante handler acknowledging a packet on ordered and unordered
// channels. It verifies that no state changes occur as the deleting of packet
// commitments from state should occur in the 'AcknowledgementExecuted'
// function. It test high level properties like ordering and basic sanity
// checks. More rigorous testing of 'AcknowledgePacket' can be found in
// the 04-channel/keeper/packet_test.go.
// tests the IBC handler acknowledgement of a packet on ordered and unordered
// channels. It verifies that the deletion of packet commitments from state
// occurs. It test high level properties like ordering and basic sanity
// checks. More rigorous testing of 'AcknowledgePacket' and 'AcknowledgementExecuted'
// can be found in the 04-channel/keeper/packet_test.go.
func (suite *HandlerTestSuite) TestHandleAcknowledgePacket() {
var (
packet channeltypes.Packet
@ -185,7 +178,7 @@ func (suite *HandlerTestSuite) TestHandleAcknowledgePacket() {
{"success: ORDERED", func() {
clientA, clientB, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, clientexported.Tendermint)
channelA, channelB := suite.coordinator.CreateChannel(suite.chainA, suite.chainB, connA, connB, channeltypes.ORDERED)
packet = channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB)
suite.Require().NoError(err)
@ -195,7 +188,7 @@ func (suite *HandlerTestSuite) TestHandleAcknowledgePacket() {
}, true},
{"success: UNORDERED", func() {
clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB)
packet = channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB)
suite.Require().NoError(err)
@ -209,7 +202,7 @@ func (suite *HandlerTestSuite) TestHandleAcknowledgePacket() {
// attempts to acknowledge ack with sequence 10 without acknowledging ack with sequence 1 (removing packet commitment)
for i := uint64(1); i < 10; i++ {
packet = channeltypes.NewPacket(ibctesting.TestHash, i, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), i, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB)
suite.Require().NoError(err)
@ -225,7 +218,7 @@ func (suite *HandlerTestSuite) TestHandleAcknowledgePacket() {
// attempts to acknowledge ack with sequence 10 without acknowledging ack with sequence 1 (removing packet commitment
for i := uint64(1); i < 10; i++ {
packet = channeltypes.NewPacket(ibctesting.TestHash, i, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), i, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB)
suite.Require().NoError(err)
@ -240,7 +233,7 @@ func (suite *HandlerTestSuite) TestHandleAcknowledgePacket() {
}, false},
{"packet not received", func() {
_, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB)
packet = channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB)
suite.Require().NoError(err)
@ -248,7 +241,7 @@ func (suite *HandlerTestSuite) TestHandleAcknowledgePacket() {
{"ORDERED: packet already acknowledged (replay)", func() {
clientA, clientB, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, clientexported.Tendermint)
channelA, channelB := suite.coordinator.CreateChannel(suite.chainA, suite.chainB, connA, connB, channeltypes.ORDERED)
packet = channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB)
suite.Require().NoError(err)
@ -262,7 +255,7 @@ func (suite *HandlerTestSuite) TestHandleAcknowledgePacket() {
{"UNORDERED: packet already received (replay)", func() {
clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB)
packet = channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB)
suite.Require().NoError(err)
@ -280,11 +273,9 @@ func (suite *HandlerTestSuite) TestHandleAcknowledgePacket() {
suite.Run(tc.name, func() {
suite.SetupTest() // reset
ibctesting.TestHash = ibctransfertypes.FungibleTokenPacketAcknowledgement{true, ""}.GetBytes()
handler := sdk.ChainAnteDecorators(ante.NewProofVerificationDecorator(
suite.chainA.App.IBCKeeper.ClientKeeper,
suite.chainA.App.IBCKeeper.ChannelKeeper,
))
handler := ibc.NewHandler(*suite.chainA.App.IBCKeeper)
tc.malleate()
@ -295,18 +286,18 @@ func (suite *HandlerTestSuite) TestHandleAcknowledgePacket() {
msg := channeltypes.NewMsgAcknowledgement(packet, ack, proof, proofHeight, suite.chainA.SenderAccount.GetAddress())
// ante-handle RecvPacket
_, err := handler(suite.chainA.GetContext(), newTx(msg), false)
_, err := handler(suite.chainA.GetContext(), msg)
if tc.expPass {
suite.Require().NoError(err)
// replay should return same result since there is no state changes
_, err := handler(suite.chainA.GetContext(), newTx(msg), false)
suite.Require().NoError(err)
// verify packet commitment was not deleted
// replay should an error
_, err := handler(suite.chainA.GetContext(), msg)
suite.Require().Error(err)
// verify packet commitment was deleted
has := suite.chainA.App.IBCKeeper.ChannelKeeper.HasPacketCommitment(suite.chainA.GetContext(), packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
suite.Require().True(has)
suite.Require().False(has)
} else {
suite.Require().Error(err)
@ -315,12 +306,11 @@ func (suite *HandlerTestSuite) TestHandleAcknowledgePacket() {
}
}
// tests the ante handler timing out a packet on ordered and unordered channels.
// It verifies that no state changes occur as the deleting of packet
// commitments from state should occur in the 'TimeoutExecuted' function. It
// tests high level properties like ordering and basic sanity
// checks. More rigorous testing of 'TimeoutPacket' can be found in the
// 04-channel/keeper/timeout_test.go.
// tests the IBC handler timing out a packet on ordered and unordered channels.
// It verifies that the deletion of a packet commitment occurs. It tests
// high level properties like ordering and basic sanity checks. More
// rigorous testing of 'TimeoutPacket' and 'TimeoutExecuted' can be found in
// the 04-channel/keeper/timeout_test.go.
func (suite *HandlerTestSuite) TestHandleTimeoutPacket() {
var (
packet channeltypes.Packet
@ -335,7 +325,7 @@ func (suite *HandlerTestSuite) TestHandleTimeoutPacket() {
{"success: ORDERED", func() {
clientA, clientB, connA, connB := suite.coordinator.SetupClientConnections(suite.chainA, suite.chainB, clientexported.Tendermint)
channelA, channelB := suite.coordinator.CreateChannel(suite.chainA, suite.chainB, connA, connB, channeltypes.ORDERED)
packet = channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, uint64(suite.chainB.GetContext().BlockHeight()), uint64(suite.chainB.GetContext().BlockTime().UnixNano()))
packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, uint64(suite.chainB.GetContext().BlockHeight()), uint64(suite.chainB.GetContext().BlockTime().UnixNano()))
err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB)
suite.Require().NoError(err)
@ -346,7 +336,7 @@ func (suite *HandlerTestSuite) TestHandleTimeoutPacket() {
}, true},
{"success: UNORDERED", func() {
clientA, clientB, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB)
packet = channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, uint64(suite.chainB.GetContext().BlockHeight()), uint64(suite.chainB.GetContext().BlockTime().UnixNano()))
packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, uint64(suite.chainB.GetContext().BlockHeight()), uint64(suite.chainB.GetContext().BlockTime().UnixNano()))
err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB)
suite.Require().NoError(err)
@ -360,7 +350,7 @@ func (suite *HandlerTestSuite) TestHandleTimeoutPacket() {
// attempts to timeout packet with sequence 10 without timing out packet with sequence 1
for i := uint64(1); i < 10; i++ {
packet = channeltypes.NewPacket(ibctesting.TestHash, i, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, uint64(suite.chainB.GetContext().BlockHeight()), 0)
packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), i, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, uint64(suite.chainB.GetContext().BlockHeight()), 0)
err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB)
suite.Require().NoError(err)
@ -376,7 +366,7 @@ func (suite *HandlerTestSuite) TestHandleTimeoutPacket() {
// attempts to timeout packet with sequence 10 without timing out packet with sequence 1
for i := uint64(1); i < 10; i++ {
packet = channeltypes.NewPacket(ibctesting.TestHash, i, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, uint64(suite.chainB.GetContext().BlockHeight()), 0)
packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), i, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, uint64(suite.chainB.GetContext().BlockHeight()), 0)
err := suite.coordinator.SendPacket(suite.chainA, suite.chainB, packet, clientB)
suite.Require().NoError(err)
@ -394,7 +384,7 @@ func (suite *HandlerTestSuite) TestHandleTimeoutPacket() {
}, false},
{"UNORDERED: packet not sent", func() {
_, _, _, _, channelA, channelB := suite.coordinator.Setup(suite.chainA, suite.chainB)
packet = channeltypes.NewPacket(ibctesting.TestHash, 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
packet = channeltypes.NewPacket(suite.chainA.GetPacketData(suite.chainB), 1, channelA.PortID, channelA.ID, channelB.PortID, channelB.ID, timeoutHeight, 0)
packetKey = host.KeyPacketAcknowledgement(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
}, false},
}
@ -405,10 +395,7 @@ func (suite *HandlerTestSuite) TestHandleTimeoutPacket() {
suite.Run(tc.name, func() {
suite.SetupTest() // reset
handler := sdk.ChainAnteDecorators(ante.NewProofVerificationDecorator(
suite.chainA.App.IBCKeeper.ClientKeeper,
suite.chainA.App.IBCKeeper.ChannelKeeper,
))
handler := ibc.NewHandler(*suite.chainA.App.IBCKeeper)
tc.malleate()
@ -416,18 +403,18 @@ func (suite *HandlerTestSuite) TestHandleTimeoutPacket() {
msg := channeltypes.NewMsgTimeout(packet, 1, proof, proofHeight, suite.chainA.SenderAccount.GetAddress())
// ante-handle RecvPacket
_, err := handler(suite.chainA.GetContext(), newTx(msg), false)
_, err := handler(suite.chainA.GetContext(), msg)
if tc.expPass {
suite.Require().NoError(err)
// replay should return same result since there is no state changes
_, err := handler(suite.chainA.GetContext(), newTx(msg), false)
suite.Require().NoError(err)
// verify packet commitment was not deleted
// replay should return an error
_, err := handler(suite.chainA.GetContext(), msg)
suite.Require().Error(err)
// verify packet commitment was deleted
has := suite.chainA.App.IBCKeeper.ChannelKeeper.HasPacketCommitment(suite.chainA.GetContext(), packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
suite.Require().True(has)
suite.Require().False(has)
} else {
suite.Require().Error(err)
@ -435,6 +422,3 @@ func (suite *HandlerTestSuite) TestHandleTimeoutPacket() {
})
}
}
func TestHandlerTestSuite(t *testing.T) {
suite.Run(t, new(HandlerTestSuite))
}

View File

@ -55,8 +55,6 @@ which call each ICS submodule's handlers (i.e `x/ibc/{XX-ICS}/handler.go`).
The following ADR provide the design and architecture decision of IBC-related components.
* [ADR 10 - Modular AnteHandler](../../../docs/architecture/adr-010-modular-antehandler.md): Introduces a decorator pattern for the [`AnteHandler`](../../../docs/basics/gas-fees.md#antehandler), making it modular.
* [ADR 15 - IBC Packet Receiver](../../../docs/architecture/adr-015-ibc-packet-receiver.md): replaces the ICS26 routing module with [`AnteHandler`](../../../docs/basics/gas-fees.md#antehandler) logic within IBC. This is implemented using the `AnteDecorators` defined in [ADR10]((../../../docs/architecture/adr-010-modular-antehandler.md))
* [ADR 17 - Historical Header Module](../../../docs/architecture/adr-017-historical-header-module.md): Introduces the ability to introspect past
consensus states in order to verify their membership in the counterparty clients.
* [ADR 19 - Protobuf State Encoding](../../../docs/architecture/adr-019-protobuf-state-encoding.md): Migration from Amino to Protobuf for state encoding.
@ -91,8 +89,6 @@ x/
│ ├── 09-localhost/
│ ├── 23-commitment/
│ ├── 24-host/
│ ├── ante
│ │ └── ante.go
│ ├── client
│  │ ├── cli
│  │ │   └── cli.go

View File

@ -589,6 +589,14 @@ func (chain *TestChain) ChanCloseInit(
return chain.SendMsg(msg)
}
// GetPacketData returns a ibc-transfer marshalled packet to be used for
// callback testing
func (chain *TestChain) GetPacketData(counterparty *TestChain) []byte {
packet := ibctransfertypes.NewFungibleTokenPacketData(sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(100))), chain.SenderAccount.GetAddress().String(), counterparty.SenderAccount.GetAddress().String())
return packet.GetBytes()
}
// SendPacket simulates sending a packet through the channel keeper. No message needs to be
// passed since this call is made from a module.
func (chain *TestChain) SendPacket(