-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathtutorial.mpc
More file actions
164 lines (129 loc) · 5.13 KB
/
tutorial.mpc
File metadata and controls
164 lines (129 loc) · 5.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# compile with either -R 32 or -R 64 for arithmetic circuits
# or -B <bit-length> where <bit-length> can be chosen arbitrarily independent
# - except a integer is read as private input: <bit-length> has to equal `BITLENGTH`
# of `BITLENGTH`/`DATTYPE` for boolean circuits
# add -k LTZ,EQZ for arithmetic circuits to include LTZ,EQZ operations
# supported simple types:
# - sint: `Additive_Share`
# - sfix: will be stored as `Additive_Share` but left shifted by `FRACTIONAL`
# - cfix: clear fix point
# - regint: will always be a 64bit int
# - cint: same bit length ask
# - sbit: unfortunately each bit will be stored in exactly ONE `XOR_SHARE`
# - cbit: will be handled efficiently as opposed to sbit
# when compiling with SIMD numbers will be printed with brackets `(`, `)` surrounding them
# for example for `DATTYPE` 128 and `BITLENGTH` 32
# print_ln("%s", sint(6).reveal())
# would print: (6, 6, 6, 6)
def test(actual, expected):
# you can reveal a number in order to print it
actual = actual.reveal()
print_ln('expected %s, got %s', expected, actual)
############################### secret shares #################################
# you can assign public values to sbit/sint
a = sint(6) # equals 1 Additive_Share
b = sint(10)
# private inputs are read (as strings) from a input-file:
# - MP-SPDZ/Input/Input-P<player-num>-<process-number>-<vectorization>
# where:
# - <process-number>: always zero but can be used to support parallel execution
# of the same function
# - <vectorization> is from 0 - `DATTYPE`/`BITLENGTH`
# to share private input from player <player> with everyone:
# and use reveal() to reveal output to every player
for player in 0, 0:
print_ln("got: %s from player %s", sint.get_input_from(player).reveal(), player)
test(a + b, 16)
test(a + 10, 16) # add by using `get_share_from_public_dat` as public val can also be SIMD
test(a * b, 60)
test(a * 10, 60) # public mult using `mult_public_dat`
test(a - b, -4)
test(a - 10, -4) # see public add
test(6 - b, -4) # similar to public add
# same as `FRACTIONAL` for fix point division
sfix.set_precision(7)
test(a / b, 6 / 10) # use fix point division for correct results (will use random secret bits)
# MP-SPDZ has int_div for integer division but this requires correct signed truncation
# therefore does not work for secure computations
# - a workaround for this is to remove the line 114 "@instructions_base.cisc" in
# `Compiler/comparison` of the MP-SPDZ compiler before the `def Trunc`
# function: this will prevent MP-SPDZ from using this instruction but instead
# use the same approach as for a / b but with correct rounding to an integer
################################# fix point ###################################
# should only be set true for programs with no division
# otherwise trunc with run-time parameters is needed
program.use_trunc_pr = False
# precision used to print fix-point numbers can be set arbitrarily
# default (if not set explicitly): `FRACTIONAL`
print_float_precision(10)
# you can assign public numbers to sfix
a = sfix(7)
b = sfix(0.5)
# will be read as float multiplied with [1u << (`FRACTIONAL`)] and converted
# to an integer
for i in 0, 0:
print_ln('got %s from player %s', sfix.get_input_from(i).reveal(), i)
# arithmetic works as expected
test(a + b, 7.5)
test(a * b, 3.5)
test(a - b, 6.5)
test(a / b, 7/0.5)
################################## Arrays #####################################
datatype = sint
n = 10
player = 0
# array of size <n> can be used with any <datatype>
# BUT: for secret shares (sint/sbit) not initialized otherwise 0 initialized
a = datatype.Array(n)
b = datatype.Array(n)
# to share private input from <player> with everyone
a.input_from(player)
# or assign public values
a.assign([i + 3 for i in range(n)])
b.assign([i for i in range(n)])
# simple operations
test(a + b, [3, 5, 7, 9, 11, 13, 15, 17, 19, 21])
test(a - b, [3 for i in range(n)])
test(a * b, [0, 4, 10, 18, 28, 40, 54, 70, 88, 108])
# dot product
test(datatype.dot_product(a,b), 420)
################################# Matrices ####################################
rows = 3
cols = 2
a = datatype.Matrix(rows, cols)
b = datatype.Matrix(rows, cols)
# to read private secret matrix:
# - will read "row-wise"
# example:
# input-file: 0 1 2 3 4 5
# 3x2 matrix: [[0 1],
# [2 3],
# [4 5]]
a.input_from(0) # will read a matrix from player 0's input-file
print_ln("Matrix: %s", a.reveal())
b = b.transpose() # matrix transpose
a.assign([[1,2], [3,4], [5,6]])
b.assign([[1,2,3], [4,5,6]])
vec = datatype.Array(cols)
vec.assign_all(3)
test(a * b, [[9, 12, 15], [19, 26, 33], [29, 40, 51]]) # matrix x matrix
test(a * vec, [9, 21, 33]) # matrix x vec
################################### sbits #####################################
# # for boolean gates uncomment and compile with -B 128
#
# sb128 = sbits.get_type(128)
#
# # to read bits as input use:
# a = sb128.get_input_from(0)
# # - as sb128 is 128 bit:
# # - reads 128/`BITLENGTH' numbers from input-file
# # - will be read into 128 XOR_Shares
#
# a = sb128(20)
# b = sb128(30)
#
# test(a ^ b, 10)
# test(a ^ 30, 10) # public xor is split into multiple NOTS
# test(a & b, 20)
# test(a & 30, 20)
# test(~a, -21)