Welcome to MP-SPDZ’s documentation!¶
If you’re new to MP-SPDZ, consider the following:
Unlike the Readme, this documentation provides a reference for more detailed aspects of the software.
Compilation process¶
The easiest way of using MP-SPDZ is using compile.py
as
described below. If you would like to run compilation directly from
Python, see Scripts/direct_compilation_example.py
. It contains all
the necessary setup steps.
After putting your code in Program/Source/<progname>.mpc
, run the
compiler from the root directory as follows
./compile.py [options] <progname> [args]
The arguments <progname> [args]
are accessible as list under
program.args
within progname.mpc
, with <progname>
as
program.args[0]
.
The following options influence the computation domain:
- -F <integer length>¶
- --field=<integer length>¶
Compile for computation modulo a prime and the default integer length. This means that secret integers are assumed to have at most said length unless explicitly told otherwise. The compiled output will communicate the minimum length of the prime number to the virtual machine, which will fail if this is not met. This is the default with an integer length set to 64. When not specifying the prime, the minimum prime length will be around 40 bits longer than the integer length. Furthermore, the computation will be optimistic in the sense that overflows in the secrets might have security implications.
- -P <prime>¶
- --prime=<prime>¶
Specify a concrete prime modulus for computation. This can be used together with
-F
, in which case integer length has to be at most the prime length minus two. The security implications of overflows in the secrets do not go beyond incorrect results.
- -R <ring size>¶
- --ring=<ring size>¶
Compile for computation modulo 2^(ring size). This will set the assumed length of secret integers to one less because many operations require this. The exact ring size will be communicated to the virtual machine, which will use it automatically if supported.
- -B <integer length>¶
- --binary=<integer length>¶
Compile for binary computation using integer length as default.
For arithmetic computation (-F
, -P
, and
-R
) you can set the bit
length during execution using program.set_bit_length(length)
. For
binary computation you can do so with sint =
sbitint.get_type(length)
.
Use sfix.set_precision()
to change the range for fixed-point
numbers.
The following options switch from a single computation domain to mixed computation when using in conjunction with arithmetic computation:
The implementation of both daBits and edaBits are explained in this paper.
- -Z <number of parties>¶
- --split=<number of parties>¶
Enables mixed computation using local conversion. This has been used by Mohassel and Rindal and Araki et al. It only works with additive secret sharing modulo a power of two.
The following options change less fundamental aspects of the computation:
- -D¶
- --dead-code-elimination¶
Eliminates unused code. This currently means computation that isn’t used for input or output or written to the so-called memory (e.g.,
Array
; seetypes
).
- -b <budget>¶
- --budget=<budget>¶
Set the budget for loop unrolling with
for_range_opt()
and similar. This means that loops are unrolled up to budget instructions. Default is 100,000 instructions.
- -C¶
- --CISC¶
Speed up the compilation of repetitive code at the expense of a potentially higher number of communication rounds. For example, the compiler by default will try to compute a division and a logarithm in parallel if possible. Using this option complex operations such as these will be separated and only multiple divisions or logarithms will be computed in parallel. This speeds up the compilation because of reduced complexity.
- -l¶
- --flow-optimization¶
Optimize simple loops (
for <iterator> in range(<n>)
) by usingfor_range_opt()
and defer if statements to the run time.
Compilation vs run time¶
The most important thing to keep in mind is that the Python code is
executed at compile-time. This means that Python data structures such
as list
and dict
only exist at compile-time
and that all Python loops are unrolled. For run-time loops and lists,
you can use for_range()
(or the more
optimizing for_range_opt()
) and
Array
. For convenient multithreading you
can use for_range_opt_multithread()
, which
automatically distributes the computation on the requested number of
threads.
This reference uses the term ‘compile-time’ to indicate Python types
(which are inherently known when compiling). If the term ‘public’ is
used, this means both compile-time values as well as public run-time
types such as regint
.
Reference¶
Contents:
- High-Level Interface
- Compiler.types module
- Basic types
- Container types
Array
Array.assign()
Array.assign_all()
Array.assign_part_vector()
Array.assign_vector()
Array.binary_output()
Array.create_from()
Array.expand_to_vector()
Array.get()
Array.get_part()
Array.get_part_vector()
Array.get_vector()
Array.input_from()
Array.maybe_get()
Array.maybe_set()
Array.print_reveal_nested()
Array.randomize()
Array.read_from_file()
Array.reveal()
Array.reveal_list()
Array.reveal_nested()
Array.reveal_to()
Array.reveal_to_binary_output()
Array.reveal_to_clients()
Array.same_shape()
Array.shuffle()
Array.sort()
Array.write_to_file()
Matrix
Matrix.assign()
Matrix.assign_all()
Matrix.assign_part_vector()
Matrix.assign_vector()
Matrix.assign_vector_by_indices()
Matrix.diag()
Matrix.direct_mul()
Matrix.direct_mul_to_matrix()
Matrix.direct_mul_trans()
Matrix.direct_trans_mul()
Matrix.dot()
Matrix.get_column()
Matrix.get_part()
Matrix.get_part_vector()
Matrix.get_slice_vector()
Matrix.get_vector()
Matrix.get_vector_by_indices()
Matrix.iadd()
Matrix.input_from()
Matrix.mul_trans()
Matrix.mul_trans_to()
Matrix.plain_mul()
Matrix.print_reveal_nested()
Matrix.randomize()
Matrix.read_from_file()
Matrix.reveal_list()
Matrix.reveal_nested()
Matrix.reveal_to_binary_output()
Matrix.reveal_to_clients()
Matrix.same_shape()
Matrix.schur()
Matrix.set_column()
Matrix.trace()
Matrix.trans_mul()
Matrix.trans_mul_to()
Matrix.transpose()
Matrix.write_to_file()
MemValue
MultiArray
MultiArray.assign()
MultiArray.assign_all()
MultiArray.assign_part_vector()
MultiArray.assign_vector()
MultiArray.assign_vector_by_indices()
MultiArray.diag()
MultiArray.direct_mul()
MultiArray.direct_mul_to_matrix()
MultiArray.direct_mul_trans()
MultiArray.direct_trans_mul()
MultiArray.dot()
MultiArray.get_part()
MultiArray.get_part_vector()
MultiArray.get_slice_vector()
MultiArray.get_vector()
MultiArray.get_vector_by_indices()
MultiArray.iadd()
MultiArray.input_from()
MultiArray.mul_trans()
MultiArray.mul_trans_to()
MultiArray.plain_mul()
MultiArray.print_reveal_nested()
MultiArray.randomize()
MultiArray.read_from_file()
MultiArray.reveal_list()
MultiArray.reveal_nested()
MultiArray.reveal_to_binary_output()
MultiArray.reveal_to_clients()
MultiArray.same_shape()
MultiArray.schur()
MultiArray.trace()
MultiArray.trans_mul()
MultiArray.trans_mul_to()
MultiArray.transpose()
MultiArray.write_to_file()
cfix
cfloat
cgf2n
cgf2n.Array()
cgf2n.Matrix()
cgf2n.MemValue()
cgf2n.Tensor()
cgf2n.binary_output()
cgf2n.bit_and()
cgf2n.bit_compose()
cgf2n.bit_decompose()
cgf2n.bit_not()
cgf2n.bit_or()
cgf2n.bit_xor()
cgf2n.cond_swap()
cgf2n.half_adder()
cgf2n.if_else()
cgf2n.load_mem()
cgf2n.malloc()
cgf2n.max()
cgf2n.min()
cgf2n.print_reg_plain()
cgf2n.reveal()
cgf2n.square()
cgf2n.store_in_mem()
cint
cint.Array()
cint.Matrix()
cint.MemValue()
cint.Tensor()
cint.binary_output()
cint.bit_adder()
cint.bit_and()
cint.bit_compose()
cint.bit_decompose()
cint.bit_not()
cint.bit_or()
cint.bit_xor()
cint.cond_swap()
cint.digest()
cint.half_adder()
cint.if_else()
cint.legendre()
cint.less_than()
cint.load_mem()
cint.malloc()
cint.max()
cint.min()
cint.mod2m()
cint.print_if()
cint.print_reg_plain()
cint.read_from_socket()
cint.reveal()
cint.right_shift()
cint.square()
cint.store_in_mem()
cint.to_regint()
cint.write_to_socket()
localint
personal
regint
regint.Array()
regint.Matrix()
regint.MemValue()
regint.Tensor()
regint.binary_output()
regint.bit_adder()
regint.bit_and()
regint.bit_compose()
regint.bit_decompose()
regint.bit_not()
regint.bit_or()
regint.bit_xor()
regint.cond_swap()
regint.get_random()
regint.half_adder()
regint.if_else()
regint.inc()
regint.load_mem()
regint.malloc()
regint.max()
regint.min()
regint.mod2m()
regint.pop()
regint.print_if()
regint.print_reg_plain()
regint.push()
regint.read_from_socket()
regint.reveal()
regint.shuffle()
regint.square()
regint.store_in_mem()
regint.write_to_socket()
sfix
sfix.Array()
sfix.Matrix()
sfix.MemValue()
sfix.Tensor()
sfix.compute_reciprocal()
sfix.dot_product()
sfix.get_input_from()
sfix.get_random()
sfix.input_tensor_from()
sfix.input_tensor_from_client()
sfix.input_tensor_via()
sfix.load_mem()
sfix.max()
sfix.min()
sfix.read_from_file()
sfix.receive_from_client()
sfix.reveal()
sfix.reveal_to()
sfix.reveal_to_clients()
sfix.round_nearest
sfix.set_precision()
sfix.square()
sfix.store_in_mem()
sfix.write_shares_to_socket()
sfix.write_to_file()
sfloat
sgf2n
sgf2n.Array()
sgf2n.Matrix()
sgf2n.MemValue()
sgf2n.Tensor()
sgf2n.bit_and()
sgf2n.bit_compose()
sgf2n.bit_decompose()
sgf2n.bit_not()
sgf2n.bit_or()
sgf2n.bit_xor()
sgf2n.cond_swap()
sgf2n.dot_product()
sgf2n.equal()
sgf2n.get_input_from()
sgf2n.get_random_bit()
sgf2n.get_random_input_mask_for()
sgf2n.get_random_inverse()
sgf2n.get_random_square()
sgf2n.get_random_triple()
sgf2n.half_adder()
sgf2n.if_else()
sgf2n.input_tensor_from()
sgf2n.input_tensor_from_client()
sgf2n.input_tensor_via()
sgf2n.load_mem()
sgf2n.malloc()
sgf2n.max()
sgf2n.min()
sgf2n.not_equal()
sgf2n.reveal()
sgf2n.reveal_to()
sgf2n.right_shift()
sgf2n.square()
sgf2n.store_in_mem()
sint
sint.Array()
sint.Matrix()
sint.MemValue()
sint.Tensor()
sint.bit_adder()
sint.bit_and()
sint.bit_compose()
sint.bit_decompose()
sint.bit_not()
sint.bit_or()
sint.bit_xor()
sint.cond_swap()
sint.dot_product()
sint.equal()
sint.get_dabit()
sint.get_edabit()
sint.get_input_from()
sint.get_random()
sint.get_random_bit()
sint.get_random_input_mask_for()
sint.get_random_int()
sint.get_random_inverse()
sint.get_random_square()
sint.get_random_triple()
sint.greater_equal()
sint.greater_than()
sint.half_adder()
sint.if_else()
sint.input_tensor_from()
sint.input_tensor_from_client()
sint.input_tensor_via()
sint.int_div()
sint.left_shift()
sint.less_equal()
sint.less_than()
sint.load_mem()
sint.malloc()
sint.max()
sint.min()
sint.mod2m()
sint.not_equal()
sint.pow2()
sint.private_division()
sint.read_from_file()
sint.read_from_socket()
sint.receive_from_client()
sint.reveal()
sint.reveal_to()
sint.reveal_to_clients()
sint.right_shift()
sint.round()
sint.square()
sint.store_in_mem()
sint.write_shares_to_socket()
sint.write_to_file()
sint.write_to_socket()
sintbit
- Compiler.GC.types module
- Compiler.library module
accept_client_connection()
break_loop()
break_point()
check_point()
crash()
do_while()
for_range()
for_range_multithread()
for_range_opt()
for_range_opt_multithread()
for_range_parallel()
foreach_enumerate()
get_arg()
get_number_of_players()
get_player_id()
get_thread_number()
get_threshold()
if_()
if_e()
listen_for_clients()
map_sum_opt()
map_sum_simple()
multithread()
print_float_precision()
print_ln()
print_ln_if()
print_ln_to()
print_str()
print_str_if()
public_input()
runtime_error()
runtime_error_if()
start_timer()
stop_timer()
tree_reduce()
tree_reduce_multithread()
while_do()
- Compiler.mpc_math module
- Compiler.ml module
- Compiler.circuit module
- Compiler.program module
- Compiler.oram module
- Compiler.types module
- Virtual Machine
- Instructions
- Compiler.instructions module
acceptclientconnection
addc
addci
addint
addm
adds
addsi
andc
andci
asm_open
bit
bitdecint
check
cisc
closeclientconnection
cond_print_plain
cond_print_str
conv2ds
convint
convmodp
crash
dabit
digestc
divc
divci
divint
dotprods
edabit
eqc
eqzc
floatoutput
floordivc
gbitcom
gbitdec
gbitgf2ntriple
gbittriple
gconvgf2n
gldmci
gldmsi
gmulbitc
gmulbitm
gnotc
gstmci
gstmsi
gtc
incint
inputfix
inputfloat
inputmask
inputmaskreg
inputmixed
inputmixedreg
inputpersonal
intoutput
inv2m
inverse
jmp
jmpeqz
jmpi
jmpnz
join_tape
ldarg
ldi
ldint
ldmc
ldmci
ldmint
ldminti
ldms
ldmsi
ldsi
ldtn
legendrec
listen
ltc
ltzc
matmuls
matmulsm
modc
modci
movc
movint
movs
mulc
mulci
mulint
mulm
mulrs
muls
mulsi
notc
nplayers
orc
orci
personal_base
playerid
popint
prep
print_char
print_char4
print_float_plain
print_float_prec
print_int
print_reg
print_reg_plain
privateoutput
pubinput
pushint
rand
randomfulls
randoms
rawinput
readsharesfromfile
readsocketc
readsocketint
readsockets
reqbl
run_tape
sedabit
sendpersonal
shlc
shlci
shrc
shrci
shrsi
shuffle
square
starg
start
stmc
stmci
stmint
stminti
stms
stmsi
stop
subc
subcfi
subci
subint
subml
submr
subs
subsfi
subsi
threshold
time
triple
trunc_pr
use
use_edabit
use_inp
use_matmul
use_prep
writesharestofile
writesockets
writesocketshare
xorc
xorci
- Compiler.GC.instructions module
addcb
addcbi
andm
andrs
ands
bitb
bitcoms
bitdecc
bitdecs
cond_print_strb
convcbit
convcbit2s
convcbitvec
convcint
convcintvec
convsint
inputb
inputbvec
ldbits
ldmcb
ldmcbi
ldmsb
ldmsbi
movsb
mulcbi
notcb
nots
print_float_plainb
print_reg_plainb
print_reg_signed
print_regb
reveal
shlcbi
shrcbi
split
stmcb
stmcbi
stmsb
stmsbi
trans
xorcb
xorcbi
xorm
xors
- Low-Level Interface
- Machine Learning
- Networking
- Input/Output
- Non-linear Computation
- Preprocessing
- Adding a Protocol
- Troubleshooting
- Crash without error message or
bad_alloc
- List indices must be integers or slices
compile.py
takes too long or runs out of memory- Order of memory instructions not preserved
- Odd timings
- Disparities in round figures
- Handshake failures
- Connection failures
- Internally called tape has unknown offline data usage
- Illegal instruction
- Invalid instruction
- Computation used more preprocessing than expected
mac_fail
- Crash without error message or