]> Git Repo - VerusCoin.git/blob - src/miner.cpp
Merge pull request #35 from miketout/dev
[VerusCoin.git] / src / miner.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6 #include "miner.h"
7 #ifdef ENABLE_MINING
8 #include "pow/tromp/equi_miner.h"
9 #endif
10
11 #include "amount.h"
12 #include "chainparams.h"
13 #include "cc/StakeGuard.h"
14 #include "importcoin.h"
15 #include "consensus/consensus.h"
16 #include "consensus/upgrades.h"
17 #include "consensus/validation.h"
18 #ifdef ENABLE_MINING
19 #include "crypto/equihash.h"
20 #include "crypto/verus_hash.h"
21 #endif
22 #include "hash.h"
23 #include "key_io.h"
24 #include "main.h"
25 #include "metrics.h"
26 #include "net.h"
27 #include "pow.h"
28 #include "primitives/transaction.h"
29 #include "random.h"
30 #include "timedata.h"
31 #include "ui_interface.h"
32 #include "util.h"
33 #include "utilmoneystr.h"
34 #ifdef ENABLE_WALLET
35 #include "wallet/wallet.h"
36 #endif
37
38 #include "zcash/Address.hpp"
39 #include "transaction_builder.h"
40
41 #include "sodium.h"
42
43 #include <boost/thread.hpp>
44 #include <boost/tuple/tuple.hpp>
45 #ifdef ENABLE_MINING
46 #include <functional>
47 #endif
48 #include <mutex>
49
50 using namespace std;
51
52 //////////////////////////////////////////////////////////////////////////////
53 //
54 // BitcoinMiner
55 //
56
57 //
58 // Unconfirmed transactions in the memory pool often depend on other
59 // transactions in the memory pool. When we select transactions from the
60 // pool, we select by highest priority or fee rate, so we might consider
61 // transactions that depend on transactions that aren't yet in the block.
62 // The COrphan class keeps track of these 'temporary orphans' while
63 // CreateBlock is figuring out which transactions to include.
64 //
65 class COrphan
66 {
67 public:
68     const CTransaction* ptx;
69     set<uint256> setDependsOn;
70     CFeeRate feeRate;
71     double dPriority;
72     
73     COrphan(const CTransaction* ptxIn) : ptx(ptxIn), feeRate(0), dPriority(0)
74     {
75     }
76 };
77
78 uint64_t nLastBlockTx = 0;
79 uint64_t nLastBlockSize = 0;
80
81 // We want to sort transactions by priority and fee rate, so:
82 typedef boost::tuple<double, CFeeRate, const CTransaction*> TxPriority;
83 class TxPriorityCompare
84 {
85     bool byFee;
86     
87 public:
88     TxPriorityCompare(bool _byFee) : byFee(_byFee) { }
89     
90     bool operator()(const TxPriority& a, const TxPriority& b)
91     {
92         if (byFee)
93         {
94             if (a.get<1>() == b.get<1>())
95                 return a.get<0>() < b.get<0>();
96             return a.get<1>() < b.get<1>();
97         }
98         else
99         {
100             if (a.get<0>() == b.get<0>())
101                 return a.get<1>() < b.get<1>();
102             return a.get<0>() < b.get<0>();
103         }
104     }
105 };
106
107 void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
108 {
109     pblock->nTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
110
111     // Updating time can change work required on testnet:
112     if (consensusParams.nPowAllowMinDifficultyBlocksAfterHeight != boost::none) {
113         pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams);
114     }
115 }
116
117 #include "komodo_defs.h"
118
119 extern CCriticalSection cs_metrics;
120 extern int32_t KOMODO_MININGTHREADS,KOMODO_LONGESTCHAIN,ASSETCHAINS_SEED,IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAIN_INIT,KOMODO_INITDONE,KOMODO_ON_DEMAND,KOMODO_INITDONE,KOMODO_PASSPORT_INITDONE;
121 extern uint64_t ASSETCHAINS_COMMISSION, ASSETCHAINS_STAKED;
122 extern bool VERUS_MINTBLOCKS;
123 extern uint64_t ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS], ASSETCHAINS_TIMELOCKGTE, ASSETCHAINS_NONCEMASK[];
124 extern const char *ASSETCHAINS_ALGORITHMS[];
125 extern int32_t VERUS_MIN_STAKEAGE, ASSETCHAINS_ALGO, ASSETCHAINS_EQUIHASH, ASSETCHAINS_VERUSHASH, ASSETCHAINS_LASTERA, ASSETCHAINS_LWMAPOS, ASSETCHAINS_NONCESHIFT[], ASSETCHAINS_HASHESPERROUND[];
126 extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
127 extern std::string NOTARY_PUBKEY,ASSETCHAINS_OVERRIDE_PUBKEY;
128 void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len);
129
130 extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33];
131 uint32_t Mining_start,Mining_height;
132 int32_t My_notaryid = -1;
133 int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp);
134 int32_t komodo_pax_opreturn(int32_t height,uint8_t *opret,int32_t maxsize);
135 int32_t komodo_baseid(char *origbase);
136 int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t nTime,int32_t dispflag);
137 int64_t komodo_block_unlocktime(uint32_t nHeight);
138 uint64_t komodo_commission(const CBlock *block);
139 int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig);
140 int32_t verus_staked(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &nBits, arith_uint256 &hashResult, uint8_t *utxosig, CPubKey &pk);
141 int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33);
142
143 CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, bool isStake)
144 {
145     CScript scriptPubKeyIn(_scriptPubKeyIn);
146
147     CPubKey pk = CPubKey();
148     std::vector<std::vector<unsigned char>> vAddrs;
149     txnouttype txT;
150     if (Solver(scriptPubKeyIn, txT, vAddrs))
151     {
152         if (txT == TX_PUBKEY)
153             pk = CPubKey(vAddrs[0]);
154     }
155
156     uint64_t deposits; int32_t isrealtime,kmdheight; uint32_t blocktime; const CChainParams& chainparams = Params();
157     //fprintf(stderr,"create new block\n");
158     // Create new block
159     if ( gpucount < 0 )
160         gpucount = KOMODO_MAXGPUCOUNT;
161     std::unique_ptr<CBlockTemplate> pblocktemplate(new CBlockTemplate());
162     if(!pblocktemplate.get())
163     {
164         fprintf(stderr,"pblocktemplate.get() failure\n");
165         return NULL;
166     }
167     CBlock *pblock = &pblocktemplate->block; // pointer for convenience
168      // -regtest only: allow overriding block.nVersion with
169     // -blockversion=N to test forking scenarios
170     if (Params().MineBlocksOnDemand())
171         pblock->nVersion = GetArg("-blockversion", pblock->nVersion);
172     
173     // Add dummy coinbase tx as first transaction
174     pblock->vtx.push_back(CTransaction());
175     pblocktemplate->vTxFees.push_back(-1); // updated at end
176     pblocktemplate->vTxSigOps.push_back(-1); // updated at end
177     
178     // Largest block you're willing to create:
179     unsigned int nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE);
180     // Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity:
181     nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize));
182     
183     // How much of the block should be dedicated to high-priority transactions,
184     // included regardless of the fees they pay
185     unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", DEFAULT_BLOCK_PRIORITY_SIZE);
186     nBlockPrioritySize = std::min(nBlockMaxSize, nBlockPrioritySize);
187     
188     // Minimum block size you want to create; block will be filled with free transactions
189     // until there are no more or the block reaches this size:
190     unsigned int nBlockMinSize = GetArg("-blockminsize", DEFAULT_BLOCK_MIN_SIZE);
191     nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize);
192     
193     // Collect memory pool transactions into the block
194     CAmount nFees = 0;
195
196     // we will attempt to spend any cheats we see
197     CTransaction cheatTx;
198     boost::optional<CTransaction> cheatSpend;
199     uint256 cbHash;
200
201     CBlockIndex* pindexPrev = 0;
202     {
203         LOCK2(cs_main, mempool.cs);
204         pindexPrev = chainActive.LastTip();
205         const int nHeight = pindexPrev->GetHeight() + 1;
206         const Consensus::Params &consensusParams = chainparams.GetConsensus();
207         uint32_t consensusBranchId = CurrentEpochBranchId(nHeight, consensusParams);
208         bool sapling = NetworkUpgradeActive(nHeight, consensusParams, Consensus::UPGRADE_SAPLING);
209
210         const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast();
211         uint32_t proposedTime = GetAdjustedTime();
212         if (proposedTime == nMedianTimePast)
213         {
214             // too fast or stuck, this addresses the too fast issue, while moving
215             // forward as quickly as possible
216             for (int i; i < 100; i++)
217             {
218                 proposedTime = GetAdjustedTime();
219                 if (proposedTime == nMedianTimePast)
220                     MilliSleep(10);
221             }
222         }
223         pblock->nTime = GetAdjustedTime();
224
225         CCoinsViewCache view(pcoinsTip);
226         uint32_t expired; uint64_t commission;
227         
228         SaplingMerkleTree sapling_tree;
229         assert(view.GetSaplingAnchorAt(view.GetBestAnchor(SAPLING), sapling_tree));
230
231         // Priority order to process transactions
232         list<COrphan> vOrphan; // list memory doesn't move
233         map<uint256, vector<COrphan*> > mapDependers;
234         bool fPrintPriority = GetBoolArg("-printpriority", false);
235         
236         // This vector will be sorted into a priority queue:
237         vector<TxPriority> vecPriority;
238         vecPriority.reserve(mempool.mapTx.size() + 1);
239
240         // check if we should add cheat transaction
241         CBlockIndex *ppast;
242         CTransaction cb;
243         int cheatHeight = nHeight - COINBASE_MATURITY < 1 ? 1 : nHeight - COINBASE_MATURITY;
244         if (cheatCatcher &&
245             sapling && chainActive.Height() > 100 && 
246             (ppast = chainActive[cheatHeight]) && 
247             ppast->IsVerusPOSBlock() && 
248             cheatList.IsHeightOrGreaterInList(cheatHeight))
249         {
250             // get the block and see if there is a cheat candidate for the stake tx
251             CBlock b;
252             if (!(fHavePruned && !(ppast->nStatus & BLOCK_HAVE_DATA) && ppast->nTx > 0) && ReadBlockFromDisk(b, ppast, 1))
253             {
254                 CTransaction &stakeTx = b.vtx[b.vtx.size() - 1];
255
256                 if (cheatList.IsCheatInList(stakeTx, &cheatTx))
257                 {
258                     // make and sign the cheat transaction to spend the coinbase to our address
259                     CMutableTransaction mtx = CreateNewContextualCMutableTransaction(consensusParams, nHeight);
260
261                     uint32_t voutNum;
262                     // get the first vout with value
263                     for (voutNum = 0; voutNum < b.vtx[0].vout.size(); voutNum++)
264                     {
265                         if (b.vtx[0].vout[voutNum].nValue > 0)
266                             break;
267                     }
268
269                     // send to the same pub key as the destination of this block reward
270                     if (MakeCheatEvidence(mtx, b.vtx[0], voutNum, cheatTx))
271                     {
272                         extern CWallet *pwalletMain;
273                         LOCK(pwalletMain->cs_wallet);
274                         TransactionBuilder tb = TransactionBuilder(consensusParams, nHeight);
275                         cb = b.vtx[0];
276                         cbHash = cb.GetHash();
277
278                         bool hasInput = false;
279                         for (uint32_t i = 0; i < cb.vout.size(); i++)
280                         {
281                             // add the spends with the cheat
282                             if (cb.vout[i].nValue > 0)
283                             {
284                                 tb.AddTransparentInput(COutPoint(cbHash,i), cb.vout[0].scriptPubKey, cb.vout[0].nValue);
285                                 hasInput = true;
286                             }
287                         }
288
289                         if (hasInput)
290                         {
291                             // this is a send from a t-address to a sapling address, which we don't have an ovk for. 
292                             // Instead, generate a common one from the HD seed. This ensures the data is
293                             // recoverable, at least for us, while keeping it logically separate from the ZIP 32
294                             // Sapling key hierarchy, which the user might not be using.
295                             uint256 ovk;
296                             HDSeed seed;
297                             if (pwalletMain->GetHDSeed(seed)) {
298                                 ovk = ovkForShieldingFromTaddr(seed);
299
300                                 // send everything to Sapling address
301                                 tb.SendChangeTo(cheatCatcher.value(), ovk);
302
303                                 tb.AddOpRet(mtx.vout[mtx.vout.size() - 1].scriptPubKey);
304
305                                 cheatSpend = tb.Build();
306                             }
307                         }
308                     }
309                 }
310             }
311         }
312
313         if (cheatSpend)
314         {
315             cheatTx = cheatSpend.value();
316             std::list<CTransaction> removed;
317             mempool.removeConflicts(cheatTx, removed);
318             printf("Found cheating stake! Adding cheat spend for %.8f at block #%d, coinbase tx\n%s\n",
319                 (double)cb.GetValueOut() / (double)COIN, nHeight, cheatSpend.value().vin[0].prevout.hash.GetHex().c_str());
320
321             // add to mem pool and relay
322             if (myAddtomempool(cheatTx))
323             {
324                 RelayTransaction(cheatTx);
325             }
326         }
327
328         // now add transactions from the mem pool
329         for (CTxMemPool::indexed_transaction_set::iterator mi = mempool.mapTx.begin();
330              mi != mempool.mapTx.end(); ++mi)
331         {
332             const CTransaction& tx = mi->GetTx();
333             
334             int64_t nLockTimeCutoff = (STANDARD_LOCKTIME_VERIFY_FLAGS & LOCKTIME_MEDIAN_TIME_PAST)
335             ? nMedianTimePast
336             : pblock->GetBlockTime();
337
338             if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight, nLockTimeCutoff) || IsExpiredTx(tx, nHeight))
339             {
340                 //fprintf(stderr,"coinbase.%d finaltx.%d expired.%d\n",tx.IsCoinBase(),IsFinalTx(tx, nHeight, nLockTimeCutoff),IsExpiredTx(tx, nHeight));
341                 continue;
342             }
343
344             if ( ASSETCHAINS_SYMBOL[0] == 0 && komodo_validate_interest(tx,nHeight,(uint32_t)pblock->nTime,0) < 0 )
345             {
346                 //fprintf(stderr,"CreateNewBlock: komodo_validate_interest failure nHeight.%d nTime.%u vs locktime.%u\n",nHeight,(uint32_t)pblock->nTime,(uint32_t)tx.nLockTime);
347                 continue;
348             }
349
350             COrphan* porphan = NULL;
351             double dPriority = 0;
352             CAmount nTotalIn = 0;
353             bool fMissingInputs = false;
354             if (tx.IsCoinImport())
355             {
356                 CAmount nValueIn = GetCoinImportValue(tx);
357                 nTotalIn += nValueIn;
358                 dPriority += (double)nValueIn * 1000;  // flat multiplier
359             } else {
360                 BOOST_FOREACH(const CTxIn& txin, tx.vin)
361                 {
362                     // Read prev transaction
363                     if (!view.HaveCoins(txin.prevout.hash))
364                     {
365                         // This should never happen; all transactions in the memory
366                         // pool should connect to either transactions in the chain
367                         // or other transactions in the memory pool.
368                         if (!mempool.mapTx.count(txin.prevout.hash))
369                         {
370                             LogPrintf("ERROR: mempool transaction missing input\n");
371                             if (fDebug) assert("mempool transaction missing input" == 0);
372                             fMissingInputs = true;
373                             if (porphan)
374                                 vOrphan.pop_back();
375                             break;
376                         }
377
378                         // Has to wait for dependencies
379                         if (!porphan)
380                         {
381                             // Use list for automatic deletion
382                             vOrphan.push_back(COrphan(&tx));
383                             porphan = &vOrphan.back();
384                         }
385                         mapDependers[txin.prevout.hash].push_back(porphan);
386                         porphan->setDependsOn.insert(txin.prevout.hash);
387                         nTotalIn += mempool.mapTx.find(txin.prevout.hash)->GetTx().vout[txin.prevout.n].nValue;
388                         continue;
389                     }
390                     const CCoins* coins = view.AccessCoins(txin.prevout.hash);
391                     assert(coins);
392
393                     CAmount nValueIn = coins->vout[txin.prevout.n].nValue;
394                     nTotalIn += nValueIn;
395
396                     int nConf = nHeight - coins->nHeight;
397
398                     dPriority += (double)nValueIn * nConf;
399                 }
400                 nTotalIn += tx.GetShieldedValueIn();
401             }
402
403             if (fMissingInputs) continue;
404             
405             // Priority is sum(valuein * age) / modified_txsize
406             unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
407             dPriority = tx.ComputePriority(dPriority, nTxSize);
408             
409             uint256 hash = tx.GetHash();
410             mempool.ApplyDeltas(hash, dPriority, nTotalIn);
411             
412             CFeeRate feeRate(nTotalIn-tx.GetValueOut(), nTxSize);
413             
414             if (porphan)
415             {
416                 porphan->dPriority = dPriority;
417                 porphan->feeRate = feeRate;
418             }
419             else
420                 vecPriority.push_back(TxPriority(dPriority, feeRate, &(mi->GetTx())));
421         }
422
423         // Collect transactions into block
424         uint64_t nBlockSize = 1000;
425         uint64_t nBlockTx = 0;
426         int64_t interest;
427         int nBlockSigOps = 100;
428         bool fSortedByFee = (nBlockPrioritySize <= 0);
429         
430         TxPriorityCompare comparer(fSortedByFee);
431         std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
432         
433         while (!vecPriority.empty())
434         {
435             // Take highest priority transaction off the priority queue:
436             double dPriority = vecPriority.front().get<0>();
437             CFeeRate feeRate = vecPriority.front().get<1>();
438             const CTransaction& tx = *(vecPriority.front().get<2>());
439             
440             std::pop_heap(vecPriority.begin(), vecPriority.end(), comparer);
441             vecPriority.pop_back();
442             
443             // Size limits
444             unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
445             if (nBlockSize + nTxSize >= nBlockMaxSize-512) // room for extra autotx
446             {
447                 //fprintf(stderr,"nBlockSize %d + %d nTxSize >= %d nBlockMaxSize\n",(int32_t)nBlockSize,(int32_t)nTxSize,(int32_t)nBlockMaxSize);
448                 continue;
449             }
450             
451             // Legacy limits on sigOps:
452             unsigned int nTxSigOps = GetLegacySigOpCount(tx);
453             if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS-1)
454             {
455                 //fprintf(stderr,"A nBlockSigOps %d + %d nTxSigOps >= %d MAX_BLOCK_SIGOPS-1\n",(int32_t)nBlockSigOps,(int32_t)nTxSigOps,(int32_t)MAX_BLOCK_SIGOPS);
456                 continue;
457             }
458             // Skip free transactions if we're past the minimum block size:
459             const uint256& hash = tx.GetHash();
460             double dPriorityDelta = 0;
461             CAmount nFeeDelta = 0;
462             mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta);
463             if (fSortedByFee && (dPriorityDelta <= 0) && (nFeeDelta <= 0) && (feeRate < ::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize))
464             {
465                 //fprintf(stderr,"fee rate skip\n");
466                 continue;
467             }
468             // Prioritise by fee once past the priority size or we run out of high-priority
469             // transactions:
470             if (!fSortedByFee &&
471                 ((nBlockSize + nTxSize >= nBlockPrioritySize) || !AllowFree(dPriority)))
472             {
473                 fSortedByFee = true;
474                 comparer = TxPriorityCompare(fSortedByFee);
475                 std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
476             }
477             
478             if (!view.HaveInputs(tx))
479             {
480                 //fprintf(stderr,"dont have inputs\n");
481                 continue;
482             }
483             CAmount nTxFees = view.GetValueIn(chainActive.LastTip()->GetHeight(),&interest,tx,chainActive.LastTip()->nTime)-tx.GetValueOut();
484             
485             nTxSigOps += GetP2SHSigOpCount(tx, view);
486             if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS-1)
487             {
488                 //fprintf(stderr,"B nBlockSigOps %d + %d nTxSigOps >= %d MAX_BLOCK_SIGOPS-1\n",(int32_t)nBlockSigOps,(int32_t)nTxSigOps,(int32_t)MAX_BLOCK_SIGOPS);
489                 continue;
490             }
491             // Note that flags: we don't want to set mempool/IsStandard()
492             // policy here, but we still have to ensure that the block we
493             // create only contains transactions that are valid in new blocks.
494             CValidationState state;
495             PrecomputedTransactionData txdata(tx);
496             if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId))
497             {
498                 //fprintf(stderr,"context failure\n");
499                 continue;
500             }
501             UpdateCoins(tx, view, nHeight);
502
503             BOOST_FOREACH(const OutputDescription &outDescription, tx.vShieldedOutput) {
504                 sapling_tree.append(outDescription.cm);
505             }
506
507             // Added
508             pblock->vtx.push_back(tx);
509             pblocktemplate->vTxFees.push_back(nTxFees);
510             pblocktemplate->vTxSigOps.push_back(nTxSigOps);
511             nBlockSize += nTxSize;
512             ++nBlockTx;
513             nBlockSigOps += nTxSigOps;
514             nFees += nTxFees;
515             
516             if (fPrintPriority)
517             {
518                 LogPrintf("priority %.1f fee %s txid %s\n",dPriority, feeRate.ToString(), tx.GetHash().ToString());
519             }
520             
521             // Add transactions that depend on this one to the priority queue
522             if (mapDependers.count(hash))
523             {
524                 BOOST_FOREACH(COrphan* porphan, mapDependers[hash])
525                 {
526                     if (!porphan->setDependsOn.empty())
527                     {
528                         porphan->setDependsOn.erase(hash);
529                         if (porphan->setDependsOn.empty())
530                         {
531                             vecPriority.push_back(TxPriority(porphan->dPriority, porphan->feeRate, porphan->ptx));
532                             std::push_heap(vecPriority.begin(), vecPriority.end(), comparer);
533                         }
534                     }
535                 }
536             }
537         }
538         
539         nLastBlockTx = nBlockTx;
540         nLastBlockSize = nBlockSize;
541         blocktime = 1 + std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
542         //pblock->nTime = blocktime + 1;
543         pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus());
544
545         int32_t stakeHeight = chainActive.Height() + 1;
546
547         //LogPrintf("CreateNewBlock(): total size %u blocktime.%u nBits.%08x\n", nBlockSize,blocktime,pblock->nBits);
548         if ( ASSETCHAINS_SYMBOL[0] != 0 && isStake )
549         {
550             uint64_t txfees,utxovalue; uint32_t txtime; uint256 utxotxid; int32_t i,siglen,numsigs,utxovout; uint8_t utxosig[128],*ptr;
551             CMutableTransaction txStaked = CreateNewContextualCMutableTransaction(Params().GetConsensus(), stakeHeight);
552
553             //if ( blocktime > pindexPrev->GetMedianTimePast()+60 )
554             //    blocktime = pindexPrev->GetMedianTimePast() + 60;
555             if (ASSETCHAINS_LWMAPOS != 0)
556             {
557                 uint32_t nBitsPOS;
558                 arith_uint256 posHash;
559
560                 siglen = verus_staked(pblock, txStaked, nBitsPOS, posHash, utxosig, pk);
561                 blocktime = GetAdjustedTime();
562
563                 // change the scriptPubKeyIn to the same output script exactly as the staking transaction
564                 if (siglen > 0)
565                     scriptPubKeyIn = CScript(txStaked.vout[0].scriptPubKey);
566             }
567             else
568             {
569                 siglen = komodo_staked(txStaked, pblock->nBits, &blocktime, &txtime, &utxotxid, &utxovout, &utxovalue, utxosig);
570             }
571
572             if ( siglen > 0 )
573             {
574                 CAmount txfees;
575
576                 // after Sapling, stake transactions have a fee, but it is recovered in the reward
577                 // this ensures that a rebroadcast goes through quickly to begin staking again
578                 txfees = sapling ? DEFAULT_STAKE_TXFEE : 0;
579
580                 pblock->vtx.push_back(txStaked);
581                 pblocktemplate->vTxFees.push_back(txfees);
582                 pblocktemplate->vTxSigOps.push_back(GetLegacySigOpCount(txStaked));
583                 nFees += txfees;
584                 pblock->nTime = blocktime;
585                 //printf("staking PoS ht.%d t%u lag.%u\n",(int32_t)chainActive.LastTip()->GetHeight()+1,blocktime,(uint32_t)(GetAdjustedTime() - (blocktime-13)));
586             } else return(0); //fprintf(stderr,"no utxos eligible for staking\n");
587         }
588         
589         // Create coinbase tx
590         CMutableTransaction txNew = CreateNewContextualCMutableTransaction(consensusParams, nHeight);
591         txNew.vin.resize(1);
592         txNew.vin[0].prevout.SetNull();
593         txNew.vin[0].scriptSig = CScript() << nHeight << OP_0;
594
595         txNew.vout.resize(1);
596         txNew.vout[0].scriptPubKey = scriptPubKeyIn;
597         txNew.vout[0].nValue = GetBlockSubsidy(nHeight,consensusParams) + nFees;
598
599         // once we get to Sapling, enable CC StakeGuard for stake transactions
600         if (isStake && sapling)
601         {
602             // if there is a specific destination, use it
603             CTransaction stakeTx = pblock->vtx[pblock->vtx.size() - 1];
604             CStakeParams p;
605             if (ValidateStakeTransaction(stakeTx, p, false))
606             {
607                 if (!p.pk.IsValid() || !MakeGuardedOutput(txNew.vout[0].nValue, p.pk, stakeTx, txNew.vout[0]))
608                 {
609                     fprintf(stderr,"CreateNewBlock: failed to make GuardedOutput on staking coinbase\n");
610                     return 0;
611                 }
612             }
613             else
614             {
615                 fprintf(stderr,"CreateNewBlock: invalid stake transaction\n");
616                 return 0;
617             }
618         }
619
620         txNew.nExpiryHeight = 0;
621         txNew.nLockTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
622
623         if ( ASSETCHAINS_SYMBOL[0] == 0 && IS_KOMODO_NOTARY != 0 && My_notaryid >= 0 )
624             txNew.vout[0].nValue += 5000;
625
626         // check if coinbase transactions must be time locked at current subsidy and prepend the time lock
627         // to transaction if so, cast for GTE operator
628         if ((uint64_t)(txNew.vout[0].nValue) >= ASSETCHAINS_TIMELOCKGTE)
629         {
630             int32_t opretlen, p2shlen, scriptlen;
631             CScriptExt opretScript = CScriptExt();
632
633             txNew.vout.resize(2);
634
635             // prepend time lock to original script unless original script is P2SH, in which case, we will leave the coins
636             // protected only by the time lock rather than 100% inaccessible
637             opretScript.AddCheckLockTimeVerify(komodo_block_unlocktime(nHeight));
638             if (scriptPubKeyIn.IsPayToScriptHash() || scriptPubKeyIn.IsPayToCryptoCondition())
639             {
640                 fprintf(stderr,"CreateNewBlock: attempt to add timelock to pay2sh or pay2cc\n");
641                 return 0;
642             }
643             
644             opretScript += scriptPubKeyIn;
645
646             txNew.vout[0].scriptPubKey = CScriptExt().PayToScriptHash(CScriptID(opretScript));
647             txNew.vout[1].scriptPubKey = CScriptExt().OpReturnScript(opretScript, OPRETTYPE_TIMELOCK);
648             txNew.vout[1].nValue = 0;
649         } // timelocks and commissions are currently incompatible due to validation complexity of the combination
650         else if ( nHeight > 1 && ASSETCHAINS_SYMBOL[0] != 0 && ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 && ASSETCHAINS_COMMISSION != 0 && (commission= komodo_commission((CBlock*)&pblocktemplate->block)) != 0 )
651         {
652             int32_t i; uint8_t *ptr;
653             txNew.vout.resize(2);
654             txNew.vout[1].nValue = commission;
655             txNew.vout[1].scriptPubKey.resize(35);
656             ptr = (uint8_t *)&txNew.vout[1].scriptPubKey[0];
657             ptr[0] = 33;
658             for (i=0; i<33; i++)
659                 ptr[i+1] = ASSETCHAINS_OVERRIDE_PUBKEY33[i];
660             ptr[34] = OP_CHECKSIG;
661             //printf("autocreate commision vout\n");
662         }
663
664         pblock->vtx[0] = txNew;
665         pblocktemplate->vTxFees[0] = -nFees;
666
667         // if not Verus stake, setup nonce, otherwise, leave it alone
668         if (!isStake || ASSETCHAINS_LWMAPOS == 0)
669         {
670             // Randomise nonce
671             arith_uint256 nonce = UintToArith256(GetRandHash());
672
673             // Clear the top 16 and bottom 16 or 24 bits (for local use as thread flags and counters)
674             nonce <<= ASSETCHAINS_NONCESHIFT[ASSETCHAINS_ALGO];
675             nonce >>= 16;
676             pblock->nNonce = ArithToUint256(nonce);
677         }
678         
679         // Fill in header
680         pblock->hashPrevBlock  = pindexPrev->GetBlockHash();
681         pblock->hashFinalSaplingRoot   = sapling_tree.root();
682
683         // all Verus PoS chains need this data in the block at all times
684         if ( ASSETCHAINS_LWMAPOS || ASSETCHAINS_SYMBOL[0] == 0 || ASSETCHAINS_STAKED == 0 || KOMODO_MININGTHREADS > 0 )
685         {
686             UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
687             pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus());
688         }
689         pblock->nSolution.clear();
690         pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
691         if ( ASSETCHAINS_SYMBOL[0] == 0 && IS_KOMODO_NOTARY != 0 && My_notaryid >= 0 )
692         {
693             uint32_t r;
694             CMutableTransaction txNotary = CreateNewContextualCMutableTransaction(Params().GetConsensus(), chainActive.Height() + 1);
695             if ( pblock->nTime < pindexPrev->nTime+60 )
696                 pblock->nTime = pindexPrev->nTime + 60;
697             if ( gpucount < 33 )
698             {
699                 uint8_t tmpbuffer[40]; uint32_t r; int32_t n=0; uint256 randvals;
700                 memcpy(&tmpbuffer[n],&My_notaryid,sizeof(My_notaryid)), n += sizeof(My_notaryid);
701                 memcpy(&tmpbuffer[n],&Mining_height,sizeof(Mining_height)), n += sizeof(Mining_height);
702                 memcpy(&tmpbuffer[n],&pblock->hashPrevBlock,sizeof(pblock->hashPrevBlock)), n += sizeof(pblock->hashPrevBlock);
703                 vcalc_sha256(0,(uint8_t *)&randvals,tmpbuffer,n);
704                 memcpy(&r,&randvals,sizeof(r));
705                 pblock->nTime += (r % (33 - gpucount)*(33 - gpucount));
706             }
707             if ( komodo_notaryvin(txNotary,NOTARY_PUBKEY33) > 0 )
708             {
709                 CAmount txfees = 5000;
710                 pblock->vtx.push_back(txNotary);
711                 pblocktemplate->vTxFees.push_back(txfees);
712                 pblocktemplate->vTxSigOps.push_back(GetLegacySigOpCount(txNotary));
713                 nFees += txfees;
714                 pblocktemplate->vTxFees[0] = -nFees;
715                 //*(uint64_t *)(&pblock->vtx[0].vout[0].nValue) += txfees;
716                 //fprintf(stderr,"added notaryvin\n");
717             }
718             else
719             {
720                 fprintf(stderr,"error adding notaryvin, need to create 0.0001 utxos\n");
721                 return(0);
722             }
723         }
724         else if ( ASSETCHAINS_CC == 0 && pindexPrev != 0 && ASSETCHAINS_STAKED == 0 && (ASSETCHAINS_SYMBOL[0] != 0 || IS_KOMODO_NOTARY == 0 || My_notaryid < 0) )
725         {
726             CValidationState state;
727             //fprintf(stderr,"check validity\n");
728             if ( !TestBlockValidity(state, *pblock, pindexPrev, false, false)) // invokes CC checks
729             {
730                 throw std::runtime_error("CreateNewBlock(): TestBlockValidity failed");
731             }
732             //fprintf(stderr,"valid\n");
733         }
734     }
735     //fprintf(stderr,"done new block\n");
736     return pblocktemplate.release();
737 }
738  
739 /*
740  #ifdef ENABLE_WALLET
741  boost::optional<CScript> GetMinerScriptPubKey(CReserveKey& reservekey)
742  #else
743  boost::optional<CScript> GetMinerScriptPubKey()
744  #endif
745  {
746  CKeyID keyID;
747  CBitcoinAddress addr;
748  if (addr.SetString(GetArg("-mineraddress", ""))) {
749  addr.GetKeyID(keyID);
750  } else {
751  #ifdef ENABLE_WALLET
752  CPubKey pubkey;
753  if (!reservekey.GetReservedKey(pubkey)) {
754  return boost::optional<CScript>();
755  }
756  keyID = pubkey.GetID();
757  #else
758  return boost::optional<CScript>();
759  #endif
760  }
761  
762  CScript scriptPubKey = CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
763  return scriptPubKey;
764  }
765  
766  #ifdef ENABLE_WALLET
767  CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey)
768  {
769  boost::optional<CScript> scriptPubKey = GetMinerScriptPubKey(reservekey);
770  #else
771  CBlockTemplate* CreateNewBlockWithKey()
772  {
773  boost::optional<CScript> scriptPubKey = GetMinerScriptPubKey();
774  #endif
775  
776  if (!scriptPubKey) {
777  return NULL;
778  }
779  return CreateNewBlock(*scriptPubKey);
780  }*/
781
782 //////////////////////////////////////////////////////////////////////////////
783 //
784 // Internal miner
785 //
786
787 #ifdef ENABLE_MINING
788
789 void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce)
790 {
791     // Update nExtraNonce
792     static uint256 hashPrevBlock;
793     if (hashPrevBlock != pblock->hashPrevBlock)
794     {
795         nExtraNonce = 0;
796         hashPrevBlock = pblock->hashPrevBlock;
797     }
798     ++nExtraNonce;
799     unsigned int nHeight = pindexPrev->GetHeight()+1; // Height first in coinbase required for block.version=2
800     CMutableTransaction txCoinbase(pblock->vtx[0]);
801     txCoinbase.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
802     assert(txCoinbase.vin[0].scriptSig.size() <= 100);
803     
804     pblock->vtx[0] = txCoinbase;
805     pblock->hashMerkleRoot = pblock->BuildMerkleTree();
806 }
807
808 #ifdef ENABLE_WALLET
809 //////////////////////////////////////////////////////////////////////////////
810 //
811 // Internal miner
812 //
813
814 CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, int32_t gpucount, bool isStake)
815 {
816     CPubKey pubkey; CScript scriptPubKey; uint8_t *ptr; int32_t i;
817     if ( nHeight == 1 && ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 )
818     {
819         scriptPubKey = CScript() << ParseHex(ASSETCHAINS_OVERRIDE_PUBKEY) << OP_CHECKSIG;
820     }
821     else if ( USE_EXTERNAL_PUBKEY != 0 )
822     {
823         //fprintf(stderr,"use notary pubkey\n");
824         scriptPubKey = CScript() << ParseHex(NOTARY_PUBKEY) << OP_CHECKSIG;
825     }
826     else
827     {
828         if (!reservekey.GetReservedKey(pubkey))
829         {
830             return NULL;
831         }
832         scriptPubKey.resize(35);
833         ptr = (uint8_t *)pubkey.begin();
834         scriptPubKey[0] = 33;
835         for (i=0; i<33; i++)
836             scriptPubKey[i+1] = ptr[i];
837         scriptPubKey[34] = OP_CHECKSIG;
838         //scriptPubKey = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
839     }
840     return CreateNewBlock(scriptPubKey, gpucount, isStake);
841 }
842
843 void komodo_broadcast(CBlock *pblock,int32_t limit)
844 {
845     int32_t n = 1;
846     //fprintf(stderr,"broadcast new block t.%u\n",(uint32_t)time(NULL));
847     {
848         LOCK(cs_vNodes);
849         BOOST_FOREACH(CNode* pnode, vNodes)
850         {
851             if ( pnode->hSocket == INVALID_SOCKET )
852                 continue;
853             if ( (rand() % n) == 0 )
854             {
855                 pnode->PushMessage("block", *pblock);
856                 if ( n++ > limit )
857                     break;
858             }
859         }
860     }
861     //fprintf(stderr,"finished broadcast new block t.%u\n",(uint32_t)time(NULL));
862 }
863
864 static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
865 #else
866 static bool ProcessBlockFound(CBlock* pblock)
867 #endif // ENABLE_WALLET
868 {
869     LogPrintf("%s\n", pblock->ToString());
870     LogPrintf("generated %s height.%d\n", FormatMoney(pblock->vtx[0].vout[0].nValue),chainActive.LastTip()->GetHeight()+1);
871     
872     // Found a solution
873     {
874         if (pblock->hashPrevBlock != chainActive.LastTip()->GetBlockHash())
875         {
876             uint256 hash; int32_t i;
877             hash = pblock->hashPrevBlock;
878             for (i=31; i>=0; i--)
879                 fprintf(stderr,"%02x",((uint8_t *)&hash)[i]);
880             fprintf(stderr," <- prev (stale)\n");
881             hash = chainActive.LastTip()->GetBlockHash();
882             for (i=31; i>=0; i--)
883                 fprintf(stderr,"%02x",((uint8_t *)&hash)[i]);
884             fprintf(stderr," <- chainTip (stale)\n");
885             
886             return error("KomodoMiner: generated block is stale");
887         }
888     }
889     
890 #ifdef ENABLE_WALLET
891     // Remove key from key pool
892     if ( IS_KOMODO_NOTARY == 0 )
893     {
894         if (GetArg("-mineraddress", "").empty()) {
895             // Remove key from key pool
896             reservekey.KeepKey();
897         }
898     }
899     // Track how many getdata requests this block gets
900     //if ( 0 )
901     {
902         //fprintf(stderr,"lock cs_wallet\n");
903         LOCK(wallet.cs_wallet);
904         wallet.mapRequestCount[pblock->GetHash()] = 0;
905     }
906 #endif
907     //fprintf(stderr,"process new block\n");
908
909     // Process this block the same as if we had received it from another node
910     CValidationState state;
911     if (!ProcessNewBlock(1,chainActive.LastTip()->GetHeight()+1,state, NULL, pblock, true, NULL))
912         return error("KomodoMiner: ProcessNewBlock, block not accepted");
913     
914     TrackMinedBlock(pblock->GetHash());
915     komodo_broadcast(pblock,16);
916     return true;
917 }
918
919 int32_t komodo_baseid(char *origbase);
920 int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t *blocktimes,int32_t *nonzpkeysp,int32_t height);
921 arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc);
922 int32_t FOUND_BLOCK,KOMODO_MAYBEMINED;
923 extern int32_t KOMODO_LASTMINED,KOMODO_INSYNC;
924 int32_t roundrobin_delay;
925 arith_uint256 HASHTarget,HASHTarget_POW;
926
927 // wait for peers to connect
928 int32_t waitForPeers(const CChainParams &chainparams)
929 {
930     if (chainparams.MiningRequiresPeers())
931     {
932         bool fvNodesEmpty;
933         {
934             boost::this_thread::interruption_point();
935             LOCK(cs_vNodes);
936             fvNodesEmpty = vNodes.empty();
937         }
938         if (fvNodesEmpty || IsNotInSync())
939         {
940             int loops = 0, blockDiff = 0, newDiff = 0;
941             
942             do {
943                 if (fvNodesEmpty)
944                 {
945                     MilliSleep(1000 + rand() % 4000);
946                     boost::this_thread::interruption_point();
947                     LOCK(cs_vNodes);
948                     fvNodesEmpty = vNodes.empty();
949                     loops = 0;
950                     blockDiff = 0;
951                 }
952                 if ((newDiff = IsNotInSync()) > 1)
953                 {
954                     if (blockDiff != newDiff)
955                     {
956                         blockDiff = newDiff;
957                     }
958                     else
959                     {
960                         if (++loops <= 10)
961                         {
962                             MilliSleep(1000);
963                         }
964                         else break;
965                     }
966                 }
967             } while (fvNodesEmpty || IsNotInSync());
968             MilliSleep(100 + rand() % 400);
969         }
970     }
971 }
972
973 #ifdef ENABLE_WALLET
974 CBlockIndex *get_chainactive(int32_t height)
975 {
976     if ( chainActive.LastTip() != 0 )
977     {
978         if ( height <= chainActive.LastTip()->GetHeight() )
979         {
980             LOCK(cs_main);
981             return(chainActive[height]);
982         }
983         // else fprintf(stderr,"get_chainactive height %d > active.%d\n",height,chainActive.Tip()->GetHeight());
984     }
985     //fprintf(stderr,"get_chainactive null chainActive.Tip() height %d\n",height);
986     return(0);
987 }
988
989 /*
990  * A separate thread to stake, while the miner threads mine.
991  */
992 void static VerusStaker(CWallet *pwallet)
993 {
994     LogPrintf("Verus staker thread started\n");
995     RenameThread("verus-staker");
996
997     const CChainParams& chainparams = Params();
998     auto consensusParams = chainparams.GetConsensus();
999
1000     // Each thread has its own key
1001     CReserveKey reservekey(pwallet);
1002
1003     // Each thread has its own counter
1004     unsigned int nExtraNonce = 0;
1005     std::vector<unsigned char> solnPlaceholder = std::vector<unsigned char>();
1006     solnPlaceholder.resize(Eh200_9.SolutionWidth);
1007     uint8_t *script; uint64_t total,checktoshis; int32_t i,j;
1008
1009     while ( (ASSETCHAIN_INIT == 0 || KOMODO_INITDONE == 0) ) //chainActive.Tip()->GetHeight() != 235300 &&
1010     {
1011         sleep(1);
1012         if ( komodo_baseid(ASSETCHAINS_SYMBOL) < 0 )
1013             break;
1014     }
1015
1016     // try a nice clean peer connection to start
1017     CBlockIndex *pindexPrev, *pindexCur;
1018     do {
1019         pindexPrev = chainActive.LastTip();
1020         MilliSleep(5000 + rand() % 5000);
1021         waitForPeers(chainparams);
1022         pindexCur = chainActive.LastTip();
1023     } while (pindexPrev != pindexCur);
1024
1025     try {
1026         while (true)
1027         {
1028             waitForPeers(chainparams);
1029             CBlockIndex* pindexPrev = chainActive.LastTip();
1030             printf("Staking height %d for %s\n", pindexPrev->GetHeight() + 1, ASSETCHAINS_SYMBOL);
1031
1032             // Create new block
1033             unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
1034             if ( Mining_height != pindexPrev->GetHeight()+1 )
1035             {
1036                 Mining_height = pindexPrev->GetHeight()+1;
1037                 Mining_start = (uint32_t)time(NULL);
1038             }
1039
1040             // Check for stop or if block needs to be rebuilt
1041             boost::this_thread::interruption_point();
1042
1043             // try to stake a block
1044             CBlockTemplate *ptr = NULL;
1045             if (Mining_height > VERUS_MIN_STAKEAGE)
1046                 ptr = CreateNewBlockWithKey(reservekey, Mining_height, 0, true);
1047
1048             if ( ptr == 0 )
1049             {
1050                 // wait to try another staking block until after the tip moves again
1051                 while ( chainActive.LastTip() == pindexPrev )
1052                     sleep(1);
1053                 continue;
1054             }
1055
1056             unique_ptr<CBlockTemplate> pblocktemplate(ptr);
1057             if (!pblocktemplate.get())
1058             {
1059                 if (GetArg("-mineraddress", "").empty()) {
1060                     LogPrintf("Error in %s staker: Keypool ran out, please call keypoolrefill before restarting the mining thread\n",
1061                               ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
1062                 } else {
1063                     // Should never reach here, because -mineraddress validity is checked in init.cpp
1064                     LogPrintf("Error in %s staker: Invalid %s -mineraddress\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO], ASSETCHAINS_SYMBOL);
1065                 }
1066                 return;
1067             }
1068
1069             CBlock *pblock = &pblocktemplate->block;
1070             LogPrintf("Staking with %u transactions in block (%u bytes)\n", pblock->vtx.size(),::GetSerializeSize(*pblock,SER_NETWORK,PROTOCOL_VERSION));
1071             //
1072             // Search
1073             //
1074             int64_t nStart = GetTime();
1075
1076             // take up the necessary space for alignment
1077             pblock->nSolution = solnPlaceholder;
1078
1079             // we don't use this, but IncrementExtraNonce is the function that builds the merkle tree
1080             unsigned int nExtraNonce = 0;
1081             IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1082
1083             if (vNodes.empty() && chainparams.MiningRequiresPeers())
1084             {
1085                 if ( Mining_height > ASSETCHAINS_MINHEIGHT )
1086                 {
1087                     fprintf(stderr,"no nodes, attempting reconnect\n");
1088                     continue;
1089                 }
1090             }
1091
1092             if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
1093             {
1094                 fprintf(stderr,"timeout, retrying\n");
1095                 continue;
1096             }
1097
1098             if ( pindexPrev != chainActive.LastTip() )
1099             {
1100                 printf("Block %d added to chain\n", chainActive.LastTip()->GetHeight());
1101                 MilliSleep(250);
1102                 continue;
1103             }
1104
1105             int32_t unlockTime = komodo_block_unlocktime(Mining_height);
1106             int64_t subsidy = (int64_t)(pblock->vtx[0].vout[0].nValue);
1107
1108             uint256 hashTarget = ArithToUint256(arith_uint256().SetCompact(pblock->nBits));
1109
1110             pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams);
1111
1112             UpdateTime(pblock, consensusParams, pindexPrev);
1113
1114             ProcessBlockFound(pblock, *pwallet, reservekey);
1115
1116             LogPrintf("Using %s algorithm:\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
1117             LogPrintf("Staked block found  \n  hash: %s  \ntarget: %s\n", pblock->GetHash().GetHex(), hashTarget.GetHex());
1118             printf("Found block %d \n", Mining_height );
1119             printf("staking reward %.8f %s!\n", (double)subsidy / (double)COIN, ASSETCHAINS_SYMBOL);
1120             arith_uint256 post;
1121             post.SetCompact(pblock->GetVerusPOSTarget());
1122             pindexPrev = get_chainactive(Mining_height - 100);
1123             CTransaction &sTx = pblock->vtx[pblock->vtx.size()-1];
1124             printf("POS hash: %s  \ntarget:   %s\n", 
1125                 CTransaction::_GetVerusPOSHash(&(pblock->nNonce), sTx.vin[0].prevout.hash, sTx.vin[0].prevout.n, Mining_height, pindexPrev->GetBlockHeader().GetVerusEntropyHash(Mining_height - 100), sTx.vout[0].nValue).GetHex().c_str(), ArithToUint256(post).GetHex().c_str());
1126             if (unlockTime > Mining_height && subsidy >= ASSETCHAINS_TIMELOCKGTE)
1127                 printf("- timelocked until block %i\n", unlockTime);
1128             else
1129                 printf("\n");
1130
1131             // Check for stop or if block needs to be rebuilt
1132             boost::this_thread::interruption_point();
1133
1134             sleep(3);
1135
1136             // In regression test mode, stop mining after a block is found.
1137             if (chainparams.MineBlocksOnDemand()) {
1138                 throw boost::thread_interrupted();
1139             }
1140         }
1141     }
1142     catch (const boost::thread_interrupted&)
1143     {
1144         LogPrintf("VerusStaker terminated\n");
1145         throw;
1146     }
1147     catch (const std::runtime_error &e)
1148     {
1149         LogPrintf("VerusStaker runtime error: %s\n", e.what());
1150         return;
1151     }
1152 }
1153
1154 void static BitcoinMiner_noeq(CWallet *pwallet)
1155 #else
1156 void static BitcoinMiner_noeq()
1157 #endif
1158 {
1159     LogPrintf("%s miner started\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
1160     RenameThread("verushash-miner");
1161
1162 #ifdef ENABLE_WALLET
1163     // Each thread has its own key
1164     CReserveKey reservekey(pwallet);
1165 #endif
1166
1167     const CChainParams& chainparams = Params();
1168     // Each thread has its own counter
1169     unsigned int nExtraNonce = 0;
1170     std::vector<unsigned char> solnPlaceholder = std::vector<unsigned char>();
1171     solnPlaceholder.resize(Eh200_9.SolutionWidth);
1172     uint8_t *script; uint64_t total,checktoshis; int32_t i,j;
1173
1174     while ( (ASSETCHAIN_INIT == 0 || KOMODO_INITDONE == 0) ) //chainActive.Tip()->GetHeight() != 235300 &&
1175     {
1176         sleep(1);
1177         if ( komodo_baseid(ASSETCHAINS_SYMBOL) < 0 )
1178             break;
1179     }
1180
1181     SetThreadPriority(THREAD_PRIORITY_LOWEST);
1182
1183     // try a nice clean peer connection to start
1184     CBlockIndex *pindexPrev, *pindexCur;
1185     do {
1186         pindexPrev = chainActive.LastTip();
1187         MilliSleep(5000 + rand() % 5000);
1188         waitForPeers(chainparams);
1189         pindexCur = chainActive.LastTip();
1190     } while (pindexPrev != pindexCur);
1191
1192     // this will not stop printing more than once in all cases, but it will allow us to print in all cases
1193     // and print duplicates rarely without having to synchronize
1194     static CBlockIndex *lastChainTipPrinted;
1195
1196     miningTimer.start();
1197
1198     try {
1199         printf("Mining %s with %s\n", ASSETCHAINS_SYMBOL, ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
1200         while (true)
1201         {
1202             miningTimer.stop();
1203             waitForPeers(chainparams);
1204
1205             pindexPrev = chainActive.LastTip();
1206             sleep(1);
1207
1208             // prevent forking on startup before the diff algorithm kicks in
1209             if (pindexPrev->GetHeight() < 50 || pindexPrev != chainActive.LastTip())
1210             {
1211                 do {
1212                     pindexPrev = chainActive.LastTip();
1213                     MilliSleep(5000 + rand() % 5000);
1214                 } while (pindexPrev != chainActive.LastTip());
1215             }
1216
1217             // Create new block
1218             unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
1219             if ( Mining_height != pindexPrev->GetHeight()+1 )
1220             {
1221                 Mining_height = pindexPrev->GetHeight()+1;
1222                 Mining_start = (uint32_t)time(NULL);
1223             }
1224
1225             if (lastChainTipPrinted != pindexPrev)
1226             {
1227                 printf("Mining height %d\n", Mining_height);
1228                 lastChainTipPrinted = pindexPrev;
1229             }
1230
1231             miningTimer.start();
1232
1233 #ifdef ENABLE_WALLET
1234             CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, Mining_height, 0);
1235 #else
1236             CBlockTemplate *ptr = CreateNewBlockWithKey();
1237 #endif
1238             if ( ptr == 0 )
1239             {
1240                 static uint32_t counter;
1241                 if ( counter++ < 100 )
1242                     fprintf(stderr,"created illegal block, retry\n");
1243                 continue;
1244             }
1245
1246             unique_ptr<CBlockTemplate> pblocktemplate(ptr);
1247             if (!pblocktemplate.get())
1248             {
1249                 if (GetArg("-mineraddress", "").empty()) {
1250                     LogPrintf("Error in %s miner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n",
1251                               ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
1252                 } else {
1253                     // Should never reach here, because -mineraddress validity is checked in init.cpp
1254                     LogPrintf("Error in %s miner: Invalid %s -mineraddress\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO], ASSETCHAINS_SYMBOL);
1255                 }
1256                 return;
1257             }
1258             CBlock *pblock = &pblocktemplate->block;
1259             if ( ASSETCHAINS_SYMBOL[0] != 0 )
1260             {
1261                 if ( ASSETCHAINS_REWARD[0] == 0 && !ASSETCHAINS_LASTERA )
1262                 {
1263                     if ( pblock->vtx.size() == 1 && pblock->vtx[0].vout.size() == 1 && Mining_height > ASSETCHAINS_MINHEIGHT )
1264                     {
1265                         static uint32_t counter;
1266                         if ( counter++ < 10 )
1267                             fprintf(stderr,"skip generating %s on-demand block, no tx avail\n",ASSETCHAINS_SYMBOL);
1268                         sleep(10);
1269                         continue;
1270                     } else fprintf(stderr,"%s vouts.%d mining.%d vs %d\n",ASSETCHAINS_SYMBOL,(int32_t)pblock->vtx[0].vout.size(),Mining_height,ASSETCHAINS_MINHEIGHT);
1271                 }
1272             }
1273             IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1274             LogPrintf("Running %s miner with %u transactions in block (%u bytes)\n",ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO],
1275                        pblock->vtx.size(),::GetSerializeSize(*pblock,SER_NETWORK,PROTOCOL_VERSION));
1276             //
1277             // Search
1278             //
1279             uint32_t savebits; int64_t nStart = GetTime();
1280
1281             pblock->nSolution = solnPlaceholder;
1282             savebits = pblock->nBits;
1283             arith_uint256 hashTarget = arith_uint256().SetCompact(pblock->nBits);
1284             arith_uint256 mask(ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO]);
1285
1286             Mining_start = 0;
1287
1288             if ( pindexPrev != chainActive.LastTip() )
1289             {
1290                 if (lastChainTipPrinted != chainActive.LastTip())
1291                 {
1292                     lastChainTipPrinted = chainActive.LastTip();
1293                     printf("Block %d added to chain\n", lastChainTipPrinted->GetHeight());
1294                 }
1295                 MilliSleep(250);
1296                 continue;
1297             }
1298
1299             if ( ASSETCHAINS_STAKED != 0 )
1300             {
1301                 int32_t percPoS,z;
1302                 hashTarget = komodo_PoWtarget(&percPoS,hashTarget,Mining_height,ASSETCHAINS_STAKED);
1303                 for (z=31; z>=0; z--)
1304                     fprintf(stderr,"%02x",((uint8_t *)&hashTarget)[z]);
1305                 fprintf(stderr," PoW for staked coin PoS %d%% vs target %d%%\n",percPoS,(int32_t)ASSETCHAINS_STAKED);
1306             }
1307
1308             while (true)
1309             {
1310                 arith_uint256 arNonce = UintToArith256(pblock->nNonce);
1311
1312                 CVerusHashWriter ss = CVerusHashWriter(SER_GETHASH, PROTOCOL_VERSION);
1313                 ss << *((CBlockHeader *)pblock);
1314                 int64_t *extraPtr = ss.xI64p();
1315                 CVerusHash &vh = ss.GetState();
1316                 uint256 hashResult = uint256();
1317                 vh.ClearExtra();
1318                 int64_t i, count = ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] + 1;
1319                 int64_t hashesToGo = ASSETCHAINS_HASHESPERROUND[ASSETCHAINS_ALGO];
1320
1321                 // for speed check NONCEMASK at a time
1322                 for (i = 0; i < count; i++)
1323                 {
1324                     *extraPtr = i;
1325                     vh.ExtraHash((unsigned char *)&hashResult);
1326
1327                     if ( UintToArith256(hashResult) <= hashTarget )
1328                     {
1329                         if (pblock->nSolution.size() != 1344)
1330                         {
1331                             LogPrintf("ERROR: Block solution is not 1344 bytes as it should be");
1332                             sleep(5);
1333                             break;
1334                         }
1335
1336                         SetThreadPriority(THREAD_PRIORITY_NORMAL);
1337
1338                         *((int64_t *)&(pblock->nSolution.data()[pblock->nSolution.size() - 15])) = i;
1339
1340                         int32_t unlockTime = komodo_block_unlocktime(Mining_height);
1341                         int64_t subsidy = (int64_t)(pblock->vtx[0].vout[0].nValue);
1342
1343                         LogPrintf("Using %s algorithm:\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
1344                         LogPrintf("proof-of-work found  \n  hash: %s  \ntarget: %s\n", pblock->GetHash().GetHex(), hashTarget.GetHex());
1345                         printf("Found block %d \n", Mining_height );
1346                         printf("mining reward %.8f %s!\n", (double)subsidy / (double)COIN, ASSETCHAINS_SYMBOL);
1347                         printf("  hash: %s  \ntarget: %s\n", pblock->GetHash().GetHex().c_str(), hashTarget.GetHex().c_str());
1348                         if (unlockTime > Mining_height && subsidy >= ASSETCHAINS_TIMELOCKGTE)
1349                             printf("- timelocked until block %i\n", unlockTime);
1350                         else
1351                             printf("\n");
1352 #ifdef ENABLE_WALLET
1353                         ProcessBlockFound(pblock, *pwallet, reservekey);
1354 #else
1355                         ProcessBlockFound(pblock));
1356 #endif
1357                         SetThreadPriority(THREAD_PRIORITY_LOWEST);
1358                         break;
1359                     }
1360                     // check periodically if we're stale
1361                     if (!--hashesToGo)
1362                     {
1363                         if ( pindexPrev != chainActive.LastTip() )
1364                         {
1365                             if (lastChainTipPrinted != chainActive.LastTip())
1366                             {
1367                                 lastChainTipPrinted = chainActive.LastTip();
1368                                 printf("Block %d added to chain\n", lastChainTipPrinted->GetHeight());
1369                             }
1370                             break;
1371                         }
1372                         hashesToGo = ASSETCHAINS_HASHESPERROUND[ASSETCHAINS_ALGO];
1373                     }
1374                 }
1375
1376                 {
1377                     LOCK(cs_metrics);
1378                     nHashCount += i;
1379                 }
1380
1381                 // Check for stop or if block needs to be rebuilt
1382                 boost::this_thread::interruption_point();
1383
1384                 if (vNodes.empty() && chainparams.MiningRequiresPeers())
1385                 {
1386                     if ( Mining_height > ASSETCHAINS_MINHEIGHT )
1387                     {
1388                         fprintf(stderr,"no nodes, attempting reconnect\n");
1389                         break;
1390                     }
1391                 }
1392
1393                 if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
1394                 {
1395                     fprintf(stderr,"timeout, retrying\n");
1396                     break;
1397                 }
1398
1399                 if ( pindexPrev != chainActive.LastTip() )
1400                 {
1401                     if (lastChainTipPrinted != chainActive.LastTip())
1402                     {
1403                         lastChainTipPrinted = chainActive.LastTip();
1404                         printf("Block %d added to chain\n", lastChainTipPrinted->GetHeight());
1405                     }
1406                     break;
1407                 }
1408
1409 #ifdef _WIN32
1410                 printf("%llu mega hashes complete - working\n", (ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] + 1) / 1048576);
1411 #else
1412                 printf("%lu mega hashes complete - working\n", (ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] + 1) / 1048576);
1413 #endif
1414                 break;
1415
1416             }
1417         }
1418     }
1419     catch (const boost::thread_interrupted&)
1420     {
1421         miningTimer.stop();
1422         LogPrintf("%s miner terminated\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
1423         throw;
1424     }
1425     catch (const std::runtime_error &e)
1426     {
1427         miningTimer.stop();
1428         LogPrintf("%s miner runtime error: %s\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO], e.what());
1429         return;
1430     }
1431     miningTimer.stop();
1432 }
1433
1434 #ifdef ENABLE_WALLET
1435 void static BitcoinMiner(CWallet *pwallet)
1436 #else
1437 void static BitcoinMiner()
1438 #endif
1439 {
1440     LogPrintf("KomodoMiner started\n");
1441     SetThreadPriority(THREAD_PRIORITY_LOWEST);
1442     RenameThread("komodo-miner");
1443     const CChainParams& chainparams = Params();
1444     
1445 #ifdef ENABLE_WALLET
1446     // Each thread has its own key
1447     CReserveKey reservekey(pwallet);
1448 #endif
1449     
1450     // Each thread has its own counter
1451     unsigned int nExtraNonce = 0;
1452     
1453     unsigned int n = chainparams.EquihashN();
1454     unsigned int k = chainparams.EquihashK();
1455     uint8_t *script; uint64_t total,checktoshis; int32_t i,j,gpucount=KOMODO_MAXGPUCOUNT,notaryid = -1;
1456     while ( (ASSETCHAIN_INIT == 0 || KOMODO_INITDONE == 0) )
1457     {
1458         sleep(1);
1459         if ( komodo_baseid(ASSETCHAINS_SYMBOL) < 0 )
1460             break;
1461     }
1462     if ( ASSETCHAINS_SYMBOL[0] == 0 )
1463         komodo_chosennotary(&notaryid,chainActive.LastTip()->GetHeight(),NOTARY_PUBKEY33,(uint32_t)chainActive.LastTip()->GetBlockTime());
1464     if ( notaryid != My_notaryid )
1465         My_notaryid = notaryid;
1466     std::string solver;
1467     //if ( notaryid >= 0 || ASSETCHAINS_SYMBOL[0] != 0 )
1468     solver = "tromp";
1469     //else solver = "default";
1470     assert(solver == "tromp" || solver == "default");
1471     LogPrint("pow", "Using Equihash solver \"%s\" with n = %u, k = %u\n", solver, n, k);
1472     if ( ASSETCHAINS_SYMBOL[0] != 0 )
1473         fprintf(stderr,"notaryid.%d Mining.%s with %s\n",notaryid,ASSETCHAINS_SYMBOL,solver.c_str());
1474     std::mutex m_cs;
1475     bool cancelSolver = false;
1476     boost::signals2::connection c = uiInterface.NotifyBlockTip.connect(
1477                                                                        [&m_cs, &cancelSolver](const uint256& hashNewTip) mutable {
1478                                                                            std::lock_guard<std::mutex> lock{m_cs};
1479                                                                            cancelSolver = true;
1480                                                                        }
1481                                                                        );
1482     miningTimer.start();
1483     
1484     try {
1485         if ( ASSETCHAINS_SYMBOL[0] != 0 )
1486             fprintf(stderr,"try %s Mining with %s\n",ASSETCHAINS_SYMBOL,solver.c_str());
1487         while (true)
1488         {
1489             if (chainparams.MiningRequiresPeers()) //chainActive.LastTip()->GetHeight() != 235300 &&
1490             {
1491                 //if ( ASSETCHAINS_SEED != 0 && chainActive.LastTip()->GetHeight() < 100 )
1492                 //    break;
1493                 // Busy-wait for the network to come online so we don't waste time mining
1494                 // on an obsolete chain. In regtest mode we expect to fly solo.
1495                 miningTimer.stop();
1496                 do {
1497                     bool fvNodesEmpty;
1498                     {
1499                         //LOCK(cs_vNodes);
1500                         fvNodesEmpty = vNodes.empty();
1501                     }
1502                     if (!fvNodesEmpty )//&& !IsInitialBlockDownload())
1503                         break;
1504                     MilliSleep(15000);
1505                     //fprintf(stderr,"fvNodesEmpty %d IsInitialBlockDownload(%s) %d\n",(int32_t)fvNodesEmpty,ASSETCHAINS_SYMBOL,(int32_t)IsInitialBlockDownload());
1506                     
1507                 } while (true);
1508                 //fprintf(stderr,"%s Found peers\n",ASSETCHAINS_SYMBOL);
1509                 miningTimer.start();
1510             }
1511             //
1512             // Create new block
1513             //
1514             unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
1515             CBlockIndex* pindexPrev = chainActive.LastTip();
1516             if ( Mining_height != pindexPrev->GetHeight()+1 )
1517             {
1518                 Mining_height = pindexPrev->GetHeight()+1;
1519                 Mining_start = (uint32_t)time(NULL);
1520             }
1521             if ( ASSETCHAINS_SYMBOL[0] != 0 && ASSETCHAINS_STAKED == 0 )
1522             {
1523                 //fprintf(stderr,"%s create new block ht.%d\n",ASSETCHAINS_SYMBOL,Mining_height);
1524                 //sleep(3);
1525             }
1526
1527 #ifdef ENABLE_WALLET
1528             // notaries always default to staking
1529             CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, pindexPrev->GetHeight()+1, gpucount, ASSETCHAINS_STAKED != 0 && GetArg("-genproclimit", 0) == 0);
1530 #else
1531             CBlockTemplate *ptr = CreateNewBlockWithKey();
1532 #endif
1533             if ( ptr == 0 )
1534             {
1535                 static uint32_t counter;
1536                 if ( counter++ < 100 && ASSETCHAINS_STAKED == 0 )
1537                     fprintf(stderr,"created illegal block, retry\n");
1538                 sleep(1);
1539                 continue;
1540             }
1541             //fprintf(stderr,"get template\n");
1542             unique_ptr<CBlockTemplate> pblocktemplate(ptr);
1543             if (!pblocktemplate.get())
1544             {
1545                 if (GetArg("-mineraddress", "").empty()) {
1546                     LogPrintf("Error in KomodoMiner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n");
1547                 } else {
1548                     // Should never reach here, because -mineraddress validity is checked in init.cpp
1549                     LogPrintf("Error in KomodoMiner: Invalid -mineraddress\n");
1550                 }
1551                 return;
1552             }
1553             CBlock *pblock = &pblocktemplate->block;
1554             if ( ASSETCHAINS_SYMBOL[0] != 0 )
1555             {
1556                 if ( ASSETCHAINS_REWARD[0] == 0 && !ASSETCHAINS_LASTERA )
1557                 {
1558                     if ( pblock->vtx.size() == 1 && pblock->vtx[0].vout.size() == 1 && Mining_height > ASSETCHAINS_MINHEIGHT )
1559                     {
1560                         static uint32_t counter;
1561                         if ( counter++ < 10 )
1562                             fprintf(stderr,"skip generating %s on-demand block, no tx avail\n",ASSETCHAINS_SYMBOL);
1563                         sleep(10);
1564                         continue;
1565                     } else fprintf(stderr,"%s vouts.%d mining.%d vs %d\n",ASSETCHAINS_SYMBOL,(int32_t)pblock->vtx[0].vout.size(),Mining_height,ASSETCHAINS_MINHEIGHT);
1566                 }
1567             }
1568             IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1569             //fprintf(stderr,"Running KomodoMiner.%s with %u transactions in block\n",solver.c_str(),(int32_t)pblock->vtx.size());
1570             LogPrintf("Running KomodoMiner.%s with %u transactions in block (%u bytes)\n",solver.c_str(),pblock->vtx.size(),::GetSerializeSize(*pblock,SER_NETWORK,PROTOCOL_VERSION));
1571             //
1572             // Search
1573             //
1574             uint8_t pubkeys[66][33]; arith_uint256 bnMaxPoSdiff; uint32_t blocktimes[66]; int mids[256],nonzpkeys,i,j,externalflag; uint32_t savebits; int64_t nStart = GetTime();
1575             pblock->nBits         = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus());
1576             savebits = pblock->nBits;
1577             HASHTarget = arith_uint256().SetCompact(savebits);
1578             roundrobin_delay = ROUNDROBIN_DELAY;
1579             if ( ASSETCHAINS_SYMBOL[0] == 0 && notaryid >= 0 )
1580             {
1581                 j = 65;
1582                 if ( (Mining_height >= 235300 && Mining_height < 236000) || (Mining_height % KOMODO_ELECTION_GAP) > 64 || (Mining_height % KOMODO_ELECTION_GAP) == 0 || Mining_height > 1000000 )
1583                 {
1584                     int32_t dispflag = 0;
1585                     if ( notaryid <= 3 || notaryid == 32 || (notaryid >= 43 && notaryid <= 45) &&notaryid == 51 || notaryid == 52 || notaryid == 56 || notaryid == 57 )
1586                         dispflag = 1;
1587                     komodo_eligiblenotary(pubkeys,mids,blocktimes,&nonzpkeys,pindexPrev->GetHeight());
1588                     if ( nonzpkeys > 0 )
1589                     {
1590                         for (i=0; i<33; i++)
1591                             if( pubkeys[0][i] != 0 )
1592                                 break;
1593                         if ( i == 33 )
1594                             externalflag = 1;
1595                         else externalflag = 0;
1596                         if ( IS_KOMODO_NOTARY != 0 )
1597                         {
1598                             for (i=1; i<66; i++)
1599                                 if ( memcmp(pubkeys[i],pubkeys[0],33) == 0 )
1600                                     break;
1601                             if ( externalflag == 0 && i != 66 && mids[i] >= 0 )
1602                                 printf("VIOLATION at %d, notaryid.%d\n",i,mids[i]);
1603                             for (j=gpucount=0; j<65; j++)
1604                             {
1605                                 if ( dispflag != 0 )
1606                                 {
1607                                     if ( mids[j] >= 0 )
1608                                         fprintf(stderr,"%d ",mids[j]);
1609                                     else fprintf(stderr,"GPU ");
1610                                 }
1611                                 if ( mids[j] == -1 )
1612                                     gpucount++;
1613                             }
1614                             if ( dispflag != 0 )
1615                                 fprintf(stderr," <- prev minerids from ht.%d notary.%d gpucount.%d %.2f%% t.%u\n",pindexPrev->GetHeight(),notaryid,gpucount,100.*(double)gpucount/j,(uint32_t)time(NULL));
1616                         }
1617                         for (j=0; j<65; j++)
1618                             if ( mids[j] == notaryid )
1619                                 break;
1620                         if ( j == 65 )
1621                             KOMODO_LASTMINED = 0;
1622                     } else fprintf(stderr,"no nonz pubkeys\n");
1623                     if ( (Mining_height >= 235300 && Mining_height < 236000) || (j == 65 && Mining_height > KOMODO_MAYBEMINED+1 && Mining_height > KOMODO_LASTMINED+64) )
1624                     {
1625                         HASHTarget = arith_uint256().SetCompact(KOMODO_MINDIFF_NBITS);
1626                         fprintf(stderr,"I am the chosen one for %s ht.%d\n",ASSETCHAINS_SYMBOL,pindexPrev->GetHeight()+1);
1627                     } //else fprintf(stderr,"duplicate at j.%d\n",j);
1628                 } else Mining_start = 0;
1629             } else Mining_start = 0;
1630             if ( ASSETCHAINS_STAKED != 0 )
1631             {
1632                 int32_t percPoS,z; bool fNegative,fOverflow;
1633                 HASHTarget_POW = komodo_PoWtarget(&percPoS,HASHTarget,Mining_height,ASSETCHAINS_STAKED);
1634                 HASHTarget.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow);
1635                 if ( ASSETCHAINS_STAKED < 100 )
1636                 {
1637                     for (z=31; z>=0; z--)
1638                         fprintf(stderr,"%02x",((uint8_t *)&HASHTarget_POW)[z]);
1639                     fprintf(stderr," PoW for staked coin PoS %d%% vs target %d%%\n",percPoS,(int32_t)ASSETCHAINS_STAKED);
1640                 }
1641             }
1642             while (true)
1643             {
1644                 if ( KOMODO_INSYNC == 0 )
1645                 {
1646                     fprintf(stderr,"Mining when blockchain might not be in sync longest.%d vs %d\n",KOMODO_LONGESTCHAIN,Mining_height);
1647                     if ( KOMODO_LONGESTCHAIN != 0 && Mining_height >= KOMODO_LONGESTCHAIN )
1648                         KOMODO_INSYNC = 1;
1649                     sleep(3);
1650                 }
1651                 // Hash state
1652                 KOMODO_CHOSEN_ONE = 0;
1653                 
1654                 crypto_generichash_blake2b_state state;
1655                 EhInitialiseState(n, k, state);
1656                 // I = the block header minus nonce and solution.
1657                 CEquihashInput I{*pblock};
1658                 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
1659                 ss << I;
1660                 // H(I||...
1661                 crypto_generichash_blake2b_update(&state, (unsigned char*)&ss[0], ss.size());
1662                 // H(I||V||...
1663                 crypto_generichash_blake2b_state curr_state;
1664                 curr_state = state;
1665                 crypto_generichash_blake2b_update(&curr_state,pblock->nNonce.begin(),pblock->nNonce.size());
1666                 // (x_1, x_2, ...) = A(I, V, n, k)
1667                 LogPrint("pow", "Running Equihash solver \"%s\" with nNonce = %s\n",solver, pblock->nNonce.ToString());
1668                 arith_uint256 hashTarget;
1669                 if ( KOMODO_MININGTHREADS > 0 && ASSETCHAINS_STAKED > 0 && ASSETCHAINS_STAKED < 100 && Mining_height > 10 )
1670                     hashTarget = HASHTarget_POW;
1671                 else hashTarget = HASHTarget;
1672                 std::function<bool(std::vector<unsigned char>)> validBlock =
1673 #ifdef ENABLE_WALLET
1674                 [&pblock, &hashTarget, &pwallet, &reservekey, &m_cs, &cancelSolver, &chainparams]
1675 #else
1676                 [&pblock, &hashTarget, &m_cs, &cancelSolver, &chainparams]
1677 #endif
1678                 (std::vector<unsigned char> soln) {
1679                     int32_t z; arith_uint256 h; CBlock B;
1680                     // Write the solution to the hash and compute the result.
1681                     LogPrint("pow", "- Checking solution against target\n");
1682                     pblock->nSolution = soln;
1683                     solutionTargetChecks.increment();
1684                     B = *pblock;
1685                     h = UintToArith256(B.GetHash());
1686                     /*for (z=31; z>=16; z--)
1687                         fprintf(stderr,"%02x",((uint8_t *)&h)[z]);
1688                     fprintf(stderr," mined ");
1689                     for (z=31; z>=16; z--)
1690                         fprintf(stderr,"%02x",((uint8_t *)&HASHTarget)[z]);
1691                     fprintf(stderr," hashTarget ");
1692                     for (z=31; z>=16; z--)
1693                         fprintf(stderr,"%02x",((uint8_t *)&HASHTarget_POW)[z]);
1694                     fprintf(stderr," POW\n");*/
1695                     if ( h > hashTarget )
1696                     {
1697                         //if ( ASSETCHAINS_STAKED != 0 && KOMODO_MININGTHREADS == 0 )
1698                         //    sleep(1);
1699                         return false;
1700                     }
1701                     if ( IS_KOMODO_NOTARY != 0 && B.nTime > GetAdjustedTime() )
1702                     {
1703                         //fprintf(stderr,"need to wait %d seconds to submit block\n",(int32_t)(B.nTime - GetAdjustedTime()));
1704                         while ( GetAdjustedTime() < B.nTime-2 )
1705                         {
1706                             sleep(1);
1707                             if ( chainActive.LastTip()->GetHeight() >= Mining_height )
1708                             {
1709                                 fprintf(stderr,"new block arrived\n");
1710                                 return(false);
1711                             }
1712                         }
1713                     }
1714                     if ( ASSETCHAINS_STAKED == 0 )
1715                     {
1716                         if ( IS_KOMODO_NOTARY != 0 )
1717                         {
1718                             int32_t r;
1719                             if ( (r= ((Mining_height + NOTARY_PUBKEY33[16]) % 64) / 8) > 0 )
1720                                 MilliSleep((rand() % (r * 1000)) + 1000);
1721                         }
1722                     }
1723                     else
1724                     {
1725                         while ( B.nTime-57 > GetAdjustedTime() )
1726                         {
1727                             sleep(1);
1728                             if ( chainActive.LastTip()->GetHeight() >= Mining_height )
1729                                 return(false);
1730                         }
1731                         uint256 tmp = B.GetHash();
1732                         int32_t z; for (z=31; z>=0; z--)
1733                             fprintf(stderr,"%02x",((uint8_t *)&tmp)[z]);
1734                         fprintf(stderr," mined %s block %d!\n",ASSETCHAINS_SYMBOL,Mining_height);
1735                     }
1736                     CValidationState state;
1737                     if ( !TestBlockValidity(state,B, chainActive.LastTip(), true, false))
1738                     {
1739                         h = UintToArith256(B.GetHash());
1740                         for (z=31; z>=0; z--)
1741                             fprintf(stderr,"%02x",((uint8_t *)&h)[z]);
1742                         fprintf(stderr," Invalid block mined, try again\n");
1743                         return(false);
1744                     }
1745                     KOMODO_CHOSEN_ONE = 1;
1746                     // Found a solution
1747                     SetThreadPriority(THREAD_PRIORITY_NORMAL);
1748                     LogPrintf("KomodoMiner:\n");
1749                     LogPrintf("proof-of-work found  \n  hash: %s  \ntarget: %s\n", B.GetHash().GetHex(), HASHTarget.GetHex());
1750 #ifdef ENABLE_WALLET
1751                     if (ProcessBlockFound(&B, *pwallet, reservekey)) {
1752 #else
1753                         if (ProcessBlockFound(&B)) {
1754 #endif
1755                             // Ignore chain updates caused by us
1756                             std::lock_guard<std::mutex> lock{m_cs};
1757                             cancelSolver = false;
1758                         }
1759                         KOMODO_CHOSEN_ONE = 0;
1760                         SetThreadPriority(THREAD_PRIORITY_LOWEST);
1761                         // In regression test mode, stop mining after a block is found.
1762                         if (chainparams.MineBlocksOnDemand()) {
1763                             // Increment here because throwing skips the call below
1764                             ehSolverRuns.increment();
1765                             throw boost::thread_interrupted();
1766                         }
1767                         return true;
1768                     };
1769                     std::function<bool(EhSolverCancelCheck)> cancelled = [&m_cs, &cancelSolver](EhSolverCancelCheck pos) {
1770                         std::lock_guard<std::mutex> lock{m_cs};
1771                         return cancelSolver;
1772                     };
1773                     
1774                     // TODO: factor this out into a function with the same API for each solver.
1775                     if (solver == "tromp" ) { //&& notaryid >= 0 ) {
1776                         // Create solver and initialize it.
1777                         equi eq(1);
1778                         eq.setstate(&curr_state);
1779                         
1780                         // Initialization done, start algo driver.
1781                         eq.digit0(0);
1782                         eq.xfull = eq.bfull = eq.hfull = 0;
1783                         eq.showbsizes(0);
1784                         for (u32 r = 1; r < WK; r++) {
1785                             (r&1) ? eq.digitodd(r, 0) : eq.digiteven(r, 0);
1786                             eq.xfull = eq.bfull = eq.hfull = 0;
1787                             eq.showbsizes(r);
1788                         }
1789                         eq.digitK(0);
1790                         ehSolverRuns.increment();
1791                         
1792                         // Convert solution indices to byte array (decompress) and pass it to validBlock method.
1793                         for (size_t s = 0; s < eq.nsols; s++) {
1794                             LogPrint("pow", "Checking solution %d\n", s+1);
1795                             std::vector<eh_index> index_vector(PROOFSIZE);
1796                             for (size_t i = 0; i < PROOFSIZE; i++) {
1797                                 index_vector[i] = eq.sols[s][i];
1798                             }
1799                             std::vector<unsigned char> sol_char = GetMinimalFromIndices(index_vector, DIGITBITS);
1800                             
1801                             if (validBlock(sol_char)) {
1802                                 // If we find a POW solution, do not try other solutions
1803                                 // because they become invalid as we created a new block in blockchain.
1804                                 break;
1805                             }
1806                         }
1807                     } else {
1808                         try {
1809                             // If we find a valid block, we rebuild
1810                             bool found = EhOptimisedSolve(n, k, curr_state, validBlock, cancelled);
1811                             ehSolverRuns.increment();
1812                             if (found) {
1813                                 int32_t i; uint256 hash = pblock->GetHash();
1814                                 for (i=0; i<32; i++)
1815                                     fprintf(stderr,"%02x",((uint8_t *)&hash)[i]);
1816                                 fprintf(stderr," <- %s Block found %d\n",ASSETCHAINS_SYMBOL,Mining_height);
1817                                 FOUND_BLOCK = 1;
1818                                 KOMODO_MAYBEMINED = Mining_height;
1819                                 break;
1820                             }
1821                         } catch (EhSolverCancelledException&) {
1822                             LogPrint("pow", "Equihash solver cancelled\n");
1823                             std::lock_guard<std::mutex> lock{m_cs};
1824                             cancelSolver = false;
1825                         }
1826                     }
1827                     
1828                     // Check for stop or if block needs to be rebuilt
1829                     boost::this_thread::interruption_point();
1830                     // Regtest mode doesn't require peers
1831                     if ( FOUND_BLOCK != 0 )
1832                     {
1833                         FOUND_BLOCK = 0;
1834                         fprintf(stderr,"FOUND_BLOCK!\n");
1835                         //sleep(2000);
1836                     }
1837                     if (vNodes.empty() && chainparams.MiningRequiresPeers())
1838                     {
1839                         if ( ASSETCHAINS_SYMBOL[0] == 0 || Mining_height > ASSETCHAINS_MINHEIGHT )
1840                         {
1841                             fprintf(stderr,"no nodes, break\n");
1842                             break;
1843                         }
1844                     }
1845                     if ((UintToArith256(pblock->nNonce) & 0xffff) == 0xffff)
1846                     {
1847                         //if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 )
1848                         fprintf(stderr,"0xffff, break\n");
1849                         break;
1850                     }
1851                     if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
1852                     {
1853                         if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 )
1854                             fprintf(stderr,"timeout, break\n");
1855                         break;
1856                     }
1857                     if ( pindexPrev != chainActive.LastTip() )
1858                     {
1859                         if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 )
1860                             fprintf(stderr,"Tip advanced, break\n");
1861                         break;
1862                     }
1863                     // Update nNonce and nTime
1864                     pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1);
1865                     pblock->nBits = savebits;
1866                     /*if ( NOTARY_PUBKEY33[0] == 0 )
1867                     {
1868                         int32_t percPoS;
1869                         UpdateTime(pblock, consensusParams, pindexPrev);
1870                         if (consensusParams.fPowAllowMinDifficultyBlocks)
1871                         {
1872                             // Changing pblock->nTime can change work required on testnet:
1873                             HASHTarget.SetCompact(pblock->nBits);
1874                             HASHTarget_POW = komodo_PoWtarget(&percPoS,HASHTarget,Mining_height,ASSETCHAINS_STAKED);
1875                         }
1876                     }*/
1877                 }
1878             }
1879         }
1880         catch (const boost::thread_interrupted&)
1881         {
1882             miningTimer.stop();
1883             c.disconnect();
1884             LogPrintf("KomodoMiner terminated\n");
1885             throw;
1886         }
1887         catch (const std::runtime_error &e)
1888         {
1889             miningTimer.stop();
1890             c.disconnect();
1891             LogPrintf("KomodoMiner runtime error: %s\n", e.what());
1892             return;
1893         }
1894         miningTimer.stop();
1895         c.disconnect();
1896     }
1897     
1898 #ifdef ENABLE_WALLET
1899     void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads)
1900 #else
1901     void GenerateBitcoins(bool fGenerate, int nThreads)
1902 #endif
1903     {
1904         // if we are supposed to catch stake cheaters, there must be a valid sapling parameter, we need it at
1905         // initialization, and this is the first time we can get it. store the Sapling address here
1906         extern boost::optional<libzcash::SaplingPaymentAddress> cheatCatcher;
1907         extern std::string VERUS_CHEATCATCHER;
1908         libzcash::PaymentAddress addr = DecodePaymentAddress(VERUS_CHEATCATCHER);
1909         if (VERUS_CHEATCATCHER.size() > 0 && IsValidPaymentAddress(addr))
1910         {
1911             cheatCatcher = boost::get<libzcash::SaplingPaymentAddress>(addr);
1912         }
1913         else
1914         {
1915             if (VERUS_CHEATCATCHER.size() > 0)
1916                 fprintf(stderr, "-cheatcatcher parameter is invalid Sapling payment address\n");
1917         }    
1918
1919         static boost::thread_group* minerThreads = NULL;
1920         
1921         if (nThreads < 0)
1922             nThreads = GetNumCores();
1923         
1924         if (minerThreads != NULL)
1925         {
1926             minerThreads->interrupt_all();
1927             delete minerThreads;
1928             minerThreads = NULL;
1929         }
1930
1931         //fprintf(stderr,"nThreads.%d fGenerate.%d\n",(int32_t)nThreads,fGenerate);
1932         if ( nThreads == 0 && ASSETCHAINS_STAKED )
1933             nThreads = 1;
1934
1935         if ((nThreads == 0 || !fGenerate) && (VERUS_MINTBLOCKS == 0 || pwallet == NULL))
1936             return;
1937
1938         minerThreads = new boost::thread_group();
1939
1940 #ifdef ENABLE_WALLET
1941         if (ASSETCHAINS_LWMAPOS != 0 && VERUS_MINTBLOCKS)
1942         {
1943             minerThreads->create_thread(boost::bind(&VerusStaker, pwallet));
1944         }
1945 #endif
1946
1947         for (int i = 0; i < nThreads; i++) {
1948
1949 #ifdef ENABLE_WALLET
1950             if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH)
1951                 minerThreads->create_thread(boost::bind(&BitcoinMiner, pwallet));
1952             else
1953                 minerThreads->create_thread(boost::bind(&BitcoinMiner_noeq, pwallet));
1954 #else
1955             if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH)
1956                 minerThreads->create_thread(&BitcoinMiner);
1957             else
1958                 minerThreads->create_thread(&BitcoinMiner_noeq);
1959 #endif
1960         }
1961     }
1962     
1963 #endif // ENABLE_MINING
This page took 0.140911 seconds and 4 git commands to generate.