mirror of
https://github.com/circify/circ.git
synced 2026-01-10 06:08:02 -05:00
Integrated EZPC helper file (#18)
* Added EZPC helper file, updated output, added shift tests
This commit is contained in:
5
examples/ZoKrates/mpc/hycc_benchmarks/biomatch.zok
Normal file
5
examples/ZoKrates/mpc/hycc_benchmarks/biomatch.zok
Normal file
@@ -0,0 +1,5 @@
|
||||
def main(private<1> u32 a, private<2> u32 b) -> u32:
|
||||
for u32 i in 1..4 do
|
||||
a = a + b
|
||||
return a
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
def main(private<1> u32 a, private<2> u32 b) -> u32[2]:
|
||||
return [a, b]
|
||||
@@ -0,0 +1,3 @@
|
||||
def main(private<1> u32 a, private<2> u32 b) -> u32:
|
||||
u32[2] c = [a, b]
|
||||
return c[0] + c[1]
|
||||
@@ -0,0 +1,5 @@
|
||||
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)
|
||||
3
examples/ZoKrates/mpc/unit_tests/shift_tests/2pc_lhs.zok
Normal file
3
examples/ZoKrates/mpc/unit_tests/shift_tests/2pc_lhs.zok
Normal file
@@ -0,0 +1,3 @@
|
||||
def main(private<1> u32 a, private<2> u32 b) -> u32:
|
||||
u32 c = 0x00000001
|
||||
return a << c
|
||||
3
examples/ZoKrates/mpc/unit_tests/shift_tests/2pc_rhs.zok
Normal file
3
examples/ZoKrates/mpc/unit_tests/shift_tests/2pc_rhs.zok
Normal file
@@ -0,0 +1,3 @@
|
||||
def main(private<1> u32 a, private<2> u32 b) -> u32:
|
||||
u32 c = 0x00000001
|
||||
return a >> c
|
||||
@@ -61,7 +61,8 @@ fn main() {
|
||||
Mode::Opt => opt(cs, vec![Opt::ConstantFold]),
|
||||
Mode::Mpc(_) => opt(
|
||||
cs,
|
||||
vec![Opt::Sha, Opt::ConstantFold, Opt::Mem, Opt::ConstantFold],
|
||||
vec![],
|
||||
// vec![Opt::Sha, Opt::ConstantFold, Opt::Mem, Opt::ConstantFold],
|
||||
),
|
||||
Mode::Proof => opt(
|
||||
cs,
|
||||
|
||||
@@ -24,50 +24,54 @@ function mpc_test {
|
||||
}
|
||||
|
||||
# build mpc arithmetic tests
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/arithmetic_tests/2pc_add.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/arithmetic_tests/2pc_sub.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/arithmetic_tests/2pc_mult.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/arithmetic_tests/2pc_mult_add_pub.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/arithmetic_tests/2pc_add.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/arithmetic_tests/2pc_sub.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/arithmetic_tests/2pc_mult.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/arithmetic_tests/2pc_mult_add_pub.zok
|
||||
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/arithmetic_tests/2pc_int_equals.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/arithmetic_tests/2pc_int_greater_than.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/arithmetic_tests/2pc_int_greater_equals.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/arithmetic_tests/2pc_int_less_than.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/arithmetic_tests/2pc_int_less_equals.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/arithmetic_tests/2pc_int_equals.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/arithmetic_tests/2pc_int_greater_than.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/arithmetic_tests/2pc_int_greater_equals.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/arithmetic_tests/2pc_int_less_than.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/arithmetic_tests/2pc_int_less_equals.zok
|
||||
|
||||
# build mpc nary arithmetic tests
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/nary_arithmetic_tests/2pc_nary_arithmetic_add.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/nary_arithmetic_tests/2pc_nary_arithmetic_add.zok
|
||||
|
||||
# build mpc bitwise tests
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/bitwise_tests/2pc_bitwise_and.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/bitwise_tests/2pc_bitwise_or.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/bitwise_tests/2pc_bitwise_xor.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/bitwise_tests/2pc_bitwise_and.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/bitwise_tests/2pc_bitwise_or.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/bitwise_tests/2pc_bitwise_xor.zok
|
||||
|
||||
# build mpc boolean tests
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/boolean_tests/2pc_boolean_and.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/boolean_tests/2pc_boolean_or.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/boolean_tests/2pc_boolean_equals.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/boolean_tests/2pc_boolean_and.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/boolean_tests/2pc_boolean_or.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/boolean_tests/2pc_boolean_equals.zok
|
||||
|
||||
# build mpc nary boolean tests
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/nary_boolean_tests/2pc_nary_boolean_and.zok
|
||||
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/ite_tests/2pc_ite_ret_bool.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/ite_tests/2pc_ite_ret_int.zok
|
||||
|
||||
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/const_tests/2pc_const_arith.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/const_tests/2pc_const_bool.zok
|
||||
|
||||
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 mpc array tests
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/array_tests/2pc_array_sum.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/array_tests/2pc_array_ret.zok
|
||||
# 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
|
||||
|
||||
# build mpc function tests
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/function_tests/2pc_function_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
|
||||
|
||||
# build mpc misc tests
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/2pc_millionaire.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/2pc_conv.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/2pc_millionaire.zok
|
||||
mpc_test 2 ./examples/ZoKrates/mpc/unit_tests/2pc_conv.zok
|
||||
|
||||
# mpc_test 2 ./examples/ZoKrates/mpc/hycc_benchmarks/biomatch.zok
|
||||
@@ -463,6 +463,43 @@ function_tests = [
|
||||
|
||||
]
|
||||
|
||||
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 = [
|
||||
[
|
||||
@@ -550,10 +587,11 @@ def main():
|
||||
nary_boolean_tests + \
|
||||
const_tests + \
|
||||
ite_tests + \
|
||||
arr_tests + \
|
||||
function_tests + \
|
||||
shift_tests + \
|
||||
misc_tests
|
||||
# tests = arr_tests
|
||||
# arr_tests + \
|
||||
|
||||
|
||||
failed_test_descs = []
|
||||
num_retries = 3
|
||||
|
||||
@@ -79,7 +79,7 @@ fn write_test_file(filename: &String) {
|
||||
);
|
||||
|
||||
fs::write(path.clone(), template.replace("{fn}", &*filename))
|
||||
.expect("Failed to write to cmake file");
|
||||
.expect("Failed to write to test file");
|
||||
}
|
||||
|
||||
/// Using the h_template.txt, write the .h file for the new test case
|
||||
@@ -92,7 +92,7 @@ fn write_h_file(filename: &String) {
|
||||
);
|
||||
|
||||
fs::write(path.clone(), template.replace("{fn}", &*filename))
|
||||
.expect("Failed to write to cmake file");
|
||||
.expect("Failed to write to h file");
|
||||
}
|
||||
|
||||
/// Using the cpp_template.txt, write the .cpp file for the new test case
|
||||
@@ -111,7 +111,7 @@ fn write_circ_file(filename: &String, circ: String, output: &String) {
|
||||
.replace("{circ}", &circ)
|
||||
.replace("{output}", &output),
|
||||
)
|
||||
.expect("Failed to write to cmake file");
|
||||
.expect("Failed to write to cpp file");
|
||||
}
|
||||
|
||||
/// Write circuit output from translation later to ABY
|
||||
|
||||
@@ -188,6 +188,14 @@ impl ToABY {
|
||||
format!("bcirc->PutCONSGate((uint64_t)1, (uint32_t)1)")
|
||||
}
|
||||
|
||||
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 {
|
||||
let s_circ = self.get_sharetype_circ(t.clone());
|
||||
match check(&a) {
|
||||
@@ -471,8 +479,41 @@ impl ToABY {
|
||||
)),
|
||||
);
|
||||
}
|
||||
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
|
||||
)),
|
||||
);
|
||||
}
|
||||
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),
|
||||
}
|
||||
}
|
||||
Op::BvExtract(start, end) => {
|
||||
|
||||
}
|
||||
_ => panic!("Non-field in embed_bv: {:?}", t),
|
||||
}
|
||||
@@ -480,51 +521,38 @@ impl ToABY {
|
||||
self.get_bv(&t)
|
||||
}
|
||||
|
||||
fn embed(&mut self, t: Term) -> String {
|
||||
let mut output_circ: String = "".to_string();
|
||||
for c in PostOrderIter::new(t) {
|
||||
match check(&c) {
|
||||
Sort::Bool => {
|
||||
output_circ = self.embed_bool(c);
|
||||
}
|
||||
Sort::BitVector(_) => {
|
||||
output_circ = self.embed_bv(c);
|
||||
}
|
||||
e => panic!("Unsupported sort in embed: {:?}", e),
|
||||
}
|
||||
}
|
||||
output_circ
|
||||
}
|
||||
|
||||
/// Given a Circuit `circ`, wrap `circ` in an OUT gate to extract the value of
|
||||
/// the circuit to a share
|
||||
///
|
||||
/// Return a String of the resulting Circuit
|
||||
fn add_output_gate(&mut self, t: Term, circ: String) -> String {
|
||||
fn format_output_circuit(&self, t: Term, circ: String) -> String {
|
||||
format!(
|
||||
"\ts_out_{} = {}->PutOUTGate({}, ALL);\n",
|
||||
self.output_counter,
|
||||
"\tadd_to_output_queue(out_q, {}->PutOUTGate({}, ALL), role, std::cout);\n",
|
||||
self.get_sharetype_circ(t),
|
||||
circ
|
||||
)
|
||||
}
|
||||
|
||||
fn embed(&mut self, t: Term) -> String {
|
||||
let mut circ = String::new();
|
||||
for c in PostOrderIter::new(t.clone()) {
|
||||
match check(&c) {
|
||||
Sort::Bool => {
|
||||
circ = self.embed_bool(c);
|
||||
}
|
||||
Sort::BitVector(_) => {
|
||||
circ = self.embed_bv(c);
|
||||
}
|
||||
e => panic!("Unsupported sort in embed: {:?}", e),
|
||||
}
|
||||
}
|
||||
self.format_output_circuit(t, circ)
|
||||
}
|
||||
|
||||
/// Given a term `t`, lower `t` to ABY Circuits
|
||||
fn lower(&mut self, t: Term) {
|
||||
let mut output_circ = self.embed(t.clone());
|
||||
|
||||
output_circ = self.add_output_gate(t, output_circ);
|
||||
self.aby.circs.push(output_circ);
|
||||
self.aby
|
||||
.setup
|
||||
.push(format!("share *s_out_{};", self.output_counter));
|
||||
self.aby.output.push(format!(
|
||||
"uint32_t output_{} = s_out_{}->get_clear_value<uint32_t>();\n
|
||||
\tstd::cout << output_{} << std::endl;",
|
||||
self.output_counter, self.output_counter, self.output_counter
|
||||
));
|
||||
|
||||
self.output_counter += 1;
|
||||
let circ = self.embed(t.clone());
|
||||
self.aby.circs.push(circ);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -550,4 +578,4 @@ pub fn to_aby(ir: Computation) -> ABY {
|
||||
converter.init_inputs();
|
||||
|
||||
converter.aby
|
||||
}
|
||||
}
|
||||
9
third_party/ABY_templates/cpp_template.txt
vendored
9
third_party/ABY_templates/cpp_template.txt
vendored
@@ -2,6 +2,7 @@
|
||||
#include "../../../abycore/circuit/booleancircuits.h"
|
||||
#include "../../../abycore/circuit/arithmeticcircuits.h"
|
||||
#include "../../../abycore/circuit/circuit.h"
|
||||
#include "../../../../../../EZPC/ezpc.h"
|
||||
|
||||
#include "../../../abycore/sharing/sharing.h"
|
||||
|
||||
@@ -14,15 +15,13 @@ int32_t test_{fn}_circuit(std::map<std::string, std::string> params, e_role role
|
||||
Circuit* acirc = sharings[S_ARITH]->GetCircuitBuildRoutine();
|
||||
Circuit* bcirc = sharings[S_BOOL]->GetCircuitBuildRoutine();
|
||||
Circuit* ycirc = sharings[S_YAO]->GetCircuitBuildRoutine();
|
||||
|
||||
output_queue out_q;
|
||||
|
||||
// compiled circuit
|
||||
{circ}
|
||||
|
||||
party->ExecCircuit();
|
||||
|
||||
// output
|
||||
{output}
|
||||
|
||||
flush_output_queue(out_q, role, bitlen);
|
||||
delete party;
|
||||
return 0;
|
||||
}
|
||||
|
||||
202
third_party/EZPC/ezpc.h
vendored
Normal file
202
third_party/EZPC/ezpc.h
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
|
||||
Authors: Aseem Rastogi, Nishant Kumar, Mayank Rathee.
|
||||
|
||||
Copyright:
|
||||
Copyright (c) 2020 Microsoft Research
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __EZPC_H_
|
||||
#define __EZPC_H_
|
||||
#include "../ABY/src/abycore/circuit/booleancircuits.h"
|
||||
#include "../ABY/src/abycore/sharing/sharing.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* somehow we need this redirection for adding Cons gates
|
||||
* directly calling PutConsGate gives an error
|
||||
*/
|
||||
share* put_cons32_gate(Circuit* c, uint32_t val) {
|
||||
uint32_t x = val;
|
||||
return c->PutCONSGate(x, (uint32_t)32);
|
||||
}
|
||||
|
||||
share* put_cons64_gate(Circuit* c, uint64_t val) {
|
||||
uint64_t x = val;
|
||||
return c->PutCONSGate(x, (uint32_t)64);
|
||||
}
|
||||
|
||||
share* put_cons1_gate(Circuit* c, uint64_t val) {
|
||||
uint64_t x = val;
|
||||
return c->PutCONSGate(x, (uint32_t)1);
|
||||
}
|
||||
|
||||
share* left_shift(Circuit* c, share* val, uint32_t shift_factor) {
|
||||
uint32_t share_wire_count = val->get_bitlength();
|
||||
share* fresh_zero_share = put_cons32_gate(c, 0);
|
||||
std::vector<uint32_t> val_wires = val->get_wires();
|
||||
if(share_wire_count == 1){
|
||||
cout<<"Error. Share not padded. A share cannot exist with just 1 wire.\n";
|
||||
}
|
||||
// Note here the assumption is that if we receive the val share as a share of size 32, we output the share as a share of size 32 only and drop the MSBs which overflow the 32 bit constraint.
|
||||
for(int i=0; i+shift_factor<share_wire_count; i++){
|
||||
fresh_zero_share->set_wire_id(shift_factor+i, val_wires[i]);
|
||||
}
|
||||
return fresh_zero_share;
|
||||
}
|
||||
|
||||
share* get_zero_share(Circuit* c, int bitlen){
|
||||
if (bitlen == 32)
|
||||
return put_cons32_gate(c, 0);
|
||||
else
|
||||
return put_cons64_gate(c, 0);
|
||||
}
|
||||
|
||||
share* logical_right_shift(Circuit* c, share* val, uint32_t shift_factor) {
|
||||
int bitlen = val->get_bitlength();
|
||||
vector<uint32_t> val_wires = val->get_wires();
|
||||
|
||||
vector<uint32_t> zero_share_wires = (get_zero_share(c, bitlen))->get_wires();
|
||||
vector<uint32_t> new_val_wires(bitlen, 0);
|
||||
for(int i=0; i<bitlen; i++){
|
||||
if (i >= (bitlen - shift_factor)){
|
||||
new_val_wires[i] = zero_share_wires[i];
|
||||
}
|
||||
else{
|
||||
new_val_wires[i] = val_wires[i+shift_factor];
|
||||
}
|
||||
}
|
||||
share* x = create_new_share(new_val_wires, c);
|
||||
return x;
|
||||
}
|
||||
|
||||
share* arithmetic_right_shift(Circuit* c, share* val, uint32_t shift_factor) {
|
||||
int bitlen = val->get_bitlength();
|
||||
share* neg_val = c->PutSUBGate(get_zero_share(c, bitlen), val);
|
||||
share* is_pos = c->PutGTGate(neg_val, val);
|
||||
val = c->PutMUXGate(val, neg_val, is_pos);
|
||||
share* x = logical_right_shift(c, val, shift_factor);
|
||||
return c->PutMUXGate(x, c->PutSUBGate(get_zero_share(c, bitlen), x), is_pos);
|
||||
}
|
||||
|
||||
/*
|
||||
* we maintain a queue of outputs
|
||||
* basically every OUTPUT adds an OUTGate,
|
||||
* and adds the returned share to this queue
|
||||
* this queue is then flushed at the end after we have done exec
|
||||
*/
|
||||
|
||||
struct output_queue_elmt {
|
||||
ostream& os; //output stream to which we will output (cout or files), can this be a reference to prevent copying?
|
||||
e_role role; //who should we output the clear value to
|
||||
enum {PrintMsg, PrintValue } kind;
|
||||
string msg;
|
||||
share *ptr;
|
||||
};
|
||||
|
||||
typedef vector<output_queue_elmt> output_queue;
|
||||
/*
|
||||
* called from the EzPC generated code
|
||||
*/
|
||||
void add_to_output_queue(output_queue &q,
|
||||
share *ptr,
|
||||
e_role role,
|
||||
ostream &os)
|
||||
{
|
||||
struct output_queue_elmt elmt { os, role, output_queue_elmt::PrintValue, "", ptr };
|
||||
q.push_back(elmt);
|
||||
}
|
||||
|
||||
void add_print_msg_to_output_queue (output_queue &q, string msg, e_role role, ostream &os)
|
||||
{
|
||||
struct output_queue_elmt elmt { os, role, output_queue_elmt::PrintMsg, msg, NULL };
|
||||
q.push_back(elmt);
|
||||
}
|
||||
|
||||
/*
|
||||
* flush the queue
|
||||
* both parties call this function with their role
|
||||
* called from the EzPC generated code
|
||||
*/
|
||||
void flush_output_queue(output_queue &q, e_role role, uint32_t bitlen)
|
||||
{
|
||||
for(output_queue::iterator it = q.begin(); it != q.end(); ++it) { //iterate over the queue
|
||||
if (it->kind == output_queue_elmt::PrintValue) {
|
||||
if(it->role == ALL || it->role == role) { //if the queue element role is same as mine
|
||||
if(bitlen == 32) { //output to the stream
|
||||
it->os << it->ptr->get_clear_value<uint32_t>() << endl;
|
||||
} else {
|
||||
it->os << it->ptr->get_clear_value<uint64_t>() << endl;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(it->role == ALL || it->role == role) { //if the queue element role is same as mine
|
||||
it->os << it->msg << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* function to write a single share
|
||||
* called from EzPC generated code
|
||||
*
|
||||
* TODO: confused about bitlen
|
||||
*/
|
||||
void write_share(share *ptr, Circuit *circ, uint32_t bitlen, e_role role,
|
||||
ofstream &of_add,
|
||||
ofstream &of_rand,
|
||||
output_queue &q)
|
||||
{
|
||||
/* input shares of a random value, SERVER handles rand, CLIENT handles added shares */
|
||||
share *rand_sh = role == SERVER ? circ->PutINGate((uint32_t)rand(), bitlen, SERVER) : circ->PutDummyINGate(bitlen);
|
||||
/* add the input share with the random share */
|
||||
share *add_sh = circ->PutADDGate(ptr, rand_sh);
|
||||
/* add to the output q, so that it gets written out */
|
||||
add_to_output_queue(q, circ->PutOUTGate(rand_sh, SERVER), SERVER, of_rand);
|
||||
add_to_output_queue(q, circ->PutOUTGate(add_sh, CLIENT), CLIENT, of_add);
|
||||
/* TODO: can we optimize OUTPUT gates for the random value, since we already have its clear value in hand? */
|
||||
return;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
share *read_share(Circuit *circ, e_role role, uint32_t bitlen,
|
||||
ifstream &if_add,
|
||||
ifstream &if_rand)
|
||||
{
|
||||
/*
|
||||
* Variables for reading the added value and the random value
|
||||
*/
|
||||
T add_val;
|
||||
T rand_val;
|
||||
if(role == SERVER) { if_rand >> rand_val; }
|
||||
if(role == CLIENT) { if_add >> add_val; }
|
||||
share *add_sh = role == SERVER ? circ->PutDummyINGate(bitlen) : circ->PutINGate(add_val, bitlen, CLIENT);
|
||||
share *rand_sh = role == SERVER ? circ->PutINGate(rand_val, bitlen, SERVER) : circ->PutDummyINGate(bitlen);
|
||||
return circ->PutSUBGate(add_sh, rand_sh);
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user