upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/net.cpp
diff options
context:
space:
mode:
authorBitflash <btf01@proton.me>2026-07-30 18:22:51 -0300
committerGitHub <noreply@github.com>2026-07-30 18:22:51 -0300
commit86f080cc6deb0464edf3913daa2e1131b5eed7c7 (patch)
tree058f6aa96501191a76cd35ee1a5e7831ca3227ba /src/net.cpp
parent773440fcc7752b85d99ee5b8500b64dbb5869603 (diff)
net: announce our height in the handshake, and say when we are behind (#56)
A node running this code cannot tell "in sync with everyone" from "not hearing anyone". The version message carries no height -- 0.1.0 never had the field and this fork inherited the gap -- so the only evidence of a problem is a number on screen that stopped moving, which looks the same as a network with nothing to report. It is the structural reason a broken node here has always been indistinguishable from an idle one. Append nBestHeight to the version message and keep what a peer announced in CNode::nStartingHeight. The field goes last, so a node that predates it stops reading after addr and treats the rest as trailing bytes, which cost it one log line. Reading it is guarded by vRecv.empty() and never required: peers that do not send it keep nStartingHeight at -1 and are left out of the median. Every release so far sends the short form. GetPeerMedianHeight() takes the median rather than the maximum so a single peer claiming an absurd height cannot move it. Then use it. After five minutes more than one block behind the peer median, the node says so in the log -- not behind a debug category, because an operator who already enabled -debug is not the one who needs telling -- and the GUI carries the same sentence in its status area. "8 blocks behind for 27 minutes" is something a user can act on; a frozen counter is not. Verified against two nodes on the live network: the one starting from an empty datadir read its peer at 3797, reported 2636 then 1274 then 433 blocks behind as it caught up, and went quiet on its own once level. The other logged "peer height = -1" for the older nodes it met on the real network, which is the compatibility path doing its job. Known limit: nStartingHeight is a snapshot from handshake time and goes stale on a long-lived connection, so this catches a node that is receiving something but not blocks, not one that has gone completely deaf. The inactivity timeout from #55 covers that case and refreshes these heights when it forces the reconnect.
Diffstat (limited to 'src/net.cpp')
-rw-r--r--src/net.cpp61
1 files changed, 61 insertions, 0 deletions
diff --git a/src/net.cpp b/src/net.cpp
index 81932d7..ac8df82 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -1225,6 +1225,65 @@ void ThreadMessageHandler(void* parg)
1225 } 1225 }
1226} 1226}
1227 1227
1228int GetPeerMedianHeight()
1229{
1230 vector<int> vHeights;
1231 CRITICAL_BLOCK(cs_vNodes)
1232 foreach(CNode* pnode, vNodes)
1233 if (pnode->nStartingHeight >= 0)
1234 vHeights.push_back(pnode->nStartingHeight);
1235
1236 if (vHeights.empty())
1237 return -1;
1238
1239 sort(vHeights.begin(), vHeights.end());
1240 return vHeights[vHeights.size() / 2];
1241}
1242
1243
1244// Say out loud when we are behind the network.
1245//
1246// This is the whole reason the height is in the handshake. Every serious bug
1247// this node has had looked identical from the outside: running, threads alive,
1248// nothing in the log, and no blocks arriving. A node that knows where everyone
1249// else is can say so, and "8 blocks behind for 27 minutes" is a sentence a
1250// user can act on. Deliberately not behind a debug category -- an operator who
1251// already suspects trouble is not the one who needs telling.
1252static void WarnIfBehind()
1253{
1254 static int64 nLastWarned;
1255 static int64 nBehindSince;
1256
1257 int nPeers = GetPeerMedianHeight();
1258 if (nPeers < 0 || nBestHeight < 0)
1259 return;
1260
1261 // One block of slack: somebody is always mid-relay.
1262 if (nBestHeight >= nPeers - 1)
1263 {
1264 nBehindSince = 0;
1265 return;
1266 }
1267
1268 int64 nNow = GetTime();
1269 if (nBehindSince == 0)
1270 {
1271 nBehindSince = nNow;
1272 return;
1273 }
1274
1275 // Falling briefly behind is ordinary. Staying behind is not.
1276 if (nNow - nBehindSince < BTF_BEHIND_GRACE_SECS)
1277 return;
1278 if (nNow - nLastWarned < BTF_BEHIND_WARN_INTERVAL_SECS)
1279 return;
1280
1281 nLastWarned = nNow;
1282 printf("WARNING: %d blocks behind the network (height %d, peers report %d) for %d minutes\n",
1283 nPeers - nBestHeight, nBestHeight, nPeers, (int)((nNow - nBehindSince) / 60));
1284}
1285
1286
1228void ThreadMessageHandler2(void* parg) 1287void ThreadMessageHandler2(void* parg)
1229{ 1288{
1230 printf("ThreadMessageHandler started\n"); 1289 printf("ThreadMessageHandler started\n");
@@ -1250,6 +1309,8 @@ void ThreadMessageHandler2(void* parg)
1250 pnode->Release(); 1309 pnode->Release();
1251 } 1310 }
1252 1311
1312 WarnIfBehind();
1313
1253 // Wait and allow messages to bunch up 1314 // Wait and allow messages to bunch up
1254 vfThreadRunning[2] = false; 1315 vfThreadRunning[2] = false;
1255 Sleep(100); 1316 Sleep(100);