Skip to content

Commit ccac596

Browse files
committed
Merge BlockstreamResearch#64: Add functions
5621179 test: Add example for custom functions (Christian Lewe) 9c724d2 feat: Add calls to custom functions (Christian Lewe) 39649dd refactor: Call parser (Christian Lewe) fb57f0c fix: Update example programs (Christian Lewe) d1ac962 feat: Add functions (Christian Lewe) cb5c37d feat: Allow blocks without final expression (Christian Lewe) 2c48a49 refactor: Return Error during alias resolving (Christian Lewe) 306a814 Cargo: Add itertools (Christian Lewe) 556e430 refactor: Implement wrapped strings in macro (Christian Lewe) dfb7d78 fix: Use wildcarded enum variants in match (Christian Lewe) Pull request description: Depends on BlockstreamResearch#63 Better version of BlockstreamResearch#24 Move the existing parts of the program into the `main` function (except type aliases). Add the possibilities to define more functions outside the `main` function. Functions can be called _after_ they are defined. This feels like 1970, but it keeps the compiler simple. Witness expressions are only allowed inside the `main` function to prevent indirect witness reuse via multiple function calls. ACKs for top commit: apoelstra: ACK 5621179 Tree-SHA512: 46aab4fce7ea5c26876316fac1fadd8b92c3a1764fafc65cd32a5f36e03490614c6c11b28f9a65b054e2d12dc46a181b1c3d8d2b896ce56e895c16e1e6c38405
2 parents 8892203 + 5621179 commit ccac596

26 files changed

+940
-425
lines changed

Cargo.lock

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ serde_json = "1.0.105"
2828
simplicity-lang = { git = "https://github.com/BlockstreamResearch/rust-simplicity", rev = "497b88fec845b3080b61b3939074b59fe24d6dec" }
2929
miniscript = "11.0.0"
3030
either = "1.12.0"
31+
itertools = "0.13.0"
3132

3233
[target.wasm32-unknown-unknown.dependencies]
3334
getrandom = { version = "0.2", features = ["js"] }

example_progs/add.simf

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
let a: u32 = 2;
2-
let b: u32 = 3;
3-
let (carry, res): (bool, u32) = jet_add_32(a, b);
4-
let add_res: (bool, u32) = jet_add_32(10, 20);
5-
let (carry2, res3): (bool, u32) = add_res;
6-
jet_verify(jet_eq_32(res3, 30));
1+
fn main() {
2+
let a: u32 = 2;
3+
let b: u32 = 3;
4+
let (carry, res): (bool, u32) = jet_add_32(a, b);
5+
let add_res: (bool, u32) = jet_add_32(10, 20);
6+
let (carry2, res3): (bool, u32) = add_res;
7+
jet_verify(jet_eq_32(res3, 30));
8+
}

example_progs/array.simf

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
let a: [u1; 0] = [];
2-
let b: [u2; 1] = [1];
3-
let c: [u4; 2] = [1, 2];
4-
let d: [u8; 3] = [1, 2, 3];
5-
let e: [u16; 4] = [1, 2, 3, 4];
6-
let f: [u32; 5] = [1, 2, 3, 4, 5];
7-
let g: [u64; 6] = [1, 2, 3, 4, 5, 6];
8-
let h: [u128; 7] = [1, 2, 3, 4, 5, 6, 7];
9-
let i: [u256; 8] = [1, 2, 3, 4, 5, 6, 7, 8];
1+
fn main() {
2+
let a: [u1; 0] = [];
3+
let b: [u2; 1] = [1];
4+
let c: [u4; 2] = [1, 2];
5+
let d: [u8; 3] = [1, 2, 3];
6+
let e: [u16; 4] = [1, 2, 3, 4];
7+
let f: [u32; 5] = [1, 2, 3, 4, 5];
8+
let g: [u64; 6] = [1, 2, 3, 4, 5, 6];
9+
let h: [u128; 7] = [1, 2, 3, 4, 5, 6, 7];
10+
let i: [u256; 8] = [1, 2, 3, 4, 5, 6, 7, 8];
1011

11-
let []: [u1; 0] = a;
12+
let []: [u1; 0] = a;
1213

13-
let [d0, d1, d2]: [u8; 3] = d;
14-
jet_verify(jet_eq_8(d0, 1));
15-
jet_verify(jet_eq_8(d1, 2));
16-
jet_verify(jet_eq_8(d2, 3));
14+
let [d0, d1, d2]: [u8; 3] = d;
15+
jet_verify(jet_eq_8(d0, 1));
16+
jet_verify(jet_eq_8(d1, 2));
17+
jet_verify(jet_eq_8(d2, 3));
18+
}

example_progs/cat.simf

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
let a: u8 = 0x10;
2-
let b: u8 = 0x01;
3-
let ab: u16 = (a, b);
4-
let c: u16 = 0x1001;
5-
jet_verify(jet_eq_16(ab, c));
6-
let a: u4 = 0b1011;
7-
let b: u4 = 0b1101;
8-
let ab: u8 = (a, b);
9-
let c: u8 = 0b10111101;
10-
jet_verify(jet_eq_8(ab, c));
1+
fn main() {
2+
let a: u8 = 0x10;
3+
let b: u8 = 0x01;
4+
let ab: u16 = (a, b);
5+
let c: u16 = 0x1001;
6+
jet_verify(jet_eq_16(ab, c));
7+
let a: u4 = 0b1011;
8+
let b: u4 = 0b1101;
9+
let ab: u8 = (a, b);
10+
let c: u8 = 0b10111101;
11+
jet_verify(jet_eq_8(ab, c));
12+
}

example_progs/checksigfromstackverify.simf

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
*
44
* It verifies that a provided message and signature match a hardcoded public key.
55
*/
6-
7-
// In the future, we could use jets to compute a custom sighash
8-
let pk: u256 = 0xf9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9;
9-
let msg: u256 = witness("msg");
10-
let sig: [u8; 64] = witness("sig");
11-
jet_bip_0340_verify(pk, msg, sig);
6+
fn main() {
7+
// In the future, we could use jets to compute a custom sighash
8+
let pk: u256 = 0xf9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9;
9+
let msg: u256 = witness("msg");
10+
let sig: [u8; 64] = witness("sig");
11+
jet_bip_0340_verify(pk, msg, sig);
12+
}

example_progs/ctv.simf

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,18 @@
55
* we require the user to specify all the components of the sighash
66
* that they want to commit.
77
*/
8+
fn main() {
9+
let ctx: Ctx8 = jet_sha_256_ctx_8_init();
10+
let ctx: Ctx8 = jet_sha_256_ctx_8_add_4(ctx, jet_version());
11+
let ctx: Ctx8 = jet_sha_256_ctx_8_add_4(ctx, jet_lock_time());
12+
let ctx: Ctx8 = jet_sha_256_ctx_8_add_32(ctx, jet_input_script_sigs_hash());
13+
let ctx: Ctx8 = jet_sha_256_ctx_8_add_4(ctx, jet_num_inputs());
14+
let ctx: Ctx8 = jet_sha_256_ctx_8_add_32(ctx, jet_input_sequences_hash());
15+
let ctx: Ctx8 = jet_sha_256_ctx_8_add_4(ctx, jet_num_outputs());
16+
let ctx: Ctx8 = jet_sha_256_ctx_8_add_32(ctx, jet_outputs_hash());
17+
let ctx: Ctx8 = jet_sha_256_ctx_8_add_4(ctx, jet_current_index());
18+
let ctv_hash: u256 = jet_sha_256_ctx_8_finalize(ctx);
819

9-
let ctx: Ctx8 = jet_sha_256_ctx_8_init();
10-
let ctx: Ctx8 = jet_sha_256_ctx_8_add_4(ctx, jet_version());
11-
let ctx: Ctx8 = jet_sha_256_ctx_8_add_4(ctx, jet_lock_time());
12-
let ctx: Ctx8 = jet_sha_256_ctx_8_add_32(ctx, jet_input_script_sigs_hash());
13-
let ctx: Ctx8 = jet_sha_256_ctx_8_add_4(ctx, jet_num_inputs());
14-
let ctx: Ctx8 = jet_sha_256_ctx_8_add_32(ctx, jet_input_sequences_hash());
15-
let ctx: Ctx8 = jet_sha_256_ctx_8_add_4(ctx, jet_num_outputs());
16-
let ctx: Ctx8 = jet_sha_256_ctx_8_add_32(ctx, jet_outputs_hash());
17-
let ctx: Ctx8 = jet_sha_256_ctx_8_add_4(ctx, jet_current_index());
18-
let ctv_hash: u256 = jet_sha_256_ctx_8_finalize(ctx);
19-
20-
let expected_hash: u256 = 0xae3d019b30529c6044d2b3d7ee2e0ee5db51a7f05ed5db8f089cd5d455f1fc5d;
21-
jet_verify(jet_eq_256(ctv_hash, expected_hash));
20+
let expected_hash: u256 = 0xae3d019b30529c6044d2b3d7ee2e0ee5db51a7f05ed5db8f089cd5d455f1fc5d;
21+
jet_verify(jet_eq_256(ctv_hash, expected_hash));
22+
}

example_progs/function.simf

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
fn checked_add_32(a: u32, b: u32) -> u32 {
2+
let (carry, sum): (bool, u32) = jet_add_32(a, b);
3+
// FIXME: Need to cast `bool` to `u1`
4+
// jet_verify(jet_complement_1(carry));
5+
sum
6+
}
7+
8+
fn first() -> u32 {
9+
1
10+
}
11+
12+
fn second() -> u32 {
13+
checked_add_32(first(), first())
14+
}
15+
16+
fn third() -> u32 {
17+
checked_add_32(first(), second())
18+
}
19+
20+
fn main() {
21+
let sum: u32 = checked_add_32(42, 1);
22+
let expected: u32 = 43;
23+
jet_verify(jet_eq_32(expected, sum));
24+
25+
let third: u32 = third();
26+
let expected: u32 = 3;
27+
jet_verify(jet_eq_32(expected, third));
28+
}

example_progs/list.simf

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
let a: List<u32, 2> = list![];
2-
let b: List<u32, 2> = list![1];
3-
let c: List<u32, 4> = list![];
4-
let d: List<u32, 4> = list![1];
5-
let e: List<u32, 4> = list![1, 2];
6-
let f: List<u32, 4> = list![1, 2, 3];
1+
fn main() {
2+
let a: List<u32, 2> = list![];
3+
let b: List<u32, 2> = list![1];
4+
let c: List<u32, 4> = list![];
5+
let d: List<u32, 4> = list![1];
6+
let e: List<u32, 4> = list![1, 2];
7+
let f: List<u32, 4> = list![1, 2, 3];
8+
}

example_progs/match.simf

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1-
let bit: bool = match Left(11) {
2-
Left(x: u32) => jet_le_32(10, x),
3-
Right(y: u32) => jet_le_32(y, 10),
4-
};
5-
jet_verify(bit);
6-
let bit: bool = match Some(11) {
7-
Some(x: u32) => jet_le_32(10, x),
8-
None => false,
9-
};
10-
jet_verify(bit);
11-
let bit: bool = match false {
12-
true => false,
13-
false => true,
14-
};
15-
jet_verify(bit);
1+
fn main() {
2+
let bit: bool = match Left(11) {
3+
Left(x: u32) => jet_le_32(10, x),
4+
Right(y: u32) => jet_le_32(y, 10),
5+
};
6+
jet_verify(bit);
7+
let bit: bool = match Some(11) {
8+
Some(x: u32) => jet_le_32(10, x),
9+
None => false,
10+
};
11+
jet_verify(bit);
12+
let bit: bool = match false {
13+
true => false,
14+
false => true,
15+
};
16+
jet_verify(bit);
17+
}

example_progs/nesting.simf

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
let v1: u32 = {
2-
let v4: u32 = 1;
3-
let v5: u32 = 2;
4-
let v6: u32 = 3;
5-
let v7: u32 = jet_max_32(v4, jet_max_32(v5, v6));
6-
v4
7-
};
8-
let res: u32 = 1;
9-
jet_verify(jet_eq_32(res, v1));
1+
fn main() {
2+
let v1: u32 = {
3+
let v4: u32 = 1;
4+
let v5: u32 = 2;
5+
let v6: u32 = 3;
6+
let v7: u32 = jet_max_32(v4, jet_max_32(v5, v6));
7+
v4
8+
};
9+
let res: u32 = 1;
10+
jet_verify(jet_eq_32(res, v1));
11+
}

example_progs/recursive-covenant.simf

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
* The scriptPubKey of the UTXO must be repeated
44
* in the first output of the spending transaction.
55
*/
6-
7-
let this_hash: u256 = jet_current_script_hash();
8-
let spend_hash: u256 = unwrap(jet_output_script_hash(0));
9-
jet_verify(jet_eq_256(this_hash, spend_hash));
6+
fn main () {
7+
let this_hash: u256 = jet_current_script_hash();
8+
let spend_hash: u256 = unwrap(jet_output_script_hash(0));
9+
jet_verify(jet_eq_256(this_hash, spend_hash));
10+
}

example_progs/scopes.simf

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
let v1: u32 = {
2-
let v2: u32 = {
3-
let v7: u32 = 10;
4-
let v3: u32 = {
5-
let v4: u32 = 2;
6-
let v5: u32 = 3;
7-
jet_verify(jet_eq_32(v7, 10)); /* Can use upper scope variables here.*/
8-
let v7: u32 = 7; /* Can also shadow the upper scope here.*/
9-
jet_max_32(jet_max_32(v4, v5),v7) /* Rust like, missing ; here is the return type of expression.*/
1+
fn main() {
2+
let v1: u32 = {
3+
let v2: u32 = {
4+
let v7: u32 = 10;
5+
let v3: u32 = {
6+
let v4: u32 = 2;
7+
let v5: u32 = 3;
8+
jet_verify(jet_eq_32(v7, 10)); /* Can use upper scope variables here.*/
9+
let v7: u32 = 7; /* Can also shadow the upper scope here.*/
10+
jet_max_32(jet_max_32(v4, v5),v7) /* Rust like, missing ; here is the return type of expression.*/
11+
};
12+
jet_verify(jet_eq_32(v7, 10)); /* Upper scope is same just like regular Programming languages*/
13+
jet_min_32(v7, v3) /*Return value of v2 block*/
1014
};
11-
jet_verify(jet_eq_32(v7, 10)); /* Upper scope is same just like regular Programming languages*/
12-
jet_min_32(v7, v3) /*Return value of v2 block*/
15+
v2
1316
};
14-
v2
15-
};
16-
jet_verify(jet_eq_32(7, v1));
17+
jet_verify(jet_eq_32(7, v1));
18+
}

0 commit comments

Comments
 (0)