batch_submitter.go 5.83 KB
Newer Older
1 2 3 4 5 6 7
package batchsubmitter

import (
	"context"
	"os"
	"time"

8 9 10 11 12 13
	"github.com/ethereum-optimism/optimism/batch-submitter/drivers/proposer"
	"github.com/ethereum-optimism/optimism/batch-submitter/drivers/sequencer"
	bsscore "github.com/ethereum-optimism/optimism/bss-core"
	"github.com/ethereum-optimism/optimism/bss-core/dial"
	"github.com/ethereum-optimism/optimism/bss-core/metrics"
	"github.com/ethereum-optimism/optimism/bss-core/txmgr"
14 15 16 17 18 19 20 21 22 23
	"github.com/ethereum/go-ethereum/log"
	"github.com/getsentry/sentry-go"
	"github.com/urfave/cli"
)

// Main is the entrypoint into the batch submitter service. This method returns
// a closure that executes the service and blocks until the service exits. The
// use of a closure allows the parameters bound to the top-level main package,
// e.g. GitVersion, to be captured and used once the function is executed.
func Main(gitVersion string) func(ctx *cli.Context) error {
24 25
	return func(cliCtx *cli.Context) error {
		cfg, err := NewConfig(cliCtx)
26 27 28 29
		if err != nil {
			return err
		}

30 31 32 33
		log.Info("Config parsed",
			"min_tx_size", cfg.MinL1TxSize,
			"max_tx_size", cfg.MaxL1TxSize)

34 35 36 37 38 39
		// The call to defer is done here so that any errors logged from
		// this point on are posted to Sentry before exiting.
		if cfg.SentryEnable {
			defer sentry.Flush(2 * time.Second)
		}

40 41
		log.Info("Initializing batch submitter")

42 43 44 45 46 47 48 49 50 51 52 53
		ctx, cancel := context.WithCancel(context.Background())
		defer cancel()

		// Set up our logging. If Sentry is enabled, we will use our custom log
		// handler that logs to stdout and forwards any error messages to Sentry
		// for collection. Otherwise, logs will only be posted to stdout.
		var logHandler log.Handler
		if cfg.SentryEnable {
			err := sentry.Init(sentry.ClientOptions{
				Dsn:              cfg.SentryDsn,
				Environment:      cfg.EthNetworkName,
				Release:          "batch-submitter@" + gitVersion,
54
				TracesSampleRate: bsscore.TraceRateToFloat64(cfg.SentryTraceRate),
55 56 57 58 59 60
				Debug:            false,
			})
			if err != nil {
				return err
			}

61 62
			logHandler = bsscore.SentryStreamHandler(os.Stdout, log.JSONFormat())
		} else if cfg.LogTerminal {
63
			logHandler = log.StreamHandler(os.Stdout, log.TerminalFormat(true))
64 65
		} else {
			logHandler = log.StreamHandler(os.Stdout, log.JSONFormat())
66 67 68 69 70 71 72 73 74 75
		}

		logLevel, err := log.LvlFromString(cfg.LogLevel)
		if err != nil {
			return err
		}

		log.Root().SetHandler(log.LvlFilterHandler(logLevel, logHandler))

		// Parse sequencer private key and CTC contract address.
76
		sequencerPrivKey, ctcAddress, err := bsscore.ParseWalletPrivKeyAndContractAddr(
77 78 79 80 81 82 83 84
			"Sequencer", cfg.Mnemonic, cfg.SequencerHDPath,
			cfg.SequencerPrivateKey, cfg.CTCAddress,
		)
		if err != nil {
			return err
		}

		// Parse proposer private key and SCC contract address.
85
		proposerPrivKey, sccAddress, err := bsscore.ParseWalletPrivKeyAndContractAddr(
86 87 88 89 90 91 92 93 94
			"Proposer", cfg.Mnemonic, cfg.ProposerHDPath,
			cfg.ProposerPrivateKey, cfg.SCCAddress,
		)
		if err != nil {
			return err
		}

		// Connect to L1 and L2 providers. Perform these last since they are the
		// most expensive.
95
		l1Client, err := dial.L1EthClientWithTimeout(ctx, cfg.L1EthRpc, cfg.DisableHTTP2)
96 97 98 99
		if err != nil {
			return err
		}

100
		l2Client, err := DialL2EthClientWithTimeout(ctx, cfg.L2EthRpc, cfg.DisableHTTP2)
101 102 103 104 105
		if err != nil {
			return err
		}

		if cfg.MetricsServerEnable {
106
			go metrics.RunServer(cfg.MetricsHostname, cfg.MetricsPort)
107 108 109 110 111 112 113 114
		}

		chainID, err := l1Client.ChainID(ctx)
		if err != nil {
			return err
		}

		txManagerConfig := txmgr.Config{
115 116 117 118
			ResubmissionTimeout:       cfg.ResubmissionTimeout,
			ReceiptQueryInterval:      time.Second,
			NumConfirmations:          cfg.NumConfirmations,
			SafeAbortNonceTooLowCount: cfg.SafeAbortNonceTooLowCount,
119 120
		}

121
		var services []*bsscore.Service
122 123
		if cfg.RunTxBatchSubmitter {
			batchTxDriver, err := sequencer.NewDriver(sequencer.Config{
124 125 126 127 128 129 130 131 132 133 134
				Name:                  "Sequencer",
				L1Client:              l1Client,
				L2Client:              l2Client,
				BlockOffset:           cfg.BlockOffset,
				MinTxSize:             cfg.MinL1TxSize,
				MaxTxSize:             cfg.MaxL1TxSize,
				MaxPlaintextBatchSize: cfg.MaxPlaintextBatchSize,
				CTCAddr:               ctcAddress,
				ChainID:               chainID,
				PrivKey:               sequencerPrivKey,
				BatchType:             sequencer.BatchTypeFromString(cfg.SequencerBatchType),
135 136 137 138 139
			})
			if err != nil {
				return err
			}

140
			services = append(services, bsscore.NewService(bsscore.ServiceConfig{
141 142 143 144 145 146 147 148 149 150 151
				Context:         ctx,
				Driver:          batchTxDriver,
				PollInterval:    cfg.PollInterval,
				ClearPendingTx:  cfg.ClearPendingTxs,
				L1Client:        l1Client,
				TxManagerConfig: txManagerConfig,
			}))
		}

		if cfg.RunStateBatchSubmitter {
			batchStateDriver, err := proposer.NewDriver(proposer.Config{
152 153 154 155 156 157 158 159 160 161
				Name:                 "Proposer",
				L1Client:             l1Client,
				L2Client:             l2Client,
				BlockOffset:          cfg.BlockOffset,
				MinStateRootElements: cfg.MinStateRootElements,
				MaxStateRootElements: cfg.MaxStateRootElements,
				SCCAddr:              sccAddress,
				CTCAddr:              ctcAddress,
				ChainID:              chainID,
				PrivKey:              proposerPrivKey,
162 163 164 165 166
			})
			if err != nil {
				return err
			}

167
			services = append(services, bsscore.NewService(bsscore.ServiceConfig{
168 169 170 171 172 173 174 175 176
				Context:         ctx,
				Driver:          batchStateDriver,
				PollInterval:    cfg.PollInterval,
				ClearPendingTx:  cfg.ClearPendingTxs,
				L1Client:        l1Client,
				TxManagerConfig: txManagerConfig,
			}))
		}

177
		batchSubmitter, err := bsscore.NewBatchSubmitter(ctx, cancel, services)
178 179 180 181 182
		if err != nil {
			log.Error("Unable to create batch submitter", "error", err)
			return err
		}

183 184 185 186 187 188 189 190 191 192 193
		log.Info("Starting batch submitter")

		if err := batchSubmitter.Start(); err != nil {
			return err
		}
		defer batchSubmitter.Stop()

		log.Info("Batch submitter started")

		<-(chan struct{})(nil)

194 195 196
		return nil
	}
}