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