Skip to content

Commit

Permalink
fix: handle ordered packets in UnreceivedPackets query
Browse files Browse the repository at this point in the history
Co-authored-by: Cian Hatton <[email protected]>
  • Loading branch information
DimitrisJim and chatton committed Mar 30, 2023
1 parent 5242ee8 commit c77f80f
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 11 deletions.
53 changes: 45 additions & 8 deletions modules/core/04-channel/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -398,18 +398,55 @@ func (q Keeper) UnreceivedPackets(c context.Context, req *types.QueryUnreceivedP

ctx := sdk.UnwrapSDKContext(c)

unreceivedSequences := []uint64{}
channel, found := q.GetChannel(sdk.UnwrapSDKContext(c), req.PortId, req.ChannelId)
if !found {
return nil, status.Error(
codes.NotFound,
errorsmod.Wrapf(types.ErrChannelNotFound, "port-id: %s, channel-id %s", req.PortId, req.ChannelId).Error(),
)
}

for i, seq := range req.PacketCommitmentSequences {
if seq == 0 {
return nil, status.Errorf(codes.InvalidArgument, "packet sequence %d cannot be 0", i)
}
var unreceivedSequences []uint64
switch channel.Ordering {
case types.UNORDERED:
for i, seq := range req.PacketCommitmentSequences {
// filter for invalid sequences to ensure they are not included in the response value.
if seq == 0 {
return nil, status.Errorf(codes.InvalidArgument, "packet sequence %d cannot be 0", i)
}

// if packet receipt exists on the receiving chain, then packet has already been received
if _, found := q.GetPacketReceipt(ctx, req.PortId, req.ChannelId, seq); !found {
unreceivedSequences = append(unreceivedSequences, seq)
// if the packet receipt does not exist, then it is unreceived
if _, found := q.GetPacketReceipt(ctx, req.PortId, req.ChannelId, seq); !found {
unreceivedSequences = append(unreceivedSequences, seq)
}
}
case types.ORDERED:
nextSequenceRecv, found := q.GetNextSequenceRecv(ctx, req.PortId, req.ChannelId)
if !found {
return nil, status.Error(
codes.NotFound,
errorsmod.Wrapf(
types.ErrSequenceReceiveNotFound,
"destination port: %s, destination channel: %s", req.PortId, req.ChannelId,
).Error(),
)
}

for i, seq := range req.PacketCommitmentSequences {
// filter for invalid sequences to ensure they are not included in the response value.
if seq == 0 {
return nil, status.Errorf(codes.InvalidArgument, "packet sequence %d cannot be 0", i)
}

// Any sequence greater than or equal to the next sequence to be received is not received.
if seq >= nextSequenceRecv {
unreceivedSequences = append(unreceivedSequences, seq)
}
}
default:
return nil, status.Error(
codes.InvalidArgument,
errorsmod.Wrapf(types.ErrInvalidChannelOrdering, "channel order %s is not supported", channel.Ordering.String()).Error())
}

selfHeight := clienttypes.GetSelfHeight(ctx)
Expand Down
100 changes: 97 additions & 3 deletions modules/core/04-channel/keeper/grpc_query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1112,7 +1112,7 @@ func (suite *KeeperTestSuite) TestQueryPacketAcknowledgements() {
func (suite *KeeperTestSuite) TestQueryUnreceivedPackets() {
var (
req *types.QueryUnreceivedPacketsRequest
expSeq = []uint64{}
expSeq = []uint64(nil)
)

testCases := []struct {
Expand Down Expand Up @@ -1158,6 +1158,46 @@ func (suite *KeeperTestSuite) TestQueryUnreceivedPackets() {
},
false,
},
{
"invalid seq, ordered channel",
func() {
path := ibctesting.NewPath(suite.chainA, suite.chainB)
path.SetChannelOrdered()
suite.coordinator.Setup(path)

req = &types.QueryUnreceivedPacketsRequest{
PortId: path.EndpointA.ChannelConfig.PortID,
ChannelId: path.EndpointA.ChannelID,
PacketCommitmentSequences: []uint64{0},
}
},
false,
},
{
"channel not found",
func() {
req = &types.QueryUnreceivedPacketsRequest{
PortId: "invalid-port-id",
ChannelId: "invalid-channel-id",
}
},
false,
},
{
"basic success empty packet commitments",
func() {
path := ibctesting.NewPath(suite.chainA, suite.chainB)
suite.coordinator.Setup(path)

expSeq = []uint64(nil)
req = &types.QueryUnreceivedPacketsRequest{
PortId: path.EndpointA.ChannelConfig.PortID,
ChannelId: path.EndpointA.ChannelID,
PacketCommitmentSequences: []uint64{},
}
},
true,
},
{
"basic success unreceived packet commitments",
func() {
Expand All @@ -1183,7 +1223,7 @@ func (suite *KeeperTestSuite) TestQueryUnreceivedPackets() {

suite.chainA.App.GetIBCKeeper().ChannelKeeper.SetPacketReceipt(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, 1)

expSeq = []uint64{}
expSeq = []uint64(nil)
req = &types.QueryUnreceivedPacketsRequest{
PortId: path.EndpointA.ChannelConfig.PortID,
ChannelId: path.EndpointA.ChannelID,
Expand All @@ -1197,7 +1237,7 @@ func (suite *KeeperTestSuite) TestQueryUnreceivedPackets() {
func() {
path := ibctesting.NewPath(suite.chainA, suite.chainB)
suite.coordinator.Setup(path)
expSeq = []uint64{} // reset
expSeq = []uint64(nil) // reset
packetCommitments := []uint64{}

// set packet receipt for every other sequence
Expand All @@ -1219,6 +1259,60 @@ func (suite *KeeperTestSuite) TestQueryUnreceivedPackets() {
},
true,
},
{
"basic success empty packet commitments, ordered channel",
func() {
path := ibctesting.NewPath(suite.chainA, suite.chainB)
path.SetChannelOrdered()
suite.coordinator.Setup(path)

expSeq = []uint64(nil)
req = &types.QueryUnreceivedPacketsRequest{
PortId: path.EndpointA.ChannelConfig.PortID,
ChannelId: path.EndpointA.ChannelID,
PacketCommitmentSequences: []uint64{},
}
},
true,
},
{
"basic success unreceived packet commitments, ordered channel",
func() {
path := ibctesting.NewPath(suite.chainA, suite.chainB)
path.SetChannelOrdered()
suite.coordinator.Setup(path)

// Note: NextSequenceRecv is set to 1 on channel creation.
expSeq = []uint64{1}
req = &types.QueryUnreceivedPacketsRequest{
PortId: path.EndpointA.ChannelConfig.PortID,
ChannelId: path.EndpointA.ChannelID,
PacketCommitmentSequences: []uint64{1},
}
},
true,
},
{
"basic success multiple unreceived packet commitments, ordered channel",
func() {
path := ibctesting.NewPath(suite.chainA, suite.chainB)
path.SetChannelOrdered()
suite.coordinator.Setup(path)

// Exercise scenario from issue #1532. NextSequenceRecv is 5, packet commitments provided are 2, 7, 9, 10.
// Packet sequence 2 is already received so only sequences 7, 9, 10 should be considered unreceived.
expSeq = []uint64{7, 9, 10}
packetCommitments := []uint64{2, 7, 9, 10}
suite.chainA.App.GetIBCKeeper().ChannelKeeper.SetNextSequenceRecv(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, 5)

req = &types.QueryUnreceivedPacketsRequest{
PortId: path.EndpointA.ChannelConfig.PortID,
ChannelId: path.EndpointA.ChannelID,
PacketCommitmentSequences: packetCommitments,
}
},
true,
},
}

for _, tc := range testCases {
Expand Down

0 comments on commit c77f80f

Please sign in to comment.