use std::fs::File;
use std::io::{stdout, BufWriter, Write};
use std::net::SocketAddr;
use std::path::PathBuf;
use anyhow::Result;
use clap::Parser;
use tracing_subscriber::EnvFilter;
use seec::circuit::base_circuit::Load;
use seec::circuit::{BaseCircuit, ExecutableCircuit};
use seec::common::BitVec;
use seec::executor::{Executor, Input, Message};
use seec::mul_triple::boolean::insecure_provider::InsecureMTProvider;
use seec::mul_triple::boolean::trusted_seed_provider::TrustedMTProviderClient;
use seec::protocols::boolean_gmw::BooleanGmw;
use seec::BooleanGate;
use seec_channel::sub_channels_for;
use seec_channel::util::{Phase, Statistics};
#[derive(Parser, Debug)]
struct Args {
#[clap(long)]
id: usize,
#[clap(long)]
server: SocketAddr,
#[clap(long)]
mt_provider: Option<SocketAddr>,
#[clap(
long,
default_value = "test_resources/bristol-circuits/sha-256-low_depth.txt"
)]
circuit: PathBuf,
#[clap(long)]
stats: Option<PathBuf>,
}
#[tokio::main]
async fn main() -> Result<()> {
let _guard = init_tracing()?;
let args = Args::parse();
let circuit: ExecutableCircuit<bool, BooleanGate, u32> = ExecutableCircuit::DynLayers(
BaseCircuit::load_bristol(args.circuit, Load::Circuit)?.into(),
);
let (mut sender, bytes_written, mut receiver, bytes_read) = match args.id {
0 => seec_channel::tcp::listen(args.server).await?,
1 => seec_channel::tcp::connect(args.server).await?,
illegal => anyhow::bail!("Illegal party id {illegal}. Must be 0 or 1."),
};
let mut comm_stats = Statistics::new(bytes_written, bytes_read).without_unaccounted(true);
let (mut sender, mut receiver) =
sub_channels_for!(&mut sender, &mut receiver, 8, Message<BooleanGmw>).await?;
let mut executor: Executor<BooleanGmw, _> = if let Some(addr) = args.mt_provider {
let (mt_sender, bytes_written, mt_receiver, bytes_read) =
seec_channel::tcp::connect(addr).await?;
comm_stats.set_helper(bytes_written, bytes_read);
let mt_provider = TrustedMTProviderClient::new("unique-id".into(), mt_sender, mt_receiver);
comm_stats
.record_helper(
Phase::Custom("Helper-Mts".into()),
Executor::new(&circuit, args.id, mt_provider),
)
.await?
} else {
let mt_provider = InsecureMTProvider::default();
comm_stats
.record(
Phase::FunctionDependentSetup,
Executor::new(&circuit, args.id, mt_provider),
)
.await?
};
let input = BitVec::repeat(false, 768);
let _out = comm_stats
.record(
Phase::Online,
executor.execute(Input::Scalar(input), &mut sender, &mut receiver),
)
.await?;
let mut writer: Box<dyn Write> = match args.stats {
Some(path) => {
let file = File::create(path)?;
Box::new(file)
}
None => Box::new(stdout()),
};
let mut res = comm_stats.into_run_result();
res.add_metadata("circuit", "sha256.rs");
serde_json::to_writer_pretty(&mut writer, &res)?;
writeln!(writer)?;
Ok(())
}
pub fn init_tracing() -> Result<tracing_appender::non_blocking::WorkerGuard> {
let log_writer = BufWriter::new(File::create("sha256.log")?);
let (non_blocking, appender_guard) = tracing_appender::non_blocking(log_writer);
tracing_subscriber::fmt()
.json()
.with_env_filter(EnvFilter::from_default_env())
.with_writer(non_blocking)
.init();
Ok(appender_guard)
}