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