diff --git a/README.md b/README.md index 5910aca..ec9fac7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,9 @@ -# Some "interesting" Leo programs +# A tour of Leo by example -Add yours by making a PR! +## Concepts + +- **Testing**: `example_with_test` +- **Modules**: `calculator` +- **Upgradability** `upgrades` +- **Const Generics**: `calculator` diff --git a/calculator/.gitignore b/calculator/.gitignore new file mode 100644 index 0000000..f721f7f --- /dev/null +++ b/calculator/.gitignore @@ -0,0 +1,5 @@ +.env +*.avm +*.prover +*.verifier +outputs/ diff --git a/calculator/build/main.aleo b/calculator/build/main.aleo new file mode 100644 index 0000000..414eab6 --- /dev/null +++ b/calculator/build/main.aleo @@ -0,0 +1,654 @@ +program calculator.aleo; + +struct Registers__7V67zj5E35T: + r as [u32; 4u32]; + +struct Instruction__Lppf6AZB52w: + opcode as u8; + op0 as i64; + op1 as i64; + d0 as i64; + +struct History__Cdcu2iyNy6a: + total as u32; + head as u32; + entries as [Instruction__Lppf6AZB52w; 8u32]; + +struct Transcript__5ydsl2cgxYJ: + total as u32; + entries as [Instruction__Lppf6AZB52w; 8u32]; + +struct Calculator__AeUcVKuTwJT: + registers as Registers__7V67zj5E35T; + history as History__Cdcu2iyNy6a; + +function init: + cast 0u32 0u32 0u32 0u32 into r0 as [u32; 4u32]; + cast r0 into r1 as Registers__7V67zj5E35T; + is.eq 0u8 0u8 into r2; + is.eq 0u8 1u8 into r3; + or r2 r3 into r4; + is.eq 0u8 2u8 into r5; + or r4 r5 into r6; + is.eq 0u8 3u8 into r7; + or r6 r7 into r8; + is.eq 0u8 4u8 into r9; + or r8 r9 into r10; + assert.eq r10 true; + gte 0i64 -32i64 into r11; + assert.eq r11 true; + gte 0i64 -32i64 into r12; + assert.eq r12 true; + lt 0i64 0i64 into r13; + gte 0i64 -32i64 into r14; + and r13 r14 into r15; + assert.eq r15 true; + cast 0u8 0i64 0i64 0i64 into r16 as Instruction__Lppf6AZB52w; + cast r16 r16 r16 r16 r16 r16 r16 r16 into r17 as [Instruction__Lppf6AZB52w; 8u32]; + cast 0u32 0u32 r17 into r18 as History__Cdcu2iyNy6a; + cast r1 r18 into r19 as Calculator__AeUcVKuTwJT; + output r19 as Calculator__AeUcVKuTwJT.private; + +function execute: + input r0 as Calculator__AeUcVKuTwJT.private; + input r1 as [Instruction__Lppf6AZB52w; 4u32].private; + is.eq r1[0u32].opcode 0u8 into r2; + cast r0.registers r0.history into r3 as Calculator__AeUcVKuTwJT; + cast 0u32 into r4 as i64; + add r4 1i64 into r5; + neg r5 into r6; + is.eq r1[0u32].op0 r6 into r7; + cast r0.registers.r[0u32] into r8 as i64; + ternary r7 r8 r1[0u32].op0 into r9; + cast 1u32 into r10 as i64; + add r10 1i64 into r11; + neg r11 into r12; + is.eq r1[0u32].op0 r12 into r13; + cast r0.registers.r[1u32] into r14 as i64; + ternary r13 r14 r9 into r15; + cast 2u32 into r16 as i64; + add r16 1i64 into r17; + neg r17 into r18; + is.eq r1[0u32].op0 r18 into r19; + cast r0.registers.r[2u32] into r20 as i64; + ternary r19 r20 r15 into r21; + cast 3u32 into r22 as i64; + add r22 1i64 into r23; + neg r23 into r24; + is.eq r1[0u32].op0 r24 into r25; + cast r0.registers.r[3u32] into r26 as i64; + ternary r25 r26 r21 into r27; + cast r27 into r28 as u32; + cast 0u32 into r29 as i64; + add r29 1i64 into r30; + neg r30 into r31; + is.eq r1[0u32].op1 r31 into r32; + cast r0.registers.r[0u32] into r33 as i64; + ternary r32 r33 r1[0u32].op1 into r34; + cast 1u32 into r35 as i64; + add r35 1i64 into r36; + neg r36 into r37; + is.eq r1[0u32].op1 r37 into r38; + cast r0.registers.r[1u32] into r39 as i64; + ternary r38 r39 r34 into r40; + cast 2u32 into r41 as i64; + add r41 1i64 into r42; + neg r42 into r43; + is.eq r1[0u32].op1 r43 into r44; + cast r0.registers.r[2u32] into r45 as i64; + ternary r44 r45 r40 into r46; + cast 3u32 into r47 as i64; + add r47 1i64 into r48; + neg r48 into r49; + is.eq r1[0u32].op1 r49 into r50; + cast r0.registers.r[3u32] into r51 as i64; + ternary r50 r51 r46 into r52; + cast r52 into r53 as u32; + is.eq r1[0u32].opcode 1u8 into r54; + add r28 r53 into r55; + not r54 into r56; + is.eq r1[0u32].opcode 2u8 into r57; + sub r28 r53 into r58; + not r57 into r59; + is.eq r1[0u32].opcode 3u8 into r60; + mul r28 r53 into r61; + not r60 into r62; + is.eq r1[0u32].opcode 4u8 into r63; + div r28 r53 into r64; + not r63 into r65; + and r56 r59 into r66; + and r66 r62 into r67; + and r67 r65 into r68; + not r68 into r69; + or false r69 into r70; + or r70 r2 into r71; + assert.eq r71 true; + ternary r63 r64 0u32 into r72; + ternary r60 r61 r72 into r73; + ternary r57 r58 r73 into r74; + ternary r54 r55 r74 into r75; + lt r1[0u32].d0 0i64 into r76; + gte r1[0u32].d0 -4i64 into r77; + and r76 r77 into r78; + assert.eq r78 true; + add r1[0u32].d0 1i64 into r79; + cast r79 into r80 as u32; + is.eq r80 0u32 into r81; + ternary r81 r75 r0.registers.r[0u32] into r82; + is.eq r80 1u32 into r83; + ternary r83 r75 r0.registers.r[1u32] into r84; + is.eq r80 2u32 into r85; + ternary r85 r75 r0.registers.r[2u32] into r86; + is.eq r80 3u32 into r87; + ternary r87 r75 r0.registers.r[3u32] into r88; + cast r82 r84 r86 r88 into r89 as [u32; 4u32]; + cast r89 into r90 as Registers__7V67zj5E35T; + cast r90 r0.history into r91 as Calculator__AeUcVKuTwJT; + ternary r2 r3.registers.r[0u32] r91.registers.r[0u32] into r92; + ternary r2 r3.registers.r[1u32] r91.registers.r[1u32] into r93; + ternary r2 r3.registers.r[2u32] r91.registers.r[2u32] into r94; + ternary r2 r3.registers.r[3u32] r91.registers.r[3u32] into r95; + cast r92 r93 r94 r95 into r96 as [u32; 4u32]; + cast r96 into r97 as Registers__7V67zj5E35T; + ternary r2 r3.history.entries[0u32].opcode r91.history.entries[0u32].opcode into r98; + ternary r2 r3.history.entries[0u32].op0 r91.history.entries[0u32].op0 into r99; + ternary r2 r3.history.entries[0u32].op1 r91.history.entries[0u32].op1 into r100; + ternary r2 r3.history.entries[0u32].d0 r91.history.entries[0u32].d0 into r101; + cast r98 r99 r100 r101 into r102 as Instruction__Lppf6AZB52w; + ternary r2 r3.history.entries[1u32].opcode r91.history.entries[1u32].opcode into r103; + ternary r2 r3.history.entries[1u32].op0 r91.history.entries[1u32].op0 into r104; + ternary r2 r3.history.entries[1u32].op1 r91.history.entries[1u32].op1 into r105; + ternary r2 r3.history.entries[1u32].d0 r91.history.entries[1u32].d0 into r106; + cast r103 r104 r105 r106 into r107 as Instruction__Lppf6AZB52w; + ternary r2 r3.history.entries[2u32].opcode r91.history.entries[2u32].opcode into r108; + ternary r2 r3.history.entries[2u32].op0 r91.history.entries[2u32].op0 into r109; + ternary r2 r3.history.entries[2u32].op1 r91.history.entries[2u32].op1 into r110; + ternary r2 r3.history.entries[2u32].d0 r91.history.entries[2u32].d0 into r111; + cast r108 r109 r110 r111 into r112 as Instruction__Lppf6AZB52w; + ternary r2 r3.history.entries[3u32].opcode r91.history.entries[3u32].opcode into r113; + ternary r2 r3.history.entries[3u32].op0 r91.history.entries[3u32].op0 into r114; + ternary r2 r3.history.entries[3u32].op1 r91.history.entries[3u32].op1 into r115; + ternary r2 r3.history.entries[3u32].d0 r91.history.entries[3u32].d0 into r116; + cast r113 r114 r115 r116 into r117 as Instruction__Lppf6AZB52w; + ternary r2 r3.history.entries[4u32].opcode r91.history.entries[4u32].opcode into r118; + ternary r2 r3.history.entries[4u32].op0 r91.history.entries[4u32].op0 into r119; + ternary r2 r3.history.entries[4u32].op1 r91.history.entries[4u32].op1 into r120; + ternary r2 r3.history.entries[4u32].d0 r91.history.entries[4u32].d0 into r121; + cast r118 r119 r120 r121 into r122 as Instruction__Lppf6AZB52w; + ternary r2 r3.history.entries[5u32].opcode r91.history.entries[5u32].opcode into r123; + ternary r2 r3.history.entries[5u32].op0 r91.history.entries[5u32].op0 into r124; + ternary r2 r3.history.entries[5u32].op1 r91.history.entries[5u32].op1 into r125; + ternary r2 r3.history.entries[5u32].d0 r91.history.entries[5u32].d0 into r126; + cast r123 r124 r125 r126 into r127 as Instruction__Lppf6AZB52w; + ternary r2 r3.history.entries[6u32].opcode r91.history.entries[6u32].opcode into r128; + ternary r2 r3.history.entries[6u32].op0 r91.history.entries[6u32].op0 into r129; + ternary r2 r3.history.entries[6u32].op1 r91.history.entries[6u32].op1 into r130; + ternary r2 r3.history.entries[6u32].d0 r91.history.entries[6u32].d0 into r131; + cast r128 r129 r130 r131 into r132 as Instruction__Lppf6AZB52w; + ternary r2 r3.history.entries[7u32].opcode r91.history.entries[7u32].opcode into r133; + ternary r2 r3.history.entries[7u32].op0 r91.history.entries[7u32].op0 into r134; + ternary r2 r3.history.entries[7u32].op1 r91.history.entries[7u32].op1 into r135; + ternary r2 r3.history.entries[7u32].d0 r91.history.entries[7u32].d0 into r136; + cast r133 r134 r135 r136 into r137 as Instruction__Lppf6AZB52w; + cast r102 r107 r112 r117 r122 r127 r132 r137 into r138 as [Instruction__Lppf6AZB52w; 8u32]; + ternary r2 r3.history.total r91.history.total into r139; + ternary r2 r3.history.head r91.history.head into r140; + cast r139 r140 r138 into r141 as History__Cdcu2iyNy6a; + cast r97 r141 into r142 as Calculator__AeUcVKuTwJT; + is.eq r1[1u32].opcode 0u8 into r143; + cast r142.registers r142.history into r144 as Calculator__AeUcVKuTwJT; + cast 0u32 into r145 as i64; + add r145 1i64 into r146; + neg r146 into r147; + is.eq r1[1u32].op0 r147 into r148; + cast r142.registers.r[0u32] into r149 as i64; + ternary r148 r149 r1[1u32].op0 into r150; + cast 1u32 into r151 as i64; + add r151 1i64 into r152; + neg r152 into r153; + is.eq r1[1u32].op0 r153 into r154; + cast r142.registers.r[1u32] into r155 as i64; + ternary r154 r155 r150 into r156; + cast 2u32 into r157 as i64; + add r157 1i64 into r158; + neg r158 into r159; + is.eq r1[1u32].op0 r159 into r160; + cast r142.registers.r[2u32] into r161 as i64; + ternary r160 r161 r156 into r162; + cast 3u32 into r163 as i64; + add r163 1i64 into r164; + neg r164 into r165; + is.eq r1[1u32].op0 r165 into r166; + cast r142.registers.r[3u32] into r167 as i64; + ternary r166 r167 r162 into r168; + cast r168 into r169 as u32; + cast 0u32 into r170 as i64; + add r170 1i64 into r171; + neg r171 into r172; + is.eq r1[1u32].op1 r172 into r173; + cast r142.registers.r[0u32] into r174 as i64; + ternary r173 r174 r1[1u32].op1 into r175; + cast 1u32 into r176 as i64; + add r176 1i64 into r177; + neg r177 into r178; + is.eq r1[1u32].op1 r178 into r179; + cast r142.registers.r[1u32] into r180 as i64; + ternary r179 r180 r175 into r181; + cast 2u32 into r182 as i64; + add r182 1i64 into r183; + neg r183 into r184; + is.eq r1[1u32].op1 r184 into r185; + cast r142.registers.r[2u32] into r186 as i64; + ternary r185 r186 r181 into r187; + cast 3u32 into r188 as i64; + add r188 1i64 into r189; + neg r189 into r190; + is.eq r1[1u32].op1 r190 into r191; + cast r142.registers.r[3u32] into r192 as i64; + ternary r191 r192 r187 into r193; + cast r193 into r194 as u32; + is.eq r1[1u32].opcode 1u8 into r195; + add r169 r194 into r196; + not r195 into r197; + is.eq r1[1u32].opcode 2u8 into r198; + sub r169 r194 into r199; + not r198 into r200; + is.eq r1[1u32].opcode 3u8 into r201; + mul r169 r194 into r202; + not r201 into r203; + is.eq r1[1u32].opcode 4u8 into r204; + div r169 r194 into r205; + not r204 into r206; + and r197 r200 into r207; + and r207 r203 into r208; + and r208 r206 into r209; + not r209 into r210; + or false r210 into r211; + or r211 r143 into r212; + assert.eq r212 true; + ternary r204 r205 0u32 into r213; + ternary r201 r202 r213 into r214; + ternary r198 r199 r214 into r215; + ternary r195 r196 r215 into r216; + lt r1[1u32].d0 0i64 into r217; + gte r1[1u32].d0 -4i64 into r218; + and r217 r218 into r219; + assert.eq r219 true; + add r1[1u32].d0 1i64 into r220; + cast r220 into r221 as u32; + is.eq r221 0u32 into r222; + ternary r222 r216 r142.registers.r[0u32] into r223; + is.eq r221 1u32 into r224; + ternary r224 r216 r142.registers.r[1u32] into r225; + is.eq r221 2u32 into r226; + ternary r226 r216 r142.registers.r[2u32] into r227; + is.eq r221 3u32 into r228; + ternary r228 r216 r142.registers.r[3u32] into r229; + cast r223 r225 r227 r229 into r230 as [u32; 4u32]; + cast r230 into r231 as Registers__7V67zj5E35T; + cast r231 r142.history into r232 as Calculator__AeUcVKuTwJT; + ternary r143 r144.registers.r[0u32] r232.registers.r[0u32] into r233; + ternary r143 r144.registers.r[1u32] r232.registers.r[1u32] into r234; + ternary r143 r144.registers.r[2u32] r232.registers.r[2u32] into r235; + ternary r143 r144.registers.r[3u32] r232.registers.r[3u32] into r236; + cast r233 r234 r235 r236 into r237 as [u32; 4u32]; + cast r237 into r238 as Registers__7V67zj5E35T; + ternary r143 r144.history.entries[0u32].opcode r232.history.entries[0u32].opcode into r239; + ternary r143 r144.history.entries[0u32].op0 r232.history.entries[0u32].op0 into r240; + ternary r143 r144.history.entries[0u32].op1 r232.history.entries[0u32].op1 into r241; + ternary r143 r144.history.entries[0u32].d0 r232.history.entries[0u32].d0 into r242; + cast r239 r240 r241 r242 into r243 as Instruction__Lppf6AZB52w; + ternary r143 r144.history.entries[1u32].opcode r232.history.entries[1u32].opcode into r244; + ternary r143 r144.history.entries[1u32].op0 r232.history.entries[1u32].op0 into r245; + ternary r143 r144.history.entries[1u32].op1 r232.history.entries[1u32].op1 into r246; + ternary r143 r144.history.entries[1u32].d0 r232.history.entries[1u32].d0 into r247; + cast r244 r245 r246 r247 into r248 as Instruction__Lppf6AZB52w; + ternary r143 r144.history.entries[2u32].opcode r232.history.entries[2u32].opcode into r249; + ternary r143 r144.history.entries[2u32].op0 r232.history.entries[2u32].op0 into r250; + ternary r143 r144.history.entries[2u32].op1 r232.history.entries[2u32].op1 into r251; + ternary r143 r144.history.entries[2u32].d0 r232.history.entries[2u32].d0 into r252; + cast r249 r250 r251 r252 into r253 as Instruction__Lppf6AZB52w; + ternary r143 r144.history.entries[3u32].opcode r232.history.entries[3u32].opcode into r254; + ternary r143 r144.history.entries[3u32].op0 r232.history.entries[3u32].op0 into r255; + ternary r143 r144.history.entries[3u32].op1 r232.history.entries[3u32].op1 into r256; + ternary r143 r144.history.entries[3u32].d0 r232.history.entries[3u32].d0 into r257; + cast r254 r255 r256 r257 into r258 as Instruction__Lppf6AZB52w; + ternary r143 r144.history.entries[4u32].opcode r232.history.entries[4u32].opcode into r259; + ternary r143 r144.history.entries[4u32].op0 r232.history.entries[4u32].op0 into r260; + ternary r143 r144.history.entries[4u32].op1 r232.history.entries[4u32].op1 into r261; + ternary r143 r144.history.entries[4u32].d0 r232.history.entries[4u32].d0 into r262; + cast r259 r260 r261 r262 into r263 as Instruction__Lppf6AZB52w; + ternary r143 r144.history.entries[5u32].opcode r232.history.entries[5u32].opcode into r264; + ternary r143 r144.history.entries[5u32].op0 r232.history.entries[5u32].op0 into r265; + ternary r143 r144.history.entries[5u32].op1 r232.history.entries[5u32].op1 into r266; + ternary r143 r144.history.entries[5u32].d0 r232.history.entries[5u32].d0 into r267; + cast r264 r265 r266 r267 into r268 as Instruction__Lppf6AZB52w; + ternary r143 r144.history.entries[6u32].opcode r232.history.entries[6u32].opcode into r269; + ternary r143 r144.history.entries[6u32].op0 r232.history.entries[6u32].op0 into r270; + ternary r143 r144.history.entries[6u32].op1 r232.history.entries[6u32].op1 into r271; + ternary r143 r144.history.entries[6u32].d0 r232.history.entries[6u32].d0 into r272; + cast r269 r270 r271 r272 into r273 as Instruction__Lppf6AZB52w; + ternary r143 r144.history.entries[7u32].opcode r232.history.entries[7u32].opcode into r274; + ternary r143 r144.history.entries[7u32].op0 r232.history.entries[7u32].op0 into r275; + ternary r143 r144.history.entries[7u32].op1 r232.history.entries[7u32].op1 into r276; + ternary r143 r144.history.entries[7u32].d0 r232.history.entries[7u32].d0 into r277; + cast r274 r275 r276 r277 into r278 as Instruction__Lppf6AZB52w; + cast r243 r248 r253 r258 r263 r268 r273 r278 into r279 as [Instruction__Lppf6AZB52w; 8u32]; + ternary r143 r144.history.total r232.history.total into r280; + ternary r143 r144.history.head r232.history.head into r281; + cast r280 r281 r279 into r282 as History__Cdcu2iyNy6a; + cast r238 r282 into r283 as Calculator__AeUcVKuTwJT; + is.eq r1[2u32].opcode 0u8 into r284; + cast r283.registers r283.history into r285 as Calculator__AeUcVKuTwJT; + cast 0u32 into r286 as i64; + add r286 1i64 into r287; + neg r287 into r288; + is.eq r1[2u32].op0 r288 into r289; + cast r283.registers.r[0u32] into r290 as i64; + ternary r289 r290 r1[2u32].op0 into r291; + cast 1u32 into r292 as i64; + add r292 1i64 into r293; + neg r293 into r294; + is.eq r1[2u32].op0 r294 into r295; + cast r283.registers.r[1u32] into r296 as i64; + ternary r295 r296 r291 into r297; + cast 2u32 into r298 as i64; + add r298 1i64 into r299; + neg r299 into r300; + is.eq r1[2u32].op0 r300 into r301; + cast r283.registers.r[2u32] into r302 as i64; + ternary r301 r302 r297 into r303; + cast 3u32 into r304 as i64; + add r304 1i64 into r305; + neg r305 into r306; + is.eq r1[2u32].op0 r306 into r307; + cast r283.registers.r[3u32] into r308 as i64; + ternary r307 r308 r303 into r309; + cast r309 into r310 as u32; + cast 0u32 into r311 as i64; + add r311 1i64 into r312; + neg r312 into r313; + is.eq r1[2u32].op1 r313 into r314; + cast r283.registers.r[0u32] into r315 as i64; + ternary r314 r315 r1[2u32].op1 into r316; + cast 1u32 into r317 as i64; + add r317 1i64 into r318; + neg r318 into r319; + is.eq r1[2u32].op1 r319 into r320; + cast r283.registers.r[1u32] into r321 as i64; + ternary r320 r321 r316 into r322; + cast 2u32 into r323 as i64; + add r323 1i64 into r324; + neg r324 into r325; + is.eq r1[2u32].op1 r325 into r326; + cast r283.registers.r[2u32] into r327 as i64; + ternary r326 r327 r322 into r328; + cast 3u32 into r329 as i64; + add r329 1i64 into r330; + neg r330 into r331; + is.eq r1[2u32].op1 r331 into r332; + cast r283.registers.r[3u32] into r333 as i64; + ternary r332 r333 r328 into r334; + cast r334 into r335 as u32; + is.eq r1[2u32].opcode 1u8 into r336; + add r310 r335 into r337; + not r336 into r338; + is.eq r1[2u32].opcode 2u8 into r339; + sub r310 r335 into r340; + not r339 into r341; + is.eq r1[2u32].opcode 3u8 into r342; + mul r310 r335 into r343; + not r342 into r344; + is.eq r1[2u32].opcode 4u8 into r345; + div r310 r335 into r346; + not r345 into r347; + and r338 r341 into r348; + and r348 r344 into r349; + and r349 r347 into r350; + not r350 into r351; + or false r351 into r352; + or r352 r284 into r353; + assert.eq r353 true; + ternary r345 r346 0u32 into r354; + ternary r342 r343 r354 into r355; + ternary r339 r340 r355 into r356; + ternary r336 r337 r356 into r357; + lt r1[2u32].d0 0i64 into r358; + gte r1[2u32].d0 -4i64 into r359; + and r358 r359 into r360; + assert.eq r360 true; + add r1[2u32].d0 1i64 into r361; + cast r361 into r362 as u32; + is.eq r362 0u32 into r363; + ternary r363 r357 r283.registers.r[0u32] into r364; + is.eq r362 1u32 into r365; + ternary r365 r357 r283.registers.r[1u32] into r366; + is.eq r362 2u32 into r367; + ternary r367 r357 r283.registers.r[2u32] into r368; + is.eq r362 3u32 into r369; + ternary r369 r357 r283.registers.r[3u32] into r370; + cast r364 r366 r368 r370 into r371 as [u32; 4u32]; + cast r371 into r372 as Registers__7V67zj5E35T; + cast r372 r283.history into r373 as Calculator__AeUcVKuTwJT; + ternary r284 r285.registers.r[0u32] r373.registers.r[0u32] into r374; + ternary r284 r285.registers.r[1u32] r373.registers.r[1u32] into r375; + ternary r284 r285.registers.r[2u32] r373.registers.r[2u32] into r376; + ternary r284 r285.registers.r[3u32] r373.registers.r[3u32] into r377; + cast r374 r375 r376 r377 into r378 as [u32; 4u32]; + cast r378 into r379 as Registers__7V67zj5E35T; + ternary r284 r285.history.entries[0u32].opcode r373.history.entries[0u32].opcode into r380; + ternary r284 r285.history.entries[0u32].op0 r373.history.entries[0u32].op0 into r381; + ternary r284 r285.history.entries[0u32].op1 r373.history.entries[0u32].op1 into r382; + ternary r284 r285.history.entries[0u32].d0 r373.history.entries[0u32].d0 into r383; + cast r380 r381 r382 r383 into r384 as Instruction__Lppf6AZB52w; + ternary r284 r285.history.entries[1u32].opcode r373.history.entries[1u32].opcode into r385; + ternary r284 r285.history.entries[1u32].op0 r373.history.entries[1u32].op0 into r386; + ternary r284 r285.history.entries[1u32].op1 r373.history.entries[1u32].op1 into r387; + ternary r284 r285.history.entries[1u32].d0 r373.history.entries[1u32].d0 into r388; + cast r385 r386 r387 r388 into r389 as Instruction__Lppf6AZB52w; + ternary r284 r285.history.entries[2u32].opcode r373.history.entries[2u32].opcode into r390; + ternary r284 r285.history.entries[2u32].op0 r373.history.entries[2u32].op0 into r391; + ternary r284 r285.history.entries[2u32].op1 r373.history.entries[2u32].op1 into r392; + ternary r284 r285.history.entries[2u32].d0 r373.history.entries[2u32].d0 into r393; + cast r390 r391 r392 r393 into r394 as Instruction__Lppf6AZB52w; + ternary r284 r285.history.entries[3u32].opcode r373.history.entries[3u32].opcode into r395; + ternary r284 r285.history.entries[3u32].op0 r373.history.entries[3u32].op0 into r396; + ternary r284 r285.history.entries[3u32].op1 r373.history.entries[3u32].op1 into r397; + ternary r284 r285.history.entries[3u32].d0 r373.history.entries[3u32].d0 into r398; + cast r395 r396 r397 r398 into r399 as Instruction__Lppf6AZB52w; + ternary r284 r285.history.entries[4u32].opcode r373.history.entries[4u32].opcode into r400; + ternary r284 r285.history.entries[4u32].op0 r373.history.entries[4u32].op0 into r401; + ternary r284 r285.history.entries[4u32].op1 r373.history.entries[4u32].op1 into r402; + ternary r284 r285.history.entries[4u32].d0 r373.history.entries[4u32].d0 into r403; + cast r400 r401 r402 r403 into r404 as Instruction__Lppf6AZB52w; + ternary r284 r285.history.entries[5u32].opcode r373.history.entries[5u32].opcode into r405; + ternary r284 r285.history.entries[5u32].op0 r373.history.entries[5u32].op0 into r406; + ternary r284 r285.history.entries[5u32].op1 r373.history.entries[5u32].op1 into r407; + ternary r284 r285.history.entries[5u32].d0 r373.history.entries[5u32].d0 into r408; + cast r405 r406 r407 r408 into r409 as Instruction__Lppf6AZB52w; + ternary r284 r285.history.entries[6u32].opcode r373.history.entries[6u32].opcode into r410; + ternary r284 r285.history.entries[6u32].op0 r373.history.entries[6u32].op0 into r411; + ternary r284 r285.history.entries[6u32].op1 r373.history.entries[6u32].op1 into r412; + ternary r284 r285.history.entries[6u32].d0 r373.history.entries[6u32].d0 into r413; + cast r410 r411 r412 r413 into r414 as Instruction__Lppf6AZB52w; + ternary r284 r285.history.entries[7u32].opcode r373.history.entries[7u32].opcode into r415; + ternary r284 r285.history.entries[7u32].op0 r373.history.entries[7u32].op0 into r416; + ternary r284 r285.history.entries[7u32].op1 r373.history.entries[7u32].op1 into r417; + ternary r284 r285.history.entries[7u32].d0 r373.history.entries[7u32].d0 into r418; + cast r415 r416 r417 r418 into r419 as Instruction__Lppf6AZB52w; + cast r384 r389 r394 r399 r404 r409 r414 r419 into r420 as [Instruction__Lppf6AZB52w; 8u32]; + ternary r284 r285.history.total r373.history.total into r421; + ternary r284 r285.history.head r373.history.head into r422; + cast r421 r422 r420 into r423 as History__Cdcu2iyNy6a; + cast r379 r423 into r424 as Calculator__AeUcVKuTwJT; + is.eq r1[3u32].opcode 0u8 into r425; + cast r424.registers r424.history into r426 as Calculator__AeUcVKuTwJT; + cast 0u32 into r427 as i64; + add r427 1i64 into r428; + neg r428 into r429; + is.eq r1[3u32].op0 r429 into r430; + cast r424.registers.r[0u32] into r431 as i64; + ternary r430 r431 r1[3u32].op0 into r432; + cast 1u32 into r433 as i64; + add r433 1i64 into r434; + neg r434 into r435; + is.eq r1[3u32].op0 r435 into r436; + cast r424.registers.r[1u32] into r437 as i64; + ternary r436 r437 r432 into r438; + cast 2u32 into r439 as i64; + add r439 1i64 into r440; + neg r440 into r441; + is.eq r1[3u32].op0 r441 into r442; + cast r424.registers.r[2u32] into r443 as i64; + ternary r442 r443 r438 into r444; + cast 3u32 into r445 as i64; + add r445 1i64 into r446; + neg r446 into r447; + is.eq r1[3u32].op0 r447 into r448; + cast r424.registers.r[3u32] into r449 as i64; + ternary r448 r449 r444 into r450; + cast r450 into r451 as u32; + cast 0u32 into r452 as i64; + add r452 1i64 into r453; + neg r453 into r454; + is.eq r1[3u32].op1 r454 into r455; + cast r424.registers.r[0u32] into r456 as i64; + ternary r455 r456 r1[3u32].op1 into r457; + cast 1u32 into r458 as i64; + add r458 1i64 into r459; + neg r459 into r460; + is.eq r1[3u32].op1 r460 into r461; + cast r424.registers.r[1u32] into r462 as i64; + ternary r461 r462 r457 into r463; + cast 2u32 into r464 as i64; + add r464 1i64 into r465; + neg r465 into r466; + is.eq r1[3u32].op1 r466 into r467; + cast r424.registers.r[2u32] into r468 as i64; + ternary r467 r468 r463 into r469; + cast 3u32 into r470 as i64; + add r470 1i64 into r471; + neg r471 into r472; + is.eq r1[3u32].op1 r472 into r473; + cast r424.registers.r[3u32] into r474 as i64; + ternary r473 r474 r469 into r475; + cast r475 into r476 as u32; + is.eq r1[3u32].opcode 1u8 into r477; + add r451 r476 into r478; + not r477 into r479; + is.eq r1[3u32].opcode 2u8 into r480; + sub r451 r476 into r481; + not r480 into r482; + is.eq r1[3u32].opcode 3u8 into r483; + mul r451 r476 into r484; + not r483 into r485; + is.eq r1[3u32].opcode 4u8 into r486; + div r451 r476 into r487; + not r486 into r488; + and r479 r482 into r489; + and r489 r485 into r490; + and r490 r488 into r491; + not r491 into r492; + or false r492 into r493; + or r493 r425 into r494; + assert.eq r494 true; + ternary r486 r487 0u32 into r495; + ternary r483 r484 r495 into r496; + ternary r480 r481 r496 into r497; + ternary r477 r478 r497 into r498; + lt r1[3u32].d0 0i64 into r499; + gte r1[3u32].d0 -4i64 into r500; + and r499 r500 into r501; + assert.eq r501 true; + add r1[3u32].d0 1i64 into r502; + cast r502 into r503 as u32; + is.eq r503 0u32 into r504; + ternary r504 r498 r424.registers.r[0u32] into r505; + is.eq r503 1u32 into r506; + ternary r506 r498 r424.registers.r[1u32] into r507; + is.eq r503 2u32 into r508; + ternary r508 r498 r424.registers.r[2u32] into r509; + is.eq r503 3u32 into r510; + ternary r510 r498 r424.registers.r[3u32] into r511; + cast r505 r507 r509 r511 into r512 as [u32; 4u32]; + cast r512 into r513 as Registers__7V67zj5E35T; + cast r513 r424.history into r514 as Calculator__AeUcVKuTwJT; + ternary r425 r426.registers.r[0u32] r514.registers.r[0u32] into r515; + ternary r425 r426.registers.r[1u32] r514.registers.r[1u32] into r516; + ternary r425 r426.registers.r[2u32] r514.registers.r[2u32] into r517; + ternary r425 r426.registers.r[3u32] r514.registers.r[3u32] into r518; + cast r515 r516 r517 r518 into r519 as [u32; 4u32]; + cast r519 into r520 as Registers__7V67zj5E35T; + ternary r425 r426.history.entries[0u32].opcode r514.history.entries[0u32].opcode into r521; + ternary r425 r426.history.entries[0u32].op0 r514.history.entries[0u32].op0 into r522; + ternary r425 r426.history.entries[0u32].op1 r514.history.entries[0u32].op1 into r523; + ternary r425 r426.history.entries[0u32].d0 r514.history.entries[0u32].d0 into r524; + cast r521 r522 r523 r524 into r525 as Instruction__Lppf6AZB52w; + ternary r425 r426.history.entries[1u32].opcode r514.history.entries[1u32].opcode into r526; + ternary r425 r426.history.entries[1u32].op0 r514.history.entries[1u32].op0 into r527; + ternary r425 r426.history.entries[1u32].op1 r514.history.entries[1u32].op1 into r528; + ternary r425 r426.history.entries[1u32].d0 r514.history.entries[1u32].d0 into r529; + cast r526 r527 r528 r529 into r530 as Instruction__Lppf6AZB52w; + ternary r425 r426.history.entries[2u32].opcode r514.history.entries[2u32].opcode into r531; + ternary r425 r426.history.entries[2u32].op0 r514.history.entries[2u32].op0 into r532; + ternary r425 r426.history.entries[2u32].op1 r514.history.entries[2u32].op1 into r533; + ternary r425 r426.history.entries[2u32].d0 r514.history.entries[2u32].d0 into r534; + cast r531 r532 r533 r534 into r535 as Instruction__Lppf6AZB52w; + ternary r425 r426.history.entries[3u32].opcode r514.history.entries[3u32].opcode into r536; + ternary r425 r426.history.entries[3u32].op0 r514.history.entries[3u32].op0 into r537; + ternary r425 r426.history.entries[3u32].op1 r514.history.entries[3u32].op1 into r538; + ternary r425 r426.history.entries[3u32].d0 r514.history.entries[3u32].d0 into r539; + cast r536 r537 r538 r539 into r540 as Instruction__Lppf6AZB52w; + ternary r425 r426.history.entries[4u32].opcode r514.history.entries[4u32].opcode into r541; + ternary r425 r426.history.entries[4u32].op0 r514.history.entries[4u32].op0 into r542; + ternary r425 r426.history.entries[4u32].op1 r514.history.entries[4u32].op1 into r543; + ternary r425 r426.history.entries[4u32].d0 r514.history.entries[4u32].d0 into r544; + cast r541 r542 r543 r544 into r545 as Instruction__Lppf6AZB52w; + ternary r425 r426.history.entries[5u32].opcode r514.history.entries[5u32].opcode into r546; + ternary r425 r426.history.entries[5u32].op0 r514.history.entries[5u32].op0 into r547; + ternary r425 r426.history.entries[5u32].op1 r514.history.entries[5u32].op1 into r548; + ternary r425 r426.history.entries[5u32].d0 r514.history.entries[5u32].d0 into r549; + cast r546 r547 r548 r549 into r550 as Instruction__Lppf6AZB52w; + ternary r425 r426.history.entries[6u32].opcode r514.history.entries[6u32].opcode into r551; + ternary r425 r426.history.entries[6u32].op0 r514.history.entries[6u32].op0 into r552; + ternary r425 r426.history.entries[6u32].op1 r514.history.entries[6u32].op1 into r553; + ternary r425 r426.history.entries[6u32].d0 r514.history.entries[6u32].d0 into r554; + cast r551 r552 r553 r554 into r555 as Instruction__Lppf6AZB52w; + ternary r425 r426.history.entries[7u32].opcode r514.history.entries[7u32].opcode into r556; + ternary r425 r426.history.entries[7u32].op0 r514.history.entries[7u32].op0 into r557; + ternary r425 r426.history.entries[7u32].op1 r514.history.entries[7u32].op1 into r558; + ternary r425 r426.history.entries[7u32].d0 r514.history.entries[7u32].d0 into r559; + cast r556 r557 r558 r559 into r560 as Instruction__Lppf6AZB52w; + cast r525 r530 r535 r540 r545 r550 r555 r560 into r561 as [Instruction__Lppf6AZB52w; 8u32]; + ternary r425 r426.history.total r514.history.total into r562; + ternary r425 r426.history.head r514.history.head into r563; + cast r562 r563 r561 into r564 as History__Cdcu2iyNy6a; + cast r520 r564 into r565 as Calculator__AeUcVKuTwJT; + output r565 as Calculator__AeUcVKuTwJT.private; + +function transcript: + input r0 as Calculator__AeUcVKuTwJT.private; + is.eq 0u8 0u8 into r1; + is.eq 0u8 1u8 into r2; + or r1 r2 into r3; + is.eq 0u8 2u8 into r4; + or r3 r4 into r5; + is.eq 0u8 3u8 into r6; + or r5 r6 into r7; + is.eq 0u8 4u8 into r8; + or r7 r8 into r9; + assert.eq r9 true; + gte 0i64 -32i64 into r10; + assert.eq r10 true; + gte 0i64 -32i64 into r11; + assert.eq r11 true; + lt 0i64 0i64 into r12; + gte 0i64 -32i64 into r13; + and r12 r13 into r14; + assert.eq r14 true; + cast r0.history.entries[7u32] r0.history.entries[0u32] r0.history.entries[1u32] r0.history.entries[2u32] r0.history.entries[3u32] r0.history.entries[4u32] r0.history.entries[5u32] r0.history.entries[6u32] into r15 as [Instruction__Lppf6AZB52w; 8u32]; + cast r0.history.total r15 into r16 as Transcript__5ydsl2cgxYJ; + output r16 as Transcript__5ydsl2cgxYJ.private; + +constructor: + assert.eq edition 0u16; diff --git a/calculator/build/program.json b/calculator/build/program.json new file mode 100644 index 0000000..a876417 --- /dev/null +++ b/calculator/build/program.json @@ -0,0 +1,9 @@ +{ + "program": "calculator.aleo", + "version": "0.1.0", + "description": "", + "license": "", + "leo": "3.1.0", + "dependencies": null, + "dev_dependencies": null +} diff --git a/calculator/program.json b/calculator/program.json new file mode 100644 index 0000000..08f051e --- /dev/null +++ b/calculator/program.json @@ -0,0 +1,8 @@ +{ + "program": "calculator.aleo", + "version": "0.1.0", + "description": "", + "license": "MIT", + "dependencies": null, + "dev_dependencies": null +} diff --git a/calculator/src/calculator.leo b/calculator/src/calculator.leo new file mode 100644 index 0000000..536097b --- /dev/null +++ b/calculator/src/calculator.leo @@ -0,0 +1,67 @@ +// A programmable calculator. +struct Calculator::[N: u32] { + // The registers. + registers: registers::Registers::[N], + // The history. + // TODO: Make history longer. + history: history::History::[2 * N], +} + +// Initialize the calculator. +inline init::[N: u32]() -> Calculator::[N] { + return Calculator::[N] { + registers: registers::init::[N](), + history: history::init::[2 * N]() + }; +} + +// Executes a sequence of instructions. +inline execute::[N: u32]( + c: Calculator::[N], + instructions: [history::instruction::Instruction; N] +) -> Calculator::[N] { + for i in 0u32..N { + c = exec::[N](c, instructions[i]); + } + return c; +} + +// Returns a transcript of the history. +inline transcript::[N: u32](c: Calculator::[N]) -> history::Transcript::[2 * N] { + return history::transcript::[2 * N](c.history); +} + +// Executes a single instruction. +inline exec::[N: u32]( + c: Calculator::[N], + i: history::instruction::Instruction, +) -> Calculator::[N] { + // Handle NOOP. + if i.opcode == history::instruction::opcodes::NOOP { + return c; + } + + // Load the operands. + let op0 = registers::load::[N](c.registers, i.op0); + let op1 = registers::load::[N](c.registers, i.op1); + + // Evaluate the operands. + let result = 0u32; + if i.opcode == history::instruction::opcodes::ADD { + result = math::add(op0, op1); + } else if i.opcode == history::instruction::opcodes::SUB { + result = math::sub(op0, op1); + } else if i.opcode == history::instruction::opcodes::MUL { + result = math::mul(op0, op1); + } else if i.opcode == history::instruction::opcodes::DIV { + result = math::div(op0, op1); + } else { + assert(false); + } + + // Store the result. + c.registers = registers::store::[N](c.registers, i.d0, result); + + // Return the updated calculator. + return c; +} diff --git a/calculator/src/calculator/history.leo b/calculator/src/calculator/history.leo new file mode 100644 index 0000000..1fbd20e --- /dev/null +++ b/calculator/src/calculator/history.leo @@ -0,0 +1,55 @@ +// A finite history of past instructions. +struct History::[N: u32] { + // The total number of instructions. + total: u32, + // The head of the buffer. + head: u32, + // The entries. + entries: [instruction::Instruction; N], +} + +// A transcript of the history in order from newest to oldest. +struct Transcript::[N: u32] { + // The total number of instructions. + total: u32, + // The entries in order. + entries: [instruction::Instruction; N] +} + +// Initializes a `History` object. +inline init::[N: u32]() -> History::[N] { + return History::[N] { + total: 0, + head: 0, + entries: [instruction::noop(); N], + }; +} + +// Adds an instruction to the history. +inline push::[N: u32](history: History::[N], instruction: instruction::Instruction) -> History::[N] { + // Add the instruction. + history.entries[history.head] = instruction; + // Increment the total. + history.total += 1; + // Increment the head. + history.head = history.head.add_wrapped(1) % N; + // Return the updated history. + return history; +} + +// Returns the transcript. +inline transcript::[N: u32](history: History::[N]) -> Transcript::[N] { + // Initialize dummy entries. + let entries = [instruction::noop(); N]; + // Update the entries. + for i in 0u32..N { + entries[i] = history.entries[i.sub_wrapped(1) % N]; + } + // Return the transcript. + return Transcript::[N] { + total: history.total, + entries + }; + +} + diff --git a/calculator/src/calculator/history/instruction.leo b/calculator/src/calculator/history/instruction.leo new file mode 100644 index 0000000..2964033 --- /dev/null +++ b/calculator/src/calculator/history/instruction.leo @@ -0,0 +1,67 @@ +// An instruction to execute on the calculator. +// Note: Negative values indicate a regsiter. +// There are 32 valid registers. (-1, ..., -32) +struct Instruction { + opcode: u8, + // An operand. + op0: i64, + // An operand. + op1: i64, + // A destination register. + d0: i64, +} + +// Creates an instruction. +inline init(opcode: u8, op0: i64, op1: i64, d0: i64) -> Instruction { + assert(opcodes::opcode_is_valid(opcode)); + assert(operand_is_valid(op0)); + assert(operand_is_valid(op1)); + assert(destination_is_valid(d0)); + return Instruction { + opcode, + op0, + op1, + d0 + }; +} + +// Createa a `NOOP` instruction. +inline noop() -> Instruction { + return init(opcodes::NOOP, 0, 0, 0); +} + +// Creates a `ADD` instruction. +inline add(r0: i64, r1: i64, d0: i64) -> Instruction { + return init(opcodes::ADD, r0, r1, d0); +} + +// Creates a `SUB` instruction. +inline sub(r0: i64, r1: i64, d0: i64) -> Instruction { + return init(opcodes::SUB, r0, r1, d0); +} + +// Creates a `MUL` instruction. +inline mul(r0: i64, r1: i64, d0: i64) -> Instruction { + return init(opcodes::MUL, r0, r1, d0); +} + +// Creates a `DIV` instruction. +inline div(r0: i64, r1: i64, d0: i64) -> Instruction { + return init(opcodes::DIV, r0, r1, d0); +} + + +// Returns whether an operand is valid. +inline operand_is_valid(op: i64) -> bool { + return op >= -32i64; +} + +// Returns whether a destination register is valid. +inline destination_is_valid(d: i64) -> bool { + return d < 0 && d >= -32i64; +} + + + + + diff --git a/calculator/src/calculator/history/instruction/opcodes.leo b/calculator/src/calculator/history/instruction/opcodes.leo new file mode 100644 index 0000000..11c4a98 --- /dev/null +++ b/calculator/src/calculator/history/instruction/opcodes.leo @@ -0,0 +1,26 @@ +// NOOP +const NOOP: u8 = 0; + +// ADD +const ADD: u8 = 1; + +// SUB +const SUB: u8 = 2; + +// MUL +const MUL: u8 = 3; + +// DIV +const DIV: u8 = 4; + +// Returns whether an opcode is valid. +inline opcode_is_valid(opcode: u8) -> bool { + return opcode == 0u8 + || opcode == 1u8 + || opcode == 2u8 + || opcode == 3u8 + || opcode == 4u8; + +} + + diff --git a/calculator/src/calculator/math.leo b/calculator/src/calculator/math.leo new file mode 100644 index 0000000..5312a42 --- /dev/null +++ b/calculator/src/calculator/math.leo @@ -0,0 +1,24 @@ +// Implements addition. +inline add(op0: u32, op1: u32) -> u32 { + return op0 + op1; +} + +// Implements subtraction. +inline sub(op0: u32, op1: u32) -> u32 { + return op0 - op1; +} + +// Implements multiplication. +inline mul(op0: u32, op1: u32) -> u32 { + return op0 * op1; +} + +// Implements division. +inline div(op0: u32, op1: u32) -> u32 { + return op0 / op1; +} + + + + + diff --git a/calculator/src/calculator/registers.leo b/calculator/src/calculator/registers.leo new file mode 100644 index 0000000..d23d84c --- /dev/null +++ b/calculator/src/calculator/registers.leo @@ -0,0 +1,52 @@ +// A register file. +struct Registers::[N: u32] { + r: [u32; N], +} + +// Initializes a register file. +inline init::[N: u32]() -> Registers::[N] { + return Registers::[N] { + r: [0u32; N], + }; +} + +// Loads an operand. +inline load::[N: u32](registers: Registers::[N], op: i64) -> u32 { + // Initialize the result. + let result = op; + // Iterate through the registers and check for a match. + for i in 0u32..N { + let id: i64 = index_to_id(i); + if op == id { + result = registers.r[i] as i64; + } + } + // Cast the result to a `u32`` and return it. + return (result as u32); +} + +// Stores a value into a register. +inline store::[N: u32](registers: Registers::[N], d: i64, v: u32) -> Registers::[N] { + // Get the register index. + let index = id_to_index::[N](d); + // Iterate through the registers and set the appropriate one. + for i in 0u32..N { + if index == i { + registers.r[i] = v; + } + } + // Return the updated registers. + return registers; +} + + +// Convert a register index into its ID. +inline index_to_id(i: u32) -> i64 { + return -(i as i64 + 1); +} + +// Convert a register ID into an index, checking for validity. +inline id_to_index::[N: u32](id: i64) -> u32 { + assert(id < 0 && id >= -(N as i64)); + return (id + 1) as u32; +} diff --git a/calculator/src/main.leo b/calculator/src/main.leo new file mode 100644 index 0000000..e258afd --- /dev/null +++ b/calculator/src/main.leo @@ -0,0 +1,25 @@ +// The 'calculator' program. +program calculator.aleo { + @noupgrade + async constructor() {} + + const SIZE: u32 = 4; + + transition init() -> calculator::Calculator::[SIZE] { + return calculator::init::[SIZE](); + } + + transition execute( + c: calculator::Calculator::[SIZE], + instructions: [calculator::history::instruction::Instruction; SIZE], + ) -> calculator::Calculator::[SIZE] { + return calculator::execute::[SIZE](c, instructions); + } + + transition transcript( + c: calculator::Calculator::[SIZE] + ) -> calculator::history::Transcript::[2 * SIZE] { + return calculator::transcript::[SIZE](c); + } + +} diff --git a/calculator/tests/test_modules.leo b/calculator/tests/test_modules.leo new file mode 100644 index 0000000..ed34f39 --- /dev/null +++ b/calculator/tests/test_modules.leo @@ -0,0 +1,18 @@ +import calculator.aleo; +program test_calculcator.aleo { + @test + script test_it() { + let result: u32 = calculator.aleo/main(1u32, 2u32); + assert_eq(result, 3u32); + } + + @test + @should_fail + transition do_nothing() { + let result: u32 = calculator.aleo/main(2u32, 3u32); + assert_eq(result, 3u32); + } + + @noupgrade + async constructor() {} +}