Skip to content

Commit c39cbc1

Browse files
core: implement BLOBBASEFEE opcode (0x4a) (#28098)
Implements "EIP-7516: BLOBBASEFEE opcode" for cancun, as per spec: https://eips.ethereum.org/EIPS/eip-7516
1 parent 7b6ff52 commit c39cbc1

File tree

12 files changed

+78
-42
lines changed

12 files changed

+78
-42
lines changed

cmd/evm/internal/t8ntool/execution.go

+9-7
Original file line numberDiff line numberDiff line change
@@ -163,17 +163,19 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
163163
rnd := common.BigToHash(pre.Env.Random)
164164
vmContext.Random = &rnd
165165
}
166-
// If excessBlobGas is defined, add it to the vmContext.
166+
// Calculate the BlobBaseFee
167+
var excessBlobGas uint64
167168
if pre.Env.ExcessBlobGas != nil {
168-
vmContext.ExcessBlobGas = pre.Env.ExcessBlobGas
169+
excessBlobGas := *pre.Env.ExcessBlobGas
170+
vmContext.BlobBaseFee = eip4844.CalcBlobFee(excessBlobGas)
169171
} else {
170172
// If it is not explicitly defined, but we have the parent values, we try
171173
// to calculate it ourselves.
172174
parentExcessBlobGas := pre.Env.ParentExcessBlobGas
173175
parentBlobGasUsed := pre.Env.ParentBlobGasUsed
174176
if parentExcessBlobGas != nil && parentBlobGasUsed != nil {
175-
excessBlobGas := eip4844.CalcExcessBlobGas(*parentExcessBlobGas, *parentBlobGasUsed)
176-
vmContext.ExcessBlobGas = &excessBlobGas
177+
excessBlobGas = eip4844.CalcExcessBlobGas(*parentExcessBlobGas, *parentBlobGasUsed)
178+
vmContext.BlobBaseFee = eip4844.CalcBlobFee(excessBlobGas)
177179
}
178180
}
179181
// If DAO is supported/enabled, we need to handle it here. In geth 'proper', it's
@@ -189,7 +191,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
189191
}
190192
var blobGasUsed uint64
191193
for i, tx := range txs {
192-
if tx.Type() == types.BlobTxType && vmContext.ExcessBlobGas == nil {
194+
if tx.Type() == types.BlobTxType && vmContext.BlobBaseFee == nil {
193195
errMsg := "blob tx used but field env.ExcessBlobGas missing"
194196
log.Warn("rejected tx", "index", i, "hash", tx.Hash(), "error", errMsg)
195197
rejectedTxs = append(rejectedTxs, &rejectedTx{i, errMsg})
@@ -322,8 +324,8 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
322324
h := types.DeriveSha(types.Withdrawals(pre.Env.Withdrawals), trie.NewStackTrie(nil))
323325
execRs.WithdrawalsRoot = &h
324326
}
325-
if vmContext.ExcessBlobGas != nil {
326-
execRs.CurrentExcessBlobGas = (*math.HexOrDecimal64)(vmContext.ExcessBlobGas)
327+
if vmContext.BlobBaseFee != nil {
328+
execRs.CurrentExcessBlobGas = (*math.HexOrDecimal64)(&excessBlobGas)
327329
execRs.CurrentBlobGasUsed = (*math.HexOrDecimal64)(&blobGasUsed)
328330
}
329331
// Re-create statedb instance with new root upon the updated database

cmd/evm/runner.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ func runCmd(ctx *cli.Context) error {
123123
sender = common.BytesToAddress([]byte("sender"))
124124
receiver = common.BytesToAddress([]byte("receiver"))
125125
preimages = ctx.Bool(DumpFlag.Name)
126-
blobHashes []common.Hash // TODO (MariusVanDerWijden) implement blob hashes in state tests
126+
blobHashes []common.Hash // TODO (MariusVanDerWijden) implement blob hashes in state tests
127+
blobBaseFee = new(big.Int) // TODO (MariusVanDerWijden) implement blob fee in state tests
127128
)
128129
if ctx.Bool(MachineFlag.Name) {
129130
tracer = logger.NewJSONLogger(logconfig, os.Stdout)
@@ -221,6 +222,7 @@ func runCmd(ctx *cli.Context) error {
221222
Coinbase: genesisConfig.Coinbase,
222223
BlockNumber: new(big.Int).SetUint64(genesisConfig.Number),
223224
BlobHashes: blobHashes,
225+
BlobBaseFee: blobBaseFee,
224226
EVMConfig: vm.Config{
225227
Tracer: tracer,
226228
},

core/evm.go

+16-11
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121

2222
"github.com/ethereum/go-ethereum/common"
2323
"github.com/ethereum/go-ethereum/consensus"
24+
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
2425
"github.com/ethereum/go-ethereum/core/types"
2526
"github.com/ethereum/go-ethereum/core/vm"
2627
)
@@ -40,6 +41,7 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
4041
var (
4142
beneficiary common.Address
4243
baseFee *big.Int
44+
blobBaseFee *big.Int
4345
random *common.Hash
4446
)
4547

@@ -52,21 +54,24 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
5254
if header.BaseFee != nil {
5355
baseFee = new(big.Int).Set(header.BaseFee)
5456
}
57+
if header.ExcessBlobGas != nil {
58+
blobBaseFee = eip4844.CalcBlobFee(*header.ExcessBlobGas)
59+
}
5560
if header.Difficulty.Cmp(common.Big0) == 0 {
5661
random = &header.MixDigest
5762
}
5863
return vm.BlockContext{
59-
CanTransfer: CanTransfer,
60-
Transfer: Transfer,
61-
GetHash: GetHashFn(header, chain),
62-
Coinbase: beneficiary,
63-
BlockNumber: new(big.Int).Set(header.Number),
64-
Time: header.Time,
65-
Difficulty: new(big.Int).Set(header.Difficulty),
66-
BaseFee: baseFee,
67-
GasLimit: header.GasLimit,
68-
Random: random,
69-
ExcessBlobGas: header.ExcessBlobGas,
64+
CanTransfer: CanTransfer,
65+
Transfer: Transfer,
66+
GetHash: GetHashFn(header, chain),
67+
Coinbase: beneficiary,
68+
BlockNumber: new(big.Int).Set(header.Number),
69+
Time: header.Time,
70+
Difficulty: new(big.Int).Set(header.Difficulty),
71+
BaseFee: baseFee,
72+
BlobBaseFee: blobBaseFee,
73+
GasLimit: header.GasLimit,
74+
Random: random,
7075
}
7176
}
7277

core/state_processor.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import (
2424
"github.com/ethereum/go-ethereum/common"
2525
"github.com/ethereum/go-ethereum/consensus"
2626
"github.com/ethereum/go-ethereum/consensus/misc"
27-
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
2827
"github.com/ethereum/go-ethereum/core/state"
2928
"github.com/ethereum/go-ethereum/core/types"
3029
"github.com/ethereum/go-ethereum/core/vm"
@@ -138,7 +137,7 @@ func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, sta
138137

139138
if tx.Type() == types.BlobTxType {
140139
receipt.BlobGasUsed = uint64(len(tx.BlobHashes()) * params.BlobTxBlobGasPerBlob)
141-
receipt.BlobGasPrice = eip4844.CalcBlobFee(*evm.Context.ExcessBlobGas)
140+
receipt.BlobGasPrice = evm.Context.BlobBaseFee
142141
}
143142

144143
// If the transaction created a contract, store the creation address in the receipt.

core/state_transition.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import (
2424

2525
"github.com/ethereum/go-ethereum/common"
2626
cmath "github.com/ethereum/go-ethereum/common/math"
27-
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
2827
"github.com/ethereum/go-ethereum/core/types"
2928
"github.com/ethereum/go-ethereum/core/vm"
3029
"github.com/ethereum/go-ethereum/params"
@@ -248,7 +247,7 @@ func (st *StateTransition) buyGas() error {
248247
balanceCheck.Add(balanceCheck, blobBalanceCheck)
249248
// Pay for blobGasUsed * actual blob fee
250249
blobFee := new(big.Int).SetUint64(blobGas)
251-
blobFee.Mul(blobFee, eip4844.CalcBlobFee(*st.evm.Context.ExcessBlobGas))
250+
blobFee.Mul(blobFee, st.evm.Context.BlobBaseFee)
252251
mgval.Add(mgval, blobFee)
253252
}
254253
}
@@ -329,7 +328,7 @@ func (st *StateTransition) preCheck() error {
329328
if st.evm.ChainConfig().IsCancun(st.evm.Context.BlockNumber, st.evm.Context.Time) {
330329
if st.blobGasUsed() > 0 {
331330
// Check that the user is paying at least the current blob fee
332-
blobFee := eip4844.CalcBlobFee(*st.evm.Context.ExcessBlobGas)
331+
blobFee := st.evm.Context.BlobBaseFee
333332
if st.msg.BlobGasFeeCap.Cmp(blobFee) < 0 {
334333
return fmt.Errorf("%w: address %v have %v want %v", ErrBlobFeeCapTooLow, st.msg.From.Hex(), st.msg.BlobGasFeeCap, blobFee)
335334
}

core/vm/eips.go

+18-2
Original file line numberDiff line numberDiff line change
@@ -282,9 +282,15 @@ func opBlobHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
282282
return nil, nil
283283
}
284284

285-
// enable4844 applies EIP-4844 (DATAHASH opcode)
285+
// opBlobBaseFee implements BLOBBASEFEE opcode
286+
func opBlobBaseFee(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
287+
blobBaseFee, _ := uint256.FromBig(interpreter.evm.Context.BlobBaseFee)
288+
scope.Stack.push(blobBaseFee)
289+
return nil, nil
290+
}
291+
292+
// enable4844 applies EIP-4844 (BLOBHASH opcode)
286293
func enable4844(jt *JumpTable) {
287-
// New opcode
288294
jt[BLOBHASH] = &operation{
289295
execute: opBlobHash,
290296
constantGas: GasFastestStep,
@@ -293,6 +299,16 @@ func enable4844(jt *JumpTable) {
293299
}
294300
}
295301

302+
// enable7516 applies EIP-7516 (BLOBBASEFEE opcode)
303+
func enable7516(jt *JumpTable) {
304+
jt[BLOBBASEFEE] = &operation{
305+
execute: opBlobBaseFee,
306+
constantGas: GasQuickStep,
307+
minStack: minStack(0, 1),
308+
maxStack: maxStack(0, 1),
309+
}
310+
}
311+
296312
// enable6780 applies EIP-6780 (deactivate SELFDESTRUCT)
297313
func enable6780(jt *JumpTable) {
298314
jt[SELFDESTRUCT] = &operation{

core/vm/evm.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,14 @@ type BlockContext struct {
6767
GetHash GetHashFunc
6868

6969
// Block information
70-
Coinbase common.Address // Provides information for COINBASE
71-
GasLimit uint64 // Provides information for GASLIMIT
72-
BlockNumber *big.Int // Provides information for NUMBER
73-
Time uint64 // Provides information for TIME
74-
Difficulty *big.Int // Provides information for DIFFICULTY
75-
BaseFee *big.Int // Provides information for BASEFEE
76-
Random *common.Hash // Provides information for PREVRANDAO
77-
ExcessBlobGas *uint64 // ExcessBlobGas field in the header, needed to compute the data
70+
Coinbase common.Address // Provides information for COINBASE
71+
GasLimit uint64 // Provides information for GASLIMIT
72+
BlockNumber *big.Int // Provides information for NUMBER
73+
Time uint64 // Provides information for TIME
74+
Difficulty *big.Int // Provides information for DIFFICULTY
75+
BaseFee *big.Int // Provides information for BASEFEE
76+
BlobBaseFee *big.Int // Provides information for BLOBBASEFEE
77+
Random *common.Hash // Provides information for PREVRANDAO
7878
}
7979

8080
// TxContext provides the EVM with information about a transaction.

core/vm/jump_table.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ func validate(jt JumpTable) JumpTable {
8282

8383
func newCancunInstructionSet() JumpTable {
8484
instructionSet := newShanghaiInstructionSet()
85-
enable4844(&instructionSet) // EIP-4844 (DATAHASH opcode)
85+
enable4844(&instructionSet) // EIP-4844 (BLOBHASH opcode)
86+
enable7516(&instructionSet) // EIP-7516 (BLOBBASEFEE opcode)
8687
enable1153(&instructionSet) // EIP-1153 "Transient Storage"
8788
enable5656(&instructionSet) // EIP-5656 (MCOPY opcode)
8889
enable6780(&instructionSet) // EIP-6780 SELFDESTRUCT only in same transaction

core/vm/opcodes.go

+3
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ const (
101101
SELFBALANCE OpCode = 0x47
102102
BASEFEE OpCode = 0x48
103103
BLOBHASH OpCode = 0x49
104+
BLOBBASEFEE OpCode = 0x4a
104105
)
105106

106107
// 0x50 range - 'storage' and execution.
@@ -287,6 +288,7 @@ var opCodeToString = map[OpCode]string{
287288
SELFBALANCE: "SELFBALANCE",
288289
BASEFEE: "BASEFEE",
289290
BLOBHASH: "BLOBHASH",
291+
BLOBBASEFEE: "BLOBBASEFEE",
290292

291293
// 0x50 range - 'storage' and execution.
292294
POP: "POP",
@@ -444,6 +446,7 @@ var stringToOp = map[string]OpCode{
444446
"CHAINID": CHAINID,
445447
"BASEFEE": BASEFEE,
446448
"BLOBHASH": BLOBHASH,
449+
"BLOBBASEFEE": BLOBBASEFEE,
447450
"DELEGATECALL": DELEGATECALL,
448451
"STATICCALL": STATICCALL,
449452
"CODESIZE": CODESIZE,

core/vm/runtime/env.go

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ func NewEnv(cfg *Config) *vm.EVM {
3737
Difficulty: cfg.Difficulty,
3838
GasLimit: cfg.GasLimit,
3939
BaseFee: cfg.BaseFee,
40+
BlobBaseFee: cfg.BlobBaseFee,
4041
Random: cfg.Random,
4142
}
4243

core/vm/runtime/runtime.go

+4
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ type Config struct {
4444
Debug bool
4545
EVMConfig vm.Config
4646
BaseFee *big.Int
47+
BlobBaseFee *big.Int
4748
BlobHashes []common.Hash
4849
Random *common.Hash
4950

@@ -95,6 +96,9 @@ func setDefaults(cfg *Config) {
9596
if cfg.BaseFee == nil {
9697
cfg.BaseFee = big.NewInt(params.InitialBaseFee)
9798
}
99+
if cfg.BlobBaseFee == nil {
100+
cfg.BlobBaseFee = new(big.Int)
101+
}
98102
}
99103

100104
// Execute executes the code using the input as call data during the execution.

internal/ethapi/api.go

+11-7
Original file line numberDiff line numberDiff line change
@@ -991,13 +991,14 @@ func (diff *StateOverride) Apply(state *state.StateDB) error {
991991

992992
// BlockOverrides is a set of header fields to override.
993993
type BlockOverrides struct {
994-
Number *hexutil.Big
995-
Difficulty *hexutil.Big
996-
Time *hexutil.Uint64
997-
GasLimit *hexutil.Uint64
998-
Coinbase *common.Address
999-
Random *common.Hash
1000-
BaseFee *hexutil.Big
994+
Number *hexutil.Big
995+
Difficulty *hexutil.Big
996+
Time *hexutil.Uint64
997+
GasLimit *hexutil.Uint64
998+
Coinbase *common.Address
999+
Random *common.Hash
1000+
BaseFee *hexutil.Big
1001+
BlobBaseFee *hexutil.Big
10011002
}
10021003

10031004
// Apply overrides the given header fields into the given block context.
@@ -1026,6 +1027,9 @@ func (diff *BlockOverrides) Apply(blockCtx *vm.BlockContext) {
10261027
if diff.BaseFee != nil {
10271028
blockCtx.BaseFee = diff.BaseFee.ToInt()
10281029
}
1030+
if diff.BlobBaseFee != nil {
1031+
blockCtx.BlobBaseFee = diff.BlobBaseFee.ToInt()
1032+
}
10291033
}
10301034

10311035
// ChainContextBackend provides methods required to implement ChainContext.

0 commit comments

Comments
 (0)