aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2015-07-01 18:38:23 +0200
committerWladimir J. van der Laan <laanwj@gmail.com>2015-07-01 18:38:48 +0200
commit786ed114c2b4ff3c315476615b492ae7c7c9b51a (patch)
tree5c8e0ff2ebbc89c965c4a5869332cae6b45489ea
parentda77a6f7611f71443914e1c71df1e52468cf507d (diff)
parenta7b9623d189eb4a7d37ff7ad706d6385c3a38e80 (diff)
downloadbitcoin-786ed114c2b4ff3c315476615b492ae7c7c9b51a.tar.xz
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)
-rw-r--r--src/init.cpp9
-rw-r--r--src/miner.cpp50
-rw-r--r--src/miner.h4
-rw-r--r--src/rpcmining.cpp31
-rw-r--r--src/rpcserver.cpp2
-rw-r--r--src/script/script.h9
-rw-r--r--src/validationinterface.cpp6
-rw-r--r--src/validationinterface.h8
-rw-r--r--src/wallet/wallet.cpp11
-rw-r--r--src/wallet/wallet.h12
10 files changed, 80 insertions, 62 deletions
diff --git a/src/init.cpp b/src/init.cpp
index c4e3573de3..b9510bec9d 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -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)
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)
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
diff --git a/src/miner.cpp b/src/miner.cpp
index f5919ca3af..2c5cba742c 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -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&
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
}
-#ifdef ENABLE_WALLET
//////////////////////////////////////////////////////////////////////////////
//
// Internal miner
@@ -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
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
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)
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)
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)
}
}
-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)
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
diff --git a/src/miner.h b/src/miner.h
index 96a6b70ecd..777a091967 100644
--- a/src/miner.h
+++ b/src/miner.h
@@ -11,6 +11,7 @@
#include <stdint.h>
class CBlockIndex;
+class CChainParams;
class CReserveKey;
class CScript;
class CWallet;
@@ -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);
diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp
index f332814611..9c6fb10af0 100644
--- a/src/rpcmining.cpp
+++ b/src/rpcmining.cpp
@@ -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)
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)
+ 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)
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)
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)
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)
+ 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)
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)
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;
}
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp
index 2f28971589..840bf57c21 100644
--- a/src/rpcserver.cpp
+++ b/src/rpcserver.cpp
@@ -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 },
diff --git a/src/script/script.h b/src/script/script.h
index c09899aabd..e39ca57f4f 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -609,4 +609,13 @@ public:
}
};
+class CReserveScript
+{
+public:
+ CScript reserveScript;
+ virtual void KeepScript() {}
+ CReserveScript() {}
+ virtual ~CReserveScript() {}
+};
+
#endif // BITCOIN_SCRIPT_SCRIPT_H
diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp
index 0532da5f37..d365f03008 100644
--- a/src/validationinterface.cpp
+++ b/src/validationinterface.cpp
@@ -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) {
}
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();
diff --git a/src/validationinterface.h b/src/validationinterface.h
index a911d1efeb..fb0ce0bdaa 100644
--- a/src/validationinterface.h
+++ b/src/validationinterface.h
@@ -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:
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 {
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();
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index eee57900b5..238f62a575 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -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
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index b6a8e8671f..f36c98e9fc 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -28,6 +28,8 @@
#include <utility>
#include <vector>
+#include <boost/shared_ptr.hpp>
+
/**
* Settings
*/
@@ -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:
};
/** A key allocated from the key pool. */
-class CReserveKey
+class CReserveKey : public CReserveScript
{
protected:
CWallet* pwallet;
@@ -756,6 +765,7 @@ public:
void ReturnKey();
bool GetReservedKey(CPubKey &pubkey);
void KeepKey();
+ void KeepScript() { KeepKey(); }
};