PIVX Core  5.6.99
P2P Digital Currency
init.cpp
Go to the documentation of this file.
1 // Copyright (c) 2021-2022 The PIVX Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or https://www.opensource.org/licenses/mit-license.php.
4 
5 #include "tiertwo/init.h"
6 
7 #include "budget/budgetdb.h"
8 #include "evo/evodb.h"
10 #include "flatdb.h"
11 #include "guiinterface.h"
12 #include "guiinterfaceutil.h"
13 #include "masternodeman.h"
14 #include "masternode-payments.h"
15 #include "masternodeconfig.h"
16 #include "llmq/quorums_init.h"
17 #include "scheduler.h"
20 #include "validation.h"
21 #include "wallet/wallet.h"
22 
23 #include <boost/thread.hpp>
24 
25 static std::unique_ptr<EvoNotificationInterface> pEvoNotificationInterface{nullptr};
26 
27 std::string GetTierTwoHelpString(bool showDebug)
28 {
29  std::string strUsage = HelpMessageGroup("Masternode options:");
30  strUsage += HelpMessageOpt("-masternode=<n>", strprintf("Enable the client to act as a masternode (0-1, default: %u)", DEFAULT_MASTERNODE));
31  strUsage += HelpMessageOpt("-mnconf=<file>", strprintf("Specify masternode configuration file (default: %s)", PIVX_MASTERNODE_CONF_FILENAME));
32  strUsage += HelpMessageOpt("-mnconflock=<n>", strprintf("Lock masternodes from masternode configuration file (default: %u)", DEFAULT_MNCONFLOCK));
33  strUsage += HelpMessageOpt("-masternodeprivkey=<n>", "Set the masternode private key");
34  strUsage += HelpMessageOpt("-masternodeaddr=<n>", strprintf("Set external address:port to get to this masternode (example: %s). Only for Legacy Masternodes", "128.127.106.235:51472"));
35  strUsage += HelpMessageOpt("-budgetvotemode=<mode>", "Change automatic finalized budget voting behavior. mode=auto: Vote for only exact finalized budget match to my generated budget. (string, default: auto)");
36  strUsage += HelpMessageOpt("-mnoperatorprivatekey=<bech32>", "Set the masternode operator private key. Only valid with -masternode=1. When set, the masternode acts as a deterministic masternode.");
37  if (showDebug) {
38  strUsage += HelpMessageOpt("-pushversion", strprintf("Modifies the mnauth serialization if the version is lower than %d."
39  "testnet/regtest only; ", MNAUTH_NODE_VER_VERSION));
40  strUsage += HelpMessageOpt("-disabledkg", "Disable the DKG sessions process threads for the entire lifecycle. testnet/regtest only.");
41  }
42  return strUsage;
43 }
44 
46 {
47  pEvoNotificationInterface = std::make_unique<EvoNotificationInterface>();
49 }
50 
52 {
56  }
57 
61  activeMasternodeManager = nullptr;
62  }
63 }
64 
66 {
67  int64_t nEvoDbCache = 1024 * 1024 * 64; // Max cache is 64MB
68  deterministicMNManager.reset();
69  evoDb.reset();
70  evoDb.reset(new CEvoDB(nEvoDbCache, false, fReindex));
72 }
73 
75 {
76  // Initialize LLMQ system
78 }
79 
81 {
82  // force UpdatedBlockTip to initialize nCachedBlockHeight for DS, MN payments and budgets
83  // but don't call it directly to prevent triggering of other listeners like zmq etc.
85 }
86 
87 // Sets the last CACHED_BLOCK_HASHES hashes into masternode manager cache
88 static void LoadBlockHashesCache(CMasternodeMan& man)
89 {
90  LOCK(cs_main);
91  const CBlockIndex* pindex = chainActive.Tip();
92  unsigned int inserted = 0;
93  while (pindex && inserted < CACHED_BLOCK_HASHES) {
94  man.CacheBlockHash(pindex);
95  pindex = pindex->pprev;
96  ++inserted;
97  }
98 }
99 
100 bool LoadTierTwo(int chain_active_height, bool load_cache_files)
101 {
102  // ################################# //
103  // ## Legacy Masternodes Manager ### //
104  // ################################# //
105  uiInterface.InitMessage(_("Loading masternode cache..."));
106 
107  mnodeman.SetBestHeight(chain_active_height);
108  LoadBlockHashesCache(mnodeman);
109  CMasternodeDB mndb;
110  CMasternodeDB::ReadResult readResult = mndb.Read(mnodeman);
111  if (readResult == CMasternodeDB::FileError)
112  LogPrintf("Missing masternode cache file - mncache.dat, will try to recreate\n");
113  else if (readResult != CMasternodeDB::Ok) {
114  LogPrintf("Error reading mncache.dat - cached data discarded\n");
115  }
116 
117  // ##################### //
118  // ## Budget Manager ### //
119  // ##################### //
120  uiInterface.InitMessage(_("Loading budget cache..."));
121 
122  CBudgetDB budgetdb;
123  const bool fDryRun = (chain_active_height <= 0);
124  if (!fDryRun) g_budgetman.SetBestHeight(chain_active_height);
125  CBudgetDB::ReadResult readResult2 = budgetdb.Read(g_budgetman, fDryRun);
126 
127  if (readResult2 == CBudgetDB::FileError)
128  LogPrintf("Missing budget cache - budget.dat, will try to recreate\n");
129  else if (readResult2 != CBudgetDB::Ok) {
130  LogPrintf("Error reading budget.dat - cached data discarded\n");
131  }
132 
133  // flag our cached items so we send them to our peers
136 
137  // ######################################### //
138  // ## Legacy Masternodes-Payments Manager ## //
139  // ######################################### //
140  uiInterface.InitMessage(_("Loading masternode payment cache..."));
141 
142  CMasternodePaymentDB mnpayments;
143  CMasternodePaymentDB::ReadResult readResult3 = mnpayments.Read(masternodePayments);
144  if (readResult3 == CMasternodePaymentDB::FileError)
145  LogPrintf("Missing masternode payment cache - mnpayments.dat, will try to recreate\n");
146  else if (readResult3 != CMasternodePaymentDB::Ok) {
147  LogPrintf("Error reading mnpayments.dat - cached data discarded\n");
148  }
149 
150  // ###################################### //
151  // ## Legacy Parse 'masternodes.conf' ## //
152  // ###################################### //
153  std::string strErr;
154  if (!masternodeConfig.read(strErr)) {
155  return UIError(strprintf(_("Error reading masternode configuration file: %s"), strErr));
156  }
157 
158  // ############################## //
159  // ## Net MNs Metadata Manager ## //
160  // ############################## //
161  uiInterface.InitMessage(_("Loading masternode cache..."));
162  CFlatDB<CMasternodeMetaMan> metadb(MN_META_CACHE_FILENAME, MN_META_CACHE_FILE_ID);
163  if (load_cache_files) {
164  if (!metadb.Load(g_mmetaman)) {
165  return UIError(strprintf(_("Failed to load masternode metadata cache from: %s"), metadb.GetDbPath().string()));
166  }
167  } else {
168  CMasternodeMetaMan mmetamanTmp;
169  if (!metadb.Dump(mmetamanTmp)) {
170  return UIError(strprintf(_("Failed to clear masternode metadata cache at: %s"), metadb.GetDbPath().string()));
171  }
172  }
173 
174  // ############################## //
175  // ## Network Requests Manager ## //
176  // ############################## //
177  uiInterface.InitMessage(_("Loading network requests cache..."));
178  CFlatDB<CNetFulfilledRequestManager> netRequestsDb(NET_REQUESTS_CACHE_FILENAME, NET_REQUESTS_CACHE_FILE_ID);
179  if (load_cache_files) {
180  if (!netRequestsDb.Load(g_netfulfilledman)) {
181  LogPrintf("Failed to load network requests cache from %s\n", netRequestsDb.GetDbPath().string());
182  }
183  } else {
184  CNetFulfilledRequestManager netfulfilledmanTmp(0);
185  if (!netRequestsDb.Dump(netfulfilledmanTmp)) {
186  LogPrintf("Failed to clear network requests cache at %s\n", netRequestsDb.GetDbPath().string());
187  }
188  }
189 
190  return true;
191 }
192 
194 {
198 }
199 
201 {
202  DumpMasternodes();
205  CFlatDB<CMasternodeMetaMan>(MN_META_CACHE_FILENAME, MN_META_CACHE_FILE_ID).Dump(g_mmetaman);
206  CFlatDB<CNetFulfilledRequestManager>(NET_REQUESTS_CACHE_FILENAME, NET_REQUESTS_CACHE_FILE_ID).Dump(g_netfulfilledman);
207 }
208 
209 void SetBudgetFinMode(const std::string& mode)
210 {
211  g_budgetman.strBudgetMode = mode;
212  LogPrintf("Budget Mode %s\n", g_budgetman.strBudgetMode);
213 }
214 
216 {
217  fMasterNode = gArgs.GetBoolArg("-masternode", DEFAULT_MASTERNODE);
218  if ((fMasterNode || masternodeConfig.getCount() > -1) && fTxIndex == false) {
219  return UIError(strprintf(_("Enabling Masternode support requires turning on transaction indexing."
220  "Please add %s to your configuration and start with %s"), "txindex=1", "-reindex"));
221  }
222 
223  if (fMasterNode) {
224 
225  if (gArgs.IsArgSet("-connect") && gArgs.GetArgs("-connect").size() > 0) {
226  return UIError(_("Cannot be a masternode and only connect to specific nodes"));
227  }
228 
229  if (gArgs.GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS) < DEFAULT_MAX_PEER_CONNECTIONS) {
230  return UIError(strprintf(_("Masternode must be able to handle at least %d connections, set %s=%d"),
231  DEFAULT_MAX_PEER_CONNECTIONS, "-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS));
232  }
233 
234  const std::string& mnoperatorkeyStr = gArgs.GetArg("-mnoperatorprivatekey", "");
235  const bool fDeterministic = !mnoperatorkeyStr.empty();
236  LogPrintf("IS %s MASTERNODE\n", (fDeterministic ? "DETERMINISTIC " : ""));
237 
238  if (fDeterministic) {
239  // Check enforcement
240  if (!deterministicMNManager->IsDIP3Enforced()) {
241  const std::string strError = strprintf(
242  _("Cannot start deterministic masternode before enforcement. Remove %s to start as legacy masternode"),
243  "-mnoperatorprivatekey");
244  LogPrintf("-- ERROR: %s\n", strError);
245  return UIError(strError);
246  }
247  // Create and register activeMasternodeManager
249  auto res = activeMasternodeManager->SetOperatorKey(mnoperatorkeyStr);
250  if (!res) { return UIError(res.getError()); }
251  // Init active masternode
252  const CBlockIndex* pindexTip = WITH_LOCK(cs_main, return chainActive.Tip(););
253  activeMasternodeManager->Init(pindexTip);
255  return UIError(activeMasternodeManager->GetStatus()); // state logged internally
256  }
257  } else {
258  // Check enforcement
259  if (deterministicMNManager->LegacyMNObsolete()) {
260  const std::string strError = strprintf(
261  _("Legacy masternode system disabled. Use %s to start as deterministic masternode"),
262  "-mnoperatorprivatekey");
263  LogPrintf("-- ERROR: %s\n", strError);
264  return UIError(strError);
265  }
266  auto res = initMasternode(gArgs.GetArg("-masternodeprivkey", ""), gArgs.GetArg("-masternodeaddr", ""),
267  true);
268  if (!res) { return UIError(res.getError()); }
269  }
270  }
271 
272 #ifdef ENABLE_WALLET
273  // !TODO: remove after complete transition to DMN
274  // use only the first wallet here. This section can be removed after transition to DMN
275  if (gArgs.GetBoolArg("-mnconflock", DEFAULT_MNCONFLOCK) && !vpwallets.empty() && vpwallets[0]) {
276  LOCK(vpwallets[0]->cs_wallet);
277  LogPrintf("Locking Masternodes collateral utxo:\n");
278  uint256 mnTxHash;
279  for (const auto& mne : masternodeConfig.getEntries()) {
280  mnTxHash.SetHex(mne.getTxHash());
281  COutPoint outpoint = COutPoint(mnTxHash, (unsigned int) std::stoul(mne.getOutputIndex()));
282  vpwallets[0]->LockCoin(outpoint);
283  LogPrintf("Locked collateral, MN: %s, tx hash: %s, output index: %s\n",
284  mne.getAlias(), mne.getTxHash(), mne.getOutputIndex());
285  }
286  }
287 
288  // automatic lock for DMN
289  if (gArgs.GetBoolArg("-mnconflock", DEFAULT_MNCONFLOCK)) {
290  LogPrintf("Locking masternode collaterals...\n");
291  const auto& mnList = deterministicMNManager->GetListAtChainTip();
292  mnList.ForEachMN(false, [&](const CDeterministicMNCPtr& dmn) {
293  for (CWallet* pwallet : vpwallets) {
294  pwallet->LockOutpointIfMineWithMutex(nullptr, dmn->collateralOutpoint);
295  }
296  });
297  }
298 #endif
299  // All good
300  return true;
301 }
302 
304 {
305  threadGroup.create_thread(std::bind(&ThreadCheckMasternodes));
307 
308  // Start LLMQ system
309  if (gArgs.GetBoolArg("-disabledkg", false)) {
310  if (Params().NetworkIDString() == CBaseChainParams::MAIN) {
311  throw std::runtime_error("DKG system can be disabled only on testnet/regtest");
312  } else {
313  LogPrintf("DKG system disabled.\n");
314  }
315  } else {
317  }
318 }
319 
321 {
323 }
324 
326 {
328  deterministicMNManager.reset();
329  evoDb.reset();
330 }
331 
333 {
335 }
OperationResult initMasternode(const std::string &_strMasterNodePrivKey, const std::string &_strMasterNodeAddr, bool isFromInit)
CActiveDeterministicMasternodeManager * activeMasternodeManager
void DumpBudgets(CBudgetManager &budgetman)
Definition: budgetdb.cpp:137
CBudgetManager g_budgetman
const CChainParams & Params()
Return the currently selected parameters.
std::vector< std::string > GetArgs(const std::string &strArg) const
Return a vector of strings of the given argument.
Definition: system.cpp:406
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition: system.cpp:425
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: system.cpp:449
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition: system.cpp:465
masternode_state_t GetState() const
OperationResult SetOperatorKey(const std::string &strMNOperatorPrivKey)
void Init(const CBlockIndex *pindexTip)
static const std::string MAIN
Chain name strings.
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:139
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:145
Save Budget Manager (budget.dat)
Definition: budgetdb.h:18
@ FileError
Definition: budgetdb.h:26
ReadResult Read(CBudgetManager &objToLoad, bool fDryRun=false)
Definition: budgetdb.cpp:55
std::string strBudgetMode
Definition: budgetmanager.h:66
void SetBestHeight(int height)
CBlockIndex * Tip(bool fProofOfStake=false) const
Returns the index entry for the tip of this chain, or nullptr if none.
Definition: chain.h:405
boost::signals2::signal< void(const std::string &message)> InitMessage
Progress message during initialization.
Definition: guiinterface.h:87
Definition: evodb.h:32
Definition: flatdb.h:25
bool Dump(T &objToSave)
Definition: flatdb.h:172
fs::path GetDbPath() const
Definition: flatdb.h:151
bool Load(T &objToLoad)
Definition: flatdb.h:153
bool read(std::string &strErr)
std::vector< CMasternodeEntry > getEntries()
Access to the MN database (mncache.dat)
Definition: masternodeman.h:34
ReadResult Read(CMasternodeMan &mnodemanToLoad)
void CacheBlockHash(const CBlockIndex *pindex)
void SetBestHeight(int height)
Save Masternode Payment Data (mnpayments.dat)
ReadResult Read(CMasternodePayments &objToLoad)
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:72
void scheduleEvery(Function f, int64_t deltaMilliSeconds)
Definition: scheduler.cpp:105
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,...
Definition: wallet.h:577
void SetHex(const char *psz)
Definition: uint256.cpp:31
256-bit opaque blob.
Definition: uint256.h:138
std::unique_ptr< CDeterministicMNManager > deterministicMNManager
std::shared_ptr< const CDeterministicMN > CDeterministicMNCPtr
std::unique_ptr< CEvoDB > evoDb
Definition: evodb.cpp:10
CClientUIInterface uiInterface
Definition: init.cpp:109
@ LOCK
Definition: lockunlock.h:16
CMasternodePayments masternodePayments
Object for who's going to get paid on which blocks.
void DumpMasternodePayments()
CMasternodeMetaMan g_mmetaman
CMasternodeConfig masternodeConfig
CMasternodeMan mnodeman
Masternode manager.
void ThreadCheckMasternodes()
void DumpMasternodes()
void DestroyLLMQSystem()
void StartLLMQSystem()
void InterruptLLMQSystem()
void StopLLMQSystem()
void InitLLMQSystem(CEvoDB &evoDb, CScheduler *scheduler, bool unitTests)
RecursiveMutex cs_main
Global state.
Definition: validation.cpp:80
CNetFulfilledRequestManager g_netfulfilledman(DEFAULT_ITEMS_FILTER_SIZE)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:247
ArgsManager gArgs
Definition: system.cpp:89
const char *const PIVX_MASTERNODE_CONF_FILENAME
Definition: system.cpp:82
std::atomic< bool > fMasterNode
Definition: system.cpp:87
std::string HelpMessageGroup(const std::string &message)
Format a string to be used as group of options in help messages.
Definition: system.cpp:499
std::string HelpMessageOpt(const std::string &option, const std::string &message)
Format a string to be used as option description in help messages.
Definition: system.cpp:503
std::string _(const char *psz)
Translation function: Call Translate signal on UI interface, which returns a Optional result.
Definition: system.h:65
bool InitActiveMN()
Initialize the active Masternode manager.
Definition: init.cpp:215
void InterruptTierTwo()
Interrupt tier two threads.
Definition: init.cpp:332
void ResetTierTwoInterfaces()
Resets the interfaces objects.
Definition: init.cpp:51
std::string GetTierTwoHelpString(bool showDebug)
Definition: init.cpp:27
void SetBudgetFinMode(const std::string &mode)
Definition: init.cpp:209
void InitTierTwoChainTip()
Initialize chain tip.
Definition: init.cpp:80
void RegisterTierTwoValidationInterface()
Register all tier two objects.
Definition: init.cpp:193
void InitTierTwoInterfaces()
Init the interfaces objects.
Definition: init.cpp:45
void InitTierTwoPreChainLoad(bool fReindex)
Inits the tier two global objects.
Definition: init.cpp:65
void StopTierTwoThreads()
Stops tier two workers.
Definition: init.cpp:320
bool LoadTierTwo(int chain_active_height, bool load_cache_files)
Loads from disk all the tier two related objects.
Definition: init.cpp:100
void StartTierTwoThreadsAndScheduleJobs(boost::thread_group &threadGroup, CScheduler &scheduler)
Starts tier two threads and jobs.
Definition: init.cpp:303
void DeleteTierTwo()
Cleans manager and worker objects pointers.
Definition: init.cpp:325
void DumpTierTwo()
Dump tier two managers to disk.
Definition: init.cpp:200
void InitTierTwoPostCoinsCacheLoad(CScheduler *scheduler)
Inits the tier two global objects that require access to the coins tip cache.
Definition: init.cpp:74
#define strprintf
Definition: tinyformat.h:1056
bool fTxIndex
Definition: validation.cpp:96
std::atomic< bool > fReindex
Definition: validation.cpp:95
CChain chainActive
The currently-connected chain of blocks (protected by cs_main).
Definition: validation.cpp:84
void UnregisterValidationInterface(CValidationInterface *pwalletIn)
Unregister a wallet from core.
void RegisterValidationInterface(CValidationInterface *pwalletIn)
Register a wallet to receive updates from core.
std::vector< CWalletRef > vpwallets
Definition: wallet.cpp:33
CScheduler scheduler
boost::thread_group threadGroup
EvoNotificationInterface * pEvoNotificationInterface