forked from bristolcrypto/SPDZ-2
-
Notifications
You must be signed in to change notification settings - Fork 281
/
bankers_bonus.mpc
143 lines (109 loc) · 4.75 KB
/
bankers_bonus.mpc
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
# coding: latin-1
"""
Solve Bankers bonus, aka Millionaires problem.
to deduce the maximum value from a range of integer input.
Demonstrate clients external to computing parties supplying input and receiving an authenticated result. See bankers-bonus-client.cpp for client (and setup instructions).
Wait for MAX_NUM_CLIENTS to join the game or client finish flag to be sent
before calculating the maximum.
Note each client connects in a single thread and so is potentially blocked.
Each round / game will reset and so this runs indefinitiely.
"""
from Compiler.types import sint, regint, Array, MemValue
from Compiler.library import print_ln, do_while, for_range
from Compiler.util import if_else
PORTNUM = 14000
MAX_NUM_CLIENTS = 8
n_rounds = 0
n_threads = 2
if len(program.args) > 1:
n_rounds = int(program.args[1])
if len(program.args) > 2:
program.active = bool(int(program.args[2]))
def accept_client():
client_socket_id = accept_client_connection(PORTNUM)
last = regint.read_from_socket(client_socket_id)
return client_socket_id, last
def close_connections(number_clients):
@for_range(number_clients)
def _(i):
closeclientconnection(i)
def client_input(t, client_socket_id):
"""
Send share of random value, receive input and deduce share.
"""
return t.receive_from_client(1, client_socket_id)[0]
def determine_winner(number_clients, client_values, client_ids):
"""Work out and return client_id which corresponds to max client_value"""
max_value = Array(1, client_values.value_type)
max_value[0] = client_values[0]
win_client_id = Array(1, sint)
win_client_id[0] = client_ids[0]
@for_range(number_clients-1)
def loop_body(i):
# Is this client input a new maximum, will be sint(1) if true, else sint(0)
is_new_max = max_value[0] < client_values[i+1]
# Keep latest max_value
max_value[0] = if_else(is_new_max, client_values[i+1], max_value[0])
# Keep current winning client id
win_client_id[0] = if_else(is_new_max, client_ids[i+1], win_client_id[0])
print_ln('maximum: %s', max_value[0].reveal())
return win_client_id[0]
def write_winner_to_clients(sockets, number_clients, winning_client_id):
"""Send share of winning client id to all clients who joined game."""
# Setup authenticate result using share of random.
# client can validate ∑ winning_client_id * ∑ rnd_from_triple = ∑ auth_result
sint.reveal_to_clients(sockets.get_sub(number_clients), [winning_client_id])
def main():
"""Listen in while loop for players to join a game.
Once maxiumum reached or have notified that round finished, run comparison and return result."""
# Start listening for client socket connections
listen_for_clients(PORTNUM)
print_ln('Listening for client connections on base port %s', PORTNUM)
def game_loop(_=None):
print_ln('Starting a new round of the game.')
# Clients socket id (integer).
client_sockets = Array(MAX_NUM_CLIENTS, regint)
# Number of clients
number_clients = MemValue(regint(0))
# Client ids to identity client
client_ids = Array(MAX_NUM_CLIENTS, sint)
# Keep track of received inputs
seen = Array(MAX_NUM_CLIENTS, regint)
seen.assign_all(0)
# Loop round waiting for each client to connect
@do_while
def client_connections():
client_id, last = accept_client()
@if_(client_id >= MAX_NUM_CLIENTS)
def _():
print_ln('client id too high')
crash()
client_sockets[client_id] = client_id
client_ids[client_id] = client_id
seen[client_id] = 1
@if_(last == 1)
def _():
number_clients.write(client_id + 1)
return (sum(seen) < number_clients) + (number_clients == 0)
def type_run(t):
# Clients secret input.
client_values = t.Array(MAX_NUM_CLIENTS)
@for_range_multithread(n_threads, 1, number_clients)
def _(client_id):
client_values[client_id] = client_input(t, client_id)
winning_client_id = determine_winner(number_clients, client_values,
client_ids)
# print_ln('Found winner, index: %s.', winning_client_id.reveal())
write_winner_to_clients(client_sockets, number_clients,
winning_client_id)
type_run(sint)
type_run(sfix)
close_connections(number_clients)
return True
if n_rounds > 0:
print('run %d rounds' % n_rounds)
for_range(n_rounds)(game_loop)
else:
print('run forever')
do_while(game_loop)
main()