35 #include <boost/thread.hpp>
36 #include <boost/tuple/tuple.hpp>
72 typedef boost::tuple<double, CFeeRate, const CTransaction*>
TxPriority;
83 if (a.get<1>() ==
b.get<1>())
84 return a.get<0>() <
b.get<0>();
85 return a.get<1>() <
b.get<1>();
87 if (a.get<0>() ==
b.get<0>())
88 return a.get<1>() <
b.get<1>();
89 return a.get<0>() <
b.get<0>();
99 if (
Params().AllowMinDifficultyBlocks())
107 uint32_t nloopIdx = currentHeight;
108 while (nloopIdx >=
Params().START_POA_BLOCK()) {
109 if (
chainActive[nloopIdx]->GetBlockHeader().IsPoABlockByVersion()) {
114 if (nloopIdx <=
Params().START_POA_BLOCK()) {
122 audits.push_back(pos);
126 uint32_t start = nloopIdx;
127 if (start >
Params().START_POA_BLOCK()) {
131 throw std::runtime_error(
"Can't read block from disk");
133 uint32_t lastAuditedHeight = back.
height;
134 uint32_t nextAuditHeight = lastAuditedHeight + 1;
136 while (nextAuditHeight <= currentHeight) {
140 throw std::runtime_error(
"Can't read block from disk");
146 pos.
height = nextAuditHeight;
147 audits.push_back(pos);
150 if (audits.size() == (
size_t)
Params().MAX_NUM_POS_BLOCKS_AUDITED()) {
165 std::unique_ptr<CBlockTemplate> pblocktemplate(
new CBlockTemplate());
166 if (!pblocktemplate.get())
169 CBlock* pblock = &pblocktemplate->block;
178 const int nHeight = pindexPrev->
nHeight + 1;
184 if (
Params().MineBlocksOnDemand())
190 txNew.
vin[0].prevout.SetNull();
191 txNew.
vout.resize(1);
192 txNew.
vout[0].scriptPubKey = scriptPubKeyIn;
193 std::copy(txPub.
begin(), txPub.
end(), std::back_inserter(txNew.
vout[0].txPub));
194 std::copy(txPriv.
begin(), txPriv.
end(), std::back_inserter(txNew.
vout[0].txPriv));
198 txNew.
vout[0].nValue = nValue;
200 pblock->
vtx.push_back(txNew);
201 pblocktemplate->vTxFees.push_back(-1);
202 pblocktemplate->vTxSigOps.push_back(-1);
208 boost::this_thread::interruption_point();
212 int64_t nSearchTime = pblock->
nTime;
213 bool fStakeFound =
false;
215 unsigned int nTxNewTime = 0;
218 pblock->
nTime = nTxNewTime;
219 pblock->
vtx[0].vout[0].SetEmpty();
221 pblock->
vtx.push_back(copied);
236 unsigned int nBlockMaxSize =
GetArg(
"-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE);
238 unsigned int nBlockMaxSizeNetwork = MAX_BLOCK_SIZE_CURRENT;
239 nBlockMaxSize = std::max((
unsigned int)1000, std::min((nBlockMaxSizeNetwork - 1000), nBlockMaxSize));
243 unsigned int nBlockPrioritySize =
GetArg(
"-blockprioritysize", DEFAULT_BLOCK_PRIORITY_SIZE);
244 nBlockPrioritySize = std::min(nBlockMaxSize, nBlockPrioritySize);
248 unsigned int nBlockMinSize =
GetArg(
"-blockminsize", DEFAULT_BLOCK_MIN_SIZE);
249 nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize);
258 const int nHeight = pindexPrev->
nHeight + 1;
262 std::list<COrphan> vOrphan;
263 std::map<uint256, std::vector<COrphan*> > mapDependers;
264 bool fPrintPriority =
GetBoolArg(
"-printpriority",
false);
267 std::vector<TxPriority> vecPriority;
269 std::set<CKeyImage> keyImages;
270 for (std::map<uint256, CTxMemPoolEntry>::iterator mi =
mempool.
mapTx.begin();
276 bool fKeyImageCheck =
true;
281 fKeyImageCheck =
false;
291 if (!fKeyImageCheck) {
298 double dPriority = 0;
310 bool isDuplicate =
false;
313 if (keyImages.count(keyImage)) {
317 keyImages.insert(keyImage);
319 if (isDuplicate)
continue;
320 vecPriority.push_back(
TxPriority(dPriority, feeRate, &mi->second.GetTx()));
325 uint64_t nBlockSize = 1000;
326 uint64_t nBlockTx = 0;
327 int nBlockSigOps = 100;
328 bool fSortedByFee = (nBlockPrioritySize <= 0);
331 std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
333 std::vector<CBigNum> vBlockSerials;
334 std::vector<CBigNum> vTxSerials;
335 while (!vecPriority.empty()) {
337 double dPriority = vecPriority.front().get<0>();
338 CFeeRate feeRate = vecPriority.front().get<1>();
339 const CTransaction& tx = *(vecPriority.front().get<2>());
341 std::pop_heap(vecPriority.begin(), vecPriority.end(), comparer);
342 vecPriority.pop_back();
346 if (nBlockSize + nTxSize >= nBlockMaxSize)
351 double dPriorityDelta = 0;
355 if (fSortedByFee && (feeRate < customMinRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize))
361 ((nBlockSize + nTxSize >= nBlockPrioritySize) || !
AllowFree(dPriority))) {
364 std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
377 if (!
CheckInputs(tx, state, view,
true, MANDATORY_SCRIPT_VERIFY_FLAGS,
true))
386 pblock->
vtx.push_back(tx);
387 pblocktemplate->vTxFees.push_back(nTxFees);
388 pblocktemplate->vTxSigOps.push_back(0);
389 nBlockSize += nTxSize;
393 for (
const CBigNum& bnSerial : vTxSerials)
394 vBlockSerials.emplace_back(bnSerial);
396 if (fPrintPriority) {
397 LogPrintf(
"priority %.1f fee %s txid %s\n",
402 if (mapDependers.count(hash)) {
403 for (
COrphan* porphan : mapDependers[hash]) {
404 if (!porphan->setDependsOn.empty()) {
405 porphan->setDependsOn.erase(hash);
406 if (porphan->setDependsOn.empty()) {
407 vecPriority.push_back(
TxPriority(porphan->dPriority, porphan->feeRate, porphan->ptx));
408 std::push_heap(vecPriority.begin(), vecPriority.end(), comparer);
415 if (!fProofOfStake) {
420 if (txNew.
vout.size() > 1) {
421 pblock->
payee = txNew.
vout[1].scriptPubKey;
424 txNew.
vout[0].nValue = blockValue;
435 if (!fProofOfStake) {
436 pblock->
vtx[0].vout[0].nValue += nFees;
437 pblocktemplate->vTxFees[0] = nFees;
439 pblock->
vtx[1].vout[2].nValue += nFees;
440 pblocktemplate->vTxFees[0] = nFees;
446 unsigned char zeroBlind[32];
447 memset(zeroBlind, 0, 32);
450 nValue = pblock->
vtx[0].vout[0].nValue;
455 pblock->
vtx[1].vout[1].nValue += pblock->
vtx[1].vout[2].nValue;
456 pblock->
vtx[1].vout[2].SetEmpty();
457 sharedSec.
Set(pblock->
vtx[1].vout[1].txPub.begin(), pblock->
vtx[1].vout[1].txPub.end());
459 nValue = pblock->
vtx[1].vout[1].nValue;
460 pblock->
vtx[1].vout[1].commitment.clear();
467 LogPrintf(
"%s : failed to make Shnorr signature\n", __func__);
473 LogPrintf(
"%s: Failed to verify shnorr key image\n", __func__);
490 unsigned int nExtraNonce = 0;
494 LogPrintf(
"%s: Signing new block failed, computing private key \n", __func__);
495 if (pblock->
vtx.size() > 1 && pblock->
vtx[1].vout.size() > 1) {
499 LogPrintf(
"%s: Signing new block with UTXO key failed \n", __func__);
506 return pblocktemplate.release();
518 std::unique_ptr<CBlockTemplate> pblocktemplate(
new CBlockTemplate());
519 if (!pblocktemplate.get())
521 CBlock* pblock = &pblocktemplate->block;
527 txNew.
vin[0].prevout.SetNull();
528 txNew.
vout.resize(1);
531 txNew.
vout[0].scriptPubKey = scriptPubKeyIn;
532 std::copy(txPub.
begin(), txPub.
end(), std::back_inserter(txNew.
vout[0].txPub));
533 std::copy(txPriv.
begin(), txPriv.
end(), std::back_inserter(txNew.
vout[0].txPriv));
535 pblock->
vtx.push_back(txNew);
536 pblocktemplate->vTxFees.push_back(-1);
537 pblocktemplate->vTxSigOps.push_back(-1);
539 boost::this_thread::interruption_point();
563 pblock->
vtx[0].vout[0].nValue = nReward;
568 unsigned char zeroBlind[32];
569 memset(zeroBlind, 0, 32);
571 if (!pwallet->
CreateCommitment(zeroBlind, pblock->
vtx[0].vout[0].nValue, pblock->
vtx[0].vout[0].commitment)) {
572 LogPrintf(
"%s: unable to create commitment to 0\n", __func__);
579 const int nHeight = pindexPrev->
nHeight + 1;
583 if (nprevPoAHeight >=
Params().START_POA_BLOCK()) {
598 assert(txCoinbase.
vin[0].scriptSig.size() <= 100);
600 pblock->
vtx[0] = txCoinbase;
606 return pblocktemplate.release();
618 unsigned int nHeight = pindexPrev->
nHeight + 1;
621 assert(txCoinbase.
vin[0].scriptSig.size() <= 100);
623 pblock->
vtx[0] = txCoinbase;
646 if ((nHeightNext > nLastPOWBlock) && !fProofOfStake) {
647 LogPrintf(
"%s: Aborting PoW block creation during PoS phase\n", __func__);
654 return CreateNewBlock(scriptPubKey, txPub, priv, pwallet, fProofOfStake);
676 return error(
"PRCYcoinMiner : generated block is stale");
694 return error(
"PRCYcoinMiner : ProcessNewBlock, block not accepted");
704 bool fMintableCoins =
false;
705 int nMintableLastCheck = 0;
709 void BitcoinMiner(
CWallet* pwallet,
bool fProofOfStake)
717 unsigned int nExtraNonce = 0;
718 bool fLastLoopOrphan =
false;
723 if ((
GetTime() - nMintableLastCheck > 5 * 60))
725 nMintableLastCheck =
GetTime();
729 while (
vNodes.empty() || pwallet->
IsLocked() || !fMintableCoins ||
734 if (!fMintableCoins && (
GetTime() - nMintableLastCheck > 1 * 60))
736 nMintableLastCheck =
GetTime();
745 LogPrintf(
"Stopping staking or mining\n");
764 LogPrintf(
"%s: Exiting Proof of Work Mining Thread at height: %d\n",
782 std::unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey, pwallet, fProofOfStake));
783 if (!pblocktemplate.get())
786 CBlock* pblock = &pblocktemplate->block;
793 LogPrintf(
"%s: Signing new block failed, computing private key \n", __func__);
794 if (pblock->
vtx.size() > 1 && pblock->
vtx[1].vout.size() > 1) {
798 LogPrintf(
"%s: Signing new block with UTXO key failed \n", __func__);
805 if (!ProcessBlockFound(pblock, *pwallet, reservekey)) {
822 unsigned int nHashesDone = 0;
827 if (hash <= hashTarget) {
830 ProcessBlockFound(pblock, *pwallet, reservekey);
831 if (!ProcessBlockFound(pblock, *pwallet, reservekey)) {
832 fLastLoopOrphan =
true;
839 if (
Params().MineBlocksOnDemand()) {
840 throw boost::thread_interrupted();
847 if ((pblock->
nNonce & 0xFF) == 0)
852 static int64_t nHashCounter;
857 nHashCounter += nHashesDone;
866 static int64_t nLogTime;
867 if (
GetTime() - nLogTime > 30 * 60) {
876 boost::this_thread::interruption_point();
880 if (pblock->
nNonce >= 0xffff0000)
889 if (
Params().AllowMinDifficultyBlocks()) {
897 void static ThreadBitcoinMiner(
void* parg)
899 boost::this_thread::interruption_point();
903 BitcoinMiner(pwallet,
true);
905 BitcoinMiner(pwallet,
false);
907 boost::this_thread::interruption_point();
908 }
catch (
const std::exception& e) {
917 void static ThreadPrcycoinMiner(
void* parg)
919 boost::this_thread::interruption_point();
923 boost::this_thread::sleep_for(boost::chrono::milliseconds(180 * 1000));
926 boost::this_thread::interruption_point();
927 }
catch (
const std::exception& e) {
928 LogPrintf(
"ThreadBitcoinMiner() exception: %s \n", e.what());
930 LogPrintf(
"ThreadBitcoinMiner() error \n");
933 LogPrintf(
"ThreadBitcoinMiner exiting\n");
936 void GeneratePoAPrcycoin(
CWallet* pwallet,
int period)
938 static boost::thread_group* minerThreads = NULL;
940 if (minerThreads != NULL) {
941 minerThreads->interrupt_all();
946 minerThreads =
new boost::thread_group();
947 minerThreads->create_thread(boost::bind(&ThreadPrcycoinMiner, pwallet));
950 void GeneratePrcycoins(
bool fGenerate,
CWallet* pwallet,
int nThreads)
952 static boost::thread_group* minerThreads = NULL;
957 if (
Params().DefaultMinerThreads())
960 nThreads = boost::thread::hardware_concurrency();
963 if (minerThreads != NULL) {
964 minerThreads->interrupt_all();
969 if (nThreads == 0 || !fGenerate)
972 minerThreads =
new boost::thread_group();
973 for (
int i = 0; i < nThreads; i++)
974 minerThreads->create_thread(boost::bind(&ThreadBitcoinMiner, pwallet));
978 void ThreadStakeMinter()
980 boost::this_thread::interruption_point();
981 LogPrintf(
"ThreadStakeMinter started\n");
984 BitcoinMiner(pwallet,
true);
985 boost::this_thread::interruption_point();
986 }
catch (
const std::exception& e) {
987 LogPrintf(
"ThreadStakeMinter() exception: %s \n", e.what());
989 LogPrintf(
"ThreadStakeMinter() error \n");
991 LogPrintf(
"ThreadStakeMinter exiting,\n");
994 #endif // ENABLE_WALLET