github.com/shrimpyuk/bor@v0.2.15-0.20220224151350-fb4ec6020bae/eth/protocols/snap/sync.go (about)

     1  // Copyright 2020 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 snap
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/json"
    22  	"errors"
    23  	"fmt"
    24  	"math/big"
    25  	"math/rand"
    26  	"sort"
    27  	"sync"
    28  	"time"
    29  
    30  	"github.com/ethereum/go-ethereum/common"
    31  	"github.com/ethereum/go-ethereum/common/math"
    32  	"github.com/ethereum/go-ethereum/core/rawdb"
    33  	"github.com/ethereum/go-ethereum/core/state"
    34  	"github.com/ethereum/go-ethereum/core/state/snapshot"
    35  	"github.com/ethereum/go-ethereum/core/types"
    36  	"github.com/ethereum/go-ethereum/crypto"
    37  	"github.com/ethereum/go-ethereum/ethdb"
    38  	"github.com/ethereum/go-ethereum/event"
    39  	"github.com/ethereum/go-ethereum/light"
    40  	"github.com/ethereum/go-ethereum/log"
    41  	"github.com/ethereum/go-ethereum/p2p/msgrate"
    42  	"github.com/ethereum/go-ethereum/rlp"
    43  	"github.com/ethereum/go-ethereum/trie"
    44  	"golang.org/x/crypto/sha3"
    45  )
    46  
    47  var (
    48  	// emptyRoot is the known root hash of an empty trie.
    49  	emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
    50  
    51  	// emptyCode is the known hash of the empty EVM bytecode.
    52  	emptyCode = crypto.Keccak256Hash(nil)
    53  )
    54  
    55  const (
    56  	// minRequestSize is the minimum number of bytes to request from a remote peer.
    57  	// This number is used as the low cap for account and storage range requests.
    58  	// Bytecode and trienode are limited inherently by item count (1).
    59  	minRequestSize = 64 * 1024
    60  
    61  	// maxRequestSize is the maximum number of bytes to request from a remote peer.
    62  	// This number is used as the high cap for account and storage range requests.
    63  	// Bytecode and trienode are limited more explicitly by the caps below.
    64  	maxRequestSize = 512 * 1024
    65  
    66  	// maxCodeRequestCount is the maximum number of bytecode blobs to request in a
    67  	// single query. If this number is too low, we're not filling responses fully
    68  	// and waste round trip times. If it's too high, we're capping responses and
    69  	// waste bandwidth.
    70  	//
    71  	// Depoyed bytecodes are currently capped at 24KB, so the minimum request
    72  	// size should be maxRequestSize / 24K. Assuming that most contracts do not
    73  	// come close to that, requesting 4x should be a good approximation.
    74  	maxCodeRequestCount = maxRequestSize / (24 * 1024) * 4
    75  
    76  	// maxTrieRequestCount is the maximum number of trie node blobs to request in
    77  	// a single query. If this number is too low, we're not filling responses fully
    78  	// and waste round trip times. If it's too high, we're capping responses and
    79  	// waste bandwidth.
    80  	maxTrieRequestCount = maxRequestSize / 512
    81  )
    82  
    83  var (
    84  	// accountConcurrency is the number of chunks to split the account trie into
    85  	// to allow concurrent retrievals.
    86  	accountConcurrency = 16
    87  
    88  	// storageConcurrency is the number of chunks to split the a large contract
    89  	// storage trie into to allow concurrent retrievals.
    90  	storageConcurrency = 16
    91  )
    92  
    93  // ErrCancelled is returned from snap syncing if the operation was prematurely
    94  // terminated.
    95  var ErrCancelled = errors.New("sync cancelled")
    96  
    97  // accountRequest tracks a pending account range request to ensure responses are
    98  // to actual requests and to validate any security constraints.
    99  //
   100  // Concurrency note: account requests and responses are handled concurrently from
   101  // the main runloop to allow Merkle proof verifications on the peer's thread and
   102  // to drop on invalid response. The request struct must contain all the data to
   103  // construct the response without accessing runloop internals (i.e. task). That
   104  // is only included to allow the runloop to match a response to the task being
   105  // synced without having yet another set of maps.
   106  type accountRequest struct {
   107  	peer string    // Peer to which this request is assigned
   108  	id   uint64    // Request ID of this request
   109  	time time.Time // Timestamp when the request was sent
   110  
   111  	deliver chan *accountResponse // Channel to deliver successful response on
   112  	revert  chan *accountRequest  // Channel to deliver request failure on
   113  	cancel  chan struct{}         // Channel to track sync cancellation
   114  	timeout *time.Timer           // Timer to track delivery timeout
   115  	stale   chan struct{}         // Channel to signal the request was dropped
   116  
   117  	origin common.Hash // First account requested to allow continuation checks
   118  	limit  common.Hash // Last account requested to allow non-overlapping chunking
   119  
   120  	task *accountTask // Task which this request is filling (only access fields through the runloop!!)
   121  }
   122  
   123  // accountResponse is an already Merkle-verified remote response to an account
   124  // range request. It contains the subtrie for the requested account range and
   125  // the database that's going to be filled with the internal nodes on commit.
   126  type accountResponse struct {
   127  	task *accountTask // Task which this request is filling
   128  
   129  	hashes   []common.Hash         // Account hashes in the returned range
   130  	accounts []*types.StateAccount // Expanded accounts in the returned range
   131  
   132  	cont bool // Whether the account range has a continuation
   133  }
   134  
   135  // bytecodeRequest tracks a pending bytecode request to ensure responses are to
   136  // actual requests and to validate any security constraints.
   137  //
   138  // Concurrency note: bytecode requests and responses are handled concurrently from
   139  // the main runloop to allow Keccak256 hash verifications on the peer's thread and
   140  // to drop on invalid response. The request struct must contain all the data to
   141  // construct the response without accessing runloop internals (i.e. task). That
   142  // is only included to allow the runloop to match a response to the task being
   143  // synced without having yet another set of maps.
   144  type bytecodeRequest struct {
   145  	peer string    // Peer to which this request is assigned
   146  	id   uint64    // Request ID of this request
   147  	time time.Time // Timestamp when the request was sent
   148  
   149  	deliver chan *bytecodeResponse // Channel to deliver successful response on
   150  	revert  chan *bytecodeRequest  // Channel to deliver request failure on
   151  	cancel  chan struct{}          // Channel to track sync cancellation
   152  	timeout *time.Timer            // Timer to track delivery timeout
   153  	stale   chan struct{}          // Channel to signal the request was dropped
   154  
   155  	hashes []common.Hash // Bytecode hashes to validate responses
   156  	task   *accountTask  // Task which this request is filling (only access fields through the runloop!!)
   157  }
   158  
   159  // bytecodeResponse is an already verified remote response to a bytecode request.
   160  type bytecodeResponse struct {
   161  	task *accountTask // Task which this request is filling
   162  
   163  	hashes []common.Hash // Hashes of the bytecode to avoid double hashing
   164  	codes  [][]byte      // Actual bytecodes to store into the database (nil = missing)
   165  }
   166  
   167  // storageRequest tracks a pending storage ranges request to ensure responses are
   168  // to actual requests and to validate any security constraints.
   169  //
   170  // Concurrency note: storage requests and responses are handled concurrently from
   171  // the main runloop to allow Merkel proof verifications on the peer's thread and
   172  // to drop on invalid response. The request struct must contain all the data to
   173  // construct the response without accessing runloop internals (i.e. tasks). That
   174  // is only included to allow the runloop to match a response to the task being
   175  // synced without having yet another set of maps.
   176  type storageRequest struct {
   177  	peer string    // Peer to which this request is assigned
   178  	id   uint64    // Request ID of this request
   179  	time time.Time // Timestamp when the request was sent
   180  
   181  	deliver chan *storageResponse // Channel to deliver successful response on
   182  	revert  chan *storageRequest  // Channel to deliver request failure on
   183  	cancel  chan struct{}         // Channel to track sync cancellation
   184  	timeout *time.Timer           // Timer to track delivery timeout
   185  	stale   chan struct{}         // Channel to signal the request was dropped
   186  
   187  	accounts []common.Hash // Account hashes to validate responses
   188  	roots    []common.Hash // Storage roots to validate responses
   189  
   190  	origin common.Hash // First storage slot requested to allow continuation checks
   191  	limit  common.Hash // Last storage slot requested to allow non-overlapping chunking
   192  
   193  	mainTask *accountTask // Task which this response belongs to (only access fields through the runloop!!)
   194  	subTask  *storageTask // Task which this response is filling (only access fields through the runloop!!)
   195  }
   196  
   197  // storageResponse is an already Merkle-verified remote response to a storage
   198  // range request. It contains the subtries for the requested storage ranges and
   199  // the databases that's going to be filled with the internal nodes on commit.
   200  type storageResponse struct {
   201  	mainTask *accountTask // Task which this response belongs to
   202  	subTask  *storageTask // Task which this response is filling
   203  
   204  	accounts []common.Hash // Account hashes requested, may be only partially filled
   205  	roots    []common.Hash // Storage roots requested, may be only partially filled
   206  
   207  	hashes [][]common.Hash // Storage slot hashes in the returned range
   208  	slots  [][][]byte      // Storage slot values in the returned range
   209  
   210  	cont bool // Whether the last storage range has a continuation
   211  }
   212  
   213  // trienodeHealRequest tracks a pending state trie request to ensure responses
   214  // are to actual requests and to validate any security constraints.
   215  //
   216  // Concurrency note: trie node requests and responses are handled concurrently from
   217  // the main runloop to allow Keccak256 hash verifications on the peer's thread and
   218  // to drop on invalid response. The request struct must contain all the data to
   219  // construct the response without accessing runloop internals (i.e. task). That
   220  // is only included to allow the runloop to match a response to the task being
   221  // synced without having yet another set of maps.
   222  type trienodeHealRequest struct {
   223  	peer string    // Peer to which this request is assigned
   224  	id   uint64    // Request ID of this request
   225  	time time.Time // Timestamp when the request was sent
   226  
   227  	deliver chan *trienodeHealResponse // Channel to deliver successful response on
   228  	revert  chan *trienodeHealRequest  // Channel to deliver request failure on
   229  	cancel  chan struct{}              // Channel to track sync cancellation
   230  	timeout *time.Timer                // Timer to track delivery timeout
   231  	stale   chan struct{}              // Channel to signal the request was dropped
   232  
   233  	hashes []common.Hash   // Trie node hashes to validate responses
   234  	paths  []trie.SyncPath // Trie node paths requested for rescheduling
   235  
   236  	task *healTask // Task which this request is filling (only access fields through the runloop!!)
   237  }
   238  
   239  // trienodeHealResponse is an already verified remote response to a trie node request.
   240  type trienodeHealResponse struct {
   241  	task *healTask // Task which this request is filling
   242  
   243  	hashes []common.Hash   // Hashes of the trie nodes to avoid double hashing
   244  	paths  []trie.SyncPath // Trie node paths requested for rescheduling missing ones
   245  	nodes  [][]byte        // Actual trie nodes to store into the database (nil = missing)
   246  }
   247  
   248  // bytecodeHealRequest tracks a pending bytecode request to ensure responses are to
   249  // actual requests and to validate any security constraints.
   250  //
   251  // Concurrency note: bytecode requests and responses are handled concurrently from
   252  // the main runloop to allow Keccak256 hash verifications on the peer's thread and
   253  // to drop on invalid response. The request struct must contain all the data to
   254  // construct the response without accessing runloop internals (i.e. task). That
   255  // is only included to allow the runloop to match a response to the task being
   256  // synced without having yet another set of maps.
   257  type bytecodeHealRequest struct {
   258  	peer string    // Peer to which this request is assigned
   259  	id   uint64    // Request ID of this request
   260  	time time.Time // Timestamp when the request was sent
   261  
   262  	deliver chan *bytecodeHealResponse // Channel to deliver successful response on
   263  	revert  chan *bytecodeHealRequest  // Channel to deliver request failure on
   264  	cancel  chan struct{}              // Channel to track sync cancellation
   265  	timeout *time.Timer                // Timer to track delivery timeout
   266  	stale   chan struct{}              // Channel to signal the request was dropped
   267  
   268  	hashes []common.Hash // Bytecode hashes to validate responses
   269  	task   *healTask     // Task which this request is filling (only access fields through the runloop!!)
   270  }
   271  
   272  // bytecodeHealResponse is an already verified remote response to a bytecode request.
   273  type bytecodeHealResponse struct {
   274  	task *healTask // Task which this request is filling
   275  
   276  	hashes []common.Hash // Hashes of the bytecode to avoid double hashing
   277  	codes  [][]byte      // Actual bytecodes to store into the database (nil = missing)
   278  }
   279  
   280  // accountTask represents the sync task for a chunk of the account snapshot.
   281  type accountTask struct {
   282  	// These fields get serialized to leveldb on shutdown
   283  	Next     common.Hash                    // Next account to sync in this interval
   284  	Last     common.Hash                    // Last account to sync in this interval
   285  	SubTasks map[common.Hash][]*storageTask // Storage intervals needing fetching for large contracts
   286  
   287  	// These fields are internals used during runtime
   288  	req  *accountRequest  // Pending request to fill this task
   289  	res  *accountResponse // Validate response filling this task
   290  	pend int              // Number of pending subtasks for this round
   291  
   292  	needCode  []bool // Flags whether the filling accounts need code retrieval
   293  	needState []bool // Flags whether the filling accounts need storage retrieval
   294  	needHeal  []bool // Flags whether the filling accounts's state was chunked and need healing
   295  
   296  	codeTasks  map[common.Hash]struct{}    // Code hashes that need retrieval
   297  	stateTasks map[common.Hash]common.Hash // Account hashes->roots that need full state retrieval
   298  
   299  	genBatch ethdb.Batch     // Batch used by the node generator
   300  	genTrie  *trie.StackTrie // Node generator from storage slots
   301  
   302  	done bool // Flag whether the task can be removed
   303  }
   304  
   305  // storageTask represents the sync task for a chunk of the storage snapshot.
   306  type storageTask struct {
   307  	Next common.Hash // Next account to sync in this interval
   308  	Last common.Hash // Last account to sync in this interval
   309  
   310  	// These fields are internals used during runtime
   311  	root common.Hash     // Storage root hash for this instance
   312  	req  *storageRequest // Pending request to fill this task
   313  
   314  	genBatch ethdb.Batch     // Batch used by the node generator
   315  	genTrie  *trie.StackTrie // Node generator from storage slots
   316  
   317  	done bool // Flag whether the task can be removed
   318  }
   319  
   320  // healTask represents the sync task for healing the snap-synced chunk boundaries.
   321  type healTask struct {
   322  	scheduler *trie.Sync // State trie sync scheduler defining the tasks
   323  
   324  	trieTasks map[common.Hash]trie.SyncPath // Set of trie node tasks currently queued for retrieval
   325  	codeTasks map[common.Hash]struct{}      // Set of byte code tasks currently queued for retrieval
   326  }
   327  
   328  // syncProgress is a database entry to allow suspending and resuming a snapshot state
   329  // sync. Opposed to full and fast sync, there is no way to restart a suspended
   330  // snap sync without prior knowledge of the suspension point.
   331  type syncProgress struct {
   332  	Tasks []*accountTask // The suspended account tasks (contract tasks within)
   333  
   334  	// Status report during syncing phase
   335  	AccountSynced  uint64             // Number of accounts downloaded
   336  	AccountBytes   common.StorageSize // Number of account trie bytes persisted to disk
   337  	BytecodeSynced uint64             // Number of bytecodes downloaded
   338  	BytecodeBytes  common.StorageSize // Number of bytecode bytes downloaded
   339  	StorageSynced  uint64             // Number of storage slots downloaded
   340  	StorageBytes   common.StorageSize // Number of storage trie bytes persisted to disk
   341  
   342  	// Status report during healing phase
   343  	TrienodeHealSynced uint64             // Number of state trie nodes downloaded
   344  	TrienodeHealBytes  common.StorageSize // Number of state trie bytes persisted to disk
   345  	TrienodeHealDups   uint64             // Number of state trie nodes already processed
   346  	TrienodeHealNops   uint64             // Number of state trie nodes not requested
   347  	BytecodeHealSynced uint64             // Number of bytecodes downloaded
   348  	BytecodeHealBytes  common.StorageSize // Number of bytecodes persisted to disk
   349  	BytecodeHealDups   uint64             // Number of bytecodes already processed
   350  	BytecodeHealNops   uint64             // Number of bytecodes not requested
   351  }
   352  
   353  // SyncPeer abstracts out the methods required for a peer to be synced against
   354  // with the goal of allowing the construction of mock peers without the full
   355  // blown networking.
   356  type SyncPeer interface {
   357  	// ID retrieves the peer's unique identifier.
   358  	ID() string
   359  
   360  	// RequestAccountRange fetches a batch of accounts rooted in a specific account
   361  	// trie, starting with the origin.
   362  	RequestAccountRange(id uint64, root, origin, limit common.Hash, bytes uint64) error
   363  
   364  	// RequestStorageRanges fetches a batch of storage slots belonging to one or
   365  	// more accounts. If slots from only one accout is requested, an origin marker
   366  	// may also be used to retrieve from there.
   367  	RequestStorageRanges(id uint64, root common.Hash, accounts []common.Hash, origin, limit []byte, bytes uint64) error
   368  
   369  	// RequestByteCodes fetches a batch of bytecodes by hash.
   370  	RequestByteCodes(id uint64, hashes []common.Hash, bytes uint64) error
   371  
   372  	// RequestTrieNodes fetches a batch of account or storage trie nodes rooted in
   373  	// a specificstate trie.
   374  	RequestTrieNodes(id uint64, root common.Hash, paths []TrieNodePathSet, bytes uint64) error
   375  
   376  	// Log retrieves the peer's own contextual logger.
   377  	Log() log.Logger
   378  }
   379  
   380  // Syncer is an Ethereum account and storage trie syncer based on snapshots and
   381  // the  snap protocol. It's purpose is to download all the accounts and storage
   382  // slots from remote peers and reassemble chunks of the state trie, on top of
   383  // which a state sync can be run to fix any gaps / overlaps.
   384  //
   385  // Every network request has a variety of failure events:
   386  //   - The peer disconnects after task assignment, failing to send the request
   387  //   - The peer disconnects after sending the request, before delivering on it
   388  //   - The peer remains connected, but does not deliver a response in time
   389  //   - The peer delivers a stale response after a previous timeout
   390  //   - The peer delivers a refusal to serve the requested state
   391  type Syncer struct {
   392  	db ethdb.KeyValueStore // Database to store the trie nodes into (and dedup)
   393  
   394  	root    common.Hash    // Current state trie root being synced
   395  	tasks   []*accountTask // Current account task set being synced
   396  	snapped bool           // Flag to signal that snap phase is done
   397  	healer  *healTask      // Current state healing task being executed
   398  	update  chan struct{}  // Notification channel for possible sync progression
   399  
   400  	peers    map[string]SyncPeer // Currently active peers to download from
   401  	peerJoin *event.Feed         // Event feed to react to peers joining
   402  	peerDrop *event.Feed         // Event feed to react to peers dropping
   403  	rates    *msgrate.Trackers   // Message throughput rates for peers
   404  
   405  	// Request tracking during syncing phase
   406  	statelessPeers map[string]struct{} // Peers that failed to deliver state data
   407  	accountIdlers  map[string]struct{} // Peers that aren't serving account requests
   408  	bytecodeIdlers map[string]struct{} // Peers that aren't serving bytecode requests
   409  	storageIdlers  map[string]struct{} // Peers that aren't serving storage requests
   410  
   411  	accountReqs  map[uint64]*accountRequest  // Account requests currently running
   412  	bytecodeReqs map[uint64]*bytecodeRequest // Bytecode requests currently running
   413  	storageReqs  map[uint64]*storageRequest  // Storage requests currently running
   414  
   415  	accountSynced  uint64             // Number of accounts downloaded
   416  	accountBytes   common.StorageSize // Number of account trie bytes persisted to disk
   417  	bytecodeSynced uint64             // Number of bytecodes downloaded
   418  	bytecodeBytes  common.StorageSize // Number of bytecode bytes downloaded
   419  	storageSynced  uint64             // Number of storage slots downloaded
   420  	storageBytes   common.StorageSize // Number of storage trie bytes persisted to disk
   421  
   422  	// Request tracking during healing phase
   423  	trienodeHealIdlers map[string]struct{} // Peers that aren't serving trie node requests
   424  	bytecodeHealIdlers map[string]struct{} // Peers that aren't serving bytecode requests
   425  
   426  	trienodeHealReqs map[uint64]*trienodeHealRequest // Trie node requests currently running
   427  	bytecodeHealReqs map[uint64]*bytecodeHealRequest // Bytecode requests currently running
   428  
   429  	trienodeHealSynced uint64             // Number of state trie nodes downloaded
   430  	trienodeHealBytes  common.StorageSize // Number of state trie bytes persisted to disk
   431  	trienodeHealDups   uint64             // Number of state trie nodes already processed
   432  	trienodeHealNops   uint64             // Number of state trie nodes not requested
   433  	bytecodeHealSynced uint64             // Number of bytecodes downloaded
   434  	bytecodeHealBytes  common.StorageSize // Number of bytecodes persisted to disk
   435  	bytecodeHealDups   uint64             // Number of bytecodes already processed
   436  	bytecodeHealNops   uint64             // Number of bytecodes not requested
   437  
   438  	stateWriter        ethdb.Batch        // Shared batch writer used for persisting raw states
   439  	accountHealed      uint64             // Number of accounts downloaded during the healing stage
   440  	accountHealedBytes common.StorageSize // Number of raw account bytes persisted to disk during the healing stage
   441  	storageHealed      uint64             // Number of storage slots downloaded during the healing stage
   442  	storageHealedBytes common.StorageSize // Number of raw storage bytes persisted to disk during the healing stage
   443  
   444  	startTime time.Time // Time instance when snapshot sync started
   445  	logTime   time.Time // Time instance when status was last reported
   446  
   447  	pend sync.WaitGroup // Tracks network request goroutines for graceful shutdown
   448  	lock sync.RWMutex   // Protects fields that can change outside of sync (peers, reqs, root)
   449  }
   450  
   451  // NewSyncer creates a new snapshot syncer to download the Ethereum state over the
   452  // snap protocol.
   453  func NewSyncer(db ethdb.KeyValueStore) *Syncer {
   454  	return &Syncer{
   455  		db: db,
   456  
   457  		peers:    make(map[string]SyncPeer),
   458  		peerJoin: new(event.Feed),
   459  		peerDrop: new(event.Feed),
   460  		rates:    msgrate.NewTrackers(log.New("proto", "snap")),
   461  		update:   make(chan struct{}, 1),
   462  
   463  		accountIdlers:  make(map[string]struct{}),
   464  		storageIdlers:  make(map[string]struct{}),
   465  		bytecodeIdlers: make(map[string]struct{}),
   466  
   467  		accountReqs:  make(map[uint64]*accountRequest),
   468  		storageReqs:  make(map[uint64]*storageRequest),
   469  		bytecodeReqs: make(map[uint64]*bytecodeRequest),
   470  
   471  		trienodeHealIdlers: make(map[string]struct{}),
   472  		bytecodeHealIdlers: make(map[string]struct{}),
   473  
   474  		trienodeHealReqs: make(map[uint64]*trienodeHealRequest),
   475  		bytecodeHealReqs: make(map[uint64]*bytecodeHealRequest),
   476  		stateWriter:      db.NewBatch(),
   477  	}
   478  }
   479  
   480  // Register injects a new data source into the syncer's peerset.
   481  func (s *Syncer) Register(peer SyncPeer) error {
   482  	// Make sure the peer is not registered yet
   483  	id := peer.ID()
   484  
   485  	s.lock.Lock()
   486  	if _, ok := s.peers[id]; ok {
   487  		log.Error("Snap peer already registered", "id", id)
   488  
   489  		s.lock.Unlock()
   490  		return errors.New("already registered")
   491  	}
   492  	s.peers[id] = peer
   493  	s.rates.Track(id, msgrate.NewTracker(s.rates.MeanCapacities(), s.rates.MedianRoundTrip()))
   494  
   495  	// Mark the peer as idle, even if no sync is running
   496  	s.accountIdlers[id] = struct{}{}
   497  	s.storageIdlers[id] = struct{}{}
   498  	s.bytecodeIdlers[id] = struct{}{}
   499  	s.trienodeHealIdlers[id] = struct{}{}
   500  	s.bytecodeHealIdlers[id] = struct{}{}
   501  	s.lock.Unlock()
   502  
   503  	// Notify any active syncs that a new peer can be assigned data
   504  	s.peerJoin.Send(id)
   505  	return nil
   506  }
   507  
   508  // Unregister injects a new data source into the syncer's peerset.
   509  func (s *Syncer) Unregister(id string) error {
   510  	// Remove all traces of the peer from the registry
   511  	s.lock.Lock()
   512  	if _, ok := s.peers[id]; !ok {
   513  		log.Error("Snap peer not registered", "id", id)
   514  
   515  		s.lock.Unlock()
   516  		return errors.New("not registered")
   517  	}
   518  	delete(s.peers, id)
   519  	s.rates.Untrack(id)
   520  
   521  	// Remove status markers, even if no sync is running
   522  	delete(s.statelessPeers, id)
   523  
   524  	delete(s.accountIdlers, id)
   525  	delete(s.storageIdlers, id)
   526  	delete(s.bytecodeIdlers, id)
   527  	delete(s.trienodeHealIdlers, id)
   528  	delete(s.bytecodeHealIdlers, id)
   529  	s.lock.Unlock()
   530  
   531  	// Notify any active syncs that pending requests need to be reverted
   532  	s.peerDrop.Send(id)
   533  	return nil
   534  }
   535  
   536  // Sync starts (or resumes a previous) sync cycle to iterate over an state trie
   537  // with the given root and reconstruct the nodes based on the snapshot leaves.
   538  // Previously downloaded segments will not be redownloaded of fixed, rather any
   539  // errors will be healed after the leaves are fully accumulated.
   540  func (s *Syncer) Sync(root common.Hash, cancel chan struct{}) error {
   541  	// Move the trie root from any previous value, revert stateless markers for
   542  	// any peers and initialize the syncer if it was not yet run
   543  	s.lock.Lock()
   544  	s.root = root
   545  	s.healer = &healTask{
   546  		scheduler: state.NewStateSync(root, s.db, nil, s.onHealState),
   547  		trieTasks: make(map[common.Hash]trie.SyncPath),
   548  		codeTasks: make(map[common.Hash]struct{}),
   549  	}
   550  	s.statelessPeers = make(map[string]struct{})
   551  	s.lock.Unlock()
   552  
   553  	if s.startTime == (time.Time{}) {
   554  		s.startTime = time.Now()
   555  	}
   556  	// Retrieve the previous sync status from LevelDB and abort if already synced
   557  	s.loadSyncStatus()
   558  	if len(s.tasks) == 0 && s.healer.scheduler.Pending() == 0 {
   559  		log.Debug("Snapshot sync already completed")
   560  		return nil
   561  	}
   562  	defer func() { // Persist any progress, independent of failure
   563  		for _, task := range s.tasks {
   564  			s.forwardAccountTask(task)
   565  		}
   566  		s.cleanAccountTasks()
   567  		s.saveSyncStatus()
   568  	}()
   569  
   570  	log.Debug("Starting snapshot sync cycle", "root", root)
   571  
   572  	// Flush out the last committed raw states
   573  	defer func() {
   574  		if s.stateWriter.ValueSize() > 0 {
   575  			s.stateWriter.Write()
   576  			s.stateWriter.Reset()
   577  		}
   578  	}()
   579  	defer s.report(true)
   580  
   581  	// Whether sync completed or not, disregard any future packets
   582  	defer func() {
   583  		log.Debug("Terminating snapshot sync cycle", "root", root)
   584  		s.lock.Lock()
   585  		s.accountReqs = make(map[uint64]*accountRequest)
   586  		s.storageReqs = make(map[uint64]*storageRequest)
   587  		s.bytecodeReqs = make(map[uint64]*bytecodeRequest)
   588  		s.trienodeHealReqs = make(map[uint64]*trienodeHealRequest)
   589  		s.bytecodeHealReqs = make(map[uint64]*bytecodeHealRequest)
   590  		s.lock.Unlock()
   591  	}()
   592  	// Keep scheduling sync tasks
   593  	peerJoin := make(chan string, 16)
   594  	peerJoinSub := s.peerJoin.Subscribe(peerJoin)
   595  	defer peerJoinSub.Unsubscribe()
   596  
   597  	peerDrop := make(chan string, 16)
   598  	peerDropSub := s.peerDrop.Subscribe(peerDrop)
   599  	defer peerDropSub.Unsubscribe()
   600  
   601  	// Create a set of unique channels for this sync cycle. We need these to be
   602  	// ephemeral so a data race doesn't accidentally deliver something stale on
   603  	// a persistent channel across syncs (yup, this happened)
   604  	var (
   605  		accountReqFails      = make(chan *accountRequest)
   606  		storageReqFails      = make(chan *storageRequest)
   607  		bytecodeReqFails     = make(chan *bytecodeRequest)
   608  		accountResps         = make(chan *accountResponse)
   609  		storageResps         = make(chan *storageResponse)
   610  		bytecodeResps        = make(chan *bytecodeResponse)
   611  		trienodeHealReqFails = make(chan *trienodeHealRequest)
   612  		bytecodeHealReqFails = make(chan *bytecodeHealRequest)
   613  		trienodeHealResps    = make(chan *trienodeHealResponse)
   614  		bytecodeHealResps    = make(chan *bytecodeHealResponse)
   615  	)
   616  	for {
   617  		// Remove all completed tasks and terminate sync if everything's done
   618  		s.cleanStorageTasks()
   619  		s.cleanAccountTasks()
   620  		if len(s.tasks) == 0 && s.healer.scheduler.Pending() == 0 {
   621  			return nil
   622  		}
   623  		// Assign all the data retrieval tasks to any free peers
   624  		s.assignAccountTasks(accountResps, accountReqFails, cancel)
   625  		s.assignBytecodeTasks(bytecodeResps, bytecodeReqFails, cancel)
   626  		s.assignStorageTasks(storageResps, storageReqFails, cancel)
   627  
   628  		if len(s.tasks) == 0 {
   629  			// Sync phase done, run heal phase
   630  			s.assignTrienodeHealTasks(trienodeHealResps, trienodeHealReqFails, cancel)
   631  			s.assignBytecodeHealTasks(bytecodeHealResps, bytecodeHealReqFails, cancel)
   632  		}
   633  		// Wait for something to happen
   634  		select {
   635  		case <-s.update:
   636  			// Something happened (new peer, delivery, timeout), recheck tasks
   637  		case <-peerJoin:
   638  			// A new peer joined, try to schedule it new tasks
   639  		case id := <-peerDrop:
   640  			s.revertRequests(id)
   641  		case <-cancel:
   642  			return ErrCancelled
   643  
   644  		case req := <-accountReqFails:
   645  			s.revertAccountRequest(req)
   646  		case req := <-bytecodeReqFails:
   647  			s.revertBytecodeRequest(req)
   648  		case req := <-storageReqFails:
   649  			s.revertStorageRequest(req)
   650  		case req := <-trienodeHealReqFails:
   651  			s.revertTrienodeHealRequest(req)
   652  		case req := <-bytecodeHealReqFails:
   653  			s.revertBytecodeHealRequest(req)
   654  
   655  		case res := <-accountResps:
   656  			s.processAccountResponse(res)
   657  		case res := <-bytecodeResps:
   658  			s.processBytecodeResponse(res)
   659  		case res := <-storageResps:
   660  			s.processStorageResponse(res)
   661  		case res := <-trienodeHealResps:
   662  			s.processTrienodeHealResponse(res)
   663  		case res := <-bytecodeHealResps:
   664  			s.processBytecodeHealResponse(res)
   665  		}
   666  		// Report stats if something meaningful happened
   667  		s.report(false)
   668  	}
   669  }
   670  
   671  // loadSyncStatus retrieves a previously aborted sync status from the database,
   672  // or generates a fresh one if none is available.
   673  func (s *Syncer) loadSyncStatus() {
   674  	var progress syncProgress
   675  
   676  	if status := rawdb.ReadSnapshotSyncStatus(s.db); status != nil {
   677  		if err := json.Unmarshal(status, &progress); err != nil {
   678  			log.Error("Failed to decode snap sync status", "err", err)
   679  		} else {
   680  			for _, task := range progress.Tasks {
   681  				log.Debug("Scheduled account sync task", "from", task.Next, "last", task.Last)
   682  			}
   683  			s.tasks = progress.Tasks
   684  			for _, task := range s.tasks {
   685  				task.genBatch = ethdb.HookedBatch{
   686  					Batch: s.db.NewBatch(),
   687  					OnPut: func(key []byte, value []byte) {
   688  						s.accountBytes += common.StorageSize(len(key) + len(value))
   689  					},
   690  				}
   691  				task.genTrie = trie.NewStackTrie(task.genBatch)
   692  
   693  				for _, subtasks := range task.SubTasks {
   694  					for _, subtask := range subtasks {
   695  						subtask.genBatch = ethdb.HookedBatch{
   696  							Batch: s.db.NewBatch(),
   697  							OnPut: func(key []byte, value []byte) {
   698  								s.storageBytes += common.StorageSize(len(key) + len(value))
   699  							},
   700  						}
   701  						subtask.genTrie = trie.NewStackTrie(subtask.genBatch)
   702  					}
   703  				}
   704  			}
   705  			s.snapped = len(s.tasks) == 0
   706  
   707  			s.accountSynced = progress.AccountSynced
   708  			s.accountBytes = progress.AccountBytes
   709  			s.bytecodeSynced = progress.BytecodeSynced
   710  			s.bytecodeBytes = progress.BytecodeBytes
   711  			s.storageSynced = progress.StorageSynced
   712  			s.storageBytes = progress.StorageBytes
   713  
   714  			s.trienodeHealSynced = progress.TrienodeHealSynced
   715  			s.trienodeHealBytes = progress.TrienodeHealBytes
   716  			s.bytecodeHealSynced = progress.BytecodeHealSynced
   717  			s.bytecodeHealBytes = progress.BytecodeHealBytes
   718  			return
   719  		}
   720  	}
   721  	// Either we've failed to decode the previus state, or there was none.
   722  	// Start a fresh sync by chunking up the account range and scheduling
   723  	// them for retrieval.
   724  	s.tasks = nil
   725  	s.accountSynced, s.accountBytes = 0, 0
   726  	s.bytecodeSynced, s.bytecodeBytes = 0, 0
   727  	s.storageSynced, s.storageBytes = 0, 0
   728  	s.trienodeHealSynced, s.trienodeHealBytes = 0, 0
   729  	s.bytecodeHealSynced, s.bytecodeHealBytes = 0, 0
   730  
   731  	var next common.Hash
   732  	step := new(big.Int).Sub(
   733  		new(big.Int).Div(
   734  			new(big.Int).Exp(common.Big2, common.Big256, nil),
   735  			big.NewInt(int64(accountConcurrency)),
   736  		), common.Big1,
   737  	)
   738  	for i := 0; i < accountConcurrency; i++ {
   739  		last := common.BigToHash(new(big.Int).Add(next.Big(), step))
   740  		if i == accountConcurrency-1 {
   741  			// Make sure we don't overflow if the step is not a proper divisor
   742  			last = common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
   743  		}
   744  		batch := ethdb.HookedBatch{
   745  			Batch: s.db.NewBatch(),
   746  			OnPut: func(key []byte, value []byte) {
   747  				s.accountBytes += common.StorageSize(len(key) + len(value))
   748  			},
   749  		}
   750  		s.tasks = append(s.tasks, &accountTask{
   751  			Next:     next,
   752  			Last:     last,
   753  			SubTasks: make(map[common.Hash][]*storageTask),
   754  			genBatch: batch,
   755  			genTrie:  trie.NewStackTrie(batch),
   756  		})
   757  		log.Debug("Created account sync task", "from", next, "last", last)
   758  		next = common.BigToHash(new(big.Int).Add(last.Big(), common.Big1))
   759  	}
   760  }
   761  
   762  // saveSyncStatus marshals the remaining sync tasks into leveldb.
   763  func (s *Syncer) saveSyncStatus() {
   764  	// Serialize any partial progress to disk before spinning down
   765  	for _, task := range s.tasks {
   766  		if err := task.genBatch.Write(); err != nil {
   767  			log.Error("Failed to persist account slots", "err", err)
   768  		}
   769  		for _, subtasks := range task.SubTasks {
   770  			for _, subtask := range subtasks {
   771  				if err := subtask.genBatch.Write(); err != nil {
   772  					log.Error("Failed to persist storage slots", "err", err)
   773  				}
   774  			}
   775  		}
   776  	}
   777  	// Store the actual progress markers
   778  	progress := &syncProgress{
   779  		Tasks:              s.tasks,
   780  		AccountSynced:      s.accountSynced,
   781  		AccountBytes:       s.accountBytes,
   782  		BytecodeSynced:     s.bytecodeSynced,
   783  		BytecodeBytes:      s.bytecodeBytes,
   784  		StorageSynced:      s.storageSynced,
   785  		StorageBytes:       s.storageBytes,
   786  		TrienodeHealSynced: s.trienodeHealSynced,
   787  		TrienodeHealBytes:  s.trienodeHealBytes,
   788  		BytecodeHealSynced: s.bytecodeHealSynced,
   789  		BytecodeHealBytes:  s.bytecodeHealBytes,
   790  	}
   791  	status, err := json.Marshal(progress)
   792  	if err != nil {
   793  		panic(err) // This can only fail during implementation
   794  	}
   795  	rawdb.WriteSnapshotSyncStatus(s.db, status)
   796  }
   797  
   798  // cleanAccountTasks removes account range retrieval tasks that have already been
   799  // completed.
   800  func (s *Syncer) cleanAccountTasks() {
   801  	// If the sync was already done before, don't even bother
   802  	if len(s.tasks) == 0 {
   803  		return
   804  	}
   805  	// Sync wasn't finished previously, check for any task that can be finalized
   806  	for i := 0; i < len(s.tasks); i++ {
   807  		if s.tasks[i].done {
   808  			s.tasks = append(s.tasks[:i], s.tasks[i+1:]...)
   809  			i--
   810  		}
   811  	}
   812  	// If everything was just finalized just, generate the account trie and start heal
   813  	if len(s.tasks) == 0 {
   814  		s.lock.Lock()
   815  		s.snapped = true
   816  		s.lock.Unlock()
   817  
   818  		// Push the final sync report
   819  		s.reportSyncProgress(true)
   820  	}
   821  }
   822  
   823  // cleanStorageTasks iterates over all the account tasks and storage sub-tasks
   824  // within, cleaning any that have been completed.
   825  func (s *Syncer) cleanStorageTasks() {
   826  	for _, task := range s.tasks {
   827  		for account, subtasks := range task.SubTasks {
   828  			// Remove storage range retrieval tasks that completed
   829  			for j := 0; j < len(subtasks); j++ {
   830  				if subtasks[j].done {
   831  					subtasks = append(subtasks[:j], subtasks[j+1:]...)
   832  					j--
   833  				}
   834  			}
   835  			if len(subtasks) > 0 {
   836  				task.SubTasks[account] = subtasks
   837  				continue
   838  			}
   839  			// If all storage chunks are done, mark the account as done too
   840  			for j, hash := range task.res.hashes {
   841  				if hash == account {
   842  					task.needState[j] = false
   843  				}
   844  			}
   845  			delete(task.SubTasks, account)
   846  			task.pend--
   847  
   848  			// If this was the last pending task, forward the account task
   849  			if task.pend == 0 {
   850  				s.forwardAccountTask(task)
   851  			}
   852  		}
   853  	}
   854  }
   855  
   856  // assignAccountTasks attempts to match idle peers to pending account range
   857  // retrievals.
   858  func (s *Syncer) assignAccountTasks(success chan *accountResponse, fail chan *accountRequest, cancel chan struct{}) {
   859  	s.lock.Lock()
   860  	defer s.lock.Unlock()
   861  
   862  	// Sort the peers by download capacity to use faster ones if many available
   863  	idlers := &capacitySort{
   864  		ids:  make([]string, 0, len(s.accountIdlers)),
   865  		caps: make([]int, 0, len(s.accountIdlers)),
   866  	}
   867  	targetTTL := s.rates.TargetTimeout()
   868  	for id := range s.accountIdlers {
   869  		if _, ok := s.statelessPeers[id]; ok {
   870  			continue
   871  		}
   872  		idlers.ids = append(idlers.ids, id)
   873  		idlers.caps = append(idlers.caps, s.rates.Capacity(id, AccountRangeMsg, targetTTL))
   874  	}
   875  	if len(idlers.ids) == 0 {
   876  		return
   877  	}
   878  	sort.Sort(sort.Reverse(idlers))
   879  
   880  	// Iterate over all the tasks and try to find a pending one
   881  	for _, task := range s.tasks {
   882  		// Skip any tasks already filling
   883  		if task.req != nil || task.res != nil {
   884  			continue
   885  		}
   886  		// Task pending retrieval, try to find an idle peer. If no such peer
   887  		// exists, we probably assigned tasks for all (or they are stateless).
   888  		// Abort the entire assignment mechanism.
   889  		if len(idlers.ids) == 0 {
   890  			return
   891  		}
   892  		var (
   893  			idle = idlers.ids[0]
   894  			peer = s.peers[idle]
   895  			cap  = idlers.caps[0]
   896  		)
   897  		idlers.ids, idlers.caps = idlers.ids[1:], idlers.caps[1:]
   898  
   899  		// Matched a pending task to an idle peer, allocate a unique request id
   900  		var reqid uint64
   901  		for {
   902  			reqid = uint64(rand.Int63())
   903  			if reqid == 0 {
   904  				continue
   905  			}
   906  			if _, ok := s.accountReqs[reqid]; ok {
   907  				continue
   908  			}
   909  			break
   910  		}
   911  		// Generate the network query and send it to the peer
   912  		req := &accountRequest{
   913  			peer:    idle,
   914  			id:      reqid,
   915  			time:    time.Now(),
   916  			deliver: success,
   917  			revert:  fail,
   918  			cancel:  cancel,
   919  			stale:   make(chan struct{}),
   920  			origin:  task.Next,
   921  			limit:   task.Last,
   922  			task:    task,
   923  		}
   924  		req.timeout = time.AfterFunc(s.rates.TargetTimeout(), func() {
   925  			peer.Log().Debug("Account range request timed out", "reqid", reqid)
   926  			s.rates.Update(idle, AccountRangeMsg, 0, 0)
   927  			s.scheduleRevertAccountRequest(req)
   928  		})
   929  		s.accountReqs[reqid] = req
   930  		delete(s.accountIdlers, idle)
   931  
   932  		s.pend.Add(1)
   933  		go func(root common.Hash) {
   934  			defer s.pend.Done()
   935  
   936  			// Attempt to send the remote request and revert if it fails
   937  			if cap > maxRequestSize {
   938  				cap = maxRequestSize
   939  			}
   940  			if cap < minRequestSize { // Don't bother with peers below a bare minimum performance
   941  				cap = minRequestSize
   942  			}
   943  			if err := peer.RequestAccountRange(reqid, root, req.origin, req.limit, uint64(cap)); err != nil {
   944  				peer.Log().Debug("Failed to request account range", "err", err)
   945  				s.scheduleRevertAccountRequest(req)
   946  			}
   947  		}(s.root)
   948  
   949  		// Inject the request into the task to block further assignments
   950  		task.req = req
   951  	}
   952  }
   953  
   954  // assignBytecodeTasks attempts to match idle peers to pending code retrievals.
   955  func (s *Syncer) assignBytecodeTasks(success chan *bytecodeResponse, fail chan *bytecodeRequest, cancel chan struct{}) {
   956  	s.lock.Lock()
   957  	defer s.lock.Unlock()
   958  
   959  	// Sort the peers by download capacity to use faster ones if many available
   960  	idlers := &capacitySort{
   961  		ids:  make([]string, 0, len(s.bytecodeIdlers)),
   962  		caps: make([]int, 0, len(s.bytecodeIdlers)),
   963  	}
   964  	targetTTL := s.rates.TargetTimeout()
   965  	for id := range s.bytecodeIdlers {
   966  		if _, ok := s.statelessPeers[id]; ok {
   967  			continue
   968  		}
   969  		idlers.ids = append(idlers.ids, id)
   970  		idlers.caps = append(idlers.caps, s.rates.Capacity(id, ByteCodesMsg, targetTTL))
   971  	}
   972  	if len(idlers.ids) == 0 {
   973  		return
   974  	}
   975  	sort.Sort(sort.Reverse(idlers))
   976  
   977  	// Iterate over all the tasks and try to find a pending one
   978  	for _, task := range s.tasks {
   979  		// Skip any tasks not in the bytecode retrieval phase
   980  		if task.res == nil {
   981  			continue
   982  		}
   983  		// Skip tasks that are already retrieving (or done with) all codes
   984  		if len(task.codeTasks) == 0 {
   985  			continue
   986  		}
   987  		// Task pending retrieval, try to find an idle peer. If no such peer
   988  		// exists, we probably assigned tasks for all (or they are stateless).
   989  		// Abort the entire assignment mechanism.
   990  		if len(idlers.ids) == 0 {
   991  			return
   992  		}
   993  		var (
   994  			idle = idlers.ids[0]
   995  			peer = s.peers[idle]
   996  			cap  = idlers.caps[0]
   997  		)
   998  		idlers.ids, idlers.caps = idlers.ids[1:], idlers.caps[1:]
   999  
  1000  		// Matched a pending task to an idle peer, allocate a unique request id
  1001  		var reqid uint64
  1002  		for {
  1003  			reqid = uint64(rand.Int63())
  1004  			if reqid == 0 {
  1005  				continue
  1006  			}
  1007  			if _, ok := s.bytecodeReqs[reqid]; ok {
  1008  				continue
  1009  			}
  1010  			break
  1011  		}
  1012  		// Generate the network query and send it to the peer
  1013  		if cap > maxCodeRequestCount {
  1014  			cap = maxCodeRequestCount
  1015  		}
  1016  		hashes := make([]common.Hash, 0, cap)
  1017  		for hash := range task.codeTasks {
  1018  			delete(task.codeTasks, hash)
  1019  			hashes = append(hashes, hash)
  1020  			if len(hashes) >= cap {
  1021  				break
  1022  			}
  1023  		}
  1024  		req := &bytecodeRequest{
  1025  			peer:    idle,
  1026  			id:      reqid,
  1027  			time:    time.Now(),
  1028  			deliver: success,
  1029  			revert:  fail,
  1030  			cancel:  cancel,
  1031  			stale:   make(chan struct{}),
  1032  			hashes:  hashes,
  1033  			task:    task,
  1034  		}
  1035  		req.timeout = time.AfterFunc(s.rates.TargetTimeout(), func() {
  1036  			peer.Log().Debug("Bytecode request timed out", "reqid", reqid)
  1037  			s.rates.Update(idle, ByteCodesMsg, 0, 0)
  1038  			s.scheduleRevertBytecodeRequest(req)
  1039  		})
  1040  		s.bytecodeReqs[reqid] = req
  1041  		delete(s.bytecodeIdlers, idle)
  1042  
  1043  		s.pend.Add(1)
  1044  		go func() {
  1045  			defer s.pend.Done()
  1046  
  1047  			// Attempt to send the remote request and revert if it fails
  1048  			if err := peer.RequestByteCodes(reqid, hashes, maxRequestSize); err != nil {
  1049  				log.Debug("Failed to request bytecodes", "err", err)
  1050  				s.scheduleRevertBytecodeRequest(req)
  1051  			}
  1052  		}()
  1053  	}
  1054  }
  1055  
  1056  // assignStorageTasks attempts to match idle peers to pending storage range
  1057  // retrievals.
  1058  func (s *Syncer) assignStorageTasks(success chan *storageResponse, fail chan *storageRequest, cancel chan struct{}) {
  1059  	s.lock.Lock()
  1060  	defer s.lock.Unlock()
  1061  
  1062  	// Sort the peers by download capacity to use faster ones if many available
  1063  	idlers := &capacitySort{
  1064  		ids:  make([]string, 0, len(s.storageIdlers)),
  1065  		caps: make([]int, 0, len(s.storageIdlers)),
  1066  	}
  1067  	targetTTL := s.rates.TargetTimeout()
  1068  	for id := range s.storageIdlers {
  1069  		if _, ok := s.statelessPeers[id]; ok {
  1070  			continue
  1071  		}
  1072  		idlers.ids = append(idlers.ids, id)
  1073  		idlers.caps = append(idlers.caps, s.rates.Capacity(id, StorageRangesMsg, targetTTL))
  1074  	}
  1075  	if len(idlers.ids) == 0 {
  1076  		return
  1077  	}
  1078  	sort.Sort(sort.Reverse(idlers))
  1079  
  1080  	// Iterate over all the tasks and try to find a pending one
  1081  	for _, task := range s.tasks {
  1082  		// Skip any tasks not in the storage retrieval phase
  1083  		if task.res == nil {
  1084  			continue
  1085  		}
  1086  		// Skip tasks that are already retrieving (or done with) all small states
  1087  		if len(task.SubTasks) == 0 && len(task.stateTasks) == 0 {
  1088  			continue
  1089  		}
  1090  		// Task pending retrieval, try to find an idle peer. If no such peer
  1091  		// exists, we probably assigned tasks for all (or they are stateless).
  1092  		// Abort the entire assignment mechanism.
  1093  		if len(idlers.ids) == 0 {
  1094  			return
  1095  		}
  1096  		var (
  1097  			idle = idlers.ids[0]
  1098  			peer = s.peers[idle]
  1099  			cap  = idlers.caps[0]
  1100  		)
  1101  		idlers.ids, idlers.caps = idlers.ids[1:], idlers.caps[1:]
  1102  
  1103  		// Matched a pending task to an idle peer, allocate a unique request id
  1104  		var reqid uint64
  1105  		for {
  1106  			reqid = uint64(rand.Int63())
  1107  			if reqid == 0 {
  1108  				continue
  1109  			}
  1110  			if _, ok := s.storageReqs[reqid]; ok {
  1111  				continue
  1112  			}
  1113  			break
  1114  		}
  1115  		// Generate the network query and send it to the peer. If there are
  1116  		// large contract tasks pending, complete those before diving into
  1117  		// even more new contracts.
  1118  		if cap > maxRequestSize {
  1119  			cap = maxRequestSize
  1120  		}
  1121  		if cap < minRequestSize { // Don't bother with peers below a bare minimum performance
  1122  			cap = minRequestSize
  1123  		}
  1124  		storageSets := cap / 1024
  1125  
  1126  		var (
  1127  			accounts = make([]common.Hash, 0, storageSets)
  1128  			roots    = make([]common.Hash, 0, storageSets)
  1129  			subtask  *storageTask
  1130  		)
  1131  		for account, subtasks := range task.SubTasks {
  1132  			for _, st := range subtasks {
  1133  				// Skip any subtasks already filling
  1134  				if st.req != nil {
  1135  					continue
  1136  				}
  1137  				// Found an incomplete storage chunk, schedule it
  1138  				accounts = append(accounts, account)
  1139  				roots = append(roots, st.root)
  1140  				subtask = st
  1141  				break // Large contract chunks are downloaded individually
  1142  			}
  1143  			if subtask != nil {
  1144  				break // Large contract chunks are downloaded individually
  1145  			}
  1146  		}
  1147  		if subtask == nil {
  1148  			// No large contract required retrieval, but small ones available
  1149  			for acccount, root := range task.stateTasks {
  1150  				delete(task.stateTasks, acccount)
  1151  
  1152  				accounts = append(accounts, acccount)
  1153  				roots = append(roots, root)
  1154  
  1155  				if len(accounts) >= storageSets {
  1156  					break
  1157  				}
  1158  			}
  1159  		}
  1160  		// If nothing was found, it means this task is actually already fully
  1161  		// retrieving, but large contracts are hard to detect. Skip to the next.
  1162  		if len(accounts) == 0 {
  1163  			continue
  1164  		}
  1165  		req := &storageRequest{
  1166  			peer:     idle,
  1167  			id:       reqid,
  1168  			time:     time.Now(),
  1169  			deliver:  success,
  1170  			revert:   fail,
  1171  			cancel:   cancel,
  1172  			stale:    make(chan struct{}),
  1173  			accounts: accounts,
  1174  			roots:    roots,
  1175  			mainTask: task,
  1176  			subTask:  subtask,
  1177  		}
  1178  		if subtask != nil {
  1179  			req.origin = subtask.Next
  1180  			req.limit = subtask.Last
  1181  		}
  1182  		req.timeout = time.AfterFunc(s.rates.TargetTimeout(), func() {
  1183  			peer.Log().Debug("Storage request timed out", "reqid", reqid)
  1184  			s.rates.Update(idle, StorageRangesMsg, 0, 0)
  1185  			s.scheduleRevertStorageRequest(req)
  1186  		})
  1187  		s.storageReqs[reqid] = req
  1188  		delete(s.storageIdlers, idle)
  1189  
  1190  		s.pend.Add(1)
  1191  		go func(root common.Hash) {
  1192  			defer s.pend.Done()
  1193  
  1194  			// Attempt to send the remote request and revert if it fails
  1195  			var origin, limit []byte
  1196  			if subtask != nil {
  1197  				origin, limit = req.origin[:], req.limit[:]
  1198  			}
  1199  			if err := peer.RequestStorageRanges(reqid, root, accounts, origin, limit, uint64(cap)); err != nil {
  1200  				log.Debug("Failed to request storage", "err", err)
  1201  				s.scheduleRevertStorageRequest(req)
  1202  			}
  1203  		}(s.root)
  1204  
  1205  		// Inject the request into the subtask to block further assignments
  1206  		if subtask != nil {
  1207  			subtask.req = req
  1208  		}
  1209  	}
  1210  }
  1211  
  1212  // assignTrienodeHealTasks attempts to match idle peers to trie node requests to
  1213  // heal any trie errors caused by the snap sync's chunked retrieval model.
  1214  func (s *Syncer) assignTrienodeHealTasks(success chan *trienodeHealResponse, fail chan *trienodeHealRequest, cancel chan struct{}) {
  1215  	s.lock.Lock()
  1216  	defer s.lock.Unlock()
  1217  
  1218  	// Sort the peers by download capacity to use faster ones if many available
  1219  	idlers := &capacitySort{
  1220  		ids:  make([]string, 0, len(s.trienodeHealIdlers)),
  1221  		caps: make([]int, 0, len(s.trienodeHealIdlers)),
  1222  	}
  1223  	targetTTL := s.rates.TargetTimeout()
  1224  	for id := range s.trienodeHealIdlers {
  1225  		if _, ok := s.statelessPeers[id]; ok {
  1226  			continue
  1227  		}
  1228  		idlers.ids = append(idlers.ids, id)
  1229  		idlers.caps = append(idlers.caps, s.rates.Capacity(id, TrieNodesMsg, targetTTL))
  1230  	}
  1231  	if len(idlers.ids) == 0 {
  1232  		return
  1233  	}
  1234  	sort.Sort(sort.Reverse(idlers))
  1235  
  1236  	// Iterate over pending tasks and try to find a peer to retrieve with
  1237  	for len(s.healer.trieTasks) > 0 || s.healer.scheduler.Pending() > 0 {
  1238  		// If there are not enough trie tasks queued to fully assign, fill the
  1239  		// queue from the state sync scheduler. The trie synced schedules these
  1240  		// together with bytecodes, so we need to queue them combined.
  1241  		var (
  1242  			have = len(s.healer.trieTasks) + len(s.healer.codeTasks)
  1243  			want = maxTrieRequestCount + maxCodeRequestCount
  1244  		)
  1245  		if have < want {
  1246  			nodes, paths, codes := s.healer.scheduler.Missing(want - have)
  1247  			for i, hash := range nodes {
  1248  				s.healer.trieTasks[hash] = paths[i]
  1249  			}
  1250  			for _, hash := range codes {
  1251  				s.healer.codeTasks[hash] = struct{}{}
  1252  			}
  1253  		}
  1254  		// If all the heal tasks are bytecodes or already downloading, bail
  1255  		if len(s.healer.trieTasks) == 0 {
  1256  			return
  1257  		}
  1258  		// Task pending retrieval, try to find an idle peer. If no such peer
  1259  		// exists, we probably assigned tasks for all (or they are stateless).
  1260  		// Abort the entire assignment mechanism.
  1261  		if len(idlers.ids) == 0 {
  1262  			return
  1263  		}
  1264  		var (
  1265  			idle = idlers.ids[0]
  1266  			peer = s.peers[idle]
  1267  			cap  = idlers.caps[0]
  1268  		)
  1269  		idlers.ids, idlers.caps = idlers.ids[1:], idlers.caps[1:]
  1270  
  1271  		// Matched a pending task to an idle peer, allocate a unique request id
  1272  		var reqid uint64
  1273  		for {
  1274  			reqid = uint64(rand.Int63())
  1275  			if reqid == 0 {
  1276  				continue
  1277  			}
  1278  			if _, ok := s.trienodeHealReqs[reqid]; ok {
  1279  				continue
  1280  			}
  1281  			break
  1282  		}
  1283  		// Generate the network query and send it to the peer
  1284  		if cap > maxTrieRequestCount {
  1285  			cap = maxTrieRequestCount
  1286  		}
  1287  		var (
  1288  			hashes   = make([]common.Hash, 0, cap)
  1289  			paths    = make([]trie.SyncPath, 0, cap)
  1290  			pathsets = make([]TrieNodePathSet, 0, cap)
  1291  		)
  1292  		for hash, pathset := range s.healer.trieTasks {
  1293  			delete(s.healer.trieTasks, hash)
  1294  
  1295  			hashes = append(hashes, hash)
  1296  			paths = append(paths, pathset)
  1297  			pathsets = append(pathsets, [][]byte(pathset)) // TODO(karalabe): group requests by account hash
  1298  
  1299  			if len(hashes) >= cap {
  1300  				break
  1301  			}
  1302  		}
  1303  		req := &trienodeHealRequest{
  1304  			peer:    idle,
  1305  			id:      reqid,
  1306  			time:    time.Now(),
  1307  			deliver: success,
  1308  			revert:  fail,
  1309  			cancel:  cancel,
  1310  			stale:   make(chan struct{}),
  1311  			hashes:  hashes,
  1312  			paths:   paths,
  1313  			task:    s.healer,
  1314  		}
  1315  		req.timeout = time.AfterFunc(s.rates.TargetTimeout(), func() {
  1316  			peer.Log().Debug("Trienode heal request timed out", "reqid", reqid)
  1317  			s.rates.Update(idle, TrieNodesMsg, 0, 0)
  1318  			s.scheduleRevertTrienodeHealRequest(req)
  1319  		})
  1320  		s.trienodeHealReqs[reqid] = req
  1321  		delete(s.trienodeHealIdlers, idle)
  1322  
  1323  		s.pend.Add(1)
  1324  		go func(root common.Hash) {
  1325  			defer s.pend.Done()
  1326  
  1327  			// Attempt to send the remote request and revert if it fails
  1328  			if err := peer.RequestTrieNodes(reqid, root, pathsets, maxRequestSize); err != nil {
  1329  				log.Debug("Failed to request trienode healers", "err", err)
  1330  				s.scheduleRevertTrienodeHealRequest(req)
  1331  			}
  1332  		}(s.root)
  1333  	}
  1334  }
  1335  
  1336  // assignBytecodeHealTasks attempts to match idle peers to bytecode requests to
  1337  // heal any trie errors caused by the snap sync's chunked retrieval model.
  1338  func (s *Syncer) assignBytecodeHealTasks(success chan *bytecodeHealResponse, fail chan *bytecodeHealRequest, cancel chan struct{}) {
  1339  	s.lock.Lock()
  1340  	defer s.lock.Unlock()
  1341  
  1342  	// Sort the peers by download capacity to use faster ones if many available
  1343  	idlers := &capacitySort{
  1344  		ids:  make([]string, 0, len(s.bytecodeHealIdlers)),
  1345  		caps: make([]int, 0, len(s.bytecodeHealIdlers)),
  1346  	}
  1347  	targetTTL := s.rates.TargetTimeout()
  1348  	for id := range s.bytecodeHealIdlers {
  1349  		if _, ok := s.statelessPeers[id]; ok {
  1350  			continue
  1351  		}
  1352  		idlers.ids = append(idlers.ids, id)
  1353  		idlers.caps = append(idlers.caps, s.rates.Capacity(id, ByteCodesMsg, targetTTL))
  1354  	}
  1355  	if len(idlers.ids) == 0 {
  1356  		return
  1357  	}
  1358  	sort.Sort(sort.Reverse(idlers))
  1359  
  1360  	// Iterate over pending tasks and try to find a peer to retrieve with
  1361  	for len(s.healer.codeTasks) > 0 || s.healer.scheduler.Pending() > 0 {
  1362  		// If there are not enough trie tasks queued to fully assign, fill the
  1363  		// queue from the state sync scheduler. The trie synced schedules these
  1364  		// together with trie nodes, so we need to queue them combined.
  1365  		var (
  1366  			have = len(s.healer.trieTasks) + len(s.healer.codeTasks)
  1367  			want = maxTrieRequestCount + maxCodeRequestCount
  1368  		)
  1369  		if have < want {
  1370  			nodes, paths, codes := s.healer.scheduler.Missing(want - have)
  1371  			for i, hash := range nodes {
  1372  				s.healer.trieTasks[hash] = paths[i]
  1373  			}
  1374  			for _, hash := range codes {
  1375  				s.healer.codeTasks[hash] = struct{}{}
  1376  			}
  1377  		}
  1378  		// If all the heal tasks are trienodes or already downloading, bail
  1379  		if len(s.healer.codeTasks) == 0 {
  1380  			return
  1381  		}
  1382  		// Task pending retrieval, try to find an idle peer. If no such peer
  1383  		// exists, we probably assigned tasks for all (or they are stateless).
  1384  		// Abort the entire assignment mechanism.
  1385  		if len(idlers.ids) == 0 {
  1386  			return
  1387  		}
  1388  		var (
  1389  			idle = idlers.ids[0]
  1390  			peer = s.peers[idle]
  1391  			cap  = idlers.caps[0]
  1392  		)
  1393  		idlers.ids, idlers.caps = idlers.ids[1:], idlers.caps[1:]
  1394  
  1395  		// Matched a pending task to an idle peer, allocate a unique request id
  1396  		var reqid uint64
  1397  		for {
  1398  			reqid = uint64(rand.Int63())
  1399  			if reqid == 0 {
  1400  				continue
  1401  			}
  1402  			if _, ok := s.bytecodeHealReqs[reqid]; ok {
  1403  				continue
  1404  			}
  1405  			break
  1406  		}
  1407  		// Generate the network query and send it to the peer
  1408  		if cap > maxCodeRequestCount {
  1409  			cap = maxCodeRequestCount
  1410  		}
  1411  		hashes := make([]common.Hash, 0, cap)
  1412  		for hash := range s.healer.codeTasks {
  1413  			delete(s.healer.codeTasks, hash)
  1414  
  1415  			hashes = append(hashes, hash)
  1416  			if len(hashes) >= cap {
  1417  				break
  1418  			}
  1419  		}
  1420  		req := &bytecodeHealRequest{
  1421  			peer:    idle,
  1422  			id:      reqid,
  1423  			time:    time.Now(),
  1424  			deliver: success,
  1425  			revert:  fail,
  1426  			cancel:  cancel,
  1427  			stale:   make(chan struct{}),
  1428  			hashes:  hashes,
  1429  			task:    s.healer,
  1430  		}
  1431  		req.timeout = time.AfterFunc(s.rates.TargetTimeout(), func() {
  1432  			peer.Log().Debug("Bytecode heal request timed out", "reqid", reqid)
  1433  			s.rates.Update(idle, ByteCodesMsg, 0, 0)
  1434  			s.scheduleRevertBytecodeHealRequest(req)
  1435  		})
  1436  		s.bytecodeHealReqs[reqid] = req
  1437  		delete(s.bytecodeHealIdlers, idle)
  1438  
  1439  		s.pend.Add(1)
  1440  		go func() {
  1441  			defer s.pend.Done()
  1442  
  1443  			// Attempt to send the remote request and revert if it fails
  1444  			if err := peer.RequestByteCodes(reqid, hashes, maxRequestSize); err != nil {
  1445  				log.Debug("Failed to request bytecode healers", "err", err)
  1446  				s.scheduleRevertBytecodeHealRequest(req)
  1447  			}
  1448  		}()
  1449  	}
  1450  }
  1451  
  1452  // revertRequests locates all the currently pending reuqests from a particular
  1453  // peer and reverts them, rescheduling for others to fulfill.
  1454  func (s *Syncer) revertRequests(peer string) {
  1455  	// Gather the requests first, revertals need the lock too
  1456  	s.lock.Lock()
  1457  	var accountReqs []*accountRequest
  1458  	for _, req := range s.accountReqs {
  1459  		if req.peer == peer {
  1460  			accountReqs = append(accountReqs, req)
  1461  		}
  1462  	}
  1463  	var bytecodeReqs []*bytecodeRequest
  1464  	for _, req := range s.bytecodeReqs {
  1465  		if req.peer == peer {
  1466  			bytecodeReqs = append(bytecodeReqs, req)
  1467  		}
  1468  	}
  1469  	var storageReqs []*storageRequest
  1470  	for _, req := range s.storageReqs {
  1471  		if req.peer == peer {
  1472  			storageReqs = append(storageReqs, req)
  1473  		}
  1474  	}
  1475  	var trienodeHealReqs []*trienodeHealRequest
  1476  	for _, req := range s.trienodeHealReqs {
  1477  		if req.peer == peer {
  1478  			trienodeHealReqs = append(trienodeHealReqs, req)
  1479  		}
  1480  	}
  1481  	var bytecodeHealReqs []*bytecodeHealRequest
  1482  	for _, req := range s.bytecodeHealReqs {
  1483  		if req.peer == peer {
  1484  			bytecodeHealReqs = append(bytecodeHealReqs, req)
  1485  		}
  1486  	}
  1487  	s.lock.Unlock()
  1488  
  1489  	// Revert all the requests matching the peer
  1490  	for _, req := range accountReqs {
  1491  		s.revertAccountRequest(req)
  1492  	}
  1493  	for _, req := range bytecodeReqs {
  1494  		s.revertBytecodeRequest(req)
  1495  	}
  1496  	for _, req := range storageReqs {
  1497  		s.revertStorageRequest(req)
  1498  	}
  1499  	for _, req := range trienodeHealReqs {
  1500  		s.revertTrienodeHealRequest(req)
  1501  	}
  1502  	for _, req := range bytecodeHealReqs {
  1503  		s.revertBytecodeHealRequest(req)
  1504  	}
  1505  }
  1506  
  1507  // scheduleRevertAccountRequest asks the event loop to clean up an account range
  1508  // request and return all failed retrieval tasks to the scheduler for reassignment.
  1509  func (s *Syncer) scheduleRevertAccountRequest(req *accountRequest) {
  1510  	select {
  1511  	case req.revert <- req:
  1512  		// Sync event loop notified
  1513  	case <-req.cancel:
  1514  		// Sync cycle got cancelled
  1515  	case <-req.stale:
  1516  		// Request already reverted
  1517  	}
  1518  }
  1519  
  1520  // revertAccountRequest cleans up an account range request and returns all failed
  1521  // retrieval tasks to the scheduler for reassignment.
  1522  //
  1523  // Note, this needs to run on the event runloop thread to reschedule to idle peers.
  1524  // On peer threads, use scheduleRevertAccountRequest.
  1525  func (s *Syncer) revertAccountRequest(req *accountRequest) {
  1526  	log.Debug("Reverting account request", "peer", req.peer, "reqid", req.id)
  1527  	select {
  1528  	case <-req.stale:
  1529  		log.Trace("Account request already reverted", "peer", req.peer, "reqid", req.id)
  1530  		return
  1531  	default:
  1532  	}
  1533  	close(req.stale)
  1534  
  1535  	// Remove the request from the tracked set
  1536  	s.lock.Lock()
  1537  	delete(s.accountReqs, req.id)
  1538  	s.lock.Unlock()
  1539  
  1540  	// If there's a timeout timer still running, abort it and mark the account
  1541  	// task as not-pending, ready for resheduling
  1542  	req.timeout.Stop()
  1543  	if req.task.req == req {
  1544  		req.task.req = nil
  1545  	}
  1546  }
  1547  
  1548  // scheduleRevertBytecodeRequest asks the event loop to clean up a bytecode request
  1549  // and return all failed retrieval tasks to the scheduler for reassignment.
  1550  func (s *Syncer) scheduleRevertBytecodeRequest(req *bytecodeRequest) {
  1551  	select {
  1552  	case req.revert <- req:
  1553  		// Sync event loop notified
  1554  	case <-req.cancel:
  1555  		// Sync cycle got cancelled
  1556  	case <-req.stale:
  1557  		// Request already reverted
  1558  	}
  1559  }
  1560  
  1561  // revertBytecodeRequest cleans up a bytecode request and returns all failed
  1562  // retrieval tasks to the scheduler for reassignment.
  1563  //
  1564  // Note, this needs to run on the event runloop thread to reschedule to idle peers.
  1565  // On peer threads, use scheduleRevertBytecodeRequest.
  1566  func (s *Syncer) revertBytecodeRequest(req *bytecodeRequest) {
  1567  	log.Debug("Reverting bytecode request", "peer", req.peer)
  1568  	select {
  1569  	case <-req.stale:
  1570  		log.Trace("Bytecode request already reverted", "peer", req.peer, "reqid", req.id)
  1571  		return
  1572  	default:
  1573  	}
  1574  	close(req.stale)
  1575  
  1576  	// Remove the request from the tracked set
  1577  	s.lock.Lock()
  1578  	delete(s.bytecodeReqs, req.id)
  1579  	s.lock.Unlock()
  1580  
  1581  	// If there's a timeout timer still running, abort it and mark the code
  1582  	// retrievals as not-pending, ready for resheduling
  1583  	req.timeout.Stop()
  1584  	for _, hash := range req.hashes {
  1585  		req.task.codeTasks[hash] = struct{}{}
  1586  	}
  1587  }
  1588  
  1589  // scheduleRevertStorageRequest asks the event loop to clean up a storage range
  1590  // request and return all failed retrieval tasks to the scheduler for reassignment.
  1591  func (s *Syncer) scheduleRevertStorageRequest(req *storageRequest) {
  1592  	select {
  1593  	case req.revert <- req:
  1594  		// Sync event loop notified
  1595  	case <-req.cancel:
  1596  		// Sync cycle got cancelled
  1597  	case <-req.stale:
  1598  		// Request already reverted
  1599  	}
  1600  }
  1601  
  1602  // revertStorageRequest cleans up a storage range request and returns all failed
  1603  // retrieval tasks to the scheduler for reassignment.
  1604  //
  1605  // Note, this needs to run on the event runloop thread to reschedule to idle peers.
  1606  // On peer threads, use scheduleRevertStorageRequest.
  1607  func (s *Syncer) revertStorageRequest(req *storageRequest) {
  1608  	log.Debug("Reverting storage request", "peer", req.peer)
  1609  	select {
  1610  	case <-req.stale:
  1611  		log.Trace("Storage request already reverted", "peer", req.peer, "reqid", req.id)
  1612  		return
  1613  	default:
  1614  	}
  1615  	close(req.stale)
  1616  
  1617  	// Remove the request from the tracked set
  1618  	s.lock.Lock()
  1619  	delete(s.storageReqs, req.id)
  1620  	s.lock.Unlock()
  1621  
  1622  	// If there's a timeout timer still running, abort it and mark the storage
  1623  	// task as not-pending, ready for resheduling
  1624  	req.timeout.Stop()
  1625  	if req.subTask != nil {
  1626  		req.subTask.req = nil
  1627  	} else {
  1628  		for i, account := range req.accounts {
  1629  			req.mainTask.stateTasks[account] = req.roots[i]
  1630  		}
  1631  	}
  1632  }
  1633  
  1634  // scheduleRevertTrienodeHealRequest asks the event loop to clean up a trienode heal
  1635  // request and return all failed retrieval tasks to the scheduler for reassignment.
  1636  func (s *Syncer) scheduleRevertTrienodeHealRequest(req *trienodeHealRequest) {
  1637  	select {
  1638  	case req.revert <- req:
  1639  		// Sync event loop notified
  1640  	case <-req.cancel:
  1641  		// Sync cycle got cancelled
  1642  	case <-req.stale:
  1643  		// Request already reverted
  1644  	}
  1645  }
  1646  
  1647  // revertTrienodeHealRequest cleans up a trienode heal request and returns all
  1648  // failed retrieval tasks to the scheduler for reassignment.
  1649  //
  1650  // Note, this needs to run on the event runloop thread to reschedule to idle peers.
  1651  // On peer threads, use scheduleRevertTrienodeHealRequest.
  1652  func (s *Syncer) revertTrienodeHealRequest(req *trienodeHealRequest) {
  1653  	log.Debug("Reverting trienode heal request", "peer", req.peer)
  1654  	select {
  1655  	case <-req.stale:
  1656  		log.Trace("Trienode heal request already reverted", "peer", req.peer, "reqid", req.id)
  1657  		return
  1658  	default:
  1659  	}
  1660  	close(req.stale)
  1661  
  1662  	// Remove the request from the tracked set
  1663  	s.lock.Lock()
  1664  	delete(s.trienodeHealReqs, req.id)
  1665  	s.lock.Unlock()
  1666  
  1667  	// If there's a timeout timer still running, abort it and mark the trie node
  1668  	// retrievals as not-pending, ready for resheduling
  1669  	req.timeout.Stop()
  1670  	for i, hash := range req.hashes {
  1671  		req.task.trieTasks[hash] = req.paths[i]
  1672  	}
  1673  }
  1674  
  1675  // scheduleRevertBytecodeHealRequest asks the event loop to clean up a bytecode heal
  1676  // request and return all failed retrieval tasks to the scheduler for reassignment.
  1677  func (s *Syncer) scheduleRevertBytecodeHealRequest(req *bytecodeHealRequest) {
  1678  	select {
  1679  	case req.revert <- req:
  1680  		// Sync event loop notified
  1681  	case <-req.cancel:
  1682  		// Sync cycle got cancelled
  1683  	case <-req.stale:
  1684  		// Request already reverted
  1685  	}
  1686  }
  1687  
  1688  // revertBytecodeHealRequest cleans up a bytecode heal request and returns all
  1689  // failed retrieval tasks to the scheduler for reassignment.
  1690  //
  1691  // Note, this needs to run on the event runloop thread to reschedule to idle peers.
  1692  // On peer threads, use scheduleRevertBytecodeHealRequest.
  1693  func (s *Syncer) revertBytecodeHealRequest(req *bytecodeHealRequest) {
  1694  	log.Debug("Reverting bytecode heal request", "peer", req.peer)
  1695  	select {
  1696  	case <-req.stale:
  1697  		log.Trace("Bytecode heal request already reverted", "peer", req.peer, "reqid", req.id)
  1698  		return
  1699  	default:
  1700  	}
  1701  	close(req.stale)
  1702  
  1703  	// Remove the request from the tracked set
  1704  	s.lock.Lock()
  1705  	delete(s.bytecodeHealReqs, req.id)
  1706  	s.lock.Unlock()
  1707  
  1708  	// If there's a timeout timer still running, abort it and mark the code
  1709  	// retrievals as not-pending, ready for resheduling
  1710  	req.timeout.Stop()
  1711  	for _, hash := range req.hashes {
  1712  		req.task.codeTasks[hash] = struct{}{}
  1713  	}
  1714  }
  1715  
  1716  // processAccountResponse integrates an already validated account range response
  1717  // into the account tasks.
  1718  func (s *Syncer) processAccountResponse(res *accountResponse) {
  1719  	// Switch the task from pending to filling
  1720  	res.task.req = nil
  1721  	res.task.res = res
  1722  
  1723  	// Ensure that the response doesn't overflow into the subsequent task
  1724  	last := res.task.Last.Big()
  1725  	for i, hash := range res.hashes {
  1726  		// Mark the range complete if the last is already included.
  1727  		// Keep iteration to delete the extra states if exists.
  1728  		cmp := hash.Big().Cmp(last)
  1729  		if cmp == 0 {
  1730  			res.cont = false
  1731  			continue
  1732  		}
  1733  		if cmp > 0 {
  1734  			// Chunk overflown, cut off excess
  1735  			res.hashes = res.hashes[:i]
  1736  			res.accounts = res.accounts[:i]
  1737  			res.cont = false // Mark range completed
  1738  			break
  1739  		}
  1740  	}
  1741  	// Iterate over all the accounts and assemble which ones need further sub-
  1742  	// filling before the entire account range can be persisted.
  1743  	res.task.needCode = make([]bool, len(res.accounts))
  1744  	res.task.needState = make([]bool, len(res.accounts))
  1745  	res.task.needHeal = make([]bool, len(res.accounts))
  1746  
  1747  	res.task.codeTasks = make(map[common.Hash]struct{})
  1748  	res.task.stateTasks = make(map[common.Hash]common.Hash)
  1749  
  1750  	resumed := make(map[common.Hash]struct{})
  1751  
  1752  	res.task.pend = 0
  1753  	for i, account := range res.accounts {
  1754  		// Check if the account is a contract with an unknown code
  1755  		if !bytes.Equal(account.CodeHash, emptyCode[:]) {
  1756  			if code := rawdb.ReadCodeWithPrefix(s.db, common.BytesToHash(account.CodeHash)); code == nil {
  1757  				res.task.codeTasks[common.BytesToHash(account.CodeHash)] = struct{}{}
  1758  				res.task.needCode[i] = true
  1759  				res.task.pend++
  1760  			}
  1761  		}
  1762  		// Check if the account is a contract with an unknown storage trie
  1763  		if account.Root != emptyRoot {
  1764  			if node, err := s.db.Get(account.Root[:]); err != nil || node == nil {
  1765  				// If there was a previous large state retrieval in progress,
  1766  				// don't restart it from scratch. This happens if a sync cycle
  1767  				// is interrupted and resumed later. However, *do* update the
  1768  				// previous root hash.
  1769  				if subtasks, ok := res.task.SubTasks[res.hashes[i]]; ok {
  1770  					log.Debug("Resuming large storage retrieval", "account", res.hashes[i], "root", account.Root)
  1771  					for _, subtask := range subtasks {
  1772  						subtask.root = account.Root
  1773  					}
  1774  					res.task.needHeal[i] = true
  1775  					resumed[res.hashes[i]] = struct{}{}
  1776  				} else {
  1777  					res.task.stateTasks[res.hashes[i]] = account.Root
  1778  				}
  1779  				res.task.needState[i] = true
  1780  				res.task.pend++
  1781  			}
  1782  		}
  1783  	}
  1784  	// Delete any subtasks that have been aborted but not resumed. This may undo
  1785  	// some progress if a new peer gives us less accounts than an old one, but for
  1786  	// now we have to live with that.
  1787  	for hash := range res.task.SubTasks {
  1788  		if _, ok := resumed[hash]; !ok {
  1789  			log.Debug("Aborting suspended storage retrieval", "account", hash)
  1790  			delete(res.task.SubTasks, hash)
  1791  		}
  1792  	}
  1793  	// If the account range contained no contracts, or all have been fully filled
  1794  	// beforehand, short circuit storage filling and forward to the next task
  1795  	if res.task.pend == 0 {
  1796  		s.forwardAccountTask(res.task)
  1797  		return
  1798  	}
  1799  	// Some accounts are incomplete, leave as is for the storage and contract
  1800  	// task assigners to pick up and fill.
  1801  }
  1802  
  1803  // processBytecodeResponse integrates an already validated bytecode response
  1804  // into the account tasks.
  1805  func (s *Syncer) processBytecodeResponse(res *bytecodeResponse) {
  1806  	batch := s.db.NewBatch()
  1807  
  1808  	var (
  1809  		codes uint64
  1810  	)
  1811  	for i, hash := range res.hashes {
  1812  		code := res.codes[i]
  1813  
  1814  		// If the bytecode was not delivered, reschedule it
  1815  		if code == nil {
  1816  			res.task.codeTasks[hash] = struct{}{}
  1817  			continue
  1818  		}
  1819  		// Code was delivered, mark it not needed any more
  1820  		for j, account := range res.task.res.accounts {
  1821  			if res.task.needCode[j] && hash == common.BytesToHash(account.CodeHash) {
  1822  				res.task.needCode[j] = false
  1823  				res.task.pend--
  1824  			}
  1825  		}
  1826  		// Push the bytecode into a database batch
  1827  		codes++
  1828  		rawdb.WriteCode(batch, hash, code)
  1829  	}
  1830  	bytes := common.StorageSize(batch.ValueSize())
  1831  	if err := batch.Write(); err != nil {
  1832  		log.Crit("Failed to persist bytecodes", "err", err)
  1833  	}
  1834  	s.bytecodeSynced += codes
  1835  	s.bytecodeBytes += bytes
  1836  
  1837  	log.Debug("Persisted set of bytecodes", "count", codes, "bytes", bytes)
  1838  
  1839  	// If this delivery completed the last pending task, forward the account task
  1840  	// to the next chunk
  1841  	if res.task.pend == 0 {
  1842  		s.forwardAccountTask(res.task)
  1843  		return
  1844  	}
  1845  	// Some accounts are still incomplete, leave as is for the storage and contract
  1846  	// task assigners to pick up and fill.
  1847  }
  1848  
  1849  // processStorageResponse integrates an already validated storage response
  1850  // into the account tasks.
  1851  func (s *Syncer) processStorageResponse(res *storageResponse) {
  1852  	// Switch the subtask from pending to idle
  1853  	if res.subTask != nil {
  1854  		res.subTask.req = nil
  1855  	}
  1856  	batch := ethdb.HookedBatch{
  1857  		Batch: s.db.NewBatch(),
  1858  		OnPut: func(key []byte, value []byte) {
  1859  			s.storageBytes += common.StorageSize(len(key) + len(value))
  1860  		},
  1861  	}
  1862  	var (
  1863  		slots           int
  1864  		oldStorageBytes = s.storageBytes
  1865  	)
  1866  	// Iterate over all the accounts and reconstruct their storage tries from the
  1867  	// delivered slots
  1868  	for i, account := range res.accounts {
  1869  		// If the account was not delivered, reschedule it
  1870  		if i >= len(res.hashes) {
  1871  			res.mainTask.stateTasks[account] = res.roots[i]
  1872  			continue
  1873  		}
  1874  		// State was delivered, if complete mark as not needed any more, otherwise
  1875  		// mark the account as needing healing
  1876  		for j, hash := range res.mainTask.res.hashes {
  1877  			if account != hash {
  1878  				continue
  1879  			}
  1880  			acc := res.mainTask.res.accounts[j]
  1881  
  1882  			// If the packet contains multiple contract storage slots, all
  1883  			// but the last are surely complete. The last contract may be
  1884  			// chunked, so check it's continuation flag.
  1885  			if res.subTask == nil && res.mainTask.needState[j] && (i < len(res.hashes)-1 || !res.cont) {
  1886  				res.mainTask.needState[j] = false
  1887  				res.mainTask.pend--
  1888  			}
  1889  			// If the last contract was chunked, mark it as needing healing
  1890  			// to avoid writing it out to disk prematurely.
  1891  			if res.subTask == nil && !res.mainTask.needHeal[j] && i == len(res.hashes)-1 && res.cont {
  1892  				res.mainTask.needHeal[j] = true
  1893  			}
  1894  			// If the last contract was chunked, we need to switch to large
  1895  			// contract handling mode
  1896  			if res.subTask == nil && i == len(res.hashes)-1 && res.cont {
  1897  				// If we haven't yet started a large-contract retrieval, create
  1898  				// the subtasks for it within the main account task
  1899  				if tasks, ok := res.mainTask.SubTasks[account]; !ok {
  1900  					var (
  1901  						keys    = res.hashes[i]
  1902  						chunks  = uint64(storageConcurrency)
  1903  						lastKey common.Hash
  1904  					)
  1905  					if len(keys) > 0 {
  1906  						lastKey = keys[len(keys)-1]
  1907  					}
  1908  					// If the number of slots remaining is low, decrease the
  1909  					// number of chunks. Somewhere on the order of 10-15K slots
  1910  					// fit into a packet of 500KB. A key/slot pair is maximum 64
  1911  					// bytes, so pessimistically maxRequestSize/64 = 8K.
  1912  					//
  1913  					// Chunk so that at least 2 packets are needed to fill a task.
  1914  					if estimate, err := estimateRemainingSlots(len(keys), lastKey); err == nil {
  1915  						if n := estimate / (2 * (maxRequestSize / 64)); n+1 < chunks {
  1916  							chunks = n + 1
  1917  						}
  1918  						log.Debug("Chunked large contract", "initiators", len(keys), "tail", lastKey, "remaining", estimate, "chunks", chunks)
  1919  					} else {
  1920  						log.Debug("Chunked large contract", "initiators", len(keys), "tail", lastKey, "chunks", chunks)
  1921  					}
  1922  					r := newHashRange(lastKey, chunks)
  1923  
  1924  					// Our first task is the one that was just filled by this response.
  1925  					batch := ethdb.HookedBatch{
  1926  						Batch: s.db.NewBatch(),
  1927  						OnPut: func(key []byte, value []byte) {
  1928  							s.storageBytes += common.StorageSize(len(key) + len(value))
  1929  						},
  1930  					}
  1931  					tasks = append(tasks, &storageTask{
  1932  						Next:     common.Hash{},
  1933  						Last:     r.End(),
  1934  						root:     acc.Root,
  1935  						genBatch: batch,
  1936  						genTrie:  trie.NewStackTrie(batch),
  1937  					})
  1938  					for r.Next() {
  1939  						batch := ethdb.HookedBatch{
  1940  							Batch: s.db.NewBatch(),
  1941  							OnPut: func(key []byte, value []byte) {
  1942  								s.storageBytes += common.StorageSize(len(key) + len(value))
  1943  							},
  1944  						}
  1945  						tasks = append(tasks, &storageTask{
  1946  							Next:     r.Start(),
  1947  							Last:     r.End(),
  1948  							root:     acc.Root,
  1949  							genBatch: batch,
  1950  							genTrie:  trie.NewStackTrie(batch),
  1951  						})
  1952  					}
  1953  					for _, task := range tasks {
  1954  						log.Debug("Created storage sync task", "account", account, "root", acc.Root, "from", task.Next, "last", task.Last)
  1955  					}
  1956  					res.mainTask.SubTasks[account] = tasks
  1957  
  1958  					// Since we've just created the sub-tasks, this response
  1959  					// is surely for the first one (zero origin)
  1960  					res.subTask = tasks[0]
  1961  				}
  1962  			}
  1963  			// If we're in large contract delivery mode, forward the subtask
  1964  			if res.subTask != nil {
  1965  				// Ensure the response doesn't overflow into the subsequent task
  1966  				last := res.subTask.Last.Big()
  1967  				// Find the first overflowing key. While at it, mark res as complete
  1968  				// if we find the range to include or pass the 'last'
  1969  				index := sort.Search(len(res.hashes[i]), func(k int) bool {
  1970  					cmp := res.hashes[i][k].Big().Cmp(last)
  1971  					if cmp >= 0 {
  1972  						res.cont = false
  1973  					}
  1974  					return cmp > 0
  1975  				})
  1976  				if index >= 0 {
  1977  					// cut off excess
  1978  					res.hashes[i] = res.hashes[i][:index]
  1979  					res.slots[i] = res.slots[i][:index]
  1980  				}
  1981  				// Forward the relevant storage chunk (even if created just now)
  1982  				if res.cont {
  1983  					res.subTask.Next = incHash(res.hashes[i][len(res.hashes[i])-1])
  1984  				} else {
  1985  					res.subTask.done = true
  1986  				}
  1987  			}
  1988  		}
  1989  		// Iterate over all the complete contracts, reconstruct the trie nodes and
  1990  		// push them to disk. If the contract is chunked, the trie nodes will be
  1991  		// reconstructed later.
  1992  		slots += len(res.hashes[i])
  1993  
  1994  		if i < len(res.hashes)-1 || res.subTask == nil {
  1995  			tr := trie.NewStackTrie(batch)
  1996  			for j := 0; j < len(res.hashes[i]); j++ {
  1997  				tr.Update(res.hashes[i][j][:], res.slots[i][j])
  1998  			}
  1999  			tr.Commit()
  2000  		}
  2001  		// Persist the received storage segements. These flat state maybe
  2002  		// outdated during the sync, but it can be fixed later during the
  2003  		// snapshot generation.
  2004  		for j := 0; j < len(res.hashes[i]); j++ {
  2005  			rawdb.WriteStorageSnapshot(batch, account, res.hashes[i][j], res.slots[i][j])
  2006  
  2007  			// If we're storing large contracts, generate the trie nodes
  2008  			// on the fly to not trash the gluing points
  2009  			if i == len(res.hashes)-1 && res.subTask != nil {
  2010  				res.subTask.genTrie.Update(res.hashes[i][j][:], res.slots[i][j])
  2011  			}
  2012  		}
  2013  	}
  2014  	// Large contracts could have generated new trie nodes, flush them to disk
  2015  	if res.subTask != nil {
  2016  		if res.subTask.done {
  2017  			if root, err := res.subTask.genTrie.Commit(); err != nil {
  2018  				log.Error("Failed to commit stack slots", "err", err)
  2019  			} else if root == res.subTask.root {
  2020  				// If the chunk's root is an overflown but full delivery, clear the heal request
  2021  				for i, account := range res.mainTask.res.hashes {
  2022  					if account == res.accounts[len(res.accounts)-1] {
  2023  						res.mainTask.needHeal[i] = false
  2024  					}
  2025  				}
  2026  			}
  2027  		}
  2028  		if res.subTask.genBatch.ValueSize() > ethdb.IdealBatchSize || res.subTask.done {
  2029  			if err := res.subTask.genBatch.Write(); err != nil {
  2030  				log.Error("Failed to persist stack slots", "err", err)
  2031  			}
  2032  			res.subTask.genBatch.Reset()
  2033  		}
  2034  	}
  2035  	// Flush anything written just now and update the stats
  2036  	if err := batch.Write(); err != nil {
  2037  		log.Crit("Failed to persist storage slots", "err", err)
  2038  	}
  2039  	s.storageSynced += uint64(slots)
  2040  
  2041  	log.Debug("Persisted set of storage slots", "accounts", len(res.hashes), "slots", slots, "bytes", s.storageBytes-oldStorageBytes)
  2042  
  2043  	// If this delivery completed the last pending task, forward the account task
  2044  	// to the next chunk
  2045  	if res.mainTask.pend == 0 {
  2046  		s.forwardAccountTask(res.mainTask)
  2047  		return
  2048  	}
  2049  	// Some accounts are still incomplete, leave as is for the storage and contract
  2050  	// task assigners to pick up and fill.
  2051  }
  2052  
  2053  // processTrienodeHealResponse integrates an already validated trienode response
  2054  // into the healer tasks.
  2055  func (s *Syncer) processTrienodeHealResponse(res *trienodeHealResponse) {
  2056  	for i, hash := range res.hashes {
  2057  		node := res.nodes[i]
  2058  
  2059  		// If the trie node was not delivered, reschedule it
  2060  		if node == nil {
  2061  			res.task.trieTasks[hash] = res.paths[i]
  2062  			continue
  2063  		}
  2064  		// Push the trie node into the state syncer
  2065  		s.trienodeHealSynced++
  2066  		s.trienodeHealBytes += common.StorageSize(len(node))
  2067  
  2068  		err := s.healer.scheduler.Process(trie.SyncResult{Hash: hash, Data: node})
  2069  		switch err {
  2070  		case nil:
  2071  		case trie.ErrAlreadyProcessed:
  2072  			s.trienodeHealDups++
  2073  		case trie.ErrNotRequested:
  2074  			s.trienodeHealNops++
  2075  		default:
  2076  			log.Error("Invalid trienode processed", "hash", hash, "err", err)
  2077  		}
  2078  	}
  2079  	batch := s.db.NewBatch()
  2080  	if err := s.healer.scheduler.Commit(batch); err != nil {
  2081  		log.Error("Failed to commit healing data", "err", err)
  2082  	}
  2083  	if err := batch.Write(); err != nil {
  2084  		log.Crit("Failed to persist healing data", "err", err)
  2085  	}
  2086  	log.Debug("Persisted set of healing data", "type", "trienodes", "bytes", common.StorageSize(batch.ValueSize()))
  2087  }
  2088  
  2089  // processBytecodeHealResponse integrates an already validated bytecode response
  2090  // into the healer tasks.
  2091  func (s *Syncer) processBytecodeHealResponse(res *bytecodeHealResponse) {
  2092  	for i, hash := range res.hashes {
  2093  		node := res.codes[i]
  2094  
  2095  		// If the trie node was not delivered, reschedule it
  2096  		if node == nil {
  2097  			res.task.codeTasks[hash] = struct{}{}
  2098  			continue
  2099  		}
  2100  		// Push the trie node into the state syncer
  2101  		s.bytecodeHealSynced++
  2102  		s.bytecodeHealBytes += common.StorageSize(len(node))
  2103  
  2104  		err := s.healer.scheduler.Process(trie.SyncResult{Hash: hash, Data: node})
  2105  		switch err {
  2106  		case nil:
  2107  		case trie.ErrAlreadyProcessed:
  2108  			s.bytecodeHealDups++
  2109  		case trie.ErrNotRequested:
  2110  			s.bytecodeHealNops++
  2111  		default:
  2112  			log.Error("Invalid bytecode processed", "hash", hash, "err", err)
  2113  		}
  2114  	}
  2115  	batch := s.db.NewBatch()
  2116  	if err := s.healer.scheduler.Commit(batch); err != nil {
  2117  		log.Error("Failed to commit healing data", "err", err)
  2118  	}
  2119  	if err := batch.Write(); err != nil {
  2120  		log.Crit("Failed to persist healing data", "err", err)
  2121  	}
  2122  	log.Debug("Persisted set of healing data", "type", "bytecode", "bytes", common.StorageSize(batch.ValueSize()))
  2123  }
  2124  
  2125  // forwardAccountTask takes a filled account task and persists anything available
  2126  // into the database, after which it forwards the next account marker so that the
  2127  // task's next chunk may be filled.
  2128  func (s *Syncer) forwardAccountTask(task *accountTask) {
  2129  	// Remove any pending delivery
  2130  	res := task.res
  2131  	if res == nil {
  2132  		return // nothing to forward
  2133  	}
  2134  	task.res = nil
  2135  
  2136  	// Persist the received account segements. These flat state maybe
  2137  	// outdated during the sync, but it can be fixed later during the
  2138  	// snapshot generation.
  2139  	oldAccountBytes := s.accountBytes
  2140  
  2141  	batch := ethdb.HookedBatch{
  2142  		Batch: s.db.NewBatch(),
  2143  		OnPut: func(key []byte, value []byte) {
  2144  			s.accountBytes += common.StorageSize(len(key) + len(value))
  2145  		},
  2146  	}
  2147  	for i, hash := range res.hashes {
  2148  		if task.needCode[i] || task.needState[i] {
  2149  			break
  2150  		}
  2151  		slim := snapshot.SlimAccountRLP(res.accounts[i].Nonce, res.accounts[i].Balance, res.accounts[i].Root, res.accounts[i].CodeHash)
  2152  		rawdb.WriteAccountSnapshot(batch, hash, slim)
  2153  
  2154  		// If the task is complete, drop it into the stack trie to generate
  2155  		// account trie nodes for it
  2156  		if !task.needHeal[i] {
  2157  			full, err := snapshot.FullAccountRLP(slim) // TODO(karalabe): Slim parsing can be omitted
  2158  			if err != nil {
  2159  				panic(err) // Really shouldn't ever happen
  2160  			}
  2161  			task.genTrie.Update(hash[:], full)
  2162  		}
  2163  	}
  2164  	// Flush anything written just now and update the stats
  2165  	if err := batch.Write(); err != nil {
  2166  		log.Crit("Failed to persist accounts", "err", err)
  2167  	}
  2168  	s.accountSynced += uint64(len(res.accounts))
  2169  
  2170  	// Task filling persisted, push it the chunk marker forward to the first
  2171  	// account still missing data.
  2172  	for i, hash := range res.hashes {
  2173  		if task.needCode[i] || task.needState[i] {
  2174  			return
  2175  		}
  2176  		task.Next = incHash(hash)
  2177  	}
  2178  	// All accounts marked as complete, track if the entire task is done
  2179  	task.done = !res.cont
  2180  
  2181  	// Stack trie could have generated trie nodes, push them to disk (we need to
  2182  	// flush after finalizing task.done. It's fine even if we crash and lose this
  2183  	// write as it will only cause more data to be downloaded during heal.
  2184  	if task.done {
  2185  		if _, err := task.genTrie.Commit(); err != nil {
  2186  			log.Error("Failed to commit stack account", "err", err)
  2187  		}
  2188  	}
  2189  	if task.genBatch.ValueSize() > ethdb.IdealBatchSize || task.done {
  2190  		if err := task.genBatch.Write(); err != nil {
  2191  			log.Error("Failed to persist stack account", "err", err)
  2192  		}
  2193  		task.genBatch.Reset()
  2194  	}
  2195  	log.Debug("Persisted range of accounts", "accounts", len(res.accounts), "bytes", s.accountBytes-oldAccountBytes)
  2196  }
  2197  
  2198  // OnAccounts is a callback method to invoke when a range of accounts are
  2199  // received from a remote peer.
  2200  func (s *Syncer) OnAccounts(peer SyncPeer, id uint64, hashes []common.Hash, accounts [][]byte, proof [][]byte) error {
  2201  	size := common.StorageSize(len(hashes) * common.HashLength)
  2202  	for _, account := range accounts {
  2203  		size += common.StorageSize(len(account))
  2204  	}
  2205  	for _, node := range proof {
  2206  		size += common.StorageSize(len(node))
  2207  	}
  2208  	logger := peer.Log().New("reqid", id)
  2209  	logger.Trace("Delivering range of accounts", "hashes", len(hashes), "accounts", len(accounts), "proofs", len(proof), "bytes", size)
  2210  
  2211  	// Whether or not the response is valid, we can mark the peer as idle and
  2212  	// notify the scheduler to assign a new task. If the response is invalid,
  2213  	// we'll drop the peer in a bit.
  2214  	s.lock.Lock()
  2215  	if _, ok := s.peers[peer.ID()]; ok {
  2216  		s.accountIdlers[peer.ID()] = struct{}{}
  2217  	}
  2218  	select {
  2219  	case s.update <- struct{}{}:
  2220  	default:
  2221  	}
  2222  	// Ensure the response is for a valid request
  2223  	req, ok := s.accountReqs[id]
  2224  	if !ok {
  2225  		// Request stale, perhaps the peer timed out but came through in the end
  2226  		logger.Warn("Unexpected account range packet")
  2227  		s.lock.Unlock()
  2228  		return nil
  2229  	}
  2230  	delete(s.accountReqs, id)
  2231  	s.rates.Update(peer.ID(), AccountRangeMsg, time.Since(req.time), int(size))
  2232  
  2233  	// Clean up the request timeout timer, we'll see how to proceed further based
  2234  	// on the actual delivered content
  2235  	if !req.timeout.Stop() {
  2236  		// The timeout is already triggered, and this request will be reverted+rescheduled
  2237  		s.lock.Unlock()
  2238  		return nil
  2239  	}
  2240  	// Response is valid, but check if peer is signalling that it does not have
  2241  	// the requested data. For account range queries that means the state being
  2242  	// retrieved was either already pruned remotely, or the peer is not yet
  2243  	// synced to our head.
  2244  	if len(hashes) == 0 && len(accounts) == 0 && len(proof) == 0 {
  2245  		logger.Debug("Peer rejected account range request", "root", s.root)
  2246  		s.statelessPeers[peer.ID()] = struct{}{}
  2247  		s.lock.Unlock()
  2248  
  2249  		// Signal this request as failed, and ready for rescheduling
  2250  		s.scheduleRevertAccountRequest(req)
  2251  		return nil
  2252  	}
  2253  	root := s.root
  2254  	s.lock.Unlock()
  2255  
  2256  	// Reconstruct a partial trie from the response and verify it
  2257  	keys := make([][]byte, len(hashes))
  2258  	for i, key := range hashes {
  2259  		keys[i] = common.CopyBytes(key[:])
  2260  	}
  2261  	nodes := make(light.NodeList, len(proof))
  2262  	for i, node := range proof {
  2263  		nodes[i] = node
  2264  	}
  2265  	proofdb := nodes.NodeSet()
  2266  
  2267  	var end []byte
  2268  	if len(keys) > 0 {
  2269  		end = keys[len(keys)-1]
  2270  	}
  2271  	cont, err := trie.VerifyRangeProof(root, req.origin[:], end, keys, accounts, proofdb)
  2272  	if err != nil {
  2273  		logger.Warn("Account range failed proof", "err", err)
  2274  		// Signal this request as failed, and ready for rescheduling
  2275  		s.scheduleRevertAccountRequest(req)
  2276  		return err
  2277  	}
  2278  	accs := make([]*types.StateAccount, len(accounts))
  2279  	for i, account := range accounts {
  2280  		acc := new(types.StateAccount)
  2281  		if err := rlp.DecodeBytes(account, acc); err != nil {
  2282  			panic(err) // We created these blobs, we must be able to decode them
  2283  		}
  2284  		accs[i] = acc
  2285  	}
  2286  	response := &accountResponse{
  2287  		task:     req.task,
  2288  		hashes:   hashes,
  2289  		accounts: accs,
  2290  		cont:     cont,
  2291  	}
  2292  	select {
  2293  	case req.deliver <- response:
  2294  	case <-req.cancel:
  2295  	case <-req.stale:
  2296  	}
  2297  	return nil
  2298  }
  2299  
  2300  // OnByteCodes is a callback method to invoke when a batch of contract
  2301  // bytes codes are received from a remote peer.
  2302  func (s *Syncer) OnByteCodes(peer SyncPeer, id uint64, bytecodes [][]byte) error {
  2303  	s.lock.RLock()
  2304  	syncing := !s.snapped
  2305  	s.lock.RUnlock()
  2306  
  2307  	if syncing {
  2308  		return s.onByteCodes(peer, id, bytecodes)
  2309  	}
  2310  	return s.onHealByteCodes(peer, id, bytecodes)
  2311  }
  2312  
  2313  // onByteCodes is a callback method to invoke when a batch of contract
  2314  // bytes codes are received from a remote peer in the syncing phase.
  2315  func (s *Syncer) onByteCodes(peer SyncPeer, id uint64, bytecodes [][]byte) error {
  2316  	var size common.StorageSize
  2317  	for _, code := range bytecodes {
  2318  		size += common.StorageSize(len(code))
  2319  	}
  2320  	logger := peer.Log().New("reqid", id)
  2321  	logger.Trace("Delivering set of bytecodes", "bytecodes", len(bytecodes), "bytes", size)
  2322  
  2323  	// Whether or not the response is valid, we can mark the peer as idle and
  2324  	// notify the scheduler to assign a new task. If the response is invalid,
  2325  	// we'll drop the peer in a bit.
  2326  	s.lock.Lock()
  2327  	if _, ok := s.peers[peer.ID()]; ok {
  2328  		s.bytecodeIdlers[peer.ID()] = struct{}{}
  2329  	}
  2330  	select {
  2331  	case s.update <- struct{}{}:
  2332  	default:
  2333  	}
  2334  	// Ensure the response is for a valid request
  2335  	req, ok := s.bytecodeReqs[id]
  2336  	if !ok {
  2337  		// Request stale, perhaps the peer timed out but came through in the end
  2338  		logger.Warn("Unexpected bytecode packet")
  2339  		s.lock.Unlock()
  2340  		return nil
  2341  	}
  2342  	delete(s.bytecodeReqs, id)
  2343  	s.rates.Update(peer.ID(), ByteCodesMsg, time.Since(req.time), len(bytecodes))
  2344  
  2345  	// Clean up the request timeout timer, we'll see how to proceed further based
  2346  	// on the actual delivered content
  2347  	if !req.timeout.Stop() {
  2348  		// The timeout is already triggered, and this request will be reverted+rescheduled
  2349  		s.lock.Unlock()
  2350  		return nil
  2351  	}
  2352  
  2353  	// Response is valid, but check if peer is signalling that it does not have
  2354  	// the requested data. For bytecode range queries that means the peer is not
  2355  	// yet synced.
  2356  	if len(bytecodes) == 0 {
  2357  		logger.Debug("Peer rejected bytecode request")
  2358  		s.statelessPeers[peer.ID()] = struct{}{}
  2359  		s.lock.Unlock()
  2360  
  2361  		// Signal this request as failed, and ready for rescheduling
  2362  		s.scheduleRevertBytecodeRequest(req)
  2363  		return nil
  2364  	}
  2365  	s.lock.Unlock()
  2366  
  2367  	// Cross reference the requested bytecodes with the response to find gaps
  2368  	// that the serving node is missing
  2369  	hasher := sha3.NewLegacyKeccak256().(crypto.KeccakState)
  2370  	hash := make([]byte, 32)
  2371  
  2372  	codes := make([][]byte, len(req.hashes))
  2373  	for i, j := 0, 0; i < len(bytecodes); i++ {
  2374  		// Find the next hash that we've been served, leaving misses with nils
  2375  		hasher.Reset()
  2376  		hasher.Write(bytecodes[i])
  2377  		hasher.Read(hash)
  2378  
  2379  		for j < len(req.hashes) && !bytes.Equal(hash, req.hashes[j][:]) {
  2380  			j++
  2381  		}
  2382  		if j < len(req.hashes) {
  2383  			codes[j] = bytecodes[i]
  2384  			j++
  2385  			continue
  2386  		}
  2387  		// We've either ran out of hashes, or got unrequested data
  2388  		logger.Warn("Unexpected bytecodes", "count", len(bytecodes)-i)
  2389  		// Signal this request as failed, and ready for rescheduling
  2390  		s.scheduleRevertBytecodeRequest(req)
  2391  		return errors.New("unexpected bytecode")
  2392  	}
  2393  	// Response validated, send it to the scheduler for filling
  2394  	response := &bytecodeResponse{
  2395  		task:   req.task,
  2396  		hashes: req.hashes,
  2397  		codes:  codes,
  2398  	}
  2399  	select {
  2400  	case req.deliver <- response:
  2401  	case <-req.cancel:
  2402  	case <-req.stale:
  2403  	}
  2404  	return nil
  2405  }
  2406  
  2407  // OnStorage is a callback method to invoke when ranges of storage slots
  2408  // are received from a remote peer.
  2409  func (s *Syncer) OnStorage(peer SyncPeer, id uint64, hashes [][]common.Hash, slots [][][]byte, proof [][]byte) error {
  2410  	// Gather some trace stats to aid in debugging issues
  2411  	var (
  2412  		hashCount int
  2413  		slotCount int
  2414  		size      common.StorageSize
  2415  	)
  2416  	for _, hashset := range hashes {
  2417  		size += common.StorageSize(common.HashLength * len(hashset))
  2418  		hashCount += len(hashset)
  2419  	}
  2420  	for _, slotset := range slots {
  2421  		for _, slot := range slotset {
  2422  			size += common.StorageSize(len(slot))
  2423  		}
  2424  		slotCount += len(slotset)
  2425  	}
  2426  	for _, node := range proof {
  2427  		size += common.StorageSize(len(node))
  2428  	}
  2429  	logger := peer.Log().New("reqid", id)
  2430  	logger.Trace("Delivering ranges of storage slots", "accounts", len(hashes), "hashes", hashCount, "slots", slotCount, "proofs", len(proof), "size", size)
  2431  
  2432  	// Whether or not the response is valid, we can mark the peer as idle and
  2433  	// notify the scheduler to assign a new task. If the response is invalid,
  2434  	// we'll drop the peer in a bit.
  2435  	s.lock.Lock()
  2436  	if _, ok := s.peers[peer.ID()]; ok {
  2437  		s.storageIdlers[peer.ID()] = struct{}{}
  2438  	}
  2439  	select {
  2440  	case s.update <- struct{}{}:
  2441  	default:
  2442  	}
  2443  	// Ensure the response is for a valid request
  2444  	req, ok := s.storageReqs[id]
  2445  	if !ok {
  2446  		// Request stale, perhaps the peer timed out but came through in the end
  2447  		logger.Warn("Unexpected storage ranges packet")
  2448  		s.lock.Unlock()
  2449  		return nil
  2450  	}
  2451  	delete(s.storageReqs, id)
  2452  	s.rates.Update(peer.ID(), StorageRangesMsg, time.Since(req.time), int(size))
  2453  
  2454  	// Clean up the request timeout timer, we'll see how to proceed further based
  2455  	// on the actual delivered content
  2456  	if !req.timeout.Stop() {
  2457  		// The timeout is already triggered, and this request will be reverted+rescheduled
  2458  		s.lock.Unlock()
  2459  		return nil
  2460  	}
  2461  
  2462  	// Reject the response if the hash sets and slot sets don't match, or if the
  2463  	// peer sent more data than requested.
  2464  	if len(hashes) != len(slots) {
  2465  		s.lock.Unlock()
  2466  		s.scheduleRevertStorageRequest(req) // reschedule request
  2467  		logger.Warn("Hash and slot set size mismatch", "hashset", len(hashes), "slotset", len(slots))
  2468  		return errors.New("hash and slot set size mismatch")
  2469  	}
  2470  	if len(hashes) > len(req.accounts) {
  2471  		s.lock.Unlock()
  2472  		s.scheduleRevertStorageRequest(req) // reschedule request
  2473  		logger.Warn("Hash set larger than requested", "hashset", len(hashes), "requested", len(req.accounts))
  2474  		return errors.New("hash set larger than requested")
  2475  	}
  2476  	// Response is valid, but check if peer is signalling that it does not have
  2477  	// the requested data. For storage range queries that means the state being
  2478  	// retrieved was either already pruned remotely, or the peer is not yet
  2479  	// synced to our head.
  2480  	if len(hashes) == 0 {
  2481  		logger.Debug("Peer rejected storage request")
  2482  		s.statelessPeers[peer.ID()] = struct{}{}
  2483  		s.lock.Unlock()
  2484  		s.scheduleRevertStorageRequest(req) // reschedule request
  2485  		return nil
  2486  	}
  2487  	s.lock.Unlock()
  2488  
  2489  	// Reconstruct the partial tries from the response and verify them
  2490  	var cont bool
  2491  
  2492  	for i := 0; i < len(hashes); i++ {
  2493  		// Convert the keys and proofs into an internal format
  2494  		keys := make([][]byte, len(hashes[i]))
  2495  		for j, key := range hashes[i] {
  2496  			keys[j] = common.CopyBytes(key[:])
  2497  		}
  2498  		nodes := make(light.NodeList, 0, len(proof))
  2499  		if i == len(hashes)-1 {
  2500  			for _, node := range proof {
  2501  				nodes = append(nodes, node)
  2502  			}
  2503  		}
  2504  		var err error
  2505  		if len(nodes) == 0 {
  2506  			// No proof has been attached, the response must cover the entire key
  2507  			// space and hash to the origin root.
  2508  			_, err = trie.VerifyRangeProof(req.roots[i], nil, nil, keys, slots[i], nil)
  2509  			if err != nil {
  2510  				s.scheduleRevertStorageRequest(req) // reschedule request
  2511  				logger.Warn("Storage slots failed proof", "err", err)
  2512  				return err
  2513  			}
  2514  		} else {
  2515  			// A proof was attached, the response is only partial, check that the
  2516  			// returned data is indeed part of the storage trie
  2517  			proofdb := nodes.NodeSet()
  2518  
  2519  			var end []byte
  2520  			if len(keys) > 0 {
  2521  				end = keys[len(keys)-1]
  2522  			}
  2523  			cont, err = trie.VerifyRangeProof(req.roots[i], req.origin[:], end, keys, slots[i], proofdb)
  2524  			if err != nil {
  2525  				s.scheduleRevertStorageRequest(req) // reschedule request
  2526  				logger.Warn("Storage range failed proof", "err", err)
  2527  				return err
  2528  			}
  2529  		}
  2530  	}
  2531  	// Partial tries reconstructed, send them to the scheduler for storage filling
  2532  	response := &storageResponse{
  2533  		mainTask: req.mainTask,
  2534  		subTask:  req.subTask,
  2535  		accounts: req.accounts,
  2536  		roots:    req.roots,
  2537  		hashes:   hashes,
  2538  		slots:    slots,
  2539  		cont:     cont,
  2540  	}
  2541  	select {
  2542  	case req.deliver <- response:
  2543  	case <-req.cancel:
  2544  	case <-req.stale:
  2545  	}
  2546  	return nil
  2547  }
  2548  
  2549  // OnTrieNodes is a callback method to invoke when a batch of trie nodes
  2550  // are received from a remote peer.
  2551  func (s *Syncer) OnTrieNodes(peer SyncPeer, id uint64, trienodes [][]byte) error {
  2552  	var size common.StorageSize
  2553  	for _, node := range trienodes {
  2554  		size += common.StorageSize(len(node))
  2555  	}
  2556  	logger := peer.Log().New("reqid", id)
  2557  	logger.Trace("Delivering set of healing trienodes", "trienodes", len(trienodes), "bytes", size)
  2558  
  2559  	// Whether or not the response is valid, we can mark the peer as idle and
  2560  	// notify the scheduler to assign a new task. If the response is invalid,
  2561  	// we'll drop the peer in a bit.
  2562  	s.lock.Lock()
  2563  	if _, ok := s.peers[peer.ID()]; ok {
  2564  		s.trienodeHealIdlers[peer.ID()] = struct{}{}
  2565  	}
  2566  	select {
  2567  	case s.update <- struct{}{}:
  2568  	default:
  2569  	}
  2570  	// Ensure the response is for a valid request
  2571  	req, ok := s.trienodeHealReqs[id]
  2572  	if !ok {
  2573  		// Request stale, perhaps the peer timed out but came through in the end
  2574  		logger.Warn("Unexpected trienode heal packet")
  2575  		s.lock.Unlock()
  2576  		return nil
  2577  	}
  2578  	delete(s.trienodeHealReqs, id)
  2579  	s.rates.Update(peer.ID(), TrieNodesMsg, time.Since(req.time), len(trienodes))
  2580  
  2581  	// Clean up the request timeout timer, we'll see how to proceed further based
  2582  	// on the actual delivered content
  2583  	if !req.timeout.Stop() {
  2584  		// The timeout is already triggered, and this request will be reverted+rescheduled
  2585  		s.lock.Unlock()
  2586  		return nil
  2587  	}
  2588  
  2589  	// Response is valid, but check if peer is signalling that it does not have
  2590  	// the requested data. For bytecode range queries that means the peer is not
  2591  	// yet synced.
  2592  	if len(trienodes) == 0 {
  2593  		logger.Debug("Peer rejected trienode heal request")
  2594  		s.statelessPeers[peer.ID()] = struct{}{}
  2595  		s.lock.Unlock()
  2596  
  2597  		// Signal this request as failed, and ready for rescheduling
  2598  		s.scheduleRevertTrienodeHealRequest(req)
  2599  		return nil
  2600  	}
  2601  	s.lock.Unlock()
  2602  
  2603  	// Cross reference the requested trienodes with the response to find gaps
  2604  	// that the serving node is missing
  2605  	hasher := sha3.NewLegacyKeccak256().(crypto.KeccakState)
  2606  	hash := make([]byte, 32)
  2607  
  2608  	nodes := make([][]byte, len(req.hashes))
  2609  	for i, j := 0, 0; i < len(trienodes); i++ {
  2610  		// Find the next hash that we've been served, leaving misses with nils
  2611  		hasher.Reset()
  2612  		hasher.Write(trienodes[i])
  2613  		hasher.Read(hash)
  2614  
  2615  		for j < len(req.hashes) && !bytes.Equal(hash, req.hashes[j][:]) {
  2616  			j++
  2617  		}
  2618  		if j < len(req.hashes) {
  2619  			nodes[j] = trienodes[i]
  2620  			j++
  2621  			continue
  2622  		}
  2623  		// We've either ran out of hashes, or got unrequested data
  2624  		logger.Warn("Unexpected healing trienodes", "count", len(trienodes)-i)
  2625  		// Signal this request as failed, and ready for rescheduling
  2626  		s.scheduleRevertTrienodeHealRequest(req)
  2627  		return errors.New("unexpected healing trienode")
  2628  	}
  2629  	// Response validated, send it to the scheduler for filling
  2630  	response := &trienodeHealResponse{
  2631  		task:   req.task,
  2632  		hashes: req.hashes,
  2633  		paths:  req.paths,
  2634  		nodes:  nodes,
  2635  	}
  2636  	select {
  2637  	case req.deliver <- response:
  2638  	case <-req.cancel:
  2639  	case <-req.stale:
  2640  	}
  2641  	return nil
  2642  }
  2643  
  2644  // onHealByteCodes is a callback method to invoke when a batch of contract
  2645  // bytes codes are received from a remote peer in the healing phase.
  2646  func (s *Syncer) onHealByteCodes(peer SyncPeer, id uint64, bytecodes [][]byte) error {
  2647  	var size common.StorageSize
  2648  	for _, code := range bytecodes {
  2649  		size += common.StorageSize(len(code))
  2650  	}
  2651  	logger := peer.Log().New("reqid", id)
  2652  	logger.Trace("Delivering set of healing bytecodes", "bytecodes", len(bytecodes), "bytes", size)
  2653  
  2654  	// Whether or not the response is valid, we can mark the peer as idle and
  2655  	// notify the scheduler to assign a new task. If the response is invalid,
  2656  	// we'll drop the peer in a bit.
  2657  	s.lock.Lock()
  2658  	if _, ok := s.peers[peer.ID()]; ok {
  2659  		s.bytecodeHealIdlers[peer.ID()] = struct{}{}
  2660  	}
  2661  	select {
  2662  	case s.update <- struct{}{}:
  2663  	default:
  2664  	}
  2665  	// Ensure the response is for a valid request
  2666  	req, ok := s.bytecodeHealReqs[id]
  2667  	if !ok {
  2668  		// Request stale, perhaps the peer timed out but came through in the end
  2669  		logger.Warn("Unexpected bytecode heal packet")
  2670  		s.lock.Unlock()
  2671  		return nil
  2672  	}
  2673  	delete(s.bytecodeHealReqs, id)
  2674  	s.rates.Update(peer.ID(), ByteCodesMsg, time.Since(req.time), len(bytecodes))
  2675  
  2676  	// Clean up the request timeout timer, we'll see how to proceed further based
  2677  	// on the actual delivered content
  2678  	if !req.timeout.Stop() {
  2679  		// The timeout is already triggered, and this request will be reverted+rescheduled
  2680  		s.lock.Unlock()
  2681  		return nil
  2682  	}
  2683  
  2684  	// Response is valid, but check if peer is signalling that it does not have
  2685  	// the requested data. For bytecode range queries that means the peer is not
  2686  	// yet synced.
  2687  	if len(bytecodes) == 0 {
  2688  		logger.Debug("Peer rejected bytecode heal request")
  2689  		s.statelessPeers[peer.ID()] = struct{}{}
  2690  		s.lock.Unlock()
  2691  
  2692  		// Signal this request as failed, and ready for rescheduling
  2693  		s.scheduleRevertBytecodeHealRequest(req)
  2694  		return nil
  2695  	}
  2696  	s.lock.Unlock()
  2697  
  2698  	// Cross reference the requested bytecodes with the response to find gaps
  2699  	// that the serving node is missing
  2700  	hasher := sha3.NewLegacyKeccak256().(crypto.KeccakState)
  2701  	hash := make([]byte, 32)
  2702  
  2703  	codes := make([][]byte, len(req.hashes))
  2704  	for i, j := 0, 0; i < len(bytecodes); i++ {
  2705  		// Find the next hash that we've been served, leaving misses with nils
  2706  		hasher.Reset()
  2707  		hasher.Write(bytecodes[i])
  2708  		hasher.Read(hash)
  2709  
  2710  		for j < len(req.hashes) && !bytes.Equal(hash, req.hashes[j][:]) {
  2711  			j++
  2712  		}
  2713  		if j < len(req.hashes) {
  2714  			codes[j] = bytecodes[i]
  2715  			j++
  2716  			continue
  2717  		}
  2718  		// We've either ran out of hashes, or got unrequested data
  2719  		logger.Warn("Unexpected healing bytecodes", "count", len(bytecodes)-i)
  2720  		// Signal this request as failed, and ready for rescheduling
  2721  		s.scheduleRevertBytecodeHealRequest(req)
  2722  		return errors.New("unexpected healing bytecode")
  2723  	}
  2724  	// Response validated, send it to the scheduler for filling
  2725  	response := &bytecodeHealResponse{
  2726  		task:   req.task,
  2727  		hashes: req.hashes,
  2728  		codes:  codes,
  2729  	}
  2730  	select {
  2731  	case req.deliver <- response:
  2732  	case <-req.cancel:
  2733  	case <-req.stale:
  2734  	}
  2735  	return nil
  2736  }
  2737  
  2738  // onHealState is a callback method to invoke when a flat state(account
  2739  // or storage slot) is downloded during the healing stage. The flat states
  2740  // can be persisted blindly and can be fixed later in the generation stage.
  2741  // Note it's not concurrent safe, please handle the concurrent issue outside.
  2742  func (s *Syncer) onHealState(paths [][]byte, value []byte) error {
  2743  	if len(paths) == 1 {
  2744  		var account types.StateAccount
  2745  		if err := rlp.DecodeBytes(value, &account); err != nil {
  2746  			return nil
  2747  		}
  2748  		blob := snapshot.SlimAccountRLP(account.Nonce, account.Balance, account.Root, account.CodeHash)
  2749  		rawdb.WriteAccountSnapshot(s.stateWriter, common.BytesToHash(paths[0]), blob)
  2750  		s.accountHealed += 1
  2751  		s.accountHealedBytes += common.StorageSize(1 + common.HashLength + len(blob))
  2752  	}
  2753  	if len(paths) == 2 {
  2754  		rawdb.WriteStorageSnapshot(s.stateWriter, common.BytesToHash(paths[0]), common.BytesToHash(paths[1]), value)
  2755  		s.storageHealed += 1
  2756  		s.storageHealedBytes += common.StorageSize(1 + 2*common.HashLength + len(value))
  2757  	}
  2758  	if s.stateWriter.ValueSize() > ethdb.IdealBatchSize {
  2759  		s.stateWriter.Write() // It's fine to ignore the error here
  2760  		s.stateWriter.Reset()
  2761  	}
  2762  	return nil
  2763  }
  2764  
  2765  // hashSpace is the total size of the 256 bit hash space for accounts.
  2766  var hashSpace = new(big.Int).Exp(common.Big2, common.Big256, nil)
  2767  
  2768  // report calculates various status reports and provides it to the user.
  2769  func (s *Syncer) report(force bool) {
  2770  	if len(s.tasks) > 0 {
  2771  		s.reportSyncProgress(force)
  2772  		return
  2773  	}
  2774  	s.reportHealProgress(force)
  2775  }
  2776  
  2777  // reportSyncProgress calculates various status reports and provides it to the user.
  2778  func (s *Syncer) reportSyncProgress(force bool) {
  2779  	// Don't report all the events, just occasionally
  2780  	if !force && time.Since(s.logTime) < 8*time.Second {
  2781  		return
  2782  	}
  2783  	// Don't report anything until we have a meaningful progress
  2784  	synced := s.accountBytes + s.bytecodeBytes + s.storageBytes
  2785  	if synced == 0 {
  2786  		return
  2787  	}
  2788  	accountGaps := new(big.Int)
  2789  	for _, task := range s.tasks {
  2790  		accountGaps.Add(accountGaps, new(big.Int).Sub(task.Last.Big(), task.Next.Big()))
  2791  	}
  2792  	accountFills := new(big.Int).Sub(hashSpace, accountGaps)
  2793  	if accountFills.BitLen() == 0 {
  2794  		return
  2795  	}
  2796  	s.logTime = time.Now()
  2797  	estBytes := float64(new(big.Int).Div(
  2798  		new(big.Int).Mul(new(big.Int).SetUint64(uint64(synced)), hashSpace),
  2799  		accountFills,
  2800  	).Uint64())
  2801  
  2802  	elapsed := time.Since(s.startTime)
  2803  	estTime := elapsed / time.Duration(synced) * time.Duration(estBytes)
  2804  
  2805  	// Create a mega progress report
  2806  	var (
  2807  		progress = fmt.Sprintf("%.2f%%", float64(synced)*100/estBytes)
  2808  		accounts = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(s.accountSynced), s.accountBytes.TerminalString())
  2809  		storage  = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(s.storageSynced), s.storageBytes.TerminalString())
  2810  		bytecode = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(s.bytecodeSynced), s.bytecodeBytes.TerminalString())
  2811  	)
  2812  	log.Info("State sync in progress", "synced", progress, "state", synced,
  2813  		"accounts", accounts, "slots", storage, "codes", bytecode, "eta", common.PrettyDuration(estTime-elapsed))
  2814  }
  2815  
  2816  // reportHealProgress calculates various status reports and provides it to the user.
  2817  func (s *Syncer) reportHealProgress(force bool) {
  2818  	// Don't report all the events, just occasionally
  2819  	if !force && time.Since(s.logTime) < 8*time.Second {
  2820  		return
  2821  	}
  2822  	s.logTime = time.Now()
  2823  
  2824  	// Create a mega progress report
  2825  	var (
  2826  		trienode = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(s.trienodeHealSynced), s.trienodeHealBytes.TerminalString())
  2827  		bytecode = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(s.bytecodeHealSynced), s.bytecodeHealBytes.TerminalString())
  2828  		accounts = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(s.accountHealed), s.accountHealedBytes.TerminalString())
  2829  		storage  = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(s.storageHealed), s.storageHealedBytes.TerminalString())
  2830  	)
  2831  	log.Info("State heal in progress", "accounts", accounts, "slots", storage,
  2832  		"codes", bytecode, "nodes", trienode, "pending", s.healer.scheduler.Pending())
  2833  }
  2834  
  2835  // estimateRemainingSlots tries to determine roughly how many slots are left in
  2836  // a contract storage, based on the number of keys and the last hash. This method
  2837  // assumes that the hashes are lexicographically ordered and evenly distributed.
  2838  func estimateRemainingSlots(hashes int, last common.Hash) (uint64, error) {
  2839  	if last == (common.Hash{}) {
  2840  		return 0, errors.New("last hash empty")
  2841  	}
  2842  	space := new(big.Int).Mul(math.MaxBig256, big.NewInt(int64(hashes)))
  2843  	space.Div(space, last.Big())
  2844  	if !space.IsUint64() {
  2845  		// Gigantic address space probably due to too few or malicious slots
  2846  		return 0, errors.New("too few slots for estimation")
  2847  	}
  2848  	return space.Uint64() - uint64(hashes), nil
  2849  }
  2850  
  2851  // capacitySort implements the Sort interface, allowing sorting by peer message
  2852  // throughput. Note, callers should use sort.Reverse to get the desired effect
  2853  // of highest capacity being at the front.
  2854  type capacitySort struct {
  2855  	ids  []string
  2856  	caps []int
  2857  }
  2858  
  2859  func (s *capacitySort) Len() int {
  2860  	return len(s.ids)
  2861  }
  2862  
  2863  func (s *capacitySort) Less(i, j int) bool {
  2864  	return s.caps[i] < s.caps[j]
  2865  }
  2866  
  2867  func (s *capacitySort) Swap(i, j int) {
  2868  	s.ids[i], s.ids[j] = s.ids[j], s.ids[i]
  2869  	s.caps[i], s.caps[j] = s.caps[j], s.caps[i]
  2870  }