~ubuntu-branches/debian/stretch/bitcoin/stretch

« back to all changes in this revision

Viewing changes to src/rpc/mining.cpp

  • Committer: Package Import Robot
  • Author(s): Anthony Towns
  • Date: 2016-10-21 17:13:13 UTC
  • mfrom: (1.3.2)
  • Revision ID: package-import@ubuntu.com-20161021171313-7eu2ltpbk0xag3q1
Tags: 0.13.0-0.1
* Non-maintainer upload.
* New upstream release.
* Allow compilation with gcc/g++ 6. (Closes: Bug#835963)
* Additional fixes for openssl 1.1 compatibility. (See Bug#828248)
* Check if -latomic is needed (it is on mips*).
* Remove reproducible build patch, since leveldb build system is
  no longer used in 0.13. (See Bug#791834)
* Update description since the blockchain is much more than "several GB"
  now. (Closes: Bug#835809)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (c) 2010 Satoshi Nakamoto
 
2
// Copyright (c) 2009-2015 The Bitcoin Core developers
 
3
// Distributed under the MIT software license, see the accompanying
 
4
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
5
 
 
6
#include "base58.h"
 
7
#include "amount.h"
 
8
#include "chain.h"
 
9
#include "chainparams.h"
 
10
#include "consensus/consensus.h"
 
11
#include "consensus/params.h"
 
12
#include "consensus/validation.h"
 
13
#include "core_io.h"
 
14
#include "init.h"
 
15
#include "main.h"
 
16
#include "miner.h"
 
17
#include "net.h"
 
18
#include "pow.h"
 
19
#include "rpc/server.h"
 
20
#include "txmempool.h"
 
21
#include "util.h"
 
22
#include "utilstrencodings.h"
 
23
#include "validationinterface.h"
 
24
 
 
25
#include <stdint.h>
 
26
 
 
27
#include <boost/assign/list_of.hpp>
 
28
#include <boost/shared_ptr.hpp>
 
29
 
 
30
#include <univalue.h>
 
31
 
 
32
using namespace std;
 
33
 
 
34
/**
 
35
 * Return average network hashes per second based on the last 'lookup' blocks,
 
36
 * or from the last difficulty change if 'lookup' is nonpositive.
 
37
 * If 'height' is nonnegative, compute the estimate at the time when a given block was found.
 
38
 */
 
39
UniValue GetNetworkHashPS(int lookup, int height) {
 
40
    CBlockIndex *pb = chainActive.Tip();
 
41
 
 
42
    if (height >= 0 && height < chainActive.Height())
 
43
        pb = chainActive[height];
 
44
 
 
45
    if (pb == NULL || !pb->nHeight)
 
46
        return 0;
 
47
 
 
48
    // If lookup is -1, then use blocks since last difficulty change.
 
49
    if (lookup <= 0)
 
50
        lookup = pb->nHeight % Params().GetConsensus().DifficultyAdjustmentInterval() + 1;
 
51
 
 
52
    // If lookup is larger than chain, then set it to chain length.
 
53
    if (lookup > pb->nHeight)
 
54
        lookup = pb->nHeight;
 
55
 
 
56
    CBlockIndex *pb0 = pb;
 
57
    int64_t minTime = pb0->GetBlockTime();
 
58
    int64_t maxTime = minTime;
 
59
    for (int i = 0; i < lookup; i++) {
 
60
        pb0 = pb0->pprev;
 
61
        int64_t time = pb0->GetBlockTime();
 
62
        minTime = std::min(time, minTime);
 
63
        maxTime = std::max(time, maxTime);
 
64
    }
 
65
 
 
66
    // In case there's a situation where minTime == maxTime, we don't want a divide by zero exception.
 
67
    if (minTime == maxTime)
 
68
        return 0;
 
69
 
 
70
    arith_uint256 workDiff = pb->nChainWork - pb0->nChainWork;
 
71
    int64_t timeDiff = maxTime - minTime;
 
72
 
 
73
    return workDiff.getdouble() / timeDiff;
 
74
}
 
75
 
 
76
UniValue getnetworkhashps(const UniValue& params, bool fHelp)
 
77
{
 
78
    if (fHelp || params.size() > 2)
 
79
        throw runtime_error(
 
80
            "getnetworkhashps ( blocks height )\n"
 
81
            "\nReturns the estimated network hashes per second based on the last n blocks.\n"
 
82
            "Pass in [blocks] to override # of blocks, -1 specifies since last difficulty change.\n"
 
83
            "Pass in [height] to estimate the network speed at the time when a certain block was found.\n"
 
84
            "\nArguments:\n"
 
85
            "1. blocks     (numeric, optional, default=120) The number of blocks, or -1 for blocks since last difficulty change.\n"
 
86
            "2. height     (numeric, optional, default=-1) To estimate at the time of the given height.\n"
 
87
            "\nResult:\n"
 
88
            "x             (numeric) Hashes per second estimated\n"
 
89
            "\nExamples:\n"
 
90
            + HelpExampleCli("getnetworkhashps", "")
 
91
            + HelpExampleRpc("getnetworkhashps", "")
 
92
       );
 
93
 
 
94
    LOCK(cs_main);
 
95
    return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1);
 
96
}
 
97
 
 
98
UniValue generateBlocks(boost::shared_ptr<CReserveScript> coinbaseScript, int nGenerate, uint64_t nMaxTries, bool keepScript)
 
99
{
 
100
    static const int nInnerLoopCount = 0x10000;
 
101
    int nHeightStart = 0;
 
102
    int nHeightEnd = 0;
 
103
    int nHeight = 0;
 
104
 
 
105
    {   // Don't keep cs_main locked
 
106
        LOCK(cs_main);
 
107
        nHeightStart = chainActive.Height();
 
108
        nHeight = nHeightStart;
 
109
        nHeightEnd = nHeightStart+nGenerate;
 
110
    }
 
111
    unsigned int nExtraNonce = 0;
 
112
    UniValue blockHashes(UniValue::VARR);
 
113
    while (nHeight < nHeightEnd)
 
114
    {
 
115
        std::unique_ptr<CBlockTemplate> pblocktemplate(BlockAssembler(Params()).CreateNewBlock(coinbaseScript->reserveScript));
 
116
        if (!pblocktemplate.get())
 
117
            throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
 
118
        CBlock *pblock = &pblocktemplate->block;
 
119
        {
 
120
            LOCK(cs_main);
 
121
            IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce);
 
122
        }
 
123
        while (nMaxTries > 0 && pblock->nNonce < nInnerLoopCount && !CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus())) {
 
124
            ++pblock->nNonce;
 
125
            --nMaxTries;
 
126
        }
 
127
        if (nMaxTries == 0) {
 
128
            break;
 
129
        }
 
130
        if (pblock->nNonce == nInnerLoopCount) {
 
131
            continue;
 
132
        }
 
133
        CValidationState state;
 
134
        if (!ProcessNewBlock(state, Params(), NULL, pblock, true, NULL))
 
135
            throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
 
136
        ++nHeight;
 
137
        blockHashes.push_back(pblock->GetHash().GetHex());
 
138
 
 
139
        //mark script as important because it was used at least for one coinbase output if the script came from the wallet
 
140
        if (keepScript)
 
141
        {
 
142
            coinbaseScript->KeepScript();
 
143
        }
 
144
    }
 
145
    return blockHashes;
 
146
}
 
147
 
 
148
UniValue generate(const UniValue& params, bool fHelp)
 
149
{
 
150
    if (fHelp || params.size() < 1 || params.size() > 2)
 
151
        throw runtime_error(
 
152
            "generate numblocks ( maxtries )\n"
 
153
            "\nMine up to numblocks blocks immediately (before the RPC call returns)\n"
 
154
            "\nArguments:\n"
 
155
            "1. numblocks    (numeric, required) How many blocks are generated immediately.\n"
 
156
            "2. maxtries     (numeric, optional) How many iterations to try (default = 1000000).\n"
 
157
            "\nResult\n"
 
158
            "[ blockhashes ]     (array) hashes of blocks generated\n"
 
159
            "\nExamples:\n"
 
160
            "\nGenerate 11 blocks\n"
 
161
            + HelpExampleCli("generate", "11")
 
162
        );
 
163
 
 
164
    int nGenerate = params[0].get_int();
 
165
    uint64_t nMaxTries = 1000000;
 
166
    if (params.size() > 1) {
 
167
        nMaxTries = params[1].get_int();
 
168
    }
 
169
 
 
170
    boost::shared_ptr<CReserveScript> coinbaseScript;
 
171
    GetMainSignals().ScriptForMining(coinbaseScript);
 
172
 
 
173
    // If the keypool is exhausted, no script is returned at all.  Catch this.
 
174
    if (!coinbaseScript)
 
175
        throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
 
176
 
 
177
    //throw an error if no script was provided
 
178
    if (coinbaseScript->reserveScript.empty())
 
179
        throw JSONRPCError(RPC_INTERNAL_ERROR, "No coinbase script available (mining requires a wallet)");
 
180
 
 
181
    return generateBlocks(coinbaseScript, nGenerate, nMaxTries, true);
 
182
}
 
183
 
 
184
UniValue generatetoaddress(const UniValue& params, bool fHelp)
 
185
{
 
186
    if (fHelp || params.size() < 2 || params.size() > 3)
 
187
        throw runtime_error(
 
188
            "generatetoaddress numblocks address (maxtries)\n"
 
189
            "\nMine blocks immediately to a specified address (before the RPC call returns)\n"
 
190
            "\nArguments:\n"
 
191
            "1. numblocks    (numeric, required) How many blocks are generated immediately.\n"
 
192
            "2. address    (string, required) The address to send the newly generated bitcoin to.\n"
 
193
            "3. maxtries     (numeric, optional) How many iterations to try (default = 1000000).\n"
 
194
            "\nResult\n"
 
195
            "[ blockhashes ]     (array) hashes of blocks generated\n"
 
196
            "\nExamples:\n"
 
197
            "\nGenerate 11 blocks to myaddress\n"
 
198
            + HelpExampleCli("generatetoaddress", "11 \"myaddress\"")
 
199
        );
 
200
 
 
201
    int nGenerate = params[0].get_int();
 
202
    uint64_t nMaxTries = 1000000;
 
203
    if (params.size() > 2) {
 
204
        nMaxTries = params[2].get_int();
 
205
    }
 
206
 
 
207
    CBitcoinAddress address(params[1].get_str());
 
208
    if (!address.IsValid())
 
209
        throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Error: Invalid address");
 
210
    
 
211
    boost::shared_ptr<CReserveScript> coinbaseScript(new CReserveScript());
 
212
    coinbaseScript->reserveScript = GetScriptForDestination(address.Get());
 
213
 
 
214
    return generateBlocks(coinbaseScript, nGenerate, nMaxTries, false);
 
215
}
 
216
 
 
217
UniValue getmininginfo(const UniValue& params, bool fHelp)
 
218
{
 
219
    if (fHelp || params.size() != 0)
 
220
        throw runtime_error(
 
221
            "getmininginfo\n"
 
222
            "\nReturns a json object containing mining-related information."
 
223
            "\nResult:\n"
 
224
            "{\n"
 
225
            "  \"blocks\": nnn,             (numeric) The current block\n"
 
226
            "  \"currentblocksize\": nnn,   (numeric) The last block size\n"
 
227
            "  \"currentblockweight\": nnn, (numeric) The last block weight\n"
 
228
            "  \"currentblocktx\": nnn,     (numeric) The last block transaction\n"
 
229
            "  \"difficulty\": xxx.xxxxx    (numeric) The current difficulty\n"
 
230
            "  \"errors\": \"...\"          (string) Current errors\n"
 
231
            "  \"pooledtx\": n              (numeric) The size of the mem pool\n"
 
232
            "  \"testnet\": true|false      (boolean) If using testnet or not\n"
 
233
            "  \"chain\": \"xxxx\",         (string) current network name as defined in BIP70 (main, test, regtest)\n"
 
234
            "}\n"
 
235
            "\nExamples:\n"
 
236
            + HelpExampleCli("getmininginfo", "")
 
237
            + HelpExampleRpc("getmininginfo", "")
 
238
        );
 
239
 
 
240
 
 
241
    LOCK(cs_main);
 
242
 
 
243
    UniValue obj(UniValue::VOBJ);
 
244
    obj.push_back(Pair("blocks",           (int)chainActive.Height()));
 
245
    obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize));
 
246
    obj.push_back(Pair("currentblockweight", (uint64_t)nLastBlockWeight));
 
247
    obj.push_back(Pair("currentblocktx",   (uint64_t)nLastBlockTx));
 
248
    obj.push_back(Pair("difficulty",       (double)GetDifficulty()));
 
249
    obj.push_back(Pair("errors",           GetWarnings("statusbar")));
 
250
    obj.push_back(Pair("networkhashps",    getnetworkhashps(params, false)));
 
251
    obj.push_back(Pair("pooledtx",         (uint64_t)mempool.size()));
 
252
    obj.push_back(Pair("testnet",          Params().TestnetToBeDeprecatedFieldRPC()));
 
253
    obj.push_back(Pair("chain",            Params().NetworkIDString()));
 
254
    return obj;
 
255
}
 
256
 
 
257
 
 
258
// NOTE: Unlike wallet RPC (which use BTC values), mining RPCs follow GBT (BIP 22) in using satoshi amounts
 
259
UniValue prioritisetransaction(const UniValue& params, bool fHelp)
 
260
{
 
261
    if (fHelp || params.size() != 3)
 
262
        throw runtime_error(
 
263
            "prioritisetransaction <txid> <priority delta> <fee delta>\n"
 
264
            "Accepts the transaction into mined blocks at a higher (or lower) priority\n"
 
265
            "\nArguments:\n"
 
266
            "1. \"txid\"       (string, required) The transaction id.\n"
 
267
            "2. priority delta (numeric, required) The priority to add or subtract.\n"
 
268
            "                  The transaction selection algorithm considers the tx as it would have a higher priority.\n"
 
269
            "                  (priority of a transaction is calculated: coinage * value_in_satoshis / txsize) \n"
 
270
            "3. fee delta      (numeric, required) The fee value (in satoshis) to add (or subtract, if negative).\n"
 
271
            "                  The fee is not actually paid, only the algorithm for selecting transactions into a block\n"
 
272
            "                  considers the transaction as it would have paid a higher (or lower) fee.\n"
 
273
            "\nResult\n"
 
274
            "true              (boolean) Returns true\n"
 
275
            "\nExamples:\n"
 
276
            + HelpExampleCli("prioritisetransaction", "\"txid\" 0.0 10000")
 
277
            + HelpExampleRpc("prioritisetransaction", "\"txid\", 0.0, 10000")
 
278
        );
 
279
 
 
280
    LOCK(cs_main);
 
281
 
 
282
    uint256 hash = ParseHashStr(params[0].get_str(), "txid");
 
283
    CAmount nAmount = params[2].get_int64();
 
284
 
 
285
    mempool.PrioritiseTransaction(hash, params[0].get_str(), params[1].get_real(), nAmount);
 
286
    return true;
 
287
}
 
288
 
 
289
 
 
290
// NOTE: Assumes a conclusive result; if result is inconclusive, it must be handled by caller
 
291
static UniValue BIP22ValidationResult(const CValidationState& state)
 
292
{
 
293
    if (state.IsValid())
 
294
        return NullUniValue;
 
295
 
 
296
    std::string strRejectReason = state.GetRejectReason();
 
297
    if (state.IsError())
 
298
        throw JSONRPCError(RPC_VERIFY_ERROR, strRejectReason);
 
299
    if (state.IsInvalid())
 
300
    {
 
301
        if (strRejectReason.empty())
 
302
            return "rejected";
 
303
        return strRejectReason;
 
304
    }
 
305
    // Should be impossible
 
306
    return "valid?";
 
307
}
 
308
 
 
309
std::string gbt_vb_name(const Consensus::DeploymentPos pos) {
 
310
    const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
 
311
    std::string s = vbinfo.name;
 
312
    if (!vbinfo.gbt_force) {
 
313
        s.insert(s.begin(), '!');
 
314
    }
 
315
    return s;
 
316
}
 
317
 
 
318
UniValue getblocktemplate(const UniValue& params, bool fHelp)
 
319
{
 
320
    if (fHelp || params.size() > 1)
 
321
        throw runtime_error(
 
322
            "getblocktemplate ( \"jsonrequestobject\" )\n"
 
323
            "\nIf the request parameters include a 'mode' key, that is used to explicitly select between the default 'template' request or a 'proposal'.\n"
 
324
            "It returns data needed to construct a block to work on.\n"
 
325
            "For full specification, see BIPs 22 and 9:\n"
 
326
            "    https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki\n"
 
327
            "    https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki#getblocktemplate_changes\n"
 
328
 
 
329
            "\nArguments:\n"
 
330
            "1. \"jsonrequestobject\"       (string, optional) A json object in the following spec\n"
 
331
            "     {\n"
 
332
            "       \"mode\":\"template\"    (string, optional) This must be set to \"template\" or omitted\n"
 
333
            "       \"capabilities\":[       (array, optional) A list of strings\n"
 
334
            "           \"support\"           (string) client side supported feature, 'longpoll', 'coinbasetxn', 'coinbasevalue', 'proposal', 'serverlist', 'workid'\n"
 
335
            "           ,...\n"
 
336
            "         ]\n"
 
337
            "     }\n"
 
338
            "\n"
 
339
 
 
340
            "\nResult:\n"
 
341
            "{\n"
 
342
            "  \"version\" : n,                    (numeric) The block version\n"
 
343
            "  \"rules\" : [ \"rulename\", ... ],    (array of strings) specific block rules that are to be enforced\n"
 
344
            "  \"vbavailable\" : {                 (json object) set of pending, supported versionbit (BIP 9) softfork deployments\n"
 
345
            "      \"rulename\" : bitnumber        (numeric) identifies the bit number as indicating acceptance and readiness for the named softfork rule\n"
 
346
            "      ,...\n"
 
347
            "  },\n"
 
348
            "  \"vbrequired\" : n,                 (numeric) bit mask of versionbits the server requires set in submissions\n"
 
349
            "  \"previousblockhash\" : \"xxxx\",    (string) The hash of current highest block\n"
 
350
            "  \"transactions\" : [                (array) contents of non-coinbase transactions that should be included in the next block\n"
 
351
            "      {\n"
 
352
            "         \"data\" : \"xxxx\",          (string) transaction data encoded in hexadecimal (byte-for-byte)\n"
 
353
            "         \"txid\" : \"xxxx\",          (string) transaction id encoded in little-endian hexadecimal\n"
 
354
            "         \"hash\" : \"xxxx\",          (string) hash encoded in little-endian hexadecimal (including witness data)\n"
 
355
            "         \"depends\" : [              (array) array of numbers \n"
 
356
            "             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"
 
357
            "             ,...\n"
 
358
            "         ],\n"
 
359
            "         \"fee\": n,                   (numeric) difference in value between transaction inputs and outputs (in Satoshis); 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"
 
360
            "         \"sigops\" : n,               (numeric) total SigOps cost, as counted for purposes of block limits; if key is not present, sigop cost is unknown and clients MUST NOT assume it is zero\n"
 
361
            "         \"weight\" : n,               (numeric) total transaction weight, as counted for purposes of block limits\n"
 
362
            "         \"required\" : true|false     (boolean) if provided and true, this transaction must be in the final block\n"
 
363
            "      }\n"
 
364
            "      ,...\n"
 
365
            "  ],\n"
 
366
            "  \"coinbaseaux\" : {                  (json object) data that should be included in the coinbase's scriptSig content\n"
 
367
            "      \"flags\" : \"flags\"            (string) \n"
 
368
            "  },\n"
 
369
            "  \"coinbasevalue\" : n,               (numeric) maximum allowable input to coinbase transaction, including the generation award and transaction fees (in Satoshis)\n"
 
370
            "  \"coinbasetxn\" : { ... },           (json object) information for coinbase transaction\n"
 
371
            "  \"target\" : \"xxxx\",               (string) The hash target\n"
 
372
            "  \"mintime\" : xxx,                   (numeric) The minimum timestamp appropriate for next block time in seconds since epoch (Jan 1 1970 GMT)\n"
 
373
            "  \"mutable\" : [                      (array of string) list of ways the block template may be changed \n"
 
374
            "     \"value\"                         (string) A way the block template may be changed, e.g. 'time', 'transactions', 'prevblock'\n"
 
375
            "     ,...\n"
 
376
            "  ],\n"
 
377
            "  \"noncerange\" : \"00000000ffffffff\",   (string) A range of valid nonces\n"
 
378
            "  \"sigoplimit\" : n,                 (numeric) cost limit of sigops in blocks\n"
 
379
            "  \"sizelimit\" : n,                  (numeric) limit of block size\n"
 
380
            "  \"weightlimit\" : n,                (numeric) limit of block weight\n"
 
381
            "  \"curtime\" : ttt,                  (numeric) current timestamp in seconds since epoch (Jan 1 1970 GMT)\n"
 
382
            "  \"bits\" : \"xxx\",                 (string) compressed target of next block\n"
 
383
            "  \"height\" : n                      (numeric) The height of the next block\n"
 
384
            "}\n"
 
385
 
 
386
            "\nExamples:\n"
 
387
            + HelpExampleCli("getblocktemplate", "")
 
388
            + HelpExampleRpc("getblocktemplate", "")
 
389
         );
 
390
 
 
391
    LOCK(cs_main);
 
392
 
 
393
    std::string strMode = "template";
 
394
    UniValue lpval = NullUniValue;
 
395
    std::set<std::string> setClientRules;
 
396
    int64_t nMaxVersionPreVB = -1;
 
397
    if (params.size() > 0)
 
398
    {
 
399
        const UniValue& oparam = params[0].get_obj();
 
400
        const UniValue& modeval = find_value(oparam, "mode");
 
401
        if (modeval.isStr())
 
402
            strMode = modeval.get_str();
 
403
        else if (modeval.isNull())
 
404
        {
 
405
            /* Do nothing */
 
406
        }
 
407
        else
 
408
            throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
 
409
        lpval = find_value(oparam, "longpollid");
 
410
 
 
411
        if (strMode == "proposal")
 
412
        {
 
413
            const UniValue& dataval = find_value(oparam, "data");
 
414
            if (!dataval.isStr())
 
415
                throw JSONRPCError(RPC_TYPE_ERROR, "Missing data String key for proposal");
 
416
 
 
417
            CBlock block;
 
418
            if (!DecodeHexBlk(block, dataval.get_str()))
 
419
                throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
 
420
 
 
421
            uint256 hash = block.GetHash();
 
422
            BlockMap::iterator mi = mapBlockIndex.find(hash);
 
423
            if (mi != mapBlockIndex.end()) {
 
424
                CBlockIndex *pindex = mi->second;
 
425
                if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
 
426
                    return "duplicate";
 
427
                if (pindex->nStatus & BLOCK_FAILED_MASK)
 
428
                    return "duplicate-invalid";
 
429
                return "duplicate-inconclusive";
 
430
            }
 
431
 
 
432
            CBlockIndex* const pindexPrev = chainActive.Tip();
 
433
            // TestBlockValidity only supports blocks built on the current Tip
 
434
            if (block.hashPrevBlock != pindexPrev->GetBlockHash())
 
435
                return "inconclusive-not-best-prevblk";
 
436
            CValidationState state;
 
437
            TestBlockValidity(state, Params(), block, pindexPrev, false, true);
 
438
            return BIP22ValidationResult(state);
 
439
        }
 
440
 
 
441
        const UniValue& aClientRules = find_value(oparam, "rules");
 
442
        if (aClientRules.isArray()) {
 
443
            for (unsigned int i = 0; i < aClientRules.size(); ++i) {
 
444
                const UniValue& v = aClientRules[i];
 
445
                setClientRules.insert(v.get_str());
 
446
            }
 
447
        } else {
 
448
            // NOTE: It is important that this NOT be read if versionbits is supported
 
449
            const UniValue& uvMaxVersion = find_value(oparam, "maxversion");
 
450
            if (uvMaxVersion.isNum()) {
 
451
                nMaxVersionPreVB = uvMaxVersion.get_int64();
 
452
            }
 
453
        }
 
454
    }
 
455
 
 
456
    if (strMode != "template")
 
457
        throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid mode");
 
458
 
 
459
    if (vNodes.empty())
 
460
        throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Bitcoin is not connected!");
 
461
 
 
462
    if (IsInitialBlockDownload())
 
463
        throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Bitcoin is downloading blocks...");
 
464
 
 
465
    static unsigned int nTransactionsUpdatedLast;
 
466
 
 
467
    if (!lpval.isNull())
 
468
    {
 
469
        // Wait to respond until either the best block changes, OR a minute has passed and there are more transactions
 
470
        uint256 hashWatchedChain;
 
471
        boost::system_time checktxtime;
 
472
        unsigned int nTransactionsUpdatedLastLP;
 
473
 
 
474
        if (lpval.isStr())
 
475
        {
 
476
            // Format: <hashBestChain><nTransactionsUpdatedLast>
 
477
            std::string lpstr = lpval.get_str();
 
478
 
 
479
            hashWatchedChain.SetHex(lpstr.substr(0, 64));
 
480
            nTransactionsUpdatedLastLP = atoi64(lpstr.substr(64));
 
481
        }
 
482
        else
 
483
        {
 
484
            // NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier
 
485
            hashWatchedChain = chainActive.Tip()->GetBlockHash();
 
486
            nTransactionsUpdatedLastLP = nTransactionsUpdatedLast;
 
487
        }
 
488
 
 
489
        // Release the wallet and main lock while waiting
 
490
        LEAVE_CRITICAL_SECTION(cs_main);
 
491
        {
 
492
            checktxtime = boost::get_system_time() + boost::posix_time::minutes(1);
 
493
 
 
494
            boost::unique_lock<boost::mutex> lock(csBestBlock);
 
495
            while (chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning())
 
496
            {
 
497
                if (!cvBlockChange.timed_wait(lock, checktxtime))
 
498
                {
 
499
                    // Timeout: Check transactions for update
 
500
                    if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
 
501
                        break;
 
502
                    checktxtime += boost::posix_time::seconds(10);
 
503
                }
 
504
            }
 
505
        }
 
506
        ENTER_CRITICAL_SECTION(cs_main);
 
507
 
 
508
        if (!IsRPCRunning())
 
509
            throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down");
 
510
        // TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners?
 
511
    }
 
512
 
 
513
    // Update block
 
514
    static CBlockIndex* pindexPrev;
 
515
    static int64_t nStart;
 
516
    static CBlockTemplate* pblocktemplate;
 
517
    if (pindexPrev != chainActive.Tip() ||
 
518
        (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 5))
 
519
    {
 
520
        // Clear pindexPrev so future calls make a new block, despite any failures from here on
 
521
        pindexPrev = NULL;
 
522
 
 
523
        // Store the pindexBest used before CreateNewBlock, to avoid races
 
524
        nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
 
525
        CBlockIndex* pindexPrevNew = chainActive.Tip();
 
526
        nStart = GetTime();
 
527
 
 
528
        // Create new block
 
529
        if(pblocktemplate)
 
530
        {
 
531
            delete pblocktemplate;
 
532
            pblocktemplate = NULL;
 
533
        }
 
534
        CScript scriptDummy = CScript() << OP_TRUE;
 
535
        pblocktemplate = BlockAssembler(Params()).CreateNewBlock(scriptDummy);
 
536
        if (!pblocktemplate)
 
537
            throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
 
538
 
 
539
        // Need to update only after we know CreateNewBlock succeeded
 
540
        pindexPrev = pindexPrevNew;
 
541
    }
 
542
    CBlock* pblock = &pblocktemplate->block; // pointer for convenience
 
543
    const Consensus::Params& consensusParams = Params().GetConsensus();
 
544
 
 
545
    // Update nTime
 
546
    UpdateTime(pblock, consensusParams, pindexPrev);
 
547
    pblock->nNonce = 0;
 
548
 
 
549
    // NOTE: If at some point we support pre-segwit miners post-segwit-activation, this needs to take segwit support into consideration
 
550
    const bool fPreSegWit = (THRESHOLD_ACTIVE != VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT, versionbitscache));
 
551
 
 
552
    UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
 
553
 
 
554
    UniValue transactions(UniValue::VARR);
 
555
    map<uint256, int64_t> setTxIndex;
 
556
    int i = 0;
 
557
    BOOST_FOREACH (CTransaction& tx, pblock->vtx) {
 
558
        uint256 txHash = tx.GetHash();
 
559
        setTxIndex[txHash] = i++;
 
560
 
 
561
        if (tx.IsCoinBase())
 
562
            continue;
 
563
 
 
564
        UniValue entry(UniValue::VOBJ);
 
565
 
 
566
        entry.push_back(Pair("data", EncodeHexTx(tx)));
 
567
        entry.push_back(Pair("txid", txHash.GetHex()));
 
568
        entry.push_back(Pair("hash", tx.GetWitnessHash().GetHex()));
 
569
 
 
570
        UniValue deps(UniValue::VARR);
 
571
        BOOST_FOREACH (const CTxIn &in, tx.vin)
 
572
        {
 
573
            if (setTxIndex.count(in.prevout.hash))
 
574
                deps.push_back(setTxIndex[in.prevout.hash]);
 
575
        }
 
576
        entry.push_back(Pair("depends", deps));
 
577
 
 
578
        int index_in_template = i - 1;
 
579
        entry.push_back(Pair("fee", pblocktemplate->vTxFees[index_in_template]));
 
580
        int64_t nTxSigOps = pblocktemplate->vTxSigOpsCost[index_in_template];
 
581
        if (fPreSegWit) {
 
582
            assert(nTxSigOps % WITNESS_SCALE_FACTOR == 0);
 
583
            nTxSigOps /= WITNESS_SCALE_FACTOR;
 
584
        }
 
585
        entry.push_back(Pair("sigops", nTxSigOps));
 
586
        entry.push_back(Pair("weight", GetTransactionWeight(tx)));
 
587
 
 
588
        transactions.push_back(entry);
 
589
    }
 
590
 
 
591
    UniValue aux(UniValue::VOBJ);
 
592
    aux.push_back(Pair("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
 
593
 
 
594
    arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);
 
595
 
 
596
    UniValue aMutable(UniValue::VARR);
 
597
    aMutable.push_back("time");
 
598
    aMutable.push_back("transactions");
 
599
    aMutable.push_back("prevblock");
 
600
 
 
601
    UniValue result(UniValue::VOBJ);
 
602
    result.push_back(Pair("capabilities", aCaps));
 
603
 
 
604
    UniValue aRules(UniValue::VARR);
 
605
    UniValue vbavailable(UniValue::VOBJ);
 
606
    for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; ++i) {
 
607
        Consensus::DeploymentPos pos = Consensus::DeploymentPos(i);
 
608
        ThresholdState state = VersionBitsState(pindexPrev, consensusParams, pos, versionbitscache);
 
609
        switch (state) {
 
610
            case THRESHOLD_DEFINED:
 
611
            case THRESHOLD_FAILED:
 
612
                // Not exposed to GBT at all
 
613
                break;
 
614
            case THRESHOLD_LOCKED_IN:
 
615
                // Ensure bit is set in block version
 
616
                pblock->nVersion |= VersionBitsMask(consensusParams, pos);
 
617
                // FALL THROUGH to get vbavailable set...
 
618
            case THRESHOLD_STARTED:
 
619
            {
 
620
                const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
 
621
                vbavailable.push_back(Pair(gbt_vb_name(pos), consensusParams.vDeployments[pos].bit));
 
622
                if (setClientRules.find(vbinfo.name) == setClientRules.end()) {
 
623
                    if (!vbinfo.gbt_force) {
 
624
                        // If the client doesn't support this, don't indicate it in the [default] version
 
625
                        pblock->nVersion &= ~VersionBitsMask(consensusParams, pos);
 
626
                    }
 
627
                }
 
628
                break;
 
629
            }
 
630
            case THRESHOLD_ACTIVE:
 
631
            {
 
632
                // Add to rules only
 
633
                const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
 
634
                aRules.push_back(gbt_vb_name(pos));
 
635
                if (setClientRules.find(vbinfo.name) == setClientRules.end()) {
 
636
                    // Not supported by the client; make sure it's safe to proceed
 
637
                    if (!vbinfo.gbt_force) {
 
638
                        // If we do anything other than throw an exception here, be sure version/force isn't sent to old clients
 
639
                        throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Support for '%s' rule requires explicit client support", vbinfo.name));
 
640
                    }
 
641
                }
 
642
                break;
 
643
            }
 
644
        }
 
645
    }
 
646
    result.push_back(Pair("version", pblock->nVersion));
 
647
    result.push_back(Pair("rules", aRules));
 
648
    result.push_back(Pair("vbavailable", vbavailable));
 
649
    result.push_back(Pair("vbrequired", int(0)));
 
650
 
 
651
    if (nMaxVersionPreVB >= 2) {
 
652
        // If VB is supported by the client, nMaxVersionPreVB is -1, so we won't get here
 
653
        // Because BIP 34 changed how the generation transaction is serialised, we can only use version/force back to v2 blocks
 
654
        // This is safe to do [otherwise-]unconditionally only because we are throwing an exception above if a non-force deployment gets activated
 
655
        // Note that this can probably also be removed entirely after the first BIP9 non-force deployment (ie, probably segwit) gets activated
 
656
        aMutable.push_back("version/force");
 
657
    }
 
658
 
 
659
    result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
 
660
    result.push_back(Pair("transactions", transactions));
 
661
    result.push_back(Pair("coinbaseaux", aux));
 
662
    result.push_back(Pair("coinbasevalue", (int64_t)pblock->vtx[0].vout[0].nValue));
 
663
    result.push_back(Pair("longpollid", chainActive.Tip()->GetBlockHash().GetHex() + i64tostr(nTransactionsUpdatedLast)));
 
664
    result.push_back(Pair("target", hashTarget.GetHex()));
 
665
    result.push_back(Pair("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1));
 
666
    result.push_back(Pair("mutable", aMutable));
 
667
    result.push_back(Pair("noncerange", "00000000ffffffff"));
 
668
    int64_t nSigOpLimit = MAX_BLOCK_SIGOPS_COST;
 
669
    if (fPreSegWit) {
 
670
        assert(nSigOpLimit % WITNESS_SCALE_FACTOR == 0);
 
671
        nSigOpLimit /= WITNESS_SCALE_FACTOR;
 
672
    }
 
673
    result.push_back(Pair("sigoplimit", nSigOpLimit));
 
674
    result.push_back(Pair("sizelimit", (int64_t)MAX_BLOCK_SERIALIZED_SIZE));
 
675
    result.push_back(Pair("weightlimit", (int64_t)MAX_BLOCK_WEIGHT));
 
676
    result.push_back(Pair("curtime", pblock->GetBlockTime()));
 
677
    result.push_back(Pair("bits", strprintf("%08x", pblock->nBits)));
 
678
    result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1)));
 
679
    if (!pblocktemplate->vchCoinbaseCommitment.empty()) {
 
680
        result.push_back(Pair("default_witness_commitment", HexStr(pblocktemplate->vchCoinbaseCommitment.begin(), pblocktemplate->vchCoinbaseCommitment.end())));
 
681
    }
 
682
 
 
683
    return result;
 
684
}
 
685
 
 
686
class submitblock_StateCatcher : public CValidationInterface
 
687
{
 
688
public:
 
689
    uint256 hash;
 
690
    bool found;
 
691
    CValidationState state;
 
692
 
 
693
    submitblock_StateCatcher(const uint256 &hashIn) : hash(hashIn), found(false), state() {};
 
694
 
 
695
protected:
 
696
    virtual void BlockChecked(const CBlock& block, const CValidationState& stateIn) {
 
697
        if (block.GetHash() != hash)
 
698
            return;
 
699
        found = true;
 
700
        state = stateIn;
 
701
    };
 
702
};
 
703
 
 
704
UniValue submitblock(const UniValue& params, bool fHelp)
 
705
{
 
706
    if (fHelp || params.size() < 1 || params.size() > 2)
 
707
        throw runtime_error(
 
708
            "submitblock \"hexdata\" ( \"jsonparametersobject\" )\n"
 
709
            "\nAttempts to submit new block to network.\n"
 
710
            "The 'jsonparametersobject' parameter is currently ignored.\n"
 
711
            "See https://en.bitcoin.it/wiki/BIP_0022 for full specification.\n"
 
712
 
 
713
            "\nArguments\n"
 
714
            "1. \"hexdata\"    (string, required) the hex-encoded block data to submit\n"
 
715
            "2. \"jsonparametersobject\"     (string, optional) object of optional parameters\n"
 
716
            "    {\n"
 
717
            "      \"workid\" : \"id\"    (string, optional) if the server provided a workid, it MUST be included with submissions\n"
 
718
            "    }\n"
 
719
            "\nResult:\n"
 
720
            "\nExamples:\n"
 
721
            + HelpExampleCli("submitblock", "\"mydata\"")
 
722
            + HelpExampleRpc("submitblock", "\"mydata\"")
 
723
        );
 
724
 
 
725
    CBlock block;
 
726
    if (!DecodeHexBlk(block, params[0].get_str()))
 
727
        throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
 
728
 
 
729
    uint256 hash = block.GetHash();
 
730
    bool fBlockPresent = false;
 
731
    {
 
732
        LOCK(cs_main);
 
733
        BlockMap::iterator mi = mapBlockIndex.find(hash);
 
734
        if (mi != mapBlockIndex.end()) {
 
735
            CBlockIndex *pindex = mi->second;
 
736
            if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
 
737
                return "duplicate";
 
738
            if (pindex->nStatus & BLOCK_FAILED_MASK)
 
739
                return "duplicate-invalid";
 
740
            // Otherwise, we might only have the header - process the block before returning
 
741
            fBlockPresent = true;
 
742
        }
 
743
    }
 
744
 
 
745
    {
 
746
        LOCK(cs_main);
 
747
        BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock);
 
748
        if (mi != mapBlockIndex.end()) {
 
749
            UpdateUncommittedBlockStructures(block, mi->second, Params().GetConsensus());
 
750
        }
 
751
    }
 
752
 
 
753
    CValidationState state;
 
754
    submitblock_StateCatcher sc(block.GetHash());
 
755
    RegisterValidationInterface(&sc);
 
756
    bool fAccepted = ProcessNewBlock(state, Params(), NULL, &block, true, NULL);
 
757
    UnregisterValidationInterface(&sc);
 
758
    if (fBlockPresent)
 
759
    {
 
760
        if (fAccepted && !sc.found)
 
761
            return "duplicate-inconclusive";
 
762
        return "duplicate";
 
763
    }
 
764
    if (fAccepted)
 
765
    {
 
766
        if (!sc.found)
 
767
            return "inconclusive";
 
768
        state = sc.state;
 
769
    }
 
770
    return BIP22ValidationResult(state);
 
771
}
 
772
 
 
773
UniValue estimatefee(const UniValue& params, bool fHelp)
 
774
{
 
775
    if (fHelp || params.size() != 1)
 
776
        throw runtime_error(
 
777
            "estimatefee nblocks\n"
 
778
            "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n"
 
779
            "confirmation within nblocks blocks.\n"
 
780
            "\nArguments:\n"
 
781
            "1. nblocks     (numeric)\n"
 
782
            "\nResult:\n"
 
783
            "n              (numeric) estimated fee-per-kilobyte\n"
 
784
            "\n"
 
785
            "A negative value is returned if not enough transactions and blocks\n"
 
786
            "have been observed to make an estimate.\n"
 
787
            "\nExample:\n"
 
788
            + HelpExampleCli("estimatefee", "6")
 
789
            );
 
790
 
 
791
    RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
 
792
 
 
793
    int nBlocks = params[0].get_int();
 
794
    if (nBlocks < 1)
 
795
        nBlocks = 1;
 
796
 
 
797
    CFeeRate feeRate = mempool.estimateFee(nBlocks);
 
798
    if (feeRate == CFeeRate(0))
 
799
        return -1.0;
 
800
 
 
801
    return ValueFromAmount(feeRate.GetFeePerK());
 
802
}
 
803
 
 
804
UniValue estimatepriority(const UniValue& params, bool fHelp)
 
805
{
 
806
    if (fHelp || params.size() != 1)
 
807
        throw runtime_error(
 
808
            "estimatepriority nblocks\n"
 
809
            "\nEstimates the approximate priority a zero-fee transaction needs to begin\n"
 
810
            "confirmation within nblocks blocks.\n"
 
811
            "\nArguments:\n"
 
812
            "1. nblocks     (numeric)\n"
 
813
            "\nResult:\n"
 
814
            "n              (numeric) estimated priority\n"
 
815
            "\n"
 
816
            "A negative value is returned if not enough transactions and blocks\n"
 
817
            "have been observed to make an estimate.\n"
 
818
            "\nExample:\n"
 
819
            + HelpExampleCli("estimatepriority", "6")
 
820
            );
 
821
 
 
822
    RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
 
823
 
 
824
    int nBlocks = params[0].get_int();
 
825
    if (nBlocks < 1)
 
826
        nBlocks = 1;
 
827
 
 
828
    return mempool.estimatePriority(nBlocks);
 
829
}
 
830
 
 
831
UniValue estimatesmartfee(const UniValue& params, bool fHelp)
 
832
{
 
833
    if (fHelp || params.size() != 1)
 
834
        throw runtime_error(
 
835
            "estimatesmartfee nblocks\n"
 
836
            "\nWARNING: This interface is unstable and may disappear or change!\n"
 
837
            "\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n"
 
838
            "confirmation within nblocks blocks if possible and return the number of blocks\n"
 
839
            "for which the estimate is valid.\n"
 
840
            "\nArguments:\n"
 
841
            "1. nblocks     (numeric)\n"
 
842
            "\nResult:\n"
 
843
            "{\n"
 
844
            "  \"feerate\" : x.x,     (numeric) estimate fee-per-kilobyte (in BTC)\n"
 
845
            "  \"blocks\" : n         (numeric) block number where estimate was found\n"
 
846
            "}\n"
 
847
            "\n"
 
848
            "A negative value is returned if not enough transactions and blocks\n"
 
849
            "have been observed to make an estimate for any number of blocks.\n"
 
850
            "However it will not return a value below the mempool reject fee.\n"
 
851
            "\nExample:\n"
 
852
            + HelpExampleCli("estimatesmartfee", "6")
 
853
            );
 
854
 
 
855
    RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
 
856
 
 
857
    int nBlocks = params[0].get_int();
 
858
 
 
859
    UniValue result(UniValue::VOBJ);
 
860
    int answerFound;
 
861
    CFeeRate feeRate = mempool.estimateSmartFee(nBlocks, &answerFound);
 
862
    result.push_back(Pair("feerate", feeRate == CFeeRate(0) ? -1.0 : ValueFromAmount(feeRate.GetFeePerK())));
 
863
    result.push_back(Pair("blocks", answerFound));
 
864
    return result;
 
865
}
 
866
 
 
867
UniValue estimatesmartpriority(const UniValue& params, bool fHelp)
 
868
{
 
869
    if (fHelp || params.size() != 1)
 
870
        throw runtime_error(
 
871
            "estimatesmartpriority nblocks\n"
 
872
            "\nWARNING: This interface is unstable and may disappear or change!\n"
 
873
            "\nEstimates the approximate priority a zero-fee transaction needs to begin\n"
 
874
            "confirmation within nblocks blocks if possible and return the number of blocks\n"
 
875
            "for which the estimate is valid.\n"
 
876
            "\nArguments:\n"
 
877
            "1. nblocks     (numeric)\n"
 
878
            "\nResult:\n"
 
879
            "{\n"
 
880
            "  \"priority\" : x.x,    (numeric) estimated priority\n"
 
881
            "  \"blocks\" : n         (numeric) block number where estimate was found\n"
 
882
            "}\n"
 
883
            "\n"
 
884
            "A negative value is returned if not enough transactions and blocks\n"
 
885
            "have been observed to make an estimate for any number of blocks.\n"
 
886
            "However if the mempool reject fee is set it will return 1e9 * MAX_MONEY.\n"
 
887
            "\nExample:\n"
 
888
            + HelpExampleCli("estimatesmartpriority", "6")
 
889
            );
 
890
 
 
891
    RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
 
892
 
 
893
    int nBlocks = params[0].get_int();
 
894
 
 
895
    UniValue result(UniValue::VOBJ);
 
896
    int answerFound;
 
897
    double priority = mempool.estimateSmartPriority(nBlocks, &answerFound);
 
898
    result.push_back(Pair("priority", priority));
 
899
    result.push_back(Pair("blocks", answerFound));
 
900
    return result;
 
901
}
 
902
 
 
903
static const CRPCCommand commands[] =
 
904
{ //  category              name                      actor (function)         okSafeMode
 
905
  //  --------------------- ------------------------  -----------------------  ----------
 
906
    { "mining",             "getnetworkhashps",       &getnetworkhashps,       true  },
 
907
    { "mining",             "getmininginfo",          &getmininginfo,          true  },
 
908
    { "mining",             "prioritisetransaction",  &prioritisetransaction,  true  },
 
909
    { "mining",             "getblocktemplate",       &getblocktemplate,       true  },
 
910
    { "mining",             "submitblock",            &submitblock,            true  },
 
911
 
 
912
    { "generating",         "generate",               &generate,               true  },
 
913
    { "generating",         "generatetoaddress",      &generatetoaddress,      true  },
 
914
 
 
915
    { "util",               "estimatefee",            &estimatefee,            true  },
 
916
    { "util",               "estimatepriority",       &estimatepriority,       true  },
 
917
    { "util",               "estimatesmartfee",       &estimatesmartfee,       true  },
 
918
    { "util",               "estimatesmartpriority",  &estimatesmartpriority,  true  },
 
919
};
 
920
 
 
921
void RegisterMiningRPCCommands(CRPCTable &tableRPC)
 
922
{
 
923
    for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++)
 
924
        tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]);
 
925
}