1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or https://www.opensource.org/licenses/mit-license.php .
8 #include "pow/tromp/equi_miner.h"
12 #include "chainparams.h"
13 #include "cc/StakeGuard.h"
14 #include "importcoin.h"
15 #include "consensus/consensus.h"
16 #include "consensus/upgrades.h"
17 #include "consensus/validation.h"
19 #include "crypto/equihash.h"
20 #include "crypto/verus_hash.h"
28 #include "primitives/transaction.h"
31 #include "ui_interface.h"
33 #include "utilmoneystr.h"
34 #include "validationinterface.h"
36 #include "zcash/Address.hpp"
37 #include "transaction_builder.h"
41 #include <boost/thread.hpp>
42 #include <boost/tuple/tuple.hpp>
48 #include "pbaas/pbaas.h"
49 #include "pbaas/notarization.h"
50 #include "pbaas/identity.h"
51 #include "rpc/pbaasrpc.h"
52 #include "transaction_builder.h"
56 //////////////////////////////////////////////////////////////////////////////
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.
72 const CTransaction* ptx;
73 set<uint256> setDependsOn;
77 COrphan(const CTransaction* ptxIn) : ptx(ptxIn), feeRate(0), dPriority(0)
82 uint64_t nLastBlockTx = 0;
83 uint64_t nLastBlockSize = 0;
85 // We want to sort transactions by priority and fee rate, so:
86 typedef boost::tuple<double, CFeeRate, const CTransaction*> TxPriority;
87 class TxPriorityCompare
92 TxPriorityCompare(bool _byFee) : byFee(_byFee) { }
94 bool operator()(const TxPriority& a, const TxPriority& b)
98 if (a.get<1>() == b.get<1>())
99 return a.get<0>() < b.get<0>();
100 return a.get<1>() < b.get<1>();
104 if (a.get<0>() == b.get<0>())
105 return a.get<1>() < b.get<1>();
106 return a.get<0>() < b.get<0>();
111 void UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev)
113 pblock->nTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
115 // Updating time can change work required on testnet:
116 if (consensusParams.nPowAllowMinDifficultyBlocksAfterHeight != boost::none) {
117 pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams);
121 #include "komodo_defs.h"
123 extern CCriticalSection cs_metrics;
124 extern int32_t KOMODO_MININGTHREADS,KOMODO_LONGESTCHAIN,ASSETCHAINS_SEED,IS_KOMODO_NOTARY,USE_EXTERNAL_PUBKEY,KOMODO_CHOSEN_ONE,ASSETCHAIN_INIT,KOMODO_INITDONE,KOMODO_ON_DEMAND,KOMODO_INITDONE,KOMODO_PASSPORT_INITDONE;
125 extern uint64_t ASSETCHAINS_COMMISSION, ASSETCHAINS_STAKED;
126 extern bool VERUS_MINTBLOCKS;
127 extern uint64_t ASSETCHAINS_REWARD[ASSETCHAINS_MAX_ERAS], ASSETCHAINS_TIMELOCKGTE, ASSETCHAINS_NONCEMASK[];
128 extern const char *ASSETCHAINS_ALGORITHMS[];
129 extern int32_t VERUS_MIN_STAKEAGE, ASSETCHAINS_EQUIHASH, ASSETCHAINS_VERUSHASH, ASSETCHAINS_LASTERA, ASSETCHAINS_LWMAPOS, ASSETCHAINS_NONCESHIFT[], ASSETCHAINS_HASHESPERROUND[];
130 extern uint32_t ASSETCHAINS_ALGO;
131 extern char ASSETCHAINS_SYMBOL[KOMODO_ASSETCHAIN_MAXLEN];
132 extern uint160 ASSETCHAINS_CHAINID;
133 extern uint160 VERUS_CHAINID;
134 extern std::string VERUS_CHAINNAME;
135 extern int32_t PBAAS_STARTBLOCK, PBAAS_ENDBLOCK;
136 extern string PBAAS_HOST, PBAAS_USERPASS, ASSETCHAINS_RPCHOST, ASSETCHAINS_RPCCREDENTIALS;;
137 extern int32_t PBAAS_PORT;
138 extern uint16_t ASSETCHAINS_RPCPORT;
139 extern std::string NOTARY_PUBKEY,ASSETCHAINS_OVERRIDE_PUBKEY;
140 void vcalc_sha256(char deprecated[(256 >> 3) * 2 + 1],uint8_t hash[256 >> 3],uint8_t *src,int32_t len);
142 extern uint8_t NOTARY_PUBKEY33[33],ASSETCHAINS_OVERRIDE_PUBKEY33[33];
143 uint32_t Mining_start, Mining_height;
144 int32_t My_notaryid = -1;
145 int32_t komodo_chosennotary(int32_t *notaryidp,int32_t height,uint8_t *pubkey33,uint32_t timestamp);
146 int32_t komodo_pax_opreturn(int32_t height,uint8_t *opret,int32_t maxsize);
147 int32_t komodo_baseid(char *origbase);
148 int32_t komodo_validate_interest(const CTransaction &tx,int32_t txheight,uint32_t nTime,int32_t dispflag);
149 int64_t komodo_block_unlocktime(uint32_t nHeight);
150 uint64_t komodo_commission(const CBlock *block);
151 int32_t komodo_staked(CMutableTransaction &txNew,uint32_t nBits,uint32_t *blocktimep,uint32_t *txtimep,uint256 *utxotxidp,int32_t *utxovoutp,uint64_t *utxovaluep,uint8_t *utxosig);
152 int32_t verus_staked(CBlock *pBlock, CMutableTransaction &txNew, uint32_t &nBits, arith_uint256 &hashResult, std::vector<unsigned char> &utxosig, CTxDestination &rewardDest);
153 int32_t komodo_notaryvin(CMutableTransaction &txNew,uint8_t *notarypub33);
155 void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int &nExtraNonce, bool buildMerkle, uint32_t *pSaveBits)
157 // Update nExtraNonce
158 static uint256 hashPrevBlock;
159 if (hashPrevBlock != pblock->hashPrevBlock)
162 hashPrevBlock = pblock->hashPrevBlock;
168 *pSaveBits = pblock->nBits;
171 int32_t nHeight = pindexPrev->GetHeight() + 1;
173 int solutionVersion = CConstVerusSolutionVector::activationHeight.ActiveVersion(nHeight);
175 if (solutionVersion >= CConstVerusSolutionVector::activationHeight.ACTIVATE_PBAAS_HEADER)
177 // coinbase should already be finalized in the new version
180 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
181 pblock->SetPrevMMRRoot(ChainMerkleMountainView(chainActive.GetMMR(), pindexPrev->GetHeight()).GetRoot());
182 BlockMMRange mmRange(pblock->BuildBlockMMRTree());
183 BlockMMView mmView(mmRange);
184 pblock->SetBlockMMRRoot(mmView.GetRoot());
185 pblock->AddUpdatePBaaSHeader();
188 UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
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
192 if (solutionVersion >= CConstVerusSolutionVector::activationHeight.ACTIVATE_PBAAS && !pblock->IsVerusPOSBlock())
194 pblock->AddUpdatePBaaSHeader();
197 // clear extra data to allow adding more PBaaS headers
198 pblock->SetExtraData(&dummy, 0);
200 // combine blocks and set compact difficulty if necessary
202 if ((savebits = ConnectedChains.CombineBlocks(*pblock)) && pSaveBits)
204 arith_uint256 ours, merged;
205 ours.SetCompact(pblock->nBits);
206 merged.SetCompact(savebits);
209 *pSaveBits = savebits;
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);
219 std::vector<unsigned char> vENonce(s.begin(), s.end());
221 assert(pblock->ExtraDataLen() >= vENonce.size());
222 pblock->SetExtraData(vENonce.data(), vENonce.size());
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;
234 pblock->hashMerkleRoot = pblock->BuildMerkleTree();
237 UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
241 extern CWallet *pwalletMain;
243 CPubKey GetSolutionPubKey(const std::vector<std::vector<unsigned char>> &vSolutions, txnouttype txType)
247 if (txType == TX_PUBKEY)
249 pk = CPubKey(vSolutions[0]);
251 else if(txType == TX_PUBKEYHASH)
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);
257 else if (txType == TX_CRYPTOCONDITION)
259 if (vSolutions[0].size() == 33)
261 pk = CPubKey(vSolutions[0]);
263 else if (vSolutions[0].size() == 34 && vSolutions[0][0] == COptCCParams::ADDRTYPE_PK)
265 pk = CPubKey(std::vector<unsigned char>(vSolutions[0].begin() + 1, vSolutions[0].end()));
267 else if (vSolutions[0].size() == 20)
269 LOCK(pwalletMain->cs_wallet);
270 pwalletMain->GetPubKey(CKeyID(uint160(vSolutions[0])), pk);
272 else if (vSolutions[0].size() == 21 && vSolutions[0][0] == COptCCParams::ADDRTYPE_ID)
274 // destination is an identity, see if we can get its first public key
275 std::pair<CIdentityMapKey, CIdentityMapValue> identity;
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())
281 CPubKey pkTmp = boost::apply_visitor<GetPubKeyForPubKey>(GetPubKeyForPubKey(), identity.second.primaryAddresses[0]);
288 LOCK(pwalletMain->cs_wallet);
289 pwalletMain->GetPubKey(CKeyID(GetDestinationID(identity.second.primaryAddresses[0])), pk);
297 CPubKey GetScriptPublicKey(const CScript &scriptPubKey)
300 std::vector<std::vector<unsigned char>> vSolutions;
301 if (Solver(scriptPubKey, typeRet, vSolutions))
303 return GetSolutionPubKey(vSolutions, typeRet);
308 // call a chain that we consider a notary chain, meaning we call its daemon, not the other way around,
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.
311 void ProcessNewImports(const uint160 &sourceChainID, CPBaaSNotarization &lastConfirmed, CUTXORef &lastConfirmedUTXO, uint32_t nHeight)
313 if (CConstVerusSolutionVector::GetVersionByHeight(nHeight) < CActivationHeight::ACTIVATE_PBAAS ||
314 CConstVerusSolutionVector::activationHeight.IsActivationHeight(CActivationHeight::ACTIVATE_PBAAS, nHeight))
319 uint32_t consensusBranchId = CurrentEpochBranchId(nHeight, Params().GetConsensus());
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();
323 uint160 thisChainID = thisChain.GetID();
324 CCurrencyDefinition sourceChain = ConnectedChains.GetCachedCurrency(sourceChainID);
325 if (!sourceChain.IsValid())
327 printf("Unrecognized source chain %s\n", EncodeDestination(CIdentityID(sourceChainID)).c_str());
331 // printf("%s: processing imports for %s\n", __func__, sourceChain.name.c_str());
333 bool isSameChain = thisChain.GetID() == sourceChainID;
335 CChainNotarizationData cnd;
336 if (!(GetNotarizationData(sourceChainID, cnd) && cnd.IsConfirmed()))
338 printf("Cannot get notarization data for currency %s\n", sourceChain.name.c_str());
342 lastConfirmedUTXO = cnd.vtx[cnd.lastConfirmed].first;
343 lastConfirmed = cnd.vtx[cnd.lastConfirmed].second;
345 CTransaction lastImportTx;
347 // we need to find the last unspent import transaction
348 std::vector<CAddressUnspentDbEntry> unspentOutputs;
351 CAddressUnspentDbEntry foundEntry;
352 CCrossChainImport lastCCI;
353 std::vector<std::pair<std::pair<CInputDescriptor, CPartialTransactionProof>, std::vector<CReserveTransfer>>> exports;
359 lastConfirmed.proofRoots.count(sourceChainID) &&
360 GetAddressUnspent(CKeyID(CCrossChainRPCData::GetConditionID(sourceChainID, CCrossChainImport::CurrencySystemImportKey())), CScript::P2IDX, unspentOutputs))
362 // if one spends the prior one, get the one that is not spent
363 for (auto &txidx : unspentOutputs)
366 if (txidx.second.script.IsPayToCryptoCondition(p) &&
368 p.evalCode == EVAL_CROSSCHAIN_IMPORT &&
370 (lastCCI = CCrossChainImport(p.vData[0])).IsValid())
379 lastCCI.sourceSystemHeight < lastConfirmed.notarizationHeight)
381 UniValue params(UniValue::VARR);
383 params.push_back(EncodeDestination(CIdentityID(thisChainID)));
384 params.push_back((int64_t)lastCCI.sourceSystemHeight);
385 params.push_back((int64_t)lastConfirmed.proofRoots[sourceChainID].rootHeight);
387 UniValue result = NullUniValue;
390 if (sourceChainID == thisChain.GetID())
392 UniValue getexports(const UniValue& params, bool fHelp);
393 result = getexports(params, false);
397 result = find_value(RPCCallRoot("getexports", params), "result");
399 } catch (exception e)
401 printf("Could not get latest export from external chain %s\n", uni_get_str(params[0]).c_str());
405 // now, we should have a list of exports to import in order
406 if (!result.isArray() || !result.size())
410 bool foundCurrent = false;
411 for (int i = 0; i < result.size(); i++)
413 uint256 exportTxId = uint256S(uni_get_str(find_value(result[i], "txid")));
414 if (!foundCurrent && !lastCCI.exportTxId.IsNull())
416 // when we find our export, take the next
417 if (exportTxId == lastCCI.exportTxId)
424 // create one import at a time
425 uint32_t notarizationHeight = uni_get_int64(find_value(result[i], "height"));
426 int32_t exportTxOutNum = uni_get_int(find_value(result[i], "txoutnum"));
427 CPartialTransactionProof txProof = CPartialTransactionProof(find_value(result[i], "partialtransactionproof"));
428 UniValue transferArrUni = find_value(result[i], "transfers");
429 if (!notarizationHeight ||
430 exportTxId.IsNull() ||
431 exportTxOutNum == -1 ||
432 !transferArrUni.isArray())
434 printf("Invalid export from %s\n", uni_get_str(params[0]).c_str());
438 CTransaction exportTx;
440 auto proofRootIt = lastConfirmed.proofRoots.find(sourceChainID);
442 !(txProof.IsValid() &&
443 !txProof.GetPartialTransaction(exportTx).IsNull() &&
444 txProof.TransactionHash() == exportTxId &&
445 proofRootIt != lastConfirmed.proofRoots.end() &&
446 proofRootIt->second.stateRoot == txProof.CheckPartialTransaction(exportTx) &&
447 exportTx.vout.size() > exportTxOutNum))
449 /* printf("%s: proofRoot: %s, checkPartialRoot: %s, proofheight: %u, ischainproof: %s, blockhash: %s\n",
451 proofRootIt->second.ToUniValue().write(1,2).c_str(),
452 txProof.CheckPartialTransaction(exportTx).GetHex().c_str(),
453 txProof.GetProofHeight(),
454 txProof.IsChainProof() ? "true" : "false",
455 txProof.GetBlockHash().GetHex().c_str()); */
456 printf("Invalid export for %s\n", uni_get_str(params[0]).c_str());
459 else if (isSameChain &&
460 !(myGetTransaction(exportTxId, exportTx, blkHash) &&
461 exportTx.vout.size() > exportTxOutNum))
463 printf("Invalid export msg2 from %s\n", uni_get_str(params[0]).c_str());
468 CCrossChainExport ccx(exportTx.vout[exportTxOutNum].scriptPubKey);
471 printf("Invalid export msg3 from %s\n", uni_get_str(params[0]).c_str());
474 if (ccx.IsChainDefinition())
479 std::pair<std::pair<CInputDescriptor, CPartialTransactionProof>, std::vector<CReserveTransfer>> oneExport =
480 std::make_pair(std::make_pair(CInputDescriptor(exportTx.vout[exportTxOutNum].scriptPubKey,
481 exportTx.vout[exportTxOutNum].nValue,
482 CTxIn(exportTxId, exportTxOutNum)),
484 std::vector<CReserveTransfer>());
485 for (int j = 0; j < transferArrUni.size(); j++)
487 //printf("%s: onetransfer: %s\n", __func__, transferArrUni[j].write(1,2).c_str());
488 oneExport.second.push_back(CReserveTransfer(transferArrUni[j]));
489 if (!oneExport.second.back().IsValid())
491 printf("Invalid reserve transfers in export from %s\n", sourceChain.name.c_str());
495 exports.push_back(oneExport);
498 std::map<uint160, std::vector<std::pair<int, CTransaction>>> newImports;
499 ConnectedChains.CreateLatestImports(sourceChain, lastConfirmedUTXO, exports, newImports);
501 else if (isSameChain)
503 ConnectedChains.ProcessLocalImports();
508 printf("Could not get prior import for currency %s\n", sourceChain.name.c_str());
514 bool CheckNotaryConnection(const CRPCChainData ¬arySystem)
516 // ensure we have connection parameters, or we fail
517 if (notarySystem.rpcHost == "" || notarySystem.rpcUserPass == "" || !notarySystem.rpcPort)
524 bool CallNotary(const CRPCChainData ¬arySystem, std::string command, const UniValue ¶ms, UniValue &result, UniValue &error)
526 // ensure we have connection parameters, or we fail
527 if (!CheckNotaryConnection(notarySystem))
534 UniValue rpcResult = RPCCall(command, params, notarySystem.rpcUserPass, notarySystem.rpcPort, notarySystem.rpcHost);
535 result = find_value(rpcResult, "result");
536 error = find_value(rpcResult, "error");
537 } catch (std::exception e)
539 error = strprintf("Failed to connect to %s chain, error: %s\n", notarySystem.chainDefinition.name.c_str(), e.what());
541 return error.isNull();
544 // get initial currency state from the notary system specified
545 bool GetBlockOneLaunchNotarization(const CRPCChainData ¬arySystem,
546 const uint160 ¤cyID,
547 CCurrencyDefinition &curDef,
548 CPBaaSNotarization &launchNotarization,
549 CPBaaSNotarization ¬aryNotarization,
550 std::pair<CUTXORef, CPartialTransactionProof> ¬arizationOutputProof,
551 std::pair<CUTXORef, CPartialTransactionProof> &exportOutputProof,
552 std::vector<CReserveTransfer> &exportTransfers)
554 UniValue result, error;
557 UniValue params(UniValue::VARR);
558 params.push_back(EncodeDestination(CIdentityID(currencyID)));
560 // VRSC and VRSCTEST do not start with a notary chain
561 if (!IsVerusActive() && ConnectedChains.IsNotaryAvailable())
563 // we are starting a PBaaS chain. We only assume that our chain definition and the first notary chain, if there is one, are setup
564 // in ConnectedChains. All other currencies and identities necessary to start have not been populated and must be in block 1 by
565 // getting the information from the notary chain.
566 if (CallNotary(notarySystem, "getlaunchinfo", params, result, error))
568 CCurrencyDefinition currency(find_value(result, "currencydefinition"));
569 CPBaaSNotarization notarization(find_value(result, "launchnotarization"));
570 notaryNotarization = CPBaaSNotarization(find_value(result, "notarynotarization"));
571 CPartialTransactionProof notarizationProof(find_value(result, "notarizationproof"));
572 CUTXORef notarizationUtxo(uint256S(uni_get_str(find_value(result, "notarizationtxid"))), uni_get_int(find_value(result, "notarizationvoutnum")));
574 CPartialTransactionProof exportProof(find_value(result, "exportproof"));
575 UniValue exportTransfersUni = find_value(result, "exportransfers");
578 if (exportTransfersUni.isArray() && exportTransfersUni.size())
580 for (int i = 0; i < exportTransfersUni.size(); i++)
582 CReserveTransfer oneTransfer(exportTransfersUni[i]);
583 if (!oneTransfer.IsValid())
589 exportTransfers.push_back(oneTransfer);
593 CUTXORef exportUtxo(uint256S(uni_get_str(find_value(result, "exporttxid"))), uni_get_int(find_value(result, "exportvoutnum")));
596 !currency.IsValid() ||
597 !notarization.IsValid() ||
598 !notarizationProof.IsValid() ||
599 !notaryNotarization.IsValid())
601 LogPrintf("%s: invalid launch notarization for currency %s\n", __func__, EncodeDestination(CIdentityID(currencyID)).c_str());
602 printf("%s: invalid launch notarization for currency %s\ncurrencydefinition: %s\nnotarization: %s\ntransactionproof: %s\n",
604 EncodeDestination(CIdentityID(currencyID)).c_str(),
605 currency.ToUniValue().write(1,2).c_str(),
606 notarization.ToUniValue().write(1,2).c_str(),
607 notarizationProof.ToUniValue().write(1,2).c_str());
611 //printf("%s: proofroot: %s\n", __func__, latestProofRoot.ToUniValue().write(1,2).c_str());
613 launchNotarization = notarization;
614 launchNotarization.proofRoots = notaryNotarization.proofRoots;
615 notaryNotarization.proofRoots[ASSETCHAINS_CHAINID] = CProofRoot::GetProofRoot(0);
616 notaryNotarization.currencyStates[ASSETCHAINS_CHAINID] = launchNotarization.currencyState;
617 notarizationOutputProof = std::make_pair(notarizationUtxo, notarizationProof);
618 exportOutputProof = std::make_pair(exportUtxo, exportProof);
624 LogPrintf("%s: error calling notary chain %s\n", __func__, error.write(1,2).c_str());
625 printf("%s: error calling notary chain %s\n", __func__, error.write(1,2).c_str());
631 bool DecodeOneExport(const UniValue obj, CCrossChainExport &ccx,
632 std::pair<std::pair<CInputDescriptor, CPartialTransactionProof>, std::vector<CReserveTransfer>> &oneExport)
634 uint32_t exportHeight = uni_get_int64(find_value(obj, "height"));
635 uint256 txId = uint256S(uni_get_str(find_value(obj, "txid")));
636 uint32_t outNum = uni_get_int(find_value(obj, "txoutnum"));
637 ccx = CCrossChainExport(find_value(obj, "exportinfo"));
640 LogPrintf("%s: invalid launch export from notary chain\n", __func__);
641 printf("%s: invalid launch export from notary chain\n", __func__);
644 CPartialTransactionProof partialTxProof(find_value(obj, "partialtransactionproof"));
645 CTransaction exportTx;
647 CScript outputScript;
650 // TODO: HARDENING - check the proof against the actual notarization here
651 if (!partialTxProof.IsValid() ||
652 partialTxProof.GetPartialTransaction(exportTx).IsNull() ||
653 partialTxProof.TransactionHash() != txId ||
654 exportTx.vout.size() <= outNum ||
655 !exportTx.vout[outNum].scriptPubKey.IsPayToCryptoCondition(p) ||
657 !p.evalCode == EVAL_CROSSCHAIN_EXPORT ||
658 (outputValue = exportTx.vout[outNum].nValue) == -1)
660 //UniValue jsonTxOut(UniValue::VOBJ);
661 //TxToUniv(exportTx, uint256(), jsonTxOut);
662 //printf("%s: proofTxRoot:%s\npartialTx: %s\n", __func__,
663 // partialTxProof.GetPartialTransaction(exportTx).GetHex().c_str(),
664 // jsonTxOut.write(1,2).c_str());
665 LogPrintf("%s: invalid partial transaction proof from notary chain\n", __func__);
666 printf("%s: invalid partial transaction proof from notary chain\n", __func__);
670 UniValue transfers = find_value(obj, "transfers");
671 std::vector<CReserveTransfer> reserveTransfers;
672 if (transfers.isArray() && transfers.size())
674 for (int i = 0; i < transfers.size(); i++)
676 CReserveTransfer rt(transfers[i]);
679 reserveTransfers.push_back(rt);
684 oneExport.first.first = CInputDescriptor(outputScript, outputValue, CTxIn(txId, outNum));
685 oneExport.first.second = partialTxProof;
686 oneExport.second = reserveTransfers;
690 // get initial currency state from the notary system specified
691 bool GetBlockOneImports(const CRPCChainData ¬arySystem, const CPBaaSNotarization &launchNotarization, std::map<uint160, std::vector<std::pair<std::pair<CInputDescriptor, CPartialTransactionProof>, std::vector<CReserveTransfer>>>> &exports)
693 UniValue result, error;
695 UniValue params(UniValue::VARR);
696 params.push_back(EncodeDestination(CIdentityID(ASSETCHAINS_CHAINID)));
697 params.push_back((int)0);
698 if (launchNotarization.proofRoots.count(ConnectedChains.ThisChain().launchSystemID))
700 params.push_back((int64_t)launchNotarization.proofRoots.find(ConnectedChains.ThisChain().launchSystemID)->second.rootHeight);
703 // VRSC and VRSCTEST do not start with a notary chain
704 if (!IsVerusActive() && ConnectedChains.IsNotaryAvailable())
706 // we are starting a PBaaS chain. We only assume that our chain definition and the first notary chain, if there is one, are setup
707 // in ConnectedChains. All other currencies and identities necessary to start have not been populated and must be in block 1 by
708 // getting the information from the notary chain.
709 if (CallNotary(notarySystem, "getexports", params, result, error) &&
713 // we now have an array of exports that we should import into this system
714 // load up to the last launch export on each currency
715 for (int i = 0; i < result.size(); i++)
717 CCrossChainExport ccx;
718 std::pair<std::pair<CInputDescriptor, CPartialTransactionProof>, std::vector<CReserveTransfer>> oneExport;
719 if (DecodeOneExport(result[i], ccx, oneExport))
721 exports[ccx.destCurrencyID].push_back(oneExport);
735 // This is called with either the initial currency, or the gateway converter currency
736 // to setup an import/export thread, transfer the initial issuance of native currency
737 // into the converter, and notarize the state of each currency.
738 // All outputs to do those things are added to the outputs vector.
739 bool AddOneCurrencyImport(const CCurrencyDefinition &newCurrency,
740 const CPBaaSNotarization &lastNotarization,
741 const std::pair<CUTXORef, CPartialTransactionProof> *pLaunchProof,
742 const std::pair<CUTXORef, CPartialTransactionProof> *pFirstExport,
743 const std::vector<CReserveTransfer> &_exportTransfers,
744 CCurrencyValueMap &gatewayDeposits,
745 std::vector<CTxOut> &outputs,
746 CCurrencyValueMap &additionalFees)
748 uint160 newCurID = newCurrency.GetID();
749 CPBaaSNotarization newNotarization = lastNotarization;
750 newNotarization.prevNotarization = CUTXORef();
751 newNotarization.SetBlockOneNotarization();
753 // each currency will get:
754 // * one currency definition output
755 // * notarization of latest currency state
760 // make a currency definition
761 cp = CCinit(&CC, EVAL_CURRENCY_DEFINITION);
762 std::vector<CTxDestination> dests({CPubKey(ParseHex(CC.CChexstr))});
763 outputs.push_back(CTxOut(0, MakeMofNCCScript(CConditionObj<CCurrencyDefinition>(EVAL_CURRENCY_DEFINITION, dests, 1, &newCurrency))));
765 // import / export capable currencies include the main currency, fractional currencies on any system,
766 // gateway currencies. the launch system, and non-token currencies. they also get an import / export thread
767 if (ConnectedChains.ThisChain().launchSystemID == newCurID ||
768 (newCurrency.systemID == ASSETCHAINS_CHAINID &&
769 (newCurrency.IsFractional() ||
770 newCurrency.systemID == newCurID ||
771 (newCurrency.IsGateway() && newCurrency.GetID() == newCurrency.gatewayID))))
773 uint160 firstNotaryID = ConnectedChains.FirstNotaryChain().chainDefinition.GetID();
775 // first, put evidence of the notarization pre-import
776 int notarizationIdx = -1;
779 // add notarization before other outputs
780 cp = CCinit(&CC, EVAL_NOTARY_EVIDENCE);
781 dests = std::vector<CTxDestination>({CPubKey(ParseHex(CC.CChexstr))});
782 // now, we need to put the launch notarization evidence, followed by the import outputs
783 CNotaryEvidence evidence = CNotaryEvidence(ConnectedChains.FirstNotaryChain().chainDefinition.GetID(),
786 std::map<CIdentityID, CIdentitySignature>(),
787 std::vector<CPartialTransactionProof>({pLaunchProof->second}),
788 CNotaryEvidence::TYPE_PARTIAL_TXPROOF);
789 notarizationIdx = outputs.size();
790 outputs.push_back(CTxOut(0, MakeMofNCCScript(CConditionObj<CNotaryEvidence>(EVAL_NOTARY_EVIDENCE, dests, 1, &evidence))));
793 // create the import thread output
794 cp = CCinit(&CC, EVAL_CROSSCHAIN_IMPORT);
795 if (newCurrency.proofProtocol == newCurrency.PROOF_CHAINID)
797 dests = std::vector<CTxDestination>({CIdentityID(newCurID)});
801 dests = std::vector<CTxDestination>({CPubKey(ParseHex(CC.CChexstr))});
804 if ((newCurrency.systemID == ASSETCHAINS_CHAINID) && firstNotaryID == newCurrency.launchSystemID)
806 uint256 transferHash;
807 std::vector<CTxOut> importOutputs;
808 CCurrencyValueMap importedCurrency, gatewayDepositsUsed, spentCurrencyOut;
810 CPBaaSNotarization tempLastNotarization = lastNotarization;
811 tempLastNotarization.currencyState.SetLaunchCompleteMarker(false);
813 std::vector<CReserveTransfer> exportTransfers(_exportTransfers);
814 if (!tempLastNotarization.NextNotarizationInfo(ConnectedChains.FirstNotaryChain().chainDefinition,
826 LogPrintf("%s: invalid import for currency %s on system %s\n", __func__,
827 newCurrency.name.c_str(),
828 EncodeDestination(CIdentityID(ASSETCHAINS_CHAINID)).c_str());
832 // if fees are not converted, we will pay out original fees,
833 // less liquidity fees, which go into the currency reserves
835 CCurrencyValueMap liquidityFees;
836 CCurrencyValueMap originalFees =
837 newNotarization.currencyState.CalculateConvertedFees(
838 newNotarization.currencyState.viaConversionPrice,
839 newNotarization.currencyState.viaConversionPrice,
847 additionalFees += (originalFees - liquidityFees);
850 newNotarization.SetBlockOneNotarization();
852 // display import outputs
853 CMutableTransaction debugTxOut;
854 debugTxOut.vout = outputs;
855 debugTxOut.vout.insert(debugTxOut.vout.end(), importOutputs.begin(), importOutputs.end());
856 UniValue jsonTxOut(UniValue::VOBJ);
857 TxToUniv(debugTxOut, uint256(), jsonTxOut);
858 printf("%s: launch outputs: %s\nlast notarization: %s\nnew notarization: %s\n", __func__,
859 jsonTxOut.write(1,2).c_str(),
860 lastNotarization.ToUniValue().write(1,2).c_str(),
861 newNotarization.ToUniValue().write(1,2).c_str());
863 newNotarization.prevNotarization = CUTXORef();
864 newNotarization.prevHeight = 0;
866 // get the first export for launch from the notary chain
867 CTransaction firstExportTx;
868 if (!pFirstExport || !(pFirstExport->second.IsValid() && !pFirstExport->second.GetPartialTransaction(firstExportTx).IsNull()))
870 LogPrintf("%s: invalid first export for PBaaS or converter launch\n");
874 // get the export for this import
875 CCrossChainExport ccx(firstExportTx.vout[pFirstExport->first.n].scriptPubKey);
878 LogPrintf("%s: invalid export output for PBaaS or converter launch\n");
882 // create an import based on launch conditions that covers all pre-allocations and uses the initial notarization.
883 // generate outputs, then fill in numOutputs
884 CCrossChainImport cci = CCrossChainImport(newCurrency.launchSystemID,
885 newNotarization.notarizationHeight,
890 ccx.hashReserveTransfers,
891 pFirstExport->first.hash,
892 pFirstExport->first.n);
893 cci.SetSameChain(newCurrency.launchSystemID == ASSETCHAINS_CHAINID);
895 cci.SetInitialLaunchImport();
897 // anything we had before plus anything imported and minus all spent currency out should
898 // be all reserve deposits remaining under control of this currency
900 /* printf("%s: ccx.totalAmounts: %s\ngatewayDepositsUsed: %s\nadditionalFees: %s\noriginalFees: %s\n",
902 ccx.totalAmounts.ToUniValue().write(1,2).c_str(),
903 gatewayDepositsUsed.ToUniValue().write(1,2).c_str(),
904 additionalFees.ToUniValue().write(1,2).c_str(),
905 originalFees.ToUniValue().write(1,2).c_str()); */
907 // to determine left over reserves for deposit, consider imported and emitted as the same
908 gatewayDeposits = CCurrencyValueMap(lastNotarization.currencyState.currencies, lastNotarization.currencyState.reserveIn);
909 if (!newCurrency.IsFractional())
911 gatewayDeposits += originalFees;
913 gatewayDeposits.valueMap[newCurID] += newNotarization.currencyState.primaryCurrencyOut;
915 printf("importedcurrency %s\nspentcurrencyout %s\ngatewaydeposits %s\n",
916 importedCurrency.ToUniValue().write(1,2).c_str(),
917 spentCurrencyOut.ToUniValue().write(1,2).c_str(),
918 gatewayDeposits.ToUniValue().write(1,2).c_str());
920 gatewayDeposits = (gatewayDeposits - spentCurrencyOut).CanonicalMap();
922 printf("importedcurrency %s\nspentcurrencyout %s\nnewgatewaydeposits %s\n",
923 importedCurrency.ToUniValue().write(1,2).c_str(),
924 spentCurrencyOut.ToUniValue().write(1,2).c_str(),
925 gatewayDeposits.ToUniValue().write(1,2).c_str());
927 // add the reserve deposit output with all deposits for this currency for the new chain
928 if (gatewayDeposits.valueMap.size())
930 CCcontract_info *depositCp;
931 CCcontract_info depositCC;
933 // create the import thread output
934 depositCp = CCinit(&depositCC, EVAL_RESERVE_DEPOSIT);
935 std::vector<CTxDestination> depositDests({CPubKey(ParseHex(depositCC.CChexstr))});
936 CReserveDeposit rd(newCurID, gatewayDeposits);
937 CAmount nativeOut = gatewayDeposits.valueMap.count(ASSETCHAINS_CHAINID) ? gatewayDeposits.valueMap[ASSETCHAINS_CHAINID] : 0;
938 outputs.push_back(CTxOut(nativeOut, MakeMofNCCScript(CConditionObj<CReserveDeposit>(EVAL_RESERVE_DEPOSIT, depositDests, 1, &rd))));
941 if (newCurrency.notaries.size())
943 // notaries all get an even share of 10% of the launch fee in the launch currency to use for notarizing
944 // they may also get pre-allocations
945 uint160 notaryNativeID = ConnectedChains.FirstNotaryChain().chainDefinition.GetID();
946 CAmount notaryFeeShare = ConnectedChains.FirstNotaryChain().chainDefinition.currencyRegistrationFee / 10;
947 additionalFees -= CCurrencyValueMap(std::vector<uint160>({notaryNativeID}), std::vector<int64_t>({notaryFeeShare}));
948 CAmount oneNotaryShare = notaryFeeShare / newCurrency.notaries.size();
949 CAmount notaryModExtra = notaryFeeShare % newCurrency.notaries.size();
950 for (auto &oneNotary : newCurrency.notaries)
952 CTokenOutput to(notaryNativeID, oneNotaryShare);
955 to.reserveValues.valueMap[notaryNativeID]++;
958 outputs.push_back(CTxOut(0, MakeMofNCCScript(CConditionObj<CTokenOutput>(EVAL_RESERVE_OUTPUT,
959 std::vector<CTxDestination>({CIdentityID(oneNotary)}),
965 cci.numOutputs = importOutputs.size();
967 // now add the import itself
968 outputs.push_back(CTxOut(0, MakeMofNCCScript(CConditionObj<CCrossChainImport>(EVAL_CROSSCHAIN_IMPORT, dests, 1, &cci))));
970 // add notarization before other outputs
971 cp = CCinit(&CC, EVAL_EARNEDNOTARIZATION);
972 if (newCurID == ASSETCHAINS_CHAINID &&
973 newCurrency.notarizationProtocol == newCurrency.NOTARIZATION_NOTARY_CHAINID)
975 dests = std::vector<CTxDestination>({CIdentityID(newCurID)});
979 dests = std::vector<CTxDestination>({CPubKey(ParseHex(CC.CChexstr))});
981 outputs.push_back(CTxOut(0, MakeMofNCCScript(CConditionObj<CPBaaSNotarization>(EVAL_EARNEDNOTARIZATION, dests, 1, &newNotarization))));
983 // add export before other outputs
984 cp = CCinit(&CC, EVAL_NOTARY_EVIDENCE);
985 dests = std::vector<CTxDestination>({CPubKey(ParseHex(CC.CChexstr))});
986 // now, we need to put the export evidence, followed by the import outputs
987 CNotaryEvidence evidence = CNotaryEvidence(cci.sourceSystemID,
988 CUTXORef(uint256(), notarizationIdx),
990 std::map<CIdentityID, CIdentitySignature>(),
991 std::vector<CPartialTransactionProof>({pFirstExport->second}),
992 CNotaryEvidence::TYPE_PARTIAL_TXPROOF);
993 outputs.push_back(CTxOut(0, MakeMofNCCScript(CConditionObj<CNotaryEvidence>(EVAL_NOTARY_EVIDENCE, dests, 1, &evidence))));
995 outputs.insert(outputs.end(), importOutputs.begin(), importOutputs.end());
999 // begin with an empty import for this currency
1000 // create an import based on launch conditions that covers all pre-allocations and uses the initial notarization
1002 // if the currency is new and owned by this chain, its registration requires the fee, paid in its launch chain currency
1003 // otherwise, it is being imported from another chain and requires an import fee
1004 CCurrencyValueMap registrationFees;
1005 CAmount registrationAmount = 0;
1006 if (newCurrency.systemID == ASSETCHAINS_CHAINID)
1008 if (newCurrency.launchSystemID != ASSETCHAINS_CHAINID)
1010 registrationFees = CCurrencyValueMap(std::vector<uint160>({newCurrency.launchSystemID}),
1011 std::vector<int64_t>({ConnectedChains.FirstNotaryChain().chainDefinition.currencyRegistrationFee}));
1015 registrationAmount = ConnectedChains.ThisChain().currencyRegistrationFee;
1020 registrationAmount = 0;
1023 CCrossChainImport cci = CCrossChainImport(ConnectedChains.ThisChain().launchSystemID,
1026 CCurrencyValueMap());
1027 cci.SetDefinitionImport(true);
1028 outputs.push_back(CTxOut(0, MakeMofNCCScript(CConditionObj<CCrossChainImport>(EVAL_CROSSCHAIN_IMPORT, dests, 1, &cci))));
1030 // add notarization before other outputs
1031 cp = CCinit(&CC, EVAL_EARNEDNOTARIZATION);
1032 if (newCurID == ASSETCHAINS_CHAINID &&
1033 newCurrency.notarizationProtocol == newCurrency.NOTARIZATION_NOTARY_CHAINID)
1035 dests = std::vector<CTxDestination>({CIdentityID(newCurID)});
1039 dests = std::vector<CTxDestination>({CPubKey(ParseHex(CC.CChexstr))});
1041 outputs.push_back(CTxOut(0, MakeMofNCCScript(CConditionObj<CPBaaSNotarization>(EVAL_EARNEDNOTARIZATION, dests, 1, &newNotarization))));
1043 CReserveTransactionDescriptor rtxd;
1044 CCoinbaseCurrencyState importState = newNotarization.currencyState;
1045 importState.RevertReservesAndSupply();
1046 CCurrencyValueMap importedCurrency;
1047 CCurrencyValueMap gatewayDepositsIn;
1048 CCurrencyValueMap spentCurrencyOut;
1049 CCoinbaseCurrencyState newCurrencyState;
1050 if (!rtxd.AddReserveTransferImportOutputs(ConnectedChains.FirstNotaryChain().chainDefinition,
1051 ConnectedChains.ThisChain(),
1054 std::vector<CReserveTransfer>(),
1061 LogPrintf("Invalid starting currency import for %s\n", ConnectedChains.ThisChain().name.c_str());
1062 printf("Invalid starting currency import for %s\n", ConnectedChains.ThisChain().name.c_str());
1067 cp = CCinit(&CC, EVAL_CROSSCHAIN_EXPORT);
1068 dests = std::vector<CTxDestination>({CPubKey(ParseHex(CC.CChexstr))});
1069 CCrossChainExport ccx;
1071 ccx = CCrossChainExport(ASSETCHAINS_CHAINID, 1, 1, newCurrency.systemID, newCurID, 0, CCurrencyValueMap(), CCurrencyValueMap(), uint256());
1072 outputs.push_back(CTxOut(0, MakeMofNCCScript(CConditionObj<CCrossChainExport>(EVAL_CROSSCHAIN_EXPORT, dests, 1, &ccx))));
1076 cp = CCinit(&CC, EVAL_EARNEDNOTARIZATION);
1077 if (newCurID == ASSETCHAINS_CHAINID &&
1078 newCurrency.notarizationProtocol == newCurrency.NOTARIZATION_NOTARY_CHAINID)
1080 dests = std::vector<CTxDestination>({CIdentityID(newCurID)});
1084 dests = std::vector<CTxDestination>({CPubKey(ParseHex(CC.CChexstr))});
1086 // we notarize our notary chain here, not ourselves
1087 if (newNotarization.currencyID == ASSETCHAINS_CHAINID)
1089 if (!newNotarization.SetMirror())
1091 LogPrintf("Cannot mirror our notarization from notary chain\n");
1092 printf("Cannot mirror our notarization from notary chain\n");
1096 newNotarization.SetBlockOneNotarization();
1097 outputs.push_back(CTxOut(0, MakeMofNCCScript(CConditionObj<CPBaaSNotarization>(EVAL_EARNEDNOTARIZATION, dests, 1, &newNotarization))));
1102 // create all special PBaaS outputs for block 1
1103 bool MakeBlockOneCoinbaseOutputs(std::vector<CTxOut> &outputs,
1104 CPBaaSNotarization &launchNotarization,
1105 CCurrencyValueMap &additionalFees,
1106 const Consensus::Params &consensusParams)
1108 uint160 thisChainID = ConnectedChains.ThisChain().GetID();
1109 CCurrencyDefinition &thisChain = ConnectedChains.ThisChain();
1110 uint160 firstNotaryID = ConnectedChains.FirstNotaryChain().GetID();
1111 CCoinbaseCurrencyState currencyState;
1112 std::map<uint160, std::vector<std::pair<std::pair<CInputDescriptor, CPartialTransactionProof>, std::vector<CReserveTransfer>>>> blockOneExportImports;
1114 std::pair<CUTXORef, CPartialTransactionProof> launchNotarizationProof;
1115 std::pair<CUTXORef, CPartialTransactionProof> launchExportProof;
1116 std::vector<CReserveTransfer> launchExportTransfers;
1117 CPBaaSNotarization notaryNotarization;
1119 if (!GetBlockOneLaunchNotarization(ConnectedChains.FirstNotaryChain(),
1124 launchNotarizationProof,
1126 launchExportTransfers))
1128 // cannot make block 1 unless we can get the initial currency state from the first notary system
1129 LogPrintf("Cannot find chain on notary system\n");
1130 printf("Cannot find chain on notary system\n");
1134 // we need to have a launch decision to be able to mine any blocks, prior to launch being clear,
1135 // it is not an error. we are just not ready.
1136 if (!launchNotarization.IsLaunchCleared())
1141 if (!launchNotarization.IsLaunchConfirmed())
1143 // we must reach minimums in all currencies to launch
1144 LogPrintf("This chain did not receive the minimum currency contributions and cannot launch. Pre-launch contributions to this chain can be refunded.\n");
1145 printf("This chain did not receive the minimum currency contributions and cannot launch. Pre-launch contributions to this chain can be refunded.\n");
1149 // get initial imports
1150 if (!GetBlockOneImports(ConnectedChains.FirstNotaryChain(), launchNotarization, blockOneExportImports))
1152 // we must reach minimums in all currencies to launch
1153 LogPrintf("Cannot retrieve initial export imports from notary system\n");
1154 printf("Cannot retrieve initial export imports from notary system\n");
1158 // get all currencies/IDs that we will need to retrieve from our notary chain
1159 std::set<uint160> blockOneCurrencies;
1160 std::set<uint160> blockOneIDs = {ASSETCHAINS_CHAINID};
1161 std::set<uint160> convertersToCreate;
1163 CPBaaSNotarization converterNotarization;
1164 std::pair<CUTXORef, CPartialTransactionProof> converterNotarizationProof;
1165 std::pair<CUTXORef, CPartialTransactionProof> converterExportProof;
1166 std::vector<CReserveTransfer> converterExportTransfers;
1167 uint160 converterCurrencyID = thisChain.GatewayConverterID();
1168 CCurrencyDefinition converterCurDef;
1170 // if we have a converter currency, ensure that it also meets requirements for currency launch
1171 if (!thisChain.gatewayConverterName.empty())
1173 if (!GetBlockOneLaunchNotarization(ConnectedChains.FirstNotaryChain(),
1174 converterCurrencyID,
1176 converterNotarization,
1178 converterNotarizationProof,
1179 converterExportProof,
1180 converterExportTransfers))
1182 LogPrintf("Unable to get gateway converter initial state\n");
1183 printf("Unable to get gateway converter initial state\n");
1187 notaryNotarization.currencyStates[converterCurrencyID] = converterNotarization.currencyState;
1189 // both currency and primary gateway must have their pre-launch phase complete before we can make a decision
1191 if (!converterNotarization.IsLaunchCleared())
1196 // we need to have a cleared launch to be able to launch
1197 if (!converterNotarization.IsLaunchConfirmed())
1199 LogPrintf("Primary currency met requirements for launch, but gateway currency converter did not\n");
1200 printf("Primary currency met requirements for launch, but gateway currency converter did not\n");
1204 convertersToCreate.insert(converterCurrencyID);
1207 // Now, add block 1 imports, which provide a foundation of all IDs and currencies needed to launch the
1208 // new system, including ID and currency outputs for notary chain, all currencies we accept for pre-conversion,
1209 // native currency of system launching the chain.
1210 for (auto &oneNotary : ConnectedChains.notarySystems)
1212 // first, we need to have the native notary currency itself and its notaries, if it has them
1213 blockOneCurrencies.insert(oneNotary.first);
1214 blockOneIDs.insert(oneNotary.second.notaryChain.chainDefinition.notaries.begin(), oneNotary.second.notaryChain.chainDefinition.notaries.end());
1217 for (auto &onePrealloc : thisChain.preAllocation)
1219 blockOneIDs.insert(onePrealloc.first);
1222 // get this chain's notaries
1223 auto ¬aryIDs = ConnectedChains.ThisChain().notaries;
1224 blockOneIDs.insert(notaryIDs.begin(), notaryIDs.end());
1226 // now retrieve IDs and currencies
1227 std::map<uint160, std::pair<CCurrencyDefinition,CPBaaSNotarization>> currencyImports;
1228 std::map<uint160, CIdentity> identityImports;
1229 if (!ConnectedChains.GetNotaryCurrencies(ConnectedChains.FirstNotaryChain(), blockOneCurrencies, currencyImports) ||
1230 !ConnectedChains.GetNotaryIDs(ConnectedChains.FirstNotaryChain(), blockOneIDs, identityImports))
1232 // we must reach minimums in all currencies to launch
1233 LogPrintf("Cannot retrieve identity and currency definitions needed to create block 1\n");
1234 printf("Cannot retrieve identity and currency definitions needed to create block 1\n");
1238 if (currencyImports.count(notaryNotarization.currencyID))
1240 currencyImports[notaryNotarization.currencyID].second = notaryNotarization;
1243 // add all imported currency and identity outputs, identity revocaton and recovery IDs must be explicitly imported if needed
1244 for (auto &oneIdentity : identityImports)
1246 outputs.push_back(CTxOut(0, oneIdentity.second.IdentityUpdateOutputScript(1)));
1249 // calculate all issued currency on this chain for both the native and converter currencies,
1250 // which is the only currency that can be considered a gateway deposit at launch. this can
1251 // be used for native currency fee conversions
1252 CCurrencyValueMap gatewayDeposits;
1254 bool success = AddOneCurrencyImport(thisChain,
1256 &launchNotarizationProof,
1258 launchExportTransfers,
1263 // now, the converter
1264 if (success && converterCurDef.IsValid())
1266 // TODO: add a new ID for the converter currency, controlled by the same primary addresses as the
1267 // ID for this chain
1268 CCurrencyValueMap converterDeposits;
1270 success = AddOneCurrencyImport(converterCurDef,
1271 converterNotarization,
1272 &converterNotarizationProof,
1273 &converterExportProof,
1274 converterExportTransfers,
1282 currencyImports.erase(ASSETCHAINS_CHAINID);
1283 currencyImports.erase(converterCurrencyID);
1284 // now, add the rest of necessary currencies
1285 for (auto &oneCurrency : currencyImports)
1287 success = AddOneCurrencyImport(oneCurrency.second.first,
1288 oneCurrency.second.second,
1291 std::vector<CReserveTransfer>(),
1304 CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const std::vector<CTxOut> &minerOutputs, bool isStake)
1306 // instead of one scriptPubKeyIn, we take a vector of them along with relative weight. each is assigned a percentage of the block subsidy and
1307 // mining reward based on its weight relative to the total
1308 if (!(minerOutputs.size() && ConnectedChains.SetLatestMiningOutputs(minerOutputs) || isStake))
1310 fprintf(stderr,"%s: Must have valid miner outputs, including script with valid PK, PKH, or Verus ID destination.\n", __func__);
1314 CTxDestination firstDestination;
1316 if (minerOutputs.size())
1318 int64_t shareCheck = 0;
1319 CTxDestination checkDest;
1320 for (auto &output : minerOutputs)
1322 shareCheck += output.nValue;
1323 if (shareCheck < 0 ||
1324 shareCheck > INT_MAX ||
1325 !ExtractDestination(output.scriptPubKey, checkDest) ||
1326 (checkDest.which() == COptCCParams::ADDRTYPE_INVALID))
1328 fprintf(stderr,"Invalid miner outputs share specifications\n");
1332 ExtractDestination(minerOutputs[0].scriptPubKey, firstDestination);
1336 //fprintf(stderr,"create new block\n");
1338 std::unique_ptr<CBlockTemplate> pblocktemplate(new CBlockTemplate());
1339 if(!pblocktemplate.get())
1341 fprintf(stderr,"pblocktemplate.get() failure\n");
1344 CBlock *pblock = &pblocktemplate->block; // pointer for convenience
1346 pblock->nSolution.resize(Eh200_9.SolutionWidth);
1348 pblock->SetVersionByHeight(chainActive.LastTip()->GetHeight() + 1);
1350 // -regtest only: allow overriding block.nVersion with
1351 // -blockversion=N to test forking scenarios
1352 if (chainparams.MineBlocksOnDemand())
1353 pblock->nVersion = GetArg("-blockversion", pblock->nVersion);
1355 // Add dummy coinbase tx placeholder as first transaction
1356 pblock->vtx.push_back(CTransaction());
1358 pblocktemplate->vTxFees.push_back(-1); // updated at end
1359 pblocktemplate->vTxSigOps.push_back(-1); // updated at end
1361 // Largest block you're willing to create:
1362 unsigned int nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE);
1364 // Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity:
1365 nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize));
1367 unsigned int nMaxIDSize = nBlockMaxSize / 2;
1368 unsigned int nCurrentIDSize = 0;
1370 // How much of the block should be dedicated to high-priority transactions,
1371 // included regardless of the fees they pay
1372 unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", DEFAULT_BLOCK_PRIORITY_SIZE);
1373 nBlockPrioritySize = std::min(nBlockMaxSize, nBlockPrioritySize);
1375 // Minimum block size you want to create; block will be filled with free transactions
1376 // until there are no more or the block reaches this size:
1377 unsigned int nBlockMinSize = GetArg("-blockminsize", DEFAULT_BLOCK_MIN_SIZE);
1378 nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize);
1380 // Collect memory pool transactions into the block
1382 CAmount takenFees = 0;
1384 bool isVerusActive = IsVerusActive();
1385 CCurrencyDefinition &thisChain = ConnectedChains.ThisChain();
1387 std::vector<CAmount> exchangeRate(thisChain.currencies.size());
1389 // we will attempt to spend any cheats we see
1390 CTransaction cheatTx;
1391 boost::optional<CTransaction> cheatSpend;
1394 CBlockIndex* pindexPrev = 0;
1400 const Consensus::Params &consensusParams = chainparams.GetConsensus();
1401 uint32_t consensusBranchId;
1402 int64_t nMedianTimePast = 0;
1403 uint32_t proposedTime = 0;
1406 while (proposedTime == nMedianTimePast)
1413 pindexPrev = chainActive.LastTip();
1414 nHeight = pindexPrev->GetHeight() + 1;
1415 consensusBranchId = CurrentEpochBranchId(nHeight, consensusParams);
1416 nMedianTimePast = pindexPrev->GetMedianTimePast();
1417 proposedTime = GetAdjustedTime();
1419 if (proposedTime == nMedianTimePast)
1421 boost::this_thread::interruption_point();
1426 CCoinbaseCurrencyState currencyState;
1427 CCoinsViewCache view(pcoinsTip);
1428 uint32_t expired; uint64_t commission;
1430 SaplingMerkleTree sapling_tree;
1433 LOCK2(cs_main, mempool.cs);
1434 if (pindexPrev != chainActive.LastTip())
1440 pblock->nTime = GetAdjustedTime();
1442 currencyState = ConnectedChains.GetCurrencyState(nHeight);
1444 if (!(view.GetSaplingAnchorAt(view.GetBestAnchor(SAPLING), sapling_tree)))
1446 LogPrintf("%s: failed to get Sapling anchor\n", __func__);
1451 // Priority order to process transactions
1452 list<COrphan> vOrphan; // list memory doesn't move
1453 map<uint256, vector<COrphan*> > mapDependers;
1454 bool fPrintPriority = GetBoolArg("-printpriority", false);
1456 // This vector will be sorted into a priority queue:
1457 vector<TxPriority> vecPriority;
1458 vecPriority.reserve(mempool.mapTx.size() + 1);
1463 // check if we should add cheat transaction
1466 int cheatHeight = nHeight - COINBASE_MATURITY < 1 ? 1 : nHeight - COINBASE_MATURITY;
1467 if (defaultSaplingDest &&
1468 chainActive.Height() > 100 &&
1469 (ppast = chainActive[cheatHeight]) &&
1470 ppast->IsVerusPOSBlock() &&
1471 cheatList.IsHeightOrGreaterInList(cheatHeight))
1473 // get the block and see if there is a cheat candidate for the stake tx
1475 if (!(fHavePruned && !(ppast->nStatus & BLOCK_HAVE_DATA) && ppast->nTx > 0) && ReadBlockFromDisk(b, ppast, chainparams.GetConsensus(), 1))
1477 CTransaction &stakeTx = b.vtx[b.vtx.size() - 1];
1479 if (cheatList.IsCheatInList(stakeTx, &cheatTx))
1481 // make and sign the cheat transaction to spend the coinbase to our address
1482 CMutableTransaction mtx = CreateNewContextualCMutableTransaction(consensusParams, nHeight);
1485 // get the first vout with value
1486 for (voutNum = 0; voutNum < b.vtx[0].vout.size(); voutNum++)
1488 if (b.vtx[0].vout[voutNum].nValue > 0)
1492 // send to the same pub key as the destination of this block reward
1493 if (MakeCheatEvidence(mtx, b.vtx[0], voutNum, cheatTx))
1495 LOCK(pwalletMain->cs_wallet);
1496 TransactionBuilder tb = TransactionBuilder(consensusParams, nHeight);
1498 cbHash = cb.GetHash();
1500 bool hasInput = false;
1501 for (uint32_t i = 0; i < cb.vout.size(); i++)
1503 // add the spends with the cheat
1504 if (cb.vout[i].nValue > 0)
1506 tb.AddTransparentInput(COutPoint(cbHash,i), cb.vout[0].scriptPubKey, cb.vout[0].nValue);
1513 // this is a send from a t-address to a sapling address, which we don't have an ovk for.
1514 // Instead, generate a common one from the HD seed. This ensures the data is
1515 // recoverable, at least for us, while keeping it logically separate from the ZIP 32
1516 // Sapling key hierarchy, which the user might not be using.
1519 if (pwalletMain->GetHDSeed(seed)) {
1520 ovk = ovkForShieldingFromTaddr(seed);
1522 // send everything to Sapling address
1523 tb.SendChangeTo(defaultSaplingDest.value(), ovk);
1525 tb.AddOpRet(mtx.vout[mtx.vout.size() - 1].scriptPubKey);
1527 TransactionBuilderResult buildResult(tb.Build());
1528 if (!buildResult.IsError() && buildResult.IsTx())
1530 cheatSpend = buildResult.GetTxOrThrow();
1534 LogPrintf("Error building cheat catcher transaction: %s\n", buildResult.GetError().c_str());
1547 cheatTx = cheatSpend.value();
1548 std::list<CTransaction> removed;
1549 mempool.removeConflicts(cheatTx, removed);
1550 printf("Found cheating stake! Adding cheat spend for %.8f at block #%d, coinbase tx\n%s\n",
1551 (double)cb.GetValueOut() / (double)COIN, nHeight, cheatSpend.value().vin[0].prevout.hash.GetHex().c_str());
1553 // add to mem pool and relay
1554 if (myAddtomempool(cheatTx))
1556 RelayTransaction(cheatTx);
1562 // Now start solving the block
1565 uint64_t nBlockSize = 1000; // initial size
1566 uint64_t nBlockTx = 1; // number of transactions - always have a coinbase
1567 uint32_t autoTxSize = 0; // extra transaction overhead that we will add while creating the block
1568 int nBlockSigOps = 100;
1570 // VerusPoP staking transaction data
1571 CMutableTransaction txStaked; // if this is a stake operation, the staking transaction that goes at the end
1572 uint32_t nStakeTxSize = 0; // serialized size of the stake transaction
1574 // if this is not for mining, first determine if we have a right to make a block
1577 uint64_t txfees, utxovalue;
1580 int32_t i, siglen, numsigs, utxovout;
1581 std::vector<unsigned char> utxosig;
1583 txStaked = CreateNewContextualCMutableTransaction(Params().GetConsensus(), nHeight);
1585 if (ASSETCHAINS_LWMAPOS != 0)
1588 arith_uint256 posHash;
1590 siglen = verus_staked(pblock, txStaked, nBitsPOS, posHash, utxosig, firstDestination);
1591 blocktime = GetAdjustedTime();
1599 pblock->nTime = blocktime;
1600 nStakeTxSize = GetSerializeSize(txStaked, SER_NETWORK, PROTOCOL_VERSION);
1601 nBlockSize += nStakeTxSize;
1604 ConnectedChains.AggregateChainTransfers(firstDestination, nHeight);
1606 // Now the coinbase -
1607 // A PBaaS coinbase must have some additional outputs to enable certain chain state and functions to be properly
1608 // validated. All but currency state and the first chain definition are either optional or not valid on non-fractional reserve PBaaS blockchains
1609 // All of these are instant spend outputs that have no maturity wait time and may be spent in the same block.
1611 // 1. (required) currency state - current state of currency supply and optionally reserve, premine, etc. This is primarily a data output to provide
1612 // cross check for coin minting and burning operations, making it efficient to determine up-to-date supply, reserves, and conversions. To provide
1613 // an extra level of supply cross-checking and fast data retrieval, this is part of all PBaaS chains' protocol, not just reserves.
1614 // This output also includes reserve and native amounts for total conversions, less fees, of any conversions between Verus reserve and the
1617 // 2. (block 1 required) chain definition - in order to confirm the amount of coins converted and issued within the possible range, before chain start,
1618 // new PBaaS chains have a zero-amount, unspendable chain definition output.
1620 // 3. (block 1 optional) initial import utxo - for any chain with conversion or pre-conversion, the first coinbase must include an initial import utxo.
1621 // Pre-conversions are handled on the launch chain before the PBaaS chain starts, so they are an additional output, which begins
1622 // 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
1623 // are imported. All pre-converted outputs get their source currency from a thread that starts with this output in block 1.
1625 // 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
1626 // may have one, but currently, they can only be spent with valid exports, which only occur on reserve chains
1628 // 5. (optional) notarization output - in order to ensure that notarization can occur independent of the availability of fungible
1629 // coins on the network, and also that the notarization can provide a spendable finalization output and possible reward
1631 // In addition, each PBaaS block can be mined with optional, fee-generating transactions. Inporting transactions from the reserve chain or sending
1632 // exported transactions to the reserve chain are optional fee-generating steps that would be easy to do when running multiple daemons.
1633 // The types of transactions miners/stakers may facilitate or create for fees are as follows:
1635 // 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
1637 // 2. Imported transactions from the export thread for this PBaaS chain on the Verus blockchain - imported transactions must spend the import utxo
1638 // thread, represent the export from the alternate chain which spends the export output from the prior import transaction, carry a notary proof, and
1639 // include outputs that map to each of its inputs on the source chain. Outputs can include unconverted reserve outputs only on fractional
1640 // reserve chains, pre-converted outputs for any chain with launch conversion, and post launch outputs to be converted on fractional reserve
1641 // chains. Each are handled in the following way:
1642 // a. Unconverted outputs are left as outputs to the intended destination of Verus reserve token and do not pass through the coinbase
1643 // b. Pre-converted outputs require that the import transaction spend the last pre-conversion output starting at block 1 as the source for
1644 // pre-converted currency.
1646 // 3. Zero or more aggregated exports that combine individual cross-chain transactions and reserve transfer outputs for export to the Verus chain.
1648 // 4. Conversion distribution transactions for all native and reserve currency conversions, including reserve transfer outputs without conversion as
1649 // a second step for reserve transfers that have conversion included. Any remaining pre-converted reserve must always remain in a change output
1650 // until it is exhausted
1653 // size of conversion tx
1654 std::vector<CInputDescriptor> conversionInputs;
1656 // if we are a PBaaS chain, first make sure we don't start prematurely, and if
1657 // we should make an earned notarization, make it and set index to non-zero value
1658 int32_t notarizationTxIndex = 0; // index of notarization if it is added
1659 int32_t conversionTxIndex = 0; // index of conversion transaction if it is added
1661 // export transactions can be created here by aggregating all pending transfer requests and either getting 10 or more together, or
1662 // waiting n (10) blocks since the last one. each export must spend the output of the one before it
1663 std::vector<CMutableTransaction> exportTransactions;
1665 // all transaction outputs requesting conversion to another currency (PBaaS fractional reserve only)
1666 // these will be used to calculate conversion price, fees, and generate coinbase conversion output as well as the
1667 // conversion output transaction
1668 std::vector<CTxOut> reserveConversionTo;
1669 std::vector<CTxOut> reserveConversionFrom;
1671 int64_t pbaasTransparentIn = 0;
1672 int64_t pbaasTransparentOut = 0;
1673 //extern int64_t ASSETCHAINS_SUPPLY;
1674 //printf("%lu premine\n", ASSETCHAINS_SUPPLY);
1675 int64_t blockSubsidy = GetBlockSubsidy(nHeight, consensusParams);
1677 uint160 thisChainID = ConnectedChains.ThisChain().GetID();
1680 vector<CInputDescriptor> notarizationInputs;
1682 // used as scratch for making CCs, should be reinitialized each time
1684 CCcontract_info *cp;
1685 std::vector<CTxDestination> dests;
1688 // Create coinbase tx and set up the null input with height
1689 CMutableTransaction coinbaseTx = CreateNewContextualCMutableTransaction(consensusParams, nHeight);
1690 coinbaseTx.vin.push_back(CTxIn(uint256(), (uint32_t)-1, CScript() << nHeight << OP_0));
1692 // we will update amounts and fees later, but convert the guarded output now for validity checking and size estimate
1695 // if there is a specific destination, use it
1696 CTransaction stakeTx(txStaked);
1698 if (ValidateStakeTransaction(stakeTx, p, false))
1700 if (p.Version() < p.VERSION_EXTENDED_STAKE && !p.pk.IsValid())
1702 LogPrintf("CreateNewBlock: invalid public key\n");
1703 fprintf(stderr,"CreateNewBlock: invalid public key\n");
1706 CTxDestination guardedOutputDest = (p.Version() < p.VERSION_EXTENDED_STAKE) ? p.pk : p.delegate;
1707 coinbaseTx.vout.push_back(CTxOut(1, CScript()));
1708 if (!MakeGuardedOutput(1, guardedOutputDest, stakeTx, coinbaseTx.vout.back()))
1710 LogPrintf("CreateNewBlock: failed to make GuardedOutput on staking coinbase\n");
1711 fprintf(stderr,"CreateNewBlock: failed to make GuardedOutput on staking coinbase\n");
1715 if (!coinbaseTx.vout.back().scriptPubKey.IsPayToCryptoCondition(optP) || !optP.IsValid())
1717 MakeGuardedOutput(1, guardedOutputDest, stakeTx, coinbaseTx.vout.back());
1718 LogPrintf("%s: created invalid staking coinbase\n", __func__);
1719 fprintf(stderr,"%s: created invalid staking coinbase\n", __func__);
1725 LogPrintf("CreateNewBlock: invalid stake transaction\n");
1726 fprintf(stderr,"CreateNewBlock: invalid stake transaction\n");
1732 // default outputs for mining and before stake guard or fee calculation
1733 // store the relative weight in the amount output to convert later to a relative portion
1734 // of the reward + fees
1735 coinbaseTx.vout.insert(coinbaseTx.vout.end(), minerOutputs.begin(), minerOutputs.end());
1738 CAmount totalEmission = blockSubsidy;
1739 CCurrencyValueMap additionalFees;
1741 // if we don't have a connected root PBaaS chain, we can't properly check
1742 // and notarize the start block, so we have to pass the notarization and cross chain steps
1743 bool notaryConnected = ConnectedChains.IsNotaryAvailable();
1745 // at block 1 for a PBaaS chain, we validate launch conditions
1746 if (!isVerusActive && nHeight == 1)
1748 CPBaaSNotarization launchNotarization;
1749 if (!ConnectedChains.readyToStart &&
1750 !ConnectedChains.CheckVerusPBaaSAvailable() &&
1751 !ConnectedChains.readyToStart)
1755 if (!MakeBlockOneCoinbaseOutputs(coinbaseTx.vout, launchNotarization, additionalFees, Params().GetConsensus()))
1757 // can't mine block 1 if we are not connected to a notary
1758 printf("%s: cannot create block one coinbase outputs\n", __func__);
1759 LogPrintf("%s: cannot create block one coinbase outputs\n", __func__);
1762 currencyState = launchNotarization.currencyState;
1765 // if we are a notary, notarize
1766 if (nHeight > CPBaaSNotarization::MIN_BLOCKS_BEFORE_NOTARY_FINALIZED && !VERUS_NOTARYID.IsNull())
1768 CValidationState state;
1769 TransactionBuilder notarizationBuilder = TransactionBuilder(consensusParams, nHeight, pwalletMain);
1771 CTransaction notarizationTx;
1772 if (CPBaaSNotarization::ConfirmOrRejectNotarizations(pwalletMain, ConnectedChains.FirstNotaryChain(), state, notarizationBuilder, finalized))
1774 if (!notarizationBuilder.mtx.vin.size())
1776 bool success = false;
1777 CCurrencyValueMap reserveValueOut;
1778 CAmount nativeValueOut;
1779 // get a native currency input capable of paying a fee, and make our notary ID the change address
1780 std::set<std::pair<const CWalletTx *, unsigned int>> setCoinsRet;
1782 LOCK2(cs_main, pwalletMain->cs_wallet);
1783 std::vector<COutput> vCoins;
1784 if (IsVerusActive())
1786 pwalletMain->AvailableCoins(vCoins,
1794 success = pwalletMain->SelectCoinsMinConf(CPBaaSNotarization::DEFAULT_NOTARIZATION_FEE, 0, 0, vCoins, setCoinsRet, nativeValueOut);
1795 notarizationBuilder.SetFee(CPBaaSNotarization::DEFAULT_NOTARIZATION_FEE);
1799 CCurrencyValueMap totalTxFees;
1800 totalTxFees.valueMap[ConnectedChains.FirstNotaryChain().chainDefinition.GetID()] = CPBaaSNotarization::DEFAULT_NOTARIZATION_FEE;
1801 notarizationBuilder.SetReserveFee(totalTxFees);
1802 notarizationBuilder.SetFee(0);
1803 pwalletMain->AvailableReserveCoins(vCoins,
1812 success = pwalletMain->SelectReserveCoinsMinConf(totalTxFees,
1822 for (auto &oneInput : setCoinsRet)
1824 notarizationBuilder.AddTransparentInput(COutPoint(oneInput.first->GetHash(), oneInput.second),
1825 oneInput.first->vout[oneInput.second].scriptPubKey,
1826 oneInput.first->vout[oneInput.second].nValue);
1828 notarizationBuilder.SendChangeTo(CTxDestination(VERUS_NOTARYID));
1832 notarizationBuilder.SetFee(0);
1835 if (notarizationBuilder.mtx.vin.size())
1837 LOCK2(cs_main, mempool.cs);
1838 TransactionBuilderResult buildResult = notarizationBuilder.Build();
1839 if (buildResult.IsTx())
1841 notarizationTx = buildResult.GetTxOrThrow();
1843 UniValue jsonNotaryConfirmations(UniValue::VOBJ);
1844 TxToUniv(notarizationTx, uint256(), jsonNotaryConfirmations);
1845 //printf("%s: (PII) Submitting notarization confirmations:\n%s\n", __func__, jsonNotaryConfirmations.write(1,2).c_str());
1846 LogPrintf("%s: (PII) Submitting notarization confirmations:\n%s\n", __func__, jsonNotaryConfirmations.write(1,2).c_str());
1848 // add to mem pool and relay
1849 if (myAddtomempool(notarizationTx))
1851 RelayTransaction(notarizationTx);
1856 printf("%s: (PII) error adding notary evidence: %s\n", __func__, buildResult.GetError().c_str());
1857 LogPrintf("%s: (PII) error adding notary evidence: %s\n", __func__, buildResult.GetError().c_str());
1863 if (notaryConnected)
1865 // if we should make an earned notarization, do so
1866 if (nHeight != 1 && !(VERUS_NOTARYID.IsNull() && VERUS_DEFAULTID.IsNull() && VERUS_NODEID.IsNull()))
1868 CIdentityID proposer = VERUS_NOTARYID.IsNull() ? (VERUS_DEFAULTID.IsNull() ? VERUS_NODEID : VERUS_DEFAULTID) : VERUS_NOTARYID;
1870 // if we have access to our notary daemon
1871 // create a notarization if we would qualify to do so. add it to the mempool and next block
1872 ChainMerkleMountainView mmv = chainActive.GetMMV();
1873 mmrRoot = mmv.GetRoot();
1874 int32_t confirmedInput = -1;
1875 CTxDestination confirmedDest;
1876 CValidationState state;
1877 CPBaaSNotarization earnedNotarization;
1879 if (CPBaaSNotarization::CreateEarnedNotarization(ConnectedChains.FirstNotaryChain(),
1880 DestinationToTransferDestination(proposer),
1883 earnedNotarization))
1886 CPBaaSNotarization lastImportNotarization;
1887 CUTXORef lastImportNotarizationUTXO;
1889 CPBaaSNotarization::SubmitFinalizedNotarizations(ConnectedChains.FirstNotaryChain(), state);
1890 ProcessNewImports(ConnectedChains.FirstNotaryChain().chainDefinition.GetID(), lastImportNotarization, lastImportNotarizationUTXO, nHeight);
1894 // done calling out, take locks for the rest
1895 LOCK2(cs_main, mempool.cs);
1897 totalEmission = GetBlockSubsidy(nHeight, consensusParams);
1898 blockSubsidy = totalEmission;
1900 // PBaaS chain's block 1 currency state is done by the time we get here,
1901 // including pre-allocations, etc.
1902 if (isVerusActive || nHeight != 1)
1904 currencyState.UpdateWithEmission(totalEmission);
1907 // process any imports from the current chain to itself
1908 ConnectedChains.ProcessLocalImports();
1911 if (!CFeePool::GetCoinbaseFeePool(feePool, nHeight - 1) ||
1912 (!feePool.IsValid() && CConstVerusSolutionVector::GetVersionByHeight(nHeight - 1) >= CActivationHeight::ACTIVATE_PBAAS))
1914 // we should be able to get a valid currency state, if not, fail
1915 LogPrintf("Failure to get fee pool information for blockchain height #%d\n", nHeight - 1);
1916 printf("Failure to get fee pool information for blockchain height #%d\n", nHeight - 1);
1920 uint32_t solutionVersion = CConstVerusSolutionVector::GetVersionByHeight(nHeight);
1921 if (solutionVersion >= CActivationHeight::ACTIVATE_PBAAS && !feePool.IsValid())
1923 // first block with a fee pool, so make it valid and empty
1924 feePool = CFeePool();
1927 // coinbase should have all necessary outputs
1928 uint32_t nCoinbaseSize = GetSerializeSize(coinbaseTx, SER_NETWORK, PROTOCOL_VERSION);
1929 nBlockSize += nCoinbaseSize;
1931 // now create the priority array, including market order reserve transactions, since they can always execute, leave limits for later
1932 bool haveReserveTransactions = false;
1933 uint32_t reserveExchangeLimitSize = 0;
1934 std::vector<CReserveTransactionDescriptor> limitOrders;
1936 // now add transactions from the mem pool to the priority heap
1937 for (CTxMemPool::indexed_transaction_set::iterator mi = mempool.mapTx.begin();
1938 mi != mempool.mapTx.end(); ++mi)
1940 const CTransaction& tx = mi->GetTx();
1941 uint256 hash = tx.GetHash();
1943 int64_t nLockTimeCutoff = (STANDARD_LOCKTIME_VERIFY_FLAGS & LOCKTIME_MEDIAN_TIME_PAST)
1945 : pblock->GetBlockTime();
1947 if (tx.IsCoinBase() || !IsFinalTx(tx, nHeight, nLockTimeCutoff) || IsExpiredTx(tx, nHeight))
1949 //fprintf(stderr,"coinbase.%d finaltx.%d expired.%d\n",tx.IsCoinBase(),IsFinalTx(tx, nHeight, nLockTimeCutoff),IsExpiredTx(tx, nHeight));
1953 if ( ASSETCHAINS_SYMBOL[0] == 0 && komodo_validate_interest(tx,nHeight,(uint32_t)pblock->nTime,0) < 0 )
1955 //fprintf(stderr,"CreateNewBlock: komodo_validate_interest failure nHeight.%d nTime.%u vs locktime.%u\n",nHeight,(uint32_t)pblock->nTime,(uint32_t)tx.nLockTime);
1959 COrphan* porphan = NULL;
1960 double dPriority = 0;
1961 CAmount nTotalIn = 0;
1962 CCurrencyValueMap totalReserveIn;
1963 bool fMissingInputs = false;
1964 CReserveTransactionDescriptor rtxd;
1965 bool isReserve = mempool.IsKnownReserveTransaction(hash, rtxd);
1967 if (tx.IsCoinImport())
1969 CAmount nValueIn = GetCoinImportValue(tx);
1970 nTotalIn += nValueIn;
1971 dPriority += (double)nValueIn * 1000; // flat multiplier
1975 nTotalIn += rtxd.nativeIn;
1976 totalReserveIn = rtxd.ReserveInputMap();
1977 assert(!totalReserveIn.valueMap.count(ASSETCHAINS_CHAINID));
1978 if (rtxd.IsIdentity() && CNameReservation(tx).IsValid())
1980 nCurrentIDSize += GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
1981 if (nCurrentIDSize > nMaxIDSize)
1987 BOOST_FOREACH(const CTxIn& txin, tx.vin)
1989 CAmount nValueIn = 0;
1990 CCurrencyValueMap reserveValueIn;
1992 // Read prev transaction
1993 if (!view.HaveCoins(txin.prevout.hash))
1995 // This should never happen; all transactions in the memory
1996 // pool should connect to either transactions in the chain
1997 // or other transactions in the memory pool.
1998 if (!mempool.mapTx.count(txin.prevout.hash))
2000 LogPrintf("ERROR: mempool transaction missing input\n");
2001 if (fDebug) assert("mempool transaction missing input" == 0);
2002 fMissingInputs = true;
2008 // Has to wait for dependencies
2011 // Use list for automatic deletion
2012 vOrphan.push_back(COrphan(&tx));
2013 porphan = &vOrphan.back();
2015 mapDependers[txin.prevout.hash].push_back(porphan);
2016 porphan->setDependsOn.insert(txin.prevout.hash);
2018 const CTransaction &otx = mempool.mapTx.find(txin.prevout.hash)->GetTx();
2019 // consider reserve outputs and set priority according to their value here as well
2022 totalReserveIn += otx.vout[txin.prevout.n].ReserveOutValue();
2024 nTotalIn += otx.vout[txin.prevout.n].nValue;
2027 const CCoins* coins = view.AccessCoins(txin.prevout.hash);
2032 reserveValueIn = coins->vout[txin.prevout.n].ReserveOutValue();
2035 nValueIn = coins->vout[txin.prevout.n].nValue;
2036 int nConf = nHeight - coins->nHeight;
2038 dPriority += ((double)((reserveValueIn.valueMap.size() ? currencyState.ReserveToNative(reserveValueIn) : 0) + nValueIn)) * nConf;
2042 nTotalIn += nValueIn;
2043 totalReserveIn += reserveValueIn;
2046 nTotalIn += tx.GetShieldedValueIn();
2049 if (fMissingInputs) continue;
2051 // Priority is sum(valuein * age) / modified_txsize
2052 unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
2053 dPriority = tx.ComputePriority(dPriority, nTxSize);
2055 CAmount nDeltaValueIn = nTotalIn + (totalReserveIn.valueMap.size() ? currencyState.ReserveToNative(totalReserveIn) : 0);
2056 CAmount nFeeValueIn = nDeltaValueIn;
2057 mempool.ApplyDeltas(hash, dPriority, nDeltaValueIn);
2059 CAmount nativeEquivalentOut = 0;
2061 // if there is reserve in, or this is a reserveexchange transaction, calculate fee properly
2062 if (isReserve && rtxd.ReserveOutputMap().valueMap.size())
2064 // if this has reserve currency out, convert it to native currency for fee calculation
2065 nativeEquivalentOut = currencyState.ReserveToNative(rtxd.ReserveOutputMap());
2068 CFeeRate feeRate(isReserve ? rtxd.AllFeesAsNative(currencyState) + currencyState.ReserveToNative(rtxd.ReserveConversionFeesMap()) + rtxd.nativeConversionFees :
2069 nFeeValueIn - (tx.GetValueOut() + nativeEquivalentOut), nTxSize);
2073 porphan->dPriority = dPriority;
2074 porphan->feeRate = feeRate;
2077 vecPriority.push_back(TxPriority(dPriority, feeRate, &(mi->GetTx())));
2081 // NOW -- REALLY START TO FILL THE BLOCK
2083 // estimate number of conversions, staking transaction size, and additional coinbase outputs that will be required
2085 int32_t maxPreLimitOrderBlockSize = nBlockMaxSize - std::min(nBlockMaxSize >> 2, reserveExchangeLimitSize);
2088 bool fSortedByFee = (nBlockPrioritySize <= 0);
2090 TxPriorityCompare comparer(fSortedByFee);
2091 std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
2093 std::vector<int> reservePositions;
2095 // now loop and fill the block, leaving space for reserve exchange limit transactions
2096 while (!vecPriority.empty())
2098 // Take highest priority transaction off the priority queue:
2099 double dPriority = vecPriority.front().get<0>();
2100 CFeeRate feeRate = vecPriority.front().get<1>();
2101 const CTransaction& tx = *(vecPriority.front().get<2>());
2103 std::pop_heap(vecPriority.begin(), vecPriority.end(), comparer);
2104 vecPriority.pop_back();
2107 unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
2108 if (nBlockSize + nTxSize >= maxPreLimitOrderBlockSize - autoTxSize) // room for extra autotx
2110 //fprintf(stderr,"nBlockSize %d + %d nTxSize >= %d maxPreLimitOrderBlockSize\n",(int32_t)nBlockSize,(int32_t)nTxSize,(int32_t)maxPreLimitOrderBlockSize);
2114 // Legacy limits on sigOps:
2115 unsigned int nTxSigOps = GetLegacySigOpCount(tx);
2116 if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS-1)
2118 //fprintf(stderr,"A nBlockSigOps %d + %d nTxSigOps >= %d MAX_BLOCK_SIGOPS-1\n",(int32_t)nBlockSigOps,(int32_t)nTxSigOps,(int32_t)MAX_BLOCK_SIGOPS);
2121 // Skip free transactions if we're past the minimum block size:
2122 const uint256& hash = tx.GetHash();
2123 double dPriorityDelta = 0;
2124 CAmount nFeeDelta = 0;
2125 mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta);
2126 if (fSortedByFee && (dPriorityDelta <= 0) && (nFeeDelta <= 0) && (feeRate < ::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize))
2128 //fprintf(stderr,"fee rate skip\n");
2132 // Prioritise by fee once past the priority size or we run out of high-priority
2134 if (!fSortedByFee &&
2135 ((nBlockSize + nTxSize >= nBlockPrioritySize) || !AllowFree(dPriority)))
2137 fSortedByFee = true;
2138 comparer = TxPriorityCompare(fSortedByFee);
2139 std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
2142 if (!view.HaveInputs(tx))
2144 //fprintf(stderr,"dont have inputs\n");
2148 CReserveTransactionDescriptor txDesc;
2149 bool isReserve = mempool.IsKnownReserveTransaction(hash, txDesc);
2151 nTxFees = view.GetValueIn(chainActive.LastTip()->GetHeight(),&interest,tx,chainActive.LastTip()->nTime) - tx.GetValueOut();
2153 nTxSigOps += GetP2SHSigOpCount(tx, view);
2154 if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS-1)
2156 //fprintf(stderr,"B nBlockSigOps %d + %d nTxSigOps >= %d MAX_BLOCK_SIGOPS-1\n",(int32_t)nBlockSigOps,(int32_t)nTxSigOps,(int32_t)MAX_BLOCK_SIGOPS);
2160 // Note that flags: we don't want to set mempool/IsStandard()
2161 // policy here, but we still have to ensure that the block we
2162 // create only contains transactions that are valid in new blocks.
2163 CValidationState state;
2164 PrecomputedTransactionData txdata(tx);
2165 if (!ContextualCheckInputs(tx, state, view, nHeight, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId))
2167 //fprintf(stderr,"context failure\n");
2171 UpdateCoins(tx, view, nHeight);
2175 reservePositions.push_back(nBlockTx);
2176 haveReserveTransactions = true;
2177 additionalFees += txDesc.ReserveFees();
2180 BOOST_FOREACH(const OutputDescription &outDescription, tx.vShieldedOutput) {
2181 sapling_tree.append(outDescription.cm);
2185 pblock->vtx.push_back(tx);
2186 pblocktemplate->vTxFees.push_back(nTxFees);
2187 pblocktemplate->vTxSigOps.push_back(nTxSigOps);
2188 nBlockSize += nTxSize;
2190 nBlockSigOps += nTxSigOps;
2194 LogPrintf("priority %.1f fee %s txid %s\n",dPriority, feeRate.ToString(), tx.GetHash().ToString());
2197 // Add transactions that depend on this one to the priority queue
2198 if (mapDependers.count(hash))
2200 BOOST_FOREACH(COrphan* porphan, mapDependers[hash])
2202 if (!porphan->setDependsOn.empty())
2204 porphan->setDependsOn.erase(hash);
2205 if (porphan->setDependsOn.empty())
2207 vecPriority.push_back(TxPriority(porphan->dPriority, porphan->feeRate, porphan->ptx));
2208 std::push_heap(vecPriority.begin(), vecPriority.end(), comparer);
2215 // first calculate and distribute block rewards, including fees in the minerOutputs vector
2216 CAmount rewardTotalShareAmount = 0;
2217 CAmount rewardFees = nFees;
2218 if (additionalFees.valueMap.count(thisChainID))
2220 rewardFees += additionalFees.valueMap[thisChainID];
2221 additionalFees.valueMap.erase(thisChainID);
2224 CAmount verusFees = 0;
2225 if (VERUS_CHAINID != ASSETCHAINS_CHAINID && additionalFees.valueMap.count(VERUS_CHAINID))
2227 verusFees += additionalFees.valueMap[VERUS_CHAINID];
2228 additionalFees.valueMap.erase(VERUS_CHAINID);
2231 if (additionalFees.valueMap.size())
2233 printf("%s: burning reserve currency: %s\n", __func__, additionalFees.ToUniValue().write(1,2).c_str());
2236 if (feePool.IsValid())
2238 // we support only the current native currency or VRSC on PBaaS chains in the fee pool for now
2239 feePool.reserveValues.valueMap[thisChainID] += rewardFees;
2242 feePool.reserveValues.valueMap[VERUS_CHAINID] += verusFees;
2244 CFeePool oneFeeShare = feePool.OneFeeShare();
2245 rewardFees = oneFeeShare.reserveValues.valueMap[thisChainID];
2246 feePool.reserveValues.valueMap[thisChainID] -= rewardFees;
2248 if (VERUS_CHAINID != ASSETCHAINS_CHAINID && oneFeeShare.reserveValues.valueMap.count(VERUS_CHAINID))
2250 verusFees = oneFeeShare.reserveValues.valueMap[VERUS_CHAINID];
2251 feePool.reserveValues.valueMap[VERUS_CHAINID] -= verusFees;
2254 cp = CCinit(&CC, EVAL_FEE_POOL);
2255 pkCC = CPubKey(ParseHex(CC.CChexstr));
2256 coinbaseTx.vout.push_back(CTxOut(0,MakeMofNCCScript(CConditionObj<CFeePool>(EVAL_FEE_POOL,{pkCC.GetID()},1,&feePool))));
2259 // printf("%s: rewardfees: %ld, verusfees: %ld\n", __func__, rewardFees, verusFees);
2261 CAmount rewardTotal = blockSubsidy + rewardFees;
2263 // now that we have the total reward, update the coinbase outputs
2266 // TODO: need to add reserve output to stake coinbase to prevent burning of VRSC
2267 coinbaseTx.vout[0].nValue = rewardTotal;
2271 for (auto &outputShare : minerOutputs)
2273 rewardTotalShareAmount += outputShare.nValue;
2277 CAmount rewardLeft = rewardTotal;
2278 CAmount verusFeeLeft = verusFees;
2279 for (cbOutIdx = 0; cbOutIdx < minerOutputs.size(); cbOutIdx++)
2281 CAmount amount = (arith_uint256(rewardTotal) * arith_uint256(minerOutputs[cbOutIdx].nValue) / arith_uint256(rewardTotalShareAmount)).GetLow64();
2282 if (rewardLeft <= amount || (cbOutIdx + 1) == minerOutputs.size())
2284 amount = rewardLeft;
2286 rewardLeft -= amount;
2288 // now make outputs for non-native, VRSC fees
2291 CAmount verusFee = (arith_uint256(verusFees) * arith_uint256(minerOutputs[cbOutIdx].nValue) / arith_uint256(rewardTotalShareAmount)).GetLow64();
2292 if (verusFeeLeft <= verusFee || (cbOutIdx + 1) == minerOutputs.size())
2294 verusFee = verusFeeLeft;
2296 CTxDestination minerDestination;
2297 if (verusFee >= CFeePool::MIN_SHARE_SIZE && ExtractDestination(coinbaseTx.vout[cbOutIdx].scriptPubKey, minerDestination))
2299 CTokenOutput to = CTokenOutput(VERUS_CHAINID, verusFee);
2300 coinbaseTx.vout[cbOutIdx].scriptPubKey = MakeMofNCCScript(CConditionObj<CTokenOutput>(EVAL_RESERVE_OUTPUT,
2301 std::vector<CTxDestination>({minerDestination}),
2305 verusFeeLeft -= verusFee;
2308 // we had to wait to update this here to ensure it represented a correct distribution ratio
2309 coinbaseTx.vout[cbOutIdx].nValue = amount;
2313 nLastBlockTx = nBlockTx;
2314 nLastBlockSize = nBlockSize;
2316 blocktime = std::max(pindexPrev->GetMedianTimePast(), GetAdjustedTime());
2318 pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus());
2320 coinbaseTx.nExpiryHeight = 0;
2321 coinbaseTx.nLockTime = blocktime;
2323 // finalize input of coinbase
2324 coinbaseTx.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(0)) + COINBASE_FLAGS;
2325 assert(coinbaseTx.vin[0].scriptSig.size() <= 100);
2328 pblock->vtx[0] = coinbaseTx;
2329 uint256 cbHash = coinbaseTx.GetHash();
2331 // display it at block 1 for PBaaS debugging
2332 /* if (nHeight == 1)
2334 UniValue jsonTxOut(UniValue::VOBJ);
2335 TxToUniv(coinbaseTx, uint256(), jsonTxOut);
2336 printf("%s: new coinbase transaction: %s\n", __func__, jsonTxOut.write(1,2).c_str());
2339 // if there is a stake transaction, add it to the very end
2342 UpdateCoins(txStaked, view, nHeight);
2343 pblock->vtx.push_back(txStaked);
2344 pblocktemplate->vTxFees.push_back(0);
2345 int txSigOps = GetLegacySigOpCount(txStaked);
2346 pblocktemplate->vTxSigOps.push_back(txSigOps);
2347 // already added to the block size above
2349 nBlockSigOps += txSigOps;
2352 extern CWallet *pwalletMain;
2354 pblock->vtx[0] = coinbaseTx;
2355 pblocktemplate->vTxFees[0] = -nFees;
2356 pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
2358 // if not Verus stake, setup nonce, otherwise, leave it alone
2359 if (!isStake || ASSETCHAINS_LWMAPOS == 0)
2362 arith_uint256 nonce = UintToArith256(GetRandHash());
2364 // Clear the top 16 and bottom 16 or 24 bits (for local use as thread flags and counters)
2365 nonce <<= ASSETCHAINS_NONCESHIFT[ASSETCHAINS_ALGO];
2367 pblock->nNonce = ArithToUint256(nonce);
2371 pblock->hashPrevBlock = pindexPrev->GetBlockHash();
2372 pblock->hashFinalSaplingRoot = sapling_tree.root();
2374 // all Verus PoS chains need this data in the block at all times
2375 if ( ASSETCHAINS_LWMAPOS || ASSETCHAINS_SYMBOL[0] == 0 || ASSETCHAINS_STAKED == 0 || KOMODO_MININGTHREADS > 0 )
2377 UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
2378 pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus());
2381 if ( ASSETCHAINS_SYMBOL[0] == 0 && IS_KOMODO_NOTARY != 0 && My_notaryid >= 0 )
2384 CMutableTransaction txNotary = CreateNewContextualCMutableTransaction(Params().GetConsensus(), chainActive.Height() + 1);
2385 if ( pblock->nTime < pindexPrev->nTime+60 )
2386 pblock->nTime = pindexPrev->nTime + 60;
2388 if ( komodo_notaryvin(txNotary,NOTARY_PUBKEY33) > 0 )
2390 CAmount txfees = 5000;
2391 pblock->vtx.push_back(txNotary);
2392 pblocktemplate->vTxFees.push_back(txfees);
2393 pblocktemplate->vTxSigOps.push_back(GetLegacySigOpCount(txNotary));
2395 pblocktemplate->vTxFees[0] = -nFees;
2396 //*(uint64_t *)(&pblock->vtx[0].vout[0].nValue) += txfees;
2397 //fprintf(stderr,"added notaryvin\n");
2401 fprintf(stderr,"error adding notaryvin, need to create 0.0001 utxos\n");
2405 else if ( ASSETCHAINS_CC == 0 && pindexPrev != 0 && ASSETCHAINS_STAKED == 0 && (ASSETCHAINS_SYMBOL[0] != 0 || IS_KOMODO_NOTARY == 0 || My_notaryid < 0) )
2407 CValidationState state;
2408 //fprintf(stderr,"check validity\n");
2409 if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) // invokes CC checks
2411 throw std::runtime_error("CreateNewBlock(): TestBlockValidity failed");
2413 //fprintf(stderr,"valid\n");
2416 //fprintf(stderr,"done new block\n");
2418 // setup the header and buid the Merkle tree
2419 unsigned int extraNonce;
2420 IncrementExtraNonce(pblock, pindexPrev, extraNonce, true);
2422 return pblocktemplate.release();
2425 CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& _scriptPubKeyIn, bool isStake)
2427 std::vector<CTxOut> minerOutputs = _scriptPubKeyIn.size() ? std::vector<CTxOut>({CTxOut(1, _scriptPubKeyIn)}) : std::vector<CTxOut>();
2428 return CreateNewBlock(chainparams, minerOutputs, isStake);
2431 //////////////////////////////////////////////////////////////////////////////
2436 #ifdef ENABLE_MINING
2438 class MinerAddressScript : public CReserveScript
2440 // CReserveScript requires implementing this function, so that if an
2441 // internal (not-visible) wallet address is used, the wallet can mark it as
2442 // important when a block is mined (so it then appears to the user).
2443 // If -mineraddress is set, the user already knows about and is managing the
2444 // address, so we don't need to do anything here.
2445 void KeepScript() {}
2448 void GetScriptForMinerAddress(boost::shared_ptr<CReserveScript> &script)
2450 CTxDestination addr = DecodeDestination(GetArg("-mineraddress", ""));
2451 if (!IsValidDestination(addr)) {
2455 boost::shared_ptr<MinerAddressScript> mAddr(new MinerAddressScript());
2457 script->reserveScript = GetScriptForDestination(addr);
2460 #ifdef ENABLE_WALLET
2461 //////////////////////////////////////////////////////////////////////////////
2466 CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey, int32_t nHeight, bool isStake)
2469 CScript scriptPubKey;
2472 boost::shared_ptr<CReserveScript> coinbaseScript;
2474 if ( nHeight == 1 && ASSETCHAINS_OVERRIDE_PUBKEY33[0] != 0 )
2476 scriptPubKey = CScript() << ParseHex(ASSETCHAINS_OVERRIDE_PUBKEY) << OP_CHECKSIG;
2478 else if ( USE_EXTERNAL_PUBKEY != 0 )
2480 //fprintf(stderr,"use notary pubkey\n");
2481 scriptPubKey = CScript() << ParseHex(NOTARY_PUBKEY) << OP_CHECKSIG;
2483 else if (GetArg("-mineraddress", "").empty() || !(GetScriptForMinerAddress(coinbaseScript), (scriptPubKey = coinbaseScript->reserveScript).size()))
2487 if (!reservekey.GetReservedKey(pubkey))
2491 scriptPubKey = GetScriptForDestination(pubkey);
2494 return CreateNewBlock(Params(), scriptPubKey, isStake);
2497 void komodo_broadcast(const CBlock *pblock,int32_t limit)
2500 //fprintf(stderr,"broadcast new block t.%u\n",(uint32_t)time(NULL));
2503 BOOST_FOREACH(CNode* pnode, vNodes)
2505 if ( pnode->hSocket == INVALID_SOCKET )
2507 if ( (rand() % n) == 0 )
2509 pnode->PushMessage("block", *pblock);
2515 //fprintf(stderr,"finished broadcast new block t.%u\n",(uint32_t)time(NULL));
2518 static bool ProcessBlockFound(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
2520 static bool ProcessBlockFound(CBlock* pblock)
2521 #endif // ENABLE_WALLET
2523 int32_t height = chainActive.LastTip()->GetHeight()+1;
2524 //LogPrintf("%s\n", pblock->ToString());
2525 LogPrintf("generated %s height.%d\n", FormatMoney(pblock->vtx[0].vout[0].nValue), height);
2529 if (pblock->hashPrevBlock != chainActive.LastTip()->GetBlockHash())
2531 uint256 hash; int32_t i;
2532 hash = pblock->hashPrevBlock;
2533 for (i=31; i>=0; i--)
2534 fprintf(stderr,"%02x",((uint8_t *)&hash)[i]);
2535 fprintf(stderr," <- prev (stale)\n");
2536 hash = chainActive.LastTip()->GetBlockHash();
2537 for (i=31; i>=0; i--)
2538 fprintf(stderr,"%02x",((uint8_t *)&hash)[i]);
2539 fprintf(stderr," <- chainTip (stale)\n");
2541 return error("VerusMiner: generated block is stale");
2545 #ifdef ENABLE_WALLET
2546 // Remove key from key pool
2547 if ( IS_KOMODO_NOTARY == 0 )
2549 if (GetArg("-mineraddress", "").empty()) {
2550 // Remove key from key pool
2551 reservekey.KeepKey();
2554 // Track how many getdata requests this block gets
2557 //fprintf(stderr,"lock cs_wallet\n");
2558 LOCK(wallet.cs_wallet);
2559 wallet.mapRequestCount[pblock->GetHash()] = 0;
2562 //fprintf(stderr,"process new block\n");
2564 // Process this block (almost) the same as if we had received it from another node
2565 CValidationState state;
2566 if (!ProcessNewBlock(1, chainActive.LastTip()->GetHeight()+1, state, Params(), NULL, pblock, true, NULL))
2567 return error("VerusMiner: ProcessNewBlock, block not accepted");
2569 TrackMinedBlock(pblock->GetHash());
2570 komodo_broadcast(pblock,16);
2574 int32_t komodo_baseid(char *origbase);
2575 int32_t komodo_eligiblenotary(uint8_t pubkeys[66][33],int32_t *mids,uint32_t *blocktimes,int32_t *nonzpkeysp,int32_t height);
2576 arith_uint256 komodo_PoWtarget(int32_t *percPoSp,arith_uint256 target,int32_t height,int32_t goalperc);
2577 int32_t FOUND_BLOCK,KOMODO_MAYBEMINED;
2578 extern int32_t KOMODO_LASTMINED,KOMODO_INSYNC;
2579 int32_t roundrobin_delay;
2580 arith_uint256 HASHTarget,HASHTarget_POW;
2581 int32_t komodo_longestchain();
2583 // wait for peers to connect
2584 void waitForPeers(const CChainParams &chainparams)
2586 if (chainparams.MiningRequiresPeers())
2590 boost::this_thread::interruption_point();
2592 fvNodesEmpty = vNodes.empty();
2594 int longestchain = komodo_longestchain();
2595 int lastlongest = 0;
2596 if (fvNodesEmpty || IsNotInSync() || (longestchain != 0 && longestchain > chainActive.LastTip()->GetHeight()))
2598 int loops = 0, blockDiff = 0, newDiff = 0;
2603 MilliSleep(1000 + rand() % 4000);
2604 boost::this_thread::interruption_point();
2606 fvNodesEmpty = vNodes.empty();
2611 else if ((newDiff = IsNotInSync()) > 0)
2613 if (blockDiff != newDiff)
2615 blockDiff = newDiff;
2627 else if (!fvNodesEmpty && !IsNotInSync() && longestchain > chainActive.LastTip()->GetHeight())
2629 // the only thing may be that we are seeing a long chain that we'll never get
2630 // don't wait forever
2631 if (lastlongest == 0)
2634 lastlongest = longestchain;
2637 } while (fvNodesEmpty || IsNotInSync());
2638 MilliSleep(500 + rand() % 1000);
2643 #ifdef ENABLE_WALLET
2644 CBlockIndex *get_chainactive(int32_t height)
2646 if ( chainActive.LastTip() != 0 )
2648 if ( height <= chainActive.LastTip()->GetHeight() )
2651 return(chainActive[height]);
2653 // else fprintf(stderr,"get_chainactive height %d > active.%d\n",height,chainActive.Tip()->GetHeight());
2655 //fprintf(stderr,"get_chainactive null chainActive.Tip() height %d\n",height);
2660 * A separate thread to stake, while the miner threads mine.
2662 void static VerusStaker(CWallet *pwallet)
2664 LogPrintf("Verus staker thread started\n");
2665 RenameThread("verus-staker");
2667 const CChainParams& chainparams = Params();
2668 auto consensusParams = chainparams.GetConsensus();
2669 bool isNotaryConnected = ConnectedChains.CheckVerusPBaaSAvailable();
2671 // Each thread has its own key
2672 CReserveKey reservekey(pwallet);
2674 // Each thread has its own counter
2675 unsigned int nExtraNonce = 0;
2677 uint8_t *script; uint64_t total,checktoshis; int32_t i,j;
2679 while ( (ASSETCHAIN_INIT == 0 || KOMODO_INITDONE == 0) ) //chainActive.Tip()->GetHeight() != 235300 &&
2682 if ( komodo_baseid(ASSETCHAINS_SYMBOL) < 0 )
2686 // try a nice clean peer connection to start
2687 CBlockIndex *pindexPrev, *pindexCur;
2689 pindexPrev = chainActive.LastTip();
2690 MilliSleep(5000 + rand() % 5000);
2691 waitForPeers(chainparams);
2692 pindexCur = chainActive.LastTip();
2693 } while (pindexPrev != pindexCur);
2696 static int32_t lastStakingHeight = 0;
2700 waitForPeers(chainparams);
2701 CBlockIndex* pindexPrev = chainActive.LastTip();
2704 unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
2706 if ( Mining_height != pindexPrev->GetHeight()+1 )
2708 Mining_height = pindexPrev->GetHeight()+1;
2709 Mining_start = (uint32_t)time(NULL);
2712 // Check for stop or if block needs to be rebuilt
2713 boost::this_thread::interruption_point();
2715 // try to stake a block
2716 CBlockTemplate *ptr = NULL;
2718 // get height locally for consistent reporting
2719 int32_t newHeight = Mining_height;
2721 if (newHeight > VERUS_MIN_STAKEAGE)
2722 ptr = CreateNewBlockWithKey(reservekey, newHeight, true);
2724 // TODO - putting this output here tends to help mitigate announcing a staking height earlier than
2725 // announcing the last block win when we start staking before a block's acceptance has been
2726 // acknowledged by the mining thread - a better solution may be to put the output on the submission
2728 if ( ptr == 0 && newHeight != lastStakingHeight )
2730 printf("Staking height %d for %s\n", newHeight, ASSETCHAINS_SYMBOL);
2732 lastStakingHeight = newHeight;
2736 if (newHeight == 1 && (isNotaryConnected = ConnectedChains.IsNotaryAvailable()))
2738 static int outputCounter;
2739 if (outputCounter++ % 60 == 0)
2741 printf("%s: waiting for confirmation of launch at or after block %u on %s before mining block 1\n", __func__,
2742 (uint32_t)ConnectedChains.ThisChain().startBlock,
2743 ConnectedChains.FirstNotaryChain().chainDefinition.name.c_str());
2747 // wait to try another staking block until after the tip moves again
2748 while ( chainActive.LastTip() == pindexPrev )
2757 unique_ptr<CBlockTemplate> pblocktemplate(ptr);
2758 if (!pblocktemplate.get())
2760 if (GetArg("-mineraddress", "").empty()) {
2761 LogPrintf("Error in %s staker: Keypool ran out, please call keypoolrefill before restarting the mining thread\n",
2762 ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
2764 // Should never reach here, because -mineraddress validity is checked in init.cpp
2765 LogPrintf("Error in %s staker: Invalid %s -mineraddress\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO], ASSETCHAINS_SYMBOL);
2770 CBlock *pblock = &pblocktemplate->block;
2771 LogPrintf("Staking with %u transactions in block (%u bytes)\n", pblock->vtx.size(),::GetSerializeSize(*pblock,SER_NETWORK,PROTOCOL_VERSION));
2775 int64_t nStart = GetTime();
2777 if (vNodes.empty() && chainparams.MiningRequiresPeers())
2779 if ( Mining_height > ASSETCHAINS_MINHEIGHT )
2781 fprintf(stderr,"no nodes, attempting reconnect\n");
2786 if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
2788 fprintf(stderr,"timeout, retrying\n");
2792 if ( pindexPrev != chainActive.LastTip() )
2794 printf("Block %d added to chain\n", chainActive.LastTip()->GetHeight());
2799 int32_t unlockTime = komodo_block_unlocktime(Mining_height);
2800 int64_t subsidy = (int64_t)(pblock->vtx[0].vout[0].nValue);
2802 uint256 hashTarget = ArithToUint256(arith_uint256().SetCompact(pblock->nBits));
2804 pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams);
2806 UpdateTime(pblock, consensusParams, pindexPrev);
2808 if (ProcessBlockFound(pblock, *pwallet, reservekey))
2810 LogPrintf("Using %s algorithm:\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
2811 LogPrintf("Staked block found \n hash: %s \ntarget: %s\n", pblock->GetHash().GetHex(), hashTarget.GetHex());
2812 printf("Found block %d \n", newHeight);
2813 printf("staking reward %.8f %s!\n", (double)subsidy / (double)COIN, ASSETCHAINS_SYMBOL);
2815 post.SetCompact(pblock->GetVerusPOSTarget());
2817 CTransaction &sTx = pblock->vtx[pblock->vtx.size()-1];
2818 printf("POS hash: %s \ntarget: %s\n",
2819 CTransaction::_GetVerusPOSHash(&(pblock->nNonce),
2820 sTx.vin[0].prevout.hash,
2821 sTx.vin[0].prevout.n,
2823 chainActive.GetVerusEntropyHash(newHeight),
2824 sTx.vout[0].nValue).GetHex().c_str(),
2825 ArithToUint256(post).GetHex().c_str());
2826 if (unlockTime > newHeight && subsidy >= ASSETCHAINS_TIMELOCKGTE)
2827 printf("- timelocked until block %i\n", unlockTime);
2833 LogPrintf("Found block rejected at staking height: %d\n", Mining_height);
2834 printf("Found block rejected at staking height: %d\n", Mining_height);
2837 // Check for stop or if block needs to be rebuilt
2838 boost::this_thread::interruption_point();
2842 // In regression test mode, stop mining after a block is found.
2843 if (chainparams.MineBlocksOnDemand()) {
2844 throw boost::thread_interrupted();
2848 catch (const boost::thread_interrupted&)
2850 LogPrintf("VerusStaker terminated\n");
2853 catch (const std::runtime_error &e)
2855 LogPrintf("VerusStaker runtime error: %s\n", e.what());
2860 typedef bool (*minefunction)(CBlockHeader &bh, CVerusHashV2bWriter &vhw, uint256 &finalHash, uint256 &target, uint64_t start, uint64_t *count);
2861 bool mine_verus_v2(CBlockHeader &bh, CVerusHashV2bWriter &vhw, uint256 &finalHash, uint256 &target, uint64_t start, uint64_t *count);
2862 bool mine_verus_v2_port(CBlockHeader &bh, CVerusHashV2bWriter &vhw, uint256 &finalHash, uint256 &target, uint64_t start, uint64_t *count);
2864 void static BitcoinMiner_noeq(CWallet *pwallet)
2866 void static BitcoinMiner_noeq()
2869 LogPrintf("%s miner started\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
2870 RenameThread("verushash-miner");
2872 #ifdef ENABLE_WALLET
2873 // Each thread has its own key
2874 CReserveKey reservekey(pwallet);
2877 miningTimer.clear();
2879 const CChainParams& chainparams = Params();
2880 // Each thread has its own counter
2881 unsigned int nExtraNonce = 0;
2883 uint8_t *script; uint64_t total,checktoshis; int32_t i,j;
2885 while ( (ASSETCHAIN_INIT == 0 || KOMODO_INITDONE == 0) ) //chainActive.Tip()->GetHeight() != 235300 &&
2888 if ( komodo_baseid(ASSETCHAINS_SYMBOL) < 0 )
2892 SetThreadPriority(THREAD_PRIORITY_LOWEST);
2894 // try a nice clean peer connection to start
2895 CBlockIndex *pindexPrev, *pindexCur;
2897 pindexPrev = chainActive.LastTip();
2898 MilliSleep(5000 + rand() % 5000);
2899 waitForPeers(chainparams);
2900 pindexCur = chainActive.LastTip();
2901 } while (pindexPrev != pindexCur);
2903 // make sure that we have checked for PBaaS availability
2904 ConnectedChains.CheckVerusPBaaSAvailable();
2906 // this will not stop printing more than once in all cases, but it will allow us to print in all cases
2907 // and print duplicates rarely without having to synchronize
2908 static CBlockIndex *lastChainTipPrinted;
2909 static int32_t lastMiningHeight = 0;
2911 miningTimer.start();
2914 printf("Mining %s with %s\n", ASSETCHAINS_SYMBOL, ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
2919 waitForPeers(chainparams);
2921 pindexPrev = chainActive.LastTip();
2923 // prevent forking on startup before the diff algorithm kicks in,
2924 // but only for a startup Verus test chain. PBaaS chains have the difficulty inherited from
2926 if (chainparams.MiningRequiresPeers() && ((IsVerusActive() && pindexPrev->GetHeight() < 50) || pindexPrev != chainActive.LastTip()))
2929 pindexPrev = chainActive.LastTip();
2930 MilliSleep(2000 + rand() % 2000);
2931 } while (pindexPrev != chainActive.LastTip());
2935 unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
2936 if ( Mining_height != pindexPrev->GetHeight()+1 )
2938 Mining_height = pindexPrev->GetHeight()+1;
2939 if (lastMiningHeight != Mining_height)
2941 lastMiningHeight = Mining_height;
2942 printf("Mining %s at height %d\n", ASSETCHAINS_SYMBOL, Mining_height);
2944 Mining_start = (uint32_t)time(NULL);
2947 miningTimer.start();
2949 #ifdef ENABLE_WALLET
2950 CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, Mining_height);
2952 CBlockTemplate *ptr = CreateNewBlockWithKey();
2956 static uint32_t counter;
2957 if ( counter++ % 40 == 0 )
2959 if (!IsVerusActive() &&
2960 ConnectedChains.IsNotaryAvailable() &&
2961 !ConnectedChains.readyToStart)
2963 fprintf(stderr,"waiting for confirmation of launch at or after block %u on %s chain to start\n", (uint32_t)ConnectedChains.ThisChain().startBlock,
2964 ConnectedChains.FirstNotaryChain().chainDefinition.name.c_str());
2968 fprintf(stderr,"Unable to create valid block... will continue to try\n");
2975 unique_ptr<CBlockTemplate> pblocktemplate(ptr);
2976 if (!pblocktemplate.get())
2978 if (GetArg("-mineraddress", "").empty()) {
2979 LogPrintf("Error in %s miner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n",
2980 ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
2982 // Should never reach here, because -mineraddress validity is checked in init.cpp
2983 LogPrintf("Error in %s miner: Invalid %s -mineraddress\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO], ASSETCHAINS_SYMBOL);
2986 miningTimer.clear();
2989 CBlock *pblock = &pblocktemplate->block;
2992 bool mergeMining = false;
2993 savebits = pblock->nBits;
2995 uint32_t solutionVersion = CConstVerusSolutionVector::Version(pblock->nSolution);
2996 if (pblock->nVersion != CBlockHeader::VERUS_V2)
2998 // must not be in sync
2999 printf("Mining on incorrect block version.\n");
3003 bool verusSolutionPBaaS = solutionVersion >= CActivationHeight::ACTIVATE_PBAAS;
3005 // v2 hash writer with adjustments for the current height
3006 CVerusHashV2bWriter ss2 = CVerusHashV2bWriter(SER_GETHASH, PROTOCOL_VERSION, solutionVersion);
3008 if ( ASSETCHAINS_SYMBOL[0] != 0 )
3010 if ( ASSETCHAINS_REWARD[0] == 0 && !ASSETCHAINS_LASTERA )
3012 if ( pblock->vtx.size() == 1 && pblock->vtx[0].vout.size() == 1 && Mining_height > ASSETCHAINS_MINHEIGHT )
3014 static uint32_t counter;
3015 if ( counter++ < 10 )
3016 fprintf(stderr,"skip generating %s on-demand block, no tx avail\n",ASSETCHAINS_SYMBOL);
3019 } else fprintf(stderr,"%s vouts.%d mining.%d vs %d\n",ASSETCHAINS_SYMBOL,(int32_t)pblock->vtx[0].vout.size(),Mining_height,ASSETCHAINS_MINHEIGHT);
3023 // set our easiest target, if V3+, no need to rebuild the merkle tree
3024 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce, verusSolutionPBaaS ? false : true, &savebits);
3026 // update PBaaS header
3027 if (verusSolutionPBaaS)
3029 if (!IsVerusActive() && ConnectedChains.IsVerusPBaaSAvailable())
3032 UniValue params(UniValue::VARR);
3033 UniValue error(UniValue::VARR);
3034 params.push_back(EncodeHexBlk(*pblock));
3035 params.push_back(ASSETCHAINS_SYMBOL);
3036 params.push_back(ASSETCHAINS_RPCHOST);
3037 params.push_back(ASSETCHAINS_RPCPORT);
3038 params.push_back(ASSETCHAINS_RPCCREDENTIALS);
3041 ConnectedChains.lastSubmissionFailed = false;
3042 params = RPCCallRoot("addmergedblock", params);
3043 params = find_value(params, "result");
3044 error = find_value(params, "error");
3045 } catch (std::exception e)
3047 printf("Failed to connect to %s chain\n", ConnectedChains.FirstNotaryChain().chainDefinition.name.c_str());
3048 params = UniValue(e.what());
3050 if (mergeMining = (params.isNull() && error.isNull()))
3052 printf("Merge mining %s with %s as the hashing chain\n", ASSETCHAINS_SYMBOL, ConnectedChains.FirstNotaryChain().chainDefinition.name.c_str());
3053 LogPrintf("Merge mining with %s as the hashing chain\n", ConnectedChains.FirstNotaryChain().chainDefinition.name.c_str());
3058 LogPrintf("Running %s miner with %u transactions in block (%u bytes)\n",ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO],
3059 pblock->vtx.size(),::GetSerializeSize(*pblock,SER_NETWORK,PROTOCOL_VERSION));
3063 int64_t nStart = GetTime();
3065 arith_uint256 hashTarget = arith_uint256().SetCompact(savebits);
3066 uint256 uintTarget = ArithToUint256(hashTarget);
3067 arith_uint256 ourTarget;
3068 ourTarget.SetCompact(pblock->nBits);
3072 if ( pindexPrev != chainActive.LastTip() )
3074 if (lastChainTipPrinted != chainActive.LastTip())
3076 lastChainTipPrinted = chainActive.LastTip();
3077 printf("Block %d added to chain\n", lastChainTipPrinted->GetHeight());
3084 uint64_t hashesToGo = 0;
3085 uint64_t totalDone = 0;
3087 int64_t subsidy = (int64_t)(pblock->vtx[0].vout[0].nValue);
3088 count = ((ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] >> 3) + 1) / ASSETCHAINS_HASHESPERROUND[ASSETCHAINS_ALGO];
3089 CVerusHashV2 *vh2 = &ss2.GetState();
3091 verusclhasher &vclh = vh2->vclh;
3092 minefunction mine_verus;
3093 mine_verus = IsCPUVerusOptimized() ? &mine_verus_v2 : &mine_verus_v2_port;
3097 uint256 hashResult = uint256();
3099 unsigned char *curBuf;
3103 // loop for a few minutes before refreshing the block
3106 uint256 ourMerkle = pblock->hashMerkleRoot;
3107 if ( pindexPrev != chainActive.LastTip() )
3109 if (lastChainTipPrinted != chainActive.LastTip())
3111 lastChainTipPrinted = chainActive.LastTip();
3112 printf("Block %d added to chain\n\n", lastChainTipPrinted->GetHeight());
3113 arith_uint256 target;
3114 target.SetCompact(lastChainTipPrinted->nBits);
3115 if (ourMerkle == lastChainTipPrinted->hashMerkleRoot)
3117 LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", lastChainTipPrinted->GetBlockHash().GetHex().c_str(), ArithToUint256(ourTarget).GetHex().c_str());
3118 printf("Found block %d \n", lastChainTipPrinted->GetHeight());
3119 printf("mining reward %.8f %s!\n", (double)subsidy / (double)COIN, ASSETCHAINS_SYMBOL);
3120 printf(" hash: %s\ntarget: %s\n", lastChainTipPrinted->GetBlockHash().GetHex().c_str(), ArithToUint256(ourTarget).GetHex().c_str());
3126 // if PBaaS is no longer available, we can't count on merge mining
3127 if (!ConnectedChains.IsVerusPBaaSAvailable())
3132 if (vNodes.empty() && chainparams.MiningRequiresPeers())
3134 if ( Mining_height > ASSETCHAINS_MINHEIGHT )
3136 fprintf(stderr,"no nodes, attempting reconnect\n");
3141 // update every few minutes, regardless
3142 int64_t elapsed = GetTime() - nStart;
3144 if ((mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && elapsed > 60) || elapsed > 60 || ConnectedChains.lastSubmissionFailed)
3149 boost::this_thread::interruption_point();
3156 // check NONCEMASK at a time
3157 for (uint64_t i = 0; i < count; i++)
3159 // 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
3160 // merge mined block, but not our own
3162 arith_uint256 arithHash;
3166 // pickup/remove any new/deleted headers
3167 if (ConnectedChains.dirty || (pblock->NumPBaaSHeaders() < ConnectedChains.mergeMinedChains.size() + 1))
3169 IncrementExtraNonce(pblock, pindexPrev, nExtraNonce, verusSolutionPBaaS ? false : true, &savebits);
3171 hashTarget.SetCompact(savebits);
3172 uintTarget = ArithToUint256(hashTarget);
3175 // hashesToGo gets updated with actual number run for metrics
3176 hashesToGo = ASSETCHAINS_HASHESPERROUND[ASSETCHAINS_ALGO];
3177 uint64_t start = i * hashesToGo + totalDone;
3178 hashesToGo -= totalDone;
3180 if (verusSolutionPBaaS)
3182 // mine on canonical header for merge mining
3183 CPBaaSPreHeader savedHeader(*pblock);
3185 pblock->ClearNonCanonicalData();
3186 blockFound = (*mine_verus)(*pblock, ss2, hashResult, uintTarget, start, &hashesToGo);
3187 savedHeader.SetBlockData(*pblock);
3191 blockFound = (*mine_verus)(*pblock, ss2, hashResult, uintTarget, start, &hashesToGo);
3194 arithHash = UintToArith256(hashResult);
3195 totalDone += hashesToGo + 1;
3196 if (blockFound && IsVerusActive())
3198 ConnectedChains.QueueNewBlockHeader(*pblock);
3199 if (arithHash > ourTarget)
3201 // all blocks qualified with this hash will be submitted
3202 // until we redo the block, we might as well not try again with anything over this hash
3203 hashTarget = arithHash;
3204 uintTarget = ArithToUint256(hashTarget);
3207 } while (blockFound && arithHash > ourTarget);
3209 if (!blockFound || arithHash > ourTarget)
3211 // Check for stop or if block needs to be rebuilt
3212 boost::this_thread::interruption_point();
3213 if ( pindexPrev != chainActive.LastTip() )
3215 if (lastChainTipPrinted != chainActive.LastTip())
3217 lastChainTipPrinted = chainActive.LastTip();
3218 printf("Block %d added to chain\n", lastChainTipPrinted->GetHeight());
3222 else if ((i + 1) < count)
3224 // if we'll not drop through, update hashcount
3226 miningTimer += totalDone;
3233 // Check for stop or if block needs to be rebuilt
3234 boost::this_thread::interruption_point();
3236 if (pblock->nSolution.size() != 1344)
3238 LogPrintf("ERROR: Block solution is not 1344 bytes as it should be");
3242 SetThreadPriority(THREAD_PRIORITY_NORMAL);
3244 int32_t unlockTime = komodo_block_unlocktime(Mining_height);
3246 #ifdef VERUSHASHDEBUG
3247 std::string validateStr = hashResult.GetHex();
3248 std::string hashStr = pblock->GetHash().GetHex();
3249 uint256 *bhalf1 = (uint256 *)vh2->CurBuffer();
3250 uint256 *bhalf2 = bhalf1 + 1;
3252 std::string hashStr = hashResult.GetHex();
3255 LogPrintf("Using %s algorithm:\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
3256 LogPrintf("proof-of-work found \n hash: %s \ntarget: %s\n", hashStr, ArithToUint256(ourTarget).GetHex());
3257 printf("Found block %d \n", Mining_height );
3258 printf("mining reward %.8f %s!\n", (double)subsidy / (double)COIN, ASSETCHAINS_SYMBOL);
3259 #ifdef VERUSHASHDEBUG
3260 printf(" hash: %s\n val: %s \ntarget: %s\n\n", hashStr.c_str(), validateStr.c_str(), ArithToUint256(ourTarget).GetHex().c_str());
3261 printf("intermediate %lx\n", intermediate);
3262 printf("Curbuf: %s%s\n", bhalf1->GetHex().c_str(), bhalf2->GetHex().c_str());
3263 bhalf1 = (uint256 *)verusclhasher_key.get();
3264 bhalf2 = bhalf1 + ((vh2->vclh.keyMask + 1) >> 5);
3265 printf(" Key: %s%s\n", bhalf1->GetHex().c_str(), bhalf2->GetHex().c_str());
3267 printf(" hash: %s\ntarget: %s", hashStr.c_str(), ArithToUint256(ourTarget).GetHex().c_str());
3269 if (unlockTime > Mining_height && subsidy >= ASSETCHAINS_TIMELOCKGTE)
3270 printf(" - timelocked until block %i\n", unlockTime);
3273 #ifdef ENABLE_WALLET
3274 ProcessBlockFound(pblock, *pwallet, reservekey);
3276 ProcessBlockFound(pblock);
3278 SetThreadPriority(THREAD_PRIORITY_LOWEST);
3284 miningTimer += totalDone;
3289 // Check for stop or if block needs to be rebuilt
3290 boost::this_thread::interruption_point();
3292 if (vNodes.empty() && chainparams.MiningRequiresPeers())
3294 if ( Mining_height > ASSETCHAINS_MINHEIGHT )
3296 fprintf(stderr,"no nodes, attempting reconnect\n");
3301 if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - nStart > 60)
3303 fprintf(stderr,"timeout, retrying\n");
3307 if ( pindexPrev != chainActive.LastTip() )
3309 if (lastChainTipPrinted != chainActive.LastTip())
3311 lastChainTipPrinted = chainActive.LastTip();
3312 printf("Block %d added to chain\n\n", lastChainTipPrinted->GetHeight());
3317 // totalDone now has the number of hashes actually done since starting on one nonce mask worth
3318 uint64_t hashesPerNonceMask = ASSETCHAINS_NONCEMASK[ASSETCHAINS_ALGO] >> 3;
3319 if (!(totalDone < hashesPerNonceMask))
3322 printf("%llu mega hashes complete - working\n", (hashesPerNonceMask + 1) / 1048576);
3324 printf("%lu mega hashes complete - working\n", (hashesPerNonceMask + 1) / 1048576);
3332 catch (const boost::thread_interrupted&)
3335 miningTimer.clear();
3336 LogPrintf("%s miner terminated\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO]);
3339 catch (const std::runtime_error &e)
3342 miningTimer.clear();
3343 LogPrintf("%s miner runtime error: %s\n", ASSETCHAINS_ALGORITHMS[ASSETCHAINS_ALGO], e.what());
3347 miningTimer.clear();
3350 #ifdef ENABLE_WALLET
3351 void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads)
3353 void GenerateBitcoins(bool fGenerate, int nThreads)
3356 static CCriticalSection cs_startmining;
3358 LOCK(cs_startmining);
3359 if (!AreParamsInitialized())
3364 VERUS_MINTBLOCKS = (VERUS_MINTBLOCKS && ASSETCHAINS_LWMAPOS != 0);
3366 if (fGenerate == true || VERUS_MINTBLOCKS)
3368 mapArgs["-gen"] = "1";
3370 if (VERUS_DEFAULT_ZADDR.size() > 0)
3372 if (defaultSaplingDest == boost::none)
3374 LogPrintf("ERROR: -defaultzaddr parameter is invalid Sapling payment address\n");
3375 fprintf(stderr, "-defaultzaddr parameter is invalid Sapling payment address\n");
3379 LogPrintf("StakeGuard searching for double stakes on %s\n", VERUS_DEFAULT_ZADDR.c_str());
3380 fprintf(stderr, "StakeGuard searching for double stakes on %s\n", VERUS_DEFAULT_ZADDR.c_str());
3385 static boost::thread_group* minerThreads = NULL;
3388 nThreads = GetNumCores();
3390 if (minerThreads != NULL)
3392 minerThreads->interrupt_all();
3393 minerThreads->join_all();
3394 delete minerThreads;
3395 minerThreads = NULL;
3398 //fprintf(stderr,"nThreads.%d fGenerate.%d\n",(int32_t)nThreads,fGenerate);
3399 if ( nThreads == 0 && ASSETCHAINS_STAKED )
3405 minerThreads = new boost::thread_group();
3407 // add the PBaaS thread when mining or staking
3408 minerThreads->create_thread(boost::bind(&CConnectedChains::SubmissionThreadStub));
3410 #ifdef ENABLE_WALLET
3411 if (VERUS_MINTBLOCKS && pwallet != NULL)
3413 minerThreads->create_thread(boost::bind(&VerusStaker, pwallet));
3417 for (int i = 0; i < nThreads; i++) {
3418 #ifdef ENABLE_WALLET
3419 minerThreads->create_thread(boost::bind(&BitcoinMiner_noeq, pwallet));
3421 minerThreads->create_thread(&BitcoinMiner_noeq);
3426 #endif // ENABLE_MINING