]> Git Repo - VerusCoin.git/blob - src/miner.cpp
Fix offset calc
[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 #include "pbaas/pbaas.h"
51 #include "pbaas/notarization.h"
52
53 using namespace std;
54
55 //////////////////////////////////////////////////////////////////////////////
56 //
57 // BitcoinMiner
58 //
59
60 //
61 // Unconfirmed transactions in the memory pool often depend on other
62 // transactions in the memory pool. When we select transactions from the
63 // pool, we select by highest priority or fee rate, so we might consider
64 // transactions that depend on transactions that aren't yet in the block.
65 // The COrphan class keeps track of these 'temporary orphans' while
66 // CreateBlock is figuring out which transactions to include.
67 //
68 class COrphan
69 {
70 public:
71     const CTransaction* ptx;
72     set<uint256> setDependsOn;
73     CFeeRate feeRate;
74     double dPriority;
75     
76     COrphan(const CTransaction* ptxIn) : ptx(ptxIn), feeRate(0), dPriority(0)
77     {
78     }
79 };
80
81 uint64_t nLastBlockTx = 0;
82 uint64_t nLastBlockSize = 0;
83
84 // We want to sort transactions by priority and fee rate, so:
85 typedef boost::tuple<double, CFeeRate, const CTransaction*> TxPriority;
86 class TxPriorityCompare
87 {
88     bool byFee;
89     
90 public:
91     TxPriorityCompare(bool _byFee) : byFee(_byFee) { }
92     
93     bool operator()(const TxPriority& a, const TxPriority& b)
94     {
95         if (byFee)
96         {
97             if (a.get<1>() == b.get<1>())
98                 return a.get<0>() < b.get<0>();
99             return a.get<1>() < b.get<1>();
100         }
101         else
102         {
103             if (a.get<0>() == b.get<0>())
104                 return a.get<1>() < b.get<1>();
105             return a.get<0>() < b.get<0>();
106         }
107     }
108 };
109
110 void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
111 {
112     pblock->nTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
113
114     // Updating time can change work required on testnet:
115     if (consensusParams.nPowAllowMinDifficultyBlocksAfterHeight != boost::none) {
116         pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams);
117     }
118 }
119
120 #include "komodo_defs.h"
121
122 extern CCriticalSection cs_metrics;
123 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;
124 extern uint64_t ASSETCHAINS_COMMISSION, ASSETCHAINS_STAKED;
125 extern bool VERUS_MINTBLOCKS;
126 extern uint64_t ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS], ASSETCHAINS_TIMELOCKGTE, ASSETCHAINS_NONCEMASK[];
127 extern const char *ASSETCHAINS_ALGORITHMS[];
128 extern int32_t VERUS_MIN_STAKEAGE, ASSETCHAINS_ALGO, ASSETCHAINS_EQUIHASH, ASSETCHAINS_VERUSHASH, ASSETCHAINS_LASTERA, ASSETCHAINS_LWMAPOS, ASSETCHAINS_NONCESHIFT[], ASSETCHAINS_HASHESPERROUND[];
129 extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
130 extern uint160 ASSETCHAINS_CHAINID;
131 extern uint160 VERUS_CHAINID;
132 extern std::string VERUS_CHAINNAME;
133 extern int32_t PBAAS_STARTBLOCK, PBAAS_ENDBLOCK;
134 extern string PBAAS_HOST, PBAAS_USERPASS;
135 extern int32_t PBAAS_PORT;
136 extern std::string NOTARY_PUBKEY,ASSETCHAINS_OVERRIDE_PUBKEY;
137 void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len);
138
139 extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33];
140 uint32_t Mining_start,Mining_height;
141 int32_t My_notaryid = -1;
142 int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp);
143 int32_t komodo_pax_opreturn(int32_t height,uint8_t *opret,int32_t maxsize);
144 int32_t komodo_baseid(char *origbase);
145 int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t nTime,int32_t dispflag);
146 int64_t komodo_block_unlocktime(uint32_t nHeight);
147 uint64_t komodo_commission(const CBlock *block);
148 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);
149 int32_t verus_staked(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &nBits, arith_uint256 &hashResult, uint8_t *utxosig, CPubKey &pk);
150 int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33);
151
152 CBlockTemplate* CreateNewBlock(const CScript& _scriptPubKeyIn, int32_t gpucount, bool isStake)
153 {
154     CScript scriptPubKeyIn(_scriptPubKeyIn);
155
156     CPubKey pk = CPubKey();
157     std::vector<std::vector<unsigned char>> vAddrs;
158     txnouttype txT;
159     if (Solver(scriptPubKeyIn, txT, vAddrs))
160     {
161         if (txT == TX_PUBKEY)
162             pk = CPubKey(vAddrs[0]);
163     }
164
165     uint64_t deposits; int32_t isrealtime,kmdheight; uint32_t blocktime; const CChainParams& chainparams = Params();
166     //fprintf(stderr,"create new block\n");
167     // Create new block
168     if ( gpucount < 0 )
169         gpucount = KOMODO_MAXGPUCOUNT;
170     std::unique_ptr<CBlockTemplate> pblocktemplate(new CBlockTemplate());
171     if(!pblocktemplate.get())
172     {
173         fprintf(stderr,"pblocktemplate.get() failure\n");
174         return NULL;
175     }
176     CBlock *pblock = &pblocktemplate->block; // pointer for convenience
177
178     // set version according to the current tip height, add solution if it is
179     // VerusHash
180     if (ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH)
181     {
182         pblock->nSolution.resize(Eh200_9.SolutionWidth);
183     }
184     else
185     {
186         pblock->nSolution.clear();
187     }
188     pblock->SetVersionByHeight(chainActive.LastTip()->GetHeight() + 1);
189
190     // -regtest only: allow overriding block.nVersion with
191     // -blockversion=N to test forking scenarios
192     if (Params().MineBlocksOnDemand())
193         pblock->nVersion = GetArg("-blockversion", pblock->nVersion);
194     
195     // Add dummy coinbase tx as first transaction
196     pblock->vtx.push_back(CTransaction());
197     pblocktemplate->vTxFees.push_back(-1); // updated at end
198     pblocktemplate->vTxSigOps.push_back(-1); // updated at end
199     
200     // Largest block you're willing to create:
201     unsigned int nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE);
202     // Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity:
203     nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize));
204     
205     // How much of the block should be dedicated to high-priority transactions,
206     // included regardless of the fees they pay
207     unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", DEFAULT_BLOCK_PRIORITY_SIZE);
208     nBlockPrioritySize = std::min(nBlockMaxSize, nBlockPrioritySize);
209     
210     // Minimum block size you want to create; block will be filled with free transactions
211     // until there are no more or the block reaches this size:
212     unsigned int nBlockMinSize = GetArg("-blockminsize", DEFAULT_BLOCK_MIN_SIZE);
213     nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize);
214     
215     // Collect memory pool transactions into the block
216     CAmount nFees = 0;
217
218     // we will attempt to spend any cheats we see
219     CTransaction cheatTx;
220     boost::optional<CTransaction> cheatSpend;
221     uint256 cbHash;
222
223     CBlockIndex* pindexPrev = 0;
224     {
225         LOCK2(cs_main, mempool.cs);
226         pindexPrev = chainActive.LastTip();
227         const int nHeight = pindexPrev->GetHeight() + 1;
228         const Consensus::Params &consensusParams = chainparams.GetConsensus();
229         uint32_t consensusBranchId = CurrentEpochBranchId(nHeight, consensusParams);
230         bool sapling = NetworkUpgradeActive(nHeight, consensusParams, Consensus::UPGRADE_SAPLING);
231
232         const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast();
233         uint32_t proposedTime = GetAdjustedTime();
234         if (proposedTime == nMedianTimePast)
235         {
236             // too fast or stuck, this addresses the too fast issue, while moving
237             // forward as quickly as possible
238             for (int i; i < 100; i++)
239             {
240                 proposedTime = GetAdjustedTime();
241                 if (proposedTime == nMedianTimePast)
242                     MilliSleep(10);
243             }
244         }
245         pblock->nTime = GetAdjustedTime();
246
247         CCoinsViewCache view(pcoinsTip);
248         uint32_t expired; uint64_t commission;
249         
250         SaplingMerkleTree sapling_tree;
251         assert(view.GetSaplingAnchorAt(view.GetBestAnchor(SAPLING), sapling_tree));
252
253         // Priority order to process transactions
254         list<COrphan> vOrphan; // list memory doesn't move
255         map<uint256, vector<COrphan*> > mapDependers;
256         bool fPrintPriority = GetBoolArg("-printpriority", false);
257         
258         // This vector will be sorted into a priority queue:
259         vector<TxPriority> vecPriority;
260         vecPriority.reserve(mempool.mapTx.size() + 1);
261
262         // check if we should add cheat transaction
263         CBlockIndex *ppast;
264         CTransaction cb;
265         int cheatHeight = nHeight - COINBASE_MATURITY < 1 ? 1 : nHeight - COINBASE_MATURITY;
266         if (cheatCatcher &&
267             sapling && chainActive.Height() > 100 && 
268             (ppast = chainActive[cheatHeight]) && 
269             ppast->IsVerusPOSBlock() && 
270             cheatList.IsHeightOrGreaterInList(cheatHeight))
271         {
272             // get the block and see if there is a cheat candidate for the stake tx
273             CBlock b;
274             if (!(fHavePruned && !(ppast->nStatus & BLOCK_HAVE_DATA) && ppast->nTx > 0) && ReadBlockFromDisk(b, ppast, 1))
275             {
276                 CTransaction &stakeTx = b.vtx[b.vtx.size() - 1];
277
278                 if (cheatList.IsCheatInList(stakeTx, &cheatTx))
279                 {
280                     // make and sign the cheat transaction to spend the coinbase to our address
281                     CMutableTransaction mtx = CreateNewContextualCMutableTransaction(consensusParams, nHeight);
282
283                     uint32_t voutNum;
284                     // get the first vout with value
285                     for (voutNum = 0; voutNum < b.vtx[0].vout.size(); voutNum++)
286                     {
287                         if (b.vtx[0].vout[voutNum].nValue > 0)
288                             break;
289                     }
290
291                     // send to the same pub key as the destination of this block reward
292                     if (MakeCheatEvidence(mtx, b.vtx[0], voutNum, cheatTx))
293                     {
294                         extern CWallet *pwalletMain;
295                         LOCK(pwalletMain->cs_wallet);
296                         TransactionBuilder tb = TransactionBuilder(consensusParams, nHeight);
297                         cb = b.vtx[0];
298                         cbHash = cb.GetHash();
299
300                         bool hasInput = false;
301                         for (uint32_t i = 0; i < cb.vout.size(); i++)
302                         {
303                             // add the spends with the cheat
304                             if (cb.vout[i].nValue > 0)
305                             {
306                                 tb.AddTransparentInput(COutPoint(cbHash,i), cb.vout[0].scriptPubKey, cb.vout[0].nValue);
307                                 hasInput = true;
308                             }
309                         }
310
311                         if (hasInput)
312                         {
313                             // this is a send from a t-address to a sapling address, which we don't have an ovk for. 
314                             // Instead, generate a common one from the HD seed. This ensures the data is
315                             // recoverable, at least for us, while keeping it logically separate from the ZIP 32
316                             // Sapling key hierarchy, which the user might not be using.
317                             uint256 ovk;
318                             HDSeed seed;
319                             if (pwalletMain->GetHDSeed(seed)) {
320                                 ovk = ovkForShieldingFromTaddr(seed);
321
322                                 // send everything to Sapling address
323                                 tb.SendChangeTo(cheatCatcher.value(), ovk);
324
325                                 tb.AddOpRet(mtx.vout[mtx.vout.size() - 1].scriptPubKey);
326
327                                 cheatSpend = tb.Build();
328                             }
329                         }
330                     }
331                 }
332             }
333         }
334
335         if (cheatSpend)
336         {
337             cheatTx = cheatSpend.value();
338             std::list<CTransaction> removed;
339             mempool.removeConflicts(cheatTx, removed);
340             printf("Found cheating stake! Adding cheat spend for %.8f at block #%d, coinbase tx\n%s\n",
341                 (double)cb.GetValueOut() / (double)COIN, nHeight, cheatSpend.value().vin[0].prevout.hash.GetHex().c_str());
342
343             // add to mem pool and relay
344             if (myAddtomempool(cheatTx))
345             {
346                 RelayTransaction(cheatTx);
347             }
348         }
349
350         // if we are a PBaaS chain, first make sure we don't start prematurely, and if
351         // we should make an earned notarization, make it and set index to non-zero value
352         int32_t pbaasNotarizationTx = 0;
353         int64_t pbaasTransparentIn = 0;
354         int64_t pbaasTransparentOut = 0;
355         if (!IsVerusActive())
356         {
357             // if we don't have a connected root PBaaS chain, we can't properly check
358             // and notarize the start block, so we have to pass and wait
359             if (nHeight != 1 || (ConnectedChains.IsVerusPBaaSAvailable() && ConnectedChains.notaryChainHeight >= PBAAS_STARTBLOCK))
360             {
361                 // if we have access to our parent daemon
362                 // create a notarization, if we would qualify, and add it to the mempool and block
363                 CMutableTransaction newNotarizationTx;
364                 CTransaction prevTx, crossTx;
365                 ChainMerkleMountainView mmv = chainActive.GetMMV();
366                 uint256 mmrRoot = mmv.GetRoot();
367                 if (CreateEarnedNotarization(newNotarizationTx, prevTx, crossTx, nHeight, mmrRoot))
368                 {
369                     // we have a valid, earned notarization transaction. we still need to verify:
370                     // 1. it has matching input for its outputs, since it can be returned with less than enough, 
371                     // if there is not enough, take it as instant-spend from the coinbase. if there is too much,
372                     // increase the output on the main notarization thread.
373                     // instant-spend and notarization 
374                     // transaction threads on a PBaaS chain can only be used for notarization, and can never convert to 
375                     // available supply
376
377                     // Fetch previous transactions (inputs):
378                     for (const CTxIn& txin : newNotarizationTx.vin)
379                     {
380                         const uint256& prevHash = txin.prevout.hash;
381                         const CCoins *pcoins = view.AccessCoins(prevHash); // this is certainly allowed to fail
382                         pbaasTransparentIn += pcoins && (pcoins->vout.size() > txin.prevout.n) ? pcoins->vout[txin.prevout.n].nValue : 0;
383                     }
384
385                     for (auto txout : newNotarizationTx.vout)
386                     {
387                         pbaasTransparentOut += txout.nValue;
388                     }
389
390                     if (pbaasTransparentOut < pbaasTransparentIn)
391                     {
392                         // add excess to the notarization output
393                         int notarizeOut = -1;
394                         for (int outIdx = 0; outIdx < newNotarizationTx.vout.size(); outIdx++)
395                         {
396                             uint32_t ecode;
397                             if (newNotarizationTx.vout[outIdx].scriptPubKey.IsPayToCryptoCondition(&ecode))
398                             {
399                                 if (ecode == EVAL_EARNEDNOTARIZATION)
400                                 {
401                                     newNotarizationTx.vout[outIdx].nValue += pbaasTransparentIn - pbaasTransparentOut;
402                                     break;
403                                 }
404                             }
405                         }
406                     }
407                     
408                     if (pbaasTransparentOut > pbaasTransparentIn)
409                     {
410                         // add an incomplete input to spend a coinbase instant spend output to fund the notarization
411                         newNotarizationTx.vin.push_back(CTxIn());
412                     }
413
414                     pblock->vtx.push_back(CTransaction(newNotarizationTx));
415                     pblocktemplate->vTxFees.push_back(0);
416                     pblocktemplate->vTxSigOps.push_back(-1); // updated at end
417                     pbaasNotarizationTx = pblock->vtx.size() - 1;
418                 }
419                 else if (nHeight == 1)
420                 {
421                     // failed to notarize at block 1
422                     return NULL;
423                 }
424             }
425             else
426             {
427                 // can't mine block 1 unless we have a connection to Verus and can notarize
428                 return NULL;
429             }
430         }
431
432         // now add transactions from the mem pool
433         for (CTxMemPool::indexed_transaction_set::iterator mi = mempool.mapTx.begin();
434              mi != mempool.mapTx.end(); ++mi)
435         {
436             const CTransaction& tx = mi->GetTx();
437             
438             int64_t nLockTimeCutoff = (STANDARD_LOCKTIME_VERIFY_FLAGS & LOCKTIME_MEDIAN_TIME_PAST)
439             ? nMedianTimePast
440             : pblock->GetBlockTime();
441
442             if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight, nLockTimeCutoff) || IsExpiredTx(tx, nHeight))
443             {
444                 //fprintf(stderr,"coinbase.%d finaltx.%d expired.%d\n",tx.IsCoinBase(),IsFinalTx(tx, nHeight, nLockTimeCutoff),IsExpiredTx(tx, nHeight));
445                 continue;
446             }
447
448             if ( ASSETCHAINS_SYMBOL[0] == 0 && komodo_validate_interest(tx,nHeight,(uint32_t)pblock->nTime,0) < 0 )
449             {
450                 //fprintf(stderr,"CreateNewBlock: komodo_validate_interest failure nHeight.%d nTime.%u vs locktime.%u\n",nHeight,(uint32_t)pblock->nTime,(uint32_t)tx.nLockTime);
451                 continue;
452             }
453
454             COrphan* porphan = NULL;
455             double dPriority = 0;
456             CAmount nTotalIn = 0;
457             bool fMissingInputs = false;
458             if (tx.IsCoinImport())
459             {
460                 CAmount nValueIn = GetCoinImportValue(tx);
461                 nTotalIn += nValueIn;
462                 dPriority += (double)nValueIn * 1000;  // flat multiplier
463             } else {
464                 BOOST_FOREACH(const CTxIn& txin, tx.vin)
465                 {
466                     // Read prev transaction
467                     if (!view.HaveCoins(txin.prevout.hash))
468                     {
469                         // This should never happen; all transactions in the memory
470                         // pool should connect to either transactions in the chain
471                         // or other transactions in the memory pool.
472                         if (!mempool.mapTx.count(txin.prevout.hash))
473                         {
474                             LogPrintf("ERROR: mempool transaction missing input\n");
475                             if (fDebug) assert("mempool transaction missing input" == 0);
476                             fMissingInputs = true;
477                             if (porphan)
478                                 vOrphan.pop_back();
479                             break;
480                         }
481
482                         // Has to wait for dependencies
483                         if (!porphan)
484                         {
485                             // Use list for automatic deletion
486                             vOrphan.push_back(COrphan(&tx));
487                             porphan = &vOrphan.back();
488                         }
489                         mapDependers[txin.prevout.hash].push_back(porphan);
490                         porphan->setDependsOn.insert(txin.prevout.hash);
491                         nTotalIn += mempool.mapTx.find(txin.prevout.hash)->GetTx().vout[txin.prevout.n].nValue;
492                         continue;
493                     }
494                     const CCoins* coins = view.AccessCoins(txin.prevout.hash);
495                     assert(coins);
496
497                     CAmount nValueIn = coins->vout[txin.prevout.n].nValue;
498                     nTotalIn += nValueIn;
499
500                     int nConf = nHeight - coins->nHeight;
501
502                     dPriority += (double)nValueIn * nConf;
503                 }
504                 nTotalIn += tx.GetShieldedValueIn();
505             }
506
507             if (fMissingInputs) continue;
508             
509             // Priority is sum(valuein * age) / modified_txsize
510             unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
511             dPriority = tx.ComputePriority(dPriority, nTxSize);
512             
513             uint256 hash = tx.GetHash();
514             mempool.ApplyDeltas(hash, dPriority, nTotalIn);
515             
516             CFeeRate feeRate(nTotalIn-tx.GetValueOut(), nTxSize);
517             
518             if (porphan)
519             {
520                 porphan->dPriority = dPriority;
521                 porphan->feeRate = feeRate;
522             }
523             else
524                 vecPriority.push_back(TxPriority(dPriority, feeRate, &(mi->GetTx())));
525         }
526
527         // Collect transactions into block
528         uint64_t nBlockSize = 1000;
529         uint64_t nBlockTx = 0;
530         int64_t interest;
531         int nBlockSigOps = 100;
532         bool fSortedByFee = (nBlockPrioritySize <= 0);
533         
534         TxPriorityCompare comparer(fSortedByFee);
535         std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
536         
537         while (!vecPriority.empty())
538         {
539             // Take highest priority transaction off the priority queue:
540             double dPriority = vecPriority.front().get<0>();
541             CFeeRate feeRate = vecPriority.front().get<1>();
542             const CTransaction& tx = *(vecPriority.front().get<2>());
543             
544             std::pop_heap(vecPriority.begin(), vecPriority.end(), comparer);
545             vecPriority.pop_back();
546             
547             // Size limits
548             unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
549             if (nBlockSize + nTxSize >= nBlockMaxSize-512) // room for extra autotx
550             {
551                 //fprintf(stderr,"nBlockSize %d + %d nTxSize >= %d nBlockMaxSize\n",(int32_t)nBlockSize,(int32_t)nTxSize,(int32_t)nBlockMaxSize);
552                 continue;
553             }
554             
555             // Legacy limits on sigOps:
556             unsigned int nTxSigOps = GetLegacySigOpCount(tx);
557             if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS-1)
558             {
559                 //fprintf(stderr,"A nBlockSigOps %d + %d nTxSigOps >= %d MAX_BLOCK_SIGOPS-1\n",(int32_t)nBlockSigOps,(int32_t)nTxSigOps,(int32_t)MAX_BLOCK_SIGOPS);
560                 continue;
561             }
562             // Skip free transactions if we're past the minimum block size:
563             const uint256& hash = tx.GetHash();
564             double dPriorityDelta = 0;
565             CAmount nFeeDelta = 0;
566             mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta);
567             if (fSortedByFee && (dPriorityDelta <= 0) && (nFeeDelta <= 0) && (feeRate < ::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize))
568             {
569                 //fprintf(stderr,"fee rate skip\n");
570                 continue;
571             }
572             // Prioritise by fee once past the priority size or we run out of high-priority
573             // transactions:
574             if (!fSortedByFee &&
575                 ((nBlockSize + nTxSize >= nBlockPrioritySize) || !AllowFree(dPriority)))
576             {
577                 fSortedByFee = true;
578                 comparer = TxPriorityCompare(fSortedByFee);
579                 std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
580             }
581             
582             if (!view.HaveInputs(tx))
583             {
584                 //fprintf(stderr,"dont have inputs\n");
585                 continue;
586             }
587             CAmount nTxFees = view.GetValueIn(chainActive.LastTip()->GetHeight(),&interest,tx,chainActive.LastTip()->nTime)-tx.GetValueOut();
588             
589             nTxSigOps += GetP2SHSigOpCount(tx, view);
590             if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS-1)
591             {
592                 //fprintf(stderr,"B nBlockSigOps %d + %d nTxSigOps >= %d MAX_BLOCK_SIGOPS-1\n",(int32_t)nBlockSigOps,(int32_t)nTxSigOps,(int32_t)MAX_BLOCK_SIGOPS);
593                 continue;
594             }
595             // Note that flags: we don't want to set mempool/IsStandard()
596             // policy here, but we still have to ensure that the block we
597             // create only contains transactions that are valid in new blocks.
598             CValidationState state;
599             PrecomputedTransactionData txdata(tx);
600             if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId))
601             {
602                 //fprintf(stderr,"context failure\n");
603                 continue;
604             }
605             UpdateCoins(tx, view, nHeight);
606
607             BOOST_FOREACH(const OutputDescription &outDescription, tx.vShieldedOutput) {
608                 sapling_tree.append(outDescription.cm);
609             }
610
611             // Added
612             pblock->vtx.push_back(tx);
613             pblocktemplate->vTxFees.push_back(nTxFees);
614             pblocktemplate->vTxSigOps.push_back(nTxSigOps);
615             nBlockSize += nTxSize;
616             ++nBlockTx;
617             nBlockSigOps += nTxSigOps;
618             nFees += nTxFees;
619             
620             if (fPrintPriority)
621             {
622                 LogPrintf("priority %.1f fee %s txid %s\n",dPriority, feeRate.ToString(), tx.GetHash().ToString());
623             }
624             
625             // Add transactions that depend on this one to the priority queue
626             if (mapDependers.count(hash))
627             {
628                 BOOST_FOREACH(COrphan* porphan, mapDependers[hash])
629                 {
630                     if (!porphan->setDependsOn.empty())
631                     {
632                         porphan->setDependsOn.erase(hash);
633                         if (porphan->setDependsOn.empty())
634                         {
635                             vecPriority.push_back(TxPriority(porphan->dPriority, porphan->feeRate, porphan->ptx));
636                             std::push_heap(vecPriority.begin(), vecPriority.end(), comparer);
637                         }
638                     }
639                 }
640             }
641         }
642         
643         nLastBlockTx = nBlockTx;
644         nLastBlockSize = nBlockSize;
645         blocktime = 1 + std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
646         //pblock->nTime = blocktime + 1;
647         pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus());
648
649         int32_t stakeHeight = chainActive.Height() + 1;
650
651         //LogPrintf("CreateNewBlock(): total size %u blocktime.%u nBits.%08x\n", nBlockSize,blocktime,pblock->nBits);
652         if ( ASSETCHAINS_SYMBOL[0] != 0 && isStake )
653         {
654             uint64_t txfees,utxovalue; uint32_t txtime; uint256 utxotxid; int32_t i,siglen,numsigs,utxovout; uint8_t utxosig[128],*ptr;
655             CMutableTransaction txStaked = CreateNewContextualCMutableTransaction(Params().GetConsensus(), stakeHeight);
656
657             //if ( blocktime > pindexPrev->GetMedianTimePast()+60 )
658             //    blocktime = pindexPrev->GetMedianTimePast() + 60;
659             if (ASSETCHAINS_LWMAPOS != 0)
660             {
661                 uint32_t nBitsPOS;
662                 arith_uint256 posHash;
663
664                 siglen = verus_staked(pblock, txStaked, nBitsPOS, posHash, utxosig, pk);
665                 blocktime = GetAdjustedTime();
666
667                 // change the scriptPubKeyIn to the same output script exactly as the staking transaction
668                 if (siglen > 0)
669                     scriptPubKeyIn = CScript(txStaked.vout[0].scriptPubKey);
670             }
671             else
672             {
673                 siglen = komodo_staked(txStaked, pblock->nBits, &blocktime, &txtime, &utxotxid, &utxovout, &utxovalue, utxosig);
674             }
675
676             if ( siglen > 0 )
677             {
678                 CAmount txfees;
679
680                 // after Sapling, stake transactions have a fee, but it is recovered in the reward
681                 // this ensures that a rebroadcast goes through quickly to begin staking again
682                 txfees = sapling ? DEFAULT_STAKE_TXFEE : 0;
683
684                 pblock->vtx.push_back(txStaked);
685                 pblocktemplate->vTxFees.push_back(txfees);
686                 pblocktemplate->vTxSigOps.push_back(GetLegacySigOpCount(txStaked));
687                 nFees += txfees;
688                 pblock->nTime = blocktime;
689                 //printf("staking PoS ht.%d t%u lag.%u\n",(int32_t)chainActive.LastTip()->GetHeight()+1,blocktime,(uint32_t)(GetAdjustedTime() - (blocktime-13)));
690             } else return(0); //fprintf(stderr,"no utxos eligible for staking\n");
691         }
692         
693         // Create coinbase tx
694         CMutableTransaction txNew = CreateNewContextualCMutableTransaction(consensusParams, nHeight);
695         txNew.vin.resize(1);
696         txNew.vin[0].prevout.SetNull();
697         txNew.vin[0].scriptSig = CScript() << nHeight << OP_0;
698
699         txNew.vout.resize(1);
700         txNew.vout[0].scriptPubKey = scriptPubKeyIn;
701         txNew.vout[0].nValue = GetBlockSubsidy(nHeight,consensusParams) + nFees;
702
703         // once we get to Sapling, enable CC StakeGuard for stake transactions
704         if (isStake && sapling)
705         {
706             // if there is a specific destination, use it
707             CTransaction stakeTx = pblock->vtx[pblock->vtx.size() - 1];
708             CStakeParams p;
709             if (ValidateStakeTransaction(stakeTx, p, false))
710             {
711                 if (!p.pk.IsValid() || !MakeGuardedOutput(txNew.vout[0].nValue, p.pk, stakeTx, txNew.vout[0]))
712                 {
713                     fprintf(stderr,"CreateNewBlock: failed to make GuardedOutput on staking coinbase\n");
714                     return 0;
715                 }
716             }
717             else
718             {
719                 fprintf(stderr,"CreateNewBlock: invalid stake transaction\n");
720                 return 0;
721             }
722         }
723
724         txNew.nExpiryHeight = 0;
725         txNew.nLockTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
726
727         if ( ASSETCHAINS_SYMBOL[0] == 0 && IS_KOMODO_NOTARY != 0 && My_notaryid >= 0 )
728             txNew.vout[0].nValue += 5000;
729
730         // check if coinbase transactions must be time locked at current subsidy and prepend the time lock
731         // to transaction if so, cast for GTE operator
732         if ((uint64_t)(txNew.vout[0].nValue) >= ASSETCHAINS_TIMELOCKGTE)
733         {
734             int32_t opretlen, p2shlen, scriptlen;
735             CScriptExt opretScript = CScriptExt();
736
737             txNew.vout.resize(2);
738
739             // prepend time lock to original script unless original script is P2SH, in which case, we will leave the coins
740             // protected only by the time lock rather than 100% inaccessible
741             opretScript.AddCheckLockTimeVerify(komodo_block_unlocktime(nHeight));
742             if (scriptPubKeyIn.IsPayToScriptHash() || scriptPubKeyIn.IsPayToCryptoCondition())
743             {
744                 fprintf(stderr,"CreateNewBlock: attempt to add timelock to pay2sh or pay2cc\n");
745                 return 0;
746             }
747             
748             opretScript += scriptPubKeyIn;
749
750             txNew.vout[0].scriptPubKey = CScriptExt().PayToScriptHash(CScriptID(opretScript));
751             txNew.vout[1].scriptPubKey = CScriptExt().OpReturnScript(opretScript, OPRETTYPE_TIMELOCK);
752             txNew.vout[1].nValue = 0;
753         } // timelocks and commissions are currently incompatible due to validation complexity of the combination
754         else if ( nHeight > 1 && ASSETCHAINS_SYMBOL[0] != 0 && ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 && ASSETCHAINS_COMMISSION != 0 && (commission= komodo_commission((CBlock*)&pblocktemplate->block)) != 0 )
755         {
756             int32_t i; uint8_t *ptr;
757             txNew.vout.resize(2);
758             txNew.vout[1].nValue = commission;
759             txNew.vout[1].scriptPubKey.resize(35);
760             ptr = (uint8_t *)&txNew.vout[1].scriptPubKey[0];
761             ptr[0] = 33;
762             for (i=0; i<33; i++)
763                 ptr[i+1] = ASSETCHAINS_OVERRIDE_PUBKEY33[i];
764             ptr[34] = OP_CHECKSIG;
765             //printf("autocreate commision vout\n");
766         }
767
768         // add final notarization and instant spend fixups
769         if (pbaasNotarizationTx)
770         {
771             extern CWallet *pwalletMain;
772             LOCK(pwalletMain->cs_wallet);
773
774             // now add an input from the coinbase to the notarization
775             CMutableTransaction mntx(pblock->vtx[pbaasNotarizationTx]);
776
777             // determine number of CB outputs
778             int numNotaryOutputs = mntx.vout.size() - (mntx.vout[mntx.vout.size() - 1].scriptPubKey.IsOpReturn() ? 1 : 0);
779
780             int64_t needed = pbaasTransparentOut - pbaasTransparentIn;
781             if (needed > PBAAS_MINNOTARIZATIONOUTPUT * numNotaryOutputs)
782             {
783                 fprintf(stderr,"CreateNewBlock: too much output from earned notarization transaction\n");
784                 return NULL;
785             }
786
787             uint256 cbHash;
788             int32_t pbaasCoinbaseInstantSpendOut;
789
790             // if we need an instant out to be a source of funds for the notarization transaction, make it here
791             if (needed > 0)
792             {
793                 // the new instant spend out will go where at the end and before any opret
794                 pbaasCoinbaseInstantSpendOut = txNew.vout.size() - (txNew.vout[txNew.vout.size() - 1].scriptPubKey.IsOpReturn() ? 1 : 0);
795
796                 auto coinbaseOutIt = txNew.vout.begin() + pbaasCoinbaseInstantSpendOut;
797
798                 CCcontract_info CC;
799                 CCcontract_info *cp;
800                 vector<CTxDestination> vKeys;
801
802                 // make the earned notarization output
803                 cp = CCinit(&CC, EVAL_EARNEDNOTARIZATION);
804                 // need to be able to send this to EVAL_PBAASDEFINITION address as a destination, locked by the default pubkey
805                 CPubKey pk = CPubKey(std::vector<unsigned char>(CC.CChexstr, CC.CChexstr + strlen(CC.CChexstr)));
806
807                 vKeys.push_back(CTxDestination(CKeyID(CCrossChainRPCData::GetConditionID(VERUS_CHAINID, EVAL_EARNEDNOTARIZATION))));
808
809                 // output duplicate notarization as coinbase output for instant spend to notarization
810                 // these coins will never join the supply pool, so they do not need to be considered as
811                 // part of the total value of this coinbase
812                 CPBaaSNotarization pbn(pblock->vtx[pbaasNotarizationTx]);
813                 txNew.vout.insert(coinbaseOutIt, MakeCC1of1Vout(EVAL_EARNEDNOTARIZATION, needed, pk, vKeys, pbn));
814                 cbHash = txNew.GetHash();
815                 mntx.vin[mntx.vin.size() - 1] = CTxIn(txNew.GetHash(), pbaasCoinbaseInstantSpendOut);
816
817                 // put notarization back in the block
818                 pblock->vtx[pbaasNotarizationTx] = mntx;
819             }
820
821             CTransaction ntx(mntx);
822
823             for (int i = 0; i < ntx.vin.size(); i++)
824             {
825                 bool signSuccess;
826                 SignatureData sigdata;
827                 CAmount value;
828                 const CScript *pScriptPubKey;
829                 if (needed > 0 && cbHash == ntx.vin[i].prevout.hash)
830                 {
831                     pScriptPubKey = &txNew.vout[pbaasCoinbaseInstantSpendOut].scriptPubKey;
832                     value = txNew.vout[pbaasCoinbaseInstantSpendOut].nValue;
833                 }
834                 else
835                 {
836                     const CCoins *coins = view.AccessCoins(ntx.vin[i].prevout.hash);
837                     pScriptPubKey = &coins->vout[ntx.vin[i].prevout.n].scriptPubKey;
838                     value = coins->vout[ntx.vin[i].prevout.n].nValue;
839                 }
840                 
841                 signSuccess = ProduceSignature(TransactionSignatureCreator(pwalletMain, &ntx, i, value, SIGHASH_ALL), *pScriptPubKey, sigdata, consensusBranchId);
842
843                 if (!signSuccess)
844                 {
845                     fprintf(stderr,"CreateNewBlock: failure to sign earned notarization\n");
846                     return NULL;
847                 } else {
848                     UpdateTransaction(mntx, i, sigdata);
849                 }
850             }
851             pblocktemplate->vTxSigOps[pbaasNotarizationTx] = GetLegacySigOpCount(mntx);
852         }
853
854         pblock->vtx[0] = txNew;
855         pblocktemplate->vTxFees[0] = -nFees;
856
857         // if not Verus stake, setup nonce, otherwise, leave it alone
858         if (!isStake || ASSETCHAINS_LWMAPOS == 0)
859         {
860             // Randomize nonce
861             arith_uint256 nonce = UintToArith256(GetRandHash());
862
863             // Clear the top 16 and bottom 16 or 24 bits (for local use as thread flags and counters)
864             nonce <<= ASSETCHAINS_NONCESHIFT[ASSETCHAINS_ALGO];
865             nonce >>= 16;
866             pblock->nNonce = ArithToUint256(nonce);
867         }
868         
869         // Fill in header
870         pblock->hashPrevBlock  = pindexPrev->GetBlockHash();
871         pblock->hashFinalSaplingRoot   = sapling_tree.root();
872
873         // all Verus PoS chains need this data in the block at all times
874         if ( ASSETCHAINS_LWMAPOS || ASSETCHAINS_SYMBOL[0] == 0 || ASSETCHAINS_STAKED == 0 || KOMODO_MININGTHREADS > 0 )
875         {
876             UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
877             pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus());
878         }
879
880         pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
881
882         if ( ASSETCHAINS_SYMBOL[0] == 0 && IS_KOMODO_NOTARY != 0 && My_notaryid >= 0 )
883         {
884             uint32_t r;
885             CMutableTransaction txNotary = CreateNewContextualCMutableTransaction(Params().GetConsensus(), chainActive.Height() + 1);
886             if ( pblock->nTime < pindexPrev->nTime+60 )
887                 pblock->nTime = pindexPrev->nTime + 60;
888             if ( gpucount < 33 )
889             {
890                 uint8_t tmpbuffer[40]; uint32_t r; int32_t n=0; uint256 randvals;
891                 memcpy(&tmpbuffer[n],&My_notaryid,sizeof(My_notaryid)), n += sizeof(My_notaryid);
892                 memcpy(&tmpbuffer[n],&Mining_height,sizeof(Mining_height)), n += sizeof(Mining_height);
893                 memcpy(&tmpbuffer[n],&pblock->hashPrevBlock,sizeof(pblock->hashPrevBlock)), n += sizeof(pblock->hashPrevBlock);
894                 vcalc_sha256(0,(uint8_t *)&randvals,tmpbuffer,n);
895                 memcpy(&r,&randvals,sizeof(r));
896                 pblock->nTime += (r % (33 - gpucount)*(33 - gpucount));
897             }
898             if ( komodo_notaryvin(txNotary,NOTARY_PUBKEY33) > 0 )
899             {
900                 CAmount txfees = 5000;
901                 pblock->vtx.push_back(txNotary);
902                 pblocktemplate->vTxFees.push_back(txfees);
903                 pblocktemplate->vTxSigOps.push_back(GetLegacySigOpCount(txNotary));
904                 nFees += txfees;
905                 pblocktemplate->vTxFees[0] = -nFees;
906                 //*(uint64_t *)(&pblock->vtx[0].vout[0].nValue) += txfees;
907                 //fprintf(stderr,"added notaryvin\n");
908             }
909             else
910             {
911                 fprintf(stderr,"error adding notaryvin, need to create 0.0001 utxos\n");
912                 return(0);
913             }
914         }
915         else if ( ASSETCHAINS_CC == 0 && pindexPrev != 0 && ASSETCHAINS_STAKED == 0 && (ASSETCHAINS_SYMBOL[0] != 0 || IS_KOMODO_NOTARY == 0 || My_notaryid < 0) )
916         {
917             CValidationState state;
918             //fprintf(stderr,"check validity\n");
919             if ( !TestBlockValidity(state, *pblock, pindexPrev, false, false)) // invokes CC checks
920             {
921                 throw std::runtime_error("CreateNewBlock(): TestBlockValidity failed");
922             }
923             //fprintf(stderr,"valid\n");
924         }
925     }
926     //fprintf(stderr,"done new block\n");
927     return pblocktemplate.release();
928 }
929  
930 /*
931  #ifdef ENABLE_WALLET
932  boost::optional<CScript> GetMinerScriptPubKey(CReserveKey& reservekey)
933  #else
934  boost::optional<CScript> GetMinerScriptPubKey()
935  #endif
936  {
937  CKeyID keyID;
938  CBitcoinAddress addr;
939  if (addr.SetString(GetArg("-mineraddress", ""))) {
940  addr.GetKeyID(keyID);
941  } else {
942  #ifdef ENABLE_WALLET
943  CPubKey pubkey;
944  if (!reservekey.GetReservedKey(pubkey)) {
945  return boost::optional<CScript>();
946  }
947  keyID = pubkey.GetID();
948  #else
949  return boost::optional<CScript>();
950  #endif
951  }
952  
953  CScript scriptPubKey = CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
954  return scriptPubKey;
955  }
956  
957  #ifdef ENABLE_WALLET
958  CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey)
959  {
960  boost::optional<CScript> scriptPubKey = GetMinerScriptPubKey(reservekey);
961  #else
962  CBlockTemplate* CreateNewBlockWithKey()
963  {
964  boost::optional<CScript> scriptPubKey = GetMinerScriptPubKey();
965  #endif
966  
967  if (!scriptPubKey) {
968  return NULL;
969  }
970  return CreateNewBlock(*scriptPubKey);
971  }*/
972
973 //////////////////////////////////////////////////////////////////////////////
974 //
975 // Internal miner
976 //
977
978 #ifdef ENABLE_MINING
979
980 void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce)
981 {
982     // Update nExtraNonce
983     static uint256 hashPrevBlock;
984     if (hashPrevBlock != pblock->hashPrevBlock)
985     {
986         nExtraNonce = 0;
987         hashPrevBlock = pblock->hashPrevBlock;
988     }
989     ++nExtraNonce;
990     unsigned int nHeight = pindexPrev->GetHeight()+1; // Height first in coinbase required for block.version=2
991     CMutableTransaction txCoinbase(pblock->vtx[0]);
992     txCoinbase.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
993     assert(txCoinbase.vin[0].scriptSig.size() <= 100);
994     
995     pblock->vtx[0] = txCoinbase;
996     pblock->hashMerkleRoot = pblock->BuildMerkleTree();
997 }
998
999 #ifdef ENABLE_WALLET
1000 //////////////////////////////////////////////////////////////////////////////
1001 //
1002 // Internal miner
1003 //
1004
1005 CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, int32_t gpucount, bool isStake)
1006 {
1007     CPubKey pubkey; CScript scriptPubKey; uint8_t *ptr; int32_t i;
1008     if ( nHeight == 1 && ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 )
1009     {
1010         scriptPubKey = CScript() << ParseHex(ASSETCHAINS_OVERRIDE_PUBKEY) << OP_CHECKSIG;
1011     }
1012     else if ( USE_EXTERNAL_PUBKEY != 0 )
1013     {
1014         //fprintf(stderr,"use notary pubkey\n");
1015         scriptPubKey = CScript() << ParseHex(NOTARY_PUBKEY) << OP_CHECKSIG;
1016     }
1017     else
1018     {
1019         if (!isStake)
1020         {
1021             if (!reservekey.GetReservedKey(pubkey))
1022             {
1023                 return NULL;
1024             }
1025             scriptPubKey.resize(35);
1026             ptr = (uint8_t *)pubkey.begin();
1027             scriptPubKey[0] = 33;
1028             for (i=0; i<33; i++)
1029                 scriptPubKey[i+1] = ptr[i];
1030             scriptPubKey[34] = OP_CHECKSIG;
1031             //scriptPubKey = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
1032         }
1033     }
1034     return CreateNewBlock(scriptPubKey, gpucount, isStake);
1035 }
1036
1037 void komodo_broadcast(CBlock *pblock,int32_t limit)
1038 {
1039     int32_t n = 1;
1040     //fprintf(stderr,"broadcast new block t.%u\n",(uint32_t)time(NULL));
1041     {
1042         LOCK(cs_vNodes);
1043         BOOST_FOREACH(CNode* pnode, vNodes)
1044         {
1045             if ( pnode->hSocket == INVALID_SOCKET )
1046                 continue;
1047             if ( (rand() % n) == 0 )
1048             {
1049                 pnode->PushMessage("block", *pblock);
1050                 if ( n++ > limit )
1051                     break;
1052             }
1053         }
1054     }
1055     //fprintf(stderr,"finished broadcast new block t.%u\n",(uint32_t)time(NULL));
1056 }
1057
1058 static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
1059 #else
1060 static bool ProcessBlockFound(CBlock* pblock)
1061 #endif // ENABLE_WALLET
1062 {
1063     LogPrintf("%s\n", pblock->ToString());
1064     LogPrintf("generated %s height.%d\n", FormatMoney(pblock->vtx[0].vout[0].nValue),chainActive.LastTip()->GetHeight()+1);
1065     
1066     // Found a solution
1067     {
1068         if (pblock->hashPrevBlock != chainActive.LastTip()->GetBlockHash())
1069         {
1070             uint256 hash; int32_t i;
1071             hash = pblock->hashPrevBlock;
1072             for (i=31; i>=0; i--)
1073                 fprintf(stderr,"%02x",((uint8_t *)&hash)[i]);
1074             fprintf(stderr," <- prev (stale)\n");
1075             hash = chainActive.LastTip()->GetBlockHash();
1076             for (i=31; i>=0; i--)
1077                 fprintf(stderr,"%02x",((uint8_t *)&hash)[i]);
1078             fprintf(stderr," <- chainTip (stale)\n");
1079             
1080             return error("KomodoMiner: generated block is stale");
1081         }
1082     }
1083     
1084 #ifdef ENABLE_WALLET
1085     // Remove key from key pool
1086     if ( IS_KOMODO_NOTARY == 0 )
1087     {
1088         if (GetArg("-mineraddress", "").empty()) {
1089             // Remove key from key pool
1090             reservekey.KeepKey();
1091         }
1092     }
1093     // Track how many getdata requests this block gets
1094     //if ( 0 )
1095     {
1096         //fprintf(stderr,"lock cs_wallet\n");
1097         LOCK(wallet.cs_wallet);
1098         wallet.mapRequestCount[pblock->GetHash()] = 0;
1099     }
1100 #endif
1101     //fprintf(stderr,"process new block\n");
1102
1103     // Process this block the same as if we had received it from another node
1104     CValidationState state;
1105     if (!ProcessNewBlock(1,chainActive.LastTip()->GetHeight()+1,state, NULL, pblock, true, NULL))
1106         return error("KomodoMiner: ProcessNewBlock, block not accepted");
1107     
1108     TrackMinedBlock(pblock->GetHash());
1109     komodo_broadcast(pblock,16);
1110     return true;
1111 }
1112
1113 int32_t komodo_baseid(char *origbase);
1114 int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t *blocktimes,int32_t *nonzpkeysp,int32_t height);
1115 arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc);
1116 int32_t FOUND_BLOCK,KOMODO_MAYBEMINED;
1117 extern int32_t KOMODO_LASTMINED,KOMODO_INSYNC;
1118 int32_t roundrobin_delay;
1119 arith_uint256 HASHTarget,HASHTarget_POW;
1120 int32_t komodo_longestchain();
1121
1122 // wait for peers to connect
1123 void waitForPeers(const CChainParams &chainparams)
1124 {
1125     if (chainparams.MiningRequiresPeers())
1126     {
1127         bool fvNodesEmpty;
1128         {
1129             boost::this_thread::interruption_point();
1130             LOCK(cs_vNodes);
1131             fvNodesEmpty = vNodes.empty();
1132         }
1133         int longestchain = komodo_longestchain();
1134         int lastlongest = 0;
1135         if (fvNodesEmpty || IsNotInSync() || (longestchain != 0 && longestchain > chainActive.LastTip()->GetHeight()))
1136         {
1137             int loops = 0, blockDiff = 0, newDiff = 0;
1138             
1139             do {
1140                 if (fvNodesEmpty)
1141                 {
1142                     MilliSleep(1000 + rand() % 4000);
1143                     boost::this_thread::interruption_point();
1144                     LOCK(cs_vNodes);
1145                     fvNodesEmpty = vNodes.empty();
1146                     loops = 0;
1147                     blockDiff = 0;
1148                     lastlongest = 0;
1149                 }
1150                 else if ((newDiff = IsNotInSync()) > 0)
1151                 {
1152                     if (blockDiff != newDiff)
1153                     {
1154                         blockDiff = newDiff;
1155                     }
1156                     else
1157                     {
1158                         if (++loops <= 5)
1159                         {
1160                             MilliSleep(1000);
1161                         }
1162                         else break;
1163                     }
1164                     lastlongest = 0;
1165                 }
1166                 else if (!fvNodesEmpty && !IsNotInSync() && longestchain > chainActive.LastTip()->GetHeight())
1167                 {
1168                     // the only thing may be that we are seeing a long chain that we'll never get
1169                     // don't wait forever
1170                     if (lastlongest == 0)
1171                     {
1172                         MilliSleep(3000);
1173                         lastlongest = longestchain;
1174                     }
1175                 }
1176             } while (fvNodesEmpty || IsNotInSync());
1177             MilliSleep(100 + rand() % 400);
1178         }
1179     }
1180 }
1181
1182 #ifdef ENABLE_WALLET
1183 CBlockIndex *get_chainactive(int32_t height)
1184 {
1185     if ( chainActive.LastTip() != 0 )
1186     {
1187         if ( height <= chainActive.LastTip()->GetHeight() )
1188         {
1189             LOCK(cs_main);
1190             return(chainActive[height]);
1191         }
1192         // else fprintf(stderr,"get_chainactive height %d > active.%d\n",height,chainActive.Tip()->GetHeight());
1193     }
1194     //fprintf(stderr,"get_chainactive null chainActive.Tip() height %d\n",height);
1195     return(0);
1196 }
1197
1198 /*
1199  * When called, this checks to see if Verus daemon is running and available. If so, it calls to get the latest
1200  * notarization data and all information necessary to make a notarization transaction for the current chain, or the
1201  * Verus chain.
1202  */
1203 void static UpdateNotarizationData()
1204 {
1205
1206 }
1207
1208 /*
1209  * A separate thread to stake, while the miner threads mine.
1210  */
1211 void static VerusStaker(CWallet *pwallet)
1212 {
1213     LogPrintf("Verus staker thread started\n");
1214     RenameThread("verus-staker");
1215
1216     const CChainParams& chainparams = Params();
1217     auto consensusParams = chainparams.GetConsensus();
1218
1219     // Each thread has its own key
1220     CReserveKey reservekey(pwallet);
1221
1222     // Each thread has its own counter
1223     unsigned int nExtraNonce = 0;
1224
1225     uint8_t *script; uint64_t total,checktoshis; int32_t i,j;
1226
1227     while ( (ASSETCHAIN_INIT == 0 || KOMODO_INITDONE == 0) ) //chainActive.Tip()->GetHeight() != 235300 &&
1228     {
1229         sleep(1);
1230         if ( komodo_baseid(ASSETCHAINS_SYMBOL) < 0 )
1231             break;
1232     }
1233
1234     // try a nice clean peer connection to start
1235     CBlockIndex *pindexPrev, *pindexCur;
1236     do {
1237         pindexPrev = chainActive.LastTip();
1238         MilliSleep(5000 + rand() % 5000);
1239         waitForPeers(chainparams);
1240         pindexCur = chainActive.LastTip();
1241     } while (pindexPrev != pindexCur);
1242
1243     try {
1244         static int32_t lastStakingHeight = 0;
1245
1246         while (true)
1247         {
1248             waitForPeers(chainparams);
1249             CBlockIndex* pindexPrev = chainActive.LastTip();
1250
1251             // Create new block
1252             unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
1253
1254             if ( Mining_height != pindexPrev->GetHeight()+1 )
1255             {
1256                 Mining_height = pindexPrev->GetHeight()+1;
1257                 Mining_start = (uint32_t)time(NULL);
1258             }
1259
1260             if ( Mining_height != lastStakingHeight )
1261             {
1262                 printf("Staking height %d for %s\n", Mining_height, ASSETCHAINS_SYMBOL);
1263                 lastStakingHeight = Mining_height;
1264             }
1265
1266             // Check for stop or if block needs to be rebuilt
1267             boost::this_thread::interruption_point();
1268
1269             // try to stake a block
1270             CBlockTemplate *ptr = NULL;
1271             if (Mining_height > VERUS_MIN_STAKEAGE)
1272                 ptr = CreateNewBlockWithKey(reservekey, Mining_height, 0, true);
1273
1274             if ( ptr == 0 )
1275             {
1276                 // wait to try another staking block until after the tip moves again
1277                 while ( chainActive.LastTip() == pindexPrev )
1278                     MilliSleep(250);
1279                 continue;
1280             }
1281
1282             unique_ptr<CBlockTemplate> pblocktemplate(ptr);
1283             if (!pblocktemplate.get())
1284             {
1285                 if (GetArg("-mineraddress", "").empty()) {
1286                     LogPrintf("Error in %s staker: Keypool ran out, please call keypoolrefill before restarting the mining thread\n",
1287                               ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
1288                 } else {
1289                     // Should never reach here, because -mineraddress validity is checked in init.cpp
1290                     LogPrintf("Error in %s staker: Invalid %s -mineraddress\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO], ASSETCHAINS_SYMBOL);
1291                 }
1292                 return;
1293             }
1294
1295             CBlock *pblock = &pblocktemplate->block;
1296             LogPrintf("Staking with %u transactions in block (%u bytes)\n", pblock->vtx.size(),::GetSerializeSize(*pblock,SER_NETWORK,PROTOCOL_VERSION));
1297             //
1298             // Search
1299             //
1300             int64_t nStart = GetTime();
1301
1302             // we don't use this, but IncrementExtraNonce is the function that builds the merkle tree
1303             unsigned int nExtraNonce = 0;
1304             IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1305
1306             // update PBaaS header
1307             if (CConstVerusSolutionVector::activationHeight.ActiveVersion(Mining_height) == CActivationHeight::SOLUTION_VERUSV3)
1308             {
1309                 uint256 mmvRoot;
1310                 {
1311                     LOCK(cs_main);
1312                     // set the PBaaS header
1313                     ChainMerkleMountainView mmv = chainActive.GetMMV();
1314                     mmvRoot = mmv.GetRoot();
1315                 }
1316                 pblock->AddUpdatePBaaSHeader(mmvRoot);
1317             }
1318
1319             if (vNodes.empty() && chainparams.MiningRequiresPeers())
1320             {
1321                 if ( Mining_height > ASSETCHAINS_MINHEIGHT )
1322                 {
1323                     fprintf(stderr,"no nodes, attempting reconnect\n");
1324                     continue;
1325                 }
1326             }
1327
1328             if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
1329             {
1330                 fprintf(stderr,"timeout, retrying\n");
1331                 continue;
1332             }
1333
1334             if ( pindexPrev != chainActive.LastTip() )
1335             {
1336                 printf("Block %d added to chain\n", chainActive.LastTip()->GetHeight());
1337                 MilliSleep(250);
1338                 continue;
1339             }
1340
1341             int32_t unlockTime = komodo_block_unlocktime(Mining_height);
1342             int64_t subsidy = (int64_t)(pblock->vtx[0].vout[0].nValue);
1343
1344             uint256 hashTarget = ArithToUint256(arith_uint256().SetCompact(pblock->nBits));
1345
1346             pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams);
1347
1348             UpdateTime(pblock, consensusParams, pindexPrev);
1349
1350             ProcessBlockFound(pblock, *pwallet, reservekey);
1351
1352             LogPrintf("Using %s algorithm:\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
1353             LogPrintf("Staked block found  \n  hash: %s  \ntarget: %s\n", pblock->GetHash().GetHex(), hashTarget.GetHex());
1354             printf("Found block %d \n", Mining_height );
1355             printf("staking reward %.8f %s!\n", (double)subsidy / (double)COIN, ASSETCHAINS_SYMBOL);
1356             arith_uint256 post;
1357             post.SetCompact(pblock->GetVerusPOSTarget());
1358             pindexPrev = get_chainactive(Mining_height - 100);
1359             CTransaction &sTx = pblock->vtx[pblock->vtx.size()-1];
1360             printf("POS hash: %s  \ntarget:   %s\n", 
1361                 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());
1362             if (unlockTime > Mining_height && subsidy >= ASSETCHAINS_TIMELOCKGTE)
1363                 printf("- timelocked until block %i\n", unlockTime);
1364             else
1365                 printf("\n");
1366
1367             // Check for stop or if block needs to be rebuilt
1368             boost::this_thread::interruption_point();
1369
1370             sleep(3);
1371
1372             // In regression test mode, stop mining after a block is found.
1373             if (chainparams.MineBlocksOnDemand()) {
1374                 throw boost::thread_interrupted();
1375             }
1376         }
1377     }
1378     catch (const boost::thread_interrupted&)
1379     {
1380         LogPrintf("VerusStaker terminated\n");
1381         throw;
1382     }
1383     catch (const std::runtime_error &e)
1384     {
1385         LogPrintf("VerusStaker runtime error: %s\n", e.what());
1386         return;
1387     }
1388 }
1389
1390 typedef bool (*minefunction)(CBlockHeader &bh, CVerusHashV2bWriter &vhw, uint256 &finalHash, uint256 &target, uint64_t start, uint64_t *count);
1391 bool mine_verus_v2(CBlockHeader &bh, CVerusHashV2bWriter &vhw, uint256 &finalHash, uint256 &target, uint64_t start, uint64_t *count);
1392 bool mine_verus_v2_port(CBlockHeader &bh, CVerusHashV2bWriter &vhw, uint256 &finalHash, uint256 &target, uint64_t start, uint64_t *count);
1393
1394 void static BitcoinMiner_noeq(CWallet *pwallet)
1395 #else
1396 void static BitcoinMiner_noeq()
1397 #endif
1398 {
1399     LogPrintf("%s miner started\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
1400     RenameThread("verushash-miner");
1401
1402 #ifdef ENABLE_WALLET
1403     // Each thread has its own key
1404     CReserveKey reservekey(pwallet);
1405 #endif
1406
1407     const CChainParams& chainparams = Params();
1408     // Each thread has its own counter
1409     unsigned int nExtraNonce = 0;
1410
1411     uint8_t *script; uint64_t total,checktoshis; int32_t i,j;
1412
1413     while ( (ASSETCHAIN_INIT == 0 || KOMODO_INITDONE == 0) ) //chainActive.Tip()->GetHeight() != 235300 &&
1414     {
1415         sleep(1);
1416         if ( komodo_baseid(ASSETCHAINS_SYMBOL) < 0 )
1417             break;
1418     }
1419
1420     SetThreadPriority(THREAD_PRIORITY_LOWEST);
1421
1422     // try a nice clean peer connection to start
1423     CBlockIndex *pindexPrev, *pindexCur;
1424     do {
1425         pindexPrev = chainActive.LastTip();
1426         MilliSleep(5000 + rand() % 5000);
1427         waitForPeers(chainparams);
1428         pindexCur = chainActive.LastTip();
1429     } while (pindexPrev != pindexCur);
1430
1431     // this will not stop printing more than once in all cases, but it will allow us to print in all cases
1432     // and print duplicates rarely without having to synchronize
1433     static CBlockIndex *lastChainTipPrinted;
1434     static int32_t lastMiningHeight = 0;
1435
1436     miningTimer.start();
1437
1438     try {
1439         printf("Mining %s with %s\n", ASSETCHAINS_SYMBOL, ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
1440
1441         // v2 hash writer
1442         CVerusHashV2bWriter ss2 = CVerusHashV2bWriter(SER_GETHASH, PROTOCOL_VERSION);
1443
1444         while (true)
1445         {
1446             miningTimer.stop();
1447             waitForPeers(chainparams);
1448
1449             pindexPrev = chainActive.LastTip();
1450
1451             // prevent forking on startup before the diff algorithm kicks in,
1452             // but only for a startup Verus test chain. PBaaS chains have the difficulty inherited from
1453             // their parent
1454             if (chainparams.MiningRequiresPeers() && ((IsVerusActive() && pindexPrev->GetHeight() < 50) || pindexPrev != chainActive.LastTip()))
1455             {
1456                 do {
1457                     pindexPrev = chainActive.LastTip();
1458                     MilliSleep(3000 + rand() % 3000);
1459                 } while (pindexPrev != chainActive.LastTip());
1460             }
1461
1462             // Create new block
1463             unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
1464             if ( Mining_height != pindexPrev->GetHeight()+1 )
1465             {
1466                 Mining_height = pindexPrev->GetHeight()+1;
1467                 if (lastMiningHeight != Mining_height)
1468                 {
1469                     lastMiningHeight = Mining_height;
1470                     printf("Mining height %d\n", Mining_height);
1471                 }
1472                 Mining_start = (uint32_t)time(NULL);
1473             }
1474
1475             miningTimer.start();
1476
1477 #ifdef ENABLE_WALLET
1478             CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, Mining_height, 0);
1479 #else
1480             CBlockTemplate *ptr = CreateNewBlockWithKey();
1481 #endif
1482             if ( ptr == 0 )
1483             {
1484                 static uint32_t counter;
1485                 if ( (counter++ < 10) || (counter % 40 == 0) )
1486                     fprintf(stderr,"Unable to create valid block... will continue to try\n");
1487                 MilliSleep(500);
1488                 continue;
1489             }
1490
1491             unique_ptr<CBlockTemplate> pblocktemplate(ptr);
1492             if (!pblocktemplate.get())
1493             {
1494                 if (GetArg("-mineraddress", "").empty()) {
1495                     LogPrintf("Error in %s miner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n",
1496                               ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
1497                 } else {
1498                     // Should never reach here, because -mineraddress validity is checked in init.cpp
1499                     LogPrintf("Error in %s miner: Invalid %s -mineraddress\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO], ASSETCHAINS_SYMBOL);
1500                 }
1501                 return;
1502             }
1503             CBlock *pblock = &pblocktemplate->block;
1504
1505             uint32_t savebits;
1506             bool mergeMining = false;
1507             savebits = pblock->nBits;
1508
1509             bool verusHashV2 = pblock->nVersion == CBlockHeader::VERUS_V2;
1510             bool verusSolutionV3 = CConstVerusSolutionVector::Version(pblock->nSolution) == CActivationHeight::SOLUTION_VERUSV3;
1511
1512             if ( ASSETCHAINS_SYMBOL[0] != 0 )
1513             {
1514                 if ( ASSETCHAINS_REWARD[0] == 0 && !ASSETCHAINS_LASTERA )
1515                 {
1516                     if ( pblock->vtx.size() == 1 && pblock->vtx[0].vout.size() == 1 && Mining_height > ASSETCHAINS_MINHEIGHT )
1517                     {
1518                         static uint32_t counter;
1519                         if ( counter++ < 10 )
1520                             fprintf(stderr,"skip generating %s on-demand block, no tx avail\n",ASSETCHAINS_SYMBOL);
1521                         sleep(10);
1522                         continue;
1523                     } else fprintf(stderr,"%s vouts.%d mining.%d vs %d\n",ASSETCHAINS_SYMBOL,(int32_t)pblock->vtx[0].vout.size(),Mining_height,ASSETCHAINS_MINHEIGHT);
1524                 }
1525             }
1526
1527             // this builds the Merkle tree
1528             IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
1529
1530             // update PBaaS header
1531             if (verusSolutionV3)
1532             {
1533                 uint256 mmvRoot;
1534                 {
1535                     LOCK(cs_main);
1536                     ChainMerkleMountainView mmv = chainActive.GetMMV();
1537                     mmvRoot = mmv.GetRoot();
1538                 }
1539                 pblock->AddUpdatePBaaSHeader(mmvRoot);
1540
1541                 if (IsVerusActive())
1542                 {
1543                     // combine all merge mined headers into this header
1544                     // and get the easiest target of all chains in savebits
1545                     if (!(savebits = ConnectedChains.CombineBlocks(*pblock)))
1546                     {
1547                         savebits = pblock->nBits;
1548                     }
1549
1550                     LOCK(cs_main);
1551                     // TODO: REMOVE OR COMMENT TESTS
1552                     // tests to validate a few transactions and all past blocks
1553                     ChainMerkleMountainView mmv = chainActive.GetMMV();
1554                     mmvRoot = mmv.GetRoot();
1555                     for (uint32_t i = 1; i <= pindexPrev->GetHeight(); i += 10)
1556                     {
1557                         CBlockIndex *pindex = chainActive[i - 1];
1558                         mmv.resize(i);
1559                         uint256 testRoot = mmv.GetRoot();
1560                         uint32_t testHeight = ((unsigned char *)&testRoot)[0] < i ? (i - ((unsigned char *)&testRoot)[0]) - 1 : i - 1;
1561                         CMerkleBranch branchMerkle, branchBlock;
1562                         chainActive.GetBlockProof(mmv, branchBlock, testHeight);
1563                         chainActive.GetMerkleProof(mmv, branchMerkle, testHeight);
1564                         uint256 merkleAnswer = branchMerkle.SafeCheck(chainActive[testHeight]->hashMerkleRoot);
1565                         uint256 blockAnswer = branchBlock.SafeCheck(chainActive[testHeight]->GetBlockHash());
1566                         if (merkleAnswer != testRoot)
1567                         {
1568                             printf("Failed merkle proof at testheight: %u\nexpected:   %s\ncalculated: %s\n", testHeight, testRoot.GetHex().c_str(), merkleAnswer.GetHex().c_str());
1569                             printf("Bits for left (0) and right (1): \n");
1570                             std::vector<unsigned char> proofBits = ChainMerkleMountainView::GetProofBits(testHeight, i);
1571                             printf("right\n");
1572                             for (auto bit : proofBits)
1573                             {
1574                                 printf("%s\n", bit ? "left" : "right");
1575                             }
1576                         }
1577                         if (blockAnswer != testRoot)
1578                         {
1579                             printf("Failed block proof at testheight: %u\nexpected:   %s\ncalculated: %s\n", testHeight, testRoot.GetHex().c_str(), blockAnswer.GetHex().c_str());
1580                             printf("Bits for left (0) and right (1): \n");
1581                             std::vector<unsigned char> proofBits = ChainMerkleMountainView::GetProofBits(testHeight, i);
1582                             printf("left\n");
1583                             for (auto bit : proofBits)
1584                             {
1585                                 printf("%s\n", bit ? "left" : "right");
1586                             }
1587                         }
1588                         const CMMRPowerNode *ppower = mmv.GetRootNode();
1589                         if (!ppower || ppower->Work() != pindex->chainPower.chainWork)
1590                         {
1591                             printf("Work did not match:\nexpected:   %s\ncalculated: %s\n", ArithToUint256(pindex->chainPower.chainWork).GetHex().c_str(), ArithToUint256(ppower->Work()).GetHex().c_str());
1592                         }
1593                         if (!ppower || ppower->Stake() != pindex->chainPower.chainStake)
1594                         {
1595                             printf("Stake did not match:\nexpected:   %s\ncalculated: %s\n", ArithToUint256(pindex->chainPower.chainStake).GetHex().c_str(), ArithToUint256(ppower->Stake()).GetHex().c_str());
1596                         }
1597                     }
1598                     // END TESTS
1599                 }
1600                 else
1601                 {
1602                     // submit the block for merge mining if Verus is present
1603                     // otherwise, mine solo
1604                     if (ConnectedChains.IsVerusPBaaSAvailable())
1605                     {
1606
1607                         UniValue params(UniValue::VARR);
1608                         params.push_back(EncodeHexBlk(*pblock));
1609                         params.push_back(ASSETCHAINS_SYMBOL);
1610                         params.push_back(PBAAS_HOST);
1611                         params.push_back(PBAAS_PORT);
1612                         params.push_back(PBAAS_USERPASS);
1613                         try
1614                         {
1615                             params = RPCCallRoot("addmergedblock", params);
1616                         } catch (std::exception e)
1617                         {
1618                             printf("Failed to connect to %s chain\n", ConnectedChains.notaryChain.chainDefinition.name.c_str());
1619                             params = UniValue(e.what());
1620                         }
1621                         if (mergeMining = params.isNull())
1622                         {
1623                             printf("Merge mining -- deferring to %s as the actual mining chain\n", ConnectedChains.notaryChain.chainDefinition.name.c_str());
1624                         }
1625                     }
1626                 }
1627             }
1628
1629             LogPrintf("Running %s miner with %u transactions in block (%u bytes)\n",ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO],
1630                        pblock->vtx.size(),::GetSerializeSize(*pblock,SER_NETWORK,PROTOCOL_VERSION));
1631             //
1632             // Search
1633             //
1634             int64_t nStart = GetTime();
1635
1636             arith_uint256 hashTarget = arith_uint256().SetCompact(savebits);
1637             uint256 uintTarget = ArithToUint256(hashTarget);
1638
1639             arith_uint256 ourTarget;
1640             ourTarget.SetCompact(pblock->nBits);
1641
1642             Mining_start = 0;
1643
1644             if ( pindexPrev != chainActive.LastTip() )
1645             {
1646                 if (lastChainTipPrinted != chainActive.LastTip())
1647                 {
1648                     lastChainTipPrinted = chainActive.LastTip();
1649                     printf("Block %d added to chain\n", lastChainTipPrinted->GetHeight());
1650                 }
1651                 MilliSleep(100);
1652                 continue;
1653             }
1654
1655             if ( ASSETCHAINS_STAKED != 0 )
1656             {
1657                 int32_t percPoS,z;
1658                 hashTarget = komodo_PoWtarget(&percPoS,hashTarget,Mining_height,ASSETCHAINS_STAKED);
1659                 for (z=31; z>=0; z--)
1660                     fprintf(stderr,"%02x",((uint8_t *)&hashTarget)[z]);
1661                 fprintf(stderr," PoW for staked coin PoS %d%% vs target %d%%\n",percPoS,(int32_t)ASSETCHAINS_STAKED);
1662             }
1663
1664             uint64_t count, hashesToGo = 0;
1665             if (!verusHashV2)
1666             {
1667                 // must not be in sync
1668                 printf("Mining on incorrect block version.\n");
1669                 sleep(2);
1670                 continue;
1671             }
1672
1673             count = ((ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] >> 3) + 1) / ASSETCHAINS_HASHESPERROUND[ASSETCHAINS_ALGO];
1674             CVerusHashV2 *vh2 = &ss2.GetState();
1675             u128 *hashKey;
1676             verusclhasher &vclh = vh2->vclh;
1677             minefunction mine_verus;
1678             mine_verus = IsCPUVerusOptimized() ? &mine_verus_v2 : &mine_verus_v2_port;
1679
1680             while (true)
1681             {
1682                 uint256 hashResult = uint256();
1683
1684                 unsigned char *curBuf;
1685
1686                 if (mergeMining)
1687                 {
1688                     // loop for about one minute before refreshing the block
1689                     for (uint64_t i = 0; i < 240; i++)
1690                     {
1691                         boost::this_thread::interruption_point();
1692                         MilliSleep(250);
1693
1694                         if (vNodes.empty() && chainparams.MiningRequiresPeers())
1695                         {
1696                             if ( Mining_height > ASSETCHAINS_MINHEIGHT )
1697                             {
1698                                 fprintf(stderr,"no nodes, attempting reconnect\n");
1699                                 break;
1700                             }
1701                         }
1702
1703                         if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
1704                         {
1705                             break;
1706                         }
1707
1708                         if ( pindexPrev != chainActive.LastTip() )
1709                         {
1710                             if (lastChainTipPrinted != chainActive.LastTip())
1711                             {
1712                                 lastChainTipPrinted = chainActive.LastTip();
1713                                 printf("Block %d added to chain\n\n", lastChainTipPrinted->GetHeight());
1714                             }
1715                             break;
1716                         }
1717                     }
1718                 }
1719                 else
1720                 {
1721                     // check NONCEMASK at a time
1722                     for (uint64_t i = 0; i < count; i++)
1723                     {
1724                         // this is the merge mining loop, which enables us to drop out and queue a header anytime we earn a block that is good enough for a
1725                         // merge mined block, but not our own
1726                         uint64_t totalDone = 0;
1727                         bool blockFound;
1728                         arith_uint256 arithHash;
1729                         do
1730                         {
1731                             // hashesToGo gets updated with actual number run for metrics
1732                             hashesToGo = ASSETCHAINS_HASHESPERROUND[ASSETCHAINS_ALGO];
1733                             uint64_t start = i * hashesToGo;
1734                             hashesToGo -= totalDone;
1735
1736                             if (verusSolutionV3)
1737                             {
1738                                 // mine on canonical header for merge mining
1739                                 CPBaaSPreHeader savedHeader(*pblock);
1740                                 pblock->ClearNonCanonicalData();
1741                                 blockFound = (*mine_verus)(*pblock, ss2, hashResult, uintTarget, start, &hashesToGo);
1742                                 savedHeader.SetBlockData(*pblock);
1743                             }
1744                             else
1745                             {
1746                                 blockFound = (*mine_verus)(*pblock, ss2, hashResult, uintTarget, start, &hashesToGo);
1747                             }
1748
1749                             arithHash = UintToArith256(hashResult);
1750                             totalDone += hashesToGo;
1751                             if (blockFound && IsVerusActive())
1752                             {
1753                                 ConnectedChains.QueueNewBlockHeader(*pblock);
1754                                 if (arithHash > ourTarget)
1755                                 {
1756                                     // all blocks qualified with this hash will be submitted
1757                                     // until we redo the block, we might as well not try again with anything over this hash
1758                                     hashTarget = arithHash;
1759                                     uintTarget = ArithToUint256(hashTarget);
1760                                 }
1761                             }
1762                             hashesToGo = totalDone;
1763                         } while (blockFound && arithHash > ourTarget);
1764
1765                         if (!blockFound || arithHash > ourTarget)
1766                         {
1767                             // Check for stop or if block needs to be rebuilt
1768                             boost::this_thread::interruption_point();
1769                             if ( pindexPrev != chainActive.LastTip() )
1770                             {
1771                                 if (lastChainTipPrinted != chainActive.LastTip())
1772                                 {
1773                                     lastChainTipPrinted = chainActive.LastTip();
1774                                     printf("Block %d added to chain\n", lastChainTipPrinted->GetHeight());
1775                                 }
1776                                 break;
1777                             }
1778                             else
1779                             {
1780                                 {
1781                                     LOCK(cs_metrics);
1782                                     nHashCount += hashesToGo;
1783                                 }
1784                                 continue;
1785                             }
1786                         }
1787                         else
1788                         {
1789                             // Check for stop or if block needs to be rebuilt
1790                             boost::this_thread::interruption_point();
1791
1792                             if (pblock->nSolution.size() != 1344)
1793                             {
1794                                 LogPrintf("ERROR: Block solution is not 1344 bytes as it should be");
1795                                 break;
1796                             }
1797
1798                             SetThreadPriority(THREAD_PRIORITY_NORMAL);
1799
1800                             int32_t unlockTime = komodo_block_unlocktime(Mining_height);
1801                             int64_t subsidy = (int64_t)(pblock->vtx[0].vout[0].nValue);
1802
1803 #ifdef VERUSHASHDEBUG
1804                             std::string validateStr = hashResult.GetHex();
1805                             std::string hashStr = pblock->GetHash().GetHex();
1806                             uint256 *bhalf1 = (uint256 *)vh2->CurBuffer();
1807                             uint256 *bhalf2 = bhalf1 + 1;
1808 #else
1809                             std::string hashStr = hashResult.GetHex();
1810 #endif
1811
1812                             LogPrintf("Using %s algorithm:\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
1813                             LogPrintf("proof-of-work found  \n  hash: %s  \ntarget: %s\n", hashStr, ArithToUint256(ourTarget).GetHex());
1814                             printf("Found block %d \n", Mining_height );
1815                             printf("mining reward %.8f %s!\n", (double)subsidy / (double)COIN, ASSETCHAINS_SYMBOL);
1816 #ifdef VERUSHASHDEBUG
1817                             printf("  hash: %s\n   val: %s  \ntarget: %s\n\n", hashStr.c_str(), validateStr.c_str(), ArithToUint256(ourTarget).GetHex().c_str());
1818                             printf("intermediate %lx\n", intermediate);
1819                             printf("Curbuf: %s%s\n", bhalf1->GetHex().c_str(), bhalf2->GetHex().c_str());
1820                             bhalf1 = (uint256 *)verusclhasher_key.get();
1821                             bhalf2 = bhalf1 + ((vh2->vclh.keyMask + 1) >> 5);
1822                             printf("   Key: %s%s\n", bhalf1->GetHex().c_str(), bhalf2->GetHex().c_str());
1823 #else
1824                             printf("  hash: %s\ntarget: %s", hashStr.c_str(), ArithToUint256(ourTarget).GetHex().c_str());
1825 #endif
1826                             if (unlockTime > Mining_height && subsidy >= ASSETCHAINS_TIMELOCKGTE)
1827                                 printf(" - timelocked until block %i\n", unlockTime);
1828                             else
1829                                 printf("\n");
1830 #ifdef ENABLE_WALLET
1831                             ProcessBlockFound(pblock, *pwallet, reservekey);
1832 #else
1833                             ProcessBlockFound(pblock);
1834 #endif
1835                             SetThreadPriority(THREAD_PRIORITY_LOWEST);
1836                             break;
1837                         }
1838                     }
1839
1840                     {
1841                         LOCK(cs_metrics);
1842                         nHashCount += hashesToGo;
1843                     }
1844                 }
1845                 
1846
1847                 // Check for stop or if block needs to be rebuilt
1848                 boost::this_thread::interruption_point();
1849
1850                 if (vNodes.empty() && chainparams.MiningRequiresPeers())
1851                 {
1852                     if ( Mining_height > ASSETCHAINS_MINHEIGHT )
1853                     {
1854                         fprintf(stderr,"no nodes, attempting reconnect\n");
1855                         break;
1856                     }
1857                 }
1858
1859                 if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
1860                 {
1861                     fprintf(stderr,"timeout, retrying\n");
1862                     break;
1863                 }
1864
1865                 if ( pindexPrev != chainActive.LastTip() )
1866                 {
1867                     if (lastChainTipPrinted != chainActive.LastTip())
1868                     {
1869                         lastChainTipPrinted = chainActive.LastTip();
1870                         printf("Block %d added to chain\n\n", lastChainTipPrinted->GetHeight());
1871                     }
1872                     break;
1873                 }
1874
1875 #ifdef _WIN32
1876                 printf("%llu mega hashes complete - working\n", ((ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] >> 3) + 1) / 1048576);
1877 #else
1878                 printf("%lu mega hashes complete - working\n", ((ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] >> 3) + 1) / 1048576);
1879 #endif
1880                 break;
1881
1882             }
1883         }
1884     }
1885     catch (const boost::thread_interrupted&)
1886     {
1887         miningTimer.stop();
1888         LogPrintf("%s miner terminated\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
1889         throw;
1890     }
1891     catch (const std::runtime_error &e)
1892     {
1893         miningTimer.stop();
1894         LogPrintf("%s miner runtime error: %s\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO], e.what());
1895         return;
1896     }
1897     miningTimer.stop();
1898 }
1899
1900 #ifdef ENABLE_WALLET
1901 void static BitcoinMiner(CWallet *pwallet)
1902 #else
1903 void static BitcoinMiner()
1904 #endif
1905 {
1906     LogPrintf("KomodoMiner started\n");
1907     SetThreadPriority(THREAD_PRIORITY_LOWEST);
1908     RenameThread("komodo-miner");
1909     const CChainParams& chainparams = Params();
1910     
1911 #ifdef ENABLE_WALLET
1912     // Each thread has its own key
1913     CReserveKey reservekey(pwallet);
1914 #endif
1915     
1916     // Each thread has its own counter
1917     unsigned int nExtraNonce = 0;
1918     
1919     unsigned int n = chainparams.EquihashN();
1920     unsigned int k = chainparams.EquihashK();
1921     uint8_t *script; uint64_t total,checktoshis; int32_t i,j,gpucount=KOMODO_MAXGPUCOUNT,notaryid = -1;
1922     while ( (ASSETCHAIN_INIT == 0 || KOMODO_INITDONE == 0) )
1923     {
1924         sleep(1);
1925         if ( komodo_baseid(ASSETCHAINS_SYMBOL) < 0 )
1926             break;
1927     }
1928     if ( ASSETCHAINS_SYMBOL[0] == 0 )
1929         komodo_chosennotary(&notaryid,chainActive.LastTip()->GetHeight(),NOTARY_PUBKEY33,(uint32_t)chainActive.LastTip()->GetBlockTime());
1930     if ( notaryid != My_notaryid )
1931         My_notaryid = notaryid;
1932     std::string solver;
1933     //if ( notaryid >= 0 || ASSETCHAINS_SYMBOL[0] != 0 )
1934     solver = "tromp";
1935     //else solver = "default";
1936     assert(solver == "tromp" || solver == "default");
1937     LogPrint("pow", "Using Equihash solver \"%s\" with n = %u, k = %u\n", solver, n, k);
1938     if ( ASSETCHAINS_SYMBOL[0] != 0 )
1939         fprintf(stderr,"notaryid.%d Mining.%s with %s\n",notaryid,ASSETCHAINS_SYMBOL,solver.c_str());
1940     std::mutex m_cs;
1941     bool cancelSolver = false;
1942     boost::signals2::connection c = uiInterface.NotifyBlockTip.connect(
1943                                                                        [&m_cs, &cancelSolver](const uint256& hashNewTip) mutable {
1944                                                                            std::lock_guard<std::mutex> lock{m_cs};
1945                                                                            cancelSolver = true;
1946                                                                        }
1947                                                                        );
1948     miningTimer.start();
1949     
1950     try {
1951         if ( ASSETCHAINS_SYMBOL[0] != 0 )
1952             fprintf(stderr,"try %s Mining with %s\n",ASSETCHAINS_SYMBOL,solver.c_str());
1953         while (true)
1954         {
1955             if (chainparams.MiningRequiresPeers()) //chainActive.LastTip()->GetHeight() != 235300 &&
1956             {
1957                 //if ( ASSETCHAINS_SEED != 0 && chainActive.LastTip()->GetHeight() < 100 )
1958                 //    break;
1959                 // Busy-wait for the network to come online so we don't waste time mining
1960                 // on an obsolete chain. In regtest mode we expect to fly solo.
1961                 miningTimer.stop();
1962                 do {
1963                     bool fvNodesEmpty;
1964                     {
1965                         //LOCK(cs_vNodes);
1966                         fvNodesEmpty = vNodes.empty();
1967                     }
1968                     if (!fvNodesEmpty )//&& !IsInitialBlockDownload())
1969                         break;
1970                     MilliSleep(15000);
1971                     //fprintf(stderr,"fvNodesEmpty %d IsInitialBlockDownload(%s) %d\n",(int32_t)fvNodesEmpty,ASSETCHAINS_SYMBOL,(int32_t)IsInitialBlockDownload());
1972                     
1973                 } while (true);
1974                 //fprintf(stderr,"%s Found peers\n",ASSETCHAINS_SYMBOL);
1975                 miningTimer.start();
1976             }
1977             //
1978             // Create new block
1979             //
1980             unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
1981             CBlockIndex* pindexPrev = chainActive.LastTip();
1982             if ( Mining_height != pindexPrev->GetHeight()+1 )
1983             {
1984                 Mining_height = pindexPrev->GetHeight()+1;
1985                 Mining_start = (uint32_t)time(NULL);
1986             }
1987             if ( ASSETCHAINS_SYMBOL[0] != 0 && ASSETCHAINS_STAKED == 0 )
1988             {
1989                 //fprintf(stderr,"%s create new block ht.%d\n",ASSETCHAINS_SYMBOL,Mining_height);
1990                 //sleep(3);
1991             }
1992
1993 #ifdef ENABLE_WALLET
1994             // notaries always default to staking
1995             CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, pindexPrev->GetHeight()+1, gpucount, ASSETCHAINS_STAKED != 0 && GetArg("-genproclimit", 0) == 0);
1996 #else
1997             CBlockTemplate *ptr = CreateNewBlockWithKey();
1998 #endif
1999             if ( ptr == 0 )
2000             {
2001                 static uint32_t counter;
2002                 if ( counter++ < 100 && ASSETCHAINS_STAKED == 0 )
2003                     fprintf(stderr,"created illegal block, retry\n");
2004                 sleep(1);
2005                 continue;
2006             }
2007             //fprintf(stderr,"get template\n");
2008             unique_ptr<CBlockTemplate> pblocktemplate(ptr);
2009             if (!pblocktemplate.get())
2010             {
2011                 if (GetArg("-mineraddress", "").empty()) {
2012                     LogPrintf("Error in KomodoMiner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n");
2013                 } else {
2014                     // Should never reach here, because -mineraddress validity is checked in init.cpp
2015                     LogPrintf("Error in KomodoMiner: Invalid -mineraddress\n");
2016                 }
2017                 return;
2018             }
2019             CBlock *pblock = &pblocktemplate->block;
2020             if ( ASSETCHAINS_SYMBOL[0] != 0 )
2021             {
2022                 if ( ASSETCHAINS_REWARD[0] == 0 && !ASSETCHAINS_LASTERA )
2023                 {
2024                     if ( pblock->vtx.size() == 1 && pblock->vtx[0].vout.size() == 1 && Mining_height > ASSETCHAINS_MINHEIGHT )
2025                     {
2026                         static uint32_t counter;
2027                         if ( counter++ < 10 )
2028                             fprintf(stderr,"skip generating %s on-demand block, no tx avail\n",ASSETCHAINS_SYMBOL);
2029                         sleep(10);
2030                         continue;
2031                     } else fprintf(stderr,"%s vouts.%d mining.%d vs %d\n",ASSETCHAINS_SYMBOL,(int32_t)pblock->vtx[0].vout.size(),Mining_height,ASSETCHAINS_MINHEIGHT);
2032                 }
2033             }
2034             IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
2035             //fprintf(stderr,"Running KomodoMiner.%s with %u transactions in block\n",solver.c_str(),(int32_t)pblock->vtx.size());
2036             LogPrintf("Running KomodoMiner.%s with %u transactions in block (%u bytes)\n",solver.c_str(),pblock->vtx.size(),::GetSerializeSize(*pblock,SER_NETWORK,PROTOCOL_VERSION));
2037             //
2038             // Search
2039             //
2040             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();
2041             pblock->nBits         = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus());
2042             savebits = pblock->nBits;
2043             HASHTarget = arith_uint256().SetCompact(savebits);
2044             roundrobin_delay = ROUNDROBIN_DELAY;
2045             if ( ASSETCHAINS_SYMBOL[0] == 0 && notaryid >= 0 )
2046             {
2047                 j = 65;
2048                 if ( (Mining_height >= 235300 && Mining_height < 236000) || (Mining_height % KOMODO_ELECTION_GAP) > 64 || (Mining_height % KOMODO_ELECTION_GAP) == 0 || Mining_height > 1000000 )
2049                 {
2050                     int32_t dispflag = 0;
2051                     if ( notaryid <= 3 || notaryid == 32 || (notaryid >= 43 && notaryid <= 45) &&notaryid == 51 || notaryid == 52 || notaryid == 56 || notaryid == 57 )
2052                         dispflag = 1;
2053                     komodo_eligiblenotary(pubkeys,mids,blocktimes,&nonzpkeys,pindexPrev->GetHeight());
2054                     if ( nonzpkeys > 0 )
2055                     {
2056                         for (i=0; i<33; i++)
2057                             if( pubkeys[0][i] != 0 )
2058                                 break;
2059                         if ( i == 33 )
2060                             externalflag = 1;
2061                         else externalflag = 0;
2062                         if ( IS_KOMODO_NOTARY != 0 )
2063                         {
2064                             for (i=1; i<66; i++)
2065                                 if ( memcmp(pubkeys[i],pubkeys[0],33) == 0 )
2066                                     break;
2067                             if ( externalflag == 0 && i != 66 && mids[i] >= 0 )
2068                                 printf("VIOLATION at %d, notaryid.%d\n",i,mids[i]);
2069                             for (j=gpucount=0; j<65; j++)
2070                             {
2071                                 if ( dispflag != 0 )
2072                                 {
2073                                     if ( mids[j] >= 0 )
2074                                         fprintf(stderr,"%d ",mids[j]);
2075                                     else fprintf(stderr,"GPU ");
2076                                 }
2077                                 if ( mids[j] == -1 )
2078                                     gpucount++;
2079                             }
2080                             if ( dispflag != 0 )
2081                                 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));
2082                         }
2083                         for (j=0; j<65; j++)
2084                             if ( mids[j] == notaryid )
2085                                 break;
2086                         if ( j == 65 )
2087                             KOMODO_LASTMINED = 0;
2088                     } else fprintf(stderr,"no nonz pubkeys\n");
2089                     if ( (Mining_height >= 235300 && Mining_height < 236000) || (j == 65 && Mining_height > KOMODO_MAYBEMINED+1 && Mining_height > KOMODO_LASTMINED+64) )
2090                     {
2091                         HASHTarget = arith_uint256().SetCompact(KOMODO_MINDIFF_NBITS);
2092                         fprintf(stderr,"I am the chosen one for %s ht.%d\n",ASSETCHAINS_SYMBOL,pindexPrev->GetHeight()+1);
2093                     } //else fprintf(stderr,"duplicate at j.%d\n",j);
2094                 } else Mining_start = 0;
2095             } else Mining_start = 0;
2096             if ( ASSETCHAINS_STAKED != 0 )
2097             {
2098                 int32_t percPoS,z; bool fNegative,fOverflow;
2099                 HASHTarget_POW = komodo_PoWtarget(&percPoS,HASHTarget,Mining_height,ASSETCHAINS_STAKED);
2100                 HASHTarget.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow);
2101                 if ( ASSETCHAINS_STAKED < 100 )
2102                 {
2103                     for (z=31; z>=0; z--)
2104                         fprintf(stderr,"%02x",((uint8_t *)&HASHTarget_POW)[z]);
2105                     fprintf(stderr," PoW for staked coin PoS %d%% vs target %d%%\n",percPoS,(int32_t)ASSETCHAINS_STAKED);
2106                 }
2107             }
2108             while (true)
2109             {
2110                 if ( KOMODO_INSYNC == 0 )
2111                 {
2112                     fprintf(stderr,"Mining when blockchain might not be in sync longest.%d vs %d\n",KOMODO_LONGESTCHAIN,Mining_height);
2113                     if ( KOMODO_LONGESTCHAIN != 0 && Mining_height >= KOMODO_LONGESTCHAIN )
2114                         KOMODO_INSYNC = 1;
2115                     sleep(3);
2116                 }
2117                 // Hash state
2118                 KOMODO_CHOSEN_ONE = 0;
2119                 
2120                 crypto_generichash_blake2b_state state;
2121                 EhInitialiseState(n, k, state);
2122                 // I = the block header minus nonce and solution.
2123                 CEquihashInput I{*pblock};
2124                 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
2125                 ss << I;
2126                 // H(I||...
2127                 crypto_generichash_blake2b_update(&state, (unsigned char*)&ss[0], ss.size());
2128                 // H(I||V||...
2129                 crypto_generichash_blake2b_state curr_state;
2130                 curr_state = state;
2131                 crypto_generichash_blake2b_update(&curr_state,pblock->nNonce.begin(),pblock->nNonce.size());
2132                 // (x_1, x_2, ...) = A(I, V, n, k)
2133                 LogPrint("pow", "Running Equihash solver \"%s\" with nNonce = %s\n",solver, pblock->nNonce.ToString());
2134                 arith_uint256 hashTarget;
2135                 if ( KOMODO_MININGTHREADS > 0 && ASSETCHAINS_STAKED > 0 && ASSETCHAINS_STAKED < 100 && Mining_height > 10 )
2136                     hashTarget = HASHTarget_POW;
2137                 else hashTarget = HASHTarget;
2138                 std::function<bool(std::vector<unsigned char>)> validBlock =
2139 #ifdef ENABLE_WALLET
2140                 [&pblock, &hashTarget, &pwallet, &reservekey, &m_cs, &cancelSolver, &chainparams]
2141 #else
2142                 [&pblock, &hashTarget, &m_cs, &cancelSolver, &chainparams]
2143 #endif
2144                 (std::vector<unsigned char> soln) {
2145                     int32_t z; arith_uint256 h; CBlock B;
2146                     // Write the solution to the hash and compute the result.
2147                     LogPrint("pow", "- Checking solution against target\n");
2148                     pblock->nSolution = soln;
2149                     solutionTargetChecks.increment();
2150                     B = *pblock;
2151                     h = UintToArith256(B.GetHash());
2152                     /*for (z=31; z>=16; z--)
2153                         fprintf(stderr,"%02x",((uint8_t *)&h)[z]);
2154                     fprintf(stderr," mined ");
2155                     for (z=31; z>=16; z--)
2156                         fprintf(stderr,"%02x",((uint8_t *)&HASHTarget)[z]);
2157                     fprintf(stderr," hashTarget ");
2158                     for (z=31; z>=16; z--)
2159                         fprintf(stderr,"%02x",((uint8_t *)&HASHTarget_POW)[z]);
2160                     fprintf(stderr," POW\n");*/
2161                     if ( h > hashTarget )
2162                     {
2163                         //if ( ASSETCHAINS_STAKED != 0 && KOMODO_MININGTHREADS == 0 )
2164                         //    sleep(1);
2165                         return false;
2166                     }
2167                     if ( IS_KOMODO_NOTARY != 0 && B.nTime > GetAdjustedTime() )
2168                     {
2169                         //fprintf(stderr,"need to wait %d seconds to submit block\n",(int32_t)(B.nTime - GetAdjustedTime()));
2170                         while ( GetAdjustedTime() < B.nTime-2 )
2171                         {
2172                             sleep(1);
2173                             if ( chainActive.LastTip()->GetHeight() >= Mining_height )
2174                             {
2175                                 fprintf(stderr,"new block arrived\n");
2176                                 return(false);
2177                             }
2178                         }
2179                     }
2180                     if ( ASSETCHAINS_STAKED == 0 )
2181                     {
2182                         if ( IS_KOMODO_NOTARY != 0 )
2183                         {
2184                             int32_t r;
2185                             if ( (r= ((Mining_height + NOTARY_PUBKEY33[16]) % 64) / 8) > 0 )
2186                                 MilliSleep((rand() % (r * 1000)) + 1000);
2187                         }
2188                     }
2189                     else
2190                     {
2191                         while ( B.nTime-57 > GetAdjustedTime() )
2192                         {
2193                             sleep(1);
2194                             if ( chainActive.LastTip()->GetHeight() >= Mining_height )
2195                                 return(false);
2196                         }
2197                         uint256 tmp = B.GetHash();
2198                         int32_t z; for (z=31; z>=0; z--)
2199                             fprintf(stderr,"%02x",((uint8_t *)&tmp)[z]);
2200                         fprintf(stderr," mined %s block %d!\n",ASSETCHAINS_SYMBOL,Mining_height);
2201                     }
2202                     CValidationState state;
2203                     if ( !TestBlockValidity(state,B, chainActive.LastTip(), true, false))
2204                     {
2205                         h = UintToArith256(B.GetHash());
2206                         for (z=31; z>=0; z--)
2207                             fprintf(stderr,"%02x",((uint8_t *)&h)[z]);
2208                         fprintf(stderr," Invalid block mined, try again\n");
2209                         return(false);
2210                     }
2211                     KOMODO_CHOSEN_ONE = 1;
2212                     // Found a solution
2213                     SetThreadPriority(THREAD_PRIORITY_NORMAL);
2214                     LogPrintf("KomodoMiner:\n");
2215                     LogPrintf("proof-of-work found  \n  hash: %s  \ntarget: %s\n", B.GetHash().GetHex(), HASHTarget.GetHex());
2216 #ifdef ENABLE_WALLET
2217                     if (ProcessBlockFound(&B, *pwallet, reservekey)) {
2218 #else
2219                         if (ProcessBlockFound(&B)) {
2220 #endif
2221                             // Ignore chain updates caused by us
2222                             std::lock_guard<std::mutex> lock{m_cs};
2223                             cancelSolver = false;
2224                         }
2225                         KOMODO_CHOSEN_ONE = 0;
2226                         SetThreadPriority(THREAD_PRIORITY_LOWEST);
2227                         // In regression test mode, stop mining after a block is found.
2228                         if (chainparams.MineBlocksOnDemand()) {
2229                             // Increment here because throwing skips the call below
2230                             ehSolverRuns.increment();
2231                             throw boost::thread_interrupted();
2232                         }
2233                         return true;
2234                     };
2235                     std::function<bool(EhSolverCancelCheck)> cancelled = [&m_cs, &cancelSolver](EhSolverCancelCheck pos) {
2236                         std::lock_guard<std::mutex> lock{m_cs};
2237                         return cancelSolver;
2238                     };
2239                     
2240                     // TODO: factor this out into a function with the same API for each solver.
2241                     if (solver == "tromp" ) { //&& notaryid >= 0 ) {
2242                         // Create solver and initialize it.
2243                         equi eq(1);
2244                         eq.setstate(&curr_state);
2245                         
2246                         // Initialization done, start algo driver.
2247                         eq.digit0(0);
2248                         eq.xfull = eq.bfull = eq.hfull = 0;
2249                         eq.showbsizes(0);
2250                         for (u32 r = 1; r < WK; r++) {
2251                             (r&1) ? eq.digitodd(r, 0) : eq.digiteven(r, 0);
2252                             eq.xfull = eq.bfull = eq.hfull = 0;
2253                             eq.showbsizes(r);
2254                         }
2255                         eq.digitK(0);
2256                         ehSolverRuns.increment();
2257                         
2258                         // Convert solution indices to byte array (decompress) and pass it to validBlock method.
2259                         for (size_t s = 0; s < eq.nsols; s++) {
2260                             LogPrint("pow", "Checking solution %d\n", s+1);
2261                             std::vector<eh_index> index_vector(PROOFSIZE);
2262                             for (size_t i = 0; i < PROOFSIZE; i++) {
2263                                 index_vector[i] = eq.sols[s][i];
2264                             }
2265                             std::vector<unsigned char> sol_char = GetMinimalFromIndices(index_vector, DIGITBITS);
2266                             
2267                             if (validBlock(sol_char)) {
2268                                 // If we find a POW solution, do not try other solutions
2269                                 // because they become invalid as we created a new block in blockchain.
2270                                 break;
2271                             }
2272                         }
2273                     } else {
2274                         try {
2275                             // If we find a valid block, we rebuild
2276                             bool found = EhOptimisedSolve(n, k, curr_state, validBlock, cancelled);
2277                             ehSolverRuns.increment();
2278                             if (found) {
2279                                 int32_t i; uint256 hash = pblock->GetHash();
2280                                 for (i=0; i<32; i++)
2281                                     fprintf(stderr,"%02x",((uint8_t *)&hash)[i]);
2282                                 fprintf(stderr," <- %s Block found %d\n",ASSETCHAINS_SYMBOL,Mining_height);
2283                                 FOUND_BLOCK = 1;
2284                                 KOMODO_MAYBEMINED = Mining_height;
2285                                 break;
2286                             }
2287                         } catch (EhSolverCancelledException&) {
2288                             LogPrint("pow", "Equihash solver cancelled\n");
2289                             std::lock_guard<std::mutex> lock{m_cs};
2290                             cancelSolver = false;
2291                         }
2292                     }
2293                     
2294                     // Check for stop or if block needs to be rebuilt
2295                     boost::this_thread::interruption_point();
2296                     // Regtest mode doesn't require peers
2297                     if ( FOUND_BLOCK != 0 )
2298                     {
2299                         FOUND_BLOCK = 0;
2300                         fprintf(stderr,"FOUND_BLOCK!\n");
2301                         //sleep(2000);
2302                     }
2303                     if (vNodes.empty() && chainparams.MiningRequiresPeers())
2304                     {
2305                         if ( ASSETCHAINS_SYMBOL[0] == 0 || Mining_height > ASSETCHAINS_MINHEIGHT )
2306                         {
2307                             fprintf(stderr,"no nodes, break\n");
2308                             break;
2309                         }
2310                     }
2311                     if ((UintToArith256(pblock->nNonce) & 0xffff) == 0xffff)
2312                     {
2313                         //if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 )
2314                         fprintf(stderr,"0xffff, break\n");
2315                         break;
2316                     }
2317                     if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
2318                     {
2319                         if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 )
2320                             fprintf(stderr,"timeout, break\n");
2321                         break;
2322                     }
2323                     if ( pindexPrev != chainActive.LastTip() )
2324                     {
2325                         if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 )
2326                             fprintf(stderr,"Tip advanced, break\n");
2327                         break;
2328                     }
2329                     // Update nNonce and nTime
2330                     pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1);
2331                     pblock->nBits = savebits;
2332                     /*if ( NOTARY_PUBKEY33[0] == 0 )
2333                     {
2334                         int32_t percPoS;
2335                         UpdateTime(pblock, consensusParams, pindexPrev);
2336                         if (consensusParams.fPowAllowMinDifficultyBlocks)
2337                         {
2338                             // Changing pblock->nTime can change work required on testnet:
2339                             HASHTarget.SetCompact(pblock->nBits);
2340                             HASHTarget_POW = komodo_PoWtarget(&percPoS,HASHTarget,Mining_height,ASSETCHAINS_STAKED);
2341                         }
2342                     }*/
2343                 }
2344             }
2345         }
2346         catch (const boost::thread_interrupted&)
2347         {
2348             miningTimer.stop();
2349             c.disconnect();
2350             LogPrintf("KomodoMiner terminated\n");
2351             throw;
2352         }
2353         catch (const std::runtime_error &e)
2354         {
2355             miningTimer.stop();
2356             c.disconnect();
2357             LogPrintf("KomodoMiner runtime error: %s\n", e.what());
2358             return;
2359         }
2360         miningTimer.stop();
2361         c.disconnect();
2362     }
2363     
2364 #ifdef ENABLE_WALLET
2365     void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads)
2366 #else
2367     void GenerateBitcoins(bool fGenerate, int nThreads)
2368 #endif
2369     {
2370         if (!AreParamsInitialized())
2371         {
2372             return;
2373         }
2374
2375         // if we are supposed to catch stake cheaters, there must be a valid sapling parameter, we need it at
2376         // initialization, and this is the first time we can get it. store the Sapling address here
2377         extern boost::optional<libzcash::SaplingPaymentAddress> cheatCatcher;
2378         extern std::string VERUS_CHEATCATCHER;
2379         libzcash::PaymentAddress addr = DecodePaymentAddress(VERUS_CHEATCATCHER);
2380         if (VERUS_CHEATCATCHER.size() > 0 && IsValidPaymentAddress(addr))
2381         {
2382             try
2383             {
2384                 cheatCatcher = boost::get<libzcash::SaplingPaymentAddress>(addr);
2385             } 
2386             catch (...)
2387             {
2388             }
2389         }
2390
2391         VERUS_MINTBLOCKS = (VERUS_MINTBLOCKS && ASSETCHAINS_LWMAPOS != 0);
2392
2393         if (fGenerate == true || VERUS_MINTBLOCKS)
2394         {
2395             mapArgs["-gen"] = "1";
2396
2397             if (VERUS_CHEATCATCHER.size() > 0)
2398             {
2399                 if (cheatCatcher == boost::none)
2400                 {
2401                     LogPrintf("ERROR: -cheatcatcher parameter is invalid Sapling payment address\n");
2402                     fprintf(stderr, "-cheatcatcher parameter is invalid Sapling payment address\n");
2403                 }
2404                 else
2405                 {
2406                     LogPrintf("StakeGuard searching for double stakes on %s\n", VERUS_CHEATCATCHER.c_str());
2407                     fprintf(stderr, "StakeGuard searching for double stakes on %s\n", VERUS_CHEATCATCHER.c_str());
2408                 }
2409             }
2410         }
2411
2412         static boost::thread_group* minerThreads = NULL;
2413
2414         if (nThreads < 0)
2415             nThreads = GetNumCores();
2416         
2417         if (minerThreads != NULL)
2418         {
2419             minerThreads->interrupt_all();
2420             delete minerThreads;
2421             minerThreads = NULL;
2422         }
2423
2424         //fprintf(stderr,"nThreads.%d fGenerate.%d\n",(int32_t)nThreads,fGenerate);
2425         if ( nThreads == 0 && ASSETCHAINS_STAKED )
2426             nThreads = 1;
2427
2428         if (!fGenerate)
2429             return;
2430
2431         minerThreads = new boost::thread_group();
2432
2433         // add the PBaaS thread when mining or staking
2434         minerThreads->create_thread(boost::bind(&CConnectedChains::SubmissionThreadStub));
2435
2436 #ifdef ENABLE_WALLET
2437         if (VERUS_MINTBLOCKS && pwallet != NULL)
2438         {
2439             minerThreads->create_thread(boost::bind(&VerusStaker, pwallet));
2440         }
2441 #endif
2442
2443         for (int i = 0; i < nThreads; i++) {
2444
2445 #ifdef ENABLE_WALLET
2446             if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH)
2447                 minerThreads->create_thread(boost::bind(&BitcoinMiner, pwallet));
2448             else
2449                 minerThreads->create_thread(boost::bind(&BitcoinMiner_noeq, pwallet));
2450 #else
2451             if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH)
2452                 minerThreads->create_thread(&BitcoinMiner);
2453             else
2454                 minerThreads->create_thread(&BitcoinMiner_noeq);
2455 #endif
2456         }
2457     }
2458     
2459 #endif // ENABLE_MINING
This page took 0.170075 seconds and 4 git commands to generate.