Skip to content

Commit bd6c832

Browse files
mergify[bot]DimitrisJimcrodriguezvegacolin-axner
authored
Handle ordered packets in UnreceivedPackets query. (backport #3346) (#3614)
* fix: handle ordered packets in `UnreceivedPackets` query Co-authored-by: Cian Hatton <cian@interchain.io> (cherry picked from commit c77f80f) --------- Co-authored-by: Jim Fasarakis-Hilliard <d.f.hilliard@gmail.com> Co-authored-by: Carlos Rodriguez <carlos@interchain.io> Co-authored-by: colin axner <25233464+colin-axner@users.noreply.github.com>
1 parent 3a593b2 commit bd6c832

File tree

4 files changed

+147
-15
lines changed

4 files changed

+147
-15
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ Ref: https://keepachangelog.com/en/1.0.0/
5151
### Features
5252

5353
### Bug Fixes
54-
54+
55+
* [\#3346](https://github.com/cosmos/ibc-go/pull/3346) Properly handle ordered channels in `UnreceivedPackets` query.
56+
5557
## [v7.0.0](https://github.com/cosmos/ibc-go/releases/tag/v6.1.0) - 2023-03-17
5658

5759
### Dependencies

modules/apps/transfer/types/transfer_authorization.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package types
33
import (
44
"math/big"
55

6-
errorsmod "cosmossdk.io/errors"
76
sdkmath "cosmossdk.io/math"
87
sdk "github.com/cosmos/cosmos-sdk/types"
98
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
@@ -43,7 +42,7 @@ func (a TransferAuthorization) Accept(ctx sdk.Context, msg sdk.Msg) (authz.Accep
4342
}
4443

4544
if !isAllowedAddress(ctx, msgTransfer.Receiver, allocation.AllowList) {
46-
return authz.AcceptResponse{}, errorsmod.Wrap(sdkerrors.ErrInvalidAddress, "not allowed receiver address for transfer")
45+
return authz.AcceptResponse{}, sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "not allowed receiver address for transfer")
4746
}
4847

4948
// If the spend limit is set to the MaxUint256 sentinel value, do not subtract the amount from the spend limit.
@@ -53,7 +52,7 @@ func (a TransferAuthorization) Accept(ctx sdk.Context, msg sdk.Msg) (authz.Accep
5352

5453
limitLeft, isNegative := allocation.SpendLimit.SafeSub(msgTransfer.Token)
5554
if isNegative {
56-
return authz.AcceptResponse{}, errorsmod.Wrapf(sdkerrors.ErrInsufficientFunds, "requested amount is more than spend limit")
55+
return authz.AcceptResponse{}, sdkerrors.Wrapf(sdkerrors.ErrInsufficientFunds, "requested amount is more than spend limit")
5756
}
5857

5958
if limitLeft.IsZero() {

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

Lines changed: 45 additions & 8 deletions
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+
sdkerrors.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+
}
422+
}
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+
sdkerrors.Wrapf(
429+
types.ErrSequenceReceiveNotFound,
430+
"destination port: %s, destination channel: %s", req.PortId, req.ChannelId,
431+
).Error(),
432+
)
411433
}
412434

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+
}
440+
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+
sdkerrors.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

Lines changed: 97 additions & 3 deletions
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)