-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add implementation for method CreateHandlers * Implement ABCI endpoints (#13) * implemetn ibc response from lendslidecore * introduce status rpc method (#14) Co-authored-by: Ivan Sukach <ivansukach@github.com> * use cometbft json rpc handler --------- Co-authored-by: ivansukach <47761294+ivansukach@users.noreply.github.com> Co-authored-by: Ivan Sukach <ivansukach@github.com> Co-authored-by: ramil <ramilexe@gmail.com> * remove landslidecore dependency add routes for abci_query and abci_info * update pb * Add all RPC methods to Route map (#17) * Add all RPC methods to Route map * rpc methods signature updated * MempoolService interface (#18) * MempoolService interface * run Github Actions on any PR --------- Co-authored-by: ramil <ramilexe@gmail.com> * RPC tests for Health and Status functions --------- Co-authored-by: ramil <ramilexe@gmail.com> Co-authored-by: chist100 <44050804+chist100@users.noreply.github.com> Co-authored-by: ivansukach <47761294+ivansukach@users.noreply.github.com> Co-authored-by: Ivan Sukach <ivansukach@github.com> Co-authored-by: Vasyl Naumenko <vnau108@gmail.com>
- Loading branch information
1 parent
609c0b6
commit d0e5a92
Showing
39 changed files
with
6,776 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,6 @@ on: | |
push: | ||
branches: [ "main" ] | ||
pull_request: | ||
branches: [ "main" ] | ||
|
||
jobs: | ||
buf-lint: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,6 @@ on: | |
push: | ||
branches: [ "main" ] | ||
pull_request: | ||
branches: [ "main" ] | ||
|
||
jobs: | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
package grpcutils | ||
|
||
import ( | ||
"math" | ||
"time" | ||
|
||
"google.golang.org/grpc" | ||
"google.golang.org/grpc/credentials/insecure" | ||
"google.golang.org/grpc/keepalive" | ||
) | ||
|
||
const ( | ||
// After a duration of this time if the client doesn't see any activity it | ||
// pings the server to see if the transport is still alive. | ||
// If set below 10s, a minimum value of 10s will be used instead. | ||
// grpc-go default infinity | ||
defaultClientKeepAliveTime = 30 * time.Second | ||
// After having pinged for keepalive check, the client waits for a duration | ||
// of Timeout and if no activity is seen even after that the connection is | ||
// closed. grpc-go default 20s | ||
defaultClientKeepAliveTimeOut = 10 * time.Second | ||
// If true, client sends keepalive pings even with no active RPCs. If false, | ||
// when there are no active RPCs, Time and Timeout will be ignored and no | ||
// keepalive pings will be sent. grpc-go default false | ||
defaultPermitWithoutStream = true | ||
// WaitForReady configures the action to take when an RPC is attempted on | ||
// broken connections or unreachable servers. If waitForReady is false and | ||
// the connection is in the TRANSIENT_FAILURE state, the RPC will fail | ||
// immediately. Otherwise, the RPC client will block the call until a | ||
// connection is available (or the call is canceled or times out) and will | ||
// retry the call if it fails due to a transient error. gRPC will not retry | ||
// if data was written to the wire unless the server indicates it did not | ||
// process the data. Please refer to | ||
// https://github.com/grpc/grpc/blob/master/doc/wait-for-ready.md. | ||
// | ||
// gRPC default behavior is to NOT "wait for ready". | ||
defaultWaitForReady = true | ||
) | ||
|
||
var DefaultDialOptions = []grpc.DialOption{ | ||
grpc.WithDefaultCallOptions( | ||
grpc.MaxCallRecvMsgSize(math.MaxInt), | ||
grpc.MaxCallSendMsgSize(math.MaxInt), | ||
grpc.WaitForReady(defaultWaitForReady), | ||
), | ||
grpc.WithKeepaliveParams(keepalive.ClientParameters{ | ||
Time: defaultClientKeepAliveTime, | ||
Timeout: defaultClientKeepAliveTimeOut, | ||
PermitWithoutStream: defaultPermitWithoutStream, | ||
}), | ||
grpc.WithTransportCredentials(insecure.NewCredentials()), | ||
} | ||
|
||
// gRPC clients created from this ClientConn will wait forever for the Server to | ||
// become Ready. If you desire a dial timeout ensure context is properly plumbed | ||
// to the client and use context.WithTimeout. | ||
// | ||
// Dial returns a gRPC ClientConn with the dial options as defined by | ||
// DefaultDialOptions. DialOption can also optionally be passed. | ||
func Dial(addr string, opts ...DialOption) (*grpc.ClientConn, error) { | ||
return grpc.Dial("passthrough:///"+addr, newDialOpts(opts...)...) | ||
} | ||
|
||
// DialOptions are options which can be applied to a gRPC client in addition to | ||
// the defaults set by DefaultDialOptions. | ||
type DialOptions struct { | ||
opts []grpc.DialOption | ||
} | ||
|
||
// append(DefaultDialOptions, ...) will always allocate a new slice and will | ||
// not overwrite any potential data that may have previously been appended to | ||
// DefaultServerOptions https://go.dev/ref/spec#Composite_literals | ||
func newDialOpts(opts ...DialOption) []grpc.DialOption { | ||
d := &DialOptions{opts: DefaultDialOptions} | ||
d.applyOpts(opts) | ||
return d.opts | ||
} | ||
|
||
func (d *DialOptions) applyOpts(opts []DialOption) { | ||
for _, opt := range opts { | ||
opt(d) | ||
} | ||
} | ||
|
||
type DialOption func(*DialOptions) | ||
|
||
// WithChainUnaryInterceptor takes a list of unary client interceptors which | ||
// are added to the dial options. | ||
func WithChainUnaryInterceptor(interceptors ...grpc.UnaryClientInterceptor) DialOption { | ||
return func(d *DialOptions) { | ||
d.opts = append(d.opts, grpc.WithChainUnaryInterceptor(interceptors...)) | ||
} | ||
} | ||
|
||
// WithChainStreamInterceptor takes a list of stream client interceptors which | ||
// are added to the dial options. | ||
func WithChainStreamInterceptor(interceptors ...grpc.StreamClientInterceptor) DialOption { | ||
return func(d *DialOptions) { | ||
d.opts = append(d.opts, grpc.WithChainStreamInterceptor(interceptors...)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
package grpcutils | ||
|
||
import ( | ||
"math" | ||
"net" | ||
"time" | ||
|
||
"google.golang.org/grpc" | ||
"google.golang.org/grpc/keepalive" | ||
) | ||
|
||
const ( | ||
// MinTime is the minimum amount of time a client should wait before sending | ||
// a keepalive ping. grpc-go default 5 mins | ||
defaultServerKeepAliveMinTime = 5 * time.Second | ||
// After a duration of this time if the server doesn't see any activity it | ||
// pings the client to see if the transport is still alive. | ||
// If set below 1s, a minimum value of 1s will be used instead. | ||
// grpc-go default 2h | ||
defaultServerKeepAliveInterval = 2 * time.Hour | ||
// After having pinged for keepalive check, the server waits for a duration | ||
// of Timeout and if no activity is seen even after that the connection is | ||
// closed. grpc-go default 20s | ||
defaultServerKeepAliveTimeout = 20 * time.Second | ||
) | ||
|
||
var DefaultServerOptions = []grpc.ServerOption{ | ||
grpc.MaxRecvMsgSize(math.MaxInt), | ||
grpc.MaxSendMsgSize(math.MaxInt), | ||
grpc.MaxConcurrentStreams(math.MaxUint32), | ||
grpc.KeepaliveEnforcementPolicy(keepalive.EnforcementPolicy{ | ||
MinTime: defaultServerKeepAliveMinTime, | ||
PermitWithoutStream: defaultPermitWithoutStream, | ||
}), | ||
grpc.KeepaliveParams(keepalive.ServerParameters{ | ||
Time: defaultServerKeepAliveInterval, | ||
Timeout: defaultServerKeepAliveTimeout, | ||
}), | ||
} | ||
|
||
// NewServer will return a gRPC server with server options as defined by | ||
// DefaultServerOptions. ServerOption can also optionally be passed. | ||
func NewServer(opts ...ServerOption) *grpc.Server { | ||
return grpc.NewServer(newServerOpts(opts)...) | ||
} | ||
|
||
type ServerOptions struct { | ||
opts []grpc.ServerOption | ||
} | ||
|
||
// append(DefaultServerOptions, ...) will always allocate a new slice and will | ||
// not overwrite any potential data that may have previously been appended to | ||
// DefaultServerOptions https://go.dev/ref/spec#Composite_literals | ||
func newServerOpts(opts []ServerOption) []grpc.ServerOption { | ||
s := &ServerOptions{opts: DefaultServerOptions} | ||
s.applyOpts(opts) | ||
return s.opts | ||
} | ||
|
||
func (s *ServerOptions) applyOpts(opts []ServerOption) { | ||
for _, opt := range opts { | ||
opt(s) | ||
} | ||
} | ||
|
||
// ServerOption are options which can be applied to a gRPC server in addition to | ||
// the defaults set by DefaultServerOPtions. | ||
type ServerOption func(*ServerOptions) | ||
|
||
// WithUnaryInterceptor adds a single unary interceptor to the gRPC server | ||
// options. | ||
func WithUnaryInterceptor(unaryInterceptor grpc.UnaryServerInterceptor) ServerOption { | ||
return func(s *ServerOptions) { | ||
s.opts = append(s.opts, grpc.UnaryInterceptor(unaryInterceptor)) | ||
} | ||
} | ||
|
||
// WithStreamInterceptor adds a single stream interceptor to the gRPC server | ||
// options. | ||
func WithStreamInterceptor(streamInterceptor grpc.StreamServerInterceptor) ServerOption { | ||
return func(s *ServerOptions) { | ||
s.opts = append(s.opts, grpc.StreamInterceptor(streamInterceptor)) | ||
} | ||
} | ||
|
||
// NewListener returns a TCP listener listening against the next available port | ||
// on the system bound to localhost. | ||
func NewListener() (net.Listener, error) { | ||
return net.Listen("tcp", "127.0.0.1:") | ||
} | ||
|
||
// Serve will start a gRPC server and block until it errors or is shutdown. | ||
func Serve(listener net.Listener, grpcServer *grpc.Server) { | ||
// TODO: While errors will be reported later, it could be useful to somehow | ||
// log this if it is the primary error. | ||
// | ||
// There is nothing to with the error returned by serve here. Later requests | ||
// will propegate their error if they occur. | ||
_ = grpcServer.Serve(listener) | ||
|
||
// Similarly, there is nothing to with an error when the listener is closed. | ||
_ = listener.Close() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package closer | ||
package grpcutils | ||
|
||
import ( | ||
"sync" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. | ||
// See the file LICENSE for licensing terms. | ||
|
||
package grpcutils | ||
|
||
import ( | ||
"fmt" | ||
"net/http" | ||
"time" | ||
|
||
"google.golang.org/grpc/status" | ||
"google.golang.org/protobuf/proto" | ||
"google.golang.org/protobuf/types/known/anypb" | ||
|
||
httppb "github.com/consideritdone/landslidevm/proto/http" | ||
spb "google.golang.org/genproto/googleapis/rpc/status" | ||
tspb "google.golang.org/protobuf/types/known/timestamppb" | ||
) | ||
|
||
func Errorf(code int, tmpl string, args ...interface{}) error { | ||
return GetGRPCErrorFromHTTPResponse(&httppb.HandleSimpleHTTPResponse{ | ||
Code: int32(code), | ||
Body: []byte(fmt.Sprintf(tmpl, args...)), | ||
}) | ||
} | ||
|
||
// GetGRPCErrorFromHTTPRespone takes an HandleSimpleHTTPResponse as input and returns a gRPC error. | ||
func GetGRPCErrorFromHTTPResponse(resp *httppb.HandleSimpleHTTPResponse) error { | ||
a, err := anypb.New(resp) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return status.ErrorProto(&spb.Status{ | ||
Code: resp.Code, | ||
Message: string(resp.Body), | ||
Details: []*anypb.Any{a}, | ||
}) | ||
} | ||
|
||
// GetHTTPResponseFromError takes an gRPC error as input and returns a gRPC | ||
// HandleSimpleHTTPResponse. | ||
func GetHTTPResponseFromError(err error) (*httppb.HandleSimpleHTTPResponse, bool) { | ||
s, ok := status.FromError(err) | ||
if !ok { | ||
return nil, false | ||
} | ||
|
||
status := s.Proto() | ||
if len(status.Details) != 1 { | ||
return nil, false | ||
} | ||
|
||
var resp httppb.HandleSimpleHTTPResponse | ||
if err := anypb.UnmarshalTo(status.Details[0], &resp, proto.UnmarshalOptions{}); err != nil { | ||
return nil, false | ||
} | ||
|
||
return &resp, true | ||
} | ||
|
||
// GetHTTPHeader takes an http.Header as input and returns a slice of Header. | ||
func GetHTTPHeader(hs http.Header) []*httppb.Element { | ||
result := make([]*httppb.Element, 0, len(hs)) | ||
for k, vs := range hs { | ||
result = append(result, &httppb.Element{ | ||
Key: k, | ||
Values: vs, | ||
}) | ||
} | ||
return result | ||
} | ||
|
||
// MergeHTTPHeader takes a slice of Header and merges with http.Header map. | ||
func MergeHTTPHeader(hs []*httppb.Element, header http.Header) { | ||
for _, h := range hs { | ||
header[h.Key] = h.Values | ||
} | ||
} | ||
|
||
// TimestampAsTime validates timestamppb timestamp and returns time.Time. | ||
func TimestampAsTime(ts *tspb.Timestamp) (time.Time, error) { | ||
if err := ts.CheckValid(); err != nil { | ||
return time.Time{}, fmt.Errorf("invalid timestamp: %w", err) | ||
} | ||
return ts.AsTime(), nil | ||
} | ||
|
||
// TimestampFromTime converts time.Time to a timestamppb timestamp. | ||
func TimestampFromTime(time time.Time) *tspb.Timestamp { | ||
return tspb.New(time) | ||
} | ||
|
||
// EnsureValidResponseCode ensures that the response code is valid otherwise it returns 500. | ||
func EnsureValidResponseCode(code int) int { | ||
// Response code outside of this range is invalid and could panic. | ||
// ref. https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html | ||
if code < 100 || code > 599 { | ||
return http.StatusInternalServerError | ||
} | ||
return code | ||
} |
Oops, something went wrong.