]> Git Repo - VerusCoin.git/blame - src/miner.cpp
Improve inter-daemon connectivity
[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
bc909a7a 4// file COPYING or https://www.opensource.org/licenses/mit-license.php .
d247a5d1 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"
b2993bc5 34#include "validationinterface.h"
09eb201b 35
df756d24
MT
36#include "zcash/Address.hpp"
37#include "transaction_builder.h"
38
fdda3c50
JG
39#include "sodium.h"
40
ad49c256 41#include <boost/thread.hpp>
a3c26c2e 42#include <boost/tuple/tuple.hpp>
8e8b6d70
JG
43#ifdef ENABLE_MINING
44#include <functional>
45#endif
5a360a5c 46#include <mutex>
ad49c256 47
2299bd95
MT
48#include "pbaas/pbaas.h"
49#include "pbaas/notarization.h"
b7c685b8 50#include "pbaas/identity.h"
e7e14f44 51#include "rpc/pbaasrpc.h"
13ed2980 52#include "transaction_builder.h"
2299bd95 53
09eb201b 54using namespace std;
7b4737c8 55
d247a5d1
JG
56//////////////////////////////////////////////////////////////////////////////
57//
58// BitcoinMiner
59//
60
c6cb21d1
GA
61//
62// Unconfirmed transactions in the memory pool often depend on other
63// transactions in the memory pool. When we select transactions from the
64// pool, we select by highest priority or fee rate, so we might consider
65// transactions that depend on transactions that aren't yet in the block.
66// The COrphan class keeps track of these 'temporary orphans' while
67// CreateBlock is figuring out which transactions to include.
68//
d247a5d1
JG
69class COrphan
70{
71public:
4d707d51 72 const CTransaction* ptx;
d247a5d1 73 set<uint256> setDependsOn;
c6cb21d1 74 CFeeRate feeRate;
02bec4b2 75 double dPriority;
e9e70b95 76
c6cb21d1 77 COrphan(const CTransaction* ptxIn) : ptx(ptxIn), feeRate(0), dPriority(0)
d247a5d1 78 {
d247a5d1 79 }
d247a5d1
JG
80};
81
51ed9ec9
BD
82uint64_t nLastBlockTx = 0;
83uint64_t nLastBlockSize = 0;
d247a5d1 84
c6cb21d1
GA
85// We want to sort transactions by priority and fee rate, so:
86typedef boost::tuple<double, CFeeRate, const CTransaction*> TxPriority;
d247a5d1
JG
87class TxPriorityCompare
88{
89 bool byFee;
e9e70b95 90
d247a5d1
JG
91public:
92 TxPriorityCompare(bool _byFee) : byFee(_byFee) { }
e9e70b95 93
d247a5d1
JG
94 bool operator()(const TxPriority& a, const TxPriority& b)
95 {
96 if (byFee)
97 {
98 if (a.get<1>() == b.get<1>())
99 return a.get<0>() < b.get<0>();
100 return a.get<1>() < b.get<1>();
101 }
102 else
103 {
104 if (a.get<0>() == b.get<0>())
105 return a.get<1>() < b.get<1>();
106 return a.get<0>() < b.get<0>();
107 }
108 }
109};
110
bebe7282 111void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
22c4272b 112{
113 pblock->nTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
5ead4b17
JG
114
115 // Updating time can change work required on testnet:
4c902704 116 if (consensusParams.nPowAllowMinDifficultyBlocksAfterHeight != boost::none) {
5ead4b17 117 pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams);
b86dc980 118 }
22c4272b 119}
120
5416af1d 121#include "komodo_defs.h"
122
69767347 123extern CCriticalSection cs_metrics;
6e78d3df 124extern 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 125extern uint64_t ASSETCHAINS_COMMISSION, ASSETCHAINS_STAKED;
5f63373e 126extern bool VERUS_MINTBLOCKS;
42181656 127extern uint64_t ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS], ASSETCHAINS_TIMELOCKGTE, ASSETCHAINS_NONCEMASK[];
128extern const char *ASSETCHAINS_ALGORITHMS[];
56fe75cb 129extern int32_t VERUS_MIN_STAKEAGE, ASSETCHAINS_EQUIHASH, ASSETCHAINS_VERUSHASH, ASSETCHAINS_LASTERA, ASSETCHAINS_LWMAPOS, ASSETCHAINS_NONCESHIFT[], ASSETCHAINS_HASHESPERROUND[];
130extern uint32_t ASSETCHAINS_ALGO;
7c130297 131extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
b2a98c42
MT
132extern uint160 ASSETCHAINS_CHAINID;
133extern uint160 VERUS_CHAINID;
f2d873d0 134extern std::string VERUS_CHAINNAME;
68b309c0 135extern int32_t PBAAS_STARTBLOCK, PBAAS_ENDBLOCK;
7af5cf39 136extern string PBAAS_HOST, PBAAS_USERPASS, ASSETCHAINS_RPCHOST, ASSETCHAINS_RPCCREDENTIALS;;
f8f61a6d 137extern int32_t PBAAS_PORT;
7af5cf39 138extern uint16_t ASSETCHAINS_RPCPORT;
d9f176ac 139extern std::string NOTARY_PUBKEY,ASSETCHAINS_OVERRIDE_PUBKEY;
292809f7 140void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len);
d9f176ac 141
94a465a6 142extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33];
31609f35 143uint32_t Mining_start, Mining_height;
28a62b60 144int32_t My_notaryid = -1;
8683bd8d 145int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp);
b4810651 146int32_t komodo_pax_opreturn(int32_t height,uint8_t *opret,int32_t maxsize);
d63fdb34 147int32_t komodo_baseid(char *origbase);
3bc88f14 148int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t nTime,int32_t dispflag);
29bd53a1 149int64_t komodo_block_unlocktime(uint32_t nHeight);
18443f69 150uint64_t komodo_commission(const CBlock *block);
d231a6a7 151int32_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);
855714b0 152int32_t verus_staked(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &nBits, arith_uint256 &hashResult, std::vector<unsigned char> &utxosig, CTxDestination &rewardDest);
496f1fd2 153int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33);
7652ed92 154
1685bba0
MT
155void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int &nExtraNonce, bool buildMerkle, uint32_t *pSaveBits)
156{
157 // Update nExtraNonce
158 static uint256 hashPrevBlock;
159 if (hashPrevBlock != pblock->hashPrevBlock)
160 {
161 nExtraNonce = 0;
162 hashPrevBlock = pblock->hashPrevBlock;
163 }
164 ++nExtraNonce;
165
166 if (pSaveBits)
167 {
168 *pSaveBits = pblock->nBits;
169 }
170
171 int32_t nHeight = pindexPrev->GetHeight() + 1;
172
d3dfc922 173 int solutionVersion = CConstVerusSolutionVector::activationHeight.ActiveVersion(nHeight);
174
175 if (solutionVersion >= CConstVerusSolutionVector::activationHeight.ACTIVATE_PBAAS_HEADER)
1685bba0
MT
176 {
177 // coinbase should already be finalized in the new version
178 if (buildMerkle)
179 {
180 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
af521e42 181 pblock->SetPrevMMRRoot(ChainMerkleMountainView(chainActive.GetMMR(), pindexPrev->GetHeight()).GetRoot());
2d88a342 182 BlockMMRange mmRange(pblock->BuildBlockMMRTree());
56fe75cb 183 BlockMMView mmView(mmRange);
184 pblock->SetBlockMMRRoot(mmView.GetRoot());
185 pblock->AddUpdatePBaaSHeader();
1685bba0
MT
186 }
187
188 UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
189
1685bba0
MT
190 // POS blocks have already had their solution space filled, and there is no actual extra nonce, extradata is used
191 // for POS proof, so don't modify it
d3dfc922 192 if (solutionVersion >= CConstVerusSolutionVector::activationHeight.ACTIVATE_PBAAS && !pblock->IsVerusPOSBlock())
1685bba0 193 {
d3dfc922 194 pblock->AddUpdatePBaaSHeader();
195
1685bba0
MT
196 uint8_t dummy;
197 // clear extra data to allow adding more PBaaS headers
198 pblock->SetExtraData(&dummy, 0);
199
200 // combine blocks and set compact difficulty if necessary
201 uint32_t savebits;
202 if ((savebits = ConnectedChains.CombineBlocks(*pblock)) && pSaveBits)
203 {
204 arith_uint256 ours, merged;
205 ours.SetCompact(pblock->nBits);
206 merged.SetCompact(savebits);
207 if (merged > ours)
208 {
209 *pSaveBits = savebits;
210 }
211 }
212
213 // extra nonce is kept in the header, not in the coinbase any longer
214 // this allows instant spend transactions to use coinbase funds for
215 // inputs by ensuring that once final, the coinbase transaction hash
216 // will not continue to change
217 CDataStream s(SER_NETWORK, PROTOCOL_VERSION);
218 s << nExtraNonce;
219 std::vector<unsigned char> vENonce(s.begin(), s.end());
220
221 assert(pblock->ExtraDataLen() >= vENonce.size());
222 pblock->SetExtraData(vENonce.data(), vENonce.size());
223 }
224 }
225 else
226 {
227 // finalize input of coinbase
228 CMutableTransaction txcb(pblock->vtx[0]);
229 txcb.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
230 assert(txcb.vin[0].scriptSig.size() <= 100);
231 pblock->vtx[0] = txcb;
232 if (buildMerkle)
233 {
234 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
235 }
236
237 UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
238 }
239}
240
a4f9bc97 241extern CWallet *pwalletMain;
242
243CPubKey GetSolutionPubKey(const std::vector<std::vector<unsigned char>> &vSolutions, txnouttype txType)
244{
245 CPubKey pk;
246
247 if (txType == TX_PUBKEY)
248 {
249 pk = CPubKey(vSolutions[0]);
250 }
251 else if(txType == TX_PUBKEYHASH)
252 {
253 // we need to have this in our wallet to get the public key
254 LOCK(pwalletMain->cs_wallet);
255 pwalletMain->GetPubKey(CKeyID(uint160(vSolutions[0])), pk);
256 }
257 else if (txType == TX_CRYPTOCONDITION)
258 {
259 if (vSolutions[0].size() == 33)
260 {
261 pk = CPubKey(vSolutions[0]);
262 }
263 else if (vSolutions[0].size() == 34 && vSolutions[0][0] == COptCCParams::ADDRTYPE_PK)
264 {
265 pk = CPubKey(std::vector<unsigned char>(vSolutions[0].begin() + 1, vSolutions[0].end()));
266 }
267 else if (vSolutions[0].size() == 20)
268 {
269 LOCK(pwalletMain->cs_wallet);
270 pwalletMain->GetPubKey(CKeyID(uint160(vSolutions[0])), pk);
271 }
272 else if (vSolutions[0].size() == 21 && vSolutions[0][0] == COptCCParams::ADDRTYPE_ID)
273 {
274 // destination is an identity, see if we can get its first public key
275 std::pair<CIdentityMapKey, CIdentityMapValue> identity;
276
277 if (pwalletMain->GetIdentity(CIdentityID(uint160(std::vector<unsigned char>(vSolutions[0].begin() + 1, vSolutions[0].end()))), identity) &&
278 identity.second.IsValidUnrevoked() &&
279 identity.second.primaryAddresses.size())
280 {
281 CPubKey pkTmp = boost::apply_visitor<GetPubKeyForPubKey>(GetPubKeyForPubKey(), identity.second.primaryAddresses[0]);
282 if (pkTmp.IsValid())
283 {
284 pk = pkTmp;
285 }
286 else
287 {
288 LOCK(pwalletMain->cs_wallet);
289 pwalletMain->GetPubKey(CKeyID(GetDestinationID(identity.second.primaryAddresses[0])), pk);
290 }
291 }
292 }
293 }
294 return pk;
295}
296
297CPubKey GetScriptPublicKey(const CScript &scriptPubKey)
298{
299 txnouttype typeRet;
300 std::vector<std::vector<unsigned char>> vSolutions;
301 if (Solver(scriptPubKey, typeRet, vSolutions))
302 {
303 return GetSolutionPubKey(vSolutions, typeRet);
304 }
305 return CPubKey();
306}
307
c8c684e9 308// call a chain that we consider a notary chain, meaning we call its daemon, not the other way around,
42bbe8d7 309// retrieve new exports that we have not imported, and process them. Also, send any exports that are now
310// provable with the available notarization on the specified chain.
c8c684e9 311void ProcessNewImports(const uint160 &sourceChainID, CPBaaSNotarization &lastConfirmed, CUTXORef &lastConfirmedUTXO, uint32_t nHeight)
a041b57e 312{
2f416b17 313 if (CConstVerusSolutionVector::GetVersionByHeight(nHeight) < CActivationHeight::ACTIVATE_PBAAS ||
314 CConstVerusSolutionVector::activationHeight.IsActivationHeight(CActivationHeight::ACTIVATE_PBAAS, nHeight))
315 {
316 return;
317 }
c8c684e9 318
a041b57e 319 uint32_t consensusBranchId = CurrentEpochBranchId(nHeight, Params().GetConsensus());
320
321 // get any pending imports from the source chain. if the source chain is this chain, we don't need notarization
322 CCurrencyDefinition thisChain = ConnectedChains.ThisChain();
c8c684e9 323 CCurrencyDefinition sourceChain = ConnectedChains.GetCachedCurrency(sourceChainID);
324 if (!sourceChain.IsValid())
325 {
326 printf("Unrecognized source chain %s\n", EncodeDestination(CIdentityID(sourceChainID)).c_str());
327 return;
328 }
329
330 bool isSameChain = thisChain.GetID() == sourceChainID;
331
332 CChainNotarizationData cnd;
333 if (!GetNotarizationData(sourceChainID, cnd))
334 {
335 printf("Cannot get notarization data for currency %s\n", sourceChain.name.c_str());
336 return;
337 }
338
339 lastConfirmedUTXO = cnd.vtx[cnd.lastConfirmed].first;
340 lastConfirmed = cnd.vtx[cnd.lastConfirmed].second;
a041b57e 341
342 CTransaction lastImportTx;
343
344 // we need to find the last unspent import transaction
345 std::vector<CAddressUnspentDbEntry> unspentOutputs;
346
347 bool found = false;
c8c684e9 348 CAddressUnspentDbEntry foundEntry;
349 CCrossChainImport lastCCI;
350 std::vector<std::pair<std::pair<CInputDescriptor, CPartialTransactionProof>, std::vector<CReserveTransfer>>> exports;
a041b57e 351
a041b57e 352 {
c8c684e9 353 LOCK(cs_main);
354
355 if (!isSameChain &&
356 GetAddressUnspent(CKeyID(CCrossChainRPCData::GetConditionID(sourceChainID, CCrossChainImport::CurrencySystemImportKey())), CScript::P2IDX, unspentOutputs))
a041b57e 357 {
c8c684e9 358 // if one spends the prior one, get the one that is not spent
359 for (auto &txidx : unspentOutputs)
360 {
361 COptCCParams p;
362 if (txidx.second.script.IsPayToCryptoCondition(p) &&
363 p.IsValid() &&
364 p.evalCode == EVAL_CROSSCHAIN_IMPORT &&
365 p.vData.size() &&
366 (lastCCI = CCrossChainImport(p.vData[0])).IsValid())
367 {
368 found = true;
369 foundEntry = txidx;
370 break;
371 }
372 }
373
374 if (found &&
375 pwalletMain &&
376 lastCCI.sourceSystemHeight < lastConfirmed.notarizationHeight)
a041b57e 377 {
c8c684e9 378 UniValue params(UniValue::VARR);
379
380 params.push_back(EncodeDestination(CIdentityID(sourceChainID)));
381 params.push_back((int64_t)lastCCI.sourceSystemHeight);
382 params.push_back((int64_t)lastConfirmed.notarizationHeight);
383
384 UniValue result = NullUniValue;
385 try
386 {
387 if (sourceChainID == thisChain.GetID())
388 {
389 UniValue getexports(const UniValue& params, bool fHelp);
390 result = getexports(params, false);
391 }
392 else
393 {
394 result = find_value(RPCCallRoot("getexports", params), "result");
395 }
396 } catch (exception e)
397 {
398 printf("Could not get latest export from external chain %s\n", uni_get_str(params[0]).c_str());
399 return;
400 }
401
402 // now, we should have a list of exports to import in order
403 if (!result.isArray() || !result.size())
404 {
405 return;
406 }
407 for (int i = 0; i < result.size(); i++)
408 {
409 // create one import at a time
410 uint32_t notarizationHeight = uni_get_int64(find_value(result[i], "height"));
411 uint256 exportTxId = uint256S(uni_get_str(find_value(result[i], "txid")));
412 int32_t exportTxOutNum = uni_get_int(find_value(result[i], "txoutnum"));
413 CPartialTransactionProof txProof = CPartialTransactionProof(find_value(result[i], "partialtransactionproof"));
414 UniValue transferArrUni = find_value(result[i], "transfers");
415 if (!notarizationHeight ||
416 exportTxId.IsNull() ||
417 exportTxOutNum == -1 ||
418 !transferArrUni.isArray())
419 {
420 printf("Invalid export from %s\n", uni_get_str(params[0]).c_str());
421 return;
422 }
423
424 CTransaction exportTx;
425 uint256 blkHash;
426 auto proofRootIt = lastConfirmed.proofRoots.find(sourceChainID);
427 if (!isSameChain &&
428 !(txProof.IsValid() &&
429 exportTxId == txProof.GetPartialTransaction(exportTx) &&
430 proofRootIt != lastConfirmed.proofRoots.end() &&
431 proofRootIt->second.stateRoot == txProof.CheckPartialTransaction(exportTx) &&
432 exportTx.vout.size() > exportTxOutNum))
433 {
434 printf("Invalid export from %s\n", uni_get_str(params[0]).c_str());
435 return;
436 }
437 else if (isSameChain &&
438 !(myGetTransaction(exportTxId, exportTx, blkHash) &&
439 exportTx.vout.size() > exportTxOutNum))
440 {
441 printf("Invalid export msg2 from %s\n", uni_get_str(params[0]).c_str());
442 return;
443 }
444 std::pair<std::pair<CInputDescriptor, CPartialTransactionProof>, std::vector<CReserveTransfer>> oneExport =
445 std::make_pair(std::make_pair(CInputDescriptor(exportTx.vout[exportTxOutNum].scriptPubKey,
446 exportTx.vout[exportTxOutNum].nValue,
447 CTxIn(exportTxId, exportTxOutNum)),
448 txProof),
449 std::vector<CReserveTransfer>());
450 for (int j = 0; j < transferArrUni.size(); j++)
451 {
452 oneExport.second.push_back(CReserveTransfer(transferArrUni));
453 if (!oneExport.second.back().IsValid())
454 {
455 printf("Invalid reserve transfers from export of %s\n", uni_get_str(params[0]).c_str());
456 return;
457 }
458 }
459 }
a041b57e 460 }
c8c684e9 461 std::map<uint160, std::vector<std::pair<int, CTransaction>>> newImports;
462 ConnectedChains.CreateLatestImports(sourceChain, lastConfirmedUTXO, exports, newImports);
463 }
464 else if (isSameChain)
465 {
466 ConnectedChains.ProcessLocalImports();
467 return;
468 }
469 else
470 {
471 printf("Could not get prior import for currency %s\n", sourceChain.name.c_str());
472 return;
a041b57e 473 }
474 }
c8c684e9 475}
a041b57e 476
c8c684e9 477bool CheckNotaryConnection(const CRPCChainData &notarySystem)
478{
479 // ensure we have connection parameters, or we fail
480 if (notarySystem.rpcHost == "" || notarySystem.rpcUserPass == "" || !notarySystem.rpcPort)
481 {
482 return false;
483 }
484 return true;
485}
486
487bool CallNotary(const CRPCChainData &notarySystem, std::string command, const UniValue &params, UniValue &result, UniValue &error)
488{
489 // ensure we have connection parameters, or we fail
490 if (!CheckNotaryConnection(notarySystem))
491 {
492 return false;
493 }
494
495 try
496 {
497 UniValue rpcResult = RPCCall(command, params, notarySystem.rpcUserPass, notarySystem.rpcPort, notarySystem.rpcHost);
498 result = find_value(rpcResult, "result");
499 error = find_value(rpcResult, "error");
500 } catch (std::exception e)
a041b57e 501 {
c8c684e9 502 error = strprintf("Failed to connect to %s chain, error: %s\n", notarySystem.chainDefinition.name.c_str(), e.what());
503 }
504 return error.isNull();
505}
506
507// get initial currency state from the notary system specified
508bool GetBlockOneLaunchNotarization(const CRPCChainData &notarySystem, const uint160 &currencyID, CPBaaSNotarization &lastNotarization)
509{
510 UniValue result, error;
a041b57e 511
c8c684e9 512 UniValue params(UniValue::VARR);
513 params.push_back(EncodeDestination(CIdentityID(currencyID)));
514
515 // VRSC and VRSCTEST do not start with a notary chain
516 if (!IsVerusActive())
517 {
518 // we are starting a PBaaS chain. We only assume that our chain definition and the first notary chain, if there is one, are setup
519 // in ConnectedChains. All other currencies and identities necessary to start have not been populated and must be in block 1 by
520 // getting the information from the notary chain.
521 if (CallNotary(notarySystem, "getnotarizationdata", params, result, error))
a041b57e 522 {
c8c684e9 523 UniValue lastConfirmedUni = find_value(result, "lastconfirmed");
524 int lastConfirmed = uni_get_int(lastConfirmedUni);
525 UniValue notarizations = find_value(result, "notarizations");
526 if (!lastConfirmedUni.isNull() &&
527 notarizations.isArray() &&
528 notarizations.size() > lastConfirmed)
529 {
530 CPBaaSNotarization notarization = CPBaaSNotarization(find_value(notarizations[lastConfirmed], "notarization"));
531 if (notarization.IsValid() && notarization.currencyID == currencyID)
532 {
533 lastNotarization = notarization;
534 return true;
535 }
a041b57e 536 }
537 }
c8c684e9 538 return false;
539 }
540 return false;
541}
542
543// This is called with either the initial currency, or the gateway converter currency
544// to setup an import/export thread, transfer the initial issuance of native currency
545// into the converter, and notarize the state of each currency.
546// All outputs to do those things are added to the outputs vector.
547bool AddOneCurrencyImport(CCurrencyDefinition &newCurrency,
548 CPBaaSNotarization &notarization,
549 std::vector<CTxOut> &outputs)
550{
551 uint160 newCurID = newCurrency.GetID();
a041b57e 552
c8c684e9 553 // each currency will get:
554 // * one currency definition output
555 // * notarization of latest currency state
556
557 CCcontract_info CC;
558 CCcontract_info *cp;
559
560 cp = CCinit(&CC, EVAL_CURRENCY_DEFINITION);
561 std::vector<CTxDestination> dests({CPubKey(ParseHex(CC.CChexstr))});
562 outputs.push_back(CTxOut(0, MakeMofNCCScript(CConditionObj<CCurrencyDefinition>(EVAL_CURRENCY_DEFINITION, dests, 1, &newCurrency))));
563
564 // import / export capable currencies include the main currency, fractional currencies on any system,
565 // gateway currencies. and non-token currencies. they also get an import / export thread
566 if (newCurrency.IsFractional() ||
567 !newCurrency.IsToken() ||
568 (newCurrency.IsGateway() && newCurrency.GetID() == newCurrency.gatewayID))
569 {
570 // create the import thread output
571 cp = CCinit(&CC, EVAL_CROSSCHAIN_IMPORT);
572
573 if (newCurrency.proofProtocol == newCurrency.PROOF_CHAINID)
574 {
575 dests = std::vector<CTxDestination>({CIdentityID(newCurID)});
576 }
577 else
578 {
579 dests = std::vector<CTxDestination>({CPubKey(ParseHex(CC.CChexstr))});
580 }
581
582 if (newCurID == ASSETCHAINS_CHAINID ||
583 (newCurrency.IsPBaaSConverter() && newCurrency.systemID == ASSETCHAINS_CHAINID))
a041b57e 584 {
c8c684e9 585 // create an import based on launch conditions that covers all pre-allocations and uses the initial notarization
586 CCrossChainImport cci = CCrossChainImport(newCurrency.launchSystemID,
587 notarization.notarizationHeight,
588 newCurID,
589 CCurrencyValueMap(),
590 CCurrencyValueMap(),
591 0,
592 uint256(),
593 uint256(),
594 0,
595 CCrossChainImport::FLAG_INITIALLAUNCHIMPORT);
596
597 // now add the import itself
598 outputs.push_back(CTxOut(0, MakeMofNCCScript(CConditionObj<CCrossChainImport>(EVAL_CROSSCHAIN_IMPORT, dests, 1, &cci))));
599
c8c684e9 600 // add notarization before other outputs
601 cp = CCinit(&CC, EVAL_EARNEDNOTARIZATION);
602 if (newCurID == ASSETCHAINS_CHAINID &&
603 newCurrency.notarizationProtocol == newCurrency.NOTARIZATION_NOTARY_CHAINID)
604 {
605 dests = std::vector<CTxDestination>({CIdentityID(newCurID)});
606 }
607 else
a041b57e 608 {
c8c684e9 609 dests = std::vector<CTxDestination>({CPubKey(ParseHex(CC.CChexstr))});
610 }
611 outputs.push_back(CTxOut(0, MakeMofNCCScript(CConditionObj<CPBaaSNotarization>(EVAL_EARNEDNOTARIZATION, dests, 1, &notarization))));
612
613 CReserveTransactionDescriptor rtxd;
614 CCoinbaseCurrencyState importState = notarization.currencyState;
615 importState.RevertReservesAndSupply();
616 CCurrencyValueMap importedCurrency;
617 CCurrencyValueMap gatewayDepositsIn;
618 CCurrencyValueMap spentCurrencyOut;
619 CCoinbaseCurrencyState newCurrencyState;
620 if (!rtxd.AddReserveTransferImportOutputs(ConnectedChains.FirstNotaryChain().chainDefinition,
621 ConnectedChains.ThisChain(),
622 newCurrency,
623 importState,
624 std::vector<CReserveTransfer>(),
625 outputs,
626 importedCurrency,
627 gatewayDepositsIn,
628 spentCurrencyOut,
629 &newCurrencyState))
630 {
631 LogPrintf("Invalid starting currency import for %s\n", ConnectedChains.ThisChain().name.c_str());
632 printf("Invalid starting currency import for %s\n", ConnectedChains.ThisChain().name.c_str());
633 return false;
634 }
635 }
636 else
637 {
638 // begin with an empty import for this currency
639 // create an import based on launch conditions that covers all pre-allocations and uses the initial notarization
2f1f5cda 640
641 // if the currency is new and owned by this chain, its registration requires the fee, paid in its launch chain currency
642 // otherwise, it is being imported from another chain and requires an import fee
643 CCurrencyValueMap registrationFees;
644 CAmount registrationAmount = 0;
645 if (newCurrency.systemID == ASSETCHAINS_CHAINID)
646 {
647 if (newCurrency.launchSystemID != ASSETCHAINS_CHAINID)
648 {
649 registrationFees = CCurrencyValueMap(std::vector<uint160>({newCurrency.launchSystemID}),
650 std::vector<int64_t>({ConnectedChains.FirstNotaryChain().chainDefinition.currencyRegistrationFee}));
651 }
652 else
653 {
654 registrationAmount = ConnectedChains.ThisChain().currencyRegistrationFee;
655 }
656 }
657 else
658 {
659 registrationAmount = ConnectedChains.ThisChain().currencyImportFee;
660 }
a420f7d8 661
2f1f5cda 662 // TODO: this should actually import the first notarization
c8c684e9 663 CCrossChainImport cci = CCrossChainImport(ASSETCHAINS_CHAINID,
664 1,
665 newCurID,
666 CCurrencyValueMap());
667 outputs.push_back(CTxOut(0, MakeMofNCCScript(CConditionObj<CCrossChainImport>(EVAL_CROSSCHAIN_IMPORT, dests, 1, &cci))));
2f1f5cda 668
669 // get the source system import as well
670 CCrossChainImport sysCCI;
671 if (newCurrency.systemID != ASSETCHAINS_CHAINID)
672 {
673 sysCCI = cci;
674 sysCCI.importCurrencyID = sysCCI.sourceSystemID;
675 sysCCI.flags |= sysCCI.FLAG_SOURCESYSTEM;
676 outputs.push_back(CTxOut(0, MakeMofNCCScript(CConditionObj<CCrossChainImport>(EVAL_CROSSCHAIN_IMPORT, dests, 1, &sysCCI))));
677 }
678 // add notarization before other outputs
679 cp = CCinit(&CC, EVAL_EARNEDNOTARIZATION);
680 if (newCurID == ASSETCHAINS_CHAINID &&
681 newCurrency.notarizationProtocol == newCurrency.NOTARIZATION_NOTARY_CHAINID)
682 {
683 dests = std::vector<CTxDestination>({CIdentityID(newCurID)});
684 }
685 else
686 {
687 dests = std::vector<CTxDestination>({CPubKey(ParseHex(CC.CChexstr))});
688 }
689 outputs.push_back(CTxOut(0, MakeMofNCCScript(CConditionObj<CPBaaSNotarization>(EVAL_EARNEDNOTARIZATION, dests, 1, &notarization))));
690
691 CReserveTransactionDescriptor rtxd;
692 CCoinbaseCurrencyState importState = notarization.currencyState;
693 importState.RevertReservesAndSupply();
694 CCurrencyValueMap importedCurrency;
695 CCurrencyValueMap gatewayDepositsIn;
696 CCurrencyValueMap spentCurrencyOut;
697 CCoinbaseCurrencyState newCurrencyState;
698 if (!rtxd.AddReserveTransferImportOutputs(ConnectedChains.FirstNotaryChain().chainDefinition,
699 ConnectedChains.ThisChain(),
700 newCurrency,
701 importState,
702 std::vector<CReserveTransfer>(),
703 outputs,
704 importedCurrency,
705 gatewayDepositsIn,
706 spentCurrencyOut,
707 &newCurrencyState))
708 {
709 LogPrintf("Invalid starting currency import for %s\n", ConnectedChains.ThisChain().name.c_str());
710 printf("Invalid starting currency import for %s\n", ConnectedChains.ThisChain().name.c_str());
711 return false;
712 }
c8c684e9 713 }
2f1f5cda 714 // export thread
715 cp = CCinit(&CC, EVAL_CROSSCHAIN_EXPORT);
716 dests = std::vector<CTxDestination>({CPubKey(ParseHex(CC.CChexstr))});
717 CCrossChainExport ccx;
718
719 ccx = CCrossChainExport(ASSETCHAINS_CHAINID, 1, 1, newCurrency.systemID, newCurID, 0, CCurrencyValueMap(), CCurrencyValueMap(), uint256());
720 outputs.push_back(CTxOut(0, MakeMofNCCScript(CConditionObj<CCrossChainExport>(EVAL_CROSSCHAIN_EXPORT, dests, 1, &ccx))));
c8c684e9 721 }
722 else
723 {
724 cp = CCinit(&CC, EVAL_EARNEDNOTARIZATION);
725 if (newCurID == ASSETCHAINS_CHAINID &&
726 newCurrency.notarizationProtocol == newCurrency.NOTARIZATION_NOTARY_CHAINID)
727 {
728 dests = std::vector<CTxDestination>({CIdentityID(newCurID)});
729 }
730 else
731 {
732 dests = std::vector<CTxDestination>({CPubKey(ParseHex(CC.CChexstr))});
733 }
734 // we notarize our notary chain here, not ourselves
735 if (notarization.currencyID == ASSETCHAINS_CHAINID)
736 {
737 if (!notarization.SetMirror())
a041b57e 738 {
c8c684e9 739 LogPrintf("Cannot mirror our notarization from notary chain\n");
740 printf("Cannot mirror our notarization from notary chain\n");
741 return false;
a041b57e 742 }
743 }
c8c684e9 744 outputs.push_back(CTxOut(0, MakeMofNCCScript(CConditionObj<CPBaaSNotarization>(EVAL_EARNEDNOTARIZATION, dests, 1, &notarization))));
745 }
c8c684e9 746 return true;
747}
748
749// create all special PBaaS outputs for block 1
750bool MakeBlockOneCoinbaseOutputs(std::vector<CTxOut> &outputs,
751 CPBaaSNotarization &launchNotarization,
752 const Consensus::Params &consensusParams)
753{
754 CCurrencyDefinition &thisChain = ConnectedChains.ThisChain();
755 uint160 thisChainID = ConnectedChains.ThisChain().GetID();
756 CCoinbaseCurrencyState currencyState;
a041b57e 757
c8c684e9 758 if (!GetBlockOneLaunchNotarization(ConnectedChains.FirstNotaryChain(), thisChainID, launchNotarization))
759 {
760 // cannot make block 1 unless we can get the initial currency state from the first notary system
761 LogPrintf("Cannot find chain on notary system\n");
762 printf("Cannot find chain on notary system\n");
763 return false;
764 }
765
766 // we need to have a launch decision to be able to mine any blocks, prior to launch being clear,
767 // it is not an error. we are just not ready.
768 if (!launchNotarization.IsLaunchCleared())
769 {
770 return false;
771 }
772
2f1f5cda 773 if (!launchNotarization.IsLaunchConfirmed())
c8c684e9 774 {
775 // we must reach minimums in all currencies to launch
776 LogPrintf("This chain did not receive the minimum currency contributions and cannot launch. Pre-launch contributions to this chain can be refunded.\n");
777 printf("This chain did not receive the minimum currency contributions and cannot launch. Pre-launch contributions to this chain can be refunded.\n");
778 return false;
779 }
780
781 // get all currencies/IDs that we will need to retrieve from our notary chain
782 std::set<uint160> blockOneCurrencies = {ASSETCHAINS_CHAINID};
783 std::set<uint160> blockOneIDs;
784 std::set<uint160> convertersToCreate;
785
786 CPBaaSNotarization converterNotarization;
441087ab 787 uint160 converterCurrencyID = thisChain.GatewayConverterID();
c8c684e9 788
789 // if we have a converter currency, ensure that it also meets requirements for currency launch
790 if (!thisChain.gatewayConverterName.empty())
791 {
792 if (!GetBlockOneLaunchNotarization(ConnectedChains.FirstNotaryChain(),
793 converterCurrencyID,
794 converterNotarization))
a041b57e 795 {
c8c684e9 796 LogPrintf("Unable to get gateway converter initial state\n");
797 printf("Unable to get gateway converter initial state\n");
798 return false;
799 }
a041b57e 800
c8c684e9 801 // both currency and primary gateway must have their pre-launch phase complete before we can make a decision
802 // about launching
803 if (!converterNotarization.IsLaunchCleared())
804 {
805 return false;
806 }
a041b57e 807
c8c684e9 808 // we need to have a cleared launch to be able to launch
809 if (!converterNotarization.IsLaunchConfirmed())
810 {
811 LogPrintf("Primary currency met requirements for launch, but gateway currency converter did not\n");
812 printf("Primary currency met requirements for launch, but gateway currency converter did not\n");
813 return false;
814 }
a041b57e 815
c8c684e9 816 convertersToCreate.insert(converterCurrencyID);
817 blockOneCurrencies.insert(converterCurrencyID);
818 }
a041b57e 819
2f1f5cda 820 // Now, add block 1 imports, which provide a foundation of all IDs and currencies needed to launch the
c8c684e9 821 // new system, including ID and currency outputs for notary chain, all currencies we accept for pre-conversion,
822 // native currency of system launching the chain.
c8c684e9 823 for (auto &oneNotary : ConnectedChains.notarySystems)
824 {
825 // first, we need to have the native notary currency itself
826 blockOneCurrencies.insert(oneNotary.first);
827 // the only currencies that need an associated ID are fractional or centralized
828 if (oneNotary.second.notaryChain.chainDefinition.IsFractional() ||
829 oneNotary.second.notaryChain.chainDefinition.proofProtocol == oneNotary.second.notaryChain.chainDefinition.PROOF_CHAINID ||
830 oneNotary.second.notaryChain.chainDefinition.notarizationProtocol == oneNotary.second.notaryChain.chainDefinition.NOTARIZATION_NOTARY_CHAINID)
831 {
832 blockOneIDs.insert(oneNotary.first);
833 }
834 }
a041b57e 835
c8c684e9 836 auto &notaryIDs = ConnectedChains.ThisChain().notaries;
837 blockOneIDs.insert(notaryIDs.begin(), notaryIDs.end());
838
839 // now retrieve IDs and currencies
840 std::map<uint160, std::pair<CCurrencyDefinition,CPBaaSNotarization>> currencyImports;
841 std::map<uint160, CIdentity> identityImports;
842 if (!ConnectedChains.GetNotaryCurrencies(ConnectedChains.FirstNotaryChain(), blockOneCurrencies, currencyImports) ||
843 !ConnectedChains.GetNotaryIDs(ConnectedChains.FirstNotaryChain(), blockOneIDs, identityImports))
844 {
845 // we must reach minimums in all currencies to launch
846 LogPrintf("Cannot retrieve identity and currency definitions needed to create block 1\n");
847 printf("Cannot retrieve identity and currency definitions needed to create block 1\n");
848 return false;
849 }
850
c8c684e9 851 // add all imported currency and identity outputs, identity revocaton and recovery IDs must be explicitly imported if needed
852 for (auto &oneIdentity : identityImports)
853 {
854 outputs.push_back(CTxOut(0, oneIdentity.second.IdentityUpdateOutputScript(1)));
855 }
856
857 bool success = true;
858 for (auto &oneCurrency : currencyImports)
859 {
860 success = AddOneCurrencyImport(oneCurrency.second.first, oneCurrency.second.second, outputs);
861 if (!success)
862 {
863 break;
a041b57e 864 }
865 }
c8c684e9 866 return success;
a041b57e 867}
868
855714b0 869CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const std::vector<CTxOut> &minerOutputs, bool isStake)
d247a5d1 870{
41f170fd
MT
871 // instead of one scriptPubKeyIn, we take a vector of them along with relative weight. each is assigned a percentage of the block subsidy and
872 // mining reward based on its weight relative to the total
855714b0 873 if (!(minerOutputs.size() && ConnectedChains.SetLatestMiningOutputs(minerOutputs) || isStake))
06f41160 874 {
a4f9bc97 875 fprintf(stderr,"%s: Must have valid miner outputs, including script with valid PK, PKH, or Verus ID destination.\n", __func__);
88bc6df5 876 return NULL;
06f41160 877 }
878
855714b0 879 CTxDestination firstDestination;
a4f9bc97 880
bb6c3482 881 if (minerOutputs.size())
06f41160 882 {
bb6c3482 883 int64_t shareCheck = 0;
855714b0 884 CTxDestination checkDest;
885 for (auto &output : minerOutputs)
c3250dcd 886 {
855714b0 887 shareCheck += output.nValue;
888 if (shareCheck < 0 ||
889 shareCheck > INT_MAX ||
890 !ExtractDestination(output.scriptPubKey, checkDest) ||
891 (checkDest.which() == COptCCParams::ADDRTYPE_INVALID))
bb6c3482 892 {
893 fprintf(stderr,"Invalid miner outputs share specifications\n");
894 return NULL;
895 }
c3250dcd 896 }
855714b0 897 ExtractDestination(minerOutputs[0].scriptPubKey, firstDestination);
06f41160 898 }
899
855714b0 900 uint32_t blocktime;
2a6a442a 901 //fprintf(stderr,"create new block\n");
df756d24 902 // Create new block
08c58194 903 std::unique_ptr<CBlockTemplate> pblocktemplate(new CBlockTemplate());
d247a5d1 904 if(!pblocktemplate.get())
1b5b89ba 905 {
906 fprintf(stderr,"pblocktemplate.get() failure\n");
d247a5d1 907 return NULL;
1b5b89ba 908 }
d247a5d1 909 CBlock *pblock = &pblocktemplate->block; // pointer for convenience
12217420 910
855714b0 911 pblock->nSolution.resize(Eh200_9.SolutionWidth);
912
12217420 913 pblock->SetVersionByHeight(chainActive.LastTip()->GetHeight() + 1);
914
915 // -regtest only: allow overriding block.nVersion with
dbca89b7 916 // -blockversion=N to test forking scenarios
793a72e3 917 if (chainparams.MineBlocksOnDemand())
dbca89b7 918 pblock->nVersion = GetArg("-blockversion", pblock->nVersion);
e9e70b95 919
41f170fd 920 // Add dummy coinbase tx placeholder as first transaction
4949004d 921 pblock->vtx.push_back(CTransaction());
41f170fd 922
d247a5d1
JG
923 pblocktemplate->vTxFees.push_back(-1); // updated at end
924 pblocktemplate->vTxSigOps.push_back(-1); // updated at end
e9e70b95 925
d247a5d1 926 // Largest block you're willing to create:
ad898b40 927 unsigned int nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE);
855714b0 928
d247a5d1
JG
929 // Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity:
930 nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize));
f711aed7 931
932 unsigned int nMaxIDSize = nBlockMaxSize / 2;
933 unsigned int nCurrentIDSize = 0;
e9e70b95 934
d247a5d1
JG
935 // How much of the block should be dedicated to high-priority transactions,
936 // included regardless of the fees they pay
937 unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", DEFAULT_BLOCK_PRIORITY_SIZE);
938 nBlockPrioritySize = std::min(nBlockMaxSize, nBlockPrioritySize);
e9e70b95 939
d247a5d1
JG
940 // Minimum block size you want to create; block will be filled with free transactions
941 // until there are no more or the block reaches this size:
037b4f14 942 unsigned int nBlockMinSize = GetArg("-blockminsize", DEFAULT_BLOCK_MIN_SIZE);
d247a5d1 943 nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize);
e9e70b95 944
d247a5d1 945 // Collect memory pool transactions into the block
a372168e 946 CAmount nFees = 0;
855714b0 947 CAmount takenFees = 0;
df756d24 948
41f170fd 949 bool isVerusActive = IsVerusActive();
56fe75cb 950 CCurrencyDefinition &thisChain = ConnectedChains.ThisChain();
56fe75cb 951
952 std::vector<CAmount> exchangeRate(thisChain.currencies.size());
41f170fd 953
df756d24
MT
954 // we will attempt to spend any cheats we see
955 CTransaction cheatTx;
956 boost::optional<CTransaction> cheatSpend;
957 uint256 cbHash;
958
562852ab 959 CBlockIndex* pindexPrev = 0;
fdf05416 960 bool loop = true;
961 while (loop)
d247a5d1 962 {
fdf05416 963 loop = false;
964 int nHeight;
df756d24 965 const Consensus::Params &consensusParams = chainparams.GetConsensus();
fdf05416 966 uint32_t consensusBranchId;
fdf05416 967 int64_t nMedianTimePast = 0;
968 uint32_t proposedTime = 0;
a0dd01bc 969
a0dd01bc 970 {
fdf05416 971 while (proposedTime == nMedianTimePast)
a0dd01bc 972 {
fdf05416 973 if (proposedTime)
974 {
975 MilliSleep(20);
976 }
977 LOCK(cs_main);
978 pindexPrev = chainActive.LastTip();
979 nHeight = pindexPrev->GetHeight() + 1;
980 consensusBranchId = CurrentEpochBranchId(nHeight, consensusParams);
fdf05416 981 nMedianTimePast = pindexPrev->GetMedianTimePast();
a0dd01bc 982 proposedTime = GetAdjustedTime();
fdf05416 983
a0dd01bc 984 if (proposedTime == nMedianTimePast)
fdf05416 985 {
986 boost::this_thread::interruption_point();
987 }
a0dd01bc 988 }
989 }
fdf05416 990
a420f7d8 991 CCoinbaseCurrencyState currencyState;
7c70438d 992 CCoinsViewCache view(pcoinsTip);
f9155fec 993 uint32_t expired; uint64_t commission;
6ff77181 994
4fc309f0 995 SaplingMerkleTree sapling_tree;
a420f7d8 996
997 {
998 LOCK2(cs_main, mempool.cs);
999 if (pindexPrev != chainActive.LastTip())
1000 {
1001 // try again
1002 loop = true;
1003 continue;
1004 }
1005 pblock->nTime = GetAdjustedTime();
1006
1007 currencyState = ConnectedChains.GetCurrencyState(nHeight);
1008
1009 if (!(view.GetSaplingAnchorAt(view.GetBestAnchor(SAPLING), sapling_tree)))
1010 {
1011 LogPrintf("%s: failed to get Sapling anchor\n", __func__);
1012 assert(false);
1013 }
1014 }
31a04d28 1015
d247a5d1
JG
1016 // Priority order to process transactions
1017 list<COrphan> vOrphan; // list memory doesn't move
1018 map<uint256, vector<COrphan*> > mapDependers;
1019 bool fPrintPriority = GetBoolArg("-printpriority", false);
e9e70b95 1020
d247a5d1
JG
1021 // This vector will be sorted into a priority queue:
1022 vector<TxPriority> vecPriority;
df756d24
MT
1023 vecPriority.reserve(mempool.mapTx.size() + 1);
1024
df756d24 1025 {
a420f7d8 1026 LOCK(cs_main);
1027
1028 // check if we should add cheat transaction
1029 CBlockIndex *ppast;
1030 CTransaction cb;
1031 int cheatHeight = nHeight - COINBASE_MATURITY < 1 ? 1 : nHeight - COINBASE_MATURITY;
1032 if (defaultSaplingDest &&
1033 chainActive.Height() > 100 &&
1034 (ppast = chainActive[cheatHeight]) &&
1035 ppast->IsVerusPOSBlock() &&
1036 cheatList.IsHeightOrGreaterInList(cheatHeight))
df756d24 1037 {
a420f7d8 1038 // get the block and see if there is a cheat candidate for the stake tx
1039 CBlock b;
1040 if (!(fHavePruned && !(ppast->nStatus & BLOCK_HAVE_DATA) && ppast->nTx > 0) && ReadBlockFromDisk(b, ppast, chainparams.GetConsensus(), 1))
df756d24 1041 {
a420f7d8 1042 CTransaction &stakeTx = b.vtx[b.vtx.size() - 1];
df756d24 1043
a420f7d8 1044 if (cheatList.IsCheatInList(stakeTx, &cheatTx))
73a4cd20 1045 {
a420f7d8 1046 // make and sign the cheat transaction to spend the coinbase to our address
1047 CMutableTransaction mtx = CreateNewContextualCMutableTransaction(consensusParams, nHeight);
df756d24 1048
a420f7d8 1049 uint32_t voutNum;
1050 // get the first vout with value
1051 for (voutNum = 0; voutNum < b.vtx[0].vout.size(); voutNum++)
df756d24 1052 {
a420f7d8 1053 if (b.vtx[0].vout[voutNum].nValue > 0)
1054 break;
df756d24
MT
1055 }
1056
a420f7d8 1057 // send to the same pub key as the destination of this block reward
1058 if (MakeCheatEvidence(mtx, b.vtx[0], voutNum, cheatTx))
df756d24 1059 {
a420f7d8 1060 LOCK(pwalletMain->cs_wallet);
1061 TransactionBuilder tb = TransactionBuilder(consensusParams, nHeight);
1062 cb = b.vtx[0];
1063 cbHash = cb.GetHash();
1064
1065 bool hasInput = false;
1066 for (uint32_t i = 0; i < cb.vout.size(); i++)
1067 {
1068 // add the spends with the cheat
1069 if (cb.vout[i].nValue > 0)
88d014d0 1070 {
a420f7d8 1071 tb.AddTransparentInput(COutPoint(cbHash,i), cb.vout[0].scriptPubKey, cb.vout[0].nValue);
1072 hasInput = true;
88d014d0 1073 }
a420f7d8 1074 }
1075
1076 if (hasInput)
1077 {
1078 // this is a send from a t-address to a sapling address, which we don't have an ovk for.
1079 // Instead, generate a common one from the HD seed. This ensures the data is
1080 // recoverable, at least for us, while keeping it logically separate from the ZIP 32
1081 // Sapling key hierarchy, which the user might not be using.
1082 uint256 ovk;
1083 HDSeed seed;
1084 if (pwalletMain->GetHDSeed(seed)) {
1085 ovk = ovkForShieldingFromTaddr(seed);
1086
1087 // send everything to Sapling address
1088 tb.SendChangeTo(defaultSaplingDest.value(), ovk);
1089
1090 tb.AddOpRet(mtx.vout[mtx.vout.size() - 1].scriptPubKey);
1091
1092 TransactionBuilderResult buildResult(tb.Build());
1093 if (!buildResult.IsError() && buildResult.IsTx())
1094 {
1095 cheatSpend = buildResult.GetTxOrThrow();
1096 }
1097 else
1098 {
1099 LogPrintf("Error building cheat catcher transaction: %s\n", buildResult.GetError().c_str());
1100 }
88d014d0 1101 }
df756d24
MT
1102 }
1103 }
1104 }
1105 }
1106 }
df756d24 1107
a420f7d8 1108 if (cheatSpend)
45bb4681 1109 {
a420f7d8 1110 LOCK(mempool.cs);
1111
1112 cheatTx = cheatSpend.value();
1113 std::list<CTransaction> removed;
1114 mempool.removeConflicts(cheatTx, removed);
1115 printf("Found cheating stake! Adding cheat spend for %.8f at block #%d, coinbase tx\n%s\n",
1116 (double)cb.GetValueOut() / (double)COIN, nHeight, cheatSpend.value().vin[0].prevout.hash.GetHex().c_str());
1117
1118 // add to mem pool and relay
1119 if (myAddtomempool(cheatTx))
1120 {
1121 RelayTransaction(cheatTx);
1122 }
45bb4681 1123 }
271326fa 1124 }
1125
41f170fd
MT
1126 //
1127 // Now start solving the block
1128 //
1129
1130 uint64_t nBlockSize = 1000; // initial size
1131 uint64_t nBlockTx = 1; // number of transactions - always have a coinbase
1132 uint32_t autoTxSize = 0; // extra transaction overhead that we will add while creating the block
1133 int nBlockSigOps = 100;
1134
1135 // VerusPoP staking transaction data
1136 CMutableTransaction txStaked; // if this is a stake operation, the staking transaction that goes at the end
1137 uint32_t nStakeTxSize = 0; // serialized size of the stake transaction
1138
855714b0 1139 // if this is not for mining, first determine if we have a right to make a block
41f170fd
MT
1140 if (isStake)
1141 {
b2a59a12 1142 uint64_t txfees, utxovalue;
1143 uint32_t txtime;
1144 uint256 utxotxid;
1145 int32_t i, siglen, numsigs, utxovout;
1146 std::vector<unsigned char> utxosig;
1147
41f170fd
MT
1148 txStaked = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nHeight);
1149
41f170fd
MT
1150 if (ASSETCHAINS_LWMAPOS != 0)
1151 {
1152 uint32_t nBitsPOS;
1153 arith_uint256 posHash;
1154
855714b0 1155 siglen = verus_staked(pblock, txStaked, nBitsPOS, posHash, utxosig, firstDestination);
41f170fd 1156 blocktime = GetAdjustedTime();
41f170fd 1157 }
41f170fd
MT
1158
1159 if (siglen <= 0)
1160 {
1161 return NULL;
1162 }
1163
1164 pblock->nTime = blocktime;
1165 nStakeTxSize = GetSerializeSize(txStaked, SER_NETWORK, PROTOCOL_VERSION);
1166 nBlockSize += nStakeTxSize;
1167 }
1168
bb6c3482 1169 ConnectedChains.AggregateChainTransfers(firstDestination, nHeight);
1170
41f170fd
MT
1171 // Now the coinbase -
1172 // A PBaaS coinbase must have some additional outputs to enable certain chain state and functions to be properly
1173 // validated. All but currency state and the first chain definition are either optional or not valid on non-fractional reserve PBaaS blockchains
1174 // All of these are instant spend outputs that have no maturity wait time and may be spent in the same block.
1175 //
1176 // 1. (required) currency state - current state of currency supply and optionally reserve, premine, etc. This is primarily a data output to provide
1177 // cross check for coin minting and burning operations, making it efficient to determine up-to-date supply, reserves, and conversions. To provide
1178 // an extra level of supply cross-checking and fast data retrieval, this is part of all PBaaS chains' protocol, not just reserves.
1179 // This output also includes reserve and native amounts for total conversions, less fees, of any conversions between Verus reserve and the
1180 // native currency.
1181 //
1182 // 2. (block 1 required) chain definition - in order to confirm the amount of coins converted and issued within the possible range, before chain start,
1183 // new PBaaS chains have a zero-amount, unspendable chain definition output.
1184 //
1185 // 3. (block 1 optional) initial import utxo - for any chain with conversion or pre-conversion, the first coinbase must include an initial import utxo.
1186 // Pre-conversions are handled on the launch chain before the PBaaS chain starts, so they are an additional output, which begins
1187 // as a fixed amount and is spent with as many outputs as necessary to the recipients of the pre-conversion transactions when those pre-conversions
1188 // are imported. All pre-converted outputs get their source currency from a thread that starts with this output in block 1.
1189 //
1190 // 4. (block 1 optional) initial export utxo - reserve chains, or any chain that will use exports to another chain must have an initial export utxo, any chain
1191 // may have one, but currently, they can only be spent with valid exports, which only occur on reserve chains
1192 //
1193 // 5. (optional) notarization output - in order to ensure that notarization can occur independent of the availability of fungible
1194 // coins on the network, and also that the notarization can provide a spendable finalization output and possible reward
1195 //
1196 // In addition, each PBaaS block can be mined with optional, fee-generating transactions. Inporting transactions from the reserve chain or sending
1197 // exported transactions to the reserve chain are optional fee-generating steps that would be easy to do when running multiple daemons.
1198 // The types of transactions miners/stakers may facilitate or create for fees are as follows:
1199 //
1200 // 1. Earned notarization of Verus chain - spends the notarization instant out. must be present and spend the notarization output if there is a notarization output
1201 //
1202 // 2. Imported transactions from the export thread for this PBaaS chain on the Verus blockchain - imported transactions must spend the import utxo
1203 // thread, represent the export from the alternate chain which spends the export output from the prior import transaction, carry a notary proof, and
1204 // include outputs that map to each of its inputs on the source chain. Outputs can include unconverted reserve outputs only on fractional
1205 // reserve chains, pre-converted outputs for any chain with launch conversion, and post launch outputs to be converted on fractional reserve
1206 // chains. Each are handled in the following way:
1207 // a. Unconverted outputs are left as outputs to the intended destination of Verus reserve token and do not pass through the coinbase
1208 // b. Pre-converted outputs require that the import transaction spend the last pre-conversion output starting at block 1 as the source for
1209 // pre-converted currency.
1210 //
1211 // 3. Zero or more aggregated exports that combine individual cross-chain transactions and reserve transfer outputs for export to the Verus chain.
1212 //
1213 // 4. Conversion distribution transactions for all native and reserve currency conversions, including reserve transfer outputs without conversion as
1214 // a second step for reserve transfers that have conversion included. Any remaining pre-converted reserve must always remain in a change output
1215 // until it is exhausted
88bc6df5 1216 CTxOut premineOut, chainDefinitionOut, importThreadOut, exportThreadOut, currencyStateOut, notarizationOut;
c8c684e9 1217 CMutableTransaction newNotarizationTx;
56fe75cb 1218 int currencyStateOutNum = 0, notarizationOutNum = 0;
41f170fd
MT
1219
1220 // size of conversion tx
0574c740 1221 std::vector<CInputDescriptor> conversionInputs;
41f170fd 1222
4fa3b13d 1223 // if we are a PBaaS chain, first make sure we don't start prematurely, and if
68b309c0 1224 // we should make an earned notarization, make it and set index to non-zero value
41f170fd
MT
1225 int32_t notarizationTxIndex = 0; // index of notarization if it is added
1226 int32_t conversionTxIndex = 0; // index of conversion transaction if it is added
1227
1228 // export transactions can be created here by aggregating all pending transfer requests and either getting 10 or more together, or
1229 // waiting n (10) blocks since the last one. each export must spend the output of the one before it
1230 std::vector<CMutableTransaction> exportTransactions;
1231
1232 // all transaction outputs requesting conversion to another currency (PBaaS fractional reserve only)
1233 // these will be used to calculate conversion price, fees, and generate coinbase conversion output as well as the
1234 // conversion output transaction
1235 std::vector<CTxOut> reserveConversionTo;
1236 std::vector<CTxOut> reserveConversionFrom;
1237
68b309c0 1238 int64_t pbaasTransparentIn = 0;
eb0a6550 1239 int64_t pbaasTransparentOut = 0;
31609f35 1240 //extern int64_t ASSETCHAINS_SUPPLY;
1241 //printf("%lu premine\n", ASSETCHAINS_SUPPLY);
1fa4454d 1242 int64_t blockSubsidy = GetBlockSubsidy(nHeight, consensusParams);
ebee7b5b 1243
56fe75cb 1244 uint160 thisChainID = ConnectedChains.ThisChain().GetID();
41f170fd 1245
8577896f 1246 uint256 mmrRoot;
13ed2980 1247 vector<CInputDescriptor> notarizationInputs;
1fa4454d 1248
41f170fd
MT
1249 // used as scratch for making CCs, should be reinitialized each time
1250 CCcontract_info CC;
1251 CCcontract_info *cp;
c8c684e9 1252 std::vector<CTxDestination> dests;
c3250dcd 1253 CPubKey pkCC;
41f170fd
MT
1254
1255 // Create coinbase tx and set up the null input with height
1256 CMutableTransaction coinbaseTx = CreateNewContextualCMutableTransaction(consensusParams, nHeight);
bb6c3482 1257 coinbaseTx.vin.push_back(CTxIn(uint256(), (uint32_t)-1, CScript() << nHeight << OP_0));
41f170fd 1258
41f170fd
MT
1259 // we will update amounts and fees later, but convert the guarded output now for validity checking and size estimate
1260 if (isStake)
1261 {
1262 // if there is a specific destination, use it
1263 CTransaction stakeTx(txStaked);
1264 CStakeParams p;
1265 if (ValidateStakeTransaction(stakeTx, p, false))
1266 {
56fe75cb 1267 if (p.Version() < p.VERSION_EXTENDED_STAKE && !p.pk.IsValid())
41f170fd
MT
1268 {
1269 LogPrintf("CreateNewBlock: invalid public key\n");
1270 fprintf(stderr,"CreateNewBlock: invalid public key\n");
1271 return NULL;
1272 }
c52bd43c 1273 CTxDestination guardedOutputDest = (p.Version() < p.VERSION_EXTENDED_STAKE) ? p.pk : p.delegate;
56fe75cb 1274 coinbaseTx.vout.push_back(CTxOut(1, CScript()));
c52bd43c 1275 if (!MakeGuardedOutput(1, guardedOutputDest, stakeTx, coinbaseTx.vout.back()))
41f170fd 1276 {
56fe75cb 1277 LogPrintf("CreateNewBlock: failed to make GuardedOutput on staking coinbase\n");
1278 fprintf(stderr,"CreateNewBlock: failed to make GuardedOutput on staking coinbase\n");
1279 return NULL;
41f170fd 1280 }
5d6bdede 1281 COptCCParams optP;
5c7c7edc 1282 if (!coinbaseTx.vout.back().scriptPubKey.IsPayToCryptoCondition(optP) || !optP.IsValid())
5d6bdede 1283 {
c52bd43c 1284 MakeGuardedOutput(1, guardedOutputDest, stakeTx, coinbaseTx.vout.back());
5d6bdede 1285 LogPrintf("%s: created invalid staking coinbase\n", __func__);
1286 fprintf(stderr,"%s: created invalid staking coinbase\n", __func__);
1287 return NULL;
1288 }
41f170fd
MT
1289 }
1290 else
1291 {
1292 LogPrintf("CreateNewBlock: invalid stake transaction\n");
1293 fprintf(stderr,"CreateNewBlock: invalid stake transaction\n");
1294 return NULL;
1295 }
1296 }
56fe75cb 1297 else
1298 {
1299 // default outputs for mining and before stake guard or fee calculation
1300 // store the relative weight in the amount output to convert later to a relative portion
1301 // of the reward + fees
855714b0 1302 coinbaseTx.vout.insert(coinbaseTx.vout.end(), minerOutputs.begin(), minerOutputs.end());
56fe75cb 1303 }
41f170fd 1304
34d1aa13
MT
1305 CAmount totalEmission = blockSubsidy;
1306
c8c684e9 1307 // if we don't have a connected root PBaaS chain, we can't properly check
1308 // and notarize the start block, so we have to pass the notarization and cross chain steps
67dceeec 1309 bool notaryConnected = ConnectedChains.IsNotaryAvailable();
5cd8b21a 1310
c8c684e9 1311 // at block 1 for a PBaaS chain, we validate launch conditions
1312 if (!isVerusActive && nHeight == 1)
1313 {
1314 CPBaaSNotarization launchNotarization;
76f69285 1315 if (!ConnectedChains.readyToStart)
1316 {
1317 return NULL;
1318 }
1319 if (!MakeBlockOneCoinbaseOutputs(coinbaseTx.vout, launchNotarization, Params().GetConsensus()))
4fa3b13d 1320 {
c8c684e9 1321 // can't mine block 1 if we are not connected to a notary
1322 printf("%s: cannot create block one coinbase outputs\n", __func__);
1323 LogPrintf("%s: cannot create block one coinbase outputs\n", __func__);
c8c684e9 1324 return NULL;
989b1de1 1325 }
c8c684e9 1326 currencyState = launchNotarization.currencyState;
1327 }
989b1de1 1328
9abe77b7 1329 // if we are a notary, notarize
1330 if (!VERUS_NOTARYID.IsNull())
1331 {
1332 CValidationState state;
1333 TransactionBuilder notarizationBuilder = TransactionBuilder(consensusParams, nHeight);
1334 bool finalized;
a420f7d8 1335 CTransaction notarizationTx;
9abe77b7 1336 if (CPBaaSNotarization::ConfirmOrRejectNotarizations(pwalletMain, ConnectedChains.FirstNotaryChain(), state, notarizationBuilder, finalized))
1337 {
a420f7d8 1338 LOCK2(cs_main, mempool.cs);
9abe77b7 1339 TransactionBuilderResult buildResult = notarizationBuilder.Build();
a420f7d8 1340 try
1341 {
1342 notarizationTx = buildResult.GetTxOrThrow();
1343 std::list<CTransaction> removed;
1344 LogPrintf("%s: Notarizing cross-chain currency\n", __func__);
9abe77b7 1345
a420f7d8 1346 // add to mem pool and relay
1347 if (myAddtomempool(notarizationTx))
1348 {
1349 RelayTransaction(notarizationTx);
1350 }
1351 }
1352 catch(const std::exception& e)
1353 {
1354 std::cerr << e.what() << '\n';
1355 }
9abe77b7 1356 }
1357 }
1358
c8c684e9 1359 if (notaryConnected)
1360 {
1361 // if we should make an earned notarization, do so
ac07d7a9 1362 if (nHeight != 1 && !(VERUS_NOTARYID.IsNull() && VERUS_DEFAULTID.IsNull() && VERUS_NODEID.IsNull()))
4fa3b13d 1363 {
ac07d7a9 1364 CIdentityID proposer = VERUS_NOTARYID.IsNull() ? (VERUS_DEFAULTID.IsNull() ? VERUS_NODEID : VERUS_DEFAULTID) : VERUS_NOTARYID;
c8c684e9 1365
41f170fd 1366 // if we have access to our notary daemon
56fe75cb 1367 // create a notarization if we would qualify to do so. add it to the mempool and next block
4fa3b13d 1368 ChainMerkleMountainView mmv = chainActive.GetMMV();
8577896f 1369 mmrRoot = mmv.GetRoot();
1fa4454d
MT
1370 int32_t confirmedInput = -1;
1371 CTxDestination confirmedDest;
c8c684e9 1372 CValidationState state;
1373 CPBaaSNotarization earnedNotarization;
1374
1375 if (CPBaaSNotarization::CreateEarnedNotarization(ConnectedChains.FirstNotaryChain(),
1376 DestinationToTransferDestination(proposer),
1377 state,
1378 coinbaseTx.vout,
1379 earnedNotarization))
4fa3b13d 1380 {
833b3007 1381 }
c8c684e9 1382 CPBaaSNotarization lastImportNotarization;
1383 CUTXORef lastImportNotarizationUTXO;
9abe77b7 1384
1385 CPBaaSNotarization::SubmitFinalizedNotarizations(ConnectedChains.FirstNotaryChain(), state);
c8c684e9 1386 ProcessNewImports(ConnectedChains.FirstNotaryChain().chainDefinition.GetID(), lastImportNotarization, lastImportNotarizationUTXO, nHeight);
4fa3b13d 1387 }
2299bd95 1388 }
855714b0 1389
a420f7d8 1390 // done calling out, take locks for the rest
1391 LOCK2(cs_main, mempool.cs);
1392
c8c684e9 1393 totalEmission = GetBlockSubsidy(nHeight, consensusParams);
1394 blockSubsidy = totalEmission;
1395 currencyState.UpdateWithEmission(totalEmission);
1396
1397 // process any imports from the current chain to itself
1398 ConnectedChains.ProcessLocalImports();
855714b0 1399
1400 CFeePool feePool;
c8c684e9 1401 if (!CFeePool::GetCoinbaseFeePool(feePool, nHeight - 1) ||
855714b0 1402 (!feePool.IsValid() && CConstVerusSolutionVector::GetVersionByHeight(nHeight - 1) >= CActivationHeight::ACTIVATE_PBAAS))
1403 {
1404 // we should be able to get a valid currency state, if not, fail
1405 LogPrintf("Failure to get fee pool information for blockchain height #%d\n", nHeight - 1);
1406 printf("Failure to get fee pool information for blockchain height #%d\n", nHeight - 1);
1407 return NULL;
34d1aa13 1408 }
e7e14f44 1409
855714b0 1410 uint32_t solutionVersion = CConstVerusSolutionVector::GetVersionByHeight(nHeight);
1411 if (solutionVersion >= CActivationHeight::ACTIVATE_PBAAS && !feePool.IsValid())
1412 {
1413 // first block with a fee pool, so make it valid and empty
1414 feePool = CFeePool();
1415 }
a041b57e 1416
c8c684e9 1417 // coinbase should have all necessary outputs
41f170fd
MT
1418 uint32_t nCoinbaseSize = GetSerializeSize(coinbaseTx, SER_NETWORK, PROTOCOL_VERSION);
1419 nBlockSize += nCoinbaseSize;
e7c700b5 1420
41f170fd
MT
1421 // now create the priority array, including market order reserve transactions, since they can always execute, leave limits for later
1422 bool haveReserveTransactions = false;
1423 uint32_t reserveExchangeLimitSize = 0;
56fe75cb 1424 std::vector<CReserveTransactionDescriptor> limitOrders;
2299bd95 1425
41f170fd 1426 // now add transactions from the mem pool to the priority heap
e328fa32 1427 for (CTxMemPool::indexed_transaction_set::iterator mi = mempool.mapTx.begin();
4d707d51 1428 mi != mempool.mapTx.end(); ++mi)
d247a5d1 1429 {
e328fa32 1430 const CTransaction& tx = mi->GetTx();
41f170fd 1431 uint256 hash = tx.GetHash();
e9e70b95 1432
a1d3c6fb 1433 int64_t nLockTimeCutoff = (STANDARD_LOCKTIME_VERIFY_FLAGS & LOCKTIME_MEDIAN_TIME_PAST)
e9e70b95 1434 ? nMedianTimePast
1435 : pblock->GetBlockTime();
9c034267 1436
9bb37bf0 1437 if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight, nLockTimeCutoff) || IsExpiredTx(tx, nHeight))
61f8caf2 1438 {
51376f3c 1439 //fprintf(stderr,"coinbase.%d finaltx.%d expired.%d\n",tx.IsCoinBase(),IsFinalTx(tx, nHeight, nLockTimeCutoff),IsExpiredTx(tx, nHeight));
14aa6cc0 1440 continue;
61f8caf2 1441 }
9c034267 1442
161f617d 1443 if ( ASSETCHAINS_SYMBOL[0] == 0 && komodo_validate_interest(tx,nHeight,(uint32_t)pblock->nTime,0) < 0 )
6ff77181 1444 {
64b45b71 1445 //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 1446 continue;
14aa6cc0 1447 }
df756d24 1448
d247a5d1
JG
1449 COrphan* porphan = NULL;
1450 double dPriority = 0;
a372168e 1451 CAmount nTotalIn = 0;
56fe75cb 1452 CCurrencyValueMap totalReserveIn;
d247a5d1 1453 bool fMissingInputs = false;
41f170fd
MT
1454 CReserveTransactionDescriptor rtxd;
1455 bool isReserve = mempool.IsKnownReserveTransaction(hash, rtxd);
e7e14f44 1456
0cb91a8d 1457 if (tx.IsCoinImport())
d247a5d1 1458 {
0cb91a8d
SS
1459 CAmount nValueIn = GetCoinImportValue(tx);
1460 nTotalIn += nValueIn;
1461 dPriority += (double)nValueIn * 1000; // flat multiplier
1462 } else {
41f170fd 1463 // separate limit orders to be added later, we add them at the end, failed fill or kills are normal transactions, consider them reserve txs
15e4d481 1464 if (isReserve && rtxd.IsReserveExchange() && rtxd.IsLimit())
41f170fd
MT
1465 {
1466 // if we might expire, refresh and check again
1467 if (rtxd.IsFillOrKill())
1468 {
1469 rtxd = CReserveTransactionDescriptor(tx, view, nHeight);
1470 mempool.PrioritiseReserveTransaction(rtxd, currencyState);
1471 }
1472
1473 // if is is a failed conversion, drop through
1474 if (!rtxd.IsFillOrKillFail())
1475 {
56fe75cb 1476 limitOrders.push_back(rtxd);
41f170fd 1477 reserveExchangeLimitSize += GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
41f170fd
MT
1478 continue;
1479 }
1480 }
1481 if (isReserve)
1482 {
1483 nTotalIn += rtxd.nativeIn;
56fe75cb 1484 totalReserveIn += rtxd.ReserveInputMap();
f711aed7 1485 if (rtxd.IsIdentity() && CNameReservation(tx).IsValid())
1486 {
1487 nCurrentIDSize += GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
1488 if (nCurrentIDSize > nMaxIDSize)
1489 {
1490 continue;
1491 }
1492 }
41f170fd 1493 }
0cb91a8d 1494 BOOST_FOREACH(const CTxIn& txin, tx.vin)
d247a5d1 1495 {
56fe75cb 1496 CAmount nValueIn = 0;
1497 CCurrencyValueMap reserveValueIn;
41f170fd 1498
0cb91a8d
SS
1499 // Read prev transaction
1500 if (!view.HaveCoins(txin.prevout.hash))
d247a5d1 1501 {
0cb91a8d
SS
1502 // This should never happen; all transactions in the memory
1503 // pool should connect to either transactions in the chain
1504 // or other transactions in the memory pool.
1505 if (!mempool.mapTx.count(txin.prevout.hash))
1506 {
1507 LogPrintf("ERROR: mempool transaction missing input\n");
1508 if (fDebug) assert("mempool transaction missing input" == 0);
1509 fMissingInputs = true;
1510 if (porphan)
1511 vOrphan.pop_back();
1512 break;
1513 }
1514
1515 // Has to wait for dependencies
1516 if (!porphan)
1517 {
1518 // Use list for automatic deletion
1519 vOrphan.push_back(COrphan(&tx));
1520 porphan = &vOrphan.back();
1521 }
1522 mapDependers[txin.prevout.hash].push_back(porphan);
1523 porphan->setDependsOn.insert(txin.prevout.hash);
e7e14f44
MT
1524
1525 const CTransaction &otx = mempool.mapTx.find(txin.prevout.hash)->GetTx();
e7e14f44 1526 // consider reserve outputs and set priority according to their value here as well
56fe75cb 1527 if (isReserve)
e7e14f44 1528 {
56fe75cb 1529 totalReserveIn += otx.vout[txin.prevout.n].ReserveOutValue();
e7e14f44 1530 }
56fe75cb 1531 nTotalIn += otx.vout[txin.prevout.n].nValue;
0cb91a8d 1532 continue;
d247a5d1 1533 }
0cb91a8d
SS
1534 const CCoins* coins = view.AccessCoins(txin.prevout.hash);
1535 assert(coins);
1536
41f170fd 1537 if (isReserve)
e7e14f44 1538 {
56fe75cb 1539 reserveValueIn = coins->vout[txin.prevout.n].ReserveOutValue();
e7e14f44 1540 }
0cb91a8d 1541
41f170fd 1542 nValueIn = coins->vout[txin.prevout.n].nValue;
0cb91a8d
SS
1543 int nConf = nHeight - coins->nHeight;
1544
56fe75cb 1545 dPriority += ((double)((reserveValueIn.valueMap.size() ? currencyState.ReserveToNative(reserveValueIn) : 0) + nValueIn)) * nConf;
71a3314d 1546
71a3314d 1547 if (!isReserve)
1548 {
1549 nTotalIn += nValueIn;
56fe75cb 1550 totalReserveIn += reserveValueIn;
71a3314d 1551 }
d247a5d1 1552 }
9feb4b9e 1553 nTotalIn += tx.GetShieldedValueIn();
d247a5d1 1554 }
0cb91a8d 1555
d247a5d1 1556 if (fMissingInputs) continue;
e9e70b95 1557
d6eb2599 1558 // Priority is sum(valuein * age) / modified_txsize
d247a5d1 1559 unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
4d707d51 1560 dPriority = tx.ComputePriority(dPriority, nTxSize);
e9e70b95 1561
56fe75cb 1562 CAmount nDeltaValueIn = nTotalIn + (totalReserveIn.valueMap.size() ? currencyState.ReserveToNative(totalReserveIn) : 0);
41f170fd
MT
1563 CAmount nFeeValueIn = nDeltaValueIn;
1564 mempool.ApplyDeltas(hash, dPriority, nDeltaValueIn);
e7e14f44 1565
71a3314d 1566 CAmount nativeEquivalentOut = 0;
e7e14f44
MT
1567
1568 // if there is reserve in, or this is a reserveexchange transaction, calculate fee properly
56fe75cb 1569 if (isReserve && rtxd.ReserveOutputMap().valueMap.size())
e7e14f44
MT
1570 {
1571 // if this has reserve currency out, convert it to native currency for fee calculation
56fe75cb 1572 nativeEquivalentOut = currencyState.ReserveToNative(rtxd.ReserveOutputMap());
e7e14f44
MT
1573 }
1574
56fe75cb 1575 CFeeRate feeRate(isReserve ? rtxd.AllFeesAsNative(currencyState) + currencyState.ReserveToNative(rtxd.ReserveConversionFeesMap()) + rtxd.nativeConversionFees :
1576 nFeeValueIn - (tx.GetValueOut() + nativeEquivalentOut), nTxSize);
e7e14f44 1577
d247a5d1
JG
1578 if (porphan)
1579 {
1580 porphan->dPriority = dPriority;
c6cb21d1 1581 porphan->feeRate = feeRate;
d247a5d1
JG
1582 }
1583 else
e328fa32 1584 vecPriority.push_back(TxPriority(dPriority, feeRate, &(mi->GetTx())));
d247a5d1 1585 }
df756d24 1586
41f170fd
MT
1587 //
1588 // NOW -- REALLY START TO FILL THE BLOCK
bb6c3482 1589 //
41f170fd 1590 // estimate number of conversions, staking transaction size, and additional coinbase outputs that will be required
e7c700b5 1591
41f170fd 1592 int32_t maxPreLimitOrderBlockSize = nBlockMaxSize - std::min(nBlockMaxSize >> 2, reserveExchangeLimitSize);
e7e14f44 1593
355ca565 1594 int64_t interest;
d247a5d1 1595 bool fSortedByFee = (nBlockPrioritySize <= 0);
41f170fd 1596
d247a5d1
JG
1597 TxPriorityCompare comparer(fSortedByFee);
1598 std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
41f170fd
MT
1599
1600 std::vector<int> reservePositions;
1601
1602 // now loop and fill the block, leaving space for reserve exchange limit transactions
d247a5d1
JG
1603 while (!vecPriority.empty())
1604 {
1605 // Take highest priority transaction off the priority queue:
1606 double dPriority = vecPriority.front().get<0>();
c6cb21d1 1607 CFeeRate feeRate = vecPriority.front().get<1>();
4d707d51 1608 const CTransaction& tx = *(vecPriority.front().get<2>());
e9e70b95 1609
d247a5d1
JG
1610 std::pop_heap(vecPriority.begin(), vecPriority.end(), comparer);
1611 vecPriority.pop_back();
e9e70b95 1612
d247a5d1
JG
1613 // Size limits
1614 unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
41f170fd 1615 if (nBlockSize + nTxSize >= maxPreLimitOrderBlockSize - autoTxSize) // room for extra autotx
61f8caf2 1616 {
41f170fd 1617 //fprintf(stderr,"nBlockSize %d + %d nTxSize >= %d maxPreLimitOrderBlockSize\n",(int32_t)nBlockSize,(int32_t)nTxSize,(int32_t)maxPreLimitOrderBlockSize);
d247a5d1 1618 continue;
61f8caf2 1619 }
e9e70b95 1620
d247a5d1
JG
1621 // Legacy limits on sigOps:
1622 unsigned int nTxSigOps = GetLegacySigOpCount(tx);
a4a40a38 1623 if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS-1)
61f8caf2 1624 {
51376f3c 1625 //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 1626 continue;
61f8caf2 1627 }
d247a5d1 1628 // Skip free transactions if we're past the minimum block size:
805344dc 1629 const uint256& hash = tx.GetHash();
2a72d459 1630 double dPriorityDelta = 0;
a372168e 1631 CAmount nFeeDelta = 0;
2a72d459 1632 mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta);
13fc83c7 1633 if (fSortedByFee && (dPriorityDelta <= 0) && (nFeeDelta <= 0) && (feeRate < ::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize))
61f8caf2 1634 {
51376f3c 1635 //fprintf(stderr,"fee rate skip\n");
d247a5d1 1636 continue;
61f8caf2 1637 }
41f170fd 1638
2a72d459 1639 // Prioritise by fee once past the priority size or we run out of high-priority
d247a5d1
JG
1640 // transactions:
1641 if (!fSortedByFee &&
1642 ((nBlockSize + nTxSize >= nBlockPrioritySize) || !AllowFree(dPriority)))
1643 {
1644 fSortedByFee = true;
1645 comparer = TxPriorityCompare(fSortedByFee);
1646 std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
1647 }
e9e70b95 1648
d247a5d1 1649 if (!view.HaveInputs(tx))
61f8caf2 1650 {
51376f3c 1651 //fprintf(stderr,"dont have inputs\n");
d247a5d1 1652 continue;
61f8caf2 1653 }
41f170fd
MT
1654 CAmount nTxFees;
1655 CReserveTransactionDescriptor txDesc;
1656 bool isReserve = mempool.IsKnownReserveTransaction(hash, txDesc);
1657
a8419988 1658 nTxFees = view.GetValueIn(chainActive.LastTip()->GetHeight(),&interest,tx,chainActive.LastTip()->nTime) - tx.GetValueOut();
e9e70b95 1659
d247a5d1 1660 nTxSigOps += GetP2SHSigOpCount(tx, view);
a4a40a38 1661 if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS-1)
61f8caf2 1662 {
51376f3c 1663 //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 1664 continue;
61f8caf2 1665 }
41f170fd 1666
68f7d1d7
PT
1667 // Note that flags: we don't want to set mempool/IsStandard()
1668 // policy here, but we still have to ensure that the block we
1669 // create only contains transactions that are valid in new blocks.
d247a5d1 1670 CValidationState state;
6514771a 1671 PrecomputedTransactionData txdata(tx);
b76f691a 1672 if (!ContextualCheckInputs(tx, state, view, nHeight, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId))
61f8caf2 1673 {
51376f3c 1674 //fprintf(stderr,"context failure\n");
d247a5d1 1675 continue;
61f8caf2 1676 }
e7e14f44 1677
8cb98d91 1678 UpdateCoins(tx, view, nHeight);
d247a5d1 1679
41f170fd
MT
1680 if (isReserve)
1681 {
1682 reservePositions.push_back(nBlockTx);
1683 haveReserveTransactions = true;
1684 }
1685
31a04d28
SB
1686 BOOST_FOREACH(const OutputDescription &outDescription, tx.vShieldedOutput) {
1687 sapling_tree.append(outDescription.cm);
1688 }
1689
d247a5d1
JG
1690 // Added
1691 pblock->vtx.push_back(tx);
1692 pblocktemplate->vTxFees.push_back(nTxFees);
1693 pblocktemplate->vTxSigOps.push_back(nTxSigOps);
1694 nBlockSize += nTxSize;
1695 ++nBlockTx;
1696 nBlockSigOps += nTxSigOps;
1697 nFees += nTxFees;
e9e70b95 1698
d247a5d1
JG
1699 if (fPrintPriority)
1700 {
3f0813b3 1701 LogPrintf("priority %.1f fee %s txid %s\n",dPriority, feeRate.ToString(), tx.GetHash().ToString());
d247a5d1 1702 }
e9e70b95 1703
d247a5d1
JG
1704 // Add transactions that depend on this one to the priority queue
1705 if (mapDependers.count(hash))
1706 {
1707 BOOST_FOREACH(COrphan* porphan, mapDependers[hash])
1708 {
1709 if (!porphan->setDependsOn.empty())
1710 {
1711 porphan->setDependsOn.erase(hash);
1712 if (porphan->setDependsOn.empty())
1713 {
c6cb21d1 1714 vecPriority.push_back(TxPriority(porphan->dPriority, porphan->feeRate, porphan->ptx));
d247a5d1
JG
1715 std::push_heap(vecPriority.begin(), vecPriority.end(), comparer);
1716 }
1717 }
1718 }
1719 }
1720 }
135fa24e 1721
05ece4c3 1722 // first calculate and distribute block rewards, including fees in the minerOutputs vector
88bc6df5 1723 CAmount rewardTotalShareAmount = 0;
855714b0 1724 CAmount rewardFees = nFees;
1725 if (feePool.IsValid())
1726 {
1727 // we currently only support the current native currency in the fee pool
1728 feePool.reserveValues.valueMap[thisChainID] += nFees;
1729 rewardFees = feePool.OneFeeShare().reserveValues.valueMap[thisChainID];
1730 feePool.reserveValues.valueMap[thisChainID] -= rewardFees;
1731
1732 cp = CCinit(&CC, EVAL_FEE_POOL);
1733 pkCC = CPubKey(ParseHex(CC.CChexstr));
1734 coinbaseTx.vout.push_back(CTxOut(0,MakeMofNCCScript(CConditionObj<CFeePool>(EVAL_FEE_POOL,{pkCC.GetID()},1,&feePool))));
1735 }
c8c684e9 1736 CAmount rewardTotal = blockSubsidy + rewardFees;
1737
1738
1739
a1a4dc8b 1740
d6f7d693 1741 CAmount rewardLeft = notarizationTxIndex ? rewardTotal - notarizationOut.nValue : rewardTotal;
41f170fd 1742
c8c684e9 1743
1744
1745
56fe75cb 1746 // now that we have the total reward, update the coinbase outputs
1747 if (isStake)
06f41160 1748 {
56fe75cb 1749 coinbaseTx.vout[0].nValue = rewardLeft;
88bc6df5 1750 }
56fe75cb 1751 else
88bc6df5 1752 {
56fe75cb 1753 for (auto &outputShare : minerOutputs)
06f41160 1754 {
855714b0 1755 rewardTotalShareAmount += outputShare.nValue;
88bc6df5 1756 }
41f170fd 1757
56fe75cb 1758 int cbOutIdx;
1759 for (cbOutIdx = 0; cbOutIdx < minerOutputs.size(); cbOutIdx++)
1760 {
855714b0 1761 CAmount amount = (arith_uint256(rewardTotal) * arith_uint256(minerOutputs[cbOutIdx].nValue) / arith_uint256(rewardTotalShareAmount)).GetLow64();
56fe75cb 1762 if (rewardLeft <= amount || (cbOutIdx + 1) == minerOutputs.size())
1763 {
1764 amount = rewardLeft;
1765 }
1766 rewardLeft -= amount;
1767 coinbaseTx.vout[cbOutIdx].nValue = amount;
1768 // the only valid CC output we currently support on coinbases is stake guard, which does not need to be modified for this
1769 }
88bc6df5
MT
1770 }
1771
88bc6df5
MT
1772 nLastBlockTx = nBlockTx;
1773 nLastBlockSize = nBlockSize;
1774
1775 blocktime = std::max(pindexPrev->GetMedianTimePast(), GetAdjustedTime());
1776
1777 pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus());
1778
41f170fd 1779 coinbaseTx.nExpiryHeight = 0;
88bc6df5 1780 coinbaseTx.nLockTime = blocktime;
abb90a89 1781
ebee7b5b 1782 // finalize input of coinbase
41f170fd
MT
1783 coinbaseTx.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(0)) + COINBASE_FLAGS;
1784 assert(coinbaseTx.vin[0].scriptSig.size() <= 100);
ebee7b5b 1785
88bc6df5
MT
1786 // coinbase is done
1787 pblock->vtx[0] = coinbaseTx;
1788 uint256 cbHash = coinbaseTx.GetHash();
ebee7b5b 1789
88bc6df5
MT
1790 // if there is a stake transaction, add it to the very end
1791 if (isStake)
1792 {
1793 UpdateCoins(txStaked, view, nHeight);
1794 pblock->vtx.push_back(txStaked);
1795 pblocktemplate->vTxFees.push_back(0);
1796 int txSigOps = GetLegacySigOpCount(txStaked);
1797 pblocktemplate->vTxSigOps.push_back(txSigOps);
1798 // already added to the block size above
1799 ++nBlockTx;
1800 nBlockSigOps += txSigOps;
1801 }
68b309c0 1802
88bc6df5 1803 extern CWallet *pwalletMain;
8577896f 1804
41f170fd 1805 pblock->vtx[0] = coinbaseTx;
d247a5d1 1806 pblocktemplate->vTxFees[0] = -nFees;
88bc6df5 1807 pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
48d800c2 1808
1fae37f6
MT
1809 // if not Verus stake, setup nonce, otherwise, leave it alone
1810 if (!isStake || ASSETCHAINS_LWMAPOS == 0)
1811 {
eb0a6550 1812 // Randomize nonce
1fae37f6 1813 arith_uint256 nonce = UintToArith256(GetRandHash());
48d800c2 1814
1fae37f6
MT
1815 // Clear the top 16 and bottom 16 or 24 bits (for local use as thread flags and counters)
1816 nonce <<= ASSETCHAINS_NONCESHIFT[ASSETCHAINS_ALGO];
1817 nonce >>= 16;
1818 pblock->nNonce = ArithToUint256(nonce);
1819 }
e9e70b95 1820
d247a5d1
JG
1821 // Fill in header
1822 pblock->hashPrevBlock = pindexPrev->GetBlockHash();
31a04d28 1823 pblock->hashFinalSaplingRoot = sapling_tree.root();
0c8fa56a
MT
1824
1825 // all Verus PoS chains need this data in the block at all times
1826 if ( ASSETCHAINS_LWMAPOS || ASSETCHAINS_SYMBOL[0] == 0 || ASSETCHAINS_STAKED == 0 || KOMODO_MININGTHREADS > 0 )
9a0f2798 1827 {
1828 UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
1fae37f6 1829 pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus());
9a0f2798 1830 }
12217420 1831
4d068367 1832 if ( ASSETCHAINS_SYMBOL[0] == 0 && IS_KOMODO_NOTARY != 0 && My_notaryid >= 0 )
af805d53 1833 {
28a62b60 1834 uint32_t r;
496f1fd2 1835 CMutableTransaction txNotary = CreateNewContextualCMutableTransaction(Params().GetConsensus(), chainActive.Height() + 1);
fa04bcf3 1836 if ( pblock->nTime < pindexPrev->nTime+60 )
1837 pblock->nTime = pindexPrev->nTime + 60;
855714b0 1838
a893e994 1839 if ( komodo_notaryvin(txNotary,NOTARY_PUBKEY33) > 0 )
496f1fd2 1840 {
2d79309f 1841 CAmount txfees = 5000;
496f1fd2 1842 pblock->vtx.push_back(txNotary);
1843 pblocktemplate->vTxFees.push_back(txfees);
1844 pblocktemplate->vTxSigOps.push_back(GetLegacySigOpCount(txNotary));
1845 nFees += txfees;
2d79309f 1846 pblocktemplate->vTxFees[0] = -nFees;
c881e52b 1847 //*(uint64_t *)(&pblock->vtx[0].vout[0].nValue) += txfees;
f31815fc 1848 //fprintf(stderr,"added notaryvin\n");
0857c3d5 1849 }
1850 else
1851 {
1852 fprintf(stderr,"error adding notaryvin, need to create 0.0001 utxos\n");
1853 return(0);
1854 }
707b061c 1855 }
809f2e25 1856 else if ( ASSETCHAINS_CC == 0 && pindexPrev != 0 && ASSETCHAINS_STAKED == 0 && (ASSETCHAINS_SYMBOL[0] != 0 || IS_KOMODO_NOTARY == 0 || My_notaryid < 0) )
af805d53 1857 {
8fc79ac9 1858 CValidationState state;
809f2e25 1859 //fprintf(stderr,"check validity\n");
88d014d0 1860 if ( !TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) // invokes CC checks
8fc79ac9 1861 {
9feb4b9e 1862 throw std::runtime_error("CreateNewBlock(): TestBlockValidity failed");
8fc79ac9 1863 }
809f2e25 1864 //fprintf(stderr,"valid\n");
af805d53 1865 }
d247a5d1 1866 }
2a6a442a 1867 //fprintf(stderr,"done new block\n");
1685bba0
MT
1868
1869 // setup the header and buid the Merkle tree
1870 unsigned int extraNonce;
88d014d0 1871 IncrementExtraNonce(pblock, pindexPrev, extraNonce, true);
1685bba0 1872
d247a5d1
JG
1873 return pblocktemplate.release();
1874}
32b915c9 1875
855714b0 1876CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& _scriptPubKeyIn, bool isStake)
1877{
1878 std::vector<CTxOut> minerOutputs = _scriptPubKeyIn.size() ? std::vector<CTxOut>({CTxOut(1, _scriptPubKeyIn)}) : std::vector<CTxOut>();
1879 return CreateNewBlock(chainparams, minerOutputs, isStake);
1880}
acfa0333 1881
c1de826f
JG
1882//////////////////////////////////////////////////////////////////////////////
1883//
1884// Internal miner
1885//
1886
2cc0a252 1887#ifdef ENABLE_MINING
c1de826f 1888
88d014d0 1889class MinerAddressScript : public CReserveScript
1890{
1891 // CReserveScript requires implementing this function, so that if an
1892 // internal (not-visible) wallet address is used, the wallet can mark it as
1893 // important when a block is mined (so it then appears to the user).
1894 // If -mineraddress is set, the user already knows about and is managing the
1895 // address, so we don't need to do anything here.
1896 void KeepScript() {}
1897};
1898
1899void GetScriptForMinerAddress(boost::shared_ptr<CReserveScript> &script)
1900{
1901 CTxDestination addr = DecodeDestination(GetArg("-mineraddress", ""));
1902 if (!IsValidDestination(addr)) {
1903 return;
1904 }
1905
1906 boost::shared_ptr<MinerAddressScript> mAddr(new MinerAddressScript());
88d014d0 1907 script = mAddr;
fa6c618c 1908 script->reserveScript = GetScriptForDestination(addr);
88d014d0 1909}
1910
4a85e067 1911#ifdef ENABLE_WALLET
acfa0333
WL
1912//////////////////////////////////////////////////////////////////////////////
1913//
1914// Internal miner
1915//
acfa0333 1916
855714b0 1917CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, bool isStake)
acfa0333 1918{
fa6c618c 1919 CPubKey pubkey;
1920 CScript scriptPubKey;
1921 uint8_t *ptr;
1922 int32_t i;
1923 boost::shared_ptr<CReserveScript> coinbaseScript;
1924
d9f176ac 1925 if ( nHeight == 1 && ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 )
1926 {
1927 scriptPubKey = CScript() << ParseHex(ASSETCHAINS_OVERRIDE_PUBKEY) << OP_CHECKSIG;
1928 }
1929 else if ( USE_EXTERNAL_PUBKEY != 0 )
998397aa 1930 {
7bfc207a 1931 //fprintf(stderr,"use notary pubkey\n");
c95fd5e0 1932 scriptPubKey = CScript() << ParseHex(NOTARY_PUBKEY) << OP_CHECKSIG;
f6c647ed 1933 }
fa6c618c 1934 else if (GetArg("-mineraddress", "").empty() || !(GetScriptForMinerAddress(coinbaseScript), (scriptPubKey = coinbaseScript->reserveScript).size()))
f6c647ed 1935 {
f1f6dfbb 1936 if (!isStake)
1b5b89ba 1937 {
f1f6dfbb 1938 if (!reservekey.GetReservedKey(pubkey))
1939 {
1940 return NULL;
1941 }
855714b0 1942 scriptPubKey = GetScriptForDestination(pubkey);
1b5b89ba 1943 }
f6c647ed 1944 }
855714b0 1945 return CreateNewBlock(Params(), scriptPubKey, isStake);
acfa0333
WL
1946}
1947
88d014d0 1948void komodo_broadcast(const CBlock *pblock,int32_t limit)
395f10cf 1949{
1950 int32_t n = 1;
1951 //fprintf(stderr,"broadcast new block t.%u\n",(uint32_t)time(NULL));
1952 {
1953 LOCK(cs_vNodes);
1954 BOOST_FOREACH(CNode* pnode, vNodes)
1955 {
1956 if ( pnode->hSocket == INVALID_SOCKET )
1957 continue;
1958 if ( (rand() % n) == 0 )
1959 {
1960 pnode->PushMessage("block", *pblock);
1961 if ( n++ > limit )
1962 break;
1963 }
1964 }
1965 }
1966 //fprintf(stderr,"finished broadcast new block t.%u\n",(uint32_t)time(NULL));
1967}
945f015d 1968
269d8ba0 1969static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
8e8b6d70
JG
1970#else
1971static bool ProcessBlockFound(CBlock* pblock)
1972#endif // ENABLE_WALLET
d247a5d1 1973{
572c763f 1974 int32_t height = chainActive.LastTip()->GetHeight()+1;
0ab273d2 1975 //LogPrintf("%s\n", pblock->ToString());
572c763f 1976 LogPrintf("generated %s height.%d\n", FormatMoney(pblock->vtx[0].vout[0].nValue), height);
af521e42 1977
d247a5d1
JG
1978 // Found a solution
1979 {
86131275 1980 if (pblock->hashPrevBlock != chainActive.LastTip()->GetBlockHash())
ba8419c7 1981 {
1982 uint256 hash; int32_t i;
1983 hash = pblock->hashPrevBlock;
92266e99 1984 for (i=31; i>=0; i--)
ba8419c7 1985 fprintf(stderr,"%02x",((uint8_t *)&hash)[i]);
c0dbb034 1986 fprintf(stderr," <- prev (stale)\n");
86131275 1987 hash = chainActive.LastTip()->GetBlockHash();
92266e99 1988 for (i=31; i>=0; i--)
ba8419c7 1989 fprintf(stderr,"%02x",((uint8_t *)&hash)[i]);
c0dbb034 1990 fprintf(stderr," <- chainTip (stale)\n");
e9e70b95 1991
ffde1589 1992 return error("VerusMiner: generated block is stale");
ba8419c7 1993 }
18e72167 1994 }
e9e70b95 1995
8e8b6d70 1996#ifdef ENABLE_WALLET
18e72167 1997 // Remove key from key pool
998397aa 1998 if ( IS_KOMODO_NOTARY == 0 )
945f015d 1999 {
2000 if (GetArg("-mineraddress", "").empty()) {
2001 // Remove key from key pool
2002 reservekey.KeepKey();
2003 }
8e8b6d70 2004 }
18e72167 2005 // Track how many getdata requests this block gets
438ba9c1 2006 //if ( 0 )
18e72167 2007 {
d1bc3a75 2008 //fprintf(stderr,"lock cs_wallet\n");
18e72167
PW
2009 LOCK(wallet.cs_wallet);
2010 wallet.mapRequestCount[pblock->GetHash()] = 0;
d247a5d1 2011 }
8e8b6d70 2012#endif
d1bc3a75 2013 //fprintf(stderr,"process new block\n");
194ad5b8 2014
c871d47f 2015 // Process this block (almost) the same as if we had received it from another node
18e72167 2016 CValidationState state;
88d014d0 2017 if (!ProcessNewBlock(1, chainActive.LastTip()->GetHeight()+1, state, Params(), NULL, pblock, true, NULL))
ffde1589 2018 return error("VerusMiner: ProcessNewBlock, block not accepted");
e9e70b95 2019
d793f94b 2020 TrackMinedBlock(pblock->GetHash());
395f10cf 2021 komodo_broadcast(pblock,16);
d247a5d1
JG
2022 return true;
2023}
2024
078f6af1 2025int32_t komodo_baseid(char *origbase);
a30dd993 2026int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t *blocktimes,int32_t *nonzpkeysp,int32_t height);
13691369 2027arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc);
8ee93080 2028int32_t FOUND_BLOCK,KOMODO_MAYBEMINED;
99ba67a0 2029extern int32_t KOMODO_LASTMINED,KOMODO_INSYNC;
8b51b9e4 2030int32_t roundrobin_delay;
18443f69 2031arith_uint256 HASHTarget,HASHTarget_POW;
3363d1c0 2032int32_t komodo_longestchain();
078f6af1 2033
5642c96c 2034// wait for peers to connect
12217420 2035void waitForPeers(const CChainParams &chainparams)
5642c96c 2036{
2037 if (chainparams.MiningRequiresPeers())
2038 {
3da69a31
MT
2039 bool fvNodesEmpty;
2040 {
00a7120e 2041 boost::this_thread::interruption_point();
3da69a31
MT
2042 LOCK(cs_vNodes);
2043 fvNodesEmpty = vNodes.empty();
2044 }
3363d1c0 2045 int longestchain = komodo_longestchain();
2046 int lastlongest = 0;
2047 if (fvNodesEmpty || IsNotInSync() || (longestchain != 0 && longestchain > chainActive.LastTip()->GetHeight()))
3da69a31 2048 {
af2e212d 2049 int loops = 0, blockDiff = 0, newDiff = 0;
2050
3da69a31 2051 do {
64d6048f 2052 if (fvNodesEmpty)
3da69a31 2053 {
69fa3d0e 2054 MilliSleep(1000 + rand() % 4000);
00a7120e 2055 boost::this_thread::interruption_point();
3da69a31
MT
2056 LOCK(cs_vNodes);
2057 fvNodesEmpty = vNodes.empty();
af2e212d 2058 loops = 0;
2059 blockDiff = 0;
3363d1c0 2060 lastlongest = 0;
af2e212d 2061 }
3363d1c0 2062 else if ((newDiff = IsNotInSync()) > 0)
af2e212d 2063 {
2064 if (blockDiff != newDiff)
2065 {
2066 blockDiff = newDiff;
2067 }
2068 else
2069 {
3363d1c0 2070 if (++loops <= 5)
af2e212d 2071 {
2072 MilliSleep(1000);
2073 }
2074 else break;
2075 }
3363d1c0 2076 lastlongest = 0;
2077 }
2078 else if (!fvNodesEmpty && !IsNotInSync() && longestchain > chainActive.LastTip()->GetHeight())
2079 {
2080 // the only thing may be that we are seeing a long chain that we'll never get
2081 // don't wait forever
2082 if (lastlongest == 0)
2083 {
2084 MilliSleep(3000);
2085 lastlongest = longestchain;
2086 }
3da69a31 2087 }
af2e212d 2088 } while (fvNodesEmpty || IsNotInSync());
2603640e 2089 MilliSleep(500 + rand() % 1000);
3da69a31 2090 }
5642c96c 2091 }
2092}
2093
42181656 2094#ifdef ENABLE_WALLET
d7e6718d
MT
2095CBlockIndex *get_chainactive(int32_t height)
2096{
3c40a9a6 2097 if ( chainActive.LastTip() != 0 )
d7e6718d 2098 {
4b729ec5 2099 if ( height <= chainActive.LastTip()->GetHeight() )
3c40a9a6
MT
2100 {
2101 LOCK(cs_main);
d7e6718d 2102 return(chainActive[height]);
3c40a9a6 2103 }
4b729ec5 2104 // else fprintf(stderr,"get_chainactive height %d > active.%d\n",height,chainActive.Tip()->GetHeight());
d7e6718d
MT
2105 }
2106 //fprintf(stderr,"get_chainactive null chainActive.Tip() height %d\n",height);
2107 return(0);
2108}
2109
135fa24e 2110/*
2111 * A separate thread to stake, while the miner threads mine.
2112 */
2113void static VerusStaker(CWallet *pwallet)
2114{
2115 LogPrintf("Verus staker thread started\n");
2116 RenameThread("verus-staker");
2117
2118 const CChainParams& chainparams = Params();
2d02c19e 2119 auto consensusParams = chainparams.GetConsensus();
76f69285 2120 bool isNotaryConnected = ConnectedChains.CheckVerusPBaaSAvailable();
135fa24e 2121
2122 // Each thread has its own key
2123 CReserveKey reservekey(pwallet);
2124
2125 // Each thread has its own counter
2126 unsigned int nExtraNonce = 0;
12217420 2127
135fa24e 2128 uint8_t *script; uint64_t total,checktoshis; int32_t i,j;
2129
4b729ec5 2130 while ( (ASSETCHAIN_INIT == 0 || KOMODO_INITDONE == 0) ) //chainActive.Tip()->GetHeight() != 235300 &&
135fa24e 2131 {
2132 sleep(1);
2133 if ( komodo_baseid(ASSETCHAINS_SYMBOL) < 0 )
2134 break;
2135 }
2136
2137 // try a nice clean peer connection to start
bf9c36f4
MT
2138 CBlockIndex *pindexPrev, *pindexCur;
2139 do {
2140 pindexPrev = chainActive.LastTip();
2141 MilliSleep(5000 + rand() % 5000);
2142 waitForPeers(chainparams);
2143 pindexCur = chainActive.LastTip();
2144 } while (pindexPrev != pindexCur);
c132b91a 2145
135fa24e 2146 try {
0fc0dc56 2147 static int32_t lastStakingHeight = 0;
2148
135fa24e 2149 while (true)
2150 {
135fa24e 2151 waitForPeers(chainparams);
4ca6678c 2152 CBlockIndex* pindexPrev = chainActive.LastTip();
135fa24e 2153
2154 // Create new block
2155 unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
0fc0dc56 2156
4b729ec5 2157 if ( Mining_height != pindexPrev->GetHeight()+1 )
135fa24e 2158 {
4b729ec5 2159 Mining_height = pindexPrev->GetHeight()+1;
135fa24e 2160 Mining_start = (uint32_t)time(NULL);
2161 }
2162
1fae37f6
MT
2163 // Check for stop or if block needs to be rebuilt
2164 boost::this_thread::interruption_point();
2165
135fa24e 2166 // try to stake a block
1fae37f6 2167 CBlockTemplate *ptr = NULL;
31609f35 2168
2169 // get height locally for consistent reporting
2170 int32_t newHeight = Mining_height;
2171
2172 if (newHeight > VERUS_MIN_STAKEAGE)
855714b0 2173 ptr = CreateNewBlockWithKey(reservekey, newHeight, true);
135fa24e 2174
a73ab4b4 2175 // TODO - putting this output here tends to help mitigate announcing a staking height earlier than
2176 // announcing the last block win when we start staking before a block's acceptance has been
2177 // acknowledged by the mining thread - a better solution may be to put the output on the submission
2178 // thread.
31609f35 2179 if ( ptr == 0 && newHeight != lastStakingHeight )
a73ab4b4 2180 {
31609f35 2181 printf("Staking height %d for %s\n", newHeight, ASSETCHAINS_SYMBOL);
a73ab4b4 2182 }
31609f35 2183 lastStakingHeight = newHeight;
a73ab4b4 2184
135fa24e 2185 if ( ptr == 0 )
2186 {
67dceeec 2187 if (newHeight == 1 && (isNotaryConnected = ConnectedChains.IsNotaryAvailable()))
76f69285 2188 {
2189 static int outputCounter;
2190 if (outputCounter++ % 60 == 0)
2191 {
695db088 2192 printf("%s: waiting for confirmation of launch at or after block %u on %s before mining block 1\n", __func__,
2193 (uint32_t)ConnectedChains.ThisChain().startBlock,
76f69285 2194 ConnectedChains.FirstNotaryChain().chainDefinition.name.c_str());
2195 sleep(1);
2196 }
2197 }
1fae37f6 2198 // wait to try another staking block until after the tip moves again
37ad6886 2199 while ( chainActive.LastTip() == pindexPrev )
bab13dd2 2200 MilliSleep(250);
76f69285 2201 if (newHeight == 1)
2202 {
2203 sleep(10);
2204 }
135fa24e 2205 continue;
2206 }
2207
2208 unique_ptr<CBlockTemplate> pblocktemplate(ptr);
2209 if (!pblocktemplate.get())
2210 {
2211 if (GetArg("-mineraddress", "").empty()) {
1fae37f6 2212 LogPrintf("Error in %s staker: Keypool ran out, please call keypoolrefill before restarting the mining thread\n",
135fa24e 2213 ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
2214 } else {
2215 // Should never reach here, because -mineraddress validity is checked in init.cpp
1fae37f6 2216 LogPrintf("Error in %s staker: Invalid %s -mineraddress\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO], ASSETCHAINS_SYMBOL);
135fa24e 2217 }
2218 return;
2219 }
2220
2221 CBlock *pblock = &pblocktemplate->block;
1fae37f6 2222 LogPrintf("Staking with %u transactions in block (%u bytes)\n", pblock->vtx.size(),::GetSerializeSize(*pblock,SER_NETWORK,PROTOCOL_VERSION));
135fa24e 2223 //
2224 // Search
2225 //
1fae37f6
MT
2226 int64_t nStart = GetTime();
2227
1fae37f6
MT
2228 if (vNodes.empty() && chainparams.MiningRequiresPeers())
2229 {
2230 if ( Mining_height > ASSETCHAINS_MINHEIGHT )
2231 {
2232 fprintf(stderr,"no nodes, attempting reconnect\n");
2233 continue;
2234 }
2235 }
2236
2237 if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
2238 {
2239 fprintf(stderr,"timeout, retrying\n");
2240 continue;
2241 }
135fa24e 2242
37ad6886 2243 if ( pindexPrev != chainActive.LastTip() )
135fa24e 2244 {
4b729ec5 2245 printf("Block %d added to chain\n", chainActive.LastTip()->GetHeight());
135fa24e 2246 MilliSleep(250);
2247 continue;
2248 }
2249
1fae37f6
MT
2250 int32_t unlockTime = komodo_block_unlocktime(Mining_height);
2251 int64_t subsidy = (int64_t)(pblock->vtx[0].vout[0].nValue);
135fa24e 2252
1fae37f6 2253 uint256 hashTarget = ArithToUint256(arith_uint256().SetCompact(pblock->nBits));
135fa24e 2254
df756d24 2255 pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams);
b9956efc 2256
df756d24 2257 UpdateTime(pblock, consensusParams, pindexPrev);
b9956efc 2258
ed47e5ec
MT
2259 if (ProcessBlockFound(pblock, *pwallet, reservekey))
2260 {
2261 LogPrintf("Using %s algorithm:\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
2262 LogPrintf("Staked block found \n hash: %s \ntarget: %s\n", pblock->GetHash().GetHex(), hashTarget.GetHex());
31609f35 2263 printf("Found block %d \n", newHeight);
ed47e5ec
MT
2264 printf("staking reward %.8f %s!\n", (double)subsidy / (double)COIN, ASSETCHAINS_SYMBOL);
2265 arith_uint256 post;
2266 post.SetCompact(pblock->GetVerusPOSTarget());
31609f35 2267
ed47e5ec
MT
2268 CTransaction &sTx = pblock->vtx[pblock->vtx.size()-1];
2269 printf("POS hash: %s \ntarget: %s\n",
31609f35 2270 CTransaction::_GetVerusPOSHash(&(pblock->nNonce),
2271 sTx.vin[0].prevout.hash,
2272 sTx.vin[0].prevout.n,
2273 newHeight,
8d2b052e 2274 chainActive.GetVerusEntropyHash(newHeight),
31609f35 2275 sTx.vout[0].nValue).GetHex().c_str(),
2276 ArithToUint256(post).GetHex().c_str());
2277 if (unlockTime > newHeight && subsidy >= ASSETCHAINS_TIMELOCKGTE)
ed47e5ec
MT
2278 printf("- timelocked until block %i\n", unlockTime);
2279 else
2280 printf("\n");
2281 }
1fae37f6 2282 else
ed47e5ec
MT
2283 {
2284 LogPrintf("Found block rejected at staking height: %d\n", Mining_height);
2285 printf("Found block rejected at staking height: %d\n", Mining_height);
2286 }
135fa24e 2287
1fae37f6
MT
2288 // Check for stop or if block needs to be rebuilt
2289 boost::this_thread::interruption_point();
135fa24e 2290
bf9c36f4 2291 sleep(3);
3da69a31 2292
1fae37f6
MT
2293 // In regression test mode, stop mining after a block is found.
2294 if (chainparams.MineBlocksOnDemand()) {
2295 throw boost::thread_interrupted();
135fa24e 2296 }
2297 }
2298 }
2299 catch (const boost::thread_interrupted&)
2300 {
135fa24e 2301 LogPrintf("VerusStaker terminated\n");
2302 throw;
2303 }
2304 catch (const std::runtime_error &e)
2305 {
135fa24e 2306 LogPrintf("VerusStaker runtime error: %s\n", e.what());
2307 return;
2308 }
135fa24e 2309}
2310
c17dbdee 2311typedef bool (*minefunction)(CBlockHeader &bh, CVerusHashV2bWriter &vhw, uint256 &finalHash, uint256 &target, uint64_t start, uint64_t *count);
2312bool mine_verus_v2(CBlockHeader &bh, CVerusHashV2bWriter &vhw, uint256 &finalHash, uint256 &target, uint64_t start, uint64_t *count);
2313bool mine_verus_v2_port(CBlockHeader &bh, CVerusHashV2bWriter &vhw, uint256 &finalHash, uint256 &target, uint64_t start, uint64_t *count);
fa7fdbc6 2314
42181656 2315void static BitcoinMiner_noeq(CWallet *pwallet)
2316#else
2317void static BitcoinMiner_noeq()
2318#endif
2319{
05f6e633 2320 LogPrintf("%s miner started\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
05f6e633 2321 RenameThread("verushash-miner");
42181656 2322
2323#ifdef ENABLE_WALLET
2324 // Each thread has its own key
2325 CReserveKey reservekey(pwallet);
2326#endif
2327
248084b7 2328 miningTimer.clear();
2329
2910478b 2330 const CChainParams& chainparams = Params();
42181656 2331 // Each thread has its own counter
2332 unsigned int nExtraNonce = 0;
12217420 2333
42181656 2334 uint8_t *script; uint64_t total,checktoshis; int32_t i,j;
2335
4b729ec5 2336 while ( (ASSETCHAIN_INIT == 0 || KOMODO_INITDONE == 0) ) //chainActive.Tip()->GetHeight() != 235300 &&
42181656 2337 {
2338 sleep(1);
2339 if ( komodo_baseid(ASSETCHAINS_SYMBOL) < 0 )
2340 break;
2341 }
9f3e2213 2342
3da69a31
MT
2343 SetThreadPriority(THREAD_PRIORITY_LOWEST);
2344
5642c96c 2345 // try a nice clean peer connection to start
c132b91a 2346 CBlockIndex *pindexPrev, *pindexCur;
9f3e2213 2347 do {
37ad6886 2348 pindexPrev = chainActive.LastTip();
3da69a31 2349 MilliSleep(5000 + rand() % 5000);
bf9c36f4 2350 waitForPeers(chainparams);
37ad6886 2351 pindexCur = chainActive.LastTip();
c132b91a 2352 } while (pindexPrev != pindexCur);
6176a421 2353
a9f18272 2354 // make sure that we have checked for PBaaS availability
2355 ConnectedChains.CheckVerusPBaaSAvailable();
2356
dbe656fe
MT
2357 // this will not stop printing more than once in all cases, but it will allow us to print in all cases
2358 // and print duplicates rarely without having to synchronize
2359 static CBlockIndex *lastChainTipPrinted;
90198f71 2360 static int32_t lastMiningHeight = 0;
9f3e2213 2361
42181656 2362 miningTimer.start();
2363
2364 try {
dbe656fe 2365 printf("Mining %s with %s\n", ASSETCHAINS_SYMBOL, ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
08d46b7f 2366
42181656 2367 while (true)
2368 {
68334c8d 2369 miningTimer.stop();
2370 waitForPeers(chainparams);
dfcf8255 2371
37ad6886 2372 pindexPrev = chainActive.LastTip();
dfcf8255 2373
f8f61a6d 2374 // prevent forking on startup before the diff algorithm kicks in,
2375 // but only for a startup Verus test chain. PBaaS chains have the difficulty inherited from
2376 // their parent
57055854 2377 if (chainparams.MiningRequiresPeers() && ((IsVerusActive() && pindexPrev->GetHeight() < 50) || pindexPrev != chainActive.LastTip()))
dfcf8255
MT
2378 {
2379 do {
37ad6886 2380 pindexPrev = chainActive.LastTip();
2830db29 2381 MilliSleep(2000 + rand() % 2000);
37ad6886 2382 } while (pindexPrev != chainActive.LastTip());
dfcf8255 2383 }
42181656 2384
2385 // Create new block
2386 unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
4b729ec5 2387 if ( Mining_height != pindexPrev->GetHeight()+1 )
42181656 2388 {
4b729ec5 2389 Mining_height = pindexPrev->GetHeight()+1;
90198f71 2390 if (lastMiningHeight != Mining_height)
2391 {
2392 lastMiningHeight = Mining_height;
dc74c06d 2393 printf("Mining %s at height %d\n", ASSETCHAINS_SYMBOL, Mining_height);
90198f71 2394 }
42181656 2395 Mining_start = (uint32_t)time(NULL);
2396 }
2397
dbe656fe 2398 miningTimer.start();
42181656 2399
2400#ifdef ENABLE_WALLET
855714b0 2401 CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, Mining_height);
42181656 2402#else
2403 CBlockTemplate *ptr = CreateNewBlockWithKey();
2404#endif
2405 if ( ptr == 0 )
2406 {
2407 static uint32_t counter;
f6084562
MT
2408 if ( counter++ % 40 == 0 )
2409 {
2410 if (!IsVerusActive() &&
67dceeec 2411 ConnectedChains.IsNotaryAvailable() &&
76f69285 2412 !ConnectedChains.readyToStart)
f6084562 2413 {
695db088 2414 fprintf(stderr,"waiting for confirmation of launch at or after block %u on %s chain to start\n", (uint32_t)ConnectedChains.ThisChain().startBlock,
c8c684e9 2415 ConnectedChains.FirstNotaryChain().chainDefinition.name.c_str());
f6084562
MT
2416 }
2417 else
2418 {
2419 fprintf(stderr,"Unable to create valid block... will continue to try\n");
2420 }
2421 }
2830db29 2422 MilliSleep(2000);
42181656 2423 continue;
2424 }
dbe656fe 2425
42181656 2426 unique_ptr<CBlockTemplate> pblocktemplate(ptr);
2427 if (!pblocktemplate.get())
2428 {
2429 if (GetArg("-mineraddress", "").empty()) {
05f6e633 2430 LogPrintf("Error in %s miner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n",
2431 ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
42181656 2432 } else {
2433 // Should never reach here, because -mineraddress validity is checked in init.cpp
05f6e633 2434 LogPrintf("Error in %s miner: Invalid %s -mineraddress\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO], ASSETCHAINS_SYMBOL);
42181656 2435 }
02dbe9a3 2436 miningTimer.stop();
248084b7 2437 miningTimer.clear();
42181656 2438 return;
2439 }
2440 CBlock *pblock = &pblocktemplate->block;
f8f61a6d 2441
2442 uint32_t savebits;
2443 bool mergeMining = false;
2444 savebits = pblock->nBits;
2445
1e435b54 2446 uint32_t solutionVersion = CConstVerusSolutionVector::Version(pblock->nSolution);
f37d48ca 2447 if (pblock->nVersion != CBlockHeader::VERUS_V2)
2448 {
2449 // must not be in sync
2450 printf("Mining on incorrect block version.\n");
2451 sleep(2);
2452 continue;
2453 }
d3dfc922 2454 bool verusSolutionPBaaS = solutionVersion >= CActivationHeight::ACTIVATE_PBAAS;
f8f61a6d 2455
c17dbdee 2456 // v2 hash writer with adjustments for the current height
2457 CVerusHashV2bWriter ss2 = CVerusHashV2bWriter(SER_GETHASH, PROTOCOL_VERSION, solutionVersion);
2458
42181656 2459 if ( ASSETCHAINS_SYMBOL[0] != 0 )
2460 {
2461 if ( ASSETCHAINS_REWARD[0] == 0 && !ASSETCHAINS_LASTERA )
2462 {
2463 if ( pblock->vtx.size() == 1 && pblock->vtx[0].vout.size() == 1 && Mining_height > ASSETCHAINS_MINHEIGHT )
2464 {
2465 static uint32_t counter;
2466 if ( counter++ < 10 )
2467 fprintf(stderr,"skip generating %s on-demand block, no tx avail\n",ASSETCHAINS_SYMBOL);
2468 sleep(10);
2469 continue;
2470 } else fprintf(stderr,"%s vouts.%d mining.%d vs %d\n",ASSETCHAINS_SYMBOL,(int32_t)pblock->vtx[0].vout.size(),Mining_height,ASSETCHAINS_MINHEIGHT);
2471 }
2472 }
b2a98c42 2473
c871d47f 2474 // set our easiest target, if V3+, no need to rebuild the merkle tree
f37d48ca 2475 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce, verusSolutionPBaaS ? false : true, &savebits);
b2a98c42
MT
2476
2477 // update PBaaS header
f37d48ca 2478 if (verusSolutionPBaaS)
b2a98c42 2479 {
2fd1f0fb 2480 if (!IsVerusActive() && ConnectedChains.IsVerusPBaaSAvailable())
f8f61a6d 2481 {
b2a98c42 2482
2fd1f0fb 2483 UniValue params(UniValue::VARR);
2484 UniValue error(UniValue::VARR);
2485 params.push_back(EncodeHexBlk(*pblock));
2486 params.push_back(ASSETCHAINS_SYMBOL);
2487 params.push_back(ASSETCHAINS_RPCHOST);
2488 params.push_back(ASSETCHAINS_RPCPORT);
2489 params.push_back(ASSETCHAINS_RPCCREDENTIALS);
2490 try
b2a98c42 2491 {
be17c611 2492 ConnectedChains.lastSubmissionFailed = false;
2fd1f0fb 2493 params = RPCCallRoot("addmergedblock", params);
2494 params = find_value(params, "result");
2495 error = find_value(params, "error");
2496 } catch (std::exception e)
2497 {
c8c684e9 2498 printf("Failed to connect to %s chain\n", ConnectedChains.FirstNotaryChain().chainDefinition.name.c_str());
2fd1f0fb 2499 params = UniValue(e.what());
b2a98c42 2500 }
2fd1f0fb 2501 if (mergeMining = (params.isNull() && error.isNull()))
f8f61a6d 2502 {
c8c684e9 2503 printf("Merge mining %s with %s as the hashing chain\n", ASSETCHAINS_SYMBOL, ConnectedChains.FirstNotaryChain().chainDefinition.name.c_str());
2504 LogPrintf("Merge mining with %s as the hashing chain\n", ConnectedChains.FirstNotaryChain().chainDefinition.name.c_str());
f8f61a6d 2505 }
b2a98c42
MT
2506 }
2507 }
2508
42181656 2509 LogPrintf("Running %s miner with %u transactions in block (%u bytes)\n",ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO],
2510 pblock->vtx.size(),::GetSerializeSize(*pblock,SER_NETWORK,PROTOCOL_VERSION));
2511 //
2512 // Search
2513 //
f8f61a6d 2514 int64_t nStart = GetTime();
42181656 2515
f8f61a6d 2516 arith_uint256 hashTarget = arith_uint256().SetCompact(savebits);
fa7fdbc6 2517 uint256 uintTarget = ArithToUint256(hashTarget);
f8f61a6d 2518 arith_uint256 ourTarget;
2519 ourTarget.SetCompact(pblock->nBits);
2520
42181656 2521 Mining_start = 0;
ef70c5b2 2522
37ad6886 2523 if ( pindexPrev != chainActive.LastTip() )
05f6e633 2524 {
37ad6886 2525 if (lastChainTipPrinted != chainActive.LastTip())
dbe656fe 2526 {
37ad6886 2527 lastChainTipPrinted = chainActive.LastTip();
4b729ec5 2528 printf("Block %d added to chain\n", lastChainTipPrinted->GetHeight());
dbe656fe 2529 }
f8f61a6d 2530 MilliSleep(100);
05f6e633 2531 continue;
2532 }
ef70c5b2 2533
2830db29 2534 uint64_t count;
2535 uint64_t hashesToGo = 0;
2536 uint64_t totalDone = 0;
2537
e29b5dd5 2538 int64_t subsidy = (int64_t)(pblock->vtx[0].vout[0].nValue);
fa7fdbc6 2539 count = ((ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] >> 3) + 1) / ASSETCHAINS_HASHESPERROUND[ASSETCHAINS_ALGO];
db027133 2540 CVerusHashV2 *vh2 = &ss2.GetState();
3b500530 2541 u128 *hashKey;
2542 verusclhasher &vclh = vh2->vclh;
fa7fdbc6 2543 minefunction mine_verus;
2544 mine_verus = IsCPUVerusOptimized() ? &mine_verus_v2 : &mine_verus_v2_port;
f21fad6a 2545
42181656 2546 while (true)
2547 {
4dcb64c0 2548 uint256 hashResult = uint256();
458bfcab 2549
e5fb645e 2550 unsigned char *curBuf;
2551
f8f61a6d 2552 if (mergeMining)
42181656 2553 {
c89d86ee 2554 // loop for a few minutes before refreshing the block
e771a884 2555 while (true)
12217420 2556 {
93ff475b 2557 uint256 ourMerkle = pblock->hashMerkleRoot;
a1d91f89 2558 if ( pindexPrev != chainActive.LastTip() )
2559 {
2560 if (lastChainTipPrinted != chainActive.LastTip())
2561 {
2562 lastChainTipPrinted = chainActive.LastTip();
2563 printf("Block %d added to chain\n\n", lastChainTipPrinted->GetHeight());
2564 arith_uint256 target;
2565 target.SetCompact(lastChainTipPrinted->nBits);
93ff475b
MT
2566 if (ourMerkle == lastChainTipPrinted->hashMerkleRoot)
2567 {
2568 LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", lastChainTipPrinted->GetBlockHash().GetHex().c_str(), ArithToUint256(ourTarget).GetHex().c_str());
607402ba 2569 printf("Found block %d \n", lastChainTipPrinted->GetHeight());
93ff475b
MT
2570 printf("mining reward %.8f %s!\n", (double)subsidy / (double)COIN, ASSETCHAINS_SYMBOL);
2571 printf(" hash: %s\ntarget: %s\n", lastChainTipPrinted->GetBlockHash().GetHex().c_str(), ArithToUint256(ourTarget).GetHex().c_str());
2572 }
a1d91f89 2573 }
2574 break;
2575 }
2576
e771a884 2577 // if PBaaS is no longer available, we can't count on merge mining
2578 if (!ConnectedChains.IsVerusPBaaSAvailable())
2579 {
2580 break;
2581 }
f8f61a6d 2582
2583 if (vNodes.empty() && chainparams.MiningRequiresPeers())
458bfcab 2584 {
f8f61a6d 2585 if ( Mining_height > ASSETCHAINS_MINHEIGHT )
fa7fdbc6 2586 {
f8f61a6d 2587 fprintf(stderr,"no nodes, attempting reconnect\n");
2588 break;
fa7fdbc6 2589 }
f8f61a6d 2590 }
2591
a82942e4 2592 // update every few minutes, regardless
2593 int64_t elapsed = GetTime() - nStart;
f8f61a6d 2594
a9663647 2595 if ((mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && elapsed > 60) || elapsed > 60 || ConnectedChains.lastSubmissionFailed)
458bfcab 2596 {
f8f61a6d 2597 break;
458bfcab 2598 }
a1d91f89 2599
dc74c06d 2600 boost::this_thread::interruption_point();
a1d91f89 2601 MilliSleep(500);
458bfcab 2602 }
ffde1589 2603 break;
f8f61a6d 2604 }
2605 else
2606 {
2607 // check NONCEMASK at a time
2608 for (uint64_t i = 0; i < count; i++)
42181656 2609 {
2fd1f0fb 2610 // this is the actual mining loop, which enables us to drop out and queue a header anytime we earn a block that is good enough for a
f8f61a6d 2611 // merge mined block, but not our own
f8f61a6d 2612 bool blockFound;
2613 arith_uint256 arithHash;
2830db29 2614 totalDone = 0;
f8f61a6d 2615 do
2616 {
2fd1f0fb 2617 // pickup/remove any new/deleted headers
71f97948 2618 if (ConnectedChains.dirty || (pblock->NumPBaaSHeaders() < ConnectedChains.mergeMinedChains.size() + 1))
2fd1f0fb 2619 {
f37d48ca 2620 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce, verusSolutionPBaaS ? false : true, &savebits);
1fa4454d 2621
2fd1f0fb 2622 hashTarget.SetCompact(savebits);
2623 uintTarget = ArithToUint256(hashTarget);
2624 }
2625
f8f61a6d 2626 // hashesToGo gets updated with actual number run for metrics
2627 hashesToGo = ASSETCHAINS_HASHESPERROUND[ASSETCHAINS_ALGO];
2830db29 2628 uint64_t start = i * hashesToGo + totalDone;
f8f61a6d 2629 hashesToGo -= totalDone;
2630
f37d48ca 2631 if (verusSolutionPBaaS)
f8f61a6d 2632 {
2633 // mine on canonical header for merge mining
2634 CPBaaSPreHeader savedHeader(*pblock);
da97aa5c 2635
f8f61a6d 2636 pblock->ClearNonCanonicalData();
c17dbdee 2637 blockFound = (*mine_verus)(*pblock, ss2, hashResult, uintTarget, start, &hashesToGo);
f8f61a6d 2638 savedHeader.SetBlockData(*pblock);
2639 }
2640 else
2641 {
c17dbdee 2642 blockFound = (*mine_verus)(*pblock, ss2, hashResult, uintTarget, start, &hashesToGo);
f8f61a6d 2643 }
2644
2645 arithHash = UintToArith256(hashResult);
249e20e4 2646 totalDone += hashesToGo + 1;
f8f61a6d 2647 if (blockFound && IsVerusActive())
2648 {
2649 ConnectedChains.QueueNewBlockHeader(*pblock);
2650 if (arithHash > ourTarget)
2651 {
2652 // all blocks qualified with this hash will be submitted
2653 // until we redo the block, we might as well not try again with anything over this hash
2654 hashTarget = arithHash;
2655 uintTarget = ArithToUint256(hashTarget);
2656 }
2657 }
2fd1f0fb 2658 } while (blockFound && arithHash > ourTarget);
c98efb5a 2659
f8f61a6d 2660 if (!blockFound || arithHash > ourTarget)
4dcb64c0 2661 {
f8f61a6d 2662 // Check for stop or if block needs to be rebuilt
2663 boost::this_thread::interruption_point();
ce40cf2e 2664 if ( pindexPrev != chainActive.LastTip() )
f8f61a6d 2665 {
2666 if (lastChainTipPrinted != chainActive.LastTip())
2667 {
2668 lastChainTipPrinted = chainActive.LastTip();
2669 printf("Block %d added to chain\n", lastChainTipPrinted->GetHeight());
2670 }
2671 break;
2672 }
a1d91f89 2673 else if ((i + 1) < count)
f8f61a6d 2674 {
a1d91f89 2675 // if we'll not drop through, update hashcount
f8f61a6d 2676 {
02dbe9a3 2677 miningTimer += totalDone;
2830db29 2678 totalDone = 0;
f8f61a6d 2679 }
f8f61a6d 2680 }
4dcb64c0 2681 }
f8f61a6d 2682 else
2683 {
2684 // Check for stop or if block needs to be rebuilt
2685 boost::this_thread::interruption_point();
4dcb64c0 2686
f8f61a6d 2687 if (pblock->nSolution.size() != 1344)
2688 {
2689 LogPrintf("ERROR: Block solution is not 1344 bytes as it should be");
2690 break;
2691 }
42181656 2692
f8f61a6d 2693 SetThreadPriority(THREAD_PRIORITY_NORMAL);
2694
2695 int32_t unlockTime = komodo_block_unlocktime(Mining_height);
ef70c5b2 2696
3363d1c0 2697#ifdef VERUSHASHDEBUG
f8f61a6d 2698 std::string validateStr = hashResult.GetHex();
2699 std::string hashStr = pblock->GetHash().GetHex();
2700 uint256 *bhalf1 = (uint256 *)vh2->CurBuffer();
2701 uint256 *bhalf2 = bhalf1 + 1;
3363d1c0 2702#else
f8f61a6d 2703 std::string hashStr = hashResult.GetHex();
3363d1c0 2704#endif
3af22e67 2705
f8f61a6d 2706 LogPrintf("Using %s algorithm:\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
2707 LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", hashStr, ArithToUint256(ourTarget).GetHex());
2708 printf("Found block %d \n", Mining_height );
2709 printf("mining reward %.8f %s!\n", (double)subsidy / (double)COIN, ASSETCHAINS_SYMBOL);
3363d1c0 2710#ifdef VERUSHASHDEBUG
f8f61a6d 2711 printf(" hash: %s\n val: %s \ntarget: %s\n\n", hashStr.c_str(), validateStr.c_str(), ArithToUint256(ourTarget).GetHex().c_str());
2712 printf("intermediate %lx\n", intermediate);
2713 printf("Curbuf: %s%s\n", bhalf1->GetHex().c_str(), bhalf2->GetHex().c_str());
2714 bhalf1 = (uint256 *)verusclhasher_key.get();
2715 bhalf2 = bhalf1 + ((vh2->vclh.keyMask + 1) >> 5);
2716 printf(" Key: %s%s\n", bhalf1->GetHex().c_str(), bhalf2->GetHex().c_str());
3363d1c0 2717#else
f8f61a6d 2718 printf(" hash: %s\ntarget: %s", hashStr.c_str(), ArithToUint256(ourTarget).GetHex().c_str());
3363d1c0 2719#endif
f8f61a6d 2720 if (unlockTime > Mining_height && subsidy >= ASSETCHAINS_TIMELOCKGTE)
2721 printf(" - timelocked until block %i\n", unlockTime);
2722 else
2723 printf("\n");
42181656 2724#ifdef ENABLE_WALLET
f8f61a6d 2725 ProcessBlockFound(pblock, *pwallet, reservekey);
42181656 2726#else
f8f61a6d 2727 ProcessBlockFound(pblock);
42181656 2728#endif
f8f61a6d 2729 SetThreadPriority(THREAD_PRIORITY_LOWEST);
2730 break;
2731 }
42181656 2732 }
42181656 2733
f8f61a6d 2734 {
02dbe9a3 2735 miningTimer += totalDone;
f8f61a6d 2736 }
69767347 2737 }
f8f61a6d 2738
69767347 2739
42181656 2740 // Check for stop or if block needs to be rebuilt
2741 boost::this_thread::interruption_point();
2742
2743 if (vNodes.empty() && chainparams.MiningRequiresPeers())
2744 {
2745 if ( Mining_height > ASSETCHAINS_MINHEIGHT )
2746 {
ef70c5b2 2747 fprintf(stderr,"no nodes, attempting reconnect\n");
42181656 2748 break;
2749 }
2750 }
2751
dbe656fe 2752 if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
42181656 2753 {
dbe656fe 2754 fprintf(stderr,"timeout, retrying\n");
42181656 2755 break;
2756 }
2757
37ad6886 2758 if ( pindexPrev != chainActive.LastTip() )
42181656 2759 {
37ad6886 2760 if (lastChainTipPrinted != chainActive.LastTip())
dbe656fe 2761 {
37ad6886 2762 lastChainTipPrinted = chainActive.LastTip();
90198f71 2763 printf("Block %d added to chain\n\n", lastChainTipPrinted->GetHeight());
dbe656fe 2764 }
42181656 2765 break;
2766 }
2767
2830db29 2768 // totalDone now has the number of hashes actually done since starting on one nonce mask worth
ce40cf2e 2769 uint64_t hashesPerNonceMask = ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] >> 3;
2830db29 2770 if (!(totalDone < hashesPerNonceMask))
ce40cf2e 2771 {
52cf66e1 2772#ifdef _WIN32
ce40cf2e 2773 printf("%llu mega hashes complete - working\n", (hashesPerNonceMask + 1) / 1048576);
52cf66e1 2774#else
ce40cf2e 2775 printf("%lu mega hashes complete - working\n", (hashesPerNonceMask + 1) / 1048576);
52cf66e1 2776#endif
ce40cf2e 2777 }
4dcb64c0 2778 break;
8682e17a 2779
42181656 2780 }
2781 }
2782 }
2783 catch (const boost::thread_interrupted&)
2784 {
2785 miningTimer.stop();
248084b7 2786 miningTimer.clear();
5034d1c1 2787 LogPrintf("%s miner terminated\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
42181656 2788 throw;
2789 }
2790 catch (const std::runtime_error &e)
2791 {
2792 miningTimer.stop();
248084b7 2793 miningTimer.clear();
5034d1c1 2794 LogPrintf("%s miner runtime error: %s\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO], e.what());
42181656 2795 return;
2796 }
2797 miningTimer.stop();
248084b7 2798 miningTimer.clear();
42181656 2799}
2800
8e8b6d70 2801#ifdef ENABLE_WALLET
e9e70b95 2802 void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads)
8e8b6d70 2803#else
e9e70b95 2804 void GenerateBitcoins(bool fGenerate, int nThreads)
8e8b6d70 2805#endif
d247a5d1 2806 {
9ae83faa 2807 static CCriticalSection cs_startmining;
2808
2809 LOCK(cs_startmining);
f8f61a6d 2810 if (!AreParamsInitialized())
2811 {
2812 return;
2813 }
2814
b20c38cc 2815 VERUS_MINTBLOCKS = (VERUS_MINTBLOCKS && ASSETCHAINS_LWMAPOS != 0);
bd6639fd 2816
89cd7b59 2817 if (fGenerate == true || VERUS_MINTBLOCKS)
10214558 2818 {
89cd7b59
MT
2819 mapArgs["-gen"] = "1";
2820
6e62f837 2821 if (VERUS_DEFAULT_ZADDR.size() > 0)
99c94fc3 2822 {
6e62f837 2823 if (defaultSaplingDest == boost::none)
89cd7b59 2824 {
6e62f837 2825 LogPrintf("ERROR: -defaultzaddr parameter is invalid Sapling payment address\n");
2826 fprintf(stderr, "-defaultzaddr parameter is invalid Sapling payment address\n");
89cd7b59
MT
2827 }
2828 else
2829 {
6e62f837 2830 LogPrintf("StakeGuard searching for double stakes on %s\n", VERUS_DEFAULT_ZADDR.c_str());
2831 fprintf(stderr, "StakeGuard searching for double stakes on %s\n", VERUS_DEFAULT_ZADDR.c_str());
89cd7b59 2832 }
99c94fc3 2833 }
2834 }
10214558 2835
e9e70b95 2836 static boost::thread_group* minerThreads = NULL;
28424e9f 2837
e9e70b95 2838 if (nThreads < 0)
2839 nThreads = GetNumCores();
9ae83faa 2840
e9e70b95 2841 if (minerThreads != NULL)
2842 {
2843 minerThreads->interrupt_all();
88d014d0 2844 minerThreads->join_all();
e9e70b95 2845 delete minerThreads;
2846 minerThreads = NULL;
2847 }
135fa24e 2848
afaeb54b 2849 //fprintf(stderr,"nThreads.%d fGenerate.%d\n",(int32_t)nThreads,fGenerate);
5034d1c1 2850 if ( nThreads == 0 && ASSETCHAINS_STAKED )
3a446d9f 2851 nThreads = 1;
5034d1c1 2852
28424e9f 2853 if (!fGenerate)
e9e70b95 2854 return;
135fa24e 2855
e9e70b95 2856 minerThreads = new boost::thread_group();
135fa24e 2857
85c51d62 2858 // add the PBaaS thread when mining or staking
2859 minerThreads->create_thread(boost::bind(&CConnectedChains::SubmissionThreadStub));
2860
135fa24e 2861#ifdef ENABLE_WALLET
b20c38cc 2862 if (VERUS_MINTBLOCKS && pwallet != NULL)
135fa24e 2863 {
2864 minerThreads->create_thread(boost::bind(&VerusStaker, pwallet));
2865 }
2866#endif
2867
e9e70b95 2868 for (int i = 0; i < nThreads; i++) {
8e8b6d70 2869#ifdef ENABLE_WALLET
855714b0 2870 minerThreads->create_thread(boost::bind(&BitcoinMiner_noeq, pwallet));
8e8b6d70 2871#else
855714b0 2872 minerThreads->create_thread(&BitcoinMiner_noeq);
8e8b6d70 2873#endif
e9e70b95 2874 }
8e8b6d70 2875 }
e9e70b95 2876
2cc0a252 2877#endif // ENABLE_MINING
This page took 1.079321 seconds and 4 git commands to generate.