use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use std::collections::{HashMap, HashSet};
use std::fmt;
use std::sync::Arc;
use tokio::sync::Notify;
use super::{ShardError, MAX_PAYLOAD_SIZE};
use crate::common::ProtocolSessionId;
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct Msg<Id: ProtocolSessionId> {
pub sender_id: usize, pub session_id: Id, pub round_id: usize, pub payload: Vec<u8>, pub metadata: Vec<u8>, pub msg_type: GenericMsgType, }
fn hash_message(message: &[u8]) -> Vec<u8> {
Sha256::digest(message).to_vec()
}
impl<Id: ProtocolSessionId> Msg<Id> {
pub fn new(
sender_id: usize,
session_id: Id,
round_id: usize,
payload: Vec<u8>,
metadata: Vec<u8>,
msg_type: GenericMsgType,
) -> Self {
Msg {
sender_id,
session_id,
round_id,
payload,
metadata,
msg_type,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum GenericMsgType {
Bracha(MsgType),
Avid(MsgTypeAvid),
ABA(MsgTypeAba),
Acs(MsgTypeAcs),
}
impl GenericMsgType {
pub fn is_dealer_message(&self) -> bool {
match self {
GenericMsgType::Bracha(MsgType::Init) => true,
GenericMsgType::Bracha(_) => false,
GenericMsgType::Avid(MsgTypeAvid::Send) => true,
GenericMsgType::Avid(_) => false,
GenericMsgType::ABA(_) => false,
GenericMsgType::Acs(_) => false,
}
}
}
impl fmt::Display for GenericMsgType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
GenericMsgType::Bracha(ref msg) => write!(f, "Bracha({})", msg),
GenericMsgType::Avid(ref msg) => write!(f, "Avid({})", msg),
GenericMsgType::ABA(ref msg) => write!(f, "ABA({})", msg),
GenericMsgType::Acs(ref msg) => write!(f, "ACS({})", msg),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum MsgType {
Init,
Echo,
Ready,
Unknown(String),
}
impl fmt::Display for MsgType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
MsgType::Init => write!(f, "Init"),
MsgType::Echo => write!(f, "Echo"),
MsgType::Ready => write!(f, "Ready"),
MsgType::Unknown(ref s) => write!(f, "Unknown({})", s),
}
}
}
#[derive(Default)]
pub struct BrachaStore {
pub echo_senders: HashMap<usize, bool>, pub ready_senders: HashMap<usize, bool>, pub echo_count: HashMap<Vec<u8>, usize>, pub ready_count: HashMap<Vec<u8>, usize>, pub ended: bool, pub echo: bool, pub ready: bool, pub output: Vec<u8>, }
impl BrachaStore {
pub fn new() -> Self {
BrachaStore {
echo_senders: HashMap::new(),
ready_senders: HashMap::new(),
echo_count: HashMap::new(),
ready_count: HashMap::new(),
ended: false,
echo: false,
ready: false,
output: Vec::new(),
}
}
pub fn has_echo(&self, sender_id: usize) -> bool {
self.echo_senders.get(&sender_id).copied().unwrap_or(false)
}
pub fn has_ready(&self, sender_id: usize) -> bool {
self.ready_senders.get(&sender_id).copied().unwrap_or(false)
}
pub fn set_echo_sent(&mut self, node_id: usize) {
self.echo_senders.insert(node_id, true);
}
pub fn set_ready_sent(&mut self, node_id: usize) {
self.ready_senders.insert(node_id, true);
}
pub fn increment_echo(&mut self, message: &[u8]) {
let hash = hash_message(message);
*self.echo_count.entry(hash).or_insert(0) += 1;
}
pub fn increment_ready(&mut self, message: &[u8]) {
let hash = hash_message(message);
*self.ready_count.entry(hash).or_insert(0) += 1;
}
pub fn get_echo_count(&self, message: &[u8]) -> usize {
let hash = hash_message(message);
*self.echo_count.get(&hash).unwrap_or(&0)
}
pub fn get_ready_count(&self, message: &[u8]) -> usize {
let hash = hash_message(message);
*self.ready_count.get(&hash).unwrap_or(&0)
}
pub fn mark_ended(&mut self) {
self.ended = true;
}
pub fn mark_echo(&mut self) {
self.echo = true;
}
pub fn mark_ready(&mut self) {
self.ready = true;
}
pub fn set_output(&mut self, value: Vec<u8>) {
self.output = value;
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum MsgTypeAvid {
Send,
Echo,
Ready,
Unknown(String),
}
impl fmt::Display for MsgTypeAvid {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
MsgTypeAvid::Send => write!(f, "Send"),
MsgTypeAvid::Echo => write!(f, "Echo"),
MsgTypeAvid::Ready => write!(f, "Ready"),
MsgTypeAvid::Unknown(ref s) => write!(f, "Unknown({})", s),
}
}
}
#[derive(Default)]
pub struct AvidStore {
pub shards: HashMap<Vec<u8>, HashMap<usize, Vec<u8>>>, pub fingerprint: HashMap<Vec<u8>, HashMap<usize, Vec<u8>>>, pub echo_senders: HashMap<usize, bool>, pub ready_senders: HashMap<usize, bool>, pub echo_count: HashMap<Vec<u8>, usize>, pub ready_count: HashMap<Vec<u8>, usize>, pub ended: bool, pub echo: bool, pub output: Vec<u8>, }
impl AvidStore {
pub fn new() -> Self {
AvidStore {
shards: HashMap::new(),
fingerprint: HashMap::new(),
echo_senders: HashMap::new(),
ready_senders: HashMap::new(),
echo_count: HashMap::new(),
ready_count: HashMap::new(),
ended: false,
echo: false,
output: Vec::new(),
}
}
pub fn has_echo(&self, sender_id: usize) -> bool {
self.echo_senders.get(&sender_id).copied().unwrap_or(false)
}
pub fn has_ready(&self, sender_id: usize) -> bool {
self.ready_senders.get(&sender_id).copied().unwrap_or(false)
}
pub fn set_echo_sent(&mut self, node_id: usize) {
self.echo_senders.insert(node_id, true);
}
pub fn set_ready_sent(&mut self, node_id: usize) {
self.ready_senders.insert(node_id, true);
}
pub fn increment_echo(&mut self, root: &[u8]) {
*self.echo_count.entry(root.to_vec()).or_insert(0) += 1;
}
pub fn increment_ready(&mut self, root: &[u8]) {
*self.ready_count.entry(root.to_vec()).or_insert(0) += 1;
}
pub fn get_echo_count(&self, root: &[u8]) -> usize {
*self.echo_count.get(root).unwrap_or(&0)
}
pub fn get_ready_count(&self, root: &[u8]) -> usize {
*self.ready_count.get(root).unwrap_or(&0)
}
pub fn mark_echo(&mut self) {
self.echo = true;
}
pub fn mark_ended(&mut self) {
self.ended = true;
}
pub fn set_output(&mut self, value: Vec<u8>) {
self.output = value;
}
pub fn insert_shard(
&mut self,
root: Vec<u8>,
sender_id: usize,
shard: Vec<u8>,
data_shards: usize,
) -> Result<(), ShardError> {
let max_shard_size = (MAX_PAYLOAD_SIZE + 8 + data_shards - 1) / data_shards;
if shard.len() > max_shard_size {
return Err(ShardError::Config(format!(
"Shard from {} exceeds maximum allowed size ({})",
sender_id,
shard.len()
)));
}
self.shards
.entry(root)
.or_default()
.insert(sender_id, shard);
Ok(())
}
pub fn insert_fingerprint(&mut self, root: Vec<u8>, sender_id: usize, proof: Vec<u8>) {
self.fingerprint
.entry(root)
.or_default()
.insert(sender_id, proof);
}
pub fn get_shards_for_root(&self, root: &Vec<u8>) -> HashMap<usize, Vec<u8>> {
self.shards.get(root).cloned().unwrap_or_else(HashMap::new)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum MsgTypeAba {
Est,
Aux,
Key,
Coin,
Unknown(String),
}
impl fmt::Display for MsgTypeAba {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
MsgTypeAba::Est => write!(f, "Est"),
MsgTypeAba::Aux => write!(f, "Aux"),
MsgTypeAba::Key => write!(f, "Key"),
MsgTypeAba::Coin => write!(f, "Coin"),
MsgTypeAba::Unknown(ref s) => write!(f, "Unknown({})", s),
}
}
}
#[derive(Default)]
pub struct AbaStore {
pub est_senders: HashMap<usize, HashMap<usize, [bool; 2]>>,
pub aux_senders: HashMap<usize, HashMap<usize, [bool; 2]>>,
pub est_count: HashMap<usize, [usize; 2]>, pub est: HashMap<usize, [bool; 2]>, pub aux: HashMap<usize, [bool; 2]>, pub values: HashMap<usize, HashMap<usize, HashSet<bool>>>,
pub bin_values: HashMap<usize, HashSet<bool>>, pub ended: bool, pub output: bool, pub notify: Arc<Notify>,
}
impl AbaStore {
pub fn mark_est(&mut self, round: usize, value: bool) {
let est = self.est.entry(round).or_insert([false; 2]);
est[value as usize] = true;
}
pub fn get_est(&self, round: usize, value: bool) -> bool {
self.est
.get(&round)
.map(|arr| arr[value as usize])
.unwrap_or(false)
}
pub fn mark_aux(&mut self, round: usize, value: bool) {
let aux_arr = self.aux.entry(round).or_insert([false; 2]);
aux_arr[value as usize] = true;
}
pub fn get_aux(&self, round: usize, value: bool) -> bool {
self.aux
.get(&round)
.map(|arr| arr[value as usize])
.unwrap_or(false)
}
pub fn has_sent_est(&self, round: usize, sender: usize, value: bool) -> bool {
self.est_senders
.get(&round)
.and_then(|senders| senders.get(&sender))
.map(|arr| arr[value as usize])
.unwrap_or(false)
}
pub fn set_est_sent(&mut self, round: usize, sender: usize, value: bool) {
self.est_senders
.entry(round)
.or_default()
.entry(sender)
.or_insert([false; 2])[value as usize] = true;
}
pub fn increment_est(&mut self, round: usize, value: bool) {
let counts = self.est_count.entry(round).or_insert([0, 0]);
if value {
counts[1] += 1;
} else {
counts[0] += 1;
}
}
pub fn get_est_count(&self, round: usize) -> [usize; 2] {
self.est_count.get(&round).copied().unwrap_or([0, 0])
}
pub fn insert_bin_value(&mut self, round: usize, value: bool) {
self.bin_values
.entry(round)
.or_insert_with(HashSet::new)
.insert(value);
}
pub fn get_bin_values(&self, round: usize) -> HashSet<bool> {
self.bin_values.get(&round).cloned().unwrap_or_default()
}
pub fn has_sent_aux(&self, round: usize, sender: usize, value: bool) -> bool {
self.aux_senders
.get(&round)
.and_then(|senders| senders.get(&sender))
.map(|arr| arr[value as usize])
.unwrap_or(false)
}
pub fn set_aux_sent(&mut self, round: usize, sender: usize, value: bool) {
self.aux_senders
.entry(round)
.or_default()
.entry(sender)
.or_insert([false; 2])[value as usize] = true;
}
pub fn insert_values(&mut self, round: usize, sender: usize, value: bool) {
self.values
.entry(round)
.or_insert_with(HashMap::new)
.entry(sender)
.or_insert_with(HashSet::new)
.insert(value);
}
pub fn get_sender_count(&self, round: usize) -> usize {
self.values
.get(&round)
.map(|sender_map| sender_map.len())
.unwrap_or(0)
}
pub fn get_all_values(&self, round: usize) -> HashSet<bool> {
self.values
.get(&round)
.map(|sender_map| {
sender_map
.values()
.flat_map(|value_set| value_set.iter().copied())
.collect()
})
.unwrap_or_default()
}
pub fn mark_ended(&mut self) {
self.ended = true;
self.notify.notify_waiters();
}
pub fn set_output(&mut self, value: bool) {
self.output = value;
}
}
#[derive(Default)]
pub struct CoinStore {
pub sign_senders: HashMap<usize, HashMap<usize, bool>>, pub sign_count: HashMap<usize, usize>, pub sign_shares: HashMap<usize, HashMap<usize, Vec<u8>>>, pub coins: HashMap<usize, bool>, pub start: HashMap<usize, bool>, pub notifiers: HashMap<usize, Arc<Notify>>, }
impl CoinStore {
pub fn has_sent_sign(&self, round: usize, sender: usize) -> bool {
self.sign_senders
.get(&round)
.and_then(|senders| senders.get(&sender))
.copied()
.unwrap_or(false)
}
pub fn increment_sign(&mut self, round: usize) {
*self.sign_count.entry(round).or_insert(0) += 1;
}
pub fn set_sign_sent(&mut self, round: usize, sender: usize) {
self.sign_senders
.entry(round)
.or_default()
.insert(sender, true);
}
pub fn get_sign_count(&self, round: usize) -> usize {
self.sign_count.get(&round).copied().unwrap_or(0)
}
pub fn insert_share(&mut self, round_id: usize, sender_id: usize, share: Vec<u8>) {
self.sign_shares
.entry(round_id)
.or_insert_with(HashMap::new)
.insert(sender_id, share);
}
pub fn get_shares_map(&self, round_id: usize) -> Option<&HashMap<usize, Vec<u8>>> {
self.sign_shares.get(&round_id)
}
pub fn set_coin(&mut self, round_id: usize, value: bool) {
self.coins.insert(round_id, value);
if let Some(notify) = self.notifiers.remove(&round_id) {
notify.notify_waiters(); }
}
pub fn coin(&self, round: usize) -> Option<bool> {
self.coins.get(&round).copied()
}
pub fn set_start(&mut self, round_id: usize) {
self.start.insert(round_id, true);
}
pub fn get_start(&self, round: usize) -> bool {
*self.start.get(&round).unwrap_or(&false)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum MsgTypeAcs {
Acs,
Unknown(String),
}
impl fmt::Display for MsgTypeAcs {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
MsgTypeAcs::Acs => write!(f, "Acs"),
MsgTypeAcs::Unknown(ref s) => write!(f, "Unknown({})", s),
}
}
}
#[derive(Default, Clone)]
pub struct AcsStore {
pub aba_input: HashMap<u128, bool>, pub aba_output: HashMap<u128, bool>, pub rbc_output: HashMap<u128, Vec<u8>>, pub ended: bool,
pub commonsubset: Vec<Vec<u8>>,
}
impl AcsStore {
pub fn has_aba_input(&self, session_id: u128) -> bool {
self.aba_input.contains_key(&session_id)
}
pub fn set_aba_input(&mut self, session_id: u128, value: bool) {
self.aba_input.insert(session_id, value);
}
pub fn set_aba_output(&mut self, session_id: u128, value: bool) {
self.aba_output.insert(session_id, value);
}
pub fn get_aba_output_one_count(&mut self) -> usize {
self.aba_output.iter().filter(|&(_, &val)| val).count()
}
pub fn has_rbc_output(&self, session_id: u128) -> bool {
self.rbc_output.contains_key(&session_id)
}
pub fn set_rbc_output(&mut self, session_id: u128, output: Vec<u8>) {
self.rbc_output.insert(session_id, output);
}
pub fn get_rbc_output(&mut self, session_id: u128) -> Option<&Vec<u8>> {
self.rbc_output.get(&session_id)
}
pub fn set_acs(&mut self, set: Vec<Vec<u8>>) {
self.commonsubset = set;
}
pub fn mark_ended(&mut self) {
self.ended = true;
}
}