#ifndef _MAC_Check #define _MAC_Check /* Class for storing MAC Check data and doing the Check */ #include #include using namespace std; #include "Protocols/Share.h" #include "Networking/Player.h" #include "Protocols/MAC_Check_Base.h" #include "Tools/time-func.h" #include "Tools/Coordinator.h" #include "Processor/OnlineOptions.h" /* The MAX number of things we will partially open before running * a MAC Check * * Keep this at much less than 1MB of data to be able to cope with * multi-threaded players * */ #define POPEN_MAX 1000000 /** * Sum and broadcast values via a tree of players */ template class TreeSum { static const char* mc_timer_names[]; void start(vector& values, const Player& P); void finish(vector& values, const Player& P); void add_openings(vector& values, const Player& P, int sum_players, int last_sum_players, int send_player); virtual void post_add_process(vector&) {} protected: int base_player; int opening_sum; int max_broadcast; octetStream os; vector lengths; void ReceiveValues(vector& values, const Player& P, int sender); virtual void AddToValues(vector& values) { (void)values; } public: vector oss; vector timers; vector player_timers; TreeSum(int opening_sum = OnlineOptions::singleton.opening_sum, int max_broadcast = OnlineOptions::singleton.max_broadcast, int base_player = 0); virtual ~TreeSum(); void run(vector& values, const Player& P); T run(const T& value, const Player& P); octetStream& get_buffer() { return os; } size_t report_size(ReportType type); }; template class Tree_MAC_Check : public TreeSum, public MAC_Check_Base { typedef typename U::open_type T; template friend class Tree_MAC_Check; protected: static Coordinator* coordinator; /* POpen Data */ int popen_cnt; vector macs; vector vals; void AddToValues(vector& values); void CheckIfNeeded(const Player& P); int WaitingForCheck() { return max(macs.size(), vals.size()); } public: static void setup(Player& P); static void teardown(); Tree_MAC_Check(const typename U::mac_key_type::Scalar& ai, int opening_sum = 10, int max_broadcast = 10, int send_player = 0); virtual ~Tree_MAC_Check(); virtual void init_open(const Player& P, int n = 0); virtual void prepare_open(const U& secret, int = -1); virtual void exchange(const Player& P); virtual void AddToCheck(const U& share, const T& value, const Player& P); virtual void Check(const Player& P) = 0; }; template Coordinator* Tree_MAC_Check::coordinator = 0; /** * SPDZ opening protocol with MAC check (indirect communication) */ template class MAC_Check_ : public virtual Tree_MAC_Check { public: MAC_Check_(const typename U::mac_key_type::Scalar& ai, int opening_sum = 10, int max_broadcast = 10, int send_player = 0); virtual ~MAC_Check_() {} virtual void Check(const Player& P); }; template using MAC_Check = MAC_Check_>; template class Spdz2kShare; template class Spdz2kPrep; template class MascotPrep; /** * SPDZ2k opening protocol with MAC check */ template class MAC_Check_Z2k : public virtual Tree_MAC_Check { protected: Preprocessing* prep; W get_random_element(); public: vector random_elements; MAC_Check_Z2k(const T& ai, int opening_sum=10, int max_broadcast=10, int send_player=0); MAC_Check_Z2k(const T& ai, Names& Nms, int thread_num); void prepare_open(const W& secret, int = -1); void prepare_open_no_mask(const W& secret); virtual void Check(const Player& P); void set_random_element(const W& random_element); void set_prep(Preprocessing& prep); virtual ~MAC_Check_Z2k() {}; }; template using MAC_Check_Z2k_ = MAC_Check_Z2k; /** * SPDZ opening protocol with MAC check (pairwise communication) */ template class Direct_MAC_Check: public virtual MAC_Check_ { typedef MAC_Check_ super; typedef typename T::open_type open_type; int open_counter; vector oss; protected: void pre_exchange(const Player& P); public: // legacy interface Direct_MAC_Check(const typename T::mac_key_type::Scalar& ai, Names& Nms, int thread_num); Direct_MAC_Check(const typename T::mac_key_type::Scalar& ai); ~Direct_MAC_Check(); void init_open(const Player& P, int n = 0); void prepare_open(const T& secret, int = -1); virtual void exchange(const Player& P); }; template class Direct_MAC_Check_Z2k: virtual public MAC_Check_Z2k_, virtual public Direct_MAC_Check { public: Direct_MAC_Check_Z2k(const typename T::mac_key_type& ai) : Tree_MAC_Check(ai), MAC_Check_Z2k_(ai), MAC_Check_(ai), Direct_MAC_Check(ai) { } void prepare_open(const T& secret, int = -1) { MAC_Check_Z2k_::prepare_open(secret); } void exchange(const Player& P) { Direct_MAC_Check::exchange(P); } void Check(const Player& P) { MAC_Check_Z2k_::Check(P); } }; enum mc_timer { SEND, RECV_ADD, BCAST, RECV_SUM, SEED, COMMIT, WAIT_SUMMER, RECV, SUM, SELECT, MAX_TIMER }; template TreeSum::TreeSum(int opening_sum, int max_broadcast, int base_player) : base_player(base_player), opening_sum(opening_sum), max_broadcast(max_broadcast) { timers.resize(MAX_TIMER); } template TreeSum::~TreeSum() { #ifdef TREESUM_TIMINGS for (unsigned int i = 0; i < timers.size(); i++) if (timers[i].elapsed() > 0) cerr << T::type_string() << " " << mc_timer_names[i] << ": " << timers[i].elapsed() << endl; for (unsigned int i = 0; i < player_timers.size(); i++) if (player_timers[i].elapsed() > 0) cerr << T::type_string() << " waiting for " << i << ": " << player_timers[i].elapsed() << endl; #endif } template void TreeSum::run(vector& values, const Player& P) { if (not values.empty()) { start(values, P); finish(values, P); } } template T TreeSum::run(const T& value, const Player& P) { vector values = {value}; run(values, P); return values[0]; } template size_t TreeSum::report_size(ReportType type) { if (type == CAPACITY) return os.get_max_length(); else return os.get_length(); } template void TreeSum::add_openings(vector& values, const Player& P, int sum_players, int last_sum_players, int send_player) { auto& MC = *this; MC.player_timers.resize(P.num_players()); vector& oss = MC.oss; oss.resize(P.num_players()); vector senders; senders.reserve(P.num_players()); bool use_lengths = values.size() == lengths.size(); for (int relative_sender = positive_modulo(P.my_num() - send_player, P.num_players()) + sum_players; relative_sender < last_sum_players; relative_sender += sum_players) { int sender = positive_modulo(send_player + relative_sender, P.num_players()); senders.push_back(sender); } for (int j = 0; j < (int)senders.size(); j++) P.request_receive(senders[j], oss[j]); for (int j = 0; j < (int)senders.size(); j++) { int sender = senders[j]; MC.player_timers[sender].start(); P.wait_receive(sender, oss[j]); MC.player_timers[sender].stop(); MC.timers[SUM].start(); T tmp = values.at(0); for (unsigned int i=0; i void TreeSum::start(vector& values, const Player& P) { CODE_LOCATION if (opening_sum < 2) opening_sum = P.num_players(); if (max_broadcast < 2) max_broadcast = P.num_players(); os.reset_write_head(); int sum_players = P.num_players(); int my_relative_num = positive_modulo(P.my_num() - base_player, P.num_players()); bool use_lengths = values.size() == lengths.size(); while (true) { // summing phase int last_sum_players = sum_players; sum_players = (sum_players - 2 + opening_sum) / opening_sum; if (sum_players == 0) break; if (my_relative_num >= sum_players && my_relative_num < last_sum_players) { // send to the player up the tree for (unsigned int i=0; i void TreeSum::finish(vector& values, const Player& P) { int my_relative_num = positive_modulo(P.my_num() - base_player, P.num_players()); if (my_relative_num * max_broadcast >= P.num_players()) { // receiving at the leafs int sender = (base_player + my_relative_num / max_broadcast) % P.num_players(); ReceiveValues(values, P, sender); } } template void TreeSum::ReceiveValues(vector& values, const Player& P, int sender) { timers[RECV_SUM].start(); P.receive_player(sender, os); timers[RECV_SUM].stop(); bool use_lengths = values.size() == lengths.size(); for (unsigned int i = 0; i < values.size(); i++) values[i].unpack(os, use_lengths ? lengths[i] : -1); AddToValues(values); } #endif