@@ -213,7 +213,7 @@ func New(stateDb ethdb.Database, mux *event.TypeMux, chain BlockChain, lightchai
213
213
dl := & Downloader {
214
214
stateDB : stateDb ,
215
215
mux : mux ,
216
- queue : newQueue (),
216
+ queue : newQueue (blockCacheItems ),
217
217
peers : newPeerSet (),
218
218
rttEstimate : uint64 (rttMaxEstimate ),
219
219
rttConfidence : uint64 (1000000 ),
@@ -359,7 +359,7 @@ func (d *Downloader) synchronise(id string, hash common.Hash, td *big.Int, mode
359
359
log .Info ("Block synchronisation started" )
360
360
}
361
361
// Reset the queue, peer set and wake channels to clean any internal leftover state
362
- d .queue .Reset ()
362
+ d .queue .Reset (blockCacheItems )
363
363
d .peers .Reset ()
364
364
365
365
for _ , ch := range []chan bool {d .bodyWakeCh , d .receiptWakeCh } {
@@ -575,7 +575,7 @@ func (d *Downloader) fetchHeight(p *peerConnection, hash common.Hash) (*types.He
575
575
// Make sure the peer actually gave something valid
576
576
headers := packet .(* headerPack ).headers
577
577
if len (headers ) != 1 {
578
- p .log .Debug ("Multiple headers for single request" , "headers" , len (headers ))
578
+ p .log .Warn ("Multiple headers for single request" , "headers" , len (headers ))
579
579
return nil , fmt .Errorf ("%w: multiple headers (%d) for single request" , errBadPeer , len (headers ))
580
580
}
581
581
head := headers [0 ]
@@ -784,7 +784,7 @@ func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header)
784
784
// Make sure the peer actually gave something valid
785
785
headers := packer .(* headerPack ).headers
786
786
if len (headers ) != 1 {
787
- p .log .Debug ("Multiple headers for single request" , "headers" , len (headers ))
787
+ p .log .Warn ("Multiple headers for single request" , "headers" , len (headers ))
788
788
return 0 , fmt .Errorf ("%w: multiple headers (%d) for single request" , errBadPeer , len (headers ))
789
789
}
790
790
arrived = true
@@ -808,7 +808,7 @@ func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header)
808
808
}
809
809
header := d .lightchain .GetHeaderByHash (h ) // Independent of sync mode, header surely exists
810
810
if header .Number .Uint64 () != check {
811
- p .log .Debug ("Received non requested header" , "number" , header .Number , "hash" , header .Hash (), "request" , check )
811
+ p .log .Warn ("Received non requested header" , "number" , header .Number , "hash" , header .Hash (), "request" , check )
812
812
return 0 , fmt .Errorf ("%w: non-requested header (%d)" , errBadPeer , header .Number )
813
813
}
814
814
start = check
@@ -1017,17 +1017,18 @@ func (d *Downloader) fillHeaderSkeleton(from uint64, skeleton []*types.Header) (
1017
1017
pack := packet .(* headerPack )
1018
1018
return d .queue .DeliverHeaders (pack .peerId , pack .headers , d .headerProcCh )
1019
1019
}
1020
- expire = func () map [string ]int { return d .queue .ExpireHeaders (d .requestTTL ()) }
1021
- throttle = func () bool { return false }
1022
- reserve = func (p * peerConnection , count int ) (* fetchRequest , bool , error ) {
1023
- return d .queue .ReserveHeaders (p , count ), false , nil
1020
+ expire = func () map [string ]int { return d .queue .ExpireHeaders (d .requestTTL ()) }
1021
+ reserve = func (p * peerConnection , count int ) (* fetchRequest , bool , bool ) {
1022
+ return d .queue .ReserveHeaders (p , count ), false , false
1024
1023
}
1025
1024
fetch = func (p * peerConnection , req * fetchRequest ) error { return p .FetchHeaders (req .From , MaxHeaderFetch ) }
1026
1025
capacity = func (p * peerConnection ) int { return p .HeaderCapacity (d .requestRTT ()) }
1027
- setIdle = func (p * peerConnection , accepted int ) { p .SetHeadersIdle (accepted ) }
1026
+ setIdle = func (p * peerConnection , accepted int , deliveryTime time.Time ) {
1027
+ p .SetHeadersIdle (accepted , deliveryTime )
1028
+ }
1028
1029
)
1029
1030
err := d .fetchParts (d .headerCh , deliver , d .queue .headerContCh , expire ,
1030
- d .queue .PendingHeaders , d .queue .InFlightHeaders , throttle , reserve ,
1031
+ d .queue .PendingHeaders , d .queue .InFlightHeaders , reserve ,
1031
1032
nil , fetch , d .queue .CancelHeaders , capacity , d .peers .HeaderIdlePeers , setIdle , "headers" )
1032
1033
1033
1034
log .Debug ("Skeleton fill terminated" , "err" , err )
@@ -1050,10 +1051,10 @@ func (d *Downloader) fetchBodies(from uint64) error {
1050
1051
expire = func () map [string ]int { return d .queue .ExpireBodies (d .requestTTL ()) }
1051
1052
fetch = func (p * peerConnection , req * fetchRequest ) error { return p .FetchBodies (req ) }
1052
1053
capacity = func (p * peerConnection ) int { return p .BlockCapacity (d .requestRTT ()) }
1053
- setIdle = func (p * peerConnection , accepted int ) { p .SetBodiesIdle (accepted ) }
1054
+ setIdle = func (p * peerConnection , accepted int , deliveryTime time. Time ) { p .SetBodiesIdle (accepted , deliveryTime ) }
1054
1055
)
1055
1056
err := d .fetchParts (d .bodyCh , deliver , d .bodyWakeCh , expire ,
1056
- d .queue .PendingBlocks , d .queue .InFlightBlocks , d .queue .ShouldThrottleBlocks , d . queue . ReserveBodies ,
1057
+ d .queue .PendingBlocks , d .queue .InFlightBlocks , d .queue .ReserveBodies ,
1057
1058
d .bodyFetchHook , fetch , d .queue .CancelBodies , capacity , d .peers .BodyIdlePeers , setIdle , "bodies" )
1058
1059
1059
1060
log .Debug ("Block body download terminated" , "err" , err )
@@ -1074,10 +1075,12 @@ func (d *Downloader) fetchReceipts(from uint64) error {
1074
1075
expire = func () map [string ]int { return d .queue .ExpireReceipts (d .requestTTL ()) }
1075
1076
fetch = func (p * peerConnection , req * fetchRequest ) error { return p .FetchReceipts (req ) }
1076
1077
capacity = func (p * peerConnection ) int { return p .ReceiptCapacity (d .requestRTT ()) }
1077
- setIdle = func (p * peerConnection , accepted int ) { p .SetReceiptsIdle (accepted ) }
1078
+ setIdle = func (p * peerConnection , accepted int , deliveryTime time.Time ) {
1079
+ p .SetReceiptsIdle (accepted , deliveryTime )
1080
+ }
1078
1081
)
1079
1082
err := d .fetchParts (d .receiptCh , deliver , d .receiptWakeCh , expire ,
1080
- d .queue .PendingReceipts , d .queue .InFlightReceipts , d .queue .ShouldThrottleReceipts , d . queue . ReserveReceipts ,
1083
+ d .queue .PendingReceipts , d .queue .InFlightReceipts , d .queue .ReserveReceipts ,
1081
1084
d .receiptFetchHook , fetch , d .queue .CancelReceipts , capacity , d .peers .ReceiptIdlePeers , setIdle , "receipts" )
1082
1085
1083
1086
log .Debug ("Transaction receipt download terminated" , "err" , err )
@@ -1110,9 +1113,9 @@ func (d *Downloader) fetchReceipts(from uint64) error {
1110
1113
// - setIdle: network callback to set a peer back to idle and update its estimated capacity (traffic shaping)
1111
1114
// - kind: textual label of the type being downloaded to display in log mesages
1112
1115
func (d * Downloader ) fetchParts (deliveryCh chan dataPack , deliver func (dataPack ) (int , error ), wakeCh chan bool ,
1113
- expire func () map [string ]int , pending func () int , inFlight func () bool , throttle func () bool , reserve func (* peerConnection , int ) (* fetchRequest , bool , error ),
1116
+ expire func () map [string ]int , pending func () int , inFlight func () bool , reserve func (* peerConnection , int ) (* fetchRequest , bool , bool ),
1114
1117
fetchHook func ([]* types.Header ), fetch func (* peerConnection , * fetchRequest ) error , cancel func (* fetchRequest ), capacity func (* peerConnection ) int ,
1115
- idle func () ([]* peerConnection , int ), setIdle func (* peerConnection , int ), kind string ) error {
1118
+ idle func () ([]* peerConnection , int ), setIdle func (* peerConnection , int , time. Time ), kind string ) error {
1116
1119
1117
1120
// Create a ticker to detect expired retrieval tasks
1118
1121
ticker := time .NewTicker (100 * time .Millisecond )
@@ -1128,6 +1131,7 @@ func (d *Downloader) fetchParts(deliveryCh chan dataPack, deliver func(dataPack)
1128
1131
return errCanceled
1129
1132
1130
1133
case packet := <- deliveryCh :
1134
+ deliveryTime := time .Now ()
1131
1135
// If the peer was previously banned and failed to deliver its pack
1132
1136
// in a reasonable time frame, ignore its message.
1133
1137
if peer := d .peers .Peer (packet .PeerId ()); peer != nil {
@@ -1140,7 +1144,7 @@ func (d *Downloader) fetchParts(deliveryCh chan dataPack, deliver func(dataPack)
1140
1144
// caused by a timed out request which came through in the end), set it to
1141
1145
// idle. If the delivery's stale, the peer should have already been idled.
1142
1146
if ! errors .Is (err , errStaleDelivery ) {
1143
- setIdle (peer , accepted )
1147
+ setIdle (peer , accepted , deliveryTime )
1144
1148
}
1145
1149
// Issue a log to the user to see what's going on
1146
1150
switch {
@@ -1193,7 +1197,7 @@ func (d *Downloader) fetchParts(deliveryCh chan dataPack, deliver func(dataPack)
1193
1197
// how response times reacts, to it always requests one more than the minimum (i.e. min 2).
1194
1198
if fails > 2 {
1195
1199
peer .log .Trace ("Data delivery timed out" , "type" , kind )
1196
- setIdle (peer , 0 )
1200
+ setIdle (peer , 0 , time . Now () )
1197
1201
} else {
1198
1202
peer .log .Debug ("Stalling delivery, dropping" , "type" , kind )
1199
1203
@@ -1228,27 +1232,27 @@ func (d *Downloader) fetchParts(deliveryCh chan dataPack, deliver func(dataPack)
1228
1232
// Send a download request to all idle peers, until throttled
1229
1233
progressed , throttled , running := false , false , inFlight ()
1230
1234
idles , total := idle ()
1231
-
1235
+ pendCount := pending ()
1232
1236
for _ , peer := range idles {
1233
1237
// Short circuit if throttling activated
1234
- if throttle () {
1235
- throttled = true
1238
+ if throttled {
1236
1239
break
1237
1240
}
1238
1241
// Short circuit if there is no more available task.
1239
- if pending () == 0 {
1242
+ if pendCount = pending (); pendCount == 0 {
1240
1243
break
1241
1244
}
1242
1245
// Reserve a chunk of fetches for a peer. A nil can mean either that
1243
1246
// no more headers are available, or that the peer is known not to
1244
1247
// have them.
1245
- request , progress , err := reserve (peer , capacity (peer ))
1246
- if err != nil {
1247
- return err
1248
- }
1248
+ request , progress , throttle := reserve (peer , capacity (peer ))
1249
1249
if progress {
1250
1250
progressed = true
1251
1251
}
1252
+ if throttle {
1253
+ throttled = true
1254
+ throttleCounter .Inc (1 )
1255
+ }
1252
1256
if request == nil {
1253
1257
continue
1254
1258
}
@@ -1273,7 +1277,7 @@ func (d *Downloader) fetchParts(deliveryCh chan dataPack, deliver func(dataPack)
1273
1277
}
1274
1278
// Make sure that we have peers available for fetching. If all peers have been tried
1275
1279
// and all failed throw an error
1276
- if ! progressed && ! throttled && ! running && len (idles ) == total && pending () > 0 {
1280
+ if ! progressed && ! throttled && ! running && len (idles ) == total && pendCount > 0 {
1277
1281
return errPeersUnavailable
1278
1282
}
1279
1283
}
@@ -1285,8 +1289,11 @@ func (d *Downloader) fetchParts(deliveryCh chan dataPack, deliver func(dataPack)
1285
1289
// queue until the stream ends or a failure occurs.
1286
1290
func (d * Downloader ) processHeaders (origin uint64 , pivot uint64 , td * big.Int ) error {
1287
1291
// Keep a count of uncertain headers to roll back
1288
- rollback := []* types.Header {}
1289
- mode := d .getMode ()
1292
+ var (
1293
+ rollback []* types.Header
1294
+ rollbackErr error
1295
+ mode = d .getMode ()
1296
+ )
1290
1297
defer func () {
1291
1298
if len (rollback ) > 0 {
1292
1299
// Flatten the headers and roll them back
@@ -1308,7 +1315,7 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er
1308
1315
log .Warn ("Rolled back headers" , "count" , len (hashes ),
1309
1316
"header" , fmt .Sprintf ("%d->%d" , lastHeader , d .lightchain .CurrentHeader ().Number ),
1310
1317
"fast" , fmt .Sprintf ("%d->%d" , lastFastBlock , curFastBlock ),
1311
- "block" , fmt .Sprintf ("%d->%d" , lastBlock , curBlock ))
1318
+ "block" , fmt .Sprintf ("%d->%d" , lastBlock , curBlock ), "reason" , rollbackErr )
1312
1319
}
1313
1320
}()
1314
1321
@@ -1318,6 +1325,7 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er
1318
1325
for {
1319
1326
select {
1320
1327
case <- d .cancelCh :
1328
+ rollbackErr = errCanceled
1321
1329
return errCanceled
1322
1330
1323
1331
case headers := <- d .headerProcCh :
@@ -1371,6 +1379,7 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er
1371
1379
// Terminate if something failed in between processing chunks
1372
1380
select {
1373
1381
case <- d .cancelCh :
1382
+ rollbackErr = errCanceled
1374
1383
return errCanceled
1375
1384
default :
1376
1385
}
@@ -1395,11 +1404,12 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er
1395
1404
frequency = 1
1396
1405
}
1397
1406
if n , err := d .lightchain .InsertHeaderChain (chunk , frequency ); err != nil {
1407
+ rollbackErr = err
1398
1408
// If some headers were inserted, add them too to the rollback list
1399
1409
if n > 0 {
1400
1410
rollback = append (rollback , chunk [:n ]... )
1401
1411
}
1402
- log .Debug ("Invalid header encountered" , "number" , chunk [n ].Number , "hash" , chunk [n ].Hash (), "err" , err )
1412
+ log .Debug ("Invalid header encountered" , "number" , chunk [n ].Number , "hash" , chunk [n ].Hash (), "parent" , chunk [ n ]. ParentHash , " err" , err )
1403
1413
return fmt .Errorf ("%w: %v" , errInvalidChain , err )
1404
1414
}
1405
1415
// All verifications passed, store newly found uncertain headers
@@ -1414,14 +1424,15 @@ func (d *Downloader) processHeaders(origin uint64, pivot uint64, td *big.Int) er
1414
1424
for d .queue .PendingBlocks () >= maxQueuedHeaders || d .queue .PendingReceipts () >= maxQueuedHeaders {
1415
1425
select {
1416
1426
case <- d .cancelCh :
1427
+ rollbackErr = errCanceled
1417
1428
return errCanceled
1418
1429
case <- time .After (time .Second ):
1419
1430
}
1420
1431
}
1421
1432
// Otherwise insert the headers for content retrieval
1422
1433
inserts := d .queue .Schedule (chunk , origin )
1423
1434
if len (inserts ) != len (chunk ) {
1424
- log . Debug ( "Stale headers" )
1435
+ rollbackErr = fmt . Errorf ( "stale headers: len inserts %v len(chunk) %v" , len ( inserts ), len ( chunk ) )
1425
1436
return fmt .Errorf ("%w: stale headers" , errBadPeer )
1426
1437
}
1427
1438
}
@@ -1638,6 +1649,14 @@ func (d *Downloader) processFastSyncContent(latest *types.Header) error {
1638
1649
}
1639
1650
1640
1651
func splitAroundPivot (pivot uint64 , results []* fetchResult ) (p * fetchResult , before , after []* fetchResult ) {
1652
+ if len (results ) == 0 {
1653
+ return nil , nil , nil
1654
+ }
1655
+ if lastNum := results [len (results )- 1 ].Header .Number .Uint64 (); lastNum < pivot {
1656
+ // the pivot is somewhere in the future
1657
+ return nil , results , nil
1658
+ }
1659
+ // This can also be optimized, but only happens very seldom
1641
1660
for _ , result := range results {
1642
1661
num := result .Header .Number .Uint64 ()
1643
1662
switch {
0 commit comments