github.com/tirogen/go-ethereum@v1.10.12-0.20221226051715-250cfede41b6/eth/protocols/snap/sync.go (about)

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