diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index 2c885f402a58..51ba6a81c1dc 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -672,7 +672,7 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transa return fmt.Errorf("could not fetch parent") } // Check transaction validity - signer := types.MakeSigner(b.blockchain.Config(), block.Number()) + signer := types.MakeSigner(b.blockchain.Config(), block.Number(), block.Time()) sender, err := types.Sender(signer, tx) if err != nil { return fmt.Errorf("invalid transaction: %v", err) diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index a05dbedea700..5ef0f96bd036 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -123,7 +123,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, } var ( statedb = MakePreState(rawdb.NewMemoryDatabase(), pre.Pre) - signer = types.MakeSigner(chainConfig, new(big.Int).SetUint64(pre.Env.Number)) + signer = types.MakeSigner(chainConfig, new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp) gaspool = new(core.GasPool) blockHash = common.Hash{0x13, 0x37} rejectedTxs []*rejectedTx diff --git a/cmd/evm/internal/t8ntool/transaction.go b/cmd/evm/internal/t8ntool/transaction.go index 3409c0a3bf01..3dd026264a70 100644 --- a/cmd/evm/internal/t8ntool/transaction.go +++ b/cmd/evm/internal/t8ntool/transaction.go @@ -112,7 +112,7 @@ func Transaction(ctx *cli.Context) error { return NewError(ErrorIO, errors.New("only rlp supported")) } } - signer := types.MakeSigner(chainConfig, new(big.Int)) + signer := types.MakeSigner(chainConfig, new(big.Int), 0) // We now have the transactions in 'body', which is supposed to be an // rlp list of transactions it, err := rlp.NewListIterator([]byte(body)) diff --git a/cmd/evm/internal/t8ntool/transition.go b/cmd/evm/internal/t8ntool/transition.go index 8b05f1def9db..38f93a170ad7 100644 --- a/cmd/evm/internal/t8ntool/transition.go +++ b/cmd/evm/internal/t8ntool/transition.go @@ -241,7 +241,7 @@ func Transition(ctx *cli.Context) error { } } // We may have to sign the transactions. - signer := types.MakeSigner(chainConfig, big.NewInt(int64(prestate.Env.Number))) + signer := types.MakeSigner(chainConfig, big.NewInt(int64(prestate.Env.Number)), prestate.Env.Timestamp) if txs, err = signUnsignedTransactions(txsWithKeys, signer); err != nil { return NewError(ErrorJson, fmt.Errorf("failed signing transactions: %v", err)) diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go index 75e454852f27..5fb89629bcbc 100644 --- a/consensus/beacon/consensus.go +++ b/consensus/beacon/consensus.go @@ -269,7 +269,7 @@ func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, pa return err } } - shanghai := chain.Config().IsShanghai(header.Number) + shanghai := chain.Config().IsShanghai(header.Time) if shanghai && header.WithdrawalsHash == nil { return fmt.Errorf("missing withdrawalsHash") } @@ -277,7 +277,7 @@ func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, pa if !shanghai && header.WithdrawalsHash != nil { return fmt.Errorf("invalid withdrawalsHash: have %s, expected nil", header.WithdrawalsHash) } - if chain.Config().IsSharding(header.Number) { + if chain.Config().IsSharding(header.Time) { // Verify the header's EIP-4844 attributes. if err := misc.VerifyEip4844Header(chain.Config(), parent, header); err != nil { return err @@ -350,7 +350,7 @@ func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types. return } // If withdrawals have been activated, process each one. - if chain.Config().IsShanghai(header.Number) { + if chain.Config().IsShanghai(header.Time) { for _, w := range withdrawals { state.AddBalance(w.Address, w.Amount) } @@ -358,7 +358,7 @@ func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types. // The block reward is no longer handled here. It's done by the // external consensus engine. header.Root = state.IntermediateRoot(true) - if chain.Config().IsSharding(header.Number) { + if chain.Config().IsSharding(header.Time) { if parent := chain.GetHeaderByHash(header.ParentHash); parent != nil { header.SetExcessDataGas(misc.CalcExcessDataGas(parent.ExcessDataGas, misc.CountBlobs(txs))) } else { diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index c84697f821eb..47bb587ce499 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -345,7 +345,7 @@ func (c *Clique) verifyCascadingFields(chain consensus.ChainHeaderReader, header // Verify the header's EIP-1559 attributes. return err } - if !chain.Config().IsSharding(header.Number) { + if !chain.Config().IsSharding(header.Time) { if header.ExcessDataGas != nil { return fmt.Errorf("invalid excessDataGas before fork: have %v, want ", header.ExcessDataGas) } @@ -576,7 +576,7 @@ func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Heade // No block rewards in PoA, so the state remains as is and uncles are dropped header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) header.UncleHash = types.CalcUncleHash(nil) - if chain.Config().IsSharding(header.Number) { + if chain.Config().IsSharding(header.Time) { if parent := chain.GetHeaderByHash(header.ParentHash); parent != nil { header.SetExcessDataGas(misc.CalcExcessDataGas(parent.ExcessDataGas, misc.CountBlobs(txs))) } else { diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index 52e103e0abf3..5c7a9f8d1f0a 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -306,7 +306,7 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainHeaderReader, header, pa // Verify the header's EIP-1559 attributes. return err } - if !chain.Config().IsSharding(header.Number) { + if !chain.Config().IsSharding(header.Time) { if header.ExcessDataGas != nil { return fmt.Errorf("invalid excessDataGas before fork: have %v, expected 'nil'", header.ExcessDataGas) } @@ -609,7 +609,7 @@ func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types. // Accumulate any block and uncle rewards and commit the final state root accumulateRewards(chain.Config(), state, header, uncles) header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) - if chain.Config().IsSharding(header.Number) { + if chain.Config().IsSharding(header.Time) { if parent := chain.GetHeaderByHash(header.ParentHash); parent != nil { header.SetExcessDataGas(misc.CalcExcessDataGas(parent.ExcessDataGas, misc.CountBlobs(txs))) } else { diff --git a/core/bench_test.go b/core/bench_test.go index f7cf0146060d..bad598274cf8 100644 --- a/core/bench_test.go +++ b/core/bench_test.go @@ -84,7 +84,7 @@ func genValueTx(nbytes int) func(int, *BlockGen) { toaddr := common.Address{} data := make([]byte, nbytes) gas, _ := IntrinsicGas(data, nil, false, false, false) - signer := types.MakeSigner(gen.config, big.NewInt(int64(i))) + signer := types.MakeSigner(gen.config, big.NewInt(int64(i)), 0) gasPrice := big.NewInt(0) if gen.header.BaseFee != nil { gasPrice = gen.header.BaseFee @@ -128,7 +128,7 @@ func genTxRing(naccounts int) func(int, *BlockGen) { if gen.header.BaseFee != nil { gasPrice = gen.header.BaseFee } - signer := types.MakeSigner(gen.config, big.NewInt(int64(i))) + signer := types.MakeSigner(gen.config, big.NewInt(int64(i)), 0) for { gas -= params.TxGas if gas < params.TxGas { diff --git a/core/blockchain.go b/core/blockchain.go index 5c90256fe2cf..910da91a3491 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1488,7 +1488,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool) } // Start a parallel signature recovery (signer will fluke on fork transition, minimal perf loss) - SenderCacher.RecoverFromBlocks(types.MakeSigner(bc.chainConfig, chain[0].Number()), chain) + SenderCacher.RecoverFromBlocks(types.MakeSigner(bc.chainConfig, chain[0].Number(), chain[0].Time()), chain) var ( stats = insertStats{startTime: mclock.Now()} diff --git a/core/blockchain_test.go b/core/blockchain_test.go index b45cc56d3de2..07d550bf5762 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -4138,7 +4138,8 @@ func TestDataBlobTxs(t *testing.T) { // Genesis (block 0): AllEthhashProtocolChanges // Block 1 : "" // Block 2 : Sharding - gspec.Config.ShardingForkBlock = common.Big2 + var time uint64 = 2 * 10 // block time is 10 seconds, so this corresponds to second block. + gspec.Config.ShardingForkTime = &time genesis := gspec.MustCommit(db) signer := types.LatestSigner(gspec.Config) @@ -4158,7 +4159,7 @@ func TestDataBlobTxs(t *testing.T) { msg.GasFeeCap.SetFromBig(newGwei(5)) msg.GasTipCap.SetFromBig(big.NewInt(2)) msg.MaxFeePerDataGas.SetFromBig(big.NewInt(params.MinDataGasPrice)) - // TODO: Add test case for max data fee too low + // TODO(eip-4844): Add test case for max data fee too low msg.BlobVersionedHashes = []common.Hash{one, two} txdata := &types.SignedBlobTx{Message: msg} @@ -4332,7 +4333,7 @@ func TestEIP3651(t *testing.T) { gspec.Config.BerlinBlock = common.Big0 gspec.Config.LondonBlock = common.Big0 - gspec.Config.ShanghaiBlock = common.Big0 + gspec.Config.ShanghaiTime = new(uint64) signer := types.LatestSigner(gspec.Config) _, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) { diff --git a/core/chain_makers.go b/core/chain_makers.go index a30f78381f9c..0af66c28046a 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -164,6 +164,10 @@ func (b *BlockGen) Number() *big.Int { return new(big.Int).Set(b.header.Number) } +func (b *BlockGen) Time() uint64 { + return b.header.Time +} + // BaseFee returns the EIP-1559 base fee of the block being generated. func (b *BlockGen) BaseFee() *big.Int { return new(big.Int).Set(b.header.BaseFee) @@ -291,7 +295,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse } if b.engine != nil { // Finalize and seal the block - shanghai := config.IsShanghai(b.header.Number) + shanghai := config.IsShanghai(b.header.Time) if shanghai && b.withdrawals == nil { // need to make empty list to denote non-nil, but empty withdrawals to calc withdrawals hash b.withdrawals = make([]*types.Withdrawal, 0) diff --git a/core/genesis.go b/core/genesis.go index 0a23d941e83b..175540b1abf6 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -478,7 +478,7 @@ func (g *Genesis) ToBlock() *types.Block { head.BaseFee = new(big.Int).SetUint64(params.InitialBaseFee) } } - if g.Config.IsSharding(common.Big0) { + if g.Config.IsSharding(0) { head.SetExcessDataGas(g.ExcessDataGas) } } diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index 16c2f60ad089..0ca9292e4f4d 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -636,7 +636,12 @@ func ReadReceipts(db ethdb.Reader, hash common.Hash, number uint64, config *para log.Error("Missing body but have receipt", "hash", hash, "number", number) return nil } - if err := receipts.DeriveFields(config, hash, number, body.Transactions); err != nil { + header := ReadHeader(db, hash, number) // fetch the header to get the block time + if header == nil { + log.Error("Failed to retrieve block header", "hash", hash, "number", number) + return nil + } + if err := receipts.DeriveFields(config, hash, number, header.Time, body.Transactions); err != nil { log.Error("Failed to derive block receipts fields", "hash", hash, "number", number, "err", err) return nil } diff --git a/core/rawdb/accessors_chain_test.go b/core/rawdb/accessors_chain_test.go index 21d23e1f0c8b..36774c11a0ec 100644 --- a/core/rawdb/accessors_chain_test.go +++ b/core/rawdb/accessors_chain_test.go @@ -377,13 +377,20 @@ func TestBlockReceiptStorage(t *testing.T) { receipt2.Bloom = types.CreateBloom(types.Receipts{receipt2}) receipts := []*types.Receipt{receipt1, receipt2} + header := types.Header{ + Number: big.NewInt(0), + Time: 0, + Extra: []byte("test read receipts"), + } + hash := header.Hash() + // Check that no receipt entries are in a pristine database - hash := common.BytesToHash([]byte{0x03, 0x14}) if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); len(rs) != 0 { t.Fatalf("non existent receipts returned: %v", rs) } - // Insert the body that corresponds to the receipts + // Insert the body & header that corresponds to the receipts WriteBody(db, hash, 0, body) + WriteHeader(db, &header) // Insert the receipt slice into the database and check presence WriteReceipts(db, hash, 0, receipts) @@ -751,7 +758,7 @@ func TestReadLogs(t *testing.T) { } // Fill in log fields so we can compare their rlp encoding - if err := types.Receipts(receipts).DeriveFields(params.TestChainConfig, hash, 0, body.Transactions); err != nil { + if err := types.Receipts(receipts).DeriveFields(params.TestChainConfig, hash, 0, 0, body.Transactions); err != nil { t.Fatal(err) } for i, pr := range receipts { diff --git a/core/state_prefetcher.go b/core/state_prefetcher.go index c5760b1790b2..7b407ba1fd2a 100644 --- a/core/state_prefetcher.go +++ b/core/state_prefetcher.go @@ -54,7 +54,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, excessDataGas *big.Int, s gaspool = new(GasPool).AddGas(block.GasLimit()).AddDataGas(params.MaxDataGasPerBlock) blockContext = NewEVMBlockContext(header, excessDataGas, p.bc, nil) evm = vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg) - signer = types.MakeSigner(p.config, header.Number) + signer = types.MakeSigner(p.config, header.Number, header.Time) ) // Iterate over and process the individual transactions byzantium := p.config.IsByzantium(block.Number()) diff --git a/core/state_processor.go b/core/state_processor.go index 30347f840007..46a4a6d12a5b 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -63,6 +63,7 @@ func (p *StateProcessor) Process(block *types.Block, excessDataGas *big.Int, sta header = block.Header() blockHash = block.Hash() blockNumber = block.Number() + blockTime = block.Time() allLogs []*types.Log gp = new(GasPool).AddGas(block.GasLimit()).AddDataGas(params.MaxDataGasPerBlock) ) @@ -74,12 +75,12 @@ func (p *StateProcessor) Process(block *types.Block, excessDataGas *big.Int, sta vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg) // Iterate over and process the individual transactions for i, tx := range block.Transactions() { - msg, err := tx.AsMessage(types.MakeSigner(p.config, header.Number), header.BaseFee) + msg, err := tx.AsMessage(types.MakeSigner(p.config, header.Number, header.Time), header.BaseFee) if err != nil { return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) } statedb.SetTxContext(tx.Hash(), i) - receipt, err := applyTransaction(msg, p.config, nil, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv) + receipt, err := applyTransaction(msg, p.config, nil, gp, statedb, blockNumber, blockTime, blockHash, tx, usedGas, vmenv) if err != nil { return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) } @@ -87,7 +88,7 @@ func (p *StateProcessor) Process(block *types.Block, excessDataGas *big.Int, sta allLogs = append(allLogs, receipt.Logs...) } // Fail if Shanghai not enabled and len(withdrawals) is non-zero. - if !p.config.IsShanghai(block.Number()) && len(block.Withdrawals()) != 0 { + if !p.config.IsShanghai(header.Time) && len(block.Withdrawals()) != 0 { return nil, nil, 0, fmt.Errorf("non-nil withdrawal before shanghai") } // Finalize the block, applying any consensus engine specific extras (e.g. block rewards) @@ -96,7 +97,7 @@ func (p *StateProcessor) Process(block *types.Block, excessDataGas *big.Int, sta return receipts, allLogs, *usedGas, nil } -func applyTransaction(msg types.Message, config *params.ChainConfig, author *common.Address, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, error) { +func applyTransaction(msg types.Message, config *params.ChainConfig, author *common.Address, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockTime uint64, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, error) { // Create a new context to be used in the EVM environment. txContext := NewEVMTxContext(msg) evm.Reset(txContext, statedb) @@ -146,12 +147,12 @@ func applyTransaction(msg types.Message, config *params.ChainConfig, author *com // for the transaction, gas used and an error if the transaction failed, // indicating the block was invalid. func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, excessDataGas *big.Int, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, error) { - msg, err := tx.AsMessage(types.MakeSigner(config, header.Number), header.BaseFee) + msg, err := tx.AsMessage(types.MakeSigner(config, header.Number, header.Time), header.BaseFee) if err != nil { return nil, err } // Create a new context to be used in the EVM environment blockContext := NewEVMBlockContext(header, excessDataGas, bc, author) vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, config, cfg) - return applyTransaction(msg, config, author, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv) + return applyTransaction(msg, config, author, gp, statedb, header.Number, header.Time, header.Hash(), tx, usedGas, vmenv) } diff --git a/core/state_transition.go b/core/state_transition.go index ec434b8f3ed3..e6b9d3c2a37f 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -193,7 +193,10 @@ func (st *StateTransition) buyGas() error { // compute data fee for eip-4844 data blobs if any dgval := new(big.Int) var dataGasUsed uint64 - if st.evm.ChainConfig().IsSharding(st.evm.Context.BlockNumber) { + if st.evm.ChainConfig().IsSharding(st.evm.Context.Time.Uint64()) { + if st.evm.Context.ExcessDataGas == nil { + return fmt.Errorf("sharding is active but ExcessDataGas is nil. Time: %v", st.evm.Context.Time.Uint64()) + } dgu := st.dataGasUsed() if !dgu.IsUint64() { return fmt.Errorf("data gas usage overflow: address %v have %v", st.msg.From().Hex(), dgu) @@ -281,7 +284,7 @@ func (st *StateTransition) preCheck() error { } } usesDataGas := st.dataGasUsed().Sign() > 0 - if usesDataGas && st.evm.ChainConfig().IsSharding(st.evm.Context.BlockNumber) { + if usesDataGas && st.evm.ChainConfig().IsSharding(st.evm.Context.Time.Uint64()) { dataGasPrice := misc.GetDataGasPrice(st.evm.Context.ExcessDataGas) if dataGasPrice.Cmp(st.msg.MaxFeePerDataGas()) > 0 { return fmt.Errorf("%w: address %v, maxFeePerDataGas: %v dataGasPrice: %v, excessDataGas: %v", @@ -330,7 +333,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) { var ( msg = st.msg sender = vm.AccountRef(msg.From()) - rules = st.evm.ChainConfig().Rules(st.evm.Context.BlockNumber, st.evm.Context.Random != nil) + rules = st.evm.ChainConfig().Rules(st.evm.Context.BlockNumber, st.evm.Context.Time.Uint64(), st.evm.Context.Random != nil) contractCreation = msg.To() == nil ) diff --git a/core/txpool/txpool.go b/core/txpool/txpool.go index 69e116ae6b58..24f66353035d 100644 --- a/core/txpool/txpool.go +++ b/core/txpool/txpool.go @@ -1406,7 +1406,7 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) { pool.istanbul = pool.chainconfig.IsIstanbul(next) pool.eip2718 = pool.chainconfig.IsBerlin(next) pool.eip1559 = pool.chainconfig.IsLondon(next) - pool.eip4844 = pool.chainconfig.IsSharding(next) + pool.eip4844 = pool.chainconfig.IsSharding(uint64(time.Now().Unix())) } // promoteExecutables moves transactions that have become processable from the diff --git a/core/types/receipt.go b/core/types/receipt.go index 09a86a96bc79..f5f76958d18d 100644 --- a/core/types/receipt.go +++ b/core/types/receipt.go @@ -401,8 +401,8 @@ func (rs Receipts) EncodeIndex(i int, w *bytes.Buffer) { // DeriveFields fills the receipts with their computed fields based on consensus // data and contextual infos like containing block and transactions. -func (rs Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, number uint64, txs Transactions) error { - signer := MakeSigner(config, new(big.Int).SetUint64(number)) +func (rs Receipts) DeriveFields(config *params.ChainConfig, hash common.Hash, number uint64, time uint64, txs Transactions) error { + signer := MakeSigner(config, new(big.Int).SetUint64(number), time) logIndex := uint(0) if len(txs) != len(rs) { diff --git a/core/types/receipt_test.go b/core/types/receipt_test.go index 6f0953bdec7d..f3b5fba4725a 100644 --- a/core/types/receipt_test.go +++ b/core/types/receipt_test.go @@ -287,14 +287,15 @@ func TestDeriveFields(t *testing.T) { } // Clear all the computed fields and re-derive them number := big.NewInt(1) + var time uint64 hash := common.BytesToHash([]byte{0x03, 0x14}) clearComputedFieldsOnReceipts(t, receipts) - if err := receipts.DeriveFields(params.TestChainConfig, hash, number.Uint64(), txs); err != nil { + if err := receipts.DeriveFields(params.TestChainConfig, hash, number.Uint64(), time, txs); err != nil { t.Fatalf("DeriveFields(...) = %v, want ", err) } // Iterate over all the computed fields and check that they're correct - signer := MakeSigner(params.TestChainConfig, number) + signer := MakeSigner(params.TestChainConfig, number, 0) logIndex := uint(0) for i := range receipts { diff --git a/core/types/transaction_signing.go b/core/types/transaction_signing.go index a5989bf1ce0c..c1a6afa63791 100644 --- a/core/types/transaction_signing.go +++ b/core/types/transaction_signing.go @@ -36,11 +36,11 @@ type sigCache struct { from common.Address } -// MakeSigner returns a Signer based on the given chain config and block number. -func MakeSigner(config *params.ChainConfig, blockNumber *big.Int) Signer { +// MakeSigner returns a Signer based on the given chain config, block number and time. +func MakeSigner(config *params.ChainConfig, blockNumber *big.Int, time uint64) Signer { var signer Signer switch { - case config.IsSharding(blockNumber): + case config.IsSharding(time): signer = NewDankSigner(config.ChainID) case config.IsLondon(blockNumber): signer = NewLondonSigner(config.ChainID) @@ -65,7 +65,7 @@ func MakeSigner(config *params.ChainConfig, blockNumber *big.Int) Signer { // have the current block number available, use MakeSigner instead. func LatestSigner(config *params.ChainConfig) Signer { if config.ChainID != nil { - if config.ShardingForkBlock != nil { + if config.ShardingForkTime != nil { return NewDankSigner(config.ChainID) } if config.LondonBlock != nil { diff --git a/core/vm/evm.go b/core/vm/evm.go index 2f0998407326..67eafe62d97c 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -136,7 +136,7 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig StateDB: statedb, Config: config, chainConfig: chainConfig, - chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil), + chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Time.Uint64(), blockCtx.Random != nil), } evm.interpreter = NewEVMInterpreter(evm, config) return evm diff --git a/core/vm/gas_table_test.go b/core/vm/gas_table_test.go index 6cd126c9b4ca..f864d001756c 100644 --- a/core/vm/gas_table_test.go +++ b/core/vm/gas_table_test.go @@ -88,6 +88,7 @@ func TestEIP2200(t *testing.T) { statedb.Finalise(true) // Push the state into the "original" slot vmctx := BlockContext{ + Time: big.NewInt(0), CanTransfer: func(StateDB, common.Address, *big.Int) bool { return true }, Transfer: func(StateDB, common.Address, common.Address, *big.Int) {}, } diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go index d1620ce29ecf..fd67c100e57c 100644 --- a/core/vm/instructions_test.go +++ b/core/vm/instructions_test.go @@ -46,6 +46,9 @@ type twoOperandParams struct { var alphabetSoup = "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff" var commonParams []*twoOperandParams var twoOpMethods map[string]executionFunc +var emptyContext BlockContext = BlockContext{ + Time: big.NewInt(0), +} type contractRef struct { addr common.Address @@ -102,7 +105,7 @@ func init() { func testTwoOperandOp(t *testing.T, tests []TwoOperandTestcase, opFn executionFunc, name string) { var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) + env = NewEVM(emptyContext, TxContext{}, nil, params.TestChainConfig, Config{}) stack = newstack() pc = uint64(0) evmInterpreter = env.interpreter @@ -201,7 +204,7 @@ func TestSAR(t *testing.T) { func TestAddMod(t *testing.T) { var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) + env = NewEVM(emptyContext, TxContext{}, nil, params.TestChainConfig, Config{}) stack = newstack() evmInterpreter = NewEVMInterpreter(env, env.Config) pc = uint64(0) @@ -245,7 +248,7 @@ func TestWriteExpectedValues(t *testing.T) { // getResult is a convenience function to generate the expected values getResult := func(args []*twoOperandParams, opFn executionFunc) []TwoOperandTestcase { var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) + env = NewEVM(emptyContext, TxContext{}, nil, params.TestChainConfig, Config{}) stack = newstack() pc = uint64(0) interpreter = env.interpreter @@ -290,7 +293,7 @@ func TestJsonTestcases(t *testing.T) { func opBenchmark(bench *testing.B, op executionFunc, args ...string) { var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) + env = NewEVM(emptyContext, TxContext{}, nil, params.TestChainConfig, Config{}) stack = newstack() scope = &ScopeContext{nil, stack, nil} evmInterpreter = NewEVMInterpreter(env, env.Config) @@ -531,7 +534,7 @@ func BenchmarkOpIsZero(b *testing.B) { func TestOpMstore(t *testing.T) { var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) + env = NewEVM(emptyContext, TxContext{}, nil, params.TestChainConfig, Config{}) stack = newstack() mem = NewMemory() evmInterpreter = NewEVMInterpreter(env, env.Config) @@ -557,7 +560,7 @@ func TestOpMstore(t *testing.T) { func BenchmarkOpMstore(bench *testing.B) { var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) + env = NewEVM(emptyContext, TxContext{}, nil, params.TestChainConfig, Config{}) stack = newstack() mem = NewMemory() evmInterpreter = NewEVMInterpreter(env, env.Config) @@ -580,7 +583,7 @@ func BenchmarkOpMstore(bench *testing.B) { func TestOpTstore(t *testing.T) { var ( statedb, _ = state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - env = NewEVM(BlockContext{}, TxContext{}, statedb, params.TestChainConfig, Config{}) + env = NewEVM(emptyContext, TxContext{}, statedb, params.TestChainConfig, Config{}) stack = newstack() mem = NewMemory() evmInterpreter = NewEVMInterpreter(env, env.Config) @@ -622,7 +625,7 @@ func TestOpTstore(t *testing.T) { func BenchmarkOpKeccak256(bench *testing.B) { var ( - env = NewEVM(BlockContext{}, TxContext{}, nil, params.TestChainConfig, Config{}) + env = NewEVM(emptyContext, TxContext{}, nil, params.TestChainConfig, Config{}) stack = newstack() mem = NewMemory() evmInterpreter = NewEVMInterpreter(env, env.Config) @@ -726,7 +729,7 @@ func TestRandom(t *testing.T) { {name: "hash(0x010203)", random: crypto.Keccak256Hash([]byte{0x01, 0x02, 0x03})}, } { var ( - env = NewEVM(BlockContext{Random: &tt.random}, TxContext{}, nil, params.TestChainConfig, Config{}) + env = NewEVM(BlockContext{Random: &tt.random, Time: big.NewInt(0)}, TxContext{}, nil, params.TestChainConfig, Config{}) stack = newstack() pc = uint64(0) evmInterpreter = env.interpreter @@ -766,7 +769,7 @@ func TestDataHash(t *testing.T) { {name: "out-of-bounds", idx: 25, expect: zero, hashes: []common.Hash{one, two, three}}, } { var ( - env = NewEVM(BlockContext{}, TxContext{DataHashes: tt.hashes}, nil, params.TestChainConfig, Config{}) + env = NewEVM(emptyContext, TxContext{DataHashes: tt.hashes}, nil, params.TestChainConfig, Config{}) stack = newstack() pc = uint64(0) evmInterpreter = env.interpreter diff --git a/core/vm/interpreter_test.go b/core/vm/interpreter_test.go index 31ee9922dbac..ee7d9dccc432 100644 --- a/core/vm/interpreter_test.go +++ b/core/vm/interpreter_test.go @@ -38,6 +38,7 @@ var loopInterruptTests = []string{ func TestLoopInterrupt(t *testing.T) { address := common.BytesToAddress([]byte("contract")) vmctx := BlockContext{ + Time: big.NewInt(0), Transfer: func(StateDB, common.Address, common.Address, *big.Int) {}, } diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go index 6b355deeb6e2..f5cf236ffa59 100644 --- a/core/vm/runtime/runtime.go +++ b/core/vm/runtime/runtime.go @@ -117,13 +117,12 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) { address = common.BytesToAddress([]byte("contract")) vmenv = NewEnv(cfg) sender = vm.AccountRef(cfg.Origin) - rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil) + rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Time.Uint64(), vmenv.Context.Random != nil) ) // Execute the preparatory steps for state transition which includes: // - prepare accessList(post-berlin) // - reset transient storage(eip 1153) cfg.State.Prepare(rules, cfg.Origin, cfg.Coinbase, &address, vm.ActivePrecompiles(rules), nil) - cfg.State.CreateAccount(address) // set the receiver's (the executing contract) code for execution. cfg.State.SetCode(address, code) @@ -151,7 +150,7 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) { var ( vmenv = NewEnv(cfg) sender = vm.AccountRef(cfg.Origin) - rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil) + rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Time.Uint64(), vmenv.Context.Random != nil) ) // Execute the preparatory steps for state transition which includes: // - prepare accessList(post-berlin) @@ -180,7 +179,7 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, er vmenv = NewEnv(cfg) sender = cfg.State.GetOrNewStateObject(cfg.Origin) statedb = cfg.State - rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil) + rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Time.Uint64(), vmenv.Context.Random != nil) ) // Execute the preparatory steps for state transition which includes: // - prepare accessList(post-berlin) diff --git a/eth/downloader/queue_test.go b/eth/downloader/queue_test.go index 6babf9440869..30f8e86dbc18 100644 --- a/eth/downloader/queue_test.go +++ b/eth/downloader/queue_test.go @@ -42,7 +42,7 @@ func makeChain(n int, seed byte, parent *types.Block, empty bool) ([]*types.Bloc block.SetCoinbase(common.Address{seed}) // Add one tx to every secondblock if !empty && i%2 == 0 { - signer := types.MakeSigner(params.TestChainConfig, block.Number()) + signer := types.MakeSigner(params.TestChainConfig, block.Number(), block.Time()) tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, block.BaseFee(), nil), signer, testKey) if err != nil { panic(err) diff --git a/eth/downloader/testchain_test.go b/eth/downloader/testchain_test.go index 01f81a7b1cde..ee1fd94c8c97 100644 --- a/eth/downloader/testchain_test.go +++ b/eth/downloader/testchain_test.go @@ -168,7 +168,7 @@ func (tc *testChain) generate(n int, seed byte, parent *types.Block, heavy bool) } // Include transactions to the miner to make blocks more interesting. if parent == tc.blocks[0] && i%22 == 0 { - signer := types.MakeSigner(params.TestChainConfig, block.Number()) + signer := types.MakeSigner(params.TestChainConfig, block.Number(), block.Time()) tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, block.BaseFee(), nil), signer, testKey) if err != nil { panic(err) diff --git a/eth/fetcher/block_fetcher_test.go b/eth/fetcher/block_fetcher_test.go index a64f42fef7d2..3088083aaef3 100644 --- a/eth/fetcher/block_fetcher_test.go +++ b/eth/fetcher/block_fetcher_test.go @@ -64,7 +64,7 @@ func init() { ArrowGlacierBlock: big.NewInt(0), GrayGlacierBlock: big.NewInt(0), MergeNetsplitBlock: big.NewInt(0), - ShanghaiBlock: big.NewInt(0), + ShanghaiTime: new(uint64), TerminalTotalDifficulty: big.NewInt(0), TerminalTotalDifficultyPassed: true, Ethash: new(params.EthashConfig), @@ -87,7 +87,7 @@ func makeChain(n int, seed byte, parent *types.Block) ([]common.Hash, map[common // If the block number is multiple of 3, send a bonus transaction to the miner if parent == genesis && i%3 == 0 { - signer := types.MakeSigner(params.TestChainConfig, block.Number()) + signer := types.MakeSigner(params.TestChainConfig, block.Number(), block.Time()) tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, block.BaseFee(), nil), signer, testKey) if err != nil { panic(err) diff --git a/eth/gasprice/gasprice.go b/eth/gasprice/gasprice.go index 604ad5e10432..96a697e28754 100644 --- a/eth/gasprice/gasprice.go +++ b/eth/gasprice/gasprice.go @@ -176,7 +176,7 @@ func (oracle *Oracle) SuggestTipCap(ctx context.Context) (*big.Int, error) { results []*big.Int ) for sent < oracle.checkBlocks && number > 0 { - go oracle.getBlockValues(ctx, types.MakeSigner(oracle.backend.ChainConfig(), big.NewInt(int64(number))), number, sampleNumber, oracle.ignorePrice, result, quit) + go oracle.getBlockValues(ctx, types.MakeSigner(oracle.backend.ChainConfig(), big.NewInt(int64(number)), head.Time), number, sampleNumber, oracle.ignorePrice, result, quit) sent++ exp++ number-- @@ -199,7 +199,7 @@ func (oracle *Oracle) SuggestTipCap(ctx context.Context) (*big.Int, error) { // meaningful returned, try to query more blocks. But the maximum // is 2*checkBlocks. if len(res.values) == 1 && len(results)+1+exp < oracle.checkBlocks*2 && number > 0 { - go oracle.getBlockValues(ctx, types.MakeSigner(oracle.backend.ChainConfig(), big.NewInt(int64(number))), number, sampleNumber, oracle.ignorePrice, result, quit) + go oracle.getBlockValues(ctx, types.MakeSigner(oracle.backend.ChainConfig(), big.NewInt(int64(number)), head.Time), number, sampleNumber, oracle.ignorePrice, result, quit) sent++ exp++ number-- diff --git a/eth/protocols/eth/handler_test.go b/eth/protocols/eth/handler_test.go index a5b9f5f0bd3e..3c2bed2f4118 100644 --- a/eth/protocols/eth/handler_test.go +++ b/eth/protocols/eth/handler_test.go @@ -90,7 +90,7 @@ func newTestBackendWithGenerator(blocks int, shanghai bool, generator func(int, ArrowGlacierBlock: big.NewInt(0), GrayGlacierBlock: big.NewInt(0), MergeNetsplitBlock: big.NewInt(0), - ShanghaiBlock: big.NewInt(0), + ShanghaiTime: new(uint64), TerminalTotalDifficulty: big.NewInt(0), TerminalTotalDifficultyPassed: true, Ethash: new(params.EthashConfig), diff --git a/eth/state_accessor.go b/eth/state_accessor.go index 81a902965e71..59ef496b4ecd 100644 --- a/eth/state_accessor.go +++ b/eth/state_accessor.go @@ -203,7 +203,7 @@ func (eth *Ethereum) stateAtTransaction(block *types.Block, txIndex int, reexec return nil, vm.BlockContext{}, statedb, release, nil } // Recompute transactions up to the target index. - signer := types.MakeSigner(eth.blockchain.Config(), block.Number()) + signer := types.MakeSigner(eth.blockchain.Config(), block.Number(), block.Time()) for idx, tx := range block.Transactions() { // Assemble the transaction call message and return if the requested offset msg, _ := tx.AsMessage(signer, block.BaseFee()) diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 6018877fbd41..61ff0d442f56 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -286,7 +286,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed // Fetch and execute the next block trace taskCh for task := range taskCh { - signer := types.MakeSigner(api.backend.ChainConfig(), task.block.Number()) + signer := types.MakeSigner(api.backend.ChainConfig(), task.block.Number(), task.block.Time()) var excessDataGas *big.Int parent, err := api.backend.BlockByHash(ctx, task.block.ParentHash()) if err != nil { @@ -549,7 +549,7 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config var ( roots []common.Hash - signer = types.MakeSigner(api.backend.ChainConfig(), block.Number()) + signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()) chainConfig = api.backend.ChainConfig() vmctx = core.NewEVMBlockContext(block.Header(), parent.Header().ExcessDataGas, api.chainContext(ctx), nil) deleteEmptyObjects = chainConfig.IsEIP158(block.Number()) @@ -612,7 +612,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac // Execute all the transaction contained within the block concurrently var ( - signer = types.MakeSigner(api.backend.ChainConfig(), block.Number()) + signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()) txs = block.Transactions() results = make([]*txTraceResult, len(txs)) @@ -716,7 +716,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block // Execute transaction, either tracing all or just the requested one var ( dumps []string - signer = types.MakeSigner(api.backend.ChainConfig(), block.Number()) + signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()) chainConfig = api.backend.ChainConfig() vmctx = core.NewEVMBlockContext(block.Header(), parent.Header().ExcessDataGas, api.chainContext(ctx), nil) canon = true diff --git a/eth/tracers/api_test.go b/eth/tracers/api_test.go index 7fb3a3c31a15..c8accfee6edb 100644 --- a/eth/tracers/api_test.go +++ b/eth/tracers/api_test.go @@ -173,7 +173,7 @@ func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block return nil, vm.BlockContext{}, statedb, release, nil } // Recompute transactions up to the target index. - signer := types.MakeSigner(b.chainConfig, block.Number()) + signer := types.MakeSigner(b.chainConfig, block.Number(), block.Time()) for idx, tx := range block.Transactions() { msg, _ := tx.AsMessage(signer, block.BaseFee()) txContext := core.NewEVMTxContext(msg) diff --git a/eth/tracers/internal/tracetest/calltrace_test.go b/eth/tracers/internal/tracetest/calltrace_test.go index 0827d3b40e41..dba597f3061d 100644 --- a/eth/tracers/internal/tracetest/calltrace_test.go +++ b/eth/tracers/internal/tracetest/calltrace_test.go @@ -122,7 +122,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) { } // Configure a blockchain with the given prestate var ( - signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number))) + signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time)) origin, _ = signer.Sender(tx) txContext = vm.TxContext{ Origin: origin, @@ -219,7 +219,7 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) { if err := rlp.DecodeBytes(common.FromHex(test.Input), tx); err != nil { b.Fatalf("failed to parse testcase input: %v", err) } - signer := types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number))) + signer := types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time)) msg, err := tx.AsMessage(signer, nil) if err != nil { b.Fatalf("failed to prepare transaction for tracing: %v", err) diff --git a/eth/tracers/internal/tracetest/prestate_test.go b/eth/tracers/internal/tracetest/prestate_test.go index 9227aff9453d..801447ef896c 100644 --- a/eth/tracers/internal/tracetest/prestate_test.go +++ b/eth/tracers/internal/tracetest/prestate_test.go @@ -92,7 +92,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) { } // Configure a blockchain with the given prestate var ( - signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number))) + signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time)) origin, _ = signer.Sender(tx) txContext = vm.TxContext{ Origin: origin, diff --git a/eth/tracers/js/goja.go b/eth/tracers/js/goja.go index ceb591a79afe..dd01ff09c133 100644 --- a/eth/tracers/js/goja.go +++ b/eth/tracers/js/goja.go @@ -243,7 +243,7 @@ func (t *jsTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Addr t.ctx["value"] = valueBig t.ctx["block"] = t.vm.ToValue(env.Context.BlockNumber.Uint64()) // Update list of precompiles based on current block - rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil) + rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Time.Uint64(), env.Context.Random != nil) t.activePrecompiles = vm.ActivePrecompiles(rules) } diff --git a/eth/tracers/js/tracer_test.go b/eth/tracers/js/tracer_test.go index 6a916f55b2a7..3b5a6b93f054 100644 --- a/eth/tracers/js/tracer_test.go +++ b/eth/tracers/js/tracer_test.go @@ -57,7 +57,7 @@ type vmContext struct { } func testCtx() *vmContext { - return &vmContext{blockCtx: vm.BlockContext{BlockNumber: big.NewInt(1)}, txCtx: vm.TxContext{GasPrice: big.NewInt(100000)}} + return &vmContext{blockCtx: vm.BlockContext{BlockNumber: big.NewInt(1), Time: big.NewInt(1)}, txCtx: vm.TxContext{GasPrice: big.NewInt(100000)}} } func runTrace(tracer tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainConfig, contractCode []byte) (json.RawMessage, error) { @@ -180,7 +180,7 @@ func TestHaltBetweenSteps(t *testing.T) { if err != nil { t.Fatal(err) } - env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(1)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer}) + env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1), Time: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(1)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer}) scope := &vm.ScopeContext{ Contract: vm.NewContract(&account{}, &account{}, big.NewInt(0), 0), } @@ -204,7 +204,7 @@ func TestNoStepExec(t *testing.T) { if err != nil { t.Fatal(err) } - env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(100)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer}) + env := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1), Time: big.NewInt(1)}, vm.TxContext{GasPrice: big.NewInt(100)}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer}) tracer.CaptureStart(env, common.Address{}, common.Address{}, false, []byte{}, 1000, big.NewInt(0)) tracer.CaptureEnd(nil, 0, 1, nil) ret, err := tracer.GetResult() @@ -239,7 +239,7 @@ func TestIsPrecompile(t *testing.T) { t.Fatal(err) } - blockCtx := vm.BlockContext{BlockNumber: big.NewInt(150)} + blockCtx := vm.BlockContext{BlockNumber: big.NewInt(150), Time: big.NewInt(150)} res, err := runTrace(tracer, &vmContext{blockCtx, txCtx}, chaincfg, nil) if err != nil { t.Error(err) @@ -249,7 +249,7 @@ func TestIsPrecompile(t *testing.T) { } tracer, _ = newJsTracer("{addr: toAddress('0000000000000000000000000000000000000009'), res: null, step: function() { this.res = isPrecompiled(this.addr); }, fault: function() {}, result: function() { return this.res; }}", nil, nil) - blockCtx = vm.BlockContext{BlockNumber: big.NewInt(250)} + blockCtx = vm.BlockContext{BlockNumber: big.NewInt(250), Time: big.NewInt(250)} res, err = runTrace(tracer, &vmContext{blockCtx, txCtx}, chaincfg, nil) if err != nil { t.Error(err) diff --git a/eth/tracers/logger/logger_test.go b/eth/tracers/logger/logger_test.go index 1bc7456d31c6..6650f1729ca4 100644 --- a/eth/tracers/logger/logger_test.go +++ b/eth/tracers/logger/logger_test.go @@ -55,7 +55,7 @@ func (*dummyStatedb) SetState(_ common.Address, _ common.Hash, _ common.Hash) {} func TestStoreCapture(t *testing.T) { var ( logger = NewStructLogger(nil) - env = vm.NewEVM(vm.BlockContext{}, vm.TxContext{}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: logger}) + env = vm.NewEVM(vm.BlockContext{Time: big.NewInt(0)}, vm.TxContext{}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Debug: true, Tracer: logger}) contract = vm.NewContract(&dummyContractRef{}, &dummyContractRef{}, new(big.Int), 100000) ) contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x0, byte(vm.SSTORE)} diff --git a/eth/tracers/native/4byte.go b/eth/tracers/native/4byte.go index 00cd5fe77b8b..d36b7b02fa5c 100644 --- a/eth/tracers/native/4byte.go +++ b/eth/tracers/native/4byte.go @@ -81,7 +81,7 @@ func (t *fourByteTracer) store(id []byte, size int) { // CaptureStart implements the EVMLogger interface to initialize the tracing operation. func (t *fourByteTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { // Update list of precompiles based on current block - rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil) + rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Time.Uint64(), env.Context.Random != nil) t.activePrecompiles = vm.ActivePrecompiles(rules) // Save the outer calldata also diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index cd812fc552d9..cd37c4b72ab7 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1306,8 +1306,8 @@ type RPCTransaction struct { // newRPCTransaction returns a transaction that will serialize to the RPC // representation, with the given location metadata set (if available). -func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber uint64, index uint64, baseFee *big.Int, config *params.ChainConfig) *RPCTransaction { - signer := types.MakeSigner(config, new(big.Int).SetUint64(blockNumber)) +func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber uint64, blockTime uint64, index uint64, baseFee *big.Int, config *params.ChainConfig) *RPCTransaction { + signer := types.MakeSigner(config, new(big.Int).SetUint64(blockNumber), blockTime) from, _ := types.Sender(signer, tx) v, r, s := tx.RawSignatureValues() result := &RPCTransaction{ @@ -1363,11 +1363,13 @@ func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber func NewRPCPendingTransaction(tx *types.Transaction, current *types.Header, config *params.ChainConfig) *RPCTransaction { var baseFee *big.Int blockNumber := uint64(0) + var blockTime uint64 if current != nil { baseFee = misc.CalcBaseFee(config, current) blockNumber = current.Number.Uint64() + blockTime = current.Time } - return newRPCTransaction(tx, common.Hash{}, blockNumber, 0, baseFee, config) + return newRPCTransaction(tx, common.Hash{}, blockNumber, blockTime, 0, baseFee, config) } // newRPCTransactionFromBlockIndex returns a transaction that will serialize to the RPC representation. @@ -1376,7 +1378,7 @@ func newRPCTransactionFromBlockIndex(b *types.Block, index uint64, config *param if index >= uint64(len(txs)) { return nil } - return newRPCTransaction(txs[index], b.Hash(), b.NumberU64(), index, b.BaseFee(), config) + return newRPCTransaction(txs[index], b.Hash(), b.NumberU64(), b.Time(), index, b.BaseFee(), config) } // newRPCRawTransactionFromBlockIndex returns the bytes of a transaction given a block and a transaction index. @@ -1453,7 +1455,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH } isPostMerge := header.Difficulty.Cmp(common.Big0) == 0 // Retrieve the precompiles since they don't need to be added to the access list - precompiles := vm.ActivePrecompiles(b.ChainConfig().Rules(header.Number, isPostMerge)) + precompiles := vm.ActivePrecompiles(b.ChainConfig().Rules(header.Number, header.Time, isPostMerge)) // Create an initial tracer prevTracer := logger.NewAccessListTracer(nil, args.from(), to, precompiles) @@ -1588,7 +1590,7 @@ func (s *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common.H if err != nil { return nil, err } - return newRPCTransaction(tx, blockHash, blockNumber, index, header.BaseFee, s.b.ChainConfig()), nil + return newRPCTransaction(tx, blockHash, blockNumber, header.Time, index, header.BaseFee, s.b.ChainConfig()), nil } // No finalized transaction, try to retrieve it from the pool if tx := s.b.GetPoolTransaction(hash); tx != nil { @@ -1632,10 +1634,13 @@ func (s *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common. return nil, nil } receipt := receipts[index] - + header, err := s.b.HeaderByHash(ctx, blockHash) + if err != nil { + return nil, err + } // Derive the sender. bigblock := new(big.Int).SetUint64(blockNumber) - signer := types.MakeSigner(s.b.ChainConfig(), bigblock) + signer := types.MakeSigner(s.b.ChainConfig(), bigblock, header.Time) from, _ := types.Sender(signer, tx) fields := map[string]interface{}{ @@ -1656,10 +1661,6 @@ func (s *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common. if !s.b.ChainConfig().IsLondon(bigblock) { fields["effectiveGasPrice"] = hexutil.Uint64(tx.GasPrice().Uint64()) } else { - header, err := s.b.HeaderByHash(ctx, blockHash) - if err != nil { - return nil, err - } gasPrice := new(big.Int).Add(header.BaseFee, tx.EffectiveGasTipValue(header.BaseFee)) fields["effectiveGasPrice"] = hexutil.Uint64(gasPrice.Uint64()) } @@ -1707,7 +1708,7 @@ func SubmitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (c return common.Hash{}, err } // Print a log with full tx details for manual investigations and interventions - signer := types.MakeSigner(b.ChainConfig(), b.CurrentBlock().Number()) + signer := types.MakeSigner(b.ChainConfig(), b.CurrentBlock().Number(), b.CurrentBlock().Time()) from, err := types.Sender(signer, tx) if err != nil { return common.Hash{}, err diff --git a/les/downloader/queue_test.go b/les/downloader/queue_test.go index 44b2208595ff..d41dd14c3723 100644 --- a/les/downloader/queue_test.go +++ b/les/downloader/queue_test.go @@ -41,7 +41,7 @@ func makeChain(n int, seed byte, parent *types.Block, empty bool) ([]*types.Bloc block.SetCoinbase(common.Address{seed}) // Add one tx to every secondblock if !empty && i%2 == 0 { - signer := types.MakeSigner(params.TestChainConfig, block.Number()) + signer := types.MakeSigner(params.TestChainConfig, block.Number(), block.Time()) tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, block.BaseFee(), nil), signer, testKey) if err != nil { panic(err) diff --git a/les/downloader/testchain_test.go b/les/downloader/testchain_test.go index 400eec94e7c4..c9089dda2771 100644 --- a/les/downloader/testchain_test.go +++ b/les/downloader/testchain_test.go @@ -131,7 +131,7 @@ func (tc *testChain) generate(n int, seed byte, parent *types.Block, heavy bool) } // Include transactions to the miner to make blocks more interesting. if parent == tc.genesis && i%22 == 0 { - signer := types.MakeSigner(params.TestChainConfig, block.Number()) + signer := types.MakeSigner(params.TestChainConfig, block.Number(), block.Time()) tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, block.BaseFee(), nil), signer, testKey) if err != nil { panic(err) diff --git a/les/fetcher/block_fetcher_test.go b/les/fetcher/block_fetcher_test.go index caff7a3b3559..47466299e8c6 100644 --- a/les/fetcher/block_fetcher_test.go +++ b/les/fetcher/block_fetcher_test.go @@ -57,7 +57,7 @@ func makeChain(n int, seed byte, parent *types.Block) ([]common.Hash, map[common // If the block number is multiple of 3, send a bonus transaction to the miner if parent == genesis && i%3 == 0 { - signer := types.MakeSigner(params.TestChainConfig, block.Number()) + signer := types.MakeSigner(params.TestChainConfig, block.Number(), block.Time()) tx, err := types.SignTx(types.NewTransaction(block.TxNonce(testAddress), common.Address{seed}, big.NewInt(1000), params.TxGas, block.BaseFee(), nil), signer, testKey) if err != nil { panic(err) diff --git a/les/state_accessor.go b/les/state_accessor.go index 544d794abf47..527d7f26aeec 100644 --- a/les/state_accessor.go +++ b/les/state_accessor.go @@ -57,7 +57,7 @@ func (leth *LightEthereum) stateAtTransaction(ctx context.Context, block *types. return nil, vm.BlockContext{}, statedb, release, nil } // Recompute transactions up to the target index. - signer := types.MakeSigner(leth.blockchain.Config(), block.Number()) + signer := types.MakeSigner(leth.blockchain.Config(), block.Number(), block.Time()) for idx, tx := range block.Transactions() { // Assemble the transaction call message and return if the requested offset msg, _ := tx.AsMessage(signer, block.BaseFee()) diff --git a/light/odr_util.go b/light/odr_util.go index ea941ec32133..66259a6400bd 100644 --- a/light/odr_util.go +++ b/light/odr_util.go @@ -175,7 +175,7 @@ func GetBlockReceipts(ctx context.Context, odr OdrBackend, hash common.Hash, num genesis := rawdb.ReadCanonicalHash(odr.Database(), 0) config := rawdb.ReadChainConfig(odr.Database(), genesis) - if err := receipts.DeriveFields(config, block.Hash(), block.NumberU64(), block.Transactions()); err != nil { + if err := receipts.DeriveFields(config, block.Hash(), block.NumberU64(), block.Time(), block.Transactions()); err != nil { return nil, err } rawdb.WriteReceipts(odr.Database(), hash, number, receipts) diff --git a/miner/worker.go b/miner/worker.go index 0cfd62a7ed03..fcef6d732c71 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -794,7 +794,7 @@ func (w *worker) makeEnv(parent *types.Block, header *types.Header, coinbase com // Note the passed coinbase may be different with header.Coinbase. env := &environment{ - signer: types.MakeSigner(w.chainConfig, header.Number), + signer: types.MakeSigner(w.chainConfig, header.Number, header.Time), state: state, coinbase: coinbase, ancestors: mapset.NewSet[common.Hash](), @@ -814,7 +814,7 @@ func (w *worker) makeEnv(parent *types.Block, header *types.Header, coinbase com env.tcount = 0 // Initialize the prestate excess_data_gas field used during state transition - if w.chainConfig.IsSharding(header.Number) { + if w.chainConfig.IsSharding(header.Time) { // TODO(EIP-4844): Unit test this env.excessDataGas = new(big.Int) if parentExcessDataGas := parent.Header().ExcessDataGas; parentExcessDataGas != nil { diff --git a/miner/worker_test.go b/miner/worker_test.go index b66dff4590fc..0730fc60ed5e 100644 --- a/miner/worker_test.go +++ b/miner/worker_test.go @@ -724,7 +724,7 @@ func testGenerateBlockWithBlobsAndImport(t *testing.T, isClique bool) { } chainConfig.LondonBlock = big.NewInt(0) - chainConfig.ShardingForkBlock = big.NewInt(0) + chainConfig.ShardingForkTime = new(uint64) w, b := newTestWorker(t, chainConfig, engine, db, 0) defer w.close() diff --git a/params/config.go b/params/config.go index e511109525b9..4334f1c60a30 100644 --- a/params/config.go +++ b/params/config.go @@ -282,7 +282,7 @@ var ( TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, nil, nil, false, new(EthashConfig), nil} NonActivatedConfig = &ChainConfig{big.NewInt(1), nil, nil, false, nil, common.Hash{}, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, false, new(EthashConfig), nil} - TestRules = TestChainConfig.Rules(new(big.Int), false) + TestRules = TestChainConfig.Rules(new(big.Int), 0, false) ) // NetworkNames are user friendly names to use in the chain spec banner. @@ -372,10 +372,10 @@ type ChainConfig struct { ArrowGlacierBlock *big.Int `json:"arrowGlacierBlock,omitempty"` // Eip-4345 (bomb delay) switch block (nil = no fork, 0 = already activated) GrayGlacierBlock *big.Int `json:"grayGlacierBlock,omitempty"` // Eip-5133 (bomb delay) switch block (nil = no fork, 0 = already activated) MergeNetsplitBlock *big.Int `json:"mergeNetsplitBlock,omitempty"` // Virtual fork after The Merge to use as a network splitter - ShanghaiBlock *big.Int `json:"shanghaiBlock,omitempty"` // Shanghai switch block (nil = no fork, 0 = already on shanghai) + ShanghaiTime *uint64 `json:"shanghaiTime,omitempty"` // Shanghai switch time (nil = no fork, 0 = already on shanghai) CancunBlock *big.Int `json:"cancunBlock,omitempty"` // Cancun switch block (nil = no fork, 0 = already on cancun) MergeForkBlock *big.Int `json:"mergeForkBlock,omitempty"` // EIP-3675 (TheMerge) switch block (nil = no fork, 0 = already in merge proceedings) - ShardingForkBlock *big.Int `json:"shardingForkBlock,omitempty"` // Mini-Danksharding switch block (nil = no fork, 0 = already activated) + ShardingForkTime *uint64 `json:"shardingForkTime,omitempty"` // Mini-Danksharding switch block (nil = no fork, 0 = already activated) // TerminalTotalDifficulty is the amount of total difficulty reached by // the network that triggers the consensus upgrade. @@ -468,14 +468,14 @@ func (c *ChainConfig) Description() string { if c.GrayGlacierBlock != nil { banner += fmt.Sprintf(" - Gray Glacier: %-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/gray-glacier.md)\n", c.GrayGlacierBlock) } - if c.ShanghaiBlock != nil { - banner += fmt.Sprintf(" - Shanghai: %-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/shanghai.md)\n", c.ShanghaiBlock) + if c.ShanghaiTime != nil { + banner += fmt.Sprintf(" - Shanghai: %-8v (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/shanghai.md)\n", c.ShanghaiTime) } if c.CancunBlock != nil { banner += fmt.Sprintf(" - Cancun: %-8v\n", c.CancunBlock) } - if c.ShardingForkBlock != nil { - banner += fmt.Sprintf(" - ShardingFork: %-8v\n", c.ShardingForkBlock) + if c.ShardingForkTime != nil { + banner += fmt.Sprintf(" - ShardingFork: %-8v\n", c.ShardingForkTime) } banner += "\n" @@ -565,9 +565,12 @@ func (c *ChainConfig) IsGrayGlacier(num *big.Int) bool { return isForked(c.GrayGlacierBlock, num) } -// IsSharding returns whether num is either equal to the Mini-Danksharding fork block or greater. -func (c *ChainConfig) IsSharding(num *big.Int) bool { - return isForked(c.ShardingForkBlock, num) +// IsSharding returns whether time is either equal to the Mini-Danksharding fork time or greater. +func (c *ChainConfig) IsSharding(time uint64) bool { + if c.ShardingForkTime == nil { + return false + } + return *c.ShardingForkTime <= time } // IsTerminalPoWBlock returns whether the given block is the last block of PoW stage. @@ -578,9 +581,12 @@ func (c *ChainConfig) IsTerminalPoWBlock(parentTotalDiff *big.Int, totalDiff *bi return parentTotalDiff.Cmp(c.TerminalTotalDifficulty) < 0 && totalDiff.Cmp(c.TerminalTotalDifficulty) >= 0 } -// IsShanghai returns whether num is either equal to the Shanghai fork block or greater. -func (c *ChainConfig) IsShanghai(num *big.Int) bool { - return isForked(c.ShanghaiBlock, num) +// IsShanghai returns whether time is either equal to the Shanghai fork time or greater. +func (c *ChainConfig) IsShanghai(time uint64) bool { + if c.ShanghaiTime == nil { + return false + } + return *c.ShanghaiTime <= time } // IsCancun returns whether num is either equal to the Cancun fork block or greater. @@ -631,10 +637,10 @@ func (c *ChainConfig) CheckConfigForkOrder() error { {name: "arrowGlacierBlock", block: c.ArrowGlacierBlock, optional: true}, {name: "grayGlacierBlock", block: c.GrayGlacierBlock, optional: true}, {name: "mergeNetsplitBlock", block: c.MergeNetsplitBlock, optional: true}, - {name: "shanghaiBlock", block: c.ShanghaiBlock, optional: true}, + //{name: "shanghaiBlock", block: c.ShanghaiBlock, optional: true}, {name: "cancunBlock", block: c.CancunBlock, optional: true}, {name: "mergeStartBlock", block: c.MergeForkBlock, optional: true}, - {name: "shardingForkBlock", block: c.ShardingForkBlock, optional: true}, + //{name: "shardingForkBlock", block: c.ShardingForkBlock, optional: true}, } { if lastFork.name != "" { // Next one must be higher number @@ -713,15 +719,19 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int) *Confi if isForkIncompatible(c.MergeNetsplitBlock, newcfg.MergeNetsplitBlock, head) { return newCompatError("Merge netsplit fork block", c.MergeNetsplitBlock, newcfg.MergeNetsplitBlock) } - if isForkIncompatible(c.ShanghaiBlock, newcfg.ShanghaiBlock, head) { - return newCompatError("Shanghai fork block", c.ShanghaiBlock, newcfg.ShanghaiBlock) - } + /* + if isForkIncompatible(c.ShanghaiBlock, newcfg.ShanghaiBlock, head) { + return newCompatError("Shanghai fork block", c.ShanghaiBlock, newcfg.ShanghaiBlock) + } + */ if isForkIncompatible(c.CancunBlock, newcfg.CancunBlock, head) { return newCompatError("Cancun fork block", c.CancunBlock, newcfg.CancunBlock) } - if isForkIncompatible(c.ShardingForkBlock, newcfg.ShardingForkBlock, head) { - return newCompatError("Mini-Danksharding fork block", c.ShardingForkBlock, newcfg.ShardingForkBlock) - } + /* + if isForkIncompatible(c.ShardingForkBlock, newcfg.ShardingForkBlock, head) { + return newCompatError("Mini-Danksharding fork block", c.ShardingForkBlock, newcfg.ShardingForkBlock) + } + */ return nil } @@ -804,7 +814,7 @@ type Rules struct { } // Rules ensures c's ChainID is not nil. -func (c *ChainConfig) Rules(num *big.Int, isMerge bool) Rules { +func (c *ChainConfig) Rules(num *big.Int, timestamp uint64, isMerge bool) Rules { chainID := c.ChainID if chainID == nil { chainID = new(big.Int) @@ -822,8 +832,8 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool) Rules { IsBerlin: c.IsBerlin(num), IsLondon: c.IsLondon(num), IsMerge: isMerge, - IsShanghai: c.IsShanghai(num), + IsShanghai: c.IsShanghai(timestamp), isCancun: c.IsCancun(num), - IsSharding: c.IsSharding(num), + IsSharding: c.IsSharding(timestamp), } } diff --git a/tests/fuzzers/les/les-fuzzer.go b/tests/fuzzers/les/les-fuzzer.go index 643ccadd7d26..ae5e8d1b59ed 100644 --- a/tests/fuzzers/les/les-fuzzer.go +++ b/tests/fuzzers/les/les-fuzzer.go @@ -390,8 +390,8 @@ func Fuzz(input []byte) int { nonce = f.nonce f.nonce += 1 } - tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(10000), params.TxGas, big.NewInt(1000000000*int64(f.randomByte())), nil), signer, bankKey) - req.Txs[i] = types.NewNetworkTransaction(tx) + tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(10000), params.TxGas, big.NewInt(1000000000*int64(f.randomByte())), nil), signer, bankKey) + req.Txs[i] = types.NewNetworkTransaction(tx) } f.doFuzz(l.SendTxV2Msg, req) diff --git a/tests/init.go b/tests/init.go index 5f8196512bc4..2f5a430c6cb6 100644 --- a/tests/init.go +++ b/tests/init.go @@ -246,7 +246,7 @@ var Forks = map[string]*params.ChainConfig{ ArrowGlacierBlock: big.NewInt(0), MergeNetsplitBlock: big.NewInt(0), TerminalTotalDifficulty: big.NewInt(0), - ShanghaiBlock: big.NewInt(0), + ShanghaiTime: new(uint64), }, } diff --git a/tests/state_test.go b/tests/state_test.go index c623b1c2d425..a8b0abc3465a 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -185,7 +185,7 @@ func runBenchmark(b *testing.B, t *StateTest) { b.Error(err) return } - var rules = config.Rules(new(big.Int), false) + var rules = config.Rules(new(big.Int), 0, false) vmconfig.ExtraEips = eips block := t.genesis(config).ToBlock()