Skip to content

Commit a45a63c

Browse files
committed
Update internal miner
- Add inner loop - Give each thread its own coinbase key/script - Various improvements
1 parent aa52529 commit a45a63c

File tree

5 files changed

+154
-61
lines changed

5 files changed

+154
-61
lines changed

src/mining-manager.cpp

+141-48
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
#include "chainparams.h"
88
#include "init.h"
9-
#include "masternode/masternode-sync.h"
109
#include "miner.h"
1110
#include "net.h"
1211
#include "policy/policy.h"
@@ -15,6 +14,7 @@
1514
#include "pos/rewards.h"
1615
#include "pos/stakeinput.h"
1716
#include "script/sign.h"
17+
#include "script/tokengroup.h"
1818
#include "tokens/tokengroupmanager.h"
1919
#include "utilmoneystr.h"
2020
#include "validation.h"
@@ -30,43 +30,79 @@ std::shared_ptr<CMiningManager> miningManager;
3030
// Internal miner
3131
//
3232

33+
//
34+
// ScanHash scans nonces looking for a hash with at least some zero bits.
35+
// The nonce is usually preserved between calls, but periodically or if the
36+
// nonce is 0xffff0000 or above, the block is rebuilt and nNonce starts over at
37+
// zero.
38+
//
39+
40+
bool static ScanHash(const CBlockHeader *pblock, const arith_uint256& hashTarget, uint32_t& nNonce, uint256& phash)
41+
{
42+
// HashX11 currently does not have an intermediary state
43+
// So we revert to doing a full hash calculation and check
44+
CBlockHeader block = *pblock;
45+
while (true) {
46+
nNonce++;
47+
block.nNonce = nNonce;
48+
phash = block.GetHash();
49+
50+
if (UintToArith256(phash) <= hashTarget)
51+
return true;
52+
// If nothing found after trying for a while, return -1
53+
if ((nNonce & 0xfff) == 0)
54+
return false;
55+
}
56+
}
57+
3358
void static IONMiner(CWallet * const pwallet)
3459
{
3560
LogPrintf("IONMiner started\n");
3661
RenameThread("ion-miner");
3762

63+
if (!g_connman) {
64+
throw std::runtime_error("No connection manager");
65+
}
66+
3867
std::shared_ptr<CReserveKey> coinbaseKey;
39-
CPubKey coinbase_pubkey;
40-
if (!pwallet->GetKeyForMining(coinbaseKey, coinbase_pubkey) || !coinbaseKey){
41-
throw std::runtime_error("No coinbase script available (mining requires a wallet)");
68+
CPubKey coinbasePubKey;
69+
{
70+
LOCK(pwallet->cs_wallet);
71+
if (!pwallet->GetKeyForMining(coinbaseKey, coinbasePubKey) || !coinbaseKey){
72+
throw std::runtime_error("No coinbase script available (mining requires a wallet and keys in the keypool)");
73+
}
4274
}
4375

76+
4477
const auto& params = Params().GetConsensus();
4578
const bool fRegtest = Params().NetworkIDString() == CBaseChainParams::REGTEST;
46-
static const int nInnerLoopCount = 0x10000;
4779
bool fPosPowPhase;
4880
bool fPosPhase;
4981
int nHeight = 0;
50-
51-
{ // Don't keep cs_main locked
52-
LOCK(cs_main);
53-
nHeight = chainActive.Height();
54-
}
5582
unsigned int nExtraNonce = 0;
83+
5684
UniValue blockHashes(UniValue::VARR);
5785
try {
5886
while (true) {
5987
if (Params().MiningRequiresPeers()) {
6088
// Busy-wait for the network to come online so we don't waste time mining
6189
// on an obsolete chain. In regtest mode we expect to fly solo.
6290
do {
63-
bool fHaveConnections = !g_connman ? false : g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) > 0;
64-
if (fHaveConnections && !IsInitialBlockDownload())
91+
bool fHaveConnections = g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) > 0;
92+
if (fHaveConnections)
6593
break;
66-
MilliSleep(1000);
94+
MilliSleep(5 * 1000);
6795
} while (true);
6896
}
6997

98+
unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
99+
CBlockIndex* pindexPrev;
100+
{ // Don't keep cs_main locked
101+
LOCK(cs_main);
102+
pindexPrev = chainActive.Tip();
103+
nHeight = chainActive.Height();
104+
}
105+
70106
fPosPowPhase = nHeight + 1 >= params.POSPOWStartHeight;
71107
fPosPhase = (nHeight + 1 >= params.POSStartHeight && nHeight + 1 < params.POSPOWStartHeight);
72108

@@ -77,27 +113,34 @@ void static IONMiner(CWallet * const pwallet)
77113
continue;
78114
} else {
79115
if (fPosPowPhase) {
116+
LOCK2(cs_main, pwallet->cs_wallet);
117+
80118
if (!tokenGroupManager->ElectronTokensCreated()) {
81119
LogPrintf("Error: Mining in hybrid mode, but the Electron token group is not yet created\n");
82120
MilliSleep(60 * 1000);
83121
continue;
84122
}
85-
std::shared_ptr<CReserveScript> coinbase_script;
123+
CScript coinbase_script;
86124
CBlockReward reward(nHeight + 1, 0, false, params);
87-
if (!pwallet->GetScriptForHybridMining(coinbase_script, coinbaseKey, reward.GetCoinbaseReward())) {
88-
LogPrintf("Error: Keypool ran out, need to call keypoolrefill\n");
89-
MilliSleep(60 * 1000);
90-
continue;
125+
CReward coinbaseReward = reward.GetCoinbaseReward();
126+
127+
CTxDestination dst = coinbasePubKey.GetID();
128+
129+
std::map<CTokenGroupID, CAmount>::const_iterator it = coinbaseReward.tokenAmounts.begin();
130+
if (it == coinbaseReward.tokenAmounts.end()) {
131+
coinbase_script = CScript();
132+
} else {
133+
coinbase_script = GetScriptForDestination(dst, it->first, it->second);
91134
}
92-
pblocktemplate = BlockAssembler(Params()).CreateNewBlock(coinbase_script->reserveScript);
135+
136+
pblocktemplate = BlockAssembler(Params()).CreateNewBlock(coinbase_script);
93137
} else {
94-
std::shared_ptr<CReserveScript> coinbase_script;
95-
if (!pwallet->GetScriptForPowMining(coinbase_script, coinbaseKey)) {
96-
LogPrintf("Error: Keypool ran out, need to call keypoolrefill\n");
97-
MilliSleep(60 * 1000);
98-
continue;
99-
}
100-
pblocktemplate = BlockAssembler(Params()).CreateNewBlock(coinbase_script->reserveScript);
138+
LOCK2(cs_main, pwallet->cs_wallet);
139+
140+
CScript coinbase_script;
141+
coinbase_script = CScript() << ToByteVector(coinbasePubKey) << OP_CHECKSIG;
142+
143+
pblocktemplate = BlockAssembler(Params()).CreateNewBlock(coinbase_script);
101144
}
102145
}
103146
if (!pblocktemplate.get()) {
@@ -106,30 +149,72 @@ void static IONMiner(CWallet * const pwallet)
106149
continue;
107150
}
108151
CBlock *pblock = &pblocktemplate->block;
109-
{
110-
LOCK(cs_main);
111-
IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce);
112-
}
113-
while (pblock->nNonce < nInnerLoopCount && !CheckProofOfWork(pblock->GetHash(), pblock->nBits, Params().GetConsensus())) {
114-
boost::this_thread::interruption_point();
115-
++pblock->nNonce;
116-
}
117-
if (pblock->nNonce == nInnerLoopCount) {
118-
continue;
119-
}
152+
miningManager->GetIncrementedExtraNonce(pblock, pindexPrev, nExtraNonce);
153+
154+
//
155+
// Search
156+
//
157+
int64_t nStart = GetTime();
120158

121-
std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(*pblock);
122-
if (!ProcessNewBlock(Params(), shared_pblock, true, nullptr)) {
123-
LogPrintf("ProcessNewBlock, block not accepted\n");
159+
bool fNegative;
160+
bool fOverflow;
161+
arith_uint256 hashTarget;
162+
hashTarget.SetCompact(pblock->nBits, &fNegative, &fOverflow);
163+
// Check range
164+
if (fNegative || hashTarget == 0 || fOverflow || hashTarget > UintToArith256(Params().GetConsensus().powLimit)) {
165+
LogPrintf("%s - Incorrect difficulty\n");
124166
MilliSleep(1000);
125-
continue;
167+
break;
126168
}
127-
++nHeight;
128-
LogPrintf("IONMiner:\n");
129-
LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", pblock->GetHash().GetHex(), pblock->nBits);
169+
170+
uint256 hash;
171+
uint32_t nNonce = 0;
172+
while (true) {
173+
if (ScanHash(pblock, hashTarget, nNonce, hash)) {
174+
// Found a solution
175+
pblock->nNonce = nNonce;
176+
assert(hash == pblock->GetHash());
177+
178+
LogPrintf("IONMiner:\n");
179+
LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", pblock->GetHash().GetHex(), pblock->nBits);
180+
std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(*pblock);
181+
if (!ProcessNewBlock(Params(), shared_pblock, true, nullptr)) {
182+
LogPrintf("ProcessNewBlock, block not accepted\n");
183+
MilliSleep(500);
184+
continue;
185+
}
186+
++nHeight;
187+
//mark script as important because it was used at least for one coinbase output if the script came from the wallet
188+
coinbaseKey->KeepKey();
189+
190+
break;
191+
}
192+
// Check for stop or if block needs to be rebuilt
193+
boost::this_thread::interruption_point();
130194

131-
//mark script as important because it was used at least for one coinbase output if the script came from the wallet
132-
coinbaseKey->KeepKey();
195+
if (nNonce >= 0xffff0000) {
196+
nNonce = 0;
197+
break;
198+
}
199+
if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
200+
break;
201+
{
202+
LOCK(cs_main);
203+
if (pindexPrev != chainActive.Tip())
204+
break;
205+
}
206+
// Update nTime every few seconds
207+
if (UpdateTime(pblock, Params().GetConsensus(), pindexPrev) < 0)
208+
break; // Recreate the block if the clock has run backwards,
209+
// so that we can use the correct time.
210+
if (Params().GetConsensus().fPowAllowMinDifficultyBlocks)
211+
{
212+
// Changing pblock->nTime can change work required on testnet:
213+
hashTarget.SetCompact(pblock->nBits);
214+
}
215+
if (Params().MiningRequiresPeers() && g_connman->GetNodeCount(CConnman::CONNECTIONS_ALL) < 1)
216+
break;
217+
}
133218
}
134219
}
135220
catch (const boost::thread_interrupted&)
@@ -144,6 +229,14 @@ void static IONMiner(CWallet * const pwallet)
144229
}
145230
}
146231

232+
void CMiningManager::GetIncrementedExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nMinerExtraNonce) {
233+
{
234+
LOCK(cs);
235+
IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
236+
nMinerExtraNonce = nExtraNonce;
237+
}
238+
}
239+
147240
CMiningManager::CMiningManager(const CChainParams& chainparams, CConnman* const connman, CWallet * const pwalletIn) :
148241
nExtraNonce(0),
149242
fEnableMining(false), fEnableIONMining(false), pwallet(pwalletIn), chainParams(chainparams), g_connman(connman),
@@ -157,7 +250,6 @@ bool CMiningManager::GenerateBitcoins(bool fGenerate, int nThreads)
157250
LOCK2(cs_main, pwallet->cs_wallet);
158251

159252
if (miningManager->fEnableMining) {
160-
// scheduler.scheduleEvery(boost::bind(&CMiningManager::DoMaintenance, boost::ref(miningManager), boost::ref(*g_connman)), 100);
161253
static boost::thread_group* minerThreads = NULL;
162254

163255
if (nThreads < 0)
@@ -166,6 +258,7 @@ bool CMiningManager::GenerateBitcoins(bool fGenerate, int nThreads)
166258
if (minerThreads != NULL)
167259
{
168260
minerThreads->interrupt_all();
261+
MilliSleep(600);
169262
delete minerThreads;
170263
minerThreads = NULL;
171264
}
@@ -174,7 +267,7 @@ bool CMiningManager::GenerateBitcoins(bool fGenerate, int nThreads)
174267
return false;
175268

176269
minerThreads = new boost::thread_group();
177-
for (int i = 0; i < nThreads; i++)
270+
for (unsigned int i = 0; i < nThreads; i++)
178271
minerThreads->create_thread(boost::bind(&IONMiner, boost::ref(pwallet)));
179272
}
180273

src/mining-manager.h

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include <univalue.h>
1313

14+
class CBlock;
1415
class CBlockIndex;
1516
class CChainParams;
1617
class CConnman;
@@ -43,6 +44,7 @@ class CMiningManager
4344
bool fEnableIONMining;
4445

4546
bool GenerateBitcoins(bool fGenerate, int nThreads);
47+
void GetIncrementedExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nMinerExtraNonce);
4648

4749
void UpdatedBlockTip(const CBlockIndex* pindex);
4850

src/pos/staker.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -67,18 +67,18 @@ UniValue generateHybridBlocks(std::shared_ptr<CReserveKey> coinbaseKey, int nGen
6767
if (!tokenGroupManager->ElectronTokensCreated()) {
6868
throw JSONRPCError(RPC_MISC_ERROR, "Error: Mining in hybrid mode, but the Electron token group is not yet created");
6969
}
70-
std::shared_ptr<CReserveScript> coinbase_script;
70+
CScript coinbase_script;
7171
CBlockReward reward(nHeight + 1, 0, false, params);
7272
if (!pwallet->GetScriptForHybridMining(coinbase_script, coinbaseKey, reward.GetCoinbaseReward())) {
7373
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
7474
}
75-
pblocktemplate = BlockAssembler(Params()).CreateNewBlock(coinbase_script->reserveScript);
75+
pblocktemplate = BlockAssembler(Params()).CreateNewBlock(coinbase_script);
7676
} else {
77-
std::shared_ptr<CReserveScript> coinbase_script;
77+
CScript coinbase_script;
7878
if (!pwallet->GetScriptForPowMining(coinbase_script, coinbaseKey)) {
7979
throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
8080
}
81-
pblocktemplate = BlockAssembler(Params()).CreateNewBlock(coinbase_script->reserveScript);
81+
pblocktemplate = BlockAssembler(Params()).CreateNewBlock(coinbase_script);
8282
}
8383
}
8484
if (!pblocktemplate.get())

src/wallet/wallet.cpp

+5-7
Original file line numberDiff line numberDiff line change
@@ -5122,31 +5122,29 @@ void CWallet::GetScriptForMining(std::shared_ptr<CReserveScript> &script)
51225122
script->reserveScript = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
51235123
}
51245124

5125-
bool CWallet::GetScriptForPowMining(std::shared_ptr<CReserveScript> &script, const std::shared_ptr<CReserveKey> &reservedKey)
5125+
bool CWallet::GetScriptForPowMining(CScript& script, const std::shared_ptr<CReserveKey> &reservedKey)
51265126
{
51275127
CPubKey pubkey;
51285128
if (!reservedKey->GetReservedKey(pubkey, false))
51295129
return false;
51305130

5131-
script = reservedKey;
5132-
script->reserveScript = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
5131+
script = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
51335132
return true;
51345133
}
51355134

5136-
bool CWallet::GetScriptForHybridMining(std::shared_ptr<CReserveScript> &script, const std::shared_ptr<CReserveKey> &reservedKey, const CReward &reward)
5135+
bool CWallet::GetScriptForHybridMining(CScript& script, const std::shared_ptr<CReserveKey> &reservedKey, const CReward &reward)
51375136
{
51385137
CPubKey pubkey;
51395138
if (!reservedKey->GetReservedKey(pubkey, false))
51405139
return false;
51415140

5142-
script = reservedKey;
51435141
CTxDestination dst = pubkey.GetID();
51445142

51455143
std::map<CTokenGroupID, CAmount>::const_iterator it = reward.tokenAmounts.begin();
51465144
if (it == reward.tokenAmounts.end()) {
5147-
script->reserveScript = CScript();
5145+
script = CScript();
51485146
} else {
5149-
script->reserveScript = GetScriptForDestination(dst, it->first, it->second);
5147+
script = GetScriptForDestination(dst, it->first, it->second);
51505148
}
51515149
return true;
51525150
}

src/wallet/wallet.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -1208,8 +1208,8 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
12081208
}
12091209

12101210
void GetScriptForMining(std::shared_ptr<CReserveScript> &script);
1211-
bool GetScriptForPowMining(std::shared_ptr<CReserveScript> &script, const std::shared_ptr<CReserveKey> &reservedKey);
1212-
bool GetScriptForHybridMining(std::shared_ptr<CReserveScript> &script, const std::shared_ptr<CReserveKey> &reservedKey, const CReward &reward);
1211+
bool GetScriptForPowMining(CScript& script, const std::shared_ptr<CReserveKey> &reservedKey);
1212+
bool GetScriptForHybridMining(CScript& script, const std::shared_ptr<CReserveKey> &reservedKey, const CReward &reward);
12131213
bool GetKeyForMining(std::shared_ptr<CReserveKey> &reservedKey, CPubKey &pubkey);
12141214

12151215
unsigned int GetKeyPoolSize()

0 commit comments

Comments
 (0)