A *point function* is a huge list of zeros with one non-zero entry. The index of that entry is secret. The value there is secret too. A *(2,2) distributed point function* splits that list between two parties. Each party gets a short key. Either key alone looks random. When both parties evaluate at the same public input and combine their shares, they recover the true value of the point function there. ## Point functions {#point_functions} Write `f_{α,β}` for the function that returns `β` at `α` and `0` elsewhere. `make_dpf(α, β)` returns keys `(k0, k1)` such that: - `Eval(k0, x)` and `Eval(k1, x)` are shares of `f_{α,β}(x)` - `|k_i|` is about `O(λ · log |domain|)` for security parameter `λ` Leaf payloads use subtractive shares. Comparison payloads use additive shares. Open with `dpf::reconstruct`. ## What you pass to `make_dpf` {#make_dpf_args} `make_dpf(x, y, ys...)` takes the secret index and one or more payloads. `dpf::at(y)` plants `y` on the public prefix of length `N`. `dpf::idpf_at(ys...)` plants one payload per listed prefix. `dpf::idpf(y0, y1, ...)` is the consecutive prefixes 1, 2, …. Read a slot with `dpf::eval_point(dpf::out, key, x)`, or `dpf::out` when `W` is that slot's prefix. \code{cpp} auto [k0, k1] = dpf::make_dpf( std::uint8_t{0x2a}, dpf::at<4>(std::uint8_t{5}), std::uint8_t{9}); auto hi = *dpf::eval_point(dpf::out<0, 4>, k0, std::uint8_t{0x2a}); \endcode A comparison payload is `dpf::lt`, `dpf::leq`, `dpf::gt`, or `dpf::geq`. The same four names with `_at` sit on a prefix. Evaluate that channel with `dpf::cmp`. See [Comparisons and ranges](@ref tour_dcf). Let `n` be the input bit length and `λ` the seed width. The key from `make_dpf` is `Θ(n λ)` bits plus the payloads, and `eval_point` expands `n` levels. That is the Boyle–Gilboa–Ishai CCS 2016 point key (full version [ePrint 2018/707](@ref bib_fss2018)): one correction word per level, not their [EUROCRYPT 2015](@ref bib_fss2015) key of `4n(λ+1)` bits. For a small output group `G`, Remark 3.4 of that full version stops `ν = log2(λ / log2|G|)` levels early and shortens the key by `ν(λ+2)` bits. This generator does that: the tree depth is `n` minus the log of how many copies of `G` fit in one leaf, and those low bits select the lane. Boyle, Gilboa, Ishai, and Kolobov ([ePrint 2023/028](@ref bib_itdpf)) give a statistically private 3-server DPF and a perfectly private 4-server DPF; `dpf::make_it_dpf3` is the additive three-server interface on a `uint8_t` domain. `make_dpf` is a 2-party PRG key. Interval, sequence, and full-domain costs are on [Evaluating DPFs](@ref evaluation). Width literals (`100_u12`, `7_x12`, `1.5_fixed16`, `1_bit`, `2_twobit`, `10_nyble`, `_bitstring`) are documented with the types that use them: [Input types](@ref input_types), [Output types](@ref output_types). **Defined in**\n @ref dpf/dpf_key.hpp, @ref dpf/placement.hpp, @ref dpf/eval_target.hpp ## DPF Trees {#dpf_trees} Keys store a seed and a list of *correction words*. Evaluation walks a binary tree from the root toward `x`. At each level a correction word mixes the two children so only the secret path keeps differing seeds. Off-path nodes match and cancel when the parties combine. Classic keys use a Boyle–Gilboa–Ishai expand (CCS 2016, full version [ePrint 2018/707](@ref bib_fss2018)). Half-Tree keys (CCR interior PRG) follow Guo, Yang, Wang, Zhang, Xie, Zhang, and Liu, [ePrint 2022/1431](@ref bib_halftree): mid-level children are `H(s)` and `H(s) XOR s`. Their dealer point key keeps the CCS 2016 length and the `n`-hash point evaluation; they state about `2n+2` random-permutation calls to generate a key versus about `4n`, and `1.5N` calls for a full-domain evaluation versus `2N`. See [tree_traits.hpp](@ref dpf/tree_traits.hpp). For a slow, friendly walk through every feature, start at the [guided tour](@ref guided_tour).