github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/ibc-go/modules/core/03-connection/client/utils/utils.go (about)

     1  package utils
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io/ioutil"
     7  
     8  	clictx "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client/context"
     9  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec"
    10  	sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors"
    11  	"github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/client/utils"
    12  	clienttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/types"
    13  	"github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/03-connection/types"
    14  	commitmenttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/23-commitment/types"
    15  	host "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/24-host"
    16  	ibcclient "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/client"
    17  	"github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/exported"
    18  
    19  	"github.com/pkg/errors"
    20  )
    21  
    22  // QueryConnection returns a connection end.
    23  // If prove is true, it performs an ABCI store query in order to retrieve the merkle proof. Otherwise,
    24  // it uses the gRPC query client.
    25  func QueryConnection(
    26  	clientCtx clictx.CLIContext, connectionID string, prove bool,
    27  ) (*types.QueryConnectionResponse, error) {
    28  	if prove {
    29  		return queryConnectionABCI(clientCtx, connectionID)
    30  	}
    31  	queryClient := types.NewQueryClient(clientCtx)
    32  	req := &types.QueryConnectionRequest{
    33  		ConnectionId: connectionID,
    34  	}
    35  
    36  	return queryClient.Connection(context.Background(), req)
    37  }
    38  
    39  func queryConnectionABCI(clientCtx clictx.CLIContext, connectionID string) (*types.QueryConnectionResponse, error) {
    40  	key := host.ConnectionKey(connectionID)
    41  
    42  	value, proofBz, proofHeight, err := ibcclient.QueryTendermintProof(clientCtx, key)
    43  	if err != nil {
    44  		return nil, err
    45  	}
    46  
    47  	// check if connection exists
    48  	if len(value) == 0 {
    49  		return nil, sdkerrors.Wrap(types.ErrConnectionNotFound, connectionID)
    50  	}
    51  
    52  	cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry)
    53  
    54  	var connection types.ConnectionEnd
    55  	if err := cdc.UnmarshalBinaryBare(value, &connection); err != nil {
    56  		return nil, err
    57  	}
    58  
    59  	return types.NewQueryConnectionResponse(connection, proofBz, proofHeight), nil
    60  }
    61  
    62  // QueryClientConnections queries the connection paths registered for a particular client.
    63  // If prove is true, it performs an ABCI store query in order to retrieve the merkle proof. Otherwise,
    64  // it uses the gRPC query client.
    65  func QueryClientConnections(
    66  	clientCtx clictx.CLIContext, clientID string, prove bool,
    67  ) (*types.QueryClientConnectionsResponse, error) {
    68  	if prove {
    69  		return queryClientConnectionsABCI(clientCtx, clientID)
    70  	}
    71  
    72  	queryClient := types.NewQueryClient(clientCtx)
    73  	req := &types.QueryClientConnectionsRequest{
    74  		ClientId: clientID,
    75  	}
    76  
    77  	return queryClient.ClientConnections(context.Background(), req)
    78  }
    79  
    80  func queryClientConnectionsABCI(clientCtx clictx.CLIContext, clientID string) (*types.QueryClientConnectionsResponse, error) {
    81  	key := host.ClientConnectionsKey(clientID)
    82  
    83  	value, proofBz, proofHeight, err := ibcclient.QueryTendermintProof(clientCtx, key)
    84  	if err != nil {
    85  		return nil, err
    86  	}
    87  
    88  	// check if connection paths exist
    89  	if len(value) == 0 {
    90  		return nil, sdkerrors.Wrap(types.ErrClientConnectionPathsNotFound, clientID)
    91  	}
    92  
    93  	var paths []string
    94  	if err := clientCtx.CodecProy.GetCdc().UnmarshalBinaryBare(value, &paths); err != nil {
    95  		return nil, err
    96  	}
    97  
    98  	return types.NewQueryClientConnectionsResponse(paths, proofBz, proofHeight), nil
    99  }
   100  
   101  // QueryConnectionClientState returns the ClientState of a connection end. If
   102  // prove is true, it performs an ABCI store query in order to retrieve the
   103  // merkle proof. Otherwise, it uses the gRPC query client.
   104  func QueryConnectionClientState(
   105  	clientCtx clictx.CLIContext, connectionID string, prove bool,
   106  ) (*types.QueryConnectionClientStateResponse, error) {
   107  
   108  	queryClient := types.NewQueryClient(clientCtx)
   109  	req := &types.QueryConnectionClientStateRequest{
   110  		ConnectionId: connectionID,
   111  	}
   112  
   113  	res, err := queryClient.ConnectionClientState(context.Background(), req)
   114  	if err != nil {
   115  		return nil, err
   116  	}
   117  
   118  	if prove {
   119  		clientStateRes, err := utils.QueryClientStateABCI(clientCtx, res.IdentifiedClientState.ClientId)
   120  		if err != nil {
   121  			return nil, err
   122  		}
   123  
   124  		// use client state returned from ABCI query in case query height differs
   125  		identifiedClientState := clienttypes.IdentifiedClientState{
   126  			ClientId:    res.IdentifiedClientState.ClientId,
   127  			ClientState: clientStateRes.ClientState,
   128  		}
   129  
   130  		res = types.NewQueryConnectionClientStateResponse(identifiedClientState, clientStateRes.Proof, clientStateRes.ProofHeight)
   131  	}
   132  
   133  	return res, nil
   134  }
   135  
   136  // QueryConnectionConsensusState returns the ConsensusState of a connection end. If
   137  // prove is true, it performs an ABCI store query in order to retrieve the
   138  // merkle proof. Otherwise, it uses the gRPC query client.
   139  func QueryConnectionConsensusState(
   140  	clientCtx clictx.CLIContext, connectionID string, height clienttypes.Height, prove bool,
   141  ) (*types.QueryConnectionConsensusStateResponse, error) {
   142  
   143  	queryClient := types.NewQueryClient(clientCtx)
   144  	req := &types.QueryConnectionConsensusStateRequest{
   145  		ConnectionId:   connectionID,
   146  		RevisionNumber: height.RevisionNumber,
   147  		RevisionHeight: height.RevisionHeight,
   148  	}
   149  
   150  	res, err := queryClient.ConnectionConsensusState(context.Background(), req)
   151  	if err != nil {
   152  		return nil, err
   153  	}
   154  
   155  	if prove {
   156  		consensusStateRes, err := utils.QueryConsensusStateABCI(clientCtx, res.ClientId, height)
   157  		if err != nil {
   158  			return nil, err
   159  		}
   160  
   161  		res = types.NewQueryConnectionConsensusStateResponse(res.ClientId, consensusStateRes.ConsensusState, height, consensusStateRes.Proof, consensusStateRes.ProofHeight)
   162  	}
   163  
   164  	return res, nil
   165  }
   166  
   167  // ParseClientState unmarshals a cmd input argument from a JSON string to a client state
   168  // If the input is not a JSON, it looks for a path to the JSON file
   169  func ParseClientState(cdc *codec.CodecProxy, arg string) (exported.ClientState, error) {
   170  	var clientState exported.ClientState
   171  	if err := cdc.GetCdc().UnmarshalJSON([]byte(arg), &clientState); err != nil {
   172  		// check for file path if JSON input is not provided
   173  		contents, err := ioutil.ReadFile(arg)
   174  		if err != nil {
   175  			return nil, errors.New("either JSON input nor path to .json file were provided")
   176  		}
   177  		if err := cdc.GetCdc().UnmarshalJSON(contents, &clientState); err != nil {
   178  			return nil, errors.Wrap(err, "error unmarshalling client state")
   179  		}
   180  	}
   181  	return clientState, nil
   182  }
   183  
   184  // ParsePrefix unmarshals an cmd input argument from a JSON string to a commitment
   185  // Prefix. If the input is not a JSON, it looks for a path to the JSON file.
   186  func ParsePrefix(cdc *codec.CodecProxy, arg string) (commitmenttypes.MerklePrefix, error) {
   187  	var prefix commitmenttypes.MerklePrefix
   188  	if err := cdc.GetCdc().UnmarshalJSON([]byte(arg), &prefix); err != nil {
   189  		// check for file path if JSON input is not provided
   190  		contents, err := ioutil.ReadFile(arg)
   191  		if err != nil {
   192  			return commitmenttypes.MerklePrefix{}, errors.New("neither JSON input nor path to .json file were provided")
   193  		}
   194  		if err := cdc.GetCdc().UnmarshalJSON(contents, &prefix); err != nil {
   195  			return commitmenttypes.MerklePrefix{}, errors.Wrap(err, "error unmarshalling commitment prefix")
   196  		}
   197  	}
   198  	return prefix, nil
   199  }
   200  
   201  // ParseProof unmarshals a cmd input argument from a JSON string to a commitment
   202  // Proof. If the input is not a JSON, it looks for a path to the JSON file. It
   203  // then marshals the commitment proof into a proto encoded byte array.
   204  func ParseProof(cdc *codec.CodecProxy, arg string) ([]byte, error) {
   205  	var merkleProof commitmenttypes.MerkleProof
   206  	if err := cdc.GetCdc().UnmarshalJSON([]byte(arg), &merkleProof); err != nil {
   207  		// check for file path if JSON input is not provided
   208  		contents, err := ioutil.ReadFile(arg)
   209  		if err != nil {
   210  			return nil, errors.New("neither JSON input nor path to .json file were provided")
   211  		}
   212  		if err := cdc.GetCdc().UnmarshalJSON(contents, &merkleProof); err != nil {
   213  			return nil, fmt.Errorf("error unmarshalling commitment proof: %w", err)
   214  		}
   215  	}
   216  
   217  	return cdc.GetCdc().MarshalJSON(&merkleProof)
   218  }