mirror of
https://github.com/data61/MP-SPDZ.git
synced 2026-01-10 05:57:57 -05:00
Semi-honest computation based on threshold semi-homomorphic encryption.
This commit is contained in:
@@ -25,7 +25,7 @@ void Binary_File_IO::write_to_file(const string filename,
|
||||
|
||||
if (start_pos != -1)
|
||||
{
|
||||
long write_pos = start_pos * T::size();
|
||||
long write_pos = file_signature<T>().get_total_length() + start_pos * T::size();
|
||||
// fill with zeros if needed
|
||||
for (long i = outf.tellp(); i < write_pos; i++)
|
||||
outf.put(0);
|
||||
@@ -50,10 +50,13 @@ void Binary_File_IO::read_from_file(const string filename, vector< T >& buffer,
|
||||
inf.open(filename, ios::in | ios::binary);
|
||||
if (inf.fail()) { throw file_missing(filename, "Binary_File_IO.read_from_file expects this file to exist."); }
|
||||
|
||||
check_file_signature<T>(inf, filename).get_length();
|
||||
auto data_start = inf.tellg();
|
||||
|
||||
int size_in_bytes = T::size() * buffer.size();
|
||||
int n_read = 0;
|
||||
char read_buffer[size_in_bytes];
|
||||
inf.seekg(start_posn * T::size());
|
||||
inf.seekg(start_posn * T::size(), iostream::cur);
|
||||
do
|
||||
{
|
||||
inf.read(read_buffer + n_read, size_in_bytes - n_read);
|
||||
@@ -62,7 +65,9 @@ void Binary_File_IO::read_from_file(const string filename, vector< T >& buffer,
|
||||
if (inf.eof())
|
||||
{
|
||||
stringstream ss;
|
||||
ss << "Got to EOF when reading from disk (expecting " << size_in_bytes << " bytes).";
|
||||
ss << "Got to EOF when reading from disk (expecting " << size_in_bytes
|
||||
<< " bytes from " << (long(data_start) + start_posn * T::size())
|
||||
<< ").";
|
||||
throw file_error(ss.str());
|
||||
}
|
||||
if (inf.fail())
|
||||
@@ -74,7 +79,7 @@ void Binary_File_IO::read_from_file(const string filename, vector< T >& buffer,
|
||||
}
|
||||
while (n_read < size_in_bytes);
|
||||
|
||||
end_posn = inf.tellg() / T::size();
|
||||
end_posn = (inf.tellg() - data_start) / T::size();
|
||||
assert (end_posn == start_posn + int(buffer.size()));
|
||||
|
||||
//Check if at end of file by getting 1 more char.
|
||||
|
||||
@@ -32,6 +32,15 @@ protected:
|
||||
Buffer<typename T::clear, typename T::clear> buffer;
|
||||
Timer timer;
|
||||
|
||||
// Send my inputs (not generally available)
|
||||
virtual void send_mine() { throw not_implemented(); }
|
||||
// Get share for next input of mine (not generally available)
|
||||
virtual T finalize_mine() { throw not_implemented(); }
|
||||
// Store share for next input from ``player`` from buffer ``o``
|
||||
// in ``target`` (not generally available)
|
||||
virtual void finalize_other(int, T&, octetStream&, int = -1)
|
||||
{ throw not_implemented(); }
|
||||
|
||||
public:
|
||||
vector<octetStream> os;
|
||||
int values_input;
|
||||
@@ -61,18 +70,12 @@ public:
|
||||
/// Schedule input from other player
|
||||
virtual void add_other(int player, int n_bits = -1) = 0;
|
||||
/// Schedule input from all players
|
||||
void add_from_all(const clear& input, int n_bits = -1);
|
||||
void add_from_all(const typename T::open_type& input, int n_bits = -1);
|
||||
|
||||
/// Send my inputs
|
||||
virtual void send_mine() = 0;
|
||||
/// Run input protocol for all players
|
||||
virtual void exchange();
|
||||
|
||||
/// Get share for next input of mine
|
||||
virtual T finalize_mine() = 0;
|
||||
/// Store share for next input from ``player`` from buffer ``o`` in ``target``
|
||||
virtual void finalize_other(int player, T& target, octetStream& o, int n_bits = -1) = 0;
|
||||
/// Get share for next input from ``player`
|
||||
/// Get share for next input from ``player``
|
||||
virtual T finalize(int player, int n_bits = -1);
|
||||
|
||||
void raw_input(SubProcessor<T>& proc, const vector<int>& args, int size);
|
||||
|
||||
@@ -113,7 +113,7 @@ void Input<T>::add_other(int player, int)
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void InputBase<T>::add_from_all(const clear& input, int n_bits)
|
||||
void InputBase<T>::add_from_all(const typename T::open_type& input, int n_bits)
|
||||
{
|
||||
for (int i = 0; i < P->num_players(); i++)
|
||||
if (i == P->my_num())
|
||||
|
||||
@@ -106,6 +106,7 @@ enum
|
||||
MATMULSM = 0xAB,
|
||||
CONV2DS = 0xAC,
|
||||
CHECK = 0xAF,
|
||||
PRIVATEOUTPUT = 0xAD,
|
||||
// Data access
|
||||
TRIPLE = 0x50,
|
||||
BIT = 0x51,
|
||||
@@ -127,6 +128,7 @@ enum
|
||||
INPUTMIXEDREG = 0xF3,
|
||||
RAWINPUT = 0xF4,
|
||||
INPUTPERSONAL = 0xF5,
|
||||
SENDPERSONAL = 0xF6,
|
||||
STARTINPUT = 0x61,
|
||||
STOPINPUT = 0x62,
|
||||
READSOCKETC = 0x63,
|
||||
|
||||
@@ -200,14 +200,17 @@ void BaseInstruction::parse_operands(istream& s, int pos, int file_pos)
|
||||
case USE:
|
||||
case USE_INP:
|
||||
case USE_EDABIT:
|
||||
case DIGESTC:
|
||||
case INPUTMASK:
|
||||
case GINPUTMASK:
|
||||
get_ints(r, s, 2);
|
||||
n = get_int(s);
|
||||
break;
|
||||
case STARTPRIVATEOUTPUT:
|
||||
case GSTARTPRIVATEOUTPUT:
|
||||
case STOPPRIVATEOUTPUT:
|
||||
case GSTOPPRIVATEOUTPUT:
|
||||
case DIGESTC:
|
||||
get_ints(r, s, 2);
|
||||
n = get_int(s);
|
||||
break;
|
||||
throw runtime_error("two-stage private output not supported any more");
|
||||
case USE_MATMUL:
|
||||
get_ints(r, s, 3);
|
||||
n = get_int(s);
|
||||
@@ -237,8 +240,6 @@ void BaseInstruction::parse_operands(istream& s, int pos, int file_pos)
|
||||
case PRINTREGB:
|
||||
case GPRINTREG:
|
||||
case LDINT:
|
||||
case INPUTMASK:
|
||||
case GINPUTMASK:
|
||||
case INV2M:
|
||||
case CONDPRINTSTR:
|
||||
case CONDPRINTSTRB:
|
||||
@@ -290,6 +291,8 @@ void BaseInstruction::parse_operands(istream& s, int pos, int file_pos)
|
||||
case RAWINPUT:
|
||||
case GRAWINPUT:
|
||||
case INPUTPERSONAL:
|
||||
case SENDPERSONAL:
|
||||
case PRIVATEOUTPUT:
|
||||
case TRUNC_PR:
|
||||
case RUN_TAPE:
|
||||
num_var_args = get_int(s);
|
||||
@@ -599,6 +602,7 @@ int BaseInstruction::get_reg_type() const
|
||||
case PUBINPUT:
|
||||
case FLOATOUTPUT:
|
||||
case READSOCKETC:
|
||||
case PRIVATEOUTPUT:
|
||||
return CINT;
|
||||
default:
|
||||
if (is_gf2n_instruction())
|
||||
@@ -738,10 +742,16 @@ unsigned BaseInstruction::get_max_reg(int reg_type) const
|
||||
skip = 1;
|
||||
break;
|
||||
case INPUTPERSONAL:
|
||||
case PRIVATEOUTPUT:
|
||||
size_offset = -2;
|
||||
offset = 2;
|
||||
skip = 4;
|
||||
break;
|
||||
case SENDPERSONAL:
|
||||
size_offset = -2;
|
||||
offset = 2;
|
||||
skip = 5;
|
||||
break;
|
||||
case READSOCKETS:
|
||||
case READSOCKETC:
|
||||
case READSOCKETINT:
|
||||
@@ -939,13 +949,11 @@ inline void Instruction::execute(Processor<sint, sgf2n>& Proc) const
|
||||
break;
|
||||
case INPUTMASK:
|
||||
Procp.DataF.get_input(Proc.get_Sp_ref(r[0]), Proc.temp.rrp, n);
|
||||
if (n == Proc.P.my_num())
|
||||
Proc.temp.rrp.output(Proc.private_output, false);
|
||||
Proc.write_Cp(r[1], Proc.temp.rrp);
|
||||
break;
|
||||
case GINPUTMASK:
|
||||
Proc2.DataF.get_input(Proc.get_S2_ref(r[0]), Proc.temp.ans2, n);
|
||||
if (n == Proc.P.my_num())
|
||||
Proc.temp.ans2.output(Proc.private_output, false);
|
||||
Proc.write_C2(r[1], Proc.temp.ans2);
|
||||
break;
|
||||
case INPUT:
|
||||
sint::Input::template input<IntInput<typename sint::clear>>(Proc.Procp, start, size);
|
||||
@@ -974,6 +982,12 @@ inline void Instruction::execute(Processor<sint, sgf2n>& Proc) const
|
||||
case INPUTPERSONAL:
|
||||
Proc.Procp.input_personal(start);
|
||||
return;
|
||||
case SENDPERSONAL:
|
||||
Proc.Procp.send_personal(start);
|
||||
return;
|
||||
case PRIVATEOUTPUT:
|
||||
Proc.Procp.private_output(start);
|
||||
return;
|
||||
// Note: Fp version has different semantics for NOTC than GNOTC
|
||||
case NOTC:
|
||||
to_bigint(Proc.temp.aa, Proc.read_Cp(r[1]));
|
||||
@@ -1202,18 +1216,6 @@ inline void Instruction::execute(Processor<sint, sgf2n>& Proc) const
|
||||
Proc.binary_output.write((char*) &tmp, sizeof(double));
|
||||
}
|
||||
break;
|
||||
case STARTPRIVATEOUTPUT:
|
||||
Proc.privateOutputp.start(n,r[0],r[1]);
|
||||
break;
|
||||
case GSTARTPRIVATEOUTPUT:
|
||||
Proc.privateOutput2.start(n,r[0],r[1]);
|
||||
break;
|
||||
case STOPPRIVATEOUTPUT:
|
||||
Proc.privateOutputp.stop(n,r[0],r[1]);
|
||||
break;
|
||||
case GSTOPPRIVATEOUTPUT:
|
||||
Proc.privateOutput2.stop(n,r[0],r[1]);
|
||||
break;
|
||||
case PREP:
|
||||
Procp.DataF.get(Proc.Procp.get_S(), r, start, size);
|
||||
return;
|
||||
|
||||
@@ -97,12 +97,19 @@ Machine<sint, sgf2n>::Machine(int my_number, Names& playerNames,
|
||||
// initialize persistence if necessary
|
||||
for (auto& prog : progs)
|
||||
{
|
||||
if (prog.writes_persistance)
|
||||
if (prog.writes_persistence)
|
||||
{
|
||||
string filename = Binary_File_IO::filename(my_number);
|
||||
ifstream pers(filename);
|
||||
if (pers.fail())
|
||||
ofstream pers(filename, ios::binary);
|
||||
try
|
||||
{
|
||||
check_file_signature<sint>(pers, filename);
|
||||
}
|
||||
catch (signature_mismatch&)
|
||||
{
|
||||
ofstream pers(filename, ios::binary);
|
||||
file_signature<sint>().output(pers);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -418,12 +425,14 @@ void Machine<sint, sgf2n>::run()
|
||||
cerr << "Full broadcast" << endl;
|
||||
#endif
|
||||
|
||||
#ifdef CHOP_MEMORY
|
||||
// Reduce memory size to speed up
|
||||
unsigned max_size = 1 << 20;
|
||||
if (M2.size_s() > max_size)
|
||||
M2.resize_s(max_size);
|
||||
if (Mp.size_s() > max_size)
|
||||
Mp.resize_s(max_size);
|
||||
#endif
|
||||
|
||||
// Write out the memory to use next time
|
||||
ofstream outf(memory_filename(), ios::out | ios::binary);
|
||||
|
||||
@@ -44,9 +44,9 @@ class Memory
|
||||
static void check_index(const vector<U>& M, size_t i)
|
||||
{
|
||||
(void) M, (void) i;
|
||||
#ifdef NO_CHECK_INDEX
|
||||
#ifndef NO_CHECK_INDEX
|
||||
if (i >= M.size())
|
||||
throw overflow("memory", i, M.size());
|
||||
throw overflow(U::type_string() + " memory", i, M.size());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,9 @@ void MemoryPart<T>::minimum_size(size_t size)
|
||||
{
|
||||
if (size > this->size())
|
||||
this->resize(size);
|
||||
#ifdef DEBUG_MEMORY_SIZE
|
||||
cerr << T::type_string() << " memory has now size " << this->size() << endl;
|
||||
#endif
|
||||
}
|
||||
catch (bad_alloc&)
|
||||
{
|
||||
@@ -58,9 +61,9 @@ istream& operator>>(istream& s,Memory<T>& M)
|
||||
int len;
|
||||
|
||||
s >> len;
|
||||
M.resize_s(len);
|
||||
M.MS.minimum_size(len);
|
||||
s >> len;
|
||||
M.resize_c(len);
|
||||
M.MC.minimum_size(len);
|
||||
s.seekg(1, istream::cur);
|
||||
|
||||
for (unsigned int i=0; i<M.MS.size(); i++)
|
||||
|
||||
@@ -17,16 +17,16 @@ class PrivateOutput
|
||||
typedef typename T::open_type open_type;
|
||||
|
||||
SubProcessor<T>& proc;
|
||||
typename T::MAC_Check MC;
|
||||
deque<open_type> masks;
|
||||
|
||||
public:
|
||||
PrivateOutput(SubProcessor<T>& proc) : proc(proc) { };
|
||||
PrivateOutput(SubProcessor<T>& proc);
|
||||
~PrivateOutput();
|
||||
|
||||
void start(int player, int target, int source);
|
||||
void stop(int player, int dest, int source);
|
||||
|
||||
T start(int player, const T& source);
|
||||
typename T::clear stop(int player, const typename T::clear& masked);
|
||||
void prepare_sending(const T& source, int player);
|
||||
void exchange();
|
||||
typename T::clear finalize(int player);
|
||||
};
|
||||
|
||||
#endif /* PROCESSOR_PRIVATEOUTPUT_H_ */
|
||||
|
||||
@@ -7,13 +7,21 @@
|
||||
#include "Processor.h"
|
||||
|
||||
template<class T>
|
||||
void PrivateOutput<T>::start(int player, int target, int source)
|
||||
PrivateOutput<T>::PrivateOutput(SubProcessor<T>& proc) :
|
||||
proc(proc), MC(proc.MC.get_alphai())
|
||||
{
|
||||
proc.get_S_ref(target) = start(player, proc.get_S_ref(source));
|
||||
MC.init_open(proc.P);
|
||||
MC.set_prep(proc.DataF);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T PrivateOutput<T>::start(int player, const T& source)
|
||||
PrivateOutput<T>::~PrivateOutput()
|
||||
{
|
||||
MC.Check(proc.P);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void PrivateOutput<T>::prepare_sending(const T& source, int player)
|
||||
{
|
||||
assert (player < proc.P.num_players());
|
||||
open_type mask;
|
||||
@@ -24,26 +32,25 @@ T PrivateOutput<T>::start(int player, const T& source)
|
||||
if (player == proc.P.my_num())
|
||||
masks.push_back(mask);
|
||||
|
||||
return res;
|
||||
MC.prepare_open(res);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void PrivateOutput<T>::stop(int player, int dest, int source)
|
||||
void PrivateOutput<T>::exchange()
|
||||
{
|
||||
auto& value = proc.get_C_ref(dest);
|
||||
value = stop(player, proc.get_C_ref(source));
|
||||
if (proc.Proc)
|
||||
value.output(proc.Proc->private_output, false);
|
||||
MC.exchange(proc.P);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
typename T::clear PrivateOutput<T>::stop(int player, const typename T::clear& source)
|
||||
typename T::clear PrivateOutput<T>::finalize(int player)
|
||||
{
|
||||
typename T::clear value;
|
||||
auto res = MC.finalize_open();
|
||||
|
||||
if (player == proc.P.my_num())
|
||||
{
|
||||
value = source - masks.front();
|
||||
res -= masks.front();
|
||||
masks.pop_front();
|
||||
}
|
||||
return value;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -71,6 +71,8 @@ public:
|
||||
void conv2ds(const Instruction& instruction);
|
||||
|
||||
void input_personal(const vector<int>& args);
|
||||
void send_personal(const vector<int>& args);
|
||||
void private_output(const vector<int>& args);
|
||||
|
||||
CheckVector<T>& get_S()
|
||||
{
|
||||
@@ -110,7 +112,6 @@ public:
|
||||
ifstream private_input;
|
||||
ifstream public_input;
|
||||
ofstream public_output;
|
||||
ofstream private_output;
|
||||
ofstream binary_output;
|
||||
|
||||
int sent, rounds;
|
||||
@@ -172,9 +173,6 @@ class Processor : public ArithmeticProcessor
|
||||
SubProcessor<sgf2n> Proc2;
|
||||
SubProcessor<sint> Procp;
|
||||
|
||||
typename sgf2n::PrivateOutput privateOutput2;
|
||||
typename sint::PrivateOutput privateOutputp;
|
||||
|
||||
unsigned int PC;
|
||||
TempVars<sint, sgf2n> temp;
|
||||
|
||||
|
||||
@@ -4,9 +4,8 @@
|
||||
#include "Processor/Processor.h"
|
||||
#include "Processor/Program.h"
|
||||
#include "GC/square64.h"
|
||||
#include "SpecificPrivateOutput.h"
|
||||
|
||||
#include "Protocols/ReplicatedInput.hpp"
|
||||
#include "Protocols/ReplicatedPrivateOutput.hpp"
|
||||
#include "Processor/ProcessorBase.hpp"
|
||||
#include "GC/Processor.hpp"
|
||||
#include "GC/ShareThread.hpp"
|
||||
@@ -63,7 +62,6 @@ Processor<sint, sgf2n>::Processor(int thread_num,Player& P,
|
||||
share_thread(DataF.DataFb, P, machine.get_bit_mac_key()),
|
||||
Procb(machine.bit_memories),
|
||||
Proc2(*this,MC2,DataF.DataF2,P),Procp(*this,MCp,DataF.DataFp,P),
|
||||
privateOutput2(Proc2),privateOutputp(Procp),
|
||||
external_clients(P.my_num()),
|
||||
binary_file_io(Binary_File_IO())
|
||||
{
|
||||
@@ -74,7 +72,6 @@ Processor<sint, sgf2n>::Processor(int thread_num,Player& P,
|
||||
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);
|
||||
binary_output.open(
|
||||
get_parameterized_filename(P.my_num(), thread_num,
|
||||
PREP_DIR "Binary-Output"), ios_base::out);
|
||||
@@ -654,6 +651,37 @@ void SubProcessor<T>::input_personal(const vector<int>& args)
|
||||
S[args[i + 2] + j] = input.finalize(args[i + 1]);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void SubProcessor<T>::private_output(const vector<int>& args)
|
||||
{
|
||||
typename T::PrivateOutput output(*this);
|
||||
for (size_t i = 0; i < args.size(); i += 4)
|
||||
for (int j = 0; j < args[i]; j++)
|
||||
{
|
||||
int player = args[i + 1];
|
||||
output.prepare_sending(S.at(args[i + 3] + j), player);
|
||||
}
|
||||
output.exchange();
|
||||
for (size_t i = 0; i < args.size(); i += 4)
|
||||
for (int j = 0; j < args[i]; j++)
|
||||
C.at(args[i + 2] + j) = output.finalize(args[i + 1]);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void SubProcessor<T>::send_personal(const vector<int>& args)
|
||||
{
|
||||
octetStreams to_send(P), to_receive(P);
|
||||
for (size_t i = 0; i < args.size(); i += 5)
|
||||
if (args[i + 3] == P.my_num())
|
||||
for (int j = 0; j < args[i]; j++)
|
||||
C[args[i + 4] + j].pack(to_send[args[i + 1]]);
|
||||
P.send_receive_all(to_send, to_receive);
|
||||
for (size_t i = 0; i < args.size(); i += 5)
|
||||
if (args[i + 1] == P.my_num())
|
||||
for (int j = 0; j < args[i]; j++)
|
||||
C[args[i + 2] + j].unpack(to_receive[args[i + 3]]);
|
||||
}
|
||||
|
||||
template<class sint, class sgf2n>
|
||||
typename sint::clear Processor<sint, sgf2n>::get_inverse2(unsigned m)
|
||||
{
|
||||
|
||||
@@ -23,7 +23,7 @@ void Program::compute_constants()
|
||||
max_mem[reg_type] = max(max_mem[reg_type],
|
||||
p[i].get_mem(RegType(reg_type)));
|
||||
}
|
||||
writes_persistance |= p[i].opcode == WRITEFILESHARE;
|
||||
writes_persistence |= p[i].opcode == WRITEFILESHARE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,10 +30,10 @@ class Program
|
||||
|
||||
public:
|
||||
|
||||
bool writes_persistance;
|
||||
bool writes_persistence;
|
||||
|
||||
Program(int nplayers) : offline_data_used(nplayers),
|
||||
unknown_usage(false), writes_persistance(false)
|
||||
unknown_usage(false), writes_persistence(false)
|
||||
{ compute_constants(); }
|
||||
|
||||
// Read in a program
|
||||
|
||||
65
Processor/SpecificPrivateOutput.h
Normal file
65
Processor/SpecificPrivateOutput.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* SpecificPrivateOutput.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PROCESSOR_SPECIFICPRIVATEOUTPUT_H_
|
||||
#define PROCESSOR_SPECIFICPRIVATEOUTPUT_H_
|
||||
|
||||
template<class T>
|
||||
class SpecificPrivateOutput
|
||||
{
|
||||
deque<T> secrets;
|
||||
vector<typename T::PO*> pos;
|
||||
Player& P;
|
||||
vector<bool> active;
|
||||
|
||||
public:
|
||||
SpecificPrivateOutput(SubProcessor<T>& proc) :
|
||||
P(proc.P)
|
||||
{
|
||||
for (int i = 0; i < P.num_players(); i++)
|
||||
pos.push_back(new typename T::PO(proc.P));
|
||||
active.resize(P.num_players());
|
||||
}
|
||||
|
||||
~SpecificPrivateOutput()
|
||||
{
|
||||
for (auto& x : pos)
|
||||
delete x;
|
||||
}
|
||||
|
||||
void prepare_sending(const T& secret, int player)
|
||||
{
|
||||
pos[player]->prepare_sending(secret, player);
|
||||
if (P.my_num() == player)
|
||||
secrets.push_back(secret);
|
||||
active[player] = true;
|
||||
}
|
||||
|
||||
void exchange()
|
||||
{
|
||||
for (int i = 0; i < this->P.num_players(); i++)
|
||||
if (active[i])
|
||||
{
|
||||
if (i == this->P.my_num())
|
||||
pos[i]->receive();
|
||||
else
|
||||
pos[i]->send(i);
|
||||
}
|
||||
}
|
||||
|
||||
typename T::clear finalize(int player)
|
||||
{
|
||||
if (player == this->P.my_num())
|
||||
{
|
||||
T secret = secrets.front();
|
||||
secrets.pop_front();
|
||||
return pos[player]->finalize(secret);
|
||||
}
|
||||
else
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* PROCESSOR_SPECIFICPRIVATEOUTPUT_H_ */
|
||||
Reference in New Issue
Block a user