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  }