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

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