From 75572c6a2c8d17fe53421ec11d92d8cc5670208c Mon Sep 17 00:00:00 2001 From: Edward Chen Date: Thu, 20 Jan 2022 13:16:27 -0500 Subject: [PATCH] C Frontend (#22) --- Cargo.lock | 7 + Cargo.toml | 1 + Makefile | 18 +- examples/C/mpc/2pc_millionaires.c | 8 + examples/C/mpc/benchmarks/2pc_biomatch.c | 38 + examples/C/mpc/benchmarks/2pc_kmeans.c | 202 +++++ examples/C/mpc/ilp_benchmarks/2pc_ilp_bench.c | 12 + .../C/mpc/ilp_benchmarks/2pc_ilp_bench_1.c | 12 + .../C/mpc/ilp_benchmarks/2pc_ilp_bench_2.c | 12 + .../C/mpc/ilp_benchmarks/2pc_ilp_bench_3.c | 12 + .../C/mpc/ilp_benchmarks/2pc_ilp_bench_4.c | 12 + .../C/mpc/ilp_benchmarks/2pc_ilp_bench_5.c | 12 + .../C/mpc/ilp_benchmarks/2pc_ilp_bench_6.c | 12 + .../C/mpc/ilp_benchmarks/2pc_ilp_bench_7.c | 12 + .../C/mpc/ilp_benchmarks/2pc_ilp_bench_8.c | 12 + .../C/mpc/ilp_benchmarks/2pc_ilp_bench_9.c | 12 + .../mpc/unit_tests/arithmetic_tests/2pc_add.c | 3 + .../arithmetic_tests/2pc_add_unsigned.c | 3 + .../arithmetic_tests/2pc_int_equals.c | 5 + .../arithmetic_tests/2pc_int_greater_equals.c | 5 + .../arithmetic_tests/2pc_int_greater_than.c | 5 + .../arithmetic_tests/2pc_int_less_equals.c | 5 + .../arithmetic_tests/2pc_int_less_than.c | 5 + .../arithmetic_tests/2pc_loop_add.c | 7 + .../mpc/unit_tests/arithmetic_tests/2pc_mod.c | 3 + .../unit_tests/arithmetic_tests/2pc_mult.c | 3 + .../arithmetic_tests/2pc_mult_add_pub.c | 3 + .../mpc/unit_tests/arithmetic_tests/2pc_sub.c | 3 + .../unit_tests/array_tests/2pc_array_index.c | 5 + .../array_tests/2pc_array_index_2.c | 8 + .../unit_tests/array_tests/2pc_array_ret.c | 3 + .../unit_tests/array_tests/2pc_array_sum.c | 4 + .../bitwise_tests/2pc_bitwise_and.c | 3 + .../unit_tests/bitwise_tests/2pc_bitwise_or.c | 3 + .../bitwise_tests/2pc_bitwise_xor.c | 3 + .../boolean_tests/2pc_boolean_and.c | 5 + .../boolean_tests/2pc_boolean_equals.c | 5 + .../unit_tests/boolean_tests/2pc_boolean_or.c | 5 + .../mpc/unit_tests/c_array_tests/2pc_array.c | 6 + .../unit_tests/c_array_tests/2pc_array_1.c | 7 + .../unit_tests/c_array_tests/2pc_array_2.c | 8 + .../unit_tests/c_array_tests/2pc_array_3.c | 7 + .../c_array_tests/2pc_array_sum_c.c | 11 + .../unit_tests/const_tests/2pc_const_arith.c | 4 + .../unit_tests/const_tests/2pc_const_bool.c | 6 + examples/C/mpc/unit_tests/div_tests/2pc_div.c | 3 + .../unit_tests/ite_tests/2pc_ite_only_if.c | 8 + .../unit_tests/ite_tests/2pc_ite_ret_bool.c | 9 + .../unit_tests/ite_tests/2pc_ite_ret_int.c | 9 + .../2pc_nary_arithmetic_add.c | 3 + .../nary_boolean_tests/2pc_nary_boolean_and.c | 5 + .../C/mpc/unit_tests/shift_tests/2pc_lhs.c | 3 + .../C/mpc/unit_tests/shift_tests/2pc_rhs.c | 3 + examples/C/r1cs/add.c | 6 + .../mpc/array_tests/2pc_array_ret.zok | 2 - .../mpc/array_tests/2pc_array_sum.zok | 3 - .../mpc/function_tests/2pc_function_sum.zok | 5 - .../ZoKrates/mpc/hycc_benchmarks/biomatch.zok | 5 - .../unit_tests/arithmetic_tests/2pc_add.zok | 2 +- examples/circ.rs | 63 +- examples/opa_bench.rs | 2 +- output1.txt | 351 ++++++++ output2.txt | 351 ++++++++ scripts/aby_tests/c_bench_aby.py | 15 + scripts/aby_tests/c_test_aby.py | 25 + scripts/aby_tests/test_suite.py | 797 ++++++++++++++++++ scripts/aby_tests/utils.py | 107 +++ scripts/aby_tests/zokrates_test_aby.py | 24 + scripts/build_mpc_c_test.zsh | 105 +++ scripts/build_mpc_zokrates_test.zsh | 13 +- scripts/build_r1cs_c_test.zsh | 26 + scripts/test_aby.py | 640 -------------- src/circify/mem.rs | 141 ++-- src/circify/mod.rs | 27 +- src/front/c/ast_utils.rs | 158 ++++ src/front/c/mod.rs | 620 ++++++++++++++ src/front/c/parser.rs | 49 ++ src/front/c/term.rs | 588 +++++++++++++ src/front/c/types.rs | 114 +++ src/front/mod.rs | 28 + src/front/zokrates/mod.rs | 32 +- src/ir/opt/binarize.rs | 121 +++ src/ir/opt/cfold.rs | 4 + src/ir/opt/mem/visit.rs | 0 src/ir/opt/mod.rs | 9 + src/target/aby/assignment/ilp.rs | 135 +-- src/target/aby/mod.rs | 30 +- src/target/aby/output.rs | 52 +- src/target/aby/trans.rs | 499 ++++++----- src/target/aby/utils.rs | 41 + third_party/ABY_templates/test_template.txt | 32 +- third_party/EZPC/ezpc.h | 191 +++++ .../ZoKrates/zokrates_parser/Cargo.lock | 189 +++++ third_party/hycc/README.md | 3 + third_party/hycc/adapted_costs.json | 264 ++++++ third_party/hycc/original_costs.json | 212 +++++ third_party/opa/README.md | 2 +- third_party/opa/adapted_costs.json | 181 ++++ ...{sample_costs.json => original_costs.json} | 1 - 99 files changed, 5712 insertions(+), 1133 deletions(-) create mode 100644 examples/C/mpc/2pc_millionaires.c create mode 100644 examples/C/mpc/benchmarks/2pc_biomatch.c create mode 100644 examples/C/mpc/benchmarks/2pc_kmeans.c create mode 100644 examples/C/mpc/ilp_benchmarks/2pc_ilp_bench.c create mode 100644 examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_1.c create mode 100644 examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_2.c create mode 100644 examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_3.c create mode 100644 examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_4.c create mode 100644 examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_5.c create mode 100644 examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_6.c create mode 100644 examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_7.c create mode 100644 examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_8.c create mode 100644 examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_9.c create mode 100644 examples/C/mpc/unit_tests/arithmetic_tests/2pc_add.c create mode 100644 examples/C/mpc/unit_tests/arithmetic_tests/2pc_add_unsigned.c create mode 100644 examples/C/mpc/unit_tests/arithmetic_tests/2pc_int_equals.c create mode 100644 examples/C/mpc/unit_tests/arithmetic_tests/2pc_int_greater_equals.c create mode 100644 examples/C/mpc/unit_tests/arithmetic_tests/2pc_int_greater_than.c create mode 100644 examples/C/mpc/unit_tests/arithmetic_tests/2pc_int_less_equals.c create mode 100644 examples/C/mpc/unit_tests/arithmetic_tests/2pc_int_less_than.c create mode 100644 examples/C/mpc/unit_tests/arithmetic_tests/2pc_loop_add.c create mode 100644 examples/C/mpc/unit_tests/arithmetic_tests/2pc_mod.c create mode 100644 examples/C/mpc/unit_tests/arithmetic_tests/2pc_mult.c create mode 100644 examples/C/mpc/unit_tests/arithmetic_tests/2pc_mult_add_pub.c create mode 100644 examples/C/mpc/unit_tests/arithmetic_tests/2pc_sub.c create mode 100644 examples/C/mpc/unit_tests/array_tests/2pc_array_index.c create mode 100644 examples/C/mpc/unit_tests/array_tests/2pc_array_index_2.c create mode 100644 examples/C/mpc/unit_tests/array_tests/2pc_array_ret.c create mode 100644 examples/C/mpc/unit_tests/array_tests/2pc_array_sum.c create mode 100644 examples/C/mpc/unit_tests/bitwise_tests/2pc_bitwise_and.c create mode 100644 examples/C/mpc/unit_tests/bitwise_tests/2pc_bitwise_or.c create mode 100644 examples/C/mpc/unit_tests/bitwise_tests/2pc_bitwise_xor.c create mode 100644 examples/C/mpc/unit_tests/boolean_tests/2pc_boolean_and.c create mode 100644 examples/C/mpc/unit_tests/boolean_tests/2pc_boolean_equals.c create mode 100644 examples/C/mpc/unit_tests/boolean_tests/2pc_boolean_or.c create mode 100644 examples/C/mpc/unit_tests/c_array_tests/2pc_array.c create mode 100644 examples/C/mpc/unit_tests/c_array_tests/2pc_array_1.c create mode 100644 examples/C/mpc/unit_tests/c_array_tests/2pc_array_2.c create mode 100644 examples/C/mpc/unit_tests/c_array_tests/2pc_array_3.c create mode 100644 examples/C/mpc/unit_tests/c_array_tests/2pc_array_sum_c.c create mode 100644 examples/C/mpc/unit_tests/const_tests/2pc_const_arith.c create mode 100644 examples/C/mpc/unit_tests/const_tests/2pc_const_bool.c create mode 100644 examples/C/mpc/unit_tests/div_tests/2pc_div.c create mode 100644 examples/C/mpc/unit_tests/ite_tests/2pc_ite_only_if.c create mode 100644 examples/C/mpc/unit_tests/ite_tests/2pc_ite_ret_bool.c create mode 100644 examples/C/mpc/unit_tests/ite_tests/2pc_ite_ret_int.c create mode 100644 examples/C/mpc/unit_tests/nary_arithmetic_tests/2pc_nary_arithmetic_add.c create mode 100644 examples/C/mpc/unit_tests/nary_boolean_tests/2pc_nary_boolean_and.c create mode 100644 examples/C/mpc/unit_tests/shift_tests/2pc_lhs.c create mode 100644 examples/C/mpc/unit_tests/shift_tests/2pc_rhs.c create mode 100644 examples/C/r1cs/add.c delete mode 100644 examples/ZoKrates/mpc/array_tests/2pc_array_ret.zok delete mode 100644 examples/ZoKrates/mpc/array_tests/2pc_array_sum.zok delete mode 100644 examples/ZoKrates/mpc/function_tests/2pc_function_sum.zok delete mode 100644 examples/ZoKrates/mpc/hycc_benchmarks/biomatch.zok create mode 100644 output1.txt create mode 100644 output2.txt create mode 100755 scripts/aby_tests/c_bench_aby.py create mode 100755 scripts/aby_tests/c_test_aby.py create mode 100644 scripts/aby_tests/test_suite.py create mode 100644 scripts/aby_tests/utils.py create mode 100755 scripts/aby_tests/zokrates_test_aby.py create mode 100755 scripts/build_mpc_c_test.zsh create mode 100755 scripts/build_r1cs_c_test.zsh delete mode 100644 scripts/test_aby.py create mode 100644 src/front/c/ast_utils.rs create mode 100644 src/front/c/mod.rs create mode 100644 src/front/c/parser.rs create mode 100644 src/front/c/term.rs create mode 100644 src/front/c/types.rs create mode 100644 src/ir/opt/binarize.rs delete mode 100644 src/ir/opt/mem/visit.rs create mode 100644 src/target/aby/utils.rs create mode 100644 third_party/ZoKrates/zokrates_parser/Cargo.lock create mode 100644 third_party/hycc/README.md create mode 100644 third_party/hycc/adapted_costs.json create mode 100644 third_party/hycc/original_costs.json create mode 100644 third_party/opa/adapted_costs.json rename third_party/opa/{sample_costs.json => original_costs.json} (99%) diff --git a/Cargo.lock b/Cargo.lock index 67ecd94c..6c6585ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -218,6 +218,7 @@ dependencies = [ "hashconsing", "ieee754", "itertools 0.10.3", + "lang-c", "lazy_static", "log", "lp-solvers", @@ -547,6 +548,12 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" +[[package]] +name = "lang-c" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a597343db6f9affec95665270028e3113864b48a1a0ba9257c1553ade3840207" + [[package]] name = "lazy_static" version = "1.4.0" diff --git a/Cargo.toml b/Cargo.toml index 0dc0d817..f4a333bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ fxhash = "0.2" good_lp = { version = "1.1", features = ["lp-solvers", "coin_cbc"], default-features = false } lp-solvers = "0.0.4" serde_json = "1.0" +lang-c = "0.10.1" pest = "2.1" pest_derive = "2.1" pest-ast = "0.3" diff --git a/Makefile b/Makefile index f87c823f..b4950a5f 100644 --- a/Makefile +++ b/Makefile @@ -10,26 +10,36 @@ build_aby_zokrates: build_deps build ./scripts/build_mpc_zokrates_test.zsh ./scripts/build_aby.zsh +build_aby_c: build_deps build + ./scripts/build_mpc_c_test.zsh + ./scripts/build_aby.zsh + build: cargo build --release --example circ cargo build --example circ -test: build build_aby_zokrates +test: build build_aby_zokrates build_aby_c cargo test ./scripts/zokrates_test.zsh - python3 ./scripts/test_aby.py + python3 ./scripts/aby_tests/zokrates_test_aby.py + python3 ./scripts/aby_tests/c_test_aby.py ./scripts/test_zok_to_ilp.zsh ./scripts/test_zok_to_ilp_pf.zsh ./scripts/test_datalog.zsh -aby: build_aby_zokrates - python3 ./scripts/test_aby.py +c_aby: build_aby_c + python3 ./scripts/aby_tests/c_test_aby.py + +z_aby: build_aby_zokrates + python3 ./scripts/aby_tests/zokrates_test_aby.py clean: # remove all generated files touch ./third_party/ABY/build && rm -r -- ./third_party/ABY/build touch ./third_party/ABY/src/examples/2pc_* && rm -r -- ./third_party/ABY/src/examples/2pc_* sed '/add_subdirectory.*2pc.*/d' -i ./third_party/ABY/src/examples/CMakeLists.txt + rm -rf ./third_party/ABY/src/examples/2pc_*.txt + rm -rf scripts/aby_tests/__pycache__ rm -rf P V pi perf.data perf.data.old flamegraph.svg format: diff --git a/examples/C/mpc/2pc_millionaires.c b/examples/C/mpc/2pc_millionaires.c new file mode 100644 index 00000000..9e5432ef --- /dev/null +++ b/examples/C/mpc/2pc_millionaires.c @@ -0,0 +1,8 @@ +#include + +bool main( + __attribute__((private(0))) int a, + __attribute__((private(1))) int b) +{ + return a < b; +} \ No newline at end of file diff --git a/examples/C/mpc/benchmarks/2pc_biomatch.c b/examples/C/mpc/benchmarks/2pc_biomatch.c new file mode 100644 index 00000000..e81fef42 --- /dev/null +++ b/examples/C/mpc/benchmarks/2pc_biomatch.c @@ -0,0 +1,38 @@ +int mpc_main( + __attribute__((private(0))) int db[1024], + __attribute__((private(1))) int sample[4]) +{ + int N = 256; + int K = 4; + int matches[N]; + + // Compute distances + for (int i = 0; i < N; i++) + { + int db_inner[K]; + for (int j = 0; j < K; j++) + { + db_inner[j] = db[i * K + j]; + } + + int r = 0; + for (int k = 0; k < K; k++) + { + int t = (db_inner[k] - sample[k]); + r += t * t; + } + matches[i] = r; + } + + // Compute minimum + int best_match = matches[0]; + for (int l = 1; l < N; l++) + { + if (matches[l] < best_match) + { + best_match = matches[l]; + } + } + + return best_match; +} \ No newline at end of file diff --git a/examples/C/mpc/benchmarks/2pc_kmeans.c b/examples/C/mpc/benchmarks/2pc_kmeans.c new file mode 100644 index 00000000..18515a7a --- /dev/null +++ b/examples/C/mpc/benchmarks/2pc_kmeans.c @@ -0,0 +1,202 @@ +int main(__attribute__((private(0))) int a[20], __attribute__((private(1))) int b[20]) +{ + int D = 2; + int NA = 10; + int NB = 10; + int NC = 5; + int PRECISION = 4; + int LEN = NA + NB; + int LEN_OUTER = 10; + int LEN_INNER = LEN / LEN_OUTER; + + // init data + int data[LEN * D]; + for (int i_0 = 0; i_0 < D * NA; i_0++) + { + data[i_0] = a[i_0]; + } + int offset = D * NA; + for (int i_1 = 0; i_1 < D * NB; i_1++) + { + data[i_1 + offset] = b[i_1]; + } + + int output[D * NC]; + + // ======================= kmeans + int cluster[D * NC]; + + // Assign random start cluster from data + for (int i_2 = 0; i_2 < NC; i_2++) + { + cluster[i_2 * D] = data[((i_2 + 3) % LEN) * D]; + cluster[i_2 * D + 1] = data[((i_2 + 3) % LEN) * D + 1]; + } + + for (int i_3 = 0; i_3 < PRECISION; i_3++) + { + int new_cluster[D * NC]; + + // ======================= iteration_unrolled_outer + int count[NC]; + + // Set Outer result + for (int i_4 = 0; i_4 < NC; i_4++) + { + new_cluster[i_4 * D] = 0; + new_cluster[i_4 * D + 1] = 0; + count[i_4] = 0; + } + + int loop_clusterD1[NC * LEN_OUTER]; + int loop_clusterD2[NC * LEN_OUTER]; + int loop_count[NC * LEN_OUTER]; + + // Compute decomposition + for (int i_5 = 0; i_5 < LEN_OUTER; i_5++) + { + // Copy data, fasthack for scalability + int data_offset = i_5 * LEN_INNER * D; + int data_inner[LEN_INNER * D]; + + // memcpy(data_inner, data+data_offset, LEN_INNER*D*sizeof(coord_t)); + for (int i_6 = 0; i_6 < LEN_INNER * D; i_6++) + { + data_inner[i_6] = data[i_6 + data_offset]; + } + + int cluster_inner[NC * D]; + int count_inner[NC]; + + // ======================= iteration_unrolled_inner_depth(data_inner, cluster, cluster_inner, count_inner, LEN_INNER, NC); + int dist[NC]; + int pos[NC]; + int bestMap_inner[LEN_INNER]; + + for (int i_7 = 0; i_7 < NC; i_7++) + { + cluster_inner[i_7 * D] = 0; + cluster_inner[i_7 * D + 1] = 0; + count_inner[i_7] = 0; + } + + // Compute nearest clusters for Data item i + for (int i_8 = 0; i_8 < LEN_INNER; i_8++) + { + int dx = data_inner[i_8 * D]; + int dy = data_inner[i_8 * D + 1]; + + for (int i_9 = 0; i_9 < NC; i_9++) + { + pos[i_9] = i_9; + int x1 = cluster[D * i_9]; + int y1 = cluster[D * i_9 + 1]; + int x2 = dx; + int y2 = dy; + dist[i_9] = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2); + } + // hardcoded NC = 5; + // stride = 1 + // stride = 2 + // stride = 4 + int stride = 1; + for (int i_10 = 0; i_10 < NC - stride; i_10 += 2) + { + if (dist[i_10 + stride] < dist[i_10]) + { + dist[i_10] = dist[i_10 + stride]; + pos[i_10] = pos[i_10 + stride]; + } + } + stride = 2; + for (int i_11 = 0; i_11 < NC - stride; i_11 += 4) + { + if (dist[i_11 + stride] < dist[i_11]) + { + dist[i_11] = dist[i_11 + stride]; + pos[i_11] = pos[i_11 + stride]; + } + } + stride = 4; + for (int i_12 = 0; i_12 < NC - stride; i_12 += 8) + { + if (dist[i_12 + stride] < dist[i_12]) + { + dist[i_12] = dist[i_12 + stride]; + pos[i_12] = pos[i_12 + stride]; + } + } + bestMap_inner[i_8] = pos[0]; + int cc = bestMap_inner[i_8]; + cluster_inner[cc * D] += data_inner[i_8 * D]; + cluster_inner[cc * D + 1] += data_inner[i_8 * D + 1]; + count_inner[cc] += 1; + } + // // ======================= iteration_unrolled_inner_depth(data_inner, cluster, cluster_inner, count_inner, LEN_INNER, NC); + + for (int i_13 = 0; i_13 < NC; i_13++) + { + loop_clusterD1[i_13 * LEN_OUTER + i_5] = cluster_inner[i_13 * D]; + loop_clusterD2[i_13 * LEN_OUTER + i_5] = cluster_inner[i_13 * D + 1]; + loop_count[i_13 * LEN_OUTER + i_5] = count_inner[i_13]; + } + } + + for (int i_14 = 0; i_14 < NC; i_14++) + { + new_cluster[i_14 * D] = + loop_clusterD1[i_14 * LEN_OUTER + 0] + loop_clusterD1[i_14 * LEN_OUTER + 1] + + loop_clusterD1[i_14 * LEN_OUTER + 2] + loop_clusterD1[i_14 * LEN_OUTER + 3] + + loop_clusterD1[i_14 * LEN_OUTER + 4] + loop_clusterD1[i_14 * LEN_OUTER + 5] + + loop_clusterD1[i_14 * LEN_OUTER + 6] + loop_clusterD1[i_14 * LEN_OUTER + 7] + + loop_clusterD1[i_14 * LEN_OUTER + 8] + loop_clusterD1[i_14 * LEN_OUTER + 9]; + + new_cluster[i_14 * D + 1] = + loop_clusterD2[i_14 * LEN_OUTER + 0] + loop_clusterD2[i_14 * LEN_OUTER + 1] + + loop_clusterD2[i_14 * LEN_OUTER + 2] + loop_clusterD2[i_14 * LEN_OUTER + 3] + + loop_clusterD2[i_14 * LEN_OUTER + 4] + loop_clusterD2[i_14 * LEN_OUTER + 5] + + loop_clusterD2[i_14 * LEN_OUTER + 6] + loop_clusterD2[i_14 * LEN_OUTER + 7] + + loop_clusterD2[i_14 * LEN_OUTER + 8] + loop_clusterD2[i_14 * LEN_OUTER + 9]; + + count[i_14] = + loop_count[i_14 * LEN_OUTER + 0] + loop_count[i_14 * LEN_OUTER + 1] + + loop_count[i_14 * LEN_OUTER + 2] + loop_count[i_14 * LEN_OUTER + 3] + + loop_count[i_14 * LEN_OUTER + 4] + loop_count[i_14 * LEN_OUTER + 5] + + loop_count[i_14 * LEN_OUTER + 6] + loop_count[i_14 * LEN_OUTER + 7] + + loop_count[i_14 * LEN_OUTER + 8] + loop_count[i_14 * LEN_OUTER + 9]; + } + + // Recompute cluster Pos + // Compute mean + for (int i_15 = 0; i_15 < NC; i_15++) + { + if (count[i_15] > 0) + { + new_cluster[i_15 * D] /= count[i_15]; + new_cluster[i_15 * D + 1] /= count[i_15]; + } + } + // ======================= iteration_unrolled_outer + + // We need to copy inputs to outputs + for (int i_16 = 0; i_16 < NC * D; i_16++) + { + cluster[i_16] = new_cluster[i_16]; + } + } + for (int i_17 = 0; i_17 < NC; i_17++) + { + output[i_17 * D] = cluster[i_17 * D]; + output[i_17 * D + 1] = cluster[i_17 * D + 1]; + } + // ======================= kmeans + // return output[0]; + + int sum = 0; + for (int i_18 = 0; i_18 < D * NC; i_18++) + { + sum += output[i_18]; + } + + return sum; +} diff --git a/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench.c b/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench.c new file mode 100644 index 00000000..384ab5ed --- /dev/null +++ b/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench.c @@ -0,0 +1,12 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) +{ + int acc = 0; + for (int i = 0; i < 75000; i++) + { + if (a > b) + { + acc += 1; + } + } + return acc; +} diff --git a/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_1.c b/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_1.c new file mode 100644 index 00000000..754ce856 --- /dev/null +++ b/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_1.c @@ -0,0 +1,12 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) +{ + int acc = 0; + for (int i = 0; i < 1000; i++) + { + if (a > b) + { + acc += 1; + } + } + return acc; +} diff --git a/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_2.c b/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_2.c new file mode 100644 index 00000000..029ba3eb --- /dev/null +++ b/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_2.c @@ -0,0 +1,12 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) +{ + int acc = 0; + for (int i = 0; i < 2000; i++) + { + if (a > b) + { + acc += 1; + } + } + return acc; +} diff --git a/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_3.c b/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_3.c new file mode 100644 index 00000000..4d26aee5 --- /dev/null +++ b/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_3.c @@ -0,0 +1,12 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) +{ + int acc = 0; + for (int i = 0; i < 3000; i++) + { + if (a > b) + { + acc += 1; + } + } + return acc; +} diff --git a/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_4.c b/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_4.c new file mode 100644 index 00000000..db1289b1 --- /dev/null +++ b/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_4.c @@ -0,0 +1,12 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) +{ + int acc = 0; + for (int i = 0; i < 4000; i++) + { + if (a > b) + { + acc += 1; + } + } + return acc; +} diff --git a/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_5.c b/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_5.c new file mode 100644 index 00000000..1470eef8 --- /dev/null +++ b/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_5.c @@ -0,0 +1,12 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) +{ + int acc = 0; + for (int i = 0; i < 5000; i++) + { + if (a > b) + { + acc += 1; + } + } + return acc; +} diff --git a/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_6.c b/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_6.c new file mode 100644 index 00000000..6c4056df --- /dev/null +++ b/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_6.c @@ -0,0 +1,12 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) +{ + int acc = 0; + for (int i = 0; i < 6000; i++) + { + if (a > b) + { + acc += 1; + } + } + return acc; +} diff --git a/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_7.c b/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_7.c new file mode 100644 index 00000000..13284180 --- /dev/null +++ b/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_7.c @@ -0,0 +1,12 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) +{ + int acc = 0; + for (int i = 0; i < 7000; i++) + { + if (a > b) + { + acc += 1; + } + } + return acc; +} diff --git a/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_8.c b/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_8.c new file mode 100644 index 00000000..eea1e76b --- /dev/null +++ b/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_8.c @@ -0,0 +1,12 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) +{ + int acc = 0; + for (int i = 0; i < 8000; i++) + { + if (a > b) + { + acc += 1; + } + } + return acc; +} diff --git a/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_9.c b/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_9.c new file mode 100644 index 00000000..32489a98 --- /dev/null +++ b/examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_9.c @@ -0,0 +1,12 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) +{ + int acc = 0; + for (int i = 0; i < 9000; i++) + { + if (a > b) + { + acc += 1; + } + } + return acc; +} diff --git a/examples/C/mpc/unit_tests/arithmetic_tests/2pc_add.c b/examples/C/mpc/unit_tests/arithmetic_tests/2pc_add.c new file mode 100644 index 00000000..fab58cef --- /dev/null +++ b/examples/C/mpc/unit_tests/arithmetic_tests/2pc_add.c @@ -0,0 +1,3 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) { + return a + b; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/arithmetic_tests/2pc_add_unsigned.c b/examples/C/mpc/unit_tests/arithmetic_tests/2pc_add_unsigned.c new file mode 100644 index 00000000..740c6875 --- /dev/null +++ b/examples/C/mpc/unit_tests/arithmetic_tests/2pc_add_unsigned.c @@ -0,0 +1,3 @@ +int main(__attribute__((private(0))) unsigned int a, __attribute__((private(1))) unsigned int b) { + return a + b; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/arithmetic_tests/2pc_int_equals.c b/examples/C/mpc/unit_tests/arithmetic_tests/2pc_int_equals.c new file mode 100644 index 00000000..65708146 --- /dev/null +++ b/examples/C/mpc/unit_tests/arithmetic_tests/2pc_int_equals.c @@ -0,0 +1,5 @@ +#include + +bool main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) { + return a == b; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/arithmetic_tests/2pc_int_greater_equals.c b/examples/C/mpc/unit_tests/arithmetic_tests/2pc_int_greater_equals.c new file mode 100644 index 00000000..a6cddc26 --- /dev/null +++ b/examples/C/mpc/unit_tests/arithmetic_tests/2pc_int_greater_equals.c @@ -0,0 +1,5 @@ +#include + +bool main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) { + return a >= b; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/arithmetic_tests/2pc_int_greater_than.c b/examples/C/mpc/unit_tests/arithmetic_tests/2pc_int_greater_than.c new file mode 100644 index 00000000..b7ad8d43 --- /dev/null +++ b/examples/C/mpc/unit_tests/arithmetic_tests/2pc_int_greater_than.c @@ -0,0 +1,5 @@ +#include + +bool main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) { + return a > b; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/arithmetic_tests/2pc_int_less_equals.c b/examples/C/mpc/unit_tests/arithmetic_tests/2pc_int_less_equals.c new file mode 100644 index 00000000..64c43e56 --- /dev/null +++ b/examples/C/mpc/unit_tests/arithmetic_tests/2pc_int_less_equals.c @@ -0,0 +1,5 @@ +#include + +bool main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) { + return a <= b; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/arithmetic_tests/2pc_int_less_than.c b/examples/C/mpc/unit_tests/arithmetic_tests/2pc_int_less_than.c new file mode 100644 index 00000000..47de35f1 --- /dev/null +++ b/examples/C/mpc/unit_tests/arithmetic_tests/2pc_int_less_than.c @@ -0,0 +1,5 @@ +#include + +bool main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) { + return a < b; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/arithmetic_tests/2pc_loop_add.c b/examples/C/mpc/unit_tests/arithmetic_tests/2pc_loop_add.c new file mode 100644 index 00000000..b6eba214 --- /dev/null +++ b/examples/C/mpc/unit_tests/arithmetic_tests/2pc_loop_add.c @@ -0,0 +1,7 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) { + int c = a * b; + for (int i = 0; i < 10000; i++) { + c = c * a; + } + return c; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/arithmetic_tests/2pc_mod.c b/examples/C/mpc/unit_tests/arithmetic_tests/2pc_mod.c new file mode 100644 index 00000000..564e46aa --- /dev/null +++ b/examples/C/mpc/unit_tests/arithmetic_tests/2pc_mod.c @@ -0,0 +1,3 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) { + return a % b; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/arithmetic_tests/2pc_mult.c b/examples/C/mpc/unit_tests/arithmetic_tests/2pc_mult.c new file mode 100644 index 00000000..9404cd92 --- /dev/null +++ b/examples/C/mpc/unit_tests/arithmetic_tests/2pc_mult.c @@ -0,0 +1,3 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) { + return a * b; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/arithmetic_tests/2pc_mult_add_pub.c b/examples/C/mpc/unit_tests/arithmetic_tests/2pc_mult_add_pub.c new file mode 100644 index 00000000..917ec25c --- /dev/null +++ b/examples/C/mpc/unit_tests/arithmetic_tests/2pc_mult_add_pub.c @@ -0,0 +1,3 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b, __attribute__((public)) int v) { + return a * b + v; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/arithmetic_tests/2pc_sub.c b/examples/C/mpc/unit_tests/arithmetic_tests/2pc_sub.c new file mode 100644 index 00000000..eabdc1b5 --- /dev/null +++ b/examples/C/mpc/unit_tests/arithmetic_tests/2pc_sub.c @@ -0,0 +1,3 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) { + return a - b; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/array_tests/2pc_array_index.c b/examples/C/mpc/unit_tests/array_tests/2pc_array_index.c new file mode 100644 index 00000000..5645558e --- /dev/null +++ b/examples/C/mpc/unit_tests/array_tests/2pc_array_index.c @@ -0,0 +1,5 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) { + int index = a + b; + int arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + return arr[index]; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/array_tests/2pc_array_index_2.c b/examples/C/mpc/unit_tests/array_tests/2pc_array_index_2.c new file mode 100644 index 00000000..5bbafbe2 --- /dev/null +++ b/examples/C/mpc/unit_tests/array_tests/2pc_array_index_2.c @@ -0,0 +1,8 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) { + int arr[4] = {a,b,a,b}; + int new_arr[4]; + for (int i = 0; i < 4; i++) { + new_arr[i] = arr[i]; + } + return new_arr[0]; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/array_tests/2pc_array_ret.c b/examples/C/mpc/unit_tests/array_tests/2pc_array_ret.c new file mode 100644 index 00000000..0c09e9e4 --- /dev/null +++ b/examples/C/mpc/unit_tests/array_tests/2pc_array_ret.c @@ -0,0 +1,3 @@ +int* main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) { + return {a, b}; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/array_tests/2pc_array_sum.c b/examples/C/mpc/unit_tests/array_tests/2pc_array_sum.c new file mode 100644 index 00000000..2a826e02 --- /dev/null +++ b/examples/C/mpc/unit_tests/array_tests/2pc_array_sum.c @@ -0,0 +1,4 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) { + int arr[2] = {a, b}; + return arr[0] + arr[1]; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/bitwise_tests/2pc_bitwise_and.c b/examples/C/mpc/unit_tests/bitwise_tests/2pc_bitwise_and.c new file mode 100644 index 00000000..0f482f5d --- /dev/null +++ b/examples/C/mpc/unit_tests/bitwise_tests/2pc_bitwise_and.c @@ -0,0 +1,3 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) { + return a & b; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/bitwise_tests/2pc_bitwise_or.c b/examples/C/mpc/unit_tests/bitwise_tests/2pc_bitwise_or.c new file mode 100644 index 00000000..01f6e48d --- /dev/null +++ b/examples/C/mpc/unit_tests/bitwise_tests/2pc_bitwise_or.c @@ -0,0 +1,3 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) { + return a | b; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/bitwise_tests/2pc_bitwise_xor.c b/examples/C/mpc/unit_tests/bitwise_tests/2pc_bitwise_xor.c new file mode 100644 index 00000000..3f3187a5 --- /dev/null +++ b/examples/C/mpc/unit_tests/bitwise_tests/2pc_bitwise_xor.c @@ -0,0 +1,3 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) { + return a ^ b; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/boolean_tests/2pc_boolean_and.c b/examples/C/mpc/unit_tests/boolean_tests/2pc_boolean_and.c new file mode 100644 index 00000000..6e4e8258 --- /dev/null +++ b/examples/C/mpc/unit_tests/boolean_tests/2pc_boolean_and.c @@ -0,0 +1,5 @@ +#include + +bool main(__attribute__((private(0))) bool a, __attribute__((private(1))) bool b) { + return a && b; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/boolean_tests/2pc_boolean_equals.c b/examples/C/mpc/unit_tests/boolean_tests/2pc_boolean_equals.c new file mode 100644 index 00000000..d0b00b09 --- /dev/null +++ b/examples/C/mpc/unit_tests/boolean_tests/2pc_boolean_equals.c @@ -0,0 +1,5 @@ +#include + +bool main(__attribute__((private(0))) bool a, __attribute__((private(1))) bool b) { + return a == b; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/boolean_tests/2pc_boolean_or.c b/examples/C/mpc/unit_tests/boolean_tests/2pc_boolean_or.c new file mode 100644 index 00000000..b66126c0 --- /dev/null +++ b/examples/C/mpc/unit_tests/boolean_tests/2pc_boolean_or.c @@ -0,0 +1,5 @@ +#include + +bool main(__attribute__((private(0))) bool a, __attribute__((private(1))) bool b) { + return a || b; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/c_array_tests/2pc_array.c b/examples/C/mpc/unit_tests/c_array_tests/2pc_array.c new file mode 100644 index 00000000..ad597b0a --- /dev/null +++ b/examples/C/mpc/unit_tests/c_array_tests/2pc_array.c @@ -0,0 +1,6 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) { + int v[5]; + v[0] = a; + b = v[0]; + return b; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/c_array_tests/2pc_array_1.c b/examples/C/mpc/unit_tests/c_array_tests/2pc_array_1.c new file mode 100644 index 00000000..cd0d91e5 --- /dev/null +++ b/examples/C/mpc/unit_tests/c_array_tests/2pc_array_1.c @@ -0,0 +1,7 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) { + int v[5]; + a = 17; + v[1] = a; + b = v[1]; + return b; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/c_array_tests/2pc_array_2.c b/examples/C/mpc/unit_tests/c_array_tests/2pc_array_2.c new file mode 100644 index 00000000..63aba9dc --- /dev/null +++ b/examples/C/mpc/unit_tests/c_array_tests/2pc_array_2.c @@ -0,0 +1,8 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) { + int v[5]; + a = 17; + int i = 4; + v[i] = a; + b = v[i]; + return b; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/c_array_tests/2pc_array_3.c b/examples/C/mpc/unit_tests/c_array_tests/2pc_array_3.c new file mode 100644 index 00000000..be9167cb --- /dev/null +++ b/examples/C/mpc/unit_tests/c_array_tests/2pc_array_3.c @@ -0,0 +1,7 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) { + int v[3]; + for (int i = 0; i < 3; i++) v[i] = a + b + i; + int acc = 0; + for (int j = 0; j < 3; j++) acc += v[j]; + return acc; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/c_array_tests/2pc_array_sum_c.c b/examples/C/mpc/unit_tests/c_array_tests/2pc_array_sum_c.c new file mode 100644 index 00000000..888dcb6a --- /dev/null +++ b/examples/C/mpc/unit_tests/c_array_tests/2pc_array_sum_c.c @@ -0,0 +1,11 @@ +int main(__attribute__((private(0))) int a[5], __attribute__((private(1))) int b[5]) { + int sum[5]; + for (int i = 0; i < 5; i++) { + sum[i] = a[i] + b[i]; + } + int acc = 0; + for (int j = 0; j < 5; j++) { + acc += sum[j]; + } + return acc; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/const_tests/2pc_const_arith.c b/examples/C/mpc/unit_tests/const_tests/2pc_const_arith.c new file mode 100644 index 00000000..7d841ad0 --- /dev/null +++ b/examples/C/mpc/unit_tests/const_tests/2pc_const_arith.c @@ -0,0 +1,4 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) { + int c = 1; + return a + b + c; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/const_tests/2pc_const_bool.c b/examples/C/mpc/unit_tests/const_tests/2pc_const_bool.c new file mode 100644 index 00000000..eea11a32 --- /dev/null +++ b/examples/C/mpc/unit_tests/const_tests/2pc_const_bool.c @@ -0,0 +1,6 @@ +#include + +bool main(__attribute__((private(0))) bool a, __attribute__((private(1))) bool b) { + bool c = true; + return a == c; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/div_tests/2pc_div.c b/examples/C/mpc/unit_tests/div_tests/2pc_div.c new file mode 100644 index 00000000..f5caa686 --- /dev/null +++ b/examples/C/mpc/unit_tests/div_tests/2pc_div.c @@ -0,0 +1,3 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) { + return a / b; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/ite_tests/2pc_ite_only_if.c b/examples/C/mpc/unit_tests/ite_tests/2pc_ite_only_if.c new file mode 100644 index 00000000..6b1a221d --- /dev/null +++ b/examples/C/mpc/unit_tests/ite_tests/2pc_ite_only_if.c @@ -0,0 +1,8 @@ +#include + +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b, __attribute__((public)) bool sel) { + if (sel) { + return a; + } + return b; +} diff --git a/examples/C/mpc/unit_tests/ite_tests/2pc_ite_ret_bool.c b/examples/C/mpc/unit_tests/ite_tests/2pc_ite_ret_bool.c new file mode 100644 index 00000000..39816a81 --- /dev/null +++ b/examples/C/mpc/unit_tests/ite_tests/2pc_ite_ret_bool.c @@ -0,0 +1,9 @@ +#include + +bool main(__attribute__((private(0))) bool a, __attribute__((private(1))) bool b, __attribute__((public)) bool sel) { + if (sel) { + return a; + } else { + return b; + } +} diff --git a/examples/C/mpc/unit_tests/ite_tests/2pc_ite_ret_int.c b/examples/C/mpc/unit_tests/ite_tests/2pc_ite_ret_int.c new file mode 100644 index 00000000..5b6c9c06 --- /dev/null +++ b/examples/C/mpc/unit_tests/ite_tests/2pc_ite_ret_int.c @@ -0,0 +1,9 @@ +#include + +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b, __attribute__((public)) bool sel) { + if (sel) { + return a; + } else { + return b; + } +} diff --git a/examples/C/mpc/unit_tests/nary_arithmetic_tests/2pc_nary_arithmetic_add.c b/examples/C/mpc/unit_tests/nary_arithmetic_tests/2pc_nary_arithmetic_add.c new file mode 100644 index 00000000..c8af060f --- /dev/null +++ b/examples/C/mpc/unit_tests/nary_arithmetic_tests/2pc_nary_arithmetic_add.c @@ -0,0 +1,3 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b, __attribute__((private(1))) int c) { + return a + b + c; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/nary_boolean_tests/2pc_nary_boolean_and.c b/examples/C/mpc/unit_tests/nary_boolean_tests/2pc_nary_boolean_and.c new file mode 100644 index 00000000..c80224b4 --- /dev/null +++ b/examples/C/mpc/unit_tests/nary_boolean_tests/2pc_nary_boolean_and.c @@ -0,0 +1,5 @@ +#include + +bool main(__attribute__((private(0))) bool a, __attribute__((private(1))) bool b, __attribute__((private(1))) bool c) { + return a && b && c; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/shift_tests/2pc_lhs.c b/examples/C/mpc/unit_tests/shift_tests/2pc_lhs.c new file mode 100644 index 00000000..c6acf20c --- /dev/null +++ b/examples/C/mpc/unit_tests/shift_tests/2pc_lhs.c @@ -0,0 +1,3 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) { + return a << b; +} \ No newline at end of file diff --git a/examples/C/mpc/unit_tests/shift_tests/2pc_rhs.c b/examples/C/mpc/unit_tests/shift_tests/2pc_rhs.c new file mode 100644 index 00000000..0deeb2bb --- /dev/null +++ b/examples/C/mpc/unit_tests/shift_tests/2pc_rhs.c @@ -0,0 +1,3 @@ +int main(__attribute__((private(0))) int a, __attribute__((private(1))) int b) { + return a >> b; +} \ No newline at end of file diff --git a/examples/C/r1cs/add.c b/examples/C/r1cs/add.c new file mode 100644 index 00000000..212667a6 --- /dev/null +++ b/examples/C/r1cs/add.c @@ -0,0 +1,6 @@ +int mpc_main( + __attribute__((private(0))) int a, + __attribute__((private(1))) int b) +{ + return a + b; +} \ No newline at end of file diff --git a/examples/ZoKrates/mpc/array_tests/2pc_array_ret.zok b/examples/ZoKrates/mpc/array_tests/2pc_array_ret.zok deleted file mode 100644 index f9b0ef39..00000000 --- a/examples/ZoKrates/mpc/array_tests/2pc_array_ret.zok +++ /dev/null @@ -1,2 +0,0 @@ -def main(private<1> u32 a, private<2> u32 b) -> u32[2]: - return [a, b] \ No newline at end of file diff --git a/examples/ZoKrates/mpc/array_tests/2pc_array_sum.zok b/examples/ZoKrates/mpc/array_tests/2pc_array_sum.zok deleted file mode 100644 index 1030a8f1..00000000 --- a/examples/ZoKrates/mpc/array_tests/2pc_array_sum.zok +++ /dev/null @@ -1,3 +0,0 @@ -def main(private<1> u32 a, private<2> u32 b) -> u32: - u32[2] c = [a, b] - return c[0] + c[1] \ No newline at end of file diff --git a/examples/ZoKrates/mpc/function_tests/2pc_function_sum.zok b/examples/ZoKrates/mpc/function_tests/2pc_function_sum.zok deleted file mode 100644 index 80036f70..00000000 --- a/examples/ZoKrates/mpc/function_tests/2pc_function_sum.zok +++ /dev/null @@ -1,5 +0,0 @@ -def sum(u32 a, u32 b) -> u32: - return a + b - -def main(private<1> u32 a, private<2> u32 b) -> u32: - return sum(a, b) diff --git a/examples/ZoKrates/mpc/hycc_benchmarks/biomatch.zok b/examples/ZoKrates/mpc/hycc_benchmarks/biomatch.zok deleted file mode 100644 index b85d3f39..00000000 --- a/examples/ZoKrates/mpc/hycc_benchmarks/biomatch.zok +++ /dev/null @@ -1,5 +0,0 @@ -def main(private<1> u32 a, private<2> u32 b) -> u32: - for u32 i in 1..4 do - a = a + b - return a - diff --git a/examples/ZoKrates/mpc/unit_tests/arithmetic_tests/2pc_add.zok b/examples/ZoKrates/mpc/unit_tests/arithmetic_tests/2pc_add.zok index 6c77453e..42d4a5ee 100644 --- a/examples/ZoKrates/mpc/unit_tests/arithmetic_tests/2pc_add.zok +++ b/examples/ZoKrates/mpc/unit_tests/arithmetic_tests/2pc_add.zok @@ -1,2 +1,2 @@ def main(private<1> u32 a, private<2> u32 b) -> u32: - return a + b + return a + b \ No newline at end of file diff --git a/examples/circ.rs b/examples/circ.rs index 77651c41..21613d08 100644 --- a/examples/circ.rs +++ b/examples/circ.rs @@ -6,9 +6,10 @@ use bellman::groth16::{ }; use bellman::Circuit; use bls12_381::{Bls12, Scalar}; +use circ::front::c::{self, C}; use circ::front::datalog::{self, Datalog}; -use circ::front::zokrates::{self, Mode, Zokrates}; -use circ::front::FrontEnd; +use circ::front::zokrates::{self, Zokrates}; +use circ::front::{FrontEnd, Mode}; use circ::ir::{ opt::{opt, Opt}, term::extras::Letified, @@ -86,7 +87,10 @@ enum Backend { }, Smt {}, Ilp {}, - Mpc {}, + Mpc { + #[structopt(long, default_value = "hycc", name = "cost_model")] + cost_model: String, + }, } arg_enum! { @@ -94,14 +98,22 @@ arg_enum! { enum Language { Zokrates, Datalog, + C, Auto, } } #[derive(PartialEq, Debug)] -enum DeterminedLanguage { +pub enum DeterminedLanguage { Zokrates, Datalog, + C, +} + +#[derive(PartialEq, Debug)] +pub enum CostModelType { + Opa, + Hycc, } arg_enum! { @@ -126,12 +138,19 @@ fn determine_language(l: &Language, input_path: &PathBuf) -> DeterminedLanguage match l { &Language::Datalog => DeterminedLanguage::Datalog, &Language::Zokrates => DeterminedLanguage::Zokrates, + &Language::C => DeterminedLanguage::C, &Language::Auto => { let p = input_path.to_str().unwrap(); if p.ends_with(".zok") { DeterminedLanguage::Zokrates } else if p.ends_with(".pl") { DeterminedLanguage::Datalog + } else if p.ends_with(".c") { + DeterminedLanguage::C + } else if p.ends_with(".cpp") { + DeterminedLanguage::C + } else if p.ends_with(".cc") { + DeterminedLanguage::C } else { println!("Could not deduce the input language from path '{}', please set the language manually", p); std::process::exit(2) @@ -175,12 +194,34 @@ fn main() { }; Datalog::gen(inputs) } + DeterminedLanguage::C => { + let inputs = c::Inputs { + file: options.path, + inputs: options.frontend.inputs, + mode: mode.clone(), + }; + C::gen(inputs) + } }; let cs = match mode { Mode::Opt => opt(cs, vec![Opt::ScalarizeVars, Opt::ConstantFold]), Mode::Mpc(_) => opt( cs, - vec![Opt::ScalarizeVars], + vec![ + Opt::Sha, + Opt::ConstantFold, + Opt::ScalarizeVars, + Opt::ConstantFold, + // The obliv elim pass produces more tuples, that must be eliminated + Opt::Obliv, + Opt::Tuple, + // The linear scan pass produces more tuples, that must be eliminated + Opt::LinearScan, + Opt::Tuple, + Opt::ConstantFold, + // Binarize nary terms + Opt::Binarize, + ], // vec![Opt::Sha, Opt::ConstantFold, Opt::Mem, Opt::ConstantFold], ), Mode::Proof | Mode::ProofOfHighValue(_) => opt( @@ -256,10 +297,16 @@ fn main() { } } } - Backend::Mpc { .. } => { + Backend::Mpc { cost_model } => { println!("Converting to aby"); - let aby = to_aby(cs); - write_aby_exec(aby, path_buf); + let lang_str = match language { + DeterminedLanguage::C => "c".to_string(), + DeterminedLanguage::Zokrates => "zok".to_string(), + _ => panic!("Language isn't supported by MPC backend: {:#?}", language), + }; + println!("Cost model: {}", cost_model); + to_aby(cs, &path_buf, &lang_str, &cost_model); + write_aby_exec(&path_buf, &lang_str); } Backend::Ilp { .. } => { println!("Converting to ilp"); diff --git a/examples/opa_bench.rs b/examples/opa_bench.rs index b344dc04..dd794113 100644 --- a/examples/opa_bench.rs +++ b/examples/opa_bench.rs @@ -30,6 +30,6 @@ fn main() { metadata: ComputationMetadata::default(), values: None, }; - let _assignment = ilp::assign(&cs); + let _assignment = ilp::assign(&cs, &format!("hycc")); //dbg!(&assignment); } diff --git a/output1.txt b/output1.txt new file mode 100644 index 00000000..bfc58daf --- /dev/null +++ b/output1.txt @@ -0,0 +1,351 @@ +Options { input_file_path: "./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_1.c", inputs: None, parties: Some(2), maximize: false } +Done with IR optimization +Converting to aby +Welcome to the CBC MILP Solver +Version: 2.10.3 +Build Date: Mar 24 2020 + +command line - Cbc_C_Interface -solve -quit (default strategy 1) +Continuous objective value is -84992 - 1.04 seconds +Cgl0004I processed model has 20004 rows, 13023 columns (13023 integer (13023 of which binary)) and 59011 elements +Cutoff increment increased from 1e-05 to 0.1999 +Cbc0038I Initial state - 0 integers unsatisfied sum - 0 +Cbc0038I Solution found of 84992 +Cbc0038I Before mini branch and bound, 13023 integers at bound fixed and 0 continuous +Cbc0038I Mini branch and bound did not improve solution (1.17 seconds) +Cbc0038I After 1.17 seconds - Feasibility pump exiting with objective of 84992 - took 0.02 seconds +Cbc0012I Integer solution of 84992 found by feasibility pump after 0 iterations and 0 nodes (1.17 seconds) +Cbc0001I Search completed - best objective 84992, took 0 iterations and 0 nodes (1.18 seconds) +Cbc0035I Maximum depth 0, 0 variables fixed on reduced cost +Cuts at root node changed objective from 84992 to 84992 +Probing was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Gomory was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Knapsack was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Clique was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +MixedIntegerRounding2 was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +FlowCover was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +TwoMirCuts was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +ZeroHalf was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) + +Result - Optimal solution found + +Objective value: -84992.00000000 +Enumerated nodes: 0 +Total iterations: 0 +Time (CPU seconds): 1.24 +Time (Wallclock seconds): 1.34 + +Total time (CPU seconds): 1.24 (Wallclock seconds): 1.34 + +Options { input_file_path: "./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_2.c", inputs: None, parties: Some(2), maximize: false } +Done with IR optimization +Converting to aby +Welcome to the CBC MILP Solver +Version: 2.10.3 +Build Date: Mar 24 2020 + +command line - Cbc_C_Interface -solve -quit (default strategy 1) +Continuous objective value is -169992 - 17.44 seconds +Cgl0004I processed model has 40004 rows, 26023 columns (26023 integer (26023 of which binary)) and 118011 elements +Cutoff increment increased from 1e-05 to 0.1999 +Cbc0038I Initial state - 0 integers unsatisfied sum - 0 +Cbc0038I Solution found of 169992 +Cbc0038I Before mini branch and bound, 26023 integers at bound fixed and 0 continuous +Cbc0038I Mini branch and bound did not improve solution (17.71 seconds) +Cbc0038I After 17.71 seconds - Feasibility pump exiting with objective of 169992 - took 0.05 seconds +Cbc0012I Integer solution of 169992 found by feasibility pump after 0 iterations and 0 nodes (17.72 seconds) +Cbc0001I Search completed - best objective 169992, took 0 iterations and 0 nodes (17.75 seconds) +Cbc0035I Maximum depth 0, 0 variables fixed on reduced cost +Cuts at root node changed objective from 169992 to 169992 +Probing was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Gomory was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Knapsack was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Clique was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +MixedIntegerRounding2 was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +FlowCover was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +TwoMirCuts was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +ZeroHalf was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) + +Result - Optimal solution found + +Objective value: -169992.00000000 +Enumerated nodes: 0 +Total iterations: 0 +Time (CPU seconds): 17.88 +Time (Wallclock seconds): 18.07 + +Total time (CPU seconds): 17.88 (Wallclock seconds): 18.07 + +Options { input_file_path: "./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_3.c", inputs: None, parties: Some(2), maximize: false } +Done with IR optimization +Converting to aby +Welcome to the CBC MILP Solver +Version: 2.10.3 +Build Date: Mar 24 2020 + +command line - Cbc_C_Interface -solve -quit (default strategy 1) +Continuous objective value is -254992 - 31.61 seconds +Cgl0004I processed model has 60004 rows, 39023 columns (39023 integer (39023 of which binary)) and 177011 elements +Cutoff increment increased from 1e-05 to 0.1999 +Cbc0038I Initial state - 0 integers unsatisfied sum - 0 +Cbc0038I Solution found of 254992 +Cbc0038I Before mini branch and bound, 39023 integers at bound fixed and 0 continuous +Cbc0038I Mini branch and bound did not improve solution (32.07 seconds) +Cbc0038I After 32.07 seconds - Feasibility pump exiting with objective of 254992 - took 0.10 seconds +Cbc0012I Integer solution of 254992 found by feasibility pump after 0 iterations and 0 nodes (32.09 seconds) +Cbc0001I Search completed - best objective 254992, took 0 iterations and 0 nodes (32.14 seconds) +Cbc0035I Maximum depth 0, 0 variables fixed on reduced cost +Cuts at root node changed objective from 254992 to 254992 +Probing was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Gomory was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Knapsack was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Clique was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +MixedIntegerRounding2 was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +FlowCover was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +TwoMirCuts was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +ZeroHalf was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) + +Result - Optimal solution found + +Objective value: -254992.00000000 +Enumerated nodes: 0 +Total iterations: 0 +Time (CPU seconds): 32.35 +Time (Wallclock seconds): 32.55 + +Total time (CPU seconds): 32.35 (Wallclock seconds): 32.55 + +Options { input_file_path: "./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_4.c", inputs: None, parties: Some(2), maximize: false } +Done with IR optimization +Converting to aby +Welcome to the CBC MILP Solver +Version: 2.10.3 +Build Date: Mar 24 2020 + +command line - Cbc_C_Interface -solve -quit (default strategy 1) +Continuous objective value is -339992 - 47.89 seconds +Cgl0004I processed model has 80004 rows, 52023 columns (52023 integer (52023 of which binary)) and 236011 elements +Cutoff increment increased from 1e-05 to 0.1999 +Cbc0038I Initial state - 0 integers unsatisfied sum - 0 +Cbc0038I Solution found of 339992 +Cbc0038I Before mini branch and bound, 52023 integers at bound fixed and 0 continuous +Cbc0038I Mini branch and bound did not improve solution (48.53 seconds) +Cbc0038I After 48.53 seconds - Feasibility pump exiting with objective of 339992 - took 0.13 seconds +Cbc0012I Integer solution of 339992 found by feasibility pump after 0 iterations and 0 nodes (48.55 seconds) +Cbc0001I Search completed - best objective 339992, took 0 iterations and 0 nodes (48.63 seconds) +Cbc0035I Maximum depth 0, 0 variables fixed on reduced cost +Cuts at root node changed objective from 339992 to 339992 +Probing was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Gomory was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Knapsack was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Clique was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +MixedIntegerRounding2 was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +FlowCover was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +TwoMirCuts was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +ZeroHalf was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) + +Result - Optimal solution found + +Objective value: -339992.00000000 +Enumerated nodes: 0 +Total iterations: 0 +Time (CPU seconds): 48.97 +Time (Wallclock seconds): 49.32 + +Total time (CPU seconds): 48.97 (Wallclock seconds): 49.32 + +Options { input_file_path: "./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_5.c", inputs: None, parties: Some(2), maximize: false } +Done with IR optimization +Converting to aby +Welcome to the CBC MILP Solver +Version: 2.10.3 +Build Date: Mar 24 2020 + +command line - Cbc_C_Interface -solve -quit (default strategy 1) +Continuous objective value is -424992 - 61.73 seconds +Cgl0004I processed model has 100004 rows, 65023 columns (65023 integer (65023 of which binary)) and 295011 elements +Cutoff increment increased from 1e-05 to 0.1999 +Cbc0038I Initial state - 0 integers unsatisfied sum - 0 +Cbc0038I Solution found of 424992 +Cbc0038I Before mini branch and bound, 65023 integers at bound fixed and 0 continuous +Cbc0038I Mini branch and bound did not improve solution (62.58 seconds) +Cbc0038I After 62.58 seconds - Feasibility pump exiting with objective of 424992 - took 0.17 seconds +Cbc0012I Integer solution of 424992 found by feasibility pump after 0 iterations and 0 nodes (62.61 seconds) +Cbc0001I Search completed - best objective 424992, took 0 iterations and 0 nodes (62.71 seconds) +Cbc0035I Maximum depth 0, 0 variables fixed on reduced cost +Cuts at root node changed objective from 424992 to 424992 +Probing was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Gomory was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Knapsack was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Clique was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +MixedIntegerRounding2 was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +FlowCover was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +TwoMirCuts was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +ZeroHalf was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) + +Result - Optimal solution found + +Objective value: -424992.00000000 +Enumerated nodes: 0 +Total iterations: 0 +Time (CPU seconds): 63.16 +Time (Wallclock seconds): 63.62 + +Total time (CPU seconds): 63.16 (Wallclock seconds): 63.62 + +Options { input_file_path: "./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_6.c", inputs: None, parties: Some(2), maximize: false } +Done with IR optimization +Converting to aby +Welcome to the CBC MILP Solver +Version: 2.10.3 +Build Date: Mar 24 2020 + +command line - Cbc_C_Interface -solve -quit (default strategy 1) +Continuous objective value is -509992 - 78.45 seconds +Cgl0004I processed model has 120004 rows, 78023 columns (78023 integer (78023 of which binary)) and 354011 elements +Cutoff increment increased from 1e-05 to 0.1999 +Cbc0038I Initial state - 0 integers unsatisfied sum - 0 +Cbc0038I Solution found of 509992 +Cbc0038I Before mini branch and bound, 78023 integers at bound fixed and 0 continuous +Cbc0038I Mini branch and bound did not improve solution (79.47 seconds) +Cbc0038I After 79.47 seconds - Feasibility pump exiting with objective of 509992 - took 0.18 seconds +Cbc0012I Integer solution of 509992 found by feasibility pump after 0 iterations and 0 nodes (79.50 seconds) +Cbc0001I Search completed - best objective 509992, took 0 iterations and 0 nodes (79.61 seconds) +Cbc0035I Maximum depth 0, 0 variables fixed on reduced cost +Cuts at root node changed objective from 509992 to 509992 +Probing was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Gomory was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Knapsack was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Clique was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +MixedIntegerRounding2 was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +FlowCover was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +TwoMirCuts was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +ZeroHalf was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) + +Result - Optimal solution found + +Objective value: -509992.00000000 +Enumerated nodes: 0 +Total iterations: 0 +Time (CPU seconds): 80.21 +Time (Wallclock seconds): 80.80 + +Total time (CPU seconds): 80.21 (Wallclock seconds): 80.80 + +Options { input_file_path: "./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_7.c", inputs: None, parties: Some(2), maximize: false } +Done with IR optimization +Converting to aby +Welcome to the CBC MILP Solver +Version: 2.10.3 +Build Date: Mar 24 2020 + +command line - Cbc_C_Interface -solve -quit (default strategy 1) +Continuous objective value is -594992 - 138.52 seconds +Cgl0004I processed model has 140004 rows, 91023 columns (91023 integer (91023 of which binary)) and 413011 elements +Cutoff increment increased from 1e-05 to 0.1999 +Cbc0038I Initial state - 0 integers unsatisfied sum - 0 +Cbc0038I Solution found of 594992 +Cbc0038I Before mini branch and bound, 91023 integers at bound fixed and 0 continuous +Cbc0038I Mini branch and bound did not improve solution (139.85 seconds) +Cbc0038I After 139.85 seconds - Feasibility pump exiting with objective of 594992 - took 0.26 seconds +Cbc0012I Integer solution of 594992 found by feasibility pump after 0 iterations and 0 nodes (139.88 seconds) +Cbc0001I Search completed - best objective 594992, took 0 iterations and 0 nodes (140.00 seconds) +Cbc0035I Maximum depth 0, 0 variables fixed on reduced cost +Cuts at root node changed objective from 594992 to 594992 +Probing was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Gomory was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Knapsack was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Clique was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +MixedIntegerRounding2 was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +FlowCover was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +TwoMirCuts was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +ZeroHalf was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) + +Result - Optimal solution found + +Objective value: -594992.00000000 +Enumerated nodes: 0 +Total iterations: 0 +Time (CPU seconds): 140.76 +Time (Wallclock seconds): 141.60 + +Total time (CPU seconds): 140.76 (Wallclock seconds): 141.60 + +Options { input_file_path: "./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_8.c", inputs: None, parties: Some(2), maximize: false } +Done with IR optimization +Converting to aby +Welcome to the CBC MILP Solver +Version: 2.10.3 +Build Date: Mar 24 2020 + +command line - Cbc_C_Interface -solve -quit (default strategy 1) +Continuous objective value is -679992 - 176.22 seconds +Cgl0004I processed model has 160004 rows, 104023 columns (104023 integer (104023 of which binary)) and 472011 elements +Cutoff increment increased from 1e-05 to 0.1999 +Cbc0038I Initial state - 0 integers unsatisfied sum - 0 +Cbc0038I Solution found of 679992 +Cbc0038I Before mini branch and bound, 104023 integers at bound fixed and 0 continuous +Cbc0038I Mini branch and bound did not improve solution (177.73 seconds) +Cbc0038I After 177.73 seconds - Feasibility pump exiting with objective of 679992 - took 0.30 seconds +Cbc0012I Integer solution of 679992 found by feasibility pump after 0 iterations and 0 nodes (177.77 seconds) +Cbc0001I Search completed - best objective 679992, took 0 iterations and 0 nodes (177.94 seconds) +Cbc0035I Maximum depth 0, 0 variables fixed on reduced cost +Cuts at root node changed objective from 679992 to 679992 +Probing was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Gomory was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Knapsack was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Clique was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +MixedIntegerRounding2 was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +FlowCover was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +TwoMirCuts was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +ZeroHalf was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) + +Result - Optimal solution found + +Objective value: -679992.00000000 +Enumerated nodes: 0 +Total iterations: 0 +Time (CPU seconds): 178.93 +Time (Wallclock seconds): 179.74 + +Total time (CPU seconds): 178.93 (Wallclock seconds): 179.74 + +Options { input_file_path: "./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_9.c", inputs: None, parties: Some(2), maximize: false } +Done with IR optimization +Converting to aby +Welcome to the CBC MILP Solver +Version: 2.10.3 +Build Date: Mar 24 2020 + +command line - Cbc_C_Interface -solve -quit (default strategy 1) +Continuous objective value is -764992 - 186.23 seconds +Cgl0004I processed model has 180004 rows, 117023 columns (117023 integer (117023 of which binary)) and 531011 elements +Cutoff increment increased from 1e-05 to 0.1999 +Cbc0038I Initial state - 0 integers unsatisfied sum - 0 +Cbc0038I Solution found of 764992 +Cbc0038I Before mini branch and bound, 117023 integers at bound fixed and 0 continuous +Cbc0038I Mini branch and bound did not improve solution (187.96 seconds) +Cbc0038I After 187.96 seconds - Feasibility pump exiting with objective of 764992 - took 0.34 seconds +Cbc0012I Integer solution of 764992 found by feasibility pump after 0 iterations and 0 nodes (188.01 seconds) +Cbc0001I Search completed - best objective 764992, took 0 iterations and 0 nodes (188.19 seconds) +Cbc0035I Maximum depth 0, 0 variables fixed on reduced cost +Cuts at root node changed objective from 764992 to 764992 +Probing was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Gomory was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Knapsack was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Clique was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +MixedIntegerRounding2 was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +FlowCover was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +TwoMirCuts was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +ZeroHalf was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) + +Result - Optimal solution found + +Objective value: -764992.00000000 +Enumerated nodes: 0 +Total iterations: 0 +Time (CPU seconds): 189.31 +Time (Wallclock seconds): 190.20 + +Total time (CPU seconds): 189.31 (Wallclock seconds): 190.20 + diff --git a/output2.txt b/output2.txt new file mode 100644 index 00000000..c57af760 --- /dev/null +++ b/output2.txt @@ -0,0 +1,351 @@ +Options { input_file_path: "./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_1.c", inputs: None, parties: Some(2), maximize: false } +Done with IR optimization +Converting to aby +Welcome to the CBC MILP Solver +Version: 2.10.3 +Build Date: Mar 24 2020 + +command line - Cbc_C_Interface -solve -quit (default strategy 1) +Continuous objective value is -169992 - 16.54 seconds +Cgl0004I processed model has 40004 rows, 26023 columns (26023 integer (26023 of which binary)) and 118011 elements +Cutoff increment increased from 1e-05 to 0.1999 +Cbc0038I Initial state - 0 integers unsatisfied sum - 0 +Cbc0038I Solution found of 169992 +Cbc0038I Before mini branch and bound, 26023 integers at bound fixed and 0 continuous +Cbc0038I Mini branch and bound did not improve solution (16.81 seconds) +Cbc0038I After 16.81 seconds - Feasibility pump exiting with objective of 169992 - took 0.06 seconds +Cbc0012I Integer solution of 169992 found by feasibility pump after 0 iterations and 0 nodes (16.82 seconds) +Cbc0001I Search completed - best objective 169992, took 0 iterations and 0 nodes (16.85 seconds) +Cbc0035I Maximum depth 0, 0 variables fixed on reduced cost +Cuts at root node changed objective from 169992 to 169992 +Probing was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Gomory was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Knapsack was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Clique was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +MixedIntegerRounding2 was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +FlowCover was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +TwoMirCuts was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +ZeroHalf was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) + +Result - Optimal solution found + +Objective value: -169992.00000000 +Enumerated nodes: 0 +Total iterations: 0 +Time (CPU seconds): 16.98 +Time (Wallclock seconds): 17.14 + +Total time (CPU seconds): 16.98 (Wallclock seconds): 17.14 + +Options { input_file_path: "./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_2.c", inputs: None, parties: Some(2), maximize: false } +Done with IR optimization +Converting to aby +Welcome to the CBC MILP Solver +Version: 2.10.3 +Build Date: Mar 24 2020 + +command line - Cbc_C_Interface -solve -quit (default strategy 1) +Continuous objective value is -339992 - 38.37 seconds +Cgl0004I processed model has 80004 rows, 52023 columns (52023 integer (52023 of which binary)) and 236011 elements +Cutoff increment increased from 1e-05 to 0.1999 +Cbc0038I Initial state - 0 integers unsatisfied sum - 0 +Cbc0038I Solution found of 339992 +Cbc0038I Before mini branch and bound, 52023 integers at bound fixed and 0 continuous +Cbc0038I Mini branch and bound did not improve solution (39.05 seconds) +Cbc0038I After 39.05 seconds - Feasibility pump exiting with objective of 339992 - took 0.13 seconds +Cbc0012I Integer solution of 339992 found by feasibility pump after 0 iterations and 0 nodes (39.06 seconds) +Cbc0001I Search completed - best objective 339992, took 0 iterations and 0 nodes (39.13 seconds) +Cbc0035I Maximum depth 0, 0 variables fixed on reduced cost +Cuts at root node changed objective from 339992 to 339992 +Probing was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Gomory was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Knapsack was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Clique was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +MixedIntegerRounding2 was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +FlowCover was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +TwoMirCuts was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +ZeroHalf was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) + +Result - Optimal solution found + +Objective value: -339992.00000000 +Enumerated nodes: 0 +Total iterations: 0 +Time (CPU seconds): 39.47 +Time (Wallclock seconds): 39.85 + +Total time (CPU seconds): 39.47 (Wallclock seconds): 39.85 + +Options { input_file_path: "./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_3.c", inputs: None, parties: Some(2), maximize: false } +Done with IR optimization +Converting to aby +Welcome to the CBC MILP Solver +Version: 2.10.3 +Build Date: Mar 24 2020 + +command line - Cbc_C_Interface -solve -quit (default strategy 1) +Continuous objective value is -509992 - 81.53 seconds +Cgl0004I processed model has 120004 rows, 78023 columns (78023 integer (78023 of which binary)) and 354011 elements +Cutoff increment increased from 1e-05 to 0.1999 +Cbc0038I Initial state - 0 integers unsatisfied sum - 0 +Cbc0038I Solution found of 509992 +Cbc0038I Before mini branch and bound, 78023 integers at bound fixed and 0 continuous +Cbc0038I Mini branch and bound did not improve solution (82.55 seconds) +Cbc0038I After 82.55 seconds - Feasibility pump exiting with objective of 509992 - took 0.21 seconds +Cbc0012I Integer solution of 509992 found by feasibility pump after 0 iterations and 0 nodes (82.58 seconds) +Cbc0001I Search completed - best objective 509992, took 0 iterations and 0 nodes (82.70 seconds) +Cbc0035I Maximum depth 0, 0 variables fixed on reduced cost +Cuts at root node changed objective from 509992 to 509992 +Probing was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Gomory was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Knapsack was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Clique was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +MixedIntegerRounding2 was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +FlowCover was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +TwoMirCuts was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +ZeroHalf was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) + +Result - Optimal solution found + +Objective value: -509992.00000000 +Enumerated nodes: 0 +Total iterations: 0 +Time (CPU seconds): 83.31 +Time (Wallclock seconds): 83.88 + +Total time (CPU seconds): 83.31 (Wallclock seconds): 83.88 + +Options { input_file_path: "./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_4.c", inputs: None, parties: Some(2), maximize: false } +Done with IR optimization +Converting to aby +Welcome to the CBC MILP Solver +Version: 2.10.3 +Build Date: Mar 24 2020 + +command line - Cbc_C_Interface -solve -quit (default strategy 1) +Continuous objective value is -679992 - 5.17 seconds +Cgl0004I processed model has 160004 rows, 104023 columns (104023 integer (104023 of which binary)) and 472011 elements +Cutoff increment increased from 1e-05 to 0.1999 +Cbc0038I Initial state - 0 integers unsatisfied sum - 0 +Cbc0038I Solution found of 679992 +Cbc0038I Before mini branch and bound, 104023 integers at bound fixed and 0 continuous +Cbc0038I Mini branch and bound did not improve solution (6.63 seconds) +Cbc0038I After 6.63 seconds - Feasibility pump exiting with objective of 679992 - took 0.27 seconds +Cbc0012I Integer solution of 679992 found by feasibility pump after 0 iterations and 0 nodes (6.68 seconds) +Cbc0001I Search completed - best objective 679992, took 0 iterations and 0 nodes (6.85 seconds) +Cbc0035I Maximum depth 0, 0 variables fixed on reduced cost +Cuts at root node changed objective from 679992 to 679992 +Probing was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Gomory was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Knapsack was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Clique was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +MixedIntegerRounding2 was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +FlowCover was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +TwoMirCuts was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +ZeroHalf was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) + +Result - Optimal solution found + +Objective value: -679992.00000000 +Enumerated nodes: 0 +Total iterations: 0 +Time (CPU seconds): 7.43 +Time (Wallclock seconds): 7.89 + +Total time (CPU seconds): 7.43 (Wallclock seconds): 7.89 + +Options { input_file_path: "./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_5.c", inputs: None, parties: Some(2), maximize: false } +Done with IR optimization +Converting to aby +Welcome to the CBC MILP Solver +Version: 2.10.3 +Build Date: Mar 24 2020 + +command line - Cbc_C_Interface -solve -quit (default strategy 1) +Continuous objective value is -849992 - 285.77 seconds +Cgl0004I processed model has 200004 rows, 130023 columns (130023 integer (130023 of which binary)) and 590011 elements +Cutoff increment increased from 1e-05 to 0.1999 +Cbc0038I Initial state - 0 integers unsatisfied sum - 0 +Cbc0038I Solution found of 849992 +Cbc0038I Before mini branch and bound, 130023 integers at bound fixed and 0 continuous +Cbc0038I Mini branch and bound did not improve solution (287.74 seconds) +Cbc0038I After 287.74 seconds - Feasibility pump exiting with objective of 849992 - took 0.39 seconds +Cbc0012I Integer solution of 849992 found by feasibility pump after 0 iterations and 0 nodes (287.79 seconds) +Cbc0001I Search completed - best objective 849992, took 0 iterations and 0 nodes (288.03 seconds) +Cbc0035I Maximum depth 0, 0 variables fixed on reduced cost +Cuts at root node changed objective from 849992 to 849992 +Probing was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Gomory was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Knapsack was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Clique was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +MixedIntegerRounding2 was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +FlowCover was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +TwoMirCuts was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +ZeroHalf was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) + +Result - Optimal solution found + +Objective value: -849992.00000000 +Enumerated nodes: 0 +Total iterations: 0 +Time (CPU seconds): 289.52 +Time (Wallclock seconds): 290.49 + +Total time (CPU seconds): 289.52 (Wallclock seconds): 290.49 + +Options { input_file_path: "./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_6.c", inputs: None, parties: Some(2), maximize: false } +Done with IR optimization +Converting to aby +Welcome to the CBC MILP Solver +Version: 2.10.3 +Build Date: Mar 24 2020 + +command line - Cbc_C_Interface -solve -quit (default strategy 1) +Continuous objective value is -1.01999e+06 - 498.81 seconds +Cgl0004I processed model has 240004 rows, 156023 columns (156023 integer (156023 of which binary)) and 708011 elements +Cutoff increment increased from 1e-05 to 0.1999 +Cbc0038I Initial state - 0 integers unsatisfied sum - 0 +Cbc0038I Solution found of 1.01999e+06 +Cbc0038I Before mini branch and bound, 156023 integers at bound fixed and 0 continuous +Cbc0038I Mini branch and bound did not improve solution (501.69 seconds) +Cbc0038I After 501.69 seconds - Feasibility pump exiting with objective of 1.01999e+06 - took 0.52 seconds +Cbc0012I Integer solution of 1019992 found by feasibility pump after 0 iterations and 0 nodes (501.77 seconds) +Cbc0001I Search completed - best objective 1019992, took 0 iterations and 0 nodes (502.09 seconds) +Cbc0035I Maximum depth 0, 0 variables fixed on reduced cost +Cuts at root node changed objective from 1.01999e+06 to 1.01999e+06 +Probing was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Gomory was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Knapsack was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Clique was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +MixedIntegerRounding2 was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +FlowCover was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +TwoMirCuts was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +ZeroHalf was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) + +Result - Optimal solution found + +Objective value: -1019992.00000000 +Enumerated nodes: 0 +Total iterations: 0 +Time (CPU seconds): 504.09 +Time (Wallclock seconds): 506.03 + +Total time (CPU seconds): 504.09 (Wallclock seconds): 506.03 + +Options { input_file_path: "./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_7.c", inputs: None, parties: Some(2), maximize: false } +Done with IR optimization +Converting to aby +Welcome to the CBC MILP Solver +Version: 2.10.3 +Build Date: Mar 24 2020 + +command line - Cbc_C_Interface -solve -quit (default strategy 1) +Continuous objective value is -1.18999e+06 - 18.77 seconds +Cgl0004I processed model has 280004 rows, 182023 columns (182023 integer (182023 of which binary)) and 826011 elements +Cutoff increment increased from 1e-05 to 0.1999 +Cbc0038I Initial state - 0 integers unsatisfied sum - 0 +Cbc0038I Solution found of 1.18999e+06 +Cbc0038I Before mini branch and bound, 182023 integers at bound fixed and 0 continuous +Cbc0038I Mini branch and bound did not improve solution (21.66 seconds) +Cbc0038I After 21.66 seconds - Feasibility pump exiting with objective of 1.18999e+06 - took 0.57 seconds +Cbc0012I Integer solution of 1189992 found by feasibility pump after 0 iterations and 0 nodes (21.74 seconds) +Cbc0001I Search completed - best objective 1189992, took 0 iterations and 0 nodes (22.04 seconds) +Cbc0035I Maximum depth 0, 0 variables fixed on reduced cost +Cuts at root node changed objective from 1.18999e+06 to 1.18999e+06 +Probing was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Gomory was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Knapsack was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Clique was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +MixedIntegerRounding2 was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +FlowCover was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +TwoMirCuts was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +ZeroHalf was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) + +Result - Optimal solution found + +Objective value: -1189992.00000000 +Enumerated nodes: 0 +Total iterations: 0 +Time (CPU seconds): 23.25 +Time (Wallclock seconds): 24.30 + +Total time (CPU seconds): 23.25 (Wallclock seconds): 24.30 + +Options { input_file_path: "./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_8.c", inputs: None, parties: Some(2), maximize: false } +Done with IR optimization +Converting to aby +Welcome to the CBC MILP Solver +Version: 2.10.3 +Build Date: Mar 24 2020 + +command line - Cbc_C_Interface -solve -quit (default strategy 1) +Continuous objective value is -1.35999e+06 - 1020.30 seconds +Cgl0004I processed model has 320004 rows, 208023 columns (208023 integer (208023 of which binary)) and 944011 elements +Cutoff increment increased from 1e-05 to 0.1999 +Cbc0038I Initial state - 0 integers unsatisfied sum - 0 +Cbc0038I Solution found of 1.35999e+06 +Cbc0038I Before mini branch and bound, 208023 integers at bound fixed and 0 continuous +Cbc0038I Mini branch and bound did not improve solution (1024.39 seconds) +Cbc0038I After 1024.39 seconds - Feasibility pump exiting with objective of 1.35999e+06 - took 0.78 seconds +Cbc0012I Integer solution of 1359992 found by feasibility pump after 0 iterations and 0 nodes (1024.50 seconds) +Cbc0001I Search completed - best objective 1359992, took 0 iterations and 0 nodes (1024.96 seconds) +Cbc0035I Maximum depth 0, 0 variables fixed on reduced cost +Cuts at root node changed objective from 1.35999e+06 to 1.35999e+06 +Probing was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Gomory was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Knapsack was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Clique was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +MixedIntegerRounding2 was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +FlowCover was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +TwoMirCuts was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +ZeroHalf was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) + +Result - Optimal solution found + +Objective value: -1359992.00000000 +Enumerated nodes: 0 +Total iterations: 0 +Time (CPU seconds): 1028.31 +Time (Wallclock seconds): 1032.55 + +Total time (CPU seconds): 1028.31 (Wallclock seconds): 1032.55 + +Options { input_file_path: "./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_9.c", inputs: None, parties: Some(2), maximize: false } +Done with IR optimization +Converting to aby +Welcome to the CBC MILP Solver +Version: 2.10.3 +Build Date: Mar 24 2020 + +command line - Cbc_C_Interface -solve -quit (default strategy 1) +Continuous objective value is -764992 - 309.78 seconds +Cgl0004I processed model has 180004 rows, 117023 columns (117023 integer (117023 of which binary)) and 531011 elements +Cutoff increment increased from 1e-05 to 0.1999 +Cbc0038I Initial state - 0 integers unsatisfied sum - 0 +Cbc0038I Solution found of 764992 +Cbc0038I Before mini branch and bound, 117023 integers at bound fixed and 0 continuous +Cbc0038I Mini branch and bound did not improve solution (311.74 seconds) +Cbc0038I After 311.74 seconds - Feasibility pump exiting with objective of 764992 - took 0.38 seconds +Cbc0012I Integer solution of 764992 found by feasibility pump after 0 iterations and 0 nodes (311.81 seconds) +Cbc0001I Search completed - best objective 764992, took 0 iterations and 0 nodes (312.04 seconds) +Cbc0035I Maximum depth 0, 0 variables fixed on reduced cost +Cuts at root node changed objective from 764992 to 764992 +Probing was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Gomory was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Knapsack was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +Clique was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +MixedIntegerRounding2 was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +FlowCover was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +TwoMirCuts was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) +ZeroHalf was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds) + +Result - Optimal solution found + +Objective value: -764992.00000000 +Enumerated nodes: 0 +Total iterations: 0 +Time (CPU seconds): 313.23 +Time (Wallclock seconds): 314.35 + +Total time (CPU seconds): 313.23 (Wallclock seconds): 314.35 + diff --git a/scripts/aby_tests/c_bench_aby.py b/scripts/aby_tests/c_bench_aby.py new file mode 100755 index 00000000..1ef2fc37 --- /dev/null +++ b/scripts/aby_tests/c_bench_aby.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +from utils import run_tests +from test_suite import * + +if __name__ == "__main__": + tests = [[ + "loop add", + 3, + "./third_party/ABY/build/bin/2pc_loop_add", + {"a": 1, "b": 0}, + {"a": 0, "b": 2}, + ]] + + run_tests('c', tests) diff --git a/scripts/aby_tests/c_test_aby.py b/scripts/aby_tests/c_test_aby.py new file mode 100755 index 00000000..4b4e8640 --- /dev/null +++ b/scripts/aby_tests/c_test_aby.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python + +from utils import run_tests +from test_suite import * + +if __name__ == "__main__": + tests = arithmetic_tests + \ + mod_tests + \ + arithmetic_boolean_tests + \ + nary_arithmetic_tests + \ + bitwise_tests + \ + boolean_tests + \ + nary_boolean_tests + \ + const_arith_tests + \ + const_bool_tests + \ + ite_tests + \ + c_array_tests + \ + div_tests + \ + array_tests + # shift_tests + + # TODO: add support for return value - int promotion + # unsigned_arithmetic_tests + \ + + run_tests('c', tests) diff --git a/scripts/aby_tests/test_suite.py b/scripts/aby_tests/test_suite.py new file mode 100644 index 00000000..ec0a5b3f --- /dev/null +++ b/scripts/aby_tests/test_suite.py @@ -0,0 +1,797 @@ +arithmetic_tests = [ + [ + "Add two numbers - 1", + 3, + "./third_party/ABY/build/bin/2pc_add", + {"a": 1, "b": 0}, + {"a": 0, "b": 2}, + ], + [ + "Add two numbers - 2", + 2, + "./third_party/ABY/build/bin/2pc_add", + {"a": 0, "b": 0}, + {"a": 0, "b": 2}, + ], + [ + "Subtract two numbers", + 1, + "./third_party/ABY/build/bin/2pc_sub", + {"a": 3, "b": 0}, + {"a": 0, "b": 2}, + ], + [ + "Subtract two numbers, negative -1 == 4294967295 because u32", + 4294967295, + "./third_party/ABY/build/bin/2pc_sub", + {"a": 2, "b": 0}, + {"a": 0, "b": 3}, + ], + [ + "Multiply two numbers - 1", + 0, + "./third_party/ABY/build/bin/2pc_mult", + {"a": 0, "b": 0}, + {"a": 0, "b": 5}, + ], + [ + "Multiply two numbers - 2", + 5, + "./third_party/ABY/build/bin/2pc_mult", + {"a": 1, "b": 0}, + {"a": 0, "b": 5}, + ], + [ + "Multiply two numbers - 3", + 10, + "./third_party/ABY/build/bin/2pc_mult", + {"a": 2, "b": 0}, + {"a": 0, "b": 5}, + ], + [ + # only server side public value works + "Multiply two numbers together and add with public value", + 42, + "./third_party/ABY/build/bin/2pc_mult_add_pub", + {"a": 5, "b": 0, "v": 7}, + {"a": 0, "b": 7, "v": 7}, + ], + [ + # only server side public value works + "Multiply two numbers together and add with public value, check only server side public value is added", + 42, + "./third_party/ABY/build/bin/2pc_mult_add_pub", + {"a": 5, "b": 0, "v": 7}, + {"a": 0, "b": 7, "v": 0}, + ], +] + +mod_tests = [ + [ + "Mod two numbers - 1", + 0, + "./third_party/ABY/build/bin/2pc_mod", + {"a": 0, "b": 0}, + {"a": 0, "b": 2}, + ], + [ + "Mod two numbers - 2", + 1, + "./third_party/ABY/build/bin/2pc_mod", + {"a": 1, "b": 0}, + {"a": 0, "b": 2}, + ], + [ + "Mod two numbers - 3", + 0, + "./third_party/ABY/build/bin/2pc_mod", + {"a": 2, "b": 0}, + {"a": 0, "b": 2}, + ], +] + +unsigned_arithmetic_tests = [ + [ + "Add two unsigned numbers - 1", + 3, + "./third_party/ABY/build/bin/2pc_add_unsigned", + {"a": 1, "b": 0}, + {"a": 0, "b": 2}, + ], +] + +arithmetic_boolean_tests = [ + [ + "Test two numbers are equal - 1", + 0, + "./third_party/ABY/build/bin/2pc_int_equals", + {"a": 5, "b": 0}, + {"a": 0, "b": 7}, + ], + [ + "Test two numbers are equal - 2", + 1, + "./third_party/ABY/build/bin/2pc_int_equals", + {"a": 7, "b": 0}, + {"a": 0, "b": 7}, + ], + [ + "Test int > int - 1", + 0, + "./third_party/ABY/build/bin/2pc_int_greater_than", + {"a": 5, "b": 0}, + {"a": 0, "b": 7}, + ], + [ + "Test int > int - 2", + 0, + "./third_party/ABY/build/bin/2pc_int_greater_than", + {"a": 7, "b": 0}, + {"a": 0, "b": 7}, + ], + [ + "Test int > int - 3", + 1, + "./third_party/ABY/build/bin/2pc_int_greater_than", + {"a": 8, "b": 0}, + {"a": 0, "b": 7}, + ], + [ + "Test int >= int - 1", + 1, + "./third_party/ABY/build/bin/2pc_int_greater_equals", + {"a": 8, "b": 0}, + {"a": 0, "b": 7}, + ], + [ + "Test int >= int - 2", + 1, + "./third_party/ABY/build/bin/2pc_int_greater_equals", + {"a": 7, "b": 0}, + {"a": 0, "b": 7}, + ], + [ + "Test int >= int - 3", + 0, + "./third_party/ABY/build/bin/2pc_int_greater_equals", + {"a": 6, "b": 0}, + {"a": 0, "b": 7}, + ], + [ + "Test int < int - 1", + 0, + "./third_party/ABY/build/bin/2pc_int_less_than", + {"a": 7, "b": 0}, + {"a": 0, "b": 2}, + ], + [ + "Test int < int - 2", + 0, + "./third_party/ABY/build/bin/2pc_int_less_than", + {"a": 7, "b": 0}, + {"a": 0, "b": 7}, + ], + [ + "Test int < int - 3", + 1, + "./third_party/ABY/build/bin/2pc_int_less_than", + {"a": 2, "b": 0}, + {"a": 0, "b": 7}, + ], + [ + "Test int <= int - 1", + 1, + "./third_party/ABY/build/bin/2pc_int_less_equals", + {"a": 7, "b": 0}, + {"a": 0, "b": 8}, + ], + [ + "Test int <= int - 2", + 1, + "./third_party/ABY/build/bin/2pc_int_less_equals", + {"a": 7, "b": 0}, + {"a": 0, "b": 7}, + ], + [ + "Test int <= int - 3", + 0, + "./third_party/ABY/build/bin/2pc_int_less_equals", + {"a": 8, "b": 0}, + {"a": 0, "b": 7}, + ], + [ + "Test int == int - 1", + 0, + "./third_party/ABY/build/bin/2pc_int_equals", + {"a": 7, "b": 0}, + {"a": 0, "b": 8}, + ], + [ + "Test int == int - 2", + 1, + "./third_party/ABY/build/bin/2pc_int_equals", + {"a": 12, "b": 0}, + {"a": 0, "b": 12}, + ], +] + +nary_arithmetic_tests = [ + [ + "Test a + b + c", + 6, + "./third_party/ABY/build/bin/2pc_nary_arithmetic_add", + {"a": 1, "b": 0, "c": 0}, + {"a": 0, "b": 2, "c": 3}, + ], +] + +bitwise_tests = [ + [ + "Bitwise & - 1", + 0, + "./third_party/ABY/build/bin/2pc_bitwise_and", + {"a": 0, "b": 0}, + {"a": 0, "b": 0}, + ], + [ + "Bitwise & - 2", + 0, + "./third_party/ABY/build/bin/2pc_bitwise_and", + {"a": 1, "b": 0}, + {"a": 0, "b": 0}, + ], + [ + "Bitwise & - 3", + 0, + "./third_party/ABY/build/bin/2pc_bitwise_and", + {"a": 0, "b": 0}, + {"a": 0, "b": 1}, + ], + [ + "Bitwise & - 4", + 1, + "./third_party/ABY/build/bin/2pc_bitwise_and", + {"a": 1, "b": 0}, + {"a": 0, "b": 1}, + ], + [ + "Bitwise | - 1", + 0, + "./third_party/ABY/build/bin/2pc_bitwise_or", + {"a": 0, "b": 0}, + {"a": 0, "b": 0}, + ], + [ + "Bitwise | - 2", + 1, + "./third_party/ABY/build/bin/2pc_bitwise_or", + {"a": 1, "b": 0}, + {"a": 0, "b": 0}, + ], + [ + "Bitwise | - 3", + 1, + "./third_party/ABY/build/bin/2pc_bitwise_or", + {"a": 0, "b": 0}, + {"a": 0, "b": 1}, + ], + [ + "Bitwise | - 4", + 1, + "./third_party/ABY/build/bin/2pc_bitwise_or", + {"a": 1, "b": 0}, + {"a": 0, "b": 1}, + ], + [ + "Bitwise ^ - 1", + 0, + "./third_party/ABY/build/bin/2pc_bitwise_xor", + {"a": 0, "b": 0}, + {"a": 0, "b": 0}, + ], + [ + "Bitwise ^ - 2", + 1, + "./third_party/ABY/build/bin/2pc_bitwise_xor", + {"a": 1, "b": 0}, + {"a": 0, "b": 0}, + ], + [ + "Bitwise ^ - 3", + 1, + "./third_party/ABY/build/bin/2pc_bitwise_xor", + {"a": 0, "b": 0}, + {"a": 0, "b": 1}, + ], + [ + "Bitwise ^ - 4", + 0, + "./third_party/ABY/build/bin/2pc_bitwise_xor", + {"a": 1, "b": 0}, + {"a": 0, "b": 1}, + ], +] + +boolean_tests = [ + [ + "Boolean && - 1", + 0, + "./third_party/ABY/build/bin/2pc_boolean_and", + {"a": 0, "b": 0}, + {"a": 0, "b": 0}, + ], + [ + "Boolean && - 2", + 0, + "./third_party/ABY/build/bin/2pc_boolean_and", + {"a": 1, "b": 0}, + {"a": 0, "b": 0}, + ], + [ + "Boolean && - 3", + 0, + "./third_party/ABY/build/bin/2pc_boolean_and", + {"a": 0, "b": 0}, + {"a": 0, "b": 1}, + ], + [ + "Boolean && - 4", + 1, + "./third_party/ABY/build/bin/2pc_boolean_and", + {"a": 1, "b": 0}, + {"a": 0, "b": 1}, + ], + [ + "Boolean || - 1", + 0, + "./third_party/ABY/build/bin/2pc_boolean_or", + {"a": 0, "b": 0}, + {"a": 0, "b": 0}, + ], + [ + "Boolean || - 2", + 1, + "./third_party/ABY/build/bin/2pc_boolean_or", + {"a": 1, "b": 0}, + {"a": 0, "b": 0}, + ], + [ + "Boolean || - 3", + 1, + "./third_party/ABY/build/bin/2pc_boolean_or", + {"a": 0, "b": 0}, + {"a": 0, "b": 1}, + ], + [ + "Boolean || - 4", + 1, + "./third_party/ABY/build/bin/2pc_boolean_or", + {"a": 1, "b": 0}, + {"a": 0, "b": 1}, + ], + [ + "Boolean == - 1", + 0, + "./third_party/ABY/build/bin/2pc_boolean_equals", + {"a": 0, "b": 0}, + {"a": 0, "b": 1}, + ], + [ + "Boolean == - 2", + 1, + "./third_party/ABY/build/bin/2pc_boolean_equals", + {"a": 1, "b": 0}, + {"a": 0, "b": 1}, + ], +] + +nary_boolean_tests = [ + [ + "Test a & b & c - 1", + 0, + "./third_party/ABY/build/bin/2pc_nary_boolean_and", + {"a": 1, "b": 0, "c": 0}, + {"a": 0, "b": 1, "c": 0}, + ], + [ + "Test a & b & c - 2", + 1, + "./third_party/ABY/build/bin/2pc_nary_boolean_and", + {"a": 1, "b": 0, "c": 0}, + {"a": 0, "b": 1, "c": 1}, + ], +] + + +const_arith_tests = [ + [ + "Test add client int + server int to const value", + 6, + "./third_party/ABY/build/bin/2pc_const_arith", + {"a": 2, "b": 0}, + {"a": 0, "b": 3}, + ], +] + +const_bool_tests = [ + [ + "Test server value == const value - 1", + 0, + "./third_party/ABY/build/bin/2pc_const_bool", + {"a": 0, "b": 0}, + {"a": 0, "b": 0}, + ], + [ + "Test server value == const value - 2", + 1, + "./third_party/ABY/build/bin/2pc_const_bool", + {"a": 1, "b": 0}, + {"a": 0, "b": 0}, + ], +] + +ite_tests = [ + [ + "Test ite ret bool - 1", + 0, + "./third_party/ABY/build/bin/2pc_ite_ret_bool", + {"a": 0, "b": 0, "sel": 1}, + {"a": 0, "b": 1, "sel": 1}, + ], + [ + "Test ite ret bool - 2", + 1, + "./third_party/ABY/build/bin/2pc_ite_ret_bool", + {"a": 0, "b": 0, "sel": 0}, + {"a": 0, "b": 1, "sel": 0}, + ], + [ + "Test ite ret int - 1", + 32, + "./third_party/ABY/build/bin/2pc_ite_ret_int", + {"a": 32, "b": 0, "sel": 1}, + {"a": 0, "b": 45, "sel": 1}, + ], + [ + "Test ite ret int - 2", + 45, + "./third_party/ABY/build/bin/2pc_ite_ret_int", + {"a": 32, "b": 0, "sel": 0}, + {"a": 0, "b": 45, "sel": 0}, + ], + [ + "Test ite only if - 1", + 32, + "./third_party/ABY/build/bin/2pc_ite_ret_int", + {"a": 32, "b": 0, "sel": 1}, + {"a": 0, "b": 45, "sel": 1}, + ], + [ + "Test ite only if - 2", + 45, + "./third_party/ABY/build/bin/2pc_ite_ret_int", + {"a": 32, "b": 0, "sel": 0}, + {"a": 0, "b": 45, "sel": 0}, + ], +] + +array_tests = [ + [ + "Array sum test", + 3, + "./third_party/ABY/build/bin/2pc_array_sum", + {"a": 2, "b": 0}, + {"a": 0, "b": 1}, + ], + [ + "Array index test", + 3, + "./third_party/ABY/build/bin/2pc_array_index", + {"a": 2, "b": 0}, + {"a": 0, "b": 1}, + ], + [ + "Array index test 2", + 2, + "./third_party/ABY/build/bin/2pc_array_index_2", + {"a": 2, "b": 0}, + {"a": 0, "b": 1}, + ], + # [ + # "Array ret test", + # "2\n1", + # "./third_party/ABY/build/bin/2pc_array_ret", + # {"a": 2, "b": 0}, + # {"a": 0, "b": 1}, + # ], +] + +c_array_tests = [ + [ + "C array test", + 2, + "./third_party/ABY/build/bin/2pc_array", + {"a": 2, "b": 0}, + {"a": 0, "b": 2}, + ], + [ + "C array test 1", + 17, + "./third_party/ABY/build/bin/2pc_array_1", + {"a": 10, "b": 0}, + {"a": 0, "b": 3}, + ], + [ + "C array test 2", + 17, + "./third_party/ABY/build/bin/2pc_array_2", + {"a": 10, "b": 0}, + {"a": 0, "b": 3}, + ], + [ + "C array test 3", + 18, + "./third_party/ABY/build/bin/2pc_array_3", + {"a": 2, "b": 0}, + {"a": 0, "b": 3}, + ], + [ + "C array test 3", + 30, + "./third_party/ABY/build/bin/2pc_array_sum_c", + {"a": [1,2,3,4,5], "b": 7}, + {"a": 6, "b": [1,2,3,4,5]}, + ], +] + +loop_tests = [ + [ + "Loop sum const - 1", + 10, + "./third_party/ABY/build/bin/2pc_loop_sum", + {"a": 2, "b": 0}, + {"a": 0, "b": 1}, + ], + [ + "Loop sum const - 2", + 10, + "./third_party/ABY/build/bin/2pc_loop_sum", + {"a": 10, "b": 0}, + {"a": 0, "b": 3}, + ], +] + +function_tests = [ + [ + "Sum() two numbers - 1", + 3, + "./third_party/ABY/build/bin/2pc_function_sum", + {"a": 1, "b": 0}, + {"a": 0, "b": 2}, + ], + [ + "Sum() two numbers - 2", + 2, + "./third_party/ABY/build/bin/2pc_function_sum", + {"a": 0, "b": 0}, + {"a": 0, "b": 2}, + ], + +] + +shift_tests = [ + [ + "Left Shift a by 1 - 1", + 20, + "./third_party/ABY/build/bin/2pc_lhs", + {"a": 10, "b": 0}, + {"a": 0, "b": 2}, + ], + [ + "Left Shift a by 1 - 2", + 0, + "./third_party/ABY/build/bin/2pc_lhs", + {"a": 0, "b": 0}, + {"a": 0, "b": 2}, + ], + [ + "Left Shift a by 1 - 3", + 0, + "./third_party/ABY/build/bin/2pc_lhs", + {"a": 2147483648, "b": 0}, + {"a": 0, "b": 2}, + ], + [ + "Right Shift a by 1 - 1", + 10, + "./third_party/ABY/build/bin/2pc_rhs", + {"a": 20, "b": 0}, + {"a": 0, "b": 2}, + ], + [ + "Right Shift a by 1 - 2", + 0, + "./third_party/ABY/build/bin/2pc_rhs", + {"a": 0, "b": 0}, + {"a": 0, "b": 2}, + ], +] + + +div_tests = [ + [ + "Divide a by 1", + 10, + "./third_party/ABY/build/bin/2pc_div", + {"a": 10, "b": 0}, + {"a": 0, "b": 1}, + ], + [ + "Divide a by b - 1", + 5, + "./third_party/ABY/build/bin/2pc_div", + {"a": 10, "b": 0}, + {"a": 0, "b": 2}, + ], + [ + "Divide a by b - 2", + 5, + "./third_party/ABY/build/bin/2pc_div", + {"a": 11, "b": 0}, + {"a": 0, "b": 2}, + ], + [ + "Divide a by b - 3", + 0, + "./third_party/ABY/build/bin/2pc_div", + {"a": 49, "b": 0}, + {"a": 0, "b": 50}, + ], +] + +misc_tests = [ + [ + "Millionaire's problem: server has more money than client", + 0, + "./third_party/ABY/build/bin/2pc_millionaire", + {"a": 2, "b": 0}, + {"a": 0, "b": 1}, + ], + [ + "Millionaire's problem: server has equal money to client", + 0, + "./third_party/ABY/build/bin/2pc_millionaire", + {"a": 1, "b": 0}, + {"a": 0, "b": 1}, + ], + [ + "Millionaire's problem: server has less money than client", + 1, + "./third_party/ABY/build/bin/2pc_millionaire", + {"a": 1, "b": 0}, + {"a": 0, "b": 2}, + ], + [ + "Conversion problem", + 7, + "./third_party/ABY/build/bin/2pc_conv", + {"a": 0, "b": 0}, + {"a": 0, "b": 7}, + ], +] + +kmeans_tests = [ + [ + "kmeans", + 103, + "./third_party/ABY/build/bin/2pc_kmeans", + {"a": [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19], "b": [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]}, + {"a": [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19], "b": [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]}, + # {"a": [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99], "b": 0}, + # {"a": 0, "b": [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99]}, + ], +] + +biomatch_tests = [ + [ + "biomatch - 1", + 14, + "./third_party/ABY/build/bin/2pc_biomatch", + {"db": [0,1,2,3,1,2,3,4,2,3,4,5,3,4,5,6,4,5,6,7,5,6,7,8,6,7,8,9,7,8,9,10,8,9,10,11,9,10,11,12,10,11,12,13,11,12,13,14,12,13,14,15,13,14,15,16,14,15,16,17,15,16,17,18,16,17,18,19,17,18,19,20,18,19,20,21,19,20,21,22,20,21,22,23,21,22,23,24,22,23,24,25,23,24,25,26,24,25,26,27,25,26,27,28,26,27,28,29,27,28,29,30,28,29,30,31,29,30,31,32,30,31,32,33,31,32,33,34,32,33,34,35,33,34,35,36,34,35,36,37,35,36,37,38,36,37,38,39,37,38,39,40,38,39,40,41,39,40,41,42,40,41,42,43,41,42,43,44,42,43,44,45,43,44,45,46,44,45,46,47,45,46,47,48,46,47,48,49,47,48,49,50,48,49,50,51,49,50,51,52,50,51,52,53,51,52,53,54,52,53,54,55,53,54,55,56,54,55,56,57,55,56,57,58,56,57,58,59,57,58,59,60,58,59,60,61,59,60,61,62,60,61,62,63,61,62,63,64,62,63,64,65,63,64,65,66,64,65,66,67,65,66,67,68,66,67,68,69,67,68,69,70,68,69,70,71,69,70,71,72,70,71,72,73,71,72,73,74,72,73,74,75,73,74,75,76,74,75,76,77,75,76,77,78,76,77,78,79,77,78,79,80,78,79,80,81,79,80,81,82,80,81,82,83,81,82,83,84,82,83,84,85,83,84,85,86,84,85,86,87,85,86,87,88,86,87,88,89,87,88,89,90,88,89,90,91,89,90,91,92,90,91,92,93,91,92,93,94,92,93,94,95,93,94,95,96,94,95,96,97,95,96,97,98,96,97,98,99,97,98,99,100,98,99,100,101,99,100,101,102,100,101,102,103,101,102,103,104,102,103,104,105,103,104,105,106,104,105,106,107,105,106,107,108,106,107,108,109,107,108,109,110,108,109,110,111,109,110,111,112,110,111,112,113,111,112,113,114,112,113,114,115,113,114,115,116,114,115,116,117,115,116,117,118,116,117,118,119,117,118,119,120,118,119,120,121,119,120,121,122,120,121,122,123,121,122,123,124,122,123,124,125,123,124,125,126,124,125,126,127,125,126,127,128,126,127,128,129,127,128,129,130,128,129,130,131,129,130,131,132,130,131,132,133,131,132,133,134,132,133,134,135,133,134,135,136,134,135,136,137,135,136,137,138,136,137,138,139,137,138,139,140,138,139,140,141,139,140,141,142,140,141,142,143,141,142,143,144,142,143,144,145,143,144,145,146,144,145,146,147,145,146,147,148,146,147,148,149,147,148,149,150,148,149,150,151,149,150,151,152,150,151,152,153,151,152,153,154,152,153,154,155,153,154,155,156,154,155,156,157,155,156,157,158,156,157,158,159,157,158,159,160,158,159,160,161,159,160,161,162,160,161,162,163,161,162,163,164,162,163,164,165,163,164,165,166,164,165,166,167,165,166,167,168,166,167,168,169,167,168,169,170,168,169,170,171,169,170,171,172,170,171,172,173,171,172,173,174,172,173,174,175,173,174,175,176,174,175,176,177,175,176,177,178,176,177,178,179,177,178,179,180,178,179,180,181,179,180,181,182,180,181,182,183,181,182,183,184,182,183,184,185,183,184,185,186,184,185,186,187,185,186,187,188,186,187,188,189,187,188,189,190,188,189,190,191,189,190,191,192,190,191,192,193,191,192,193,194,192,193,194,195,193,194,195,196,194,195,196,197,195,196,197,198,196,197,198,199,197,198,199,200,198,199,200,201,199,200,201,202,200,201,202,203,201,202,203,204,202,203,204,205,203,204,205,206,204,205,206,207,205,206,207,208,206,207,208,209,207,208,209,210,208,209,210,211,209,210,211,212,210,211,212,213,211,212,213,214,212,213,214,215,213,214,215,216,214,215,216,217,215,216,217,218,216,217,218,219,217,218,219,220,218,219,220,221,219,220,221,222,220,221,222,223,221,222,223,224,222,223,224,225,223,224,225,226,224,225,226,227,225,226,227,228,226,227,228,229,227,228,229,230,228,229,230,231,229,230,231,232,230,231,232,233,231,232,233,234,232,233,234,235,233,234,235,236,234,235,236,237,235,236,237,238,236,237,238,239,237,238,239,240,238,239,240,241,239,240,241,242,240,241,242,243,241,242,243,244,242,243,244,245,243,244,245,246,244,245,246,247,245,246,247,248,246,247,248,249,247,248,249,250,248,249,250,251,249,250,251,252,250,251,252,253,251,252,253,254,252,253,254,255,253,254,255,256,254,255,256,257,255,256,257,258], "sample": [0,0,0,0]}, + {"db": [0,1,2,3,1,2,3,4,2,3,4,5,3,4,5,6,4,5,6,7,5,6,7,8,6,7,8,9,7,8,9,10,8,9,10,11,9,10,11,12,10,11,12,13,11,12,13,14,12,13,14,15,13,14,15,16,14,15,16,17,15,16,17,18,16,17,18,19,17,18,19,20,18,19,20,21,19,20,21,22,20,21,22,23,21,22,23,24,22,23,24,25,23,24,25,26,24,25,26,27,25,26,27,28,26,27,28,29,27,28,29,30,28,29,30,31,29,30,31,32,30,31,32,33,31,32,33,34,32,33,34,35,33,34,35,36,34,35,36,37,35,36,37,38,36,37,38,39,37,38,39,40,38,39,40,41,39,40,41,42,40,41,42,43,41,42,43,44,42,43,44,45,43,44,45,46,44,45,46,47,45,46,47,48,46,47,48,49,47,48,49,50,48,49,50,51,49,50,51,52,50,51,52,53,51,52,53,54,52,53,54,55,53,54,55,56,54,55,56,57,55,56,57,58,56,57,58,59,57,58,59,60,58,59,60,61,59,60,61,62,60,61,62,63,61,62,63,64,62,63,64,65,63,64,65,66,64,65,66,67,65,66,67,68,66,67,68,69,67,68,69,70,68,69,70,71,69,70,71,72,70,71,72,73,71,72,73,74,72,73,74,75,73,74,75,76,74,75,76,77,75,76,77,78,76,77,78,79,77,78,79,80,78,79,80,81,79,80,81,82,80,81,82,83,81,82,83,84,82,83,84,85,83,84,85,86,84,85,86,87,85,86,87,88,86,87,88,89,87,88,89,90,88,89,90,91,89,90,91,92,90,91,92,93,91,92,93,94,92,93,94,95,93,94,95,96,94,95,96,97,95,96,97,98,96,97,98,99,97,98,99,100,98,99,100,101,99,100,101,102,100,101,102,103,101,102,103,104,102,103,104,105,103,104,105,106,104,105,106,107,105,106,107,108,106,107,108,109,107,108,109,110,108,109,110,111,109,110,111,112,110,111,112,113,111,112,113,114,112,113,114,115,113,114,115,116,114,115,116,117,115,116,117,118,116,117,118,119,117,118,119,120,118,119,120,121,119,120,121,122,120,121,122,123,121,122,123,124,122,123,124,125,123,124,125,126,124,125,126,127,125,126,127,128,126,127,128,129,127,128,129,130,128,129,130,131,129,130,131,132,130,131,132,133,131,132,133,134,132,133,134,135,133,134,135,136,134,135,136,137,135,136,137,138,136,137,138,139,137,138,139,140,138,139,140,141,139,140,141,142,140,141,142,143,141,142,143,144,142,143,144,145,143,144,145,146,144,145,146,147,145,146,147,148,146,147,148,149,147,148,149,150,148,149,150,151,149,150,151,152,150,151,152,153,151,152,153,154,152,153,154,155,153,154,155,156,154,155,156,157,155,156,157,158,156,157,158,159,157,158,159,160,158,159,160,161,159,160,161,162,160,161,162,163,161,162,163,164,162,163,164,165,163,164,165,166,164,165,166,167,165,166,167,168,166,167,168,169,167,168,169,170,168,169,170,171,169,170,171,172,170,171,172,173,171,172,173,174,172,173,174,175,173,174,175,176,174,175,176,177,175,176,177,178,176,177,178,179,177,178,179,180,178,179,180,181,179,180,181,182,180,181,182,183,181,182,183,184,182,183,184,185,183,184,185,186,184,185,186,187,185,186,187,188,186,187,188,189,187,188,189,190,188,189,190,191,189,190,191,192,190,191,192,193,191,192,193,194,192,193,194,195,193,194,195,196,194,195,196,197,195,196,197,198,196,197,198,199,197,198,199,200,198,199,200,201,199,200,201,202,200,201,202,203,201,202,203,204,202,203,204,205,203,204,205,206,204,205,206,207,205,206,207,208,206,207,208,209,207,208,209,210,208,209,210,211,209,210,211,212,210,211,212,213,211,212,213,214,212,213,214,215,213,214,215,216,214,215,216,217,215,216,217,218,216,217,218,219,217,218,219,220,218,219,220,221,219,220,221,222,220,221,222,223,221,222,223,224,222,223,224,225,223,224,225,226,224,225,226,227,225,226,227,228,226,227,228,229,227,228,229,230,228,229,230,231,229,230,231,232,230,231,232,233,231,232,233,234,232,233,234,235,233,234,235,236,234,235,236,237,235,236,237,238,236,237,238,239,237,238,239,240,238,239,240,241,239,240,241,242,240,241,242,243,241,242,243,244,242,243,244,245,243,244,245,246,244,245,246,247,245,246,247,248,246,247,248,249,247,248,249,250,248,249,250,251,249,250,251,252,250,251,252,253,251,252,253,254,252,253,254,255,253,254,255,256,254,255,256,257,255,256,257,258], "sample": [0,0,0,0]} + ], + [ + "biomatch - 2", + 0, + "./third_party/ABY/build/bin/2pc_biomatch", + {"db": [0,1,2,3,1,2,3,4,2,3,4,5,3,4,5,6,4,5,6,7,5,6,7,8,6,7,8,9,7,8,9,10,8,9,10,11,9,10,11,12,10,11,12,13,11,12,13,14,12,13,14,15,13,14,15,16,14,15,16,17,15,16,17,18,16,17,18,19,17,18,19,20,18,19,20,21,19,20,21,22,20,21,22,23,21,22,23,24,22,23,24,25,23,24,25,26,24,25,26,27,25,26,27,28,26,27,28,29,27,28,29,30,28,29,30,31,29,30,31,32,30,31,32,33,31,32,33,34,32,33,34,35,33,34,35,36,34,35,36,37,35,36,37,38,36,37,38,39,37,38,39,40,38,39,40,41,39,40,41,42,40,41,42,43,41,42,43,44,42,43,44,45,43,44,45,46,44,45,46,47,45,46,47,48,46,47,48,49,47,48,49,50,48,49,50,51,49,50,51,52,50,51,52,53,51,52,53,54,52,53,54,55,53,54,55,56,54,55,56,57,55,56,57,58,56,57,58,59,57,58,59,60,58,59,60,61,59,60,61,62,60,61,62,63,61,62,63,64,62,63,64,65,63,64,65,66,64,65,66,67,65,66,67,68,66,67,68,69,67,68,69,70,68,69,70,71,69,70,71,72,70,71,72,73,71,72,73,74,72,73,74,75,73,74,75,76,74,75,76,77,75,76,77,78,76,77,78,79,77,78,79,80,78,79,80,81,79,80,81,82,80,81,82,83,81,82,83,84,82,83,84,85,83,84,85,86,84,85,86,87,85,86,87,88,86,87,88,89,87,88,89,90,88,89,90,91,89,90,91,92,90,91,92,93,91,92,93,94,92,93,94,95,93,94,95,96,94,95,96,97,95,96,97,98,96,97,98,99,97,98,99,100,98,99,100,101,99,100,101,102,100,101,102,103,101,102,103,104,102,103,104,105,103,104,105,106,104,105,106,107,105,106,107,108,106,107,108,109,107,108,109,110,108,109,110,111,109,110,111,112,110,111,112,113,111,112,113,114,112,113,114,115,113,114,115,116,114,115,116,117,115,116,117,118,116,117,118,119,117,118,119,120,118,119,120,121,119,120,121,122,120,121,122,123,121,122,123,124,122,123,124,125,123,124,125,126,124,125,126,127,125,126,127,128,126,127,128,129,127,128,129,130,128,129,130,131,129,130,131,132,130,131,132,133,131,132,133,134,132,133,134,135,133,134,135,136,134,135,136,137,135,136,137,138,136,137,138,139,137,138,139,140,138,139,140,141,139,140,141,142,140,141,142,143,141,142,143,144,142,143,144,145,143,144,145,146,144,145,146,147,145,146,147,148,146,147,148,149,147,148,149,150,148,149,150,151,149,150,151,152,150,151,152,153,151,152,153,154,152,153,154,155,153,154,155,156,154,155,156,157,155,156,157,158,156,157,158,159,157,158,159,160,158,159,160,161,159,160,161,162,160,161,162,163,161,162,163,164,162,163,164,165,163,164,165,166,164,165,166,167,165,166,167,168,166,167,168,169,167,168,169,170,168,169,170,171,169,170,171,172,170,171,172,173,171,172,173,174,172,173,174,175,173,174,175,176,174,175,176,177,175,176,177,178,176,177,178,179,177,178,179,180,178,179,180,181,179,180,181,182,180,181,182,183,181,182,183,184,182,183,184,185,183,184,185,186,184,185,186,187,185,186,187,188,186,187,188,189,187,188,189,190,188,189,190,191,189,190,191,192,190,191,192,193,191,192,193,194,192,193,194,195,193,194,195,196,194,195,196,197,195,196,197,198,196,197,198,199,197,198,199,200,198,199,200,201,199,200,201,202,200,201,202,203,201,202,203,204,202,203,204,205,203,204,205,206,204,205,206,207,205,206,207,208,206,207,208,209,207,208,209,210,208,209,210,211,209,210,211,212,210,211,212,213,211,212,213,214,212,213,214,215,213,214,215,216,214,215,216,217,215,216,217,218,216,217,218,219,217,218,219,220,218,219,220,221,219,220,221,222,220,221,222,223,221,222,223,224,222,223,224,225,223,224,225,226,224,225,226,227,225,226,227,228,226,227,228,229,227,228,229,230,228,229,230,231,229,230,231,232,230,231,232,233,231,232,233,234,232,233,234,235,233,234,235,236,234,235,236,237,235,236,237,238,236,237,238,239,237,238,239,240,238,239,240,241,239,240,241,242,240,241,242,243,241,242,243,244,242,243,244,245,243,244,245,246,244,245,246,247,245,246,247,248,246,247,248,249,247,248,249,250,248,249,250,251,249,250,251,252,250,251,252,253,251,252,253,254,252,253,254,255,253,254,255,256,254,255,256,257,255,256,257,258], "sample": [0,0,0,0]}, + {"db": [0,1,2,3,1,2,3,4,2,3,4,5,3,4,5,6,4,5,6,7,5,6,7,8,6,7,8,9,7,8,9,10,8,9,10,11,9,10,11,12,10,11,12,13,11,12,13,14,12,13,14,15,13,14,15,16,14,15,16,17,15,16,17,18,16,17,18,19,17,18,19,20,18,19,20,21,19,20,21,22,20,21,22,23,21,22,23,24,22,23,24,25,23,24,25,26,24,25,26,27,25,26,27,28,26,27,28,29,27,28,29,30,28,29,30,31,29,30,31,32,30,31,32,33,31,32,33,34,32,33,34,35,33,34,35,36,34,35,36,37,35,36,37,38,36,37,38,39,37,38,39,40,38,39,40,41,39,40,41,42,40,41,42,43,41,42,43,44,42,43,44,45,43,44,45,46,44,45,46,47,45,46,47,48,46,47,48,49,47,48,49,50,48,49,50,51,49,50,51,52,50,51,52,53,51,52,53,54,52,53,54,55,53,54,55,56,54,55,56,57,55,56,57,58,56,57,58,59,57,58,59,60,58,59,60,61,59,60,61,62,60,61,62,63,61,62,63,64,62,63,64,65,63,64,65,66,64,65,66,67,65,66,67,68,66,67,68,69,67,68,69,70,68,69,70,71,69,70,71,72,70,71,72,73,71,72,73,74,72,73,74,75,73,74,75,76,74,75,76,77,75,76,77,78,76,77,78,79,77,78,79,80,78,79,80,81,79,80,81,82,80,81,82,83,81,82,83,84,82,83,84,85,83,84,85,86,84,85,86,87,85,86,87,88,86,87,88,89,87,88,89,90,88,89,90,91,89,90,91,92,90,91,92,93,91,92,93,94,92,93,94,95,93,94,95,96,94,95,96,97,95,96,97,98,96,97,98,99,97,98,99,100,98,99,100,101,99,100,101,102,100,101,102,103,101,102,103,104,102,103,104,105,103,104,105,106,104,105,106,107,105,106,107,108,106,107,108,109,107,108,109,110,108,109,110,111,109,110,111,112,110,111,112,113,111,112,113,114,112,113,114,115,113,114,115,116,114,115,116,117,115,116,117,118,116,117,118,119,117,118,119,120,118,119,120,121,119,120,121,122,120,121,122,123,121,122,123,124,122,123,124,125,123,124,125,126,124,125,126,127,125,126,127,128,126,127,128,129,127,128,129,130,128,129,130,131,129,130,131,132,130,131,132,133,131,132,133,134,132,133,134,135,133,134,135,136,134,135,136,137,135,136,137,138,136,137,138,139,137,138,139,140,138,139,140,141,139,140,141,142,140,141,142,143,141,142,143,144,142,143,144,145,143,144,145,146,144,145,146,147,145,146,147,148,146,147,148,149,147,148,149,150,148,149,150,151,149,150,151,152,150,151,152,153,151,152,153,154,152,153,154,155,153,154,155,156,154,155,156,157,155,156,157,158,156,157,158,159,157,158,159,160,158,159,160,161,159,160,161,162,160,161,162,163,161,162,163,164,162,163,164,165,163,164,165,166,164,165,166,167,165,166,167,168,166,167,168,169,167,168,169,170,168,169,170,171,169,170,171,172,170,171,172,173,171,172,173,174,172,173,174,175,173,174,175,176,174,175,176,177,175,176,177,178,176,177,178,179,177,178,179,180,178,179,180,181,179,180,181,182,180,181,182,183,181,182,183,184,182,183,184,185,183,184,185,186,184,185,186,187,185,186,187,188,186,187,188,189,187,188,189,190,188,189,190,191,189,190,191,192,190,191,192,193,191,192,193,194,192,193,194,195,193,194,195,196,194,195,196,197,195,196,197,198,196,197,198,199,197,198,199,200,198,199,200,201,199,200,201,202,200,201,202,203,201,202,203,204,202,203,204,205,203,204,205,206,204,205,206,207,205,206,207,208,206,207,208,209,207,208,209,210,208,209,210,211,209,210,211,212,210,211,212,213,211,212,213,214,212,213,214,215,213,214,215,216,214,215,216,217,215,216,217,218,216,217,218,219,217,218,219,220,218,219,220,221,219,220,221,222,220,221,222,223,221,222,223,224,222,223,224,225,223,224,225,226,224,225,226,227,225,226,227,228,226,227,228,229,227,228,229,230,228,229,230,231,229,230,231,232,230,231,232,233,231,232,233,234,232,233,234,235,233,234,235,236,234,235,236,237,235,236,237,238,236,237,238,239,237,238,239,240,238,239,240,241,239,240,241,242,240,241,242,243,241,242,243,244,242,243,244,245,243,244,245,246,244,245,246,247,245,246,247,248,246,247,248,249,247,248,249,250,248,249,250,251,249,250,251,252,250,251,252,253,251,252,253,254,252,253,254,255,253,254,255,256,254,255,256,257,255,256,257,258], "sample": [1,2,3,4]} + ], +] + +ilp_benchmark_tests = [ + [ + "ilp bench - array sum 1", + 1000, + "./third_party/ABY/build/bin/2pc_ilp_bench_1", + {"a": 2, "b": 0}, + {"a": 0, "b": 1}, + ], + [ + "ilp bench - array sum 2", + 2000, + "./third_party/ABY/build/bin/2pc_ilp_bench_2", + {"a": 2, "b": 0}, + {"a": 0, "b": 1}, + ], + [ + "ilp bench - array sum 3", + 3000, + "./third_party/ABY/build/bin/2pc_ilp_bench_3", + {"a": 2, "b": 0}, + {"a": 0, "b": 1}, + ], + [ + "ilp bench - array sum 4", + 4000, + "./third_party/ABY/build/bin/2pc_ilp_bench_4", + {"a": 2, "b": 0}, + {"a": 0, "b": 1}, + ], + [ + "ilp bench - array sum 5", + 5000, + "./third_party/ABY/build/bin/2pc_ilp_bench_5", + {"a": 2, "b": 0}, + {"a": 0, "b": 1}, + ], + [ + "ilp bench - array sum 6", + 6000, + "./third_party/ABY/build/bin/2pc_ilp_bench_6", + {"a": 2, "b": 0}, + {"a": 0, "b": 1}, + ], + [ + "ilp bench - array sum 7", + 7000, + "./third_party/ABY/build/bin/2pc_ilp_bench_7", + {"a": 2, "b": 0}, + {"a": 0, "b": 1}, + ], + [ + "ilp bench - array sum 8", + 8000, + "./third_party/ABY/build/bin/2pc_ilp_bench_8", + {"a": 2, "b": 0}, + {"a": 0, "b": 1}, + ], + [ + "ilp bench - array sum 9", + 9000, + "./third_party/ABY/build/bin/2pc_ilp_bench_9", + {"a": 2, "b": 0}, + {"a": 0, "b": 1}, + ], + +] + +millionaires_test = [ + [ + "Millionaire's problem", + 0, + "./third_party/ABY/build/bin/2pc_millionaires", + {"a": 2, "b": 0}, + {"a": 0, "b": 1}, + ], +] + +# ree_tests = [ +# [ +# "Array sum test 2", +# 6, +# "./third_party/ABY/build/bin/2pc_array_sum_2", +# {"a": 2, "b": 0}, +# {"a": 0, "b": 1}, +# ], +# ] diff --git a/scripts/aby_tests/utils.py b/scripts/aby_tests/utils.py new file mode 100644 index 00000000..3ce384b3 --- /dev/null +++ b/scripts/aby_tests/utils.py @@ -0,0 +1,107 @@ +from subprocess import Popen, PIPE +import sys +from typing import List +import time + +def init_progress_bar(toolbar_width=40): + ''' Initialize progress bar ''' + print("Running ABY unit tests") + sys.stdout.write("[%s]" % ("." * toolbar_width)) + sys.stdout.flush() + sys.stdout.write("\b" * (toolbar_width+1)) + +def update_progress_bar(): + ''' Increment progress bar ''' + sys.stdout.write("#") + sys.stdout.flush() + +def end_progress_bar(): + ''' Close progress bar ''' + sys.stdout.write("]\n") # this ends the progress bar + +def flatten_args(args: dict) -> list: + ''' Flatten dictionary into list ''' + flat_args = [] + for k, v in args.items(): + flat_args.append(str(k)) + if type(v) == list: + flat_args += [str(x) for x in v] + else: + flat_args.append(str(v)) + return flat_args + +def update_path(path: str, lang: str) -> str: + '''Append path with language type''' + return f'{path}_{lang}_test' + +def build_server_cmd(exec: str, args: dict) -> List[str]: + return [exec, "-r", "0", "-i"] + flatten_args(args) + +def build_client_cmd(exec: str, args: dict) -> List[str]: + return [exec, "-r", "1", "-i"] + flatten_args(args) + +def run_test(desc: str, expected: str, server_cmd: List[str], client_cmd: List[str]) -> bool: + assert len(server_cmd) > 3, "server cmd does not have enough arguments" + assert len(client_cmd) > 3, "client cmd does not have enough arguments" + + assert server_cmd[0] == client_cmd[0], "server and client do not have the same cmd: " + server_cmd[0] + ", " + client_cmd[0] + + try: + server_proc = Popen(server_cmd, stdout=PIPE, stderr=PIPE) + client_proc = Popen(client_cmd, stdout=PIPE, stderr=PIPE) + + server_out, server_err = server_proc.communicate(timeout=5) + client_out, client_err = client_proc.communicate(timeout=5) + + assert not server_err, "server cmd has an error" + assert not client_err, "client cmd has an error" + + server_out = server_out.decode('utf-8').strip() + client_out = client_out.decode('utf-8').strip() + + assert server_out == client_out, "server out != client out\nserver_out: "+server_out+"\nclient_out: "+client_out + assert server_out == expected, "server_out: "+server_out+"\nexpected: "+expected + return True, "" + except Exception as e: + # print("Exception: ", e) + return False, e + +def run_tests(lang: str, tests: List[dict]): + ''' + tests will be a list of all tests to run. each element in the list will be + 1. description of test case: string + 2. expected output: string + 3. executable path: string + 4. server arguments: dict[name] = value + 5. client arguments: dict[name] = value + ''' + print("Running tests for frontend", lang) + failed_test_descs = [] + num_retries = 3 + progress_inc = 5 + init_progress_bar(len(tests) // progress_inc + 1) + for t, test in enumerate(tests): + assert len(test) == 5, "test configurations are wrong for test: "+test[0] + desc = test[0] + expected = str(test[1]) + path = update_path(test[2], lang) + server_cmd = build_server_cmd(path, test[3]) + client_cmd = build_client_cmd(path, test[4]) + + test_results = [] + for i in range(num_retries): + test_results.append(run_test(desc, expected, server_cmd, client_cmd)) + + if all([not r[0] for r in test_results]): + failed_test_descs += [(desc, e[1]) for e in test_results] + + if t % progress_inc == 0: + update_progress_bar() + end_progress_bar() + + if len(failed_test_descs) == 0: + print("All tests passed ✅") + + failed_test_descs = [f"{r}:\n{e}" for r, e in failed_test_descs] + + assert len(failed_test_descs) == 0, "there were failed test cases:\n======\n" + "\n\n".join(failed_test_descs) \ No newline at end of file diff --git a/scripts/aby_tests/zokrates_test_aby.py b/scripts/aby_tests/zokrates_test_aby.py new file mode 100755 index 00000000..db4a3b6e --- /dev/null +++ b/scripts/aby_tests/zokrates_test_aby.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +from utils import run_tests +from test_suite import * + +if __name__ == "__main__": + tests = arithmetic_tests + \ + arithmetic_boolean_tests + \ + nary_arithmetic_tests + \ + bitwise_tests + \ + boolean_tests + \ + nary_boolean_tests + \ + const_arith_tests + \ + const_bool_tests + \ + loop_tests + \ + ite_tests + \ + function_tests + \ + misc_tests + # shift_tests + \ + # arr_tests + \ + + run_tests('zok', tests) + + diff --git a/scripts/build_mpc_c_test.zsh b/scripts/build_mpc_c_test.zsh new file mode 100755 index 00000000..6e2cd888 --- /dev/null +++ b/scripts/build_mpc_c_test.zsh @@ -0,0 +1,105 @@ +#!/usr/bin/env zsh + +set -ex + +disable -r time + +cargo build --release --example circ + +BIN=./target/release/examples/circ +export CARGO_MANIFEST_DIR=$(pwd) + +case "$OSTYPE" in + darwin*) + alias measure_time="gtime --format='%e seconds %M kB'" + ;; + linux*) + alias measure_time="time --format='%e seconds %M kB'" + ;; +esac + +function mpc_test { + parties=$1 + cpath=$2 + RUST_BACKTRACE=1 measure_time $BIN --parties $parties $cpath mpc --cost-model "hycc" +} + +# build mpc arithmetic tests +mpc_test 2 ./examples/C/mpc/unit_tests/arithmetic_tests/2pc_add.c +mpc_test 2 ./examples/C/mpc/unit_tests/arithmetic_tests/2pc_sub.c +mpc_test 2 ./examples/C/mpc/unit_tests/arithmetic_tests/2pc_mult.c +mpc_test 2 ./examples/C/mpc/unit_tests/arithmetic_tests/2pc_mult_add_pub.c +mpc_test 2 ./examples/C/mpc/unit_tests/arithmetic_tests/2pc_mod.c +# mpc_test 2 ./examples/C/mpc/unit_tests/arithmetic_tests/2pc_add_unsigned.c + +mpc_test 2 ./examples/C/mpc/unit_tests/arithmetic_tests/2pc_int_equals.c +mpc_test 2 ./examples/C/mpc/unit_tests/arithmetic_tests/2pc_int_greater_than.c +mpc_test 2 ./examples/C/mpc/unit_tests/arithmetic_tests/2pc_int_greater_equals.c +mpc_test 2 ./examples/C/mpc/unit_tests/arithmetic_tests/2pc_int_less_than.c +mpc_test 2 ./examples/C/mpc/unit_tests/arithmetic_tests/2pc_int_less_equals.c + +# build mpc nary arithmetic tests +mpc_test 2 ./examples/C/mpc/unit_tests/nary_arithmetic_tests/2pc_nary_arithmetic_add.c + +# build mpc bitwise tests +mpc_test 2 ./examples/C/mpc/unit_tests/bitwise_tests/2pc_bitwise_and.c +mpc_test 2 ./examples/C/mpc/unit_tests/bitwise_tests/2pc_bitwise_or.c +mpc_test 2 ./examples/C/mpc/unit_tests/bitwise_tests/2pc_bitwise_xor.c + +# build mpc boolean tests +mpc_test 2 ./examples/C/mpc/unit_tests/boolean_tests/2pc_boolean_and.c +mpc_test 2 ./examples/C/mpc/unit_tests/boolean_tests/2pc_boolean_or.c +mpc_test 2 ./examples/C/mpc/unit_tests/boolean_tests/2pc_boolean_equals.c + +# build mpc nary boolean tests +mpc_test 2 ./examples/C/mpc/unit_tests/nary_boolean_tests/2pc_nary_boolean_and.c + +# build mpc const tests +mpc_test 2 ./examples/C/mpc/unit_tests/const_tests/2pc_const_arith.c +mpc_test 2 ./examples/C/mpc/unit_tests/const_tests/2pc_const_bool.c + +# build if statement tests +mpc_test 2 ./examples/C/mpc/unit_tests/ite_tests/2pc_ite_ret_bool.c +mpc_test 2 ./examples/C/mpc/unit_tests/ite_tests/2pc_ite_ret_int.c +mpc_test 2 ./examples/C/mpc/unit_tests/ite_tests/2pc_ite_only_if.c + +# build div tests +mpc_test 2 ./examples/C/mpc/unit_tests/div_tests/2pc_div.c + +# build array tests +mpc_test 2 ./examples/C/mpc/unit_tests/array_tests/2pc_array_sum.c +mpc_test 2 ./examples/C/mpc/unit_tests/array_tests/2pc_array_index.c +mpc_test 2 ./examples/C/mpc/unit_tests/array_tests/2pc_array_index_2.c + +# build circ/compiler array tests +mpc_test 2 ./examples/C/mpc/unit_tests/c_array_tests/2pc_array.c +mpc_test 2 ./examples/C/mpc/unit_tests/c_array_tests/2pc_array_1.c +mpc_test 2 ./examples/C/mpc/unit_tests/c_array_tests/2pc_array_2.c +mpc_test 2 ./examples/C/mpc/unit_tests/c_array_tests/2pc_array_3.c +mpc_test 2 ./examples/C/mpc/unit_tests/c_array_tests/2pc_array_sum_c.c + +# # # build shift tests +# # mpc_test 2 ./examples/C/mpc/unit_tests/shift_tests/2pc_lhs.c +# # mpc_test 2 ./examples/C/mpc/unit_tests/shift_tests/2pc_rhs.c + + + +# # benchmarks +# # mpc_test 2 ./examples/C/mpc/benchmarks/2pc_kmeans.c +# # mpc_test 2 ./examples/C/mpc/benchmarks/2pc_biomatch.c + +# # ilp benchmarks +# # mpc_test 2 ./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_1.c +# # mpc_test 2 ./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_2.c +# # mpc_test 2 ./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_3.c +# # mpc_test 2 ./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_4.c +# # mpc_test 2 ./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_5.c +# # mpc_test 2 ./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_6.c +# # mpc_test 2 ./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_7.c +# # mpc_test 2 ./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_8.c +# # mpc_test 2 ./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench_9.c +# # mpc_test 2 ./examples/C/mpc/ilp_benchmarks/2pc_ilp_bench.c + +# # mpc_test 2 ./examples/C/mpc/unit_tests/arithmetic_tests/2pc_loop_add.c + +# # mpc_test 2 ./examples/C/mpc/2pc_millionaires.c diff --git a/scripts/build_mpc_zokrates_test.zsh b/scripts/build_mpc_zokrates_test.zsh index 317f7b0b..0d7b46cc 100755 --- a/scripts/build_mpc_zokrates_test.zsh +++ b/scripts/build_mpc_zokrates_test.zsh @@ -7,6 +7,7 @@ disable -r time cargo build --release --example circ BIN=./target/release/examples/circ +export CARGO_MANIFEST_DIR=$(pwd) case "$OSTYPE" in darwin*) @@ -51,14 +52,14 @@ mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/boolean_tests/2pc_boolean_equals.z # build mpc nary boolean tests mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/nary_boolean_tests/2pc_nary_boolean_and.zok -# build ite tests -mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/ite_tests/2pc_ite_ret_bool.zok -mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/ite_tests/2pc_ite_ret_int.zok - # build mpc const tests mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/const_tests/2pc_const_arith.zok mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/const_tests/2pc_const_bool.zok +# build ite tests +mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/ite_tests/2pc_ite_ret_bool.zok +mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/ite_tests/2pc_ite_ret_int.zok + # build mpc array tests # mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/array_tests/2pc_array_sum.zok # mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/array_tests/2pc_array_ret.zok @@ -70,8 +71,8 @@ mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/loop_tests/2pc_loop_sum.zok mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/function_tests/2pc_function_sum.zok # build mpc shift tests -mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/shift_tests/2pc_lhs.zok -mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/shift_tests/2pc_rhs.zok +# mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/shift_tests/2pc_lhs.zok +# mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/shift_tests/2pc_rhs.zok # build mpc misc tests mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/2pc_millionaire.zok diff --git a/scripts/build_r1cs_c_test.zsh b/scripts/build_r1cs_c_test.zsh new file mode 100755 index 00000000..3c9287fb --- /dev/null +++ b/scripts/build_r1cs_c_test.zsh @@ -0,0 +1,26 @@ +#!/usr/bin/env zsh + +set -ex + +disable -r time + +cargo build --release --example circ + +BIN=./target/release/examples/circ + +case "$OSTYPE" in + darwin*) + alias measure_time="gtime --format='%e seconds %M kB'" + ;; + linux*) + alias measure_time="time --format='%e seconds %M kB'" + ;; +esac + +function r1cs_test { + cpath=$1 + measure_time $BIN $cpath r1cs --action count +} + +r1cs_test ./examples/C/r1cs/add.c + diff --git a/scripts/test_aby.py b/scripts/test_aby.py deleted file mode 100644 index 60b7be3b..00000000 --- a/scripts/test_aby.py +++ /dev/null @@ -1,640 +0,0 @@ -from subprocess import Popen, PIPE -from typing import List -import time - -arithmetic_tests = [ - [ - "Add two numbers - 1", - 3, - "./third_party/ABY/build/bin/2pc_add_test", - {"a": 1, "b": 0}, - {"a": 0, "b": 2}, - ], - [ - "Add two numbers - 2", - 2, - "./third_party/ABY/build/bin/2pc_add_test", - {"a": 0, "b": 0}, - {"a": 0, "b": 2}, - ], - [ - "Subtract two numbers", - 1, - "./third_party/ABY/build/bin/2pc_sub_test", - {"a": 3, "b": 0}, - {"a": 0, "b": 2}, - ], - [ - "Subtract two numbers, negative -1 == 4294967295 because u32", - 4294967295, - "./third_party/ABY/build/bin/2pc_sub_test", - {"a": 2, "b": 0}, - {"a": 0, "b": 3}, - ], - [ - "Multiply two numbers - 1", - 0, - "./third_party/ABY/build/bin/2pc_mult_test", - {"a": 0, "b": 0}, - {"a": 0, "b": 5}, - ], - [ - "Multiply two numbers - 2", - 5, - "./third_party/ABY/build/bin/2pc_mult_test", - {"a": 1, "b": 0}, - {"a": 0, "b": 5}, - ], - [ - "Multiply two numbers - 3", - 10, - "./third_party/ABY/build/bin/2pc_mult_test", - {"a": 2, "b": 0}, - {"a": 0, "b": 5}, - ], - [ - # only server side public value works - "Multiply two numbers together and add with public value", - 42, - "./third_party/ABY/build/bin/2pc_mult_add_pub_test", - {"a": 5, "b": 0, "v": 7}, - {"a": 0, "b": 7, "v": 7}, - ], - [ - # only server side public value works - "Multiply two numbers together and add with public value, check only server side public value is added", - 42, - "./third_party/ABY/build/bin/2pc_mult_add_pub_test", - {"a": 5, "b": 0, "v": 7}, - {"a": 0, "b": 7, "v": 0}, - ], -] - -arithmetic_boolean_tests = [ - [ - "Test two numbers are equal - 1", - 0, - "./third_party/ABY/build/bin/2pc_int_equals_test", - {"a": 5, "b": 0}, - {"a": 0, "b": 7}, - ], - [ - "Test two numbers are equal - 2", - 1, - "./third_party/ABY/build/bin/2pc_int_equals_test", - {"a": 7, "b": 0}, - {"a": 0, "b": 7}, - ], - [ - "Test int > int - 1", - 0, - "./third_party/ABY/build/bin/2pc_int_greater_than_test", - {"a": 5, "b": 0}, - {"a": 0, "b": 7}, - ], - [ - "Test int > int - 2", - 0, - "./third_party/ABY/build/bin/2pc_int_greater_than_test", - {"a": 7, "b": 0}, - {"a": 0, "b": 7}, - ], - [ - "Test int > int - 3", - 1, - "./third_party/ABY/build/bin/2pc_int_greater_than_test", - {"a": 8, "b": 0}, - {"a": 0, "b": 7}, - ], - [ - "Test int >= int - 1", - 1, - "./third_party/ABY/build/bin/2pc_int_greater_equals_test", - {"a": 8, "b": 0}, - {"a": 0, "b": 7}, - ], - [ - "Test int >= int - 2", - 1, - "./third_party/ABY/build/bin/2pc_int_greater_equals_test", - {"a": 7, "b": 0}, - {"a": 0, "b": 7}, - ], - [ - "Test int >= int - 3", - 0, - "./third_party/ABY/build/bin/2pc_int_greater_equals_test", - {"a": 6, "b": 0}, - {"a": 0, "b": 7}, - ], - [ - "Test int < int - 1", - 0, - "./third_party/ABY/build/bin/2pc_int_less_than_test", - {"a": 7, "b": 0}, - {"a": 0, "b": 2}, - ], - [ - "Test int < int - 2", - 0, - "./third_party/ABY/build/bin/2pc_int_less_than_test", - {"a": 7, "b": 0}, - {"a": 0, "b": 7}, - ], - [ - "Test int < int - 3", - 1, - "./third_party/ABY/build/bin/2pc_int_less_than_test", - {"a": 2, "b": 0}, - {"a": 0, "b": 7}, - ], - [ - "Test int <= int - 1", - 1, - "./third_party/ABY/build/bin/2pc_int_less_equals_test", - {"a": 7, "b": 0}, - {"a": 0, "b": 8}, - ], - [ - "Test int <= int - 2", - 1, - "./third_party/ABY/build/bin/2pc_int_less_equals_test", - {"a": 7, "b": 0}, - {"a": 0, "b": 7}, - ], - [ - "Test int <= int - 3", - 0, - "./third_party/ABY/build/bin/2pc_int_less_equals_test", - {"a": 8, "b": 0}, - {"a": 0, "b": 7}, - ], - [ - "Test int == int - 1", - 0, - "./third_party/ABY/build/bin/2pc_int_equals_test", - {"a": 7, "b": 0}, - {"a": 0, "b": 8}, - ], - [ - "Test int == int - 2", - 1, - "./third_party/ABY/build/bin/2pc_int_equals_test", - {"a": 12, "b": 0}, - {"a": 0, "b": 12}, - ], -] - -nary_arithmetic_tests = [ - [ - "Test a + b + c", - 6, - "./third_party/ABY/build/bin/2pc_nary_arithmetic_add_test", - {"a": 1, "b": 0, "c": 0}, - {"a": 0, "b": 2, "c": 3}, - ], -] - -bitwise_tests = [ - [ - "Bitwise & - 1", - 0, - "./third_party/ABY/build/bin/2pc_bitwise_and_test", - {"a": 0, "b": 0}, - {"a": 0, "b": 0}, - ], - [ - "Bitwise & - 2", - 0, - "./third_party/ABY/build/bin/2pc_bitwise_and_test", - {"a": 1, "b": 0}, - {"a": 0, "b": 0}, - ], - [ - "Bitwise & - 3", - 0, - "./third_party/ABY/build/bin/2pc_bitwise_and_test", - {"a": 0, "b": 0}, - {"a": 0, "b": 1}, - ], - [ - "Bitwise & - 4", - 1, - "./third_party/ABY/build/bin/2pc_bitwise_and_test", - {"a": 1, "b": 0}, - {"a": 0, "b": 1}, - ], - [ - "Bitwise | - 1", - 0, - "./third_party/ABY/build/bin/2pc_bitwise_or_test", - {"a": 0, "b": 0}, - {"a": 0, "b": 0}, - ], - [ - "Bitwise | - 2", - 1, - "./third_party/ABY/build/bin/2pc_bitwise_or_test", - {"a": 1, "b": 0}, - {"a": 0, "b": 0}, - ], - [ - "Bitwise | - 3", - 1, - "./third_party/ABY/build/bin/2pc_bitwise_or_test", - {"a": 0, "b": 0}, - {"a": 0, "b": 1}, - ], - [ - "Bitwise | - 4", - 1, - "./third_party/ABY/build/bin/2pc_bitwise_or_test", - {"a": 1, "b": 0}, - {"a": 0, "b": 1}, - ], - [ - "Bitwise ^ - 1", - 0, - "./third_party/ABY/build/bin/2pc_bitwise_xor_test", - {"a": 0, "b": 0}, - {"a": 0, "b": 0}, - ], - [ - "Bitwise ^ - 2", - 1, - "./third_party/ABY/build/bin/2pc_bitwise_xor_test", - {"a": 1, "b": 0}, - {"a": 0, "b": 0}, - ], - [ - "Bitwise ^ - 3", - 1, - "./third_party/ABY/build/bin/2pc_bitwise_xor_test", - {"a": 0, "b": 0}, - {"a": 0, "b": 1}, - ], - [ - "Bitwise ^ - 4", - 0, - "./third_party/ABY/build/bin/2pc_bitwise_xor_test", - {"a": 1, "b": 0}, - {"a": 0, "b": 1}, - ], -] - -boolean_tests = [ - [ - "Boolean && - 1", - 0, - "./third_party/ABY/build/bin/2pc_boolean_and_test", - {"a": 0, "b": 0}, - {"a": 0, "b": 0}, - ], - [ - "Boolean && - 2", - 0, - "./third_party/ABY/build/bin/2pc_boolean_and_test", - {"a": 1, "b": 0}, - {"a": 0, "b": 0}, - ], - [ - "Boolean && - 3", - 0, - "./third_party/ABY/build/bin/2pc_boolean_and_test", - {"a": 0, "b": 0}, - {"a": 0, "b": 1}, - ], - [ - "Boolean && - 4", - 1, - "./third_party/ABY/build/bin/2pc_boolean_and_test", - {"a": 1, "b": 0}, - {"a": 0, "b": 1}, - ], - [ - "Boolean || - 1", - 0, - "./third_party/ABY/build/bin/2pc_boolean_or_test", - {"a": 0, "b": 0}, - {"a": 0, "b": 0}, - ], - [ - "Boolean || - 2", - 1, - "./third_party/ABY/build/bin/2pc_boolean_or_test", - {"a": 1, "b": 0}, - {"a": 0, "b": 0}, - ], - [ - "Boolean || - 3", - 1, - "./third_party/ABY/build/bin/2pc_boolean_or_test", - {"a": 0, "b": 0}, - {"a": 0, "b": 1}, - ], - [ - "Boolean || - 4", - 1, - "./third_party/ABY/build/bin/2pc_boolean_or_test", - {"a": 1, "b": 0}, - {"a": 0, "b": 1}, - ], - [ - "Boolean == - 1", - 0, - "./third_party/ABY/build/bin/2pc_boolean_equals_test", - {"a": 0, "b": 0}, - {"a": 0, "b": 1}, - ], - [ - "Boolean == - 2", - 1, - "./third_party/ABY/build/bin/2pc_boolean_equals_test", - {"a": 1, "b": 0}, - {"a": 0, "b": 1}, - ], -] - -nary_boolean_tests = [ - [ - "Test a & b & c - 1", - 0, - "./third_party/ABY/build/bin/2pc_nary_boolean_and_test", - {"a": 1, "b": 0, "c": 0}, - {"a": 0, "b": 1, "c": 0}, - ], - [ - "Test a & b & c - 2", - 1, - "./third_party/ABY/build/bin/2pc_nary_boolean_and_test", - {"a": 1, "b": 0, "c": 0}, - {"a": 0, "b": 1, "c": 1}, - ], -] - - -const_tests = [ - [ - "Test add client int + server int to const value", - 6, - "./third_party/ABY/build/bin/2pc_const_arith_test", - {"a": 2, "b": 0}, - {"a": 0, "b": 3}, - ], - [ - "Test server value == const value - 1", - 0, - "./third_party/ABY/build/bin/2pc_const_bool_test", - {"a": 0, "b": 0}, - {"a": 0, "b": 0}, - ], - [ - "Test server value == const value - 2", - 1, - "./third_party/ABY/build/bin/2pc_const_bool_test", - {"a": 1, "b": 0}, - {"a": 0, "b": 0}, - ], -] - -ite_tests = [ - [ - "Test ite ret bool - 1", - 0, - "./third_party/ABY/build/bin/2pc_ite_ret_bool_test", - {"a": 0, "b": 0, "sel": 1}, - {"a": 0, "b": 1, "sel": 1}, - ], - [ - "Test ite ret bool - 2", - 1, - "./third_party/ABY/build/bin/2pc_ite_ret_bool_test", - {"a": 0, "b": 0, "sel": 0}, - {"a": 0, "b": 1, "sel": 0}, - ], - [ - "Test ite ret int - 1", - 32, - "./third_party/ABY/build/bin/2pc_ite_ret_int_test", - {"a": 32, "b": 0, "sel": 1}, - {"a": 0, "b": 45, "sel": 1}, - ], - [ - "Test ite ret int - 2", - 45, - "./third_party/ABY/build/bin/2pc_ite_ret_int_test", - {"a": 32, "b": 0, "sel": 0}, - {"a": 0, "b": 45, "sel": 0}, - ], -] - -arr_tests = [ - [ - "Array sum test", - 3, - "./third_party/ABY/build/bin/2pc_array_sum_test", - {"a": 2, "b": 0}, - {"a": 0, "b": 1}, - ], - [ - "Array ret test", - "2\n1", - "./third_party/ABY/build/bin/2pc_array_ret_test", - {"a": 2, "b": 0}, - {"a": 0, "b": 1}, - ], -] - -loop_tests = [ - [ - "Loop sum const - 1", - 10, - "./third_party/ABY/build/bin/2pc_loop_sum_test", - {"a": 2, "b": 0}, - {"a": 0, "b": 1}, - ], - [ - "Loop sum const - 2", - 10, - "./third_party/ABY/build/bin/2pc_loop_sum_test", - {"a": 10, "b": 0}, - {"a": 0, "b": 3}, - ], -] - -function_tests = [ - [ - "Sum() two numbers - 1", - 3, - "./third_party/ABY/build/bin/2pc_function_sum_test", - {"a": 1, "b": 0}, - {"a": 0, "b": 2}, - ], - [ - "Sum() two numbers - 2", - 2, - "./third_party/ABY/build/bin/2pc_function_sum_test", - {"a": 0, "b": 0}, - {"a": 0, "b": 2}, - ], - -] - -shift_tests = [ - [ - "Left Shift a by 1 - 1", - 20, - "./third_party/ABY/build/bin/2pc_lhs_test", - {"a": 10, "b": 0}, - {"a": 0, "b": 2}, - ], - [ - "Left Shift a by 1 - 2", - 0, - "./third_party/ABY/build/bin/2pc_lhs_test", - {"a": 0, "b": 0}, - {"a": 0, "b": 2}, - ], - [ - "Left Shift a by 1 - 3", - 0, - "./third_party/ABY/build/bin/2pc_lhs_test", - {"a": 2147483648, "b": 0}, - {"a": 0, "b": 2}, - ], - [ - "Right Shift a by 1 - 1", - 10, - "./third_party/ABY/build/bin/2pc_rhs_test", - {"a": 20, "b": 0}, - {"a": 0, "b": 2}, - ], - [ - "Right Shift a by 1 - 2", - 0, - "./third_party/ABY/build/bin/2pc_rhs_test", - {"a": 0, "b": 0}, - {"a": 0, "b": 2}, - ], -] - -misc_tests = [ - [ - "Millionaire's problem: server has more money than client", - 0, - "./third_party/ABY/build/bin/2pc_millionaire_test", - {"a": 2, "b": 0}, - {"a": 0, "b": 1}, - ], - [ - "Millionaire's problem: server has equal money to client", - 0, - "./third_party/ABY/build/bin/2pc_millionaire_test", - {"a": 1, "b": 0}, - {"a": 0, "b": 1}, - ], - [ - "Millionaire's problem: server has less money than client", - 1, - "./third_party/ABY/build/bin/2pc_millionaire_test", - {"a": 1, "b": 0}, - {"a": 0, "b": 2}, - ], - [ - "Conversion problem", - 7, - "./third_party/ABY/build/bin/2pc_conv_test", - {"a": 0, "b": 0}, - {"a": 0, "b": 7}, - ], -] - -def flatten_args(args: dict) -> list: - ''' flatten dictionary into list ''' - flat_args = [] - for k, v in args.items(): - flat_args.append(str(k)) - flat_args.append(str(v)) - return flat_args - -def build_server_cmd(exec: str, args: dict) -> List[str]: - return [exec, "-r", "0", "-i"] + flatten_args(args) - -def build_client_cmd(exec: str, args: dict) -> List[str]: - return [exec, "-r", "1", "-i"] + flatten_args(args) - -def run_test(desc: str, expected: str, server_cmd: List[str], client_cmd: List[str]) -> bool: - assert len(server_cmd) > 3, "server cmd does not have enough arguments" - assert len(client_cmd) > 3, "client cmd does not have enough arguments" - - assert server_cmd[0] == client_cmd[0], "server and client do not have the same cmd: " + server_cmd[0] + ", " + client_cmd[0] - - try: - server_proc = Popen(server_cmd, stdout=PIPE, stderr=PIPE) - client_proc = Popen(client_cmd, stdout=PIPE, stderr=PIPE) - - server_out, server_err = server_proc.communicate() - client_out, client_err = client_proc.communicate() - - assert not server_err, "server cmd has an error" - assert not client_err, "client cmd has an error" - - server_out = server_out.decode('utf-8').strip() - client_out = client_out.decode('utf-8').strip() - - assert server_out == client_out, "server out != client out\nserver_out: "+server_out+"\nclient_out: "+client_out - assert server_out == expected, "output != expected\nserver_out: "+server_out+"\nexpected: "+expected - return True - except Exception as e: - print("Exception: ", e) - return False - -def main(): - # tests will be a list of all tests to run. each element in the list will be - # 1. description of test case: string - # 2. expected output: string - # 3. executable path: string - # 4. server arguments: dict[name] = value - # 5. client arguments: dict[name] = value - tests = arithmetic_tests + \ - arithmetic_boolean_tests + \ - nary_arithmetic_tests + \ - bitwise_tests + \ - boolean_tests + \ - nary_boolean_tests + \ - const_tests + \ - loop_tests + \ - ite_tests + \ - function_tests + \ - shift_tests + \ - misc_tests - # arr_tests + \ - - - failed_test_descs = [] - num_retries = 3 - for test in tests: - assert len(test) == 5, "test configurations are wrong for test: "+test[0] - desc = test[0] - expected = str(test[1]) - path = test[2] - server_cmd = build_server_cmd(path, test[3]) - client_cmd = build_client_cmd(path, test[4]) - - print("Running test:", server_cmd[0]) - print("Description:", desc) - - test_results = [] - for i in range(num_retries): - test_results.append(run_test(desc, expected, server_cmd, client_cmd)) - - if any(test_results): - print("Pass ✅\n") - else: - failed_test_descs.append(desc) - print("Fail 🚫\n") - - assert len(failed_test_descs) == 0, "there were failed test cases:\n\t- " + "\n\t- ".join(failed_test_descs) - -if __name__ == "__main__": - main() diff --git a/src/circify/mem.rs b/src/circify/mem.rs index 7e1a88f1..86ac7228 100644 --- a/src/circify/mem.rs +++ b/src/circify/mem.rs @@ -1,61 +1,31 @@ //! The stack-allocation memory manager use crate::ir::term::*; +use rug::Integer; +use std::collections::HashMap; -use std::cell::RefCell; -use std::collections::{BTreeMap, HashMap}; -use std::rc::Rc; - -type AllocId = usize; +/// Identifier for an Allocation block in memory +pub type AllocId = usize; struct Alloc { - id: AllocId, addr_width: usize, val_width: usize, - cur_ver: usize, size: usize, - cur_var: Term, + cur_term: Term, } impl Alloc { - /// Get the variable for the next version, and advance the next version. - fn next_var(&mut self) { - self.cur_ver += 1; - let t = leaf_term(Op::Var( - format!("mem_{}_v{}", self.id, self.cur_ver), - self.sort(), - )); - self.cur_var = t; - } - - fn sort(&self) -> Sort { - Sort::Array( - Box::new(Sort::BitVector(self.addr_width)), - Box::new(Sort::BitVector(self.val_width)), - self.size, - ) - } - - fn new(id: AllocId, addr_width: usize, val_width: usize, size: usize) -> Self { + fn new(addr_width: usize, val_width: usize, size: usize, cur_term: Term) -> Self { Self { - id, addr_width, val_width, size, - cur_ver: 0, - cur_var: leaf_term(Op::Var( - format!("mem_{}_v{}", id, 0), - Sort::Array( - Box::new(Sort::BitVector(addr_width)), - Box::new(Sort::BitVector(val_width)), - size, - ), - )), + cur_term, } } fn var(&self) -> &Term { - &self.cur_var + &self.cur_term } } @@ -63,19 +33,19 @@ impl Alloc { pub struct MemManager { allocs: HashMap, next_id: usize, - cs: Rc>, } -impl MemManager { +impl Default for MemManager { /// Create a new manager, with an empty stack. - pub fn new(cs: Rc>) -> Self { + fn default() -> Self { Self { allocs: HashMap::default(), next_id: 0, - cs, } } +} +impl MemManager { /// Returns the next allocation identifier, and advances it. fn take_next_id(&mut self) -> usize { let i = self.next_id; @@ -83,32 +53,21 @@ impl MemManager { i } - fn assert(&mut self, t: Term) { - debug_assert!(check(&t) == Sort::Bool); - self.cs.borrow_mut().assert(t); - } - /// Allocate a new stack array, equal to `array`. pub fn allocate(&mut self, array: Term) -> AllocId { let s = check(&array); - if let Sort::Array(k_s, v_s, size) = &s { - match (&**k_s, &**v_s) { - (Sort::BitVector(addr_width), Sort::BitVector(val_width)) => { + if let Sort::Array(box_addr_width, box_val_width, size) = s { + if let Sort::BitVector(addr_width) = *box_addr_width { + if let Sort::BitVector(val_width) = *box_val_width { let id = self.take_next_id(); - let alloc = Alloc::new(id, *addr_width, *val_width, *size); - let v = alloc.var().clone(); - if let Op::Var(n, _) = &v.op { - self.cs.borrow_mut().eval_and_save(n, &array); - } else { - unreachable!() - } - self.assert(term![Op::Eq; v, array]); + let alloc = Alloc::new(addr_width, val_width, size, array); self.allocs.insert(id, alloc); id + } else { + panic!("Cannot access val_width") } - _ => { - panic!("Cannot allocate array of sort: {}", s) - } + } else { + panic!("Cannot access addr_width") } } else { panic!("Cannot allocate array of sort: {}", s) @@ -127,13 +86,11 @@ impl MemManager { /// /// Returns a (concrete) allocation identifier which can be used to access this allocation. pub fn zero_allocate(&mut self, size: usize, addr_width: usize, val_width: usize) -> AllocId { - let array = Value::Array(Array::new( + self.allocate(term![Op::Const(Value::Array(Array::default( Sort::BitVector(addr_width), - Box::new(Value::BitVector(BitVector::zeros(val_width))), - BTreeMap::new(), - size, - )); - self.allocate(leaf_term(Op::Const(array))) + &Sort::BitVector(val_width), + size + )))]) } /// Load the value of index `offset` from the allocation `id`. @@ -144,26 +101,27 @@ impl MemManager { } /// Write the value `val` to index `offset` in the allocation `id`. - pub fn store(&mut self, id: AllocId, offset: Term, val: Term) { + pub fn store(&mut self, id: AllocId, offset: Term, val: Term, cond: Term) { let alloc = self.allocs.get_mut(&id).expect("Missing allocation"); assert_eq!(alloc.addr_width, check(&offset).as_bv()); assert_eq!(alloc.val_width, check(&val).as_bv()); + let old = alloc.cur_term.clone(); let new = term![Op::Store; alloc.var().clone(), offset, val]; - alloc.next_var(); - let v = alloc.var().clone(); - if let Op::Var(n, _) = &v.op { - self.cs.borrow_mut().eval_and_save(n, &new); - } else { - unreachable!() - } - self.assert(term![Op::Eq; v, new]); + let ite_store = term![Op::Ite; cond, new, old]; + alloc.cur_term = ite_store; } /// Is `offset` in bounds for the allocation `id`? pub fn in_bounds(&self, id: AllocId, offset: Term) -> Term { let alloc = self.allocs.get(&id).expect("Missing allocation"); assert_eq!(alloc.addr_width, check(&offset).as_bv()); - term![Op::BvBinPred(BvBinPred::Ult); offset, bv_lit(alloc.size, alloc.addr_width)] + term![Op::BvBinPred(BvBinPred::Ult); offset, bv_lit(Integer::from(alloc.size), alloc.addr_width)] + } + + /// Get size of the array at the allocation `id` + pub fn get_size(&self, id: AllocId) -> usize { + let alloc = self.allocs.get(&id).expect("Missing allocation"); + alloc.size } } @@ -171,20 +129,26 @@ impl MemManager { mod test { use super::*; use crate::target::smt::check_sat; + use std::cell::RefCell; + use std::rc::Rc; fn bv_var(s: &str, w: usize) -> Term { leaf_term(Op::Var(s.to_owned(), Sort::BitVector(w))) } - #[test] fn sat_test() { let cs = Rc::new(RefCell::new(Computation::new(false))); - let mut mem = MemManager::new(cs.clone()); + let mut mem = MemManager::default(); let id0 = mem.zero_allocate(6, 4, 8); let _id1 = mem.zero_allocate(6, 4, 8); - mem.store(id0, bv_lit(3, 4), bv_lit(2, 8)); - let a = mem.load(id0, bv_lit(3, 4)); - let b = mem.load(id0, bv_lit(1, 4)); + mem.store( + id0, + bv_lit(Integer::from(3), 4), + bv_lit(Integer::from(2), 8), + leaf_term(Op::Const(Value::Bool(true))), + ); + let a = mem.load(id0, bv_lit(Integer::from(3), 4)); + let b = mem.load(id0, bv_lit(Integer::from(1), 4)); let t = term![Op::BvBinPred(BvBinPred::Ugt); a, b]; cs.borrow_mut().assert(t); let sys = term( @@ -197,12 +161,17 @@ mod test { #[test] fn unsat_test() { let cs = Rc::new(RefCell::new(Computation::new(false))); - let mut mem = MemManager::new(cs.clone()); + let mut mem = MemManager::default(); let id0 = mem.zero_allocate(6, 4, 8); let _id1 = mem.zero_allocate(6, 4, 8); - mem.store(id0, bv_lit(3, 4), bv_var("a", 8)); - let a = mem.load(id0, bv_lit(3, 4)); - let b = mem.load(id0, bv_lit(3, 4)); + mem.store( + id0, + bv_lit(Integer::from(3), 4), + bv_var("a", 8), + leaf_term(Op::Const(Value::Bool(true))), + ); + let a = mem.load(id0, bv_lit(Integer::from(3), 4)); + let b = mem.load(id0, bv_lit(Integer::from(3), 4)); let t = term![Op::Not; term![Op::Eq; a, b]]; cs.borrow_mut().assert(t); let sys = term( diff --git a/src/circify/mod.rs b/src/circify/mod.rs index e6c33645..dcfb91ca 100644 --- a/src/circify/mod.rs +++ b/src/circify/mod.rs @@ -1,5 +1,5 @@ //! A library for building front-ends - +use crate::circify::mem::AllocId; use crate::ir::term::*; use std::cell::RefCell; @@ -196,7 +196,7 @@ impl LexScope { /// Circuit construction context. Useful for addition assertions, using memory, etc. pub struct CirCtx { /// Memory manager - pub mem: mem::MemManager, + pub mem: Rc>, /// Underlying constraint system pub cs: Rc>, } @@ -437,7 +437,7 @@ impl Circify { fn_ctr: 0, globals: LexScope::with_prefix("global".to_string()), cir_ctx: CirCtx { - mem: mem::MemManager::new(cs.clone()), + mem: Rc::new(RefCell::new(mem::MemManager::default())), cs, }, condition: leaf_term(Op::Const(Value::Bool(true))), @@ -662,7 +662,7 @@ impl Circify { } /// Exit a conditional block - pub fn exit_codition(&mut self) { + pub fn exit_condition(&mut self) { self.fn_stack.last_mut().expect("No fn").exit_condition(); self.condition = self.condition(); } @@ -792,6 +792,25 @@ impl Circify { pub fn consume(self) -> Rc> { self.cir_ctx.cs } + + /// Load from an AllocId + pub fn load(&self, id: AllocId, offset: Term) -> Term { + self.cir_ctx.mem.borrow_mut().load(id, offset) + } + + /// Conditional store to an AllocId based on current path condition + pub fn store(&mut self, id: AllocId, offset: Term, val: Term) { + let cond = self.condition(); + self.cir_ctx.mem.borrow_mut().store(id, offset, val, cond); + } + + /// Zero allocate an array + pub fn zero_allocate(&mut self, size: usize, addr_width: usize, val_width: usize) -> AllocId { + self.cir_ctx + .mem + .borrow_mut() + .zero_allocate(size, addr_width, val_width) + } } const RET_NAME: &str = "return"; diff --git a/src/front/c/ast_utils.rs b/src/front/c/ast_utils.rs new file mode 100644 index 00000000..6fec9cb7 --- /dev/null +++ b/src/front/c/ast_utils.rs @@ -0,0 +1,158 @@ +use crate::front::c::types::Ty; +use crate::front::c::Expression::Identifier; +use lang_c::ast::*; +use lang_c::span::Node; +use std::fmt::{self, Display, Formatter}; + +pub struct FnInfo { + pub name: String, + pub ret_ty: Option, + pub args: Vec, + pub body: Statement, +} + +pub struct DeclInfo { + pub name: String, + pub ty: Ty, +} + +pub struct ConstIteration { + pub val: i32, +} + +impl Display for FnInfo { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!( + f, + "name: {},\nargs: {:#?},\nbody: {:#?}", + self.name, self.args, self.body + ) + } +} + +pub fn name_from_decl(decl: &Declarator) -> String { + match decl.kind.node { + DeclaratorKind::Identifier(ref id) => id.node.name.clone(), + _ => panic!("Identifier not found: {:?}", decl), + } +} + +pub fn name_from_ident(ident: &Expression) -> String { + match ident { + Identifier(i) => i.node.name.clone(), + //TODO: make this Option + _ => "".to_string(), + } +} + +pub fn d_type_(ds: Vec>) -> Option { + assert!(!ds.is_empty()); + let res: Vec> = ds + .iter() + .map(|d| match &d.node { + DeclarationSpecifier::TypeSpecifier(t) => type_(t.node.clone()), + _ => unimplemented!("Unimplemented declaration type: {:#?}", d), + }) + .collect(); + compress_type(res) +} + +pub fn s_type_(ss: Vec>) -> Option { + assert!(!ss.is_empty()); + let res: Vec> = ss + .iter() + .map(|s| match &s.node { + SpecifierQualifier::TypeSpecifier(t) => type_(t.node.clone()), + _ => unimplemented!("Unimplemented specifier type: {:#?}", s), + }) + .collect(); + compress_type(res) +} + +fn compress_type(ts: Vec>) -> Option { + if ts.len() == 1 { + return ts.first().unwrap().clone(); + } else { + let mut signed: bool = true; + let mut _void: bool = false; + let mut bit_len: usize = 0; + for (i, t) in ts.iter().enumerate() { + // TODO: void pointers? + match t.as_ref().unwrap() { + Ty::Int(s, w) => { + if !*s && i > 0 { + panic!("unsigned type defined later: {:#?}", ts); + } + signed &= *s; + if !*s { + bit_len += *w; + } + } + _ => unimplemented!("Current type not supported: {:#?}", ts), + } + } + Some(Ty::Int(signed, bit_len)) + } +} + +fn type_(t: TypeSpecifier) -> Option { + return match t { + TypeSpecifier::Int => Some(Ty::Int(true, 32)), + TypeSpecifier::Unsigned => Some(Ty::Int(false, 32)), // Some(Ty::Int(false, 32)), + TypeSpecifier::Bool => Some(Ty::Bool), + TypeSpecifier::Void => None, + _ => unimplemented!("Type {:#?} not implemented yet.", t), + }; +} + +pub fn get_decl_info(decl: Declaration) -> DeclInfo { + // TODO: support more than 1 declaration + let ty = d_type_(decl.specifiers).unwrap(); + assert!(decl.declarators.len() == 1); + let decls = decl.declarators.first().unwrap().node.clone(); + let name = name_from_decl(&decls.declarator.node); + DeclInfo { name, ty } +} + +pub fn get_fn_info(fn_def: &FunctionDefinition) -> FnInfo { + let name = name_from_func(fn_def); + let ret_ty = ret_ty_from_func(fn_def); + let args = args_from_func(fn_def).unwrap(); + let body = body_from_func(fn_def); + + FnInfo { + name, + ret_ty, + args: args.to_vec(), + body, + } +} + +fn name_from_func(fn_def: &FunctionDefinition) -> String { + let decl = &fn_def.declarator.node; + name_from_decl(decl) +} + +fn ret_ty_from_func(fn_def: &FunctionDefinition) -> Option { + d_type_(fn_def.specifiers.clone()) +} + +fn args_from_func(fn_def: &FunctionDefinition) -> Option> { + let dec = &fn_def.declarator.node; + dec.derived.iter().find_map(|d| match d.node { + DerivedDeclarator::Function(ref fn_dec) => { + let args = fn_dec + .node + .parameters + .iter() + .map(|a| a.node.clone()) + .collect::>(); + Some(args) + } + _ => None, + }) +} + +fn body_from_func(fn_def: &FunctionDefinition) -> Statement { + fn_def.statement.node.clone() +} diff --git a/src/front/c/mod.rs b/src/front/c/mod.rs new file mode 100644 index 00000000..bb784356 --- /dev/null +++ b/src/front/c/mod.rs @@ -0,0 +1,620 @@ +//! The C front-end + +mod ast_utils; +mod parser; +mod term; +mod types; + +use super::{FrontEnd, Mode}; +use crate::circify::{Circify, Loc, Val}; +use crate::front::c::ast_utils::*; +use crate::front::c::term::*; +use crate::front::c::types::*; +use crate::ir::opt::cfold::fold; +use crate::ir::proof::{self, ConstraintMetadata}; +use crate::ir::term::*; +use lang_c::ast::*; +use lang_c::span::Node; +use log::debug; + +// use std::collections::HashMap; +use std::fmt::Display; +use std::path::PathBuf; + +/// The prover visibility +const PROVER_VIS: Option = Some(proof::PROVER_ID); +/// Public visibility +const PUBLIC_VIS: Option = None; + +/// Inputs to the C compiler +pub struct Inputs { + /// The file to look for `main` in. + pub file: PathBuf, + /// The file to look for concrete arguments to main in. Optional. + /// + /// ## Examples + /// + /// If main takes `x: u64, y: field`, this file might contain + /// + /// ```ignore + /// x 4 + /// y -1 + /// ``` + pub inputs: Option, + /// The mode to generate for (MPC or proof). Effects visibility. + pub mode: Mode, +} + +/// The C front-end. Implements [FrontEnd]. +pub struct C; + +impl FrontEnd for C { + type Inputs = Inputs; + fn gen(i: Inputs) -> Computation { + let parser = parser::CParser::new(); + let p = parser.parse_file(&i.file).unwrap(); + let mut g = CGen::new(i.inputs, i.mode, p.unit); + g.gen(); + g.circ.consume().borrow().clone() + } +} + +struct CGen { + circ: Circify, + mode: Mode, + tu: TranslationUnit, +} + +enum CLoc { + Var(Loc), + Idx(Box, CTerm), +} + +impl CLoc { + fn loc(&self) -> &Loc { + match self { + CLoc::Var(l) => l, + CLoc::Idx(i, _) => i.loc(), + } + } +} + +impl CGen { + fn new(inputs: Option, mode: Mode, tu: TranslationUnit) -> Self { + let this = Self { + circ: Circify::new(Ct::new(inputs.map(parser::parse_inputs))), + mode, + tu, + }; + this.circ + .cir_ctx() + .cs + .borrow_mut() + .metadata + .add_prover_and_verifier(); + this + } + + /// Unwrap a result of an error and abort + fn err(&self, e: E) -> ! { + println!("Error: {}", e); + std::process::exit(1) + } + + /// Unwrap result of a computation + fn unwrap(&self, r: Result) -> CTerm { + r.unwrap_or_else(|e| self.err(e)) + } + + fn array_select(&self, array: CTerm, idx: CTerm) -> Result { + match (array.clone().term, idx.term) { + (CTermData::CArray(ty, id), CTermData::CInt(_, _, idx)) => { + let i = id.unwrap_or_else(|| panic!("Unknown AllocID: {:#?}", array)); + Ok(cterm(match ty { + Ty::Bool => CTermData::CBool(self.circ.load(i, idx)), + Ty::Int(s, w) => CTermData::CInt(s, w, self.circ.load(i, idx)), + // TODO: Flatten array so this case doesn't occur + // Ty::Array(_,t) => { + // CTermData::CArray(*t, id) + // } + _ => unimplemented!(), + })) + } + (a, b) => Err(format!("[Array Select] cannot index {} by {}", b, a)), + } + } + + pub fn array_store(&mut self, array: CTerm, idx: CTerm, val: CTerm) -> Result { + match (array.clone().term, idx.term) { + (CTermData::CArray(_, id), CTermData::CInt(_, _, idx_term)) => { + let i = id.unwrap_or_else(|| panic!("Unknown AllocID: {:#?}", array.clone())); + let new_val = val.term.term(&self.circ); + self.circ.store(i, idx_term, new_val); + Ok(val) + } + (a, b) => Err(format!("[Array Store] cannot index {} by {}", b, a)), + } + } + + fn mod_lval(&mut self, l: CLoc, t: CTerm) -> Result { + let var = l.loc().clone(); + let old = self + .circ + .get_value(var.clone()) + .map_err(|e| format!("{}", e))? + .unwrap_term(); + + match l { + CLoc::Var(_) => self + .circ + .assign(var, Val::Term(t.clone())) + .map_err(|e| format!("{}", e)) + .map(|_| t), + CLoc::Idx(_, offset) => self.array_store(old, offset, t), + } + } + + fn lval(&mut self, expr: Node) -> CLoc { + match expr.node { + Expression::Identifier(_) => { + let base_name = name_from_ident(&expr.node); + CLoc::Var(Loc::local(base_name)) + } + Expression::BinaryOperator(node) => { + let bin_op = node.node; + match bin_op.operator.node { + BinaryOperator::Index => { + let base_name = name_from_ident(&bin_op.lhs.node); + let idx = self.gen_expr(bin_op.rhs.node); + CLoc::Idx(Box::new(CLoc::Var(Loc::local(base_name))), idx) + } + _ => unimplemented!("Invalid left hand value"), + } + } + _ => unimplemented!("Invalid left hand value"), + } + } + + fn fold_(&mut self, expr: CTerm) -> i32 { + let term_ = fold(&expr.term.term(&self.circ)); + let cterm_ = cterm(CTermData::CInt(true, 32, term_)); + let val = const_int(cterm_).ok().unwrap(); + val.to_i32().unwrap() + } + + fn inner_derived_type_(&mut self, base_ty: Ty, d: DerivedDeclarator) -> Ty { + match d { + DerivedDeclarator::Array(arr) => { + if let ArraySize::VariableExpression(expr) = &arr.node.size { + let expr_ = self.gen_expr(expr.node.clone()); + let size = self.fold_(expr_) as usize; + return Ty::Array(Some(size), Box::new(base_ty)); + } + Ty::Array(None, Box::new(base_ty)) + } + DerivedDeclarator::Pointer(_ptr) => { + unimplemented!("pointers not implemented yet"); + } + _ => panic!("Not implemented: {:#?}", d), + } + } + + fn derived_type_(&mut self, base_ty: Ty, derived: Vec>) -> Ty { + if derived.is_empty() { + return base_ty; + } + let mut derived_ty = base_ty.clone(); + for d in derived { + let next_ty = self.inner_derived_type_(base_ty.clone(), d.node.clone()); + match derived_ty { + Ty::Array(s, _) => derived_ty = Ty::Array(s, Box::new(next_ty)), + _ => derived_ty = next_ty, + } + } + derived_ty + } + + /// Interpret the party association of input parameters + pub fn interpret_visibility(&mut self, ext: &DeclarationSpecifier) -> Option { + if let DeclarationSpecifier::Extension(nodes) = ext { + assert!(nodes.len() == 1); + let node = nodes.first().unwrap(); + if let Extension::Attribute(attr) = &node.node { + let name = &attr.name; + return match name.node.as_str() { + "public" => PUBLIC_VIS, + "private" => match self.mode { + Mode::Mpc(n_parties) => { + assert!(attr.arguments.len() == 1); + let arg = attr.arguments.first().unwrap(); + let cons = self.gen_expr(arg.node.clone()); + let num_val = const_int(cons).ok()?; + if num_val <= n_parties { + Some(num_val.to_u8()?) + } else { + self.err(format!( + "Party number {} greater than the number of parties ({})", + num_val, n_parties + )) + } + } + Mode::Proof => PROVER_VIS, + _ => unimplemented!("Mode {} is not supported.", self.mode), + }, + _ => panic!("Unknown visibility: {:#?}", name), + }; + } + } + panic!("Bad visibility declaration."); + } + + fn const_(&self, c: Constant) -> CTerm { + match c { + // TODO: move const integer function out to separate function + Constant::Integer(i) => cterm(CTermData::CInt( + true, + 32, + bv_lit(i.number.parse::().unwrap(), 32), + )), + _ => unimplemented!("Constant {:#?} hasn't been implemented", c), + } + } + + fn get_bin_op(&self, op: BinaryOperator) -> fn(CTerm, CTerm) -> Result { + match op { + BinaryOperator::Plus => add, + BinaryOperator::AssignPlus => add, + BinaryOperator::AssignDivide => div, + BinaryOperator::Minus => sub, + BinaryOperator::Multiply => mul, + BinaryOperator::Divide => div, + BinaryOperator::Equals => eq, + BinaryOperator::Greater => ugt, + BinaryOperator::GreaterOrEqual => uge, + BinaryOperator::Less => ult, + BinaryOperator::LessOrEqual => ule, + BinaryOperator::BitwiseAnd => bitand, + BinaryOperator::BitwiseOr => bitor, + BinaryOperator::BitwiseXor => bitxor, + BinaryOperator::LogicalAnd => and, + BinaryOperator::LogicalOr => or, + BinaryOperator::Modulo => rem, + BinaryOperator::ShiftLeft => shl, + BinaryOperator::ShiftRight => shr, + _ => unimplemented!("BinaryOperator {:#?} hasn't been implemented", op), + } + } + + fn get_u_op(&self, op: UnaryOperator) -> fn(CTerm, CTerm) -> Result { + match op { + UnaryOperator::PostIncrement => add, + _ => unimplemented!("UnaryOperator {:#?} hasn't been implemented", op), + } + } + + fn gen_expr(&mut self, expr: Expression) -> CTerm { + let res = match expr.clone() { + Expression::Identifier(node) => Ok(self + .unwrap(self.circ.get_value(Loc::local(node.node.name.clone()))) + .unwrap_term()), + Expression::Constant(node) => Ok(self.const_(node.node)), + Expression::BinaryOperator(node) => { + let bin_op = node.node; + match bin_op.operator.node { + BinaryOperator::Assign => { + let e = self.gen_expr(bin_op.rhs.node); + let lval = self.lval(*bin_op.lhs); + let mod_res = self.mod_lval(lval, e.clone()); + self.unwrap(mod_res); + Ok(e) + } + BinaryOperator::AssignPlus | BinaryOperator::AssignDivide => { + let f = self.get_bin_op(bin_op.operator.node); + let i = self.gen_expr(bin_op.lhs.node.clone()); + let rhs = self.gen_expr(bin_op.rhs.node); + let e = f(i, rhs).unwrap(); + let lval = self.lval(*bin_op.lhs); + let mod_res = self.mod_lval(lval, e.clone()); + self.unwrap(mod_res); + Ok(e) + } + BinaryOperator::Index => { + let a = self.gen_expr(bin_op.lhs.node); + let b = self.gen_expr(bin_op.rhs.node); + self.array_select(a, b) + } + _ => { + let f = self.get_bin_op(bin_op.operator.node.clone()); + let mut a = self.gen_expr(bin_op.lhs.node); + let mut b = self.gen_expr(bin_op.rhs.node); + + // TODO: fix hack, const int check for shifting + if bin_op.operator.node == BinaryOperator::ShiftLeft + || bin_op.operator.node == BinaryOperator::ShiftRight + { + let a_t = fold(&a.term.term(&self.circ)); + a = cterm(CTermData::CInt(true, 32, a_t)); + + let b_t = fold(&b.term.term(&self.circ)); + b = cterm(CTermData::CInt(true, 32, b_t)); + } + f(a, b) + } + } + } + Expression::UnaryOperator(node) => { + let u_op = node.node; + match u_op.operator.node { + UnaryOperator::PostIncrement => { + let f = self.get_u_op(u_op.operator.node); + let i = self.gen_expr(u_op.operand.node.clone()); + let one = cterm(CTermData::CInt(true, 32, bv_lit(1, 32))); + let e = f(i, one).unwrap(); + let lval = self.lval(*u_op.operand); + let mod_res = self.mod_lval(lval, e.clone()); + self.unwrap(mod_res); + Ok(e) + } + _ => unimplemented!("UnaryOperator {:#?} hasn't been implemented", u_op), + } + } + Expression::Cast(node) => { + let CastExpression { + type_name, + expression, + } = node.node; + let to_ty = s_type_(type_name.node.specifiers); + let expr = self.gen_expr(expression.node); + Ok(cast(to_ty, expr)) + } + _ => unimplemented!("Expr {:#?} hasn't been implemented", expr), + }; + self.unwrap(res) + } + + fn gen_init(&mut self, derived_ty: Ty, init: Initializer) -> CTerm { + match init { + Initializer::Expression(e) => self.gen_expr(e.node), + Initializer::List(l) => { + // TODO: check length of values to initialized number + let mut values: Vec = Vec::new(); + let inner_type = derived_ty.inner_ty(); + for li in l { + let expr = self.gen_init(inner_type.clone(), li.node.initializer.node.clone()); + values.push(expr) + } + let id = self + .circ + .zero_allocate(values.len(), 32, inner_type.num_bits()); + + for (i, v) in values.iter().enumerate() { + let offset = bv_lit(i, 32); + let v_ = v.term.term(&self.circ); + self.circ.store(id, offset, v_); + } + + cterm(CTermData::CArray(inner_type, Some(id))) + } + } + } + + fn gen_decl(&mut self, decl: Declaration) -> CTerm { + let decl_info = get_decl_info(decl.clone()); + let d = decl.declarators.first().unwrap().node.clone(); + let base_ty: Ty = decl_info.ty; + let derived = &d.declarator.node.derived; + let derived_ty = self.derived_type_(base_ty, derived.to_vec()); + let expr: CTerm; + if let Some(init) = d.initializer { + expr = self.gen_init(derived_ty.clone(), init.node); + } else { + expr = match derived_ty { + Ty::Array(size, ref ty) => { + let id = self.circ.zero_allocate(size.unwrap(), 32, ty.num_bits()); + cterm(CTermData::CArray(*ty.clone(), Some(id))) + } + _ => derived_ty.default(), + } + } + + let res = self.circ.declare_init( + decl_info.name, + derived_ty.clone(), + Val::Term(cast(Some(derived_ty), expr.clone())), + ); + self.unwrap(res); + expr + } + + //TODO: This function is not quite right because the loop body could modify the iteration variable. + fn get_const_iters(&mut self, for_stmt: ForStatement) -> ConstIteration { + let init: Option = match for_stmt.initializer.node { + ForInitializer::Declaration(d) => { + let expr = self.gen_decl(d.node); + let val = self.fold_(expr); + Some(ConstIteration { val }) + } + ForInitializer::Expression(e) => { + if let Expression::BinaryOperator(bin_op) = e.node { + let expr = self.gen_expr(bin_op.node.rhs.node); + let val = self.fold_(expr); + // let ass_res = self.circ.assign( + // Loc::local(name.clone()), + // Val::Term(expr.clone()), + // ); + // self.unwrap(ass_res); + Some(ConstIteration { val }) + } else { + None + } + } + _ => None, + }; + + let cond: Option = match for_stmt.condition.unwrap().node { + Expression::BinaryOperator(bin_op) => { + let expr = self.gen_expr(bin_op.node.rhs.node); + let val = self.fold_(expr); + match bin_op.node.operator.node { + BinaryOperator::Less => Some(ConstIteration { val }), + BinaryOperator::LessOrEqual => Some(ConstIteration { val: val + 1 }), + _ => None, + } + } + _ => None, + }; + + let step: Option = match for_stmt.step.unwrap().node { + Expression::UnaryOperator(u_op) => match u_op.node.operator.node { + UnaryOperator::PostIncrement | UnaryOperator::PreIncrement => { + Some(ConstIteration { val: 1 }) + } + _ => None, + }, + Expression::BinaryOperator(bin_op) => match bin_op.node.operator.node { + BinaryOperator::AssignPlus => { + let expr = self.gen_expr(bin_op.node.rhs.node); + let val = self.fold_(expr); + Some(ConstIteration { val }) + } + _ => None, + }, + _ => None, + }; + + // TODO: error checking here + let init_ = init.unwrap(); + let cond_ = cond.unwrap(); + let incr_ = step.unwrap(); + + let start = init_.val; + let end = cond_.val; + let incr = incr_.val; + + ConstIteration { + val: ((end - start - 1) / incr) + 1, + } + } + + fn gen_stmt(&mut self, stmt: Statement) { + match stmt { + Statement::Compound(nodes) => { + for node in nodes { + match node.node { + BlockItem::Declaration(decl) => { + self.gen_decl(decl.node); + } + BlockItem::Statement(stmt) => { + self.gen_stmt(stmt.node); + } + BlockItem::StaticAssert(_sa) => { + unimplemented!("Static Assert not supported yet") + } + } + } + } + Statement::If(node) => { + let cond = self.gen_expr(node.node.condition.node); + let t_term = cond.term.term(&self.circ); + let t_res = self.circ.enter_condition(t_term); + self.unwrap(t_res); + self.gen_stmt(node.node.then_statement.node); + self.circ.exit_condition(); + + if let Some(f_cond) = node.node.else_statement { + let f_term = term!(Op::Not; cond.term.term(&self.circ)); + let f_res = self.circ.enter_condition(f_term); + self.unwrap(f_res); + self.gen_stmt(f_cond.node); + self.circ.exit_condition(); + } + } + Statement::Return(ret) => { + match ret { + Some(expr) => { + let ret = self.gen_expr(expr.node); + let ret_res = self.circ.return_(Some(ret)); + self.unwrap(ret_res); + } + None => { + let ret_res = self.circ.return_(None); + self.unwrap(ret_res); + } + }; + } + Statement::Expression(expr) => { + let e = expr.unwrap().node; + self.gen_expr(e); + } + Statement::For(for_stmt) => { + // TODO: Add enter_breakable + self.circ.enter_scope(); + let const_iters = self.get_const_iters(for_stmt.node.clone()); + // TODO: Loop 5 times if const not specified + let bound = const_iters.val; + + for _ in 0..bound { + self.circ.enter_scope(); + self.gen_stmt(for_stmt.node.statement.node.clone()); + self.circ.exit_scope(); + self.gen_expr(for_stmt.node.step.as_ref().unwrap().node.clone()); + } + self.circ.exit_scope(); + } + _ => unimplemented!("Statement {:#?} hasn't been implemented", stmt), + } + } + + fn gen(&mut self) { + let TranslationUnit(nodes) = self.tu.clone(); + for n in nodes.iter() { + match n.node { + ExternalDeclaration::Declaration(ref decl) => { + debug!("{:#?}", decl); + } + ExternalDeclaration::FunctionDefinition(ref fn_def) => { + debug!("{:#?}", fn_def.node.clone()); + let fn_info = ast_utils::get_fn_info(&fn_def.node); + self.circ + .enter_fn(fn_info.name.to_owned(), fn_info.ret_ty.clone()); + for arg in fn_info.args.iter() { + // TODO: self.gen_decl(arg); + let p = &arg.specifiers[0]; + let vis = self.interpret_visibility(&p.node); + let base_ty = d_type_(arg.specifiers[1..].to_vec()); + let d = &arg.declarator.as_ref().unwrap().node; + let derived_ty = self.derived_type_(base_ty.unwrap(), d.derived.to_vec()); + let name = name_from_decl(d); + let res = self.circ.declare(name.clone(), &derived_ty, true, vis); + self.unwrap(res); + } + self.gen_stmt(fn_info.body.clone()); + if let Some(r) = self.circ.exit_fn() { + match self.mode { + Mode::Mpc(_) => { + let ret_term = r.unwrap_term(); + let ret_terms = ret_term.term.terms(); + self.circ + .cir_ctx() + .cs + .borrow_mut() + .outputs + .extend(ret_terms); + } + Mode::Proof => { + let ty = fn_info.ret_ty.as_ref().unwrap(); + let name = "return".to_owned(); + let term = r.unwrap_term(); + let _r = self.circ.declare(name.clone(), ty, false, PROVER_VIS); + self.circ.assign_with_assertions(name, term, ty, PUBLIC_VIS); + unimplemented!(); + } + _ => unimplemented!("Mode: {}", self.mode), + } + } + } + _ => unimplemented!("Haven't implemented node: {:?}", n.node), + } + } + } +} diff --git a/src/front/c/parser.rs b/src/front/c/parser.rs new file mode 100644 index 00000000..49dbcc14 --- /dev/null +++ b/src/front/c/parser.rs @@ -0,0 +1,49 @@ +//! Parsing and recursively loading C. + +use lang_c::driver::Error; +use lang_c::driver::{parse, Config, Parse}; +use rug::Integer; +use std::collections::HashMap; +use std::fs::File; +use std::io::{BufRead, BufReader}; +use std::path::Path; +use std::path::PathBuf; + +/// Parse an inputs file where each line has format: `no-whitespace integer`. +/// +/// Permits blank lines and ignores non-separating whitespace. +/// +/// ```ignore +/// x 5 +/// x.y -7 +/// ``` +pub fn parse_inputs(p: PathBuf) -> HashMap { + let mut m = HashMap::new(); + for l in BufReader::new(File::open(p).unwrap()).lines() { + let l = l.unwrap(); + let l = l.trim(); + if !l.is_empty() { + let mut s = l.split_whitespace(); + let key = s.next().unwrap().to_owned(); + let value = Integer::from(Integer::parse_radix(&s.next().unwrap(), 10).unwrap()); + m.insert(key, value); + } + } + m +} + +pub struct CParser { + config: Config, +} + +impl CParser { + pub fn new() -> Self { + Self { + config: Config::default(), + } + } + + pub fn parse_file(&self, path: &Path) -> Result { + parse(&self.config, path) + } +} diff --git a/src/front/c/term.rs b/src/front/c/term.rs new file mode 100644 index 00000000..d001e24d --- /dev/null +++ b/src/front/c/term.rs @@ -0,0 +1,588 @@ +//! C Terms +use crate::circify::mem::AllocId; +use crate::circify::{CirCtx, Embeddable}; +use crate::front::c::types::*; +use crate::front::c::Circify; +use crate::ir::term::*; +use rug::Integer; +use std::collections::HashMap; +use std::fmt::{self, Display, Formatter}; + +#[derive(Clone)] +pub enum CTermData { + CBool(Term), + CInt(bool, usize, Term), + CArray(Ty, Option), +} + +impl CTermData { + pub fn type_(&self) -> Ty { + match self { + Self::CBool(_) => Ty::Bool, + Self::CInt(s, w, _) => Ty::Int(*s, *w), + Self::CArray(b, _) => Ty::Array(None, Box::new(b.clone())), + } + } + /// Get all IR terms inside this value, as a list. + pub fn terms(&self) -> Vec { + let mut output: Vec = Vec::new(); + fn terms_tail(term: &CTermData, output: &mut Vec) { + match term { + CTermData::CBool(b) => output.push(b.clone()), + CTermData::CInt(_, _, b) => output.push(b.clone()), + _ => unimplemented!("Term: {} not implemented yet", term), + } + } + terms_tail(self, &mut output); + output + } + pub fn term(&self, circ: &Circify) -> Term { + match self { + CTermData::CBool(b) => b.clone(), + CTermData::CInt(_, _, b) => b.clone(), + CTermData::CArray(_, b) => { + // TODO: load all of the array + let i = b.unwrap_or_else(|| panic!("Unknown AllocID: {:#?}", self)); + circ.load(i, bv_lit(0, 32)) + } + } + } +} + +impl Display for CTermData { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + CTermData::CBool(x) => write!(f, "Bool({})", x), + CTermData::CInt(_, _, x) => write!(f, "Int({})", x), + CTermData::CArray(_, v) => write!(f, "Array({:#?})", v), + } + } +} + +impl fmt::Debug for CTermData { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +#[derive(Clone, Debug)] +pub struct CTerm { + pub term: CTermData, + pub udef: bool, +} + +impl Display for CTerm { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "Term: {:#?},\nudef: {}", self.term, self.udef) + } +} + +pub fn cterm(data: CTermData) -> CTerm { + CTerm { + term: data, + udef: false, + } +} + +pub fn cast(to_ty: Option, t: CTerm) -> CTerm { + let ty = t.term.type_(); + match t.term { + CTermData::CBool(ref term) => match to_ty { + Some(Ty::Int(s, w)) => CTerm { + term: CTermData::CInt( + s, + w, + term![Op::Not; term![Op::Eq; bv_lit(0, w), term.clone()]], + ), + udef: t.udef, + }, + Some(Ty::Bool) => t.clone(), + _ => panic!("Bad cast from {} to {:?}", ty, to_ty), + }, + CTermData::CInt(_, w, ref term) => match to_ty { + Some(Ty::Bool) => CTerm { + term: CTermData::CBool(term![Op::Not; term![Op::Eq; bv_lit(0, w), term.clone()]]), + udef: t.udef, + }, + Some(Ty::Int(_, _)) => t.clone(), + _ => panic!("Bad cast from {} to {:?}", ty, to_ty), + }, + CTermData::CArray(_, ref ty) => match to_ty { + Some(Ty::Array(_, _)) => t.clone(), + _ => panic!("Bad cast from {:#?} to {:?}", ty, to_ty), + }, + } +} + +/// Implementation of integer promotion (C11, 6.3.1.1.3) +fn int_promotion(t: &CTerm) -> CTerm { + let ty = t.term.type_(); + if (ty.is_integer_type() || Ty::Bool == ty) && ty.int_conversion_rank() < 32 { + match &t.term { + // "If an int can represent all values ... converted to an int ... + // otherwise an unsigned int" + CTermData::CInt(s, w, v) => { + let width = w - if *s { 1 } else { 0 }; + let max_val: u32 = u32::pow(2, width as u32) - 1; + let signed = max_val < u32::pow(2u32, 31u32) - 1; + CTerm { + term: CTermData::CInt(signed, 32, v.clone()), + udef: t.udef, + } + } + CTermData::CBool(v) => CTerm { + term: CTermData::CInt(false, 32, v.clone()), + udef: t.udef, + }, + _ => t.clone(), + } + } else { + t.clone() + } +} + +fn inner_usual_arith_conversions(a: &CTerm, b: &CTerm) -> (CTerm, CTerm) { + let _a_ty = a.term.type_(); + let _b_ty = b.term.type_(); + let a_prom = int_promotion(a); + let b_prom = int_promotion(b); + let a_prom_ty = a_prom.term.type_(); + let b_prom_ty = b_prom.term.type_(); + + if a_prom_ty == b_prom_ty { + (a_prom, b_prom) + } else if a_prom_ty.is_signed_int() == b_prom_ty.is_signed_int() { + if a_prom_ty.int_conversion_rank() < b_prom_ty.int_conversion_rank() { + (cast(Some(b_prom_ty), a_prom), b_prom) + } else { + (a_prom, cast(Some(a_prom_ty), b_prom)) + } + } else { + unimplemented!("Not implemented case in iUAC"); + } +} + +fn usual_arith_conversions(a: CTerm, b: CTerm) -> (CTerm, CTerm) { + if a.term.type_().is_arith_type() && b.term.type_().is_arith_type() { + let (a_, b_) = inner_usual_arith_conversions(&a, &b); + if a_.term.type_() == b_.term.type_() { + (a_, b_) + } else { + panic!( + "UAC failed: {:#?}, {:#?} to non-equal {:#?}, {:#?}", + a, b, a_, b_ + ); + } + } else { + (a, b) + } +} + +fn wrap_bin_arith( + name: &str, + fu: Option Term>, + fb: Option Term>, + a: CTerm, + b: CTerm, +) -> Result { + let (a_arith, b_arith) = usual_arith_conversions(a, b); + match (a_arith.term, b_arith.term, fu, fb) { + (CTermData::CInt(sx, nx, x), CTermData::CInt(sy, ny, y), Some(fu), _) if nx == ny => { + Ok(CTerm { + term: CTermData::CInt(sx && sy, nx, fu(x, y)), + udef: false, + }) + } + (CTermData::CBool(x), CTermData::CBool(y), _, Some(fb)) => Ok(CTerm { + term: CTermData::CBool(fb(x, y)), + udef: false, + }), + (x, y, _, _) => Err(format!("Cannot perform op '{}' on {} and {}", name, x, y)), + } +} + +fn add_uint(a: Term, b: Term) -> Term { + term![Op::BvNaryOp(BvNaryOp::Add); a, b] +} + +pub fn add(a: CTerm, b: CTerm) -> Result { + wrap_bin_arith("+", Some(add_uint), None, a, b) +} + +fn sub_uint(a: Term, b: Term) -> Term { + term![Op::BvBinOp(BvBinOp::Sub); a, b] +} + +pub fn sub(a: CTerm, b: CTerm) -> Result { + wrap_bin_arith("-", Some(sub_uint), None, a, b) +} + +fn mul_uint(a: Term, b: Term) -> Term { + term![Op::BvNaryOp(BvNaryOp::Mul); a, b] +} + +pub fn mul(a: CTerm, b: CTerm) -> Result { + wrap_bin_arith("*", Some(mul_uint), None, a, b) +} + +fn div_uint(a: Term, b: Term) -> Term { + term![Op::BvBinOp(BvBinOp::Udiv); a, b] +} + +pub fn div(a: CTerm, b: CTerm) -> Result { + wrap_bin_arith("/", Some(div_uint), None, a, b) +} + +fn rem_uint(a: Term, b: Term) -> Term { + term![Op::BvBinOp(BvBinOp::Urem); a, b] +} + +pub fn rem(a: CTerm, b: CTerm) -> Result { + wrap_bin_arith("%", Some(rem_uint), None, a, b) +} + +fn bitand_uint(a: Term, b: Term) -> Term { + term![Op::BvNaryOp(BvNaryOp::And); a, b] +} + +pub fn bitand(a: CTerm, b: CTerm) -> Result { + wrap_bin_arith("&", Some(bitand_uint), None, a, b) +} + +fn bitor_uint(a: Term, b: Term) -> Term { + term![Op::BvNaryOp(BvNaryOp::Or); a, b] +} + +pub fn bitor(a: CTerm, b: CTerm) -> Result { + wrap_bin_arith("|", Some(bitor_uint), None, a, b) +} + +fn bitxor_uint(a: Term, b: Term) -> Term { + term![Op::BvNaryOp(BvNaryOp::Xor); a, b] +} + +pub fn bitxor(a: CTerm, b: CTerm) -> Result { + wrap_bin_arith("^", Some(bitxor_uint), None, a, b) +} + +fn wrap_bin_logical( + name: &str, + fu: Option Term>, + fb: Option Term>, + a: CTerm, + b: CTerm, +) -> Result { + let a_bool = cast(Some(Ty::Bool), a); + let b_bool = cast(Some(Ty::Bool), b); + match (a_bool.term, b_bool.term, fu, fb) { + (CTermData::CBool(a), CTermData::CBool(b), _, Some(fb)) => Ok(CTerm { + term: CTermData::CBool(fb(a, b)), + udef: false, + }), + (x, y, _, _) => Err(format!("Cannot perform op '{}' on {} and {}", name, x, y)), + } +} + +fn or_bool(a: Term, b: Term) -> Term { + term![Op::BoolNaryOp(BoolNaryOp::Or); a, b] +} + +pub fn or(a: CTerm, b: CTerm) -> Result { + wrap_bin_logical("||", None, Some(or_bool), a, b) +} + +fn and_bool(a: Term, b: Term) -> Term { + term![Op::BoolNaryOp(BoolNaryOp::And); a, b] +} + +pub fn and(a: CTerm, b: CTerm) -> Result { + wrap_bin_logical("&&", None, Some(and_bool), a, b) +} + +fn wrap_bin_cmp( + name: &str, + fu: Option Term>, + fb: Option Term>, + a: CTerm, + b: CTerm, +) -> Result { + let (a_arith, b_arith) = usual_arith_conversions(a, b); + match (a_arith.term, b_arith.term, fu, fb) { + (CTermData::CInt(_, nx, x), CTermData::CInt(_, ny, y), Some(fu), _) if nx == ny => { + Ok(CTerm { + term: CTermData::CBool(fu(x, y)), + udef: false, + }) + } + (CTermData::CBool(x), CTermData::CBool(y), _, Some(fb)) => Ok(CTerm { + term: CTermData::CBool(fb(x, y)), + udef: false, + }), + (x, y, _, _) => Err(format!("Cannot perform op '{}' on {} and {}", name, x, y)), + } +} + +fn eq_base(a: Term, b: Term) -> Term { + term![Op::Eq; a, b] +} + +pub fn eq(a: CTerm, b: CTerm) -> Result { + wrap_bin_cmp("==", Some(eq_base), Some(eq_base), a, b) +} + +fn ult_uint(a: Term, b: Term) -> Term { + term![Op::BvBinPred(BvBinPred::Ult); a, b] +} + +pub fn ult(a: CTerm, b: CTerm) -> Result { + wrap_bin_cmp("<", Some(ult_uint), None, a, b) +} + +fn ule_uint(a: Term, b: Term) -> Term { + term![Op::BvBinPred(BvBinPred::Ule); a, b] +} + +pub fn ule(a: CTerm, b: CTerm) -> Result { + wrap_bin_cmp("<=", Some(ule_uint), None, a, b) +} + +fn ugt_uint(a: Term, b: Term) -> Term { + term![Op::BvBinPred(BvBinPred::Ugt); a, b] +} + +pub fn ugt(a: CTerm, b: CTerm) -> Result { + wrap_bin_cmp(">", Some(ugt_uint), None, a, b) +} + +fn uge_uint(a: Term, b: Term) -> Term { + term![Op::BvBinPred(BvBinPred::Uge); a, b] +} + +pub fn uge(a: CTerm, b: CTerm) -> Result { + wrap_bin_cmp(">=", Some(uge_uint), None, a, b) +} + +pub fn const_int(a: CTerm) -> Result { + let s = match &a.term { + CTermData::CInt(s, _, i) => match &i.op { + Op::Const(Value::BitVector(f)) => { + if *s { + Some(f.as_sint()) + } else { + Some(f.uint().clone()) + } + } + _ => None, + }, + _ => None, + }; + s.ok_or_else(|| format!("{} is not a constant integer", a)) +} + +fn wrap_shift(name: &str, op: BvBinOp, a: CTerm, b: CTerm) -> Result { + let bc = const_int(b)?; + match &a.term { + CTermData::CInt(s, na, a) => Ok(CTerm { + term: CTermData::CInt(*s, *na, term![Op::BvBinOp(op); a.clone(), bv_lit(bc, *na)]), + udef: false, + }), + x => Err(format!("Cannot perform op '{}' on {} and {}", name, x, bc)), + } +} + +pub fn shl(a: CTerm, b: CTerm) -> Result { + wrap_shift("<<", BvBinOp::Shl, a, b) +} + +pub fn shr(a: CTerm, b: CTerm) -> Result { + wrap_shift(">>", BvBinOp::Lshr, a, b) +} + +fn _ite(c: Term, a: CTerm, b: CTerm) -> Result { + match (a.term, b.term) { + (CTermData::CInt(sa, na, a), CTermData::CInt(sb, nb, b)) if na == nb => Ok(CTerm { + term: CTermData::CInt(sa && sb, na, term![Op::Ite; c, a, b]), + udef: false, + }), + (CTermData::CBool(a), CTermData::CBool(b)) => Ok(CTerm { + term: CTermData::CBool(term![Op::Ite; c, a, b]), + udef: false, + }), + (x, y) => Err(format!("Cannot perform ITE on {} and {}", x, y)), + } +} + +// fn array>(elems: I) -> Result { +// let v: Vec = elems.into_iter().collect(); +// if let Some(e) = v.first() { +// let ty = e.term.type_(); +// if v.iter().skip(1).any(|a| a.term.type_() != ty) { +// Err(format!("Inconsistent types in array")) +// } else { +// Ok(CTerm { +// term: CTermData::CArray(ty), +// udef: false, +// }) +// } +// } else { +// Err(format!("Empty array")) +// } +// } + +pub struct Ct { + values: Option>, +} + +fn idx_name(struct_name: &str, idx: usize) -> String { + format!("{}.{}", struct_name, idx) +} + +impl Ct { + pub fn new(values: Option>) -> Self { + Self { values } + } +} + +impl Embeddable for Ct { + type T = CTerm; + type Ty = Ty; + fn declare( + &self, + ctx: &mut CirCtx, + ty: &Self::Ty, + raw_name: String, + user_name: Option, + visibility: Option, + ) -> Self::T { + let get_int_val = || -> Integer { + self.values + .as_ref() + .and_then(|vs| { + user_name + .as_ref() + .and_then(|n| vs.get(n)) + .or_else(|| vs.get(&raw_name)) + }) + .cloned() + .unwrap_or_else(|| Integer::from(0)) + }; + match ty { + Ty::Bool => Self::T { + term: CTermData::CBool(ctx.cs.borrow_mut().new_var( + &raw_name, + Sort::Bool, + || Value::Bool(get_int_val() != 0), + visibility, + )), + udef: false, + }, + Ty::Int(s, w) => Self::T { + term: CTermData::CInt( + *s, + *w, + ctx.cs.borrow_mut().new_var( + &raw_name, + Sort::BitVector(*w), + || Value::BitVector(BitVector::new(get_int_val(), *w)), + visibility, + ), + ), + udef: false, + }, + Ty::Array(n, ty) => { + let v: Vec = (0..n.unwrap()) + .map(|i| { + self.declare( + ctx, + &*ty, + idx_name(&raw_name, i), + user_name.as_ref().map(|u| idx_name(u, i)), + visibility, + ) + }) + .collect(); + let mut mem = ctx.mem.borrow_mut(); + let id = mem.zero_allocate(n.unwrap(), 32, ty.num_bits()); + let arr = Self::T { + term: CTermData::CArray(*ty.clone(), Some(id)), + udef: false, + }; + for (i, t) in v.iter().enumerate() { + let val = t.term.terms()[0].clone(); + let t_term = leaf_term(Op::Const(Value::Bool(true))); + mem.store(id, bv_lit(i, 32), val, t_term); + } + arr + } + } + } + fn ite(&self, _ctx: &mut CirCtx, cond: Term, t: Self::T, f: Self::T) -> Self::T { + match (t.term, f.term) { + (CTermData::CBool(a), CTermData::CBool(b)) => Self::T { + term: CTermData::CBool(term![Op::Ite; cond, a, b]), + udef: false, + }, + (CTermData::CInt(sa, wa, a), CTermData::CInt(sb, wb, b)) if wa == wb => Self::T { + term: CTermData::CInt(sa && sb, wa, term![Op::Ite; cond, a, b]), + udef: false, + }, + // (CTermData::CArray(a_ty, a), CTermData::CArray(b_ty, b)) if a_ty == b_ty => Self::T { + // term: CTermData::CArray( + // a_ty, + // a.into_iter() + // .zip(b.into_iter()) + // .map(|(a_i, b_i)| self.ite(ctx, cond.clone(), a_i, b_i)) + // .collect(), + // ), + // udef: false, + // }, + (t, f) => panic!("Cannot ITE {} and {}", t, f), + } + } + + fn assign( + &self, + ctx: &mut CirCtx, + ty: &Self::Ty, + name: String, + t: Self::T, + visibility: Option, + ) -> Self::T { + assert!(&t.term.type_() == ty); + match (ty, t.term) { + (_, CTermData::CBool(b)) => Self::T { + term: CTermData::CBool(ctx.cs.borrow_mut().assign(&name, b, visibility)), + udef: false, + }, + (_, CTermData::CInt(s, w, b)) => Self::T { + term: CTermData::CInt(s, w, ctx.cs.borrow_mut().assign(&name, b, visibility)), + udef: false, + }, + // (_, CTermData::CArray(ety, list)) => Self::T { + // term: CTermData::CArray( + // ety.clone(), + // list.into_iter() + // .enumerate() + // .map(|(i, elem)| { + // self.assign(ctx, &ety, idx_name(&name, i), elem, visibility.clone()) + // }) + // .collect(), + // ), + // udef: false, + // }, + _ => unimplemented!(), + } + } + + fn values(&self) -> bool { + self.values.is_some() + } + + fn type_of(&self, cterm: &Self::T) -> Self::Ty { + cterm.term.type_() + } + + fn initialize_return(&self, ty: &Self::Ty, _ssa_name: &String) -> Self::T { + ty.default() + } +} diff --git a/src/front/c/types.rs b/src/front/c/types.rs new file mode 100644 index 00000000..0a90623d --- /dev/null +++ b/src/front/c/types.rs @@ -0,0 +1,114 @@ +//! C Types +use crate::front::c::term::CTerm; +use crate::front::c::term::CTermData; +use crate::ir::term::*; + +use std::fmt::{self, Display, Formatter}; + +#[derive(Clone, PartialEq, Eq)] +pub enum Ty { + Bool, + Int(bool, usize), + Array(Option, Box), +} + +impl Display for Ty { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + match self { + Ty::Bool => write!(f, "bool"), + Ty::Int(s, w) => { + if *s { + write!(f, "s{}", w) + } else { + write!(f, "u{}", w) + } + } + Ty::Array(_, b) => write!(f, "{}[]", b), + } + } +} + +impl fmt::Debug for Ty { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + +impl Ty { + pub fn default(&self) -> CTerm { + match self { + Self::Bool => CTerm { + term: CTermData::CBool(leaf_term(Op::Const(Value::Bool(false)))), + udef: false, + }, + Self::Int(s, w) => CTerm { + term: CTermData::CInt(*s, *w, bv_lit(0, *w)), + udef: false, + }, + Self::Array(_s, ty) => CTerm { + term: CTermData::CArray(*ty.clone(), None), + udef: false, + }, + } + } + + pub fn is_arith_type(&self) -> bool { + matches!(self, Ty::Int(_, _) | Ty::Bool) + } + + pub fn is_signed_int(&self) -> bool { + if let Ty::Int(s, w) = self { + if *w == 8 || *w == 16 || *w == 32 || *w == 64 { + return *s; + } + return false; + } + false + } + + pub fn is_unsigned_int(&self) -> bool { + if let Ty::Int(s, w) = self { + if !*s && (*w == 8 || *w == 16 || *w == 32 || *w == 64) { + return !*s; + } + return *s; + } + false + } + + pub fn is_integer_type(&self) -> bool { + self.is_signed_int() || self.is_unsigned_int() + } + + pub fn int_conversion_rank(&self) -> usize { + match self { + Ty::Int(_, w) => *w, + Ty::Bool => 1, + _ => panic!("int_conversion_rank received a non-int type: {:#?}", self), + } + } + + pub fn _total_num_bits(&self, ty: Ty) -> usize { + match ty { + Ty::Int(_, w) => w, + Ty::Bool => 1, + Ty::Array(s, t) => s.unwrap() * t.num_bits(), + } + } + + pub fn num_bits(&self) -> usize { + match self { + Ty::Int(_, w) => *w, + Ty::Bool => 1, + Ty::Array(_, _) => 32, + } + } + + pub fn inner_ty(self) -> Ty { + match self { + Ty::Int(_, _) => self, + Ty::Bool => self, + Ty::Array(_, t) => *t, + } + } +} diff --git a/src/front/mod.rs b/src/front/mod.rs index 87e9b11f..bbea821e 100644 --- a/src/front/mod.rs +++ b/src/front/mod.rs @@ -1,10 +1,12 @@ //! Input language front-ends +pub mod c; pub mod datalog; #[allow(clippy::all)] pub mod zokrates; use super::ir::term::Computation; +use std::fmt::{self, Display, Formatter}; /// A front-end pub trait FrontEnd { @@ -14,3 +16,29 @@ pub trait FrontEnd { /// Compile the program (and possibly assignment) to constraints fn gen(i: Self::Inputs) -> Computation; } + +#[derive(Clone, Copy, Debug)] +/// Kind of circuit to generate. Effects privacy labels. +pub enum Mode { + /// Generating an MPC circuit. Inputs are public or private (to a party in 1..N). + Mpc(u8), + /// Generating for a proof circuit. Inputs are public of private (to the prover). + Proof, + /// Generating for an optimization circuit. Inputs are existentially quantified. + /// There should be only one output, which will be maximized. + Opt, + /// Find inputs that yeild an output at least this large, + /// and then prove knowledge of them. + ProofOfHighValue(u64), +} + +impl Display for Mode { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match *self { + Mode::Mpc(n) => write!(f, "{}-pc", n), + Mode::Proof => write!(f, "proof"), + Mode::Opt => write!(f, "opt"), + Mode::ProofOfHighValue(v) => write!(f, "proof_of_high_value({})", v), + } + } +} diff --git a/src/front/zokrates/mod.rs b/src/front/zokrates/mod.rs index b27725c9..da9e216a 100644 --- a/src/front/zokrates/mod.rs +++ b/src/front/zokrates/mod.rs @@ -3,7 +3,7 @@ mod parser; mod term; -use super::FrontEnd; +use super::{FrontEnd, Mode}; use crate::circify::{Circify, Loc, Val}; use crate::ir::proof::{self, ConstraintMetadata}; use crate::ir::term::extras::Letified; @@ -11,7 +11,7 @@ use crate::ir::term::*; use log::debug; use rug::Integer; use std::collections::HashMap; -use std::fmt::{self, Display, Formatter}; +use std::fmt::Display; use std::path::{Path, PathBuf}; use std::str::FromStr; use zokrates_pest_ast as ast; @@ -30,7 +30,7 @@ pub const PROVER_VIS: Option = Some(proof::PROVER_ID); /// Public visibility pub const PUBLIC_VIS: Option = None; -/// Inputs to the ZoKrates compilier +/// Inputs to the ZoKrates compiler pub struct Inputs { /// The file to look for `main` in. pub file: PathBuf, @@ -49,32 +49,6 @@ pub struct Inputs { pub mode: Mode, } -#[derive(Clone, Copy, Debug)] -/// Kind of circuit to generate. Effects privacy labels. -pub enum Mode { - /// Generating an MPC circuit. Inputs are public or private (to a party in 1..N). - Mpc(u8), - /// Generating for a proof circuit. Inputs are public of private (to the prover). - Proof, - /// Generating for an optimization circuit. Inputs are existentially quantified. - /// There should be only one output, which will be maximized. - Opt, - /// Find inputs that yeild an output at least this large, - /// and then prove knowledge of them. - ProofOfHighValue(u64), -} - -impl Display for Mode { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - match self { - &Mode::Mpc(n) => write!(f, "{}-pc", n), - &Mode::Proof => write!(f, "proof"), - &Mode::Opt => write!(f, "opt"), - &Mode::ProofOfHighValue(v) => write!(f, "proof_of_high_value({})", v), - } - } -} - /// The ZoKrates front-end. Implements [FrontEnd]. pub struct Zokrates; diff --git a/src/ir/opt/binarize.rs b/src/ir/opt/binarize.rs new file mode 100644 index 00000000..487ddf10 --- /dev/null +++ b/src/ir/opt/binarize.rs @@ -0,0 +1,121 @@ +//! Binarize terms + +use crate::ir::term::*; + +/// Binarize cache. +#[derive(Default)] +pub struct Cache(TermMap); + +impl Cache { + /// Empty cache. + pub fn new() -> Self { + Cache(TermMap::new()) + } +} + +fn binarize(op: &Op, children: &[Term]) -> Term { + if children.is_empty() || children.len() == 1 { + term(op.clone(), children.to_vec()) + } else { + children[2..].to_vec().iter().fold( + term![op.clone(); children[1].clone(), children[0].clone()], + |acc, x| term![op.clone(); x.clone(), acc], + ) + } +} + +/// Traverse `term`, binarize n-ary operators. +pub fn binarize_nary_ops(term_: Term) -> Term { + let mut c = Cache::new(); + binarize_nary_ops_cached(term_, &mut c) +} +/// Traverse `term`, binarize n-ary operators. +pub fn binarize_nary_ops_cached(term_: Term, Cache(ref mut rewritten): &mut Cache) -> Term { + let mut stack = vec![(term_.clone(), false)]; + + // Maps terms to their rewritten versions. + while let Some((t, children_pushed)) = stack.pop() { + if rewritten.contains_key(&t) { + continue; + } + if !children_pushed { + stack.push((t.clone(), true)); + stack.extend(t.cs.iter().map(|c| (c.clone(), false))); + continue; + } + let entry = match &t.op { + Op::BoolNaryOp(_) | Op::BvNaryOp(_) | Op::PfNaryOp(_) => binarize(&t.op, &t.cs), + _ => t.clone(), + }; + rewritten.insert(t, entry); + } + + for t in PostOrderIter::new(term_.clone()) { + let mut children = Vec::new(); + for c in &t.cs { + if let Some(rewritten_c) = rewritten.get(c) { + children.push(rewritten_c.clone()); + } else { + children.push(c.clone()); + } + } + let entry = match t.op { + Op::BoolNaryOp(_) | Op::BvNaryOp(_) | Op::PfNaryOp(_) => binarize(&t.op, &children), + _ => term(t.op.clone(), children), + }; + rewritten.insert(t.clone(), entry); + } + + if let Some(t) = rewritten.get(&term_) { + t.clone() + } else { + panic!("Couldn't find rewritten binarized term: {}", term_); + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::ir::term::dist::test::*; + use quickcheck_macros::quickcheck; + + fn bool(b: bool) -> Term { + leaf_term(Op::Const(Value::Bool(b))) + } + + fn is_binary(t: Term) -> bool { + PostOrderIter::new(t).all(|c| match c.op { + Op::BoolNaryOp(_) | Op::BvNaryOp(_) | Op::PfNaryOp(_) => c.cs.len() <= 2, + _ => true, + }) + } + + #[quickcheck] + fn binarize_random(ArbitraryTerm(t): ArbitraryTerm) -> bool { + is_binary(binarize_nary_ops(t)) + } + + #[quickcheck] + fn binarize_semantics_random(ArbitraryTermEnv(t, vs): ArbitraryTermEnv) -> bool { + let tt = binarize_nary_ops(t.clone()); + eval(&t, &vs) == eval(&tt, &vs) + } + + #[test] + fn simple_bool() { + for o in vec![AND, OR, XOR] { + let t = term![o.clone(); bool(true), term![o.clone(); bool(false), bool(true)]]; + let tt = term![o.clone(); bool(true), bool(false), bool(true)]; + assert_eq!(t, binarize_nary_ops(tt)); + } + } + + #[test] + fn simple_bv() { + for o in vec![BV_AND, BV_OR, BV_XOR, BV_ADD, BV_MUL] { + let t = term![o.clone(); bv_lit(3,5), term![o.clone(); bv_lit(3,5), bv_lit(3,5)]]; + let tt = term![o.clone(); bv_lit(3, 5), bv_lit(3, 5), bv_lit(3, 5)]; + assert_eq!(t, binarize_nary_ops(tt)); + } + } +} diff --git a/src/ir/opt/cfold.rs b/src/ir/opt/cfold.rs index 08b18482..aafd731b 100644 --- a/src/ir/opt/cfold.rs +++ b/src/ir/opt/cfold.rs @@ -85,6 +85,10 @@ pub fn fold_cache(node: &Term, cache: &mut TermMap) -> Term { match (o, c0.as_bv_opt(), c1.as_bv_opt()) { (Sub, Some(a), Some(b)) => cbv(a.clone() - b.clone()), (Sub, _, Some(b)) if b.uint() == &Integer::from(0) => Some(c0.clone()), + (Udiv, _, Some(b)) if b.uint() == &Integer::from(0) => Some(bv_lit( + (Integer::from(1) << b.width() as u32) - 1, + b.width(), + )), (Udiv, Some(a), Some(b)) => cbv(a.clone() / b), (Udiv, _, Some(b)) if b.uint() == &Integer::from(1) => Some(c0.clone()), (Udiv, _, Some(b)) if b.uint() == &Integer::from(-1) => { diff --git a/src/ir/opt/mem/visit.rs b/src/ir/opt/mem/visit.rs deleted file mode 100644 index e69de29b..00000000 diff --git a/src/ir/opt/mod.rs b/src/ir/opt/mod.rs index ff9b79b0..e9006101 100644 --- a/src/ir/opt/mod.rs +++ b/src/ir/opt/mod.rs @@ -1,4 +1,5 @@ //! Optimizations +pub mod binarize; pub mod cfold; pub mod flat; pub mod inline; @@ -21,6 +22,8 @@ pub enum Opt { ConstantFold, /// Flatten n-ary operators Flatten, + /// Binarize n-ary operators + Binarize, /// SHA-2 peephole optimizations Sha, /// Replace oblivious arrays with tuples @@ -78,6 +81,12 @@ pub fn opt>(mut cs: Computation, optimizations: I) - *a = flat::flatten_nary_ops_cached(a.clone(), &mut cache); } } + Opt::Binarize => { + let mut cache = binarize::Cache::new(); + for a in &mut cs.outputs { + *a = binarize::binarize_nary_ops_cached(a.clone(), &mut cache); + } + } Opt::Inline => { let public_inputs = cs .metadata diff --git a/src/target/aby/assignment/ilp.rs b/src/target/aby/assignment/ilp.rs index 4e807651..15aa3e5c 100644 --- a/src/target/aby/assignment/ilp.rs +++ b/src/target/aby/assignment/ilp.rs @@ -54,72 +54,79 @@ impl CostModel { pub fn from_opa_cost_file(p: &impl AsRef) -> CostModel { use ShareType::*; let get_cost_opt = - |op_name: &str, obj: &serde_json::map::Map| -> Option { - let o = obj.get(op_name)?; + |share_name: &str, obj: &serde_json::map::Map| -> Option { + let o = obj.get(share_name)?; Some( - o.get("1") - .unwrap_or_else(|| panic!("Missing op '1' entry in {:#?}", o)) + o.get("32") + .unwrap_or_else(|| panic!("Missing op '32' entry in {:#?}", o)) .as_f64() .expect("not a number"), ) }; let get_cost = |op_name: &str, obj: &serde_json::map::Map| -> f64 { - get_cost_opt(op_name, obj).unwrap() + let o = obj + .get(op_name) + .unwrap_or_else(|| panic!("Missing op {} in {:#?}", op_name, obj)); + Some( + o.get("32") + .unwrap_or_else(|| panic!("Missing op '32' entry in {:#?}", o)) + .as_f64() + .expect("not a number"), + ) + .unwrap() }; let mut conversions = FxHashMap::default(); let mut ops = FxHashMap::default(); let f = File::open(p).expect("Missing file"); let json: Value = serde_json::from_reader(f).expect("Bad JSON"); - let obj = json.as_object().unwrap(); - for (_width, json) in obj { - //let w = u32::from_str(width).expect("bad width"); - let obj = json.as_object().unwrap(); + let costs = json.as_object().unwrap(); + // conversions + conversions.insert((Arithmetic, Boolean), get_cost("a2b", costs)); + conversions.insert((Boolean, Arithmetic), get_cost("b2a", costs)); + conversions.insert((Yao, Boolean), get_cost("y2b", costs)); + conversions.insert((Boolean, Yao), get_cost("b2y", costs)); + conversions.insert((Yao, Arithmetic), get_cost("y2a", costs)); + conversions.insert((Arithmetic, Yao), get_cost("a2y", costs)); - // conversions - conversions.insert((Arithmetic, Boolean), get_cost("a2b", obj)); - conversions.insert((Boolean, Arithmetic), get_cost("b2a", obj)); - conversions.insert((Yao, Boolean), get_cost("y2b", obj)); - conversions.insert((Boolean, Yao), get_cost("b2y", obj)); - conversions.insert((Yao, Arithmetic), get_cost("y2a", obj)); - conversions.insert((Arithmetic, Yao), get_cost("a2y", obj)); - - let ops_from_name = |name: &str| { - match name { - // assume comparisions are unsigned - "ge" => vec![BV_UGE], - "le" => vec![BV_ULE], - "gt" => vec![BV_UGT], - "lt" => vec![BV_ULT], - // assume n-ary ops apply to BVs - "add" => vec![BV_ADD], - "mul" => vec![BV_MUL], - "and" => vec![BV_AND], - "or" => vec![BV_OR], - "xor" => vec![BV_XOR], - // assume eq applies to BVs - "eq" => vec![Op::Eq], - "shl" => vec![BV_SHL], - // assume shr is logical, not arithmetic - "shr" => vec![BV_LSHR], - "sub" => vec![BV_SUB], - "mux" => vec![ITE], - "ne" => vec![], - _ => panic!("Unknown operator name: {}", name), - } - }; - for (op_name, json) in obj { - // HACK: assumes the presence of 2 partitions names into conversion and otherwise. - if !op_name.contains('2') { - for op in ops_from_name(op_name) { - let obj = json.as_object().unwrap(); - for (share_type, share_name) in - &[(Arithmetic, "a"), (Boolean, "b"), (Yao, "y")] - { - if let Some(cost) = get_cost_opt(share_name, obj) { - ops.entry(op.clone()) - .or_insert_with(FxHashMap::default) - .insert(*share_type, cost); - } + let ops_from_name = |name: &str| { + match name { + // assume comparisions are unsigned + "ge" => vec![BV_UGE], + "le" => vec![BV_ULE], + "gt" => vec![BV_UGT], + "lt" => vec![BV_ULT], + // assume n-ary ops apply to BVs + "add" => vec![BV_ADD], + "mul" => vec![BV_MUL], + "and" => vec![BV_AND], + "or" => vec![BV_OR], + "xor" => vec![BV_XOR], + // assume eq applies to BVs + "eq" => vec![Op::Eq], + "shl" => vec![BV_SHL], + // assume shr is logical, not arithmetic + "shr" => vec![BV_LSHR], + "sub" => vec![BV_SUB], + "mux" => vec![ITE], + "ne" => vec![Op::Not, Op::Eq], + "div" => vec![BV_UDIV], + "rem" => vec![BV_UREM], + // added to pass test case + "&&" => vec![AND], + "||" => vec![OR], + _ => panic!("Unknown operator name: {}", name), + } + }; + for (op_name, cost) in costs { + // HACK: assumes the presence of 2 partitions names into conversion and otherwise. + if !op_name.contains('2') { + for op in ops_from_name(op_name) { + for (share_type, share_name) in &[(Arithmetic, "a"), (Boolean, "b"), (Yao, "y")] + { + if let Some(c) = get_cost_opt(share_name, cost.as_object().unwrap()) { + ops.entry(op.clone()) + .or_insert_with(FxHashMap::default) + .insert(*share_type, c); } } } @@ -130,10 +137,16 @@ impl CostModel { } /// Uses an ILP to assign... -pub fn assign(c: &Computation) -> SharingMap { +pub fn assign(c: &Computation, cm: &str) -> SharingMap { + let base_dir = match cm { + "opa" => "opa", + "hycc" => "hycc", + _ => panic!("Unknown cost model type: {}", cm), + }; let p = format!( - "{}/third_party/opa/sample_costs.json", - var("CARGO_MANIFEST_DIR").expect("Could not find env var CARGO_MANIFEST_DIR") + "{}/third_party/{}/adapted_costs.json", + var("CARGO_MANIFEST_DIR").expect("Could not find env var CARGO_MANIFEST_DIR"), + base_dir ); let costs = CostModel::from_opa_cost_file(&p); build_ilp(c, &costs) @@ -264,7 +277,7 @@ mod tests { #[test] fn parse_cost_model() { let p = format!( - "{}/third_party/opa/sample_costs.json", + "{}/third_party/opa/adapted_costs.json", var("CARGO_MANIFEST_DIR").expect("Could not find env var CARGO_MANIFEST_DIR") ); let c = CostModel::from_opa_cost_file(&p); @@ -294,7 +307,7 @@ mod tests { #[test] fn mul1_bv_opt() { let p = format!( - "{}/third_party/opa/sample_costs.json", + "{}/third_party/opa/adapted_costs.json", var("CARGO_MANIFEST_DIR").expect("Could not find env var CARGO_MANIFEST_DIR") ); let costs = CostModel::from_opa_cost_file(&p); @@ -312,7 +325,7 @@ mod tests { #[test] fn huge_mul_then_eq() { let p = format!( - "{}/third_party/opa/sample_costs.json", + "{}/third_party/opa/adapted_costs.json", var("CARGO_MANIFEST_DIR").expect("Could not find env var CARGO_MANIFEST_DIR") ); let costs = CostModel::from_opa_cost_file(&p); @@ -358,7 +371,7 @@ mod tests { #[test] fn big_mul_then_eq() { let p = format!( - "{}/third_party/opa/sample_costs.json", + "{}/third_party/opa/adapted_costs.json", var("CARGO_MANIFEST_DIR").expect("Could not find env var CARGO_MANIFEST_DIR") ); let costs = CostModel::from_opa_cost_file(&p); diff --git a/src/target/aby/mod.rs b/src/target/aby/mod.rs index b6489e5d..abb8b001 100644 --- a/src/target/aby/mod.rs +++ b/src/target/aby/mod.rs @@ -2,32 +2,4 @@ pub mod assignment; pub mod output; pub mod trans; - -#[derive(Clone, Debug)] -/// ABY Circuit -/// The ABY Circuit consists of three Vec: setup, circ, and closer -/// *setup* holds code for initializing the ABY party, sharing scheme, and input values -/// *circs* holds the lowered code from the IR to ABY Circuits -/// *output* holds the code for printing the output value -pub struct ABY { - setup: Vec, - circs: Vec, - output: Vec, -} - -impl Default for ABY { - fn default() -> Self { - Self::new() - } -} - -impl ABY { - /// Initialize ABY circuit - pub fn new() -> Self { - ABY { - setup: Vec::new(), - circs: Vec::new(), - output: Vec::new(), - } - } -} +pub mod utils; diff --git a/src/target/aby/output.rs b/src/target/aby/output.rs index 93ede884..5b7e9360 100644 --- a/src/target/aby/output.rs +++ b/src/target/aby/output.rs @@ -1,15 +1,13 @@ //! Utility functions to write compiler output to ABY -use crate::target::aby::*; use std::fs; use std::fs::{File, OpenOptions}; use std::io::{prelude::*, BufRead, BufReader}; use std::path::Path; -use std::path::PathBuf; -/// Given PathBuf `path_buf`, return the filename of the path -fn get_filename(path_buf: PathBuf) -> String { - Path::new(&path_buf.iter().last().unwrap().to_os_string()) +/// Given Path `path`, return the filename of the path +fn get_filename(path: &Path) -> String { + Path::new(&path.iter().last().unwrap().to_os_string()) .file_stem() .unwrap() .to_os_string() @@ -46,8 +44,7 @@ fn update_cmake_file(filename: &str) { .open(cmake_filename) .unwrap(); - writeln!(file, "{}", format!("add_subdirectory({})", filename)) - .expect("Failed to write to cmake file"); + writeln!(file, "add_subdirectory({})", filename).expect("Failed to write to cmake file"); } } @@ -94,7 +91,23 @@ fn write_h_file(filename: &str) { } /// Using the cpp_template.txt, write the .cpp file for the new test case -fn write_circ_file(filename: &str, circ: &str, output: &str) { +fn write_circ_file(filename: &str) { + let setup_file_path = format!("third_party/ABY/src/examples/{}_setup_tmp.txt", filename); + let mut setup_file = File::open(setup_file_path).expect("Unable to open the file"); + let mut setup = String::new(); + setup_file + .read_to_string(&mut setup) + .expect("Unable to read the file"); + + let circuit_file_path = format!("third_party/ABY/src/examples/{}_circuit_tmp.txt", filename); + let mut circuit_file = File::open(circuit_file_path).expect("Unable to open the file"); + let mut circuit = String::new(); + circuit_file + .read_to_string(&mut circuit) + .expect("Unable to read the file"); + + let content = format!("{}\n{}", setup, circuit); + let template = fs::read_to_string("third_party/ABY_templates/cpp_template.txt") .expect("Unable to read file"); let path = format!( @@ -105,21 +118,20 @@ fn write_circ_file(filename: &str, circ: &str, output: &str) { fs::write( &path, template - .replace("{fn}", filename) - .replace("{circ}", circ) - .replace("{output}", output), + .replace("{fn}", &*filename) + .replace("{circ}", &content), ) .expect("Failed to write to cpp file"); } /// Write circuit output from translation later to ABY -pub fn write_aby_exec(aby: ABY, path_buf: PathBuf) { - let filename = get_filename(path_buf); - create_dir_in_aby(&filename); - update_cmake_file(&filename); - write_test_cmake_file(&filename); - write_test_file(&filename); - write_h_file(&filename); - let circ_str = aby.setup.join("\n\t") + &aby.circs.join("\n\t"); - write_circ_file(&filename, &circ_str, &aby.output.join("\n\t")); +pub fn write_aby_exec(path: &Path, lang: &str) { + let filename = get_filename(path); + let name = format!("{}_{}", filename, lang); + create_dir_in_aby(&name); + update_cmake_file(&name); + write_test_cmake_file(&name); + write_test_file(&name); + write_h_file(&name); + write_circ_file(&name); } diff --git a/src/target/aby/trans.rs b/src/target/aby/trans.rs index 1220b488..983b2b29 100644 --- a/src/target/aby/trans.rs +++ b/src/target/aby/trans.rs @@ -5,9 +5,12 @@ //! [Link to comment in EzPC Compiler](https://github.com/mpc-msri/EzPC/blob/da94a982709123c8186d27c9c93e27f243d85f0e/EzPC/EzPC/codegen.ml) use crate::ir::term::*; -// use crate::target::aby::assignment::ilp::assign; -use crate::target::aby::assignment::{some_arith_sharing, ShareType, SharingMap}; -use crate::target::aby::*; +use crate::target::aby::assignment::ilp::assign; +use crate::target::aby::assignment::{ShareType, SharingMap}; +use crate::target::aby::utils::*; +use std::fmt; + +use std::path::Path; const NO_ROLE: u8 = u8::MAX; const SERVER: u8 = 0; @@ -20,39 +23,71 @@ enum EmbeddedTerm { Bv(String), } +impl fmt::Display for EmbeddedTerm { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self) + } +} + struct ToABY { - aby: ABY, md: ComputationMetadata, inputs: TermMap>, cache: TermMap, s_map: SharingMap, + share_cnt: i32, + setup_fname: String, + circuit_fname: String, } impl ToABY { - fn new(metadata: ComputationMetadata, s_map: SharingMap) -> Self { + fn new(metadata: ComputationMetadata, s_map: SharingMap, path: &Path, lang: &str) -> Self { Self { - aby: ABY::new(), md: metadata, inputs: TermMap::new(), cache: TermMap::new(), s_map, + share_cnt: 0, + setup_fname: get_path(path, lang, &String::from("setup")), + circuit_fname: get_path(path, lang, &String::from("circuit")), } } - fn get_var_name(t: Term) -> String { + fn get_var_name(t: Term, b: bool) -> String { match &t.op { - Op::Var(name, _) => name.to_string(), + Op::Var(name, _) => { + if b { + name.to_string().replace(".", "_") + } else { + name.to_string() + } + } _ => panic!("Term {} is not of type Var", t), } } + fn get_share_name(&mut self) -> String { + format!("s_{}", self.share_cnt) + } + + fn inc_share(&mut self) { + self.share_cnt += 1; + } + /// Parse variable name from IR representation of a variable fn parse_var_name(&self, full_name: String) -> String { let parsed: Vec = full_name.split('_').map(str::to_string).collect(); if parsed.len() < 2 { panic!("Invalid variable name: {}", full_name); } - parsed[parsed.len() - 2].to_string() + let mut name = parsed[parsed.len() - 2].to_string(); + if full_name.contains('.') { + let index: Vec = full_name.split('.').map(str::to_string).collect(); + if index.is_empty() { + panic!("Invalid variable name: {}", full_name); + } + name += &("_".to_owned() + &index[index.len() - 1].to_string()); + } + name } fn get_sharetype_circ(&self, t: Term) -> String { @@ -89,27 +124,27 @@ impl ToABY { } fn add_cons_gate(&self, t: Term) -> String { - let name = ToABY::get_var_name(t.clone()); + let name = ToABY::get_var_name(t.clone(), true); let s_circ = self.get_sharetype_circ(t); format!( - "s_{} = {}->PutCONSGate((uint64_t){}, bitlen);", + "s_{} = {}->PutCONSGate((uint64_t){}, bitlen);\n", name, s_circ, name ) } fn add_in_gate(&self, t: Term, role: String) -> String { - let name = ToABY::get_var_name(t.clone()); + let name = ToABY::get_var_name(t.clone(), true); let s_circ = self.get_sharetype_circ(t); format!( - "\ts_{} = {}->PutINGate({}, bitlen, {});", + "\ts_{} = {}->PutINGate({}, bitlen, {});\n", name, s_circ, name, role ) } fn add_dummy_gate(&self, t: Term) -> String { - let name = ToABY::get_var_name(t.clone()); + let name = ToABY::get_var_name(t.clone(), true); let s_circ = self.get_sharetype_circ(t); - format!("\ts_{} = {}->PutDummyINGate(bitlen);", name, s_circ) + format!("\ts_{} = {}->PutDummyINGate(bitlen);\n", name, s_circ) } /// Initialize private and public inputs from each party @@ -122,21 +157,29 @@ impl ToABY { // Parse input parameters from command line as uint32_t variables // Initialize shares for each party for (t, party) in self.inputs.iter() { - let name = ToABY::get_var_name(t.clone()); - self.aby.setup.push(format!( - "uint32_t {} = std::atoi(params[\"{}\"].c_str());", - name, - self.parse_var_name(name.to_string()) - )); - self.aby - .setup - .push(format!("share *s_{};", name).to_string()); + let name = ToABY::get_var_name(t.clone(), false); + let name_ = ToABY::get_var_name(t.clone(), true); + + write_line_to_file( + &self.setup_fname, + &format!( + "uint32_t {} = std::atoi(params[\"{}\"].c_str());\n", + name_, + self.parse_var_name(name.to_string()) + ), + ); + + write_line_to_file( + &self.setup_fname, + &format!("share* s_{};\n", name_).to_string(), + ); + let role = party.unwrap_or_else(|| NO_ROLE); if role == SERVER { server_inputs.insert(t.clone()); } else if role == CLIENT { client_inputs.insert(t.clone()); - } else if role != SERVER && role != CLIENT && self.md.is_input_public(&name) { + } else if role != SERVER && role != CLIENT && self.md.is_input_public(&name_) { public_inputs.insert(t.clone()); } else { panic!("Unknown role or visibility for variable: {}", name); @@ -145,60 +188,50 @@ impl ToABY { // Initialize public inputs as CONS gateshares for t in public_inputs.iter() { - self.aby.setup.push(self.add_cons_gate(t.clone())); + write_line_to_file(&self.setup_fname, &self.add_cons_gate(t.clone())); } // Initialize Server inputs - self.aby.setup.push("if (role == SERVER) {".to_string()); + write_line_to_file(&self.setup_fname, &String::from("if (role == SERVER) {\n")); + // TODO: add in gates based on type / number of inputs for t in server_inputs.iter() { - self.aby - .setup - .push(self.add_in_gate(t.clone(), "SERVER".to_string())); + write_line_to_file( + &self.setup_fname, + &self.add_in_gate(t.clone(), "SERVER".to_string()), + ); } for t in client_inputs.iter() { - self.aby.setup.push(self.add_dummy_gate(t.clone())); + write_line_to_file(&self.setup_fname, &self.add_dummy_gate(t.clone())); } - self.aby.setup.push("}".to_string()); + write_line_to_file(&self.setup_fname, &String::from("}\n")); // Initialize Client inputs - self.aby.setup.push("if (role == CLIENT) {".to_string()); + write_line_to_file(&self.setup_fname, &String::from("if (role == CLIENT) {\n")); for t in client_inputs.iter() { - self.aby - .setup - .push(self.add_in_gate(t.clone(), "CLIENT".to_string())); + write_line_to_file( + &self.setup_fname, + &self.add_in_gate(t.clone(), "CLIENT".to_string()), + ); } for t in server_inputs.iter() { - self.aby.setup.push(self.add_dummy_gate(t.clone())); + write_line_to_file(&self.setup_fname, &self.add_dummy_gate(t.clone())); } - self.aby.setup.push("}\n".to_string()); + write_line_to_file(&self.setup_fname, &String::from("}\n")); } /// Return constant gate evaluating to 0 + // TODO: const should not be hardcoded to acirc #[allow(dead_code)] - fn zero() -> &'static str { - "bcirc->PutCONSGate((uint64_t)0, (uint32_t)1)" + fn zero() -> String { + "acirc->PutCONSGate((uint64_t)0, (uint32_t)1)".to_string() } /// Return constant gate evaluating to 1 - fn one() -> &'static str { - "bcirc->PutCONSGate((uint64_t)1, (uint32_t)1)" + fn one(s_type: &str) -> String { + format!("{}->PutCONSGate((uint64_t)1, (uint32_t)1)", s_type) } - fn remove_cons_gate(&self, circ: String) -> String { - if circ.contains("PutCONSGate(") { - circ.split("PutCONSGate(") - .last() - .unwrap_or("") - .split(',') - .next() - .unwrap_or("") - .to_string() - } else { - panic!("PutCONSGate not found in: {}", circ) - } - } - - fn embed_eq(&mut self, t: Term, a: Term, b: Term) -> String { + fn embed_eq(&mut self, t: Term, a: Term, b: Term) { let s_circ = self.get_sharetype_circ(t.clone()); match check(&a) { Sort::Bool => { @@ -208,16 +241,20 @@ impl ToABY { let a_conv = self.add_conv_gate(t.clone(), a, a_circ); let b_conv = self.add_conv_gate(t.clone(), b, b_circ); + let share = self.get_share_name(); + self.inc_share(); let s = format!( - "{}->PutXORGate({}->PutXORGate({}, {}), {})", + "share* {} = {}->PutXORGate({}->PutXORGate({}, {}), {});\n", + share, s_circ, s_circ, a_conv, b_conv, - ToABY::one() + ToABY::one(&s_circ) ); - self.cache.insert(t, EmbeddedTerm::Bool(s.clone())); - s + write_line_to_file(&self.circuit_fname, &s); + + self.cache.insert(t, EmbeddedTerm::Bool(share)); } Sort::BitVector(_) => { let a_circ = self.get_bv(&a); @@ -226,12 +263,14 @@ impl ToABY { let a_conv = self.add_conv_gate(t.clone(), a, a_circ); let b_conv = self.add_conv_gate(t.clone(), b, b_circ); + let share = self.get_share_name(); + self.inc_share(); let s = format!( - "{}->PutXORGate({}->PutXORGate({}->PutGTGate({}, {}), {}->PutGTGate({}, {})), {})", - s_circ, s_circ, s_circ, a_conv, b_conv, s_circ, b_conv, a_conv, ToABY::one() + "share* {} = {}->PutXORGate({}->PutXORGate({}->PutGTGate({}, {}), {}->PutGTGate({}, {})), {});\n", + share, s_circ, s_circ, s_circ, a_conv, b_conv, s_circ, b_conv, a_conv, ToABY::one(&s_circ) ); - self.cache.insert(t, EmbeddedTerm::Bool(s.clone())); - s + write_line_to_file(&self.circuit_fname, &s); + self.cache.insert(t, EmbeddedTerm::Bool(share)); } e => panic!("Unimplemented sort for Eq: {:?}", e), } @@ -259,21 +298,25 @@ impl ToABY { .insert(t.clone(), *self.md.input_vis.get(name).unwrap()); } if !self.cache.contains_key(&t) { - self.cache - .insert(t.clone(), EmbeddedTerm::Bool(format!("s_{}", name))); + self.cache.insert( + t.clone(), + EmbeddedTerm::Bool(format!("s_{}", name.replace(".", "_"))), + ); } } Op::Const(Value::Bool(b)) => { - self.cache.insert( - t.clone(), - EmbeddedTerm::Bool(format!( - "{}->PutCONSGate((uint64_t){}, (uint32_t){})", - s_circ, *b as isize, BOOLEAN_BITLEN - )), + let share = self.get_share_name(); + self.inc_share(); + let s = format!( + "share* {} = {}->PutCONSGate((uint64_t){}, (uint32_t){});\n", + share, s_circ, *b as isize, BOOLEAN_BITLEN ); + write_line_to_file(&self.circuit_fname, &s); + + self.cache.insert(t.clone(), EmbeddedTerm::Bool(share)); } Op::Eq => { - let _s = self.embed_eq(t.clone(), t.cs[0].clone(), t.cs[1].clone()); + self.embed_eq(t.clone(), t.cs[0].clone(), t.cs[1].clone()); } Op::Ite => { let sel_circ = self.get_bool(&t.cs[0]); @@ -284,40 +327,52 @@ impl ToABY { let a_conv = self.add_conv_gate(t.clone(), t.cs[1].clone(), a_circ); let b_conv = self.add_conv_gate(t.clone(), t.cs[2].clone(), b_circ); - self.cache.insert( - t.clone(), - EmbeddedTerm::Bool(format!( - "{}->PutMUXGate({}, {}, {})", - s_circ, a_conv, b_conv, sel_conv - )), + let share = self.get_share_name(); + self.inc_share(); + let s = format!( + "share* {} = {}->PutMUXGate({}, {}, {});\n", + share, s_circ, a_conv, b_conv, sel_conv ); + write_line_to_file(&self.circuit_fname, &s); + self.cache.insert(t.clone(), EmbeddedTerm::Bool(share)); } Op::Not => { let a_circ = self.get_bool(&t.cs[0]); let a_conv = self.add_conv_gate(t.clone(), t.cs[0].clone(), a_circ); - self.cache.insert( - t.clone(), - EmbeddedTerm::Bool(format!( - "((BooleanCircuit *) {})->PutINVGate({})", - s_circ, a_conv - )), + + let share = self.get_share_name(); + self.inc_share(); + let s = format!( + "share* {} = ((BooleanCircuit *) {})->PutINVGate({});\n", + share, s_circ, a_conv ); + write_line_to_file(&self.circuit_fname, &s); + self.cache.insert(t.clone(), EmbeddedTerm::Bool(share)); } Op::BoolNaryOp(o) => { - let a_circ = self.get_bool(&t.cs[0]); - let b_circ = self.get_bool(&t.cs[1]); + if t.cs.len() == 1 { + // HACK: Conditionals might not contain two variables + // If t.cs len is 1, just output that term + // This is to bypass adding an AND gate with a single conditional term + // Refer to pub fn condition() in src/circify/mod.rs + let a = self.get_bool(&t.cs[0]); + self.cache.insert(t.clone(), EmbeddedTerm::Bool(a)); + } else { + let a_circ = self.get_bool(&t.cs[0]); + let b_circ = self.get_bool(&t.cs[1]); - let a_conv = self.add_conv_gate(t.clone(), t.cs[0].clone(), a_circ); - let b_conv = self.add_conv_gate(t.clone(), t.cs[1].clone(), b_circ); + let a_conv = self.add_conv_gate(t.clone(), t.cs[0].clone(), a_circ); + let b_conv = self.add_conv_gate(t.clone(), t.cs[1].clone(), b_circ); - if *o == BoolNaryOp::Or { - s_circ = format!("((BooleanCircuit *) {})", s_circ); - } + if *o == BoolNaryOp::Or { + s_circ = format!("((BooleanCircuit *) {})", s_circ); + } - self.cache.insert( - t.clone(), - EmbeddedTerm::Bool(format!( - "{}->{}({}, {})", + let share = self.get_share_name(); + self.inc_share(); + let s = format!( + "share* {} = {}->{}({}, {});\n", + share, s_circ, match o { BoolNaryOp::Or => "PutORGate", @@ -326,8 +381,10 @@ impl ToABY { }, a_conv, b_conv - )), - ); + ); + write_line_to_file(&self.circuit_fname, &s); + self.cache.insert(t.clone(), EmbeddedTerm::Bool(share)); + } } Op::BvBinPred(op) => { let a_circ = self.get_bv(&t.cs[0]); @@ -336,49 +393,40 @@ impl ToABY { let a_conv = self.add_conv_gate(t.clone(), t.cs[0].clone(), a_circ); let b_conv = self.add_conv_gate(t.clone(), t.cs[1].clone(), b_circ); - match op { - BvBinPred::Uge => { - self.cache.insert( - t.clone(), - EmbeddedTerm::Bool(format!( - "((BooleanCircuit *){})->PutINVGate({}->PutGTGate({}, {}))", - s_circ, s_circ, b_conv, a_conv - )), - ); - } + let share = self.get_share_name(); + self.inc_share(); + let s = match op { BvBinPred::Ugt => { - self.cache.insert( - t.clone(), - EmbeddedTerm::Bool(format!( - "{}->PutGTGate({}, {})", - s_circ, a_conv, b_conv - )), - ); - } - BvBinPred::Ule => { - self.cache.insert( - t.clone(), - EmbeddedTerm::Bool(format!( - "((BooleanCircuit *){})->PutINVGate({}->PutGTGate({}, {}))", - s_circ, s_circ, a_conv, b_conv - )), - ); + format!( + "share* {} = {}->PutGTGate({}, {});\n", + share, s_circ, a_conv, b_conv + ) } BvBinPred::Ult => { - self.cache.insert( - t.clone(), - EmbeddedTerm::Bool(format!( - "{}->PutGTGate({}, {})", - s_circ, b_conv, a_conv - )), - ); + format!( + "share* {} = {}->PutGTGate({}, {});\n", + share, s_circ, b_conv, a_conv + ) + } + BvBinPred::Uge => { + format!( + "share* {} = ((BooleanCircuit *){})->PutINVGate({}->PutGTGate({}, {}));\n", + share, s_circ, s_circ, b_conv, a_conv + ) + } + BvBinPred::Ule => { + format!( + "share* {} = ((BooleanCircuit *){})->PutINVGate({}->PutGTGate({}, {}));\n", + share, s_circ, s_circ, a_conv, b_conv + ) } _ => panic!("Non-field in bool BvBinPred: {}", op), - } + }; + write_line_to_file(&self.circuit_fname, &s); + self.cache.insert(t.clone(), EmbeddedTerm::Bool(share)); } _ => panic!("Non-field in embed_bool: {}", t), } - self.get_bool(&t) } @@ -404,20 +452,25 @@ impl ToABY { .insert(t.clone(), *self.md.input_vis.get(name).unwrap()); } if !self.cache.contains_key(&t) { - self.cache - .insert(t.clone(), EmbeddedTerm::Bv(format!("s_{}", name))); + self.cache.insert( + t.clone(), + EmbeddedTerm::Bv(format!("s_{}", name.replace(".", "_"))), + ); } } Op::Const(Value::BitVector(b)) => { - self.cache.insert( - t.clone(), - EmbeddedTerm::Bv(format!( - "{}->PutCONSGate((uint64_t){}, (uint32_t){})", - s_circ, - format!("{}", b).replace("#", "0"), - b.width() - )), + let share = self.get_share_name(); + self.inc_share(); + let s = format!( + "share* {} = {}->PutCONSGate((uint64_t){}, (uint32_t){});\n", + share, + s_circ, + format!("{}", b).replace("#", "0"), + b.width() ); + write_line_to_file(&self.circuit_fname, &s); + + self.cache.insert(t.clone(), EmbeddedTerm::Bv(share)); } Op::Ite => { let sel_circ = self.get_bool(&t.cs[0]); @@ -428,13 +481,15 @@ impl ToABY { let a_conv = self.add_conv_gate(t.clone(), t.cs[1].clone(), a_circ); let b_conv = self.add_conv_gate(t.clone(), t.cs[2].clone(), b_circ); - self.cache.insert( - t.clone(), - EmbeddedTerm::Bv(format!( - "{}->PutMUXGate({}, {}, {})", - s_circ, a_conv, b_conv, sel_conv - )), + let share = self.get_share_name(); + self.inc_share(); + let s = format!( + "share* {} = {}->PutMUXGate({}, {}, {});\n", + share, s_circ, a_conv, b_conv, sel_conv ); + write_line_to_file(&self.circuit_fname, &s); + + self.cache.insert(t.clone(), EmbeddedTerm::Bv(share)); } Op::BvNaryOp(o) => { let a_circ = self.get_bv(&t.cs[0]); @@ -447,22 +502,25 @@ impl ToABY { s_circ = format!("((BooleanCircuit *){})", s_circ); } - self.cache.insert( - t.clone(), - EmbeddedTerm::Bv(format!( - "{}->{}({}, {})", - s_circ, - match o { - BvNaryOp::Xor => "PutXORGate", - BvNaryOp::Or => "PutORGate", - BvNaryOp::And => "PutANDGate", - BvNaryOp::Add => "PutADDGate", - BvNaryOp::Mul => "PutMULGate", - }, - a_conv, - b_conv - )), + let share = self.get_share_name(); + self.inc_share(); + let s = format!( + "share* {} = {}->{}({}, {});\n", + share, + s_circ, + match o { + BvNaryOp::Xor => "PutXORGate", + BvNaryOp::Or => "PutORGate", + BvNaryOp::And => "PutANDGate", + BvNaryOp::Add => "PutADDGate", + BvNaryOp::Mul => "PutMULGate", + }, + a_conv, + b_conv ); + write_line_to_file(&self.circuit_fname, &s); + + self.cache.insert(t.clone(), EmbeddedTerm::Bv(share)); } Op::BvBinOp(o) => { let a_circ = self.get_bv(&t.cs[0]); @@ -471,49 +529,37 @@ impl ToABY { let a_conv = self.add_conv_gate(t.clone(), t.cs[0].clone(), a_circ); let b_conv = self.add_conv_gate(t.clone(), t.cs[1].clone(), b_circ); - match o { + let share = self.get_share_name(); + self.inc_share(); + let s = match o { BvBinOp::Sub => { - self.cache.insert( - t.clone(), - EmbeddedTerm::Bv(format!( - "{}->PutSUBGate({}, {})", - s_circ, a_conv, b_conv - )), - ); + format!( + "share* {} = {}->PutSUBGate({}, {});\n", + share, s_circ, a_conv, b_conv + ) } - BvBinOp::Shl => { - let b_val = self.remove_cons_gate(b_conv); - self.cache.insert( - t.clone(), - EmbeddedTerm::Bv(format!( - "left_shift({}, {}, {})", - s_circ, a_conv, b_val - )), - ); + _ => { + format!( + "share* {} = {}({}, {}, {});\n", + share, + match o { + BvBinOp::Udiv => "signeddivbl", + BvBinOp::Urem => "signedmodbl", + BvBinOp::Shl => "left_shift", + BvBinOp::Lshr => "logical_right_shift", + BvBinOp::Ashr => "arithmetic_right_shift", + _ => unreachable!(), + }, + s_circ, + a_conv, + b_conv, + ) } - BvBinOp::Lshr => { - let b_val = self.remove_cons_gate(b_conv); - self.cache.insert( - t.clone(), - EmbeddedTerm::Bv(format!( - "logical_right_shift({}, {}, {})", - s_circ, a_conv, b_val - )), - ); - } - BvBinOp::Ashr => { - let b_val = self.remove_cons_gate(b_conv); - self.cache.insert( - t.clone(), - EmbeddedTerm::Bv(format!( - "arithmetic_right_shift({}, {}, {})", - s_circ, a_conv, b_val - )), - ); - } - _ => panic!("Invalid bv-op in BvBinOp: {:?}", o), - } + }; + write_line_to_file(&self.circuit_fname, &s); + self.cache.insert(t.clone(), EmbeddedTerm::Bv(share)); } + // TODO Op::BvExtract(_start, _end) => {} _ => panic!("Non-field in embed_bv: {:?}", t), } @@ -525,51 +571,58 @@ impl ToABY { /// the circuit to a share /// /// Return a String of the resulting Circuit - fn format_output_circuit(&self, t: Term, circ: String) -> String { - format!( - "\tadd_to_output_queue(out_q, {}->PutOUTGate({}, ALL), role, std::cout);\n", - self.get_sharetype_circ(t), - circ - ) + fn format_output_circuit(&self, t: Term) -> String { + match self.cache.get(&t) { + Some(EmbeddedTerm::Bool(s)) | Some(EmbeddedTerm::Bv(s)) => { + format!( + "add_to_output_queue(out_q, {}->PutOUTGate({}, ALL), role, std::cout);\n", + self.get_sharetype_circ(t), + s + ) + } + None => panic!("Term not found in cache: {:#?}", t), + } } fn embed(&mut self, t: Term) -> String { - let mut circ = String::new(); for c in PostOrderIter::new(t.clone()) { - println!("Embedding: {:?}", c); match check(&c) { Sort::Bool => { - circ = self.embed_bool(c); + self.embed_bool(c); } Sort::BitVector(_) => { - circ = self.embed_bv(c); + self.embed_bv(c); } e => panic!("Unsupported sort in embed: {:?}", e), } } - self.format_output_circuit(t, circ) + self.format_output_circuit(t) } /// Given a term `t`, lower `t` to ABY Circuits fn lower(&mut self, t: Term) { - let circ = self.embed(t); - self.aby.circs.push(circ); + let s = self.embed(t); + write_line_to_file(&self.circuit_fname, &s); } } /// Convert this (IR) `ir` to ABY. -pub fn to_aby(ir: Computation) -> ABY { +pub fn to_aby(ir: Computation, path: &Path, lang: &str, cm: &str) { let Computation { outputs: terms, metadata: md, values: _, } = ir.clone(); - // let s_map: SharingMap = assign(&ir); - let s_map: SharingMap = some_arith_sharing(&ir); - let mut converter = ToABY::new(md, s_map); + for t in terms.clone() { + println!("terms: {}", t); + } + + let s_map: SharingMap = assign(&ir, cm); + // let s_map: SharingMap = some_arith_sharing(&ir); + let mut converter = ToABY::new(md, s_map, path, lang); for t in terms { - println!("Terms: {}", t); + println!("terms: {}", t); converter.lower(t.clone()); } @@ -577,6 +630,4 @@ pub fn to_aby(ir: Computation) -> ABY { // are the input parameters for the ABY circuit. // Call init_inputs here after self.inputs is populated. converter.init_inputs(); - - converter.aby } diff --git a/src/target/aby/utils.rs b/src/target/aby/utils.rs new file mode 100644 index 00000000..922a09c1 --- /dev/null +++ b/src/target/aby/utils.rs @@ -0,0 +1,41 @@ +//! Utility functions to write compiler output to ABY + +use std::fs; +use std::io::prelude::*; +use std::path::Path; + +/// Given Path `path` and String denominator `lang`, return the filename of the path +pub fn get_path(path: &Path, lang: &str, t: &str) -> String { + let filename = Path::new(&path.iter().last().unwrap().to_os_string()) + .file_stem() + .unwrap() + .to_os_string() + .into_string() + .unwrap(); + + let name = format!("{}_{}", filename, lang); + + // TODO: clean + let path = format!("third_party/ABY/src/examples/{}_{}_tmp.txt", name, t); + + if Path::new(&path).exists() { + fs::remove_file(&path).expect("Failed to remove old circuit_tmp file"); + } + path +} + +/// Write circuit output to temporary file +pub fn write_line_to_file(path: &str, line: &str) { + if !Path::new(&path).exists() { + fs::File::create(&path).expect("Failed to create tmp file"); + } + + let mut file = fs::OpenOptions::new() + .write(true) + .append(true) + .open(path) + .expect("Failed to open circuit_tmp file"); + + file.write_all(line.as_bytes()) + .expect("Failed to write to circuit_tmp file"); +} diff --git a/third_party/ABY_templates/test_template.txt b/third_party/ABY_templates/test_template.txt index 46250f2c..caabac9c 100644 --- a/third_party/ABY_templates/test_template.txt +++ b/third_party/ABY_templates/test_template.txt @@ -1,3 +1,6 @@ +#include +#include + #include #include @@ -56,15 +59,38 @@ std::map parameters_to_map(std::string s, std::string } v.push_back(s.substr(start, end - start)); + // TODO: this input parameter map does not support strings since it + // uses strings as parameter keys + std::map m; - for (int i = 0; i < v.size(); i += 2) { - if (i+1 < v.size()) { - m[v[i]] = v[i+1]; + int idx = 0; + std::string base_key = ""; + for (int i = 0; i < v.size(); i++) { + if (!isdigit(*v[i].c_str())) { + idx = 0; + base_key = v[i]; + } else { + std::string key = ""; + if (i+1 < v.size()) { + if (idx == 0 && !isdigit(*v[i+1].c_str())) { + key = base_key; + } + else { + key = base_key + '_' + std::to_string(idx); + idx++; + } + } else if (idx > 0) { + key = base_key + '_' + std::to_string(idx); + } else { + key = base_key; + } + m[key] = v[i]; } } return m; } + int main(int argc, char** argv) { e_role role; diff --git a/third_party/EZPC/ezpc.h b/third_party/EZPC/ezpc.h index 89038403..a23746fe 100644 --- a/third_party/EZPC/ezpc.h +++ b/third_party/EZPC/ezpc.h @@ -102,6 +102,197 @@ share* arithmetic_right_shift(Circuit* c, share* val, uint32_t shift_factor) { return c->PutMUXGate(x, c->PutSUBGate(get_zero_share(c, bitlen), x), is_pos); } + +share* signedgtbl(Circuit* c, share* x, share* y){ + share* ux = x; + share* uy = y; + int32_t __tac_var1 = ( (int32_t)1 << (int32_t)31); + share* __tac_var2 = put_cons32_gate(c, __tac_var1); + share* signBitX = c->PutANDGate(x, __tac_var2); + int32_t __tac_var3 = __tac_var1; + share* __tac_var4 = __tac_var2; + share* signBitY = c->PutANDGate(y, __tac_var2); + share* __tac_var5 = c->PutXORGate(signBitX, signBitY); + share* __tac_var6 = put_cons32_gate(c, (uint32_t)0); + share* __tac_var7 = c->PutGTGate(__tac_var5, __tac_var6); + share* __tac_var8 = __tac_var6; + share* __tac_var9 = c->PutGTGate(signBitX, __tac_var6); + share* __tac_var10 = put_cons1_gate(c, 0); + share* __tac_var11 = put_cons1_gate(c, 1); + share* __tac_var12 = c->PutMUXGate(__tac_var10, __tac_var11, __tac_var9); + share* __tac_var13 = c->PutGTGate(ux, uy); + share* __tac_var14 = c->PutMUXGate(__tac_var12, __tac_var13, __tac_var7); + return __tac_var14; +} + +share* signedarshiftbl(Circuit* c, share* x, uint32_t y){ + share* ux = x; + int32_t __tac_var15 = ( (int32_t)1 << (int32_t)31); + share* __tac_var16 = put_cons32_gate(c, __tac_var15); + share* signBitX = c->PutANDGate(x, __tac_var16); + share* __tac_var17 = put_cons32_gate(c, (uint32_t)0); + share* __tac_var18 = c->PutGTGate(signBitX, __tac_var17); + share* __tac_var19 = __tac_var17; + share* __tac_var20 = __tac_var17; + share* __tac_var21 = c->PutSUBGate(__tac_var17, ux); + share* __tac_var22 = arithmetic_right_shift(c, __tac_var21, y); + share* __tac_var23 = c->PutSUBGate(__tac_var17, __tac_var22); + share* __tac_var24 = arithmetic_right_shift(c, ux, y); + share* __tac_var25 = c->PutMUXGate(__tac_var23, __tac_var24, __tac_var18); + return __tac_var25; +} + +share* unsignedltbl(Circuit* c, share* x, share* y){ + share* __tac_var26 = c->PutGTGate(y, x); + return __tac_var26; +} + +share* signedltbl(Circuit* c, share* x, share* y){ + share* __tac_var27 = signedgtbl(c, y, x); + return __tac_var27; +} + +share* unsignedleqbl(Circuit* c, share* x, share* y){ + share* __tac_var28 = c->PutGTGate(x, y); + share* __tac_var29 = ((BooleanCircuit *) c)->PutINVGate(__tac_var28); + return __tac_var29; +} + +share* signedleqbl(Circuit* c, share* x, share* y){ + share* __tac_var30 = signedgtbl(c, x, y); + share* __tac_var31 = ((BooleanCircuit *) c)->PutINVGate(__tac_var30); + return __tac_var31; +} + +share* unsignedgeqbl(Circuit* c, share* x, share* y){ + share* __tac_var32 = c->PutGTGate(y, x); + share* __tac_var33 = ((BooleanCircuit *) c)->PutINVGate(__tac_var32); + return __tac_var33; +} + +share* signedgeqbl(Circuit* c, share* x, share* y){ + share* __tac_var34 = signedgtbl(c, y, x); + share* __tac_var35 = ((BooleanCircuit *) c)->PutINVGate(__tac_var34); + return __tac_var35; +} + +share* unsignedequalsbl(Circuit* c, share* x, share* y){ + share* __tac_var36 = unsignedltbl(c, x, y); + share* __tac_var37 = ((BooleanCircuit *) c)->PutINVGate(__tac_var36); + share* __tac_var38 = unsignedltbl(c, y, x); + share* __tac_var39 = ((BooleanCircuit *) c)->PutINVGate(__tac_var38); + share* __tac_var40 = c->PutANDGate(__tac_var37, __tac_var39); + return __tac_var40; +} + +share* signedequalsbl(Circuit* c, share* x, share* y){ + share* __tac_var41 = signedltbl(c, x, y); + share* __tac_var42 = ((BooleanCircuit *) c)->PutINVGate(__tac_var41); + share* __tac_var43 = signedltbl(c, y, x); + share* __tac_var44 = ((BooleanCircuit *) c)->PutINVGate(__tac_var43); + share* __tac_var45 = c->PutANDGate(__tac_var42, __tac_var44); + return __tac_var45; +} + +share* longDivision(Circuit* c, share* x, share* y, uint32_t getQuotient){ + share* q = put_cons32_gate(c, (uint32_t)0); + share* divisor = q; + share* cond = put_cons1_gate(c, 0); + for (uint32_t iter = (int32_t)0; iter < (int32_t)32; iter++){ + uint32_t i = ( (int32_t)31 - iter); + divisor = left_shift(c, divisor, (uint32_t)1); + uint32_t __tac_var46 = ( (uint32_t)1 << i); + share* __tac_var47 = put_cons32_gate(c, __tac_var46); + share* __tac_var48 = c->PutANDGate(x, __tac_var47); + share* __tac_var49 = logical_right_shift(c, __tac_var48, i); + divisor = c->PutADDGate(divisor, __tac_var49); + cond = unsignedgeqbl(c, divisor, y); + share* __tac_var50 = c->PutSUBGate(divisor, y); + divisor = c->PutMUXGate(__tac_var50, divisor, cond); + q = left_shift(c, q, (uint32_t)1); + share* __tac_var51 = put_cons32_gate(c, (uint32_t)1); + share* __tac_var52 = c->PutADDGate(q, __tac_var51); + q = c->PutMUXGate(__tac_var52, q, cond); + } + share* __tac_var53 = getQuotient ? q : divisor; + return __tac_var53; +} + +share* unsigneddivbl(Circuit* c, share* x, share* y){ + share* __tac_var54 = longDivision(c, x, y, 1); + return __tac_var54; +} + +share* unsigneddival(Circuit* c, share* x, share* y){ + share* bx = c->PutA2YGate(x); + share* by = c->PutA2YGate(y); + share* __tac_var55 = unsigneddivbl(c, bx, by); + return __tac_var55; +} + +share* signeddivbl(Circuit* c, share* x, share* y){ + share* __tac_var56 = put_cons32_gate(c, (int32_t)0); + share* isXNeg = signedltbl(c, x, __tac_var56); + share* __tac_var57 = __tac_var56; + share* isYNeg = signedltbl(c, y, __tac_var56); + share* __tac_var58 = __tac_var56; + share* __tac_var59 = c->PutSUBGate(__tac_var56, x); + share* ux = c->PutMUXGate(__tac_var59, x, isXNeg); + share* __tac_var60 = __tac_var56; + share* __tac_var61 = c->PutSUBGate(__tac_var56, y); + share* uy = c->PutMUXGate(__tac_var61, y, isYNeg); + share* ures = unsigneddivbl(c, ux, uy); + share* isResNeg = c->PutXORGate(isXNeg, isYNeg); + share* __tac_var62 = put_cons32_gate(c, (uint32_t)0); + share* __tac_var63 = c->PutSUBGate(__tac_var62, ures); + share* __tac_var64 = c->PutMUXGate(__tac_var63, ures, isResNeg); + return __tac_var64; +} + +share* signeddival(Circuit* c, share* x, share* y){ + share* bx = c->PutA2YGate(x); + share* by = c->PutA2YGate(y); + share* __tac_var65 = signeddivbl(c, bx, by); + return __tac_var65; +} + +share* unsignedmodbl(Circuit* c, share* x, share* y){ + share* __tac_var66 = longDivision(c, x, y, 0); + return __tac_var66; +} + +share* unsignedmodal(Circuit* c, share* x, share* y){ + share* bx = c->PutA2YGate(x); + share* by = c->PutA2YGate(y); + share* __tac_var67 = unsignedmodbl(c, bx, by); + return __tac_var67; +} + +share* signedmodbl(Circuit* c, share* x, share* y){ + share* __tac_var68 = put_cons32_gate(c, (int32_t)0); + share* isXNeg = signedltbl(c, x, __tac_var68); + share* __tac_var69 = __tac_var68; + share* isYNeg = signedltbl(c, y, __tac_var68); + share* __tac_var70 = __tac_var68; + share* __tac_var71 = c->PutSUBGate(__tac_var68, x); + share* ux = c->PutMUXGate(__tac_var71, x, isXNeg); + share* __tac_var72 = __tac_var68; + share* __tac_var73 = c->PutSUBGate(__tac_var68, y); + share* uy = c->PutMUXGate(__tac_var73, y, isYNeg); + share* urem = unsignedmodbl(c, ux, uy); + share* __tac_var74 = put_cons32_gate(c, (uint32_t)0); + share* __tac_var75 = c->PutSUBGate(__tac_var74, urem); + share* __tac_var76 = c->PutMUXGate(__tac_var75, urem, isXNeg); + return __tac_var76; +} + +share* signedmodal(Circuit* c, share* x, share* y){ + share* bx = c->PutA2YGate(x); + share* by = c->PutA2YGate(y); + share* __tac_var77 = signedmodbl(c, bx, by); + return __tac_var77; +} + /* * we maintain a queue of outputs * basically every OUTPUT adds an OUTGate, diff --git a/third_party/ZoKrates/zokrates_parser/Cargo.lock b/third_party/ZoKrates/zokrates_parser/Cargo.lock new file mode 100644 index 00000000..b94f0b54 --- /dev/null +++ b/third_party/ZoKrates/zokrates_parser/Cargo.lock @@ -0,0 +1,189 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding", + "byte-tools", + "byteorder", + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", +] + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + +[[package]] +name = "glob" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" + +[[package]] +name = "maplit" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" + +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" + +[[package]] +name = "pest" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +dependencies = [ + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pest_meta" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" +dependencies = [ + "maplit", + "pest", + "sha-1", +] + +[[package]] +name = "proc-macro2" +version = "1.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "sha-1" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" +dependencies = [ + "block-buffer", + "digest", + "fake-simd", + "opaque-debug", +] + +[[package]] +name = "syn" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "typenum" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" + +[[package]] +name = "ucd-trie" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "zokrates_parser" +version = "0.1.6" +dependencies = [ + "glob", + "pest", + "pest_derive", +] diff --git a/third_party/hycc/README.md b/third_party/hycc/README.md new file mode 100644 index 00000000..6a97e940 --- /dev/null +++ b/third_party/hycc/README.md @@ -0,0 +1,3 @@ +# Adapted from the HyCC distribution + +[Source](https://gitlab.com/securityengineering/HyCC/) diff --git a/third_party/hycc/adapted_costs.json b/third_party/hycc/adapted_costs.json new file mode 100644 index 00000000..cd3139bf --- /dev/null +++ b/third_party/hycc/adapted_costs.json @@ -0,0 +1,264 @@ +{ + "&&": { + "b": { + "32": 117 + }, + "y": { + "32": 32 + } + }, + "||": { + "b": { + "32": 123 + }, + "y": { + "32": 40 + } + }, + "a2b": { + "1": 334.02, + "8": 327.064, + "16": 322.452, + "32": 335.764 + }, + "a2y": { + "1": 325.398, + "8": 318.621, + "16": 314.128, + "32": 327.097 + }, + "add": { + "a": { + "1": 214.449, + "8": 108.999, + "16": 202.045, + "32": 116.869 + }, + "b": { + "1": 1056.463, + "8": 1059.493, + "16": 1066.69, + "32": 1049.803 + }, + "y": { + "1": 316.939, + "8": 317.848, + "16": 320.007, + "32": 314.941 + } + }, + "and": { + "b": { + "1": 322.521, + "8": 320.293, + "16": 313.943, + "32": 315.589 + }, + "y": { + "1": 318.946, + "8": 326.198, + "16": 328.816, + "32": 314.308 + } + }, + "b2a": { + "1": 314.401, + "8": 328.788, + "16": 328.053, + "32": 326.316 + }, + "b2y": { + "1": 329.222, + "8": 318.638, + "16": 316.215, + "32": 319.556 + }, + "eq": { + "b": { + "1": 200.331, + "8": 429.922, + "16": 439.933, + "32": 529.283 + }, + "y": { + "1": 309.717, + "8": 323.07, + "16": 319.867, + "32": 316.492 + } + }, + "ge": { + "b": { + "1": 6987.454, + "8": 6832.078, + "16": 6794.562, + "32": 6743.487 + }, + "y": { + "1": 487.781, + "8": 476.934, + "16": 474.315, + "32": 470.749 + } + }, + "gt": { + "b": { + "1": 4658.303, + "8": 4554.719, + "16": 4529.708, + "32": 4495.658 + }, + "y": { + "1": 325.187, + "8": 317.956, + "16": 316.21, + "32": 313.833 + } + }, + "le": { + "b": { + "1": 6987.454, + "8": 6832.078, + "16": 6794.562, + "32": 6743.487 + }, + "y": { + "1": 487.781, + "8": 476.934, + "16": 474.315, + "32": 470.749 + } + }, + "lt": { + "b": { + "1": 4658.303, + "8": 4554.719, + "16": 4529.708, + "32": 4495.658 + }, + "y": { + "1": 325.187, + "8": 317.956, + "16": 316.21, + "32": 313.833 + } + }, + "mul": { + "a": { + "1": 323.99, + "8": 425.06, + "16": 324.338, + "32": 416.112 + }, + "y": { + "1": 318.776, + "8": 323.827, + "16": 320.097, + "32": 410.183 + } + }, + "mux": { + "b": { + "1": 320.388, + "8": 322.502, + "16": 324.969, + "32": 316.438 + }, + "y": { + "1": 330.528, + "8": 318.433, + "16": 325.117, + "32": 319.27 + } + }, + "ne": { + "b": { + "1": 200.331, + "8": 429.922, + "16": 439.933, + "32": 529.283 + }, + "y": { + "1": 309.717, + "8": 323.07, + "16": 319.867, + "32": 316.492 + } + }, + "or": { + "b": { + "1": 322.521, + "8": 320.293, + "16": 313.943, + "32": 315.589 + }, + "y": { + "1": 318.946, + "8": 326.198, + "16": 328.816, + "32": 314.308 + } + }, + "sub": { + "a": { + "1": 214.449, + "8": 108.999, + "16": 202.045, + "32": 116.869 + }, + "b": { + "1": 1056.463, + "8": 1059.493, + "16": 1066.69, + "32": 1049.803 + }, + "y": { + "1": 316.939, + "8": 317.848, + "16": 320.007, + "32": 314.941 + } + }, + "xor": { + "b": { + "1": 205.544, + "8": 120.112, + "16": 195.179, + "32": 125.154 + }, + "y": { + "1": 323.464, + "8": 314.425, + "16": 310.38, + "32": 322.615 + } + }, + "y2a": { + "1": 491.107, + "8": 510.63, + "16": 499.249, + "32": 501.104 + }, + "y2b": { + "1": 312.428, + "8": 324.848, + "16": 317.608, + "32": 318.788 + }, + "div": { + "b": { + "32": 10 + }, + "y": { + "32": 100 + } + }, + "rem": { + "b": { + "32": 10 + }, + "y": { + "32": 100 + } + } +} diff --git a/third_party/hycc/original_costs.json b/third_party/hycc/original_costs.json new file mode 100644 index 00000000..fad5435b --- /dev/null +++ b/third_party/hycc/original_costs.json @@ -0,0 +1,212 @@ +{ + "and": { + "yao": { + "8": 326.198, + "1": 318.946, + "16": 328.816, + "32": 314.308 + }, + "bool": { + "8": 320.293, + "1": 322.521, + "16": 313.943, + "32": 315.589 + } + }, + "addso": { + "bool": { + "8": 637.953, + "1": 129.796, + "16": 1070.69, + "32": 1905.64 + } + }, + "adddo": { + "bool": { + "8": 465.945, + "1": 294.112, + "16": 524.457, + "32": 602.37 + } + }, + "muxvec": { + "bool": { + "8": 310.333, + "1": 325.364, + "16": 322.711, + "32": 324.6 + } + }, + "eq": { + "yao": { + "8": 323.07, + "1": 309.717, + "16": 319.867, + "32": 316.492 + }, + "bool": { + "8": 429.922, + "1": 200.331, + "16": 439.933, + "32": 529.283 + } + }, + "xor": { + "yao": { + "8": 314.425, + "1": 323.464, + "16": 310.38, + "32": 322.615 + }, + "bool": { + "8": 120.112, + "1": 205.544, + "16": 195.179, + "32": 125.154 + } + }, + "mux": { + "yao": { + "8": 318.433, + "1": 330.528, + "16": 325.117, + "32": 319.27 + }, + "bool": { + "8": 322.502, + "1": 320.388, + "16": 324.969, + "32": 316.438 + } + }, + "add": { + "yao": { + "8": 317.848, + "1": 316.939, + "16": 320.007, + "32": 314.941 + }, + "arith": { + "8": 108.999, + "1": 214.449, + "16": 202.045, + "32": 116.869 + } + }, + "muldo": { + "bool": { + "8": 654.57, + "1": 318.94, + "16": 766.692, + "32": 1044.67 + } + }, + "muldovec": { + "bool": { + "8": 747.069, + "1": 314.69, + "16": 857.161, + "32": 1161.19 + } + }, + "mul": { + "yao": { + "8": 323.827, + "1": 318.776, + "16": 320.097, + "32": 410.183 + }, + "arith": { + "8": 425.06, + "1": 323.99, + "16": 324.338, + "32": 416.112 + } + }, + "adddovec": { + "bool": { + "8": 616.533, + "1": 234.807, + "16": 649.626, + "32": 657.659 + } + }, + "inv": { + "yao": { + "8": 214.483, + "1": 212.694, + "16": 229.117, + "32": 222.065 + }, + "bool": { + "8": 203.205, + "1": 117.708, + "16": 113.149, + "32": 207.055 + } + }, + "cmpso": { + "bool": { + "8": 665.959, + "1": 319.328, + "16": 1124.82, + "32": 1927.67 + } + }, + "b2y": { + "8": 318.638, + "1": 329.222, + "16": 316.215, + "32": 319.556 + }, + "a2y": { + "8": 318.621, + "1": 325.398, + "16": 314.128, + "32": 327.097 + }, + "mulsovec": { + "bool": { + "8": 740.136, + "1": 318.247, + "16": 1265.37, + "32": 2142.29 + } + }, + "cmpdo": { + "bool": { + "8": 499.259, + "1": 317.219, + "16": 526.257, + "32": 550.834 + } + }, + "b2a": { + "8": 328.788, + "1": 314.401, + "16": 328.053, + "32": 326.316 + }, + "y2b": { + "8": 324.848, + "1": 312.428, + "16": 317.608, + "32": 318.788 + }, + "mulso": { + "bool": { + "8": 717.302, + "1": 315.436, + "16": 1088.29, + "32": 2121.48 + } + }, + "cmp": { + "yao": { + "8": 317.956, + "1": 325.187, + "16": 316.21, + "32": 313.833 + } + } +} diff --git a/third_party/opa/README.md b/third_party/opa/README.md index 46e8fded..3798dbae 100644 --- a/third_party/opa/README.md +++ b/third_party/opa/README.md @@ -1,3 +1,3 @@ -# From the OPA distribution +# Adapted from the OPA distribution [Source](https://github.com/ishaq/OPA) diff --git a/third_party/opa/adapted_costs.json b/third_party/opa/adapted_costs.json new file mode 100644 index 00000000..46d6f983 --- /dev/null +++ b/third_party/opa/adapted_costs.json @@ -0,0 +1,181 @@ +{ + "&&": { + "b": { + "32": 117 + }, + "y": { + "32": 32 + } + }, + "||": { + "b": { + "32": 123 + }, + "y": { + "32": 40 + } + }, + "a2b": { + "32": 2596.4 + }, + "a2y": { + "32": 2665.2 + }, + "add": { + "a": { + "32": 1 + }, + "b": { + "32": 160 + }, + "y": { + "32": 48 + } + }, + "and": { + "b": { + "32": 117 + }, + "y": { + "32": 32 + } + }, + "b2a": { + "32": 1868.3999999999999 + }, + "b2y": { + "32": 2293 + }, + "eq": { + "b": { + "32": 489 + }, + "y": { + "32": 39 + } + }, + "ge": { + "b": { + "32": 733 + }, + "y": { + "32": 60 + } + }, + "gt": { + "b": { + "32": 573 + }, + "y": { + "32": 40 + } + }, + "le": { + "b": { + "32": 618 + }, + "y": { + "32": 41 + } + }, + "lt": { + "b": { + "32": 739 + }, + "y": { + "32": 60 + } + }, + "mul": { + "b": { + "32": 1731 + }, + "y": { + "32": 1127 + }, + "a": { + "32": 104 + } + }, + "mux": { + "b": { + "32": 108 + }, + "y": { + "32": 37 + } + }, + "ne": { + "b": { + "32": 484 + }, + "y": { + "32": 38 + } + }, + "or": { + "b": { + "32": 123 + }, + "y": { + "32": 40 + } + }, + "shl": { + "b": { + "32": 981 + }, + "y": { + "32": 224 + } + }, + "shr": { + "b": { + "32": 1015 + }, + "y": { + "32": 224 + } + }, + "sub": { + "a": { + "32": 1 + }, + "b": { + "32": 52 + }, + "y": { + "32": 49 + } + }, + "xor": { + "b": { + "32": 7 + }, + "y": { + "32": 23 + } + }, + "y2a": { + "32": 3207 + }, + "y2b": { + "32": 2040.2 + }, + "div": { + "b": { + "32": 10 + }, + "y": { + "32": 100 + } + }, + "rem": { + "b": { + "32": 10 + }, + "y": { + "32": 100 + } + } +} diff --git a/third_party/opa/sample_costs.json b/third_party/opa/original_costs.json similarity index 99% rename from third_party/opa/sample_costs.json rename to third_party/opa/original_costs.json index f0b85d8a..36c7e578 100644 --- a/third_party/opa/sample_costs.json +++ b/third_party/opa/original_costs.json @@ -149,4 +149,3 @@ } } } -