]> Git Repo - VerusCoin.git/blob - src/miner.cpp
getidentity fix
[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 https://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 #include "validationinterface.h"
35
36 #include "zcash/Address.hpp"
37 #include "transaction_builder.h"
38
39 #include "sodium.h"
40
41 #include <boost/thread.hpp>
42 #include <boost/tuple/tuple.hpp>
43 #ifdef ENABLE_MINING
44 #include <functional>
45 #endif
46 #include <mutex>
47
48 #include "pbaas/pbaas.h"
49 #include "pbaas/notarization.h"
50 #include "pbaas/identity.h"
51 #include "rpc/pbaasrpc.h"
52 #include "transaction_builder.h"
53
54 using namespace std;
55
56 //////////////////////////////////////////////////////////////////////////////
57 //
58 // BitcoinMiner
59 //
60
61 //
62 // Unconfirmed transactions in the memory pool often depend on other
63 // transactions in the memory pool. When we select transactions from the
64 // pool, we select by highest priority or fee rate, so we might consider
65 // transactions that depend on transactions that aren't yet in the block.
66 // The COrphan class keeps track of these 'temporary orphans' while
67 // CreateBlock is figuring out which transactions to include.
68 //
69 class COrphan
70 {
71 public:
72     const CTransaction* ptx;
73     set<uint256> setDependsOn;
74     CFeeRate feeRate;
75     double dPriority;
76     
77     COrphan(const CTransaction* ptxIn) : ptx(ptxIn), feeRate(0), dPriority(0)
78     {
79     }
80 };
81
82 uint64_t nLastBlockTx = 0;
83 uint64_t nLastBlockSize = 0;
84
85 // We want to sort transactions by priority and fee rate, so:
86 typedef boost::tuple<double, CFeeRate, const CTransaction*> TxPriority;
87 class TxPriorityCompare
88 {
89     bool byFee;
90     
91 public:
92     TxPriorityCompare(bool _byFee) : byFee(_byFee) { }
93     
94     bool operator()(const TxPriority& a, const TxPriority& b)
95     {
96         if (byFee)
97         {
98             if (a.get<1>() == b.get<1>())
99                 return a.get<0>() < b.get<0>();
100             return a.get<1>() < b.get<1>();
101         }
102         else
103         {
104             if (a.get<0>() == b.get<0>())
105                 return a.get<1>() < b.get<1>();
106             return a.get<0>() < b.get<0>();
107         }
108     }
109 };
110
111 void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
112 {
113     pblock->nTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
114
115     // Updating time can change work required on testnet:
116     if (consensusParams.nPowAllowMinDifficultyBlocksAfterHeight != boost::none) {
117         pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams);
118     }
119 }
120
121 #include "komodo_defs.h"
122
123 extern CCriticalSection cs_metrics;
124 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;
125 extern uint64_t ASSETCHAINS_COMMISSION, ASSETCHAINS_STAKED;
126 extern bool VERUS_MINTBLOCKS;
127 extern uint64_t ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS], ASSETCHAINS_TIMELOCKGTE, ASSETCHAINS_NONCEMASK[];
128 extern const char *ASSETCHAINS_ALGORITHMS[];
129 extern int32_t VERUS_MIN_STAKEAGE, ASSETCHAINS_EQUIHASH, ASSETCHAINS_VERUSHASH, ASSETCHAINS_LASTERA, ASSETCHAINS_LWMAPOS, ASSETCHAINS_NONCESHIFT[], ASSETCHAINS_HASHESPERROUND[];
130 extern uint32_t ASSETCHAINS_ALGO;
131 extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
132 extern uint160 ASSETCHAINS_CHAINID;
133 extern uint160 VERUS_CHAINID;
134 extern std::string VERUS_CHAINNAME;
135 extern int32_t PBAAS_STARTBLOCK, PBAAS_ENDBLOCK;
136 extern string PBAAS_HOST, PBAAS_USERPASS, ASSETCHAINS_RPCHOST, ASSETCHAINS_RPCCREDENTIALS;;
137 extern int32_t PBAAS_PORT;
138 extern uint16_t ASSETCHAINS_RPCPORT;
139 extern std::string NOTARY_PUBKEY,ASSETCHAINS_OVERRIDE_PUBKEY;
140 void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len);
141
142 extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33];
143 uint32_t Mining_start, Mining_height;
144 int32_t My_notaryid = -1;
145 int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp);
146 int32_t komodo_pax_opreturn(int32_t height,uint8_t *opret,int32_t maxsize);
147 int32_t komodo_baseid(char *origbase);
148 int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t nTime,int32_t dispflag);
149 int64_t komodo_block_unlocktime(uint32_t nHeight);
150 uint64_t komodo_commission(const CBlock *block);
151 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);
152 int32_t verus_staked(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &nBits, arith_uint256 &hashResult, uint8_t *utxosig, CPubKey &pk);
153 int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33);
154
155 void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int &nExtraNonce, bool buildMerkle, uint32_t *pSaveBits)
156 {
157     // Update nExtraNonce
158     static uint256 hashPrevBlock;
159     if (hashPrevBlock != pblock->hashPrevBlock)
160     {
161         nExtraNonce = 0;
162         hashPrevBlock = pblock->hashPrevBlock;
163     }
164     ++nExtraNonce;
165
166     if (pSaveBits)
167     {
168         *pSaveBits = pblock->nBits;
169     }
170
171     int32_t nHeight = pindexPrev->GetHeight() + 1;
172
173     if (CConstVerusSolutionVector::activationHeight.ActiveVersion(nHeight) >= CConstVerusSolutionVector::activationHeight.ACTIVATE_PBAAS)
174     {
175         // coinbase should already be finalized in the new version
176         if (buildMerkle)
177         {
178             pblock->hashMerkleRoot = pblock->BuildMerkleTree();
179             pblock->SetPrevMMRRoot(ChainMerkleMountainView(chainActive.GetMMR(), pindexPrev->GetHeight()).GetRoot());
180             BlockMMRange mmRange(pblock->BuildBlockMMRTree());
181             BlockMMView mmView(mmRange);
182             pblock->SetBlockMMRRoot(mmView.GetRoot());
183             pblock->AddUpdatePBaaSHeader();
184         }
185
186         UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
187
188         uint256 mmvRoot;
189         {
190             LOCK(cs_main);
191             // set the PBaaS header
192             ChainMerkleMountainView mmv = chainActive.GetMMV();
193             mmvRoot = mmv.GetRoot();
194         }
195
196         pblock->AddUpdatePBaaSHeader();
197
198         // POS blocks have already had their solution space filled, and there is no actual extra nonce, extradata is used
199         // for POS proof, so don't modify it
200         if (!pblock->IsVerusPOSBlock())
201         {
202             uint8_t dummy;
203             // clear extra data to allow adding more PBaaS headers
204             pblock->SetExtraData(&dummy, 0);
205
206             // combine blocks and set compact difficulty if necessary
207             uint32_t savebits;
208             if ((savebits = ConnectedChains.CombineBlocks(*pblock)) && pSaveBits)
209             {
210                 arith_uint256 ours, merged;
211                 ours.SetCompact(pblock->nBits);
212                 merged.SetCompact(savebits);
213                 if (merged > ours)
214                 {
215                     *pSaveBits = savebits;
216                 }
217             }
218
219             // extra nonce is kept in the header, not in the coinbase any longer
220             // this allows instant spend transactions to use coinbase funds for
221             // inputs by ensuring that once final, the coinbase transaction hash
222             // will not continue to change
223             CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
224             s << nExtraNonce;
225             std::vector<unsigned char> vENonce(s.begin(), s.end());
226
227             assert(pblock->ExtraDataLen() >= vENonce.size());
228             pblock->SetExtraData(vENonce.data(), vENonce.size());
229         }
230     }
231     else
232     {
233         // finalize input of coinbase
234         CMutableTransaction txcb(pblock->vtx[0]);
235         txcb.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
236         assert(txcb.vin[0].scriptSig.size() <= 100);
237         pblock->vtx[0] = txcb;
238         if (buildMerkle)
239         {
240             pblock->hashMerkleRoot = pblock->BuildMerkleTree();
241         }
242
243         UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
244     }
245 }
246
247 extern CWallet *pwalletMain;
248
249 CPubKey GetSolutionPubKey(const std::vector<std::vector<unsigned char>> &vSolutions, txnouttype txType)
250 {
251     CPubKey pk;
252
253     if (txType == TX_PUBKEY)
254     {
255         pk = CPubKey(vSolutions[0]);
256     }
257     else if(txType == TX_PUBKEYHASH)
258     {
259         // we need to have this in our wallet to get the public key
260         LOCK(pwalletMain->cs_wallet);
261         pwalletMain->GetPubKey(CKeyID(uint160(vSolutions[0])), pk);
262     }
263     else if (txType == TX_CRYPTOCONDITION)
264     {
265         if (vSolutions[0].size() == 33)
266         {
267             pk = CPubKey(vSolutions[0]);
268         }
269         else if (vSolutions[0].size() == 34 && vSolutions[0][0] == COptCCParams::ADDRTYPE_PK)
270         {
271             pk = CPubKey(std::vector<unsigned char>(vSolutions[0].begin() + 1, vSolutions[0].end()));
272         }
273         else if (vSolutions[0].size() == 20)
274         {
275             LOCK(pwalletMain->cs_wallet);
276             pwalletMain->GetPubKey(CKeyID(uint160(vSolutions[0])), pk);
277         }
278         else if (vSolutions[0].size() == 21 && vSolutions[0][0] == COptCCParams::ADDRTYPE_ID)
279         {
280             // destination is an identity, see if we can get its first public key
281             std::pair<CIdentityMapKey, CIdentityMapValue> identity;
282
283             if (pwalletMain->GetIdentity(CIdentityID(uint160(std::vector<unsigned char>(vSolutions[0].begin() + 1, vSolutions[0].end()))), identity) && 
284                 identity.second.IsValidUnrevoked() && 
285                 identity.second.primaryAddresses.size())
286             {
287                 CPubKey pkTmp = boost::apply_visitor<GetPubKeyForPubKey>(GetPubKeyForPubKey(), identity.second.primaryAddresses[0]);
288                 if (pkTmp.IsValid())
289                 {
290                     pk = pkTmp;
291                 }
292                 else
293                 {
294                     LOCK(pwalletMain->cs_wallet);
295                     pwalletMain->GetPubKey(CKeyID(GetDestinationID(identity.second.primaryAddresses[0])), pk);
296                 }
297             }
298         }
299     }
300     return pk;
301 }
302
303 CPubKey GetScriptPublicKey(const CScript &scriptPubKey)
304 {
305     txnouttype typeRet;
306     std::vector<std::vector<unsigned char>> vSolutions;
307     if (Solver(scriptPubKey, typeRet, vSolutions))
308     {
309         return GetSolutionPubKey(vSolutions, typeRet);
310     }
311     return CPubKey();
312 }
313
314 CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& _scriptPubKeyIn, int32_t gpucount, bool isStake)
315 {
316     CScript scriptPubKeyIn(_scriptPubKeyIn);
317
318     // instead of one scriptPubKeyIn, we take a vector of them along with relative weight. each is assigned a percentage of the block subsidy and
319     // mining reward based on its weight relative to the total
320     std::vector<pair<int, CScript>> minerOutputs = scriptPubKeyIn.size() ? std::vector<pair<int, CScript>>({make_pair((int)1, scriptPubKeyIn)}) : std::vector<pair<int, CScript>>();
321
322     CTxDestination firstDestination;
323     if (!(scriptPubKeyIn.size() && ConnectedChains.SetLatestMiningOutputs(minerOutputs, firstDestination) || isStake))
324     {
325         fprintf(stderr,"%s: Must have valid miner outputs, including script with valid PK, PKH, or Verus ID destination.\n", __func__);
326         return NULL;
327     }
328
329     CPubKey pk;
330
331     if (minerOutputs.size())
332     {
333         int64_t shareCheck = 0;
334         for (auto output : minerOutputs)
335         {
336             shareCheck += output.first;
337             if (shareCheck < 0 || shareCheck > INT_MAX)
338             {
339                 fprintf(stderr,"Invalid miner outputs share specifications\n");
340                 return NULL;
341             }
342         }
343         pk = GetScriptPublicKey(minerOutputs[0].second);
344     }
345
346     uint64_t deposits; int32_t isrealtime,kmdheight; uint32_t blocktime;
347     //fprintf(stderr,"create new block\n");
348     // Create new block
349     if ( gpucount < 0 )
350         gpucount = KOMODO_MAXGPUCOUNT;
351     std::unique_ptr<CBlockTemplate> pblocktemplate(new CBlockTemplate());
352     if(!pblocktemplate.get())
353     {
354         fprintf(stderr,"pblocktemplate.get() failure\n");
355         return NULL;
356     }
357     CBlock *pblock = &pblocktemplate->block; // pointer for convenience
358
359     // set version according to the current tip height, add solution if it is
360     // VerusHash
361     if (ASSETCHAINS_ALGO == ASSETCHAINS_VERUSHASH)
362     {
363         pblock->nSolution.resize(Eh200_9.SolutionWidth);
364     }
365     else
366     {
367         pblock->nSolution.clear();
368     }
369     pblock->SetVersionByHeight(chainActive.LastTip()->GetHeight() + 1);
370
371     // -regtest only: allow overriding block.nVersion with
372     // -blockversion=N to test forking scenarios
373     if (chainparams.MineBlocksOnDemand())
374         pblock->nVersion = GetArg("-blockversion", pblock->nVersion);
375     
376     // Add dummy coinbase tx placeholder as first transaction
377     pblock->vtx.push_back(CTransaction());
378
379     pblocktemplate->vTxFees.push_back(-1); // updated at end
380     pblocktemplate->vTxSigOps.push_back(-1); // updated at end
381     
382     // Largest block you're willing to create:
383     unsigned int nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE);
384     // Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity:
385     nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize));
386
387     unsigned int nMaxIDSize = nBlockMaxSize / 2;
388     unsigned int nCurrentIDSize = 0;
389     
390     // How much of the block should be dedicated to high-priority transactions,
391     // included regardless of the fees they pay
392     unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", DEFAULT_BLOCK_PRIORITY_SIZE);
393     nBlockPrioritySize = std::min(nBlockMaxSize, nBlockPrioritySize);
394     
395     // Minimum block size you want to create; block will be filled with free transactions
396     // until there are no more or the block reaches this size:
397     unsigned int nBlockMinSize = GetArg("-blockminsize", DEFAULT_BLOCK_MIN_SIZE);
398     nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize);
399     
400     // Collect memory pool transactions into the block
401     CAmount nFees = 0;
402
403     // if this is a reserve currency, update the currency state from the coinbase of the last block
404     bool isVerusActive = IsVerusActive();
405     CCurrencyDefinition &thisChain = ConnectedChains.ThisChain();
406     CAmount prealloc = 0;
407     for (auto &onePair : thisChain.preAllocation)
408     {
409         prealloc += onePair.second;
410     }
411     CCoinbaseCurrencyState currencyState = CCoinbaseCurrencyState(CCurrencyStateNew(thisChain.currencies,
412                                                                                     thisChain.weights,
413                                                                                     thisChain.contributions,
414                                                                                     prealloc, 0, 0));
415
416     std::vector<CAmount> exchangeRate(thisChain.currencies.size());
417
418     // we will attempt to spend any cheats we see
419     CTransaction cheatTx;
420     boost::optional<CTransaction> cheatSpend;
421     uint256 cbHash;
422
423     CBlockIndex* pindexPrev = 0;
424     {
425         LOCK2(cs_main, mempool.cs);
426         pindexPrev = chainActive.LastTip();
427         const int nHeight = pindexPrev->GetHeight() + 1;
428         const Consensus::Params &consensusParams = chainparams.GetConsensus();
429         uint32_t consensusBranchId = CurrentEpochBranchId(nHeight, consensusParams);
430         bool sapling = consensusParams.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_SAPLING);
431
432         const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast();
433         uint32_t proposedTime = GetAdjustedTime();
434         if (proposedTime == nMedianTimePast)
435         {
436             // too fast or stuck, this addresses the too fast issue, while moving
437             // forward as quickly as possible
438             for (int i; i < 100; i++)
439             {
440                 proposedTime = GetAdjustedTime();
441                 if (proposedTime == nMedianTimePast)
442                     MilliSleep(10);
443             }
444         }
445         pblock->nTime = GetAdjustedTime();
446
447         CCoinsViewCache view(pcoinsTip);
448         uint32_t expired; uint64_t commission;
449         
450         SaplingMerkleTree sapling_tree;
451         assert(view.GetSaplingAnchorAt(view.GetBestAnchor(SAPLING), sapling_tree));
452
453         // Priority order to process transactions
454         list<COrphan> vOrphan; // list memory doesn't move
455         map<uint256, vector<COrphan*> > mapDependers;
456         bool fPrintPriority = GetBoolArg("-printpriority", false);
457         
458         // This vector will be sorted into a priority queue:
459         vector<TxPriority> vecPriority;
460         vecPriority.reserve(mempool.mapTx.size() + 1);
461
462         // check if we should add cheat transaction
463         CBlockIndex *ppast;
464         CTransaction cb;
465         int cheatHeight = nHeight - COINBASE_MATURITY < 1 ? 1 : nHeight - COINBASE_MATURITY;
466         if (cheatCatcher &&
467             sapling && chainActive.Height() > 100 && 
468             (ppast = chainActive[cheatHeight]) && 
469             ppast->IsVerusPOSBlock() && 
470             cheatList.IsHeightOrGreaterInList(cheatHeight))
471         {
472             // get the block and see if there is a cheat candidate for the stake tx
473             CBlock b;
474             if (!(fHavePruned && !(ppast->nStatus & BLOCK_HAVE_DATA) && ppast->nTx > 0) && ReadBlockFromDisk(b, ppast, chainparams.GetConsensus(), 1))
475             {
476                 CTransaction &stakeTx = b.vtx[b.vtx.size() - 1];
477
478                 if (cheatList.IsCheatInList(stakeTx, &cheatTx))
479                 {
480                     // make and sign the cheat transaction to spend the coinbase to our address
481                     CMutableTransaction mtx = CreateNewContextualCMutableTransaction(consensusParams, nHeight);
482
483                     uint32_t voutNum;
484                     // get the first vout with value
485                     for (voutNum = 0; voutNum < b.vtx[0].vout.size(); voutNum++)
486                     {
487                         if (b.vtx[0].vout[voutNum].nValue > 0)
488                             break;
489                     }
490
491                     // send to the same pub key as the destination of this block reward
492                     if (MakeCheatEvidence(mtx, b.vtx[0], voutNum, cheatTx))
493                     {
494                         LOCK(pwalletMain->cs_wallet);
495                         TransactionBuilder tb = TransactionBuilder(consensusParams, nHeight);
496                         cb = b.vtx[0];
497                         cbHash = cb.GetHash();
498
499                         bool hasInput = false;
500                         for (uint32_t i = 0; i < cb.vout.size(); i++)
501                         {
502                             // add the spends with the cheat
503                             if (cb.vout[i].nValue > 0)
504                             {
505                                 tb.AddTransparentInput(COutPoint(cbHash,i), cb.vout[0].scriptPubKey, cb.vout[0].nValue);
506                                 hasInput = true;
507                             }
508                         }
509
510                         if (hasInput)
511                         {
512                             // this is a send from a t-address to a sapling address, which we don't have an ovk for.
513                             // Instead, generate a common one from the HD seed. This ensures the data is
514                             // recoverable, at least for us, while keeping it logically separate from the ZIP 32
515                             // Sapling key hierarchy, which the user might not be using.
516                             uint256 ovk;
517                             HDSeed seed;
518                             if (pwalletMain->GetHDSeed(seed)) {
519                                 ovk = ovkForShieldingFromTaddr(seed);
520
521                                 // send everything to Sapling address
522                                 tb.SendChangeTo(cheatCatcher.value(), ovk);
523
524                                 tb.AddOpRet(mtx.vout[mtx.vout.size() - 1].scriptPubKey);
525
526                                 TransactionBuilderResult buildResult(tb.Build());
527                                 if (!buildResult.IsError() && buildResult.IsTx())
528                                 {
529                                     cheatSpend = buildResult.GetTxOrThrow();
530                                 }
531                                 else
532                                 {
533                                     LogPrintf("Error building cheat catcher transaction: %s\n", buildResult.GetError().c_str());
534                                 }
535                             }
536                         }
537                     }
538                 }
539             }
540         }
541
542         if (cheatSpend)
543         {
544             cheatTx = cheatSpend.value();
545             std::list<CTransaction> removed;
546             mempool.removeConflicts(cheatTx, removed);
547             printf("Found cheating stake! Adding cheat spend for %.8f at block #%d, coinbase tx\n%s\n",
548                 (double)cb.GetValueOut() / (double)COIN, nHeight, cheatSpend.value().vin[0].prevout.hash.GetHex().c_str());
549
550             // add to mem pool and relay
551             if (myAddtomempool(cheatTx))
552             {
553                 RelayTransaction(cheatTx);
554             }
555         }
556
557         //
558         // Now start solving the block
559         //
560
561         uint64_t nBlockSize = 1000;             // initial size
562         uint64_t nBlockTx = 1;                  // number of transactions - always have a coinbase
563         uint32_t autoTxSize = 0;                // extra transaction overhead that we will add while creating the block
564         int nBlockSigOps = 100;
565
566         // VerusPoP staking transaction data
567         CMutableTransaction txStaked;           // if this is a stake operation, the staking transaction that goes at the end
568         uint32_t nStakeTxSize = 0;              // serialized size of the stake transaction
569
570         // if this is not for mining, first determine if we have a right to bother
571         if (isStake)
572         {
573             uint64_t txfees,utxovalue; uint32_t txtime; uint256 utxotxid; int32_t i,siglen,numsigs,utxovout; uint8_t utxosig[128],*ptr;
574             txStaked = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nHeight);
575
576             //if ( blocktime > pindexPrev->GetMedianTimePast()+60 )
577             //    blocktime = pindexPrev->GetMedianTimePast() + 60;
578             if (ASSETCHAINS_LWMAPOS != 0)
579             {
580                 uint32_t nBitsPOS;
581                 arith_uint256 posHash;
582
583                 siglen = verus_staked(pblock, txStaked, nBitsPOS, posHash, utxosig, pk);
584                 blocktime = GetAdjustedTime();
585
586                 // change the default scriptPubKeyIn to the same output script exactly as the staking transaction
587                 // TODO: improve this and just implement stake guard here rather than keeping this legacy
588                 if (siglen > 0)
589                     scriptPubKeyIn = CScript(txStaked.vout[0].scriptPubKey);
590             }
591             else
592             {
593                 siglen = komodo_staked(txStaked, pblock->nBits, &blocktime, &txtime, &utxotxid, &utxovout, &utxovalue, utxosig);
594             }
595
596             if (siglen <= 0)
597             {
598                 return NULL;
599             }
600
601             pblock->nTime = blocktime;
602             nStakeTxSize = GetSerializeSize(txStaked, SER_NETWORK, PROTOCOL_VERSION);
603             nBlockSize += nStakeTxSize;
604
605             // get the public key and make a miner output if needed for this
606             if (!minerOutputs.size())
607             {
608                 minerOutputs.push_back(make_pair((int)1, txStaked.vout[0].scriptPubKey));
609                 pk = GetScriptPublicKey(txStaked.vout[0].scriptPubKey);
610                 ExtractDestination(minerOutputs[0].second, firstDestination);
611             }
612         }
613
614         ConnectedChains.AggregateChainTransfers(firstDestination, nHeight);
615
616         // Now the coinbase -
617         // A PBaaS coinbase must have some additional outputs to enable certain chain state and functions to be properly
618         // validated. All but currency state and the first chain definition are either optional or not valid on non-fractional reserve PBaaS blockchains
619         // All of these are instant spend outputs that have no maturity wait time and may be spent in the same block.
620         //
621         // 1. (required) currency state - current state of currency supply and optionally reserve, premine, etc. This is primarily a data output to provide
622         //    cross check for coin minting and burning operations, making it efficient to determine up-to-date supply, reserves, and conversions. To provide
623         //    an extra level of supply cross-checking and fast data retrieval, this is part of all PBaaS chains' protocol, not just reserves.
624         //    This output also includes reserve and native amounts for total conversions, less fees, of any conversions between Verus reserve and the
625         //    native currency.
626         //
627         // 2. (block 1 required) chain definition - in order to confirm the amount of coins converted and issued within the possible range, before chain start,
628         //    new PBaaS chains have a zero-amount, unspendable chain definition output.
629         //
630         // 3. (block 1 optional) initial import utxo - for any chain with conversion or pre-conversion, the first coinbase must include an initial import utxo. 
631         //    Pre-conversions are handled on the launch chain before the PBaaS chain starts, so they are an additional output, which begins
632         //    as a fixed amount and is spent with as many outputs as necessary to the recipients of the pre-conversion transactions when those pre-conversions
633         //    are imported. All pre-converted outputs get their source currency from a thread that starts with this output in block 1.
634         //
635         // 4. (block 1 optional) initial export utxo - reserve chains, or any chain that will use exports to another chain must have an initial export utxo, any chain
636         //    may have one, but currently, they can only be spent with valid exports, which only occur on reserve chains
637         //
638         // 5. (optional) notarization output - in order to ensure that notarization can occur independent of the availability of fungible
639         //    coins on the network, and also that the notarization can provide a spendable finalization output and possible reward
640         //
641         // In addition, each PBaaS block can be mined with optional, fee-generating transactions. Inporting transactions from the reserve chain or sending
642         // exported transactions to the reserve chain are optional fee-generating steps that would be easy to do when running multiple daemons.
643         // The types of transactions miners/stakers may facilitate or create for fees are as follows:
644         //
645         // 1. Earned notarization of Verus chain - spends the notarization instant out. must be present and spend the notarization output if there is a notarization output
646         //
647         // 2. Imported transactions from the export thread for this PBaaS chain on the Verus blockchain - imported transactions must spend the import utxo
648         //    thread, represent the export from the alternate chain which spends the export output from the prior import transaction, carry a notary proof, and
649         //    include outputs that map to each of its inputs on the source chain. Outputs can include unconverted reserve outputs only on fractional
650         //    reserve chains, pre-converted outputs for any chain with launch conversion, and post launch outputs to be converted on fractional reserve
651         //    chains. Each are handled in the following way:
652         //      a. Unconverted outputs are left as outputs to the intended destination of Verus reserve token and do not pass through the coinbase
653         //      b. Pre-converted outputs require that the import transaction spend the last pre-conversion output starting at block 1 as the source for
654         //         pre-converted currency.
655         //
656         // 3. Zero or more aggregated exports that combine individual cross-chain transactions and reserve transfer outputs for export to the Verus chain. 
657         //
658         // 4. Conversion distribution transactions for all native and reserve currency conversions, including reserve transfer outputs without conversion as
659         //    a second step for reserve transfers that have conversion included. Any remaining pre-converted reserve must always remain in a change output
660         //    until it is exhausted
661         CTxOut premineOut, chainDefinitionOut, importThreadOut, exportThreadOut, currencyStateOut, notarizationOut;
662         CMutableTransaction newNotarizationTx, newConversionOutputTx;
663         int currencyStateOutNum = 0, notarizationOutNum = 0;
664
665         // size of conversion tx
666         std::vector<CInputDescriptor> conversionInputs;
667
668         // if we are a PBaaS chain, first make sure we don't start prematurely, and if
669         // we should make an earned notarization, make it and set index to non-zero value
670         int32_t notarizationTxIndex = 0;                            // index of notarization if it is added
671         int32_t conversionTxIndex = 0;                              // index of conversion transaction if it is added
672
673         // export transactions can be created here by aggregating all pending transfer requests and either getting 10 or more together, or
674         // waiting n (10) blocks since the last one. each export must spend the output of the one before it
675         std::vector<CMutableTransaction> exportTransactions;
676
677         // all transaction outputs requesting conversion to another currency (PBaaS fractional reserve only)
678         // these will be used to calculate conversion price, fees, and generate coinbase conversion output as well as the
679         // conversion output transaction
680         std::vector<CTxOut> reserveConversionTo;
681         std::vector<CTxOut> reserveConversionFrom;
682
683         int64_t pbaasTransparentIn = 0;
684         int64_t pbaasTransparentOut = 0;
685         //extern int64_t ASSETCHAINS_SUPPLY;
686         //printf("%lu premine\n", ASSETCHAINS_SUPPLY);
687         int64_t blockSubsidy = GetBlockSubsidy(nHeight, consensusParams);
688
689         uint160 thisChainID = ConnectedChains.ThisChain().GetID();
690
691         uint256 mmrRoot;
692         vector<CInputDescriptor> notarizationInputs;
693
694         // used as scratch for making CCs, should be reinitialized each time
695         CCcontract_info CC;
696         CCcontract_info *cp;
697         vector<CTxDestination> vKeys;
698         CPubKey pkCC;
699
700         // Create coinbase tx and set up the null input with height
701         CMutableTransaction coinbaseTx = CreateNewContextualCMutableTransaction(consensusParams, nHeight);
702         coinbaseTx.vin.push_back(CTxIn(uint256(), (uint32_t)-1, CScript() << nHeight << OP_0));
703
704         // we will update amounts and fees later, but convert the guarded output now for validity checking and size estimate
705         if (isStake)
706         {
707             // if there is a specific destination, use it
708             CTransaction stakeTx(txStaked);
709             CStakeParams p;
710             if (ValidateStakeTransaction(stakeTx, p, false))
711             {
712                 if (p.Version() < p.VERSION_EXTENDED_STAKE && !p.pk.IsValid())
713                 {
714                     LogPrintf("CreateNewBlock: invalid public key\n");
715                     fprintf(stderr,"CreateNewBlock: invalid public key\n");
716                     return NULL;
717                 }
718                 coinbaseTx.vout.push_back(CTxOut(1, CScript()));
719                 if (!MakeGuardedOutput(1, p.pk, stakeTx, coinbaseTx.vout.back()))
720                 {
721                     LogPrintf("CreateNewBlock: failed to make GuardedOutput on staking coinbase\n");
722                     fprintf(stderr,"CreateNewBlock: failed to make GuardedOutput on staking coinbase\n");
723                     return NULL;
724                 }
725             }
726             else
727             {
728                 LogPrintf("CreateNewBlock: invalid stake transaction\n");
729                 fprintf(stderr,"CreateNewBlock: invalid stake transaction\n");
730                 return NULL;
731             }
732         }
733         else
734         {
735             // default outputs for mining and before stake guard or fee calculation
736             // store the relative weight in the amount output to convert later to a relative portion
737             // of the reward + fees
738             for (auto &spk : minerOutputs)
739             {
740                 coinbaseTx.vout.push_back(CTxOut(spk.first, spk.second));
741             }
742         }
743
744         CAmount totalEmission = blockSubsidy;
745
746         // make earned notarization only if this is not the Verus chain and we have enough subsidy
747         if (!isVerusActive)
748         {
749             // if we don't have a connected root PBaaS chain, we can't properly check
750             // and notarize the start block, so we have to pass the notarization and cross chain steps
751             bool notaryConnected = ConnectedChains.IsVerusPBaaSAvailable() && ConnectedChains.notaryChainHeight >= PBAAS_STARTBLOCK;
752
753             // get current currency state differently, depending on height
754             if (nHeight == 1)
755             {
756                 if (!notaryConnected || !ConnectedChains.readyToStart)
757                 {
758                     // cannot make block 1 unless we can properly notarize that the launch chain is past the start block
759                     return NULL;
760                 }
761
762                 // if some amount of pre-conversion was allowed, we need to check with all eligible currency
763                 // chains or systems to determine how much in each currency is available for preconversion
764                 // TODO: support querying multiple systems... initial support for VRSC and VRSCTEST-homed currencies
765                 if (thisChain.maxPreconvert.size() && thisChain.maxPreconvert.size() == thisChain.currencies.size())
766                 {
767                     // get the total amount pre-converted
768                     UniValue params(UniValue::VARR);
769                     params.push_back(EncodeDestination(CIdentityID(ASSETCHAINS_CHAINID)));
770
771                     UniValue result;
772                     try
773                     {
774                         result = find_value(RPCCallRoot("getinitialcurrencystate", params), "result");
775                     } catch (exception e)
776                     {
777                         result = NullUniValue;
778                     }
779
780                     if (!result.isNull())
781                     {
782                         currencyState = CCoinbaseCurrencyState(result);
783                     }
784
785                     if (result.isNull() || !currencyState.IsValid())
786                     {
787                         // no matter what happens, we should be able to get a valid currency state of some sort, if not, fail
788                         LogPrintf("Unable to get initial currency state to create block.\n");
789                         printf("Failure to get initial currency state. Cannot create block.\n");
790                         return NULL;
791                     }
792
793                     CCurrencyValueMap preConverted = CCurrencyValueMap(ConnectedChains.ThisChain().currencies, currencyState.reserveIn);
794                     CCurrencyValueMap minPreconvert = CCurrencyValueMap(ConnectedChains.ThisChain().currencies, ConnectedChains.ThisChain().minPreconvert);
795
796                     if (preConverted < minPreconvert)
797                     {
798                         // we must reach minimums in all currencies to launch
799                         LogPrintf("This chain did not receive the minimum currency contributions and cannot launch. Pre-launch contributions to this chain can be refunded.\n");
800                         printf("This chain did not receive the minimum currency contributions and cannot launch. Pre-launch contributions to this chain can be refunded.\n");
801                         return NULL;
802                     }
803
804                     thisChain.preconverted = preConverted.AsCurrencyVector(thisChain.currencies);
805                     thisChain.conversions = currencyState.conversionPrice;
806                 }
807
808                 CAmount blockOnePremine = thisChain.GetTotalPreallocation();
809                 SetBlockOnePremine(blockOnePremine);
810                 totalEmission = GetBlockSubsidy(nHeight, consensusParams);
811                 blockSubsidy = totalEmission - blockOnePremine;
812
813                 // add needed block one coinbase outputs for preallocation
814                 if (blockOnePremine)
815                 {
816                     std::vector<CTxOut> tmpOut;
817                     for (auto &onePremine : ConnectedChains.ThisChain().GetPreAllocationAmounts())
818                     {
819                         premineOut = CTxOut(onePremine.second, GetScriptForDestination(CTxDestination(CIdentityID(onePremine.first))));
820                         tmpOut.push_back(premineOut);
821                     }
822                     if (tmpOut.size())
823                     {
824                         coinbaseTx.vout.insert(coinbaseTx.vout.end(), tmpOut.begin(), tmpOut.end());
825                     }
826                 }
827
828                 // now, we have pre-mine outputs calculated and created for either absolute or percentage-based
829                 // pre-allocation
830
831                 // following that, we have either 1 stake guarded output to the staker or delegate,
832                 // or some number of miner outputs
833
834                 // now, start adding additional outputs, including chain-definition output for Notary chain and all currencies in ConnectedChains
835                 ConnectedChains.LoadReserveCurrencies();
836
837                 // create a currency definition output for this currency, the notary currency, and all reserves
838                 CCcontract_info CC;
839                 CCcontract_info *cp;
840                 cp = CCinit(&CC, EVAL_CURRENCY_DEFINITION);
841                 pkCC = CPubKey(ParseHex(CC.CChexstr));
842
843                 std::vector<CTxDestination> indexDests({CKeyID(ConnectedChains.ThisChain().GetConditionID(EVAL_CURRENCY_DEFINITION))});
844                 std::vector<CTxDestination> dests({pkCC});
845
846                 coinbaseTx.vout.push_back(CTxOut(0,
847                                             MakeMofNCCScript(CConditionObj<CCurrencyDefinition>(EVAL_CURRENCY_DEFINITION, dests, 1, 
848                                                              &ConnectedChains.ThisChain()),
849                                             &indexDests)));
850
851                 for (auto &oneCur : ConnectedChains.reserveCurrencies)
852                 {
853                     indexDests = std::vector<CTxDestination>({CKeyID(ConnectedChains.ThisChain().GetConditionID(EVAL_CURRENCY_DEFINITION)),
854                                                             CKeyID(oneCur.second.GetConditionID(EVAL_CURRENCY_DEFINITION))});
855                     coinbaseTx.vout.push_back(CTxOut(0,
856                                               MakeMofNCCScript(CConditionObj<CCurrencyDefinition>(EVAL_CURRENCY_DEFINITION, dests, 1, &oneCur.second),
857                                               &indexDests)));
858                 }
859
860                 if (!ConnectedChains.reserveCurrencies.count(ConnectedChains.NotaryChain().GetID()))
861                 {
862                     indexDests = std::vector<CTxDestination>({CKeyID(ConnectedChains.ThisChain().GetConditionID(EVAL_CURRENCY_DEFINITION)),
863                                                             CKeyID(ConnectedChains.NotaryChain().chainDefinition.GetConditionID(EVAL_CURRENCY_DEFINITION))});
864                     coinbaseTx.vout.push_back(CTxOut(0,
865                                               MakeMofNCCScript(CConditionObj<CCurrencyDefinition>(EVAL_CURRENCY_DEFINITION, dests, 1, 
866                                                                &ConnectedChains.NotaryChain().chainDefinition),
867                                               &indexDests)));
868                 }
869
870                 // create the import thread output
871                 cp = CCinit(&CC, EVAL_CROSSCHAIN_IMPORT);
872                 pkCC = CPubKey(ParseHex(CC.CChexstr));
873
874                 // import thread from PBaaS parent
875                 indexDests = std::vector<CTxDestination>({CKeyID(CCrossChainRPCData::GetConditionID(ConnectedChains.notaryChain.GetID(), EVAL_CROSSCHAIN_IMPORT))});
876                 dests = std::vector<CTxDestination>({pkCC});
877
878                 CCurrencyValueMap cvm;
879                 for (auto &inPair : ConnectedChains.ThisChain().preAllocation)
880                 {
881                     cvm.valueMap[inPair.first] = inPair.second;
882                 }
883                 CCrossChainImport cci = CCrossChainImport(ConnectedChains.notaryChain.GetID(), cvm);
884                 coinbaseTx.vout.push_back(CTxOut(currencyState.ReserveToNativeRaw(CCurrencyValueMap(thisChain.currencies, thisChain.preconverted), thisChain.conversions),
885                                                  MakeMofNCCScript(CConditionObj<CCrossChainImport>(EVAL_CROSSCHAIN_IMPORT, dests, 1, &cci), &indexDests)));
886
887                 // export thread to PBaaS parent
888                 cp = CCinit(&CC, EVAL_CROSSCHAIN_EXPORT);
889                 pkCC = CPubKey(ParseHex(CC.CChexstr));
890                 indexDests = std::vector<CTxDestination>({CKeyID(CCrossChainRPCData::GetConditionID(ConnectedChains.notaryChain.GetID(), EVAL_CROSSCHAIN_EXPORT))});
891                 dests = std::vector<CTxDestination>({pkCC});
892
893                 CCrossChainExport ccx(ConnectedChains.NotaryChain().GetID(), 0, CCurrencyValueMap(), CCurrencyValueMap());
894                 coinbaseTx.vout.push_back(CTxOut(0, MakeMofNCCScript(CConditionObj<CCrossChainExport>(EVAL_CROSSCHAIN_EXPORT, dests, 1, &ccx), &indexDests)));
895             }
896             else
897             {
898                 CBlock block;
899                 assert(nHeight > 1);
900                 currencyState = ConnectedChains.GetCurrencyState(nHeight - 1);
901                 currencyState.ClearForNextBlock();
902
903                 if (!currencyState.IsValid())
904                 {
905                     // we should be able to get a valid currency state, if not, fail
906                     LogPrintf("Unable to get initial currency state to create block #%d.\n", nHeight);
907                     printf("Failure to get initial currency state. Cannot create block #%d.\n", nHeight);
908                     return NULL;
909                 }
910             }
911
912             // update the currency state to include emissions before calculating conversions
913             // premine is an emission that is factored in before this
914             currencyState.UpdateWithEmission(totalEmission);
915
916             // add currency state output to coinbase
917             vKeys.clear();
918             cp = CCinit(&CC, EVAL_CURRENCYSTATE);
919
920             CPubKey currencyOutPK(ParseHex(cp->CChexstr));
921             std::vector<CTxDestination> indexDests({CKeyID(CCrossChainRPCData::GetConditionID(thisChainID, EVAL_CURRENCYSTATE))});
922             std::vector<CTxDestination> dests({currencyOutPK});
923
924             // pre-conversions go to the import thread
925             // conversions for this block, if any, will be processed
926             // below
927             coinbaseTx.vout.push_back(CTxOut(currencyState.ReserveToNativeRaw(CCurrencyValueMap(thisChain.currencies, thisChain.preconverted), thisChain.conversions),
928                                                 MakeMofNCCScript(CConditionObj<CCoinbaseCurrencyState>(EVAL_CROSSCHAIN_EXPORT, dests, 1, &currencyState), &indexDests)));
929
930             currencyStateOutNum = coinbaseTx.vout.size() - 1;
931
932             if (notaryConnected)
933             {
934                 // if we have access to our notary daemon
935                 // create a notarization if we would qualify to do so. add it to the mempool and next block
936                 CTransaction prevTx, crossTx, lastConfirmed, lastImportTx;
937                 ChainMerkleMountainView mmv = chainActive.GetMMV();
938                 mmrRoot = mmv.GetRoot();
939                 int32_t confirmedInput = -1;
940                 CTxDestination confirmedDest;
941                 if (CreateEarnedNotarization(newNotarizationTx, notarizationInputs, prevTx, crossTx, lastConfirmed, nHeight, &confirmedInput, &confirmedDest))
942                 {
943                     // we have a valid, earned notarization transaction. we still need to complete it as follows:
944                     // 1. Add an instant-spend input from the coinbase transaction to fund the finalization output
945                     //
946                     // 2. if we are spending finalization outputs, create an output of the same amount as a finalization output 
947                     //    plus and any excess from the other, orphaned finalizations to the creator of the confirmed notarization
948                     //
949                     // 3. make sure the currency state is correct
950
951                     // input should either be 0 or PBAAS_MINNOTARIZATIONOUTPUT + all finalized outputs
952                     // we will add PBAAS_MINNOTARIZATIONOUTPUT from a coinbase instant spend in all cases and double that when it is 0 for block 1
953                     for (const CTxIn& txin : newNotarizationTx.vin)
954                     {
955                         const uint256& prevHash = txin.prevout.hash;
956                         const CCoins *pcoins = view.AccessCoins(prevHash);
957                         pbaasTransparentIn += pcoins && (pcoins->vout.size() > txin.prevout.n) ? pcoins->vout[txin.prevout.n].nValue : 0;
958                     }
959
960                     // calculate the amount that will be sent to the confirmed notary address
961                     // this will only be non-zero if we have finalized inputs
962                     if (pbaasTransparentIn > 0)
963                     {
964                         pbaasTransparentOut = pbaasTransparentIn - PBAAS_MINNOTARIZATIONOUTPUT;
965                     }
966
967                     if (pbaasTransparentOut)
968                     {
969                         // if we are on a non-fungible chain, reward out must be unspendable
970                         // make a normal output to the confirmed notary with the excess right behind the op_return
971                         // TODO: make this a cc out to only allow spending on a fungible chain
972                         CTxOut rewardOut = CTxOut(pbaasTransparentOut, GetScriptForDestination(confirmedDest));
973                         newNotarizationTx.vout.insert(newNotarizationTx.vout.begin() + newNotarizationTx.vout.size() - 1, rewardOut);
974                     }
975
976                     // make the earned notarization coinbase output
977                     vKeys.clear();
978                     cp = CCinit(&CC, EVAL_EARNEDNOTARIZATION);
979
980                     // send this to EVAL_EARNEDNOTARIZATION address as a destination, locked by the default pubkey
981                     pkCC = CPubKey(ParseHex(cp->CChexstr));
982                     vKeys.push_back(CTxDestination(CKeyID(CCrossChainRPCData::GetConditionID(VERUS_CHAINID, EVAL_EARNEDNOTARIZATION))));
983
984                     int64_t needed = nHeight == 1 ? PBAAS_MINNOTARIZATIONOUTPUT << 1 : PBAAS_MINNOTARIZATIONOUTPUT;
985
986                     // output duplicate notarization as coinbase output for instant spend to notarization
987                     // the output amount is considered part of the total value of this coinbase
988                     CPBaaSNotarization pbn(newNotarizationTx);
989                     notarizationOut = MakeCC1of1Vout(EVAL_EARNEDNOTARIZATION, needed, pkCC, vKeys, pbn);
990                     coinbaseTx.vout.push_back(notarizationOut);
991                     notarizationOutNum = coinbaseTx.vout.size() - 1;
992
993                     // place the notarization
994                     pblock->vtx.push_back(CTransaction(newNotarizationTx));
995                     pblocktemplate->vTxFees.push_back(0);
996                     pblocktemplate->vTxSigOps.push_back(-1); // updated at end
997                     nBlockSize += GetSerializeSize(newNotarizationTx, SER_NETWORK, PROTOCOL_VERSION);
998                     notarizationTxIndex = pblock->vtx.size() - 1;
999                     nBlockTx++;
1000                 }
1001                 else if (nHeight == 1)
1002                 {
1003                     // failed to notarize at block 1
1004                     return NULL;
1005                 }
1006
1007                 // if we have a last confirmed notarization, then check for new imports from the notary chain
1008                 if (lastConfirmed.vout.size())
1009                 {
1010                     // we need to find the last unspent import transaction
1011                     std::vector<CAddressUnspentDbEntry> unspentOutputs;
1012
1013                     bool found = false;
1014
1015                     // we cannot get export to a chain that has shut down
1016                     // if the chain definition is spent, a chain is inactive
1017                     if (GetAddressUnspent(CKeyID(CCrossChainRPCData::GetConditionID(ConnectedChains.NotaryChain().GetID(), EVAL_CROSSCHAIN_IMPORT)), 1, unspentOutputs))
1018                     {
1019                         // if one spends the prior one, get the one that is not spent
1020                         for (auto txidx : unspentOutputs)
1021                         {
1022                             uint256 blkHash;
1023                             CTransaction itx;
1024                             if (myGetTransaction(txidx.first.txhash, lastImportTx, blkHash) &&
1025                                 CCrossChainImport(lastImportTx).IsValid() &&
1026                                 (lastImportTx.IsCoinBase() ||
1027                                 (myGetTransaction(lastImportTx.vin[0].prevout.hash, itx, blkHash) &&
1028                                 CCrossChainImport(itx).IsValid())))
1029                             {
1030                                 found = true;
1031                                 break;
1032                             }
1033                         }
1034                     }
1035
1036                     if (found && pwalletMain)
1037                     {
1038                         UniValue params(UniValue::VARR);
1039                         UniValue param(UniValue::VOBJ);
1040
1041                         CMutableTransaction txTemplate = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nHeight);
1042                         int i;
1043                         for (i = 0; i < lastImportTx.vout.size(); i++)
1044                         {
1045                             COptCCParams p;
1046                             if (lastImportTx.vout[i].scriptPubKey.IsPayToCryptoCondition(p) && p.IsValid() && p.evalCode == EVAL_CROSSCHAIN_IMPORT)
1047                             {
1048                                 txTemplate.vin.push_back(CTxIn(lastImportTx.GetHash(), (uint32_t)i));
1049                                 break;
1050                             }
1051                         }
1052
1053                         UniValue result = NullUniValue;
1054                         if (i < lastImportTx.vout.size())
1055                         {
1056                             param.push_back(Pair("name", thisChain.name));
1057                             param.push_back(Pair("lastimporttx", EncodeHexTx(lastImportTx)));
1058                             param.push_back(Pair("lastconfirmednotarization", EncodeHexTx(lastConfirmed)));
1059                             param.push_back(Pair("importtxtemplate", EncodeHexTx(txTemplate)));
1060                             param.push_back(Pair("totalimportavailable", lastImportTx.vout[txTemplate.vin[0].prevout.n].nValue));
1061                             params.push_back(param);
1062
1063                             try
1064                             {
1065                                 result = find_value(RPCCallRoot("getlatestimportsout", params), "result");
1066                             } catch (exception e)
1067                             {
1068                                 printf("Could not get latest imports from notary chain\n");
1069                             }
1070                         }
1071
1072                         if (result.isArray() && result.size())
1073                         {
1074                             LOCK(pwalletMain->cs_wallet);
1075
1076                             uint256 lastImportHash = lastImportTx.GetHash();
1077                             for (int i = 0; i < result.size(); i++)
1078                             {
1079                                 CTransaction itx;
1080                                 if (result[i].isStr() && DecodeHexTx(itx, result[i].get_str()) && itx.vin.size() && itx.vin[0].prevout.hash == lastImportHash)
1081                                 {
1082                                     // sign the transaction spending the last import and add to mempool
1083                                     CMutableTransaction mtx(itx);
1084                                     CCrossChainImport cci(lastImportTx);
1085
1086                                     bool signSuccess;
1087                                     SignatureData sigdata;
1088                                     CAmount value;
1089                                     const CScript *pScriptPubKey;
1090
1091                                     signSuccess = ProduceSignature(
1092                                         TransactionSignatureCreator(pwalletMain, &itx, 0, lastImportTx.vout[itx.vin[0].prevout.n].nValue, SIGHASH_ALL), lastImportTx.vout[itx.vin[0].prevout.n].scriptPubKey, sigdata, consensusBranchId);
1093
1094                                     if (!signSuccess)
1095                                     {
1096                                         break;
1097                                     }
1098
1099                                     UpdateTransaction(mtx, 0, sigdata);
1100                                     itx = CTransaction(mtx);
1101
1102                                     // commit to mempool and remove any conflicts
1103                                     std::list<CTransaction> removed;
1104                                     mempool.removeConflicts(itx, removed);
1105                                     CValidationState state;
1106                                     if (!myAddtomempool(itx, &state))
1107                                     {
1108                                         LogPrintf("Failed to add import transactions to the mempool due to: %s\n", state.GetRejectReason().c_str());
1109                                         printf("Failed to add import transactions to the mempool due to: %s\n", state.GetRejectReason().c_str());
1110                                         break;  // if we failed to add one, the others will fail to spend it
1111                                     }
1112
1113                                     lastImportTx = itx;
1114                                     lastImportHash = itx.GetHash();
1115                                 }
1116                             }
1117                         }
1118                     }
1119                 }
1120             }
1121         }
1122         else
1123         {
1124             CAmount blockOnePremine = thisChain.GetTotalPreallocation();
1125             SetBlockOnePremine(blockOnePremine);
1126             totalEmission = GetBlockSubsidy(nHeight, consensusParams);
1127             blockSubsidy = totalEmission;
1128             currencyState.UpdateWithEmission(totalEmission);
1129         }
1130
1131         // coinbase should have all necessary outputs (TODO: timelock is not supported yet)
1132         uint32_t nCoinbaseSize = GetSerializeSize(coinbaseTx, SER_NETWORK, PROTOCOL_VERSION);
1133         nBlockSize += nCoinbaseSize;
1134
1135         // now create the priority array, including market order reserve transactions, since they can always execute, leave limits for later
1136         bool haveReserveTransactions = false;
1137         uint32_t reserveExchangeLimitSize = 0;
1138         std::vector<CReserveTransactionDescriptor> limitOrders;
1139
1140         // now add transactions from the mem pool to the priority heap
1141         for (CTxMemPool::indexed_transaction_set::iterator mi = mempool.mapTx.begin();
1142              mi != mempool.mapTx.end(); ++mi)
1143         {
1144             const CTransaction& tx = mi->GetTx();
1145             uint256 hash = tx.GetHash();
1146             
1147             int64_t nLockTimeCutoff = (STANDARD_LOCKTIME_VERIFY_FLAGS & LOCKTIME_MEDIAN_TIME_PAST)
1148             ? nMedianTimePast
1149             : pblock->GetBlockTime();
1150
1151             if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight, nLockTimeCutoff) || IsExpiredTx(tx, nHeight))
1152             {
1153                 //fprintf(stderr,"coinbase.%d finaltx.%d expired.%d\n",tx.IsCoinBase(),IsFinalTx(tx, nHeight, nLockTimeCutoff),IsExpiredTx(tx, nHeight));
1154                 continue;
1155             }
1156
1157             if ( ASSETCHAINS_SYMBOL[0] == 0 && komodo_validate_interest(tx,nHeight,(uint32_t)pblock->nTime,0) < 0 )
1158             {
1159                 //fprintf(stderr,"CreateNewBlock: komodo_validate_interest failure nHeight.%d nTime.%u vs locktime.%u\n",nHeight,(uint32_t)pblock->nTime,(uint32_t)tx.nLockTime);
1160                 continue;
1161             }
1162
1163             COrphan* porphan = NULL;
1164             double dPriority = 0;
1165             CAmount nTotalIn = 0;
1166             CCurrencyValueMap totalReserveIn;
1167             bool fMissingInputs = false;
1168             CReserveTransactionDescriptor rtxd;
1169             bool isReserve = mempool.IsKnownReserveTransaction(hash, rtxd);
1170
1171             if (tx.IsCoinImport())
1172             {
1173                 CAmount nValueIn = GetCoinImportValue(tx);
1174                 nTotalIn += nValueIn;
1175                 dPriority += (double)nValueIn * 1000;  // flat multiplier
1176             } else {
1177                 // separate limit orders to be added later, we add them at the end, failed fill or kills are normal transactions, consider them reserve txs
1178                 if (isReserve && rtxd.IsReserveExchange() && rtxd.IsLimit())
1179                 {
1180                     // if we might expire, refresh and check again
1181                     if (rtxd.IsFillOrKill())
1182                     {
1183                         rtxd = CReserveTransactionDescriptor(tx, view, nHeight);
1184                         mempool.PrioritiseReserveTransaction(rtxd, currencyState);
1185                     }
1186
1187                     // if is is a failed conversion, drop through
1188                     if (!rtxd.IsFillOrKillFail())
1189                     {
1190                         limitOrders.push_back(rtxd);
1191                         reserveExchangeLimitSize += GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
1192                         continue;
1193                     }
1194                 }
1195                 if (isReserve)
1196                 {
1197                     nTotalIn += rtxd.nativeIn;
1198                     totalReserveIn += rtxd.ReserveInputMap();
1199                     if (rtxd.IsIdentity() && CNameReservation(tx).IsValid())
1200                     {
1201                         nCurrentIDSize += GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
1202                         if (nCurrentIDSize > nMaxIDSize)
1203                         {
1204                             continue;
1205                         }
1206                     }
1207                 }
1208                 BOOST_FOREACH(const CTxIn& txin, tx.vin)
1209                 {
1210                     CAmount nValueIn = 0;
1211                     CCurrencyValueMap reserveValueIn;
1212
1213                     // Read prev transaction
1214                     if (!view.HaveCoins(txin.prevout.hash))
1215                     {
1216                         // This should never happen; all transactions in the memory
1217                         // pool should connect to either transactions in the chain
1218                         // or other transactions in the memory pool.
1219                         if (!mempool.mapTx.count(txin.prevout.hash))
1220                         {
1221                             LogPrintf("ERROR: mempool transaction missing input\n");
1222                             if (fDebug) assert("mempool transaction missing input" == 0);
1223                             fMissingInputs = true;
1224                             if (porphan)
1225                                 vOrphan.pop_back();
1226                             break;
1227                         }
1228
1229                         // Has to wait for dependencies
1230                         if (!porphan)
1231                         {
1232                             // Use list for automatic deletion
1233                             vOrphan.push_back(COrphan(&tx));
1234                             porphan = &vOrphan.back();
1235                         }
1236                         mapDependers[txin.prevout.hash].push_back(porphan);
1237                         porphan->setDependsOn.insert(txin.prevout.hash);
1238
1239                         const CTransaction &otx = mempool.mapTx.find(txin.prevout.hash)->GetTx();
1240                         // consider reserve outputs and set priority according to their value here as well
1241                         if (isReserve)
1242                         {
1243                             totalReserveIn += otx.vout[txin.prevout.n].ReserveOutValue();
1244                         }
1245                         nTotalIn += otx.vout[txin.prevout.n].nValue;
1246                         continue;
1247                     }
1248                     const CCoins* coins = view.AccessCoins(txin.prevout.hash);
1249                     assert(coins);
1250
1251                     if (isReserve)
1252                     {
1253                         reserveValueIn = coins->vout[txin.prevout.n].ReserveOutValue();
1254                     }
1255
1256                     nValueIn = coins->vout[txin.prevout.n].nValue;
1257                     int nConf = nHeight - coins->nHeight;
1258
1259                     dPriority += ((double)((reserveValueIn.valueMap.size() ? currencyState.ReserveToNative(reserveValueIn) : 0) + nValueIn)) * nConf;
1260
1261                     if (!isReserve)
1262                     {
1263                         nTotalIn += nValueIn;
1264                         totalReserveIn += reserveValueIn;
1265                     }
1266                 }
1267                 nTotalIn += tx.GetShieldedValueIn();
1268             }
1269
1270             if (fMissingInputs) continue;
1271             
1272             // Priority is sum(valuein * age) / modified_txsize
1273             unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
1274             dPriority = tx.ComputePriority(dPriority, nTxSize);
1275             
1276             CAmount nDeltaValueIn = nTotalIn + (totalReserveIn.valueMap.size() ? currencyState.ReserveToNative(totalReserveIn) : 0);
1277             CAmount nFeeValueIn = nDeltaValueIn;
1278             mempool.ApplyDeltas(hash, dPriority, nDeltaValueIn);
1279
1280             CAmount nativeEquivalentOut = 0;
1281
1282             // if there is reserve in, or this is a reserveexchange transaction, calculate fee properly
1283             if (isReserve && rtxd.ReserveOutputMap().valueMap.size())
1284             {
1285                 // if this has reserve currency out, convert it to native currency for fee calculation
1286                 nativeEquivalentOut = currencyState.ReserveToNative(rtxd.ReserveOutputMap());
1287             }
1288
1289             CFeeRate feeRate(isReserve ? rtxd.AllFeesAsNative(currencyState) + currencyState.ReserveToNative(rtxd.ReserveConversionFeesMap()) + rtxd.nativeConversionFees : 
1290                                          nFeeValueIn - (tx.GetValueOut() + nativeEquivalentOut), nTxSize);
1291
1292             if (porphan)
1293             {
1294                 porphan->dPriority = dPriority;
1295                 porphan->feeRate = feeRate;
1296             }
1297             else
1298                 vecPriority.push_back(TxPriority(dPriority, feeRate, &(mi->GetTx())));
1299         }
1300
1301         //
1302         // NOW -- REALLY START TO FILL THE BLOCK
1303         //
1304         // estimate number of conversions, staking transaction size, and additional coinbase outputs that will be required
1305
1306         int32_t maxPreLimitOrderBlockSize = nBlockMaxSize - std::min(nBlockMaxSize >> 2, reserveExchangeLimitSize);
1307
1308         int64_t interest;
1309         bool fSortedByFee = (nBlockPrioritySize <= 0);
1310
1311         TxPriorityCompare comparer(fSortedByFee);
1312         std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
1313
1314         std::vector<int> reservePositions;
1315
1316         // now loop and fill the block, leaving space for reserve exchange limit transactions
1317         while (!vecPriority.empty())
1318         {
1319             // Take highest priority transaction off the priority queue:
1320             double dPriority = vecPriority.front().get<0>();
1321             CFeeRate feeRate = vecPriority.front().get<1>();
1322             const CTransaction& tx = *(vecPriority.front().get<2>());
1323             
1324             std::pop_heap(vecPriority.begin(), vecPriority.end(), comparer);
1325             vecPriority.pop_back();
1326             
1327             // Size limits
1328             unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
1329             if (nBlockSize + nTxSize >= maxPreLimitOrderBlockSize - autoTxSize) // room for extra autotx
1330             {
1331                 //fprintf(stderr,"nBlockSize %d + %d nTxSize >= %d maxPreLimitOrderBlockSize\n",(int32_t)nBlockSize,(int32_t)nTxSize,(int32_t)maxPreLimitOrderBlockSize);
1332                 continue;
1333             }
1334             
1335             // Legacy limits on sigOps:
1336             unsigned int nTxSigOps = GetLegacySigOpCount(tx);
1337             if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS-1)
1338             {
1339                 //fprintf(stderr,"A nBlockSigOps %d + %d nTxSigOps >= %d MAX_BLOCK_SIGOPS-1\n",(int32_t)nBlockSigOps,(int32_t)nTxSigOps,(int32_t)MAX_BLOCK_SIGOPS);
1340                 continue;
1341             }
1342             // Skip free transactions if we're past the minimum block size:
1343             const uint256& hash = tx.GetHash();
1344             double dPriorityDelta = 0;
1345             CAmount nFeeDelta = 0;
1346             mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta);
1347             if (fSortedByFee && (dPriorityDelta <= 0) && (nFeeDelta <= 0) && (feeRate < ::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize))
1348             {
1349                 //fprintf(stderr,"fee rate skip\n");
1350                 continue;
1351             }
1352
1353             // Prioritise by fee once past the priority size or we run out of high-priority
1354             // transactions:
1355             if (!fSortedByFee &&
1356                 ((nBlockSize + nTxSize >= nBlockPrioritySize) || !AllowFree(dPriority)))
1357             {
1358                 fSortedByFee = true;
1359                 comparer = TxPriorityCompare(fSortedByFee);
1360                 std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
1361             }
1362             
1363             if (!view.HaveInputs(tx))
1364             {
1365                 //fprintf(stderr,"dont have inputs\n");
1366                 continue;
1367             }
1368             CAmount nTxFees;
1369             CReserveTransactionDescriptor txDesc;
1370             bool isReserve = mempool.IsKnownReserveTransaction(hash, txDesc);
1371
1372             nTxFees = view.GetValueIn(chainActive.LastTip()->GetHeight(),&interest,tx,chainActive.LastTip()->nTime)-tx.GetValueOut();
1373             
1374             nTxSigOps += GetP2SHSigOpCount(tx, view);
1375             if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS-1)
1376             {
1377                 //fprintf(stderr,"B nBlockSigOps %d + %d nTxSigOps >= %d MAX_BLOCK_SIGOPS-1\n",(int32_t)nBlockSigOps,(int32_t)nTxSigOps,(int32_t)MAX_BLOCK_SIGOPS);
1378                 continue;
1379             }
1380
1381             // Note that flags: we don't want to set mempool/IsStandard()
1382             // policy here, but we still have to ensure that the block we
1383             // create only contains transactions that are valid in new blocks.
1384             CValidationState state;
1385             PrecomputedTransactionData txdata(tx);
1386             if (!ContextualCheckInputs(tx, state, view, nHeight, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId))
1387             {
1388                 //fprintf(stderr,"context failure\n");
1389                 continue;
1390             }
1391
1392             UpdateCoins(tx, view, nHeight);
1393
1394             if (isReserve)
1395             {
1396                 nTxFees = 0;            // we will adjust all reserve transaction fees when we get an accurate conversion rate
1397                 reservePositions.push_back(nBlockTx);
1398                 haveReserveTransactions = true;
1399             }
1400
1401             BOOST_FOREACH(const OutputDescription &outDescription, tx.vShieldedOutput) {
1402                 sapling_tree.append(outDescription.cm);
1403             }
1404
1405             // Added
1406             pblock->vtx.push_back(tx);
1407             pblocktemplate->vTxFees.push_back(nTxFees);
1408             pblocktemplate->vTxSigOps.push_back(nTxSigOps);
1409             nBlockSize += nTxSize;
1410             ++nBlockTx;
1411             nBlockSigOps += nTxSigOps;
1412             nFees += nTxFees;
1413             
1414             if (fPrintPriority)
1415             {
1416                 LogPrintf("priority %.1f fee %s txid %s\n",dPriority, feeRate.ToString(), tx.GetHash().ToString());
1417             }
1418             
1419             // Add transactions that depend on this one to the priority queue
1420             if (mapDependers.count(hash))
1421             {
1422                 BOOST_FOREACH(COrphan* porphan, mapDependers[hash])
1423                 {
1424                     if (!porphan->setDependsOn.empty())
1425                     {
1426                         porphan->setDependsOn.erase(hash);
1427                         if (porphan->setDependsOn.empty())
1428                         {
1429                             vecPriority.push_back(TxPriority(porphan->dPriority, porphan->feeRate, porphan->ptx));
1430                             std::push_heap(vecPriority.begin(), vecPriority.end(), comparer);
1431                         }
1432                     }
1433                 }
1434             }
1435         }
1436
1437         // if we have reserve transactions or limit transactions to add:
1438         // 1. collect all the reserve transactions from the block and add them to the reserveFills vector
1439         // 2. add all limit transactions to the orders vector
1440         // 3. match orders to include all limit transactions that qualify and will fit
1441         CAmount conversionFees = 0;
1442
1443         if (haveReserveTransactions)
1444         {
1445             std::vector<CReserveTransactionDescriptor> reserveFills;
1446             std::vector<CReserveTransactionDescriptor> noFills;
1447             std::vector<const CReserveTransactionDescriptor *> expiredFillOrKills;
1448             std::vector<const CReserveTransactionDescriptor *> rejects;
1449
1450             // identify all reserve transactions in the block to calculate fees
1451             for (int i = 0; i < reservePositions.size(); i++)
1452             {
1453                 CReserveTransactionDescriptor txDesc;
1454                 if (mempool.IsKnownReserveTransaction(pblock->vtx[reservePositions[i]].GetHash(), txDesc))
1455                 {
1456                     reserveFills.push_back(txDesc);
1457                 }
1458             }
1459
1460             // now, we need to have room for the transaction which will spend the coinbase
1461             // and output all conversions mined/staked
1462             newConversionOutputTx = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nHeight);
1463             newConversionOutputTx.vin.resize(1); // placeholder for size calculation
1464
1465             int64_t newBlockSize = nBlockSize;
1466
1467             // TODO:PBAAS - NEED TO ADD SIGOPS LIMIT TO THIS FOR HARDENING
1468             CCoinbaseCurrencyState newState = currencyState.MatchOrders(limitOrders,
1469                                                                         reserveFills,
1470                                                                         noFills,
1471                                                                         expiredFillOrKills,
1472                                                                         rejects,
1473                                                                         exchangeRate, 
1474                                                                         nHeight, 
1475                                                                         conversionInputs,
1476                                                                         nBlockMaxSize - autoTxSize, 
1477                                                                         &newBlockSize, 
1478                                                                         &newConversionOutputTx);
1479
1480             // TODO:PBAAS - account for the edge case where we have too large expected fills and have no room
1481             // for transactions that we would otherwise take
1482             assert(reserveFills.size() >= reservePositions.size());
1483
1484             // create the conversion transaction and all outputs indicated by every single mined transaction
1485             if (reserveFills.size())
1486             {
1487                 currencyState = newState;
1488             }
1489
1490             int oldRPSize = reservePositions.size();
1491
1492             // add the rest of the reserve fills that have not yet been added to the block,
1493             for (int i = oldRPSize; i < reserveFills.size(); i++)
1494             {
1495                 // add these transactions to the block
1496                 reservePositions.push_back(nBlockTx);
1497                 pblock->vtx.push_back(*reserveFills[i].ptx);
1498                 const CTransaction &tx = pblock->vtx.back();
1499
1500                 UpdateCoins(tx, view, nHeight);
1501
1502                 BOOST_FOREACH(const OutputDescription &outDescription, tx.vShieldedOutput) {
1503                     sapling_tree.append(outDescription.cm);
1504                 }
1505
1506                 CAmount nTxFees = reserveFills[i].AllFeesAsNative(currencyState, exchangeRate);
1507                 uint32_t nTxSigOps = GetLegacySigOpCount(tx);
1508
1509                 // size was already updated
1510                 pblocktemplate->vTxFees.push_back(nTxFees);
1511                 pblocktemplate->vTxSigOps.push_back(nTxSigOps);
1512                 ++nBlockTx;
1513                 nBlockSigOps += nTxSigOps;
1514                 nFees += nTxFees;
1515             }
1516
1517             // update block size with the calculation from the function called, which includes all additional transactions, 
1518             // but does not include the conversion transaction, since its final size is still unknown
1519             nBlockSize = newBlockSize;
1520
1521             // fixup the transaction block template fees that were added before we knew the correct exchange rate and
1522             // add them to the block fee total
1523             for (int i = 0; i < oldRPSize; i++)
1524             {
1525                 assert(pblocktemplate->vTxFees.size() > reservePositions[i]);
1526                 CAmount nTxFees = reserveFills[i].AllFeesAsNative(currencyState, exchangeRate);
1527                 pblocktemplate->vTxFees[reservePositions[i]] = nTxFees;
1528                 nFees += nTxFees;
1529             }
1530
1531             // remake the newConversionOutputTx, right now, it has dummy inputs and placeholder outputs, just remake it correctly
1532             newConversionOutputTx.vin.resize(1);
1533             newConversionOutputTx.vout.clear();
1534             conversionInputs.clear();
1535
1536             // keep one placeholder for txCoinbase output as input and remake with the correct exchange rate
1537             for (auto fill : reserveFills)
1538             {
1539                 fill.AddConversionInOuts(newConversionOutputTx, conversionInputs, CCurrencyValueMap(currencyState.currencies, exchangeRate), &currencyState);
1540             }
1541         }
1542
1543         // first calculate and distribute block rewards, including fees in the minerOutputs vector
1544         CAmount rewardTotalShareAmount = 0;
1545         CAmount rewardTotal = blockSubsidy + 
1546                               currencyState.nativeConversionFees + 
1547                               currencyState.ReserveToNativeRaw(CCurrencyValueMap(currencyState.currencies, currencyState.conversionFees), exchangeRate) + 
1548                               currencyState.ReserveToNativeRaw(CCurrencyValueMap(currencyState.currencies, currencyState.fees), exchangeRate) + 
1549                               nFees;
1550
1551         CAmount rewardLeft = notarizationTxIndex ? rewardTotal - notarizationOut.nValue : rewardTotal;
1552
1553         // now that we have the total reward, update the coinbase outputs
1554         if (isStake)
1555         {
1556             coinbaseTx.vout[0].nValue = rewardLeft;
1557         }
1558         else
1559         {
1560             for (auto &outputShare : minerOutputs)
1561             {
1562                 rewardTotalShareAmount += outputShare.first;
1563             }
1564
1565             int cbOutIdx;
1566             for (cbOutIdx = 0; cbOutIdx < minerOutputs.size(); cbOutIdx++)
1567             {
1568                 CAmount amount = (arith_uint256(rewardTotal) * arith_uint256(minerOutputs[cbOutIdx].first) / arith_uint256(rewardTotalShareAmount)).GetLow64();
1569                 if (rewardLeft <= amount || (cbOutIdx + 1) == minerOutputs.size())
1570                 {
1571                     amount = rewardLeft;
1572                 }
1573                 rewardLeft -= amount;
1574                 coinbaseTx.vout[cbOutIdx].nValue = amount;
1575                 // the only valid CC output we currently support on coinbases is stake guard, which does not need to be modified for this
1576             }
1577         }
1578
1579         // currencyStateOut - update currency state, output is present whether or not there is a conversion transaction
1580         // the transaction itself pays no fees, but all conversion fees are included for each conversion transaction between its input and this output
1581         if (currencyStateOut.scriptPubKey.size())
1582         {
1583             COptCCParams p;
1584             currencyStateOut.scriptPubKey.IsPayToCryptoCondition(p);
1585             p.vData[0] = currencyState.AsVector();
1586             currencyStateOut.scriptPubKey.ReplaceCCParams(p);
1587
1588             if (conversionInputs.size())
1589             {
1590                 CTransaction convertTx(newConversionOutputTx);
1591                 currencyStateOut.nValue = convertTx.GetValueOut();
1592
1593                 auto reserveOutMap = convertTx.GetReserveValueOut();
1594                 for (int i = 0; i < currencyState.currencies.size(); i++)
1595                 {
1596                     auto it = reserveOutMap.valueMap.find(currencyState.currencies[i]);
1597                     currencyState.reserveOut[i] = (it != reserveOutMap.valueMap.end()) ? it->second : 0;
1598                 }
1599
1600                 // the coinbase is not finished, store index placeholder here now and fixup hash later
1601                 newConversionOutputTx.vin[0] = CTxIn(uint256(), currencyStateOutNum);
1602             }
1603             else
1604             {
1605                 newConversionOutputTx.vin.clear();
1606                 newConversionOutputTx.vout.clear();
1607             }
1608
1609             coinbaseTx.vout[currencyStateOutNum] = currencyStateOut;
1610         }
1611
1612         // notarizationOut - update currencyState in notarization
1613         if (notarizationTxIndex)
1614         {
1615             COptCCParams p;
1616             int i;
1617             for (i = 0; i < newNotarizationTx.vout.size(); i++)
1618             {
1619                 if (newNotarizationTx.vout[i].scriptPubKey.IsPayToCryptoCondition(p) && p.evalCode == EVAL_EARNEDNOTARIZATION)
1620                 {
1621                     break;
1622                 }
1623             }
1624             if (i >= newNotarizationTx.vout.size())
1625             {
1626                 LogPrintf("CreateNewBlock: bad notarization\n");
1627                 fprintf(stderr,"CreateNewBlock: bad notarization\n");
1628                 return NULL;
1629             }
1630             CPBaaSNotarization nz(p.vData[0]);
1631             nz.currencyState = currencyState;
1632             p.vData[0] = nz.AsVector();
1633             newNotarizationTx.vout[i].scriptPubKey.ReplaceCCParams(p);
1634
1635             notarizationOut.scriptPubKey.IsPayToCryptoCondition(p);
1636             p.vData[0] = nz.AsVector();
1637             notarizationOut.scriptPubKey.ReplaceCCParams(p);
1638
1639             coinbaseTx.vout[notarizationOutNum] = notarizationOut;
1640
1641             // now that the coinbase is finished, finish and place conversion transaction before the stake transaction
1642             newNotarizationTx.vin.push_back(CTxIn(uint256(), notarizationOutNum));
1643
1644             pblock->vtx[notarizationTxIndex] = newNotarizationTx;
1645         }
1646
1647         nLastBlockTx = nBlockTx;
1648         nLastBlockSize = nBlockSize;
1649
1650         blocktime = std::max(pindexPrev->GetMedianTimePast(), GetAdjustedTime());
1651
1652         pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus());
1653
1654         coinbaseTx.nExpiryHeight = 0;
1655         coinbaseTx.nLockTime = blocktime;
1656
1657         if ( ASSETCHAINS_SYMBOL[0] == 0 && IS_KOMODO_NOTARY != 0 && My_notaryid >= 0 )
1658             coinbaseTx.vout[0].nValue += 5000;
1659
1660         /*
1661         // check if coinbase transactions must be time locked at current subsidy and prepend the time lock
1662         // to transaction if so, cast for GTE operator
1663         CAmount cbValueOut = 0;
1664         for (auto txout : coinbaseTx.vout)
1665         {
1666             cbValueOut += txout.nValue;
1667         }
1668         if (cbValueOut >= ASSETCHAINS_TIMELOCKGTE)
1669         {
1670             int32_t opretlen, p2shlen, scriptlen;
1671             CScriptExt opretScript = CScriptExt();
1672
1673             coinbaseTx.vout.push_back(CTxOut());
1674
1675             // prepend time lock to original script unless original script is P2SH, in which case, we will leave the coins
1676             // protected only by the time lock rather than 100% inaccessible
1677             opretScript.AddCheckLockTimeVerify(komodo_block_unlocktime(nHeight));
1678             if (scriptPubKeyIn.IsPayToScriptHash() || scriptPubKeyIn.IsPayToCryptoCondition())
1679             {
1680                 LogPrintf("CreateNewBlock: attempt to add timelock to pay2sh or pay2cc\n");
1681                 fprintf(stderr,"CreateNewBlock: attempt to add timelock to pay2sh or pay2cc\n");
1682                 return 0;
1683             }
1684             
1685             opretScript += scriptPubKeyIn;
1686
1687             coinbaseTx.vout[0].scriptPubKey = CScriptExt().PayToScriptHash(CScriptID(opretScript));
1688             coinbaseTx.vout.back().scriptPubKey = CScriptExt().OpReturnScript(opretScript, OPRETTYPE_TIMELOCK);
1689             coinbaseTx.vout.back().nValue = 0;
1690         } // timelocks and commissions are currently incompatible due to validation complexity of the combination
1691         else if ( nHeight > 1 && ASSETCHAINS_SYMBOL[0] != 0 && ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 && ASSETCHAINS_COMMISSION != 0 && (commission= komodo_commission((CBlock*)&pblocktemplate->block)) != 0 )
1692         {
1693             int32_t i; uint8_t *ptr;
1694             coinbaseTx.vout.resize(2);
1695             coinbaseTx.vout[1].nValue = commission;
1696             coinbaseTx.vout[1].scriptPubKey.resize(35);
1697             ptr = (uint8_t *)&coinbaseTx.vout[1].scriptPubKey[0];
1698             ptr[0] = 33;
1699             for (i=0; i<33; i++)
1700                 ptr[i+1] = ASSETCHAINS_OVERRIDE_PUBKEY33[i];
1701             ptr[34] = OP_CHECKSIG;
1702             //printf("autocreate commision vout\n");
1703         }
1704         */
1705
1706         // finalize input of coinbase
1707         coinbaseTx.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(0)) + COINBASE_FLAGS;
1708         assert(coinbaseTx.vin[0].scriptSig.size() <= 100);
1709
1710         // coinbase is done
1711         pblock->vtx[0] = coinbaseTx;
1712         uint256 cbHash = coinbaseTx.GetHash();
1713
1714         // if there is a conversion, update the correct coinbase hash and add it to the block
1715         // we also need to sign the conversion transaction
1716         if (newConversionOutputTx.vin.size() > 1)
1717         {
1718             // put the coinbase into the updated coins, since we will spend from it
1719             UpdateCoins(pblock->vtx[0], view, nHeight);
1720
1721             newConversionOutputTx.vin[0].prevout.hash = cbHash;
1722
1723             CTransaction ncoTx(newConversionOutputTx);
1724
1725             // sign transaction for cb output and conversions
1726             for (int i = 0; i < ncoTx.vin.size(); i++)
1727             {
1728                 bool signSuccess;
1729                 SignatureData sigdata;
1730                 CAmount value;
1731                 const CScript *pScriptPubKey;
1732
1733                 // if this is our coinbase input, different signing
1734                 if (i)
1735                 {
1736                     pScriptPubKey = &conversionInputs[i - 1].scriptPubKey;
1737                     value = conversionInputs[i - 1].nValue;
1738                 }
1739                 else
1740                 {
1741                     pScriptPubKey = &coinbaseTx.vout[ncoTx.vin[i].prevout.n].scriptPubKey;
1742                     value = coinbaseTx.vout[ncoTx.vin[i].prevout.n].nValue;
1743                 }
1744
1745                 signSuccess = ProduceSignature(TransactionSignatureCreator(pwalletMain, &ncoTx, i, value, SIGHASH_ALL), *pScriptPubKey, sigdata, consensusBranchId);
1746
1747                 if (!signSuccess)
1748                 {
1749                     if (ncoTx.vin[i].prevout.hash == coinbaseTx.GetHash())
1750                     {
1751                         LogPrintf("Coinbase conversion source tx id: %s\n", coinbaseTx.GetHash().GetHex().c_str());
1752                         printf("Coinbase conversion source tx - amount: %lu, n: %d, id: %s\n", coinbaseTx.vout[ncoTx.vin[i].prevout.n].nValue, ncoTx.vin[i].prevout.n, coinbaseTx.GetHash().GetHex().c_str());
1753                     }
1754                     LogPrintf("CreateNewBlock: failure to sign conversion tx for input %d from output %d of %s\n", i, ncoTx.vin[i].prevout.n, ncoTx.vin[i].prevout.hash.GetHex().c_str());
1755                     printf("CreateNewBlock: failure to sign conversion tx for input %d from output %d of %s\n", i, ncoTx.vin[i].prevout.n, ncoTx.vin[i].prevout.hash.GetHex().c_str());
1756                     return NULL;
1757                 } else {
1758                     UpdateTransaction(newConversionOutputTx, i, sigdata);
1759                 }
1760             }
1761
1762             UpdateCoins(newConversionOutputTx, view, nHeight);
1763             pblock->vtx.push_back(newConversionOutputTx);
1764             pblocktemplate->vTxFees.push_back(0);
1765             int txSigOps = GetLegacySigOpCount(newConversionOutputTx);
1766             pblocktemplate->vTxSigOps.push_back(txSigOps);
1767             nBlockSize += GetSerializeSize(newConversionOutputTx, SER_NETWORK, PROTOCOL_VERSION);
1768             ++nBlockTx;
1769             nBlockSigOps += txSigOps;
1770         }
1771
1772         // if there is a stake transaction, add it to the very end
1773         if (isStake)
1774         {
1775             UpdateCoins(txStaked, view, nHeight);
1776             pblock->vtx.push_back(txStaked);
1777             pblocktemplate->vTxFees.push_back(0);
1778             int txSigOps = GetLegacySigOpCount(txStaked);
1779             pblocktemplate->vTxSigOps.push_back(txSigOps);
1780             // already added to the block size above
1781             ++nBlockTx;
1782             nBlockSigOps += txSigOps;
1783         }
1784
1785         extern CWallet *pwalletMain;
1786
1787         // add final notarization and instant spend coinbase output hash fixup
1788         if (notarizationTxIndex)
1789         {
1790             LOCK(pwalletMain->cs_wallet);
1791
1792             newNotarizationTx.vin.back().prevout.hash = cbHash;
1793
1794             CTransaction ntx(newNotarizationTx);
1795
1796             for (int i = 0; i < ntx.vin.size(); i++)
1797             {
1798                 bool signSuccess;
1799                 SignatureData sigdata;
1800                 CAmount value;
1801                 const CScript *pScriptPubKey;
1802
1803                 // if this is our coinbase input, we won't find it elsewhere
1804                 if (i < notarizationInputs.size())
1805                 {
1806                     pScriptPubKey = &notarizationInputs[i].scriptPubKey;
1807                     value = notarizationInputs[i].nValue;
1808                 }
1809                 else
1810                 {
1811                     pScriptPubKey = &coinbaseTx.vout[ntx.vin[i].prevout.n].scriptPubKey;
1812                     value = coinbaseTx.vout[ntx.vin[i].prevout.n].nValue;
1813                 }
1814
1815                 signSuccess = ProduceSignature(TransactionSignatureCreator(pwalletMain, &ntx, i, value, SIGHASH_ALL), *pScriptPubKey, sigdata, consensusBranchId);
1816
1817                 if (!signSuccess)
1818                 {
1819                     if (ntx.vin[i].prevout.hash == coinbaseTx.GetHash())
1820                     {
1821                         LogPrintf("Coinbase source tx id: %s\n", coinbaseTx.GetHash().GetHex().c_str());
1822                         printf("Coinbase source tx - amount: %lu, n: %d, id: %s\n", coinbaseTx.vout[ntx.vin[i].prevout.n].nValue, ntx.vin[i].prevout.n, coinbaseTx.GetHash().GetHex().c_str());
1823                     }
1824                     LogPrintf("CreateNewBlock: failure to sign earned notarization for input %d from output %d of %s\n", i, ntx.vin[i].prevout.n, ntx.vin[i].prevout.hash.GetHex().c_str());
1825                     printf("CreateNewBlock: failure to sign earned notarization for input %d from output %d of %s\n", i, ntx.vin[i].prevout.n, ntx.vin[i].prevout.hash.GetHex().c_str());
1826                     return NULL;
1827                 } else {
1828                     UpdateTransaction(newNotarizationTx, i, sigdata);
1829                 }
1830             }
1831             pblocktemplate->vTxSigOps[notarizationTxIndex] = GetLegacySigOpCount(newNotarizationTx);
1832
1833             // put now signed notarization back in the block
1834             pblock->vtx[notarizationTxIndex] = newNotarizationTx;
1835
1836             LogPrintf("Coinbase source tx id: %s\n", coinbaseTx.GetHash().GetHex().c_str());
1837             //printf("Coinbase source tx id: %s\n", coinbaseTx.GetHash().GetHex().c_str());
1838             LogPrintf("adding notarization tx at height %d, index %d, id: %s\n", nHeight, notarizationTxIndex, newNotarizationTx.GetHash().GetHex().c_str());
1839             //printf("adding notarization tx at height %d, index %d, id: %s\n", nHeight, notarizationTxIndex, mntx.GetHash().GetHex().c_str());
1840             {
1841                 LOCK(cs_main);
1842                 for (auto input : newNotarizationTx.vin)
1843                 {
1844                     LogPrintf("Earned notarization input n: %d, hash: %s, HaveCoins: %s\n", input.prevout.n, input.prevout.hash.GetHex().c_str(), pcoinsTip->HaveCoins(input.prevout.hash) ? "true" : "false");
1845                     //printf("Earned notarization input n: %d, hash: %s, HaveCoins: %s\n", input.prevout.n, input.prevout.hash.GetHex().c_str(), pcoinsTip->HaveCoins(input.prevout.hash) ? "true" : "false");
1846                 }
1847             }
1848         }
1849
1850         pblock->vtx[0] = coinbaseTx;
1851         pblocktemplate->vTxFees[0] = -nFees;
1852         pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
1853
1854         // if not Verus stake, setup nonce, otherwise, leave it alone
1855         if (!isStake || ASSETCHAINS_LWMAPOS == 0)
1856         {
1857             // Randomize nonce
1858             arith_uint256 nonce = UintToArith256(GetRandHash());
1859
1860             // Clear the top 16 and bottom 16 or 24 bits (for local use as thread flags and counters)
1861             nonce <<= ASSETCHAINS_NONCESHIFT[ASSETCHAINS_ALGO];
1862             nonce >>= 16;
1863             pblock->nNonce = ArithToUint256(nonce);
1864         }
1865         
1866         // Fill in header
1867         pblock->hashPrevBlock  = pindexPrev->GetBlockHash();
1868         pblock->hashFinalSaplingRoot   = sapling_tree.root();
1869
1870         // all Verus PoS chains need this data in the block at all times
1871         if ( ASSETCHAINS_LWMAPOS || ASSETCHAINS_SYMBOL[0] == 0 || ASSETCHAINS_STAKED == 0 || KOMODO_MININGTHREADS > 0 )
1872         {
1873             UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
1874             pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus());
1875         }
1876
1877         if ( ASSETCHAINS_SYMBOL[0] == 0 && IS_KOMODO_NOTARY != 0 && My_notaryid >= 0 )
1878         {
1879             uint32_t r;
1880             CMutableTransaction txNotary = CreateNewContextualCMutableTransaction(Params().GetConsensus(), chainActive.Height() + 1);
1881             if ( pblock->nTime < pindexPrev->nTime+60 )
1882                 pblock->nTime = pindexPrev->nTime + 60;
1883             if ( gpucount < 33 )
1884             {
1885                 uint8_t tmpbuffer[40]; uint32_t r; int32_t n=0; uint256 randvals;
1886                 memcpy(&tmpbuffer[n],&My_notaryid,sizeof(My_notaryid)), n += sizeof(My_notaryid);
1887                 memcpy(&tmpbuffer[n],&Mining_height,sizeof(Mining_height)), n += sizeof(Mining_height);
1888                 memcpy(&tmpbuffer[n],&pblock->hashPrevBlock,sizeof(pblock->hashPrevBlock)), n += sizeof(pblock->hashPrevBlock);
1889                 vcalc_sha256(0,(uint8_t *)&randvals,tmpbuffer,n);
1890                 memcpy(&r,&randvals,sizeof(r));
1891                 pblock->nTime += (r % (33 - gpucount)*(33 - gpucount));
1892             }
1893             if ( komodo_notaryvin(txNotary,NOTARY_PUBKEY33) > 0 )
1894             {
1895                 CAmount txfees = 5000;
1896                 pblock->vtx.push_back(txNotary);
1897                 pblocktemplate->vTxFees.push_back(txfees);
1898                 pblocktemplate->vTxSigOps.push_back(GetLegacySigOpCount(txNotary));
1899                 nFees += txfees;
1900                 pblocktemplate->vTxFees[0] = -nFees;
1901                 //*(uint64_t *)(&pblock->vtx[0].vout[0].nValue) += txfees;
1902                 //fprintf(stderr,"added notaryvin\n");
1903             }
1904             else
1905             {
1906                 fprintf(stderr,"error adding notaryvin, need to create 0.0001 utxos\n");
1907                 return(0);
1908             }
1909         }
1910         else if ( ASSETCHAINS_CC == 0 && pindexPrev != 0 && ASSETCHAINS_STAKED == 0 && (ASSETCHAINS_SYMBOL[0] != 0 || IS_KOMODO_NOTARY == 0 || My_notaryid < 0) )
1911         {
1912             CValidationState state;
1913             //fprintf(stderr,"check validity\n");
1914             if ( !TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) // invokes CC checks
1915             {
1916                 throw std::runtime_error("CreateNewBlock(): TestBlockValidity failed");
1917             }
1918             //fprintf(stderr,"valid\n");
1919         }
1920     }
1921     //fprintf(stderr,"done new block\n");
1922
1923     // setup the header and buid the Merkle tree
1924     unsigned int extraNonce;
1925     IncrementExtraNonce(pblock, pindexPrev, extraNonce, true);
1926
1927     return pblocktemplate.release();
1928 }
1929  
1930 /*
1931  #ifdef ENABLE_WALLET
1932  boost::optional<CScript> GetMinerScriptPubKey(CReserveKey& reservekey)
1933  #else
1934  boost::optional<CScript> GetMinerScriptPubKey()
1935  #endif
1936  {
1937  CKeyID keyID;
1938  CBitcoinAddress addr;
1939  if (addr.SetString(GetArg("-mineraddress", ""))) {
1940  addr.GetKeyID(keyID);
1941  } else {
1942  #ifdef ENABLE_WALLET
1943  CPubKey pubkey;
1944  if (!reservekey.GetReservedKey(pubkey)) {
1945  return boost::optional<CScript>();
1946  }
1947  keyID = pubkey.GetID();
1948  #else
1949  return boost::optional<CScript>();
1950  #endif
1951  }
1952  
1953  CScript scriptPubKey = CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
1954  return scriptPubKey;
1955  }
1956  
1957  #ifdef ENABLE_WALLET
1958  CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey)
1959  {
1960  boost::optional<CScript> scriptPubKey = GetMinerScriptPubKey(reservekey);
1961  #else
1962  CBlockTemplate* CreateNewBlockWithKey()
1963  {
1964  boost::optional<CScript> scriptPubKey = GetMinerScriptPubKey();
1965  #endif
1966  
1967  if (!scriptPubKey) {
1968  return NULL;
1969  }
1970  return CreateNewBlock(*scriptPubKey);
1971  }*/
1972
1973 //////////////////////////////////////////////////////////////////////////////
1974 //
1975 // Internal miner
1976 //
1977
1978 #ifdef ENABLE_MINING
1979
1980 class MinerAddressScript : public CReserveScript
1981 {
1982     // CReserveScript requires implementing this function, so that if an
1983     // internal (not-visible) wallet address is used, the wallet can mark it as
1984     // important when a block is mined (so it then appears to the user).
1985     // If -mineraddress is set, the user already knows about and is managing the
1986     // address, so we don't need to do anything here.
1987     void KeepScript() {}
1988 };
1989
1990 void GetScriptForMinerAddress(boost::shared_ptr<CReserveScript> &script)
1991 {
1992     CTxDestination addr = DecodeDestination(GetArg("-mineraddress", ""));
1993     if (!IsValidDestination(addr)) {
1994         return;
1995     }
1996
1997     boost::shared_ptr<MinerAddressScript> mAddr(new MinerAddressScript());
1998     CKeyID keyID = boost::get<CKeyID>(addr);
1999
2000     script = mAddr;
2001     script->reserveScript = CScript() << OP_DUP << OP_HASH160 << ToByteVector(keyID) << OP_EQUALVERIFY << OP_CHECKSIG;
2002 }
2003
2004 #ifdef ENABLE_WALLET
2005 //////////////////////////////////////////////////////////////////////////////
2006 //
2007 // Internal miner
2008 //
2009
2010 CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, int32_t gpucount, bool isStake)
2011 {
2012     CPubKey pubkey; CScript scriptPubKey; uint8_t *ptr; int32_t i;
2013     if ( nHeight == 1 && ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 )
2014     {
2015         scriptPubKey = CScript() << ParseHex(ASSETCHAINS_OVERRIDE_PUBKEY) << OP_CHECKSIG;
2016     }
2017     else if ( USE_EXTERNAL_PUBKEY != 0 )
2018     {
2019         //fprintf(stderr,"use notary pubkey\n");
2020         scriptPubKey = CScript() << ParseHex(NOTARY_PUBKEY) << OP_CHECKSIG;
2021     }
2022     else
2023     {
2024         if (!isStake)
2025         {
2026             if (!reservekey.GetReservedKey(pubkey))
2027             {
2028                 return NULL;
2029             }
2030             scriptPubKey.resize(35);
2031             ptr = (uint8_t *)pubkey.begin();
2032             scriptPubKey[0] = 33;
2033             for (i=0; i<33; i++)
2034                 scriptPubKey[i+1] = ptr[i];
2035             scriptPubKey[34] = OP_CHECKSIG;
2036             //scriptPubKey = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
2037         }
2038     }
2039     return CreateNewBlock(Params(), scriptPubKey, gpucount, isStake);
2040 }
2041
2042 void komodo_broadcast(const CBlock *pblock,int32_t limit)
2043 {
2044     int32_t n = 1;
2045     //fprintf(stderr,"broadcast new block t.%u\n",(uint32_t)time(NULL));
2046     {
2047         LOCK(cs_vNodes);
2048         BOOST_FOREACH(CNode* pnode, vNodes)
2049         {
2050             if ( pnode->hSocket == INVALID_SOCKET )
2051                 continue;
2052             if ( (rand() % n) == 0 )
2053             {
2054                 pnode->PushMessage("block", *pblock);
2055                 if ( n++ > limit )
2056                     break;
2057             }
2058         }
2059     }
2060     //fprintf(stderr,"finished broadcast new block t.%u\n",(uint32_t)time(NULL));
2061 }
2062
2063 static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
2064 #else
2065 static bool ProcessBlockFound(CBlock* pblock)
2066 #endif // ENABLE_WALLET
2067 {
2068     int32_t height = chainActive.LastTip()->GetHeight()+1;
2069     LogPrintf("%s\n", pblock->ToString());
2070     LogPrintf("generated %s height.%d\n", FormatMoney(pblock->vtx[0].vout[0].nValue), height);
2071
2072     // Found a solution
2073     {
2074         if (pblock->hashPrevBlock != chainActive.LastTip()->GetBlockHash())
2075         {
2076             uint256 hash; int32_t i;
2077             hash = pblock->hashPrevBlock;
2078             for (i=31; i>=0; i--)
2079                 fprintf(stderr,"%02x",((uint8_t *)&hash)[i]);
2080             fprintf(stderr," <- prev (stale)\n");
2081             hash = chainActive.LastTip()->GetBlockHash();
2082             for (i=31; i>=0; i--)
2083                 fprintf(stderr,"%02x",((uint8_t *)&hash)[i]);
2084             fprintf(stderr," <- chainTip (stale)\n");
2085             
2086             return error("VerusMiner: generated block is stale");
2087         }
2088     }
2089     
2090 #ifdef ENABLE_WALLET
2091     // Remove key from key pool
2092     if ( IS_KOMODO_NOTARY == 0 )
2093     {
2094         if (GetArg("-mineraddress", "").empty()) {
2095             // Remove key from key pool
2096             reservekey.KeepKey();
2097         }
2098     }
2099     // Track how many getdata requests this block gets
2100     //if ( 0 )
2101     {
2102         //fprintf(stderr,"lock cs_wallet\n");
2103         LOCK(wallet.cs_wallet);
2104         wallet.mapRequestCount[pblock->GetHash()] = 0;
2105     }
2106 #endif
2107     //fprintf(stderr,"process new block\n");
2108
2109     // Process this block (almost) the same as if we had received it from another node
2110     CValidationState state;
2111     if (!ProcessNewBlock(1, chainActive.LastTip()->GetHeight()+1, state, Params(), NULL, pblock, true, NULL))
2112         return error("VerusMiner: ProcessNewBlock, block not accepted");
2113     
2114     TrackMinedBlock(pblock->GetHash());
2115     komodo_broadcast(pblock,16);
2116     return true;
2117 }
2118
2119 int32_t komodo_baseid(char *origbase);
2120 int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t *blocktimes,int32_t *nonzpkeysp,int32_t height);
2121 arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc);
2122 int32_t FOUND_BLOCK,KOMODO_MAYBEMINED;
2123 extern int32_t KOMODO_LASTMINED,KOMODO_INSYNC;
2124 int32_t roundrobin_delay;
2125 arith_uint256 HASHTarget,HASHTarget_POW;
2126 int32_t komodo_longestchain();
2127
2128 // wait for peers to connect
2129 void waitForPeers(const CChainParams &chainparams)
2130 {
2131     if (chainparams.MiningRequiresPeers())
2132     {
2133         bool fvNodesEmpty;
2134         {
2135             boost::this_thread::interruption_point();
2136             LOCK(cs_vNodes);
2137             fvNodesEmpty = vNodes.empty();
2138         }
2139         int longestchain = komodo_longestchain();
2140         int lastlongest = 0;
2141         if (fvNodesEmpty || IsNotInSync() || (longestchain != 0 && longestchain > chainActive.LastTip()->GetHeight()))
2142         {
2143             int loops = 0, blockDiff = 0, newDiff = 0;
2144             
2145             do {
2146                 if (fvNodesEmpty)
2147                 {
2148                     MilliSleep(1000 + rand() % 4000);
2149                     boost::this_thread::interruption_point();
2150                     LOCK(cs_vNodes);
2151                     fvNodesEmpty = vNodes.empty();
2152                     loops = 0;
2153                     blockDiff = 0;
2154                     lastlongest = 0;
2155                 }
2156                 else if ((newDiff = IsNotInSync()) > 0)
2157                 {
2158                     if (blockDiff != newDiff)
2159                     {
2160                         blockDiff = newDiff;
2161                     }
2162                     else
2163                     {
2164                         if (++loops <= 5)
2165                         {
2166                             MilliSleep(1000);
2167                         }
2168                         else break;
2169                     }
2170                     lastlongest = 0;
2171                 }
2172                 else if (!fvNodesEmpty && !IsNotInSync() && longestchain > chainActive.LastTip()->GetHeight())
2173                 {
2174                     // the only thing may be that we are seeing a long chain that we'll never get
2175                     // don't wait forever
2176                     if (lastlongest == 0)
2177                     {
2178                         MilliSleep(3000);
2179                         lastlongest = longestchain;
2180                     }
2181                 }
2182             } while (fvNodesEmpty || IsNotInSync());
2183             MilliSleep(100 + rand() % 400);
2184         }
2185     }
2186 }
2187
2188 #ifdef ENABLE_WALLET
2189 CBlockIndex *get_chainactive(int32_t height)
2190 {
2191     if ( chainActive.LastTip() != 0 )
2192     {
2193         if ( height <= chainActive.LastTip()->GetHeight() )
2194         {
2195             LOCK(cs_main);
2196             return(chainActive[height]);
2197         }
2198         // else fprintf(stderr,"get_chainactive height %d > active.%d\n",height,chainActive.Tip()->GetHeight());
2199     }
2200     //fprintf(stderr,"get_chainactive null chainActive.Tip() height %d\n",height);
2201     return(0);
2202 }
2203
2204 /*
2205  * A separate thread to stake, while the miner threads mine.
2206  */
2207 void static VerusStaker(CWallet *pwallet)
2208 {
2209     LogPrintf("Verus staker thread started\n");
2210     RenameThread("verus-staker");
2211
2212     const CChainParams& chainparams = Params();
2213     auto consensusParams = chainparams.GetConsensus();
2214
2215     // Each thread has its own key
2216     CReserveKey reservekey(pwallet);
2217
2218     // Each thread has its own counter
2219     unsigned int nExtraNonce = 0;
2220
2221     uint8_t *script; uint64_t total,checktoshis; int32_t i,j;
2222
2223     while ( (ASSETCHAIN_INIT == 0 || KOMODO_INITDONE == 0) ) //chainActive.Tip()->GetHeight() != 235300 &&
2224     {
2225         sleep(1);
2226         if ( komodo_baseid(ASSETCHAINS_SYMBOL) < 0 )
2227             break;
2228     }
2229
2230     // try a nice clean peer connection to start
2231     CBlockIndex *pindexPrev, *pindexCur;
2232     do {
2233         pindexPrev = chainActive.LastTip();
2234         MilliSleep(5000 + rand() % 5000);
2235         waitForPeers(chainparams);
2236         pindexCur = chainActive.LastTip();
2237     } while (pindexPrev != pindexCur);
2238
2239     try {
2240         static int32_t lastStakingHeight = 0;
2241
2242         while (true)
2243         {
2244             waitForPeers(chainparams);
2245             CBlockIndex* pindexPrev = chainActive.LastTip();
2246
2247             // Create new block
2248             unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
2249
2250             if ( Mining_height != pindexPrev->GetHeight()+1 )
2251             {
2252                 Mining_height = pindexPrev->GetHeight()+1;
2253                 Mining_start = (uint32_t)time(NULL);
2254             }
2255
2256             // Check for stop or if block needs to be rebuilt
2257             boost::this_thread::interruption_point();
2258
2259             // try to stake a block
2260             CBlockTemplate *ptr = NULL;
2261
2262             // get height locally for consistent reporting
2263             int32_t newHeight = Mining_height;
2264
2265             if (newHeight > VERUS_MIN_STAKEAGE)
2266                 ptr = CreateNewBlockWithKey(reservekey, newHeight, 0, true);
2267
2268             // TODO - putting this output here tends to help mitigate announcing a staking height earlier than
2269             // announcing the last block win when we start staking before a block's acceptance has been
2270             // acknowledged by the mining thread - a better solution may be to put the output on the submission
2271             // thread.
2272             if ( ptr == 0 && newHeight != lastStakingHeight )
2273             {
2274                 printf("Staking height %d for %s\n", newHeight, ASSETCHAINS_SYMBOL);
2275             }
2276             lastStakingHeight = newHeight;
2277
2278             if ( ptr == 0 )
2279             {
2280                 // wait to try another staking block until after the tip moves again
2281                 while ( chainActive.LastTip() == pindexPrev )
2282                     MilliSleep(250);
2283                 continue;
2284             }
2285
2286             unique_ptr<CBlockTemplate> pblocktemplate(ptr);
2287             if (!pblocktemplate.get())
2288             {
2289                 if (GetArg("-mineraddress", "").empty()) {
2290                     LogPrintf("Error in %s staker: Keypool ran out, please call keypoolrefill before restarting the mining thread\n",
2291                               ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
2292                 } else {
2293                     // Should never reach here, because -mineraddress validity is checked in init.cpp
2294                     LogPrintf("Error in %s staker: Invalid %s -mineraddress\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO], ASSETCHAINS_SYMBOL);
2295                 }
2296                 return;
2297             }
2298
2299             CBlock *pblock = &pblocktemplate->block;
2300             LogPrintf("Staking with %u transactions in block (%u bytes)\n", pblock->vtx.size(),::GetSerializeSize(*pblock,SER_NETWORK,PROTOCOL_VERSION));
2301             //
2302             // Search
2303             //
2304             int64_t nStart = GetTime();
2305
2306             if (vNodes.empty() && chainparams.MiningRequiresPeers())
2307             {
2308                 if ( Mining_height > ASSETCHAINS_MINHEIGHT )
2309                 {
2310                     fprintf(stderr,"no nodes, attempting reconnect\n");
2311                     continue;
2312                 }
2313             }
2314
2315             if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
2316             {
2317                 fprintf(stderr,"timeout, retrying\n");
2318                 continue;
2319             }
2320
2321             if ( pindexPrev != chainActive.LastTip() )
2322             {
2323                 printf("Block %d added to chain\n", chainActive.LastTip()->GetHeight());
2324                 MilliSleep(250);
2325                 continue;
2326             }
2327
2328             int32_t unlockTime = komodo_block_unlocktime(Mining_height);
2329             int64_t subsidy = (int64_t)(pblock->vtx[0].vout[0].nValue);
2330
2331             uint256 hashTarget = ArithToUint256(arith_uint256().SetCompact(pblock->nBits));
2332
2333             pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams);
2334
2335             UpdateTime(pblock, consensusParams, pindexPrev);
2336
2337             if (ProcessBlockFound(pblock, *pwallet, reservekey))
2338             {
2339                 LogPrintf("Using %s algorithm:\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
2340                 LogPrintf("Staked block found  \n  hash: %s  \ntarget: %s\n", pblock->GetHash().GetHex(), hashTarget.GetHex());
2341                 printf("Found block %d \n", newHeight);
2342                 printf("staking reward %.8f %s!\n", (double)subsidy / (double)COIN, ASSETCHAINS_SYMBOL);
2343                 arith_uint256 post;
2344                 post.SetCompact(pblock->GetVerusPOSTarget());
2345
2346                 CTransaction &sTx = pblock->vtx[pblock->vtx.size()-1];
2347                 printf("POS hash: %s  \ntarget:   %s\n", 
2348                     CTransaction::_GetVerusPOSHash(&(pblock->nNonce), 
2349                                                      sTx.vin[0].prevout.hash, 
2350                                                      sTx.vin[0].prevout.n, 
2351                                                      newHeight, 
2352                                                      chainActive.GetVerusEntropyHash(Mining_height), 
2353                                                      sTx.vout[0].nValue).GetHex().c_str(), 
2354                                                      ArithToUint256(post).GetHex().c_str());
2355                 if (unlockTime > newHeight && subsidy >= ASSETCHAINS_TIMELOCKGTE)
2356                     printf("- timelocked until block %i\n", unlockTime);
2357                 else
2358                     printf("\n");
2359             }
2360             else
2361             {
2362                 LogPrintf("Found block rejected at staking height: %d\n", Mining_height);
2363                 printf("Found block rejected at staking height: %d\n", Mining_height);
2364             }
2365
2366             // Check for stop or if block needs to be rebuilt
2367             boost::this_thread::interruption_point();
2368
2369             sleep(3);
2370
2371             // In regression test mode, stop mining after a block is found.
2372             if (chainparams.MineBlocksOnDemand()) {
2373                 throw boost::thread_interrupted();
2374             }
2375         }
2376     }
2377     catch (const boost::thread_interrupted&)
2378     {
2379         LogPrintf("VerusStaker terminated\n");
2380         throw;
2381     }
2382     catch (const std::runtime_error &e)
2383     {
2384         LogPrintf("VerusStaker runtime error: %s\n", e.what());
2385         return;
2386     }
2387 }
2388
2389 typedef bool (*minefunction)(CBlockHeader &bh, CVerusHashV2bWriter &vhw, uint256 &finalHash, uint256 &target, uint64_t start, uint64_t *count);
2390 bool mine_verus_v2(CBlockHeader &bh, CVerusHashV2bWriter &vhw, uint256 &finalHash, uint256 &target, uint64_t start, uint64_t *count);
2391 bool mine_verus_v2_port(CBlockHeader &bh, CVerusHashV2bWriter &vhw, uint256 &finalHash, uint256 &target, uint64_t start, uint64_t *count);
2392
2393 void static BitcoinMiner_noeq(CWallet *pwallet)
2394 #else
2395 void static BitcoinMiner_noeq()
2396 #endif
2397 {
2398     LogPrintf("%s miner started\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
2399     RenameThread("verushash-miner");
2400
2401 #ifdef ENABLE_WALLET
2402     // Each thread has its own key
2403     CReserveKey reservekey(pwallet);
2404 #endif
2405
2406     miningTimer.clear();
2407
2408     const CChainParams& chainparams = Params();
2409     // Each thread has its own counter
2410     unsigned int nExtraNonce = 0;
2411
2412     uint8_t *script; uint64_t total,checktoshis; int32_t i,j;
2413
2414     while ( (ASSETCHAIN_INIT == 0 || KOMODO_INITDONE == 0) ) //chainActive.Tip()->GetHeight() != 235300 &&
2415     {
2416         sleep(1);
2417         if ( komodo_baseid(ASSETCHAINS_SYMBOL) < 0 )
2418             break;
2419     }
2420
2421     SetThreadPriority(THREAD_PRIORITY_LOWEST);
2422
2423     // try a nice clean peer connection to start
2424     CBlockIndex *pindexPrev, *pindexCur;
2425     do {
2426         pindexPrev = chainActive.LastTip();
2427         MilliSleep(5000 + rand() % 5000);
2428         waitForPeers(chainparams);
2429         pindexCur = chainActive.LastTip();
2430     } while (pindexPrev != pindexCur);
2431
2432     // make sure that we have checked for PBaaS availability
2433     ConnectedChains.CheckVerusPBaaSAvailable();
2434
2435     // this will not stop printing more than once in all cases, but it will allow us to print in all cases
2436     // and print duplicates rarely without having to synchronize
2437     static CBlockIndex *lastChainTipPrinted;
2438     static int32_t lastMiningHeight = 0;
2439
2440     miningTimer.start();
2441
2442     try {
2443         printf("Mining %s with %s\n", ASSETCHAINS_SYMBOL, ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
2444
2445         while (true)
2446         {
2447             miningTimer.stop();
2448             waitForPeers(chainparams);
2449
2450             pindexPrev = chainActive.LastTip();
2451
2452             // prevent forking on startup before the diff algorithm kicks in,
2453             // but only for a startup Verus test chain. PBaaS chains have the difficulty inherited from
2454             // their parent
2455             if (chainparams.MiningRequiresPeers() && ((IsVerusActive() && pindexPrev->GetHeight() < 50) || pindexPrev != chainActive.LastTip()))
2456             {
2457                 do {
2458                     pindexPrev = chainActive.LastTip();
2459                     MilliSleep(2000 + rand() % 2000);
2460                 } while (pindexPrev != chainActive.LastTip());
2461             }
2462
2463             // Create new block
2464             unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
2465             if ( Mining_height != pindexPrev->GetHeight()+1 )
2466             {
2467                 Mining_height = pindexPrev->GetHeight()+1;
2468                 if (lastMiningHeight != Mining_height)
2469                 {
2470                     lastMiningHeight = Mining_height;
2471                     printf("Mining %s at height %d\n", ASSETCHAINS_SYMBOL, Mining_height);
2472                 }
2473                 Mining_start = (uint32_t)time(NULL);
2474             }
2475
2476             miningTimer.start();
2477
2478 #ifdef ENABLE_WALLET
2479             CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, Mining_height, 0);
2480 #else
2481             CBlockTemplate *ptr = CreateNewBlockWithKey();
2482 #endif
2483             if ( ptr == 0 )
2484             {
2485                 static uint32_t counter;
2486                 if ( counter++ % 40 == 0 )
2487                 {
2488                     if (!IsVerusActive() &&
2489                         ConnectedChains.IsVerusPBaaSAvailable() &&
2490                         ConnectedChains.notaryChainHeight < ConnectedChains.ThisChain().startBlock)
2491                     {
2492                         fprintf(stderr,"Waiting for block %d on %s chain to start. Current block is %d\n", ConnectedChains.ThisChain().startBlock,
2493                                                                                                            ConnectedChains.notaryChain.chainDefinition.name.c_str(),
2494                                                                                                            ConnectedChains.notaryChainHeight);
2495                     }
2496                     else
2497                     {
2498                         fprintf(stderr,"Unable to create valid block... will continue to try\n");
2499                     }
2500                 }
2501                 MilliSleep(2000);
2502                 continue;
2503             }
2504
2505             unique_ptr<CBlockTemplate> pblocktemplate(ptr);
2506             if (!pblocktemplate.get())
2507             {
2508                 if (GetArg("-mineraddress", "").empty()) {
2509                     LogPrintf("Error in %s miner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n",
2510                               ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
2511                 } else {
2512                     // Should never reach here, because -mineraddress validity is checked in init.cpp
2513                     LogPrintf("Error in %s miner: Invalid %s -mineraddress\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO], ASSETCHAINS_SYMBOL);
2514                 }
2515                 miningTimer.stop();
2516                 miningTimer.clear();
2517                 return;
2518             }
2519             CBlock *pblock = &pblocktemplate->block;
2520
2521             uint32_t savebits;
2522             bool mergeMining = false;
2523             savebits = pblock->nBits;
2524
2525             uint32_t solutionVersion = CConstVerusSolutionVector::Version(pblock->nSolution);
2526             if (pblock->nVersion != CBlockHeader::VERUS_V2)
2527             {
2528                 // must not be in sync
2529                 printf("Mining on incorrect block version.\n");
2530                 sleep(2);
2531                 continue;
2532             }
2533             bool verusSolutionPBaaS = solutionVersion >= CActivationHeight::ACTIVATE_PBAAS;
2534
2535             // v2 hash writer with adjustments for the current height
2536             CVerusHashV2bWriter ss2 = CVerusHashV2bWriter(SER_GETHASH, PROTOCOL_VERSION, solutionVersion);
2537
2538             if ( ASSETCHAINS_SYMBOL[0] != 0 )
2539             {
2540                 if ( ASSETCHAINS_REWARD[0] == 0 && !ASSETCHAINS_LASTERA )
2541                 {
2542                     if ( pblock->vtx.size() == 1 && pblock->vtx[0].vout.size() == 1 && Mining_height > ASSETCHAINS_MINHEIGHT )
2543                     {
2544                         static uint32_t counter;
2545                         if ( counter++ < 10 )
2546                             fprintf(stderr,"skip generating %s on-demand block, no tx avail\n",ASSETCHAINS_SYMBOL);
2547                         sleep(10);
2548                         continue;
2549                     } else fprintf(stderr,"%s vouts.%d mining.%d vs %d\n",ASSETCHAINS_SYMBOL,(int32_t)pblock->vtx[0].vout.size(),Mining_height,ASSETCHAINS_MINHEIGHT);
2550                 }
2551             }
2552
2553             // set our easiest target, if V3+, no need to rebuild the merkle tree
2554             IncrementExtraNonce(pblock, pindexPrev, nExtraNonce, verusSolutionPBaaS ? false : true, &savebits);
2555
2556             // update PBaaS header
2557             if (verusSolutionPBaaS)
2558             {
2559                 if (!IsVerusActive() && ConnectedChains.IsVerusPBaaSAvailable())
2560                 {
2561
2562                     UniValue params(UniValue::VARR);
2563                     UniValue error(UniValue::VARR);
2564                     params.push_back(EncodeHexBlk(*pblock));
2565                     params.push_back(ASSETCHAINS_SYMBOL);
2566                     params.push_back(ASSETCHAINS_RPCHOST);
2567                     params.push_back(ASSETCHAINS_RPCPORT);
2568                     params.push_back(ASSETCHAINS_RPCCREDENTIALS);
2569                     try
2570                     {
2571                         ConnectedChains.lastSubmissionFailed = false;
2572                         params = RPCCallRoot("addmergedblock", params);
2573                         params = find_value(params, "result");
2574                         error = find_value(params, "error");
2575                     } catch (std::exception e)
2576                     {
2577                         printf("Failed to connect to %s chain\n", ConnectedChains.notaryChain.chainDefinition.name.c_str());
2578                         params = UniValue(e.what());
2579                     }
2580                     if (mergeMining = (params.isNull() && error.isNull()))
2581                     {
2582                         printf("Merge mining %s with %s as the hashing chain\n", ASSETCHAINS_SYMBOL, ConnectedChains.notaryChain.chainDefinition.name.c_str());
2583                         LogPrintf("Merge mining with %s as the hashing chain\n", ConnectedChains.notaryChain.chainDefinition.name.c_str());
2584                     }
2585                 }
2586             }
2587
2588             LogPrintf("Running %s miner with %u transactions in block (%u bytes)\n",ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO],
2589                        pblock->vtx.size(),::GetSerializeSize(*pblock,SER_NETWORK,PROTOCOL_VERSION));
2590             //
2591             // Search
2592             //
2593             int64_t nStart = GetTime();
2594
2595             arith_uint256 hashTarget = arith_uint256().SetCompact(savebits);
2596             uint256 uintTarget = ArithToUint256(hashTarget);
2597             arith_uint256 ourTarget;
2598             ourTarget.SetCompact(pblock->nBits);
2599
2600             Mining_start = 0;
2601
2602             if ( pindexPrev != chainActive.LastTip() )
2603             {
2604                 if (lastChainTipPrinted != chainActive.LastTip())
2605                 {
2606                     lastChainTipPrinted = chainActive.LastTip();
2607                     printf("Block %d added to chain\n", lastChainTipPrinted->GetHeight());
2608                 }
2609                 MilliSleep(100);
2610                 continue;
2611             }
2612
2613             uint64_t count;
2614             uint64_t hashesToGo = 0;
2615             uint64_t totalDone = 0;
2616
2617             int64_t subsidy = (int64_t)(pblock->vtx[0].vout[0].nValue);
2618             count = ((ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] >> 3) + 1) / ASSETCHAINS_HASHESPERROUND[ASSETCHAINS_ALGO];
2619             CVerusHashV2 *vh2 = &ss2.GetState();
2620             u128 *hashKey;
2621             verusclhasher &vclh = vh2->vclh;
2622             minefunction mine_verus;
2623             mine_verus = IsCPUVerusOptimized() ? &mine_verus_v2 : &mine_verus_v2_port;
2624
2625             while (true)
2626             {
2627                 uint256 hashResult = uint256();
2628
2629                 unsigned char *curBuf;
2630
2631                 if (mergeMining)
2632                 {
2633                     // loop for a few minutes before refreshing the block
2634                     while (true)
2635                     {
2636                         uint256 ourMerkle = pblock->hashMerkleRoot;
2637                         if ( pindexPrev != chainActive.LastTip() )
2638                         {
2639                             if (lastChainTipPrinted != chainActive.LastTip())
2640                             {
2641                                 lastChainTipPrinted = chainActive.LastTip();
2642                                 printf("Block %d added to chain\n\n", lastChainTipPrinted->GetHeight());
2643                                 arith_uint256 target;
2644                                 target.SetCompact(lastChainTipPrinted->nBits);
2645                                 if (ourMerkle == lastChainTipPrinted->hashMerkleRoot)
2646                                 {
2647                                     LogPrintf("proof-of-work found  \n  hash: %s  \ntarget: %s\n", lastChainTipPrinted->GetBlockHash().GetHex().c_str(), ArithToUint256(ourTarget).GetHex().c_str());
2648                                     printf("Found block %d \n", lastChainTipPrinted->GetHeight());
2649                                     printf("mining reward %.8f %s!\n", (double)subsidy / (double)COIN, ASSETCHAINS_SYMBOL);
2650                                     printf("  hash: %s\ntarget: %s\n", lastChainTipPrinted->GetBlockHash().GetHex().c_str(), ArithToUint256(ourTarget).GetHex().c_str());
2651                                 }
2652                             }
2653                             break;
2654                         }
2655
2656                         // if PBaaS is no longer available, we can't count on merge mining
2657                         if (!ConnectedChains.IsVerusPBaaSAvailable())
2658                         {
2659                             break;
2660                         }
2661
2662                         if (vNodes.empty() && chainparams.MiningRequiresPeers())
2663                         {
2664                             if ( Mining_height > ASSETCHAINS_MINHEIGHT )
2665                             {
2666                                 fprintf(stderr,"no nodes, attempting reconnect\n");
2667                                 break;
2668                             }
2669                         }
2670
2671                         // update every few minutes, regardless
2672                         int64_t elapsed = GetTime() - nStart;
2673
2674                         if ((mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && elapsed > 60) || elapsed > 60 || ConnectedChains.lastSubmissionFailed)
2675                         {
2676                             break;
2677                         }
2678
2679                         boost::this_thread::interruption_point();
2680                         MilliSleep(500);
2681                     }
2682                     break;
2683                 }
2684                 else
2685                 {
2686                     // check NONCEMASK at a time
2687                     for (uint64_t i = 0; i < count; i++)
2688                     {
2689                         // this is the actual mining loop, which enables us to drop out and queue a header anytime we earn a block that is good enough for a
2690                         // merge mined block, but not our own
2691                         bool blockFound;
2692                         arith_uint256 arithHash;
2693                         totalDone = 0;
2694                         do
2695                         {
2696                             // pickup/remove any new/deleted headers
2697                             if (ConnectedChains.dirty || (pblock->NumPBaaSHeaders() < ConnectedChains.mergeMinedChains.size() + 1))
2698                             {
2699                                 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce, verusSolutionPBaaS ? false : true, &savebits);
2700
2701                                 hashTarget.SetCompact(savebits);
2702                                 uintTarget = ArithToUint256(hashTarget);
2703                             }
2704
2705                             // hashesToGo gets updated with actual number run for metrics
2706                             hashesToGo = ASSETCHAINS_HASHESPERROUND[ASSETCHAINS_ALGO];
2707                             uint64_t start = i * hashesToGo + totalDone;
2708                             hashesToGo -= totalDone;
2709
2710                             if (verusSolutionPBaaS)
2711                             {
2712                                 // mine on canonical header for merge mining
2713                                 CPBaaSPreHeader savedHeader(*pblock);
2714
2715                                 pblock->ClearNonCanonicalData();
2716                                 blockFound = (*mine_verus)(*pblock, ss2, hashResult, uintTarget, start, &hashesToGo);
2717                                 savedHeader.SetBlockData(*pblock);
2718                             }
2719                             else
2720                             {
2721                                 blockFound = (*mine_verus)(*pblock, ss2, hashResult, uintTarget, start, &hashesToGo);
2722                             }
2723
2724                             arithHash = UintToArith256(hashResult);
2725                             totalDone += hashesToGo + 1;
2726                             if (blockFound && IsVerusActive())
2727                             {
2728                                 ConnectedChains.QueueNewBlockHeader(*pblock);
2729                                 if (arithHash > ourTarget)
2730                                 {
2731                                     // all blocks qualified with this hash will be submitted
2732                                     // until we redo the block, we might as well not try again with anything over this hash
2733                                     hashTarget = arithHash;
2734                                     uintTarget = ArithToUint256(hashTarget);
2735                                 }
2736                             }
2737                         } while (blockFound && arithHash > ourTarget);
2738
2739                         if (!blockFound || arithHash > ourTarget)
2740                         {
2741                             // Check for stop or if block needs to be rebuilt
2742                             boost::this_thread::interruption_point();
2743                             if ( pindexPrev != chainActive.LastTip() )
2744                             {
2745                                 if (lastChainTipPrinted != chainActive.LastTip())
2746                                 {
2747                                     lastChainTipPrinted = chainActive.LastTip();
2748                                     printf("Block %d added to chain\n", lastChainTipPrinted->GetHeight());
2749                                 }
2750                                 break;
2751                             }
2752                             else if ((i + 1) < count)
2753                             {
2754                                 // if we'll not drop through, update hashcount
2755                                 {
2756                                     miningTimer += totalDone;
2757                                     totalDone = 0;
2758                                 }
2759                             }
2760                         }
2761                         else
2762                         {
2763                             // Check for stop or if block needs to be rebuilt
2764                             boost::this_thread::interruption_point();
2765
2766                             if (pblock->nSolution.size() != 1344)
2767                             {
2768                                 LogPrintf("ERROR: Block solution is not 1344 bytes as it should be");
2769                                 break;
2770                             }
2771
2772                             SetThreadPriority(THREAD_PRIORITY_NORMAL);
2773
2774                             int32_t unlockTime = komodo_block_unlocktime(Mining_height);
2775
2776 #ifdef VERUSHASHDEBUG
2777                             std::string validateStr = hashResult.GetHex();
2778                             std::string hashStr = pblock->GetHash().GetHex();
2779                             uint256 *bhalf1 = (uint256 *)vh2->CurBuffer();
2780                             uint256 *bhalf2 = bhalf1 + 1;
2781 #else
2782                             std::string hashStr = hashResult.GetHex();
2783 #endif
2784
2785                             LogPrintf("Using %s algorithm:\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
2786                             LogPrintf("proof-of-work found  \n  hash: %s  \ntarget: %s\n", hashStr, ArithToUint256(ourTarget).GetHex());
2787                             printf("Found block %d \n", Mining_height );
2788                             printf("mining reward %.8f %s!\n", (double)subsidy / (double)COIN, ASSETCHAINS_SYMBOL);
2789 #ifdef VERUSHASHDEBUG
2790                             printf("  hash: %s\n   val: %s  \ntarget: %s\n\n", hashStr.c_str(), validateStr.c_str(), ArithToUint256(ourTarget).GetHex().c_str());
2791                             printf("intermediate %lx\n", intermediate);
2792                             printf("Curbuf: %s%s\n", bhalf1->GetHex().c_str(), bhalf2->GetHex().c_str());
2793                             bhalf1 = (uint256 *)verusclhasher_key.get();
2794                             bhalf2 = bhalf1 + ((vh2->vclh.keyMask + 1) >> 5);
2795                             printf("   Key: %s%s\n", bhalf1->GetHex().c_str(), bhalf2->GetHex().c_str());
2796 #else
2797                             printf("  hash: %s\ntarget: %s", hashStr.c_str(), ArithToUint256(ourTarget).GetHex().c_str());
2798 #endif
2799                             if (unlockTime > Mining_height && subsidy >= ASSETCHAINS_TIMELOCKGTE)
2800                                 printf(" - timelocked until block %i\n", unlockTime);
2801                             else
2802                                 printf("\n");
2803 #ifdef ENABLE_WALLET
2804                             ProcessBlockFound(pblock, *pwallet, reservekey);
2805 #else
2806                             ProcessBlockFound(pblock);
2807 #endif
2808                             SetThreadPriority(THREAD_PRIORITY_LOWEST);
2809                             break;
2810                         }
2811                     }
2812
2813                     {
2814                         miningTimer += totalDone;
2815                     }
2816                 }
2817                 
2818
2819                 // Check for stop or if block needs to be rebuilt
2820                 boost::this_thread::interruption_point();
2821
2822                 if (vNodes.empty() && chainparams.MiningRequiresPeers())
2823                 {
2824                     if ( Mining_height > ASSETCHAINS_MINHEIGHT )
2825                     {
2826                         fprintf(stderr,"no nodes, attempting reconnect\n");
2827                         break;
2828                     }
2829                 }
2830
2831                 if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
2832                 {
2833                     fprintf(stderr,"timeout, retrying\n");
2834                     break;
2835                 }
2836
2837                 if ( pindexPrev != chainActive.LastTip() )
2838                 {
2839                     if (lastChainTipPrinted != chainActive.LastTip())
2840                     {
2841                         lastChainTipPrinted = chainActive.LastTip();
2842                         printf("Block %d added to chain\n\n", lastChainTipPrinted->GetHeight());
2843                     }
2844                     break;
2845                 }
2846
2847                 // totalDone now has the number of hashes actually done since starting on one nonce mask worth
2848                 uint64_t hashesPerNonceMask = ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] >> 3;
2849                 if (!(totalDone < hashesPerNonceMask))
2850                 {
2851 #ifdef _WIN32
2852                     printf("%llu mega hashes complete - working\n", (hashesPerNonceMask + 1) / 1048576);
2853 #else
2854                     printf("%lu mega hashes complete - working\n", (hashesPerNonceMask + 1) / 1048576);
2855 #endif
2856                 }
2857                 break;
2858
2859             }
2860         }
2861     }
2862     catch (const boost::thread_interrupted&)
2863     {
2864         miningTimer.stop();
2865         miningTimer.clear();
2866         LogPrintf("%s miner terminated\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
2867         throw;
2868     }
2869     catch (const std::runtime_error &e)
2870     {
2871         miningTimer.stop();
2872         miningTimer.clear();
2873         LogPrintf("%s miner runtime error: %s\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO], e.what());
2874         return;
2875     }
2876     miningTimer.stop();
2877     miningTimer.clear();
2878 }
2879
2880 void static BitcoinMiner(CWallet *pwallet)
2881 {
2882     LogPrintf("KomodoMiner started\n");
2883     SetThreadPriority(THREAD_PRIORITY_LOWEST);
2884     RenameThread("komodo-miner");
2885
2886     const CChainParams& chainparams = Params();
2887
2888 #ifdef ENABLE_WALLET
2889     // Each thread has its own key
2890     CReserveKey reservekey(pwallet);
2891 #endif
2892     
2893     // Each thread has its own counter
2894     unsigned int nExtraNonce = 0;
2895     
2896     unsigned int n = chainparams.GetConsensus().EquihashN();
2897     unsigned int k = chainparams.GetConsensus().EquihashK();
2898     uint8_t *script; uint64_t total,checktoshis; int32_t i,j,gpucount=KOMODO_MAXGPUCOUNT,notaryid = -1;
2899     while ( (ASSETCHAIN_INIT == 0 || KOMODO_INITDONE == 0) )
2900     {
2901         sleep(1);
2902         if ( komodo_baseid(ASSETCHAINS_SYMBOL) < 0 )
2903             break;
2904     }
2905     if ( ASSETCHAINS_SYMBOL[0] == 0 )
2906         komodo_chosennotary(&notaryid,chainActive.LastTip()->GetHeight(),NOTARY_PUBKEY33,(uint32_t)chainActive.LastTip()->GetBlockTime());
2907     if ( notaryid != My_notaryid )
2908         My_notaryid = notaryid;
2909     std::string solver;
2910     //if ( notaryid >= 0 || ASSETCHAINS_SYMBOL[0] != 0 )
2911     solver = "tromp";
2912     //else solver = "default";
2913     assert(solver == "tromp" || solver == "default");
2914     LogPrint("pow", "Using Equihash solver \"%s\" with n = %u, k = %u\n", solver, n, k);
2915     if ( ASSETCHAINS_SYMBOL[0] != 0 )
2916         fprintf(stderr,"notaryid.%d Mining.%s with %s\n",notaryid,ASSETCHAINS_SYMBOL,solver.c_str());
2917     std::mutex m_cs;
2918     bool cancelSolver = false;
2919     boost::signals2::connection c = uiInterface.NotifyBlockTip.connect(
2920                                                                        [&m_cs, &cancelSolver](const uint256& hashNewTip) mutable {
2921                                                                            std::lock_guard<std::mutex> lock{m_cs};
2922                                                                            cancelSolver = true;
2923                                                                        }
2924                                                                        );
2925     miningTimer.start();
2926     
2927     try {
2928         if ( ASSETCHAINS_SYMBOL[0] != 0 )
2929             fprintf(stderr,"try %s Mining with %s\n",ASSETCHAINS_SYMBOL,solver.c_str());
2930         while (true)
2931         {
2932             if (chainparams.MiningRequiresPeers()) //chainActive.LastTip()->GetHeight() != 235300 &&
2933             {
2934                 //if ( ASSETCHAINS_SEED != 0 && chainActive.LastTip()->GetHeight() < 100 )
2935                 //    break;
2936                 // Busy-wait for the network to come online so we don't waste time mining
2937                 // on an obsolete chain. In regtest mode we expect to fly solo.
2938                 miningTimer.stop();
2939                 do {
2940                     bool fvNodesEmpty;
2941                     {
2942                         //LOCK(cs_vNodes);
2943                         fvNodesEmpty = vNodes.empty();
2944                     }
2945                     if (!fvNodesEmpty && !IsInitialBlockDownload(chainparams))
2946                         break;
2947                     MilliSleep(15000);
2948                     //fprintf(stderr,"fvNodesEmpty %d IsInitialBlockDownload(%s) %d\n",(int32_t)fvNodesEmpty,ASSETCHAINS_SYMBOL,(int32_t)IsInitialBlockDownload());
2949                     
2950                 } while (true);
2951                 //fprintf(stderr,"%s Found peers\n",ASSETCHAINS_SYMBOL);
2952                 miningTimer.start();
2953             }
2954             //
2955             // Create new block
2956             //
2957             unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
2958             CBlockIndex* pindexPrev = chainActive.LastTip();
2959             if ( Mining_height != pindexPrev->GetHeight()+1 )
2960             {
2961                 Mining_height = pindexPrev->GetHeight()+1;
2962                 Mining_start = (uint32_t)time(NULL);
2963             }
2964             if ( ASSETCHAINS_SYMBOL[0] != 0 && ASSETCHAINS_STAKED == 0 )
2965             {
2966                 //fprintf(stderr,"%s create new block ht.%d\n",ASSETCHAINS_SYMBOL,Mining_height);
2967                 //sleep(3);
2968             }
2969
2970 #ifdef ENABLE_WALLET
2971             // notaries always default to staking
2972             CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, pindexPrev->GetHeight()+1, gpucount, ASSETCHAINS_STAKED != 0 && GetArg("-genproclimit", 0) == 0);
2973 #else
2974             CBlockTemplate *ptr = CreateNewBlockWithKey();
2975 #endif
2976             if ( ptr == 0 )
2977             {
2978                 static uint32_t counter;
2979                 if ( counter++ < 100 && ASSETCHAINS_STAKED == 0 )
2980                     fprintf(stderr,"created illegal block, retry\n");
2981                 sleep(1);
2982                 continue;
2983             }
2984             //fprintf(stderr,"get template\n");
2985             unique_ptr<CBlockTemplate> pblocktemplate(ptr);
2986             if (!pblocktemplate.get())
2987             {
2988                 if (GetArg("-mineraddress", "").empty()) {
2989                     LogPrintf("Error in KomodoMiner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n");
2990                 } else {
2991                     // Should never reach here, because -mineraddress validity is checked in init.cpp
2992                     LogPrintf("Error in KomodoMiner: Invalid -mineraddress\n");
2993                 }
2994                 return;
2995             }
2996             CBlock *pblock = &pblocktemplate->block;
2997             if ( ASSETCHAINS_SYMBOL[0] != 0 )
2998             {
2999                 if ( ASSETCHAINS_REWARD[0] == 0 && !ASSETCHAINS_LASTERA )
3000                 {
3001                     if ( pblock->vtx.size() == 1 && pblock->vtx[0].vout.size() == 1 && Mining_height > ASSETCHAINS_MINHEIGHT )
3002                     {
3003                         static uint32_t counter;
3004                         if ( counter++ < 10 )
3005                             fprintf(stderr,"skip generating %s on-demand block, no tx avail\n",ASSETCHAINS_SYMBOL);
3006                         sleep(10);
3007                         continue;
3008                     } else fprintf(stderr,"%s vouts.%d mining.%d vs %d\n",ASSETCHAINS_SYMBOL,(int32_t)pblock->vtx[0].vout.size(),Mining_height,ASSETCHAINS_MINHEIGHT);
3009                 }
3010             }
3011             IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
3012             //fprintf(stderr,"Running KomodoMiner.%s with %u transactions in block\n",solver.c_str(),(int32_t)pblock->vtx.size());
3013             LogPrintf("Running KomodoMiner.%s with %u transactions in block (%u bytes)\n",solver.c_str(),pblock->vtx.size(),::GetSerializeSize(*pblock,SER_NETWORK,PROTOCOL_VERSION));
3014             //
3015             // Search
3016             //
3017             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();
3018             pblock->nBits         = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus());
3019             savebits = pblock->nBits;
3020             HASHTarget = arith_uint256().SetCompact(savebits);
3021             roundrobin_delay = ROUNDROBIN_DELAY;
3022             if ( ASSETCHAINS_SYMBOL[0] == 0 && notaryid >= 0 )
3023             {
3024                 j = 65;
3025                 if ( (Mining_height >= 235300 && Mining_height < 236000) || (Mining_height % KOMODO_ELECTION_GAP) > 64 || (Mining_height % KOMODO_ELECTION_GAP) == 0 || Mining_height > 1000000 )
3026                 {
3027                     int32_t dispflag = 0;
3028                     if ( notaryid <= 3 || notaryid == 32 || (notaryid >= 43 && notaryid <= 45) &&notaryid == 51 || notaryid == 52 || notaryid == 56 || notaryid == 57 )
3029                         dispflag = 1;
3030                     komodo_eligiblenotary(pubkeys,mids,blocktimes,&nonzpkeys,pindexPrev->GetHeight());
3031                     if ( nonzpkeys > 0 )
3032                     {
3033                         for (i=0; i<33; i++)
3034                             if( pubkeys[0][i] != 0 )
3035                                 break;
3036                         if ( i == 33 )
3037                             externalflag = 1;
3038                         else externalflag = 0;
3039                         if ( IS_KOMODO_NOTARY != 0 )
3040                         {
3041                             for (i=1; i<66; i++)
3042                                 if ( memcmp(pubkeys[i],pubkeys[0],33) == 0 )
3043                                     break;
3044                             if ( externalflag == 0 && i != 66 && mids[i] >= 0 )
3045                                 printf("VIOLATION at %d, notaryid.%d\n",i,mids[i]);
3046                             for (j=gpucount=0; j<65; j++)
3047                             {
3048                                 if ( dispflag != 0 )
3049                                 {
3050                                     if ( mids[j] >= 0 )
3051                                         fprintf(stderr,"%d ",mids[j]);
3052                                     else fprintf(stderr,"GPU ");
3053                                 }
3054                                 if ( mids[j] == -1 )
3055                                     gpucount++;
3056                             }
3057                             if ( dispflag != 0 )
3058                                 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));
3059                         }
3060                         for (j=0; j<65; j++)
3061                             if ( mids[j] == notaryid )
3062                                 break;
3063                         if ( j == 65 )
3064                             KOMODO_LASTMINED = 0;
3065                     } else fprintf(stderr,"no nonz pubkeys\n");
3066                     if ( (Mining_height >= 235300 && Mining_height < 236000) || (j == 65 && Mining_height > KOMODO_MAYBEMINED+1 && Mining_height > KOMODO_LASTMINED+64) )
3067                     {
3068                         HASHTarget = arith_uint256().SetCompact(KOMODO_MINDIFF_NBITS);
3069                         fprintf(stderr,"I am the chosen one for %s ht.%d\n",ASSETCHAINS_SYMBOL,pindexPrev->GetHeight()+1);
3070                     } //else fprintf(stderr,"duplicate at j.%d\n",j);
3071                 } else Mining_start = 0;
3072             } else Mining_start = 0;
3073             if ( ASSETCHAINS_STAKED != 0 )
3074             {
3075                 int32_t percPoS,z; bool fNegative,fOverflow;
3076                 HASHTarget_POW = komodo_PoWtarget(&percPoS,HASHTarget,Mining_height,ASSETCHAINS_STAKED);
3077                 HASHTarget.SetCompact(KOMODO_MINDIFF_NBITS,&fNegative,&fOverflow);
3078                 if ( ASSETCHAINS_STAKED < 100 )
3079                 {
3080                     for (z=31; z>=0; z--)
3081                         fprintf(stderr,"%02x",((uint8_t *)&HASHTarget_POW)[z]);
3082                     fprintf(stderr," PoW for staked coin PoS %d%% vs target %d%%\n",percPoS,(int32_t)ASSETCHAINS_STAKED);
3083                 }
3084             }
3085             while (true)
3086             {
3087                 if ( KOMODO_INSYNC == 0 )
3088                 {
3089                     fprintf(stderr,"Mining when blockchain might not be in sync longest.%d vs %d\n",KOMODO_LONGESTCHAIN,Mining_height);
3090                     if ( KOMODO_LONGESTCHAIN != 0 && Mining_height >= KOMODO_LONGESTCHAIN )
3091                         KOMODO_INSYNC = 1;
3092                     sleep(3);
3093                 }
3094                 // Hash state
3095                 KOMODO_CHOSEN_ONE = 0;
3096                 
3097                 crypto_generichash_blake2b_state state;
3098                 EhInitialiseState(n, k, state);
3099                 // I = the block header minus nonce and solution.
3100                 CEquihashInput I{*pblock};
3101                 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
3102                 ss << I;
3103                 // H(I||...
3104                 crypto_generichash_blake2b_update(&state, (unsigned char*)&ss[0], ss.size());
3105                 // H(I||V||...
3106                 crypto_generichash_blake2b_state curr_state;
3107                 curr_state = state;
3108                 crypto_generichash_blake2b_update(&curr_state,pblock->nNonce.begin(),pblock->nNonce.size());
3109                 // (x_1, x_2, ...) = A(I, V, n, k)
3110                 LogPrint("pow", "Running Equihash solver \"%s\" with nNonce = %s\n",solver, pblock->nNonce.ToString());
3111                 arith_uint256 hashTarget;
3112                 if ( KOMODO_MININGTHREADS > 0 && ASSETCHAINS_STAKED > 0 && ASSETCHAINS_STAKED < 100 && Mining_height > 10 )
3113                     hashTarget = HASHTarget_POW;
3114                 else hashTarget = HASHTarget;
3115                 std::function<bool(std::vector<unsigned char>)> validBlock =
3116 #ifdef ENABLE_WALLET
3117                 [&pblock, &hashTarget, &pwallet, &reservekey, &m_cs, &cancelSolver, &chainparams]
3118 #else
3119                 [&pblock, &hashTarget, &m_cs, &cancelSolver, &chainparams]
3120 #endif
3121                 (std::vector<unsigned char> soln) {
3122                     int32_t z; arith_uint256 h; CBlock B;
3123                     // Write the solution to the hash and compute the result.
3124                     LogPrint("pow", "- Checking solution against target\n");
3125                     pblock->nSolution = soln;
3126                     solutionTargetChecks.increment();
3127                     B = *pblock;
3128                     h = UintToArith256(B.GetHash());
3129                     /*for (z=31; z>=16; z--)
3130                         fprintf(stderr,"%02x",((uint8_t *)&h)[z]);
3131                     fprintf(stderr," mined ");
3132                     for (z=31; z>=16; z--)
3133                         fprintf(stderr,"%02x",((uint8_t *)&HASHTarget)[z]);
3134                     fprintf(stderr," hashTarget ");
3135                     for (z=31; z>=16; z--)
3136                         fprintf(stderr,"%02x",((uint8_t *)&HASHTarget_POW)[z]);
3137                     fprintf(stderr," POW\n");*/
3138                     if ( h > hashTarget )
3139                     {
3140                         //if ( ASSETCHAINS_STAKED != 0 && KOMODO_MININGTHREADS == 0 )
3141                         //    sleep(1);
3142                         return false;
3143                     }
3144                     if ( IS_KOMODO_NOTARY != 0 && B.nTime > GetAdjustedTime() )
3145                     {
3146                         //fprintf(stderr,"need to wait %d seconds to submit block\n",(int32_t)(B.nTime - GetAdjustedTime()));
3147                         while ( GetAdjustedTime() < B.nTime-2 )
3148                         {
3149                             sleep(1);
3150                             if ( chainActive.LastTip()->GetHeight() >= Mining_height )
3151                             {
3152                                 fprintf(stderr,"new block arrived\n");
3153                                 return(false);
3154                             }
3155                         }
3156                     }
3157                     if ( ASSETCHAINS_STAKED == 0 )
3158                     {
3159                         if ( IS_KOMODO_NOTARY != 0 )
3160                         {
3161                             int32_t r;
3162                             if ( (r= ((Mining_height + NOTARY_PUBKEY33[16]) % 64) / 8) > 0 )
3163                                 MilliSleep((rand() % (r * 1000)) + 1000);
3164                         }
3165                     }
3166                     else
3167                     {
3168                         while ( B.nTime-57 > GetAdjustedTime() )
3169                         {
3170                             sleep(1);
3171                             if ( chainActive.LastTip()->GetHeight() >= Mining_height )
3172                                 return(false);
3173                         }
3174                         uint256 tmp = B.GetHash();
3175                         int32_t z; for (z=31; z>=0; z--)
3176                             fprintf(stderr,"%02x",((uint8_t *)&tmp)[z]);
3177                         fprintf(stderr," mined %s block %d!\n",ASSETCHAINS_SYMBOL,Mining_height);
3178                     }
3179                     CValidationState state;
3180                     if ( !TestBlockValidity(state, Params(), B, chainActive.LastTip(), true, false))
3181                     {
3182                         h = UintToArith256(B.GetHash());
3183                         for (z=31; z>=0; z--)
3184                             fprintf(stderr,"%02x",((uint8_t *)&h)[z]);
3185                         fprintf(stderr," Invalid block mined, try again\n");
3186                         return(false);
3187                     }
3188                     KOMODO_CHOSEN_ONE = 1;
3189                     // Found a solution
3190                     SetThreadPriority(THREAD_PRIORITY_NORMAL);
3191                     LogPrintf("KomodoMiner:\n");
3192                     LogPrintf("proof-of-work found  \n  hash: %s  \ntarget: %s\n", B.GetHash().GetHex(), HASHTarget.GetHex());
3193 #ifdef ENABLE_WALLET
3194                     if (ProcessBlockFound(&B, *pwallet, reservekey)) {
3195 #else
3196                         if (ProcessBlockFound(&B)) {
3197 #endif
3198                             // Ignore chain updates caused by us
3199                             std::lock_guard<std::mutex> lock{m_cs};
3200                             cancelSolver = false;
3201                         }
3202                         KOMODO_CHOSEN_ONE = 0;
3203                         SetThreadPriority(THREAD_PRIORITY_LOWEST);
3204                         // In regression test mode, stop mining after a block is found.
3205                         if (chainparams.MineBlocksOnDemand()) {
3206                             // Increment here because throwing skips the call below
3207                             ehSolverRuns.increment();
3208                             throw boost::thread_interrupted();
3209                         }
3210                         return true;
3211                     };
3212                     std::function<bool(EhSolverCancelCheck)> cancelled = [&m_cs, &cancelSolver](EhSolverCancelCheck pos) {
3213                         std::lock_guard<std::mutex> lock{m_cs};
3214                         return cancelSolver;
3215                     };
3216                     
3217                     // TODO: factor this out into a function with the same API for each solver.
3218                     if (solver == "tromp" ) { //&& notaryid >= 0 ) {
3219                         // Create solver and initialize it.
3220                         equi eq(1);
3221                         eq.setstate(&curr_state);
3222                         
3223                         // Initialization done, start algo driver.
3224                         eq.digit0(0);
3225                         eq.xfull = eq.bfull = eq.hfull = 0;
3226                         eq.showbsizes(0);
3227                         for (u32 r = 1; r < WK; r++) {
3228                             (r&1) ? eq.digitodd(r, 0) : eq.digiteven(r, 0);
3229                             eq.xfull = eq.bfull = eq.hfull = 0;
3230                             eq.showbsizes(r);
3231                         }
3232                         eq.digitK(0);
3233                         ehSolverRuns.increment();
3234                         
3235                         // Convert solution indices to byte array (decompress) and pass it to validBlock method.
3236                         for (size_t s = 0; s < eq.nsols; s++) {
3237                             LogPrint("pow", "Checking solution %d\n", s+1);
3238                             std::vector<eh_index> index_vector(PROOFSIZE);
3239                             for (size_t i = 0; i < PROOFSIZE; i++) {
3240                                 index_vector[i] = eq.sols[s][i];
3241                             }
3242                             std::vector<unsigned char> sol_char = GetMinimalFromIndices(index_vector, DIGITBITS);
3243                             
3244                             if (validBlock(sol_char)) {
3245                                 // If we find a POW solution, do not try other solutions
3246                                 // because they become invalid as we created a new block in blockchain.
3247                                 break;
3248                             }
3249                         }
3250                     } else {
3251                         try {
3252                             // If we find a valid block, we rebuild
3253                             bool found = EhOptimisedSolve(n, k, curr_state, validBlock, cancelled);
3254                             ehSolverRuns.increment();
3255                             if (found) {
3256                                 int32_t i; uint256 hash = pblock->GetHash();
3257                                 for (i=0; i<32; i++)
3258                                     fprintf(stderr,"%02x",((uint8_t *)&hash)[i]);
3259                                 fprintf(stderr," <- %s Block found %d\n",ASSETCHAINS_SYMBOL,Mining_height);
3260                                 FOUND_BLOCK = 1;
3261                                 KOMODO_MAYBEMINED = Mining_height;
3262                                 break;
3263                             }
3264                         } catch (EhSolverCancelledException&) {
3265                             LogPrint("pow", "Equihash solver cancelled\n");
3266                             std::lock_guard<std::mutex> lock{m_cs};
3267                             cancelSolver = false;
3268                         }
3269                     }
3270                     
3271                     // Check for stop or if block needs to be rebuilt
3272                     boost::this_thread::interruption_point();
3273                     // Regtest mode doesn't require peers
3274                     if ( FOUND_BLOCK != 0 )
3275                     {
3276                         FOUND_BLOCK = 0;
3277                         fprintf(stderr,"FOUND_BLOCK!\n");
3278                         //sleep(2000);
3279                     }
3280                     if (vNodes.empty() && chainparams.MiningRequiresPeers())
3281                     {
3282                         if ( ASSETCHAINS_SYMBOL[0] == 0 || Mining_height > ASSETCHAINS_MINHEIGHT )
3283                         {
3284                             fprintf(stderr,"no nodes, break\n");
3285                             break;
3286                         }
3287                     }
3288                     if ((UintToArith256(pblock->nNonce) & 0xffff) == 0xffff)
3289                     {
3290                         //if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 )
3291                         fprintf(stderr,"0xffff, break\n");
3292                         break;
3293                     }
3294                     if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
3295                     {
3296                         if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 )
3297                             fprintf(stderr,"timeout, break\n");
3298                         break;
3299                     }
3300                     if ( pindexPrev != chainActive.LastTip() )
3301                     {
3302                         if ( 0 && ASSETCHAINS_SYMBOL[0] != 0 )
3303                             fprintf(stderr,"Tip advanced, break\n");
3304                         break;
3305                     }
3306                     // Update nNonce and nTime
3307                     pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1);
3308                     pblock->nBits = savebits;
3309                     /*if ( NOTARY_PUBKEY33[0] == 0 )
3310                     {
3311                         int32_t percPoS;
3312                         UpdateTime(pblock, consensusParams, pindexPrev);
3313                         if (consensusParams.fPowAllowMinDifficultyBlocks)
3314                         {
3315                             // Changing pblock->nTime can change work required on testnet:
3316                             HASHTarget.SetCompact(pblock->nBits);
3317                             HASHTarget_POW = komodo_PoWtarget(&percPoS,HASHTarget,Mining_height,ASSETCHAINS_STAKED);
3318                         }
3319                     }*/
3320                 }
3321             }
3322         }
3323         catch (const boost::thread_interrupted&)
3324         {
3325             miningTimer.stop();
3326             c.disconnect();
3327             LogPrintf("KomodoMiner terminated\n");
3328             throw;
3329         }
3330         catch (const std::runtime_error &e)
3331         {
3332             miningTimer.stop();
3333             c.disconnect();
3334             LogPrintf("KomodoMiner runtime error: %s\n", e.what());
3335             return;
3336         }
3337         miningTimer.stop();
3338         c.disconnect();
3339     }
3340
3341 #ifdef ENABLE_WALLET
3342     void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads)
3343 #else
3344     void GenerateBitcoins(bool fGenerate, int nThreads)
3345 #endif
3346     {
3347         static CCriticalSection cs_startmining;
3348
3349         LOCK(cs_startmining);
3350         if (!AreParamsInitialized())
3351         {
3352             return;
3353         }
3354
3355         // if we are supposed to catch stake cheaters, there must be a valid sapling parameter, we need it at
3356         // initialization, and this is the first time we can get it. store the Sapling address here
3357         extern boost::optional<libzcash::SaplingPaymentAddress> cheatCatcher;
3358         extern std::string VERUS_CHEATCATCHER;
3359         libzcash::PaymentAddress addr = DecodePaymentAddress(VERUS_CHEATCATCHER);
3360         if (VERUS_CHEATCATCHER.size() > 0 && IsValidPaymentAddress(addr))
3361         {
3362             try
3363             {
3364                 cheatCatcher = boost::get<libzcash::SaplingPaymentAddress>(addr);
3365             } 
3366             catch (...)
3367             {
3368             }
3369         }
3370
3371         VERUS_MINTBLOCKS = (VERUS_MINTBLOCKS && ASSETCHAINS_LWMAPOS != 0);
3372
3373         if (fGenerate == true || VERUS_MINTBLOCKS)
3374         {
3375             mapArgs["-gen"] = "1";
3376
3377             if (VERUS_CHEATCATCHER.size() > 0)
3378             {
3379                 if (cheatCatcher == boost::none)
3380                 {
3381                     LogPrintf("ERROR: -cheatcatcher parameter is invalid Sapling payment address\n");
3382                     fprintf(stderr, "-cheatcatcher parameter is invalid Sapling payment address\n");
3383                 }
3384                 else
3385                 {
3386                     LogPrintf("StakeGuard searching for double stakes on %s\n", VERUS_CHEATCATCHER.c_str());
3387                     fprintf(stderr, "StakeGuard searching for double stakes on %s\n", VERUS_CHEATCATCHER.c_str());
3388                 }
3389             }
3390         }
3391
3392         static boost::thread_group* minerThreads = NULL;
3393
3394         if (nThreads < 0)
3395             nThreads = GetNumCores();
3396
3397         if (minerThreads != NULL)
3398         {
3399             minerThreads->interrupt_all();
3400             minerThreads->join_all();
3401             delete minerThreads;
3402             minerThreads = NULL;
3403         }
3404
3405         //fprintf(stderr,"nThreads.%d fGenerate.%d\n",(int32_t)nThreads,fGenerate);
3406         if ( nThreads == 0 && ASSETCHAINS_STAKED )
3407             nThreads = 1;
3408
3409         if (!fGenerate)
3410             return;
3411
3412         minerThreads = new boost::thread_group();
3413
3414         // add the PBaaS thread when mining or staking
3415         minerThreads->create_thread(boost::bind(&CConnectedChains::SubmissionThreadStub));
3416
3417 #ifdef ENABLE_WALLET
3418         if (VERUS_MINTBLOCKS && pwallet != NULL)
3419         {
3420             minerThreads->create_thread(boost::bind(&VerusStaker, pwallet));
3421         }
3422 #endif
3423
3424         for (int i = 0; i < nThreads; i++) {
3425
3426 #ifdef ENABLE_WALLET
3427             if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH)
3428                 minerThreads->create_thread(boost::bind(&BitcoinMiner, pwallet));
3429             else
3430                 minerThreads->create_thread(boost::bind(&BitcoinMiner_noeq, pwallet));
3431 #else
3432             if (ASSETCHAINS_ALGO == ASSETCHAINS_EQUIHASH)
3433                 minerThreads->create_thread(&BitcoinMiner);
3434             else
3435                 minerThreads->create_thread(&BitcoinMiner_noeq);
3436 #endif
3437         }
3438     }
3439     
3440 #endif // ENABLE_MINING
This page took 0.233268 seconds and 4 git commands to generate.