aboutsummaryrefslogtreecommitdiff
path: root/src/rpcmining.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/rpcmining.cpp')
-rw-r--r--src/rpcmining.cpp217
1 files changed, 117 insertions, 100 deletions
diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp
index fcba7e222..f33281461 100644
--- a/src/rpcmining.cpp
+++ b/src/rpcmining.cpp
@@ -5,17 +5,18 @@
#include "amount.h"
#include "chainparams.h"
+#include "consensus/consensus.h"
+#include "consensus/validation.h"
#include "core_io.h"
#include "init.h"
-#include "net.h"
#include "main.h"
#include "miner.h"
+#include "net.h"
#include "pow.h"
#include "rpcserver.h"
#include "util.h"
#include "validationinterface.h"
#ifdef ENABLE_WALLET
-#include "wallet/db.h"
#include "wallet/wallet.h"
#endif
@@ -23,10 +24,8 @@
#include <boost/assign/list_of.hpp>
-#include "json/json_spirit_utils.h"
-#include "json/json_spirit_value.h"
+#include "univalue/univalue.h"
-using namespace json_spirit;
using namespace std;
/**
@@ -34,7 +33,7 @@ using namespace std;
* or from the last difficulty change if 'lookup' is nonpositive.
* If 'height' is nonnegative, compute the estimate at the time when a given block was found.
*/
-Value GetNetworkHashPS(int lookup, int height) {
+UniValue GetNetworkHashPS(int lookup, int height) {
CBlockIndex *pb = chainActive.Tip();
if (height >= 0 && height < chainActive.Height())
@@ -45,7 +44,7 @@ Value GetNetworkHashPS(int lookup, int height) {
// If lookup is -1, then use blocks since last difficulty change.
if (lookup <= 0)
- lookup = pb->nHeight % Params().DifficultyAdjustmentInterval() + 1;
+ lookup = pb->nHeight % Params().GetConsensus().DifficultyAdjustmentInterval() + 1;
// If lookup is larger than chain, then set it to chain length.
if (lookup > pb->nHeight)
@@ -71,7 +70,7 @@ Value GetNetworkHashPS(int lookup, int height) {
return (int64_t)(workDiff.getdouble() / timeDiff);
}
-Value getnetworkhashps(const Array& params, bool fHelp)
+UniValue getnetworkhashps(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() > 2)
throw runtime_error(
@@ -94,7 +93,7 @@ Value getnetworkhashps(const Array& params, bool fHelp)
}
#ifdef ENABLE_WALLET
-Value getgenerate(const Array& params, bool fHelp)
+UniValue getgenerate(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@@ -113,8 +112,66 @@ Value getgenerate(const Array& params, bool fHelp)
return GetBoolArg("-gen", false);
}
+UniValue generate(const UniValue& params, bool fHelp)
+{
+ if (fHelp || params.size() < 1 || params.size() > 1)
+ throw runtime_error(
+ "generate numblocks\n"
+ "\nMine blocks immediately (before the RPC call returns)\n"
+ "\nNote: this function can only be used on the regtest network\n"
+ "1. numblocks (numeric) How many blocks are generated immediately.\n"
+ "\nResult\n"
+ "[ blockhashes ] (array) hashes of blocks generated\n"
+ "\nExamples:\n"
+ "\nGenerate 11 blocks\n"
+ + HelpExampleCli("generate", "11")
+ );
+
+ if (pwalletMain == NULL)
+ throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
+ if (!Params().MineBlocksOnDemand())
+ throw JSONRPCError(RPC_METHOD_NOT_FOUND, "This method can only be used on regtest");
+
+ int nHeightStart = 0;
+ int nHeightEnd = 0;
+ int nHeight = 0;
+ int nGenerate = params[0].get_int();
+ CReserveKey reservekey(pwalletMain);
+
+ { // Don't keep cs_main locked
+ LOCK(cs_main);
+ nHeightStart = chainActive.Height();
+ nHeight = nHeightStart;
+ nHeightEnd = nHeightStart+nGenerate;
+ }
+ unsigned int nExtraNonce = 0;
+ UniValue blockHashes(UniValue::VARR);
+ while (nHeight < nHeightEnd)
+ {
+ auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
+ if (!pblocktemplate.get())
+ throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet keypool empty");
+ CBlock *pblock = &pblocktemplate->block;
+ {
+ LOCK(cs_main);
+ IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce);
+ }
+ while (!CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus())) {
+ // Yes, there is a chance every nonce could fail to satisfy the -regtest
+ // target -- 1 in 2^(2^32). That ain't gonna happen.
+ ++pblock->nNonce;
+ }
+ CValidationState state;
+ if (!ProcessNewBlock(state, NULL, pblock, true, NULL))
+ throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
+ ++nHeight;
+ blockHashes.push_back(pblock->GetHash().GetHex());
+ }
+ return blockHashes;
+}
+
-Value setgenerate(const Array& params, bool fHelp)
+UniValue setgenerate(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
@@ -125,9 +182,6 @@ Value setgenerate(const Array& params, bool fHelp)
"\nArguments:\n"
"1. generate (boolean, required) Set to true to turn on generation, off to turn off.\n"
"2. genproclimit (numeric, optional) Set the processor limit for when generation is on. Can be -1 for unlimited.\n"
- " Note: in -regtest mode, genproclimit controls how many blocks are generated immediately.\n"
- "\nResult\n"
- "[ blockhashes ] (array, -regtest only) hashes of blocks generated\n"
"\nExamples:\n"
"\nSet the generation on with a limit of one processor\n"
+ HelpExampleCli("setgenerate", "true 1") +
@@ -141,6 +195,8 @@ Value setgenerate(const Array& params, bool fHelp)
if (pwalletMain == NULL)
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
+ if (Params().MineBlocksOnDemand())
+ throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Use the generate method instead of setgenerate on this network");
bool fGenerate = true;
if (params.size() > 0)
@@ -154,59 +210,16 @@ Value setgenerate(const Array& params, bool fHelp)
fGenerate = false;
}
- // -regtest mode: don't return until nGenProcLimit blocks are generated
- if (fGenerate && Params().MineBlocksOnDemand())
- {
- int nHeightStart = 0;
- int nHeightEnd = 0;
- int nHeight = 0;
- int nGenerate = (nGenProcLimit > 0 ? nGenProcLimit : 1);
- CReserveKey reservekey(pwalletMain);
-
- { // Don't keep cs_main locked
- LOCK(cs_main);
- nHeightStart = chainActive.Height();
- nHeight = nHeightStart;
- nHeightEnd = nHeightStart+nGenerate;
- }
- unsigned int nExtraNonce = 0;
- Array blockHashes;
- while (nHeight < nHeightEnd)
- {
- auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
- if (!pblocktemplate.get())
- throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet keypool empty");
- CBlock *pblock = &pblocktemplate->block;
- {
- LOCK(cs_main);
- IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce);
- }
- while (!CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus())) {
- // Yes, there is a chance every nonce could fail to satisfy the -regtest
- // target -- 1 in 2^(2^32). That ain't gonna happen.
- ++pblock->nNonce;
- }
- CValidationState state;
- if (!ProcessNewBlock(state, NULL, pblock))
- throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
- ++nHeight;
- blockHashes.push_back(pblock->GetHash().GetHex());
- }
- return blockHashes;
- }
- else // Not -regtest: start generate thread, return immediately
- {
- mapArgs["-gen"] = (fGenerate ? "1" : "0");
- mapArgs ["-genproclimit"] = itostr(nGenProcLimit);
- GenerateBitcoins(fGenerate, pwalletMain, nGenProcLimit);
- }
+ mapArgs["-gen"] = (fGenerate ? "1" : "0");
+ mapArgs ["-genproclimit"] = itostr(nGenProcLimit);
+ GenerateBitcoins(fGenerate, pwalletMain, nGenProcLimit);
- return Value::null;
+ return NullUniValue;
}
#endif
-Value getmininginfo(const Array& params, bool fHelp)
+UniValue getmininginfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
@@ -233,7 +246,7 @@ Value getmininginfo(const Array& params, bool fHelp)
LOCK(cs_main);
- Object obj;
+ UniValue obj(UniValue::VOBJ);
obj.push_back(Pair("blocks", (int)chainActive.Height()));
obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize));
obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx));
@@ -252,7 +265,7 @@ Value getmininginfo(const Array& params, bool fHelp)
// NOTE: Unlike wallet RPC (which use BTC values), mining RPCs follow GBT (BIP 22) in using satoshi amounts
-Value prioritisetransaction(const Array& params, bool fHelp)
+UniValue prioritisetransaction(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 3)
throw runtime_error(
@@ -284,10 +297,10 @@ Value prioritisetransaction(const Array& params, bool fHelp)
// NOTE: Assumes a conclusive result; if result is inconclusive, it must be handled by caller
-static Value BIP22ValidationResult(const CValidationState& state)
+static UniValue BIP22ValidationResult(const CValidationState& state)
{
if (state.IsValid())
- return Value::null;
+ return NullUniValue;
std::string strRejectReason = state.GetRejectReason();
if (state.IsError())
@@ -302,7 +315,7 @@ static Value BIP22ValidationResult(const CValidationState& state)
return "valid?";
}
-Value getblocktemplate(const Array& params, bool fHelp)
+UniValue getblocktemplate(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() > 1)
throw runtime_error(
@@ -367,14 +380,14 @@ Value getblocktemplate(const Array& params, bool fHelp)
LOCK(cs_main);
std::string strMode = "template";
- Value lpval = Value::null;
+ UniValue lpval = NullUniValue;
if (params.size() > 0)
{
- const Object& oparam = params[0].get_obj();
- const Value& modeval = find_value(oparam, "mode");
- if (modeval.type() == str_type)
+ const UniValue& oparam = params[0].get_obj();
+ const UniValue& modeval = find_value(oparam, "mode");
+ if (modeval.isStr())
strMode = modeval.get_str();
- else if (modeval.type() == null_type)
+ else if (modeval.isNull())
{
/* Do nothing */
}
@@ -384,8 +397,8 @@ Value getblocktemplate(const Array& params, bool fHelp)
if (strMode == "proposal")
{
- const Value& dataval = find_value(oparam, "data");
- if (dataval.type() != str_type)
+ const UniValue& dataval = find_value(oparam, "data");
+ if (!dataval.isStr())
throw JSONRPCError(RPC_TYPE_ERROR, "Missing data String key for proposal");
CBlock block;
@@ -424,14 +437,14 @@ Value getblocktemplate(const Array& params, bool fHelp)
static unsigned int nTransactionsUpdatedLast;
- if (lpval.type() != null_type)
+ if (!lpval.isNull())
{
// Wait to respond until either the best block changes, OR a minute has passed and there are more transactions
uint256 hashWatchedChain;
boost::system_time checktxtime;
unsigned int nTransactionsUpdatedLastLP;
- if (lpval.type() == str_type)
+ if (lpval.isStr())
{
// Format: <hashBestChain><nTransactionsUpdatedLast>
std::string lpstr = lpval.get_str();
@@ -502,29 +515,28 @@ Value getblocktemplate(const Array& params, bool fHelp)
CBlock* pblock = &pblocktemplate->block; // pointer for convenience
// Update nTime
- UpdateTime(pblock, pindexPrev);
+ UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
pblock->nNonce = 0;
- static const Array aCaps = boost::assign::list_of("proposal");
+ UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
- Array transactions;
+ UniValue transactions(UniValue::VARR);
map<uint256, int64_t> setTxIndex;
int i = 0;
- BOOST_FOREACH (CTransaction& tx, pblock->vtx)
- {
+ BOOST_FOREACH (const CTransaction& tx, pblock->vtx) {
uint256 txHash = tx.GetHash();
setTxIndex[txHash] = i++;
if (tx.IsCoinBase())
continue;
- Object entry;
+ UniValue entry(UniValue::VOBJ);
entry.push_back(Pair("data", EncodeHexTx(tx)));
entry.push_back(Pair("hash", txHash.GetHex()));
- Array deps;
+ UniValue deps(UniValue::VARR);
BOOST_FOREACH (const CTxIn &in, tx.vin)
{
if (setTxIndex.count(in.prevout.hash))
@@ -539,12 +551,12 @@ Value getblocktemplate(const Array& params, bool fHelp)
transactions.push_back(entry);
}
- Object aux;
+ UniValue aux(UniValue::VOBJ);
aux.push_back(Pair("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);
- static Array aMutable;
+ static UniValue aMutable(UniValue::VARR);
if (aMutable.empty())
{
aMutable.push_back("time");
@@ -552,7 +564,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
aMutable.push_back("prevblock");
}
- Object result;
+ UniValue result(UniValue::VOBJ);
result.push_back(Pair("capabilities", aCaps));
result.push_back(Pair("version", pblock->nVersion));
result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex()));
@@ -591,7 +603,7 @@ protected:
};
};
-Value submitblock(const Array& params, bool fHelp)
+UniValue submitblock(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
@@ -617,22 +629,27 @@ Value submitblock(const Array& params, bool fHelp)
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed");
uint256 hash = block.GetHash();
- BlockMap::iterator mi = mapBlockIndex.find(hash);
- if (mi != mapBlockIndex.end()) {
- CBlockIndex *pindex = mi->second;
- if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
- return "duplicate";
- if (pindex->nStatus & BLOCK_FAILED_MASK)
- return "duplicate-invalid";
- // Otherwise, we might only have the header - process the block before returning
+ bool fBlockPresent = false;
+ {
+ LOCK(cs_main);
+ BlockMap::iterator mi = mapBlockIndex.find(hash);
+ if (mi != mapBlockIndex.end()) {
+ CBlockIndex *pindex = mi->second;
+ if (pindex->IsValid(BLOCK_VALID_SCRIPTS))
+ return "duplicate";
+ if (pindex->nStatus & BLOCK_FAILED_MASK)
+ return "duplicate-invalid";
+ // Otherwise, we might only have the header - process the block before returning
+ fBlockPresent = true;
+ }
}
CValidationState state;
submitblock_StateCatcher sc(block.GetHash());
RegisterValidationInterface(&sc);
- bool fAccepted = ProcessNewBlock(state, NULL, &block);
+ bool fAccepted = ProcessNewBlock(state, NULL, &block, true, NULL);
UnregisterValidationInterface(&sc);
- if (mi != mapBlockIndex.end())
+ if (fBlockPresent)
{
if (fAccepted && !sc.found)
return "duplicate-inconclusive";
@@ -647,7 +664,7 @@ Value submitblock(const Array& params, bool fHelp)
return BIP22ValidationResult(state);
}
-Value estimatefee(const Array& params, bool fHelp)
+UniValue estimatefee(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
@@ -666,7 +683,7 @@ Value estimatefee(const Array& params, bool fHelp)
+ HelpExampleCli("estimatefee", "6")
);
- RPCTypeCheck(params, boost::assign::list_of(int_type));
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
int nBlocks = params[0].get_int();
if (nBlocks < 1)
@@ -679,7 +696,7 @@ Value estimatefee(const Array& params, bool fHelp)
return ValueFromAmount(feeRate.GetFeePerK());
}
-Value estimatepriority(const Array& params, bool fHelp)
+UniValue estimatepriority(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
@@ -698,7 +715,7 @@ Value estimatepriority(const Array& params, bool fHelp)
+ HelpExampleCli("estimatepriority", "6")
);
- RPCTypeCheck(params, boost::assign::list_of(int_type));
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
int nBlocks = params[0].get_int();
if (nBlocks < 1)