mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
all: integrate blsync into geth cmd
This commit is contained in:
parent
ca0feab9d3
commit
b3289536f1
11 changed files with 181 additions and 233 deletions
|
|
@ -40,6 +40,7 @@ type LightClient struct {
|
|||
store *store
|
||||
|
||||
chainHeadFeed event.Feed
|
||||
quitCh chan struct{}
|
||||
}
|
||||
|
||||
// Bootstrap retrieves a light client bootstrap and authenticates it against the
|
||||
|
|
@ -68,6 +69,7 @@ func Bootstrap(ctx context.Context, server string, root common.Hash) (*LightClie
|
|||
optimistic: &bs.Header.Header,
|
||||
finalized: &bs.Header.Header,
|
||||
},
|
||||
quitCh: make(chan struct{}),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -90,65 +92,72 @@ func (c *LightClient) Finalized() *types.Header {
|
|||
|
||||
// Start executes the main active loop of the light client which drives the
|
||||
// underlying light client store.
|
||||
func (c *LightClient) Start() {
|
||||
log.Info("beacon light client starting")
|
||||
func (c *LightClient) Start() error {
|
||||
var (
|
||||
ticker = time.NewTicker(params.SlotLength * time.Second)
|
||||
lastFinality = time.Now()
|
||||
)
|
||||
for ; ; <-ticker.C {
|
||||
if c.store.next == nil {
|
||||
log.Debug("fetching committee update", "period", c.store.finalizedPeriod())
|
||||
updates, err := c.beacon.GetRangeUpdate(c.store.finalizedPeriod(), 1)
|
||||
if err != nil {
|
||||
log.Error("failed to fetch next committee", "err", err)
|
||||
} else {
|
||||
for _, update := range updates {
|
||||
if err := c.store.Insert(update); err != nil {
|
||||
log.Error("failed to insert committee update", "err", err)
|
||||
break
|
||||
for {
|
||||
select {
|
||||
case <-c.quitCh:
|
||||
return nil
|
||||
case <-ticker.C:
|
||||
if c.store.next == nil {
|
||||
log.Debug("Fetching committee update", "period", c.store.finalizedPeriod())
|
||||
updates, err := c.beacon.GetRangeUpdate(c.store.finalizedPeriod(), 1)
|
||||
if err != nil {
|
||||
log.Error("Failed to fetch next committee", "err", err)
|
||||
} else {
|
||||
for _, update := range updates {
|
||||
if err := c.store.Insert(update); err != nil {
|
||||
log.Error("Failed to insert committee update", "err", err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
update *types.LightClientUpdate
|
||||
err error
|
||||
)
|
||||
if time.Since(lastFinality) > time.Minute*5 {
|
||||
log.Trace("fetching finality update")
|
||||
lastFinality = time.Now()
|
||||
update, err = c.beacon.GetFinalityUpdate()
|
||||
} else {
|
||||
log.Trace("fetching optimistic update")
|
||||
update, err = c.beacon.GetOptimisticUpdate()
|
||||
}
|
||||
if err != nil {
|
||||
log.Error("failed to retrieve update", "err", err)
|
||||
continue
|
||||
}
|
||||
log.Trace("got update", "slot", update.AttestedHeader.Slot, "root", update.AttestedHeader.Hash(), "sigslot", update.SignatureSlot, "period", update.AttestedHeader.SyncPeriod(), "hasFinalized", update.FinalizedHeader != nil, "hasNext", update.NextSyncCommittee != nil)
|
||||
if err := c.store.Insert(update); err != nil {
|
||||
log.Error("failed to insert update", "err", err)
|
||||
continue
|
||||
}
|
||||
head := update.AttestedHeader
|
||||
log.Info("beacon head updated", "slot", head.Slot, "root", head.Hash(), "finalized", c.Finalized().Hash(), "signers", update.SyncAggregate.SignerCount())
|
||||
var (
|
||||
update *types.LightClientUpdate
|
||||
err error
|
||||
)
|
||||
if time.Since(lastFinality) > time.Minute*5 {
|
||||
lastFinality = time.Now()
|
||||
update, err = c.beacon.GetFinalityUpdate()
|
||||
} else {
|
||||
update, err = c.beacon.GetOptimisticUpdate()
|
||||
}
|
||||
if err != nil {
|
||||
log.Error("Failed to retrieve update", "err", err)
|
||||
continue
|
||||
}
|
||||
log.Trace("New beacon update", "slot", update.AttestedHeader.Slot, "root", update.AttestedHeader.Hash(), "sigslot", update.SignatureSlot, "period", update.AttestedHeader.SyncPeriod(), "hasFinalized", update.FinalizedHeader != nil, "hasNext", update.NextSyncCommittee != nil)
|
||||
if err := c.store.Insert(update); err != nil {
|
||||
log.Error("Failed to insert update", "err", err)
|
||||
continue
|
||||
}
|
||||
head := update.AttestedHeader
|
||||
log.Info("Beacon head updated", "slot", head.Slot, "root", head.Hash(), "finalized", c.Finalized().Hash(), "signers", update.SyncAggregate.SignerCount())
|
||||
|
||||
// Fetch full execution payload from beacon provider and send to head feed.
|
||||
data, err := c.getExecutableData(head.Hash())
|
||||
if err != nil {
|
||||
log.Error("failed to insert update", "err", err)
|
||||
continue
|
||||
// Fetch full execution payload from beacon provider and send to head feed.
|
||||
data, err := c.fetchExecutableData(head.Hash())
|
||||
if err != nil {
|
||||
log.Error("Failed to insert update", "err", err)
|
||||
continue
|
||||
}
|
||||
c.chainHeadFeed.Send(ChainHeadEvent{Data: data})
|
||||
}
|
||||
c.chainHeadFeed.Send(ChainHeadEvent{Data: data})
|
||||
}
|
||||
}
|
||||
|
||||
// getExecutableData retrieves the full beacon block associated with the beacon
|
||||
func (c *LightClient) Stop() error {
|
||||
close(c.quitCh)
|
||||
return nil
|
||||
}
|
||||
|
||||
// fetchExecutableData retrieves the full beacon block associated with the beacon
|
||||
// block root and returns the inner execution payload.
|
||||
func (c *LightClient) getExecutableData(head common.Hash) (*engine.ExecutableData, error) {
|
||||
func (c *LightClient) fetchExecutableData(head common.Hash) (*engine.ExecutableData, error) {
|
||||
block, err := c.beacon.GetBlock(head)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get execution payload: %w", err)
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ import (
|
|||
"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 (
|
||||
|
|
@ -71,7 +70,6 @@ func (s *store) validate(update *types.LightClientUpdate) error {
|
|||
)
|
||||
// Verify update does not skip a sync committee.
|
||||
if updatePeriod != storedPeriod && (s.next == nil || updatePeriod != storedPeriod+1) {
|
||||
log.Error("update not from current or next sync committee", "stored", storedPeriod, "update", updatePeriod)
|
||||
return errWrongPeriod
|
||||
}
|
||||
if !(update.AttestedHeader.Slot > s.finalized.Slot || update.NextSyncCommittee != nil) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2024 The go-ethereum Authors
|
||||
// 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
|
||||
|
|
|
|||
|
|
@ -1,185 +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 (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"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"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/node"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"github.com/mattn/go-colorable"
|
||||
"github.com/mattn/go-isatty"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var app = &cli.App{
|
||||
Usage: "go-ethereum beacon light sync tool",
|
||||
Action: run,
|
||||
}
|
||||
|
||||
var (
|
||||
EngineApiFlag = &cli.StringFlag{
|
||||
Name: "engine",
|
||||
Usage: "url to execution client engine api",
|
||||
}
|
||||
JwtSecretFlag = &cli.StringFlag{
|
||||
Name: "jwtsecret",
|
||||
Usage: "path to jwt secret used to communicate with execution client",
|
||||
}
|
||||
LightClientServerFlag = &cli.StringFlag{
|
||||
Name: "server",
|
||||
Usage: "server which provides the beacon light client apis",
|
||||
}
|
||||
TrustedBlockRootFlag = &cli.StringFlag{
|
||||
Name: "trusted-root",
|
||||
Usage: "root of trusted block within the weak-subjectivity window",
|
||||
}
|
||||
VerbosityFlag = &cli.IntFlag{
|
||||
Name: "verbosity",
|
||||
Usage: "Logging verbosity: 0=silent, 1=error, 2=warn, 3=info, 4=debug, 5=detail",
|
||||
Value: 3,
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
app.Flags = flags.Merge([]cli.Flag{
|
||||
EngineApiFlag,
|
||||
JwtSecretFlag,
|
||||
LightClientServerFlag,
|
||||
TrustedBlockRootFlag,
|
||||
VerbosityFlag,
|
||||
})
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func run(ctx *cli.Context) error {
|
||||
// Setup logger.
|
||||
var (
|
||||
usecolor = (isatty.IsTerminal(os.Stderr.Fd()) || isatty.IsCygwinTerminal(os.Stderr.Fd())) && os.Getenv("TERM") != "dumb"
|
||||
output = io.Writer(os.Stdout)
|
||||
verbosity = log.FromLegacyLevel(ctx.Int(VerbosityFlag.Name))
|
||||
)
|
||||
if usecolor {
|
||||
output = colorable.NewColorable(os.Stdout)
|
||||
}
|
||||
log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(output, verbosity, usecolor)))
|
||||
|
||||
// Start light client.
|
||||
var (
|
||||
root = ctx.String(TrustedBlockRootFlag.Name)
|
||||
engine = makeRPCClient(ctx)
|
||||
server = ctx.String(LightClientServerFlag.Name)
|
||||
)
|
||||
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 light.ChainHeadEvent)
|
||||
chain.SubscribeChainHeadEvent(headCh)
|
||||
|
||||
// Send new head events to engine api.
|
||||
for {
|
||||
select {
|
||||
case head := <-headCh:
|
||||
if err := sendUpdate(engine, head.Data, chain.Finalized().Hash()); err != nil {
|
||||
log.Error("unable to send update to execution client", "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sendUpdate passes the execution payload to execution client and affirms it
|
||||
// with a forck choice updated.
|
||||
func sendUpdate(engine *rpc.Client, ep *engine.ExecutableData, finalized common.Hash) error {
|
||||
if _, err := callNewPayloadV2(engine, ep); err != nil {
|
||||
return fmt.Errorf("failed to send new payload: %w", err)
|
||||
}
|
||||
if _, err := callForkchoiceUpdatedV1(engine, ep.BlockHash, finalized); err != nil {
|
||||
return fmt.Errorf("failed to send forkchoice updated: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func makeRPCClient(ctx *cli.Context) *rpc.Client {
|
||||
if !ctx.IsSet(EngineApiFlag.Name) {
|
||||
log.Warn("No engine API target specified, performing a dry run")
|
||||
return nil
|
||||
}
|
||||
if !ctx.IsSet(JwtSecretFlag.Name) {
|
||||
exit(fmt.Errorf("JWT secret parameter missing")) // TODO use default if datadir is specified
|
||||
}
|
||||
engineApiUrl, jwtFileName := ctx.String(EngineApiFlag.Name), ctx.String(JwtSecretFlag.Name)
|
||||
var jwtSecret [32]byte
|
||||
if jwt, err := os.ReadFile(jwtFileName); err != nil {
|
||||
utils.Fatalf("Error loading or generating JWT secret: %v", err)
|
||||
} else {
|
||||
copy(jwtSecret[:], common.FromHex(string(jwt)))
|
||||
}
|
||||
auth := node.NewJWTAuth(jwtSecret)
|
||||
cl, err := rpc.DialOptions(context.Background(), engineApiUrl, rpc.WithHTTPAuth(auth))
|
||||
if err != nil {
|
||||
utils.Fatalf("Could not create RPC client: %v", err)
|
||||
}
|
||||
return cl
|
||||
}
|
||||
|
||||
func callNewPayloadV2(client *rpc.Client, ep *engine.ExecutableData) (string, error) {
|
||||
var resp engine.PayloadStatusV1
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||
err := client.CallContext(ctx, &resp, "engine_newPayloadV2", ep)
|
||||
cancel()
|
||||
return resp.Status, err
|
||||
}
|
||||
|
||||
func callForkchoiceUpdatedV1(client *rpc.Client, headHash, finalizedHash common.Hash) (string, error) {
|
||||
var resp engine.ForkChoiceResponse
|
||||
update := engine.ForkchoiceStateV1{
|
||||
HeadBlockHash: headHash,
|
||||
SafeBlockHash: common.Hash{},
|
||||
FinalizedBlockHash: common.Hash{},
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||
err := client.CallContext(ctx, &resp, "engine_forkchoiceUpdatedV1", update, nil)
|
||||
cancel()
|
||||
return resp.PayloadStatus.Status, err
|
||||
}
|
||||
|
||||
func exit(err interface{}) {
|
||||
if err == nil {
|
||||
os.Exit(0)
|
||||
}
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
|
@ -221,6 +221,9 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
|
|||
}
|
||||
catalyst.RegisterSimulatedBeaconAPIs(stack, simBeacon)
|
||||
stack.RegisterLifecycle(simBeacon)
|
||||
} else if ctx.IsSet(utils.BeaconAPIFlag.Name) && ctx.IsSet(utils.BeaconTrustedBlockRootFlag.Name) {
|
||||
blsync := catalyst.NewBlsync(eth)
|
||||
stack.RegisterLifecycle(blsync)
|
||||
} else {
|
||||
err := catalyst.Register(stack, eth)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -146,6 +146,8 @@ var (
|
|||
configFileFlag,
|
||||
utils.LogDebugFlag,
|
||||
utils.LogBacktraceAtFlag,
|
||||
utils.BeaconAPIFlag,
|
||||
utils.BeaconTrustedBlockRootFlag,
|
||||
}, utils.NetworkFlags, utils.DatabaseFlags)
|
||||
|
||||
rpcFlags = []cli.Flag{
|
||||
|
|
|
|||
|
|
@ -908,6 +908,18 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server.
|
|||
Value: metrics.DefaultConfig.InfluxDBOrganization,
|
||||
Category: flags.MetricsCategory,
|
||||
}
|
||||
|
||||
// Beacon light client flags.
|
||||
BeaconAPIFlag = &cli.StringFlag{
|
||||
Name: "beacon.api",
|
||||
Usage: "server which provides the beacon light client apis",
|
||||
Category: flags.BeaconCategory,
|
||||
}
|
||||
BeaconTrustedBlockRootFlag = &cli.StringFlag{
|
||||
Name: "beacon.wss",
|
||||
Usage: "root of trusted block within the weak-subjectivity window",
|
||||
Category: flags.BeaconCategory,
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -1842,6 +1854,12 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
|||
if err := kzg4844.UseCKZG(ctx.String(CryptoKZGFlag.Name) == "ckzg"); err != nil {
|
||||
Fatalf("Failed to set KZG library implementation to %s: %v", ctx.String(CryptoKZGFlag.Name), err)
|
||||
}
|
||||
|
||||
if (ctx.IsSet(BeaconAPIFlag.Name) && !ctx.IsSet(BeaconTrustedBlockRootFlag.Name)) || (!ctx.IsSet(BeaconAPIFlag.Name) && ctx.IsSet(BeaconTrustedBlockRootFlag.Name)) {
|
||||
Fatalf("Must set both beacon api flag and beacon trusted block root flag to use beacon light client")
|
||||
}
|
||||
cfg.BeaconAPI = ctx.String(BeaconAPIFlag.Name)
|
||||
cfg.BeaconTrustedBlockRoot = ctx.String(BeaconTrustedBlockRootFlag.Name)
|
||||
}
|
||||
|
||||
// SetDNSDiscoveryDefaults configures DNS discovery with the given URL if
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
package eth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
|
@ -25,6 +26,7 @@ import (
|
|||
"sync"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/beacon/light"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/consensus"
|
||||
|
|
@ -71,6 +73,7 @@ type Ethereum struct {
|
|||
txPool *txpool.TxPool
|
||||
|
||||
blockchain *core.BlockChain
|
||||
beacon *light.LightClient
|
||||
handler *handler
|
||||
ethDialCandidates enode.Iterator
|
||||
snapDialCandidates enode.Iterator
|
||||
|
|
@ -273,6 +276,14 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if config.BeaconAPI != "" && config.BeaconTrustedBlockRoot != "" {
|
||||
beacon, err := light.Bootstrap(context.Background(), config.BeaconAPI, common.HexToHash(config.BeaconTrustedBlockRoot))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
eth.beacon = beacon
|
||||
}
|
||||
|
||||
// Start the RPC service
|
||||
eth.netRPCService = ethapi.NewNetAPI(eth.p2pServer, networkID)
|
||||
|
||||
|
|
@ -476,6 +487,7 @@ func (s *Ethereum) Miner() *miner.Miner { return s.miner }
|
|||
|
||||
func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager }
|
||||
func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain }
|
||||
func (s *Ethereum) Beacon() *light.LightClient { return s.beacon }
|
||||
func (s *Ethereum) TxPool() *txpool.TxPool { return s.txPool }
|
||||
func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux }
|
||||
func (s *Ethereum) Engine() consensus.Engine { return s.engine }
|
||||
|
|
|
|||
86
eth/catalyst/blsync.go
Normal file
86
eth/catalyst/blsync.go
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
// 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 catalyst
|
||||
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/beacon/engine"
|
||||
"github.com/ethereum/go-ethereum/beacon/light"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/eth"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
)
|
||||
|
||||
// Blsync tracks the head of the beacon chain through the beacon light client
|
||||
// and drives the local node via ConsensusAPI.
|
||||
type Blsync struct {
|
||||
eth *eth.Ethereum
|
||||
engine *ConsensusAPI
|
||||
client *light.LightClient
|
||||
headCh chan light.ChainHeadEvent
|
||||
headSub event.Subscription
|
||||
|
||||
quitCh chan struct{}
|
||||
}
|
||||
|
||||
// NewBlsync creates a new beacon light syncer.
|
||||
func NewBlsync(eth *eth.Ethereum) *Blsync {
|
||||
engine := newConsensusAPIWithoutHeartbeat(eth)
|
||||
return &Blsync{
|
||||
eth: eth,
|
||||
engine: engine,
|
||||
client: eth.Beacon(),
|
||||
headCh: make(chan light.ChainHeadEvent, 128),
|
||||
quitCh: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
// Start starts underlying beacon light client and the sync logic for driving
|
||||
// the local node.
|
||||
func (b *Blsync) Start() error {
|
||||
log.Info("Blsync started")
|
||||
b.headSub = b.client.SubscribeChainHeadEvent(b.headCh)
|
||||
go b.client.Start()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-b.quitCh:
|
||||
return nil
|
||||
case head := <-b.headCh:
|
||||
if _, err := b.engine.NewPayloadV2(*head.Data); err != nil {
|
||||
log.Error("failed to send new payload", "err", err)
|
||||
continue
|
||||
}
|
||||
update := engine.ForkchoiceStateV1{
|
||||
HeadBlockHash: head.Data.BlockHash,
|
||||
SafeBlockHash: common.Hash{},
|
||||
FinalizedBlockHash: common.Hash{},
|
||||
}
|
||||
if _, err := b.engine.ForkchoiceUpdatedV1(update, nil); err != nil {
|
||||
log.Error("failed to send forkchoice updated", "err", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stop signals to the light client and syncer to exit.
|
||||
func (b *Blsync) Stop() error {
|
||||
b.client.Stop()
|
||||
close(b.quitCh)
|
||||
return nil
|
||||
}
|
||||
|
|
@ -113,6 +113,10 @@ type Config struct {
|
|||
LightNoPrune bool `toml:",omitempty"` // Whether to disable light chain pruning
|
||||
LightNoSyncServe bool `toml:",omitempty"` // Whether to serve light clients before syncing
|
||||
|
||||
// Beacon light client options
|
||||
BeaconAPI string
|
||||
BeaconTrustedBlockRoot string
|
||||
|
||||
// Database options
|
||||
SkipBcVersionCheck bool `toml:"-"`
|
||||
DatabaseHandles int `toml:"-"`
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import "github.com/urfave/cli/v2"
|
|||
|
||||
const (
|
||||
EthCategory = "ETHEREUM"
|
||||
BeaconCategory = "BEACON"
|
||||
LightCategory = "LIGHT CLIENT"
|
||||
DevCategory = "DEVELOPER CHAIN"
|
||||
StateCategory = "STATE HISTORY MANAGEMENT"
|
||||
|
|
|
|||
Loading…
Reference in a new issue