github.com/ethereum/go-ethereum@v1.14.3/beacon/blsync/client.go (about)

     1  // Copyright 2024 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package blsync
    18  
    19  import (
    20  	"strings"
    21  
    22  	"github.com/ethereum/go-ethereum/beacon/light"
    23  	"github.com/ethereum/go-ethereum/beacon/light/api"
    24  	"github.com/ethereum/go-ethereum/beacon/light/request"
    25  	"github.com/ethereum/go-ethereum/beacon/light/sync"
    26  	"github.com/ethereum/go-ethereum/beacon/types"
    27  	"github.com/ethereum/go-ethereum/cmd/utils"
    28  	"github.com/ethereum/go-ethereum/common/mclock"
    29  	"github.com/ethereum/go-ethereum/ethdb/memorydb"
    30  	"github.com/ethereum/go-ethereum/event"
    31  	"github.com/ethereum/go-ethereum/rpc"
    32  	"github.com/urfave/cli/v2"
    33  )
    34  
    35  type Client struct {
    36  	urls         []string
    37  	customHeader map[string]string
    38  	chainConfig  *lightClientConfig
    39  	scheduler    *request.Scheduler
    40  	blockSync    *beaconBlockSync
    41  	engineRPC    *rpc.Client
    42  
    43  	chainHeadSub event.Subscription
    44  	engineClient *engineClient
    45  }
    46  
    47  func NewClient(ctx *cli.Context) *Client {
    48  	if !ctx.IsSet(utils.BeaconApiFlag.Name) {
    49  		utils.Fatalf("Beacon node light client API URL not specified")
    50  	}
    51  	var (
    52  		chainConfig  = makeChainConfig(ctx)
    53  		customHeader = make(map[string]string)
    54  	)
    55  	for _, s := range ctx.StringSlice(utils.BeaconApiHeaderFlag.Name) {
    56  		kv := strings.Split(s, ":")
    57  		if len(kv) != 2 {
    58  			utils.Fatalf("Invalid custom API header entry: %s", s)
    59  		}
    60  		customHeader[strings.TrimSpace(kv[0])] = strings.TrimSpace(kv[1])
    61  	}
    62  
    63  	// create data structures
    64  	var (
    65  		db             = memorydb.New()
    66  		threshold      = ctx.Int(utils.BeaconThresholdFlag.Name)
    67  		committeeChain = light.NewCommitteeChain(db, chainConfig.ChainConfig, threshold, !ctx.Bool(utils.BeaconNoFilterFlag.Name))
    68  		headTracker    = light.NewHeadTracker(committeeChain, threshold)
    69  	)
    70  	headSync := sync.NewHeadSync(headTracker, committeeChain)
    71  
    72  	// set up scheduler and sync modules
    73  	scheduler := request.NewScheduler()
    74  	checkpointInit := sync.NewCheckpointInit(committeeChain, chainConfig.Checkpoint)
    75  	forwardSync := sync.NewForwardUpdateSync(committeeChain)
    76  	beaconBlockSync := newBeaconBlockSync(headTracker)
    77  	scheduler.RegisterTarget(headTracker)
    78  	scheduler.RegisterTarget(committeeChain)
    79  	scheduler.RegisterModule(checkpointInit, "checkpointInit")
    80  	scheduler.RegisterModule(forwardSync, "forwardSync")
    81  	scheduler.RegisterModule(headSync, "headSync")
    82  	scheduler.RegisterModule(beaconBlockSync, "beaconBlockSync")
    83  
    84  	return &Client{
    85  		scheduler:    scheduler,
    86  		urls:         ctx.StringSlice(utils.BeaconApiFlag.Name),
    87  		customHeader: customHeader,
    88  		chainConfig:  &chainConfig,
    89  		blockSync:    beaconBlockSync,
    90  	}
    91  }
    92  
    93  func (c *Client) SetEngineRPC(engine *rpc.Client) {
    94  	c.engineRPC = engine
    95  }
    96  
    97  func (c *Client) Start() error {
    98  	headCh := make(chan types.ChainHeadEvent, 16)
    99  	c.chainHeadSub = c.blockSync.SubscribeChainHead(headCh)
   100  	c.engineClient = startEngineClient(c.chainConfig, c.engineRPC, headCh)
   101  
   102  	c.scheduler.Start()
   103  	for _, url := range c.urls {
   104  		beaconApi := api.NewBeaconLightApi(url, c.customHeader)
   105  		c.scheduler.RegisterServer(request.NewServer(api.NewApiServer(beaconApi), &mclock.System{}))
   106  	}
   107  	return nil
   108  }
   109  
   110  func (c *Client) Stop() error {
   111  	c.engineClient.stop()
   112  	c.chainHeadSub.Unsubscribe()
   113  	c.scheduler.Stop()
   114  	return nil
   115  }