preproc.cpp 5.2 KB

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