github.com/Finschia/finschia-sdk@v0.49.1/client/grpc/tmservice/service.go (about)

     1  package tmservice
     2  
     3  import (
     4  	"context"
     5  
     6  	octypes "github.com/Finschia/ostracon/proto/ostracon/types"
     7  	gogogrpc "github.com/gogo/protobuf/grpc"
     8  	"github.com/grpc-ecosystem/grpc-gateway/runtime"
     9  	tmtypes "github.com/tendermint/tendermint/proto/tendermint/types"
    10  	"google.golang.org/grpc/codes"
    11  	"google.golang.org/grpc/status"
    12  
    13  	"github.com/Finschia/finschia-sdk/client"
    14  	"github.com/Finschia/finschia-sdk/client/rpc"
    15  	codectypes "github.com/Finschia/finschia-sdk/codec/types"
    16  	cryptotypes "github.com/Finschia/finschia-sdk/crypto/types"
    17  	qtypes "github.com/Finschia/finschia-sdk/types/query"
    18  	"github.com/Finschia/finschia-sdk/version"
    19  )
    20  
    21  // This is the struct that we will implement all the handlers on.
    22  type queryServer struct {
    23  	clientCtx         client.Context
    24  	interfaceRegistry codectypes.InterfaceRegistry
    25  }
    26  
    27  var (
    28  	_ ServiceServer                      = queryServer{}
    29  	_ codectypes.UnpackInterfacesMessage = &GetLatestValidatorSetResponse{}
    30  )
    31  
    32  // NewQueryServer creates a new tendermint query server.
    33  func NewQueryServer(clientCtx client.Context, interfaceRegistry codectypes.InterfaceRegistry) ServiceServer {
    34  	return queryServer{
    35  		clientCtx:         clientCtx,
    36  		interfaceRegistry: interfaceRegistry,
    37  	}
    38  }
    39  
    40  // GetSyncing implements ServiceServer.GetSyncing
    41  func (s queryServer) GetSyncing(ctx context.Context, _ *GetSyncingRequest) (*GetSyncingResponse, error) {
    42  	status, err := GetNodeStatus(ctx, s.clientCtx)
    43  	if err != nil {
    44  		return nil, err
    45  	}
    46  	return &GetSyncingResponse{
    47  		Syncing: status.SyncInfo.CatchingUp,
    48  	}, nil
    49  }
    50  
    51  // ConvertOcProtoBlockToTmProtoBlock convert from ostracon proto block to tendermint proto block.
    52  func ConvertOcProtoBlockToTmProtoBlock(block *octypes.Block) *tmtypes.Block {
    53  	return &tmtypes.Block{
    54  		Header:     block.Header,
    55  		Data:       block.Data,
    56  		Evidence:   block.Evidence,
    57  		LastCommit: block.LastCommit,
    58  	}
    59  }
    60  
    61  // GetLatestBlock implements ServiceServer.GetLatestBlock
    62  func (s queryServer) GetLatestBlock(ctx context.Context, _ *GetLatestBlockRequest) (*GetLatestBlockResponse, error) {
    63  	status, err := GetBlock(ctx, s.clientCtx, nil)
    64  	if err != nil {
    65  		return nil, err
    66  	}
    67  
    68  	protoBlockID := status.BlockID.ToProto()
    69  	protoBlock, err := status.Block.ToProto()
    70  	if err != nil {
    71  		return nil, err
    72  	}
    73  
    74  	return &GetLatestBlockResponse{
    75  		BlockId: &protoBlockID,
    76  		Block:   ConvertOcProtoBlockToTmProtoBlock(protoBlock),
    77  	}, nil
    78  }
    79  
    80  // GetBlockByHeight implements ServiceServer.GetBlockByHeight
    81  func (s queryServer) GetBlockByHeight(ctx context.Context, req *GetBlockByHeightRequest) (*GetBlockByHeightResponse, error) {
    82  	chainHeight, err := rpc.GetChainHeight(s.clientCtx)
    83  	if err != nil {
    84  		return nil, err
    85  	}
    86  
    87  	if req.Height > chainHeight {
    88  		return nil, status.Error(codes.InvalidArgument, "requested block height is bigger then the chain length")
    89  	}
    90  
    91  	protoBlockID, protoBlock, err := GetProtoBlock(ctx, s.clientCtx, &req.Height)
    92  	if err != nil {
    93  		return nil, err
    94  	}
    95  	return &GetBlockByHeightResponse{
    96  		BlockId: &protoBlockID,
    97  		Block:   ConvertOcProtoBlockToTmProtoBlock(protoBlock),
    98  	}, nil
    99  }
   100  
   101  // GetLatestValidatorSet implements ServiceServer.GetLatestValidatorSet
   102  func (s queryServer) GetLatestValidatorSet(ctx context.Context, req *GetLatestValidatorSetRequest) (*GetLatestValidatorSetResponse, error) {
   103  	page, limit, err := qtypes.ParsePagination(req.Pagination)
   104  	if err != nil {
   105  		return nil, err
   106  	}
   107  	return validatorsOutput(ctx, s.clientCtx, nil, page, limit)
   108  }
   109  
   110  func (m *GetLatestValidatorSetResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error {
   111  	var pubKey cryptotypes.PubKey
   112  	for _, val := range m.Validators {
   113  		err := unpacker.UnpackAny(val.PubKey, &pubKey)
   114  		if err != nil {
   115  			return err
   116  		}
   117  	}
   118  	return nil
   119  }
   120  
   121  // GetValidatorSetByHeight implements ServiceServer.GetValidatorSetByHeight
   122  func (s queryServer) GetValidatorSetByHeight(ctx context.Context, req *GetValidatorSetByHeightRequest) (*GetValidatorSetByHeightResponse, error) {
   123  	page, limit, err := qtypes.ParsePagination(req.Pagination)
   124  	if err != nil {
   125  		return nil, err
   126  	}
   127  
   128  	chainHeight, err := rpc.GetChainHeight(s.clientCtx)
   129  	if err != nil {
   130  		return nil, status.Error(codes.Internal, "failed to parse chain height")
   131  	}
   132  	if req.Height > chainHeight {
   133  		return nil, status.Error(codes.InvalidArgument, "requested block height is bigger then the chain length")
   134  	}
   135  	r, err := validatorsOutput(ctx, s.clientCtx, &req.Height, page, limit)
   136  	if err != nil {
   137  		return nil, err
   138  	}
   139  	return &GetValidatorSetByHeightResponse{
   140  		BlockHeight: r.BlockHeight,
   141  		Validators:  r.Validators,
   142  		Pagination:  r.Pagination,
   143  	}, nil
   144  }
   145  
   146  func validatorsOutput(ctx context.Context, cctx client.Context, height *int64, page, limit int) (*GetLatestValidatorSetResponse, error) {
   147  	vs, err := rpc.GetValidators(ctx, cctx, height, &page, &limit)
   148  	if err != nil {
   149  		return nil, err
   150  	}
   151  	resp := GetLatestValidatorSetResponse{
   152  		BlockHeight: vs.BlockHeight,
   153  		Validators:  make([]*Validator, len(vs.Validators)),
   154  		Pagination: &qtypes.PageResponse{
   155  			Total: vs.Total,
   156  		},
   157  	}
   158  	for i, v := range vs.Validators {
   159  		anyPub, err := codectypes.NewAnyWithValue(v.PubKey)
   160  		if err != nil {
   161  			return nil, err
   162  		}
   163  		resp.Validators[i] = &Validator{
   164  			Address:          v.Address.String(),
   165  			ProposerPriority: v.ProposerPriority,
   166  			PubKey:           anyPub,
   167  			VotingPower:      v.VotingPower,
   168  		}
   169  	}
   170  	return &resp, nil
   171  }
   172  
   173  // GetNodeInfo implements ServiceServer.GetNodeInfo
   174  func (s queryServer) GetNodeInfo(ctx context.Context, req *GetNodeInfoRequest) (*GetNodeInfoResponse, error) {
   175  	status, err := GetNodeStatus(ctx, s.clientCtx)
   176  	if err != nil {
   177  		return nil, err
   178  	}
   179  
   180  	protoNodeInfo := status.NodeInfo.ToProto()
   181  	nodeInfo := version.NewInfo()
   182  
   183  	deps := make([]*Module, len(nodeInfo.BuildDeps))
   184  
   185  	for i, dep := range nodeInfo.BuildDeps {
   186  		deps[i] = &Module{
   187  			Path:    dep.Path,
   188  			Sum:     dep.Sum,
   189  			Version: dep.Version,
   190  		}
   191  	}
   192  
   193  	resp := GetNodeInfoResponse{
   194  		DefaultNodeInfo: protoNodeInfo,
   195  		ApplicationVersion: &VersionInfo{
   196  			AppName:          nodeInfo.AppName,
   197  			Name:             nodeInfo.Name,
   198  			GitCommit:        nodeInfo.GitCommit,
   199  			GoVersion:        nodeInfo.GoVersion,
   200  			Version:          nodeInfo.Version,
   201  			BuildTags:        nodeInfo.BuildTags,
   202  			BuildDeps:        deps,
   203  			CosmosSdkVersion: nodeInfo.LbmSdkVersion,
   204  		},
   205  	}
   206  	return &resp, nil
   207  }
   208  
   209  // RegisterTendermintService registers the tendermint queries on the gRPC router.
   210  func RegisterTendermintService(
   211  	qrt gogogrpc.Server,
   212  	clientCtx client.Context,
   213  	interfaceRegistry codectypes.InterfaceRegistry,
   214  ) {
   215  	RegisterServiceServer(
   216  		qrt,
   217  		NewQueryServer(clientCtx, interfaceRegistry),
   218  	)
   219  }
   220  
   221  // RegisterGRPCGatewayRoutes mounts the tendermint service's GRPC-gateway routes on the
   222  // given Mux.
   223  func RegisterGRPCGatewayRoutes(clientConn gogogrpc.ClientConn, mux *runtime.ServeMux) {
   224  	err := RegisterServiceHandlerClient(context.Background(), mux, NewServiceClient(clientConn))
   225  	if err != nil {
   226  		panic(err)
   227  	}
   228  }