github.com/ethereum-optimism/optimism@v1.7.2/op-node/node/superchain.go (about) 1 package node 2 3 import ( 4 "context" 5 "errors" 6 7 "github.com/ethereum-optimism/optimism/op-node/rollup" 8 "github.com/ethereum/go-ethereum/eth/catalyst" 9 "github.com/ethereum/go-ethereum/params" 10 ) 11 12 var errNodeHalt = errors.New("opted to halt, unprepared for protocol change") 13 14 func (n *OpNode) handleProtocolVersionsUpdate(ctx context.Context) error { 15 recommended := n.runCfg.RecommendedProtocolVersion() 16 required := n.runCfg.RequiredProtocolVersion() 17 // if the protocol version sources are disabled we do not process them 18 if recommended == (params.ProtocolVersion{}) && required == (params.ProtocolVersion{}) { 19 return nil 20 } 21 local := rollup.OPStackSupport 22 // forward to execution engine, and get back the protocol version that op-geth supports 23 engineSupport, err := n.l2Source.SignalSuperchainV1(ctx, recommended, required) 24 if err != nil { 25 n.log.Warn("failed to notify engine of protocol version", "err", err) 26 // engineSupport may still be available, or otherwise zero to signal as unknown 27 } else { 28 catalyst.LogProtocolVersionSupport(n.log.New("node", "op-node"), engineSupport, recommended, "recommended") 29 catalyst.LogProtocolVersionSupport(n.log.New("node", "op-node"), engineSupport, required, "required") 30 } 31 n.metrics.ReportProtocolVersions(local, engineSupport, recommended, required) 32 catalyst.LogProtocolVersionSupport(n.log.New("node", "engine"), local, recommended, "recommended") 33 catalyst.LogProtocolVersionSupport(n.log.New("node", "engine"), local, required, "required") 34 35 // We may need to halt the node, if the user opted in to handling incompatible protocol-version signals 36 return n.haltMaybe() 37 } 38 39 // haltMaybe returns errNodeHalt if the runtime config indicates an incompatible required protocol change 40 // and the node is configured to opt-in to halting at this protocol-change level. 41 func (n *OpNode) haltMaybe() error { 42 local := rollup.OPStackSupport 43 required := n.runCfg.RequiredProtocolVersion() 44 if haltMaybe(n.rollupHalt, local.Compare(required)) { // halt if we opted in to do so at this granularity 45 n.log.Error("Opted to halt, unprepared for protocol change", "required", required, "local", local) 46 // Avoid deadlocking the runtime config reloader by closing the OpNode elsewhere 47 return errNodeHalt 48 } 49 return nil 50 } 51 52 // haltMaybe returns true when we should halt, given the halt-option and required-version comparison 53 func haltMaybe(haltOption string, reqCmp params.ProtocolVersionComparison) bool { 54 var needLevel int 55 switch haltOption { 56 case "major": 57 needLevel = 3 58 case "minor": 59 needLevel = 2 60 case "patch": 61 needLevel = 1 62 default: 63 return false // do not consider halting if not configured to 64 } 65 haveLevel := 0 66 switch reqCmp { 67 case params.OutdatedMajor: 68 haveLevel = 3 69 case params.OutdatedMinor: 70 haveLevel = 2 71 case params.OutdatedPatch: 72 haveLevel = 1 73 } 74 return haveLevel >= needLevel 75 }