Add Oracle and graphviz output
This commit is contained in:
parent
7ac7eaa193
commit
e681e35054
|
@ -13,5 +13,6 @@ rand_distr = "0.4.0"
|
|||
hashbrown = "0.9.1"
|
||||
termcolor = "1.1.2"
|
||||
clap = "3.0.0-beta.2"
|
||||
tracing = "0.1.0"
|
||||
tracing-subscriber = "0.2"
|
||||
tracing = "0.1.22"
|
||||
tracing-subscriber = "0.2.15"
|
||||
hex = "0.4.2"
|
17
src/main.rs
17
src/main.rs
|
@ -3,11 +3,14 @@ use crate::server::SimulatedServer;
|
|||
use rand_distr::Pareto;
|
||||
use std::io::Write;
|
||||
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
|
||||
mod oracle;
|
||||
mod parties;
|
||||
mod server;
|
||||
|
||||
use clap::Clap;
|
||||
use tracing::event;
|
||||
|
||||
use crate::oracle::Oracle;
|
||||
use tracing::Level;
|
||||
use tracing_subscriber;
|
||||
use tracing_subscriber::FmtSubscriber;
|
||||
|
@ -47,7 +50,10 @@ fn main() {
|
|||
true => Level::TRACE,
|
||||
_ => Level::INFO,
|
||||
};
|
||||
let subscriber = FmtSubscriber::builder().with_max_level(level).finish();
|
||||
|
||||
let mut oracle = Oracle::new();
|
||||
|
||||
let subscriber = FmtSubscriber::default();
|
||||
tracing::subscriber::with_default(subscriber, || {
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut server = SimulatedServer::new();
|
||||
|
@ -55,14 +61,14 @@ fn main() {
|
|||
let simulated_parties = SimulatedParties::new_simulation(opts.num_parties, opts.gamma);
|
||||
{
|
||||
event!(Level::INFO, "Generating {} Parties and registering them with the server", opts.num_parties);
|
||||
simulated_parties.register_with_server(&mut server, &mut rng, opts.min_p, opts.max_p);
|
||||
simulated_parties.register_with_server(&mut server, &mut rng, opts.min_p, opts.max_p, &mut oracle);
|
||||
}
|
||||
|
||||
let pareto = Pareto::new(1.0, 1.0).unwrap();
|
||||
|
||||
{
|
||||
event!(Level::INFO, "Simulating message sends using {} samples from a pareto distribution...", opts.samples_per_round);
|
||||
(0..opts.samples_per_round).for_each(|_i| simulated_parties.sample_traffic(&mut server, &mut rng, pareto, opts.prob_entangled));
|
||||
(0..opts.samples_per_round).for_each(|_i| simulated_parties.sample_traffic(&mut server, &mut rng, pareto, opts.prob_entangled, &mut oracle));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -71,7 +77,7 @@ fn main() {
|
|||
}
|
||||
|
||||
{
|
||||
let (round_stats, party_stats) = server.statistics();
|
||||
let (server_oracle, round_stats, party_stats) = server.statistics();
|
||||
let if_uniform = (round_stats.num_messages as f64) / (round_stats.num_registered_parties as f64);
|
||||
event!(
|
||||
Level::INFO,
|
||||
|
@ -101,6 +107,9 @@ fn main() {
|
|||
)
|
||||
.unwrap();
|
||||
}
|
||||
server_oracle.compile_to_dot("server_event.dot", true);
|
||||
}
|
||||
});
|
||||
|
||||
oracle.compile_to_dot("actual_events.dot", false);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
// todo would be neat to just make this a subscriber of the tracing log, but there doesn't
|
||||
// seem to be a nice way for that API to do what we want.. so until then...
|
||||
|
||||
use rand::{thread_rng, Rng};
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Event {
|
||||
sender: String,
|
||||
intended_receiver: String,
|
||||
entangled_receiver: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Oracle {
|
||||
parties: Vec<String>,
|
||||
actual_events: Vec<Event>,
|
||||
}
|
||||
|
||||
impl Oracle {
|
||||
pub fn new() -> Oracle {
|
||||
Oracle {
|
||||
parties: vec![],
|
||||
actual_events: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_party(&mut self, party: String) {
|
||||
self.parties.push(party);
|
||||
}
|
||||
|
||||
pub fn add_event(&mut self, sender: String, intended_receiver: String, entangled_receiver: Option<String>) {
|
||||
self.actual_events.push(Event {
|
||||
sender,
|
||||
intended_receiver,
|
||||
entangled_receiver,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn compile_to_dot(&self, filename: &str, strict: bool) {
|
||||
let mut output = File::create(filename).unwrap();
|
||||
if strict {
|
||||
write!(output, "strict ");
|
||||
}
|
||||
write!(output, "digraph {{\n");
|
||||
write!(
|
||||
output,
|
||||
r#"K=2.5;
|
||||
repulsiveforce=0.1;
|
||||
overlap=true;
|
||||
splines = true;
|
||||
dpi=400;
|
||||
penwidth = 0.8;
|
||||
"#
|
||||
);
|
||||
|
||||
for party in self.parties.iter() {
|
||||
let r = hex::decode(party).unwrap()[0];
|
||||
let g = hex::decode(party).unwrap()[1];
|
||||
let b = hex::decode(party).unwrap()[2];
|
||||
writeln!(output, "\"{}\" [shape=point, color=\"#{:x}{:x}{:x}\"]", party, r, g, b);
|
||||
}
|
||||
|
||||
for event in self.actual_events.iter() {
|
||||
writeln!(output, "\"{}\" -> \"{}\" [arrowhead=none]", event.sender, event.intended_receiver);
|
||||
match &event.entangled_receiver {
|
||||
Some(entangled_receiver) => {
|
||||
writeln!(output, "\"{}\" -> \"{}\" [arrowhead=none,style=dashed]", event.sender, entangled_receiver);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
write!(output, "}}");
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
use crate::oracle::Oracle;
|
||||
use crate::server::SimulatedServer;
|
||||
use fuzzytags::{FuzzyPublicKey, FuzzySecretKey};
|
||||
use rand::distributions::Distribution;
|
||||
|
@ -22,24 +23,23 @@ impl SimulatedParties {
|
|||
SimulatedParties { gamma, parties }
|
||||
}
|
||||
|
||||
pub fn register_with_server<R>(&self, server: &mut SimulatedServer, rng: &mut R, min_p: usize, max_p: usize)
|
||||
pub fn register_with_server<R>(&self, server: &mut SimulatedServer, rng: &mut R, min_p: usize, max_p: usize, oracle: &mut Oracle)
|
||||
where
|
||||
R: Rng,
|
||||
{
|
||||
let span = span!(Level::TRACE, "register_with_server");
|
||||
let _enter = span.enter();
|
||||
for party in self.parties.iter() {
|
||||
let n = rng.gen_range(min_p..max_p);
|
||||
let span = span!(Level::TRACE, "{register}", party = party.public_key().id().as_str());
|
||||
let span = span!(Level::INFO, "register", party = party.public_key().id().as_str());
|
||||
let _enter = span.enter();
|
||||
let detection_key = party.extract(n);
|
||||
event!(Level::TRACE, "create detection key {detection_key}", detection_key = detection_key.id().as_str());
|
||||
event!(Level::TRACE, "register with server");
|
||||
server.register_key(&detection_key, &party.public_key());
|
||||
oracle.register_party(party.public_key().id());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sample_traffic<R, D>(&self, server: &mut SimulatedServer, rng: &mut R, distribution: D, probs_entangled: f64)
|
||||
pub fn sample_traffic<R, D>(&self, server: &mut SimulatedServer, rng: &mut R, distribution: D, probs_entangled: f64, oracle: &mut Oracle)
|
||||
where
|
||||
D: Distribution<f64>,
|
||||
R: Rng,
|
||||
|
@ -47,31 +47,40 @@ impl SimulatedParties {
|
|||
let span = span!(Level::INFO, "sample_traffic");
|
||||
let _enter = span.enter();
|
||||
let v = distribution.sample(rng).to_u16().unwrap();
|
||||
|
||||
let sender = rng.gen_range(0..self.parties.len());
|
||||
let sender_public_key = self.parties.get(sender).unwrap().public_key();
|
||||
|
||||
let receiver = rng.gen_range(0..self.parties.len());
|
||||
let receiver_public_key = self.parties.get(receiver).unwrap().public_key();
|
||||
|
||||
let entangle = rng.gen_bool(probs_entangled);
|
||||
if entangle {
|
||||
let receiver_2 = rng.gen_range(0..self.parties.len());
|
||||
let receiver_public_key_2 = self.parties.get(receiver_2).unwrap().public_key();
|
||||
event!(
|
||||
Level::INFO,
|
||||
"entangled send {party_1} {party_2}",
|
||||
party_1 = receiver_public_key.id().as_str(),
|
||||
party_2 = receiver_public_key_2.id().as_str()
|
||||
);
|
||||
if sender != receiver {
|
||||
let entangle = rng.gen_bool(probs_entangled);
|
||||
if entangle {
|
||||
let receiver_2 = rng.gen_range(0..self.parties.len());
|
||||
let receiver_public_key_2 = self.parties.get(receiver_2).unwrap().public_key();
|
||||
event!(
|
||||
Level::INFO,
|
||||
"entangled send {party_1} {party_2}",
|
||||
party_1 = receiver_public_key.id().as_str(),
|
||||
party_2 = receiver_public_key_2.id().as_str()
|
||||
);
|
||||
|
||||
for _i in 0..v {
|
||||
let tag = FuzzyPublicKey::generate_entangled_tag(vec![receiver_public_key.clone(), receiver_public_key_2.clone()], self.gamma);
|
||||
event!(Level::TRACE, "message sent to server {tag}", tag = tag.to_string());
|
||||
server.add_message(tag);
|
||||
}
|
||||
} else {
|
||||
event!(Level::INFO, "regular send {party}", party = receiver_public_key.id().as_str());
|
||||
for _i in 0..v {
|
||||
let tag = receiver_public_key.generate_tag();
|
||||
event!(Level::INFO, "message sent server {tag}", tag = tag.to_string());
|
||||
server.add_message(tag);
|
||||
for _i in 0..v {
|
||||
let tag = FuzzyPublicKey::generate_entangled_tag(vec![receiver_public_key.clone(), receiver_public_key_2.clone()], self.gamma);
|
||||
event!(Level::TRACE, "message sent to server {tag}", tag = tag.to_string());
|
||||
server.add_message(tag, &sender_public_key);
|
||||
}
|
||||
|
||||
oracle.add_event(sender_public_key.id().clone(), receiver_public_key.id(), Some(receiver_public_key_2.id()));
|
||||
} else {
|
||||
event!(Level::INFO, "regular send {party}", party = receiver_public_key.id().as_str());
|
||||
for _i in 0..v {
|
||||
let tag = receiver_public_key.generate_tag();
|
||||
event!(Level::INFO, "message sent server {tag}", tag = tag.to_string());
|
||||
server.add_message(tag, &sender_public_key);
|
||||
}
|
||||
oracle.add_event(sender_public_key.id().clone(), receiver_public_key.id(), None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::oracle::Oracle;
|
||||
use fuzzytags::{FuzzyDetectionKey, FuzzyPublicKey, FuzzyTag};
|
||||
use hashbrown::HashMap;
|
||||
use tracing::event;
|
||||
|
@ -6,9 +7,10 @@ use tracing::Level;
|
|||
|
||||
pub struct SimulatedServer {
|
||||
keybase: Vec<(FuzzyDetectionKey, FuzzyPublicKey)>,
|
||||
messages: Vec<FuzzyTag>,
|
||||
messages: Vec<(FuzzyTag, FuzzyPublicKey)>,
|
||||
tags_to_keys_cache: HashMap<String, Vec<FuzzyPublicKey>>,
|
||||
keys_to_tags_cache: HashMap<String, Vec<FuzzyTag>>,
|
||||
oracle: Oracle,
|
||||
}
|
||||
|
||||
pub struct RoundStatistics {
|
||||
|
@ -34,35 +36,37 @@ impl SimulatedServer {
|
|||
messages: vec![],
|
||||
tags_to_keys_cache: HashMap::new(),
|
||||
keys_to_tags_cache: HashMap::new(),
|
||||
oracle: Oracle::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_key(&mut self, detection_key: &FuzzyDetectionKey, public_key: &FuzzyPublicKey) {
|
||||
self.keybase.push((detection_key.clone(), public_key.clone()));
|
||||
self.keys_to_tags_cache.insert(public_key.id(), vec![]);
|
||||
self.oracle.register_party(public_key.id());
|
||||
}
|
||||
|
||||
pub fn add_message(&mut self, tag: FuzzyTag) {
|
||||
self.messages.push(tag.clone());
|
||||
pub fn add_message(&mut self, tag: FuzzyTag, sender_public_key: &FuzzyPublicKey) {
|
||||
self.messages.push((tag.clone(), sender_public_key.clone()));
|
||||
self.tags_to_keys_cache.insert(tag.to_string(), vec![]);
|
||||
}
|
||||
|
||||
pub fn test_messages(&mut self) {
|
||||
for message in self.messages.iter() {
|
||||
for (message, sender) in self.messages.iter() {
|
||||
for (detection_key, public_key) in self.keybase.iter() {
|
||||
let span = span!(Level::TRACE, "{detection}", party = public_key.id().as_str());
|
||||
let _enter = span.enter();
|
||||
if detection_key.test_tag(message) {
|
||||
event!(Level::TRACE, "Matched detection key for {key} to tag {tag} ", key = public_key.id(), tag = message.to_string());
|
||||
self.tags_to_keys_cache.get_mut(message.to_string().as_str()).unwrap().push((*public_key).clone());
|
||||
|
||||
self.keys_to_tags_cache.get_mut(public_key.id().as_str()).unwrap().push((*message).clone());
|
||||
self.oracle.add_event(sender.id(), public_key.id(), None);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn statistics(&self) -> (RoundStatistics, HashMap<String, PartyStatistics>) {
|
||||
pub fn statistics(&self) -> (Oracle, RoundStatistics, HashMap<String, PartyStatistics>) {
|
||||
let mut party_stats = HashMap::new();
|
||||
let round_stats = RoundStatistics {
|
||||
num_messages: self.messages.len(),
|
||||
|
@ -98,6 +102,6 @@ impl SimulatedServer {
|
|||
party_stats.insert(pub_key.id(), p_stats);
|
||||
}
|
||||
|
||||
(round_stats, party_stats)
|
||||
(self.oracle.clone(), round_stats, party_stats)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue