Changeset View
Changeset View
Standalone View
Standalone View
src/miner.cpp
Show First 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | int64_t UpdateTime(CBlockHeader *pblock, const Consensus::Params ¶ms, | ||||
} | } | ||||
return nNewTime - nOldTime; | return nNewTime - nOldTime; | ||||
} | } | ||||
BlockAssembler::Options::Options() | BlockAssembler::Options::Options() | ||||
: nExcessiveBlockSize(DEFAULT_MAX_BLOCK_SIZE), | : nExcessiveBlockSize(DEFAULT_MAX_BLOCK_SIZE), | ||||
nMaxGeneratedBlockSize(DEFAULT_MAX_GENERATED_BLOCK_SIZE), | nMaxGeneratedBlockSize(DEFAULT_MAX_GENERATED_BLOCK_SIZE), | ||||
blockMinFeeRate(DEFAULT_BLOCK_MIN_TX_FEE_PER_KB), | blockMinFeeRate(DEFAULT_BLOCK_MIN_TX_FEE_PER_KB) {} | ||||
nBlockPriorityPercentage(DEFAULT_BLOCK_PRIORITY_PERCENTAGE) {} | |||||
BlockAssembler::BlockAssembler(const CChainParams ¶ms, | BlockAssembler::BlockAssembler(const CChainParams ¶ms, | ||||
const CTxMemPool &_mempool, | const CTxMemPool &_mempool, | ||||
const Options &options) | const Options &options) | ||||
: chainparams(params), mempool(&_mempool) { | : chainparams(params), mempool(&_mempool) { | ||||
blockMinFeeRate = options.blockMinFeeRate; | blockMinFeeRate = options.blockMinFeeRate; | ||||
// Limit size to between 1K and options.nExcessiveBlockSize -1K for sanity: | // Limit size to between 1K and options.nExcessiveBlockSize -1K for sanity: | ||||
nMaxGeneratedBlockSize = std::max<uint64_t>( | nMaxGeneratedBlockSize = std::max<uint64_t>( | ||||
1000, std::min<uint64_t>(options.nExcessiveBlockSize - 1000, | 1000, std::min<uint64_t>(options.nExcessiveBlockSize - 1000, | ||||
options.nMaxGeneratedBlockSize)); | options.nMaxGeneratedBlockSize)); | ||||
// Reserve a portion of the block for high priority transactions. | |||||
nBlockPriorityPercentage = options.nBlockPriorityPercentage; | |||||
} | } | ||||
static BlockAssembler::Options DefaultOptions(const Config &config) { | static BlockAssembler::Options DefaultOptions(const Config &config) { | ||||
// Block resource limits | // Block resource limits | ||||
// If -blockmaxsize is not given, limit to DEFAULT_MAX_GENERATED_BLOCK_SIZE | // If -blockmaxsize is not given, limit to DEFAULT_MAX_GENERATED_BLOCK_SIZE | ||||
// If only one is given, only restrict the specified resource. | // If only one is given, only restrict the specified resource. | ||||
// If both are given, restrict both. | // If both are given, restrict both. | ||||
BlockAssembler::Options options; | BlockAssembler::Options options; | ||||
options.nExcessiveBlockSize = config.GetMaxBlockSize(); | options.nExcessiveBlockSize = config.GetMaxBlockSize(); | ||||
if (gArgs.IsArgSet("-blockmaxsize")) { | if (gArgs.IsArgSet("-blockmaxsize")) { | ||||
options.nMaxGeneratedBlockSize = | options.nMaxGeneratedBlockSize = | ||||
gArgs.GetArg("-blockmaxsize", DEFAULT_MAX_GENERATED_BLOCK_SIZE); | gArgs.GetArg("-blockmaxsize", DEFAULT_MAX_GENERATED_BLOCK_SIZE); | ||||
} | } | ||||
Amount n = Amount::zero(); | Amount n = Amount::zero(); | ||||
if (gArgs.IsArgSet("-blockmintxfee") && | if (gArgs.IsArgSet("-blockmintxfee") && | ||||
ParseMoney(gArgs.GetArg("-blockmintxfee", ""), n)) { | ParseMoney(gArgs.GetArg("-blockmintxfee", ""), n)) { | ||||
options.blockMinFeeRate = CFeeRate(n); | options.blockMinFeeRate = CFeeRate(n); | ||||
} | } | ||||
options.nBlockPriorityPercentage = config.GetBlockPriorityPercentage(); | |||||
return options; | return options; | ||||
} | } | ||||
BlockAssembler::BlockAssembler(const Config &config, const CTxMemPool &_mempool) | BlockAssembler::BlockAssembler(const Config &config, const CTxMemPool &_mempool) | ||||
: BlockAssembler(config.GetChainParams(), _mempool, | : BlockAssembler(config.GetChainParams(), _mempool, | ||||
DefaultOptions(config)) {} | DefaultOptions(config)) {} | ||||
void BlockAssembler::resetBlock() { | void BlockAssembler::resetBlock() { | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | BlockAssembler::CreateNewBlock(const CScript &scriptPubKeyIn) { | ||||
pblock->nTime = GetAdjustedTime(); | pblock->nTime = GetAdjustedTime(); | ||||
nMedianTimePast = pindexPrev->GetMedianTimePast(); | nMedianTimePast = pindexPrev->GetMedianTimePast(); | ||||
nLockTimeCutoff = | nLockTimeCutoff = | ||||
(STANDARD_LOCKTIME_VERIFY_FLAGS & LOCKTIME_MEDIAN_TIME_PAST) | (STANDARD_LOCKTIME_VERIFY_FLAGS & LOCKTIME_MEDIAN_TIME_PAST) | ||||
? nMedianTimePast | ? nMedianTimePast | ||||
: pblock->GetBlockTime(); | : pblock->GetBlockTime(); | ||||
addPriorityTxs(); | |||||
int nPackagesSelected = 0; | int nPackagesSelected = 0; | ||||
int nDescendantsUpdated = 0; | int nDescendantsUpdated = 0; | ||||
addPackageTxs(nPackagesSelected, nDescendantsUpdated); | addPackageTxs(nPackagesSelected, nDescendantsUpdated); | ||||
if (IsMagneticAnomalyEnabled(chainparams.GetConsensus(), pindexPrev)) { | if (IsMagneticAnomalyEnabled(chainparams.GetConsensus(), pindexPrev)) { | ||||
// If magnetic anomaly is enabled, we make sure transaction are | // If magnetic anomaly is enabled, we make sure transaction are | ||||
// canonically ordered. | // canonically ordered. | ||||
// FIXME: Use a zipped list. See T479 | // FIXME: Use a zipped list. See T479 | ||||
▲ Show 20 Lines • Show All 408 Lines • ▼ Show 20 Lines | while (mi != mempool->mapTx.get<ancestor_score>().end() || | ||||
++nPackagesSelected; | ++nPackagesSelected; | ||||
// Update transactions that depend on each of these | // Update transactions that depend on each of these | ||||
nDescendantsUpdated += UpdatePackagesForAdded(ancestors, mapModifiedTx); | nDescendantsUpdated += UpdatePackagesForAdded(ancestors, mapModifiedTx); | ||||
} | } | ||||
} | } | ||||
void BlockAssembler::addPriorityTxs() { | |||||
// How much of the block should be dedicated to high-priority transactions. | |||||
if (nBlockPriorityPercentage == 0) { | |||||
return; | |||||
} | |||||
uint64_t nBlockPrioritySize = | |||||
nMaxGeneratedBlockSize * nBlockPriorityPercentage / 100; | |||||
// This vector will be sorted into a priority queue: | |||||
std::vector<TxCoinAgePriority> vecPriority; | |||||
TxCoinAgePriorityCompare pricomparer; | |||||
std::map<CTxMemPool::txiter, double, CTxMemPool::CompareIteratorByHash> | |||||
waitPriMap; | |||||
typedef std::map<CTxMemPool::txiter, double, | |||||
CTxMemPool::CompareIteratorByHash>::iterator waitPriIter; | |||||
double actualPriority = -1; | |||||
vecPriority.reserve(mempool->mapTx.size()); | |||||
for (CTxMemPool::indexed_transaction_set::iterator mi = | |||||
mempool->mapTx.begin(); | |||||
mi != mempool->mapTx.end(); ++mi) { | |||||
double dPriority = mi->GetPriority(nHeight); | |||||
Amount dummy; | |||||
mempool->ApplyDeltas(mi->GetTx().GetId(), dPriority, dummy); | |||||
vecPriority.push_back(TxCoinAgePriority(dPriority, mi)); | |||||
} | |||||
std::make_heap(vecPriority.begin(), vecPriority.end(), pricomparer); | |||||
CTxMemPool::txiter iter; | |||||
// Add a tx from priority queue to fill the part of block reserved to | |||||
// priority transactions. | |||||
while (!vecPriority.empty()) { | |||||
iter = vecPriority.front().second; | |||||
actualPriority = vecPriority.front().first; | |||||
std::pop_heap(vecPriority.begin(), vecPriority.end(), pricomparer); | |||||
vecPriority.pop_back(); | |||||
// If tx already in block, skip. | |||||
if (inBlock.count(iter)) { | |||||
// Shouldn't happen for priority txs. | |||||
assert(false); | |||||
continue; | |||||
} | |||||
// If tx is dependent on other mempool txs which haven't yet been | |||||
// included then put it in the waitSet. | |||||
if (isStillDependent(iter)) { | |||||
waitPriMap.insert(std::make_pair(iter, actualPriority)); | |||||
continue; | |||||
} | |||||
TestForBlockResult testResult = TestForBlock(iter); | |||||
// Break if the block is completed | |||||
if (testResult == TestForBlockResult::BlockFinished) { | |||||
break; | |||||
} | |||||
// If this tx does not fit in the block, skip to next transaction. | |||||
if (testResult != TestForBlockResult::TXFits) { | |||||
continue; | |||||
} | |||||
AddToBlock(iter); | |||||
// If now that this txs is added we've surpassed our desired priority | |||||
// size, then we're done adding priority transactions. | |||||
if (nBlockSize >= nBlockPrioritySize) { | |||||
break; | |||||
} | |||||
// This tx was successfully added, so add transactions that depend | |||||
// on this one to the priority queue to try again. | |||||
for (CTxMemPool::txiter child : mempool->GetMemPoolChildren(iter)) { | |||||
waitPriIter wpiter = waitPriMap.find(child); | |||||
if (wpiter == waitPriMap.end()) { | |||||
continue; | |||||
} | |||||
vecPriority.push_back(TxCoinAgePriority(wpiter->second, child)); | |||||
std::push_heap(vecPriority.begin(), vecPriority.end(), pricomparer); | |||||
waitPriMap.erase(wpiter); | |||||
} | |||||
} | |||||
} | |||||
static const std::vector<uint8_t> | static const std::vector<uint8_t> | ||||
getExcessiveBlockSizeSig(uint64_t nExcessiveBlockSize) { | getExcessiveBlockSizeSig(uint64_t nExcessiveBlockSize) { | ||||
std::string cbmsg = "/EB" + getSubVersionEB(nExcessiveBlockSize) + "/"; | std::string cbmsg = "/EB" + getSubVersionEB(nExcessiveBlockSize) + "/"; | ||||
std::vector<uint8_t> vec(cbmsg.begin(), cbmsg.end()); | std::vector<uint8_t> vec(cbmsg.begin(), cbmsg.end()); | ||||
return vec; | return vec; | ||||
} | } | ||||
void IncrementExtraNonce(CBlock *pblock, const CBlockIndex *pindexPrev, | void IncrementExtraNonce(CBlock *pblock, const CBlockIndex *pindexPrev, | ||||
Show All 31 Lines |