config.go 11.2 KB
Newer Older
1 2 3 4 5 6 7 8 9
package batchsubmitter

import (
	"errors"
	"time"

	"github.com/ethereum/go-ethereum/log"
	"github.com/urfave/cli"

10
	"github.com/ethereum-optimism/optimism/batch-submitter/flags"
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
)

var (
	// ErrSequencerPrivKeyOrMnemonic signals that the user tried to set both
	// sequencer wallet derivation methods or neither of them.
	ErrSequencerPrivKeyOrMnemonic = errors.New("either sequencer-private-key " +
		"or mnemonic + sequencer-hd-path must be set")

	// ErrProposererPrivKeyOrMnemonic signals that the user tried to set
	// both proposer wallet derivation methods or neither of them.
	ErrProposerPrivKeyOrMnemonic = errors.New("either proposer-private-key " +
		"or mnemonic + proposer-hd-path must be set")

	// ErrSameSequencerAndProposerHDPath signals that the user specified the
	// same sequencer and proposer derivations paths, which otherwise would
	// lead to the two using the same wallet.
	ErrSameSequencerAndProposerHDPath = errors.New("sequencer-hd-path and " +
		"proposer-hd-path must be distinct when using mnemonic")

	// ErrSameSequencerAndProposerPrivKey signals that the user specified
	// the same sequencer and proposer private keys, which otherwise would
	// lead to the two using the same wallet.
	ErrSameSequencerAndProposerPrivKey = errors.New("sequencer-priv-key and " +
		"proposer-priv-key must be distinct")

36 37 38 39 40
	// ErrInvalidBatchType  signals that an unsupported batch type is being
	// configured. The default is "legacy" and the options are "legacy" or
	// "zlib"
	ErrInvalidBatchType = errors.New("invalid batch type")

41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
	// ErrSentryDSNNotSet signals that not Data Source Name was provided
	// with which to configure Sentry logging.
	ErrSentryDSNNotSet = errors.New("sentry-dsn must be set if use-sentry " +
		"is true")
)

type Config struct {
	/* Required Params */

	// BuildEnv identifies the environment this binary is intended for, i.e.
	// production, development, etc.
	BuildEnv string

	// EthNetworkName identifies the intended Ethereum network.
	EthNetworkName string

	// L1EthRpc is the HTTP provider URL for L1.
	L1EthRpc string

	// L2EthRpc is the HTTP provider URL for L1.
	L2EthRpc string

	// CTCAddress is the CTC contract address.
	CTCAddress string

	// SCCAddress is the SCC contract address.
	SCCAddress string

	// MinL1TxSize is the minimum size in bytes of any L1 transactions generated
	// by the batch submitter.
	MinL1TxSize uint64

	// MaxL1TxSize is the maximum size in bytes of any L1 transactions generated
	// by the batch submitter.
	MaxL1TxSize uint64

77 78 79 80
	// MaxPlaintextL1TxSize is the maximum size in bytes of the plaintext tx
	// data encoded in batches.
	MaxPlaintextBatchSize uint64

81 82 83 84 85 86 87 88
	// MinStateRootElements is the minimum number of state root elements that
	// can be submitted in single proposer batch.
	MinStateRootElements uint64

	// MaxStateRootElements is the maximum number of state root elements that
	// can be submitted in single proposer batch.
	MaxStateRootElements uint64

89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
	// MaxTxBatchCount is the maximum number of L2 transactions that can ever be
	// in a batch.
	MaxTxBatchCount uint64

	// MaxBatchSubmissionTime is the maximum amount of time that we will
	// wait before submitting an under-sized batch.
	MaxBatchSubmissionTime time.Duration

	// PollInterval is the delay between querying L2 for more transaction
	// and creating a new batch.
	PollInterval time.Duration

	// NumConfirmations is the number of confirmations which we will wait after
	// appending new batches.
	NumConfirmations uint64

105 106 107 108 109
	// SafeAbortNonceTooLowCount is the number of ErrNonceTooLowObservations
	// required to give up on a tx at a particular nonce without receiving
	// confirmation.
	SafeAbortNonceTooLowCount uint64

110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
	// ResubmissionTimeout is time we will wait before resubmitting a
	// transaction.
	ResubmissionTimeout time.Duration

	// FinalityConfirmations is the number of confirmations that we should wait
	// before submitting state roots for CTC elements.
	FinalityConfirmations uint64

	// RunTxBatchSubmitter determines whether or not to run the tx batch
	// submitter.
	RunTxBatchSubmitter bool

	// RunStateBatchSubmitter determines whether or not to run the state batch
	// submitter.
	RunStateBatchSubmitter bool

	//SafeMinimumEtherBalance is the safe minimum amount of ether the batch
	//submitter key should hold before it starts to log errors.
	SafeMinimumEtherBalance uint64

	// ClearPendingTxs is a boolean to clear the pending transactions in the
	// mempool on startup.
	ClearPendingTxs bool

	/* Optional Params */

	// LogLevel is the lowest log level that will be output.
	LogLevel string

139 140 141 142 143
	// LogTerminal if true, prints to stdout in terminal format, otherwise
	// prints using JSON. If SentryEnable is true this flag is ignored, and logs
	// are printed using JSON.
	LogTerminal bool

144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
	// SentryEnable if true, logs any error messages to sentry. SentryDsn
	// must also be set if SentryEnable is true.
	SentryEnable bool

	// SentryDsn is the sentry Data Source Name.
	SentryDsn string

	// SentryTraceRate the frequency with which Sentry should flush buffered
	// events.
	SentryTraceRate time.Duration

	// BlockOffset is the offset between the CTC contract start and the L2 geth
	// blocks.
	BlockOffset uint64

	// SequencerPrivateKey the private key of the wallet used to submit
	// transactions to the CTC contract.
	SequencerPrivateKey string

	// PropopserPrivateKey the private key of the wallet used to submit
	// transaction to the SCC contract.
	ProposerPrivateKey string

	// Mnemonic is the HD seed used to derive the wallet private keys for both
	// the sequence and proposer. Must be used in conjunction with
	// SequencerHDPath and ProposerHDPath.
	Mnemonic string

	// SequencerHDPath is the derivation path used to obtain the private key for
	// the sequencer transactions.
	SequencerHDPath string

	// ProposerHDPath is the derivation path used to obtain the private key for
	// the proposer transactions.
	ProposerHDPath string

180 181 182
	// SequencerBatchType represents the type of batch the sequencer submits.
	SequencerBatchType string

183 184 185 186 187 188 189 190 191
	// MetricsServerEnable if true, will create a metrics client and log to
	// Prometheus.
	MetricsServerEnable bool

	// MetricsHostname is the hostname at which the metrics server is running.
	MetricsHostname string

	// MetricsPort is the port at which the metrics server is running.
	MetricsPort uint64
192 193 194

	// DisableHTTP2 disables HTTP2 support.
	DisableHTTP2 bool
195 196 197 198 199 200 201
}

// NewConfig parses the Config from the provided flags or environment variables.
// This method fails if ValidateConfig deems the configuration to be malformed.
func NewConfig(ctx *cli.Context) (Config, error) {
	cfg := Config{
		/* Required Flags */
202 203 204 205 206 207
		BuildEnv:                  ctx.GlobalString(flags.BuildEnvFlag.Name),
		EthNetworkName:            ctx.GlobalString(flags.EthNetworkNameFlag.Name),
		L1EthRpc:                  ctx.GlobalString(flags.L1EthRpcFlag.Name),
		L2EthRpc:                  ctx.GlobalString(flags.L2EthRpcFlag.Name),
		CTCAddress:                ctx.GlobalString(flags.CTCAddressFlag.Name),
		SCCAddress:                ctx.GlobalString(flags.SCCAddressFlag.Name),
208
		MinL1TxSize:               ctx.GlobalUint64(flags.MinL1TxSizeFlag.Name),
209
		MaxL1TxSize:               ctx.GlobalUint64(flags.MaxL1TxSizeFlag.Name),
210
		MaxPlaintextBatchSize:     ctx.GlobalUint64(flags.MaxPlaintextBatchSizeFlag.Name),
211 212
		MinStateRootElements:      ctx.GlobalUint64(flags.MinStateRootElementsFlag.Name),
		MaxStateRootElements:      ctx.GlobalUint64(flags.MinStateRootElementsFlag.Name),
213 214 215 216 217 218 219 220 221 222
		MaxBatchSubmissionTime:    ctx.GlobalDuration(flags.MaxBatchSubmissionTimeFlag.Name),
		PollInterval:              ctx.GlobalDuration(flags.PollIntervalFlag.Name),
		NumConfirmations:          ctx.GlobalUint64(flags.NumConfirmationsFlag.Name),
		SafeAbortNonceTooLowCount: ctx.GlobalUint64(flags.SafeAbortNonceTooLowCountFlag.Name),
		ResubmissionTimeout:       ctx.GlobalDuration(flags.ResubmissionTimeoutFlag.Name),
		FinalityConfirmations:     ctx.GlobalUint64(flags.FinalityConfirmationsFlag.Name),
		RunTxBatchSubmitter:       ctx.GlobalBool(flags.RunTxBatchSubmitterFlag.Name),
		RunStateBatchSubmitter:    ctx.GlobalBool(flags.RunStateBatchSubmitterFlag.Name),
		SafeMinimumEtherBalance:   ctx.GlobalUint64(flags.SafeMinimumEtherBalanceFlag.Name),
		ClearPendingTxs:           ctx.GlobalBool(flags.ClearPendingTxsFlag.Name),
223
		/* Optional Flags */
224
		LogLevel:            ctx.GlobalString(flags.LogLevelFlag.Name),
225
		LogTerminal:         ctx.GlobalBool(flags.LogTerminalFlag.Name),
226 227 228 229 230 231 232 233 234
		SentryEnable:        ctx.GlobalBool(flags.SentryEnableFlag.Name),
		SentryDsn:           ctx.GlobalString(flags.SentryDsnFlag.Name),
		SentryTraceRate:     ctx.GlobalDuration(flags.SentryTraceRateFlag.Name),
		BlockOffset:         ctx.GlobalUint64(flags.BlockOffsetFlag.Name),
		SequencerPrivateKey: ctx.GlobalString(flags.SequencerPrivateKeyFlag.Name),
		ProposerPrivateKey:  ctx.GlobalString(flags.ProposerPrivateKeyFlag.Name),
		Mnemonic:            ctx.GlobalString(flags.MnemonicFlag.Name),
		SequencerHDPath:     ctx.GlobalString(flags.SequencerHDPathFlag.Name),
		ProposerHDPath:      ctx.GlobalString(flags.ProposerHDPathFlag.Name),
235
		SequencerBatchType:  ctx.GlobalString(flags.SequencerBatchType.Name),
236 237 238
		MetricsServerEnable: ctx.GlobalBool(flags.MetricsServerEnableFlag.Name),
		MetricsHostname:     ctx.GlobalString(flags.MetricsHostnameFlag.Name),
		MetricsPort:         ctx.GlobalUint64(flags.MetricsPortFlag.Name),
239
		DisableHTTP2:        ctx.GlobalBool(flags.HTTP2DisableFlag.Name),
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
	}

	err := ValidateConfig(&cfg)
	if err != nil {
		return Config{}, err
	}

	return cfg, nil
}

// ValidateConfig ensures additional constraints on the parsed configuration to
// ensure that it is well-formed.
func ValidateConfig(cfg *Config) error {
	// Sanity check log level.
	_, err := log.LvlFromString(cfg.LogLevel)
	if err != nil {
		return err
	}

	// Enforce that either sequencer-private-key or mnemonic + sequencer-hd-path
	// is enabled, but not both or neither.
	usingSequencerPrivateKey := cfg.SequencerPrivateKey != ""
	usingSequencerHDPath := cfg.Mnemonic != "" && cfg.SequencerHDPath != ""
	if usingSequencerPrivateKey == usingSequencerHDPath {
		return ErrSequencerPrivKeyOrMnemonic
	}

	// Enforce that either proposer-private-key or mnemonic + proposer-hd-path
	// is enabled, but not both or neither.
	usingProposerPrivateKey := cfg.ProposerPrivateKey != ""
	usingProposerHDPath := cfg.Mnemonic != "" && cfg.ProposerHDPath != ""
	if usingProposerPrivateKey == usingProposerHDPath {
		return ErrProposerPrivKeyOrMnemonic
	}

	// If mnemonic is used, the sequencer-hd-path and proposer-hd-path must
	// differ to avoid resuing the same wallet for both.
	if cfg.Mnemonic != "" && cfg.SequencerHDPath == cfg.ProposerHDPath {
		return ErrSameSequencerAndProposerHDPath
	}

	// If private keys are used, ensure the keys are different to avoid resuing
	// the same wallet for both.
	if usingSequencerPrivateKey && usingProposerPrivateKey &&
		cfg.SequencerPrivateKey == cfg.ProposerPrivateKey {

		return ErrSameSequencerAndProposerPrivKey
	}

289 290 291 292 293 294
	usingTypedBatches := cfg.SequencerBatchType != ""
	validBatchType := cfg.SequencerBatchType == "legacy" || cfg.SequencerBatchType == "zlib"
	if usingTypedBatches && !validBatchType {
		return ErrInvalidBatchType
	}

295 296 297 298 299 300 301
	// Ensure the Sentry Data Source Name is set when using Sentry.
	if cfg.SentryEnable && cfg.SentryDsn == "" {
		return ErrSentryDSNNotSet
	}

	return nil
}