upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/util.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/util.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/util.h')
-rw-r--r--src/util.h93
1 files changed, 87 insertions, 6 deletions
diff --git a/src/util.h b/src/util.h
index d72518b..dfe7511 100644
--- a/src/util.h
+++ b/src/util.h
@@ -87,6 +87,15 @@ inline T& REF(const T& val)
87 87
88extern bool fDebug; 88extern bool fDebug;
89 89
90// /debugrelay: the per-message firehose ("relay" and "nostrdiscovery"
91// categories) that even -debug keeps off. See LogAcceptsCategory().
92extern bool fDebugRelay;
93
94// debug.log is rolled to debug.log.old once it grows past this many bytes
95// (set from -maxdebugfilesize, in MB; 0 disables the check). See the roll
96// site in OutputDebugStringF() below.
97extern int64 nMaxDebugFileSize;
98
90// --------------------------------------------------------------------------- 99// ---------------------------------------------------------------------------
91// Categorized, burst-collapsing logging 100// Categorized, burst-collapsing logging
92// 101//
@@ -106,15 +115,29 @@ extern bool fDebug;
106// 2. Burst collapse: repeated LogPrint() calls from the *same source line* 115// 2. Burst collapse: repeated LogPrint() calls from the *same source line*
107// only emit one line per DEDUP_WINDOW_SECS; if more calls land inside 116// only emit one line per DEDUP_WINDOW_SECS; if more calls land inside
108// that window they're counted instead of reprinted, and the count is 117// that window they're counted instead of reprinted, and the count is
109// flushed as a single "(xN similar in Ws)" line the moment the window 118// flushed as a single "(xN similar in Ws)" line once the window expires
110// rolls over. A loop discovering 500 peers by address now produces a 119// -- whether or not that call site ever fires again. A loop discovering
111// small, bounded number of lines instead of 500 -- log growth is capped 120// 500 peers by address now produces a small, bounded number of lines
112// by elapsed time, not by how many similar events happen to fire. 121// instead of 500 -- log growth is capped by elapsed time, not by how
122// many similar events happen to fire.
123//
124// Use LogPrintAlways() instead for anything that reports an irreversible
125// change to money: an obligation voided, a payment sent, a payment that
126// failed. One line standing in for an unknown number of identical events is
127// a tidy report of peer chatter and a false report of a ledger. A reorg
128// voiding 100 entries hits one source line 100 times inside one window;
129// under LogPrint() that read as a single block losing a single 49.49 BTF
130// payment, while 4,950 BTF of obligations were actually destroyed, and the
131// discrepancy was only found by counting entries in pending_payouts.json
132// (issue #3). Bounded log growth is not worth that ambiguity here.
113// --------------------------------------------------------------------------- 133// ---------------------------------------------------------------------------
114bool LogAcceptsCategory(const char* category); 134bool LogAcceptsCategory(const char* category);
115void LogPrintDedup(const char* category, const char* file, int line, const std::string& msg); 135void LogPrintDedup(const char* category, const char* file, int line, const std::string& msg);
136void LogPrintNoCollapse(const char* category, const std::string& msg);
116#define LogPrint(category, ...) \ 137#define LogPrint(category, ...) \
117 do { if (LogAcceptsCategory(category)) LogPrintDedup((category), __FILE__, __LINE__, strprintf(__VA_ARGS__)); } while (0) 138 do { if (LogAcceptsCategory(category)) LogPrintDedup((category), __FILE__, __LINE__, strprintf(__VA_ARGS__)); } while (0)
139#define LogPrintAlways(category, ...) \
140 do { if (LogAcceptsCategory(category)) LogPrintNoCollapse((category), strprintf(__VA_ARGS__)); } while (0)
118 141
119// Every format string in this project goes through one of the four functions 142// Every format string in this project goes through one of the four functions
120// below -- `printf` itself is remapped to OutputDebugStringF just above, and 143// below -- `printf` itself is remapped to OutputDebugStringF just above, and
@@ -145,7 +168,7 @@ void ParseString(const string& str, char c, vector<string>& v);
145string FormatMoney(int64 n, bool fPlus=false); 168string FormatMoney(int64 n, bool fPlus=false);
146bool ParseMoney(const char* pszIn, int64& nRet); 169bool ParseMoney(const char* pszIn, int64& nRet);
147bool FileExists(const char* psz); 170bool FileExists(const char* psz);
148int GetFilesize(FILE* file); 171int64 GetFilesize(FILE* file);
149uint64 GetRand(uint64 nMax); 172uint64 GetRand(uint64 nMax);
150int64 GetTime(); 173int64 GetTime();
151int64 GetAdjustedTime(); 174int64 GetAdjustedTime();
@@ -199,7 +222,7 @@ protected:
199public: 222public:
200 char* pszFile; 223 char* pszFile;
201 int nLine; 224 int nLine;
202 explicit CCriticalSection() { InitializeCriticalSection(&cs); } 225 explicit CCriticalSection() : pszFile(NULL), nLine(0) { InitializeCriticalSection(&cs); }
203 ~CCriticalSection() { DeleteCriticalSection(&cs); } 226 ~CCriticalSection() { DeleteCriticalSection(&cs); }
204 void Enter() { EnterCriticalSection(&cs); } 227 void Enter() { EnterCriticalSection(&cs); }
205 void Leave() { LeaveCriticalSection(&cs); } 228 void Leave() { LeaveCriticalSection(&cs); }
@@ -390,7 +413,65 @@ inline int OutputDebugStringF(const char* pszFormat, ...)
390 else 413 else
391 strDebugFile = "debug.log"; 414 strDebugFile = "debug.log";
392 } 415 }
416 // Latched by a failed rename in the roll below, which cannot be
417 // retried usefully and must not be retried endlessly.
418 static bool fRollDisabled = false;
393 FILE* fileout = fopen(strDebugFile.c_str(), "a"); 419 FILE* fileout = fopen(strDebugFile.c_str(), "a");
420 if (fileout && nMaxDebugFileSize > 0 && !fRollDisabled)
421 {
422 // Roll an overgrown debug.log before adding to it. Nothing in the
423 // tree shrinks this file once the process is running (there is no
424 // ShrinkDebugFile, and even Bitcoin's only ran at startup), so a
425 // node that stays up for months grows the log without bound --
426 // production hit ~2 GiB. The file is opened and closed per line,
427 // so a rename is safe here: the next line simply reopens the
428 // path. One generation is kept as debug.log.old; logrotate
429 // (contrib/logrotate/) handles anything longer-term.
430 int64 nSize = GetFilesize(fileout);
431 if (nSize >= 0 && nSize > nMaxDebugFileSize)
432 {
433 fclose(fileout);
434 string strOldFile = strDebugFile + ".old";
435 remove(strOldFile.c_str()); // rename() won't clobber on Windows
436 bool fRolled = (rename(strDebugFile.c_str(), strOldFile.c_str()) == 0);
437 int nRenameErrno = errno; // before fopen() can overwrite it
438 fileout = fopen(strDebugFile.c_str(), "a");
439 if (fRolled)
440 {
441 if (fileout)
442 fprintf(fileout,
443 "debug.log grew past %lld MB; previous contents moved to debug.log.old (-maxdebugfilesize)\n",
444 (long long)(nMaxDebugFileSize / 1024 / 1024));
445 }
446 else if (nRenameErrno == ENOENT)
447 {
448 // The file went away between the size check and the
449 // rename, so an external rotator (logrotate) got there
450 // first. Nothing left to roll and nothing wrong: the
451 // fopen above has already recreated it. Latching on this
452 // would let a benign race with logrotate switch the cap
453 // off for the rest of the run.
454 }
455 else
456 {
457 // The file is still over the cap, so this branch would be
458 // reached again on the next line and every line after it.
459 // Unlatched, the complaint about failing to roll becomes
460 // the runaway growth the roll exists to prevent. Say it
461 // once and stop trying -- on stderr too, because whatever
462 // blocked the rename (read-only mount, permissions, EXDEV
463 // across a bind mount) may equally block the log write.
464 fRollDisabled = true;
465 fprintf(stderr,
466 "cannot roll %s (rename to .old failed: %s); -maxdebugfilesize disabled for this run\n",
467 strDebugFile.c_str(), strerror(nRenameErrno));
468 if (fileout)
469 fprintf(fileout,
470 "cannot roll debug.log (rename to .old failed: %s); -maxdebugfilesize disabled for this run\n",
471 strerror(nRenameErrno));
472 }
473 }
474 }
394 if (fileout) 475 if (fileout)
395 { 476 {
396 va_list arg_ptr; 477 va_list arg_ptr;