core/vm: implement eip-7843

This commit is contained in:
MariusVanDerWijden 2026-01-12 21:55:52 +01:00 committed by Jared Wasinger
parent 4c36eaf532
commit f7ce5467e3
9 changed files with 71 additions and 8 deletions

View file

@ -36,6 +36,7 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
BlockAccessList *bal.BlockAccessList `json:"blockAccessList"`
SlotNumber *hexutil.Uint64 `json:"slotNumber"`
}
var enc ExecutableData
enc.ParentHash = e.ParentHash
@ -61,6 +62,7 @@ func (e ExecutableData) MarshalJSON() ([]byte, error) {
enc.BlobGasUsed = (*hexutil.Uint64)(e.BlobGasUsed)
enc.ExcessBlobGas = (*hexutil.Uint64)(e.ExcessBlobGas)
enc.BlockAccessList = e.BlockAccessList
enc.SlotNumber = (*hexutil.Uint64)(e.SlotNumber)
return json.Marshal(&enc)
}
@ -85,6 +87,7 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error {
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
BlockAccessList *bal.BlockAccessList `json:"blockAccessList"`
SlotNumber *hexutil.Uint64 `json:"slotNumber"`
}
var dec ExecutableData
if err := json.Unmarshal(input, &dec); err != nil {
@ -161,5 +164,8 @@ func (e *ExecutableData) UnmarshalJSON(input []byte) error {
if dec.BlockAccessList != nil {
e.BlockAccessList = dec.BlockAccessList
}
if dec.SlotNumber != nil {
e.SlotNumber = (*uint64)(dec.SlotNumber)
}
return nil
}

View file

@ -93,6 +93,7 @@ type ExecutableData struct {
BlobGasUsed *uint64 `json:"blobGasUsed"`
ExcessBlobGas *uint64 `json:"excessBlobGas"`
BlockAccessList *bal.BlockAccessList `json:"blockAccessList"`
SlotNumber *uint64 `json:"slotNumber"`
}
// JSON type overrides for executableData.
@ -107,6 +108,7 @@ type executableDataMarshaling struct {
Transactions []hexutil.Bytes
BlobGasUsed *hexutil.Uint64
ExcessBlobGas *hexutil.Uint64
SlotNumber *hexutil.Uint64
}
// StatelessPayloadStatusV1 is the result of a stateless payload execution.
@ -302,7 +304,6 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
balHash := data.BlockAccessList.Hash()
blockAccessListHash = &balHash
}
header := &types.Header{
ParentHash: data.ParentHash,
UncleHash: types.EmptyUncleHash,
@ -325,6 +326,7 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
ParentBeaconRoot: beaconRoot,
RequestsHash: requestsHash,
BlockAccessListHash: blockAccessListHash,
SlotNumber: data.SlotNumber,
}
return types.NewBlockWithHeader(header).WithBody(body), nil
}
@ -350,6 +352,7 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.
Withdrawals: block.Withdrawals(),
BlobGasUsed: block.BlobGasUsed(),
ExcessBlobGas: block.ExcessBlobGas(),
SlotNumber: block.SlotNumber(),
BlockAccessList: block.Body().AccessList,
}

View file

@ -44,6 +44,7 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
baseFee *big.Int
blobBaseFee *big.Int
random *common.Hash
slotnum uint64
)
// If we don't have an explicit author (i.e. not mining), extract from the header
@ -61,6 +62,10 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
if header.Difficulty.Sign() == 0 {
random = &header.MixDigest
}
if header.SlotNumber != nil {
slotnum = *header.SlotNumber
}
return vm.BlockContext{
CanTransfer: CanTransfer,
Transfer: Transfer,
@ -73,6 +78,7 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common
BlobBaseFee: blobBaseFee,
GasLimit: header.GasLimit,
Random: random,
Slotnum: slotnum,
}
}

View file

@ -103,6 +103,9 @@ type Header struct {
// BlockAccessListHash was added by EIP-7928 and is ignored in legacy headers.
BlockAccessListHash *common.Hash `json:"balHash" rlp:"optional"`
// SlotNumber was added by EIP-7843 and is ignored in legacy headers.
SlotNumber *uint64 `json:"slotNumber" rlp:"optional"`
}
// field type overrides for gencodec
@ -117,6 +120,7 @@ type headerMarshaling struct {
Hash common.Hash `json:"hash"` // adds call to Hash() in MarshalJSON
BlobGasUsed *hexutil.Uint64
ExcessBlobGas *hexutil.Uint64
SlotNumber *hexutil.Uint64
}
// Hash returns the block hash of the header, which is simply the keccak256 hash of its
@ -431,6 +435,15 @@ func (b *Block) BlobGasUsed() *uint64 {
return blobGasUsed
}
func (b *Block) SlotNumber() *uint64 {
var slotNum *uint64
if b.header.SlotNumber != nil {
slotNum = new(uint64)
*slotNum = *b.header.SlotNumber
}
return slotNum
}
// Size returns the true RLP encoded storage size of the block, either by encoding
// and returning it, or returning a previously cached value.
func (b *Block) Size() uint64 {

View file

@ -38,6 +38,7 @@ func (h Header) MarshalJSON() ([]byte, error) {
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
BlockAccessListHash *common.Hash `json:"balHash" rlp:"optional"`
SlotNumber *hexutil.Uint64 `json:"slotNumber" rlp:"optional"`
Hash common.Hash `json:"hash"`
}
var enc Header
@ -63,6 +64,7 @@ func (h Header) MarshalJSON() ([]byte, error) {
enc.ParentBeaconRoot = h.ParentBeaconRoot
enc.RequestsHash = h.RequestsHash
enc.BlockAccessListHash = h.BlockAccessListHash
enc.SlotNumber = (*hexutil.Uint64)(h.SlotNumber)
enc.Hash = h.Hash()
return json.Marshal(&enc)
}
@ -92,6 +94,7 @@ func (h *Header) UnmarshalJSON(input []byte) error {
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
BlockAccessListHash *common.Hash `json:"balHash" rlp:"optional"`
SlotNumber *hexutil.Uint64 `json:"slotNumber" rlp:"optional"`
}
var dec Header
if err := json.Unmarshal(input, &dec); err != nil {
@ -175,5 +178,8 @@ func (h *Header) UnmarshalJSON(input []byte) error {
if dec.BlockAccessListHash != nil {
h.BlockAccessListHash = dec.BlockAccessListHash
}
if dec.SlotNumber != nil {
h.SlotNumber = (*uint64)(dec.SlotNumber)
}
return nil
}

View file

@ -44,7 +44,8 @@ func (obj *Header) EncodeRLP(_w io.Writer) error {
_tmp5 := obj.ParentBeaconRoot != nil
_tmp6 := obj.RequestsHash != nil
_tmp7 := obj.BlockAccessListHash != nil
if _tmp1 || _tmp2 || _tmp3 || _tmp4 || _tmp5 || _tmp6 || _tmp7 {
_tmp8 := obj.SlotNumber != nil
if _tmp1 || _tmp2 || _tmp3 || _tmp4 || _tmp5 || _tmp6 || _tmp7 || _tmp8 {
if obj.BaseFee == nil {
w.Write(rlp.EmptyString)
} else {
@ -54,48 +55,55 @@ func (obj *Header) EncodeRLP(_w io.Writer) error {
w.WriteBigInt(obj.BaseFee)
}
}
if _tmp2 || _tmp3 || _tmp4 || _tmp5 || _tmp6 || _tmp7 {
if _tmp2 || _tmp3 || _tmp4 || _tmp5 || _tmp6 || _tmp7 || _tmp8 {
if obj.WithdrawalsHash == nil {
w.Write([]byte{0x80})
} else {
w.WriteBytes(obj.WithdrawalsHash[:])
}
}
if _tmp3 || _tmp4 || _tmp5 || _tmp6 || _tmp7 {
if _tmp3 || _tmp4 || _tmp5 || _tmp6 || _tmp7 || _tmp8 {
if obj.BlobGasUsed == nil {
w.Write([]byte{0x80})
} else {
w.WriteUint64((*obj.BlobGasUsed))
}
}
if _tmp4 || _tmp5 || _tmp6 || _tmp7 {
if _tmp4 || _tmp5 || _tmp6 || _tmp7 || _tmp8 {
if obj.ExcessBlobGas == nil {
w.Write([]byte{0x80})
} else {
w.WriteUint64((*obj.ExcessBlobGas))
}
}
if _tmp5 || _tmp6 || _tmp7 {
if _tmp5 || _tmp6 || _tmp7 || _tmp8 {
if obj.ParentBeaconRoot == nil {
w.Write([]byte{0x80})
} else {
w.WriteBytes(obj.ParentBeaconRoot[:])
}
}
if _tmp6 || _tmp7 {
if _tmp6 || _tmp7 || _tmp8 {
if obj.RequestsHash == nil {
w.Write([]byte{0x80})
} else {
w.WriteBytes(obj.RequestsHash[:])
}
}
if _tmp7 {
if _tmp7 || _tmp8 {
if obj.BlockAccessListHash == nil {
w.Write([]byte{0x80})
} else {
w.WriteBytes(obj.BlockAccessListHash[:])
}
}
if _tmp8 {
if obj.SlotNumber == nil {
w.Write([]byte{0x80})
} else {
w.WriteUint64((*obj.SlotNumber))
}
}
w.ListEnd(_tmp0)
return w.Flush()
}

View file

@ -43,6 +43,7 @@ var activators = map[int]func(*JumpTable){
7702: enable7702,
7939: enable7939,
8024: enable8024,
7843: enable7843,
}
// EnableEIP enables the given EIP on the config.
@ -579,3 +580,19 @@ func enable7702(jt *JumpTable) {
jt[STATICCALL].dynamicGas = gasStaticCallEIP7702
jt[DELEGATECALL].dynamicGas = gasDelegateCallEIP7702
}
// opSlotnum enables the SLOTNUM opcode
func opSlotnum(pc *uint64, evm *EVM, scope *ScopeContext) ([]byte, error) {
scope.Stack.push(uint256.NewInt(evm.Context.Slotnum))
return nil, nil
}
// enable7843 enables the SLOTNUM opcode as specified in EIP-7843.
func enable7843(jt *JumpTable) {
jt[SLOTNUM] = &operation{
execute: opSlotnum,
constantGas: GasQuickStep,
minStack: minStack(0, 1),
maxStack: maxStack(0, 1),
}
}

View file

@ -66,6 +66,7 @@ type BlockContext struct {
BaseFee *big.Int // Provides information for BASEFEE (0 if vm runs with NoBaseFee flag and 0 gas price)
BlobBaseFee *big.Int // Provides information for BLOBBASEFEE (0 if vm runs with NoBaseFee flag and 0 blob gas price)
Random *common.Hash // Provides information for PREVRANDAO
Slotnum uint64 // Provides information for SLOTNUM
}
// TxContext provides the EVM with information about a transaction.

View file

@ -105,6 +105,7 @@ const (
BASEFEE OpCode = 0x48
BLOBHASH OpCode = 0x49
BLOBBASEFEE OpCode = 0x4a
SLOTNUM OpCode = 0x4b
)
// 0x50 range - 'storage' and execution.
@ -320,6 +321,7 @@ var opCodeToString = [256]string{
BASEFEE: "BASEFEE",
BLOBHASH: "BLOBHASH",
BLOBBASEFEE: "BLOBBASEFEE",
SLOTNUM: "SLOTNUM",
// 0x50 range - 'storage' and execution.
POP: "POP",
@ -502,6 +504,7 @@ var stringToOp = map[string]OpCode{
"BASEFEE": BASEFEE,
"BLOBHASH": BLOBHASH,
"BLOBBASEFEE": BLOBBASEFEE,
"SLOTNUM": SLOTNUM,
"DELEGATECALL": DELEGATECALL,
"STATICCALL": STATICCALL,
"CODESIZE": CODESIZE,