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

chore: add redundancy checks for V2 Msgs #7509

Merged
merged 2 commits into from
Nov 4, 2024
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
31 changes: 31 additions & 0 deletions modules/core/ante/ante.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

clienttypes "github.com/cosmos/ibc-go/v9/modules/core/02-client/types"
channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types"
channeltypesv2 "github.com/cosmos/ibc-go/v9/modules/core/04-channel/v2/types"
"github.com/cosmos/ibc-go/v9/modules/core/exported"
"github.com/cosmos/ibc-go/v9/modules/core/keeper"
)
Expand Down Expand Up @@ -89,6 +90,36 @@ func (rrd RedundantRelayDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
return ctx, err
}

case *channeltypesv2.MsgTimeout:
response, err := rrd.k.ChannelKeeperV2.Timeout(ctx, msg)
if err != nil {
return ctx, err
}

if response.Result == channeltypes.NOOP {
redundancies++
}
packetMsgs++
case *channeltypesv2.MsgAcknowledgement:
response, err := rrd.k.ChannelKeeperV2.Acknowledgement(ctx, msg)
if err != nil {
return ctx, err
}

if response.Result == channeltypes.NOOP {
redundancies++
}
packetMsgs++
case *channeltypesv2.MsgRecvPacket:
response, err := rrd.k.ChannelKeeperV2.RecvPacket(ctx, msg)
if err != nil {
return ctx, err
}

if response.Result == channeltypes.NOOP {
redundancies++
}
packetMsgs++
default:
// if the multiMsg tx has a msg that is not a packet msg or update msg, then we will not return error
// regardless of if all packet messages are redundant. This ensures that non-packet messages get processed
Expand Down
123 changes: 123 additions & 0 deletions modules/core/ante/ante_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"testing"
"time"

"github.com/stretchr/testify/require"
testifysuite "github.com/stretchr/testify/suite"
Expand All @@ -13,12 +14,15 @@ import (

clienttypes "github.com/cosmos/ibc-go/v9/modules/core/02-client/types"
channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types"
channeltypesv2 "github.com/cosmos/ibc-go/v9/modules/core/04-channel/v2/types"
commitmenttypes "github.com/cosmos/ibc-go/v9/modules/core/23-commitment/types"
host "github.com/cosmos/ibc-go/v9/modules/core/24-host"
hostv2 "github.com/cosmos/ibc-go/v9/modules/core/24-host/v2"
"github.com/cosmos/ibc-go/v9/modules/core/ante"
"github.com/cosmos/ibc-go/v9/modules/core/exported"
ibctm "github.com/cosmos/ibc-go/v9/modules/light-clients/07-tendermint"
ibctesting "github.com/cosmos/ibc-go/v9/testing"
"github.com/cosmos/ibc-go/v9/testing/mock/v2"
)

type AnteTestSuite struct {
Expand Down Expand Up @@ -74,6 +78,25 @@ func (suite *AnteTestSuite) createRecvPacketMessage(isRedundant bool) *channelty
return channeltypes.NewMsgRecvPacket(packet, proof, proofHeight, suite.path.EndpointA.Chain.SenderAccount.GetAddress().String())
}

// createRecvPacketMessageV2 creates a V2 RecvPacket message for a packet sent from chain A to chain B.
func (suite *AnteTestSuite) createRecvPacketMessageV2(isRedundant bool) *channeltypesv2.MsgRecvPacket {
packet, err := suite.path.EndpointA.MsgSendPacket(suite.chainA.GetTimeoutTimestamp(), mock.NewMockPayload(mock.ModuleNameA, mock.ModuleNameB))
suite.Require().NoError(err)

if isRedundant {
err = suite.path.EndpointB.MsgRecvPacket(packet)
suite.Require().NoError(err)
}

err = suite.path.EndpointB.UpdateClient()
suite.Require().NoError(err)

packetKey := hostv2.PacketCommitmentKey(packet.SourceChannel, packet.Sequence)
proof, proofHeight := suite.chainA.QueryProof(packetKey)

return channeltypesv2.NewMsgRecvPacket(packet, proof, proofHeight, suite.path.EndpointA.Chain.SenderAccount.GetAddress().String())
}

// createAcknowledgementMessage creates an Acknowledgement message for a packet sent from chain B to chain A.
func (suite *AnteTestSuite) createAcknowledgementMessage(isRedundant bool) sdk.Msg {
sequence, err := suite.path.EndpointB.SendPacket(clienttypes.NewHeight(2, 0), 0, ibctesting.MockPacketData)
Expand All @@ -97,6 +120,33 @@ func (suite *AnteTestSuite) createAcknowledgementMessage(isRedundant bool) sdk.M
return channeltypes.NewMsgAcknowledgement(packet, ibctesting.MockAcknowledgement, proof, proofHeight, suite.path.EndpointA.Chain.SenderAccount.GetAddress().String())
}

// createAcknowledgementMessageV2 creates a V2 Acknowledgement message for a packet sent from chain B to chain A.
func (suite *AnteTestSuite) createAcknowledgementMessageV2(isRedundant bool) *channeltypesv2.MsgAcknowledgement {
packet, err := suite.path.EndpointB.MsgSendPacket(suite.chainB.GetTimeoutTimestamp(), mock.NewMockPayload(mock.ModuleNameA, mock.ModuleNameB))
suite.Require().NoError(err)

err = suite.path.EndpointA.MsgRecvPacket(packet)
suite.Require().NoError(err)

ack := channeltypesv2.Acknowledgement{
AcknowledgementResults: []channeltypesv2.AcknowledgementResult{
{
AppName: mock.ModuleNameB,
RecvPacketResult: mock.MockRecvPacketResult,
},
},
}
if isRedundant {
err = suite.path.EndpointB.MsgAcknowledgePacket(packet, ack)
suite.Require().NoError(err)
}

packetKey := hostv2.PacketAcknowledgementKey(packet.DestinationChannel, packet.Sequence)
proof, proofHeight := suite.chainA.QueryProof(packetKey)

return channeltypesv2.NewMsgAcknowledgement(packet, ack, proof, proofHeight, suite.path.EndpointA.Chain.SenderAccount.GetAddress().String())
}

// createTimeoutMessage creates an Timeout message for a packet sent from chain B to chain A.
func (suite *AnteTestSuite) createTimeoutMessage(isRedundant bool) sdk.Msg {
height := suite.chainA.LatestCommittedHeader.GetHeight()
Expand Down Expand Up @@ -126,6 +176,27 @@ func (suite *AnteTestSuite) createTimeoutMessage(isRedundant bool) sdk.Msg {
return channeltypes.NewMsgTimeout(packet, sequence, proof, proofHeight, suite.path.EndpointA.Chain.SenderAccount.GetAddress().String())
}

// createTimeoutMessageV2 creates a V2 Timeout message for a packet sent from chain B to chain A.
func (suite *AnteTestSuite) createTimeoutMessageV2(isRedundant bool) *channeltypesv2.MsgTimeout {
timeoutTimestamp := uint64(suite.chainB.GetContext().BlockTime().Unix())
packet, err := suite.path.EndpointB.MsgSendPacket(timeoutTimestamp, mock.NewMockPayload(mock.ModuleNameA, mock.ModuleNameB))
suite.Require().NoError(err)

suite.coordinator.IncrementTimeBy(time.Hour)
err = suite.path.EndpointB.UpdateClient()
suite.Require().NoError(err)

if isRedundant {
err = suite.path.EndpointB.MsgTimeoutPacket(packet)
suite.Require().NoError(err)
}

packetKey := hostv2.PacketReceiptKey(packet.SourceChannel, packet.Sequence)
proof, proofHeight := suite.chainA.QueryProof(packetKey)

return channeltypesv2.NewMsgTimeout(packet, proof, proofHeight, suite.path.EndpointA.Chain.SenderAccount.GetAddress().String())
}

// createTimeoutOnCloseMessage creates an TimeoutOnClose message for a packet sent from chain B to chain A.
func (suite *AnteTestSuite) createTimeoutOnCloseMessage(isRedundant bool) sdk.Msg {
height := suite.chainA.LatestCommittedHeader.GetHeight()
Expand Down Expand Up @@ -193,6 +264,15 @@ func (suite *AnteTestSuite) TestAnteDecoratorCheckTx() {
},
nil,
},
{
"success on one new V2 RecvPacket message",
func(suite *AnteTestSuite) []sdk.Msg {
suite.path.SetupV2()
// the RecvPacket message has not been submitted to the chain yet, so it will succeed
return []sdk.Msg{suite.createRecvPacketMessageV2(false)}
},
nil,
},
{
"success on one new Acknowledgement message",
func(suite *AnteTestSuite) []sdk.Msg {
Expand All @@ -201,6 +281,15 @@ func (suite *AnteTestSuite) TestAnteDecoratorCheckTx() {
},
nil,
},
{
"success on one new V2 Acknowledgement message",
func(suite *AnteTestSuite) []sdk.Msg {
suite.path.SetupV2()
// the Acknowledgement message has not been submitted to the chain yet, so it will succeed
return []sdk.Msg{suite.createAcknowledgementMessageV2(false)}
},
nil,
},
{
"success on one new Timeout message",
func(suite *AnteTestSuite) []sdk.Msg {
Expand All @@ -209,6 +298,15 @@ func (suite *AnteTestSuite) TestAnteDecoratorCheckTx() {
},
nil,
},
{
"success on one new Timeout V2 message",
func(suite *AnteTestSuite) []sdk.Msg {
suite.path.SetupV2()
// the Timeout message has not been submitted to the chain yet, so it will succeed
return []sdk.Msg{suite.createTimeoutMessageV2(false)}
},
nil,
},
{
"success on one new TimeoutOnClose message",
func(suite *AnteTestSuite) []sdk.Msg {
Expand Down Expand Up @@ -368,6 +466,14 @@ func (suite *AnteTestSuite) TestAnteDecoratorCheckTx() {
},
channeltypes.ErrRedundantTx,
},
{
"no success on one redundant V2 RecvPacket message",
func(suite *AnteTestSuite) []sdk.Msg {
suite.path.SetupV2()
return []sdk.Msg{suite.createRecvPacketMessageV2(true)}
},
channeltypes.ErrRedundantTx,
},
{
"no success on three redundant messages of each type",
func(suite *AnteTestSuite) []sdk.Msg {
Expand Down Expand Up @@ -555,6 +661,15 @@ func (suite *AnteTestSuite) TestAnteDecoratorReCheckTx() {
},
nil,
},
{
"success on one new V2 RecvPacket message",
func(suite *AnteTestSuite) []sdk.Msg {
suite.path.SetupV2()
// the RecvPacket message has not been submitted to the chain yet, so it will succeed
return []sdk.Msg{suite.createRecvPacketMessageV2(false)}
},
nil,
},
{
"success on one redundant and one new RecvPacket message",
func(suite *AnteTestSuite) []sdk.Msg {
Expand Down Expand Up @@ -595,6 +710,14 @@ func (suite *AnteTestSuite) TestAnteDecoratorReCheckTx() {
},
channeltypes.ErrRedundantTx,
},
{
"no success on one redundant V2 RecvPacket message",
func(suite *AnteTestSuite) []sdk.Msg {
suite.path.SetupV2()
return []sdk.Msg{suite.createRecvPacketMessageV2(true)}
},
channeltypes.ErrRedundantTx,
},
}

for _, tc := range testCases {
Expand Down
Loading