-
Notifications
You must be signed in to change notification settings - Fork 36.6k
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
MiniTapscript: port Miniscript to Tapscript #27255
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. |
Concept ACK, an important piece in opening up Taproot scripting.
Your PR description is great but perhaps you can link to a few of those discussions for extra background reading for those that are interested? e.g. https://gist.github.com/sipa/06c5c844df155d4e5044c2c8cac9c05e Also just checking if this PR should be in Draft or not? Are there ongoing open discussions on anything important or is this ready for extensive review? |
386c71c
to
33f28a8
Compare
Yeah, thanks for the suggestion. Reviewers may be interested in sipa/miniscript#134 as well.
It is ready for (extensive or not) review. Otherwise i'd have opened it as a draft. But please tell me clearly if you disagree. |
As it stands in this PR it would be possible to import a EDIT: Actually since we are still bounded by the |
src/script/miniscript.h
Outdated
@@ -316,11 +316,22 @@ struct MaxInt { | |||
return a.value + b.value; | |||
} | |||
|
|||
friend MaxInt<I> operator-(const MaxInt<I>& a, const I& b) { | |||
if (!a.valid) return {}; | |||
return a.value - b; |
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 suppose it never happens, but worth checking that a.value >= b
?
Especially since it could be used with unsigned types.
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.
Hmm that's a good point re unsigned type, but it needs to be able to return negative values. So i guess it's up to the caller to make sure they don't call this with b > a
if a
is unsigned, as with regular substractions?
973d0d6
to
b4e747e
Compare
In the last push i've:
This PR is now ready for another round of review. |
Pushed to try to wake the CI up. Looks like it worked! |
Very cool. I also noticed bitcoin.sipa.be/miniscript has been updated. Has there been any thought into how MuSig2 (and threshold friends) would fit into this in the future? I guess that's only a problem for the compiler, since for the purpose of script it doesn't matter if e.g. public key C is an aggregate of A + B. But it does change the meaning of something like |
Concept ACK |
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.
Left some style nits, nothing important. Might want to run clang-tidy
, as it ended up reformatting a lot of the new code. Also got a few warnings, not quite sure about the FromPKBytes
warning
Still trying to wrap my head around the logic; I'll follow up with a (hopefully) more helpful review
Reviewers, i've seen the comments i'm going to address them soon and rebase this. I have discussed this with @sipa in person today. A couple notes from my recollection:
We'll see if we can introduce some of this to the existing code and rebase this on top. |
To avoid recursive calls in shared_ptr's destructor that could lead to a stack overflow.
Make sure we can spend a maximum-sized Miniscript under Tapscript context.
f695ad8
to
ec0fc14
Compare
ACK ec0fc14 I have reviewed the code carefully, and contributed a new stack size limit checking implementation, while testing with fuzzing and the other included tests. I have not tested the feature manually. Also note that some of the code is mine, so my review does not cover that. Unsure what @DrahtBot is smoking when claiming this needs rebase. It looks perfectly based to me. |
ACK ec0fc14 |
I looked over the release notes draft for 26.0 today. I think this was not mentioned. Should this have release notes? |
@murchandamus Yes! |
Currently, only the P2WSH context is supported. Miniscript for Taproot was not yet well specified at the time of writing. Currently, there is an open PR for Bitcoin Core at bitcoin/bitcoin#27255 which, when merged, can be taken as a reference. This implementation contains: - miniscript parser - type checker - malleability check - script length limit check (P2WSH standardness rule) - op count check (P2WSH consensus rule) - duplicate pubkey check - script generation - witness generation (satisfactions) - unit tests that create receive addresses based on some miniscripts and spend from them again (see `TestRedeem()`). Unit tests exist to check that this implementation's type checking passes some of the unit tests of rust-miniscript. See [./testdata](./testdata). Missing/todo: - timelock mixing check - stack size check (P2WSH standardness rule) - witness generation for thresh/multi currently has a naive implementation that is very inefficient (exponential runtime). This should be replaced with a fast algorithm. - maybe more Co-authored-by: Oliver Gugger <gugger@gmail.com>
Currently, only the P2WSH context is supported. Miniscript for Taproot was not yet well specified at the time of writing. Currently, there is an open PR for Bitcoin Core at bitcoin/bitcoin#27255 which, when merged, can be taken as a reference. This implementation contains: - miniscript parser - type checker - malleability check - script length limit check (P2WSH standardness rule) - op count check (P2WSH consensus rule) - duplicate pubkey check - script generation - witness generation (satisfactions) - unit tests that create receive addresses based on some miniscripts and spend from them again (see `TestRedeem()`). Unit tests exist to check that this implementation's type checking passes some of the unit tests of rust-miniscript. See [./testdata](./testdata). Missing/todo: - timelock mixing check - stack size check (P2WSH standardness rule) - witness generation for thresh/multi currently has a naive implementation that is very inefficient (exponential runtime). This should be replaced with a fast algorithm. - maybe more Co-authored-by: Oliver Gugger <gugger@gmail.com>
Miniscript was targeting P2WSH, and as such can currently only be used in
wsh()
descriptors. This pull request introduces support for Tapscript in Miniscript and makes Miniscript available insidetr()
descriptors. It adds support for both watching and signing TapMiniscript descriptors.The main changes to Miniscript for Tapscript are the following:
multi_a
fragment is introduced with the same semantics asmulti
. Like in other descriptorsmulti
andmulti_a
can exclusively be used in respectively P2WSH and Tapscript.d:
fragment has theu
property under Tapscript, since theMINIMALIF
rule is now consensus. See also miniscript: the 'd:' wrapper must not be 'u' #24906.The largest amount of complexity probably lies in the last item. Scripts under Taproot can now run into the maximum stack size while executing a fragment. For instance if you've got a stack size of
999
due to the initial witness plus some execution that happened before and try to execute ahash256
it wouldDUP
(increasing the stack size1000
),HASH160
and then push the hash on the stack making the script fail.To make sure this does not happen on any of the spending paths of a sane Miniscript, we introduce a tracking of the maximum stack size during execution of a fragment. See the commits messages for details. Those commits were separated from the resource consumption change, and the fuzz target was tweaked to sometimes pad the witness so the script runs on the brink of the stack size limit to make sure the stack size was not underestimated.
Existing Miniscript unit, functional and fuzz tests are extended with Tapscript logic and test cases. Care was taken for seed stability in the fuzz targets where we cared more about them.
The design of Miniscript for Tapscript is the result of discussions between various people over the past year(s). To the extent of my knowledge at least Pieter Wuille, Sanket Kanjalkar, Andrew Poelstra and Andrew Chow contributed thoughts and ideas.