Functionality to call high-level code from C++.

This commit is contained in:
Marcel Keller
2024-11-21 12:18:10 +11:00
parent e7554ccbfd
commit 91321ff8cd
245 changed files with 3875 additions and 1139 deletions

1
.gitignore vendored
View File

@@ -49,6 +49,7 @@ callgrind.out.*
Programs/Bytecode/*
Programs/Schedules/*
Programs/Public-Input/*
Programs/Functions
*.com
*.class
*.dll

3
.gitmodules vendored
View File

@@ -13,3 +13,6 @@
[submodule "deps/SimplestOT_C"]
path = deps/SimplestOT_C
url = https://github.com/mkskeller/SimplestOT_C
[submodule "deps/sse2neon"]
path = deps/sse2neon
url = https://github.com/DLTcollab/sse2neon

View File

@@ -1,5 +1,14 @@
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.4.0 (November 21, 2024)
- Functionality to call high-level code from C++
- Matrix triples from file for all appropriate protocols
- Exit with message on errors instead of uncaught exceptions
- Reduce memory usage for binary memory
- Optimized cint-regint conversion in Dealer protocol
- Fixed security bug: missing MAC check in probabilistic truncation
## 0.3.9 (July 9, 2024)
- Inference with non-sequential PyTorch networks

2
CONFIG
View File

@@ -71,6 +71,8 @@ CXX = clang++
# use CONFIG.mine to overwrite DIR settings
-include CONFIG.mine
AVX_SIMPLEOT := $(AVX_OT)
ifeq ($(USE_GF2N_LONG),1)
GF2N_LONG = -DUSE_GF2N_LONG
endif

View File

@@ -540,8 +540,8 @@ class split(base.Instruction):
:param: number of arguments to follow (number of bits times number of additive shares plus one)
:param: source (sint)
:param: first share of least significant bit
:param: second share of least significant bit
:param: first share of least significant bit (sbit)
:param: second share of least significant bit (sbit)
:param: (remaining share of least significant bit)...
:param: (repeat from first share for bit one step higher)...
"""

View File

@@ -737,6 +737,7 @@ class sbitvec(_vec, _bit, _binary):
:py:obj:`v` and the columns by calling :py:obj:`elements`.
"""
class sbitvecn(cls, _structure):
n_bits = n
@staticmethod
def get_type(n):
return cls.get_type(n)
@@ -757,17 +758,19 @@ class sbitvec(_vec, _bit, _binary):
:param: player (int)
"""
v = [0] * n
sbits._check_input_player(player)
instructions_base.check_vector_size(size)
for i in range(size):
vv = [sbit() for i in range(n)]
inst.inputbvec(n + 3, f, player, *vv)
for j in range(n):
tmp = vv[j] << i
v[j] = tmp ^ v[j]
sbits._check_input_player(player)
return cls.from_vec(v)
if size == 1:
res = cls.from_vec(sbit() for i in range(n))
inst.inputbvec(n + 3, f, player, *res.v)
return res
else:
elements = []
for i in range(size):
v = sbits.get_type(n)()
inst.inputb(player, n, f, v)
elements.append(v)
return cls(elements)
get_raw_input_from = get_input_from
@classmethod
def from_vec(cls, vector):

View File

@@ -178,6 +178,8 @@ class StraightlineAllocator:
dup = dup.vectorbase
self.alloc[dup] = self.alloc[base]
dup.i = self.alloc[base]
if not dup.dup_count:
dup.dup_count = len(base.duplicates)
def dealloc_reg(self, reg, inst, free):
if reg.vector:
@@ -275,8 +277,9 @@ class StraightlineAllocator:
for reg in self.alloc:
for x in reg.get_all():
if x not in self.dealloc and reg not in self.dealloc \
and len(x.duplicates) == 0:
print('Warning: read before write at register', x)
and len(x.duplicates) == x.dup_count:
print('Warning: read before write at register %s/%x' %
(x, id(x)))
print('\tregister trace: %s' % format_trace(x.caller,
'\t\t'))
if options.stop:
@@ -750,6 +753,8 @@ class Merger:
G.remove_node(i)
merge_nodes.discard(i)
stats[type(instructions[i]).__name__] += 1
for reg in instructions[i].get_def():
self.block.parent.program.base_addresses.pop(reg)
instructions[i] = None
if unused_result:
eliminate(i)

View File

@@ -13,8 +13,18 @@ from .program import Program, defaults
class Compiler:
singleton = None
def __init__(self, custom_args=None, usage=None, execute=False,
split_args=False):
if Compiler.singleton:
raise CompilerError(
"Cannot have more than one compiler instance. "
"It's not possible to run direct compilation programs with "
"compile.py or compile-run.py.")
else:
Compiler.singleton = self
if usage:
self.usage = usage
else:

View File

@@ -1,3 +1,8 @@
""" This module implements `Dijkstra's algorithm
<https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm>`_ based on
oblivious RAM. """
from Compiler.oram import *
from Compiler.program import Program
@@ -222,7 +227,21 @@ class HeapQ(object):
print_ln()
print_ln()
def dijkstra(source, edges, e_index, oram_type, n_loops=None, int_type=None):
def dijkstra(source, edges, e_index, oram_type, n_loops=None, int_type=None,
debug=False):
""" Securely compute Dijstra's algorithm on a secret graph. See
:download:`../Programs/Source/dijkstra_example.mpc` for an
explanation of the required inputs.
:param source: source node (secret or clear-text integer)
:param edges: ORAM representation of edges
:param e_index: ORAM representation of vertices
:param oram_type: ORAM type to use internally (default:
:py:func:`~Compiler.oram.OptimalORAM`)
:param n_loops: when to stop (default: number of edges)
:param int_type: secret integer type (default: sint)
"""
vert_loops = n_loops * e_index.size // edges.size \
if n_loops else -1
dist = oram_type(e_index.size, entry_size=(32,log2(e_index.size)), \
@@ -267,27 +286,46 @@ def dijkstra(source, edges, e_index, oram_type, n_loops=None, int_type=None):
dist.access(v, (basic_type(alt), u), is_shorter)
#previous.access(v, u, is_shorter)
Q.update(v, basic_type(alt), is_shorter)
print_ln('u: %s, v: %s, alt: %s, dv: %s, first visit: %s', \
u.reveal(), v.reveal(), alt.reveal(), dv[0].reveal(), \
not_visited.reveal())
if debug:
print_ln('u: %s, v: %s, alt: %s, dv: %s, first visit: %s, '
'shorter: %s, running: %s, queue size: %s, last edge: %s',
u.reveal(), v.reveal(), alt.reveal(), dv[0].reveal(),
not_visited.reveal(), is_shorter.reveal(),
running.reveal(), Q.size.reveal(), last_edge.reveal())
return dist
def convert_graph(G):
edges = [None] * (2 * G.size())
e_index = [None] * (len(G))
i = 0
for v in G:
e_index[v] = i
for u in G[v]:
edges[i] = [u, G[v][u]['weight'], 0]
i += 1
edges[i-1][-1] = 1
return edges, e_index
def test_dijkstra(G, source, oram_type=ORAM, n_loops=None, int_type=sint):
""" Convert a `NetworkX directed graph
<https://networkx.org/documentation/stable/reference/classes/digraph.html>`_
to the cleartext representation of what :py:func:`dijkstra` expects. """
G = G.copy()
for u in G:
for v in G[u]:
G[u][v].setdefault('weight', 1)
edges = [None] * (2 * G.size())
e_index = [None] * (len(G))
i = 0
for v in sorted(G):
e_index[v] = i
for u in sorted(G[v]):
edges[i] = [u, G[v][u]['weight'], 0]
i += 1
if not G[v]:
edges[i] = [v, 0, 0]
i += 1
edges[i-1][-1] = 1
return list(filter(lambda x: x, edges)), e_index
def test_dijkstra(G, source, oram_type=ORAM, n_loops=None,
int_type=sint):
""" Securely compute Dijstra's algorithm on a cleartext graph.
:param G: directed graph with NetworkX interface
:param source: source node (secret or clear-text integer)
:param n_loops: when to stop (default: number of edges)
:param int_type: secret integer type (default: sint)
"""
edges_list, e_index_list = convert_graph(G)
edges = oram_type(len(edges_list), \
entry_size=(log2(len(G)), log2(len(G)), 1), \

View File

@@ -399,7 +399,7 @@ class stop(base.Instruction):
arg_format = ['i']
class use(base.Instruction):
""" Offline data usage. Necessary to avoid reusage while using
r""" Offline data usage. Necessary to avoid reusage while using
preprocessing from files. Also used to multithreading for expensive
preprocessing.
@@ -419,7 +419,7 @@ class use(base.Instruction):
args[2].i}
class use_inp(base.Instruction):
""" Input usage. Necessary to avoid reusage while using
r""" Input usage. Necessary to avoid reusage while using
preprocessing from files.
:param: domain (0: integer, 1: :math:`\mathrm{GF}(2^n)`, 2: bit)
@@ -1738,7 +1738,7 @@ class print_reg_plains(base.IOInstruction):
arg_format = ['s']
class cond_print_plain(base.IOInstruction):
""" Conditionally output clear register (with precision).
r""" Conditionally output clear register (with precision).
Outputs :math:`x \cdot 2^p` where :math:`p` is the precision.
:param: condition (cint, no output if zero)
@@ -1989,7 +1989,7 @@ class closeclientconnection(base.IOInstruction):
code = base.opcodes['CLOSECLIENTCONNECTION']
arg_format = ['ci']
class writesharestofile(base.IOInstruction):
class writesharestofile(base.VectorInstruction, base.IOInstruction):
""" Write shares to ``Persistence/Transactions-P<playerno>.data``
(appending at the end).
@@ -2002,11 +2002,12 @@ class writesharestofile(base.IOInstruction):
__slots__ = []
code = base.opcodes['WRITEFILESHARE']
arg_format = tools.chain(['ci'], itertools.repeat('s'))
vector_index = 1
def has_var_args(self):
return True
class readsharesfromfile(base.IOInstruction):
class readsharesfromfile(base.VectorInstruction, base.IOInstruction):
""" Read shares from ``Persistence/Transactions-P<playerno>.data``.
:param: number of arguments to follow / number of shares plus two (int)
@@ -2018,6 +2019,7 @@ class readsharesfromfile(base.IOInstruction):
__slots__ = []
code = base.opcodes['READFILESHARE']
arg_format = tools.chain(['ci', 'ciw'], itertools.repeat('sw'))
vector_index = 2
def has_var_args(self):
return True
@@ -2341,7 +2343,7 @@ class convint(base.Instruction):
@base.vectorize
class convmodp(base.Instruction):
""" Convert clear integer register (vector) to clear register
r""" Convert clear integer register (vector) to clear register
(vector). If the bit length is zero, the unsigned conversion is
used, otherwise signed conversion is used. This makes a difference
when computing modulo a prime :math:`p`. Signed conversion of
@@ -2814,13 +2816,11 @@ class check(base.Instruction):
@base.gf2n
@base.vectorize
class sqrs(base.CISC):
""" Secret squaring $s_i = s_j \cdot s_j$. """
r""" Secret squaring $s_i = s_j \cdot s_j$. """
__slots__ = []
arg_format = ['sw', 's']
def expand(self):
if program.options.ring:
return muls(self.args[0], self.args[1], self.args[1])
s = [program.curr_block.new_reg('s') for i in range(6)]
c = [program.curr_block.new_reg('c') for i in range(2)]
square(s[0], s[1])

View File

@@ -1200,9 +1200,11 @@ class VarArgsInstruction(Instruction):
class VectorInstruction(Instruction):
__slots__ = []
is_vec = lambda self: True
vector_index = 0
def get_code(self):
return super(VectorInstruction, self).get_code(len(self.args[0]))
return super(VectorInstruction, self).get_code(
len(self.args[self.vector_index]))
class Ciscable(Instruction):
def copy(self, size, subs):

View File

@@ -402,7 +402,8 @@ class FunctionCallTape(FunctionTape):
def __init__(self, *args, **kwargs):
super(FunctionTape, self).__init__(*args, **kwargs)
self.instances = {}
def __call__(self, *args, **kwargs):
@staticmethod
def get_key(args, kwargs):
key = (get_program(),)
def process_for_key(arg):
nonlocal key
@@ -419,6 +420,9 @@ class FunctionCallTape(FunctionTape):
for name, arg in sorted(kwargs.items()):
key += (name, 'kw')
process_for_key(arg)
return key
def __call__(self, *args, **kwargs):
key = self.get_key(args, kwargs)
if key not in self.instances:
my_args = []
def wrapped_function():
@@ -502,6 +506,60 @@ class FunctionCallTape(FunctionTape):
break_point('call-%s' % self.name)
return untuplify(tuple(out_result))
class ExportFunction(FunctionCallTape):
def __init__(self, function):
super(ExportFunction, self).__init__(function)
self.done = set()
def __call__(self, *args, **kwargs):
if kwargs:
raise CompilerError('keyword arguments not supported')
def arg_signature(arg):
if isinstance(arg, types._structure):
return '%s:%d' % (arg.arg_type(), arg.size)
elif isinstance(arg, types._vectorizable):
from .GC.types import sbitvec
if issubclass(arg.value_type, sbitvec):
return 'sbv:[%dx%d]' % (arg.total_size(),
arg.value_type.n_bits)
else:
return '%s:[%d]' % (arg.value_type.arg_type(),
arg.total_size())
else:
raise CompilerError('argument not supported: %s' % arg)
signature = []
for arg in args:
signature.append(arg_signature(arg))
signature = tuple(signature)
key = self.get_key(args, kwargs)
if key in self.instances and signature not in self.done:
raise CompilerError('signature conflict')
super(ExportFunction, self).__call__(*args, **kwargs)
if signature not in self.done:
filename = '%s/%s/%s-%s' % (get_program().programs_dir, 'Functions',
self.name, '-'.join(signature))
print('Writing to', filename)
out = open(filename, 'w')
print(get_program().name, file=out)
print(self.instances[key][0], file=out)
result = self.instances[key][1]
try:
if result is not None:
result = untuplify(result)
print(arg_signature(result), result.i, file=out)
else:
print('- 0', file=out)
except CompilerError:
raise CompilerError('return type not supported: %s' % result)
for arg in self.instances[key][2]:
if isinstance(arg, types._structure):
print(arg.i, end=' ', file=out)
elif isinstance(arg, types._vectorizable):
print(arg.address, end=' ', file=out)
else:
CompilerError('argument not supported: %s', arg)
print(file=out)
self.done.add(signature)
def function_tape(function):
return FunctionTape(function)
@@ -589,6 +647,9 @@ def function(function):
"""
return FunctionCallTape(function)
def export(function):
return ExportFunction(function)
def memorize(x, write=True):
if isinstance(x, (tuple, list)):
return tuple(memorize(i, write=write) for i in x)
@@ -898,8 +959,10 @@ def for_range(start, stop=None, step=None):
"""
def decorator(loop_body):
get_tape().unused_decorators.pop(decorator)
range_loop(loop_body, start, stop, step)
return loop_body
get_tape().unused_decorators[decorator] = 'for_range'
return decorator
def for_range_parallel(n_parallel, n_loops):
@@ -948,7 +1011,7 @@ def for_range_opt(start, stop=None, step=None, budget=None):
:param start/stop/step: int/regint/cint (used as in :py:func:`range`)
or :py:obj:`start` only as list/tuple of int (see below)
:param budget: number of instructions after which to start optimization
(default is 100,000)
(default is 1000 or as given with ``--budget``)
Example:
@@ -1487,7 +1550,7 @@ def while_do(condition, *args):
return loop_body
return decorator
def _run_and_link(function, g=None, lock_lists=True):
def _run_and_link(function, g=None, lock_lists=True, allow_return=False):
if g is None:
g = function.__globals__
if lock_lists:
@@ -1504,6 +1567,9 @@ def _run_and_link(function, g=None, lock_lists=True):
g[x] = A(g[x])
pre = copy.copy(g)
res = function()
if res is not None and not allow_return:
raise CompilerError('Conditional blocks cannot return values. '
'Use if_else instead: https://mp-spdz.readthedocs.io/en/latest/Compiler.html#Compiler.types.regint.if_else')
_link(pre, g)
return res
@@ -1536,7 +1602,7 @@ def do_while(loop_fn, g=None):
name='begin-loop')
get_tape().loop_breaks.append([])
loop_block = instructions.program.curr_block
condition = _run_and_link(loop_fn, g)
condition = _run_and_link(loop_fn, g, allow_return=True)
if callable(condition):
condition = condition()
branch = instructions.jmpnz(regint.conv(condition), 0, add_to_prog=False)
@@ -1558,7 +1624,9 @@ def if_then(condition):
condition = condition()
try:
if not condition.is_clear:
raise CompilerError('cannot branch on secret values')
raise CompilerError(
'cannot branch on secret values, use if_else instead: '
'https://mp-spdz.readthedocs.io/en/latest/Compiler.html#Compiler.types.sint.if_else')
except AttributeError:
pass
state.condition = regint.conv(condition)

View File

@@ -849,7 +849,7 @@ class Dense(DenseBase):
prod = MultiArray([N, self.d, self.d_out], sfix)
else:
prod = self.f_input
max_size = get_program().budget // self.d_out
max_size = get_program().budget
@multithread(self.n_threads, N, max_size)
def _(base, size):
X_sub = sfix.Matrix(self.N, self.d_in, address=self.X.address)
@@ -1316,12 +1316,12 @@ class Add(NoVariableLayer):
self.inputs = inputs
def _forward(self, batch=[0]):
assert len(batch) == 1
@multithread(self.n_threads, self.Y[0].total_size())
def _(base, size):
tmp = sum(inp.Y[batch[0]].get_vector(base, size)
for inp in self.inputs)
self.Y[batch[0]].assign_vector(tmp, base)
for bb in batch:
tmp = sum(inp.Y[bb].get_vector(base, size)
for inp in self.inputs)
self.Y[bb].assign_vector(tmp, base)
class FusedBatchNorm(Layer):
""" Fixed-point fused batch normalization layer (inference only).
@@ -1400,11 +1400,11 @@ class BatchNorm(Layer):
def _output(self, batch, mu, var):
factor = sfix.Array(len(mu))
factor[:] = self.InvertSqrt(var[:] + self.epsilon)
factor[:] = self.InvertSqrt(var[:] + self.epsilon) * self.weights[:]
@for_range_opt_multithread(self.n_threads,
[len(batch), self.X.sizes[1]])
def _(i, j):
tmp = self.weights[:] * (self.X[i][j][:] - mu[:]) * factor[:]
tmp = (self.X[i][j][:] - mu[:]) * factor[:]
self.my_Y[i][j][:] = self.bias[:] + tmp
@_layer_method_call_tape
@@ -2233,7 +2233,7 @@ class Optimizer:
res.output_stats = 'output_stats' in program.args
return res
def __init__(self, layers=[], report_loss=None):
def __init__(self, layers=[], report_loss=None, time_layers=False):
if get_program().options.binary:
raise CompilerError(
'machine learning code not compatible with binary circuits')
@@ -2248,6 +2248,10 @@ class Optimizer:
self.stopped_on_loss = MemValue(0)
self.stopped_on_low_loss = MemValue(0)
self.layers = layers
self.time_layers = time_layers
if time_layers:
for i, layer in enumerate(layers):
print('Timer %d: %s' % (100 + i, repr(layer)))
@property
def layers(self):
@@ -2667,8 +2671,12 @@ class Optimizer:
if model_input:
for layer in self.layers:
layer.input_from(0)
elif reset:
elif reset and not 'no_reset' in program.args:
self.reset()
else:
for layer in self.layers:
for theta in layer.thetas():
theta.alloc()
if 'one_iter' in program.args:
print_float_prec(16)
self.output_weights()
@@ -2689,6 +2697,8 @@ class Optimizer:
if 'bench10' in program.args or 'bench1' in program.args:
n = 1 if 'bench1' in program.args else 10
print('benchmarking %s iterations' % n)
# force allocatoin
self.layers[0].X, self.layers[-1].Y
@for_range(n)
def _(i):
batch = Array.create_from(regint.inc(batch_size))

View File

@@ -422,7 +422,7 @@ def mux_exp(x, y, block_size=8):
@types.vectorize
@instructions_base.sfix_cisc
def log2_fx(x, use_division=True):
"""
r"""
Returns the result of :math:`\log_2(x)` for any unbounded
number. This is achieved by changing :py:obj:`x` into
:math:`f \cdot 2^n` where f is bounded by :math:`[0.5, 1]`. Then the
@@ -463,7 +463,7 @@ def log2_fx(x, use_division=True):
def pow_fx(x, y, zero_output=False):
"""
r"""
Returns the value of the expression :math:`x^y` where both inputs
are secret shared. It uses :py:func:`log2_fx` together with
:py:func:`exp2_fx` to calculate the expression :math:`2^{y \log_2(x)}`.
@@ -487,7 +487,7 @@ def pow_fx(x, y, zero_output=False):
def log_fx(x, b):
"""
r"""
Returns the value of the expression :math:`\log_b(x)` where
:py:obj:`x` is secret shared. It uses :py:func:`log2_fx` to
calculate the expression :math:`\log_b(2) \cdot \log_2(x)`.
@@ -859,7 +859,7 @@ def atan(x):
def asin(x):
"""
r"""
Returns the arcsine (sfix) of any given fractional value.
:param x: fractional input (sfix). valid interval is :math:`-1 \le x \le 1`
@@ -875,7 +875,7 @@ def asin(x):
def acos(x):
"""
r"""
Returns the arccosine (sfix) of any given fractional value.
:param x: fractional input (sfix). :math:`-1 \le x \le 1`
@@ -887,7 +887,7 @@ def acos(x):
def tanh(x):
"""
r"""
Hyperbolic tangent. For efficiency, accuracy is diminished
around :math:`\pm \log(k - f - 2) / 2` where :math:`k` and
:math:`f` denote the fixed-point parameters.

View File

@@ -9,6 +9,11 @@ secret index::
i = sint.get_input_from(0)
a[i] = sint.get_input_from(1)
`The introductory book by Evans et
al. <https://securecomputation.org>`_ contains `a chapter dedicated to
oblivious RAM
<https://securecomputation.org/docs/ch5-obliviousdata.pdf>`_.
"""
import random
@@ -41,6 +46,7 @@ debug_online = False
crash_on_overflow = False
use_insecure_randomness = False
debug_ram_size = False
single_thread = False
def maybe_start_timer(n):
if detailed_timing:
@@ -844,7 +850,7 @@ class TrivialORAM(RefTrivialORAM, AbstractORAM):
start_timer()
def get_n_threads(n_loops):
if n_threads is None:
if n_threads is None and not single_thread:
if n_loops > 2048:
return 8
else:
@@ -1038,7 +1044,7 @@ class LocalIndexStructure(List):
__getitem__ = lambda self,index: List.__getitem__(self, index)[0]
def get_n_threads_for_tree(size):
if n_threads_for_tree is None:
if n_threads_for_tree is None and not single_thread:
if size >= 2**13:
return 8
else:

View File

@@ -1,4 +1,4 @@
"""This module contains an implementation of the "Path Oblivious Heap"
r"""This module contains an implementation of the "Path Oblivious Heap"
oblivious priority queue as proposed by
`Shi <https://eprint.iacr.org/2019/274.pdf>`_.

View File

@@ -260,7 +260,7 @@ class Program(object):
os.mkdir(dirname)
# create extra directories if needed
for dirname in ["Public-Input", "Bytecode", "Schedules"]:
for dirname in ["Public-Input", "Bytecode", "Schedules", "Functions"]:
if not os.path.exists(self.programs_dir + "/" + dirname):
os.mkdir(self.programs_dir + "/" + dirname)
@@ -859,6 +859,7 @@ class Tape:
self.warned_about_mem = False
self.return_values = []
self.ran_threads = False
self.unused_decorators = {}
class BasicBlock(object):
def __init__(self, parent, name, scope, exit_condition=None,
@@ -1054,6 +1055,10 @@ class Tape:
print()
raise CompilerError("Unclosed if/else blocks, see tracebacks above")
if self.unused_decorators:
raise CompilerError("Unused branching decorators, make sure to write " + ",".join(
"'@%s' instead of '%s'" % (x, x) for x in set(self.unused_decorators.values())))
if self.program.verbose:
print(
"Processing tape", self.name, "with %d blocks" % len(self.basicblocks)
@@ -1561,10 +1566,7 @@ class Tape:
def __bool__(self):
raise CompilerError(
"Cannot derive truth value from register. "
"This is a catch-all error appearing if you try to use a "
"run-time value where the compiler expects a compile-time "
"value, most likely a Python integer. "
"In some cases, you can fix this by using 'compile.py -l'."
"See https://mp-spdz.readthedocs.io/en/latest/troubleshooting.html#cannot-derive-truth-value-from-register"
)
def __int__(self):
@@ -1599,6 +1601,7 @@ class Tape:
"caller",
"can_eliminate",
"duplicates",
"dup_count",
"block",
]
maximum_size = 2 ** (64 - inst_base.Instruction.code_length) - 1
@@ -1631,6 +1634,7 @@ class Tape:
self.vector = []
self.can_eliminate = True
self.duplicates = util.set_by_id([self])
self.dup_count = None
if Program.prog.DEBUG:
self.caller = [frame[1:] for frame in inspect.stack()[1:]]
else:

View File

@@ -11,7 +11,7 @@ def dest_comp(B):
return sum(Tt) - 1
def reveal_sort(k, D, reverse=False):
""" Sort in place according to "perfect" key. The name hints at the fact
r""" Sort in place according to "perfect" key. The name hints at the fact
that a random order of the keys is revealed.
:param k: vector or Array of sint containing exactly :math:`0,\dots,n-1`

View File

@@ -428,7 +428,7 @@ class _int(Tape._no_truth):
:return: type depends on inputs (secret if any of them is) """
if util.is_constant(other):
if other:
return self
return 1
else:
return 0
return self + other - self * other
@@ -502,14 +502,14 @@ class _bit(Tape._no_truth):
return a ^ prod, b ^ prod
class _gf2n(_bit):
""" :math:`\mathrm{GF}(2^n)` functionality. """
r""" :math:`\mathrm{GF}(2^n)` functionality. """
def if_else(self, a, b):
""" MUX in :math:`\mathrm{GF}(2^n)` circuits. Similar to :py:meth:`_int.if_else`. """
r""" MUX in :math:`\mathrm{GF}(2^n)` circuits. Similar to :py:meth:`_int.if_else`. """
return b ^ self * self.hard_conv(a ^ b)
def cond_swap(self, a, b, t=None):
""" Swapping in :math:`\mathrm{GF}(2^n)`. Similar to :py:meth:`_int.if_else`. """
r""" Swapping in :math:`\mathrm{GF}(2^n)`. Similar to :py:meth:`_int.if_else`. """
prod = self * self.hard_conv(a ^ b)
res = a ^ prod, b ^ prod
if t is None:
@@ -518,7 +518,7 @@ class _gf2n(_bit):
return tuple(t.conv(r) for r in res)
def bit_xor(self, other):
""" XOR in :math:`\mathrm{GF}(2^n)` circuits.
r""" XOR in :math:`\mathrm{GF}(2^n)` circuits.
:param self/other: 0 or 1 (any compatible type)
:rtype: depending on inputs (secret if any of them is) """
@@ -583,6 +583,14 @@ class _structure(Tape._no_truth):
def size_for_mem(self):
return self.size
@classmethod
def arg_type(cls):
if issubclass(cls, _register):
return cls.reg_type
if issubclass(cls, (cfix, sfix)):
return cls.int_type.reg_type
raise CompilerError('type not supported as argument: %s' % cls)
class _secret_structure(_structure):
@classmethod
def input_tensor_from(cls, player, shape):
@@ -1362,7 +1370,7 @@ class cint(_clear, _int):
class cgf2n(_clear, _gf2n):
"""
r"""
Clear :math:`\mathrm{GF}(2^n)` value. n is chosen at runtime. A
number operators are supported (``+, -, *, /, **, ^, &, |, ~, ==,
!=, <<, >>``), returning either :py:class:`cgf2n` if the other
@@ -1381,7 +1389,7 @@ class cgf2n(_clear, _gf2n):
@classmethod
def bit_compose(cls, bits, step=None):
""" Clear :math:`\mathrm{GF}(2^n)` bit composition.
r""" Clear :math:`\mathrm{GF}(2^n)` bit composition.
:param bits: list of cgf2n
:param step: set every :py:obj:`step`-th bit in output (defaults to 1) """
@@ -1478,7 +1486,7 @@ class cgf2n(_clear, _gf2n):
@vectorize
def bit_decompose(self, bit_length=None, step=None):
""" Clear bit decomposition.
r""" Clear bit decomposition.
:param bit_length: number of bits (defaults to global :math:`\mathrm{GF}(2^n)` bit length)
:param step: extract every :py:obj:`step`-th bit (defaults to 1) """
@@ -2685,19 +2693,23 @@ class sint(_secret, _int):
writesocketshare(client_id, message_type, values[0].size, *values)
@classmethod
def read_from_file(cls, start, n_items):
def read_from_file(cls, start, n_items=1, crash_if_missing=True, size=1):
""" Read shares from
``Persistence/Transactions-P<playerno>.data``. See :ref:`this
section <persistence>` for details on the data format.
:param start: starting position in number of shares from beginning (int/regint/cint)
:param n_items: number of items (int)
:param crash_if_missing: crash if file not found (default)
:param size: vector size (int)
:returns: destination for final position, -1 for eof reached, or -2 for file not found (regint)
:returns: list of shares
"""
shares = [cls(size=1) for i in range(n_items)]
shares = [cls(size=size) for i in range(n_items)]
stop = regint()
readsharesfromfile(regint.conv(start), stop, *shares)
if crash_if_missing:
library.runtime_error_if(stop == -2, 'Persistence not found')
return stop, shares
@staticmethod
@@ -2710,9 +2722,11 @@ class sint(_secret, _int):
:param position: start position (int/regint/cint),
defaults to end of file
"""
if isinstance(shares, sint):
shares = [shares]
for share in shares:
assert isinstance(share, sint)
assert share.size == 1
assert share.size == shares[0].size
if position is None:
position = -1
writesharestofile(regint.conv(position), *shares)
@@ -3246,7 +3260,7 @@ class sintbit(sint):
__ror__ = __or__
class sgf2n(_secret, _gf2n):
"""
r"""
Secret :math:`\mathrm{GF}(2^n)` value. n is chosen at runtime. A
number operators are supported (``+, -, *, /, **, ^, ~, ==, !=,
<<``), :py:class:`sgf2n`. Operators generally work with
@@ -3271,7 +3285,7 @@ class sgf2n(_secret, _gf2n):
return res
def add(self, other):
""" Secret :math:`\mathrm{GF}(2^n)` addition (XOR).
r""" Secret :math:`\mathrm{GF}(2^n)` addition (XOR).
:param other: sg2fn/cgf2n/regint/int """
if isinstance(other, sgf2nint):
@@ -3280,7 +3294,7 @@ class sgf2n(_secret, _gf2n):
return super(sgf2n, self).add(other)
def mul(self, other):
""" Secret :math:`\mathrm{GF}(2^n)` multiplication.
r""" Secret :math:`\mathrm{GF}(2^n)` multiplication.
:param other: sg2fn/cgf2n/regint/int """
if isinstance(other, (sgf2nint)):
@@ -3349,7 +3363,7 @@ class sgf2n(_secret, _gf2n):
@vectorize
def right_shift(self, other, bit_length=None):
""" Secret right shift by public value:
r""" Secret right shift by public value:
:param other: compile-time (int)
:param bit_length: number of bits of :py:obj:`self` (defaults to :math:`\mathrm{GF}(2^n)` bit length) """
@@ -4458,6 +4472,7 @@ class _single(_number, _secret_structure):
:param start: starting position in number of shares from beginning
(int/regint/cint)
:param n_items: number of items (int)
:param crash_if_missing: crash if file not found (default)
:returns: destination for final position, -1 for eof reached,
or -2 for file not found (regint)
:returns: list of shares
@@ -4980,11 +4995,21 @@ class sfix(_fix):
return cfix._new(cint.conv(v, size=size), k, f)
def dot(self, other):
""" Dot product with :py:class:`sint`. """
""" Dot product with any vector or iterable. """
if isinstance(other, sint):
return self._new(sint.dot_product(self.v, other), k=self.k, f=self.f)
elif isinstance(other, sfix):
assert self.k == other.k
assert self.f == other.f
return self._new(sint.dot_product(self.v, other.v).round(
self.k + other.f, self.f, nearest=self.round_nearest,
signed=True), k=self.k, f=self.f)
elif isinstance(other, (_int, cfix)):
return (self * other).sum()
else:
raise NotImplementedError()
other = list(other)
assert len(self) == len(other)
return sum(a * b for a, b in zip(self, other))
def reveal_to(self, player):
""" Reveal secret value to :py:obj:`player`.
@@ -5280,7 +5305,7 @@ class squant_params(object):
return squant._new(shifted, params=self)
class sfloat(_number, _secret_structure):
"""
r"""
Secret floating-point number.
Represents :math:`(1 - 2s) \cdot (1 - z)\cdot v \cdot 2^p`.
@@ -5769,6 +5794,23 @@ def _get_type(t):
return t
class _vectorizable:
@classmethod
def check(cls, index, length, sizes):
if isinstance(index, _clear):
index = regint.conv(index)
if length is not None:
from .GC.types import cbits
if isinstance(index, int):
index += length * (index < 0)
if index >= length or index < 0:
raise IndexError('index %s, length %s' % \
(str(index), str(length)))
elif cls.check_indices and not isinstance(index, cbits):
library.runtime_error_if(
(index >= length).bit_or(index < 0),
'overflow: %s/%s', index, sizes)
return index
def reveal_to_clients(self, clients):
""" Reveal contents to list of clients.
@@ -5807,11 +5849,11 @@ class Array(_vectorizable):
@classmethod
def create_from(cls, l):
""" Convert Python iterator or vector to array. Basic type will be taken
from first element, further elements must to be convertible to
that.
""" Convert Python iterator or vector to array or copy another array.
Basic type will be taken from first element, further elements
must to be convertible to that.
:param l: Python iterable or register vector
:param l: Python iterable, register vector, or array
:returns: :py:class:`Array` of appropriate type containing the contents
of :py:obj:`l`
@@ -5871,19 +5913,7 @@ class Array(_vectorizable):
if isinstance(index, (_secret, _single)):
raise CompilerError('need cleartext index')
key = str(index), size or 1
if isinstance(index, _clear):
index = regint.conv(index)
if self.length is not None:
from .GC.types import cbits
if isinstance(index, int):
index += self.length * (index < 0)
if index >= self.length or index < 0:
raise IndexError('index %s, length %s' % \
(str(index), str(self.length)))
elif self.check_indices and not isinstance(index, cbits):
library.runtime_error_if(
(index >= self.length).bit_or(index < 0),
'overflow: %s/%s', index, self.length)
index = self.check(index, self.length, self.length)
if (program.curr_block, key) not in self.address_cache:
n = self.value_type.n_elements()
length = self.length
@@ -6178,13 +6208,14 @@ class Array(_vectorizable):
def _(i):
self[i] = input_from(player, **kwargs)
def read_from_file(self, start):
def read_from_file(self, start, *args, **kwargs):
""" Read content from ``Persistence/Transactions-P<playerno>.data``.
Precision must be the same as when storing if applicable. See
:ref:`this section <persistence>` for details on the data format.
:param start: starting position in number of shares from beginning
(int/regint/cint)
:param crash_if_missing: crash if file not found (default)
:returns: destination for final position, -1 for eof reached,
or -2 for file not found (regint)
"""
@@ -6192,8 +6223,9 @@ class Array(_vectorizable):
res = MemValue(0)
@library.multithread(None, len(self), max_size=program.budget)
def _(base, size):
stop, shares = self.value_type.read_from_file(start, size)
self.assign(shares, base=base)
stop, shares = self.value_type.read_from_file(
start, *args, size=size, **kwargs)
self.assign(shares[0], base=base)
start.iadd(size)
res.write(stop)
return res
@@ -6402,7 +6434,7 @@ class Array(_vectorizable):
return personal(player, self.create_from(self[:].reveal_to(player)._v))
def sort(self, n_threads=None, batcher=False, n_bits=None):
"""
r"""
Sort in place using `radix sort
<https://eprint.iacr.org/2014/121>`_ with complexity
:math:`O(n \log n)` for :py:class:`sint` and :py:class:`sfix`,
@@ -6495,13 +6527,7 @@ class SubMultiArray(_vectorizable):
key = program.curr_tape, tuple(
(x, x.has_else) for x in program.curr_tape.if_states), str(index)
if key not in self.sub_cache:
if util.is_constant(index) and \
(index >= self.sizes[0] or index < 0):
raise CompilerError('index out of range')
elif self.check_indices:
library.runtime_error_if(index >= self.sizes[0],
'overflow: %s/%s',
index, self.sizes)
index = self.check(index, self.sizes[0], self.sizes)
if len(self.sizes) == 2:
self.sub_cache[key] = \
Array(self.sizes[1], self.value_type, \
@@ -6769,20 +6795,21 @@ class SubMultiArray(_vectorizable):
my_pos = position + i * self[i].total_size()
self[i].write_to_file(my_pos)
def read_from_file(self, start):
def read_from_file(self, start, *args, **kwargs):
""" Read content from ``Persistence/Transactions-P<playerno>.data``.
Precision must be the same as when storing if applicable. See
:ref:`this section <persistence>` for details on the data format.
:param start: starting position in number of shares from beginning
(int/regint/cint)
:param crash_if_missing: crash if file not found (default)
:returns: destination for final position, -1 for eof reached,
or -2 for file not found (regint)
"""
start = MemValue(start)
@library.for_range(len(self))
def _(i):
start.write(self[i].read_from_file(start))
start.write(self[i].read_from_file(start, *args, **kwargs))
return start
def write_to_socket(self, socket, debug=False):

View File

@@ -292,6 +292,9 @@ class dict_by_id(object):
def __iter__(self):
return self.keys()
def pop(self, key):
return self.content.pop(id(key), None)
class defaultdict_by_id(dict_by_id):
def __init__(self, default):
dict_by_id.__init__(self)

View File

@@ -10,10 +10,12 @@
#include "Math/gfp.h"
#include "ECDSA/P256Element.h"
#include "GC/VectorInput.h"
#include "Protocols/SPDZ.h"
#include "ECDSA/preprocessing.hpp"
#include "ECDSA/sign.hpp"
#include "Protocols/Beaver.hpp"
#include "Protocols/Hemi.hpp"
#include "Protocols/fake-stuff.hpp"
#include "Protocols/Share.hpp"
#include "Protocols/MAC_Check.hpp"

View File

@@ -32,7 +32,7 @@
#include "GC/RepPrep.hpp"
#include "GC/ThreadMaster.hpp"
#include "GC/Secret.hpp"
#include "Machines/ShamirMachine.hpp"
#include "Machines/Shamir.hpp"
#include "Machines/MalRep.hpp"
#include "Machines/Rep.hpp"

View File

@@ -8,6 +8,7 @@
#include "Math/gfp.h"
#include "ECDSA/P256Element.h"
#include "Protocols/SemiShare.h"
#include "Protocols/SPDZ.h"
#include "Processor/BaseMachine.h"
#include "ECDSA/preprocessing.hpp"
@@ -15,6 +16,7 @@
#include "Protocols/Beaver.hpp"
#include "Protocols/fake-stuff.hpp"
#include "Protocols/MascotPrep.hpp"
#include "Protocols/Hemi.hpp"
#include "Processor/Processor.hpp"
#include "Processor/Data_Files.hpp"
#include "Processor/Input.hpp"

View File

@@ -6,6 +6,7 @@
#include "GC/SemiSecret.h"
#include "GC/SemiPrep.h"
#include "Protocols/Hemi.hpp"
#include "Protocols/SemiMC.hpp"
#include "Protocols/SemiPrep.hpp"
#include "Protocols/SemiInput.hpp"

View File

@@ -17,11 +17,10 @@
* - share of winning unique id * random value [w]
* winning unique id is valid if ∑ [y] * ∑ [r] = ∑ [w]
*
* To run with 2 parties / SPDZ engines:
* ./Scripts/setup-online.sh to create triple shares for each party (spdz engine).
* To run:
* ./Scripts/setup-clients.sh to create SSL keys and certificates for clients
* ./compile.py bankers_bonus
* ./Scripts/run-online.sh bankers_bonus to run the engines.
* ./Scripts/compile-run.py <protocol> bankers_bonus to compile and run the engines.
* (See https://github.com/data61/MP-SPDZ/?tab=readme-ov-file#protocols for options.)
*
* ./bankers-bonus-client.x 0 2 100 0
* ./bankers-bonus-client.x 1 2 200 0

View File

@@ -16,14 +16,14 @@ template<class T>
class AddableVector: public vector<T>
{
public:
AddableVector<T>() {}
AddableVector<T>(size_t n, const T& x = T()) : vector<T>(n, x) {}
AddableVector() {}
AddableVector(size_t n, const T& x = T()) : vector<T>(n, x) {}
template <class U, class FD, class S>
AddableVector<T>(const Plaintext<U,FD,S>& other) :
AddableVector<T>(other.get_poly()) {}
AddableVector(const Plaintext<U,FD,S>& other) :
AddableVector(other.get_poly()) {}
template <class U>
AddableVector<T>(const vector<U>& other)
AddableVector(const vector<U>& other)
{
this->assign(other.begin(), other.end());
}
@@ -129,29 +129,41 @@ public:
(*this)[i].pack(os);
}
void unpack_size(octetStream& os, const T& init = T())
size_t unpack_size(octetStream& os)
{
unsigned int size;
os.get(size);
this->resize(size, init);
this->reserve(size);
return size;
}
void unpack(octetStream& os, const T& init = T())
{
unpack_size(os, init);
for (unsigned int i = 0; i < this->size(); i++)
(*this)[i].unpack(os);
size_t new_size = unpack_size(os);
this->clear();
for (unsigned int i = 0; i < new_size; i++)
{
this->push_back(init);
this->back().unpack(os);
}
}
void add(octetStream& os, T& tmp)
{
unpack_size(os, tmp);
size_t new_size = unpack_size(os);
T init = tmp;
T& item = tmp;
for (unsigned int i = 0; i < this->size(); i++)
{
item.unpack(os);
(*this)[i] += item;
}
for (size_t i = this->size(); i < new_size; i++)
{
item.unpack(os);
this->push_back(init);
this->back() += item;
}
}
T infinity_norm() const

View File

@@ -61,9 +61,7 @@ bigint FHE_Params::Q() const
void FHE_Params::pack(octetStream& o) const
{
o.store(FFTData.size());
for(auto& fd: FFTData)
fd.pack(o);
o.store(FFTData);
Chi.pack(o);
Bval.pack(o);
o.store(sec_p);
@@ -73,11 +71,7 @@ void FHE_Params::pack(octetStream& o) const
void FHE_Params::unpack(octetStream& o)
{
size_t size;
o.get(size);
FFTData.resize(size);
for (auto& fd : FFTData)
fd.unpack(o);
o.get(FFTData);
Chi.unpack(o);
Bval.unpack(o);
o.get(sec_p);

View File

@@ -311,22 +311,18 @@ void imatrix::hash(octetStream& o) const
void imatrix::pack(octetStream& o) const
{
o.store(size());
for (auto& x : *this)
{
assert(x.size() == size());
x.pack(o);
}
o.store(static_cast<const super&>(*this));
}
void imatrix::unpack(octetStream& o)
{
size_t size;
o.get(size);
resize(size);
o.get(static_cast<super&>(*this));
for (auto& x : *this)
{
x.resize(size);
x.unpack(o);
assert(x.size() == size());
}
}

View File

@@ -13,6 +13,8 @@ typedef vector< vector<bigint> > matrix;
class imatrix : public vector< BitVector >
{
typedef vector<BitVector> super;
public:
bool operator!=(const imatrix& other) const;

View File

@@ -13,6 +13,8 @@
#include "FHEOffline/Proof.h"
#include "Processor/OnlineOptions.h"
#include <fstream>
using namespace std;
@@ -735,9 +737,9 @@ void load_or_generate(P2Data& P2D, const Ring& R)
{
P2D.load(R);
}
catch (...)
catch (exception& e)
{
cout << "Loading failed" << endl;
cerr << "Loading parameters failed, generating (" << e.what() << ")" << endl;
init(P2D,R);
P2D.store(R);
}

View File

@@ -2,6 +2,7 @@
#include "FHE/P2Data.h"
#include "Math/Setup.h"
#include "Math/fixint.h"
#include "Processor/OnlineOptions.h"
#include <fstream>
@@ -74,7 +75,6 @@ bool P2Data::operator!=(const P2Data& other) const
void P2Data::hash(octetStream& o) const
{
check_dimensions();
o.store(gf2n_short::degree());
o.store(slots);
A.hash(o);
@@ -113,17 +113,18 @@ string get_filename(const Ring& Rg)
void P2Data::load(const Ring& Rg)
{
string filename = get_filename(Rg);
cout << "Loading from " << filename << endl;
ifstream s(filename);
if (OnlineOptions::singleton.verbose)
cerr << "Loading from " << filename << endl;
octetStream os;
os.input(s);
os.input(filename);
unpack(os);
}
void P2Data::store(const Ring& Rg) const
{
string filename = get_filename(Rg);
cout << "Storing in " << filename << endl;
if (OnlineOptions::singleton.verbose)
cerr << "Storing in " << filename << endl;
ofstream s(filename);
octetStream os;
pack(os);

View File

@@ -562,22 +562,17 @@ template <class T,class FD,class S>
void Plaintext<T,FD,S>::pack(octetStream& o) const
{
to_poly();
o.store((unsigned int)b.size());
for (unsigned int i = 0; i < b.size(); i++)
o.store(b[i]);
o.store(b);
}
template <class T,class FD,class S>
void Plaintext<T,FD,S>::unpack(octetStream& o)
{
type = Polynomial;
unsigned int size;
o.get(size);
allocate();
o.get(b);
auto size = b.size();
allocate(Polynomial);
if (size != b.size() and size != 0)
throw length_error("unexpected length received");
for (unsigned int i = 0; i < size; i++)
b[i] = o.get<S>();
}

View File

@@ -512,9 +512,7 @@ modp Ring_Element::get_constant() const
void store(octetStream& o,const vector<modp>& v,const Zp_Data& ZpD)
{
ZpD.pack(o);
o.store((int)v.size());
for (unsigned int i=0; i<v.size(); i++)
{ v[i].pack(o,ZpD); }
o.store(v);
}
@@ -526,16 +524,7 @@ void get(octetStream& o,vector<modp>& v,const Zp_Data& ZpD)
throw runtime_error(
"mismatch: " + to_string(check_Zpd.pr_bit_length) + "/"
+ to_string(ZpD.pr_bit_length));
unsigned int length;
o.get(length);
v.clear();
v.reserve(length);
modp tmp;
for (unsigned int i=0; i<length; i++)
{
tmp.unpack(o,ZpD);
v.push_back(tmp);
}
o.get(v);
}

View File

@@ -1,5 +1,5 @@
#ifndef _Subroutines
#define _Subroutines
#ifndef FHE_SUBROUTINES_H_
#define FHE_SUBROUTINES_H_
#include "Math/Zp_Data.h"

View File

@@ -27,8 +27,7 @@ void read_or_generate_secrets(T& setup, Player& P, U& machine,
try
{
ifstream input(filename);
os.input(input);
os.input(filename);
setup.unpack(os);
machine.unpack(os);
}
@@ -44,11 +43,15 @@ void read_or_generate_secrets(T& setup, Player& P, U& machine,
}
catch (mismatch_among_parties& e)
{
error = e.what();
if (error.empty())
error = e.what();
}
if (not error.empty())
{
if (OnlineOptions::singleton.has_option("expect_setup"))
throw runtime_error("error in setup: " + error);
cerr << "Running secrets generation because no suitable material "
"from a previous run was found (" << error << ")" << endl;
setup.key_and_mac_generation(P, machine, num_runs, V());

View File

@@ -80,9 +80,8 @@ void secure_init(T& setup, Player& P, U& machine,
try
{
ifstream file(filename);
octetStream os;
os.input(file);
os.input(filename);
os.get(machine.extra_slack);
setup.unpack(os);
}
@@ -95,13 +94,17 @@ void secure_init(T& setup, Player& P, U& machine,
{
setup.check(P, machine);
}
catch (exception& e)
catch (mismatch_among_parties& e)
{
reason = e.what();
if (reason.empty())
reason = e.what();
}
if (not reason.empty())
{
if (OnlineOptions::singleton.has_option("expect_setup"))
throw runtime_error("error in setup: " + reason);
if (OnlineOptions::singleton.verbose)
cerr << "Generating parameters for security " << sec
<< " and field size ~2^" << plaintext_length

View File

@@ -82,9 +82,23 @@ void Instruction::parse(istream& s, int pos)
#undef X
default:
ostringstream os;
os << "Code not defined for instruction " << showbase << hex << opcode << dec << endl;
os << "This virtual machine executes binary circuits only." << endl;
os << "Use 'compile.py -B'.";
os << "Code not defined for instruction ";
bool known = true;
switch (opcode)
{
#define X(NAME, PRE, CODE) case NAME: os << #NAME; break;
ALL_INSTRUCTIONS
#undef X
default:
known = false;
os << showbase << hex << opcode << dec;
}
os << endl;
if (known)
{
os << "This virtual machine executes binary circuits only. ";
os << "Use 'compile.py -B'.";
}
exit_error(os.str());
break;
}

View File

@@ -62,6 +62,7 @@ public:
typedef MaliciousRepMC<U> MC;
typedef MC MAC_Check;
typedef HashMaliciousRepMC<U> DefaultMC;
typedef ReplicatedInput<U> Input;
typedef RepPrep<U> LivePrep;

View File

@@ -71,9 +71,9 @@ void Program::parse(istream& s)
CALLGRIND_STOP_INSTRUMENTATION;
while (!s.eof())
{
instr.parse(s, pos);
if (s.bad() or s.fail())
throw runtime_error("error reading program");
instr.parse(s, pos);
p.push_back(instr);
//cerr << "\t" << instr << endl;
s.peek();

View File

@@ -65,6 +65,8 @@ public:
typedef typename T::out_type out_type;
typedef void DefaultMC;
static string type_string() { return "evaluation secret"; }
static string phase_name() { return T::name(); }
@@ -179,6 +181,7 @@ public:
void finalize_input(U& inputter, int from, int n_bits);
int size() const { return registers.size(); }
size_t maximum_size() const { return registers.size(); }
RegVector& get_regs() { return registers; }
const RegVector& get_regs() const { return registers; }

View File

@@ -17,7 +17,8 @@ namespace GC
void Semi::prepare_mult(const SemiSecret& x, const SemiSecret& y, int n,
bool repeat)
{
if (repeat and OnlineOptions::singleton.live_prep and (n < 0 or n > 1))
if (repeat and OnlineOptions::singleton.live_prep and (n < 0 or n > 1)
and P.num_players() == 2)
{
this->triples.push_back({{}});
auto& triple = this->triples.back();

View File

@@ -51,6 +51,11 @@ public:
static void trans(Processor<T>& processor, int n_outputs,
const vector<int>& args);
static size_t maximum_size()
{
return default_length;
}
SemiSecretBase()
{
}

View File

@@ -3,6 +3,9 @@
*
*/
#ifndef GC_SEMISECRET_HPP_
#define GC_SEMISECRET_HPP_
#include "GC/ShareParty.h"
#include "GC/ShareSecret.hpp"
#include "Protocols/MAC_Check_Base.hpp"
@@ -161,3 +164,5 @@ void SemiSecretBase<T, V>::reveal(size_t n_bits, Clear& x)
}
} /* namespace GC */
#endif

View File

@@ -42,7 +42,7 @@ inline ShareParty<T>& ShareParty<T>::s()
if (singleton)
return *singleton;
else
throw runtime_error("no singleton");
throw runtime_error("no ShareParty singleton");
}
}

View File

@@ -125,6 +125,8 @@ public:
typedef NoShare bit_type;
typedef void DefaultMC;
static const int N_BITS = clear::N_BITS;
static const bool dishonest_majority = false;
@@ -166,6 +168,11 @@ public:
return T::fake_opts();
}
static size_t maximum_size()
{
return default_length;
}
RepSecretBase()
{
}
@@ -203,7 +210,7 @@ public:
typedef ReplicatedBase Protocol;
static ReplicatedSecret constant(const typename super::clear& value,
int my_num, typename super::mac_key_type, int = -1)
int my_num, typename super::mac_key_type = {}, int = -1)
{
ReplicatedSecret res;
if (my_num < 2)

View File

@@ -67,7 +67,7 @@ inline ShareThread<T>& ShareThread<T>::s()
if (singleton and T::is_real)
return *singleton;
else
throw runtime_error("no singleton");
throw runtime_error("no ShareThread singleton");
}
} /* namespace GC */

View File

@@ -144,6 +144,9 @@ void ShareThread<T>::and_(Processor<T>& processor,
res.mask(res, n);
}
}
if (OnlineOptions::singleton.has_option("always_check"))
protocol->check();
}
template<class T>
@@ -195,6 +198,9 @@ void ShareThread<T>::andrsvec(Processor<T>& processor, const vector<int>& args)
}
it += 2 * n_args + 1;
}
if (OnlineOptions::singleton.has_option("always_check"))
protocol->check();
}
template<class T>

View File

@@ -48,6 +48,7 @@ public:
Thread(int thread_num, ThreadMaster<T>& master);
virtual ~Thread();
void start();
void run();
virtual void pre_run() {}
virtual void run(Program& program);

View File

@@ -31,7 +31,12 @@ template<class T>
Thread<T>::Thread(int thread_num, ThreadMaster<T>& master) :
master(master), machine(master.machine), processor(machine),
N(master.N), P(0),
thread_num(thread_num)
thread_num(thread_num), thread(0)
{
}
template<class T>
void Thread<T>::start()
{
pthread_create(&thread, 0, run_thread, this);
}

View File

@@ -60,6 +60,7 @@ public:
virtual Thread<T>* new_thread(int i);
void run();
void run_with_error();
virtual void post_run() {}
};

View File

@@ -59,6 +59,25 @@ Thread<T>* ThreadMaster<T>::new_thread(int i)
template<class T>
void ThreadMaster<T>::run()
{
if (opts.has_option("throw_exceptions"))
run_with_error();
else
{
try
{
run_with_error();
}
catch (exception& e)
{
cerr << "Fatal error: " << e.what() << endl;
exit(1);
}
}
}
template<class T>
void ThreadMaster<T>::run_with_error()
{
if (not opts.live_prep)
{
@@ -72,6 +91,9 @@ void ThreadMaster<T>::run()
for (int i = 0; i < machine.nthreads; i++)
threads.push_back(new_thread(i));
// must start after constructor due to virtual functions
for (auto thread : threads)
thread->start();
for (auto thread : threads)
thread->join_tape();

View File

@@ -50,7 +50,7 @@ public:
return *part_MC;
}
void init_open(const Player& P, int n)
void init_open(const Player& P, int n = 0)
{
part_MC->init_open(P);
sizes.clear();

View File

@@ -10,7 +10,8 @@
#include "Protocols/AtlasPrep.h"
#include "GC/AtlasSecret.h"
#include "ShamirMachine.hpp"
#include "Protocols/Atlas.hpp"
#include "Shamir.hpp"
#endif /* MACHINES_ATLAS_HPP_ */

View File

@@ -4,7 +4,7 @@
*/
#include "BMR/RealProgramParty.hpp"
#include "Machines/ShamirMachine.hpp"
#include "Machines/Shamir.hpp"
#include "Math/Z2k.hpp"
#include "Machines/MalRep.hpp"

View File

@@ -4,7 +4,7 @@
*/
#include "BMR/RealProgramParty.hpp"
#include "Machines/ShamirMachine.hpp"
#include "Machines/Shamir.hpp"
#include "Math/Z2k.hpp"
int main(int argc, const char** argv)

View File

@@ -5,3 +5,5 @@
#include "Math/gfp.hpp"
template class FieldMachine<Share, Share, DishonestMajorityMachine>;
template class Machine<Share<gfp_<0, 2>>, Share<gf2n>>;

View File

@@ -6,6 +6,9 @@
#ifndef MACHINES_SPDZ_HPP_
#define MACHINES_SPDZ_HPP_
#include "Protocols/MAC_Check.h"
#include "Protocols/SPDZ.h"
#include "Processor/Data_Files.hpp"
#include "Processor/Instruction.hpp"
#include "Processor/Machine.hpp"

50
Machines/Shamir.hpp Normal file
View File

@@ -0,0 +1,50 @@
/*
* ShamirMachine.cpp
*
*/
#ifndef MACHINE_SHAMIR_HPP_
#define MACHINE_SHAMIR_HPP_
#include "Protocols/ShamirOptions.h"
#include "Protocols/ShamirShare.h"
#include "Protocols/MaliciousShamirShare.h"
#include "Math/gfp.h"
#include "Math/gf2n.h"
#include "GC/VectorProtocol.h"
#include "GC/CcdPrep.h"
#include "GC/TinyMC.h"
#include "GC/MaliciousCcdSecret.h"
#include "GC/VectorInput.h"
#include "Processor/FieldMachine.hpp"
#include "Processor/Data_Files.hpp"
#include "Processor/Instruction.hpp"
#include "Processor/Machine.hpp"
#include "Protocols/ShamirInput.hpp"
#include "Protocols/Shamir.hpp"
#include "Protocols/ShamirMC.hpp"
#include "Protocols/MaliciousShamirMC.hpp"
#include "Protocols/MaliciousShamirPO.hpp"
#include "Protocols/MAC_Check_Base.hpp"
#include "Protocols/Beaver.hpp"
#include "Protocols/Spdz2kPrep.hpp"
#include "Protocols/ReplicatedPrep.hpp"
#include "Protocols/MalRepRingPrep.hpp"
#include "GC/ShareSecret.hpp"
#include "GC/VectorProtocol.hpp"
#include "GC/Secret.hpp"
#include "GC/CcdPrep.hpp"
#include "Math/gfp.hpp"
template<template<class U> class T>
ShamirMachineSpec<T>::ShamirMachineSpec(int argc, const char** argv)
{
auto& opts = ShamirOptions::singleton;
ez::ezOptionParser opt;
opts = {opt, argc, argv};
HonestMajorityFieldMachine<T>(argc, argv, opt, opts.nparties);
}
#endif

View File

@@ -13,7 +13,7 @@
#include "GC/ThreadMaster.hpp"
#include "GC/Secret.hpp"
#include "GC/CcdPrep.hpp"
#include "Machines/ShamirMachine.hpp"
#include "Machines/Shamir.hpp"
int main(int argc, const char** argv)
{

View File

@@ -0,0 +1,8 @@
/*
* export-vm.cpp
*
*/
#include "maximal.hpp"
template class Machine<AtlasShare<gfp_<0, 2>>>;

View File

@@ -0,0 +1,8 @@
/*
* export-vm.cpp
*
*/
#include "maximal.hpp"
template class Machine<CowGearShare<gfp_<0, 2>>>;

View File

@@ -0,0 +1,8 @@
/*
* export-vm.cpp
*
*/
#include "maximal.hpp"
template class Machine<DealerShare<SignedZ2<64>>>;

8
Machines/export-hemi.cpp Normal file
View File

@@ -0,0 +1,8 @@
/*
* export-vm.cpp
*
*/
#include "maximal.hpp"
template class Machine<HemiShare<gfp_<0, 2>>>;

View File

@@ -0,0 +1,8 @@
/*
* export-vm.cpp
*
*/
#include "maximal.hpp"
template class Machine<Rep4Share2<64>>;

8
Machines/export-ring.cpp Normal file
View File

@@ -0,0 +1,8 @@
/*
* export-vm.cpp
*
*/
#include "maximal.hpp"
template class Machine<Rep3Share2<64>>;

View File

@@ -0,0 +1,8 @@
/*
* export-vm.cpp
*
*/
#include "maximal.hpp"
template class Machine<Semi2kShare<64>>;

View File

@@ -0,0 +1,8 @@
/*
* export-vm.cpp
*
*/
#include "maximal.hpp"
template class Machine<SpdzWiseRingShare<64, 40>>;

377
Machines/h-files.h Normal file
View File

@@ -0,0 +1,377 @@
#include "BMR/AndJob.h"
#include "BMR/BooleanCircuit.h"
#include "BMR/common.h"
#include "BMR/CommonParty.h"
#include "BMR/config.h"
#include "BMR/GarbledGate.h"
#include "BMR/Gate.h"
#include "BMR/Key.h"
#include "BMR/msg_types.h"
#include "BMR/Party.h"
#include "BMR/prf.h"
#include "BMR/proto_utils.h"
#include "BMR/RealGarbleWire.h"
#include "BMR/RealProgramParty.h"
#include "BMR/Register.h"
#include "BMR/Register_inline.h"
#include "BMR/SpdzWire.h"
#include "BMR/TrustedParty.h"
#include "BMR/Wire.h"
#include "ECDSA/CurveElement.h"
#include "ECDSA/EcdsaOptions.h"
#include "ECDSA/P256Element.h"
#include "ExternalIO/Client.h"
#include "FHE/AddableVector.h"
#include "FHE/Ciphertext.h"
#include "FHE/Diagonalizer.h"
#include "FHE/DiscreteGauss.h"
#include "FHE/FFT_Data.h"
#include "FHE/FFT.h"
#include "FHE/FHE_Keys.h"
#include "FHE/FHE_Params.h"
#include "FHE/Generator.h"
#include "FHE/Matrix.h"
#include "FHE/NoiseBounds.h"
#include "FHE/NTL-Subs.h"
#include "FHEOffline/config.h"
#include "FHEOffline/CutAndChooseMachine.h"
#include "FHEOffline/DataSetup.h"
#include "FHEOffline/DistDecrypt.h"
#include "FHEOffline/DistKeyGen.h"
#include "FHEOffline/EncCommit.h"
#include "FHEOffline/Multiplier.h"
#include "FHEOffline/PairwiseGenerator.h"
#include "FHEOffline/PairwiseMachine.h"
#include "FHEOffline/PairwiseSetup.h"
#include "FHEOffline/Producer.h"
#include "FHEOffline/Proof.h"
#include "FHEOffline/Prover.h"
#include "FHEOffline/Reshare.h"
#include "FHEOffline/Sacrificing.h"
#include "FHEOffline/SimpleDistDecrypt.h"
#include "FHEOffline/SimpleEncCommit.h"
#include "FHEOffline/SimpleGenerator.h"
#include "FHEOffline/SimpleMachine.h"
#include "FHEOffline/TemiSetup.h"
#include "FHEOffline/Verifier.h"
#include "FHE/P2Data.h"
#include "FHE/Plaintext.h"
#include "FHE/QGroup.h"
#include "FHE/Random_Coins.h"
#include "FHE/Ring_Element.h"
#include "FHE/Ring.h"
#include "FHE/Rq_Element.h"
#include "FHE/Subroutines.h"
#include "FHE/tools.h"
#include "GC/Access.h"
#include "GC/ArgTuples.h"
#include "GC/AtlasSecret.h"
#include "GC/AtlasShare.h"
#include "GC/BitAdder.h"
#include "GC/BitPrepFiles.h"
#include "GC/CcdPrep.h"
#include "GC/CcdSecret.h"
#include "GC/CcdShare.h"
#include "GC/Clear.h"
#include "GC/config.h"
#include "GC/DealerPrep.h"
#include "GC/FakeSecret.h"
#include "GC/Instruction.h"
#include "GC/Instruction_inline.h"
#include "GC/instructions.h"
#include "GC/Machine.h"
#include "GC/MaliciousCcdSecret.h"
#include "GC/MaliciousCcdShare.h"
#include "GC/MaliciousRepSecret.h"
#include "GC/Memory.h"
#include "GC/NoShare.h"
#include "GC/PersonalPrep.h"
#include "GC/PostSacriBin.h"
#include "GC/PostSacriSecret.h"
#include "GC/Processor.h"
#include "GC/Program.h"
#include "GC/Rep4Prep.h"
#include "GC/Rep4Secret.h"
#include "GC/RepPrep.h"
#include "GC/RuntimeBranching.h"
#include "GC/Secret.h"
#include "GC/Secret_inline.h"
#include "GC/Semi.h"
#include "GC/SemiHonestRepPrep.h"
#include "GC/SemiPrep.h"
#include "GC/SemiSecret.h"
#include "GC/ShareParty.h"
#include "GC/ShareSecret.h"
#include "GC/ShareThread.h"
#include "GC/ShiftableTripleBuffer.h"
#include "GC/square64.h"
#include "GC/Thread.h"
#include "GC/ThreadMaster.h"
#include "GC/TinierSecret.h"
#include "GC/TinierShare.h"
#include "GC/TinierSharePrep.h"
#include "GC/TinyMC.h"
#include "GC/TinySecret.h"
#include "GC/TinyShare.h"
#include "GC/VectorInput.h"
#include "GC/VectorProtocol.h"
#include "Machines/OTMachine.h"
#include "Machines/OutputCheck.h"
#include "Math/bigint.h"
#include "Math/Bit.h"
#include "Math/BitVec.h"
#include "Math/config.h"
#include "Math/field_types.h"
#include "Math/FixedVec.h"
#include "Math/fixint.h"
#include "Math/gf2n.h"
#include "Math/gf2nlong.h"
#include "Math/gfp.h"
#include "Math/gfpvar.h"
#include "Math/Integer.h"
#include "Math/modp.h"
#include "Math/mpn_fixed.h"
#include "Math/Setup.h"
#include "Math/Square.h"
#include "Math/ValueInterface.h"
#include "Math/Z2k.h"
#include "Math/Zp_Data.h"
#include "Networking/AllButLastPlayer.h"
#include "Networking/CryptoPlayer.h"
#include "Networking/data.h"
#include "Networking/Exchanger.h"
#include "Networking/PlayerBuffer.h"
#include "Networking/PlayerCtSocket.h"
#include "Networking/Player.h"
#include "Networking/Receiver.h"
#include "Networking/Sender.h"
#include "Networking/Server.h"
#include "Networking/ServerSocket.h"
#include "Networking/sockets.h"
#include "Networking/ssl_sockets.h"
#include "OT/BaseOT.h"
#include "OT/BitDiagonal.h"
#include "OT/BitMatrix.h"
#include "OT/config.h"
#include "OT/MamaRectangle.h"
#include "OT/MascotParams.h"
#include "OT/NPartyTripleGenerator.h"
#include "OT/OTExtension.h"
#include "OT/OTExtensionWithMatrix.h"
#include "OT/OTMultiplier.h"
#include "OT/OTTripleSetup.h"
#include "OT/OTVole.h"
#include "OT/Rectangle.h"
#include "OT/Row.h"
#include "OT/Tools.h"
#include "OT/TripleMachine.h"
#include "Processor/BaseMachine.h"
#include "Processor/Binary_File_IO.h"
#include "Processor/config.h"
#include "Processor/Conv2dTuple.h"
#include "Processor/Data_Files.h"
#include "Processor/DummyProtocol.h"
#include "Processor/EdabitBuffer.h"
#include "Processor/ExternalClients.h"
#include "Processor/FieldMachine.h"
#include "Processor/FixInput.h"
#include "Processor/FloatInput.h"
#include "Processor/FunctionArgument.h"
#include "Processor/HonestMajorityMachine.h"
#include "Processor/Input.h"
#include "Processor/InputTuple.h"
#include "Processor/Instruction.h"
#include "Processor/instructions.h"
#include "Processor/IntInput.h"
#include "Processor/Machine.h"
#include "Processor/Memory.h"
#include "Processor/NoFilePrep.h"
#include "Processor/OfflineMachine.h"
#include "Processor/OnlineMachine.h"
#include "Processor/OnlineOptions.h"
#include "Processor/Online-Thread.h"
#include "Processor/PrepBase.h"
#include "Processor/PrepBuffer.h"
#include "Processor/PrivateOutput.h"
#include "Processor/ProcessorBase.h"
#include "Processor/Processor.h"
#include "Processor/Program.h"
#include "Processor/RingMachine.h"
#include "Processor/RingOptions.h"
#include "Processor/SpecificPrivateOutput.h"
#include "Processor/ThreadJob.h"
#include "Processor/ThreadQueue.h"
#include "Processor/ThreadQueues.h"
#include "Processor/TruncPrTuple.h"
#include "Protocols/Atlas.h"
#include "Protocols/AtlasPrep.h"
#include "Protocols/AtlasShare.h"
#include "Protocols/Beaver.h"
#include "Protocols/BrainPrep.h"
#include "Protocols/BrainShare.h"
#include "Protocols/BufferScope.h"
#include "Protocols/ChaiGearPrep.h"
#include "Protocols/ChaiGearShare.h"
#include "Protocols/config.h"
#include "Protocols/CowGearOptions.h"
#include "Protocols/CowGearPrep.h"
#include "Protocols/CowGearShare.h"
#include "Protocols/dabit.h"
#include "Protocols/DabitSacrifice.h"
#include "Protocols/Dealer.h"
#include "Protocols/DealerInput.h"
#include "Protocols/DealerMatrixPrep.h"
#include "Protocols/DealerMC.h"
#include "Protocols/DealerPrep.h"
#include "Protocols/DealerShare.h"
#include "Protocols/DummyMatrixPrep.h"
#include "Protocols/edabit.h"
#include "Protocols/FakeInput.h"
#include "Protocols/FakeMC.h"
#include "Protocols/FakePrep.h"
#include "Protocols/FakeProtocol.h"
#include "Protocols/FakeShare.h"
#include "Protocols/fake-stuff.h"
#include "Protocols/Hemi.h"
#include "Protocols/HemiMatrixPrep.h"
#include "Protocols/HemiOptions.h"
#include "Protocols/HemiPrep.h"
#include "Protocols/HemiShare.h"
#include "Protocols/HighGearKeyGen.h"
#include "Protocols/HighGearShare.h"
#include "Protocols/LimitedPrep.h"
#include "Protocols/LowGearKeyGen.h"
#include "Protocols/LowGearShare.h"
#include "Protocols/MAC_Check_Base.h"
#include "Protocols/MAC_Check.h"
#include "Protocols/MaliciousRep3Share.h"
#include "Protocols/MaliciousRepMC.h"
#include "Protocols/MaliciousRepPO.h"
#include "Protocols/MaliciousRepPrep.h"
#include "Protocols/MaliciousShamirMC.h"
#include "Protocols/MaliciousShamirPO.h"
#include "Protocols/MaliciousShamirShare.h"
#include "Protocols/MalRepRingOptions.h"
#include "Protocols/MalRepRingPrep.h"
#include "Protocols/MalRepRingShare.h"
#include "Protocols/MamaPrep.h"
#include "Protocols/MamaShare.h"
#include "Protocols/MascotPrep.h"
#include "Protocols/MatrixFile.h"
#include "Protocols/NoLivePrep.h"
#include "Protocols/NoProtocol.h"
#include "Protocols/NoShare.h"
#include "Protocols/Opener.h"
#include "Protocols/PostSacrifice.h"
#include "Protocols/PostSacriRepFieldShare.h"
#include "Protocols/PostSacriRepRingShare.h"
#include "Protocols/ProtocolSet.h"
#include "Protocols/ProtocolSetup.h"
#include "Protocols/Rep3Share2k.h"
#include "Protocols/Rep3Share.h"
#include "Protocols/Rep3Shuffler.h"
#include "Protocols/Rep4.h"
#include "Protocols/Rep4Input.h"
#include "Protocols/Rep4MC.h"
#include "Protocols/Rep4Prep.h"
#include "Protocols/Rep4Share2k.h"
#include "Protocols/Rep4Share.h"
#include "Protocols/Replicated.h"
#include "Protocols/ReplicatedInput.h"
#include "Protocols/ReplicatedMC.h"
#include "Protocols/ReplicatedPO.h"
#include "Protocols/ReplicatedPrep.h"
#include "Protocols/RepRingOnlyEdabitPrep.h"
#include "Protocols/RingOnlyPrep.h"
#include "Protocols/SecureShuffle.h"
#include "Protocols/Semi2kShare.h"
#include "Protocols/Semi.h"
#include "Protocols/SemiInput.h"
#include "Protocols/SemiMC.h"
#include "Protocols/SemiPrep2k.h"
#include "Protocols/SemiPrep.h"
#include "Protocols/SemiRep3Prep.h"
#include "Protocols/SemiShare.h"
#include "Protocols/Shamir.h"
#include "Protocols/ShamirInput.h"
#include "Protocols/ShamirMC.h"
#include "Protocols/ShamirOptions.h"
#include "Protocols/ShamirShare.h"
#include "Protocols/Share.h"
#include "Protocols/ShareInterface.h"
#include "Protocols/ShareMatrix.h"
#include "Protocols/ShareVector.h"
#include "Protocols/ShuffleSacrifice.h"
#include "Protocols/SohoPrep.h"
#include "Protocols/SohoShare.h"
#include "Protocols/SPDZ2k.h"
#include "Protocols/Spdz2kPrep.h"
#include "Protocols/Spdz2kShare.h"
#include "Protocols/SPDZ.h"
#include "Protocols/SpdzWise.h"
#include "Protocols/SpdzWiseInput.h"
#include "Protocols/SpdzWiseMC.h"
#include "Protocols/SpdzWisePrep.h"
#include "Protocols/SpdzWiseRep3Shuffler.h"
#include "Protocols/SpdzWiseRing.h"
#include "Protocols/SpdzWiseRingPrep.h"
#include "Protocols/SpdzWiseRingShare.h"
#include "Protocols/SpdzWiseShare.h"
#include "Protocols/SquarePrep.h"
#include "Protocols/TemiPrep.h"
#include "Protocols/TemiShare.h"
#include "Tools/aes.h"
#include "Tools/avx_memcpy.h"
#include "Tools/benchmarking.h"
#include "Tools/BitVector.h"
#include "Tools/Buffer.h"
#include "Tools/Bundle.h"
#include "Tools/callgrind.h"
#include "Tools/CheckVector.h"
#include "Tools/Commit.h"
#include "Tools/Coordinator.h"
#include "Tools/cpu_support.h"
#include "Tools/DiskVector.h"
#include "Tools/Exceptions.h"
#include "Tools/ExecutionStats.h"
#include "Tools/FixedVector.h"
#include "Tools/FlexBuffer.h"
#include "Tools/Hash.h"
#include "Tools/int.h"
#include "Tools/intrinsics.h"
#include "Tools/Lock.h"
#include "Tools/MemoryUsage.h"
#include "Tools/mkpath.h"
#include "Tools/MMO.h"
#include "Tools/NamedStats.h"
#include "Tools/NetworkOptions.h"
#include "Tools/octetStream.h"
#include "Tools/oct.h"
#include "Tools/OfflineMachineBase.h"
#include "Tools/parse.h"
#include "Tools/PointerVector.h"
#include "Tools/pprint.h"
#include "Tools/random.h"
#include "Tools/Signal.h"
#include "Tools/Subroutines.h"
#include "Tools/SwitchableOutput.h"
#include "Tools/time-func.h"
#include "Tools/TimerWithComm.h"
#include "Tools/WaitQueue.h"
#include "Tools/Waksman.h"
#include "Tools/Worker.h"
#include "Yao/config.h"
#include "Yao/YaoAndJob.h"
#include "Yao/YaoCommon.h"
#include "Yao/YaoEvalInput.h"
#include "Yao/YaoEvalMaster.h"
#include "Yao/YaoEvaluator.h"
#include "Yao/YaoEvalWire.h"
#include "Yao/YaoGarbleInput.h"
#include "Yao/YaoGarbleMaster.h"
#include "Yao/YaoGarbler.h"
#include "Yao/YaoGarbleWire.h"
#include "Yao/YaoGate.h"
#include "Yao/YaoHalfGate.h"
#include "Yao/YaoPlayer.h"
#include "Yao/YaoWire.h"

View File

@@ -3,7 +3,7 @@
*
*/
#include "ShamirMachine.hpp"
#include <Machines/Shamir.hpp>
#include "MalRep.hpp"
#include "Processor/OfflineMachine.hpp"

View File

@@ -13,7 +13,7 @@
#include "GC/ThreadMaster.hpp"
#include "GC/Secret.hpp"
#include "GC/CcdPrep.hpp"
#include "Machines/ShamirMachine.hpp"
#include "Machines/Shamir.hpp"
#include "Machines/MalRep.hpp"
int main(int argc, const char** argv)

View File

@@ -3,11 +3,11 @@
*
*/
#include "Machines/ShamirMachine.h"
#include "Protocols/MaliciousShamirShare.h"
#include "Protocols/ShamirOptions.h"
#include "Machines/MalRep.hpp"
#include "ShamirMachine.hpp"
#include "Shamir.hpp"
int main(int argc, const char** argv)
{

37
Machines/maximal.hpp Normal file
View File

@@ -0,0 +1,37 @@
/*
* maximal.hpp
*
*/
#ifndef MACHINES_MAXIMAL_HPP_
#define MACHINES_MAXIMAL_HPP_
#include "minimal.hpp"
#include "Atlas.hpp"
#include "MalRep.hpp"
#include "Rep4.hpp"
#include "Rep.hpp"
#include "RepRing.hpp"
#include "Semi2k.hpp"
#include "SPDZ2k.hpp"
#include "SPDZ.hpp"
#include "GC/CcdPrep.hpp"
#include "GC/TinierSharePrep.hpp"
#include "GC/TinyPrep.hpp"
#include "Protocols/ChaiGearPrep.hpp"
#include "Protocols/CowGearPrep.hpp"
#include "Protocols/DealerPrep.hpp"
#include "Protocols/DealerInput.hpp"
#include "Protocols/DealerMC.hpp"
#include "Protocols/DealerMatrixPrep.hpp"
#include "Protocols/SpdzWise.hpp"
#include "Protocols/SpdzWiseRing.hpp"
#include "Protocols/SpdzWiseInput.hpp"
#include "Protocols/SpdzWisePrep.hpp"
#include "Protocols/SpdzWiseShare.hpp"
#include "Protocols/SpdzWiseRep3Shuffler.hpp"
#include "Protocols/TemiPrep.hpp"
#endif /* MACHINES_MAXIMAL_HPP_ */

26
Machines/minimal.hpp Normal file
View File

@@ -0,0 +1,26 @@
/*
* minimal.hpp
*
*/
// minimal header file to make all C++ code compile
// but not produce all templated code in binary
// use maximal.hpp for that
// please report if otherwise
#ifndef MACHINES_MINIMAL_HPP_
#define MACHINES_MINIMAL_HPP_
#include "h-files.h"
// some h files depend on hpp files
#include "GC/Secret.hpp"
#include "GC/SemiSecret.hpp"
#include "Protocols/DealerMC.hpp"
#include "Protocols/MAC_Check.hpp"
#include "Protocols/MaliciousRepMC.hpp"
#include "Protocols/ShamirMC.hpp"
#endif /* MACHINES_MINIMAL_HPP_ */

View File

@@ -3,10 +3,10 @@
*
*/
#include "Machines/ShamirMachine.h"
#include "Protocols/ShamirOptions.h"
#include "Protocols/ShamirShare.h"
#include "ShamirMachine.hpp"
#include "Shamir.hpp"
int main(int argc, const char** argv)
{

View File

@@ -4,6 +4,7 @@
*/
#include "Protocols/SohoShare.h"
#include "Protocols/SPDZ.h"
#include "Math/gfp.h"
#include "Math/gf2n.h"
#include "FHE/P2Data.h"

View File

@@ -3,7 +3,6 @@
*
*/
#include "ShamirMachine.h"
#include "Protocols/SpdzWiseShare.h"
#include "Protocols/MaliciousShamirShare.h"
#include "Protocols/SpdzWiseMC.h"
@@ -19,7 +18,7 @@
#include "Protocols/SpdzWisePrep.hpp"
#include "Protocols/SpdzWiseInput.hpp"
#include "Protocols/SpdzWiseShare.hpp"
#include "Machines/ShamirMachine.hpp"
#include "Machines/Shamir.hpp"
#include "Machines/MalRep.hpp"
template<class T>

View File

@@ -7,7 +7,7 @@ TOOLS = $(patsubst %.cpp,%.o,$(wildcard Tools/*.cpp))
NETWORK = $(patsubst %.cpp,%.o,$(wildcard Networking/*.cpp))
PROCESSOR = $(patsubst %.cpp,%.o,$(wildcard Processor/*.cpp))
PROCESSOR = $(patsubst %.cpp,%.o,$(wildcard Processor/*.cpp)) Protocols/ShamirOptions.o
FHEOBJS = $(patsubst %.cpp,%.o,$(wildcard FHEOffline/*.cpp FHE/*.cpp)) Protocols/CowGearOptions.o
@@ -59,7 +59,7 @@ DEPS := $(wildcard */*.d */*/*.d)
.SECONDARY: $(OBJS)
all: arithmetic binary gen_input online offline externalIO bmr ecdsa
all: arithmetic binary gen_input online offline externalIO bmr ecdsa export
vm: arithmetic binary
.PHONY: doc
@@ -124,7 +124,7 @@ tldr: setup
mkdir Player-Data 2> /dev/null; true
ifeq ($(ARM), 1)
$(patsubst %.cpp,%.o,$(wildcard */*.cpp)): deps/simde/simde
$(patsubst %.cpp,%.o,$(wildcard */*.cpp */*/*.cpp)): deps/simde/simde deps/sse2neon/sse2neon.h
endif
shamir: shamir-party.x malicious-shamir-party.x atlas-party.x galois-degree.x
@@ -162,6 +162,16 @@ static-dir:
static-release: static-dir $(patsubst Machines/%.cpp, static/%.x, $(wildcard Machines/*-party.cpp)) $(patsubst Machines/BMR/%.cpp, static/%.x, $(wildcard Machines/BMR/*-party.cpp)) static/emulate.x
EXPORT_VM = $(patsubst %.cpp, %.o, $(wildcard Machines/export-*.cpp))
.SECONDARY: $(EXPORT_VM)
export-trunc.x: Machines/export-ring.o
export-sort.x: Machines/export-ring.o
export-a2b.x: GC/AtlasSecret.o Machines/SPDZ.o Machines/SPDZ2^64+64.o $(GC_SEMI) $(TINIER) $(EXPORT_VM) GC/Rep4Secret.o GC/Rep4Prep.o $(FHEOFFLINE)
export-b2a.x: Machines/export-ring.o
export: $(patsubst Utils/%.cpp, %.x, $(wildcard Utils/export*.cpp))
Fake-ECDSA.x: ECDSA/Fake-ECDSA.cpp ECDSA/P256Element.o $(COMMON) Processor/PrepBase.o
$(CXX) -o $@ $^ $(CFLAGS) $(LDLIBS)
@@ -367,8 +377,11 @@ mac-machine-setup:
deps/simde/simde:
git submodule update --init deps/simde || git clone https://github.com/simd-everywhere/simde deps/simde
deps/sse2neon/sse2neon.h:
git submodule update --init deps/sse2neon || git clone https://github.com/DLTcollab/sse2neon deps/sse2neon
clean-deps:
-rm -rf local/lib/liblibOTe.* deps/libOTe/out deps/SimplestOT_C
-rm -rf local/lib/liblibOTe.* deps/libOTe/out deps/SimplestOT_C deps/SimpleOT
clean: clean-deps
-rm -f */*.o *.o */*.d *.d *.x core.* *.a gmon.out */*/*.o static/*.x *.so

View File

@@ -63,25 +63,25 @@ public:
return res;
}
FixedVec<T, L>(const T& other = {})
FixedVec(const T& other = {})
{
for (auto& x : v)
x = other;
}
FixedVec<T, L>(long other) :
FixedVec<T, L>(T(other))
FixedVec(long other) :
FixedVec(T(other))
{
}
template<class U>
FixedVec<T, L>(const FixedVec<U, L>& other)
FixedVec(const FixedVec<U, L>& other)
{
for (int i = 0; i < L; i++)
v[i] = other[i];
}
FixedVec<T, L>(const array<T, L>& other)
FixedVec(const array<T, L>& other)
{
v = other;
}

View File

@@ -71,14 +71,14 @@ int default_m(int& lgp, int& idx)
return m;
}
bigint generate_prime(int lgp, int m)
bigint generate_prime(int lgp, int m, bool force_degree)
{
bigint p;
generate_prime(p, lgp, m);
generate_prime(p, lgp, m, force_degree);
return p;
}
void generate_prime(bigint& p, int lgp, int m)
void generate_prime(bigint& p, int lgp, int m, bool force_degree)
{
if (OnlineOptions::singleton.prime > 0)
{
@@ -100,7 +100,8 @@ void generate_prime(bigint& p, int lgp, int m)
}
int idx;
m = max(m, default_m(lgp, idx));
if (not force_degree)
m = max(m, default_m(lgp, idx));
bigint u;
int ex;

View File

@@ -33,8 +33,8 @@ void check_setup(string dirname, bigint p);
// Chooses a p of at least lgp bits
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);
void generate_prime(bigint& p, int lgp, int m, bool force_degree = false);
bigint generate_prime(int lgp, int m, bool force_degree = false);
int default_m(int& lgp, int& idx);
string get_prep_sub_dir(const string& prep_dir, int nparties, int log2mod,

View File

@@ -35,7 +35,7 @@ public:
word get_upper() const { return _mm_cvtsi128_si64(_mm_unpackhi_epi64(a, a)); }
word get_half(bool upper) const { return upper ? get_upper() : get_lower(); }
#ifdef __SSE41__
#ifdef __SSE4_1__
bool operator==(const int128& other) const { return _mm_test_all_zeros(a ^ other.a, a ^ other.a); }
#else
bool operator==(const int128& other) const { return get_lower() == other.get_lower() and get_upper() == other.get_upper(); }
@@ -152,6 +152,8 @@ class gf2n_long : public gf2n_<int128>
gf2n_long(const super& g) : super(g) {}
gf2n_long(const int128& g) : super(g) {}
gf2n_long(int g) : gf2n_long(int128(unsigned(g))) {}
gf2n_long(long g) : gf2n_long(int128(g)) {}
gf2n_long(word g) : gf2n_long(int128(g)) {}
template<class T>
gf2n_long(IntBase<T> g) : super(g.get()) {}
template<class T>

View File

@@ -311,6 +311,11 @@ typedef gfp_<1, GFP_MOD_SZ> gfp1;
template<int X, int L>
Zp_Data gfp_<X, L>::ZpD;
template<int X, int L>
gfp_<X, L> gfp_<X, L>::two;
template<int X, int L>
const true_type gfp_<X, L>::prime_field;
template<int X, int L>
thread_local vector<gfp_<X, L>> gfp_<X, L>::powers;

View File

@@ -13,11 +13,7 @@
template<int X, int L>
const true_type gfp_<X, L>::invertible;
template<int X, int L>
const true_type gfp_<X, L>::prime_field;
template<int X, int L>
const int gfp_<X, L>::MAX_N_BITS;
template<int X, int L>
gfp_<X, L> gfp_<X, L>::two;
template<int X, int L>
inline void gfp_<X, L>::read_or_generate_setup(string dir,

View File

@@ -95,8 +95,10 @@ CryptoPlayer::CryptoPlayer(const Names& Nms, const string& id_base) :
continue;
}
senders[i] = new Sender<ssl_socket*>(i < my_num() ? sockets[i] : other_sockets[i]);
receivers[i] = new Receiver<ssl_socket*>(i < my_num() ? other_sockets[i] : sockets[i]);
senders[i] = new Sender<ssl_socket*>(
i < my_num() ? sockets[i] : other_sockets[i], i);
receivers[i] = new Receiver<ssl_socket*>(
i < my_num() ? other_sockets[i] : sockets[i], i);
}
}

View File

@@ -80,11 +80,14 @@ void Names::init(int player, int pnb, const string& filename, int nplayers_wante
}
if (nplayers_wanted > 0 and nplayers_wanted != nplayers)
exit_error("not enough hosts in " + filename);
#ifdef DEBUG_NETWORKING
cerr << "Got list of " << nplayers << " players from file: " << endl;
for (unsigned int i = 0; i < names.size(); i++)
cerr << " " << names[i] << ":" << ports[i] << endl;
#endif
if (OnlineOptions::singleton.has_option("debug_networking"))
{
cerr << "Got list of " << nplayers << " players from file: " << endl;
for (unsigned int i = 0; i < names.size(); i++)
cerr << " " << names[i] << ":" << ports[i] << endl;
}
setup_server();
}
@@ -140,9 +143,9 @@ void Names::setup_names(const char *servername, int my_port)
}
octetStream("P" + to_string(player_no)).Send(socket_num);
#ifdef DEBUG_NETWORKING
cerr << "Sent " << player_no << " to " << servername << ":" << pn << endl;
#endif
if (OnlineOptions::singleton.has_option("debug_networking"))
cerr << "Sent " << player_no << " to " << servername << ":" << pn << endl;
// Send my name
sockaddr_in address;
@@ -151,10 +154,12 @@ void Names::setup_names(const char *servername, int my_port)
char* my_name = inet_ntoa(address.sin_addr);
octetStream(my_name).Send(socket_num);
send(socket_num,(octet*)&my_port,4);
#ifdef DEBUG_NETWORKING
fprintf(stderr, "My Name = %s\n",my_name);
cerr << "My number = " << player_no << endl;
#endif
if (OnlineOptions::singleton.has_option("debug_networking"))
{
fprintf(stderr, "My Name = %s\n",my_name);
cerr << "My number = " << player_no << endl;
}
// Now get the set of names
try
@@ -172,10 +177,12 @@ void Names::setup_names(const char *servername, int my_port)
if (names.size() != ports.size())
exit_error("invalid network setup");
nplayers = names.size();
#ifdef VERBOSE
for (int i = 0; i < nplayers; i++)
cerr << "Player " << i << " is running on machine " << names[i] << endl;
#endif
if (OnlineOptions::singleton.has_option("debug_networking"))
for (int i = 0; i < nplayers; i++)
cerr << "Player " << i << " is running on machine " << names[i] << endl;
close_client_socket(socket_num);
}
@@ -640,8 +647,8 @@ ThreadPlayer::ThreadPlayer(const Names& Nms, const string& id_base) :
{
for (int i = 0; i < Nms.num_players(); i++)
{
receivers.push_back(new Receiver<int>(sockets[i]));
senders.push_back(new Sender<int>(socket_to_send(i)));
receivers.push_back(new Receiver<int>(sockets[i], i));
senders.push_back(new Sender<int>(socket_to_send(i), i));
}
}
@@ -845,10 +852,15 @@ Timer& CommStatsWithName::add_length_only(size_t length)
}
Timer& CommStatsWithName::add(const octetStream& os)
{
return add(os.get_length());
}
Timer& CommStatsWithName::add(size_t length)
{
if (OnlineOptions::singleton.has_option("verbose_comm"))
fprintf(stderr, "%s %zu bytes\n", name.c_str(), os.get_length());
return stats.add(os);
fprintf(stderr, "%s %zu bytes\n", name.c_str(), length);
return stats.add(length);
}
void Player::reset_stats()

View File

@@ -160,6 +160,7 @@ public:
Timer& add_length_only(size_t length);
Timer& add(const octetStream& os);
Timer& add(size_t length);
void add(const octetStream& os, const TimeScope& scope) { add(os) += scope; }
};

View File

@@ -5,6 +5,7 @@
#include "Receiver.h"
#include "ssl_sockets.h"
#include "Processor/OnlineOptions.h"
#include <iostream>
using namespace std;
@@ -19,8 +20,14 @@ void* Receiver<T>::run_thread(void* receiver)
return 0;
}
CommunicationThread::CommunicationThread(int other) :
other(other)
{
}
template<class T>
Receiver<T>::Receiver(T socket) : socket(socket), thread(0)
Receiver<T>::Receiver(T socket, int other) :
CommunicationThread(other), socket(socket), thread(0)
{
start();
}
@@ -44,8 +51,28 @@ void Receiver<T>::stop()
pthread_join(thread, 0);
}
void CommunicationThread::run()
{
if (OnlineOptions::singleton.has_option("throw_exceptions"))
run_with_error();
else
{
try
{
run_with_error();
}
catch (exception& e)
{
cerr << "Fatal error in communication: " << e.what() << endl;
cerr << "This is probably because party " << other
<< " encountered a problem." << endl;
exit(1);
}
}
}
template<class T>
void Receiver<T>::run()
void Receiver<T>::run_with_error()
{
octetStream* os = 0;
while (in.pop(os))

View File

@@ -12,8 +12,20 @@
#include "Tools/WaitQueue.h"
#include "Tools/time-func.h"
class CommunicationThread
{
int other;
protected:
CommunicationThread(int other);
virtual ~CommunicationThread() {}
void run();
virtual void run_with_error() = 0;
};
template<class T>
class Receiver
class Receiver : CommunicationThread
{
T socket;
WaitQueue<octetStream*> in;
@@ -27,12 +39,12 @@ class Receiver
void start();
void stop();
void run();
void run_with_error();
public:
Timer timer;
Receiver(T socket);
Receiver(T socket, int other);
~Receiver();
T get_socket()

View File

@@ -17,7 +17,8 @@ void* Sender<T>::run_thread(void* sender)
}
template<class T>
Sender<T>::Sender(T socket) : socket(socket), thread(0)
Sender<T>::Sender(T socket, int other) :
CommunicationThread(other), socket(socket), thread(0)
{
start();
}
@@ -42,7 +43,7 @@ void Sender<T>::stop()
}
template<class T>
void Sender<T>::run()
void Sender<T>::run_with_error()
{
const octetStream* os = 0;
while (in.pop(os))

View File

@@ -8,12 +8,14 @@
#include <pthread.h>
#include "Receiver.h"
#include "Tools/octetStream.h"
#include "Tools/WaitQueue.h"
#include "Tools/time-func.h"
template<class T>
class Sender
class Sender : CommunicationThread
{
T socket;
WaitQueue<const octetStream*> in;
@@ -27,12 +29,12 @@ class Sender
void start();
void stop();
void run();
void run_with_error();
public:
Timer timer;
Sender(T socket);
Sender(T socket, int other);
~Sender();
T get_socket()

View File

@@ -2,6 +2,7 @@
#include "Networking/sockets.h"
#include "Networking/ServerSocket.h"
#include "Networking/Server.h"
#include "Processor/OnlineOptions.h"
#include <iostream>
#include <pthread.h>
@@ -30,26 +31,23 @@ void Server::get_ip(int num)
names[num] = ipstr;
#ifdef DEBUG_NETWORKING
cerr << "Client IP address: " << names[num] << endl;
#endif
if (OnlineOptions::singleton.has_option("debug_networking"))
cerr << "IP address of party " << num << ": " << names[num] << endl;
}
void Server::get_name(int num)
{
#ifdef DEBUG_NETWORKING
cerr << "Player " << num << " started." << endl;
#endif
if (OnlineOptions::singleton.has_option("debug_networking"))
cerr << "Player " << num << " started." << endl;
// Receive name sent by client (legacy) - not used here
octetStream os;
os.Receive(socket_num[num]);
receive(socket_num[num],(octet*)&ports[num],4);
#ifdef DEBUG_NETWORKING
cerr << "Player " << num << " sent (IP for info only) " << os.str() << ":"
<< ports[num] << endl;
#endif
if (OnlineOptions::singleton.has_option("debug_networking"))
cerr << "Player " << num << " listening on " << os.str() << ":"
<< ports[num] << endl;
// Get client IP
get_ip(num);
@@ -121,13 +119,13 @@ void Server::start()
// set up connections
for (i=0; i<nmachines; i++)
{
#ifdef DEBUG_NETWORKING
cerr << "Waiting for player " << i << endl;
#endif
if (OnlineOptions::singleton.has_option("debug_networking"))
cerr << "Waiting for player " << i << endl;
socket_num[i] = server.get_connection_socket("P" + to_string(i));
#ifdef DEBUG_NETWORKING
cerr << "Connected to player " << i << endl;
#endif
if (OnlineOptions::singleton.has_option("debug_networking"))
cerr << "Connected to player " << i << endl;
}
// get names
@@ -164,10 +162,10 @@ void* Server::start_in_thread(void* server)
Server* Server::start_networking(Names& N, int my_num, int nplayers,
string hostname, int portnum, int my_port)
{
#ifdef DEBUG_NETWORKING
cerr << "Starting networking for " << my_num << "/" << nplayers
<< " with server on " << hostname << ":" << (portnum) << endl;
#endif
if (OnlineOptions::singleton.has_option("debug_networking"))
cerr << "Starting networking for " << my_num << "/" << nplayers
<< " with server on " << hostname << ":" << (portnum) << endl;
if (my_num < 0 or my_num >= nplayers)
{
cerr << "Player number " << my_num << " outside range: 0-"

View File

@@ -8,6 +8,7 @@
#include "Tools/Exceptions.h"
#include "Tools/time-func.h"
#include "Tools/octetStream.h"
#include "Processor/OnlineOptions.h"
#include <netinet/ip.h>
#include <netinet/tcp.h>
@@ -60,10 +61,9 @@ ServerSocket::ServerSocket(int Portnum) : portnum(Portnum), thread(0)
<< "), trying again in a second ..." << endl;
sleep(1);
}
#ifdef DEBUG_NETWORKING
else
{ cerr << "ServerSocket is bound on port " << Portnum << endl; }
#endif
if (OnlineOptions::singleton.has_option("debug_networking"))
cerr << "ServerSocket is bound on port " << Portnum << endl;
}
if (fl<0) { error("set_up_socket:bind"); }
@@ -121,11 +121,12 @@ void ServerSocket::wait_for_client_id(int socket, struct sockaddr dest)
}
catch (closed_connection&)
{
#ifdef DEBUG_NETWORKING
auto& conn = *(sockaddr_in*) &dest;
fprintf(stderr, "client on %s:%d left without identification\n",
inet_ntoa(conn.sin_addr), ntohs(conn.sin_port));
#endif
if (OnlineOptions::singleton.has_option("debug_networking"))
{
auto& conn = *(sockaddr_in*) &dest;
fprintf(stderr, "client on %s:%d left without identification\n",
inet_ntoa(conn.sin_addr), ntohs(conn.sin_port));
}
}
}

View File

@@ -2,19 +2,23 @@
#include "sockets.h"
#include "Tools/Exceptions.h"
#include "Tools/time-func.h"
#include "Processor/OnlineOptions.h"
#include <iostream>
#include <fcntl.h>
using namespace std;
void error(const char *str)
void error(const char *str, bool interrupted)
{
int old_errno = errno;
char err[1000];
gethostname(err,1000);
strcat(err," : ");
strcat(err,str);
exit_error(string() + err + " : " + strerror(old_errno));
gethostname(err, 1000);
err[999] = 0;
string message = string() + "Fatal communication error on " + err + ": "
+ str + " (" + strerror(old_errno) + ")";
if (interrupted)
message += "\nThis is probably because another party encountered a problem.";
exit_error(message);
}
void set_up_client_socket(int& mysocket,const char* hostname,int Portnum)
@@ -91,12 +95,13 @@ void set_up_client_socket(int& mysocket,const char* hostname,int Portnum)
{
close(mysocket);
usleep(wait < 1000 ? wait *= 2 : wait);
#ifdef DEBUG_NETWORKING
string msg = "Connecting to " + string(hostname) + ":" +
to_string(Portnum) + " failed";
errno = connect_errno;
perror(msg.c_str());
#endif
if (OnlineOptions::singleton.has_option("debug_networking"))
{
string msg = "Connecting to " + string(hostname) + ":"
+ to_string(Portnum) + " failed";
errno = connect_errno;
perror(msg.c_str());
}
}
errno = connect_errno;
}

View File

@@ -28,7 +28,7 @@ using namespace std;
#define CONNECTION_TIMEOUT 60
#endif
void error(const char *str);
void error(const char *str, bool interrupted = false);
void set_up_client_socket(int& mysocket,const char* hostname,int Portnum);
void close_client_socket(int socket);
@@ -51,7 +51,7 @@ inline size_t send_non_blocking(int socket, octet* msg, size_t len)
{
if (errno != EINTR and errno != EAGAIN and errno != EWOULDBLOCK and
errno != ENOBUFS)
{ error("Send error - 1 "); }
{ error("Sending error", true); }
else
return 0;
}
@@ -103,14 +103,14 @@ inline void receive(int socket,octet *msg,size_t len)
if (errno == EAGAIN or errno == EINTR)
{
if (++fail > 25)
error("Unavailable too many times");
error("Unavailable too many times", true);
else
{
usleep(wait *= 2);
}
}
else
{ error("Receiving error - 1"); }
{ error("Receiving error", true); }
}
else
throw closed_connection();
@@ -130,7 +130,7 @@ inline ssize_t check_non_blocking_result(ssize_t res)
if (res < 0)
{
if (errno != EWOULDBLOCK)
error("Non-blocking receiving error");
error("Non-blocking receiving error", true);
return 0;
}
return res;
@@ -149,7 +149,7 @@ inline ssize_t receive_all_or_nothing(int socket, octet *msg, ssize_t len)
if (res == len)
{
if (recv(socket, msg, len, 0) != len)
error("All or nothing receiving error");
error("All or nothing receiving error", true);
return len;
}
else

View File

@@ -111,6 +111,16 @@ void receiver_keygen(ref10_RECEIVER* r, unsigned char (*keys)[HASHBYTES])
ref10_receiver_keygen(r, keys);
}
void BaseOT::allocate()
{
for (int i = 0; i < nOT; i++)
{
sender_inputs[i][0] = BitVector(8 * AES_BLK_SIZE);
sender_inputs[i][1] = BitVector(8 * AES_BLK_SIZE);
receiver_outputs[i] = BitVector(8 * AES_BLK_SIZE);
}
}
int BaseOT::avx = -1;
bool BaseOT::use_avx()
@@ -186,6 +196,7 @@ void BaseOT::exec_base(bool new_receiver_inputs)
}
os[0].reset_write_head();
allocate();
for (i = 0; i < nOT; i += 4)
{
@@ -409,6 +420,8 @@ void FakeOT::exec_base(bool new_receiver_inputs)
vector<octetStream> os(2);
vector<BitVector> bv(2, 128);
allocate();
if ((ot_role & RECEIVER) && new_receiver_inputs)
{
for (int i = 0; i < nOT; i++)

View File

@@ -61,13 +61,6 @@ public:
receiver_outputs.resize(nOT);
G_sender.resize(nOT);
G_receiver.resize(nOT);
for (int i = 0; i < nOT; i++)
{
sender_inputs[i][0] = BitVector(8 * AES_BLK_SIZE);
sender_inputs[i][1] = BitVector(8 * AES_BLK_SIZE);
receiver_outputs[i] = BitVector(8 * AES_BLK_SIZE);
}
}
BaseOT(TwoPartyPlayer* player, OT_ROLE role) :
@@ -118,6 +111,8 @@ protected:
bool is_sender() { return (bool) (ot_role & SENDER); }
bool is_receiver() { return (bool) (ot_role & RECEIVER); }
void allocate();
bool use_avx();
/// CPU-specific instantiation of Simplest OT using Curve25519

View File

@@ -9,6 +9,7 @@
#include "Protocols/MAC_Check.h"
#include "GC/SemiSecret.h"
#include "GC/SemiPrep.h"
#include "Processor/OnlineOptions.h"
#include "OT/Triple.hpp"
#include "OT/OTMultiplier.hpp"
@@ -25,7 +26,21 @@ template<class T>
void* run_ot_thread(void* ptr)
{
bigint::init_thread();
((OTMultiplierBase*)ptr)->multiply();
auto multiplier = (OTMultiplierBase*) ptr;
if (OnlineOptions::singleton.has_option("throw_exceptions"))
multiplier->multiply();
else
{
try
{
multiplier->multiply();
}
catch (exception& e)
{
cerr << "Fatal error in OT thread: " << e.what() << endl;
exit(1);
}
}
return NULL;
}

View File

@@ -110,20 +110,13 @@ void DeferredPlus<T, U>::pack(octetStream& o) const
template<class T>
void Row<T>::pack(octetStream& o) const
{
o.store(this->size());
for (size_t i = 0; i < this->size(); i++)
rows[i].pack(o);
o.store(rows);
}
template<class T>
void Row<T>::unpack(octetStream& o)
{
size_t size;
o.get(size);
rows.clear();
rows.reserve(size);
for (size_t i = 0; i < size; i++)
rows.push_back(o.get<T>());
o.get(rows);
}
template <class V>

View File

@@ -30,7 +30,7 @@ BaseMachine& BaseMachine::s()
if (singleton)
return *singleton;
else
throw runtime_error("no singleton");
throw runtime_error("no BaseMachine singleton");
}
bool BaseMachine::has_program()
@@ -72,7 +72,8 @@ int BaseMachine::bucket_size(size_t usage)
int BaseMachine::matrix_batch_size(int n_rows, int n_inner, int n_cols)
{
unsigned res = min(100, OnlineOptions::singleton.batch_size);
int limit = max(1., 1e6 / (max(n_rows * n_inner, n_inner * n_cols)));
unsigned res = min(limit, OnlineOptions::singleton.batch_size);
if (has_program())
res = min(res, (unsigned) matrix_requirement(n_rows, n_inner, n_cols));
return res;
@@ -93,7 +94,8 @@ int BaseMachine::matrix_requirement(int n_rows, int n_inner, int n_cols)
return -1;
}
BaseMachine::BaseMachine() : nthreads(0)
BaseMachine::BaseMachine() :
nthreads(0), multithread(false)
{
if (sodium_init() == -1)
throw runtime_error("couldn't initialize libsodium");
@@ -147,7 +149,12 @@ void BaseMachine::load_schedule(const string& progname, bool load_bytecode)
#endif
long size = load_program(threadname, filename);
if (expected >= 0 and expected != size)
throw runtime_error("broken bytecode file");
{
stringstream os;
os << "broken bytecode file, found " << size
<< " instructions, expected " << expected;
throw runtime_error(os.str());
}
}
}

View File

@@ -37,7 +37,8 @@ class Binary_File_IO
* Throws file_error.
*/
template <class T>
void read_from_file(const string filename, vector< T >& buffer, const int start_posn, int &end_posn);
void read_from_file(const string filename, vector<T>& buffer,
const long start_posn, long& end_posn);
};
#endif

Some files were not shown because too many files have changed in this diff Show More