Revert "Added conversion gates and integrated SharingMap"

This reverts commit bd022fad38.
This commit is contained in:
Edward Chen
2021-08-25 16:48:07 -04:00
parent bd022fad38
commit 5579b99888
14 changed files with 183 additions and 296 deletions

View File

@@ -10,7 +10,7 @@ init:
git submodule update --init
aby:
./scripts/build_mpc_zokrates_test.zsh && ./scripts/build_aby.zsh && python3 ./scripts/test_aby.py
./scripts/zokrates_test.zsh && ./scripts/build_aby.zsh && python3 ./scripts/test_aby.py
clean:
# remove all generated files

View File

@@ -1,4 +0,0 @@
def main(private<1> u32 a, private<2> u32 b) -> u32:
bool c = true
bool d = false
return if c || d then a + b else a * b fi

View File

@@ -7,9 +7,11 @@ use circ::front::FrontEnd;
use circ::ir::opt::{opt, Opt};
use circ::target::aby::output::write_aby_exec;
use circ::target::aby::trans::to_aby;
use circ::target::ilp::trans::to_ilp;
use circ::target::r1cs::opt::reduce_linearities;
use circ::target::r1cs::trans::to_r1cs;
use circ::target::ilp::{
trans::to_ilp
};
use env_logger;
use good_lp::default_solver;
use std::path::PathBuf;
@@ -58,10 +60,13 @@ fn main() {
};
let cs = Zokrates::gen(inputs);
let cs = match mode {
Mode::Opt => opt(cs, vec![Opt::ConstantFold]),
Mode::Opt => opt(
cs,
vec![Opt::ConstantFold],
),
Mode::Mpc(_) => opt(
cs,
vec![], //Opt::Sha, Opt::ConstantFold, Opt::Mem, Opt::ConstantFold],
vec![Opt::Sha, Opt::ConstantFold, Opt::Mem, Opt::ConstantFold],
),
Mode::Proof => opt(
cs,
@@ -102,7 +107,7 @@ fn main() {
let (max, vars) = solver_result.expect("ILP could not be solved");
println!("Max value: {}", max.round() as u64);
println!("Assignment:");
for (var, val) in &vars {
println!(" {}: {}", var, val.round() as u64);
}

View File

@@ -1,7 +1,7 @@
use circ::ir::term::*;
use circ::target::aby::assignment::ilp;
use circ::term;
use structopt::StructOpt;
use circ::ir::term::*;
use circ::term;
use circ::target::aby::assignment::ilp;
#[derive(Debug, StructOpt)]
#[structopt(

View File

@@ -23,7 +23,7 @@ function mpc_test {
RUST_BACKTRACE=1 measure_time $BIN -p $parties $zpath
}
# build mpc arithmetic tests
# # 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
@@ -35,20 +35,20 @@ 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
# build mpc nary arithmetic tests
# # build mpc nary arithmetic tests
mpc_test 2 ./examples/ZoKrates/mpc/nary_arithmetic_tests/2pc_nary_arithmetic_add.zok
# build mpc bitwise tests
# # 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
# build mpc boolean tests
# # 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
# build mpc nary boolean tests
# # build mpc nary boolean tests
mpc_test 2 ./examples/ZoKrates/mpc/nary_boolean_tests/2pc_nary_boolean_and.zok
# build ite tests
@@ -56,7 +56,7 @@ 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
# build mpc misc tests
# # build mpc misc tests
mpc_test 2 ./examples/ZoKrates/mpc/2pc_millionaire.zok
@@ -66,4 +66,3 @@ mpc_test 2 ./examples/ZoKrates/mpc/const_tests/2pc_const_bool.zok
# build mpc misc tests
mpc_test 2 ./examples/ZoKrates/mpc/2pc_millionaire.zok
mpc_test 2 ./examples/ZoKrates/mpc/2pc_conv.zok

View File

@@ -1,6 +1,5 @@
from subprocess import Popen, PIPE
from typing import List
import time
arithmetic_tests = [
[
@@ -451,13 +450,6 @@ misc_tests = [
{"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:
@@ -487,6 +479,7 @@ def run_test(desc: str, expected: str, server_cmd: List[str], client_cmd: List[s
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()
@@ -521,7 +514,7 @@ def main():
const_tests + \
ite_tests + \
misc_tests
# tests = misc_tests
failed_test_descs = []
num_retries = 3

View File

@@ -487,18 +487,21 @@ impl<'ast> ZGen<'ast> {
Mode::Opt => {
let ret_term = r.unwrap_term();
let ret_terms = ret_term.terms();
assert!(
ret_terms.len() == 1,
"When compiling to optimize, there can only be one output"
);
assert!(ret_terms.len() == 1, "When compiling to optimize, there can only be one output");
let t = ret_terms.into_iter().next().unwrap();
match check(&t) {
Sort::BitVector(_) => {}
Sort::BitVector(_) => {
}
s => {
panic!("Cannot maximize output of type {}", s)
}
}
self.circ.cir_ctx().cs.borrow_mut().outputs.push(t);
self.circ
.cir_ctx()
.cs
.borrow_mut()
.outputs
.push(t);
}
}
}

View File

@@ -37,7 +37,7 @@ use crate::ir::term::*;
use crate::target::ilp::{variable, Expression, Ilp, Variable};
use std::{env::var, fs::File, path::Path};
use std::{fs::File, path::Path, env::var};
/// A cost model for ABY operations and share conversions
#[derive(Debug)]
@@ -86,10 +86,10 @@ impl CostModel {
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],
"ge" => vec![BV_ULE],
"le" => vec![BV_SLE],
"gt" => vec![BV_ULT],
"lt" => vec![BV_SLT],
// assume n-ary ops apply to BVs
"add" => vec![BV_ADD],
"mul" => vec![BV_MUL],

View File

@@ -1,11 +1,11 @@
//! Machinery for assigning operations to sharing schemes
use crate::ir::term::{Computation, Op, BvNaryOp, PostOrderIter, TermMap};
use crate::ir::term::{Computation, PostOrderIter, TermMap};
pub mod ilp;
/// The sharing scheme used for an operation
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
#[derive(Debug,PartialEq,Eq,Hash,Clone,Copy)]
pub enum ShareType {
/// Arithmetic sharing (additive mod `Z_(2^l)`)
Arithmetic,
@@ -15,6 +15,7 @@ pub enum ShareType {
Yao,
}
/// List of share types.
pub const SHARE_TYPES: [ShareType; 3] = [ShareType::Arithmetic, ShareType::Boolean, ShareType::Yao];
@@ -40,20 +41,3 @@ pub fn all_boolean_sharing(c: &Computation) -> SharingMap {
})
.collect()
}
/// Assigns arithmetic sharing to addition and multiplication
pub fn some_arith_sharing(c: &Computation) -> SharingMap {
c.outputs
.iter()
.flat_map(|output| {
PostOrderIter::new(output.clone()).map(|term| match &term.op {
Op::BvNaryOp(o) => match o {
BvNaryOp::Add => (term.clone(), ShareType::Arithmetic),
BvNaryOp::Mul => (term.clone(), ShareType::Arithmetic),
_ => (term.clone(), ShareType::Boolean),
}
_ => (term.clone(), ShareType::Boolean),
})
})
.collect()
}

View File

@@ -3,6 +3,7 @@ pub mod assignment;
pub mod output;
pub mod trans;
#[derive(Clone, Debug)]
/// ABY Circuit
/// The ABY Circuit consists of three Vec<String>: setup, circ, and closer

View File

@@ -5,11 +5,8 @@
//! [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 std::collections::HashMap;
const NO_ROLE: u8 = u8::MAX;
const SERVER: u8 = 0;
@@ -25,108 +22,52 @@ enum EmbeddedTerm {
struct ToABY {
aby: ABY,
md: ComputationMetadata,
inputs: TermMap<Option<PartyId>>,
inputs: HashMap<String, Option<PartyId>>,
cache: TermMap<EmbeddedTerm>,
s_map: SharingMap,
output_gate: String,
}
impl ToABY {
fn new(metadata: ComputationMetadata, s_map: SharingMap) -> Self {
fn new(metadata: ComputationMetadata) -> Self {
Self {
aby: ABY::new(),
md: metadata,
inputs: TermMap::new(),
inputs: HashMap::new(),
cache: TermMap::new(),
s_map: s_map,
output_gate: "out".to_string(),
}
}
fn get_var_name(t: Term) -> String {
match &t.op {
Op::Var(name, _) => name.to_string(),
_ => panic!("Term {} is not of type Var", t),
}
/// Initialize the ABY Party, sharing scheme, and Circuit object
fn setup(&mut self) {
self.aby.setup.push("ABYParty* party = new ABYParty(role, address, port, seclvl, bitlen, nthreads, mt_alg);".to_string());
self.aby
.setup
.push("std::vector<Sharing*>& sharings = party->GetSharings();".to_string());
self.aby
.setup
.push("Circuit* circ = sharings[sharing]->GetCircuitBuildRoutine();".to_string());
}
/// Parse variable name from IR representation of a variable
fn parse_var_name(&self, full_name: String) -> String {
let parsed: Vec<String> = full_name.split("_").map(str::to_string).collect();
let parsed: Vec::<String> = full_name.split("_").map(str::to_string).collect();
if parsed.len() < 2 {
panic!("Invalid variable name: {}", full_name);
}
parsed[parsed.len() - 2].to_string()
}
fn get_sharetype_circ(&self, t: Term) -> String {
if !self.s_map.contains_key(&t) {
panic!("No sharing type for {:?}", t);
}
let s = self.s_map.get(&t).unwrap();
match *s {
ShareType::Arithmetic => "acirc".to_string(),
ShareType::Boolean => "bcirc".to_string(),
ShareType::Yao => "ycirc".to_string(),
}
}
fn add_conv_gate(&self, p_t: Term, c_t: Term, c_circ: String) -> String {
let p_share = self.s_map.get(&p_t).unwrap();
let c_share = self.s_map.get(&c_t).unwrap();
match (c_share, p_share) {
(ShareType::Arithmetic, ShareType::Arithmetic) => c_circ,
(ShareType::Boolean, ShareType::Boolean) => c_circ,
(ShareType::Yao, ShareType::Yao) => c_circ,
(ShareType::Arithmetic, ShareType::Boolean) => {
format!("bcirc->PutY2BGate(ycirc->PutA2YGate({}))", c_circ)
}
(ShareType::Arithmetic, ShareType::Yao) => format!("ycirc->PutA2YGate({})", c_circ),
(ShareType::Boolean, ShareType::Arithmetic) => format!("acirc->PutB2AGate({})", c_circ),
(ShareType::Boolean, ShareType::Yao) => format!("ycirc->PutB2YGate({})", c_circ),
(ShareType::Yao, ShareType::Arithmetic) => {
format!("acirc->PutB2AGate(bcirc->PutY2BGate({}))", c_circ)
}
(ShareType::Yao, ShareType::Boolean) => format!("bcirc->PutY2BGate({})", c_circ),
}
}
fn add_cons_gate(&self, t: Term) -> String {
let name = ToABY::get_var_name(t.clone());
let s_circ = self.get_sharetype_circ(t.clone());
format!(
"s_{} = {}->PutCONSGate((uint64_t){}, bitlen);",
name, s_circ, name
)
.to_string()
}
fn add_in_gate(&self, t: Term, role: String) -> String {
let name = ToABY::get_var_name(t.clone());
let s_circ = self.get_sharetype_circ(t.clone());
format!(
"\ts_{} = {}->PutINGate({}, bitlen, {});",
name, s_circ, name, role
)
.to_string()
}
fn add_dummy_gate(&self, t: Term) -> String {
let name = ToABY::get_var_name(t.clone());
let s_circ = self.get_sharetype_circ(t.clone());
format!("\ts_{} = {}->PutDummyINGate(bitlen);", name, s_circ).to_string()
}
/// Initialize private and public inputs from each party
/// Party inputs are stored in *self.inputs*
fn init_inputs(&mut self) {
let mut server_inputs = TermSet::new();
let mut client_inputs = TermSet::new();
let mut public_inputs = TermSet::new();
let mut server_inputs = Vec::<&str>::new();
let mut client_inputs = Vec::<&str>::new();
let mut public_inputs = Vec::<&str>::new();
// 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());
for (name, party) in self.inputs.iter() {
self.aby.setup.push(format!(
"uint32_t {} = std::atoi(params[\"{}\"].c_str());",
name,
@@ -137,88 +78,108 @@ impl ToABY {
.push(format!("share *s_{};", name).to_string());
let role = party.unwrap_or_else(|| NO_ROLE);
if role == SERVER {
server_inputs.insert(t.clone());
server_inputs.push(name);
} else if role == CLIENT {
client_inputs.insert(t.clone());
client_inputs.push(name);
} else if role != SERVER && role != CLIENT && self.md.is_input_public(&name) {
public_inputs.insert(t.clone());
public_inputs.push(name);
} else {
panic!("Unknown role or visibility for variable: {}", name);
}
}
// Initialize public inputs as CONS gateshares
for t in public_inputs.iter() {
self.aby.setup.push(self.add_cons_gate(t.clone()));
// Initialize output gate
self.aby
.setup
.push(format!("share *s_{};", self.output_gate).to_string());
// Initialize public inputs as CONS shares
for input in public_inputs.iter() {
self.aby
.setup
.push(format!("s_{} = circ->PutCONSGate({}, bitlen);", input, input).to_string());
}
// Initialize Server inputs
self.aby.setup.push("if (role == SERVER) {".to_string());
for t in server_inputs.iter() {
for input in server_inputs.iter() {
self.aby.setup.push(
format!(
"\ts_{} = circ->PutINGate({}, bitlen, SERVER);",
input, input
)
.to_string(),
);
}
for input in client_inputs.iter() {
self.aby
.setup
.push(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()));
.push(format!("\ts_{} = circ->PutDummyINGate(bitlen);", input).to_string());
}
self.aby.setup.push("}".to_string());
// Initialize Client inputs
self.aby.setup.push("if (role == CLIENT) {".to_string());
for t in client_inputs.iter() {
for input in client_inputs.iter() {
self.aby.setup.push(
format!(
"\ts_{} = circ->PutINGate({}, bitlen, CLIENT);",
input, input
)
.to_string(),
);
}
for input in server_inputs.iter() {
self.aby
.setup
.push(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()));
.push(format!("\ts_{} = circ->PutDummyINGate(bitlen);", input).to_string());
}
self.aby.setup.push("}\n".to_string());
}
/// Clean up code to execute circuit, get circuit output, and return
fn closer(&mut self) {
self.aby.closer.push("\tparty->ExecCircuit();".to_string());
self.aby.closer.push(format!(
"uint32_t output = s_{}->get_clear_value<uint32_t>();\n\tstd::cout << \"output: \" << output << std::endl;",
self.output_gate
));
self.aby.closer.push("delete party;".to_string());
self.aby.closer.push("return 0;".to_string());
}
/// Return constant gate evaluating to 0
#[allow(dead_code)]
fn zero() -> String {
format!("bcirc->PutCONSGate((uint64_t)0, (uint32_t)1)")
format!("circ->PutCONSGate((uint32_t)0, (uint32_t)1)")
}
/// Return constant gate evaluating to 1
fn one() -> String {
format!("bcirc->PutCONSGate((uint64_t)1, (uint32_t)1)")
format!("circ->PutCONSGate((uint32_t)1, (uint32_t)1)")
}
fn embed_eq(&mut self, t: Term, a: Term, b: Term) -> String {
let s_circ = self.get_sharetype_circ(t.clone());
match check(&a) {
fn embed_eq(&mut self, t: Term, a: &Term, b: &Term) -> String {
match check(a) {
Sort::Bool => {
let a_circ = self.get_bool(&a).clone();
let b_circ = self.get_bool(&b).clone();
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 a = self.get_bool(a).clone();
let b = self.get_bool(b).clone();
let s = format!(
"{}->PutXORGate({}->PutXORGate({}, {}), {})",
s_circ,
s_circ,
a_conv,
b_conv,
"circ->PutXORGate(circ->PutXORGate({}, {}), {})",
a,
b,
ToABY::one()
);
self.cache.insert(t.clone(), EmbeddedTerm::Bool(s.clone()));
s
}
Sort::BitVector(_) => {
let a_circ = self.get_bv(&a).clone();
let b_circ = self.get_bv(&b).clone();
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 a = self.get_bv(a).clone();
let b = self.get_bv(b).clone();
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()
"circ->PutXORGate(circ->PutXORGate(circ->PutGTGate({}, {}), circ->PutGTGate({}, {})), {})",
a, b, b, a, ToABY::one()
);
self.cache.insert(t.clone(), EmbeddedTerm::Bool(s.clone()));
s
@@ -241,12 +202,11 @@ impl ToABY {
}
fn embed_bool(&mut self, t: Term) -> String {
let mut s_circ = self.get_sharetype_circ(t.clone());
match &t.op {
Op::Var(name, Sort::Bool) => {
if !self.inputs.contains_key(&t) {
if !self.inputs.contains_key(name) {
self.inputs
.insert(t.clone(), *self.md.inputs.get(name).unwrap());
.insert(name.to_string(), *self.md.inputs.get(name).unwrap());
}
if !self.cache.contains_key(&t) {
self.cache
@@ -257,110 +217,88 @@ impl ToABY {
self.cache.insert(
t.clone(),
EmbeddedTerm::Bool(format!(
"{}->PutCONSGate((uint64_t){}, (uint32_t){})",
s_circ, *b as isize, BOOLEAN_BITLEN
"circ->PutCONSGate((uint32_t){}, (uint32_t){})",
*b as isize,
BOOLEAN_BITLEN
)),
);
}
Op::Eq => {
let _s = self.embed_eq(t.clone(), t.cs[0].clone(), t.cs[1].clone());
let _s = self.embed_eq(t.clone(), &t.cs[0], &t.cs[1]);
}
Op::Ite => {
let sel_circ = self.get_bool(&t.cs[0]).clone();
let a_circ = self.get_bool(&t.cs[1]).clone();
let b_circ = self.get_bool(&t.cs[2]).clone();
let sel_conv = self.add_conv_gate(t.clone(), t.cs[0].clone(), sel_circ);
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);
let sel = self.get_bool(&t.cs[0]).clone();
let a = self.get_bool(&t.cs[1]).clone();
let b = self.get_bool(&t.cs[2]).clone();
self.cache.insert(
t.clone(),
EmbeddedTerm::Bool(format!(
"{}->PutMUXGate({}, {}, {})",
s_circ, a_conv, b_conv, sel_conv
)),
EmbeddedTerm::Bool(format!("circ->PutMUXGate({}, {}, {})", a, b, sel)),
);
}
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);
let a = self.get_bool(&t.cs[0]);
self.cache.insert(
t.clone(),
EmbeddedTerm::Bool(format!(
"((BooleanCircuit *) {})->PutINVGate({})",
s_circ, a_conv
)),
EmbeddedTerm::Bool(format!("((BooleanCircuit *)circ)->PutINVGate({})", a)),
);
}
Op::BoolNaryOp(o) => {
let a_circ = self.get_bool(&t.cs[0]).clone();
let b_circ = self.get_bool(&t.cs[1]).clone();
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 = self.get_bool(&t.cs[0]).clone();
let b = self.get_bool(&t.cs[1]).clone();
let mut circ = "circ";
if *o == BoolNaryOp::Or {
s_circ = format!("((BooleanCircuit *) {})", s_circ);
circ = "((BooleanCircuit *)circ)";
}
self.cache.insert(
t.clone(),
EmbeddedTerm::Bool(format!(
"{}->{}({}, {})",
s_circ,
circ,
match o {
BoolNaryOp::Or => "PutORGate",
BoolNaryOp::And => "PutANDGate",
BoolNaryOp::Xor => "PutXORGate",
},
a_conv,
b_conv
a,
b
)),
);
}
Op::BvBinPred(op) => {
let a_circ = self.get_bv(&t.cs[0]);
let b_circ = self.get_bv(&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 = self.get_bv(&t.cs[0]);
let b = self.get_bv(&t.cs[1]);
match op {
BvBinPred::Uge => {
self.cache.insert(
t.clone(),
EmbeddedTerm::Bool(format!(
"((BooleanCircuit *){})->PutINVGate({}->PutGTGate({}, {}))",
s_circ, s_circ, b_conv, a_conv
"((BooleanCircuit *)circ)->PutINVGate(circ->PutGTGate({}, {}))",
b, a
)),
);
}
BvBinPred::Ugt => {
self.cache.insert(
t.clone(),
EmbeddedTerm::Bool(format!(
"{}->PutGTGate({}, {})",
s_circ, a_conv, b_conv
)),
EmbeddedTerm::Bool(format!("circ->PutGTGate({}, {})", a, b)),
);
}
BvBinPred::Ule => {
self.cache.insert(
t.clone(),
EmbeddedTerm::Bool(format!(
"((BooleanCircuit *){})->PutINVGate({}->PutGTGate({}, {}))",
s_circ, s_circ, a_conv, b_conv
"((BooleanCircuit *)circ)->PutINVGate(circ->PutGTGate({}, {}))",
a, b
)),
);
}
BvBinPred::Ult => {
self.cache.insert(
t.clone(),
EmbeddedTerm::Bool(format!(
"{}->PutGTGate({}, {})",
s_circ, b_conv, a_conv
)),
EmbeddedTerm::Bool(format!("circ->PutGTGate({}, {})", b, a)),
);
}
_ => panic!("Non-field in bool BvBinPred: {}", op),
@@ -386,12 +324,11 @@ impl ToABY {
}
fn embed_bv(&mut self, t: Term) -> String {
let mut s_circ = self.get_sharetype_circ(t.clone());
match &t.op {
Op::Var(name, Sort::BitVector(_)) => {
if !self.inputs.contains_key(&t) {
if !self.inputs.contains_key(name) {
self.inputs
.insert(t.clone(), *self.md.inputs.get(name).unwrap());
.insert(name.to_string(), *self.md.inputs.get(name).unwrap());
}
if !self.cache.contains_key(&t) {
self.cache
@@ -399,49 +336,39 @@ impl ToABY {
}
}
Op::Const(Value::BitVector(b)) => {
println!("BV: {}", b);
self.cache.insert(
t.clone(),
EmbeddedTerm::Bv(format!(
"{}->PutCONSGate((uint64_t){}, (uint32_t){})",
s_circ,
"circ->PutCONSGate((uint32_t){}, (uint32_t){})",
format!("{}", b).replace("#", "0"),
b.width()
)),
);
}
Op::Ite => {
let sel_circ = self.get_bool(&t.cs[0]).clone();
let a_circ = self.get_bv(&t.cs[1]).clone();
let b_circ = self.get_bv(&t.cs[2]).clone();
let sel_conv = self.add_conv_gate(t.clone(), t.cs[0].clone(), sel_circ);
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);
let sel = self.get_bool(&t.cs[0]).clone();
let a = self.get_bv(&t.cs[1]).clone();
let b = self.get_bv(&t.cs[2]).clone();
self.cache.insert(
t.clone(),
EmbeddedTerm::Bv(format!(
"{}->PutMUXGate({}, {}, {})",
s_circ, a_conv, b_conv, sel_conv
)),
EmbeddedTerm::Bv(format!("circ->PutMUXGate({}, {}, {})", a, b, sel)),
);
}
Op::BvNaryOp(o) => {
let a_circ = self.get_bv(&t.cs[0]);
let b_circ = self.get_bv(&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 = self.get_bv(&t.cs[0]);
let b = self.get_bv(&t.cs[1]);
let mut circ = "circ";
if *o == BvNaryOp::Or {
s_circ = format!("((BooleanCircuit *){})", s_circ);
circ = "((BooleanCircuit *)circ)";
}
self.cache.insert(
t.clone(),
EmbeddedTerm::Bv(format!(
"{}->{}({}, {})",
s_circ,
circ,
match o {
BvNaryOp::Xor => "PutXORGate",
BvNaryOp::Or => "PutORGate",
@@ -449,26 +376,20 @@ impl ToABY {
BvNaryOp::Add => "PutADDGate",
BvNaryOp::Mul => "PutMULGate",
},
a_conv,
b_conv
a,
b
)),
);
}
Op::BvBinOp(o) => {
let a_circ = self.get_bv(&t.cs[0]);
let b_circ = self.get_bv(&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 = self.get_bv(&t.cs[0]);
let b = self.get_bv(&t.cs[1]);
match o {
BvBinOp::Sub => {
self.cache.insert(
t.clone(),
EmbeddedTerm::Bv(format!(
"{}->PutSUBGate({}, {})",
s_circ, a_conv, b_conv
)),
EmbeddedTerm::Bv(format!("circ->PutSUBGate({}, {})", a, b)),
);
}
_ => panic!("Invalid bv-op in BvBinOp: {:?}", o),
@@ -501,12 +422,15 @@ impl ToABY {
///
/// Return a String of the resulting Circuit
fn add_output_gate(&mut self, circ: String) -> String {
format!("\ts_out = bcirc->PutOUTGate({}, ALL);\n", circ)
format!(
"\ts_{} = circ->PutOUTGate({}, ALL);\n",
self.output_gate.clone(),
circ
)
}
/// Given a term `t`, lower `t` to ABY Circuits
fn lower(&mut self, t: Term) {
println!("{:?}", t);
let mut output_circ = self.embed(t);
output_circ = self.add_output_gate(output_circ);
self.aby.circs.push(output_circ);
@@ -519,11 +443,10 @@ pub fn to_aby(ir: Computation) -> ABY {
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);
} = ir;
let mut converter = ToABY::new(md);
converter.setup();
for t in terms {
println!("Terms: {}", t);
converter.lower(t.clone());
@@ -533,6 +456,7 @@ 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.closer();
converter.aby
}

View File

@@ -4,11 +4,11 @@ pub mod trans;
use ahash::AHashMap as HashMap;
pub(crate) use good_lp::{
variable, Constraint, Expression, ProblemVariables, ResolutionError, Solution, Solver,
SolverModel, Variable, VariableDefinition,
Constraint, Expression, ProblemVariables, ResolutionError, Solution, Solver, SolverModel,
Variable, VariableDefinition, variable
};
use log::debug;
use std::fmt::{self, Debug, Formatter};
use std::fmt::{self, Formatter, Debug};
/// An integer linear program
pub struct Ilp {
@@ -92,7 +92,9 @@ impl Ilp {
}
}
/// Solve, using the default solver of [good_lp].
pub fn default_solve(self) -> Result<(f64, HashMap<String, f64>), IlpUnsat> {
pub fn default_solve(
self,
) -> Result<(f64, HashMap<String, f64>), IlpUnsat> {
self.solve(good_lp::default_solver)
}
}

View File

@@ -905,9 +905,10 @@ mod test {
let c = leaf_term(Op::Var("c".to_owned(), Sort::Bool));
let cs = Computation {
outputs: vec![term![BV_ADD;
term![ITE; c, bv(2,4), bv(1,4)],
term![BV_MUL; a, bv(2,4)]
]],
term![ITE; c, bv(2,4), bv(1,4)],
term![BV_MUL; a, bv(2,4)]
],
],
metadata: ComputationMetadata::default(),
values: None,
};

View File

@@ -1,29 +1,8 @@
#include "{fn}.h"
#include "../../../abycore/circuit/booleancircuits.h"
#include "../../../abycore/circuit/arithmeticcircuits.h"
#include "../../../abycore/circuit/circuit.h"
#include "../../../abycore/sharing/sharing.h"
int32_t test_{fn}_circuit(std::map<std::string, std::string> params, e_role role, const std::string& address,
uint16_t port, seclvl seclvl, uint32_t bitlen, uint32_t nthreads, e_mt_gen_alg mt_alg, e_sharing sharing) {
// setup
ABYParty* party = new ABYParty(role, address, port, seclvl, bitlen, nthreads, mt_alg);
std::vector<Sharing*>& sharings = party->GetSharings();
Circuit* acirc = sharings[S_ARITH]->GetCircuitBuildRoutine();
Circuit* bcirc = sharings[S_BOOL]->GetCircuitBuildRoutine();
Circuit* ycirc = sharings[S_YAO]->GetCircuitBuildRoutine();
share *s_out;
// compiled circuit
uint16_t port, seclvl seclvl, uint32_t bitlen, uint32_t nthreads, e_mt_gen_alg mt_alg, e_sharing sharing) {
{circ}
// output
party->ExecCircuit();
uint32_t output = s_out->get_clear_value<uint32_t>();
std::cout << "output: " << output << std::endl;
delete party;
return 0;
}