Files
MP-SPDZ/FHEOffline/Sacrificing.cpp
2019-06-07 15:26:28 +10:00

531 lines
16 KiB
C++

/*
* Checking.cpp
*
*/
#include "FHE/P2Data.h"
#include "Sacrificing.h"
#include "Producer.h"
#include "Tools/Subroutines.h"
// The number of sacrifices to amortize at one time
#define amortize 512
template<class T>
inline FileSacriFactory<T>::FileSacriFactory(const char* type, const Player& P,
int output_thread)
{
typename T::clear dummy;
/* Open file for reading in the initial triples */
stringstream file1;
file1 << PREP_DIR "Initial-" << type << "-" << file_completion(dummy)
<< "-P" << P.my_num();
if (output_thread)
file1 << "-" << output_thread;
this->inpf.open(file1.str().c_str(),ios::in | ios::binary);
if (this->inpf.fail()) { throw file_error(); }
}
template<class T>
inline void FileSacriFactory<T>::get(T& a, T& b, T& c)
{
a.input(this->inpf, false);
b.input(this->inpf, false);
c.input(this->inpf, false);
}
template<class T>
inline void FileSacriFactory<T>::get(T& a, T& b)
{
a.input(this->inpf, false);
b.input(this->inpf, false);
}
template<class T>
inline void FileSacriFactory<T>::get(T& a)
{
a.input(this->inpf, false);
}
void Triple_Inverse_Checking(const Player& P, MAC_Check<gfp>& MC, int nm,
int nr, int output_thread)
{
gfp dummy;
printf("Doing Main Triple/Inverse Checking: %s\n",file_completion(dummy).c_str());
FileSacriFactory< Share<gfp> > triple_factory("Triples", P, output_thread);
FileSacriFactory< Share<gfp> > inverse_factory("Inverses", P, output_thread);
Triple_Checking(P, MC, nm, output_thread, triple_factory);
Inverse_Checking(P, MC, nr, output_thread, triple_factory, inverse_factory);
printf("Finished Main Triple/Inverse Checking: %s\n",file_completion(dummy).c_str());
}
template <class T>
void Triple_Checking(const Player& P, MAC_Check<T>& MC, int nm,
int output_thread, TripleSacriFactory< Share<T> >& factory, bool write_output,
bool clear, string dir)
{
ofstream outf;
if (write_output)
open_prep_file<T>(outf, "Triples", P.my_num(), output_thread, false,
clear, dir);
T te,t;
Create_Random(t,P);
vector<Share<T> > Sh_PO(2*amortize),Sh_Tau(amortize);
vector<T> PO(2*amortize),Tau(amortize);
vector<Share<T> > a1(amortize),b1(amortize),c1(amortize);
vector<Share<T> > a2(amortize),b2(amortize),c2(amortize);
Share<T> temp;
// Triple checking
int left_todo=nm;
while (left_todo>0)
{ int this_loop=amortize;
if (this_loop>left_todo)
{ this_loop=left_todo;
PO.resize(2*this_loop);
Sh_PO.resize(2*this_loop);
Tau.resize(this_loop);
Sh_Tau.resize(this_loop);
}
for (int i=0; i<this_loop; i++)
{
factory.get(a1[i], b1[i], c1[i]);
factory.get(a2[i], b2[i], c2[i]);
Sh_PO[2*i].mul(a1[i],t);
Sh_PO[2*i].sub(Sh_PO[2*i],a2[i]);
Sh_PO[2*i+1].sub(b1[i],b2[i]);
}
MC.POpen_Begin(PO,Sh_PO,P);
MC.POpen_End(PO,Sh_PO,P);
for (int i=0; i<this_loop; i++)
{ Sh_Tau[i].mul(c1[i],t);
Sh_Tau[i].sub(Sh_Tau[i],c2[i]);
temp.mul(a2[i],PO[2*i+1]);
Sh_Tau[i].sub(Sh_Tau[i],temp);
temp.mul(b2[i],PO[2*i]);
Sh_Tau[i].sub(Sh_Tau[i],temp);
te.mul(PO[2*i],PO[2*i+1]);
Sh_Tau[i].sub(Sh_Tau[i],te,P.my_num(),MC.get_alphai());
}
MC.POpen_Begin(Tau,Sh_Tau,P);
MC.POpen_End(Tau,Sh_Tau,P);
for (int i=0; i<this_loop; i++)
{ if (!Tau[i].is_zero())
{ throw Offline_Check_Error("Multiplication Triples"); }
if (write_output)
{
a1[i].output(outf,false);
b1[i].output(outf,false);
c1[i].output(outf,false);
}
else
factory.triples.push_back({{a1[i], b1[i], c1[i]}});
}
left_todo-=this_loop;
}
if (write_output)
outf.close();
}
template <class T>
void Inverse_Checking(const Player& P, MAC_Check<T>& MC, int nr,
int output_thread, TripleSacriFactory<Share<T> >& triple_factory,
TupleSacriFactory<Share<T> >& inverse_factor, bool write_output,
bool clear, string dir)
{
ofstream outf_inv;
if (write_output)
open_prep_file<T>(outf_inv, "Inverses", P.my_num(), output_thread, false,
clear, dir);
T te,t;
Create_Random(t,P);
vector<Share<T> > Sh_PO(2*amortize),Sh_Tau(amortize);
vector<T> PO(2*amortize),Tau(amortize);
vector<Share<T> > a1(amortize),b1(amortize),c1(amortize);
vector<Share<T> > a2(amortize),b2(amortize),c2(amortize);
Share<T> temp;
// Inverse checking
int left_todo=nr;
while (left_todo>0)
{ int this_loop=amortize;
if (this_loop>left_todo)
{ this_loop=left_todo;
PO.resize(2*this_loop);
Sh_PO.resize(2*this_loop);
Tau.resize(this_loop);
Sh_Tau.resize(this_loop);
}
for (int i=0; i<this_loop; i++)
{
inverse_factor.get(a1[i], b1[i]);
triple_factory.get(a2[i], b2[i], c2[i]);
Sh_PO[2*i].mul(a1[i],t);
Sh_PO[2*i].sub(Sh_PO[2*i],a2[i]);
Sh_PO[2*i+1].sub(b1[i],b2[i]);
}
MC.POpen_Begin(PO,Sh_PO,P);
MC.POpen_End(PO,Sh_PO,P);
for (int i=0; i<this_loop; i++)
{
Sh_Tau[i].sub(c2[i],t,P.my_num(),MC.get_alphai());
temp.mul(a2[i],PO[2*i+1]);
Sh_Tau[i].add(Sh_Tau[i],temp);
temp.mul(b1[i],PO[2*i]);
Sh_Tau[i].add(Sh_Tau[i],temp);
}
MC.POpen_Begin(Tau,Sh_Tau,P);
MC.POpen_End(Tau,Sh_Tau,P);
for (int i=0; i<this_loop; i++)
{ if (!Tau[i].is_zero())
{ throw Offline_Check_Error("Inverses"); }
if (write_output)
{
a1[i].output(outf_inv,false);
b1[i].output(outf_inv,false);
}
}
left_todo-=this_loop;
}
if (write_output)
{
outf_inv.close();
}
}
void Triple_Checking(const Player& P,MAC_Check<gf2n_short>& MC,int nm)
{
gf2n_short dummy;
printf("Doing Main Triple Checking: %s\n",file_completion(dummy).c_str());
/* Open file for reading in the initial triples */
stringstream file1; file1 << PREP_DIR "Initial-Triples-" << file_completion(dummy) << "-P" << P.my_num();
ifstream inpf(file1.str().c_str(),ios::in | ios::binary);
if (inpf.fail()) { throw file_error(); }
/* Open file for writing out the final triples */
stringstream file3; file3 << PREP_DIR "Triples-" << file_completion(dummy) << "-P" << P.my_num();
ofstream outf(file3.str().c_str(),ios::out | ios::binary);
if (outf.fail()) { throw file_error(); }
gf2n_short te,t;
Create_Random(t,P);
vector<Share<gf2n_short> > Sh_PO(2*amortize),Sh_Tau(amortize);
vector<gf2n_short> PO(2*amortize),Tau(amortize);
vector<Share<gf2n_short> > a1(amortize),b1(amortize),c1(amortize);
vector<Share<gf2n_short> > a2(amortize),b2(amortize),c2(amortize);
Share<gf2n_short> temp;
// Triple checking
int left_todo=nm;
while (left_todo>0)
{ int this_loop=amortize;
if (this_loop>left_todo)
{ this_loop=left_todo;
PO.resize(2*this_loop);
Sh_PO.resize(2*this_loop);
Tau.resize(this_loop);
Sh_Tau.resize(this_loop);
}
for (int i=0; i<this_loop; i++)
{ a1[i].input(inpf,false);
b1[i].input(inpf,false);
c1[i].input(inpf,false);
a2[i].input(inpf,false);
b2[i].input(inpf,false);
c2[i].input(inpf,false);
Sh_PO[2*i].mul(a1[i],t);
Sh_PO[2*i].sub(Sh_PO[2*i],a2[i]);
Sh_PO[2*i+1].sub(b1[i],b2[i]);
}
MC.POpen_Begin(PO,Sh_PO,P);
MC.POpen_End(PO,Sh_PO,P);
for (int i=0; i<this_loop; i++)
{ Sh_Tau[i].mul(c1[i],t);
Sh_Tau[i].sub(Sh_Tau[i],c2[i]);
temp.mul(a2[i],PO[2*i+1]);
Sh_Tau[i].sub(Sh_Tau[i],temp);
temp.mul(b2[i],PO[2*i]);
Sh_Tau[i].sub(Sh_Tau[i],temp);
te.mul(PO[2*i],PO[2*i+1]);
Sh_Tau[i].sub(Sh_Tau[i],te,P.my_num(),MC.get_alphai());
}
MC.POpen_Begin(Tau,Sh_Tau,P);
MC.POpen_End(Tau,Sh_Tau,P);
for (int i=0; i<this_loop; i++)
{ if (!Tau[i].is_zero())
{ throw Offline_Check_Error("Multiplication Triples"); }
a1[i].output(outf,false);
b1[i].output(outf,false);
c1[i].output(outf,false);
}
left_todo-=this_loop;
}
outf.close();
inpf.close();
printf("Finished Main Triple Checking: %s\n",file_completion(dummy).c_str());
}
void Square_Bit_Checking(const Player& P,MAC_Check<gfp>& MC,int ns,int nb)
{
gfp dummy;
printf("Doing Main Square/Bit Checking: %s\n",file_completion(dummy).c_str());
FileSacriFactory< Share<gfp> > square_factory("Squares", P, 0);
FileSacriFactory< Share<gfp> > bit_factory("Bits", P, 0);
Square_Checking(P, MC, ns, 0, square_factory, true);
Bit_Checking(P, MC, nb, 0, square_factory, bit_factory, true);
printf("Finished Main Square/Bit Checking: %s\n",file_completion(dummy).c_str());
}
template <class T>
void Square_Checking(const Player& P, MAC_Check<T>& MC, int ns,
int output_thread, TupleSacriFactory<Share<T> >& square_factory,
bool write_output, bool clear, string dir)
{
ofstream outf_s, outf_b;
if (write_output)
{
open_prep_file<T>(outf_s, "Squares", P.my_num(), output_thread, false, clear, dir);
}
T te,t,t2;
Create_Random(t,P);
t2.mul(t,t);
vector<Share<T> > Sh_PO(amortize);
vector<T> PO(amortize);
vector<Share<T> > f(amortize),h(amortize),a(amortize),b(amortize);
Share<T> temp;
// Do the square checking
int left_todo=ns;
while (left_todo>0)
{ int this_loop=amortize;
if (this_loop>left_todo)
{ this_loop=left_todo;
PO.resize(this_loop);
Sh_PO.resize(this_loop);
}
for (int i=0; i<this_loop; i++)
{
square_factory.get(f[i], h[i]);
square_factory.get(a[i], b[i]);
Sh_PO[i].mul(a[i],t);
Sh_PO[i].sub(Sh_PO[i],f[i]);
}
MC.POpen_Begin(PO,Sh_PO,P);
MC.POpen_End(PO,Sh_PO,P);
for (int i=0; i<this_loop; i++)
{ Sh_PO[i].mul(b[i],t2);
Sh_PO[i].sub(Sh_PO[i],h[i]);
temp.mul(a[i],t);
temp.add(temp,f[i]);
temp.mul(temp,PO[i]);
Sh_PO[i].sub(Sh_PO[i],temp);
}
MC.POpen_Begin(PO,Sh_PO,P);
MC.POpen_End(PO,Sh_PO,P);
for (int i=0; i<this_loop; i++)
{ if (!PO[i].is_zero())
{ throw Offline_Check_Error("Squares"); }
if (write_output)
{
a[i].output(outf_s,false); b[i].output(outf_s,false);
}
}
left_todo-=this_loop;
}
outf_s.close();
}
void Bit_Checking(const Player& P, MAC_Check<gfp>& MC, int nb,
int output_thread, TupleSacriFactory<Share<gfp> >& square_factory,
SingleSacriFactory<Share<gfp> >& bit_factory, bool write_output,
bool clear, string dir)
{
gfp dummy;
ofstream outf_b;
if (write_output)
open_prep_file<gfp>(outf_b, "Bits", P.my_num(), output_thread, false, clear,
dir);
gfp te,t,t2;
Create_Random(t,P);
t2.mul(t,t);
vector<Share<gfp> > Sh_PO(amortize);
vector<gfp> PO(amortize);
vector<Share<gfp> > f(amortize),h(amortize),a(amortize),b(amortize);
Share<gfp> temp;
// Do the bits checking
PO.resize(amortize);
Sh_PO.resize(amortize);
int left_todo=nb;
while (left_todo>0)
{ int this_loop=amortize;
if (this_loop>left_todo)
{ this_loop=left_todo;
PO.resize(this_loop);
Sh_PO.resize(this_loop);
}
for (int i=0; i<this_loop; i++)
{
square_factory.get(f[i], h[i]);
bit_factory.get(a[i]);
Sh_PO[i].mul(a[i],t);
Sh_PO[i].sub(Sh_PO[i],f[i]);
}
MC.POpen_Begin(PO,Sh_PO,P);
MC.POpen_End(PO,Sh_PO,P);
for (int i=0; i<this_loop; i++)
{ Sh_PO[i].mul(a[i],t2);
Sh_PO[i].sub(Sh_PO[i],h[i]);
temp.mul(a[i],t);
temp.add(temp,f[i]);
temp.mul(temp,PO[i]);
Sh_PO[i].sub(Sh_PO[i],temp);
}
MC.POpen_Begin(PO,Sh_PO,P);
MC.POpen_End(PO,Sh_PO,P);
for (int i=0; i<this_loop; i++)
{ if (!PO[i].is_zero())
{ throw Offline_Check_Error("Bits"); }
if (write_output)
a[i].output(outf_b,false);
}
left_todo-=this_loop;
}
outf_b.close();
}
void Square_Checking(const Player& P,MAC_Check<gf2n_short>& MC,int ns)
{
gf2n_short dummy;
printf("Doing Main Square Checking: %s\n",file_completion(dummy).c_str());
/* Open files for reading in the initial data */
stringstream file1; file1 << PREP_DIR "Initial-Squares-" << file_completion(dummy) << "-P" << P.my_num();
ifstream inpf_s(file1.str().c_str(),ios::in | ios::binary);
if (inpf_s.fail()) { throw file_error(); }
/* Open files for writing out the final data */
stringstream file3; file3 << PREP_DIR "Squares-" << file_completion(dummy) << "-P" << P.my_num();
ofstream outf_s(file3.str().c_str(),ios::out | ios::binary);
if (outf_s.fail()) { throw file_error(); }
gf2n_short te,t,t2;
Create_Random(t,P);
t2.mul(t,t);
vector<Share<gf2n_short> > Sh_PO(amortize);
vector<gf2n_short> PO(amortize);
vector<Share<gf2n_short> > f(amortize),h(amortize),a(amortize),b(amortize);
Share<gf2n_short> temp;
// Do the square checking
int left_todo=ns;
while (left_todo>0)
{ int this_loop=amortize;
if (this_loop>left_todo)
{ this_loop=left_todo;
PO.resize(this_loop);
Sh_PO.resize(this_loop);
}
for (int i=0; i<this_loop; i++)
{ f[i].input(inpf_s,false);
h[i].input(inpf_s,false);
a[i].input(inpf_s,false);
b[i].input(inpf_s,false);
Sh_PO[i].mul(a[i],t);
Sh_PO[i].sub(Sh_PO[i],f[i]);
}
MC.POpen_Begin(PO,Sh_PO,P);
MC.POpen_End(PO,Sh_PO,P);
for (int i=0; i<this_loop; i++)
{ Sh_PO[i].mul(b[i],t2);
Sh_PO[i].sub(Sh_PO[i],h[i]);
temp.mul(a[i],t);
temp.add(temp,f[i]);
temp.mul(temp,PO[i]);
Sh_PO[i].sub(Sh_PO[i],temp);
}
MC.POpen_Begin(PO,Sh_PO,P);
MC.POpen_End(PO,Sh_PO,P);
for (int i=0; i<this_loop; i++)
{ if (!PO[i].is_zero())
{ throw Offline_Check_Error("Squares"); }
a[i].output(outf_s,false); b[i].output(outf_s,false);
}
left_todo-=this_loop;
}
outf_s.close();
inpf_s.close();
printf("Finished Main Square Checking: %s\n",file_completion(dummy).c_str());
}
template void Triple_Checking(const Player& P, MAC_Check<gfp>& MC, int nm,
int output_thread, TripleSacriFactory<Share<gfp> >& factory,
bool write_output, bool clear, string dir);
template void Triple_Checking(const Player& P, MAC_Check<gf2n_short>& MC,
int nm, int output_thread,
TripleSacriFactory<Share<gf2n_short> >& factory, bool write_output,
bool clear, string dir);
template void Square_Checking(const Player& P, MAC_Check<gfp>& MC, int ns,
int output_thread, TupleSacriFactory<Share<gfp> >& square_factory,
bool write_output, bool clear, string dir);
template void Square_Checking(const Player& P, MAC_Check<gf2n_short>& MC,
int ns, int output_thread,
TupleSacriFactory<Share<gf2n_short> >& square_factory,
bool write_output, bool clear, string dir);
template void Inverse_Checking(const Player& P, MAC_Check<gfp>& MC, int nr,
int output_thread, TripleSacriFactory<Share<gfp> >& triple_factory,
TupleSacriFactory<Share<gfp> >& inverse_factor, bool write_output,
bool clear, string dir);
template void Inverse_Checking(const Player& P, MAC_Check<gf2n_short>& MC, int nr,
int output_thread, TripleSacriFactory<Share<gf2n_short> >& triple_factory,
TupleSacriFactory<Share<gf2n_short> >& inverse_factor, bool write_output,
bool clear, string dir);