Files
MP-SPDZ/Processor/OfflineMachine.hpp
2025-12-13 12:59:25 +11:00

197 lines
6.0 KiB
C++

/*
* DishonestMajorityOfflineMachine.hpp
*
*/
#ifndef PROCESSOR_OFFLINEMACHINE_HPP_
#define PROCESSOR_OFFLINEMACHINE_HPP_
#include "OfflineMachine.h"
#include "Protocols/mac_key.hpp"
#include "Tools/Buffer.h"
template<class W>
template<class V>
OfflineMachine<W>::OfflineMachine(int argc, const char** argv,
ez::ezOptionParser& opt, OnlineOptions& online_opts, V,
int nplayers) :
W(argc, argv, opt, online_opts, V(), nplayers), playerNames(
W::playerNames), P(*this->new_player("machine"))
{
load_schedule(online_opts.progname, false);
Program program(playerNames.num_players());
program.parse(bc_filenames[0]);
progs.push_back(program);
if (program.usage_unknown())
{
cerr << "Preprocessing will be insufficient "
<< "due to unknown requirements" << endl;
exit(1);
}
usage = program.get_offline_data_used();
}
template<class W>
OfflineMachine<W>::~OfflineMachine()
{
delete &P;
}
template<class W>
template<class T, class U>
int OfflineMachine<W>::run()
{
if (this->online_opts.prime)
T::clear::init_field(this->online_opts.prime);
else
T::clear::init_default(this->online_opts.prime_length());
Machine<T, U>::init_binary_domains(this->online_opts.security_parameter,
this->get_lg2());
auto binary_mac_key = read_generate_write_mac_key<
typename T::bit_type::part_type>(P);
typename T::bit_type::LivePrep bit_prep(usage);
GC::ShareThread<typename T::bit_type> thread(bit_prep, P, binary_mac_key);
// setup before generation to fix prime
T::LivePrep::basic_setup(P);
T::MAC_Check::setup(P);
T::bit_type::MAC_Check::setup(P);
U::MAC_Check::setup(P);
generate<T>();
generate<typename T::bit_type::part_type>();
generate<U>();
thread.MC->Check(P);
T::MAC_Check::teardown();
T::bit_type::MAC_Check::teardown();
U::MAC_Check::teardown();
return 0;
}
template<class W>
int OfflineMachine<W>::buffered_total(size_t required, size_t batch)
{
return DIV_CEIL(required, batch) * batch + (nthreads - 1) * batch;
}
template<class W>
template<class T>
void OfflineMachine<W>::generate()
{
T::clear::next::template init<typename T::clear>(false);
T::clear::template write_setup<T>(P.num_players());
auto mac_key = read_generate_write_mac_key<T>(P);
DataPositions generated;
generated.set_num_players(P.num_players());
typename T::MAC_Check output(mac_key);
typename T::LivePrep preprocessing(0, generated);
SubProcessor<T> processor(output, preprocessing, P);
auto& domain_usage = usage.files[T::clear::field_type()];
for (unsigned i = 0; i < domain_usage.size(); i++)
{
auto my_usage = domain_usage[i];
Dtype dtype = Dtype(i);
string filename = Sub_Data_Files<T>::get_filename(playerNames, dtype,
0);
if (my_usage > 0)
{
ofstream out(filename, iostream::out | iostream::binary);
file_signature<T>().output(out);
if (i == DATA_DABIT)
{
for (long long j = 0;
j < buffered_total(my_usage, BUFFER_SIZE); j++)
{
T a;
typename T::bit_type b;
preprocessing.get_dabit(a, b);
dabit<T>(a, b).output(out, false);
}
}
else if (not (i == DATA_RANDOM or i == DATA_OPEN))
{
vector<T> tuple(DataPositions::tuple_size[i]);
for (long long j = 0;
j < buffered_total(my_usage, BUFFER_SIZE); j++)
{
preprocessing.get(dtype, tuple.data());
for (auto& x : tuple)
x.output(out, false);
}
}
}
else
remove(filename.c_str());
}
long additional_inputs = Sub_Data_Files<T>::additional_inputs(usage);
for (int i = 0; i < P.num_players(); i++)
{
auto n_inputs = usage.inputs[i][T::clear::field_type()]
+ additional_inputs;
string filename = Sub_Data_Files<T>::get_input_filename(playerNames, i, 0);
if (n_inputs > 0)
{
ofstream out(filename, iostream::out | iostream::binary);
file_signature<T>().output(out);
InputTuple<T> tuple;
for (long long j = 0;
j < buffered_total(n_inputs, BUFFER_SIZE); j++)
{
preprocessing.get_input(tuple.share, tuple.value, i);
tuple.share.output(out, false);
if (i == P.my_num())
tuple.value.output(out, false);
}
}
else
remove(filename.c_str());
}
if (T::clear::field_type() == DATA_INT)
{
int max_n_bits = 0;
for (auto& x : usage.edabits)
max_n_bits = max(max_n_bits, x.first.second);
for (int n_bits = 1; n_bits < max(100, max_n_bits); n_bits++)
{
int batch = edabitvec<T>::MAX_SIZE;
int total = usage.edabits[{false, n_bits}] +
usage.edabits[{true, n_bits}];
string filename = Sub_Data_Files<T>::get_edabit_filename(playerNames,
n_bits, 0);
if (total > 0)
{
ofstream out(filename, ios::binary);
file_signature<T>().output(out);
auto& opts = OnlineOptions::singleton;
opts.batch_size = DIV_CEIL(opts.batch_size, batch) * batch;
for (int i = 0; i < buffered_total(total, batch) / batch; i++)
preprocessing.get_edabitvec(true, n_bits).output(n_bits,
out);
}
else
remove(filename.c_str());
}
}
output.Check(P);
}
template<class W>
const Names& OfflineMachine<W>::get_N()
{
return playerNames;
}
#endif /* PROCESSOR_OFFLINEMACHINE_HPP_ */