Skip to content

Commit c77f80f

Browse files
DimitrisJimchatton
andauthored
fix: handle ordered packets in UnreceivedPackets query
Co-authored-by: Cian Hatton <cian@interchain.io>
1 parent 5242ee8 commit c77f80f

File tree

2 files changed

+142
-11
lines changed

2 files changed

+142
-11
lines changed

modules/core/04-channel/keeper/grpc_query.go

+45-8
Original file line numberDiff line numberDiff line change
@@ -398,18 +398,55 @@ func (q Keeper) UnreceivedPackets(c context.Context, req *types.QueryUnreceivedP
398398

399399
ctx := sdk.UnwrapSDKContext(c)
400400

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

403-
for i, seq := range req.PacketCommitmentSequences {
404-
if seq == 0 {
405-
return nil, status.Errorf(codes.InvalidArgument, "packet sequence %d cannot be 0", i)
406-
}
409+
var unreceivedSequences []uint64
410+
switch channel.Ordering {
411+
case types.UNORDERED:
412+
for i, seq := range req.PacketCommitmentSequences {
413+
// filter for invalid sequences to ensure they are not included in the response value.
414+
if seq == 0 {
415+
return nil, status.Errorf(codes.InvalidArgument, "packet sequence %d cannot be 0", i)
416+
}
407417

408-
// if packet receipt exists on the receiving chain, then packet has already been received
409-
if _, found := q.GetPacketReceipt(ctx, req.PortId, req.ChannelId, seq); !found {
410-
unreceivedSequences = append(unreceivedSequences, seq)
418+
// if the packet receipt does not exist, then it is unreceived
419+
if _, found := q.GetPacketReceipt(ctx, req.PortId, req.ChannelId, seq); !found {
420+
unreceivedSequences = append(unreceivedSequences, seq)
421+
}
411422
}
423+
case types.ORDERED:
424+
nextSequenceRecv, found := q.GetNextSequenceRecv(ctx, req.PortId, req.ChannelId)
425+
if !found {
426+
return nil, status.Error(
427+
codes.NotFound,
428+
errorsmod.Wrapf(
429+
types.ErrSequenceReceiveNotFound,
430+
"destination port: %s, destination channel: %s", req.PortId, req.ChannelId,
431+
).Error(),
432+
)
433+
}
434+
435+
for i, seq := range req.PacketCommitmentSequences {
436+
// filter for invalid sequences to ensure they are not included in the response value.
437+
if seq == 0 {
438+
return nil, status.Errorf(codes.InvalidArgument, "packet sequence %d cannot be 0", i)
439+
}
412440

441+
// Any sequence greater than or equal to the next sequence to be received is not received.
442+
if seq >= nextSequenceRecv {
443+
unreceivedSequences = append(unreceivedSequences, seq)
444+
}
445+
}
446+
default:
447+
return nil, status.Error(
448+
codes.InvalidArgument,
449+
errorsmod.Wrapf(types.ErrInvalidChannelOrdering, "channel order %s is not supported", channel.Ordering.String()).Error())
413450
}
414451

415452
selfHeight := clienttypes.GetSelfHeight(ctx)

modules/core/04-channel/keeper/grpc_query_test.go

+97-3
Original file line numberDiff line numberDiff line change
@@ -1112,7 +1112,7 @@ func (suite *KeeperTestSuite) TestQueryPacketAcknowledgements() {
11121112
func (suite *KeeperTestSuite) TestQueryUnreceivedPackets() {
11131113
var (
11141114
req *types.QueryUnreceivedPacketsRequest
1115-
expSeq = []uint64{}
1115+
expSeq = []uint64(nil)
11161116
)
11171117

11181118
testCases := []struct {
@@ -1158,6 +1158,46 @@ func (suite *KeeperTestSuite) TestQueryUnreceivedPackets() {
11581158
},
11591159
false,
11601160
},
1161+
{
1162+
"invalid seq, ordered channel",
1163+
func() {
1164+
path := ibctesting.NewPath(suite.chainA, suite.chainB)
1165+
path.SetChannelOrdered()
1166+
suite.coordinator.Setup(path)
1167+
1168+
req = &types.QueryUnreceivedPacketsRequest{
1169+
PortId: path.EndpointA.ChannelConfig.PortID,
1170+
ChannelId: path.EndpointA.ChannelID,
1171+
PacketCommitmentSequences: []uint64{0},
1172+
}
1173+
},
1174+
false,
1175+
},
1176+
{
1177+
"channel not found",
1178+
func() {
1179+
req = &types.QueryUnreceivedPacketsRequest{
1180+
PortId: "invalid-port-id",
1181+
ChannelId: "invalid-channel-id",
1182+
}
1183+
},
1184+
false,
1185+
},
1186+
{
1187+
"basic success empty packet commitments",
1188+
func() {
1189+
path := ibctesting.NewPath(suite.chainA, suite.chainB)
1190+
suite.coordinator.Setup(path)
1191+
1192+
expSeq = []uint64(nil)
1193+
req = &types.QueryUnreceivedPacketsRequest{
1194+
PortId: path.EndpointA.ChannelConfig.PortID,
1195+
ChannelId: path.EndpointA.ChannelID,
1196+
PacketCommitmentSequences: []uint64{},
1197+
}
1198+
},
1199+
true,
1200+
},
11611201
{
11621202
"basic success unreceived packet commitments",
11631203
func() {
@@ -1183,7 +1223,7 @@ func (suite *KeeperTestSuite) TestQueryUnreceivedPackets() {
11831223

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

1186-
expSeq = []uint64{}
1226+
expSeq = []uint64(nil)
11871227
req = &types.QueryUnreceivedPacketsRequest{
11881228
PortId: path.EndpointA.ChannelConfig.PortID,
11891229
ChannelId: path.EndpointA.ChannelID,
@@ -1197,7 +1237,7 @@ func (suite *KeeperTestSuite) TestQueryUnreceivedPackets() {
11971237
func() {
11981238
path := ibctesting.NewPath(suite.chainA, suite.chainB)
11991239
suite.coordinator.Setup(path)
1200-
expSeq = []uint64{} // reset
1240+
expSeq = []uint64(nil) // reset
12011241
packetCommitments := []uint64{}
12021242

12031243
// set packet receipt for every other sequence
@@ -1219,6 +1259,60 @@ func (suite *KeeperTestSuite) TestQueryUnreceivedPackets() {
12191259
},
12201260
true,
12211261
},
1262+
{
1263+
"basic success empty packet commitments, ordered channel",
1264+
func() {
1265+
path := ibctesting.NewPath(suite.chainA, suite.chainB)
1266+
path.SetChannelOrdered()
1267+
suite.coordinator.Setup(path)
1268+
1269+
expSeq = []uint64(nil)
1270+
req = &types.QueryUnreceivedPacketsRequest{
1271+
PortId: path.EndpointA.ChannelConfig.PortID,
1272+
ChannelId: path.EndpointA.ChannelID,
1273+
PacketCommitmentSequences: []uint64{},
1274+
}
1275+
},
1276+
true,
1277+
},
1278+
{
1279+
"basic success unreceived packet commitments, ordered channel",
1280+
func() {
1281+
path := ibctesting.NewPath(suite.chainA, suite.chainB)
1282+
path.SetChannelOrdered()
1283+
suite.coordinator.Setup(path)
1284+
1285+
// Note: NextSequenceRecv is set to 1 on channel creation.
1286+
expSeq = []uint64{1}
1287+
req = &types.QueryUnreceivedPacketsRequest{
1288+
PortId: path.EndpointA.ChannelConfig.PortID,
1289+
ChannelId: path.EndpointA.ChannelID,
1290+
PacketCommitmentSequences: []uint64{1},
1291+
}
1292+
},
1293+
true,
1294+
},
1295+
{
1296+
"basic success multiple unreceived packet commitments, ordered channel",
1297+
func() {
1298+
path := ibctesting.NewPath(suite.chainA, suite.chainB)
1299+
path.SetChannelOrdered()
1300+
suite.coordinator.Setup(path)
1301+
1302+
// Exercise scenario from issue #1532. NextSequenceRecv is 5, packet commitments provided are 2, 7, 9, 10.
1303+
// Packet sequence 2 is already received so only sequences 7, 9, 10 should be considered unreceived.
1304+
expSeq = []uint64{7, 9, 10}
1305+
packetCommitments := []uint64{2, 7, 9, 10}
1306+
suite.chainA.App.GetIBCKeeper().ChannelKeeper.SetNextSequenceRecv(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, 5)
1307+
1308+
req = &types.QueryUnreceivedPacketsRequest{
1309+
PortId: path.EndpointA.ChannelConfig.PortID,
1310+
ChannelId: path.EndpointA.ChannelID,
1311+
PacketCommitmentSequences: packetCommitments,
1312+
}
1313+
},
1314+
true,
1315+
},
12221316
}
12231317

12241318
for _, tc := range testCases {

0 commit comments

Comments
 (0)