Auto merge of #1965 - str4d:1955-single-address-mining, r=bitcartel

Switch miner to P2PKH, add -mineraddress option

Closes #945 and #1955.
This commit is contained in:
zkbot 2017-02-09 20:58:00 +00:00
commit 0c78782662
8 changed files with 344 additions and 57 deletions

View File

@ -26,6 +26,7 @@ zcash_gtest_SOURCES += \
gtest/test_noteencryption.cpp \ gtest/test_noteencryption.cpp \
gtest/test_merkletree.cpp \ gtest/test_merkletree.cpp \
gtest/test_metrics.cpp \ gtest/test_metrics.cpp \
gtest/test_miner.cpp \
gtest/test_pow.cpp \ gtest/test_pow.cpp \
gtest/test_random.cpp \ gtest/test_random.cpp \
gtest/test_rpc.cpp \ gtest/test_rpc.cpp \

103
src/gtest/test_miner.cpp Normal file
View File

@ -0,0 +1,103 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "chainparams.h"
#include "key.h"
#include "miner.h"
#include "util.h"
#ifdef ENABLE_WALLET
#include "wallet/wallet.h"
#endif
#include <boost/optional.hpp>
using ::testing::Return;
#ifdef ENABLE_WALLET
class MockReserveKey : public CReserveKey {
public:
MockReserveKey() : CReserveKey(nullptr) { }
MOCK_METHOD1(GetReservedKey, bool(CPubKey &pubkey));
};
#endif
TEST(Miner, GetMinerScriptPubKey) {
SelectParams(CBaseChainParams::MAIN);
boost::optional<CScript> scriptPubKey;
#ifdef ENABLE_WALLET
MockReserveKey reservekey;
EXPECT_CALL(reservekey, GetReservedKey(::testing::_))
.WillRepeatedly(Return(false));
#endif
// No miner address set
#ifdef ENABLE_WALLET
scriptPubKey = GetMinerScriptPubKey(reservekey);
#else
scriptPubKey = GetMinerScriptPubKey();
#endif
EXPECT_FALSE((bool) scriptPubKey);
mapArgs["-mineraddress"] = "notAnAddress";
#ifdef ENABLE_WALLET
scriptPubKey = GetMinerScriptPubKey(reservekey);
#else
scriptPubKey = GetMinerScriptPubKey();
#endif
EXPECT_FALSE((bool) scriptPubKey);
// Partial address
mapArgs["-mineraddress"] = "t1T8yaLVhNqxA5KJcmiqq";
#ifdef ENABLE_WALLET
scriptPubKey = GetMinerScriptPubKey(reservekey);
#else
scriptPubKey = GetMinerScriptPubKey();
#endif
EXPECT_FALSE((bool) scriptPubKey);
// Typo in address
mapArgs["-mineraddress"] = "t1TByaLVhNqxA5KJcmiqqFN88e8DNp2PBfF";
#ifdef ENABLE_WALLET
scriptPubKey = GetMinerScriptPubKey(reservekey);
#else
scriptPubKey = GetMinerScriptPubKey();
#endif
EXPECT_FALSE((bool) scriptPubKey);
// Set up expected scriptPubKey for t1T8yaLVhNqxA5KJcmiqqFN88e8DNp2PBfF
CKeyID keyID;
keyID.SetHex("eb88f1c65b39a823479ac9c7db2f4a865960a165");
CScript expectedScriptPubKey = CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
// Valid address
mapArgs["-mineraddress"] = "t1T8yaLVhNqxA5KJcmiqqFN88e8DNp2PBfF";
#ifdef ENABLE_WALLET
scriptPubKey = GetMinerScriptPubKey(reservekey);
#else
scriptPubKey = GetMinerScriptPubKey();
#endif
EXPECT_TRUE((bool) scriptPubKey);
EXPECT_EQ(expectedScriptPubKey, *scriptPubKey);
// Valid address with leading whitespace
mapArgs["-mineraddress"] = " t1T8yaLVhNqxA5KJcmiqqFN88e8DNp2PBfF";
#ifdef ENABLE_WALLET
scriptPubKey = GetMinerScriptPubKey(reservekey);
#else
scriptPubKey = GetMinerScriptPubKey();
#endif
EXPECT_TRUE((bool) scriptPubKey);
EXPECT_EQ(expectedScriptPubKey, *scriptPubKey);
// Valid address with trailing whitespace
mapArgs["-mineraddress"] = "t1T8yaLVhNqxA5KJcmiqqFN88e8DNp2PBfF ";
#ifdef ENABLE_WALLET
scriptPubKey = GetMinerScriptPubKey(reservekey);
#else
scriptPubKey = GetMinerScriptPubKey();
#endif
EXPECT_TRUE((bool) scriptPubKey);
EXPECT_EQ(expectedScriptPubKey, *scriptPubKey);
}

View File

@ -11,6 +11,9 @@
#include "crypto/common.h" #include "crypto/common.h"
#include "addrman.h" #include "addrman.h"
#include "amount.h" #include "amount.h"
#ifdef ENABLE_MINING
#include "base58.h"
#endif
#include "checkpoints.h" #include "checkpoints.h"
#include "compat/sanity.h" #include "compat/sanity.h"
#include "consensus/validation.h" #include "consensus/validation.h"
@ -170,8 +173,12 @@ void Shutdown()
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
if (pwalletMain) if (pwalletMain)
pwalletMain->Flush(false); pwalletMain->Flush(false);
#ifdef ENABLE_MINING #endif
#ifdef ENABLE_MINING
#ifdef ENABLE_WALLET
GenerateBitcoins(false, NULL, 0); GenerateBitcoins(false, NULL, 0);
#else
GenerateBitcoins(false, 0);
#endif #endif
#endif #endif
StopNode(); StopNode();
@ -409,11 +416,6 @@ std::string HelpMessage(HelpMessageMode mode)
debugCategories += ", qt"; debugCategories += ", qt";
strUsage += HelpMessageOpt("-debug=<category>", strprintf(_("Output debugging information (default: %u, supplying <category> is optional)"), 0) + ". " + 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 + "."); _("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));
strUsage += HelpMessageOpt("-equihashsolver=<name>", _("Specify the Equihash solver to be used if enabled (default: \"default\")"));
#endif
strUsage += HelpMessageOpt("-help-debug", _("Show all debugging options (usage: --help -help-debug)")); 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("-logips", strprintf(_("Include IP addresses in debug output (default: %u)"), 0));
strUsage += HelpMessageOpt("-logtimestamps", strprintf(_("Prepend debug output with timestamp (default: %u)"), 1)); strUsage += HelpMessageOpt("-logtimestamps", strprintf(_("Prepend debug output with timestamp (default: %u)"), 1));
@ -444,6 +446,22 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-blockmaxsize=<n>", strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE)); strUsage += HelpMessageOpt("-blockmaxsize=<n>", strprintf(_("Set maximum block size in bytes (default: %d)"), DEFAULT_BLOCK_MAX_SIZE));
strUsage += HelpMessageOpt("-blockprioritysize=<n>", strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE)); strUsage += HelpMessageOpt("-blockprioritysize=<n>", strprintf(_("Set maximum size of high-priority/low-fee transactions in bytes (default: %d)"), DEFAULT_BLOCK_PRIORITY_SIZE));
#ifdef ENABLE_MINING
strUsage += HelpMessageGroup(_("Mining options:"));
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));
strUsage += HelpMessageOpt("-equihashsolver=<name>", _("Specify the Equihash solver to be used if enabled (default: \"default\")"));
strUsage += HelpMessageOpt("-mineraddress=<addr>", _("Send mined coins to a specific single address"));
strUsage += HelpMessageOpt("-minetolocalwallet", strprintf(
_("Require that mined blocks use a coinbase address in the local wallet (default: %u)"),
#ifdef ENABLE_WALLET
1
#else
0
#endif
));
#endif
strUsage += HelpMessageGroup(_("RPC server options:")); strUsage += HelpMessageGroup(_("RPC server options:"));
strUsage += HelpMessageOpt("-server", _("Accept command line and JSON-RPC commands")); strUsage += HelpMessageOpt("-server", _("Accept command line and JSON-RPC commands"));
strUsage += HelpMessageOpt("-rest", strprintf(_("Accept public REST requests (default: %u)"), 0)); strUsage += HelpMessageOpt("-rest", strprintf(_("Accept public REST requests (default: %u)"), 0));
@ -952,6 +970,17 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
fAlerts = GetBoolArg("-alerts", DEFAULT_ALERTS); fAlerts = GetBoolArg("-alerts", DEFAULT_ALERTS);
#ifdef ENABLE_MINING
if (mapArgs.count("-mineraddress")) {
CBitcoinAddress addr;
if (!addr.SetString(mapArgs["-mineraddress"])) {
return InitError(strprintf(
_("Invalid address for -mineraddress=<addr>: '%s' (must be a transparent address)"),
mapArgs["-mineraddress"]));
}
}
#endif
// ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log // ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log
// Initialize libsodium // Initialize libsodium
@ -1477,6 +1506,35 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
LogPrintf("No wallet support compiled in!\n"); LogPrintf("No wallet support compiled in!\n");
#endif // !ENABLE_WALLET #endif // !ENABLE_WALLET
#ifdef ENABLE_MINING
#ifndef ENABLE_WALLET
auto mineToLocalWallet = GetBoolArg("-minetolocalwallet", false);
if (mineToLocalWallet) {
return InitError(_("Zcash was not built with wallet support. Set -minetolocalwallet=0 to use -mineraddress, or rebuild Zcash with wallet support."));
}
if (!mapArgs.count("-mineraddress")) {
return InitError(_("Zcash was not built with wallet support. Set -mineraddress, or rebuild Zcash with wallet support."));
}
#endif // !ENABLE_WALLET
if (mapArgs.count("-mineraddress")) {
#ifdef ENABLE_WALLET
auto mineToLocalWallet = GetBoolArg("-minetolocalwallet", true);
bool minerAddressInLocalWallet = false;
if (pwalletMain) {
// Address has alreday been validated
CBitcoinAddress addr(mapArgs["-mineraddress"]);
CKeyID keyID;
addr.GetKeyID(keyID);
minerAddressInLocalWallet = pwalletMain->HaveKey(keyID);
}
if (mineToLocalWallet && !minerAddressInLocalWallet) {
return InitError(_("-mineraddress is not in the local wallet. Either use a local address, or set -minetolocalwallet=0"));
}
#endif // ENABLE_WALLET
}
#endif // ENABLE_MINING
// ********************************************************* Step 9: data directory maintenance // ********************************************************* Step 9: data directory maintenance
// if pruning, unset the service bit and perform the initial blockstore prune // if pruning, unset the service bit and perform the initial blockstore prune
@ -1539,10 +1597,14 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
boost::ref(cs_main), boost::cref(pindexBestHeader), nPowTargetSpacing); boost::ref(cs_main), boost::cref(pindexBestHeader), nPowTargetSpacing);
scheduler.scheduleEvery(f, nPowTargetSpacing); scheduler.scheduleEvery(f, nPowTargetSpacing);
#if defined(ENABLE_WALLET) && defined(ENABLE_MINING) #ifdef ENABLE_MINING
// Generate coins in the background // Generate coins in the background
if (pwalletMain) #ifdef ENABLE_WALLET
if (pwalletMain || !GetArg("-mineraddress", "").empty())
GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain, GetArg("-genproclimit", 1)); GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain, GetArg("-genproclimit", 1));
#else
GenerateBitcoins(GetBoolArg("-gen", false), GetArg("-genproclimit", 1));
#endif
#endif #endif
// ********************************************************* Step 11: finished // ********************************************************* Step 11: finished

View File

@ -4,14 +4,18 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "miner.h" #include "miner.h"
#if defined(ENABLE_WALLET) && defined(ENABLE_MINING) #ifdef ENABLE_MINING
#include "pow/tromp/equi_miner.h" #include "pow/tromp/equi_miner.h"
#endif #endif
#include "amount.h" #include "amount.h"
#include "base58.h"
#include "chainparams.h" #include "chainparams.h"
#include "consensus/consensus.h" #include "consensus/consensus.h"
#include "consensus/validation.h" #include "consensus/validation.h"
#ifdef ENABLE_MINING
#include "crypto/equihash.h"
#endif
#include "hash.h" #include "hash.h"
#include "main.h" #include "main.h"
#include "metrics.h" #include "metrics.h"
@ -20,20 +24,20 @@
#include "primitives/transaction.h" #include "primitives/transaction.h"
#include "random.h" #include "random.h"
#include "timedata.h" #include "timedata.h"
#include "ui_interface.h"
#include "util.h" #include "util.h"
#include "utilmoneystr.h" #include "utilmoneystr.h"
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
#ifdef ENABLE_MINING
#include "crypto/equihash.h"
#endif
#include "wallet/wallet.h" #include "wallet/wallet.h"
#include <functional>
#endif #endif
#include "sodium.h" #include "sodium.h"
#include <boost/thread.hpp> #include <boost/thread.hpp>
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>
#ifdef ENABLE_MINING
#include <functional>
#endif
#include <mutex> #include <mutex>
using namespace std; using namespace std;
@ -383,6 +387,55 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
return pblocktemplate.release(); return pblocktemplate.release();
} }
#ifdef ENABLE_WALLET
boost::optional<CScript> GetMinerScriptPubKey(CReserveKey& reservekey)
#else
boost::optional<CScript> GetMinerScriptPubKey()
#endif
{
CKeyID keyID;
CBitcoinAddress addr;
if (addr.SetString(GetArg("-mineraddress", ""))) {
addr.GetKeyID(keyID);
} else {
#ifdef ENABLE_WALLET
CPubKey pubkey;
if (!reservekey.GetReservedKey(pubkey)) {
return boost::optional<CScript>();
}
keyID = pubkey.GetID();
#else
return boost::optional<CScript>();
#endif
}
CScript scriptPubKey = CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
return scriptPubKey;
}
#ifdef ENABLE_WALLET
CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey)
{
boost::optional<CScript> scriptPubKey = GetMinerScriptPubKey(reservekey);
#else
CBlockTemplate* CreateNewBlockWithKey()
{
boost::optional<CScript> scriptPubKey = GetMinerScriptPubKey();
#endif
if (!scriptPubKey) {
return NULL;
}
return CreateNewBlock(*scriptPubKey);
}
//////////////////////////////////////////////////////////////////////////////
//
// Internal miner
//
#ifdef ENABLE_MINING
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce) void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce)
{ {
// Update nExtraNonce // Update nExtraNonce
@ -403,23 +456,10 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int&
} }
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
//////////////////////////////////////////////////////////////////////////////
//
// Internal miner
//
CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey)
{
CPubKey pubkey;
if (!reservekey.GetReservedKey(pubkey))
return NULL;
CScript scriptPubKey = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
return CreateNewBlock(scriptPubKey);
}
#ifdef ENABLE_MINING
static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey) static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
#else
static bool ProcessBlockFound(CBlock* pblock)
#endif // ENABLE_WALLET
{ {
LogPrintf("%s\n", pblock->ToString()); LogPrintf("%s\n", pblock->ToString());
LogPrintf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue)); LogPrintf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue));
@ -431,14 +471,18 @@ static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& rese
return error("ZcashMiner: generated block is stale"); return error("ZcashMiner: generated block is stale");
} }
// Remove key from key pool #ifdef ENABLE_WALLET
reservekey.KeepKey(); if (GetArg("-mineraddress", "").empty()) {
// Remove key from key pool
reservekey.KeepKey();
}
// Track how many getdata requests this block gets // Track how many getdata requests this block gets
{ {
LOCK(wallet.cs_wallet); LOCK(wallet.cs_wallet);
wallet.mapRequestCount[pblock->GetHash()] = 0; wallet.mapRequestCount[pblock->GetHash()] = 0;
} }
#endif
// Process this block the same as if we had received it from another node // Process this block the same as if we had received it from another node
CValidationState state; CValidationState state;
@ -450,15 +494,23 @@ static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& rese
return true; return true;
} }
#ifdef ENABLE_WALLET
void static BitcoinMiner(CWallet *pwallet) void static BitcoinMiner(CWallet *pwallet)
#else
void static BitcoinMiner()
#endif
{ {
LogPrintf("ZcashMiner started\n"); LogPrintf("ZcashMiner started\n");
SetThreadPriority(THREAD_PRIORITY_LOWEST); SetThreadPriority(THREAD_PRIORITY_LOWEST);
RenameThread("zcash-miner"); RenameThread("zcash-miner");
const CChainParams& chainparams = Params(); const CChainParams& chainparams = Params();
// Each thread has its own key and counter #ifdef ENABLE_WALLET
// Each thread has its own key
CReserveKey reservekey(pwallet); CReserveKey reservekey(pwallet);
#endif
// Each thread has its own counter
unsigned int nExtraNonce = 0; unsigned int nExtraNonce = 0;
unsigned int n = chainparams.EquihashN(); unsigned int n = chainparams.EquihashN();
@ -500,10 +552,19 @@ void static BitcoinMiner(CWallet *pwallet)
unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
CBlockIndex* pindexPrev = chainActive.Tip(); CBlockIndex* pindexPrev = chainActive.Tip();
#ifdef ENABLE_WALLET
unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey)); unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
#else
unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey());
#endif
if (!pblocktemplate.get()) if (!pblocktemplate.get())
{ {
LogPrintf("Error in ZcashMiner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n"); if (GetArg("-mineraddress", "").empty()) {
LogPrintf("Error in ZcashMiner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n");
} else {
// Should never reach here, because -mineraddress validity is checked in init.cpp
LogPrintf("Error in ZcashMiner: Invalid -mineraddress\n");
}
return; return;
} }
CBlock *pblock = &pblocktemplate->block; CBlock *pblock = &pblocktemplate->block;
@ -543,7 +604,11 @@ void static BitcoinMiner(CWallet *pwallet)
solver, pblock->nNonce.ToString()); solver, pblock->nNonce.ToString());
std::function<bool(std::vector<unsigned char>)> validBlock = std::function<bool(std::vector<unsigned char>)> validBlock =
#ifdef ENABLE_WALLET
[&pblock, &hashTarget, &pwallet, &reservekey, &m_cs, &cancelSolver, &chainparams] [&pblock, &hashTarget, &pwallet, &reservekey, &m_cs, &cancelSolver, &chainparams]
#else
[&pblock, &hashTarget, &m_cs, &cancelSolver, &chainparams]
#endif
(std::vector<unsigned char> soln) { (std::vector<unsigned char> soln) {
// Write the solution to the hash and compute the result. // Write the solution to the hash and compute the result.
LogPrint("pow", "- Checking solution against target\n"); LogPrint("pow", "- Checking solution against target\n");
@ -558,7 +623,11 @@ void static BitcoinMiner(CWallet *pwallet)
SetThreadPriority(THREAD_PRIORITY_NORMAL); SetThreadPriority(THREAD_PRIORITY_NORMAL);
LogPrintf("ZcashMiner:\n"); LogPrintf("ZcashMiner:\n");
LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", pblock->GetHash().GetHex(), hashTarget.GetHex()); LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", pblock->GetHash().GetHex(), hashTarget.GetHex());
#ifdef ENABLE_WALLET
if (ProcessBlockFound(pblock, *pwallet, reservekey)) { if (ProcessBlockFound(pblock, *pwallet, reservekey)) {
#else
if (ProcessBlockFound(pblock)) {
#endif
// Ignore chain updates caused by us // Ignore chain updates caused by us
std::lock_guard<std::mutex> lock{m_cs}; std::lock_guard<std::mutex> lock{m_cs};
cancelSolver = false; cancelSolver = false;
@ -665,7 +734,11 @@ void static BitcoinMiner(CWallet *pwallet)
c.disconnect(); c.disconnect();
} }
#ifdef ENABLE_WALLET
void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads) void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads)
#else
void GenerateBitcoins(bool fGenerate, int nThreads)
#endif
{ {
static boost::thread_group* minerThreads = NULL; static boost::thread_group* minerThreads = NULL;
@ -688,9 +761,13 @@ void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads)
return; return;
minerThreads = new boost::thread_group(); minerThreads = new boost::thread_group();
for (int i = 0; i < nThreads; i++) for (int i = 0; i < nThreads; i++) {
#ifdef ENABLE_WALLET
minerThreads->create_thread(boost::bind(&BitcoinMiner, pwallet)); minerThreads->create_thread(boost::bind(&BitcoinMiner, pwallet));
#else
minerThreads->create_thread(&BitcoinMiner);
#endif
}
} }
#endif // ENABLE_MINING #endif // ENABLE_MINING
#endif // ENABLE_WALLET

View File

@ -8,12 +8,15 @@
#include "primitives/block.h" #include "primitives/block.h"
#include <boost/optional.hpp>
#include <stdint.h> #include <stdint.h>
class CBlockIndex; class CBlockIndex;
class CReserveKey;
class CScript; class CScript;
#ifdef ENABLE_WALLET
class CReserveKey;
class CWallet; class CWallet;
#endif
namespace Consensus { struct Params; }; namespace Consensus { struct Params; };
struct CBlockTemplate struct CBlockTemplate
@ -23,15 +26,27 @@ struct CBlockTemplate
std::vector<int64_t> vTxSigOps; std::vector<int64_t> vTxSigOps;
}; };
#ifdef ENABLE_MINING
/** Run the miner threads */
void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads);
#endif
/** Generate a new block, without valid proof-of-work */ /** Generate a new block, without valid proof-of-work */
CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn); CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn);
#ifdef ENABLE_WALLET
boost::optional<CScript> GetMinerScriptPubKey(CReserveKey& reservekey);
CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey); CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey);
#else
boost::optional<CScript> GetMinerScriptPubKey();
CBlockTemplate* CreateNewBlockWithKey();
#endif
#ifdef ENABLE_MINING
/** Modify the extranonce in a block */ /** Modify the extranonce in a block */
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce); void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
/** Run the miner threads */
#ifdef ENABLE_WALLET
void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads);
#else
void GenerateBitcoins(bool fGenerate, int nThreads);
#endif
#endif
void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev); void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev);
#endif // BITCOIN_MINER_H #endif // BITCOIN_MINER_H

View File

@ -8,7 +8,9 @@
#include "consensus/consensus.h" #include "consensus/consensus.h"
#include "consensus/validation.h" #include "consensus/validation.h"
#include "core_io.h" #include "core_io.h"
#ifdef ENABLE_MINING
#include "crypto/equihash.h" #include "crypto/equihash.h"
#endif
#include "init.h" #include "init.h"
#include "main.h" #include "main.h"
#include "metrics.h" #include "metrics.h"
@ -137,7 +139,7 @@ Value getnetworkhashps(const Array& params, bool fHelp)
return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1); return GetNetworkHashPS(params.size() > 0 ? params[0].get_int() : 120, params.size() > 1 ? params[1].get_int() : -1);
} }
#if defined(ENABLE_WALLET) && defined(ENABLE_MINING) #ifdef ENABLE_MINING
Value getgenerate(const Array& params, bool fHelp) Value getgenerate(const Array& params, bool fHelp)
{ {
if (fHelp || params.size() != 0) if (fHelp || params.size() != 0)
@ -173,8 +175,15 @@ Value generate(const Array& params, bool fHelp)
+ HelpExampleCli("generate", "11") + HelpExampleCli("generate", "11")
); );
if (pwalletMain == NULL) if (GetArg("-mineraddress", "").empty()) {
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)"); #ifdef ENABLE_WALLET
if (!pwalletMain) {
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Wallet disabled and -mineraddress not set");
}
#else
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "zcashd compiled without wallet and -mineraddress not set");
#endif
}
if (!Params().MineBlocksOnDemand()) if (!Params().MineBlocksOnDemand())
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "This method can only be used on regtest"); throw JSONRPCError(RPC_METHOD_NOT_FOUND, "This method can only be used on regtest");
@ -182,7 +191,9 @@ Value generate(const Array& params, bool fHelp)
int nHeightEnd = 0; int nHeightEnd = 0;
int nHeight = 0; int nHeight = 0;
int nGenerate = params[0].get_int(); int nGenerate = params[0].get_int();
#ifdef ENABLE_WALLET
CReserveKey reservekey(pwalletMain); CReserveKey reservekey(pwalletMain);
#endif
{ // Don't keep cs_main locked { // Don't keep cs_main locked
LOCK(cs_main); LOCK(cs_main);
@ -196,7 +207,11 @@ Value generate(const Array& params, bool fHelp)
unsigned int k = Params().EquihashK(); unsigned int k = Params().EquihashK();
while (nHeight < nHeightEnd) while (nHeight < nHeightEnd)
{ {
#ifdef ENABLE_WALLET
unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey)); unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
#else
unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey());
#endif
if (!pblocktemplate.get()) if (!pblocktemplate.get())
throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet keypool empty"); throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet keypool empty");
CBlock *pblock = &pblocktemplate->block; CBlock *pblock = &pblocktemplate->block;
@ -275,8 +290,15 @@ Value setgenerate(const Array& params, bool fHelp)
+ HelpExampleRpc("setgenerate", "true, 1") + HelpExampleRpc("setgenerate", "true, 1")
); );
if (pwalletMain == NULL) if (GetArg("-mineraddress", "").empty()) {
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (disabled)"); #ifdef ENABLE_WALLET
if (!pwalletMain) {
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Wallet disabled and -mineraddress not set");
}
#else
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "zcashd compiled without wallet and -mineraddress not set");
#endif
}
if (Params().MineBlocksOnDemand()) if (Params().MineBlocksOnDemand())
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Use the generate method instead of setgenerate on this network"); throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Use the generate method instead of setgenerate on this network");
@ -294,7 +316,11 @@ Value setgenerate(const Array& params, bool fHelp)
mapArgs["-gen"] = (fGenerate ? "1" : "0"); mapArgs["-gen"] = (fGenerate ? "1" : "0");
mapArgs ["-genproclimit"] = itostr(nGenProcLimit); mapArgs ["-genproclimit"] = itostr(nGenProcLimit);
#ifdef ENABLE_WALLET
GenerateBitcoins(fGenerate, pwalletMain, nGenProcLimit); GenerateBitcoins(fGenerate, pwalletMain, nGenProcLimit);
#else
GenerateBitcoins(fGenerate, nGenProcLimit);
#endif
return Value::null; return Value::null;
} }
@ -343,7 +369,7 @@ Value getmininginfo(const Array& params, bool fHelp)
obj.push_back(Pair("pooledtx", (uint64_t)mempool.size())); obj.push_back(Pair("pooledtx", (uint64_t)mempool.size()));
obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC())); obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC()));
obj.push_back(Pair("chain", Params().NetworkIDString())); obj.push_back(Pair("chain", Params().NetworkIDString()));
#if defined(ENABLE_WALLET) && defined(ENABLE_MINING) #ifdef ENABLE_MINING
obj.push_back(Pair("generate", getgenerate(params, false))); obj.push_back(Pair("generate", getgenerate(params, false)));
#endif #endif
return obj; return obj;
@ -401,7 +427,6 @@ static Value BIP22ValidationResult(const CValidationState& state)
return "valid?"; return "valid?";
} }
#ifdef ENABLE_WALLET
Value getblocktemplate(const Array& params, bool fHelp) Value getblocktemplate(const Array& params, bool fHelp)
{ {
if (fHelp || params.size() > 1) if (fHelp || params.size() > 1)
@ -466,10 +491,15 @@ Value getblocktemplate(const Array& params, bool fHelp)
LOCK(cs_main); LOCK(cs_main);
// Wallet or miner address is required because we support coinbasetxn
if (GetArg("-mineraddress", "").empty()) {
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
// Wallet is required because we support coinbasetxn if (!pwalletMain) {
if (pwalletMain == NULL) { throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Wallet disabled and -mineraddress not set");
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (wallet disabled)"); }
#else
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "zcashd compiled without wallet and -mineraddress not set");
#endif
} }
std::string strMode = "template"; std::string strMode = "template";
@ -599,8 +629,12 @@ Value getblocktemplate(const Array& params, bool fHelp)
delete pblocktemplate; delete pblocktemplate;
pblocktemplate = NULL; pblocktemplate = NULL;
} }
#ifdef ENABLE_WALLET
CReserveKey reservekey(pwalletMain); CReserveKey reservekey(pwalletMain);
pblocktemplate = CreateNewBlockWithKey(reservekey); pblocktemplate = CreateNewBlockWithKey(reservekey);
#else
pblocktemplate = CreateNewBlockWithKey();
#endif
if (!pblocktemplate) if (!pblocktemplate)
throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory");
@ -695,12 +729,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1))); result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1)));
return result; return result;
#else // ENABLE_WALLET
// Wallet is required because we support coinbasetxn
throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Method not found (wallet support not built)");
#endif // !ENABLE_WALLET
} }
#endif
class submitblock_StateCatcher : public CValidationInterface class submitblock_StateCatcher : public CValidationInterface
{ {

View File

@ -313,7 +313,7 @@ static const CRPCCommand vRPCCommands[] =
{ "mining", "submitblock", &submitblock, true }, { "mining", "submitblock", &submitblock, true },
{ "mining", "getblocksubsidy", &getblocksubsidy, true }, { "mining", "getblocksubsidy", &getblocksubsidy, true },
#if defined(ENABLE_WALLET) && defined(ENABLE_MINING) #ifdef ENABLE_MINING
/* Coin generation */ /* Coin generation */
{ "generating", "getgenerate", &getgenerate, true }, { "generating", "getgenerate", &getgenerate, true },
{ "generating", "setgenerate", &setgenerate, true }, { "generating", "setgenerate", &setgenerate, true },

View File

@ -1059,7 +1059,7 @@ public:
} }
void ReturnKey(); void ReturnKey();
bool GetReservedKey(CPubKey &pubkey); virtual bool GetReservedKey(CPubKey &pubkey);
void KeepKey(); void KeepKey();
}; };