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 unreceived packets rpc #7561

Merged
Merged
Show file tree
Hide file tree
Changes from 3 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
1 change: 1 addition & 0 deletions modules/core/04-channel/v2/client/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func GetQueryCmd() *cobra.Command {
getCmdQueryPacketCommitments(),
getCmdQueryPacketAcknowledgement(),
getCmdQueryPacketReceipt(),
getCmdQueryUnreceivedPackets(),
)

return queryCmd
Expand Down
46 changes: 46 additions & 0 deletions modules/core/04-channel/v2/client/cli/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ import (
"github.com/cosmos/ibc-go/v9/modules/core/exported"
)

const (
flagSequences = "sequences"
)

// getCmdQueryChannel defines the command to query the channel information (creator and channel) for the given channel ID.
func getCmdQueryChannel() *cobra.Command {
cmd := &cobra.Command{
Expand Down Expand Up @@ -282,3 +286,45 @@ func getCmdQueryPacketReceipt() *cobra.Command {

return cmd
}

func getCmdQueryUnreceivedPackets() *cobra.Command {
cmd := &cobra.Command{
Use: "unreceived-packets [channel-id]",
Short: "Query a channel/v2 unreceived-packets",
Long: "Query a channel/v2 unreceived-packets by channel-id and sequences",
Example: fmt.Sprintf(
"%s query %s %s unreceived-packet [channel-id] --sequences=1,2,3", version.AppName, exported.ModuleName, types.SubModuleName,
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}

channelID := args[0]
seqSlice, err := cmd.Flags().GetInt64Slice(flagSequences)
if err != nil {
return err
}

seqs := make([]uint64, len(seqSlice))
for i := range seqSlice {
seqs[i] = uint64(seqSlice[i])
}

queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.UnreceivedPackets(cmd.Context(), types.NewQueryUnreceivedPacketsRequest(channelID, seqs))
if err != nil {
return err
}

return clientCtx.PrintProto(res)
},
}

cmd.Flags().Bool(flags.FlagProve, true, "show proofs for the query results")
flags.AddQueryFlagsToCmd(cmd)

return cmd
}
53 changes: 53 additions & 0 deletions modules/core/04-channel/v2/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,56 @@ func (q *queryServer) PacketReceipt(ctx context.Context, req *types.QueryPacketR

return types.NewQueryPacketReceiptResponse(hasReceipt, nil, clienttypes.GetSelfHeight(ctx)), nil
}

// UnreceivedPackets implements the Query/UnreceivedPackets gRPC method. Given
// a list of counterparty packet commitments, the querier checks if the packet
// has already been received by checking if a receipt exists on this
// chain for the packet sequence. All packets that haven't been received yet
// are returned in the response
// Usage: To use this method correctly, first query all packet commitments on
// the sending chain using the Query/PacketCommitments gRPC method.
// Then input the returned sequences into the QueryUnreceivedPacketsRequest
// and send the request to this Query/UnreceivedPackets on the **receiving**
// chain. This gRPC method will then return the list of packet sequences that
// are yet to be received on the receiving chain.
//
// NOTE: The querier makes the assumption that the provided list of packet
// commitments is correct and will not function properly if the list
// is not up to date. Ideally the query height should equal the latest height
// on the counterparty's client which represents this chain.
func (q *queryServer) UnreceivedPackets(ctx context.Context, req *types.QueryUnreceivedPacketsRequest) (*types.QueryUnreceivedPacketsResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}

if err := host.ChannelIdentifierValidator(req.ChannelId); err != nil {
return nil, status.Error(codes.InvalidArgument, err.Error())
}

_, found := q.GetChannel(ctx, req.ChannelId)
if !found {
return nil, status.Error(
codes.NotFound,
errorsmod.Wrapf(types.ErrChannelNotFound, "channel-id %s", req.ChannelId).Error(),
)
}

var unreceivedSequences []uint64
for i, seq := range req.Sequences {
// 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 the packet receipt does not exist, then it is unreceived
if _, found := q.GetPacketReceipt(ctx, req.ChannelId, seq); !found {
unreceivedSequences = append(unreceivedSequences, seq)
}
}

selfHeight := clienttypes.GetSelfHeight(ctx)
return &types.QueryUnreceivedPacketsResponse{
Sequences: unreceivedSequences,
Height: selfHeight,
}, nil
}
8 changes: 8 additions & 0 deletions modules/core/04-channel/v2/types/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,11 @@ func NewQueryPacketReceiptResponse(exists bool, proof []byte, height clienttypes
ProofHeight: height,
}
}

// NewQueryPacketReceiptRequest creates and returns a new packet receipt query request.
func NewQueryUnreceivedPacketsRequest(channelID string, sequences []uint64) *QueryUnreceivedPacketsRequest {
return &QueryUnreceivedPacketsRequest{
ChannelId: channelID,
Sequences: sequences,
}
}
Loading
Loading