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