From 85bb6c9f48bdc2cba108d32e7eaea4928b4d7eae Mon Sep 17 00:00:00 2001
From: a
Date: Sun, 29 Oct 2023 19:17:53 -0500
Subject: [PATCH 1/5] ok
---
cmd/rpcdaemon/cli/config.go | 78 +++++++++++++++++++--------
cmd/rpcdaemon/cli/httpcfg/http_cfg.go | 7 +++
node/endpoints.go | 74 +++++++++++++++++++++++--
3 files changed, 135 insertions(+), 24 deletions(-)
diff --git a/cmd/rpcdaemon/cli/config.go b/cmd/rpcdaemon/cli/config.go
index ea15834adcb..35a86cb1cdf 100644
--- a/cmd/rpcdaemon/cli/config.go
+++ b/cmd/rpcdaemon/cli/config.go
@@ -89,10 +89,6 @@ func RootCommand() (*cobra.Command, *httpcfg.HttpCfg) {
rootCmd.PersistentFlags().StringVar(&cfg.PrivateApiAddr, "private.api.addr", "127.0.0.1:9090", "Erigon's components (txpool, rpcdaemon, sentry, downloader, ...) can be deployed as independent Processes on same/another server. Then components will connect to erigon by this internal grpc API. Example: 127.0.0.1:9090")
rootCmd.PersistentFlags().StringVar(&cfg.DataDir, "datadir", "", "path to Erigon working directory")
rootCmd.PersistentFlags().BoolVar(&cfg.GraphQLEnabled, "graphql", false, "enables graphql endpoint (disabled by default)")
- rootCmd.PersistentFlags().StringVar(&cfg.HttpListenAddress, "http.addr", nodecfg.DefaultHTTPHost, "HTTP-RPC server listening interface")
- rootCmd.PersistentFlags().StringVar(&cfg.TLSCertfile, "tls.cert", "", "certificate for client side TLS handshake")
- rootCmd.PersistentFlags().StringVar(&cfg.TLSKeyFile, "tls.key", "", "key file for client side TLS handshake")
- rootCmd.PersistentFlags().StringVar(&cfg.TLSCACert, "tls.cacert", "", "CA certificate for client side TLS handshake")
rootCmd.PersistentFlags().Uint64Var(&cfg.Gascap, "rpc.gascap", 50_000_000, "Sets a cap on gas that can be used in eth_call/estimateGas")
rootCmd.PersistentFlags().Uint64Var(&cfg.MaxTraces, "trace.maxtraces", 200, "Sets a limit on traces that can be returned in trace_filter")
@@ -110,17 +106,29 @@ func RootCommand() (*cobra.Command, *httpcfg.HttpCfg) {
rootCmd.PersistentFlags().IntVar(&cfg.GRPCPort, "grpc.port", nodecfg.DefaultGRPCPort, "GRPC server listening port")
rootCmd.PersistentFlags().BoolVar(&cfg.GRPCHealthCheckEnabled, "grpc.healthcheck", false, "Enable GRPC health check")
rootCmd.PersistentFlags().Float64Var(ðconfig.Defaults.RPCTxFeeCap, utils.RPCGlobalTxFeeCapFlag.Name, utils.RPCGlobalTxFeeCapFlag.Value, utils.RPCGlobalTxFeeCapFlag.Usage)
+ rootCmd.PersistentFlags().StringVar(&cfg.TLSCertfile, "tls.cert", "", "certificate for client side TLS handshake for GRPC")
+ rootCmd.PersistentFlags().StringVar(&cfg.TLSKeyFile, "tls.key", "", "key file for client side TLS handshake for GRPC")
+ rootCmd.PersistentFlags().StringVar(&cfg.TLSCACert, "tls.cacert", "", "CA certificate for client side TLS handshake for GRPC")
+
+ rootCmd.PersistentFlags().StringSliceVar(&cfg.API, "http.api", []string{"eth", "erigon"}, "API's offered over the RPC interface: eth,erigon,web3,net,debug,trace,txpool,db. Supported methods: https://github.com/ledgerwatch/erigon/tree/devel/cmd/rpcdaemon")
rootCmd.PersistentFlags().BoolVar(&cfg.HttpServerEnabled, "http.enabled", true, "enable http server")
+ rootCmd.PersistentFlags().StringVar(&cfg.HttpListenAddress, "http.addr", nodecfg.DefaultHTTPHost, "HTTP server listening interface")
+ rootCmd.PersistentFlags().IntVar(&cfg.HttpPort, "http.port", nodecfg.DefaultHTTPPort, "HTTP server listening port")
rootCmd.PersistentFlags().StringVar(&cfg.HttpURL, "http.url", "", "HTTP server listening url. will OVERRIDE http.addr and http.port. will NOT respect http paths. prefix supported are tcp, unix")
- rootCmd.PersistentFlags().IntVar(&cfg.HttpPort, "http.port", nodecfg.DefaultHTTPPort, "HTTP-RPC server listening port")
rootCmd.PersistentFlags().StringSliceVar(&cfg.HttpCORSDomain, "http.corsdomain", []string{}, "Comma separated list of domains from which to accept cross origin requests (browser enforced)")
rootCmd.PersistentFlags().StringSliceVar(&cfg.HttpVirtualHost, "http.vhosts", nodecfg.DefaultConfig.HTTPVirtualHosts, "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.")
rootCmd.PersistentFlags().BoolVar(&cfg.HttpCompression, "http.compression", true, "Disable http compression")
- rootCmd.PersistentFlags().StringSliceVar(&cfg.API, "http.api", []string{"eth", "erigon"}, "API's offered over the HTTP-RPC interface: eth,erigon,web3,net,debug,trace,txpool,db. Supported methods: https://github.com/ledgerwatch/erigon/tree/devel/cmd/rpcdaemon")
- rootCmd.PersistentFlags().BoolVar(&cfg.WebsocketEnabled, "ws", false, "Enable Websockets - Same port as HTTP")
+ rootCmd.PersistentFlags().BoolVar(&cfg.WebsocketEnabled, "ws", false, "Enable Websockets - Same port as HTTP[S]")
rootCmd.PersistentFlags().BoolVar(&cfg.WebsocketCompression, "ws.compression", false, "Enable Websocket compression (RFC 7692)")
+ rootCmd.PersistentFlags().BoolVar(&cfg.HttpsServerEnabled, "https.enabled", false, "enable http server")
+ rootCmd.PersistentFlags().StringVar(&cfg.HttpsListenAddress, "https.addr", nodecfg.DefaultHTTPHost, "rpc HTTPS server listening interface")
+ rootCmd.PersistentFlags().IntVar(&cfg.HttpsPort, "https.port", nodecfg.DefaultHTTPPort+363, "rpc HTTPS server listening port")
+ rootCmd.PersistentFlags().StringVar(&cfg.HttpsURL, "https.url", "", "rpc HTTPS server listening url. will OVERRIDE https.addr and https.port. will NOT respect paths. prefix supported are tcp, unix")
+ rootCmd.PersistentFlags().StringVar(&cfg.HttpsCertfile, "https.cert", "", "certificate for rpc HTTPS server")
+ rootCmd.PersistentFlags().StringVar(&cfg.HttpsKeyFile, "https.key", "", "key file for rpc HTTPS server")
+
rootCmd.PersistentFlags().BoolVar(&cfg.SocketServerEnabled, "socket.enabled", false, "Enable IPC server")
rootCmd.PersistentFlags().StringVar(&cfg.SocketListenUrl, "socket.url", "unix:///var/run/erigon.sock", "IPC server listening url. prefix supported are tcp, unix")
@@ -610,24 +618,25 @@ func startRegularRpcServer(ctx context.Context, cfg httpcfg.HttpCfg, rpcAPI []rp
logger.Info("Socket Endpoint opened", "url", socketUrl)
}
- if cfg.HttpServerEnabled {
- httpHandler := node.NewHTTPHandlerStack(srv, cfg.HttpCORSDomain, cfg.HttpVirtualHost, cfg.HttpCompression)
- var wsHandler http.Handler
- if cfg.WebsocketEnabled {
- wsHandler = srv.WebsocketHandler([]string{"*"}, nil, cfg.WebsocketCompression, logger)
- }
-
- graphQLHandler := graphql.CreateHandler(defaultAPIList)
+ httpHandler := node.NewHTTPHandlerStack(srv, cfg.HttpCORSDomain, cfg.HttpVirtualHost, cfg.HttpCompression)
+ var wsHandler http.Handler
+ if cfg.WebsocketEnabled {
+ wsHandler = srv.WebsocketHandler([]string{"*"}, nil, cfg.WebsocketCompression, logger)
+ }
+ graphQLHandler := graphql.CreateHandler(defaultAPIList)
+ apiHandler, err := createHandler(cfg, defaultAPIList, httpHandler, wsHandler, graphQLHandler, nil)
+ if err != nil {
+ return err
+ }
- apiHandler, err := createHandler(cfg, defaultAPIList, httpHandler, wsHandler, graphQLHandler, nil)
- if err != nil {
- return err
- }
+ if cfg.HttpServerEnabled {
httpEndpoint := fmt.Sprintf("tcp://%s:%d", cfg.HttpListenAddress, cfg.HttpPort)
if cfg.HttpURL != "" {
httpEndpoint = cfg.HttpURL
}
- listener, httpAddr, err := node.StartHTTPEndpoint(httpEndpoint, cfg.HTTPTimeouts, apiHandler)
+ listener, httpAddr, err := node.StartHTTPEndpoint(httpEndpoint, &node.HttpEndpointConfig{
+ Timeouts: cfg.HTTPTimeouts,
+ }, apiHandler)
if err != nil {
return fmt.Errorf("could not start RPC api: %w", err)
}
@@ -639,6 +648,31 @@ func startRegularRpcServer(ctx context.Context, cfg httpcfg.HttpCfg, rpcAPI []rp
logger.Info("HTTP endpoint closed", "url", httpAddr)
}()
}
+ if cfg.HttpsURL != "" {
+ cfg.HttpsServerEnabled = true
+ }
+ if cfg.HttpsServerEnabled {
+ httpsEndpoint := fmt.Sprintf("tcp://%s:%d", cfg.HttpsListenAddress, cfg.HttpsPort)
+ if cfg.HttpsURL != "" {
+ httpsEndpoint = cfg.HttpsURL
+ }
+ listener, httpAddr, err := node.StartHTTPEndpoint(httpsEndpoint, &node.HttpEndpointConfig{
+ Timeouts: cfg.HTTPTimeouts,
+ HTTPS: true,
+ CertFile: cfg.HttpsCertfile,
+ KeyFile: cfg.HttpsKeyFile,
+ }, apiHandler)
+ if err != nil {
+ return fmt.Errorf("could not start RPC api: %w", err)
+ }
+ info = append(info, "https.url", httpAddr)
+ defer func() {
+ shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+ defer cancel()
+ _ = listener.Shutdown(shutdownCtx)
+ logger.Info("HTTPS endpoint closed", "url", httpAddr)
+ }()
+ }
var (
healthServer *grpcHealth.Server
@@ -797,7 +831,9 @@ func createEngineListener(cfg httpcfg.HttpCfg, engineApi []rpc.API, logger log.L
return nil, nil, "", err
}
- engineListener, engineAddr, err := node.StartHTTPEndpoint(engineHttpEndpoint, cfg.AuthRpcTimeouts, engineApiHandler)
+ engineListener, engineAddr, err := node.StartHTTPEndpoint(engineHttpEndpoint, &node.HttpEndpointConfig{
+ Timeouts: cfg.AuthRpcTimeouts,
+ }, engineApiHandler)
if err != nil {
return nil, nil, "", fmt.Errorf("could not start RPC api: %w", err)
}
diff --git a/cmd/rpcdaemon/cli/httpcfg/http_cfg.go b/cmd/rpcdaemon/cli/httpcfg/http_cfg.go
index 408d3f82d90..b2b2a99d091 100644
--- a/cmd/rpcdaemon/cli/httpcfg/http_cfg.go
+++ b/cmd/rpcdaemon/cli/httpcfg/http_cfg.go
@@ -30,6 +30,13 @@ type HttpCfg struct {
AuthRpcVirtualHost []string
HttpCompression bool
+ HttpsServerEnabled bool
+ HttpsURL string
+ HttpsListenAddress string
+ HttpsPort int
+ HttpsCertfile string
+ HttpsKeyFile string
+
AuthRpcPort int
PrivateApiAddr string
diff --git a/node/endpoints.go b/node/endpoints.go
index 8ca2e1696a2..5a2a1051735 100644
--- a/node/endpoints.go
+++ b/node/endpoints.go
@@ -29,10 +29,73 @@ import (
"github.com/ledgerwatch/erigon/rpc"
"github.com/ledgerwatch/erigon/rpc/rpccfg"
"github.com/ledgerwatch/log/v3"
+ "golang.org/x/net/http2"
+ "golang.org/x/net/http2/h2c"
)
+type HttpEndpointConfig struct {
+ Timeouts rpccfg.HTTPTimeouts
+ HTTPS bool
+ CertFile string
+ KeyFile string
+}
+
+// StartHTTPEndpoint starts the HTTP RPC endpoint.
+func StartHTTPEndpoint(urlEndpoint string, cfg *HttpEndpointConfig, handler http.Handler) (*http.Server, net.Addr, error) {
+ // start the HTTP listener
+ var (
+ listener net.Listener
+ err error
+ )
+ socketUrl, err := url.Parse(urlEndpoint)
+ if err != nil {
+ return nil, nil, fmt.Errorf("malformatted http listen url %s: %w", urlEndpoint, err)
+ }
+ if listener, err = net.Listen(socketUrl.Scheme, socketUrl.Host+socketUrl.EscapedPath()); err != nil {
+ return nil, nil, err
+ }
+ // make sure timeout values are meaningful
+ CheckTimeouts(&cfg.Timeouts)
+ // create the http2 server for handling h2c
+ h2 := &http2.Server{}
+ // enable h2c support
+ handler = h2c.NewHandler(handler, h2)
+ // Bundle the http server
+ httpSrv := &http.Server{
+ Handler: handler,
+ ReadTimeout: cfg.Timeouts.ReadTimeout,
+ WriteTimeout: cfg.Timeouts.WriteTimeout,
+ IdleTimeout: cfg.Timeouts.IdleTimeout,
+ ReadHeaderTimeout: cfg.Timeouts.ReadTimeout,
+ }
+ // start the HTTP server
+ go func() {
+ var serveErr error
+ if cfg.HTTPS {
+ serveErr = httpSrv.ServeTLS(listener, cfg.CertFile, cfg.KeyFile)
+ if serveErr != nil && !isIgnoredHttpServerError(serveErr) {
+ log.Warn("Failed to serve https endpoint", "err", serveErr)
+ }
+ } else {
+ serveErr = httpSrv.Serve(listener)
+ if serveErr != nil && !isIgnoredHttpServerError(serveErr) {
+ log.Warn("Failed to serve http endpoint", "err", serveErr)
+ }
+ }
+ }()
+ return httpSrv, listener.Addr(), err
+}
+
+func isIgnoredHttpServerError(serveErr error) bool {
+ return (errors.Is(serveErr, context.Canceled) || errors.Is(serveErr, libcommon.ErrStopped) || errors.Is(serveErr, http.ErrServerClosed))
+
+}
+
// StartHTTPEndpoint starts the HTTP RPC endpoint.
-func StartHTTPEndpoint(urlEndpoint string, timeouts rpccfg.HTTPTimeouts, handler http.Handler) (*http.Server, net.Addr, error) {
+func StartHTTPSEndpoint(urlEndpoint string,
+ keyFile string, certFile string,
+ timeouts rpccfg.HTTPTimeouts, handler http.Handler,
+) (*http.Server, net.Addr, error) {
// start the HTTP listener
var (
listener net.Listener
@@ -47,7 +110,11 @@ func StartHTTPEndpoint(urlEndpoint string, timeouts rpccfg.HTTPTimeouts, handler
}
// make sure timeout values are meaningful
CheckTimeouts(&timeouts)
- // Bundle and start the HTTP server
+ // create the http2 server for handling h2c
+ h2 := &http2.Server{}
+ // enable h2c support
+ handler = h2c.NewHandler(handler, h2)
+ // Bundle the http server
httpSrv := &http.Server{
Handler: handler,
ReadTimeout: timeouts.ReadTimeout,
@@ -55,8 +122,9 @@ func StartHTTPEndpoint(urlEndpoint string, timeouts rpccfg.HTTPTimeouts, handler
IdleTimeout: timeouts.IdleTimeout,
ReadHeaderTimeout: timeouts.ReadTimeout,
}
+ // start the HTTP server
go func() {
- serveErr := httpSrv.Serve(listener)
+ serveErr := httpSrv.ServeTLS(listener, certFile, keyFile)
if serveErr != nil &&
!(errors.Is(serveErr, context.Canceled) || errors.Is(serveErr, libcommon.ErrStopped) || errors.Is(serveErr, http.ErrServerClosed)) {
log.Warn("Failed to serve http endpoint", "err", serveErr)
From b3b38a37dda37df45a5e8c26445a2c67dcd0681a Mon Sep 17 00:00:00 2001
From: a
Date: Sun, 29 Oct 2023 19:22:17 -0500
Subject: [PATCH 2/5] Set port
---
cmd/rpcdaemon/cli/config.go | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/cmd/rpcdaemon/cli/config.go b/cmd/rpcdaemon/cli/config.go
index 35a86cb1cdf..614287a639e 100644
--- a/cmd/rpcdaemon/cli/config.go
+++ b/cmd/rpcdaemon/cli/config.go
@@ -124,7 +124,7 @@ func RootCommand() (*cobra.Command, *httpcfg.HttpCfg) {
rootCmd.PersistentFlags().BoolVar(&cfg.HttpsServerEnabled, "https.enabled", false, "enable http server")
rootCmd.PersistentFlags().StringVar(&cfg.HttpsListenAddress, "https.addr", nodecfg.DefaultHTTPHost, "rpc HTTPS server listening interface")
- rootCmd.PersistentFlags().IntVar(&cfg.HttpsPort, "https.port", nodecfg.DefaultHTTPPort+363, "rpc HTTPS server listening port")
+ rootCmd.PersistentFlags().IntVar(&cfg.HttpsPort, "https.port", 0, "rpc HTTPS server listening port. default to http+363 if not set")
rootCmd.PersistentFlags().StringVar(&cfg.HttpsURL, "https.url", "", "rpc HTTPS server listening url. will OVERRIDE https.addr and https.port. will NOT respect paths. prefix supported are tcp, unix")
rootCmd.PersistentFlags().StringVar(&cfg.HttpsCertfile, "https.cert", "", "certificate for rpc HTTPS server")
rootCmd.PersistentFlags().StringVar(&cfg.HttpsKeyFile, "https.key", "", "key file for rpc HTTPS server")
@@ -652,6 +652,9 @@ func startRegularRpcServer(ctx context.Context, cfg httpcfg.HttpCfg, rpcAPI []rp
cfg.HttpsServerEnabled = true
}
if cfg.HttpsServerEnabled {
+ if cfg.HttpsPort == 0 {
+ cfg.HttpsPort = cfg.HttpPort + 363
+ }
httpsEndpoint := fmt.Sprintf("tcp://%s:%d", cfg.HttpsListenAddress, cfg.HttpsPort)
if cfg.HttpsURL != "" {
httpsEndpoint = cfg.HttpsURL
From 8dd0d0913f24a33ffce6d7fde202b0a1266b7a9a Mon Sep 17 00:00:00 2001
From: a
Date: Sun, 29 Oct 2023 19:53:47 -0500
Subject: [PATCH 3/5] add readme blurb
---
cmd/rpcdaemon/README.md | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/cmd/rpcdaemon/README.md b/cmd/rpcdaemon/README.md
index 5ee769e25a8..7a275d2ac5b 100644
--- a/cmd/rpcdaemon/README.md
+++ b/cmd/rpcdaemon/README.md
@@ -194,6 +194,20 @@ If the `--http.url` flag is set, then `--http.addr` and `--http.port` with both
note that this is NOT geth-style IPC. for that, read the next section, IPC endpoint(geth-compatible)
+
+### HTTPS, HTTP2, and H2C
+
+Erigon supports HTTPS, HTTP2, and H2C out of the box. H2C is served by the default HTTP handler.
+
+To enable the HTTPS+HTTP2 server, add flag `--https.enabled`, along with providing flags `-https.cert="/path/to.cert"` and `--https.key=/path/to.key`
+
+By default, the HTTPS server will run on the HTTP port + 363. use flag `--https.port` to set the port
+
+The HTTPS server will inherit all other configuration parameters from http, for instance, enabling the websocket server, cors domains, or enabled namespaces
+
+If the `--https.url` flag is set, then `--https.addr` and `--https.port` with both be ignored.
+
+
### IPC endpoint (geth compatible)
erigon supports the geth-style unix socket IPC. you can enable this with `--socket.enabled` flag,
@@ -266,7 +280,7 @@ The following table shows the current implementation status of Erigon's RPC daem
| eth_getFilterChanges | Yes | |
| eth_uninstallFilter | Yes | |
| eth_getLogs | Yes | |
-| | | |
+| interned spe | | |
| eth_accounts | No | deprecated |
| eth_sendRawTransaction | Yes | `remote`. |
| eth_sendTransaction | - | not yet implemented |
From 4ea67cfe7c522f5efcb76a41dd3d552c23cf563f Mon Sep 17 00:00:00 2001
From: a
Date: Mon, 30 Oct 2023 19:19:49 -0500
Subject: [PATCH 4/5] add enable flag to main erigon binary
---
cmd/utils/flags.go | 7 ++++++-
turbo/cli/flags.go | 8 +++++---
2 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 95ccca55945..e1e1164b0e0 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -305,7 +305,12 @@ var (
}
HTTPEnabledFlag = cli.BoolFlag{
Name: "http",
- Usage: "HTTP-RPC server (enabled by default). Use --http=false to disable it",
+ Usage: "JSON-RPC server (enabled by default). Use --http=false to disable it",
+ Value: true,
+ }
+ HTTPServerEnabledFlag = cli.BoolFlag{
+ Name: "http.enabled",
+ Usage: "JSON-RPC HTTP server (enabled by default). Use --http.enabled=false to disable it",
Value: true,
}
HTTPListenAddrFlag = cli.StringFlag{
diff --git a/turbo/cli/flags.go b/turbo/cli/flags.go
index 43a903f0ad5..80bd6210f42 100644
--- a/turbo/cli/flags.go
+++ b/turbo/cli/flags.go
@@ -2,9 +2,10 @@ package cli
import (
"fmt"
- "github.com/ledgerwatch/erigon-lib/common/hexutil"
"time"
+ "github.com/ledgerwatch/erigon-lib/common/hexutil"
+
"github.com/ledgerwatch/erigon-lib/txpool/txpoolcfg"
libcommon "github.com/ledgerwatch/erigon-lib/common"
@@ -356,8 +357,9 @@ func setEmbeddedRpcDaemon(ctx *cli.Context, cfg *nodecfg.Config, logger log.Logg
logger.Info("starting HTTP APIs", "APIs", apis)
c := &httpcfg.HttpCfg{
- Enabled: ctx.Bool(utils.HTTPEnabledFlag.Name),
- Dirs: cfg.Dirs,
+ Enabled: ctx.Bool(utils.HTTPEnabledFlag.Name),
+ HttpServerEnabled: ctx.Bool(utils.HTTPServerEnabledFlag.Name),
+ Dirs: cfg.Dirs,
TLSKeyFile: cfg.TLSKeyFile,
TLSCACert: cfg.TLSCACert,
From 8f5e9e11cbc56fae80fec91d100691d04051200a Mon Sep 17 00:00:00 2001
From: a
Date: Tue, 31 Oct 2023 03:22:26 -0500
Subject: [PATCH 5/5] ok maybe second time is the charm
---
turbo/cli/default_flags.go | 1 +
1 file changed, 1 insertion(+)
diff --git a/turbo/cli/default_flags.go b/turbo/cli/default_flags.go
index 40fad68e151..978b96d974b 100644
--- a/turbo/cli/default_flags.go
+++ b/turbo/cli/default_flags.go
@@ -51,6 +51,7 @@ var DefaultFlags = []cli.Flag{
&BadBlockFlag,
&utils.HTTPEnabledFlag,
+ &utils.HTTPServerEnabledFlag,
&utils.GraphQLEnabledFlag,
&utils.HTTPListenAddrFlag,
&utils.HTTPPortFlag,