-
Notifications
You must be signed in to change notification settings - Fork 37.7k
Wallet: estimate the size of signed inputs using descriptors #26567
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
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. 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. |
5f5ae96
to
1af8d9d
Compare
55cb06a
to
052edf8
Compare
Pushed a commit to accurately compute the serialized size of the witness stack size, cleanup the commits a bit, and add the newly introduced methods in the descriptors to the |
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
052edf8
to
594c33e
Compare
Thanks for the review. Addressed your comments and rebased on master. |
594c33e
to
967795c
Compare
Rebased after #28244. |
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 932556c
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
Added to my queue. Will start reviewing next week.
It was taking into account the P2WSH script push in the number of stack elements.
Similarly to how we compute the maximum stack size. Also note how it would be quite expensive to recompute it recursively by accounting for different ECDSA signature sizes. So we just assume high-R everywhere. It's only a trivial difference anyways.
932556c
to
617b579
Compare
In the wallet code, we are currently estimating the size of a signed input by doing a dry run of the signing logic. This is unnecessary as all outputs we are able to sign for can be represented by a descriptor, and we can derive the size of a satisfaction ("signature") from the descriptor itself directly. In addition, this approach does not scale: getting the size of a satisfaction through a dry run of the signing logic is only possible for the most basic scripts. This commit introduces the computation of the size of satisfaction per descriptor. It's a bit intricate for 2 main reasons: - We want to conserve the behaviour of the current dry-run logic used by the wallet that sometimes assumes ECDSA signatures will be low-r, sometimes not (when we don't create them). - We need to account for the witness discount. A single descriptor may sometimes benefit of it, sometimes not (for instance `pk()` if used as top-level versus if used inside `wsh()`).
It is sometimes useful to interface with multiple signing providers at once. For instance when inferring a descriptor with solving information being provided from multiple sources (see next commit). Instead of inneficiently copying the information from one provider into the other, introduce a new signing provider that takes a list of pointers to existing providers.
Instead of using the dummysigner to compute a placeholder satisfaction, infer a descriptor on the scriptPubKey of the coin being spent and use the estimation of the satisfaction size given by the descriptor directly. Note this (almost, see next paragraph) exactly conserves the previous behaviour. For instance CalculateMaximumSignedInputSize was previously assuming the input to be spent in a transaction that spends at least one Segwit coin, since it was always accounting for the serialization of the number of witness elements. In this commit we use a placeholder for the size of the serialization of the witness stack size (1 byte). Since the logic in this commit is already tricky enough to review, and that it is only a very tiny approximation not observable through the existing tests, it is addressed in the next commit.
When estimating the maximum size of an input, we were assuming the number of elements on the witness stack could be encode in a single byte. This is a valid approximation for all the descriptors we support (including P2WSH Miniscript ones), but may not hold anymore once we support Miniscript within Taproot descriptors (since the max standard witness stack size of 100 gets lifted). It's a low-hanging fruit to account for it correctly, so just do it now.
617b579
to
10546a5
Compare
utACK 10546a5 |
re-ACK 10546a5 |
8d6228f consensus/validation.h: remove needless GetTransactionOutputWeight helper (Antoine Poinsot) Pull request description: Introduced in #26567. My bad. Thanks AJ for noticing. ACKs for top commit: ajtowns: utACK 8d6228f Tree-SHA512: cf13647b4aac82fb6a54ae0338e3928e9bdf226ed4f5e91d529996328471744132db2bee9676e0b3f40a8bbe0e0ca51a9e5f91560a84e0f33597290551a1ee18
8d6228f consensus/validation.h: remove needless GetTransactionOutputWeight helper (Antoine Poinsot) Pull request description: Introduced in bitcoin#26567. My bad. Thanks AJ for noticing. ACKs for top commit: ajtowns: utACK 8d6228f Tree-SHA512: cf13647b4aac82fb6a54ae0338e3928e9bdf226ed4f5e91d529996328471744132db2bee9676e0b3f40a8bbe0e0ca51a9e5f91560a84e0f33597290551a1ee18
The wallet currently estimates the size of a signed input by doing a dry run of the signing logic. This is unnecessary since all outputs we can sign for can be represented by a descriptor, and we can derive the size of a satisfaction ("signature") directly from the descriptor itself.
In addition, the current approach does not generalize well: dry runs of the signing logic are only possible for the most basic scripts. See for instance the discussion in #24149 around that.
This introduces a method to get the maximum size of a satisfaction from a descriptor, and makes the wallet use that instead of the dry-run.