2020-05-20 15:23:22 +00:00
|
|
|
package slashingprotection
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
2020-07-27 20:06:49 +00:00
|
|
|
"fmt"
|
2020-05-20 15:23:22 +00:00
|
|
|
"strings"
|
2020-07-22 03:45:52 +00:00
|
|
|
"time"
|
2020-05-20 15:23:22 +00:00
|
|
|
|
|
|
|
middleware "github.com/grpc-ecosystem/go-grpc-middleware"
|
|
|
|
grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
|
|
|
|
grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
|
|
|
|
grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
|
|
|
|
ethsl "github.com/prysmaticlabs/prysm/proto/slashing"
|
|
|
|
"github.com/prysmaticlabs/prysm/shared/grpcutils"
|
|
|
|
"go.opencensus.io/plugin/ocgrpc"
|
|
|
|
"google.golang.org/grpc"
|
2020-07-27 20:06:49 +00:00
|
|
|
"google.golang.org/grpc/connectivity"
|
2020-05-20 15:23:22 +00:00
|
|
|
"google.golang.org/grpc/credentials"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Service represents a service to manage the validator
|
|
|
|
// slashing protection.
|
|
|
|
type Service struct {
|
2021-03-21 17:53:17 +00:00
|
|
|
cfg *Config
|
|
|
|
ctx context.Context
|
|
|
|
cancel context.CancelFunc
|
|
|
|
conn *grpc.ClientConn
|
|
|
|
grpcHeaders []string
|
|
|
|
slasherClient ethsl.SlasherClient
|
2020-05-20 15:23:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Config for the validator service.
|
|
|
|
type Config struct {
|
|
|
|
Endpoint string
|
|
|
|
CertFlag string
|
|
|
|
GrpcMaxCallRecvMsgSizeFlag int
|
|
|
|
GrpcRetriesFlag uint
|
2020-07-22 03:45:52 +00:00
|
|
|
GrpcRetryDelay time.Duration
|
2020-05-20 15:23:22 +00:00
|
|
|
GrpcHeadersFlag string
|
|
|
|
}
|
|
|
|
|
2021-02-12 17:45:22 +00:00
|
|
|
// NewService creates a new validator service for the service
|
2020-05-20 15:23:22 +00:00
|
|
|
// registry.
|
2021-02-12 17:45:22 +00:00
|
|
|
func NewService(ctx context.Context, cfg *Config) (*Service, error) {
|
2020-05-20 15:23:22 +00:00
|
|
|
ctx, cancel := context.WithCancel(ctx)
|
|
|
|
return &Service{
|
2021-03-21 17:53:17 +00:00
|
|
|
cfg: cfg,
|
|
|
|
ctx: ctx,
|
|
|
|
cancel: cancel,
|
|
|
|
grpcHeaders: strings.Split(cfg.GrpcHeadersFlag, ","),
|
2020-05-20 15:23:22 +00:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Start the slasher protection service and grpc client.
|
|
|
|
func (s *Service) Start() {
|
2021-03-21 17:53:17 +00:00
|
|
|
if s.cfg.Endpoint != "" {
|
2020-05-20 15:23:22 +00:00
|
|
|
s.slasherClient = s.startSlasherClient()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Service) startSlasherClient() ethsl.SlasherClient {
|
|
|
|
var dialOpt grpc.DialOption
|
|
|
|
|
2021-03-21 17:53:17 +00:00
|
|
|
if s.cfg.CertFlag != "" {
|
|
|
|
creds, err := credentials.NewClientTLSFromFile(s.cfg.CertFlag, "")
|
2020-05-20 15:23:22 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Errorf("Could not get valid slasher credentials: %v", err)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
dialOpt = grpc.WithTransportCredentials(creds)
|
|
|
|
} else {
|
|
|
|
dialOpt = grpc.WithInsecure()
|
|
|
|
log.Warn("You are using an insecure slasher gRPC connection! Please provide a certificate and key to use a secure connection.")
|
|
|
|
}
|
|
|
|
|
2021-01-28 14:58:32 +00:00
|
|
|
s.ctx = grpcutils.AppendHeaders(s.ctx, s.grpcHeaders)
|
2020-05-20 15:23:22 +00:00
|
|
|
|
|
|
|
opts := []grpc.DialOption{
|
|
|
|
dialOpt,
|
|
|
|
grpc.WithDefaultCallOptions(
|
2021-03-21 17:53:17 +00:00
|
|
|
grpc_retry.WithMax(s.cfg.GrpcRetriesFlag),
|
|
|
|
grpc_retry.WithBackoff(grpc_retry.BackoffLinear(s.cfg.GrpcRetryDelay)),
|
2020-05-20 15:23:22 +00:00
|
|
|
),
|
|
|
|
grpc.WithStatsHandler(&ocgrpc.ClientHandler{}),
|
|
|
|
grpc.WithStreamInterceptor(middleware.ChainStreamClient(
|
|
|
|
grpc_opentracing.StreamClientInterceptor(),
|
|
|
|
grpc_prometheus.StreamClientInterceptor,
|
|
|
|
grpc_retry.StreamClientInterceptor(),
|
|
|
|
)),
|
|
|
|
grpc.WithUnaryInterceptor(middleware.ChainUnaryClient(
|
|
|
|
grpc_opentracing.UnaryClientInterceptor(),
|
|
|
|
grpc_prometheus.UnaryClientInterceptor,
|
|
|
|
grpc_retry.UnaryClientInterceptor(),
|
2021-01-28 14:58:32 +00:00
|
|
|
grpcutils.LogRequests,
|
2020-05-20 15:23:22 +00:00
|
|
|
)),
|
|
|
|
}
|
2021-03-21 17:53:17 +00:00
|
|
|
conn, err := grpc.DialContext(s.ctx, s.cfg.Endpoint, opts...)
|
2020-05-20 15:23:22 +00:00
|
|
|
if err != nil {
|
2021-03-21 17:53:17 +00:00
|
|
|
log.Errorf("Could not dial slasher endpoint: %s, %v", s.cfg.Endpoint, err)
|
2020-05-20 15:23:22 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
log.Debug("Successfully started slasher gRPC connection")
|
|
|
|
s.conn = conn
|
|
|
|
return ethsl.NewSlasherClient(s.conn)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Stop the validator service.
|
|
|
|
func (s *Service) Stop() error {
|
|
|
|
s.cancel()
|
|
|
|
log.Info("Stopping slashing protection service")
|
|
|
|
if s.conn != nil {
|
|
|
|
return s.conn.Close()
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-07-27 20:06:49 +00:00
|
|
|
// Status checks if the connection to slasher server is ready,
|
|
|
|
// returns error otherwise.
|
2020-05-20 15:23:22 +00:00
|
|
|
func (s *Service) Status() error {
|
|
|
|
if s.conn == nil {
|
|
|
|
return errors.New("no connection to slasher RPC")
|
|
|
|
}
|
2020-07-27 20:06:49 +00:00
|
|
|
if s.conn.GetState() != connectivity.Ready {
|
2021-03-21 17:53:17 +00:00
|
|
|
return fmt.Errorf("can`t connect to slasher server at: %v connection status: %v ", s.cfg.Endpoint, s.conn.GetState())
|
2020-07-27 20:06:49 +00:00
|
|
|
}
|
2020-05-20 15:23:22 +00:00
|
|
|
return nil
|
|
|
|
}
|