Compile all online phases at once.

This commit is contained in:
Marcel Keller
2018-10-26 15:52:49 +11:00
parent 3c69da139a
commit 0f16629963
93 changed files with 1374 additions and 823 deletions

View File

@@ -5,33 +5,34 @@
#include "ReplicatedMC.h"
#include "GC/ReplicatedSecret.h"
#include "Math/Rep3Share.h"
template<class T>
void ReplicatedMC<T>::POpen_Begin(vector<typename T::value_type>& values,
const vector<Share<T> >& S, const Player& P)
void ReplicatedMC<T>::POpen_Begin(vector<typename T::clear>& values,
const vector<T>& 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<class T>
void ReplicatedMC<T>::POpen_End(vector<typename T::value_type>& values,
const vector<Share<T> >& S, const Player& P)
void ReplicatedMC<T>::POpen_End(vector<typename T::clear>& values,
const vector<T>& 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<FixedVec<Integer, 2> >;
template class ReplicatedMC<Rep3Share>;
template class ReplicatedMC<GC::ReplicatedSecret>;

View File

@@ -12,12 +12,18 @@ template <class T>
class ReplicatedMC : public MAC_Check_Base<typename T::value_type>
{
public:
// emulate MAC_Check
ReplicatedMC(const gfp& _ = {}, int __ = 0, int ___ = 0) :
MAC_Check_Base<typename T::value_type>({})
{ (void)_; (void)__; (void)___; }
void POpen_Begin(vector<typename T::value_type>& values,const vector<Share<T> >& S,const Player& P);
void POpen_End(vector<typename T::value_type>& values,const vector<Share<T> >& S,const Player& P);
// emulate Direct_MAC_Check
ReplicatedMC(const gfp& _, Names& ____, int __ = 0, int ___ = 0) :
MAC_Check_Base<typename T::value_type>({})
{ (void)_; (void)__; (void)___; (void)____; }
void POpen_Begin(vector<typename T::clear>& values,const vector<T>& S,const Player& P);
void POpen_End(vector<typename T::clear>& values,const vector<T>& S,const Player& P);
void Check(const Player& P) { (void)P; }
};

View File

@@ -29,9 +29,8 @@ void make_share(vector<Share<T> >& Sa,const T& a,int N,const T& key,PRNG& G)
Sa[N-1]=S;
}
template<>
void make_share(vector<Share<FixedVec<Integer, 2> > >& Sa,
const FixedVec<Integer, 2>& a, int N, const FixedVec<Integer, 2>& key,
void make_share(vector<Rep3Share>& Sa,
const Integer& a, int N, const Integer& key,
PRNG& G)
{
(void)key;
@@ -40,13 +39,13 @@ void make_share(vector<Share<FixedVec<Integer, 2> > >& Sa,
Sa.resize(N);
FixedVec<Integer, 3> add_shares;
// hack
add_shares.randomize_to_sum(a[0], G);
add_shares.randomize_to_sum(a, G);
for (int i=0; i<N; i++)
{
FixedVec<Integer, 2> 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<Share<T> >& Sa,T& value,T& mac,int N,const T& key)
}
}
void check_share(vector<Rep3Share>& 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<Share<gf2n> >& Sa,const gf2n& a,int N,const gf2n& key,PRNG& G);
template void make_share(vector<Share<gfp> >& Sa,const gfp& a,int N,const gfp& key,PRNG& G);
template void check_share(vector<Share<gf2n> >& Sa,gf2n& value,gf2n& mac,int N,const gf2n& key);
template void check_share(vector<sint>& Sa,sint::value_type& value,sint::value_type& mac,int N,const sint::value_type& key);
template void check_share(vector<Share<gfp> >& Sa,gfp& value,gfp& mac,int N,const gfp& key);
#ifdef USE_GF2N_LONG
template void make_share(vector<Share<gf2n_short> >& Sa,const gf2n_short& a,int N,const gf2n_short& key,PRNG& G);

View File

@@ -5,15 +5,20 @@
#include "Math/gf2n.h"
#include "Math/gfp.h"
#include "Math/Share.h"
#include "Math/Rep3Share.h"
#include <fstream>
using namespace std;
template<class T>
void make_share(vector<Share<T> >& Sa,const T& a,int N,const T& key,PRNG& G);
void make_share(vector<Rep3Share>& Sa, const Integer& a, int N,
const Integer& key, PRNG& G);
template<class T>
void check_share(vector<Share<T> >& Sa,T& value,T& mac,int N,const T& key);
void check_share(vector<Rep3Share>& 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);

View File

@@ -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 <class T>
Secret<T> Secret<T>::reconstruct(const int128& x, int length)
{
Secret<T> res;
for (int i = 0; i < CommonParty::singleton->get_n_parties(); i++)
{
Secret<T> tmp = res;
Secret<T> 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 <class T>
void Secret<T>::store(Memory<AuthValue>& mem, size_t address)
{
AuthValue& dest = mem[address];
Secret<T> mac_key = reconstruct(CommonParty::s().get_mac_key().get(), default_length);
Secret<T> 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 <class T>
void Secret<T>::load(int n, const Memory<AuthValue>& mem, size_t address)
{
(void)n;
const AuthValue& x = mem[address];
*this = reconstruct(x.share, default_length);
Secret<T> 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<EvalRegister>;
template class Secret<PRFRegister>;
template class Secret<GarbleRegister>;
@@ -32,6 +116,11 @@ template class Processor< Secret<EvalRegister> >;
template class Processor< Secret<GarbleRegister> >;
template class Processor< Secret<RandomRegister> >;
template class Thread< Secret<PRFRegister> >;
template class Thread< Secret<EvalRegister> >;
template class Thread< Secret<GarbleRegister> >;
template class Thread< Secret<RandomRegister> >;
template class ThreadMaster< Secret<PRFRegister> >;
template class ThreadMaster< Secret<EvalRegister> >;
template class ThreadMaster< Secret<GarbleRegister> >;

View File

@@ -3,6 +3,9 @@
*
*/
#include "Register.h"
#include "GC/Secret.h"
#include "GC/Instruction.hpp"
#include "GC/Program.hpp"

View File

@@ -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;

View File

@@ -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 T>
class Secret;
template <class T>
class Processor;
}
class Register {
@@ -224,8 +224,12 @@ public:
static void ands(T& processor, const vector<int>& args) { processor.ands(args); }
template <class T>
static void inputb(T& processor, const vector<int>& args) { processor.input(args); }
template <class T>
static void check_input(long long in, int n_bits) { (void)in; (void)n_bits; }
static T get_input(int from, GC::Processor<T>& 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<GC::ReadAccess<T> >& accesses,
const GC::Memory<GC::SpdzShare>& source) { (void)accesses; (void)source; }
// most BMR phases don't need actual input
template<class T>
static T get_input(int from, GC::Processor<T>& 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 <class T>
static void inputb(T& processor, const vector<int>& args);
template <class T>
static T get_input(int from, GC::Processor<T>& 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);

View File

@@ -6,11 +6,14 @@
#ifndef CIRCUIT_INC_COMMON_H_
#define CIRCUIT_INC_COMMON_H_
#include <cstring>
#include <string>
#include <vector>
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];

5
CONFIG
View File

@@ -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)

View File

@@ -21,17 +21,17 @@ using namespace std;
string PREP_DATA_PREFIX;
template<class T>
void check_mult_triples(const T& key,int N,vector<Data_Files*>& dataF,DataFieldType field_type)
void check_mult_triples(const T& key,int N,vector<Sub_Data_Files<Share<T>>*>& dataF)
{
T a,b,c,mac,res;
vector<Share<T> > Sa(N),Sb(N),Sc(N);
int n = 0;
try {
while (!dataF[0]->eof<T>(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<class T>
void check_tuples(const T& key,int N,vector<Data_Files*>& dataF, Dtype type)
void check_tuples(const T& key,int N,vector<Sub_Data_Files<Share<T>>*>& dataF, Dtype type)
{
T a,b,c,mac,res;
vector<Share<T> > Sa(N),Sb(N),Sc(N);
int n = 0;
DataFieldType field_type = T::field_type();
try {
while (!dataF[0]->eof<T>(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<class T>
void check_bits(const T& key,int N,vector<Data_Files*>& dataF,DataFieldType field_type)
void check_bits(const typename T::value_type& key,int N,vector<Sub_Data_Files<T>*>& dataF)
{
T a,b,c,mac,res;
vector<Share<T> > Sa(N),Sb(N),Sc(N);
typename T::clear a,b,c,mac,res;
vector<T> Sa(N),Sb(N),Sc(N);
int n = 0;
try {
while (!dataF[0]->eof<T>(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<Data_Files*>& 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<class T>
void check_inputs(const T& key,int N,vector<Data_Files*>& dataF)
void check_inputs(const T& key,int N,vector<Sub_Data_Files<Share<T>>*>& dataF)
{
T a, mac, x;
vector< Share<T> > Sa(N);
@@ -157,7 +156,7 @@ void check_inputs(const T& key,int N,vector<Data_Files*>& dataF)
{
int n = 0;
try {
while (!dataF[0]->input_eof<T>(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<Data_Files*>& dataF)
}
}
template<class T>
vector<Sub_Data_Files<T>*> setup(int N, DataPositions& usage)
{
vector<Sub_Data_Files<T>*> dataF(N);
for (int i = 0; i < N; i++)
dataF[i] = new Sub_Data_Files<T>(i, N, PREP_DATA_PREFIX, usage);
return dataF;
}
template<class T>
void check(T key, int N, bool only_bits = false)
{
DataPositions usage(N);
auto dataF = setup<Share<T>>(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<Data_Files*> 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<Rep3Share>(N, pos);
check_bits({}, N, dataF);
}
}

View File

@@ -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:

View File

@@ -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)]

View File

@@ -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

View File

@@ -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"; }
};

View File

@@ -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

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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<N; i++)
{ stringstream filename;
filename << prep_data_prefix << Data_Files::dtype_names[dtype] << "-2-P" << i;
filename << prep_data_prefix << DataPositions::dtype_names[dtype] << "-2-P" << i;
cout << "Opening " << filename.str() << endl;
outf[i].open(filename.str().c_str(),ios::out | ios::binary);
if (outf[i].fail()) { throw file_error(filename.str().c_str()); }
@@ -143,21 +143,20 @@ void make_square_tuples(const T& key,int N,int ntrip,const string& str,bool zero
/* N = Number players
* ntrip = Number bits needed
* str = "2" or "p"
*/
template<class T>
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<Share<T> > Sa(N);
typename T::value_type a;
vector<T> Sa(N);
/* Generate Bits */
for (int i=0; i<N; i++)
{ stringstream filename;
filename << prep_data_prefix << "Bits-" << str << "-P" << i;
filename << prep_data_prefix << "Bits-" << T::type_char() << "-P" << i;
cout << "Opening " << filename.str() << endl;
outf[i].open(filename.str().c_str(),ios::out | ios::binary);
if (outf[i].fail()) { throw file_error(filename.str().c_str()); }
@@ -538,8 +537,8 @@ int main(int argc, const char** argv)
make_mult_triples(key2,nplayers,ntrip2,"2",zero);
make_mult_triples(keyp,nplayers,ntripp,"p",zero);
make_bits(key2,nplayers,nbits2,"2",zero);
make_bits(keyp,nplayers,nbitsp,"p",zero);
make_bits<Share<gf2n>>(key2,nplayers,nbits2,zero);
make_bits<Share<gfp>>(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<Rep3Share>({}, nplayers, nbitsp, zero);
}

View File

@@ -75,11 +75,9 @@ void FakeSecret::trans(Processor<FakeSecret>& 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<FakeSecret>& 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)

View File

@@ -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 <random>
#include <fstream>
@@ -32,6 +31,7 @@ public:
// dummy
typedef MAC_Check_Base<FakeSecret> 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<FakeSecret>& processor, int n_inputs,
const vector<int>& args);
static FakeSecret input(int from, ifstream& input_file, int n_bits);
static FakeSecret input(int from, GC::Processor<FakeSecret>& processor, int n_bits);
static FakeSecret input(int from, const int128& input, int n_bits);
FakeSecret() : a(0) {}

View File

@@ -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
{

View File

@@ -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 <vector>

View File

@@ -10,9 +10,6 @@
#include "ReplicatedSecret.h"
#include "ThreadMaster.h"
#include "Yao/YaoGarbleWire.h"
#include "Yao/YaoEvalWire.h"
namespace GC
{

View File

@@ -10,7 +10,6 @@
using namespace std;
#include "GC/Clear.h"
#include <GC/FakeSecret.h>
#include "GC/Machine.h"
#include "Math/Integer.h"
@@ -30,6 +29,8 @@ class Processor : public ::ProcessorBase
public:
static int check_args(const vector<int>& args, int n);
static void check_input(long long in, int n_bits);
Machine<T>& machine;
unsigned int PC;

View File

@@ -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<T>::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<class T>
void GC::Processor<T>::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 <class T>
void Processor<T>::bitdecc(const vector<int>& regs, const Clear& x)
{
@@ -172,7 +186,7 @@ void Processor<T>::input(const vector<int>& 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

View File

@@ -10,9 +10,6 @@
#include <valgrind/callgrind.h>
#include "Yao/YaoGarbleWire.h"
#include "Yao/YaoEvalWire.h"
#ifdef MAX_INLINE
#include "Instruction_inline.h"
#endif

View File

@@ -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] <progname>";
opt.syntax = "./replicated-bin-party.x [OPTIONS] <progname>";
if (opt.lastArgs.size() == 1)
{
progname = *opt.lastArgs[0];

View File

@@ -92,7 +92,7 @@ void ReplicatedSecret::inputb(Processor<ReplicatedSecret>& processor,
}
}
ReplicatedSecret ReplicatedSecret::input(int from, long input, int n_bits)
ReplicatedSecret ReplicatedSecret::input(int from, Processor<ReplicatedSecret>& 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<ReplicatedSecret>& 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<ReplicatedSecret>& processor,
inline void ReplicatedSecret::prepare_and(vector<octetStream>& os, int n,
const ReplicatedSecret& x, const ReplicatedSecret& y,
PRNG& secure_prng, bool repeat)
Thread<ReplicatedSecret>& party, bool repeat)
{
ReplicatedSecret y_ext;
if (repeat)
@@ -159,11 +159,14 @@ inline void ReplicatedSecret::prepare_and(vector<octetStream>& 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<octetStream>& 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<ReplicatedSecret>& processor,
@@ -217,8 +215,7 @@ void ReplicatedSecret::trans(Processor<ReplicatedSecret>& processor,
void ReplicatedSecret::reveal(Clear& x)
{
Share<ReplicatedSecret> share;
share.set_share(*this);
ReplicatedSecret share = *this;
vector<BitVec> opened;
auto& party = ReplicatedParty::s();
party.MC.POpen_Begin(opened, {share}, *party.P);

View File

@@ -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<BitVec, 2>
public:
typedef ReplicatedSecret DynamicType;
typedef BitVec clear;
typedef ReplicatedMC<ReplicatedSecret> 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<ReplicatedSecret>& processor, int n_bits);
void prepare_input(vector<octetStream>& os, long input, int n_bits, PRNG& secure_prng);
void finalize_input(Thread<ReplicatedSecret>& 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<octetStream>& os, int n,
const ReplicatedSecret& x, const ReplicatedSecret& y,
PRNG& secure_prng, bool repeat);
Thread<ReplicatedSecret>& party, bool repeat);
void finalize_andrs(vector<octetStream>& os, int n);
void reveal(Clear& x);

View File

@@ -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 <fstream>
namespace GC
{
template<class T>
class Secret;
template <class T>
inline void XOR(T& res, const T& left, const T& right)
{
@@ -77,6 +80,7 @@ public:
// dummy
typedef MAC_Check_Base<Secret<T> > 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<const T*>(&reg); }
static Secret<T> input(party_id_t from, const int128& input, int n_bits = -1);
static Secret<T> input(party_id_t from, ifstream& input_file, int n_bits = -1);
static Secret<T> input(party_id_t from, Processor<Secret<T>>& processor, int n_bits = -1);
void random(int n_bits, int128 share);
void random_bit();
static Secret<T> reconstruct(const int128& x, int length);

View File

@@ -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<class T>
Secret<T> Secret<T>::input(party_id_t from, ifstream& input_file, int n_bits)
Secret<T> Secret<T>::input(party_id_t from, Processor<Secret<T>>& 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<class T>
@@ -114,64 +101,6 @@ void Secret<T>::random_bit()
#endif
}
template <class T>
Secret<T> Secret<T>::reconstruct(const int128& x, int length)
{
Secret<T> res;
for (int i = 0; i < CommonParty::singleton->get_n_parties(); i++)
{
Secret<T> tmp = res;
Secret<T> 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 <class T>
void Secret<T>::store(Memory<AuthValue>& mem, size_t address)
{
AuthValue& dest = mem[address];
Secret<T> mac_key = reconstruct(CommonParty::s().get_mac_key().get(), default_length);
Secret<T> 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 <class T>
void Secret<T>::store(Memory<SpdzShare>& mem,
vector<WriteAccess<Secret<T> > >& accesses)
@@ -288,29 +217,6 @@ void Secret<T>::load(int n, const Integer& x)
#endif
}
template <class T>
void Secret<T>::load(int n, const Memory<AuthValue>& mem, size_t address)
{
(void)n;
const AuthValue& x = mem[address];
*this = reconstruct(x.share, default_length);
Secret<T> 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 T>
void Secret<T>::load(vector<ReadAccess < Secret<T> > >& accesses, const Memory<SpdzShare>& mem)
{

View File

@@ -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 <class T>

View File

@@ -31,6 +31,7 @@ public:
Machine<T>& machine;
Processor<T> processor;
typename T::MC MC;
typename T::Protocol* protocol;
Names& N;
Player* P;
PRNG secure_prng;

View File

@@ -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<T>::run_thread(void* thread)
template<class T>
Thread<T>::Thread(int thread_num, Machine<T>& 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<T>::~Thread()
{
if (P)
delete P;
if (protocol)
delete protocol;
}
template<class T>
@@ -43,6 +44,7 @@ void Thread<T>::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<T>::finish()
}
template class Thread<FakeSecret>;
template class Thread< Secret<PRFRegister> >;
template class Thread< Secret<EvalRegister> >;
template class Thread< Secret<GarbleRegister> >;
template class Thread< Secret<RandomRegister> >;
template class Thread<ReplicatedSecret>;
} /* namespace GC */

View File

@@ -8,8 +8,6 @@
#include "ReplicatedSecret.h"
#include "Secret.h"
#include "Yao/YaoGarbleWire.h"
#include "Yao/YaoEvalWire.h"
namespace GC
{

View File

@@ -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

View File

@@ -27,11 +27,6 @@ public:
typedef T value_type;
static const int length = L;
typedef ReplicatedMC<FixedVec<T, L> > MC;
typedef ReplicatedInput<FixedVec<T, L> > Inp;
typedef ReplicatedPrivateOutput<FixedVec<T, L> > PO;
typedef Replicated<FixedVec<T, L> > 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);
}
FixedVec<T, L>operator+(const FixedVec<T, L>& other) const
{
FixedVec<T, L> res;
res.add(*this, other);
return res;
}
FixedVec<T, L>operator-(const FixedVec<T, L>& other) const
{
FixedVec<T, L> res;
res.sub(*this, other);
return res;
}
FixedVec<T, L>operator^(const FixedVec<T, L>& other) const
@@ -147,6 +160,12 @@ public:
return res;
}
FixedVec<T, L>& operator+=(const FixedVec<T, L>& other)
{
add(other);
return *this;
}
FixedVec<T, L>& operator^=(const FixedVec<T, L>& other)
{
for (int i = 0; i < L; i++)

View File

@@ -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(); }

93
Math/Rep3Share.h Normal file
View File

@@ -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<Integer, 2>
{
public:
typedef Integer clear;
typedef Replicated<Rep3Share> Protocol;
typedef ReplicatedMC<Rep3Share> MAC_Check;
typedef MAC_Check Direct_MC;
typedef ReplicatedInput<Rep3Share> Input;
typedef ReplicatedPrivateOutput<Rep3Share> PrivateOutput;
static char type_char()
{
return clear::type_char();
}
Rep3Share()
{
}
Rep3Share(const FixedVec<Integer, 2>& other)
{
FixedVec<Integer, 2>::operator=(other);
}
Rep3Share(Integer value, int my_num)
{
Replicated<Rep3Share>::assign(*this, value, my_num);
}
// Share<T> compatibility
void assign(clear other, int my_num, const Integer& alphai)
{
(void)alphai;
*this = Rep3Share(other, my_num);
}
void assign(const char* buffer)
{
FixedVec<Integer, 2>::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<Integer, 2>::pack(os);
}
void unpack(octetStream& os, bool full = true)
{
(void)full;
FixedVec<Integer, 2>::unpack(os);
}
};
#endif /* MATH_REP3SHARE_H_ */

View File

@@ -38,17 +38,19 @@ T combine(const vector< Share<T> >& S)
template<class T>
inline void Share<T>::pack(octetStream& os) const
inline void Share<T>::pack(octetStream& os, bool full) const
{
a.pack(os);
mac.pack(os);
if (full)
mac.pack(os);
}
template<class T>
inline void Share<T>::unpack(octetStream& os)
inline void Share<T>::unpack(octetStream& os, bool full)
{
a.unpack(os);
mac.unpack(os);
if (full)
mac.unpack(os);
}
@@ -77,5 +79,3 @@ template class Share<gf2n_short>;
template gf2n_short combine(const vector< Share<gf2n_short> >& S);
template bool check_macs(const vector< Share<gf2n_short> >& S,const gf2n_short& key);
#endif
template class Share<FixedVec<Integer, 2> >;

View File

@@ -20,6 +20,7 @@ template<class T> class Share;
template<class T> T combine(const vector< Share<T> >& S);
template<class T> bool check_macs(const vector< Share<T> >& S,const T& key);
template<class T> class Direct_MAC_Check;
template<class T>
class Share
@@ -33,6 +34,7 @@ class Share
typedef typename T::value_type clear;
typedef typename T::MC MAC_Check;
typedef Direct_MAC_Check<T> 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<T>& 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<T>& 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

View File

@@ -9,6 +9,7 @@
*
*/
#include "Math/config.h"
#include "Math/bigint.h"
#include "Math/mpn_fixed.h"
#include "Tools/random.h"

11
Math/config.h Normal file
View File

@@ -0,0 +1,11 @@
/*
* config.h
*
*/
#ifndef MATH_CONFIG_H_
#define MATH_CONFIG_H_
//#define MAX_MOD_SZ 6
#endif /* MATH_CONFIG_H_ */

View File

@@ -253,7 +253,7 @@ int main(int argc, const char** argv)
try
#endif
{
Machine(playerno, playerNames, progname, memtype, lgp, lg2,
Machine<sgfp>(playerno, playerNames, progname, memtype, lgp, lg2,
opt.get("--direct")->isSet, opening_sum, opt.get("--parallel")->isSet,
opt.get("--threads")->isSet, max_broadcast).run();

View File

@@ -1,4 +1,5 @@
#include "Processor/Binary_File_IO.h"
#include "Math/Rep3Share.h"
#include "Math/gfp.h"
/*
@@ -8,7 +9,7 @@
*/
template<class T>
void Binary_File_IO::write_to_file(const string filename, const vector< Share<T> >& 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<gfp> >& buffer);
template void Binary_File_IO::read_from_file(const string filename, vector< Share<gfp> >& buffer, const int start_posn, int &end_posn);
template void Binary_File_IO::write_to_file(const string filename, const vector< Share<FixedVec<Integer, 2> > >& buffer);
template void Binary_File_IO::read_from_file(const string filename, vector< Share<FixedVec<Integer, 2> > >& 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);

View File

@@ -26,7 +26,7 @@ class Binary_File_IO
* Throws file_error.
*/
template <class T>
void write_to_file(const string filename, const vector< Share<T> >& 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.

View File

@@ -143,58 +143,13 @@ void Buffer<T,U>::input(U& a)
next++;
}
template < template<class T> class U, template<class T> class V >
BufferBase& BufferHelper<U,V>::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 T> class U, template<class T> class V >
void BufferHelper<U,V>::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<template<class T> class U, template<class T> class V>
void BufferHelper<U,V>::close()
{
for (int i = 0; i < N_DATA_FIELD_TYPE; i++)
if (files[i])
{
files[i]->close();
delete files[i];
}
}
template<template<class T> class U, template<class T> class V>
void BufferHelper<U,V>::prune()
{
buffer2.prune();
bufferp.prune();
}
template<template<class T> class U, template<class T> class V>
void BufferHelper<U,V>::purge()
{
buffer2.purge();
bufferp.purge();
}
template class Buffer< Share<gfp>, Share<gfp> >;
template class Buffer< Share<gf2n>, Share<gf2n> >;
template class Buffer< Share<FixedVec<Integer, 2> >, Share<FixedVec<Integer, 2> > >;
template class Buffer< InputTuple<sint::value_type>, RefInputTuple<sint::value_type> >;
template class Buffer< InputTuple<gf2n>, RefInputTuple<gf2n> >;
template class Buffer< sint::value_type, sint::value_type >;
template class Buffer< Rep3Share, Rep3Share>;
template class Buffer< InputTuple<sgfp>, RefInputTuple<sgfp> >;
template class Buffer< InputTuple<sgf2n>, RefInputTuple<sgf2n> >;
template class Buffer< InputTuple<Rep3Share>, RefInputTuple<Rep3Share> >;
template class Buffer< gfp, gfp >;
template class Buffer< gf2n, gf2n >;
template class Buffer< FixedVec<Integer, 2>, FixedVec<Integer, 2> >;
template class Buffer< Integer, Integer >;
template class BufferHelper<Share, Share>;
template class BufferHelper<InputTuple, RefInputTuple>;

View File

@@ -60,23 +60,29 @@ public:
void fill_buffer();
};
template < template<class T> class U, template<class T> class V >
class BufferHelper
template<class U, class V>
class BufferOwner : public Buffer<U, V>
{
public:
Buffer< U<sint::value_type>, V<sint::value_type> > bufferp;
Buffer< U<gf2n>, V<gf2n> > buffer2;
ifstream* files[N_DATA_FIELD_TYPE];
ifstream* file;
BufferHelper() { memset(files, 0, sizeof(files)); }
void input(V<sint::value_type>& a) { bufferp.input(a); }
void input(V<gf2n>& 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<U, V>::setup(file, tuple_length, filename, data_type, U::type_string().c_str());
}
void close()
{
if (file)
delete file;
file = 0;
}
};
#endif /* PROCESSOR_BUFFER_H_ */

View File

@@ -4,22 +4,35 @@
#include <iomanip>
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<DataTag, int> Data_Files::tuple_lengths;
template<>
const bool Sub_Data_Files<sgfp>::implemented[N_DTYPE] =
{ true, true, true, true, false, false }
;
template<>
const bool Sub_Data_Files<sgf2n>::implemented[N_DTYPE] =
{ true, true, true, true, true, true }
;
template<>
const bool Sub_Data_Files<Rep3Share>::implemented[N_DTYPE] =
{ false, false, true, false, false, false }
;
const int DataPositions::tuple_size[N_DTYPE] = { 3, 2, 1, 2, 3, 3 };
template<class T>
Lock Sub_Data_Files<T>::tuple_lengths_lock;
template<class T>
map<DataTag, int> Sub_Data_Files<T>::tuple_lengths;
void DataPositions::set_num_players(int num_players)
{
files.resize(N_DATA_FIELD_TYPE, vector<int>(N_DTYPE));
inputs.resize(num_players, vector<int>(N_DATA_FIELD_TYPE));
files.resize(N_DATA_FIELD_TYPE, vector<long long>(N_DTYPE));
inputs.resize(num_players, vector<long long>(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<DataTag, int>::const_iterator it;
const map<DataTag, int>& delta_ext = delta.extended[field_type];
map<DataTag, long long>::const_iterator it;
const map<DataTag, long long>& 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<DataTag, int>::const_iterator it = extended[i].begin();
for (map<DataTag, long long>::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<class T>
int Sub_Data_Files<T>::tuple_length(int dtype)
{
switch (field_type)
{
case DATA_MODP:
return 2 * gfp::t() * sizeof(mp_limb_t);
case DATA_GF2N:
return Share<gf2n>::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<class T>
Sub_Data_Files<T>::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<Share, Share>[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<num_players; i++)
{
sprintf(filename,(prep_data_dir + "Inputs-%s-P%d-%d").c_str(),
field_names[field_type],my_num,i);
if (i == my_num)
my_input_buffers.setup(DataFieldType(field_type), filename,
share_length(field_type) * 3 / 2);
else
input_buffers[i].setup(DataFieldType(field_type), filename,
share_length(field_type));
}
input_buffers.resize(num_players);
for (int i=0; i<num_players; i++)
{
sprintf(filename,(prep_data_dir + "Inputs-%s-P%d-%d").c_str(),
string(1, T::type_char()).c_str(),my_num,i);
if (i == my_num)
my_input_buffers.setup(filename,
T::size() * 3 / 2);
else
input_buffers[i].setup(filename,
T::size());
}
cerr << "done\n";
}
Data_Files::~Data_Files()
template<class sint>
Data_Files<sint>::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<class T>
Sub_Data_Files<T>::~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<DataTag, BufferHelper<Share, Share> >::iterator it =
for (auto it =
extended.begin(); it != extended.end(); it++)
it->second.close();
}
void Data_Files::seekg(DataPositions& pos)
template<class T>
void Sub_Data_Files<T>::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<DataTag, long long>::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<DataTag, int>::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<class sint>
void Data_Files<sint>::seekg(DataPositions& pos)
{
DataFp.seekg(pos);
DataF2.seekg(pos);
usage = pos;
}
void Data_Files::skip(const DataPositions& pos)
template<class sint>
void Data_Files<sint>::skip(const DataPositions& pos)
{
DataPositions new_pos = usage;
new_pos.increase(pos);
seekg(new_pos);
}
void Data_Files::prune()
template<class T>
void Sub_Data_Files<T>::prune()
{
for (auto& buffer : buffers)
buffer.prune();
@@ -183,7 +196,15 @@ void Data_Files::prune()
it.second.prune();
}
void Data_Files::purge()
template<class sint>
void Data_Files<sint>::prune()
{
DataFp.prune();
DataF2.prune();
}
template<class T>
void Sub_Data_Files<T>::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<class sint>
void Data_Files<sint>::purge()
{
BufferBase& buffer = extended[tag].get_buffer(field_type);
DataFp.purge();
DataF2.purge();
}
template<class T>
void Sub_Data_Files<T>::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<class T>
void Data_Files::get(Processor& proc, DataTag tag, const vector<int>& regs, int vector_size)
void Sub_Data_Files<T>::get(SubProcessor<T>& proc, DataTag tag, const vector<int>& 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<T>(regs[i] + j));
extended[tag].input(proc.get_S_ref(regs[i] + j));
}
template void Data_Files::get<sint::value_type>(Processor& proc, DataTag tag, const vector<int>& regs, int vector_size);
template void Data_Files::get<gf2n>(Processor& proc, DataTag tag, const vector<int>& regs, int vector_size);
template class Sub_Data_Files<sgf2n>;
template class Sub_Data_Files<sgfp>;
template class Sub_Data_Files<Rep3Share>;
template class Data_Files<sgfp>;
template class Data_Files<Rep3Share>;

View File

@@ -46,9 +46,13 @@ public:
struct DataPositions
{
vector< vector<int> > files;
vector< vector<int> > inputs;
map<DataTag, int> 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<long long> > files;
vector< vector<long long> > inputs;
map<DataTag, long long> 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 sint> class Processor;
template<class sint> class Data_Files;
class Data_Files
template<class T>
class Sub_Data_Files
{
static const bool implemented[N_DTYPE];
static map<DataTag, int> tuple_lengths;
static Lock tuple_lengths_lock;
BufferHelper<Share, Share> buffers[N_DTYPE];
BufferHelper<Share, Share>* input_buffers;
BufferHelper<InputTuple, RefInputTuple> my_input_buffers;
map<DataTag, BufferHelper<Share, Share> > extended;
static int tuple_length(int dtype);
BufferOwner<T, T> buffers[N_DTYPE];
vector<BufferOwner<T, T>> input_buffers;
BufferOwner<InputTuple<T>, RefInputTuple<T>> my_input_buffers;
map<DataTag, BufferOwner<T, T> > 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<class T>
bool eof(Dtype dtype);
template<class T>
bool input_eof(int player);
void setup_extended(DataFieldType field_type, const DataTag& tag, int tuple_size = 0);
template<class T>
void get(Processor& proc, DataTag tag, const vector<int>& regs, int vector_size);
void get(Dtype dtype, T* a);
DataPositions get_usage()
{
return usage;
}
template <class T>
void get(Dtype dtype, Share<T>* 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 <class T>
void get_three(DataFieldType field_type, Dtype dtype, Share<T>& a, Share<T>& b, Share<T>& c)
{
usage.files[field_type][dtype]++;
buffers[dtype].input(a);
buffers[dtype].input(b);
buffers[dtype].input(c);
}
template <class T>
void get_two(DataFieldType field_type, Dtype dtype, Share<T>& a, Share<T>& 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 <class T>
void get_one(DataFieldType field_type, Dtype dtype, Share<T>& a)
void get_one(Dtype dtype, T& a)
{
usage.files[field_type][dtype]++;
usage.files[T::field_type()][dtype]++;
buffers[dtype].input(a);
}
template <class T>
void get_input(Share<T>& a,T& x,int i)
void get_input(T& a,typename T::clear& x,int i)
{
usage.inputs[i][T::field_type()]++;
RefInputTuple<T> 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<T>& proc, DataTag tag, const vector<int>& regs, int vector_size);
};
template<class sint>
class Data_Files
{
DataPositions usage;
public:
Sub_Data_Files<sint> DataFp;
Sub_Data_Files<sgf2n> 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<class T>
bool eof(Dtype dtype)
{
return get_sub<T>().eof(dtype);
}
template<class T>
bool input_eof(int player)
{
return get_sub<T>().input_eof(player);
}
void setup_extended(DataFieldType field_type, const DataTag& tag, int tuple_size = 0);
template<class T>
void get(SubProcessor<T>& proc, DataTag tag, const vector<int>& regs, int vector_size)
{
get_sub<T>().get(proc, tag, regs, vector_size);
}
DataPositions get_usage()
{
return usage;
}
template<class T>
Sub_Data_Files<T>& get_sub();
template <class T>
void get(Dtype dtype, T* a)
{
get_sub<T>().get(dtype, a);
}
template <class T>
void get_three(DataFieldType field_type, Dtype dtype, T& a, T& b, T& c)
{
(void)field_type;
get_sub<T>().get_three(dtype, a, b, c);
}
template <class T>
void get_two(DataFieldType field_type, Dtype dtype, T& a, T& b)
{
(void)field_type;
get_sub<T>().get_two(dtype, a, b);
}
template <class T>
void get_one(DataFieldType field_type, Dtype dtype, T& a)
{
(void)field_type;
get_sub<T>().get_one(dtype, a);
}
template <class T>
void get_input(T& a,typename T::clear& x,int i)
{
get_sub<T>().get_input(a, x, i);
}
};
template<class T> inline
bool Data_Files::eof(Dtype dtype)
{ return buffers[dtype].get_buffer(T::field_type()).eof; }
bool Sub_Data_Files<T>::eof(Dtype dtype)
{ return buffers[dtype].eof; }
template<class T> inline
bool Data_Files::input_eof(int player)
bool Sub_Data_Files<T>::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<class T>
inline void Sub_Data_Files<T>::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<sgfp>& Data_Files<sgfp>::get_sub<sgfp>()
{
return DataFp;
}
template<>
template<>
inline Sub_Data_Files<sgf2n>& Data_Files<sgfp>::get_sub<sgf2n>()
{
return DataF2;
}
template<>
template<>
inline Sub_Data_Files<Rep3Share>& Data_Files<Rep3Share>::get_sub<Rep3Share>()
{
return DataFp;
}
template<>
template<>
inline Sub_Data_Files<sgf2n>& Data_Files<Rep3Share>::get_sub<sgf2n>()
{
return DataF2;
}
#endif

20
Processor/DummyProtocol.h Normal file
View File

@@ -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_ */

View File

@@ -7,15 +7,15 @@
#include "Processor.h"
template<class T>
InputBase<T>::InputBase(Processor& proc) :
InputBase<T>::InputBase(ArithmeticProcessor& proc) :
values_input(0)
{
buffer.setup(&proc.private_input, -1, proc.private_input_filename);
}
template<class T>
Input<T>::Input(Processor& proc, MAC_Check<T>& mc) :
InputBase<T>(proc), proc(proc), MC(mc), shares(proc.P.num_players())
Input<T>::Input(SubProcessor<Share<T>>& proc, MAC_Check<T>& mc) :
InputBase<T>(proc.Proc), proc(proc), MC(mc), shares(proc.P.num_players())
{
}
@@ -81,7 +81,7 @@ template<class T>
void Input<T>::stop(int player, vector<int> targets)
{
for (unsigned int i = 0; i < targets.size(); i++)
proc.get_S_ref<T>(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<T>::stop(int player, vector<int> targets)
this->timer.stop();
for (unsigned int i = 0; i < targets.size(); i++)
{
Share<T>& share = proc.get_S_ref<T>(targets[i]);
Share<T>& share = proc.get_S_ref(targets[i]);
t.unpack(o);
adjust_mac(share, t);
}
@@ -101,7 +101,4 @@ void Input<T>::stop(int player, vector<int> targets)
template class InputBase<Integer>;
template class Input<gf2n>;
#ifndef REPLICATED
template class Input<gfp>;
#endif

View File

@@ -14,7 +14,7 @@ using namespace std;
#include "Processor/Buffer.h"
#include "Tools/time-func.h"
class Processor;
class ArithmeticProcessor;
template<class T>
class InputBase
@@ -26,21 +26,21 @@ protected:
public:
int values_input;
InputBase(Processor& proc);
InputBase(ArithmeticProcessor& proc);
~InputBase();
};
template<class T>
class Input : public InputBase<T>
{
Processor& proc;
SubProcessor<Share<T>>& proc;
MAC_Check<T>& MC;
vector< vector< Share<T> > > shares;
void adjust_mac(Share<T>& share, T& value);
public:
Input(Processor& proc, MAC_Check<T>& mc);
Input(SubProcessor<Share<T>>& proc, MAC_Check<T>& mc);
void start(int player, int n_inputs);
void stop(int player, vector<int> targets);

View File

@@ -10,11 +10,11 @@
template <class T>
struct InputTuple
{
Share<T> share;
T value;
T share;
typename T::clear value;
static int size()
{ return Share<T>::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<T>::size());
value.assign(buffer + T::size());
}
};
@@ -30,9 +30,9 @@ struct InputTuple
template <class T>
struct RefInputTuple
{
Share<T>& share;
T& value;
RefInputTuple(Share<T>& 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<T>& other) { share = other.share; value = other.value; }
};

View File

@@ -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<class sint>
#ifndef __clang__
__attribute__((always_inline))
#endif
inline void Instruction::execute(Processor& Proc) const
inline void Instruction::execute(Processor<sint>& 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<sint>(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<sint>(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<sint::value_type>(start);
Proc.write_shares_to_file(start);
break;
case READFILESHARE:
// Read shares from file system
Proc.read_shares_from_file<sint>(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<sint::value_type>(Proc, r, start, size);
Proc.DataF.get(Proc.Procp, r, start, size);
return;
case GPREP:
Proc.DataF.get<gf2n>(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<class sint>
void Program::execute(Processor<sint>& Proc) const
{
unsigned int size = p.size();
Proc.PC=0;
@@ -1760,3 +1716,6 @@ void Program::execute(Processor& Proc) const
while (Proc.PC<size)
{ p[Proc.PC].execute(Proc); }
}
template void Program::execute(Processor<sgfp>& Proc) const;
template void Program::execute(Processor<Rep3Share>& Proc) const;

View File

@@ -14,8 +14,8 @@ using namespace std;
#include "Math/Integer.h"
#include "Auth/MAC_Check.h"
class Machine;
class Processor;
template<class sint> class Machine;
template<class sint> class Processor;
/*
* Opcode constants
@@ -272,14 +272,15 @@ enum SecrecyType {
MAX_SECRECY_TYPE
};
template<class sint>
struct TempVars {
gf2n ans2; Share<gf2n> 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<class sint>
void execute(Processor<sint>& Proc) const;
};

View File

@@ -13,7 +13,26 @@
#include <pthread.h>
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<class sint>
Machine<sint>::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<sint>::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<class sint>
void Machine<sint>::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<class sint>
DataPositions Machine<sint>::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<class sint>
void Machine<sint>::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<class sint>
void Machine<sint>::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<int,Timer>::iterator it = timer.begin(); it != timer.end(); it++)
cerr << "Time" << it->first << " = " << it->second.elapsed() << " seconds " << endl;
}
template<class sint>
void Machine<sint>::reqbl(int n)
{
sint::Protocol::reqbl(n);
}
template class Machine<sgfp>;
template class Machine<Rep3Share>;

View File

@@ -22,6 +22,8 @@ using namespace std;
class BaseMachine
{
protected:
static BaseMachine* singleton;
std::map<int,Timer> 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 sint>
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<thread_info> tinfo;
vector<thread_info<sint>> tinfo;
vector<pthread_t> 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_ */

View File

@@ -107,8 +107,10 @@ istream& operator>>(istream& s,Memory<T>& M)
template<class T>
void Load_Memory(Memory<T>& M,ifstream& inpf)
void Memory<T>::Load_Memory(ifstream& inpf)
{
Memory<T>& M = *this;
int a;
typename T::clear val;
T S;
@@ -140,18 +142,17 @@ void Load_Memory(Memory<T>& M,ifstream& inpf)
}
}
template class Memory<sint>;
template class Memory<sgfp>;
template class Memory<sgf2n>;
template class Memory<Integer>;
template class Memory<Rep3Share>;
template istream& operator>>(istream& s,Memory<sint>& M);
template istream& operator>>(istream& s,Memory<sgfp>& M);
template istream& operator>>(istream& s,Memory<sgf2n>& M);
template istream& operator>>(istream& s,Memory<Integer>& M);
template istream& operator>>(istream& s,Memory<Rep3Share>& M);
template ostream& operator<<(ostream& s,const Memory<sint>& M);
template ostream& operator<<(ostream& s,const Memory<sgfp>& M);
template ostream& operator<<(ostream& s,const Memory<sgf2n>& M);
template ostream& operator<<(ostream& s,const Memory<Integer>& M);
template void Load_Memory(Memory<sint>& M,ifstream& inpf);
template void Load_Memory(Memory<sgf2n>& M,ifstream& inpf);
template void Load_Memory(Memory<Integer>& M,ifstream& inpf);
template ostream& operator<<(ostream& s,const Memory<Rep3Share>& M);

View File

@@ -76,23 +76,21 @@ class Memory
friend ostream& operator<< <>(ostream& s,const Memory<T>& M);
friend istream& operator>> <>(istream& s,Memory<T>& 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<class T>
void Load_Memory(Memory<T>& M,ifstream& inpf);
#endif

View File

@@ -12,10 +12,11 @@
using namespace std;
template<class sint>
void* Sub_Main_Func(void* ptr)
{
thread_info *tinfo=(thread_info *) ptr;
Machine& machine=*(tinfo->machine);
thread_info<sint> *tinfo=(thread_info<sint> *) ptr;
Machine<sint>& machine=*(tinfo->machine);
vector<pthread_mutex_t>& t_mutex = machine.t_mutex;
vector<pthread_cond_t>& client_ready = machine.client_ready;
vector<pthread_cond_t>& 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<sint> DataF(P.my_num(),P.num_players(),machine.prep_dir_prefix);
MAC_Check<gf2n>* 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<gf2n>(*(tinfo->alpha2i),*(tinfo->Nms), num);
//MCp = new Direct_MAC_Check<gfp>(*(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<gf2n>(*(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<sint> Proc(tinfo->thread_num,DataF,P,*MC2,*MCp,machine,progs[0]);
Share<gf2n> a,b,c;
bool flag=true;
@@ -168,18 +168,19 @@ void* Sub_Main_Func(void* ptr)
}
void* Main_Func(void* ptr)
template<class sint>
void* thread_info<sint>::Main_Func(void* ptr)
{
#ifndef INSECURE
try
#endif
{
Sub_Main_Func(ptr);
Sub_Main_Func<sint>(ptr);
}
#ifndef INSECURE
catch (...)
{
thread_info* ti = (thread_info*)ptr;
thread_info<sint>* ti = (thread_info<sint>*)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<class sint>
void thread_info<sint>::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<sint> 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<sgfp>;
template class thread_info<Rep3Share>;

View File

@@ -10,8 +10,9 @@
#include <vector>
using namespace std;
class Machine;
template<class sint> class Machine;
template<class sint>
class thread_info
{
public:
@@ -30,12 +31,12 @@ class thread_info
// Integer arg (optional)
int arg;
Machine* machine;
Machine<sint>* 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

View File

@@ -10,8 +10,8 @@ template<class T>
void PrivateOutput<T>::start(int player, int target, int source)
{
T mask;
proc.DataF.get_input(proc.get_S_ref<T>(target), mask, player);
proc.get_S_ref<T>(target).add(proc.get_S_ref<T>(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<T>::stop(int player, int source)
if (player == proc.P.my_num())
{
T value;
value.sub(proc.get_C_ref<T>(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<gf2n>;
#ifndef REPLICATED
template class PrivateOutput<gfp>;
#endif

View File

@@ -11,16 +11,14 @@ using namespace std;
#include "Math/Share.h"
class Processor;
template<class T>
class PrivateOutput
{
Processor& proc;
SubProcessor<Share<T>>& proc;
deque<T> masks;
public:
PrivateOutput(Processor& proc) : proc(proc) { };
PrivateOutput(SubProcessor<Share<T>>& proc) : proc(proc) { };
void start(int player, int target, int source);
void stop(int player, int source);

View File

@@ -8,23 +8,25 @@
#include <string>
template <class T>
SubProcessor<T>::SubProcessor(Processor& Proc, typename T::MAC_Check& MC) :
Proc(Proc), MC(MC), P(Proc.P)
SubProcessor<T>::SubProcessor(ArithmeticProcessor& Proc, typename T::MAC_Check& MC,
Sub_Data_Files<T>& 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<gf2n>& MC2,sint::MAC_Check& MCp,Machine& machine,
template<class sint>
Processor<sint>::Processor(int thread_num,Data_Files<sint>& DataF,Player& P,
MAC_Check<gf2n>& MC2,typename sint::MAC_Check& MCp,Machine<sint>& 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<class sint>
Processor<sint>::~Processor()
{
cerr << "Sent " << sent << " elements in " << rounds << " rounds" << endl;
}
string Processor::get_filename(const char* prefix, bool use_number)
template<class sint>
string Processor<sint>::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<class sint>
void Processor<sint>::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<class sint>
void Processor<sint>::write_socket(const RegType reg_type, const SecrecyType secrecy_type, const bool send_macs,
int socket_id, int message_type, const vector<int>& 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<sint::value_type>(registers[i]).get_share().pack(socket_stream);
if (send_macs)
get_S_ref<sint::value_type>(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<sint::clear>(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<int>& registers)
template<class sint>
void Processor<sint>::read_socket_ints(int client_id, const vector<int>& 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<int>& registers)
}
// Receive vector of public field elements
template <class T>
void Processor::read_socket_vector(int client_id, const vector<int>& registers)
template<class sint>
void Processor<sint>::read_socket_vector(int client_id, const vector<int>& 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<int>& registers)
maybe_decrypt_sequence(client_id);
for (int i = 0; i < m; i++)
{
get_C_ref<typename T::clear>(registers[i]).unpack(socket_stream);
get_Cp_ref(registers[i]).unpack(socket_stream);
}
}
// Receive vector of field element shares over private channel
template <class T>
void Processor::read_socket_private(int client_id, const vector<int>& registers, bool read_macs)
template<class sint>
void Processor<sint>::read_socket_private(int client_id, const vector<int>& 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<int>& 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<int>& registers) {
template<class sint>
void Processor<sint>::read_client_public_key(int client_id, const vector<int>& registers) {
read_socket_ints(client_id, registers);
@@ -225,7 +225,8 @@ void Processor::read_client_public_key(int client_id, const vector<int>& registe
external_clients.generate_session_key_for_client(client_id, client_public_key);
}
void Processor::init_secure_socket_internal(int client_id, const vector<int>& registers) {
template<class sint>
void Processor<sint>::init_secure_socket_internal(int client_id, const vector<int>& 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<int>& re
external_clients.symmetric_client_commsec_recv_keys[client_id] = make_pair(recvKey,0);
}
void Processor::init_secure_socket(int client_id, const vector<int>& registers) {
template<class sint>
void Processor<sint>::init_secure_socket(int client_id, const vector<int>& registers) {
try {
init_secure_socket_internal(client_id, registers);
@@ -285,7 +287,8 @@ void Processor::init_secure_socket(int client_id, const vector<int>& registers)
}
}
void Processor::resp_secure_socket(int client_id, const vector<int>& registers) {
template<class sint>
void Processor<sint>::resp_secure_socket(int client_id, const vector<int>& 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<int>& registers)
}
}
void Processor::resp_secure_socket_internal(int client_id, const vector<int>& registers) {
template<class sint>
void Processor<sint>::resp_secure_socket_internal(int client_id, const vector<int>& 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<int>& 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 <class T>
void Processor::read_shares_from_file(int start_file_posn, int end_file_pos_register, const vector<int>& data_registers) {
template<class sint>
void Processor<sint>::read_shares_from_file(int start_file_posn, int end_file_pos_register, const vector<int>& 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<T>(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 <class T>
void Processor::write_shares_to_file(const vector<int>& data_registers) {
template<class sint>
void Processor<sint>::write_shares_to_file(const vector<int>& data_registers) {
string filename;
filename = "Persistence/Transactions-P" + to_string(P.my_num()) + ".data";
unsigned int size = data_registers.size();
vector< Share<T> > inpbuf (size);
vector< sint > inpbuf (size);
for (unsigned int i = 0; i < size; i++)
{
inpbuf[i] = get_S_ref<T>(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<T>::POpen(const vector<int>& reg, const Player& P,
POpen_Stop(dest, P, size);
}
ostream& operator<<(ostream& s,const Processor& P)
template<class sint>
ostream& operator<<(ostream& s,const Processor<sint>& 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<class sint>
void Processor<sint>::maybe_decrypt_sequence(int client_id)
{
map<int, pair<vector<octet>,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<class sint>
void Processor<sint>::maybe_encrypt_sequence(int client_id)
{
map<int, pair<vector<octet>,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<sgf2n>;
template class SubProcessor<sint>;
template class SubProcessor<sgfp>;
template class SubProcessor<Rep3Share>;
template void Processor::read_socket_private<sint>(int client_id, const vector<int>& registers, bool send_macs);
template void Processor::read_socket_vector<sint>(int client_id, const vector<int>& registers);
template void Processor::read_shares_from_file<sint>(int start_file_pos, int end_file_pos_register, const vector<int>& data_registers);
template void Processor::write_shares_to_file<sint::value_type>(const vector<int>& data_registers);
template class Processor<sgfp>;
template class Processor<Rep3Share>;

View File

@@ -65,18 +65,20 @@ class SubProcessor
void resize(int size) { C.resize(size); S.resize(size); }
friend class Processor;
template<class sint> friend class Processor;
template<class U> friend class SPDZ;
template<class U> friend class Replicated;
public:
Processor& Proc;
ArithmeticProcessor& Proc;
typename T::MAC_Check& MC;
Player& P;
Sub_Data_Files<T>& DataF;
typename T::Protocol protocol;
SubProcessor(Processor& Proc, typename T::MAC_Check& MC);
SubProcessor(ArithmeticProcessor& Proc, typename T::MAC_Check& MC,
Sub_Data_Files<T>& DataF, Player& P);
// Access to PO (via calls to POpen start/stop)
void POpen_Start(const vector<int>& reg,const Player& P,int size);
@@ -84,9 +86,37 @@ public:
void POpen(const vector<int>& reg,const Player& P,int size);
void muls(const vector<int>& 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 sint>
class Processor : public ArithmeticProcessor
{
vector<long> Ci;
@@ -113,47 +143,39 @@ class Processor : public ProcessorBase
vector<typename T::clear>& get_PO();
public:
Data_Files& DataF;
Data_Files<sint>& DataF;
Player& P;
MAC_Check<gf2n>& MC2;
sint::MAC_Check& MCp;
Machine& machine;
string private_input_filename;
typename sint::MAC_Check& MCp;
Machine<sint>& machine;
SubProcessor<sgf2n> Proc2;
SubProcessor<sint> Procp;
Input<gf2n> input2;
sint::Input inputp;
typename sint::Input inputp;
PrivateOutput<gf2n> 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<sint> temp;
int sent, rounds;
PRNG shared_prng;
ExternalClients external_clients;
Binary_File_IO binary_file_io;
// avoid re-computation of expensive division
map<int, sint::clear> inverses2m;
map<int, typename sint::clear> 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<gf2n>& MC2,sint::MAC_Check& MCp,Machine& machine,
Processor(int thread_num,Data_Files<sint>& DataF,Player& P,
MAC_Check<gf2n>& MC2,typename sint::MAC_Check& MCp,Machine<sint>& machine,
const Program& program);
~Processor();
@@ -244,15 +266,15 @@ class Processor : public ProcessorBase
void write_S2(int i,const Share<gf2n> & 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<class T> Share<T>& get_S_ref(int i);
template<class T> 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<int>& 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<int>& registers);
template <class T>
void read_socket_vector(int client_id, const vector<int>& registers);
template <class T>
void read_socket_private(int client_id, const vector<int>& registers, bool send_macs);
// Read and write secret numeric data to file (name hardcoded at present)
template <class T>
void read_shares_from_file(int start_file_pos, int end_file_pos_register, const vector<int>& data_registers);
template <class T>
void write_shares_to_file(const vector<int>& data_registers);
// Print the processor state
friend ostream& operator<<(ostream& s,const Processor& P);
template<class T>
friend ostream& operator<<(ostream& s,const Processor<T>& P);
private:
void maybe_decrypt_sequence(int client_id);
@@ -303,10 +318,5 @@ class Processor : public ProcessorBase
template<class T> friend class SubProcessor;
};
template<> inline Share<gf2n>& 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

View File

@@ -4,7 +4,7 @@
#include "Processor/Instruction.h"
#include "Processor/Data_Files.h"
class Machine;
template<class sint> 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<class sint>
void execute(Processor<sint>& Proc) const;
};

View File

@@ -8,11 +8,23 @@
#include "Math/FixedVec.h"
#include "Math/Integer.h"
#include "Tools/benchmarking.h"
#include "GC/ReplicatedSecret.h"
template<class T>
Replicated<T>::Replicated() : counter(0)
Replicated<T>::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<class T>
@@ -23,7 +35,7 @@ inline Replicated<T>::~Replicated()
template<class T>
void Replicated<T>::muls(const vector<int>& reg,
SubProcessor<Share<T> >& proc, ReplicatedMC<T>& MC, int size)
SubProcessor<T>& proc, ReplicatedMC<T>& MC, int size)
{
(void)MC;
assert(T::length == 2);
@@ -37,30 +49,53 @@ void Replicated<T>::muls(const vector<int>& 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<FixedVec<Integer, 2> >;
template<>
void Replicated<Rep3Share>::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<class T>
inline void Replicated<T>::input(SubProcessor<T>& Proc, int n, int* r)
{
(void)Proc;
(void)n;
(void)r;
throw not_implemented();
}
template class Replicated<Rep3Share>;

View File

@@ -11,15 +11,26 @@
using namespace std;
#include "Tools/octetStream.h"
#include "Tools/random.h"
#include "Networking/Player.h"
template<class T> class SubProcessor;
template<class T> class ReplicatedMC;
template<class T> class ReplicatedInput;
template<class T> class ReplicatedPrivateOutput;
template<class T> class Share;
template<class sint> class Processor;
class ReplicatedBase
{
public:
PRNG shared_prngs[2];
ReplicatedBase(Player& P);
};
template <class T>
class Replicated
class Replicated : ReplicatedBase
{
vector<octetStream> os;
vector<T> results;
@@ -30,10 +41,10 @@ public:
typedef ReplicatedInput<T> Input;
typedef ReplicatedPrivateOutput<T> 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<int>& reg, SubProcessor<Share<T> >& proc, ReplicatedMC<T>& MC,
void muls(const vector<int>& reg, SubProcessor<T>& proc, ReplicatedMC<T>& MC,
int size);
static void reqbl(int n);
static void input(SubProcessor<T>& Proc, int n, int* r);
};
#endif /* PROCESSOR_REPLICATED_H_ */

View File

@@ -22,7 +22,7 @@ void ReplicatedInput<T>::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<T>::stop(int player, vector<int> targets)
if (proc.P.my_num() == player)
{
for (unsigned int i = 0; i < targets.size(); i++)
proc.get_S_ref<T>(targets[i]).set_share(shares[i]);
proc.get_S_ref(targets[i]) = shares[i];
}
else
{
@@ -57,11 +57,9 @@ void ReplicatedInput<T>::stop(int player, vector<int> targets)
T share;
share[j] = t;
share[1 - j] = 0;
this->proc.template get_S_ref<T>(targets[i]).set_share(share);
this->proc.get_S_ref(targets[i]) = share;
}
}
}
#ifdef REPLICATED
template class ReplicatedInput<FixedVec<Integer, 2> >;
#endif
template class ReplicatedInput<Rep3Share>;

View File

@@ -9,16 +9,18 @@
#include "Auth/ReplicatedMC.h"
#include "Input.h"
class Processor;
template <class T>
class ReplicatedInput : public InputBase<typename T::value_type>
{
Processor& proc;
SubProcessor<T>& proc;
vector<T> shares;
public:
ReplicatedInput(Processor& proc, ReplicatedMC<T>& MC) : InputBase<typename T::value_type>(proc), proc(proc) { (void)MC; }
ReplicatedInput(SubProcessor<T>& proc, ReplicatedMC<T>& MC) :
InputBase<typename T::value_type>(proc.Proc), proc(proc)
{
(void) MC;
}
void start(int player, int n_inputs);
void stop(int player, vector<int> targets);

View File

@@ -4,14 +4,23 @@
*/
#include "ReplicatedPrivateOutput.h"
#include "Processor.h"
#include "Math/FixedVec.h"
#include "Math/Integer.h"
template<class T>
inline ReplicatedPrivateOutput<T>::ReplicatedPrivateOutput(
SubProcessor<T>& proc) :
proc(proc)
{
}
template<class T>
void ReplicatedPrivateOutput<T>::start(int player, int target,
int source)
{
(void)player, (void)target, (void)source;
throw not_implemented();
}
template<class T>
@@ -20,4 +29,4 @@ void ReplicatedPrivateOutput<T>::stop(int player, int source)
(void)player, (void)source;
}
template class ReplicatedPrivateOutput<FixedVec<Integer, 2> >;
template class ReplicatedPrivateOutput<Rep3Share>;

View File

@@ -6,15 +6,18 @@
#ifndef PROCESSOR_REPLICATEDPRIVATEOUTPUT_H_
#define PROCESSOR_REPLICATEDPRIVATEOUTPUT_H_
class Processor;
template<class T>
class SubProcessor;
template<class T>
class Share;
template <class T>
class ReplicatedPrivateOutput
{
Processor& proc;
SubProcessor<T>& proc;
public:
ReplicatedPrivateOutput(Processor& proc) : proc(proc) {}
ReplicatedPrivateOutput(SubProcessor<T>& proc);
void start(int player, int target, int source);
void stop(int player, int source);

View File

@@ -21,7 +21,7 @@ void SPDZ<T>::muls(const vector<int>& reg, SubProcessor<Share<T> >& 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<T>::muls(const vector<int>& reg, SubProcessor<Share<T> >& proc, MAC_Ch
}
}
#ifndef REPLICATED
template class SPDZ<gfp>;
#endif
template<>
void SPDZ<gfp>::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<class T>
inline void SPDZ<T>::input(SubProcessor<Share<T>>& 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<gfp>;
template class SPDZ<gf2n>;

View File

@@ -12,11 +12,18 @@ using namespace std;
template<class T> class SubProcessor;
template<class T> class MAC_Check;
template<class T> class Share;
class Player;
template<class sint> class Processor;
template <class T>
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<int>& reg, SubProcessor<Share<T> >& proc, MAC_Check<T>& MC,
int size);
static void reqbl(int n);
static void input(SubProcessor<Share<T>>& Proc, int n, int* r);
};
#endif /* PROCESSOR_SPDZ_H_ */

View File

@@ -7,15 +7,13 @@
#define PROCESSOR_CONFIG_H_
#include "Math/Share.h"
//#define REPLICATED
#include "Math/Rep3Share.h"
#ifdef REPLICATED
typedef Share<FixedVec<Integer, 2> > sint;
#else
typedef Share<gfp> sint;
#error REPLICATED flag is obsolete
#endif
typedef Share<gf2n> sgf2n;
typedef Share<gfp> sgfp;
#endif /* PROCESSOR_CONFIG_H_ */

View File

@@ -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)

View File

@@ -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 <host of party 0> -p <0/1/2> gc_tutorial`
`replicated-bin-party.x -h <host of party 0> -p <0/1/2> gc_tutorial`
When running locally, you can omit the host argument.

View File

@@ -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

10
Scripts/ring.sh Executable file
View File

@@ -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

View File

@@ -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 $*"

View File

@@ -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;

View File

@@ -7,6 +7,8 @@
#define TOOLS_BENCHMARKING_H_
#include <stdexcept>
#include <string>
using namespace std;
// call before insecure benchmarking functionality
inline void insecure(string message, bool warning = true)

View File

@@ -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" };

View File

@@ -3,6 +3,9 @@
*
*/
#include "YaoGarbleWire.h"
#include "YaoEvalWire.h"
#include "GC/Machine.hpp"
#include "GC/Processor.hpp"
#include "GC/Secret.hpp"

View File

@@ -3,6 +3,9 @@
*
*/
#include "YaoEvalWire.h"
#include "YaoGarbleWire.h"
#include "GC/Instruction.hpp"
#include "GC/Program.hpp"

View File

@@ -24,8 +24,9 @@ void YaoEvalWire::public_input(bool value)
set(0);
}
template<bool repeat>
void YaoEvalWire::and_(GC::Processor<GC::Secret<YaoEvalWire> >& processor,
const vector<int>& args, bool repeat)
const vector<int>& args)
{
int total_ands = processor.check_args(args, 4);
if (total_ands < 10)
@@ -53,11 +54,13 @@ void YaoEvalWire::and_(GC::Processor<GC::Secret<YaoEvalWire> >& 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<GC::Secret<YaoEvalWire> >& 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_<false>(
GC::Processor<GC::Secret<YaoEvalWire> >& processor,
const vector<int>& args);
template void YaoEvalWire::and_<true>(
GC::Processor<GC::Secret<YaoEvalWire> >& processor,
const vector<int>& args);

View File

@@ -30,15 +30,16 @@ public:
static void andrs(GC::Processor<GC::Secret<YaoEvalWire>>& processor,
const vector<int>& args)
{
and_(processor, args, true);
and_<true>(processor, args);
}
static void ands(GC::Processor<GC::Secret<YaoEvalWire>>& processor,
const vector<int>& args)
{
and_(processor, args, false);
and_<false>(processor, args);
}
template<bool repeat>
static void and_(GC::Processor<GC::Secret<YaoEvalWire>>& processor,
const vector<int>& args, bool repeat);
const vector<int>& args);
static void inputb(GC::Processor<GC::Secret<YaoEvalWire>>& processor,
const vector<int>& args);

View File

@@ -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"

View File

@@ -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.
);

74
replicated-ring-party.cpp Normal file
View File

@@ -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] <playerno> <progname>";
opt.parse(argc, argv);
vector<string*> 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<Rep3Share>(playerno, N, progname, "empty", 128,
gf2n::default_degree(), 0, 0, 0, 0, 0).run();
if (server)
delete server;
}