UniValue generateBlocks(std::shared_ptr<CReserveScript> coinbaseScript, int nGenerate, uint64_t nMaxTries, bool keepScript) { static const int nInnerLoopCount = 0x10000; int nHeightEnd = 0; int nHeight = 0; unsigned int profile = 0x3; { // Don't keep cs_main locked LOCK(cs_main); nHeight = chainActive.Height(); nHeightEnd = nHeight+nGenerate; } unsigned int nExtraNonce = 0; UniValue blockHashes(UniValue::VARR); while (nHeight < nHeightEnd && !ShutdownRequested()) { std::unique_ptr<CBlockTemplate> pblocktemplate(BlockAssembler(Params()).CreateNewBlock(coinbaseScript->reserveScript)); if (!pblocktemplate.get()) throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block"); CBlock *pblock = &pblocktemplate->block; { LOCK(cs_main); IncrementExtraNonce(pblock, chainActive.Tip(), nExtraNonce); } if (pblock->GetBlockTime() >= Params().GetConsensus().nNeoScryptFork) profile = 0x0; while (nMaxTries > 0 && pblock->nNonce < nInnerLoopCount && !CheckProofOfWork(pblock->GetPoWHash(profile), pblock->nBits, Params().GetConsensus())) { ++pblock->nNonce; --nMaxTries; } if (nMaxTries == 0) { break; } if (pblock->nNonce == nInnerLoopCount) { continue; } std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(*pblock); if (!ProcessNewBlock(Params(), shared_pblock, true, nullptr)) throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted"); ++nHeight; blockHashes.push_back(pblock->GetHash().GetHex()); //mark script as important because it was used at least for one coinbase output if the script came from the wallet if (keepScript) { coinbaseScript->KeepScript(); } } return blockHashes; }
uint256 CreateBlockWithAppointedAddr(CKeyID const &keyID) { if (SysCfg().NetworkID() == CBaseParams::REGTEST) { // unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated(); mempool.GetTransactionsUpdated(); CBlockIndex* pindexPrev = chainActive.Tip(); CAccountViewCache accview(*pAccountViewTip, true); CTransactionDBCache txCache(*pTxCacheTip, true); CScriptDBViewCache ScriptDbTemp(*pScriptDBTip, true); shared_ptr<CBlockTemplate> pblocktemplate(CreateNewBlock(accview,txCache,ScriptDbTemp)); if (!pblocktemplate.get()) return uint256(); CBlock *pblock = &pblocktemplate.get()->block; // int nBlockSize = pblock->GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION); pblock->GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION); // int64_t nStart = GetTime(); while (true) { pblock->SetTime(max(pindexPrev->GetMedianTimePast() + 1, GetAdjustedTime())); set<CKeyID> setCreateKey; setCreateKey.clear(); setCreateKey.insert(keyID); if (CreatePosTx(pindexPrev, pblock,setCreateKey,accview,txCache,ScriptDbTemp)) { CheckWork(pblock, *pwalletMain); // int nBlockSize = pblock->GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION); } if(setCreateKey.empty()) { LogPrint("postx", "%s is not exist in the wallet\r\n",keyID.ToAddress()); break; } ::MilliSleep(1); if (pindexPrev != chainActive.Tip()) { return chainActive.Tip()->GetBlockHash() ; } } } return uint256(); }
void static HonghuoMiner(CWallet *pwallet,int targetConter) { LogPrint("INFO","Miner started\n"); SetThreadPriority(THREAD_PRIORITY_LOWEST); RenameThread("Honghuo-miner"); auto CheckIsHaveMinerKey = [&]() { LOCK2(cs_main, pwalletMain->cs_wallet); set<CKeyID> setMineKey; setMineKey.clear(); pwalletMain->GetKeys(setMineKey, true); return !setMineKey.empty(); }; if (!CheckIsHaveMinerKey()) { LogPrint("INFO", "HonghuoMiner terminated\n"); ERRORMSG("ERROR:%s ", "no key for minering\n"); return ; } auto getcurhigh = [&]() { LOCK(cs_main); return chainActive.Height(); }; targetConter = targetConter+getcurhigh(); try { SetMinerStatus(true); while (true) { if (SysCfg().NetworkID() != CBaseParams::REGTEST) { // Busy-wait for the network to come online so we don't waste time mining // on an obsolete chain. In regtest mode we expect to fly solo. while (vNodes.empty() || (chainActive.Tip() && chainActive.Tip()->nHeight>1 && GetAdjustedTime()-chainActive.Tip()->nTime > 60*60)) MilliSleep(1000); } // // Create new block // unsigned int LastTrsa = mempool.GetTransactionsUpdated(); CBlockIndex* pindexPrev = chainActive.Tip(); CAccountViewCache accview(*pAccountViewTip, true); CTransactionDBCache txCache(*pTxCacheTip, true); CScriptDBViewCache ScriptDbTemp(*pScriptDBTip, true); int64_t lasttime1 = GetTimeMillis(); shared_ptr<CBlockTemplate> pblocktemplate(CreateNewBlock(accview, txCache, ScriptDbTemp)); if (!pblocktemplate.get()){ throw runtime_error("Create new block fail."); } LogPrint("MINER", "CreateNewBlock tx count:%d used time :%d ms\n", pblocktemplate.get()->block.vptx.size(), GetTimeMillis() - lasttime1); CBlock *pblock = &pblocktemplate.get()->block; MiningBlock(pblock, pwallet, pindexPrev, LastTrsa, accview, txCache, ScriptDbTemp); if (SysCfg().NetworkID() != CBaseParams::MAIN) if(targetConter <= getcurhigh()) { throw boost::thread_interrupted(); } } } catch (...) { LogPrint("INFO","HonghuoMiner terminated\n"); SetMinerStatus(false); throw; } }
CBlockTemplate* CreateNewBlock(CAccountViewCache &view, CTransactionDBCache &txCache, CScriptDBViewCache &scriptCache){ // // Create new block auto_ptr<CBlockTemplate> pblocktemplate(new CBlockTemplate()); if (!pblocktemplate.get()) return NULL; CBlock *pblock = &pblocktemplate->block; // pointer for convenience // Create coinbase tx CRewardTransaction rtx; // Add our coinbase tx as first transaction pblock->vptx.push_back(make_shared<CRewardTransaction>(rtx)); pblocktemplate->vTxFees.push_back(-1); // updated at end pblocktemplate->vTxSigOps.push_back(-1); // updated at end // Largest block you're willing to create: unsigned int nBlockMaxSize = SysCfg().GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE); // Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity: nBlockMaxSize = max((unsigned int) 1000, min((unsigned int) (MAX_BLOCK_SIZE - 1000), nBlockMaxSize)); // How much of the block should be dedicated to high-priority transactions, // included regardless of the fees they pay unsigned int nBlockPrioritySize = SysCfg().GetArg("-blockprioritysize", DEFAULT_BLOCK_PRIORITY_SIZE); nBlockPrioritySize = min(nBlockMaxSize, nBlockPrioritySize); // Minimum block size you want to create; block will be filled with free transactions // until there are no more or the block reaches this size: unsigned int nBlockMinSize = SysCfg().GetArg("-blockminsize", DEFAULT_BLOCK_MIN_SIZE); nBlockMinSize = min(nBlockMaxSize, nBlockMinSize); // Collect memory pool transactions into the block int64_t nFees = 0; { LOCK2(cs_main, mempool.cs); CBlockIndex* pIndexPrev = chainActive.Tip(); pblock->SetFuelRate(GetElementForBurn(pIndexPrev)); // This vector will be sorted into a priority queue: vector<TxPriority> vecPriority; GetPriorityTx(vecPriority, pblock->GetFuelRate()); // Collect transactions into block uint64_t nBlockSize = ::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION); uint64_t nBlockTx(0); bool fSortedByFee(true); uint64_t nTotalRunStep(0); int64_t nTotalFuel(0); TxPriorityCompare comparer(fSortedByFee); make_heap(vecPriority.begin(), vecPriority.end(), comparer); while (!vecPriority.empty()) { // Take highest priority transaction off the priority queue: double dPriority = vecPriority.front().get<0>(); double dFeePerKb = vecPriority.front().get<1>(); shared_ptr<CBaseTransaction> stx = vecPriority.front().get<2>(); CBaseTransaction *pBaseTx = stx.get(); //const CTransaction& tx = *(vecPriority.front().get<2>()); pop_heap(vecPriority.begin(), vecPriority.end(), comparer); vecPriority.pop_back(); // Size limits unsigned int nTxSize = ::GetSerializeSize(*pBaseTx, SER_NETWORK, PROTOCOL_VERSION); if (nBlockSize + nTxSize >= nBlockMaxSize) continue; // Skip free transactions if we're past the minimum block size: if (fSortedByFee && (dFeePerKb < CTransaction::nMinRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize)) continue; // Prioritize by fee once past the priority size or we run out of high-priority // transactions: if (!fSortedByFee && ((nBlockSize + nTxSize >= nBlockPrioritySize) || !AllowFree(dPriority))) { fSortedByFee = true; comparer = TxPriorityCompare(fSortedByFee); make_heap(vecPriority.begin(), vecPriority.end(), comparer); } if(uint256() != std::move(txCache.IsContainTx(std::move(pBaseTx->GetHash())))) { LogPrint("INFO","CreatePosTx duplicate tx\n"); continue; } CTxUndo txundo; CValidationState state; if(pBaseTx->IsCoinBase()){ ERRORMSG("TX type is coin base tx error......"); // assert(0); //never come here } if (CONTRACT_TX == pBaseTx->nTxType) { LogPrint("vm", "tx hash=%s CreateNewBlock run contract\n", pBaseTx->GetHash().GetHex()); } CAccountViewCache viewTemp(view, true); CScriptDBViewCache scriptCacheTemp(scriptCache, true); pBaseTx->nFuelRate = pblock->GetFuelRate(); if (!pBaseTx->ExecuteTx(nBlockTx + 1, viewTemp, state, txundo, pIndexPrev->nHeight + 1, txCache, scriptCacheTemp)) { continue; } // Run step limits if(nTotalRunStep + pBaseTx->nRunStep >= MAX_BLOCK_RUN_STEP) continue; assert(viewTemp.Flush()); assert(scriptCacheTemp.Flush()); nFees += pBaseTx->GetFee(); nBlockSize += stx->GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION); nTotalRunStep += pBaseTx->nRunStep; nTotalFuel += pBaseTx->GetFuel(pblock->GetFuelRate()); nBlockTx++; pblock->vptx.push_back(stx); LogPrint("fuel", "miner total fuel:%d, tx fuel:%d runStep:%d fuelRate:%d txhash:%s\n",nTotalFuel, pBaseTx->GetFuel(pblock->GetFuelRate()), pBaseTx->nRunStep, pblock->GetFuelRate(), pBaseTx->GetHash().GetHex()); } nLastBlockTx = nBlockTx; nLastBlockSize = nBlockSize; LogPrint("INFO","CreateNewBlock(): total size %u\n", nBlockSize); assert(nFees-nTotalFuel >= 0); ((CRewardTransaction*) pblock->vptx[0].get())->rewardValue = nFees - nTotalFuel + GetBlockSubsidy(pIndexPrev->nHeight + 1); // Fill in header pblock->SetHashPrevBlock(pIndexPrev->GetBlockHash()); UpdateTime(*pblock, pIndexPrev); pblock->SetBits(GetNextWorkRequired(pIndexPrev, pblock)); pblock->SetNonce(0); pblock->SetHeight(pIndexPrev->nHeight + 1); pblock->SetFuel(nTotalFuel); } return pblocktemplate.release(); }