mirror of
https://github.com/luxfi/evm.git
synced 2026-09-24 00:27:44 +00:00
GetRulesExtra derived a Rules' Lux rules from a process-wide last context: the chain config and timestamp of whichever Rules any goroutine evaluated most recently. Rules are evaluated concurrently, by block processing, the miner, the tx pool and every eth_call, so a Rules could read another evaluation's upgrades: its IsDurango, its predicaters, its enabled precompiles, and the intrinsic gas that depends on them. The context now travels with the Rules value. core's rules hook already put the chain config and timestamp in Rules.Payload for its precompile overrider; the overrider answers them, and GetRulesExtra reads them from the Rules it is given. RulesAt attaches them where no hook did. The global and SetRulesContext are gone. Every call site evaluates its Rules for the block it reads them for, so a caller that no other goroutine races sees the same rules as before. The blob pool's state checks passed a zero Rules and read the head's context the check before them had left; they now pass the head's Rules. TestRulesExtraIsTheRulesOwn evaluates two rule sets and reads the first; TestRulesExtraUnderConcurrentEvaluation reads four rule sets on four goroutines at once, across two times and two chains, including the intrinsic gas of a creation. TestActivePrecompiles, skipped for this bug, runs again. Co-authored-by: Hanzo Dev <[email protected]>
346 lines
11 KiB
Go
346 lines
11 KiB
Go
// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
//
|
|
// This file is a derived work, based on the go-ethereum library whose original
|
|
// notices appear below.
|
|
//
|
|
// It is distributed under a license compatible with the licensing terms of the
|
|
// original code from which it is derived.
|
|
//
|
|
// Much love to the original authors for their work.
|
|
// **********
|
|
// Copyright 2016 The go-ethereum Authors
|
|
// This file is part of the go-ethereum library.
|
|
//
|
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Lesser General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
package params
|
|
|
|
import (
|
|
"encoding/json"
|
|
"math/big"
|
|
"time"
|
|
|
|
"github.com/luxfi/evm/params/extras"
|
|
"github.com/luxfi/evm/utils"
|
|
ethparams "github.com/luxfi/geth/params"
|
|
)
|
|
|
|
// Guarantees extras initialisation before a call to [params.ChainConfig.Rules].
|
|
// Disabled: libevm integration removed
|
|
// var _ = gethInit()
|
|
|
|
// Local constants to replace upgrade package constants
|
|
var (
|
|
// InitiallyActiveTime represents the Unix epoch (time 0)
|
|
InitiallyActiveTime = time.Unix(0, 0)
|
|
)
|
|
|
|
var (
|
|
// EVMDefaultChainConfig is the default configuration with all EVM
|
|
// upgrades (Shanghai, Cancun, etc.) active from genesis so that
|
|
// every opcode (PUSH0, MCOPY, TSTORE, TLOAD, etc.) is available.
|
|
EVMDefaultChainConfig = WithExtra(
|
|
&ChainConfig{
|
|
ChainID: DefaultChainID,
|
|
|
|
HomesteadBlock: big.NewInt(0),
|
|
EIP150Block: big.NewInt(0),
|
|
EIP155Block: big.NewInt(0),
|
|
EIP158Block: big.NewInt(0),
|
|
ByzantiumBlock: big.NewInt(0),
|
|
ConstantinopleBlock: big.NewInt(0),
|
|
PetersburgBlock: big.NewInt(0),
|
|
IstanbulBlock: big.NewInt(0),
|
|
MuirGlacierBlock: big.NewInt(0),
|
|
BerlinBlock: big.NewInt(0),
|
|
LondonBlock: big.NewInt(0),
|
|
ShanghaiTime: utils.TimeToNewUint64(InitiallyActiveTime),
|
|
CancunTime: utils.TimeToNewUint64(InitiallyActiveTime),
|
|
BlobScheduleConfig: ðparams.BlobScheduleConfig{
|
|
Cancun: ðparams.BlobConfig{
|
|
Target: 3,
|
|
Max: 6,
|
|
UpdateFraction: 3338477,
|
|
},
|
|
},
|
|
},
|
|
extras.EVMDefaultChainConfig,
|
|
)
|
|
|
|
TestChainConfig = WithExtra(
|
|
&ChainConfig{
|
|
ChainID: big.NewInt(1337),
|
|
HomesteadBlock: big.NewInt(0),
|
|
EIP150Block: big.NewInt(0),
|
|
EIP155Block: big.NewInt(0),
|
|
EIP158Block: big.NewInt(0),
|
|
ByzantiumBlock: big.NewInt(0),
|
|
ConstantinopleBlock: big.NewInt(0),
|
|
PetersburgBlock: big.NewInt(0),
|
|
IstanbulBlock: big.NewInt(0),
|
|
MuirGlacierBlock: big.NewInt(0),
|
|
BerlinBlock: big.NewInt(0),
|
|
LondonBlock: big.NewInt(0),
|
|
// Test networks activate all upgrades at genesis via InitiallyActiveTime.
|
|
ShanghaiTime: utils.TimeToNewUint64(InitiallyActiveTime),
|
|
CancunTime: utils.TimeToNewUint64(InitiallyActiveTime),
|
|
BlobScheduleConfig: ðparams.BlobScheduleConfig{
|
|
Cancun: ðparams.BlobConfig{
|
|
Target: 3,
|
|
Max: 6,
|
|
UpdateFraction: 3338477,
|
|
},
|
|
},
|
|
},
|
|
extras.TestChainConfig,
|
|
)
|
|
|
|
TestPreEVMChainConfig = WithExtra(
|
|
&ChainConfig{
|
|
ChainID: big.NewInt(1337),
|
|
HomesteadBlock: big.NewInt(0),
|
|
EIP150Block: big.NewInt(0),
|
|
EIP155Block: big.NewInt(0),
|
|
EIP158Block: big.NewInt(0),
|
|
ByzantiumBlock: big.NewInt(0),
|
|
ConstantinopleBlock: big.NewInt(0),
|
|
PetersburgBlock: big.NewInt(0),
|
|
IstanbulBlock: big.NewInt(0),
|
|
MuirGlacierBlock: big.NewInt(0),
|
|
BerlinBlock: big.NewInt(0),
|
|
LondonBlock: big.NewInt(0),
|
|
// Add Shanghai/Cancun so CheckCompatible test checks EVM fork, not Shanghai
|
|
ShanghaiTime: utils.TimeToNewUint64(InitiallyActiveTime),
|
|
CancunTime: utils.TimeToNewUint64(InitiallyActiveTime),
|
|
BlobScheduleConfig: ðparams.BlobScheduleConfig{
|
|
Cancun: ðparams.BlobConfig{
|
|
Target: 3,
|
|
Max: 6,
|
|
UpdateFraction: 3338477,
|
|
},
|
|
},
|
|
},
|
|
extras.TestPreEVMChainConfig,
|
|
)
|
|
|
|
TestEVMChainConfig = WithExtra(
|
|
&ChainConfig{
|
|
ChainID: big.NewInt(1337),
|
|
HomesteadBlock: big.NewInt(0),
|
|
EIP150Block: big.NewInt(0),
|
|
EIP155Block: big.NewInt(0),
|
|
EIP158Block: big.NewInt(0),
|
|
ByzantiumBlock: big.NewInt(0),
|
|
ConstantinopleBlock: big.NewInt(0),
|
|
PetersburgBlock: big.NewInt(0),
|
|
IstanbulBlock: big.NewInt(0),
|
|
MuirGlacierBlock: big.NewInt(0),
|
|
BerlinBlock: big.NewInt(0),
|
|
LondonBlock: big.NewInt(0),
|
|
},
|
|
extras.TestEVMChainConfig,
|
|
)
|
|
|
|
TestDurangoChainConfig = WithExtra(
|
|
&ChainConfig{
|
|
ChainID: big.NewInt(1337),
|
|
HomesteadBlock: big.NewInt(0),
|
|
EIP150Block: big.NewInt(0),
|
|
EIP155Block: big.NewInt(0),
|
|
EIP158Block: big.NewInt(0),
|
|
ByzantiumBlock: big.NewInt(0),
|
|
ConstantinopleBlock: big.NewInt(0),
|
|
PetersburgBlock: big.NewInt(0),
|
|
IstanbulBlock: big.NewInt(0),
|
|
MuirGlacierBlock: big.NewInt(0),
|
|
BerlinBlock: big.NewInt(0),
|
|
LondonBlock: big.NewInt(0),
|
|
ShanghaiTime: utils.TimeToNewUint64(InitiallyActiveTime),
|
|
},
|
|
extras.TestDurangoChainConfig,
|
|
)
|
|
|
|
TestQuasarChainConfig = WithExtra(
|
|
&ChainConfig{
|
|
ChainID: big.NewInt(1337),
|
|
HomesteadBlock: big.NewInt(0),
|
|
EIP150Block: big.NewInt(0),
|
|
EIP155Block: big.NewInt(0),
|
|
EIP158Block: big.NewInt(0),
|
|
ByzantiumBlock: big.NewInt(0),
|
|
ConstantinopleBlock: big.NewInt(0),
|
|
PetersburgBlock: big.NewInt(0),
|
|
IstanbulBlock: big.NewInt(0),
|
|
MuirGlacierBlock: big.NewInt(0),
|
|
BerlinBlock: big.NewInt(0),
|
|
LondonBlock: big.NewInt(0),
|
|
ShanghaiTime: utils.TimeToNewUint64(InitiallyActiveTime),
|
|
CancunTime: utils.TimeToNewUint64(InitiallyActiveTime),
|
|
BlobScheduleConfig: ðparams.BlobScheduleConfig{
|
|
Cancun: ðparams.BlobConfig{
|
|
Target: 3,
|
|
Max: 6,
|
|
UpdateFraction: 3338477,
|
|
},
|
|
},
|
|
},
|
|
extras.TestQuasarChainConfig,
|
|
)
|
|
|
|
TestFortunaChainConfig = WithExtra(
|
|
&ChainConfig{
|
|
ChainID: big.NewInt(1337),
|
|
HomesteadBlock: big.NewInt(0),
|
|
EIP150Block: big.NewInt(0),
|
|
EIP155Block: big.NewInt(0),
|
|
EIP158Block: big.NewInt(0),
|
|
ByzantiumBlock: big.NewInt(0),
|
|
ConstantinopleBlock: big.NewInt(0),
|
|
PetersburgBlock: big.NewInt(0),
|
|
IstanbulBlock: big.NewInt(0),
|
|
MuirGlacierBlock: big.NewInt(0),
|
|
BerlinBlock: big.NewInt(0),
|
|
LondonBlock: big.NewInt(0),
|
|
ShanghaiTime: utils.TimeToNewUint64(InitiallyActiveTime),
|
|
CancunTime: utils.TimeToNewUint64(InitiallyActiveTime),
|
|
BlobScheduleConfig: ðparams.BlobScheduleConfig{
|
|
Cancun: ðparams.BlobConfig{
|
|
Target: 3,
|
|
Max: 6,
|
|
UpdateFraction: 3338477,
|
|
},
|
|
},
|
|
},
|
|
extras.TestFortunaChainConfig,
|
|
)
|
|
|
|
TestGraniteChainConfig = WithExtra(
|
|
&ChainConfig{
|
|
ChainID: big.NewInt(1337),
|
|
HomesteadBlock: big.NewInt(0),
|
|
EIP150Block: big.NewInt(0),
|
|
EIP155Block: big.NewInt(0),
|
|
EIP158Block: big.NewInt(0),
|
|
ByzantiumBlock: big.NewInt(0),
|
|
ConstantinopleBlock: big.NewInt(0),
|
|
PetersburgBlock: big.NewInt(0),
|
|
IstanbulBlock: big.NewInt(0),
|
|
MuirGlacierBlock: big.NewInt(0),
|
|
BerlinBlock: big.NewInt(0),
|
|
LondonBlock: big.NewInt(0),
|
|
ShanghaiTime: utils.TimeToNewUint64(InitiallyActiveTime),
|
|
CancunTime: utils.TimeToNewUint64(InitiallyActiveTime),
|
|
BlobScheduleConfig: ðparams.BlobScheduleConfig{
|
|
Cancun: ðparams.BlobConfig{
|
|
Target: 3,
|
|
Max: 6,
|
|
UpdateFraction: 3338477,
|
|
},
|
|
},
|
|
},
|
|
extras.TestGraniteChainConfig,
|
|
)
|
|
|
|
TestRules = TestChainConfig.Rules(new(big.Int), IsMergeTODO, 0)
|
|
)
|
|
|
|
// RulesAt returns the Rules for the given ChainConfig at the specified
|
|
// timestamp, carrying that config and timestamp for GetRulesExtra. With core
|
|
// linked, ChainConfig.Rules already carries them (core's rules hook); RulesAt
|
|
// attaches them where nothing did.
|
|
func RulesAt(c *ChainConfig, blockNum *big.Int, isMerge bool, timestamp uint64) Rules {
|
|
rules := c.Rules(blockNum, isMerge, timestamp)
|
|
if _, ok := rules.Payload.(rulesContext); !ok {
|
|
rules.Payload = evaluatedAt{config: c, timestamp: timestamp}
|
|
}
|
|
return rules
|
|
}
|
|
|
|
// ChainConfig is the core config which determines the blockchain settings.
|
|
//
|
|
// ChainConfig is stored in the database on a per block basis. This means
|
|
// that any network, identified by its genesis block, can have its own
|
|
// set of configuration options.
|
|
type ChainConfig = ethparams.ChainConfig
|
|
|
|
// Rules wraps ChainConfig and is merely syntactic sugar or can be used for functions
|
|
// that do not have or require information about the block.
|
|
//
|
|
// Rules is a one time interface meaning that it shouldn't be used in between transition
|
|
// phases.
|
|
type Rules = ethparams.Rules
|
|
|
|
// ChainConfigJSON is a wrapper for ChainConfig that handles JSON marshaling/unmarshaling
|
|
// with extras fields. This is used when we need to unmarshal JSON that contains both
|
|
// standard ChainConfig fields and extras fields.
|
|
type ChainConfigJSON struct {
|
|
*ChainConfig
|
|
}
|
|
|
|
// UnmarshalJSON unmarshals the JSON into the ChainConfig and handles extras fields
|
|
func (c *ChainConfigJSON) UnmarshalJSON(data []byte) error {
|
|
// First unmarshal the standard ChainConfig fields
|
|
c.ChainConfig = &ChainConfig{}
|
|
if err := json.Unmarshal(data, c.ChainConfig); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Now unmarshal the extras fields
|
|
extraFields := &extras.ChainConfig{}
|
|
if err := json.Unmarshal(data, extraFields); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Set the extras using WithExtra
|
|
WithExtra(c.ChainConfig, extraFields)
|
|
return nil
|
|
}
|
|
|
|
// MarshalJSON marshals the ChainConfig with extras fields
|
|
func (c *ChainConfigJSON) MarshalJSON() ([]byte, error) {
|
|
// Get the extras
|
|
extra := GetExtra(c.ChainConfig)
|
|
|
|
// Marshal the standard config
|
|
configJSON, err := json.Marshal(c.ChainConfig)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Marshal the extras
|
|
extraJSON, err := extra.MarshalJSON()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Merge the two JSON objects
|
|
var configMap map[string]json.RawMessage
|
|
if err := json.Unmarshal(configJSON, &configMap); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var extraMap map[string]json.RawMessage
|
|
if err := json.Unmarshal(extraJSON, &extraMap); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Merge extras into config
|
|
for k, v := range extraMap {
|
|
configMap[k] = v
|
|
}
|
|
|
|
return json.Marshal(configMap)
|
|
}
|