LCOV - code coverage report
Current view: top level - src/rpc - mining.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 112 166 67.5 %
Date: 2025-02-23 09:33:43 Functions: 8 9 88.9 %

          Line data    Source code
       1             : // Copyright (c) 2010 Satoshi Nakamoto
       2             : // Copyright (c) 2009-2014 The Bitcoin developers
       3             : // Copyright (c) 2014-2015 The Dash developers
       4             : // Copyright (c) 2015-2022 The PIVX Core developers
       5             : // Distributed under the MIT software license, see the accompanying
       6             : // file COPYING or https://www.opensource.org/licenses/mit-license.php.
       7             : 
       8             : #include "amount.h"
       9             : #include "blockassembler.h"
      10             : #include "chainparams.h"
      11             : #include "core_io.h"
      12             : #include "key_io.h"
      13             : #include "miner.h"
      14             : #include "net.h"
      15             : #include "rpc/server.h"
      16             : #include "shutdown.h"
      17             : #include "util/blockstatecatcher.h"
      18             : #include "validationinterface.h"
      19             : #ifdef ENABLE_WALLET
      20             : #include "wallet/rpcwallet.h"
      21             : #include "wallet/db.h"
      22             : #include "wallet/wallet.h"
      23             : #endif
      24             : #include "warnings.h"
      25             : 
      26             : #include <univalue.h>
      27             : 
      28             : #ifdef ENABLE_WALLET
      29        3271 : UniValue generateBlocks(const Consensus::Params& consensus,
      30             :                         CWallet* const pwallet,
      31             :                         bool fPoS,
      32             :                         const int nGenerate,
      33             :                         int nHeight,
      34             :                         int nHeightEnd,
      35             :                         CScript* coinbaseScript)
      36             : {
      37        3271 :     UniValue blockHashes(UniValue::VARR);
      38             : 
      39        3277 :     BlockStateCatcherWrapper sc(UINT256_ZERO);
      40        3271 :     sc.registerEvent();
      41       15746 :     while (nHeight < nHeightEnd && !ShutdownRequested()) {
      42             : 
      43             :         // Get available coins
      44       24956 :         std::vector<CStakeableOutput> availableCoins;
      45       12481 :         if (fPoS && !pwallet->StakeableCoins(&availableCoins)) {
      46           0 :             throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "No available coins to stake");
      47             :         }
      48             : 
      49       12481 :         std::unique_ptr<CBlockTemplate> pblocktemplate(fPoS ?
      50       14356 :                                                        BlockAssembler(Params(), DEFAULT_PRINTPRIORITY).CreateNewBlock(CScript(), pwallet, true, &availableCoins) :
      51       26831 :                                                        CreateNewBlockWithScript(*coinbaseScript, pwallet));
      52       12481 :         if (!pblocktemplate.get()) break;
      53       24950 :         std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(pblocktemplate->block);
      54             : 
      55       12475 :         if(!fPoS) {
      56       10606 :             if (ShutdownRequested()) break;
      57       10606 :             if (!SolveBlock(pblock, nHeight + 1)) continue;
      58             :         }
      59             : 
      60       12475 :         sc.get().setBlockHash(pblock->GetHash());
      61       12475 :         bool res = ProcessNewBlock(pblock, nullptr);
      62       12475 :         if (!res || sc.get().stateErrorFound())
      63           0 :             throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
      64             : 
      65       12475 :         ++nHeight;
      66       12475 :         blockHashes.push_back(pblock->GetHash().GetHex());
      67             : 
      68             :         // Check PoS if needed.
      69       12475 :         if (!fPoS)
      70       10606 :             fPoS = consensus.NetworkUpgradeActive(nHeight + 1, Consensus::UPGRADE_POS);
      71             :     }
      72             : 
      73        3271 :     const int nGenerated = blockHashes.size();
      74        3271 :     if (nGenerated == 0 || (!fPoS && nGenerated < nGenerate))
      75          12 :         throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new blocks");
      76             : 
      77        3265 :     return blockHashes;
      78             : }
      79             : 
      80        3271 : UniValue generate(const JSONRPCRequest& request)
      81             : {
      82        3271 :     CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
      83             : 
      84        3271 :     if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
      85           0 :         return NullUniValue;
      86             : 
      87        3271 :     if (request.fHelp || request.params.size() < 1 || request.params.size() > 1)
      88           0 :         throw std::runtime_error(
      89             :             "generate nblocks\n"
      90             :             "\nMine blocks immediately (before the RPC call returns)\n"
      91             :             "\nNote: this function can only be used on the regtest network\n"
      92             : 
      93             :             "\nArguments:\n"
      94             :             "1. nblocks    (numeric, required) How many blocks to generate.\n"
      95             : 
      96             :             "\nResult\n"
      97             :             "[ blockhashes ]     (array) hashes of blocks generated\n"
      98             : 
      99             :             "\nExamples:\n"
     100             :             "\nGenerate 11 blocks\n"
     101           0 :             + HelpExampleCli("generate", "11")
     102           0 :         );
     103             : 
     104        3271 :     if (!Params().IsRegTestNet())
     105           0 :         throw JSONRPCError(RPC_METHOD_NOT_FOUND, "This method can only be used on regtest");
     106             : 
     107        3271 :     const int nGenerate = request.params[0].get_int();
     108        3271 :     int nHeightEnd = 0;
     109        3271 :     int nHeight = 0;
     110             : 
     111        3271 :     {   // Don't keep cs_main locked
     112        3271 :         LOCK(cs_main);
     113        3271 :         nHeight = chainActive.Height();
     114        3271 :         nHeightEnd = nHeight + nGenerate;
     115             :     }
     116             : 
     117        3271 :     const Consensus::Params& consensus = Params().GetConsensus();
     118        3271 :     bool fPoS = consensus.NetworkUpgradeActive(nHeight + 1, Consensus::UPGRADE_POS);
     119           6 :     std::unique_ptr<CReserveKey> reservekey;
     120        6542 :     CScript coinbaseScript;
     121             : 
     122        3271 :     if (fPoS) {
     123             :         // If we are in PoS, wallet must be unlocked.
     124         626 :         EnsureWalletIsUnlocked(pwallet);
     125             :     } else {
     126             :         // Coinbase key
     127        2645 :         reservekey = std::make_unique<CReserveKey>(pwallet);
     128        2645 :         CPubKey pubkey;
     129        2645 :         if (!reservekey->GetReservedKey(pubkey)) throw JSONRPCError(RPC_INTERNAL_ERROR, "Error: Cannot get key from keypool");
     130        2651 :         coinbaseScript = GetScriptForDestination(pubkey.GetID());
     131             :     }
     132             : 
     133             :     // Create the blocks
     134        3271 :     UniValue blockHashes = generateBlocks(consensus,
     135             :                                           pwallet,
     136             :                                           fPoS,
     137             :                                           nGenerate,
     138             :                                           nHeight,
     139             :                                           nHeightEnd,
     140        6536 :                                           &coinbaseScript);
     141             : 
     142             :     // mark key as used, only for PoW coinbases
     143        3265 :     if (reservekey) {
     144             :         // Remove key from key pool
     145        2645 :         reservekey->KeepKey();
     146             :     }
     147             : 
     148        3265 :     return blockHashes;
     149             : }
     150             : 
     151           0 : UniValue generatetoaddress(const JSONRPCRequest& request)
     152             : {
     153           0 :     CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
     154             : 
     155           0 :     if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
     156           0 :         return NullUniValue;
     157             : 
     158           0 :     if (request.fHelp || request.params.size() != 2)
     159           0 :         throw std::runtime_error(
     160             :                 "generatetoaddress nblocks \"address\"\n"
     161             :                 "\nMine blocks immediately to a specified address (before the RPC call returns)\n"
     162             :                 "\nArguments:\n"
     163             :                 "1. nblocks          (numeric, required) How many blocks are generated immediately.\n"
     164             :                 "2. \"address\"      (string, required) The address to send the newly generated bitcoin to.\n"
     165             :                 "\nResult\n"
     166             :                 "[ blockhashes ]     (array) hashes of blocks generated\n"
     167             :                 "\nExamples:\n"
     168             :                 "\nGenerate 11 blocks to myaddress\n"
     169           0 :                 + HelpExampleCli("generatetoaddress", "11 \"myaddress\"")
     170           0 :         );
     171             : 
     172           0 :     int nGenerate = request.params[0].get_int();
     173           0 :     CTxDestination dest(DecodeDestination(request.params[1].get_str()));
     174           0 :     if (!IsValidDestination(dest)) {
     175           0 :         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Error: Invalid address");
     176             :     }
     177           0 :     CScript coinbaseScript = GetScriptForDestination(dest);
     178             : 
     179           0 :     const Consensus::Params& consensus = Params().GetConsensus();
     180           0 :     int nHeightEnd = 0;
     181           0 :     int nHeight = 0;
     182             : 
     183           0 :     {   // Don't keep cs_main locked
     184           0 :         LOCK(cs_main);
     185           0 :         nHeight = chainActive.Height();
     186           0 :         nHeightEnd = nHeight + nGenerate;
     187             :     }
     188             : 
     189           0 :     bool fPoS = consensus.NetworkUpgradeActive(nHeight + 1, Consensus::UPGRADE_POS);
     190           0 :     return generateBlocks(consensus,
     191             :                           pwallet,
     192             :                           fPoS,
     193             :                           nGenerate,
     194             :                           nHeight,
     195             :                           nHeightEnd,
     196           0 :                           &coinbaseScript);
     197             : }
     198             : 
     199             : #endif // ENABLE_WALLET
     200             : 
     201             : #ifdef ENABLE_MINING_RPC
     202             : /**
     203             :  * Return average network hashes per second based on the last 'lookup' blocks,
     204             :  * or from the last difficulty change if 'lookup' is nonpositive.
     205             :  * If 'height' is nonnegative, compute the estimate at the time when a given block was found.
     206             :  */
     207             : UniValue GetNetworkHashPS(int lookup, int height)
     208             : {
     209             :     CBlockIndex *pb = chainActive.Tip();
     210             : 
     211             :     if (height >= 0 && height < chainActive.Height())
     212             :         pb = chainActive[height];
     213             : 
     214             :     if (pb == nullptr || !pb->nHeight)
     215             :         return 0;
     216             : 
     217             :     // If lookup is -1, then use blocks since last difficulty change.
     218             :     if (lookup <= 0)
     219             :         lookup = pb->nHeight % 2016 + 1;
     220             : 
     221             :     // If lookup is larger than chain, then set it to chain length.
     222             :     if (lookup > pb->nHeight)
     223             :         lookup = pb->nHeight;
     224             : 
     225             :     CBlockIndex* pb0 = pb;
     226             :     int64_t minTime = pb0->GetBlockTime();
     227             :     int64_t maxTime = minTime;
     228             :     for (int i = 0; i < lookup; i++) {
     229             :         pb0 = pb0->pprev;
     230             :         int64_t time = pb0->GetBlockTime();
     231             :         minTime = std::min(time, minTime);
     232             :         maxTime = std::max(time, maxTime);
     233             :     }
     234             : 
     235             :     // In case there's a situation where minTime == maxTime, we don't want a divide by zero exception.
     236             :     if (minTime == maxTime)
     237             :         return 0;
     238             : 
     239             :     arith_uint256 workDiff = pb->nChainWork - pb0->nChainWork;
     240             :     int64_t timeDiff = maxTime - minTime;
     241             : 
     242             :     return (int64_t)(workDiff.getdouble() / timeDiff);
     243             : }
     244             : 
     245             : UniValue getnetworkhashps(const JSONRPCRequest& request)
     246             : {
     247             :     if (request.fHelp || request.params.size() > 2)
     248             :         throw std::runtime_error(
     249             :             "getnetworkhashps ( nblocks height )\n"
     250             :             "\nReturns the estimated network hashes per second based on the last n blocks.\n"
     251             :             "Pass in [blocks] to override # of blocks, -1 specifies since last difficulty change.\n"
     252             :             "Pass in [height] to estimate the network speed at the time when a certain block was found.\n"
     253             : 
     254             :             "\nArguments:\n"
     255             :             "1. nblocks     (numeric, optional, default=120) The number of blocks, or -1 for blocks since last difficulty change.\n"
     256             :             "2. height     (numeric, optional, default=-1) To estimate at the time of the given height.\n"
     257             : 
     258             :             "\nResult:\n"
     259             :             "x             (numeric) Hashes per second estimated\n"
     260             :             "\nExamples:\n" +
     261             :             HelpExampleCli("getnetworkhashps", "") + HelpExampleRpc("getnetworkhashps", ""));
     262             : 
     263             :     LOCK(cs_main);
     264             :     return GetNetworkHashPS(request.params.size() > 0 ? request.params[0].get_int() : 120, request.params.size() > 1 ? request.params[1].get_int() : -1);
     265             : }
     266             : 
     267             : #ifdef ENABLE_WALLET
     268             : UniValue getgenerate(const JSONRPCRequest& request)
     269             : {
     270             :     if (request.fHelp || request.params.size() != 0)
     271             :         throw std::runtime_error(
     272             :             "getgenerate\n"
     273             :             "\nReturn if the server is set to generate coins or not. The default is false.\n"
     274             :             "It is set with the command line argument -gen (or pivx.conf setting gen)\n"
     275             :             "It can also be set with the setgenerate call.\n"
     276             : 
     277             :             "\nResult\n"
     278             :             "true|false      (boolean) If the server is set to generate coins or not\n"
     279             : 
     280             :             "\nExamples:\n" +
     281             :             HelpExampleCli("getgenerate", "") + HelpExampleRpc("getgenerate", ""));
     282             : 
     283             :     LOCK(cs_main);
     284             :     return gArgs.GetBoolArg("-gen", false);
     285             : }
     286             : 
     287             : UniValue setgenerate(const JSONRPCRequest& request)
     288             : {
     289             :     CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
     290             : 
     291             :     if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
     292             :         return NullUniValue;
     293             : 
     294             :     if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
     295             :         throw std::runtime_error(
     296             :             "setgenerate generate ( genproclimit )\n"
     297             :             "\nSet 'generate' true or false to turn generation on or off.\n"
     298             :             "Generation is limited to 'genproclimit' processors, -1 is unlimited.\n"
     299             :             "See the getgenerate call for the current setting.\n"
     300             : 
     301             :             "\nArguments:\n"
     302             :             "1. generate         (boolean, required) Set to true to turn on generation, false to turn off.\n"
     303             :             "2. genproclimit     (numeric, optional) Set the processor limit for when generation is on. Can be -1 for unlimited.\n"
     304             : 
     305             :             "\nExamples:\n"
     306             :             "\nSet the generation on with a limit of one processor\n" +
     307             :             HelpExampleCli("setgenerate", "true 1") +
     308             :             "\nCheck the setting\n" + HelpExampleCli("getgenerate", "") +
     309             :             "\nTurn off generation\n" + HelpExampleCli("setgenerate", "false") +
     310             :             "\nUsing json rpc\n" + HelpExampleRpc("setgenerate", "true, 1"));
     311             : 
     312             :     if (Params().IsRegTestNet())
     313             :         throw JSONRPCError(RPC_INVALID_REQUEST, "Use the generate method instead of setgenerate on regtest");
     314             : 
     315             :     bool fGenerate = true;
     316             :     if (request.params.size() > 0)
     317             :         fGenerate = request.params[0].get_bool();
     318             : 
     319             :     const int nHeight = WITH_LOCK(cs_main, return chainActive.Height() + 1);
     320             :     if (fGenerate && Params().GetConsensus().NetworkUpgradeActive(nHeight, Consensus::UPGRADE_POS))
     321             :         throw JSONRPCError(RPC_INVALID_REQUEST, "Proof of Work phase has already ended");
     322             : 
     323             :     int nGenProcLimit = -1;
     324             :     if (request.params.size() > 1) {
     325             :         nGenProcLimit = request.params[1].get_int();
     326             :         if (nGenProcLimit == 0)
     327             :             fGenerate = false;
     328             :     }
     329             : 
     330             :     gArgs.GetArg("-gen", "") = (fGenerate ? "1" : "0");
     331             :     gArgs.GetArg("-genproclimit", "") = itostr(nGenProcLimit);
     332             :     GenerateBitcoins(fGenerate, pwallet, nGenProcLimit);
     333             : 
     334             :     return NullUniValue;
     335             : }
     336             : 
     337             : UniValue gethashespersec(const JSONRPCRequest& request)
     338             : {
     339             :     if (request.fHelp || request.params.size() != 0)
     340             :         throw std::runtime_error(
     341             :             "gethashespersec\n"
     342             :             "\nReturns a recent hashes per second performance measurement while generating.\n"
     343             :             "See the getgenerate and setgenerate calls to turn generation on and off.\n"
     344             : 
     345             :             "\nResult:\n"
     346             :             "n            (numeric) The recent hashes per second when generation is on (will return 0 if generation is off)\n"
     347             : 
     348             :             "\nExamples:\n" +
     349             :             HelpExampleCli("gethashespersec", "") + HelpExampleRpc("gethashespersec", ""));
     350             : 
     351             :     if (GetTimeMillis() - nHPSTimerStart > 8000)
     352             :         return (int64_t)0;
     353             :     return (int64_t)dHashesPerSec;
     354             : }
     355             : #endif
     356             : 
     357             : 
     358             : UniValue getmininginfo(const JSONRPCRequest& request)
     359             : {
     360             :     if (request.fHelp || request.params.size() != 0)
     361             :         throw std::runtime_error(
     362             :             "getmininginfo\n"
     363             :             "\nReturns a json object containing mining-related information."
     364             : 
     365             :             "\nResult:\n"
     366             :             "{\n"
     367             :             "  \"blocks\": nnn,             (numeric) The current block\n"
     368             :             "  \"currentblocksize\": nnn,   (numeric) The last block size\n"
     369             :             "  \"currentblocktx\": nnn,     (numeric) The last block transaction\n"
     370             :             "  \"difficulty\": xxx.xxxxx    (numeric) The current difficulty\n"
     371             :             "  \"generate\": true|false     (boolean) If the generation is on or off (see getgenerate or setgenerate calls)\n"
     372             :             "  \"genproclimit\": n          (numeric) The processor limit for generation. -1 if no generation. (see getgenerate or setgenerate calls)\n"
     373             :             "  \"hashespersec\": n          (numeric) The hashes per second of the generation, or 0 if no generation.\n"
     374             :             "  \"pooledtx\": n              (numeric) The size of the mem pool\n"
     375             :             "  \"testnet\": true|false      (boolean) If using testnet or not\n"
     376             :             "  \"chain\": \"xxxx\",         (string) current network name (main, test, regtest)\n"
     377             :             "  \"warnings\": \"...\"        (string) any network and blockchain warnings\n"
     378             :             "  \"errors\": \"...\"          (string) DEPRECATED. Same as warnings. Only shown when bitcoind is started with -deprecatedrpc=getmininginfo\n"
     379             :             "}\n"
     380             : 
     381             :             "\nExamples:\n" +
     382             :             HelpExampleCli("getmininginfo", "") + HelpExampleRpc("getmininginfo", ""));
     383             : 
     384             :     LOCK(cs_main);
     385             : 
     386             :     UniValue obj(UniValue::VOBJ);
     387             :     obj.pushKV("blocks", (int)chainActive.Height());
     388             :     obj.pushKV("currentblocksize", (uint64_t)nLastBlockSize);
     389             :     obj.pushKV("currentblocktx", (uint64_t)nLastBlockTx);
     390             :     obj.pushKV("difficulty", (double)GetDifficulty());
     391             :     obj.pushKV("genproclimit", (int)gArgs.GetArg("-genproclimit", -1));
     392             :     obj.pushKV("networkhashps", getnetworkhashps(request));
     393             :     obj.pushKV("pooledtx", (uint64_t)mempool.size());
     394             :     obj.pushKV("testnet", Params().IsTestnet());
     395             :     obj.pushKV("chain", Params().NetworkIDString());
     396             :     obj.pushKV("errors", GetWarnings("statusbar"));
     397             :     if (IsDeprecatedRPCEnabled("getmininginfo")) {
     398             :         obj.pushKV("errors", GetWarnings("statusbar"));
     399             :     } else {
     400             :         obj.pushKV("warnings", GetWarnings("statusbar"));
     401             :     }
     402             : #ifdef ENABLE_WALLET
     403             :     obj.pushKV("generate", getgenerate(request));
     404             :     obj.pushKV("hashespersec", gethashespersec(request));
     405             : #endif
     406             :     return obj;
     407             : }
     408             : #endif // ENABLE_MINING_RPC
     409             : 
     410             : // NOTE: Unlike wallet RPC (which use BTC values), mining RPCs follow GBT (BIP 22) in using satoshi amounts
     411           2 : UniValue prioritisetransaction(const JSONRPCRequest& request)
     412             : {
     413           2 :     if (request.fHelp || request.params.size() != 2)
     414           0 :         throw std::runtime_error(
     415             :             "prioritisetransaction \"txid\" priority_delta fee_delta\n"
     416             :             "Accepts the transaction into mined blocks at a higher (or lower) priority\n"
     417             : 
     418             :             "\nArguments:\n"
     419             :             "1. \"txid\"       (string, required) The transaction id.\n"
     420             :             "2. fee_delta      (numeric, required) The fee value (in satoshis) to add (or subtract, if negative).\n"
     421             :             "                  The fee is not actually paid, only the algorithm for selecting transactions into a block\n"
     422             :             "                  considers the transaction as it would have paid a higher (or lower) fee.\n"
     423             : 
     424             :             "\nResult\n"
     425             :             "true              (boolean) Returns true\n"
     426             : 
     427           0 :             "\nExamples:\n" +
     428           0 :             HelpExampleCli("prioritisetransaction", "\"txid\" 10000") + HelpExampleRpc("prioritisetransaction", "\"txid\", 10000"));
     429             : 
     430           2 :     LOCK(cs_main);
     431             : 
     432           2 :     uint256 hash = ParseHashStr(request.params[0].get_str(), "txid");
     433           2 :     CAmount nAmount = request.params[1].get_int64();
     434             : 
     435           2 :     mempool.PrioritiseTransaction(hash, nAmount);
     436           4 :     return true;
     437             : }
     438             : 
     439             : // NOTE: Assumes a conclusive result; if result is inconclusive, it must be handled by caller
     440          24 : static UniValue BIP22ValidationResult(const CValidationState& state)
     441             : {
     442          24 :     if (state.IsValid())
     443          16 :         return NullUniValue;
     444             : 
     445          32 :     std::string strRejectReason = state.GetRejectReason();
     446           8 :     if (state.IsError())
     447           0 :         throw JSONRPCError(RPC_VERIFY_ERROR, strRejectReason);
     448           8 :     if (state.IsInvalid()) {
     449           8 :         if (strRejectReason.empty())
     450           4 :             return "rejected";
     451           4 :         return strRejectReason;
     452             :     }
     453             :     // Should be impossible
     454           0 :     return "valid?";
     455             : }
     456             : 
     457             : #ifdef ENABLE_MINING_RPC
     458             : UniValue getblocktemplate(const JSONRPCRequest& request)
     459             : {
     460             :     CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
     461             : 
     462             :     if (request.fHelp || request.params.size() > 1)
     463             :         throw std::runtime_error(
     464             :             "getblocktemplate ( \"template_request\" )\n"
     465             :             "\nIf the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n"
     466             :             "It returns data needed to construct a block to work on.\n"
     467             :             "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n"
     468             : 
     469             :             "\nArguments:\n"
     470             :             "1. template_request         (json object, optional) A json object in the following spec\n"
     471             :             "     {\n"
     472             :             "       \"mode\":\"template\"    (string, optional) This must be set to \"template\" or omitted\n"
     473             :             "       \"capabilities\":[       (array, optional) A list of strings\n"
     474             :             "           \"support\"           (string) client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'\n"
     475             :             "           ,...\n"
     476             :             "         ]\n"
     477             :             "     }\n"
     478             :             "\n"
     479             : 
     480             :             "\nResult:\n"
     481             :             "{\n"
     482             :             "  \"version\" : n,                    (numeric) The block version\n"
     483             :             "  \"previousblockhash\" : \"xxxx\",    (string) The hash of current highest block\n"
     484             :             "  \"transactions\" : [                (array) contents of non-coinbase transactions that should be included in the next block\n"
     485             :             "      {\n"
     486             :             "         \"data\" : \"xxxx\",          (string) transaction data encoded in hexadecimal (byte-for-byte)\n"
     487             :             "         \"hash\" : \"xxxx\",          (string) hash/id encoded in little-endian hexadecimal\n"
     488             :             "         \"depends\" : [              (array) array of numbers \n"
     489             :             "             n                        (numeric) transactions before this one (by 1-based index in 'transactions' list) that must be present in the final block if this one is\n"
     490             :             "             ,...\n"
     491             :             "         ],\n"
     492             :             "         \"fee\": n,                   (numeric) difference in value between transaction inputs and outputs (in upiv); for coinbase transactions, this is a negative Number of the total collected block fees (ie, not including the block subsidy); if key is not present, fee is unknown and clients MUST NOT assume there isn't one\n"
     493             :             "         \"sigops\" : n,               (numeric) total number of SigOps, as counted for purposes of block limits; if key is not present, sigop count is unknown and clients MUST NOT assume there aren't any\n"
     494             :             "         \"required\" : true|false     (boolean) if provided and true, this transaction must be in the final block\n"
     495             :             "      }\n"
     496             :             "      ,...\n"
     497             :             "  ],\n"
     498             :             "  \"coinbaseaux\" : {                  (json object) data that should be included in the coinbase's scriptSig content\n"
     499             :             "      \"flags\" : \"flags\"            (string) \n"
     500             :             "  },\n"
     501             :             "  \"coinbasevalue\" : n,               (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in upiv)\n"
     502             :             "  \"coinbasetxn\" : { ... },           (json object) information for coinbase transaction\n"
     503             :             "  \"target\" : \"xxxx\",               (string) The hash target\n"
     504             :             "  \"mintime\" : xxx,                   (numeric) The minimum timestamp appropriate for next block time in seconds since epoch (Jan 1 1970 GMT)\n"
     505             :             "  \"mutable\" : [                      (array of string) list of ways the block template may be changed \n"
     506             :             "     \"value\"                         (string) A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'\n"
     507             :             "     ,...\n"
     508             :             "  ],\n"
     509             :             "  \"noncerange\" : \"00000000ffffffff\",   (string) A range of valid nonces\n"
     510             :             "  \"sigoplimit\" : n,                 (numeric) limit of sigops in blocks\n"
     511             :             "  \"sizelimit\" : n,                  (numeric) limit of block size\n"
     512             :             "  \"curtime\" : ttt,                  (numeric) current timestamp in seconds since epoch (Jan 1 1970 GMT)\n"
     513             :             "  \"bits\" : \"xxx\",                 (string) compressed target of next block\n"
     514             :             "  \"height\" : n                      (numeric) The height of the next block\n"
     515             :             "  \"payee\" : \"xxx\",                (string) required payee for the next block\n"
     516             :             "  \"payee_amount\" : n,               (numeric) required amount to pay\n"
     517             :             "  \"votes\" : [\n                     (array) show vote candidates\n"
     518             :             "        { ... }                       (json object) vote candidate\n"
     519             :             "        ,...\n"
     520             :             "  ],\n"
     521             :             "  \"enforce_masternode_payments\" : true|false  (boolean) true, if masternode payments are enforced\n"
     522             :             "}\n"
     523             : 
     524             :             "\nExamples:\n" +
     525             :             HelpExampleCli("getblocktemplate", "") + HelpExampleRpc("getblocktemplate", ""));
     526             : 
     527             :     LOCK(cs_main);
     528             : 
     529             :     std::string strMode = "template";
     530             :     UniValue lpval = NullUniValue;
     531             :     if (request.params.size() > 0) {
     532             :         const UniValue& oparam = request.params[0].get_obj();
     533             :         const UniValue& modeval = find_value(oparam, "mode");
     534             :         if (modeval.isStr())
     535             :             strMode = modeval.get_str();
     536             :         else if (modeval.isNull()) {
     537             :             /* Do nothing */
     538             :         } else
     539             :             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
     540             :         lpval = find_value(oparam, "longpollid");
     541             : 
     542             :         if (strMode == "proposal") {
     543             :             const UniValue& dataval = find_value(oparam, "data");
     544             :             if (!dataval.isStr())
     545             :                 throw JSONRPCError(RPC_TYPE_ERROR, "Missing data String key for proposal");
     546             : 
     547             :             CBlock block;
     548             :             if (!DecodeHexBlk(block, dataval.get_str()))
     549             :                 throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
     550             : 
     551             :             uint256 hash = block.GetHash();
     552             :             CBlockIndex* pindex = LookupBlockIndex(hash);
     553             :             if (pindex) {
     554             :                 if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
     555             :                     return "duplicate";
     556             :                 if (pindex->nStatus & BLOCK_FAILED_MASK)
     557             :                     return "duplicate-invalid";
     558             :                 return "duplicate-inconclusive";
     559             :             }
     560             : 
     561             :             CBlockIndex* const pindexPrev = chainActive.Tip();
     562             :             // TestBlockValidity only supports blocks built on the current Tip
     563             :             if (block.hashPrevBlock != pindexPrev->GetBlockHash())
     564             :                 return "inconclusive-not-best-prevblk";
     565             :             CValidationState state;
     566             :             TestBlockValidity(state, block, pindexPrev, false, true);
     567             :             return BIP22ValidationResult(state);
     568             :         }
     569             :     }
     570             : 
     571             :     if (strMode != "template")
     572             :         throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
     573             : 
     574             :     if(!g_connman)
     575             :         throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled");
     576             : 
     577             :     if (g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) == 0)
     578             :         throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "PIVX is not connected!");
     579             : 
     580             :     if (IsInitialBlockDownload())
     581             :         throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "PIVX is downloading blocks...");
     582             : 
     583             :     static unsigned int nTransactionsUpdatedLast;
     584             : 
     585             :     if (!lpval.isNull()) {
     586             :         // Wait to respond until either the best block changes, OR a minute has passed and there are more transactions
     587             :         uint256 hashWatchedChain;
     588             :         std::chrono::steady_clock::time_point checktxtime;
     589             :         unsigned int nTransactionsUpdatedLastLP;
     590             : 
     591             :         if (lpval.isStr()) {
     592             :             // Format: <hashBestChain><nTransactionsUpdatedLast>
     593             :             std::string lpstr = lpval.get_str();
     594             : 
     595             :             hashWatchedChain = ParseHashV(lpstr.substr(0, 64), "longpollid");
     596             :             nTransactionsUpdatedLastLP = atoi64(lpstr.substr(64));
     597             :         } else {
     598             :             // NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier
     599             :             hashWatchedChain = chainActive.Tip()->GetBlockHash();
     600             :             nTransactionsUpdatedLastLP = nTransactionsUpdatedLast;
     601             :         }
     602             : 
     603             :         // Release the wallet and main lock while waiting
     604             :         LEAVE_CRITICAL_SECTION(cs_main);
     605             :         {
     606             :             checktxtime = std::chrono::steady_clock::now() + std::chrono::minutes(1);
     607             : 
     608             :             WAIT_LOCK(g_best_block_mutex, lock);
     609             :             while (g_best_block == hashWatchedChain && IsRPCRunning()) {
     610             :                 if (g_best_block_cv.wait_until(lock, checktxtime) == std::cv_status::timeout)
     611             :                 {
     612             :                     // Timeout: Check transactions for update
     613             :                     if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
     614             :                         break;
     615             :                     checktxtime += std::chrono::seconds(10);
     616             :                 }
     617             :             }
     618             :         }
     619             :         ENTER_CRITICAL_SECTION(cs_main);
     620             : 
     621             :         if (!IsRPCRunning())
     622             :             throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
     623             :         // TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners?
     624             :     }
     625             : 
     626             :     // Update block
     627             :     static CBlockIndex* pindexPrev;
     628             :     static int64_t nStart;
     629             :     static std::unique_ptr<CBlockTemplate> pblocktemplate;
     630             :     if (pindexPrev != chainActive.Tip() ||
     631             :         (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5)) {
     632             :         // Clear pindexPrev so future calls make a new block, despite any failures from here on
     633             :         pindexPrev = nullptr;
     634             : 
     635             :         // Store the chainActive.Tip() used before CreateNewBlock, to avoid races
     636             :         nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
     637             :         CBlockIndex* pindexPrevNew = chainActive.Tip();
     638             :         nStart = GetTime();
     639             : 
     640             :         // Create new block
     641             :         if (pblocktemplate) {
     642             :             pblocktemplate.release();
     643             :             pblocktemplate = nullptr;
     644             :         }
     645             :         CScript scriptDummy = CScript() << OP_TRUE;
     646             :         pblocktemplate = BlockAssembler(Params(), DEFAULT_PRINTPRIORITY).CreateNewBlock(scriptDummy, pwallet, false);
     647             :         if (!pblocktemplate)
     648             :             throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
     649             : 
     650             :         // Need to update only after we know CreateNewBlock succeeded
     651             :         pindexPrev = pindexPrevNew;
     652             :     }
     653             :     CBlock* pblock = &pblocktemplate->block; // pointer for convenience
     654             : 
     655             :     // Update nTime
     656             :     UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
     657             :     pblock->nNonce = 0;
     658             : 
     659             :     UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
     660             : 
     661             :     UniValue transactions(UniValue::VARR);
     662             :     std::map<uint256, int64_t> setTxIndex;
     663             :     int i = 0;
     664             :     for (const auto& txIn : pblock->vtx) {
     665             :         const CTransaction& tx = *txIn;
     666             :         const uint256& txHash = tx.GetHash();
     667             :         setTxIndex[txHash] = i++;
     668             : 
     669             :         if (tx.IsCoinBase())
     670             :             continue;
     671             : 
     672             :         UniValue entry(UniValue::VOBJ);
     673             : 
     674             :         entry.pushKV("data", EncodeHexTx(tx));
     675             : 
     676             :         entry.pushKV("hash", txHash.GetHex());
     677             : 
     678             :         UniValue deps(UniValue::VARR);
     679             :         for (const CTxIn& in : tx.vin) {
     680             :             if (setTxIndex.count(in.prevout.hash))
     681             :                 deps.push_back(setTxIndex[in.prevout.hash]);
     682             :         }
     683             :         entry.pushKV("depends", deps);
     684             : 
     685             :         int index_in_template = i - 1;
     686             :         entry.pushKV("fee", pblocktemplate->vTxFees[index_in_template]);
     687             :         entry.pushKV("sigops", pblocktemplate->vTxSigOps[index_in_template]);
     688             : 
     689             :         transactions.push_back(entry);
     690             :     }
     691             : 
     692             :     UniValue aux(UniValue::VOBJ);
     693             :     aux.pushKV("flags", HexStr(COINBASE_FLAGS));
     694             : 
     695             :     arith_uint256& hashTarget = arith_uint256().SetCompact(pblock->nBits);
     696             : 
     697             :     static UniValue aMutable(UniValue::VARR);
     698             :     if (aMutable.empty()) {
     699             :         aMutable.push_back("time");
     700             :         aMutable.push_back("transactions");
     701             :         aMutable.push_back("prevblock");
     702             :     }
     703             : 
     704             :     UniValue aVotes(UniValue::VARR);
     705             : 
     706             :     UniValue result(UniValue::VOBJ);
     707             :     result.pushKV("capabilities", aCaps);
     708             :     result.pushKV("version", pblock->nVersion);
     709             :     result.pushKV("previousblockhash", pblock->hashPrevBlock.GetHex());
     710             :     result.pushKV("transactions", transactions);
     711             :     result.pushKV("coinbaseaux", aux);
     712             :     result.pushKV("coinbasevalue", (int64_t)pblock->vtx[0]->GetValueOut());
     713             :     result.pushKV("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast));
     714             :     result.pushKV("target", hashTarget.GetHex());
     715             :     result.pushKV("mintime", (int64_t)pindexPrev->GetMedianTimePast() + 1);
     716             :     result.pushKV("mutable", aMutable);
     717             :     result.pushKV("noncerange", "00000000ffffffff");
     718             : //    result.pushKV("sigoplimit", (int64_t)MAX_BLOCK_SIGOPS);
     719             : //    result.pushKV("sizelimit", (int64_t)MAX_BLOCK_SIZE);
     720             :     result.pushKV("curtime", pblock->GetBlockTime());
     721             :     result.pushKV("bits", strprintf("%08x", pblock->nBits));
     722             :     result.pushKV("height", (int64_t)(pindexPrev->nHeight + 1));
     723             :     result.pushKV("votes", aVotes);
     724             :     result.pushKV("enforce_masternode_payments", true);
     725             : 
     726             :     return result;
     727             : }
     728             : #endif // ENABLE_MINING_RPC
     729             : 
     730          50 : UniValue submitblock(const JSONRPCRequest& request)
     731             : {
     732          50 :     if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
     733           0 :         throw std::runtime_error(
     734             :             "submitblock \"hexdata\" ( \"jsonparametersobject\" )\n"
     735             :             "\nAttempts to submit new block to network.\n"
     736             :             "The 'jsonparametersobject' parameter is currently ignored.\n"
     737             :             "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n"
     738             : 
     739             :             "\nArguments\n"
     740             :             "1. \"hexdata\"    (string, required) the hex-encoded block data to submit\n"
     741             :             "2. \"parameters\"     (string, optional) object of optional parameters\n"
     742             :             "    {\n"
     743             :             "      \"workid\" : \"id\"    (string, optional) if the server provided a workid, it MUST be included with submissions\n"
     744             :             "    }\n"
     745             : 
     746             :             "\nResult:\n"
     747             : 
     748           0 :             "\nExamples:\n" +
     749           0 :             HelpExampleCli("submitblock", "\"mydata\"") + HelpExampleRpc("submitblock", "\"mydata\""));
     750             : 
     751         100 :     std::shared_ptr<CBlock> blockptr = std::make_shared<CBlock>();
     752          50 :     CBlock& block = *blockptr;
     753          50 :     if (!DecodeHexBlk(block, request.params[0].get_str()))
     754           0 :         throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
     755             : 
     756          50 :     if (block.vtx.empty() || !block.vtx[0]->IsCoinBase()) {
     757           0 :         throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block does not start with a coinbase");
     758             :     }
     759             : 
     760          50 :     uint256 hash = block.GetHash();
     761          50 :     bool fBlockPresent = false;
     762          50 :     {
     763          50 :         LOCK(cs_main);
     764          50 :         CBlockIndex* pindex = LookupBlockIndex(hash);
     765          50 :         if (pindex) {
     766           0 :             if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
     767           0 :                 return "duplicate";
     768           0 :             if (pindex->nStatus & BLOCK_FAILED_MASK)
     769           0 :                 return "duplicate-invalid";
     770             :             // Otherwise, we might only have the header - process the block before returning
     771             :             fBlockPresent = true;
     772             :         }
     773             :     }
     774             : 
     775         100 :     BlockStateCatcherWrapper sc(block.GetHash());
     776          50 :     sc.registerEvent();
     777          50 :     bool fAccepted = ProcessNewBlock(blockptr, nullptr);
     778          50 :     if (fBlockPresent) {
     779           0 :         if (fAccepted && !sc.get().found)
     780           0 :             return "duplicate-inconclusive";
     781           0 :         return "duplicate";
     782             :     }
     783          50 :     if (fAccepted) {
     784          40 :         if (!sc.get().found)
     785          26 :             return "inconclusive";
     786             :     }
     787          24 :     return BIP22ValidationResult(sc.get().state);
     788             : }
     789             : 
     790         125 : UniValue estimatefee(const JSONRPCRequest& request)
     791             : {
     792         125 :     if (request.fHelp || request.params.size() != 1)
     793           0 :         throw std::runtime_error(
     794             :             "estimatefee nblocks\n"
     795             :             "\nEstimates the approximate fee per kilobyte\n"
     796             :             "needed for a transaction to begin confirmation\n"
     797             :             "within nblocks blocks.\n"
     798             : 
     799             :             "\nArguments:\n"
     800             :             "1. nblocks     (numeric)\n"
     801             : 
     802             :             "\nResult:\n"
     803             :             "n :    (numeric) estimated fee-per-kilobyte\n"
     804             :             "\n"
     805             :             "-1.0 is returned if not enough transactions and\n"
     806             :             "blocks have been observed to make an estimate.\n"
     807             : 
     808           0 :             "\nExample:\n" +
     809           0 :             HelpExampleCli("estimatefee", "6"));
     810             : 
     811         125 :     RPCTypeCheck(request.params, {UniValue::VNUM});
     812             : 
     813         125 :     int nBlocks = request.params[0].get_int();
     814         125 :     if (nBlocks < 1)
     815           0 :         nBlocks = 1;
     816             : 
     817         125 :     CFeeRate feeRate = mempool.estimateFee(nBlocks);
     818         125 :     if (feeRate == CFeeRate(0))
     819           1 :         return -1.0;
     820             : 
     821         124 :     return ValueFromAmount(feeRate.GetFeePerK());
     822             : }
     823             : 
     824          62 : UniValue estimatesmartfee(const JSONRPCRequest& request)
     825             : {
     826          62 :     if (request.fHelp || request.params.size() != 1)
     827           0 :         throw std::runtime_error(
     828             :                 "estimatesmartfee nblocks\n"
     829             :                 "\nDEPRECATED. WARNING: This interface is unstable and may disappear or change!\n"
     830             :                 "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n"
     831             :                 "confirmation within nblocks blocks if possible and return the number of blocks\n"
     832             :                 "for which the estimate is valid.\n"
     833             :                 "\nArguments:\n"
     834             :                 "1. nblocks     (numeric)\n"
     835             :                 "\nResult:\n"
     836             :                 "{\n"
     837             :                 "  \"feerate\" : x.x,     (numeric) estimate fee-per-kilobyte (in BTC)\n"
     838             :                 "  \"blocks\" : n         (numeric) block number where estimate was found\n"
     839             :                 "}\n"
     840             :                 "\n"
     841             :                 "A negative value is returned if not enough transactions and blocks\n"
     842             :                 "have been observed to make an estimate for any number of blocks.\n"
     843             :                 "However it will not return a value below the mempool reject fee.\n"
     844             :                 "\nExample:\n"
     845           0 :                 + HelpExampleCli("estimatesmartfee", "6")
     846           0 :         );
     847             : 
     848          62 :     RPCTypeCheck(request.params, {UniValue::VNUM});
     849             : 
     850          62 :     int nBlocks = request.params[0].get_int();
     851             : 
     852          62 :     UniValue result(UniValue::VOBJ);
     853          62 :     int answerFound;
     854          62 :     CFeeRate feeRate = mempool.estimateSmartFee(nBlocks, &answerFound);
     855         186 :     result.pushKV("feerate", feeRate == CFeeRate(0) ? -1.0 : ValueFromAmount(feeRate.GetFeePerK()));
     856          62 :     result.pushKV("blocks", answerFound);
     857          62 :     return result;
     858             : }
     859             : 
     860             : // clang-format off
     861             : static const CRPCCommand commands[] =
     862             : { //  category              name                      actor (function)         okSafe argNames
     863             :   //  --------------------- ------------------------  -----------------------  ------ --------
     864             :     { "util",               "estimatefee",            &estimatefee,            true,  {"nblocks"} },
     865             :     { "util",               "estimatesmartfee",       &estimatesmartfee,       true,  {"nblocks"} },
     866             :     { "mining",             "prioritisetransaction",  &prioritisetransaction,  true,  {"txid","priority_delta","fee_delta"} },
     867             : 
     868             :     /** Not shown in help */
     869             : #ifdef ENABLE_WALLET
     870             :     { "hidden",             "generate",               &generate,               true,  {"nblocks"} },
     871             :     { "hidden",             "generatetoaddress",      &generatetoaddress,      true,  {"nblocks","address"} },
     872             : #endif
     873             :     { "hidden",             "submitblock",            &submitblock,            true,  {"hexdata","parameters"} },
     874             : #ifdef ENABLE_MINING_RPC
     875             :     { "hidden",             "getblocktemplate",       &getblocktemplate,       true,  {"template_request"} },
     876             :     { "hidden",             "getnetworkhashps",       &getnetworkhashps,       true,  {"nblocks","height"} },
     877             :     { "hidden",             "getmininginfo",          &getmininginfo,          true,  {} },
     878             : #ifdef ENABLE_WALLET
     879             :     { "hidden",             "getgenerate",            &getgenerate,            true,  {} },
     880             :     { "hidden",             "gethashespersec",        &gethashespersec,        true,  {} },
     881             :     { "hidden",             "setgenerate",            &setgenerate,            true,  {"generate","genproclimit"} },
     882             : #endif // ENABLE_WALLET
     883             : #endif // ENABLE_MINING_RPC
     884             : 
     885             : };
     886             : // clang-format on
     887             : 
     888         494 : void RegisterMiningRPCCommands(CRPCTable &tableRPC)
     889             : {
     890        3458 :     for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
     891        2964 :         tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
     892         494 : }

Generated by: LCOV version 1.14