aboutsummaryrefslogtreecommitdiffstats
path: root/eth/downloader/downloader.go
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2016-02-16 16:36:26 +0800
committerPéter Szilágyi <peterke@gmail.com>2016-02-19 17:17:02 +0800
commit216729009b7be7de68a88d35f8e0c734b8d011f4 (patch)
treeefe73708db5fa67d98acc9f983ab6bf0dd60e13e /eth/downloader/downloader.go
parent4f28c5b69d652e12adf8a88f526f459a492e159e (diff)
downloaddexon-216729009b7be7de68a88d35f8e0c734b8d011f4.tar
dexon-216729009b7be7de68a88d35f8e0c734b8d011f4.tar.gz
dexon-216729009b7be7de68a88d35f8e0c734b8d011f4.tar.bz2
dexon-216729009b7be7de68a88d35f8e0c734b8d011f4.tar.lz
dexon-216729009b7be7de68a88d35f8e0c734b8d011f4.tar.xz
dexon-216729009b7be7de68a88d35f8e0c734b8d011f4.tar.zst
dexon-216729009b7be7de68a88d35f8e0c734b8d011f4.zip
eth/downloader: fix partial rollback and ancestor lookup
Diffstat (limited to 'eth/downloader/downloader.go')
-rw-r--r--eth/downloader/downloader.go30
1 files changed, 28 insertions, 2 deletions
diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go
index 6dad6a2cd..de54bd859 100644
--- a/eth/downloader/downloader.go
+++ b/eth/downloader/downloader.go
@@ -571,8 +571,14 @@ func (d *Downloader) findAncestor61(p *peer) (uint64, error) {
// Check if a common ancestor was found
finished = true
for i := len(hashes) - 1; i >= 0; i-- {
+ // Skip any headers that underflow/overflow our requested set
+ header := d.getHeader(hashes[i])
+ if header == nil || header.Number.Int64() < from || header.Number.Uint64() > head {
+ continue
+ }
+ // Otherwise check if we already know the header or not
if d.hasBlockAndState(hashes[i]) {
- number, hash = uint64(from)+uint64(i), hashes[i]
+ number, hash = header.Number.Uint64(), header.Hash()
break
}
}
@@ -990,12 +996,28 @@ func (d *Downloader) findAncestor(p *peer) (uint64, error) {
// Make sure the peer actually gave something valid
headers := packet.(*headerPack).headers
if len(headers) == 0 {
- glog.V(logger.Debug).Infof("%v: empty head header set", p)
+ glog.V(logger.Warn).Infof("%v: empty head header set", p)
return 0, errEmptyHeaderSet
}
+ // Make sure the peer's reply conforms to the request
+ for i := 0; i < len(headers); i++ {
+ if number := headers[i].Number.Int64(); number != from+int64(i) {
+ glog.V(logger.Warn).Infof("%v: head header set (item %d) broke chain ordering: requested %d, got %d", p, i, from+int64(i), number)
+ return 0, errInvalidChain
+ }
+ if i > 0 && headers[i-1].Hash() != headers[i].ParentHash {
+ glog.V(logger.Warn).Infof("%v: head header set (item %d) broke chain ancestry: expected [%x], got [%x]", p, i, headers[i-1].Hash().Bytes()[:4], headers[i].ParentHash[:4])
+ return 0, errInvalidChain
+ }
+ }
// Check if a common ancestor was found
finished = true
for i := len(headers) - 1; i >= 0; i-- {
+ // Skip any headers that underflow/overflow our requested set
+ if headers[i].Number.Int64() < from || headers[i].Number.Uint64() > head {
+ continue
+ }
+ // Otherwise check if we already know the header or not
if (d.mode != LightSync && d.hasBlockAndState(headers[i].Hash())) || (d.mode == LightSync && d.hasHeader(headers[i].Hash())) {
number, hash = headers[i].Number.Uint64(), headers[i].Hash()
break
@@ -1206,6 +1228,10 @@ func (d *Downloader) fetchHeaders(p *peer, td *big.Int, from uint64) error {
frequency = 1
}
if n, err := d.insertHeaders(headers, frequency); err != nil {
+ // If some headers were inserted, add them too to the rollback list
+ if n > 0 {
+ rollback = append(rollback, headers[:n]...)
+ }
glog.V(logger.Debug).Infof("%v: invalid header #%d [%x…]: %v", p, headers[n].Number, headers[n].Hash().Bytes()[:4], err)
return errInvalidChain
}