dpf.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. /* Copyright (C) 2019 Anonymous
  2. *
  3. * This is a pre-release version of the DPF++ library distributed anonymously
  4. * for peer review. A public release of the software will be published under the
  5. * LPGL v2.1 license in the near future. Please do not redistribute this version
  6. * of the software.
  7. */
  8. // #ifndef DPFPP_DPF_H__
  9. // #define DPFPP_DPF_H__
  10. // #include <type_traits> // std::is_same<>
  11. // #include <limits> // std::numeric_limits<>
  12. // #include <climits> // CHAR_BIT
  13. // #include <cmath> // std::log2, std::ceil, std::floor
  14. // #include <stdexcept> // std::runtime_error
  15. // #include <array> // std::array<>
  16. // #include <iostream> // std::istream and std::ostream
  17. // #include <vector> // std::vector<>
  18. // #include <memory> // std::shared_ptr<>
  19. // #include <utility> // std::move
  20. // #include <algorithm> // std::copy
  21. // #include <cstring> // std::memcpy
  22. // #include <bsd/stdlib.h> // arc4random_buf
  23. // #include <x86intrin.h> // SSE and AVX intrinsics
  24. // #include <boost/asio/thread_pool.hpp>
  25. // #include "bitutils.h"
  26. // #include "../block.h"
  27. // #include "prg.h"
  28. // #include "prg_aes_impl.h"
  29. // constexpr int L = 0;
  30. // constexpr int R = 1;
  31. // const size_t ncores = 16;
  32. // uint64_t progress[ncores] = {0};
  33. // namespace dpf
  34. // {
  35. // template <typename node_t>
  36. // node_t init_val(uint64_t val);
  37. // template <> __m128i init_val(uint64_t val) { return _mm_set_epi64x(0, val); }
  38. // template <> __m256i init_val(uint64_t val) { return _mm256_set_epi64x(0, 0, 0, val); }
  39. // // template<typename leaf_t = bool, typename node_t = __m128i, typename prgkey_t = lowmc::lowmc<128,29, 11>>
  40. // // struct dpf_key;
  41. // template<typename leaf_t = __m128i, typename node_t = __m128i, typename leaf_type = __m128i, typename prgkey_t = AES_KEY>
  42. // struct dpf_key;
  43. // template<typename leaf_t = bool, typename node_t = __m128i, typename prgkey_t = lowmc::bitsliced_lowmc<128,29, 11,256>>
  44. // struct bitsliced_dpf_key;
  45. // using slicerow_t = block<__m256i>;
  46. // using sliceblock_t = std::array<slicerow_t, 128>;
  47. // template<typename leaf_t, typename node_t, typename prgkey_t>
  48. // inline leaf_t eval(const dpf_key <leaf_t, node_t, prgkey_t> & dpfkey, const size_t input);
  49. // template<typename leaf_t, typename node_t, typename prgkey_t>
  50. // inline void evalinterval(const dpf_key<leaf_t, node_t, prgkey_t> & dpfkey, const size_t from, const size_t to, leaf_t * output, uint8_t * t = NULL);
  51. // template<typename leaf_t, typename node_t, typename prgkey_t>
  52. // inline void evalfull(const dpf_key<leaf_t, node_t, prgkey_t> & dpfkey, leaf_t * output, uint8_t * t = NULL);
  53. // template<typename node_t, typename prgkey_t>
  54. // static inline void expand(const prgkey_t & prgkey, const node_t & seed, node_t s[2], uint8_t t[2], int lsbmask = 0b11)
  55. // {
  56. // dpf::PRG(prgkey, clear_lsb(seed, 0b11), s, 2);
  57. // t[L] = get_lsb(s[L]);
  58. // s[L] = clear_lsb(s[L], lsbmask);
  59. // t[R] = get_lsb(s[R]);
  60. // s[R] = clear_lsb(s[R], lsbmask);
  61. // } // dpf::expand
  62. // template<typename node_t, typename prgkey_t>
  63. // static inline void traverse2(const prgkey_t & prgkey, const node_t & seed,
  64. // const uint8_t cw_t[2], const node_t & cw, const uint8_t prev_t,
  65. // node_t s[2], uint8_t t[2], int lsbmask = 0b11)
  66. // {
  67. // dpf::PRG(prgkey, clear_lsb(seed, 0b11), s, 2);
  68. // t[L] = get_lsb(s[L]) ^ (cw_t[L] & prev_t);;
  69. // s[L] = clear_lsb(xor_if(s[L], cw, !prev_t), lsbmask);
  70. // t[R] = get_lsb(s[R]) ^ (cw_t[R] & prev_t);;
  71. // s[R] = clear_lsb(xor_if(s[R], cw, !prev_t), lsbmask);
  72. // } // dpf::expand
  73. // template<typename node_t, typename prgkey_t>
  74. // static inline void traverse(const prgkey_t & prgkey, const node_t & seed, const bool direction,
  75. // const uint8_t cw_t, const node_t & cw, const uint8_t prev_t,
  76. // node_t & s, uint8_t & t, int lsbmask = 0b11)
  77. // {
  78. // dpf::PRG(prgkey, clear_lsb(seed, 0b11), &s, 1, direction);
  79. // t = get_lsb(s) ^ (cw_t & prev_t);
  80. // s = clear_lsb(xor_if(s, cw, !prev_t), lsbmask);
  81. // } // dpf::traverse
  82. // template<typename finalizer_t, typename prgkey_t>
  83. // static inline void stretch_leaf(const prgkey_t & prgkey, const typename finalizer_t::value_type & seed, finalizer_t & s)
  84. // {
  85. // dpf::PRG(prgkey, clear_lsb(seed, 0b11), &s, s.size());
  86. // } // dpf::stretch_leaf
  87. // template<typename leaf_t, typename node_t, typename leaf_type, typename prgkey_t>
  88. // struct dpf_key final
  89. // {
  90. // public:
  91. // static constexpr size_t bits_per_leaf = std::is_same<leaf_t, bool>::value ? 1 : sizeof(leaf_t) * CHAR_BIT;
  92. // static constexpr bool is_packed = (sizeof(leaf_t) < sizeof(node_t));
  93. // static constexpr size_t leaves_per_node = dpf_key::is_packed ? sizeof(node_t) * CHAR_BIT / bits_per_leaf : 1;
  94. // static constexpr size_t nodes_per_leaf = dpf_key::is_packed ? 1 : std::ceil(static_cast<double>(bits_per_leaf) / (sizeof(node_t) * CHAR_BIT));
  95. // static_assert(leaves_per_node * bits_per_leaf == sizeof(node_t) * CHAR_BIT
  96. // || nodes_per_leaf * sizeof(node_t) == sizeof(leaf_t));
  97. // using finalizer_t = std::array<node_t, nodes_per_leaf>;
  98. // typedef std::pair<finalizer_t, finalizer_t> (*finalizer_callback)(const prgkey_t &, const size_t, const leaf_t &, const node_t[2], const uint8_t[2]);
  99. // inline static constexpr size_t depth(const size_t nitems) { return std::ceil(std::log2(std::ceil(static_cast<double>(nitems) / dpf_key::leaves_per_node))); }
  100. // inline constexpr size_t depth() const { return dpf_key::depth(nitems); }
  101. // inline static constexpr size_t input_bits(const size_t nitems) { return std::ceil(std::log2(nitems)); }
  102. // inline constexpr size_t input_bits() const { return dpf_key::input_bits(nitems); }
  103. // inline static constexpr size_t nodes_in_interval(const size_t from, const size_t to) { return (to < from) ? 0 : std::max(1.0, std::ceil(static_cast<double>(to+1) / leaves_per_node) - std::floor(static_cast<double>(from) / leaves_per_node)); }
  104. // inline static constexpr size_t interval_bytes(const size_t from, const size_t to) { return nodes_in_interval(from, to) * (is_packed ? sizeof(node_t) : sizeof(leaf_t)); }
  105. // inline constexpr size_t full_bytes() { return interval_bytes(0, nitems-1); }
  106. // inline static constexpr size_t nodes_at_leaf_layer(const size_t nitems) { return std::ceil(static_cast<double>(nitems) / dpf_key::leaves_per_node); }
  107. // inline constexpr size_t nodes_at_leaf_layer() const { return dpf_key::nodes_at_leaf_layer(nitems); }
  108. // inline dpf_key(dpf_key &&) = default;
  109. // inline dpf_key & operator=(dpf_key &&) = default;
  110. // inline dpf_key(const dpf_key &) = default;
  111. // inline dpf_key & operator=(const dpf_key &) = default;
  112. // inline bool operator==(const dpf_key & rhs) const { return nitems == rhs.nitems && root == rhs.root && cw == rhs.cw && finalizer == rhs.finalizer; }
  113. // inline bool operator!=(const dpf_key & rhs) const { return !(*this == rhs); }
  114. // static auto default_make_finalizer(const prgkey_t & prgkey, const size_t target, const leaf_t & val, const node_t s[2], const uint8_t t[2])
  115. // {
  116. // finalizer_t finalizer;
  117. // finalizer_t stretched[2];
  118. // stretch_leaf(prgkey, s[L], stretched[L]);
  119. // stretch_leaf(prgkey, s[R], stretched[R]);
  120. // if constexpr(dpf_key::is_packed)
  121. // {
  122. // auto finalizer0 = reinterpret_cast<node_t *>(&finalizer[0]);
  123. // if constexpr(std::numeric_limits<leaf_t>::is_integer)
  124. // {
  125. // if constexpr(std::is_same<leaf_t, bool>::value)
  126. // {
  127. // *finalizer0 = (node_t)init_val<__m128i>(val ? 1 : 0);
  128. // //*finalizer0 = init_val<node_t>(val ? 1 : 0);
  129. // }
  130. // else
  131. // {
  132. // typedef typename std::make_unsigned_t<leaf_t> unsigned_leaf_t;
  133. // *finalizer0 = init_val<node_t>(static_cast<unsigned_leaf_t>(val));
  134. // }
  135. // auto tmp = reinterpret_cast<std::bitset<8*sizeof(node_t)> *>(finalizer0);
  136. // *tmp <<= bits_per_leaf * (target % leaves_per_node);
  137. // }
  138. // else
  139. // {
  140. // *finalizer0 = val;
  141. // }
  142. // }
  143. // else
  144. // {
  145. // std::memcpy(&finalizer[0], &val, sizeof(finalizer_t));
  146. // }
  147. // for (size_t j = 0; j < nodes_per_leaf; ++j)
  148. // {
  149. // finalizer[j] ^= stretched[L][j] ^ stretched[R][j];
  150. // }
  151. // return std::make_pair(finalizer, finalizer);
  152. // } // dpf_key::default_make_finalizer
  153. // static auto gen(const prgkey_t & prgkey, size_t nitems, size_t target, const leaf_t & val = 1, const finalizer_callback make_finalizer = default_make_finalizer)
  154. // {
  155. // if (nitems <= target)
  156. // {
  157. // throw std::runtime_error("target point out of range");
  158. // }
  159. // node_t root[2];
  160. // srand(1);
  161. // arc4random_buf(root, sizeof(root));
  162. // root[0][0] = rand();
  163. // root[0][1] = rand();
  164. // root[1][0] = rand();
  165. // root[1][1] = rand();
  166. // uint8_t t[2] = { get_lsb(root[0]), !t[0] };
  167. // root[1] = set_lsb(root[1], t[1]);
  168. // node_t s[2] = { root[0], root[1] };
  169. // const size_t depth = dpf_key::depth(nitems);
  170. // std::vector<node_t> cw;
  171. // cw.reserve(depth);
  172. // node_t s0[2], s1[2];
  173. // uint8_t t0[2], t1[2];
  174. // const size_t nbits = input_bits(nitems);
  175. // for (size_t layer = 0; layer < depth; ++layer)
  176. // {
  177. // const uint8_t bit = (target >> (nbits - layer - 1)) & 1U;
  178. // expand(prgkey, s[0], s0, t0);
  179. // expand(prgkey, s[1], s1, t1);
  180. // const uint8_t keep = (bit == 0) ? L : R, lose = 1 - keep;
  181. // bool cwt[2] = {
  182. // cwt[L] = t0[L] ^ t1[L] ^ bit ^ 1,
  183. // cwt[R] = t0[R] ^ t1[R] ^ bit
  184. // };
  185. // auto nextcw = s0[lose] ^ s1[lose];
  186. // s[L] = xor_if(s0[keep], nextcw, !t[L]);
  187. // t[L] = t0[keep] ^ (t[L] & cwt[keep]);
  188. // s[R] = xor_if(s1[keep], nextcw, !t[R]);
  189. // t[R] = t1[keep] ^ (t[R] & cwt[keep]);
  190. // cw.emplace_back(set_lsbs(nextcw, cwt));
  191. // }
  192. // cw.shrink_to_fit();
  193. // auto [finalizer0, finalizer1] = make_finalizer(prgkey, target, val, s, t);
  194. // return std::make_pair(
  195. // std::forward<dpf_key>(dpf_key(nitems, root[0], cw, finalizer0, prgkey)),
  196. // std::forward<dpf_key>(dpf_key(nitems, root[1], cw, finalizer1, prgkey)));
  197. // } // dpf_key::gen
  198. // inline leaf_t eval(const size_t input) const { return std::forward<leaf_t>(dpf::eval(*this, input)); }
  199. // inline void evalinterval(const size_t from, const size_t to, leaf_t * output, uint8_t * t = NULL) const { dpf::evalinterval(*this, from, to, output, t); }
  200. // inline void evalfull(leaf_t * output, uint8_t * t = NULL) const { dpf::evalfull(*this, output, t); }
  201. // const size_t nitems;
  202. // const node_t root;
  203. // const std::vector<node_t> cw;
  204. // const finalizer_t finalizer;
  205. // const prgkey_t prgkey;
  206. // private:
  207. // dpf_key(size_t nitems_, const node_t & root_, const std::vector<node_t> cw_,
  208. // const finalizer_t & finalizer_, const prgkey_t & prgkey_)
  209. // : nitems(nitems_),
  210. // root(root_),
  211. // cw(cw_),
  212. // finalizer(finalizer_),
  213. // prgkey(prgkey_) { }
  214. //}; // struct dpf::dpf_key
  215. // template<typename leaf_t, typename node_t>
  216. // inline leaf_t getword(const node_t & S, const size_t input)
  217. // {
  218. // auto S_ = reinterpret_cast<const leaf_t *>(&S);
  219. // if constexpr(sizeof(leaf_t) >= sizeof(node_t)) return *S_;
  220. // return S_[input];
  221. // } // dpf::getword
  222. // template<>
  223. // inline bool getword(const __m128i & S, const size_t input)
  224. // {
  225. // const __m128i mask = bool128_mask[input / 64];
  226. // __m128i vcmp = _mm_xor_si128(_mm_and_si128(S >> (input % 64), mask), mask);
  227. // return static_cast<bool>(_mm_testz_si128(vcmp, vcmp));
  228. // } // dpf::getword<__m128i,bool>
  229. // template<>
  230. // inline bool getword(const __m256i & S, const size_t input)
  231. // {
  232. // const __m256i mask = bool256_mask[input / 64];
  233. // __m256i vcmp = _mm256_xor_si256(_mm256_and_si256(S >> (input % 64), mask), mask);
  234. // return static_cast<bool>(_mm256_testz_si256(vcmp, vcmp));
  235. // } // dpf::getword<__m256i,bool>
  236. // template<typename leaf_t, typename node_t, typename prgkey_t>
  237. // inline void finalize(const prgkey_t & prgkey, std::array<node_t, dpf_key<leaf_t, node_t, prgkey_t>::nodes_per_leaf> finalizer, leaf_t * output, node_t * s, size_t nnodes, uint8_t * t)
  238. // {
  239. // auto output_ = reinterpret_cast<std::array<node_t, dpf_key<leaf_t, node_t, prgkey_t>::nodes_per_leaf> *>(output);
  240. // for (size_t i = 0; i < nnodes; ++i)
  241. // {
  242. // stretch_leaf(prgkey, s[i], output_[i]);
  243. // for (size_t j = 0; j < dpf_key<leaf_t, node_t, prgkey_t>::nodes_per_leaf; ++j)
  244. // {
  245. // output_[i][j] = xor_if(output_[i][j], finalizer[j], t[i]);
  246. // }
  247. // }
  248. // } // dpf::finalize
  249. // template<typename leaf_t, typename node_t, typename prgkey_t>
  250. // inline void __evalinterval(const dpf_key<leaf_t, node_t, prgkey_t> & dpfkey, const size_t from, const size_t to, leaf_t * output, uint8_t * _t)
  251. // {
  252. // auto nodes_per_leaf = dpfkey.nodes_per_leaf;
  253. // auto depth = dpfkey.depth();
  254. // auto nbits = dpfkey.input_bits();
  255. // auto nodes_in_interval = dpfkey.nodes_in_interval(from, to);
  256. // auto root = dpfkey.root;
  257. // auto prgkey = dpfkey.prgkey;
  258. // const size_t from_node = std::floor(static_cast<double>(from) / nodes_per_leaf);
  259. // node_t * s[2] = {
  260. // reinterpret_cast<node_t *>(output) + nodes_in_interval * (nodes_per_leaf - 1),
  261. // s[0] + nodes_in_interval / 2
  262. // };
  263. // uint8_t * t[2] = { _t, _t + nodes_in_interval / 2};
  264. // int curlayer = depth % 2;
  265. // s[curlayer][0] = root;
  266. // t[curlayer][0] = get_lsb(root, 0b01);
  267. // //printf("depth = %u\n", depth);
  268. // for (size_t layer = 0; layer < depth; ++layer)
  269. // {
  270. // auto & cw = dpfkey.cw[layer];
  271. // uint8_t cw_t[2] = { get_lsb(cw, 0b01), get_lsb(cw, 0b10) };
  272. // curlayer = 1-curlayer;
  273. // size_t i=0, j=0;
  274. // auto nextbit = (from_node >> (nbits-layer-1)) & 1;
  275. // size_t nodes_in_prev_layer = std::ceil(static_cast<double>(nodes_in_interval) / (1ULL << (depth-layer)));
  276. // size_t nodes_in_cur_layer = std::ceil(static_cast<double>(nodes_in_interval) / (1ULL << (depth-layer-1)));
  277. // //printf("nextbit = %u\n", (from_node >> (nbits-layer-1)));
  278. // if (nextbit == 1) traverse(prgkey, s[1-curlayer][0], R, cw_t[R], cw, t[1-curlayer][j], s[curlayer][0], t[curlayer][0]); // these will not be called in evalfull
  279. // for (i = nextbit, j = nextbit; j < nodes_in_prev_layer-1; ++j, i+=2)
  280. // {
  281. // //printf("j = %u\n", j );
  282. // traverse2(prgkey, s[1-curlayer][j], cw_t, cw, t[1-curlayer][j], &s[curlayer][i], &t[curlayer][i]);
  283. // }
  284. // if (nodes_in_prev_layer > j)
  285. // {
  286. // //printf("jj' = %u\n", j );
  287. // if (i < nodes_in_cur_layer - 1)
  288. // {
  289. // traverse2(prgkey, s[1-curlayer][j], cw_t, cw, t[1-curlayer][j], &s[curlayer][i], &t[curlayer][i]);
  290. // //printf("If\n");
  291. // }
  292. // else
  293. // {
  294. // traverse(prgkey, s[1-curlayer][j], L, cw_t[L], cw, t[1-curlayer][j], s[curlayer][i], t[curlayer][i]); // will not be called in evalfull
  295. // // printf("else\n");
  296. // }
  297. // }
  298. // }
  299. // finalize(prgkey, dpfkey.finalizer, output, s[0], nodes_in_interval, t[0]);
  300. // } // dpf::__evalinterval
  301. // template<typename leaf_t, typename node_t, typename prgkey_t>
  302. // inline void evalinterval(const dpf_key<leaf_t, node_t, prgkey_t> & dpfkey, const size_t from, const size_t to, leaf_t * output, uint8_t * t)
  303. // {
  304. // uint8_t * tt = t ? t : reinterpret_cast<uint8_t *>(malloc(dpfkey.nodes_in_interval(from, to) * sizeof(uint8_t)));
  305. // __evalinterval(dpfkey, from, to, output, tt);
  306. // if (!t) free(tt);
  307. // } // dpf::evalinterval
  308. // template<typename leaf_t, typename node_t, typename prgkey_t>
  309. // inline void evalfull(const dpf_key<leaf_t, node_t, prgkey_t> & dpfkey, leaf_t * output, uint8_t * t)
  310. // {
  311. // uint8_t * tt = t ? t : reinterpret_cast<uint8_t *>(malloc(dpfkey.nodes_at_leaf_layer() * sizeof(uint8_t)));
  312. // __evalinterval(dpfkey, 0, dpfkey.nitems-1, output, tt);
  313. // if (!t) free(tt);
  314. // } // dpf::evalfull
  315. // template<typename leaf_t, typename node_t, typename prgkey_t>
  316. // inline leaf_t eval(const dpf_key<leaf_t, node_t, prgkey_t> & dpfkey, const size_t input)
  317. // {
  318. // auto prgkey = dpfkey.prgkey;
  319. // auto root = dpfkey.root;
  320. // auto depth = dpfkey.depth();
  321. // auto nbits = dpfkey.input_bits();
  322. // node_t S = root;
  323. // uint8_t T = get_lsb(root, 0b01);
  324. // for (size_t layer = 0; layer < depth; ++layer)
  325. // {
  326. // auto & cw = dpfkey.cw[layer];
  327. // const uint8_t nextbit = (input >> (nbits-layer-1)) & 1;
  328. // traverse(prgkey, S, nextbit, get_lsb(cw, nextbit ? 0b10 : 0b01), cw, T, S, T);
  329. // }
  330. // std::array<node_t, dpf_key<leaf_t, node_t, prgkey_t>::nodes_per_leaf> final;
  331. // finalize(prgkey, dpfkey.finalizer, &final, &S, 1, &T);
  332. // if constexpr(dpfkey.is_packed)
  333. // {
  334. // auto S_ = reinterpret_cast<node_t *>(&final);
  335. // return std::forward<leaf_t>(getword<leaf_t>(*S_, input % dpfkey.leaves_per_node));
  336. // }
  337. // else
  338. // {
  339. // auto ret = reinterpret_cast<leaf_t *>(&final);
  340. // return *ret;
  341. // }
  342. // // } // dpf::eval
  343. // } // namespace dpf
  344. //#endif // DPFPP_DPF_H