github.com/ari-anchor/sei-tendermint@v0.0.0-20230519144642-dc826b7b56bb/cmd/priv_val_server/main.go (about) 1 package main 2 3 import ( 4 "context" 5 "crypto/tls" 6 "crypto/x509" 7 "flag" 8 "fmt" 9 "net" 10 "net/http" 11 "os" 12 "os/signal" 13 "syscall" 14 "time" 15 16 grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" 17 "github.com/prometheus/client_golang/prometheus" 18 "github.com/prometheus/client_golang/prometheus/promhttp" 19 "google.golang.org/grpc" 20 "google.golang.org/grpc/credentials" 21 22 "github.com/ari-anchor/sei-tendermint/libs/log" 23 tmnet "github.com/ari-anchor/sei-tendermint/libs/net" 24 "github.com/ari-anchor/sei-tendermint/privval" 25 grpcprivval "github.com/ari-anchor/sei-tendermint/privval/grpc" 26 privvalproto "github.com/ari-anchor/sei-tendermint/proto/tendermint/privval" 27 ) 28 29 var ( 30 // Create a metrics registry. 31 reg = prometheus.NewRegistry() 32 33 // Create some standard server metrics. 34 grpcMetrics = grpc_prometheus.NewServerMetrics() 35 ) 36 37 func main() { 38 var ( 39 addr = flag.String("addr", "127.0.0.1:26659", "Address to listen on (host:port)") 40 chainID = flag.String("chain-id", "mychain", "chain id") 41 privValKeyPath = flag.String("priv-key", "", "priv val key file path") 42 privValStatePath = flag.String("priv-state", "", "priv val state file path") 43 insecure = flag.Bool("insecure", false, "allow server to run insecurely (no TLS)") 44 certFile = flag.String("certfile", "", "absolute path to server certificate") 45 keyFile = flag.String("keyfile", "", "absolute path to server key") 46 rootCA = flag.String("rootcafile", "", "absolute path to root CA") 47 prometheusAddr = flag.String("prometheus-addr", "", "address for prometheus endpoint (host:port)") 48 ) 49 flag.Parse() 50 51 logger, err := log.NewDefaultLogger(log.LogFormatPlain, log.LogLevelInfo) 52 if err != nil { 53 fmt.Fprintf(os.Stderr, "failed to construct logger: %v", err) 54 os.Exit(1) 55 } 56 logger = logger.With("module", "priv_val") 57 58 ctx, cancel := context.WithCancel(context.Background()) 59 defer cancel() 60 61 logger.Info( 62 "Starting private validator", 63 "addr", *addr, 64 "chainID", *chainID, 65 "privKeyPath", *privValKeyPath, 66 "privStatePath", *privValStatePath, 67 "insecure", *insecure, 68 "certFile", *certFile, 69 "keyFile", *keyFile, 70 "rootCA", *rootCA, 71 ) 72 73 pv, err := privval.LoadFilePV(*privValKeyPath, *privValStatePath) 74 if err != nil { 75 fmt.Fprint(os.Stderr, err) 76 os.Exit(1) 77 } 78 79 opts := []grpc.ServerOption{} 80 if !*insecure { 81 certificate, err := tls.LoadX509KeyPair(*certFile, *keyFile) 82 if err != nil { 83 fmt.Fprintf(os.Stderr, "failed to load X509 key pair: %v", err) 84 os.Exit(1) 85 } 86 87 certPool := x509.NewCertPool() 88 bs, err := os.ReadFile(*rootCA) 89 if err != nil { 90 fmt.Fprintf(os.Stderr, "failed to read client ca cert: %s", err) 91 os.Exit(1) 92 } 93 94 if ok := certPool.AppendCertsFromPEM(bs); !ok { 95 fmt.Fprintf(os.Stderr, "failed to append client certs") 96 os.Exit(1) 97 } 98 99 tlsConfig := &tls.Config{ 100 ClientAuth: tls.RequireAndVerifyClientCert, 101 Certificates: []tls.Certificate{certificate}, 102 ClientCAs: certPool, 103 MinVersion: tls.VersionTLS13, 104 } 105 106 creds := grpc.Creds(credentials.NewTLS(tlsConfig)) 107 opts = append(opts, creds) 108 logger.Info("SignerServer: Creating security credentials") 109 } else { 110 logger.Info("SignerServer: You are using an insecure gRPC connection!") 111 } 112 113 // add prometheus metrics for unary RPC calls 114 opts = append(opts, grpc.UnaryInterceptor(grpc_prometheus.UnaryServerInterceptor)) 115 116 ss := grpcprivval.NewSignerServer(logger, *chainID, pv) 117 118 protocol, address := tmnet.ProtocolAndAddress(*addr) 119 120 lis, err := net.Listen(protocol, address) 121 if err != nil { 122 fmt.Fprintf(os.Stderr, "SignerServer: Failed to listen %v", err) 123 os.Exit(1) 124 } 125 126 s := grpc.NewServer(opts...) 127 128 privvalproto.RegisterPrivValidatorAPIServer(s, ss) 129 130 var httpSrv *http.Server 131 if *prometheusAddr != "" { 132 httpSrv = registerPrometheus(*prometheusAddr, s) 133 } 134 135 logger.Info("SignerServer: Starting grpc server") 136 if err := s.Serve(lis); err != nil { 137 fmt.Fprintf(os.Stderr, "Unable to listen on port %s: %v", *addr, err) 138 os.Exit(1) 139 } 140 141 opctx, opcancel := signal.NotifyContext(ctx, os.Interrupt, syscall.SIGTERM) 142 defer opcancel() 143 go func() { 144 <-opctx.Done() 145 if *prometheusAddr != "" { 146 ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) 147 defer cancel() 148 if err := httpSrv.Shutdown(ctx); err != nil { 149 fmt.Fprintf(os.Stderr, "Unable to stop http server: %v", err) 150 os.Exit(1) 151 } 152 } 153 s.GracefulStop() 154 }() 155 156 // Run forever. 157 select {} 158 } 159 160 func registerPrometheus(addr string, s *grpc.Server) *http.Server { 161 // Initialize all metrics. 162 grpcMetrics.InitializeMetrics(s) 163 // create http server to serve prometheus 164 httpServer := &http.Server{Handler: promhttp.HandlerFor(reg, promhttp.HandlerOpts{}), Addr: addr} 165 166 go func() { 167 if err := httpServer.ListenAndServe(); err != nil { 168 fmt.Fprintf(os.Stderr, "Unable to start a http server: %v", err) 169 os.Exit(1) 170 } 171 }() 172 173 return httpServer 174 }