updated cost models for hycc

This commit is contained in:
Edward Chen
2021-12-09 17:45:01 -05:00
parent adac3c114f
commit 57166c7cc9
13 changed files with 755 additions and 198 deletions

View File

@@ -40,6 +40,9 @@ struct Options {
#[structopt(long, default_value = "2", name = "PARTIES")]
parties: u8,
#[structopt(long, default_value = "hycc", name = "cost_model")]
cost_model: String,
#[structopt(subcommand)]
backend: Backend,
}
@@ -98,12 +101,18 @@ arg_enum! {
}
#[derive(PartialEq, Debug)]
enum DeterminedLanguage {
pub enum DeterminedLanguage {
Zokrates,
Datalog,
C,
}
#[derive(PartialEq, Debug)]
pub enum CostModelType {
Opa,
Hycc,
}
arg_enum! {
#[derive(PartialEq, Debug)]
enum ProofAction {
@@ -254,9 +263,14 @@ fn main() {
}
Backend::Mpc { .. } => {
println!("Converting to aby");
let lang = &String::from("zok");
to_aby(cs, &path_buf, &lang);
write_aby_exec(&path_buf, &lang);
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: {}", options.cost_model);
to_aby(cs, &path_buf, &lang_str, &options.cost_model);
write_aby_exec(&path_buf, &lang_str);
}
Backend::Ilp { .. } => {
println!("Converting to ilp");

View File

@@ -1,81 +0,0 @@
#![allow(unused_imports)]
use bellman::gadgets::test::TestConstraintSystem;
use bellman::Circuit;
use bls12_381::Scalar;
use circ::front::c::{Inputs, C};
use circ::front::{FrontEnd, Mode};
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 env_logger;
use good_lp::default_solver;
use std::path::PathBuf;
use structopt::StructOpt;
#[derive(Debug, StructOpt)]
#[structopt(name = "circ", about = "CirC: the circuit compiler")]
struct Options {
/// Input file
#[structopt(parse(from_os_str))]
input_file_path: PathBuf,
/// File with input witness
#[structopt(short, long, name = "FILE", parse(from_os_str))]
inputs: Option<PathBuf>,
/// Number of parties for an MPC. If missing, generates a proof circuit.
#[structopt(short, long, name = "PARTIES")]
parties: Option<u8>,
/// Whether to maximize the output
#[structopt(short, long)]
maximize: bool,
}
fn main() {
env_logger::Builder::from_default_env()
.format_level(false)
.format_timestamp(None)
.init();
let options = Options::from_args();
let path_buf = options.input_file_path.clone();
println!("{:?}", options);
let mode = if options.maximize {
Mode::Opt
} else {
match options.parties {
Some(p) => Mode::Mpc(p),
None => Mode::Proof,
}
};
let inputs = Inputs {
file: options.input_file_path,
inputs: options.inputs,
mode: mode.clone(),
};
let cs = C::gen(inputs);
// println!("{:#?}", cs);
let cs = match mode {
Mode::Mpc(_) => opt(
cs,
// vec![],
vec![Opt::Sha, Opt::ConstantFold, Opt::Mem, Opt::ConstantFold],
),
_ => unimplemented!(),
};
println!("Done with IR optimization");
match mode {
Mode::Mpc(_) => {
println!("Converting to aby");
let lang = &String::from("c");
to_aby(cs, &path_buf, &lang);
write_aby_exec(&path_buf, &lang);
}
_ => unimplemented!(),
}
}

View File

@@ -21,12 +21,12 @@ if __name__ == "__main__":
# tests = ilp_benchmark_tests
# tests = kmeans_tests + div_tests
# tests = kmeans_tests
tests = kmeans_tests
# tests = arithmetic_tests
# tests = div_tests
# TODO: add support for return value - int promotion
# unsigned_arithmetic_tests + \
tests = biomatch_tests
# tests = biomatch_tests
run_tests('c', tests)

View File

@@ -4,9 +4,10 @@ set -ex
disable -r time
cargo build --release --example circ_c
cargo build --release --example circ
BIN=./target/release/examples/circ_c
BIN=./target/release/examples/circ
export CARGO_MANIFEST_DIR=$(pwd)
case "$OSTYPE" in
darwin*)
@@ -19,8 +20,8 @@ esac
function mpc_test {
parties=$1
zpath=$2
RUST_BACKTRACE=1 measure_time $BIN -p $parties $zpath
cpath=$2
RUST_BACKTRACE=1 measure_time $BIN --parties $parties --cost-model "hycc" $cpath mpc
}
# # build mpc arithmetic tests
@@ -89,8 +90,8 @@ function mpc_test {
# mpc_test 2 ./examples/C/mpc/unit_tests/c_array_tests/2pc_array_sum_c.c
# benchmarks
# mpc_test 2 ./examples/C/mpc/benchmarks/2pc_kmeans.c
mpc_test 2 ./examples/C/mpc/benchmarks/2pc_biomatch.c
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

View File

@@ -54,77 +54,77 @@ impl CostModel {
pub fn from_opa_cost_file(p: &impl AsRef<Path>) -> CostModel {
use ShareType::*;
let get_cost_opt =
|op_name: &str, obj: &serde_json::map::Map<String, Value>| -> Option<f64> {
let o = obj.get(op_name)?;
|share_name: &str, obj: &serde_json::map::Map<String, Value>| -> Option<f64> {
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<String, Value>| -> 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![Op::Not, Op::Eq],
"bvudiv" => vec![BV_UDIV],
"bvurem" => vec![BV_UREM],
// added to pass test case
"&&" => vec![AND],
"||" => vec![OR],
_ => 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);
}
}
}
@@ -135,10 +135,16 @@ impl CostModel {
}
/// Uses an ILP to assign...
pub fn assign(c: &Computation) -> SharingMap {
pub fn assign(c: &Computation, cm: &String) -> SharingMap {
let base_dir = match cm.as_ref() {
"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)
@@ -159,7 +165,7 @@ fn build_ilp(c: &Computation, costs: &CostModel) -> SharingMap {
let mut term_vars: FxHashMap<(Term, ShareType), (Variable, f64, String)> = FxHashMap::default();
let mut conv_vars: FxHashMap<(Term, ShareType, ShareType), (Variable, f64)> = FxHashMap::default();
let mut ilp = Ilp::new();
// build variables for all term assignments
for (t, i) in terms.iter() {
let mut vars = vec![];

View File

@@ -628,13 +628,13 @@ impl ToABY {
}
/// Convert this (IR) `ir` to ABY.
pub fn to_aby(ir: Computation, path_buf: &PathBuf, lang: &String) {
pub fn to_aby(ir: Computation, path_buf: &PathBuf, lang: &String, cm: &String) {
let Computation {
outputs: terms,
metadata: md,
values: _,
} = ir.clone();
let s_map: SharingMap = assign(&ir);
let s_map: SharingMap = assign(&ir, cm);
// let s_map: SharingMap = some_arith_sharing(&ir);
let mut converter = ToABY::new(md, s_map, path_buf, lang);

3
third_party/hycc/README.md vendored Normal file
View File

@@ -0,0 +1,3 @@
# Adapted from the HyCC distribution
[Source](https://gitlab.com/securityengineering/HyCC/)

254
third_party/hycc/adapted_costs.json vendored Normal file
View File

@@ -0,0 +1,254 @@
{
"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": {
"a": {
"32": 1
},
"b": {
"32": 10
},
"y": {
"32": 100
}
},
"rem": {
"a": {
"32": 1
},
"b": {
"32": 10
},
"y": {
"32": 100
}
}
}

212
third_party/hycc/original_costs.json vendored Normal file
View File

@@ -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
}
}
}

View File

@@ -1,3 +1,3 @@
# From the OPA distribution
# Adapted from the OPA distribution
[Source](https://github.com/ishaq/OPA)

187
third_party/opa/adapted_costs.json vendored Normal file
View File

@@ -0,0 +1,187 @@
{
"&&": {
"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": {
"a": {
"32": 1
},
"b": {
"32": 10
},
"y": {
"32": 100
}
},
"rem": {
"a": {
"32": 1
},
"b": {
"32": 10
},
"y": {
"32": 100
}
}
}

View File

@@ -146,45 +146,6 @@
},
"y2b": {
"1": 2040.2
},
"bvudiv": {
"b": {
"1": 10
},
"y": {
"1": 100
},
"a": {
"1": 1
}
},
"bvurem": {
"b": {
"1": 10
},
"y": {
"1": 100
},
"a": {
"1": 1
}
},
"&&": {
"b": {
"1": 117
},
"y": {
"1": 32
}
},
"||": {
"b": {
"1": 123
},
"y": {
"1": 40
}
}
}
}