CashScript / cashscript

⚖️ Easily write and interact with Bitcoin Cash smart contracts
https://cashscript.org
MIT License
112 stars 79 forks source link

Use OP_CODESEPARATOR to increase effective byte limit #98

Closed rkalis closed 2 years ago

rkalis commented 3 years ago

A simple and universal improvement that could be made to covenant contracts is adding an OP_CODESEPARATOR immediately after the constructor arguments (i.e. at the very start of the compiled bytecode).

So for covenants, the constructor arguments are not included in the preimage, meaning that the rest of the bytrecode can be larger while the entire preimage still fits in the 520 byte limit.

One obvious concern with this is that it doesn't work with any contracts that currently use tx.bytecode, since they expect to get the entire bytecode, rather than just the "base" bytecode.

One solution to this could be to detect the usage of tx.bytecode in the contract and only add the OP_CODESEPARATOR if no tx.bytecode is used.

An extension to this could be adding a new covenant variable tx.baseBytecode which indicates that they want to use the "scriptCode" part of the preimage, but they also want to apply OP_CODESEPARATOR to effectively strip the constructor args. This can be an actual use case as some "simulated state" contracts already employ a similar structure of using the "base bytecode" (see e.g. MistCoin).

On the SDK side, the transaction builder needs to be aware of the position of any OP_CODESAPARATORS when constructing the preimage and update the scriptCode accordingly.

This idea was formulated with some valuable brainstorms and feedback from @jcramer and @EyeOfPython.

rkalis commented 2 years ago

Once native introspection is implemented, this does not need to be implemented any more. However, adding an OP_CODESEPARATOR between the constructor args and the bytecode should allow us to make it easier to make "state simulated" contracts. Since then OP_ACTIVEBYTECODE would always be the "base" bytecode, and we could add the "new" state in front of that.

Example syntax (for a contract with name ExampleContract):

bytes34 output = new OutputP2SH(bytes8(1000), hash160(new ExampleContract(tx.locktime + 100, 1000)));
rkalis commented 2 years ago

Closing this issue and continuing the comment about "state simulated contracts" in #106.