diff --git a/cmd/evm/internal/t8ntool/block.go b/cmd/evm/internal/t8ntool/block.go index 37a6db9ffc..6148e9e248 100644 --- a/cmd/evm/internal/t8ntool/block.go +++ b/cmd/evm/internal/t8ntool/block.go @@ -56,6 +56,7 @@ type header struct { BlobGasUsed *uint64 `json:"blobGasUsed" rlp:"optional"` ExcessBlobGas *uint64 `json:"excessBlobGas" rlp:"optional"` ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"` + SlotNumber *uint64 `json:"slotNumber" rlp:"optional"` } type headerMarshaling struct { @@ -68,6 +69,7 @@ type headerMarshaling struct { BaseFee *math.HexOrDecimal256 BlobGasUsed *math.HexOrDecimal64 ExcessBlobGas *math.HexOrDecimal64 + SlotNumber *math.HexOrDecimal64 } type bbInput struct { @@ -136,6 +138,7 @@ func (i *bbInput) ToBlock() *types.Block { BlobGasUsed: i.Header.BlobGasUsed, ExcessBlobGas: i.Header.ExcessBlobGas, ParentBeaconRoot: i.Header.ParentBeaconBlockRoot, + SlotNumber: i.Header.SlotNumber, } // Fill optional values. diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index 44f15c322c..6f1b7ffdf0 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -102,6 +102,7 @@ type stEnv struct { ParentExcessBlobGas *uint64 `json:"parentExcessBlobGas,omitempty"` ParentBlobGasUsed *uint64 `json:"parentBlobGasUsed,omitempty"` ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"` + SlotNumber *uint64 `json:"slotNumber"` } type stEnvMarshaling struct { @@ -120,6 +121,7 @@ type stEnvMarshaling struct { ExcessBlobGas *math.HexOrDecimal64 ParentExcessBlobGas *math.HexOrDecimal64 ParentBlobGasUsed *math.HexOrDecimal64 + SlotNumber *math.HexOrDecimal64 } type rejectedTx struct { @@ -195,6 +197,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, ExcessBlobGas: pre.Env.ParentExcessBlobGas, BlobGasUsed: pre.Env.ParentBlobGasUsed, BaseFee: pre.Env.ParentBaseFee, + SlotNumber: pre.Env.SlotNumber, } header := &types.Header{ Time: pre.Env.Timestamp, diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go index 1281b26650..5cb637a81e 100644 --- a/consensus/beacon/consensus.go +++ b/consensus/beacon/consensus.go @@ -275,6 +275,14 @@ func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, pa if chain.Config().IsAmsterdam(header.Number, header.Time) && header.BlockAccessListHash == nil { 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 } diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index 4a33848fd5..e2127deba1 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -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) case header.ParentBeaconRoot != nil: 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 return c.verifyCascadingFields(chain, header, parents) @@ -698,6 +700,9 @@ func encodeSigHeader(w io.Writer, header *types.Header) { if header.ParentBeaconRoot != nil { 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 { panic("can't encode: " + err.Error()) } diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index f5a6f52612..8d125da692 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -283,6 +283,8 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainHeaderReader, header, pa return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", *header.BlobGasUsed) case header.ParentBeaconRoot != nil: 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 if ethash.fakeDelay != nil { @@ -562,6 +564,9 @@ func (ethash *Ethash) SealHash(header *types.Header) (hash common.Hash) { if header.ParentBeaconRoot != nil { panic("parent beacon root set on ethash") } + if header.SlotNumber != nil { + panic("slot number set on ethash") + } rlp.Encode(hasher, enc) hasher.Sum(hash[:0]) return hash diff --git a/core/genesis.go b/core/genesis.go index c086038253..e18f7c5f43 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -74,6 +74,7 @@ type Genesis struct { ExcessBlobGas *uint64 `json:"excessBlobGas"` // EIP-4844 BlobGasUsed *uint64 `json:"blobGasUsed"` // EIP-4844 BlockAccessListHash *common.Hash `json:"blockAccessListHash,omitempty"` // EIP-7928 + SlotNumber *uint64 `json:"slotNumber"` // EIP-7843 } // copy copies the genesis. @@ -123,7 +124,11 @@ func ReadGenesis(db ethdb.Database) (*Genesis, error) { genesis.BaseFee = genesisHeader.BaseFee genesis.ExcessBlobGas = genesisHeader.ExcessBlobGas genesis.BlobGasUsed = genesisHeader.BlobGasUsed +<<<<<<< HEAD genesis.BlockAccessListHash = genesisHeader.BlockAccessListHash +======= + genesis.SlotNumber = genesisHeader.SlotNumber +>>>>>>> 06c09385b5 (core/vm: implement eip-7843) return &genesis, nil } @@ -550,6 +555,12 @@ func (g *Genesis) toBlockWithRoot(root common.Hash) *types.Block { if conf.IsPrague(num, g.Timestamp) { 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)) } diff --git a/core/state_processor_test.go b/core/state_processor_test.go index 9d6cbdbc8b..b903f7cdaa 100644 --- a/core/state_processor_test.go +++ b/core/state_processor_test.go @@ -422,6 +422,9 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr beaconRoot := common.HexToHash("0xbeac00") header.ParentBeaconRoot = &beaconRoot } + if config.IsAmsterdam(header.Number, header.Time) { + header.SlotNumber = new(uint64) + } // Assemble and return the final block for sealing body := &types.Body{Transactions: txs} if config.IsShanghai(header.Number, header.Time) { diff --git a/core/types/block.go b/core/types/block.go index 498047c509..3597d7f49d 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -332,6 +332,10 @@ func CopyHeader(h *Header) *Header { cpy.RequestsHash = new(common.Hash) *cpy.RequestsHash = *h.RequestsHash } + if h.SlotNumber != nil { + cpy.SlotNumber = new(uint64) + *cpy.SlotNumber = *h.SlotNumber + } return &cpy } diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index a8a0f71d0c..25c5f4c788 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -932,6 +932,9 @@ func RPCMarshalHeader(head *types.Header) map[string]interface{} { if head.RequestsHash != nil { result["requestsHash"] = head.RequestsHash } + if head.SlotNumber != nil { + result["slotNumber"] = head.SlotNumber + } return result } diff --git a/tests/block_test_util.go b/tests/block_test_util.go index 26c4b29b0e..ceb1df94bf 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -100,6 +100,7 @@ type btHeader struct { ExcessBlobGas *uint64 ParentBeaconBlockRoot *common.Hash BlockAccessListHash *common.Hash + SlotNumber *uint64 } type btHeaderMarshaling struct { @@ -112,6 +113,7 @@ type btHeaderMarshaling struct { BaseFeePerGas *math.HexOrDecimal256 BlobGasUsed *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) { @@ -409,6 +411,9 @@ func validateHeader(h *btHeader, h2 *types.Header) error { if !reflect.DeepEqual(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 } diff --git a/tests/gen_btheader.go b/tests/gen_btheader.go index 4ddd2195c2..d1bcaf690b 100644 --- a/tests/gen_btheader.go +++ b/tests/gen_btheader.go @@ -39,6 +39,7 @@ func (b btHeader) MarshalJSON() ([]byte, error) { ExcessBlobGas *math.HexOrDecimal64 ParentBeaconBlockRoot *common.Hash BlockAccessListHash *common.Hash + SlotNumber *math.HexOrDecimal64 } var enc btHeader enc.Bloom = b.Bloom @@ -62,6 +63,7 @@ func (b btHeader) MarshalJSON() ([]byte, error) { enc.BlobGasUsed = (*math.HexOrDecimal64)(b.BlobGasUsed) enc.ExcessBlobGas = (*math.HexOrDecimal64)(b.ExcessBlobGas) enc.ParentBeaconBlockRoot = b.ParentBeaconBlockRoot + enc.SlotNumber = (*math.HexOrDecimal64)(b.SlotNumber) return json.Marshal(&enc) } @@ -90,6 +92,7 @@ func (b *btHeader) UnmarshalJSON(input []byte) error { ExcessBlobGas *math.HexOrDecimal64 ParentBeaconBlockRoot *common.Hash BlockAccessListHash *common.Hash + SlotNumber *math.HexOrDecimal64 } var dec btHeader if err := json.Unmarshal(input, &dec); err != nil { @@ -161,5 +164,8 @@ func (b *btHeader) UnmarshalJSON(input []byte) error { if dec.BlockAccessListHash != nil { b.BlockAccessListHash = dec.BlockAccessListHash } + if dec.SlotNumber != nil { + b.SlotNumber = (*uint64)(dec.SlotNumber) + } return nil }