diff --git a/cmd/geth/config.go b/cmd/geth/config.go index c304cb89c3..6174d53a0a 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -179,6 +179,11 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) { cfg.Eth.ECBP1100NoDisable = &enable } } + if ctx.IsSet(utils.OverrideECBP1100DeactivateFlag.Name) { + if n := ctx.Uint64(utils.OverrideECBP1100DeactivateFlag.Name); n != math.MaxUint64 { + cfg.Eth.OverrideECBP1100Deactivate = new(big.Int).SetUint64(n) + } + } if ctx.IsSet(utils.OverrideShanghai.Name) { v := ctx.Uint64(utils.OverrideShanghai.Name) cfg.Eth.OverrideShanghai = &v diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 962518d773..0255d798f7 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -167,6 +167,7 @@ var ( utils.MinerNotifyFullFlag, utils.ECBP1100Flag, utils.ECBP1100NoDisableFlag, + utils.OverrideECBP1100DeactivateFlag, configFileFlag, }, utils.NetworkFlags, utils.DatabasePathFlags) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 515a0f7424..2182e0d5d3 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1064,13 +1064,19 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server. Value: "", } ECBP1100Flag = &cli.Uint64Flag{ - Name: "ecbp1100", - Usage: "Configure ECBP-1100 (MESS) block activation number", - Value: math.MaxUint64, + Name: "ecbp1100", // should have been override.ecbp1100, but maintained now for backwards compatibility + Usage: "Manually specify the ECBP-1100 (MESS) block activation number, overriding the bundled setting", + Category: flags.EthCategory, + } + OverrideECBP1100DeactivateFlag = &cli.Uint64Flag{ + Name: "override.ecbp1100.deactivate", + Usage: "Manually specify the ECBP-1100 (MESS) deactivation block number, overriding the bundled setting", + Category: flags.EthCategory, } ECBP1100NoDisableFlag = &cli.BoolFlag{ - Name: "ecbp1100.nodisable", - Usage: "Short-circuit ECBP-1100 (MESS) disable mechanisms; (yields a permanent-once-activated state, deactivating auto-shutoff mechanisms)", + Name: "ecbp1100.nodisable", + Usage: "Short-circuit ECBP-1100 (MESS) disable mechanisms; (yields a permanent-once-activated state, deactivating auto-shutoff mechanisms)", + Category: flags.DeprecatedCategory, } MetricsEnableInfluxDBV2Flag = &cli.BoolFlag{ @@ -2081,6 +2087,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { cfg.EthDiscoveryURLs = SplitAndTrim(urls) } } + // Override any default configs for hard coded networks. // Override genesis configuration if a -- flag. diff --git a/core/blockchain_af.go b/core/blockchain_af.go index a4627606d3..efbfae913f 100644 --- a/core/blockchain_af.go +++ b/core/blockchain_af.go @@ -20,9 +20,31 @@ var errReorgFinality = errors.New("finality-enforced invalid new chain") // n = 1 : ON // n != 1 : OFF func (bc *BlockChain) ArtificialFinalityNoDisable(n int32) { - log.Warn("Deactivating ECBP1100 (MESS) disablers", "always on", true) + log.Warn("Deactivating ECBP1100 (MESS) safety mechanisms", "always on", true) bc.artificialFinalityNoDisable = new(int32) atomic.StoreInt32(bc.artificialFinalityNoDisable, n) + + if n == 1 { + deactivateTransition := bc.chainConfig.GetECBP1100DeactivateTransition() + if deactivateTransition != nil && big.NewInt(int64(*deactivateTransition)).Cmp(big.NewInt(0)) > 0 { + // Log the activation block as well as the deactivation block. + // Context is nice to have for the user. + var logActivationBlock uint64 + logActivationBlockRaw := bc.chainConfig.GetECBP1100Transition() + if logActivationBlockRaw == nil { + // panic("impossible") + logActivationBlock = *deactivateTransition + } else { + logActivationBlock = *logActivationBlockRaw + } + + log.Warn(`Deactivate-ECBP1100 (MESS) block activation number is set together with '--ecbp1100.nodisable'. +The --ecbp1100.nodisable feature prevents the toggling of ECBP1100 (MESS) artificial finality with its safety mechanisms of low peer count and stale head. +ECBP1100 (MESS) is scheduled for network-wide deactivation, rendering the --ecbp1100.nodisable feature anachronistic. +`, "ECBP1100 activation block", logActivationBlock, + "ECBP1100 deactivation block", *deactivateTransition) + } + } } // EnableArtificialFinality enables and disable artificial finality features for the blockchain. diff --git a/eth/backend.go b/eth/backend.go index 09c8b36241..f8232de2e6 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -20,7 +20,6 @@ package eth import ( "errors" "fmt" - "math" "math/big" "runtime" "sync" @@ -231,13 +230,19 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { } eth.bloomIndexer.Start(eth.blockchain) // Handle artificial finality config override cases. - if config.ECBP1100 != nil { - if n := config.ECBP1100.Uint64(); n != math.MaxUint64 { - if err := eth.blockchain.Config().SetECBP1100Transition(&n); err != nil { - return nil, err - } + if n := config.ECBP1100; n != nil { + v := n.Uint64() + if err := eth.blockchain.Config().SetECBP1100Transition(&v); err != nil { + return nil, err + } + } + if n := config.OverrideECBP1100Deactivate; n != nil { + v := n.Uint64() + if err := eth.blockchain.Config().SetECBP1100DeactivateTransition(&v); err != nil { + return nil, err } } + if config.ECBP1100NoDisable != nil { if *config.ECBP1100NoDisable { eth.blockchain.ArtificialFinalityNoDisable(1) diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index e8b3d3051a..417b70f8c8 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -218,6 +218,8 @@ type Config struct { // Manual configuration field for ECBP1100 activation number. Used for modifying genesis config via CLI flag. ECBP1100 *big.Int + // Manual configuration field for ECBP1100's disablement block number. Used for modifying genesis config via CLI flag. + OverrideECBP1100Deactivate *big.Int // ECBP1100NoDisable overrides // When this value is *true, ECBP100 will not (ever) be disabled; when *false, it will never be enabled. diff --git a/eth/ethconfig/gen_config.go b/eth/ethconfig/gen_config.go index 4f74ed83f0..fc71033021 100644 --- a/eth/ethconfig/gen_config.go +++ b/eth/ethconfig/gen_config.go @@ -66,6 +66,7 @@ func (c Config) MarshalTOML() (interface{}, error) { Checkpoint *ctypes.TrustedCheckpoint `toml:",omitempty"` CheckpointOracle *ctypes.CheckpointOracleConfig `toml:",omitempty"` ECBP1100 *big.Int + ECBP1100Disable *big.Int ECBP1100NoDisable *bool `toml:",omitempty"` OverrideShanghai *uint64 `toml:",omitempty"` OverrideCancun *uint64 `toml:",omitempty"` @@ -118,7 +119,9 @@ func (c Config) MarshalTOML() (interface{}, error) { enc.Checkpoint = c.Checkpoint enc.CheckpointOracle = c.CheckpointOracle enc.ECBP1100 = c.ECBP1100 + enc.ECBP1100Disable = c.OverrideECBP1100Deactivate enc.ECBP1100NoDisable = c.ECBP1100NoDisable + enc.OverrideShanghai = c.OverrideShanghai enc.OverrideCancun = c.OverrideCancun enc.OverrideVerkle = c.OverrideVerkle @@ -174,6 +177,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { Checkpoint *ctypes.TrustedCheckpoint `toml:",omitempty"` CheckpointOracle *ctypes.CheckpointOracleConfig `toml:",omitempty"` ECBP1100 *big.Int + ECBP1100Disable *big.Int ECBP1100NoDisable *bool `toml:",omitempty"` OverrideShanghai *uint64 `toml:",omitempty"` OverrideCancun *uint64 `toml:",omitempty"` @@ -321,6 +325,9 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.ECBP1100 != nil { c.ECBP1100 = dec.ECBP1100 } + if dec.ECBP1100Disable != nil { + c.OverrideECBP1100Deactivate = dec.ECBP1100Disable + } if dec.ECBP1100NoDisable != nil { c.ECBP1100NoDisable = dec.ECBP1100NoDisable } diff --git a/params/config_classic.go b/params/config_classic.go index ceba7d4ffe..e14286afde 100644 --- a/params/config_classic.go +++ b/params/config_classic.go @@ -81,8 +81,9 @@ var ( EIP2028FBlock: big.NewInt(10_500_839), EIP2200FBlock: big.NewInt(10_500_839), // RePetersburg (=~ re-1283) - ECBP1100FBlock: big.NewInt(11_380_000), // ETA 09 Oct 2020 - ECIP1099FBlock: big.NewInt(11_700_000), // Etchash (DAG size limit) + ECBP1100FBlock: big.NewInt(11_380_000), // ETA 09 Oct 2020 + ECBP1100DeactivateFBlock: big.NewInt(19_250_000), // ETA 31 Jan 2023 (== Spiral hard fork) + ECIP1099FBlock: big.NewInt(11_700_000), // Etchash (DAG size limit) // Berlin eq, aka Magneto EIP2565FBlock: big.NewInt(13_189_133), diff --git a/params/types/coregeth/chain_config.go b/params/types/coregeth/chain_config.go index 7e37900ccf..7db8b8525e 100644 --- a/params/types/coregeth/chain_config.go +++ b/params/types/coregeth/chain_config.go @@ -184,8 +184,9 @@ type CoreGethChainConfig struct { ECIP1017EraRounds *big.Int `json:"ecip1017EraRounds,omitempty"` // ECIP1017 era rounds ECIP1080FBlock *big.Int `json:"ecip1080FBlock,omitempty"` - ECIP1099FBlock *big.Int `json:"ecip1099FBlock,omitempty"` // ECIP1099 etchash HF block - ECBP1100FBlock *big.Int `json:"ecbp1100FBlock,omitempty"` // ECBP1100:MESS artificial finality + ECIP1099FBlock *big.Int `json:"ecip1099FBlock,omitempty"` // ECIP1099 etchash HF block + ECBP1100FBlock *big.Int `json:"ecbp1100FBlock,omitempty"` // ECBP1100:MESS artificial finality + ECBP1100DeactivateFBlock *big.Int `json:"ecbp1100DeactivateFBlockFBlock,omitempty"` // Deactivate ECBP1100:MESS artificial finality // EIP-2315: Simple Subroutines // https://eips.ethereum.org/EIPS/eip-2315 diff --git a/params/types/coregeth/chain_config_configurator.go b/params/types/coregeth/chain_config_configurator.go index 2f34271355..9fbfd42fad 100644 --- a/params/types/coregeth/chain_config_configurator.go +++ b/params/types/coregeth/chain_config_configurator.go @@ -28,6 +28,9 @@ package coregeth import ( "math/big" + "reflect" + "runtime" + "strings" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" @@ -424,6 +427,15 @@ func (c *CoreGethChainConfig) SetECBP1100Transition(n *uint64) error { return nil } +func (c *CoreGethChainConfig) GetECBP1100DeactivateTransition() *uint64 { + return bigNewU64(c.ECBP1100DeactivateFBlock) +} + +func (c *CoreGethChainConfig) SetECBP1100DeactivateTransition(n *uint64) error { + c.ECBP1100DeactivateFBlock = setBig(c.ECBP1100DeactivateFBlock, n) + return nil +} + func (c *CoreGethChainConfig) GetEIP2315Transition() *uint64 { return bigNewU64(c.EIP2315FBlock) } @@ -669,6 +681,13 @@ func (c *CoreGethChainConfig) IsEnabled(fn func() *uint64, n *big.Int) bool { if f == nil || n == nil { return false } + fnName := runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name() + if strings.Contains(fnName, "ECBP1100Transition") { + deactivateTransition := c.GetECBP1100DeactivateTransition() + if deactivateTransition != nil { + return big.NewInt(int64(*deactivateTransition)).Cmp(n) > 0 && big.NewInt(int64(*f)).Cmp(n) <= 0 + } + } return big.NewInt(int64(*f)).Cmp(n) <= 0 } diff --git a/params/types/coregeth/chain_config_test.go b/params/types/coregeth/chain_config_test.go index 2657452721..12da6958fe 100644 --- a/params/types/coregeth/chain_config_test.go +++ b/params/types/coregeth/chain_config_test.go @@ -49,3 +49,43 @@ func TestCoreGethChainConfig_String(t *testing.T) { t.Skip("(noop) development use only") t.Log(testConfig.String()) } + +func TestCoreGethChainConfig_ECBP1100Deactivate(t *testing.T) { + var _testConfig = &CoreGethChainConfig{} + *_testConfig = *testConfig + + activate := uint64(100) + deactivate := uint64(200) + _testConfig.SetECBP1100Transition(&activate) + _testConfig.SetECBP1100DeactivateTransition(&deactivate) + + n := uint64(10) + bigN := new(big.Int).SetUint64(n) + if _testConfig.IsEnabled(_testConfig.GetECBP1100Transition, bigN) { + t.Errorf("ECBP1100 should be not yet be activated at block %d", n) + } + + n = uint64(100) + bigN = new(big.Int).SetUint64(n) + if !_testConfig.IsEnabled(_testConfig.GetECBP1100Transition, bigN) { + t.Errorf("ECBP1100 should be activated at block %d", n) + } + + n = uint64(110) + bigN = new(big.Int).SetUint64(n) + if !_testConfig.IsEnabled(_testConfig.GetECBP1100Transition, bigN) { + t.Errorf("ECBP1100 should be activated at block %d", n) + } + + n = uint64(200) + bigN = new(big.Int).SetUint64(n) + if _testConfig.IsEnabled(_testConfig.GetECBP1100Transition, bigN) { + t.Errorf("ECBP1100 should be deactivated at block %d", n) + } + + n = uint64(210) + bigN = new(big.Int).SetUint64(n) + if _testConfig.IsEnabled(_testConfig.GetECBP1100Transition, bigN) { + t.Errorf("ECBP1100 should be deactivated at block %d", n) + } +} diff --git a/params/types/ctypes/configurator_iface.go b/params/types/ctypes/configurator_iface.go index 166312f639..5780ae02d1 100644 --- a/params/types/ctypes/configurator_iface.go +++ b/params/types/ctypes/configurator_iface.go @@ -142,6 +142,9 @@ type ProtocolSpecifier interface { GetECBP1100Transition() *uint64 SetECBP1100Transition(n *uint64) error + GetECBP1100DeactivateTransition() *uint64 + SetECBP1100DeactivateTransition(n *uint64) error + GetEIP2315Transition() *uint64 SetEIP2315Transition(n *uint64) error diff --git a/params/types/genesisT/genesis.go b/params/types/genesisT/genesis.go index de7cf98bb6..be6a21e996 100644 --- a/params/types/genesisT/genesis.go +++ b/params/types/genesisT/genesis.go @@ -789,6 +789,14 @@ func (g *Genesis) SetECBP1100Transition(n *uint64) error { return g.Config.SetECBP1100Transition(n) } +func (g *Genesis) GetECBP1100DeactivateTransition() *uint64 { + return g.Config.GetECBP1100DeactivateTransition() +} + +func (g *Genesis) SetECBP1100DeactivateTransition(n *uint64) error { + return g.Config.SetECBP1100DeactivateTransition(n) +} + func (g *Genesis) IsEnabled(fn func() *uint64, n *big.Int) bool { return g.Config.IsEnabled(fn, n) } diff --git a/params/types/goethereum/goethereum.go b/params/types/goethereum/goethereum.go index 3482407ed5..b67fd314d1 100644 --- a/params/types/goethereum/goethereum.go +++ b/params/types/goethereum/goethereum.go @@ -99,7 +99,8 @@ type ChainConfig struct { ECIP1080Transition *big.Int `json:"-"` // Cache types for use with testing, but will not show up in config API. - ecbp1100Transition *big.Int + ecbp1100Transition *big.Int + ecbp1100DeactivateTransition *big.Int Lyra2NonceTransitionBlock *big.Int `json:"lyra2NonceTransitionBlock,omitempty"` } diff --git a/params/types/goethereum/goethereum_configurator.go b/params/types/goethereum/goethereum_configurator.go index 65b9db3550..e4e8845a63 100644 --- a/params/types/goethereum/goethereum_configurator.go +++ b/params/types/goethereum/goethereum_configurator.go @@ -18,6 +18,9 @@ package goethereum import ( "math/big" + "reflect" + "runtime" + "strings" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/params/types/ctypes" @@ -449,6 +452,15 @@ func (c *ChainConfig) SetECBP1100Transition(n *uint64) error { return nil } +func (c *ChainConfig) GetECBP1100DeactivateTransition() *uint64 { + return bigNewU64(c.ecbp1100DeactivateTransition) +} + +func (c *ChainConfig) SetECBP1100DeactivateTransition(n *uint64) error { + c.ecbp1100DeactivateTransition = setBig(c.ecbp1100DeactivateTransition, n) + return nil +} + // GetEIP2315Transition implements EIP2537. // This logic is written but not configured for any Ethereum-supported networks, yet. func (c *ChainConfig) GetEIP2315Transition() *uint64 { @@ -691,6 +703,13 @@ func (c *ChainConfig) IsEnabled(fn func() *uint64, n *big.Int) bool { if f == nil || n == nil { return false } + fnName := runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name() + if strings.Contains(fnName, "ECBP1100Transition") { + deactivateTransition := c.GetECBP1100DeactivateTransition() + if deactivateTransition != nil { + return big.NewInt(int64(*deactivateTransition)).Cmp(n) > 0 && big.NewInt(int64(*f)).Cmp(n) <= 0 + } + } return big.NewInt(int64(*f)).Cmp(n) <= 0 }