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

     1  package utils
     2  
     3  import (
     4  	"context"
     5  
     6  	clictx "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client/context"
     7  	sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors"
     8  	"github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/types"
     9  	commitmenttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/23-commitment/types"
    10  	host "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/24-host"
    11  	ibcclient "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/client"
    12  	"github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/exported"
    13  	ibctmtypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/light-clients/07-tendermint/types"
    14  	tmtypes "github.com/fibonacci-chain/fbc/libs/tendermint/types"
    15  )
    16  
    17  // QueryClientState returns a client state. If prove is true, it performs an ABCI store query
    18  // in order to retrieve the merkle proof. Otherwise, it uses the gRPC query client.
    19  func QueryClientState(
    20  	clientCtx clictx.CLIContext, clientID string, prove bool,
    21  ) (*types.QueryClientStateResponse, error) {
    22  	if prove {
    23  		return QueryClientStateABCI(clientCtx, clientID)
    24  	}
    25  
    26  	queryClient := types.NewQueryClient(clientCtx)
    27  	req := &types.QueryClientStateRequest{
    28  		ClientId: clientID,
    29  	}
    30  
    31  	return queryClient.ClientState(context.Background(), req)
    32  }
    33  
    34  // QueryClientStateABCI queries the store to get the light client state and a merkle proof.
    35  func QueryClientStateABCI(
    36  	clientCtx clictx.CLIContext, clientID string,
    37  ) (*types.QueryClientStateResponse, error) {
    38  	key := host.FullClientStateKey(clientID)
    39  
    40  	value, proofBz, proofHeight, err := ibcclient.QueryTendermintProof(clientCtx, key)
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  
    45  	// check if client exists
    46  	if len(value) == 0 {
    47  		return nil, sdkerrors.Wrap(types.ErrClientNotFound, clientID)
    48  	}
    49  
    50  	cdc := clientCtx.CodecProy
    51  
    52  	clientState, err := types.UnmarshalClientState(cdc, value)
    53  	if err != nil {
    54  		return nil, err
    55  	}
    56  
    57  	anyClientState, err := types.PackClientState(clientState)
    58  	if err != nil {
    59  		return nil, err
    60  	}
    61  
    62  	clientStateRes := types.NewQueryClientStateResponse(anyClientState, proofBz, proofHeight)
    63  	return clientStateRes, nil
    64  }
    65  
    66  // QueryConsensusState returns a consensus state. If prove is true, it performs an ABCI store
    67  // query in order to retrieve the merkle proof. Otherwise, it uses the gRPC query client.
    68  func QueryConsensusState(
    69  	clientCtx clictx.CLIContext, clientID string, height exported.Height, prove, latestHeight bool,
    70  ) (*types.QueryConsensusStateResponse, error) {
    71  	if prove {
    72  		return QueryConsensusStateABCI(clientCtx, clientID, height)
    73  	}
    74  
    75  	queryClient := types.NewQueryClient(clientCtx)
    76  	req := &types.QueryConsensusStateRequest{
    77  		ClientId:       clientID,
    78  		RevisionNumber: height.GetRevisionNumber(),
    79  		RevisionHeight: height.GetRevisionHeight(),
    80  		LatestHeight:   latestHeight,
    81  	}
    82  
    83  	return queryClient.ConsensusState(context.Background(), req)
    84  }
    85  
    86  // QueryConsensusStateABCI queries the store to get the consensus state of a light client and a
    87  // merkle proof of its existence or non-existence.
    88  func QueryConsensusStateABCI(
    89  	clientCtx clictx.CLIContext, clientID string, height exported.Height,
    90  ) (*types.QueryConsensusStateResponse, error) {
    91  	key := host.FullConsensusStateKey(clientID, height)
    92  	value, proofBz, proofHeight, err := ibcclient.QueryTendermintProof(clientCtx, key)
    93  	if err != nil {
    94  		return nil, err
    95  	}
    96  
    97  	// check if consensus state exists
    98  	if len(value) == 0 {
    99  		return nil, sdkerrors.Wrap(types.ErrConsensusStateNotFound, clientID)
   100  	}
   101  
   102  	cdc := clientCtx.CodecProy
   103  
   104  	cs, err := types.UnmarshalConsensusState(cdc, value)
   105  	if err != nil {
   106  		return nil, err
   107  	}
   108  
   109  	anyConsensusState, err := types.PackConsensusState(cs)
   110  	if err != nil {
   111  		return nil, err
   112  	}
   113  
   114  	return types.NewQueryConsensusStateResponse(anyConsensusState, proofBz, proofHeight), nil
   115  }
   116  
   117  // QueryTendermintHeader takes a client context and returns the appropriate
   118  // tendermint header
   119  func QueryTendermintHeader(clientCtx clictx.CLIContext) (ibctmtypes.Header, int64, error) {
   120  	node, err := clientCtx.GetNode()
   121  	if err != nil {
   122  		return ibctmtypes.Header{}, 0, err
   123  	}
   124  
   125  	info, err := node.ABCIInfo()
   126  	if err != nil {
   127  		return ibctmtypes.Header{}, 0, err
   128  	}
   129  
   130  	var height int64
   131  	if clientCtx.Height != 0 {
   132  		height = clientCtx.Height
   133  	} else {
   134  		height = info.Response.LastBlockHeight
   135  	}
   136  
   137  	commit, err := node.Commit(&height)
   138  	if err != nil {
   139  		return ibctmtypes.Header{}, 0, err
   140  	}
   141  
   142  	page := 1
   143  	count := 10_000
   144  
   145  	validators, err := node.Validators(&height, page, count)
   146  	if err != nil {
   147  		return ibctmtypes.Header{}, 0, err
   148  	}
   149  
   150  	protoCommit := commit.SignedHeader.ToProto()
   151  	protoValset, err := tmtypes.NewValidatorSet(validators.Validators).ToProto()
   152  	if err != nil {
   153  		return ibctmtypes.Header{}, 0, err
   154  	}
   155  
   156  	header := ibctmtypes.Header{
   157  		SignedHeader: protoCommit,
   158  		ValidatorSet: protoValset,
   159  	}
   160  
   161  	return header, height, nil
   162  }
   163  
   164  // QueryNodeConsensusState takes a client context and returns the appropriate
   165  // tendermint consensus state
   166  func QueryNodeConsensusState(clientCtx clictx.CLIContext) (*ibctmtypes.ConsensusState, int64, error) {
   167  	node, err := clientCtx.GetNode()
   168  	if err != nil {
   169  		return &ibctmtypes.ConsensusState{}, 0, err
   170  	}
   171  
   172  	info, err := node.ABCIInfo()
   173  	if err != nil {
   174  		return &ibctmtypes.ConsensusState{}, 0, err
   175  	}
   176  
   177  	var height int64
   178  	if clientCtx.Height != 0 {
   179  		height = clientCtx.Height
   180  	} else {
   181  		height = info.Response.LastBlockHeight
   182  	}
   183  
   184  	commit, err := node.Commit(&height)
   185  	if err != nil {
   186  		return &ibctmtypes.ConsensusState{}, 0, err
   187  	}
   188  
   189  	page := 1
   190  	count := 10_000
   191  
   192  	nextHeight := height + 1
   193  	nextVals, err := node.Validators(&nextHeight, page, count)
   194  	if err != nil {
   195  		return &ibctmtypes.ConsensusState{}, 0, err
   196  	}
   197  
   198  	state := &ibctmtypes.ConsensusState{
   199  		Timestamp:          commit.Time,
   200  		Root:               commitmenttypes.NewMerkleRoot(commit.AppHash),
   201  		NextValidatorsHash: tmtypes.NewValidatorSet(nextVals.Validators).Hash(height),
   202  	}
   203  
   204  	return state, height, nil
   205  }
   206  
   207  // QuerySelfConsensusState takes a client context and returns the appropriate
   208  // tendermint consensus state
   209  func QuerySelfConsensusState(clientCtx clictx.CLIContext) (*ibctmtypes.ConsensusState, int64, error) {
   210  	node, err := clientCtx.GetNode()
   211  	if err != nil {
   212  		return &ibctmtypes.ConsensusState{}, 0, err
   213  	}
   214  
   215  	info, err := node.ABCIInfo()
   216  	if err != nil {
   217  		return &ibctmtypes.ConsensusState{}, 0, err
   218  	}
   219  
   220  	var height int64
   221  	if clientCtx.Height != 0 {
   222  		height = clientCtx.Height
   223  	} else {
   224  		height = info.Response.LastBlockHeight
   225  	}
   226  
   227  	commit, err := node.Commit(&height)
   228  	if err != nil {
   229  		return &ibctmtypes.ConsensusState{}, 0, err
   230  	}
   231  
   232  	page := 1
   233  	count := 10_000
   234  
   235  	nextHeight := height + 1
   236  	nextVals, err := node.Validators(&nextHeight, page, count)
   237  	if err != nil {
   238  		return &ibctmtypes.ConsensusState{}, 0, err
   239  	}
   240  
   241  	state := &ibctmtypes.ConsensusState{
   242  		Timestamp:          commit.Time,
   243  		Root:               commitmenttypes.NewMerkleRoot(commit.AppHash),
   244  		NextValidatorsHash: tmtypes.NewValidatorSet(nextVals.Validators).Hash(height),
   245  	}
   246  
   247  	return state, height, nil
   248  }