Create generatetoaddress rpc

Creates the generatetoaddress rpc which is virtually identical to the generate rpc except that it takes an argument for the address to mine to. It does not rely on wallet functionality.

The mining code shared by generate and generatetoaddress has been moved to another method to reduce duplication.
This commit is contained in:
Andrew C 2016-03-12 11:41:51 -05:00
parent 29b2be6ad7
commit fe00ca758a
4 changed files with 81 additions and 33 deletions

View File

@ -29,6 +29,9 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "getaddednodeinfo", 0 }, { "getaddednodeinfo", 0 },
{ "generate", 0 }, { "generate", 0 },
{ "generate", 1 }, { "generate", 1 },
{ "generatetoaddress", 0 },
{ "generatetoaddress", 1 },
{ "generatetoaddress", 2 },
{ "getnetworkhashps", 0 }, { "getnetworkhashps", 0 },
{ "getnetworkhashps", 1 }, { "getnetworkhashps", 1 },
{ "sendtoaddress", 1 }, { "sendtoaddress", 1 },

View File

@ -3,6 +3,7 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "base58.h"
#include "amount.h" #include "amount.h"
#include "chain.h" #include "chain.h"
#include "chainparams.h" #include "chainparams.h"
@ -93,42 +94,12 @@ UniValue getnetworkhashps(const UniValue& params, bool fHelp)
return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1); return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1);
} }
UniValue generate(const UniValue& params, bool fHelp) UniValue generateBlocks(boost::shared_ptr<CReserveScript> coinbaseScript, int nGenerate, uint64_t nMaxTries, bool keepScript)
{ {
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
"generate numblocks ( maxtries )\n"
"\nMine up to numblocks blocks immediately (before the RPC call returns)\n"
"\nArguments:\n"
"1. numblocks (numeric, required) How many blocks are generated immediately.\n"
"2. maxtries (numeric, optional) How many iterations to try (default = 1000000).\n"
"\nResult\n"
"[ blockhashes ] (array) hashes of blocks generated\n"
"\nExamples:\n"
"\nGenerate 11 blocks\n"
+ HelpExampleCli("generate", "11")
);
static const int nInnerLoopCount = 0x10000; static const int nInnerLoopCount = 0x10000;
int nHeightStart = 0; int nHeightStart = 0;
int nHeightEnd = 0; int nHeightEnd = 0;
int nHeight = 0; int nHeight = 0;
int nGenerate = params[0].get_int();
uint64_t nMaxTries = 1000000;
if (params.size() > 1) {
nMaxTries = params[1].get_int();
}
boost::shared_ptr<CReserveScript> coinbaseScript;
GetMainSignals().ScriptForMining(coinbaseScript);
// If the keypool is exhausted, no script is returned at all. Catch this.
if (!coinbaseScript)
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
//throw an error if no script was provided
if (coinbaseScript->reserveScript.empty())
throw JSONRPCError(RPC_INTERNAL_ERROR, "No coinbase script available (mining requires a wallet)");
{ // Don't keep cs_main locked { // Don't keep cs_main locked
LOCK(cs_main); LOCK(cs_main);
@ -164,12 +135,84 @@ UniValue generate(const UniValue& params, bool fHelp)
++nHeight; ++nHeight;
blockHashes.push_back(pblock->GetHash().GetHex()); blockHashes.push_back(pblock->GetHash().GetHex());
//mark script as important because it was used at least for one coinbase output //mark script as important because it was used at least for one coinbase output if the script came from the wallet
if (keepScript)
{
coinbaseScript->KeepScript(); coinbaseScript->KeepScript();
} }
}
return blockHashes; return blockHashes;
} }
UniValue generate(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
"generate numblocks ( maxtries )\n"
"\nMine up to numblocks blocks immediately (before the RPC call returns)\n"
"\nArguments:\n"
"1. numblocks (numeric, required) How many blocks are generated immediately.\n"
"2. maxtries (numeric, optional) How many iterations to try (default = 1000000).\n"
"\nResult\n"
"[ blockhashes ] (array) hashes of blocks generated\n"
"\nExamples:\n"
"\nGenerate 11 blocks\n"
+ HelpExampleCli("generate", "11")
);
int nGenerate = params[0].get_int();
uint64_t nMaxTries = 1000000;
if (params.size() > 1) {
nMaxTries = params[1].get_int();
}
boost::shared_ptr<CReserveScript> coinbaseScript;
GetMainSignals().ScriptForMining(coinbaseScript);
// If the keypool is exhausted, no script is returned at all. Catch this.
if (!coinbaseScript)
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
//throw an error if no script was provided
if (coinbaseScript->reserveScript.empty())
throw JSONRPCError(RPC_INTERNAL_ERROR, "No coinbase script available (mining requires a wallet)");
return generateBlocks(coinbaseScript, nGenerate, nMaxTries, true);
}
UniValue generatetoaddress(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 2 || params.size() > 3)
throw runtime_error(
"generatetoaddress numblocks address (maxtries)\n"
"\nMine blocks immediately to a specified address (before the RPC call returns)\n"
"\nArguments:\n"
"1. numblocks (numeric, required) How many blocks are generated immediately.\n"
"2. address (string, required) The address to send the newly generated bitcoin to.\n"
"3. maxtries (numeric, optional) How many iterations to try (default = 1000000).\n"
"\nResult\n"
"[ blockhashes ] (array) hashes of blocks generated\n"
"\nExamples:\n"
"\nGenerate 11 blocks to myaddress\n"
+ HelpExampleCli("generatetoaddress", "11 \"myaddress\"")
);
int nGenerate = params[0].get_int();
uint64_t nMaxTries = 1000000;
if (params.size() > 2) {
nMaxTries = params[2].get_int();
}
CBitcoinAddress address(params[1].get_str());
if (!address.IsValid())
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Error: Invalid address");
boost::shared_ptr<CReserveScript> coinbaseScript(new CReserveScript());
coinbaseScript->reserveScript = GetScriptForDestination(address.Get());
return generateBlocks(coinbaseScript, nGenerate, nMaxTries, false);
}
UniValue getmininginfo(const UniValue& params, bool fHelp) UniValue getmininginfo(const UniValue& params, bool fHelp)
{ {
if (fHelp || params.size() != 0) if (fHelp || params.size() != 0)

View File

@ -299,6 +299,7 @@ static const CRPCCommand vRPCCommands[] =
/* Coin generation */ /* Coin generation */
{ "generating", "generate", &generate, true }, { "generating", "generate", &generate, true },
{ "generating", "generatetoaddress", &generatetoaddress, true },
/* Raw transactions */ /* Raw transactions */
{ "rawtransactions", "createrawtransaction", &createrawtransaction, true }, { "rawtransactions", "createrawtransaction", &createrawtransaction, true },

View File

@ -193,6 +193,7 @@ extern UniValue listbanned(const UniValue& params, bool fHelp);
extern UniValue clearbanned(const UniValue& params, bool fHelp); extern UniValue clearbanned(const UniValue& params, bool fHelp);
extern UniValue generate(const UniValue& params, bool fHelp); extern UniValue generate(const UniValue& params, bool fHelp);
extern UniValue generatetoaddress(const UniValue& params, bool fHelp);
extern UniValue getnetworkhashps(const UniValue& params, bool fHelp); extern UniValue getnetworkhashps(const UniValue& params, bool fHelp);
extern UniValue getmininginfo(const UniValue& params, bool fHelp); extern UniValue getmininginfo(const UniValue& params, bool fHelp);
extern UniValue prioritisetransaction(const UniValue& params, bool fHelp); extern UniValue prioritisetransaction(const UniValue& params, bool fHelp);