diff --git a/Auth/ReplicatedMC.cpp b/Auth/ReplicatedMC.cpp index 3a97af8f..f686dd61 100644 --- a/Auth/ReplicatedMC.cpp +++ b/Auth/ReplicatedMC.cpp @@ -5,33 +5,34 @@ #include "ReplicatedMC.h" #include "GC/ReplicatedSecret.h" +#include "Math/Rep3Share.h" template -void ReplicatedMC::POpen_Begin(vector& values, - const vector >& S, const Player& P) +void ReplicatedMC::POpen_Begin(vector& values, + const vector& S, const Player& P) { assert(T::length == 2); (void)values; octetStream o; for (auto& x : S) - x.get_share()[0].pack(o); + x[0].pack(o); P.send_relative(-1, o); } template -void ReplicatedMC::POpen_End(vector& values, - const vector >& S, const Player& P) +void ReplicatedMC::POpen_End(vector& values, + const vector& S, const Player& P) { octetStream o; P.receive_relative(1, o); values.resize(S.size()); for (size_t i = 0; i < S.size(); i++) { - typename T::value_type tmp; + typename T::clear tmp; tmp.unpack(o); - values[i] = S[i].get_share().sum() + tmp; + values[i] = S[i].sum() + tmp; } } -template class ReplicatedMC >; +template class ReplicatedMC; template class ReplicatedMC; diff --git a/Auth/ReplicatedMC.h b/Auth/ReplicatedMC.h index 708a9609..3b006f3b 100644 --- a/Auth/ReplicatedMC.h +++ b/Auth/ReplicatedMC.h @@ -12,12 +12,18 @@ template class ReplicatedMC : public MAC_Check_Base { public: + // emulate MAC_Check ReplicatedMC(const gfp& _ = {}, int __ = 0, int ___ = 0) : MAC_Check_Base({}) { (void)_; (void)__; (void)___; } - void POpen_Begin(vector& values,const vector >& S,const Player& P); - void POpen_End(vector& values,const vector >& S,const Player& P); + // emulate Direct_MAC_Check + ReplicatedMC(const gfp& _, Names& ____, int __ = 0, int ___ = 0) : + MAC_Check_Base({}) + { (void)_; (void)__; (void)___; (void)____; } + + void POpen_Begin(vector& values,const vector& S,const Player& P); + void POpen_End(vector& values,const vector& S,const Player& P); void Check(const Player& P) { (void)P; } }; diff --git a/Auth/fake-stuff.cpp b/Auth/fake-stuff.cpp index 2d3b8735..de427956 100644 --- a/Auth/fake-stuff.cpp +++ b/Auth/fake-stuff.cpp @@ -29,9 +29,8 @@ void make_share(vector >& Sa,const T& a,int N,const T& key,PRNG& G) Sa[N-1]=S; } -template<> -void make_share(vector > >& Sa, - const FixedVec& a, int N, const FixedVec& key, +void make_share(vector& Sa, + const Integer& a, int N, const Integer& key, PRNG& G) { (void)key; @@ -40,13 +39,13 @@ void make_share(vector > >& Sa, Sa.resize(N); FixedVec add_shares; // hack - add_shares.randomize_to_sum(a[0], G); + add_shares.randomize_to_sum(a, G); for (int i=0; i share; share[0] = add_shares[(i + 1) % 3]; share[1] = add_shares[i]; - Sa[i].set_share(share); + Sa[i] = share; } } @@ -74,11 +73,29 @@ void check_share(vector >& Sa,T& value,T& mac,int N,const T& key) } } +void check_share(vector& Sa, + Integer& value, Integer& mac, int N, + const Integer& key) +{ + assert(N == 3); + value = 0; + (void)key; + (void)mac; + + for (int i = 0; i < N; i++) + { + auto share = Sa[i]; + value += share[0]; + if (share[1] != Sa[positive_modulo(i - 1, N)][0]) + throw bad_value("invalid replicated secret sharing"); + } +} + template void make_share(vector >& Sa,const gf2n& a,int N,const gf2n& key,PRNG& G); template void make_share(vector >& Sa,const gfp& a,int N,const gfp& key,PRNG& G); template void check_share(vector >& Sa,gf2n& value,gf2n& mac,int N,const gf2n& key); -template void check_share(vector& Sa,sint::value_type& value,sint::value_type& mac,int N,const sint::value_type& key); +template void check_share(vector >& Sa,gfp& value,gfp& mac,int N,const gfp& key); #ifdef USE_GF2N_LONG template void make_share(vector >& Sa,const gf2n_short& a,int N,const gf2n_short& key,PRNG& G); diff --git a/Auth/fake-stuff.h b/Auth/fake-stuff.h index 3a2ee946..11509997 100644 --- a/Auth/fake-stuff.h +++ b/Auth/fake-stuff.h @@ -5,15 +5,20 @@ #include "Math/gf2n.h" #include "Math/gfp.h" #include "Math/Share.h" +#include "Math/Rep3Share.h" #include using namespace std; template void make_share(vector >& Sa,const T& a,int N,const T& key,PRNG& G); +void make_share(vector& Sa, const Integer& a, int N, + const Integer& key, PRNG& G); template void check_share(vector >& Sa,T& value,T& mac,int N,const T& key); +void check_share(vector& Sa, Integer& value, Integer& mac, int N, + const Integer& key); void expand_byte(gf2n_short& a,int b); void collapse_byte(int& b,const gf2n_short& a); diff --git a/BMR/Machine.cpp b/BMR/Machine.cpp index ca292d9d..935fc6d0 100644 --- a/BMR/Machine.cpp +++ b/BMR/Machine.cpp @@ -3,6 +3,9 @@ * */ +#include "BMR/CommonParty.h" +#include "BMR/Register_inline.h" + #include "GC/Machine.hpp" #include "GC/Processor.hpp" #include "GC/Secret.hpp" @@ -12,6 +15,87 @@ namespace GC { +template +Secret Secret::reconstruct(const int128& x, int length) +{ + Secret res; + for (int i = 0; i < CommonParty::singleton->get_n_parties(); i++) + { + Secret tmp = res; + Secret share = input(i + 1, x, length); + res = share + tmp; +#ifdef DEBUG_DYNAMIC + int128 a,b,c; + tmp.reveal(a); + share.reveal(b); + res.reveal(c); + cout << hex << c << "(" << dec << res.size() << ") = " << hex << a + << "(" << dec << tmp.size() << ")" << " ^ " << hex << b << "(" + << dec << share.size() << ") (" << dec << x << ", " << dec + << length << ")" << endl; +#endif + } + return res; + if ((size_t)length != res.registers.size()) + { + cout << length << " " << res.registers.size() << endl; + throw runtime_error("wrong bit length in reconstruct()"); + } +} + +template +void Secret::store(Memory& mem, size_t address) +{ + AuthValue& dest = mem[address]; + Secret mac_key = reconstruct(CommonParty::s().get_mac_key().get(), default_length); + Secret mac, mask, mac_mask; + mac = carryless_mult(*this, mac_key); + GC::Mask mask_share; + int length = registers.size(); + int mac_length = mac.registers.size(); + T::get_dyn_mask(mask_share, length, mac_length); + mask.random(length, mask_share.share); + mac_mask.random(mac_length, mask_share.mac); + word masked; + int128 masked_mac; + (*this + mask).reveal(masked); + (mac + mac_mask).reveal(masked_mac); +#ifdef DEBUG_DYNAMIC + word a,b; + int128 c,d; + reveal(a); + mask.reveal(b); + mac.reveal(c); + mac_mask.reveal(d); + cout << masked << " = " << a << " ^ " << b << endl; + cout << masked_mac << " = " << c << " ^ " << d << endl; +#endif + T::unmask(dest, mask_share.share, mask_share.mac, masked, masked_mac); +} + +template +void Secret::load(int n, const Memory& mem, size_t address) +{ + (void)n; + const AuthValue& x = mem[address]; + *this = reconstruct(x.share, default_length); + Secret mac, check_mac, mac_key; + mac = reconstruct(x.mac, 2 * default_length); + mac_key = reconstruct(CommonParty::s().get_mac_key().get(), default_length); + check_mac = carryless_mult(*this, mac_key); + int128 result; + (mac + check_mac).reveal(result); +#ifdef DEBUG_DYNAMIC + cout << "loading " << hex << x.share << " " << x.mac << endl; + int128 a; + mac.reveal(a); + word b; + reveal(b); + cout << "stored value " << hex << b << " mac " << a << endl; +#endif + T::check(result, x.share, x.mac); +} + template class Secret; template class Secret; template class Secret; @@ -32,6 +116,11 @@ template class Processor< Secret >; template class Processor< Secret >; template class Processor< Secret >; +template class Thread< Secret >; +template class Thread< Secret >; +template class Thread< Secret >; +template class Thread< Secret >; + template class ThreadMaster< Secret >; template class ThreadMaster< Secret >; template class ThreadMaster< Secret >; diff --git a/BMR/Program.cpp b/BMR/Program.cpp index 9cd42376..79cee993 100644 --- a/BMR/Program.cpp +++ b/BMR/Program.cpp @@ -3,6 +3,9 @@ * */ +#include "Register.h" +#include "GC/Secret.h" + #include "GC/Instruction.hpp" #include "GC/Program.hpp" diff --git a/BMR/Register.cpp b/BMR/Register.cpp index 1e725e40..8b2c9966 100644 --- a/BMR/Register.cpp +++ b/BMR/Register.cpp @@ -511,22 +511,6 @@ void PRFRegister::random() #endif } -void EvalRegister::check_input(long long in, int n_bits) -{ - auto test = in >> (n_bits - 1); - if (n_bits == 1) - { - if (not (in == 0 or in == 1)) - throw runtime_error("input not a bit: " + to_string(in)); - } - else if (not (test == 0 or test == -1)) - { - throw runtime_error( - "input too large for a " + std::to_string(n_bits) - + "-bit signed integer: " + to_string(in)); - } -} - class InputAccess { party_id_t from; diff --git a/BMR/Register.h b/BMR/Register.h index 66527b15..1c0208d0 100644 --- a/BMR/Register.h +++ b/BMR/Register.h @@ -24,8 +24,6 @@ using namespace std; #warning not using free XOR has not been tested in a while #endif -typedef unsigned int party_id_t; - //#define PAD_TO_8(n) (n+8-n%8) #define PAD_TO_8(n) (n) @@ -119,6 +117,8 @@ class Mask; class SpdzShare; template class Secret; +template +class Processor; } class Register { @@ -224,8 +224,12 @@ public: static void ands(T& processor, const vector& args) { processor.ands(args); } template static void inputb(T& processor, const vector& args) { processor.input(args); } + template - static void check_input(long long in, int n_bits) { (void)in; (void)n_bits; } + static T get_input(int from, GC::Processor& processor, int n_bits) + { return T::input(from, processor.get_input(n_bits), n_bits); } + +// static void check_input(long long in, int n_bits) { (void)in; (void)n_bits; } void input(party_id_t from, char value = -1) { (void)from; (void)value; } void public_input(bool value) { (void)value; } void random() {} @@ -246,6 +250,11 @@ public: static void load(vector >& accesses, const GC::Memory& source) { (void)accesses; (void)source; } + // most BMR phases don't need actual input + template + static T get_input(int from, GC::Processor& processor, int n_bits) + { (void)processor; return T::input(from, 0, n_bits); } + char get_output() { return 0; } ProgramRegister(const Register& reg) : Register(reg) {} @@ -295,6 +304,13 @@ public: template static void inputb(T& processor, const vector& args); + template + static T get_input(int from, GC::Processor& processor, int n_bits) + { + (void)from, (void)processor, (void)n_bits; + throw runtime_error("use EvalRegister::inputb()"); + } + EvalRegister(const Register& reg) : ProgramRegister(reg) {} void op(const ProgramRegister& left, const ProgramRegister& right, Function func); diff --git a/BMR/common.h b/BMR/common.h index c6f577bb..cb18cc68 100644 --- a/BMR/common.h +++ b/BMR/common.h @@ -6,11 +6,14 @@ #ifndef CIRCUIT_INC_COMMON_H_ #define CIRCUIT_INC_COMMON_H_ +#include #include #include +using namespace std; typedef unsigned long wire_id_t; typedef unsigned long gate_id_t; +typedef unsigned int party_id_t; class Function { bool rep[4]; diff --git a/CONFIG b/CONFIG index b07f11a1..65f0b4a3 100644 --- a/CONFIG +++ b/CONFIG @@ -42,9 +42,8 @@ endif BOOST = -lboost_system -lboost_thread $(MY_BOOST) -CXX = g++ CXX = g++ -no-pie +#CXX = clang++ CFLAGS += $(ARCH) $(MY_CFLAGS) -g -Wextra -Wall $(OPTIM) -I$(ROOT) -pthread $(PROF) $(DEBUG) $(MOD) $(MEMPROTECT) $(GF2N_LONG) $(PREP_DIR) -maes -mpclmul -msse4.1 -mavx -mavx2 -mbmi2 --std=c++11 -Werror CPPFLAGS = $(CFLAGS) -LD = g++ -no-pie - +LD = $(CXX) diff --git a/Check-Offline.cpp b/Check-Offline.cpp index 1428a0a9..8cc56c77 100644 --- a/Check-Offline.cpp +++ b/Check-Offline.cpp @@ -21,17 +21,17 @@ using namespace std; string PREP_DATA_PREFIX; template -void check_mult_triples(const T& key,int N,vector& dataF,DataFieldType field_type) +void check_mult_triples(const T& key,int N,vector>*>& dataF) { T a,b,c,mac,res; vector > Sa(N),Sb(N),Sc(N); int n = 0; try { - while (!dataF[0]->eof(DATA_TRIPLE)) + while (!dataF[0]->eof(DATA_TRIPLE)) { for (int i = 0; i < N; i++) - dataF[i]->get_three(field_type, DATA_TRIPLE, Sa[i], Sb[i], Sc[i]); + dataF[i]->get_three(DATA_TRIPLE, Sa[i], Sb[i], Sc[i]); check_share(Sa, a, mac, N, key); check_share(Sb, b, mac, N, key); check_share(Sc, c, mac, N, key); @@ -89,46 +89,45 @@ void check_tuple(const T& a, const T& b, int n, Dtype type) } template -void check_tuples(const T& key,int N,vector& dataF, Dtype type) +void check_tuples(const T& key,int N,vector>*>& dataF, Dtype type) { T a,b,c,mac,res; vector > Sa(N),Sb(N),Sc(N); int n = 0; - DataFieldType field_type = T::field_type(); try { - while (!dataF[0]->eof(type)) + while (!dataF[0]->eof(type)) { for (int i = 0; i < N; i++) - dataF[i]->get_two(field_type, type, Sa[i], Sb[i]); + dataF[i]->get_two(type, Sa[i], Sb[i]); check_share(Sa, a, mac, N, key); check_share(Sb, b, mac, N, key); check_tuple(a, b, n, type); n++; } - cout << n << " " << Data_Files::dtype_names[type] << " of type " + cout << n << " " << DataPositions::dtype_names[type] << " of type " << T::type_string() << endl; } catch (exception& e) { - cout << "Error after " << n << " " << Data_Files::dtype_names[type] << + cout << "Error after " << n << " " << DataPositions::dtype_names[type] << " of type " << T::type_string() << endl; } } template -void check_bits(const T& key,int N,vector& dataF,DataFieldType field_type) +void check_bits(const typename T::value_type& key,int N,vector*>& dataF) { - T a,b,c,mac,res; - vector > Sa(N),Sb(N),Sc(N); + typename T::clear a,b,c,mac,res; + vector Sa(N),Sb(N),Sc(N); int n = 0; try { - while (!dataF[0]->eof(DATA_BIT)) + while (!dataF[0]->eof(DATA_BIT)) { for (int i = 0; i < N; i++) - dataF[i]->get_one(field_type, DATA_BIT, Sa[i]); + dataF[i]->get_one(DATA_BIT, Sa[i]); check_share(Sa, a, mac, N, key); if (!(a.is_zero() || a.is_one())) @@ -141,14 +140,14 @@ void check_bits(const T& key,int N,vector& dataF,DataFieldType fiel cout << n << " bits of type " << T::type_string() << endl; } - catch (exception& e) + catch (bad_value& e) { cout << "Error after " << n << " bits of type " << T::type_string() << endl; } } template -void check_inputs(const T& key,int N,vector& dataF) +void check_inputs(const T& key,int N,vector>*>& dataF) { T a, mac, x; vector< Share > Sa(N); @@ -157,7 +156,7 @@ void check_inputs(const T& key,int N,vector& dataF) { int n = 0; try { - while (!dataF[0]->input_eof(player)) + while (!dataF[0]->input_eof(player)) { for (int i = 0; i < N; i++) dataF[i]->get_input(Sa[i], x, player); @@ -176,6 +175,31 @@ void check_inputs(const T& key,int N,vector& dataF) } } +template +vector*> setup(int N, DataPositions& usage) +{ + vector*> dataF(N); + for (int i = 0; i < N; i++) + dataF[i] = new Sub_Data_Files(i, N, PREP_DATA_PREFIX, usage); + return dataF; +} + +template +void check(T key, int N, bool only_bits = false) +{ + DataPositions usage(N); + auto dataF = setup>(N, usage); + check_bits(key, N, dataF); + + if (not only_bits) + { + check_mult_triples(key, N, dataF); + check_inputs(key, N, dataF); + check_tuples(key, N, dataF, DATA_SQUARE); + check_tuples(key, N, dataF, DATA_INVERSE); + } +} + int main(int argc, const char** argv) { ez::ezOptionParser opt; @@ -194,11 +218,11 @@ int main(int argc, const char** argv) "--lgp" // Flag token. ); opt.add( - "40", // Default. + to_string(gf2n::default_degree()).c_str(), // Default. 0, // Required? 1, // Number of args expected. 0, // Delimiter if expecting multiple args. - "Bit length of GF(2^n) field (default: 40)", // Help description. + ("Bit length of GF(2^n) field (default: " + to_string(gf2n::default_degree()) + ")").c_str(), // Help description. "-lg2", // Flag token. "--lg2" // Flag token. ); @@ -260,7 +284,7 @@ int main(int argc, const char** argv) /* Find number players and MAC keys etc*/ char filename[1024]; - sint::value_type keyp,pp; keyp.assign_zero(); + gfp keyp,pp; keyp.assign_zero(); gf2n key2,p2; key2.assign_zero(); int N=1; ifstream inpf; @@ -280,19 +304,13 @@ int main(int argc, const char** argv) cout << "--------------\n"; cout << "Final Keys :\t p: " << keyp << "\n\t\t 2: " << key2 << endl; - vector dataF(N); - for (int i = 0; i < N; i++) - dataF[i] = new Data_Files(i, N, PREP_DATA_PREFIX); - check_mult_triples(key2, N, dataF, DATA_GF2N); - check_mult_triples(keyp, N, dataF, DATA_MODP); - check_inputs(key2, N, dataF); - check_inputs(keyp, N, dataF); - check_bits(key2, N, dataF, DATA_GF2N); - check_bits(keyp, N, dataF, DATA_MODP); - check_tuples(key2, N, dataF, DATA_SQUARE); - check_tuples(keyp, N, dataF, DATA_SQUARE); - check_tuples(key2, N, dataF, DATA_INVERSE); - check_tuples(keyp, N, dataF, DATA_INVERSE); - for (int i = 0; i < N; i++) - delete dataF[i]; + check(keyp, N); + check(key2, N); + + if (N == 3) + { + DataPositions pos(N); + auto dataF = setup(N, pos); + check_bits({}, N, dataF); + } } diff --git a/Compiler/floatingpoint.py b/Compiler/floatingpoint.py index a0f409fc..e2e204ff 100644 --- a/Compiler/floatingpoint.py +++ b/Compiler/floatingpoint.py @@ -484,13 +484,9 @@ def TruncPr(a, k, m, kappa=None): def TruncPrRing(a, k, m): if m == 0: return a - n_shift = int(program.Program.prog.options.ring) - k - if n_shift < 0: - raise CompilerError('too many bits for ring: %d' % k) - r_bits = [types.sint.get_random_bit() for i in range(k)] - r = types.sint.bit_compose(r_bits) - masked = ((a + r) << n_shift).reveal() >> (n_shift + m) - return masked - types.sint.bit_compose(r_bits[m:]) + res = types.sint() + comparison.TruncRing(res, a, k, m, True) + return res def TruncPrField(a, k, m, kappa=None): if kappa is None: diff --git a/Compiler/instructions.py b/Compiler/instructions.py index a04f3d7a..a6c6e822 100644 --- a/Compiler/instructions.py +++ b/Compiler/instructions.py @@ -809,7 +809,12 @@ class inverse(base.DataInstruction): code = base.opcodes['INV'] arg_format = ['sw','sw'] data_type = 'inverse' - + + def __init__(self, *args, **kwargs): + if program.options.ring and not self.is_gf2n(): + raise CompilerError('random inverse in ring not implemented') + base.DataInstruction.__init__(self, *args, **kwargs) + def execute(self): self.args[0].value = randint(0,program.P) import gmpy @@ -1331,11 +1336,18 @@ class asm_open(base.VarArgsInstruction): @base.gf2n @base.vectorize -class muls(base.VarArgsInstruction): +class muls(base.VarArgsInstruction, base.DataInstruction): """ Secret multiplication $s_i = s_j \cdot s_k$. """ __slots__ = [] code = base.opcodes['MULS'] arg_format = tools.cycle(['sw','s','s']) + data_type = 'triple' + + def get_repeat(self): + if program.options.ring: + return 0 + else: + return len(self.args) / 3 # def expand(self): # s = [program.curr_block.new_reg('s') for i in range(9)] diff --git a/Compiler/instructions_base.py b/Compiler/instructions_base.py index e32940b2..4ee7e152 100644 --- a/Compiler/instructions_base.py +++ b/Compiler/instructions_base.py @@ -687,7 +687,11 @@ class DataInstruction(Instruction): field_type = 'modp' def add_usage(self, req_node): - req_node.increment((self.field_type, self.data_type), self.get_size()) + req_node.increment((self.field_type, self.data_type), + self.get_size() * self.get_repeat()) + + def get_repeat(self): + return 1 ### ### Integer operations diff --git a/Exceptions/Exceptions.h b/Exceptions/Exceptions.h index f78fb7ac..5bce6599 100644 --- a/Exceptions/Exceptions.h +++ b/Exceptions/Exceptions.h @@ -78,9 +78,10 @@ class invalid_params: public exception { virtual const char* what() const throw() { return "Invalid Params"; } }; -class bad_value: public exception - { virtual const char* what() const throw() - { return "Some value is wrong somewhere"; } +class bad_value: public runtime_error + { + public: + bad_value(string msg = "Some value is wrong somewhere") : runtime_error(msg) {} }; class Offline_Check_Error: public runtime_error { @@ -88,7 +89,7 @@ class Offline_Check_Error: public runtime_error Offline_Check_Error(string m) : runtime_error("Offline-Check-Error : " + m) {} }; -class mac_fail: public exception +class mac_fail: public bad_value { virtual const char* what() const throw() { return "MacCheck Failure"; } }; diff --git a/ExternalIO/bankers-bonus-client.cpp b/ExternalIO/bankers-bonus-client.cpp index 49a3f2f9..391c78c4 100644 --- a/ExternalIO/bankers-bonus-client.cpp +++ b/ExternalIO/bankers-bonus-client.cpp @@ -163,7 +163,7 @@ int main(int argc, char** argv) port_base = atoi(argv[6]); // init static gfp - string prep_data_prefix = get_prep_dir(nparties, 128, 40); + string prep_data_prefix = get_prep_dir(nparties, 128, gf2n::default_degree()); initialise_fields(prep_data_prefix); // Setup connections from this client to each party socket diff --git a/ExternalIO/bankers-bonus-commsec-client.cpp b/ExternalIO/bankers-bonus-commsec-client.cpp index 0a77d12c..3a2a5a9d 100644 --- a/ExternalIO/bankers-bonus-commsec-client.cpp +++ b/ExternalIO/bankers-bonus-commsec-client.cpp @@ -363,7 +363,7 @@ int main(int argc, char** argv) } // init static gfp - string prep_data_prefix = get_prep_dir(nparties, 128, 40); + string prep_data_prefix = get_prep_dir(nparties, 128, gf2n::default_degree()); initialise_fields(prep_data_prefix); // Generate session keys to decrypt data sent from each spdz engine (party) diff --git a/FHEOffline/SimpleMachine.cpp b/FHEOffline/SimpleMachine.cpp index d13bb214..7264681e 100644 --- a/FHEOffline/SimpleMachine.cpp +++ b/FHEOffline/SimpleMachine.cpp @@ -151,7 +151,7 @@ string MachineBase::item_type() if (produce_inputs) res = "Inputs"; else - res = Data_Files::dtype_names[data_type]; + res = DataPositions::dtype_names[data_type]; transform(res.begin(), res.end(), res.begin(), ::tolower); return res; } diff --git a/Fake-Offline.cpp b/Fake-Offline.cpp index 481f49df..a7e63cbd 100644 --- a/Fake-Offline.cpp +++ b/Fake-Offline.cpp @@ -73,7 +73,7 @@ void make_bit_triples(const gf2n& key,int N,int ntrip,Dtype dtype,bool zero) /* Generate Triples */ for (int i=0; i -void make_bits(const T& key,int N,int ntrip,const string& str,bool zero) +void make_bits(const typename T::value_type& key,int N,int ntrip,bool zero) { PRNG G; G.ReSeed(); ofstream* outf=new ofstream[N]; - T a; - vector > Sa(N); + typename T::value_type a; + vector Sa(N); /* Generate Bits */ for (int i=0; i>(key2,nplayers,nbits2,zero); + make_bits>(keyp,nplayers,nbitsp,zero); make_square_tuples(key2,nplayers,nsqr2,"2",zero); make_square_tuples(keyp,nplayers,nsqrp,"p",zero); make_inputs(key2,nplayers,ninp2,"2",zero); @@ -551,7 +550,7 @@ int main(int argc, const char** argv) make_PreMulC(key2,nplayers,ninv,zero); make_PreMulC(keyp,nplayers,ninv,zero); -#ifdef REPLICATED - make_bits(sint::value_type(), nplayers, nbitsp, "p", zero); -#endif + // replicated secret sharing only for three parties + if (nplayers == 3) + make_bits({}, nplayers, nbitsp, zero); } diff --git a/GC/FakeSecret.cpp b/GC/FakeSecret.cpp index 482e3844..3a880306 100644 --- a/GC/FakeSecret.cpp +++ b/GC/FakeSecret.cpp @@ -75,11 +75,9 @@ void FakeSecret::trans(Processor& processor, int n_outputs, processor.S[args[i]] = square.rows[i]; } -FakeSecret FakeSecret::input(int from, ifstream& input_file, int n_bits) +FakeSecret FakeSecret::input(int from, GC::Processor& processor, int n_bits) { - long long int in; - input_file >> in; - return input(from, in, n_bits); + return input(from, processor.get_input(n_bits), n_bits); } FakeSecret FakeSecret::input(int from, const int128& input, int n_bits) diff --git a/GC/FakeSecret.h b/GC/FakeSecret.h index bcab9cab..fd721ccc 100644 --- a/GC/FakeSecret.h +++ b/GC/FakeSecret.h @@ -10,9 +10,8 @@ #include "GC/Memory.h" #include "GC/Access.h" -#include "Math/Share.h" -#include "Math/gf2n.h" #include "Auth/MAC_Check.h" +#include "Processor/DummyProtocol.h" #include #include @@ -32,6 +31,7 @@ public: // dummy typedef MAC_Check_Base MC; + typedef DummyProtocol Protocol; static string type_string() { return "fake secret"; } static string phase_name() { return "Faking"; } @@ -58,7 +58,7 @@ public: static void trans(Processor& processor, int n_inputs, const vector& args); - static FakeSecret input(int from, ifstream& input_file, int n_bits); + static FakeSecret input(int from, GC::Processor& processor, int n_bits); static FakeSecret input(int from, const int128& input, int n_bits); FakeSecret() : a(0) {} diff --git a/GC/Instruction.hpp b/GC/Instruction.hpp index 9d9fae6d..90645032 100644 --- a/GC/Instruction.hpp +++ b/GC/Instruction.hpp @@ -10,7 +10,6 @@ #include "GC/Secret_inline.h" #endif #include "Processor/Instruction.h" -#include "BMR/Party.h" #include "Secret.h" #include "Tools/parse.h" @@ -18,9 +17,6 @@ #include "GC/Instruction_inline.h" #include "GC/ReplicatedSecret.h" -#include "Yao/YaoGarbleWire.h" -#include "Yao/YaoEvalWire.h" - namespace GC { diff --git a/GC/Machine.h b/GC/Machine.h index 73f8e2eb..d65a38bd 100644 --- a/GC/Machine.h +++ b/GC/Machine.h @@ -10,9 +10,6 @@ #include "GC/Clear.h" #include "GC/Memory.h" -#include "Math/Share.h" -#include "Math/gf2n.h" - #include "Processor/Machine.h" #include diff --git a/GC/Machine.hpp b/GC/Machine.hpp index eab70a32..3bfe33d7 100644 --- a/GC/Machine.hpp +++ b/GC/Machine.hpp @@ -10,9 +10,6 @@ #include "ReplicatedSecret.h" #include "ThreadMaster.h" -#include "Yao/YaoGarbleWire.h" -#include "Yao/YaoEvalWire.h" - namespace GC { diff --git a/GC/Processor.h b/GC/Processor.h index 9b5817f0..059ac181 100644 --- a/GC/Processor.h +++ b/GC/Processor.h @@ -10,7 +10,6 @@ using namespace std; #include "GC/Clear.h" -#include #include "GC/Machine.h" #include "Math/Integer.h" @@ -30,6 +29,8 @@ class Processor : public ::ProcessorBase public: static int check_args(const vector& args, int n); + static void check_input(long long in, int n_bits); + Machine& machine; unsigned int PC; diff --git a/GC/Processor.hpp b/GC/Processor.hpp index b952d220..ed98754e 100644 --- a/GC/Processor.hpp +++ b/GC/Processor.hpp @@ -13,9 +13,6 @@ using namespace std; #include "Access.h" #include "ReplicatedSecret.h" -#include "Yao/YaoGarbleWire.h" -#include "Yao/YaoEvalWire.h" - namespace GC { @@ -66,10 +63,27 @@ inline long long GC::Processor::get_input(int n_bits) throw IO_Error("not enough inputs in " + input_filename); if (input_file.fail()) throw IO_Error("cannot read from " + input_filename); - EvalRegister::check_input(res, n_bits); + check_input(res, n_bits); return res; } +template +void GC::Processor::check_input(long long in, int n_bits) +{ + auto test = in >> (n_bits - 1); + if (n_bits == 1) + { + if (not (in == 0 or in == 1)) + throw runtime_error("input not a bit: " + to_string(in)); + } + else if (not (test == 0 or test == -1)) + { + throw runtime_error( + "input too large for a " + std::to_string(n_bits) + + "-bit signed integer: " + to_string(in)); + } +} + template void Processor::bitdecc(const vector& regs, const Clear& x) { @@ -172,7 +186,7 @@ void Processor::input(const vector& args) for (size_t i = 0; i < args.size(); i += 3) { int n_bits = args[i + 1]; - S[args[i+2]] = T::input(args[i] + 1, get_input(n_bits), n_bits); + S[args[i+2]] = T::input(args[i] + 1, *this, n_bits); #ifdef DEBUG_INPUT cout << "input to " << args[i+2] << "/" << &S[args[i+2]] << endl; #endif diff --git a/GC/Program.hpp b/GC/Program.hpp index a125200b..2cf1b49c 100644 --- a/GC/Program.hpp +++ b/GC/Program.hpp @@ -10,9 +10,6 @@ #include -#include "Yao/YaoGarbleWire.h" -#include "Yao/YaoEvalWire.h" - #ifdef MAX_INLINE #include "Instruction_inline.h" #endif diff --git a/GC/ReplicatedParty.cpp b/GC/ReplicatedParty.cpp index 8b3a3e1d..34b80a0b 100644 --- a/GC/ReplicatedParty.cpp +++ b/GC/ReplicatedParty.cpp @@ -20,7 +20,7 @@ ReplicatedParty::ReplicatedParty(int argc, const char** argv) 1, // Required? 1, // Number of args expected. 0, // Delimiter if expecting multiple args. - "This player's number, 0 for garbling, 1 for evaluating.", // Help description. + "This player's number (required)", // Help description. "-p", // Flag token. "--player" // Flag token. ); @@ -43,7 +43,7 @@ ReplicatedParty::ReplicatedParty(int argc, const char** argv) "--portnum" // Flag token. ); opt.parse(argc, argv); - opt.syntax = "./replicated-party.x [OPTIONS] "; + opt.syntax = "./replicated-bin-party.x [OPTIONS] "; if (opt.lastArgs.size() == 1) { progname = *opt.lastArgs[0]; diff --git a/GC/ReplicatedSecret.cpp b/GC/ReplicatedSecret.cpp index f292d390..2e4a8c45 100644 --- a/GC/ReplicatedSecret.cpp +++ b/GC/ReplicatedSecret.cpp @@ -92,7 +92,7 @@ void ReplicatedSecret::inputb(Processor& processor, } } -ReplicatedSecret ReplicatedSecret::input(int from, long input, int n_bits) +ReplicatedSecret ReplicatedSecret::input(int from, Processor& processor, int n_bits) { // BMR stuff counts from 1 from--; @@ -103,7 +103,7 @@ ReplicatedSecret ReplicatedSecret::input(int from, long input, int n_bits) o.reset_write_head(); if (from == party.P->my_num()) { - res.prepare_input(party.os, input, n_bits, party.secure_prng); + res.prepare_input(party.os, processor.get_input(n_bits), n_bits, party.secure_prng); party.P->send_relative(party.os); } else @@ -142,7 +142,7 @@ void ReplicatedSecret::and_(Processor& processor, for (size_t i = 0; i < args.size(); i += 4) processor.S[args[i + 1]].prepare_and(os, args[i], processor.S[args[i + 2]], processor.S[args[i + 3]], - party.secure_prng, repeat); + party, repeat); party.P->send_relative(os); party.P->receive_relative(os); for (size_t i = 0; i < args.size(); i += 4) @@ -151,7 +151,7 @@ void ReplicatedSecret::and_(Processor& processor, inline void ReplicatedSecret::prepare_and(vector& os, int n, const ReplicatedSecret& x, const ReplicatedSecret& y, - PRNG& secure_prng, bool repeat) + Thread& party, bool repeat) { ReplicatedSecret y_ext; if (repeat) @@ -159,11 +159,14 @@ inline void ReplicatedSecret::prepare_and(vector& os, int n, else y_ext = y; auto add_share = x[0] * y_ext.sum() + x[1] * y_ext[0]; - randomize_to_sum(add_share, secure_prng); + BitVec tmp[2]; + for (int i = 0; i < 2; i++) + tmp[i].randomize(party.protocol->shared_prngs[i]); + add_share += tmp[0] - tmp[1]; + (*this)[0] = add_share; BitVec mask = get_mask(n); *this &= mask; - for (int k = 0; k < 2; k++) - BitVec(mask & (*this)[k]).pack(os[k], n); + BitVec(mask & (*this)[0]).pack(os[0], n); } void ReplicatedSecret::and_(int n, const ReplicatedSecret& x, @@ -184,7 +187,7 @@ void ReplicatedSecret::andrs(int n, const ReplicatedSecret& x, os.resize(2); for (auto& o : os) o.reset_write_head(); - prepare_and(os, n, x, y, party.secure_prng, true); + prepare_and(os, n, x, y, party, true); party.P->send_relative(os); party.P->receive_relative(os); finalize_andrs(os, n); @@ -192,12 +195,7 @@ void ReplicatedSecret::andrs(int n, const ReplicatedSecret& x, inline void ReplicatedSecret::finalize_andrs(vector& os, int n) { - for (int k = 0; k < 2; k++) - { - value_type tmp; - tmp.unpack(os[k], n); - (*this)[k] += tmp; - } + (*this)[1].unpack(os[1], n); } void ReplicatedSecret::trans(Processor& processor, @@ -217,8 +215,7 @@ void ReplicatedSecret::trans(Processor& processor, void ReplicatedSecret::reveal(Clear& x) { - Share share; - share.set_share(*this); + ReplicatedSecret share = *this; vector opened; auto& party = ReplicatedParty::s(); party.MC.POpen_Begin(opened, {share}, *party.P); diff --git a/GC/ReplicatedSecret.h b/GC/ReplicatedSecret.h index 9b01c7c7..c086886d 100644 --- a/GC/ReplicatedSecret.h +++ b/GC/ReplicatedSecret.h @@ -15,6 +15,7 @@ using namespace std; #include "Math/FixedVec.h" #include "Math/BitVec.h" #include "Tools/SwitchableOutput.h" +#include "Processor/Replicated.h" namespace GC { @@ -32,10 +33,12 @@ class ReplicatedSecret : public FixedVec public: typedef ReplicatedSecret DynamicType; + typedef BitVec clear; + typedef ReplicatedMC MC; typedef void Inp; typedef void PO; - typedef void Protocol; + typedef ReplicatedBase Protocol; static string type_string() { return "replicated secret"; } static string phase_name() { return "Replicated computation"; } @@ -61,7 +64,7 @@ public: static BitVec get_mask(int n) { return n >= 64 ? -1 : ((1L << n) - 1); } - static ReplicatedSecret input(int from, long input, int n_bits); + static ReplicatedSecret input(int from, Processor& processor, int n_bits); void prepare_input(vector& os, long input, int n_bits, PRNG& secure_prng); void finalize_input(Thread& party, octetStream& o, int from, int n_bits); @@ -80,7 +83,7 @@ public: void andrs(int n, const ReplicatedSecret& x, const ReplicatedSecret& y); void prepare_and(vector& os, int n, const ReplicatedSecret& x, const ReplicatedSecret& y, - PRNG& secure_prng, bool repeat); + Thread& party, bool repeat); void finalize_andrs(vector& os, int n); void reveal(Clear& x); diff --git a/GC/Secret.h b/GC/Secret.h index ae581d99..55dface2 100644 --- a/GC/Secret.h +++ b/GC/Secret.h @@ -8,9 +8,7 @@ #include "GC/config.h" #include "BMR/config.h" - -#include "BMR/Register.h" -#include "BMR/AndJob.h" +#include "BMR/common.h" #include "GC/Clear.h" #include "GC/Memory.h" @@ -19,11 +17,16 @@ #include "Math/Share.h" +#include "Processor/DummyProtocol.h" + #include namespace GC { +template +class Secret; + template inline void XOR(T& res, const T& left, const T& right) { @@ -77,6 +80,7 @@ public: // dummy typedef MAC_Check_Base > MC; + typedef DummyProtocol Protocol; static string type_string() { return "evaluation secret"; } static string phase_name() { return T::name(); } @@ -89,7 +93,7 @@ public: static const T& cast(const T& reg) { return *reinterpret_cast(®); } static Secret input(party_id_t from, const int128& input, int n_bits = -1); - static Secret input(party_id_t from, ifstream& input_file, int n_bits = -1); + static Secret input(party_id_t from, Processor>& processor, int n_bits = -1); void random(int n_bits, int128 share); void random_bit(); static Secret reconstruct(const int128& x, int length); diff --git a/GC/Secret.hpp b/GC/Secret.hpp index b8f5998f..e468ed15 100644 --- a/GC/Secret.hpp +++ b/GC/Secret.hpp @@ -3,29 +3,16 @@ * */ -#include "BMR/CommonParty.h" -#include "BMR/Party.h" -#include "BMR/Register_inline.h" - #include "Secret.h" #include "Secret_inline.h" -#include "Yao/YaoGarbleWire.h" -#include "Yao/YaoEvalWire.h" - namespace GC { template -Secret Secret::input(party_id_t from, ifstream& input_file, int n_bits) +Secret Secret::input(party_id_t from, Processor>& processor, int n_bits) { - long long int in = 0; - if (from == CommonParty::s().get_id()) - { - input_file >> in; - T::check_input(in, n_bits); - } - return input(from, in, n_bits); + return T::get_input(from, processor, n_bits); } template @@ -114,64 +101,6 @@ void Secret::random_bit() #endif } -template -Secret Secret::reconstruct(const int128& x, int length) -{ - Secret res; - for (int i = 0; i < CommonParty::singleton->get_n_parties(); i++) - { - Secret tmp = res; - Secret share = input(i + 1, x, length); - res = share + tmp; -#ifdef DEBUG_DYNAMIC - int128 a,b,c; - tmp.reveal(a); - share.reveal(b); - res.reveal(c); - cout << hex << c << "(" << dec << res.size() << ") = " << hex << a - << "(" << dec << tmp.size() << ")" << " ^ " << hex << b << "(" - << dec << share.size() << ") (" << dec << x << ", " << dec - << length << ")" << endl; -#endif - } - return res; - if ((size_t)length != res.registers.size()) - { - cout << length << " " << res.registers.size() << endl; - throw runtime_error("wrong bit length in reconstruct()"); - } -} - -template -void Secret::store(Memory& mem, size_t address) -{ - AuthValue& dest = mem[address]; - Secret mac_key = reconstruct(CommonParty::s().get_mac_key().get(), default_length); - Secret mac, mask, mac_mask; - mac = carryless_mult(*this, mac_key); - GC::Mask mask_share; - int length = registers.size(); - int mac_length = mac.registers.size(); - T::get_dyn_mask(mask_share, length, mac_length); - mask.random(length, mask_share.share); - mac_mask.random(mac_length, mask_share.mac); - word masked; - int128 masked_mac; - (*this + mask).reveal(masked); - (mac + mac_mask).reveal(masked_mac); -#ifdef DEBUG_DYNAMIC - word a,b; - int128 c,d; - reveal(a); - mask.reveal(b); - mac.reveal(c); - mac_mask.reveal(d); - cout << masked << " = " << a << " ^ " << b << endl; - cout << masked_mac << " = " << c << " ^ " << d << endl; -#endif - T::unmask(dest, mask_share.share, mask_share.mac, masked, masked_mac); -} - template void Secret::store(Memory& mem, vector > >& accesses) @@ -288,29 +217,6 @@ void Secret::load(int n, const Integer& x) #endif } -template -void Secret::load(int n, const Memory& mem, size_t address) -{ - (void)n; - const AuthValue& x = mem[address]; - *this = reconstruct(x.share, default_length); - Secret mac, check_mac, mac_key; - mac = reconstruct(x.mac, 2 * default_length); - mac_key = reconstruct(CommonParty::s().get_mac_key().get(), default_length); - check_mac = carryless_mult(*this, mac_key); - int128 result; - (mac + check_mac).reveal(result); -#ifdef DEBUG_DYNAMIC - cout << "loading " << hex << x.share << " " << x.mac << endl; - int128 a; - mac.reveal(a); - word b; - reveal(b); - cout << "stored value " << hex << b << " mac " << a << endl; -#endif - T::check(result, x.share, x.mac); -} - template void Secret::load(vector > >& accesses, const Memory& mem) { diff --git a/GC/Secret_inline.h b/GC/Secret_inline.h index 7465ff73..69f6c5dc 100644 --- a/GC/Secret_inline.h +++ b/GC/Secret_inline.h @@ -7,6 +7,7 @@ #define GC_SECRET_INLINE_H_ #include "BMR/config.h" +#include "GC/Secret.h" #ifdef MAX_INLINE #define MAYBE_INLINE inline @@ -14,8 +15,6 @@ #define MAYBE_INLINE #endif -#include "BMR/Register_inline.h" - namespace GC { template diff --git a/GC/Thread.h b/GC/Thread.h index 5f971529..b2962753 100644 --- a/GC/Thread.h +++ b/GC/Thread.h @@ -31,6 +31,7 @@ public: Machine& machine; Processor processor; typename T::MC MC; + typename T::Protocol* protocol; Names& N; Player* P; PRNG secure_prng; diff --git a/GC/Thread.hpp b/GC/Thread.hpp index 149703e2..47dbb83d 100644 --- a/GC/Thread.hpp +++ b/GC/Thread.hpp @@ -8,8 +8,6 @@ #include "ReplicatedSecret.h" #include "Secret.h" -#include "Yao/YaoGarbleWire.h" -#include "Yao/YaoEvalWire.h" namespace GC { @@ -23,7 +21,8 @@ void* Thread::run_thread(void* thread) template Thread::Thread(int thread_num, Machine& machine, Names& N) : - machine(machine), processor(machine), N(N), P(0), thread_num(thread_num) + machine(machine), processor(machine), protocol(0), N(N), P(0), + thread_num(thread_num) { pthread_create(&thread, 0, run_thread, this); } @@ -33,6 +32,8 @@ Thread::~Thread() { if (P) delete P; + if (protocol) + delete protocol; } template @@ -43,6 +44,7 @@ void Thread::run() singleton = this; secure_prng.ReSeed(); P = new Player(N, thread_num << 16); + protocol = new typename T::Protocol(*P); string input_file = "Player-Data/Input-P" + to_string(N.my_num()) + "-" + to_string(thread_num); processor.open_input_file(input_file); done.push(0); @@ -82,10 +84,6 @@ void Thread::finish() } template class Thread; -template class Thread< Secret >; -template class Thread< Secret >; -template class Thread< Secret >; -template class Thread< Secret >; template class Thread; } /* namespace GC */ diff --git a/GC/ThreadMaster.hpp b/GC/ThreadMaster.hpp index 5c3c7e7d..2e7df634 100644 --- a/GC/ThreadMaster.hpp +++ b/GC/ThreadMaster.hpp @@ -8,8 +8,6 @@ #include "ReplicatedSecret.h" #include "Secret.h" -#include "Yao/YaoGarbleWire.h" -#include "Yao/YaoEvalWire.h" namespace GC { diff --git a/Makefile b/Makefile index 3e6289f6..a2ec0212 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ ifeq ($(USE_NTL),1) FHEOFFLINE = $(patsubst %.cpp,%.o,$(wildcard FHEOffline/*.cpp FHE/*.cpp)) endif -GC = $(patsubst %.cpp,%.o,$(wildcard GC/*.cpp)) +GC = $(patsubst %.cpp,%.o,$(wildcard GC/*.cpp)) $(PROCESSOR) # OT stuff needs GF2N_LONG, so only compile if this is enabled ifeq ($(USE_GF2N_LONG),1) @@ -25,7 +25,7 @@ endif COMMON = $(MATH) $(TOOLS) $(NETWORK) $(AUTH) COMPLETE = $(COMMON) $(PROCESSOR) $(FHEOFFLINE) $(TINYOTOFFLINE) $(GC) $(OT) -YAO = $(patsubst %.cpp,%.o,$(wildcard Yao/*.cpp)) $(OT) +YAO = $(patsubst %.cpp,%.o,$(wildcard Yao/*.cpp)) $(OT) $(GC) BMR = $(patsubst %.cpp,%.o,$(wildcard BMR/*.cpp BMR/network/*.cpp)) $(COMMON) $(PROCESSOR) $(GC) @@ -33,11 +33,11 @@ LIB = libSPDZ.a LIBSIMPLEOT = SimpleOT/libsimpleot.a # used for dependency generation -OBJS = $(BMR) $(FHEOFFLINE) $(TINYOTOFFLINE) +OBJS = $(BMR) $(FHEOFFLINE) $(TINYOTOFFLINE) $(YAO) $(COMPLETE) DEPS := $(OBJS:.o=.d) -all: gen_input online offline externalIO yao replicated-party.x +all: gen_input online offline externalIO yao replicated-bin-party.x replicated-ring-party.x ifeq ($(USE_GF2N_LONG),1) all: bmr @@ -141,8 +141,8 @@ spdz2-offline.x: $(COMMON) $(FHEOFFLINE) spdz2-offline.cpp endif ifeq ($(USE_GF2N_LONG),1) -yao-player.x: $(YAO) $(BMR) yao-player.cpp - $(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS) $(BOOST) $(LIBSIMPLEOT) +yao-player.x: $(YAO) $(COMMON) yao-player.cpp + $(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS) $(LIBSIMPLEOT) endif yao-clean: @@ -151,8 +151,11 @@ yao-clean: galois-degree.x: $(COMMON) galois-degree.cpp $(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS) -replicated-party.x: $(BMR) replicated-party.cpp +replicated-bin-party.x: $(BMR) replicated-bin-party.cpp $(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS) $(BOOST) +replicated-ring-party.x: replicated-ring-party.cpp $(PROCESSOR) $(COMMON) + $(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS) + clean: -rm */*.o *.o */*.d *.d *.x core.* *.a gmon.out */*/*.o diff --git a/Math/FixedVec.h b/Math/FixedVec.h index f917cd68..52a8f75a 100644 --- a/Math/FixedVec.h +++ b/Math/FixedVec.h @@ -27,11 +27,6 @@ public: typedef T value_type; static const int length = L; - typedef ReplicatedMC > MC; - typedef ReplicatedInput > Inp; - typedef ReplicatedPrivateOutput > PO; - typedef Replicated > Protocol; - static int size() { return L * T::size(); @@ -40,6 +35,10 @@ public: { return T::type_string() + "^" + to_string(L); } + static char type_char() + { + return T::type_char(); + } static DataFieldType field_type() { return DATA_MODP; @@ -124,11 +123,25 @@ public: bool is_zero() { - throw not_implemented(); + return equal(0); } bool is_one() { - throw not_implemented(); + return equal(1); + } + + FixedVecoperator+(const FixedVec& other) const + { + FixedVec res; + res.add(*this, other); + return res; + } + + FixedVecoperator-(const FixedVec& other) const + { + FixedVec res; + res.sub(*this, other); + return res; } FixedVecoperator^(const FixedVec& other) const @@ -147,6 +160,12 @@ public: return res; } + FixedVec& operator+=(const FixedVec& other) + { + add(other); + return *this; + } + FixedVec& operator^=(const FixedVec& other) { for (int i = 0; i < L; i++) diff --git a/Math/Integer.h b/Math/Integer.h index 624cfefc..d8884544 100644 --- a/Math/Integer.h +++ b/Math/Integer.h @@ -66,12 +66,16 @@ class Integer : public IntBase typedef Integer value_type; typedef Integer clear; + static char type_char() { return 'R'; } + Integer() { a = 0; } Integer(long a) : IntBase(a) {} Integer(const bigint& x) { *this = x.get_si(); } void convert_destroy(bigint& other) { *this = other.get_si(); } + void assign_one() { a = 1; } + bool is_zero() const { return a == 0; } bool is_one() const { return a == 1; } bool is_bit() const { return is_zero() or is_one(); } diff --git a/Math/Rep3Share.h b/Math/Rep3Share.h new file mode 100644 index 00000000..ea414e64 --- /dev/null +++ b/Math/Rep3Share.h @@ -0,0 +1,93 @@ +/* + * Rep3Share.h + * + */ + +#ifndef MATH_REP3SHARE_H_ +#define MATH_REP3SHARE_H_ + +#include "Math/FixedVec.h" +#include "Math/Integer.h" +#include "Processor/Replicated.h" + +class Rep3Share: public FixedVec +{ +public: + typedef Integer clear; + + typedef Replicated Protocol; + typedef ReplicatedMC MAC_Check; + typedef MAC_Check Direct_MC; + typedef ReplicatedInput Input; + typedef ReplicatedPrivateOutput PrivateOutput; + + static char type_char() + { + return clear::type_char(); + } + + Rep3Share() + { + } + Rep3Share(const FixedVec& other) + { + FixedVec::operator=(other); + } + + Rep3Share(Integer value, int my_num) + { + Replicated::assign(*this, value, my_num); + } + + // Share compatibility + void assign(clear other, int my_num, const Integer& alphai) + { + (void)alphai; + *this = Rep3Share(other, my_num); + } + void assign(const char* buffer) + { + FixedVec::assign(buffer); + } + + void add(const Rep3Share& x, const Rep3Share& y) + { + *this = x + y; + } + void sub(const Rep3Share& x, const Rep3Share& y) + { + *this = x - y; + } + + void add(const Rep3Share& S, const clear aa, int my_num, + const Integer& alphai) + { + (void)alphai; + *this = S + Rep3Share(aa, my_num); + } + void sub(const Rep3Share& S, const clear& aa, int my_num, + const Integer& alphai) + { + (void)alphai; + *this = S - Rep3Share(aa, my_num); + } + void sub(const clear& aa, const Rep3Share& S, int my_num, + const Integer& alphai) + { + (void)alphai; + *this = Rep3Share(aa, my_num) - S; + } + + void pack(octetStream& os, bool full = true) const + { + (void)full; + FixedVec::pack(os); + } + void unpack(octetStream& os, bool full = true) + { + (void)full; + FixedVec::unpack(os); + } +}; + +#endif /* MATH_REP3SHARE_H_ */ diff --git a/Math/Share.cpp b/Math/Share.cpp index 93431a79..27c5ed0f 100644 --- a/Math/Share.cpp +++ b/Math/Share.cpp @@ -38,17 +38,19 @@ T combine(const vector< Share >& S) template -inline void Share::pack(octetStream& os) const +inline void Share::pack(octetStream& os, bool full) const { a.pack(os); - mac.pack(os); + if (full) + mac.pack(os); } template -inline void Share::unpack(octetStream& os) +inline void Share::unpack(octetStream& os, bool full) { a.unpack(os); - mac.unpack(os); + if (full) + mac.unpack(os); } @@ -77,5 +79,3 @@ template class Share; template gf2n_short combine(const vector< Share >& S); template bool check_macs(const vector< Share >& S,const gf2n_short& key); #endif - -template class Share >; diff --git a/Math/Share.h b/Math/Share.h index 97601622..578983ce 100644 --- a/Math/Share.h +++ b/Math/Share.h @@ -20,6 +20,7 @@ template class Share; template T combine(const vector< Share >& S); template bool check_macs(const vector< Share >& S,const T& key); +template class Direct_MAC_Check; template class Share @@ -33,6 +34,7 @@ class Share typedef typename T::value_type clear; typedef typename T::MC MAC_Check; + typedef Direct_MAC_Check Direct_MC; typedef typename T::Inp Input; typedef typename T::PO PrivateOutput; typedef typename T::Protocol Protocol; @@ -43,6 +45,12 @@ class Share static string type_string() { return T::type_string(); } + static char type_char() + { return T::type_char(); } + + static DataFieldType field_type() + { return T::field_type(); } + void assign(const Share& S) { a=S.a; mac=S.mac; } void assign(const char* buffer) @@ -106,8 +114,8 @@ class Share friend ostream& operator<<(ostream& s, const Share& x) { x.output(s, true); return s; } - void pack(octetStream& os) const; - void unpack(octetStream& os); + void pack(octetStream& os, bool full = true) const; + void unpack(octetStream& os, bool full = true); /* Takes a vector of shares, one from each player and * determines the shared value diff --git a/Math/Zp_Data.h b/Math/Zp_Data.h index 0d6f26b9..bcff3a15 100644 --- a/Math/Zp_Data.h +++ b/Math/Zp_Data.h @@ -9,6 +9,7 @@ * */ +#include "Math/config.h" #include "Math/bigint.h" #include "Math/mpn_fixed.h" #include "Tools/random.h" diff --git a/Math/config.h b/Math/config.h new file mode 100644 index 00000000..a1fc17d7 --- /dev/null +++ b/Math/config.h @@ -0,0 +1,11 @@ +/* + * config.h + * + */ + +#ifndef MATH_CONFIG_H_ +#define MATH_CONFIG_H_ + +//#define MAX_MOD_SZ 6 + +#endif /* MATH_CONFIG_H_ */ diff --git a/Player-Online.cpp b/Player-Online.cpp index 44303ad7..3a92dd76 100644 --- a/Player-Online.cpp +++ b/Player-Online.cpp @@ -253,7 +253,7 @@ int main(int argc, const char** argv) try #endif { - Machine(playerno, playerNames, progname, memtype, lgp, lg2, + Machine(playerno, playerNames, progname, memtype, lgp, lg2, opt.get("--direct")->isSet, opening_sum, opt.get("--parallel")->isSet, opt.get("--threads")->isSet, max_broadcast).run(); diff --git a/Processor/Binary_File_IO.cpp b/Processor/Binary_File_IO.cpp index 2c19ffe2..92ccfdd4 100644 --- a/Processor/Binary_File_IO.cpp +++ b/Processor/Binary_File_IO.cpp @@ -1,4 +1,5 @@ #include "Processor/Binary_File_IO.h" +#include "Math/Rep3Share.h" #include "Math/gfp.h" /* @@ -8,7 +9,7 @@ */ template -void Binary_File_IO::write_to_file(const string filename, const vector< Share >& buffer) +void Binary_File_IO::write_to_file(const string filename, const vector< T >& buffer) { ofstream outf; @@ -69,5 +70,5 @@ void Binary_File_IO::read_from_file(const string filename, vector< T >& buffer, template void Binary_File_IO::write_to_file(const string filename, const vector< Share >& buffer); template void Binary_File_IO::read_from_file(const string filename, vector< Share >& buffer, const int start_posn, int &end_posn); -template void Binary_File_IO::write_to_file(const string filename, const vector< Share > >& buffer); -template void Binary_File_IO::read_from_file(const string filename, vector< Share > >& buffer, const int start_posn, int &end_posn); +template void Binary_File_IO::write_to_file(const string filename, const vector< Rep3Share >& buffer); +template void Binary_File_IO::read_from_file(const string filename, vector< Rep3Share >& buffer, const int start_posn, int &end_posn); diff --git a/Processor/Binary_File_IO.h b/Processor/Binary_File_IO.h index 7c1592f0..6648eb08 100644 --- a/Processor/Binary_File_IO.h +++ b/Processor/Binary_File_IO.h @@ -26,7 +26,7 @@ class Binary_File_IO * Throws file_error. */ template - void write_to_file(const string filename, const vector< Share >& buffer); + void write_to_file(const string filename, const vector< T >& buffer); /* * Read from posn in the filename the binary values until the buffer is full. diff --git a/Processor/Buffer.cpp b/Processor/Buffer.cpp index 3ddd4c24..7eedd1f8 100644 --- a/Processor/Buffer.cpp +++ b/Processor/Buffer.cpp @@ -143,58 +143,13 @@ void Buffer::input(U& a) next++; } -template < template class U, template class V > -BufferBase& BufferHelper::get_buffer(DataFieldType field_type) -{ - if (field_type == DATA_MODP) - return bufferp; - else if (field_type == DATA_GF2N) - return buffer2; - else - throw not_implemented(); -} - -template < template class U, template class V > -void BufferHelper::setup(DataFieldType field_type, string filename, int tuple_length, const char* data_type) -{ - files[field_type] = new ifstream(filename.c_str(), ios::in | ios::binary); - get_buffer(field_type).setup(files[field_type], tuple_length, filename, - data_type, Data_Files::long_field_names[field_type]); -} - -template class U, template class V> -void BufferHelper::close() -{ - for (int i = 0; i < N_DATA_FIELD_TYPE; i++) - if (files[i]) - { - files[i]->close(); - delete files[i]; - } -} - -template class U, template class V> -void BufferHelper::prune() -{ - buffer2.prune(); - bufferp.prune(); -} - -template class U, template class V> -void BufferHelper::purge() -{ - buffer2.purge(); - bufferp.purge(); -} - template class Buffer< Share, Share >; template class Buffer< Share, Share >; -template class Buffer< Share >, Share > >; -template class Buffer< InputTuple, RefInputTuple >; -template class Buffer< InputTuple, RefInputTuple >; -template class Buffer< sint::value_type, sint::value_type >; +template class Buffer< Rep3Share, Rep3Share>; +template class Buffer< InputTuple, RefInputTuple >; +template class Buffer< InputTuple, RefInputTuple >; +template class Buffer< InputTuple, RefInputTuple >; +template class Buffer< gfp, gfp >; template class Buffer< gf2n, gf2n >; +template class Buffer< FixedVec, FixedVec >; template class Buffer< Integer, Integer >; - -template class BufferHelper; -template class BufferHelper; diff --git a/Processor/Buffer.h b/Processor/Buffer.h index 36b2d2c7..9cf050ff 100644 --- a/Processor/Buffer.h +++ b/Processor/Buffer.h @@ -60,23 +60,29 @@ public: void fill_buffer(); }; - -template < template class U, template class V > -class BufferHelper +template +class BufferOwner : public Buffer { -public: - Buffer< U, V > bufferp; - Buffer< U, V > buffer2; - ifstream* files[N_DATA_FIELD_TYPE]; + ifstream* file; - BufferHelper() { memset(files, 0, sizeof(files)); } - void input(V& a) { bufferp.input(a); } - void input(V& a) { buffer2.input(a); } - BufferBase& get_buffer(DataFieldType field_type); - void setup(DataFieldType field_type, string filename, int tuple_length, const char* data_type = 0); - void close(); - void prune(); - void purge(); +public: + BufferOwner() : + file(0) + { + } + + void setup(string filename, int tuple_length, const char* data_type = 0) + { + file = new ifstream(filename, ios::in | ios::binary); + Buffer::setup(file, tuple_length, filename, data_type, U::type_string().c_str()); + } + + void close() + { + if (file) + delete file; + file = 0; + } }; #endif /* PROCESSOR_BUFFER_H_ */ diff --git a/Processor/Data_Files.cpp b/Processor/Data_Files.cpp index c57a4618..5d84313c 100644 --- a/Processor/Data_Files.cpp +++ b/Processor/Data_Files.cpp @@ -4,22 +4,35 @@ #include -const char* Data_Files::field_names[] = { "p", "2" }; -const char* Data_Files::long_field_names[] = { "gfp", "gf2n" }; -const bool Data_Files::implemented[N_DATA_FIELD_TYPE][N_DTYPE] = { - { true, true, true, true, false, false }, - { true, true, true, true, true, true }, -}; -const int Data_Files::tuple_size[N_DTYPE] = { 3, 2, 1, 2, 3, 3 }; +const char* DataPositions::field_names[] = { "sint", "sgf2n" }; -Lock Data_Files::tuple_lengths_lock; -map Data_Files::tuple_lengths; +template<> +const bool Sub_Data_Files::implemented[N_DTYPE] = + { true, true, true, true, false, false } +; + +template<> +const bool Sub_Data_Files::implemented[N_DTYPE] = + { true, true, true, true, true, true } +; + +template<> +const bool Sub_Data_Files::implemented[N_DTYPE] = + { false, false, true, false, false, false } +; + +const int DataPositions::tuple_size[N_DTYPE] = { 3, 2, 1, 2, 3, 3 }; + +template +Lock Sub_Data_Files::tuple_lengths_lock; +template +map Sub_Data_Files::tuple_lengths; void DataPositions::set_num_players(int num_players) { - files.resize(N_DATA_FIELD_TYPE, vector(N_DTYPE)); - inputs.resize(num_players, vector(N_DATA_FIELD_TYPE)); + files.resize(N_DATA_FIELD_TYPE, vector(N_DTYPE)); + inputs.resize(num_players, vector(N_DATA_FIELD_TYPE)); } void DataPositions::increase(const DataPositions& delta) @@ -33,8 +46,8 @@ void DataPositions::increase(const DataPositions& delta) for (unsigned int j = 0; j < inputs.size(); j++) inputs[j][field_type] += delta.inputs[j][field_type]; - map::const_iterator it; - const map& delta_ext = delta.extended[field_type]; + map::const_iterator it; + const map& delta_ext = delta.extended[field_type]; for (it = delta_ext.begin(); it != delta_ext.end(); it++) extended[field_type][it->first] += it->second; } @@ -46,7 +59,7 @@ void DataPositions::print_cost() const double total_cost = 0; for (int i = 0; i < N_DATA_FIELD_TYPE; i++) { - cerr << " Type " << Data_Files::field_names[i] << endl; + cerr << " Type " << field_names[i] << endl; for (int j = 0; j < N_DTYPE; j++) { double cost_per_item = 0; @@ -57,11 +70,12 @@ void DataPositions::print_cost() const double cost = items_used * cost_per_item; total_cost += cost; cerr.fill(' '); - cerr << " " << setw(10) << cost << " = " << setw(10) << items_used - << " " << setw(14) << Data_Files::dtype_names[j] << " à " << setw(11) - << cost_per_item << endl; + if (items_used) + cerr << " " << setw(10) << cost << " = " << setw(10) << items_used + << " " << setw(14) << dtype_names[j] << " @ " << setw(11) + << cost_per_item << endl; } - for (map::const_iterator it = extended[i].begin(); + for (map::const_iterator it = extended[i].begin(); it != extended[i].end(); it++) { cerr.fill(' '); @@ -73,106 +87,105 @@ void DataPositions::print_cost() const } -int Data_Files::share_length(int field_type) +template +int Sub_Data_Files::tuple_length(int dtype) { - switch (field_type) - { - case DATA_MODP: - return 2 * gfp::t() * sizeof(mp_limb_t); - case DATA_GF2N: - return Share::size(); - default: - throw invalid_params(); - } + return DataPositions::tuple_size[dtype] * T::size(); } -int Data_Files::tuple_length(int field_type, int dtype) -{ - return tuple_size[dtype] * share_length(field_type); -} - -Data_Files::Data_Files(int myn, int n, const string& prep_data_dir) : - usage(n), prep_data_dir(prep_data_dir) +template +Sub_Data_Files::Sub_Data_Files(int my_num, int num_players, + const string& prep_data_dir, DataPositions& usage) : + my_num(my_num), num_players(num_players), prep_data_dir(prep_data_dir), + usage(usage) { cerr << "Setting up Data_Files in: " << prep_data_dir << endl; - num_players=n; - my_num=myn; char filename[1024]; - input_buffers = new BufferHelper[num_players]; - - for (int field_type = 0; field_type < N_DATA_FIELD_TYPE; field_type++) + for (int dtype = 0; dtype < N_DTYPE; dtype++) { - for (int dtype = 0; dtype < N_DTYPE; dtype++) + if (implemented[dtype]) { - if (implemented[field_type][dtype]) - { - sprintf(filename,(prep_data_dir + "%s-%s-P%d").c_str(),dtype_names[dtype], - field_names[field_type],my_num); - buffers[dtype].setup(DataFieldType(field_type), filename, - tuple_length(field_type, dtype), dtype_names[dtype]); - } + sprintf(filename,(prep_data_dir + "%s-%s-P%d").c_str(),DataPositions::dtype_names[dtype], + string(1, T::type_char()).c_str(),my_num); + buffers[dtype].setup(filename, + tuple_length(dtype), DataPositions::dtype_names[dtype]); } + } - for (int i=0; i +Data_Files::Data_Files(int myn, int n, const string& prep_data_dir) : + usage(n), DataFp(myn, n, prep_data_dir, usage), + DataF2(myn, n, prep_data_dir, usage), prep_data_dir(prep_data_dir) +{ +} + +template +Sub_Data_Files::~Sub_Data_Files() { for (int i = 0; i < N_DTYPE; i++) buffers[i].close(); for (int i = 0; i < num_players; i++) input_buffers[i].close(); - delete[] input_buffers; my_input_buffers.close(); - for (map >::iterator it = + for (auto it = extended.begin(); it != extended.end(); it++) it->second.close(); } -void Data_Files::seekg(DataPositions& pos) +template +void Sub_Data_Files::seekg(DataPositions& pos) { - for (int field_type = 0; field_type < N_DATA_FIELD_TYPE; field_type++) + DataFieldType field_type = T::field_type(); + for (int dtype = 0; dtype < N_DTYPE; dtype++) + if (implemented[dtype]) + buffers[dtype].seekg(pos.files[field_type][dtype]); + for (int j = 0; j < num_players; j++) + if (j == my_num) + my_input_buffers.seekg(pos.inputs[j][field_type]); + else + input_buffers[j].seekg(pos.inputs[j][field_type]); + for (map::const_iterator it = pos.extended[field_type].begin(); + it != pos.extended[field_type].end(); it++) { - for (int dtype = 0; dtype < N_DTYPE; dtype++) - if (implemented[field_type][dtype]) - buffers[dtype].get_buffer(DataFieldType(field_type)).seekg(pos.files[field_type][dtype]); - for (int j = 0; j < num_players; j++) - if (j == my_num) - my_input_buffers.get_buffer(DataFieldType(field_type)).seekg(pos.inputs[j][field_type]); - else - input_buffers[j].get_buffer(DataFieldType(field_type)).seekg(pos.inputs[j][field_type]); - for (map::const_iterator it = pos.extended[field_type].begin(); - it != pos.extended[field_type].end(); it++) - { - setup_extended(DataFieldType(field_type), it->first); - extended[it->first].get_buffer(DataFieldType(field_type)).seekg(it->second); - } + setup_extended(it->first); + extended[it->first].seekg(it->second); } +} +template +void Data_Files::seekg(DataPositions& pos) +{ + DataFp.seekg(pos); + DataF2.seekg(pos); usage = pos; } -void Data_Files::skip(const DataPositions& pos) +template +void Data_Files::skip(const DataPositions& pos) { DataPositions new_pos = usage; new_pos.increase(pos); seekg(new_pos); } -void Data_Files::prune() +template +void Sub_Data_Files::prune() { for (auto& buffer : buffers) buffer.prune(); @@ -183,7 +196,15 @@ void Data_Files::prune() it.second.prune(); } -void Data_Files::purge() +template +void Data_Files::prune() +{ + DataFp.prune(); + DataF2.prune(); +} + +template +void Sub_Data_Files::purge() { for (auto& buffer : buffers) buffer.purge(); @@ -194,18 +215,26 @@ void Data_Files::purge() it.second.purge(); } -void Data_Files::setup_extended(DataFieldType field_type, const DataTag& tag, int tuple_size) +template +void Data_Files::purge() { - BufferBase& buffer = extended[tag].get_buffer(field_type); + DataFp.purge(); + DataF2.purge(); +} + +template +void Sub_Data_Files::setup_extended(const DataTag& tag, int tuple_size) +{ + BufferBase& buffer = extended[tag]; tuple_lengths_lock.lock(); int tuple_length = tuple_lengths[tag]; - int my_tuple_length = tuple_size * share_length(field_type); + int my_tuple_length = tuple_size * T::size(); if (tuple_length > 0) { if (tuple_size > 0 && my_tuple_length != tuple_length) { stringstream ss; - ss << "Inconsistent size of " << field_names[field_type] << " " + ss << "Inconsistent size of " << T::type_string() << " " << tag.get_string() << ": " << my_tuple_length << " vs " << tuple_length; throw Processor_Error(ss.str()); @@ -218,20 +247,24 @@ void Data_Files::setup_extended(DataFieldType field_type, const DataTag& tag, in if (!buffer.is_up()) { stringstream ss; - ss << prep_data_dir << tag.get_string() << "-" << field_names[field_type] << "-P" << my_num; - extended[tag].setup(field_type, ss.str(), tuple_length); + ss << prep_data_dir << tag.get_string() << "-" << T::type_char() << "-P" << my_num; + extended[tag].setup(ss.str(), tuple_length); } } template -void Data_Files::get(Processor& proc, DataTag tag, const vector& regs, int vector_size) +void Sub_Data_Files::get(SubProcessor& proc, DataTag tag, const vector& regs, int vector_size) { usage.extended[T::field_type()][tag] += vector_size; - setup_extended(T::field_type(), tag, regs.size()); + setup_extended(tag, regs.size()); for (int j = 0; j < vector_size; j++) for (unsigned int i = 0; i < regs.size(); i++) - extended[tag].input(proc.get_S_ref(regs[i] + j)); + extended[tag].input(proc.get_S_ref(regs[i] + j)); } -template void Data_Files::get(Processor& proc, DataTag tag, const vector& regs, int vector_size); -template void Data_Files::get(Processor& proc, DataTag tag, const vector& regs, int vector_size); +template class Sub_Data_Files; +template class Sub_Data_Files; +template class Sub_Data_Files; + +template class Data_Files; +template class Data_Files; diff --git a/Processor/Data_Files.h b/Processor/Data_Files.h index 0fd7c5f6..1441d99b 100644 --- a/Processor/Data_Files.h +++ b/Processor/Data_Files.h @@ -46,9 +46,13 @@ public: struct DataPositions { - vector< vector > files; - vector< vector > inputs; - map extended[N_DATA_FIELD_TYPE]; + static const char* dtype_names[N_DTYPE]; + static const char* field_names[N_DATA_FIELD_TYPE]; + static const int tuple_size[N_DTYPE]; + + vector< vector > files; + vector< vector > inputs; + map extended[N_DATA_FIELD_TYPE]; DataPositions(int num_players = 0) { set_num_players(num_players); } void set_num_players(int num_players); @@ -56,94 +60,66 @@ struct DataPositions void print_cost() const; }; -class Processor; +template class Processor; +template class Data_Files; -class Data_Files +template +class Sub_Data_Files { + static const bool implemented[N_DTYPE]; + static map tuple_lengths; static Lock tuple_lengths_lock; - BufferHelper buffers[N_DTYPE]; - BufferHelper* input_buffers; - BufferHelper my_input_buffers; - map > extended; + static int tuple_length(int dtype); + + BufferOwner buffers[N_DTYPE]; + vector> input_buffers; + BufferOwner, RefInputTuple> my_input_buffers; + map > extended; int my_num,num_players; - DataPositions usage; - - public: - const string prep_data_dir; - static const char* dtype_names[N_DTYPE]; - static const char* field_names[N_DATA_FIELD_TYPE]; - static const char* long_field_names[N_DATA_FIELD_TYPE]; - static const bool implemented[N_DATA_FIELD_TYPE][N_DTYPE]; - static const int tuple_size[N_DTYPE]; + DataPositions& usage; - static int share_length(int field_type); - static int tuple_length(int field_type, int dtype); +public: + Sub_Data_Files(int my_num, int num_players, const string& prep_data_dir, + DataPositions& usage); + ~Sub_Data_Files(); - Data_Files(int my_num,int n,const string& prep_data_dir); - Data_Files(Names& N, const string& prep_data_dir) : - Data_Files(N.my_num(), N.num_players(), prep_data_dir) {} - ~Data_Files(); - - DataPositions tellg(); void seekg(DataPositions& pos); - void skip(const DataPositions& pos); void prune(); void purge(); - template bool eof(Dtype dtype); - template bool input_eof(int player); - void setup_extended(DataFieldType field_type, const DataTag& tag, int tuple_size = 0); - template - void get(Processor& proc, DataTag tag, const vector& regs, int vector_size); + void get(Dtype dtype, T* a); - DataPositions get_usage() - { - return usage; - } - - template - void get(Dtype dtype, Share* a) + void get_three(Dtype dtype, T& a, T& b, T& c) { usage.files[T::field_type()][dtype]++; - for (int i = 0; i < tuple_size[dtype]; i++) - buffers[dtype].input(a[i]); - } - - template - void get_three(DataFieldType field_type, Dtype dtype, Share& a, Share& b, Share& c) - { - usage.files[field_type][dtype]++; buffers[dtype].input(a); buffers[dtype].input(b); buffers[dtype].input(c); } - template - void get_two(DataFieldType field_type, Dtype dtype, Share& a, Share& b) + void get_two(Dtype dtype, T& a, T& b) { - usage.files[field_type][dtype]++; + usage.files[T::field_type()][dtype]++; buffers[dtype].input(a); buffers[dtype].input(b); } - template - void get_one(DataFieldType field_type, Dtype dtype, Share& a) + void get_one(Dtype dtype, T& a) { - usage.files[field_type][dtype]++; + usage.files[T::field_type()][dtype]++; buffers[dtype].input(a); } - template - void get_input(Share& a,T& x,int i) + void get_input(T& a,typename T::clear& x,int i) { usage.inputs[i][T::field_type()]++; RefInputTuple tuple(a, x); @@ -152,19 +128,140 @@ class Data_Files else input_buffers[i].input(a); } + + void setup_extended(const DataTag& tag, int tuple_size = 0); + void get(SubProcessor& proc, DataTag tag, const vector& regs, int vector_size); +}; + +template +class Data_Files +{ + DataPositions usage; + + public: + + Sub_Data_Files DataFp; + Sub_Data_Files DataF2; + + const string& prep_data_dir; + + Data_Files(int my_num,int n,const string& prep_data_dir); + Data_Files(Names& N, const string& prep_data_dir) : + Data_Files(N.my_num(), N.num_players(), prep_data_dir) {} + + DataPositions tellg(); + void seekg(DataPositions& pos); + void skip(const DataPositions& pos); + void prune(); + void purge(); + + template + bool eof(Dtype dtype) + { + return get_sub().eof(dtype); + } + template + bool input_eof(int player) + { + return get_sub().input_eof(player); + } + + void setup_extended(DataFieldType field_type, const DataTag& tag, int tuple_size = 0); + template + void get(SubProcessor& proc, DataTag tag, const vector& regs, int vector_size) + { + get_sub().get(proc, tag, regs, vector_size); + } + + DataPositions get_usage() + { + return usage; + } + + template + Sub_Data_Files& get_sub(); + + template + void get(Dtype dtype, T* a) + { + get_sub().get(dtype, a); + } + + template + void get_three(DataFieldType field_type, Dtype dtype, T& a, T& b, T& c) + { + (void)field_type; + get_sub().get_three(dtype, a, b, c); + } + + template + void get_two(DataFieldType field_type, Dtype dtype, T& a, T& b) + { + (void)field_type; + get_sub().get_two(dtype, a, b); + } + + template + void get_one(DataFieldType field_type, Dtype dtype, T& a) + { + (void)field_type; + get_sub().get_one(dtype, a); + } + + template + void get_input(T& a,typename T::clear& x,int i) + { + get_sub().get_input(a, x, i); + } }; template inline -bool Data_Files::eof(Dtype dtype) - { return buffers[dtype].get_buffer(T::field_type()).eof; } +bool Sub_Data_Files::eof(Dtype dtype) + { return buffers[dtype].eof; } template inline -bool Data_Files::input_eof(int player) +bool Sub_Data_Files::input_eof(int player) { if (player == my_num) - return my_input_buffers.get_buffer(T::field_type()).eof; + return my_input_buffers.eof; else - return input_buffers[player].get_buffer(T::field_type()).eof; + return input_buffers[player].eof; +} + +template +inline void Sub_Data_Files::get(Dtype dtype, T* a) +{ + usage.files[T::field_type()][dtype]++; + for (int i = 0; i < DataPositions::tuple_size[dtype]; i++) + buffers[dtype].input(a[i]); +} + +template<> +template<> +inline Sub_Data_Files& Data_Files::get_sub() +{ + return DataFp; +} + +template<> +template<> +inline Sub_Data_Files& Data_Files::get_sub() +{ + return DataF2; +} + +template<> +template<> +inline Sub_Data_Files& Data_Files::get_sub() +{ + return DataFp; +} + +template<> +template<> +inline Sub_Data_Files& Data_Files::get_sub() +{ + return DataF2; } #endif diff --git a/Processor/DummyProtocol.h b/Processor/DummyProtocol.h new file mode 100644 index 00000000..524c6f5f --- /dev/null +++ b/Processor/DummyProtocol.h @@ -0,0 +1,20 @@ +/* + * DummyProtocol.h + * + */ + +#ifndef PROCESSOR_DUMMYPROTOCOL_H_ +#define PROCESSOR_DUMMYPROTOCOL_H_ + +class Player; + +class DummyProtocol +{ +public: + DummyProtocol(Player& P) + { + (void) P; + } +}; + +#endif /* PROCESSOR_DUMMYPROTOCOL_H_ */ diff --git a/Processor/Input.cpp b/Processor/Input.cpp index 98711933..eec0870c 100644 --- a/Processor/Input.cpp +++ b/Processor/Input.cpp @@ -7,15 +7,15 @@ #include "Processor.h" template -InputBase::InputBase(Processor& proc) : +InputBase::InputBase(ArithmeticProcessor& proc) : values_input(0) { buffer.setup(&proc.private_input, -1, proc.private_input_filename); } template -Input::Input(Processor& proc, MAC_Check& mc) : - InputBase(proc), proc(proc), MC(mc), shares(proc.P.num_players()) +Input::Input(SubProcessor>& proc, MAC_Check& mc) : + InputBase(proc.Proc), proc(proc), MC(mc), shares(proc.P.num_players()) { } @@ -81,7 +81,7 @@ template void Input::stop(int player, vector targets) { for (unsigned int i = 0; i < targets.size(); i++) - proc.get_S_ref(targets[i]) = shares[player][i]; + proc.get_S_ref(targets[i]) = shares[player][i]; if (proc.P.my_num() != player) { @@ -92,7 +92,7 @@ void Input::stop(int player, vector targets) this->timer.stop(); for (unsigned int i = 0; i < targets.size(); i++) { - Share& share = proc.get_S_ref(targets[i]); + Share& share = proc.get_S_ref(targets[i]); t.unpack(o); adjust_mac(share, t); } @@ -101,7 +101,4 @@ void Input::stop(int player, vector targets) template class InputBase; template class Input; - -#ifndef REPLICATED template class Input; -#endif diff --git a/Processor/Input.h b/Processor/Input.h index 725ad5ae..8a2bb20a 100644 --- a/Processor/Input.h +++ b/Processor/Input.h @@ -14,7 +14,7 @@ using namespace std; #include "Processor/Buffer.h" #include "Tools/time-func.h" -class Processor; +class ArithmeticProcessor; template class InputBase @@ -26,21 +26,21 @@ protected: public: int values_input; - InputBase(Processor& proc); + InputBase(ArithmeticProcessor& proc); ~InputBase(); }; template class Input : public InputBase { - Processor& proc; + SubProcessor>& proc; MAC_Check& MC; vector< vector< Share > > shares; void adjust_mac(Share& share, T& value); public: - Input(Processor& proc, MAC_Check& mc); + Input(SubProcessor>& proc, MAC_Check& mc); void start(int player, int n_inputs); void stop(int player, vector targets); diff --git a/Processor/InputTuple.h b/Processor/InputTuple.h index 8a3587cd..d81dc8a1 100644 --- a/Processor/InputTuple.h +++ b/Processor/InputTuple.h @@ -10,11 +10,11 @@ template struct InputTuple { - Share share; - T value; + T share; + typename T::clear value; static int size() - { return Share::size() + T::size(); } + { return T::clear::size() + T::size(); } static string type_string() { return T::type_string(); } @@ -22,7 +22,7 @@ struct InputTuple void assign(const char* buffer) { share.assign(buffer); - value.assign(buffer + Share::size()); + value.assign(buffer + T::size()); } }; @@ -30,9 +30,9 @@ struct InputTuple template struct RefInputTuple { - Share& share; - T& value; - RefInputTuple(Share& share, T& value) : share(share), value(value) {} + T& share; + typename T::clear& value; + RefInputTuple(T& share, typename T::clear& value) : share(share), value(value) {} void operator=(InputTuple& other) { share = other.share; value = other.value; } }; diff --git a/Processor/Instruction.cpp b/Processor/Instruction.cpp index b1620411..f7fc6232 100644 --- a/Processor/Instruction.cpp +++ b/Processor/Instruction.cpp @@ -347,29 +347,7 @@ void BaseInstruction::parse_operands(istream& s, int pos) break; case REQBL: n = get_int(s); -#ifdef REPLICATED - if ((int)n < 0 && sint::value_type::value_type::size() * 8 != -(int)n) - { - throw Processor_Error( - "Program compiled for rings of length " + to_string(-(int)n) - + " but VM supports only " - + to_string(sint::value_type::value_type::size() * 8)); - } - else if ((int)n > 0) - { - throw Processor_Error("Program compiled for fields not rings"); - } -#else - if ((int)n > 0 && gfp::pr() < bigint(1) << (n-1)) - { - cout << "Tape requires prime of bit length " << n << endl; - throw invalid_params(); - } - else if ((int)n < 0) - { - throw Processor_Error("Program compiled for rings not fields"); - } -#endif + BaseMachine::s().reqbl(n); break; case GREQBL: n = get_int(s); @@ -520,10 +498,11 @@ ostream& operator<<(ostream& s,const Instruction& instr) } +template #ifndef __clang__ __attribute__((always_inline)) #endif -inline void Instruction::execute(Processor& Proc) const +inline void Instruction::execute(Processor& Proc) const { Proc.PC+=1; @@ -942,7 +921,7 @@ inline void Instruction::execute(Processor& Proc) const break; case MODCI: to_bigint(Proc.temp.aa, Proc.read_Cp(r[1])); - to_gfp(Proc.temp.ansp, bigint::tmp = mpz_fdiv_ui(Proc.temp.aa.get_mpz_t(), n)); + to_gfp(Proc.temp.ansp, Proc.temp.aa2 = mpz_fdiv_ui(Proc.temp.aa.get_mpz_t(), n)); Proc.write_Cp(r[0],Proc.temp.ansp); break; case GMULBITC: @@ -1146,31 +1125,7 @@ inline void Instruction::execute(Processor& Proc) const Proc.temp.ans2.output(Proc.private_output, false); break; case INPUT: - { auto& rr=Proc.temp.rrp; auto& t=Proc.temp.tp; auto& tmp=Proc.temp.tmpp; - Proc.DataF.get_input(Proc.get_Sp_ref(r[0]),rr,n); - octetStream o; - if (n==Proc.P.my_num()) - { auto& xi=Proc.temp.xip; - #ifdef DEBUG - printf("Enter your input : \n"); - #endif - long x; - cin >> x; - t.assign(x); - t.sub(t,rr); - t.pack(o); - Proc.P.send_all(o); - xi.add(t,Proc.get_Sp_ref(r[0]).get_share()); - Proc.get_Sp_ref(r[0]).set_share(xi); - } - else - { Proc.P.receive_player(n,o); - t.unpack(o); - } - tmp.mul(t, Proc.MCp.get_alphai()); - tmp.add(Proc.get_Sp_ref(r[0]).get_mac(),tmp); - Proc.get_Sp_ref(r[0]).set_mac(tmp); - } + sint::Protocol::input(Proc.Procp, n, r); break; case GINPUT: { gf2n& rr=Proc.temp.rr2; gf2n& t=Proc.temp.t2; gf2n& tmp=Proc.temp.tmp2; @@ -1553,10 +1508,10 @@ inline void Instruction::execute(Processor& Proc) const case PRINTFLOATPLAIN: if (Proc.P.my_num() == 0) { - sint::clear v = Proc.read_Cp(start[0]); - sint::clear p = Proc.read_Cp(start[1]); - sint::clear z = Proc.read_Cp(start[2]); - sint::clear s = Proc.read_Cp(start[3]); + typename sint::clear v = Proc.read_Cp(start[0]); + typename sint::clear p = Proc.read_Cp(start[1]); + typename sint::clear z = Proc.read_Cp(start[2]); + typename sint::clear s = Proc.read_Cp(start[3]); to_bigint(Proc.temp.aa, v); // MPIR can't handle more precision in exponent to_signed_bigint(Proc.temp.aa2, p, 31); @@ -1674,11 +1629,11 @@ inline void Instruction::execute(Processor& Proc) const Proc.read_socket_ints(Proc.read_Ci(r[0]), start); break; case READSOCKETC: - Proc.read_socket_vector(Proc.read_Ci(r[0]), start); + Proc.read_socket_vector(Proc.read_Ci(r[0]), start); break; case READSOCKETS: // read shares and MAC shares - Proc.read_socket_private(Proc.read_Ci(r[0]), start, true); + Proc.read_socket_private(Proc.read_Ci(r[0]), start, true); break; case GREADSOCKETS: //Proc.get_S2_ref(r[0]).get_share().pack(socket_octetstream); @@ -1705,11 +1660,11 @@ inline void Instruction::execute(Processor& Proc) const break;*/ case WRITEFILESHARE: // Write shares to file system - Proc.write_shares_to_file(start); + Proc.write_shares_to_file(start); break; case READFILESHARE: // Read shares from file system - Proc.read_shares_from_file(Proc.read_Ci(r[0]), r[1], start); + Proc.read_shares_from_file(Proc.read_Ci(r[0]), r[1], start); break; case PUBINPUT: Proc.public_input >> Proc.get_Ci_ref(r[0]); @@ -1733,10 +1688,10 @@ inline void Instruction::execute(Processor& Proc) const Proc.privateOutput2.stop(n,r[0]); break; case PREP: - Proc.DataF.get(Proc, r, start, size); + Proc.DataF.get(Proc.Procp, r, start, size); return; case GPREP: - Proc.DataF.get(Proc, r, start, size); + Proc.DataF.get(Proc.Proc2, r, start, size); return; default: printf("Case of opcode=%d not implemented yet\n",opcode); @@ -1750,7 +1705,8 @@ inline void Instruction::execute(Processor& Proc) const } } -void Program::execute(Processor& Proc) const +template +void Program::execute(Processor& Proc) const { unsigned int size = p.size(); Proc.PC=0; @@ -1760,3 +1716,6 @@ void Program::execute(Processor& Proc) const while (Proc.PC& Proc) const; +template void Program::execute(Processor& Proc) const; diff --git a/Processor/Instruction.h b/Processor/Instruction.h index 6908a282..9dcceef7 100644 --- a/Processor/Instruction.h +++ b/Processor/Instruction.h @@ -14,8 +14,8 @@ using namespace std; #include "Math/Integer.h" #include "Auth/MAC_Check.h" -class Machine; -class Processor; +template class Machine; +template class Processor; /* * Opcode constants @@ -272,14 +272,15 @@ enum SecrecyType { MAX_SECRECY_TYPE }; +template struct TempVars { gf2n ans2; Share Sans2; - sint::clear ansp; + typename sint::clear ansp; sint Sansp; bigint aa,aa2; // INPUT and LDSI - sint::value_type rrp,tp,tmpp; - sint::clear xip; + typename sint::value_type rrp,tp,tmpp; + typename sint::clear xip; // GINPUT and GLDSI gf2n rr2,t2,tmp2; gf2n xi2; @@ -331,7 +332,8 @@ public: // Execute this instruction, updateing the processor and memory // and streams pointing to the triples etc - void execute(Processor& Proc) const; + template + void execute(Processor& Proc) const; }; diff --git a/Processor/Machine.cpp b/Processor/Machine.cpp index 0d18c7c6..5cbdf2e3 100644 --- a/Processor/Machine.cpp +++ b/Processor/Machine.cpp @@ -13,7 +13,26 @@ #include using namespace std; -Machine::Machine(int my_number, Names& playerNames, +BaseMachine* BaseMachine::singleton = 0; + +BaseMachine& BaseMachine::s() +{ + if (singleton) + return *singleton; + else + throw runtime_error("no singleton"); +} + +BaseMachine::BaseMachine() : nthreads(0) +{ + if (singleton) + throw runtime_error("there can only be one"); + else + singleton = this; +} + +template +Machine::Machine(int my_number, Names& playerNames, string progname_str, string memtype, int lgp, int lg2, bool direct, int opening_sum, bool parallel, bool receive_threads, int max_broadcast) : my_number(my_number), N(playerNames), tn(0), numt(0), usage_unknown(false), @@ -58,9 +77,9 @@ Machine::Machine(int my_number, Names& playerNames, {sprintf(filename, PREP_DIR "Player-Memory-P%d", my_number); ifstream memfile(filename); if (memfile.fail()) { throw file_error(filename); } - Load_Memory(M2,memfile); - Load_Memory(Mp,memfile); - Load_Memory(Mi,memfile); + M2.Load_Memory(memfile); + Mp.Load_Memory(memfile); + Mi.Load_Memory(memfile); memfile.close(); } else if (memtype.compare("old")==0) @@ -105,7 +124,7 @@ Machine::Machine(int my_number, Names& playerNames, tinfo[i].machine=this; // lock for synchronization pthread_mutex_lock(&t_mutex[i]); - pthread_create(&threads[i],NULL,Main_Func,&tinfo[i]); + pthread_create(&threads[i],NULL,thread_info::Main_Func,&tinfo[i]); } // synchronize with clients before starting timer @@ -156,7 +175,8 @@ void BaseMachine::print_compiler() inpf.close(); } -void Machine::load_program(string threadname, string filename) +template +void Machine::load_program(string threadname, string filename) { ifstream pinp(filename); if (pinp.fail()) { throw file_error(filename); } @@ -169,7 +189,8 @@ void Machine::load_program(string threadname, string filename) Mi.minimum_size(INT, progs[i], threadname); } -DataPositions Machine::run_tape(int thread_number, int tape_number, int arg, int line_number) +template +DataPositions Machine::run_tape(int thread_number, int tape_number, int arg, int line_number) { if (thread_number >= (int)tinfo.size()) throw Processor_Error("invalid thread number: " + to_string(thread_number) + "/" + to_string(tinfo.size())); @@ -208,7 +229,8 @@ DataPositions Machine::run_tape(int thread_number, int tape_number, int arg, int } } -void Machine::join_tape(int i) +template +void Machine::join_tape(int i) { join_timer[i].start(); pthread_mutex_lock(&t_mutex[i]); @@ -219,7 +241,8 @@ void Machine::join_tape(int i) join_timer[i].stop(); } -void Machine::run() +template +void Machine::run() { Timer proc_timer(CLOCK_PROCESS_CPUTIME_ID); proc_timer.start(); @@ -328,14 +351,14 @@ void Machine::run() for (int dtype = 0; dtype < N_DTYPE; dtype++) { - cerr << "Num " << Data_Files::dtype_names[dtype] << "\t="; + cerr << "Num " << DataPositions::dtype_names[dtype] << "\t="; for (int field_type = 0; field_type < N_DATA_FIELD_TYPE; field_type++) cerr << " " << pos.files[field_type][dtype]; cerr << endl; } for (int field_type = 0; field_type < N_DATA_FIELD_TYPE; field_type++) { - cerr << "Num " << Data_Files::long_field_names[field_type] << " Inputs\t="; + cerr << "Num " << DataPositions::field_names[field_type] << " Inputs\t="; for (int i = 0; i < N.num_players(); i++) cerr << " " << pos.inputs[i][field_type]; cerr << endl; @@ -385,3 +408,12 @@ void BaseMachine::print_timers() for (map::iterator it = timer.begin(); it != timer.end(); it++) cerr << "Time" << it->first << " = " << it->second.elapsed() << " seconds " << endl; } + +template +void Machine::reqbl(int n) +{ + sint::Protocol::reqbl(n); +} + +template class Machine; +template class Machine; diff --git a/Processor/Machine.h b/Processor/Machine.h index fbf2351c..3015e5b8 100644 --- a/Processor/Machine.h +++ b/Processor/Machine.h @@ -22,6 +22,8 @@ using namespace std; class BaseMachine { protected: + static BaseMachine* singleton; + std::map timer; ifstream inpf; @@ -34,6 +36,9 @@ public: string progname; int nthreads; + static BaseMachine& s(); + + BaseMachine(); virtual ~BaseMachine() {} void load_schedule(string progname); @@ -42,8 +47,11 @@ public: void time(); void start(int n); void stop(int n); + + virtual void reqbl(int n) { (void)n; } }; +template class Machine : public BaseMachine { /* The mutex's lock the C-threads and then only release @@ -52,7 +60,7 @@ class Machine : public BaseMachine * MPC thread releases the mutex */ - vector tinfo; + vector> tinfo; vector threads; int my_number; @@ -97,6 +105,11 @@ class Machine : public BaseMachine DataPositions run_tape(int thread_number, int tape_number, int arg, int line_number); void join_tape(int thread_number); void run(); + + // Only for Player-Demo.cpp + Machine(): N(*(new Names())) {} + + void reqbl(int n); }; #endif /* MACHINE_H_ */ diff --git a/Processor/Memory.cpp b/Processor/Memory.cpp index e23e41bb..65814fe4 100644 --- a/Processor/Memory.cpp +++ b/Processor/Memory.cpp @@ -107,8 +107,10 @@ istream& operator>>(istream& s,Memory& M) template -void Load_Memory(Memory& M,ifstream& inpf) +void Memory::Load_Memory(ifstream& inpf) { + Memory& M = *this; + int a; typename T::clear val; T S; @@ -140,18 +142,17 @@ void Load_Memory(Memory& M,ifstream& inpf) } } -template class Memory; +template class Memory; template class Memory; template class Memory; +template class Memory; -template istream& operator>>(istream& s,Memory& M); +template istream& operator>>(istream& s,Memory& M); template istream& operator>>(istream& s,Memory& M); template istream& operator>>(istream& s,Memory& M); +template istream& operator>>(istream& s,Memory& M); -template ostream& operator<<(ostream& s,const Memory& M); +template ostream& operator<<(ostream& s,const Memory& M); template ostream& operator<<(ostream& s,const Memory& M); template ostream& operator<<(ostream& s,const Memory& M); - -template void Load_Memory(Memory& M,ifstream& inpf); -template void Load_Memory(Memory& M,ifstream& inpf); -template void Load_Memory(Memory& M,ifstream& inpf); +template ostream& operator<<(ostream& s,const Memory& M); diff --git a/Processor/Memory.h b/Processor/Memory.h index 109afe23..fd77050f 100644 --- a/Processor/Memory.h +++ b/Processor/Memory.h @@ -76,23 +76,21 @@ class Memory friend ostream& operator<< <>(ostream& s,const Memory& M); friend istream& operator>> <>(istream& s,Memory& M); + /* This function loads a un-shared global memory from disk and + * produces the memory + * + * The global unshared memory is of the form + * sz <- Size + * n val <- Clear values + * n val <- Clear values + * -1 -1 <- End of clear values + * n val <- Shared values + * n val <- Shared values + * -1 -1 + */ + void Load_Memory(ifstream& inpf); + }; - -/* This function loads a un-shared global memory from disk and - * produces the memory - * - * The global unshared memory is of the form - * sz <- Size - * n val <- Clear values - * n val <- Clear values - * -1 -1 <- End of clear values - * n val <- Shared values - * n val <- Shared values - * -1 -1 - */ -template -void Load_Memory(Memory& M,ifstream& inpf); - #endif diff --git a/Processor/Online-Thread.cpp b/Processor/Online-Thread.cpp index 575679c5..3ba5f7b3 100644 --- a/Processor/Online-Thread.cpp +++ b/Processor/Online-Thread.cpp @@ -12,10 +12,11 @@ using namespace std; +template void* Sub_Main_Func(void* ptr) { - thread_info *tinfo=(thread_info *) ptr; - Machine& machine=*(tinfo->machine); + thread_info *tinfo=(thread_info *) ptr; + Machine& machine=*(tinfo->machine); vector& t_mutex = machine.t_mutex; vector& client_ready = machine.client_ready; vector& server_ready = machine.server_ready; @@ -37,18 +38,17 @@ void* Sub_Main_Func(void* ptr) Player& P = *player; fprintf(stderr, "\tSet up player in thread %d\n",num); - Data_Files DataF(P.my_num(),P.num_players(),machine.prep_dir_prefix); + Data_Files DataF(P.my_num(),P.num_players(),machine.prep_dir_prefix); MAC_Check* MC2; - sint::MAC_Check* MCp; + typename sint::MAC_Check* MCp; // Use MAC_Check instead for more than 10000 openings at once if (machine.direct) { cerr << "Using direct communication. If computation stalls, use -m when compiling." << endl; MC2 = new Direct_MAC_Check(*(tinfo->alpha2i),*(tinfo->Nms), num); - //MCp = new Direct_MAC_Check(*(tinfo->alphapi),*(tinfo->Nms), num); - throw not_implemented(); + MCp = new typename sint::Direct_MC(*(tinfo->alphapi),*(tinfo->Nms), num); } else if (machine.parallel) { @@ -61,11 +61,11 @@ void* Sub_Main_Func(void* ptr) { cerr << "Using indirect communication." << endl; MC2 = new MAC_Check(*(tinfo->alpha2i), machine.opening_sum, machine.max_broadcast); - MCp = new sint::MAC_Check(*(tinfo->alphapi), machine.opening_sum, machine.max_broadcast); + MCp = new typename sint::MAC_Check(*(tinfo->alphapi), machine.opening_sum, machine.max_broadcast); } // Allocate memory for first program before starting the clock - Processor Proc(tinfo->thread_num,DataF,P,*MC2,*MCp,machine,progs[0]); + Processor Proc(tinfo->thread_num,DataF,P,*MC2,*MCp,machine,progs[0]); Share a,b,c; bool flag=true; @@ -168,18 +168,19 @@ void* Sub_Main_Func(void* ptr) } -void* Main_Func(void* ptr) +template +void* thread_info::Main_Func(void* ptr) { #ifndef INSECURE try #endif { - Sub_Main_Func(ptr); + Sub_Main_Func(ptr); } #ifndef INSECURE catch (...) { - thread_info* ti = (thread_info*)ptr; + thread_info* ti = (thread_info*)ptr; purge_preprocessing(*ti->Nms, ti->machine->prep_dir_prefix); throw; @@ -189,12 +190,13 @@ void* Main_Func(void* ptr) } -void purge_preprocessing(Names& N, string prep_dir) +template +void thread_info::purge_preprocessing(Names& N, string prep_dir) { cerr << "Purging preprocessed data because something is wrong" << endl; try { - Data_Files df(N, prep_dir); + Data_Files df(N, prep_dir); df.purge(); } catch(...) @@ -203,3 +205,7 @@ void purge_preprocessing(Names& N, string prep_dir) << "SECURITY FAILURE; YOU ARE ON YOUR OWN NOW!" << endl; } } + + +template class thread_info; +template class thread_info; diff --git a/Processor/Online-Thread.h b/Processor/Online-Thread.h index 5ad8b806..c4f83702 100644 --- a/Processor/Online-Thread.h +++ b/Processor/Online-Thread.h @@ -10,8 +10,9 @@ #include using namespace std; -class Machine; +template class Machine; +template class thread_info { public: @@ -30,12 +31,12 @@ class thread_info // Integer arg (optional) int arg; - Machine* machine; + Machine* machine; + + static void* Main_Func(void *ptr); + + static void purge_preprocessing(Names& N, string prep_dir); }; -void* Main_Func(void *ptr); - -void purge_preprocessing(Names& N, string prep_dir); - #endif diff --git a/Processor/PrivateOutput.cpp b/Processor/PrivateOutput.cpp index c9838ade..8eec4990 100644 --- a/Processor/PrivateOutput.cpp +++ b/Processor/PrivateOutput.cpp @@ -10,8 +10,8 @@ template void PrivateOutput::start(int player, int target, int source) { T mask; - proc.DataF.get_input(proc.get_S_ref(target), mask, player); - proc.get_S_ref(target).add(proc.get_S_ref(source)); + proc.DataF.get_input(proc.get_S_ref(target), mask, player); + proc.get_S_ref(target).add(proc.get_S_ref(source)); if (player == proc.P.my_num()) masks.push_back(mask); @@ -23,14 +23,11 @@ void PrivateOutput::stop(int player, int source) if (player == proc.P.my_num()) { T value; - value.sub(proc.get_C_ref(source), masks.front()); - value.output(proc.private_output, false); + value.sub(proc.get_C_ref(source), masks.front()); + value.output(proc.Proc.private_output, false); masks.pop_front(); } } template class PrivateOutput; - -#ifndef REPLICATED template class PrivateOutput; -#endif diff --git a/Processor/PrivateOutput.h b/Processor/PrivateOutput.h index ce8c4975..40952744 100644 --- a/Processor/PrivateOutput.h +++ b/Processor/PrivateOutput.h @@ -11,16 +11,14 @@ using namespace std; #include "Math/Share.h" -class Processor; - template class PrivateOutput { - Processor& proc; + SubProcessor>& proc; deque masks; public: - PrivateOutput(Processor& proc) : proc(proc) { }; + PrivateOutput(SubProcessor>& proc) : proc(proc) { }; void start(int player, int target, int source); void stop(int player, int source); diff --git a/Processor/Processor.cpp b/Processor/Processor.cpp index a552634f..fb622d0d 100644 --- a/Processor/Processor.cpp +++ b/Processor/Processor.cpp @@ -8,23 +8,25 @@ #include template -SubProcessor::SubProcessor(Processor& Proc, typename T::MAC_Check& MC) : - Proc(Proc), MC(MC), P(Proc.P) +SubProcessor::SubProcessor(ArithmeticProcessor& Proc, typename T::MAC_Check& MC, + Sub_Data_Files& DataF, Player& P) : + Proc(Proc), MC(MC), P(P), DataF(DataF), protocol(P) { } -Processor::Processor(int thread_num,Data_Files& DataF,Player& P, - MAC_Check& MC2,sint::MAC_Check& MCp,Machine& machine, +template +Processor::Processor(int thread_num,Data_Files& DataF,Player& P, + MAC_Check& MC2,typename sint::MAC_Check& MCp,Machine& machine, const Program& program) : thread_num(thread_num),DataF(DataF),P(P),MC2(MC2),MCp(MCp),machine(machine), - private_input_filename(get_filename(PREP_DIR "Private-Input-",true)), - Proc2(*this,MC2),Procp(*this,MCp), - input2(*this,MC2),inputp(*this,MCp),privateOutput2(*this),privateOutputp(*this),sent(0),rounds(0), + Proc2(*this,MC2,DataF.DataF2,P),Procp(*this,MCp,DataF.DataFp,P), + input2(Proc2,MC2),inputp(Procp,MCp),privateOutput2(Proc2),privateOutputp(Procp), external_clients(ExternalClients(P.my_num(), DataF.prep_data_dir)),binary_file_io(Binary_File_IO()) { reset(program,0); public_input.open(get_filename("Programs/Public-Input/",false).c_str()); + private_input_filename = (get_filename(PREP_DIR "Private-Input-",true)); private_input.open(private_input_filename.c_str()); public_output.open(get_filename(PREP_DIR "Public-Output-",true).c_str(), ios_base::out); private_output.open(get_filename(PREP_DIR "Private-Output-",true).c_str(), ios_base::out); @@ -33,12 +35,14 @@ Processor::Processor(int thread_num,Data_Files& DataF,Player& P, } -Processor::~Processor() +template +Processor::~Processor() { cerr << "Sent " << sent << " elements in " << rounds << " rounds" << endl; } -string Processor::get_filename(const char* prefix, bool use_number) +template +string Processor::get_filename(const char* prefix, bool use_number) { stringstream filename; filename << prefix; @@ -53,7 +57,8 @@ string Processor::get_filename(const char* prefix, bool use_number) } -void Processor::reset(const Program& program,int arg) +template +void Processor::reset(const Program& program,int arg) { reg_max2 = program.num_reg(GF2N); reg_maxp = program.num_reg(MODP); @@ -81,7 +86,8 @@ void Processor::reset(const Program& program,int arg) // If message_type is > 0, send message_type in bytes 0 - 3, to allow an external client to // determine the data structure being sent in a message. // Encryption is enabled if key material (for DH Auth Encryption and/or STS protocol) has been already setup. -void Processor::write_socket(const RegType reg_type, const SecrecyType secrecy_type, const bool send_macs, +template +void Processor::write_socket(const RegType reg_type, const SecrecyType secrecy_type, const bool send_macs, int socket_id, int message_type, const vector& registers) { if (socket_id >= (int)external_clients.external_client_sockets.size()) @@ -101,13 +107,11 @@ void Processor::write_socket(const RegType reg_type, const SecrecyType secrecy_t { if (reg_type == MODP && secrecy_type == SECRET) { // Send vector of secret shares and optionally macs - get_S_ref(registers[i]).get_share().pack(socket_stream); - if (send_macs) - get_S_ref(registers[i]).get_mac().pack(socket_stream); + get_Sp_ref(registers[i]).pack(socket_stream, send_macs); } else if (reg_type == MODP && secrecy_type == CLEAR) { // Send vector of clear public field elements - get_C_ref(registers[i]).pack(socket_stream); + get_Cp_ref(registers[i]).pack(socket_stream); } else if (reg_type == INT && secrecy_type == CLEAR) { // Send vector of 32-bit clear ints @@ -140,7 +144,8 @@ void Processor::write_socket(const RegType reg_type, const SecrecyType secrecy_t // Receive vector of 32-bit clear ints -void Processor::read_socket_ints(int client_id, const vector& registers) +template +void Processor::read_socket_ints(int client_id, const vector& registers) { if (client_id >= (int)external_clients.external_client_sockets.size()) { @@ -161,8 +166,8 @@ void Processor::read_socket_ints(int client_id, const vector& registers) } // Receive vector of public field elements -template -void Processor::read_socket_vector(int client_id, const vector& registers) +template +void Processor::read_socket_vector(int client_id, const vector& registers) { if (client_id >= (int)external_clients.external_client_sockets.size()) { @@ -176,13 +181,13 @@ void Processor::read_socket_vector(int client_id, const vector& registers) maybe_decrypt_sequence(client_id); for (int i = 0; i < m; i++) { - get_C_ref(registers[i]).unpack(socket_stream); + get_Cp_ref(registers[i]).unpack(socket_stream); } } // Receive vector of field element shares over private channel -template -void Processor::read_socket_private(int client_id, const vector& registers, bool read_macs) +template +void Processor::read_socket_private(int client_id, const vector& registers, bool read_macs) { if (client_id >= (int)external_clients.external_client_sockets.size()) { @@ -201,18 +206,13 @@ void Processor::read_socket_private(int client_id, const vector& registers, } for (int i = 0; i < m; i++) { - temp.ansp.unpack(socket_stream); - get_Sp_ref(registers[i]).set_share(temp.ansp); - if (read_macs) - { - temp.ansp.unpack(socket_stream); - get_Sp_ref(registers[i]).set_mac(temp.ansp); - } + get_Sp_ref(registers[i]).unpack(socket_stream, read_macs); } } // Read socket for client public key as 8 ints, calculate session key for client. -void Processor::read_client_public_key(int client_id, const vector& registers) { +template +void Processor::read_client_public_key(int client_id, const vector& registers) { read_socket_ints(client_id, registers); @@ -225,7 +225,8 @@ void Processor::read_client_public_key(int client_id, const vector& registe external_clients.generate_session_key_for_client(client_id, client_public_key); } -void Processor::init_secure_socket_internal(int client_id, const vector& registers) { +template +void Processor::init_secure_socket_internal(int client_id, const vector& registers) { external_clients.symmetric_client_commsec_send_keys.erase(client_id); external_clients.symmetric_client_commsec_recv_keys.erase(client_id); unsigned char client_public_bytes[crypto_sign_PUBLICKEYBYTES]; @@ -275,7 +276,8 @@ void Processor::init_secure_socket_internal(int client_id, const vector& re external_clients.symmetric_client_commsec_recv_keys[client_id] = make_pair(recvKey,0); } -void Processor::init_secure_socket(int client_id, const vector& registers) { +template +void Processor::init_secure_socket(int client_id, const vector& registers) { try { init_secure_socket_internal(client_id, registers); @@ -285,7 +287,8 @@ void Processor::init_secure_socket(int client_id, const vector& registers) } } -void Processor::resp_secure_socket(int client_id, const vector& registers) { +template +void Processor::resp_secure_socket(int client_id, const vector& registers) { try { resp_secure_socket_internal(client_id, registers); } catch (char const *e) { @@ -294,7 +297,8 @@ void Processor::resp_secure_socket(int client_id, const vector& registers) } } -void Processor::resp_secure_socket_internal(int client_id, const vector& registers) { +template +void Processor::resp_secure_socket_internal(int client_id, const vector& registers) { external_clients.symmetric_client_commsec_send_keys.erase(client_id); external_clients.symmetric_client_commsec_recv_keys.erase(client_id); unsigned char client_public_bytes[crypto_sign_PUBLICKEYBYTES]; @@ -347,19 +351,19 @@ void Processor::resp_secure_socket_internal(int client_id, const vector& re // Read share data from a file starting at file_pos until registers filled. // file_pos_register is written with new file position (-1 is eof). // Tolerent to no file if no shares yet persisted. -template -void Processor::read_shares_from_file(int start_file_posn, int end_file_pos_register, const vector& data_registers) { +template +void Processor::read_shares_from_file(int start_file_posn, int end_file_pos_register, const vector& data_registers) { string filename; filename = "Persistence/Transactions-P" + to_string(P.my_num()) + ".data"; unsigned int size = data_registers.size(); - vector< T > outbuf(size); + vector< sint > outbuf(size); int end_file_posn = start_file_posn; try { - binary_file_io.read_from_file(filename, outbuf, start_file_posn, end_file_posn); + binary_file_io.read_from_file(filename, outbuf, start_file_posn, end_file_posn); for (unsigned int i = 0; i < size; i++) { @@ -375,18 +379,18 @@ void Processor::read_shares_from_file(int start_file_posn, int end_file_pos_regi } // Append share data in data_registers to end of file. Expects Persistence directory to exist. -template -void Processor::write_shares_to_file(const vector& data_registers) { +template +void Processor::write_shares_to_file(const vector& data_registers) { string filename; filename = "Persistence/Transactions-P" + to_string(P.my_num()) + ".data"; unsigned int size = data_registers.size(); - vector< Share > inpbuf (size); + vector< sint > inpbuf (size); for (unsigned int i = 0; i < size; i++) { - inpbuf[i] = get_S_ref(data_registers[i]); + inpbuf[i] = get_Sp_ref(data_registers[i]); } binary_file_io.write_to_file(filename, inpbuf); @@ -469,7 +473,8 @@ void SubProcessor::POpen(const vector& reg, const Player& P, POpen_Stop(dest, P, size); } -ostream& operator<<(ostream& s,const Processor& P) +template +ostream& operator<<(ostream& s,const Processor& P) { s << "Processor State" << endl; s << "Char 2 Registers" << endl; @@ -494,7 +499,8 @@ ostream& operator<<(ostream& s,const Processor& P) return s; } -void Processor::maybe_decrypt_sequence(int client_id) +template +void Processor::maybe_decrypt_sequence(int client_id) { map,uint64_t> >::iterator it_cs = external_clients.symmetric_client_commsec_recv_keys.find(client_id); if (it_cs != external_clients.symmetric_client_commsec_recv_keys.end()) @@ -504,7 +510,8 @@ void Processor::maybe_decrypt_sequence(int client_id) } } -void Processor::maybe_encrypt_sequence(int client_id) +template +void Processor::maybe_encrypt_sequence(int client_id) { map,uint64_t> >::iterator it_cs = external_clients.symmetric_client_commsec_send_keys.find(client_id); if (it_cs != external_clients.symmetric_client_commsec_send_keys.end()) @@ -515,9 +522,8 @@ void Processor::maybe_encrypt_sequence(int client_id) } template class SubProcessor; -template class SubProcessor; +template class SubProcessor; +template class SubProcessor; -template void Processor::read_socket_private(int client_id, const vector& registers, bool send_macs); -template void Processor::read_socket_vector(int client_id, const vector& registers); -template void Processor::read_shares_from_file(int start_file_pos, int end_file_pos_register, const vector& data_registers); -template void Processor::write_shares_to_file(const vector& data_registers); +template class Processor; +template class Processor; diff --git a/Processor/Processor.h b/Processor/Processor.h index 92e282df..13744704 100644 --- a/Processor/Processor.h +++ b/Processor/Processor.h @@ -65,18 +65,20 @@ class SubProcessor void resize(int size) { C.resize(size); S.resize(size); } - friend class Processor; + template friend class Processor; template friend class SPDZ; template friend class Replicated; public: - Processor& Proc; + ArithmeticProcessor& Proc; typename T::MAC_Check& MC; Player& P; + Sub_Data_Files& DataF; typename T::Protocol protocol; - SubProcessor(Processor& Proc, typename T::MAC_Check& MC); + SubProcessor(ArithmeticProcessor& Proc, typename T::MAC_Check& MC, + Sub_Data_Files& DataF, Player& P); // Access to PO (via calls to POpen start/stop) void POpen_Start(const vector& reg,const Player& P,int size); @@ -84,9 +86,37 @@ public: void POpen(const vector& reg,const Player& P,int size); void muls(const vector& reg,const Player& P,int size); + + T& get_S_ref(int i) + { + return S[i]; + } + + typename T::clear& get_C_ref(int i) + { + return C[i]; + } }; -class Processor : public ProcessorBase +class ArithmeticProcessor : public ProcessorBase +{ +public: + PRNG secure_prng; + + string private_input_filename; + + ifstream private_input; + ifstream public_input; + ofstream public_output; + ofstream private_output; + + int sent, rounds; + + ArithmeticProcessor() : sent(0), rounds(0) {} +}; + +template +class Processor : public ArithmeticProcessor { vector Ci; @@ -113,47 +143,39 @@ class Processor : public ProcessorBase vector& get_PO(); public: - Data_Files& DataF; + Data_Files& DataF; Player& P; MAC_Check& MC2; - sint::MAC_Check& MCp; - Machine& machine; - - string private_input_filename; + typename sint::MAC_Check& MCp; + Machine& machine; SubProcessor Proc2; SubProcessor Procp; Input input2; - sint::Input inputp; + typename sint::Input inputp; PrivateOutput privateOutput2; - sint::PrivateOutput privateOutputp; - - ifstream public_input; - ifstream private_input; - ofstream public_output; - ofstream private_output; + typename sint::PrivateOutput privateOutputp; unsigned int PC; - TempVars temp; - PRNG shared_prng, secure_prng; + TempVars temp; - int sent, rounds; + PRNG shared_prng; ExternalClients external_clients; Binary_File_IO binary_file_io; // avoid re-computation of expensive division - map inverses2m; + map inverses2m; static const int reg_bytes = 4; void reset(const Program& program,int arg); // Reset the state of the processor string get_filename(const char* basename, bool use_number); - Processor(int thread_num,Data_Files& DataF,Player& P, - MAC_Check& MC2,sint::MAC_Check& MCp,Machine& machine, + Processor(int thread_num,Data_Files& DataF,Player& P, + MAC_Check& MC2,typename sint::MAC_Check& MCp,Machine& machine, const Program& program); ~Processor(); @@ -244,15 +266,15 @@ class Processor : public ProcessorBase void write_S2(int i,const Share & x) { Proc2.S[i]=x; } - const sint::clear& read_Cp(int i) const + const typename sint::clear& read_Cp(int i) const { return Procp.C[i]; } const sint & read_Sp(int i) const { return Procp.S[i]; } - sint::clear& get_Cp_ref(int i) + typename sint::clear& get_Cp_ref(int i) { return Procp.C[i]; } sint & get_Sp_ref(int i) { return Procp.S[i]; } - void write_Cp(int i,const sint::clear& x) + void write_Cp(int i,const typename sint::clear& x) { Procp.C[i]=x; } void write_Sp(int i,const sint & x) { Procp.S[i]=x; } @@ -265,10 +287,6 @@ class Processor : public ProcessorBase { Ci[i]=x; } #endif - // Template-based access - template Share& get_S_ref(int i); - template T& get_C_ref(int i); - // Access to external client sockets for reading clear/shared data void read_socket_ints(int client_id, const vector& registers); // Setup client public key @@ -281,19 +299,16 @@ class Processor : public ProcessorBase void write_socket(const RegType reg_type, const SecrecyType secrecy_type, const bool send_macs, int socket_id, int message_type, const vector& registers); - template void read_socket_vector(int client_id, const vector& registers); - template void read_socket_private(int client_id, const vector& registers, bool send_macs); // Read and write secret numeric data to file (name hardcoded at present) - template void read_shares_from_file(int start_file_pos, int end_file_pos_register, const vector& data_registers); - template void write_shares_to_file(const vector& data_registers); // Print the processor state - friend ostream& operator<<(ostream& s,const Processor& P); + template + friend ostream& operator<<(ostream& s,const Processor& P); private: void maybe_decrypt_sequence(int client_id); @@ -303,10 +318,5 @@ class Processor : public ProcessorBase template friend class SubProcessor; }; -template<> inline Share& Processor::get_S_ref(int i) { return get_S2_ref(i); } -template<> inline gf2n& Processor::get_C_ref(int i) { return get_C2_ref(i); } -template<> inline sint& Processor::get_S_ref(int i) { return get_Sp_ref(i); } -template<> inline sint::clear& Processor::get_C_ref(int i) { return get_Cp_ref(i); } - #endif diff --git a/Processor/Program.h b/Processor/Program.h index c02d4d00..8b8cb6d2 100644 --- a/Processor/Program.h +++ b/Processor/Program.h @@ -4,7 +4,7 @@ #include "Processor/Instruction.h" #include "Processor/Data_Files.h" -class Machine; +template class Machine; /* A program is a vector of instructions */ @@ -52,7 +52,8 @@ class Program // Execute this program, updateing the processor and memory // and streams pointing to the triples etc - void execute(Processor& Proc) const; + template + void execute(Processor& Proc) const; }; diff --git a/Processor/Replicated.cpp b/Processor/Replicated.cpp index f78b18c7..27a33e52 100644 --- a/Processor/Replicated.cpp +++ b/Processor/Replicated.cpp @@ -8,11 +8,23 @@ #include "Math/FixedVec.h" #include "Math/Integer.h" #include "Tools/benchmarking.h" +#include "GC/ReplicatedSecret.h" template -Replicated::Replicated() : counter(0) +Replicated::Replicated(Player& P) : ReplicatedBase(P), counter(0) +{ +} + +ReplicatedBase::ReplicatedBase(Player& P) { insecure("unencrypted communication"); + + shared_prngs[0].ReSeed(); + octetStream os; + os.append(shared_prngs[0].get_seed(), SEED_SIZE); + P.send_relative(1, os); + P.receive_relative(-1, os); + shared_prngs[1].SetSeed(os.get_data()); } template @@ -23,7 +35,7 @@ inline Replicated::~Replicated() template void Replicated::muls(const vector& reg, - SubProcessor >& proc, ReplicatedMC& MC, int size) + SubProcessor& proc, ReplicatedMC& MC, int size) { (void)MC; assert(T::length == 2); @@ -37,30 +49,53 @@ void Replicated::muls(const vector& reg, for (int i = 0; i < n; i++) for (int j = 0; j < size; j++) { - auto& x = proc.S[reg[3 * i + 1] + j].get_share(); - auto& y = proc.S[reg[3 * i + 2] + j].get_share(); - auto add_share = x[0] * y.sum() + x[1] * y[0]; + auto& x = proc.S[reg[3 * i + 1] + j]; + auto& y = proc.S[reg[3 * i + 2] + j]; + typename T::value_type add_share = x[0] * y.sum() + x[1] * y[0]; + typename T::value_type tmp[2]; + for (int i = 0; i < 2; i++) + tmp[i].randomize(shared_prngs[i]); + add_share += tmp[0] - tmp[1]; + add_share.pack(os[0]); auto& result = results[i * size + j]; - result.randomize_to_sum(add_share, proc.Proc.secure_prng); - for (int k = 0; k < 2; k++) - result[k].pack(os[k]); + result[0] = add_share; } - proc.P.send_relative(os); - proc.P.receive_relative(os); + proc.P.send_relative(1, os[0]); + proc.P.receive_relative(- 1, os[0]); for (int i = 0; i < n; i++) for (int j = 0; j < size; j++) { auto& result = results[i * size + j]; - for (int k = 0; k < 2; k++) - { - typename T::value_type tmp; - tmp.unpack(os[k]); - result[k] += tmp; - } - proc.S[reg[3 * i] + j].set_share(result); + result[1].unpack(os[0]); + proc.S[reg[3 * i] + j] = result; } counter += n * size; } -template class Replicated >; +template<> +void Replicated::reqbl(int n) +{ + if ((int)n < 0 && Integer::size() * 8 != -(int)n) + { + throw Processor_Error( + "Program compiled for rings of length " + to_string(-(int)n) + + " but VM supports only " + + to_string(Integer::size() * 8)); + } + else if ((int)n > 0) + { + throw Processor_Error("Program compiled for fields not rings"); + } +} + +template +inline void Replicated::input(SubProcessor& Proc, int n, int* r) +{ + (void)Proc; + (void)n; + (void)r; + throw not_implemented(); +} + +template class Replicated; diff --git a/Processor/Replicated.h b/Processor/Replicated.h index 5311b19a..81932f37 100644 --- a/Processor/Replicated.h +++ b/Processor/Replicated.h @@ -11,15 +11,26 @@ using namespace std; #include "Tools/octetStream.h" +#include "Tools/random.h" +#include "Networking/Player.h" template class SubProcessor; template class ReplicatedMC; template class ReplicatedInput; template class ReplicatedPrivateOutput; template class Share; +template class Processor; + +class ReplicatedBase +{ +public: + PRNG shared_prngs[2]; + + ReplicatedBase(Player& P); +}; template -class Replicated +class Replicated : ReplicatedBase { vector os; vector results; @@ -30,10 +41,10 @@ public: typedef ReplicatedInput Input; typedef ReplicatedPrivateOutput PrivateOutput; - Replicated(); + Replicated(Player& P); ~Replicated(); - static void assign(T& share, const typename T::value_type& value, int my_num) + static void assign(T& share, const typename T::clear& value, int my_num) { assert(T::length == 2); share.assign_zero(); @@ -41,8 +52,12 @@ public: share[my_num] = value; } - void muls(const vector& reg, SubProcessor >& proc, ReplicatedMC& MC, + void muls(const vector& reg, SubProcessor& proc, ReplicatedMC& MC, int size); + + static void reqbl(int n); + + static void input(SubProcessor& Proc, int n, int* r); }; #endif /* PROCESSOR_REPLICATED_H_ */ diff --git a/Processor/ReplicatedInput.cpp b/Processor/ReplicatedInput.cpp index a778dd40..d107f3a5 100644 --- a/Processor/ReplicatedInput.cpp +++ b/Processor/ReplicatedInput.cpp @@ -22,7 +22,7 @@ void ReplicatedInput::start(int player, int n_inputs) typename T::value_type t; this->buffer.input(t); T& my_share = shares[i]; - my_share[0].randomize(proc.secure_prng); + my_share[0].randomize(proc.Proc.secure_prng); my_share[1] = t - my_share[0]; for (int j = 0; j < 2; j++) { @@ -41,7 +41,7 @@ void ReplicatedInput::stop(int player, vector targets) if (proc.P.my_num() == player) { for (unsigned int i = 0; i < targets.size(); i++) - proc.get_S_ref(targets[i]).set_share(shares[i]); + proc.get_S_ref(targets[i]) = shares[i]; } else { @@ -57,11 +57,9 @@ void ReplicatedInput::stop(int player, vector targets) T share; share[j] = t; share[1 - j] = 0; - this->proc.template get_S_ref(targets[i]).set_share(share); + this->proc.get_S_ref(targets[i]) = share; } } } -#ifdef REPLICATED -template class ReplicatedInput >; -#endif +template class ReplicatedInput; diff --git a/Processor/ReplicatedInput.h b/Processor/ReplicatedInput.h index 9541ff2b..bda52ea7 100644 --- a/Processor/ReplicatedInput.h +++ b/Processor/ReplicatedInput.h @@ -9,16 +9,18 @@ #include "Auth/ReplicatedMC.h" #include "Input.h" -class Processor; - template class ReplicatedInput : public InputBase { - Processor& proc; + SubProcessor& proc; vector shares; public: - ReplicatedInput(Processor& proc, ReplicatedMC& MC) : InputBase(proc), proc(proc) { (void)MC; } + ReplicatedInput(SubProcessor& proc, ReplicatedMC& MC) : + InputBase(proc.Proc), proc(proc) + { + (void) MC; + } void start(int player, int n_inputs); void stop(int player, vector targets); diff --git a/Processor/ReplicatedPrivateOutput.cpp b/Processor/ReplicatedPrivateOutput.cpp index 7a398fd2..0d41a457 100644 --- a/Processor/ReplicatedPrivateOutput.cpp +++ b/Processor/ReplicatedPrivateOutput.cpp @@ -4,14 +4,23 @@ */ #include "ReplicatedPrivateOutput.h" +#include "Processor.h" #include "Math/FixedVec.h" #include "Math/Integer.h" +template +inline ReplicatedPrivateOutput::ReplicatedPrivateOutput( + SubProcessor& proc) : + proc(proc) +{ +} + template void ReplicatedPrivateOutput::start(int player, int target, int source) { (void)player, (void)target, (void)source; + throw not_implemented(); } template @@ -20,4 +29,4 @@ void ReplicatedPrivateOutput::stop(int player, int source) (void)player, (void)source; } -template class ReplicatedPrivateOutput >; +template class ReplicatedPrivateOutput; diff --git a/Processor/ReplicatedPrivateOutput.h b/Processor/ReplicatedPrivateOutput.h index e87fb530..0fdcb87b 100644 --- a/Processor/ReplicatedPrivateOutput.h +++ b/Processor/ReplicatedPrivateOutput.h @@ -6,15 +6,18 @@ #ifndef PROCESSOR_REPLICATEDPRIVATEOUTPUT_H_ #define PROCESSOR_REPLICATEDPRIVATEOUTPUT_H_ -class Processor; +template +class SubProcessor; +template +class Share; template class ReplicatedPrivateOutput { - Processor& proc; + SubProcessor& proc; public: - ReplicatedPrivateOutput(Processor& proc) : proc(proc) {} + ReplicatedPrivateOutput(SubProcessor& proc); void start(int player, int target, int source); void stop(int player, int source); diff --git a/Processor/SPDZ.cpp b/Processor/SPDZ.cpp index d5cebd9f..101eceef 100644 --- a/Processor/SPDZ.cpp +++ b/Processor/SPDZ.cpp @@ -21,7 +21,7 @@ void SPDZ::muls(const vector& reg, SubProcessor >& proc, MAC_Ch for (int i = 0; i < n; i++) for (int j = 0; j < size; j++) { - proc.Proc.DataF.get(DATA_TRIPLE, triples[i][j]); + proc.DataF.get(DATA_TRIPLE, triples[i][j]); for (int k = 0; k < 2; k++) shares.push_back(proc.S[reg[i * 3 + k + 1] + j] - triples[i][j][k]); } @@ -46,8 +46,50 @@ void SPDZ::muls(const vector& reg, SubProcessor >& proc, MAC_Ch } } -#ifndef REPLICATED -template class SPDZ; -#endif +template<> +void SPDZ::reqbl(int n) +{ + if ((int)n > 0 && gfp::pr() < bigint(1) << (n-1)) + { + cout << "Tape requires prime of bit length " << n << endl; + throw invalid_params(); + } + else if ((int)n < 0) + { + throw Processor_Error("Program compiled for rings not fields"); + } +} +template +inline void SPDZ::input(SubProcessor>& Proc, int n, int* r) +{ + T rr, t, tmp; + Proc.DataF.get_input(Proc.get_S_ref(r[0]),rr,n); + octetStream o; + if (n==Proc.P.my_num()) + { + T xi; +#ifdef DEBUG + printf("Enter your input : \n"); +#endif + long x; + cin >> x; + t.assign(x); + t.sub(t,rr); + t.pack(o); + Proc.P.send_all(o); + xi.add(t,Proc.get_S_ref(r[0]).get_share()); + Proc.get_S_ref(r[0]).set_share(xi); + } + else + { + Proc.P.receive_player(n,o); + t.unpack(o); + } + tmp.mul(t, Proc.MC.get_alphai()); + tmp.add(Proc.get_S_ref(r[0]).get_mac(),tmp); + Proc.get_S_ref(r[0]).set_mac(tmp); +} + +template class SPDZ; template class SPDZ; diff --git a/Processor/SPDZ.h b/Processor/SPDZ.h index 21cfd5a7..cd030d82 100644 --- a/Processor/SPDZ.h +++ b/Processor/SPDZ.h @@ -12,11 +12,18 @@ using namespace std; template class SubProcessor; template class MAC_Check; template class Share; +class Player; +template class Processor; template class SPDZ { public: + SPDZ(Player& P) + { + (void) P; + } + static void assign(T& share, const T& clear, int my_num) { if (my_num == 0) @@ -27,6 +34,10 @@ public: static void muls(const vector& reg, SubProcessor >& proc, MAC_Check& MC, int size); + + static void reqbl(int n); + + static void input(SubProcessor>& Proc, int n, int* r); }; #endif /* PROCESSOR_SPDZ_H_ */ diff --git a/Processor/config.h b/Processor/config.h index fe4e777c..b5059253 100644 --- a/Processor/config.h +++ b/Processor/config.h @@ -7,15 +7,13 @@ #define PROCESSOR_CONFIG_H_ #include "Math/Share.h" - -//#define REPLICATED +#include "Math/Rep3Share.h" #ifdef REPLICATED -typedef Share > sint; -#else -typedef Share sint; +#error REPLICATED flag is obsolete #endif typedef Share sgf2n; +typedef Share sgfp; #endif /* PROCESSOR_CONFIG_H_ */ diff --git a/Programs/Source/blink.mpc b/Programs/Source/blink.mpc index 4e632994..07adec60 100644 --- a/Programs/Source/blink.mpc +++ b/Programs/Source/blink.mpc @@ -98,3 +98,5 @@ test(mismatches[0][1], 0) test(mismatches[0][0], 64) test(mismatches[1][0], 64) test(mismatches[1][1], 128) + +print_ln('%sx%s linkage of %s bits', n, n, l * batch_size) diff --git a/README.md b/README.md index a2d6034a..977e1b80 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,6 @@ compute the preprocessing time for a particulor computation. 1) Edit `CONFIG` or `CONFIG.mine` to your needs: - To benchmark anything other than Yao's garbled circuits, add the following line at the top: `MY_CFLAGS = -DINSECURE` - - To use replicated secret sharing modulo 2^64 instead of SPDZ modulo a large prime, add `MY_CFLAGS = -DREPLICATED` (or add `#define REPLICATED` to `Processor/config.h`). - `PREP_DIR` should point to should be a local, unversioned directory to store preprocessing data (default is `Player-Data` in the current directory). - For the SPDZ-2 and Overdrive offline phases, set `USE_NTL = 1` and `MOD = -DMAX_MOD_SZ=6`. - To use GF(2^40) in the online phase, set `USE_GF2N_LONG = 1`. This will deactive anything that requires OT. @@ -199,10 +198,15 @@ Player-Data Programs $ ../spdz/Scripts/run-online.sh test ``` -### Semi-honest 3-party replicated secret sharing +### Semi-honest 3-party replicated secret sharing modulo 2^64 -Make sure to compile for this setting according to compilation -section and use `make clean` if you change `CONFIG` or `CONFIG.mine`. +Compile the virtual machine: + +`make -j 8 replicated-ring-party.x` + +Run setup to create necessary files and random bits (needed for comparisons etc.): + +`Scripts/setup-online.sh 3` In order to compile a program, use `./compile.py -R 64`, for example: @@ -211,15 +215,15 @@ In order to compile a program, use `./compile.py -R 64`, for example: Running the computation is similar to SPDZ but you will need to start three parties: -`./Player-Online.x -N 3 0 tutorial` +`./replicated-ring-party.x 0 tutorial` -`./Player-Online.x -N 3 1 tutorial` (in a separate terminal) +`./replicated-ring-party.x 1 tutorial` (in a separate terminal) -`./Player-Online.x -N 3 2 tutorial` (in a separate terminal) +`./replicated-ring-party.x 2 tutorial` (in a separate terminal) or -`PLAYERS=3 Scripts/run-online.sh tutorial` +`Scripts/ring.sh tutorial` ## Binary circuits @@ -232,15 +236,11 @@ and `sfix`. See `gc_tutorial.mpc` and `gc_fixed_point_tutorial.mpc` in Compile the virtual machine: -`make -j 8 replicated-party.x` - -Generate the correlated randomness: - -`Scripts/setup-online.sh 3` +`make -j 8 replicated-bin-party.x` After compilating the mpc file, run as follows: -`replicated-party.x -h -p <0/1/2> gc_tutorial` +`replicated-bin-party.x -h -p <0/1/2> gc_tutorial` When running locally, you can omit the host argument. diff --git a/Scripts/replicated.sh b/Scripts/replicated.sh index 7fb10258..ccfcd2f3 100755 --- a/Scripts/replicated.sh +++ b/Scripts/replicated.sh @@ -4,7 +4,7 @@ for i in 0 1 2; do IFS="" log="replicated-$*-$i" IFS=" " - $prefix ./replicated-party.x -p $i $* | tee -a logs/$log & true + $prefix ./replicated-bin-party.x -p $i $* | tee -a logs/$log & true done wait || exit 1 diff --git a/Scripts/ring.sh b/Scripts/ring.sh new file mode 100755 index 00000000..61c52067 --- /dev/null +++ b/Scripts/ring.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +HERE=$(cd `dirname $0`; pwd) +SPDZROOT=$HERE/.. + +export PLAYERS=3 + +. $HERE/run-common.sh + +run_player replicated-ring-party.x ${1:-test_all} || exit 1 diff --git a/Scripts/run-common.sh b/Scripts/run-common.sh index fb79489c..3ee29ced 100644 --- a/Scripts/run-common.sh +++ b/Scripts/run-common.sh @@ -16,7 +16,7 @@ run_player() { if ! test -e $SPDZROOT/logs; then mkdir $SPDZROOT/logs fi - if test $bin = Player-Online.x; then + if test $bin = Player-Online.x -o $bin = replicated-ring-party.x; then params="$* -pn $port -h localhost" else params="$port localhost $*" diff --git a/Tools/avx_memcpy.h b/Tools/avx_memcpy.h index 96985b38..f506983c 100644 --- a/Tools/avx_memcpy.h +++ b/Tools/avx_memcpy.h @@ -33,6 +33,9 @@ inline void avx_memcpy(void* dest, const void* source, size_t length) case 1: *(char*)d2 = *(char*)s2; return; + case 8: + *(int64_t*)d2 = *(int64_t*)s2; + return; default: memcpy(d2, s2, length); return; diff --git a/Tools/benchmarking.h b/Tools/benchmarking.h index 03e4d7fd..0ca65b76 100644 --- a/Tools/benchmarking.h +++ b/Tools/benchmarking.h @@ -7,6 +7,8 @@ #define TOOLS_BENCHMARKING_H_ #include +#include +using namespace std; // call before insecure benchmarking functionality inline void insecure(string message, bool warning = true) diff --git a/Tools/names.cpp b/Tools/names.cpp index 3f6c95ee..bf010d83 100644 --- a/Tools/names.cpp +++ b/Tools/names.cpp @@ -1,3 +1,3 @@ #include "Processor/Data_Files.h" -const char* Data_Files::dtype_names[N_DTYPE] = { "Triples", "Squares", "Bits", "Inverses", "BitTriples", "BitGF2NTriples" }; +const char* DataPositions::dtype_names[N_DTYPE] = { "Triples", "Squares", "Bits", "Inverses", "BitTriples", "BitGF2NTriples" }; diff --git a/Yao/Machine.cpp b/Yao/Machine.cpp index a635da42..880521d1 100644 --- a/Yao/Machine.cpp +++ b/Yao/Machine.cpp @@ -3,6 +3,9 @@ * */ +#include "YaoGarbleWire.h" +#include "YaoEvalWire.h" + #include "GC/Machine.hpp" #include "GC/Processor.hpp" #include "GC/Secret.hpp" diff --git a/Yao/Program.cpp b/Yao/Program.cpp index fc177ddc..384c787f 100644 --- a/Yao/Program.cpp +++ b/Yao/Program.cpp @@ -3,6 +3,9 @@ * */ +#include "YaoEvalWire.h" +#include "YaoGarbleWire.h" + #include "GC/Instruction.hpp" #include "GC/Program.hpp" diff --git a/Yao/YaoEvalWire.cpp b/Yao/YaoEvalWire.cpp index 79235891..e0f2949d 100644 --- a/Yao/YaoEvalWire.cpp +++ b/Yao/YaoEvalWire.cpp @@ -24,8 +24,9 @@ void YaoEvalWire::public_input(bool value) set(0); } +template void YaoEvalWire::and_(GC::Processor >& processor, - const vector& args, bool repeat) + const vector& args) { int total_ands = processor.check_args(args, 4); if (total_ands < 10) @@ -53,11 +54,13 @@ void YaoEvalWire::and_(GC::Processor >& processor, auto& evaluator = YaoEvaluator::s(); for (size_t i = 0; i < n_args; i += 4) { + auto& left = processor.S[args[i + 2]]; + auto& right = processor.S[args[i + 3]]; + for (int k = 0; k < args[i]; k++) { - auto& left_wire = processor.S[args[i + 2]].get_reg(k); - auto& right_key = - processor.S[args[i + 3]].get_reg(repeat ? 0 : k).key; + auto& left_wire = left.get_reg(k); + auto& right_key = right.get_reg(repeat ? 0 : k).key; evaluator.counter++; labels[i_label++] = YaoGate::E_input(left_wire.key, right_key, evaluator.get_gate_id()); @@ -72,13 +75,16 @@ void YaoEvalWire::and_(GC::Processor >& processor, size_t j = 0; for (size_t i = 0; i < n_args; i += 4) { + auto& left = processor.S[args[i + 2]]; + auto& right = processor.S[args[i + 3]]; auto& out = processor.S[args[i + 1]]; out.resize_regs(args[i]); int n = args[i]; + for (int k = 0; k < n; k++) { - auto& right_wire = processor.S[args[i + 3]].get_reg(repeat ? 0 : k); - auto& left_wire = processor.S[args[i + 2]].get_reg(k); + auto& right_wire = right.get_reg(repeat ? 0 : k); + auto& left_wire = left.get_reg(k); YaoGate gate; evaluator.load_gate(gate); gate.eval(out.get_reg(k), hashes[j++], @@ -173,3 +179,10 @@ void YaoEvalWire::set(Key key, bool external) key.set_signal(external); set(key); } + +template void YaoEvalWire::and_( + GC::Processor >& processor, + const vector& args); +template void YaoEvalWire::and_( + GC::Processor >& processor, + const vector& args); diff --git a/Yao/YaoEvalWire.h b/Yao/YaoEvalWire.h index 0cbccc45..d751543f 100644 --- a/Yao/YaoEvalWire.h +++ b/Yao/YaoEvalWire.h @@ -30,15 +30,16 @@ public: static void andrs(GC::Processor>& processor, const vector& args) { - and_(processor, args, true); + and_(processor, args); } static void ands(GC::Processor>& processor, const vector& args) { - and_(processor, args, false); + and_(processor, args); } + template static void and_(GC::Processor>& processor, - const vector& args, bool repeat); + const vector& args); static void inputb(GC::Processor>& processor, const vector& args); diff --git a/Yao/YaoEvaluator.h b/Yao/YaoEvaluator.h index bfaa55f5..b8773d88 100644 --- a/Yao/YaoEvaluator.h +++ b/Yao/YaoEvaluator.h @@ -12,11 +12,7 @@ #include "YaoCommon.h" #include "GC/Secret.h" #include "GC/Program.h" -#include "GC/Machine.h" -#include "GC/Processor.h" -#include "GC/Memory.h" #include "GC/Thread.h" -#include "GC/ThreadMaster.h" #include "Tools/MMO.h" #include "OT/OTExtensionWithMatrix.h" diff --git a/client-setup.cpp b/client-setup.cpp index 1c93e6da..cfbafeba 100644 --- a/client-setup.cpp +++ b/client-setup.cpp @@ -56,11 +56,11 @@ int main(int argc, const char** argv) "--lgp" // Flag token. ); opt.add( - "40", // Default. + to_string(gf2n::default_degree()).c_str(), // Default. 0, // Required? 1, // Number of args expected. 0, // Delimiter if expecting multiple args. - "Bit length of GF(2^n) field (default: 40)", // Help description. + ("Bit length of GF(2^n) field (default: " + to_string(gf2n::default_degree()) + ")").c_str(), // Help description. "-lg2", // Flag token. "--lg2" // Flag token. ); diff --git a/replicated-party.cpp b/replicated-bin-party.cpp similarity index 100% rename from replicated-party.cpp rename to replicated-bin-party.cpp diff --git a/replicated-ring-party.cpp b/replicated-ring-party.cpp new file mode 100644 index 00000000..e9324e19 --- /dev/null +++ b/replicated-ring-party.cpp @@ -0,0 +1,74 @@ +/* + * replicated-ring-party.cpp + * + */ + +#include "Tools/ezOptionParser.h" +#include "Tools/benchmarking.h" +#include "Networking/Server.h" +#include "Math/Rep3Share.h" +#include "Processor/Machine.h" + +int main(int argc, const char** argv) +{ + ez::ezOptionParser opt; + opt.add( + "localhost", // Default. + 0, // Required? + 1, // Number of args expected. + 0, // Delimiter if expecting multiple args. + "Host where party 0 is running (default: localhost)", // Help description. + "-h", // Flag token. + "--hostname" // Flag token. + ); + opt.add( + "5000", // Default. + 0, // Required? + 1, // Number of args expected. + 0, // Delimiter if expecting multiple args. + "Base port number (default: 5000).", // Help description. + "-pn", // Flag token. + "--portnum" // Flag token. + ); + opt.syntax = "./replicated-ring-party.x [OPTIONS] "; + opt.parse(argc, argv); + vector allArgs(opt.firstArgs); + allArgs.insert(allArgs.end(), opt.lastArgs.begin(), opt.lastArgs.end()); + + int playerno; + string progname; + + if (allArgs.size() != 3) + { + cerr << "ERROR: incorrect number of arguments to " << argv[0] << endl; + cerr << "Arguments given were:\n"; + for (unsigned int j = 1; j < allArgs.size(); j++) + cout << "'" << *allArgs[j] << "'" << endl; + string usage; + opt.getUsage(usage); + cout << usage; + return 1; + } + else + { + playerno = atoi(allArgs[1]->c_str()); + progname = *allArgs[2]; + + } + + int pnb; + string hostname; + opt.get("-pn")->getInt(pnb); + opt.get("-h")->getString(hostname); + + insecure("unencrypted communication"); + Names N; + Server* server = Server::start_networking(N, playerno, 3, hostname, pnb); + + Machine(playerno, N, progname, "empty", 128, + gf2n::default_degree(), 0, 0, 0, 0, 0).run(); + + if (server) + delete server; + +}