Skip to content

Conversation

jnewbery
Copy link
Contributor

@jnewbery jnewbery commented Mar 22, 2020

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 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 #17977 so that PR is only the logical changes needed for Schnorr/Taproot.

@DrahtBot
Copy link
Contributor

DrahtBot commented Mar 22, 2020

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, 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.

@sipa
Copy link
Member

sipa commented Mar 26, 2020

Concept ACK, of course.

@laanwj laanwj added this to the 0.21.0 milestone Mar 27, 2020
@sipa
Copy link
Member

sipa commented Mar 28, 2020

Code review ACK, post squash, and for 0.21.

@jnewbery jnewbery force-pushed the 2020-03-precomputedtransactiondata branch from de43efc to b409b61 Compare March 28, 2020 03:06
@jnewbery
Copy link
Contributor Author

Squashed commits. No code changes.

Copy link
Contributor

@theStack theStack left a 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().

if (txTo.HasWitness()) {
if (!txTo.HasWitness()) return;

if (!ready) {
Copy link
Member

@instagibbs instagibbs Apr 1, 2020

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

Copy link
Contributor Author

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.

@fjahr
Copy link
Contributor

fjahr commented Apr 1, 2020

Code-review ACK b409b61

Also ran tests locally.

Copy link
Member

@jonatack jonatack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK b409b61

@sipa
Copy link
Member

sipa commented Apr 1, 2020

@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.

@jnewbery
Copy link
Contributor Author

jnewbery commented Apr 1, 2020

@sipa

... this calls for splitting up CheckInputScripts...

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?

@bitcoin bitcoin deleted a comment from sipa Apr 1, 2020
@sipa
Copy link
Member

sipa commented Apr 1, 2020

Would you prefer to leave the assert in this commit, or revert to not having it?

No opinion either way.

Copy link
Member

@jonatack jonatack left a 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

@maflcko
Copy link
Member

maflcko commented Apr 2, 2020

Does this speed up IBD?

@sipa
Copy link
Member

sipa commented Apr 2, 2020

@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.
@jnewbery jnewbery force-pushed the 2020-03-precomputedtransactiondata branch from 851908d to f63dec1 Compare April 12, 2020 01:32
@jnewbery
Copy link
Contributor Author

Squashed commits

@jonatack
Copy link
Member

Re-ACK f63dec1 git diff 851908d f63dec1 shows no change since last ACK.

@jnewbery
Copy link
Contributor Author

I think this should be ready for merge if @sipa @fjahr @theStack reACK.

@sipa
Copy link
Member

sipa commented Apr 15, 2020

utACK f63dec1

Copy link

@ariard ariard left a 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 and nLocktime 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.

@theStack
Copy link
Contributor

re-ACK f63dec1
Verified that since my last ACK only minor changes happened that didn't change the overall logic (s/ready/m_ready/, conditional call of .Init() method in CheckInputScripts(), minor reordering of conditions and added assert() in .Init())

@jnewbery
Copy link
Contributor Author

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)

No. Coins checks are done in MemPoolAccept::PreChecks(), which is called before PrecomputedTransactionData is instantiated (both before and after this PR).

Why we don't cache nVersion and nLocktime they won't change given the sigops, is this because they're not worth it considering their size ?

Because those fields aren't hashed before going into the sighash message. hashPrevouts, hashSequence and hashOutputs are all hashed before going into that message, so caching the hash digests means we don't have to recalculate those hashes every time.

Add a commit commenting PrecomputedTransactionData, there is a lot of context around it : ariard/bitcoin@5624724

Feel free to open a follow-up PR. No need to overload this one now that we have several ACKs.

@fjahr
Copy link
Contributor

fjahr commented Apr 15, 2020

Re-ACK f63dec1

Only changes since my last ACK were minor improvements addressing review comments and squash of commits.

@ariard
Copy link

ariard commented Apr 15, 2020

No. Coins checks are done in MemPoolAccept::PreChecks(), which is called before PrecomputedTransactionData is instantiated (both before and after this PR).

Coin checks was just a (bad) example, you may have a scriptpubkey without any sigops or script may fail before first one.

Because those fields aren't hashed before going into the sighash message. hashPrevouts, hashSequence and hashOutputs are all hashed before going into that message, so caching the hash digests means we don't have to recalculate those hashes every time.

Hmmm right, reusing their hash would break final digest, I understand better what BIP143 aim to achieve compare to original transaction digest algo.

Feel free to open a follow-up PR. No need to overload this one now that we have several ACKs.

Will do, ofc no need to break ACKs for docs!

@jnewbery
Copy link
Contributor Author

Coin checks was just a (bad) example, you may have a scriptpubkey without any sigops or script may fail before first one.

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.

@ariard
Copy link

ariard commented Apr 15, 2020

We need the precomputed transaction data to be cached before any script checking because in the ConnectBlock case

Right but not in the mempool case. Thanks for answer, will update comment with this insight in a follow-up PR.

@maflcko maflcko merged commit e16718a into bitcoin:master Apr 16, 2020
@jnewbery jnewbery deleted the 2020-03-precomputedtransactiondata branch April 16, 2020 12:55
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Apr 16, 2020
…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
@maflcko
Copy link
Member

maflcko commented Apr 24, 2020

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.

ComputerCraftr pushed a commit to ComputerCraftr/bitcoin that referenced this pull request Jun 10, 2020
…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
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Feb 15, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.