6
6
7
7
#include " chainparams.h"
8
8
#include " init.h"
9
- #include " masternode/masternode-sync.h"
10
9
#include " miner.h"
11
10
#include " net.h"
12
11
#include " policy/policy.h"
15
14
#include " pos/rewards.h"
16
15
#include " pos/stakeinput.h"
17
16
#include " script/sign.h"
17
+ #include " script/tokengroup.h"
18
18
#include " tokens/tokengroupmanager.h"
19
19
#include " utilmoneystr.h"
20
20
#include " validation.h"
@@ -30,43 +30,79 @@ std::shared_ptr<CMiningManager> miningManager;
30
30
// Internal miner
31
31
//
32
32
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
+
33
58
void static IONMiner (CWallet * const pwallet)
34
59
{
35
60
LogPrintf (" IONMiner started\n " );
36
61
RenameThread (" ion-miner" );
37
62
63
+ if (!g_connman) {
64
+ throw std::runtime_error (" No connection manager" );
65
+ }
66
+
38
67
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
+ }
42
74
}
43
75
76
+
44
77
const auto & params = Params ().GetConsensus ();
45
78
const bool fRegtest = Params ().NetworkIDString () == CBaseChainParams::REGTEST;
46
- static const int nInnerLoopCount = 0x10000 ;
47
79
bool fPosPowPhase ;
48
80
bool fPosPhase ;
49
81
int nHeight = 0 ;
50
-
51
- { // Don't keep cs_main locked
52
- LOCK (cs_main);
53
- nHeight = chainActive.Height ();
54
- }
55
82
unsigned int nExtraNonce = 0 ;
83
+
56
84
UniValue blockHashes (UniValue::VARR);
57
85
try {
58
86
while (true ) {
59
87
if (Params ().MiningRequiresPeers ()) {
60
88
// Busy-wait for the network to come online so we don't waste time mining
61
89
// on an obsolete chain. In regtest mode we expect to fly solo.
62
90
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 )
65
93
break ;
66
- MilliSleep (1000 );
94
+ MilliSleep (5 * 1000 );
67
95
} while (true );
68
96
}
69
97
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
+
70
106
fPosPowPhase = nHeight + 1 >= params.POSPOWStartHeight ;
71
107
fPosPhase = (nHeight + 1 >= params.POSStartHeight && nHeight + 1 < params.POSPOWStartHeight );
72
108
@@ -77,27 +113,34 @@ void static IONMiner(CWallet * const pwallet)
77
113
continue ;
78
114
} else {
79
115
if (fPosPowPhase ) {
116
+ LOCK2 (cs_main, pwallet->cs_wallet );
117
+
80
118
if (!tokenGroupManager->ElectronTokensCreated ()) {
81
119
LogPrintf (" Error: Mining in hybrid mode, but the Electron token group is not yet created\n " );
82
120
MilliSleep (60 * 1000 );
83
121
continue ;
84
122
}
85
- std::shared_ptr<CReserveScript> coinbase_script;
123
+ CScript coinbase_script;
86
124
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 );
91
134
}
92
- pblocktemplate = BlockAssembler (Params ()).CreateNewBlock (coinbase_script->reserveScript );
135
+
136
+ pblocktemplate = BlockAssembler (Params ()).CreateNewBlock (coinbase_script);
93
137
} 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);
101
144
}
102
145
}
103
146
if (!pblocktemplate.get ()) {
@@ -106,30 +149,72 @@ void static IONMiner(CWallet * const pwallet)
106
149
continue ;
107
150
}
108
151
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 ();
120
158
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 " );
124
166
MilliSleep (1000 );
125
- continue ;
167
+ break ;
126
168
}
127
- ++nHeight;
128
- LogPrintf (" IONMiner:\n " );
129
- LogPrintf (" proof-of-work found \n hash: %s \n target: %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 \n target: %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 ();
130
194
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
+ }
133
218
}
134
219
}
135
220
catch (const boost::thread_interrupted&)
@@ -144,6 +229,14 @@ void static IONMiner(CWallet * const pwallet)
144
229
}
145
230
}
146
231
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
+
147
240
CMiningManager::CMiningManager (const CChainParams& chainparams, CConnman* const connman, CWallet * const pwalletIn) :
148
241
nExtraNonce(0 ),
149
242
fEnableMining(false ), fEnableIONMining(false ), pwallet(pwalletIn), chainParams(chainparams), g_connman(connman),
@@ -157,7 +250,6 @@ bool CMiningManager::GenerateBitcoins(bool fGenerate, int nThreads)
157
250
LOCK2 (cs_main, pwallet->cs_wallet );
158
251
159
252
if (miningManager->fEnableMining ) {
160
- // scheduler.scheduleEvery(boost::bind(&CMiningManager::DoMaintenance, boost::ref(miningManager), boost::ref(*g_connman)), 100);
161
253
static boost::thread_group* minerThreads = NULL ;
162
254
163
255
if (nThreads < 0 )
@@ -166,6 +258,7 @@ bool CMiningManager::GenerateBitcoins(bool fGenerate, int nThreads)
166
258
if (minerThreads != NULL )
167
259
{
168
260
minerThreads->interrupt_all ();
261
+ MilliSleep (600 );
169
262
delete minerThreads;
170
263
minerThreads = NULL ;
171
264
}
@@ -174,7 +267,7 @@ bool CMiningManager::GenerateBitcoins(bool fGenerate, int nThreads)
174
267
return false ;
175
268
176
269
minerThreads = new boost::thread_group ();
177
- for (int i = 0 ; i < nThreads; i++)
270
+ for (unsigned int i = 0 ; i < nThreads; i++)
178
271
minerThreads->create_thread (boost::bind (&IONMiner, boost::ref (pwallet)));
179
272
}
180
273
0 commit comments