-
Notifications
You must be signed in to change notification settings - Fork 37.8k
Use int32_t
type for most transaction size/weight values
#23962
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -75,7 +75,7 @@ class CTxMemPoolEntry | |
mutable Parents m_parents; | ||
mutable Children m_children; | ||
const CAmount nFee; //!< Cached to avoid expensive parent-transaction lookups | ||
const size_t nTxWeight; //!< ... and avoid recomputing tx weight (also used for GetTxSize()) | ||
const int32_t nTxWeight; //!< ... and avoid recomputing tx weight (also used for GetTxSize()) | ||
const size_t nUsageSize; //!< ... and total memory usage | ||
const int64_t nTime; //!< Local time when entering the mempool | ||
const unsigned int entryHeight; //!< Chain height when entering the mempool | ||
|
@@ -88,12 +88,14 @@ class CTxMemPoolEntry | |
// mempool; if we remove this transaction we must remove all of these | ||
// descendants as well. | ||
uint64_t nCountWithDescendants{1}; //!< number of descendant transactions | ||
uint64_t nSizeWithDescendants; //!< ... and size | ||
// Using int64_t instead of int32_t to avoid signed integer overflow issues. | ||
int64_t nSizeWithDescendants; //!< ... and size | ||
CAmount nModFeesWithDescendants; //!< ... and total fees (all including us) | ||
|
||
// Analogous statistics for ancestor transactions | ||
uint64_t nCountWithAncestors{1}; | ||
uint64_t nSizeWithAncestors; | ||
// Using int64_t instead of int32_t to avoid signed integer overflow issues. | ||
int64_t nSizeWithAncestors; | ||
CAmount nModFeesWithAncestors; | ||
int64_t nSigOpCostWithAncestors; | ||
|
||
|
@@ -104,7 +106,7 @@ class CTxMemPoolEntry | |
int64_t sigops_cost, LockPoints lp) | ||
: tx{tx}, | ||
nFee{fee}, | ||
nTxWeight(GetTransactionWeight(*tx)), | ||
nTxWeight{GetTransactionWeight(*tx)}, | ||
nUsageSize{RecursiveDynamicUsage(tx)}, | ||
nTime{time}, | ||
entryHeight{entry_height}, | ||
|
@@ -121,11 +123,11 @@ class CTxMemPoolEntry | |
const CTransaction& GetTx() const { return *this->tx; } | ||
CTransactionRef GetSharedTx() const { return this->tx; } | ||
const CAmount& GetFee() const { return nFee; } | ||
size_t GetTxSize() const | ||
int32_t GetTxSize() const | ||
{ | ||
return GetVirtualTransactionSize(nTxWeight, sigOpCost, ::nBytesPerSigOp); | ||
} | ||
size_t GetTxWeight() const { return nTxWeight; } | ||
int32_t GetTxWeight() const { return nTxWeight; } | ||
std::chrono::seconds GetTime() const { return std::chrono::seconds{nTime}; } | ||
unsigned int GetHeight() const { return entryHeight; } | ||
int64_t GetSigOpCost() const { return sigOpCost; } | ||
|
@@ -134,9 +136,9 @@ class CTxMemPoolEntry | |
const LockPoints& GetLockPoints() const { return lockPoints; } | ||
|
||
// Adjusts the descendant state. | ||
void UpdateDescendantState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount); | ||
void UpdateDescendantState(int32_t modifySize, CAmount modifyFee, int64_t modifyCount); | ||
// Adjusts the ancestor state | ||
void UpdateAncestorState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount, int64_t modifySigOps); | ||
void UpdateAncestorState(int32_t modifySize, CAmount modifyFee, int64_t modifyCount, int64_t modifySigOps); | ||
// Updates the modified fees with descendants/ancestors. | ||
void UpdateModifiedFee(CAmount fee_diff) | ||
{ | ||
|
@@ -152,13 +154,13 @@ class CTxMemPoolEntry | |
} | ||
|
||
uint64_t GetCountWithDescendants() const { return nCountWithDescendants; } | ||
uint64_t GetSizeWithDescendants() const { return nSizeWithDescendants; } | ||
int64_t GetSizeWithDescendants() const { return nSizeWithDescendants; } | ||
CAmount GetModFeesWithDescendants() const { return nModFeesWithDescendants; } | ||
|
||
bool GetSpendsCoinbase() const { return spendsCoinbase; } | ||
|
||
uint64_t GetCountWithAncestors() const { return nCountWithAncestors; } | ||
uint64_t GetSizeWithAncestors() const { return nSizeWithAncestors; } | ||
int64_t GetSizeWithAncestors() const { return nSizeWithAncestors; } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As above |
||
CAmount GetModFeesWithAncestors() const { return nModFeesWithAncestors; } | ||
int64_t GetSigOpCostWithAncestors() const { return nSigOpCostWithAncestors; } | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -75,7 +75,7 @@ void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap& cachedDescendan | |
} | ||
// descendants now contains all in-mempool descendants of updateIt. | ||
// Update and add to cached descendant map | ||
int64_t modifySize = 0; | ||
int32_t modifySize = 0; | ||
CAmount modifyFee = 0; | ||
int64_t modifyCount = 0; | ||
for (const CTxMemPoolEntry& descendant : descendants) { | ||
|
@@ -91,7 +91,7 @@ void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap& cachedDescendan | |
// Don't directly remove the transaction here -- doing so would | ||
// invalidate iterators in cachedDescendants. Mark it for removal | ||
// by inserting into descendants_to_remove. | ||
if (descendant.GetCountWithAncestors() > uint64_t(m_limits.ancestor_count) || descendant.GetSizeWithAncestors() > uint64_t(m_limits.ancestor_size_vbytes)) { | ||
if (descendant.GetCountWithAncestors() > uint64_t(m_limits.ancestor_count) || descendant.GetSizeWithAncestors() > m_limits.ancestor_size_vbytes) { | ||
descendants_to_remove.insert(descendant.GetTx().GetHash()); | ||
} | ||
} | ||
|
@@ -278,8 +278,8 @@ void CTxMemPool::UpdateAncestorsOf(bool add, txiter it, setEntries &setAncestors | |
for (const CTxMemPoolEntry& parent : parents) { | ||
UpdateChild(mapTx.iterator_to(parent), it, add); | ||
} | ||
const int64_t updateCount = (add ? 1 : -1); | ||
const int64_t updateSize = updateCount * it->GetTxSize(); | ||
const int32_t updateCount = (add ? 1 : -1); | ||
const int32_t updateSize{updateCount * it->GetTxSize()}; | ||
const CAmount updateFee = updateCount * it->GetModifiedFee(); | ||
for (txiter ancestorIt : setAncestors) { | ||
mapTx.modify(ancestorIt, [=](CTxMemPoolEntry& e) { e.UpdateDescendantState(updateSize, updateFee, updateCount); }); | ||
|
@@ -323,7 +323,7 @@ void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove, b | |
setEntries setDescendants; | ||
CalculateDescendants(removeIt, setDescendants); | ||
setDescendants.erase(removeIt); // don't update state for self | ||
int64_t modifySize = -((int64_t)removeIt->GetTxSize()); | ||
int32_t modifySize = -removeIt->GetTxSize(); | ||
CAmount modifyFee = -removeIt->GetModifiedFee(); | ||
int modifySigOps = -removeIt->GetSigOpCost(); | ||
for (txiter dit : setDescendants) { | ||
|
@@ -365,21 +365,21 @@ void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove, b | |
} | ||
} | ||
|
||
void CTxMemPoolEntry::UpdateDescendantState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount) | ||
void CTxMemPoolEntry::UpdateDescendantState(int32_t modifySize, CAmount modifyFee, int64_t modifyCount) | ||
{ | ||
nSizeWithDescendants += modifySize; | ||
assert(int64_t(nSizeWithDescendants) > 0); | ||
assert(nSizeWithDescendants > 0); | ||
nModFeesWithDescendants = SaturatingAdd(nModFeesWithDescendants, modifyFee); | ||
nCountWithDescendants += modifyCount; | ||
nCountWithDescendants += uint64_t(modifyCount); | ||
assert(int64_t(nCountWithDescendants) > 0); | ||
Comment on lines
-373
to
374
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In commit "Remove txmempool implicit-integer-sign-change sanitizer suppressions" (93daff4) IIUC, the code here casting
Also, the new code is equivalent to previous code because previous code was just doing the same conversion implicitly. However, it seems like it be nice to follow up by making nCountWithDescendants += uint64_t(modifyCount);
assert(int64_t(nCountWithDescendants) > 0); could be replaced with: nCountWithDescendants += modifyCount;
assert(nCountWithDescendants > 0); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree with the suggested changes. In addition, it seems reasonable to combine them with making signed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Either way seems fine. I suggested it for a followup because it isn't directly related to using a consistent type for transaction sizes. If you will make a follow up PR, you could consider dropping the second commit from this PR to avoid churn, since the second commit 93daff4 also isn't directly related to tx sizes. But whatever you want to do is fine. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just started reading the open threads on this pull and realized I did this yesterday in #27890 ? |
||
} | ||
|
||
void CTxMemPoolEntry::UpdateAncestorState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount, int64_t modifySigOps) | ||
void CTxMemPoolEntry::UpdateAncestorState(int32_t modifySize, CAmount modifyFee, int64_t modifyCount, int64_t modifySigOps) | ||
{ | ||
nSizeWithAncestors += modifySize; | ||
assert(int64_t(nSizeWithAncestors) > 0); | ||
assert(nSizeWithAncestors > 0); | ||
nModFeesWithAncestors = SaturatingAdd(nModFeesWithAncestors, modifyFee); | ||
nCountWithAncestors += modifyCount; | ||
nCountWithAncestors += uint64_t(modifyCount); | ||
assert(int64_t(nCountWithAncestors) > 0); | ||
nSigOpCostWithAncestors += modifySigOps; | ||
assert(int(nSigOpCostWithAncestors) >= 0); | ||
|
@@ -699,7 +699,7 @@ void CTxMemPool::check(const CCoinsViewCache& active_coins_tip, int64_t spendhei | |
// Verify ancestor state is correct. | ||
auto ancestors{AssumeCalculateMemPoolAncestors(__func__, *it, Limits::NoLimits())}; | ||
uint64_t nCountCheck = ancestors.size() + 1; | ||
uint64_t nSizeCheck = it->GetTxSize(); | ||
int32_t nSizeCheck = it->GetTxSize(); | ||
CAmount nFeesCheck = it->GetModifiedFee(); | ||
int64_t nSigOpCheck = it->GetSigOpCost(); | ||
|
||
|
@@ -720,7 +720,7 @@ void CTxMemPool::check(const CCoinsViewCache& active_coins_tip, int64_t spendhei | |
// Check children against mapNextTx | ||
CTxMemPoolEntry::Children setChildrenCheck; | ||
auto iter = mapNextTx.lower_bound(COutPoint(it->GetTx().GetHash(), 0)); | ||
uint64_t child_sizes = 0; | ||
int32_t child_sizes{0}; | ||
for (; iter != mapNextTx.end() && iter->first->hash == it->GetTx().GetHash(); ++iter) { | ||
txiter childit = mapTx.find(iter->second->GetHash()); | ||
assert(childit != mapTx.end()); // mapNextTx points to in-mempool transactions | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re-reviewing this basically from scratch, I stumble here.
int32_t
should be big enough to represent the weight of more than 5,000 max standard weight transactions. Are we actually bumping into overflow issues withint32_t
somewhere for size with descendants?I see that this was brought up before, so I assume it was left a 64-bit value to limit the scope of this PR. Is that right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so.
However, UBSan raises "signed-integer-overflow" warnings about
nSizeWithAncestors += modifySize;
etc.