diff --git a/cmd/geth/config.go b/cmd/geth/config.go index 6a4dbc2c2e..75ece99546 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -189,6 +189,11 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) { cfg.Eth.OverrideOptimismFjord = &v } + if ctx.IsSet(utils.OverrideOptimismLibplanetVn1.Name) { + v := ctx.Uint64(utils.OverrideOptimismLibplanetVn1.Name) + cfg.Eth.OverrideOptimismLibplanetVn1 = &v + } + if ctx.IsSet(utils.OverrideOptimismInterop.Name) { v := ctx.Uint64(utils.OverrideOptimismInterop.Name) cfg.Eth.OverrideOptimismInterop = &v diff --git a/cmd/geth/main.go b/cmd/geth/main.go index d987364ca1..eb8de6dda6 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -70,6 +70,7 @@ var ( utils.OverrideOptimismCanyon, utils.OverrideOptimismEcotone, utils.OverrideOptimismFjord, + utils.OverrideOptimismLibplanetVn1, utils.OverrideOptimismInterop, utils.EnablePersonal, utils.TxPoolLocalsFlag, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index f4ecd35287..3ca727c7b5 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -276,6 +276,11 @@ var ( Usage: "Manually specify the Optimism Fjord fork timestamp, overriding the bundled setting", Category: flags.EthCategory, } + OverrideOptimismLibplanetVn1 = &cli.Uint64Flag{ + Name: "override.libplanetVn1", + Usage: "Manually specify the Optimism LibplanetVn1 fork timestamp, overriding the bundled setting", + Category: flags.EthCategory, + } OverrideOptimismInterop = &cli.Uint64Flag{ Name: "override.interop", Usage: "Manually specify the Optimsim Interop feature-set fork timestamp, overriding the bundled setting", diff --git a/core/genesis.go b/core/genesis.go index 934eb6e234..f4294b9dae 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -222,11 +222,12 @@ type ChainOverrides struct { OverrideCancun *uint64 OverrideVerkle *uint64 // optimism - OverrideOptimismCanyon *uint64 - OverrideOptimismEcotone *uint64 - OverrideOptimismFjord *uint64 - ApplySuperchainUpgrades bool - OverrideOptimismInterop *uint64 + OverrideOptimismCanyon *uint64 + OverrideOptimismEcotone *uint64 + OverrideOptimismFjord *uint64 + OverrideOptimismLibplanetVn1 *uint64 + ApplySuperchainUpgrades bool + OverrideOptimismInterop *uint64 } // SetupGenesisBlock writes or updates the genesis block in db. @@ -293,6 +294,9 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, g if overrides != nil && overrides.OverrideOptimismFjord != nil { config.FjordTime = overrides.OverrideOptimismFjord } + if overrides != nil && overrides.OverrideOptimismLibplanetVn1 != nil { + config.LibplanetVn1Time = overrides.OverrideOptimismLibplanetVn1 + } if overrides != nil && overrides.OverrideOptimismInterop != nil { config.InteropTime = overrides.OverrideOptimismInterop } diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 1e72816cc7..ecb063a808 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -126,6 +126,22 @@ var PrecompiledContractsFjord = map[common.Address]PrecompiledContract{ common.BytesToAddress([]byte{9}): &blake2F{}, common.BytesToAddress([]byte{0x0a}): &kzgPointEvaluation{}, common.BytesToAddress([]byte{0x01, 0x00}): &p256Verify{}, +} + +// PrecompiledContractsLibplanetVn1 contains the default set of pre-compiled Ethereum +// contracts used in the LibplanetVn1 release. +var PrecompiledContractsLibplanetVn1 = map[common.Address]PrecompiledContract{ + common.BytesToAddress([]byte{1}): &ecrecover{}, + common.BytesToAddress([]byte{2}): &sha256hash{}, + common.BytesToAddress([]byte{3}): &ripemd160hash{}, + common.BytesToAddress([]byte{4}): &dataCopy{}, + common.BytesToAddress([]byte{5}): &bigModExp{eip2565: true}, + common.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, + common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, + common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, + common.BytesToAddress([]byte{9}): &blake2F{}, + common.BytesToAddress([]byte{0x0a}): &kzgPointEvaluation{}, + common.BytesToAddress([]byte{0x01, 0x00}): &p256Verify{}, common.BytesToAddress([]byte{0x02, 0x00}): &libplanetVerifyProof{}, common.BytesToAddress([]byte{0x02, 0x01}): &libplanetWithdrawalTransactionHashing{}, } @@ -145,12 +161,13 @@ var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{ } var ( - PrecompiledAddressesFjord []common.Address - PrecompiledAddressesCancun []common.Address - PrecompiledAddressesBerlin []common.Address - PrecompiledAddressesIstanbul []common.Address - PrecompiledAddressesByzantium []common.Address - PrecompiledAddressesHomestead []common.Address + PrecompiledAddressesLibplanetVn1 []common.Address + PrecompiledAddressesFjord []common.Address + PrecompiledAddressesCancun []common.Address + PrecompiledAddressesBerlin []common.Address + PrecompiledAddressesIstanbul []common.Address + PrecompiledAddressesByzantium []common.Address + PrecompiledAddressesHomestead []common.Address ) func init() { @@ -172,11 +189,16 @@ func init() { for k := range PrecompiledContractsFjord { PrecompiledAddressesFjord = append(PrecompiledAddressesFjord, k) } + for k := range PrecompiledContractsLibplanetVn1 { + PrecompiledAddressesLibplanetVn1 = append(PrecompiledAddressesLibplanetVn1, k) + } } // ActivePrecompiles returns the precompiles enabled with the current configuration. func ActivePrecompiles(rules params.Rules) []common.Address { switch { + case rules.IsOptimismLibplanetVn1: + return PrecompiledAddressesLibplanetVn1 case rules.IsOptimismFjord: return PrecompiledAddressesFjord case rules.IsCancun: diff --git a/core/vm/evm.go b/core/vm/evm.go index c1b0ff0d0f..2c398aabba 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -41,6 +41,8 @@ type ( func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) { var precompiles map[common.Address]PrecompiledContract switch { + case evm.chainRules.IsOptimismLibplanetVn1: + precompiles = PrecompiledContractsLibplanetVn1 case evm.chainRules.IsOptimismFjord: precompiles = PrecompiledContractsFjord case evm.chainRules.IsCancun: diff --git a/eth/backend.go b/eth/backend.go index aedbd01634..0d71e66c02 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -229,6 +229,9 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { if config.OverrideOptimismFjord != nil { overrides.OverrideOptimismFjord = config.OverrideOptimismFjord } + if config.OverrideOptimismLibplanetVn1 != nil { + overrides.OverrideOptimismLibplanetVn1 = config.OverrideOptimismLibplanetVn1 + } if config.OverrideOptimismInterop != nil { overrides.OverrideOptimismInterop = config.OverrideOptimismInterop } diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index fa1bfd4642..bebdd2b8e4 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -167,6 +167,8 @@ type Config struct { OverrideOptimismFjord *uint64 `toml:",omitempty"` + OverrideOptimismLibplanetVn1 *uint64 `toml:",omitempty"` + OverrideOptimismInterop *uint64 `toml:",omitempty"` // ApplySuperchainUpgrades requests the node to load chain-configuration from the superchain-registry. diff --git a/eth/ethconfig/gen_config.go b/eth/ethconfig/gen_config.go index a80fb68fa4..0b450d498c 100644 --- a/eth/ethconfig/gen_config.go +++ b/eth/ethconfig/gen_config.go @@ -59,6 +59,7 @@ func (c Config) MarshalTOML() (interface{}, error) { OverrideOptimismCanyon *uint64 `toml:",omitempty"` OverrideOptimismEcotone *uint64 `toml:",omitempty"` OverrideOptimismFjord *uint64 `toml:",omitempty"` + OverrideOptimismLibplanetVn1 *uint64 `toml:",omitempty"` OverrideOptimismInterop *uint64 `toml:",omitempty"` ApplySuperchainUpgrades bool `toml:",omitempty"` RollupSequencerHTTP string @@ -111,6 +112,7 @@ func (c Config) MarshalTOML() (interface{}, error) { enc.OverrideOptimismCanyon = c.OverrideOptimismCanyon enc.OverrideOptimismEcotone = c.OverrideOptimismEcotone enc.OverrideOptimismFjord = c.OverrideOptimismFjord + enc.OverrideOptimismLibplanetVn1 = c.OverrideOptimismLibplanetVn1 enc.OverrideOptimismInterop = c.OverrideOptimismInterop enc.ApplySuperchainUpgrades = c.ApplySuperchainUpgrades enc.RollupSequencerHTTP = c.RollupSequencerHTTP @@ -167,6 +169,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { OverrideOptimismCanyon *uint64 `toml:",omitempty"` OverrideOptimismEcotone *uint64 `toml:",omitempty"` OverrideOptimismFjord *uint64 `toml:",omitempty"` + OverrideOptimismLibplanetVn1 *uint64 `toml:",omitempty"` OverrideOptimismInterop *uint64 `toml:",omitempty"` ApplySuperchainUpgrades *bool `toml:",omitempty"` RollupSequencerHTTP *string @@ -306,6 +309,9 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.OverrideOptimismFjord != nil { c.OverrideOptimismFjord = dec.OverrideOptimismFjord } + if dec.OverrideOptimismLibplanetVn1 != nil { + c.OverrideOptimismLibplanetVn1 = dec.OverrideOptimismLibplanetVn1 + } if dec.OverrideOptimismInterop != nil { c.OverrideOptimismInterop = dec.OverrideOptimismInterop } diff --git a/params/config.go b/params/config.go index b3a96a96af..4b317abb2d 100644 --- a/params/config.go +++ b/params/config.go @@ -396,6 +396,8 @@ type ChainConfig struct { EcotoneTime *uint64 `json:"ecotoneTime,omitempty"` // Ecotone switch time (nil = no fork, 0 = already on optimism ecotone) FjordTime *uint64 `json:"fjordTime,omitempty"` // Fjord switch time (nil = no fork, 0 = already on Optimism Fjord) + LibplanetVn1Time *uint64 `json:"libplanetVn1Time,omitempty"` // Libplanet switch time (nil = no fork, 0 = already on libplanetVn1) + InteropTime *uint64 `json:"interopTime,omitempty"` // Interop switch time (nil = no fork, 0 = already on optimism interop) // TerminalTotalDifficulty is the amount of total difficulty reached by @@ -549,6 +551,9 @@ func (c *ChainConfig) Description() string { if c.FjordTime != nil { banner += fmt.Sprintf(" - Fjord: @%-10v\n", *c.FjordTime) } + if c.LibplanetVn1Time != nil { + banner += fmt.Sprintf(" - LibplanetVn1: @%-10v\n", *c.LibplanetVn1Time) + } if c.InteropTime != nil { banner += fmt.Sprintf(" - Interop: @%-10v\n", *c.InteropTime) } @@ -676,6 +681,10 @@ func (c *ChainConfig) IsFjord(time uint64) bool { return isTimestampForked(c.FjordTime, time) } +func (c *ChainConfig) IsLibplanetVn1(time uint64) bool { + return isTimestampForked(c.LibplanetVn1Time, time) +} + func (c *ChainConfig) IsInterop(time uint64) bool { return isTimestampForked(c.InteropTime, time) } @@ -706,6 +715,10 @@ func (c *ChainConfig) IsOptimismFjord(time uint64) bool { return c.IsOptimism() && c.IsFjord(time) } +func (c *ChainConfig) IsOptimismLibplanetVn1(time uint64) bool { + return c.IsOptimism() && c.IsLibplanetVn1(time) +} + // IsOptimismPreBedrock returns true iff this is an optimism node & bedrock is not yet active func (c *ChainConfig) IsOptimismPreBedrock(num *big.Int) bool { return c.IsOptimism() && !c.IsBedrock(num) @@ -1047,6 +1060,7 @@ type Rules struct { IsVerkle bool IsOptimismBedrock, IsOptimismRegolith bool IsOptimismCanyon, IsOptimismFjord bool + IsOptimismLibplanetVn1 bool } // Rules ensures c's ChainID is not nil. @@ -1075,9 +1089,10 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules IsPrague: isMerge && c.IsPrague(num, timestamp), IsVerkle: isMerge && c.IsVerkle(num, timestamp), // Optimism - IsOptimismBedrock: isMerge && c.IsOptimismBedrock(num), - IsOptimismRegolith: isMerge && c.IsOptimismRegolith(timestamp), - IsOptimismCanyon: isMerge && c.IsOptimismCanyon(timestamp), - IsOptimismFjord: isMerge && c.IsOptimismFjord(timestamp), + IsOptimismBedrock: isMerge && c.IsOptimismBedrock(num), + IsOptimismRegolith: isMerge && c.IsOptimismRegolith(timestamp), + IsOptimismCanyon: isMerge && c.IsOptimismCanyon(timestamp), + IsOptimismFjord: isMerge && c.IsOptimismFjord(timestamp), + IsOptimismLibplanetVn1: isMerge && c.IsOptimismLibplanetVn1(timestamp), } }