Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 5 additions & 23 deletions doc/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,29 +183,11 @@ The command line option `-blockmaxsize` remains an option to specify the
maximum number of serialized bytes in a generated block. In addition, the new
command line option `-blockmaxweight` has been added, which specifies the
maximum "block weight" of a generated block, as defined by [BIP 141 (Segregated
Witness)] (https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki).

In preparation for Segregated Witness, the mining algorithm has been modified
to optimize transaction selection for a given block weight, rather than a given
number of serialized bytes in a block. In this release, transaction selection
is unaffected by this distinction (as BIP 141 activation is not supported on
mainnet in this release, see above), but in future releases and after BIP 141
activation, these calculations would be expected to differ.

For optimal runtime performance, miners using this release should specify
`-blockmaxweight` on the command line, and not specify `-blockmaxsize`.
Additionally (or only) specifying `-blockmaxsize`, or relying on default
settings for both, may result in performance degradation, as the logic to
support `-blockmaxsize` performs additional computation to ensure that
constraint is met. (Note that for mainnet, in this release, the equivalent
parameter for `-blockmaxweight` would be four times the desired
`-blockmaxsize`. See [BIP 141]
(https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki) for additional
details.)

In the future, the `-blockmaxsize` option may be removed, as block creation is
no longer optimized for this metric. Feedback is requested on whether to
deprecate or keep this command line option in future releases.
Witness)] (https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki). In
this release, transaction selection is only affected by this distinction for
testnet (as BIP 141 activation is not supported on mainnet in this release, see
above), but in future releases and after BIP 141 activation, these calculations
would be expected to differ.


Removal of internal miner
Expand Down
32 changes: 11 additions & 21 deletions src/miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,6 @@ BlockAssembler::BlockAssembler(const CChainParams& _chainparams)
nBlockMaxWeight = std::max((unsigned int)4000, std::min((unsigned int)(MAX_BLOCK_WEIGHT-4000), nBlockMaxWeight));
// Limit size to between 1K and MAX_BLOCK_SERIALIZED_SIZE-1K for sanity:
nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SERIALIZED_SIZE-1000), nBlockMaxSize));

// Whether we need to account for byte usage (in addition to weight usage)
fNeedSizeAccounting = (nBlockMaxSize < MAX_BLOCK_SERIALIZED_SIZE-1000);
}

void BlockAssembler::resetBlock()
Expand Down Expand Up @@ -221,11 +218,13 @@ void BlockAssembler::onlyUnconfirmed(CTxMemPool::setEntries& testSet)
}
}

bool BlockAssembler::TestPackage(uint64_t packageSize, int64_t packageSigOpsCost)
bool BlockAssembler::TestPackage(uint64_t packageSize, int64_t packageSigOpsCost, uint64_t packageRealSize)
{
// TODO: switch to weight-based accounting for packages instead of vsize-based accounting.
if (nBlockWeight + WITNESS_SCALE_FACTOR * packageSize >= nBlockMaxWeight)
return false;
if (nBlockSize + packageRealSize >= nBlockMaxSize)
return false;
if (nBlockSigOpsCost + packageSigOpsCost >= MAX_BLOCK_SIGOPS_COST)
return false;
return true;
Expand All @@ -238,19 +237,11 @@ bool BlockAssembler::TestPackage(uint64_t packageSize, int64_t packageSigOpsCost
// - serialized size (in case -blockmaxsize is in use)
bool BlockAssembler::TestPackageTransactions(const CTxMemPool::setEntries& package)
{
uint64_t nPotentialBlockSize = nBlockSize; // only used with fNeedSizeAccounting
BOOST_FOREACH (const CTxMemPool::txiter it, package) {
if (!IsFinalTx(it->GetTx(), nHeight, nLockTimeCutoff))
return false;
if (!fIncludeWitness && !it->GetTx().wit.IsNull())
return false;
if (fNeedSizeAccounting) {
uint64_t nTxSize = ::GetSerializeSize(it->GetTx(), SER_NETWORK, PROTOCOL_VERSION);
if (nPotentialBlockSize + nTxSize >= nBlockMaxSize) {
return false;
}
nPotentialBlockSize += nTxSize;
}
}
return true;
}
Expand All @@ -273,8 +264,8 @@ bool BlockAssembler::TestForBlock(CTxMemPool::txiter iter)
return false;
}

if (fNeedSizeAccounting) {
if (nBlockSize + ::GetSerializeSize(iter->GetTx(), SER_NETWORK, PROTOCOL_VERSION) >= nBlockMaxSize) {
{
if (nBlockSize + iter->GetRealTxSize() >= nBlockMaxSize) {
if (nBlockSize > nBlockMaxSize - 100 || lastFewTxs > 50) {
blockFinished = true;
return false;
Expand Down Expand Up @@ -312,8 +303,8 @@ void BlockAssembler::AddToBlock(CTxMemPool::txiter iter)
pblock->vtx.push_back(iter->GetTx());
pblocktemplate->vTxFees.push_back(iter->GetFee());
pblocktemplate->vTxSigOpsCost.push_back(iter->GetSigOpCost());
if (fNeedSizeAccounting) {
nBlockSize += ::GetSerializeSize(iter->GetTx(), SER_NETWORK, PROTOCOL_VERSION);
{
nBlockSize += iter->GetRealTxSize();
}
nBlockWeight += iter->GetTxWeight();
++nBlockTx;
Expand Down Expand Up @@ -346,6 +337,7 @@ void BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& alread
modtxiter mit = mapModifiedTx.find(desc);
if (mit == mapModifiedTx.end()) {
CTxMemPoolModifiedEntry modEntry(desc);
modEntry.nRealSizeWithAncestors -= it->GetRealTxSize();
modEntry.nSizeWithAncestors -= it->GetTxSize();
modEntry.nModFeesWithAncestors -= it->GetModifiedFee();
modEntry.nSigOpCostWithAncestors -= it->GetSigOpCost();
Expand Down Expand Up @@ -448,10 +440,12 @@ void BlockAssembler::addPackageTxs()
// contain anything that is inBlock.
assert(!inBlock.count(iter));

uint64_t packageRealSize = iter->GetRealSizeWithAncestors();
uint64_t packageSize = iter->GetSizeWithAncestors();
CAmount packageFees = iter->GetModFeesWithAncestors();
int64_t packageSigOpsCost = iter->GetSigOpCostWithAncestors();
if (fUsingModified) {
packageRealSize = modit->nRealSizeWithAncestors;
packageSize = modit->nSizeWithAncestors;
packageFees = modit->nModFeesWithAncestors;
packageSigOpsCost = modit->nSigOpCostWithAncestors;
Expand All @@ -462,7 +456,7 @@ void BlockAssembler::addPackageTxs()
return;
}

if (!TestPackage(packageSize, packageSigOpsCost)) {
if (!TestPackage(packageSize, packageSigOpsCost, packageRealSize)) {
if (fUsingModified) {
// Since we always look at the best entry in mapModifiedTx,
// we must erase failed entries so that we can consider the
Expand Down Expand Up @@ -516,9 +510,6 @@ void BlockAssembler::addPriorityTxs()
return;
}

bool fSizeAccounting = fNeedSizeAccounting;
fNeedSizeAccounting = true;

// This vector will be sorted into a priority queue:
vector<TxCoinAgePriority> vecPriority;
TxCoinAgePriorityCompare pricomparer;
Expand Down Expand Up @@ -584,7 +575,6 @@ void BlockAssembler::addPriorityTxs()
}
}
}
fNeedSizeAccounting = fSizeAccounting;
}

void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nExtraNonce)
Expand Down
4 changes: 3 additions & 1 deletion src/miner.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,14 @@ struct CTxMemPoolModifiedEntry {
CTxMemPoolModifiedEntry(CTxMemPool::txiter entry)
{
iter = entry;
nRealSizeWithAncestors = entry->GetRealSizeWithAncestors();
nSizeWithAncestors = entry->GetSizeWithAncestors();
nModFeesWithAncestors = entry->GetModFeesWithAncestors();
nSigOpCostWithAncestors = entry->GetSigOpCostWithAncestors();
}

CTxMemPool::txiter iter;
uint64_t nRealSizeWithAncestors;
uint64_t nSizeWithAncestors;
CAmount nModFeesWithAncestors;
int64_t nSigOpCostWithAncestors;
Expand Down Expand Up @@ -189,7 +191,7 @@ class BlockAssembler
/** Remove confirmed (inBlock) entries from given set */
void onlyUnconfirmed(CTxMemPool::setEntries& testSet);
/** Test if a new package would "fit" in the block */
bool TestPackage(uint64_t packageSize, int64_t packageSigOpsCost);
bool TestPackage(uint64_t packageSize, int64_t packageSigOpsCost, uint64_t packageRealSize);
/** Perform checks on each transaction in a package:
* locktime, premature-witness, serialized size (if necessary)
* These checks should always succeed, and they're here
Expand Down
20 changes: 16 additions & 4 deletions src/txmempool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
hadNoDependencies(poolHasNoInputsOf), inChainInputValue(_inChainInputValue),
spendsCoinbase(_spendsCoinbase), sigOpCost(_sigOpsCost), lockPoints(lp)
{
nTxSize = ::GetSerializeSize(_tx, SER_NETWORK, PROTOCOL_VERSION);
nTxWeight = GetTransactionWeight(_tx);
nModSize = _tx.CalculateModifiedSize(GetTxSize());
nUsageSize = RecursiveDynamicUsage(*tx) + memusage::DynamicUsage(tx);
Expand All @@ -42,6 +43,7 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,

nCountWithAncestors = 1;
nSizeWithAncestors = GetTxSize();
nRealSizeWithAncestors = GetRealTxSize();
nModFeesWithAncestors = nFee;
nSigOpCostWithAncestors = sigOpCost;
}
Expand Down Expand Up @@ -78,6 +80,11 @@ size_t CTxMemPoolEntry::GetTxSize() const
return GetVirtualTransactionSize(nTxWeight);
}

size_t CTxMemPoolEntry::GetRealTxSize() const
{
return nTxSize;
}

// Update the given tx for any in-mempool descendants.
// Assumes that setMemPoolChildren is correct for the given tx and all
// descendants.
Expand Down Expand Up @@ -117,7 +124,7 @@ void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap &cachedDescendan
modifyCount++;
cachedDescendants[updateIt].insert(cit);
// Update ancestor state for each descendant
mapTx.modify(cit, update_ancestor_state(updateIt->GetTxSize(), updateIt->GetModifiedFee(), 1, updateIt->GetSigOpCost()));
mapTx.modify(cit, update_ancestor_state(updateIt->GetTxSize(), updateIt->GetModifiedFee(), 1, updateIt->GetSigOpCost(), updateIt->GetRealTxSize()));
}
}
mapTx.modify(updateIt, update_descendant_state(modifySize, modifyFee, modifyCount));
Expand Down Expand Up @@ -251,15 +258,17 @@ void CTxMemPool::UpdateAncestorsOf(bool add, txiter it, setEntries &setAncestors
void CTxMemPool::UpdateEntryForAncestors(txiter it, const setEntries &setAncestors)
{
int64_t updateCount = setAncestors.size();
int64_t updateRealSize = 0;
int64_t updateSize = 0;
CAmount updateFee = 0;
int64_t updateSigOpsCost = 0;
BOOST_FOREACH(txiter ancestorIt, setAncestors) {
updateRealSize += ancestorIt->GetRealTxSize();
updateSize += ancestorIt->GetTxSize();
updateFee += ancestorIt->GetModifiedFee();
updateSigOpsCost += ancestorIt->GetSigOpCost();
}
mapTx.modify(it, update_ancestor_state(updateSize, updateFee, updateCount, updateSigOpsCost));
mapTx.modify(it, update_ancestor_state(updateSize, updateFee, updateCount, updateSigOpsCost, updateRealSize));
}

void CTxMemPool::UpdateChildrenForRemoval(txiter it)
Expand All @@ -286,11 +295,12 @@ void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove, b
setEntries setDescendants;
CalculateDescendants(removeIt, setDescendants);
setDescendants.erase(removeIt); // don't update state for self
int64_t modifyRealSize = -((int64_t)removeIt->GetRealTxSize());
int64_t modifySize = -((int64_t)removeIt->GetTxSize());
CAmount modifyFee = -removeIt->GetModifiedFee();
int modifySigOps = -removeIt->GetSigOpCost();
BOOST_FOREACH(txiter dit, setDescendants) {
mapTx.modify(dit, update_ancestor_state(modifySize, modifyFee, -1, modifySigOps));
mapTx.modify(dit, update_ancestor_state(modifySize, modifyFee, -1, modifySigOps, modifyRealSize));
}
}
}
Expand Down Expand Up @@ -337,7 +347,7 @@ void CTxMemPoolEntry::UpdateDescendantState(int64_t modifySize, CAmount modifyFe
assert(int64_t(nCountWithDescendants) > 0);
}

void CTxMemPoolEntry::UpdateAncestorState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount, int modifySigOps)
void CTxMemPoolEntry::UpdateAncestorState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount, int modifySigOps, int64_t modifyRealSize)
{
nSizeWithAncestors += modifySize;
assert(int64_t(nSizeWithAncestors) > 0);
Expand All @@ -346,6 +356,8 @@ void CTxMemPoolEntry::UpdateAncestorState(int64_t modifySize, CAmount modifyFee,
assert(int64_t(nCountWithAncestors) > 0);
nSigOpCostWithAncestors += modifySigOps;
assert(int(nSigOpCostWithAncestors) >= 0);
nRealSizeWithAncestors += modifyRealSize;
assert(int64_t(nRealSizeWithAncestors) > 0);
}

CTxMemPool::CTxMemPool(const CFeeRate& _minReasonableRelayFee) :
Expand Down
13 changes: 9 additions & 4 deletions src/txmempool.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class CTxMemPoolEntry
private:
std::shared_ptr<const CTransaction> tx;
CAmount nFee; //!< Cached to avoid expensive parent-transaction lookups
size_t nTxSize;
size_t nTxWeight; //!< ... and avoid recomputing tx weight (also used for GetTxSize())
size_t nModSize; //!< ... and modified size for priority
size_t nUsageSize; //!< ... and total memory usage
Expand All @@ -102,6 +103,7 @@ class CTxMemPoolEntry

// Analogous statistics for ancestor transactions
uint64_t nCountWithAncestors;
uint64_t nRealSizeWithAncestors;
uint64_t nSizeWithAncestors;
CAmount nModFeesWithAncestors;
int64_t nSigOpCostWithAncestors;
Expand All @@ -121,6 +123,7 @@ class CTxMemPoolEntry
*/
double GetPriority(unsigned int currentHeight) const;
const CAmount& GetFee() const { return nFee; }
size_t GetRealTxSize() const;
size_t GetTxSize() const;
size_t GetTxWeight() const { return nTxWeight; }
int64_t GetTime() const { return nTime; }
Expand All @@ -134,7 +137,7 @@ class CTxMemPoolEntry
// Adjusts the descendant state, if this entry is not dirty.
void UpdateDescendantState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount);
// Adjusts the ancestor state
void UpdateAncestorState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount, int modifySigOps);
void UpdateAncestorState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount, int modifySigOps, int64_t modifyRealSize);
// Updates the fee delta used for mining priority score, and the
// modified fees with descendants.
void UpdateFeeDelta(int64_t feeDelta);
Expand All @@ -148,6 +151,7 @@ class CTxMemPoolEntry
bool GetSpendsCoinbase() const { return spendsCoinbase; }

uint64_t GetCountWithAncestors() const { return nCountWithAncestors; }
uint64_t GetRealSizeWithAncestors() const { return nRealSizeWithAncestors; }
uint64_t GetSizeWithAncestors() const { return nSizeWithAncestors; }
CAmount GetModFeesWithAncestors() const { return nModFeesWithAncestors; }
int64_t GetSigOpCostWithAncestors() const { return nSigOpCostWithAncestors; }
Expand All @@ -173,14 +177,15 @@ struct update_descendant_state

struct update_ancestor_state
{
update_ancestor_state(int64_t _modifySize, CAmount _modifyFee, int64_t _modifyCount, int64_t _modifySigOpsCost) :
modifySize(_modifySize), modifyFee(_modifyFee), modifyCount(_modifyCount), modifySigOpsCost(_modifySigOpsCost)
update_ancestor_state(int64_t _modifySize, CAmount _modifyFee, int64_t _modifyCount, int64_t _modifySigOpsCost, int64_t _modifyRealSize) :
modifyRealSize(_modifyRealSize), modifySize(_modifySize), modifyFee(_modifyFee), modifyCount(_modifyCount), modifySigOpsCost(_modifySigOpsCost)
{}

void operator() (CTxMemPoolEntry &e)
{ e.UpdateAncestorState(modifySize, modifyFee, modifyCount, modifySigOpsCost); }
{ e.UpdateAncestorState(modifySize, modifyFee, modifyCount, modifySigOpsCost, modifyRealSize); }

private:
int64_t modifyRealSize;
int64_t modifySize;
CAmount modifyFee;
int64_t modifyCount;
Expand Down