rpc: Move the generate
RPC call to rpcwallet
This makes it possible to mine to any wallet when multi-wallet mode is added. Solves the same problem as #10649, but IMO in a cleaner way. It also gets rid of the circuitous `ScriptForMining` method on `CValidationInterface`, which really doesn't belong there. After this change it's still possible to mine without wallet through `generatetoaddress`.
This commit is contained in:
parent
ac52492cd2
commit
df7e2f057b
7 changed files with 62 additions and 44 deletions
|
@ -127,6 +127,7 @@ BITCOIN_CORE_H = \
|
||||||
reverselock.h \
|
reverselock.h \
|
||||||
rpc/blockchain.h \
|
rpc/blockchain.h \
|
||||||
rpc/client.h \
|
rpc/client.h \
|
||||||
|
rpc/mining.h \
|
||||||
rpc/protocol.h \
|
rpc/protocol.h \
|
||||||
rpc/server.h \
|
rpc/server.h \
|
||||||
rpc/register.h \
|
rpc/register.h \
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "policy/fees.h"
|
#include "policy/fees.h"
|
||||||
#include "pow.h"
|
#include "pow.h"
|
||||||
#include "rpc/blockchain.h"
|
#include "rpc/blockchain.h"
|
||||||
|
#include "rpc/mining.h"
|
||||||
#include "rpc/server.h"
|
#include "rpc/server.h"
|
||||||
#include "txmempool.h"
|
#include "txmempool.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
@ -141,42 +142,6 @@ UniValue generateBlocks(std::shared_ptr<CReserveScript> coinbaseScript, int nGen
|
||||||
return blockHashes;
|
return blockHashes;
|
||||||
}
|
}
|
||||||
|
|
||||||
UniValue generate(const JSONRPCRequest& request)
|
|
||||||
{
|
|
||||||
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
|
|
||||||
throw std::runtime_error(
|
|
||||||
"generate nblocks ( maxtries )\n"
|
|
||||||
"\nMine up to nblocks blocks immediately (before the RPC call returns)\n"
|
|
||||||
"\nArguments:\n"
|
|
||||||
"1. nblocks (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 = request.params[0].get_int();
|
|
||||||
uint64_t nMaxTries = 1000000;
|
|
||||||
if (request.params.size() > 1) {
|
|
||||||
nMaxTries = request.params[1].get_int();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::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 JSONRPCRequest& request)
|
UniValue generatetoaddress(const JSONRPCRequest& request)
|
||||||
{
|
{
|
||||||
if (request.fHelp || request.params.size() < 2 || request.params.size() > 3)
|
if (request.fHelp || request.params.size() < 2 || request.params.size() > 3)
|
||||||
|
@ -962,7 +927,6 @@ static const CRPCCommand commands[] =
|
||||||
{ "mining", "getblocktemplate", &getblocktemplate, true, {"template_request"} },
|
{ "mining", "getblocktemplate", &getblocktemplate, true, {"template_request"} },
|
||||||
{ "mining", "submitblock", &submitblock, true, {"hexdata","dummy"} },
|
{ "mining", "submitblock", &submitblock, true, {"hexdata","dummy"} },
|
||||||
|
|
||||||
{ "generating", "generate", &generate, true, {"nblocks","maxtries"} },
|
|
||||||
{ "generating", "generatetoaddress", &generatetoaddress, true, {"nblocks","address","maxtries"} },
|
{ "generating", "generatetoaddress", &generatetoaddress, true, {"nblocks","address","maxtries"} },
|
||||||
|
|
||||||
{ "util", "estimatefee", &estimatefee, true, {"nblocks"} },
|
{ "util", "estimatefee", &estimatefee, true, {"nblocks"} },
|
||||||
|
|
15
src/rpc/mining.h
Normal file
15
src/rpc/mining.h
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright (c) 2017 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#ifndef BITCOIN_RPC_MINING_H
|
||||||
|
#define BITCOIN_RPC_MINING_H
|
||||||
|
|
||||||
|
#include "script/script.h"
|
||||||
|
|
||||||
|
#include <univalue.h>
|
||||||
|
|
||||||
|
/** Generate blocks (mine) */
|
||||||
|
UniValue generateBlocks(std::shared_ptr<CReserveScript> coinbaseScript, int nGenerate, uint64_t nMaxTries, bool keepScript);
|
||||||
|
|
||||||
|
#endif
|
|
@ -21,12 +21,10 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) {
|
||||||
g_signals.Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
|
g_signals.Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
|
||||||
g_signals.Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2));
|
g_signals.Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2));
|
||||||
g_signals.BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
|
g_signals.BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
|
||||||
g_signals.ScriptForMining.connect(boost::bind(&CValidationInterface::GetScriptForMining, pwalletIn, _1));
|
|
||||||
g_signals.NewPoWValidBlock.connect(boost::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2));
|
g_signals.NewPoWValidBlock.connect(boost::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2));
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
|
void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
|
||||||
g_signals.ScriptForMining.disconnect(boost::bind(&CValidationInterface::GetScriptForMining, pwalletIn, _1));
|
|
||||||
g_signals.BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
|
g_signals.BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
|
||||||
g_signals.Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2));
|
g_signals.Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2));
|
||||||
g_signals.Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
|
g_signals.Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
|
||||||
|
@ -39,7 +37,6 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnregisterAllValidationInterfaces() {
|
void UnregisterAllValidationInterfaces() {
|
||||||
g_signals.ScriptForMining.disconnect_all_slots();
|
|
||||||
g_signals.BlockChecked.disconnect_all_slots();
|
g_signals.BlockChecked.disconnect_all_slots();
|
||||||
g_signals.Broadcast.disconnect_all_slots();
|
g_signals.Broadcast.disconnect_all_slots();
|
||||||
g_signals.Inventory.disconnect_all_slots();
|
g_signals.Inventory.disconnect_all_slots();
|
||||||
|
|
|
@ -40,7 +40,6 @@ protected:
|
||||||
virtual void Inventory(const uint256 &hash) {}
|
virtual void Inventory(const uint256 &hash) {}
|
||||||
virtual void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) {}
|
virtual void ResendWalletTransactions(int64_t nBestBlockTime, CConnman* connman) {}
|
||||||
virtual void BlockChecked(const CBlock&, const CValidationState&) {}
|
virtual void BlockChecked(const CBlock&, const CValidationState&) {}
|
||||||
virtual void GetScriptForMining(std::shared_ptr<CReserveScript>&) {};
|
|
||||||
virtual void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr<const CBlock>& block) {};
|
virtual void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr<const CBlock>& block) {};
|
||||||
friend void ::RegisterValidationInterface(CValidationInterface*);
|
friend void ::RegisterValidationInterface(CValidationInterface*);
|
||||||
friend void ::UnregisterValidationInterface(CValidationInterface*);
|
friend void ::UnregisterValidationInterface(CValidationInterface*);
|
||||||
|
@ -72,8 +71,6 @@ struct CMainSignals {
|
||||||
* callback was generated (not necessarily now)
|
* callback was generated (not necessarily now)
|
||||||
*/
|
*/
|
||||||
boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked;
|
boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked;
|
||||||
/** Notifies listeners that a key for mining is required (coinbase) */
|
|
||||||
boost::signals2::signal<void (std::shared_ptr<CReserveScript>&)> ScriptForMining;
|
|
||||||
/**
|
/**
|
||||||
* Notifies listeners that a block which builds directly on our current tip
|
* Notifies listeners that a block which builds directly on our current tip
|
||||||
* has been received and connected to the headers tree, though not validated yet */
|
* has been received and connected to the headers tree, though not validated yet */
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "policy/fees.h"
|
#include "policy/fees.h"
|
||||||
#include "policy/policy.h"
|
#include "policy/policy.h"
|
||||||
#include "policy/rbf.h"
|
#include "policy/rbf.h"
|
||||||
|
#include "rpc/mining.h"
|
||||||
#include "rpc/server.h"
|
#include "rpc/server.h"
|
||||||
#include "script/sign.h"
|
#include "script/sign.h"
|
||||||
#include "timedata.h"
|
#include "timedata.h"
|
||||||
|
@ -2922,6 +2923,47 @@ UniValue bumpfee(const JSONRPCRequest& request)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UniValue generate(const JSONRPCRequest& request)
|
||||||
|
{
|
||||||
|
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
|
||||||
|
|
||||||
|
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
|
||||||
|
return NullUniValue;
|
||||||
|
|
||||||
|
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2)
|
||||||
|
throw std::runtime_error(
|
||||||
|
"generate nblocks ( maxtries )\n"
|
||||||
|
"\nMine up to nblocks blocks immediately (before the RPC call returns) to an address in the wallet.\n"
|
||||||
|
"\nArguments:\n"
|
||||||
|
"1. nblocks (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 = request.params[0].get_int();
|
||||||
|
uint64_t nMaxTries = 1000000;
|
||||||
|
if (request.params.size() > 1) {
|
||||||
|
nMaxTries = request.params[1].get_int();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<CReserveScript> coinbaseScript;
|
||||||
|
pwallet->GetScriptForMining(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);
|
||||||
|
}
|
||||||
|
|
||||||
extern UniValue abortrescan(const JSONRPCRequest& request); // in rpcdump.cpp
|
extern UniValue abortrescan(const JSONRPCRequest& request); // in rpcdump.cpp
|
||||||
extern UniValue dumpprivkey(const JSONRPCRequest& request); // in rpcdump.cpp
|
extern UniValue dumpprivkey(const JSONRPCRequest& request); // in rpcdump.cpp
|
||||||
extern UniValue importprivkey(const JSONRPCRequest& request);
|
extern UniValue importprivkey(const JSONRPCRequest& request);
|
||||||
|
@ -2985,6 +3027,8 @@ static const CRPCCommand commands[] =
|
||||||
{ "wallet", "walletpassphrasechange", &walletpassphrasechange, true, {"oldpassphrase","newpassphrase"} },
|
{ "wallet", "walletpassphrasechange", &walletpassphrasechange, true, {"oldpassphrase","newpassphrase"} },
|
||||||
{ "wallet", "walletpassphrase", &walletpassphrase, true, {"passphrase","timeout"} },
|
{ "wallet", "walletpassphrase", &walletpassphrase, true, {"passphrase","timeout"} },
|
||||||
{ "wallet", "removeprunedfunds", &removeprunedfunds, true, {"txid"} },
|
{ "wallet", "removeprunedfunds", &removeprunedfunds, true, {"txid"} },
|
||||||
|
|
||||||
|
{ "generating", "generate", &generate, true, {"nblocks","maxtries"} },
|
||||||
};
|
};
|
||||||
|
|
||||||
void RegisterWalletRPCCommands(CRPCTable &t)
|
void RegisterWalletRPCCommands(CRPCTable &t)
|
||||||
|
|
|
@ -1025,7 +1025,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetScriptForMining(std::shared_ptr<CReserveScript> &script) override;
|
void GetScriptForMining(std::shared_ptr<CReserveScript> &script);
|
||||||
|
|
||||||
unsigned int GetKeyPoolSize()
|
unsigned int GetKeyPoolSize()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue