github.com/okex/exchain@v1.8.0/libs/ibc-go/modules/core/04-channel/keeper/grpc_query.go (about) 1 package keeper 2 3 import ( 4 "context" 5 "strconv" 6 "strings" 7 8 "github.com/okex/exchain/libs/cosmos-sdk/store/prefix" 9 sdk "github.com/okex/exchain/libs/cosmos-sdk/types" 10 sdkerrors "github.com/okex/exchain/libs/cosmos-sdk/types/errors" 11 "github.com/okex/exchain/libs/cosmos-sdk/types/query" 12 clienttypes "github.com/okex/exchain/libs/ibc-go/modules/core/02-client/types" 13 connectiontypes "github.com/okex/exchain/libs/ibc-go/modules/core/03-connection/types" 14 "github.com/okex/exchain/libs/ibc-go/modules/core/04-channel/types" 15 host "github.com/okex/exchain/libs/ibc-go/modules/core/24-host" 16 17 "google.golang.org/grpc/codes" 18 "google.golang.org/grpc/status" 19 ) 20 21 var _ types.QueryServer = (*Keeper)(nil) 22 23 // Channel implements the Query/Channel gRPC method 24 func (q Keeper) Channel(c context.Context, req *types.QueryChannelRequest) (*types.QueryChannelResponse, error) { 25 if req == nil { 26 return nil, status.Error(codes.InvalidArgument, "empty request") 27 } 28 29 if err := validategRPCRequest(req.PortId, req.ChannelId); err != nil { 30 return nil, err 31 } 32 33 ctx := sdk.UnwrapSDKContext(c) 34 channel, found := q.GetChannel(ctx, req.PortId, req.ChannelId) 35 if !found { 36 return nil, status.Error( 37 codes.NotFound, 38 sdkerrors.Wrapf(types.ErrChannelNotFound, "port-id: %s, channel-id %s", req.PortId, req.ChannelId).Error(), 39 ) 40 } 41 42 selfHeight := clienttypes.GetSelfHeight(ctx) 43 return types.NewQueryChannelResponse(channel, nil, selfHeight), nil 44 } 45 46 // Channels implements the Query/Channels gRPC method 47 func (q Keeper) Channels(c context.Context, req *types.QueryChannelsRequest) (*types.QueryChannelsResponse, error) { 48 if req == nil { 49 return nil, status.Error(codes.InvalidArgument, "empty request") 50 } 51 52 ctx := sdk.UnwrapSDKContext(c) 53 54 channels := []*types.IdentifiedChannel{} 55 store := prefix.NewStore(ctx.KVStore(q.storeKey), []byte(host.KeyChannelEndPrefix)) 56 57 pageRes, err := query.Paginate(store, req.Pagination, func(key, value []byte) error { 58 var result types.Channel 59 if err := q.cdc.GetProtocMarshal().UnmarshalBinaryBare(value, &result); err != nil { 60 return err 61 } 62 63 portID, channelID, err := host.ParseChannelPath(string(key)) 64 if err != nil { 65 return err 66 } 67 68 identifiedChannel := types.NewIdentifiedChannel(portID, channelID, result) 69 channels = append(channels, &identifiedChannel) 70 return nil 71 }) 72 73 if err != nil { 74 return nil, err 75 } 76 77 selfHeight := clienttypes.GetSelfHeight(ctx) 78 return &types.QueryChannelsResponse{ 79 Channels: channels, 80 Pagination: pageRes, 81 Height: selfHeight, 82 }, nil 83 } 84 85 // ConnectionChannels implements the Query/ConnectionChannels gRPC method 86 func (q Keeper) ConnectionChannels(c context.Context, req *types.QueryConnectionChannelsRequest) (*types.QueryConnectionChannelsResponse, error) { 87 if req == nil { 88 return nil, status.Error(codes.InvalidArgument, "empty request") 89 } 90 91 if err := host.ConnectionIdentifierValidator(req.Connection); err != nil { 92 return nil, status.Error(codes.InvalidArgument, err.Error()) 93 } 94 95 ctx := sdk.UnwrapSDKContext(c) 96 97 channels := []*types.IdentifiedChannel{} 98 store := prefix.NewStore(ctx.KVStore(q.storeKey), []byte(host.KeyChannelEndPrefix)) 99 100 pageRes, err := query.Paginate(store, req.Pagination, func(key, value []byte) error { 101 var result types.Channel 102 if err := q.cdc.GetProtocMarshal().UnmarshalBinaryBare(value, &result); err != nil { 103 return err 104 } 105 106 // ignore channel and continue to the next item if the connection is 107 // different than the requested one 108 if result.ConnectionHops[0] != req.Connection { 109 return nil 110 } 111 112 portID, channelID, err := host.ParseChannelPath(string(key)) 113 if err != nil { 114 return err 115 } 116 117 identifiedChannel := types.NewIdentifiedChannel(portID, channelID, result) 118 channels = append(channels, &identifiedChannel) 119 return nil 120 }) 121 122 if err != nil { 123 return nil, err 124 } 125 126 selfHeight := clienttypes.GetSelfHeight(ctx) 127 return &types.QueryConnectionChannelsResponse{ 128 Channels: channels, 129 Pagination: pageRes, 130 Height: selfHeight, 131 }, nil 132 } 133 134 // ChannelClientState implements the Query/ChannelClientState gRPC method 135 func (q Keeper) ChannelClientState(c context.Context, req *types.QueryChannelClientStateRequest) (*types.QueryChannelClientStateResponse, error) { 136 if req == nil { 137 return nil, status.Error(codes.InvalidArgument, "empty request") 138 } 139 140 if err := validategRPCRequest(req.PortId, req.ChannelId); err != nil { 141 return nil, err 142 } 143 144 ctx := sdk.UnwrapSDKContext(c) 145 146 clientID, clientState, err := q.GetChannelClientState(ctx, req.PortId, req.ChannelId) 147 if err != nil { 148 return nil, status.Error(codes.NotFound, err.Error()) 149 } 150 151 identifiedClientState := clienttypes.NewIdentifiedClientState(clientID, clientState) 152 153 selfHeight := clienttypes.GetSelfHeight(ctx) 154 return types.NewQueryChannelClientStateResponse(identifiedClientState, nil, selfHeight), nil 155 } 156 157 // ChannelConsensusState implements the Query/ChannelConsensusState gRPC method 158 func (q Keeper) ChannelConsensusState(c context.Context, req *types.QueryChannelConsensusStateRequest) (*types.QueryChannelConsensusStateResponse, error) { 159 if req == nil { 160 return nil, status.Error(codes.InvalidArgument, "empty request") 161 } 162 163 if err := validategRPCRequest(req.PortId, req.ChannelId); err != nil { 164 return nil, err 165 } 166 167 ctx := sdk.UnwrapSDKContext(c) 168 169 channel, found := q.GetChannel(ctx, req.PortId, req.ChannelId) 170 if !found { 171 return nil, status.Error( 172 codes.NotFound, 173 sdkerrors.Wrapf(types.ErrChannelNotFound, "port-id: %s, channel-id %s", req.PortId, req.ChannelId).Error(), 174 ) 175 } 176 177 connection, found := q.connectionKeeper.GetConnection(ctx, channel.ConnectionHops[0]) 178 if !found { 179 return nil, status.Error( 180 codes.NotFound, 181 sdkerrors.Wrapf(connectiontypes.ErrConnectionNotFound, "connection-id: %s", channel.ConnectionHops[0]).Error(), 182 ) 183 } 184 185 consHeight := clienttypes.NewHeight(req.RevisionNumber, req.RevisionHeight) 186 consensusState, found := q.clientKeeper.GetClientConsensusState(ctx, connection.ClientId, consHeight) 187 if !found { 188 return nil, status.Error( 189 codes.NotFound, 190 sdkerrors.Wrapf(clienttypes.ErrConsensusStateNotFound, "client-id: %s", connection.ClientId).Error(), 191 ) 192 } 193 194 anyConsensusState, err := clienttypes.PackConsensusState(consensusState) 195 if err != nil { 196 return nil, status.Error(codes.Internal, err.Error()) 197 } 198 199 selfHeight := clienttypes.GetSelfHeight(ctx) 200 return types.NewQueryChannelConsensusStateResponse(connection.ClientId, anyConsensusState, consHeight, nil, selfHeight), nil 201 } 202 203 // PacketCommitment implements the Query/PacketCommitment gRPC method 204 func (q Keeper) PacketCommitment(c context.Context, req *types.QueryPacketCommitmentRequest) (*types.QueryPacketCommitmentResponse, error) { 205 if req == nil { 206 return nil, status.Error(codes.InvalidArgument, "empty request") 207 } 208 209 if err := validategRPCRequest(req.PortId, req.ChannelId); err != nil { 210 return nil, err 211 } 212 213 if req.Sequence == 0 { 214 return nil, status.Error(codes.InvalidArgument, "packet sequence cannot be 0") 215 } 216 217 ctx := sdk.UnwrapSDKContext(c) 218 219 commitmentBz := q.GetPacketCommitment(ctx, req.PortId, req.ChannelId, req.Sequence) 220 if len(commitmentBz) == 0 { 221 return nil, status.Error(codes.NotFound, "packet commitment hash not found") 222 } 223 224 selfHeight := clienttypes.GetSelfHeight(ctx) 225 return types.NewQueryPacketCommitmentResponse(commitmentBz, nil, selfHeight), nil 226 } 227 228 // PacketCommitments implements the Query/PacketCommitments gRPC method 229 func (q Keeper) PacketCommitments(c context.Context, req *types.QueryPacketCommitmentsRequest) (*types.QueryPacketCommitmentsResponse, error) { 230 if req == nil { 231 return nil, status.Error(codes.InvalidArgument, "empty request") 232 } 233 234 if err := validategRPCRequest(req.PortId, req.ChannelId); err != nil { 235 return nil, err 236 } 237 238 ctx := sdk.UnwrapSDKContext(c) 239 240 commitments := []*types.PacketState{} 241 store := prefix.NewStore(ctx.KVStore(q.storeKey), []byte(host.PacketCommitmentPrefixPath(req.PortId, req.ChannelId))) 242 243 pageRes, err := query.Paginate(store, req.Pagination, func(key, value []byte) error { 244 keySplit := strings.Split(string(key), "/") 245 246 sequence, err := strconv.ParseUint(keySplit[len(keySplit)-1], 10, 64) 247 if err != nil { 248 return err 249 } 250 251 commitment := types.NewPacketState(req.PortId, req.ChannelId, sequence, value) 252 commitments = append(commitments, &commitment) 253 return nil 254 }) 255 256 if err != nil { 257 return nil, err 258 } 259 260 selfHeight := clienttypes.GetSelfHeight(ctx) 261 return &types.QueryPacketCommitmentsResponse{ 262 Commitments: commitments, 263 Pagination: pageRes, 264 Height: selfHeight, 265 }, nil 266 } 267 268 // PacketReceipt implements the Query/PacketReceipt gRPC method 269 func (q Keeper) PacketReceipt(c context.Context, req *types.QueryPacketReceiptRequest) (*types.QueryPacketReceiptResponse, error) { 270 if req == nil { 271 return nil, status.Error(codes.InvalidArgument, "empty request") 272 } 273 274 if err := validategRPCRequest(req.PortId, req.ChannelId); err != nil { 275 return nil, err 276 } 277 278 if req.Sequence == 0 { 279 return nil, status.Error(codes.InvalidArgument, "packet sequence cannot be 0") 280 } 281 282 ctx := sdk.UnwrapSDKContext(c) 283 284 _, recvd := q.GetPacketReceipt(ctx, req.PortId, req.ChannelId, req.Sequence) 285 286 selfHeight := clienttypes.GetSelfHeight(ctx) 287 return types.NewQueryPacketReceiptResponse(recvd, nil, selfHeight), nil 288 } 289 290 // PacketAcknowledgement implements the Query/PacketAcknowledgement gRPC method 291 func (q Keeper) PacketAcknowledgement(c context.Context, req *types.QueryPacketAcknowledgementRequest) (*types.QueryPacketAcknowledgementResponse, error) { 292 if req == nil { 293 return nil, status.Error(codes.InvalidArgument, "empty request") 294 } 295 296 if err := validategRPCRequest(req.PortId, req.ChannelId); err != nil { 297 return nil, err 298 } 299 300 if req.Sequence == 0 { 301 return nil, status.Error(codes.InvalidArgument, "packet sequence cannot be 0") 302 } 303 304 ctx := sdk.UnwrapSDKContext(c) 305 306 acknowledgementBz, found := q.GetPacketAcknowledgement(ctx, req.PortId, req.ChannelId, req.Sequence) 307 if !found || len(acknowledgementBz) == 0 { 308 return nil, status.Error(codes.NotFound, "packet acknowledgement hash not found") 309 } 310 311 selfHeight := clienttypes.GetSelfHeight(ctx) 312 return types.NewQueryPacketAcknowledgementResponse(acknowledgementBz, nil, selfHeight), nil 313 } 314 315 // PacketAcknowledgements implements the Query/PacketAcknowledgements gRPC method 316 func (q Keeper) PacketAcknowledgements(c context.Context, req *types.QueryPacketAcknowledgementsRequest) (*types.QueryPacketAcknowledgementsResponse, error) { 317 if req == nil { 318 return nil, status.Error(codes.InvalidArgument, "empty request") 319 } 320 321 if err := validategRPCRequest(req.PortId, req.ChannelId); err != nil { 322 return nil, err 323 } 324 325 ctx := sdk.UnwrapSDKContext(c) 326 327 acks := []*types.PacketState{} 328 store := prefix.NewStore(ctx.KVStore(q.storeKey), []byte(host.PacketAcknowledgementPrefixPath(req.PortId, req.ChannelId))) 329 330 // if a list of packet sequences is provided then query for each specific ack and return a list <= len(req.PacketCommitmentSequences) 331 // otherwise, maintain previous behaviour and perform paginated query 332 for _, seq := range req.PacketCommitmentSequences { 333 acknowledgementBz, found := q.GetPacketAcknowledgement(ctx, req.PortId, req.ChannelId, seq) 334 if !found || len(acknowledgementBz) == 0 { 335 continue 336 } 337 338 ack := types.NewPacketState(req.PortId, req.ChannelId, seq, acknowledgementBz) 339 acks = append(acks, &ack) 340 } 341 342 if len(req.PacketCommitmentSequences) > 0 { 343 selfHeight := clienttypes.GetSelfHeight(ctx) 344 return &types.QueryPacketAcknowledgementsResponse{ 345 Acknowledgements: acks, 346 Pagination: nil, 347 Height: selfHeight, 348 }, nil 349 } 350 351 pageRes, err := query.Paginate(store, req.Pagination, func(key, value []byte) error { 352 keySplit := strings.Split(string(key), "/") 353 354 sequence, err := strconv.ParseUint(keySplit[len(keySplit)-1], 10, 64) 355 if err != nil { 356 return err 357 } 358 359 ack := types.NewPacketState(req.PortId, req.ChannelId, sequence, value) 360 acks = append(acks, &ack) 361 return nil 362 }) 363 364 if err != nil { 365 return nil, err 366 } 367 368 selfHeight := clienttypes.GetSelfHeight(ctx) 369 return &types.QueryPacketAcknowledgementsResponse{ 370 Acknowledgements: acks, 371 Pagination: pageRes, 372 Height: selfHeight, 373 }, nil 374 } 375 376 // UnreceivedPackets implements the Query/UnreceivedPackets gRPC method. Given 377 // a list of counterparty packet commitments, the querier checks if the packet 378 // has already been received by checking if a receipt exists on this 379 // chain for the packet sequence. All packets that haven't been received yet 380 // are returned in the response 381 // Usage: To use this method correctly, first query all packet commitments on 382 // the sending chain using the Query/PacketCommitments gRPC method. 383 // Then input the returned sequences into the QueryUnreceivedPacketsRequest 384 // and send the request to this Query/UnreceivedPackets on the **receiving** 385 // chain. This gRPC method will then return the list of packet sequences that 386 // are yet to be received on the receiving chain. 387 // 388 // NOTE: The querier makes the assumption that the provided list of packet 389 // commitments is correct and will not function properly if the list 390 // is not up to date. Ideally the query height should equal the latest height 391 // on the counterparty's client which represents this chain. 392 func (q Keeper) UnreceivedPackets(c context.Context, req *types.QueryUnreceivedPacketsRequest) (*types.QueryUnreceivedPacketsResponse, error) { 393 if req == nil { 394 return nil, status.Error(codes.InvalidArgument, "empty request") 395 } 396 397 if err := validategRPCRequest(req.PortId, req.ChannelId); err != nil { 398 return nil, err 399 } 400 401 ctx := sdk.UnwrapSDKContext(c) 402 403 channel, found := q.GetChannel(sdk.UnwrapSDKContext(c), req.PortId, req.ChannelId) 404 if !found { 405 return nil, status.Error( 406 codes.NotFound, 407 sdkerrors.Wrapf(types.ErrChannelNotFound, "port-id: %s, channel-id %s", req.PortId, req.ChannelId).Error(), 408 ) 409 } 410 411 var unreceivedSequences []uint64 412 switch channel.Ordering { 413 case types.UNORDERED: 414 for i, seq := range req.PacketCommitmentSequences { 415 // filter for invalid sequences to ensure they are not included in the response value. 416 if seq == 0 { 417 return nil, status.Errorf(codes.InvalidArgument, "packet sequence %d cannot be 0", i) 418 } 419 420 // if the packet receipt does not exist, then it is unreceived 421 if _, found := q.GetPacketReceipt(ctx, req.PortId, req.ChannelId, seq); !found { 422 unreceivedSequences = append(unreceivedSequences, seq) 423 } 424 } 425 case types.ORDERED: 426 nextSequenceRecv, found := q.GetNextSequenceRecv(ctx, req.PortId, req.ChannelId) 427 if !found { 428 return nil, status.Error( 429 codes.NotFound, 430 sdkerrors.Wrapf( 431 types.ErrSequenceReceiveNotFound, 432 "destination port: %s, destination channel: %s", req.PortId, req.ChannelId, 433 ).Error(), 434 ) 435 } 436 437 for i, seq := range req.PacketCommitmentSequences { 438 // filter for invalid sequences to ensure they are not included in the response value. 439 if seq == 0 { 440 return nil, status.Errorf(codes.InvalidArgument, "packet sequence %d cannot be 0", i) 441 } 442 443 // Any sequence greater than or equal to the next sequence to be received is not received. 444 if seq >= nextSequenceRecv { 445 unreceivedSequences = append(unreceivedSequences, seq) 446 } 447 } 448 default: 449 return nil, status.Error( 450 codes.InvalidArgument, 451 sdkerrors.Wrapf(types.ErrInvalidChannelOrdering, "channel order %s is not supported", channel.Ordering.String()).Error()) 452 } 453 454 selfHeight := clienttypes.GetSelfHeight(ctx) 455 return &types.QueryUnreceivedPacketsResponse{ 456 Sequences: unreceivedSequences, 457 Height: selfHeight, 458 }, nil 459 } 460 461 // UnreceivedAcks implements the Query/UnreceivedAcks gRPC method. Given 462 // a list of counterparty packet acknowledgements, the querier checks if the packet 463 // has already been received by checking if the packet commitment still exists on this 464 // chain (original sender) for the packet sequence. 465 // All acknowledgmeents that haven't been received yet are returned in the response. 466 // Usage: To use this method correctly, first query all packet acknowledgements on 467 // the original receiving chain (ie the chain that wrote the acks) using the Query/PacketAcknowledgements gRPC method. 468 // Then input the returned sequences into the QueryUnreceivedAcksRequest 469 // and send the request to this Query/UnreceivedAcks on the **original sending** 470 // chain. This gRPC method will then return the list of packet sequences whose 471 // acknowledgements are already written on the receiving chain but haven't yet 472 // been received back to the sending chain. 473 // 474 // NOTE: The querier makes the assumption that the provided list of packet 475 // acknowledgements is correct and will not function properly if the list 476 // is not up to date. Ideally the query height should equal the latest height 477 // on the counterparty's client which represents this chain. 478 func (q Keeper) UnreceivedAcks(c context.Context, req *types.QueryUnreceivedAcksRequest) (*types.QueryUnreceivedAcksResponse, error) { 479 if req == nil { 480 return nil, status.Error(codes.InvalidArgument, "empty request") 481 } 482 483 if err := validategRPCRequest(req.PortId, req.ChannelId); err != nil { 484 return nil, err 485 } 486 487 ctx := sdk.UnwrapSDKContext(c) 488 489 var unreceivedSequences = []uint64{} 490 491 for i, seq := range req.PacketAckSequences { 492 if seq == 0 { 493 return nil, status.Errorf(codes.InvalidArgument, "packet sequence %d cannot be 0", i) 494 } 495 496 // if packet commitment still exists on the original sending chain, then packet ack has not been received 497 // since processing the ack will delete the packet commitment 498 if commitment := q.GetPacketCommitment(ctx, req.PortId, req.ChannelId, seq); len(commitment) != 0 { 499 unreceivedSequences = append(unreceivedSequences, seq) 500 } 501 502 } 503 504 selfHeight := clienttypes.GetSelfHeight(ctx) 505 return &types.QueryUnreceivedAcksResponse{ 506 Sequences: unreceivedSequences, 507 Height: selfHeight, 508 }, nil 509 } 510 511 // NextSequenceReceive implements the Query/NextSequenceReceive gRPC method 512 func (q Keeper) NextSequenceReceive(c context.Context, req *types.QueryNextSequenceReceiveRequest) (*types.QueryNextSequenceReceiveResponse, error) { 513 if req == nil { 514 return nil, status.Error(codes.InvalidArgument, "empty request") 515 } 516 517 if err := validategRPCRequest(req.PortId, req.ChannelId); err != nil { 518 return nil, err 519 } 520 521 ctx := sdk.UnwrapSDKContext(c) 522 sequence, found := q.GetNextSequenceRecv(ctx, req.PortId, req.ChannelId) 523 if !found { 524 return nil, status.Error( 525 codes.NotFound, 526 sdkerrors.Wrapf(types.ErrSequenceReceiveNotFound, "port-id: %s, channel-id %s", req.PortId, req.ChannelId).Error(), 527 ) 528 } 529 530 selfHeight := clienttypes.GetSelfHeight(ctx) 531 return types.NewQueryNextSequenceReceiveResponse(sequence, nil, selfHeight), nil 532 } 533 534 func validategRPCRequest(portID, channelID string) error { 535 if err := host.PortIdentifierValidator(portID); err != nil { 536 return status.Error(codes.InvalidArgument, err.Error()) 537 } 538 539 if err := host.ChannelIdentifierValidator(channelID); err != nil { 540 return status.Error(codes.InvalidArgument, err.Error()) 541 } 542 543 return nil 544 }