github.com/tirogen/go-ethereum@v1.10.12-0.20221226051715-250cfede41b6/eth/catalyst/tester.go (about)

     1  // Copyright 2022 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 catalyst
    18  
    19  import (
    20  	"sync"
    21  	"time"
    22  
    23  	"github.com/tirogen/go-ethereum/core/beacon"
    24  	"github.com/tirogen/go-ethereum/core/types"
    25  	"github.com/tirogen/go-ethereum/eth"
    26  	"github.com/tirogen/go-ethereum/log"
    27  	"github.com/tirogen/go-ethereum/node"
    28  )
    29  
    30  // FullSyncTester is an auxiliary service that allows Geth to perform full sync
    31  // alone without consensus-layer attached. Users must specify a valid block as
    32  // the sync target. This tester can be applied to different networks, no matter
    33  // it's pre-merge or post-merge, but only for full-sync.
    34  type FullSyncTester struct {
    35  	api    *ConsensusAPI
    36  	block  *types.Block
    37  	closed chan struct{}
    38  	wg     sync.WaitGroup
    39  }
    40  
    41  // RegisterFullSyncTester registers the full-sync tester service into the node
    42  // stack for launching and stopping the service controlled by node.
    43  func RegisterFullSyncTester(stack *node.Node, backend *eth.Ethereum, block *types.Block) (*FullSyncTester, error) {
    44  	cl := &FullSyncTester{
    45  		api:    NewConsensusAPI(backend),
    46  		block:  block,
    47  		closed: make(chan struct{}),
    48  	}
    49  	stack.RegisterLifecycle(cl)
    50  	return cl, nil
    51  }
    52  
    53  // Start launches the full-sync tester by spinning up a background thread
    54  // for keeping firing NewPayload-UpdateForkChoice combos with the provided
    55  // target block, it may or may not trigger the beacon sync depends on if
    56  // there are protocol peers connected.
    57  func (tester *FullSyncTester) Start() error {
    58  	tester.wg.Add(1)
    59  	go func() {
    60  		defer tester.wg.Done()
    61  
    62  		ticker := time.NewTicker(time.Second * 5)
    63  		defer ticker.Stop()
    64  
    65  		for {
    66  			select {
    67  			case <-ticker.C:
    68  				// Don't bother downloader in case it's already syncing.
    69  				if tester.api.eth.Downloader().Synchronising() {
    70  					continue
    71  				}
    72  				// Short circuit in case the target block is already stored
    73  				// locally.
    74  				if tester.api.eth.BlockChain().HasBlock(tester.block.Hash(), tester.block.NumberU64()) {
    75  					log.Info("Full-sync target reached", "number", tester.block.NumberU64(), "hash", tester.block.Hash())
    76  					return
    77  				}
    78  				// Shoot out consensus events in order to trigger syncing.
    79  				data := beacon.BlockToExecutableData(tester.block)
    80  				tester.api.NewPayloadV1(*data)
    81  				tester.api.ForkchoiceUpdatedV1(beacon.ForkchoiceStateV1{
    82  					HeadBlockHash:      tester.block.Hash(),
    83  					SafeBlockHash:      tester.block.Hash(),
    84  					FinalizedBlockHash: tester.block.Hash(),
    85  				}, nil)
    86  			case <-tester.closed:
    87  				return
    88  			}
    89  		}
    90  	}()
    91  	return nil
    92  }
    93  
    94  // Stop stops the full-sync tester to stop all background activities.
    95  // This function can only be called for one time.
    96  func (tester *FullSyncTester) Stop() error {
    97  	close(tester.closed)
    98  	tester.wg.Wait()
    99  	return nil
   100  }