add CReserveScript to allow modular script keeping/returning
- use one CReserveScript per mining thread
This commit is contained in:
parent
38da0d16b1
commit
f4055fe158
|
@ -10,28 +10,35 @@
|
|||
TEST(Miner, GetScriptForMinerAddress) {
|
||||
SelectParams(CBaseChainParams::MAIN);
|
||||
|
||||
CScript coinbaseScript;
|
||||
|
||||
// No miner address set
|
||||
GetScriptForMinerAddress(coinbaseScript);
|
||||
EXPECT_EQ(0, coinbaseScript.size());
|
||||
{
|
||||
boost::shared_ptr<CReserveScript> coinbaseScript;
|
||||
GetScriptForMinerAddress(coinbaseScript);
|
||||
EXPECT_FALSE((bool) coinbaseScript);
|
||||
}
|
||||
|
||||
mapArgs["-mineraddress"] = "notAnAddress";
|
||||
coinbaseScript.clear();
|
||||
GetScriptForMinerAddress(coinbaseScript);
|
||||
EXPECT_EQ(0, coinbaseScript.size());
|
||||
{
|
||||
boost::shared_ptr<CReserveScript> coinbaseScript;
|
||||
GetScriptForMinerAddress(coinbaseScript);
|
||||
EXPECT_FALSE((bool) coinbaseScript);
|
||||
}
|
||||
|
||||
// Partial address
|
||||
mapArgs["-mineraddress"] = "t1T8yaLVhNqxA5KJcmiqq";
|
||||
coinbaseScript.clear();
|
||||
GetScriptForMinerAddress(coinbaseScript);
|
||||
EXPECT_EQ(0, coinbaseScript.size());
|
||||
{
|
||||
boost::shared_ptr<CReserveScript> coinbaseScript;
|
||||
GetScriptForMinerAddress(coinbaseScript);
|
||||
EXPECT_FALSE((bool) coinbaseScript);
|
||||
}
|
||||
|
||||
// Typo in address
|
||||
mapArgs["-mineraddress"] = "t1TByaLVhNqxA5KJcmiqqFN88e8DNp2PBfF";
|
||||
coinbaseScript.clear();
|
||||
GetScriptForMinerAddress(coinbaseScript);
|
||||
EXPECT_EQ(0, coinbaseScript.size());
|
||||
{
|
||||
boost::shared_ptr<CReserveScript> coinbaseScript;
|
||||
GetScriptForMinerAddress(coinbaseScript);
|
||||
EXPECT_FALSE((bool) coinbaseScript);
|
||||
}
|
||||
|
||||
// Set up expected scriptPubKey for t1T8yaLVhNqxA5KJcmiqqFN88e8DNp2PBfF
|
||||
CKeyID keyID;
|
||||
|
@ -40,19 +47,28 @@ TEST(Miner, GetScriptForMinerAddress) {
|
|||
|
||||
// Valid address
|
||||
mapArgs["-mineraddress"] = "t1T8yaLVhNqxA5KJcmiqqFN88e8DNp2PBfF";
|
||||
coinbaseScript.clear();
|
||||
GetScriptForMinerAddress(coinbaseScript);
|
||||
EXPECT_EQ(expectedCoinbaseScript, coinbaseScript);
|
||||
{
|
||||
boost::shared_ptr<CReserveScript> coinbaseScript;
|
||||
GetScriptForMinerAddress(coinbaseScript);
|
||||
EXPECT_TRUE((bool) coinbaseScript);
|
||||
EXPECT_EQ(expectedCoinbaseScript, coinbaseScript->reserveScript);
|
||||
}
|
||||
|
||||
// Valid address with leading whitespace
|
||||
mapArgs["-mineraddress"] = " t1T8yaLVhNqxA5KJcmiqqFN88e8DNp2PBfF";
|
||||
coinbaseScript.clear();
|
||||
GetScriptForMinerAddress(coinbaseScript);
|
||||
EXPECT_EQ(expectedCoinbaseScript, coinbaseScript);
|
||||
{
|
||||
boost::shared_ptr<CReserveScript> coinbaseScript;
|
||||
GetScriptForMinerAddress(coinbaseScript);
|
||||
EXPECT_TRUE((bool) coinbaseScript);
|
||||
EXPECT_EQ(expectedCoinbaseScript, coinbaseScript->reserveScript);
|
||||
}
|
||||
|
||||
// Valid address with trailing whitespace
|
||||
mapArgs["-mineraddress"] = "t1T8yaLVhNqxA5KJcmiqqFN88e8DNp2PBfF ";
|
||||
coinbaseScript.clear();
|
||||
GetScriptForMinerAddress(coinbaseScript);
|
||||
EXPECT_EQ(expectedCoinbaseScript, coinbaseScript);
|
||||
{
|
||||
boost::shared_ptr<CReserveScript> coinbaseScript;
|
||||
GetScriptForMinerAddress(coinbaseScript);
|
||||
EXPECT_TRUE((bool) coinbaseScript);
|
||||
EXPECT_EQ(expectedCoinbaseScript, coinbaseScript->reserveScript);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -405,15 +405,23 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
|||
|
||||
#ifdef ENABLE_MINING
|
||||
|
||||
void GetScriptForMinerAddress(CScript &script)
|
||||
class MinerAddressScript : public CReserveScript
|
||||
{
|
||||
void KeepScript() {}
|
||||
};
|
||||
|
||||
void GetScriptForMinerAddress(boost::shared_ptr<CReserveScript> &script)
|
||||
{
|
||||
CTxDestination addr = DecodeDestination(GetArg("-mineraddress", ""));
|
||||
if (!IsValidDestination(addr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
boost::shared_ptr<MinerAddressScript> mAddr(new MinerAddressScript());
|
||||
CKeyID keyID = boost::get<CKeyID>(addr);
|
||||
script = CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
|
||||
|
||||
script = mAddr;
|
||||
script->reserveScript = CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
|
||||
}
|
||||
|
||||
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce)
|
||||
|
@ -460,7 +468,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("ZcashMiner started\n");
|
||||
SetThreadPriority(THREAD_PRIORITY_LOWEST);
|
||||
|
@ -469,6 +477,9 @@ void static BitcoinMiner(const CChainParams& chainparams, const CScript& coinbas
|
|||
// Each thread has its own counter
|
||||
unsigned int nExtraNonce = 0;
|
||||
|
||||
boost::shared_ptr<CReserveScript> coinbaseScript;
|
||||
GetMainSignals().ScriptForMining(coinbaseScript);
|
||||
|
||||
unsigned int n = chainparams.EquihashN();
|
||||
unsigned int k = chainparams.EquihashK();
|
||||
|
||||
|
@ -487,6 +498,10 @@ void static BitcoinMiner(const CChainParams& chainparams, const CScript& coinbas
|
|||
miningTimer.start();
|
||||
|
||||
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 or -mineraddress)");
|
||||
|
||||
while (true) {
|
||||
if (chainparams.MiningRequiresPeers()) {
|
||||
// Busy-wait for the network to come online so we don't waste time mining
|
||||
|
@ -511,7 +526,7 @@ void static BitcoinMiner(const CChainParams& chainparams, const CScript& coinbas
|
|||
unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
|
||||
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||
|
||||
unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlock(coinbaseScript));
|
||||
unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlock(coinbaseScript->reserveScript));
|
||||
if (!pblocktemplate.get())
|
||||
{
|
||||
if (GetArg("-mineraddress", "").empty()) {
|
||||
|
@ -559,7 +574,7 @@ void static BitcoinMiner(const CChainParams& chainparams, const CScript& coinbas
|
|||
solver, pblock->nNonce.ToString());
|
||||
|
||||
std::function<bool(std::vector<unsigned char>)> validBlock =
|
||||
[&pblock, &hashTarget, &chainparams, &m_cs, &cancelSolver]
|
||||
[&pblock, &hashTarget, &chainparams, &m_cs, &cancelSolver, &coinbaseScript]
|
||||
(std::vector<unsigned char> soln) {
|
||||
// Write the solution to the hash and compute the result.
|
||||
LogPrint("pow", "- Checking solution against target\n");
|
||||
|
@ -580,6 +595,7 @@ void static BitcoinMiner(const CChainParams& chainparams, const CScript& coinbas
|
|||
cancelSolver = false;
|
||||
}
|
||||
SetThreadPriority(THREAD_PRIORITY_LOWEST);
|
||||
coinbaseScript->KeepScript();
|
||||
|
||||
// In regression test mode, stop mining after a block is found.
|
||||
if (chainparams.MineBlocksOnDemand()) {
|
||||
|
@ -702,16 +718,9 @@ 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 or -mineraddress)");
|
||||
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn);
|
|||
|
||||
#ifdef ENABLE_MINING
|
||||
/** Get script for -mineraddress */
|
||||
void GetScriptForMinerAddress(CScript &script);
|
||||
void GetScriptForMinerAddress(boost::shared_ptr<CReserveScript> &script);
|
||||
/** Modify the extranonce in a block */
|
||||
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
|
||||
/** Run the miner threads */
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include <boost/assign/list_of.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <univalue.h>
|
||||
|
||||
|
@ -179,11 +180,11 @@ UniValue generate(const UniValue& params, bool fHelp)
|
|||
int nHeight = 0;
|
||||
int nGenerate = params[0].get_int();
|
||||
|
||||
CScript coinbaseScript;
|
||||
boost::shared_ptr<CReserveScript> 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 or -mineraddress)");
|
||||
|
||||
{ // Don't keep cs_main locked
|
||||
|
@ -198,7 +199,7 @@ UniValue generate(const UniValue& params, bool fHelp)
|
|||
unsigned int k = Params().EquihashK();
|
||||
while (nHeight < nHeightEnd)
|
||||
{
|
||||
std::unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlock(coinbaseScript));
|
||||
std::unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlock(coinbaseScript->reserveScript));
|
||||
if (!pblocktemplate.get())
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
|
||||
CBlock *pblock = &pblocktemplate->block;
|
||||
|
@ -250,6 +251,9 @@ endloop:
|
|||
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;
|
||||
}
|
||||
|
@ -603,17 +607,20 @@ UniValue getblocktemplate(const UniValue& params, bool fHelp)
|
|||
pblocktemplate = NULL;
|
||||
}
|
||||
|
||||
CScript coinbaseScript;
|
||||
boost::shared_ptr<CReserveScript> 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 or -mineraddress)");
|
||||
|
||||
pblocktemplate = CreateNewBlock(coinbaseScript);
|
||||
pblocktemplate = CreateNewBlock(coinbaseScript->reserveScript);
|
||||
if (!pblocktemplate)
|
||||
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
|
||||
|
||||
// Mark script as important because it was used at least for one coinbase output
|
||||
coinbaseScript->KeepScript();
|
||||
|
||||
// Need to update only after we know CreateNewBlock succeeded
|
||||
pindexPrev = pindexPrevNew;
|
||||
}
|
||||
|
|
|
@ -587,4 +587,13 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class CReserveScript
|
||||
{
|
||||
public:
|
||||
CScript reserveScript;
|
||||
virtual void KeepScript() {}
|
||||
CReserveScript() {}
|
||||
virtual ~CReserveScript() {}
|
||||
};
|
||||
|
||||
#endif // BITCOIN_SCRIPT_SCRIPT_H
|
||||
|
|
|
@ -7,13 +7,14 @@
|
|||
#define BITCOIN_VALIDATIONINTERFACE_H
|
||||
|
||||
#include <boost/signals2/signal.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include "zcash/IncrementalMerkleTree.hpp"
|
||||
|
||||
class CBlock;
|
||||
class CBlockIndex;
|
||||
struct CBlockLocator;
|
||||
class CScript;
|
||||
class CReserveScript;
|
||||
class CTransaction;
|
||||
class CValidationInterface;
|
||||
class CValidationState;
|
||||
|
@ -41,7 +42,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<CReserveScript>&) {};
|
||||
virtual void UpdateRequestCount(const CBlock&) {};
|
||||
friend void ::RegisterValidationInterface(CValidationInterface*);
|
||||
friend void ::UnregisterValidationInterface(CValidationInterface*);
|
||||
|
@ -68,7 +69,7 @@ struct CMainSignals {
|
|||
/** 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 (CScript &script)> ScriptForMining;
|
||||
boost::signals2::signal<void (boost::shared_ptr<CReserveScript>&)> ScriptForMining;
|
||||
/** Notifies listeners that a block has been successfully mined */
|
||||
boost::signals2::signal<void (const CBlock&)> BlockFound;
|
||||
};
|
||||
|
|
|
@ -4039,18 +4039,19 @@ void CWallet::UpdatedTransaction(const uint256 &hashTx)
|
|||
}
|
||||
}
|
||||
|
||||
void CWallet::GetScriptForMining(CScript &script)
|
||||
void CWallet::GetScriptForMining(boost::shared_ptr<CReserveScript> &script)
|
||||
{
|
||||
if (!GetArg("-mineraddress", "").empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
CReserveKey reservekey(this);
|
||||
boost::shared_ptr<CReserveKey> rKey(new CReserveKey(this));
|
||||
CPubKey pubkey;
|
||||
if (!reservekey.GetReservedKey(pubkey))
|
||||
if (!rKey->GetReservedKey(pubkey))
|
||||
return;
|
||||
script = CScript() << OP_DUP << OP_HASH160 << ToByteVector(pubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
|
||||
reservekey.KeepKey();
|
||||
|
||||
script = rKey;
|
||||
script->reserveScript = CScript() << OP_DUP << OP_HASH160 << ToByteVector(pubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
|
||||
}
|
||||
|
||||
void CWallet::LockCoin(COutPoint& output)
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
/**
|
||||
* Settings
|
||||
*/
|
||||
|
@ -1206,7 +1208,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void GetScriptForMining(CScript &script);
|
||||
void GetScriptForMining(boost::shared_ptr<CReserveScript> &script);
|
||||
void UpdateRequestCount(const CBlock& block)
|
||||
{
|
||||
LOCK(cs_wallet);
|
||||
|
@ -1308,7 +1310,7 @@ public:
|
|||
};
|
||||
|
||||
/** A key allocated from the key pool. */
|
||||
class CReserveKey
|
||||
class CReserveKey : public CReserveScript
|
||||
{
|
||||
protected:
|
||||
CWallet* pwallet;
|
||||
|
@ -1329,6 +1331,7 @@ public:
|
|||
void ReturnKey();
|
||||
virtual bool GetReservedKey(CPubKey &pubkey);
|
||||
void KeepKey();
|
||||
void KeepScript() { KeepKey(); }
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue