github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/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/fibonacci-chain/fbc/libs/cosmos-sdk/store/prefix" 9 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 10 sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors" 11 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/query" 12 clienttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/types" 13 connectiontypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/03-connection/types" 14 "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/04-channel/types" 15 host "github.com/fibonacci-chain/fbc/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 var unreceivedSequences = []uint64{} 404 405 for i, seq := range req.PacketCommitmentSequences { 406 if seq == 0 { 407 return nil, status.Errorf(codes.InvalidArgument, "packet sequence %d cannot be 0", i) 408 } 409 410 // if packet receipt exists on the receiving chain, then packet has already been received 411 if _, found := q.GetPacketReceipt(ctx, req.PortId, req.ChannelId, seq); !found { 412 unreceivedSequences = append(unreceivedSequences, seq) 413 } 414 415 } 416 417 selfHeight := clienttypes.GetSelfHeight(ctx) 418 return &types.QueryUnreceivedPacketsResponse{ 419 Sequences: unreceivedSequences, 420 Height: selfHeight, 421 }, nil 422 } 423 424 // UnreceivedAcks implements the Query/UnreceivedAcks gRPC method. Given 425 // a list of counterparty packet acknowledgements, the querier checks if the packet 426 // has already been received by checking if the packet commitment still exists on this 427 // chain (original sender) for the packet sequence. 428 // All acknowledgmeents that haven't been received yet are returned in the response. 429 // Usage: To use this method correctly, first query all packet acknowledgements on 430 // the original receiving chain (ie the chain that wrote the acks) using the Query/PacketAcknowledgements gRPC method. 431 // Then input the returned sequences into the QueryUnreceivedAcksRequest 432 // and send the request to this Query/UnreceivedAcks on the **original sending** 433 // chain. This gRPC method will then return the list of packet sequences whose 434 // acknowledgements are already written on the receiving chain but haven't yet 435 // been received back to the sending chain. 436 // 437 // NOTE: The querier makes the assumption that the provided list of packet 438 // acknowledgements is correct and will not function properly if the list 439 // is not up to date. Ideally the query height should equal the latest height 440 // on the counterparty's client which represents this chain. 441 func (q Keeper) UnreceivedAcks(c context.Context, req *types.QueryUnreceivedAcksRequest) (*types.QueryUnreceivedAcksResponse, error) { 442 if req == nil { 443 return nil, status.Error(codes.InvalidArgument, "empty request") 444 } 445 446 if err := validategRPCRequest(req.PortId, req.ChannelId); err != nil { 447 return nil, err 448 } 449 450 ctx := sdk.UnwrapSDKContext(c) 451 452 var unreceivedSequences = []uint64{} 453 454 for i, seq := range req.PacketAckSequences { 455 if seq == 0 { 456 return nil, status.Errorf(codes.InvalidArgument, "packet sequence %d cannot be 0", i) 457 } 458 459 // if packet commitment still exists on the original sending chain, then packet ack has not been received 460 // since processing the ack will delete the packet commitment 461 if commitment := q.GetPacketCommitment(ctx, req.PortId, req.ChannelId, seq); len(commitment) != 0 { 462 unreceivedSequences = append(unreceivedSequences, seq) 463 } 464 465 } 466 467 selfHeight := clienttypes.GetSelfHeight(ctx) 468 return &types.QueryUnreceivedAcksResponse{ 469 Sequences: unreceivedSequences, 470 Height: selfHeight, 471 }, nil 472 } 473 474 // NextSequenceReceive implements the Query/NextSequenceReceive gRPC method 475 func (q Keeper) NextSequenceReceive(c context.Context, req *types.QueryNextSequenceReceiveRequest) (*types.QueryNextSequenceReceiveResponse, error) { 476 if req == nil { 477 return nil, status.Error(codes.InvalidArgument, "empty request") 478 } 479 480 if err := validategRPCRequest(req.PortId, req.ChannelId); err != nil { 481 return nil, err 482 } 483 484 ctx := sdk.UnwrapSDKContext(c) 485 sequence, found := q.GetNextSequenceRecv(ctx, req.PortId, req.ChannelId) 486 if !found { 487 return nil, status.Error( 488 codes.NotFound, 489 sdkerrors.Wrapf(types.ErrSequenceReceiveNotFound, "port-id: %s, channel-id %s", req.PortId, req.ChannelId).Error(), 490 ) 491 } 492 493 selfHeight := clienttypes.GetSelfHeight(ctx) 494 return types.NewQueryNextSequenceReceiveResponse(sequence, nil, selfHeight), nil 495 } 496 497 func validategRPCRequest(portID, channelID string) error { 498 if err := host.PortIdentifierValidator(portID); err != nil { 499 return status.Error(codes.InvalidArgument, err.Error()) 500 } 501 502 if err := host.ChannelIdentifierValidator(channelID); err != nil { 503 return status.Error(codes.InvalidArgument, err.Error()) 504 } 505 506 return nil 507 }