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 }