-
Notifications
You must be signed in to change notification settings - Fork 38.8k
rpc: Distinguish between vsize and sigop adjusted mempool vsize #32800
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
base: master
Are you sure you want to change the base?
rpc: Distinguish between vsize and sigop adjusted mempool vsize #32800
Conversation
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code Coverage & BenchmarksFor details see: https://corecheck.dev/bitcoin/bitcoin/pulls/32800. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please copy-paste ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
|
🚧 At least one of the CI tasks failed. HintsTry to run the tests locally, according to the documentation. However, a CI failure may still
Leave a comment here, if you need help tracking down a confusing failure. |
969193c to
89d1220
Compare
janb84
left a comment
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.
A few comments / NITs on the documentation side of this PR.
89d1220 to
c8da5c1
Compare
hodlinator
left a comment
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.
Reviewed c8da5c1576636e31acb3422e52b8cb685dbbba64
src/rpc/rawtransaction.cpp
Outdated
| const size_t txSize = entry->GetTxSize(); | ||
| const size_t vSize = GetVirtualTransactionSize(txSize, 0, 0); | ||
| // Only report sigopsize when vSize is strictly less than the raw tx size | ||
| if (vSize < txSize) { |
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.
Q1: Why do we want to only conditionally report sigopsize, is there some comment to that affect from the old PR? I don't get that impression from #27591 (comment).
Q2: In the above linked comment, do you understand what is meant by "(Or, even better, do the sigop adjustment in cases where we can -- getrawtransaction of txs in blocks could pull up the utxo being spent via rev*.dat and calculate the sigop adjustment?)"? I must admit I don't fully understand it myself.
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.
Q1. Yeah there's no comment about that in #27591, Am still skeptical about conditionally reporting the sigosize , the initial idea's to check when txSize which is the transaction in the mempool (which might be sigops adjusted from entry->GetTxSize()) is less than vSize GetVirtualTransactionSize(txSize, 0, 0) which is not sigop adjusted. But I think it will make more sense to remove the codition and report the sigopsize.
Q2. My understanding of the comment is; I think it’s suggesting that getrawtransaction could compute sigopsize for confirmed transactions by retrieving spent output scripts from rev*.dat. While possible, this is expensive and sometimes not feasible (e.g., on pruned nodes). That’s why sigopsize is only reported for mempool transactions, where all required data is readily available in memory. (I might wrong in as well)
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.
Q1. Yeah, I think the interface is less confusing if we remove the condition. #27591 seems to use the term "sigop-adjusted size" rather than "sigop-equivalent size". So could change the description from:
https://github.com/bitcoin/bitcoin/blob/be75fa48fa77c417b9ebdd3be4d1ddb212ab16b3/src/rpc/rawtransaction.cpp#L284
to:
"Sigop-adjusted size in bytes, only present for mempool transactions."
(Unless we implement Q2, which I agree is not critical).
Maybe replace "sigop-equivalent" with "sigop-adjusted" everywhere else too unless there is precedent for it?
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.
Fixed as suggested in 70316b5. Thanks
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.
Realized the comment is now out of date:
- // Add sigopsize if the transaction exists in the mempool and its size is affected by it.
+ // Add sigopsize if the transaction exists in the mempool.
src/rpc/rawtransaction.cpp
Outdated
| if (vSize < txSize) { | ||
| // bytes per sigop = witness scale factor (4) | ||
| const uint64_t sigopSize = uint64_t(entry->GetSigOpCost()) * uint64_t(nBytesPerSigOp); | ||
| result.pushKV("sigopsize", sigopSize); |
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.
nit: #27591 (comment) mentions adding sigopsize to other RPCs as well. Not sure if necessary.
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.
Yeah, I don't think it's necessary that's why I decide to report it (sigopsize) only in getrawtransaction RPC
4cc9be2 to
be75fa4
Compare
|
Thanks @hodlinator and @janb84 for the detailed review. Well Appreciated, Please let me know if there's any comment left unaddressed. |
|
It makes much more sense to stick to weight for consensus-related matters, and vsize for policy in all cases. |
Sorry, I didn't quite fully understand the comment (do you mean sigopsize should return only |
hodlinator
left a comment
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.
Concept ACK be75fa48fa77c417b9ebdd3be4d1ddb212ab16b3
Might be good to add release notes for this PR as it is adding to the user-facing RPC interface, similarly to: https://github.com/bitcoin/bitcoin/blob/be75fa48fa77c417b9ebdd3be4d1ddb212ab16b3/doc/release-notes-27826.md
src/rpc/rawtransaction.cpp
Outdated
| const size_t txSize = entry->GetTxSize(); | ||
| const size_t vSize = GetVirtualTransactionSize(txSize, 0, 0); | ||
| // Only report sigopsize when vSize is strictly less than the raw tx size | ||
| if (vSize < txSize) { |
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.
Q1. Yeah, I think the interface is less confusing if we remove the condition. #27591 seems to use the term "sigop-adjusted size" rather than "sigop-equivalent size". So could change the description from:
https://github.com/bitcoin/bitcoin/blob/be75fa48fa77c417b9ebdd3be4d1ddb212ab16b3/src/rpc/rawtransaction.cpp#L284
to:
"Sigop-adjusted size in bytes, only present for mempool transactions."
(Unless we implement Q2, which I agree is not critical).
Maybe replace "sigop-equivalent" with "sigop-adjusted" everywhere else too unless there is precedent for it?
abe0c4d to
ede20b4
Compare
68ec63e to
05cc5e5
Compare
|
🚧 At least one of the CI tasks failed. HintsTry to run the tests locally, according to the documentation. However, a CI failure may still
Leave a comment here, if you need help tracking down a confusing failure. |
05cc5e5 to
74530ac
Compare
I understand it can be calculated from I can remove ca16b18 if you feel strongly about it. I added it because of the discussion here: #27591. Thank you so much! |
hodlinator
left a comment
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.
ACK 74530ac9e05aafa91aaa00cc4f53bb4f26a55153
Clarifies the distinction between sigop-adjusted and non-sigop-adjusted vsize for RPC users.
Minor fixups and corrections since my last review #32800 (review)
| defaulting to 20 vbytes per sigop). Using a single combined metric like this simplifies block template | ||
| construction by avoiding the need to optimize for both weight and sigops separately — a potential | ||
| “two-dimensional knapsack” problem — though in practice the impact of that problem is often limited. | ||
| Some miners prefer to handle weight and sigops as separate constraints, while others use the sigop-adjusted | ||
| size for simplicity. |
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.
info: Verified that Bitcoin Core seems to use sigop-adjusted size for block template construction as it sounds like that in this part. IIUC, we do, going by:
-
Checking the block is full with
packageSize...
https://github.com/bitcoin/bitcoin/blob/ca9c5219a4029901db6f49678620d1935bf1634f/src/node/miner.cpp#L209-L214
...which comes fromGetSizeWithAncestors()...
https://github.com/bitcoin/bitcoin/blob/ca9c5219a4029901db6f49678620d1935bf1634f/src/node/miner.cpp#L376-L390
...which comes from...
https://github.com/bitcoin/bitcoin/blob/ca9c5219a4029901db6f49678620d1935bf1634f/src/kernel/mempool_entry.h#L126
...which is sigop-adjusted:
https://github.com/bitcoin/bitcoin/blob/ca9c5219a4029901db6f49678620d1935bf1634f/src/kernel/mempool_entry.h#L140-L143 -
Ordering by feerate, which uses
GetTxSize():
https://github.com/bitcoin/bitcoin/blob/ca9c5219a4029901db6f49678620d1935bf1634f/src/node/miner.cpp#L313
doc/release-notes-32800.md
Outdated
| @@ -0,0 +1,5 @@ | |||
| - Mempool-related RPCs (`getrawmempool`, `getmempoolentry`, `testmempoolaccept`, `submitpackage`) now | |||
| clarify the difference between BIP-141 virtual size (`vsize_bip141`) and policy-adjusted virtual size | |||
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.
nit: The adjusted beginning is nicer, but would rather bring back the end from 1523e8d6c981efff1394bd1669fbbbea5ff7ac97:
Additionally,
getrawtransactionnow includes
+asigopsizefield and continues to report the unadjusted BIP-141 virtual size in itsvsizefield.
doc/policy/feerates-and-vsize.md
Outdated
|
|
||
| Both methods are valid: the first prioritizes simplicity, the second prioritizes potentially optimal | ||
| space usage. For consensus-level weight calculations, refer to `vsize_bip141`. If you need to inspect | ||
| the raw BIP-141 size of a transaction in the mempool, use `getrawtransaction`; if you need the | ||
| policy-adjusted size, use `getmempoolentry` or `getrawmempool`. |
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.
nit: I think this part is repetitive and somewhat arbitrary, currently the PR ensures sigop-adjusted and non-sigop-adjusted sizes are available for all mentioned RPCs. If I was using RPCs for each transaction for this calculation I would just pick the fastest one. Maybe I'm overlooking something though.
| Both methods are valid: the first prioritizes simplicity, the second prioritizes potentially optimal | |
| space usage. For consensus-level weight calculations, refer to `vsize_bip141`. If you need to inspect | |
| the raw BIP-141 size of a transaction in the mempool, use `getrawtransaction`; if you need the | |
| policy-adjusted size, use `getmempoolentry` or `getrawmempool`. |
jonatack
left a comment
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.
Concept ACK, appears to clarify these values, and adds a new "vsize_bip141" field to the API while not changing the existing vsize values returned.
74530ac to
c61bc4f
Compare
Addressed by bring back the last sentence in commit 1523e8d
Agreed. I removed the entire paragraph from the docs. All addressed changes are in 967d16 |
c61bc4f to
c62b40d
Compare
hodlinator
left a comment
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-ACK c62b40d7abd8de1972bacb8c600bbab55a231b20
Changes since my first ACK (#32800 (review)):
- Adjusted docs based on my latest feedback.
- Avoids re-converting tx hash in the RPC code.
This commit adds a new `vsize_bip141` field to mempool acceptance and submission RPCs, including `testmempoolaccept` and `submitpackage`, to explicitly report the virtual transaction size as defined in BIP 141. RPC help texts are updated to reflect this addition. Tests in `mempool_accept.py, mempool_accept, p2p_segwit, rpc_packages, mempool_sigoplimit` are extended to verify the presence and correctness of the new field. Co-authored-by: Gloria Zhao <[email protected]>
…sactions Extend the `getrawtransaction` RPC to include a new field `sigopsize` when the transaction is in the mempool. The `sigopsize` provides the mempool's accounting size for the transaction based on its sigop cost, which can exceed its serialized vsize under `-bytespersigop` policies. Test coverage is added to verify the correct calculation and exposure of the `sigopsize` field via `mempool_sigoplimit.py`.
This commit introduces a new policy document at `doc/policy/feerates‑and‑vsize.md` that clarifies: - How transaction weight, BIP‑141 virtual size, and sigop‑adjusted size are calculated. - Which RPCs expose “vsize” (sigop‑adjusted) versus “vsize_bip141” (pure BIP‑141). - Guidance for users on fee estimation, block template construction, and consensus‑level size reporting.
c62b40d to
ad07093
Compare
|
Rebased and fixed conflict. |
hodlinator
left a comment
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-ACK ad07093
Just resolved conflict with b0417ba in doc/policy/README.md (also removing double-newline at EOF) since my previous ACK (#32800 (review)).
|
🐙 This pull request conflicts with the target branch and needs rebase. |
Motivation and Problem
CTxMemPoolEntry::GetTxSize()returns the larger of two values: the BIP 141 virtual size (vsize) and the "sigop-adjusted size." This sigop-adjusted size is used by mempool validation and mining algorithms as a safeguard to prevent overfilling blocks with transactions that approach both the weight and signature operation (sigop) limits in a way that could exploit block space efficiency.In the current implementation, the sigop-adjusted size is reported as the "vsize" in RPCs that provide mempool transaction data, such as
getmempoolentry,getrawmempool,testmempoolaccept, andsubmitpackage. However, the documentation for these RPCs typically describes this value simply as the "virtual transaction size as defined in BIP 141," without acknowledging the sigop adjustment. Since the reported size may differ from the pure BIP 141 definition, this confuses people as in this tweet, discrepancy can be misleading, as the reported size may differ from the pure BIP 141 definition.Proposed Solution
To resolve this, all mempool-related RPCs now return two separate fields:
vsize: the sigop-adjusted size, i.e. max(BIP 141 vsize, sigop-adjusted size), which reflects the value previously returned under the vsize label and continues to drive mempool acceptance and block template scoring.
vsize_bip141: the pure BIP 141 virtual size, strictly
ceil(weight/4), matching the consensus definition and now reported separately for clarity.This preserves the behavior for clients that depend on the mempool policy size being reported as vsize while making the consensus size explicitly accessible under vsize_bip141.
Additionally, this PR updates the relevant RPC help text to clearly document the distinction between these two sizes, and adds supporting documentation
doc/policy/feerates-and-vsize.mdto better explain fee rates, virtual size calculations, sigop adjustments, and the mempool policy heuristics.A new field, sigopsize, has also been added to the getrawtransaction RPC result when input information (transaction is in the mempool) is available. This field explicitly reports the sigop-adjusted size as calculated by
ceil(sigop cost * bytes_per_sigop / WITNESS_SCALE_FACTOR). Exposing this value provides users with more precise insight into how the transaction’s sigops impact its effective size for policy and fee estimation.Note: This picks up work from the closed #27591
Fixes #32775