main.go 4.51 KB
Newer Older
1 2 3 4
package main

import (
	"context"
5
	"net"
6
	"os"
7
	"strconv"
8

9
	"github.com/ethereum-optimism/optimism/op-node/chaincfg"
10 11
	"github.com/ethereum-optimism/optimism/op-node/cmd/doc"

12
	"github.com/urfave/cli/v2"
13

14 15
	"github.com/ethereum/go-ethereum/log"

16
	opnode "github.com/ethereum-optimism/optimism/op-node"
17
	"github.com/ethereum-optimism/optimism/op-node/cmd/genesis"
18
	"github.com/ethereum-optimism/optimism/op-node/cmd/p2p"
19
	"github.com/ethereum-optimism/optimism/op-node/flags"
20 21
	"github.com/ethereum-optimism/optimism/op-node/heartbeat"
	"github.com/ethereum-optimism/optimism/op-node/metrics"
22
	"github.com/ethereum-optimism/optimism/op-node/node"
23
	"github.com/ethereum-optimism/optimism/op-node/version"
24
	opservice "github.com/ethereum-optimism/optimism/op-service"
25
	oplog "github.com/ethereum-optimism/optimism/op-service/log"
26
	"github.com/ethereum-optimism/optimism/op-service/opio"
27
	oppprof "github.com/ethereum-optimism/optimism/op-service/pprof"
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
)

var (
	GitCommit = ""
	GitDate   = ""
)

// VersionWithMeta holds the textual version string including the metadata.
var VersionWithMeta = func() string {
	v := version.Version
	if GitCommit != "" {
		v += "-" + GitCommit[:8]
	}
	if GitDate != "" {
		v += "-" + GitDate
	}
	if version.Meta != "" {
		v += "-" + version.Meta
	}
	return v
}()

func main() {
	// Set up logger with a default INFO level in case we fail to parse flags,
	// otherwise the final critical log won't show what the parsing error was.
53
	oplog.SetupDefaults()
54 55 56

	app := cli.NewApp()
	app.Version = VersionWithMeta
57
	app.Flags = flags.Flags
58
	app.Name = "op-node"
59
	app.Usage = "Optimism Rollup Node"
60
	app.Description = "The Optimism Rollup Node derives L2 block inputs from L1 data and drives an external L2 Execution Engine to build a L2 chain."
61
	app.Action = RollupNodeMain
62
	app.Commands = []*cli.Command{
63 64 65 66
		{
			Name:        "p2p",
			Subcommands: p2p.Subcommands,
		},
67 68 69 70
		{
			Name:        "genesis",
			Subcommands: genesis.Subcommands,
		},
71 72 73 74
		{
			Name:        "doc",
			Subcommands: doc.Subcommands,
		},
75 76
	}

77 78 79 80 81 82 83 84
	err := app.Run(os.Args)
	if err != nil {
		log.Crit("Application failed", "message", err)
	}
}

func RollupNodeMain(ctx *cli.Context) error {
	log.Info("Initializing Rollup Node")
85 86
	logCfg := oplog.ReadCLIConfig(ctx)
	if err := logCfg.Check(); err != nil {
87
		log.Error("Unable to create the log config", "error", err)
88 89
		return err
	}
90
	log := oplog.NewLogger(logCfg)
91
	opservice.ValidateEnvVars(flags.EnvVarPrefix, flags.Flags, log)
92
	m := metrics.NewMetrics("default")
93 94

	cfg, err := opnode.NewConfig(ctx, log)
95
	if err != nil {
96
		log.Error("Unable to create the rollup node config", "error", err)
97 98 99 100 101 102 103 104
		return err
	}
	snapshotLog, err := opnode.NewSnapshotLogger(ctx)
	if err != nil {
		log.Error("Unable to create snapshot root logger", "error", err)
		return err
	}

105 106 107 108 109 110 111
	// Only pretty-print the banner if it is a terminal log. Other log it as key-value pairs.
	if logCfg.Format == "terminal" {
		log.Info("rollup config:\n" + cfg.Rollup.Description(chaincfg.L2ChainIDToNetworkName))
	} else {
		cfg.Rollup.LogDescription(log, chaincfg.L2ChainIDToNetworkName)
	}

112
	n, err := node.New(context.Background(), cfg, log, snapshotLog, VersionWithMeta, m)
113 114 115 116
	if err != nil {
		log.Error("Unable to create the rollup node", "error", err)
		return err
	}
117
	log.Info("Starting rollup node", "version", VersionWithMeta)
118 119 120 121 122 123 124

	if err := n.Start(context.Background()); err != nil {
		log.Error("Unable to start rollup node", "error", err)
		return err
	}
	defer n.Close()

125 126
	m.RecordInfo(VersionWithMeta)
	m.RecordUp()
127 128
	log.Info("Rollup node started")

129 130
	if cfg.Heartbeat.Enabled {
		var peerID string
131
		if cfg.P2P.Disabled() {
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
			peerID = "disabled"
		} else {
			peerID = n.P2P().Host().ID().String()
		}

		beatCtx, beatCtxCancel := context.WithCancel(context.Background())
		payload := &heartbeat.Payload{
			Version: version.Version,
			Meta:    version.Meta,
			Moniker: cfg.Heartbeat.Moniker,
			PeerID:  peerID,
			ChainID: cfg.Rollup.L2ChainID.Uint64(),
		}
		go func() {
			if err := heartbeat.Beat(beatCtx, log, cfg.Heartbeat.URL, payload); err != nil {
				log.Error("heartbeat goroutine crashed", "err", err)
			}
		}()
		defer beatCtxCancel()
	}

153
	if cfg.Pprof.Enabled {
154
		pprofCtx, pprofCancel := context.WithCancel(context.Background())
155
		go func() {
156 157 158
			log.Info("pprof server started", "addr", net.JoinHostPort(cfg.Pprof.ListenAddr, strconv.Itoa(cfg.Pprof.ListenPort)))
			if err := oppprof.ListenAndServe(pprofCtx, cfg.Pprof.ListenAddr, cfg.Pprof.ListenPort); err != nil {
				log.Error("error starting pprof", "err", err)
159 160
			}
		}()
161
		defer pprofCancel()
162 163
	}

164
	opio.BlockOnInterrupts()
165 166 167 168

	return nil

}