Files
coreth/params/config_extra.go

170 lines
5.2 KiB
Go

// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package params
import (
"encoding/json"
"errors"
"math/big"
"github.com/luxfi/coreth/params/extras"
"github.com/luxfi/coreth/utils"
ethparams "github.com/luxfi/geth/params"
"github.com/luxfi/upgrade"
)
const (
maxJSONLen = 64 * 1024 * 1024 // 64MB
// TODO: Value to pass to geth's Rules by default where the appropriate
// context is not available in the lux code. (similar to context.TODO())
IsMergeTODO = true
)
// initiallyActive is the canonical Lux C-Chain genesis-activation timestamp.
// Tests in this package reference it; production paths under
// activate-all-implicitly do not need to read it directly because every
// upgrade is unconditionally live.
var initiallyActive = uint64(upgrade.InitiallyActiveTime.Unix())
// SetEthUpgrades enables Ethereum network upgrades using the same time as
// the Lux network upgrade that enables them.
func SetEthUpgrades(c *ChainConfig) error {
// Set Ethereum block upgrades to initially activated as they were already
// activated on launch.
c.HomesteadBlock = big.NewInt(0)
c.DAOForkBlock = big.NewInt(0)
c.DAOForkSupport = true
c.EIP150Block = big.NewInt(0)
c.EIP155Block = big.NewInt(0)
c.EIP158Block = big.NewInt(0)
c.ByzantiumBlock = big.NewInt(0)
c.ConstantinopleBlock = big.NewInt(0)
c.PetersburgBlock = big.NewInt(0)
c.IstanbulBlock = big.NewInt(0)
c.MuirGlacierBlock = big.NewInt(0)
// For Lux mainnet (96369) and testnet (96370), and other networks,
// Berlin and London are always active from genesis.
c.BerlinBlock = big.NewInt(0)
c.LondonBlock = big.NewInt(0)
_ = GetExtra(c)
// Under activate-all-implicitly: Shanghai and Cancun are live from
// genesis. If the genesis JSON pinned an explicit timestamp, preserve it.
if c.ShanghaiTime == nil {
c.ShanghaiTime = utils.NewUint64(0)
}
if c.CancunTime == nil {
c.CancunTime = utils.NewUint64(0)
}
return nil
}
func GetExtra(c *ChainConfig) *extras.ChainConfig {
ex := payloads.ChainConfig.Get(c)
if ex == nil {
ex = &extras.ChainConfig{}
payloads.ChainConfig.Set(c, ex)
}
return ex
}
func Copy(c *ChainConfig) *ChainConfig {
cpy := *c
cpyPtr := &cpy
extraCpy := *GetExtra(c)
// Note: We need to heap-allocate the copy so the pointer remains valid
// after this function returns, as extras are keyed by pointer.
heapCpy := new(ChainConfig)
*heapCpy = *cpyPtr
heapExtraCpy := new(extras.ChainConfig)
*heapExtraCpy = extraCpy
return WithExtra(heapCpy, heapExtraCpy)
}
// WithExtra sets the extra payload on `c` and returns the modified argument.
func WithExtra(c *ChainConfig, extra *extras.ChainConfig) *ChainConfig {
payloads.ChainConfig.Set(c, extra)
return c
}
type ChainConfigWithUpgradesJSON struct {
ChainConfig
UpgradeConfig extras.UpgradeConfig `json:"upgrades,omitempty"`
}
// MarshalJSON implements json.Marshaler. This is a workaround for the fact that
// the embedded ChainConfig struct has a MarshalJSON method, which prevents
// the default JSON marshalling from working for UpgradeConfig.
// TODO: consider removing this method by allowing external tag for the embedded
// ChainConfig struct.
func (cu ChainConfigWithUpgradesJSON) MarshalJSON() ([]byte, error) {
// embed the ChainConfig struct into the response
chainConfigJSON, err := json.Marshal(&cu.ChainConfig)
if err != nil {
return nil, err
}
if len(chainConfigJSON) > maxJSONLen {
return nil, errors.New("value too large")
}
type upgrades struct {
UpgradeConfig extras.UpgradeConfig `json:"upgrades"`
}
upgradeJSON, err := json.Marshal(upgrades{cu.UpgradeConfig})
if err != nil {
return nil, err
}
if len(upgradeJSON) > maxJSONLen {
return nil, errors.New("value too large")
}
// merge the two JSON objects
mergedJSON := make([]byte, 0, len(chainConfigJSON)+len(upgradeJSON)+1)
mergedJSON = append(mergedJSON, chainConfigJSON[:len(chainConfigJSON)-1]...)
mergedJSON = append(mergedJSON, ',')
mergedJSON = append(mergedJSON, upgradeJSON[1:]...)
return mergedJSON, nil
}
func (cu *ChainConfigWithUpgradesJSON) UnmarshalJSON(input []byte) error {
var cc ChainConfig
if err := json.Unmarshal(input, &cc); err != nil {
return err
}
type upgrades struct {
UpgradeConfig extras.UpgradeConfig `json:"upgrades"`
}
var u upgrades
if err := json.Unmarshal(input, &u); err != nil {
return err
}
cu.ChainConfig = cc
cu.UpgradeConfig = u.UpgradeConfig
return nil
}
// ToWithUpgradesJSON converts the ChainConfig to ChainConfigWithUpgradesJSON with upgrades explicitly displayed.
// ChainConfig does not include upgrades in its JSON output.
// This is a workaround for showing upgrades in the JSON output.
func ToWithUpgradesJSON(c *ChainConfig) *ChainConfigWithUpgradesJSON {
return &ChainConfigWithUpgradesJSON{
ChainConfig: *c,
UpgradeConfig: GetExtra(c).UpgradeConfig,
}
}
// CheckCompatible checks whether scheduled fork transitions have been imported
// with a mismatching chain configuration. Under activate-all-implicitly the
// Lux-side upgrades have no ordering to enforce; only geth's Ethereum forks
// can raise a compat error.
func CheckCompatible(stored, newcfg *ChainConfig, headBlock uint64, headTimestamp uint64) *ethparams.ConfigCompatError {
return stored.CheckCompatible(newcfg, headBlock, headTimestamp)
}