preprocessing.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. #include <type_traits> // std::is_same<>
  2. #include <limits> // std::numeric_limits<>
  3. #include <climits> // CHAR_BIT
  4. #include <cmath> // std::log2, std::ceil, std::floor
  5. #include <stdexcept> // std::runtime_error
  6. #include <array> // std::array<>
  7. #include <iostream> // std::istream and std::ostream
  8. #include <vector> // std::vector<>
  9. #include <memory> // std::shared_ptr<>
  10. #include <utility> // std::move
  11. #include <algorithm> // std::copy
  12. #include <cstring> // std::memcpy
  13. #include <bsd/stdlib.h> // arc4random_buf
  14. #include <x86intrin.h> // SSE and AVX intrinsics
  15. #include <../boost/asio/thread_pool.hpp>
  16. #include <../boost/lexical_cast.hpp>
  17. #include <../boost/asio.hpp>
  18. #include <fcntl.h>
  19. #include <cstdlib>
  20. #include <chrono>
  21. #include <sys/mman.h>
  22. #include <sys/stat.h>
  23. #include <fstream>
  24. #include <future>
  25. #include <mutex>
  26. typedef __m128i node_t;
  27. constexpr size_t leaf_size = 1;
  28. typedef __m128i leaf_type;
  29. typedef std::array<leaf_type, leaf_size> leaf_t;
  30. size_t communication_cost = 0;
  31. #include "bitutils.h"
  32. #include "block.h"
  33. #include "prg_aes_impl.h"
  34. #include "filesio.h"
  35. using boost::asio::ip::tcp;
  36. using socket_t = boost::asio::ip::tcp::socket;
  37. using namespace dpf; // The namespace is found in bitutils.h
  38. #include "mpc.h"
  39. #include "network.h"
  40. #include "dpfgen.h"
  41. #include "share-conversion.h"
  42. int main(int argc, char * argv[])
  43. {
  44. boost::asio::io_context io_context;
  45. std::string addr = "127.0.0.1";
  46. const std::string host1 = (argc < 2) ? "127.0.0.1" : argv[1];
  47. const std::string host2 = (argc < 3) ? "127.0.0.1" : argv[2];
  48. const size_t n_threads = atoi(argv[3]);
  49. const size_t expo = atoi(argv[4]);
  50. const size_t op = atoi(argv[5]);
  51. const size_t number_of_sockets = 5 * n_threads;
  52. std::vector<socket_t> socketsPb, socketsP2;
  53. std::vector<int> ports, ports2_1, ports2_0;
  54. bool party;
  55. /* The function make_connections appears in network.h */
  56. make_connections(party, host1, host2, io_context, socketsPb, socketsP2, ports, ports2_1, ports2_0, number_of_sockets);
  57. const size_t db_nitems = 1ULL << atoi(argv[4]);
  58. uint8_t ** target_share_read = new uint8_t*[n_threads];
  59. generate_random_targets(target_share_read, n_threads, party, expo);
  60. AES_KEY aeskey;
  61. __m128i * final_correction_word = (__m128i *) std::aligned_alloc(sizeof(__m256i), n_threads * sizeof(__m128i));
  62. __m128i ** output = (__m128i ** ) malloc(sizeof(__m128i *) * n_threads);
  63. int8_t ** flags = (int8_t ** ) malloc(sizeof(uint8_t *) * n_threads);
  64. for(size_t j = 0; j < n_threads; ++j)
  65. {
  66. output[j] = (__m128i *)std::aligned_alloc(sizeof(node_t), db_nitems * sizeof(__m128i));
  67. flags[j] = (int8_t *)std::aligned_alloc(sizeof(node_t), db_nitems * sizeof(uint8_t));
  68. }
  69. boost::asio::thread_pool pool_share_conversion(n_threads);
  70. // The following function call creates and evaluates DPFs at target_share_read[j] for j \in \{0, \ldots, n_threads}
  71. // the flag vectors are stored in flags
  72. // the leaves are stored in output
  73. // the final correctionword is stored in final_correction_word
  74. dpfP2 * dpf_instance = (dpfP2 * ) malloc (sizeof(dpfP2) * n_threads);
  75. cw_construction computecw_array;
  76. auto start = std::chrono::steady_clock::now();
  77. boost::asio::read(socketsP2[0], boost::asio::buffer(&computecw_array, sizeof(computecw_array)));
  78. #ifdef VERBOSE
  79. std::cout << "computecw_array.rand_b: " << computecw_array.rand_b[0] << " " << computecw_array.rand_b[1] << std::endl;
  80. #endif
  81. /* The function create_dpfs appears in dpf-gen.h*/
  82. bool reading = true;
  83. boost::asio::thread_pool pool(n_threads);
  84. for(size_t j = 0; j < n_threads; ++j)
  85. {
  86. boost::asio::post(pool, std::bind(create_dpfs, reading, db_nitems, std::ref(aeskey), target_share_read[j], std::ref(socketsPb), std::ref(socketsP2), 0, db_nitems-1,
  87. output[j], flags[j], std::ref(final_correction_word[j]), computecw_array, std::ref(dpf_instance), party, 5 * j, j));
  88. }
  89. pool.join();
  90. bool interleaved = false;
  91. if(op == 1) interleaved = true;
  92. if(interleaved)
  93. {
  94. boost::asio::thread_pool pool2(n_threads);
  95. for(size_t j = 0; j < n_threads; ++j)
  96. {
  97. boost::asio::post(pool2, std::bind(create_dpfs, reading, db_nitems, std::ref (aeskey), target_share_read[j], std::ref(socketsPb), std::ref(socketsP2), 0, db_nitems-1,
  98. output[j], flags[j], std::ref(final_correction_word[j]), computecw_array, std::ref(dpf_instance), party, 5 * j, j));
  99. }
  100. pool2.join();
  101. }
  102. boost::asio::write(socketsP2[0], boost::asio::buffer(dpf_instance, n_threads * sizeof(dpfP2))); // do this in parallel.
  103. #ifdef DEBUG
  104. for(size_t j = 0; j < n_threads; ++j)
  105. {
  106. std::cout << "n_threads = " << j << std::endl;
  107. for(size_t i = 0; i < db_nitems; ++i)
  108. {
  109. int8_t flags_reconstruction;
  110. boost::asio::write(socketsPb[0], boost::asio::buffer(&flags[j][i], sizeof(flags[j][i])));
  111. boost::asio::read(socketsPb[0], boost::asio::buffer(&flags_reconstruction, sizeof(flags_reconstruction)));
  112. flags_reconstruction -= flags[j][i];
  113. if(flags_reconstruction != 0) std::cout << i << " (flag) ---> " << (int) flags_reconstruction << std::endl;
  114. int64_t output_reconstruction;
  115. boost::asio::write(socketsPb[0], boost::asio::buffer(&output[j][i][0], sizeof(output[j][i][0])));
  116. boost::asio::read(socketsPb[0], boost::asio::buffer(&output_reconstruction, sizeof(output_reconstruction)));
  117. output_reconstruction -= output[j][i][0];
  118. if(output_reconstruction != 0) std::cout << i << " (output) ---> " << output_reconstruction << std::endl;
  119. }
  120. int64_t final_correction_word_reconstruction = 0;
  121. boost::asio::write(socketsPb[0], boost::asio::buffer(&final_correction_word[j][0], sizeof(final_correction_word[j][0])));
  122. boost::asio::read(socketsPb[0], boost::asio::buffer(&final_correction_word_reconstruction, sizeof(final_correction_word_reconstruction)));
  123. final_correction_word_reconstruction = final_correction_word_reconstruction + final_correction_word[j][0];
  124. std::cout << "final_correction_word_reconstruction = " << final_correction_word_reconstruction << std::endl << std::endl;
  125. }
  126. #endif
  127. /*
  128. leaves is a additive shares of the outputs (leaves of the DPF)
  129. leafbits is the additive shares of flag bits of the DPFs
  130. */
  131. int64_t ** leaves = (int64_t ** ) malloc(sizeof(int64_t *) * n_threads);
  132. int64_t ** leafbits = (int64_t ** ) malloc(sizeof(int64_t *) * n_threads);
  133. for(size_t j = 0; j < n_threads; ++j)
  134. {
  135. leaves[j] = (int64_t *)std::aligned_alloc(sizeof(node_t), db_nitems * sizeof(int64_t));
  136. leafbits[j] = (int64_t *)std::aligned_alloc(sizeof(node_t), db_nitems * sizeof(int64_t));
  137. }
  138. /* The function convert_shares appears in share-conversion.h */
  139. for(size_t j = 0; j < n_threads; ++j)
  140. {
  141. boost::asio::post(pool_share_conversion, std::bind(convert_shares, j, output, flags, n_threads, db_nitems, final_correction_word, leaves, leafbits,
  142. std::ref(socketsPb), std::ref(socketsP2), party));
  143. }
  144. pool_share_conversion.join();
  145. boost::asio::thread_pool pool_xor_to_additive(n_threads);
  146. std::array<int64_t, 128> additve_shares;
  147. for(size_t j = 0; j < n_threads; ++j)
  148. {
  149. boost::asio::post(pool_xor_to_additive, std::bind(xor_to_additive, party, target_share_read[j], std::ref(socketsPb[j]), std::ref(socketsP2[j]), expo, std::ref(additve_shares[j])));
  150. }
  151. pool_xor_to_additive.join();
  152. auto end = std::chrono::steady_clock::now();
  153. std::chrono::duration<double> elapsed_seconds = end-start;
  154. std::cerr << "time to generate and evaluate " << n_threads << " dpfs of size 2^" << atoi(argv[4]) << " is: " << elapsed_seconds.count() << "s\n";
  155. std::cout << elapsed_seconds.count() << std::endl;
  156. start = std::chrono::steady_clock::now();
  157. for(size_t i = 0; i < n_threads; ++i)
  158. {
  159. write_evalfull_outs_into_a_file(party, i, db_nitems, flags[i], leaves[i], final_correction_word[i], additve_shares[i]);
  160. }
  161. end = std::chrono::steady_clock::now();
  162. elapsed_seconds = end-start;
  163. std::cerr << "communication cost = " << communication_cost << " bytes" << std::endl;
  164. #ifdef VERBOSE
  165. for(size_t j = 0; j < n_threads; ++j)
  166. {
  167. int64_t add_;
  168. boost::asio::write(socketsPb[0], boost::asio::buffer(&additve_shares[j], sizeof(additve_shares[j])));
  169. boost::asio::read(socketsPb[0], boost::asio::buffer(&add_, sizeof(add_)));
  170. add_ = add_ + additve_shares[j];
  171. std::cout << "add_ = " << add_ << std::endl;
  172. }
  173. #endif
  174. return 0;
  175. }