From 5496253966abec287ea61a648cb518d14903f91f Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Wed, 1 Jul 2015 08:32:30 +0200 Subject: [PATCH] add CReserveScript to allow modular script keeping/returning - use one CReserveScript per mining thread --- src/miner.cpp | 21 +++++++++++---------- src/rpcmining.cpp | 10 +++++++--- src/script/script.h | 9 +++++++++ src/validationinterface.h | 7 ++++--- src/wallet/wallet.cpp | 11 ++++++----- src/wallet/wallet.h | 7 +++++-- 6 files changed, 42 insertions(+), 23 deletions(-) diff --git a/src/miner.cpp b/src/miner.cpp index c51c21b8c..46cde91a4 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -421,7 +421,7 @@ static bool ProcessBlockFound(CBlock* pblock, const CChainParams& chainparams) return true; } -void static BitcoinMiner(const CChainParams& chainparams, const CScript& coinbaseScript) +void static BitcoinMiner(const CChainParams& chainparams) { LogPrintf("BitcoinMiner started\n"); SetThreadPriority(THREAD_PRIORITY_LOWEST); @@ -429,7 +429,14 @@ void static BitcoinMiner(const CChainParams& chainparams, const CScript& coinbas unsigned int nExtraNonce = 0; + boost::shared_ptr 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 @@ -452,7 +459,7 @@ void static BitcoinMiner(const CChainParams& chainparams, const CScript& coinbas unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); CBlockIndex* pindexPrev = chainActive.Tip(); - auto_ptr pblocktemplate(CreateNewBlock(coinbaseScript)); + auto_ptr pblocktemplate(CreateNewBlock(coinbaseScript->reserveScript)); if (!pblocktemplate.get()) { LogPrintf("Error in BitcoinMiner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n"); @@ -486,6 +493,7 @@ void static BitcoinMiner(const CChainParams& chainparams, const CScript& coinbas LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", hash.GetHex(), hashTarget.GetHex()); ProcessBlockFound(pblock, chainparams); SetThreadPriority(THREAD_PRIORITY_LOWEST); + coinbaseScript->KeepScript(); // In regression test mode, stop mining after a block is found. if (chainparams.MineBlocksOnDemand()) @@ -551,14 +559,7 @@ void GenerateBitcoins(bool fGenerate, int nThreads, const CChainParams& chainpar if (nThreads == 0 || !fGenerate) return; - CScript coinbaseScript; - GetMainSignals().ScriptForMining(coinbaseScript); - - //throw an error if no script was provided - if (!coinbaseScript.size()) - throw std::runtime_error("No coinbase script available (mining requires a wallet)"); - minerThreads = new boost::thread_group(); for (int i = 0; i < nThreads; i++) - minerThreads->create_thread(boost::bind(&BitcoinMiner, boost::cref(chainparams), coinbaseScript)); + minerThreads->create_thread(boost::bind(&BitcoinMiner, boost::cref(chainparams))); } diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index 3e4071bef..9c6fb10af 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -20,6 +20,7 @@ #include #include +#include #include "univalue/univalue.h" @@ -131,11 +132,11 @@ UniValue generate(const UniValue& params, bool fHelp) int nHeight = 0; int nGenerate = params[0].get_int(); - CScript coinbaseScript; + boost::shared_ptr coinbaseScript; GetMainSignals().ScriptForMining(coinbaseScript); //throw an error if no script was provided - if (!coinbaseScript.size()) + if (!coinbaseScript->reserveScript.size()) throw JSONRPCError(RPC_INTERNAL_ERROR, "No coinbase script available (mining requires a wallet)"); { // Don't keep cs_main locked @@ -148,7 +149,7 @@ UniValue generate(const UniValue& params, bool fHelp) UniValue blockHashes(UniValue::VARR); while (nHeight < nHeightEnd) { - auto_ptr pblocktemplate(CreateNewBlock(coinbaseScript)); + auto_ptr pblocktemplate(CreateNewBlock(coinbaseScript->reserveScript)); if (!pblocktemplate.get()) throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block"); CBlock *pblock = &pblocktemplate->block; @@ -166,6 +167,9 @@ 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; } diff --git a/src/script/script.h b/src/script/script.h index c09899aab..e39ca57f4 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.h b/src/validationinterface.h index 2d2427a19..34acd4016 100644 --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -7,10 +7,11 @@ #define BITCOIN_VALIDATIONINTERFACE_H #include +#include class CBlock; struct CBlockLocator; -class CScript; +class CReserveScript; class CTransaction; class CValidationInterface; class CValidationState; @@ -35,7 +36,7 @@ protected: virtual void Inventory(const uint256 &hash) {} virtual void ResendWalletTransactions(int64_t nBestBlockTime) {} virtual void BlockChecked(const CBlock&, const CValidationState&) {} - virtual void GetScriptForMining(CScript &script) {}; + virtual void GetScriptForMining(boost::shared_ptr&) {}; virtual void UpdateRequestCount(const CBlock&) {}; friend void ::RegisterValidationInterface(CValidationInterface*); friend void ::UnregisterValidationInterface(CValidationInterface*); @@ -56,7 +57,7 @@ struct CMainSignals { /** Notifies listeners of a block validation result */ boost::signals2::signal BlockChecked; /** Notifies listeners that a key for mining is required (coinbase) */ - boost::signals2::signal ScriptForMining; + boost::signals2::signal&)> ScriptForMining; /** Notifies listeners that a block has been successfully mined */ boost::signals2::signal BlockFound; }; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 997ca1e2f..238f62a57 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2583,14 +2583,15 @@ void CWallet::UpdatedTransaction(const uint256 &hashTx) } } -void CWallet::GetScriptForMining(CScript &script) +void CWallet::GetScriptForMining(boost::shared_ptr &script) { - CReserveKey reservekey(this); + boost::shared_ptr rKey(new CReserveKey(this)); CPubKey pubkey; - if (!reservekey.GetReservedKey(pubkey)) + if (!rKey->GetReservedKey(pubkey)) return; - script = CScript() << ToByteVector(pubkey) << OP_CHECKSIG; - reservekey.KeepKey(); + + script = rKey; + script->reserveScript = CScript() << ToByteVector(pubkey) << OP_CHECKSIG; } void CWallet::LockCoin(COutPoint& output) diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index c8ce5ad22..1774596af 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -28,6 +28,8 @@ #include #include +#include + /** * Settings */ @@ -680,7 +682,7 @@ public: } } - void GetScriptForMining(CScript &script); + void GetScriptForMining(boost::shared_ptr &script); void UpdateRequestCount(const CBlock& block) { LOCK(cs_wallet); @@ -742,7 +744,7 @@ public: }; /** A key allocated from the key pool. */ -class CReserveKey +class CReserveKey : public CReserveScript { protected: CWallet* pwallet; @@ -763,6 +765,7 @@ public: void ReturnKey(); bool GetReservedKey(CPubKey &pubkey); void KeepKey(); + void KeepScript() { KeepKey(); } };