Skip to content

Blockstream/simplicity-codespace

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Simplicity Workshop

A GitHub Codespace workshop for writing and deploying Simplicity smart contracts on Liquid Testnet.

Open in GitHub Codespaces


What is Simplicity?

Simplicity is a low-level, formally-verified smart contract language designed for Bitcoin and Liquid. Programs are represented as typed combinator trees, giving them provable resource bounds and a clean formal semantics. SimplicityHL is a higher-level language that compiles down to Simplicity.


Toolchain

The Codespace includes:

Tool Purpose
simc SimplicityHL compiler — turns .simf source into a compiled program
hal-simplicity HAL tools — inspect programs, build PSETs, sign, broadcast
lwk_cli Liquid Wallet Kit CLI — wallet and transaction utilities

All tools are pre-built from source and available on PATH when the Codespace starts.


Exercises

Work through the exercises in order. Each one introduces new concepts.

The simplest possible Simplicity contract: coins move only when the holder of a given public key produces a valid Schnorr signature.

Concepts: jet::bip_0340_verify, witness, jet::sig_all_hash

cd exercises/01-p2pk
simc p2pk.simf                    # compile and inspect
bash demo.sh                      # end-to-end testnet demo

A 2-of-3 multisig contract. Three public keys are embedded in the contract; any two valid signatures unlock the coins.

Concepts: Option<T>, arrays, helper functions, checksig_add pattern

cd exercises/02-p2ms
simc p2ms.simf
bash demo.sh

A vault with a state commitment. A single signature approves a transaction, but the state commitment value must be 2 before the withdrawal is permitted. The update transaction is available to increment the state. Thus, if the contract is funded with state equal to 0, three separate transactions in sequence are required in order to withdraw the coins.

Concepts: State commitment, state load, state save, multiple contract actions, covenant pattern

cd exercises/03-third-time
simc third-time.simf
bash demo.sh

A hashed timelock contract. This has two branches (complete and timeout). This exercise currently only demonstrates the "complete" branch in which the assets are claimed by revealing a secret password (hash preimage). The HTLC pattern is useful for completing trustless swaps, including between different chains that may even use different technologies.

To redeem this via the "timeout" branch (indicating that the swap was presumed to have failed due to inaction by the counterparty), we would need to build a PSET that asserts the relevant timelock is satisfied, as well as a witness indicating that we're using that branch rather than the "complete" branch.

Concepts: Hashing, multiple contract actions, timelocks

cd exercises/04-htlc
simc htlc.simf
bash demo.sh

How a Demo Works

Each demo.sh walks through the full lifecycle of a Simplicity contract on testnet:

1. Compile         simc <program>.simf
2. Get address     hal-simplicity simplicity info <compiled>
3. Fund            Liquid Testnet faucet → contract address
4. Build PSET      hal-simplicity simplicity pset create ...
5. Sign            hal-simplicity simplicity sighash ...
6. Inject witness  update .wit file with real signature(s)
7. Recompile       simc <program>.simf -w <witness>.wit
8. Finalize        hal-simplicity simplicity pset finalize ...
9. Broadcast       curl → Liquid Testnet API

Run any script with an optional destination address, or omit it to return funds to the faucet:

bash demo.sh [your-liquid-testnet-address]

Writing Your Own Contract

  1. Create a new .simf file:
fn main() {
    // your logic here
}
  1. Compile to check for errors:
simc mycontract.simf
  1. Inspect the compiled program:
PROGRAM=$(simc mycontract.simf | sed '1d; 3,$d')
hal-simplicity simplicity info "$PROGRAM" | jq
  1. Create a .wit file for any witness values your contract needs, then compile with it:
simc mycontract.simf -w mycontract.wit
  1. Follow the same PSET lifecycle as the demo scripts to fund and spend on testnet.

Key Concepts

Witnesses

Witness values (e.g. signatures) are provided at spend time, not at contract creation. They live in .wit JSON files:

{
    "MY_SIGNATURE": {
        "value": "0x...",
        "type": "Signature"
    }
}

Reference them in Simplicity as witness::MY_SIGNATURE.

Internal Key

All contracts use a BIP-341 NUMS (nothing-up-my-sleeve) internal key so that the Taproot key-path spend is provably disabled:

50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0

Test Keys

The demo scripts use the secp256k1 generator multiples as private keys (1, 2, 3). The corresponding public keys are embedded in the contracts. These are well-known test vectors — never use them with real funds.


Resources

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors