Merge pull request #11 from 0glabs/delegate-staking

add staking contract
This commit is contained in:
Pignard 2025-06-04 14:35:22 +08:00 committed by GitHub
commit 240cb5c156
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 174 additions and 2 deletions

View file

@ -18,6 +18,7 @@ package t8ntool
import ( import (
"fmt" "fmt"
gomath "math"
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -345,6 +346,11 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
} }
// Apply withdrawals // Apply withdrawals
for _, w := range pre.Env.Withdrawals { for _, w := range pre.Env.Withdrawals {
if chainConfig.IsDelegationActive(vmContext.BlockNumber, vmContext.Time) {
if w.Validator == gomath.MaxUint64 {
continue
}
}
// Amount is in gwei, turn into wei // Amount is in gwei, turn into wei
amount := new(big.Int).Mul(new(big.Int).SetUint64(w.Amount), big.NewInt(params.GWei)) amount := new(big.Int).Mul(new(big.Int).SetUint64(w.Amount), big.NewInt(params.GWei))
statedb.AddBalance(w.Address, uint256.MustFromBig(amount), tracing.BalanceIncreaseWithdrawal) statedb.AddBalance(w.Address, uint256.MustFromBig(amount), tracing.BalanceIncreaseWithdrawal)
@ -362,6 +368,17 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
if err := core.ParseDepositLogs(&requests, allLogs, chainConfig); err != nil { if err := core.ParseDepositLogs(&requests, allLogs, chainConfig); err != nil {
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not parse requests logs: %v", err)) return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not parse requests logs: %v", err))
} }
if chainConfig.IsDelegationActive(vmContext.BlockNumber, vmContext.Time) {
if len(pre.Env.Withdrawals) > 0 {
firstWithdrawal := pre.Env.Withdrawals[0]
if firstWithdrawal.Validator == gomath.MaxUint64 {
amount := new(big.Int).Mul(new(big.Int).SetUint64(firstWithdrawal.Amount), big.NewInt(params.GWei))
if err := core.ProcessStakingDistribution(evm, firstWithdrawal.Address, amount); err != nil {
log.Error("could not process staking distribution", "err", err)
}
}
}
}
// EIP-7002 // EIP-7002
if err := core.ProcessWithdrawalQueue(&requests, evm); err != nil { if err := core.ProcessWithdrawalQueue(&requests, evm); err != nil {
return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not process withdrawal requests: %v", err)) return nil, nil, nil, NewError(ErrorEVM, fmt.Errorf("could not process withdrawal requests: %v", err))

View file

@ -55,6 +55,7 @@ var (
utils.CachePreimagesFlag, utils.CachePreimagesFlag,
utils.OverridePrague, utils.OverridePrague,
utils.OverrideVerkle, utils.OverrideVerkle,
utils.OverrideDelegationActivation,
}, utils.DatabaseFlags), }, utils.DatabaseFlags),
Description: ` Description: `
The init command initializes a new genesis block and definition for the network. The init command initializes a new genesis block and definition for the network.
@ -236,6 +237,10 @@ func initGenesis(ctx *cli.Context) error {
v := ctx.Uint64(utils.OverrideVerkle.Name) v := ctx.Uint64(utils.OverrideVerkle.Name)
overrides.OverrideVerkle = &v overrides.OverrideVerkle = &v
} }
if ctx.IsSet(utils.OverrideDelegationActivation.Name) {
v := ctx.Uint64(utils.OverrideDelegationActivation.Name)
overrides.OverrideDelegationActivation = &v
}
chaindb, err := stack.OpenDatabaseWithFreezer("chaindata", 0, 0, ctx.String(utils.AncientFlag.Name), "", false) chaindb, err := stack.OpenDatabaseWithFreezer("chaindata", 0, 0, ctx.String(utils.AncientFlag.Name), "", false)
if err != nil { if err != nil {

View file

@ -191,6 +191,10 @@ func makeFullNode(ctx *cli.Context) *node.Node {
v := ctx.Uint64(utils.OverrideVerkle.Name) v := ctx.Uint64(utils.OverrideVerkle.Name)
cfg.Eth.OverrideVerkle = &v cfg.Eth.OverrideVerkle = &v
} }
if ctx.IsSet(utils.OverrideDelegationActivation.Name) {
v := ctx.Uint64(utils.OverrideDelegationActivation.Name)
cfg.Eth.OverrideDelegationActivation = &v
}
// Start metrics export if enabled // Start metrics export if enabled
utils.SetupMetrics(&cfg.Metrics) utils.SetupMetrics(&cfg.Metrics)

View file

@ -64,6 +64,7 @@ var (
utils.SmartCardDaemonPathFlag, utils.SmartCardDaemonPathFlag,
utils.OverridePrague, utils.OverridePrague,
utils.OverrideVerkle, utils.OverrideVerkle,
utils.OverrideDelegationActivation,
utils.EnablePersonal, // deprecated utils.EnablePersonal, // deprecated
utils.TxPoolLocalsFlag, utils.TxPoolLocalsFlag,
utils.TxPoolNoLocalsFlag, utils.TxPoolNoLocalsFlag,

View file

@ -248,6 +248,11 @@ var (
Usage: "Manually specify the Verkle fork timestamp, overriding the bundled setting", Usage: "Manually specify the Verkle fork timestamp, overriding the bundled setting",
Category: flags.EthCategory, Category: flags.EthCategory,
} }
OverrideDelegationActivation = &cli.Uint64Flag{
Name: "override.delegationActivation",
Usage: "Manually specify the Delegation Activation timestamp, overriding the bundled setting",
Category: flags.EthCategory,
}
SyncModeFlag = &cli.StringFlag{ SyncModeFlag = &cli.StringFlag{
Name: "syncmode", Name: "syncmode",
Usage: `Blockchain sync mode ("snap" or "full")`, Usage: `Blockchain sync mode ("snap" or "full")`,

View file

@ -19,6 +19,7 @@ package beacon
import ( import (
"errors" "errors"
"fmt" "fmt"
"math"
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -344,6 +345,11 @@ func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.
} }
// Withdrawals processing. // Withdrawals processing.
for _, w := range body.Withdrawals { for _, w := range body.Withdrawals {
if chain.Config().IsDelegationActive(header.Number, header.Time) {
if w.Validator == math.MaxUint64 {
continue
}
}
// Convert amount from gwei to wei. // Convert amount from gwei to wei.
amount := new(uint256.Int).SetUint64(w.Amount) amount := new(uint256.Int).SetUint64(w.Amount)
amount = amount.Mul(amount, uint256.NewInt(params.GWei)) amount = amount.Mul(amount, uint256.NewInt(params.GWei))

View file

@ -18,6 +18,7 @@ package core
import ( import (
"fmt" "fmt"
"math"
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -30,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/triedb" "github.com/ethereum/go-ethereum/triedb"
"github.com/ethereum/go-verkle" "github.com/ethereum/go-verkle"
@ -327,6 +329,17 @@ func (b *BlockGen) collectRequests(readonly bool) (requests [][]byte) {
// create EVM for system calls // create EVM for system calls
blockContext := NewEVMBlockContext(b.header, b.cm, &b.header.Coinbase) blockContext := NewEVMBlockContext(b.header, b.cm, &b.header.Coinbase)
evm := vm.NewEVM(blockContext, statedb, b.cm.config, vm.Config{}) evm := vm.NewEVM(blockContext, statedb, b.cm.config, vm.Config{})
if b.cm.config.IsDelegationActive(b.header.Number, b.header.Time) {
if len(b.withdrawals) > 0 {
firstWithdrawal := b.withdrawals[0]
if firstWithdrawal.Validator == math.MaxUint64 {
amount := new(big.Int).Mul(new(big.Int).SetUint64(firstWithdrawal.Amount), big.NewInt(params.GWei))
if err := ProcessStakingDistribution(evm, firstWithdrawal.Address, amount); err != nil {
log.Error("could not process staking distribution", "err", err)
}
}
}
}
// EIP-7002 // EIP-7002
if err := ProcessWithdrawalQueue(&requests, evm); err != nil { if err := ProcessWithdrawalQueue(&requests, evm); err != nil {
panic(fmt.Sprintf("could not process withdrawal requests: %v", err)) panic(fmt.Sprintf("could not process withdrawal requests: %v", err))

View file

@ -260,6 +260,7 @@ func (e *GenesisMismatchError) Error() string {
type ChainOverrides struct { type ChainOverrides struct {
OverridePrague *uint64 OverridePrague *uint64
OverrideVerkle *uint64 OverrideVerkle *uint64
OverrideDelegationActivation *uint64
} }
// apply applies the chain overrides on the supplied chain config. // apply applies the chain overrides on the supplied chain config.
@ -273,6 +274,9 @@ func (o *ChainOverrides) apply(cfg *params.ChainConfig) error {
if o.OverrideVerkle != nil { if o.OverrideVerkle != nil {
cfg.VerkleTime = o.OverrideVerkle cfg.VerkleTime = o.OverrideVerkle
} }
if o.OverrideDelegationActivation != nil {
cfg.DelegationActivationTime = o.OverrideDelegationActivation
}
return cfg.CheckConfigForkOrder() return cfg.CheckConfigForkOrder()
} }

View file

@ -18,6 +18,7 @@ package core
import ( import (
"fmt" "fmt"
"math"
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -27,7 +28,9 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/holiman/uint256"
) )
// StateProcessor is a basic Processor, which takes care of transitioning // StateProcessor is a basic Processor, which takes care of transitioning
@ -112,6 +115,17 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
if err := ParseDepositLogs(&requests, allLogs, p.config); err != nil { if err := ParseDepositLogs(&requests, allLogs, p.config); err != nil {
return nil, err return nil, err
} }
if p.config.IsDelegationActive(block.Number(), block.Time()) {
if len(block.Withdrawals()) > 0 {
firstWithdrawal := block.Withdrawals()[0]
if firstWithdrawal.Validator == math.MaxUint64 {
amount := new(big.Int).Mul(new(big.Int).SetUint64(firstWithdrawal.Amount), big.NewInt(params.GWei))
if err := ProcessStakingDistribution(evm, firstWithdrawal.Address, amount); err != nil {
log.Error("could not process staking distribution", "err", err)
}
}
}
}
// EIP-7002 // EIP-7002
if err := ProcessWithdrawalQueue(&requests, evm); err != nil { if err := ProcessWithdrawalQueue(&requests, evm); err != nil {
return nil, err return nil, err
@ -279,6 +293,42 @@ func ProcessConsolidationQueue(requests *[][]byte, evm *vm.EVM) error {
return processRequestsSystemCall(requests, evm, 0x02, params.ConsolidationQueueAddress) return processRequestsSystemCall(requests, evm, 0x02, params.ConsolidationQueueAddress)
} }
// ProcessStakingDistribution
func ProcessStakingDistribution(evm *vm.EVM, address common.Address, amount *big.Int) error {
if tracer := evm.Config.Tracer; tracer != nil {
onSystemCallStart(tracer, evm.GetVMContext())
if tracer.OnSystemCallEnd != nil {
defer tracer.OnSystemCallEnd()
}
}
data := make([]byte, 32)
amount.FillBytes(data)
addr := address
msg := &Message{
From: params.SystemAddress,
// Value: amount,
GasLimit: 30_000_000,
GasPrice: common.Big0,
GasFeeCap: common.Big0,
GasTipCap: common.Big0,
To: &addr,
Data: data,
}
evm.SetTxContext(NewEVMTxContext(msg))
evm.StateDB.AddAddressToAccessList(addr)
evm.StateDB.AddBalance(
address,
uint256.NewInt(0).SetBytes(amount.Bytes()),
tracing.BalanceIncreaseRewardMineBlock,
)
_, _, err := evm.Call(msg.From, *msg.To, msg.Data, 30_000_000, common.U2560)
evm.StateDB.Finalise(true)
if err != nil {
return fmt.Errorf("system call failed to execute: %v", err)
}
return nil
}
func processRequestsSystemCall(requests *[][]byte, evm *vm.EVM, requestType byte, addr common.Address) error { func processRequestsSystemCall(requests *[][]byte, evm *vm.EVM, requestType byte, addr common.Address) error {
if tracer := evm.Config.Tracer; tracer != nil { if tracer := evm.Config.Tracer; tracer != nil {
onSystemCallStart(tracer, evm.GetVMContext()) onSystemCallStart(tracer, evm.GetVMContext())

View file

@ -226,6 +226,9 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
if config.OverrideVerkle != nil { if config.OverrideVerkle != nil {
overrides.OverrideVerkle = config.OverrideVerkle overrides.OverrideVerkle = config.OverrideVerkle
} }
if config.OverrideDelegationActivation != nil {
overrides.OverrideDelegationActivation = config.OverrideDelegationActivation
}
eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, config.Genesis, &overrides, eth.engine, vmConfig, &config.TransactionHistory) eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, config.Genesis, &overrides, eth.engine, vmConfig, &config.TransactionHistory)
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -162,6 +162,9 @@ type Config struct {
// OverrideVerkle (TODO: remove after the fork) // OverrideVerkle (TODO: remove after the fork)
OverrideVerkle *uint64 `toml:",omitempty"` OverrideVerkle *uint64 `toml:",omitempty"`
// OverrideDelegationActivation (TODO: remove after the fork)
OverrideDelegationActivation *uint64 `toml:",omitempty"`
} }
// CreateConsensusEngine creates a consensus engine for the given chain config. // CreateConsensusEngine creates a consensus engine for the given chain config.

View file

@ -55,6 +55,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
RPCTxFeeCap float64 RPCTxFeeCap float64
OverridePrague *uint64 `toml:",omitempty"` OverridePrague *uint64 `toml:",omitempty"`
OverrideVerkle *uint64 `toml:",omitempty"` OverrideVerkle *uint64 `toml:",omitempty"`
OverrideDelegationActivation *uint64 `toml:",omitempty"`
} }
var enc Config var enc Config
enc.Genesis = c.Genesis enc.Genesis = c.Genesis
@ -95,6 +96,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
enc.RPCTxFeeCap = c.RPCTxFeeCap enc.RPCTxFeeCap = c.RPCTxFeeCap
enc.OverridePrague = c.OverridePrague enc.OverridePrague = c.OverridePrague
enc.OverrideVerkle = c.OverrideVerkle enc.OverrideVerkle = c.OverrideVerkle
enc.OverrideDelegationActivation = c.OverrideDelegationActivation
return &enc, nil return &enc, nil
} }
@ -139,6 +141,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
RPCTxFeeCap *float64 RPCTxFeeCap *float64
OverridePrague *uint64 `toml:",omitempty"` OverridePrague *uint64 `toml:",omitempty"`
OverrideVerkle *uint64 `toml:",omitempty"` OverrideVerkle *uint64 `toml:",omitempty"`
OverrideDelegationActivation *uint64 `toml:",omitempty"`
} }
var dec Config var dec Config
if err := unmarshal(&dec); err != nil { if err := unmarshal(&dec); err != nil {
@ -258,5 +261,8 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
if dec.OverrideVerkle != nil { if dec.OverrideVerkle != nil {
c.OverrideVerkle = dec.OverrideVerkle c.OverrideVerkle = dec.OverrideVerkle
} }
if dec.OverrideDelegationActivation != nil {
c.OverrideDelegationActivation = dec.OverrideDelegationActivation
}
return nil return nil
} }

View file

@ -21,6 +21,7 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"math"
"math/big" "math/big"
"time" "time"
@ -34,6 +35,7 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/internal/ethapi/override" "github.com/ethereum/go-ethereum/internal/ethapi/override"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
) )
@ -332,6 +334,17 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
if err := core.ParseDepositLogs(&requests, allLogs, sim.chainConfig); err != nil { if err := core.ParseDepositLogs(&requests, allLogs, sim.chainConfig); err != nil {
return nil, nil, nil, err return nil, nil, nil, err
} }
if sim.chainConfig.IsDelegationActive(header.Number, header.Time) {
if block.BlockOverrides.Withdrawals != nil && len(*block.BlockOverrides.Withdrawals) > 0 {
firstWithdrawal := (*block.BlockOverrides.Withdrawals)[0]
if firstWithdrawal.Validator == math.MaxUint64 {
amount := new(big.Int).Mul(new(big.Int).SetUint64(firstWithdrawal.Amount), big.NewInt(params.GWei))
if err := core.ProcessStakingDistribution(evm, firstWithdrawal.Address, amount); err != nil {
log.Error("could not process staking distribution", "err", err)
}
}
}
}
// EIP-7002 // EIP-7002
if err := core.ProcessWithdrawalQueue(&requests, evm); err != nil { if err := core.ProcessWithdrawalQueue(&requests, evm); err != nil {
return nil, nil, nil, err return nil, nil, nil, err

View file

@ -19,6 +19,7 @@ package miner
import ( import (
"errors" "errors"
"fmt" "fmt"
"math"
"math/big" "math/big"
"sync/atomic" "sync/atomic"
"time" "time"
@ -34,6 +35,7 @@ import (
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
ethparams "github.com/ethereum/go-ethereum/params"
"github.com/holiman/uint256" "github.com/holiman/uint256"
) )
@ -126,6 +128,17 @@ func (miner *Miner) generateWork(params *generateParams, witness bool) *newPaylo
if err := core.ParseDepositLogs(&requests, allLogs, miner.chainConfig); err != nil { if err := core.ParseDepositLogs(&requests, allLogs, miner.chainConfig); err != nil {
return &newPayloadResult{err: err} return &newPayloadResult{err: err}
} }
if miner.chainConfig.IsDelegationActive(work.header.Number, work.header.Time) {
if len(params.withdrawals) > 0 {
firstWithdrawal := params.withdrawals[0]
if firstWithdrawal.Validator == math.MaxUint64 {
amount := new(big.Int).Mul(new(big.Int).SetUint64(firstWithdrawal.Amount), big.NewInt(ethparams.GWei))
if err := core.ProcessStakingDistribution(work.evm, firstWithdrawal.Address, amount); err != nil {
log.Error("could not process staking distribution", "err", err)
}
}
}
}
// EIP-7002 // EIP-7002
if err := core.ProcessWithdrawalQueue(&requests, work.evm); err != nil { if err := core.ProcessWithdrawalQueue(&requests, work.evm); err != nil {
return &newPayloadResult{err: err} return &newPayloadResult{err: err}

View file

@ -63,6 +63,8 @@ var (
PragueTime: newUint64(1746612311), PragueTime: newUint64(1746612311),
DepositContractAddress: common.HexToAddress("0x00000000219ab540356cbb839cbe05303d7705fa"), DepositContractAddress: common.HexToAddress("0x00000000219ab540356cbb839cbe05303d7705fa"),
Ethash: new(EthashConfig), Ethash: new(EthashConfig),
// DelegationActivationTime is the activation time of Delegation logic
DelegationActivationTime: newUint64(1746612311),
BlobScheduleConfig: &BlobScheduleConfig{ BlobScheduleConfig: &BlobScheduleConfig{
Cancun: DefaultCancunBlobConfig, Cancun: DefaultCancunBlobConfig,
Prague: DefaultPragueBlobConfig, Prague: DefaultPragueBlobConfig,
@ -93,6 +95,8 @@ var (
PragueTime: newUint64(1740434112), PragueTime: newUint64(1740434112),
DepositContractAddress: common.HexToAddress("0x4242424242424242424242424242424242424242"), DepositContractAddress: common.HexToAddress("0x4242424242424242424242424242424242424242"),
Ethash: new(EthashConfig), Ethash: new(EthashConfig),
// DelegationActivationTime is the activation time of Delegation logic
DelegationActivationTime: newUint64(1740434112),
BlobScheduleConfig: &BlobScheduleConfig{ BlobScheduleConfig: &BlobScheduleConfig{
Cancun: DefaultCancunBlobConfig, Cancun: DefaultCancunBlobConfig,
Prague: DefaultPragueBlobConfig, Prague: DefaultPragueBlobConfig,
@ -123,6 +127,8 @@ var (
PragueTime: newUint64(1741159776), PragueTime: newUint64(1741159776),
DepositContractAddress: common.HexToAddress("0x7f02c3e3c98b133055b8b348b2ac625669ed295d"), DepositContractAddress: common.HexToAddress("0x7f02c3e3c98b133055b8b348b2ac625669ed295d"),
Ethash: new(EthashConfig), Ethash: new(EthashConfig),
// DelegationActivationTime is the activation time of Delegation logic
DelegationActivationTime: newUint64(1741159776),
BlobScheduleConfig: &BlobScheduleConfig{ BlobScheduleConfig: &BlobScheduleConfig{
Cancun: DefaultCancunBlobConfig, Cancun: DefaultCancunBlobConfig,
Prague: DefaultPragueBlobConfig, Prague: DefaultPragueBlobConfig,
@ -153,6 +159,8 @@ var (
PragueTime: newUint64(1742999832), PragueTime: newUint64(1742999832),
DepositContractAddress: common.HexToAddress("0x00000000219ab540356cBB839Cbe05303d7705Fa"), DepositContractAddress: common.HexToAddress("0x00000000219ab540356cBB839Cbe05303d7705Fa"),
Ethash: new(EthashConfig), Ethash: new(EthashConfig),
// DelegationActivationTime is the activation time of Delegation logic
DelegationActivationTime: newUint64(1742999832),
BlobScheduleConfig: &BlobScheduleConfig{ BlobScheduleConfig: &BlobScheduleConfig{
Cancun: DefaultCancunBlobConfig, Cancun: DefaultCancunBlobConfig,
Prague: DefaultPragueBlobConfig, Prague: DefaultPragueBlobConfig,
@ -186,6 +194,8 @@ var (
VerkleTime: nil, VerkleTime: nil,
Ethash: new(EthashConfig), Ethash: new(EthashConfig),
Clique: nil, Clique: nil,
// DelegationActivationTime is the activation time of Delegation logic
DelegationActivationTime: nil,
} }
AllDevChainProtocolChanges = &ChainConfig{ AllDevChainProtocolChanges = &ChainConfig{
@ -207,6 +217,8 @@ var (
CancunTime: newUint64(0), CancunTime: newUint64(0),
TerminalTotalDifficulty: big.NewInt(0), TerminalTotalDifficulty: big.NewInt(0),
PragueTime: newUint64(0), PragueTime: newUint64(0),
// DelegationActivationTime is the activation time of Delegation logic
DelegationActivationTime: newUint64(0),
BlobScheduleConfig: &BlobScheduleConfig{ BlobScheduleConfig: &BlobScheduleConfig{
Cancun: DefaultCancunBlobConfig, Cancun: DefaultCancunBlobConfig,
Prague: DefaultPragueBlobConfig, Prague: DefaultPragueBlobConfig,
@ -241,6 +253,8 @@ var (
TerminalTotalDifficulty: big.NewInt(math.MaxInt64), TerminalTotalDifficulty: big.NewInt(math.MaxInt64),
Ethash: nil, Ethash: nil,
Clique: &CliqueConfig{Period: 0, Epoch: 30000}, Clique: &CliqueConfig{Period: 0, Epoch: 30000},
// DelegationActivationTime is the activation time of Delegation logic
DelegationActivationTime: nil,
} }
// TestChainConfig contains every protocol change (EIPs) introduced // TestChainConfig contains every protocol change (EIPs) introduced
@ -271,6 +285,8 @@ var (
TerminalTotalDifficulty: big.NewInt(math.MaxInt64), TerminalTotalDifficulty: big.NewInt(math.MaxInt64),
Ethash: new(EthashConfig), Ethash: new(EthashConfig),
Clique: nil, Clique: nil,
// DelegationActivationTime is the activation time of Delegation logic
DelegationActivationTime: nil,
} }
// MergedTestChainConfig contains every protocol change (EIPs) introduced // MergedTestChainConfig contains every protocol change (EIPs) introduced
@ -301,6 +317,8 @@ var (
TerminalTotalDifficulty: big.NewInt(0), TerminalTotalDifficulty: big.NewInt(0),
Ethash: new(EthashConfig), Ethash: new(EthashConfig),
Clique: nil, Clique: nil,
// DelegationActivationTime is the activation time of Delegation logic
DelegationActivationTime: newUint64(0),
BlobScheduleConfig: &BlobScheduleConfig{ BlobScheduleConfig: &BlobScheduleConfig{
Cancun: DefaultCancunBlobConfig, Cancun: DefaultCancunBlobConfig,
Prague: DefaultPragueBlobConfig, Prague: DefaultPragueBlobConfig,
@ -335,6 +353,8 @@ var (
TerminalTotalDifficulty: big.NewInt(math.MaxInt64), TerminalTotalDifficulty: big.NewInt(math.MaxInt64),
Ethash: new(EthashConfig), Ethash: new(EthashConfig),
Clique: nil, Clique: nil,
// DelegationActivationTime is the activation time of Delegation logic
DelegationActivationTime: nil,
} }
TestRules = TestChainConfig.Rules(new(big.Int), false, 0) TestRules = TestChainConfig.Rules(new(big.Int), false, 0)
) )
@ -416,6 +436,8 @@ type ChainConfig struct {
TerminalTotalDifficulty *big.Int `json:"terminalTotalDifficulty,omitempty"` TerminalTotalDifficulty *big.Int `json:"terminalTotalDifficulty,omitempty"`
DepositContractAddress common.Address `json:"depositContractAddress,omitempty"` DepositContractAddress common.Address `json:"depositContractAddress,omitempty"`
// DelegationActivationTime is the activation time of Delegation logic
DelegationActivationTime *uint64 `json:"DelegationActivationTime,omitempty"`
// EnableVerkleAtGenesis is a flag that specifies whether the network uses // EnableVerkleAtGenesis is a flag that specifies whether the network uses
// the Verkle tree starting from the genesis block. If set to true, the // the Verkle tree starting from the genesis block. If set to true, the
@ -530,6 +552,9 @@ func (c *ChainConfig) Description() string {
if c.VerkleTime != nil { if c.VerkleTime != nil {
banner += fmt.Sprintf(" - Verkle: @%-10v\n", *c.VerkleTime) banner += fmt.Sprintf(" - Verkle: @%-10v\n", *c.VerkleTime)
} }
if c.DelegationActivationTime != nil {
banner += fmt.Sprintf(" - DelegationActivationTime: @%-10v\n", *c.DelegationActivationTime)
}
return banner return banner
} }
@ -643,6 +668,10 @@ func (c *ChainConfig) IsPrague(num *big.Int, time uint64) bool {
return c.IsLondon(num) && isTimestampForked(c.PragueTime, time) return c.IsLondon(num) && isTimestampForked(c.PragueTime, time)
} }
func (c *ChainConfig) IsDelegationActive(num *big.Int, time uint64) bool {
return c.IsPrague(num, time) && (c.DelegationActivationTime != nil) && (time >= *c.DelegationActivationTime)
}
// IsOsaka returns whether time is either equal to the Osaka fork time or greater. // IsOsaka returns whether time is either equal to the Osaka fork time or greater.
func (c *ChainConfig) IsOsaka(num *big.Int, time uint64) bool { func (c *ChainConfig) IsOsaka(num *big.Int, time uint64) bool {
return c.IsLondon(num) && isTimestampForked(c.OsakaTime, time) return c.IsLondon(num) && isTimestampForked(c.OsakaTime, time)