CHIP 2024-12 OP_EVAL: Function Evaluation

Word/function signature verification

I see some discussion about function signatures being generally useful in programming (I agree), and that being somehow an argument for OP_EXEC and/or “stack isolation”.

Please note that Libauth and Bitauth IDE have supported compile-time verification of “function signatures” and behavior since 2020 – I’ve found it invaluable for optimizing various constructions (e.g. P2SH assurance contract - #15 by bitjson predates CashTokens lock-in).

Adding – via a consensus upgrade – some half-baked runtime checks to approximate function signatures wouldn’t simplify or improve our current capabilities.

If I understand correctly, @andrewstone designed Nexa’s OP_EXEC.

@andrewstone, do you disagree with my review of OP_EXEC? I also responded to you here:

https://x.com/bitjson/status/1880227699198714348

GAndrewStone: TBH, tl;dr. It allows the template to execute untrusted holder constraints.

OP_EXEC is like requiring motorcycle helmets in a swimming pool.

It simply misunderstands contract development.

Even with the correction I described (@NexaMoney’s version is even more nonsensical) – OP_EXEC adds no security and harms protocol complexity, contract complexity, and overall transaction sizes when compared to OP_EVAL.

If you disagree, it should be easy to provide a counterexample that doesn’t hand-wave about context (e.g. leaving a blank for the “untrusted code”). Given any particular contract, what exploit is prevented by OP_EXEC’s stack isolation? Please be sure to include threat model info, then I can help you optimize it by switching to OP_EVAL.


Again, unless someone can produce a credible counterexample (with enough context to review), I don’t plan to spend more time on OP_EXEC.

Thanks Jason for a very enlightening series of posts.

You asked a bunch of times to show a “counterexample”, which was your choice of words indicating an example that did something nasty. Inside of the VM. Knowing full well that a VM is already a sand-box.
Repeating that so often while ignoring all the actually quotable objections I made is really quite enlightening.

You’re arguing that stack isolation is “not good” and that “experienced programmers will be misled” by “intuition”. Yeah, because who would have the audacity to ask people with experience! Where is the fun in that?

Ok, lets leave the schoolyard and sum up the actual facts;

  • op-exec from nexa is super expensive in every usage. Nobody likes that one.
  • op-eval avoids a function signature and avoid stack safety to be less expensive.
  • a simple op-exec1 (lets use my design for discussion sake) is not expensive. Is actually cheaper than op-eval for repeated cases. And Jason stated he expects hundreds or more calls in some cases. Arguing cost makes op-eval lose.
  • a simple op-exec1 design with pushing of a single int for argument count allows stack safety.

A argument count as part of a function description has 2 main advantages:

  1. a toolset like an IDE can do compile time checking. Notice that “compile time” is per definition at the time of transaction construction. I mean, no full node compiles, so this one should have been obvious. But we got someone misunderstanding this, so lets be clear. A transaction with a single output that has a bunch of pre-defined subroutines can be used by a contract you’re building. You’ll compile the contract using the binary library and voila, you have compile time safety.
    Or, in short, this 1 byte that indicates the number of arguments is the simplest form of an API-docs for your IDE to use. Pretty cheap, if you ask me!

  2. a much more important usage of an argument count is the stack protection.
    Now, this is not about being able to escape your VM. That suggestion is more like a “when did you stop hitting your wife” question.
    Instread, this is about avoiding all the hallmarks of unsafe code.

Arguing “it is not worth anything” is a great way of saying you don’t actually have an argument against it, you just don’t like it. Fine, don’t like it. It still is valuable to others and practically free.

Unsafe code in this context is about unpredictable code. If I use this library method in my contract, will it do funny stuff? Will my money be stolen because I didn’t manage to understand the code I used from another dev?

Being able to chop up a script on-stack, partly execute it with usage of codeseparators and indeed altering or reading the stack outside your subroutine, those are all really nasty things that makes code very hard to understand and near impossible to test to be “correct” when used in not yet written scripts.

But the bottom line here is that this is money. This is not some toy virtual machine to do cool new things with. Well, not new, nothing here is novel. Jason may think he came up with this all on his own, but sorry to say that he’s about 60 years late to that party. One way or another any and all options we pick have been tried before.
Maybe that knowledge helps letting the ego’s deflate and we can get back to picking something that actually is good for Bitcoin Cash.

I started the discussion some time ago here:

My opinions on each item above in the original post.

And, to repeat, op-eval doesn’t just allow spaghetti code that can steal your funds, it ALSO has a pretty serious security issue by default:
code can come from any place without being known at the time of building the transaction. That allows injection of untrusted code and that means bugs can steal your money.

You can claim you can write code to verify your inputs, but first of all this after DECADES is still the number one issue in software: unverified inputs. (xkcd).
And that just throws out of the window the entire argument that it would somehow be cheaper byte-wise, being forced to write your own input verification.

None of the arguments hold water, which is why Jason isn’t replying to my posts, which is why he uses very angry and dismissive language (tit for tat) because he knows he’s in the wrong and his lovely op-eval is rotten under the surface.

Which others, how many smart contracts have you designed? Let’s hear from these others.

It’s not even his (it came from Gavin, remember?) and it is certainly not rotten, it is the preferred solution.

1 Like

@tom again, unless someone can produce a credible counterexample (with enough context to review), I don’t plan to spend more time reviewing stack isolation.

And I’d go back further than that! There are many decades of prior art here – if anything, this CHIP is taken more from Chuck Moore than Gavin or any of the other 2012 proposals. OP_EVAL gets BCH VM bytecode to a “fully capable” Forth dialect.

On the other hand, the various 2012 proposals did nonsensical things like clearing stacks and preventing “nesting” – i.e. functions calling functions – and generally misunderstood the control stack and/or how non-trivial Forth programs are factored. (Understandable for the time: VM limits were a huge, untenable problem that overshadowed clear thinking about a lot of topics, and most “smart contract” ideas were very hypothetical. We’re spoiled now to have more certainty on both.)