forked from cerc-io/plugeth
core: implement BLOBBASEFEE opcode (0x4a) (#28098)
Implements "EIP-7516: BLOBBASEFEE opcode" for cancun, as per spec: https://eips.ethereum.org/EIPS/eip-7516
This commit is contained in:
parent
7b6ff527d5
commit
c39cbc1a78
@ -163,17 +163,19 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||||||
rnd := common.BigToHash(pre.Env.Random)
|
rnd := common.BigToHash(pre.Env.Random)
|
||||||
vmContext.Random = &rnd
|
vmContext.Random = &rnd
|
||||||
}
|
}
|
||||||
// If excessBlobGas is defined, add it to the vmContext.
|
// Calculate the BlobBaseFee
|
||||||
|
var excessBlobGas uint64
|
||||||
if pre.Env.ExcessBlobGas != nil {
|
if pre.Env.ExcessBlobGas != nil {
|
||||||
vmContext.ExcessBlobGas = pre.Env.ExcessBlobGas
|
excessBlobGas := *pre.Env.ExcessBlobGas
|
||||||
|
vmContext.BlobBaseFee = eip4844.CalcBlobFee(excessBlobGas)
|
||||||
} else {
|
} else {
|
||||||
// If it is not explicitly defined, but we have the parent values, we try
|
// If it is not explicitly defined, but we have the parent values, we try
|
||||||
// to calculate it ourselves.
|
// to calculate it ourselves.
|
||||||
parentExcessBlobGas := pre.Env.ParentExcessBlobGas
|
parentExcessBlobGas := pre.Env.ParentExcessBlobGas
|
||||||
parentBlobGasUsed := pre.Env.ParentBlobGasUsed
|
parentBlobGasUsed := pre.Env.ParentBlobGasUsed
|
||||||
if parentExcessBlobGas != nil && parentBlobGasUsed != nil {
|
if parentExcessBlobGas != nil && parentBlobGasUsed != nil {
|
||||||
excessBlobGas := eip4844.CalcExcessBlobGas(*parentExcessBlobGas, *parentBlobGasUsed)
|
excessBlobGas = eip4844.CalcExcessBlobGas(*parentExcessBlobGas, *parentBlobGasUsed)
|
||||||
vmContext.ExcessBlobGas = &excessBlobGas
|
vmContext.BlobBaseFee = eip4844.CalcBlobFee(excessBlobGas)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If DAO is supported/enabled, we need to handle it here. In geth 'proper', it's
|
// 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,
|
|||||||
}
|
}
|
||||||
var blobGasUsed uint64
|
var blobGasUsed uint64
|
||||||
for i, tx := range txs {
|
for i, tx := range txs {
|
||||||
if tx.Type() == types.BlobTxType && vmContext.ExcessBlobGas == nil {
|
if tx.Type() == types.BlobTxType && vmContext.BlobBaseFee == nil {
|
||||||
errMsg := "blob tx used but field env.ExcessBlobGas missing"
|
errMsg := "blob tx used but field env.ExcessBlobGas missing"
|
||||||
log.Warn("rejected tx", "index", i, "hash", tx.Hash(), "error", errMsg)
|
log.Warn("rejected tx", "index", i, "hash", tx.Hash(), "error", errMsg)
|
||||||
rejectedTxs = append(rejectedTxs, &rejectedTx{i, errMsg})
|
rejectedTxs = append(rejectedTxs, &rejectedTx{i, errMsg})
|
||||||
@ -322,8 +324,8 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||||||
h := types.DeriveSha(types.Withdrawals(pre.Env.Withdrawals), trie.NewStackTrie(nil))
|
h := types.DeriveSha(types.Withdrawals(pre.Env.Withdrawals), trie.NewStackTrie(nil))
|
||||||
execRs.WithdrawalsRoot = &h
|
execRs.WithdrawalsRoot = &h
|
||||||
}
|
}
|
||||||
if vmContext.ExcessBlobGas != nil {
|
if vmContext.BlobBaseFee != nil {
|
||||||
execRs.CurrentExcessBlobGas = (*math.HexOrDecimal64)(vmContext.ExcessBlobGas)
|
execRs.CurrentExcessBlobGas = (*math.HexOrDecimal64)(&excessBlobGas)
|
||||||
execRs.CurrentBlobGasUsed = (*math.HexOrDecimal64)(&blobGasUsed)
|
execRs.CurrentBlobGasUsed = (*math.HexOrDecimal64)(&blobGasUsed)
|
||||||
}
|
}
|
||||||
// Re-create statedb instance with new root upon the updated database
|
// Re-create statedb instance with new root upon the updated database
|
||||||
|
@ -124,6 +124,7 @@ func runCmd(ctx *cli.Context) error {
|
|||||||
receiver = common.BytesToAddress([]byte("receiver"))
|
receiver = common.BytesToAddress([]byte("receiver"))
|
||||||
preimages = ctx.Bool(DumpFlag.Name)
|
preimages = ctx.Bool(DumpFlag.Name)
|
||||||
blobHashes []common.Hash // TODO (MariusVanDerWijden) implement blob hashes in state tests
|
blobHashes []common.Hash // TODO (MariusVanDerWijden) implement blob hashes in state tests
|
||||||
|
blobBaseFee = new(big.Int) // TODO (MariusVanDerWijden) implement blob fee in state tests
|
||||||
)
|
)
|
||||||
if ctx.Bool(MachineFlag.Name) {
|
if ctx.Bool(MachineFlag.Name) {
|
||||||
tracer = logger.NewJSONLogger(logconfig, os.Stdout)
|
tracer = logger.NewJSONLogger(logconfig, os.Stdout)
|
||||||
@ -221,6 +222,7 @@ func runCmd(ctx *cli.Context) error {
|
|||||||
Coinbase: genesisConfig.Coinbase,
|
Coinbase: genesisConfig.Coinbase,
|
||||||
BlockNumber: new(big.Int).SetUint64(genesisConfig.Number),
|
BlockNumber: new(big.Int).SetUint64(genesisConfig.Number),
|
||||||
BlobHashes: blobHashes,
|
BlobHashes: blobHashes,
|
||||||
|
BlobBaseFee: blobBaseFee,
|
||||||
EVMConfig: vm.Config{
|
EVMConfig: vm.Config{
|
||||||
Tracer: tracer,
|
Tracer: tracer,
|
||||||
},
|
},
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
)
|
)
|
||||||
@ -40,6 +41,7 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
|
|||||||
var (
|
var (
|
||||||
beneficiary common.Address
|
beneficiary common.Address
|
||||||
baseFee *big.Int
|
baseFee *big.Int
|
||||||
|
blobBaseFee *big.Int
|
||||||
random *common.Hash
|
random *common.Hash
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -52,6 +54,9 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
|
|||||||
if header.BaseFee != nil {
|
if header.BaseFee != nil {
|
||||||
baseFee = new(big.Int).Set(header.BaseFee)
|
baseFee = new(big.Int).Set(header.BaseFee)
|
||||||
}
|
}
|
||||||
|
if header.ExcessBlobGas != nil {
|
||||||
|
blobBaseFee = eip4844.CalcBlobFee(*header.ExcessBlobGas)
|
||||||
|
}
|
||||||
if header.Difficulty.Cmp(common.Big0) == 0 {
|
if header.Difficulty.Cmp(common.Big0) == 0 {
|
||||||
random = &header.MixDigest
|
random = &header.MixDigest
|
||||||
}
|
}
|
||||||
@ -64,9 +69,9 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
|
|||||||
Time: header.Time,
|
Time: header.Time,
|
||||||
Difficulty: new(big.Int).Set(header.Difficulty),
|
Difficulty: new(big.Int).Set(header.Difficulty),
|
||||||
BaseFee: baseFee,
|
BaseFee: baseFee,
|
||||||
|
BlobBaseFee: blobBaseFee,
|
||||||
GasLimit: header.GasLimit,
|
GasLimit: header.GasLimit,
|
||||||
Random: random,
|
Random: random,
|
||||||
ExcessBlobGas: header.ExcessBlobGas,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc"
|
"github.com/ethereum/go-ethereum/consensus/misc"
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
|
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
@ -138,7 +137,7 @@ func applyTransaction(msg *Message, config *params.ChainConfig, gp *GasPool, sta
|
|||||||
|
|
||||||
if tx.Type() == types.BlobTxType {
|
if tx.Type() == types.BlobTxType {
|
||||||
receipt.BlobGasUsed = uint64(len(tx.BlobHashes()) * params.BlobTxBlobGasPerBlob)
|
receipt.BlobGasUsed = uint64(len(tx.BlobHashes()) * params.BlobTxBlobGasPerBlob)
|
||||||
receipt.BlobGasPrice = eip4844.CalcBlobFee(*evm.Context.ExcessBlobGas)
|
receipt.BlobGasPrice = evm.Context.BlobBaseFee
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the transaction created a contract, store the creation address in the receipt.
|
// If the transaction created a contract, store the creation address in the receipt.
|
||||||
|
@ -24,7 +24,6 @@ import (
|
|||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
cmath "github.com/ethereum/go-ethereum/common/math"
|
cmath "github.com/ethereum/go-ethereum/common/math"
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
@ -248,7 +247,7 @@ func (st *StateTransition) buyGas() error {
|
|||||||
balanceCheck.Add(balanceCheck, blobBalanceCheck)
|
balanceCheck.Add(balanceCheck, blobBalanceCheck)
|
||||||
// Pay for blobGasUsed * actual blob fee
|
// Pay for blobGasUsed * actual blob fee
|
||||||
blobFee := new(big.Int).SetUint64(blobGas)
|
blobFee := new(big.Int).SetUint64(blobGas)
|
||||||
blobFee.Mul(blobFee, eip4844.CalcBlobFee(*st.evm.Context.ExcessBlobGas))
|
blobFee.Mul(blobFee, st.evm.Context.BlobBaseFee)
|
||||||
mgval.Add(mgval, blobFee)
|
mgval.Add(mgval, blobFee)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -329,7 +328,7 @@ func (st *StateTransition) preCheck() error {
|
|||||||
if st.evm.ChainConfig().IsCancun(st.evm.Context.BlockNumber, st.evm.Context.Time) {
|
if st.evm.ChainConfig().IsCancun(st.evm.Context.BlockNumber, st.evm.Context.Time) {
|
||||||
if st.blobGasUsed() > 0 {
|
if st.blobGasUsed() > 0 {
|
||||||
// Check that the user is paying at least the current blob fee
|
// Check that the user is paying at least the current blob fee
|
||||||
blobFee := eip4844.CalcBlobFee(*st.evm.Context.ExcessBlobGas)
|
blobFee := st.evm.Context.BlobBaseFee
|
||||||
if st.msg.BlobGasFeeCap.Cmp(blobFee) < 0 {
|
if st.msg.BlobGasFeeCap.Cmp(blobFee) < 0 {
|
||||||
return fmt.Errorf("%w: address %v have %v want %v", ErrBlobFeeCapTooLow, st.msg.From.Hex(), st.msg.BlobGasFeeCap, blobFee)
|
return fmt.Errorf("%w: address %v have %v want %v", ErrBlobFeeCapTooLow, st.msg.From.Hex(), st.msg.BlobGasFeeCap, blobFee)
|
||||||
}
|
}
|
||||||
|
@ -282,9 +282,15 @@ func opBlobHash(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// enable4844 applies EIP-4844 (DATAHASH opcode)
|
// opBlobBaseFee implements BLOBBASEFEE opcode
|
||||||
|
func opBlobBaseFee(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
blobBaseFee, _ := uint256.FromBig(interpreter.evm.Context.BlobBaseFee)
|
||||||
|
scope.Stack.push(blobBaseFee)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// enable4844 applies EIP-4844 (BLOBHASH opcode)
|
||||||
func enable4844(jt *JumpTable) {
|
func enable4844(jt *JumpTable) {
|
||||||
// New opcode
|
|
||||||
jt[BLOBHASH] = &operation{
|
jt[BLOBHASH] = &operation{
|
||||||
execute: opBlobHash,
|
execute: opBlobHash,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
@ -293,6 +299,16 @@ func enable4844(jt *JumpTable) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// enable7516 applies EIP-7516 (BLOBBASEFEE opcode)
|
||||||
|
func enable7516(jt *JumpTable) {
|
||||||
|
jt[BLOBBASEFEE] = &operation{
|
||||||
|
execute: opBlobBaseFee,
|
||||||
|
constantGas: GasQuickStep,
|
||||||
|
minStack: minStack(0, 1),
|
||||||
|
maxStack: maxStack(0, 1),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// enable6780 applies EIP-6780 (deactivate SELFDESTRUCT)
|
// enable6780 applies EIP-6780 (deactivate SELFDESTRUCT)
|
||||||
func enable6780(jt *JumpTable) {
|
func enable6780(jt *JumpTable) {
|
||||||
jt[SELFDESTRUCT] = &operation{
|
jt[SELFDESTRUCT] = &operation{
|
||||||
|
@ -73,8 +73,8 @@ type BlockContext struct {
|
|||||||
Time uint64 // Provides information for TIME
|
Time uint64 // Provides information for TIME
|
||||||
Difficulty *big.Int // Provides information for DIFFICULTY
|
Difficulty *big.Int // Provides information for DIFFICULTY
|
||||||
BaseFee *big.Int // Provides information for BASEFEE
|
BaseFee *big.Int // Provides information for BASEFEE
|
||||||
|
BlobBaseFee *big.Int // Provides information for BLOBBASEFEE
|
||||||
Random *common.Hash // Provides information for PREVRANDAO
|
Random *common.Hash // Provides information for PREVRANDAO
|
||||||
ExcessBlobGas *uint64 // ExcessBlobGas field in the header, needed to compute the data
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TxContext provides the EVM with information about a transaction.
|
// TxContext provides the EVM with information about a transaction.
|
||||||
|
@ -82,7 +82,8 @@ func validate(jt JumpTable) JumpTable {
|
|||||||
|
|
||||||
func newCancunInstructionSet() JumpTable {
|
func newCancunInstructionSet() JumpTable {
|
||||||
instructionSet := newShanghaiInstructionSet()
|
instructionSet := newShanghaiInstructionSet()
|
||||||
enable4844(&instructionSet) // EIP-4844 (DATAHASH opcode)
|
enable4844(&instructionSet) // EIP-4844 (BLOBHASH opcode)
|
||||||
|
enable7516(&instructionSet) // EIP-7516 (BLOBBASEFEE opcode)
|
||||||
enable1153(&instructionSet) // EIP-1153 "Transient Storage"
|
enable1153(&instructionSet) // EIP-1153 "Transient Storage"
|
||||||
enable5656(&instructionSet) // EIP-5656 (MCOPY opcode)
|
enable5656(&instructionSet) // EIP-5656 (MCOPY opcode)
|
||||||
enable6780(&instructionSet) // EIP-6780 SELFDESTRUCT only in same transaction
|
enable6780(&instructionSet) // EIP-6780 SELFDESTRUCT only in same transaction
|
||||||
|
@ -101,6 +101,7 @@ const (
|
|||||||
SELFBALANCE OpCode = 0x47
|
SELFBALANCE OpCode = 0x47
|
||||||
BASEFEE OpCode = 0x48
|
BASEFEE OpCode = 0x48
|
||||||
BLOBHASH OpCode = 0x49
|
BLOBHASH OpCode = 0x49
|
||||||
|
BLOBBASEFEE OpCode = 0x4a
|
||||||
)
|
)
|
||||||
|
|
||||||
// 0x50 range - 'storage' and execution.
|
// 0x50 range - 'storage' and execution.
|
||||||
@ -287,6 +288,7 @@ var opCodeToString = map[OpCode]string{
|
|||||||
SELFBALANCE: "SELFBALANCE",
|
SELFBALANCE: "SELFBALANCE",
|
||||||
BASEFEE: "BASEFEE",
|
BASEFEE: "BASEFEE",
|
||||||
BLOBHASH: "BLOBHASH",
|
BLOBHASH: "BLOBHASH",
|
||||||
|
BLOBBASEFEE: "BLOBBASEFEE",
|
||||||
|
|
||||||
// 0x50 range - 'storage' and execution.
|
// 0x50 range - 'storage' and execution.
|
||||||
POP: "POP",
|
POP: "POP",
|
||||||
@ -444,6 +446,7 @@ var stringToOp = map[string]OpCode{
|
|||||||
"CHAINID": CHAINID,
|
"CHAINID": CHAINID,
|
||||||
"BASEFEE": BASEFEE,
|
"BASEFEE": BASEFEE,
|
||||||
"BLOBHASH": BLOBHASH,
|
"BLOBHASH": BLOBHASH,
|
||||||
|
"BLOBBASEFEE": BLOBBASEFEE,
|
||||||
"DELEGATECALL": DELEGATECALL,
|
"DELEGATECALL": DELEGATECALL,
|
||||||
"STATICCALL": STATICCALL,
|
"STATICCALL": STATICCALL,
|
||||||
"CODESIZE": CODESIZE,
|
"CODESIZE": CODESIZE,
|
||||||
|
@ -37,6 +37,7 @@ func NewEnv(cfg *Config) *vm.EVM {
|
|||||||
Difficulty: cfg.Difficulty,
|
Difficulty: cfg.Difficulty,
|
||||||
GasLimit: cfg.GasLimit,
|
GasLimit: cfg.GasLimit,
|
||||||
BaseFee: cfg.BaseFee,
|
BaseFee: cfg.BaseFee,
|
||||||
|
BlobBaseFee: cfg.BlobBaseFee,
|
||||||
Random: cfg.Random,
|
Random: cfg.Random,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ type Config struct {
|
|||||||
Debug bool
|
Debug bool
|
||||||
EVMConfig vm.Config
|
EVMConfig vm.Config
|
||||||
BaseFee *big.Int
|
BaseFee *big.Int
|
||||||
|
BlobBaseFee *big.Int
|
||||||
BlobHashes []common.Hash
|
BlobHashes []common.Hash
|
||||||
Random *common.Hash
|
Random *common.Hash
|
||||||
|
|
||||||
@ -95,6 +96,9 @@ func setDefaults(cfg *Config) {
|
|||||||
if cfg.BaseFee == nil {
|
if cfg.BaseFee == nil {
|
||||||
cfg.BaseFee = big.NewInt(params.InitialBaseFee)
|
cfg.BaseFee = big.NewInt(params.InitialBaseFee)
|
||||||
}
|
}
|
||||||
|
if cfg.BlobBaseFee == nil {
|
||||||
|
cfg.BlobBaseFee = new(big.Int)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute executes the code using the input as call data during the execution.
|
// Execute executes the code using the input as call data during the execution.
|
||||||
|
@ -998,6 +998,7 @@ type BlockOverrides struct {
|
|||||||
Coinbase *common.Address
|
Coinbase *common.Address
|
||||||
Random *common.Hash
|
Random *common.Hash
|
||||||
BaseFee *hexutil.Big
|
BaseFee *hexutil.Big
|
||||||
|
BlobBaseFee *hexutil.Big
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply overrides the given header fields into the given block context.
|
// Apply overrides the given header fields into the given block context.
|
||||||
@ -1026,6 +1027,9 @@ func (diff *BlockOverrides) Apply(blockCtx *vm.BlockContext) {
|
|||||||
if diff.BaseFee != nil {
|
if diff.BaseFee != nil {
|
||||||
blockCtx.BaseFee = diff.BaseFee.ToInt()
|
blockCtx.BaseFee = diff.BaseFee.ToInt()
|
||||||
}
|
}
|
||||||
|
if diff.BlobBaseFee != nil {
|
||||||
|
blockCtx.BlobBaseFee = diff.BlobBaseFee.ToInt()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChainContextBackend provides methods required to implement ChainContext.
|
// ChainContextBackend provides methods required to implement ChainContext.
|
||||||
|
Loading…
Reference in New Issue
Block a user