Skip to content

Commit

Permalink
Merge pull request #11 from crocs-muni/devel
Browse files Browse the repository at this point in the history
Sync with client
  • Loading branch information
dufkan authored Sep 27, 2022
2 parents c7c46cf + e7f40b7 commit 8a8398d
Show file tree
Hide file tree
Showing 9 changed files with 307 additions and 61 deletions.
8 changes: 6 additions & 2 deletions proto/mpc.proto
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ service MPC {
rpc GetTask(TaskRequest) returns (Task);
rpc UpdateTask(TaskUpdate) returns (Resp);
rpc DecideTask(TaskDecision) returns (Resp);
rpc AcknowledgeTask(TaskAcknowledgement) returns (Resp);
rpc GetTasks(TasksRequest) returns (Tasks);
rpc GetGroups(GroupsRequest) returns (Groups);
rpc GetDevices(DevicesRequest) returns (Devices);
Expand Down Expand Up @@ -123,13 +124,16 @@ message TaskDecision {
bool accept = 3;
};

message TaskAcknowledgement {
bytes task_id = 1;
bytes device_id = 2;
};

message LogRequest {
string message = 1;
optional bytes device_id = 2;
};

message TaskAcknowledgement {};

message GG18KeyGenInit {
uint32 index = 1;
uint32 parties = 2;
Expand Down
59 changes: 50 additions & 9 deletions src/communicator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ pub struct Communicator {
/// Ordered list of active devices (participating in the protocol)
active_devices: Option<Vec<Vec<u8>>>,
/// A mapping of device identifiers to their Task decision
devices: HashMap<Vec<u8>, Option<bool>>,
decisions: HashMap<Vec<u8>, Option<bool>>,
/// A mapping of device identifiers to their Task acknowledgement
acknowledgements: HashMap<Vec<u8>, bool>,
/// Incoming messages
input: Vec<Vec<Option<Vec<u8>>>>,
/// Outgoing messages
Expand All @@ -30,14 +32,19 @@ impl Communicator {
assert!(threshold <= devices.len() as u32);
// TODO uncomment once is_sorted is stabilized
// assert!(devices.is_sorted());

let mut communicator = Communicator {
threshold,
device_list: devices.iter().map(Device::clone).collect(),
active_devices: None,
devices: devices
decisions: devices
.iter()
.map(|x| (x.identifier().to_vec(), None))
.collect(),
acknowledgements: devices
.iter()
.map(|x| (x.identifier().to_vec(), false))
.collect(),
input: Vec::new(),
output: Vec::new(),
};
Expand Down Expand Up @@ -153,7 +160,7 @@ impl Communicator {
self.active_devices = Some(
self.device_list
.iter()
.filter(|device| self.devices.get(device.identifier()) == Some(&Some(true)))
.filter(|device| self.decisions.get(device.identifier()) == Some(&Some(true)))
.take(self.threshold as usize)
.map(|device| device.identifier().to_vec())
.collect(),
Expand All @@ -166,40 +173,54 @@ impl Communicator {
self.active_devices.clone()
}

/// Save decision by the given device; return if successful
/// Save decision by the given device; return true if successful
pub fn decide(&mut self, device: &[u8], decision: bool) -> bool {
if !self.devices.contains_key(device) || self.devices[device].is_some() {
if !self.decisions.contains_key(device) || self.decisions[device].is_some() {
return false;
}
self.devices.insert(device.to_vec(), Some(decision));
self.decisions.insert(device.to_vec(), Some(decision));
true
}

/// Get the number of Task accepts
pub fn accept_count(&self) -> u32 {
self.devices
self.decisions
.iter()
.map(|x| if x.1.unwrap_or(false) { 1 } else { 0 })
.sum()
}

/// Get the number of Task rejects
pub fn reject_count(&self) -> u32 {
self.devices
self.decisions
.iter()
.map(|x| if x.1.unwrap_or(true) { 0 } else { 1 })
.sum()
}

/// Check whether a device submitted its decision
pub fn device_decided(&self, device: &[u8]) -> bool {
if let Some(Some(_)) = self.devices.get(device) {
if let Some(Some(_)) = self.decisions.get(device) {
true
} else {
false
}
}

/// Save acknowledgement by the given device; return true if successful
pub fn acknowledge(&mut self, device: &[u8]) -> bool {
if !self.acknowledgements.contains_key(device) || self.acknowledgements[device] {
return false;
}
self.acknowledgements.insert(device.to_vec(), true);
true
}

/// Check whether a device acknowledged task output
pub fn device_acknowledged(&self, device: &[u8]) -> bool {
*self.acknowledgements.get(device).unwrap_or(&false)
}

/// Get indices of active devices in the corresponding group
///
/// Indices returned by this command correspond to key share indices of `active_devices`.
Expand Down Expand Up @@ -343,6 +364,11 @@ mod tests {
);
}
assert_eq!(communicator.round_received(), false);
for device in devices {
assert_eq!(communicator.device_acknowledged(device.identifier()), false);
assert_eq!(communicator.acknowledge(device.identifier()), true);
assert_eq!(communicator.device_acknowledged(device.identifier()), true);
}
}

#[test]
Expand Down Expand Up @@ -432,6 +458,21 @@ mod tests {
);
}

#[test]
fn unknown_device_acknowledgement() {
let devices = prepare_devices(3);
let mut communicator = Communicator::new(&devices[..2], 2);
assert_eq!(communicator.acknowledge(devices[2].identifier()), false);
}

#[test]
fn repeated_device_acknowledgement() {
let devices = prepare_devices(2);
let mut communicator = Communicator::new(&devices, 2);
assert_eq!(communicator.acknowledge(devices[0].identifier()), true);
assert_eq!(communicator.acknowledge(devices[0].identifier()), false);
}

fn prepare_devices(n: usize) -> Vec<Device> {
assert!(n < u8::MAX as usize);
(0..n)
Expand Down
49 changes: 47 additions & 2 deletions src/device.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
use std::cmp::Ordering;
use std::time::{SystemTime, UNIX_EPOCH};

#[derive(Clone, Eq)]
#[derive(Clone, Eq, Debug)]
pub struct Device {
identifier: Vec<u8>,
name: String,
last_active: u64,
// protocol: ProtocolType
}

impl Device {
pub fn new(identifier: Vec<u8>, name: String) -> Self {
assert!(identifier.len() > 0);
Device {
identifier,
name,
Expand Down Expand Up @@ -63,3 +63,48 @@ impl From<&Device> for crate::proto::Device {
}
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
#[should_panic]
fn empty_identifier() {
Device::new(vec![], String::from("Sample Device"));
}

#[test]
fn compare_devices() {
let d0 = Device::new(vec![0x00], String::from("d0"));
let d1 = Device::new(vec![0x01], String::from("d1"));
let d2 = Device::new(vec![0x02], String::from("d2"));
let d0_duplicate = Device::new(vec![0x00], String::from("d0_duplicate"));
assert!(d0 < d1);
assert!(d1 < d2);
assert!(d0 < d2);
assert!(d0 == d0_duplicate);
}

#[test]
fn protobuf_device() {
let device = Device::new(vec![0x01, 0x02, 0x03, 0x04], String::from("Sample Device"));
let protobuf = crate::proto::Device::from(&device);
assert_eq!(protobuf.identifier, device.identifier());
assert_eq!(protobuf.name, device.name());
assert_eq!(protobuf.last_active, device.last_active());
}

#[test]
fn sample_device() {
let identifier = vec![0x01, 0x02, 0x03, 0x04];
let name = String::from("Sample Device");
let mut device = Device::new(identifier.clone(), name.clone());
assert_eq!(device.identifier(), &identifier);
assert_eq!(device.name(), &name);
let previous_active = device.last_active();
let activated = device.activated();
assert!(previous_active <= device.last_active());
assert_eq!(device.last_active(), activated);
}
}
Loading

0 comments on commit 8a8398d

Please sign in to comment.