mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
cmd/blsync,beacon: move blsync code into beacon
This commit is contained in:
parent
e151f4a93d
commit
ca0feab9d3
12 changed files with 398 additions and 426 deletions
|
|
@ -14,7 +14,7 @@
|
|||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
package beaclient
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
|
@ -27,6 +27,7 @@ import (
|
|||
eth2api "github.com/attestantio/go-eth2-client/api"
|
||||
eth2http "github.com/attestantio/go-eth2-client/http"
|
||||
eth2spec "github.com/attestantio/go-eth2-client/spec"
|
||||
"github.com/ethereum/go-ethereum/beacon/types"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
|
@ -38,13 +39,13 @@ var (
|
|||
beaconLightClientFinalityUpdate = "eth/v1/beacon/light_client/finality_update"
|
||||
)
|
||||
|
||||
type BeaconClient struct {
|
||||
type Client struct {
|
||||
ctx context.Context
|
||||
url string
|
||||
client eth2client.Service
|
||||
}
|
||||
|
||||
func NewBeaconClient(ctx context.Context, server string) (*BeaconClient, error) {
|
||||
func NewClient(ctx context.Context, server string) (*Client, error) {
|
||||
client, err := eth2http.New(
|
||||
ctx,
|
||||
eth2http.WithAddress(server),
|
||||
|
|
@ -54,14 +55,14 @@ func NewBeaconClient(ctx context.Context, server string) (*BeaconClient, error)
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &BeaconClient{
|
||||
return &Client{
|
||||
ctx: ctx,
|
||||
url: server,
|
||||
client: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *BeaconClient) Bootstrap(root common.Hash) (*Bootstrap, error) {
|
||||
func (c *Client) Bootstrap(root common.Hash) (*types.Bootstrap, error) {
|
||||
resp, err := http.Get(fmt.Sprintf("%s/%s/%s", c.url, beaconLightClientBootstrap, root.String()))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed http request: %w", err)
|
||||
|
|
@ -70,14 +71,14 @@ func (c *BeaconClient) Bootstrap(root common.Hash) (*Bootstrap, error) {
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read response: %w", err)
|
||||
}
|
||||
var bs Bootstrap
|
||||
var bs types.Bootstrap
|
||||
if err := json.Unmarshal(b, &bs); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal data: %v", err)
|
||||
}
|
||||
return &bs, nil
|
||||
}
|
||||
|
||||
func (c *BeaconClient) GetRangeUpdate(start, count int) ([]*LightClientUpdate, error) {
|
||||
func (c *Client) GetRangeUpdate(start, count int) ([]*types.LightClientUpdate, error) {
|
||||
resp, err := http.Get(fmt.Sprintf("%s/%s?start_period=%d&count=%d", c.url, beaconLightClientUpdate, start, count))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed http request: %w", err)
|
||||
|
|
@ -86,7 +87,7 @@ func (c *BeaconClient) GetRangeUpdate(start, count int) ([]*LightClientUpdate, e
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read response: %w", err)
|
||||
}
|
||||
var u []*LightClientUpdate
|
||||
var u []*types.LightClientUpdate
|
||||
if err := json.Unmarshal(b, &u); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal data: %v", err)
|
||||
}
|
||||
|
|
@ -94,7 +95,7 @@ func (c *BeaconClient) GetRangeUpdate(start, count int) ([]*LightClientUpdate, e
|
|||
|
||||
}
|
||||
|
||||
func (c *BeaconClient) GetOptimisticUpdate() (*LightClientUpdate, error) {
|
||||
func (c *Client) GetOptimisticUpdate() (*types.LightClientUpdate, error) {
|
||||
resp, err := http.Get(fmt.Sprintf("%s/%s", c.url, beaconLightClientOptimisticUpdate))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed http request: %w", err)
|
||||
|
|
@ -103,14 +104,14 @@ func (c *BeaconClient) GetOptimisticUpdate() (*LightClientUpdate, error) {
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read response: %w", err)
|
||||
}
|
||||
var u LightClientUpdate
|
||||
var u types.LightClientUpdate
|
||||
if err := json.Unmarshal(b, &u); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal data: %v", err)
|
||||
}
|
||||
return &u, nil
|
||||
}
|
||||
|
||||
func (c *BeaconClient) GetFinalityUpdate() (*LightClientUpdate, error) {
|
||||
func (c *Client) GetFinalityUpdate() (*types.LightClientUpdate, error) {
|
||||
resp, err := http.Get(fmt.Sprintf("%s/%s", c.url, beaconLightClientFinalityUpdate))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed http request: %w", err)
|
||||
|
|
@ -119,7 +120,7 @@ func (c *BeaconClient) GetFinalityUpdate() (*LightClientUpdate, error) {
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read response: %w", err)
|
||||
}
|
||||
var u LightClientUpdate
|
||||
var u types.LightClientUpdate
|
||||
if err := json.Unmarshal(b, &u); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal data: %v", err)
|
||||
}
|
||||
|
|
@ -127,7 +128,7 @@ func (c *BeaconClient) GetFinalityUpdate() (*LightClientUpdate, error) {
|
|||
|
||||
}
|
||||
|
||||
func (c *BeaconClient) GetBlock(root common.Hash) (*eth2spec.VersionedSignedBeaconBlock, error) {
|
||||
func (c *Client) GetBlock(root common.Hash) (*eth2spec.VersionedSignedBeaconBlock, error) {
|
||||
provider, ok := c.client.(eth2client.SignedBeaconBlockProvider)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("beacon server does not support retrieving blocks")
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2023 The go-ethereum Authors
|
||||
// Copyright 2024 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
|
||||
|
|
@ -14,16 +14,21 @@
|
|||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
package light
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
eth2spec "github.com/attestantio/go-eth2-client/spec"
|
||||
"github.com/ethereum/go-ethereum/beacon/beaclient"
|
||||
"github.com/ethereum/go-ethereum/beacon/engine"
|
||||
"github.com/ethereum/go-ethereum/beacon/params"
|
||||
"github.com/ethereum/go-ethereum/beacon/types"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
ctypes "github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
)
|
||||
|
|
@ -31,16 +36,16 @@ import (
|
|||
// LightClient tracks the head of the chain using the light client protocol,
|
||||
// which assumes the majority of beacon chain sync committe is honest.
|
||||
type LightClient struct {
|
||||
beacon *BeaconClient
|
||||
beacon *beaclient.Client
|
||||
store *store
|
||||
|
||||
chainHeadFeed event.Feed
|
||||
}
|
||||
|
||||
// bootstrap retrieves a light client bootstrap and authenticates it against the
|
||||
// Bootstrap retrieves a light client bootstrap and authenticates it against the
|
||||
// provided trusted root.
|
||||
func bootstrap(ctx context.Context, server string, root common.Hash) (*LightClient, error) {
|
||||
api, err := NewBeaconClient(ctx, server)
|
||||
func Bootstrap(ctx context.Context, server string, root common.Hash) (*LightClient, error) {
|
||||
api, err := beaclient.NewClient(ctx, server)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to connect to beacon server: %w", err)
|
||||
}
|
||||
|
|
@ -58,7 +63,7 @@ func bootstrap(ctx context.Context, server string, root common.Hash) (*LightClie
|
|||
return &LightClient{
|
||||
beacon: api,
|
||||
store: &store{
|
||||
config: SepoliaChainConfig,
|
||||
config: params.SepoliaChainConfig,
|
||||
current: current,
|
||||
optimistic: &bs.Header.Header,
|
||||
finalized: &bs.Header.Header,
|
||||
|
|
@ -88,7 +93,7 @@ func (c *LightClient) Finalized() *types.Header {
|
|||
func (c *LightClient) Start() {
|
||||
log.Info("beacon light client starting")
|
||||
var (
|
||||
ticker = time.NewTicker(SecondsPerSlot * time.Second)
|
||||
ticker = time.NewTicker(params.SlotLength * time.Second)
|
||||
lastFinality = time.Now()
|
||||
)
|
||||
for ; ; <-ticker.C {
|
||||
|
|
@ -108,7 +113,7 @@ func (c *LightClient) Start() {
|
|||
}
|
||||
|
||||
var (
|
||||
update *LightClientUpdate
|
||||
update *types.LightClientUpdate
|
||||
err error
|
||||
)
|
||||
if time.Since(lastFinality) > time.Minute*5 {
|
||||
|
|
@ -159,3 +164,114 @@ func (c *LightClient) getExecutableData(head common.Hash) (*engine.ExecutableDat
|
|||
}
|
||||
return versionedBlockToExecutableData(block), nil
|
||||
}
|
||||
|
||||
// versionedBlockToExecutableData parses versioned blocks and returns a generic
|
||||
// execution payload object.
|
||||
func versionedBlockToExecutableData(block *eth2spec.VersionedSignedBeaconBlock) *engine.ExecutableData {
|
||||
var ep *engine.ExecutableData
|
||||
switch block.Version {
|
||||
case eth2spec.DataVersionPhase0:
|
||||
panic("phase0 block has no execution payload to send")
|
||||
case eth2spec.DataVersionAltair:
|
||||
panic("altair block has no execution payload to send")
|
||||
case eth2spec.DataVersionBellatrix:
|
||||
p := block.Bellatrix.Message.Body.ExecutionPayload
|
||||
ep = &engine.ExecutableData{
|
||||
ParentHash: common.Hash(p.ParentHash),
|
||||
FeeRecipient: common.Address(p.FeeRecipient),
|
||||
StateRoot: p.StateRoot,
|
||||
ReceiptsRoot: p.ReceiptsRoot,
|
||||
LogsBloom: p.LogsBloom[:],
|
||||
Random: p.PrevRandao,
|
||||
Number: p.BlockNumber,
|
||||
GasLimit: p.GasLimit,
|
||||
GasUsed: p.GasUsed,
|
||||
Timestamp: p.Timestamp,
|
||||
ExtraData: p.ExtraData,
|
||||
BaseFeePerGas: new(big.Int).SetBytes(reverse(p.BaseFeePerGas[:])),
|
||||
BlockHash: common.Hash(p.BlockHash),
|
||||
Transactions: [][]byte{},
|
||||
Withdrawals: nil,
|
||||
BlobGasUsed: nil,
|
||||
ExcessBlobGas: nil,
|
||||
}
|
||||
for _, tx := range p.Transactions {
|
||||
ep.Transactions = append(ep.Transactions, tx)
|
||||
}
|
||||
case eth2spec.DataVersionCapella:
|
||||
p := block.Capella.Message.Body.ExecutionPayload
|
||||
ep = &engine.ExecutableData{
|
||||
ParentHash: common.Hash(p.ParentHash),
|
||||
FeeRecipient: common.Address(p.FeeRecipient),
|
||||
StateRoot: p.StateRoot,
|
||||
ReceiptsRoot: p.ReceiptsRoot,
|
||||
LogsBloom: p.LogsBloom[:],
|
||||
Random: p.PrevRandao,
|
||||
Number: p.BlockNumber,
|
||||
GasLimit: p.GasLimit,
|
||||
GasUsed: p.GasUsed,
|
||||
Timestamp: p.Timestamp,
|
||||
ExtraData: p.ExtraData,
|
||||
BaseFeePerGas: new(big.Int).SetBytes(reverse(p.BaseFeePerGas[:])),
|
||||
BlockHash: common.Hash(p.BlockHash),
|
||||
Transactions: [][]byte{},
|
||||
Withdrawals: nil,
|
||||
BlobGasUsed: nil,
|
||||
ExcessBlobGas: nil,
|
||||
}
|
||||
for _, tx := range p.Transactions {
|
||||
ep.Transactions = append(ep.Transactions, tx)
|
||||
}
|
||||
for _, wx := range p.Withdrawals {
|
||||
ep.Withdrawals = append(ep.Withdrawals, &ctypes.Withdrawal{
|
||||
Index: uint64(wx.Index),
|
||||
Validator: uint64(wx.ValidatorIndex),
|
||||
Address: common.Address(wx.Address),
|
||||
Amount: uint64(wx.Amount),
|
||||
})
|
||||
}
|
||||
case eth2spec.DataVersionDeneb:
|
||||
p := block.Deneb.Message.Body.ExecutionPayload
|
||||
ep = &engine.ExecutableData{
|
||||
ParentHash: common.Hash(p.ParentHash),
|
||||
FeeRecipient: common.Address(p.FeeRecipient),
|
||||
StateRoot: common.Hash(p.StateRoot),
|
||||
ReceiptsRoot: common.Hash(p.ReceiptsRoot),
|
||||
LogsBloom: p.LogsBloom[:],
|
||||
Random: p.PrevRandao,
|
||||
Number: p.BlockNumber,
|
||||
GasLimit: p.GasLimit,
|
||||
GasUsed: p.GasUsed,
|
||||
Timestamp: p.Timestamp,
|
||||
ExtraData: p.ExtraData,
|
||||
BaseFeePerGas: nil, // TODO: convert this []uint64 correctly to big.Int
|
||||
BlockHash: common.Hash(p.BlockHash),
|
||||
Transactions: [][]byte{},
|
||||
Withdrawals: nil,
|
||||
BlobGasUsed: &p.BlobGasUsed,
|
||||
ExcessBlobGas: &p.ExcessBlobGas,
|
||||
}
|
||||
for _, tx := range p.Transactions {
|
||||
ep.Transactions = append(ep.Transactions, tx)
|
||||
}
|
||||
for _, wx := range p.Withdrawals {
|
||||
ep.Withdrawals = append(ep.Withdrawals, &ctypes.Withdrawal{
|
||||
Index: uint64(wx.Index),
|
||||
Validator: uint64(wx.ValidatorIndex),
|
||||
Address: common.Address(wx.Address),
|
||||
Amount: uint64(wx.Amount),
|
||||
})
|
||||
}
|
||||
default:
|
||||
panic("unknown beacon block version")
|
||||
}
|
||||
return ep
|
||||
}
|
||||
|
||||
func reverse(b []byte) []byte {
|
||||
for i := 0; i < len(b)/2; i++ {
|
||||
j := len(b) - i - 1
|
||||
b[i], b[j] = b[j], b[i]
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2023 The go-ethereum Authors
|
||||
// Copyright 2024 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
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
package light
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
|
@ -14,23 +14,35 @@
|
|||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
package light
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"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"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
)
|
||||
|
||||
var (
|
||||
errNotEnoughParticipants = errors.New("not enough sync committee participants")
|
||||
errWrongPeriod = errors.New("update not from active period")
|
||||
errUselessUpdate = errors.New("useless update")
|
||||
errInvalidFinalityBranch = errors.New("invalid finality branch")
|
||||
errInvalidNextSyncCommitteeBranch = errors.New("invalid next sync committee branch")
|
||||
errInvalidSyncCommitteeSignature = errors.New("invalid sync committee signature")
|
||||
)
|
||||
|
||||
// store implements the light client state machine LightClientStore from the
|
||||
// light client specification.
|
||||
//
|
||||
// https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/sync-protocol.md#lightclientstore
|
||||
type store struct {
|
||||
config *ChainConfig
|
||||
config *params.ChainConfig
|
||||
|
||||
finalized *types.Header
|
||||
optimistic *types.Header
|
||||
|
|
@ -38,7 +50,7 @@ type store struct {
|
|||
current *types.SyncCommittee
|
||||
next *types.SyncCommittee
|
||||
|
||||
best *LightClientUpdate
|
||||
best *types.LightClientUpdate
|
||||
|
||||
prevActive uint64
|
||||
currActive uint64
|
||||
|
|
@ -49,8 +61,8 @@ func (s *store) copy() *store {
|
|||
return shallow
|
||||
}
|
||||
|
||||
func (s *store) validate(update *LightClientUpdate) error {
|
||||
if update.SyncAggregate.SignerCount() <= MinSyncCommitteeParticipants {
|
||||
func (s *store) validate(update *types.LightClientUpdate) error {
|
||||
if update.SyncAggregate.SignerCount() <= params.SyncCommitteeMinParticipants {
|
||||
return errNotEnoughParticipants
|
||||
}
|
||||
var (
|
||||
|
|
@ -93,7 +105,7 @@ func (s *store) validate(update *LightClientUpdate) error {
|
|||
|
||||
// Validate sync committee signature.
|
||||
var (
|
||||
domain = s.config.Domain(SyncCommitteeDomain, update.SignatureSlot)
|
||||
domain = s.config.Domain(params.SyncCommitteeDomain, update.SignatureSlot)
|
||||
signingRoot = computeSigningRoot(update.AttestedHeader.Hash(), domain)
|
||||
)
|
||||
committee := s.current
|
||||
|
|
@ -115,7 +127,7 @@ func (s *store) finalizedPeriod() int {
|
|||
return int(types.SyncPeriod(s.finalized.Slot))
|
||||
}
|
||||
|
||||
func (s *store) Insert(update *LightClientUpdate) error {
|
||||
func (s *store) Insert(update *types.LightClientUpdate) error {
|
||||
if err := s.validate(update); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -181,3 +193,18 @@ func max(x, y uint64) uint64 {
|
|||
}
|
||||
return x
|
||||
}
|
||||
|
||||
func computeSigningRoot(root, domain common.Hash) common.Hash {
|
||||
return hash(root.Bytes(), domain.Bytes())
|
||||
}
|
||||
|
||||
func hash(left, right []byte) common.Hash {
|
||||
var (
|
||||
hasher = sha256.New()
|
||||
sum common.Hash
|
||||
)
|
||||
hasher.Write(left)
|
||||
hasher.Write(right)
|
||||
hasher.Sum(sum[:0])
|
||||
return sum
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2023 The go-ethereum Authors
|
||||
// Copyright 2024 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
|
||||
|
|
@ -14,9 +14,11 @@
|
|||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
package params
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
|
|
@ -51,7 +53,7 @@ type ChainConfig struct {
|
|||
|
||||
// Version returns the active version for a given slot.
|
||||
func (c *ChainConfig) Version(slot uint64) []byte {
|
||||
epoch := slot / SlotsPerEpoch
|
||||
epoch := slot / SlotLength
|
||||
switch {
|
||||
case c.Capella.Epoch <= epoch:
|
||||
return c.Capella.Version
|
||||
|
|
@ -74,3 +76,21 @@ func (c *ChainConfig) Domain(typ []byte, slot uint64) common.Hash {
|
|||
copy(domain[4:], forkData[0:28])
|
||||
return domain
|
||||
}
|
||||
|
||||
// https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#compute_fork_data_root
|
||||
func computeForkDataRoot(version []byte, genesisValidatorsRoot common.Hash) common.Hash {
|
||||
var padded common.Hash
|
||||
copy(padded[:], version)
|
||||
return hash(padded.Bytes(), genesisValidatorsRoot.Bytes())
|
||||
}
|
||||
|
||||
func hash(left, right []byte) common.Hash {
|
||||
var (
|
||||
hasher = sha256.New()
|
||||
sum common.Hash
|
||||
)
|
||||
hasher.Write(left)
|
||||
hasher.Write(right)
|
||||
hasher.Sum(sum[:0])
|
||||
return sum
|
||||
}
|
||||
|
|
@ -17,15 +17,18 @@
|
|||
package params
|
||||
|
||||
const (
|
||||
SlotLength = 12
|
||||
EpochLength = 32
|
||||
SyncPeriodLength = 8192
|
||||
|
||||
BLSSignatureSize = 96
|
||||
BLSPubkeySize = 48
|
||||
|
||||
SyncCommitteeSize = 512
|
||||
SyncCommitteeBitmaskSize = SyncCommitteeSize / 8
|
||||
SyncCommitteeSupermajority = (SyncCommitteeSize*2 + 2) / 3
|
||||
SyncCommitteeSize = 512
|
||||
SyncCommitteeBitmaskSize = SyncCommitteeSize / 8
|
||||
SyncCommitteeSupermajority = (SyncCommitteeSize*2 + 2) / 3
|
||||
SyncCommitteeMinParticipants = 1
|
||||
SyncCommitteeEpochsPerPeriod = 256
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
|||
190
beacon/types/light_client.go
Normal file
190
beacon/types/light_client.go
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
// Copyright 2024 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/ethereum/go-ethereum/beacon/merkle"
|
||||
"github.com/ethereum/go-ethereum/beacon/params"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
// LightClientHeader is a wrapper around a beacon header with special, nested
|
||||
// marshalling.
|
||||
type LightClientHeader struct {
|
||||
Header
|
||||
}
|
||||
|
||||
type lightClientHeaderMarshaling struct {
|
||||
Beacon Header `json:"beacon"`
|
||||
}
|
||||
|
||||
// MarshalJSON marshals as JSON.
|
||||
func (h LightClientHeader) MarshalJSON() ([]byte, error) {
|
||||
var enc lightClientHeaderMarshaling
|
||||
enc.Beacon = h.Header
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals from JSON.
|
||||
func (h *LightClientHeader) UnmarshalJSON(input []byte) error {
|
||||
var dec lightClientHeaderMarshaling
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
return err
|
||||
}
|
||||
*h = LightClientHeader{dec.Beacon}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Boostrap is response to the bootstap endpoint in the beacon API.
|
||||
type Bootstrap struct {
|
||||
Header LightClientHeader `json:"header"`
|
||||
Committee *SerializedSyncCommittee `json:"current_sync_committee"`
|
||||
CommitteeBranch merkle.Values `json:"current_sync_committee_branch"`
|
||||
}
|
||||
|
||||
// Valid verifies the current committee root is correctly encoded in the beacon
|
||||
// state of the weak-subjectivity checkpoint.
|
||||
func (b *Bootstrap) Valid() error {
|
||||
root := merkle.Value(b.Committee.Root())
|
||||
if err := merkle.VerifyProof(b.Header.StateRoot, params.StateIndexSyncCommittee, b.CommitteeBranch, root); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type bootstrapMarshaling struct {
|
||||
Data struct {
|
||||
Header LightClientHeader `json:"header"`
|
||||
Committee *SerializedSyncCommittee `json:"current_sync_committee"`
|
||||
CommitteeBranch merkle.Values `json:"current_sync_committee_branch"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// MarshalJSON marshals as JSON.
|
||||
func (b Bootstrap) MarshalJSON() ([]byte, error) {
|
||||
var enc bootstrapMarshaling
|
||||
enc.Data.Header = b.Header
|
||||
enc.Data.Committee = b.Committee
|
||||
enc.Data.CommitteeBranch = b.CommitteeBranch
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals from JSON.
|
||||
func (b *Bootstrap) UnmarshalJSON(input []byte) error {
|
||||
var dec bootstrapMarshaling
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
return err
|
||||
}
|
||||
b.Header = dec.Data.Header
|
||||
b.Committee = dec.Data.Committee
|
||||
b.CommitteeBranch = dec.Data.CommitteeBranch
|
||||
return nil
|
||||
}
|
||||
|
||||
// LightClientUpdate represents the possible light client updates the beacon api
|
||||
// may respond with.
|
||||
type LightClientUpdate struct {
|
||||
AttestedHeader LightClientHeader // Arbitrary header out of the period signed by the sync committee
|
||||
SyncAggregate SyncAggregate // BLS aggregate signature from sync committee
|
||||
SignatureSlot uint64 // Slot at which the signature is computed
|
||||
NextSyncCommittee *SerializedSyncCommittee // Sync committee of the next period advertised in the current one
|
||||
NextSyncCommitteeBranch *merkle.Values // Proof for the next period's sync committee
|
||||
FinalizedHeader *LightClientHeader // Optional header to announce a point of finality
|
||||
FinalityBranch *merkle.Values // Proof for the announced finality
|
||||
}
|
||||
|
||||
type lightClientUpdateMarshaling struct {
|
||||
Data struct {
|
||||
AttestedHeader LightClientHeader `json:"attested_header"`
|
||||
SyncAggregate SyncAggregate `json:"sync_aggregate"`
|
||||
SignatureSlot common.Decimal `json:"signature_slot"`
|
||||
NextSyncCommittee *SerializedSyncCommittee `json:"next_sync_committee"`
|
||||
NextSyncCommitteeBranch *merkle.Values `json:"next_sync_committee_branch"`
|
||||
FinalizedHeader *LightClientHeader `json:"finalized_header"`
|
||||
FinalityBranch *merkle.Values `json:"finality_branch"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// MarshalJSON marshals to JSON.
|
||||
func (u LightClientUpdate) MarshalJSON() ([]byte, error) {
|
||||
var enc lightClientUpdateMarshaling
|
||||
enc.Data.AttestedHeader = u.AttestedHeader
|
||||
enc.Data.SyncAggregate = u.SyncAggregate
|
||||
enc.Data.SignatureSlot = common.Decimal(u.SignatureSlot)
|
||||
enc.Data.NextSyncCommittee = u.NextSyncCommittee
|
||||
enc.Data.NextSyncCommitteeBranch = u.NextSyncCommitteeBranch
|
||||
enc.Data.FinalizedHeader = u.FinalizedHeader
|
||||
enc.Data.FinalityBranch = u.FinalityBranch
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals from JSON.
|
||||
func (u *LightClientUpdate) UnmarshalJSON(input []byte) error {
|
||||
var dec lightClientUpdateMarshaling
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
return err
|
||||
}
|
||||
u.AttestedHeader = dec.Data.AttestedHeader
|
||||
u.SyncAggregate = dec.Data.SyncAggregate
|
||||
u.SignatureSlot = uint64(dec.Data.SignatureSlot)
|
||||
u.NextSyncCommittee = dec.Data.NextSyncCommittee
|
||||
u.NextSyncCommitteeBranch = dec.Data.NextSyncCommitteeBranch
|
||||
u.FinalizedHeader = dec.Data.FinalizedHeader
|
||||
u.FinalityBranch = dec.Data.FinalityBranch
|
||||
return nil
|
||||
}
|
||||
|
||||
// Compare will compare two light client updates and determine the better one.
|
||||
// If next is not better than curr, it will error.
|
||||
func (curr *LightClientUpdate) Compare(next *LightClientUpdate) error {
|
||||
if curr == nil {
|
||||
// Nothing to compare.
|
||||
return nil
|
||||
}
|
||||
var (
|
||||
maxActiveParticipants = params.SyncCommitteeSize
|
||||
newNumActiveParticipants = next.SyncAggregate.SignerCount()
|
||||
oldNumActiveParticipants = curr.SyncAggregate.SignerCount()
|
||||
newHasSupermajority = newNumActiveParticipants*3 >= maxActiveParticipants*2
|
||||
oldHasSupermajority = oldNumActiveParticipants*3 >= maxActiveParticipants*2
|
||||
)
|
||||
if newHasSupermajority && !oldHasSupermajority {
|
||||
return nil
|
||||
} else if !newHasSupermajority && oldHasSupermajority {
|
||||
return fmt.Errorf("new update does not have supermajority while old does")
|
||||
}
|
||||
if !newHasSupermajority && newNumActiveParticipants > oldNumActiveParticipants {
|
||||
return nil
|
||||
} else if !newHasSupermajority && newNumActiveParticipants <= oldNumActiveParticipants {
|
||||
return fmt.Errorf("more active participants in old update")
|
||||
}
|
||||
|
||||
// TODO: implement all tie breakers from spec
|
||||
// var (
|
||||
// sigPeriod = slotToSyncCommitteePeriod(next.SignatureSlot)
|
||||
// newHasRelevantSyncCommitteeUpdate = next.NextSyncCommittee != nil && (slotToSyncCommitteePeriod(next.AttestedHeader.Slot) == sigPeriod)
|
||||
// oldHasRelevantSyncCommitteeUpdate = curr.NextSyncCommittee != nil && (slotToSyncCommitteePeriod(curr.AttestedHeader.Slot) == sigPeriod)
|
||||
// )
|
||||
// if !newHasRelevantSyncCommitteeUpdate && oldHasRelevantSyncCommitteeUpdate {
|
||||
// return fmt.Errorf("old update also includes sync committee update")
|
||||
// }
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -1,52 +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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
const (
|
||||
MinSyncCommitteeParticipants = 1
|
||||
SecondsPerSlot = 12
|
||||
SlotsPerEpoch = 32
|
||||
EpochsPerSyncCommitteePeriod = 256
|
||||
)
|
||||
|
||||
// https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#compute_fork_data_root
|
||||
func computeForkDataRoot(version []byte, genesisValidatorsRoot common.Hash) common.Hash {
|
||||
var padded common.Hash
|
||||
copy(padded[:], version)
|
||||
return hash(padded.Bytes(), genesisValidatorsRoot.Bytes())
|
||||
}
|
||||
|
||||
func computeSigningRoot(root, domain common.Hash) common.Hash {
|
||||
return hash(root.Bytes(), domain.Bytes())
|
||||
}
|
||||
|
||||
func hash(left, right []byte) common.Hash {
|
||||
var (
|
||||
hasher = sha256.New()
|
||||
sum common.Hash
|
||||
)
|
||||
hasher.Write(left)
|
||||
hasher.Write(right)
|
||||
hasher.Sum(sum[:0])
|
||||
return sum
|
||||
}
|
||||
|
|
@ -1,28 +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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
errNotEnoughParticipants = errors.New("not enough sync committee participants")
|
||||
errWrongPeriod = errors.New("update not from active period")
|
||||
errUselessUpdate = errors.New("useless update")
|
||||
errInvalidFinalityBranch = errors.New("invalid finality branch")
|
||||
errInvalidNextSyncCommitteeBranch = errors.New("invalid next sync committee branch")
|
||||
errInvalidSyncCommitteeSignature = errors.New("invalid sync committee signature")
|
||||
)
|
||||
|
|
@ -24,6 +24,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/beacon/engine"
|
||||
"github.com/ethereum/go-ethereum/beacon/light"
|
||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/internal/flags"
|
||||
|
|
@ -99,13 +100,13 @@ func run(ctx *cli.Context) error {
|
|||
engine = makeRPCClient(ctx)
|
||||
server = ctx.String(LightClientServerFlag.Name)
|
||||
)
|
||||
chain, err := bootstrap(context.Background(), server, common.HexToHash(root))
|
||||
chain, err := light.Bootstrap(context.Background(), server, common.HexToHash(root))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to bootstrap: %v", err)
|
||||
}
|
||||
go chain.Start()
|
||||
|
||||
headCh := make(chan ChainHeadEvent)
|
||||
headCh := make(chan light.ChainHeadEvent)
|
||||
chain.SubscribeChainHeadEvent(headCh)
|
||||
|
||||
// Send new head events to engine api.
|
||||
|
|
|
|||
|
|
@ -1,306 +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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
eth2spec "github.com/attestantio/go-eth2-client/spec"
|
||||
"github.com/ethereum/go-ethereum/beacon/engine"
|
||||
"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"
|
||||
ctypes "github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
// LightClientHeader is a wrapper around a beacon header with special, nested
|
||||
// marshalling.
|
||||
type LightClientHeader struct {
|
||||
types.Header
|
||||
}
|
||||
|
||||
type lightClientHeaderMarshaling struct {
|
||||
Beacon types.Header `json:"beacon"`
|
||||
}
|
||||
|
||||
// MarshalJSON marshals as JSON.
|
||||
func (h LightClientHeader) MarshalJSON() ([]byte, error) {
|
||||
var enc lightClientHeaderMarshaling
|
||||
enc.Beacon = h.Header
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals from JSON.
|
||||
func (h *LightClientHeader) UnmarshalJSON(input []byte) error {
|
||||
var dec lightClientHeaderMarshaling
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
return err
|
||||
}
|
||||
*h = LightClientHeader{dec.Beacon}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Boostrap is response to the bootstap endpoint in the beacon API.
|
||||
type Bootstrap struct {
|
||||
Header LightClientHeader `json:"header"`
|
||||
Committee *types.SerializedSyncCommittee `json:"current_sync_committee"`
|
||||
CommitteeBranch merkle.Values `json:"current_sync_committee_branch"`
|
||||
}
|
||||
|
||||
// Valid verifies the current committee root is correctly encoded in the beacon
|
||||
// state of the weak-subjectivity checkpoint.
|
||||
func (b *Bootstrap) Valid() error {
|
||||
root := merkle.Value(b.Committee.Root())
|
||||
if err := merkle.VerifyProof(b.Header.StateRoot, params.StateIndexSyncCommittee, b.CommitteeBranch, root); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type bootstrapMarshaling struct {
|
||||
Data struct {
|
||||
Header LightClientHeader `json:"header"`
|
||||
Committee *types.SerializedSyncCommittee `json:"current_sync_committee"`
|
||||
CommitteeBranch merkle.Values `json:"current_sync_committee_branch"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// MarshalJSON marshals as JSON.
|
||||
func (b Bootstrap) MarshalJSON() ([]byte, error) {
|
||||
var enc bootstrapMarshaling
|
||||
enc.Data.Header = b.Header
|
||||
enc.Data.Committee = b.Committee
|
||||
enc.Data.CommitteeBranch = b.CommitteeBranch
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals from JSON.
|
||||
func (b *Bootstrap) UnmarshalJSON(input []byte) error {
|
||||
var dec bootstrapMarshaling
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
return err
|
||||
}
|
||||
b.Header = dec.Data.Header
|
||||
b.Committee = dec.Data.Committee
|
||||
b.CommitteeBranch = dec.Data.CommitteeBranch
|
||||
return nil
|
||||
}
|
||||
|
||||
// LightClientUpdate represents the possible light client updates the beacon api
|
||||
// may respond with.
|
||||
type LightClientUpdate struct {
|
||||
AttestedHeader LightClientHeader // Arbitrary header out of the period signed by the sync committee
|
||||
SyncAggregate types.SyncAggregate // BLS aggregate signature from sync committee
|
||||
SignatureSlot uint64 // Slot at which the signature is computed
|
||||
NextSyncCommittee *types.SerializedSyncCommittee // Sync committee of the next period advertised in the current one
|
||||
NextSyncCommitteeBranch *merkle.Values // Proof for the next period's sync committee
|
||||
FinalizedHeader *LightClientHeader // Optional header to announce a point of finality
|
||||
FinalityBranch *merkle.Values // Proof for the announced finality
|
||||
}
|
||||
|
||||
type lightClientUpdateMarshaling struct {
|
||||
Data struct {
|
||||
AttestedHeader LightClientHeader `json:"attested_header"`
|
||||
SyncAggregate types.SyncAggregate `json:"sync_aggregate"`
|
||||
SignatureSlot common.Decimal `json:"signature_slot"`
|
||||
NextSyncCommittee *types.SerializedSyncCommittee `json:"next_sync_committee"`
|
||||
NextSyncCommitteeBranch *merkle.Values `json:"next_sync_committee_branch"`
|
||||
FinalizedHeader *LightClientHeader `json:"finalized_header"`
|
||||
FinalityBranch *merkle.Values `json:"finality_branch"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// MarshalJSON marshals to JSON.
|
||||
func (u LightClientUpdate) MarshalJSON() ([]byte, error) {
|
||||
var enc lightClientUpdateMarshaling
|
||||
enc.Data.AttestedHeader = u.AttestedHeader
|
||||
enc.Data.SyncAggregate = u.SyncAggregate
|
||||
enc.Data.SignatureSlot = common.Decimal(u.SignatureSlot)
|
||||
enc.Data.NextSyncCommittee = u.NextSyncCommittee
|
||||
enc.Data.NextSyncCommitteeBranch = u.NextSyncCommitteeBranch
|
||||
enc.Data.FinalizedHeader = u.FinalizedHeader
|
||||
enc.Data.FinalityBranch = u.FinalityBranch
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals from JSON.
|
||||
func (u *LightClientUpdate) UnmarshalJSON(input []byte) error {
|
||||
var dec lightClientUpdateMarshaling
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
return err
|
||||
}
|
||||
u.AttestedHeader = dec.Data.AttestedHeader
|
||||
u.SyncAggregate = dec.Data.SyncAggregate
|
||||
u.SignatureSlot = uint64(dec.Data.SignatureSlot)
|
||||
u.NextSyncCommittee = dec.Data.NextSyncCommittee
|
||||
u.NextSyncCommitteeBranch = dec.Data.NextSyncCommitteeBranch
|
||||
u.FinalizedHeader = dec.Data.FinalizedHeader
|
||||
u.FinalityBranch = dec.Data.FinalityBranch
|
||||
return nil
|
||||
}
|
||||
|
||||
// Compare will compare two light client updates and determine the better one.
|
||||
// If next is not better than curr, it will error.
|
||||
func (curr *LightClientUpdate) Compare(next *LightClientUpdate) error {
|
||||
if curr == nil {
|
||||
// Nothing to compare.
|
||||
return nil
|
||||
}
|
||||
var (
|
||||
maxActiveParticipants = params.SyncCommitteeSize
|
||||
newNumActiveParticipants = next.SyncAggregate.SignerCount()
|
||||
oldNumActiveParticipants = curr.SyncAggregate.SignerCount()
|
||||
newHasSupermajority = newNumActiveParticipants*3 >= maxActiveParticipants*2
|
||||
oldHasSupermajority = oldNumActiveParticipants*3 >= maxActiveParticipants*2
|
||||
)
|
||||
if newHasSupermajority && !oldHasSupermajority {
|
||||
return nil
|
||||
} else if !newHasSupermajority && oldHasSupermajority {
|
||||
return fmt.Errorf("new update does not have supermajority while old does")
|
||||
}
|
||||
if !newHasSupermajority && newNumActiveParticipants > oldNumActiveParticipants {
|
||||
return nil
|
||||
} else if !newHasSupermajority && newNumActiveParticipants <= oldNumActiveParticipants {
|
||||
return fmt.Errorf("more active participants in old update")
|
||||
}
|
||||
|
||||
// TODO: implement all tie breakers from spec
|
||||
// var (
|
||||
// sigPeriod = slotToSyncCommitteePeriod(next.SignatureSlot)
|
||||
// newHasRelevantSyncCommitteeUpdate = next.NextSyncCommittee != nil && (slotToSyncCommitteePeriod(next.AttestedHeader.Slot) == sigPeriod)
|
||||
// oldHasRelevantSyncCommitteeUpdate = curr.NextSyncCommittee != nil && (slotToSyncCommitteePeriod(curr.AttestedHeader.Slot) == sigPeriod)
|
||||
// )
|
||||
// if !newHasRelevantSyncCommitteeUpdate && oldHasRelevantSyncCommitteeUpdate {
|
||||
// return fmt.Errorf("old update also includes sync committee update")
|
||||
// }
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// versionedBlockToExecutableData parses versioned blocks and returns a generic
|
||||
// execution payload object.
|
||||
func versionedBlockToExecutableData(block *eth2spec.VersionedSignedBeaconBlock) *engine.ExecutableData {
|
||||
var ep *engine.ExecutableData
|
||||
switch block.Version {
|
||||
case eth2spec.DataVersionPhase0:
|
||||
panic("phase0 block has no execution payload to send")
|
||||
case eth2spec.DataVersionAltair:
|
||||
panic("altair block has no execution payload to send")
|
||||
case eth2spec.DataVersionBellatrix:
|
||||
p := block.Bellatrix.Message.Body.ExecutionPayload
|
||||
ep = &engine.ExecutableData{
|
||||
ParentHash: common.Hash(p.ParentHash),
|
||||
FeeRecipient: common.Address(p.FeeRecipient),
|
||||
StateRoot: p.StateRoot,
|
||||
ReceiptsRoot: p.ReceiptsRoot,
|
||||
LogsBloom: p.LogsBloom[:],
|
||||
Random: p.PrevRandao,
|
||||
Number: p.BlockNumber,
|
||||
GasLimit: p.GasLimit,
|
||||
GasUsed: p.GasUsed,
|
||||
Timestamp: p.Timestamp,
|
||||
ExtraData: p.ExtraData,
|
||||
BaseFeePerGas: new(big.Int).SetBytes(reverse(p.BaseFeePerGas[:])),
|
||||
BlockHash: common.Hash(p.BlockHash),
|
||||
Transactions: [][]byte{},
|
||||
Withdrawals: nil,
|
||||
BlobGasUsed: nil,
|
||||
ExcessBlobGas: nil,
|
||||
}
|
||||
for _, tx := range p.Transactions {
|
||||
ep.Transactions = append(ep.Transactions, tx)
|
||||
}
|
||||
case eth2spec.DataVersionCapella:
|
||||
p := block.Capella.Message.Body.ExecutionPayload
|
||||
ep = &engine.ExecutableData{
|
||||
ParentHash: common.Hash(p.ParentHash),
|
||||
FeeRecipient: common.Address(p.FeeRecipient),
|
||||
StateRoot: p.StateRoot,
|
||||
ReceiptsRoot: p.ReceiptsRoot,
|
||||
LogsBloom: p.LogsBloom[:],
|
||||
Random: p.PrevRandao,
|
||||
Number: p.BlockNumber,
|
||||
GasLimit: p.GasLimit,
|
||||
GasUsed: p.GasUsed,
|
||||
Timestamp: p.Timestamp,
|
||||
ExtraData: p.ExtraData,
|
||||
BaseFeePerGas: new(big.Int).SetBytes(reverse(p.BaseFeePerGas[:])),
|
||||
BlockHash: common.Hash(p.BlockHash),
|
||||
Transactions: [][]byte{},
|
||||
Withdrawals: nil,
|
||||
BlobGasUsed: nil,
|
||||
ExcessBlobGas: nil,
|
||||
}
|
||||
for _, tx := range p.Transactions {
|
||||
ep.Transactions = append(ep.Transactions, tx)
|
||||
}
|
||||
for _, wx := range p.Withdrawals {
|
||||
ep.Withdrawals = append(ep.Withdrawals, &ctypes.Withdrawal{
|
||||
Index: uint64(wx.Index),
|
||||
Validator: uint64(wx.ValidatorIndex),
|
||||
Address: common.Address(wx.Address),
|
||||
Amount: uint64(wx.Amount),
|
||||
})
|
||||
}
|
||||
case eth2spec.DataVersionDeneb:
|
||||
p := block.Deneb.Message.Body.ExecutionPayload
|
||||
ep = &engine.ExecutableData{
|
||||
ParentHash: common.Hash(p.ParentHash),
|
||||
FeeRecipient: common.Address(p.FeeRecipient),
|
||||
StateRoot: common.Hash(p.StateRoot),
|
||||
ReceiptsRoot: common.Hash(p.ReceiptsRoot),
|
||||
LogsBloom: p.LogsBloom[:],
|
||||
Random: p.PrevRandao,
|
||||
Number: p.BlockNumber,
|
||||
GasLimit: p.GasLimit,
|
||||
GasUsed: p.GasUsed,
|
||||
Timestamp: p.Timestamp,
|
||||
ExtraData: p.ExtraData,
|
||||
BaseFeePerGas: nil, // TODO: convert this []uint64 correctly to big.Int
|
||||
BlockHash: common.Hash(p.BlockHash),
|
||||
Transactions: [][]byte{},
|
||||
Withdrawals: nil,
|
||||
BlobGasUsed: &p.BlobGasUsed,
|
||||
ExcessBlobGas: &p.ExcessBlobGas,
|
||||
}
|
||||
for _, tx := range p.Transactions {
|
||||
ep.Transactions = append(ep.Transactions, tx)
|
||||
}
|
||||
for _, wx := range p.Withdrawals {
|
||||
ep.Withdrawals = append(ep.Withdrawals, &ctypes.Withdrawal{
|
||||
Index: uint64(wx.Index),
|
||||
Validator: uint64(wx.ValidatorIndex),
|
||||
Address: common.Address(wx.Address),
|
||||
Amount: uint64(wx.Amount),
|
||||
})
|
||||
}
|
||||
default:
|
||||
panic("unknown beacon block version")
|
||||
}
|
||||
return ep
|
||||
}
|
||||
|
||||
func reverse(b []byte) []byte {
|
||||
for i := 0; i < len(b)/2; i++ {
|
||||
j := len(b) - i - 1
|
||||
b[i], b[j] = b[j], b[i]
|
||||
}
|
||||
return b
|
||||
}
|
||||
2
go.mod
2
go.mod
|
|
@ -72,7 +72,6 @@ require (
|
|||
golang.org/x/time v0.3.0
|
||||
golang.org/x/tools v0.15.0
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
@ -154,5 +153,6 @@ require (
|
|||
google.golang.org/protobuf v1.30.0 // indirect
|
||||
gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
rsc.io/tmplfunc v0.0.3 // indirect
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue