#include "consensus/consensus.h"
#include "consensus/validation.h"
#include "core_io.h"
+#ifdef ENABLE_MINING
#include "crypto/equihash.h"
+#endif
#include "init.h"
#include "main.h"
#include "metrics.h"
#include <boost/assign/list_of.hpp>
-#include "json/json_spirit_utils.h"
-#include "json/json_spirit_value.h"
+#include <univalue.h>
-using namespace json_spirit;
using namespace std;
+extern int32_t ASSETCHAINS_ALGO, ASSETCHAINS_EQUIHASH;
+
/**
* Return average network hashes per second based on the last 'lookup' blocks,
* or over the difficulty averaging window if 'lookup' is nonpositive.
return (int64_t)(workDiff.getdouble() / timeDiff);
}
-Value getlocalsolps(const Array& params, bool fHelp)
+UniValue getlocalsolps(const UniValue& params, bool fHelp)
{
if (fHelp)
throw runtime_error(
return GetLocalSolPS();
}
-Value getnetworksolps(const Array& params, bool fHelp)
+UniValue getnetworksolps(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() > 2)
throw runtime_error(
return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1);
}
-Value getnetworkhashps(const Array& params, bool fHelp)
+UniValue getnetworkhashps(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() > 2)
throw runtime_error(
return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1);
}
-#ifdef ENABLE_WALLET
-Value getgenerate(const Array& params, bool fHelp)
+#ifdef ENABLE_MINING
+UniValue getgenerate(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
extern uint8_t NOTARY_PUBKEY33[33];
-Value generate(const Array& params, bool fHelp)
+//Value generate(const Array& params, bool fHelp)
+UniValue generate(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 1)
throw runtime_error(
+ HelpExampleCli("generate", "11")
);
- if (pwalletMain == NULL)
- throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
+ if (GetArg("-mineraddress", "").empty()) {
+#ifdef ENABLE_WALLET
+ if (!pwalletMain) {
+ throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Wallet disabled and -mineraddress not set");
+ }
+#else
+ throw JSONRPCError(RPC_METHOD_NOT_FOUND, "zcashd compiled without wallet and -mineraddress not set");
+#endif
+ }
if (!Params().MineBlocksOnDemand())
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "This method can only be used on regtest");
int nHeightEnd = 0;
int nHeight = 0;
int nGenerate = params[0].get_int();
+#ifdef ENABLE_WALLET
CReserveKey reservekey(pwalletMain);
+#endif
{ // Don't keep cs_main locked
LOCK(cs_main);
nHeightEnd = nHeightStart+nGenerate;
}
unsigned int nExtraNonce = 0;
- Array blockHashes;
+ UniValue blockHashes(UniValue::VARR);
unsigned int n = Params().EquihashN();
unsigned int k = Params().EquihashK();
+ uint64_t lastTime = 0;
while (nHeight < nHeightEnd)
{
- unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
+ // Validation may fail if block generation is too fast
+ if (GetTime() == lastTime) MilliSleep(1001);
+ lastTime = GetTime();
+
+#ifdef ENABLE_WALLET
+ std::unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
+#else
+ std::unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey());
+#endif
if (!pblocktemplate.get())
throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet keypool empty");
CBlock *pblock = &pblocktemplate->block;
LOCK(cs_main);
pblock->nSolution = soln;
solutionTargetChecks.increment();
- return CheckProofOfWork(chainActive.Height(),NOTARY_PUBKEY33,pblock->GetHash(), pblock->nBits, Params().GetConsensus());
+ return CheckProofOfWork(chainActive.Height(),NOTARY_PUBKEY33,pblock->GetHash(), pblock->nBits, Params().GetConsensus(),pblock->nTime);
};
bool found = EhBasicSolveUncancellable(n, k, curr_state, validBlock);
ehSolverRuns.increment();
}
endloop:
CValidationState state;
- if (!ProcessNewBlock(chainActive.Tip()->nHeight+1,state, NULL, pblock, true, NULL))
+ if (!ProcessNewBlock(1,chainActive.Tip()->nHeight+1,state, NULL, pblock, true, NULL))
throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
++nHeight;
blockHashes.push_back(pblock->GetHash().GetHex());
}
-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(
+ HelpExampleRpc("setgenerate", "true, 1")
);
- if (pwalletMain == NULL)
- throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
+ if (GetArg("-mineraddress", "").empty()) {
+#ifdef ENABLE_WALLET
+ if (!pwalletMain) {
+ throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Wallet disabled and -mineraddress not set");
+ }
+#else
+ throw JSONRPCError(RPC_METHOD_NOT_FOUND, "zcashd compiled without wallet and -mineraddress not set");
+#endif
+ }
if (Params().MineBlocksOnDemand())
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Use the generate method instead of setgenerate on this network");
mapArgs["-gen"] = (fGenerate ? "1" : "0");
mapArgs ["-genproclimit"] = itostr(nGenProcLimit);
+#ifdef ENABLE_WALLET
GenerateBitcoins(fGenerate, pwalletMain, nGenProcLimit);
+#else
+ GenerateBitcoins(fGenerate, nGenProcLimit);
+#endif
- 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(
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));
obj.push_back(Pair("difficulty", (double)GetNetworkDifficulty()));
obj.push_back(Pair("errors", GetWarnings("statusbar")));
obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
- obj.push_back(Pair("localsolps" , getlocalsolps(params, false)));
- obj.push_back(Pair("networksolps", getnetworksolps(params, false)));
+ if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH)
+ {
+ obj.push_back(Pair("localsolps" , getlocalsolps(params, false)));
+ obj.push_back(Pair("networksolps", getnetworksolps(params, false)));
+ }
+ else
+ {
+ obj.push_back(Pair("localhashps" , getlocalsolps(params, false)));
+ }
obj.push_back(Pair("networkhashps", getnetworksolps(params, false)));
obj.push_back(Pair("pooledtx", (uint64_t)mempool.size()));
obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC()));
obj.push_back(Pair("chain", Params().NetworkIDString()));
-#ifdef ENABLE_WALLET
+#ifdef ENABLE_MINING
obj.push_back(Pair("generate", getgenerate(params, false)));
#endif
return obj;
// 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(
// 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())
return "valid?";
}
-#ifdef ENABLE_WALLET
-Value getblocktemplate(const Array& params, bool fHelp)
+UniValue getblocktemplate(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() > 1)
throw runtime_error(
LOCK(cs_main);
- // Wallet is required because we support coinbasetxn
- if (pwalletMain == NULL) {
- throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)");
+ // Wallet or miner address is required because we support coinbasetxn
+ if (GetArg("-mineraddress", "").empty()) {
+#ifdef ENABLE_WALLET
+ if (!pwalletMain) {
+ throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Wallet disabled and -mineraddress not set");
+ }
+#else
+ throw JSONRPCError(RPC_METHOD_NOT_FOUND, "zcashd compiled without wallet and -mineraddress not set");
+#endif
}
std::string strMode = "template";
- Value lpval = Value::null;
+ UniValue lpval = NullUniValue;
// TODO: Re-enable coinbasevalue once a specification has been written
bool coinbasetxn = true;
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 */
}
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;
if (vNodes.empty())
throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Zcash is not connected!");
- if (IsInitialBlockDownload())
- throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Zcash is downloading blocks...");
+ //if (IsInitialBlockDownload())
+ // throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Zcash is downloading blocks...");
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();
delete pblocktemplate;
pblocktemplate = NULL;
}
+#ifdef ENABLE_WALLET
CReserveKey reservekey(pwalletMain);
pblocktemplate = CreateNewBlockWithKey(reservekey);
+#else
+ pblocktemplate = CreateNewBlockWithKey();
+#endif
if (!pblocktemplate)
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
pblock->nNonce = uint256();
- static const Array aCaps = boost::assign::list_of("proposal");
+ UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal");
- Value txCoinbase = Value::null;
- Array transactions;
+ UniValue txCoinbase = NullUniValue;
+ 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() && !coinbasetxn)
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))
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");
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()));
result.push_back(Pair("transactions", transactions));
if (coinbasetxn) {
- assert(txCoinbase.type() == obj_type);
+ assert(txCoinbase.isObject());
result.push_back(Pair("coinbasetxn", txCoinbase));
} else {
result.push_back(Pair("coinbaseaux", aux));
result.push_back(Pair("bits", strprintf("%08x", pblock->nBits)));
result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1)));
+ //fprintf(stderr,"return complete template\n");
return result;
}
-#endif
class submitblock_StateCatcher : public CValidationInterface
{
};
};
-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(
" \"workid\" : \"id\" (string, optional) if the server provided a workid, it MUST be included with submissions\n"
" }\n"
"\nResult:\n"
+ "\"duplicate\" - node already has valid copy of block\n"
+ "\"duplicate-invalid\" - node already has block, but it is invalid\n"
+ "\"duplicate-inconclusive\" - node already has block but has not validated it\n"
+ "\"inconclusive\" - node has not validated the block, it may not be on the node's current best chain\n"
+ "\"rejected\" - block was rejected as invalid\n"
+ "For more information on submitblock parameters and results, see: https://github.com/bitcoin/bips/blob/master/bip-0022.mediawiki#block-submission\n"
"\nExamples:\n"
+ HelpExampleCli("submitblock", "\"mydata\"")
+ HelpExampleRpc("submitblock", "\"mydata\"")
CValidationState state;
submitblock_StateCatcher sc(block.GetHash());
RegisterValidationInterface(&sc);
- bool fAccepted = ProcessNewBlock(chainActive.Tip()->nHeight+1,state, NULL, &block, true, NULL);
+ bool fAccepted = ProcessNewBlock(1,chainActive.Tip()->nHeight+1,state, NULL, &block, true, NULL);
UnregisterValidationInterface(&sc);
if (fBlockPresent)
{
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(
+ 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)
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(
+ 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)
return mempool.estimatePriority(nBlocks);
}
-Value getblocksubsidy(const Array& params, bool fHelp)
+UniValue getblocksubsidy(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() > 1)
throw runtime_error(
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range");
CAmount nReward = GetBlockSubsidy(nHeight, Params().GetConsensus());
- Object result;
+ UniValue result(UniValue::VOBJ);
result.push_back(Pair("miner", ValueFromAmount(nReward)));
//result.push_back(Pair("founders", ValueFromAmount(nFoundersReward)));
return result;