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-05 22:46:52 +0000
committerbitflash-maintainer <noreply@bitflash.invalid>2026-09-05 22:46:52 +0000
commitceae3d076b5ad11ee84729ae43f14e9312896646 (patch)
tree7e9132aa871fdc01cb95268d2f5ea3bb11853ddf /src/net.h
parentbe63e83d79e7e00e6b8ca889a70e6a19886aa1d8 (diff)
parent66e0b9158d050c46b1ff2509faeee3f4573cac1c (diff)
Bring main onto the line this project actually ships
main had drifted to a history with no ancestor in common with the tree we build and deploy. It sat at be63e83 (2026-08-09) with 28 commits; the shipped line, deploy/soak-2026-08-21, had 383. The two shared nothing -- git merge-base returns no result at all -- so anyone cloning this repository landed on a default branch that was neither current nor related to the running node. The 28 commits on main were audited before this merge: every one is already present in the tree by content, including the two that are hardest to see because they were rewritten afterwards -- the payout reorg-safety work (PayoutBlockStillOnChain, since evolved to re-check on every retry rather than once at maturity) and the nostr relay certificate verification (SSL_set1_host, now with a Windows root-store path). Nothing on main is lost by this merge. Recorded as a merge rather than a force-push: main only ever moves forward, its old history stays reachable as the first parent, and this is revertible. The tree is taken wholesale from the merged branch, so main's content is now exactly what was built and tested. What this brings onto main: - compactblock: BIP152-style compact block relay ported from upstream 1.2.23, primitives and unit test only, with the RAND_bytes failure path closed and the reconstruction allocation bounded. - upstream/main 17741d9: isolated testnet parameters and genesis, optional 2 MB large pages for RandomX. Mainnet genesis verified byte-identical through upstream's BuildGenesisBlock() refactor. - deploy: every image built on bookworm so binaries run on Debian 12, and the container build now honours the RandomX and libsecp256k1 pins it had been silently ignoring since before 1.2.15. Gates at this tree: 15/15 selftests, compactblock's 17 checks, consensus constants unchanged against e4f898c apart from the pre-existing MAX_BLOCK_SIZE_GEN, mainnet genesis intact, money-log check ok.
Diffstat (limited to 'src/net.h')
-rw-r--r--src/net.h150
1 files changed, 117 insertions, 33 deletions
diff --git a/src/net.h b/src/net.h
index 8b0245a..0988542 100644
--- a/src/net.h
+++ b/src/net.h
@@ -12,7 +12,13 @@ class CBlockIndex;
12 12
13 13
14 14
15static const unsigned short DEFAULT_PORT = htons(8433); 15// Held in host byte order, unlike the DEFAULT_PORT constant these replace,
16// which was htons(8433). Nothing is lost: net.cpp's GetDefaultPort() applies
17// htons() itself and is what every caller now uses, so the value that reaches
18// a sockaddr is byte-for-byte what it was. Mainnet stays on 8433.
19static const unsigned short MAINNET_PORT = 8433;
20static const unsigned short TESTNET_PORT = 18433;
21static const unsigned int PUBLISH_HOPS = 5;
16enum 22enum
17{ 23{
18 NODE_NETWORK = (1 << 0), 24 NODE_NETWORK = (1 << 0),
@@ -23,13 +29,24 @@ enum
23 29
24 30
25 31
32// Defined in main.cpp. True while this node is tracking the tip rather than
33// still catching up, measured off the age of our own best block -- see there
34// for why that and not a peer-reported height. Declared here because net.h is
35// parsed before main.h and CNode::AskFor needs it.
36bool IsBlockFetchNearTip();
37
26bool GetMyExternalIP(unsigned int& ipRet); 38bool GetMyExternalIP(unsigned int& ipRet);
39bool IsTestNet();
40unsigned short GetDefaultPort();
41void SelectNetworkParams(bool fTestNetIn);
27CNode* ConnectNodeBtf(const string& strBtfAddr); 42CNode* ConnectNodeBtf(const string& strBtfAddr);
28CNode* ConnectNodeBtfResolved(const string& strBtfAddr, const string& strMeeting, 43CNode* ConnectNodeBtfResolved(const string& strBtfAddr, const string& strMeeting,
29 const unsigned char enc_pub[32]); 44 const string& strOnion, const unsigned char enc_pub[32],
45 const string& strDesc=string());
30void ThreadBtfAccept(void* parg); 46void ThreadBtfAccept(void* parg);
31void ThreadBtfConnect(void* parg); 47void ThreadBtfConnect(void* parg);
32extern string strBtfConnect; 48extern string strBtfConnect;
49extern bool fBtfOnionOnly;
33// Bootstrap seeds added at runtime with /btfseed=ADDRESS:ENCHEX (repeatable). 50// Bootstrap seeds added at runtime with /btfseed=ADDRESS:ENCHEX (repeatable).
34// The compiled-in list lives in net.cpp; these are appended to it. 51// The compiled-in list lives in net.cpp; these are appended to it.
35extern std::vector<std::pair<std::string, std::string> > vBtfExtraSeeds; 52extern std::vector<std::pair<std::string, std::string> > vBtfExtraSeeds;
@@ -87,30 +104,52 @@ static const int BTF_RECV_TIMEOUT_SECS = 30 * 60;
87static const int BTF_SEND_STALL_SECS = 10 * 60; 104static const int BTF_SEND_STALL_SECS = 10 * 60;
88static const int BTF_HANDSHAKE_GRACE_SECS = 60; 105static const int BTF_HANDSHAKE_GRACE_SECS = 60;
89 106
107// How long a requested block gets before it is asked for again, in seconds.
108// Used twice: CNode::AskFor spaces the queued per-announcer block retries this
109// far apart instead of the two minutes transactions get, and the failover
110// sweep in main.cpp re-issues a getdata to a different peer once a sent
111// request has gone unanswered this long. A block body is at most 1 MB and
112// somebody demonstrably has it -- they announced it -- so on this timescale
113// "not here yet" means "not coming from that peer", not "still in transit".
114static const int BLOCK_FETCH_RETRY_SECS = 15;
115
90// A serialized object cannot be larger than MAX_SIZE, so no valid network 116// A serialized object cannot be larger than MAX_SIZE, so no valid network
91// message needs the old 256 MB header allowance. Keep the wire cap aligned with 117// message needs the old 256 MB header allowance. Keep the wire cap aligned with
92// what the deserializer can accept and bound how long one peer may sit on a 118// what the deserializer can accept. How long a peer may sit on a partial
93// partial payload after a complete header has arrived. 119// payload after a complete header has arrived is BTF_MSG_WAIT_MAX_SECS, below.
94static const unsigned int MAX_PROTOCOL_MESSAGE_SIZE = MAX_SIZE; 120static const unsigned int MAX_PROTOCOL_MESSAGE_SIZE = MAX_SIZE;
95static const int BTF_INCOMPLETE_MESSAGE_TIMEOUT_SECS = 2 * 60;
96 121
97// Ceiling on simultaneous connections. 122// Ceiling on simultaneous connections.
98// 123//
99// ThreadSocketHandler watches every peer through one select(), and select() 124// ThreadSocketHandler watches every peer in one socket loop. This used to be a
100// cannot watch more descriptors than FD_SETSIZE. On Windows FD_SET simply 125// select() loop, which made FD_SETSIZE the real limit and silently starved
101// stops adding once the set is full -- no error, no log -- so every socket 126// sockets past that bitmap. It is now poll()/WSAPoll(), so the ceiling below is
102// past the limit stays open and is never read again. Nothing capped vNodes, 127// a deliberate resource bound rather than a descriptor-set accident.
103// so a node accepted connections it had no way to service, and because new
104// entries go on the end of vNodes it was always the newest connection that
105// starved, including the ones dialed to fix connectivity.
106// 128//
107// Measured on two nodes before this ceiling existed: 277 and 90 CNode objects 129// Measured on two nodes before this ceiling existed: 277 and 90 CNode objects
108// against 93 and 90 live sockets, and a status bar reporting hundreds of 130// against 93 and 90 live sockets, and a status bar reporting hundreds of
109// peers for a node that was really talking to thirty. 131// peers for a node that was really talking to thirty.
110// 132//
111// 125 is Bitcoin's number and sits far below FD_SETSIZE on both platforms. 133// 125 is Bitcoin's number and remains a conservative public-node default.
112static const unsigned int MAX_CONNECTIONS = 125; 134static const unsigned int MAX_CONNECTIONS = 125;
113 135
136// Cap inbound connections from any single address. Without it one source can
137// hold every slot up to MAX_CONNECTIONS -- exactly what happened to the
138// rendezvous relays, where a single IP parked hundreds of connections and
139// starved real peers. A legitimate peer, even a relay talking to a relay,
140// needs only a handful; 32 leaves generous room while denying any one address
141// more than a quarter of the table. The firewall connlimit on the relays does
142// the same thing a layer lower; this makes every build carry the defense.
143//
144// Loopback (127.0.0.0/8) is exempt in the accept path. A managed-Tor node
145// receives every inbound onion peer over its local hidden-service listener, so
146// they all appear as 127.0.0.1 -- capping loopback would cap onion peers as a
147// group, which is exactly wrong for a network moving toward onion-only. The
148// global MAX_CONNECTIONS still bounds the total; a per-onion-identity limit,
149// applied once identity is known after accept(), is the right future tool for
150// onion floods.
151static const unsigned int MAX_CONNECTIONS_PER_IP = 32;
152
114// A node marked for disconnect is normally held until its buffers drain, so 153// A node marked for disconnect is normally held until its buffers drain, so
115// a last message still goes out. But vSend cannot drain through a socket 154// a last message still goes out. But vSend cannot drain through a socket
116// whose far end is gone, and that made such a node immortal: it stayed in 155// whose far end is gone, and that made such a node immortal: it stayed in
@@ -176,7 +215,7 @@ static const int BTF_BEHIND_WARN_INTERVAL_SECS = 5 * 60;
176// 215//
177// These counters exist so it can. Cheap to keep, and they name the failures 216// These counters exist so it can. Cheap to keep, and they name the failures
178// that actually happened rather than the ones that sound impressive. 217// that actually happened rather than the ones that sound impressive.
179extern int nPeersWatched; // peers in the last select() set 218extern int nPeersWatched; // peers in the last poll() set
180extern int64 nBlocksReceived; // blocks handed to ProcessBlock 219extern int64 nBlocksReceived; // blocks handed to ProcessBlock
181extern int64 nBlocksWithoutParent; // ...of those, how many arrived orphaned 220extern int64 nBlocksWithoutParent; // ...of those, how many arrived orphaned
182 221
@@ -236,15 +275,17 @@ void CheckForShutdown(int n);
236// The message start string is designed to be unlikely to occur in normal data. 275// The message start string is designed to be unlikely to occur in normal data.
237// The characters are rarely used upper ascii, not valid as UTF-8, and produce 276// The characters are rarely used upper ascii, not valid as UTF-8, and produce
238// a large 4-byte int at any alignment. 277// a large 4-byte int at any alignment.
239// Magic bytes unique to the Bitflash network (0xbf = "BF"). Second byte bumped 278// Magic bytes unique to the selected Bitflash network. Mainnet uses 0xbf =
240// to 0x20 for the 2026 stable relaunch so the old test chain can't interfere. 279// "BF"; testnet swaps the whole sequence so a test node cannot handshake with
241static const char pchMessageStart[4] = { 0xbf, 0x20, 0x5c, 0xfd }; 280// mainnet before consensus-level testnet activation exists.
281extern char pchMessageStart[4];
242 282
243class CMessageHeader 283class CMessageHeader
244{ 284{
245public: 285public:
246 enum { COMMAND_SIZE=12 }; 286 enum { COMMAND_SIZE=12 };
247 char pchMessageStart[sizeof(::pchMessageStart)]; 287 enum { MESSAGE_START_SIZE=4 };
288 char pchMessageStart[MESSAGE_START_SIZE];
248 char pchCommand[COMMAND_SIZE]; 289 char pchCommand[COMMAND_SIZE];
249 unsigned int nMessageSize; 290 unsigned int nMessageSize;
250 291
@@ -335,7 +376,7 @@ public:
335 nServices = 0; 376 nServices = 0;
336 memcpy(pchReserved, pchIPv4, sizeof(pchReserved)); 377 memcpy(pchReserved, pchIPv4, sizeof(pchReserved));
337 ip = 0; 378 ip = 0;
338 port = DEFAULT_PORT; 379 port = GetDefaultPort();
339 nTime = GetAdjustedTime(); 380 nTime = GetAdjustedTime();
340 nLastFailed = 0; 381 nLastFailed = 0;
341 } 382 }
@@ -365,7 +406,7 @@ public:
365 nServices = nServicesIn; 406 nServices = nServicesIn;
366 memcpy(pchReserved, pchIPv4, sizeof(pchReserved)); 407 memcpy(pchReserved, pchIPv4, sizeof(pchReserved));
367 ip = 0; 408 ip = 0;
368 port = DEFAULT_PORT; 409 port = GetDefaultPort();
369 nTime = GetAdjustedTime(); 410 nTime = GetAdjustedTime();
370 nLastFailed = 0; 411 nLastFailed = 0;
371 412
@@ -656,9 +697,6 @@ public:
656 int64 nLastSend; 697 int64 nLastSend;
657 int64 nLastRecv; 698 int64 nLastRecv;
658 int64 nLastSendEmpty; 699 int64 nLastSendEmpty;
659 int64 nIncompleteMessageStart;
660 unsigned int nIncompleteMessageSize;
661 string strIncompleteMessageCommand;
662 string strBtfAddr; 700 string strBtfAddr;
663 string strBtfMeeting; 701 string strBtfMeeting;
664 702
@@ -699,11 +737,13 @@ public:
699 nLastSend = 0; 737 nLastSend = 0;
700 nLastRecv = 0; 738 nLastRecv = 0;
701 nLastSendEmpty = GetTime(); 739 nLastSendEmpty = GetTime();
702 nIncompleteMessageStart = 0;
703 nIncompleteMessageSize = 0;
704 strIncompleteMessageCommand.clear();
705 strBtfAddr.clear(); 740 strBtfAddr.clear();
706 strBtfMeeting.clear(); 741 strBtfMeeting.clear();
742 // Not waiting on anything yet. Left indeterminate, the first partial
743 // message this peer sends is measured against whatever was in this
744 // memory, and ProcessMessages drops it as unreadable on first contact.
745 nMsgWaitSince = 0;
746 nMsgWaitSize = 0;
707 nStartingHeight = -1; 747 nStartingHeight = -1;
708 748
709 // Push a version message 749 // Push a version message
@@ -798,13 +838,51 @@ public:
798 static int64 nLastTime; 838 static int64 nLastTime;
799 nLastTime = nNow = max(nNow, ++nLastTime); 839 nLastTime = nNow = max(nNow, ++nLastTime);
800 840
801 // Each retry is 2 minutes after the last 841 // Each retry is 2 minutes after the last -- and because nRequestTime
802 nRequestTime = max(nRequestTime + 2 * 60 * 1000000, nNow); 842 // is shared across peers, the same spacing is what strings requests
843 // for one inv across its announcers. For transactions that is pacing;
844 // for a new block it was the stall of issue #33: nine peers announce
845 // the block, the first one asked does not serve it, and the ninth
846 // candidate is not even asked until sixteen minutes in, with the pool
847 // mining on the stale tip the whole time.
848 //
849 // Blocks retry on the fetch timescale, but only while we are at the
850 // tip. That is where the stall costs something -- the pool keeps
851 // handing out jobs against a dead tip -- and it is also where the
852 // spacing is nearly free: one block is in flight, and its body has
853 // almost always arrived before the second announcer's turn comes
854 // round, so AlreadyHave drops the duplicate before a getdata is sent.
855 //
856 // While catching up neither half holds. A peer working through a
857 // 500-deep queue can be minutes away from block N without anything
858 // being wrong, so at 15s the second announcer is asked at +15s, the
859 // third at +30s, and the bulk download arrives once per announcer --
860 // up to eight times over. Nothing caps that: the eight-entry cap is on
861 // mapBlockFetch, which is a different mechanism from this spacing.
862 // Two minutes is the right number there, and it is what this line did
863 // before. Failover at the tip does not depend on this being 15s in any
864 // case: mapBlockFetch re-issues a stalled getdata to the next peer on
865 // its own timer, which is what actually fixes #33.
866 bool fFast = (inv.type == MSG_BLOCK && IsBlockFetchNearTip());
867 int64 nRetryUsecs = (fFast ? BLOCK_FETCH_RETRY_SECS : 2 * 60) * 1000000LL;
868 nRequestTime = max(nRequestTime + nRetryUsecs, nNow);
803 mapAskFor.insert(make_pair(nRequestTime, inv)); 869 mapAskFor.insert(make_pair(nRequestTime, inv));
804 } 870 }
805 871
806 872
807 873
874 // "sending: tx (N bytes)" alone was ~71% of a 13-hour production
875 // debug.log (issue #35), so tx sends are demoted to the /debugrelay-gated
876 // "relay" category; every other command's send trace stays on "net".
877 // The line is emitted in pieces across BeginMessage/EndMessage/
878 // AbortMessage, so all three must agree on the category or orphaned
879 // "(N bytes)" fragments would leak into a plain -debug log.
880 // Valid only mid-message (nPushPos != -1).
881 const char* SendLogCategory() const
882 {
883 return strcmp(GetMessageCommand(), "tx") == 0 ? "relay" : "net";
884 }
885
808 void BeginMessage(const char* pszCommand) 886 void BeginMessage(const char* pszCommand)
809 { 887 {
810 EnterCriticalSection(&cs_vSend); 888 EnterCriticalSection(&cs_vSend);
@@ -812,17 +890,19 @@ public:
812 AbortMessage(); 890 AbortMessage();
813 nPushPos = vSend.size(); 891 nPushPos = vSend.size();
814 vSend << CMessageHeader(pszCommand, 0); 892 vSend << CMessageHeader(pszCommand, 0);
815 if (LogAcceptsCategory("net")) printf("sending: %-12s ", pszCommand); 893 if (LogAcceptsCategory(SendLogCategory())) printf("sending: %-12s ", pszCommand);
816 } 894 }
817 895
818 void AbortMessage() 896 void AbortMessage()
819 { 897 {
820 if (nPushPos == -1) 898 if (nPushPos == -1)
821 return; 899 return;
900 // Capture before nPushPos is cleared; GetMessageCommand() needs it.
901 const char* pszCategory = SendLogCategory();
822 vSend.resize(nPushPos); 902 vSend.resize(nPushPos);
823 nPushPos = -1; 903 nPushPos = -1;
824 LeaveCriticalSection(&cs_vSend); 904 LeaveCriticalSection(&cs_vSend);
825 if (LogAcceptsCategory("net")) printf("(aborted)\n"); 905 if (LogAcceptsCategory(pszCategory)) printf("(aborted)\n");
826 } 906 }
827 907
828 void EndMessage() 908 void EndMessage()
@@ -830,7 +910,11 @@ public:
830 extern int nDropMessagesTest; 910 extern int nDropMessagesTest;
831 if (nDropMessagesTest > 0 && GetRand(nDropMessagesTest) == 0) 911 if (nDropMessagesTest > 0 && GetRand(nDropMessagesTest) == 0)
832 { 912 {
833 if (LogAcceptsCategory("net")) printf("dropmessages DROPPING SEND MESSAGE\n"); 913 // Same category as the "sending: " this line interrupts, so a tx
914 // does not announce its own drop under "net" having been gated
915 // off under "relay". nPushPos can be -1 here, and then
916 // GetMessageCommand() returns "" and this is "net" as before.
917 if (LogAcceptsCategory(SendLogCategory())) printf("dropmessages DROPPING SEND MESSAGE\n");
834 AbortMessage(); 918 AbortMessage();
835 return; 919 return;
836 } 920 }
@@ -842,10 +926,10 @@ public:
842 unsigned int nSize = vSend.size() - nPushPos - sizeof(CMessageHeader); 926 unsigned int nSize = vSend.size() - nPushPos - sizeof(CMessageHeader);
843 memcpy((char*)&vSend[nPushPos] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize)); 927 memcpy((char*)&vSend[nPushPos] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize));
844 928
845 if (LogAcceptsCategory("net")) printf("(%d bytes) ", nSize); 929 if (LogAcceptsCategory(SendLogCategory())) printf("(%d bytes) ", nSize);
846 //for (int i = nPushPos+sizeof(CMessageHeader); i < min(vSend.size(), nPushPos+sizeof(CMessageHeader)+20U); i++) 930 //for (int i = nPushPos+sizeof(CMessageHeader); i < min(vSend.size(), nPushPos+sizeof(CMessageHeader)+20U); i++)
847 // printf("%02x ", vSend[i] & 0xff); 931 // printf("%02x ", vSend[i] & 0xff);
848 if (LogAcceptsCategory("net")) printf("\n"); 932 if (LogAcceptsCategory(SendLogCategory())) printf("\n");
849 933
850 nPushPos = -1; 934 nPushPos = -1;
851 LeaveCriticalSection(&cs_vSend); 935 LeaveCriticalSection(&cs_vSend);