@@ -219,7 +219,7 @@ func New(checkpoint uint64, stateDb ethdb.Database, stateBloom *trie.SyncBloom,
219
219
stateBloom : stateBloom ,
220
220
mux : mux ,
221
221
checkpoint : checkpoint ,
222
- queue : newQueue (),
222
+ queue : newQueue (blockCacheItems ),
223
223
peers : newPeerSet (),
224
224
rttEstimate : uint64 (rttMaxEstimate ),
225
225
rttConfidence : uint64 (1000000 ),
@@ -370,7 +370,7 @@ func (d *Downloader) synchronise(id string, hash common.Hash, td *big.Int, mode
370
370
d .stateBloom .Close ()
371
371
}
372
372
// Reset the queue, peer set and wake channels to clean any internal leftover state
373
- d .queue .Reset ()
373
+ d .queue .Reset (blockCacheItems )
374
374
d .peers .Reset ()
375
375
376
376
for _ , ch := range []chan bool {d .bodyWakeCh , d .receiptWakeCh } {
@@ -597,8 +597,10 @@ func (d *Downloader) Terminate() {
597
597
default :
598
598
close (d .quitCh )
599
599
}
600
+ if d .stateBloom != nil {
601
+ d .stateBloom .Close ()
602
+ }
600
603
d .quitLock .Unlock ()
601
-
602
604
// Cancel any pending download requests
603
605
d .Cancel ()
604
606
}
@@ -629,7 +631,7 @@ func (d *Downloader) fetchHeight(p *peerConnection) (*types.Header, error) {
629
631
// Make sure the peer actually gave something valid
630
632
headers := packet .(* headerPack ).headers
631
633
if len (headers ) != 1 {
632
- p .log .Debug ("Multiple headers for single request" , "headers" , len (headers ))
634
+ p .log .Warn ("Multiple headers for single request" , "headers" , len (headers ))
633
635
return nil , fmt .Errorf ("%w: multiple headers (%d) for single request" , errBadPeer , len (headers ))
634
636
}
635
637
head := headers [0 ]
@@ -866,7 +868,7 @@ func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header)
866
868
// Make sure the peer actually gave something valid
867
869
headers := packer .(* headerPack ).headers
868
870
if len (headers ) != 1 {
869
- p .log .Debug ("Multiple headers for single request" , "headers" , len (headers ))
871
+ p .log .Warn ("Multiple headers for single request" , "headers" , len (headers ))
870
872
return 0 , fmt .Errorf ("%w: multiple headers (%d) for single request" , errBadPeer , len (headers ))
871
873
}
872
874
arrived = true
@@ -890,7 +892,7 @@ func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header)
890
892
}
891
893
header := d .lightchain .GetHeaderByHash (h ) // Independent of sync mode, header surely exists
892
894
if header .Number .Uint64 () != check {
893
- p .log .Debug ("Received non requested header" , "number" , header .Number , "hash" , header .Hash (), "request" , check )
895
+ p .log .Warn ("Received non requested header" , "number" , header .Number , "hash" , header .Hash (), "request" , check )
894
896
return 0 , fmt .Errorf ("%w: non-requested header (%d)" , errBadPeer , header .Number )
895
897
}
896
898
start = check
@@ -1106,17 +1108,18 @@ func (d *Downloader) fillHeaderSkeleton(from uint64, skeleton []*types.Header) (
1106
1108
pack := packet .(* headerPack )
1107
1109
return d .queue .DeliverHeaders (pack .peerID , pack .headers , d .headerProcCh )
1108
1110
}
1109
- expire = func () map [string ]int { return d .queue .ExpireHeaders (d .requestTTL ()) }
1110
- throttle = func () bool { return false }
1111
- reserve = func (p * peerConnection , count int ) (* fetchRequest , bool , error ) {
1112
- return d .queue .ReserveHeaders (p , count ), false , nil
1111
+ expire = func () map [string ]int { return d .queue .ExpireHeaders (d .requestTTL ()) }
1112
+ reserve = func (p * peerConnection , count int ) (* fetchRequest , bool , bool ) {
1113
+ return d .queue .ReserveHeaders (p , count ), false , false
1113
1114
}
1114
1115
fetch = func (p * peerConnection , req * fetchRequest ) error { return p .FetchHeaders (req .From , MaxHeaderFetch ) }
1115
1116
capacity = func (p * peerConnection ) int { return p .HeaderCapacity (d .requestRTT ()) }
1116
- setIdle = func (p * peerConnection , accepted int ) { p .SetHeadersIdle (accepted ) }
1117
+ setIdle = func (p * peerConnection , accepted int , deliveryTime time.Time ) {
1118
+ p .SetHeadersIdle (accepted , deliveryTime )
1119
+ }
1117
1120
)
1118
1121
err := d .fetchParts (d .headerCh , deliver , d .queue .headerContCh , expire ,
1119
- d .queue .PendingHeaders , d .queue .InFlightHeaders , throttle , reserve ,
1122
+ d .queue .PendingHeaders , d .queue .InFlightHeaders , reserve ,
1120
1123
nil , fetch , d .queue .CancelHeaders , capacity , d .peers .HeaderIdlePeers , setIdle , "headers" )
1121
1124
1122
1125
log .Debug ("Skeleton fill terminated" , "err" , err )
@@ -1139,10 +1142,10 @@ func (d *Downloader) fetchBodies(from uint64) error {
1139
1142
expire = func () map [string ]int { return d .queue .ExpireBodies (d .requestTTL ()) }
1140
1143
fetch = func (p * peerConnection , req * fetchRequest ) error { return p .FetchBodies (req ) }
1141
1144
capacity = func (p * peerConnection ) int { return p .BlockCapacity (d .requestRTT ()) }
1142
- setIdle = func (p * peerConnection , accepted int ) { p .SetBodiesIdle (accepted ) }
1145
+ setIdle = func (p * peerConnection , accepted int , deliveryTime time. Time ) { p .SetBodiesIdle (accepted , deliveryTime ) }
1143
1146
)
1144
1147
err := d .fetchParts (d .bodyCh , deliver , d .bodyWakeCh , expire ,
1145
- d .queue .PendingBlocks , d .queue .InFlightBlocks , d .queue .ShouldThrottleBlocks , d . queue . ReserveBodies ,
1148
+ d .queue .PendingBlocks , d .queue .InFlightBlocks , d .queue .ReserveBodies ,
1146
1149
d .bodyFetchHook , fetch , d .queue .CancelBodies , capacity , d .peers .BodyIdlePeers , setIdle , "bodies" )
1147
1150
1148
1151
log .Debug ("Block body download terminated" , "err" , err )
@@ -1163,10 +1166,12 @@ func (d *Downloader) fetchReceipts(from uint64) error {
1163
1166
expire = func () map [string ]int { return d .queue .ExpireReceipts (d .requestTTL ()) }
1164
1167
fetch = func (p * peerConnection , req * fetchRequest ) error { return p .FetchReceipts (req ) }
1165
1168
capacity = func (p * peerConnection ) int { return p .ReceiptCapacity (d .requestRTT ()) }
1166
- setIdle = func (p * peerConnection , accepted int ) { p .SetReceiptsIdle (accepted ) }
1169
+ setIdle = func (p * peerConnection , accepted int , deliveryTime time.Time ) {
1170
+ p .SetReceiptsIdle (accepted , deliveryTime )
1171
+ }
1167
1172
)
1168
1173
err := d .fetchParts (d .receiptCh , deliver , d .receiptWakeCh , expire ,
1169
- d .queue .PendingReceipts , d .queue .InFlightReceipts , d .queue .ShouldThrottleReceipts , d . queue . ReserveReceipts ,
1174
+ d .queue .PendingReceipts , d .queue .InFlightReceipts , d .queue .ReserveReceipts ,
1170
1175
d .receiptFetchHook , fetch , d .queue .CancelReceipts , capacity , d .peers .ReceiptIdlePeers , setIdle , "receipts" )
1171
1176
1172
1177
log .Debug ("Transaction receipt download terminated" , "err" , err )
@@ -1199,14 +1204,13 @@ func (d *Downloader) fetchReceipts(from uint64) error {
1199
1204
// - setIdle: network callback to set a peer back to idle and update its estimated capacity (traffic shaping)
1200
1205
// - kind: textual label of the type being downloaded to display in log messages
1201
1206
func (d * Downloader ) fetchParts (deliveryCh chan dataPack , deliver func (dataPack ) (int , error ), wakeCh chan bool ,
1202
- expire func () map [string ]int , pending func () int , inFlight func () bool , throttle func () bool , reserve func (* peerConnection , int ) (* fetchRequest , bool , error ),
1207
+ expire func () map [string ]int , pending func () int , inFlight func () bool , reserve func (* peerConnection , int ) (* fetchRequest , bool , bool ),
1203
1208
fetchHook func ([]* types.Header ), fetch func (* peerConnection , * fetchRequest ) error , cancel func (* fetchRequest ), capacity func (* peerConnection ) int ,
1204
- idle func () ([]* peerConnection , int ), setIdle func (* peerConnection , int ), kind string ) error {
1209
+ idle func () ([]* peerConnection , int ), setIdle func (* peerConnection , int , time. Time ), kind string ) error {
1205
1210
1206
1211
// Create a ticker to detect expired retrieval tasks
1207
1212
ticker := time .NewTicker (100 * time .Millisecond )
1208
1213
defer ticker .Stop ()
1209
-
1210
1214
update := make (chan struct {}, 1 )
1211
1215
1212
1216
// Prepare the queue and fetch block parts until the block header fetcher's done
@@ -1217,6 +1221,7 @@ func (d *Downloader) fetchParts(deliveryCh chan dataPack, deliver func(dataPack)
1217
1221
return errCanceled
1218
1222
1219
1223
case packet := <- deliveryCh :
1224
+ deliveryTime := time .Now ()
1220
1225
// If the peer was previously banned and failed to deliver its pack
1221
1226
// in a reasonable time frame, ignore its message.
1222
1227
if peer := d .peers .Peer (packet .PeerId ()); peer != nil {
@@ -1229,7 +1234,7 @@ func (d *Downloader) fetchParts(deliveryCh chan dataPack, deliver func(dataPack)
1229
1234
// caused by a timed out request which came through in the end), set it to
1230
1235
// idle. If the delivery's stale, the peer should have already been idled.
1231
1236
if ! errors .Is (err , errStaleDelivery ) {
1232
- setIdle (peer , accepted )
1237
+ setIdle (peer , accepted , deliveryTime )
1233
1238
}
1234
1239
// Issue a log to the user to see what's going on
1235
1240
switch {
@@ -1282,7 +1287,7 @@ func (d *Downloader) fetchParts(deliveryCh chan dataPack, deliver func(dataPack)
1282
1287
// how response times reacts, to it always requests one more than the minimum (i.e. min 2).
1283
1288
if fails > 2 {
1284
1289
peer .log .Trace ("Data delivery timed out" , "type" , kind )
1285
- setIdle (peer , 0 )
1290
+ setIdle (peer , 0 , time . Now () )
1286
1291
} else {
1287
1292
peer .log .Debug ("Stalling delivery, dropping" , "type" , kind )
1288
1293
@@ -1317,27 +1322,27 @@ func (d *Downloader) fetchParts(deliveryCh chan dataPack, deliver func(dataPack)
1317
1322
// Send a download request to all idle peers, until throttled
1318
1323
progressed , throttled , running := false , false , inFlight ()
1319
1324
idles , total := idle ()
1320
-
1325
+ pendCount := pending ()
1321
1326
for _ , peer := range idles {
1322
1327
// Short circuit if throttling activated
1323
- if throttle () {
1324
- throttled = true
1328
+ if throttled {
1325
1329
break
1326
1330
}
1327
1331
// Short circuit if there is no more available task.
1328
- if pending () == 0 {
1332
+ if pendCount = pending (); pendCount == 0 {
1329
1333
break
1330
1334
}
1331
1335
// Reserve a chunk of fetches for a peer. A nil can mean either that
1332
1336
// no more headers are available, or that the peer is known not to
1333
1337
// have them.
1334
- request , progress , err := reserve (peer , capacity (peer ))
1335
- if err != nil {
1336
- return err
1337
- }
1338
+ request , progress , throttle := reserve (peer , capacity (peer ))
1338
1339
if progress {
1339
1340
progressed = true
1340
1341
}
1342
+ if throttle {
1343
+ throttled = true
1344
+ throttleCounter .Inc (1 )
1345
+ }
1341
1346
if request == nil {
1342
1347
continue
1343
1348
}
@@ -1362,7 +1367,7 @@ func (d *Downloader) fetchParts(deliveryCh chan dataPack, deliver func(dataPack)
1362
1367
}
1363
1368
// Make sure that we have peers available for fetching. If all peers have been tried
1364
1369
// and all failed throw an error
1365
- if ! progressed && ! throttled && ! running && len (idles ) == total && pending () > 0 {
1370
+ if ! progressed && ! throttled && ! running && len (idles ) == total && pendCount > 0 {
1366
1371
return errPeersUnavailable
1367
1372
}
1368
1373
}
@@ -1374,8 +1379,11 @@ func (d *Downloader) fetchParts(deliveryCh chan dataPack, deliver func(dataPack)
1374
1379
// queue until the stream ends or a failure occurs.
1375
1380
func (d * Downloader ) processHeaders (origin uint64 , pivot uint64 , td * big.Int ) error {
1376
1381
// Keep a count of uncertain headers to roll back
1377
- var rollback []* types.Header
1378
- mode := d .getMode ()
1382
+ var (
1383
+ rollback []* types.Header
1384
+ rollbackErr error
1385
+ mode = d .getMode ()
1386
+ )
1379
1387
defer func () {
1380
1388
if len (rollback ) > 0 {
1381
1389
// Flatten the headers and roll them back
@@ -1397,7 +1405,7 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er
1397
1405
log .Warn ("Rolled back headers" , "count" , len (hashes ),
1398
1406
"header" , fmt .Sprintf ("%d->%d" , lastHeader , d .lightchain .CurrentHeader ().Number ),
1399
1407
"fast" , fmt .Sprintf ("%d->%d" , lastFastBlock , curFastBlock ),
1400
- "block" , fmt .Sprintf ("%d->%d" , lastBlock , curBlock ))
1408
+ "block" , fmt .Sprintf ("%d->%d" , lastBlock , curBlock ), "reason" , rollbackErr )
1401
1409
}
1402
1410
}()
1403
1411
@@ -1407,6 +1415,7 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er
1407
1415
for {
1408
1416
select {
1409
1417
case <- d .cancelCh :
1418
+ rollbackErr = errCanceled
1410
1419
return errCanceled
1411
1420
1412
1421
case headers := <- d .headerProcCh :
@@ -1460,6 +1469,7 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er
1460
1469
// Terminate if something failed in between processing chunks
1461
1470
select {
1462
1471
case <- d .cancelCh :
1472
+ rollbackErr = errCanceled
1463
1473
return errCanceled
1464
1474
default :
1465
1475
}
@@ -1484,11 +1494,12 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er
1484
1494
frequency = 1
1485
1495
}
1486
1496
if n , err := d .lightchain .InsertHeaderChain (chunk , frequency ); err != nil {
1497
+ rollbackErr = err
1487
1498
// If some headers were inserted, add them too to the rollback list
1488
1499
if n > 0 {
1489
1500
rollback = append (rollback , chunk [:n ]... )
1490
1501
}
1491
- log .Debug ("Invalid header encountered" , "number" , chunk [n ].Number , "hash" , chunk [n ].Hash (), "err" , err )
1502
+ log .Debug ("Invalid header encountered" , "number" , chunk [n ].Number , "hash" , chunk [n ].Hash (), "parent" , chunk [ n ]. ParentHash , " err" , err )
1492
1503
return fmt .Errorf ("%w: %v" , errInvalidChain , err )
1493
1504
}
1494
1505
// All verifications passed, store newly found uncertain headers
@@ -1503,14 +1514,15 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er
1503
1514
for d .queue .PendingBlocks () >= maxQueuedHeaders || d .queue .PendingReceipts () >= maxQueuedHeaders {
1504
1515
select {
1505
1516
case <- d .cancelCh :
1517
+ rollbackErr = errCanceled
1506
1518
return errCanceled
1507
1519
case <- time .After (time .Second ):
1508
1520
}
1509
1521
}
1510
1522
// Otherwise insert the headers for content retrieval
1511
1523
inserts := d .queue .Schedule (chunk , origin )
1512
1524
if len (inserts ) != len (chunk ) {
1513
- log . Debug ( "Stale headers" )
1525
+ rollbackErr = fmt . Errorf ( "stale headers: len inserts %v len(chunk) %v" , len ( inserts ), len ( chunk ) )
1514
1526
return fmt .Errorf ("%w: stale headers" , errBadPeer )
1515
1527
}
1516
1528
}
@@ -1680,6 +1692,14 @@ func (d *Downloader) processFastSyncContent(latest *types.Header) error {
1680
1692
}
1681
1693
1682
1694
func splitAroundPivot (pivot uint64 , results []* fetchResult ) (p * fetchResult , before , after []* fetchResult ) {
1695
+ if len (results ) == 0 {
1696
+ return nil , nil , nil
1697
+ }
1698
+ if lastNum := results [len (results )- 1 ].Header .Number .Uint64 (); lastNum < pivot {
1699
+ // the pivot is somewhere in the future
1700
+ return nil , results , nil
1701
+ }
1702
+ // This can also be optimized, but only happens very seldom
1683
1703
for _ , result := range results {
1684
1704
num := result .Header .Number .Uint64 ()
1685
1705
switch {
0 commit comments