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