diff --git a/beacon/engine/gen_blockparams.go b/beacon/engine/gen_blockparams.go index 0dd2b52597..2193b2f976 100644 --- a/beacon/engine/gen_blockparams.go +++ b/beacon/engine/gen_blockparams.go @@ -17,12 +17,14 @@ var _ = (*payloadAttributesMarshaling)(nil) func (p PayloadAttributes) MarshalJSON() ([]byte, error) { type PayloadAttributes struct { Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"` + Number *uint64 `json:"blockNumber,omitempty"` Random common.Hash `json:"prevRandao" gencodec:"required"` SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"` Withdrawals []*types.Withdrawal `json:"withdrawals"` } var enc PayloadAttributes enc.Timestamp = hexutil.Uint64(p.Timestamp) + enc.Number = p.Number enc.Random = p.Random enc.SuggestedFeeRecipient = p.SuggestedFeeRecipient enc.Withdrawals = p.Withdrawals @@ -33,6 +35,7 @@ func (p PayloadAttributes) MarshalJSON() ([]byte, error) { func (p *PayloadAttributes) UnmarshalJSON(input []byte) error { type PayloadAttributes struct { Timestamp *hexutil.Uint64 `json:"timestamp" gencodec:"required"` + Number *uint64 `json:"blockNumber,omitempty"` Random *common.Hash `json:"prevRandao" gencodec:"required"` SuggestedFeeRecipient *common.Address `json:"suggestedFeeRecipient" gencodec:"required"` Withdrawals []*types.Withdrawal `json:"withdrawals"` @@ -45,6 +48,9 @@ func (p *PayloadAttributes) UnmarshalJSON(input []byte) error { return errors.New("missing required field 'timestamp' for PayloadAttributes") } p.Timestamp = uint64(*dec.Timestamp) + if dec.Number != nil { + p.Number = dec.Number + } if dec.Random == nil { return errors.New("missing required field 'prevRandao' for PayloadAttributes") } diff --git a/beacon/engine/types.go b/beacon/engine/types.go index f1801edd1a..9688506ae2 100644 --- a/beacon/engine/types.go +++ b/beacon/engine/types.go @@ -33,6 +33,7 @@ import ( // be built. type PayloadAttributes struct { Timestamp uint64 `json:"timestamp" gencodec:"required"` + Number *uint64 `json:"blockNumber,omitempty"` Random common.Hash `json:"prevRandao" gencodec:"required"` SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"` Withdrawals []*types.Withdrawal `json:"withdrawals"` diff --git a/cmd/evm/internal/t8ntool/transaction.go b/cmd/evm/internal/t8ntool/transaction.go index 001bec55f2..39e86304f0 100644 --- a/cmd/evm/internal/t8ntool/transaction.go +++ b/cmd/evm/internal/t8ntool/transaction.go @@ -145,7 +145,7 @@ func Transaction(ctx *cli.Context) error { eip2f := chainConfig.IsEnabled(chainConfig.GetEIP2Transition, new(big.Int)) eip2028f := chainConfig.IsEnabled(chainConfig.GetEIP2028Transition, new(big.Int)) zero := uint64(0) - eip3860f := chainConfig.IsEnabledByTime(chainConfig.GetEIP3860TransitionTime, &zero) + eip3860f := chainConfig.IsEnabledByTime(chainConfig.GetEIP3860TransitionTime, &zero) || chainConfig.IsEnabled(chainConfig.GetEIP3860Transition, new(big.Int)) // Check intrinsic gas if gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil, @@ -182,7 +182,7 @@ func Transaction(ctx *cli.Context) error { } // Check whether the init code size has been exceeded. // EIP-3860: Limit and meter initcode - if chainConfig.IsEnabledByTime(chainConfig.GetEIP3860TransitionTime, &zero) && tx.To() == nil && uint64(len(tx.Data())) > vars.MaxInitCodeSize { + if (chainConfig.IsEnabledByTime(chainConfig.GetEIP3860TransitionTime, &zero) || chainConfig.IsEnabled(chainConfig.GetEIP3860Transition, new(big.Int))) && tx.To() == nil && uint64(len(tx.Data())) > vars.MaxInitCodeSize { r.Error = errors.New("max initcode size exceeded") } results = append(results, r) diff --git a/cmd/evm/internal/t8ntool/transition.go b/cmd/evm/internal/t8ntool/transition.go index 95ec29adee..37f565a944 100644 --- a/cmd/evm/internal/t8ntool/transition.go +++ b/cmd/evm/internal/t8ntool/transition.go @@ -276,7 +276,7 @@ func Transition(ctx *cli.Context) error { } } // Withdrawals are only valid in Shanghai; EIP-4895. - if chainConfig.IsEnabledByTime(chainConfig.GetEIP4895TransitionTime, &prestate.Env.Number) && prestate.Env.Withdrawals == nil { + if (chainConfig.IsEnabledByTime(chainConfig.GetEIP4895TransitionTime, &prestate.Env.Timestamp) || chainConfig.IsEnabled(chainConfig.GetEIP4895Transition, new(big.Int).SetUint64(prestate.Env.Number))) && prestate.Env.Withdrawals == nil { return NewError(ErrorConfig, errors.New("Shanghai config but missing 'withdrawals' in env section")) } isMerged := chainConfig.GetEthashTerminalTotalDifficulty() != nil && chainConfig.GetEthashTerminalTotalDifficulty().BitLen() == 0 diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go index 03d096623b..bcb3d1cc30 100644 --- a/consensus/beacon/consensus.go +++ b/consensus/beacon/consensus.go @@ -262,7 +262,7 @@ func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, pa return err } // Verify existence / non-existence of withdrawalsHash. - shanghai := chain.Config().IsEnabledByTime(chain.Config().GetEIP4895TransitionTime, &header.Time) + shanghai := chain.Config().IsEnabledByTime(chain.Config().GetEIP4895TransitionTime, &header.Time) || chain.Config().IsEnabled(chain.Config().GetEIP4895Transition, header.Number) if shanghai && header.WithdrawalsHash == nil { return errors.New("missing withdrawalsHash") } @@ -362,7 +362,7 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea if !beacon.IsPoSHeader(header) { return beacon.ethone.FinalizeAndAssemble(chain, header, state, txs, uncles, receipts, nil) } - shanghai := chain.Config().IsEnabledByTime(chain.Config().GetEIP4895TransitionTime, &header.Time) + shanghai := chain.Config().IsEnabledByTime(chain.Config().GetEIP4895TransitionTime, &header.Time) || chain.Config().IsEnabled(chain.Config().GetEIP4895Transition, header.Number) if shanghai { // All blocks after Shanghai must include a withdrawals root. if withdrawals == nil { diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index fbf2a72543..7f3eb1770e 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -300,7 +300,7 @@ func (c *Clique) verifyHeader(chain consensus.ChainHeaderReader, header *types.H if header.GasLimit > vars.MaxGasLimit { return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, vars.MaxGasLimit) } - if chain.Config().IsEnabledByTime(chain.Config().GetEIP3855TransitionTime, &header.Time) { + if chain.Config().IsEnabledByTime(chain.Config().GetEIP3855TransitionTime, &header.Time) || chain.Config().IsEnabled(chain.Config().GetEIP3855Transition, header.Number) { return fmt.Errorf("clique does not support shanghai fork") } if chain.Config().IsEnabledByTime(chain.Config().GetEIP4844TransitionTime, &header.Time) { diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index 500b46235a..45c21b4540 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -278,7 +278,7 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainHeaderReader, header, pa if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(big.NewInt(1)) != 0 { return consensus.ErrInvalidNumber } - if chain.Config().IsEnabledByTime(chain.Config().GetEIP3860TransitionTime, &header.Time) { + if chain.Config().IsEnabledByTime(chain.Config().GetEIP3860TransitionTime, &header.Time) || chain.Config().IsEnabled(chain.Config().GetEIP3860Transition, header.Number) { return fmt.Errorf("ethash does not support shanghai fork") } if chain.Config().IsEnabledByTime(chain.Config().GetEIP4844TransitionTime, &header.Time) { diff --git a/core/forkid/forkid_test.go b/core/forkid/forkid_test.go index 285e73b5d6..04582e0541 100644 --- a/core/forkid/forkid_test.go +++ b/core/forkid/forkid_test.go @@ -372,21 +372,21 @@ func TestValidation(t *testing.T) { // In this case we don't know if Cancun passed yet or not. // // TODO(karalabe): Enable this when Cancun is specced - //{params.MainnetChainConfig, 20000000, 1668000000, ID{Hash: checksumToBytes(0x71147644), Next: 0}, nil}, + // {params.MainnetChainConfig, 20000000, 1668000000, ID{Hash: checksumToBytes(0x71147644), Next: 0}, nil}, // Local is mainnet currently in Shanghai only (so it's aware of Cancun), remote announces // also Shanghai, and it's also aware of Cancun (e.g. updated node before the fork). We // don't know if Cancun passed yet (will pass) or not. // // TODO(karalabe): Enable this when Cancun is specced and update next timestamp - //{params.MainnetChainConfig, 20000000, 1668000000, ID{Hash: checksumToBytes(0x71147644), Next: 1678000000}, nil}, + // {params.MainnetChainConfig, 20000000, 1668000000, ID{Hash: checksumToBytes(0x71147644), Next: 1678000000}, nil}, // Local is mainnet currently in Shanghai only (so it's aware of Cancun), remote announces // also Shanghai, and it's also aware of some random fork (e.g. misconfigured Cancun). As // neither forks passed at neither nodes, they may mismatch, but we still connect for now. // // TODO(karalabe): Enable this when Cancun is specced - //{params.MainnetChainConfig, 20000000, 1668000000, ID{Hash: checksumToBytes(0x71147644), Next: math.MaxUint64}, nil}, + // {params.MainnetChainConfig, 20000000, 1668000000, ID{Hash: checksumToBytes(0x71147644), Next: math.MaxUint64}, nil}, // Local is mainnet exactly on Cancun, remote announces Shanghai + knowledge about Cancun. Remote // is simply out of sync, accept. @@ -397,30 +397,30 @@ func TestValidation(t *testing.T) { // Local is mainnet Cancun, remote announces Shanghai + knowledge about Cancun. Remote // is simply out of sync, accept. // TODO(karalabe): Enable this when Cancun is specced, update local head and time, next timestamp - //{params.MainnetChainConfig, 21123456, 1678123456, ID{Hash: checksumToBytes(0x71147644), Next: 1678000000}, nil}, + // {params.MainnetChainConfig, 21123456, 1678123456, ID{Hash: checksumToBytes(0x71147644), Next: 1678000000}, nil}, // Local is mainnet Prague, remote announces Shanghai + knowledge about Cancun. Remote // is definitely out of sync. It may or may not need the Prague update, we don't know yet. // // TODO(karalabe): Enable this when Cancun **and** Prague is specced, update all the numbers - //{params.MainnetChainConfig, 0, 0, ID{Hash: checksumToBytes(0x3edd5b10), Next: 4370000}, nil}, + // {params.MainnetChainConfig, 0, 0, ID{Hash: checksumToBytes(0x3edd5b10), Next: 4370000}, nil}, // Local is mainnet Shanghai, remote announces Cancun. Local is out of sync, accept. // // TODO(karalabe): Enable this when Cancun is specced, update remote checksum - //{params.MainnetChainConfig, 21000000, 1678000000, ID{Hash: checksumToBytes(0x00000000), Next: 0}, nil}, + // {params.MainnetChainConfig, 21000000, 1678000000, ID{Hash: checksumToBytes(0x00000000), Next: 0}, nil}, // Local is mainnet Shanghai, remote announces Cancun, but is not aware of Prague. Local // out of sync. Local also knows about a future fork, but that is uncertain yet. // // TODO(karalabe): Enable this when Cancun **and** Prague is specced, update remote checksum - //{params.MainnetChainConfig, 21000000, 1678000000, ID{Hash: checksumToBytes(0x00000000), Next: 0}, nil}, + // {params.MainnetChainConfig, 21000000, 1678000000, ID{Hash: checksumToBytes(0x00000000), Next: 0}, nil}, // Local is mainnet Cancun. remote announces Shanghai but is not aware of further forks. // Remote needs software update. // // TODO(karalabe): Enable this when Cancun is specced, update local head and time - //{params.MainnetChainConfig, 21000000, 1678000000, ID{Hash: checksumToBytes(0x71147644), Next: 0}, ErrRemoteStale}, + // {params.MainnetChainConfig, 21000000, 1678000000, ID{Hash: checksumToBytes(0x71147644), Next: 0}, ErrRemoteStale}, // Local is mainnet Shanghai, and isn't aware of more forks. Remote announces Shanghai + // 0xffffffff. Local needs software update, reject. @@ -430,7 +430,7 @@ func TestValidation(t *testing.T) { // 0xffffffff. Local needs software update, reject. // // TODO(karalabe): Enable this when Cancun is specced, update remote checksum - //{params.MainnetChainConfig, 20000000, 1668000000, ID{Hash: checksumToBytes(checksumUpdate(0x00000000, math.MaxUint64)), Next: 0}, ErrLocalIncompatibleOrStale}, + // {params.MainnetChainConfig, 20000000, 1668000000, ID{Hash: checksumToBytes(checksumUpdate(0x00000000, math.MaxUint64)), Next: 0}, ErrLocalIncompatibleOrStale}, // Local is mainnet Shanghai, remote is random Shanghai. {params.MainnetChainConfig, 20000000, 1681338455, ID{Hash: checksumToBytes(0x12345678), Next: 0}, ErrLocalIncompatibleOrStale}, diff --git a/core/genesis.go b/core/genesis.go index 4172a7f51d..857dee8f09 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -96,6 +96,8 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen applyOverrides := func(config ctypes.ChainConfigurator) { if config != nil { + // Block-based overrides are not provided because Shanghai is + // ETH-network specific and that protocol is defined exclusively in time-based forks. if overrides != nil && overrides.OverrideShanghai != nil { config.SetEIP3651TransitionTime(overrides.OverrideShanghai) config.SetEIP3855TransitionTime(overrides.OverrideShanghai) @@ -436,8 +438,9 @@ func GenesisToBlock(g *genesisT.Genesis, db ethdb.Database) *types.Block { } var withdrawals []*types.Withdrawal if conf := g.Config; conf != nil { - isShangai := conf.IsEnabledByTime(g.Config.GetEIP4895TransitionTime, &g.Timestamp) - if isShangai { + // EIP4895 defines the withdwrawals tx type, implemented on ETH in the Shanghai fork. + isEIP4895 := conf.IsEnabledByTime(g.Config.GetEIP4895TransitionTime, &g.Timestamp) || g.Config.IsEnabled(g.Config.GetEIP4895Transition, new(big.Int).SetUint64(g.Number)) + if isEIP4895 { head.WithdrawalsHash = &types.EmptyWithdrawalsHash withdrawals = make([]*types.Withdrawal, 0) } diff --git a/core/state_processor.go b/core/state_processor.go index 5590e6dcc8..036f25eba3 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -96,7 +96,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg // Fail if Shanghai not enabled and len(withdrawals) is non-zero. withdrawals := block.Withdrawals() blockTime := block.Time() - if len(withdrawals) > 0 && !p.config.IsEnabledByTime(p.config.GetEIP4895TransitionTime, &blockTime) { + if len(withdrawals) > 0 && !(p.config.IsEnabledByTime(p.config.GetEIP4895TransitionTime, &blockTime) || p.config.IsEnabled(p.config.GetEIP4895Transition, blockNumber)) { return nil, nil, 0, fmt.Errorf("withdrawals before shanghai") } // Finalize the block, applying any consensus engine specific extras (e.g. block rewards) diff --git a/core/state_processor_test.go b/core/state_processor_test.go index 0258ef7f86..7135d5b2c2 100644 --- a/core/state_processor_test.go +++ b/core/state_processor_test.go @@ -451,7 +451,7 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr if config.IsEnabled(config.GetEIP1559Transition, header.Number) { header.BaseFee = eip1559.CalcBaseFee(config, parent.Header()) } - if config.IsEnabledByTime(config.GetEIP4895TransitionTime, &header.Time) { + if config.IsEnabledByTime(config.GetEIP4895TransitionTime, &header.Time) || config.IsEnabled(config.GetEIP4895Transition, header.Number) { header.WithdrawalsHash = &types.EmptyWithdrawalsHash } var receipts []*types.Receipt @@ -485,7 +485,7 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr header.BlobGasUsed = &used } // Assemble and return the final block for sealing - if config.IsEnabledByTime(config.GetEIP4895TransitionTime, &header.Time) { + if config.IsEnabledByTime(config.GetEIP4895TransitionTime, &header.Time) || config.IsEnabled(config.GetEIP4895Transition, header.Number) { return types.NewBlockWithWithdrawals(header, txs, nil, receipts, []*types.Withdrawal{}, trie.NewStackTrie(nil)) } return types.NewBlock(header, txs, nil, receipts, trie.NewStackTrie(nil)) diff --git a/core/state_transition.go b/core/state_transition.go index 5893b16934..0aa7af9f04 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -399,10 +399,12 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) { eip3529f = st.evm.ChainConfig().IsEnabled(st.evm.ChainConfig().GetEIP3529Transition, st.evm.Context.BlockNumber) // EIP-3860: Limit and meter initcode - eip3860f = st.evm.ChainConfig().IsEnabledByTime(st.evm.ChainConfig().GetEIP3860TransitionTime, &st.evm.Context.Time) + eip3860f = st.evm.ChainConfig().IsEnabledByTime(st.evm.ChainConfig().GetEIP3860TransitionTime, &st.evm.Context.Time) || + st.evm.ChainConfig().IsEnabled(st.evm.ChainConfig().GetEIP3860Transition, st.evm.Context.BlockNumber) // EIP-3651: Warm coinbase - eip3651f = st.evm.ChainConfig().IsEnabledByTime(st.evm.ChainConfig().GetEIP3651TransitionTime, &st.evm.Context.Time) + eip3651f = st.evm.ChainConfig().IsEnabledByTime(st.evm.ChainConfig().GetEIP3651TransitionTime, &st.evm.Context.Time) || + st.evm.ChainConfig().IsEnabled(st.evm.ChainConfig().GetEIP3651Transition, st.evm.Context.BlockNumber) ) // Check clauses 4-5, subtract intrinsic gas if everything is correct diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go index 37b0bbac4a..9901eb03a9 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -193,7 +193,7 @@ func instructionSetForConfig(config ctypes.ChainConfigurator, isPostMerge bool, if config.IsEnabled(config.GetEIP3198Transition, bn) { enable3198(instructionSet) // BASEFEE opcode https://eips.ethereum.org/EIPS/eip-3198 } - if isPostMerge { + if isPostMerge || config.IsEnabled(config.GetEIP4399Transition, bn) { // EIP4399: Supplant DIFFICULTY opcode with PREVRANDAO (ETH @ PoS) instructionSet[PREVRANDAO] = &operation{ execute: opRandom, constantGas: GasQuickStep, @@ -203,10 +203,10 @@ func instructionSetForConfig(config ctypes.ChainConfigurator, isPostMerge bool, } // Shangai - if config.IsEnabledByTime(config.GetEIP3855TransitionTime, bt) { + if config.IsEnabledByTime(config.GetEIP3855TransitionTime, bt) || config.IsEnabled(config.GetEIP3855Transition, bn) { enable3855(instructionSet) // PUSH0 instruction } - if config.IsEnabledByTime(config.GetEIP3860TransitionTime, bt) { + if config.IsEnabledByTime(config.GetEIP3860TransitionTime, bt) || config.IsEnabled(config.GetEIP3860Transition, bn) { enable3860(instructionSet) // Limit and meter initcode } diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go index 593d6c9dbc..c6b68256a8 100644 --- a/core/vm/runtime/runtime.go +++ b/core/vm/runtime/runtime.go @@ -124,7 +124,8 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) { // Shanghai // EIP-3651: Warm coinbase - eip3651f = cfg.ChainConfig.IsEnabledByTime(cfg.ChainConfig.GetEIP3651TransitionTime, &vmenv.Context.Time) + eip3651f = cfg.ChainConfig.IsEnabledByTime(cfg.ChainConfig.GetEIP3651TransitionTime, &vmenv.Context.Time) || + cfg.ChainConfig.IsEnabled(cfg.ChainConfig.GetEIP3651Transition, vmenv.Context.BlockNumber) ) // Execute the preparatory steps for state transition which includes: // - prepare accessList(post-berlin) @@ -165,7 +166,8 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) { // Shanghai // EIP-3651: Warm coinbase - eip3651f = cfg.ChainConfig.IsEnabledByTime(cfg.ChainConfig.GetEIP3651TransitionTime, &vmenv.Context.Time) + eip3651f = cfg.ChainConfig.IsEnabledByTime(cfg.ChainConfig.GetEIP3651TransitionTime, &vmenv.Context.Time) || + cfg.ChainConfig.IsEnabled(cfg.ChainConfig.GetEIP3651Transition, vmenv.Context.BlockNumber) ) // Execute the preparatory steps for state transition which includes: // - prepare accessList(post-berlin) @@ -200,7 +202,8 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, er // Shanghai // EIP-3651: Warm coinbase - eip3651f = cfg.ChainConfig.IsEnabledByTime(cfg.ChainConfig.GetEIP3651TransitionTime, &vmenv.Context.Time) + eip3651f = cfg.ChainConfig.IsEnabledByTime(cfg.ChainConfig.GetEIP3651TransitionTime, &vmenv.Context.Time) || + cfg.ChainConfig.IsEnabled(cfg.ChainConfig.GetEIP3651Transition, vmenv.Context.BlockNumber) ) // Execute the preparatory steps for state transition which includes: // - prepare accessList(post-berlin) diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go index 1aa9951620..f8aecb17ad 100644 --- a/eth/catalyst/api.go +++ b/eth/catalyst/api.go @@ -20,6 +20,7 @@ package catalyst import ( "errors" "fmt" + "math/big" "sync" "time" @@ -169,7 +170,11 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV1(update engine.ForkchoiceStateV1, pa if payloadAttributes.Withdrawals != nil { return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("withdrawals not supported in V1")) } - if api.eth.BlockChain().Config().IsEnabledByTime(api.eth.BlockChain().Config().GetEIP4895TransitionTime, &payloadAttributes.Timestamp) { + eip4895 := api.eth.BlockChain().Config().IsEnabledByTime(api.eth.BlockChain().Config().GetEIP4895TransitionTime, &payloadAttributes.Timestamp) + if payloadAttributes.Number != nil { + eip4895 = eip4895 || api.eth.BlockChain().Config().IsEnabled(api.eth.BlockChain().Config().GetEIP4895Transition, new(big.Int).SetUint64(*payloadAttributes.Number)) + } + if eip4895 { return engine.STATUS_INVALID, engine.InvalidParams.With(fmt.Errorf("forkChoiceUpdateV1 called post-shanghai")) } } @@ -187,7 +192,11 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV2(update engine.ForkchoiceStateV1, pa } func (api *ConsensusAPI) verifyPayloadAttributes(attr *engine.PayloadAttributes) error { - if !api.eth.BlockChain().Config().IsEnabledByTime(api.eth.BlockChain().Config().GetEIP4895TransitionTime, &attr.Timestamp) { + eip4895 := api.eth.BlockChain().Config().IsEnabledByTime(api.eth.BlockChain().Config().GetEIP4895TransitionTime, &attr.Timestamp) + if attr.Number != nil { + eip4895 = eip4895 || api.eth.BlockChain().Config().IsEnabled(api.eth.BlockChain().Config().GetEIP4895Transition, new(big.Int).SetUint64(*attr.Number)) + } + if !eip4895 { // Reject payload attributes with withdrawals before shanghai if attr.Withdrawals != nil { return errors.New("withdrawals before shanghai") @@ -431,7 +440,7 @@ func (api *ConsensusAPI) NewPayloadV1(params engine.ExecutableData) (engine.Payl // NewPayloadV2 creates an Eth1 block, inserts it in the chain, and returns the status of the chain. func (api *ConsensusAPI) NewPayloadV2(params engine.ExecutableData) (engine.PayloadStatusV1, error) { - if api.eth.BlockChain().Config().IsEnabledByTime(api.eth.BlockChain().Config().GetEIP4895TransitionTime, ¶ms.Timestamp) { + if api.eth.BlockChain().Config().IsEnabledByTime(api.eth.BlockChain().Config().GetEIP4895TransitionTime, ¶ms.Timestamp) || api.eth.BlockChain().Config().IsEnabled(api.eth.BlockChain().Config().GetEIP4895Transition, new(big.Int).SetUint64(params.Number)) { if params.Withdrawals == nil { return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai")) } diff --git a/eth/catalyst/api_test.go b/eth/catalyst/api_test.go index 4d59165445..50897fa7c9 100644 --- a/eth/catalyst/api_test.go +++ b/eth/catalyst/api_test.go @@ -1274,11 +1274,11 @@ func setupBodies(t *testing.T) (*node.Node, *eth.Ethereum, []*types.Block) { // enable shanghai on the last block time := blocks[len(blocks)-1].Header().Time + 1 // enable shanghai on the last block - genesis.Config.SetEIP3651TransitionTime(&time) - genesis.Config.SetEIP3855TransitionTime(&time) - genesis.Config.SetEIP3860TransitionTime(&time) - genesis.Config.SetEIP4895TransitionTime(&time) - genesis.Config.SetEIP6049TransitionTime(&time) + genesis.Config.SetEIP3651TransitionTime(&time) // SetEIP3651Transition is not implemented in this test helper. + genesis.Config.SetEIP3855TransitionTime(&time) // SetEIP3855Transition is not implemented in this test helper. + genesis.Config.SetEIP3860TransitionTime(&time) // SetEIP3860Transition is not implemented in this test helper. + genesis.Config.SetEIP4895TransitionTime(&time) // SetEIP4895Transition is not implemented in this test helper. + genesis.Config.SetEIP6049TransitionTime(&time) // SetEIP6049Transition is not implemented in this test helper. n, ethservice := startEthService(t, genesis, blocks) var ( diff --git a/light/txpool.go b/light/txpool.go index 46a1ef9a6b..688cc7493f 100644 --- a/light/txpool.go +++ b/light/txpool.go @@ -339,7 +339,7 @@ func (pool *TxPool) setNewHead(head *types.Header) { pool.eip2028f = pool.config.IsEnabled(pool.config.GetEIP2028Transition, next) pool.eip2718 = pool.config.IsEnabled(pool.config.GetEIP2718Transition, next) now := uint64(time.Now().Unix()) - pool.eip3860 = pool.config.IsEnabledByTime(pool.config.GetEIP3860TransitionTime, &now) + pool.eip3860 = pool.config.IsEnabledByTime(pool.config.GetEIP3860TransitionTime, &now) || pool.config.IsEnabled(pool.config.GetEIP3860Transition, next) } // Stop stops the light transaction pool diff --git a/params/config_classic.go b/params/config_classic.go index 471ddb5c9e..ceba7d4ffe 100644 --- a/params/config_classic.go +++ b/params/config_classic.go @@ -94,6 +94,14 @@ var ( EIP3529FBlock: big.NewInt(14_525_000), EIP3541FBlock: big.NewInt(14_525_000), + // Spiral, aka Shanghai (partially) + // EIP4399FBlock: nil, // Supplant DIFFICULTY with PREVRANDAO. ETC does not spec 4399 because it's still PoW, and 4399 is only applicable for the PoS system. + EIP3651FBlock: nil, // Warm COINBASE (gas reprice) + EIP3855FBlock: nil, // PUSH0 instruction + EIP3860FBlock: nil, // Limit and meter initcode + // EIP4895FBlock: nil, // Beacon chain push withdrawals as operations + EIP6049FBlock: nil, // Deprecate SELFDESTRUCT (noop) + RequireBlockHashes: map[uint64]common.Hash{ 1920000: common.HexToHash("0x94365e3a8c0b35089c1d1195081fe7489b528a84b22199c916180db8b28ade7f"), 2500000: common.HexToHash("0xca12c63534f565899681965528d536c52cb05b7c48e269c2a6cb77ad864d878a"), diff --git a/params/config_mordor.go b/params/config_mordor.go index 1540a1c689..a1dd40dc02 100644 --- a/params/config_mordor.go +++ b/params/config_mordor.go @@ -80,6 +80,14 @@ var ( EIP3529FBlock: big.NewInt(5_520_000), EIP3541FBlock: big.NewInt(5_520_000), + // Spiral, aka Shanghai (partially) + // EIP4399FBlock: nil, // Supplant DIFFICULTY with PREVRANDAO. ETC does not spec 4399 because it's still PoW, and 4399 is only applicable for the PoS system. + EIP3651FBlock: nil, // Warm COINBASE (gas reprice) + EIP3855FBlock: nil, // PUSH0 instruction + EIP3860FBlock: nil, // Limit and meter initcode + // EIP4895FBlock: nil, // Beacon chain push withdrawals as operations + EIP6049FBlock: nil, // Deprecate SELFDESTRUCT (noop) + DisposalBlock: big.NewInt(0), ECIP1017FBlock: big.NewInt(0), ECIP1017EraRounds: big.NewInt(2000000), diff --git a/params/types/coregeth/chain_config.go b/params/types/coregeth/chain_config.go index 968ceceffe..7e37900ccf 100644 --- a/params/types/coregeth/chain_config.go +++ b/params/types/coregeth/chain_config.go @@ -225,6 +225,13 @@ type CoreGethChainConfig struct { EIP4895FTime *uint64 `json:"eip4895FTime,omitempty"` // EIP-4895: Beacon chain push withdrawals as operations EIP6049FTime *uint64 `json:"eip6049FTime,omitempty"` // EIP-6049: Deprecate SELFDESTRUCT. Note: EIP-6049 does not change the behavior of SELFDESTRUCT in and of itself, but formally announces client developers' intention of changing it in future upgrades. It is recommended that software which exposes the SELFDESTRUCT opcode to users warn them about an upcoming change in semantics. + // Shanghai with block activations + EIP3651FBlock *big.Int `json:"eip3651FBlock,omitempty"` // EIP-3651: Warm COINBASE + EIP3855FBlock *big.Int `json:"eip3855FBlock,omitempty"` // EIP-3855: PUSH0 instruction + EIP3860FBlock *big.Int `json:"eip3860FBlock,omitempty"` // EIP-3860: Limit and meter initcode + EIP4895FBlock *big.Int `json:"eip4895FBlock,omitempty"` // EIP-4895: Beacon chain push withdrawals as operations + EIP6049FBlock *big.Int `json:"eip6049FBlock,omitempty"` // EIP-6049: Deprecate SELFDESTRUCT. Note: EIP-6049 does not change the behavior of SELFDESTRUCT in and of itself, but formally announces client developers' intention of changing it in future upgrades. It is recommended that software which exposes the SELFDESTRUCT opcode to users warn them about an upcoming change in semantics. + // Cancun EIP4844FTime *uint64 `json:"eip4844FTime,omitempty"` // EIP-4844: Shard Blob Transactions https://eips.ethereum.org/EIPS/eip-4844 EIP1153FTime *uint64 `json:"eip1153FTime,omitempty"` // EIP-1153: Transient Storage opcodes https://eips.ethereum.org/EIPS/eip-1153 diff --git a/params/types/coregeth/chain_config_configurator.go b/params/types/coregeth/chain_config_configurator.go index e11e279d1b..2f34271355 100644 --- a/params/types/coregeth/chain_config_configurator.go +++ b/params/types/coregeth/chain_config_configurator.go @@ -564,6 +564,57 @@ func (c *CoreGethChainConfig) SetEIP6049TransitionTime(n *uint64) error { return nil } +// Shanghai by block +// EIP3651: Warm COINBASE +func (c *CoreGethChainConfig) GetEIP3651Transition() *uint64 { + return bigNewU64(c.EIP3651FBlock) +} + +func (c *CoreGethChainConfig) SetEIP3651Transition(n *uint64) error { + c.EIP3651FBlock = setBig(c.EIP3651FBlock, n) + return nil +} + +// GetEIP3855Transition EIP3855: PUSH0 instruction +func (c *CoreGethChainConfig) GetEIP3855Transition() *uint64 { + return bigNewU64(c.EIP3855FBlock) +} + +func (c *CoreGethChainConfig) SetEIP3855Transition(n *uint64) error { + c.EIP3855FBlock = setBig(c.EIP3855FBlock, n) + return nil +} + +// GetEIP3860Transition EIP3860: Limit and meter initcode +func (c *CoreGethChainConfig) GetEIP3860Transition() *uint64 { + return bigNewU64(c.EIP3860FBlock) +} + +func (c *CoreGethChainConfig) SetEIP3860Transition(n *uint64) error { + c.EIP3860FBlock = setBig(c.EIP3860FBlock, n) + return nil +} + +// GetEIP4895Transition EIP4895: Beacon chain push withdrawals as operations +func (c *CoreGethChainConfig) GetEIP4895Transition() *uint64 { + return bigNewU64(c.EIP4895FBlock) +} + +func (c *CoreGethChainConfig) SetEIP4895Transition(n *uint64) error { + c.EIP4895FBlock = setBig(c.EIP4895FBlock, n) + return nil +} + +// GetEIP6049Transition EIP6049: Deprecate SELFDESTRUCT +func (c *CoreGethChainConfig) GetEIP6049Transition() *uint64 { + return bigNewU64(c.EIP6049FBlock) +} + +func (c *CoreGethChainConfig) SetEIP6049Transition(n *uint64) error { + c.EIP6049FBlock = setBig(c.EIP6049FBlock, n) + return nil +} + // GetEIP4844TransitionTime EIP4844: Shard Blob Transactions func (c *CoreGethChainConfig) GetEIP4844TransitionTime() *uint64 { return c.EIP4844FTime diff --git a/params/types/ctypes/configurator_iface.go b/params/types/ctypes/configurator_iface.go index 7d9ccac97e..166312f639 100644 --- a/params/types/ctypes/configurator_iface.go +++ b/params/types/ctypes/configurator_iface.go @@ -196,6 +196,18 @@ type ProtocolSpecifier interface { GetEIP6049TransitionTime() *uint64 SetEIP6049TransitionTime(n *uint64) error + // Shanghai expressed as block activation numbers: + GetEIP3651Transition() *uint64 + SetEIP3651Transition(n *uint64) error + GetEIP3855Transition() *uint64 + SetEIP3855Transition(n *uint64) error + GetEIP3860Transition() *uint64 + SetEIP3860Transition(n *uint64) error + GetEIP4895Transition() *uint64 + SetEIP4895Transition(n *uint64) error + GetEIP6049Transition() *uint64 + SetEIP6049Transition(n *uint64) error + // GetMergeVirtualTransition is a Virtual fork after The Merge to use as a network splitter GetMergeVirtualTransition() *uint64 SetMergeVirtualTransition(n *uint64) error diff --git a/params/types/genesisT/genesis.go b/params/types/genesisT/genesis.go index 97676daee0..de7cf98bb6 100644 --- a/params/types/genesisT/genesis.go +++ b/params/types/genesisT/genesis.go @@ -116,6 +116,46 @@ func (g *Genesis) SetEIP6049TransitionTime(n *uint64) error { return g.Config.SetEIP6049TransitionTime(n) } +func (g *Genesis) GetEIP3651Transition() *uint64 { + return g.Config.GetEIP3651Transition() +} + +func (g *Genesis) SetEIP3651Transition(n *uint64) error { + return g.Config.SetEIP3651Transition(n) +} + +func (g *Genesis) GetEIP3855Transition() *uint64 { + return g.Config.GetEIP3855Transition() +} + +func (g *Genesis) SetEIP3855Transition(n *uint64) error { + return g.Config.SetEIP3855Transition(n) +} + +func (g *Genesis) GetEIP3860Transition() *uint64 { + return g.Config.GetEIP3860Transition() +} + +func (g *Genesis) SetEIP3860Transition(n *uint64) error { + return g.Config.SetEIP3860Transition(n) +} + +func (g *Genesis) GetEIP4895Transition() *uint64 { + return g.Config.GetEIP4895Transition() +} + +func (g *Genesis) SetEIP4895Transition(n *uint64) error { + return g.Config.SetEIP4895Transition(n) +} + +func (g *Genesis) GetEIP6049Transition() *uint64 { + return g.Config.GetEIP6049Transition() +} + +func (g *Genesis) SetEIP6049Transition(n *uint64) error { + return g.Config.SetEIP6049Transition(n) +} + func (g *Genesis) GetEIP4844TransitionTime() *uint64 { return g.Config.GetEIP4844TransitionTime() } diff --git a/params/types/goethereum/goethereum_configurator.go b/params/types/goethereum/goethereum_configurator.go index c70a36e389..65b9db3550 100644 --- a/params/types/goethereum/goethereum_configurator.go +++ b/params/types/goethereum/goethereum_configurator.go @@ -592,6 +592,51 @@ func (c *ChainConfig) SetEIP6049TransitionTime(n *uint64) error { return nil } +// EIP3651: Warm COINBASE +func (c *ChainConfig) GetEIP3651Transition() *uint64 { + return nil +} + +func (c *ChainConfig) SetEIP3651Transition(n *uint64) error { + return ctypes.ErrUnsupportedConfigNoop +} + +// GetEIP3855Transition EIP3855: PUSH0 instruction +func (c *ChainConfig) GetEIP3855Transition() *uint64 { + return nil +} + +func (c *ChainConfig) SetEIP3855Transition(n *uint64) error { + return ctypes.ErrUnsupportedConfigNoop +} + +// GetEIP3860Transition EIP3860: Limit and meter initcode +func (c *ChainConfig) GetEIP3860Transition() *uint64 { + return nil +} + +func (c *ChainConfig) SetEIP3860Transition(n *uint64) error { + return ctypes.ErrUnsupportedConfigNoop +} + +// GetEIP4895Transition EIP4895: Beacon chain push withdrawals as operations +func (c *ChainConfig) GetEIP4895Transition() *uint64 { + return nil +} + +func (c *ChainConfig) SetEIP4895Transition(n *uint64) error { + return ctypes.ErrUnsupportedConfigNoop +} + +// GetEIP6049Transition EIP6049: Deprecate SELFDESTRUCT +func (c *ChainConfig) GetEIP6049Transition() *uint64 { + return nil +} + +func (c *ChainConfig) SetEIP6049Transition(n *uint64) error { + return ctypes.ErrUnsupportedConfigNoop +} + // GetEIP4844TransitionTime EIP4844: Shard Block Transactions func (c *ChainConfig) GetEIP4844TransitionTime() *uint64 { return c.CancunTime diff --git a/tests/init.go b/tests/init.go index f15088af6c..1ea643e456 100644 --- a/tests/init.go +++ b/tests/init.go @@ -521,6 +521,76 @@ var Forks = map[string]ctypes.ChainConfigurator{ TerminalTotalDifficulty: big.NewInt(0), ShanghaiTime: u64(15_000), }, + "ETC_Spiral": &coregeth.CoreGethChainConfig{ + NetworkID: 1, + Ethash: new(ctypes.EthashConfig), + ChainID: big.NewInt(61), + EIP2FBlock: big.NewInt(0), + EIP7FBlock: big.NewInt(0), + EIP150Block: big.NewInt(0), + EIP155Block: big.NewInt(0), + EIP160FBlock: big.NewInt(0), + EIP161FBlock: big.NewInt(0), + EIP170FBlock: big.NewInt(0), + EIP100FBlock: big.NewInt(0), + EIP140FBlock: big.NewInt(0), + EIP198FBlock: big.NewInt(0), + EIP211FBlock: big.NewInt(0), + EIP212FBlock: big.NewInt(0), + EIP213FBlock: big.NewInt(0), + EIP214FBlock: big.NewInt(0), + EIP658FBlock: big.NewInt(0), + EIP145FBlock: big.NewInt(0), + EIP1014FBlock: big.NewInt(0), + EIP1052FBlock: big.NewInt(0), + EIP1283FBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + // Istanbul eq, aka Phoenix + // ECIP-1088 + EIP152FBlock: big.NewInt(0), + EIP1108FBlock: big.NewInt(0), + EIP1344FBlock: big.NewInt(0), + EIP1884FBlock: big.NewInt(0), + EIP2028FBlock: big.NewInt(0), + EIP2200FBlock: big.NewInt(0), // RePetersburg (=~ re-1283) + + // Berlin + EIP2565FBlock: big.NewInt(0), + EIP2929FBlock: big.NewInt(0), + EIP2718FBlock: big.NewInt(0), + EIP2930FBlock: big.NewInt(0), + + // London + /* + https://github.com/ethereumclassic/ECIPs/blob/master/_specs/ecip-1104.md + + 3529 (Alternative refund reduction) #22733 Include + 3541 (Reject new contracts starting with the 0xEF byte) #22809 Include + 1559 (Fee market change) #22837 #22896 Omit + 3198 (BASEFEE opcode) #22837 Omit + 3228 (bomb delay) #22840 and #22870 Omit + */ + EIP3529FBlock: big.NewInt(0), + EIP3541FBlock: big.NewInt(0), + EIP1559FBlock: nil, + EIP3198FBlock: nil, + EIP3554FBlock: nil, + + // Shanghai == Spiral + EIP4399FBlock: nil, // Supplant DIFFICULTY with PREVRANDAO. ETC does not spec 4399 because it's still PoW, and 4399 is only applicable for the PoS system. + EIP3651FBlock: big.NewInt(0), // Warm COINBASE (gas reprice) + EIP3855FBlock: big.NewInt(0), // PUSH0 instruction + EIP3860FBlock: big.NewInt(0), // Limit and meter initcode + EIP4895FBlock: nil, // Beacon chain push withdrawals as operations + EIP6049FBlock: big.NewInt(0), // Deprecate SELFDESTRUCT (noop) + + // ETC specifics + DisposalBlock: big.NewInt(0), + ECIP1017FBlock: big.NewInt(5000000), // FIXME(meows) maybe + ECIP1017EraRounds: big.NewInt(5000000), + ECIP1010PauseBlock: nil, + ECIP1010Length: nil, + }, "Cancun": &goethereum.ChainConfig{ ChainID: big.NewInt(1), HomesteadBlock: big.NewInt(0), diff --git a/tests/state_test.go b/tests/state_test.go index 3f94a26b93..faddad2709 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -289,7 +289,8 @@ func runBenchmark(b *testing.B, t *StateTest) { // Shanghai // EIP-3651: Warm coinbase - eip3651f = config.IsEnabledByTime(config.GetEIP3651TransitionTime, &evm.Context.Time) + eip3651f = config.IsEnabledByTime(config.GetEIP3651TransitionTime, &evm.Context.Time) || + config.IsEnabled(config.GetEIP3651Transition, evm.Context.BlockNumber) ) b.ResetTimer() for n := 0; n < b.N; n++ {