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

Handle ordered packets in UnreceivedPackets query. #3346

51 changes: 43 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,53 @@ 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)
unreceivedSequences := []uint64{}
switch channel.Ordering {
case types.UNORDERED:
for i, seq := range req.PacketCommitmentSequences {
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 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)
case types.ORDERED:
nextSequenceRecv, found := q.GetNextSequenceRecv(ctx, req.PortId, req.ChannelId)
if !found {
return nil, status.Error(
codes.InvalidArgument,
errorsmod.Wrapf(
types.ErrSequenceReceiveNotFound,
"destination port: %s, destination channel: %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)
}

// If the packet sequence is greater than the sequence most recently received, then the packet has not been received.
if seq >= nextSequenceRecv {
unreceivedSequences = append(unreceivedSequences, seq)
}
}
default:
return nil, status.Error(
codes.InvalidArgument,
errorsmod.Wrapf(types.ErrInvalidChannelOrdering, channel.Ordering.String()).Error())
}

selfHeight := clienttypes.GetSelfHeight(ctx)
Expand Down
49 changes: 49 additions & 0 deletions modules/core/04-channel/keeper/grpc_query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1158,6 +1158,16 @@ func (suite *KeeperTestSuite) TestQueryUnreceivedPackets() {
},
false,
},
{
"channel not found",
func() {
req = &types.QueryUnreceivedPacketsRequest{
PortId: "test-port-id",
ChannelId: "test-channel-id",
}
},
false,
},
{
"basic success unreceived packet commitments",
func() {
Expand Down Expand Up @@ -1219,6 +1229,45 @@ func (suite *KeeperTestSuite) TestQueryUnreceivedPackets() {
},
true,
},
{
"success basic unreceived packet commitments, ordered channel",
func() {
path := ibctesting.NewPath(suite.chainA, suite.chainB)
path.SetChannelOrdered()
suite.coordinator.Setup(path)

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

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

// Excersise scenario from issue 1532. NextSequenceRecv is 5, commitments for 2, 7, 9, 10
// are present. 2 is received so 7, 9, 10 should be 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)
Copy link
Contributor

@charleenfei charleenfei Mar 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe the NextSequenceRecv parameter and the expSeq/packetCommitments variables can be set up as well generally as variables for the test which are then malleated per test?

Copy link
Contributor Author

@DimitrisJim DimitrisJim Mar 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expSeq is already set up as so (If i'm understanding the comment correctly) and the rationale I got was that it's done since we need to assert its value against the expected in the main test body. Let me know if I got something wrong here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah okay, i was just seeing the packet commitment sequences getting declared/set on the tests as well as the sequence number, so i was thinking to just set them as variables instead for readability -- but i am not very strongly opinionated, i agree that expSeq is the most important as we are testing for that value as the expected one. thanks!


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

for _, tc := range testCases {
Expand Down