Browse Source

Merge pull request #5994

a7b9623 miner: rename UpdateRequestCount signal to ResetRequestCount (Jonas Schnelli)
5496253 add CReserveScript to allow modular script keeping/returning (Jonas Schnelli)
087e65d fix GetScriptForMining() CReserveKey::keepKey() issue (Jonas Schnelli)
d0fc10a detach wallet from miner (Jonas Schnelli)
0.13
Wladimir J. van der Laan 10 years ago
parent
commit
786ed114c2
No known key found for this signature in database
GPG Key ID: 74810B012346C9A6
  1. 9
      src/init.cpp
  2. 50
      src/miner.cpp
  3. 4
      src/miner.h
  4. 31
      src/rpcmining.cpp
  5. 2
      src/rpcserver.cpp
  6. 9
      src/script/script.h
  7. 6
      src/validationinterface.cpp
  8. 8
      src/validationinterface.h
  9. 11
      src/wallet/wallet.cpp
  10. 12
      src/wallet/wallet.h

9
src/init.cpp

@ -156,8 +156,8 @@ void Shutdown() @@ -156,8 +156,8 @@ void Shutdown()
#ifdef ENABLE_WALLET
if (pwalletMain)
pwalletMain->Flush(false);
GenerateBitcoins(false, NULL, 0);
#endif
GenerateBitcoins(false, 0, Params());
StopNode();
UnregisterNodeSignals(GetNodeSignals());
@ -370,10 +370,8 @@ std::string HelpMessage(HelpMessageMode mode) @@ -370,10 +370,8 @@ std::string HelpMessage(HelpMessageMode mode)
debugCategories += ", qt";
strUsage += HelpMessageOpt("-debug=<category>", strprintf(_("Output debugging information (default: %u, supplying <category> is optional)"), 0) + ". " +
_("If <category> is not supplied or if <category> = 1, output all debugging information.") + _("<category> can be:") + " " + debugCategories + ".");
#ifdef ENABLE_WALLET
strUsage += HelpMessageOpt("-gen", strprintf(_("Generate coins (default: %u)"), 0));
strUsage += HelpMessageOpt("-genproclimit=<n>", strprintf(_("Set the number of threads for coin generation if enabled (-1 = all cores, default: %d)"), 1));
#endif
strUsage += HelpMessageOpt("-help-debug", _("Show all debugging options (usage: --help -help-debug)"));
strUsage += HelpMessageOpt("-logips", strprintf(_("Include IP addresses in debug output (default: %u)"), 0));
strUsage += HelpMessageOpt("-logtimestamps", strprintf(_("Prepend debug output with timestamp (default: %u)"), 1));
@ -1439,11 +1437,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) @@ -1439,11 +1437,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
boost::ref(cs_main), boost::cref(pindexBestHeader), nPowTargetSpacing);
scheduler.scheduleEvery(f, nPowTargetSpacing);
#ifdef ENABLE_WALLET
// Generate coins in the background
if (pwalletMain)
GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain, GetArg("-genproclimit", 1));
#endif
GenerateBitcoins(GetBoolArg("-gen", false), GetArg("-genproclimit", 1), Params());
// ********************************************************* Step 11: finished

50
src/miner.cpp

@ -17,9 +17,7 @@ @@ -17,9 +17,7 @@
#include "timedata.h"
#include "util.h"
#include "utilmoneystr.h"
#ifdef ENABLE_WALLET
#include "wallet/wallet.h"
#endif
#include "validationinterface.h"
#include <boost/thread.hpp>
#include <boost/tuple/tuple.hpp>
@ -362,7 +360,6 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& @@ -362,7 +360,6 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int&
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
}
#ifdef ENABLE_WALLET
//////////////////////////////////////////////////////////////////////////////
//
// Internal miner
@ -401,17 +398,7 @@ bool static ScanHash(const CBlockHeader *pblock, uint32_t& nNonce, uint256 *phas @@ -401,17 +398,7 @@ bool static ScanHash(const CBlockHeader *pblock, uint32_t& nNonce, uint256 *phas
}
}
CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey)
{
CPubKey pubkey;
if (!reservekey.GetReservedKey(pubkey))
return NULL;
CScript scriptPubKey = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
return CreateNewBlock(scriptPubKey);
}
static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
static bool ProcessBlockFound(CBlock* pblock, const CChainParams& chainparams)
{
LogPrintf("%s\n", pblock->ToString());
LogPrintf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue));
@ -423,14 +410,8 @@ static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& rese @@ -423,14 +410,8 @@ static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& rese
return error("BitcoinMiner: generated block is stale");
}
// Remove key from key pool
reservekey.KeepKey();
// Track how many getdata requests this block gets
{
LOCK(wallet.cs_wallet);
wallet.mapRequestCount[pblock->GetHash()] = 0;
}
// Inform about the new block
GetMainSignals().BlockFound(pblock->GetHash());
// Process this block the same as if we had received it from another node
CValidationState state;
@ -440,18 +421,22 @@ static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& rese @@ -440,18 +421,22 @@ static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& rese
return true;
}
void static BitcoinMiner(CWallet *pwallet)
void static BitcoinMiner(const CChainParams& chainparams)
{
LogPrintf("BitcoinMiner started\n");
SetThreadPriority(THREAD_PRIORITY_LOWEST);
RenameThread("bitcoin-miner");
const CChainParams& chainparams = Params();
// Each thread has its own key and counter
CReserveKey reservekey(pwallet);
unsigned int nExtraNonce = 0;
boost::shared_ptr<CReserveScript> coinbaseScript;
GetMainSignals().ScriptForMining(coinbaseScript);
try {
//throw an error if no script was provided
if (!coinbaseScript->reserveScript.size())
throw std::runtime_error("No coinbase script available (mining requires a wallet)");
while (true) {
if (chainparams.MiningRequiresPeers()) {
// Busy-wait for the network to come online so we don't waste time mining
@ -474,7 +459,7 @@ void static BitcoinMiner(CWallet *pwallet) @@ -474,7 +459,7 @@ void static BitcoinMiner(CWallet *pwallet)
unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
CBlockIndex* pindexPrev = chainActive.Tip();
auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlock(coinbaseScript->reserveScript));
if (!pblocktemplate.get())
{
LogPrintf("Error in BitcoinMiner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n");
@ -506,8 +491,9 @@ void static BitcoinMiner(CWallet *pwallet) @@ -506,8 +491,9 @@ void static BitcoinMiner(CWallet *pwallet)
SetThreadPriority(THREAD_PRIORITY_NORMAL);
LogPrintf("BitcoinMiner:\n");
LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", hash.GetHex(), hashTarget.GetHex());
ProcessBlockFound(pblock, *pwallet, reservekey);
ProcessBlockFound(pblock, chainparams);
SetThreadPriority(THREAD_PRIORITY_LOWEST);
coinbaseScript->KeepScript();
// In regression test mode, stop mining after a block is found.
if (chainparams.MineBlocksOnDemand())
@ -551,7 +537,7 @@ void static BitcoinMiner(CWallet *pwallet) @@ -551,7 +537,7 @@ void static BitcoinMiner(CWallet *pwallet)
}
}
void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads)
void GenerateBitcoins(bool fGenerate, int nThreads, const CChainParams& chainparams)
{
static boost::thread_group* minerThreads = NULL;
@ -575,7 +561,5 @@ void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads) @@ -575,7 +561,5 @@ void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads)
minerThreads = new boost::thread_group();
for (int i = 0; i < nThreads; i++)
minerThreads->create_thread(boost::bind(&BitcoinMiner, pwallet));
minerThreads->create_thread(boost::bind(&BitcoinMiner, boost::cref(chainparams)));
}
#endif // ENABLE_WALLET

4
src/miner.h

@ -11,6 +11,7 @@ @@ -11,6 +11,7 @@
#include <stdint.h>
class CBlockIndex;
class CChainParams;
class CReserveKey;
class CScript;
class CWallet;
@ -24,10 +25,9 @@ struct CBlockTemplate @@ -24,10 +25,9 @@ struct CBlockTemplate
};
/** Run the miner threads */
void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads);
void GenerateBitcoins(bool fGenerate, int nThreads, const CChainParams& chainparams);
/** Generate a new block, without valid proof-of-work */
CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn);
CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey);
/** Modify the extranonce in a block */
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev);

31
src/rpcmining.cpp

@ -16,13 +16,11 @@ @@ -16,13 +16,11 @@
#include "rpcserver.h"
#include "util.h"
#include "validationinterface.h"
#ifdef ENABLE_WALLET
#include "wallet/wallet.h"
#endif
#include <stdint.h>
#include <boost/assign/list_of.hpp>
#include <boost/shared_ptr.hpp>
#include "univalue/univalue.h"
@ -92,7 +90,6 @@ UniValue getnetworkhashps(const UniValue& params, bool fHelp) @@ -92,7 +90,6 @@ 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);
}
#ifdef ENABLE_WALLET
UniValue getgenerate(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
@ -127,8 +124,6 @@ UniValue generate(const UniValue& params, bool fHelp) @@ -127,8 +124,6 @@ UniValue generate(const UniValue& params, bool fHelp)
+ 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");
@ -136,7 +131,13 @@ UniValue generate(const UniValue& params, bool fHelp) @@ -136,7 +131,13 @@ UniValue generate(const UniValue& params, bool fHelp)
int nHeightEnd = 0;
int nHeight = 0;
int nGenerate = params[0].get_int();
CReserveKey reservekey(pwalletMain);
boost::shared_ptr<CReserveScript> coinbaseScript;
GetMainSignals().ScriptForMining(coinbaseScript);
//throw an error if no script was provided
if (!coinbaseScript->reserveScript.size())
throw JSONRPCError(RPC_INTERNAL_ERROR, "No coinbase script available (mining requires a wallet)");
{ // Don't keep cs_main locked
LOCK(cs_main);
@ -148,9 +149,9 @@ UniValue generate(const UniValue& params, bool fHelp) @@ -148,9 +149,9 @@ UniValue generate(const UniValue& params, bool fHelp)
UniValue blockHashes(UniValue::VARR);
while (nHeight < nHeightEnd)
{
auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlock(coinbaseScript->reserveScript));
if (!pblocktemplate.get())
throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet keypool empty");
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
CBlock *pblock = &pblocktemplate->block;
{
LOCK(cs_main);
@ -166,11 +167,13 @@ UniValue generate(const UniValue& params, bool fHelp) @@ -166,11 +167,13 @@ UniValue generate(const UniValue& params, bool fHelp)
throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
++nHeight;
blockHashes.push_back(pblock->GetHash().GetHex());
//mark script as important because it was used at least for one coinbase output
coinbaseScript->KeepScript();
}
return blockHashes;
}
UniValue setgenerate(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() < 1 || params.size() > 2)
@ -193,8 +196,6 @@ UniValue setgenerate(const UniValue& params, bool fHelp) @@ -193,8 +196,6 @@ UniValue setgenerate(const UniValue& params, bool fHelp)
+ HelpExampleRpc("setgenerate", "true, 1")
);
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");
@ -212,12 +213,10 @@ UniValue setgenerate(const UniValue& params, bool fHelp) @@ -212,12 +213,10 @@ UniValue setgenerate(const UniValue& params, bool fHelp)
mapArgs["-gen"] = (fGenerate ? "1" : "0");
mapArgs ["-genproclimit"] = itostr(nGenProcLimit);
GenerateBitcoins(fGenerate, pwalletMain, nGenProcLimit);
GenerateBitcoins(fGenerate, nGenProcLimit, Params());
return NullUniValue;
}
#endif
UniValue getmininginfo(const UniValue& params, bool fHelp)
{
@ -257,9 +256,7 @@ UniValue getmininginfo(const UniValue& params, bool fHelp) @@ -257,9 +256,7 @@ UniValue getmininginfo(const UniValue& params, bool fHelp)
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
obj.push_back(Pair("generate", getgenerate(params, false)));
#endif
return obj;
}

2
src/rpcserver.cpp

@ -306,12 +306,10 @@ static const CRPCCommand vRPCCommands[] = @@ -306,12 +306,10 @@ static const CRPCCommand vRPCCommands[] =
{ "mining", "prioritisetransaction", &prioritisetransaction, true },
{ "mining", "submitblock", &submitblock, true },
#ifdef ENABLE_WALLET
/* Coin generation */
{ "generating", "getgenerate", &getgenerate, true },
{ "generating", "setgenerate", &setgenerate, true },
{ "generating", "generate", &generate, true },
#endif
/* Raw transactions */
{ "rawtransactions", "createrawtransaction", &createrawtransaction, true },

9
src/script/script.h

@ -609,4 +609,13 @@ public: @@ -609,4 +609,13 @@ public:
}
};
class CReserveScript
{
public:
CScript reserveScript;
virtual void KeepScript() {}
CReserveScript() {}
virtual ~CReserveScript() {}
};
#endif // BITCOIN_SCRIPT_SCRIPT_H

6
src/validationinterface.cpp

@ -19,9 +19,13 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) { @@ -19,9 +19,13 @@ void RegisterValidationInterface(CValidationInterface* pwalletIn) {
g_signals.Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
g_signals.Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1));
g_signals.BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
g_signals.ScriptForMining.connect(boost::bind(&CValidationInterface::GetScriptForMining, pwalletIn, _1));
g_signals.BlockFound.connect(boost::bind(&CValidationInterface::ResetRequestCount, pwalletIn, _1));
}
void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
g_signals.BlockFound.disconnect(boost::bind(&CValidationInterface::ResetRequestCount, pwalletIn, _1));
g_signals.ScriptForMining.disconnect(boost::bind(&CValidationInterface::GetScriptForMining, pwalletIn, _1));
g_signals.BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2));
g_signals.Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1));
g_signals.Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1));
@ -31,6 +35,8 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) { @@ -31,6 +35,8 @@ void UnregisterValidationInterface(CValidationInterface* pwalletIn) {
}
void UnregisterAllValidationInterfaces() {
g_signals.BlockFound.disconnect_all_slots();
g_signals.ScriptForMining.disconnect_all_slots();
g_signals.BlockChecked.disconnect_all_slots();
g_signals.Broadcast.disconnect_all_slots();
g_signals.Inventory.disconnect_all_slots();

8
src/validationinterface.h

@ -7,9 +7,11 @@ @@ -7,9 +7,11 @@
#define BITCOIN_VALIDATIONINTERFACE_H
#include <boost/signals2/signal.hpp>
#include <boost/shared_ptr.hpp>
class CBlock;
struct CBlockLocator;
class CReserveScript;
class CTransaction;
class CValidationInterface;
class CValidationState;
@ -34,6 +36,8 @@ protected: @@ -34,6 +36,8 @@ protected:
virtual void Inventory(const uint256 &hash) {}
virtual void ResendWalletTransactions(int64_t nBestBlockTime) {}
virtual void BlockChecked(const CBlock&, const CValidationState&) {}
virtual void GetScriptForMining(boost::shared_ptr<CReserveScript>&) {};
virtual void ResetRequestCount(const uint256 &hash) {};
friend void ::RegisterValidationInterface(CValidationInterface*);
friend void ::UnregisterValidationInterface(CValidationInterface*);
friend void ::UnregisterAllValidationInterfaces();
@ -52,6 +56,10 @@ struct CMainSignals { @@ -52,6 +56,10 @@ struct CMainSignals {
boost::signals2::signal<void (int64_t nBestBlockTime)> Broadcast;
/** Notifies listeners of a block validation result */
boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked;
/** Notifies listeners that a key for mining is required (coinbase) */
boost::signals2::signal<void (boost::shared_ptr<CReserveScript>&)> ScriptForMining;
/** Notifies listeners that a block has been successfully mined */
boost::signals2::signal<void (const uint256 &)> BlockFound;
};
CMainSignals& GetMainSignals();

11
src/wallet/wallet.cpp

@ -2583,6 +2583,17 @@ void CWallet::UpdatedTransaction(const uint256 &hashTx) @@ -2583,6 +2583,17 @@ void CWallet::UpdatedTransaction(const uint256 &hashTx)
}
}
void CWallet::GetScriptForMining(boost::shared_ptr<CReserveScript> &script)
{
boost::shared_ptr<CReserveKey> rKey(new CReserveKey(this));
CPubKey pubkey;
if (!rKey->GetReservedKey(pubkey))
return;
script = rKey;
script->reserveScript = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
}
void CWallet::LockCoin(COutPoint& output)
{
AssertLockHeld(cs_wallet); // setLockedCoins

12
src/wallet/wallet.h

@ -28,6 +28,8 @@ @@ -28,6 +28,8 @@
#include <utility>
#include <vector>
#include <boost/shared_ptr.hpp>
/**
* Settings
*/
@ -680,6 +682,13 @@ public: @@ -680,6 +682,13 @@ public:
}
}
void GetScriptForMining(boost::shared_ptr<CReserveScript> &script);
void ResetRequestCount(const uint256 &hash)
{
LOCK(cs_wallet);
mapRequestCount[hash] = 0;
};
unsigned int GetKeyPoolSize()
{
AssertLockHeld(cs_wallet); // setKeyPool
@ -735,7 +744,7 @@ public: @@ -735,7 +744,7 @@ public:
};
/** A key allocated from the key pool. */
class CReserveKey
class CReserveKey : public CReserveScript
{
protected:
CWallet* pwallet;
@ -756,6 +765,7 @@ public: @@ -756,6 +765,7 @@ public:
void ReturnKey();
bool GetReservedKey(CPubKey &pubkey);
void KeepKey();
void KeepScript() { KeepKey(); }
};

Loading…
Cancel
Save