Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ itertools = "0.13.0"
arbitrary = { version = "1", optional = true, features = ["derive"] }
clap = "4.5.37"
chumsky = "0.11.2"
semver = "1.0.27"

[target.wasm32-unknown-unknown.dependencies]
getrandom = { version = "0.2", features = ["js"] }
Expand Down
30 changes: 30 additions & 0 deletions doc/versioning.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Compiler Versioning

The SimplicityHL compiler enforces strict version compatibility to prevent contracts from silently breaking due to compiler updates, semantic changes, or new language features.

Every `.simf` file must begin with a compiler version directive:
```rust
simc ">=0.6.0";
```

## Semantic Versioning (SemVer)

The compiler uses standard Semantic Versioning rules to evaluate whether a file is compatible with the currently running compiler. You can use operators to define acceptable ranges:

* **Caret (`^`) or Bare strings:** `^0.6.0` or `0.6.0`. Allows patch-level and minor-level updates that do not modify the left-most non-zero digit. (e.g., `^0.6.0` allows `0.6.1`, but rejects `0.7.0`).
* **Tilde (`~`):** `~0.6.0`. Allows only patch-level updates. (e.g., `~0.6.0` allows `0.6.1`, but rejects `0.6.2` if it introduces new minor features).
* **Exact (`=`):** `=0.6.0`. Strictly requires this exact version of the compiler.
* **Inequalities (`>`, `>=`, `<`, `<=`):** `>=0.6.0`. Allows any compiler version equal to or newer than `0.6.0`.
* **Wildcards (`*`, `x`):** `0.x.x`. Allows any version matching the specified major release.
* **Multiple Bounds:** `>=0.6.0, <1.0.0`. You can combine operators with a comma.

### Pre-release versions
If the compiler is currently on a pre-release version (e.g., `0.6.0-rc.0`), it will only match against contracts that explicitly request that exact pre-release base, or contracts that safely encompass the base version.

## Multi-File Enforcement

Version checking is performed eagerly immediately after the initial syntax parsing, before dependency resolution and semantic analysis occur. When building a multi-file project, the compiler driver evaluates the version directive of the `main.simf` entry point, as well as the directives of every external library file imported via the `--dep` flag.

If *any* file in the dependency graph requires a compiler version that is incompatible with the currently running compiler, the driver immediately halts compilation.

This mathematical guarantee ensures that an older, stable library cannot be accidentally compiled with an incompatible compiler without the developer's explicit consent.
2 changes: 2 additions & 0 deletions examples/array_fold.simf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
simc ">=0.6.0";

fn sum(elt: u32, acc: u32) -> u32 {
let (_, acc): (bool, u32) = jet::add_32(elt, acc);
acc
Expand Down
4 changes: 4 additions & 0 deletions examples/array_fold_2n.simf
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
simc ">=0.6.0";

// From https://github.com/BlockstreamResearch/SimplicityHL/issues/153



fn sum(elt: u32, acc: u32) -> u32 {
let (_, acc): (bool, u32) = jet::add_32(elt, acc);
acc
Expand Down
2 changes: 2 additions & 0 deletions examples/cat.simf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
simc ">=0.6.0";

fn main() {
let ab: u16 = <(u8, u8)>::into((0x10, 0x01));
let c: u16 = 0x1001;
Expand Down
4 changes: 4 additions & 0 deletions examples/ctv.simf
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
simc ">=0.6.0";

/*
* This program is an emulation of CTV using simplicity
*
* Instead of specifying the template hash as in BIP CTV,
* we require the user to specify all the components of the sighash
* that they want to commit.
*/


fn main() {
let ctx: Ctx8 = jet::sha_256_ctx_8_init();
let ctx: Ctx8 = jet::sha_256_ctx_8_add_4(ctx, jet::version());
Expand Down
4 changes: 4 additions & 0 deletions examples/escrow_with_delay.simf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
simc ">=0.6.0";

/*
* ESCROW WITH DELAY
*
Expand All @@ -7,6 +9,8 @@
*
* https://docs.ivylang.org/bitcoin/language/ExampleContracts.html#escrowwithdelay
*/


fn not(bit: bool) -> bool {
<u1>::into(jet::complement_1(<bool>::into(bit)))
}
Expand Down
2 changes: 2 additions & 0 deletions examples/hash_loop.simf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
simc ">=0.6.0";

// Add counter to streaming hash and finalize when the loop exists
fn hash_counter_8(ctx: Ctx8, unused: (), byte: u8) -> Either<u256, Ctx8> {
let new_ctx: Ctx8 = jet::sha_256_ctx_8_add_1(ctx, byte);
Expand Down
4 changes: 4 additions & 0 deletions examples/hodl_vault.simf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
simc ">=0.6.0";

/*
* HODL VAULT
*
Expand All @@ -8,6 +10,8 @@
* the use of old data. The transaction is timelocked to the oracle height,
* which means that the transaction becomes valid after the oracle height.
*/


fn checksig(pk: Pubkey, sig: Signature) {
let msg: u256 = jet::sig_all_hash();
jet::bip_0340_verify((pk, msg), sig);
Expand Down
4 changes: 4 additions & 0 deletions examples/htlc.simf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
simc ">=0.6.0";

/*
* HTLC (Hash Time-Locked Contract)
*
Expand All @@ -9,6 +11,8 @@
*
* https://docs.ivylang.org/bitcoin/language/ExampleContracts.html#htlc
*/


fn sha2(string: u256) -> u256 {
let hasher: Ctx8 = jet::sha_256_ctx_8_init();
let hasher: Ctx8 = jet::sha_256_ctx_8_add_32(hasher, string);
Expand Down
4 changes: 4 additions & 0 deletions examples/last_will.simf
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
simc ">=0.6.0";

/*
* LAST WILL
*
* The inheritor can spend the coins if the owner doesn't move the them for 180
* days. The owner has to repeat the covenant when he moves the coins with his
* hot key. The owner can break out of the covenant with his cold key.
*/


fn checksig(pk: Pubkey, sig: Signature) {
let msg: u256 = jet::sig_all_hash();
jet::bip_0340_verify((pk, msg), sig);
Expand Down
2 changes: 2 additions & 0 deletions examples/local_crate/main.simf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
simc ">=0.6.0";

use crate::math::add;

fn main() {
Expand Down
2 changes: 2 additions & 0 deletions examples/local_crate/math.simf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
simc ">=0.6.0";

pub fn add(a: u32, b: u32) -> u32 {
let (_, sum): (bool, u32) = jet::add_32(a, b);
sum
Expand Down
2 changes: 2 additions & 0 deletions examples/multiple_deps/main.simf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
simc ">=0.6.0";

use merkle::build_root::{get_root, hash as and_hash};
use base_math::simple_op::hash as or_hash;

Expand Down
2 changes: 2 additions & 0 deletions examples/multiple_deps/math/simple_op.simf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
simc ">=0.6.0";

pub fn hash(x: u32, y: u32) -> u32 {
jet::xor_32(x, y)
}
2 changes: 2 additions & 0 deletions examples/multiple_deps/merkle/build_root.simf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
simc ">=0.6.0";

use math::simple_op::hash as temp_hash;

pub fn get_root(tx1: u32, tx2: u32) -> u32 {
Expand Down
3 changes: 3 additions & 0 deletions examples/non_interactive_fee_bump.simf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
simc ">=0.6.0";

/*
* NON-INTERACTIVE FEE BUMPING
*
Expand All @@ -12,6 +14,7 @@
* sponsors, Child-Pays-For-Parent (CPFP), or anchor outputs, simplifying fee management for transaction inclusion.
*/


// This function computes a signature hash for transactions that allows non-interactive fee bumping.
// It omits certain fields from the transaction that can be modified by anyone,
// specifically nLockTime and change/fee outputs amounts.
Expand Down
4 changes: 4 additions & 0 deletions examples/p2ms.simf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
simc ">=0.6.0";

/*
* PAY TO MULTISIG
*
Expand All @@ -6,6 +8,8 @@
*
* https://docs.ivylang.org/bitcoin/language/ExampleContracts.html#lockwithmultisig
*/


fn not(bit: bool) -> bool {
<u1>::into(jet::complement_1(<bool>::into(bit)))
}
Expand Down
4 changes: 4 additions & 0 deletions examples/p2pk.simf
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
simc ">=0.6.0";

/*
* PAY TO PUBLIC KEY
*
* The coins move if the person with the given public key signs the transaction.
*
* https://docs.ivylang.org/bitcoin/language/ExampleContracts.html#lockwithpublickey
*/


fn main() {
jet::bip_0340_verify((param::ALICE_PUBLIC_KEY, jet::sig_all_hash()), witness::ALICE_SIGNATURE)
}
4 changes: 4 additions & 0 deletions examples/p2pkh.simf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
simc ">=0.6.0";

/*
* PAY TO PUBLIC KEY HASH
*
Expand All @@ -6,6 +8,8 @@
*
* https://docs.ivylang.org/bitcoin/language/ExampleContracts.html#lockwithpublickeyhash
*/


fn sha2(string: u256) -> u256 {
let hasher: Ctx8 = jet::sha_256_ctx_8_init();
let hasher: Ctx8 = jet::sha_256_ctx_8_add_32(hasher, string);
Expand Down
2 changes: 2 additions & 0 deletions examples/pattern_matching.simf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
simc ">=0.6.0";

fn main() {
let complex_pattern: Either<(u32, u32, (u1, u1)), [u1; 8]> = Left((32, 3, (0, 1)));

Expand Down
4 changes: 4 additions & 0 deletions examples/presigned_vault.simf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
simc ">=0.6.0";

/*
* PRESIGNED VAULT
*
Expand All @@ -16,6 +18,8 @@
*
* https://docs.ivylang.org/bitcoin/language/ExampleContracts.html#vaultspend
*/


fn checksig(pk: Pubkey, sig: Signature) {
let msg: u256 = jet::sig_all_hash();
jet::bip_0340_verify((pk, msg), sig);
Expand Down
4 changes: 4 additions & 0 deletions examples/reveal_collision.simf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
simc ">=0.6.0";

/*
* REVEAL COLLISION
*
Expand All @@ -8,6 +10,8 @@
*
* https://docs.ivylang.org/bitcoin/language/ExampleContracts.html#revealcollision
*/


fn not(bit: bool) -> bool {
<u1>::into(jet::complement_1(<bool>::into(bit)))
}
Expand Down
4 changes: 4 additions & 0 deletions examples/reveal_fix_point.simf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
simc ">=0.6.0";

/*
* REVEAL FIX POINT
*
Expand All @@ -8,6 +10,8 @@
*
* https://docs.ivylang.org/bitcoin/language/ExampleContracts.html#revealfixedpoint
*/


fn sha2(string: u256) -> u256 {
let hasher: Ctx8 = jet::sha_256_ctx_8_init();
let hasher: Ctx8 = jet::sha_256_ctx_8_add_32(hasher, string);
Expand Down
4 changes: 4 additions & 0 deletions examples/sighash_all_anyonecanpay.simf
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
simc ">=0.6.0";

/*
* This program verifies a Schnorr signature based on
* SIGHASH_ALL | SIGHASH_ANYONECANPAY.
*/


fn main() {
let ctx: Ctx8 = jet::sha_256_ctx_8_init();
// Blockchain
Expand Down
4 changes: 4 additions & 0 deletions examples/sighash_all_anyprevout.simf
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
simc ">=0.6.0";

/*
* This program verifies a Schnorr signature based on
* SIGHASH_ALL | SIGHASH_ANYPREVOUT.
*/


fn main() {
let ctx: Ctx8 = jet::sha_256_ctx_8_init();
// Blockchain
Expand Down
4 changes: 4 additions & 0 deletions examples/sighash_all_anyprevoutanyscript.simf
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
simc ">=0.6.0";

/*
* This program verifies a Schnorr signature based on
* SIGHASH_ALL | SIGHASH_ANYPREVOUTANYSCRIPT.
*/


fn main() {
let ctx: Ctx8 = jet::sha_256_ctx_8_init();
// Blockchain
Expand Down
4 changes: 4 additions & 0 deletions examples/sighash_none.simf
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
simc ">=0.6.0";

/*
* This program verifies a Schnorr signature based on
* SIGHASH_NONE.
*/


fn main() {
let ctx: Ctx8 = jet::sha_256_ctx_8_init();
// Blockchain
Expand Down
4 changes: 4 additions & 0 deletions examples/sighash_single.simf
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
simc ">=0.6.0";

/*
* This program verifies a Schnorr signature based on
* SIGHASH_SINGLE.
*/


fn main() {
let ctx: Ctx8 = jet::sha_256_ctx_8_init();
// Blockchain
Expand Down
2 changes: 2 additions & 0 deletions examples/simple_multidep/crypto/hashes.simf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
simc ">=0.6.0";

pub fn sha256(data: u32) -> u256 {
let ctx: Ctx8 = jet::sha_256_ctx_8_init();
let ctx: Ctx8 = jet::sha_256_ctx_8_add_4(ctx, data);
Expand Down
2 changes: 2 additions & 0 deletions examples/simple_multidep/main.simf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
simc ">=0.6.0";

use math::arithmetic::add;
use crypto::hashes::sha256;

Expand Down
2 changes: 2 additions & 0 deletions examples/simple_multidep/math/arithmetic.simf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
simc ">=0.6.0";

pub fn add(a: u32, b: u32) -> u32 {
let (_, res): (bool, u32) = jet::add_32(a, b);
res
Expand Down
2 changes: 2 additions & 0 deletions examples/single_dep/main.simf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
simc ">=0.6.0";

pub use temp::constants::utils::two as smth;
use temp::funcs::{get_five, Smth};

Expand Down
2 changes: 2 additions & 0 deletions examples/single_dep/temp/constants/utils.simf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
simc ">=0.6.0";

pub use crate::funcs::Smth;

pub fn two() -> Smth {
Expand Down
2 changes: 2 additions & 0 deletions examples/single_dep/temp/funcs.simf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
simc ">=0.6.0";

pub type Smth = u32;

pub fn get_five() -> u32 {
Expand Down
Loading
Loading