upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/main_gui.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/main_gui.cpp')
-rw-r--r--src/main_gui.cpp154
1 files changed, 150 insertions, 4 deletions
diff --git a/src/main_gui.cpp b/src/main_gui.cpp
index a561174..2e4eb91 100644
--- a/src/main_gui.cpp
+++ b/src/main_gui.cpp
@@ -111,6 +111,8 @@ static void PrintUsage()
111 printf(" /help, -help, --help, /?\n"); 111 printf(" /help, -help, --help, /?\n");
112 printf(" /datadir=PATH\n"); 112 printf(" /datadir=PATH\n");
113 printf(" /debug\n"); 113 printf(" /debug\n");
114 printf(" /debugrelay (/debug plus per-message relay chatter and block dumps)\n");
115 printf(" /maxdebugfilesize=N (roll debug.log at N MB, default 1024; 0 = never)\n");
114 printf(" /gen\n"); 116 printf(" /gen\n");
115 printf(" /nogui or /daemon\n"); 117 printf(" /nogui or /daemon\n");
116 printf(" /selftest=wallet-keypool, wallet-hd, wallet-format, wallet-storage-sanity,\n"); 118 printf(" /selftest=wallet-keypool, wallet-hd, wallet-format, wallet-storage-sanity,\n");
@@ -123,6 +125,9 @@ static void PrintUsage()
123 printf("Mining mode:\n"); 125 printf("Mining mode:\n");
124 printf(" /operator\n"); 126 printf(" /operator\n");
125 printf(" /participant=POOL_BTF_ADDRESS\n"); 127 printf(" /participant=POOL_BTF_ADDRESS\n");
128 printf(" /payoutaddr=BTF_ADDRESS (participant: pay shares to this address, no wallet needed)\n");
129 printf(" /payoutfile=FILE (participant: rotate payout addresses from file)\n");
130 printf(" /hashthreads=N (participant: mining threads, default cores-1)\n");
126 printf(" /stratumbridge=POOL_BTF_ADDRESS\n"); 131 printf(" /stratumbridge=POOL_BTF_ADDRESS\n");
127 printf(" /stratumbridgeport=N (default 3333; listen on 127.0.0.1)\n"); 132 printf(" /stratumbridgeport=N (default 3333; listen on 127.0.0.1)\n");
128 printf(" /solomine\n"); 133 printf(" /solomine\n");
@@ -150,6 +155,7 @@ static void PrintUsage()
150 printf(" /socks=HOST:PORT (SOCKS5 proxy for Nostr, .btf relay, and onion dials)\n"); 155 printf(" /socks=HOST:PORT (SOCKS5 proxy for Nostr, .btf relay, and onion dials)\n");
151 printf(" /tor[=HOST:PORT] (Tor mode; default SOCKS5 proxy is 127.0.0.1:9050)\n"); 156 printf(" /tor[=HOST:PORT] (Tor mode; default SOCKS5 proxy is 127.0.0.1:9050)\n");
152 printf(" /managedtor[=PATH] (start Tor, create a hidden service, advertise its onion)\n"); 157 printf(" /managedtor[=PATH] (start Tor, create a hidden service, advertise its onion)\n");
158 printf(" /automanagedtor (auto-start a bundled Tor if one sits next to the executable)\n");
153 printf(" /nomanagedtor (disable automatic bundled Tor startup)\n"); 159 printf(" /nomanagedtor (disable automatic bundled Tor startup)\n");
154 printf(" /oniononly (do not fall back to rendezvous when a .btf onion dial fails)\n"); 160 printf(" /oniononly (do not fall back to rendezvous when a .btf onion dial fails)\n");
155 printf(" /btfseed=ADDRESS:ENCHEX (extra bootstrap peer, repeatable)\n"); 161 printf(" /btfseed=ADDRESS:ENCHEX (extra bootstrap peer, repeatable)\n");
@@ -195,6 +201,9 @@ static void PrintUsage()
195 printf(" /walletsqlite=FILE (stage-load a SQLite wallet export, then exit)\n"); 201 printf(" /walletsqlite=FILE (stage-load a SQLite wallet export, then exit)\n");
196 printf(" /walletbackend=sqlite (opt-in: run the node on <datadir>/wallet.sqlite\n"); 202 printf(" /walletbackend=sqlite (opt-in: run the node on <datadir>/wallet.sqlite\n");
197 printf(" instead of wallet.dat; export one first)\n"); 203 printf(" instead of wallet.dat; export one first)\n");
204 printf(" /createwallet (headless only: permit creating a new wallet in a\n");
205 printf(" datadir that has none -- otherwise refused, since\n");
206 printf(" a missing wallet is usually a mount/backup fault)\n");
198 printf(" /rescan (walk the chain for coins this wallet owns\n"); 207 printf(" /rescan (walk the chain for coins this wallet owns\n");
199 printf(" but never recorded, then exit)\n"); 208 printf(" but never recorded, then exit)\n");
200 printf("\n"); 209 printf("\n");
@@ -214,6 +223,54 @@ static void ParseStartupArguments(int argc, char* argv[])
214 if (arg(argc,argv,"/debug") || arg(argc,argv,"-debug")) 223 if (arg(argc,argv,"/debug") || arg(argc,argv,"-debug"))
215 fDebug = true; 224 fDebug = true;
216 225
226 // /debugrelay -- everything /debug shows, plus the per-message firehose
227 // ("relay" and "nostrdiscovery" categories: sending: tx, Relaying wtx,
228 // raw CBlock dumps, per-peer discovery lines). That traffic was ~90% of
229 // a 13-hour production debug.log (issue #35), so plain /debug leaves it
230 // off; the message text itself is unchanged for anyone grepping it.
231 if (arg(argc,argv,"/debugrelay") || arg(argc,argv,"-debugrelay"))
232 {
233 fDebug = true;
234 fDebugRelay = true;
235 }
236
237 // /maxdebugfilesize=N -- roll debug.log to debug.log.old once it passes
238 // N MB, checked on each write. Default is 1024 (see util.cpp); 0 turns
239 // the check off and leaves rotation entirely to logrotate.
240 string strMaxDebugSize = argval2(argc, argv, "/maxdebugfilesize", "-maxdebugfilesize");
241 if (!strMaxDebugSize.empty())
242 {
243 // Parsed with atoi64() before, which is strtoll() with the endptr
244 // thrown away: it returns 0 for anything it cannot read, so
245 // /maxdebugfilesize=1G and =1024MB both came out as 0 -- "never
246 // roll", identical to asking for that on purpose, with nothing said
247 // to the operator. The old code also multiplied without a range
248 // check, so a big enough N wrapped to a negative cap, which the roll
249 // reads as "off" too. Every rejection is now reported and leaves the
250 // default in place; the value is a plain count of MB, no suffix.
251 const char* psz = strMaxDebugSize.c_str();
252 char* pszEnd = NULL;
253 errno = 0;
254 int64 nMB = strtoll(psz, &pszEnd, 10);
255 // INT64_MAX, without depending on which limits header this tree pulls in.
256 const int64 nMaxMB = (int64)((~(uint64)0) >> 1) / (1024 * 1024);
257 const char* pszWhy = NULL;
258 if (pszEnd == psz)
259 pszWhy = "not a number";
260 else if (*pszEnd != '\0')
261 pszWhy = "trailing characters -- the value is a count of MB, with no unit suffix";
262 else if (errno == ERANGE || nMB < 0)
263 pszWhy = "not a size in MB";
264 else if (nMB > nMaxMB)
265 pszWhy = "larger than a file size can be";
266 if (pszWhy)
267 fprintf(stderr, "Ignoring /maxdebugfilesize=%s: %s (keeping %lld MB)\n",
268 strMaxDebugSize.c_str(), pszWhy,
269 (long long)(nMaxDebugFileSize / 1024 / 1024));
270 else
271 nMaxDebugFileSize = nMB * 1024 * 1024;
272 }
273
217 if (arg(argc,argv,"/gen") || arg(argc,argv,"-gen")) 274 if (arg(argc,argv,"/gen") || arg(argc,argv,"-gen"))
218 { 275 {
219 fGenerateBitcoins = 1; 276 fGenerateBitcoins = 1;
@@ -245,7 +302,7 @@ static void ParseStartupArguments(int argc, char* argv[])
245 if (!strProcLimit.empty()) 302 if (!strProcLimit.empty())
246 { 303 {
247 int n = atoi(strProcLimit.c_str()); 304 int n = atoi(strProcLimit.c_str());
248 unsigned int nCores = std::thread::hardware_concurrency(); 305 unsigned int nCores = AvailableCoreCount();
249 if (n < 0) 306 if (n < 0)
250 fprintf(stderr, "Ignoring /genproclimit=%s: not a thread count\n", 307 fprintf(stderr, "Ignoring /genproclimit=%s: not a thread count\n",
251 strProcLimit.c_str()); 308 strProcLimit.c_str());
@@ -271,6 +328,18 @@ static void ParseStartupArguments(int argc, char* argv[])
271 fMineModeFromCommandLine = true; 328 fMineModeFromCommandLine = true;
272 } 329 }
273 330
331 string payoutAddr = argval2(argc, argv, "/payoutaddr", "-payoutaddr");
332 if (!payoutAddr.empty())
333 strPayoutAddress = payoutAddr;
334
335 string payoutFile = argval2(argc, argv, "/payoutfile", "-payoutfile");
336 if (!payoutFile.empty())
337 strPayoutFile = payoutFile;
338
339 string hashThreads = argval2(argc, argv, "/hashthreads", "-hashthreads");
340 if (!hashThreads.empty())
341 nHashThreads = atoi(hashThreads.c_str());
342
274 if (arg(argc,argv,"/stratumbridge") || arg(argc,argv,"-stratumbridge")) 343 if (arg(argc,argv,"/stratumbridge") || arg(argc,argv,"-stratumbridge"))
275 { 344 {
276 fStratumBridge = true; 345 fStratumBridge = true;
@@ -297,6 +366,12 @@ static void ParseStartupArguments(int argc, char* argv[])
297 if (!poolDash.empty()) 366 if (!poolDash.empty())
298 strPoolDashboardUrl = poolDash; 367 strPoolDashboardUrl = poolDash;
299 368
369 if (arg(argc,argv,"/noannounce") || arg(argc,argv,"-noannounce"))
370 fPoolNoAnnounce = true;
371
372 if (arg(argc,argv,"/poolmineblind") || arg(argc,argv,"-poolmineblind"))
373 fPoolMineBlind = true;
374
300 string poolFee = argval2(argc, argv, "/poolfee", "-poolfee"); 375 string poolFee = argval2(argc, argv, "/poolfee", "-poolfee");
301 if (!poolFee.empty()) 376 if (!poolFee.empty())
302 dPoolFeePercent = atof(poolFee.c_str()); 377 dPoolFeePercent = atof(poolFee.c_str());
@@ -317,8 +392,20 @@ static void ParseStartupArguments(int argc, char* argv[])
317 string rvRelay = argval2(argc, argv, "/rvrelay", "-rvrelay"); 392 string rvRelay = argval2(argc, argv, "/rvrelay", "-rvrelay");
318 if (!rvRelay.empty()) 393 if (!rvRelay.empty())
319 { 394 {
320 vBtfMeetingRelays.clear(); 395 if (!LooksLikeRelay(rvRelay))
321 vBtfMeetingRelays.push_back(rvRelay); 396 {
397 // A malformed pin must not replace the seed list: with the pin
398 // set, no discovered relay can ever mask the typo, and the pool
399 // would publish a garbage (or no) meeting node forever.
400 fprintf(stderr, "Ignoring /rvrelay=%s: expected host:port\n",
401 rvRelay.c_str());
402 }
403 else
404 {
405 vBtfMeetingRelays.clear();
406 vBtfMeetingRelays.push_back(rvRelay);
407 fBtfRelayPinned = true;
408 }
322 } 409 }
323 410
324 // net.cpp has described nListenPort as "tunable via /port" since it was 411 // net.cpp has described nListenPort as "tunable via /port" since it was
@@ -359,8 +446,16 @@ static void ParseStartupArguments(int argc, char* argv[])
359 bool fTorMode = arg(argc, argv, "/tor") || arg(argc, argv, "-tor"); 446 bool fTorMode = arg(argc, argv, "/tor") || arg(argc, argv, "-tor");
360 string socksProxy = argval2(argc, argv, "/socks", "-socks"); 447 string socksProxy = argval2(argc, argv, "/socks", "-socks");
361 string bundledTorPath; 448 string bundledTorPath;
449 // Managed Tor is opt-in on this fork. Upstream 1.2.19 auto-starts a
450 // bundled tor whenever one sits next to the executable, which silently
451 // moves Nostr/.btf traffic onto Tor, creates a hidden service, and starts
452 // publishing descriptors with meeting_node="rendezvous-pending" on nodes
453 // that never asked for it -- against our pinned-relay posture. The
454 // upstream behavior remains available under the explicit /automanagedtor.
362 bool fAutoManagedTor = !fManagedTor && !fNoManagedTor && !fTorMode && 455 bool fAutoManagedTor = !fManagedTor && !fNoManagedTor && !fTorMode &&
363 socksProxy.empty() && BtfBundledTorPath(bundledTorPath); 456 socksProxy.empty() &&
457 (arg(argc, argv, "/automanagedtor") || arg(argc, argv, "-automanagedtor")) &&
458 BtfBundledTorPath(bundledTorPath);
364 if (fManagedTor || fAutoManagedTor) 459 if (fManagedTor || fAutoManagedTor)
365 { 460 {
366 if (fManagedTor && (fTorMode || !socksProxy.empty())) 461 if (fManagedTor && (fTorMode || !socksProxy.empty()))
@@ -804,6 +899,32 @@ int main(int argc, char* argv[])
804 else { fUseSQLite = true; fCreateSQLite = true; } 899 else { fUseSQLite = true; fCreateSQLite = true; }
805 } 900 }
806 901
902 // A headless node whose datadir holds no wallet of either kind is
903 // far more often an operations fault -- datadir not mounted, or
904 // wallet.dat caught mid-rename by a backup -- than a first run.
905 // Creating one here is not the harmless default it looks like:
906 // success also writes the backend marker, and from then on
907 // restoring the real wallet.dat no longer takes effect, because the
908 // marker keeps the node on the empty wallet it just made. Under
909 // 1.2.19 the same fault created a wallet.dat that a restore
910 // overwrote, so operators could recover by putting the file back.
911 // Refuse instead, and name the flag that makes it deliberate.
912 if (fCreateSQLite && fHeadlessStartup &&
913 !arg(argc, argv, "/createwallet") && !arg(argc, argv, "-createwallet"))
914 {
915 AttachTerminal();
916 fprintf(stderr,
917 "No wallet found in %s\n"
918 "Refusing to create one. On a headless node an absent wallet is\n"
919 "usually a mount or backup fault, and creating one would record a\n"
920 "backend marker that makes restoring the real wallet a no-op.\n"
921 "Pass -createwallet to start a new one deliberately, or\n"
922 "-walletbackend=bdb to run on a Berkeley DB wallet.dat.\n",
923 GetAppDir().c_str());
924 fflush(stderr);
925 return 1;
926 }
927
807 if (fUseSQLite) 928 if (fUseSQLite)
808 { 929 {
809 AttachTerminal(); 930 AttachTerminal();
@@ -1041,6 +1162,31 @@ int main(int argc, char* argv[])
1041 1162
1042 ReacceptWalletTransactions(); 1163 ReacceptWalletTransactions();
1043 1164
1165 // /dumpaddresses=N:FILE -- generate N fresh wallet keys and write their
1166 // addresses (one per line) to FILE, then exit. Keys stay in this wallet;
1167 // the file alone is enough for a miner elsewhere to rotate payout
1168 // addresses via /payoutfile. (No HD/xpub exists in this wallet format.)
1169 string dumpSpec = argval2(argc, argv, "/dumpaddresses", "-dumpaddresses");
1170 if (!dumpSpec.empty())
1171 {
1172 size_t colon = dumpSpec.rfind(':');
1173 if (colon == string::npos) { fprintf(stderr, "usage: /dumpaddresses=N:FILE\n"); return 1; }
1174 int n = atoi(dumpSpec.substr(0, colon).c_str());
1175 string file = dumpSpec.substr(colon + 1);
1176 FILE* f = fopen(file.c_str(), "w");
1177 if (!f) { fprintf(stderr, "cannot open %s\n", file.c_str()); return 1; }
1178 for (int i = 0; i < n; i++)
1179 {
1180 CKey key;
1181 key.MakeNewKey();
1182 if (!AddKey(key)) { fclose(f); fprintf(stderr, "AddKey failed at %d\n", i); return 1; }
1183 fprintf(f, "%s\n", PubKeyToAddress(key.GetPubKey()).c_str());
1184 }
1185 fclose(f);
1186 printf("wrote %d fresh wallet addresses to %s\n", n, file.c_str());
1187 return 0;
1188 }
1189
1044 if (!StartNode(strErrors)) 1190 if (!StartNode(strErrors))
1045 { 1191 {
1046 fprintf(stderr,"StartNode: %s\n",strErrors.c_str()); 1192 fprintf(stderr,"StartNode: %s\n",strErrors.c_str());