github.com/cosmos/cosmos-sdk@v0.50.10/client/grpc/cmtservice/service.go (about) 1 package cmtservice 2 3 import ( 4 "context" 5 6 abci "github.com/cometbft/cometbft/abci/types" 7 gogogrpc "github.com/cosmos/gogoproto/grpc" 8 "github.com/grpc-ecosystem/grpc-gateway/runtime" 9 "google.golang.org/grpc/codes" 10 "google.golang.org/grpc/status" 11 12 "github.com/cosmos/cosmos-sdk/baseapp" 13 "github.com/cosmos/cosmos-sdk/client" 14 codectypes "github.com/cosmos/cosmos-sdk/codec/types" 15 cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" 16 cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" 17 sdk "github.com/cosmos/cosmos-sdk/types" 18 qtypes "github.com/cosmos/cosmos-sdk/types/query" 19 "github.com/cosmos/cosmos-sdk/version" 20 ) 21 22 var ( 23 _ ServiceServer = queryServer{} 24 _ codectypes.UnpackInterfacesMessage = &GetLatestValidatorSetResponse{} 25 ) 26 27 type ( 28 abciQueryFn = func(context.Context, *abci.RequestQuery) (*abci.ResponseQuery, error) 29 30 queryServer struct { 31 clientCtx client.Context 32 interfaceRegistry codectypes.InterfaceRegistry 33 queryFn abciQueryFn 34 } 35 ) 36 37 // NewQueryServer creates a new CometBFT query server. 38 func NewQueryServer( 39 clientCtx client.Context, 40 interfaceRegistry codectypes.InterfaceRegistry, 41 queryFn abciQueryFn, 42 ) ServiceServer { 43 return queryServer{ 44 clientCtx: clientCtx, 45 interfaceRegistry: interfaceRegistry, 46 queryFn: queryFn, 47 } 48 } 49 50 // GetSyncing implements ServiceServer.GetSyncing 51 func (s queryServer) GetSyncing(ctx context.Context, _ *GetSyncingRequest) (*GetSyncingResponse, error) { 52 status, err := GetNodeStatus(ctx, s.clientCtx) 53 if err != nil { 54 return nil, err 55 } 56 57 return &GetSyncingResponse{ 58 Syncing: status.SyncInfo.CatchingUp, 59 }, nil 60 } 61 62 // GetLatestBlock implements ServiceServer.GetLatestBlock 63 func (s queryServer) GetLatestBlock(ctx context.Context, _ *GetLatestBlockRequest) (*GetLatestBlockResponse, error) { 64 status, err := getBlock(ctx, s.clientCtx, nil) 65 if err != nil { 66 return nil, err 67 } 68 69 protoBlockID := status.BlockID.ToProto() 70 protoBlock, err := status.Block.ToProto() 71 if err != nil { 72 return nil, err 73 } 74 75 return &GetLatestBlockResponse{ 76 BlockId: &protoBlockID, 77 Block: protoBlock, 78 SdkBlock: convertBlock(protoBlock), 79 }, nil 80 } 81 82 // GetBlockByHeight implements ServiceServer.GetBlockByHeight 83 func (s queryServer) GetBlockByHeight(ctx context.Context, req *GetBlockByHeightRequest) (*GetBlockByHeightResponse, error) { 84 blockHeight, err := getBlockHeight(ctx, s.clientCtx) 85 if err != nil { 86 return nil, err 87 } 88 89 if req.Height > blockHeight { 90 return nil, status.Error(codes.InvalidArgument, "requested block height is bigger then the chain length") 91 } 92 93 protoBlockID, protoBlock, err := GetProtoBlock(ctx, s.clientCtx, &req.Height) 94 if err != nil { 95 return nil, err 96 } 97 98 return &GetBlockByHeightResponse{ 99 BlockId: &protoBlockID, 100 Block: protoBlock, 101 SdkBlock: convertBlock(protoBlock), 102 }, nil 103 } 104 105 // GetLatestValidatorSet implements ServiceServer.GetLatestValidatorSet 106 func (s queryServer) GetLatestValidatorSet(ctx context.Context, req *GetLatestValidatorSetRequest) (*GetLatestValidatorSetResponse, error) { 107 page, limit, err := qtypes.ParsePagination(req.Pagination) 108 if err != nil { 109 return nil, err 110 } 111 112 return ValidatorsOutput(ctx, s.clientCtx, nil, page, limit) 113 } 114 115 func (m *GetLatestValidatorSetResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { 116 var pubKey cryptotypes.PubKey 117 for _, val := range m.Validators { 118 err := unpacker.UnpackAny(val.PubKey, &pubKey) 119 if err != nil { 120 return err 121 } 122 } 123 124 return nil 125 } 126 127 // GetValidatorSetByHeight implements ServiceServer.GetValidatorSetByHeight 128 func (s queryServer) GetValidatorSetByHeight(ctx context.Context, req *GetValidatorSetByHeightRequest) (*GetValidatorSetByHeightResponse, error) { 129 page, limit, err := qtypes.ParsePagination(req.Pagination) 130 if err != nil { 131 return nil, err 132 } 133 134 blockHeight, err := getBlockHeight(ctx, s.clientCtx) 135 if err != nil { 136 return nil, status.Error(codes.Internal, "failed to parse chain height") 137 } 138 139 if req.Height > blockHeight { 140 return nil, status.Error(codes.InvalidArgument, "requested block height is bigger then the chain length") 141 } 142 143 r, err := ValidatorsOutput(ctx, s.clientCtx, &req.Height, page, limit) 144 if err != nil { 145 return nil, err 146 } 147 148 return &GetValidatorSetByHeightResponse{ 149 BlockHeight: r.BlockHeight, 150 Validators: r.Validators, 151 Pagination: r.Pagination, 152 }, nil 153 } 154 155 func ValidatorsOutput(ctx context.Context, clientCtx client.Context, height *int64, page, limit int) (*GetLatestValidatorSetResponse, error) { 156 vs, err := getValidators(ctx, clientCtx, height, page, limit) 157 if err != nil { 158 return nil, err 159 } 160 161 resp := GetLatestValidatorSetResponse{ 162 BlockHeight: vs.BlockHeight, 163 Validators: make([]*Validator, len(vs.Validators)), 164 Pagination: &qtypes.PageResponse{ 165 Total: uint64(vs.Total), 166 }, 167 } 168 169 for i, v := range vs.Validators { 170 pk, err := cryptocodec.FromCmtPubKeyInterface(v.PubKey) 171 if err != nil { 172 return nil, err 173 } 174 anyPub, err := codectypes.NewAnyWithValue(pk) 175 if err != nil { 176 return nil, err 177 } 178 179 resp.Validators[i] = &Validator{ 180 Address: sdk.ConsAddress(v.Address).String(), 181 ProposerPriority: v.ProposerPriority, 182 PubKey: anyPub, 183 VotingPower: v.VotingPower, 184 } 185 } 186 187 return &resp, nil 188 } 189 190 // GetNodeInfo implements ServiceServer.GetNodeInfo 191 func (s queryServer) GetNodeInfo(ctx context.Context, _ *GetNodeInfoRequest) (*GetNodeInfoResponse, error) { 192 status, err := GetNodeStatus(ctx, s.clientCtx) 193 if err != nil { 194 return nil, err 195 } 196 197 protoNodeInfo := status.NodeInfo.ToProto() 198 nodeInfo := version.NewInfo() 199 200 deps := make([]*Module, len(nodeInfo.BuildDeps)) 201 202 for i, dep := range nodeInfo.BuildDeps { 203 deps[i] = &Module{ 204 Path: dep.Path, 205 Sum: dep.Sum, 206 Version: dep.Version, 207 } 208 } 209 210 resp := GetNodeInfoResponse{ 211 DefaultNodeInfo: protoNodeInfo, 212 ApplicationVersion: &VersionInfo{ 213 AppName: nodeInfo.AppName, 214 Name: nodeInfo.Name, 215 GitCommit: nodeInfo.GitCommit, 216 GoVersion: nodeInfo.GoVersion, 217 Version: nodeInfo.Version, 218 BuildTags: nodeInfo.BuildTags, 219 BuildDeps: deps, 220 CosmosSdkVersion: nodeInfo.CosmosSdkVersion, 221 }, 222 } 223 return &resp, nil 224 } 225 226 func (s queryServer) ABCIQuery(ctx context.Context, req *ABCIQueryRequest) (*ABCIQueryResponse, error) { 227 if s.queryFn == nil { 228 return nil, status.Error(codes.Internal, "ABCI Query handler undefined") 229 } 230 if req == nil { 231 return nil, status.Error(codes.InvalidArgument, "empty request") 232 } 233 if len(req.Path) == 0 { 234 return nil, status.Error(codes.InvalidArgument, "empty query path") 235 } 236 237 if path := baseapp.SplitABCIQueryPath(req.Path); len(path) > 0 { 238 switch path[0] { 239 case baseapp.QueryPathApp, baseapp.QueryPathStore, baseapp.QueryPathP2P, baseapp.QueryPathCustom: 240 // valid path 241 242 default: 243 // Otherwise, error as to prevent either valid gRPC service requests or 244 // bogus ABCI queries. 245 return nil, status.Errorf(codes.InvalidArgument, "unsupported ABCI query path: %s", req.Path) 246 } 247 } 248 249 res, err := s.queryFn(ctx, req.ToABCIRequestQuery()) 250 if err != nil { 251 return nil, err 252 } 253 return FromABCIResponseQuery(res), nil 254 } 255 256 // RegisterTendermintService registers the CometBFT queries on the gRPC router. 257 func RegisterTendermintService( 258 clientCtx client.Context, 259 server gogogrpc.Server, 260 iRegistry codectypes.InterfaceRegistry, 261 queryFn abciQueryFn, 262 ) { 263 RegisterServiceServer(server, NewQueryServer(clientCtx, iRegistry, queryFn)) 264 } 265 266 // RegisterGRPCGatewayRoutes mounts the CometBFT service's GRPC-gateway routes on the 267 // given Mux. 268 func RegisterGRPCGatewayRoutes(clientConn gogogrpc.ClientConn, mux *runtime.ServeMux) { 269 _ = RegisterServiceHandlerClient(context.Background(), mux, NewServiceClient(clientConn)) 270 }