Changeset View
Changeset View
Standalone View
Standalone View
src/miner.cpp
Show First 20 Lines • Show All 111 Lines • ▼ Show 20 Lines | void BlockAssembler::resetBlock() { | ||||
nBlockSize = 1000; | nBlockSize = 1000; | ||||
nBlockSigOps = 100; | nBlockSigOps = 100; | ||||
// These counters do not include coinbase tx. | // These counters do not include coinbase tx. | ||||
nBlockTx = 0; | nBlockTx = 0; | ||||
nFees = Amount(0); | nFees = Amount(0); | ||||
lastFewTxs = 0; | lastFewTxs = 0; | ||||
blockFinished = false; | |||||
} | } | ||||
static const std::vector<uint8_t> | static const std::vector<uint8_t> | ||||
getExcessiveBlockSizeSig(const Config &config) { | getExcessiveBlockSizeSig(const Config &config) { | ||||
std::string cbmsg = "/EB" + getSubVersionEB(config.GetMaxBlockSize()) + "/"; | std::string cbmsg = "/EB" + getSubVersionEB(config.GetMaxBlockSize()) + "/"; | ||||
const char *cbcstr = cbmsg.c_str(); | const char *cbcstr = cbmsg.c_str(); | ||||
std::vector<uint8_t> vec(cbcstr, cbcstr + cbmsg.size()); | std::vector<uint8_t> vec(cbcstr, cbcstr + cbmsg.size()); | ||||
return vec; | return vec; | ||||
▲ Show 20 Lines • Show All 163 Lines • ▼ Show 20 Lines | for (const CTxMemPool::txiter it : package) { | ||||
} | } | ||||
nPotentialBlockSize += nTxSize; | nPotentialBlockSize += nTxSize; | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
bool BlockAssembler::TestForBlock(CTxMemPool::txiter it) { | struct TestForBlockResult { | ||||
bool addedTransaction; | |||||
bool blockFinished; | |||||
}; | |||||
TestForBlockResult BlockAssembler::TestForBlock(CTxMemPool::txiter it) { | |||||
auto blockSizeWithTx = | auto blockSizeWithTx = | ||||
nBlockSize + | nBlockSize + | ||||
::GetSerializeSize(it->GetTx(), SER_NETWORK, PROTOCOL_VERSION); | ::GetSerializeSize(it->GetTx(), SER_NETWORK, PROTOCOL_VERSION); | ||||
if (blockSizeWithTx >= nMaxGeneratedBlockSize) { | if (blockSizeWithTx >= nMaxGeneratedBlockSize) { | ||||
if (nBlockSize > nMaxGeneratedBlockSize - 100 || lastFewTxs > 50) { | if (nBlockSize > nMaxGeneratedBlockSize - 100 || lastFewTxs > 50) { | ||||
blockFinished = true; | return {false, true}; | ||||
return false; | |||||
} | } | ||||
if (nBlockSize > nMaxGeneratedBlockSize - 1000) { | if (nBlockSize > nMaxGeneratedBlockSize - 1000) { | ||||
lastFewTxs++; | lastFewTxs++; | ||||
} | } | ||||
return false; | return {false, false}; | ||||
} | } | ||||
auto maxBlockSigOps = GetMaxBlockSigOpsCount(blockSizeWithTx); | auto maxBlockSigOps = GetMaxBlockSigOpsCount(blockSizeWithTx); | ||||
if (nBlockSigOps + it->GetSigOpCount() >= maxBlockSigOps) { | if (nBlockSigOps + it->GetSigOpCount() >= maxBlockSigOps) { | ||||
// If the block has room for no more sig ops then flag that the block is | // If the block has room for no more sig ops then flag that the block is | ||||
// finished. | // finished. | ||||
// TODO: We should consider adding another transaction that isn't very | // TODO: We should consider adding another transaction that isn't very | ||||
// dense in sigops instead of bailing out so easily. | // dense in sigops instead of bailing out so easily. | ||||
if (nBlockSigOps > maxBlockSigOps - 2) { | if (nBlockSigOps > maxBlockSigOps - 2) { | ||||
blockFinished = true; | return {false, true}; | ||||
return false; | |||||
} | } | ||||
// Otherwise attempt to find another tx with fewer sigops to put in the | // Otherwise attempt to find another tx with fewer sigops to put in the | ||||
// block. | // block. | ||||
return false; | return {false, false}; | ||||
; | |||||
} | } | ||||
// Must check that lock times are still valid. This can be removed once MTP | // Must check that lock times are still valid. This can be removed once MTP | ||||
// is always enforced as long as reorgs keep the mempool consistent. | // is always enforced as long as reorgs keep the mempool consistent. | ||||
CValidationState state; | CValidationState state; | ||||
if (!ContextualCheckTransaction(*config, it->GetTx(), state, nHeight, | if (!ContextualCheckTransaction(*config, it->GetTx(), state, nHeight, | ||||
nLockTimeCutoff)) { | nLockTimeCutoff)) { | ||||
return false; | return {false, false}; | ||||
} | } | ||||
return true; | return {true, false}; | ||||
} | } | ||||
void BlockAssembler::AddToBlock(CTxMemPool::txiter iter) { | void BlockAssembler::AddToBlock(CTxMemPool::txiter iter) { | ||||
pblock->vtx.emplace_back(iter->GetSharedTx()); | pblock->vtx.emplace_back(iter->GetSharedTx()); | ||||
pblocktemplate->vTxFees.push_back(iter->GetFee()); | pblocktemplate->vTxFees.push_back(iter->GetFee()); | ||||
pblocktemplate->vTxSigOpsCount.push_back(iter->GetSigOpCount()); | pblocktemplate->vTxSigOpsCount.push_back(iter->GetSigOpCount()); | ||||
nBlockSize += iter->GetTxSize(); | nBlockSize += iter->GetTxSize(); | ||||
++nBlockTx; | ++nBlockTx; | ||||
▲ Show 20 Lines • Show All 253 Lines • ▼ Show 20 Lines | for (CTxMemPool::indexed_transaction_set::iterator mi = | ||||
vecPriority.push_back(TxCoinAgePriority(dPriority, mi)); | vecPriority.push_back(TxCoinAgePriority(dPriority, mi)); | ||||
} | } | ||||
std::make_heap(vecPriority.begin(), vecPriority.end(), pricomparer); | std::make_heap(vecPriority.begin(), vecPriority.end(), pricomparer); | ||||
CTxMemPool::txiter iter; | CTxMemPool::txiter iter; | ||||
// Add a tx from priority queue to fill the part of block reserved to | // Add a tx from priority queue to fill the part of block reserved to | ||||
// priority transactions. | // priority transactions. | ||||
while (!vecPriority.empty() && !blockFinished) { | while (!vecPriority.empty()) { | ||||
iter = vecPriority.front().second; | iter = vecPriority.front().second; | ||||
actualPriority = vecPriority.front().first; | actualPriority = vecPriority.front().first; | ||||
std::pop_heap(vecPriority.begin(), vecPriority.end(), pricomparer); | std::pop_heap(vecPriority.begin(), vecPriority.end(), pricomparer); | ||||
vecPriority.pop_back(); | vecPriority.pop_back(); | ||||
// If tx already in block, skip. | // If tx already in block, skip. | ||||
if (inBlock.count(iter)) { | if (inBlock.count(iter)) { | ||||
// Shouldn't happen for priority txs. | // Shouldn't happen for priority txs. | ||||
assert(false); | assert(false); | ||||
continue; | continue; | ||||
} | } | ||||
// If tx is dependent on other mempool txs which haven't yet been | // If tx is dependent on other mempool txs which haven't yet been | ||||
// included then put it in the waitSet. | // included then put it in the waitSet. | ||||
if (isStillDependent(iter)) { | if (isStillDependent(iter)) { | ||||
waitPriMap.insert(std::make_pair(iter, actualPriority)); | waitPriMap.insert(std::make_pair(iter, actualPriority)); | ||||
continue; | continue; | ||||
} | } | ||||
// If this tx fits in the block add it, otherwise keep looping. | // If this tx fits in the block add it, otherwise keep looping. | ||||
if (!TestForBlock(iter)) { | TestForBlockResult testResult = TestForBlock(iter); | ||||
if (!testResult.addedTransaction) { | |||||
continue; | continue; | ||||
} | } | ||||
// Or break if the block is completed | |||||
if (!testResult.blockFinished) { | |||||
break; | |||||
} | |||||
AddToBlock(iter); | AddToBlock(iter); | ||||
// If now that this txs is added we've surpassed our desired priority | // If now that this txs is added we've surpassed our desired priority | ||||
// size, then we're done adding priority transactions. | // size, then we're done adding priority transactions. | ||||
if (nBlockSize >= nBlockPrioritySize) { | if (nBlockSize >= nBlockPrioritySize) { | ||||
break; | break; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 44 Lines • Show Last 20 Lines |