LCOV - code coverage report
Current view: top level - src/tiertwo - init.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 141 184 76.6 %
Date: 2025-02-23 09:33:43 Functions: 17 18 94.4 %

          Line data    Source code
       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"
       9             : #include "evo/evonotificationinterface.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"
      18             : #include "tiertwo/masternode_meta_manager.h"
      19             : #include "tiertwo/netfulfilledman.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           1 : std::string GetTierTwoHelpString(bool showDebug)
      28             : {
      29           1 :     std::string strUsage = HelpMessageGroup("Masternode options:");
      30           3 :     strUsage += HelpMessageOpt("-masternode=<n>", strprintf("Enable the client to act as a masternode (0-1, default: %u)", DEFAULT_MASTERNODE));
      31           3 :     strUsage += HelpMessageOpt("-mnconf=<file>", strprintf("Specify masternode configuration file (default: %s)", PIVX_MASTERNODE_CONF_FILENAME));
      32           3 :     strUsage += HelpMessageOpt("-mnconflock=<n>", strprintf("Lock masternodes from masternode configuration file (default: %u)", DEFAULT_MNCONFLOCK));
      33           4 :     strUsage += HelpMessageOpt("-masternodeprivkey=<n>", "Set the masternode private key");
      34           4 :     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           4 :     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           4 :     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           1 :     if (showDebug) {
      38           0 :         strUsage += HelpMessageOpt("-pushversion", strprintf("Modifies the mnauth serialization if the version is lower than %d."
      39           0 :                                                              "testnet/regtest only; ", MNAUTH_NODE_VER_VERSION));
      40           0 :         strUsage += HelpMessageOpt("-disabledkg", "Disable the DKG sessions process threads for the entire lifecycle. testnet/regtest only.");
      41             :     }
      42           1 :     return strUsage;
      43             : }
      44             : 
      45         357 : void InitTierTwoInterfaces()
      46             : {
      47         357 :     pEvoNotificationInterface = std::make_unique<EvoNotificationInterface>();
      48         357 :     RegisterValidationInterface(pEvoNotificationInterface.get());
      49         357 : }
      50             : 
      51         378 : void ResetTierTwoInterfaces()
      52             : {
      53         378 :     if (pEvoNotificationInterface) {
      54         357 :         UnregisterValidationInterface(pEvoNotificationInterface.get());
      55         357 :         pEvoNotificationInterface.reset();
      56             :     }
      57             : 
      58         378 :     if (activeMasternodeManager) {
      59          41 :         UnregisterValidationInterface(activeMasternodeManager);
      60          41 :         delete activeMasternodeManager;
      61          41 :         activeMasternodeManager = nullptr;
      62             :     }
      63         378 : }
      64             : 
      65         357 : void InitTierTwoPreChainLoad(bool fReindex)
      66             : {
      67         357 :     int64_t nEvoDbCache = 1024 * 1024 * 64; // Max cache is 64MB
      68         357 :     deterministicMNManager.reset();
      69         357 :     evoDb.reset();
      70         357 :     evoDb.reset(new CEvoDB(nEvoDbCache, false, fReindex));
      71         357 :     deterministicMNManager.reset(new CDeterministicMNManager(*evoDb));
      72         357 : }
      73             : 
      74         357 : void InitTierTwoPostCoinsCacheLoad(CScheduler* scheduler)
      75             : {
      76             :     // Initialize LLMQ system
      77         357 :     llmq::InitLLMQSystem(*evoDb, scheduler, false);
      78         357 : }
      79             : 
      80         355 : void InitTierTwoChainTip()
      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.
      84         355 :     pEvoNotificationInterface->InitializeCurrentBlockTip();
      85         355 : }
      86             : 
      87             : // Sets the last CACHED_BLOCK_HASHES hashes into masternode manager cache
      88         355 : static void LoadBlockHashesCache(CMasternodeMan& man)
      89             : {
      90         355 :     LOCK(cs_main);
      91         355 :     const CBlockIndex* pindex = chainActive.Tip();
      92             :     unsigned int inserted = 0;
      93       24715 :     while (pindex && inserted < CACHED_BLOCK_HASHES) {
      94       24360 :         man.CacheBlockHash(pindex);
      95       24360 :         pindex = pindex->pprev;
      96       24360 :         ++inserted;
      97             :     }
      98         355 : }
      99             : 
     100         355 : bool LoadTierTwo(int chain_active_height, bool load_cache_files)
     101             : {
     102             :     // ################################# //
     103             :     // ## Legacy Masternodes Manager ### //
     104             :     // ################################# //
     105         355 :     uiInterface.InitMessage(_("Loading masternode cache..."));
     106             : 
     107         355 :     mnodeman.SetBestHeight(chain_active_height);
     108         355 :     LoadBlockHashesCache(mnodeman);
     109         710 :     CMasternodeDB mndb;
     110         355 :     CMasternodeDB::ReadResult readResult = mndb.Read(mnodeman);
     111         355 :     if (readResult == CMasternodeDB::FileError)
     112         273 :         LogPrintf("Missing masternode cache file - mncache.dat, will try to recreate\n");
     113          82 :     else if (readResult != CMasternodeDB::Ok) {
     114           0 :         LogPrintf("Error reading mncache.dat - cached data discarded\n");
     115             :     }
     116             : 
     117             :     // ##################### //
     118             :     // ## Budget Manager ### //
     119             :     // ##################### //
     120         355 :     uiInterface.InitMessage(_("Loading budget cache..."));
     121             : 
     122         710 :     CBudgetDB budgetdb;
     123         355 :     const bool fDryRun = (chain_active_height <= 0);
     124         355 :     if (!fDryRun) g_budgetman.SetBestHeight(chain_active_height);
     125         355 :     CBudgetDB::ReadResult readResult2 = budgetdb.Read(g_budgetman, fDryRun);
     126             : 
     127         355 :     if (readResult2 == CBudgetDB::FileError)
     128         273 :         LogPrintf("Missing budget cache - budget.dat, will try to recreate\n");
     129          82 :     else if (readResult2 != CBudgetDB::Ok) {
     130           0 :         LogPrintf("Error reading budget.dat - cached data discarded\n");
     131             :     }
     132             : 
     133             :     // flag our cached items so we send them to our peers
     134         355 :     g_budgetman.ResetSync();
     135         355 :     g_budgetman.ReloadMapSeen();
     136             : 
     137             :     // ######################################### //
     138             :     // ## Legacy Masternodes-Payments Manager ## //
     139             :     // ######################################### //
     140         355 :     uiInterface.InitMessage(_("Loading masternode payment cache..."));
     141             : 
     142         355 :     CMasternodePaymentDB mnpayments;
     143         355 :     CMasternodePaymentDB::ReadResult readResult3 = mnpayments.Read(masternodePayments);
     144         355 :     if (readResult3 == CMasternodePaymentDB::FileError)
     145         273 :         LogPrintf("Missing masternode payment cache - mnpayments.dat, will try to recreate\n");
     146          82 :     else if (readResult3 != CMasternodePaymentDB::Ok) {
     147           0 :         LogPrintf("Error reading mnpayments.dat - cached data discarded\n");
     148             :     }
     149             : 
     150             :     // ###################################### //
     151             :     // ## Legacy Parse 'masternodes.conf'  ## //
     152             :     // ###################################### //
     153         710 :     std::string strErr;
     154         355 :     if (!masternodeConfig.read(strErr)) {
     155           0 :         return UIError(strprintf(_("Error reading masternode configuration file: %s"), strErr));
     156             :     }
     157             : 
     158             :     // ############################## //
     159             :     // ## Net MNs Metadata Manager ## //
     160             :     // ############################## //
     161         355 :     uiInterface.InitMessage(_("Loading masternode cache..."));
     162         710 :     CFlatDB<CMasternodeMetaMan> metadb(MN_META_CACHE_FILENAME, MN_META_CACHE_FILE_ID);
     163         355 :     if (load_cache_files) {
     164         348 :         if (!metadb.Load(g_mmetaman)) {
     165           0 :             return UIError(strprintf(_("Failed to load masternode metadata cache from: %s"), metadb.GetDbPath().string()));
     166             :         }
     167             :     } else {
     168          14 :         CMasternodeMetaMan mmetamanTmp;
     169           7 :         if (!metadb.Dump(mmetamanTmp)) {
     170           0 :             return UIError(strprintf(_("Failed to clear masternode metadata cache at: %s"), metadb.GetDbPath().string()));
     171             :         }
     172             :     }
     173             : 
     174             :     // ############################## //
     175             :     // ## Network Requests Manager ## //
     176             :     // ############################## //
     177         355 :     uiInterface.InitMessage(_("Loading network requests cache..."));
     178         355 :     CFlatDB<CNetFulfilledRequestManager> netRequestsDb(NET_REQUESTS_CACHE_FILENAME, NET_REQUESTS_CACHE_FILE_ID);
     179         355 :     if (load_cache_files) {
     180         348 :         if (!netRequestsDb.Load(g_netfulfilledman)) {
     181           0 :             LogPrintf("Failed to load network requests cache from %s\n", netRequestsDb.GetDbPath().string());
     182             :         }
     183             :     } else {
     184          14 :         CNetFulfilledRequestManager netfulfilledmanTmp(0);
     185           7 :         if (!netRequestsDb.Dump(netfulfilledmanTmp)) {
     186           0 :             LogPrintf("Failed to clear network requests cache at %s\n", netRequestsDb.GetDbPath().string());
     187             :         }
     188             :     }
     189             : 
     190         355 :     return true;
     191             : }
     192             : 
     193         355 : void RegisterTierTwoValidationInterface()
     194             : {
     195         355 :     RegisterValidationInterface(&g_budgetman);
     196         355 :     RegisterValidationInterface(&masternodePayments);
     197         355 :     if (activeMasternodeManager) RegisterValidationInterface(activeMasternodeManager);
     198         355 : }
     199             : 
     200         378 : void DumpTierTwo()
     201             : {
     202         378 :     DumpMasternodes();
     203         378 :     DumpBudgets(g_budgetman);
     204         378 :     DumpMasternodePayments();
     205         378 :     CFlatDB<CMasternodeMetaMan>(MN_META_CACHE_FILENAME, MN_META_CACHE_FILE_ID).Dump(g_mmetaman);
     206         378 :     CFlatDB<CNetFulfilledRequestManager>(NET_REQUESTS_CACHE_FILENAME, NET_REQUESTS_CACHE_FILE_ID).Dump(g_netfulfilledman);
     207         378 : }
     208             : 
     209         355 : void SetBudgetFinMode(const std::string& mode)
     210             : {
     211         355 :     g_budgetman.strBudgetMode = mode;
     212         355 :     LogPrintf("Budget Mode %s\n", g_budgetman.strBudgetMode);
     213         355 : }
     214             : 
     215         355 : bool InitActiveMN()
     216             : {
     217         355 :     fMasterNode = gArgs.GetBoolArg("-masternode", DEFAULT_MASTERNODE);
     218         355 :     if ((fMasterNode || masternodeConfig.getCount() > -1) && fTxIndex == false) {
     219           0 :         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         355 :     if (fMasterNode) {
     224             : 
     225           0 :         if (gArgs.IsArgSet("-connect") && gArgs.GetArgs("-connect").size() > 0) {
     226           0 :             return UIError(_("Cannot be a masternode and only connect to specific nodes"));
     227             :         }
     228             : 
     229           0 :         if (gArgs.GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS) < DEFAULT_MAX_PEER_CONNECTIONS) {
     230           0 :             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           0 :         const std::string& mnoperatorkeyStr = gArgs.GetArg("-mnoperatorprivatekey", "");
     235           0 :         const bool fDeterministic = !mnoperatorkeyStr.empty();
     236           0 :         LogPrintf("IS %s MASTERNODE\n", (fDeterministic ? "DETERMINISTIC " : ""));
     237             : 
     238           0 :         if (fDeterministic) {
     239             :             // Check enforcement
     240           0 :             if (!deterministicMNManager->IsDIP3Enforced()) {
     241           0 :                 const std::string strError = strprintf(
     242           0 :                         _("Cannot start deterministic masternode before enforcement. Remove %s to start as legacy masternode"),
     243           0 :                         "-mnoperatorprivatekey");
     244           0 :                 LogPrintf("-- ERROR: %s\n", strError);
     245           0 :                 return UIError(strError);
     246             :             }
     247             :             // Create and register activeMasternodeManager
     248           0 :             activeMasternodeManager = new CActiveDeterministicMasternodeManager();
     249           0 :             auto res = activeMasternodeManager->SetOperatorKey(mnoperatorkeyStr);
     250           0 :             if (!res) { return UIError(res.getError()); }
     251             :             // Init active masternode
     252           0 :             const CBlockIndex* pindexTip = WITH_LOCK(cs_main, return chainActive.Tip(););
     253           0 :             activeMasternodeManager->Init(pindexTip);
     254           0 :             if (activeMasternodeManager->GetState() == CActiveDeterministicMasternodeManager::MASTERNODE_ERROR) {
     255           0 :                 return UIError(activeMasternodeManager->GetStatus()); // state logged internally
     256             :             }
     257             :         } else {
     258             :             // Check enforcement
     259           0 :             if (deterministicMNManager->LegacyMNObsolete()) {
     260           0 :                 const std::string strError = strprintf(
     261           0 :                         _("Legacy masternode system disabled. Use %s to start as deterministic masternode"),
     262           0 :                         "-mnoperatorprivatekey");
     263           0 :                 LogPrintf("-- ERROR: %s\n", strError);
     264           0 :                 return UIError(strError);
     265             :             }
     266           0 :             auto res = initMasternode(gArgs.GetArg("-masternodeprivkey", ""), gArgs.GetArg("-masternodeaddr", ""),
     267           0 :                                       true);
     268           0 :             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         710 :     if (gArgs.GetBoolArg("-mnconflock", DEFAULT_MNCONFLOCK) && !vpwallets.empty() && vpwallets[0]) {
     276         686 :         LOCK(vpwallets[0]->cs_wallet);
     277         343 :         LogPrintf("Locking Masternodes collateral utxo:\n");
     278         343 :         uint256 mnTxHash;
     279         344 :         for (const auto& mne : masternodeConfig.getEntries()) {
     280           1 :             mnTxHash.SetHex(mne.getTxHash());
     281           1 :             COutPoint outpoint = COutPoint(mnTxHash, (unsigned int) std::stoul(mne.getOutputIndex()));
     282           1 :             vpwallets[0]->LockCoin(outpoint);
     283           1 :             LogPrintf("Locked collateral, MN: %s, tx hash: %s, output index: %s\n",
     284           1 :                       mne.getAlias(), mne.getTxHash(), mne.getOutputIndex());
     285             :         }
     286             :     }
     287             : 
     288             :     // automatic lock for DMN
     289         355 :     if (gArgs.GetBoolArg("-mnconflock", DEFAULT_MNCONFLOCK)) {
     290         355 :         LogPrintf("Locking masternode collaterals...\n");
     291         355 :         const auto& mnList = deterministicMNManager->GetListAtChainTip();
     292         355 :         mnList.ForEachMN(false, [&](const CDeterministicMNCPtr& dmn) {
     293          24 :             for (CWallet* pwallet : vpwallets) {
     294          24 :                 pwallet->LockOutpointIfMineWithMutex(nullptr, dmn->collateralOutpoint);
     295             :             }
     296          12 :         });
     297             :     }
     298             : #endif
     299             :     // All good
     300             :     return true;
     301             : }
     302             : 
     303         355 : void StartTierTwoThreadsAndScheduleJobs(boost::thread_group& threadGroup, CScheduler& scheduler)
     304             : {
     305         355 :     threadGroup.create_thread(std::bind(&ThreadCheckMasternodes));
     306         355 :     scheduler.scheduleEvery(std::bind(&CNetFulfilledRequestManager::DoMaintenance, std::ref(g_netfulfilledman)), 60 * 1000);
     307             : 
     308             :     // Start LLMQ system
     309         355 :     if (gArgs.GetBoolArg("-disabledkg", false)) {
     310           8 :         if (Params().NetworkIDString() == CBaseChainParams::MAIN) {
     311           0 :             throw std::runtime_error("DKG system can be disabled only on testnet/regtest");
     312             :         } else {
     313           8 :             LogPrintf("DKG system disabled.\n");
     314             :         }
     315             :     } else {
     316         347 :         llmq::StartLLMQSystem();
     317             :     }
     318         355 : }
     319             : 
     320         378 : void StopTierTwoThreads()
     321             : {
     322         378 :     llmq::StopLLMQSystem();
     323         378 : }
     324             : 
     325         378 : void DeleteTierTwo()
     326             : {
     327         378 :     llmq::DestroyLLMQSystem();
     328         378 :     deterministicMNManager.reset();
     329         378 :     evoDb.reset();
     330         378 : }
     331             : 
     332         378 : void InterruptTierTwo()
     333             : {
     334         378 :     llmq::InterruptLLMQSystem();
     335         378 : }

Generated by: LCOV version 1.14