This commit is contained in:
Cedrick AH 2025-05-05 15:31:31 +02:00 committed by GitHub
commit c14eeec71b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 235 additions and 144 deletions

View file

@ -213,7 +213,8 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
if beaconRoot := pre.Env.ParentBeaconBlockRoot; beaconRoot != nil { if beaconRoot := pre.Env.ParentBeaconBlockRoot; beaconRoot != nil {
core.ProcessBeaconBlockRoot(*beaconRoot, evm) core.ProcessBeaconBlockRoot(*beaconRoot, evm)
} }
if pre.Env.BlockHashes != nil && chainConfig.IsPrague(new(big.Int).SetUint64(pre.Env.Number), pre.Env.Timestamp) { rules := evm.Rules()
if pre.Env.BlockHashes != nil && rules.IsPrague {
var ( var (
prevNumber = pre.Env.Number - 1 prevNumber = pre.Env.Number - 1
prevHash = pre.Env.BlockHashes[math.HexOrDecimal64(prevNumber)] prevHash = pre.Env.BlockHashes[math.HexOrDecimal64(prevNumber)]
@ -233,7 +234,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
rejectedTxs = append(rejectedTxs, &rejectedTx{i, errMsg}) rejectedTxs = append(rejectedTxs, &rejectedTx{i, errMsg})
continue continue
} }
msg, err := core.TransactionToMessage(tx, signer, pre.Env.BaseFee) msg, err := core.TransactionToMessage(tx, signer, pre.Env.BaseFee, rules)
if err != nil { if err != nil {
log.Warn("rejected tx", "index", i, "hash", tx.Hash(), "error", err) log.Warn("rejected tx", "index", i, "hash", tx.Hash(), "error", err)
rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()}) rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()})

View file

@ -132,9 +132,9 @@ func Transaction(ctx *cli.Context) error {
} else { } else {
r.Address = sender r.Address = sender
} }
// Check intrinsic gas
rules := chainConfig.Rules(common.Big0, true, 0) rules := chainConfig.Rules(common.Big0, true, 0)
gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations(), tx.To() == nil, rules.IsHomestead, rules.IsIstanbul, rules.IsShanghai) // Check intrinsic gas
gas, err := tx.IntrinsicGas(&rules)
if err != nil { if err != nil {
r.Error = err r.Error = err
results = append(results, r) results = append(results, r)

View file

@ -245,7 +245,7 @@ func applyMergeChecks(env *stEnv, chainConfig *params.ChainConfig) error {
switch { switch {
case env.Random == nil: case env.Random == nil:
return NewError(ErrorConfig, errors.New("post-merge requires currentRandom to be defined in env")) return NewError(ErrorConfig, errors.New("post-merge requires currentRandom to be defined in env"))
case env.Difficulty != nil && env.Difficulty.BitLen() != 0: case env.Difficulty != nil && env.Difficulty.Sign() != 0:
return NewError(ErrorConfig, errors.New("post-merge difficulty must be zero (or omitted) in env")) return NewError(ErrorConfig, errors.New("post-merge difficulty must be zero (or omitted) in env"))
} }
env.Difficulty = nil env.Difficulty = nil

View file

@ -90,20 +90,21 @@ func genValueTx(nbytes int) func(int, *BlockGen) {
data := make([]byte, nbytes) data := make([]byte, nbytes)
return func(i int, gen *BlockGen) { return func(i int, gen *BlockGen) {
toaddr := common.Address{} toaddr := common.Address{}
gas, _ := IntrinsicGas(data, nil, nil, false, false, false, false)
signer := gen.Signer() signer := gen.Signer()
gasPrice := big.NewInt(0) gasPrice := big.NewInt(0)
if gen.header.BaseFee != nil { if gen.header.BaseFee != nil {
gasPrice = gen.header.BaseFee gasPrice = gen.header.BaseFee
} }
tx, _ := types.SignNewTx(benchRootKey, signer, &types.LegacyTx{ rules := params.TestChainConfig.Rules(common.Big0, true, 0)
txdata := &types.LegacyTx{
Nonce: gen.TxNonce(benchRootAddr), Nonce: gen.TxNonce(benchRootAddr),
To: &toaddr, To: &toaddr,
Value: big.NewInt(1), Value: big.NewInt(1),
Gas: gas,
Data: data, Data: data,
GasPrice: gasPrice, GasPrice: gasPrice,
}) }
txdata.Gas = types.IntrinsicGas(txdata, &rules)
tx, _ := types.SignNewTx(benchRootKey, signer, txdata)
gen.AddTx(tx) gen.AddTx(tx)
} }
} }

View file

@ -51,6 +51,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c
blockContext = NewEVMBlockContext(header, p.chain, nil) blockContext = NewEVMBlockContext(header, p.chain, nil)
evm = vm.NewEVM(blockContext, statedb, p.config, cfg) evm = vm.NewEVM(blockContext, statedb, p.config, cfg)
signer = types.MakeSigner(p.config, header.Number, header.Time) signer = types.MakeSigner(p.config, header.Number, header.Time)
rules = evm.Rules()
) )
// Iterate over and process the individual transactions // Iterate over and process the individual transactions
byzantium := p.config.IsByzantium(block.Number()) byzantium := p.config.IsByzantium(block.Number())
@ -60,7 +61,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c
return return
} }
// Convert the transaction into an executable message and pre-cache its sender // Convert the transaction into an executable message and pre-cache its sender
msg, err := TransactionToMessage(tx, signer, header.BaseFee) msg, err := TransactionToMessage(tx, signer, header.BaseFee, rules)
if err != nil { if err != nil {
return // Also invalid block, bail out return // Also invalid block, bail out
} }

View file

@ -69,29 +69,29 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 { if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
misc.ApplyDAOHardFork(statedb) misc.ApplyDAOHardFork(statedb)
} }
var (
context vm.BlockContext
signer = types.MakeSigner(p.config, header.Number, header.Time)
)
// Apply pre-execution system calls. // Apply pre-execution system calls.
var tracingStateDB = vm.StateDB(statedb) var tracingStateDB = vm.StateDB(statedb)
if hooks := cfg.Tracer; hooks != nil { if hooks := cfg.Tracer; hooks != nil {
tracingStateDB = state.NewHookedState(statedb, hooks) tracingStateDB = state.NewHookedState(statedb, hooks)
} }
context = NewEVMBlockContext(header, p.chain, nil)
evm := vm.NewEVM(context, tracingStateDB, p.config, cfg)
var (
context = NewEVMBlockContext(header, p.chain, nil)
evm = vm.NewEVM(context, tracingStateDB, p.config, cfg)
rules = evm.Rules()
signer = types.MakeSigner(p.config, header.Number, header.Time)
)
if beaconRoot := block.BeaconRoot(); beaconRoot != nil { if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
ProcessBeaconBlockRoot(*beaconRoot, evm) ProcessBeaconBlockRoot(*beaconRoot, evm)
} }
if p.config.IsPrague(block.Number(), block.Time()) || p.config.IsVerkle(block.Number(), block.Time()) { if rules.IsPrague || rules.IsVerkle {
ProcessParentBlockHash(block.ParentHash(), evm) ProcessParentBlockHash(block.ParentHash(), evm)
} }
// Iterate over and process the individual transactions // Iterate over and process the individual transactions
for i, tx := range block.Transactions() { for i, tx := range block.Transactions() {
msg, err := TransactionToMessage(tx, signer, header.BaseFee) msg, err := TransactionToMessage(tx, signer, header.BaseFee, rules)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) return nil, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
} }
@ -205,7 +205,7 @@ func MakeReceipt(evm *vm.EVM, result *ExecutionResult, statedb *state.StateDB, b
// for the transaction, gas used and an error if the transaction failed, // for the transaction, gas used and an error if the transaction failed,
// indicating the block was invalid. // indicating the block was invalid.
func ApplyTransaction(evm *vm.EVM, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64) (*types.Receipt, error) { func ApplyTransaction(evm *vm.EVM, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64) (*types.Receipt, error) {
msg, err := TransactionToMessage(tx, types.MakeSigner(evm.ChainConfig(), header.Number, header.Time), header.BaseFee) msg, err := TransactionToMessage(tx, types.MakeSigner(evm.ChainConfig(), header.Number, header.Time), header.BaseFee, evm.Rules())
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -67,55 +67,6 @@ func (result *ExecutionResult) Revert() []byte {
return common.CopyBytes(result.ReturnData) return common.CopyBytes(result.ReturnData)
} }
// IntrinsicGas computes the 'intrinsic gas' for a message with the given data.
func IntrinsicGas(data []byte, accessList types.AccessList, authList []types.SetCodeAuthorization, isContractCreation, isHomestead, isEIP2028, isEIP3860 bool) (uint64, error) {
// Set the starting gas for the raw transaction
var gas uint64
if isContractCreation && isHomestead {
gas = params.TxGasContractCreation
} else {
gas = params.TxGas
}
dataLen := uint64(len(data))
// Bump the required gas by the amount of transactional data
if dataLen > 0 {
// Zero and non-zero bytes are priced differently
z := uint64(bytes.Count(data, []byte{0}))
nz := dataLen - z
// Make sure we don't exceed uint64 for all data combinations
nonZeroGas := params.TxDataNonZeroGasFrontier
if isEIP2028 {
nonZeroGas = params.TxDataNonZeroGasEIP2028
}
if (math.MaxUint64-gas)/nonZeroGas < nz {
return 0, ErrGasUintOverflow
}
gas += nz * nonZeroGas
if (math.MaxUint64-gas)/params.TxDataZeroGas < z {
return 0, ErrGasUintOverflow
}
gas += z * params.TxDataZeroGas
if isContractCreation && isEIP3860 {
lenWords := toWordSize(dataLen)
if (math.MaxUint64-gas)/params.InitCodeWordGas < lenWords {
return 0, ErrGasUintOverflow
}
gas += lenWords * params.InitCodeWordGas
}
}
if accessList != nil {
gas += uint64(len(accessList)) * params.TxAccessListAddressGas
gas += uint64(accessList.StorageKeys()) * params.TxAccessListStorageKeyGas
}
if authList != nil {
gas += uint64(len(authList)) * params.CallNewAccountGas
}
return gas, nil
}
// FloorDataGas computes the minimum gas required for a transaction based on its data tokens (EIP-7623). // FloorDataGas computes the minimum gas required for a transaction based on its data tokens (EIP-7623).
func FloorDataGas(data []byte) (uint64, error) { func FloorDataGas(data []byte) (uint64, error) {
var ( var (
@ -131,15 +82,6 @@ func FloorDataGas(data []byte) (uint64, error) {
return params.TxGas + tokens*params.TxCostFloorPerToken, nil return params.TxGas + tokens*params.TxCostFloorPerToken, nil
} }
// toWordSize returns the ceiled word size required for init code payment calculation.
func toWordSize(size uint64) uint64 {
if size > math.MaxUint64-31 {
return math.MaxUint64/32 + 1
}
return (size + 31) / 32
}
// A Message contains the data derived from a single transaction that is relevant to state // A Message contains the data derived from a single transaction that is relevant to state
// processing. // processing.
type Message struct { type Message struct {
@ -151,6 +93,7 @@ type Message struct {
GasPrice *big.Int GasPrice *big.Int
GasFeeCap *big.Int GasFeeCap *big.Int
GasTipCap *big.Int GasTipCap *big.Int
IntrinsicGas uint64
Data []byte Data []byte
AccessList types.AccessList AccessList types.AccessList
BlobGasFeeCap *big.Int BlobGasFeeCap *big.Int
@ -167,7 +110,7 @@ type Message struct {
} }
// TransactionToMessage converts a transaction into a Message. // TransactionToMessage converts a transaction into a Message.
func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.Int) (*Message, error) { func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.Int, rules *params.Rules) (*Message, error) {
msg := &Message{ msg := &Message{
Nonce: tx.Nonce(), Nonce: tx.Nonce(),
GasLimit: tx.Gas(), GasLimit: tx.Gas(),
@ -191,7 +134,14 @@ func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.In
msg.GasPrice = msg.GasFeeCap msg.GasPrice = msg.GasFeeCap
} }
} }
var err error // Fill in intrinsic gas.
intrinsicGas, err := tx.IntrinsicGas(rules)
if err != nil {
return nil, err
}
msg.IntrinsicGas = intrinsicGas
// Recover sender.
msg.From, err = types.Sender(s, tx) msg.From, err = types.Sender(s, tx)
return msg, err return msg, err
} }
@ -426,15 +376,12 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
rules = st.evm.ChainConfig().Rules(st.evm.Context.BlockNumber, st.evm.Context.Random != nil, st.evm.Context.Time) rules = st.evm.ChainConfig().Rules(st.evm.Context.BlockNumber, st.evm.Context.Random != nil, st.evm.Context.Time)
contractCreation = msg.To == nil contractCreation = msg.To == nil
floorDataGas uint64 floorDataGas uint64
err error
) )
// Check clauses 4-5, subtract intrinsic gas if everything is correct // Check clauses 4-5, subtract intrinsic gas if everything is correct
gas, err := IntrinsicGas(msg.Data, msg.AccessList, msg.SetCodeAuthorizations, contractCreation, rules.IsHomestead, rules.IsIstanbul, rules.IsShanghai) if st.gasRemaining < msg.IntrinsicGas {
if err != nil { return nil, fmt.Errorf("%w: have %d, want %d", ErrIntrinsicGas, st.gasRemaining, msg.IntrinsicGas)
return nil, err
}
if st.gasRemaining < gas {
return nil, fmt.Errorf("%w: have %d, want %d", ErrIntrinsicGas, st.gasRemaining, gas)
} }
// Gas limit suffices for the floor data cost (EIP-7623) // Gas limit suffices for the floor data cost (EIP-7623)
if rules.IsPrague { if rules.IsPrague {
@ -447,9 +394,9 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
} }
} }
if t := st.evm.Config.Tracer; t != nil && t.OnGasChange != nil { if t := st.evm.Config.Tracer; t != nil && t.OnGasChange != nil {
t.OnGasChange(st.gasRemaining, st.gasRemaining-gas, tracing.GasChangeTxIntrinsicGas) t.OnGasChange(st.gasRemaining, st.gasRemaining-msg.IntrinsicGas, tracing.GasChangeTxIntrinsicGas)
} }
st.gasRemaining -= gas st.gasRemaining -= msg.IntrinsicGas
if rules.IsEIP4762 { if rules.IsEIP4762 {
st.evm.AccessEvents.AddTxOrigin(msg.From) st.evm.AccessEvents.AddTxOrigin(msg.From)

View file

@ -112,7 +112,7 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types
} }
// Ensure the transaction has more gas than the bare minimum needed to cover // Ensure the transaction has more gas than the bare minimum needed to cover
// the transaction metadata // the transaction metadata
intrGas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations(), tx.To() == nil, true, rules.IsIstanbul, rules.IsShanghai) intrGas, err := tx.IntrinsicGas(&rules)
if err != nil { if err != nil {
return err return err
} }

View file

@ -21,12 +21,14 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"math"
"math/big" "math/big"
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
) )
@ -40,6 +42,7 @@ var (
errInvalidYParity = errors.New("'yParity' field must be 0 or 1") errInvalidYParity = errors.New("'yParity' field must be 0 or 1")
errVYParityMismatch = errors.New("'v' and 'yParity' fields do not match") errVYParityMismatch = errors.New("'v' and 'yParity' fields do not match")
errVYParityMissing = errors.New("missing 'yParity' or 'v' field in transaction") errVYParityMissing = errors.New("missing 'yParity' or 'v' field in transaction")
ErrGasUintOverflow = errors.New("gas uint64 overflow")
) )
// Transaction types. // Transaction types.
@ -86,6 +89,7 @@ type TxData interface {
value() *big.Int value() *big.Int
nonce() uint64 nonce() uint64
to() *common.Address to() *common.Address
setCodeAuthorizations() []SetCodeAuthorization
rawSignatureValues() (v, r, s *big.Int) rawSignatureValues() (v, r, s *big.Int)
setSignatureValues(chainID, v, r, s *big.Int) setSignatureValues(chainID, v, r, s *big.Int)
@ -479,11 +483,7 @@ func (tx *Transaction) WithBlobTxSidecar(sideCar *BlobTxSidecar) *Transaction {
// SetCodeAuthorizations returns the authorizations list of the transaction. // SetCodeAuthorizations returns the authorizations list of the transaction.
func (tx *Transaction) SetCodeAuthorizations() []SetCodeAuthorization { func (tx *Transaction) SetCodeAuthorizations() []SetCodeAuthorization {
setcodetx, ok := tx.inner.(*SetCodeTx) return tx.inner.setCodeAuthorizations()
if !ok {
return nil
}
return setcodetx.AuthList
} }
// SetCodeAuthorities returns a list of unique authorities from the // SetCodeAuthorities returns a list of unique authorities from the
@ -581,6 +581,78 @@ func (tx *Transaction) WithSignature(signer Signer, sig []byte) (*Transaction, e
return &Transaction{inner: cpy, time: tx.time}, nil return &Transaction{inner: cpy, time: tx.time}, nil
} }
// IntrinsicGas returns the calculated intrinsic gas for the given transaction.
func (tx *Transaction) IntrinsicGas(rules *params.Rules) (uint64, error) {
return calcIntrinsicGas(tx.inner, rules)
}
// IntrinsicGas returns the calculated intrinsic gas for the given transaction.
func IntrinsicGas(txdata TxData, rules *params.Rules) uint64 {
gas, err := calcIntrinsicGas(txdata, rules)
if err != nil {
panic(err)
}
return gas
}
// calcIntrinsicGas is an internal function that drives exported versions of the function.
func calcIntrinsicGas(txdata TxData, rules *params.Rules) (uint64, error) {
// Set the starting gas for the raw transaction
var gas uint64
if txdata.to() == nil && rules.IsHomestead {
gas = params.TxGasContractCreation
} else {
gas = params.TxGas
}
dataLen := uint64(len(txdata.data()))
// Bump the required gas by the amount of transactional data
if dataLen > 0 {
// Zero and non-zero bytes are priced differently
z := uint64(bytes.Count(txdata.data(), []byte{0}))
nz := dataLen - z
// Make sure we don't exceed uint64 for all data combinations
nonZeroGas := params.TxDataNonZeroGasFrontier
if rules.IsIstanbul {
nonZeroGas = params.TxDataNonZeroGasEIP2028
}
if (math.MaxUint64-gas)/nonZeroGas < nz {
return 0, ErrGasUintOverflow
}
gas += nz * nonZeroGas
if (math.MaxUint64-gas)/params.TxDataZeroGas < z {
return 0, ErrGasUintOverflow
}
gas += z * params.TxDataZeroGas
if txdata.to() == nil && rules.IsShanghai {
lenWords := toWordSize(dataLen)
if (math.MaxUint64-gas)/params.InitCodeWordGas < lenWords {
return 0, ErrGasUintOverflow
}
gas += lenWords * params.InitCodeWordGas
}
}
if txdata.accessList() != nil {
gas += uint64(len(txdata.accessList())) * params.TxAccessListAddressGas
gas += uint64(txdata.accessList().StorageKeys()) * params.TxAccessListStorageKeyGas
}
if txdata.setCodeAuthorizations() != nil {
gas += uint64(len(txdata.setCodeAuthorizations())) * params.CallNewAccountGas
}
return gas, nil
}
// toWordSize returns the ceiled word size required for init code payment calculation.
func toWordSize(size uint64) uint64 {
if size > math.MaxUint64-31 {
return math.MaxUint64/32 + 1
}
return (size + 31) / 32
}
// Transactions implements DerivableList for transactions. // Transactions implements DerivableList for transactions.
type Transactions []*Transaction type Transactions []*Transaction

View file

@ -107,6 +107,9 @@ func (tx *AccessListTx) gasFeeCap() *big.Int { return tx.GasPrice }
func (tx *AccessListTx) value() *big.Int { return tx.Value } func (tx *AccessListTx) value() *big.Int { return tx.Value }
func (tx *AccessListTx) nonce() uint64 { return tx.Nonce } func (tx *AccessListTx) nonce() uint64 { return tx.Nonce }
func (tx *AccessListTx) to() *common.Address { return tx.To } func (tx *AccessListTx) to() *common.Address { return tx.To }
func (tx *AccessListTx) setCodeAuthorizations() []SetCodeAuthorization {
return nil
}
func (tx *AccessListTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int { func (tx *AccessListTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int {
return dst.Set(tx.GasPrice) return dst.Set(tx.GasPrice)

View file

@ -179,6 +179,9 @@ func (tx *BlobTx) value() *big.Int { return tx.Value.ToBig() }
func (tx *BlobTx) nonce() uint64 { return tx.Nonce } func (tx *BlobTx) nonce() uint64 { return tx.Nonce }
func (tx *BlobTx) to() *common.Address { tmp := tx.To; return &tmp } func (tx *BlobTx) to() *common.Address { tmp := tx.To; return &tmp }
func (tx *BlobTx) blobGas() uint64 { return params.BlobTxBlobGasPerBlob * uint64(len(tx.BlobHashes)) } func (tx *BlobTx) blobGas() uint64 { return params.BlobTxBlobGasPerBlob * uint64(len(tx.BlobHashes)) }
func (tx *BlobTx) setCodeAuthorizations() []SetCodeAuthorization {
return nil
}
func (tx *BlobTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int { func (tx *BlobTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int {
if baseFee == nil { if baseFee == nil {

View file

@ -96,6 +96,9 @@ func (tx *DynamicFeeTx) gasPrice() *big.Int { return tx.GasFeeCap }
func (tx *DynamicFeeTx) value() *big.Int { return tx.Value } func (tx *DynamicFeeTx) value() *big.Int { return tx.Value }
func (tx *DynamicFeeTx) nonce() uint64 { return tx.Nonce } func (tx *DynamicFeeTx) nonce() uint64 { return tx.Nonce }
func (tx *DynamicFeeTx) to() *common.Address { return tx.To } func (tx *DynamicFeeTx) to() *common.Address { return tx.To }
func (tx *DynamicFeeTx) setCodeAuthorizations() []SetCodeAuthorization {
return nil
}
func (tx *DynamicFeeTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int { func (tx *DynamicFeeTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int {
if baseFee == nil { if baseFee == nil {

View file

@ -103,6 +103,9 @@ func (tx *LegacyTx) gasFeeCap() *big.Int { return tx.GasPrice }
func (tx *LegacyTx) value() *big.Int { return tx.Value } func (tx *LegacyTx) value() *big.Int { return tx.Value }
func (tx *LegacyTx) nonce() uint64 { return tx.Nonce } func (tx *LegacyTx) nonce() uint64 { return tx.Nonce }
func (tx *LegacyTx) to() *common.Address { return tx.To } func (tx *LegacyTx) to() *common.Address { return tx.To }
func (tx *LegacyTx) setCodeAuthorizations() []SetCodeAuthorization {
return nil
}
func (tx *LegacyTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int { func (tx *LegacyTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int {
return dst.Set(tx.GasPrice) return dst.Set(tx.GasPrice)

View file

@ -193,6 +193,9 @@ func (tx *SetCodeTx) gasPrice() *big.Int { return tx.GasFeeCap.ToBig() }
func (tx *SetCodeTx) value() *big.Int { return tx.Value.ToBig() } func (tx *SetCodeTx) value() *big.Int { return tx.Value.ToBig() }
func (tx *SetCodeTx) nonce() uint64 { return tx.Nonce } func (tx *SetCodeTx) nonce() uint64 { return tx.Nonce }
func (tx *SetCodeTx) to() *common.Address { tmp := tx.To; return &tmp } func (tx *SetCodeTx) to() *common.Address { tmp := tx.To; return &tmp }
func (tx *SetCodeTx) setCodeAuthorizations() []SetCodeAuthorization {
return tx.AuthList
}
func (tx *SetCodeTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int { func (tx *SetCodeTx) effectiveGasPrice(dst *big.Int, baseFee *big.Int) *big.Int {
if baseFee == nil { if baseFee == nil {

View file

@ -92,12 +92,13 @@ var (
func TestProcessVerkle(t *testing.T) { func TestProcessVerkle(t *testing.T) {
var ( var (
code = common.FromHex(`6060604052600a8060106000396000f360606040526008565b00`) code = common.FromHex(`6060604052600a8060106000396000f360606040526008565b00`)
intrinsicContractCreationGas, _ = IntrinsicGas(code, nil, nil, true, true, true, true) rules = testVerkleChainConfig.Rules(common.Big0, true, 0)
intrinsicContractCreationGas, _ = types.NewContractCreation(0, big.NewInt(999), params.TxGas, big.NewInt(875000000), code).IntrinsicGas(&rules)
// A contract creation that calls EXTCODECOPY in the constructor. Used to ensure that the witness // A contract creation that calls EXTCODECOPY in the constructor. Used to ensure that the witness
// will not contain that copied data. // will not contain that copied data.
// Source: https://gist.github.com/gballet/a23db1e1cb4ed105616b5920feb75985 // Source: https://gist.github.com/gballet/a23db1e1cb4ed105616b5920feb75985
codeWithExtCodeCopy = common.FromHex(`0x60806040526040516100109061017b565b604051809103906000f08015801561002c573d6000803e3d6000fd5b506000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561007857600080fd5b5060008067ffffffffffffffff8111156100955761009461024a565b5b6040519080825280601f01601f1916602001820160405280156100c75781602001600182028036833780820191505090505b50905060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506020600083833c81610101906101e3565b60405161010d90610187565b61011791906101a3565b604051809103906000f080158015610133573d6000803e3d6000fd5b50600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505061029b565b60d58061046783390190565b6102068061053c83390190565b61019d816101d9565b82525050565b60006020820190506101b86000830184610194565b92915050565b6000819050602082019050919050565b600081519050919050565b6000819050919050565b60006101ee826101ce565b826101f8846101be565b905061020381610279565b925060208210156102435761023e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8360200360080261028e565b831692505b5050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600061028582516101d9565b80915050919050565b600082821b905092915050565b6101bd806102aa6000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f566852414610030575b600080fd5b61003861004e565b6040516100459190610146565b60405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166381ca91d36040518163ffffffff1660e01b815260040160206040518083038186803b1580156100b857600080fd5b505afa1580156100cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100f0919061010a565b905090565b60008151905061010481610170565b92915050565b6000602082840312156101205761011f61016b565b5b600061012e848285016100f5565b91505092915050565b61014081610161565b82525050565b600060208201905061015b6000830184610137565b92915050565b6000819050919050565b600080fd5b61017981610161565b811461018457600080fd5b5056fea2646970667358221220a6a0e11af79f176f9c421b7b12f441356b25f6489b83d38cc828a701720b41f164736f6c63430008070033608060405234801561001057600080fd5b5060b68061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063ab5ed15014602d575b600080fd5b60336047565b604051603e9190605d565b60405180910390f35b60006001905090565b6057816076565b82525050565b6000602082019050607060008301846050565b92915050565b600081905091905056fea26469706673582212203a14eb0d5cd07c277d3e24912f110ddda3e553245a99afc4eeefb2fbae5327aa64736f6c63430008070033608060405234801561001057600080fd5b5060405161020638038061020683398181016040528101906100329190610063565b60018160001c6100429190610090565b60008190555050610145565b60008151905061005d8161012e565b92915050565b60006020828403121561007957610078610129565b5b60006100878482850161004e565b91505092915050565b600061009b826100f0565b91506100a6836100f0565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156100db576100da6100fa565b5b828201905092915050565b6000819050919050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600080fd5b610137816100e6565b811461014257600080fd5b50565b60b3806101536000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806381ca91d314602d575b600080fd5b60336047565b604051603e9190605a565b60405180910390f35b60005481565b6054816073565b82525050565b6000602082019050606d6000830184604d565b92915050565b600081905091905056fea26469706673582212209bff7098a2f526de1ad499866f27d6d0d6f17b74a413036d6063ca6a0998ca4264736f6c63430008070033`) codeWithExtCodeCopy = common.FromHex(`0x60806040526040516100109061017b565b604051809103906000f08015801561002c573d6000803e3d6000fd5b506000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561007857600080fd5b5060008067ffffffffffffffff8111156100955761009461024a565b5b6040519080825280601f01601f1916602001820160405280156100c75781602001600182028036833780820191505090505b50905060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506020600083833c81610101906101e3565b60405161010d90610187565b61011791906101a3565b604051809103906000f080158015610133573d6000803e3d6000fd5b50600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505061029b565b60d58061046783390190565b6102068061053c83390190565b61019d816101d9565b82525050565b60006020820190506101b86000830184610194565b92915050565b6000819050602082019050919050565b600081519050919050565b6000819050919050565b60006101ee826101ce565b826101f8846101be565b905061020381610279565b925060208210156102435761023e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8360200360080261028e565b831692505b5050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600061028582516101d9565b80915050919050565b600082821b905092915050565b6101bd806102aa6000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f566852414610030575b600080fd5b61003861004e565b6040516100459190610146565b60405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166381ca91d36040518163ffffffff1660e01b815260040160206040518083038186803b1580156100b857600080fd5b505afa1580156100cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100f0919061010a565b905090565b60008151905061010481610170565b92915050565b6000602082840312156101205761011f61016b565b5b600061012e848285016100f5565b91505092915050565b61014081610161565b82525050565b600060208201905061015b6000830184610137565b92915050565b6000819050919050565b600080fd5b61017981610161565b811461018457600080fd5b5056fea2646970667358221220a6a0e11af79f176f9c421b7b12f441356b25f6489b83d38cc828a701720b41f164736f6c63430008070033608060405234801561001057600080fd5b5060b68061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063ab5ed15014602d575b600080fd5b60336047565b604051603e9190605d565b60405180910390f35b60006001905090565b6057816076565b82525050565b6000602082019050607060008301846050565b92915050565b600081905091905056fea26469706673582212203a14eb0d5cd07c277d3e24912f110ddda3e553245a99afc4eeefb2fbae5327aa64736f6c63430008070033608060405234801561001057600080fd5b5060405161020638038061020683398181016040528101906100329190610063565b60018160001c6100429190610090565b60008190555050610145565b60008151905061005d8161012e565b92915050565b60006020828403121561007957610078610129565b5b60006100878482850161004e565b91505092915050565b600061009b826100f0565b91506100a6836100f0565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156100db576100da6100fa565b5b828201905092915050565b6000819050919050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600080fd5b610137816100e6565b811461014257600080fd5b50565b60b3806101536000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806381ca91d314602d575b600080fd5b60336047565b604051603e9190605a565b60405180910390f35b60005481565b6054816073565b82525050565b6000602082019050606d6000830184604d565b92915050565b600081905091905056fea26469706673582212209bff7098a2f526de1ad499866f27d6d0d6f17b74a413036d6063ca6a0998ca4264736f6c63430008070033`)
intrinsicCodeWithExtCodeCopyGas, _ = IntrinsicGas(codeWithExtCodeCopy, nil, nil, true, true, true, true) intrinsicCodeWithExtCodeCopyGas, _ = types.NewContractCreation(0, big.NewInt(999), params.TxGas, big.NewInt(875000000), codeWithExtCodeCopy).IntrinsicGas(&rules)
signer = types.LatestSigner(testVerkleChainConfig) signer = types.LatestSigner(testVerkleChainConfig)
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
bcdb = rawdb.NewMemoryDatabase() // Database for the blockchain bcdb = rawdb.NewMemoryDatabase() // Database for the blockchain

View file

@ -591,6 +591,13 @@ func (evm *EVM) resolveCodeHash(addr common.Address) common.Hash {
// ChainConfig returns the environment's chain configuration // ChainConfig returns the environment's chain configuration
func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig } func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig }
// Rules returns the rules for the EVM given the current block's context.
func (evm *EVM) Rules() *params.Rules {
bctx := evm.Context
rules := evm.ChainConfig().Rules(bctx.BlockNumber, bctx.Random != nil, bctx.Time)
return &rules
}
func (evm *EVM) captureBegin(depth int, typ OpCode, from common.Address, to common.Address, input []byte, startGas uint64, value *big.Int) { func (evm *EVM) captureBegin(depth int, typ OpCode, from common.Address, to common.Address, input []byte, startGas uint64, value *big.Int) {
tracer := evm.Config.Tracer tracer := evm.Config.Tracer
if tracer.OnEnter != nil { if tracer.OnEnter != nil {

View file

@ -235,13 +235,16 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
return nil, vm.BlockContext{}, nil, nil, err return nil, vm.BlockContext{}, nil, nil, err
} }
// Insert parent beacon block root in the state as per EIP-4788. // Insert parent beacon block root in the state as per EIP-4788.
context := core.NewEVMBlockContext(block.Header(), eth.blockchain, nil) var (
evm := vm.NewEVM(context, statedb, eth.blockchain.Config(), vm.Config{}) context = core.NewEVMBlockContext(block.Header(), eth.blockchain, nil)
evm = vm.NewEVM(context, statedb, eth.blockchain.Config(), vm.Config{})
rules = evm.Rules()
)
if beaconRoot := block.BeaconRoot(); beaconRoot != nil { if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
core.ProcessBeaconBlockRoot(*beaconRoot, evm) core.ProcessBeaconBlockRoot(*beaconRoot, evm)
} }
// If prague hardfork, insert parent block hash in the state as per EIP-2935. // If prague hardfork, insert parent block hash in the state as per EIP-2935.
if eth.blockchain.Config().IsPrague(block.Number(), block.Time()) { if rules.IsPrague {
core.ProcessParentBlockHash(block.ParentHash(), evm) core.ProcessParentBlockHash(block.ParentHash(), evm)
} }
if txIndex == 0 && len(block.Transactions()) == 0 { if txIndex == 0 && len(block.Transactions()) == 0 {
@ -254,7 +257,7 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
return tx, context, statedb, release, nil return tx, context, statedb, release, nil
} }
// Assemble the transaction call message and return if the requested offset // Assemble the transaction call message and return if the requested offset
msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee(), rules)
// Not yet the searched for transaction, execute on top of the current state // Not yet the searched for transaction, execute on top of the current state
statedb.SetTxContext(tx.Hash(), idx) statedb.SetTxContext(tx.Hash(), idx)

View file

@ -270,10 +270,11 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
var ( var (
signer = types.MakeSigner(api.backend.ChainConfig(), task.block.Number(), task.block.Time()) signer = types.MakeSigner(api.backend.ChainConfig(), task.block.Number(), task.block.Time())
blockCtx = core.NewEVMBlockContext(task.block.Header(), api.chainContext(ctx), nil) blockCtx = core.NewEVMBlockContext(task.block.Header(), api.chainContext(ctx), nil)
rules = api.backend.ChainConfig().Rules(task.block.Number(), blockCtx.Random != nil, task.block.Time())
) )
// Trace all the transactions contained within // Trace all the transactions contained within
for i, tx := range task.block.Transactions() { for i, tx := range task.block.Transactions() {
msg, _ := core.TransactionToMessage(tx, signer, task.block.BaseFee()) msg, _ := core.TransactionToMessage(tx, signer, task.block.BaseFee(), &rules)
txctx := &Context{ txctx := &Context{
BlockHash: task.block.Hash(), BlockHash: task.block.Hash(),
BlockNumber: task.block.Number(), BlockNumber: task.block.Number(),
@ -536,19 +537,20 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
chainConfig = api.backend.ChainConfig() chainConfig = api.backend.ChainConfig()
vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
deleteEmptyObjects = chainConfig.IsEIP158(block.Number()) deleteEmptyObjects = chainConfig.IsEIP158(block.Number())
evm = vm.NewEVM(vmctx, statedb, chainConfig, vm.Config{})
rules = evm.Rules()
) )
evm := vm.NewEVM(vmctx, statedb, chainConfig, vm.Config{})
if beaconRoot := block.BeaconRoot(); beaconRoot != nil { if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
core.ProcessBeaconBlockRoot(*beaconRoot, evm) core.ProcessBeaconBlockRoot(*beaconRoot, evm)
} }
if chainConfig.IsPrague(block.Number(), block.Time()) { if rules.IsPrague {
core.ProcessParentBlockHash(block.ParentHash(), evm) core.ProcessParentBlockHash(block.ParentHash(), evm)
} }
for i, tx := range block.Transactions() { for i, tx := range block.Transactions() {
if err := ctx.Err(); err != nil { if err := ctx.Err(); err != nil {
return nil, err return nil, err
} }
msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee(), rules)
statedb.SetTxContext(tx.Hash(), i) statedb.SetTxContext(tx.Hash(), i)
if _, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit)); err != nil { if _, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit)); err != nil {
log.Warn("Tracing intermediate roots did not complete", "txindex", i, "txhash", tx.Hash(), "err", err) log.Warn("Tracing intermediate roots did not complete", "txindex", i, "txhash", tx.Hash(), "err", err)
@ -600,12 +602,15 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
} }
defer release() defer release()
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) var (
evm := vm.NewEVM(blockCtx, statedb, api.backend.ChainConfig(), vm.Config{}) blockCtx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
evm = vm.NewEVM(blockCtx, statedb, api.backend.ChainConfig(), vm.Config{})
rules = evm.Rules()
)
if beaconRoot := block.BeaconRoot(); beaconRoot != nil { if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
core.ProcessBeaconBlockRoot(*beaconRoot, evm) core.ProcessBeaconBlockRoot(*beaconRoot, evm)
} }
if api.backend.ChainConfig().IsPrague(block.Number(), block.Time()) { if rules.IsPrague {
core.ProcessParentBlockHash(block.ParentHash(), evm) core.ProcessParentBlockHash(block.ParentHash(), evm)
} }
@ -626,7 +631,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
) )
for i, tx := range txs { for i, tx := range txs {
// Generate the next state snapshot fast without tracing // Generate the next state snapshot fast without tracing
msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee(), rules)
txctx := &Context{ txctx := &Context{
BlockHash: blockHash, BlockHash: blockHash,
BlockNumber: block.Number(), BlockNumber: block.Number(),
@ -653,6 +658,7 @@ func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, stat
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()) signer = types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time())
results = make([]*txTraceResult, len(txs)) results = make([]*txTraceResult, len(txs))
pend sync.WaitGroup pend sync.WaitGroup
rules = api.backend.ChainConfig().Rules(block.Number(), block.Difficulty().Sign() == 0, block.Time())
) )
threads := runtime.NumCPU() threads := runtime.NumCPU()
if threads > len(txs) { if threads > len(txs) {
@ -665,7 +671,7 @@ func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, stat
defer pend.Done() defer pend.Done()
// Fetch and execute the next transaction trace tasks // Fetch and execute the next transaction trace tasks
for task := range jobs { for task := range jobs {
msg, _ := core.TransactionToMessage(txs[task.index], signer, block.BaseFee()) msg, _ := core.TransactionToMessage(txs[task.index], signer, block.BaseFee(), &rules)
txctx := &Context{ txctx := &Context{
BlockHash: blockHash, BlockHash: blockHash,
BlockNumber: block.Number(), BlockNumber: block.Number(),
@ -704,7 +710,7 @@ txloop:
} }
// Generate the next state snapshot fast without tracing // Generate the next state snapshot fast without tracing
msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee(), &rules)
statedb.SetTxContext(tx.Hash(), i) statedb.SetTxContext(tx.Hash(), i)
if _, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit)); err != nil { if _, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(msg.GasLimit)); err != nil {
failed = err failed = err
@ -778,17 +784,20 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
// Note: This copies the config, to not screw up the main config // Note: This copies the config, to not screw up the main config
chainConfig, canon = overrideConfig(chainConfig, config.Overrides) chainConfig, canon = overrideConfig(chainConfig, config.Overrides)
} }
evm := vm.NewEVM(vmctx, statedb, chainConfig, vm.Config{}) var (
evm = vm.NewEVM(vmctx, statedb, chainConfig, vm.Config{})
rules = evm.Rules()
)
if beaconRoot := block.BeaconRoot(); beaconRoot != nil { if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
core.ProcessBeaconBlockRoot(*beaconRoot, evm) core.ProcessBeaconBlockRoot(*beaconRoot, evm)
} }
if chainConfig.IsPrague(block.Number(), block.Time()) { if rules.IsPrague {
core.ProcessParentBlockHash(block.ParentHash(), evm) core.ProcessParentBlockHash(block.ParentHash(), evm)
} }
for i, tx := range block.Transactions() { for i, tx := range block.Transactions() {
// Prepare the transaction for un-traced execution // Prepare the transaction for un-traced execution
var ( var (
msg, _ = core.TransactionToMessage(tx, signer, block.BaseFee()) msg, _ = core.TransactionToMessage(tx, signer, block.BaseFee(), rules)
vmConf vm.Config vmConf vm.Config
dump *os.File dump *os.File
writer *bufio.Writer writer *bufio.Writer
@ -885,7 +894,8 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *
return nil, err return nil, err
} }
defer release() defer release()
msg, err := core.TransactionToMessage(tx, types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()), block.BaseFee()) rules := api.backend.ChainConfig().Rules(block.Number(), vmctx.Random != nil, block.Time())
msg, err := core.TransactionToMessage(tx, types.MakeSigner(api.backend.ChainConfig(), block.Number(), block.Time()), block.BaseFee(), &rules)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -967,7 +977,8 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
return nil, err return nil, err
} }
var ( var (
msg = args.ToMessage(vmctx.BaseFee, true, true) rules = api.backend.ChainConfig().Rules(block.Number(), vmctx.Random != nil, block.Time())
msg = args.ToMessage(&rules, vmctx.BaseFee, true, true)
tx = args.ToTransaction(types.LegacyTxType) tx = args.ToTransaction(types.LegacyTxType)
traceConfig *TraceConfig traceConfig *TraceConfig
) )

View file

@ -178,11 +178,12 @@ func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block
signer := types.MakeSigner(b.chainConfig, block.Number(), block.Time()) signer := types.MakeSigner(b.chainConfig, block.Number(), block.Time())
context := core.NewEVMBlockContext(block.Header(), b.chain, nil) context := core.NewEVMBlockContext(block.Header(), b.chain, nil)
evm := vm.NewEVM(context, statedb, b.chainConfig, vm.Config{}) evm := vm.NewEVM(context, statedb, b.chainConfig, vm.Config{})
rules := evm.Rules()
for idx, tx := range block.Transactions() { for idx, tx := range block.Transactions() {
if idx == txIndex { if idx == txIndex {
return tx, context, statedb, release, nil return tx, context, statedb, release, nil
} }
msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee()) msg, _ := core.TransactionToMessage(tx, signer, block.BaseFee(), rules)
if _, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil { if _, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err) return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
} }

View file

@ -125,11 +125,11 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
if tracer.Hooks != nil { if tracer.Hooks != nil {
logState = state.NewHookedState(st.StateDB, tracer.Hooks) logState = state.NewHookedState(st.StateDB, tracer.Hooks)
} }
msg, err := core.TransactionToMessage(tx, signer, context.BaseFee) evm := vm.NewEVM(context, logState, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
msg, err := core.TransactionToMessage(tx, signer, context.BaseFee, evm.Rules())
if err != nil { if err != nil {
t.Fatalf("failed to prepare transaction for tracing: %v", err) t.Fatalf("failed to prepare transaction for tracing: %v", err)
} }
evm := vm.NewEVM(context, logState, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From) tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas())) vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
if err != nil { if err != nil {
@ -201,20 +201,20 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
if err := tx.UnmarshalBinary(common.FromHex(test.Input)); err != nil { if err := tx.UnmarshalBinary(common.FromHex(test.Input)); err != nil {
b.Fatalf("failed to parse testcase input: %v", err) b.Fatalf("failed to parse testcase input: %v", err)
} }
signer := types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time))
context := test.Context.toBlockContext(test.Genesis)
msg, err := core.TransactionToMessage(tx, signer, context.BaseFee)
if err != nil {
b.Fatalf("failed to prepare transaction for tracing: %v", err)
}
state := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme) state := tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
defer state.Close() defer state.Close()
signer := types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time))
context := test.Context.toBlockContext(test.Genesis)
evm := vm.NewEVM(context, state.StateDB, test.Genesis.Config, vm.Config{})
msg, err := core.TransactionToMessage(tx, signer, context.BaseFee, evm.Rules())
if err != nil {
b.Fatalf("failed to prepare transaction for tracing: %v", err)
}
b.ReportAllocs() b.ReportAllocs()
b.ResetTimer() b.ResetTimer()
evm := vm.NewEVM(context, state.StateDB, test.Genesis.Config, vm.Config{})
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
snap := state.StateDB.Snapshot() snap := state.StateDB.Snapshot()
tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), nil, test.Genesis.Config) tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), nil, test.Genesis.Config)
@ -370,7 +370,7 @@ func TestInternals(t *testing.T) {
t.Fatalf("test %v: failed to sign transaction: %v", tc.name, err) t.Fatalf("test %v: failed to sign transaction: %v", tc.name, err)
} }
evm := vm.NewEVM(context, logState, config, vm.Config{Tracer: tc.tracer.Hooks}) evm := vm.NewEVM(context, logState, config, vm.Config{Tracer: tc.tracer.Hooks})
msg, err := core.TransactionToMessage(tx, signer, big.NewInt(0)) msg, err := core.TransactionToMessage(tx, signer, big.NewInt(0), evm.Rules())
if err != nil { if err != nil {
t.Fatalf("test %v: failed to create message: %v", tc.name, err) t.Fatalf("test %v: failed to create message: %v", tc.name, err)
} }

View file

@ -107,11 +107,11 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string
return fmt.Errorf("failed to create call tracer: %v", err) return fmt.Errorf("failed to create call tracer: %v", err)
} }
msg, err := core.TransactionToMessage(tx, signer, context.BaseFee) evm := vm.NewEVM(context, state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
msg, err := core.TransactionToMessage(tx, signer, context.BaseFee, evm.Rules())
if err != nil { if err != nil {
return fmt.Errorf("failed to prepare transaction for tracing: %v", err) return fmt.Errorf("failed to prepare transaction for tracing: %v", err)
} }
evm := vm.NewEVM(context, state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From) tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas())) vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
if err != nil { if err != nil {

View file

@ -99,11 +99,11 @@ func testPrestateTracer(tracerName string, dirPath string, t *testing.T) {
t.Fatalf("failed to create call tracer: %v", err) t.Fatalf("failed to create call tracer: %v", err)
} }
msg, err := core.TransactionToMessage(tx, signer, context.BaseFee) evm := vm.NewEVM(context, state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
msg, err := core.TransactionToMessage(tx, signer, context.BaseFee, evm.Rules())
if err != nil { if err != nil {
t.Fatalf("failed to prepare transaction for tracing: %v", err) t.Fatalf("failed to prepare transaction for tracing: %v", err)
} }
evm := vm.NewEVM(context, state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From) tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas())) vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
if err != nil { if err != nil {

View file

@ -80,7 +80,7 @@ func BenchmarkTransactionTraceV2(b *testing.B) {
evm := vm.NewEVM(context, state.StateDB, params.AllEthashProtocolChanges, vm.Config{}) evm := vm.NewEVM(context, state.StateDB, params.AllEthashProtocolChanges, vm.Config{})
msg, err := core.TransactionToMessage(tx, signer, context.BaseFee) msg, err := core.TransactionToMessage(tx, signer, context.BaseFee, evm.Rules())
if err != nil { if err != nil {
b.Fatalf("failed to prepare transaction for tracing: %v", err) b.Fatalf("failed to prepare transaction for tracing: %v", err)
} }

View file

@ -695,7 +695,8 @@ func applyMessage(ctx context.Context, b Backend, args TransactionArgs, state *s
if err := args.CallDefaults(gp.Gas(), blockContext.BaseFee, b.ChainConfig().ChainID); err != nil { if err := args.CallDefaults(gp.Gas(), blockContext.BaseFee, b.ChainConfig().ChainID); err != nil {
return nil, err return nil, err
} }
msg := args.ToMessage(header.BaseFee, skipChecks, skipChecks) rules := b.ChainConfig().Rules(header.Number, blockContext.Random != nil, header.Time)
msg := args.ToMessage(&rules, header.BaseFee, skipChecks, skipChecks)
// Lower the basefee to 0 to avoid breaking EVM // Lower the basefee to 0 to avoid breaking EVM
// invariants (basefee < feecap). // invariants (basefee < feecap).
if msg.GasPrice.Sign() == 0 { if msg.GasPrice.Sign() == 0 {
@ -838,7 +839,8 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
if err := args.CallDefaults(gasCap, header.BaseFee, b.ChainConfig().ChainID); err != nil { if err := args.CallDefaults(gasCap, header.BaseFee, b.ChainConfig().ChainID); err != nil {
return 0, err return 0, err
} }
call := args.ToMessage(header.BaseFee, true, true) rules := b.ChainConfig().Rules(header.Number, header.Difficulty.Sign() == 0, header.Time)
call := args.ToMessage(&rules, header.BaseFee, true, true)
// Run the gas estimation and wrap any revertals into a custom return // Run the gas estimation and wrap any revertals into a custom return
estimate, revert, err := gasestimator.Estimate(ctx, call, opts, gasCap) estimate, revert, err := gasestimator.Estimate(ctx, call, opts, gasCap)
@ -1214,15 +1216,15 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH
// Copy the original db so we don't modify it // Copy the original db so we don't modify it
statedb := db.Copy() statedb := db.Copy()
// Set the accesslist to the last al
args.AccessList = &accessList
msg := args.ToMessage(header.BaseFee, true, true)
// Apply the transaction with the access list tracer // Apply the transaction with the access list tracer
tracer := logger.NewAccessListTracer(accessList, addressesToExclude) tracer := logger.NewAccessListTracer(accessList, addressesToExclude)
config := vm.Config{Tracer: tracer.Hooks(), NoBaseFee: true} config := vm.Config{Tracer: tracer.Hooks(), NoBaseFee: true}
evm := b.GetEVM(ctx, statedb, header, &config, nil) evm := b.GetEVM(ctx, statedb, header, &config, nil)
// Set the accesslist to the last al
args.AccessList = &accessList
msg := args.ToMessage(evm.Rules(), header.BaseFee, true, true)
// Lower the basefee to 0 to avoid breaking EVM // Lower the basefee to 0 to avoid breaking EVM
// invariants (basefee < feecap). // invariants (basefee < feecap).
if msg.GasPrice.Sign() == 0 { if msg.GasPrice.Sign() == 0 {

View file

@ -259,12 +259,13 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
tracingStateDB = state.NewHookedState(sim.state, hooks) tracingStateDB = state.NewHookedState(sim.state, hooks)
} }
evm := vm.NewEVM(blockContext, tracingStateDB, sim.chainConfig, *vmConfig) evm := vm.NewEVM(blockContext, tracingStateDB, sim.chainConfig, *vmConfig)
rules := evm.Rules()
// It is possible to override precompiles with EVM bytecode, or // It is possible to override precompiles with EVM bytecode, or
// move them to another address. // move them to another address.
if precompiles != nil { if precompiles != nil {
evm.SetPrecompiles(precompiles) evm.SetPrecompiles(precompiles)
} }
if sim.chainConfig.IsPrague(header.Number, header.Time) || sim.chainConfig.IsVerkle(header.Number, header.Time) { if rules.IsPrague || rules.IsVerkle {
core.ProcessParentBlockHash(header.ParentHash, evm) core.ProcessParentBlockHash(header.ParentHash, evm)
} }
if header.ParentBeaconRoot != nil { if header.ParentBeaconRoot != nil {
@ -287,7 +288,7 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
tracer.reset(txHash, uint(i)) tracer.reset(txHash, uint(i))
sim.state.SetTxContext(txHash, i) sim.state.SetTxContext(txHash, i)
// EoA check is always skipped, even in validation mode. // EoA check is always skipped, even in validation mode.
msg := call.ToMessage(header.BaseFee, !sim.validate, true) msg := call.ToMessage(rules, header.BaseFee, !sim.validate, true)
result, err := applyMessageWithEVM(ctx, evm, msg, timeout, sim.gp) result, err := applyMessageWithEVM(ctx, evm, msg, timeout, sim.gp)
if err != nil { if err != nil {
txErr := txValidationError(err) txErr := txValidationError(err)

View file

@ -414,7 +414,7 @@ func (args *TransactionArgs) CallDefaults(globalGasCap uint64, baseFee *big.Int,
// core evm. This method is used in calls and traces that do not require a real // core evm. This method is used in calls and traces that do not require a real
// live transaction. // live transaction.
// Assumes that fields are not nil, i.e. setDefaults or CallDefaults has been called. // Assumes that fields are not nil, i.e. setDefaults or CallDefaults has been called.
func (args *TransactionArgs) ToMessage(baseFee *big.Int, skipNonceCheck, skipEoACheck bool) *core.Message { func (args *TransactionArgs) ToMessage(rules *params.Rules, baseFee *big.Int, skipNonceCheck, skipEoACheck bool) *core.Message {
var ( var (
gasPrice *big.Int gasPrice *big.Int
gasFeeCap *big.Int gasFeeCap *big.Int
@ -447,11 +447,25 @@ func (args *TransactionArgs) ToMessage(baseFee *big.Int, skipNonceCheck, skipEoA
if args.AccessList != nil { if args.AccessList != nil {
accessList = *args.AccessList accessList = *args.AccessList
} }
// Compute the intrinsic gas for stTransaction. Since the test file doesn't
// specify the transaction type we need to infer. This is hacky but we can use
// dynamic fee tx to represent all txs (with respect to instrinsic gas calc at
// least) types except the set code tx type.
var txdata types.TxData
if args.To == nil {
txdata = &types.DynamicFeeTx{To: args.To, Data: args.data(), AccessList: accessList}
} else {
txdata = &types.SetCodeTx{To: *args.To, Data: args.data(), AccessList: accessList, AuthList: args.AuthorizationList}
}
intrinsicGas := types.IntrinsicGas(txdata, rules)
return &core.Message{ return &core.Message{
From: args.from(), From: args.from(),
To: args.To, To: args.To,
Value: (*big.Int)(args.Value), Value: (*big.Int)(args.Value),
Nonce: uint64(*args.Nonce), Nonce: uint64(*args.Nonce),
IntrinsicGas: intrinsicGas,
GasLimit: uint64(*args.Gas), GasLimit: uint64(*args.Gas),
GasPrice: gasPrice, GasPrice: gasPrice,
GasFeeCap: gasFeeCap, GasFeeCap: gasFeeCap,

View file

@ -271,7 +271,7 @@ func runBenchmark(b *testing.B, t *StateTest) {
} }
} }
post := t.json.Post[subtest.Fork][subtest.Index] post := t.json.Post[subtest.Fork][subtest.Index]
msg, err := t.json.Tx.toMessage(post, baseFee) msg, err := t.json.Tx.toMessage(post, baseFee, &rules)
if err != nil { if err != nil {
b.Error(err) b.Error(err)
return return

View file

@ -257,6 +257,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
return st, common.Hash{}, 0, UnsupportedForkError{subtest.Fork} return st, common.Hash{}, 0, UnsupportedForkError{subtest.Fork}
} }
vmconfig.ExtraEips = eips vmconfig.ExtraEips = eips
rules := config.Rules(new(big.Int).SetUint64(t.json.Env.Number), t.json.Env.Random != nil, t.json.Env.Timestamp)
block := t.genesis(config).ToBlock() block := t.genesis(config).ToBlock()
st = MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, snapshotter, scheme) st = MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, snapshotter, scheme)
@ -271,7 +272,7 @@ func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapsh
} }
} }
post := t.json.Post[subtest.Fork][subtest.Index] post := t.json.Post[subtest.Fork][subtest.Index]
msg, err := t.json.Tx.toMessage(post, baseFee) msg, err := t.json.Tx.toMessage(post, baseFee, &rules)
if err != nil { if err != nil {
return st, common.Hash{}, 0, err return st, common.Hash{}, 0, err
} }
@ -376,7 +377,7 @@ func (t *StateTest) genesis(config *params.ChainConfig) *core.Genesis {
return genesis return genesis
} }
func (tx *stTransaction) toMessage(ps stPostState, baseFee *big.Int) (*core.Message, error) { func (tx *stTransaction) toMessage(ps stPostState, baseFee *big.Int, rules *params.Rules) (*core.Message, error) {
var from common.Address var from common.Address
// If 'sender' field is present, use that // If 'sender' field is present, use that
if tx.Sender != nil { if tx.Sender != nil {
@ -463,11 +464,24 @@ func (tx *stTransaction) toMessage(ps stPostState, baseFee *big.Int) (*core.Mess
} }
} }
// Compute the intrinsic gas for stTransaction. Since the test file doesn't
// specify the transaction type we need to infer. This is hacky but we can use
// dynamic fee tx to represent all txs (with respect to instrinsic gas calc at
// least) types except the set code tx type.
var txdata types.TxData
if to == nil {
txdata = &types.DynamicFeeTx{To: to, Data: data, AccessList: accessList}
} else {
txdata = &types.SetCodeTx{To: *to, Data: data, AccessList: accessList, AuthList: authList}
}
gas := types.IntrinsicGas(txdata, rules)
msg := &core.Message{ msg := &core.Message{
From: from, From: from,
To: to, To: to,
Nonce: tx.Nonce, Nonce: tx.Nonce,
Value: value, Value: value,
IntrinsicGas: gas,
GasLimit: gasLimit, GasLimit: gasLimit,
GasPrice: gasPrice, GasPrice: gasPrice,
GasFeeCap: tx.MaxFeePerGas, GasFeeCap: tx.MaxFeePerGas,

View file

@ -80,7 +80,7 @@ func (tt *TransactionTest) Run() error {
return return
} }
// Intrinsic gas // Intrinsic gas
requiredGas, err = core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations(), tx.To() == nil, rules.IsHomestead, rules.IsIstanbul, rules.IsShanghai) requiredGas, err = tx.IntrinsicGas(rules)
if err != nil { if err != nil {
return return
} }