From 5905f3dc59a7f062a63742c89b37973cea4daa86 Mon Sep 17 00:00:00 2001 From: Matthew Slipper Date: Tue, 25 Jan 2022 15:45:12 -0700 Subject: [PATCH] go/batch-submitter: HTTP/2 fixes The built-in geth client has a bugger implementation of HTTP/2: https://github.com/ethereum/go-ethereum/pull/24292. Additionally, Go 1.17 has better HTTP/2 support than Go 1.15. This PR updates the BSS to use Go 1.17 in built binaries, and adds a flag to disable HTTP/2 support if necessary. --- .changeset/empty-coats-beam.md | 5 ++ go/batch-submitter/batch_submitter.go | 46 +++++++++++++++++-- go/batch-submitter/config.go | 4 ++ go/batch-submitter/flags/flags.go | 6 +++ ops/docker/Dockerfile.batch-submitter-service | 4 +- 5 files changed, 59 insertions(+), 6 deletions(-) create mode 100644 .changeset/empty-coats-beam.md diff --git a/.changeset/empty-coats-beam.md b/.changeset/empty-coats-beam.md new file mode 100644 index 000000000000..9bec2a66e441 --- /dev/null +++ b/.changeset/empty-coats-beam.md @@ -0,0 +1,5 @@ +--- +'@eth-optimism/batch-submitter-service': patch +--- + +Update golang version to support HTTP/2 diff --git a/go/batch-submitter/batch_submitter.go b/go/batch-submitter/batch_submitter.go index a27c898aa4a5..862c4cc27430 100644 --- a/go/batch-submitter/batch_submitter.go +++ b/go/batch-submitter/batch_submitter.go @@ -3,10 +3,13 @@ package batchsubmitter import ( "context" "crypto/ecdsa" + "crypto/tls" "fmt" + "github.com/ethereum/go-ethereum/rpc" "net/http" "os" "strconv" + "strings" "time" "github.com/ethereum-optimism/optimism/go/batch-submitter/drivers/proposer" @@ -14,6 +17,7 @@ import ( "github.com/ethereum-optimism/optimism/go/batch-submitter/txmgr" "github.com/ethereum-optimism/optimism/go/batch-submitter/utils" l2ethclient "github.com/ethereum-optimism/optimism/l2geth/ethclient" + l2rpc "github.com/ethereum-optimism/optimism/l2geth/rpc" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" @@ -139,12 +143,12 @@ func NewBatchSubmitter(cfg Config, gitVersion string) (*BatchSubmitter, error) { // Connect to L1 and L2 providers. Perform these last since they are the // most expensive. - l1Client, err := dialL1EthClientWithTimeout(ctx, cfg.L1EthRpc) + l1Client, err := dialL1EthClientWithTimeout(ctx, cfg.L1EthRpc, cfg.DisableHTTP2) if err != nil { return nil, err } - l2Client, err := dialL2EthClientWithTimeout(ctx, cfg.L2EthRpc) + l2Client, err := dialL2EthClientWithTimeout(ctx, cfg.L2EthRpc, cfg.DisableHTTP2) if err != nil { return nil, err } @@ -305,24 +309,58 @@ func runMetricsServer(hostname string, port uint64) { // dialL1EthClientWithTimeout attempts to dial the L1 provider using the // provided URL. If the dial doesn't complete within defaultDialTimeout seconds, // this method will return an error. -func dialL1EthClientWithTimeout(ctx context.Context, url string) ( +func dialL1EthClientWithTimeout(ctx context.Context, url string, disableHTTP2 bool) ( *ethclient.Client, error) { ctxt, cancel := context.WithTimeout(ctx, defaultDialTimeout) defer cancel() + if strings.HasPrefix(url, "http") { + httpClient := new(http.Client) + if disableHTTP2 { + log.Info("Disabled HTTP/2 support in L1 eth client") + httpClient.Transport = &http.Transport{ + TLSNextProto: make(map[string]func(authority string, c *tls.Conn) http.RoundTripper), + } + } + + rpcClient, err := rpc.DialHTTPWithClient(url, httpClient) + if err != nil { + return nil, err + } + + return ethclient.NewClient(rpcClient), nil + } + return ethclient.DialContext(ctxt, url) } // dialL2EthClientWithTimeout attempts to dial the L2 provider using the // provided URL. If the dial doesn't complete within defaultDialTimeout seconds, // this method will return an error. -func dialL2EthClientWithTimeout(ctx context.Context, url string) ( +func dialL2EthClientWithTimeout(ctx context.Context, url string, disableHTTP2 bool) ( *l2ethclient.Client, error) { ctxt, cancel := context.WithTimeout(ctx, defaultDialTimeout) defer cancel() + if strings.HasPrefix(url, "http") { + httpClient := new(http.Client) + if disableHTTP2 { + log.Info("Disabled HTTP/2 support in L2 eth client") + httpClient.Transport = &http.Transport{ + TLSNextProto: make(map[string]func(authority string, c *tls.Conn) http.RoundTripper), + } + } + + rpcClient, err := l2rpc.DialHTTPWithClient(url, httpClient) + if err != nil { + return nil, err + } + + return l2ethclient.NewClient(rpcClient), nil + } + return l2ethclient.DialContext(ctxt, url) } diff --git a/go/batch-submitter/config.go b/go/batch-submitter/config.go index e7efa6b7e33b..1931a387d38e 100644 --- a/go/batch-submitter/config.go +++ b/go/batch-submitter/config.go @@ -171,6 +171,9 @@ type Config struct { // MetricsPort is the port at which the metrics server is running. MetricsPort uint64 + + // DisableHTTP2 disables HTTP2 support. + DisableHTTP2 bool } // NewConfig parses the Config from the provided flags or environment variables. @@ -209,6 +212,7 @@ func NewConfig(ctx *cli.Context) (Config, error) { MetricsServerEnable: ctx.GlobalBool(flags.MetricsServerEnableFlag.Name), MetricsHostname: ctx.GlobalString(flags.MetricsHostnameFlag.Name), MetricsPort: ctx.GlobalUint64(flags.MetricsPortFlag.Name), + DisableHTTP2: ctx.GlobalBool(flags.HTTP2DisableFlag.Name), } err := ValidateConfig(&cfg) diff --git a/go/batch-submitter/flags/flags.go b/go/batch-submitter/flags/flags.go index b967c2f6bcb8..f083ed39ce6f 100644 --- a/go/batch-submitter/flags/flags.go +++ b/go/batch-submitter/flags/flags.go @@ -208,6 +208,11 @@ var ( Value: 7300, EnvVar: prefixEnvVar("METRICS_PORT"), } + HTTP2DisableFlag = cli.BoolFlag{ + Name: "http2-disable", + Usage: "Whether or not to disable HTTP/2 support.", + EnvVar: prefixEnvVar("HTTP2_DISABLE"), + } ) var requiredFlags = []cli.Flag{ @@ -245,6 +250,7 @@ var optionalFlags = []cli.Flag{ MetricsServerEnableFlag, MetricsHostnameFlag, MetricsPortFlag, + HTTP2DisableFlag, } // Flags contains the list of configuration options available to the binary. diff --git a/ops/docker/Dockerfile.batch-submitter-service b/ops/docker/Dockerfile.batch-submitter-service index 6e9555fb3516..4adc44f1db34 100644 --- a/ops/docker/Dockerfile.batch-submitter-service +++ b/ops/docker/Dockerfile.batch-submitter-service @@ -1,4 +1,4 @@ -FROM golang:1.15-alpine3.13 as builder +FROM golang:1.17.6-alpine3.15 as builder RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash @@ -9,7 +9,7 @@ RUN go mod graph | grep -v l2geth | awk '{if ($1 !~ "@") print $2}' | xargs -n 1 COPY ./go/batch-submitter/ ./ RUN make -FROM alpine:3.13 +FROM alpine:3.15 RUN apk add --no-cache ca-certificates jq curl COPY --from=builder /go/batch-submitter/batch-submitter /usr/local/bin/