upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile21
-rw-r--r--src/btfaddr.cpp3
-rw-r--r--src/main.cpp16
-rw-r--r--src/main.h14
-rw-r--r--src/makefile.mingw9
-rw-r--r--src/net.cpp2
-rw-r--r--src/net.h4
-rw-r--r--src/nostr.cpp6
-rw-r--r--src/util.cpp4
-rw-r--r--src/util.h44
10 files changed, 92 insertions, 31 deletions
diff --git a/src/Makefile b/src/Makefile
index 9846d8e..f0c6706 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -9,7 +9,26 @@ RANDOMX_DIR ?= $(HOME)/RandomX
9 9
10IMGUI_DIR = imgui 10IMGUI_DIR = imgui
11 11
12CXXFLAGS = -std=gnu++14 -O2 -w -fpermissive -pthread \ 12# -w used to sit here and suppressed every diagnostic in the build, including
13# the one that mattered: `%I64d` is MSVC-only, glibc mis-parses it as the GNU
14# `I` flag with a width of 64 and an `int` conversion, and the resulting vararg
15# desynchronisation segfaulted the node while logging a received block (issue
16# #5, deterministic at height 1062 -- the first block carrying a real
17# transaction). GCC had been reporting it all along:
18#
19# warning: format '%d' expects argument of type 'int',
20# but argument 4 has type 'int64_t'
21#
22# -w cannot be narrowed: it wins over any -W or -Werror= that follows it, so it
23# has to go. The four -Wno- entries below are the categories this 2009-era tree
24# genuinely produces (measured: 248 deprecated-declarations, 157 write-strings,
25# 18 narrowing, 1 unused-result); silencing them by name instead of silencing
26# everything keeps the build quiet while leaving format errors fatal.
27WARNFLAGS = -Wformat -Werror=format \
28 -Wno-deprecated-declarations -Wno-write-strings \
29 -Wno-narrowing -Wno-unused-result
30
31CXXFLAGS = -std=gnu++14 -O2 $(WARNFLAGS) -fpermissive -pthread \
13 -DSECP256K1_STATIC \ 32 -DSECP256K1_STATIC \
14 -I$(SECP_INC) -I$(RANDOMX_DIR)/src \ 33 -I$(SECP_INC) -I$(RANDOMX_DIR)/src \
15 -I/usr/include/nlohmann \ 34 -I/usr/include/nlohmann \
diff --git a/src/btfaddr.cpp b/src/btfaddr.cpp
index 55bb6c5..6edcc91 100644
--- a/src/btfaddr.cpp
+++ b/src/btfaddr.cpp
@@ -7,7 +7,10 @@
7#include "btfaddr.h" 7#include "btfaddr.h"
8 8
9#include <openssl/sha.h> 9#include <openssl/sha.h>
10// See the note in nostr.cpp: the makefiles pass -DSECP256K1_STATIC too.
11#ifndef SECP256K1_STATIC
10#define SECP256K1_STATIC 12#define SECP256K1_STATIC
13#endif
11#include <secp256k1.h> 14#include <secp256k1.h>
12#include <secp256k1_schnorrsig.h> 15#include <secp256k1_schnorrsig.h>
13#include <secp256k1_extrakeys.h> 16#include <secp256k1_extrakeys.h>
diff --git a/src/main.cpp b/src/main.cpp
index bb317d2..c882b0b 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -898,7 +898,7 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, map<uint256, CTxIndex>& mapTestPoo
898 } 898 }
899 899
900 if (prevout.n >= txPrev.vout.size() || prevout.n >= txindex.vSpent.size()) 900 if (prevout.n >= txPrev.vout.size() || prevout.n >= txindex.vSpent.size())
901 return error("ConnectInputs() : %s prevout.n out of range %d %d %d", GetHash().ToString().substr(0,6).c_str(), prevout.n, txPrev.vout.size(), txindex.vSpent.size()); 901 return error("ConnectInputs() : %s prevout.n out of range %d %d %d", GetHash().ToString().substr(0,6).c_str(), prevout.n, (int)txPrev.vout.size(), (int)txindex.vSpent.size());
902 902
903 // If prev is coinbase, check that it's matured 903 // If prev is coinbase, check that it's matured
904 if (txPrev.IsCoinBase()) 904 if (txPrev.IsCoinBase())
@@ -1690,14 +1690,14 @@ void PrintBlockTree()
1690 pindex->nBlockPos, 1690 pindex->nBlockPos,
1691 block.GetHash().ToString().substr(0,14).c_str(), 1691 block.GetHash().ToString().substr(0,14).c_str(),
1692 DateTimeStr(block.nTime).c_str(), 1692 DateTimeStr(block.nTime).c_str(),
1693 block.vtx.size()); 1693 (int)block.vtx.size());
1694 1694
1695 CRITICAL_BLOCK(cs_mapWallet) 1695 CRITICAL_BLOCK(cs_mapWallet)
1696 { 1696 {
1697 if (mapWallet.count(block.vtx[0].GetHash())) 1697 if (mapWallet.count(block.vtx[0].GetHash()))
1698 { 1698 {
1699 CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()]; 1699 CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
1700 printf(" mine: %d %d %d", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit()); 1700 printf(" mine: %d %d %lld", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
1701 } 1701 }
1702 } 1702 }
1703 printf("\n"); 1703 printf("\n");
@@ -1759,7 +1759,7 @@ bool ProcessMessages(CNode* pfrom)
1759 CDataStream& vRecv = pfrom->vRecv; 1759 CDataStream& vRecv = pfrom->vRecv;
1760 if (vRecv.empty()) 1760 if (vRecv.empty())
1761 return true; 1761 return true;
1762 LogPrint("net", "ProcessMessages(%d bytes)\n", vRecv.size()); 1762 LogPrint("net", "ProcessMessages(%d bytes)\n", (int)vRecv.size());
1763 1763
1764 // 1764 //
1765 // Message format 1765 // Message format
@@ -1783,7 +1783,7 @@ bool ProcessMessages(CNode* pfrom)
1783 break; 1783 break;
1784 } 1784 }
1785 if (pstart - vRecv.begin() > 0) 1785 if (pstart - vRecv.begin() > 0)
1786 if (LogAcceptsCategory("net")) printf("\n\nPROCESSMESSAGE SKIPPED %d BYTES\n\n", pstart - vRecv.begin()); 1786 if (LogAcceptsCategory("net")) printf("\n\nPROCESSMESSAGE SKIPPED %d BYTES\n\n", (int)(pstart - vRecv.begin()));
1787 vRecv.erase(vRecv.begin(), pstart); 1787 vRecv.erase(vRecv.begin(), pstart);
1788 1788
1789 // Read header 1789 // Read header
@@ -1836,7 +1836,7 @@ bool ProcessMessages(CNode* pfrom)
1836bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) 1836bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
1837{ 1837{
1838 static map<unsigned int, vector<unsigned char> > mapReuseKey; 1838 static map<unsigned int, vector<unsigned char> > mapReuseKey;
1839 if (LogAcceptsCategory("net")) { printf("received: %-12s (%d bytes) ", strCommand.c_str(), vRecv.size()); for (int i = 0; i < min(vRecv.size(), (unsigned int)25); i++) printf("%02x ", vRecv[i] & 0xff); printf("\n"); } 1839 if (LogAcceptsCategory("net")) { printf("received: %-12s (%d bytes) ", strCommand.c_str(), (int)vRecv.size()); for (int i = 0; i < min(vRecv.size(), (unsigned int)25); i++) printf("%02x ", vRecv[i] & 0xff); printf("\n"); }
1840 if (nDropMessagesTest > 0 && GetRand(nDropMessagesTest) == 0) 1840 if (nDropMessagesTest > 0 && GetRand(nDropMessagesTest) == 0)
1841 { 1841 {
1842 if (LogAcceptsCategory("net")) printf("dropmessages DROPPING RECV MESSAGE\n"); 1842 if (LogAcceptsCategory("net")) printf("dropmessages DROPPING RECV MESSAGE\n");
@@ -2171,7 +2171,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
2171 2171
2172 2172
2173 if (!vRecv.empty()) 2173 if (!vRecv.empty())
2174 if (LogAcceptsCategory("net")) printf("ProcessMessage(%s) : %d extra bytes\n", strCommand.c_str(), vRecv.size()); 2174 if (LogAcceptsCategory("net")) printf("ProcessMessage(%s) : %d extra bytes\n", strCommand.c_str(), (int)vRecv.size());
2175 2175
2176 return true; 2176 return true;
2177} 2177}
@@ -2885,7 +2885,7 @@ bool BitcoinMiner()
2885 } 2885 }
2886 pblock->nBits = nBits; 2886 pblock->nBits = nBits;
2887 pblock->vtx[0].vout[0].nValue = pblock->GetBlockValue(nBestHeight + 1, nFees); 2887 pblock->vtx[0].vout[0].nValue = pblock->GetBlockValue(nBestHeight + 1, nFees);
2888 if (LogAcceptsCategory("net")) printf("\n\nRunning BitcoinMiner with %d transactions in block\n", pblock->vtx.size()); 2888 if (LogAcceptsCategory("net")) printf("\n\nRunning BitcoinMiner with %d transactions in block\n", (int)pblock->vtx.size());
2889 2889
2890 2890
2891 // 2891 //
diff --git a/src/main.h b/src/main.h
index fde3a4e..7e5bdf2 100644
--- a/src/main.h
+++ b/src/main.h
@@ -650,11 +650,11 @@ public:
650 string ToString() const 650 string ToString() const
651 { 651 {
652 string str; 652 string str;
653 str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%d, vout.size=%d, nLockTime=%d)\n", 653 str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%d, vout.size=%d, nLockTime=%u)\n",
654 GetHash().ToString().substr(0,6).c_str(), 654 GetHash().ToString().substr(0,6).c_str(),
655 nVersion, 655 nVersion,
656 vin.size(), 656 (int)vin.size(),
657 vout.size(), 657 (int)vout.size(),
658 nLockTime); 658 nLockTime);
659 for (int i = 0; i < vin.size(); i++) 659 for (int i = 0; i < vin.size(); i++)
660 str += " " + vin[i].ToString() + "\n"; 660 str += " " + vin[i].ToString() + "\n";
@@ -1081,7 +1081,7 @@ public:
1081 hashPrevBlock.ToString().substr(0,14).c_str(), 1081 hashPrevBlock.ToString().substr(0,14).c_str(),
1082 hashMerkleRoot.ToString().substr(0,6).c_str(), 1082 hashMerkleRoot.ToString().substr(0,6).c_str(),
1083 nTime, nBits, nNonce, 1083 nTime, nBits, nNonce,
1084 vtx.size()); 1084 (int)vtx.size());
1085 for (int i = 0; i < vtx.size(); i++) 1085 for (int i = 0; i < vtx.size(); i++)
1086 { 1086 {
1087 printf(" "); 1087 printf(" ");
@@ -1223,8 +1223,10 @@ public:
1223 1223
1224 string ToString() const 1224 string ToString() const
1225 { 1225 {
1226 return strprintf("CBlockIndex(nprev=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d nHeight=%d, merkle=%s, hashBlock=%s)", 1226 // pprev/pnext are pointers: %08x truncated them to 32 bits on a 64-bit
1227 pprev, pnext, nFile, nBlockPos, nHeight, 1227 // build, so the two fields this line exists to show were unreliable.
1228 return strprintf("CBlockIndex(nprev=%p, pnext=%p, nFile=%d, nBlockPos=%-6d nHeight=%d, merkle=%s, hashBlock=%s)",
1229 (void*)pprev, (void*)pnext, nFile, nBlockPos, nHeight,
1228 hashMerkleRoot.ToString().substr(0,6).c_str(), 1230 hashMerkleRoot.ToString().substr(0,6).c_str(),
1229 GetBlockHash().ToString().substr(0,14).c_str()); 1231 GetBlockHash().ToString().substr(0,14).c_str());
1230 } 1232 }
diff --git a/src/makefile.mingw b/src/makefile.mingw
index 7d35d92..01f7702 100644
--- a/src/makefile.mingw
+++ b/src/makefile.mingw
@@ -7,7 +7,14 @@ DEPS = ../deps
7RANDOMX = ../RandomX 7RANDOMX = ../RandomX
8IMGUI_DIR = imgui 8IMGUI_DIR = imgui
9 9
10CXXFLAGS = -std=gnu++14 -O2 -w -fpermissive -Wno-deprecated-declarations -pthread \ 10# See the long note in Makefile: -w hid the format bug that segfaulted the node
11# on glibc (issue #5), and -w cannot be narrowed, so format diagnostics are now
12# fatal and only the categories this tree actually produces are silenced.
13WARNFLAGS = -Wformat -Werror=format \
14 -Wno-deprecated-declarations -Wno-write-strings \
15 -Wno-narrowing -Wno-unused-result
16
17CXXFLAGS = -std=gnu++14 -O2 $(WARNFLAGS) -fpermissive -pthread \
11 -DWIN32 -DNOPCH \ 18 -DWIN32 -DNOPCH \
12 -DSECP256K1_STATIC \ 19 -DSECP256K1_STATIC \
13 -I$(DEPS)/include -I$(RANDOMX)/src \ 20 -I$(DEPS)/include -I$(RANDOMX)/src \
diff --git a/src/net.cpp b/src/net.cpp
index 08a3348..395092d 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -920,7 +920,7 @@ void ThreadSocketHandler2(void* parg)
920 920
921 if (pnodeExtra->GetRefCount() <= (pnodeExtra->fNetworkNode ? 1 : 0)) 921 if (pnodeExtra->GetRefCount() <= (pnodeExtra->fNetworkNode ? 1 : 0))
922 { 922 {
923 LogPrint("net", "(%d nodes) disconnecting duplicate: %s\n", vNodes.size(), pnodeExtra->addr.ToString().c_str()); 923 LogPrint("net", "(%d nodes) disconnecting duplicate: %s\n", (int)vNodes.size(), pnodeExtra->addr.ToString().c_str());
924 if (pnodeExtra->fNetworkNode && !pnode->fNetworkNode) 924 if (pnodeExtra->fNetworkNode && !pnode->fNetworkNode)
925 { 925 {
926 pnode->AddRef(); 926 pnode->AddRef();
diff --git a/src/net.h b/src/net.h
index d13de61..364fbfb 100644
--- a/src/net.h
+++ b/src/net.h
@@ -392,7 +392,9 @@ public:
392 const char* GetCommand() const 392 const char* GetCommand() const
393 { 393 {
394 if (!IsKnownType()) 394 if (!IsKnownType())
395 throw std::out_of_range(strprintf("CInv::GetCommand() : type=% unknown type", type)); 395 // Was "type=% unknown type": the % swallowed the space as a flag and
396 // the u as the conversion, so this read "type= 3nknown type".
397 throw std::out_of_range(strprintf("CInv::GetCommand() : type=%d unknown type", type));
396 return ppszTypeName[type]; 398 return ppszTypeName[type];
397 } 399 }
398 400
diff --git a/src/nostr.cpp b/src/nostr.cpp
index 482a835..088174a 100644
--- a/src/nostr.cpp
+++ b/src/nostr.cpp
@@ -6,8 +6,12 @@
6#include "headers.h" 6#include "headers.h"
7#include <openssl/ssl.h> 7#include <openssl/ssl.h>
8#include <openssl/err.h> 8#include <openssl/err.h>
9// We link libsecp256k1 statically (without this the header assumes DLL import) 9// We link libsecp256k1 statically (without this the header assumes DLL import).
10// Both makefiles also pass -DSECP256K1_STATIC; the guard keeps that from
11// warning while leaving this file correct if built without the flag.
12#ifndef SECP256K1_STATIC
10#define SECP256K1_STATIC 13#define SECP256K1_STATIC
14#endif
11#include <secp256k1.h> 15#include <secp256k1.h>
12#include <secp256k1_schnorrsig.h> 16#include <secp256k1_schnorrsig.h>
13#include <secp256k1_extrakeys.h> 17#include <secp256k1_extrakeys.h>
diff --git a/src/util.cpp b/src/util.cpp
index e4e314f..d52ca88 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -180,7 +180,7 @@ void RandAddSeed(bool fPerfmon)
180 RAND_add(&hash, sizeof(hash), min(nSize/500.0, (double)sizeof(hash))); 180 RAND_add(&hash, sizeof(hash), min(nSize/500.0, (double)sizeof(hash)));
181 hash = 0; 181 hash = 0;
182 memset(pdata, 0, nSize); 182 memset(pdata, 0, nSize);
183 printf("RandAddSeed() got %d bytes of performance data\n", nSize); 183 printf("RandAddSeed() got %lu bytes of performance data\n", nSize);
184 } 184 }
185 } 185 }
186#else 186#else
@@ -472,7 +472,7 @@ void AddTimeData(unsigned int ip, int64 nTime)
472 if (vTimeOffsets.empty()) 472 if (vTimeOffsets.empty())
473 vTimeOffsets.push_back(0); 473 vTimeOffsets.push_back(0);
474 vTimeOffsets.push_back(nOffsetSample); 474 vTimeOffsets.push_back(nOffsetSample);
475 printf("Added time data, samples %d, ip %08x, offset %+lld (%+lld minutes)\n", vTimeOffsets.size(), ip, vTimeOffsets.back(), vTimeOffsets.back()/60); 475 printf("Added time data, samples %d, ip %08x, offset %+lld (%+lld minutes)\n", (int)vTimeOffsets.size(), ip, vTimeOffsets.back(), vTimeOffsets.back()/60);
476 if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1) 476 if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
477 { 477 {
478 sort(vTimeOffsets.begin(), vTimeOffsets.end()); 478 sort(vTimeOffsets.begin(), vTimeOffsets.end());
diff --git a/src/util.h b/src/util.h
index b583248..797ed27 100644
--- a/src/util.h
+++ b/src/util.h
@@ -14,7 +14,9 @@ typedef unsigned long long uint64;
14#define for if (false) ; else for 14#define for if (false) ; else for
15#endif 15#endif
16 16
17#ifndef _MSC_VER 17// MinGW already provides __forceinline for MSVC compatibility, so defining it
18// unconditionally warned ten times per build once -w was removed.
19#if !defined(_MSC_VER) && !defined(__forceinline)
18#define __forceinline inline 20#define __forceinline inline
19#endif 21#endif
20 22
@@ -40,17 +42,17 @@ typedef unsigned long long uint64;
40#endif 42#endif
41#define snprintf my_snprintf 43#define snprintf my_snprintf
42 44
45// One definition for every target. The MSVCRT branch that used to sit here
46// produced "I64d", which is the specifier that segfaults on glibc (issue #5) --
47// and it was pointless besides: this build targets UCRT, which accepts the C99
48// forms, and the rest of the tree already prints int64 with %lld on Windows.
49// Keeping one spelling everywhere is also what lets the format attributes below
50// use a single archetype, so a bad specifier fails the build on both platforms.
43#ifndef PRId64 51#ifndef PRId64
44#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MSVCRT__)
45#define PRId64 "I64d"
46#define PRIu64 "I64u"
47#define PRIx64 "I64x"
48#else
49#define PRId64 "lld" 52#define PRId64 "lld"
50#define PRIu64 "llu" 53#define PRIu64 "llu"
51#define PRIx64 "llx" 54#define PRIx64 "llx"
52#endif 55#endif
53#endif
54 56
55// This is needed because the foreach macro can't get over the comma in pair<t1, t2> 57// This is needed because the foreach macro can't get over the comma in pair<t1, t2>
56#define PAIRTYPE(t1, t2) pair<t1, t2> 58#define PAIRTYPE(t1, t2) pair<t1, t2>
@@ -102,10 +104,30 @@ void LogPrintDedup(const char* category, const char* file, int line, const std::
102#define LogPrint(category, ...) \ 104#define LogPrint(category, ...) \
103 do { if (LogAcceptsCategory(category)) LogPrintDedup((category), __FILE__, __LINE__, strprintf(__VA_ARGS__)); } while (0) 105 do { if (LogAcceptsCategory(category)) LogPrintDedup((category), __FILE__, __LINE__, strprintf(__VA_ARGS__)); } while (0)
104 106
107// Every format string in this project goes through one of the four functions
108// below -- `printf` itself is remapped to OutputDebugStringF just above, and
109// snprintf to my_snprintf. None of them carried a format attribute, and GCC
110// only checks format strings for functions it knows are printf-like, so
111// -Wformat had nothing to inspect and the whole tree was unchecked. That is
112// how `%I64d` (MSVC-only, and a segfault on glibc) survived in
113// CTxOut::ToString until it crashed a node mid-sync -- see issue #5.
114//
115// gnu_printf on both platforms, deliberately. MinGW's other option, ms_printf,
116// models the legacy msvcrt: it rejects %zu, which this tree uses and UCRT
117// supports, and it accepts %I64d, which is the specifier that crashes on glibc.
118// It would give false positives where the code is right and stay silent where it
119// is dangerous. gnu_printf describes UCRT's C99 behaviour accurately, so one
120// archetype covers both builds and a bad specifier fails either one.
121#if defined(__GNUC__)
122#define BF_FORMAT(fmt, args) __attribute__((format(gnu_printf, fmt, args)))
123#else
124#define BF_FORMAT(fmt, args)
125#endif
126
105void RandAddSeed(bool fPerfmon=false); 127void RandAddSeed(bool fPerfmon=false);
106int my_snprintf(char* buffer, size_t limit, const char* format, ...); 128int my_snprintf(char* buffer, size_t limit, const char* format, ...) BF_FORMAT(3, 4);
107string strprintf(const char* format, ...); 129string strprintf(const char* format, ...) BF_FORMAT(1, 2);
108bool error(const char* format, ...); 130bool error(const char* format, ...) BF_FORMAT(1, 2);
109void PrintException(std::exception* pex, const char* pszThread); 131void PrintException(std::exception* pex, const char* pszThread);
110void ParseString(const string& str, char c, vector<string>& v); 132void ParseString(const string& str, char c, vector<string>& v);
111string FormatMoney(int64 n, bool fPlus=false); 133string FormatMoney(int64 n, bool fPlus=false);
@@ -266,6 +288,8 @@ void PrintHex(const T pbegin, const T pend, const char* pszFormat="%s", bool fSp
266// Forward declaration -- defined in main.cpp 288// Forward declaration -- defined in main.cpp
267string GetAppDir(); 289string GetAppDir();
268 290
291inline int OutputDebugStringF(const char* pszFormat, ...) BF_FORMAT(1, 2);
292
269inline int OutputDebugStringF(const char* pszFormat, ...) 293inline int OutputDebugStringF(const char* pszFormat, ...)
270{ 294{
271#if 1 // debug.log always enabled 295#if 1 // debug.log always enabled