diff --git a/beacon/engine/errors.go b/beacon/engine/errors.go
deleted file mode 100644
index 62773a0ea9..0000000000
--- a/beacon/engine/errors.go
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2022 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package engine
-
-import (
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/rpc"
-)
-
-// EngineAPIError is a standardized error message between consensus and execution
-// clients, also containing any custom error message Geth might include.
-type EngineAPIError struct {
- code int
- msg string
- err error
-}
-
-func (e *EngineAPIError) ErrorCode() int { return e.code }
-func (e *EngineAPIError) Error() string { return e.msg }
-func (e *EngineAPIError) ErrorData() interface{} {
- if e.err == nil {
- return nil
- }
- return struct {
- Error string `json:"err"`
- }{e.err.Error()}
-}
-
-// With returns a copy of the error with a new embedded custom data field.
-func (e *EngineAPIError) With(err error) *EngineAPIError {
- return &EngineAPIError{
- code: e.code,
- msg: e.msg,
- err: err,
- }
-}
-
-var (
- _ rpc.Error = new(EngineAPIError)
- _ rpc.DataError = new(EngineAPIError)
-)
-
-var (
- // VALID is returned by the engine API in the following calls:
- // - newPayloadV1: if the payload was already known or was just validated and executed
- // - forkchoiceUpdateV1: if the chain accepted the reorg (might ignore if it's stale)
- VALID = "VALID"
-
- // INVALID is returned by the engine API in the following calls:
- // - newPayloadV1: if the payload failed to execute on top of the local chain
- // - forkchoiceUpdateV1: if the new head is unknown, pre-merge, or reorg to it fails
- INVALID = "INVALID"
-
- // SYNCING is returned by the engine API in the following calls:
- // - newPayloadV1: if the payload was accepted on top of an active sync
- // - forkchoiceUpdateV1: if the new head was seen before, but not part of the chain
- SYNCING = "SYNCING"
-
- // ACCEPTED is returned by the engine API in the following calls:
- // - newPayloadV1: if the payload was accepted, but not processed (side chain)
- ACCEPTED = "ACCEPTED"
-
- GenericServerError = &EngineAPIError{code: -32000, msg: "Server error"}
- UnknownPayload = &EngineAPIError{code: -38001, msg: "Unknown payload"}
- InvalidForkChoiceState = &EngineAPIError{code: -38002, msg: "Invalid forkchoice state"}
- InvalidPayloadAttributes = &EngineAPIError{code: -38003, msg: "Invalid payload attributes"}
- TooLargeRequest = &EngineAPIError{code: -38004, msg: "Too large request"}
- InvalidParams = &EngineAPIError{code: -32602, msg: "Invalid parameters"}
- UnsupportedFork = &EngineAPIError{code: -38005, msg: "Unsupported fork"}
-
- STATUS_INVALID = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: INVALID}, PayloadID: nil}
- STATUS_SYNCING = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: SYNCING}, PayloadID: nil}
- INVALID_TERMINAL_BLOCK = PayloadStatusV1{Status: INVALID, LatestValidHash: &common.Hash{}}
-)
diff --git a/beacon/engine/gen_blockparams.go b/beacon/engine/gen_blockparams.go
deleted file mode 100644
index b1f01b50ff..0000000000
--- a/beacon/engine/gen_blockparams.go
+++ /dev/null
@@ -1,66 +0,0 @@
-// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
-
-package engine
-
-import (
- "encoding/json"
- "errors"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/hexutil"
- "github.com/ethereum/go-ethereum/core/types"
-)
-
-var _ = (*payloadAttributesMarshaling)(nil)
-
-// MarshalJSON marshals as JSON.
-func (p PayloadAttributes) MarshalJSON() ([]byte, error) {
- type PayloadAttributes struct {
- Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"`
- Random common.Hash `json:"prevRandao" gencodec:"required"`
- SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
- Withdrawals []*types.Withdrawal `json:"withdrawals"`
- BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
- }
- var enc PayloadAttributes
- enc.Timestamp = hexutil.Uint64(p.Timestamp)
- enc.Random = p.Random
- enc.SuggestedFeeRecipient = p.SuggestedFeeRecipient
- enc.Withdrawals = p.Withdrawals
- enc.BeaconRoot = p.BeaconRoot
- return json.Marshal(&enc)
-}
-
-// UnmarshalJSON unmarshals from JSON.
-func (p *PayloadAttributes) UnmarshalJSON(input []byte) error {
- type PayloadAttributes struct {
- Timestamp *hexutil.Uint64 `json:"timestamp" gencodec:"required"`
- Random *common.Hash `json:"prevRandao" gencodec:"required"`
- SuggestedFeeRecipient *common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
- Withdrawals []*types.Withdrawal `json:"withdrawals"`
- BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
- }
- var dec PayloadAttributes
- if err := json.Unmarshal(input, &dec); err != nil {
- return err
- }
- if dec.Timestamp == nil {
- return errors.New("missing required field 'timestamp' for PayloadAttributes")
- }
- p.Timestamp = uint64(*dec.Timestamp)
- if dec.Random == nil {
- return errors.New("missing required field 'prevRandao' for PayloadAttributes")
- }
- p.Random = *dec.Random
- if dec.SuggestedFeeRecipient == nil {
- return errors.New("missing required field 'suggestedFeeRecipient' for PayloadAttributes")
- }
- p.SuggestedFeeRecipient = *dec.SuggestedFeeRecipient
- if dec.Withdrawals != nil {
- p.Withdrawals = dec.Withdrawals
- }
- if dec.BeaconRoot != nil {
- p.BeaconRoot = dec.BeaconRoot
- }
- return nil
-}
diff --git a/beacon/engine/gen_ed.go b/beacon/engine/gen_ed.go
deleted file mode 100644
index 6893d64a16..0000000000
--- a/beacon/engine/gen_ed.go
+++ /dev/null
@@ -1,158 +0,0 @@
-// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
-
-package engine
-
-import (
- "encoding/json"
- "errors"
- "math/big"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/hexutil"
- "github.com/ethereum/go-ethereum/core/types"
-)
-
-var _ = (*executableDataMarshaling)(nil)
-
-// MarshalJSON marshals as JSON.
-func (e ExecutableData) MarshalJSON() ([]byte, error) {
- type ExecutableData struct {
- ParentHash common.Hash `json:"parentHash" gencodec:"required"`
- FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"`
- StateRoot common.Hash `json:"stateRoot" gencodec:"required"`
- ReceiptsRoot common.Hash `json:"receiptsRoot" gencodec:"required"`
- LogsBloom hexutil.Bytes `json:"logsBloom" gencodec:"required"`
- Random common.Hash `json:"prevRandao" gencodec:"required"`
- Number hexutil.Uint64 `json:"blockNumber" gencodec:"required"`
- GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
- GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
- Timestamp hexutil.Uint64 `json:"timestamp" gencodec:"required"`
- ExtraData hexutil.Bytes `json:"extraData" gencodec:"required"`
- BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"`
- BlockHash common.Hash `json:"blockHash" gencodec:"required"`
- Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"`
- Withdrawals []*types.Withdrawal `json:"withdrawals"`
- BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
- ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
- }
- var enc ExecutableData
- enc.ParentHash = e.ParentHash
- enc.FeeRecipient = e.FeeRecipient
- enc.StateRoot = e.StateRoot
- enc.ReceiptsRoot = e.ReceiptsRoot
- enc.LogsBloom = e.LogsBloom
- enc.Random = e.Random
- enc.Number = hexutil.Uint64(e.Number)
- enc.GasLimit = hexutil.Uint64(e.GasLimit)
- enc.GasUsed = hexutil.Uint64(e.GasUsed)
- enc.Timestamp = hexutil.Uint64(e.Timestamp)
- enc.ExtraData = e.ExtraData
- enc.BaseFeePerGas = (*hexutil.Big)(e.BaseFeePerGas)
- enc.BlockHash = e.BlockHash
- if e.Transactions != nil {
- enc.Transactions = make([]hexutil.Bytes, len(e.Transactions))
- for k, v := range e.Transactions {
- enc.Transactions[k] = v
- }
- }
- enc.Withdrawals = e.Withdrawals
- enc.BlobGasUsed = (*hexutil.Uint64)(e.BlobGasUsed)
- enc.ExcessBlobGas = (*hexutil.Uint64)(e.ExcessBlobGas)
- return json.Marshal(&enc)
-}
-
-// UnmarshalJSON unmarshals from JSON.
-func (e *ExecutableData) UnmarshalJSON(input []byte) error {
- type ExecutableData struct {
- ParentHash *common.Hash `json:"parentHash" gencodec:"required"`
- FeeRecipient *common.Address `json:"feeRecipient" gencodec:"required"`
- StateRoot *common.Hash `json:"stateRoot" gencodec:"required"`
- ReceiptsRoot *common.Hash `json:"receiptsRoot" gencodec:"required"`
- LogsBloom *hexutil.Bytes `json:"logsBloom" gencodec:"required"`
- Random *common.Hash `json:"prevRandao" gencodec:"required"`
- Number *hexutil.Uint64 `json:"blockNumber" gencodec:"required"`
- GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
- GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
- Timestamp *hexutil.Uint64 `json:"timestamp" gencodec:"required"`
- ExtraData *hexutil.Bytes `json:"extraData" gencodec:"required"`
- BaseFeePerGas *hexutil.Big `json:"baseFeePerGas" gencodec:"required"`
- BlockHash *common.Hash `json:"blockHash" gencodec:"required"`
- Transactions []hexutil.Bytes `json:"transactions" gencodec:"required"`
- Withdrawals []*types.Withdrawal `json:"withdrawals"`
- BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
- ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
- }
- var dec ExecutableData
- if err := json.Unmarshal(input, &dec); err != nil {
- return err
- }
- if dec.ParentHash == nil {
- return errors.New("missing required field 'parentHash' for ExecutableData")
- }
- e.ParentHash = *dec.ParentHash
- if dec.FeeRecipient == nil {
- return errors.New("missing required field 'feeRecipient' for ExecutableData")
- }
- e.FeeRecipient = *dec.FeeRecipient
- if dec.StateRoot == nil {
- return errors.New("missing required field 'stateRoot' for ExecutableData")
- }
- e.StateRoot = *dec.StateRoot
- if dec.ReceiptsRoot == nil {
- return errors.New("missing required field 'receiptsRoot' for ExecutableData")
- }
- e.ReceiptsRoot = *dec.ReceiptsRoot
- if dec.LogsBloom == nil {
- return errors.New("missing required field 'logsBloom' for ExecutableData")
- }
- e.LogsBloom = *dec.LogsBloom
- if dec.Random == nil {
- return errors.New("missing required field 'prevRandao' for ExecutableData")
- }
- e.Random = *dec.Random
- if dec.Number == nil {
- return errors.New("missing required field 'blockNumber' for ExecutableData")
- }
- e.Number = uint64(*dec.Number)
- if dec.GasLimit == nil {
- return errors.New("missing required field 'gasLimit' for ExecutableData")
- }
- e.GasLimit = uint64(*dec.GasLimit)
- if dec.GasUsed == nil {
- return errors.New("missing required field 'gasUsed' for ExecutableData")
- }
- e.GasUsed = uint64(*dec.GasUsed)
- if dec.Timestamp == nil {
- return errors.New("missing required field 'timestamp' for ExecutableData")
- }
- e.Timestamp = uint64(*dec.Timestamp)
- if dec.ExtraData == nil {
- return errors.New("missing required field 'extraData' for ExecutableData")
- }
- e.ExtraData = *dec.ExtraData
- if dec.BaseFeePerGas == nil {
- return errors.New("missing required field 'baseFeePerGas' for ExecutableData")
- }
- e.BaseFeePerGas = (*big.Int)(dec.BaseFeePerGas)
- if dec.BlockHash == nil {
- return errors.New("missing required field 'blockHash' for ExecutableData")
- }
- e.BlockHash = *dec.BlockHash
- if dec.Transactions == nil {
- return errors.New("missing required field 'transactions' for ExecutableData")
- }
- e.Transactions = make([][]byte, len(dec.Transactions))
- for k, v := range dec.Transactions {
- e.Transactions[k] = v
- }
- if dec.Withdrawals != nil {
- e.Withdrawals = dec.Withdrawals
- }
- if dec.BlobGasUsed != nil {
- e.BlobGasUsed = (*uint64)(dec.BlobGasUsed)
- }
- if dec.ExcessBlobGas != nil {
- e.ExcessBlobGas = (*uint64)(dec.ExcessBlobGas)
- }
- return nil
-}
diff --git a/beacon/engine/gen_epe.go b/beacon/engine/gen_epe.go
deleted file mode 100644
index e69f9a5951..0000000000
--- a/beacon/engine/gen_epe.go
+++ /dev/null
@@ -1,58 +0,0 @@
-// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
-
-package engine
-
-import (
- "encoding/json"
- "errors"
- "math/big"
-
- "github.com/ethereum/go-ethereum/common/hexutil"
-)
-
-var _ = (*executionPayloadEnvelopeMarshaling)(nil)
-
-// MarshalJSON marshals as JSON.
-func (e ExecutionPayloadEnvelope) MarshalJSON() ([]byte, error) {
- type ExecutionPayloadEnvelope struct {
- ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
- BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"`
- BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
- Override bool `json:"shouldOverrideBuilder"`
- }
- var enc ExecutionPayloadEnvelope
- enc.ExecutionPayload = e.ExecutionPayload
- enc.BlockValue = (*hexutil.Big)(e.BlockValue)
- enc.BlobsBundle = e.BlobsBundle
- enc.Override = e.Override
- return json.Marshal(&enc)
-}
-
-// UnmarshalJSON unmarshals from JSON.
-func (e *ExecutionPayloadEnvelope) UnmarshalJSON(input []byte) error {
- type ExecutionPayloadEnvelope struct {
- ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
- BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"`
- BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
- Override *bool `json:"shouldOverrideBuilder"`
- }
- var dec ExecutionPayloadEnvelope
- if err := json.Unmarshal(input, &dec); err != nil {
- return err
- }
- if dec.ExecutionPayload == nil {
- return errors.New("missing required field 'executionPayload' for ExecutionPayloadEnvelope")
- }
- e.ExecutionPayload = dec.ExecutionPayload
- if dec.BlockValue == nil {
- return errors.New("missing required field 'blockValue' for ExecutionPayloadEnvelope")
- }
- e.BlockValue = (*big.Int)(dec.BlockValue)
- if dec.BlobsBundle != nil {
- e.BlobsBundle = dec.BlobsBundle
- }
- if dec.Override != nil {
- e.Override = *dec.Override
- }
- return nil
-}
diff --git a/beacon/engine/types.go b/beacon/engine/types.go
deleted file mode 100644
index 67f30d4455..0000000000
--- a/beacon/engine/types.go
+++ /dev/null
@@ -1,280 +0,0 @@
-// Copyright 2022 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package engine
-
-import (
- "fmt"
- "math/big"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/hexutil"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/trie"
-)
-
-//go:generate go run github.com/fjl/gencodec -type PayloadAttributes -field-override payloadAttributesMarshaling -out gen_blockparams.go
-
-// PayloadAttributes describes the environment context in which a block should
-// be built.
-type PayloadAttributes struct {
- Timestamp uint64 `json:"timestamp" gencodec:"required"`
- Random common.Hash `json:"prevRandao" gencodec:"required"`
- SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
- Withdrawals []*types.Withdrawal `json:"withdrawals"`
- BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
-}
-
-// JSON type overrides for PayloadAttributes.
-type payloadAttributesMarshaling struct {
- Timestamp hexutil.Uint64
-}
-
-//go:generate go run github.com/fjl/gencodec -type ExecutableData -field-override executableDataMarshaling -out gen_ed.go
-
-// ExecutableData is the data necessary to execute an EL payload.
-type ExecutableData struct {
- ParentHash common.Hash `json:"parentHash" gencodec:"required"`
- FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"`
- StateRoot common.Hash `json:"stateRoot" gencodec:"required"`
- ReceiptsRoot common.Hash `json:"receiptsRoot" gencodec:"required"`
- LogsBloom []byte `json:"logsBloom" gencodec:"required"`
- Random common.Hash `json:"prevRandao" gencodec:"required"`
- Number uint64 `json:"blockNumber" gencodec:"required"`
- GasLimit uint64 `json:"gasLimit" gencodec:"required"`
- GasUsed uint64 `json:"gasUsed" gencodec:"required"`
- Timestamp uint64 `json:"timestamp" gencodec:"required"`
- ExtraData []byte `json:"extraData" gencodec:"required"`
- BaseFeePerGas *big.Int `json:"baseFeePerGas" gencodec:"required"`
- BlockHash common.Hash `json:"blockHash" gencodec:"required"`
- Transactions [][]byte `json:"transactions" gencodec:"required"`
- Withdrawals []*types.Withdrawal `json:"withdrawals"`
- BlobGasUsed *uint64 `json:"blobGasUsed"`
- ExcessBlobGas *uint64 `json:"excessBlobGas"`
-}
-
-// JSON type overrides for executableData.
-type executableDataMarshaling struct {
- Number hexutil.Uint64
- GasLimit hexutil.Uint64
- GasUsed hexutil.Uint64
- Timestamp hexutil.Uint64
- BaseFeePerGas *hexutil.Big
- ExtraData hexutil.Bytes
- LogsBloom hexutil.Bytes
- Transactions []hexutil.Bytes
- BlobGasUsed *hexutil.Uint64
- ExcessBlobGas *hexutil.Uint64
-}
-
-//go:generate go run github.com/fjl/gencodec -type ExecutionPayloadEnvelope -field-override executionPayloadEnvelopeMarshaling -out gen_epe.go
-
-type ExecutionPayloadEnvelope struct {
- ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"`
- BlockValue *big.Int `json:"blockValue" gencodec:"required"`
- BlobsBundle *BlobsBundleV1 `json:"blobsBundle"`
- Override bool `json:"shouldOverrideBuilder"`
-}
-
-type BlobsBundleV1 struct {
- Commitments []hexutil.Bytes `json:"commitments"`
- Proofs []hexutil.Bytes `json:"proofs"`
- Blobs []hexutil.Bytes `json:"blobs"`
-}
-
-// JSON type overrides for ExecutionPayloadEnvelope.
-type executionPayloadEnvelopeMarshaling struct {
- BlockValue *hexutil.Big
-}
-
-type PayloadStatusV1 struct {
- Status string `json:"status"`
- LatestValidHash *common.Hash `json:"latestValidHash"`
- ValidationError *string `json:"validationError"`
-}
-
-type TransitionConfigurationV1 struct {
- TerminalTotalDifficulty *hexutil.Big `json:"terminalTotalDifficulty"`
- TerminalBlockHash common.Hash `json:"terminalBlockHash"`
- TerminalBlockNumber hexutil.Uint64 `json:"terminalBlockNumber"`
-}
-
-// PayloadID is an identifier of the payload build process
-type PayloadID [8]byte
-
-func (b PayloadID) String() string {
- return hexutil.Encode(b[:])
-}
-
-func (b PayloadID) MarshalText() ([]byte, error) {
- return hexutil.Bytes(b[:]).MarshalText()
-}
-
-func (b *PayloadID) UnmarshalText(input []byte) error {
- err := hexutil.UnmarshalFixedText("PayloadID", input, b[:])
- if err != nil {
- return fmt.Errorf("invalid payload id %q: %w", input, err)
- }
- return nil
-}
-
-type ForkChoiceResponse struct {
- PayloadStatus PayloadStatusV1 `json:"payloadStatus"`
- PayloadID *PayloadID `json:"payloadId"`
-}
-
-type ForkchoiceStateV1 struct {
- HeadBlockHash common.Hash `json:"headBlockHash"`
- SafeBlockHash common.Hash `json:"safeBlockHash"`
- FinalizedBlockHash common.Hash `json:"finalizedBlockHash"`
-}
-
-func encodeTransactions(txs []*types.Transaction) [][]byte {
- var enc = make([][]byte, len(txs))
- for i, tx := range txs {
- enc[i], _ = tx.MarshalBinary()
- }
- return enc
-}
-
-func decodeTransactions(enc [][]byte) ([]*types.Transaction, error) {
- var txs = make([]*types.Transaction, len(enc))
- for i, encTx := range enc {
- var tx types.Transaction
- if err := tx.UnmarshalBinary(encTx); err != nil {
- return nil, fmt.Errorf("invalid transaction %d: %v", i, err)
- }
- txs[i] = &tx
- }
- return txs, nil
-}
-
-// ExecutableDataToBlock constructs a block from executable data.
-// It verifies that the following fields:
-//
-// len(extraData) <= 32
-// uncleHash = emptyUncleHash
-// difficulty = 0
-// if versionedHashes != nil, versionedHashes match to blob transactions
-//
-// and that the blockhash of the constructed block matches the parameters. Nil
-// Withdrawals value will propagate through the returned block. Empty
-// Withdrawals value must be passed via non-nil, length 0 value in params.
-func ExecutableDataToBlock(params ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (*types.Block, error) {
- txs, err := decodeTransactions(params.Transactions)
- if err != nil {
- return nil, err
- }
- if len(params.ExtraData) > 32 {
- return nil, fmt.Errorf("invalid extradata length: %v", len(params.ExtraData))
- }
- if len(params.LogsBloom) != 256 {
- return nil, fmt.Errorf("invalid logsBloom length: %v", len(params.LogsBloom))
- }
- // Check that baseFeePerGas is not negative or too big
- if params.BaseFeePerGas != nil && (params.BaseFeePerGas.Sign() == -1 || params.BaseFeePerGas.BitLen() > 256) {
- return nil, fmt.Errorf("invalid baseFeePerGas: %v", params.BaseFeePerGas)
- }
- var blobHashes []common.Hash
- for _, tx := range txs {
- blobHashes = append(blobHashes, tx.BlobHashes()...)
- }
- if len(blobHashes) != len(versionedHashes) {
- return nil, fmt.Errorf("invalid number of versionedHashes: %v blobHashes: %v", versionedHashes, blobHashes)
- }
- for i := 0; i < len(blobHashes); i++ {
- if blobHashes[i] != versionedHashes[i] {
- return nil, fmt.Errorf("invalid versionedHash at %v: %v blobHashes: %v", i, versionedHashes, blobHashes)
- }
- }
- // Only set withdrawalsRoot if it is non-nil. This allows CLs to use
- // ExecutableData before withdrawals are enabled by marshaling
- // Withdrawals as the json null value.
- var withdrawalsRoot *common.Hash
- if params.Withdrawals != nil {
- h := types.DeriveSha(types.Withdrawals(params.Withdrawals), trie.NewStackTrie(nil))
- withdrawalsRoot = &h
- }
- header := &types.Header{
- ParentHash: params.ParentHash,
- UncleHash: types.EmptyUncleHash,
- Coinbase: params.FeeRecipient,
- Root: params.StateRoot,
- TxHash: types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil)),
- ReceiptHash: params.ReceiptsRoot,
- Bloom: types.BytesToBloom(params.LogsBloom),
- Difficulty: common.Big0,
- Number: new(big.Int).SetUint64(params.Number),
- GasLimit: params.GasLimit,
- GasUsed: params.GasUsed,
- Time: params.Timestamp,
- BaseFee: params.BaseFeePerGas,
- Extra: params.ExtraData,
- MixDigest: params.Random,
- WithdrawalsHash: withdrawalsRoot,
- ExcessBlobGas: params.ExcessBlobGas,
- BlobGasUsed: params.BlobGasUsed,
- ParentBeaconRoot: beaconRoot,
- }
- block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */).WithWithdrawals(params.Withdrawals)
- if block.Hash() != params.BlockHash {
- return nil, fmt.Errorf("blockhash mismatch, want %x, got %x", params.BlockHash, block.Hash())
- }
- return block, nil
-}
-
-// BlockToExecutableData constructs the ExecutableData structure by filling the
-// fields from the given block. It assumes the given block is post-merge block.
-func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types.BlobTxSidecar) *ExecutionPayloadEnvelope {
- data := &ExecutableData{
- BlockHash: block.Hash(),
- ParentHash: block.ParentHash(),
- FeeRecipient: block.Coinbase(),
- StateRoot: block.Root(),
- Number: block.NumberU64(),
- GasLimit: block.GasLimit(),
- GasUsed: block.GasUsed(),
- BaseFeePerGas: block.BaseFee(),
- Timestamp: block.Time(),
- ReceiptsRoot: block.ReceiptHash(),
- LogsBloom: block.Bloom().Bytes(),
- Transactions: encodeTransactions(block.Transactions()),
- Random: block.MixDigest(),
- ExtraData: block.Extra(),
- Withdrawals: block.Withdrawals(),
- BlobGasUsed: block.BlobGasUsed(),
- ExcessBlobGas: block.ExcessBlobGas(),
- }
- bundle := BlobsBundleV1{
- Commitments: make([]hexutil.Bytes, 0),
- Blobs: make([]hexutil.Bytes, 0),
- Proofs: make([]hexutil.Bytes, 0),
- }
- for _, sidecar := range sidecars {
- for j := range sidecar.Blobs {
- bundle.Blobs = append(bundle.Blobs, hexutil.Bytes(sidecar.Blobs[j][:]))
- bundle.Commitments = append(bundle.Commitments, hexutil.Bytes(sidecar.Commitments[j][:]))
- bundle.Proofs = append(bundle.Proofs, hexutil.Bytes(sidecar.Proofs[j][:]))
- }
- }
- return &ExecutionPayloadEnvelope{ExecutionPayload: data, BlockValue: fees, BlobsBundle: &bundle, Override: false}
-}
-
-// ExecutionPayloadBodyV1 is used in the response to GetPayloadBodiesByHashV1 and GetPayloadBodiesByRangeV1
-type ExecutionPayloadBodyV1 struct {
- TransactionData []hexutil.Bytes `json:"transactions"`
- Withdrawals []*types.Withdrawal `json:"withdrawals"`
-}
diff --git a/beacon/light/canonical.go b/beacon/light/canonical.go
deleted file mode 100644
index b5371493b4..0000000000
--- a/beacon/light/canonical.go
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright 2023 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package light
-
-import (
- "encoding/binary"
- "fmt"
-
- "github.com/ethereum/go-ethereum/common/lru"
- "github.com/ethereum/go-ethereum/ethdb"
- "github.com/ethereum/go-ethereum/log"
- "github.com/ethereum/go-ethereum/rlp"
-)
-
-// canonicalStore stores instances of the given type in a database and caches
-// them in memory, associated with a continuous range of period numbers.
-// Note: canonicalStore is not thread safe and it is the caller's responsibility
-// to avoid concurrent access.
-type canonicalStore[T any] struct {
- keyPrefix []byte
- periods periodRange
- cache *lru.Cache[uint64, T]
-}
-
-// newCanonicalStore creates a new canonicalStore and loads all keys associated
-// with the keyPrefix in order to determine the ranges available in the database.
-func newCanonicalStore[T any](db ethdb.Iteratee, keyPrefix []byte) (*canonicalStore[T], error) {
- cs := &canonicalStore[T]{
- keyPrefix: keyPrefix,
- cache: lru.NewCache[uint64, T](100),
- }
- var (
- iter = db.NewIterator(keyPrefix, nil)
- kl = len(keyPrefix)
- first = true
- )
- defer iter.Release()
-
- for iter.Next() {
- if len(iter.Key()) != kl+8 {
- log.Warn("Invalid key length in the canonical chain database", "key", fmt.Sprintf("%#x", iter.Key()))
- continue
- }
- period := binary.BigEndian.Uint64(iter.Key()[kl : kl+8])
- if first {
- cs.periods.Start = period
- } else if cs.periods.End != period {
- return nil, fmt.Errorf("gap in the canonical chain database between periods %d and %d", cs.periods.End, period-1)
- }
- first = false
- cs.periods.End = period + 1
- }
- return cs, nil
-}
-
-// databaseKey returns the database key belonging to the given period.
-func (cs *canonicalStore[T]) databaseKey(period uint64) []byte {
- return binary.BigEndian.AppendUint64(append([]byte{}, cs.keyPrefix...), period)
-}
-
-// add adds the given item to the database. It also ensures that the range remains
-// continuous. Can be used either with a batch or database backend.
-func (cs *canonicalStore[T]) add(backend ethdb.KeyValueWriter, period uint64, value T) error {
- if !cs.periods.canExpand(period) {
- return fmt.Errorf("period expansion is not allowed, first: %d, next: %d, period: %d", cs.periods.Start, cs.periods.End, period)
- }
- enc, err := rlp.EncodeToBytes(value)
- if err != nil {
- return err
- }
- if err := backend.Put(cs.databaseKey(period), enc); err != nil {
- return err
- }
- cs.cache.Add(period, value)
- cs.periods.expand(period)
- return nil
-}
-
-// deleteFrom removes items starting from the given period.
-func (cs *canonicalStore[T]) deleteFrom(db ethdb.KeyValueWriter, fromPeriod uint64) (deleted periodRange) {
- keepRange, deleteRange := cs.periods.split(fromPeriod)
- deleteRange.each(func(period uint64) {
- db.Delete(cs.databaseKey(period))
- cs.cache.Remove(period)
- })
- cs.periods = keepRange
- return deleteRange
-}
-
-// get returns the item at the given period or the null value of the given type
-// if no item is present.
-func (cs *canonicalStore[T]) get(backend ethdb.KeyValueReader, period uint64) (T, bool) {
- var null, value T
- if !cs.periods.contains(period) {
- return null, false
- }
- if value, ok := cs.cache.Get(period); ok {
- return value, true
- }
- enc, err := backend.Get(cs.databaseKey(period))
- if err != nil {
- log.Error("Canonical store value not found", "period", period, "start", cs.periods.Start, "end", cs.periods.End)
- return null, false
- }
- if err := rlp.DecodeBytes(enc, &value); err != nil {
- log.Error("Error decoding canonical store value", "error", err)
- return null, false
- }
- cs.cache.Add(period, value)
- return value, true
-}
diff --git a/beacon/light/committee_chain.go b/beacon/light/committee_chain.go
deleted file mode 100644
index d707f8cc34..0000000000
--- a/beacon/light/committee_chain.go
+++ /dev/null
@@ -1,514 +0,0 @@
-// Copyright 2023 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package light
-
-import (
- "errors"
- "fmt"
- "math"
- "sync"
- "time"
-
- "github.com/ethereum/go-ethereum/beacon/params"
- "github.com/ethereum/go-ethereum/beacon/types"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/lru"
- "github.com/ethereum/go-ethereum/common/mclock"
- "github.com/ethereum/go-ethereum/core/rawdb"
- "github.com/ethereum/go-ethereum/ethdb"
- "github.com/ethereum/go-ethereum/log"
-)
-
-var (
- ErrNeedCommittee = errors.New("sync committee required")
- ErrInvalidUpdate = errors.New("invalid committee update")
- ErrInvalidPeriod = errors.New("invalid update period")
- ErrWrongCommitteeRoot = errors.New("wrong committee root")
- ErrCannotReorg = errors.New("can not reorg committee chain")
-)
-
-// CommitteeChain is a passive data structure that can validate, hold and update
-// a chain of beacon light sync committees and updates. It requires at least one
-// externally set fixed committee root at the beginning of the chain which can
-// be set either based on a BootstrapData or a trusted source (a local beacon
-// full node). This makes the structure useful for both light client and light
-// server setups.
-//
-// It always maintains the following consistency constraints:
-// - a committee can only be present if its root hash matches an existing fixed
-// root or if it is proven by an update at the previous period
-// - an update can only be present if a committee is present at the same period
-// and the update signature is valid and has enough participants.
-// The committee at the next period (proven by the update) should also be
-// present (note that this means they can only be added together if neither
-// is present yet). If a fixed root is present at the next period then the
-// update can only be present if it proves the same committee root.
-//
-// Once synced to the current sync period, CommitteeChain can also validate
-// signed beacon headers.
-type CommitteeChain struct {
- // chainmu guards against concurrent access to the canonicalStore structures
- // (updates, committees, fixedCommitteeRoots) and ensures that they stay consistent
- // with each other and with committeeCache.
- chainmu sync.RWMutex
- db ethdb.KeyValueStore
- updates *canonicalStore[*types.LightClientUpdate]
- committees *canonicalStore[*types.SerializedSyncCommittee]
- fixedCommitteeRoots *canonicalStore[common.Hash]
- committeeCache *lru.Cache[uint64, syncCommittee] // cache deserialized committees
-
- clock mclock.Clock // monotonic clock (simulated clock in tests)
- unixNano func() int64 // system clock (simulated clock in tests)
- sigVerifier committeeSigVerifier // BLS sig verifier (dummy verifier in tests)
-
- config *types.ChainConfig
- signerThreshold int
- minimumUpdateScore types.UpdateScore
- enforceTime bool // enforceTime specifies whether the age of a signed header should be checked
-}
-
-// NewCommitteeChain creates a new CommitteeChain.
-func NewCommitteeChain(db ethdb.KeyValueStore, config *types.ChainConfig, signerThreshold int, enforceTime bool) *CommitteeChain {
- return newCommitteeChain(db, config, signerThreshold, enforceTime, blsVerifier{}, &mclock.System{}, func() int64 { return time.Now().UnixNano() })
-}
-
-// newCommitteeChain creates a new CommitteeChain with the option of replacing the
-// clock source and signature verification for testing purposes.
-func newCommitteeChain(db ethdb.KeyValueStore, config *types.ChainConfig, signerThreshold int, enforceTime bool, sigVerifier committeeSigVerifier, clock mclock.Clock, unixNano func() int64) *CommitteeChain {
- s := &CommitteeChain{
- committeeCache: lru.NewCache[uint64, syncCommittee](10),
- db: db,
- sigVerifier: sigVerifier,
- clock: clock,
- unixNano: unixNano,
- config: config,
- signerThreshold: signerThreshold,
- enforceTime: enforceTime,
- minimumUpdateScore: types.UpdateScore{
- SignerCount: uint32(signerThreshold),
- SubPeriodIndex: params.SyncPeriodLength / 16,
- },
- }
-
- var err1, err2, err3 error
- if s.fixedCommitteeRoots, err1 = newCanonicalStore[common.Hash](db, rawdb.FixedCommitteeRootKey); err1 != nil {
- log.Error("Error creating fixed committee root store", "error", err1)
- }
- if s.committees, err2 = newCanonicalStore[*types.SerializedSyncCommittee](db, rawdb.SyncCommitteeKey); err2 != nil {
- log.Error("Error creating committee store", "error", err2)
- }
- if s.updates, err3 = newCanonicalStore[*types.LightClientUpdate](db, rawdb.BestUpdateKey); err3 != nil {
- log.Error("Error creating update store", "error", err3)
- }
- if err1 != nil || err2 != nil || err3 != nil || !s.checkConstraints() {
- log.Info("Resetting invalid committee chain")
- s.Reset()
- }
- // roll back invalid updates (might be necessary if forks have been changed since last time)
- for !s.updates.periods.isEmpty() {
- update, ok := s.updates.get(s.db, s.updates.periods.End-1)
- if !ok {
- log.Error("Sync committee update missing", "period", s.updates.periods.End-1)
- s.Reset()
- break
- }
- if valid, err := s.verifyUpdate(update); err != nil {
- log.Error("Error validating update", "period", s.updates.periods.End-1, "error", err)
- } else if valid {
- break
- }
- if err := s.rollback(s.updates.periods.End); err != nil {
- log.Error("Error writing batch into chain database", "error", err)
- }
- }
- if !s.committees.periods.isEmpty() {
- log.Trace("Sync committee chain loaded", "first period", s.committees.periods.Start, "last period", s.committees.periods.End-1)
- }
- return s
-}
-
-// checkConstraints checks committee chain validity constraints
-func (s *CommitteeChain) checkConstraints() bool {
- isNotInFixedCommitteeRootRange := func(r periodRange) bool {
- return s.fixedCommitteeRoots.periods.isEmpty() ||
- r.Start < s.fixedCommitteeRoots.periods.Start ||
- r.Start >= s.fixedCommitteeRoots.periods.End
- }
-
- valid := true
- if !s.updates.periods.isEmpty() {
- if isNotInFixedCommitteeRootRange(s.updates.periods) {
- log.Error("Start update is not in the fixed roots range")
- valid = false
- }
- if s.committees.periods.Start > s.updates.periods.Start || s.committees.periods.End <= s.updates.periods.End {
- log.Error("Missing committees in update range")
- valid = false
- }
- }
- if !s.committees.periods.isEmpty() {
- if isNotInFixedCommitteeRootRange(s.committees.periods) {
- log.Error("Start committee is not in the fixed roots range")
- valid = false
- }
- if s.committees.periods.End > s.fixedCommitteeRoots.periods.End && s.committees.periods.End > s.updates.periods.End+1 {
- log.Error("Last committee is neither in the fixed roots range nor proven by updates")
- valid = false
- }
- }
- return valid
-}
-
-// Reset resets the committee chain.
-func (s *CommitteeChain) Reset() {
- s.chainmu.Lock()
- defer s.chainmu.Unlock()
-
- if err := s.rollback(0); err != nil {
- log.Error("Error writing batch into chain database", "error", err)
- }
-}
-
-// CheckpointInit initializes a CommitteeChain based on the checkpoint.
-// Note: if the chain is already initialized and the committees proven by the
-// checkpoint do match the existing chain then the chain is retained and the
-// new checkpoint becomes fixed.
-func (s *CommitteeChain) CheckpointInit(bootstrap *types.BootstrapData) error {
- s.chainmu.Lock()
- defer s.chainmu.Unlock()
-
- if err := bootstrap.Validate(); err != nil {
- return err
- }
-
- period := bootstrap.Header.SyncPeriod()
- if err := s.deleteFixedCommitteeRootsFrom(period + 2); err != nil {
- s.Reset()
- return err
- }
- if s.addFixedCommitteeRoot(period, bootstrap.CommitteeRoot) != nil {
- s.Reset()
- if err := s.addFixedCommitteeRoot(period, bootstrap.CommitteeRoot); err != nil {
- s.Reset()
- return err
- }
- }
- if err := s.addFixedCommitteeRoot(period+1, common.Hash(bootstrap.CommitteeBranch[0])); err != nil {
- s.Reset()
- return err
- }
- if err := s.addCommittee(period, bootstrap.Committee); err != nil {
- s.Reset()
- return err
- }
- return nil
-}
-
-// addFixedCommitteeRoot sets a fixed committee root at the given period.
-// Note that the period where the first committee is added has to have a fixed
-// root which can either come from a BootstrapData or a trusted source.
-func (s *CommitteeChain) addFixedCommitteeRoot(period uint64, root common.Hash) error {
- if root == (common.Hash{}) {
- return ErrWrongCommitteeRoot
- }
-
- batch := s.db.NewBatch()
- oldRoot := s.getCommitteeRoot(period)
- if !s.fixedCommitteeRoots.periods.canExpand(period) {
- // Note: the fixed committee root range should always be continuous and
- // therefore the expected syncing method is to forward sync and optionally
- // backward sync periods one by one, starting from a checkpoint. The only
- // case when a root that is not adjacent to the already fixed ones can be
- // fixed is when the same root has already been proven by an update chain.
- // In this case the all roots in between can and should be fixed.
- // This scenario makes sense when a new trusted checkpoint is added to an
- // existing chain, ensuring that it will not be rolled back (might be
- // important in case of low signer participation rate).
- if root != oldRoot {
- return ErrInvalidPeriod
- }
- // if the old root exists and matches the new one then it is guaranteed
- // that the given period is after the existing fixed range and the roots
- // in between can also be fixed.
- for p := s.fixedCommitteeRoots.periods.End; p < period; p++ {
- if err := s.fixedCommitteeRoots.add(batch, p, s.getCommitteeRoot(p)); err != nil {
- return err
- }
- }
- }
- if oldRoot != (common.Hash{}) && (oldRoot != root) {
- // existing old root was different, we have to reorg the chain
- if err := s.rollback(period); err != nil {
- return err
- }
- }
- if err := s.fixedCommitteeRoots.add(batch, period, root); err != nil {
- return err
- }
- if err := batch.Write(); err != nil {
- log.Error("Error writing batch into chain database", "error", err)
- return err
- }
- return nil
-}
-
-// deleteFixedCommitteeRootsFrom deletes fixed roots starting from the given period.
-// It also maintains chain consistency, meaning that it also deletes updates and
-// committees if they are no longer supported by a valid update chain.
-func (s *CommitteeChain) deleteFixedCommitteeRootsFrom(period uint64) error {
- if period >= s.fixedCommitteeRoots.periods.End {
- return nil
- }
- batch := s.db.NewBatch()
- s.fixedCommitteeRoots.deleteFrom(batch, period)
- if s.updates.periods.isEmpty() || period <= s.updates.periods.Start {
- // Note: the first period of the update chain should always be fixed so if
- // the fixed root at the first update is removed then the entire update chain
- // and the proven committees have to be removed. Earlier committees in the
- // remaining fixed root range can stay.
- s.updates.deleteFrom(batch, period)
- s.deleteCommitteesFrom(batch, period)
- } else {
- // The update chain stays intact, some previously fixed committee roots might
- // get unfixed but are still proven by the update chain. If there were
- // committees present after the range proven by updates, those should be
- // removed if the belonging fixed roots are also removed.
- fromPeriod := s.updates.periods.End + 1 // not proven by updates
- if period > fromPeriod {
- fromPeriod = period // also not justified by fixed roots
- }
- s.deleteCommitteesFrom(batch, fromPeriod)
- }
- if err := batch.Write(); err != nil {
- log.Error("Error writing batch into chain database", "error", err)
- return err
- }
- return nil
-}
-
-// deleteCommitteesFrom deletes committees starting from the given period.
-func (s *CommitteeChain) deleteCommitteesFrom(batch ethdb.Batch, period uint64) {
- deleted := s.committees.deleteFrom(batch, period)
- for period := deleted.Start; period < deleted.End; period++ {
- s.committeeCache.Remove(period)
- }
-}
-
-// addCommittee adds a committee at the given period if possible.
-func (s *CommitteeChain) addCommittee(period uint64, committee *types.SerializedSyncCommittee) error {
- if !s.committees.periods.canExpand(period) {
- return ErrInvalidPeriod
- }
- root := s.getCommitteeRoot(period)
- if root == (common.Hash{}) {
- return ErrInvalidPeriod
- }
- if root != committee.Root() {
- return ErrWrongCommitteeRoot
- }
- if !s.committees.periods.contains(period) {
- if err := s.committees.add(s.db, period, committee); err != nil {
- return err
- }
- s.committeeCache.Remove(period)
- }
- return nil
-}
-
-// InsertUpdate adds a new update if possible.
-func (s *CommitteeChain) InsertUpdate(update *types.LightClientUpdate, nextCommittee *types.SerializedSyncCommittee) error {
- s.chainmu.Lock()
- defer s.chainmu.Unlock()
-
- period := update.AttestedHeader.Header.SyncPeriod()
- if !s.updates.periods.canExpand(period) || !s.committees.periods.contains(period) {
- return ErrInvalidPeriod
- }
- if s.minimumUpdateScore.BetterThan(update.Score()) {
- return ErrInvalidUpdate
- }
- oldRoot := s.getCommitteeRoot(period + 1)
- reorg := oldRoot != (common.Hash{}) && oldRoot != update.NextSyncCommitteeRoot
- if oldUpdate, ok := s.updates.get(s.db, period); ok && !update.Score().BetterThan(oldUpdate.Score()) {
- // a better or equal update already exists; no changes, only fail if new one tried to reorg
- if reorg {
- return ErrCannotReorg
- }
- return nil
- }
- if s.fixedCommitteeRoots.periods.contains(period+1) && reorg {
- return ErrCannotReorg
- }
- if ok, err := s.verifyUpdate(update); err != nil {
- return err
- } else if !ok {
- return ErrInvalidUpdate
- }
- addCommittee := !s.committees.periods.contains(period+1) || reorg
- if addCommittee {
- if nextCommittee == nil {
- return ErrNeedCommittee
- }
- if nextCommittee.Root() != update.NextSyncCommitteeRoot {
- return ErrWrongCommitteeRoot
- }
- }
- if reorg {
- if err := s.rollback(period + 1); err != nil {
- return err
- }
- }
- batch := s.db.NewBatch()
- if addCommittee {
- if err := s.committees.add(batch, period+1, nextCommittee); err != nil {
- return err
- }
- s.committeeCache.Remove(period + 1)
- }
- if err := s.updates.add(batch, period, update); err != nil {
- return err
- }
- if err := batch.Write(); err != nil {
- log.Error("Error writing batch into chain database", "error", err)
- return err
- }
- log.Info("Inserted new committee update", "period", period, "next committee root", update.NextSyncCommitteeRoot)
- return nil
-}
-
-// NextSyncPeriod returns the next period where an update can be added and also
-// whether the chain is initialized at all.
-func (s *CommitteeChain) NextSyncPeriod() (uint64, bool) {
- s.chainmu.RLock()
- defer s.chainmu.RUnlock()
-
- if s.committees.periods.isEmpty() {
- return 0, false
- }
- if !s.updates.periods.isEmpty() {
- return s.updates.periods.End, true
- }
- return s.committees.periods.End - 1, true
-}
-
-// rollback removes all committees and fixed roots from the given period and updates
-// starting from the previous period.
-func (s *CommitteeChain) rollback(period uint64) error {
- max := s.updates.periods.End + 1
- if s.committees.periods.End > max {
- max = s.committees.periods.End
- }
- if s.fixedCommitteeRoots.periods.End > max {
- max = s.fixedCommitteeRoots.periods.End
- }
- for max > period {
- max--
- batch := s.db.NewBatch()
- s.deleteCommitteesFrom(batch, max)
- s.fixedCommitteeRoots.deleteFrom(batch, max)
- if max > 0 {
- s.updates.deleteFrom(batch, max-1)
- }
- if err := batch.Write(); err != nil {
- log.Error("Error writing batch into chain database", "error", err)
- return err
- }
- }
- return nil
-}
-
-// getCommitteeRoot returns the committee root at the given period, either fixed,
-// proven by a previous update or both. It returns an empty hash if the committee
-// root is unknown.
-func (s *CommitteeChain) getCommitteeRoot(period uint64) common.Hash {
- if root, ok := s.fixedCommitteeRoots.get(s.db, period); ok || period == 0 {
- return root
- }
- if update, ok := s.updates.get(s.db, period-1); ok {
- return update.NextSyncCommitteeRoot
- }
- return common.Hash{}
-}
-
-// getSyncCommittee returns the deserialized sync committee at the given period.
-func (s *CommitteeChain) getSyncCommittee(period uint64) (syncCommittee, error) {
- if c, ok := s.committeeCache.Get(period); ok {
- return c, nil
- }
- if sc, ok := s.committees.get(s.db, period); ok {
- c, err := s.sigVerifier.deserializeSyncCommittee(sc)
- if err != nil {
- return nil, fmt.Errorf("Sync committee #%d deserialization error: %v", period, err)
- }
- s.committeeCache.Add(period, c)
- return c, nil
- }
- return nil, fmt.Errorf("Missing serialized sync committee #%d", period)
-}
-
-// VerifySignedHeader returns true if the given signed header has a valid signature
-// according to the local committee chain. The caller should ensure that the
-// committees advertised by the same source where the signed header came from are
-// synced before verifying the signature.
-// The age of the header is also returned (the time elapsed since the beginning
-// of the given slot, according to the local system clock). If enforceTime is
-// true then negative age (future) headers are rejected.
-func (s *CommitteeChain) VerifySignedHeader(head types.SignedHeader) (bool, time.Duration, error) {
- s.chainmu.RLock()
- defer s.chainmu.RUnlock()
-
- return s.verifySignedHeader(head)
-}
-
-func (s *CommitteeChain) verifySignedHeader(head types.SignedHeader) (bool, time.Duration, error) {
- var age time.Duration
- now := s.unixNano()
- if head.Header.Slot < (uint64(now-math.MinInt64)/uint64(time.Second)-s.config.GenesisTime)/12 {
- age = time.Duration(now - int64(time.Second)*int64(s.config.GenesisTime+head.Header.Slot*12))
- } else {
- age = time.Duration(math.MinInt64)
- }
- if s.enforceTime && age < 0 {
- return false, age, nil
- }
- committee, err := s.getSyncCommittee(types.SyncPeriod(head.SignatureSlot))
- if err != nil {
- return false, 0, err
- }
- if committee == nil {
- return false, age, nil
- }
- if signingRoot, err := s.config.Forks.SigningRoot(head.Header); err == nil {
- return s.sigVerifier.verifySignature(committee, signingRoot, &head.Signature), age, nil
- }
- return false, age, nil
-}
-
-// verifyUpdate checks whether the header signature is correct and the update
-// fits into the specified constraints (assumes that the update has been
-// successfully validated previously)
-func (s *CommitteeChain) verifyUpdate(update *types.LightClientUpdate) (bool, error) {
- // Note: SignatureSlot determines the sync period of the committee used for signature
- // verification. Though in reality SignatureSlot is always bigger than update.Header.Slot,
- // setting them as equal here enforces the rule that they have to be in the same sync
- // period in order for the light client update proof to be meaningful.
- ok, age, err := s.verifySignedHeader(update.AttestedHeader)
- if age < 0 {
- log.Warn("Future committee update received", "age", age)
- }
- return ok, err
-}
diff --git a/beacon/light/committee_chain_test.go b/beacon/light/committee_chain_test.go
deleted file mode 100644
index 60ea2a0efd..0000000000
--- a/beacon/light/committee_chain_test.go
+++ /dev/null
@@ -1,356 +0,0 @@
-// Copyright 2022 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package light
-
-import (
- "crypto/rand"
- "testing"
- "time"
-
- "github.com/ethereum/go-ethereum/beacon/params"
- "github.com/ethereum/go-ethereum/beacon/types"
- "github.com/ethereum/go-ethereum/common/mclock"
- "github.com/ethereum/go-ethereum/ethdb/memorydb"
-)
-
-var (
- testGenesis = newTestGenesis()
- testGenesis2 = newTestGenesis()
-
- tfBase = newTestForks(testGenesis, types.Forks{
- &types.Fork{Epoch: 0, Version: []byte{0}},
- })
- tfAlternative = newTestForks(testGenesis, types.Forks{
- &types.Fork{Epoch: 0, Version: []byte{0}},
- &types.Fork{Epoch: 0x700, Version: []byte{1}},
- })
- tfAnotherGenesis = newTestForks(testGenesis2, types.Forks{
- &types.Fork{Epoch: 0, Version: []byte{0}},
- })
-
- tcBase = newTestCommitteeChain(nil, tfBase, true, 0, 10, 400, false)
- tcBaseWithInvalidUpdates = newTestCommitteeChain(tcBase, tfBase, false, 5, 10, 200, false) // signer count too low
- tcBaseWithBetterUpdates = newTestCommitteeChain(tcBase, tfBase, false, 5, 10, 440, false)
- tcReorgWithWorseUpdates = newTestCommitteeChain(tcBase, tfBase, true, 5, 10, 400, false)
- tcReorgWithWorseUpdates2 = newTestCommitteeChain(tcBase, tfBase, true, 5, 10, 380, false)
- tcReorgWithBetterUpdates = newTestCommitteeChain(tcBase, tfBase, true, 5, 10, 420, false)
- tcReorgWithFinalizedUpdates = newTestCommitteeChain(tcBase, tfBase, true, 5, 10, 400, true)
- tcFork = newTestCommitteeChain(tcBase, tfAlternative, true, 7, 10, 400, false)
- tcAnotherGenesis = newTestCommitteeChain(nil, tfAnotherGenesis, true, 0, 10, 400, false)
-)
-
-func TestCommitteeChainFixedCommitteeRoots(t *testing.T) {
- for _, reload := range []bool{false, true} {
- c := newCommitteeChainTest(t, tfBase, 300, true)
- c.setClockPeriod(7)
- c.addFixedCommitteeRoot(tcBase, 4, nil)
- c.addFixedCommitteeRoot(tcBase, 5, nil)
- c.addFixedCommitteeRoot(tcBase, 6, nil)
- c.addFixedCommitteeRoot(tcBase, 8, ErrInvalidPeriod) // range has to be continuous
- c.addFixedCommitteeRoot(tcBase, 3, nil)
- c.addFixedCommitteeRoot(tcBase, 2, nil)
- if reload {
- c.reloadChain()
- }
- c.addCommittee(tcBase, 4, nil)
- c.addCommittee(tcBase, 6, ErrInvalidPeriod) // range has to be continuous
- c.addCommittee(tcBase, 5, nil)
- c.addCommittee(tcBase, 6, nil)
- c.addCommittee(tcAnotherGenesis, 3, ErrWrongCommitteeRoot)
- c.addCommittee(tcBase, 3, nil)
- if reload {
- c.reloadChain()
- }
- c.verifyRange(tcBase, 3, 6)
- }
-}
-
-func TestCommitteeChainCheckpointSync(t *testing.T) {
- for _, enforceTime := range []bool{false, true} {
- for _, reload := range []bool{false, true} {
- c := newCommitteeChainTest(t, tfBase, 300, enforceTime)
- if enforceTime {
- c.setClockPeriod(6)
- }
- c.insertUpdate(tcBase, 3, true, ErrInvalidPeriod)
- c.addFixedCommitteeRoot(tcBase, 3, nil)
- c.addFixedCommitteeRoot(tcBase, 4, nil)
- c.insertUpdate(tcBase, 4, true, ErrInvalidPeriod) // still no committee
- c.addCommittee(tcBase, 3, nil)
- c.addCommittee(tcBase, 4, nil)
- if reload {
- c.reloadChain()
- }
- c.verifyRange(tcBase, 3, 4)
- c.insertUpdate(tcBase, 3, false, nil) // update can be added without committee here
- c.insertUpdate(tcBase, 4, false, ErrNeedCommittee) // but not here as committee 5 is not there yet
- c.insertUpdate(tcBase, 4, true, nil)
- c.verifyRange(tcBase, 3, 5)
- c.insertUpdate(tcBaseWithInvalidUpdates, 5, true, ErrInvalidUpdate) // signer count too low
- c.insertUpdate(tcBase, 5, true, nil)
- if reload {
- c.reloadChain()
- }
- if enforceTime {
- c.insertUpdate(tcBase, 6, true, ErrInvalidUpdate) // future update rejected
- c.setClockPeriod(7)
- }
- c.insertUpdate(tcBase, 6, true, nil) // when the time comes it's accepted
- if reload {
- c.reloadChain()
- }
- if enforceTime {
- c.verifyRange(tcBase, 3, 6) // committee 7 is there but still in the future
- c.setClockPeriod(8)
- }
- c.verifyRange(tcBase, 3, 7) // now period 7 can also be verified
- // try reverse syncing an update
- c.insertUpdate(tcBase, 2, false, ErrInvalidPeriod) // fixed committee is needed first
- c.addFixedCommitteeRoot(tcBase, 2, nil)
- c.addCommittee(tcBase, 2, nil)
- c.insertUpdate(tcBase, 2, false, nil)
- c.verifyRange(tcBase, 2, 7)
- }
- }
-}
-
-func TestCommitteeChainReorg(t *testing.T) {
- for _, reload := range []bool{false, true} {
- for _, addBetterUpdates := range []bool{false, true} {
- c := newCommitteeChainTest(t, tfBase, 300, true)
- c.setClockPeriod(11)
- c.addFixedCommitteeRoot(tcBase, 3, nil)
- c.addFixedCommitteeRoot(tcBase, 4, nil)
- c.addCommittee(tcBase, 3, nil)
- for period := uint64(3); period < 10; period++ {
- c.insertUpdate(tcBase, period, true, nil)
- }
- if reload {
- c.reloadChain()
- }
- c.verifyRange(tcBase, 3, 10)
- c.insertUpdate(tcReorgWithWorseUpdates, 5, true, ErrCannotReorg)
- c.insertUpdate(tcReorgWithWorseUpdates2, 5, true, ErrCannotReorg)
- if addBetterUpdates {
- // add better updates for the base chain and expect first reorg to fail
- // (only add updates as committees should be the same)
- for period := uint64(5); period < 10; period++ {
- c.insertUpdate(tcBaseWithBetterUpdates, period, false, nil)
- }
- if reload {
- c.reloadChain()
- }
- c.verifyRange(tcBase, 3, 10) // still on the same chain
- c.insertUpdate(tcReorgWithBetterUpdates, 5, true, ErrCannotReorg)
- } else {
- // reorg with better updates
- c.insertUpdate(tcReorgWithBetterUpdates, 5, false, ErrNeedCommittee)
- c.verifyRange(tcBase, 3, 10) // no success yet, still on the base chain
- c.verifyRange(tcReorgWithBetterUpdates, 3, 5)
- c.insertUpdate(tcReorgWithBetterUpdates, 5, true, nil)
- // successful reorg, base chain should only match before the reorg period
- if reload {
- c.reloadChain()
- }
- c.verifyRange(tcBase, 3, 5)
- c.verifyRange(tcReorgWithBetterUpdates, 3, 6)
- for period := uint64(6); period < 10; period++ {
- c.insertUpdate(tcReorgWithBetterUpdates, period, true, nil)
- }
- c.verifyRange(tcReorgWithBetterUpdates, 3, 10)
- }
- // reorg with finalized updates; should succeed even if base chain updates
- // have been improved because a finalized update beats everything else
- c.insertUpdate(tcReorgWithFinalizedUpdates, 5, false, ErrNeedCommittee)
- c.insertUpdate(tcReorgWithFinalizedUpdates, 5, true, nil)
- if reload {
- c.reloadChain()
- }
- c.verifyRange(tcReorgWithFinalizedUpdates, 3, 6)
- for period := uint64(6); period < 10; period++ {
- c.insertUpdate(tcReorgWithFinalizedUpdates, period, true, nil)
- }
- c.verifyRange(tcReorgWithFinalizedUpdates, 3, 10)
- }
- }
-}
-
-func TestCommitteeChainFork(t *testing.T) {
- c := newCommitteeChainTest(t, tfAlternative, 300, true)
- c.setClockPeriod(11)
- // trying to sync a chain on an alternative fork with the base chain data
- c.addFixedCommitteeRoot(tcBase, 0, nil)
- c.addFixedCommitteeRoot(tcBase, 1, nil)
- c.addCommittee(tcBase, 0, nil)
- // shared section should sync without errors
- for period := uint64(0); period < 7; period++ {
- c.insertUpdate(tcBase, period, true, nil)
- }
- c.insertUpdate(tcBase, 7, true, ErrInvalidUpdate) // wrong fork
- // committee root #7 is still the same but signatures are already signed with
- // a different fork id so period 7 should only verify on the alternative fork
- c.verifyRange(tcBase, 0, 6)
- c.verifyRange(tcFork, 0, 7)
- for period := uint64(7); period < 10; period++ {
- c.insertUpdate(tcFork, period, true, nil)
- }
- c.verifyRange(tcFork, 0, 10)
- // reload the chain while switching to the base fork
- c.config = tfBase
- c.reloadChain()
- // updates 7..9 should be rolled back now
- c.verifyRange(tcFork, 0, 6) // again, period 7 only verifies on the right fork
- c.verifyRange(tcBase, 0, 7)
- c.insertUpdate(tcFork, 7, true, ErrInvalidUpdate) // wrong fork
- for period := uint64(7); period < 10; period++ {
- c.insertUpdate(tcBase, period, true, nil)
- }
- c.verifyRange(tcBase, 0, 10)
-}
-
-type committeeChainTest struct {
- t *testing.T
- db *memorydb.Database
- clock *mclock.Simulated
- config types.ChainConfig
- signerThreshold int
- enforceTime bool
- chain *CommitteeChain
-}
-
-func newCommitteeChainTest(t *testing.T, config types.ChainConfig, signerThreshold int, enforceTime bool) *committeeChainTest {
- c := &committeeChainTest{
- t: t,
- db: memorydb.New(),
- clock: &mclock.Simulated{},
- config: config,
- signerThreshold: signerThreshold,
- enforceTime: enforceTime,
- }
- c.chain = newCommitteeChain(c.db, &config, signerThreshold, enforceTime, dummyVerifier{}, c.clock, func() int64 { return int64(c.clock.Now()) })
- return c
-}
-
-func (c *committeeChainTest) reloadChain() {
- c.chain = newCommitteeChain(c.db, &c.config, c.signerThreshold, c.enforceTime, dummyVerifier{}, c.clock, func() int64 { return int64(c.clock.Now()) })
-}
-
-func (c *committeeChainTest) setClockPeriod(period float64) {
- target := mclock.AbsTime(period * float64(time.Second*12*params.SyncPeriodLength))
- wait := time.Duration(target - c.clock.Now())
- if wait < 0 {
- c.t.Fatalf("Invalid setClockPeriod")
- }
- c.clock.Run(wait)
-}
-
-func (c *committeeChainTest) addFixedCommitteeRoot(tc *testCommitteeChain, period uint64, expErr error) {
- if err := c.chain.addFixedCommitteeRoot(period, tc.periods[period].committee.Root()); err != expErr {
- c.t.Errorf("Incorrect error output from addFixedCommitteeRoot at period %d (expected %v, got %v)", period, expErr, err)
- }
-}
-
-func (c *committeeChainTest) addCommittee(tc *testCommitteeChain, period uint64, expErr error) {
- if err := c.chain.addCommittee(period, tc.periods[period].committee); err != expErr {
- c.t.Errorf("Incorrect error output from addCommittee at period %d (expected %v, got %v)", period, expErr, err)
- }
-}
-
-func (c *committeeChainTest) insertUpdate(tc *testCommitteeChain, period uint64, addCommittee bool, expErr error) {
- var committee *types.SerializedSyncCommittee
- if addCommittee {
- committee = tc.periods[period+1].committee
- }
- if err := c.chain.InsertUpdate(tc.periods[period].update, committee); err != expErr {
- c.t.Errorf("Incorrect error output from InsertUpdate at period %d (expected %v, got %v)", period, expErr, err)
- }
-}
-
-func (c *committeeChainTest) verifySignedHeader(tc *testCommitteeChain, period float64, expOk bool) {
- slot := uint64(period * float64(params.SyncPeriodLength))
- signedHead := GenerateTestSignedHeader(types.Header{Slot: slot}, &tc.config, tc.periods[types.SyncPeriod(slot)].committee, slot+1, 400)
- if ok, _, _ := c.chain.VerifySignedHeader(signedHead); ok != expOk {
- c.t.Errorf("Incorrect output from VerifySignedHeader at period %f (expected %v, got %v)", period, expOk, ok)
- }
-}
-
-func (c *committeeChainTest) verifyRange(tc *testCommitteeChain, begin, end uint64) {
- if begin > 0 {
- c.verifySignedHeader(tc, float64(begin)-0.5, false)
- }
- for period := begin; period <= end; period++ {
- c.verifySignedHeader(tc, float64(period)+0.5, true)
- }
- c.verifySignedHeader(tc, float64(end)+1.5, false)
-}
-
-func newTestGenesis() types.ChainConfig {
- var config types.ChainConfig
- rand.Read(config.GenesisValidatorsRoot[:])
- return config
-}
-
-func newTestForks(config types.ChainConfig, forks types.Forks) types.ChainConfig {
- for _, fork := range forks {
- config.AddFork(fork.Name, fork.Epoch, fork.Version)
- }
- return config
-}
-
-func newTestCommitteeChain(parent *testCommitteeChain, config types.ChainConfig, newCommittees bool, begin, end int, signerCount int, finalizedHeader bool) *testCommitteeChain {
- tc := &testCommitteeChain{
- config: config,
- }
- if parent != nil {
- tc.periods = make([]testPeriod, len(parent.periods))
- copy(tc.periods, parent.periods)
- }
- if newCommittees {
- if begin == 0 {
- tc.fillCommittees(begin, end+1)
- } else {
- tc.fillCommittees(begin+1, end+1)
- }
- }
- tc.fillUpdates(begin, end, signerCount, finalizedHeader)
- return tc
-}
-
-type testPeriod struct {
- committee *types.SerializedSyncCommittee
- update *types.LightClientUpdate
-}
-
-type testCommitteeChain struct {
- periods []testPeriod
- config types.ChainConfig
-}
-
-func (tc *testCommitteeChain) fillCommittees(begin, end int) {
- if len(tc.periods) <= end {
- tc.periods = append(tc.periods, make([]testPeriod, end+1-len(tc.periods))...)
- }
- for i := begin; i <= end; i++ {
- tc.periods[i].committee = GenerateTestCommittee()
- }
-}
-
-func (tc *testCommitteeChain) fillUpdates(begin, end int, signerCount int, finalizedHeader bool) {
- for i := begin; i <= end; i++ {
- tc.periods[i].update = GenerateTestUpdate(&tc.config, uint64(i), tc.periods[i].committee, tc.periods[i+1].committee, signerCount, finalizedHeader)
- }
-}
diff --git a/beacon/light/range.go b/beacon/light/range.go
deleted file mode 100644
index 76ebe2381a..0000000000
--- a/beacon/light/range.go
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2023 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package light
-
-// periodRange represents a (possibly zero-length) range of integers (sync periods).
-type periodRange struct {
- Start, End uint64
-}
-
-// isEmpty returns true if the length of the range is zero.
-func (a periodRange) isEmpty() bool {
- return a.End == a.Start
-}
-
-// contains returns true if the range includes the given period.
-func (a periodRange) contains(period uint64) bool {
- return period >= a.Start && period < a.End
-}
-
-// canExpand returns true if the range includes or can be expanded with the given
-// period (either the range is empty or the given period is inside, right before or
-// right after the range).
-func (a periodRange) canExpand(period uint64) bool {
- return a.isEmpty() || (period+1 >= a.Start && period <= a.End)
-}
-
-// expand expands the range with the given period.
-// This method assumes that canExpand returned true: otherwise this is a no-op.
-func (a *periodRange) expand(period uint64) {
- if a.isEmpty() {
- a.Start, a.End = period, period+1
- return
- }
- if a.Start == period+1 {
- a.Start--
- }
- if a.End == period {
- a.End++
- }
-}
-
-// split splits the range into two ranges. The 'fromPeriod' will be the first
-// element in the second range (if present).
-// The original range is unchanged by this operation
-func (a *periodRange) split(fromPeriod uint64) (periodRange, periodRange) {
- if fromPeriod <= a.Start {
- // First range empty, everything in second range,
- return periodRange{}, *a
- }
- if fromPeriod >= a.End {
- // Second range empty, everything in first range,
- return *a, periodRange{}
- }
- x := periodRange{a.Start, fromPeriod}
- y := periodRange{fromPeriod, a.End}
- return x, y
-}
-
-// each invokes the supplied function fn once per period in range
-func (a *periodRange) each(fn func(uint64)) {
- for p := a.Start; p < a.End; p++ {
- fn(p)
- }
-}
diff --git a/beacon/light/test_helpers.go b/beacon/light/test_helpers.go
deleted file mode 100644
index f537d963a6..0000000000
--- a/beacon/light/test_helpers.go
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright 2023 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package light
-
-import (
- "crypto/rand"
- "crypto/sha256"
- mrand "math/rand"
-
- "github.com/ethereum/go-ethereum/beacon/merkle"
- "github.com/ethereum/go-ethereum/beacon/params"
- "github.com/ethereum/go-ethereum/beacon/types"
- "github.com/ethereum/go-ethereum/common"
-)
-
-func GenerateTestCommittee() *types.SerializedSyncCommittee {
- s := new(types.SerializedSyncCommittee)
- rand.Read(s[:32])
- return s
-}
-
-func GenerateTestUpdate(config *types.ChainConfig, period uint64, committee, nextCommittee *types.SerializedSyncCommittee, signerCount int, finalizedHeader bool) *types.LightClientUpdate {
- update := new(types.LightClientUpdate)
- update.NextSyncCommitteeRoot = nextCommittee.Root()
- var attestedHeader types.Header
- if finalizedHeader {
- update.FinalizedHeader = new(types.Header)
- *update.FinalizedHeader, update.NextSyncCommitteeBranch = makeTestHeaderWithMerkleProof(types.SyncPeriodStart(period)+100, params.StateIndexNextSyncCommittee, merkle.Value(update.NextSyncCommitteeRoot))
- attestedHeader, update.FinalityBranch = makeTestHeaderWithMerkleProof(types.SyncPeriodStart(period)+200, params.StateIndexFinalBlock, merkle.Value(update.FinalizedHeader.Hash()))
- } else {
- attestedHeader, update.NextSyncCommitteeBranch = makeTestHeaderWithMerkleProof(types.SyncPeriodStart(period)+2000, params.StateIndexNextSyncCommittee, merkle.Value(update.NextSyncCommitteeRoot))
- }
- update.AttestedHeader = GenerateTestSignedHeader(attestedHeader, config, committee, attestedHeader.Slot+1, signerCount)
- return update
-}
-
-func GenerateTestSignedHeader(header types.Header, config *types.ChainConfig, committee *types.SerializedSyncCommittee, signatureSlot uint64, signerCount int) types.SignedHeader {
- bitmask := makeBitmask(signerCount)
- signingRoot, _ := config.Forks.SigningRoot(header)
- c, _ := dummyVerifier{}.deserializeSyncCommittee(committee)
- return types.SignedHeader{
- Header: header,
- Signature: types.SyncAggregate{
- Signers: bitmask,
- Signature: makeDummySignature(c.(dummySyncCommittee), signingRoot, bitmask),
- },
- SignatureSlot: signatureSlot,
- }
-}
-
-func GenerateTestCheckpoint(period uint64, committee *types.SerializedSyncCommittee) *types.BootstrapData {
- header, branch := makeTestHeaderWithMerkleProof(types.SyncPeriodStart(period)+200, params.StateIndexSyncCommittee, merkle.Value(committee.Root()))
- return &types.BootstrapData{
- Header: header,
- Committee: committee,
- CommitteeRoot: committee.Root(),
- CommitteeBranch: branch,
- }
-}
-
-func makeBitmask(signerCount int) (bitmask [params.SyncCommitteeBitmaskSize]byte) {
- for i := 0; i < params.SyncCommitteeSize; i++ {
- if mrand.Intn(params.SyncCommitteeSize-i) < signerCount {
- bitmask[i/8] += byte(1) << (i & 7)
- signerCount--
- }
- }
- return
-}
-
-func makeTestHeaderWithMerkleProof(slot, index uint64, value merkle.Value) (types.Header, merkle.Values) {
- var branch merkle.Values
- hasher := sha256.New()
- for index > 1 {
- var proofHash merkle.Value
- rand.Read(proofHash[:])
- hasher.Reset()
- if index&1 == 0 {
- hasher.Write(value[:])
- hasher.Write(proofHash[:])
- } else {
- hasher.Write(proofHash[:])
- hasher.Write(value[:])
- }
- hasher.Sum(value[:0])
- index >>= 1
- branch = append(branch, proofHash)
- }
- return types.Header{Slot: slot, StateRoot: common.Hash(value)}, branch
-}
-
-// syncCommittee holds either a blsSyncCommittee or a fake dummySyncCommittee used for testing
-type syncCommittee interface{}
-
-// committeeSigVerifier verifies sync committee signatures (either proper BLS
-// signatures or fake signatures used for testing)
-type committeeSigVerifier interface {
- deserializeSyncCommittee(s *types.SerializedSyncCommittee) (syncCommittee, error)
- verifySignature(committee syncCommittee, signedRoot common.Hash, aggregate *types.SyncAggregate) bool
-}
-
-// blsVerifier implements committeeSigVerifier
-type blsVerifier struct{}
-
-// deserializeSyncCommittee implements committeeSigVerifier
-func (blsVerifier) deserializeSyncCommittee(s *types.SerializedSyncCommittee) (syncCommittee, error) {
- return s.Deserialize()
-}
-
-// verifySignature implements committeeSigVerifier
-func (blsVerifier) verifySignature(committee syncCommittee, signingRoot common.Hash, aggregate *types.SyncAggregate) bool {
- return committee.(*types.SyncCommittee).VerifySignature(signingRoot, aggregate)
-}
-
-type dummySyncCommittee [32]byte
-
-// dummyVerifier implements committeeSigVerifier
-type dummyVerifier struct{}
-
-// deserializeSyncCommittee implements committeeSigVerifier
-func (dummyVerifier) deserializeSyncCommittee(s *types.SerializedSyncCommittee) (syncCommittee, error) {
- var sc dummySyncCommittee
- copy(sc[:], s[:32])
- return sc, nil
-}
-
-// verifySignature implements committeeSigVerifier
-func (dummyVerifier) verifySignature(committee syncCommittee, signingRoot common.Hash, aggregate *types.SyncAggregate) bool {
- return aggregate.Signature == makeDummySignature(committee.(dummySyncCommittee), signingRoot, aggregate.Signers)
-}
-
-func makeDummySignature(committee dummySyncCommittee, signingRoot common.Hash, bitmask [params.SyncCommitteeBitmaskSize]byte) (sig [params.BLSSignatureSize]byte) {
- for i, b := range committee[:] {
- sig[i] = b ^ signingRoot[i]
- }
- copy(sig[32:], bitmask[:])
- return
-}
diff --git a/beacon/merkle/merkle.go b/beacon/merkle/merkle.go
deleted file mode 100644
index 30896f9b01..0000000000
--- a/beacon/merkle/merkle.go
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2022 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-// Package merkle implements proof verifications in binary merkle trees.
-package merkle
-
-import (
- "crypto/sha256"
- "errors"
- "reflect"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/hexutil"
-)
-
-// Value represents either a 32 byte leaf value or hash node in a binary merkle tree/partial proof.
-type Value [32]byte
-
-// Values represent a series of merkle tree leaves/nodes.
-type Values []Value
-
-var valueT = reflect.TypeOf(Value{})
-
-// UnmarshalJSON parses a merkle value in hex syntax.
-func (m *Value) UnmarshalJSON(input []byte) error {
- return hexutil.UnmarshalFixedJSON(valueT, input, m[:])
-}
-
-// VerifyProof verifies a Merkle proof branch for a single value in a
-// binary Merkle tree (index is a generalized tree index).
-func VerifyProof(root common.Hash, index uint64, branch Values, value Value) error {
- hasher := sha256.New()
- for _, sibling := range branch {
- hasher.Reset()
- if index&1 == 0 {
- hasher.Write(value[:])
- hasher.Write(sibling[:])
- } else {
- hasher.Write(sibling[:])
- hasher.Write(value[:])
- }
- hasher.Sum(value[:0])
- if index >>= 1; index == 0 {
- return errors.New("branch has extra items")
- }
- }
- if index != 1 {
- return errors.New("branch is missing items")
- }
- if common.Hash(value) != root {
- return errors.New("root mismatch")
- }
- return nil
-}
diff --git a/beacon/params/params.go b/beacon/params/params.go
deleted file mode 100644
index ee9feb1acb..0000000000
--- a/beacon/params/params.go
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2022 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package params
-
-const (
- EpochLength = 32
- SyncPeriodLength = 8192
-
- BLSSignatureSize = 96
- BLSPubkeySize = 48
-
- SyncCommitteeSize = 512
- SyncCommitteeBitmaskSize = SyncCommitteeSize / 8
- SyncCommitteeSupermajority = (SyncCommitteeSize*2 + 2) / 3
-)
-
-const (
- StateIndexGenesisTime = 32
- StateIndexGenesisValidators = 33
- StateIndexForkVersion = 141
- StateIndexLatestHeader = 36
- StateIndexBlockRoots = 37
- StateIndexStateRoots = 38
- StateIndexHistoricRoots = 39
- StateIndexFinalBlock = 105
- StateIndexSyncCommittee = 54
- StateIndexNextSyncCommittee = 55
- StateIndexExecPayload = 56
- StateIndexExecHead = 908
-)
diff --git a/beacon/types/committee.go b/beacon/types/committee.go
deleted file mode 100644
index 5f89c27554..0000000000
--- a/beacon/types/committee.go
+++ /dev/null
@@ -1,191 +0,0 @@
-// Copyright 2023 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package types
-
-import (
- "crypto/sha256"
- "encoding/json"
- "fmt"
- "math/bits"
-
- "github.com/ethereum/go-ethereum/beacon/params"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/hexutil"
- bls "github.com/protolambda/bls12-381-util"
-)
-
-// SerializedSyncCommitteeSize is the size of the sync committee plus the
-// aggregate public key.
-const SerializedSyncCommitteeSize = (params.SyncCommitteeSize + 1) * params.BLSPubkeySize
-
-// SerializedSyncCommittee is the serialized version of a sync committee
-// plus the aggregate public key.
-type SerializedSyncCommittee [SerializedSyncCommitteeSize]byte
-
-// jsonSyncCommittee is the JSON representation of a sync committee.
-//
-// See data structure definition here:
-// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/beacon-chain.md#syncaggregate
-type jsonSyncCommittee struct {
- Pubkeys []hexutil.Bytes `json:"pubkeys"`
- Aggregate hexutil.Bytes `json:"aggregate_pubkey"`
-}
-
-// MarshalJSON implements json.Marshaler.
-func (s *SerializedSyncCommittee) MarshalJSON() ([]byte, error) {
- sc := jsonSyncCommittee{Pubkeys: make([]hexutil.Bytes, params.SyncCommitteeSize)}
- for i := range sc.Pubkeys {
- sc.Pubkeys[i] = make(hexutil.Bytes, params.BLSPubkeySize)
- copy(sc.Pubkeys[i][:], s[i*params.BLSPubkeySize:(i+1)*params.BLSPubkeySize])
- }
- sc.Aggregate = make(hexutil.Bytes, params.BLSPubkeySize)
- copy(sc.Aggregate[:], s[params.SyncCommitteeSize*params.BLSPubkeySize:])
- return json.Marshal(&sc)
-}
-
-// UnmarshalJSON implements json.Marshaler.
-func (s *SerializedSyncCommittee) UnmarshalJSON(input []byte) error {
- var sc jsonSyncCommittee
- if err := json.Unmarshal(input, &sc); err != nil {
- return err
- }
- if len(sc.Pubkeys) != params.SyncCommitteeSize {
- return fmt.Errorf("invalid number of pubkeys %d", len(sc.Pubkeys))
- }
- for i, key := range sc.Pubkeys {
- if len(key) != params.BLSPubkeySize {
- return fmt.Errorf("pubkey %d has invalid size %d", i, len(key))
- }
- copy(s[i*params.BLSPubkeySize:], key[:])
- }
- if len(sc.Aggregate) != params.BLSPubkeySize {
- return fmt.Errorf("invalid aggregate pubkey size %d", len(sc.Aggregate))
- }
- copy(s[params.SyncCommitteeSize*params.BLSPubkeySize:], sc.Aggregate[:])
- return nil
-}
-
-// Root calculates the root hash of the binary tree representation of a sync
-// committee provided in serialized format.
-//
-// TODO(zsfelfoldi): Get rid of this when SSZ encoding lands.
-func (s *SerializedSyncCommittee) Root() common.Hash {
- var (
- hasher = sha256.New()
- padding [64 - params.BLSPubkeySize]byte
- data [params.SyncCommitteeSize]common.Hash
- l = params.SyncCommitteeSize
- )
- for i := range data {
- hasher.Reset()
- hasher.Write(s[i*params.BLSPubkeySize : (i+1)*params.BLSPubkeySize])
- hasher.Write(padding[:])
- hasher.Sum(data[i][:0])
- }
- for l > 1 {
- for i := 0; i < l/2; i++ {
- hasher.Reset()
- hasher.Write(data[i*2][:])
- hasher.Write(data[i*2+1][:])
- hasher.Sum(data[i][:0])
- }
- l /= 2
- }
- hasher.Reset()
- hasher.Write(s[SerializedSyncCommitteeSize-params.BLSPubkeySize : SerializedSyncCommitteeSize])
- hasher.Write(padding[:])
- hasher.Sum(data[1][:0])
- hasher.Reset()
- hasher.Write(data[0][:])
- hasher.Write(data[1][:])
- hasher.Sum(data[0][:0])
- return data[0]
-}
-
-// Deserialize splits open the pubkeys into proper BLS key types.
-func (s *SerializedSyncCommittee) Deserialize() (*SyncCommittee, error) {
- sc := new(SyncCommittee)
- for i := 0; i <= params.SyncCommitteeSize; i++ {
- key := new(bls.Pubkey)
-
- var bytes [params.BLSPubkeySize]byte
- copy(bytes[:], s[i*params.BLSPubkeySize:(i+1)*params.BLSPubkeySize])
-
- if err := key.Deserialize(&bytes); err != nil {
- return nil, err
- }
- if i < params.SyncCommitteeSize {
- sc.keys[i] = key
- } else {
- sc.aggregate = key
- }
- }
- return sc, nil
-}
-
-// SyncCommittee is a set of sync committee signer pubkeys and the aggregate key.
-//
-// See data structure definition here:
-// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/beacon-chain.md#syncaggregate
-type SyncCommittee struct {
- keys [params.SyncCommitteeSize]*bls.Pubkey
- aggregate *bls.Pubkey
-}
-
-// VerifySignature returns true if the given sync aggregate is a valid signature
-// or the given hash.
-func (sc *SyncCommittee) VerifySignature(signingRoot common.Hash, signature *SyncAggregate) bool {
- var (
- sig bls.Signature
- keys = make([]*bls.Pubkey, 0, params.SyncCommitteeSize)
- )
- if err := sig.Deserialize(&signature.Signature); err != nil {
- return false
- }
- for i, key := range sc.keys {
- if signature.Signers[i/8]&(byte(1)<<(i%8)) != 0 {
- keys = append(keys, key)
- }
- }
- return bls.FastAggregateVerify(keys, signingRoot[:], &sig)
-}
-
-//go:generate go run github.com/fjl/gencodec -type SyncAggregate -field-override syncAggregateMarshaling -out gen_syncaggregate_json.go
-
-// SyncAggregate represents an aggregated BLS signature with Signers referring
-// to a subset of the corresponding sync committee.
-//
-// See data structure definition here:
-// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/beacon-chain.md#syncaggregate
-type SyncAggregate struct {
- Signers [params.SyncCommitteeBitmaskSize]byte `gencodec:"required" json:"sync_committee_bits"`
- Signature [params.BLSSignatureSize]byte `gencodec:"required" json:"sync_committee_signature"`
-}
-
-type syncAggregateMarshaling struct {
- Signers hexutil.Bytes
- Signature hexutil.Bytes
-}
-
-// SignerCount returns the number of signers in the aggregate signature.
-func (s *SyncAggregate) SignerCount() int {
- var count int
- for _, v := range s.Signers {
- count += bits.OnesCount8(v)
- }
- return count
-}
diff --git a/beacon/types/config.go b/beacon/types/config.go
deleted file mode 100644
index 8cb8808b6f..0000000000
--- a/beacon/types/config.go
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright 2022 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package types
-
-import (
- "crypto/sha256"
- "fmt"
- "os"
- "sort"
- "strconv"
- "strings"
-
- "github.com/ethereum/go-ethereum/beacon/merkle"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/hexutil"
- "gopkg.in/yaml.v3"
-)
-
-// syncCommitteeDomain specifies the signatures specific use to avoid clashes
-// across signing different data structures.
-const syncCommitteeDomain = 7
-
-// Fork describes a single beacon chain fork and also stores the calculated
-// signature domain used after this fork.
-type Fork struct {
- // Name of the fork in the chain config (config.yaml) file{
- Name string
-
- // Epoch when given fork version is activated
- Epoch uint64
-
- // Fork version, see https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#custom-types
- Version []byte
-
- // calculated by computeDomain, based on fork version and genesis validators root
- domain merkle.Value
-}
-
-// computeDomain returns the signature domain based on the given fork version
-// and genesis validator set root.
-func (f *Fork) computeDomain(genesisValidatorsRoot common.Hash) {
- var (
- hasher = sha256.New()
- forkVersion32 merkle.Value
- forkDataRoot merkle.Value
- )
- copy(forkVersion32[:], f.Version)
- hasher.Write(forkVersion32[:])
- hasher.Write(genesisValidatorsRoot[:])
- hasher.Sum(forkDataRoot[:0])
-
- f.domain[0] = syncCommitteeDomain
- copy(f.domain[4:], forkDataRoot[:28])
-}
-
-// Forks is the list of all beacon chain forks in the chain configuration.
-type Forks []*Fork
-
-// domain returns the signature domain for the given epoch (assumes that domains
-// have already been calculated).
-func (f Forks) domain(epoch uint64) (merkle.Value, error) {
- for i := len(f) - 1; i >= 0; i-- {
- if epoch >= f[i].Epoch {
- return f[i].domain, nil
- }
- }
- return merkle.Value{}, fmt.Errorf("unknown fork for epoch %d", epoch)
-}
-
-// SigningRoot calculates the signing root of the given header.
-func (f Forks) SigningRoot(header Header) (common.Hash, error) {
- domain, err := f.domain(header.Epoch())
- if err != nil {
- return common.Hash{}, err
- }
- var (
- signingRoot common.Hash
- headerHash = header.Hash()
- hasher = sha256.New()
- )
- hasher.Write(headerHash[:])
- hasher.Write(domain[:])
- hasher.Sum(signingRoot[:0])
-
- return signingRoot, nil
-}
-
-func (f Forks) Len() int { return len(f) }
-func (f Forks) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
-func (f Forks) Less(i, j int) bool { return f[i].Epoch < f[j].Epoch }
-
-// ChainConfig contains the beacon chain configuration.
-type ChainConfig struct {
- GenesisTime uint64 // Unix timestamp of slot 0
- GenesisValidatorsRoot common.Hash // Root hash of the genesis validator set, used for signature domain calculation
- Forks Forks
-}
-
-// AddFork adds a new item to the list of forks.
-func (c *ChainConfig) AddFork(name string, epoch uint64, version []byte) *ChainConfig {
- fork := &Fork{
- Name: name,
- Epoch: epoch,
- Version: version,
- }
- fork.computeDomain(c.GenesisValidatorsRoot)
-
- c.Forks = append(c.Forks, fork)
- sort.Sort(c.Forks)
-
- return c
-}
-
-// LoadForks parses the beacon chain configuration file (config.yaml) and extracts
-// the list of forks.
-func (c *ChainConfig) LoadForks(path string) error {
- file, err := os.ReadFile(path)
- if err != nil {
- return fmt.Errorf("failed to read beacon chain config file: %v", err)
- }
- config := make(map[string]string)
- if err := yaml.Unmarshal(file, &config); err != nil {
- return fmt.Errorf("failed to parse beacon chain config file: %v", err)
- }
- var (
- versions = make(map[string][]byte)
- epochs = make(map[string]uint64)
- )
- epochs["GENESIS"] = 0
-
- for key, value := range config {
- if strings.HasSuffix(key, "_FORK_VERSION") {
- name := key[:len(key)-len("_FORK_VERSION")]
- if v, err := hexutil.Decode(value); err == nil {
- versions[name] = v
- } else {
- return fmt.Errorf("failed to decode hex fork id %q in beacon chain config file: %v", value, err)
- }
- }
- if strings.HasSuffix(key, "_FORK_EPOCH") {
- name := key[:len(key)-len("_FORK_EPOCH")]
- if v, err := strconv.ParseUint(value, 10, 64); err == nil {
- epochs[name] = v
- } else {
- return fmt.Errorf("failed to parse epoch number %q in beacon chain config file: %v", value, err)
- }
- }
- }
- for name, epoch := range epochs {
- if version, ok := versions[name]; ok {
- delete(versions, name)
- c.AddFork(name, epoch, version)
- } else {
- return fmt.Errorf("fork id missing for %q in beacon chain config file", name)
- }
- }
- for name := range versions {
- return fmt.Errorf("epoch number missing for fork %q in beacon chain config file", name)
- }
- sort.Sort(c.Forks)
- return nil
-}
diff --git a/beacon/types/gen_header_json.go b/beacon/types/gen_header_json.go
deleted file mode 100644
index 9b3ffea06f..0000000000
--- a/beacon/types/gen_header_json.go
+++ /dev/null
@@ -1,66 +0,0 @@
-// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
-
-package types
-
-import (
- "encoding/json"
- "errors"
-
- "github.com/ethereum/go-ethereum/common"
-)
-
-var _ = (*headerMarshaling)(nil)
-
-// MarshalJSON marshals as JSON.
-func (h Header) MarshalJSON() ([]byte, error) {
- type Header struct {
- Slot common.Decimal `gencodec:"required" json:"slot"`
- ProposerIndex common.Decimal `gencodec:"required" json:"proposer_index"`
- ParentRoot common.Hash `gencodec:"required" json:"parent_root"`
- StateRoot common.Hash `gencodec:"required" json:"state_root"`
- BodyRoot common.Hash `gencodec:"required" json:"body_root"`
- }
- var enc Header
- enc.Slot = common.Decimal(h.Slot)
- enc.ProposerIndex = common.Decimal(h.ProposerIndex)
- enc.ParentRoot = h.ParentRoot
- enc.StateRoot = h.StateRoot
- enc.BodyRoot = h.BodyRoot
- return json.Marshal(&enc)
-}
-
-// UnmarshalJSON unmarshals from JSON.
-func (h *Header) UnmarshalJSON(input []byte) error {
- type Header struct {
- Slot *common.Decimal `gencodec:"required" json:"slot"`
- ProposerIndex *common.Decimal `gencodec:"required" json:"proposer_index"`
- ParentRoot *common.Hash `gencodec:"required" json:"parent_root"`
- StateRoot *common.Hash `gencodec:"required" json:"state_root"`
- BodyRoot *common.Hash `gencodec:"required" json:"body_root"`
- }
- var dec Header
- if err := json.Unmarshal(input, &dec); err != nil {
- return err
- }
- if dec.Slot == nil {
- return errors.New("missing required field 'slot' for Header")
- }
- h.Slot = uint64(*dec.Slot)
- if dec.ProposerIndex == nil {
- return errors.New("missing required field 'proposer_index' for Header")
- }
- h.ProposerIndex = uint64(*dec.ProposerIndex)
- if dec.ParentRoot == nil {
- return errors.New("missing required field 'parent_root' for Header")
- }
- h.ParentRoot = *dec.ParentRoot
- if dec.StateRoot == nil {
- return errors.New("missing required field 'state_root' for Header")
- }
- h.StateRoot = *dec.StateRoot
- if dec.BodyRoot == nil {
- return errors.New("missing required field 'body_root' for Header")
- }
- h.BodyRoot = *dec.BodyRoot
- return nil
-}
diff --git a/beacon/types/gen_syncaggregate_json.go b/beacon/types/gen_syncaggregate_json.go
deleted file mode 100644
index 1547ec5f01..0000000000
--- a/beacon/types/gen_syncaggregate_json.go
+++ /dev/null
@@ -1,51 +0,0 @@
-// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
-
-package types
-
-import (
- "encoding/json"
- "errors"
-
- "github.com/ethereum/go-ethereum/common/hexutil"
-)
-
-var _ = (*syncAggregateMarshaling)(nil)
-
-// MarshalJSON marshals as JSON.
-func (s SyncAggregate) MarshalJSON() ([]byte, error) {
- type SyncAggregate struct {
- Signers hexutil.Bytes `gencodec:"required" json:"sync_committee_bits"`
- Signature hexutil.Bytes `gencodec:"required" json:"sync_committee_signature"`
- }
- var enc SyncAggregate
- enc.Signers = s.Signers[:]
- enc.Signature = s.Signature[:]
- return json.Marshal(&enc)
-}
-
-// UnmarshalJSON unmarshals from JSON.
-func (s *SyncAggregate) UnmarshalJSON(input []byte) error {
- type SyncAggregate struct {
- Signers *hexutil.Bytes `gencodec:"required" json:"sync_committee_bits"`
- Signature *hexutil.Bytes `gencodec:"required" json:"sync_committee_signature"`
- }
- var dec SyncAggregate
- if err := json.Unmarshal(input, &dec); err != nil {
- return err
- }
- if dec.Signers == nil {
- return errors.New("missing required field 'sync_committee_bits' for SyncAggregate")
- }
- if len(*dec.Signers) != len(s.Signers) {
- return errors.New("field 'sync_committee_bits' has wrong length, need 64 items")
- }
- copy(s.Signers[:], *dec.Signers)
- if dec.Signature == nil {
- return errors.New("missing required field 'sync_committee_signature' for SyncAggregate")
- }
- if len(*dec.Signature) != len(s.Signature) {
- return errors.New("field 'sync_committee_signature' has wrong length, need 96 items")
- }
- copy(s.Signature[:], *dec.Signature)
- return nil
-}
diff --git a/beacon/types/header.go b/beacon/types/header.go
deleted file mode 100644
index 2ddc4575f1..0000000000
--- a/beacon/types/header.go
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright 2022 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-// Package types implements a few types of the beacon chain for light client usage.
-package types
-
-import (
- "crypto/sha256"
- "encoding/binary"
-
- "github.com/ethereum/go-ethereum/beacon/merkle"
- "github.com/ethereum/go-ethereum/beacon/params"
- "github.com/ethereum/go-ethereum/common"
-)
-
-//go:generate go run github.com/fjl/gencodec -type Header -field-override headerMarshaling -out gen_header_json.go
-
-const (
- headerIndexSlot = 8
- headerIndexProposerIndex = 9
- headerIndexParentRoot = 10
- headerIndexStateRoot = 11
- headerIndexBodyRoot = 12
-)
-
-// Header defines a beacon header.
-//
-// See data structure definition here:
-// https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#beaconblockheader
-type Header struct {
- // Monotonically increasing slot number for the beacon block (may be gapped)
- Slot uint64 `gencodec:"required" json:"slot"`
-
- // Index into the validator table who created the beacon block
- ProposerIndex uint64 `gencodec:"required" json:"proposer_index"`
-
- // SSZ hash of the parent beacon header
- ParentRoot common.Hash `gencodec:"required" json:"parent_root"`
-
- // SSZ hash of the beacon state (https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/beacon-chain.md#beacon-state)
- StateRoot common.Hash `gencodec:"required" json:"state_root"`
-
- // SSZ hash of the beacon block body (https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/beacon-chain.md#beaconblockbody)
- BodyRoot common.Hash `gencodec:"required" json:"body_root"`
-}
-
-// headerMarshaling is a field type overrides for gencodec.
-type headerMarshaling struct {
- Slot common.Decimal
- ProposerIndex common.Decimal
-}
-
-// Hash calculates the block root of the header.
-//
-// TODO(zsfelfoldi): Remove this when an SSZ encoder lands.
-func (h *Header) Hash() common.Hash {
- var values [16]merkle.Value // values corresponding to indices 8 to 15 of the beacon header tree
- binary.LittleEndian.PutUint64(values[headerIndexSlot][:8], h.Slot)
- binary.LittleEndian.PutUint64(values[headerIndexProposerIndex][:8], h.ProposerIndex)
- values[headerIndexParentRoot] = merkle.Value(h.ParentRoot)
- values[headerIndexStateRoot] = merkle.Value(h.StateRoot)
- values[headerIndexBodyRoot] = merkle.Value(h.BodyRoot)
- hasher := sha256.New()
- for i := 7; i > 0; i-- {
- hasher.Reset()
- hasher.Write(values[i*2][:])
- hasher.Write(values[i*2+1][:])
- hasher.Sum(values[i][:0])
- }
- return common.Hash(values[1])
-}
-
-// Epoch returns the epoch the header belongs to.
-func (h *Header) Epoch() uint64 {
- return h.Slot / params.EpochLength
-}
-
-// SyncPeriod returns the sync period the header belongs to.
-func (h *Header) SyncPeriod() uint64 {
- return SyncPeriod(h.Slot)
-}
-
-// SyncPeriodStart returns the first slot of the given period.
-func SyncPeriodStart(period uint64) uint64 {
- return period * params.SyncPeriodLength
-}
-
-// SyncPeriod returns the sync period that the given slot belongs to.
-func SyncPeriod(slot uint64) uint64 {
- return slot / params.SyncPeriodLength
-}
-
-// SignedHeader represents a beacon header signed by a sync committee.
-//
-// This structure is created from either an optimistic update or an instant update:
-// - https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/sync-protocol.md#lightclientoptimisticupdate
-// - https://github.com/zsfelfoldi/beacon-APIs/blob/instant_update/apis/beacon/light_client/instant_update.yaml
-type SignedHeader struct {
- // Beacon header being signed
- Header Header
-
- // Sync committee BLS signature aggregate
- Signature SyncAggregate
-
- // Slot in which the signature has been created (newer than Header.Slot,
- // determines the signing sync committee)
- SignatureSlot uint64
-}
diff --git a/beacon/types/light_sync.go b/beacon/types/light_sync.go
deleted file mode 100644
index 3284081e4d..0000000000
--- a/beacon/types/light_sync.go
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 2022 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package types
-
-import (
- "errors"
- "fmt"
-
- "github.com/ethereum/go-ethereum/beacon/merkle"
- "github.com/ethereum/go-ethereum/beacon/params"
- "github.com/ethereum/go-ethereum/common"
-)
-
-// BootstrapData contains a sync committee where light sync can be started,
-// together with a proof through a beacon header and corresponding state.
-// Note: BootstrapData is fetched from a server based on a known checkpoint hash.
-type BootstrapData struct {
- Header Header
- CommitteeRoot common.Hash
- Committee *SerializedSyncCommittee `rlp:"-"`
- CommitteeBranch merkle.Values
-}
-
-// Validate verifies the proof included in BootstrapData.
-func (c *BootstrapData) Validate() error {
- if c.CommitteeRoot != c.Committee.Root() {
- return errors.New("wrong committee root")
- }
- return merkle.VerifyProof(c.Header.StateRoot, params.StateIndexSyncCommittee, c.CommitteeBranch, merkle.Value(c.CommitteeRoot))
-}
-
-// LightClientUpdate is a proof of the next sync committee root based on a header
-// signed by the sync committee of the given period. Optionally, the update can
-// prove quasi-finality by the signed header referring to a previous, finalized
-// header from the same period, and the finalized header referring to the next
-// sync committee root.
-//
-// See data structure definition here:
-// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/sync-protocol.md#lightclientupdate
-type LightClientUpdate struct {
- AttestedHeader SignedHeader // Arbitrary header out of the period signed by the sync committee
- NextSyncCommitteeRoot common.Hash // Sync committee of the next period advertised in the current one
- NextSyncCommitteeBranch merkle.Values // Proof for the next period's sync committee
-
- FinalizedHeader *Header `rlp:"nil"` // Optional header to announce a point of finality
- FinalityBranch merkle.Values // Proof for the announced finality
-
- score *UpdateScore // Weight of the update to compare between competing ones
-}
-
-// Validate verifies the validity of the update.
-func (update *LightClientUpdate) Validate() error {
- period := update.AttestedHeader.Header.SyncPeriod()
- if SyncPeriod(update.AttestedHeader.SignatureSlot) != period {
- return errors.New("signature slot and signed header are from different periods")
- }
- if update.FinalizedHeader != nil {
- if update.FinalizedHeader.SyncPeriod() != period {
- return errors.New("finalized header is from different period")
- }
- if err := merkle.VerifyProof(update.AttestedHeader.Header.StateRoot, params.StateIndexFinalBlock, update.FinalityBranch, merkle.Value(update.FinalizedHeader.Hash())); err != nil {
- return fmt.Errorf("invalid finalized header proof: %w", err)
- }
- }
- if err := merkle.VerifyProof(update.AttestedHeader.Header.StateRoot, params.StateIndexNextSyncCommittee, update.NextSyncCommitteeBranch, merkle.Value(update.NextSyncCommitteeRoot)); err != nil {
- return fmt.Errorf("invalid next sync committee proof: %w", err)
- }
- return nil
-}
-
-// Score returns the UpdateScore describing the proof strength of the update
-// Note: thread safety can be ensured by always calling Score on a newly received
-// or decoded update before making it potentially available for other threads
-func (update *LightClientUpdate) Score() UpdateScore {
- if update.score == nil {
- update.score = &UpdateScore{
- SignerCount: uint32(update.AttestedHeader.Signature.SignerCount()),
- SubPeriodIndex: uint32(update.AttestedHeader.Header.Slot & 0x1fff),
- FinalizedHeader: update.FinalizedHeader != nil,
- }
- }
- return *update.score
-}
-
-// UpdateScore allows the comparison between updates at the same period in order
-// to find the best update chain that provides the strongest proof of being canonical.
-//
-// UpdateScores have a tightly packed binary encoding format for efficient p2p
-// protocol transmission. Each UpdateScore is encoded in 3 bytes.
-// When interpreted as a 24 bit little indian unsigned integer:
-// - the lowest 10 bits contain the number of signers in the header signature aggregate
-// - the next 13 bits contain the "sub-period index" which is he signed header's
-// slot modulo params.SyncPeriodLength (which is correlated with the risk of the chain being
-// re-orged before the previous period boundary in case of non-finalized updates)
-// - the highest bit is set when the update is finalized (meaning that the finality
-// header referenced by the signed header is in the same period as the signed
-// header, making reorgs before the period boundary impossible
-type UpdateScore struct {
- SignerCount uint32 // number of signers in the header signature aggregate
- SubPeriodIndex uint32 // signed header's slot modulo params.SyncPeriodLength
- FinalizedHeader bool // update is considered finalized if has finalized header from the same period and 2/3 signatures
-}
-
-// finalized returns true if the update has a header signed by at least 2/3 of
-// the committee, referring to a finalized header that refers to the next sync
-// committee. This condition is a close approximation of the actual finality
-// condition that can only be verified by full beacon nodes.
-func (u *UpdateScore) finalized() bool {
- return u.FinalizedHeader && u.SignerCount >= params.SyncCommitteeSupermajority
-}
-
-// BetterThan returns true if update u is considered better than w.
-func (u UpdateScore) BetterThan(w UpdateScore) bool {
- var (
- uFinalized = u.finalized()
- wFinalized = w.finalized()
- )
- if uFinalized != wFinalized {
- return uFinalized
- }
- return u.SignerCount > w.SignerCount
-}