github.com/ethereum/go-ethereum@v1.16.1/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  	"github.com/ethereum/go-ethereum/beacon/light"
    21  	"github.com/ethereum/go-ethereum/beacon/light/api"
    22  	"github.com/ethereum/go-ethereum/beacon/light/request"
    23  	"github.com/ethereum/go-ethereum/beacon/light/sync"
    24  	"github.com/ethereum/go-ethereum/beacon/params"
    25  	"github.com/ethereum/go-ethereum/beacon/types"
    26  	"github.com/ethereum/go-ethereum/common"
    27  	"github.com/ethereum/go-ethereum/common/mclock"
    28  	"github.com/ethereum/go-ethereum/ethdb/memorydb"
    29  	"github.com/ethereum/go-ethereum/event"
    30  	"github.com/ethereum/go-ethereum/log"
    31  	"github.com/ethereum/go-ethereum/rpc"
    32  )
    33  
    34  type Client struct {
    35  	urls         []string
    36  	customHeader map[string]string
    37  	config       *params.ClientConfig
    38  	scheduler    *request.Scheduler
    39  	blockSync    *beaconBlockSync
    40  	engineRPC    *rpc.Client
    41  
    42  	chainHeadSub event.Subscription
    43  	engineClient *engineClient
    44  }
    45  
    46  func NewClient(config params.ClientConfig) *Client {
    47  	// create data structures
    48  	var (
    49  		db             = memorydb.New()
    50  		committeeChain = light.NewCommitteeChain(db, &config.ChainConfig, config.Threshold, !config.NoFilter)
    51  		headTracker    = light.NewHeadTracker(committeeChain, config.Threshold, func(checkpoint common.Hash) {
    52  			if saved, err := config.SaveCheckpointToFile(checkpoint); saved {
    53  				log.Debug("Saved beacon checkpoint", "file", config.CheckpointFile, "checkpoint", checkpoint)
    54  			} else if err != nil {
    55  				log.Error("Failed to save beacon checkpoint", "file", config.CheckpointFile, "checkpoint", checkpoint, "error", err)
    56  			}
    57  		})
    58  	)
    59  	headSync := sync.NewHeadSync(headTracker, committeeChain)
    60  
    61  	// set up scheduler and sync modules
    62  	scheduler := request.NewScheduler()
    63  	checkpointInit := sync.NewCheckpointInit(committeeChain, config.Checkpoint)
    64  	forwardSync := sync.NewForwardUpdateSync(committeeChain)
    65  	beaconBlockSync := newBeaconBlockSync(headTracker)
    66  	scheduler.RegisterTarget(headTracker)
    67  	scheduler.RegisterTarget(committeeChain)
    68  	scheduler.RegisterModule(checkpointInit, "checkpointInit")
    69  	scheduler.RegisterModule(forwardSync, "forwardSync")
    70  	scheduler.RegisterModule(headSync, "headSync")
    71  	scheduler.RegisterModule(beaconBlockSync, "beaconBlockSync")
    72  
    73  	return &Client{
    74  		scheduler:    scheduler,
    75  		urls:         config.Apis,
    76  		customHeader: config.CustomHeader,
    77  		config:       &config,
    78  		blockSync:    beaconBlockSync,
    79  	}
    80  }
    81  
    82  func (c *Client) SetEngineRPC(engine *rpc.Client) {
    83  	c.engineRPC = engine
    84  }
    85  
    86  func (c *Client) Start() error {
    87  	headCh := make(chan types.ChainHeadEvent, 16)
    88  	c.chainHeadSub = c.blockSync.SubscribeChainHead(headCh)
    89  	c.engineClient = startEngineClient(c.config, c.engineRPC, headCh)
    90  
    91  	c.scheduler.Start()
    92  	for _, url := range c.urls {
    93  		beaconApi := api.NewBeaconLightApi(url, c.customHeader)
    94  		c.scheduler.RegisterServer(request.NewServer(api.NewApiServer(beaconApi), &mclock.System{}))
    95  	}
    96  	return nil
    97  }
    98  
    99  func (c *Client) Stop() error {
   100  	c.engineClient.stop()
   101  	c.chainHeadSub.Unsubscribe()
   102  	c.scheduler.Stop()
   103  	return nil
   104  }