-
Notifications
You must be signed in to change notification settings - Fork 37.7k
test: fix MiniWallet script-path spend (missing parity bit in leaf version) #30076
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
test: fix MiniWallet script-path spend (missing parity bit in leaf version) #30076
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code CoverageFor detailed information about the code coverage, see the test coverage report. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. 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. |
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.
tACK e4abac2
Reviewing #29939 previously made it easy for me to review this one!
Make successful and all functional tests pass on this branch. Using the shared patch, I can see these 2 tests fail in master branch.
feature_versionbits_warning.py | ✖ Failed | 3 s
wallet_fundrawtransaction.py --descriptors | ✖ Failed | 17 s
ALL | ✖ Failed | 2752 s (accumulated)
e4abac2
to
57eb590
Compare
Thanks for the review @rkrux! Addressed your comment #30076 (comment); the single taproot leaf is now accessed directly rather than by name, so there is no magic string involved anymore. Note that the leaf name (second parameter to |
Rather than only returning the internal key from the P2TR anyone-can-spend address creation routine, provide the whole TaprootInfo object, which in turn contains a dictionary of TaprootLeafInfo object for named leaves. This data is used in MiniWallet for the default ADDRESS_OP_TRUE mode, in order to deduplicate the witness script and leaf version of the control block.
…rsion) This commit fixes a dormant bug in MiniWallet that exists since support for P2TR was initially added in bitcoin#23371 (see commit 041abfe). In the course of spending the output, the leaf version byte of the control block in the witness stack doesn't set the parity bit, i.e. we were so far just lucky that the used combinations of relevant data (internal pubkey, leaf script / version) didn't result in a tweaked pubkey with odd y-parity. If that was the case, we'd get the following validation error: `mandatory-script-verify-flag-failed (Witness program hash mismatch) (-26)` Since MiniWallets can now optionally be tagged (bitcoin#29939), resulting in different internal pubkeys, the issue is more prevalent now. Fix it by passing the parity bit, as specified in BIP341.
Not every pseudorandom hash result is a valid x-only public key, so the pubkey tweaking in the course of creating the output public key would fail about every second time. Fix this by treating the hash result as private key and calculate the x-only public key out of that, to be used then as internal key.
57eb590
to
e4b0dab
Compare
Rebased on master, after the merge of #30162. Adding a functional test for tagged wallets to the new |
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 e4b0dab
Not an expert but: Checked that test_wallet_tagging
fails without the fix on "mandatory-script-verify-flag-failed (Witness program hash mismatch) (-26)". Reviewed the test by editing the parity check in VerifyTaprootCommitment
to make it pass on master and examining bytes(version + negflag)
while running.
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.
reACK e4b0dab
Applied the shared patch again and the following tests fail on master with the mentioned error. Though I've not been able to go through the corresponding control block C++ code yet :(
raise JSONRPCException(response['error'], status)
test_framework.authproxy.JSONRPCException: mandatory-script-verify-flag-failed (Witness program hash mismatch) (-26)
mempool_limit.py | ✖ Failed | 1 s
p2p_1p1c_network.py | ✖ Failed | 5 s
p2p_opportunistic_1p1c.py | ✖ Failed | 1 s
p2p_tx_download.py | ✖ Failed | 31 s
rpc_packages.py | ✖ Failed | 3 s
self.log.info(f"Test tagged wallet instances...") | ||
node = self.nodes[0] | ||
untagged_wallet = self.wallets[0][1] | ||
for i in range(10): |
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.
Is the sole reason for creating 10 tagged wallets to be thorough? Or is there any other reason 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.
i.e. to test for the following assumption
we were so far just lucky that the used combinations of relevant data (internal pubkey, leaf script / version) didn't result in a tweaked pubkey with odd y-parity.
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.
Is the sole reason for creating 10 tagged wallets to be thorough? Or is there any other reason as well?
Yes it's thoroughness, no other reason. Since the fixed bugs only occur with a certain probability, creating several random tagged wallets in a row increase the likelihood of catching the bugs in a single test run (nothing special about the number 10 though).
Got it, nice.
…On Tue, Jun 18, 2024, 06:43 Sebastian Falbesoner ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In test/functional/feature_framework_miniwallet.py
<#30076 (comment)>:
> @@ -31,6 +34,20 @@ def test_tx_padding(self):
assert_greater_than_or_equal(tx.get_weight(), target_weight)
assert_greater_than_or_equal(target_weight + 3, tx.get_weight())
+ def test_wallet_tagging(self):
+ """Verify that tagged wallet instances are able to send funds."""
+ self.log.info(f"Test tagged wallet instances...")
+ node = self.nodes[0]
+ untagged_wallet = self.wallets[0][1]
+ for i in range(10):
Is the sole reason for creating 10 tagged wallets to be thorough? Or is
there any other reason as well?
Yes it's thoroughness, no other reason. Since the fixed bugs only occur
with a certain probability, creating several random tagged wallets in a row
increase the likelihood of catching the bugs in a single test run (nothing
special about the number 10 though).
—
Reply to this email directly, view it on GitHub
<#30076 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABNPILUIX2ZRNELG5ECQDSLZH6CT3AVCNFSM6AAAAABHPTP73OVHI2DSMVQWIX3LMV43YUDVNRWFEZLROVSXG5CSMV3GSZLXHMZDCMRUGE2TAMBSGE>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
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 e4b0dab
Confirmed to fix #30528 which I discovered independently. Rebased my test commit from there on top of this PR and verified that exceptions are no longer raised for the 2 cases I found.
Re-ran feature_framework_miniwallet.py without my changes on top and verified it passed. Also ran with --randomseed <X>
to verify that tag names are generated deterministically.
Passed test_runner.py
(other tests are using MiniWallet
indirectly, and mempool_util.py specifically was already using a tag_name
value that still works).
Not an expert on Taproot so haven't fully understood the context around the fixes, but they look small & safe and only touch functional test Python code.
Sorry again for not finding this PR before creating the issue. Eager to use this fix to fearlessly create multiple tagged wallets in upcoming tests. :)
This PR fixes a dormant bug in MiniWallet that exists since support for P2TR was initially added in #23371 (see commit 041abfe).
In the course of spending the output, the leaf version byte of the control block in the witness stack doesn't set the parity bit, i.e. we were so far just lucky that the used combinations of relevant data (internal pubkey, leaf script / version) didn't result in a tweaked pubkey with odd y-parity. If that was the case, we'd get the following validation error:
mandatory-script-verify-flag-failed (Witness program hash mismatch) (-26)
Since MiniWallets can now optionally be tagged (#29939), resulting in different internal pubkeys, the issue is more prevalent now. Fix it by passing the parity bit, as specified in BIP341.
Can be tested with the following patch (fails on master, succeeds on PR):
In addition to that, another bug is fixed where the internal key derivation failed, as not every pseudorandom hash results in a valid x-only pubkey. Fix this by treating the hash result as private key and calculate the x-only public key out of that, to be used then as internal key.
Fixes #30528.