github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/ibc-go/modules/core/04-channel/client/utils/utils.go (about) 1 package utils 2 3 // 4 import ( 5 "context" 6 "encoding/binary" 7 8 clictx "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client/context" 9 sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors" 10 "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/client/utils" 11 clienttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/types" 12 "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/04-channel/types" 13 host "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/24-host" 14 ibcclient "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/client" 15 "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/exported" 16 ) 17 18 // QueryChannel returns a channel end. 19 // If prove is true, it performs an ABCI store query in order to retrieve the merkle proof. Otherwise, 20 // it uses the gRPC query client. 21 func QueryChannel( 22 clientCtx clictx.CLIContext, portID, channelID string, prove bool, 23 ) (*types.QueryChannelResponse, error) { 24 if prove { 25 return queryChannelABCI(clientCtx, portID, channelID) 26 } 27 28 queryClient := types.NewQueryClient(clientCtx) 29 req := &types.QueryChannelRequest{ 30 PortId: portID, 31 ChannelId: channelID, 32 } 33 34 return queryClient.Channel(context.Background(), req) 35 } 36 37 func queryChannelABCI(clientCtx clictx.CLIContext, portID, channelID string) (*types.QueryChannelResponse, error) { 38 key := host.ChannelKey(portID, channelID) 39 40 value, proofBz, proofHeight, err := ibcclient.QueryTendermintProof(clientCtx, key) 41 if err != nil { 42 return nil, err 43 } 44 45 // check if channel exists 46 if len(value) == 0 { 47 return nil, sdkerrors.Wrapf(types.ErrChannelNotFound, "portID (%s), channelID (%s)", portID, channelID) 48 } 49 50 cdc := clientCtx.Codec 51 52 var channel types.Channel 53 if err := cdc.UnmarshalBinaryBare(value, &channel); err != nil { 54 return nil, err 55 } 56 57 return types.NewQueryChannelResponse(channel, proofBz, proofHeight), nil 58 } 59 60 // QueryChannelClientState returns the ClientState of a channel end. If 61 // prove is true, it performs an ABCI store query in order to retrieve the 62 // merkle proof. Otherwise, it uses the gRPC query client. 63 func QueryChannelClientState( 64 clientCtx clictx.CLIContext, portID, channelID string, prove bool, 65 ) (*types.QueryChannelClientStateResponse, error) { 66 67 queryClient := types.NewQueryClient(clientCtx) 68 req := &types.QueryChannelClientStateRequest{ 69 PortId: portID, 70 ChannelId: channelID, 71 } 72 73 res, err := queryClient.ChannelClientState(context.Background(), req) 74 if err != nil { 75 return nil, err 76 } 77 78 if prove { 79 clientStateRes, err := utils.QueryClientStateABCI(clientCtx, res.IdentifiedClientState.ClientId) 80 if err != nil { 81 return nil, err 82 } 83 84 // use client state returned from ABCI query in case query height differs 85 identifiedClientState := clienttypes.IdentifiedClientState{ 86 ClientId: res.IdentifiedClientState.ClientId, 87 ClientState: clientStateRes.ClientState, 88 } 89 res = types.NewQueryChannelClientStateResponse(identifiedClientState, clientStateRes.Proof, clientStateRes.ProofHeight) 90 } 91 92 return res, nil 93 } 94 95 // QueryChannelConsensusState returns the ConsensusState of a channel end. If 96 // prove is true, it performs an ABCI store query in order to retrieve the 97 // merkle proof. Otherwise, it uses the gRPC query client. 98 func QueryChannelConsensusState( 99 clientCtx clictx.CLIContext, portID, channelID string, height clienttypes.Height, prove bool, 100 ) (*types.QueryChannelConsensusStateResponse, error) { 101 102 queryClient := types.NewQueryClient(clientCtx) 103 req := &types.QueryChannelConsensusStateRequest{ 104 PortId: portID, 105 ChannelId: channelID, 106 RevisionNumber: height.RevisionNumber, 107 RevisionHeight: height.RevisionHeight, 108 } 109 110 res, err := queryClient.ChannelConsensusState(context.Background(), req) 111 if err != nil { 112 return nil, err 113 } 114 115 if prove { 116 consensusStateRes, err := utils.QueryConsensusStateABCI(clientCtx, res.ClientId, height) 117 if err != nil { 118 return nil, err 119 } 120 121 res = types.NewQueryChannelConsensusStateResponse(res.ClientId, consensusStateRes.ConsensusState, height, consensusStateRes.Proof, consensusStateRes.ProofHeight) 122 } 123 124 return res, nil 125 } 126 127 // QueryLatestConsensusState uses the channel Querier to return the 128 // latest ConsensusState given the source port ID and source channel ID. 129 func QueryLatestConsensusState( 130 clientCtx clictx.CLIContext, portID, channelID string, 131 ) (exported.ConsensusState, clienttypes.Height, clienttypes.Height, error) { 132 clientRes, err := QueryChannelClientState(clientCtx, portID, channelID, false) 133 if err != nil { 134 return nil, clienttypes.Height{}, clienttypes.Height{}, err 135 } 136 137 var clientState exported.ClientState 138 if err := clientCtx.InterfaceRegistry.UnpackAny(clientRes.IdentifiedClientState.ClientState, &clientState); err != nil { 139 return nil, clienttypes.Height{}, clienttypes.Height{}, err 140 } 141 142 clientHeight, ok := clientState.GetLatestHeight().(clienttypes.Height) 143 if !ok { 144 return nil, clienttypes.Height{}, clienttypes.Height{}, sdkerrors.Wrapf(sdkerrors.ErrInvalidHeight, "invalid height type. expected type: %T, got: %T", 145 clienttypes.Height{}, clientHeight) 146 } 147 res, err := QueryChannelConsensusState(clientCtx, portID, channelID, clientHeight, false) 148 if err != nil { 149 return nil, clienttypes.Height{}, clienttypes.Height{}, err 150 } 151 152 var consensusState exported.ConsensusState 153 if err := clientCtx.InterfaceRegistry.UnpackAny(res.ConsensusState, &consensusState); err != nil { 154 return nil, clienttypes.Height{}, clienttypes.Height{}, err 155 } 156 157 return consensusState, clientHeight, res.ProofHeight, nil 158 } 159 160 // QueryNextSequenceReceive returns the next sequence receive. 161 // If prove is true, it performs an ABCI store query in order to retrieve the merkle proof. Otherwise, 162 // it uses the gRPC query client. 163 func QueryNextSequenceReceive( 164 clientCtx clictx.CLIContext, portID, channelID string, prove bool, 165 ) (*types.QueryNextSequenceReceiveResponse, error) { 166 if prove { 167 return queryNextSequenceRecvABCI(clientCtx, portID, channelID) 168 } 169 170 queryClient := types.NewQueryClient(clientCtx) 171 req := &types.QueryNextSequenceReceiveRequest{ 172 PortId: portID, 173 ChannelId: channelID, 174 } 175 176 return queryClient.NextSequenceReceive(context.Background(), req) 177 } 178 179 func queryNextSequenceRecvABCI(clientCtx clictx.CLIContext, portID, channelID string) (*types.QueryNextSequenceReceiveResponse, error) { 180 key := host.NextSequenceRecvKey(portID, channelID) 181 182 value, proofBz, proofHeight, err := ibcclient.QueryTendermintProof(clientCtx, key) 183 if err != nil { 184 return nil, err 185 } 186 187 // check if next sequence receive exists 188 if len(value) == 0 { 189 return nil, sdkerrors.Wrapf(types.ErrChannelNotFound, "portID (%s), channelID (%s)", portID, channelID) 190 } 191 192 sequence := binary.BigEndian.Uint64(value) 193 194 return types.NewQueryNextSequenceReceiveResponse(sequence, proofBz, proofHeight), nil 195 } 196 197 // QueryPacketCommitment returns a packet commitment. 198 // If prove is true, it performs an ABCI store query in order to retrieve the merkle proof. Otherwise, 199 // it uses the gRPC query client. 200 func QueryPacketCommitment( 201 clientCtx clictx.CLIContext, portID, channelID string, 202 sequence uint64, prove bool, 203 ) (*types.QueryPacketCommitmentResponse, error) { 204 if prove { 205 return queryPacketCommitmentABCI(clientCtx, portID, channelID, sequence) 206 } 207 208 queryClient := types.NewQueryClient(clientCtx) 209 req := &types.QueryPacketCommitmentRequest{ 210 PortId: portID, 211 ChannelId: channelID, 212 Sequence: sequence, 213 } 214 215 return queryClient.PacketCommitment(context.Background(), req) 216 } 217 218 func queryPacketCommitmentABCI( 219 clientCtx clictx.CLIContext, portID, channelID string, sequence uint64, 220 ) (*types.QueryPacketCommitmentResponse, error) { 221 key := host.PacketCommitmentKey(portID, channelID, sequence) 222 223 value, proofBz, proofHeight, err := ibcclient.QueryTendermintProof(clientCtx, key) 224 if err != nil { 225 return nil, err 226 } 227 228 // check if packet commitment exists 229 if len(value) == 0 { 230 return nil, sdkerrors.Wrapf(types.ErrPacketCommitmentNotFound, "portID (%s), channelID (%s), sequence (%d)", portID, channelID, sequence) 231 } 232 233 return types.NewQueryPacketCommitmentResponse(value, proofBz, proofHeight), nil 234 } 235 236 // QueryPacketReceipt returns data about a packet receipt. 237 // If prove is true, it performs an ABCI store query in order to retrieve the merkle proof. Otherwise, 238 // it uses the gRPC query client. 239 func QueryPacketReceipt( 240 clientCtx clictx.CLIContext, portID, channelID string, 241 sequence uint64, prove bool, 242 ) (*types.QueryPacketReceiptResponse, error) { 243 if prove { 244 return queryPacketReceiptABCI(clientCtx, portID, channelID, sequence) 245 } 246 247 queryClient := types.NewQueryClient(clientCtx) 248 req := &types.QueryPacketReceiptRequest{ 249 PortId: portID, 250 ChannelId: channelID, 251 Sequence: sequence, 252 } 253 254 return queryClient.PacketReceipt(context.Background(), req) 255 } 256 257 func queryPacketReceiptABCI( 258 clientCtx clictx.CLIContext, portID, channelID string, sequence uint64, 259 ) (*types.QueryPacketReceiptResponse, error) { 260 key := host.PacketReceiptKey(portID, channelID, sequence) 261 262 value, proofBz, proofHeight, err := ibcclient.QueryTendermintProof(clientCtx, key) 263 if err != nil { 264 return nil, err 265 } 266 267 return types.NewQueryPacketReceiptResponse(value != nil, proofBz, proofHeight), nil 268 } 269 270 // QueryPacketAcknowledgement returns the data about a packet acknowledgement. 271 // If prove is true, it performs an ABCI store query in order to retrieve the merkle proof. Otherwise, 272 // it uses the gRPC query client 273 func QueryPacketAcknowledgement(clientCtx clictx.CLIContext, portID, channelID string, sequence uint64, prove bool) (*types.QueryPacketAcknowledgementResponse, error) { 274 if prove { 275 return queryPacketAcknowledgementABCI(clientCtx, portID, channelID, sequence) 276 } 277 278 queryClient := types.NewQueryClient(clientCtx) 279 req := &types.QueryPacketAcknowledgementRequest{ 280 PortId: portID, 281 ChannelId: channelID, 282 Sequence: sequence, 283 } 284 285 return queryClient.PacketAcknowledgement(context.Background(), req) 286 } 287 288 func queryPacketAcknowledgementABCI(clientCtx clictx.CLIContext, portID, channelID string, sequence uint64) (*types.QueryPacketAcknowledgementResponse, error) { 289 key := host.PacketAcknowledgementKey(portID, channelID, sequence) 290 291 value, proofBz, proofHeight, err := ibcclient.QueryTendermintProof(clientCtx, key) 292 if err != nil { 293 return nil, err 294 } 295 296 if len(value) == 0 { 297 return nil, sdkerrors.Wrapf(types.ErrInvalidAcknowledgement, "portID (%s), channelID (%s), sequence (%d)", portID, channelID, sequence) 298 } 299 300 return types.NewQueryPacketAcknowledgementResponse(value, proofBz, proofHeight), nil 301 }