core/vm: implement eip-7843

This commit is contained in:
MariusVanDerWijden 2026-01-12 22:47:41 +01:00 committed by Jared Wasinger
parent a644b7f03c
commit 4a2a3d0e1f
11 changed files with 56 additions and 0 deletions

View file

@ -56,6 +56,7 @@ type header struct {
BlobGasUsed *uint64 `json:"blobGasUsed" rlp:"optional"` BlobGasUsed *uint64 `json:"blobGasUsed" rlp:"optional"`
ExcessBlobGas *uint64 `json:"excessBlobGas" rlp:"optional"` ExcessBlobGas *uint64 `json:"excessBlobGas" rlp:"optional"`
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
SlotNumber *uint64 `json:"slotNumber" rlp:"optional"`
} }
type headerMarshaling struct { type headerMarshaling struct {
@ -68,6 +69,7 @@ type headerMarshaling struct {
BaseFee *math.HexOrDecimal256 BaseFee *math.HexOrDecimal256
BlobGasUsed *math.HexOrDecimal64 BlobGasUsed *math.HexOrDecimal64
ExcessBlobGas *math.HexOrDecimal64 ExcessBlobGas *math.HexOrDecimal64
SlotNumber *math.HexOrDecimal64
} }
type bbInput struct { type bbInput struct {
@ -136,6 +138,7 @@ func (i *bbInput) ToBlock() *types.Block {
BlobGasUsed: i.Header.BlobGasUsed, BlobGasUsed: i.Header.BlobGasUsed,
ExcessBlobGas: i.Header.ExcessBlobGas, ExcessBlobGas: i.Header.ExcessBlobGas,
ParentBeaconRoot: i.Header.ParentBeaconBlockRoot, ParentBeaconRoot: i.Header.ParentBeaconBlockRoot,
SlotNumber: i.Header.SlotNumber,
} }
// Fill optional values. // Fill optional values.

View file

@ -102,6 +102,7 @@ type stEnv struct {
ParentExcessBlobGas *uint64 `json:"parentExcessBlobGas,omitempty"` ParentExcessBlobGas *uint64 `json:"parentExcessBlobGas,omitempty"`
ParentBlobGasUsed *uint64 `json:"parentBlobGasUsed,omitempty"` ParentBlobGasUsed *uint64 `json:"parentBlobGasUsed,omitempty"`
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"` ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
SlotNumber *uint64 `json:"slotNumber"`
} }
type stEnvMarshaling struct { type stEnvMarshaling struct {
@ -120,6 +121,7 @@ type stEnvMarshaling struct {
ExcessBlobGas *math.HexOrDecimal64 ExcessBlobGas *math.HexOrDecimal64
ParentExcessBlobGas *math.HexOrDecimal64 ParentExcessBlobGas *math.HexOrDecimal64
ParentBlobGasUsed *math.HexOrDecimal64 ParentBlobGasUsed *math.HexOrDecimal64
SlotNumber *math.HexOrDecimal64
} }
type rejectedTx struct { type rejectedTx struct {
@ -195,6 +197,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
ExcessBlobGas: pre.Env.ParentExcessBlobGas, ExcessBlobGas: pre.Env.ParentExcessBlobGas,
BlobGasUsed: pre.Env.ParentBlobGasUsed, BlobGasUsed: pre.Env.ParentBlobGasUsed,
BaseFee: pre.Env.ParentBaseFee, BaseFee: pre.Env.ParentBaseFee,
SlotNumber: pre.Env.SlotNumber,
} }
header := &types.Header{ header := &types.Header{
Time: pre.Env.Timestamp, Time: pre.Env.Timestamp,

View file

@ -275,6 +275,14 @@ func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, pa
if chain.Config().IsAmsterdam(header.Number, header.Time) && header.BlockAccessListHash == nil { if chain.Config().IsAmsterdam(header.Number, header.Time) && header.BlockAccessListHash == nil {
return fmt.Errorf("block access list hash must be set post-Amsterdam") return fmt.Errorf("block access list hash must be set post-Amsterdam")
} }
amsterdam := chain.Config().IsAmsterdam(header.Number, header.Time)
if amsterdam && header.SlotNumber == nil {
return errors.New("header is missing slotNumber")
}
if !amsterdam && header.SlotNumber != nil {
return fmt.Errorf("invalid slotNumber: have %d, expected nil", *header.SlotNumber)
}
return nil return nil
} }

View file

@ -310,6 +310,8 @@ func (c *Clique) verifyHeader(chain consensus.ChainHeaderReader, header *types.H
return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", *header.BlobGasUsed) return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", *header.BlobGasUsed)
case header.ParentBeaconRoot != nil: case header.ParentBeaconRoot != nil:
return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected nil", *header.ParentBeaconRoot) return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected nil", *header.ParentBeaconRoot)
case header.SlotNumber != nil:
return fmt.Errorf("invalid slotNumber, have %#x, expected nil", *header.SlotNumber)
} }
// All basic checks passed, verify cascading fields // All basic checks passed, verify cascading fields
return c.verifyCascadingFields(chain, header, parents) return c.verifyCascadingFields(chain, header, parents)
@ -698,6 +700,9 @@ func encodeSigHeader(w io.Writer, header *types.Header) {
if header.ParentBeaconRoot != nil { if header.ParentBeaconRoot != nil {
panic("unexpected parent beacon root value in clique") panic("unexpected parent beacon root value in clique")
} }
if header.SlotNumber != nil {
panic("unexpected slot number value in clique")
}
if err := rlp.Encode(w, enc); err != nil { if err := rlp.Encode(w, enc); err != nil {
panic("can't encode: " + err.Error()) panic("can't encode: " + err.Error())
} }

View file

@ -283,6 +283,8 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainHeaderReader, header, pa
return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", *header.BlobGasUsed) return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", *header.BlobGasUsed)
case header.ParentBeaconRoot != nil: case header.ParentBeaconRoot != nil:
return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected nil", *header.ParentBeaconRoot) return fmt.Errorf("invalid parentBeaconRoot, have %#x, expected nil", *header.ParentBeaconRoot)
case header.SlotNumber != nil:
return fmt.Errorf("invalid slotNumber, have %#x, expected nil", *header.SlotNumber)
} }
// Add some fake checks for tests // Add some fake checks for tests
if ethash.fakeDelay != nil { if ethash.fakeDelay != nil {
@ -562,6 +564,9 @@ func (ethash *Ethash) SealHash(header *types.Header) (hash common.Hash) {
if header.ParentBeaconRoot != nil { if header.ParentBeaconRoot != nil {
panic("parent beacon root set on ethash") panic("parent beacon root set on ethash")
} }
if header.SlotNumber != nil {
panic("slot number set on ethash")
}
rlp.Encode(hasher, enc) rlp.Encode(hasher, enc)
hasher.Sum(hash[:0]) hasher.Sum(hash[:0])
return hash return hash

View file

@ -74,6 +74,7 @@ type Genesis struct {
ExcessBlobGas *uint64 `json:"excessBlobGas"` // EIP-4844 ExcessBlobGas *uint64 `json:"excessBlobGas"` // EIP-4844
BlobGasUsed *uint64 `json:"blobGasUsed"` // EIP-4844 BlobGasUsed *uint64 `json:"blobGasUsed"` // EIP-4844
BlockAccessListHash *common.Hash `json:"blockAccessListHash,omitempty"` // EIP-7928 BlockAccessListHash *common.Hash `json:"blockAccessListHash,omitempty"` // EIP-7928
SlotNumber *uint64 `json:"slotNumber"` // EIP-7843
} }
// copy copies the genesis. // copy copies the genesis.
@ -123,7 +124,11 @@ func ReadGenesis(db ethdb.Database) (*Genesis, error) {
genesis.BaseFee = genesisHeader.BaseFee genesis.BaseFee = genesisHeader.BaseFee
genesis.ExcessBlobGas = genesisHeader.ExcessBlobGas genesis.ExcessBlobGas = genesisHeader.ExcessBlobGas
genesis.BlobGasUsed = genesisHeader.BlobGasUsed genesis.BlobGasUsed = genesisHeader.BlobGasUsed
<<<<<<< HEAD
genesis.BlockAccessListHash = genesisHeader.BlockAccessListHash genesis.BlockAccessListHash = genesisHeader.BlockAccessListHash
=======
genesis.SlotNumber = genesisHeader.SlotNumber
>>>>>>> 06c09385b5 (core/vm: implement eip-7843)
return &genesis, nil return &genesis, nil
} }
@ -550,6 +555,12 @@ func (g *Genesis) toBlockWithRoot(root common.Hash) *types.Block {
if conf.IsPrague(num, g.Timestamp) { if conf.IsPrague(num, g.Timestamp) {
head.RequestsHash = &types.EmptyRequestsHash head.RequestsHash = &types.EmptyRequestsHash
} }
if conf.IsAmsterdam(num, g.Timestamp) {
head.SlotNumber = g.SlotNumber
if head.SlotNumber == nil {
head.SlotNumber = new(uint64)
}
}
} }
return types.NewBlock(head, &types.Body{Withdrawals: withdrawals}, nil, trie.NewStackTrie(nil)) return types.NewBlock(head, &types.Body{Withdrawals: withdrawals}, nil, trie.NewStackTrie(nil))
} }

View file

@ -422,6 +422,9 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr
beaconRoot := common.HexToHash("0xbeac00") beaconRoot := common.HexToHash("0xbeac00")
header.ParentBeaconRoot = &beaconRoot header.ParentBeaconRoot = &beaconRoot
} }
if config.IsAmsterdam(header.Number, header.Time) {
header.SlotNumber = new(uint64)
}
// Assemble and return the final block for sealing // Assemble and return the final block for sealing
body := &types.Body{Transactions: txs} body := &types.Body{Transactions: txs}
if config.IsShanghai(header.Number, header.Time) { if config.IsShanghai(header.Number, header.Time) {

View file

@ -332,6 +332,10 @@ func CopyHeader(h *Header) *Header {
cpy.RequestsHash = new(common.Hash) cpy.RequestsHash = new(common.Hash)
*cpy.RequestsHash = *h.RequestsHash *cpy.RequestsHash = *h.RequestsHash
} }
if h.SlotNumber != nil {
cpy.SlotNumber = new(uint64)
*cpy.SlotNumber = *h.SlotNumber
}
return &cpy return &cpy
} }

View file

@ -932,6 +932,9 @@ func RPCMarshalHeader(head *types.Header) map[string]interface{} {
if head.RequestsHash != nil { if head.RequestsHash != nil {
result["requestsHash"] = head.RequestsHash result["requestsHash"] = head.RequestsHash
} }
if head.SlotNumber != nil {
result["slotNumber"] = head.SlotNumber
}
return result return result
} }

View file

@ -100,6 +100,7 @@ type btHeader struct {
ExcessBlobGas *uint64 ExcessBlobGas *uint64
ParentBeaconBlockRoot *common.Hash ParentBeaconBlockRoot *common.Hash
BlockAccessListHash *common.Hash BlockAccessListHash *common.Hash
SlotNumber *uint64
} }
type btHeaderMarshaling struct { type btHeaderMarshaling struct {
@ -112,6 +113,7 @@ type btHeaderMarshaling struct {
BaseFeePerGas *math.HexOrDecimal256 BaseFeePerGas *math.HexOrDecimal256
BlobGasUsed *math.HexOrDecimal64 BlobGasUsed *math.HexOrDecimal64
ExcessBlobGas *math.HexOrDecimal64 ExcessBlobGas *math.HexOrDecimal64
SlotNumber *math.HexOrDecimal64
} }
func (t *BlockTest) createTestBlockChain(config *params.ChainConfig, snapshotter bool, scheme string, witness, createAndVerifyBAL bool, tracer *tracing.Hooks) (*core.BlockChain, error) { func (t *BlockTest) createTestBlockChain(config *params.ChainConfig, snapshotter bool, scheme string, witness, createAndVerifyBAL bool, tracer *tracing.Hooks) (*core.BlockChain, error) {
@ -409,6 +411,9 @@ func validateHeader(h *btHeader, h2 *types.Header) error {
if !reflect.DeepEqual(h.ParentBeaconBlockRoot, h2.ParentBeaconRoot) { if !reflect.DeepEqual(h.ParentBeaconBlockRoot, h2.ParentBeaconRoot) {
return fmt.Errorf("parentBeaconBlockRoot: want: %v have: %v", h.ParentBeaconBlockRoot, h2.ParentBeaconRoot) return fmt.Errorf("parentBeaconBlockRoot: want: %v have: %v", h.ParentBeaconBlockRoot, h2.ParentBeaconRoot)
} }
if !reflect.DeepEqual(h.SlotNumber, h2.SlotNumber) {
return fmt.Errorf("slotNumber: want: %v have: %v", h.SlotNumber, h2.SlotNumber)
}
return nil return nil
} }

View file

@ -39,6 +39,7 @@ func (b btHeader) MarshalJSON() ([]byte, error) {
ExcessBlobGas *math.HexOrDecimal64 ExcessBlobGas *math.HexOrDecimal64
ParentBeaconBlockRoot *common.Hash ParentBeaconBlockRoot *common.Hash
BlockAccessListHash *common.Hash BlockAccessListHash *common.Hash
SlotNumber *math.HexOrDecimal64
} }
var enc btHeader var enc btHeader
enc.Bloom = b.Bloom enc.Bloom = b.Bloom
@ -62,6 +63,7 @@ func (b btHeader) MarshalJSON() ([]byte, error) {
enc.BlobGasUsed = (*math.HexOrDecimal64)(b.BlobGasUsed) enc.BlobGasUsed = (*math.HexOrDecimal64)(b.BlobGasUsed)
enc.ExcessBlobGas = (*math.HexOrDecimal64)(b.ExcessBlobGas) enc.ExcessBlobGas = (*math.HexOrDecimal64)(b.ExcessBlobGas)
enc.ParentBeaconBlockRoot = b.ParentBeaconBlockRoot enc.ParentBeaconBlockRoot = b.ParentBeaconBlockRoot
enc.SlotNumber = (*math.HexOrDecimal64)(b.SlotNumber)
return json.Marshal(&enc) return json.Marshal(&enc)
} }
@ -90,6 +92,7 @@ func (b *btHeader) UnmarshalJSON(input []byte) error {
ExcessBlobGas *math.HexOrDecimal64 ExcessBlobGas *math.HexOrDecimal64
ParentBeaconBlockRoot *common.Hash ParentBeaconBlockRoot *common.Hash
BlockAccessListHash *common.Hash BlockAccessListHash *common.Hash
SlotNumber *math.HexOrDecimal64
} }
var dec btHeader var dec btHeader
if err := json.Unmarshal(input, &dec); err != nil { if err := json.Unmarshal(input, &dec); err != nil {
@ -161,5 +164,8 @@ func (b *btHeader) UnmarshalJSON(input []byte) error {
if dec.BlockAccessListHash != nil { if dec.BlockAccessListHash != nil {
b.BlockAccessListHash = dec.BlockAccessListHash b.BlockAccessListHash = dec.BlockAccessListHash
} }
if dec.SlotNumber != nil {
b.SlotNumber = (*uint64)(dec.SlotNumber)
}
return nil return nil
} }