preproc.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #include <vector>
  2. #include <bsd/stdlib.h> // arc4random_buf
  3. #include "types.hpp"
  4. #include "preproc.hpp"
  5. // Open a file for writing with name the given prefix, and ".pX.tY"
  6. // suffix, where X is the (one-digit) player number and Y is the thread
  7. // number
  8. static std::ofstream openfile(const char *prefix, unsigned player,
  9. unsigned thread_num)
  10. {
  11. std::string filename(prefix);
  12. char suffix[20];
  13. sprintf(suffix, ".p%d.t%u", player%10, thread_num);
  14. filename.append(suffix);
  15. std::ofstream f;
  16. f.open(filename);
  17. if (f.fail()) {
  18. std::cerr << "Failed to open " << filename << "\n";
  19. exit(1);
  20. }
  21. return f;
  22. }
  23. // The server-to-computational-peer protocol for sending precomputed
  24. // data is:
  25. //
  26. // One byte: type
  27. // 0x80: Multiplication triple
  28. // 0x81: Multiplication half-triple
  29. // 0x01 to 0x40: DPF of that depth
  30. // 0x00: End of preprocessing
  31. //
  32. // Four bytes: number of objects of that type (not sent for type == 0x00)
  33. //
  34. // Then that number of objects
  35. //
  36. // Repeat the whole thing until type == 0x00 is received
  37. void preprocessing_comp(MPCIO &mpcio, int num_threads, char **args)
  38. {
  39. boost::asio::thread_pool pool(num_threads);
  40. for (int thread_num = 0; thread_num < num_threads; ++thread_num) {
  41. boost::asio::post(pool, [&mpcio, thread_num] {
  42. MPCTIO tio(mpcio, thread_num);
  43. while(1) {
  44. unsigned char type = 0;
  45. unsigned int num = 0;
  46. size_t res = tio.recv_server(&type, 1);
  47. if (res < 1 || type == 0) break;
  48. tio.recv_server(&num, 4);
  49. if (type == 0x80) {
  50. // Multiplication triples
  51. std::ofstream tripfile = openfile("triples",
  52. mpcio.player, thread_num);
  53. MultTriple T;
  54. for (unsigned int i=0; i<num; ++i) {
  55. res = tio.recv_server(&T, sizeof(T));
  56. if (res < sizeof(T)) break;
  57. tripfile.write((const char *)&T, sizeof(T));
  58. }
  59. tripfile.close();
  60. } else if (type == 0x81) {
  61. // Multiplication half triples
  62. std::ofstream halffile = openfile("halves",
  63. mpcio.player, thread_num);
  64. HalfTriple H;
  65. for (unsigned int i=0; i<num; ++i) {
  66. res = tio.recv_server(&H, sizeof(H));
  67. if (res < sizeof(H)) break;
  68. halffile.write((const char *)&H, sizeof(H));
  69. }
  70. halffile.close();
  71. }
  72. }
  73. });
  74. }
  75. pool.join();
  76. }
  77. // Create triples (X0,Y0,Z0),(X1,Y1,Z1) such that
  78. // (X0*Y1 + Y0*X1) = (Z0+Z1)
  79. static void create_triples(MPCTIO &stio, unsigned num)
  80. {
  81. for (unsigned int i=0; i<num; ++i) {
  82. value_t X0, Y0, Z0, X1, Y1, Z1;
  83. arc4random_buf(&X0, sizeof(X0));
  84. arc4random_buf(&Y0, sizeof(Y0));
  85. arc4random_buf(&Z0, sizeof(Z0));
  86. arc4random_buf(&X1, sizeof(X1));
  87. arc4random_buf(&Y1, sizeof(Y1));
  88. Z1 = X0 * Y1 + X1 * Y0 - Z0;
  89. MultTriple T0, T1;
  90. T0 = std::make_tuple(X0, Y0, Z0);
  91. T1 = std::make_tuple(X1, Y1, Z1);
  92. stio.queue_p0(&T0, sizeof(T0));
  93. stio.queue_p1(&T1, sizeof(T1));
  94. }
  95. }
  96. // Create half-triples (X0,Z0),(Y1,Z1) such that
  97. // X0*Y1 = Z0 + Z1
  98. static void create_halftriples(MPCTIO &stio, unsigned num)
  99. {
  100. for (unsigned int i=0; i<num; ++i) {
  101. value_t X0, Z0, Y1, Z1;
  102. arc4random_buf(&X0, sizeof(X0));
  103. arc4random_buf(&Z0, sizeof(Z0));
  104. arc4random_buf(&Y1, sizeof(Y1));
  105. Z1 = X0 * Y1 - Z0;
  106. HalfTriple H0, H1;
  107. H0 = std::make_tuple(X0, Z0);
  108. H1 = std::make_tuple(Y1, Z1);
  109. stio.queue_p0(&H0, sizeof(H0));
  110. stio.queue_p1(&H1, sizeof(H1));
  111. }
  112. }
  113. void preprocessing_server(MPCServerIO &mpcsrvio, int num_threads, char **args)
  114. {
  115. boost::asio::thread_pool pool(num_threads);
  116. for (int thread_num = 0; thread_num < num_threads; ++thread_num) {
  117. boost::asio::post(pool, [&mpcsrvio, thread_num, args] {
  118. char **threadargs = args;
  119. MPCTIO stio(mpcsrvio, thread_num);
  120. while (*threadargs) {
  121. char *arg = strdup(*threadargs);
  122. char *colon = strchr(arg, ':');
  123. if (!colon) {
  124. std::cerr << "Args must be type:num\n";
  125. ++threadargs;
  126. free(arg);
  127. continue;
  128. }
  129. unsigned num = atoi(colon+1);
  130. *colon = '\0';
  131. char *type = arg;
  132. if (!strcmp(type, "t")) {
  133. unsigned char typetag = 0x80;
  134. stio.queue_p0(&typetag, 1);
  135. stio.queue_p0(&num, 4);
  136. stio.queue_p1(&typetag, 1);
  137. stio.queue_p1(&num, 4);
  138. create_triples(stio, num);
  139. } else if (!strcmp(type, "h")) {
  140. unsigned char typetag = 0x81;
  141. stio.queue_p0(&typetag, 1);
  142. stio.queue_p0(&num, 4);
  143. stio.queue_p1(&typetag, 1);
  144. stio.queue_p1(&num, 4);
  145. create_halftriples(stio, num);
  146. }
  147. free(arg);
  148. ++threadargs;
  149. }
  150. // That's all
  151. unsigned char typetag = 0x00;
  152. stio.queue_p0(&typetag, 1);
  153. stio.queue_p1(&typetag, 1);
  154. stio.send();
  155. });
  156. }
  157. pool.join();
  158. }