Skip to content

Commit

Permalink
Fix a few missed version number updates in tests and docs
Browse files Browse the repository at this point in the history
  • Loading branch information
rkalis committed Oct 16, 2023
1 parent 65f18f9 commit 63d31cb
Show file tree
Hide file tree
Showing 4 changed files with 9 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pragma cashscript ^0.8.0;
pragma cashscript >=0.8.0;

contract Test() {
function test() {
Expand Down
4 changes: 2 additions & 2 deletions packages/cashscript/test/fixture/announcement.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
}
],
"bytecode": "6a 6d02 OP_SIZE OP_SWAP OP_CAT OP_CAT 4120636f6e7472616374206d6179206e6f7420696e6a75726520612068756d616e206265696e67206f722c207468726f75676820696e616374696f6e2c20616c6c6f7720612068756d616e206265696e6720746f20636f6d6520746f206861726d2e OP_SIZE OP_DUP 4b OP_GREATERTHAN OP_IF 4c OP_SWAP OP_CAT OP_ENDIF OP_SWAP OP_CAT OP_CAT OP_0 OP_OUTPUTVALUE OP_0 OP_NUMEQUALVERIFY OP_0 OP_OUTPUTBYTECODE OP_EQUALVERIFY e803 OP_INPUTINDEX OP_UTXOVALUE OP_OVER OP_SUB OP_DUP OP_ROT OP_GREATERTHANOREQUAL OP_IF OP_1 OP_OUTPUTBYTECODE OP_INPUTINDEX OP_UTXOBYTECODE OP_EQUALVERIFY OP_1 OP_OUTPUTVALUE OP_OVER OP_NUMEQUALVERIFY OP_ENDIF OP_DROP OP_1",
"source": "pragma cashscript ^0.8.0;\n\n/* This is a contract showcasing covenants outside of regular transactional use.\n * It enforces the contract to make an \"announcement\" on Memo.cash, and send the\n * remainder of contract funds back to the contract.\n */\ncontract Announcement() {\n function announce() {\n // Create the memo.cash announcement output\n bytes announcement = new LockingBytecodeNullData([\n 0x6d02,\n bytes('A contract may not injure a human being or, through inaction, allow a human being to come to harm.')\n ]);\n\n // Check that the first tx output matches the announcement\n require(tx.outputs[0].value == 0);\n require(tx.outputs[0].lockingBytecode == announcement);\n\n // Calculate leftover money after fee (1000 sats)\n // Check that the second tx output sends the change back if there's enough leftover for another announcement\n int minerFee = 1000;\n int changeAmount = tx.inputs[this.activeInputIndex].value - minerFee;\n if (changeAmount >= minerFee) {\n require(tx.outputs[1].lockingBytecode == tx.inputs[this.activeInputIndex].lockingBytecode);\n require(tx.outputs[1].value == changeAmount);\n }\n }\n}\n",
"source": "pragma cashscript ^0.9.0;\n\n/* This is a contract showcasing covenants outside of regular transactional use.\n * It enforces the contract to make an \"announcement\" on Memo.cash, and send the\n * remainder of contract funds back to the contract.\n */\ncontract Announcement() {\n function announce() {\n // Create the memo.cash announcement output\n bytes announcement = new LockingBytecodeNullData([\n 0x6d02,\n bytes('A contract may not injure a human being or, through inaction, allow a human being to come to harm.')\n ]);\n\n // Check that the first tx output matches the announcement\n require(tx.outputs[0].value == 0);\n require(tx.outputs[0].lockingBytecode == announcement);\n\n // Calculate leftover money after fee (1000 sats)\n // Check that the second tx output sends the change back if there's enough leftover for another announcement\n int minerFee = 1000;\n int changeAmount = tx.inputs[this.activeInputIndex].value - minerFee;\n if (changeAmount >= minerFee) {\n require(tx.outputs[1].lockingBytecode == tx.inputs[this.activeInputIndex].lockingBytecode);\n require(tx.outputs[1].value == changeAmount);\n }\n }\n}\n",
"compiler": {
"name": "cashc",
"version": "0.8.0-next.0"
},
"updatedAt": "2023-02-10T15:22:49.703Z"
}
}
4 changes: 2 additions & 2 deletions packages/cashscript/test/fixture/mecenas.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@
}
],
"bytecode": "OP_3 OP_PICK OP_0 OP_NUMEQUAL OP_IF OP_0 OP_OUTPUTBYTECODE 76a914 OP_ROT OP_CAT 88ac OP_CAT OP_EQUALVERIFY e803 OP_INPUTINDEX OP_UTXOVALUE OP_DUP OP_4 OP_PICK OP_SUB OP_2 OP_PICK OP_SUB OP_DUP OP_5 OP_PICK OP_4 OP_PICK OP_ADD OP_LESSTHANOREQUAL OP_IF OP_0 OP_OUTPUTVALUE OP_2OVER OP_SWAP OP_SUB OP_NUMEQUALVERIFY OP_ELSE OP_0 OP_OUTPUTVALUE OP_5 OP_PICK OP_NUMEQUALVERIFY OP_1 OP_OUTPUTBYTECODE OP_INPUTINDEX OP_UTXOBYTECODE OP_EQUALVERIFY OP_1 OP_OUTPUTVALUE OP_OVER OP_NUMEQUALVERIFY OP_ENDIF OP_2DROP OP_2DROP OP_2DROP OP_1 OP_ELSE OP_3 OP_ROLL OP_1 OP_NUMEQUALVERIFY OP_3 OP_PICK OP_HASH160 OP_ROT OP_EQUALVERIFY OP_2SWAP OP_CHECKSIG OP_NIP OP_NIP OP_ENDIF",
"source": "pragma cashscript ^0.8.0;\n\n/* This is an unofficial CashScript port of Licho's Mecenas contract. It is\n * not compatible with Licho's EC plugin, but rather meant as a demonstration\n * of covenants in CashScript.\n * The time checking has been removed so it can be tested without time requirements.\n */\ncontract Mecenas(bytes20 recipient, bytes20 funder, int pledge/*, int period */) {\n function receive() {\n // require(tx.age >= period);\n\n // Check that the first output sends to the recipient\n require(tx.outputs[0].lockingBytecode == new LockingBytecodeP2PKH(recipient));\n\n int minerFee = 1000;\n int currentValue = tx.inputs[this.activeInputIndex].value;\n int changeValue = currentValue - pledge - minerFee;\n\n // If there is not enough left for *another* pledge after this one, we send the remainder to the recipient\n // Otherwise we send the remainder to the recipient and the change back to the contract\n if (changeValue <= pledge + minerFee) {\n require(tx.outputs[0].value == currentValue - minerFee);\n } else {\n require(tx.outputs[0].value == pledge);\n require(tx.outputs[1].lockingBytecode == tx.inputs[this.activeInputIndex].lockingBytecode);\n require(tx.outputs[1].value == changeValue);\n }\n }\n\n function reclaim(pubkey pk, sig s) {\n require(hash160(pk) == funder);\n require(checkSig(s, pk));\n }\n}\n",
"source": "pragma cashscript ^0.9.0;\n\n/* This is an unofficial CashScript port of Licho's Mecenas contract. It is\n * not compatible with Licho's EC plugin, but rather meant as a demonstration\n * of covenants in CashScript.\n * The time checking has been removed so it can be tested without time requirements.\n */\ncontract Mecenas(bytes20 recipient, bytes20 funder, int pledge/*, int period */) {\n function receive() {\n // require(tx.age >= period);\n\n // Check that the first output sends to the recipient\n require(tx.outputs[0].lockingBytecode == new LockingBytecodeP2PKH(recipient));\n\n int minerFee = 1000;\n int currentValue = tx.inputs[this.activeInputIndex].value;\n int changeValue = currentValue - pledge - minerFee;\n\n // If there is not enough left for *another* pledge after this one, we send the remainder to the recipient\n // Otherwise we send the remainder to the recipient and the change back to the contract\n if (changeValue <= pledge + minerFee) {\n require(tx.outputs[0].value == currentValue - minerFee);\n } else {\n require(tx.outputs[0].value == pledge);\n require(tx.outputs[1].lockingBytecode == tx.inputs[this.activeInputIndex].lockingBytecode);\n require(tx.outputs[1].value == changeValue);\n }\n }\n\n function reclaim(pubkey pk, sig s) {\n require(hash160(pk) == funder);\n require(checkSig(s, pk));\n }\n}\n",
"compiler": {
"name": "cashc",
"version": "0.8.0-next.0"
},
"updatedAt": "2023-02-10T15:22:51.736Z"
}
}
8 changes: 4 additions & 4 deletions website/docs/guides/optimization.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ As an example, below is a simple [hodl](https://github.com/mainnet-pat/hodl_ec_p

```solidity
// hodl.cash
pragma cashscript ^0.8.0;
pragma cashscript ^0.9.0;
contract hodl(
int locktime,
Expand Down Expand Up @@ -66,7 +66,7 @@ cashc hodl.cash | grep bytecode;

As you can see, in this case, the logic to spend time-locked funds and verify the spender takes up six (6) bytes of information.

The simplest workflow to optimize the redeem script of `hodl.cash`, or any contract, would be to compile it directly from the command line with `cashc` then look at the `bytecode` field on the generated artifact to see if there are any unnecessary or duplicative operations.
The simplest workflow to optimize the redeem script of `hodl.cash`, or any contract, would be to compile it directly from the command line with `cashc` then look at the `bytecode` field on the generated artifact to see if there are any unnecessary or duplicative operations.

In this toy example, the redeem script is so small there isn't a lot of need or use in making it smaller. The [anyhedge contracts](https://gitlab.com/GeneralProtocols/anyhedge/contracts/) are again a great example of a more complex progressive optimization over time.

Expand All @@ -77,13 +77,13 @@ There are two important alternative approaches to optimization to consider.

### OP_NOP

>We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%.
>We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%.
It's worth considering whether optimizing the redeem script is necessary at all. If the contract is accepted by the network, and there is no glaring inefficiency in the bytecode, perhaps the best optimization is to not to obsess prematurely about things like blocksize.

### Hyper Introspect-imization

Finally, there have been a number of novel approaches taken since 2009 to approximate higher level functionality with bitcoin's deliberately restricted instruction set. These techniques include using a cumbersome [old covenant style](https://fc16.ifca.ai/bitcoin/papers/MES16.pdf) of storing data, [`OP_CODESEPARATOR`](https://web.archive.org/web/20210507164307/https://mistcoin.org/#appendix-b) to split contracts around an old 520-byte limitation, and hiding redeem paths in "sidecars".

It's **very** important to be up-to-date on documentation covering introspection, as it greatly simplifies using state and writing more complex contracts. If a contract has been developed from an old example or a pre-introspection design pattern, the fastest way to achieve significant optimization is to utilize the [the latest introspection design patterns](./covenants).
It's **very** important to be up-to-date on documentation covering introspection, as it greatly simplifies using state and writing more complex contracts. If a contract has been developed from an old example or a pre-introspection design pattern, the fastest way to achieve significant optimization is to utilize the [the latest introspection design patterns](./covenants).

1 comment on commit 63d31cb

@vercel
Copy link

@vercel vercel bot commented on 63d31cb Oct 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.