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  }