Skip to content

Commit 49d2543

Browse files
MariusVanDerWijdens1na
authored andcommitted
core: implement eip-7623
Co-authored-by: Marius van der Wijden <[email protected]> Co-authored-by: Sina Mahmoodi <[email protected]>
1 parent 82e963e commit 49d2543

16 files changed

+110
-61
lines changed

cmd/evm/internal/t8ntool/transaction.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ func Transaction(ctx *cli.Context) error {
133133
r.Address = sender
134134
}
135135
// Check intrinsic gas
136-
if gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations(), tx.To() == nil,
136+
if gas, _, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations(), tx.To() == nil,
137137
chainConfig.IsHomestead(new(big.Int)), chainConfig.IsIstanbul(new(big.Int)), chainConfig.IsShanghai(new(big.Int), 0)); err != nil {
138138
r.Error = err
139139
results = append(results, r)

core/bench_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ func genValueTx(nbytes int) func(int, *BlockGen) {
9090
data := make([]byte, nbytes)
9191
return func(i int, gen *BlockGen) {
9292
toaddr := common.Address{}
93-
gas, _ := IntrinsicGas(data, nil, nil, false, false, false, false)
93+
gas, _, _ := IntrinsicGas(data, nil, nil, false, false, false, false)
9494
signer := gen.Signer()
9595
gasPrice := big.NewInt(0)
9696
if gen.header.BaseFee != nil {

core/error.go

+4
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ var (
8080
// than required to start the invocation.
8181
ErrIntrinsicGas = errors.New("intrinsic gas too low")
8282

83+
// ErrDataFloorGas is returned if the transaction is specified to use less gas
84+
// than required for the data floor cost.
85+
ErrDataFloorGas = errors.New("insufficient gas for data floor cost")
86+
8387
// ErrTxTypeNotSupported is returned if a transaction is not supported in the
8488
// current network configuration.
8589
ErrTxTypeNotSupported = types.ErrTxTypeNotSupported

core/state_processor_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,9 @@ func TestStateProcessorErrors(t *testing.T) {
251251
},
252252
{ // ErrMaxInitCodeSizeExceeded
253253
txs: []*types.Transaction{
254-
mkDynamicCreationTx(0, 500000, common.Big0, big.NewInt(params.InitialBaseFee), tooBigInitCode[:]),
254+
mkDynamicCreationTx(0, 520000, common.Big0, big.NewInt(params.InitialBaseFee), tooBigInitCode[:]),
255255
},
256-
want: "could not apply tx 0 [0xd491405f06c92d118dd3208376fcee18a57c54bc52063ee4a26b1cf296857c25]: max initcode size exceeded: code size 49153 limit 49152",
256+
want: "could not apply tx 0 [0x3a30404d42d6ccc843d7c391fd0c87b9b9795a0c174261b46d2ac95ca17b81cd]: max initcode size exceeded: code size 49153 limit 49152",
257257
},
258258
{ // ErrIntrinsicGas: Not enough gas to cover init code
259259
txs: []*types.Transaction{

core/state_transition.go

+43-9
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,14 @@ func (result *ExecutionResult) Revert() []byte {
6666
return common.CopyBytes(result.ReturnData)
6767
}
6868

69-
// IntrinsicGas computes the 'intrinsic gas' for a message with the given data.
70-
func IntrinsicGas(data []byte, accessList types.AccessList, authList []types.SetCodeAuthorization, isContractCreation, isHomestead, isEIP2028, isEIP3860 bool) (uint64, error) {
69+
// IntrinsicGas computes the 'intrinsic gas' and the number of tokens for EIP-7623
70+
// for a message with the given data.
71+
func IntrinsicGas(data []byte, accessList types.AccessList, authList []types.SetCodeAuthorization, isContractCreation, isHomestead, isEIP2028, isEIP3860 bool) (uint64, uint64, error) {
7172
// Set the starting gas for the raw transaction
72-
var gas uint64
73+
var (
74+
gas uint64
75+
tokens uint64
76+
)
7377
if isContractCreation && isHomestead {
7478
gas = params.TxGasContractCreation
7579
} else {
@@ -85,26 +89,28 @@ func IntrinsicGas(data []byte, accessList types.AccessList, authList []types.Set
8589
nz++
8690
}
8791
}
92+
z := dataLen - nz
93+
tokens = nz*params.TokenPerNonZeroByte7623 + z
94+
8895
// Make sure we don't exceed uint64 for all data combinations
8996
nonZeroGas := params.TxDataNonZeroGasFrontier
9097
if isEIP2028 {
9198
nonZeroGas = params.TxDataNonZeroGasEIP2028
9299
}
93100
if (math.MaxUint64-gas)/nonZeroGas < nz {
94-
return 0, ErrGasUintOverflow
101+
return 0, tokens, ErrGasUintOverflow
95102
}
96103
gas += nz * nonZeroGas
97104

98-
z := dataLen - nz
99105
if (math.MaxUint64-gas)/params.TxDataZeroGas < z {
100-
return 0, ErrGasUintOverflow
106+
return 0, tokens, ErrGasUintOverflow
101107
}
102108
gas += z * params.TxDataZeroGas
103109

104110
if isContractCreation && isEIP3860 {
105111
lenWords := toWordSize(dataLen)
106112
if (math.MaxUint64-gas)/params.InitCodeWordGas < lenWords {
107-
return 0, ErrGasUintOverflow
113+
return 0, tokens, ErrGasUintOverflow
108114
}
109115
gas += lenWords * params.InitCodeWordGas
110116
}
@@ -116,7 +122,7 @@ func IntrinsicGas(data []byte, accessList types.AccessList, authList []types.Set
116122
if authList != nil {
117123
gas += uint64(len(authList)) * params.CallNewAccountGas
118124
}
119-
return gas, nil
125+
return gas, tokens, nil
120126
}
121127

122128
// toWordSize returns the ceiled word size required for init code payment calculation.
@@ -417,13 +423,23 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
417423
)
418424

419425
// Check clauses 4-5, subtract intrinsic gas if everything is correct
420-
gas, err := IntrinsicGas(msg.Data, msg.AccessList, msg.SetCodeAuthorizations, contractCreation, rules.IsHomestead, rules.IsIstanbul, rules.IsShanghai)
426+
gas, dataTokens, err := IntrinsicGas(msg.Data, msg.AccessList, msg.SetCodeAuthorizations, contractCreation, rules.IsHomestead, rules.IsIstanbul, rules.IsShanghai)
421427
if err != nil {
422428
return nil, err
423429
}
424430
if st.gasRemaining < gas {
425431
return nil, fmt.Errorf("%w: have %d, want %d", ErrIntrinsicGas, st.gasRemaining, gas)
426432
}
433+
// Gas limit suffices for the floor data cost (EIP-7623)
434+
if rules.IsPrague {
435+
floorGas, err := FloorDataGas(dataTokens)
436+
if err != nil {
437+
return nil, err
438+
}
439+
if st.gasRemaining < floorGas {
440+
return nil, fmt.Errorf("%w: have %d, want %d", ErrDataFloorGas, st.gasRemaining, floorGas)
441+
}
442+
}
427443
if t := st.evm.Config.Tracer; t != nil && t.OnGasChange != nil {
428444
t.OnGasChange(st.gasRemaining, st.gasRemaining-gas, tracing.GasChangeTxIntrinsicGas)
429445
}
@@ -486,6 +502,14 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
486502
// Execute the transaction's call.
487503
ret, st.gasRemaining, vmerr = st.evm.Call(sender, st.to(), msg.Data, st.gasRemaining, value)
488504
}
505+
if rules.IsPrague {
506+
// After EIP-7623: Data-heavy transactions pay the floor gas.
507+
// Overflow error has already been checked and can be ignored here.
508+
floorGas, _ := FloorDataGas(dataTokens)
509+
if st.gasUsed() < floorGas {
510+
st.gasRemaining = st.initialGas - floorGas
511+
}
512+
}
489513

490514
var gasRefund uint64
491515
if !rules.IsLondon {
@@ -623,3 +647,13 @@ func (st *stateTransition) gasUsed() uint64 {
623647
func (st *stateTransition) blobGasUsed() uint64 {
624648
return uint64(len(st.msg.BlobHashes) * params.BlobTxBlobGasPerBlob)
625649
}
650+
651+
// FloorDataGas calculates the minimum gas required for a transaction
652+
// based on its data tokens (EIP-7623).
653+
func FloorDataGas(tokens uint64) (uint64, error) {
654+
// Check for overflow
655+
if (math.MaxUint64-params.TxGas)/params.CostFloorPerToken7623 < tokens {
656+
return 0, ErrGasUintOverflow
657+
}
658+
return params.TxGas + tokens*params.CostFloorPerToken7623, nil
659+
}

core/txpool/validation.go

+11-1
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,23 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types
108108
}
109109
// Ensure the transaction has more gas than the bare minimum needed to cover
110110
// the transaction metadata
111-
intrGas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations(), tx.To() == nil, true, opts.Config.IsIstanbul(head.Number), opts.Config.IsShanghai(head.Number, head.Time))
111+
intrGas, dataTokens, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.SetCodeAuthorizations(), tx.To() == nil, true, opts.Config.IsIstanbul(head.Number), opts.Config.IsShanghai(head.Number, head.Time))
112112
if err != nil {
113113
return err
114114
}
115115
if tx.Gas() < intrGas {
116116
return fmt.Errorf("%w: gas %v, minimum needed %v", core.ErrIntrinsicGas, tx.Gas(), intrGas)
117117
}
118+
// Ensure the transaction can cover floor data gas.
119+
if opts.Config.IsPrague(head.Number, head.Time) {
120+
floorGas, err := core.FloorDataGas(dataTokens)
121+
if err != nil {
122+
return err
123+
}
124+
if tx.Gas() < floorGas {
125+
return fmt.Errorf("%w: gas %v, minimum needed %v", core.ErrDataFloorGas, tx.Gas(), floorGas)
126+
}
127+
}
118128
// Ensure the gasprice is high enough to cover the requirement of the calling pool
119129
if tx.GasTipCapIntCmp(opts.MinTip) < 0 {
120130
return fmt.Errorf("%w: gas tip cap %v, minimum needed %v", ErrUnderpriced, tx.GasTipCap(), opts.MinTip)

core/verkle_witness_test.go

+9-9
Original file line numberDiff line numberDiff line change
@@ -82,18 +82,18 @@ var (
8282

8383
func TestProcessVerkle(t *testing.T) {
8484
var (
85-
code = common.FromHex(`6060604052600a8060106000396000f360606040526008565b00`)
86-
intrinsicContractCreationGas, _ = IntrinsicGas(code, nil, nil, true, true, true, true)
85+
code = common.FromHex(`6060604052600a8060106000396000f360606040526008565b00`)
86+
intrinsicContractCreationGas, _, _ = IntrinsicGas(code, nil, nil, true, true, true, true)
8787
// A contract creation that calls EXTCODECOPY in the constructor. Used to ensure that the witness
8888
// will not contain that copied data.
8989
// Source: https://gist.github.com/gballet/a23db1e1cb4ed105616b5920feb75985
90-
codeWithExtCodeCopy = common.FromHex(`0x60806040526040516100109061017b565b604051809103906000f08015801561002c573d6000803e3d6000fd5b506000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561007857600080fd5b5060008067ffffffffffffffff8111156100955761009461024a565b5b6040519080825280601f01601f1916602001820160405280156100c75781602001600182028036833780820191505090505b50905060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506020600083833c81610101906101e3565b60405161010d90610187565b61011791906101a3565b604051809103906000f080158015610133573d6000803e3d6000fd5b50600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505061029b565b60d58061046783390190565b6102068061053c83390190565b61019d816101d9565b82525050565b60006020820190506101b86000830184610194565b92915050565b6000819050602082019050919050565b600081519050919050565b6000819050919050565b60006101ee826101ce565b826101f8846101be565b905061020381610279565b925060208210156102435761023e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8360200360080261028e565b831692505b5050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600061028582516101d9565b80915050919050565b600082821b905092915050565b6101bd806102aa6000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f566852414610030575b600080fd5b61003861004e565b6040516100459190610146565b60405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166381ca91d36040518163ffffffff1660e01b815260040160206040518083038186803b1580156100b857600080fd5b505afa1580156100cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100f0919061010a565b905090565b60008151905061010481610170565b92915050565b6000602082840312156101205761011f61016b565b5b600061012e848285016100f5565b91505092915050565b61014081610161565b82525050565b600060208201905061015b6000830184610137565b92915050565b6000819050919050565b600080fd5b61017981610161565b811461018457600080fd5b5056fea2646970667358221220a6a0e11af79f176f9c421b7b12f441356b25f6489b83d38cc828a701720b41f164736f6c63430008070033608060405234801561001057600080fd5b5060b68061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063ab5ed15014602d575b600080fd5b60336047565b604051603e9190605d565b60405180910390f35b60006001905090565b6057816076565b82525050565b6000602082019050607060008301846050565b92915050565b600081905091905056fea26469706673582212203a14eb0d5cd07c277d3e24912f110ddda3e553245a99afc4eeefb2fbae5327aa64736f6c63430008070033608060405234801561001057600080fd5b5060405161020638038061020683398181016040528101906100329190610063565b60018160001c6100429190610090565b60008190555050610145565b60008151905061005d8161012e565b92915050565b60006020828403121561007957610078610129565b5b60006100878482850161004e565b91505092915050565b600061009b826100f0565b91506100a6836100f0565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156100db576100da6100fa565b5b828201905092915050565b6000819050919050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600080fd5b610137816100e6565b811461014257600080fd5b50565b60b3806101536000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806381ca91d314602d575b600080fd5b60336047565b604051603e9190605a565b60405180910390f35b60005481565b6054816073565b82525050565b6000602082019050606d6000830184604d565b92915050565b600081905091905056fea26469706673582212209bff7098a2f526de1ad499866f27d6d0d6f17b74a413036d6063ca6a0998ca4264736f6c63430008070033`)
91-
intrinsicCodeWithExtCodeCopyGas, _ = IntrinsicGas(codeWithExtCodeCopy, nil, nil, true, true, true, true)
92-
signer = types.LatestSigner(testVerkleChainConfig)
93-
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
94-
bcdb = rawdb.NewMemoryDatabase() // Database for the blockchain
95-
coinbase = common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7")
96-
gspec = &Genesis{
90+
codeWithExtCodeCopy = common.FromHex(`0x60806040526040516100109061017b565b604051809103906000f08015801561002c573d6000803e3d6000fd5b506000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555034801561007857600080fd5b5060008067ffffffffffffffff8111156100955761009461024a565b5b6040519080825280601f01601f1916602001820160405280156100c75781602001600182028036833780820191505090505b50905060008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506020600083833c81610101906101e3565b60405161010d90610187565b61011791906101a3565b604051809103906000f080158015610133573d6000803e3d6000fd5b50600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505061029b565b60d58061046783390190565b6102068061053c83390190565b61019d816101d9565b82525050565b60006020820190506101b86000830184610194565b92915050565b6000819050602082019050919050565b600081519050919050565b6000819050919050565b60006101ee826101ce565b826101f8846101be565b905061020381610279565b925060208210156102435761023e7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8360200360080261028e565b831692505b5050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600061028582516101d9565b80915050919050565b600082821b905092915050565b6101bd806102aa6000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063f566852414610030575b600080fd5b61003861004e565b6040516100459190610146565b60405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166381ca91d36040518163ffffffff1660e01b815260040160206040518083038186803b1580156100b857600080fd5b505afa1580156100cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100f0919061010a565b905090565b60008151905061010481610170565b92915050565b6000602082840312156101205761011f61016b565b5b600061012e848285016100f5565b91505092915050565b61014081610161565b82525050565b600060208201905061015b6000830184610137565b92915050565b6000819050919050565b600080fd5b61017981610161565b811461018457600080fd5b5056fea2646970667358221220a6a0e11af79f176f9c421b7b12f441356b25f6489b83d38cc828a701720b41f164736f6c63430008070033608060405234801561001057600080fd5b5060b68061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063ab5ed15014602d575b600080fd5b60336047565b604051603e9190605d565b60405180910390f35b60006001905090565b6057816076565b82525050565b6000602082019050607060008301846050565b92915050565b600081905091905056fea26469706673582212203a14eb0d5cd07c277d3e24912f110ddda3e553245a99afc4eeefb2fbae5327aa64736f6c63430008070033608060405234801561001057600080fd5b5060405161020638038061020683398181016040528101906100329190610063565b60018160001c6100429190610090565b60008190555050610145565b60008151905061005d8161012e565b92915050565b60006020828403121561007957610078610129565b5b60006100878482850161004e565b91505092915050565b600061009b826100f0565b91506100a6836100f0565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156100db576100da6100fa565b5b828201905092915050565b6000819050919050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600080fd5b610137816100e6565b811461014257600080fd5b50565b60b3806101536000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806381ca91d314602d575b600080fd5b60336047565b604051603e9190605a565b60405180910390f35b60005481565b6054816073565b82525050565b6000602082019050606d6000830184604d565b92915050565b600081905091905056fea26469706673582212209bff7098a2f526de1ad499866f27d6d0d6f17b74a413036d6063ca6a0998ca4264736f6c63430008070033`)
91+
intrinsicCodeWithExtCodeCopyGas, _, _ = IntrinsicGas(codeWithExtCodeCopy, nil, nil, true, true, true, true)
92+
signer = types.LatestSigner(testVerkleChainConfig)
93+
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
94+
bcdb = rawdb.NewMemoryDatabase() // Database for the blockchain
95+
coinbase = common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7")
96+
gspec = &Genesis{
9797
Config: testVerkleChainConfig,
9898
Alloc: GenesisAlloc{
9999
coinbase: {

internal/ethapi/override/override_test.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import (
2424
"github.com/ethereum/go-ethereum/common/hexutil"
2525
"github.com/ethereum/go-ethereum/core/rawdb"
2626
"github.com/ethereum/go-ethereum/core/state"
27-
"github.com/ethereum/go-ethereum/core/types"
2827
"github.com/ethereum/go-ethereum/core/vm"
2928
"github.com/ethereum/go-ethereum/triedb"
3029
)
@@ -37,7 +36,7 @@ func (p *precompileContract) Run(input []byte) ([]byte, error) { return nil, nil
3736

3837
func TestStateOverrideMovePrecompile(t *testing.T) {
3938
db := state.NewDatabase(triedb.NewDatabase(rawdb.NewMemoryDatabase(), nil), nil)
40-
statedb, err := state.New(types.EmptyRootHash, db)
39+
statedb, err := state.New(common.Hash{}, db)
4140
if err != nil {
4241
t.Fatalf("failed to create statedb: %v", err)
4342
}

internal/ethapi/testdata/eth_getBlockReceipts-block-with-blob-tx.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@
22
{
33
"blobGasPrice": "0x1",
44
"blobGasUsed": "0x20000",
5-
"blockHash": "0x17124e31fb075a301b1d7d4135683b0a09fe4e6d453c54e2e734d5ee00744a49",
5+
"blockHash": "0x5f58514bcb3b216908f0aff6ced44666c3aa250df06093150ac850a7a7850f3c",
66
"blockNumber": "0x6",
77
"contractAddress": null,
88
"cumulativeGasUsed": "0x5208",
9-
"effectiveGasPrice": "0x1b09d63b",
9+
"effectiveGasPrice": "0x1b0a08c4",
1010
"from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
1111
"gasUsed": "0x5208",
1212
"logs": [],
1313
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
1414
"status": "0x1",
1515
"to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e",
16-
"transactionHash": "0xb51ee3d2a89ba5d5623c73133c8d7a6ba9fb41194c17f4302c21b30994a1180f",
16+
"transactionHash": "0x80348f994fb5f3b05bd2e5f58bbdc73485e449c028612a2c0680f9ac6ff70add",
1717
"transactionIndex": "0x0",
1818
"type": "0x3"
1919
}
20-
]
20+
]

0 commit comments

Comments
 (0)