CashScript / cashscript

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

Split preimage up into chunks #79

Closed rkalis closed 3 years ago

rkalis commented 3 years ago

The max stack push size in BCH Script is 520 bytes. Because the redeem script in P2SH needs to be pushed to the stack, there is an effective size limit on P2SH scripts of 520 bytes. However, when using covenants, the entire preimage needs to be pushed to the stack, which includes the redeem script + around 160 bytes of other data. Which puts an effective limit of 360 bytes on the redeem script, If it is pushed to the stack in its entirety.

Currently, the CashScript compiler expects a full preimage to be provided by the CashScript SDK, and the CashScript SDK provides it. Then the compiled CashScript contract verifies the preimage and cuts out only the parts that are needed by the contract.

In order to provide developers with more bytesize space for their contracts is to push the preimage in three chunks (pre-bytecode, bytecode, post-bytecode). This effectively resets the bytecode limit to 520 bytes (minus 3 bytes for the VarInt). Then the contract code reassembles the preimage (OP_CAT OP_CAT), and then does everything else the same as it already did. So for the price of two opcodes we receive 160 extra bytes.

This could be taken further. Because we don't need to split the preimage at any specific places, we could also provide it in two chunks (split in the middle). Then it only takes one OP_CAT to reassemble, which brings the price for 160 extra bytes down to one opcode, which seems very reasonable.

Of course this needs to be implemented in a way so that contracts compiled with the old compiler still work with newer versions of the SDK, but that is doable.

I would love to get some feedback on this proposal, since there might be security implications with passing the preimage in multiple chunks. I feel like it should be fine, since the contract immediately concats them and then uses it as if it was provided as the full preimage.

rkalis commented 3 years ago

Obviously, this won't work :sweat_smile:

The result of OP_CAT also needs to be <520 bytes.