github.1485827954.workers.dev/ethereum/go-ethereum@v1.14.3/eth/downloader/beacondevsync.go (about)

     1  // Copyright 2023 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 downloader
    18  
    19  import (
    20  	"errors"
    21  	"time"
    22  
    23  	"github.com/ethereum/go-ethereum/common"
    24  	"github.com/ethereum/go-ethereum/log"
    25  )
    26  
    27  // BeaconDevSync is a development helper to test synchronization by providing
    28  // a block hash instead of header to run the beacon sync against.
    29  //
    30  // The method will reach out to the network to retrieve the header of the sync
    31  // target instead of receiving it from the consensus node.
    32  //
    33  // Note, this must not be used in live code. If the forkchcoice endpoint where
    34  // to use this instead of giving us the payload first, then essentially nobody
    35  // in the network would have the block yet that we'd attempt to retrieve.
    36  func (d *Downloader) BeaconDevSync(mode SyncMode, hash common.Hash, stop chan struct{}) error {
    37  	// Be very loud that this code should not be used in a live node
    38  	log.Warn("----------------------------------")
    39  	log.Warn("Beacon syncing with hash as target", "hash", hash)
    40  	log.Warn("This is unhealthy for a live node!")
    41  	log.Warn("----------------------------------")
    42  
    43  	log.Info("Waiting for peers to retrieve sync target")
    44  	for {
    45  		// If the node is going down, unblock
    46  		select {
    47  		case <-stop:
    48  			return errors.New("stop requested")
    49  		default:
    50  		}
    51  		// Pick a random peer to sync from and keep retrying if none are yet
    52  		// available due to fresh startup
    53  		d.peers.lock.RLock()
    54  		var peer *peerConnection
    55  		for _, peer = range d.peers.peers {
    56  			break
    57  		}
    58  		d.peers.lock.RUnlock()
    59  
    60  		if peer == nil {
    61  			time.Sleep(time.Second)
    62  			continue
    63  		}
    64  		// Found a peer, attempt to retrieve the header whilst blocking and
    65  		// retry if it fails for whatever reason
    66  		log.Info("Attempting to retrieve sync target", "peer", peer.id)
    67  		headers, metas, err := d.fetchHeadersByHash(peer, hash, 1, 0, false)
    68  		if err != nil || len(headers) != 1 {
    69  			log.Warn("Failed to fetch sync target", "headers", len(headers), "err", err)
    70  			time.Sleep(time.Second)
    71  			continue
    72  		}
    73  		// Head header retrieved, if the hash matches, start the actual sync
    74  		if metas[0] != hash {
    75  			log.Error("Received invalid sync target", "want", hash, "have", metas[0])
    76  			time.Sleep(time.Second)
    77  			continue
    78  		}
    79  		return d.BeaconSync(mode, headers[0], headers[0])
    80  	}
    81  }