Simply is a simple community built CLI for SimplicityHL projects, simplifying building, testing, debugging, and deploying scripts.
cargo install --git https://github.com/starkware-bitcoin/simplySimplicityHL is Rust-like so we'll create a project with a similar structure:
simplicity-p2pk
├ src
│ └ main.simf
└ tests
└ price.wit
We are going to use one of the examples from the SimplicityHL repo. Here is the description:
/*
* HODL VAULT
*
* Lock your coins until the Bitcoin price exceeds a threshold.
*
* An oracle signs a message with the current block height and the current
* Bitcoin price. The block height is compared with a minimum height to prevent
* the use of old data. The transaction is timelocked to the oracle height,
* which means that the transaction becomes valid after the oracle height.
*/
cd simplicity-p2pk
simply buildYou'll find the build artifacts in target/ folder: program bytecode and witness (empty since we haven't provided one).
Any function which name starts with prefix test_ would be considered as a unit test by simply and run separately. Note that this is simply specific feature, not a builtin functionality of SimplicityHL.
simply testIn other words build the program and make sure the witness matches the expected type. We'll use the witness file from the SimplicityHL repo examples.
simply build --witness tests/price.witYou will see the estimated resource usage, in particular we are interested in CPU cost which is measured in mWU (0.001 weight units).
Let's run our program with the provided witness:
simply run --witness tests/price.wit --logging traceWe see that it fails at the check_lock_height call:
Le32(1000, 1000) = false
Verify(false) = ()
CheckLockHeight(1000) = ()
Error: Jet failed during execution: Jet failed during execution
By default simply executes the program with the default environment, and we need to specify the transaction lock time (in blocks) in order to unlock the funds:
simply run --witness tests/price.wit --logging trace --lock-time 1001Ok great, we made some progress! The execution now fails at checksig:
Le32(1000, 1000) = false
Verify(false) = ()
CheckLockHeight(1000) = ()
Le32(100000, 100000) = false
Verify(false) = ()
Sha256Ctx8Init() = (list![], (0, 0x1a827999eed9eba14f1bbcdca953fd4e9443949fe6c15a2307e0f66ad6f83346))
Sha256Ctx8Add4((list![], (0, 0x1a827999eed9eba14f1bbcdca953fd4e9443949fe6c15a2307e0f66ad6f83346)), 1073742074) = (list![], (0, 0x1a827999eed9eba14f1bbcdca953fd4e9443949fe6c15a2307e0f66ad6f83346))
Sha256Ctx8Add4((list![], (0, 0x1a827999eed9eba14f1bbcdca953fd4e9443949fe6c15a2307e0f66ad6f83346)), 1073766824) = (list![], (0, 0x1a827999eed9eba14f1bbcdca953fd4e9443949fe6c15a2307e0f66ad6f83346))
Sha256Ctx8Finalize((list![], (0, 0x1a827999eed9eba14f1bbcdca953fd4e9443949fe6c15a2307e0f66ad6f83346))) = 0xb31871164d4262343185fb3bcea586061f3a0d4e13b95cf5df0229f792a0e2e2
Bip0340Verify((0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798, 0xb31871164d4262343185fb3bcea586061f3a0d4e13b95cf5df0229f792a0e2e2), 0x90231b8de96a1f940ddcf406fe8389417ca8fb0b03151608e2f94b31b443a7e0d26a12e437df69028f09027c37d5f6742a10c1e8864061d119b8bbce962d26d3) = ()
SigAllHash() = 0x7ef747fe22fb5beacac2c6d7369cf4ff3ea96ba9382e5fd9ff09b77809f3e69c
DBG: jet::sig_all_hash() = 0x7ef747fe22fb5beacac2c6d7369cf4ff3ea96ba9382e5fd9ff09b77809f3e69c
Bip0340Verify((0xc6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5, 0x7ef747fe22fb5beacac2c6d7369cf4ff3ea96ba9382e5fd9ff09b77809f3e69c), 0xf2341f571f069216edfc72822f6094b8ec339c2f72dc64aea0eed1e3d60abf4572fdd04618e5b5bc672ccd71cfaf125b6c1b101aeca3a7b938fe83932ab38743) = ()
Error: Jet failed during execution: Jet failed during execution
Note the DBG log message: this is produced by dbg!() macro which you can use to wrap expressions.
The owner signature is incorrect and we need to generate a new one. Luckily simply has a command for that.
Given the message printed by DBG:
simply sign --message 7ef747fe22fb5beacac2c6d7369cf4ff3ea96ba9382e5fd9ff09b77809f3e69c Now we need to edit both the public key (in code) and signature (in witness) and rerun the program.
Next we will generate a P2TR address for a script path locked with our program (key path disabled):
simply depositGo to https://liquidtestnet.com/faucet and get some coins to the generated address.
Remember the txid of the funding transaction!
Look up the deposit transaction on https://liquid.network/testnet and run:
simply withdraw --txid TXID --witness tests/price.wit --destination DEST_ADDRAaand it fails :( The reason is that faucet transaction has locktime 0 so our program fails at that check.
Your assignment: change the program to temporarily ignore the locktime so that you can withdraw funds.
Good luck!