github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/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/ethereum/go-ethereum/common"
    24  	"github.com/ethereum/go-ethereum/eth"
    25  	"github.com/ethereum/go-ethereum/eth/downloader"
    26  	"github.com/ethereum/go-ethereum/log"
    27  	"github.com/ethereum/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 hash
    32  // as the sync target.
    33  //
    34  // This tester can be applied to different networks, no matter it's pre-merge or
    35  // post-merge, but only for full-sync.
    36  type FullSyncTester struct {
    37  	stack   *node.Node
    38  	backend *eth.Ethereum
    39  	target  common.Hash
    40  	closed  chan struct{}
    41  	wg      sync.WaitGroup
    42  }
    43  
    44  // RegisterFullSyncTester registers the full-sync tester service into the node
    45  // stack for launching and stopping the service controlled by node.
    46  func RegisterFullSyncTester(stack *node.Node, backend *eth.Ethereum, target common.Hash) (*FullSyncTester, error) {
    47  	cl := &FullSyncTester{
    48  		stack:   stack,
    49  		backend: backend,
    50  		target:  target,
    51  		closed:  make(chan struct{}),
    52  	}
    53  	stack.RegisterLifecycle(cl)
    54  	return cl, nil
    55  }
    56  
    57  // Start launches the beacon sync with provided sync target.
    58  func (tester *FullSyncTester) Start() error {
    59  	tester.wg.Add(1)
    60  	go func() {
    61  		defer tester.wg.Done()
    62  
    63  		// Trigger beacon sync with the provided block hash as trusted
    64  		// chain head.
    65  		err := tester.backend.Downloader().BeaconDevSync(downloader.FullSync, tester.target, tester.closed)
    66  		if err != nil {
    67  			log.Info("Failed to trigger beacon sync", "err", err)
    68  		}
    69  
    70  		ticker := time.NewTicker(time.Second * 5)
    71  		defer ticker.Stop()
    72  
    73  		for {
    74  			select {
    75  			case <-ticker.C:
    76  				// Stop in case the target block is already stored locally.
    77  				if block := tester.backend.BlockChain().GetBlockByHash(tester.target); block != nil {
    78  					log.Info("Full-sync target reached", "number", block.NumberU64(), "hash", block.Hash())
    79  					go tester.stack.Close() // async since we need to close ourselves
    80  					return
    81  				}
    82  
    83  			case <-tester.closed:
    84  				return
    85  			}
    86  		}
    87  	}()
    88  	return nil
    89  }
    90  
    91  // Stop stops the full-sync tester to stop all background activities.
    92  // This function can only be called for one time.
    93  func (tester *FullSyncTester) Stop() error {
    94  	close(tester.closed)
    95  	tester.wg.Wait()
    96  	return nil
    97  }