eth/downloader: limit state node retries

This commit is contained in:
Felix Lange 2017-05-30 15:40:32 +02:00 committed by Péter Szilágyi
parent 4c6040c334
commit 44b8cb852c
No known key found for this signature in database
GPG key ID: E9AE538CEDF8293D

View file

@ -31,6 +31,9 @@ import (
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
) )
// If a single state node is tried more than this many times, sync fails.
const maxStateNodeRetries = 50
type stateReq struct { type stateReq struct {
items []common.Hash items []common.Hash
tasks map[common.Hash]*stateTask tasks map[common.Hash]*stateTask
@ -168,6 +171,7 @@ type stateSync struct {
type stateTask struct { type stateTask struct {
triedPeers map[string]struct{} triedPeers map[string]struct{}
numTries int
} }
func newStateSync(d *Downloader, root common.Hash) *stateSync { func newStateSync(d *Downloader, root common.Hash) *stateSync {
@ -263,7 +267,7 @@ func (s *stateSync) popTasks(n int, req *stateReq) error {
if len(s.tasksAvailable) < n { if len(s.tasksAvailable) < n {
new := s.sched.Missing(n - len(s.tasksAvailable)) new := s.sched.Missing(n - len(s.tasksAvailable))
for _, hash := range new { for _, hash := range new {
s.tasksAvailable[hash] = &stateTask{make(map[string]struct{})} s.tasksAvailable[hash] = &stateTask{make(map[string]struct{}), 0}
} }
} }
// Find tasks that haven't been tried with the request's peer. // Find tasks that haven't been tried with the request's peer.
@ -277,6 +281,7 @@ func (s *stateSync) popTasks(n int, req *stateReq) error {
continue continue
} }
t.triedPeers[req.peer.id] = struct{}{} t.triedPeers[req.peer.id] = struct{}{}
t.numTries++
req.items = append(req.items, hash) req.items = append(req.items, hash)
req.tasks[hash] = t req.tasks[hash] = t
delete(s.tasksAvailable, hash) delete(s.tasksAvailable, hash)
@ -309,6 +314,9 @@ func (s *stateSync) process(req *stateReq) (nproc int, err error) {
if npeers := s.d.peers.Len(); len(task.triedPeers) >= npeers { if npeers := s.d.peers.Len(); len(task.triedPeers) >= npeers {
return nproc, fmt.Errorf("state node %s failed with all peers (%d tries, %d peers)", hash.TerminalString(), len(task.triedPeers), npeers) return nproc, fmt.Errorf("state node %s failed with all peers (%d tries, %d peers)", hash.TerminalString(), len(task.triedPeers), npeers)
} }
if task.numTries > maxStateNodeRetries {
return nproc, fmt.Errorf("download of state node %s failed %d times", hash.TerminalString(), task.numTries)
}
s.tasksAvailable[hash] = task s.tasksAvailable[hash] = task
} }
return nproc, nil return nproc, nil