-
Notifications
You must be signed in to change notification settings - Fork 388
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
[Doc] New Opcodes for tapscript #949
Conversation
Seems like a big effort that would increase the ergonomics of using Script, but will also make it more complex due to increased number of opcodes. I thought that Simplicity was a path to more expressive contracts. This seems to be a parallel effort to have another system that is more expressive than current Script (effectively, due to added ergonomics) At the same time, propping up script with more power means that people's focus will be diluted - they will need to choose between studying Simplicity and this extended script. The amount of new opcodes is huge, and implementation of each opcode is a huge undertaking. Even if it may seem to be simple to implement the opcodes, the amount of what can go wrong is usually very big. And there's no way to formally verify these implementations, as is the case with Simplicity. It seems to me that such effort, if applied towards Simplicity, would made it real-world-usable much faster Is Simplicity not expected to be usage-ready for extended amount of time, so a decision to prop up Script is made instead ? |
@dgpv The timeline for Simplicity is (hopefully) not that much longer than the timeline for this. We certainly don't mean this as a replacement for Simplicity or as some sort of crutch because we foresee long delays. The goal is rather to improve the ergonomics of the existing script and give people a sandbox to play with where they can continue to work in the "I can hex-edit a script for an imperative stack machine" model which is easy to experiment with. So there are sorta two goals here, which I think explain how large this an effort this appears to be:
So I dispute your charactization of "huge" for both the number of new opcodes and the size of the undertaking :). I think in practice, for you and I (and everyone else who isn't at the "basic experimentation" phase of development), the bulk of the complexity will be in understanding and reasoning about Then as for the relationship with Simplicity -- our first goals with Simplicity are to implement Miniscript fragments (you can see some early work in this repo), with the idea that much of the "standard script operations" you can write Simplicty for by just taking a Miniscript and translating it directly into Simplicity, and then the difficult parts of actually writing Simplicity will be limited to the cool stuff that actually makes use of Simplicity's extra power. (And the way to do this would be either fork elements-miniscript to add some new crazy script fragment that could only be compiled to Simplicity, or to use some sort of We'd like to extend Miniscript on Elements to include a bit more than just sig/hash/time checks, e.g. to do some basic forms of transaction introspection and oracle signature checks, to make this progarmming model even easier to get started with. But to do that, we need I hope this clarifies our goals and the scope of this project. |
This is subjective, of course. It is just that implementing/reviewing such critical code parts is always a bit anxiety-inducing (at least for me), and thus the effort expended seem extra huge relative to the size of the code. Each implemented opcode is in consensus-critical path, and any bug might be consensus bug. It is not on Bitcoin, so maybe the potential consequences of a bug are not that bad, but at the same time - less eyes for review before merge, less people trying to break it after merge, the bug might lurk for a long time. It seemed to me that goal of the new opcodes is to make it easier to build more expressive miniscript, and this is what most of the people would use, not raw script. And the miniscript -> simplicity link seemed more logical. But if the goal of these is first give the tools to raw script writers, that's fine by me. Given these more specialized opcodes, maybe raw scripts will be smaller an simpler, that's a plus. |
It is definitely anxiety-inducing! But hopefully by only working with fixed-length hashes and EC points, and fixed-width numbers, we can eliminate the majority of the consensus risk, and reduce the review burden of these opcodes. It may be that when we actually start writing code, we find that some of them are excessively branch-heavy or do things where we fear we may touch resource limits or allow division by zero or somehow depend on endianness, and then we'll just drop them. But we did consider this when choosing which opcodes to include. Personally for me, the multi-byte opcode stuff is more worrisome than any individual proposed opcode (but still manageable, to be clear). |
It might be helpful to either add CTV explicitly, or a modified version with whatever elements extensions are needed, bitcoin/bitcoin#21702, or to ensure that the transaction data inspection opcodes are sufficient to construct the template hash on the stack. Currently I think some fields (like scriptsigs) are missing, for legacy address support. |
As a MVP I think we should reduce scope to:
|
Would it be possible to add OP_INSPECTTXSIZE as an extension to OP_INSPECTTX? Advanced covenants in some cases need to enforce fee policies and it’s required to know transaction size in vBytes. Also, OP_INSPECTTXFEE should be very useful since a tx can have multiple fee outputs and it’s very tricky to inspect total fees paid. |
For now, to keep implementation scope down, I'm gonna say no ... you can use If this turns out to be a common pattern we'd be happy to add it in a future tapscript version (alongside the other "experimental" opcodes that are listed in this doc but which we are cutting from the initial implementation). |
@apoelstra, there is no |
I'd like to jump in to also suggest including BIP-119 CheckTemplateVerify, perhaps even instead of the dozen introspection opcodes (I think CTV can fulfill most use-cases these target?), for the sake of providing smart contracts that can be potentially replicated both on main chain and elements in the future. |
Lol, we are definitley not replacing introspection opcodes with CTV. We already have CHECKSIGFROMSTACK+CAT if you want to do covenants in indirect/general ways. We could plausibly introduce CTV in the future as a way to onboard developers who are excited about it, but it's not the direction that we're focusing our script development on. @sanket1729 oh! Lol, I misread @brqgoo as writing "inspect X" i.e. "inspect arbitrary parts of the transaction" rather than "inspect TX". I definitely agree that |
Another thing we might want to bring into scope is widening the |
Fair enough, I can live with either solution for my Liquid projects but would have preferred something that's more likely to find its way to BTC. |
Certainly if/when it looked likely that CTV would get into BTC then we'd pull it into Elements. |
- Define `OP_SUCCESS207` as `OP_MUL64`: pop the first number(8 byte LE) as `b` followed another pop for `a`(8 byte LE). Push `a*b` onto the stack. Push 1 `CScriptNum` if there is no overflow. Overflow behavior defined above. | ||
- Define `OP_SUCCESS208` as `OP_DIV64`: pop the first number(8 byte LE) as `b` followed another pop for `a`(8 byte LE). First push remainder `a%b`(must be non-negative and less than |b|) onto the stack followed by quotient(`a//b`) onto the stack. Abort if `b=0`. Push 1 `CScriptNum` if there is no overflow. Overflow behavior defined above. | ||
- Define `OP_SUCCESS209` as `OP_LESSTHAN64`(cannot fail!): pop the first number(8 byte LE) as `b` followed another pop for `a`(8 byte LE). Push ` a < b`. | ||
- Define `OP_SUCCESS210` as `OP_LESSTHANOREQUAL64`(cannot fail!): pop the first number(8 byte LE) as `b` followed another pop for `a`(8 byte LE). Push ` a <= 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'm torn between having the "less than or equal" opcodes and requiring the user do GREATERTHAN
NOT
. What do others think?
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 think there's a decent amount of value in just having GT in terms of minimalism, but in practice having both GT/LT should be able to yield more efficient scripts...
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.
The concern here is that we are consuming opcodes(already up to 222/254) and we don't want to run out of them in future upgrades.
The previous version of this doc had multi-byte opcodes(opcodes for ec operations, scalar exps etc) which were removed in favor of implementation simplicity.
- Define `OP_SUCCESS222` as `OP_LE32TOLE64`: pop the stack as a 4 byte signed LE. Push the corresponding 8 byte LE number. Cannot fail, useful for conversion of version/sequence. | ||
|
||
6. **Changes to existing Opcodes**: | ||
- Add `OP_CHECKSIGFROMSTACK` and `OP_CHECKSIGFROMSTACKVERIFY` to follow the semantics from bip340-342 when witness program is v1. |
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.
How about we remove CHECKSIGFROMSTACK
and leave only the VERIFY variant?
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 don't feel strongly about it. It's not additional code complexity so might as well have it?
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 agree that both seems reasonable -- although I thought CHECKSIGFROMSTACK was already part of elements?
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.
They are part of elements, but we need to modify them to use BIP340-342 type schnorr signatures. Currently, this uses ECDSA sigs
FYI to readers, Sanket's recent force-push actually rewrites the document to reduce its scope. The new document lists everything we actually plan to deploy on Liquid alongside Taproot. The other opcodes will have to wait for another softfork. |
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.
Pushed another commit addressing @apoelstra's suggestions
- Define `OP_SUCCESS222` as `OP_LE32TOLE64`: pop the stack as a 4 byte signed LE. Push the corresponding 8 byte LE number. Cannot fail, useful for conversion of version/sequence. | ||
|
||
6. **Changes to existing Opcodes**: | ||
- Add `OP_CHECKSIGFROMSTACK` and `OP_CHECKSIGFROMSTACKVERIFY` to follow the semantics from bip340-342 when witness program is v1. |
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 don't feel strongly about it. It's not additional code complexity so might as well have it?
somewhat of a concept NACK towards inspect annex, given that there are no defined uses for annex yet -- when one is soft forked in, it should be enabled then? i think there are some circumstances where being able to put the annex on the stack might be counter to the purpose of the annex itself. |
Is that normative for Elements? I.e., do the other upgrades planned in this release pass such a test? |
Yes, if it looked likely that anything in this planned release were to get into Bitcoin, we would still include it in the planned release. |
@sanket1729 the non- A similar argument applies to |
I mean that is the inclusion of features in this upgrade to Elements an indication that the house view is these are going to be included in Bitcoin? Or would it being clear a feature would not go into Bitcoin be a reason to disinclude from elements? |
Hi @JeremyRubin, I spent some time trying to read BIP119 and figuring out how it might adapt to elements. Some comments in no particular order of importance:
These things might require more discussion, opening a new issue for this |
Opened an issue #1015 for more discussion. |
It is already possible to inspect |
right... that's an interesting observation! |
Sanket pointed out to me that we already have a consensus rule for CHECKSIG that any invalid signature needs to be the null signature. If we extend this rule to CSFS then there is no issue wit h batch verification. |
Hmm, crap, I meant to merge the other doc PR #933. Since this is documentation only I think it's OK to just leave it be, and to make any additional changes in a future PR. |
This PR adds a doc describing suggested new opcodes for better script programming with elements. The purpose of these opcodes to aid easier writing of complex scripts like covenants in elements.
This introduces 1) Opcodes for Streaming hashes, 2) Transaction introspection opcodes 3) 64 byte athematic opcodes 4) Some utility conversion opcodes 5) Crypto opcodes for low-level operations and tweaking 6) A cleaner way to write For loops and 7) Changes to existing opcodes.
The doc also describes a brief rationale for choice. Feedback welcome :)