@@ -207,6 +207,10 @@ struct CNodeState {
207
207
std::string name;
208
208
// List of asynchronously-determined block rejections to notify this peer about.
209
209
std::vector<CBlockReject> rejects;
210
+ // The best known block we know this peer has announced.
211
+ CBlockIndex *pindexBestKnownBlock;
212
+ // The hash of the last unknown block this peer has announced.
213
+ uint256 hashLastUnknownBlock;
210
214
list<QueuedBlock> vBlocksInFlight;
211
215
int nBlocksInFlight;
212
216
list<uint256> vBlocksToDownload;
@@ -217,6 +221,8 @@ struct CNodeState {
217
221
CNodeState () {
218
222
nMisbehavior = 0 ;
219
223
fShouldBan = false ;
224
+ pindexBestKnownBlock = NULL ;
225
+ hashLastUnknownBlock = uint256 (0 );
220
226
nBlocksToDownload = 0 ;
221
227
nBlocksInFlight = 0 ;
222
228
nLastBlockReceive = 0 ;
@@ -313,6 +319,39 @@ void MarkBlockAsInFlight(NodeId nodeid, const uint256 &hash) {
313
319
mapBlocksInFlight[hash] = std::make_pair (nodeid, it);
314
320
}
315
321
322
+ /* * Check whether the last unknown block a peer advertized is not yet known. */
323
+ void ProcessBlockAvailability (NodeId nodeid) {
324
+ CNodeState *state = State (nodeid);
325
+ assert (state != NULL );
326
+
327
+ if (state->hashLastUnknownBlock != 0 ) {
328
+ map<uint256, CBlockIndex*>::iterator itOld = mapBlockIndex.find (state->hashLastUnknownBlock );
329
+ if (itOld != mapBlockIndex.end () && itOld->second ->nChainWork > 0 ) {
330
+ if (state->pindexBestKnownBlock == NULL || itOld->second ->nChainWork >= state->pindexBestKnownBlock ->nChainWork )
331
+ state->pindexBestKnownBlock = itOld->second ;
332
+ state->hashLastUnknownBlock = uint256 (0 );
333
+ }
334
+ }
335
+ }
336
+
337
+ /* * Update tracking information about which blocks a peer is assumed to have. */
338
+ void UpdateBlockAvailability (NodeId nodeid, const uint256 &hash) {
339
+ CNodeState *state = State (nodeid);
340
+ assert (state != NULL );
341
+
342
+ ProcessBlockAvailability (nodeid);
343
+
344
+ map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find (hash);
345
+ if (it != mapBlockIndex.end () && it->second ->nChainWork > 0 ) {
346
+ // An actually better block was announced.
347
+ if (state->pindexBestKnownBlock == NULL || it->second ->nChainWork >= state->pindexBestKnownBlock ->nChainWork )
348
+ state->pindexBestKnownBlock = it->second ;
349
+ } else {
350
+ // An unknown block was announced; just assume that the latest one is the best one.
351
+ state->hashLastUnknownBlock = hash;
352
+ }
353
+ }
354
+
316
355
} // anon namespace
317
356
318
357
bool GetNodeStateStats (NodeId nodeid, CNodeStateStats &stats) {
@@ -321,6 +360,7 @@ bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats) {
321
360
if (state == NULL )
322
361
return false ;
323
362
stats.nMisbehavior = state->nMisbehavior ;
363
+ stats.nSyncHeight = state->pindexBestKnownBlock ? state->pindexBestKnownBlock ->nHeight : -1 ;
324
364
return true ;
325
365
}
326
366
@@ -3613,6 +3653,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
3613
3653
PushGetBlocks (pfrom, chainActive.Tip (), GetOrphanRoot (inv.hash ));
3614
3654
}
3615
3655
3656
+ if (inv.type == MSG_BLOCK)
3657
+ UpdateBlockAvailability (pfrom->GetId (), inv.hash );
3658
+
3616
3659
// Track requests for our stuff
3617
3660
g_signals.Inventory (inv.hash );
3618
3661
}
@@ -4359,6 +4402,9 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
4359
4402
pto->fDisconnect = true ;
4360
4403
}
4361
4404
4405
+ // Update knowledge of peer's block availability.
4406
+ ProcessBlockAvailability (pto->GetId ());
4407
+
4362
4408
//
4363
4409
// Message: getdata (blocks)
4364
4410
//
0 commit comments