Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Denial of Service] "Opted to halt, unprepared for protocol change" #269

Open
feld opened this issue Mar 14, 2024 · 3 comments
Open

[Denial of Service] "Opted to halt, unprepared for protocol change" #269

feld opened this issue Mar 14, 2024 · 3 comments

Comments

@feld
Copy link

feld commented Mar 14, 2024

Hey could we maybe not automatically halt when a major version change is encountered and just log an error instead?

This is the opposite of designing your distributed system to be antifragile.

op-geth/eth/backend.go

Lines 612 to 640 in 336d284

// HandleRequiredProtocolVersion handles the protocol version signal. This implements opt-in halting,
// the protocol version data is already logged and metered when signaled through the Engine API.
func (s *Ethereum) HandleRequiredProtocolVersion(required params.ProtocolVersion) error {
var needLevel int
switch s.config.RollupHaltOnIncompatibleProtocolVersion {
case "major":
needLevel = 3
case "minor":
needLevel = 2
case "patch":
needLevel = 1
default:
return nil // do not consider halting if not configured to
}
haveLevel := 0
switch params.OPStackSupport.Compare(required) {
case params.OutdatedMajor:
haveLevel = 3
case params.OutdatedMinor:
haveLevel = 2
case params.OutdatedPatch:
haveLevel = 1
}
if haveLevel >= needLevel { // halt if we opted in to do so at this granularity
log.Error("Opted to halt, unprepared for protocol change", "required", required, "local", params.OPStackSupport)
return s.nodeCloser()
}
return nil
}

@ajsutton
Copy link
Contributor

Worth noting for the record that halting is an opt-in thing. It's actually very useful for a full node to prevent it following a non-upgraded chain if it misses an update and then having to completely resync to get back to the correct chain because it no longer has world states old enough to handle the very large reorg.

Also, the recommended protocol version is updated prior to the required protocol version being updated which causes op-geth to log an error about being out of date but not halt.

    --rollup.halt value                                                    ($GETH_ROLLUP_HALT)
          Opt-in option to halt on incompatible protocol version requirements of the given
          level (major/minor/patch/none), as signaled through the Engine API by the rollup
          node

I believe you can achieve a policy of only ever logging by using the options from op-node:

--rollup.halt value                                                    ($OP_NODE_ROLLUP_HALT)
          Opt-in option to halt on incompatible protocol version requirements of the given
          level (major/minor/patch/none), as signaled onchain in L1

    --rollup.load-protocol-versions     (default: false)                   ($OP_NODE_ROLLUP_LOAD_PROTOCOL_VERSIONS)
          Load protocol versions from the superchain L1 ProtocolVersions contract (if
          available), and report in logs and metrics

You can instruct it to load protocol versions but not opt in to rollup halt and op-node will use the JSON-RPC call to also check that its op-geth is up to date.

@feld
Copy link
Author

feld commented Mar 15, 2024

How is this opt-in? I did not set the GET_ROLLUP_HALT env or --rollup.halt on either Optimism or Base nodes that I operate, but I did encounter this behavior.

@ajsutton
Copy link
Contributor

If you look at

op-geth/eth/backend.go

Lines 616 to 625 in 425e757

switch s.config.RollupHaltOnIncompatibleProtocolVersion {
case "major":
needLevel = 3
case "minor":
needLevel = 2
case "patch":
needLevel = 1
default:
return nil // do not consider halting if not configured to
}
if s.config.RollupHaltOnIncompatibleProtocolVersion is not set, it does not halt. That config var is set in
cfg.RollupHaltOnIncompatibleProtocolVersion = ctx.String(RollupHaltOnIncompatibleProtocolVersionFlag.Name)
to the value set in the rollup.halt flag which has now default value:

op-geth/cmd/utils/flags.go

Lines 888 to 892 in 352fbe6

RollupHaltOnIncompatibleProtocolVersionFlag = &cli.StringFlag{
Name: "rollup.halt",
Usage: "Opt-in option to halt on incompatible protocol version requirements of the given level (major/minor/patch/none), as signaled through the Engine API by the rollup node",
Category: flags.RollupCategory,
}

So it's off by default. If op-geth halted then something must have set that flag.

What version of op-geth were you running?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants