mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-25 06:06:44 +00:00
eth/downloader: assume stale delivery vs. attack
This commit is contained in:
parent
aad2559b53
commit
efc1d5127f
3 changed files with 15 additions and 18 deletions
|
|
@ -1372,11 +1372,6 @@ func (d *Downloader) fetchParts(errCancel error, deliveryCh chan dataPack, deliv
|
||||||
// The hash chain is invalid (blocks are not ordered properly), abort
|
// The hash chain is invalid (blocks are not ordered properly), abort
|
||||||
return err
|
return err
|
||||||
|
|
||||||
case errInvalidBody, errInvalidReceipt:
|
|
||||||
// The peer delivered something very bad, drop immediately
|
|
||||||
glog.V(logger.Error).Infof("%s: delivered invalid %s, dropping", peer, strings.ToLower(kind))
|
|
||||||
d.dropPeer(peer.id)
|
|
||||||
|
|
||||||
case errNoFetchesPending:
|
case errNoFetchesPending:
|
||||||
// Peer probably timed out with its delivery but came through
|
// Peer probably timed out with its delivery but came through
|
||||||
// in the end, demote, but allow to to pull from this peer.
|
// in the end, demote, but allow to to pull from this peer.
|
||||||
|
|
|
||||||
|
|
@ -1127,6 +1127,7 @@ func testInvalidHeaderRollback(t *testing.T, protocol int, mode SyncMode) {
|
||||||
assertOwnChain(t, tester, targetBlocks+1)
|
assertOwnChain(t, tester, targetBlocks+1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// Tests that if a peer sends an invalid block piece (body or receipt) for a
|
// Tests that if a peer sends an invalid block piece (body or receipt) for a
|
||||||
// requested block, it gets dropped immediately by the downloader.
|
// requested block, it gets dropped immediately by the downloader.
|
||||||
func TestInvalidContentAttack62(t *testing.T) { testInvalidContentAttack(t, 62, FullSync) }
|
func TestInvalidContentAttack62(t *testing.T) { testInvalidContentAttack(t, 62, FullSync) }
|
||||||
|
|
@ -1171,7 +1172,7 @@ func testInvalidContentAttack(t *testing.T, protocol int, mode SyncMode) {
|
||||||
if _, ok := tester.peerHashes["receipt attack"]; ok {
|
if _, ok := tester.peerHashes["receipt attack"]; ok {
|
||||||
t.Fatalf("receipt attacker not detected/dropped")
|
t.Fatalf("receipt attacker not detected/dropped")
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// Tests that a peer advertising an high TD doesn't get to stall the downloader
|
// Tests that a peer advertising an high TD doesn't get to stall the downloader
|
||||||
// afterwards by not sending any useful hashes.
|
// afterwards by not sending any useful hashes.
|
||||||
|
|
|
||||||
|
|
@ -859,7 +859,10 @@ func (q *queue) deliver(id string, taskPool map[common.Hash]*types.Header, taskQ
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Assemble each of the results with their headers and retrieved data parts
|
// Assemble each of the results with their headers and retrieved data parts
|
||||||
errs := make([]error, 0)
|
var (
|
||||||
|
failure error
|
||||||
|
useful bool
|
||||||
|
)
|
||||||
for i, header := range request.Headers {
|
for i, header := range request.Headers {
|
||||||
// Short circuit assembly if no more fetch results are found
|
// Short circuit assembly if no more fetch results are found
|
||||||
if i >= results {
|
if i >= results {
|
||||||
|
|
@ -868,15 +871,16 @@ func (q *queue) deliver(id string, taskPool map[common.Hash]*types.Header, taskQ
|
||||||
// Reconstruct the next result if contents match up
|
// Reconstruct the next result if contents match up
|
||||||
index := int(header.Number.Int64() - int64(q.resultOffset))
|
index := int(header.Number.Int64() - int64(q.resultOffset))
|
||||||
if index >= len(q.resultCache) || index < 0 || q.resultCache[index] == nil {
|
if index >= len(q.resultCache) || index < 0 || q.resultCache[index] == nil {
|
||||||
errs = []error{errInvalidChain}
|
failure = errInvalidChain
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if err := reconstruct(header, i, q.resultCache[index]); err != nil {
|
if err := reconstruct(header, i, q.resultCache[index]); err != nil {
|
||||||
errs = []error{err}
|
failure = err
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
donePool[header.Hash()] = struct{}{}
|
donePool[header.Hash()] = struct{}{}
|
||||||
q.resultCache[index].Pending--
|
q.resultCache[index].Pending--
|
||||||
|
useful = true
|
||||||
|
|
||||||
// Clean up a successful fetch
|
// Clean up a successful fetch
|
||||||
request.Headers[i] = nil
|
request.Headers[i] = nil
|
||||||
|
|
@ -888,19 +892,16 @@ func (q *queue) deliver(id string, taskPool map[common.Hash]*types.Header, taskQ
|
||||||
taskQueue.Push(header, -float32(header.Number.Uint64()))
|
taskQueue.Push(header, -float32(header.Number.Uint64()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If none of the blocks were good, it's a stale delivery
|
// If none of the data was good, it's a stale delivery
|
||||||
switch {
|
switch {
|
||||||
case len(errs) == 0:
|
case failure == nil || failure == errInvalidChain:
|
||||||
return nil
|
return failure
|
||||||
|
|
||||||
case len(errs) == 1 && (errs[0] == errInvalidChain || errs[0] == errInvalidBody || errs[0] == errInvalidReceipt):
|
case useful:
|
||||||
return errs[0]
|
return fmt.Errorf("partial failure: %v", failure)
|
||||||
|
|
||||||
case len(errs) == results:
|
|
||||||
return errStaleDelivery
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("multiple failures: %v", errs)
|
return errStaleDelivery
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue