1 /*******************************************************************************
2 This file is part of LibTMCG.
3
4 Copyright (C) 2016, 2017, 2018, 2019 Heiko Stamer <HeikoStamer@gmx.net>
5
6 LibTMCG is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 LibTMCG is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with LibTMCG; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *******************************************************************************/
20
21 // include headers
22 #ifdef HAVE_CONFIG_H
23 #include "libTMCG_config.h"
24 #endif
25 #include <libTMCG.hh>
26
27 #ifdef FORKING
28
29 #include <exception>
30 #include <sstream>
31 #include <vector>
32 #include <algorithm>
33 #include <cassert>
34 #include <unistd.h>
35 #include <errno.h>
36 #include <sys/wait.h>
37
38 #include "test_helper.h"
39 #include "pipestream.hh"
40
41 #undef NDEBUG
42 #define PLAYERS 9
43 #define DECKSIZE 52
44 #define FLOPSIZE 5
45
46 int pipefd[PLAYERS][PLAYERS][2];
47 pid_t pid[PLAYERS];
48
start_instance(std::istream & vtmf_str,size_t player)49 void start_instance
50 (std::istream& vtmf_str, size_t player)
51 {
52 if ((pid[player] = fork()) < 0)
53 perror("t-poker-cutnchoose (fork)");
54 else
55 {
56 if (pid[player] == 0)
57 {
58 try
59 {
60 /* BEGIN child code: participant P_i */
61
62 // create pipe streams between all players
63 ipipestream *P_in[PLAYERS];
64 opipestream *P_out[PLAYERS];
65 for (size_t i = 0; i < PLAYERS; i++)
66 {
67 P_in[i] = new ipipestream(pipefd[i][player][0]);
68 P_out[i] = new opipestream(pipefd[player][i][1]);
69 }
70
71 // create TMCG and VTMF instances
72 start_clock();
73 SchindelhauerTMCG *tmcg = new SchindelhauerTMCG(80, PLAYERS, 6);
74 BarnettSmartVTMF_dlog *vtmf = new BarnettSmartVTMF_dlog(vtmf_str);
75 if (!vtmf->CheckGroup())
76 {
77 std::cout << "P_" << player << ": " <<
78 "Group G was not correctly generated!" << std::endl;
79 exit(-1);
80 }
81 stop_clock();
82 std::cout << "P_" << player << ": " << elapsed_time() <<
83 std::endl;
84
85 // create and exchange VTMF keys
86 start_clock();
87 vtmf->KeyGenerationProtocol_GenerateKey();
88 for (size_t i = 0; i < PLAYERS; i++)
89 {
90 if (i != player)
91 vtmf->KeyGenerationProtocol_PublishKey(*P_out[i]);
92 }
93 for (size_t i = 0; i < PLAYERS; i++)
94 {
95 if (i != player)
96 {
97 if (!vtmf->KeyGenerationProtocol_UpdateKey(*P_in[i]))
98 {
99 std::cout << "P_" << player << ": Public key of" <<
100 " P_" << i << " was not correctly generated!" <<
101 std::endl;
102 exit(-1);
103 }
104 }
105 }
106 vtmf->KeyGenerationProtocol_Finalize();
107 stop_clock();
108 std::cout << "P_" << player << ": " << elapsed_time() <<
109 std::endl;
110
111 // create and shuffle the deck
112 start_clock();
113 TMCG_OpenStack<VTMF_Card> deck;
114 for (size_t type = 0; type < DECKSIZE; type++)
115 {
116 VTMF_Card c;
117 tmcg->TMCG_CreateOpenCard(c, vtmf, type);
118 deck.push(type, c);
119 }
120 TMCG_Stack<VTMF_Card> s;
121 s.push(deck);
122 for (size_t i = 0; i < PLAYERS; i++)
123 {
124 TMCG_Stack<VTMF_Card> s2;
125 if (i == player)
126 {
127 TMCG_StackSecret<VTMF_CardSecret> ss;
128 tmcg->TMCG_CreateStackSecret(ss, false, s.size(), vtmf);
129 tmcg->TMCG_MixStack(s, s2, ss, vtmf);
130 for (size_t i2 = 0; i2 < PLAYERS; i2++)
131 {
132 if (i2 == player)
133 continue;
134 *P_out[i2] << s2 << std::endl;
135 tmcg->TMCG_ProveStackEquality(s, s2, ss, false,
136 vtmf, *P_in[i2], *P_out[i2]);
137 }
138 }
139 else
140 {
141 *P_in[i] >> s2;
142 if (!P_in[i]->good())
143 {
144 std::cout << "Read or parse error!" << std::endl;
145 exit(-1);
146 }
147 if (!tmcg->TMCG_VerifyStackEquality(s, s2, false, vtmf,
148 *P_in[i], *P_out[i]))
149 {
150 std::cout << "Shuffle verification failed!" <<
151 std::endl;
152 exit(-1);
153 }
154 }
155 s = s2;
156 }
157 stop_clock();
158 std::cout << "P_" << player << ": " << elapsed_time() <<
159 std::endl;
160
161 // drawing two cards for each player
162 start_clock();
163 TMCG_Stack<VTMF_Card> hand[PLAYERS];
164 for (size_t i = 0; i < PLAYERS; i++)
165 {
166 VTMF_Card c1, c2;
167 s.pop(c1), s.pop(c2);
168 hand[i].push(c1), hand[i].push(c2);
169 }
170 TMCG_OpenStack<VTMF_Card> private_hand;
171 for (size_t i = 0; i < PLAYERS; i++)
172 {
173 if (i == player)
174 {
175 for (size_t k = 0; k < hand[i].size(); k++)
176 {
177 tmcg->TMCG_SelfCardSecret(hand[i][k], vtmf);
178 for (size_t i2 = 0; i2 < PLAYERS; i2++)
179 {
180 if (i2 == player)
181 continue;
182 if (!tmcg->TMCG_VerifyCardSecret(hand[i][k],
183 vtmf, *P_in[i2], *P_out[i2]))
184 {
185 std::cout << "Card verification failed!" <<
186 std::endl;
187 exit(-1);
188 }
189 }
190 size_t type = tmcg->TMCG_TypeOfCard(hand[i][k],
191 vtmf);
192 private_hand.push(type, hand[i][k]);
193 }
194 }
195 else
196 {
197 for (size_t k = 0; k < hand[i].size(); k++)
198 {
199 tmcg->TMCG_ProveCardSecret(hand[i][k], vtmf,
200 *P_in[i], *P_out[i]);
201 }
202 }
203 }
204 stop_clock();
205 std::cout << "P_" << player << ": " << elapsed_time() <<
206 std::endl;
207 std::cout << "P_" << player << ": my cards are " <<
208 private_hand[0].first << " and " <<
209 private_hand[1].first << std::endl;
210
211 // drawing the flop
212 start_clock();
213 TMCG_Stack<VTMF_Card> flop;
214 VTMF_Card c;
215 for (size_t i = 0; i < FLOPSIZE; i++)
216 {
217 s.pop(c), flop.push(c);
218 }
219 TMCG_OpenStack<VTMF_Card> open_flop;
220 for (size_t i = 0; i < PLAYERS; i++)
221 {
222 if (i == player)
223 {
224 for (size_t k = 0; k < flop.size(); k++)
225 {
226 tmcg->TMCG_SelfCardSecret(flop[k], vtmf);
227 for (size_t i2 = 0; i2 < PLAYERS; i2++)
228 {
229 if (i2 == player)
230 continue;
231 if (!tmcg->TMCG_VerifyCardSecret(flop[k], vtmf,
232 *P_in[i2], *P_out[i2]))
233 {
234 std::cout << "Card verification failed!" <<
235 std::endl;
236 exit(-1);
237 }
238 }
239 size_t type = tmcg->TMCG_TypeOfCard(flop[k], vtmf);
240 open_flop.push(type, flop[k]);
241 }
242 }
243 else
244 {
245 for (size_t k = 0; k < flop.size(); k++)
246 {
247 tmcg->TMCG_ProveCardSecret(flop[k], vtmf,
248 *P_in[i], *P_out[i]);
249 }
250 }
251 }
252 stop_clock();
253 std::cout << "P_" << player << ": " << elapsed_time() <<
254 std::endl;
255 std::cout << "P_" << player << ": flop cards are ";
256 for (size_t i = 0; i < FLOPSIZE; i++)
257 std::cout << open_flop[i].first << " ";
258 std::cout << std::endl;
259
260 // release TMCG and VTMF instances
261 delete tmcg, delete vtmf;
262
263 // release pipe streams
264 size_t numRead = 0, numWrite = 0;
265 for (size_t i = 0; i < PLAYERS; i++)
266 {
267 numRead += P_in[i]->get_numRead() + P_out[i]->get_numRead();
268 numWrite += P_in[i]->get_numWrite() + P_out[i]->get_numWrite();
269 delete P_in[i], delete P_out[i];
270 }
271 std::cout << "P_" << player << ": numRead = " << numRead <<
272 " numWrite = " << numWrite << std::endl;
273
274 std::cout << "P_" << player << ": exit(0)" << std::endl;
275 exit(0);
276 /* END child code: participant P_i */
277 }
278 catch (std::exception& e)
279 {
280 std::cerr << "exception catched with what = " << e.what() <<
281 std::endl;
282 exit(-1);
283 }
284 }
285 else
286 std::cout << "fork() = " << pid[player] << std::endl;
287 }
288 }
289
main(int argc,char ** argv)290 int main
291 (int argc, char **argv)
292 {
293 assert(((argc > 0) && (argv != NULL)));
294 assert(init_libTMCG());
295
296 try
297 {
298 BarnettSmartVTMF_dlog *vtmf;
299 std::stringstream vtmf_str;
300
301 // create and check VTMF instance (CRS)
302 std::cout << "BarnettSmartVTMF_dlog()" << std::endl;
303 vtmf = new BarnettSmartVTMF_dlog();
304 std::cout << "vtmf.CheckGroup()" << std::endl;
305 start_clock();
306 assert(vtmf->CheckGroup());
307 stop_clock();
308 std::cout << elapsed_time() << std::endl;
309
310 // publish VTMF instance as string stream
311 std::cout << "vtmf.PublishGroup(vtmf_str)" << std::endl;
312 vtmf->PublishGroup(vtmf_str);
313
314 // open pipes
315 for (size_t i = 0; i < PLAYERS; i++)
316 {
317 for (size_t j = 0; j < PLAYERS; j++)
318 {
319 if (pipe(pipefd[i][j]) < 0)
320 perror("t-poker-cutnchoose (pipe)");
321 }
322 }
323
324 // start poker childs
325 for (size_t i = 0; i < PLAYERS; i++)
326 start_instance(vtmf_str, i);
327
328 // wait for poker childs and close pipes
329 bool result = true;
330 for (size_t i = 0; i < PLAYERS; i++)
331 {
332 int wstatus = 0;
333 std::cerr << "waitpid(" << pid[i] << ")" << std::endl;
334 if (waitpid(pid[i], &wstatus, 0) != pid[i])
335 perror("t-poker-cutnchoose (waitpid)");
336 if (!WIFEXITED(wstatus))
337 {
338 std::cerr << "ERROR: ";
339 if (WIFSIGNALED(wstatus))
340 {
341 std::cerr << pid[i] << " terminated by signal " <<
342 WTERMSIG(wstatus) << std::endl;
343 }
344 if (WCOREDUMP(wstatus))
345 std::cerr << pid[i] << " dumped core" << std::endl;
346 result = false;
347 }
348 for (size_t j = 0; j < PLAYERS; j++)
349 {
350 if ((close(pipefd[i][j][0]) < 0) || (close(pipefd[i][j][1]) < 0))
351 perror("t-poker-cutnchoose (close)");
352 }
353 }
354
355 // release VTMF instance
356 delete vtmf;
357
358 if (result)
359 return 0;
360 else
361 return 1;
362 }
363 catch (std::exception& e)
364 {
365 std::cerr << "exception catched with what = " << e.what() << std::endl;
366 return -1;
367 }
368 }
369
370 #else
371
main(int argc,char ** argv)372 int main
373 (int argc, char **argv)
374 {
375 assert(((argc > 0) && (argv != NULL)));
376 std::cout << "test skipped" << std::endl;
377 return 77;
378 }
379
380 #endif
381
382