@@ -219,12 +219,11 @@ type SyncManager struct {
219
219
headersBuildMode bool
220
220
221
221
// The following fields are used for headers-first mode.
222
- headersFirstMode bool
223
- headerList * list.List
224
- startHeader * list.Element
225
- nextCheckpoint * chaincfg.Checkpoint
226
- utreexoHeaders map [chainhash.Hash ]* wire.MsgUtreexoHeader
227
- requestedUtreexoHeaders map [chainhash.Hash ]struct {}
222
+ headersFirstMode bool
223
+ headerList * list.List
224
+ startHeader * list.Element
225
+ nextCheckpoint * chaincfg.Checkpoint
226
+ utreexoHeaders map [chainhash.Hash ]* wire.MsgUtreexoHeader
228
227
229
228
// An optional fee estimator.
230
229
feeEstimator * mempool.FeeEstimator
@@ -366,7 +365,6 @@ func (sm *SyncManager) startSync() {
366
365
// during headersFirstMode.
367
366
if ! sm .headersFirstMode {
368
367
sm .requestedBlocks = make (map [chainhash.Hash ]struct {})
369
- sm .requestedUtreexoHeaders = make (map [chainhash.Hash ]struct {})
370
368
}
371
369
372
370
log .Infof ("Syncing to block height %d from peer %v" ,
@@ -396,11 +394,11 @@ func (sm *SyncManager) startSync() {
396
394
// should have all the previous headers as well.
397
395
_ , have := sm .utreexoHeaders [* node .hash ]
398
396
if ! have {
399
- sm .fetchUtreexoHeaders ()
397
+ sm .fetchUtreexoHeaders (nil )
400
398
return
401
399
}
402
400
}
403
- sm .fetchHeaderBlocks ()
401
+ sm .fetchHeaderBlocks (nil )
404
402
return
405
403
}
406
404
@@ -414,11 +412,11 @@ func (sm *SyncManager) startSync() {
414
412
// should have all the previous headers as well.
415
413
_ , have := sm .utreexoHeaders [* node .hash ]
416
414
if ! have {
417
- sm .fetchUtreexoHeaders ()
415
+ sm .fetchUtreexoHeaders (nil )
418
416
return
419
417
}
420
418
}
421
- sm .fetchHeaderBlocks ()
419
+ sm .fetchHeaderBlocks (nil )
422
420
return
423
421
}
424
422
@@ -693,12 +691,6 @@ func (sm *SyncManager) clearRequestedState(state *peerSyncState) {
693
691
for blockHash := range state .requestedBlocks {
694
692
delete (sm .requestedBlocks , blockHash )
695
693
}
696
-
697
- // Also remove requested utreexo headers from the global map so
698
- // that they will be fetched from elsewhere next time we get an inv.
699
- for blockHash := range state .requestedUtreexoHeaders {
700
- delete (sm .requestedUtreexoHeaders , blockHash )
701
- }
702
694
}
703
695
}
704
696
@@ -1030,7 +1022,7 @@ func (sm *SyncManager) handleBlockMsg(bmsg *blockMsg) {
1030
1022
if bmsg .block .Height () < lastHeight {
1031
1023
if sm .startHeader != nil &&
1032
1024
len (state .requestedBlocks ) < minInFlightBlocks {
1033
- sm .fetchHeaderBlocks ()
1025
+ sm .fetchHeaderBlocks (nil )
1034
1026
}
1035
1027
return
1036
1028
}
@@ -1050,7 +1042,7 @@ func (sm *SyncManager) handleBlockMsg(bmsg *blockMsg) {
1050
1042
if ! isCheckpointBlock {
1051
1043
if sm .startHeader != nil &&
1052
1044
len (state .requestedBlocks ) < minInFlightBlocks {
1053
- sm .fetchHeaderBlocks ()
1045
+ sm .fetchHeaderBlocks (nil )
1054
1046
}
1055
1047
return
1056
1048
}
@@ -1090,16 +1082,23 @@ func (sm *SyncManager) handleBlockMsg(bmsg *blockMsg) {
1090
1082
1091
1083
// fetchUtreexoHeaders creates and sends a request to the syncPeer for the next
1092
1084
// list of utreexo headers to be downloaded based on the current list of headers.
1093
- func (sm * SyncManager ) fetchUtreexoHeaders () {
1085
+ // Will fetch from the peer if it's not nil. Otherwise it'll default to the syncPeer.
1086
+ func (sm * SyncManager ) fetchUtreexoHeaders (peer * peerpkg.Peer ) {
1094
1087
// Nothing to do if there is no start header.
1095
1088
if sm .startHeader == nil {
1096
1089
log .Warnf ("fetchUtreexoHeaders called with no start header" )
1097
1090
return
1098
1091
}
1099
1092
1100
- state , exists := sm .peerStates [sm .syncPeer ]
1093
+ // Default to the syncPeer unless we're given a peer by the caller.
1094
+ reqPeer := sm .syncPeer
1095
+ if reqPeer == nil {
1096
+ reqPeer = peer
1097
+ }
1098
+
1099
+ state , exists := sm .peerStates [reqPeer ]
1101
1100
if ! exists {
1102
- log .Warnf ("Don't have peer state for sync peer %s" , sm . syncPeer .String ())
1101
+ log .Warnf ("Don't have peer state for request peer %s" , reqPeer .String ())
1103
1102
return
1104
1103
}
1105
1104
@@ -1115,7 +1114,7 @@ func (sm *SyncManager) fetchUtreexoHeaders() {
1115
1114
if ! requested && ! have {
1116
1115
state .requestedUtreexoHeaders [* node .hash ] = struct {}{}
1117
1116
ghmsg := wire .NewMsgGetUtreexoHeader (* node .hash )
1118
- sm . syncPeer .QueueMessage (ghmsg , nil )
1117
+ reqPeer .QueueMessage (ghmsg , nil )
1119
1118
}
1120
1119
1121
1120
if len (state .requestedUtreexoHeaders ) > minInFlightBlocks {
@@ -1126,13 +1125,20 @@ func (sm *SyncManager) fetchUtreexoHeaders() {
1126
1125
1127
1126
// fetchHeaderBlocks creates and sends a request to the syncPeer for the next
1128
1127
// list of blocks to be downloaded based on the current list of headers.
1129
- func (sm * SyncManager ) fetchHeaderBlocks () {
1128
+ // Will fetch from the peer if it's not nil. Otherwise it'll default to the syncPeer.
1129
+ func (sm * SyncManager ) fetchHeaderBlocks (peer * peerpkg.Peer ) {
1130
1130
// Nothing to do if there is no start header.
1131
1131
if sm .startHeader == nil {
1132
1132
log .Warnf ("fetchHeaderBlocks called with no start header" )
1133
1133
return
1134
1134
}
1135
1135
1136
+ // Default to the syncPeer unless we're given a peer by the caller.
1137
+ reqPeer := sm .syncPeer
1138
+ if reqPeer == nil {
1139
+ reqPeer = peer
1140
+ }
1141
+
1136
1142
// Build up a getdata request for the list of blocks the headers
1137
1143
// describe. The size hint will be limited to wire.MaxInvPerMsg by
1138
1144
// the function, so no need to double check it here.
@@ -1153,24 +1159,24 @@ func (sm *SyncManager) fetchHeaderBlocks() {
1153
1159
"fetch: %v" , err )
1154
1160
}
1155
1161
if ! haveInv {
1156
- syncPeerState := sm .peerStates [sm . syncPeer ]
1162
+ syncPeerState := sm .peerStates [reqPeer ]
1157
1163
syncPeerState .requestedBlocks [* node .hash ] = struct {}{}
1158
1164
1159
1165
// If we're fetching from a witness enabled peer
1160
1166
// post-fork, then ensure that we receive all the
1161
1167
// witness data in the blocks.
1162
- if sm . syncPeer .IsWitnessEnabled () {
1168
+ if reqPeer .IsWitnessEnabled () {
1163
1169
iv .Type = wire .InvTypeWitnessBlock
1164
1170
1165
1171
// If we're syncing from a utreexo enabled peer, also
1166
1172
// ask for the proofs.
1167
- if sm . syncPeer .IsUtreexoEnabled () {
1173
+ if reqPeer .IsUtreexoEnabled () {
1168
1174
iv .Type = wire .InvTypeWitnessUtreexoBlock
1169
1175
}
1170
1176
} else {
1171
1177
// If we're syncing from a utreexo enabled peer, also
1172
1178
// ask for the proofs.
1173
- if sm . syncPeer .IsUtreexoEnabled () {
1179
+ if reqPeer .IsUtreexoEnabled () {
1174
1180
iv .Type = wire .InvTypeUtreexoBlock
1175
1181
}
1176
1182
}
@@ -1184,7 +1190,7 @@ func (sm *SyncManager) fetchHeaderBlocks() {
1184
1190
}
1185
1191
}
1186
1192
if len (gdmsg .InvList ) > 0 {
1187
- sm . syncPeer .QueueMessage (gdmsg , nil )
1193
+ reqPeer .QueueMessage (gdmsg , nil )
1188
1194
}
1189
1195
}
1190
1196
@@ -1198,21 +1204,79 @@ func (sm *SyncManager) handleHeadersMsg(hmsg *headersMsg) {
1198
1204
return
1199
1205
}
1200
1206
1201
- // The remote peer is misbehaving if we didn't request headers.
1202
1207
msg := hmsg .headers
1203
1208
numHeaders := len (msg .Headers )
1204
- if ! sm .headersFirstMode && ! sm .headersBuildMode {
1205
- log .Warnf ("Got %d unrequested headers from %s -- " +
1206
- "disconnecting" , numHeaders , peer .Addr ())
1207
- peer .Disconnect ()
1208
- return
1209
- }
1210
1209
1211
1210
// Nothing to do for an empty headers message.
1212
1211
if numHeaders == 0 {
1213
1212
return
1214
1213
}
1215
1214
1215
+ utreexoViewActive := sm .chain .IsUtreexoViewActive ()
1216
+
1217
+ // If we're not in headers first, it means that these headers are for new
1218
+ // block announcements.
1219
+ if ! sm .headersFirstMode && ! sm .headersBuildMode {
1220
+ best := sm .chain .BestSnapshot ()
1221
+ sm .headerList .Init ()
1222
+ sm .resetHeaderState (& best .Hash , best .Height )
1223
+
1224
+ for _ , blockHeader := range msg .Headers {
1225
+ err := sm .chain .ProcessBlockHeader (blockHeader )
1226
+ if err != nil {
1227
+ log .Warnf ("Received block header from peer %v " +
1228
+ "failed header verification -- disconnecting" ,
1229
+ peer .Addr ())
1230
+ peer .Disconnect ()
1231
+ return
1232
+ }
1233
+
1234
+ prevNodeEl := sm .headerList .Back ()
1235
+ if prevNodeEl == nil {
1236
+ log .Warnf ("Header list does not contain a previous" +
1237
+ "element as expected -- disconnecting peer" )
1238
+ peer .Disconnect ()
1239
+ return
1240
+ }
1241
+
1242
+ prevNode := prevNodeEl .Value .(* headerNode )
1243
+ blockHash := blockHeader .BlockHash ()
1244
+ node := headerNode {hash : & blockHash }
1245
+ if prevNode .hash .IsEqual (& blockHeader .PrevBlock ) {
1246
+ node .height = prevNode .height + 1
1247
+ e := sm .headerList .PushBack (& node )
1248
+ if sm .startHeader == nil {
1249
+ sm .startHeader = e
1250
+ }
1251
+ } else {
1252
+ log .Warnf ("Received block header that does not " +
1253
+ "properly connect to the chain from peer %s " +
1254
+ "-- disconnecting" , peer .Addr ())
1255
+ peer .Disconnect ()
1256
+ return
1257
+ }
1258
+ }
1259
+
1260
+ // Since the first entry of the list is always the final block
1261
+ // that is already in the database and is only used to ensure
1262
+ // the next header links properly, it must be removed before
1263
+ // fetching the headers or the utreexo headers.
1264
+ sm .headerList .Remove (sm .headerList .Front ())
1265
+ sm .progressLogger .SetLastLogTime (time .Now ())
1266
+
1267
+ if utreexoViewActive {
1268
+ log .Infof ("Received %v block headers: Fetching utreexo headers" ,
1269
+ sm .headerList .Len ())
1270
+ sm .fetchUtreexoHeaders (hmsg .peer )
1271
+ } else {
1272
+ log .Infof ("Received %v block headers: Fetching blocks" ,
1273
+ sm .headerList .Len ())
1274
+ sm .fetchHeaderBlocks (hmsg .peer )
1275
+ }
1276
+
1277
+ return
1278
+ }
1279
+
1216
1280
if sm .headersBuildMode {
1217
1281
var finalHeader * wire.BlockHeader
1218
1282
var finalHeight int32
@@ -1294,8 +1358,6 @@ func (sm *SyncManager) handleHeadersMsg(hmsg *headersMsg) {
1294
1358
return
1295
1359
}
1296
1360
1297
- utreexoViewActive := sm .chain .IsUtreexoViewActive ()
1298
-
1299
1361
// This means that we've ran out of checkpoints and need to verify the headers that
1300
1362
// we've received.
1301
1363
if sm .nextCheckpoint == nil {
@@ -1359,11 +1421,11 @@ func (sm *SyncManager) handleHeadersMsg(hmsg *headersMsg) {
1359
1421
if utreexoViewActive {
1360
1422
log .Infof ("Received %v block headers: Fetching utreexo headers" ,
1361
1423
sm .headerList .Len ())
1362
- sm .fetchUtreexoHeaders ()
1424
+ sm .fetchUtreexoHeaders (nil )
1363
1425
} else {
1364
1426
log .Infof ("Received %v block headers: Fetching blocks" ,
1365
1427
sm .headerList .Len ())
1366
- sm .fetchHeaderBlocks ()
1428
+ sm .fetchHeaderBlocks (nil )
1367
1429
}
1368
1430
}
1369
1431
@@ -1438,7 +1500,7 @@ func (sm *SyncManager) handleHeadersMsg(hmsg *headersMsg) {
1438
1500
log .Infof ("Received %v block headers: Fetching utreexo headers" ,
1439
1501
sm .headerList .Len ())
1440
1502
sm .progressLogger .SetLastLogTime (time .Now ())
1441
- sm .fetchUtreexoHeaders ()
1503
+ sm .fetchUtreexoHeaders (nil )
1442
1504
return
1443
1505
}
1444
1506
// Since the first entry of the list is always the final block
@@ -1449,7 +1511,7 @@ func (sm *SyncManager) handleHeadersMsg(hmsg *headersMsg) {
1449
1511
log .Infof ("Received %v block headers: Fetching blocks" ,
1450
1512
sm .headerList .Len ())
1451
1513
sm .progressLogger .SetLastLogTime (time .Now ())
1452
- sm .fetchHeaderBlocks ()
1514
+ sm .fetchHeaderBlocks (nil )
1453
1515
return
1454
1516
}
1455
1517
@@ -1510,20 +1572,20 @@ func (sm *SyncManager) handleUtreexoHeaderMsg(hmsg *utreexoHeaderMsg) {
1510
1572
log .Infof ("Received utreexo headers to block " +
1511
1573
"%d/hash %s. Fetching blocks" ,
1512
1574
node .height , node .hash )
1513
- sm .fetchHeaderBlocks ()
1575
+ sm .fetchHeaderBlocks (nil )
1514
1576
return
1515
1577
} else if node .height == peer .LastBlock () {
1516
1578
log .Infof ("Received utreexo headers to block " +
1517
1579
"%d/hash %s. Fetching blocks" ,
1518
1580
node .height , node .hash )
1519
- sm .fetchHeaderBlocks ()
1581
+ sm .fetchHeaderBlocks (nil )
1520
1582
return
1521
1583
}
1522
1584
}
1523
1585
}
1524
1586
1525
1587
if len (peerState .requestedUtreexoHeaders ) < minInFlightBlocks {
1526
- sm .fetchUtreexoHeaders ()
1588
+ sm .fetchUtreexoHeaders (nil )
1527
1589
}
1528
1590
1529
1591
return
@@ -1532,19 +1594,12 @@ func (sm *SyncManager) handleUtreexoHeaderMsg(hmsg *utreexoHeaderMsg) {
1532
1594
// We're not in headers-first mode. When we receive a utreexo header,
1533
1595
// immediately ask for the block.
1534
1596
sm .utreexoHeaders [msg .BlockHash ] = hmsg .header
1535
- delete (sm .requestedUtreexoHeaders , msg .BlockHash )
1597
+ delete (peerState .requestedUtreexoHeaders , msg .BlockHash )
1536
1598
log .Debugf ("accepted utreexo header for block %v. have %v headers" ,
1537
1599
msg .BlockHash , len (sm .utreexoHeaders ))
1538
1600
1539
- if ! sm .headersFirstMode {
1540
- sm .requestedBlocks [msg .BlockHash ] = struct {}{}
1541
- }
1542
1601
peerState .requestedBlocks [msg .BlockHash ] = struct {}{}
1543
-
1544
- gdmsg := wire .NewMsgGetData ()
1545
- iv := wire .NewInvVect (wire .InvTypeWitnessUtreexoBlock , & msg .BlockHash )
1546
- gdmsg .AddInvVect (iv )
1547
- peer .QueueMessage (gdmsg , nil )
1602
+ sm .fetchHeaderBlocks (peer )
1548
1603
}
1549
1604
1550
1605
// handleNotFoundMsg handles notfound messages from all peers.
@@ -1876,7 +1931,6 @@ func (sm *SyncManager) handleInvMsg(imsg *invMsg) {
1876
1931
if _ , exists := sm .requestedBlocks [iv .Hash ]; ! exists {
1877
1932
amUtreexoNode := sm .chain .IsUtreexoViewActive ()
1878
1933
if amUtreexoNode {
1879
- sm .requestedUtreexoHeaders [iv .Hash ] = struct {}{}
1880
1934
ghmsg := wire .NewMsgGetUtreexoHeader (iv .Hash )
1881
1935
peer .QueueMessage (ghmsg , nil )
1882
1936
continue
@@ -2362,21 +2416,20 @@ func (sm *SyncManager) Pause() chan<- struct{} {
2362
2416
// block, tx, and inv updates.
2363
2417
func New (config * Config ) (* SyncManager , error ) {
2364
2418
sm := SyncManager {
2365
- peerNotifier : config .PeerNotifier ,
2366
- chain : config .Chain ,
2367
- txMemPool : config .TxMemPool ,
2368
- chainParams : config .ChainParams ,
2369
- rejectedTxns : make (map [chainhash.Hash ]struct {}),
2370
- requestedTxns : make (map [chainhash.Hash ]struct {}),
2371
- requestedBlocks : make (map [chainhash.Hash ]struct {}),
2372
- requestedUtreexoHeaders : make (map [chainhash.Hash ]struct {}),
2373
- utreexoHeaders : make (map [chainhash.Hash ]* wire.MsgUtreexoHeader ),
2374
- peerStates : make (map [* peerpkg.Peer ]* peerSyncState ),
2375
- progressLogger : newBlockProgressLogger ("Processed" , log ),
2376
- msgChan : make (chan interface {}, config .MaxPeers * 3 ),
2377
- headerList : list .New (),
2378
- quit : make (chan struct {}),
2379
- feeEstimator : config .FeeEstimator ,
2419
+ peerNotifier : config .PeerNotifier ,
2420
+ chain : config .Chain ,
2421
+ txMemPool : config .TxMemPool ,
2422
+ chainParams : config .ChainParams ,
2423
+ rejectedTxns : make (map [chainhash.Hash ]struct {}),
2424
+ requestedTxns : make (map [chainhash.Hash ]struct {}),
2425
+ requestedBlocks : make (map [chainhash.Hash ]struct {}),
2426
+ utreexoHeaders : make (map [chainhash.Hash ]* wire.MsgUtreexoHeader ),
2427
+ peerStates : make (map [* peerpkg.Peer ]* peerSyncState ),
2428
+ progressLogger : newBlockProgressLogger ("Processed" , log ),
2429
+ msgChan : make (chan interface {}, config .MaxPeers * 3 ),
2430
+ headerList : list .New (),
2431
+ quit : make (chan struct {}),
2432
+ feeEstimator : config .FeeEstimator ,
2380
2433
}
2381
2434
2382
2435
best := sm .chain .BestSnapshot ()
0 commit comments