mirror of
https://github.com/data61/MP-SPDZ.git
synced 2026-01-08 05:03:59 -05:00
Protocol in dealer model.
This commit is contained in:
10
CHANGELOG.md
10
CHANGELOG.md
@@ -1,5 +1,15 @@
|
||||
The changelog explains changes pulled through from the private development repository. Bug fixes and small enhancements are committed between releases and not documented here.
|
||||
|
||||
## 0.3.1 (Apr 19, 2022)
|
||||
|
||||
- Protocol in dealer model
|
||||
- Command-line option for security parameter
|
||||
- Fixed security bug in SPDZ2k (see Section 3.4 of [the updated paper](https://eprint.iacr.org/2018/482))
|
||||
- Ability to run high-level (Python) code from C++
|
||||
- More memory capacity due to 64-bit addressing
|
||||
- Homomorphic encryption for more fields of characteristic two
|
||||
- Docker container
|
||||
|
||||
## 0.3.0 (Feb 17, 2022)
|
||||
|
||||
- Semi-honest computation based on threshold semi-homomorphic encryption
|
||||
|
||||
@@ -305,7 +305,7 @@ class ldmsb(base.DirectMemoryInstruction, base.ReadMemoryInstruction,
|
||||
:param: memory address (int)
|
||||
"""
|
||||
code = opcodes['LDMSB']
|
||||
arg_format = ['sbw','int']
|
||||
arg_format = ['sbw','long']
|
||||
|
||||
class stmsb(base.DirectMemoryWriteInstruction, base.VectorInstruction):
|
||||
""" Copy secret bit register to secret bit memory cell with compile-time
|
||||
@@ -315,7 +315,7 @@ class stmsb(base.DirectMemoryWriteInstruction, base.VectorInstruction):
|
||||
:param: memory address (int)
|
||||
"""
|
||||
code = opcodes['STMSB']
|
||||
arg_format = ['sb','int']
|
||||
arg_format = ['sb','long']
|
||||
# def __init__(self, *args, **kwargs):
|
||||
# super(type(self), self).__init__(*args, **kwargs)
|
||||
# import inspect
|
||||
@@ -330,7 +330,7 @@ class ldmcb(base.DirectMemoryInstruction, base.ReadMemoryInstruction,
|
||||
:param: memory address (int)
|
||||
"""
|
||||
code = opcodes['LDMCB']
|
||||
arg_format = ['cbw','int']
|
||||
arg_format = ['cbw','long']
|
||||
|
||||
class stmcb(base.DirectMemoryWriteInstruction, base.VectorInstruction):
|
||||
""" Copy clear bit register to clear bit memory cell with compile-time
|
||||
@@ -340,7 +340,7 @@ class stmcb(base.DirectMemoryWriteInstruction, base.VectorInstruction):
|
||||
:param: memory address (int)
|
||||
"""
|
||||
code = opcodes['STMCB']
|
||||
arg_format = ['cb','int']
|
||||
arg_format = ['cb','long']
|
||||
|
||||
class ldmsbi(base.ReadMemoryInstruction, base.VectorInstruction):
|
||||
""" Copy secret bit memory cell with run-time address to secret bit
|
||||
|
||||
@@ -3,6 +3,9 @@ This modules contains basic types for binary circuits. The
|
||||
fixed-length types obtained by :py:obj:`get_type(n)` are the preferred
|
||||
way of using them, and in some cases required in connection with
|
||||
container types.
|
||||
|
||||
Computation using these types will always be executed as a binary
|
||||
circuit. See :ref:`protocol-pairs` for the exact protocols.
|
||||
"""
|
||||
|
||||
from Compiler.types import MemValue, read_mem_value, regint, Array, cint
|
||||
@@ -17,7 +20,6 @@ import math
|
||||
from functools import reduce
|
||||
|
||||
class bits(Tape.Register, _structure, _bit):
|
||||
""" Base class for binary registers. """
|
||||
n = 40
|
||||
unit = 64
|
||||
PreOp = staticmethod(floatingpoint.PreOpN)
|
||||
@@ -400,12 +402,18 @@ class sbits(bits):
|
||||
res = sbit()
|
||||
inst.bitb(res)
|
||||
return res
|
||||
@staticmethod
|
||||
def _check_input_player(player):
|
||||
if not util.is_constant(player):
|
||||
raise CompilerError('player must be known at compile time '
|
||||
'for binary circuit inputs')
|
||||
@classmethod
|
||||
def get_input_from(cls, player, n_bits=None):
|
||||
""" Secret input from :py:obj:`player`.
|
||||
|
||||
:param: player (int)
|
||||
"""
|
||||
cls._check_input_player(player)
|
||||
if n_bits is None:
|
||||
n_bits = cls.n
|
||||
res = cls()
|
||||
@@ -653,6 +661,7 @@ class sbitvec(_vec):
|
||||
|
||||
:param: player (int)
|
||||
"""
|
||||
sbits._check_input_player(player)
|
||||
res = cls.from_vec(sbit() for i in range(n))
|
||||
inst.inputbvec(n + 3, 0, player, *res.v)
|
||||
return res
|
||||
@@ -780,6 +789,8 @@ class sbitvec(_vec):
|
||||
size = other.size
|
||||
return (other.get_vector(base, min(64, size - base)) \
|
||||
for base in range(0, size, 64))
|
||||
if not isinstance(other, type(self)):
|
||||
return type(self)(other)
|
||||
return other
|
||||
def __xor__(self, other):
|
||||
other = self.coerce(other)
|
||||
@@ -1222,6 +1233,7 @@ class sbitfix(_fix):
|
||||
|
||||
:param: player (int)
|
||||
"""
|
||||
sbits._check_input_player(player)
|
||||
v = cls.int_type()
|
||||
inst.inputb(player, cls.k, cls.f, v)
|
||||
return cls._new(v)
|
||||
@@ -1287,6 +1299,7 @@ class sbitfixvec(_fix):
|
||||
:param: player (int)
|
||||
"""
|
||||
v = [sbit() for i in range(sbitfix.k)]
|
||||
sbits._check_input_player(player)
|
||||
inst.inputbvec(len(v) + 3, sbitfix.f, player, *v)
|
||||
return cls._new(cls.int_type.from_vec(v))
|
||||
def __init__(self, value=None, *args, **kwargs):
|
||||
|
||||
@@ -15,11 +15,11 @@ from functools import reduce
|
||||
class BlockAllocator:
|
||||
""" Manages freed memory blocks. """
|
||||
def __init__(self):
|
||||
self.by_logsize = [defaultdict(set) for i in range(32)]
|
||||
self.by_logsize = [defaultdict(set) for i in range(64)]
|
||||
self.by_address = {}
|
||||
|
||||
def by_size(self, size):
|
||||
if size >= 2 ** 32:
|
||||
if size >= 2 ** 64:
|
||||
raise CompilerError('size exceeds addressing capability')
|
||||
return self.by_logsize[int(math.log(size, 2))][size]
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ class ldmc(base.DirectMemoryInstruction, base.ReadMemoryInstruction):
|
||||
"""
|
||||
__slots__ = []
|
||||
code = base.opcodes['LDMC']
|
||||
arg_format = ['cw','int']
|
||||
arg_format = ['cw','long']
|
||||
|
||||
@base.gf2n
|
||||
@base.vectorize
|
||||
@@ -84,7 +84,7 @@ class ldms(base.DirectMemoryInstruction, base.ReadMemoryInstruction):
|
||||
"""
|
||||
__slots__ = []
|
||||
code = base.opcodes['LDMS']
|
||||
arg_format = ['sw','int']
|
||||
arg_format = ['sw','long']
|
||||
|
||||
@base.gf2n
|
||||
@base.vectorize
|
||||
@@ -99,7 +99,7 @@ class stmc(base.DirectMemoryWriteInstruction):
|
||||
"""
|
||||
__slots__ = []
|
||||
code = base.opcodes['STMC']
|
||||
arg_format = ['c','int']
|
||||
arg_format = ['c','long']
|
||||
|
||||
@base.gf2n
|
||||
@base.vectorize
|
||||
@@ -114,7 +114,7 @@ class stms(base.DirectMemoryWriteInstruction):
|
||||
"""
|
||||
__slots__ = []
|
||||
code = base.opcodes['STMS']
|
||||
arg_format = ['s','int']
|
||||
arg_format = ['s','long']
|
||||
|
||||
@base.vectorize
|
||||
class ldmint(base.DirectMemoryInstruction, base.ReadMemoryInstruction):
|
||||
@@ -128,7 +128,7 @@ class ldmint(base.DirectMemoryInstruction, base.ReadMemoryInstruction):
|
||||
"""
|
||||
__slots__ = []
|
||||
code = base.opcodes['LDMINT']
|
||||
arg_format = ['ciw','int']
|
||||
arg_format = ['ciw','long']
|
||||
|
||||
@base.vectorize
|
||||
class stmint(base.DirectMemoryWriteInstruction):
|
||||
@@ -142,7 +142,7 @@ class stmint(base.DirectMemoryWriteInstruction):
|
||||
"""
|
||||
__slots__ = []
|
||||
code = base.opcodes['STMINT']
|
||||
arg_format = ['ci','int']
|
||||
arg_format = ['ci','long']
|
||||
|
||||
@base.vectorize
|
||||
class ldmci(base.ReadMemoryInstruction, base.IndirectMemoryInstruction):
|
||||
|
||||
@@ -337,7 +337,7 @@ def gf2n(instruction):
|
||||
if isinstance(arg_format, list):
|
||||
__format = []
|
||||
for __f in arg_format:
|
||||
if __f in ('int', 'p', 'ci', 'str'):
|
||||
if __f in ('int', 'long', 'p', 'ci', 'str'):
|
||||
__format.append(__f)
|
||||
else:
|
||||
__format.append(__f[0] + 'g' + __f[1:])
|
||||
@@ -360,7 +360,7 @@ def gf2n(instruction):
|
||||
arg_format = instruction_cls.gf2n_arg_format
|
||||
elif isinstance(instruction_cls.arg_format, itertools.repeat):
|
||||
__f = next(instruction_cls.arg_format)
|
||||
if __f != 'int' and __f != 'p':
|
||||
if __f not in ('int', 'long', 'p'):
|
||||
arg_format = itertools.repeat(__f[0] + 'g' + __f[1:])
|
||||
else:
|
||||
arg_format = copy.deepcopy(instruction_cls.arg_format)
|
||||
@@ -711,6 +711,14 @@ class IntArgFormat(ArgFormat):
|
||||
def __str__(self):
|
||||
return str(self.i)
|
||||
|
||||
class LongArgFormat(IntArgFormat):
|
||||
@classmethod
|
||||
def encode(cls, arg):
|
||||
return struct.pack('>Q', arg)
|
||||
|
||||
def __init__(self, f):
|
||||
self.i = struct.unpack('>Q', f.read(8))[0]
|
||||
|
||||
class ImmediateModpAF(IntArgFormat):
|
||||
@classmethod
|
||||
def check(cls, arg):
|
||||
@@ -768,6 +776,7 @@ ArgFormats = {
|
||||
'i': ImmediateModpAF,
|
||||
'ig': ImmediateGF2NAF,
|
||||
'int': IntArgFormat,
|
||||
'long': LongArgFormat,
|
||||
'p': PlayerNoAF,
|
||||
'str': String,
|
||||
}
|
||||
|
||||
@@ -1149,6 +1149,7 @@ def multithread(n_threads, n_items=None, max_size=None):
|
||||
|
||||
:param n_threads: compile-time (int)
|
||||
:param n_items: regint/cint/int (default: :py:obj:`n_threads`)
|
||||
:param max_size: maximum size to be processed at once (default: no limit)
|
||||
|
||||
The following executes ``f(0, 8)``, ``f(8, 8)``, and
|
||||
``f(16, 9)`` in three different threads:
|
||||
@@ -1366,6 +1367,18 @@ def tree_reduce_multithread(n_threads, function, vector):
|
||||
left = (left + 1) // 2
|
||||
return inputs[0]
|
||||
|
||||
def tree_reduce(function, sequence):
|
||||
""" Round-efficient reduction. The following computes the maximum
|
||||
of the list :py:obj:`l`::
|
||||
|
||||
m = tree_reduce(lambda x, y: x.max(y), l)
|
||||
|
||||
:param function: reduction function taking two arguments
|
||||
:param sequence: list, vector, or array
|
||||
|
||||
"""
|
||||
return util.tree_reduce(function, sequence)
|
||||
|
||||
def foreach_enumerate(a):
|
||||
""" Run-time loop over public data. This uses
|
||||
``Player-Data/Public-Input/<progname>``. Example:
|
||||
|
||||
@@ -1079,14 +1079,17 @@ class MaxPool(NoVariableLayer):
|
||||
(type(self).__name__, self.X.sizes, self.strides,
|
||||
self.ksize, self.padding)
|
||||
|
||||
def _forward(self, batch):
|
||||
def forward(self, batch=None, training=False):
|
||||
if batch is None:
|
||||
batch = Array.create_from(regint(0))
|
||||
def process(pool, bi, k, i, j):
|
||||
def m(a, b):
|
||||
c = a[0] > b[0]
|
||||
l = [c * x for x in a[1]]
|
||||
l += [(1 - c) * x for x in b[1]]
|
||||
return c.if_else(a[0], b[0]), l
|
||||
red = util.tree_reduce(m, [(x[0], [1]) for x in pool])
|
||||
red = util.tree_reduce(m, [(x[0], [1] if training else [])
|
||||
for x in pool])
|
||||
self.Y[bi][i][j][k] = red[0]
|
||||
for i, x in enumerate(red[1]):
|
||||
self.comparisons[bi][k][i] = x
|
||||
|
||||
@@ -400,6 +400,9 @@ class Program(object):
|
||||
self.allocated_mem[mem_type] += size
|
||||
if len(str(addr)) != len(str(addr + size)) and self.verbose:
|
||||
print("Memory of type '%s' now of size %d" % (mem_type, addr + size))
|
||||
if addr + size >= 2 ** 32:
|
||||
raise CompilerError("allocation exceeded for type '%s'" %
|
||||
mem_type)
|
||||
self.allocated_mem_blocks[addr,mem_type] = size
|
||||
if single_size:
|
||||
from .library import get_thread_number, runtime_error_if
|
||||
|
||||
@@ -1710,7 +1710,12 @@ class personal(Tape._no_truth):
|
||||
res = Array.create_from(res)
|
||||
return personal(player, res)
|
||||
|
||||
def bit_decompose(self, length):
|
||||
def bit_decompose(self, length=None):
|
||||
""" Bit decomposition.
|
||||
|
||||
:param length: number of bits
|
||||
|
||||
"""
|
||||
return [personal(self.player, x) for x in self._v.bit_decompose(length)]
|
||||
|
||||
def _san(self, other):
|
||||
@@ -2144,7 +2149,7 @@ class sint(_secret, _int):
|
||||
the bit length.
|
||||
|
||||
:param val: initialization (sint/cint/regint/int/cgf2n or list
|
||||
thereof or sbits/sbitvec/sfix)
|
||||
thereof, sbits/sbitvec/sfix, or :py:class:`personal`)
|
||||
:param size: vector size (int), defaults to 1 or size of list
|
||||
|
||||
When converting :py:class:`~Compiler.GC.types.sbits`, the result is a
|
||||
@@ -2152,6 +2157,9 @@ class sint(_secret, _int):
|
||||
:py:class:`~Compiler.GC.types.sbitvec`, the result is a vector of values
|
||||
with bit length equal the length of the input.
|
||||
|
||||
Initializing from a :py:class:`personal` value implies the
|
||||
relevant party inputting their value securely.
|
||||
|
||||
"""
|
||||
__slots__ = []
|
||||
instruction_type = 'modp'
|
||||
@@ -4285,6 +4293,7 @@ class sfix(_fix):
|
||||
""" Secret fixed-point number represented as secret integer, by
|
||||
multiplying with ``2^f`` and then rounding. See :py:class:`sint`
|
||||
for security considerations of the underlying integer operations.
|
||||
The secret integer is stored as the :py:obj:`v` member.
|
||||
|
||||
It supports basic arithmetic (``+, -, *, /``), returning
|
||||
:py:class:`sfix`, and comparisons (``==, !=, <, <=, >, >=``),
|
||||
@@ -5121,7 +5130,8 @@ class Array(_vectorizable):
|
||||
array ``a`` and ``i`` being a :py:class:`regint`,
|
||||
:py:class:`cint`, or a Python integer.
|
||||
|
||||
:param length: compile-time integer (int) or :py:obj:`None` for unknown length
|
||||
:param length: compile-time integer (int) or :py:obj:`None`
|
||||
for unknown length (need to specify :py:obj:`address`)
|
||||
:param value_type: basic type
|
||||
:param address: if given (regint/int), the array will not be allocated
|
||||
|
||||
@@ -5178,6 +5188,8 @@ class Array(_vectorizable):
|
||||
self.address = None
|
||||
|
||||
def get_address(self, index):
|
||||
if isinstance(index, (_secret, _single)):
|
||||
raise CompilerError('need cleartext index')
|
||||
key = str(index)
|
||||
if self.length is not None:
|
||||
from .GC.types import cbits
|
||||
@@ -5211,6 +5223,7 @@ class Array(_vectorizable):
|
||||
if index.step == 0:
|
||||
raise CompilerError('slice step cannot be zero')
|
||||
return index.start or 0, \
|
||||
index.stop if self.length is None else \
|
||||
min(index.stop or self.length, self.length), index.step or 1
|
||||
|
||||
def __getitem__(self, index):
|
||||
@@ -5517,7 +5530,15 @@ class Array(_vectorizable):
|
||||
|
||||
:param end: string to print after (default: line break)
|
||||
"""
|
||||
library.print_str('%s' + end, self.get_vector().reveal())
|
||||
if util.is_constant(self.length):
|
||||
library.print_str('%s' + end, self.get_vector().reveal())
|
||||
else:
|
||||
library.print_str('[')
|
||||
@library.for_range(self.length - 1)
|
||||
def _(i):
|
||||
library.print_str('%s, ', self[i].reveal())
|
||||
library.print_str('%s', self[self.length - 1].reveal())
|
||||
library.print_str(']' + end)
|
||||
|
||||
def reveal_to_binary_output(self, player=None):
|
||||
""" Reveal to binary output if supported by type.
|
||||
@@ -5893,7 +5914,8 @@ class SubMultiArray(_vectorizable):
|
||||
""" Matrix-matrix and matrix-vector multiplication.
|
||||
|
||||
:param self: two-dimensional
|
||||
:param other: Matrix or Array of matching size and type """
|
||||
:param other: Matrix or Array of matching size and type
|
||||
:param n_threads: number of threads (default: all in same thread) """
|
||||
assert len(self.sizes) == 2
|
||||
if isinstance(other, Array):
|
||||
assert len(other) == self.sizes[1]
|
||||
@@ -5928,6 +5950,7 @@ class SubMultiArray(_vectorizable):
|
||||
res_matrix.assign_part_vector(
|
||||
self.get_part(base, size).direct_mul(other), base)
|
||||
except AttributeError:
|
||||
assert n_threads is None
|
||||
if max(res_matrix.sizes) > 1000:
|
||||
raise AttributeError()
|
||||
A = self.get_vector()
|
||||
@@ -5937,7 +5960,7 @@ class SubMultiArray(_vectorizable):
|
||||
res_params))
|
||||
except (AttributeError, AssertionError):
|
||||
# fallback for sfloat etc.
|
||||
@library.for_range_opt(self.sizes[0])
|
||||
@library.for_range_opt_multithread(n_threads, self.sizes[0])
|
||||
def _(i):
|
||||
try:
|
||||
res_matrix[i] = self.value_type.row_matrix_mul(
|
||||
|
||||
@@ -28,6 +28,7 @@ public:
|
||||
static const true_type invertible;
|
||||
|
||||
static int size() { return 0; }
|
||||
static int length() { return 256; }
|
||||
static string type_string() { return "P256"; }
|
||||
|
||||
static void init();
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "Protocols/SemiPrep.hpp"
|
||||
#include "Protocols/SemiInput.hpp"
|
||||
#include "Protocols/MAC_Check_Base.hpp"
|
||||
#include "GC/SemiSecret.hpp"
|
||||
#include "ot-ecdsa-party.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
@@ -49,8 +49,8 @@ public:
|
||||
* @param n number of values
|
||||
* @returns vector of integer-like values
|
||||
*/
|
||||
template<class T>
|
||||
vector<T> receive_outputs(int n);
|
||||
template<class T, class U = T>
|
||||
vector<U> receive_outputs(int n);
|
||||
};
|
||||
|
||||
#endif /* EXTERNALIO_CLIENT_H_ */
|
||||
|
||||
@@ -91,8 +91,8 @@ void Client::send_private_inputs(const vector<T>& values)
|
||||
|
||||
// Receive shares of the result and sum together.
|
||||
// Also receive authenticating values.
|
||||
template<class T>
|
||||
vector<T> Client::receive_outputs(int n)
|
||||
template<class T, class U>
|
||||
vector<U> Client::receive_outputs(int n)
|
||||
{
|
||||
vector<T> triples(3 * n);
|
||||
octetStream os;
|
||||
@@ -111,7 +111,7 @@ vector<T> Client::receive_outputs(int n)
|
||||
}
|
||||
}
|
||||
|
||||
vector<T> output_values;
|
||||
vector<U> output_values;
|
||||
for (int i = 0; i < 3 * n; i += 3)
|
||||
{
|
||||
if (T(triples[i] * triples[i + 1]) != triples[i + 2])
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
template<class T>
|
||||
template<class T, class U>
|
||||
void one_run(T salary_value, Client& client)
|
||||
{
|
||||
// Run the computation
|
||||
@@ -54,18 +54,18 @@ void one_run(T salary_value, Client& client)
|
||||
cout << "Sent private inputs to each SPDZ engine, waiting for result..." << endl;
|
||||
|
||||
// Get the result back (client_id of winning client)
|
||||
T result = client.receive_outputs<T>(1)[0];
|
||||
U result = client.receive_outputs<T>(1)[0];
|
||||
|
||||
cout << "Winning client id is : " << result << endl;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
template<class T, class U>
|
||||
void run(double salary_value, Client& client)
|
||||
{
|
||||
// sint
|
||||
one_run<T>(long(round(salary_value)), client);
|
||||
one_run<T, U>(long(round(salary_value)), client);
|
||||
// sfix with f = 16
|
||||
one_run<T>(long(round(salary_value * exp2(16))), client);
|
||||
one_run<T, U>(long(round(salary_value * exp2(16))), client);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
@@ -125,7 +125,7 @@ int main(int argc, char** argv)
|
||||
{
|
||||
gfp::init_field(specification.get<bigint>());
|
||||
cerr << "using prime " << gfp::pr() << endl;
|
||||
run<gfp>(salary_value, client);
|
||||
run<gfp, gfp>(salary_value, client);
|
||||
break;
|
||||
}
|
||||
case 'R':
|
||||
@@ -134,13 +134,13 @@ int main(int argc, char** argv)
|
||||
switch (R)
|
||||
{
|
||||
case 64:
|
||||
run<Z2<64>>(salary_value, client);
|
||||
run<Z2<64>, Z2<64>>(salary_value, client);
|
||||
break;
|
||||
case 104:
|
||||
run<Z2<104>>(salary_value, client);
|
||||
run<Z2<104>, Z2<64>>(salary_value, client);
|
||||
break;
|
||||
case 128:
|
||||
run<Z2<128>>(salary_value, client);
|
||||
run<Z2<128>, Z2<64>>(salary_value, client);
|
||||
break;
|
||||
default:
|
||||
cerr << R << "-bit ring not implemented";
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
#include "FHE_Params.h"
|
||||
#include "FHE/Ring_Element.h"
|
||||
#include "Tools/Exceptions.h"
|
||||
#include "Protocols/HemiOptions.h"
|
||||
#include "Processor/OnlineOptions.h"
|
||||
|
||||
FHE_Params::FHE_Params(int n_mults) :
|
||||
FFTData(n_mults + 1), Chi(0.7), sec_p(-1), matrix_dim(1)
|
||||
FHE_Params::FHE_Params(int n_mults, int drown_sec) :
|
||||
FFTData(n_mults + 1), Chi(0.7), sec_p(drown_sec), matrix_dim(1)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -17,16 +19,20 @@ void FHE_Params::set(const Ring& R,
|
||||
for (size_t i = 0; i < FFTData.size(); i++)
|
||||
FFTData[i].init(R,primes[i]);
|
||||
|
||||
set_sec(40);
|
||||
set_sec(sec_p);
|
||||
}
|
||||
|
||||
void FHE_Params::set_sec(int sec)
|
||||
{
|
||||
assert(sec >= 0);
|
||||
sec_p=sec;
|
||||
Bval=1; Bval=Bval<<sec_p;
|
||||
Bval=FFTData[0].get_prime()/(2*(1+Bval));
|
||||
if (Bval == 0)
|
||||
throw runtime_error("distributed decryption bound is zero");
|
||||
}
|
||||
|
||||
void FHE_Params::set_min_sec(int sec)
|
||||
{
|
||||
set_sec(max(sec, sec_p));
|
||||
}
|
||||
|
||||
void FHE_Params::set_matrix_dim(int matrix_dim)
|
||||
@@ -37,6 +43,13 @@ void FHE_Params::set_matrix_dim(int matrix_dim)
|
||||
this->matrix_dim = matrix_dim;
|
||||
}
|
||||
|
||||
void FHE_Params::set_matrix_dim_from_options()
|
||||
{
|
||||
set_matrix_dim(
|
||||
HemiOptions::singleton.plain_matmul ?
|
||||
1 : OnlineOptions::singleton.batch_size);
|
||||
}
|
||||
|
||||
bigint FHE_Params::Q() const
|
||||
{
|
||||
bigint res = FFTData[0].get_prime();
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "FHE/FFT_Data.h"
|
||||
#include "FHE/DiscreteGauss.h"
|
||||
#include "Tools/random.h"
|
||||
#include "Protocols/config.h"
|
||||
|
||||
class FHE_Params
|
||||
{
|
||||
@@ -30,15 +31,17 @@ class FHE_Params
|
||||
|
||||
public:
|
||||
|
||||
FHE_Params(int n_mults = 1);
|
||||
FHE_Params(int n_mults = 1, int drown_sec = DEFAULT_SECURITY);
|
||||
|
||||
int n_mults() const { return FFTData.size() - 1; }
|
||||
|
||||
void set(const Ring& R,const vector<bigint>& primes);
|
||||
void set(const vector<bigint>& primes);
|
||||
void set_sec(int sec);
|
||||
void set_min_sec(int sec);
|
||||
|
||||
void set_matrix_dim(int matrix_dim);
|
||||
void set_matrix_dim_from_options();
|
||||
int get_matrix_dim() const { return matrix_dim; }
|
||||
|
||||
const vector<FFT_Data>& FFTD() const { return FFTData; }
|
||||
|
||||
@@ -68,6 +68,10 @@ void HNF(matrix& H,matrix& U,const matrix& A)
|
||||
{
|
||||
int m=A.size(),n=A[0].size(),r,i,j,k;
|
||||
|
||||
#ifdef VERBOSE
|
||||
cerr << "HNF m=" << m << ", n=" << n << endl;
|
||||
#endif
|
||||
|
||||
H=A;
|
||||
ident(U,n);
|
||||
r=min(m,n);
|
||||
@@ -79,9 +83,9 @@ void HNF(matrix& H,matrix& U,const matrix& A)
|
||||
{ if (step==2)
|
||||
{ // Step 2
|
||||
k=-1;
|
||||
mn=bigint(1)<<256;
|
||||
mn=bigint(0);
|
||||
for (j=i; j<n; j++)
|
||||
{ if (H[i][j]!=0 && abs(H[i][j])<mn)
|
||||
{ if (H[i][j]!=0 && (abs(H[i][j])<mn || mn == 0))
|
||||
{ k=j; mn=abs(H[i][j]); }
|
||||
}
|
||||
if (k!=-1)
|
||||
@@ -207,6 +211,11 @@ void SNF_Step(matrix& S,matrix& V)
|
||||
void SNF(matrix& S,const matrix& A,matrix& V)
|
||||
{
|
||||
int m=A.size(),n=A[0].size();
|
||||
|
||||
#ifdef VERBOSE
|
||||
cerr << "SNF m=" << m << ", n=" << n << endl;
|
||||
#endif
|
||||
|
||||
S=A;
|
||||
ident(V,n);
|
||||
|
||||
|
||||
@@ -100,11 +100,12 @@ int generate_semi_setup(int plaintext_length, int sec,
|
||||
numBits(NonInteractiveProof::slack(sec, phi_N(m))), true, params);
|
||||
int lgp0 = numBits(nb.min_p0(false, 0));
|
||||
int extra_slack = common_semi_setup(params, m, 2, lgp0, -1, round_up);
|
||||
assert(nb.min_phi_m(lgp0, false) * 2 <= m);
|
||||
load_or_generate(P2D, params.get_ring());
|
||||
return extra_slack;
|
||||
}
|
||||
|
||||
int common_semi_setup(FHE_Params& params, int m, bigint p, int lgp0, int lgp1, bool round_up)
|
||||
int common_semi_setup(FHE_Params& params, int m, bigint p, int& lgp0, int lgp1, bool round_up)
|
||||
{
|
||||
cout << "Need ciphertext modulus of length " << lgp0;
|
||||
if (params.n_mults() > 0)
|
||||
@@ -428,6 +429,16 @@ GF2X Subs_PowX_Mod(const GF2X& a,int pow,int m,const GF2X& c)
|
||||
|
||||
|
||||
|
||||
GF2X get_F(const Ring& Rg)
|
||||
{
|
||||
GF2X F;
|
||||
for (int i=0; i<=Rg.phi_m(); i++)
|
||||
{ if (((Rg.Phi()[i])%2)!=0)
|
||||
{ SetCoeff(F,i,1); }
|
||||
}
|
||||
//cout << "F = " << F << endl;
|
||||
return F;
|
||||
}
|
||||
|
||||
void init(P2Data& P2D,const Ring& Rg)
|
||||
{
|
||||
@@ -438,16 +449,12 @@ void init(P2Data& P2D,const Ring& Rg)
|
||||
{ SetCoeff(G,gf2n_short::get_t(i),1); }
|
||||
//cout << "G = " << G << endl;
|
||||
|
||||
for (int i=0; i<=Rg.phi_m(); i++)
|
||||
{ if (((Rg.Phi()[i])%2)!=0)
|
||||
{ SetCoeff(F,i,1); }
|
||||
}
|
||||
//cout << "F = " << F << endl;
|
||||
F = get_F(Rg);
|
||||
|
||||
// seed randomness to achieve same result for all players
|
||||
// randomness is used in SFCanZass and FindRoot
|
||||
SetSeed(ZZ(0));
|
||||
|
||||
|
||||
// Now factor F modulo 2
|
||||
vec_GF2X facts=SFCanZass(F);
|
||||
|
||||
@@ -459,17 +466,34 @@ void init(P2Data& P2D,const Ring& Rg)
|
||||
// Compute the quotient group
|
||||
QGroup QGrp;
|
||||
int Gord=-1,e=Rg.phi_m()/d; // e = # of plaintext slots, phi(m)/degree
|
||||
int seed=1;
|
||||
while (Gord!=e)
|
||||
|
||||
if ((e*gf2n_short::degree())!=Rg.phi_m())
|
||||
{ cout << "Plaintext type requires Gord*gf2n_short::degree == phi_m" << endl;
|
||||
cout << e << " * " << gf2n_short::degree() << " != " << Rg.phi_m() << endl;
|
||||
throw invalid_params();
|
||||
}
|
||||
|
||||
int max_tries = 10;
|
||||
for (int seed = 0;; seed++)
|
||||
{ QGrp.assign(Rg.m(),seed); // QGrp encodes the the quotient group Z_m^*/<2>
|
||||
Gord=QGrp.order();
|
||||
if (Gord!=e) { cout << "Group order wrong, need to repeat the Haf-Mc algorithm" << endl; seed++; }
|
||||
Gord = QGrp.order();
|
||||
if (Gord == e)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (seed == max_tries)
|
||||
{
|
||||
cerr << "abort after " << max_tries << " tries" << endl;
|
||||
throw invalid_params();
|
||||
}
|
||||
else
|
||||
cout << "Group order wrong, need to repeat the Haf-Mc algorithm"
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
//cout << " l = " << Gord << " , d = " << d << endl;
|
||||
if ((Gord*gf2n_short::degree())!=Rg.phi_m())
|
||||
{ cout << "Plaintext type requires Gord*gf2n_short::degree == phi_m" << endl;
|
||||
throw not_implemented();
|
||||
}
|
||||
|
||||
vector<GF2X> Fi(Gord);
|
||||
vector<GF2X> Rts(Gord);
|
||||
@@ -590,8 +614,23 @@ void char_2_dimension(int& m, int& lg2)
|
||||
m=5797;
|
||||
lg2=40;
|
||||
break;
|
||||
case 64:
|
||||
m = 9615;
|
||||
break;
|
||||
case 63:
|
||||
m = 9271;
|
||||
break;
|
||||
case 28:
|
||||
m = 3277;
|
||||
break;
|
||||
case 16:
|
||||
m = 13107;
|
||||
m = 4369;
|
||||
break;
|
||||
case 12:
|
||||
m = 4095;
|
||||
break;
|
||||
case 11:
|
||||
m = 2047;
|
||||
break;
|
||||
default:
|
||||
throw runtime_error("field size not supported");
|
||||
@@ -628,7 +667,7 @@ void Parameters::SPDZ_Data_Setup(FHE_Params& params, P2Data& P2D)
|
||||
finalize_lengths(lg2p0, lg2p1, n, m, lg2pi[0], round_up, params);
|
||||
}
|
||||
|
||||
if (NoiseBounds::min_phi_m(lg2p0 + lg2p1, params) > phi_N(m))
|
||||
if (NoiseBounds::min_phi_m(lg2p0 + lg2p1, params) * 2 > m)
|
||||
throw runtime_error("number of slots too small");
|
||||
|
||||
cout << "m = " << m << endl;
|
||||
|
||||
@@ -55,12 +55,19 @@ int generate_semi_setup(int plaintext_length, int sec,
|
||||
FHE_Params& params, FD& FieldD, bool round_up, int n = 1);
|
||||
|
||||
// field-independent semi-homomorphic setup
|
||||
int common_semi_setup(FHE_Params& params, int m, bigint p, int lgp0, int lgp1,
|
||||
int common_semi_setup(FHE_Params& params, int m, bigint p, int& lgp0, int lgp1,
|
||||
bool round_up);
|
||||
|
||||
void init(Ring& Rg, int m, bool generate_poly);
|
||||
void init(P2Data& P2D,const Ring& Rg);
|
||||
|
||||
namespace NTL
|
||||
{
|
||||
class GF2X;
|
||||
}
|
||||
|
||||
NTL::GF2X get_F(const Ring& Rg);
|
||||
|
||||
// For use when we want p to be a specific value
|
||||
void SPDZ_Data_Setup_Char_p_General(Ring& R, PPData& PPD, bigint& pr0,
|
||||
bigint& pr1, int n, int sec, bigint& p, FHE_Params& params);
|
||||
|
||||
@@ -36,11 +36,12 @@ SemiHomomorphicNoiseBounds::SemiHomomorphicNoiseBounds(const bigint& p,
|
||||
* (20.5 + c1 * sigma * sqrt(phi_m) + 20 * c1 * V_s);
|
||||
// unify parameters by taking maximum over TopGear or not
|
||||
bigint B_clean_top_gear = B_clean * 2;
|
||||
bigint B_clean_not_top_gear = B_clean << int(ceil(sec / 2.));
|
||||
bigint B_clean_not_top_gear = B_clean << max(slack - sec, 0);
|
||||
B_clean = max(B_clean_not_top_gear, B_clean_top_gear);
|
||||
B_scale = (c1 + c2 * V_s) * p * sqrt(phi_m / 12.0);
|
||||
int matrix_dim = params.get_matrix_dim();
|
||||
#ifdef NOISY
|
||||
cout << "phi(m): " << phi_m << endl;
|
||||
cout << "p * sqrt(phi(m) / 12): " << p * sqrt(phi_m / 12.0) << endl;
|
||||
cout << "V_s: " << V_s << endl;
|
||||
cout << "c1: " << c1 << endl;
|
||||
@@ -50,10 +51,13 @@ SemiHomomorphicNoiseBounds::SemiHomomorphicNoiseBounds(const bigint& p,
|
||||
cout << "B_clean: " << B_clean << endl;
|
||||
cout << "B_scale: " << B_scale << endl;
|
||||
cout << "matrix dimension: " << matrix_dim << endl;
|
||||
cout << "drown sec: " << params.secp() << endl;
|
||||
cout << "sec: " << sec << endl;
|
||||
#endif
|
||||
|
||||
assert(matrix_dim > 0);
|
||||
drown = 1 + matrix_dim * n * (bigint(1) << sec);
|
||||
assert(params.secp() >= 0);
|
||||
drown = 1 + (p > 2 ? matrix_dim : 1) * n * (bigint(1) << params.secp());
|
||||
}
|
||||
|
||||
bigint SemiHomomorphicNoiseBounds::min_p0(const bigint& p1)
|
||||
@@ -71,8 +75,14 @@ double SemiHomomorphicNoiseBounds::min_phi_m(int log_q, double sigma)
|
||||
{
|
||||
if (sigma <= 0)
|
||||
sigma = FHE_Params().get_R();
|
||||
// the constant was updated using Martin Albrecht's LWE estimator in Sep 2019
|
||||
return 37.8 * (log_q - log2(sigma));
|
||||
// the constant was updated using Martin Albrecht's LWE estimator in Mar 2022
|
||||
// found the following pairs for 128-bit security
|
||||
// and alpha = 0.7 * sqrt(2*pi) / q
|
||||
// m = 2048, log_2(q) = 68
|
||||
// m = 4096, log_2(q) = 138
|
||||
// m = 8192, log_2(q) = 302
|
||||
// m = 16384, log_2(q) = 560
|
||||
return 15.1 * log_q;
|
||||
}
|
||||
|
||||
double SemiHomomorphicNoiseBounds::min_phi_m(int log_q, const FHE_Params& params)
|
||||
|
||||
@@ -11,35 +11,15 @@ void Subs(modp& ans,const vector<int>& poly,const modp& x,const Zp_Data& ZpD)
|
||||
assignZero(ans,ZpD);
|
||||
for (int i=poly.size()-1; i>=0; i--)
|
||||
{ Mul(ans,ans,x,ZpD);
|
||||
switch (poly[i])
|
||||
{ case 0:
|
||||
break;
|
||||
case 1:
|
||||
Add(ans,ans,one,ZpD);
|
||||
break;
|
||||
case -1:
|
||||
Sub(ans,ans,one,ZpD);
|
||||
break;
|
||||
case 2:
|
||||
Add(ans,ans,one,ZpD);
|
||||
Add(ans,ans,one,ZpD);
|
||||
break;
|
||||
case -2:
|
||||
Sub(ans,ans,one,ZpD);
|
||||
Sub(ans,ans,one,ZpD);
|
||||
break;
|
||||
case 3:
|
||||
Add(ans,ans,one,ZpD);
|
||||
Add(ans,ans,one,ZpD);
|
||||
Add(ans,ans,one,ZpD);
|
||||
break;
|
||||
case -3:
|
||||
Sub(ans,ans,one,ZpD);
|
||||
Sub(ans,ans,one,ZpD);
|
||||
Sub(ans,ans,one,ZpD);
|
||||
break;
|
||||
default:
|
||||
throw not_implemented();
|
||||
if (poly[i] > 0)
|
||||
{
|
||||
for (int j = 0; j < poly[i]; j++)
|
||||
Add(ans, ans, one, ZpD);
|
||||
}
|
||||
if (poly[i] < 0)
|
||||
{
|
||||
for (int j = 0; j < -poly[i]; j++)
|
||||
Sub(ans, ans, one, ZpD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,10 +40,9 @@ template <class FD>
|
||||
void PartSetup<FD>::generate_setup(int n_parties, int plaintext_length, int sec,
|
||||
int slack, bool round_up)
|
||||
{
|
||||
sec = max(sec, 40);
|
||||
params.set_min_sec(sec);
|
||||
Parameters(n_parties, plaintext_length, sec, slack, round_up).generate_setup(
|
||||
params, FieldD);
|
||||
params.set_sec(sec);
|
||||
pk = FHE_PK(params, FieldD.get_prime());
|
||||
sk = FHE_SK(params, FieldD.get_prime());
|
||||
calpha = Ciphertext(params);
|
||||
@@ -180,11 +179,8 @@ void PartSetup<P2Data>::init_field()
|
||||
}
|
||||
|
||||
template <class FD>
|
||||
void PartSetup<FD>::check(int sec) const
|
||||
void PartSetup<FD>::check() const
|
||||
{
|
||||
sec = max(sec, 40);
|
||||
if (abs(sec - params.secp()) > 2)
|
||||
throw runtime_error("security parameters vary too much between protocol and distributed decryption");
|
||||
sk.check(params, pk, FieldD.get_prime());
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ public:
|
||||
|
||||
void init_field();
|
||||
|
||||
void check(int sec) const;
|
||||
void check() const;
|
||||
bool operator!=(const PartSetup<FD>& other);
|
||||
|
||||
void secure_init(Player& P, MachineBase& machine, int plaintext_length,
|
||||
|
||||
@@ -69,7 +69,7 @@ void Multiplier<FD>::add(Plaintext_<FD>& res, const Ciphertext& c,
|
||||
product_share.randomize(G);
|
||||
bigint B = 6 * machine.setup<FD>().params.get_R();
|
||||
B *= machine.setup<FD>().FieldD.get_prime();
|
||||
B <<= machine.drown_sec;
|
||||
B <<= machine.setup<FD>().params.secp();
|
||||
// slack
|
||||
B *= NonInteractiveProof::slack(machine.sec,
|
||||
machine.setup<FD>().params.phi_m());
|
||||
|
||||
@@ -29,7 +29,7 @@ void PairwiseMachine::init()
|
||||
{
|
||||
if (use_gf2n)
|
||||
{
|
||||
field_size = 40;
|
||||
field_size = gf2n_short::DEFAULT_LENGTH;
|
||||
gf2n_short::init_field(field_size);
|
||||
setup_keys<P2Data>();
|
||||
}
|
||||
@@ -67,7 +67,7 @@ void PairwiseMachine::setup_keys()
|
||||
{
|
||||
auto& N = P;
|
||||
PairwiseSetup<FD>& s = setup<FD>();
|
||||
s.init(P, drown_sec, field_size, extra_slack);
|
||||
s.init(P, sec, field_size, extra_slack);
|
||||
if (output)
|
||||
write_mac_key(get_prep_dir<FD>(P), P.my_num(), P.num_players(), s.alphai);
|
||||
for (auto& x : other_pks)
|
||||
|
||||
@@ -65,11 +65,12 @@ template <class T, class U>
|
||||
void secure_init(T& setup, Player& P, U& machine,
|
||||
int plaintext_length, int sec, FHE_Params& params)
|
||||
{
|
||||
assert(sec >= 0);
|
||||
machine.sec = sec;
|
||||
sec = max(sec, 40);
|
||||
machine.drown_sec = sec;
|
||||
params.set_min_sec(sec);
|
||||
string filename = PREP_DIR + T::name() + "-"
|
||||
+ to_string(plaintext_length) + "-" + to_string(sec) + "-"
|
||||
+ to_string(params.secp()) + "-"
|
||||
+ to_string(params.get_matrix_dim()) + "-"
|
||||
+ OnlineOptions::singleton.prime.get_str() + "-"
|
||||
+ to_string(CowGearOptions::singleton.top_gear()) + "-P"
|
||||
|
||||
@@ -78,6 +78,7 @@ class Proof
|
||||
diagonal(diagonal),
|
||||
B_plain_length(0), B_rand_length(0), pk(&pk), n_proofs(n_proofs)
|
||||
{ sec=sc;
|
||||
assert(sec > 0);
|
||||
tau=Tau; rho=Rho;
|
||||
|
||||
phim=(pk.get_params()).phi_m();
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
#include "Tools/Subroutines.h"
|
||||
|
||||
#include "Protocols/mac_key.hpp"
|
||||
|
||||
// The number of sacrifices to amortize at one time
|
||||
#define amortize 512
|
||||
|
||||
@@ -19,12 +21,7 @@ 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)
|
||||
{
|
||||
if (T::length() < 40)
|
||||
{
|
||||
cerr << "Field too small for reasonable security" << endl;
|
||||
cerr << "Use a larger field or remove this warning from " << __FILE__ << endl;
|
||||
exit(1);
|
||||
}
|
||||
check_field_size<T>();
|
||||
|
||||
ofstream outf;
|
||||
if (write_output)
|
||||
|
||||
@@ -27,7 +27,7 @@ void* run_generator(void* generator)
|
||||
MachineBase::MachineBase() :
|
||||
throughput_loop_thread(0),portnum_base(0),
|
||||
data_type(DATA_TRIPLE),
|
||||
sec(0), drown_sec(0), field_size(0), extra_slack(0),
|
||||
sec(0), field_size(0), extra_slack(0),
|
||||
produce_inputs(false),
|
||||
use_gf2n(false)
|
||||
{
|
||||
@@ -91,7 +91,6 @@ void MachineBase::parse_options(int argc, const char** argv)
|
||||
opt.get("-h")->getString(hostname);
|
||||
opt.get("-pn")->getInt(portnum_base);
|
||||
opt.get("-s")->getInt(sec);
|
||||
drown_sec = max(40, sec);
|
||||
opt.get("-f")->getInt(field_size);
|
||||
use_gf2n = opt.isSet("-2");
|
||||
if (use_gf2n)
|
||||
@@ -221,7 +220,7 @@ void MultiplicativeMachine::fake_keys(int slack)
|
||||
PartSetup<FD>& part_setup = setup.part<FD>();
|
||||
if (P.my_num() == 0)
|
||||
{
|
||||
part_setup.generate_setup(N.num_players(), field_size, drown_sec, slack, true);
|
||||
part_setup.generate_setup(N.num_players(), field_size, sec, slack, true);
|
||||
vector<PartSetup<FD> > setups;
|
||||
part_setup.fake(setups, P.num_players(), false);
|
||||
for (int i = 1; i < P.num_players(); i++)
|
||||
@@ -238,7 +237,7 @@ void MultiplicativeMachine::fake_keys(int slack)
|
||||
P.receive_player(0, os);
|
||||
}
|
||||
part_setup.unpack(os);
|
||||
part_setup.check(drown_sec);
|
||||
part_setup.check();
|
||||
|
||||
part_setup.alphai = read_or_generate_mac_key<Share<typename FD::T>>(P);
|
||||
Plaintext_<FD> m(part_setup.FieldD);
|
||||
|
||||
@@ -26,7 +26,6 @@ protected:
|
||||
|
||||
public:
|
||||
int sec;
|
||||
int drown_sec;
|
||||
int field_size;
|
||||
int extra_slack;
|
||||
bool produce_inputs;
|
||||
|
||||
@@ -15,9 +15,7 @@ TemiSetup<FD>::TemiSetup()
|
||||
this->pk = {this->params, 0};
|
||||
this->sk = {this->params, 0};
|
||||
this->calpha = this->params;
|
||||
this->params.set_matrix_dim(
|
||||
HemiOptions::singleton.plain_matmul ?
|
||||
1 : OnlineOptions::singleton.batch_size);
|
||||
this->params.set_matrix_dim_from_options();
|
||||
}
|
||||
|
||||
template<class FD>
|
||||
|
||||
@@ -40,7 +40,7 @@ public:
|
||||
return "CCD";
|
||||
}
|
||||
|
||||
static MAC_Check* new_mc(T)
|
||||
static MAC_Check* new_mc(typename super::mac_key_type)
|
||||
{
|
||||
return new MAC_Check;
|
||||
}
|
||||
|
||||
69
GC/DealerPrep.h
Normal file
69
GC/DealerPrep.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* DealerPrep.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GC_DEALERPREP_H_
|
||||
#define GC_DEALERPREP_H_
|
||||
|
||||
#include "Protocols/DealerPrep.h"
|
||||
#include "Protocols/ProtocolSet.h"
|
||||
#include "ShiftableTripleBuffer.h"
|
||||
#include "SemiSecret.h"
|
||||
|
||||
namespace GC
|
||||
{
|
||||
class DealerPrep : public BufferPrep<DealerSecret>, ShiftableTripleBuffer<DealerSecret>
|
||||
{
|
||||
Player* P;
|
||||
|
||||
public:
|
||||
DealerPrep(DataPositions& usage, int = -1) :
|
||||
BufferPrep<DealerSecret>(usage), P(0)
|
||||
{
|
||||
}
|
||||
|
||||
void set_protocol(DealerSecret::Protocol& protocol)
|
||||
{
|
||||
P = &protocol.P;
|
||||
}
|
||||
|
||||
void buffer_triples()
|
||||
{
|
||||
ProtocolSetup<DealerShare<BitVec>> setup(*P);
|
||||
ProtocolSet<DealerShare<BitVec>> set(*P, setup);
|
||||
for (int i = 0; i < OnlineOptions::singleton.batch_size; i++)
|
||||
{
|
||||
auto triple = set.preprocessing.get_triple(
|
||||
DealerSecret::default_length);
|
||||
this->triples.push_back({{triple[0], triple[1], triple[2]}});
|
||||
}
|
||||
}
|
||||
|
||||
void buffer_bits()
|
||||
{
|
||||
SeededPRNG G;
|
||||
if (P->my_num() != 0)
|
||||
for (int i = 0; i < OnlineOptions::singleton.batch_size; i++)
|
||||
this->bits.push_back(G.get_bit());
|
||||
else
|
||||
this->bits.resize(
|
||||
this->bits.size() + OnlineOptions::singleton.batch_size);
|
||||
}
|
||||
|
||||
void get(Dtype type, DealerSecret* data)
|
||||
{
|
||||
BufferPrep<DealerSecret>::get(type, data);
|
||||
}
|
||||
|
||||
array<DealerSecret, 3> get_triple_no_count(int n_bits)
|
||||
{
|
||||
if (n_bits == -1)
|
||||
n_bits = DealerSecret::default_length;
|
||||
return ShiftableTripleBuffer<DealerSecret>::get_triple_no_count(n_bits);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* GC_DEALERPREP_H_ */
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "GC/Memory.h"
|
||||
#include "GC/Access.h"
|
||||
#include "GC/ArgTuples.h"
|
||||
#include "GC/NoShare.h"
|
||||
|
||||
#include "Math/gf2nlong.h"
|
||||
#include "Tools/SwitchableOutput.h"
|
||||
@@ -40,7 +41,6 @@ public:
|
||||
typedef FakeSecret DynamicType;
|
||||
typedef Memory<FakeSecret> DynamicMemory;
|
||||
|
||||
typedef BitVec mac_key_type;
|
||||
typedef BitVec clear;
|
||||
typedef BitVec open_type;
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
return "Malicious CCD";
|
||||
}
|
||||
|
||||
static MAC_Check* new_mc(T)
|
||||
static MAC_Check* new_mc(typename super::mac_key_type)
|
||||
{
|
||||
return new MAC_Check;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ public:
|
||||
typedef MaliciousRepMC<This> MC;
|
||||
typedef BitVec_<unsigned char> open_type;
|
||||
typedef open_type clear;
|
||||
typedef BitVec mac_key_type;
|
||||
typedef NoValue mac_key_type;
|
||||
|
||||
static MC* new_mc(mac_key_type)
|
||||
{
|
||||
@@ -71,7 +71,7 @@ public:
|
||||
|
||||
static const bool expensive_triples = true;
|
||||
|
||||
static MC* new_mc(BitVec)
|
||||
static MC* new_mc(typename super::mac_key_type)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
16
GC/NoShare.h
16
GC/NoShare.h
@@ -60,35 +60,43 @@ public:
|
||||
throw not_implemented();
|
||||
}
|
||||
|
||||
static void init_minimum(int)
|
||||
{
|
||||
}
|
||||
|
||||
static void fail()
|
||||
{
|
||||
throw runtime_error("VM does not support binary circuits");
|
||||
}
|
||||
|
||||
NoValue() {}
|
||||
NoValue(int) { fail(); }
|
||||
NoValue(bool) {}
|
||||
NoValue(ValueInterface) {}
|
||||
NoValue(int128) {}
|
||||
|
||||
void assign(const char*) { fail(); }
|
||||
|
||||
const char* get_ptr() const { return (char*) this; }
|
||||
|
||||
int get() const { fail(); return 0; }
|
||||
|
||||
int operator<<(int) const { fail(); return 0; }
|
||||
void operator+=(int) { fail(); }
|
||||
|
||||
bool operator!=(NoValue) const { fail(); return 0; }
|
||||
bool operator!=(NoValue) const { return false; }
|
||||
|
||||
bool operator==(int) { fail(); return false; }
|
||||
|
||||
bool get_bit(int) { fail(); return 0; }
|
||||
|
||||
void randomize(PRNG&) { fail(); }
|
||||
void randomize(PRNG&) {}
|
||||
|
||||
void invert() { fail(); }
|
||||
|
||||
void mask(int) { fail(); }
|
||||
|
||||
void input(istream&, bool) { fail(); }
|
||||
void output(ostream&, bool) { fail(); }
|
||||
void output(ostream&, bool) {}
|
||||
};
|
||||
|
||||
inline ostream& operator<<(ostream& o, NoValue)
|
||||
|
||||
@@ -340,7 +340,7 @@ void Processor<T>::convcbit2s(const BaseInstruction& instruction)
|
||||
for (int i = 0; i < DIV_CEIL(instruction.get_n(), unit); i++)
|
||||
S[instruction.get_r(0) + i] = T::constant(C[instruction.get_r(1) + i],
|
||||
share_thread.P->my_num(), share_thread.MC->get_alphai(),
|
||||
min(unsigned(unit), instruction.get_n() - i * unit));
|
||||
min(size_t(unit), instruction.get_n() - i * unit));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
|
||||
106
GC/SemiSecret.h
106
GC/SemiSecret.h
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "Protocols/SemiMC.h"
|
||||
#include "Protocols/SemiShare.h"
|
||||
#include "Protocols/DealerShare.h"
|
||||
#include "Processor/DummyProtocol.h"
|
||||
#include "ShareSecret.h"
|
||||
|
||||
@@ -17,71 +18,116 @@ namespace GC
|
||||
{
|
||||
|
||||
class SemiPrep;
|
||||
class DealerPrep;
|
||||
|
||||
class SemiSecret : public SemiShare<BitVec>, public ShareSecret<SemiSecret>
|
||||
template<class T, class V>
|
||||
class SemiSecretBase : public V, public ShareSecret<T>
|
||||
{
|
||||
typedef V super;
|
||||
|
||||
public:
|
||||
typedef Memory<SemiSecret> DynamicMemory;
|
||||
typedef Memory<T> DynamicMemory;
|
||||
|
||||
typedef SemiMC<SemiSecret> MC;
|
||||
typedef DirectSemiMC<SemiSecret> Direct_MC;
|
||||
typedef Beaver<SemiSecret> Protocol;
|
||||
typedef MC MAC_Check;
|
||||
typedef SemiPrep LivePrep;
|
||||
typedef SemiInput<SemiSecret> Input;
|
||||
typedef Beaver<T> Protocol;
|
||||
|
||||
typedef SemiSecret part_type;
|
||||
typedef SemiSecret small_type;
|
||||
typedef T part_type;
|
||||
typedef T small_type;
|
||||
|
||||
static const int default_length = sizeof(BitVec) * 8;
|
||||
|
||||
static string type_string() { return "binary secret"; }
|
||||
static string phase_name() { return "Binary computation"; }
|
||||
|
||||
static MC* new_mc(mac_key_type);
|
||||
|
||||
template<class T>
|
||||
static void generate_mac_key(mac_key_type, T)
|
||||
{
|
||||
}
|
||||
|
||||
static void trans(Processor<SemiSecret>& processor, int n_outputs,
|
||||
static void trans(Processor<T>& processor, int n_outputs,
|
||||
const vector<int>& args);
|
||||
|
||||
SemiSecret()
|
||||
SemiSecretBase()
|
||||
{
|
||||
}
|
||||
SemiSecret(long other) :
|
||||
SemiShare<BitVec>(other)
|
||||
SemiSecretBase(long other) :
|
||||
V(other)
|
||||
{
|
||||
}
|
||||
SemiSecret(const IntBase& other) :
|
||||
SemiShare<BitVec>(other)
|
||||
template<class U>
|
||||
SemiSecretBase(const IntBase<U>& other) :
|
||||
V(other)
|
||||
{
|
||||
}
|
||||
template<int K>
|
||||
SemiSecret(const Z2<K>& other) :
|
||||
SemiShare<BitVec>(other)
|
||||
SemiSecretBase(const Z2<K>& other) :
|
||||
V(other)
|
||||
{
|
||||
}
|
||||
|
||||
void load_clear(int n, const Integer& x);
|
||||
|
||||
void bitcom(Memory<SemiSecret>& S, const vector<int>& regs);
|
||||
void bitdec(Memory<SemiSecret>& S, const vector<int>& regs) const;
|
||||
void bitcom(Memory<T>& S, const vector<int>& regs);
|
||||
void bitdec(Memory<T>& S, const vector<int>& regs) const;
|
||||
|
||||
void xor_(int n, const SemiSecret& x, const SemiSecret& y)
|
||||
void xor_(int n, const T& x, const T& y)
|
||||
{ *this = BitVec(x ^ y).mask(n); }
|
||||
|
||||
void xor_bit(int i, const SemiSecret& bit)
|
||||
void xor_bit(int i, const T& bit)
|
||||
{ *this ^= bit << i; }
|
||||
|
||||
void reveal(size_t n_bits, Clear& x);
|
||||
|
||||
SemiSecret lsb()
|
||||
T lsb()
|
||||
{ return *this & 1; }
|
||||
};
|
||||
|
||||
class SemiSecret: public SemiSecretBase<SemiSecret, SemiShare<BitVec>>
|
||||
{
|
||||
typedef SemiSecret This;
|
||||
|
||||
public:
|
||||
typedef SemiSecretBase<SemiSecret, SemiShare<BitVec>> super;
|
||||
|
||||
typedef SemiMC<This> MC;
|
||||
typedef DirectSemiMC<This> Direct_MC;
|
||||
typedef MC MAC_Check;
|
||||
typedef SemiInput<This> Input;
|
||||
typedef SemiPrep LivePrep;
|
||||
|
||||
static MC* new_mc(typename SemiShare<BitVec>::mac_key_type);
|
||||
|
||||
SemiSecret()
|
||||
{
|
||||
}
|
||||
|
||||
template<class T>
|
||||
SemiSecret(const T& other) :
|
||||
super(other)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class DealerSecret : public SemiSecretBase<DealerSecret, DealerShare<BitVec>>
|
||||
{
|
||||
typedef DealerSecret This;
|
||||
|
||||
public:
|
||||
typedef SemiSecretBase<DealerSecret, DealerShare<BitVec>> super;
|
||||
|
||||
typedef DealerMC<This> MC;
|
||||
typedef DirectDealerMC<This> Direct_MC;
|
||||
typedef MC MAC_Check;
|
||||
typedef DealerInput<This> Input;
|
||||
typedef DealerPrep LivePrep;
|
||||
|
||||
static MC* new_mc(typename super::mac_key_type);
|
||||
|
||||
DealerSecret()
|
||||
{
|
||||
}
|
||||
|
||||
template<class T>
|
||||
DealerSecret(const T& other) :
|
||||
super(other)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace GC */
|
||||
|
||||
#endif /* GC_SEMISECRET_H_ */
|
||||
|
||||
@@ -4,17 +4,20 @@
|
||||
*/
|
||||
|
||||
#include "GC/ShareParty.h"
|
||||
#include "SemiSecret.h"
|
||||
|
||||
#include "GC/ShareSecret.hpp"
|
||||
#include "Protocols/MAC_Check_Base.hpp"
|
||||
#include "Protocols/DealerMC.h"
|
||||
#include "SemiSecret.h"
|
||||
|
||||
namespace GC
|
||||
{
|
||||
|
||||
const int SemiSecret::default_length;
|
||||
template<class T, class V>
|
||||
const int SemiSecretBase<T, V>::default_length;
|
||||
|
||||
SemiSecret::MC* SemiSecret::new_mc(mac_key_type)
|
||||
inline
|
||||
SemiSecret::MC* SemiSecret::new_mc(
|
||||
typename super::mac_key_type)
|
||||
{
|
||||
if (OnlineOptions::singleton.direct)
|
||||
return new Direct_MC;
|
||||
@@ -22,7 +25,18 @@ SemiSecret::MC* SemiSecret::new_mc(mac_key_type)
|
||||
return new MC;
|
||||
}
|
||||
|
||||
void SemiSecret::trans(Processor<SemiSecret>& processor, int n_outputs,
|
||||
inline
|
||||
DealerSecret::MC* DealerSecret::new_mc(
|
||||
typename super::mac_key_type)
|
||||
{
|
||||
if (OnlineOptions::singleton.direct)
|
||||
return new Direct_MC;
|
||||
else
|
||||
return new MC;
|
||||
}
|
||||
|
||||
template<class T, class V>
|
||||
void SemiSecretBase<T, V>::trans(Processor<T>& processor, int n_outputs,
|
||||
const vector<int>& args)
|
||||
{
|
||||
int N_BITS = default_length;
|
||||
@@ -46,29 +60,33 @@ void SemiSecret::trans(Processor<SemiSecret>& processor, int n_outputs,
|
||||
}
|
||||
}
|
||||
|
||||
void SemiSecret::load_clear(int n, const Integer& x)
|
||||
template<class T, class V>
|
||||
void SemiSecretBase<T, V>::load_clear(int n, const Integer& x)
|
||||
{
|
||||
check_length(n, x);
|
||||
*this = constant(x, ShareThread<SemiSecret>::s().P->my_num());
|
||||
this->check_length(n, x);
|
||||
*this = this->constant(x, ShareThread<T>::s().P->my_num());
|
||||
}
|
||||
|
||||
void SemiSecret::bitcom(Memory<SemiSecret>& S, const vector<int>& regs)
|
||||
template<class T, class V>
|
||||
void SemiSecretBase<T, V>::bitcom(Memory<T>& S, const vector<int>& regs)
|
||||
{
|
||||
*this = 0;
|
||||
for (unsigned int i = 0; i < regs.size(); i++)
|
||||
*this ^= (S[regs[i]] << i);
|
||||
}
|
||||
|
||||
void SemiSecret::bitdec(Memory<SemiSecret>& S,
|
||||
template<class T, class V>
|
||||
void SemiSecretBase<T, V>::bitdec(Memory<T>& S,
|
||||
const vector<int>& regs) const
|
||||
{
|
||||
for (unsigned int i = 0; i < regs.size(); i++)
|
||||
S[regs[i]] = (*this >> i) & 1;
|
||||
}
|
||||
|
||||
void SemiSecret::reveal(size_t n_bits, Clear& x)
|
||||
template<class T, class V>
|
||||
void SemiSecretBase<T, V>::reveal(size_t n_bits, Clear& x)
|
||||
{
|
||||
auto& thread = ShareThread<SemiSecret>::s();
|
||||
auto& thread = ShareThread<T>::s();
|
||||
x = thread.MC->POpen(*this, *thread.P).mask(n_bits);
|
||||
}
|
||||
|
||||
@@ -112,8 +112,8 @@ public:
|
||||
|
||||
typedef BitVec clear;
|
||||
typedef BitVec open_type;
|
||||
typedef BitVec mac_type;
|
||||
typedef BitVec mac_key_type;
|
||||
typedef NoShare mac_type;
|
||||
typedef NoValue mac_key_type;
|
||||
|
||||
typedef NoShare bit_type;
|
||||
|
||||
@@ -213,7 +213,7 @@ public:
|
||||
typedef ReplicatedMC<This> MC;
|
||||
typedef BitVec_<unsigned char> open_type;
|
||||
typedef open_type clear;
|
||||
typedef BitVec mac_key_type;
|
||||
typedef NoValue mac_key_type;
|
||||
|
||||
static MC* new_mc(mac_key_type)
|
||||
{
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#include "instructions.h"
|
||||
|
||||
#include "Tools/benchmarking.h"
|
||||
|
||||
#include "Machine.hpp"
|
||||
|
||||
namespace GC
|
||||
@@ -58,15 +60,10 @@ Thread<T>* ThreadMaster<T>::new_thread(int i)
|
||||
template<class T>
|
||||
void ThreadMaster<T>::run()
|
||||
{
|
||||
#ifndef INSECURE
|
||||
if (not opts.live_prep)
|
||||
{
|
||||
cerr
|
||||
<< "Preprocessing from file not supported by binary virtual machines"
|
||||
<< endl;
|
||||
exit(1);
|
||||
insecure("preprocessing from file in binary virtual machines");
|
||||
}
|
||||
#endif
|
||||
|
||||
P = new PlainPlayer(N, "main");
|
||||
|
||||
|
||||
@@ -48,12 +48,12 @@ public:
|
||||
part_MC.exchange(P);
|
||||
}
|
||||
|
||||
typename T::open_type finalize_open()
|
||||
typename T::open_type finalize_raw()
|
||||
{
|
||||
int n = sizes.next();
|
||||
typename T::open_type opened = 0;
|
||||
for (int i = 0; i < n; i++)
|
||||
opened += typename T::open_type(part_MC.finalize_open().get_bit(0)) << i;
|
||||
opened += typename T::open_type(part_MC.finalize_raw().get_bit(0)) << i;
|
||||
return opened;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "Protocols/Spdz2kShare.h"
|
||||
#include "Protocols/Spdz2kPrep.h"
|
||||
#include "Protocols/SPDZ2k.h"
|
||||
|
||||
#include "GC/TinySecret.h"
|
||||
#include "GC/TinyMC.h"
|
||||
|
||||
@@ -19,3 +19,4 @@
|
||||
#include "Protocols/SemiMC.hpp"
|
||||
#include "Protocols/Beaver.hpp"
|
||||
#include "Protocols/MalRepRingPrep.hpp"
|
||||
#include "GC/SemiSecret.hpp"
|
||||
|
||||
@@ -97,6 +97,5 @@ ShamirMachineSpec<T>::ShamirMachineSpec(int argc, const char** argv)
|
||||
auto& opts = ShamirOptions::singleton;
|
||||
ez::ezOptionParser opt;
|
||||
opts = {opt, argc, argv};
|
||||
T<gfp>::bit_type::part_type::open_type::init_field();
|
||||
HonestMajorityFieldMachine<T>(argc, argv, opt, opts.nparties);
|
||||
}
|
||||
|
||||
@@ -142,8 +142,8 @@ TripleMachine::TripleMachine(int argc, const char** argv) :
|
||||
gfpvar1::init_field(prime, false);
|
||||
else
|
||||
gfpvar1::init_default(128, false);
|
||||
gf2n_long::init_field(128);
|
||||
gf2n_short::init_field(40);
|
||||
gf2n_long::init_field();
|
||||
gf2n_short::init_field();
|
||||
|
||||
PRNG G;
|
||||
G.ReSeed();
|
||||
|
||||
22
Machines/dealer-ring-party.cpp
Normal file
22
Machines/dealer-ring-party.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* dealer-ring-party.cpp
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Protocols/DealerShare.h"
|
||||
#include "Protocols/DealerInput.h"
|
||||
|
||||
#include "Processor/RingMachine.hpp"
|
||||
#include "Processor/Machine.hpp"
|
||||
#include "Protocols/Replicated.hpp"
|
||||
#include "Protocols/DealerPrep.hpp"
|
||||
#include "Protocols/DealerInput.hpp"
|
||||
#include "Protocols/DealerMC.hpp"
|
||||
#include "Protocols/Beaver.hpp"
|
||||
#include "Semi.hpp"
|
||||
#include "GC/DealerPrep.h"
|
||||
|
||||
int main(int argc, const char** argv)
|
||||
{
|
||||
HonestMajorityRingMachine<DealerRingShare, DealerShare>(argc, argv, 0);
|
||||
}
|
||||
@@ -54,9 +54,8 @@ int main(int argc, const char** argv)
|
||||
{
|
||||
#define X(L) \
|
||||
case L: \
|
||||
Machine<FakeShare<SignedZ2<L>>, FakeShare<gf2n>>(0, N, progname, \
|
||||
online_opts.memtype, gf2n::default_degree(), 0, 0, 0, 0, false, \
|
||||
online_opts.live_prep, online_opts).run(); \
|
||||
Machine<FakeShare<SignedZ2<L>>, FakeShare<gf2n>>(N, false, online_opts, \
|
||||
gf2n::default_degree()).run(progname); \
|
||||
break;
|
||||
X(64) X(128) X(256) X(192) X(384) X(512)
|
||||
#ifdef RING_SIZE
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "Protocols/MalRepRingPrep.hpp"
|
||||
#include "GC/ShareSecret.hpp"
|
||||
#include "GC/SemiHonestRepPrep.h"
|
||||
#include "GC/SemiSecret.hpp"
|
||||
#include "Math/gfp.hpp"
|
||||
|
||||
int main(int argc, const char** argv)
|
||||
|
||||
@@ -18,8 +18,9 @@
|
||||
|
||||
int main(int argc, const char** argv)
|
||||
{
|
||||
gf2n_short::init_field(40);
|
||||
ez::ezOptionParser opt;
|
||||
ShamirOptions::singleton = {opt, argc, argv};
|
||||
OnlineOptions opts(opt, argc, argv);
|
||||
gf2n_short::init_minimum(opts.security_parameter);
|
||||
GC::ShareParty<GC::MaliciousCcdSecret<gf2n_short>>(argc, argv, opt);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "GC/Thread.hpp"
|
||||
#include "GC/ThreadMaster.hpp"
|
||||
#include "GC/Processor.hpp"
|
||||
#include "GC/SemiSecret.hpp"
|
||||
#include "Protocols/MAC_Check_Base.hpp"
|
||||
#include "Protocols/SemiMC.hpp"
|
||||
#include "Protocols/SemiInput.hpp"
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "Protocols/MalRepRingPrep.hpp"
|
||||
#include "GC/ShareSecret.hpp"
|
||||
#include "GC/SemiHonestRepPrep.h"
|
||||
#include "GC/SemiSecret.hpp"
|
||||
#include "Math/gfp.hpp"
|
||||
|
||||
int main(int argc, const char** argv)
|
||||
|
||||
@@ -22,12 +22,12 @@ int main(int argc, const char** argv)
|
||||
1, // Number of args expected.
|
||||
0, // Delimiter if expecting multiple args.
|
||||
"SPDZ2k security parameter (default: 64)", // Help description.
|
||||
"-S", // Flag token.
|
||||
"--security" // Flag token.
|
||||
"-SP", // Flag token.
|
||||
"--spdz2k-security" // Flag token.
|
||||
);
|
||||
opt.parse(argc, argv);
|
||||
int s;
|
||||
opt.get("-S")->getInt(s);
|
||||
opt.get("-SP")->getInt(s);
|
||||
opt.resetArgs();
|
||||
RingOptions ring_options(opt, argc, argv);
|
||||
int k = ring_options.R;
|
||||
@@ -62,6 +62,8 @@ int main(int argc, const char** argv)
|
||||
cerr << "add Z(" << k << ", " << s << ") to " << __FILE__ << " at line "
|
||||
<< (__LINE__ - 11) << " and create Machines/SPDZ2^" << k << "+"
|
||||
<< s << ".cpp based on Machines/SPDZ2^72+64.cpp" << endl;
|
||||
cerr << "Alternatively, compile with -DRING_SIZE=" << k
|
||||
<< " and -DSPDZ2K_DEFAULT_SECURITY=" << s << endl;
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "Protocols/Hemi.hpp"
|
||||
#include "GC/ShareSecret.hpp"
|
||||
#include "GC/SemiHonestRepPrep.h"
|
||||
#include "GC/SemiSecret.hpp"
|
||||
#include "Math/gfp.hpp"
|
||||
|
||||
int main(int argc, const char** argv)
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
int main(int argc, const char** argv)
|
||||
{
|
||||
gf2n_short::init_field(40);
|
||||
ez::ezOptionParser opt;
|
||||
OnlineOptions opts(opt, argc, argv);
|
||||
gf2n_short::init_minimum(opts.security_parameter);
|
||||
GC::simple_binary_main<GC::TinierSecret<gf2n_short>>(argc, argv, 1000);
|
||||
}
|
||||
|
||||
@@ -29,5 +29,5 @@
|
||||
|
||||
int main(int argc, const char** argv)
|
||||
{
|
||||
GC::simple_binary_main<GC::TinySecret<40>>(argc, argv, 1000);
|
||||
GC::simple_binary_main<GC::TinySecret<DEFAULT_SECURITY>>(argc, argv, 1000);
|
||||
}
|
||||
|
||||
26
Makefile
26
Makefile
@@ -12,7 +12,7 @@ PROCESSOR = $(patsubst %.cpp,%.o,$(wildcard Processor/*.cpp))
|
||||
FHEOBJS = $(patsubst %.cpp,%.o,$(wildcard FHEOffline/*.cpp FHE/*.cpp)) Protocols/CowGearOptions.o
|
||||
|
||||
GC = $(patsubst %.cpp,%.o,$(wildcard GC/*.cpp)) $(PROCESSOR)
|
||||
GC_SEMI = GC/SemiSecret.o GC/SemiPrep.o GC/square64.o
|
||||
GC_SEMI = GC/SemiPrep.o GC/square64.o
|
||||
|
||||
OT = $(patsubst %.cpp,%.o,$(wildcard OT/*.cpp))
|
||||
OT_EXE = ot.x ot-offline.x
|
||||
@@ -57,7 +57,7 @@ vm: arithmetic binary
|
||||
doc:
|
||||
cd doc; $(MAKE) html
|
||||
|
||||
arithmetic: rep-ring rep-field shamir semi2k-party.x semi-party.x mascot sy
|
||||
arithmetic: rep-ring rep-field shamir semi2k-party.x semi-party.x mascot sy dealer-ring-party.x
|
||||
binary: rep-bin yao semi-bin-party.x tinier-party.x tiny-party.x ccd-party.x malicious-ccd-party.x real-bmr
|
||||
|
||||
all: overdrive she-offline
|
||||
@@ -162,7 +162,7 @@ bmr-%.x: $(BMR) $(VM) Machines/bmr-%.cpp $(LIBSIMPLEOT)
|
||||
bmr-clean:
|
||||
-rm BMR/*.o BMR/*/*.o GC/*.o
|
||||
|
||||
bankers-bonus-client.x: ExternalIO/bankers-bonus-client.cpp $(COMMON)
|
||||
bankers-bonus-client.x: ExternalIO/bankers-bonus-client.o $(COMMON)
|
||||
$(CXX) $(CFLAGS) -o $@ $^ $(LDLIBS)
|
||||
|
||||
simple-offline.x: $(FHEOFFLINE)
|
||||
@@ -203,13 +203,13 @@ replicated-field-party.x: GC/square64.o
|
||||
brain-party.x: GC/square64.o
|
||||
malicious-rep-bin-party.x: GC/square64.o
|
||||
ps-rep-bin-party.x: GC/PostSacriBin.o
|
||||
semi-bin-party.x: $(OT) GC/SemiSecret.o GC/SemiPrep.o GC/square64.o
|
||||
semi-bin-party.x: $(OT) GC/SemiPrep.o GC/square64.o
|
||||
tiny-party.x: $(OT)
|
||||
tinier-party.x: $(OT)
|
||||
spdz2k-party.x: $(TINIER) $(patsubst %.cpp,%.o,$(wildcard Machines/SPDZ2*.cpp))
|
||||
static/spdz2k-party.x: $(patsubst %.cpp,%.o,$(wildcard Machines/SPDZ2*.cpp))
|
||||
semi-party.x: $(OT) GC/SemiSecret.o GC/SemiPrep.o GC/square64.o
|
||||
semi2k-party.x: $(OT) GC/SemiSecret.o GC/SemiPrep.o GC/square64.o
|
||||
semi-party.x: $(OT) GC/SemiPrep.o GC/square64.o
|
||||
semi2k-party.x: $(OT) GC/SemiPrep.o GC/square64.o
|
||||
hemi-party.x: $(FHEOFFLINE) $(GC_SEMI) $(OT)
|
||||
temi-party.x: $(FHEOFFLINE) $(GC_SEMI) $(OT)
|
||||
soho-party.x: $(FHEOFFLINE) $(GC_SEMI) $(OT)
|
||||
@@ -234,15 +234,16 @@ malicious-rep-ring-party.x: Protocols/MalRepRingOptions.o
|
||||
sy-rep-ring-party.x: Protocols/MalRepRingOptions.o
|
||||
rep4-ring-party.x: GC/Rep4Secret.o
|
||||
no-party.x: Protocols/ShareInterface.o
|
||||
semi-ecdsa-party.x: $(OT) $(LIBSIMPLEOT) GC/SemiPrep.o GC/SemiSecret.o
|
||||
semi-ecdsa-party.x: $(OT) $(LIBSIMPLEOT) GC/SemiPrep.o
|
||||
mascot-ecdsa-party.x: $(OT) $(LIBSIMPLEOT)
|
||||
fake-spdz-ecdsa-party.x: $(OT) $(LIBSIMPLEOT)
|
||||
emulate.x: GC/FakeSecret.o
|
||||
semi-bmr-party.x: GC/SemiPrep.o GC/SemiSecret.o $(OT)
|
||||
semi-bmr-party.x: GC/SemiPrep.o $(OT)
|
||||
real-bmr-party.x: $(OT)
|
||||
paper-example.x: $(VM) $(OT) $(FHEOFFLINE)
|
||||
binary-example.x: $(VM) $(OT) GC/PostSacriBin.o GC/SemiPrep.o GC/SemiSecret.o GC/AtlasSecret.o
|
||||
mixed-example.x: $(VM) $(OT) GC/PostSacriBin.o GC/SemiPrep.o GC/SemiSecret.o GC/AtlasSecret.o Machines/Tinier.o
|
||||
binary-example.x: $(VM) $(OT) GC/PostSacriBin.o GC/SemiPrep.o GC/AtlasSecret.o
|
||||
mixed-example.x: $(VM) $(OT) GC/PostSacriBin.o GC/SemiPrep.o GC/AtlasSecret.o Machines/Tinier.o
|
||||
l2h-example.x: $(VM) $(OT) Machines/Tinier.o
|
||||
mascot-offline.x: $(VM) $(TINIER)
|
||||
cowgear-offline.x: $(TINIER) $(FHEOFFLINE)
|
||||
static/rep-bmr-party.x: $(BMR)
|
||||
@@ -253,6 +254,7 @@ static/semi-bmr-party.x: $(BMR)
|
||||
static/real-bmr-party.x: $(BMR)
|
||||
static/bmr-program-party.x: $(BMR)
|
||||
static/no-party.x: Protocols/ShareInterface.o
|
||||
Test/failure.x: Protocols/MalRepRingOptions.o
|
||||
|
||||
ifeq ($(AVX_OT), 1)
|
||||
$(LIBSIMPLEOT): SimpleOT/Makefile
|
||||
@@ -270,7 +272,7 @@ Programs/Circuits:
|
||||
|
||||
.PHONY: mpir-setup mpir-global mpir
|
||||
mpir-setup:
|
||||
git submodule update --init mpir
|
||||
git submodule update --init mpir || git clone https://github.com/wbhart/mpir
|
||||
cd mpir; \
|
||||
autoreconf -i; \
|
||||
autoreconf -i
|
||||
@@ -306,7 +308,7 @@ linux-machine-setup:
|
||||
endif
|
||||
|
||||
simde/simde:
|
||||
git submodule update --init simde
|
||||
git submodule update --init simde || git clone https://github.com/simd-everywhere/simde
|
||||
|
||||
clean:
|
||||
-rm -f */*.o *.o */*.d *.d *.x core.* *.a gmon.out */*/*.o static/*.x *.so
|
||||
|
||||
@@ -37,8 +37,6 @@ public:
|
||||
|
||||
static void specification(octetStream& os);
|
||||
|
||||
static void init_default(int lgp) { (void)lgp; }
|
||||
|
||||
static bool allows(Dtype type) { return type <= DATA_BIT; }
|
||||
|
||||
IntBase() { a = 0; }
|
||||
|
||||
@@ -27,6 +27,13 @@ void SPDZ_Data_Setup_Primes(bigint& p,int lgp,int& idx,int& m)
|
||||
cerr << "Setting up parameters" << endl;
|
||||
#endif
|
||||
|
||||
m = default_m(lgp, idx);
|
||||
generate_prime(p, lgp, m);
|
||||
}
|
||||
|
||||
int default_m(int& lgp, int& idx)
|
||||
{
|
||||
int m;
|
||||
switch (lgp)
|
||||
{ case -1:
|
||||
m=16;
|
||||
@@ -56,15 +63,12 @@ void SPDZ_Data_Setup_Primes(bigint& p,int lgp,int& idx,int& m)
|
||||
default:
|
||||
m=1;
|
||||
idx=0;
|
||||
#ifdef VERBOSE
|
||||
cerr << "no precomputed parameters, trying anyway" << endl;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
#ifdef VERBOSE
|
||||
cerr << "m = " << m << endl;
|
||||
#endif
|
||||
generate_prime(p, lgp, m);
|
||||
return m;
|
||||
}
|
||||
|
||||
bigint generate_prime(int lgp, int m)
|
||||
@@ -95,6 +99,9 @@ void generate_prime(bigint& p, int lgp, int m)
|
||||
return;
|
||||
}
|
||||
|
||||
int idx;
|
||||
m = max(m, default_m(lgp, idx));
|
||||
|
||||
bigint u;
|
||||
int ex;
|
||||
ex = lgp - numBits(m);
|
||||
|
||||
@@ -35,6 +35,7 @@ bigint SPDZ_Data_Setup_Primes(int lgp);
|
||||
void SPDZ_Data_Setup_Primes(bigint& p,int lgp,int& idx,int& m);
|
||||
void generate_prime(bigint& p, int lgp, int m);
|
||||
bigint generate_prime(int lgp, int m);
|
||||
int default_m(int& lgp, int& idx);
|
||||
|
||||
string get_prep_sub_dir(const string& prep_dir, int nparties, int log2mod,
|
||||
const string& type_short);
|
||||
|
||||
@@ -12,6 +12,7 @@ using namespace std;
|
||||
#include "Tools/random.h"
|
||||
#include "Tools/octetStream.h"
|
||||
#include "Tools/avx_memcpy.h"
|
||||
#include "Protocols/config.h"
|
||||
|
||||
enum ReportType
|
||||
{
|
||||
@@ -270,7 +271,8 @@ inline int probPrime(const bigint& x)
|
||||
{
|
||||
gmp_randstate_t rand_state;
|
||||
gmp_randinit_default(rand_state);
|
||||
int ans=mpz_probable_prime_p(x.get_mpz_t(),rand_state,40,0);
|
||||
int ans = mpz_probable_prime_p(x.get_mpz_t(), rand_state,
|
||||
max(40, DEFAULT_SECURITY), 0);
|
||||
gmp_randclear(rand_state);
|
||||
return ans;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ bool gf2n_<U>::useC;
|
||||
|
||||
word gf2n_short_table[256][256];
|
||||
|
||||
#define num_2_fields 7
|
||||
#define num_2_fields 17
|
||||
|
||||
/* Require
|
||||
* 2*(n-1)-64+t1<64
|
||||
@@ -26,11 +26,21 @@ word gf2n_short_table[256][256];
|
||||
int fields_2[num_2_fields][4] =
|
||||
{
|
||||
{ 4, 1, 0, 0 },
|
||||
{ 5, 2, 0, 0 },
|
||||
{ 6, 1, 0, 0 },
|
||||
{ 7, 1, 0, 0 },
|
||||
{ 8, 4, 3, 1 },
|
||||
{ 9, 1, 0, 0 },
|
||||
{ 10, 3, 0, 0},
|
||||
{ 11, 2, 0, 0},
|
||||
{ 12, 3, 0, 0},
|
||||
{ 14, 5, 0, 0},
|
||||
{ 15, 1, 0, 0},
|
||||
{ 16, 5, 3, 1 },
|
||||
{ 28, 1, 0, 0 },
|
||||
{ 40, 20, 15, 10 },
|
||||
{ 63, 1, 0, 0 },
|
||||
{ 64, 4, 3, 1},
|
||||
{ 128, 7, 2, 1 },
|
||||
};
|
||||
|
||||
@@ -55,6 +65,21 @@ void gf2n_<U>::init_tables()
|
||||
}
|
||||
}
|
||||
|
||||
template<class U>
|
||||
void gf2n_<U>::init_minimum(int lower)
|
||||
{
|
||||
if (lower <= n)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < num_2_fields; i++)
|
||||
{
|
||||
int n = fields_2[i][0];
|
||||
if (lower <= n and n <= MAX_N_BITS)
|
||||
return init_field(n);
|
||||
}
|
||||
throw runtime_error("no suitable field for minimum degree " + to_string(lower));
|
||||
}
|
||||
|
||||
void gf2n_short::init_field(int nn)
|
||||
{
|
||||
super::init_field(nn == 0 ? DEFAULT_LENGTH : nn);
|
||||
@@ -88,7 +113,7 @@ void gf2n_<U>::init_field(int nn)
|
||||
|
||||
if (j==-1)
|
||||
{
|
||||
throw runtime_error("field size not supported");
|
||||
throw gf2n_not_supported(nn);
|
||||
}
|
||||
|
||||
n=nn;
|
||||
@@ -332,7 +357,11 @@ gf2n_<U> gf2n_<U>::invert() const
|
||||
if (n < 64)
|
||||
return U(invert<word>(a));
|
||||
else
|
||||
return invert<bit_plus<U>>(a).get_lower();
|
||||
{
|
||||
gf2n_ res;
|
||||
res.a = invert<int128>(a).get_lower();
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
|
||||
@@ -65,6 +65,7 @@ protected:
|
||||
|
||||
static void init_field(int nn = 0);
|
||||
static void init_default(int, bool = false) { init_field(); }
|
||||
static void init_minimum(int lower);
|
||||
|
||||
static void reset() { n = 0; }
|
||||
static int degree() { return n; }
|
||||
@@ -213,7 +214,7 @@ public:
|
||||
static const int DEFAULT_LENGTH = 40;
|
||||
|
||||
static int length() { return n == 0 ? DEFAULT_LENGTH : n; }
|
||||
static int default_degree() { return 40; }
|
||||
static int default_degree() { return DEFAULT_LENGTH; }
|
||||
|
||||
static void init_field(int nn = 0);
|
||||
|
||||
|
||||
67
Networking/AllButLastPlayer.h
Normal file
67
Networking/AllButLastPlayer.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* AllButZeroPlayer.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NETWORKING_ALLBUTLASTPLAYER_H_
|
||||
#define NETWORKING_ALLBUTLASTPLAYER_H_
|
||||
|
||||
#include "Player.h"
|
||||
|
||||
class AllButLastPlayer : public Player
|
||||
{
|
||||
const Player& P;
|
||||
Names* N;
|
||||
|
||||
public:
|
||||
AllButLastPlayer(const Player& P) :
|
||||
Player(*(N = new Names(P.my_num(), P.num_players() - 1))), P(P)
|
||||
{
|
||||
}
|
||||
|
||||
~AllButLastPlayer()
|
||||
{
|
||||
delete N;
|
||||
}
|
||||
|
||||
void send_to_no_stats(int player, const octetStream& o) const
|
||||
{
|
||||
P.send_to(player, o);
|
||||
}
|
||||
|
||||
void receive_player_no_stats(int i, octetStream& o) const
|
||||
{
|
||||
P.receive_player(i, o);
|
||||
}
|
||||
|
||||
void send_receive_all_no_stats(const vector<vector<bool>>& channels,
|
||||
const vector<octetStream>& to_send,
|
||||
vector<octetStream>& to_receive) const
|
||||
{
|
||||
auto my_channels = channels;
|
||||
my_channels.resize(P.num_players());
|
||||
for (auto& x : my_channels)
|
||||
x.resize(P.num_players());
|
||||
auto my_to_send = to_send;
|
||||
if (P.my_num() != P.num_players() - 1)
|
||||
P.send_receive_all(my_channels, my_to_send, to_receive);
|
||||
to_receive.resize(P.num_players() - 1);
|
||||
}
|
||||
|
||||
void Broadcast_Receive_no_stats(vector<octetStream>& os) const
|
||||
{
|
||||
vector<octetStream> to_send(P.num_players(), os[P.my_num()]);
|
||||
vector<vector<bool>> channels(P.num_players(),
|
||||
vector<bool>(P.num_players(), true));
|
||||
for (auto& x: channels)
|
||||
x.back() = false;
|
||||
channels.back() = vector<bool>(P.num_players(), false);
|
||||
vector<octetStream> to_receive;
|
||||
P.send_receive_all(channels, to_send, to_receive);
|
||||
for (int i = 0; i < P.num_players() - 1; i++)
|
||||
if (i != P.my_num())
|
||||
os[i] = to_receive[i];
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -146,10 +146,18 @@ void Names::setup_names(const char *servername, int my_port)
|
||||
#endif
|
||||
|
||||
// Now get the set of names
|
||||
octetStream os;
|
||||
os.Receive(socket_num);
|
||||
os.get(names);
|
||||
os.get(ports);
|
||||
try
|
||||
{
|
||||
octetStream os;
|
||||
os.Receive(socket_num);
|
||||
os.get(names);
|
||||
os.get(ports);
|
||||
}
|
||||
catch (exception& e)
|
||||
{
|
||||
throw runtime_error(string("error in network setup: ") + e.what());
|
||||
}
|
||||
|
||||
if (names.size() != ports.size())
|
||||
throw runtime_error("invalid network setup");
|
||||
nplayers = names.size();
|
||||
@@ -186,6 +194,11 @@ Names::Names(const Names& other)
|
||||
server = 0;
|
||||
}
|
||||
|
||||
Names::Names(int my_num, int num_players) :
|
||||
nplayers(num_players), portnum_base(-1), player_no(my_num), server(0)
|
||||
{
|
||||
}
|
||||
|
||||
Names::~Names()
|
||||
{
|
||||
if (server != 0)
|
||||
@@ -817,6 +830,17 @@ void NamedCommStats::print(bool newline)
|
||||
cerr << endl;
|
||||
}
|
||||
|
||||
void NamedCommStats::reset()
|
||||
{
|
||||
clear();
|
||||
sent = 0;
|
||||
}
|
||||
|
||||
void PlayerBase::reset_stats()
|
||||
{
|
||||
comm_stats.reset();
|
||||
}
|
||||
|
||||
NamedCommStats Player::total_comm() const
|
||||
{
|
||||
auto res = comm_stats;
|
||||
|
||||
@@ -116,7 +116,7 @@ class Names
|
||||
Names(ez::ezOptionParser& opt, int argc, const char** argv,
|
||||
int default_nplayers = 2);
|
||||
|
||||
Names() : nplayers(1), portnum_base(-1), player_no(0), server(0) { ; }
|
||||
Names(int my_num = 0, int num_players = 1);
|
||||
Names(const Names& other);
|
||||
~Names();
|
||||
|
||||
@@ -159,6 +159,7 @@ public:
|
||||
NamedCommStats operator-(const NamedCommStats& other) const;
|
||||
size_t total_data();
|
||||
void print(bool newline = false);
|
||||
void reset();
|
||||
#ifdef VERBOSE_COMM
|
||||
CommStats& operator[](const string& name)
|
||||
{
|
||||
@@ -190,10 +191,19 @@ public:
|
||||
virtual int my_num() const = 0;
|
||||
virtual int num_players() const = 0;
|
||||
|
||||
virtual void pass_around(octetStream& o, int offset = 1) const = 0;
|
||||
virtual void Broadcast_Receive(vector<octetStream>& o) const = 0;
|
||||
virtual void receive_player(int, octetStream&) const
|
||||
{ throw not_implemented(); }
|
||||
virtual void pass_around(octetStream&, int = 1) const
|
||||
{ throw not_implemented(); }
|
||||
virtual void Broadcast_Receive(vector<octetStream>&) const
|
||||
{ throw not_implemented(); }
|
||||
virtual void unchecked_broadcast(vector<octetStream>& o) const
|
||||
{ Broadcast_Receive(o); }
|
||||
virtual void send_receive_all(const vector<octetStream>&,
|
||||
vector<octetStream>&) const
|
||||
{ throw not_implemented(); }
|
||||
|
||||
void reset_stats();
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -230,8 +240,8 @@ public:
|
||||
|
||||
virtual bool is_encrypted() { return false; }
|
||||
|
||||
virtual void send_long(int i, long a) const = 0;
|
||||
virtual long receive_long(int i) const = 0;
|
||||
virtual void send_long(int, long) const { throw not_implemented(); }
|
||||
virtual long receive_long(int) const { throw not_implemented(); }
|
||||
|
||||
// The following functions generally update the statistics
|
||||
// and then call the *_no_stats equivalent specified by a subclass.
|
||||
@@ -283,7 +293,8 @@ public:
|
||||
* reusing the buffer if possible.
|
||||
*/
|
||||
void exchange(int other, const octetStream& to_send, octetStream& ot_receive) const;
|
||||
virtual void exchange_no_stats(int other, const octetStream& to_send, octetStream& ot_receive) const = 0;
|
||||
virtual void exchange_no_stats(int, const octetStream&, octetStream&) const
|
||||
{ throw runtime_error("implement exchange"); }
|
||||
/**
|
||||
* Exchange information with one other party, reusing the buffer.
|
||||
*/
|
||||
@@ -304,8 +315,8 @@ public:
|
||||
* The default is to send to the next party while receiving from the previous.
|
||||
*/
|
||||
void pass_around(octetStream& to_send, octetStream& to_receive, int offset) const;
|
||||
virtual void pass_around_no_stats(const octetStream& to_send,
|
||||
octetStream& to_receive, int offset) const = 0;
|
||||
virtual void pass_around_no_stats(const octetStream&, octetStream&,
|
||||
int) const { throw runtime_error("implement passing around"); }
|
||||
|
||||
/**
|
||||
* Broadcast and receive data to/from all players.
|
||||
@@ -317,7 +328,8 @@ public:
|
||||
* Assumes o[player_no] contains the data to be broadcast by me.
|
||||
*/
|
||||
virtual void Broadcast_Receive(vector<octetStream>& o) const;
|
||||
virtual void Broadcast_Receive_no_stats(vector<octetStream>& o) const = 0;
|
||||
virtual void Broadcast_Receive_no_stats(vector<octetStream>&) const
|
||||
{ throw runtime_error("implement broadcast"); }
|
||||
|
||||
/**
|
||||
* Run protocol to verify broadcast is correct
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "Protocols/MAC_Check.hpp"
|
||||
#include "Protocols/SemiInput.hpp"
|
||||
#include "Protocols/SemiMC.hpp"
|
||||
#include "Protocols/mac_key.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
@@ -274,9 +275,9 @@ void NPartyTripleGenerator<W>::generateInputs(int player)
|
||||
inputs.resize(nTriplesPerLoop);
|
||||
|
||||
typename W::input_check_type::MAC_Check MC(mac_key);
|
||||
MC.POpen(check_sum, globalPlayer);
|
||||
// use zero element because all is perfectly randomized
|
||||
MC.set_random_element({});
|
||||
MC.POpen(check_sum, globalPlayer);
|
||||
MC.Check(globalPlayer);
|
||||
}
|
||||
|
||||
@@ -673,7 +674,7 @@ void MascotTripleGenerator<T>::sacrifice(typename T::MAC_Check& MC, PRNG& G)
|
||||
auto& outputFile = this->outputFile;
|
||||
auto& uncheckedTriples = this->uncheckedTriples;
|
||||
|
||||
assert(T::clear::length() >= 40);
|
||||
check_field_size<typename T::clear>();
|
||||
|
||||
vector<T> maskedAs(nTriplesPerLoop);
|
||||
vector<TripleToSacrifice<T> > maskedTriples(nTriplesPerLoop);
|
||||
@@ -744,6 +745,8 @@ void Spdz2kTripleGenerator<W>::sacrificeZ2k(U& MC, PRNG& G)
|
||||
// and first part of [sigma], i.e., t * [c] - [chat]
|
||||
maskedTriples[j].template prepare_sacrifice<W>(uncheckedTriples[j], G);
|
||||
maskedAs[j] = maskedTriples[j].a[0];
|
||||
// enough randomness in values
|
||||
MC.set_random_element({});
|
||||
}
|
||||
|
||||
vector<T> openedAs(nTriplesPerLoop);
|
||||
@@ -754,6 +757,8 @@ void Spdz2kTripleGenerator<W>::sacrificeZ2k(U& MC, PRNG& G)
|
||||
for (int j = 0; j < nTriplesPerLoop; j++) {
|
||||
// compute t * [c] - [chat] - [b] * p
|
||||
sigmas.push_back(maskedTriples[j].computeCheckShare(V(openedAs[j])));
|
||||
// enough randomness in values
|
||||
MC.set_random_element({});
|
||||
}
|
||||
vector<T> open_sigmas;
|
||||
|
||||
|
||||
@@ -59,6 +59,8 @@ void BaseMachine::load_schedule(const string& progname, bool load_bytecode)
|
||||
cerr << "Number of program sequences I need to load = " << nprogs << endl;
|
||||
#endif
|
||||
|
||||
bc_filenames.clear();
|
||||
|
||||
// Load in the programs
|
||||
string threadname;
|
||||
for (int i=0; i<nprogs; i++)
|
||||
|
||||
@@ -299,9 +299,7 @@ template<int>
|
||||
void Sub_Data_Files<T>::buffer_edabits_with_queues(bool strict, int n_bits,
|
||||
false_type)
|
||||
{
|
||||
#ifndef INSECURE
|
||||
throw runtime_error("no secure implementation of reading edaBits from files");
|
||||
#endif
|
||||
insecure("reading edaBits from files");
|
||||
if (edabit_buffers.find(n_bits) == edabit_buffers.end())
|
||||
{
|
||||
string filename = PrepBase::get_edabit_filename(prep_data_dir,
|
||||
|
||||
@@ -26,7 +26,7 @@ class InputBase
|
||||
typedef typename T::clear clear;
|
||||
|
||||
protected:
|
||||
Player* P;
|
||||
PlayerBase* P;
|
||||
int my_num;
|
||||
|
||||
Buffer<typename T::clear, typename T::clear> buffer;
|
||||
@@ -63,7 +63,7 @@ public:
|
||||
/// Initialize input round for ``player``
|
||||
virtual void reset(int player) = 0;
|
||||
/// Initialize input round for all players
|
||||
void reset_all(Player& P);
|
||||
void reset_all(PlayerBase& P);
|
||||
|
||||
/// Schedule input from me
|
||||
virtual void add_mine(const typename T::open_type& input, int n_bits = -1) = 0;
|
||||
|
||||
@@ -81,7 +81,7 @@ void InputBase<T>::reset(int player)
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void InputBase<T>::reset_all(Player& P)
|
||||
void InputBase<T>::reset_all(PlayerBase& P)
|
||||
{
|
||||
this->P = &P;
|
||||
my_num = P.my_num();
|
||||
|
||||
@@ -328,14 +328,14 @@ protected:
|
||||
int opcode; // The code
|
||||
int size; // Vector size
|
||||
int r[4]; // Fixed parameter registers
|
||||
unsigned int n; // Possible immediate value
|
||||
size_t n; // Possible immediate value
|
||||
vector<int> start; // Values for a start/stop open
|
||||
|
||||
public:
|
||||
virtual ~BaseInstruction() {};
|
||||
|
||||
int get_r(int i) const { return r[i]; }
|
||||
unsigned int get_n() const { return n; }
|
||||
size_t get_n() const { return n; }
|
||||
const vector<int>& get_start() const { return start; }
|
||||
int get_opcode() const { return opcode; }
|
||||
int get_size() const { return size; }
|
||||
@@ -350,7 +350,7 @@ public:
|
||||
bool is_direct_memory_access() const;
|
||||
|
||||
// Returns the memory size used if applicable and known
|
||||
unsigned get_mem(RegType reg_type) const;
|
||||
size_t get_mem(RegType reg_type) const;
|
||||
|
||||
// Returns the maximal register used
|
||||
unsigned get_max_reg(int reg_type) const;
|
||||
|
||||
@@ -218,24 +218,10 @@ void BaseInstruction::parse_operands(istream& s, int pos, int file_pos)
|
||||
// instructions with 1 register + 1 integer operand
|
||||
case LDI:
|
||||
case LDSI:
|
||||
case LDMC:
|
||||
case LDMS:
|
||||
case STMC:
|
||||
case STMS:
|
||||
case LDMSB:
|
||||
case STMSB:
|
||||
case LDMCB:
|
||||
case STMCB:
|
||||
case LDMINT:
|
||||
case STMINT:
|
||||
case JMPNZ:
|
||||
case JMPEQZ:
|
||||
case GLDI:
|
||||
case GLDSI:
|
||||
case GLDMC:
|
||||
case GLDMS:
|
||||
case GSTMC:
|
||||
case GSTMS:
|
||||
case PRINTREG:
|
||||
case PRINTREGB:
|
||||
case GPRINTREG:
|
||||
@@ -247,6 +233,24 @@ void BaseInstruction::parse_operands(istream& s, int pos, int file_pos)
|
||||
r[0]=get_int(s);
|
||||
n = get_int(s);
|
||||
break;
|
||||
// instructions with 1 register + 1 long operand
|
||||
case LDMC:
|
||||
case LDMS:
|
||||
case STMC:
|
||||
case STMS:
|
||||
case LDMSB:
|
||||
case STMSB:
|
||||
case LDMCB:
|
||||
case STMCB:
|
||||
case LDMINT:
|
||||
case STMINT:
|
||||
case GLDMC:
|
||||
case GLDMS:
|
||||
case GSTMC:
|
||||
case GSTMS:
|
||||
r[0] = get_int(s);
|
||||
n = get_long(s);
|
||||
break;
|
||||
// instructions with 1 integer operand
|
||||
case PRINTSTR:
|
||||
case PRINTCHR:
|
||||
@@ -783,7 +787,7 @@ unsigned BaseInstruction::get_max_reg(int reg_type) const
|
||||
}
|
||||
|
||||
inline
|
||||
unsigned BaseInstruction::get_mem(RegType reg_type) const
|
||||
size_t BaseInstruction::get_mem(RegType reg_type) const
|
||||
{
|
||||
if (get_reg_type() == reg_type and is_direct_memory_access())
|
||||
return n + size;
|
||||
@@ -843,7 +847,7 @@ inline void Instruction::execute(Processor<sint, sgf2n>& Proc) const
|
||||
}
|
||||
|
||||
int r[3] = {this->r[0], this->r[1], this->r[2]};
|
||||
int n = this->n;
|
||||
int64_t n = this->n;
|
||||
for (int i = 0; i < size; i++)
|
||||
{ switch (opcode)
|
||||
{
|
||||
@@ -1065,7 +1069,7 @@ inline void Instruction::execute(Processor<sint, sgf2n>& Proc) const
|
||||
case PRINTREG:
|
||||
{
|
||||
Proc.out << "Reg[" << r[0] << "] = " << Proc.read_Cp(r[0])
|
||||
<< " # " << string((char*)&n,sizeof(n)) << endl;
|
||||
<< " # " << string((char*)&n, 4) << endl;
|
||||
}
|
||||
break;
|
||||
case PRINTREGPLAIN:
|
||||
@@ -1085,7 +1089,7 @@ inline void Instruction::execute(Processor<sint, sgf2n>& Proc) const
|
||||
case CONDPRINTSTR:
|
||||
if (not Proc.read_Cp(r[0]).is_zero())
|
||||
{
|
||||
string str = {(char*)&n, sizeof(n)};
|
||||
string str = {(char*)&n, 4};
|
||||
size_t n = str.find('\0');
|
||||
if (n < 4)
|
||||
str.erase(n);
|
||||
@@ -1313,7 +1317,7 @@ void Instruction::print(SwitchableOutput& out, T* v, T* p, T* s, T* z, T* nan) c
|
||||
out << "[";
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
if (p == 0)
|
||||
if (p == 0 or (*p == 0 and s == 0))
|
||||
out << v[i];
|
||||
else if (s == 0)
|
||||
out << bigint::get_float(v[i], p[i], {}, {});
|
||||
|
||||
@@ -46,6 +46,8 @@ class Machine : public BaseMachine
|
||||
|
||||
void load_program(const string& threadname, const string& filename);
|
||||
|
||||
void prepare(const string& progname_str);
|
||||
|
||||
void suggest_optimizations();
|
||||
|
||||
public:
|
||||
@@ -71,10 +73,10 @@ class Machine : public BaseMachine
|
||||
|
||||
ExecutionStats stats;
|
||||
|
||||
Machine(int my_number, Names& playerNames, const string& progname,
|
||||
const string& memtype, int lg2, bool direct, int opening_sum,
|
||||
bool receive_threads, int max_broadcast, bool use_encryption, bool live_prep,
|
||||
OnlineOptions opts);
|
||||
static void init_binary_domains(int security_parameter, int lg2);
|
||||
|
||||
Machine(Names& playerNames, bool use_encryption = true,
|
||||
const OnlineOptions opts = sint(), int lg2 = 0);
|
||||
~Machine();
|
||||
|
||||
const Names& get_N() { return N; }
|
||||
@@ -92,7 +94,11 @@ class Machine : public BaseMachine
|
||||
DataPositions run_tape(int thread_number, int tape_number, int arg,
|
||||
const DataPositions& pos);
|
||||
DataPositions join_tape(int thread_number);
|
||||
void run();
|
||||
|
||||
void run(const string& progname);
|
||||
|
||||
void run_step(const string& progname);
|
||||
pair<DataPositions, NamedCommStats> stop_threads();
|
||||
|
||||
string memory_filename();
|
||||
|
||||
@@ -102,6 +108,9 @@ class Machine : public BaseMachine
|
||||
void reqbl(int n);
|
||||
|
||||
typename sint::bit_type::mac_key_type get_bit_mac_key() { return alphabi; }
|
||||
typename sint::mac_key_type get_sint_mac_key() { return alphapi; }
|
||||
|
||||
Player& get_player() { return *P; }
|
||||
};
|
||||
|
||||
#endif /* MACHINE_H_ */
|
||||
|
||||
@@ -24,28 +24,52 @@
|
||||
using namespace std;
|
||||
|
||||
template<class sint, class sgf2n>
|
||||
Machine<sint, sgf2n>::Machine(int my_number, Names& playerNames,
|
||||
const string& progname_str, const string& memtype,
|
||||
int lg2, bool direct,
|
||||
int opening_sum, bool receive_threads, int max_broadcast,
|
||||
bool use_encryption, bool live_prep, OnlineOptions opts)
|
||||
: my_number(my_number), N(playerNames),
|
||||
direct(direct), opening_sum(opening_sum),
|
||||
receive_threads(receive_threads), max_broadcast(max_broadcast),
|
||||
use_encryption(use_encryption), live_prep(live_prep), opts(opts)
|
||||
void Machine<sint, sgf2n>::init_binary_domains(int security_parameter, int lg2)
|
||||
{
|
||||
sgf2n::clear::init_field(lg2);
|
||||
|
||||
if (not is_same<typename sgf2n::mac_key_type, GC::NoValue>())
|
||||
{
|
||||
if (sgf2n::clear::degree() < security_parameter)
|
||||
{
|
||||
cerr << "Security parameter needs to be at most n in GF(2^n)."
|
||||
<< endl;
|
||||
cerr << "Increase the latter (-lg2) or decrease the former (-S)."
|
||||
<< endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (not is_same<typename sint::bit_type::mac_key_type, GC::NoValue>())
|
||||
{
|
||||
sint::bit_type::mac_key_type::init_minimum(security_parameter);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Initialize field for CCD
|
||||
sint::bit_type::part_type::open_type::init_field();
|
||||
}
|
||||
}
|
||||
|
||||
template<class sint, class sgf2n>
|
||||
Machine<sint, sgf2n>::Machine(Names& playerNames, bool use_encryption,
|
||||
const OnlineOptions opts, int lg2)
|
||||
: my_number(playerNames.my_num()), N(playerNames),
|
||||
direct(opts.direct), opening_sum(opts.opening_sum),
|
||||
receive_threads(opts.receive_threads), max_broadcast(opts.max_broadcast),
|
||||
use_encryption(use_encryption), live_prep(opts.live_prep), opts(opts)
|
||||
{
|
||||
OnlineOptions::singleton = opts;
|
||||
|
||||
if (opening_sum < 2)
|
||||
this->opening_sum = N.num_players();
|
||||
if (max_broadcast < 2)
|
||||
this->max_broadcast = N.num_players();
|
||||
|
||||
// Set up the fields
|
||||
sgf2n::clear::init_field(lg2);
|
||||
sint::clear::read_or_generate_setup(prep_dir_prefix<sint>(), opts);
|
||||
sint::bit_type::mac_key_type::init_field();
|
||||
|
||||
// Initialize gf2n_short for CCD
|
||||
sint::bit_type::part_type::open_type::init_field();
|
||||
init_binary_domains(opts.security_parameter, lg2);
|
||||
|
||||
// make directory for outputs if necessary
|
||||
mkdir_p(PREP_DIR);
|
||||
@@ -75,6 +99,7 @@ Machine<sint, sgf2n>::Machine(int my_number, Names& playerNames,
|
||||
sint::clear::next::template init<typename sint::clear>(false);
|
||||
|
||||
// Initialize the global memory
|
||||
auto memtype = opts.memtype;
|
||||
if (memtype.compare("old")==0)
|
||||
{
|
||||
ifstream inpf;
|
||||
@@ -92,9 +117,18 @@ Machine<sint, sgf2n>::Machine(int my_number, Names& playerNames,
|
||||
{ cerr << "Invalid memory argument" << endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
template<class sint, class sgf2n>
|
||||
void Machine<sint, sgf2n>::prepare(const string& progname_str)
|
||||
{
|
||||
int old_n_threads = nthreads;
|
||||
progs.clear();
|
||||
load_schedule(progname_str);
|
||||
|
||||
// keep preprocessing
|
||||
nthreads = max(old_n_threads, nthreads);
|
||||
|
||||
// initialize persistence if necessary
|
||||
for (auto& prog : progs)
|
||||
{
|
||||
@@ -122,7 +156,7 @@ Machine<sint, sgf2n>::Machine(int my_number, Names& playerNames,
|
||||
if (live_prep
|
||||
and (sint::needs_ot or sgf2n::needs_ot or sint::bit_type::needs_ot))
|
||||
{
|
||||
for (int i = 0; i < nthreads; i++)
|
||||
for (int i = old_n_threads; i < nthreads; i++)
|
||||
ot_setups.push_back({ *P, true });
|
||||
}
|
||||
|
||||
@@ -132,7 +166,7 @@ Machine<sint, sgf2n>::Machine(int my_number, Names& playerNames,
|
||||
queues.resize(nthreads);
|
||||
join_timer.resize(nthreads);
|
||||
|
||||
for (int i=0; i<nthreads; i++)
|
||||
for (int i = old_n_threads; i < nthreads; i++)
|
||||
{
|
||||
queues[i] = new ThreadQueue;
|
||||
// stand-in for initialization
|
||||
@@ -146,7 +180,7 @@ Machine<sint, sgf2n>::Machine(int my_number, Names& playerNames,
|
||||
}
|
||||
|
||||
// synchronize with clients before starting timer
|
||||
for (int i=0; i<nthreads; i++)
|
||||
for (int i=old_n_threads; i<nthreads; i++)
|
||||
{
|
||||
queues[i]->result();
|
||||
}
|
||||
@@ -155,6 +189,9 @@ Machine<sint, sgf2n>::Machine(int my_number, Names& playerNames,
|
||||
template<class sint, class sgf2n>
|
||||
Machine<sint, sgf2n>::~Machine()
|
||||
{
|
||||
sint::LivePrep::teardown();
|
||||
sgf2n::LivePrep::teardown();
|
||||
|
||||
delete P;
|
||||
for (auto& queue : queues)
|
||||
delete queue;
|
||||
@@ -308,14 +345,12 @@ DataPositions Machine<sint, sgf2n>::run_tape(int thread_number, int tape_number,
|
||||
//printf("Running line %d\n",exec);
|
||||
if (progs[tape_number].usage_unknown())
|
||||
{
|
||||
#ifndef INSECURE
|
||||
if (not opts.live_prep and thread_number != 0)
|
||||
{
|
||||
cerr << "Internally called tape " << tape_number <<
|
||||
" has unknown offline data usage" << endl;
|
||||
throw invalid_program();
|
||||
insecure(
|
||||
"Internally called tape " + to_string(tape_number)
|
||||
+ " has unknown offline data usage");
|
||||
}
|
||||
#endif
|
||||
return DataPositions(N.num_players());
|
||||
}
|
||||
else
|
||||
@@ -336,23 +371,20 @@ DataPositions Machine<sint, sgf2n>::join_tape(int i)
|
||||
}
|
||||
|
||||
template<class sint, class sgf2n>
|
||||
void Machine<sint, sgf2n>::run()
|
||||
void Machine<sint, sgf2n>::run_step(const string& progname)
|
||||
{
|
||||
Timer proc_timer(CLOCK_PROCESS_CPUTIME_ID);
|
||||
proc_timer.start();
|
||||
timer[0].start({});
|
||||
|
||||
// run main tape
|
||||
prepare(progname);
|
||||
run_tape(0, 0, 0, N.num_players());
|
||||
join_tape(0);
|
||||
}
|
||||
|
||||
print_compiler();
|
||||
|
||||
finish_timer.start();
|
||||
template<class sint, class sgf2n>
|
||||
pair<DataPositions, NamedCommStats> Machine<sint, sgf2n>::stop_threads()
|
||||
{
|
||||
// Tell all C-threads to stop
|
||||
for (int i=0; i<nthreads; i++)
|
||||
{
|
||||
//printf("Send kill signal to client\n");
|
||||
//printf("Send kill signal to client\n");
|
||||
queues[i]->schedule(-1);
|
||||
}
|
||||
|
||||
@@ -369,6 +401,40 @@ void Machine<sint, sgf2n>::run()
|
||||
pos.increase(queues[i]->result().pos);
|
||||
pthread_join(threads[i],NULL);
|
||||
}
|
||||
|
||||
auto comm_stats = total_comm();
|
||||
|
||||
for (auto& queue : queues)
|
||||
delete queue;
|
||||
|
||||
queues.clear();
|
||||
|
||||
nthreads = 0;
|
||||
|
||||
return {pos, comm_stats};
|
||||
}
|
||||
|
||||
template<class sint, class sgf2n>
|
||||
void Machine<sint, sgf2n>::run(const string& progname)
|
||||
{
|
||||
prepare(progname);
|
||||
|
||||
Timer proc_timer(CLOCK_PROCESS_CPUTIME_ID);
|
||||
proc_timer.start();
|
||||
timer[0].start({});
|
||||
|
||||
// run main tape
|
||||
run_tape(0, 0, 0, N.num_players());
|
||||
join_tape(0);
|
||||
|
||||
print_compiler();
|
||||
|
||||
finish_timer.start();
|
||||
|
||||
// actual usage
|
||||
auto res = stop_threads();
|
||||
DataPositions& pos = res.first;
|
||||
|
||||
finish_timer.stop();
|
||||
|
||||
#ifdef VERBOSE
|
||||
@@ -387,7 +453,7 @@ void Machine<sint, sgf2n>::run()
|
||||
cerr << "Finish timer: " << finish_timer.elapsed() << endl;
|
||||
#endif
|
||||
|
||||
NamedCommStats comm_stats = total_comm();
|
||||
NamedCommStats& comm_stats = res.second;
|
||||
|
||||
if (opts.verbose)
|
||||
{
|
||||
@@ -475,17 +541,12 @@ void Machine<sint, sgf2n>::run()
|
||||
stats.print();
|
||||
}
|
||||
|
||||
#ifndef INSECURE
|
||||
if (not opts.file_prep_per_thread)
|
||||
{
|
||||
Data_Files<sint, sgf2n> df(*this);
|
||||
df.seekg(pos);
|
||||
df.prune();
|
||||
}
|
||||
#endif
|
||||
|
||||
sint::LivePrep::teardown();
|
||||
sgf2n::LivePrep::teardown();
|
||||
|
||||
suggest_optimizations();
|
||||
|
||||
|
||||
@@ -37,13 +37,16 @@ template<class T, class U>
|
||||
int OfflineMachine<W>::run()
|
||||
{
|
||||
T::clear::init_default(this->online_opts.prime_length());
|
||||
U::clear::init_field(U::clear::default_degree());
|
||||
T::bit_type::mac_key_type::init_field();
|
||||
Machine<T, U>::init_binary_domains(this->online_opts.security_parameter,
|
||||
this->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);
|
||||
|
||||
generate<T>();
|
||||
generate<typename T::bit_type::part_type>();
|
||||
generate<U>();
|
||||
|
||||
@@ -100,6 +100,9 @@ void thread_info<sint, sgf2n>::Sub_Main_Func()
|
||||
processor = new Processor<sint, sgf2n>(tinfo->thread_num,P,*MC2,*MCp,machine,progs.at(thread_num > 0));
|
||||
auto& Proc = *processor;
|
||||
|
||||
// don't count communication for initialization
|
||||
P.reset_stats();
|
||||
|
||||
bool flag=true;
|
||||
int program=-3;
|
||||
// int exec=0;
|
||||
@@ -287,10 +290,8 @@ void thread_info<sint, sgf2n>::Sub_Main_Func()
|
||||
// final check
|
||||
Proc.check();
|
||||
|
||||
#ifndef INSECURE
|
||||
if (machine.opts.file_prep_per_thread)
|
||||
Proc.DataF.prune();
|
||||
#endif
|
||||
|
||||
wait_timer.start();
|
||||
queues->next();
|
||||
|
||||
@@ -17,11 +17,11 @@ protected:
|
||||
const char** argv;
|
||||
OnlineOptions& online_opts;
|
||||
|
||||
int lg2, opening_sum, max_broadcast;
|
||||
int lg2;
|
||||
|
||||
Names playerNames;
|
||||
|
||||
bool use_encryption, receive_threads;
|
||||
bool use_encryption;
|
||||
|
||||
ez::ezOptionParser& opt;
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ template<class T, class U>
|
||||
int spdz_main(int argc, const char** argv, ez::ezOptionParser& opt, bool live_prep_default = true)
|
||||
{
|
||||
OnlineOptions& online_opts = OnlineOptions::singleton;
|
||||
online_opts = {opt, argc, argv, 1000, live_prep_default, T::clear::invertible};
|
||||
online_opts = {opt, argc, argv, T(), live_prep_default};
|
||||
|
||||
DishonestMajorityMachine machine(argc, argv, opt, online_opts, typename U::clear());
|
||||
return machine.run<T, U>();
|
||||
@@ -28,8 +28,7 @@ template<class V>
|
||||
OnlineMachine::OnlineMachine(int argc, const char** argv, ez::ezOptionParser& opt,
|
||||
OnlineOptions& online_opts, int nplayers, V) :
|
||||
argc(argc), argv(argv), online_opts(online_opts), lg2(0),
|
||||
opening_sum(0), max_broadcast(0),
|
||||
use_encryption(false), receive_threads(false),
|
||||
use_encryption(false),
|
||||
opt(opt), nplayers(nplayers)
|
||||
{
|
||||
opt.add(
|
||||
@@ -125,33 +124,6 @@ DishonestMajorityMachine::DishonestMajorityMachine(int argc, const char** argv,
|
||||
opt.example = string() + argv[0] + " -p 0 -N 2 sample-prog\n" + argv[0]
|
||||
+ " -h localhost -p 1 -N 2 sample-prog\n";
|
||||
|
||||
opt.add(
|
||||
"0", // Default.
|
||||
0, // Required?
|
||||
1, // Number of args expected.
|
||||
0, // Delimiter if expecting multiple args.
|
||||
"Sum at most n shares at once when using indirect communication", // Help description.
|
||||
"-s", // Flag token.
|
||||
"--opening-sum" // Flag token.
|
||||
);
|
||||
opt.add(
|
||||
"", // Default.
|
||||
0, // Required?
|
||||
0, // Number of args expected.
|
||||
0, // Delimiter if expecting multiple args.
|
||||
"Use player-specific threads for communication", // Help description.
|
||||
"-t", // Flag token.
|
||||
"--threads" // Flag token.
|
||||
);
|
||||
opt.add(
|
||||
"0", // Default.
|
||||
0, // Required?
|
||||
1, // Number of args expected.
|
||||
0, // Delimiter if expecting multiple args.
|
||||
"Maximum number of parties to send to at once", // Help description.
|
||||
"-mb", // Flag token.
|
||||
"--max-broadcast" // Flag token.
|
||||
);
|
||||
opt.add(
|
||||
"", // Default.
|
||||
0, // Required?
|
||||
@@ -163,11 +135,7 @@ DishonestMajorityMachine::DishonestMajorityMachine(int argc, const char** argv,
|
||||
);
|
||||
online_opts.finalize(opt, argc, argv);
|
||||
|
||||
opt.get("--opening-sum")->getInt(opening_sum);
|
||||
opt.get("--max-broadcast")->getInt(max_broadcast);
|
||||
|
||||
use_encryption = opt.isSet("--encrypted");
|
||||
receive_threads = opt.isSet("--threads");
|
||||
|
||||
start_networking();
|
||||
}
|
||||
@@ -230,12 +198,8 @@ int OnlineMachine::run()
|
||||
try
|
||||
#endif
|
||||
{
|
||||
Machine<T, U>(online_opts.playerno, playerNames, online_opts.progname,
|
||||
online_opts.memtype, lg2,
|
||||
online_opts.direct, opening_sum,
|
||||
receive_threads, max_broadcast,
|
||||
use_encryption, online_opts.live_prep,
|
||||
online_opts).run();
|
||||
Machine<T, U>(playerNames, use_encryption, online_opts, lg2).run(
|
||||
online_opts.progname);
|
||||
|
||||
if (online_opts.verbose)
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "Math/gfp.h"
|
||||
#include "Math/gfpvar.h"
|
||||
#include "Protocols/HemiOptions.h"
|
||||
#include "Protocols/config.h"
|
||||
|
||||
#include "Math/gfp.hpp"
|
||||
|
||||
@@ -26,10 +27,14 @@ OnlineOptions::OnlineOptions() : playerno(-1)
|
||||
bits_from_squares = false;
|
||||
direct = false;
|
||||
bucket_size = 4;
|
||||
security_parameter = DEFAULT_SECURITY;
|
||||
cmd_private_input_file = "Player-Data/Input";
|
||||
cmd_private_output_file = "";
|
||||
file_prep_per_thread = false;
|
||||
trunc_error = 40;
|
||||
trunc_error = DEFAULT_SECURITY;
|
||||
opening_sum = 0;
|
||||
max_broadcast = 0;
|
||||
receive_threads = false;
|
||||
#ifdef VERBOSE
|
||||
verbose = true;
|
||||
#else
|
||||
@@ -38,7 +43,7 @@ OnlineOptions::OnlineOptions() : playerno(-1)
|
||||
}
|
||||
|
||||
OnlineOptions::OnlineOptions(ez::ezOptionParser& opt, int argc,
|
||||
const char** argv, false_type) :
|
||||
const char** argv, bool security) :
|
||||
OnlineOptions()
|
||||
{
|
||||
opt.syntax = std::string(argv[0]) + " [OPTIONS] [<playerno>] <progname>";
|
||||
@@ -104,6 +109,18 @@ OnlineOptions::OnlineOptions(ez::ezOptionParser& opt, int argc,
|
||||
"--bucket-size" // Flag token.
|
||||
);
|
||||
|
||||
if (security)
|
||||
opt.add(
|
||||
to_string(security_parameter).c_str(), // Default.
|
||||
0, // Required?
|
||||
1, // Number of args expected.
|
||||
0, // Delimiter if expecting multiple args.
|
||||
("Security parameter (default: " + to_string(security_parameter)
|
||||
+ ")").c_str(), // Help description.
|
||||
"-S", // Flag token.
|
||||
"--security" // Flag token.
|
||||
);
|
||||
|
||||
opt.parse(argc, argv);
|
||||
|
||||
interactive = opt.isSet("-I");
|
||||
@@ -117,13 +134,24 @@ OnlineOptions::OnlineOptions(ez::ezOptionParser& opt, int argc,
|
||||
verbose = opt.isSet("--verbose");
|
||||
#endif
|
||||
|
||||
if (security)
|
||||
{
|
||||
opt.get("-S")->getInt(security_parameter);
|
||||
cerr << "Using security parameter " << security_parameter << endl;
|
||||
if (security_parameter <= 0)
|
||||
{
|
||||
cerr << "Invalid security parameter: " << security_parameter << endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
opt.resetArgs();
|
||||
}
|
||||
|
||||
OnlineOptions::OnlineOptions(ez::ezOptionParser& opt, int argc,
|
||||
const char** argv, int default_batch_size, bool default_live_prep,
|
||||
bool variable_prime_length) :
|
||||
OnlineOptions(opt, argc, argv, false_type())
|
||||
bool variable_prime_length, bool security) :
|
||||
OnlineOptions(opt, argc, argv, security)
|
||||
{
|
||||
if (default_batch_size <= 0)
|
||||
default_batch_size = batch_size;
|
||||
@@ -263,6 +291,9 @@ void OnlineOptions::finalize(ez::ezOptionParser& opt, int argc,
|
||||
vector<string> badOptions;
|
||||
unsigned int i;
|
||||
|
||||
opt.footer += "\nSee also https://mp-spdz.readthedocs.io/en/latest/networking.html "
|
||||
"for documentation on the networking setup.\n";
|
||||
|
||||
if (allArgs.size() != 3u - opt.isSet("-p"))
|
||||
{
|
||||
cerr << "ERROR: incorrect number of arguments to " << argv[0] << endl;
|
||||
@@ -329,6 +360,16 @@ void OnlineOptions::finalize(ez::ezOptionParser& opt, int argc,
|
||||
}
|
||||
|
||||
set_trunc_error(opt);
|
||||
|
||||
auto o = opt.get("--opening-sum");
|
||||
if (o)
|
||||
o->getInt(opening_sum);
|
||||
|
||||
o = opt.get("--max-broadcast");
|
||||
if (o)
|
||||
o->getInt(max_broadcast);
|
||||
|
||||
receive_threads = opt.isSet("--threads");
|
||||
}
|
||||
|
||||
void OnlineOptions::set_trunc_error(ez::ezOptionParser& opt)
|
||||
|
||||
@@ -26,21 +26,26 @@ public:
|
||||
bool bits_from_squares;
|
||||
bool direct;
|
||||
int bucket_size;
|
||||
int security_parameter;
|
||||
std::string cmd_private_input_file;
|
||||
std::string cmd_private_output_file;
|
||||
bool verbose;
|
||||
bool file_prep_per_thread;
|
||||
int trunc_error;
|
||||
int opening_sum, max_broadcast;
|
||||
bool receive_threads;
|
||||
|
||||
OnlineOptions();
|
||||
OnlineOptions(ez::ezOptionParser& opt, int argc, const char** argv,
|
||||
false_type);
|
||||
bool security);
|
||||
OnlineOptions(ez::ezOptionParser& opt, int argc, const char** argv,
|
||||
int default_batch_size = 0, bool default_live_prep = true,
|
||||
bool variable_prime_length = false);
|
||||
bool variable_prime_length = false, bool security = true);
|
||||
template<class T>
|
||||
OnlineOptions(ez::ezOptionParser& opt, int argc, const char** argv, T,
|
||||
bool default_live_prep = true);
|
||||
template<class T>
|
||||
OnlineOptions(T);
|
||||
~OnlineOptions() {}
|
||||
|
||||
void finalize(ez::ezOptionParser& opt, int argc, const char** argv);
|
||||
|
||||
@@ -20,11 +20,49 @@ OnlineOptions::OnlineOptions(ez::ezOptionParser& opt, int argc,
|
||||
0, // Required?
|
||||
1, // Number of args expected.
|
||||
0, // Delimiter if expecting multiple args.
|
||||
"Probabilistic truncation error "
|
||||
"(2^-x, default: 40)", // Help description.
|
||||
("Probabilistic truncation error (2^-x, default: "
|
||||
+ to_string(trunc_error) + ")").c_str(), // Help description.
|
||||
"-E", // Flag token.
|
||||
"--trunc-error" // Flag token.
|
||||
);
|
||||
|
||||
if (T::dishonest_majority)
|
||||
{
|
||||
opt.add(
|
||||
"0", // Default.
|
||||
0, // Required?
|
||||
1, // Number of args expected.
|
||||
0, // Delimiter if expecting multiple args.
|
||||
"Sum at most n shares at once when using indirect communication", // Help description.
|
||||
"-s", // Flag token.
|
||||
"--opening-sum" // Flag token.
|
||||
);
|
||||
opt.add(
|
||||
"", // Default.
|
||||
0, // Required?
|
||||
0, // Number of args expected.
|
||||
0, // Delimiter if expecting multiple args.
|
||||
"Use player-specific threads for communication", // Help description.
|
||||
"-t", // Flag token.
|
||||
"--threads" // Flag token.
|
||||
);
|
||||
opt.add(
|
||||
"0", // Default.
|
||||
0, // Required?
|
||||
1, // Number of args expected.
|
||||
0, // Delimiter if expecting multiple args.
|
||||
"Maximum number of parties to send to at once", // Help description.
|
||||
"-mb", // Flag token.
|
||||
"--max-broadcast" // Flag token.
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
OnlineOptions::OnlineOptions(T) : OnlineOptions()
|
||||
{
|
||||
if (T::dishonest_majority)
|
||||
batch_size = 1000;
|
||||
}
|
||||
|
||||
#endif /* PROCESSOR_ONLINEOPTIONS_HPP_ */
|
||||
|
||||
@@ -21,7 +21,7 @@ class Program
|
||||
unsigned max_reg[MAX_REG_TYPE];
|
||||
|
||||
// Memory size used directly
|
||||
unsigned max_mem[MAX_REG_TYPE];
|
||||
size_t max_mem[MAX_REG_TYPE];
|
||||
|
||||
// True if program contains variable-sized loop
|
||||
bool unknown_usage;
|
||||
@@ -48,7 +48,7 @@ class Program
|
||||
unsigned num_reg(RegType reg_type) const
|
||||
{ return max_reg[reg_type]; }
|
||||
|
||||
unsigned direct_mem(RegType reg_type) const
|
||||
size_t direct_mem(RegType reg_type) const
|
||||
{ return max_mem[reg_type]; }
|
||||
|
||||
friend ostream& operator<<(ostream& s,const Program& P);
|
||||
|
||||
@@ -65,7 +65,7 @@ HonestMajorityRingMachineWithSecurity<U, V>::HonestMajorityRingMachineWithSecuri
|
||||
int argc, const char** argv, ez::ezOptionParser& opt)
|
||||
{
|
||||
OnlineOptions online_opts(opt, argc, argv);
|
||||
RingOptions opts(opt, argc, argv, true);
|
||||
RingOptions opts(opt, argc, argv);
|
||||
HonestMajorityMachine machine(argc, argv, opt, online_opts);
|
||||
int R = opts.ring_size_from_opts_or_schedule(online_opts.progname);
|
||||
switch (R)
|
||||
@@ -76,15 +76,19 @@ HonestMajorityRingMachineWithSecurity<U, V>::HonestMajorityRingMachineWithSecuri
|
||||
break;
|
||||
#define X(K) \
|
||||
case K: \
|
||||
switch (opts.S) \
|
||||
{ \
|
||||
int S = online_opts.security_parameter; \
|
||||
switch (S) \
|
||||
{ \
|
||||
Y(K, 40) \
|
||||
Y(K, DEFAULT_SECURITY) \
|
||||
default: \
|
||||
cerr << "not compiled for security parameter " << to_string(opts.S) << endl; \
|
||||
cerr << "add 'Y(K, " << opts.S << ")' to " __FILE__ ", line 76" << endl; \
|
||||
cerr << "not compiled for security parameter " << to_string(S) << endl; \
|
||||
cerr << "add 'Y(K, " << S << ")' to " __FILE__ ", line 76" << endl; \
|
||||
cerr << "or compile with -DDEFAULT_SECURITY=" << S << endl; \
|
||||
exit(1); \
|
||||
} \
|
||||
break;
|
||||
break; \
|
||||
}
|
||||
X(64)
|
||||
#ifdef RING_SIZE
|
||||
X(RING_SIZE)
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
RingOptions::RingOptions(ez::ezOptionParser& opt, int argc, const char** argv,
|
||||
bool security)
|
||||
RingOptions::RingOptions(ez::ezOptionParser& opt, int argc, const char** argv)
|
||||
{
|
||||
opt.add(
|
||||
"64", // Default.
|
||||
@@ -21,28 +20,12 @@ RingOptions::RingOptions(ez::ezOptionParser& opt, int argc, const char** argv,
|
||||
"-R", // Flag token.
|
||||
"--ring" // Flag token.
|
||||
);
|
||||
if (security)
|
||||
opt.add(
|
||||
"40", // Default.
|
||||
0, // Required?
|
||||
1, // Number of args expected.
|
||||
0, // Delimiter if expecting multiple args.
|
||||
"Security parameter (default: 40)", // Help description.
|
||||
"-S", // Flag token.
|
||||
"--security" // Flag token.
|
||||
);
|
||||
opt.parse(argc, argv);
|
||||
opt.get("-R")->getInt(R);
|
||||
if (security)
|
||||
opt.get("-S")->getInt(S);
|
||||
else
|
||||
S = -1;
|
||||
R_is_set = opt.isSet("-R");
|
||||
opt.resetArgs();
|
||||
if (R_is_set)
|
||||
cerr << "Trying to run " << R << "-bit computation" << endl;
|
||||
if (security)
|
||||
cerr << "Using security parameter " << S << endl;
|
||||
}
|
||||
|
||||
int RingOptions::ring_size_from_opts_or_schedule(string progname)
|
||||
|
||||
@@ -16,10 +16,8 @@ class RingOptions
|
||||
|
||||
public:
|
||||
int R;
|
||||
int S;
|
||||
|
||||
RingOptions(ez::ezOptionParser& opt, int argc, const char** argv,
|
||||
bool security = false);
|
||||
RingOptions(ez::ezOptionParser& opt, int argc, const char** argv);
|
||||
|
||||
int ring_size_from_opts_or_schedule(string progname);
|
||||
};
|
||||
|
||||
@@ -203,7 +203,7 @@
|
||||
*dest++ = *op1++ == *op2++) \
|
||||
X(PRINTINT, Proc.out << Proc.read_Ci(r[0]) << flush,) \
|
||||
X(PRINTFLOATPREC, Proc.out << setprecision(n),) \
|
||||
X(PRINTSTR, Proc.out << string((char*)&n,sizeof(n)) << flush,) \
|
||||
X(PRINTSTR, Proc.out << string((char*)&n,4) << flush,) \
|
||||
X(PRINTCHR, Proc.out << string((char*)&n,1) << flush,) \
|
||||
X(SHUFFLE, shuffle(Proc),) \
|
||||
X(BITDECINT, bitdecint(Proc),) \
|
||||
@@ -270,7 +270,7 @@
|
||||
*dest++ = *op1++ >> n) \
|
||||
X(GPRINTREG, auto source = &C2[r[0]], \
|
||||
Proc.out << "Reg[" << r[0] << "] = " << *source++ \
|
||||
<< " # " << string((char*)&n,sizeof(n)) << endl) \
|
||||
<< " # " << string((char*)&n, 4) << endl) \
|
||||
X(GPRINTREGPLAIN, auto source = &C2[r[0]], \
|
||||
Proc.out << *source++ << flush) \
|
||||
X(GBITDEC, gbitdec(C2),) \
|
||||
|
||||
3
Programs/Source/l2h_comparison.mpc
Normal file
3
Programs/Source/l2h_comparison.mpc
Normal file
@@ -0,0 +1,3 @@
|
||||
res = sint.load_mem(0) < sint.load_mem(1)
|
||||
res.store_in_mem(3)
|
||||
print_ln('comparison in VM: %s', res.reveal())
|
||||
1
Programs/Source/l2h_multiplication.mpc
Normal file
1
Programs/Source/l2h_multiplication.mpc
Normal file
@@ -0,0 +1 @@
|
||||
(sint.load_mem(0) * sint.load_mem(1)).store_in_mem(2)
|
||||
@@ -23,6 +23,7 @@ class Player;
|
||||
template<class T>
|
||||
class Beaver : public ProtocolBase<T>
|
||||
{
|
||||
protected:
|
||||
vector<T> shares;
|
||||
vector<typename T::open_type> opened;
|
||||
vector<array<T, 3>> triples;
|
||||
|
||||
@@ -43,15 +43,16 @@ void ChaiGearPrep<T>::basic_setup(Player& P)
|
||||
assert(machine == 0);
|
||||
machine = new MultiplicativeMachine;
|
||||
auto& setup = machine->setup.part<FD>();
|
||||
auto& options = CowGearOptions::singleton;
|
||||
int lowgear_security = OnlineOptions::singleton.security_parameter;
|
||||
#ifdef VERBOSE
|
||||
auto& options = CowGearOptions::singleton;
|
||||
cerr << "Covert security parameter for key and MAC generation: "
|
||||
<< options.covert_security << endl;
|
||||
cerr << "Triple generation security parameter: "
|
||||
<< options.lowgear_security << endl;
|
||||
<< lowgear_security << endl;
|
||||
#endif
|
||||
machine->sec = options.lowgear_security;
|
||||
setup.secure_init(P, *machine, T::clear::length(), options.lowgear_security);
|
||||
machine->sec = lowgear_security;
|
||||
setup.secure_init(P, *machine, T::clear::length(), lowgear_security);
|
||||
T::clear::template init<typename FD::T>();
|
||||
#ifdef VERBOSE
|
||||
cerr << T::type_string() << " parameter setup took " << timer.elapsed()
|
||||
|
||||
@@ -23,7 +23,6 @@ CowGearOptions::CowGearOptions(bool covert)
|
||||
covert_security = -1;
|
||||
}
|
||||
|
||||
lowgear_security = 40;
|
||||
use_top_gear = false;
|
||||
}
|
||||
|
||||
@@ -49,7 +48,7 @@ CowGearOptions::CowGearOptions(ez::ezOptionParser& opt, int argc,
|
||||
0, // Required?
|
||||
1, // Number of args expected.
|
||||
0, // Delimiter if expecting multiple args.
|
||||
"LowGear security parameter (default: 40)", // Help description.
|
||||
"DEPRECATED: use -S/--security", // Help description.
|
||||
"-l", // Flag token.
|
||||
"--lowgear-security" // Flag token.
|
||||
);
|
||||
@@ -76,15 +75,8 @@ CowGearOptions::CowGearOptions(ez::ezOptionParser& opt, int argc,
|
||||
opt.get("-c")->getInt(covert_security);
|
||||
if (opt.isSet("-l"))
|
||||
{
|
||||
opt.get("-l")->getInt(lowgear_security);
|
||||
if (lowgear_security <= 0)
|
||||
{
|
||||
throw exception();
|
||||
cerr << "Invalid LowGear Security parameter: " << lowgear_security << endl;
|
||||
exit(1);
|
||||
}
|
||||
if (covert_security > (1LL << lowgear_security))
|
||||
insecure(", LowGear security less than key generation security");
|
||||
cerr << "Deprecated parameter, use -S/--security" << endl;
|
||||
exit(1);
|
||||
}
|
||||
use_top_gear = not opt.isSet("-J");
|
||||
if (opt.isSet("-T"))
|
||||
|
||||
@@ -16,7 +16,6 @@ public:
|
||||
static CowGearOptions singleton;
|
||||
|
||||
int covert_security;
|
||||
int lowgear_security;
|
||||
|
||||
CowGearOptions(bool covert = true);
|
||||
CowGearOptions(ez::ezOptionParser& opt, int argc, const char** argv,
|
||||
|
||||
@@ -38,14 +38,15 @@ void CowGearPrep<T>::basic_setup(Player& P)
|
||||
pairwise_machine = new PairwiseMachine(P);
|
||||
auto& machine = *pairwise_machine;
|
||||
auto& setup = machine.setup<FD>();
|
||||
auto& options = CowGearOptions::singleton;
|
||||
int lowgear_security = OnlineOptions::singleton.security_parameter;
|
||||
#ifdef VERBOSE
|
||||
auto& options = CowGearOptions::singleton;
|
||||
if (T::covert)
|
||||
cerr << "Covert security parameter for key and MAC generation: "
|
||||
<< options.covert_security << endl;
|
||||
cerr << "LowGear security parameter: " << options.lowgear_security << endl;
|
||||
cerr << "LowGear security parameter: " << lowgear_security << endl;
|
||||
#endif
|
||||
setup.secure_init(P, machine, T::clear::length(), options.lowgear_security);
|
||||
setup.secure_init(P, machine, T::clear::length(), lowgear_security);
|
||||
T::clear::template init<typename FD::T>();
|
||||
#ifdef VERBOSE
|
||||
cerr << T::type_string() << " parameter setup took " << timer.elapsed()
|
||||
|
||||
@@ -9,10 +9,12 @@
|
||||
template<class T>
|
||||
class DabitSacrifice
|
||||
{
|
||||
static const int S = 40;
|
||||
const int S;
|
||||
|
||||
public:
|
||||
static int minimum_n_inputs(int n_outputs = 0)
|
||||
DabitSacrifice();
|
||||
|
||||
int minimum_n_inputs(int n_outputs = 0)
|
||||
{
|
||||
if (n_outputs < 1)
|
||||
n_outputs = OnlineOptions::singleton.batch_size;
|
||||
|
||||
@@ -11,6 +11,12 @@
|
||||
|
||||
#include <math.h>
|
||||
|
||||
template<class T>
|
||||
DabitSacrifice<T>::DabitSacrifice() :
|
||||
S(OnlineOptions::singleton.security_parameter)
|
||||
{
|
||||
}
|
||||
|
||||
template<class T>
|
||||
dabit<T>& operator+=(dabit<T>& x, const dabit<T>& y)
|
||||
{
|
||||
|
||||
38
Protocols/DealerInput.h
Normal file
38
Protocols/DealerInput.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* DealerInput.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PROTOCOLS_DEALERINPUT_H_
|
||||
#define PROTOCOLS_DEALERINPUT_H_
|
||||
|
||||
#include "../Networking/AllButLastPlayer.h"
|
||||
#include "Processor/Input.h"
|
||||
|
||||
template<class T>
|
||||
class DealerInput : public InputBase<T>
|
||||
{
|
||||
Player& P;
|
||||
octetStreams to_send, to_receive;
|
||||
SeededPRNG G;
|
||||
vector<SemiShare<typename T::clear>> shares;
|
||||
bool from_dealer;
|
||||
AllButLastPlayer sub_player;
|
||||
SemiInput<SemiShare<typename T::clear>>* internal;
|
||||
|
||||
public:
|
||||
DealerInput(SubProcessor<T>& proc, typename T::MAC_Check&);
|
||||
DealerInput(typename T::MAC_Check&, Preprocessing<T>&, Player& P);
|
||||
DealerInput(Player& P);
|
||||
~DealerInput();
|
||||
|
||||
bool is_dealer(int player = -1);
|
||||
|
||||
void reset(int player);
|
||||
void add_mine(const typename T::open_type& input, int n_bits = -1);
|
||||
void add_other(int player, int n_bits = -1);
|
||||
void exchange();
|
||||
T finalize(int player, int n_bits = -1);
|
||||
};
|
||||
|
||||
#endif /* PROTOCOLS_DEALERINPUT_H_ */
|
||||
115
Protocols/DealerInput.hpp
Normal file
115
Protocols/DealerInput.hpp
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* DealerInput.hpp
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PROTOCOLS_DEALERINPUT_HPP_
|
||||
#define PROTOCOLS_DEALERINPUT_HPP_
|
||||
|
||||
#include "DealerInput.h"
|
||||
|
||||
template<class T>
|
||||
DealerInput<T>::DealerInput(SubProcessor<T>& proc, typename T::MAC_Check&) :
|
||||
DealerInput(proc.P)
|
||||
{
|
||||
}
|
||||
|
||||
template<class T>
|
||||
DealerInput<T>::DealerInput(typename T::MAC_Check&, Preprocessing<T>&,
|
||||
Player& P) :
|
||||
DealerInput(P)
|
||||
{
|
||||
}
|
||||
|
||||
template<class T>
|
||||
DealerInput<T>::DealerInput(Player& P) :
|
||||
P(P), to_send(P), shares(P.num_players()), from_dealer(false),
|
||||
sub_player(P)
|
||||
{
|
||||
if (is_dealer())
|
||||
internal = 0;
|
||||
else
|
||||
internal = new SemiInput<SemiShare<typename T::clear>>(0, sub_player);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
DealerInput<T>::~DealerInput()
|
||||
{
|
||||
if (internal)
|
||||
delete internal;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool DealerInput<T>::is_dealer(int player)
|
||||
{
|
||||
int dealer_player = P.num_players() - 1;
|
||||
if (player == -1)
|
||||
return P.my_num() == dealer_player;
|
||||
else
|
||||
return player == dealer_player;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void DealerInput<T>::reset(int player)
|
||||
{
|
||||
if (player == 0)
|
||||
{
|
||||
to_send.reset(P);
|
||||
from_dealer = false;
|
||||
}
|
||||
else if (not is_dealer())
|
||||
internal->reset(player - 1);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void DealerInput<T>::add_mine(const typename T::open_type& input,
|
||||
int)
|
||||
{
|
||||
if (is_dealer())
|
||||
{
|
||||
make_share(shares.data(), input, P.num_players() - 1, 0, G);
|
||||
for (int i = 1; i < P.num_players(); i++)
|
||||
shares.at(i - 1).pack(to_send[i]);
|
||||
from_dealer = true;
|
||||
}
|
||||
else
|
||||
internal->add_mine(input);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void DealerInput<T>::add_other(int player, int)
|
||||
{
|
||||
if (is_dealer(player))
|
||||
from_dealer = true;
|
||||
else if (not is_dealer())
|
||||
internal->add_other(player);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void DealerInput<T>::exchange()
|
||||
{
|
||||
if (from_dealer)
|
||||
{
|
||||
vector<bool> senders(P.num_players());
|
||||
senders.back() = true;
|
||||
P.send_receive_all(senders, to_send, to_receive);
|
||||
}
|
||||
else if (not is_dealer())
|
||||
internal->exchange();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T DealerInput<T>::finalize(int player, int)
|
||||
{
|
||||
if (is_dealer())
|
||||
return {};
|
||||
else
|
||||
{
|
||||
if (is_dealer(player))
|
||||
return to_receive.back().template get<T>();
|
||||
else
|
||||
return internal->finalize(player);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* PROTOCOLS_DEALERINPUT_HPP_ */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user