Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : // Copyright (c) 2009-2021 The Bitcoin developers
3 : // Copyright (c) 2014-2015 The Dash developers
4 : // Copyright (c) 2011-2013 The PPCoin developers
5 : // Copyright (c) 2013-2014 The NovaCoin Developers
6 : // Copyright (c) 2014-2018 The BlackCoin Developers
7 : // Copyright (c) 2015-2022 The PIVX Core developers
8 : // Distributed under the MIT software license, see the accompanying
9 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
10 :
11 : #if defined(HAVE_CONFIG_H)
12 : #include "config/pivx-config.h"
13 : #endif
14 :
15 : #include "init.h"
16 :
17 : #include "activemasternode.h"
18 : #include "addrman.h"
19 : #include "amount.h"
20 : #include "bls/bls_wrapper.h"
21 : #include "checkpoints.h"
22 : #include "compat/sanity.h"
23 : #include "consensus/upgrades.h"
24 : #include "fs.h"
25 : #include "httpserver.h"
26 : #include "httprpc.h"
27 : #include "invalid.h"
28 : #include "key.h"
29 : #include "mapport.h"
30 : #include "miner.h"
31 : #include "netbase.h"
32 : #include "net_processing.h"
33 : #include "policy/feerate.h"
34 : #include "policy/policy.h"
35 : #include "rpc/register.h"
36 : #include "rpc/server.h"
37 : #include "script/sigcache.h"
38 : #include "script/standard.h"
39 : #include "scheduler.h"
40 : #include "shutdown.h"
41 : #include "spork.h"
42 : #include "sporkdb.h"
43 : #include "tiertwo/init.h"
44 : #include "txdb.h"
45 : #include "torcontrol.h"
46 : #include "guiinterface.h"
47 : #include "guiinterfaceutil.h"
48 : #include "util/system.h"
49 : #include "utilmoneystr.h"
50 : #include "util/threadnames.h"
51 : #include "validation.h"
52 : #include "validationinterface.h"
53 : #include "warnings.h"
54 :
55 : #ifdef ENABLE_WALLET
56 : #include "wallet/init.h"
57 : #include "wallet/wallet.h"
58 : #include "wallet/rpcwallet.h"
59 : #endif
60 :
61 : #include <atomic>
62 : #include <fstream>
63 : #include <stdint.h>
64 : #include <stdio.h>
65 : #include <memory>
66 :
67 : #ifndef WIN32
68 : #include <attributes.h>
69 : #include <cerrno>
70 : #include <signal.h>
71 : #include <sys/stat.h>
72 : #endif
73 :
74 : #include <boost/algorithm/string.hpp>
75 : #include <boost/algorithm/string/split.hpp>
76 : #include <boost/algorithm/string/replace.hpp>
77 : #include <boost/thread.hpp>
78 :
79 : #if ENABLE_ZMQ
80 : #include "zmq/zmqnotificationinterface.h"
81 : #endif
82 :
83 :
84 : volatile bool fFeeEstimatesInitialized = false;
85 : static const bool DEFAULT_PROXYRANDOMIZE = true;
86 : static const bool DEFAULT_REST_ENABLE = false;
87 : static const bool DEFAULT_DISABLE_SAFEMODE = false;
88 : static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false;
89 :
90 : std::unique_ptr<CConnman> g_connman;
91 : std::unique_ptr<PeerLogicValidation> peerLogic;
92 :
93 : #if ENABLE_ZMQ
94 : static CZMQNotificationInterface* pzmqNotificationInterface = nullptr;
95 : #endif
96 :
97 : #ifdef WIN32
98 : // Win32 LevelDB doesn't use filedescriptors, and the ones used for
99 : // accessing block files, don't count towards to fd_set size limit
100 : // anyway.
101 : #define MIN_CORE_FILEDESCRIPTORS 0
102 : #else
103 : #define MIN_CORE_FILEDESCRIPTORS 150
104 : #endif
105 :
106 : static const char* DEFAULT_ASMAP_FILENAME="ip_asn.map";
107 :
108 : static const char* FEE_ESTIMATES_FILENAME = "fee_estimates.dat";
109 : CClientUIInterface uiInterface; // Declared but not defined in guiinterface.h
110 :
111 : /**
112 : * The PID file facilities.
113 : */
114 : const char * const PIVX_PID_FILENAME = "pivx.pid";
115 :
116 756 : fs::path GetPidFile()
117 : {
118 1512 : fs::path pathPidFile(gArgs.GetArg("-pid", PIVX_PID_FILENAME));
119 1512 : return AbsPathForConfigVal(pathPidFile);
120 : }
121 :
122 378 : NODISCARD static bool CreatePidFile()
123 : {
124 378 : FILE* file = fsbridge::fopen(GetPidFile(), "w");
125 378 : if (file) {
126 378 : fprintf(file, "%d\n", getpid());
127 378 : fclose(file);
128 378 : return true;
129 : } else {
130 0 : return UIError(strprintf(_("Unable to create the PID file '%s': %s"), GetPidFile().string(), std::strerror(errno)));
131 : }
132 : }
133 :
134 : //////////////////////////////////////////////////////////////////////////////
135 : //
136 : // Shutdown
137 : //
138 :
139 : //
140 : // Thread management and startup/shutdown:
141 : //
142 : // The network-processing threads are all part of a thread group
143 : // created by AppInit() or the Qt main() function.
144 : //
145 : // A clean exit happens when StartShutdown() or the SIGTERM
146 : // signal handler sets ShutdownRequested(), which triggers
147 : // the DetectShutdownThread(), which interrupts the main thread group.
148 : // DetectShutdownThread() then exits, which causes AppInit() to
149 : // continue (it .joins the shutdown thread).
150 : // Shutdown() is then
151 : // called to clean up database connections, and stop other
152 : // threads that should only be stopped after the main network-processing
153 : // threads have exited.
154 : //
155 : // Shutdown for Qt is very similar, only it uses a QTimer to detect
156 : // ShutdownRequested() getting set, and then does the normal Qt
157 : // shutdown thing.
158 : //
159 :
160 : class CCoinsViewErrorCatcher : public CCoinsViewBacked
161 : {
162 : public:
163 714 : explicit CCoinsViewErrorCatcher(CCoinsView* view) : CCoinsViewBacked(view) {}
164 1307110 : bool GetCoin(const COutPoint& outpoint, Coin& coin) const override
165 : {
166 1307110 : try {
167 1307110 : return CCoinsViewBacked::GetCoin(outpoint, coin);
168 0 : } catch (const std::runtime_error& e) {
169 0 : uiInterface.ThreadSafeMessageBox(_("Error reading from database, shutting down."), "", CClientUIInterface::MSG_ERROR);
170 0 : LogPrintf("Error reading from database: %s\n", e.what());
171 : // Starting the shutdown sequence and returning false to the caller would be
172 : // interpreted as 'entry not found' (as opposed to unable to read data), and
173 : // could lead to invalid interpration. Just exit immediately, as we can't
174 : // continue anyway, and all writes should be atomic.
175 0 : abort();
176 : }
177 : }
178 : // Writes do not need similar protection, as failure to write is handled by the caller.
179 : };
180 :
181 : static std::unique_ptr<CCoinsViewErrorCatcher> pcoinscatcher;
182 : static std::unique_ptr<ECCVerifyHandle> globalVerifyHandle;
183 :
184 : static boost::thread_group threadGroup;
185 : static CScheduler scheduler;
186 378 : void Interrupt()
187 : {
188 378 : InterruptHTTPServer();
189 378 : InterruptHTTPRPC();
190 378 : InterruptRPC();
191 378 : InterruptREST();
192 378 : InterruptTorControl();
193 378 : InterruptMapPort();
194 378 : InterruptTierTwo();
195 378 : if (g_connman)
196 366 : g_connman->Interrupt();
197 378 : }
198 :
199 378 : void Shutdown()
200 : {
201 378 : StartShutdown(); // Needed when we shutdown the wallet
202 378 : LogPrintf("%s: In progress...\n", __func__);
203 378 : static RecursiveMutex cs_Shutdown;
204 756 : TRY_LOCK(cs_Shutdown, lockShutdown);
205 378 : if (!lockShutdown)
206 0 : return;
207 :
208 : /// Note: Shutdown() must be able to handle cases in which initialization failed part of the way,
209 : /// for example if the data directory was found to be locked.
210 : /// Be sure that anything that writes files or flushes caches only does this if the respective
211 : /// module was initialized.
212 378 : util::ThreadRename("pivx-shutoff");
213 378 : mempool.AddTransactionsUpdated(1);
214 378 : StopHTTPRPC();
215 378 : StopREST();
216 378 : StopRPC();
217 378 : StopHTTPServer();
218 378 : StopTierTwoThreads();
219 : #ifdef ENABLE_WALLET
220 740 : for (CWalletRef pwallet : vpwallets) {
221 362 : pwallet->Flush(false);
222 : }
223 378 : GenerateBitcoins(false, nullptr, 0);
224 : #endif
225 378 : StopMapPort();
226 :
227 : // Because these depend on each-other, we make sure that neither can be
228 : // using the other before destroying them.
229 378 : if (peerLogic) UnregisterValidationInterface(peerLogic.get());
230 378 : if (g_connman) g_connman->Stop();
231 :
232 378 : StopTorControl();
233 :
234 : // After everything has been shut down, but before things get flushed, stop the
235 : // CScheduler/checkqueue threadGroup
236 378 : scheduler.stop();
237 378 : threadGroup.interrupt_all();
238 378 : threadGroup.join_all();
239 :
240 : // After the threads that potentially access these pointers have been stopped,
241 : // destruct and reset all to nullptr.
242 378 : g_connman.reset();
243 378 : peerLogic.reset();
244 :
245 378 : DumpTierTwo();
246 741 : if (::mempool.IsLoaded() && gArgs.GetBoolArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
247 347 : DumpMempool(::mempool);
248 : }
249 :
250 378 : if (fFeeEstimatesInitialized) {
251 712 : fs::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
252 712 : CAutoFile est_fileout(fsbridge::fopen(est_path, "wb"), SER_DISK, CLIENT_VERSION);
253 356 : if (!est_fileout.IsNull())
254 356 : mempool.WriteFeeEstimates(est_fileout);
255 : else
256 0 : LogPrintf("%s: Failed to write fee estimates to %s\n", __func__, est_path.string());
257 356 : fFeeEstimatesInitialized = false;
258 : }
259 :
260 : // FlushStateToDisk generates a SetBestChain callback, which we should avoid missing
261 378 : if (pcoinsTip != nullptr) {
262 357 : FlushStateToDisk();
263 : }
264 :
265 : // After there are no more peers/RPC left to give us new data which may generate
266 : // CValidationInterface callbacks, flush them...
267 378 : GetMainSignals().FlushBackgroundCallbacks();
268 :
269 : // Any future callbacks will be dropped. This should absolutely be safe - if
270 : // missing a callback results in an unrecoverable situation, unclean shutdown
271 : // would too. The only reason to do the above flushes is to let the wallet catch
272 : // up with our current chain to avoid any strange pruning edge cases and make
273 : // next startup faster by avoiding rescan.
274 :
275 378 : {
276 378 : LOCK(cs_main);
277 378 : if (pcoinsTip != nullptr) {
278 357 : FlushStateToDisk();
279 :
280 : //record that client took the proper shutdown procedure
281 714 : pblocktree->WriteFlag("shutdown", true);
282 : }
283 378 : pcoinsTip.reset();
284 378 : pcoinscatcher.reset();
285 378 : pcoinsdbview.reset();
286 378 : pblocktree.reset();
287 378 : zerocoinDB.reset();
288 378 : accumulatorCache.reset();
289 378 : pSporkDB.reset();
290 378 : DeleteTierTwo();
291 : }
292 : #ifdef ENABLE_WALLET
293 740 : for (CWalletRef pwallet : vpwallets) {
294 362 : pwallet->Flush(true);
295 : }
296 : #endif
297 :
298 : // Tier two
299 378 : ResetTierTwoInterfaces();
300 :
301 : #if ENABLE_ZMQ
302 378 : if (pzmqNotificationInterface) {
303 1 : UnregisterValidationInterface(pzmqNotificationInterface);
304 1 : delete pzmqNotificationInterface;
305 1 : pzmqNotificationInterface = nullptr;
306 : }
307 : #endif
308 :
309 : // Disconnect all slots
310 378 : UnregisterAllValidationInterfaces();
311 378 : GetMainSignals().UnregisterBackgroundSignalScheduler();
312 :
313 : #ifndef WIN32
314 378 : try {
315 1134 : if (!fs::remove(GetPidFile())) {
316 0 : LogPrintf("%s: Unable to remove PID file: File does not exist\n", __func__);
317 : }
318 0 : } catch (const fs::filesystem_error& e) {
319 0 : LogPrintf("%s: Unable to remove PID file: %s\n", __func__, e.what());
320 : }
321 : #endif
322 :
323 : #ifdef ENABLE_WALLET
324 740 : for (CWalletRef pwallet : vpwallets) {
325 362 : delete pwallet;
326 : }
327 378 : vpwallets.clear();
328 : #endif
329 378 : globalVerifyHandle.reset();
330 378 : ECC_Stop();
331 378 : LogPrintf("%s: done\n", __func__);
332 : }
333 :
334 : /**
335 : * Signal handlers are very limited in what they are allowed to do, so:
336 : */
337 0 : void HandleSIGTERM(int)
338 : {
339 0 : StartShutdown();
340 0 : }
341 :
342 0 : void HandleSIGHUP(int)
343 : {
344 0 : g_logger->m_reopen_file = true;
345 0 : }
346 :
347 : #ifndef WIN32
348 1161 : static void registerSignalHandler(int signal, void(*handler)(int))
349 : {
350 1161 : struct sigaction sa{};
351 1161 : sa.sa_handler = handler;
352 1161 : sigemptyset(&sa.sa_mask);
353 1161 : sa.sa_flags = 0;
354 1161 : sigaction(signal, &sa, nullptr);
355 1161 : }
356 : #endif
357 :
358 375 : void OnRPCStarted()
359 : {
360 750 : uiInterface.NotifyBlockTip.connect(RPCNotifyBlockChange);
361 375 : }
362 :
363 375 : void OnRPCStopped()
364 : {
365 375 : uiInterface.NotifyBlockTip.disconnect(RPCNotifyBlockChange);
366 : // TODO: remove unused parameter fInitialDownload
367 375 : RPCNotifyBlockChange(false, nullptr);
368 375 : g_best_block_cv.notify_all();
369 375 : LogPrint(BCLog::RPC, "RPC stopped.\n");
370 375 : }
371 :
372 298052 : void OnRPCPreCommand(const CRPCCommand& cmd)
373 : {
374 : // Observe safe mode
375 298052 : std::string strWarning = GetWarnings("rpc");
376 298052 : if (!strWarning.empty() && !gArgs.GetBoolArg("-disablesafemode", DEFAULT_DISABLE_SAFEMODE) &&
377 0 : !cmd.okSafeMode)
378 0 : throw JSONRPCError(RPC_FORBIDDEN_BY_SAFE_MODE, std::string("Safe mode: ") + strWarning);
379 298052 : }
380 :
381 1 : std::string HelpMessage(HelpMessageMode mode)
382 : {
383 1 : const auto defaultBaseParams = CreateBaseChainParams(CBaseChainParams::MAIN);
384 2 : const auto testnetBaseParams = CreateBaseChainParams(CBaseChainParams::TESTNET);
385 2 : const auto defaultChainParams = CreateChainParams(CBaseChainParams::MAIN);
386 2 : const auto testnetChainParams = CreateChainParams(CBaseChainParams::TESTNET);
387 1 : const bool showDebug = gArgs.GetBoolArg("-help-debug", false);
388 :
389 : // When adding new options to the categories, please keep and ensure alphabetical ordering.
390 1 : std::string strUsage = HelpMessageGroup("Options:");
391 3 : strUsage += HelpMessageOpt("-?", "This help message");
392 3 : strUsage += HelpMessageOpt("-version", "Print version and exit");
393 4 : strUsage += HelpMessageOpt("-alertnotify=<cmd>", "Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)");
394 4 : strUsage += HelpMessageOpt("-blocksdir=<dir>", "Specify directory to hold blocks subdirectory for *.dat files (default: <datadir>)");
395 4 : strUsage += HelpMessageOpt("-blocknotify=<cmd>", "Execute command when the best block changes (%s in cmd is replaced by block hash)");
396 4 : strUsage += HelpMessageOpt("-checkblocks=<n>", strprintf("How many blocks to check at startup (default: %u, 0 = all)", DEFAULT_CHECKBLOCKS));
397 3 : strUsage += HelpMessageOpt("-checklevel=<n>", strprintf("How thorough the block verification of -checkblocks is (0-4, default: %u)", DEFAULT_CHECKLEVEL));
398 :
399 3 : strUsage += HelpMessageOpt("-conf=<file>", strprintf("Specify configuration file (default: %s)", PIVX_CONF_FILENAME));
400 1 : if (mode == HMM_BITCOIND) {
401 : #if !defined(WIN32)
402 4 : strUsage += HelpMessageOpt("-daemon", "Run in the background as a daemon and accept commands");
403 : #endif
404 : }
405 3 : strUsage += HelpMessageOpt("-datadir=<dir>", "Specify data directory");
406 1 : if (showDebug) {
407 0 : strUsage += HelpMessageOpt("-dbbatchsize", strprintf("Maximum database write batch size in bytes (default: %u)", nDefaultDbBatchSize));
408 : }
409 4 : strUsage += HelpMessageOpt("-paramsdir=<dir>", strprintf("Specify zk params directory (default: %s)", ZC_GetParamsDir().string()));
410 4 : strUsage += HelpMessageOpt("-debuglogfile=<file>", strprintf("Specify location of debug log file: this can be an absolute path or a path relative to the data directory (default: %s)", DEFAULT_DEBUGLOGFILE));
411 4 : strUsage += HelpMessageOpt("-disablesystemnotifications", strprintf("Disable OS notifications for incoming transactions (default: %u)", 0));
412 3 : strUsage += HelpMessageOpt("-dbcache=<n>", strprintf("Set database cache size in megabytes (%d to %d, default: %d)", nMinDbCache, nMaxDbCache, nDefaultDbCache));
413 4 : strUsage += HelpMessageOpt("-loadblock=<file>", "Imports blocks from external blk000??.dat file on startup");
414 3 : strUsage += HelpMessageOpt("-maxreorg=<n>", strprintf("Set the Maximum reorg depth (default: %u)", DEFAULT_MAX_REORG_DEPTH));
415 4 : strUsage += HelpMessageOpt("-maxorphantx=<n>", strprintf("Keep at most <n> unconnectable transactions in memory (default: %u)", DEFAULT_MAX_ORPHAN_TRANSACTIONS));
416 3 : strUsage += HelpMessageOpt("-maxmempool=<n>", strprintf("Keep the transaction memory pool below <n> megabytes (default: %u)", DEFAULT_MAX_MEMPOOL_SIZE));
417 4 : strUsage += HelpMessageOpt("-mempoolexpiry=<n>", strprintf("Do not keep transactions in the mempool longer than <n> hours (default: %u)", DEFAULT_MEMPOOL_EXPIRY));
418 3 : strUsage += HelpMessageOpt("-persistmempool", strprintf("Whether to save the mempool on shutdown and load on restart (default: %u)", DEFAULT_PERSIST_MEMPOOL));
419 3 : strUsage += HelpMessageOpt("-par=<n>", strprintf("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)", -GetNumCores(), MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS));
420 : #ifndef WIN32
421 3 : strUsage += HelpMessageOpt("-pid=<file>", strprintf("Specify pid file (default: %s)", PIVX_PID_FILENAME));
422 : #endif
423 4 : strUsage += HelpMessageOpt("-reindex-chainstate", "Rebuild chain state from the currently indexed blocks");
424 3 : strUsage += HelpMessageOpt("-reindex", "Rebuild block chain index from current blk000??.dat files on startup");
425 3 : strUsage += HelpMessageOpt("-resync", "Delete blockchain folders and resync from scratch on startup");
426 : #if !defined(WIN32)
427 3 : strUsage += HelpMessageOpt("-sysperms", "Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)");
428 : #endif
429 3 : strUsage += HelpMessageOpt("-txindex", strprintf("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)", DEFAULT_TXINDEX));
430 3 : strUsage += HelpMessageOpt("-forcestart", "Attempt to force blockchain corruption recovery on startup");
431 :
432 3 : strUsage += HelpMessageGroup("Connection options:");
433 3 : strUsage += HelpMessageOpt("-addnode=<ip>", "Add a node to connect to and attempt to keep the connection open");
434 3 : strUsage += HelpMessageOpt("-asmap=<file>", strprintf("Specify asn mapping used for bucketing of the peers (default: %s). Relative paths will be prefixed by the net-specific datadir location.", DEFAULT_ASMAP_FILENAME));
435 3 : strUsage += HelpMessageOpt("-banscore=<n>", strprintf("Threshold for disconnecting misbehaving peers (default: %u)", DEFAULT_BANSCORE_THRESHOLD));
436 3 : strUsage += HelpMessageOpt("-bantime=<n>", strprintf("Number of seconds to keep misbehaving peers from reconnecting (default: %u)", DEFAULT_MISBEHAVING_BANTIME));
437 3 : strUsage += HelpMessageOpt("-bind=<addr>", "Bind to given address and always listen on it. Use [host]:port notation for IPv6");
438 3 : strUsage += HelpMessageOpt("-connect=<ip>", "Connect only to the specified node(s); -noconnect or -connect=0 alone to disable automatic connections");
439 3 : strUsage += HelpMessageOpt("-discover", "Discover own IP address (default: 1 when listening and no -externalip)");
440 3 : strUsage += HelpMessageOpt("-dns", strprintf("Allow DNS lookups for -addnode, -seednode and -connect (default: %u)", DEFAULT_NAME_LOOKUP));
441 3 : strUsage += HelpMessageOpt("-dnsseed", "Query for peer addresses via DNS lookup, if low on addresses (default: 1 unless -connect/-noconnect)");
442 4 : strUsage += HelpMessageOpt("-externalip=<ip>", "Specify your own public address");
443 3 : strUsage += HelpMessageOpt("-forcednsseed", strprintf("Always query for peer addresses via DNS lookup (default: %u)", DEFAULT_FORCEDNSSEED));
444 3 : strUsage += HelpMessageOpt("-listen", strprintf("Accept connections from outside (default: %u if no -proxy or -connect/-noconnect)", DEFAULT_LISTEN));
445 3 : strUsage += HelpMessageOpt("-listenonion", strprintf("Automatically create Tor hidden service (default: %d)", DEFAULT_LISTEN_ONION));
446 4 : strUsage += HelpMessageOpt("-maxconnections=<n>", strprintf("Maintain at most <n> connections to peers (default: %u)", DEFAULT_MAX_PEER_CONNECTIONS));
447 4 : strUsage += HelpMessageOpt("-maxreceivebuffer=<n>", strprintf("Maximum per-connection receive buffer, <n>*1000 bytes (default: %u)", DEFAULT_MAXRECEIVEBUFFER));
448 4 : strUsage += HelpMessageOpt("-maxsendbuffer=<n>", strprintf("Maximum per-connection send buffer, <n>*1000 bytes (default: %u)", DEFAULT_MAXSENDBUFFER));
449 4 : strUsage += HelpMessageOpt("-onion=<ip:port>", strprintf("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)", "-proxy"));
450 3 : strUsage += HelpMessageOpt("-onlynet=<net>", "Only connect to nodes in network <net> (ipv4, ipv6 or onion)");
451 4 : strUsage += HelpMessageOpt("-permitbaremultisig", strprintf("Relay non-P2SH multisig (default: %u)", DEFAULT_PERMIT_BAREMULTISIG));
452 4 : strUsage += HelpMessageOpt("-peerbloomfilters", strprintf("Support filtering of blocks and transaction with bloom filters (default: %u)", DEFAULT_PEERBLOOMFILTERS));
453 3 : strUsage += HelpMessageOpt("-port=<port>", strprintf("Listen for connections on <port> (default: %u or testnet: %u)", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort()));
454 4 : strUsage += HelpMessageOpt("-proxy=<ip:port>", "Connect through SOCKS5 proxy");
455 3 : strUsage += HelpMessageOpt("-proxyrandomize", strprintf("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)", DEFAULT_PROXYRANDOMIZE));
456 3 : strUsage += HelpMessageOpt("-seednode=<ip>", "Connect to a node to retrieve peer addresses, and disconnect");
457 3 : strUsage += HelpMessageOpt("-timeout=<n>", strprintf("Specify connection timeout in milliseconds (minimum: 1, default: %d)", DEFAULT_CONNECT_TIMEOUT));
458 4 : strUsage += HelpMessageOpt("-torcontrol=<ip>:<port>", strprintf("Tor control port to use if onion listening enabled (default: %s)", DEFAULT_TOR_CONTROL));
459 4 : strUsage += HelpMessageOpt("-torpassword=<pass>", "Tor control port password (default: empty)");
460 3 : strUsage += HelpMessageOpt("-upnp", strprintf("Use UPnP to map the listening port (default: %u)", DEFAULT_UPNP));
461 : #ifdef USE_NATPMP
462 3 : strUsage += HelpMessageOpt("-natpmp", strprintf("Use NAT-PMP to map the listening port (default: %s)", DEFAULT_NATPMP ? "1 when listening and no -proxy" : "0"));
463 : #endif // USE_NATPMP
464 4 : strUsage += HelpMessageOpt("-whitebind=<addr>", "Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6");
465 3 : strUsage += HelpMessageOpt("-whitelist=<netmask>", "Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times."
466 1 : " Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway");
467 :
468 : #if ENABLE_WALLET
469 2 : strUsage += GetWalletHelpString(showDebug);
470 : #endif
471 :
472 1 : if (mode == HMM_BITCOIN_QT) {
473 0 : strUsage += HelpMessageOpt("-windowtitle=<name>", "Wallet window title");
474 : }
475 :
476 : #if ENABLE_ZMQ
477 3 : strUsage += HelpMessageGroup("ZeroMQ notification options:");
478 4 : strUsage += HelpMessageOpt("-zmqpubhashblock=<address>", "Enable publish hash block in <address>");
479 4 : strUsage += HelpMessageOpt("-zmqpubhashtx=<address>", "Enable publish hash transaction in <address>");
480 4 : strUsage += HelpMessageOpt("-zmqpubrawblock=<address>", "Enable publish raw block in <address>");
481 4 : strUsage += HelpMessageOpt("-zmqpubrawtx=<address>", "Enable publish raw transaction in <address>");
482 : #endif
483 :
484 3 : strUsage += HelpMessageGroup("Debugging/Testing options:");
485 4 : strUsage += HelpMessageOpt("-uacomment=<cmt>", "Append comment to the user agent string");
486 1 : if (showDebug) {
487 0 : strUsage += HelpMessageOpt("-checkblockindex", strprintf("Do a full consistency check for mapBlockIndex, setBlockIndexCandidates, chainActive and mapBlocksUnlinked occasionally. Also sets -checkmempool (default: %u)", defaultChainParams->DefaultConsistencyChecks()));
488 0 : strUsage += HelpMessageOpt("-checkmempool=<n>", strprintf("Run checks every <n> transactions (default: %u)", defaultChainParams->DefaultConsistencyChecks()));
489 0 : strUsage += HelpMessageOpt("-checkpoints", strprintf("Only accept block chain matching built-in checkpoints (default: %u)", DEFAULT_CHECKPOINTS_ENABLED));
490 0 : strUsage += HelpMessageOpt("-disablesafemode", strprintf("Disable safemode, override a real safe mode event (default: %u)", DEFAULT_DISABLE_SAFEMODE));
491 0 : strUsage += HelpMessageOpt("-testsafemode", strprintf("Force safe mode (default: %u)", DEFAULT_TESTSAFEMODE));
492 0 : strUsage += HelpMessageOpt("-deprecatedrpc=<method>", "Allows deprecated RPC method(s) to be used");
493 0 : strUsage += HelpMessageOpt("-dropmessagestest=<n>", "Randomly drop 1 of every <n> network messages");
494 0 : strUsage += HelpMessageOpt("-fuzzmessagestest=<n>", "Randomly fuzz 1 of every <n> network messages");
495 0 : strUsage += HelpMessageOpt("-stopafterblockimport", strprintf("Stop running after importing blocks from disk (default: %u)", DEFAULT_STOPAFTERBLOCKIMPORT));
496 0 : strUsage += HelpMessageOpt("-limitancestorcount=<n>", strprintf("Do not accept transactions if number of in-mempool ancestors is <n> or more (default: %u)", DEFAULT_ANCESTOR_LIMIT));
497 0 : strUsage += HelpMessageOpt("-limitancestorsize=<n>", strprintf("Do not accept transactions whose size with all in-mempool ancestors exceeds <n> kilobytes (default: %u)", DEFAULT_ANCESTOR_SIZE_LIMIT));
498 0 : strUsage += HelpMessageOpt("-limitdescendantcount=<n>", strprintf("Do not accept transactions if any ancestor would have <n> or more in-mempool descendants (default: %u)", DEFAULT_DESCENDANT_LIMIT));
499 0 : strUsage += HelpMessageOpt("-limitdescendantsize=<n>", strprintf("Do not accept transactions if any ancestor would have more than <n> kilobytes of in-mempool descendants (default: %u).", DEFAULT_DESCENDANT_SIZE_LIMIT));
500 0 : strUsage += HelpMessageOpt("-sporkkey=<privkey>", "Enable spork administration functionality with the appropriate private key.");
501 0 : strUsage += HelpMessageOpt("-nuparams=upgradeName:activationHeight", "Use given activation height for specified network upgrade (regtest-only)");
502 : }
503 5 : strUsage += HelpMessageOpt("-debug=<category>", strprintf("Output debugging information (default: %u, supplying <category> is optional)", 0) + ". " +
504 4 : "If <category> is not supplied, output all debugging information. <category> can be: " + ListLogCategories() + ".");
505 4 : strUsage += HelpMessageOpt("-debugexclude=<category>", "Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories.");
506 1 : if (showDebug)
507 0 : strUsage += HelpMessageOpt("-nodebug", "Turn off debugging messages, same as -debug=0");
508 :
509 3 : strUsage += HelpMessageOpt("-help-debug", "Show all debugging options (usage: --help -help-debug)");
510 3 : strUsage += HelpMessageOpt("-logips", strprintf("Include IP addresses in debug output (default: %u)", DEFAULT_LOGIPS));
511 3 : strUsage += HelpMessageOpt("-logtimestamps", strprintf("Prepend debug output with timestamp (default: %u)", DEFAULT_LOGTIMESTAMPS));
512 3 : strUsage += HelpMessageOpt("-logtimemicros", strprintf("Add microsecond precision to debug timestamps (default: %u)", DEFAULT_LOGTIMEMICROS));
513 1 : if (showDebug) {
514 0 : strUsage += HelpMessageOpt("-mocktime=<n>", "Replace actual time with <n> seconds since epoch (default: 0)");
515 0 : strUsage += HelpMessageOpt("-maxsigcachesize=<n>", strprintf("Limit size of signature cache to <n> MiB (default: %u)", DEFAULT_MAX_SIG_CACHE_SIZE));
516 : }
517 3 : strUsage += HelpMessageOpt("-maxtipage=<n>", strprintf("Maximum tip age in seconds to consider node in initial block download (default: %u)", DEFAULT_MAX_TIP_AGE));
518 5 : strUsage += HelpMessageOpt("-minrelaytxfee=<amt>", strprintf("Fees (in %s/Kb) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)", CURRENCY_UNIT, FormatMoney(::minRelayTxFee.GetFeePerK())));
519 3 : strUsage += HelpMessageOpt("-printtoconsole", strprintf("Send trace/debug info to console instead of debug.log file (default: %u)", 0));
520 1 : if (showDebug) {
521 0 : strUsage += HelpMessageOpt("-dustrelayfee=<amt>", strprintf("Fee rate (in %s/kB) used to define dust, the value of an output such that it will cost more than its value in fees at this fee rate to spend it. (default: %s)", CURRENCY_UNIT, FormatMoney(DUST_RELAY_TX_FEE)));
522 0 : strUsage += HelpMessageOpt("-printpriority", strprintf("Log transaction fee per kB when mining blocks (default: %u)", DEFAULT_PRINTPRIORITY));
523 : }
524 4 : strUsage += HelpMessageOpt("-shrinkdebugfile", "Shrink debug.log file on client startup (default: 1 when no -debug)");
525 1 : AppendParamsHelpMessages(strUsage, showDebug);
526 :
527 2 : strUsage += GetTierTwoHelpString(showDebug);
528 :
529 3 : strUsage += HelpMessageGroup("Node relay options:");
530 1 : if (showDebug) {
531 0 : strUsage += HelpMessageOpt("-acceptnonstdtxn",
532 0 : strprintf("Relay and mine \"non-standard\" transactions (%sdefault: %u)",
533 : "testnet/regtest only; ",
534 0 : !CreateChainParams(CBaseChainParams::TESTNET)->RequireStandard()));
535 : }
536 3 : strUsage += HelpMessageOpt("-datacarrier", strprintf("Relay and mine data carrier transactions (default: %u)", DEFAULT_ACCEPT_DATACARRIER));
537 4 : strUsage += HelpMessageOpt("-datacarriersize", strprintf("Maximum size of data in data carrier transactions we relay and mine (default: %u)", MAX_OP_RETURN_RELAY));
538 1 : if (showDebug) {
539 0 : strUsage += HelpMessageOpt("-blockversion=<n>", "Override block version to test forking scenarios");
540 : }
541 :
542 3 : strUsage += HelpMessageGroup("Block creation options:");
543 4 : strUsage += HelpMessageOpt("-blockmaxsize=<n>", strprintf("Set maximum block size in bytes (default: %d)", DEFAULT_BLOCK_MAX_SIZE));
544 1 : if (showDebug)
545 0 : strUsage += HelpMessageOpt("-blockversion=<n>", "Override block version to test forking scenarios");
546 :
547 3 : strUsage += HelpMessageGroup("RPC server options:");
548 3 : strUsage += HelpMessageOpt("-server", "Accept command line and JSON-RPC commands");
549 3 : strUsage += HelpMessageOpt("-rest", strprintf("Accept public REST requests (default: %u)", DEFAULT_REST_ENABLE));
550 3 : strUsage += HelpMessageOpt("-rpcbind=<addr>", "Bind to given address to listen for JSON-RPC connections. Do not expose the RPC server to untrusted networks such as the public internet! This option is ignored unless -rpcallowip is also passed. Port is optional and overrides -rpcport. Use [host]:port notation for IPv6. This option can be specified multiple times (default: 127.0.0.1 and ::1 i.e., localhost)");
551 4 : strUsage += HelpMessageOpt("-rpccookiefile=<loc>", "Location of the auth cookie (default: data dir)");
552 3 : strUsage += HelpMessageOpt("-rpcuser=<user>", "Username for JSON-RPC connections");
553 4 : strUsage += HelpMessageOpt("-rpcpassword=<pw>", "Password for JSON-RPC connections");
554 4 : strUsage += HelpMessageOpt("-rpcauth=<userpw>", "Username and hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=<USERNAME>/rpcpassword=<PASSWORD> pair of arguments. This option can be specified multiple times");
555 3 : strUsage += HelpMessageOpt("-rpcport=<port>", strprintf("Listen for JSON-RPC connections on <port> (default: %u or testnet: %u)", defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort()));
556 4 : strUsage += HelpMessageOpt("-rpcallowip=<ip>", "Allow JSON-RPC connections from specified source. Valid for <ip> are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times");
557 3 : strUsage += HelpMessageOpt("-rpcthreads=<n>", strprintf("Set the number of threads to service RPC calls (default: %d)", DEFAULT_HTTP_THREADS));
558 1 : if (showDebug) {
559 0 : strUsage += HelpMessageOpt("-rpcworkqueue=<n>", strprintf("Set the depth of the work queue to service RPC calls (default: %d)", DEFAULT_HTTP_WORKQUEUE));
560 0 : strUsage += HelpMessageOpt("-rpcservertimeout=<n>", strprintf("Timeout during HTTP requests (default: %d)", DEFAULT_HTTP_SERVER_TIMEOUT));
561 : }
562 :
563 4 : strUsage += HelpMessageOpt("-blockspamfilter=<n>", strprintf("Use block spam filter (default: %u)", DEFAULT_BLOCK_SPAM_FILTER));
564 4 : strUsage += HelpMessageOpt("-blockspamfiltermaxsize=<n>", strprintf("Maximum size of the list of indexes in the block spam filter (default: %u)", DEFAULT_BLOCK_SPAM_FILTER_MAX_SIZE));
565 4 : strUsage += HelpMessageOpt("-blockspamfiltermaxavg=<n>", strprintf("Maximum average size of an index occurrence in the block spam filter (default: %u)", DEFAULT_BLOCK_SPAM_FILTER_MAX_AVG));
566 :
567 2 : return strUsage;
568 : }
569 :
570 1 : std::string LicenseInfo()
571 : {
572 4 : return FormatParagraph(strprintf(_("Copyright (C) 2009-%i The Bitcoin Core Developers"), COPYRIGHT_YEAR)) + "\n" +
573 2 : "\n" +
574 6 : FormatParagraph(strprintf(_("Copyright (C) 2014-%i The Dash Core Developers"), COPYRIGHT_YEAR)) + "\n" +
575 2 : "\n" +
576 6 : FormatParagraph(strprintf(_("Copyright (C) 2015-%i The %s Developers"), COPYRIGHT_YEAR, PACKAGE_NAME)) + "\n" +
577 2 : "\n" +
578 5 : FormatParagraph(_("This is experimental software.")) + "\n" +
579 2 : "\n" +
580 5 : FormatParagraph(_("Distributed under the MIT software license, see the accompanying file COPYING or <http://www.opensource.org/licenses/mit-license.php>.")) + "\n" +
581 2 : "\n" +
582 2 : FormatParagraph(_("This product includes UPnP software written by Thomas Bernard.")) +
583 2 : "\n";
584 : }
585 :
586 64 : static void BlockNotifyCallback(bool initialSync, const CBlockIndex *pBlockIndex)
587 : {
588 :
589 64 : if (initialSync || !pBlockIndex)
590 1 : return;
591 :
592 189 : std::string strCmd = gArgs.GetArg("-blocknotify", "");
593 :
594 63 : if (!strCmd.empty()) {
595 63 : boost::replace_all(strCmd, "%s", pBlockIndex->GetBlockHash().GetHex());
596 126 : std::thread t(runCommand, strCmd);
597 63 : t.detach(); // thread runs free
598 : }
599 : }
600 :
601 : ////////////////////////////////////////////////////
602 :
603 : static bool fHaveGenesis = false;
604 : static std::mutex cs_GenesisWait;
605 : static std::condition_variable condvar_GenesisWait;
606 :
607 200 : static void BlockNotifyGenesisWait(bool, const CBlockIndex *pBlockIndex)
608 : {
609 200 : if (pBlockIndex != nullptr) {
610 200 : {
611 200 : std::unique_lock<std::mutex> lock_GenesisWait(cs_GenesisWait);
612 200 : fHaveGenesis = true;
613 : }
614 200 : condvar_GenesisWait.notify_all();
615 : }
616 200 : }
617 :
618 : ////////////////////////////////////////////////////
619 :
620 :
621 : struct CImportingNow {
622 355 : CImportingNow()
623 : {
624 355 : assert(fImporting == false);
625 355 : fImporting = true;
626 355 : }
627 :
628 355 : ~CImportingNow()
629 : {
630 355 : assert(fImporting == true);
631 355 : fImporting = false;
632 355 : }
633 : };
634 :
635 355 : void ThreadImport(const std::vector<fs::path>& vImportFiles)
636 : {
637 355 : util::ThreadRename("pivx-loadblk");
638 355 : CImportingNow imp;
639 355 : ScheduleBatchPriority();
640 :
641 : // -reindex
642 355 : if (fReindex) {
643 : int nFile = 0;
644 15 : while (true) {
645 10 : FlatFilePos pos(nFile, 0);
646 30 : if (!fs::exists(GetBlockPosFilename(pos)))
647 : break; // No block files left to reindex
648 5 : FILE* file = OpenBlockFile(pos, true);
649 5 : if (!file)
650 : break; // This error is logged in OpenBlockFile
651 5 : LogPrintf("Reindexing block file blk%05u.dat...\n", (unsigned int)nFile);
652 5 : LoadExternalBlockFile(file, &pos);
653 5 : nFile++;
654 5 : }
655 5 : pblocktree->WriteReindexing(false);
656 5 : fReindex = false;
657 5 : LogPrintf("Reindexing finished\n");
658 : // To avoid ending up in a situation without genesis block, re-try initializing (no-op if reindexing worked):
659 5 : if (!LoadGenesisBlock()) {
660 0 : throw std::runtime_error("Error initializing block database");
661 : }
662 : }
663 :
664 : // hardcoded $DATADIR/bootstrap.dat
665 710 : fs::path pathBootstrap = GetDataDir() / "bootstrap.dat";
666 710 : if (fs::exists(pathBootstrap)) {
667 0 : FILE* file = fsbridge::fopen(pathBootstrap, "rb");
668 0 : if (file) {
669 0 : fs::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old";
670 0 : LogPrintf("Importing bootstrap.dat...\n");
671 0 : LoadExternalBlockFile(file);
672 0 : RenameOver(pathBootstrap, pathBootstrapOld);
673 : } else {
674 0 : LogPrintf("Warning: Could not open bootstrap file %s\n", pathBootstrap.string());
675 : }
676 : }
677 :
678 : // -loadblock=
679 355 : for (const fs::path& path : vImportFiles) {
680 0 : FILE* file = fsbridge::fopen(path, "rb");
681 0 : if (file) {
682 0 : LogPrintf("Importing blocks file %s...\n", path.string());
683 0 : LoadExternalBlockFile(file);
684 : } else {
685 0 : LogPrintf("Warning: Could not open blocks file %s\n", path.string());
686 : }
687 : }
688 :
689 710 : if (gArgs.GetBoolArg("-stopafterblockimport", DEFAULT_STOPAFTERBLOCKIMPORT)) {
690 0 : LogPrintf("Stopping after block import\n");
691 0 : StartShutdown();
692 : }
693 :
694 : // scan for better chains in the block chain database, that are not yet connected in the active best chain
695 710 : CValidationState state;
696 355 : if (!ActivateBestChain(state)) {
697 0 : LogPrintf("Failed to connect best block\n");
698 0 : StartShutdown();
699 : }
700 :
701 : // tier two
702 355 : InitTierTwoChainTip();
703 :
704 355 : if (gArgs.GetBoolArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
705 347 : LoadMempool(::mempool);
706 : }
707 355 : ::mempool.SetIsLoaded(!ShutdownRequested());
708 355 : }
709 :
710 : /** Sanity checks
711 : * Ensure that PIVX is running in a usable environment with all
712 : * necessary library support.
713 : */
714 379 : bool InitSanityCheck(void)
715 : {
716 379 : if (!ECC_InitSanityCheck()) {
717 0 : UIError(_("Elliptic curve cryptography sanity check failure. Aborting."));
718 0 : return false;
719 : }
720 :
721 379 : if (!glibc_sanity_test() || !glibcxx_sanity_test()) {
722 0 : return false;
723 : }
724 :
725 379 : if (!Random_SanityCheck()) {
726 0 : UIError(_("OS cryptographic RNG sanity check failure. Aborting."));
727 0 : return false;
728 : }
729 :
730 379 : if (!BLSInit()) {
731 0 : return false;
732 : }
733 :
734 : return true;
735 : }
736 :
737 376 : static void LoadSaplingParams()
738 : {
739 376 : struct timeval tv_start{}, tv_end{};
740 376 : float elapsed;
741 376 : gettimeofday(&tv_start, nullptr);
742 :
743 376 : try {
744 376 : initZKSNARKS();
745 0 : } catch (std::runtime_error &e) {
746 0 : std::string strError = strprintf(_("Cannot find the Sapling parameters in the following directory:\n%s"), ZC_GetParamsDir());
747 0 : std::string strErrorPosix = strprintf(_("Please run the included %s script and then restart."), "install-params.sh");
748 0 : std::string strErrorWin = strprintf(_("Please copy the included params files to the %s directory."), ZC_GetParamsDir());
749 0 : uiInterface.ThreadSafeMessageBox(strError + "\n"
750 : #ifndef WIN32
751 0 : + strErrorPosix,
752 : #else
753 : + strErrorWin,
754 : #endif
755 : "", CClientUIInterface::MSG_ERROR);
756 0 : StartShutdown();
757 0 : return;
758 : }
759 :
760 376 : gettimeofday(&tv_end, nullptr);
761 376 : elapsed = float(tv_end.tv_sec-tv_start.tv_sec) + (tv_end.tv_usec-tv_start.tv_usec)/float(1000000);
762 376 : LogPrintf("Loaded Sapling parameters in %fs seconds.\n", elapsed);
763 : }
764 :
765 375 : bool AppInitServers()
766 : {
767 375 : RPCServer::OnStarted(&OnRPCStarted);
768 375 : RPCServer::OnStopped(&OnRPCStopped);
769 375 : RPCServer::OnPreCommand(&OnRPCPreCommand);
770 375 : if (!InitHTTPServer())
771 : return false;
772 375 : if (!StartRPC())
773 : return false;
774 375 : if (!StartHTTPRPC())
775 : return false;
776 750 : if (gArgs.GetBoolArg("-rest", DEFAULT_REST_ENABLE) && !StartREST())
777 : return false;
778 375 : if (!StartHTTPServer())
779 0 : return false;
780 : return true;
781 : }
782 :
783 0 : [[noreturn]] static void new_handler_terminate()
784 : {
785 : // Rather than throwing std::bad-alloc if allocation fails, terminate
786 : // immediately to (try to) avoid chain corruption.
787 : // Since LogPrintf may itself allocate memory, set the handler directly
788 : // to terminate first.
789 0 : std::set_new_handler(std::terminate);
790 0 : LogPrintf("Error: Out of memory. Terminating.\n");
791 :
792 : // The log was successful, terminate now.
793 0 : std::terminate();
794 : }
795 :
796 : namespace { // Variables internal to initialization process only
797 :
798 : ServiceFlags nRelevantServices = NODE_NETWORK;
799 : int nMaxConnections;
800 : int nUserMaxConnections;
801 : int nFD;
802 : ServiceFlags nLocalServices = NODE_NETWORK;
803 : }
804 :
805 387 : bool AppInitBasicSetup()
806 : {
807 : // ********************************************************* Step 1: setup
808 : #ifdef _MSC_VER
809 : // Turn off Microsoft heap dump noise
810 : _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
811 : _CrtSetReportFile(_CRT_WARN, CreateFileA("NUL", GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, 0));
812 : #endif
813 : #if _MSC_VER >= 1400
814 : // Disable confusing "helpful" text message on abort, Ctrl-C
815 : _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
816 : #endif
817 : #ifdef WIN32
818 : // Enable Data Execution Prevention (DEP)
819 : // Minimum supported OS versions: WinXP SP3, WinVista >= SP1, Win Server 2008
820 : // A failure is non-critical and needs no further attention!
821 : #ifndef PROCESS_DEP_ENABLE
822 : // We define this here, because GCCs winbase.h limits this to _WIN32_WINNT >= 0x0601 (Windows 7),
823 : // which is not correct. Can be removed, when GCCs winbase.h is fixed!
824 : #define PROCESS_DEP_ENABLE 0x00000001
825 : #endif
826 : typedef BOOL(WINAPI * PSETPROCDEPPOL)(DWORD);
827 : PSETPROCDEPPOL setProcDEPPol = (PSETPROCDEPPOL)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "SetProcessDEPPolicy");
828 : if (setProcDEPPol != nullptr) setProcDEPPol(PROCESS_DEP_ENABLE);
829 : #endif
830 :
831 387 : if (!SetupNetworking())
832 0 : return UIError(_("Error: Initializing networking failed"));
833 :
834 : #ifndef WIN32
835 387 : if (!gArgs.GetBoolArg("-sysperms", false)) {
836 387 : umask(077);
837 : }
838 :
839 : // Clean shutdown on SIGTERMx
840 387 : registerSignalHandler(SIGTERM, HandleSIGTERM);
841 387 : registerSignalHandler(SIGINT, HandleSIGTERM);
842 :
843 : // Reopen debug.log on SIGHUP
844 387 : registerSignalHandler(SIGHUP, HandleSIGHUP);
845 :
846 : // Ignore SIGPIPE, otherwise it will bring the daemon down if the client closes unexpectedly
847 387 : signal(SIGPIPE, SIG_IGN);
848 : #endif
849 :
850 387 : std::set_new_handler(new_handler_terminate);
851 :
852 387 : return true;
853 : }
854 :
855 : // Parameter interaction based on rules
856 387 : void InitParameterInteraction()
857 : {
858 399 : if (gArgs.IsArgSet("-bind") || gArgs.IsArgSet("-whitebind")) {
859 : // when specifying an explicit binding address, you want to listen on it
860 : // even when -connect or -proxy is specified
861 375 : if (gArgs.SoftSetBoolArg("-listen", true))
862 349 : LogPrintf("%s : parameter interaction: -bind or -whitebind set -> setting -listen=1\n", __func__);
863 : }
864 :
865 387 : if (gArgs.IsArgSet("-connect")) {
866 : // when only connecting to trusted nodes, do not seed via DNS, or listen by default
867 0 : if (gArgs.SoftSetBoolArg("-dnsseed", false))
868 0 : LogPrintf("%s : parameter interaction: -connect set -> setting -dnsseed=0\n", __func__);
869 0 : if (gArgs.SoftSetBoolArg("-listen", false))
870 0 : LogPrintf("%s : parameter interaction: -connect set -> setting -listen=0\n", __func__);
871 : }
872 :
873 387 : if (gArgs.IsArgSet("-proxy")) {
874 : // to protect privacy, do not listen by default if a default proxy server is specified
875 4 : if (gArgs.SoftSetBoolArg("-listen", false))
876 0 : LogPrintf("%s: parameter interaction: -proxy set -> setting -listen=0\n", __func__);
877 : // to protect privacy, do not use map ports when a proxy is set. The user may still specify -listen=1
878 : // to listen locally, so don't rely on this happening through -listen below.
879 4 : if (gArgs.SoftSetBoolArg("-upnp", false))
880 4 : LogPrintf("%s: parameter interaction: -proxy set -> setting -upnp=0\n", __func__);
881 4 : if (gArgs.SoftSetBoolArg("-natpmp", false)) {
882 0 : LogPrintf("%s: parameter interaction: -proxy set -> setting -natpmp=0\n", __func__);
883 : }
884 : // to protect privacy, do not discover addresses by default
885 4 : if (gArgs.SoftSetBoolArg("-discover", false))
886 0 : LogPrintf("%s : parameter interaction: -proxy set -> setting -discover=0\n", __func__);
887 : }
888 :
889 387 : if (!gArgs.GetBoolArg("-listen", DEFAULT_LISTEN)) {
890 : // do not map ports or try to retrieve public IP when not listening (pointless)
891 10 : if (gArgs.SoftSetBoolArg("-upnp", false))
892 10 : LogPrintf("%s : parameter interaction: -listen=0 -> setting -upnp=0\n", __func__);
893 10 : if (gArgs.SoftSetBoolArg("-natpmp", false)) {
894 0 : LogPrintf("%s: parameter interaction: -listen=0 -> setting -natpmp=0\n", __func__);
895 : }
896 10 : if (gArgs.SoftSetBoolArg("-discover", false))
897 0 : LogPrintf("%s : parameter interaction: -listen=0 -> setting -discover=0\n", __func__);
898 10 : if (gArgs.SoftSetBoolArg("-listenonion", false))
899 0 : LogPrintf("%s : parameter interaction: -listen=0 -> setting -listenonion=0\n", __func__);
900 : }
901 :
902 387 : if (gArgs.IsArgSet("-externalip")) {
903 : // if an explicit public IP is specified, do not try to find others
904 22 : if (gArgs.SoftSetBoolArg("-discover", false))
905 0 : LogPrintf("%s : parameter interaction: -externalip set -> setting -discover=0\n", __func__);
906 : }
907 387 : }
908 :
909 379 : bool InitNUParams()
910 : {
911 379 : if (gArgs.IsArgSet("-nuparams")) {
912 : // Allow overriding network upgrade parameters for testing
913 136 : if (Params().NetworkIDString() != "regtest") {
914 0 : return UIError(_("Network upgrade parameters may only be overridden on regtest."));
915 : }
916 418 : for (const std::string& strDeployment : gArgs.GetArgs("-nuparams")) {
917 282 : std::vector<std::string> vDeploymentParams;
918 282 : boost::split(vDeploymentParams, strDeployment, boost::is_any_of(":"));
919 282 : if (vDeploymentParams.size() != 2) {
920 0 : return UIError(strprintf(_("Network upgrade parameters malformed, expecting %s"), "hexBranchId:activationHeight"));
921 : }
922 282 : int nActivationHeight;
923 282 : if (!ParseInt32(vDeploymentParams[1], &nActivationHeight)) {
924 0 : return UIError(strprintf(_("Invalid activation height (%s)"), vDeploymentParams[1]));
925 : }
926 2774 : bool found = false;
927 : // Exclude base network from upgrades
928 2774 : for (auto j = Consensus::BASE_NETWORK + 1; j < Consensus::MAX_NETWORK_UPGRADES; ++j) {
929 2774 : if (vDeploymentParams[0] == NetworkUpgradeInfo[j].strName) {
930 282 : UpdateNetworkUpgradeParameters(Consensus::UpgradeIndex(j), nActivationHeight);
931 282 : found = true;
932 282 : LogPrintf("Setting network upgrade activation parameters for %s to height=%d\n", vDeploymentParams[0], nActivationHeight);
933 : break;
934 : }
935 : }
936 282 : if (!found) {
937 0 : return UIError(strprintf(_("Invalid network upgrade (%s)"), vDeploymentParams[0]));
938 : }
939 : }
940 : }
941 : return true;
942 : }
943 :
944 0 : static std::string ResolveErrMsg(const char * const optname, const std::string& strBind)
945 : {
946 0 : return strprintf(_("Cannot resolve -%s address: '%s'"), optname, strBind);
947 : }
948 :
949 387 : void InitLogging()
950 : {
951 387 : g_logger->m_print_to_file = !gArgs.IsArgNegated("-debuglogfile");
952 780 : g_logger->m_file_path = AbsPathForConfigVal(gArgs.GetArg("-debuglogfile", DEFAULT_DEBUGLOGFILE));
953 :
954 : // Add newlines to the logfile to distinguish this execution from the last
955 : // one; called before console logging is set up, so this is only sent to
956 : // debug.log.
957 387 : LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
958 :
959 387 : g_logger->m_print_to_console = gArgs.GetBoolArg("-printtoconsole", !gArgs.GetBoolArg("-daemon", false));
960 387 : g_logger->m_log_timestamps = gArgs.GetBoolArg("-logtimestamps", DEFAULT_LOGTIMESTAMPS);
961 387 : g_logger->m_log_time_micros = gArgs.GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS);
962 :
963 387 : fLogIPs = gArgs.GetBoolArg("-logips", DEFAULT_LOGIPS);
964 :
965 387 : std::string version_string = FormatFullVersion();
966 : #ifdef DEBUG
967 : version_string += " (debug build)";
968 : #else
969 387 : version_string += " (release build)";
970 : #endif
971 387 : LogPrintf("PIVX version %s\n", version_string);
972 387 : }
973 :
974 387 : bool AppInitParameterInteraction()
975 : {
976 : // ********************************************************* Step 2: parameter interactions
977 :
978 387 : if (!fs::is_directory(GetBlocksDir())) {
979 4 : return UIError(strprintf(_("Specified blocks directory \"%s\" does not exist."), gArgs.GetArg("-blocksdir", "").c_str()));
980 : }
981 :
982 : // Make sure enough file descriptors are available
983 :
984 : // -bind and -whitebind can't be set when not listening
985 386 : size_t nUserBind =
986 1147 : (gArgs.IsArgSet("-bind") ? gArgs.GetArgs("-bind").size() : 0) +
987 386 : (gArgs.IsArgSet("-whitebind") ? gArgs.GetArgs("-whitebind").size() : 0);
988 1136 : if (nUserBind != 0 && !gArgs.GetBoolArg("-listen", DEFAULT_LISTEN)) {
989 0 : return UIError(strprintf(_("Cannot set %s or %s together with %s"), "-bind", "-whitebind", "-listen=0"));
990 : }
991 :
992 : // Make sure enough file descriptors are available
993 386 : int nBind = std::max(nUserBind, size_t(1));
994 386 : nUserMaxConnections = gArgs.GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS);
995 386 : nMaxConnections = std::max(nUserMaxConnections, 0);
996 :
997 : // Trim requested connection counts, to fit into system limitations
998 386 : nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS + MAX_ADDNODE_CONNECTIONS);
999 : #ifdef USE_POLL
1000 386 : int fd_max = nFD;
1001 : #else
1002 : int fd_max = FD_SETSIZE;
1003 : #endif
1004 386 : nMaxConnections = std::max(std::min<int>(nMaxConnections, fd_max - nBind - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS), 0);
1005 386 : if (nFD < MIN_CORE_FILEDESCRIPTORS)
1006 0 : return UIError(_("Not enough file descriptors available."));
1007 386 : nMaxConnections = std::min(nFD - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS, nMaxConnections);
1008 :
1009 : // ********************************************************* Step 3: parameter-to-internal-flags
1010 :
1011 : // Special-case: if -debug=0/-nodebug is set, turn off debugging messages
1012 772 : const std::vector<std::string>& categories = gArgs.GetArgs("-debug");
1013 :
1014 1158 : if (!(gArgs.GetBoolArg("-nodebug", false) ||
1015 772 : find(categories.begin(), categories.end(), std::string("0")) != categories.end())) {
1016 867 : for (const auto& cat : categories) {
1017 481 : if (!g_logger->EnableCategory(cat)) {
1018 0 : UIWarning(strprintf(_("Unsupported logging category %s=%s."), "-debug", cat));
1019 : }
1020 : }
1021 : }
1022 :
1023 : // Now remove the logging categories which were explicitly excluded
1024 1150 : for (const std::string& cat : gArgs.GetArgs("-debugexclude")) {
1025 764 : if (!g_logger->DisableCategory(cat)) {
1026 0 : UIWarning(strprintf(_("Unsupported logging category %s=%s."), "-debugexclude", cat));
1027 : }
1028 : }
1029 :
1030 : // Check for -debugnet
1031 386 : if (gArgs.GetBoolArg("-debugnet", false))
1032 0 : UIWarning(strprintf(_("Warning: Unsupported argument %s ignored, use %s."), "-debugnet", "-debug=net"));
1033 : // Check for -socks - as this is a privacy risk to continue, exit here
1034 386 : if (gArgs.IsArgSet("-socks"))
1035 0 : return UIError(
1036 0 : strprintf(_("Error: Unsupported argument %s found. Setting SOCKS version isn't possible anymore, only SOCKS5 proxies are supported."), "-socks"));
1037 : // Check for -tor - as this is a privacy risk to continue, exit here
1038 386 : if (gArgs.GetBoolArg("-tor", false))
1039 0 : return UIError(strprintf(_("Error: Unsupported argument %s found, use %s."), "-tor", "-onion"));
1040 : // Check level must be 4 for zerocoin checks
1041 386 : if (gArgs.IsArgSet("-checklevel"))
1042 0 : return UIError(strprintf(_("Error: Unsupported argument %s found. Checklevel must be level 4."), "-checklevel"));
1043 : // Exit early if -masternode=1 and -listen=0
1044 386 : if (gArgs.GetBoolArg("-masternode", DEFAULT_MASTERNODE) && !gArgs.GetBoolArg("-listen", DEFAULT_LISTEN))
1045 0 : return UIError(strprintf(_("Error: %s must be true if %s is set."), "-listen", "-masternode"));
1046 386 : if (gArgs.GetBoolArg("-benchmark", false))
1047 0 : UIWarning(strprintf(_("Warning: Unsupported argument %s ignored, use %s"), "-benchmark", "-debug=bench."));
1048 :
1049 : // Checkmempool and checkblockindex default to true in regtest mode
1050 386 : int ratio = std::min<int>(
1051 386 : std::max<int>(gArgs.GetArg("-checkmempool", Params().DefaultConsistencyChecks() ? 1 : 0), 0), 1000000);
1052 386 : if (ratio != 0) {
1053 382 : mempool.setSanityCheck(1.0 / ratio);
1054 : }
1055 386 : fCheckBlockIndex = gArgs.GetBoolArg("-checkblockindex", Params().DefaultConsistencyChecks());
1056 386 : Checkpoints::fEnabled = gArgs.GetBoolArg("-checkpoints", DEFAULT_CHECKPOINTS_ENABLED);
1057 :
1058 : // -mempoollimit limits
1059 386 : int64_t nMempoolSizeLimit = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
1060 386 : int64_t nMempoolDescendantSizeLimit = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) * 1000;
1061 386 : if (nMempoolSizeLimit < 0 || nMempoolSizeLimit < nMempoolDescendantSizeLimit * 40)
1062 0 : return UIError(strprintf(_("Error: %s must be at least %d MB"), "-maxmempool",
1063 0 : gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) / 25));
1064 :
1065 : // -par=0 means autodetect, but nScriptCheckThreads==0 means no concurrency
1066 386 : nScriptCheckThreads = gArgs.GetArg("-par", DEFAULT_SCRIPTCHECK_THREADS);
1067 386 : if (nScriptCheckThreads <= 0)
1068 386 : nScriptCheckThreads += GetNumCores();
1069 386 : if (nScriptCheckThreads <= 1)
1070 0 : nScriptCheckThreads = 0;
1071 386 : else if (nScriptCheckThreads > MAX_SCRIPTCHECK_THREADS)
1072 0 : nScriptCheckThreads = MAX_SCRIPTCHECK_THREADS;
1073 :
1074 386 : setvbuf(stdout, nullptr, _IOLBF, 0); /// ***TODO*** do we still need this after -printtoconsole is gone?
1075 :
1076 : #ifndef ENABLE_WALLET
1077 : if (gArgs.SoftSetBoolArg("-staking", false))
1078 : LogPrintf("AppInit2 : parameter interaction: wallet functionality not enabled -> setting -staking=0\n");
1079 : #endif
1080 :
1081 386 : nConnectTimeout = gArgs.GetArg("-timeout", DEFAULT_CONNECT_TIMEOUT);
1082 386 : if (nConnectTimeout <= 0)
1083 0 : nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
1084 :
1085 : // Fee-per-kilobyte amount required for mempool acceptance and relay
1086 : // If you are mining, be careful setting this:
1087 : // if you set it to zero then
1088 : // a transaction spammer can cheaply fill blocks using
1089 : // 0-fee transactions. It should be set above the real
1090 : // cost to you of processing a transaction.
1091 386 : if (gArgs.IsArgSet("-minrelaytxfee")) {
1092 8 : CAmount n = 0;
1093 8 : if (!ParseMoney(gArgs.GetArg("-minrelaytxfee", ""), n)) {
1094 0 : return UIError(AmountErrMsg("minrelaytxfee", gArgs.GetArg("-minrelaytxfee", "")));
1095 : }
1096 : // High fee check is done afterward in CWallet::ParameterInteraction()
1097 8 : ::minRelayTxFee = CFeeRate(n);
1098 : }
1099 :
1100 386 : const CChainParams& chainparams = Params();
1101 386 : fRequireStandard = !gArgs.GetBoolArg("-acceptnonstdtxn", !chainparams.RequireStandard());
1102 386 : if (!chainparams.IsTestChain() && !fRequireStandard)
1103 0 : return UIError(strprintf("%s is not currently supported for %s chain", "-acceptnonstdtxn", chainparams.NetworkIDString()));
1104 :
1105 : // Feerate used to define dust. Shouldn't be changed lightly as old
1106 : // implementations may inadvertently create non-standard transactions
1107 386 : if (gArgs.IsArgSet("-dustrelayfee")) {
1108 0 : CAmount n = 0;
1109 0 : if (!ParseMoney(gArgs.GetArg("-dustrelayfee", ""), n) || 0 == n)
1110 0 : return UIError(AmountErrMsg("dustrelayfee", gArgs.GetArg("-dustrelayfee", "")));
1111 0 : dustRelayFee = CFeeRate(n);
1112 : }
1113 :
1114 : #ifdef ENABLE_WALLET
1115 386 : if (!WalletParameterInteraction())
1116 : return false;
1117 : #endif // ENABLE_WALLET
1118 :
1119 379 : fIsBareMultisigStd = gArgs.GetBoolArg("-permitbaremultisig", DEFAULT_PERMIT_BAREMULTISIG);
1120 379 : nMaxDatacarrierBytes = gArgs.GetArg("-datacarriersize", nMaxDatacarrierBytes);
1121 :
1122 : // Option to startup with mocktime set (used for regression testing):
1123 379 : if (Params().IsRegTestNet()) {
1124 758 : SetMockTime(gArgs.GetArg("-mocktime", 0)); // SetMockTime(0) is a no-op
1125 : }
1126 :
1127 758 : if (gArgs.GetBoolArg("-peerbloomfilters", DEFAULT_PEERBLOOMFILTERS))
1128 378 : nLocalServices = ServiceFlags(nLocalServices | NODE_BLOOM);
1129 :
1130 379 : nMaxTipAge = gArgs.GetArg("-maxtipage", DEFAULT_MAX_TIP_AGE);
1131 :
1132 379 : if (!InitNUParams())
1133 0 : return false;
1134 :
1135 : return true;
1136 : }
1137 :
1138 757 : static bool LockDataDirectory(bool probeOnly)
1139 : {
1140 : // Make sure only a single PIVX process is using the data directory.
1141 1514 : fs::path datadir = GetDataDir();
1142 757 : if (!DirIsWritable(datadir)) {
1143 0 : return UIError(strprintf(_("Cannot write to data directory '%s'; check permissions."), datadir.string()));
1144 : }
1145 757 : if (!LockDirectory(datadir, ".lock", probeOnly)) {
1146 3 : return UIError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running."), datadir.string(), PACKAGE_NAME));
1147 : }
1148 : return true;
1149 : }
1150 :
1151 379 : bool AppInitSanityChecks()
1152 : {
1153 : // ********************************************************* Step 4: sanity checks
1154 :
1155 : // Initialize elliptic curve code
1156 379 : RandomInit();
1157 379 : ECC_Start();
1158 758 : globalVerifyHandle.reset(new ECCVerifyHandle());
1159 :
1160 : // Sanity check
1161 379 : if (!InitSanityCheck())
1162 0 : return UIError(strprintf(_("Initialization sanity check failed. %s is shutting down."), PACKAGE_NAME));
1163 :
1164 : // Probe the data directory lock to give an early error message, if possible
1165 379 : return LockDataDirectory(true);
1166 : }
1167 :
1168 378 : bool AppInitMain()
1169 : {
1170 : // ********************************************************* Step 4a: application initialization
1171 : // After daemonization get the data directory lock again and hold on to it until exit
1172 : // This creates a slight window for a race condition to happen, however this condition is harmless: it
1173 : // will at most make us exit without printing a message to console.
1174 378 : if (!LockDataDirectory(false)) {
1175 : // Detailed error printed inside LockDataDirectory
1176 : return false;
1177 : }
1178 :
1179 : #ifndef WIN32
1180 378 : if (!CreatePidFile()) {
1181 : // Detailed error printed inside CreatePidFile().
1182 : return false;
1183 : }
1184 : #endif
1185 378 : if (g_logger->m_print_to_file) {
1186 756 : if (gArgs.GetBoolArg("-shrinkdebugfile", g_logger->DefaultShrinkDebugFile()))
1187 4 : g_logger->ShrinkDebugFile();
1188 378 : if (!g_logger->OpenDebugLog())
1189 6 : return UIError(strprintf(_("Could not open debug log file %s"), g_logger->m_file_path.string()));
1190 : }
1191 : #ifdef ENABLE_WALLET
1192 376 : LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0));
1193 : #endif
1194 376 : if (!g_logger->m_log_timestamps)
1195 0 : LogPrintf("Startup time: %s\n", FormatISO8601DateTime(GetTime()));
1196 376 : LogPrintf("Default data directory %s\n", GetDefaultDataDir().string());
1197 376 : LogPrintf("Using data directory %s\n", GetDataDir().string());
1198 754 : LogPrintf("Using config file %s\n", GetConfigFile(gArgs.GetArg("-conf", PIVX_CONF_FILENAME)).string());
1199 376 : LogPrintf("Using at most %i automatic connections (%i file descriptors available)\n", nMaxConnections, nFD);
1200 376 : std::ostringstream strErrors;
1201 :
1202 : // Warn about relative -datadir path.
1203 2632 : if (gArgs.IsArgSet("-datadir") && !fs::path(gArgs.GetArg("-datadir", "")).is_absolute()) {
1204 0 : LogPrintf("Warning: relative datadir option '%s' specified, which will be interpreted relative to the " /* Continued */
1205 : "current working directory '%s'. This is fragile because if PIVX is started in the future " /* Continued */
1206 : "from a different location. It will be unable to locate the current data files. There could " /* Continued */
1207 : "also be data loss if PIVX is started while in a temporary directory.\n",
1208 0 : gArgs.GetArg("-datadir", ""), fs::current_path().string());
1209 : }
1210 :
1211 376 : InitSignatureCache();
1212 :
1213 376 : LogPrintf("Using %u threads for script verification\n", nScriptCheckThreads);
1214 376 : if (nScriptCheckThreads) {
1215 3008 : for (int i = 0; i < nScriptCheckThreads - 1; i++)
1216 2632 : threadGroup.create_thread(&ThreadScriptCheck);
1217 : }
1218 :
1219 376 : if (gArgs.IsArgSet("-sporkkey")) // spork priv key
1220 : {
1221 170 : if (!sporkManager.SetPrivKey(gArgs.GetArg("-sporkkey", "")))
1222 0 : return UIError(_("Unable to sign spork message, wrong key?"));
1223 : }
1224 :
1225 : // Start the lightweight task scheduler thread
1226 752 : CScheduler::Function serviceLoop = std::bind(&CScheduler::serviceQueue, &scheduler);
1227 376 : threadGroup.create_thread(std::bind(&TraceThread<CScheduler::Function>, "scheduler", serviceLoop));
1228 :
1229 : // Gather some entropy once per minute.
1230 376 : scheduler.scheduleEvery([]{
1231 231 : RandAddPeriodic();
1232 : }, 60000);
1233 :
1234 376 : GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
1235 :
1236 : // Initialize Sapling circuit parameters
1237 376 : LoadSaplingParams();
1238 :
1239 : /* Register RPC commands regardless of -server setting so they will be
1240 : * available in the GUI RPC console even if external calls are disabled.
1241 : */
1242 376 : RegisterAllCoreRPCCommands(tableRPC);
1243 : #ifdef ENABLE_WALLET
1244 376 : RegisterWalletRPCCommands(tableRPC);
1245 : #endif
1246 :
1247 : /* Start the RPC server already. It will be started in "warmup" mode
1248 : * and not really process calls already (but it will signify connections
1249 : * that the server is there and will be ready later). Warmup mode will
1250 : * be disabled when initialisation is finished.
1251 : */
1252 376 : if (gArgs.GetBoolArg("-server", false)) {
1253 750 : uiInterface.InitMessage.connect(SetRPCWarmupStatus);
1254 375 : if (!AppInitServers())
1255 0 : return UIError(_("Unable to start HTTP server. See debug log for details."));
1256 : }
1257 :
1258 376 : if (gArgs.GetBoolArg("-resync", false)) {
1259 0 : uiInterface.InitMessage(_("Preparing for resync..."));
1260 : // Delete the local blockchain folders to force a resync from scratch to get a consistent blockchain-state
1261 0 : fs::path blocksDir = GetBlocksDir();
1262 0 : fs::path chainstateDir = GetDataDir() / "chainstate";
1263 0 : fs::path sporksDir = GetDataDir() / "sporks";
1264 0 : fs::path zerocoinDir = GetDataDir() / "zerocoin";
1265 0 : fs::path evoDir = GetDataDir() / "evodb";
1266 :
1267 0 : LogPrintf("Deleting blockchain folders blocks, chainstate, sporks, zerocoin and evodb\n");
1268 0 : std::vector<fs::path> removeDirs{blocksDir, chainstateDir, sporksDir, zerocoinDir, evoDir};
1269 : // We delete in 5 individual steps in case one of the folder is missing already
1270 0 : try {
1271 0 : for (const auto& dir : removeDirs) {
1272 0 : if (fs::exists(dir)) {
1273 0 : fs::remove_all(dir);
1274 0 : LogPrintf("-resync: folder deleted: %s\n", dir.string().c_str());
1275 : }
1276 : }
1277 0 : } catch (const fs::filesystem_error& error) {
1278 0 : LogPrintf("Failed to delete blockchain folders %s\n", error.what());
1279 : }
1280 : }
1281 :
1282 : // ********************************************************* Step 5: Verify wallet database integrity
1283 : #ifdef ENABLE_WALLET
1284 376 : if (!WalletVerify()) {
1285 : return false;
1286 : }
1287 : #endif
1288 :
1289 : // ********************************************************* Step 6: network initialization
1290 : // Note that we absolutely cannot open any actual connections
1291 : // until the very end ("start node") as the UTXO/block state
1292 : // is not yet setup and may end up being set up twice if we
1293 : // need to reindex later.
1294 :
1295 366 : assert(!g_connman);
1296 734 : g_connman = std::make_unique<CConnman>(GetRand(std::numeric_limits<uint64_t>::max()), GetRand(std::numeric_limits<uint64_t>::max()));
1297 366 : CConnman& connman = *g_connman;
1298 :
1299 366 : peerLogic.reset(new PeerLogicValidation(&connman));
1300 366 : RegisterValidationInterface(peerLogic.get());
1301 :
1302 : // sanitize comments per BIP-0014, format user agent and check total size
1303 366 : std::vector<std::string> uacomments;
1304 730 : for (const std::string& cmt : gArgs.GetArgs("-uacomment")) {
1305 371 : if (cmt != SanitizeString(cmt, SAFE_CHARS_UA_COMMENT))
1306 18 : return UIError(strprintf(_("User Agent comment (%s) contains unsafe characters."), cmt));
1307 364 : uacomments.push_back(cmt);
1308 : }
1309 :
1310 : // format user agent, check total size
1311 360 : strSubVersion = FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, uacomments);
1312 360 : if (strSubVersion.size() > MAX_SUBVERSION_LENGTH) {
1313 2 : return UIError(strprintf(_("Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of %s."),
1314 3 : strSubVersion.size(), MAX_SUBVERSION_LENGTH, "-uacomment"));
1315 : }
1316 :
1317 359 : if (gArgs.IsArgSet("-onlynet")) {
1318 0 : std::set<enum Network> nets;
1319 0 : for (const std::string& snet : gArgs.GetArgs("-onlynet")) {
1320 0 : enum Network net = ParseNetwork(snet);
1321 0 : if (net == NET_UNROUTABLE)
1322 0 : return UIError(strprintf(_("Unknown network specified in %s: '%s'"), "-onlynet", snet));
1323 0 : nets.insert(net);
1324 : }
1325 0 : for (int n = 0; n < NET_MAX; n++) {
1326 0 : enum Network net = (enum Network)n;
1327 0 : if (!nets.count(net))
1328 0 : SetReachable(net, false);
1329 : }
1330 : }
1331 :
1332 : // Check for host lookup allowed before parsing any network related parameters
1333 359 : fNameLookup = gArgs.GetBoolArg("-dns", DEFAULT_NAME_LOOKUP);
1334 :
1335 359 : bool proxyRandomize = gArgs.GetBoolArg("-proxyrandomize", DEFAULT_PROXYRANDOMIZE);
1336 : // -proxy sets a proxy for all outgoing network traffic
1337 : // -noproxy (or -proxy=0) as well as the empty string can be used to not set a proxy, this is the default
1338 1084 : std::string proxyArg = gArgs.GetArg("-proxy", "");
1339 359 : SetReachable(NET_ONION, false);
1340 363 : if (!proxyArg.empty() && proxyArg != "0") {
1341 8 : CService proxyAddr;
1342 4 : if (!Lookup(proxyArg, proxyAddr, 9050, fNameLookup)) {
1343 0 : return UIError(strprintf(_("%s Invalid %s address or hostname: '%s'"), "Lookup():", "-proxy", proxyArg));
1344 : }
1345 :
1346 8 : proxyType addrProxy = proxyType(proxyAddr, proxyRandomize);
1347 4 : if (!addrProxy.IsValid())
1348 0 : return UIError(strprintf(_("%s Invalid %s address or hostname: '%s'"), "isValid():", "-proxy", proxyArg));
1349 :
1350 4 : SetProxy(NET_IPV4, addrProxy);
1351 4 : SetProxy(NET_IPV6, addrProxy);
1352 4 : SetProxy(NET_ONION, addrProxy);
1353 4 : SetNameProxy(addrProxy);
1354 4 : SetReachable(NET_ONION, true); // by default, -proxy sets onion as reachable, unless -noonion later
1355 : }
1356 :
1357 : // -onion can be used to set only a proxy for .onion, or override normal proxy for .onion addresses
1358 : // -noonion (or -onion=0) disables connecting to .onion entirely
1359 : // An empty string is used to not override the onion proxy (in which case it defaults to -proxy set above, or none)
1360 1077 : std::string onionArg = gArgs.GetArg("-onion", "");
1361 359 : if (!onionArg.empty()) {
1362 2 : if (onionArg == "0") { // Handle -noonion/-onion=0
1363 1 : SetReachable(NET_ONION, false);
1364 : } else {
1365 2 : CService onionProxy;
1366 1 : if (!Lookup(onionArg, onionProxy, 9050, fNameLookup)) {
1367 0 : return UIError(strprintf(_("%s Invalid %s address or hostname: '%s'"), "Lookup():", "-onion", onionArg));
1368 : }
1369 2 : proxyType addrOnion = proxyType(onionProxy, proxyRandomize);
1370 1 : if (!addrOnion.IsValid())
1371 0 : return UIError(strprintf(_("%s Invalid %s address or hostname: '%s'"), "isValid():", "-onion", onionArg));
1372 1 : SetProxy(NET_ONION, addrOnion);
1373 1 : SetReachable(NET_ONION, true);
1374 : }
1375 : }
1376 :
1377 : // see Step 2: parameter interactions for more information about these
1378 359 : fListen = gArgs.GetBoolArg("-listen", DEFAULT_LISTEN);
1379 359 : fDiscover = gArgs.GetBoolArg("-discover", true);
1380 :
1381 435 : for (const std::string& strAddr : gArgs.GetArgs("-externalip")) {
1382 152 : CService addrLocal;
1383 76 : if (Lookup(strAddr, addrLocal, GetListenPort(), fNameLookup) && addrLocal.IsValid())
1384 76 : AddLocal(addrLocal, LOCAL_MANUAL);
1385 : else
1386 0 : return UIError(ResolveErrMsg("externalip", strAddr));
1387 : }
1388 :
1389 : // Read asmap file if configured
1390 359 : if (gArgs.IsArgSet("-asmap")) {
1391 17 : fs::path asmap_path = fs::path(gArgs.GetArg("-asmap", ""));
1392 6 : if (asmap_path.empty()) {
1393 4 : asmap_path = DEFAULT_ASMAP_FILENAME;
1394 : }
1395 6 : if (!asmap_path.is_absolute()) {
1396 10 : asmap_path = GetDataDir() / asmap_path;
1397 : }
1398 7 : if (!fs::exists(asmap_path)) {
1399 2 : UIError(strprintf(_("Could not find asmap file %s"), asmap_path));
1400 3 : return false;
1401 : }
1402 14 : std::vector<bool> asmap = CAddrMan::DecodeAsmap(asmap_path);
1403 5 : if (asmap.size() == 0) {
1404 2 : UIError(strprintf(_("Could not parse asmap file %s"), asmap_path));
1405 3 : return false;
1406 : }
1407 4 : const uint256 asmap_version = SerializeHash(asmap);
1408 4 : connman.SetAsmap(std::move(asmap));
1409 8 : LogPrintf("Using asmap version %s for IP bucketing\n", asmap_version.ToString());
1410 : } else {
1411 353 : LogPrintf("Using /16 prefix for IP bucketing\n");
1412 : }
1413 :
1414 : // Warn if network-specific options (-addnode, -connect, etc) are
1415 : // specified in default section of config file, but not overridden
1416 : // on the command line or in this network's section of the config file.
1417 357 : gArgs.WarnForSectionOnlyArgs();
1418 :
1419 : #if ENABLE_ZMQ
1420 357 : pzmqNotificationInterface = CZMQNotificationInterface::Create();
1421 :
1422 357 : if (pzmqNotificationInterface) {
1423 1 : RegisterValidationInterface(pzmqNotificationInterface);
1424 : }
1425 : #endif
1426 :
1427 357 : InitTierTwoInterfaces();
1428 :
1429 : // ********************************************************* Step 7: load block chain
1430 :
1431 357 : fReindex = gArgs.GetBoolArg("-reindex", false);
1432 357 : bool fReindexChainState = gArgs.GetBoolArg("-reindex-chainstate", false);
1433 :
1434 : // cache size calculations
1435 357 : int64_t nTotalCache = (gArgs.GetArg("-dbcache", nDefaultDbCache) << 20);
1436 357 : nTotalCache = std::max(nTotalCache, nMinDbCache << 20); // total cache cannot be less than nMinDbCache
1437 357 : nTotalCache = std::min(nTotalCache, nMaxDbCache << 20); // total cache cannot be greater than nMaxDbcache
1438 357 : int64_t nBlockTreeDBCache = nTotalCache / 8;
1439 357 : nBlockTreeDBCache = std::min(nBlockTreeDBCache, (gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX) ? nMaxBlockDBAndTxIndexCache : nMaxBlockDBCache) << 20);
1440 357 : nTotalCache -= nBlockTreeDBCache;
1441 357 : int64_t nCoinDBCache = std::min(nTotalCache / 2, (nTotalCache / 4) + (1 << 23)); // use 25%-50% of the remainder for disk cache
1442 357 : nCoinDBCache = std::min(nCoinDBCache, nMaxCoinsDBCache << 20); // cap total coins db cache
1443 357 : nTotalCache -= nCoinDBCache;
1444 357 : nCoinCacheUsage = nTotalCache; // the rest goes to in-memory cache
1445 357 : LogPrintf("Cache configuration:\n");
1446 357 : LogPrintf("* Using %.1fMiB for block index database\n", nBlockTreeDBCache * (1.0 / 1024 / 1024));
1447 357 : LogPrintf("* Using %.1fMiB for chain state database\n", nCoinDBCache * (1.0 / 1024 / 1024));
1448 357 : LogPrintf("* Using %.1fMiB for in-memory UTXO set\n", nCoinCacheUsage * (1.0 / 1024 / 1024));
1449 :
1450 357 : const CChainParams& chainparams = Params();
1451 357 : const Consensus::Params& consensus = chainparams.GetConsensus();
1452 :
1453 357 : bool fLoaded = false;
1454 713 : while (!fLoaded && !ShutdownRequested()) {
1455 357 : bool fReset = fReindex;
1456 713 : std::string strLoadError;
1457 :
1458 713 : LOCK(cs_main);
1459 :
1460 357 : do {
1461 357 : const int64_t load_block_index_start_time = GetTimeMillis();
1462 :
1463 357 : try {
1464 357 : UnloadBlockIndex();
1465 357 : pcoinsTip.reset();
1466 357 : pcoinsdbview.reset();
1467 357 : pcoinscatcher.reset();
1468 357 : pblocktree.reset(new CBlockTreeDB(nBlockTreeDBCache, false, fReset));
1469 :
1470 : //PIVX specific: zerocoin and spork DB's
1471 357 : zerocoinDB.reset(new CZerocoinDB(0, false, fReindex));
1472 357 : pSporkDB.reset(new CSporkDB(0, false, false));
1473 357 : accumulatorCache.reset(new AccumulatorCache(zerocoinDB.get()));
1474 :
1475 357 : InitTierTwoPreChainLoad(fReindex);
1476 :
1477 357 : if (fReset) {
1478 5 : pblocktree->WriteReindexing(true);
1479 : }
1480 :
1481 : // End loop if shutdown was requested
1482 357 : if (ShutdownRequested()) break;
1483 :
1484 : // PIVX: load previous sessions sporks if we have them.
1485 357 : uiInterface.InitMessage(_("Loading sporks..."));
1486 357 : sporkManager.LoadSporksFromDB();
1487 :
1488 : // LoadBlockIndex will load fTxIndex from the db, or set it if
1489 : // we're reindexing. It will also load fHavePruned if we've
1490 : // ever removed a block file from disk.
1491 : // Note that it also sets fReindex based on the disk flag!
1492 : // From here on out fReindex and fReset mean something different!
1493 357 : uiInterface.InitMessage(_("Loading block index..."));
1494 357 : std::string strBlockIndexError;
1495 357 : if (!LoadBlockIndex(strBlockIndexError)) {
1496 0 : if (ShutdownRequested()) break;
1497 0 : strLoadError = _("Error loading block database");
1498 0 : strLoadError = strprintf("%s : %s", strLoadError, strBlockIndexError);
1499 0 : break;
1500 : }
1501 :
1502 : // If the loaded chain has a wrong genesis, bail out immediately
1503 : // (we're likely using a testnet datadir, or the other way around).
1504 357 : if (!mapBlockIndex.empty() && !LookupBlockIndex(consensus.hashGenesisBlock)) {
1505 0 : return UIError(_("Incorrect or no genesis block found. Wrong datadir for network?"));
1506 : }
1507 :
1508 : // Check for changed -txindex state
1509 357 : if (fTxIndex != gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
1510 0 : strLoadError = strprintf(_("You need to rebuild the database using %s to change %s"), "-reindex-chainstate", "-txindex");
1511 0 : break;
1512 : }
1513 :
1514 : // At this point blocktree args are consistent with what's on disk.
1515 : // If we're not mid-reindex (based on disk + args), add a genesis block on disk.
1516 : // This is called again in ThreadImport in the reindex completes.
1517 357 : if (!fReindex && !LoadGenesisBlock()) {
1518 0 : strLoadError = _("Error initializing block database");
1519 0 : break;
1520 : }
1521 :
1522 : // At this point we're either in reindex or we've loaded a useful
1523 : // block tree into mapBlockIndex!
1524 :
1525 357 : pcoinsdbview.reset(new CCoinsViewDB(nCoinDBCache, false, fReset || fReindexChainState));
1526 357 : pcoinscatcher.reset(new CCoinsViewErrorCatcher(pcoinsdbview.get()));
1527 :
1528 : // If necessary, upgrade from older database format.
1529 : // This is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate
1530 357 : uiInterface.InitMessage(_("Upgrading coins database if needed..."));
1531 : // If necessary, upgrade from older database format.
1532 357 : if (!pcoinsdbview->Upgrade()) {
1533 0 : strLoadError = _("Error upgrading chainstate database");
1534 0 : break;
1535 : }
1536 :
1537 : // ReplayBlocks is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate
1538 357 : if (!ReplayBlocks(chainparams, pcoinsdbview.get())) {
1539 0 : strLoadError = strprintf(_("Unable to replay blocks. You will need to rebuild the database using %s."), "-reindex");
1540 0 : break;
1541 : }
1542 :
1543 : // The on-disk coinsdb is now in a good state, create the cache
1544 357 : pcoinsTip.reset(new CCoinsViewCache(pcoinscatcher.get()));
1545 :
1546 357 : InitTierTwoPostCoinsCacheLoad(&scheduler);
1547 :
1548 707 : bool is_coinsview_empty = fReset || fReindexChainState || pcoinsTip->GetBestBlock().IsNull();
1549 200 : if (!is_coinsview_empty) {
1550 : // LoadChainTip sets chainActive based on pcoinsTip's best block
1551 157 : if (!LoadChainTip(chainparams)) {
1552 0 : strLoadError = _("Error initializing block database");
1553 0 : break;
1554 : }
1555 157 : assert(chainActive.Tip() != nullptr);
1556 : }
1557 :
1558 714 : if (Params().NetworkIDString() == CBaseChainParams::MAIN) {
1559 : // Prune zerocoin invalid outs if they were improperly stored in the coins database
1560 0 : int chainHeight = chainActive.Height();
1561 0 : bool fZerocoinActive = chainHeight > 0 && consensus.NetworkUpgradeActive(chainHeight, Consensus::UPGRADE_ZC);
1562 :
1563 0 : uiInterface.InitMessage(_("Loading/Pruning invalid outputs..."));
1564 0 : if (fZerocoinActive) {
1565 0 : if (!pcoinsTip->PruneInvalidEntries()) {
1566 0 : strLoadError = _("System error while flushing the chainstate after pruning invalid entries. Possible corrupt database.");
1567 0 : break;
1568 : }
1569 0 : MoneySupply.Update(pcoinsTip->GetTotalAmount(), chainHeight);
1570 : // No need to keep the invalid outs in memory. Clear the map 100 blocks after the last invalid UTXO
1571 0 : if (chainHeight > consensus.height_last_invalid_UTXO + 100) {
1572 0 : invalid_out::setInvalidOutPoints.clear();
1573 : }
1574 : } else {
1575 : // Populate list of invalid/fraudulent outpoints that are banned from the chain
1576 : // They will not be added to coins view
1577 0 : invalid_out::LoadOutpoints();
1578 : }
1579 : }
1580 :
1581 357 : if (!is_coinsview_empty) {
1582 157 : uiInterface.InitMessage(_("Verifying blocks..."));
1583 157 : CBlockIndex *tip = chainActive.Tip();
1584 157 : RPCNotifyBlockChange(true, tip);
1585 157 : if (tip && tip->nTime > GetAdjustedTime() + 2 * 60 * 60) {
1586 0 : strLoadError = _("The block database contains a block which appears to be from the future. "
1587 : "This may be due to your computer's date and time being set incorrectly. "
1588 0 : "Only rebuild the block database if you are sure that your computer's date and time are correct");
1589 0 : break;
1590 : }
1591 :
1592 471 : if (!CVerifyDB().VerifyDB(pcoinsdbview.get(), gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL),
1593 314 : gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS))) {
1594 1 : strLoadError = _("Corrupted block database detected");
1595 1 : break;
1596 : }
1597 : }
1598 0 : } catch (const std::exception& e) {
1599 0 : LogPrintf("%s\n", e.what());
1600 0 : strLoadError = _("Error opening block database");
1601 0 : break;
1602 : }
1603 :
1604 356 : fLoaded = true;
1605 356 : LogPrintf(" block index %15dms\n", GetTimeMillis() - load_block_index_start_time);
1606 : } while (false);
1607 :
1608 357 : if (!fLoaded && !ShutdownRequested()) {
1609 : // first suggest a reindex
1610 1 : if (!fReset) {
1611 2 : bool fRet = uiInterface.ThreadSafeMessageBox(
1612 3 : strLoadError + ".\n\n" + _("Do you want to rebuild the block database now?"),
1613 : "", CClientUIInterface::MSG_ERROR | CClientUIInterface::BTN_ABORT);
1614 1 : if (fRet) {
1615 0 : fReindex = true;
1616 0 : AbortShutdown();
1617 : } else {
1618 1 : LogPrintf("Aborted block database rebuild. Exiting.\n");
1619 : return false;
1620 : }
1621 : } else {
1622 0 : return UIError(strLoadError);
1623 : }
1624 : }
1625 : }
1626 :
1627 : // As LoadBlockIndex can take several minutes, it's possible the user
1628 : // requested to kill the GUI during the last operation. If so, exit.
1629 : // As the program has not fully started yet, Shutdown() is possibly overkill.
1630 356 : if (ShutdownRequested()) {
1631 0 : LogPrintf("Shutdown requested. Exiting.\n");
1632 : return false;
1633 : }
1634 :
1635 715 : fs::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
1636 712 : CAutoFile est_filein(fsbridge::fopen(est_path, "rb"), SER_DISK, CLIENT_VERSION);
1637 : // Allowed to fail as this file IS missing on first startup.
1638 356 : if (!est_filein.IsNull())
1639 84 : mempool.ReadFeeEstimates(est_filein);
1640 356 : fFeeEstimatesInitialized = true;
1641 :
1642 : // ********************************************************* Step 8: Backup and Load wallet
1643 : #ifdef ENABLE_WALLET
1644 356 : if (!InitLoadWallet())
1645 : return false;
1646 : #else
1647 : LogPrintf("No wallet compiled in!\n");
1648 : #endif
1649 : // ********************************************************* Step 9: import blocks
1650 :
1651 355 : if (!CheckDiskSpace(GetDataDir())) {
1652 0 : UIError(strprintf(_("Error: Disk space is low for %s"), GetDataDir()));
1653 0 : return false;
1654 : }
1655 355 : if (!CheckDiskSpace(GetBlocksDir())) {
1656 0 : UIError(strprintf(_("Error: Disk space is low for %s"), GetBlocksDir()));
1657 0 : return false;
1658 : }
1659 :
1660 : // Either install a handler to notify us when genesis activates, or set fHaveGenesis directly.
1661 : // No locking, as this happens before any background thread is started.
1662 355 : if (chainActive.Tip() == nullptr) {
1663 400 : uiInterface.NotifyBlockTip.connect(BlockNotifyGenesisWait);
1664 : } else {
1665 155 : fHaveGenesis = true;
1666 : }
1667 :
1668 355 : if (gArgs.IsArgSet("-blocknotify"))
1669 3 : uiInterface.NotifyBlockTip.connect(BlockNotifyCallback);
1670 :
1671 : // update g_best_block if needed
1672 355 : {
1673 355 : LOCK(g_best_block_mutex);
1674 12225 : if (g_best_block.IsNull() && chainActive.Tip()) {
1675 155 : CBlockIndex* tip = chainActive.Tip();
1676 155 : g_best_block = tip->GetBlockHash();
1677 155 : g_best_block_time = tip->GetBlockTime();
1678 155 : g_best_block_cv.notify_all();
1679 : }
1680 : }
1681 :
1682 710 : std::vector<fs::path> vImportFiles;
1683 355 : for (const std::string& strFile : gArgs.GetArgs("-loadblock")) {
1684 0 : vImportFiles.emplace_back(strFile);
1685 : }
1686 710 : threadGroup.create_thread(std::bind(&ThreadImport, vImportFiles));
1687 :
1688 : // Wait for genesis block to be processed
1689 355 : LogPrintf("Waiting for genesis block to be imported...\n");
1690 355 : {
1691 355 : std::unique_lock<std::mutex> lockG(cs_GenesisWait);
1692 : // We previously could hang here if StartShutdown() is called prior to
1693 : // ThreadImport getting started, so instead we just wait on a timer to
1694 : // check ShutdownRequested() regularly.
1695 555 : while (!fHaveGenesis && !ShutdownRequested()) {
1696 200 : condvar_GenesisWait.wait_for(lockG, std::chrono::milliseconds(500));
1697 : }
1698 355 : uiInterface.NotifyBlockTip.disconnect(BlockNotifyGenesisWait);
1699 : }
1700 :
1701 355 : if (ShutdownRequested()) {
1702 : return false;
1703 : }
1704 :
1705 355 : int chain_active_height;
1706 :
1707 : //// debug print
1708 355 : {
1709 355 : LOCK(cs_main);
1710 355 : chain_active_height = chainActive.Height();
1711 355 : LogPrintf("mapBlockIndex.size() = %u\n", mapBlockIndex.size());
1712 : }
1713 355 : LogPrintf("chainActive.Height() = %d\n", chain_active_height);
1714 :
1715 : // Update money supply
1716 355 : if (!fReindex && !fReindexChainState) {
1717 348 : uiInterface.InitMessage(_("Calculating money supply..."));
1718 348 : MoneySupply.Update(pcoinsTip->GetTotalAmount(), chain_active_height);
1719 : }
1720 :
1721 :
1722 : // ********************************************************* Step 10: setup layer 2 data
1723 :
1724 355 : bool load_cache_files = !(fReindex || fReindexChainState);
1725 355 : {
1726 355 : LOCK(cs_main);
1727 : // was blocks/chainstate deleted?
1728 355 : if (chainActive.Tip() == nullptr) {
1729 0 : load_cache_files = false;
1730 : }
1731 : }
1732 :
1733 355 : LoadTierTwo(chain_active_height, load_cache_files);
1734 355 : RegisterTierTwoValidationInterface();
1735 :
1736 : // set the mode of budget voting for this node
1737 710 : SetBudgetFinMode(gArgs.GetArg("-budgetvotemode", "auto"));
1738 :
1739 : // Start tier two threads and jobs
1740 355 : StartTierTwoThreadsAndScheduleJobs(threadGroup, scheduler);
1741 :
1742 355 : if (ShutdownRequested()) {
1743 0 : LogPrintf("Shutdown requested. Exiting.\n");
1744 : return false;
1745 : }
1746 :
1747 : // ********************************************************* Step 11: start node
1748 :
1749 355 : if (!strErrors.str().empty())
1750 0 : return UIError(strErrors.str());
1751 :
1752 : #ifdef ENABLE_WALLET
1753 355 : {
1754 355 : int idx = 0;
1755 716 : for (CWalletRef pwallet : vpwallets) {
1756 361 : LogPrintf("Wallet %d\n", idx++);
1757 722 : LOCK(pwallet->cs_wallet);
1758 361 : LogPrintf("setKeyPool.size() = %u\n", pwallet->GetKeyPoolSize());
1759 361 : LogPrintf("mapWallet.size() = %u\n", pwallet->mapWallet.size());
1760 361 : LogPrintf("mapAddressBook.size() = %u\n", pwallet->GetAddressBookSize());
1761 : }
1762 : }
1763 : #endif
1764 :
1765 355 : if (gArgs.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION))
1766 0 : StartTorControl();
1767 :
1768 355 : Discover();
1769 :
1770 : // Map ports with UPnP or NAT-PMP
1771 710 : StartMapPort(gArgs.GetBoolArg("-upnp", DEFAULT_UPNP), gArgs.GetBoolArg("-natpmp", DEFAULT_NATPMP));
1772 :
1773 710 : CConnman::Options connOptions;
1774 355 : connOptions.nLocalServices = nLocalServices;
1775 355 : connOptions.nRelevantServices = nRelevantServices;
1776 355 : connOptions.nMaxConnections = nMaxConnections;
1777 355 : connOptions.nMaxOutbound = std::min(MAX_OUTBOUND_CONNECTIONS, connOptions.nMaxConnections);
1778 355 : connOptions.nMaxAddnode = MAX_ADDNODE_CONNECTIONS;
1779 355 : connOptions.nMaxFeeler = 1;
1780 355 : connOptions.nBestHeight = chain_active_height;
1781 355 : connOptions.uiInterface = &uiInterface;
1782 355 : connOptions.m_msgproc = peerLogic.get();
1783 355 : connOptions.nSendBufferMaxSize = 1000*gArgs.GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER);
1784 355 : connOptions.nReceiveFloodSize = 1000*gArgs.GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER);
1785 710 : connOptions.m_added_nodes = gArgs.GetArgs("-addnode");
1786 :
1787 355 : if (gArgs.IsArgSet("-bind")) {
1788 688 : for (const std::string& strBind : gArgs.GetArgs("-bind")) {
1789 688 : CService addrBind;
1790 344 : if (!Lookup(strBind, addrBind, GetListenPort(), false)) {
1791 0 : return UIError(ResolveErrMsg("bind", strBind));
1792 : }
1793 344 : connOptions.vBinds.emplace_back(addrBind);
1794 : }
1795 : }
1796 355 : if (gArgs.IsArgSet("-whitebind")) {
1797 0 : for (const std::string& strBind : gArgs.GetArgs("-whitebind")) {
1798 0 : CService addrBind;
1799 0 : if (!Lookup(strBind, addrBind, 0, false)) {
1800 0 : return UIError(ResolveErrMsg("whitebind", strBind));
1801 : }
1802 0 : if (addrBind.GetPort() == 0) {
1803 0 : return UIError(strprintf(_("Need to specify a port with %s: '%s'"), "-whitebind", strBind));
1804 : }
1805 0 : connOptions.vWhiteBinds.emplace_back(addrBind);
1806 : }
1807 : }
1808 :
1809 400 : for (const auto& net : gArgs.GetArgs("-whitelist")) {
1810 90 : CSubNet subnet;
1811 45 : LookupSubNet(net, subnet);
1812 45 : if (!subnet.IsValid())
1813 0 : return UIError(strprintf(_("Invalid netmask specified in %s: '%s'"), "-whitelist", net));
1814 45 : connOptions.vWhitelistedRange.emplace_back(subnet);
1815 : }
1816 :
1817 710 : connOptions.vSeedNodes = gArgs.GetArgs("-seednode");
1818 :
1819 : // Initiate outbound connections unless connect=0
1820 355 : connOptions.m_use_addrman_outgoing = !gArgs.IsArgSet("-connect");
1821 355 : if (!connOptions.m_use_addrman_outgoing) {
1822 0 : const auto connect = gArgs.GetArgs("-connect");
1823 0 : if (connect.size() != 1 || connect[0] != "0") {
1824 0 : connOptions.m_specified_outgoing = connect;
1825 : }
1826 : }
1827 355 : if (!connman.Start(scheduler, connOptions)) {
1828 : return false;
1829 : }
1830 :
1831 : #ifdef ENABLE_WALLET
1832 : // Generate coins in the background (disabled on mainnet. use only wallet 0)
1833 355 : if (!vpwallets.empty())
1834 686 : GenerateBitcoins(gArgs.GetBoolArg("-gen", DEFAULT_GENERATE), vpwallets[0], gArgs.GetArg("-genproclimit", DEFAULT_GENERATE_PROCLIMIT));
1835 : #endif
1836 :
1837 : #ifdef ENABLE_WALLET
1838 355 : uiInterface.InitMessage(_("Reaccepting wallet transactions..."));
1839 716 : for (CWalletRef pwallet : vpwallets) {
1840 361 : pwallet->postInitProcess(scheduler);
1841 : }
1842 : // StakeMiner thread disabled by default on regtest
1843 1041 : if (!vpwallets.empty() && gArgs.GetBoolArg("-staking", !Params().IsRegTestNet() && DEFAULT_STAKING)) {
1844 0 : threadGroup.create_thread(std::bind(&ThreadStakeMinter));
1845 : }
1846 : #endif
1847 :
1848 : // Enable active MN
1849 355 : if (!InitActiveMN()) return false;
1850 :
1851 : // ********************************************************* Step 12: finished
1852 :
1853 355 : SetRPCWarmupFinished();
1854 355 : uiInterface.InitMessage(_("Done loading"));
1855 :
1856 355 : return true;
1857 : }
|