github.com/ethereum-optimism/optimism@v1.7.2/op-node/service.go (about) 1 package opnode 2 3 import ( 4 "crypto/rand" 5 "encoding/json" 6 "errors" 7 "fmt" 8 "io" 9 "os" 10 "strings" 11 12 "github.com/ethereum-optimism/optimism/op-node/chaincfg" 13 plasma "github.com/ethereum-optimism/optimism/op-plasma" 14 "github.com/ethereum-optimism/optimism/op-service/oppprof" 15 "github.com/ethereum-optimism/optimism/op-service/sources" 16 "github.com/ethereum/go-ethereum/common" 17 "github.com/ethereum/go-ethereum/common/hexutil" 18 "github.com/ethereum/go-ethereum/log" 19 "github.com/urfave/cli/v2" 20 21 "github.com/ethereum-optimism/optimism/op-node/flags" 22 "github.com/ethereum-optimism/optimism/op-node/node" 23 p2pcli "github.com/ethereum-optimism/optimism/op-node/p2p/cli" 24 "github.com/ethereum-optimism/optimism/op-node/rollup" 25 "github.com/ethereum-optimism/optimism/op-node/rollup/driver" 26 "github.com/ethereum-optimism/optimism/op-node/rollup/sync" 27 opflags "github.com/ethereum-optimism/optimism/op-service/flags" 28 ) 29 30 // NewConfig creates a Config from the provided flags or environment variables. 31 func NewConfig(ctx *cli.Context, log log.Logger) (*node.Config, error) { 32 if err := flags.CheckRequired(ctx); err != nil { 33 return nil, err 34 } 35 36 rollupConfig, err := NewRollupConfigFromCLI(log, ctx) 37 if err != nil { 38 return nil, err 39 } 40 41 if !ctx.Bool(flags.RollupLoadProtocolVersions.Name) { 42 log.Info("Not opted in to ProtocolVersions signal loading, disabling ProtocolVersions contract now.") 43 rollupConfig.ProtocolVersionsAddress = common.Address{} 44 } 45 46 configPersistence := NewConfigPersistence(ctx) 47 48 driverConfig := NewDriverConfig(ctx) 49 50 p2pSignerSetup, err := p2pcli.LoadSignerSetup(ctx) 51 if err != nil { 52 return nil, fmt.Errorf("failed to load p2p signer: %w", err) 53 } 54 55 p2pConfig, err := p2pcli.NewConfig(ctx, rollupConfig) 56 if err != nil { 57 return nil, fmt.Errorf("failed to load p2p config: %w", err) 58 } 59 60 l1Endpoint := NewL1EndpointConfig(ctx) 61 62 l2Endpoint, err := NewL2EndpointConfig(ctx, log) 63 if err != nil { 64 return nil, fmt.Errorf("failed to load l2 endpoints info: %w", err) 65 } 66 67 syncConfig, err := NewSyncConfig(ctx, log) 68 if err != nil { 69 return nil, fmt.Errorf("failed to create the sync config: %w", err) 70 } 71 72 haltOption := ctx.String(flags.RollupHalt.Name) 73 if haltOption == "none" { 74 haltOption = "" 75 } 76 77 cfg := &node.Config{ 78 L1: l1Endpoint, 79 L2: l2Endpoint, 80 Rollup: *rollupConfig, 81 Driver: *driverConfig, 82 Beacon: NewBeaconEndpointConfig(ctx), 83 RPC: node.RPCConfig{ 84 ListenAddr: ctx.String(flags.RPCListenAddr.Name), 85 ListenPort: ctx.Int(flags.RPCListenPort.Name), 86 EnableAdmin: ctx.Bool(flags.RPCEnableAdmin.Name), 87 }, 88 Metrics: node.MetricsConfig{ 89 Enabled: ctx.Bool(flags.MetricsEnabledFlag.Name), 90 ListenAddr: ctx.String(flags.MetricsAddrFlag.Name), 91 ListenPort: ctx.Int(flags.MetricsPortFlag.Name), 92 }, 93 Pprof: oppprof.ReadCLIConfig(ctx), 94 P2P: p2pConfig, 95 P2PSigner: p2pSignerSetup, 96 L1EpochPollInterval: ctx.Duration(flags.L1EpochPollIntervalFlag.Name), 97 RuntimeConfigReloadInterval: ctx.Duration(flags.RuntimeConfigReloadIntervalFlag.Name), 98 Heartbeat: node.HeartbeatConfig{ 99 Enabled: ctx.Bool(flags.HeartbeatEnabledFlag.Name), 100 Moniker: ctx.String(flags.HeartbeatMonikerFlag.Name), 101 URL: ctx.String(flags.HeartbeatURLFlag.Name), 102 }, 103 ConfigPersistence: configPersistence, 104 SafeDBPath: ctx.String(flags.SafeDBPath.Name), 105 Sync: *syncConfig, 106 RollupHalt: haltOption, 107 RethDBPath: ctx.String(flags.L1RethDBPath.Name), 108 109 ConductorEnabled: ctx.Bool(flags.ConductorEnabledFlag.Name), 110 ConductorRpc: ctx.String(flags.ConductorRpcFlag.Name), 111 ConductorRpcTimeout: ctx.Duration(flags.ConductorRpcTimeoutFlag.Name), 112 113 Plasma: plasma.ReadCLIConfig(ctx), 114 } 115 116 if err := cfg.LoadPersisted(log); err != nil { 117 return nil, fmt.Errorf("failed to load driver config: %w", err) 118 } 119 120 // conductor controls the sequencer state 121 if cfg.ConductorEnabled { 122 cfg.Driver.SequencerStopped = true 123 } 124 125 if err := cfg.Check(); err != nil { 126 return nil, err 127 } 128 return cfg, nil 129 } 130 131 func NewBeaconEndpointConfig(ctx *cli.Context) node.L1BeaconEndpointSetup { 132 return &node.L1BeaconEndpointConfig{ 133 BeaconAddr: ctx.String(flags.BeaconAddr.Name), 134 BeaconHeader: ctx.String(flags.BeaconHeader.Name), 135 BeaconArchiverAddr: ctx.String(flags.BeaconArchiverAddr.Name), 136 BeaconCheckIgnore: ctx.Bool(flags.BeaconCheckIgnore.Name), 137 BeaconFetchAllSidecars: ctx.Bool(flags.BeaconFetchAllSidecars.Name), 138 } 139 } 140 141 func NewL1EndpointConfig(ctx *cli.Context) *node.L1EndpointConfig { 142 return &node.L1EndpointConfig{ 143 L1NodeAddr: ctx.String(flags.L1NodeAddr.Name), 144 L1TrustRPC: ctx.Bool(flags.L1TrustRPC.Name), 145 L1RPCKind: sources.RPCProviderKind(strings.ToLower(ctx.String(flags.L1RPCProviderKind.Name))), 146 RateLimit: ctx.Float64(flags.L1RPCRateLimit.Name), 147 BatchSize: ctx.Int(flags.L1RPCMaxBatchSize.Name), 148 HttpPollInterval: ctx.Duration(flags.L1HTTPPollInterval.Name), 149 MaxConcurrency: ctx.Int(flags.L1RPCMaxConcurrency.Name), 150 } 151 } 152 153 func NewL2EndpointConfig(ctx *cli.Context, log log.Logger) (*node.L2EndpointConfig, error) { 154 l2Addr := ctx.String(flags.L2EngineAddr.Name) 155 fileName := ctx.String(flags.L2EngineJWTSecret.Name) 156 var secret [32]byte 157 fileName = strings.TrimSpace(fileName) 158 if fileName == "" { 159 return nil, fmt.Errorf("file-name of jwt secret is empty") 160 } 161 if data, err := os.ReadFile(fileName); err == nil { 162 jwtSecret := common.FromHex(strings.TrimSpace(string(data))) 163 if len(jwtSecret) != 32 { 164 return nil, fmt.Errorf("invalid jwt secret in path %s, not 32 hex-formatted bytes", fileName) 165 } 166 copy(secret[:], jwtSecret) 167 } else { 168 log.Warn("Failed to read JWT secret from file, generating a new one now. Configure L2 geth with --authrpc.jwt-secret=" + fmt.Sprintf("%q", fileName)) 169 if _, err := io.ReadFull(rand.Reader, secret[:]); err != nil { 170 return nil, fmt.Errorf("failed to generate jwt secret: %w", err) 171 } 172 if err := os.WriteFile(fileName, []byte(hexutil.Encode(secret[:])), 0o600); err != nil { 173 return nil, err 174 } 175 } 176 177 return &node.L2EndpointConfig{ 178 L2EngineAddr: l2Addr, 179 L2EngineJWTSecret: secret, 180 }, nil 181 } 182 183 func NewConfigPersistence(ctx *cli.Context) node.ConfigPersistence { 184 stateFile := ctx.String(flags.RPCAdminPersistence.Name) 185 if stateFile == "" { 186 return node.DisabledConfigPersistence{} 187 } 188 return node.NewConfigPersistence(stateFile) 189 } 190 191 func NewDriverConfig(ctx *cli.Context) *driver.Config { 192 return &driver.Config{ 193 VerifierConfDepth: ctx.Uint64(flags.VerifierL1Confs.Name), 194 SequencerConfDepth: ctx.Uint64(flags.SequencerL1Confs.Name), 195 SequencerEnabled: ctx.Bool(flags.SequencerEnabledFlag.Name), 196 SequencerStopped: ctx.Bool(flags.SequencerStoppedFlag.Name), 197 SequencerMaxSafeLag: ctx.Uint64(flags.SequencerMaxSafeLagFlag.Name), 198 } 199 } 200 201 func NewRollupConfigFromCLI(log log.Logger, ctx *cli.Context) (*rollup.Config, error) { 202 network := ctx.String(opflags.NetworkFlagName) 203 rollupConfigPath := ctx.String(opflags.RollupConfigFlagName) 204 if ctx.Bool(flags.BetaExtraNetworks.Name) { 205 log.Warn("The beta.extra-networks flag is deprecated and can be omitted safely.") 206 } 207 rollupConfig, err := NewRollupConfig(log, network, rollupConfigPath) 208 if err != nil { 209 return nil, err 210 } 211 applyOverrides(ctx, rollupConfig) 212 return rollupConfig, nil 213 } 214 215 func NewRollupConfig(log log.Logger, network string, rollupConfigPath string) (*rollup.Config, error) { 216 if network != "" { 217 if rollupConfigPath != "" { 218 log.Error(`Cannot configure network and rollup-config at the same time. 219 Startup will proceed to use the network-parameter and ignore the rollup config. 220 Conflicting configuration is deprecated, and will stop the op-node from starting in the future. 221 `, "network", network, "rollup_config", rollupConfigPath) 222 } 223 rollupConfig, err := chaincfg.GetRollupConfig(network) 224 if err != nil { 225 return nil, err 226 } 227 return rollupConfig, nil 228 } 229 230 file, err := os.Open(rollupConfigPath) 231 if err != nil { 232 return nil, fmt.Errorf("failed to read rollup config: %w", err) 233 } 234 defer file.Close() 235 236 var rollupConfig rollup.Config 237 if err := json.NewDecoder(file).Decode(&rollupConfig); err != nil { 238 return nil, fmt.Errorf("failed to decode rollup config: %w", err) 239 } 240 return &rollupConfig, nil 241 } 242 243 func applyOverrides(ctx *cli.Context, rollupConfig *rollup.Config) { 244 if ctx.IsSet(opflags.CanyonOverrideFlagName) { 245 canyon := ctx.Uint64(opflags.CanyonOverrideFlagName) 246 rollupConfig.CanyonTime = &canyon 247 } 248 if ctx.IsSet(opflags.DeltaOverrideFlagName) { 249 delta := ctx.Uint64(opflags.DeltaOverrideFlagName) 250 rollupConfig.DeltaTime = &delta 251 } 252 if ctx.IsSet(opflags.EcotoneOverrideFlagName) { 253 ecotone := ctx.Uint64(opflags.EcotoneOverrideFlagName) 254 rollupConfig.EcotoneTime = &ecotone 255 } 256 } 257 258 func NewSnapshotLogger(ctx *cli.Context) (log.Logger, error) { 259 snapshotFile := ctx.String(flags.SnapshotLog.Name) 260 if snapshotFile == "" { 261 return log.NewLogger(log.DiscardHandler()), nil 262 } 263 264 sf, err := os.OpenFile(snapshotFile, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644) 265 if err != nil { 266 return nil, err 267 } 268 handler := log.JSONHandler(sf) 269 return log.NewLogger(handler), nil 270 } 271 272 func NewSyncConfig(ctx *cli.Context, log log.Logger) (*sync.Config, error) { 273 if ctx.IsSet(flags.L2EngineSyncEnabled.Name) && ctx.IsSet(flags.SyncModeFlag.Name) { 274 return nil, errors.New("cannot set both --l2.engine-sync and --syncmode at the same time.") 275 } else if ctx.IsSet(flags.L2EngineSyncEnabled.Name) { 276 log.Error("l2.engine-sync is deprecated and will be removed in a future release. Use --syncmode=execution-layer instead.") 277 } 278 mode, err := sync.StringToMode(ctx.String(flags.SyncModeFlag.Name)) 279 if err != nil { 280 return nil, err 281 } 282 cfg := &sync.Config{ 283 SyncMode: mode, 284 SkipSyncStartCheck: ctx.Bool(flags.SkipSyncStartCheck.Name), 285 } 286 if ctx.Bool(flags.L2EngineSyncEnabled.Name) { 287 cfg.SyncMode = sync.ELSync 288 } 289 290 return cfg, nil 291 }