The PR branch HEAD was 6e3b37b at the time of this review club meeting.
Notes
Background and prior work
Miniscript is a language for writing (a subset of) Bitcoin Scripts in a structured way, enabling analysis, composition, generic signing and more. Miniscript support in Bitcoin Core has been an ongoing effort, with watch-only support for Miniscript in P2WSH descriptors added in v24.0.1 and signing support to be added in the upcoming v25. For background:
#24147 provides the rationale and initial backbone needed for Miniscript support in Bitcoin Core
#24148 adds watch-only support for Miniscript descriptors (see previous review club #24148)
#24149 adds signing support for Miniscript descriptors
TapMiniscript
While Tapscript shares most operations with legacy Bitcoin Script, there are a few notable differences. As such, TapMiniscript has been a project to support Tapscript in Miniscript. For background:
This gist contains the initial design and discussion on supporting Miniscript in Tapscript
Putting it all together, this PR adds support for Tapscript in Miniscript in Bitcoin Core and makes Miniscript available inside tr() descriptors, both with watching and signing support.
In your own words, what are some of the differences between Segwit v0 Script (Bitcoin Script with the Segwit Soft Fork rules) and Tapscript rules that may be relevant to Miniscript? Why?
What is Tapscript?
This PR adds a multi_a fragment for Tapscript. How is this different than the existing multi fragment? Does it have the same properties as multi? Why?
In Miniscript, we have type modifiers, which guarantee additional properties for an expression. 866284d makes the wrapper βd:β have the βuβ property under Tapscript.
What is the βd:β wrapper and the βuβ type modifier?
Why is it that we can make d: have the u property here? Why not in non-Tapscript Miniscript?
This PR adds some logic for statically ensuring no spending path exceeds the stack size at execution time:
Why does this matter for Tapscript?
Whatβs the approach taken by this PR? What are the pros/cons? (hint: efdd154)
Can you think of an alternative approach to ensure no spending path exceeds the stack size?
In e81635c, the scripts are optionally padded during fuzzing. Why?
What is the most significant change to the descriptor logic in this PR (hint: 08db38a). Why is it needed?
<turkycat> I'm comfortable with the code changes and understand them- descriptors in general though not so much. some of the concepts of the descriptors are still fuzzy to me after reading the doc on them. hoping to pick up more today
<LarryRuane> I have a very basic question (sorry), but this https://bitcoin.sipa.be/miniscript/ already mentions Tapscript, so what is this PR for? I'm unclear on what is already done and what more is needed
<josie> a few of you have already mentioned some differences, but can you summarize in your own words some differences between Segwit v0 Script and Tapscript?
<turkycat> segwit v0 supports pubkeyhash and script hash operations via witness data. taproot allows for a merkle tree of different script leaves that can be revealed at spending time or satisfied with a composite signature of a single key
<stickies-v> josie: OP_(NOT)IF is now only allowed (consensus) to have 0 or 1 as its argument, whereas in v0 e.g. 4 would also evaluate as true (this is also referred to as MINIMALIF)
<josie> turkycat: close. I'd say it's more correct to say that segwit v1 introduces the merkle tree of scripts (with leaf versions) and tapscript is defined as leaf version 0
<turkycat> brunoerg - I had to google "MAST", but I think so. All I know is that with a single merkle root you can have an unbalanced trie of script leaves
<turkycat> extending Script requires the redefining of the numbered NO_OP codes (like NO_OP1), where I could make a WAG that tapscript can be extensible without requiring to always be backwards compatible? by adding a new version I mean
<stickies-v> brunoerg: if during script execution one of those opcodes is encountered, script termination fails. if the opcodes are in a branch that's not executed, they're ignored
<josie> brunoerg, stickies-v: that's my understanding as well. I'm not sure about this, but perhaps it also means those OP_CODE numbers are still reserved? meaning they cant be redefined to mean something else in the future
<josie> abubakar: the stack element size, and the element count limit are the same, but the non-push opcodes limit of 201 per script was removed and the maximum script size limit of 10,000 bytes was removed
<josie> kevkevin, abubakar: tapscript definitely uses checksigadd, but I suppose we could have reused the same multi fragment and recognized that it was being used in a tapscript context. but this would only be possible if the multi fragment had the same properties under both p2wsh and tapscript
<josie> stickies-v: multi does have the n property, which means it must always consume at least one stack element. good point about the off-by-one tho, I'm not sure if this is the reason
<josie> let me rephrase the question a bit: the `multi` fragment has the `n` type modifier, which means it must always consume at least one stack element. `multi_a` does not have the `n` type modifier, which means the top of the stack can be the empty vector. any ideas as to why?
<turkycat> maybe because it still requires n items to satisfy the NUMEQUAL at the end, but if we're using, say 2-of-3 multisig then we only need 2 valid signatures? idk feels like a shaky guess but there doesn't appear to be a 'k' value on `multi_a`
<josie> we are pretty close to time, so instead of going into the next Q (which is a pretty big one), are there any questions about stuff we've talked about so far?
<josie> also, any interest in finishing the remaining questions in a follow-up review club? there's some pretty good stuff in the remaining questions :)
<josie> cool, follow-up it is! probably should have started with less questions because this is a really big topic! what we are seeing in this PR is the tip of the iceberg