github.com/aidoskuneen/adk-node@v0.0.0-20220315131952-2e32567cb7f4/eth/protocols/snap/sync.go (about)

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