mirror of
https://github.com/data61/MP-SPDZ.git
synced 2026-04-20 03:01:31 -04:00
839 lines
24 KiB
C++
839 lines
24 KiB
C++
#include "NPartyTripleGenerator.h"
|
|
|
|
#include "OT/OTExtensionWithMatrix.h"
|
|
#include "OT/OTMultiplier.h"
|
|
#include "Math/gfp.h"
|
|
#include "Protocols/Share.h"
|
|
#include "Protocols/SemiShare.h"
|
|
#include "Protocols/Semi2kShare.h"
|
|
#include "Protocols/Spdz2kShare.h"
|
|
#include "Math/operators.h"
|
|
#include "Tools/Subroutines.h"
|
|
#include "Protocols/MAC_Check.h"
|
|
#include "Protocols/Spdz2kPrep.h"
|
|
|
|
#include "OT/Triple.hpp"
|
|
#include "OT/Rectangle.hpp"
|
|
#include "Protocols/MAC_Check.hpp"
|
|
#include "Protocols/SemiMC.h"
|
|
#include "Protocols/MascotPrep.hpp"
|
|
#include "Protocols/ReplicatedInput.hpp"
|
|
#include "Protocols/SemiInput.hpp"
|
|
#include "Processor/Input.hpp"
|
|
#include "Math/Z2k.hpp"
|
|
|
|
#include <sstream>
|
|
#include <fstream>
|
|
#include <math.h>
|
|
|
|
template<class T>
|
|
void* run_ot_thread(void* ptr)
|
|
{
|
|
((OTMultiplierBase*)ptr)->multiply();
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* Copies the relevant base OTs from setup
|
|
* N.B. setup must not be stored as it will be used by other threads
|
|
*/
|
|
template<class T>
|
|
NPartyTripleGenerator<T>::NPartyTripleGenerator(OTTripleSetup& setup,
|
|
const Names& names, int thread_num, int _nTriples, int nloops,
|
|
MascotParams& machine, Player* parentPlayer) :
|
|
OTTripleGenerator<T>(setup, names, thread_num, _nTriples, nloops,
|
|
machine, parentPlayer)
|
|
{
|
|
}
|
|
|
|
template<class T>
|
|
OTTripleGenerator<T>::OTTripleGenerator(OTTripleSetup& setup,
|
|
const Names& names, int thread_num, int _nTriples, int nloops,
|
|
MascotParams& machine, Player* parentPlayer) :
|
|
globalPlayer(parentPlayer ? *parentPlayer : *new PlainPlayer(names,
|
|
- thread_num * names.num_players() * names.num_players())),
|
|
parentPlayer(parentPlayer),
|
|
thread_num(thread_num),
|
|
my_num(setup.get_my_num()),
|
|
nloops(nloops),
|
|
nparties(setup.get_nparties()),
|
|
machine(machine)
|
|
{
|
|
nTriplesPerLoop = DIV_CEIL(_nTriples, nloops);
|
|
nTriples = nTriplesPerLoop * nloops;
|
|
field_size = T::open_type::size() * 8;
|
|
nAmplify = machine.amplify ? N_AMPLIFY : 1;
|
|
nPreampTriplesPerLoop = nTriplesPerLoop * nAmplify;
|
|
|
|
int n = nparties;
|
|
//baseReceiverInput = machines[0]->baseReceiverInput;
|
|
//baseSenderInputs.resize(n-1);
|
|
//baseReceiverOutputs.resize(n-1);
|
|
nbase = setup.get_nbase();
|
|
baseReceiverInput.resize(nbase);
|
|
baseReceiverOutputs = setup.baseReceiverOutputs;
|
|
baseSenderInputs = setup.baseSenderInputs;
|
|
players.resize(n-1);
|
|
|
|
for (int i = 0; i < n-1; i++)
|
|
{
|
|
// i for indexing, other_player is actual number
|
|
int other_player;
|
|
if (i >= my_num)
|
|
other_player = i + 1;
|
|
else
|
|
other_player = i;
|
|
|
|
// copy base OT inputs + outputs
|
|
for (int j = 0; j < 128; j++)
|
|
{
|
|
baseReceiverInput.set_bit(j, (unsigned int)setup.get_base_receiver_input(j));
|
|
}
|
|
|
|
players[i] = new VirtualTwoPartyPlayer(globalPlayer, other_player);
|
|
}
|
|
|
|
pthread_mutex_init(&mutex, 0);
|
|
pthread_cond_init(&ready, 0);
|
|
|
|
ot_multipliers.resize(nparties-1);
|
|
|
|
for (int i = 0; i < nparties-1; i++)
|
|
{
|
|
ot_multipliers[i] = new_multiplier(i);
|
|
pthread_create(&(ot_multipliers[i]->thread), 0, run_ot_thread<T>, ot_multipliers[i]);
|
|
}
|
|
|
|
wait_for_multipliers();
|
|
}
|
|
|
|
template<class T>
|
|
OTTripleGenerator<T>::~OTTripleGenerator()
|
|
{
|
|
// wait for threads to finish
|
|
for (int i = 0; i < nparties-1; i++)
|
|
{
|
|
ot_multipliers[i]->inbox.stop();
|
|
pthread_join(ot_multipliers[i]->thread, NULL);
|
|
#ifdef DEBUG_THREADS
|
|
cout << "OT thread " << i << " finished\n" << flush;
|
|
#endif
|
|
}
|
|
|
|
for (size_t i = 0; i < ot_multipliers.size(); i++)
|
|
delete ot_multipliers[i];
|
|
|
|
for (size_t i = 0; i < players.size(); i++)
|
|
delete players[i];
|
|
//delete nplayer;
|
|
pthread_mutex_destroy(&mutex);
|
|
pthread_cond_destroy(&ready);
|
|
|
|
if (parentPlayer != &globalPlayer)
|
|
delete &globalPlayer;
|
|
}
|
|
|
|
template<class T>
|
|
typename T::Multiplier* OTTripleGenerator<T>::new_multiplier(int i)
|
|
{
|
|
return new typename T::Multiplier(*this, i);
|
|
}
|
|
|
|
template<class T>
|
|
void NPartyTripleGenerator<T>::generate()
|
|
{
|
|
bigint::init_thread();
|
|
|
|
auto& timers = this->timers;
|
|
auto& machine = this->machine;
|
|
auto& my_num = this->my_num;
|
|
auto& thread_num = this->thread_num;
|
|
auto& nTriples = this->nTriples;
|
|
auto& outputFile = this->outputFile;
|
|
|
|
timers["Generator thread"].start();
|
|
|
|
// add up the shares from each thread and write to file
|
|
stringstream ss;
|
|
ss << machine.prep_data_dir;
|
|
if (machine.generateBits)
|
|
ss << "Bits-";
|
|
else
|
|
ss << "Triples-";
|
|
ss << T::type_short() << "-P" << my_num;
|
|
if (thread_num != 0)
|
|
ss << "-" << thread_num;
|
|
if (machine.output)
|
|
outputFile.open(ss.str().c_str());
|
|
|
|
if (machine.generateBits)
|
|
generateBits();
|
|
else
|
|
generateTriples();
|
|
|
|
timers["Generator thread"].stop();
|
|
if (machine.output)
|
|
cout << "Written " << nTriples << " " << T::type_string() << " outputs to " << ss.str() << endl;
|
|
#ifdef VERBOSE
|
|
else
|
|
cout << "Generated " << nTriples << " " << T::type_string() << " outputs" << endl;
|
|
#endif
|
|
}
|
|
|
|
template<class W>
|
|
void NPartyTripleGenerator<W>::generateInputs(int player)
|
|
{
|
|
typedef open_type T;
|
|
|
|
auto& machine = this->machine;
|
|
auto& nTriplesPerLoop = this->nTriplesPerLoop;
|
|
auto& valueBits = this->valueBits;
|
|
auto& share_prg = this->share_prg;
|
|
auto& field_size = this->field_size;
|
|
auto& ot_multipliers = this->ot_multipliers;
|
|
auto& nparties = this->nparties;
|
|
auto& globalPlayer = this->globalPlayer;
|
|
|
|
// extra value for sacrifice
|
|
int toCheck = nTriplesPerLoop + 1;
|
|
this->signal_multipliers({player, toCheck});
|
|
bool mine = player == globalPlayer.my_num();
|
|
valueBits.resize(1);
|
|
|
|
if (mine)
|
|
{
|
|
valueBits[0].resize(toCheck * field_size);
|
|
valueBits[0].template randomize_blocks<T>(share_prg);
|
|
this->signal_multipliers({});
|
|
}
|
|
|
|
this->wait_for_multipliers();
|
|
|
|
GlobalPRNG G(globalPlayer);
|
|
Share<T> check_sum;
|
|
inputs.resize(toCheck);
|
|
auto mac_key = machine.template get_mac_key<mac_key_type>();
|
|
SemiInput<SemiShare<T>> input(0, globalPlayer);
|
|
input.reset_all(globalPlayer);
|
|
vector<T> secrets(toCheck);
|
|
if (mine)
|
|
for (int j = 0; j < toCheck; j++)
|
|
{
|
|
secrets[j] = valueBits[0].template get_portion<T>(j);
|
|
input.add_mine(secrets[j]);
|
|
}
|
|
input.exchange();
|
|
for (int j = 0; j < toCheck; j++)
|
|
{
|
|
T share, mac_sum;
|
|
share = input.finalize(player);
|
|
if (mine)
|
|
{
|
|
mac_sum = secrets[j] * mac_key;
|
|
for (int i = 0; i < nparties-1; i++)
|
|
mac_sum += (ot_multipliers[i])->input_macs[j];
|
|
}
|
|
else
|
|
{
|
|
int i_thread = player - (player > globalPlayer.my_num() ? 1 : 0);
|
|
mac_sum = (ot_multipliers[i_thread])->input_macs[j];
|
|
}
|
|
inputs[j] = {{share, mac_sum}, secrets[j]};
|
|
check_sum += inputs[j].share * G.get<T>();
|
|
}
|
|
inputs.resize(nTriplesPerLoop);
|
|
|
|
typename W::MAC_Check MC(mac_key);
|
|
MC.POpen(check_sum, globalPlayer);
|
|
// use zero element because all is perfectly randomized
|
|
MC.set_random_element({});
|
|
MC.Check(globalPlayer);
|
|
}
|
|
|
|
template<>
|
|
void NPartyTripleGenerator<Share<gf2n>>::generateBits()
|
|
{
|
|
for (int i = 0; i < nparties-1; i++)
|
|
ot_multipliers[i]->inbox.push(DATA_BIT);
|
|
|
|
int nBitsToCheck = nTriplesPerLoop + field_size;
|
|
valueBits.resize(1);
|
|
valueBits[0].resize(ceil(1.0 * nBitsToCheck / 128) * 128);
|
|
bits.resize(nBitsToCheck);
|
|
vector< Share<gf2n> > to_open(1);
|
|
vector<gf2n> opened(1);
|
|
MAC_Check<gf2n> MC(machine.get_mac_key<gf2n>());
|
|
|
|
start_progress();
|
|
|
|
for (int k = 0; k < nloops; k++)
|
|
{
|
|
print_progress(k);
|
|
|
|
valueBits[0].randomize_blocks<gf2n>(share_prg);
|
|
|
|
for (int i = 0; i < nparties-1; i++)
|
|
ot_multipliers[i]->inbox.push({});
|
|
timers["Authentication OTs"].start();
|
|
for (int i = 0; i < nparties-1; i++)
|
|
ot_multipliers[i]->outbox.pop();
|
|
timers["Authentication OTs"].stop();
|
|
|
|
octet seed[SEED_SIZE];
|
|
Create_Random_Seed(seed, globalPlayer, SEED_SIZE);
|
|
PRNG G;
|
|
G.SetSeed(seed);
|
|
|
|
Share<gf2n> check_sum;
|
|
gf2n r;
|
|
for (int j = 0; j < nBitsToCheck; j++)
|
|
{
|
|
gf2n mac_sum = bool(valueBits[0].get_bit(j)) * machine.get_mac_key<gf2n>();
|
|
for (int i = 0; i < nparties-1; i++)
|
|
mac_sum += ((MascotMultiplier<gf2n>*)ot_multipliers[i])->macs[0][j];
|
|
bits[j].set_share(valueBits[0].get_bit(j));
|
|
bits[j].set_mac(mac_sum);
|
|
r.randomize(G);
|
|
check_sum += r * bits[j];
|
|
}
|
|
bits.resize(nTriplesPerLoop);
|
|
|
|
to_open[0] = check_sum;
|
|
MC.POpen_Begin(opened, to_open, globalPlayer);
|
|
MC.POpen_End(opened, to_open, globalPlayer);
|
|
MC.Check(globalPlayer);
|
|
|
|
if (machine.output)
|
|
for (int j = 0; j < nTriplesPerLoop; j++)
|
|
bits[j].output(outputFile, false);
|
|
}
|
|
}
|
|
|
|
template<>
|
|
void NPartyTripleGenerator<Share<gfp1>>::generateBits()
|
|
{
|
|
generateTriples();
|
|
}
|
|
|
|
template <class T>
|
|
void NPartyTripleGenerator<T>::generateBits()
|
|
{
|
|
throw not_implemented();
|
|
}
|
|
|
|
template<class T>
|
|
template<int K, int S>
|
|
void NPartyTripleGenerator<T>::generateTriplesZ2k()
|
|
{
|
|
auto& timers = this->timers;
|
|
auto& machine = this->machine;
|
|
auto& nTriplesPerLoop = this->nTriplesPerLoop;
|
|
auto& valueBits = this->valueBits;
|
|
auto& share_prg = this->share_prg;
|
|
auto& ot_multipliers = this->ot_multipliers;
|
|
auto& nparties = this->nparties;
|
|
auto& globalPlayer = this->globalPlayer;
|
|
auto& nloops = this->nloops;
|
|
auto& b_padded_bits = this->b_padded_bits;
|
|
|
|
this->signal_multipliers(DATA_TRIPLE);
|
|
|
|
const int TAU = Spdz2kMultiplier<K, S>::TAU;
|
|
const int TAU_ROUNDED = (TAU + 7) / 8 * 8;
|
|
valueBits.resize(3);
|
|
for (int i = 0; i < 2; i++)
|
|
valueBits[2*i].resize(max(2 * 8 * Z2<K + 2 * S>::N_BYTES, TAU_ROUNDED) * nTriplesPerLoop);
|
|
valueBits[1].resize(8 * Z2<K + S>::N_BYTES * (nTriplesPerLoop + 1));
|
|
b_padded_bits.resize(8 * Z2<K + 2 * S>::N_BYTES * (nTriplesPerLoop + 1));
|
|
vector< PlainTriple_<Z2<K + 2 * S>, Z2<K + S>, 2> > amplifiedTriples(nTriplesPerLoop);
|
|
uncheckedTriples.resize(nTriplesPerLoop);
|
|
MAC_Check_Z2k<Z2<K + 2 * S>, Z2<S>, Z2<K + S>, Share<Z2<K + 2 * S>> > MC(
|
|
machine.template get_mac_key<Z2<S> >());
|
|
|
|
this->start_progress();
|
|
|
|
for (int k = 0; k < nloops; k++)
|
|
{
|
|
this->print_progress(k);
|
|
|
|
for (int j = 0; j < 2; j++)
|
|
valueBits[j].template randomize_blocks<gf2n>(share_prg);
|
|
|
|
for (int j = 0; j < nTriplesPerLoop + 1; j++)
|
|
{
|
|
Z2<K + S> b(valueBits[1].get_ptr_to_byte(j, Z2<K + S>::N_BYTES));
|
|
b_padded_bits.set_portion(j, Z2<K + 2 * S>(b));
|
|
}
|
|
|
|
timers["OTs"].start();
|
|
this->signal_multipliers({});
|
|
this->wait_for_multipliers();
|
|
timers["OTs"].stop();
|
|
|
|
octet seed[SEED_SIZE];
|
|
Create_Random_Seed(seed, globalPlayer, SEED_SIZE);
|
|
PRNG G;
|
|
G.SetSeed(seed);
|
|
|
|
BitVector aBits = valueBits[0];
|
|
|
|
for (int j = 0; j < nTriplesPerLoop; j++)
|
|
{
|
|
BitVector a(aBits.get_ptr_to_bit(j, TAU_ROUNDED), TAU);
|
|
Z2<K + S> b(valueBits[1].get_ptr_to_byte(j, Z2<K + S>::N_BYTES));
|
|
Z2kRectangle<TAU, K + S> c;
|
|
c.mul(a, b);
|
|
timers["Triple computation"].start();
|
|
for (int i = 0; i < nparties-1; i++)
|
|
{
|
|
c += ((Spdz2kMultiplier<K, S>*)ot_multipliers[i])->c_output[j];
|
|
}
|
|
|
|
#ifdef DEBUG_SPDZ2K
|
|
for (int l = 0; l < c.N_ROWS; l++)
|
|
{
|
|
Z2<K + S> z = fake.POpen({c.rows[l], {}}, globalPlayer);
|
|
auto x = fake.POpen({a.get_bit(l), {}}, globalPlayer);
|
|
auto y = fake.POpen({b, {}}, globalPlayer);
|
|
Z2<K + S> zz = x * y;
|
|
if (z != zz)
|
|
{
|
|
cout << dec << j << " " << l << " " << hex << z << " " << zz
|
|
<< " " << y << " " << x << " " << a.get_byte(l / 8) << endl;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
timers["Triple computation"].stop();
|
|
amplifiedTriples[j].amplify(a, b, c, G);
|
|
amplifiedTriples[j].to(valueBits, j);
|
|
}
|
|
|
|
this->signal_multipliers({});
|
|
this->wait_for_multipliers();
|
|
|
|
for (int j = 0; j < nTriplesPerLoop; j++)
|
|
{
|
|
uncheckedTriples[j].from(amplifiedTriples[j], j, *this);
|
|
}
|
|
|
|
// we can skip the consistency check since we're doing a mac-check next
|
|
// get piggy-backed random value
|
|
Z2<K + 2 * S> r_share = b_padded_bits.get_ptr_to_byte(nTriplesPerLoop, Z2<K + 2 * S>::N_BYTES);
|
|
Z2<K + 2 * S> r_mac;
|
|
r_mac.mul(r_share, this->machine.template get_mac_key<Z2<S>>());
|
|
for (int i = 0; i < this->nparties-1; i++)
|
|
r_mac += (ot_multipliers[i])->macs.at(1).at(nTriplesPerLoop);
|
|
Share<Z2<K + 2 * S>> r;
|
|
r.set_share(r_share);
|
|
r.set_mac(r_mac);
|
|
|
|
MC.set_random_element(r);
|
|
sacrificeZ2k(uncheckedTriples, MC, G);
|
|
}
|
|
}
|
|
|
|
template<>
|
|
void NPartyTripleGenerator<Spdz2kShare<32, 32>>::generateTriples()
|
|
{
|
|
this->generateTriplesZ2k<32, 32>();
|
|
}
|
|
|
|
template<>
|
|
void NPartyTripleGenerator<Spdz2kShare<64, 64>>::generateTriples()
|
|
{
|
|
this->generateTriplesZ2k<64, 64>();
|
|
}
|
|
|
|
template<>
|
|
void NPartyTripleGenerator<Spdz2kShare<64, 48>>::generateTriples()
|
|
{
|
|
this->generateTriplesZ2k<64, 48>();
|
|
}
|
|
|
|
template<>
|
|
void NPartyTripleGenerator<Spdz2kShare<66, 64>>::generateTriples()
|
|
{
|
|
this->generateTriplesZ2k<66, 64>();
|
|
}
|
|
|
|
template<>
|
|
void NPartyTripleGenerator<Spdz2kShare<66, 48>>::generateTriples()
|
|
{
|
|
this->generateTriplesZ2k<66, 48>();
|
|
}
|
|
|
|
template<class U>
|
|
void OTTripleGenerator<U>::generatePlainTriples()
|
|
{
|
|
machine.set_passive();
|
|
machine.output = false;
|
|
signal_multipliers(DATA_TRIPLE);
|
|
|
|
valueBits.resize(3);
|
|
for (int i = 0; i < 3; i++)
|
|
valueBits[i].resize(field_size * nPreampTriplesPerLoop);
|
|
|
|
start_progress();
|
|
for (int i = 0; i < nloops; i++)
|
|
plainTripleRound(i);
|
|
}
|
|
|
|
template<class U>
|
|
void OTTripleGenerator<U>::plainTripleRound(int k)
|
|
{
|
|
typedef typename U::open_type T;
|
|
|
|
if (not (machine.amplify or machine.output))
|
|
plainTriples.resize(nPreampTriplesPerLoop);
|
|
|
|
print_progress(k);
|
|
|
|
for (int j = 0; j < 2; j++)
|
|
valueBits[j].template randomize_blocks<T>(share_prg);
|
|
|
|
timers["OTs"].start();
|
|
for (int i = 0; i < nparties-1; i++)
|
|
ot_multipliers[i]->inbox.push({});
|
|
this->wait_for_multipliers();
|
|
timers["OTs"].stop();
|
|
|
|
for (int j = 0; j < nPreampTriplesPerLoop; j++)
|
|
{
|
|
T a((char*)valueBits[0].get_ptr() + j * T::size());
|
|
T b((char*)valueBits[1].get_ptr() + j / nAmplify * T::size());
|
|
T c = a * b;
|
|
timers["Triple computation"].start();
|
|
for (int i = 0; i < nparties-1; i++)
|
|
{
|
|
c += dynamic_cast<typename U::Multiplier*>(ot_multipliers[i])->c_output[j];
|
|
}
|
|
timers["Triple computation"].stop();
|
|
if (machine.amplify)
|
|
{
|
|
preampTriples[j/nAmplify].a[j%nAmplify] = a;
|
|
preampTriples[j/nAmplify].b = b;
|
|
preampTriples[j/nAmplify].c[j%nAmplify] = c;
|
|
}
|
|
else if (machine.output)
|
|
{
|
|
timers["Writing"].start();
|
|
a.output(outputFile, false);
|
|
b.output(outputFile, false);
|
|
c.output(outputFile, false);
|
|
timers["Writing"].stop();
|
|
}
|
|
else
|
|
{
|
|
plainTriples[j] = {{a, b, c}};
|
|
}
|
|
}
|
|
}
|
|
|
|
template<class U>
|
|
void NPartyTripleGenerator<U>::generateTriples()
|
|
{
|
|
typedef typename U::open_type T;
|
|
|
|
auto& timers = this->timers;
|
|
auto& machine = this->machine;
|
|
auto& nTriplesPerLoop = this->nTriplesPerLoop;
|
|
auto& valueBits = this->valueBits;
|
|
auto& ot_multipliers = this->ot_multipliers;
|
|
auto& nparties = this->nparties;
|
|
auto& globalPlayer = this->globalPlayer;
|
|
auto& nloops = this->nloops;
|
|
auto& preampTriples = this->preampTriples;
|
|
auto& outputFile = this->outputFile;
|
|
auto& field_size = this->field_size;
|
|
auto& nPreampTriplesPerLoop = this->nPreampTriplesPerLoop;
|
|
|
|
for (int i = 0; i < nparties-1; i++)
|
|
ot_multipliers[i]->inbox.push(DATA_TRIPLE);
|
|
|
|
valueBits.resize(3);
|
|
for (int i = 0; i < 2; i++)
|
|
valueBits[2*i].resize(field_size * nPreampTriplesPerLoop);
|
|
valueBits[1].resize(field_size * nTriplesPerLoop);
|
|
vector< PlainTriple<T,2> > amplifiedTriples;
|
|
MAC_Check<T> MC(machine.template get_mac_key<T>());
|
|
|
|
if (machine.amplify)
|
|
preampTriples.resize(nTriplesPerLoop);
|
|
if (machine.generateMACs)
|
|
{
|
|
amplifiedTriples.resize(nTriplesPerLoop);
|
|
uncheckedTriples.resize(nTriplesPerLoop);
|
|
}
|
|
|
|
this->start_progress();
|
|
|
|
for (int k = 0; k < nloops; k++)
|
|
{
|
|
this->plainTripleRound();
|
|
|
|
if (machine.amplify)
|
|
{
|
|
octet seed[SEED_SIZE];
|
|
Create_Random_Seed(seed, globalPlayer, SEED_SIZE);
|
|
PRNG G;
|
|
G.SetSeed(seed);
|
|
for (int iTriple = 0; iTriple < nTriplesPerLoop; iTriple++)
|
|
{
|
|
PlainTriple<T,2> triple;
|
|
triple.amplify(preampTriples[iTriple], G);
|
|
|
|
if (machine.generateMACs)
|
|
amplifiedTriples[iTriple] = triple;
|
|
else if (machine.output)
|
|
{
|
|
timers["Writing"].start();
|
|
triple.output(outputFile);
|
|
timers["Writing"].stop();
|
|
}
|
|
}
|
|
|
|
if (machine.generateMACs)
|
|
{
|
|
for (int iTriple = 0; iTriple < nTriplesPerLoop; iTriple++)
|
|
amplifiedTriples[iTriple].to(valueBits, iTriple);
|
|
|
|
for (int i = 0; i < nparties-1; i++)
|
|
ot_multipliers[i]->inbox.push({});
|
|
timers["Authentication OTs"].start();
|
|
this->wait_for_multipliers();
|
|
timers["Authentication OTs"].stop();
|
|
|
|
for (int iTriple = 0; iTriple < nTriplesPerLoop; iTriple++)
|
|
{
|
|
uncheckedTriples[iTriple].from(amplifiedTriples[iTriple], iTriple, *this);
|
|
|
|
if (!machine.check and machine.output)
|
|
{
|
|
timers["Writing"].start();
|
|
amplifiedTriples[iTriple].output(outputFile);
|
|
timers["Writing"].stop();
|
|
}
|
|
}
|
|
|
|
if (machine.check)
|
|
{
|
|
sacrifice(uncheckedTriples, MC, G);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
void NPartyTripleGenerator<T>::sacrifice(
|
|
vector<ShareTriple_<open_type, mac_key_type, 2> >& uncheckedTriples, typename T::MAC_Check& MC, PRNG& G)
|
|
{
|
|
auto& machine = this->machine;
|
|
auto& nTriplesPerLoop = this->nTriplesPerLoop;
|
|
auto& globalPlayer = this->globalPlayer;
|
|
auto& outputFile = this->outputFile;
|
|
|
|
vector<T> maskedAs(nTriplesPerLoop);
|
|
vector<TripleToSacrifice<open_type> > maskedTriples(nTriplesPerLoop);
|
|
for (int j = 0; j < nTriplesPerLoop; j++)
|
|
{
|
|
maskedTriples[j].prepare_sacrifice(uncheckedTriples[j], G);
|
|
maskedAs[j] = maskedTriples[j].a[0];
|
|
}
|
|
|
|
vector<open_type> openedAs(nTriplesPerLoop);
|
|
MC.POpen_Begin(openedAs, maskedAs, globalPlayer);
|
|
MC.POpen_End(openedAs, maskedAs, globalPlayer);
|
|
|
|
for (int j = 0; j < nTriplesPerLoop; j++) {
|
|
MC.AddToCheck(maskedTriples[j].computeCheckShare(openedAs[j]), 0,
|
|
globalPlayer);
|
|
}
|
|
|
|
MC.Check(globalPlayer);
|
|
|
|
if (machine.generateBits)
|
|
generateBitsFromTriples(uncheckedTriples, MC, outputFile);
|
|
else
|
|
if (machine.output)
|
|
for (int j = 0; j < nTriplesPerLoop; j++)
|
|
uncheckedTriples[j].output(outputFile, 1);
|
|
}
|
|
|
|
template<class W>
|
|
template<class U>
|
|
void NPartyTripleGenerator<W>::sacrificeZ2k(
|
|
vector<ShareTriple_<sacri_type, mac_key_type, 2> >& uncheckedTriples, U& MC, PRNG& G)
|
|
{
|
|
typedef sacri_type T;
|
|
typedef open_type V;
|
|
|
|
auto& machine = this->machine;
|
|
auto& nTriplesPerLoop = this->nTriplesPerLoop;
|
|
auto& globalPlayer = this->globalPlayer;
|
|
auto& outputFile = this->outputFile;
|
|
|
|
vector< Share<T> > maskedAs(nTriplesPerLoop);
|
|
vector<TripleToSacrifice<T> > maskedTriples(nTriplesPerLoop);
|
|
for (int j = 0; j < nTriplesPerLoop; j++)
|
|
{
|
|
// compute [p] = t * [a] - [ahat]
|
|
// and first part of [sigma], i.e., t * [c] - [chat]
|
|
maskedTriples[j].prepare_sacrifice(uncheckedTriples[j], G);
|
|
maskedAs[j] = maskedTriples[j].a[0];
|
|
}
|
|
|
|
vector<T> openedAs(nTriplesPerLoop);
|
|
MC.POpen_Begin(openedAs, maskedAs, globalPlayer);
|
|
MC.POpen_End(openedAs, maskedAs, globalPlayer);
|
|
|
|
vector<Share<T>> sigmas;
|
|
for (int j = 0; j < nTriplesPerLoop; j++) {
|
|
// compute t * [c] - [chat] - [b] * p
|
|
sigmas.push_back(maskedTriples[j].computeCheckShare(V(openedAs[j])));
|
|
}
|
|
vector<T> open_sigmas;
|
|
|
|
MC.POpen_Begin(open_sigmas, sigmas, globalPlayer);
|
|
MC.POpen_End(open_sigmas, sigmas, globalPlayer);
|
|
MC.Check(globalPlayer);
|
|
|
|
for (int j = 0; j < nTriplesPerLoop; j++) {
|
|
if (V(open_sigmas[j]) != 0)
|
|
{
|
|
throw runtime_error("sacrifice fail");
|
|
}
|
|
}
|
|
|
|
if (machine.generateBits)
|
|
generateBitsFromTriples(uncheckedTriples, MC, outputFile);
|
|
else
|
|
if (machine.output)
|
|
for (int j = 0; j < nTriplesPerLoop; j++)
|
|
uncheckedTriples[j].template reduce<V>().output(outputFile, 1);
|
|
}
|
|
|
|
template<>
|
|
template<class U, class V, class W, int N>
|
|
void NPartyTripleGenerator<Share<gfp1>>::generateBitsFromTriples(
|
|
vector< ShareTriple_<U, V, N> >& triples, W& MC, ofstream& outputFile)
|
|
{
|
|
vector< Share<gfp1> > a_plus_b(nTriplesPerLoop), a_squared(nTriplesPerLoop);
|
|
for (int i = 0; i < nTriplesPerLoop; i++)
|
|
a_plus_b[i] = triples[i].a[0] + triples[i].b;
|
|
vector<gfp1> opened(nTriplesPerLoop);
|
|
MC.POpen_Begin(opened, a_plus_b, globalPlayer);
|
|
MC.POpen_End(opened, a_plus_b, globalPlayer);
|
|
for (int i = 0; i < nTriplesPerLoop; i++)
|
|
a_squared[i] = triples[i].a[0] * opened[i] - triples[i].c[0];
|
|
MC.POpen_Begin(opened, a_squared, globalPlayer);
|
|
MC.POpen_End(opened, a_squared, globalPlayer);
|
|
Share<gfp1> one(gfp1(1), globalPlayer.my_num(), MC.get_alphai());
|
|
bits.clear();
|
|
for (int i = 0; i < nTriplesPerLoop; i++)
|
|
{
|
|
gfp1 root = opened[i].sqrRoot();
|
|
if (root.is_zero())
|
|
continue;
|
|
Share<gfp1> bit = (triples[i].a[0] / root + one) / gfp1(2);
|
|
if (machine.output)
|
|
bit.output(outputFile, false);
|
|
else
|
|
bits.push_back(bit);
|
|
}
|
|
}
|
|
|
|
template<class T>
|
|
template<class U, class V, class W, int N>
|
|
void NPartyTripleGenerator<T>::generateBitsFromTriples(
|
|
vector< ShareTriple_<U, V, N> >& triples, W& MC, ofstream& outputFile)
|
|
{
|
|
throw how_would_that_work();
|
|
// warning gymnastics
|
|
triples[0];
|
|
MC.number();
|
|
outputFile << "";
|
|
}
|
|
|
|
template <class T>
|
|
void OTTripleGenerator<T>::start_progress()
|
|
{
|
|
wait_for_multipliers();
|
|
lock();
|
|
signal();
|
|
wait();
|
|
gettimeofday(&last_lap, 0);
|
|
}
|
|
|
|
template<class T>
|
|
void OTTripleGenerator<T>::print_progress(int k)
|
|
{
|
|
if (thread_num == 0 && my_num == 0)
|
|
{
|
|
struct timeval stop;
|
|
gettimeofday(&stop, 0);
|
|
if (timeval_diff_in_seconds(&last_lap, &stop) > 1)
|
|
{
|
|
double diff = timeval_diff_in_seconds(&machine.start, &stop);
|
|
double throughput = k * nTriplesPerLoop * machine.nthreads / diff;
|
|
double remaining = diff * (nloops - k) / k;
|
|
cout << k << '/' << nloops << ", throughput: " << throughput
|
|
<< ", time left: " << remaining << ", elapsed: " << diff
|
|
<< ", estimated total: " << (diff + remaining) << endl;
|
|
last_lap = stop;
|
|
}
|
|
}
|
|
}
|
|
|
|
void MascotGenerator::lock()
|
|
{
|
|
pthread_mutex_lock(&mutex);
|
|
}
|
|
|
|
void MascotGenerator::unlock()
|
|
{
|
|
pthread_mutex_unlock(&mutex);
|
|
}
|
|
|
|
void MascotGenerator::signal()
|
|
{
|
|
pthread_cond_signal(&ready);
|
|
}
|
|
|
|
void MascotGenerator::wait()
|
|
{
|
|
if (multi_threaded)
|
|
pthread_cond_wait(&ready, &mutex);
|
|
}
|
|
|
|
template<class T>
|
|
void OTTripleGenerator<T>::signal_multipliers(MultJob job)
|
|
{
|
|
for (int i = 0; i < nparties-1; i++)
|
|
ot_multipliers[i]->inbox.push(job);
|
|
}
|
|
|
|
template<class T>
|
|
void OTTripleGenerator<T>::wait_for_multipliers()
|
|
{
|
|
for (int i = 0; i < nparties-1; i++)
|
|
ot_multipliers[i]->outbox.pop();
|
|
}
|
|
|
|
|
|
template class NPartyTripleGenerator<Share<gf2n_long>>;
|
|
template class NPartyTripleGenerator<Share<gf2n_short>>;
|
|
template class NPartyTripleGenerator<Share<gfp1>>;
|
|
|
|
template class OTTripleGenerator<SemiShare<gf2n>>;
|
|
template class OTTripleGenerator<SemiShare<gfp1>>;
|
|
template class OTTripleGenerator<Semi2kShare<64>>;
|
|
template class OTTripleGenerator<Semi2kShare<72>>;
|
|
|
|
template class NPartyTripleGenerator<Spdz2kShare<32, 32>>;
|
|
template class NPartyTripleGenerator<Spdz2kShare<64, 64>>;
|
|
template class NPartyTripleGenerator<Spdz2kShare<64, 48>>;
|
|
template class NPartyTripleGenerator<Spdz2kShare<66, 64>>;
|
|
template class NPartyTripleGenerator<Spdz2kShare<66, 48>>;
|