-
Notifications
You must be signed in to change notification settings - Fork 37.7k
Refactor: Initialize PrecomputedTransactionData in CheckInputScripts #18401
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
Refactor: Initialize PrecomputedTransactionData in CheckInputScripts #18401
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. 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. |
Concept ACK, of course. |
Code review ACK, post squash, and for 0.21. |
de43efc
to
b409b61
Compare
Squashed commits. No code changes. |
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.
Code-review ACK b409b61 💻
Checked that the resulting code logic remains the same, the only internal difference is that the initialization of the precomputed transaction data happens later, in CheckInputScripts()
rather than in AcceptSingleTransaction()
.
src/script/interpreter.cpp
Outdated
if (txTo.HasWitness()) { | ||
if (!txTo.HasWitness()) return; | ||
|
||
if (!ready) { |
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.
while we're touching this code can we make ready
be something more self-explanatory? Especially if we're expanding condition checks in the future. e.g., m_amounts_spent_ready
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.
This, plus the discussion here: https://github.com/bitcoin/bitcoin/pull/18401/files#r401812158 has made me think that there shouldn't be two different ready bools in the final taproot implementation, since we only ever want to initialize the object once. I've changed this to m_ready
and made some minor changes to the Init
function.
Code-review ACK b409b61 Also ran tests locally. |
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 b409b61
@jnewbery I guess this calls for splitting up CheckInputScripts into two separate functions (one looking up inputs and initializing txdata, and one doing the rest). I suggest keeping that for a future improvement, though. |
Sounds sensible now that it has a potentially unexpected side-effect of initializing the txdata. I agree that we should save that for later. Would you prefer to leave the assert in this commit, or revert to not having it? |
No opinion either way. |
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 851908d for 0.21
Does this speed up IBD? |
@MarcoFalke Probably slightly, as it avoids constructing precomputed tx data in the assumevalid range. |
Add a default constructor to `PrecomputedTransactionData`, which doesn't initialize the struct's members. Instead they're initialized inside the `CheckInputScripts()` function. This allows a later commit to add the spent UTXOs to that structure.
851908d
to
f63dec1
Compare
Squashed commits |
Re-ACK f63dec1 |
utACK f63dec1 |
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.
Code Review ACK f63dec1
Add a commit commenting PrecomputedTransactionData
, there is a lot of context around it : ariard@5624724
Few aside questions, :
- As far as I can tell, we're going to compute "midstate" even if validation fail before signature verification (like a script spending a coin already spent), instead of hashing-at-first-use ? (not sure if ternary in
SignatureHash
are currently exercised) - Why we don't cache
nVersion
andnLocktime
they won't change given the sigops, is this because they're not worth it considering their size ?
I guess minimizing code complexity answers both.
re-ACK f63dec1 |
No. Coins checks are done in
Because those fields aren't hashed before going into the sighash message.
Feel free to open a follow-up PR. No need to overload this one now that we have several ACKs. |
Re-ACK f63dec1 Only changes since my last ACK were minor improvements addressing review comments and squash of commits. |
Coin checks was just a (bad) example, you may have a
Hmmm right, reusing their hash would break final digest, I understand better what BIP143 aim to achieve compare to original transaction digest algo.
Will do, ofc no need to break ACKs for docs! |
We need the precomputed transaction data to be cached before any script checking because in the ConnectBlock case, each input script validation is parallelized separately. If the cache was filled during script execution, you'd need locking between those threads to ensure they're not trying to read/write concurrently. |
Right but not in the mempool case. Thanks for answer, will update comment with this insight in a follow-up PR. |
…in CheckInputScripts f63dec1 [REFACTOR] Initialize PrecomputedTransactionData in CheckInputScripts (Pieter Wuille) Pull request description: This is a single commit taken from the Schnorr/Taproot PR bitcoin#17977. Add a default constructor to `PrecomputedTransactionData`, which doesn't initialize the struct's members. Instead they're initialized inside the `CheckInputScripts()` function. This allows a later commit to add the spent UTXOs to that structure. The spent UTXOs are required for the schnorr signature hash, since it commits to the scriptPubKeys. See https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#common-signature-message for details. By itself, this isn't really an improvement to the code, but I think it makes sense to separate out the refactor/moveonly commits from PR bitcoin#17977 so that PR is only the logical changes needed for Schnorr/Taproot. ACKs for top commit: jonatack: Re-ACK f63dec1 `git diff 851908d f63dec1` shows no change since last ACK. sipa: utACK f63dec1 theStack: re-ACK f63dec1 fjahr: Re-ACK f63dec1 ariard: Code Review ACK f63dec1 Tree-SHA512: ecf9154077824ae4c274b4341e985797f3648c0cb0c31cb25ce382163b923a3acbc7048683720be4ae3663501801129cd0f48c441a36f049cc304ebe9f30994e
I did some more benchmarking and this should speed up CreateNewBlock by a factor inversely related to the number of transactions in the block. So a block with one transaction (beside the coinbase tx) should be generated about twice as fast. Whereas a block with 1000 txs (beside the coinbase tx) should be generated at a slight but almost no speedup. |
…in CheckInputScripts f63dec1 [REFACTOR] Initialize PrecomputedTransactionData in CheckInputScripts (Pieter Wuille) Pull request description: This is a single commit taken from the Schnorr/Taproot PR bitcoin#17977. Add a default constructor to `PrecomputedTransactionData`, which doesn't initialize the struct's members. Instead they're initialized inside the `CheckInputScripts()` function. This allows a later commit to add the spent UTXOs to that structure. The spent UTXOs are required for the schnorr signature hash, since it commits to the scriptPubKeys. See https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#common-signature-message for details. By itself, this isn't really an improvement to the code, but I think it makes sense to separate out the refactor/moveonly commits from PR bitcoin#17977 so that PR is only the logical changes needed for Schnorr/Taproot. ACKs for top commit: jonatack: Re-ACK f63dec1 `git diff 851908d f63dec1` shows no change since last ACK. sipa: utACK f63dec1 theStack: re-ACK f63dec1 fjahr: Re-ACK f63dec1 ariard: Code Review ACK f63dec1 Tree-SHA512: ecf9154077824ae4c274b4341e985797f3648c0cb0c31cb25ce382163b923a3acbc7048683720be4ae3663501801129cd0f48c441a36f049cc304ebe9f30994e
This is a single commit taken from the Schnorr/Taproot PR #17977.
Add a default constructor to
PrecomputedTransactionData
, which doesn't initialize the struct's members. Instead they're initialized inside theCheckInputScripts()
function. This allows a later commit to add the spent UTXOs to that structure. The spent UTXOs are required for the schnorr signature hash, since it commits to the scriptPubKeys. See https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#common-signature-message for details.By itself, this isn't really an improvement to the code, but I think it makes sense to separate out the refactor/moveonly commits from PR #17977 so that PR is only the logical changes needed for Schnorr/Taproot.