#ifndef _MAC_Check #define _MAC_Check /* Class for storing MAC Check data and doing the Check */ #include #include using namespace std; #include "Math/Share.h" #include "Networking/Player.h" #include "Networking/ServerSocket.h" #include "Auth/Summer.h" #include "Tools/time-func.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 template class TreeSum { protected: int base_player; int opening_sum; int max_broadcast; octetStream os; void ReceiveValues(vector& values, const Player& P, int sender); virtual void AddToValues(vector& values) { (void)values; } virtual void GetValues(vector& values) { (void)values; } public: vector oss; vector timers; vector player_timers; TreeSum(int opening_sum = 10, int max_broadcast = 10, int base_player = 0); virtual ~TreeSum(); void start(vector& values, const Player& P); void finish(vector& values, const Player& P); void run(vector& values, const Player& P); octetStream& get_buffer() { return os; } size_t report_size(ReportType type); }; template class MAC_Check_Base { protected: /* MAC Share */ typename T::clear alphai; public: int values_opened; MAC_Check_Base() : values_opened(0) {} virtual ~MAC_Check_Base() {} virtual void Check(const Player& P) { (void)P; } int number() const { return values_opened; } const typename T::clear& get_alphai() const { return alphai; } virtual void POpen_Begin(vector& values,const vector& S,const Player& P) = 0; virtual void POpen_End(vector& values,const vector& S,const Player& P) = 0; void POpen(vector& values,const vector& S,const Player& P); typename T::clear POpen(const T& secret, const Player& P); }; template class MAC_Check : public TreeSum, public MAC_Check_Base> { protected: /* POpen Data */ int popen_cnt; vector macs; vector vals; void AddToMacs(const vector< Share >& shares); void AddToValues(vector& values); void GetValues(vector& values); void CheckIfNeeded(const Player& P); int WaitingForCheck() { return max(macs.size(), vals.size()); } public: MAC_Check(const T& ai, int opening_sum=10, int max_broadcast=10, int send_player=0); virtual ~MAC_Check(); /* Run protocols to partially open data and check the MACs are * all OK. * - Implicit assume that the amount of data being sent does * not overload the OS * Begin and End expect the same arrays values and S passed to them * and they expect values to be of the same size as S. */ virtual void POpen_Begin(vector& values,const vector >& S,const Player& P); virtual void POpen_End(vector& values,const vector >& S,const Player& P); void AddToCheck(const T& mac, const T& value, const Player& P); virtual void Check(const Player& P); }; template void add_openings(vector& values, const Player& P, int sum_players, int last_sum_players, int send_player, TreeSum& MC); template class Separate_MAC_Check: public MAC_Check { // Different channel for checks PlainPlayer check_player; protected: // No sense to expose this Separate_MAC_Check(const T& ai, Names& Nms, int thread_num, int opening_sum=10, int max_broadcast=10, int send_player=0); virtual ~Separate_MAC_Check() {}; public: virtual void Check(const Player& P); }; template class Parallel_MAC_Check: public Separate_MAC_Check { // Different channel for every round PlainPlayer send_player; // Managed by Summer Player* receive_player; vector< Summer* > summers; int send_base_player; WaitQueue< vector > value_queue; public: Parallel_MAC_Check(const T& ai, Names& Nms, int thread_num, int opening_sum=10, int max_broadcast=10, int send_player=0); virtual ~Parallel_MAC_Check(); virtual void POpen_Begin(vector& values,const vector >& S,const Player& P); virtual void POpen_End(vector& values,const vector >& S,const Player& P); friend class Summer; }; template class Direct_MAC_Check: public Separate_MAC_Check { int open_counter; vector oss; public: Direct_MAC_Check(const T& ai, Names& Nms, int thread_num); ~Direct_MAC_Check(); void POpen_Begin(vector& values,const vector >& S,const Player& P); void POpen_End(vector& values,const vector >& S,const Player& P); }; template class Passing_MAC_Check : public Separate_MAC_Check { public: Passing_MAC_Check(const T& ai, Names& Nms, int thread_num); void POpen_Begin(vector& values,const vector >& S,const Player& P); void POpen_End(vector& values,const vector >& S,const Player& 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) { start(values, P); finish(values, P); } template size_t TreeSum::report_size(ReportType type) { if (type == CAPACITY) return os.get_max_length(); else return os.get_length(); } template void add_openings(vector& values, const Player& P, int sum_players, int last_sum_players, int send_player, TreeSum& MC) { MC.player_timers.resize(P.num_players()); vector& oss = MC.oss; oss.resize(P.num_players()); vector senders; senders.reserve(P.num_players()); 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], true); MC.player_timers[sender].stop(); if ((unsigned)oss[j].get_length() < values.size() * T::size()) { stringstream ss; ss << "Not enough information received, expected " << values.size() * T::size() << " bytes, got " << oss[j].get_length(); throw Processor_Error(ss.str()); } MC.timers[SUM].start(); for (unsigned int i=0; i(oss[j]); } MC.timers[SUM].stop(); } } template void TreeSum::start(vector& values, const Player& P) { os.reset_write_head(); int sum_players = P.num_players(); int my_relative_num = positive_modulo(P.my_num() - base_player, P.num_players()); while (true) { 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) { for (unsigned int i=0; i(values, P, sum_players, last_sum_players, base_player, *this); else add_openings(values, P, sum_players, last_sum_players, base_player, *this); timers[RECV_ADD].stop(); } } if (P.my_num() == base_player) { os.reset_write_head(); 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()) { int sender = (base_player + my_relative_num / max_broadcast) % P.num_players(); ReceiveValues(values, P, sender); } else GetValues(values); } template void TreeSum::ReceiveValues(vector& values, const Player& P, int sender) { timers[RECV_SUM].start(); P.receive_player(sender, os, true); timers[RECV_SUM].stop(); for (unsigned int i = 0; i < values.size(); i++) values[i].unpack(os); AddToValues(values); } #endif