Skip to content

SimplicityHL tutorial: HODL vault with OP_CSFS

License

starkware-bitcoin/scaffold-simplicity

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Scaffold Simplicity

0. Install Rust

1. Install Simply CLI

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/simply

2. Create a new project

SimplicityHL is Rust-like so we'll create a project with a similar structure:

simplicity-p2pk
├ src
│ └ main.simf
└ tests
  └ price.wit

3. Write the program

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.
 */

4. Build program

cd simplicity-p2pk
simply build

You'll find the build artifacts in target/ folder: program bytecode and witness (empty since we haven't provided one).

5. Write unit test

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 test

6. Prepare witness

In 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.wit

You will see the estimated resource usage, in particular we are interested in CPU cost which is measured in mWU (0.001 weight units).

7. Debug the program

Let's run our program with the provided witness:

simply run --witness tests/price.wit --logging trace

We 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 1001

Ok 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.

8. Create deposit address

Next we will generate a P2TR address for a script path locked with our program (key path disabled):

simply deposit

Go to https://liquidtestnet.com/faucet and get some coins to the generated address.
Remember the txid of the funding transaction!

9. Spend locked funds

Look up the deposit transaction on https://liquid.network/testnet and run:

simply withdraw --txid TXID --witness tests/price.wit --destination DEST_ADDR

Aaand 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!

About

SimplicityHL tutorial: HODL vault with OP_CSFS

Topics

Resources

License

Stars

Watchers

Forks