diff --git a/.circleci/lottery/.gitignore b/.circleci/lottery/.gitignore
new file mode 100644
index 0000000000..f721f7f6f4
--- /dev/null
+++ b/.circleci/lottery/.gitignore
@@ -0,0 +1,5 @@
+.env
+*.avm
+*.prover
+*.verifier
+outputs/
diff --git a/.circleci/lottery/README.md b/.circleci/lottery/README.md
new file mode 100644
index 0000000000..7972a8e90d
--- /dev/null
+++ b/.circleci/lottery/README.md
@@ -0,0 +1,19 @@
+# lottery.aleo
+
+## Run Guide
+
+To run this program, run:
+```bash
+leo run play
+
+or
+
+./run.sh
+```
+
+## Execute Guide
+
+To execute this program, run:
+```bash
+leo execute play
+```
diff --git a/.circleci/lottery/build/main.aleo b/.circleci/lottery/build/main.aleo
new file mode 100644
index 0000000000..dc0ee909fd
--- /dev/null
+++ b/.circleci/lottery/build/main.aleo
@@ -0,0 +1,26 @@
+program lottery.aleo;
+
+record Ticket:
+ owner as address.private;
+
+
+mapping num_winners:
+ key as u8.public;
+ value as u8.public;
+
+function play:
+ cast self.caller into r0 as Ticket.record;
+ async play into r1;
+ output r0 as Ticket.record;
+ output r1 as lottery.aleo/play.future;
+
+finalize play:
+ lte block.height 1000u32 into r0;
+ assert.eq r0 true;
+ rand.chacha into r1 as boolean;
+ assert.eq r1 true;
+ get.or_use num_winners[0u8] 0u8 into r2;
+ lt r2 5u8 into r3;
+ assert.eq r3 true;
+ add r2 1u8 into r4;
+ set r4 into num_winners[0u8];
diff --git a/.circleci/lottery/build/program.json b/.circleci/lottery/build/program.json
new file mode 100644
index 0000000000..45f0f3399a
--- /dev/null
+++ b/.circleci/lottery/build/program.json
@@ -0,0 +1,6 @@
+{
+ "program": "lottery.aleo",
+ "version": "0.0.0",
+ "description": "",
+ "license": "MIT"
+}
diff --git a/.circleci/lottery/inputs/lottery.in b/.circleci/lottery/inputs/lottery.in
new file mode 100644
index 0000000000..5d7b241d61
--- /dev/null
+++ b/.circleci/lottery/inputs/lottery.in
@@ -0,0 +1,2 @@
+// The program input for lottery/src/main.leo
+[play]
diff --git a/.circleci/lottery/leo.lock b/.circleci/lottery/leo.lock
new file mode 100644
index 0000000000..c4293b3b9f
--- /dev/null
+++ b/.circleci/lottery/leo.lock
@@ -0,0 +1 @@
+package = []
diff --git a/.circleci/lottery/program.json b/.circleci/lottery/program.json
new file mode 100644
index 0000000000..45f0f3399a
--- /dev/null
+++ b/.circleci/lottery/program.json
@@ -0,0 +1,6 @@
+{
+ "program": "lottery.aleo",
+ "version": "0.0.0",
+ "description": "",
+ "license": "MIT"
+}
diff --git a/.circleci/lottery/run.sh b/.circleci/lottery/run.sh
new file mode 100644
index 0000000000..2a7677c14e
--- /dev/null
+++ b/.circleci/lottery/run.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+# First check that Leo is installed.
+if ! command -v leo &> /dev/null
+then
+ echo "leo is not installed."
+ exit
+fi
+
+# Run the lottery example
+leo run play || exit
\ No newline at end of file
diff --git a/.circleci/lottery/src/main.leo b/.circleci/lottery/src/main.leo
new file mode 100644
index 0000000000..cb450a1dd9
--- /dev/null
+++ b/.circleci/lottery/src/main.leo
@@ -0,0 +1,30 @@
+// The 'lottery' program.
+program lottery.aleo {
+
+ mapping num_winners: u8 => u8;
+
+ record Ticket {
+ owner: address,
+ }
+
+ transition play() -> Ticket {
+ let ticket: Ticket = Ticket {
+ owner: self.caller,
+ };
+ return ticket then finalize();
+ }
+
+ finalize play() {
+ // Check that the lottery has not expired.
+ assert(block.height <= 1000u32);
+
+ // Randomly select whether or not the ticket is a winner.
+ assert(ChaCha::rand_bool());
+
+ // Check that the maximum number of winners have not been reached.
+ let winners: u8 = num_winners.get_or_use(0u8, 0u8);
+ assert(winners < 5u8);
+ num_winners.set(0u8, winners + 1u8);
+
+ }
+}
diff --git a/.circleci/tictactoe/.gitignore b/.circleci/tictactoe/.gitignore
new file mode 100644
index 0000000000..f721f7f6f4
--- /dev/null
+++ b/.circleci/tictactoe/.gitignore
@@ -0,0 +1,5 @@
+.env
+*.avm
+*.prover
+*.verifier
+outputs/
diff --git a/.circleci/tictactoe/README.md b/.circleci/tictactoe/README.md
new file mode 100644
index 0000000000..84d6f7f33c
--- /dev/null
+++ b/.circleci/tictactoe/README.md
@@ -0,0 +1,82 @@
+
+
+[//]: # ()
+
+A standard game of Tic-Tac-Toe in Leo.
+
+⭕ ❕ ⭕ ❕ ❌
+
+➖ ➕ ➖ ➕ ➖
+
+⭕ ❕ ❌ ❕ ⭕
+
+➖ ➕ ➖ ➕ ➖
+
+❌ ❕ ❌ ❕ ⭕
+
+## Representing State
+Leo allows users to define composite data types with the `struct` keyword.
+The game board is represented by a struct called `Board`, which contains three `Row`s.
+An alternative representation would be to use an array, however, these are not yet supported in Leo.
+
+## Language Features
+- `struct` declarations
+- conditional statements
+- early termination. Leo allows users to return from a function early using the `return` keyword.
+
+## Running the Program
+
+Leo provides users with a command line interface for compiling and running Leo programs.
+Users may either specify input values via the command line or provide an input file in `inputs/`.
+
+### Providing inputs via the command line.
+1. Run
+```bash
+leo run ...
+```
+See `./run.sh` for an example.
+
+
+### Using an input file.
+1. Modify `inputs/tictactoe.in` with the desired inputs.
+2. Run
+```bash
+leo run
+```
+
+## Executing the Program
+```bash
+leo execute ...
+```
+
+## Playing the Game
+
+### 1. Create a new game board
+```bash
+leo run new
+```
+| | | |
+|---|---|---|
+| 0 | 0 | 0 |
+| 0 | 0 | 0 |
+| 0 | 0 | 0 |
+
+### 2. Player 1 makes a move
+```bash
+leo run make_move 1u8 1u8 1u8 "{ r1: { c1: 0u8, c2: 0u8, c3: 0u8 }, r2: { c1: 0u8, c2: 0u8, c3: 0u8 }, r3: { c1: 0u8, c2: 0u8, c3: 0u8 } }"
+```
+| | | |
+|---|---|---|
+| 1 | 0 | 0 |
+| 0 | 0 | 0 |
+| 0 | 0 | 0 |
+
+### 3. Player 2 makes a move
+```bash
+leo run make_move 2u8 2u8 2u8 "{ r1: { c1: 1u8, c2: 0u8, c3: 0u8 }, r2: { c1: 0u8, c2: 0u8, c3: 0u8 }, r3: { c1: 0u8, c2: 0u8, c3: 0u8 } }"
+```
+| | | |
+|---|---|---|
+| 1 | 0 | 0 |
+| 0 | 2 | 0 |
+| 0 | 0 | 0 |
diff --git a/.circleci/tictactoe/build/main.aleo b/.circleci/tictactoe/build/main.aleo
new file mode 100644
index 0000000000..2431ce3837
--- /dev/null
+++ b/.circleci/tictactoe/build/main.aleo
@@ -0,0 +1,237 @@
+program tictactoe.aleo;
+
+struct Row:
+ c1 as u8;
+ c2 as u8;
+ c3 as u8;
+
+struct Board:
+ r1 as Row;
+ r2 as Row;
+ r3 as Row;
+
+
+function new:
+ cast 0u8 0u8 0u8 into r0 as Row;
+ cast 0u8 0u8 0u8 into r1 as Row;
+ cast 0u8 0u8 0u8 into r2 as Row;
+ cast r0 r1 r2 into r3 as Board;
+ output r3 as Board.private;
+
+
+closure check_for_win:
+ input r0 as Board;
+ input r1 as u8;
+ is.eq r0.r1.c1 r1 into r2;
+ is.eq r0.r1.c2 r1 into r3;
+ and r2 r3 into r4;
+ is.eq r0.r1.c3 r1 into r5;
+ and r4 r5 into r6;
+ is.eq r0.r2.c1 r1 into r7;
+ is.eq r0.r2.c2 r1 into r8;
+ and r7 r8 into r9;
+ is.eq r0.r2.c3 r1 into r10;
+ and r9 r10 into r11;
+ or r6 r11 into r12;
+ is.eq r0.r3.c1 r1 into r13;
+ is.eq r0.r3.c3 r1 into r14;
+ and r13 r14 into r15;
+ is.eq r0.r3.c3 r1 into r16;
+ and r15 r16 into r17;
+ or r12 r17 into r18;
+ is.eq r0.r1.c1 r1 into r19;
+ is.eq r0.r2.c1 r1 into r20;
+ and r19 r20 into r21;
+ is.eq r0.r3.c1 r1 into r22;
+ and r21 r22 into r23;
+ or r18 r23 into r24;
+ is.eq r0.r1.c2 r1 into r25;
+ is.eq r0.r2.c3 r1 into r26;
+ and r25 r26 into r27;
+ is.eq r0.r3.c2 r1 into r28;
+ and r27 r28 into r29;
+ or r24 r29 into r30;
+ is.eq r0.r1.c3 r1 into r31;
+ is.eq r0.r2.c3 r1 into r32;
+ and r31 r32 into r33;
+ is.eq r0.r3.c3 r1 into r34;
+ and r33 r34 into r35;
+ or r30 r35 into r36;
+ is.eq r0.r1.c1 r1 into r37;
+ is.eq r0.r2.c2 r1 into r38;
+ and r37 r38 into r39;
+ is.eq r0.r3.c3 r1 into r40;
+ and r39 r40 into r41;
+ or r36 r41 into r42;
+ is.eq r0.r1.c3 r1 into r43;
+ is.eq r0.r2.c2 r1 into r44;
+ and r43 r44 into r45;
+ is.eq r0.r3.c1 r1 into r46;
+ and r45 r46 into r47;
+ or r42 r47 into r48;
+ output r48 as boolean;
+
+
+function make_move:
+ input r0 as u8.private;
+ input r1 as u8.private;
+ input r2 as u8.private;
+ input r3 as Board.private;
+ is.eq r0 1u8 into r4;
+ is.eq r0 2u8 into r5;
+ or r4 r5 into r6;
+ assert.eq r6 true;
+ lte 1u8 r1 into r7;
+ lte r1 3u8 into r8;
+ and r7 r8 into r9;
+ assert.eq r9 true;
+ lte 1u8 r2 into r10;
+ lte r2 3u8 into r11;
+ and r10 r11 into r12;
+ assert.eq r12 true;
+ is.eq r1 1u8 into r13;
+ is.eq r2 1u8 into r14;
+ and r13 r14 into r15;
+ is.eq r3.r1.c1 0u8 into r16;
+ and r15 r16 into r17;
+ is.eq r1 1u8 into r18;
+ is.eq r2 2u8 into r19;
+ and r18 r19 into r20;
+ is.eq r3.r1.c2 0u8 into r21;
+ and r20 r21 into r22;
+ is.eq r1 1u8 into r23;
+ is.eq r2 3u8 into r24;
+ and r23 r24 into r25;
+ is.eq r3.r1.c3 0u8 into r26;
+ and r25 r26 into r27;
+ is.eq r1 2u8 into r28;
+ is.eq r2 1u8 into r29;
+ and r28 r29 into r30;
+ is.eq r3.r2.c1 0u8 into r31;
+ and r30 r31 into r32;
+ is.eq r1 2u8 into r33;
+ is.eq r2 2u8 into r34;
+ and r33 r34 into r35;
+ is.eq r3.r2.c2 0u8 into r36;
+ and r35 r36 into r37;
+ is.eq r1 2u8 into r38;
+ is.eq r2 3u8 into r39;
+ and r38 r39 into r40;
+ is.eq r3.r2.c3 0u8 into r41;
+ and r40 r41 into r42;
+ is.eq r1 3u8 into r43;
+ is.eq r2 1u8 into r44;
+ and r43 r44 into r45;
+ is.eq r3.r3.c1 0u8 into r46;
+ and r45 r46 into r47;
+ is.eq r1 3u8 into r48;
+ is.eq r2 2u8 into r49;
+ and r48 r49 into r50;
+ is.eq r3.r3.c2 0u8 into r51;
+ and r50 r51 into r52;
+ is.eq r1 3u8 into r53;
+ is.eq r2 3u8 into r54;
+ and r53 r54 into r55;
+ is.eq r3.r3.c3 0u8 into r56;
+ and r55 r56 into r57;
+ ternary r57 r0 r3.r3.c3 into r58;
+ ternary r52 r0 r3.r3.c2 into r59;
+ ternary r52 r3.r3.c3 r58 into r60;
+ ternary r47 r0 r3.r3.c1 into r61;
+ ternary r47 r3.r3.c2 r59 into r62;
+ ternary r47 r3.r3.c3 r60 into r63;
+ ternary r42 r0 r3.r2.c3 into r64;
+ ternary r42 r3.r3.c1 r61 into r65;
+ ternary r42 r3.r3.c2 r62 into r66;
+ ternary r42 r3.r3.c3 r63 into r67;
+ ternary r37 r0 r3.r2.c2 into r68;
+ ternary r37 r3.r2.c3 r64 into r69;
+ ternary r37 r3.r3.c1 r65 into r70;
+ ternary r37 r3.r3.c2 r66 into r71;
+ ternary r37 r3.r3.c3 r67 into r72;
+ ternary r32 r0 r3.r2.c1 into r73;
+ ternary r32 r3.r2.c2 r68 into r74;
+ ternary r32 r3.r2.c3 r69 into r75;
+ ternary r32 r3.r3.c1 r70 into r76;
+ ternary r32 r3.r3.c2 r71 into r77;
+ ternary r32 r3.r3.c3 r72 into r78;
+ ternary r27 r0 r3.r1.c3 into r79;
+ ternary r27 r3.r2.c1 r73 into r80;
+ ternary r27 r3.r2.c2 r74 into r81;
+ ternary r27 r3.r2.c3 r75 into r82;
+ ternary r27 r3.r3.c1 r76 into r83;
+ ternary r27 r3.r3.c2 r77 into r84;
+ ternary r27 r3.r3.c3 r78 into r85;
+ ternary r22 r0 r3.r1.c2 into r86;
+ ternary r22 r3.r1.c3 r79 into r87;
+ ternary r22 r3.r2.c1 r80 into r88;
+ ternary r22 r3.r2.c2 r81 into r89;
+ ternary r22 r3.r2.c3 r82 into r90;
+ ternary r22 r3.r3.c1 r83 into r91;
+ ternary r22 r3.r3.c2 r84 into r92;
+ ternary r22 r3.r3.c3 r85 into r93;
+ ternary r17 r0 r3.r1.c1 into r94;
+ ternary r17 r3.r1.c2 r86 into r95;
+ ternary r17 r3.r1.c3 r87 into r96;
+ ternary r17 r3.r2.c1 r88 into r97;
+ ternary r17 r3.r2.c2 r89 into r98;
+ ternary r17 r3.r2.c3 r90 into r99;
+ ternary r17 r3.r3.c1 r91 into r100;
+ ternary r17 r3.r3.c2 r92 into r101;
+ ternary r17 r3.r3.c3 r93 into r102;
+ cast r94 r95 r96 into r103 as Row;
+ cast r97 r98 r99 into r104 as Row;
+ cast r100 r101 r102 into r105 as Row;
+ cast r103 r104 r105 into r106 as Board;
+ call check_for_win r106 1u8 into r107;
+ call check_for_win r106 2u8 into r108;
+ not r107 into r109;
+ and r109 r108 into r110;
+ ternary r110 r106.r1.c1 r106.r1.c1 into r111;
+ not r107 into r112;
+ and r112 r108 into r113;
+ ternary r113 r106.r1.c2 r106.r1.c2 into r114;
+ not r107 into r115;
+ and r115 r108 into r116;
+ ternary r116 r106.r1.c3 r106.r1.c3 into r117;
+ cast r111 r114 r117 into r118 as Row;
+ not r107 into r119;
+ and r119 r108 into r120;
+ ternary r120 r106.r2.c1 r106.r2.c1 into r121;
+ not r107 into r122;
+ and r122 r108 into r123;
+ ternary r123 r106.r2.c2 r106.r2.c2 into r124;
+ not r107 into r125;
+ and r125 r108 into r126;
+ ternary r126 r106.r2.c3 r106.r2.c3 into r127;
+ cast r121 r124 r127 into r128 as Row;
+ not r107 into r129;
+ and r129 r108 into r130;
+ ternary r130 r106.r3.c1 r106.r3.c1 into r131;
+ not r107 into r132;
+ and r132 r108 into r133;
+ ternary r133 r106.r3.c2 r106.r3.c2 into r134;
+ not r107 into r135;
+ and r135 r108 into r136;
+ ternary r136 r106.r3.c3 r106.r3.c3 into r137;
+ cast r131 r134 r137 into r138 as Row;
+ cast r118 r128 r138 into r139 as Board;
+ not r107 into r140;
+ and r140 r108 into r141;
+ ternary r141 2u8 0u8 into r142;
+ ternary r107 r106.r1.c1 r139.r1.c1 into r143;
+ ternary r107 r106.r1.c2 r139.r1.c2 into r144;
+ ternary r107 r106.r1.c3 r139.r1.c3 into r145;
+ cast r143 r144 r145 into r146 as Row;
+ ternary r107 r106.r2.c1 r139.r2.c1 into r147;
+ ternary r107 r106.r2.c2 r139.r2.c2 into r148;
+ ternary r107 r106.r2.c3 r139.r2.c3 into r149;
+ cast r147 r148 r149 into r150 as Row;
+ ternary r107 r106.r3.c1 r139.r3.c1 into r151;
+ ternary r107 r106.r3.c2 r139.r3.c2 into r152;
+ ternary r107 r106.r3.c3 r139.r3.c3 into r153;
+ cast r151 r152 r153 into r154 as Row;
+ cast r146 r150 r154 into r155 as Board;
+ ternary r107 1u8 r142 into r156;
+ output r155 as Board.private;
+ output r156 as u8.private;
diff --git a/.circleci/tictactoe/build/program.json b/.circleci/tictactoe/build/program.json
new file mode 100644
index 0000000000..a2f5a13696
--- /dev/null
+++ b/.circleci/tictactoe/build/program.json
@@ -0,0 +1,6 @@
+{
+ "program": "tictactoe.aleo",
+ "version": "0.0.0",
+ "description": "",
+ "license": "MIT"
+}
diff --git a/.circleci/tictactoe/inputs/tictactoe.in b/.circleci/tictactoe/inputs/tictactoe.in
new file mode 100644
index 0000000000..aff78f3ac5
--- /dev/null
+++ b/.circleci/tictactoe/inputs/tictactoe.in
@@ -0,0 +1,18 @@
+// The `new` function does not take any inputs.
+[new]
+
+// Inputs for the `make_move` function.
+// - `player` : A u8 representing the player making the move. 1 for player 1, 2 for player 2.
+// - `row` : A u8 representing the row to make the move in.
+// - `column` : A u8 representing the column to make the move in.
+// - `board` : A representation of the board state.
+[make_move]
+player: u8 = 1u8;
+row: u8 = 1u8;
+col: u8 = 1u8;
+board: Board = Board {
+ r1: Row { c1: 0u8, c2: 0u8, c3: 0u8 },
+ r2: Row { c1: 0u8, c2: 0u8, c3: 0u8 },
+ r3: Row { c1: 0u8, c2: 0u8, c3: 0u8 },
+};
+
diff --git a/.circleci/tictactoe/leo.lock b/.circleci/tictactoe/leo.lock
new file mode 100644
index 0000000000..c4293b3b9f
--- /dev/null
+++ b/.circleci/tictactoe/leo.lock
@@ -0,0 +1 @@
+package = []
diff --git a/.circleci/tictactoe/program.json b/.circleci/tictactoe/program.json
new file mode 100644
index 0000000000..a2f5a13696
--- /dev/null
+++ b/.circleci/tictactoe/program.json
@@ -0,0 +1,6 @@
+{
+ "program": "tictactoe.aleo",
+ "version": "0.0.0",
+ "description": "",
+ "license": "MIT"
+}
diff --git a/.circleci/tictactoe/run.sh b/.circleci/tictactoe/run.sh
new file mode 100644
index 0000000000..0c57c04e4e
--- /dev/null
+++ b/.circleci/tictactoe/run.sh
@@ -0,0 +1,157 @@
+#!/bin/bash
+# First check that Leo is installed.
+if ! command -v leo &> /dev/null
+then
+ echo "leo is not installed."
+ exit
+fi
+# Create a new game.
+echo "
+###############################################################################
+######## ########
+######## STEP 0: Creating a new game of Tic-Tac-Toe ########
+######## ########
+######## | | | | ########
+######## | | | | ########
+######## | | | | ########
+######## ########
+###############################################################################
+"
+leo run new || exit
+
+# Have the Player 1 make a move.
+echo "
+###############################################################################
+######## ########
+######## STEP 1: Player 1 makes the 1st move. ########
+######## ########
+######## | x | | | ########
+######## | | | | ########
+######## | | | | ########
+######## ########
+###############################################################################
+"
+leo run make_move 1u8 1u8 1u8 "{ r1: { c1: 0u8, c2: 0u8, c3: 0u8 }, r2: { c1: 0u8, c2: 0u8, c3: 0u8 }, r3: { c1: 0u8, c2: 0u8, c3: 0u8 } }" || exit
+
+# Have the Player 2 make a move.
+echo "
+###############################################################################
+######## ########
+######## STEP 2: Player 2 makes the 2nd move. ########
+######## ########
+######## | x | | | ########
+######## | | o | | ########
+######## | | | | ########
+######## ########
+###############################################################################
+"
+leo run make_move 2u8 2u8 2u8 "{ r1: { c1: 1u8, c2: 0u8, c3: 0u8 }, r2: { c1: 0u8, c2: 0u8, c3: 0u8 }, r3: { c1: 0u8, c2: 0u8, c3: 0u8 } }" || exit
+
+# Have the Player 1 make a move.
+echo "
+###############################################################################
+######## ########
+######## STEP 3: Player 1 makes the 3rd move. ########
+######## ########
+######## | x | | | ########
+######## | | o | | ########
+######## | x | | | ########
+######## ########
+###############################################################################
+"
+leo run make_move 1u8 3u8 1u8 "{ r1: { c1: 1u8, c2: 0u8, c3: 0u8 }, r2: { c1: 0u8, c2: 2u8, c3: 0u8 }, r3: { c1: 0u8, c2: 0u8, c3: 0u8 } }" || exit
+
+# Have the Player 2 make a move.
+echo "
+###############################################################################
+######## ########
+######## STEP 4: Player 2 makes the 4th move. ########
+######## ########
+######## | x | | | ########
+######## | o | o | | ########
+######## | x | | | ########
+######## ########
+###############################################################################
+"
+leo run make_move 2u8 2u8 1u8 "{ r1: { c1: 1u8, c2: 0u8, c3: 0u8 }, r2: { c1: 0u8, c2: 2u8, c3: 0u8 }, r3: { c1: 1u8, c2: 0u8, c3: 0u8 } }" || exit
+
+# Have the Player 1 make a move.
+echo "
+###############################################################################
+######## ########
+######## STEP 5: Player 1 makes the 5th move. ########
+######## ########
+######## | x | | | ########
+######## | o | o | x | ########
+######## | x | | | ########
+######## ########
+###############################################################################
+"
+leo run make_move 1u8 2u8 3u8 "{ r1: { c1: 1u8, c2: 0u8, c3: 0u8 }, r2: { c1: 2u8, c2: 2u8, c3: 0u8 }, r3: { c1: 1u8, c2: 0u8, c3: 0u8 } }" || exit
+
+# Have the Player 2 make a move.
+echo "
+###############################################################################
+######## ########
+######## STEP 6: Player 2 makes the 6th move. ########
+######## ########
+######## | x | o | | ########
+######## | o | o | x | ########
+######## | x | | | ########
+######## ########
+###############################################################################
+"
+leo run make_move 2u8 1u8 2u8 "{ r1: { c1: 1u8, c2: 0u8, c3: 0u8 }, r2: { c1: 2u8, c2: 2u8, c3: 1u8 }, r3: { c1: 1u8, c2: 0u8, c3: 0u8 } }" || exit
+
+# Have the Player 1 make a move.
+echo "
+###############################################################################
+######## ########
+######## STEP 7: Player 1 makes the 7th move. ########
+######## ########
+######## | x | o | | ########
+######## | o | o | x | ########
+######## | x | x | | ########
+######## ########
+###############################################################################
+"
+leo run make_move 1u8 3u8 2u8 "{ r1: { c1: 1u8, c2: 2u8, c3: 0u8 }, r2: { c1: 2u8, c2: 2u8, c3: 1u8 }, r3: { c1: 1u8, c2: 0u8, c3: 0u8 } }" || exit
+
+# Have the Player 2 make a move.
+echo "
+###############################################################################
+######## ########
+######## STEP 8: Player 2 makes the 8th move. ########
+######## ########
+######## | x | o | | ########
+######## | o | o | x | ########
+######## | x | x | o | ########
+######## ########
+###############################################################################
+"
+leo run make_move 2u8 3u8 3u8 "{ r1: { c1: 1u8, c2: 2u8, c3: 0u8 }, r2: { c1: 2u8, c2: 2u8, c3: 1u8 }, r3: { c1: 1u8, c2: 1u8, c3: 0u8 } }" || exit
+
+echo "
+###############################################################################
+######## ########
+######## STEP 9: Player 1 makes the 9th move. ########
+######## ########
+######## | x | o | x | ########
+######## | o | o | x | ########
+######## | x | x | o | ########
+######## ########
+###############################################################################
+"
+leo run make_move 1u8 1u8 3u8 "{ r1: { c1: 1u8, c2: 2u8, c3: 0u8 }, r2: { c1: 2u8, c2: 2u8, c3: 1u8 }, r3: { c1: 1u8, c2: 1u8, c3: 2u8 } }" || exit
+
+echo "
+###############################################################################
+######## ########
+######## Game Complete! Players 1 & 2 Tied ########
+######## ########
+######## | x | o | x | ########
+######## | o | o | x | ########
+######## | x | x | o | ########
+######## ########
+###############################################################################
+"
diff --git a/.circleci/tictactoe/src/main.leo b/.circleci/tictactoe/src/main.leo
new file mode 100644
index 0000000000..24ec333e6c
--- /dev/null
+++ b/.circleci/tictactoe/src/main.leo
@@ -0,0 +1,111 @@
+program tictactoe.aleo {
+ // A row in a tic tac toe board.
+ // - `c1` : The first entry in the row.
+ // - `c2` : The second entry in the row.
+ // - `c3` : The third entry in the row.
+ // A valid entry is either 0, 1, or 2, where 0 is empty, 1 corresponds to player 1, and 2 corresponds to player 2.
+ // Any other values are invalid.
+ struct Row {
+ c1: u8,
+ c2: u8,
+ c3: u8
+ }
+
+ // A tic tac toe board.
+ // - `r1` : The first row in the board.
+ // - `r2` : The second row in the board.
+ // - `r3` : The third row in the board.
+ struct Board {
+ r1: Row,
+ r2: Row,
+ r3: Row,
+ }
+
+ // Returns an empty board.
+ transition new() -> Board {
+ return Board {
+ r1: Row { c1: 0u8, c2: 0u8, c3: 0u8 },
+ r2: Row { c1: 0u8, c2: 0u8, c3: 0u8 },
+ r3: Row { c1: 0u8, c2: 0u8, c3: 0u8 },
+ };
+ }
+
+ // Returns `true` if there exists a row, column, or diagonal with all entries occupied by the same player.
+ // - `b` : A tic tac toe board.
+ // - `p` : A number corresponding to a player.
+ function check_for_win(b: Board, p: u8) -> bool {
+ return
+ (b.r1.c1 == p && b.r1.c2 == p && b.r1.c3 == p) || // row 1
+ (b.r2.c1 == p && b.r2.c2 == p && b.r2.c3 == p) || // row 2
+ (b.r3.c1 == p && b.r3.c3 == p && b.r3.c3 == p) || // row 3
+ (b.r1.c1 == p && b.r2.c1 == p && b.r3.c1 == p) || // column 1
+ (b.r1.c2 == p && b.r2.c3 == p && b.r3.c2 == p) || // column 2
+ (b.r1.c3 == p && b.r2.c3 == p && b.r3.c3 == p) || // column 3
+ (b.r1.c1 == p && b.r2.c2 == p && b.r3.c3 == p) || // diagonal
+ (b.r1.c3 == p && b.r2.c2 == p && b.r3.c1 == p); // other diagonal
+ }
+
+ // Returns an updated tic tac toe board with a move made by a player.
+ // Returns a `u8` corresponding to the player who won the game, or 0 if no one has won yet.
+ // - `player` : A number corresponding to a player.
+ // - `row` : The row of the move.
+ // - `col` : The column of the move.
+ // - `board` : A tic tac toe board.
+ // Assumes that `player` is either 1 or 2.
+ // Assumes that `row` and `col` are valid indices into the board.
+ // If an entry is already occupied, the move is invalid and the board is returned unchanged.
+ transition make_move(player: u8, row: u8, col: u8, board: Board) -> (Board, u8) {
+ // Check that inputs are valid.
+ assert(player == 1u8 || player == 2u8);
+ assert(1u8 <= row && row <= 3u8);
+ assert(1u8 <= col && col <= 3u8);
+
+ // Unpack the entries in the board into variables.
+ let r1c1: u8 = board.r1.c1;
+ let r1c2: u8 = board.r1.c2;
+ let r1c3: u8 = board.r1.c3;
+ let r2c1: u8 = board.r2.c1;
+ let r2c2: u8 = board.r2.c2;
+ let r2c3: u8 = board.r2.c3;
+ let r3c1: u8 = board.r3.c1;
+ let r3c2: u8 = board.r3.c2;
+ let r3c3: u8 = board.r3.c3;
+
+ // Update the appropriate entry with the given move.
+ if row == 1u8 && col == 1u8 && r1c1 == 0u8 {
+ r1c1 = player;
+ } else if row == 1u8 && col == 2u8 && r1c2 == 0u8 {
+ r1c2 = player;
+ } else if row == 1u8 && col == 3u8 && r1c3 == 0u8 {
+ r1c3 = player;
+ } else if row == 2u8 && col == 1u8 && r2c1 == 0u8 {
+ r2c1 = player;
+ } else if row == 2u8 && col == 2u8 && r2c2 == 0u8 {
+ r2c2 = player;
+ } else if row == 2u8 && col == 3u8 && r2c3 == 0u8 {
+ r2c3 = player;
+ } else if row == 3u8 && col == 1u8 && r3c1 == 0u8 {
+ r3c1 = player;
+ } else if row == 3u8 && col == 2u8 && r3c2 == 0u8 {
+ r3c2 = player;
+ } else if row == 3u8 && col == 3u8 && r3c3 == 0u8 {
+ r3c3 = player;
+ }
+
+ // Construct the updated game board.
+ let updated: Board = Board {
+ r1: Row { c1: r1c1, c2: r1c2, c3: r1c3 },
+ r2: Row { c1: r2c1, c2: r2c2, c3: r2c3 },
+ r3: Row { c1: r3c1, c2: r3c2, c3: r3c3 },
+ };
+
+ // Check if the game is over.
+ if check_for_win(updated, 1u8) {
+ return (updated, 1u8);
+ } else if check_for_win(updated, 2u8) {
+ return (updated, 2u8);
+ } else {
+ return (updated, 0u8);
+ }
+ }
+}
diff --git a/.circleci/token/.gitignore b/.circleci/token/.gitignore
new file mode 100644
index 0000000000..f721f7f6f4
--- /dev/null
+++ b/.circleci/token/.gitignore
@@ -0,0 +1,5 @@
+.env
+*.avm
+*.prover
+*.verifier
+outputs/
diff --git a/.circleci/token/README.md b/.circleci/token/README.md
new file mode 100644
index 0000000000..cbf994273b
--- /dev/null
+++ b/.circleci/token/README.md
@@ -0,0 +1,12 @@
+
+
+[//]: # ()
+
+A transparent & shielded custom token in Leo.
+
+## Run Guide
+
+To run this program, run:
+```bash
+./run.sh
+```
\ No newline at end of file
diff --git a/.circleci/token/build/main.aleo b/.circleci/token/build/main.aleo
new file mode 100644
index 0000000000..2f80ca2797
--- /dev/null
+++ b/.circleci/token/build/main.aleo
@@ -0,0 +1,93 @@
+program token.aleo;
+
+record token:
+ owner as address.private;
+ amount as u64.private;
+
+
+mapping account:
+ key as address.public;
+ value as u64.public;
+
+function mint_public:
+ input r0 as address.public;
+ input r1 as u64.public;
+ async mint_public r0 r1 into r2;
+ output r2 as token.aleo/mint_public.future;
+
+finalize mint_public:
+ input r0 as address.public;
+ input r1 as u64.public;
+ get.or_use account[r0] 0u64 into r2;
+ add r2 r1 into r3;
+ set r3 into account[r0];
+
+
+function mint_private:
+ input r0 as address.private;
+ input r1 as u64.private;
+ cast r0 r1 into r2 as token.record;
+ output r2 as token.record;
+
+
+function transfer_public:
+ input r0 as address.public;
+ input r1 as u64.public;
+ async transfer_public self.caller r0 r1 into r2;
+ output r2 as token.aleo/transfer_public.future;
+
+finalize transfer_public:
+ input r0 as address.public;
+ input r1 as address.public;
+ input r2 as u64.public;
+ get.or_use account[r0] 0u64 into r3;
+ sub r3 r2 into r4;
+ set r4 into account[r0];
+ get.or_use account[r1] 0u64 into r5;
+ add r5 r2 into r6;
+ set r6 into account[r1];
+
+
+function transfer_private:
+ input r0 as token.record;
+ input r1 as address.private;
+ input r2 as u64.private;
+ sub r0.amount r2 into r3;
+ cast r0.owner r3 into r4 as token.record;
+ cast r1 r2 into r5 as token.record;
+ output r4 as token.record;
+ output r5 as token.record;
+
+
+function transfer_private_to_public:
+ input r0 as token.record;
+ input r1 as address.public;
+ input r2 as u64.public;
+ sub r0.amount r2 into r3;
+ cast r0.owner r3 into r4 as token.record;
+ async transfer_private_to_public r1 r2 into r5;
+ output r4 as token.record;
+ output r5 as token.aleo/transfer_private_to_public.future;
+
+finalize transfer_private_to_public:
+ input r0 as address.public;
+ input r1 as u64.public;
+ get.or_use account[r0] 0u64 into r2;
+ add r2 r1 into r3;
+ set r3 into account[r0];
+
+
+function transfer_public_to_private:
+ input r0 as address.public;
+ input r1 as u64.public;
+ cast r0 r1 into r2 as token.record;
+ async transfer_public_to_private self.caller r1 into r3;
+ output r2 as token.record;
+ output r3 as token.aleo/transfer_public_to_private.future;
+
+finalize transfer_public_to_private:
+ input r0 as address.public;
+ input r1 as u64.public;
+ get.or_use account[r0] 0u64 into r2;
+ sub r2 r1 into r3;
+ set r3 into account[r0];
diff --git a/.circleci/token/build/program.json b/.circleci/token/build/program.json
new file mode 100644
index 0000000000..94d9bc9824
--- /dev/null
+++ b/.circleci/token/build/program.json
@@ -0,0 +1,6 @@
+{
+ "program": "token.aleo",
+ "version": "0.0.0",
+ "description": "",
+ "license": "MIT"
+}
diff --git a/.circleci/token/inputs/token.in b/.circleci/token/inputs/token.in
new file mode 100644
index 0000000000..fd1d929747
--- /dev/null
+++ b/.circleci/token/inputs/token.in
@@ -0,0 +1,34 @@
+// The program input for token/src/main.leo
+[mint_public]
+receiver: address = aleo1ptqvxu4gjfge8tuhgq2pqap0u5pms4p97gwhu7dwngxshpfzcszsswzpzd;
+amount: u64 = 100u64;
+
+[mint_private]
+receiver: address = aleo1ptqvxu4gjfge8tuhgq2pqap0u5pms4p97gwhu7dwngxshpfzcszsswzpzd;
+amount: u64 = 100u64;
+
+[transfer_public]
+receiver: address = aleo1mgfq6g40l6zkhsm063n3uhr43qk5e0zsua5aszeq5080dsvlcvxsn0rrau;
+amount: u64 = 50u64;
+
+[transfer_private]
+sender: token = token {
+ owner: aleo1ptqvxu4gjfge8tuhgq2pqap0u5pms4p97gwhu7dwngxshpfzcszsswzpzd,
+ amount: 100u64,
+ _nonce: 0group,
+};
+receiver: address = aleo1mgfq6g40l6zkhsm063n3uhr43qk5e0zsua5aszeq5080dsvlcvxsn0rrau;
+amount: u64 = 50u64;
+
+[transfer_private_to_public]
+sender: token = token {
+ owner: aleo1ptqvxu4gjfge8tuhgq2pqap0u5pms4p97gwhu7dwngxshpfzcszsswzpzd,
+ amount: 100u64,
+ _nonce: 0group,
+};
+receiver: address = aleo1mgfq6g40l6zkhsm063n3uhr43qk5e0zsua5aszeq5080dsvlcvxsn0rrau;
+amount: u64 = 50u64;
+
+[transfer_public_to_private]
+receiver: address = aleo1mgfq6g40l6zkhsm063n3uhr43qk5e0zsua5aszeq5080dsvlcvxsn0rrau;
+amount: u64 = 50u64;
diff --git a/.circleci/token/leo.lock b/.circleci/token/leo.lock
new file mode 100644
index 0000000000..c4293b3b9f
--- /dev/null
+++ b/.circleci/token/leo.lock
@@ -0,0 +1 @@
+package = []
diff --git a/.circleci/token/program.json b/.circleci/token/program.json
new file mode 100644
index 0000000000..94d9bc9824
--- /dev/null
+++ b/.circleci/token/program.json
@@ -0,0 +1,6 @@
+{
+ "program": "token.aleo",
+ "version": "0.0.0",
+ "description": "",
+ "license": "MIT"
+}
diff --git a/.circleci/token/run.sh b/.circleci/token/run.sh
new file mode 100644
index 0000000000..45fdc91936
--- /dev/null
+++ b/.circleci/token/run.sh
@@ -0,0 +1,239 @@
+#!/bin/bash
+# First check that Leo is installed.
+if ! command -v leo &> /dev/null
+then
+ echo "leo is not installed."
+ exit
+fi
+
+# The private key and address of Alice.
+# Swap these into program.json, when running transactions as the first bidder.
+# "private_key": "APrivateKey1zkp1w8PTxrRgGfAtfKUSq43iQyVbdQHfhGbiNPEg2LVSEXR",
+# "address": "aleo13ssze66adjjkt795z9u5wpq8h6kn0y2657726h4h3e3wfnez4vqsm3008q"
+
+# The private key and address of Bob.
+# Swap these into program.json, when running transactions as the second bidder.
+# "private_key": "APrivateKey1zkpFo72g7N9iFt3JzzeG8CqsS5doAiXyFvNCgk2oHvjRCzF"
+# "address": "aleo17vy26rpdhqx4598y5gp7nvaa9rk7tnvl6ufhvvf4calsrrqdaqyshdsf5z"
+
+# Swap in the private key of Alice.
+echo "
+NETWORK=testnet3
+PRIVATE_KEY=APrivateKey1zkp1w8PTxrRgGfAtfKUSq43iQyVbdQHfhGbiNPEg2LVSEXR
+" > .env
+
+# Publicly mint 100 tokens for Alice.
+echo "
+###############################################################################
+######## ########
+######## STEP 1: Publicly mint 100 tokens for Alice ########
+######## ########
+######## ----------------------------------------- ########
+######## | PUBLIC BALANCES | ########
+######## ----------------------------------------- ########
+######## ----------------------------------------- ########
+######## | Alice | 100 | ########
+######## ----------------------------------------- ########
+######## | Bob | 0 | ########
+######## ----------------------------------------- ########
+######## ########
+######## ----------------------------------------- ########
+######## | PRIVATE BALANCES | ########
+######## ----------------------------------------- ########
+######## ----------------------------------------- ########
+######## | Alice | 0 | ########
+######## ----------------------------------------- ########
+######## | Bob | 0 | ########
+######## ----------------------------------------- ########
+######## ########
+###############################################################################
+"
+leo run mint_public aleo13ssze66adjjkt795z9u5wpq8h6kn0y2657726h4h3e3wfnez4vqsm3008q 100u64
+
+# Swap in the private key of Bob.
+echo "
+NETWORK=testnet3
+PRIVATE_KEY=APrivateKey1zkpFo72g7N9iFt3JzzeG8CqsS5doAiXyFvNCgk2oHvjRCzF
+" > .env
+
+# Privately mint 100 tokens for Bob.
+echo "
+###############################################################################
+######## ########
+######## STEP 2: Privately mint 100 tokens for Bob ########
+######## ########
+######## ----------------------------------------- ########
+######## | PUBLIC BALANCES | ########
+######## ----------------------------------------- ########
+######## ----------------------------------------- ########
+######## | Alice | 100 | ########
+######## ----------------------------------------- ########
+######## | Bob | 0 | ########
+######## ----------------------------------------- ########
+######## ########
+######## ----------------------------------------- ########
+######## | PRIVATE BALANCES | ########
+######## ----------------------------------------- ########
+######## ----------------------------------------- ########
+######## | Alice | 0 | ########
+######## ----------------------------------------- ########
+######## | Bob | 100 | ########
+######## ----------------------------------------- ########
+######## ########
+###############################################################################
+"
+leo run mint_private aleo17vy26rpdhqx4598y5gp7nvaa9rk7tnvl6ufhvvf4calsrrqdaqyshdsf5z 100u64
+
+# Swap in the private key of Alice.
+echo "
+NETWORK=testnet3
+PRIVATE_KEY=APrivateKey1zkp1w8PTxrRgGfAtfKUSq43iQyVbdQHfhGbiNPEg2LVSEXR
+" > .env
+
+# Publicly transfer 10 tokens from Alice to Bob.
+echo "
+###############################################################################
+######## ########
+######## STEP 3: Publicly transfer 10 tokens from Alice to Bob ########
+######## ########
+######## ----------------------------------------- ########
+######## | PUBLIC BALANCES | ########
+######## ----------------------------------------- ########
+######## ----------------------------------------- ########
+######## | Alice | 90 | ########
+######## ----------------------------------------- ########
+######## | Bob | 10 | ########
+######## ----------------------------------------- ########
+######## ########
+######## ----------------------------------------- ########
+######## | PRIVATE BALANCES | ########
+######## ----------------------------------------- ########
+######## ----------------------------------------- ########
+######## | Alice | 0 | ########
+######## ----------------------------------------- ########
+######## | Bob | 100 | ########
+######## ----------------------------------------- ########
+######## ########
+###############################################################################
+"
+leo run transfer_public aleo17vy26rpdhqx4598y5gp7nvaa9rk7tnvl6ufhvvf4calsrrqdaqyshdsf5z 10u64
+
+# Swap in the private key of Bob.
+echo "
+NETWORK=testnet3
+PRIVATE_KEY=APrivateKey1zkpFo72g7N9iFt3JzzeG8CqsS5doAiXyFvNCgk2oHvjRCzF
+" > .env
+
+# Privately transfer 20 tokens from Bob to Alice.
+echo "
+###############################################################################
+######## ########
+######## STEP 4: Privately transfer 20 tokens from Bob to Alice ########
+######## ########
+######## ----------------------------------------- ########
+######## | PUBLIC BALANCES | ########
+######## ----------------------------------------- ########
+######## ----------------------------------------- ########
+######## | Alice | 90 | ########
+######## ----------------------------------------- ########
+######## | Bob | 10 | ########
+######## ----------------------------------------- ########
+######## ########
+######## ----------------------------------------- ########
+######## | PRIVATE BALANCES | ########
+######## ----------------------------------------- ########
+######## ----------------------------------------- ########
+######## | Alice | 20 | ########
+######## ----------------------------------------- ########
+######## | Bob | 80 | ########
+######## ----------------------------------------- ########
+######## ########
+###############################################################################
+"
+leo run transfer_private "{
+ owner: aleo17vy26rpdhqx4598y5gp7nvaa9rk7tnvl6ufhvvf4calsrrqdaqyshdsf5z.private,
+ amount: 100u64.private,
+ _nonce: 6586771265379155927089644749305420610382723873232320906747954786091923851913group.public
+ }" aleo13ssze66adjjkt795z9u5wpq8h6kn0y2657726h4h3e3wfnez4vqsm3008q 20u64
+
+# Swap in the private key of Alice.
+echo "
+NETWORK=testnet3
+PRIVATE_KEY=APrivateKey1zkp1w8PTxrRgGfAtfKUSq43iQyVbdQHfhGbiNPEg2LVSEXR
+" > .env
+
+# Convert 30 public tokens from Alice into 30 private tokens for Bob.
+echo "
+###############################################################################
+######## ########
+######## STEP 5: Convert 30 public tokens from Alice into 30 ########
+######## private tokens for Bob. ########
+######## ########
+######## ----------------------------------------- ########
+######## | PUBLIC BALANCES | ########
+######## ----------------------------------------- ########
+######## ----------------------------------------- ########
+######## | Alice | 60 | ########
+######## ----------------------------------------- ########
+######## | Bob | 10 | ########
+######## ----------------------------------------- ########
+######## ########
+######## ----------------------------------------- ########
+######## | PRIVATE BALANCES | ########
+######## ----------------------------------------- ########
+######## ----------------------------------------- ########
+######## | Alice | 20 | ########
+######## ----------------------------------------- ########
+######## | Bob | 110 | ########
+######## ----------------------------------------- ########
+######## ########
+###############################################################################
+"
+leo run transfer_public_to_private aleo17vy26rpdhqx4598y5gp7nvaa9rk7tnvl6ufhvvf4calsrrqdaqyshdsf5z 30u64
+
+# Swap in the private key of Bob.
+echo "
+NETWORK=testnet3
+PRIVATE_KEY=APrivateKey1zkpFo72g7N9iFt3JzzeG8CqsS5doAiXyFvNCgk2oHvjRCzF
+" > .env
+
+# Convert 40 private tokens from Bob into 40 public tokens for Alice.
+echo "
+###############################################################################
+######## ########
+######## STEP 6: Convert 40 private tokens from Bob into 40 ########
+######## public tokens for Alice. ########
+######## ########
+######## ----------------------------------------- ########
+######## | PUBLIC BALANCES | ########
+######## ----------------------------------------- ########
+######## ----------------------------------------- ########
+######## | Alice | 100 | ########
+######## ----------------------------------------- ########
+######## | Bob | 10 | ########
+######## ----------------------------------------- ########
+######## ########
+######## ----------------------------------------- ########
+######## | PRIVATE BALANCES | ########
+######## ----------------------------------------- ########
+######## ----------------------------------------- ########
+######## | Alice | 20 | ########
+######## ----------------------------------------- ########
+######## | Bob | 70 | ########
+######## ----------------------------------------- ########
+######## ########
+###############################################################################
+"
+leo run transfer_private_to_public "{
+ owner: aleo17vy26rpdhqx4598y5gp7nvaa9rk7tnvl6ufhvvf4calsrrqdaqyshdsf5z.private,
+ amount: 80u64.private,
+ _nonce: 1852830456042139988098466781381363679605019151318121788109768539956661608520group.public
+ }" aleo13ssze66adjjkt795z9u5wpq8h6kn0y2657726h4h3e3wfnez4vqsm3008q 40u64
+
+
+# Swap in the private key of Alice.
+# This is done to ensure that program.json is the same after every execution of ./run.sh.
+echo "
+NETWORK=testnet3
+PRIVATE_KEY=APrivateKey1zkp1w8PTxrRgGfAtfKUSq43iQyVbdQHfhGbiNPEg2LVSEXR
+" > .env
diff --git a/.circleci/token/src/main.leo b/.circleci/token/src/main.leo
new file mode 100644
index 0000000000..120c6648fd
--- /dev/null
+++ b/.circleci/token/src/main.leo
@@ -0,0 +1,128 @@
+program token.aleo {
+ // On-chain storage of an `account` map, with `address` as the key,
+ // and `u64` as the value.
+ mapping account: address => u64;
+
+ record token {
+ // The token owner.
+ owner: address,
+ // The token amount.
+ amount: u64,
+ }
+
+ /* Mint */
+
+ // The function `mint_public` issues the specified token amount for the token receiver publicly on the network.
+ transition mint_public(public receiver: address, public amount: u64) {
+ // Mint the tokens publicly by invoking the computation on-chain.
+ return then finalize(receiver, amount);
+ }
+
+ finalize mint_public(public receiver: address, public amount: u64) {
+ // Increments `account[receiver]` by `amount`.
+ // If `account[receiver]` does not exist, it will be created.
+ // If `account[receiver] + amount` overflows, `mint_public` is reverted.
+ let current_amount: u64 = Mapping::get_or_use(account, receiver, 0u64);
+ Mapping::set(account, receiver, current_amount + amount);
+ }
+
+ // The function `mint_private` initializes a new record with the specified amount of tokens for the receiver.
+ transition mint_private(receiver: address, amount: u64) -> token {
+ return token {
+ owner: receiver,
+ amount: amount,
+ };
+ }
+
+ /* Transfer */
+ transition transfer_public(public receiver: address, public amount: u64) {
+ // Transfer the tokens publicly, by invoking the computation on-chain.
+ return then finalize(self.caller, receiver, amount);
+ }
+
+ finalize transfer_public(public sender: address, public receiver: address, public amount: u64) {
+ // Decrements `account[sender]` by `amount`.
+ // If `account[sender]` does not exist, it will be created.
+ // If `account[sender] - amount` underflows, `transfer_public` is reverted.
+ let sender_amount: u64 = Mapping::get_or_use(account, sender, 0u64);
+ Mapping::set(account, sender, sender_amount - amount);
+ // Increments `account[receiver]` by `amount`.
+ // If `account[receiver]` does not exist, it will be created.
+ // If `account[receiver] + amount` overflows, `transfer_public` is reverted.
+ let receiver_amount: u64 = Mapping::get_or_use(account, receiver, 0u64);
+ Mapping::set(account, receiver, receiver_amount + amount);
+ }
+
+ // The function `transfer_private` sends the specified token amount to the token receiver from the specified token record.
+ transition transfer_private(sender: token, receiver: address, amount: u64) -> (token, token) {
+ // Checks the given token record has sufficient balance.
+ // This `sub` operation is safe, and the proof will fail if an overflow occurs.
+ // `difference` holds the change amount to be returned to sender.
+ let difference: u64 = sender.amount - amount;
+
+ // Produce a token record with the change amount for the sender.
+ let remaining: token = token {
+ owner: sender.owner,
+ amount: difference,
+ };
+
+ // Produce a token record for the specified receiver.
+ let transferred: token = token {
+ owner: receiver,
+ amount: amount,
+ };
+
+ // Output the sender's change record and the receiver's record.
+ return (remaining, transferred);
+ }
+
+ // The function `transfer_private_to_public` turns a specified token amount from a token record into public tokens for the specified receiver.
+ // This function preserves privacy for the sender's record, however it publicly reveals the token receiver and the token amount.
+ transition transfer_private_to_public(sender: token, public receiver: address, public amount: u64) -> token {
+ // Checks the given token record has a sufficient token amount.
+ // This `sub` operation is safe, and the proof will fail if an underflow occurs.
+ // `difference` holds the change amount for the caller.
+ let difference: u64 = sender.amount - amount;
+
+ // Produces a token record with the change amount for the caller.
+ let remaining: token = token {
+ owner: sender.owner,
+ amount: difference,
+ };
+
+ // Output the sender's change record.
+ // Increment the token amount publicly for the token receiver.
+ return remaining then finalize(receiver, amount);
+ }
+
+ finalize transfer_private_to_public(public receiver: address, public amount: u64) {
+ // Increments `account[receiver]` by `amount`.
+ // If `account[receiver]` does not exist, it will be created.
+ // If `account[receiver] + amount` overflows, `transfer_private_to_public` is reverted.
+ let current_amount: u64 = Mapping::get_or_use(account, receiver, 0u64);
+ Mapping::set(account, receiver, current_amount + amount);
+ }
+
+ // The function `transfer_public_to_private` turns a specified token amount from `account` into a token record for the specified receiver.
+ // This function preserves privacy for the receiver's record, however it publicly reveals the caller and the specified token amount.
+ transition transfer_public_to_private(public receiver: address, public amount: u64) -> token {
+ // Produces a token record for the token receiver.
+ let transferred: token = token {
+ owner: receiver,
+ amount: amount,
+ };
+
+ // Output the receiver's record.
+ // Decrement the token amount of the caller publicly.
+ return transferred then finalize(self.caller, amount);
+ }
+
+ finalize transfer_public_to_private(public sender: address, public amount: u64) {
+ // Decrements `account[sender]` by `amount`.
+ // If `account[sender]` does not exist, it will be created.
+ // If `account[sender] - amount` underflows, `transfer_public_to_private` is reverted.
+ let current_amount: u64 = Mapping::get_or_use(account, sender, 0u64);
+ Mapping::set(account, sender, current_amount - amount);
+ }
+
+}
diff --git a/Cargo.lock b/Cargo.lock
index 460916e7be..d642a4db7f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -735,6 +735,19 @@ dependencies = [
"syn 2.0.46",
]
+[[package]]
+name = "dashmap"
+version = "5.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
+dependencies = [
+ "cfg-if",
+ "hashbrown 0.14.2",
+ "lock_api",
+ "once_cell",
+ "parking_lot_core",
+]
+
[[package]]
name = "der"
version = "0.7.8"
@@ -823,6 +836,16 @@ dependencies = [
"windows-sys 0.48.0",
]
+[[package]]
+name = "disassembler"
+version = "1.10.0"
+dependencies = [
+ "leo-ast",
+ "leo-errors",
+ "leo-span",
+ "snarkvm",
+]
+
[[package]]
name = "doc-comment"
version = "0.3.3"
@@ -990,6 +1013,21 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1fd087255f739f4f1aeea69f11b72f8080e9c2e7645cd06955dad4a178a49e3"
+[[package]]
+name = "futures"
+version = "0.3.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-executor",
+ "futures-io",
+ "futures-sink",
+ "futures-task",
+ "futures-util",
+]
+
[[package]]
name = "futures-channel"
version = "0.3.29"
@@ -997,6 +1035,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb"
dependencies = [
"futures-core",
+ "futures-sink",
]
[[package]]
@@ -1005,6 +1044,17 @@ version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
+[[package]]
+name = "futures-executor"
+version = "0.3.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "futures-util",
+]
+
[[package]]
name = "futures-io"
version = "0.3.29"
@@ -1029,8 +1079,10 @@ version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"
dependencies = [
+ "futures-channel",
"futures-core",
"futures-io",
+ "futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
@@ -1380,6 +1432,7 @@ dependencies = [
"serde",
"serde_json",
"smallvec",
+ "snarkvm",
]
[[package]]
@@ -1387,6 +1440,7 @@ name = "leo-compiler"
version = "1.10.0"
dependencies = [
"dotenvy",
+ "indexmap 1.9.3",
"leo-ast",
"leo-errors",
"leo-package",
@@ -1413,6 +1467,7 @@ dependencies = [
"colored",
"derivative",
"leo-span",
+ "reqwest",
"serde",
"thiserror",
]
@@ -1421,6 +1476,7 @@ dependencies = [
name = "leo-lang"
version = "1.10.0"
dependencies = [
+ "aleo-std",
"ansi_term",
"assert_cmd",
"backtrace",
@@ -1442,10 +1498,12 @@ dependencies = [
"rand_chacha",
"rand_core",
"reqwest",
+ "retriever",
"rusty-hook",
"self_update 0.39.0",
"serde",
"serde_json",
+ "serial_test",
"snarkvm",
"sys-info",
"test_dir",
@@ -1460,11 +1518,14 @@ dependencies = [
name = "leo-package"
version = "1.10.0"
dependencies = [
+ "aleo-std",
"indexmap 1.9.3",
"lazy_static",
"leo-errors",
"rand",
+ "retriever",
"serde",
+ "serial_test",
"snarkvm",
"toml 0.8.8",
"tracing",
@@ -1522,6 +1583,7 @@ dependencies = [
"backtrace",
"clap",
"criterion",
+ "indexmap 1.9.3",
"leo-compiler",
"leo-errors",
"leo-span",
@@ -2180,6 +2242,26 @@ dependencies = [
"winreg",
]
+[[package]]
+name = "retriever"
+version = "1.10.0"
+dependencies = [
+ "aleo-std",
+ "disassembler",
+ "indexmap 1.9.3",
+ "leo-ast",
+ "leo-errors",
+ "leo-passes",
+ "leo-span",
+ "serde",
+ "serde_json",
+ "serial_test",
+ "sha2",
+ "tempfile",
+ "toml 0.8.8",
+ "ureq",
+]
+
[[package]]
name = "ring"
version = "0.17.5"
@@ -2447,6 +2529,31 @@ dependencies = [
"yaml-rust",
]
+[[package]]
+name = "serial_test"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0e56dd856803e253c8f298af3f4d7eb0ae5e23a737252cd90bb4f3b435033b2d"
+dependencies = [
+ "dashmap",
+ "futures",
+ "lazy_static",
+ "log",
+ "parking_lot",
+ "serial_test_derive",
+]
+
+[[package]]
+name = "serial_test_derive"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f"
+dependencies = [
+ "proc-macro2",
+ "quote 1.0.35",
+ "syn 2.0.46",
+]
+
[[package]]
name = "sha1"
version = "0.10.6"
diff --git a/Cargo.toml b/Cargo.toml
index eda070d9ba..99066dbd0b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -41,7 +41,9 @@ members = [
"docs/grammar",
"errors",
"leo/package",
- "tests/test-framework"
+ "tests/test-framework",
+ "utils/disassembler",
+ "utils/retriever"
]
[workspace.dependencies.snarkvm]
@@ -59,6 +61,10 @@ default = [ ]
ci_skip = [ "leo-compiler/ci_skip" ]
noconfig = [ ]
+[dependencies.aleo-std]
+version = "0.1.18"
+default-features = false
+
[dependencies.leo-ast]
path = "./compiler/ast"
version = "=1.10.0"
@@ -83,6 +89,10 @@ version = "=1.10.0"
path = "./compiler/span"
version = "=1.10.0"
+[dependencies.retriever]
+path = "./utils/retriever"
+version = "1.10.0"
+
[dependencies.backtrace]
version = "0.3.68"
@@ -137,6 +147,9 @@ features = [ "derive" ]
[dependencies.serde_json]
version = "1.0"
+[dependencies.serial_test]
+version = "2.0.0"
+
[dependencies.snarkvm]
workspace = true
features = [ "circuit", "console" ]
diff --git a/compiler/ast/Cargo.toml b/compiler/ast/Cargo.toml
index 7e85eab976..95ddf55f07 100644
--- a/compiler/ast/Cargo.toml
+++ b/compiler/ast/Cargo.toml
@@ -18,6 +18,9 @@ license = "GPL-3.0"
edition = "2021"
rust-version = "1.69"
+[dependencies.snarkvm]
+workspace = true
+
[dependencies.leo-errors]
path = "../../errors"
version = "=1.10.0"
diff --git a/compiler/ast/src/common/identifier.rs b/compiler/ast/src/common/identifier.rs
index 59ec2482e4..b798677a2f 100644
--- a/compiler/ast/src/common/identifier.rs
+++ b/compiler/ast/src/common/identifier.rs
@@ -16,6 +16,7 @@
use leo_errors::Result;
use leo_span::{Span, Symbol};
+use snarkvm::console::program::Identifier as IdentifierCore;
use crate::{simple_node_impl, Node, NodeID};
use serde::{
@@ -28,6 +29,7 @@ use serde::{
Serialize,
Serializer,
};
+use snarkvm::prelude::Network;
use std::{
collections::BTreeMap,
fmt,
@@ -152,3 +154,8 @@ impl<'de> Deserialize<'de> for Identifier {
deserializer.deserialize_str(IdentifierVisitor)
}
}
+impl From<&IdentifierCore> for Identifier {
+ fn from(id: &IdentifierCore) -> Self {
+ Self { name: Symbol::intern(&id.to_string()), span: Default::default(), id: Default::default() }
+ }
+}
diff --git a/compiler/ast/src/functions/finalize.rs b/compiler/ast/src/functions/finalize.rs
index fbc0b31173..e792467a15 100644
--- a/compiler/ast/src/functions/finalize.rs
+++ b/compiler/ast/src/functions/finalize.rs
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see .
-use crate::{Block, Identifier, Input, Node, NodeID, Output, TupleType, Type};
+use crate::{Block, FinalizeStub, Identifier, Input, Node, NodeID, Output, TupleType, Type};
use leo_span::Span;
@@ -72,4 +72,17 @@ impl fmt::Display for Finalize {
}
}
+impl From for Finalize {
+ fn from(finalize_stub: FinalizeStub) -> Self {
+ Self::new(
+ finalize_stub.identifier,
+ finalize_stub.input,
+ finalize_stub.output,
+ Block::default(),
+ finalize_stub.span,
+ finalize_stub.id,
+ )
+ }
+}
+
crate::simple_node_impl!(Finalize);
diff --git a/compiler/ast/src/functions/mod.rs b/compiler/ast/src/functions/mod.rs
index a122ac480f..26ae6c1975 100644
--- a/compiler/ast/src/functions/mod.rs
+++ b/compiler/ast/src/functions/mod.rs
@@ -38,7 +38,7 @@ pub use output::*;
pub mod mode;
pub use mode::*;
-use crate::{Block, Identifier, Node, NodeID, TupleType, Type};
+use crate::{Block, FunctionStub, Identifier, Node, NodeID, TupleType, Type};
use leo_span::{Span, Symbol};
use serde::{Deserialize, Serialize};
@@ -139,6 +139,24 @@ impl Function {
}
}
+impl From for Function {
+ fn from(function: FunctionStub) -> Self {
+ let finalize = function.finalize_stub.map(Finalize::from);
+ Self {
+ annotations: function.annotations,
+ variant: function.variant,
+ identifier: function.identifier,
+ input: function.input,
+ output: function.output,
+ output_type: function.output_type,
+ block: Block::default(),
+ finalize,
+ span: function.span,
+ id: function.id,
+ }
+ }
+}
+
impl fmt::Debug for Function {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.format(f)
diff --git a/compiler/ast/src/lib.rs b/compiler/ast/src/lib.rs
index 62d95ced40..3e7b234b73 100644
--- a/compiler/ast/src/lib.rs
+++ b/compiler/ast/src/lib.rs
@@ -59,6 +59,10 @@ pub mod types;
pub use self::types::*;
pub mod value;
+
+pub mod stub;
+pub use self::stub::*;
+
pub use self::value::*;
pub use common::node::*;
diff --git a/compiler/ast/src/mapping/mod.rs b/compiler/ast/src/mapping/mod.rs
index 6ca05fac57..e5875ccccc 100644
--- a/compiler/ast/src/mapping/mod.rs
+++ b/compiler/ast/src/mapping/mod.rs
@@ -19,6 +19,7 @@ use crate::{Identifier, Node, NodeID, Type};
use leo_span::Span;
use serde::{Deserialize, Serialize};
+use snarkvm::prelude::{Mapping as MappingCore, Network};
use std::fmt;
/// A mapping declaration, e.g `mapping balances: address => u128`.
@@ -36,6 +37,17 @@ pub struct Mapping {
pub id: NodeID,
}
+impl From<&MappingCore> for Mapping {
+ fn from(mapping: &MappingCore) -> Self {
+ Self {
+ identifier: Identifier::from(mapping.name()),
+ key_type: Type::from(mapping.key().plaintext_type()),
+ value_type: Type::from(mapping.value().plaintext_type()),
+ span: Default::default(),
+ id: Default::default(),
+ }
+ }
+}
impl fmt::Display for Mapping {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "mapping {}: {} => {}", self.identifier, self.key_type, self.value_type)
diff --git a/compiler/ast/src/passes/reconstructor.rs b/compiler/ast/src/passes/reconstructor.rs
index 793df279b9..8e6b9149cb 100644
--- a/compiler/ast/src/passes/reconstructor.rs
+++ b/compiler/ast/src/passes/reconstructor.rs
@@ -417,6 +417,7 @@ pub trait ProgramReconstructor: StatementReconstructor {
.into_iter()
.map(|(id, import)| (id, (self.reconstruct_import(import.0), import.1)))
.collect(),
+ stubs: input.stubs.into_iter().map(|(id, stub)| (id, self.reconstruct_stub(stub))).collect(),
program_scopes: input
.program_scopes
.into_iter()
@@ -425,6 +426,18 @@ pub trait ProgramReconstructor: StatementReconstructor {
}
}
+ fn reconstruct_stub(&mut self, input: Stub) -> Stub {
+ Stub {
+ imports: input.imports,
+ stub_id: input.stub_id,
+ consts: input.consts,
+ structs: input.structs,
+ mappings: input.mappings,
+ span: input.span,
+ functions: input.functions.into_iter().map(|(i, f)| (i, self.reconstruct_function_stub(f))).collect(),
+ }
+ }
+
fn reconstruct_program_scope(&mut self, input: ProgramScope) -> ProgramScope {
ProgramScope {
program_id: input.program_id,
@@ -466,6 +479,10 @@ pub trait ProgramReconstructor: StatementReconstructor {
}
}
+ fn reconstruct_function_stub(&mut self, input: FunctionStub) -> FunctionStub {
+ input
+ }
+
fn reconstruct_struct(&mut self, input: Struct) -> Struct {
input
}
diff --git a/compiler/ast/src/passes/visitor.rs b/compiler/ast/src/passes/visitor.rs
index dbcefea609..b2c16d6648 100644
--- a/compiler/ast/src/passes/visitor.rs
+++ b/compiler/ast/src/passes/visitor.rs
@@ -222,7 +222,7 @@ pub trait StatementVisitor<'a>: ExpressionVisitor<'a> {
pub trait ProgramVisitor<'a>: StatementVisitor<'a> {
fn visit_program(&mut self, input: &'a Program) {
input.imports.values().for_each(|import| self.visit_import(&import.0));
-
+ input.stubs.values().for_each(|stub| self.visit_stub(stub));
input.program_scopes.values().for_each(|scope| self.visit_program_scope(scope));
}
@@ -236,6 +236,8 @@ pub trait ProgramVisitor<'a>: StatementVisitor<'a> {
input.consts.iter().for_each(|(_, c)| (self.visit_const(c)));
}
+ fn visit_stub(&mut self, _input: &'a Stub) {}
+
fn visit_import(&mut self, input: &'a Program) {
self.visit_program(input)
}
@@ -250,4 +252,8 @@ pub trait ProgramVisitor<'a>: StatementVisitor<'a> {
self.visit_block(&finalize.block);
}
}
+
+ fn visit_function_stub(&mut self, _input: &'a FunctionStub) {}
+
+ fn visit_struct_stub(&mut self, _input: &'a Struct) {}
}
diff --git a/compiler/ast/src/program/mod.rs b/compiler/ast/src/program/mod.rs
index 0d6bc76de0..16973cba18 100644
--- a/compiler/ast/src/program/mod.rs
+++ b/compiler/ast/src/program/mod.rs
@@ -24,6 +24,7 @@ pub use program_scope::*;
use leo_span::{Span, Symbol};
+use crate::Stub;
use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
use std::fmt;
@@ -33,6 +34,8 @@ use std::fmt;
pub struct Program {
/// A map from import names to import definitions.
pub imports: IndexMap,
+ /// A map from program stub names to program stub scopes.
+ pub stubs: IndexMap,
/// A map from program names to program scopes.
pub program_scopes: IndexMap,
}
@@ -42,6 +45,10 @@ impl fmt::Display for Program {
for (id, _import) in self.imports.iter() {
writeln!(f, "import {id}.leo;")?;
}
+ for (_, stub) in self.stubs.iter() {
+ stub.fmt(f)?;
+ writeln!(f,)?;
+ }
for (_, program_scope) in self.program_scopes.iter() {
program_scope.fmt(f)?;
writeln!(f,)?;
@@ -53,6 +60,6 @@ impl fmt::Display for Program {
impl Default for Program {
/// Constructs an empty program node.
fn default() -> Self {
- Self { imports: IndexMap::new(), program_scopes: IndexMap::new() }
+ Self { imports: IndexMap::new(), stubs: IndexMap::new(), program_scopes: IndexMap::new() }
}
}
diff --git a/compiler/ast/src/program/program_id.rs b/compiler/ast/src/program/program_id.rs
index 77f36c9010..3d284e5cca 100644
--- a/compiler/ast/src/program/program_id.rs
+++ b/compiler/ast/src/program/program_id.rs
@@ -18,6 +18,7 @@ use crate::Identifier;
use core::fmt;
use serde::{de, de::Visitor, Deserialize, Deserializer, Serialize, Serializer};
+use snarkvm::{console::program::ProgramID, prelude::Network};
use std::collections::BTreeMap;
/// An identifier for a program that is eventually deployed to the network.
@@ -92,3 +93,9 @@ impl<'de> Deserialize<'de> for ProgramId {
deserializer.deserialize_str(ProgramIdVisitor)
}
}
+
+impl From<&ProgramID> for ProgramId {
+ fn from(program: &ProgramID) -> Self {
+ Self { name: Identifier::from(program.name()), network: Identifier::from(program.network()) }
+ }
+}
diff --git a/compiler/ast/src/program/program_scope.rs b/compiler/ast/src/program/program_scope.rs
index 1a70e60b3c..9ad8c54579 100644
--- a/compiler/ast/src/program/program_scope.rs
+++ b/compiler/ast/src/program/program_scope.rs
@@ -16,7 +16,7 @@
//! A Leo program scope consists of struct, function, and mapping definitions.
-use crate::{ConstDeclaration, Function, Mapping, ProgramId, Struct};
+use crate::{ConstDeclaration, Function, Mapping, ProgramId, Struct, Stub};
use leo_span::{Span, Symbol};
use serde::{Deserialize, Serialize};
@@ -39,6 +39,23 @@ pub struct ProgramScope {
pub span: Span,
}
+impl From for ProgramScope {
+ fn from(stub: Stub) -> Self {
+ Self {
+ program_id: stub.stub_id,
+ consts: stub.consts,
+ structs: stub.structs,
+ mappings: stub.mappings,
+ functions: stub
+ .functions
+ .into_iter()
+ .map(|(symbol, function)| (symbol, Function::from(function)))
+ .collect(),
+ span: stub.span,
+ }
+ }
+}
+
impl fmt::Display for ProgramScope {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, "program {} {{", self.program_id)?;
diff --git a/compiler/ast/src/statement/block.rs b/compiler/ast/src/statement/block.rs
index e57f5821d9..cd034dbc6f 100644
--- a/compiler/ast/src/statement/block.rs
+++ b/compiler/ast/src/statement/block.rs
@@ -21,7 +21,7 @@ use serde::{Deserialize, Serialize};
use std::fmt;
/// A block `{ [stmt]* }` consisting of a list of statements to execute in order.
-#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
+#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug, Default)]
pub struct Block {
/// The list of statements to execute.
pub statements: Vec,
diff --git a/compiler/ast/src/struct/mod.rs b/compiler/ast/src/struct/mod.rs
index bec8684036..8a511df9d6 100644
--- a/compiler/ast/src/struct/mod.rs
+++ b/compiler/ast/src/struct/mod.rs
@@ -17,12 +17,21 @@
pub mod member;
pub use member::*;
-use crate::{Identifier, Node, NodeID};
+use crate::{Identifier, Mode, Node, NodeID, Type};
use leo_span::{Span, Symbol};
+use itertools::Itertools;
use serde::{Deserialize, Serialize};
use std::fmt;
+use snarkvm::{
+ console::program::{RecordType, StructType},
+ prelude::{
+ EntryType::{Constant, Private, Public},
+ Network,
+ },
+};
+
/// A struct type definition, e.g., `struct Foo { my_field: Bar }`.
/// In some languages these are called `struct`s.
///
@@ -70,10 +79,68 @@ impl fmt::Display for Struct {
f.write_str(if self.is_record { "record" } else { "struct" })?;
writeln!(f, " {} {{ ", self.identifier)?;
for field in self.members.iter() {
- writeln!(f, " {field}")?;
+ writeln!(f, " {field}")?;
}
- write!(f, "}}")
+ write!(f, " }}")
}
}
crate::simple_node_impl!(Struct);
+
+impl From<&StructType> for Struct {
+ fn from(input: &StructType) -> Self {
+ Self {
+ identifier: Identifier::from(input.name()),
+ members: input
+ .members()
+ .iter()
+ .map(|(id, type_)| Member {
+ mode: Mode::None,
+ identifier: Identifier::from(id),
+ type_: Type::from(type_),
+ span: Default::default(),
+ id: Default::default(),
+ })
+ .collect(),
+ is_record: false,
+ span: Default::default(),
+ id: Default::default(),
+ }
+ }
+}
+
+impl From<&RecordType> for Struct {
+ fn from(input: &RecordType) -> Self {
+ Self {
+ identifier: Identifier::from(input.name()),
+ members: [
+ vec![Member {
+ mode: if input.owner().is_private() { Mode::Public } else { Mode::Private },
+ identifier: Identifier::new(Symbol::intern("owner"), Default::default()),
+ type_: Type::Address,
+ span: Default::default(),
+ id: Default::default(),
+ }],
+ input
+ .entries()
+ .iter()
+ .map(|(id, entry)| Member {
+ mode: if input.owner().is_public() { Mode::Public } else { Mode::Private },
+ identifier: Identifier::from(id),
+ type_: match entry {
+ Public(t) => Type::from(t),
+ Private(t) => Type::from(t),
+ Constant(t) => Type::from(t),
+ },
+ span: Default::default(),
+ id: Default::default(),
+ })
+ .collect_vec(),
+ ]
+ .concat(),
+ is_record: true,
+ span: Default::default(),
+ id: Default::default(),
+ }
+ }
+}
diff --git a/compiler/ast/src/stub/finalize_stub.rs b/compiler/ast/src/stub/finalize_stub.rs
new file mode 100644
index 0000000000..9cfdcbef72
--- /dev/null
+++ b/compiler/ast/src/stub/finalize_stub.rs
@@ -0,0 +1,101 @@
+// Copyright (C) 2019-2023 Aleo Systems Inc.
+// This file is part of the Leo library.
+
+// The Leo library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// The Leo library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with the Leo library. If not, see .
+
+use crate::{Finalize, FunctionInput, Identifier, Input, Mode, Node, NodeID, Output, TupleType, Type};
+
+use leo_span::{Span, Symbol};
+
+use core::fmt;
+use serde::{Deserialize, Serialize};
+use snarkvm::{
+ prelude::{
+ FinalizeType::{Future, Plaintext},
+ Network,
+ },
+ synthesizer::program::{CommandTrait, FinalizeCore},
+};
+
+/// A finalize stub.
+#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Debug)]
+pub struct FinalizeStub {
+ /// The finalize identifier.
+ pub identifier: Identifier,
+ /// The finalize block's input parameters.
+ pub input: Vec,
+ /// The finalize blocks's output declaration.
+ pub output: Vec