upleb.uk

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

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gui.cpp10
-rw-r--r--src/main.cpp8
-rw-r--r--src/net.cpp61
-rw-r--r--src/net.h42
4 files changed, 119 insertions, 2 deletions
diff --git a/src/gui.cpp b/src/gui.cpp
index 825202b..28f5ffa 100644
--- a/src/gui.cpp
+++ b/src/gui.cpp
@@ -26,6 +26,7 @@ extern CAddress addrLocalHost;
26 26
27void MainFrameRepaint(); 27void MainFrameRepaint();
28int GetDiscoveredPeerCount(); 28int GetDiscoveredPeerCount();
29int GetPeerMedianHeight();
29string DateTimeStr(int64 nTime); 30string DateTimeStr(int64 nTime);
30bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew); 31bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew);
31int64 GetBalance(); 32int64 GetBalance();
@@ -238,6 +239,15 @@ static void DrawStatusBar()
238 connected, discovered, nBestHeight); 239 connected, discovered, nBestHeight);
239 } 240 }
240 241
242 // A node that has stopped receiving looks exactly like one with nothing to
243 // do. Now that peers announce their height, say the difference out loud
244 // instead of leaving the user to guess from a number that stopped moving.
245 int peerHeight = GetPeerMedianHeight();
246 if (peerHeight >= 0 && nBestHeight < peerHeight - 1)
247 ImGui::TextColored(ImVec4(0.95f, 0.65f, 0.20f, 1.0f),
248 "Behind the network by %d block(s) -- peers report height %d",
249 peerHeight - nBestHeight, peerHeight);
250
241 ImGui::End(); 251 ImGui::End();
242} 252}
243 253
diff --git a/src/main.cpp b/src/main.cpp
index c77448d..15805ca 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1884,6 +1884,12 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
1884 if (pfrom->nVersion == 0) 1884 if (pfrom->nVersion == 0)
1885 return false; 1885 return false;
1886 1886
1887 // Optional: peers older than this field simply end the message here,
1888 // and nStartingHeight stays -1 for them. Never make this a requirement
1889 // -- every node released so far sends the short form.
1890 if (!vRecv.empty())
1891 vRecv >> pfrom->nStartingHeight;
1892
1887 pfrom->vSend.SetVersion(min(pfrom->nVersion, VERSION)); 1893 pfrom->vSend.SetVersion(min(pfrom->nVersion, VERSION));
1888 pfrom->vRecv.SetVersion(min(pfrom->nVersion, VERSION)); 1894 pfrom->vRecv.SetVersion(min(pfrom->nVersion, VERSION));
1889 1895
@@ -1912,7 +1918,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
1912 if (!vPexOut.empty()) 1918 if (!vPexOut.empty())
1913 pfrom->PushMessage("btfpeers", vPexOut); 1919 pfrom->PushMessage("btfpeers", vPexOut);
1914 1920
1915 if (LogAcceptsCategory("net")) printf("version addrMe = %s\n", addrMe.ToString().c_str()); 1921 if (LogAcceptsCategory("net")) printf("version addrMe = %s, peer height = %d\n", addrMe.ToString().c_str(), pfrom->nStartingHeight);
1916 } 1922 }
1917 1923
1918 1924
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);
diff --git a/src/net.h b/src/net.h
index 449cff5..831a880 100644
--- a/src/net.h
+++ b/src/net.h
@@ -69,6 +69,21 @@ static const int BTF_HANDSHAKE_GRACE_SECS = 60;
69// stay well under BTF_RECV_TIMEOUT_SECS. 69// stay well under BTF_RECV_TIMEOUT_SECS.
70static const int BTF_PING_INTERVAL_SECS = 10 * 60; 70static const int BTF_PING_INTERVAL_SECS = 10 * 60;
71 71
72// How long a node must stay behind the network before it says so, and how
73// often it repeats itself. Five minutes is two and a half block intervals --
74// long enough that ordinary relay lag never trips it.
75static const int BTF_BEHIND_GRACE_SECS = 5 * 60;
76static const int BTF_BEHIND_WARN_INTERVAL_SECS = 5 * 60;
77
78// Defined in main.cpp. Declared here because CNode announces it in the version
79// message, and net.h is included before main.h.
80extern int nBestHeight;
81
82// Median height announced by the peers we are connected to, or -1 while nobody
83// has told us anything. Median rather than maximum so one peer claiming an
84// absurd height cannot move it.
85int GetPeerMedianHeight();
86
72// Descriptors to hand a peer: ours first, then peers that answered us. 87// Descriptors to hand a peer: ours first, then peers that answered us.
73void BtfPexCollect(std::vector<std::string>& vDescOut); 88void BtfPexCollect(std::vector<std::string>& vDescOut);
74// Verify descriptors a peer sent and remember the good ones. Returns how many. 89// Verify descriptors a peer sent and remember the good ones. Returns how many.
@@ -528,6 +543,11 @@ public:
528 int64 nLastRecv; 543 int64 nLastRecv;
529 int64 nLastSendEmpty; 544 int64 nLastSendEmpty;
530 545
546 // Height this peer announced in its version message, or -1 if it sent a
547 // version message that predates the field. Knowing how far along everyone
548 // else is, is the only way a node can tell "in sync" from "not hearing".
549 int nStartingHeight;
550
531 551
532 CNode(SOCKET hSocketIn, CAddress addrIn, bool fInboundIn=false) 552 CNode(SOCKET hSocketIn, CAddress addrIn, bool fInboundIn=false)
533 { 553 {
@@ -549,12 +569,16 @@ public:
549 nLastSend = 0; 569 nLastSend = 0;
550 nLastRecv = 0; 570 nLastRecv = 0;
551 nLastSendEmpty = GetTime(); 571 nLastSendEmpty = GetTime();
572 nStartingHeight = -1;
552 vfSubscribe.assign(256, false); 573 vfSubscribe.assign(256, false);
553 574
554 // Push a version message 575 // Push a version message
555 /// when NTP implemented, change to just nTime = GetAdjustedTime() 576 /// when NTP implemented, change to just nTime = GetAdjustedTime()
556 int64 nTime = (fInbound ? GetAdjustedTime() : GetTime()); 577 int64 nTime = (fInbound ? GetAdjustedTime() : GetTime());
557 PushMessage("version", VERSION, nLocalServices, nTime, addr); 578 // nBestHeight goes last so a node that predates it stops reading after
579 // addr and treats the rest as trailing bytes, which cost it a log line
580 // and nothing else.
581 PushMessage("version", VERSION, nLocalServices, nTime, addr, nBestHeight);
558 } 582 }
559 583
560 ~CNode() 584 ~CNode()
@@ -771,6 +795,22 @@ public:
771 } 795 }
772 } 796 }
773 797
798 template<typename T1, typename T2, typename T3, typename T4, typename T5>
799 void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5)
800 {
801 try
802 {
803 BeginMessage(pszCommand);
804 vSend << a1 << a2 << a3 << a4 << a5;
805 EndMessage();
806 }
807 catch (...)
808 {
809 AbortMessage();
810 throw;
811 }
812 }
813
774 814
775 void PushRequest(const char* pszCommand, 815 void PushRequest(const char* pszCommand,
776 void (*fn)(void*, CDataStream&), void* param1) 816 void (*fn)(void*, CDataStream&), void* param1)