upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/net.h
diff options
context:
space:
mode:
authorbitflash-maintainer <noreply@bitflash.invalid>2026-09-04 05:59:40 +0000
committerbitflash-maintainer <noreply@bitflash.invalid>2026-09-04 05:59:40 +0000
commit152c859b18b222a7c11a82b5485110e902267d40 (patch)
tree1ceadf421609a2e58da81103165a2fb7085387de /src/net.h
parente4f898c4a6b9900553c64b9804889b5fdae3e55f (diff)
parentb810d86752ddb2674118f737582c924bb9eb74c1 (diff)
Merge branch 'deploy/all-2026-08-24' into 'deploy/soak-2026-08-21'
deploy: land MRs 1-12 and upstream 1.2.20, as shipped in relay component See merge request !13
Diffstat (limited to 'src/net.h')
-rw-r--r--src/net.h90
1 files changed, 83 insertions, 7 deletions
diff --git a/src/net.h b/src/net.h
index 9f3c7e4..752b1fe 100644
--- a/src/net.h
+++ b/src/net.h
@@ -23,6 +23,12 @@ enum
23 23
24 24
25 25
26// Defined in main.cpp. True while this node is tracking the tip rather than
27// still catching up, measured off the age of our own best block -- see there
28// for why that and not a peer-reported height. Declared here because net.h is
29// parsed before main.h and CNode::AskFor needs it.
30bool IsBlockFetchNearTip();
31
26bool GetMyExternalIP(unsigned int& ipRet); 32bool GetMyExternalIP(unsigned int& ipRet);
27CNode* ConnectNodeBtf(const string& strBtfAddr); 33CNode* ConnectNodeBtf(const string& strBtfAddr);
28CNode* ConnectNodeBtfResolved(const string& strBtfAddr, const string& strMeeting, 34CNode* ConnectNodeBtfResolved(const string& strBtfAddr, const string& strMeeting,
@@ -89,6 +95,15 @@ static const int BTF_RECV_TIMEOUT_SECS = 30 * 60;
89static const int BTF_SEND_STALL_SECS = 10 * 60; 95static const int BTF_SEND_STALL_SECS = 10 * 60;
90static const int BTF_HANDSHAKE_GRACE_SECS = 60; 96static const int BTF_HANDSHAKE_GRACE_SECS = 60;
91 97
98// How long a requested block gets before it is asked for again, in seconds.
99// Used twice: CNode::AskFor spaces the queued per-announcer block retries this
100// far apart instead of the two minutes transactions get, and the failover
101// sweep in main.cpp re-issues a getdata to a different peer once a sent
102// request has gone unanswered this long. A block body is at most 1 MB and
103// somebody demonstrably has it -- they announced it -- so on this timescale
104// "not here yet" means "not coming from that peer", not "still in transit".
105static const int BLOCK_FETCH_RETRY_SECS = 15;
106
92// A serialized object cannot be larger than MAX_SIZE, so no valid network 107// A serialized object cannot be larger than MAX_SIZE, so no valid network
93// message needs the old 256 MB header allowance. Keep the wire cap aligned with 108// message needs the old 256 MB header allowance. Keep the wire cap aligned with
94// what the deserializer can accept. How long a peer may sit on a partial 109// what the deserializer can accept. How long a peer may sit on a partial
@@ -109,6 +124,23 @@ static const unsigned int MAX_PROTOCOL_MESSAGE_SIZE = MAX_SIZE;
109// 125 is Bitcoin's number and remains a conservative public-node default. 124// 125 is Bitcoin's number and remains a conservative public-node default.
110static const unsigned int MAX_CONNECTIONS = 125; 125static const unsigned int MAX_CONNECTIONS = 125;
111 126
127// Cap inbound connections from any single address. Without it one source can
128// hold every slot up to MAX_CONNECTIONS -- exactly what happened to the
129// rendezvous relays, where a single IP parked hundreds of connections and
130// starved real peers. A legitimate peer, even a relay talking to a relay,
131// needs only a handful; 32 leaves generous room while denying any one address
132// more than a quarter of the table. The firewall connlimit on the relays does
133// the same thing a layer lower; this makes every build carry the defense.
134//
135// Loopback (127.0.0.0/8) is exempt in the accept path. A managed-Tor node
136// receives every inbound onion peer over its local hidden-service listener, so
137// they all appear as 127.0.0.1 -- capping loopback would cap onion peers as a
138// group, which is exactly wrong for a network moving toward onion-only. The
139// global MAX_CONNECTIONS still bounds the total; a per-onion-identity limit,
140// applied once identity is known after accept(), is the right future tool for
141// onion floods.
142static const unsigned int MAX_CONNECTIONS_PER_IP = 32;
143
112// A node marked for disconnect is normally held until its buffers drain, so 144// A node marked for disconnect is normally held until its buffers drain, so
113// a last message still goes out. But vSend cannot drain through a socket 145// a last message still goes out. But vSend cannot drain through a socket
114// whose far end is gone, and that made such a node immortal: it stayed in 146// whose far end is gone, and that made such a node immortal: it stayed in
@@ -795,13 +827,51 @@ public:
795 static int64 nLastTime; 827 static int64 nLastTime;
796 nLastTime = nNow = max(nNow, ++nLastTime); 828 nLastTime = nNow = max(nNow, ++nLastTime);
797 829
798 // Each retry is 2 minutes after the last 830 // Each retry is 2 minutes after the last -- and because nRequestTime
799 nRequestTime = max(nRequestTime + 2 * 60 * 1000000, nNow); 831 // is shared across peers, the same spacing is what strings requests
832 // for one inv across its announcers. For transactions that is pacing;
833 // for a new block it was the stall of issue #33: nine peers announce
834 // the block, the first one asked does not serve it, and the ninth
835 // candidate is not even asked until sixteen minutes in, with the pool
836 // mining on the stale tip the whole time.
837 //
838 // Blocks retry on the fetch timescale, but only while we are at the
839 // tip. That is where the stall costs something -- the pool keeps
840 // handing out jobs against a dead tip -- and it is also where the
841 // spacing is nearly free: one block is in flight, and its body has
842 // almost always arrived before the second announcer's turn comes
843 // round, so AlreadyHave drops the duplicate before a getdata is sent.
844 //
845 // While catching up neither half holds. A peer working through a
846 // 500-deep queue can be minutes away from block N without anything
847 // being wrong, so at 15s the second announcer is asked at +15s, the
848 // third at +30s, and the bulk download arrives once per announcer --
849 // up to eight times over. Nothing caps that: the eight-entry cap is on
850 // mapBlockFetch, which is a different mechanism from this spacing.
851 // Two minutes is the right number there, and it is what this line did
852 // before. Failover at the tip does not depend on this being 15s in any
853 // case: mapBlockFetch re-issues a stalled getdata to the next peer on
854 // its own timer, which is what actually fixes #33.
855 bool fFast = (inv.type == MSG_BLOCK && IsBlockFetchNearTip());
856 int64 nRetryUsecs = (fFast ? BLOCK_FETCH_RETRY_SECS : 2 * 60) * 1000000LL;
857 nRequestTime = max(nRequestTime + nRetryUsecs, nNow);
800 mapAskFor.insert(make_pair(nRequestTime, inv)); 858 mapAskFor.insert(make_pair(nRequestTime, inv));
801 } 859 }
802 860
803 861
804 862
863 // "sending: tx (N bytes)" alone was ~71% of a 13-hour production
864 // debug.log (issue #35), so tx sends are demoted to the /debugrelay-gated
865 // "relay" category; every other command's send trace stays on "net".
866 // The line is emitted in pieces across BeginMessage/EndMessage/
867 // AbortMessage, so all three must agree on the category or orphaned
868 // "(N bytes)" fragments would leak into a plain -debug log.
869 // Valid only mid-message (nPushPos != -1).
870 const char* SendLogCategory() const
871 {
872 return strcmp(GetMessageCommand(), "tx") == 0 ? "relay" : "net";
873 }
874
805 void BeginMessage(const char* pszCommand) 875 void BeginMessage(const char* pszCommand)
806 { 876 {
807 EnterCriticalSection(&cs_vSend); 877 EnterCriticalSection(&cs_vSend);
@@ -809,17 +879,19 @@ public:
809 AbortMessage(); 879 AbortMessage();
810 nPushPos = vSend.size(); 880 nPushPos = vSend.size();
811 vSend << CMessageHeader(pszCommand, 0); 881 vSend << CMessageHeader(pszCommand, 0);
812 if (LogAcceptsCategory("net")) printf("sending: %-12s ", pszCommand); 882 if (LogAcceptsCategory(SendLogCategory())) printf("sending: %-12s ", pszCommand);
813 } 883 }
814 884
815 void AbortMessage() 885 void AbortMessage()
816 { 886 {
817 if (nPushPos == -1) 887 if (nPushPos == -1)
818 return; 888 return;
889 // Capture before nPushPos is cleared; GetMessageCommand() needs it.
890 const char* pszCategory = SendLogCategory();
819 vSend.resize(nPushPos); 891 vSend.resize(nPushPos);
820 nPushPos = -1; 892 nPushPos = -1;
821 LeaveCriticalSection(&cs_vSend); 893 LeaveCriticalSection(&cs_vSend);
822 if (LogAcceptsCategory("net")) printf("(aborted)\n"); 894 if (LogAcceptsCategory(pszCategory)) printf("(aborted)\n");
823 } 895 }
824 896
825 void EndMessage() 897 void EndMessage()
@@ -827,7 +899,11 @@ public:
827 extern int nDropMessagesTest; 899 extern int nDropMessagesTest;
828 if (nDropMessagesTest > 0 && GetRand(nDropMessagesTest) == 0) 900 if (nDropMessagesTest > 0 && GetRand(nDropMessagesTest) == 0)
829 { 901 {
830 if (LogAcceptsCategory("net")) printf("dropmessages DROPPING SEND MESSAGE\n"); 902 // Same category as the "sending: " this line interrupts, so a tx
903 // does not announce its own drop under "net" having been gated
904 // off under "relay". nPushPos can be -1 here, and then
905 // GetMessageCommand() returns "" and this is "net" as before.
906 if (LogAcceptsCategory(SendLogCategory())) printf("dropmessages DROPPING SEND MESSAGE\n");
831 AbortMessage(); 907 AbortMessage();
832 return; 908 return;
833 } 909 }
@@ -839,10 +915,10 @@ public:
839 unsigned int nSize = vSend.size() - nPushPos - sizeof(CMessageHeader); 915 unsigned int nSize = vSend.size() - nPushPos - sizeof(CMessageHeader);
840 memcpy((char*)&vSend[nPushPos] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize)); 916 memcpy((char*)&vSend[nPushPos] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize));
841 917
842 if (LogAcceptsCategory("net")) printf("(%d bytes) ", nSize); 918 if (LogAcceptsCategory(SendLogCategory())) printf("(%d bytes) ", nSize);
843 //for (int i = nPushPos+sizeof(CMessageHeader); i < min(vSend.size(), nPushPos+sizeof(CMessageHeader)+20U); i++) 919 //for (int i = nPushPos+sizeof(CMessageHeader); i < min(vSend.size(), nPushPos+sizeof(CMessageHeader)+20U); i++)
844 // printf("%02x ", vSend[i] & 0xff); 920 // printf("%02x ", vSend[i] & 0xff);
845 if (LogAcceptsCategory("net")) printf("\n"); 921 if (LogAcceptsCategory(SendLogCategory())) printf("\n");
846 922
847 nPushPos = -1; 923 nPushPos = -1;
848 LeaveCriticalSection(&cs_vSend); 924 LeaveCriticalSection(&cs_vSend);