etclabscore / core-geth

A highly configurable Go implementation of the Ethereum protocol.
https://etclabscore.github.io/core-geth
GNU Lesser General Public License v3.0
267 stars 147 forks source link

Disable MESS #592

Closed meowsbits closed 9 months ago

meowsbits commented 9 months ago

This PR drafts the disablement of MESS/ECBP1100, anticipated to occur on ETC concurrently with the Spiral network upgrade.

Following convention, a configuration override flag --ecbp1100.disable=[number] is provided.

As-is, this draft uses runtime and reflect at the Configurator implementation level to handle the actual enable/disable logic (https://github.com/etclabscore/core-geth/commit/9e274d02851888a9dab51d5ba197193f09aa2b24). Alternatively, we could consider instead adding conditions at the places where the configuration is referenced to handle it, like the example below.

diff --git a/core/forkchoice.go b/core/forkchoice.go
index d07cdf6aa4..55d898c3a0 100644
--- a/core/forkchoice.go
+++ b/core/forkchoice.go
@@ -162,7 +162,8 @@ func (f *ForkChoice) ReorgNeeded(current *types.Header, extern *types.Header) (b
                        return reorg, nil
                }
        }
-       if !f.chain.Config().IsEnabled(f.chain.Config().GetECBP1100Transition, current.Number) {
+       if !f.chain.Config().IsEnabled(f.chain.Config().GetECBP1100Transition, current.Number) ||
+               f.chain.Config().IsEnabled(f.chain.Config().GetECBP1100DisableTransition, current.Number) {
                return reorg, nil
        }
ziogaschr commented 9 months ago

I wonder if we also have to handle cases where --ecbp1100.nodisable is set.

Shall we force disable and raise a warning? This is what we prefer, on the other way, it's against the user's preference. I think if user decided to use --ecbp1100.nodisable we can only show a warning but we can't force a disable.

meowsbits commented 9 months ago

Good point on the nodisable flag. That feature was on request, and was intended to turn off the MinPeers and StaleHead safety mechanisms. The concern was that the safety mechanisms could be used to knock a node off the canonical network, assuming that the canonical network followed MESS. If was MESS was on, they wanted it to stay on.

MESS is only enabled if a peer has greater than or equal to the MinimumSyncPeers peers. In Core-Geth this value is by default 5. MESS is disabled if, once synced, a node's head block is not changed within a time limit (ie becomes stale). In Core-Geth this value is by default 30 * 13 seconds https://github.com/ethereumclassic/ECIPs/blob/master/_specs/ecip-1100.md#implementation

So its my understanding that conceptually there's no conflict with these flags, although you're definitely right to point to it.

ziogaschr commented 9 months ago

Oh, so this will not allow MESS to be disabled only once it has been enabled. Is this right? If yes, then there is no conflict indeed.

meowsbits commented 9 months ago

The naming/conceptual conflict of ecbp1100.nodisable and GetECBP1100DisableTransition is annoying and confusing.

IMO ecbp1100.nodisable could have been better named ecbp1100.nosafety, but now is unchangeable since it holds an API place in the flags and config TOML marshalling:

    ECBP1100NoDisableFlag = &cli.BoolFlag{
        Name:  "ecbp1100.nodisable",
        Usage: "Short-circuit ECBP-1100 (MESS) disable/safety mechanisms; (yields a permanent-once-activated state, deactivating auto-shutoff mechanisms)",
    }
    // ECBP1100NoDisable overrides
    // When this value is *true, ECBP100 will not (ever) be disabled; when *false, it will never be enabled.
    ECBP1100NoDisable *bool `toml:",omitempty"`

This configuration value is used as:

func (bc *BlockChain) EnableArtificialFinality(enable bool, logValues ...interface{}) {
    // Short circuit if AF state is enabled and nodisable=true.
    if bc.artificialFinalityNoDisable != nil && atomic.LoadInt32(bc.artificialFinalityNoDisable) == 1 &&
        bc.IsArtificialFinalityEnabled() && !enable {
        log.Warn("Preventing disable artificial finality", "enabled", true, "nodisable", true)
        return
    }

How about renaming our new GetECBP1100DisableTransition and her associated fields to ECBP1100Deactivate instead to lessen the confusion? "Activation" being common language for turning on fork features ("block activation number"), and we're talking about "turning off" the feature.