Checkpoint the party/runtime stack before share-program and malicious-mode work.
Ship the TLS mesh, composer, Beaver/Yao/leaf MPC, prep/online paths, apps, and docs so the tree is pushable before elevating share_expr, security_mode, and prep resume. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
695f8e84f7
commit
0d22946a0e
1835 changed files with 170291 additions and 2849 deletions
57
examples/evaluation/defer_eval.cpp
Normal file
57
examples/evaluation/defer_eval.cpp
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#include <cstdint>
|
||||
#include <iostream>
|
||||
|
||||
#include "dpf.hpp"
|
||||
|
||||
/// Pre-assign full-domain expand, then rotate after the input wildcard opens.
|
||||
int main()
|
||||
{
|
||||
using input_type = std::uint8_t;
|
||||
using output_type = std::uint64_t;
|
||||
const output_type beta = 7;
|
||||
const input_type alpha = 42;
|
||||
const input_type from = 40;
|
||||
const input_type to = 50;
|
||||
|
||||
auto [k0, k1] = dpf::make_dpf(dpf::wildcard_value<input_type>{}, beta);
|
||||
|
||||
//! [defer-eval]
|
||||
auto buf0 = dpf::make_output_buffer_for_full(k0);
|
||||
auto buf1 = dpf::make_output_buffer_for_full(k1);
|
||||
auto deferred0 = dpf::defer_eval_interval(k0, from, to, buf0);
|
||||
auto deferred1 = dpf::defer_eval_interval(k1, from, to, buf1);
|
||||
|
||||
// Parties open mask - alpha into offset_x (local demo of the exchange).
|
||||
const input_type a0 = 0x12;
|
||||
const input_type a1 = static_cast<input_type>(alpha - a0);
|
||||
const auto sh0 = k0.offset_x.compute_and_get_share(a0);
|
||||
const auto sh1 = k1.offset_x.compute_and_get_share(a1);
|
||||
k0.offset_x.reconstruct(sh1);
|
||||
k1.offset_x.reconstruct(sh0);
|
||||
|
||||
auto view0 = deferred0.get();
|
||||
auto view1 = deferred1.get();
|
||||
//! [defer-eval]
|
||||
|
||||
auto it0 = std::begin(view0);
|
||||
auto it1 = std::begin(view1);
|
||||
for (input_type x = from; x <= to; ++x, ++it0, ++it1)
|
||||
{
|
||||
const output_type got = dpf::reconstruct(*it0, *it1);
|
||||
const output_type expect = (x == alpha) ? beta : 0;
|
||||
if (got != expect)
|
||||
{
|
||||
std::cerr << "defer_eval\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (it0 != std::end(view0) || it1 != std::end(view1))
|
||||
{
|
||||
std::cerr << "defer_eval length\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << dpf::reconstruct(*std::begin(view0), *std::begin(view1))
|
||||
<< "\n";
|
||||
return 0;
|
||||
}
|
||||
44
examples/evaluation/eval_dpf3_cmp_ic.cpp
Normal file
44
examples/evaluation/eval_dpf3_cmp_ic.cpp
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
#include <cstdint>
|
||||
#include <iostream>
|
||||
|
||||
#include "dpf.hpp"
|
||||
|
||||
/// Three-party comparison and interval-containment keys (one DCF share each).
|
||||
int main()
|
||||
{
|
||||
using Input = std::uint8_t;
|
||||
const Input thresh = 100;
|
||||
const std::uint64_t beta = 5;
|
||||
|
||||
//! [eval-dpf3-cmp]
|
||||
auto [c1, c2, c3] = dpf::make_dpf3_cmp(thresh, beta);
|
||||
// Parties 1 and 3 hold the k0 half; party 2 holds k1. Open any complementary pair.
|
||||
const dpf::fp61 hot =
|
||||
dpf::reconstruct_cmp_halves(dpf::eval_point(c1, Input{10}),
|
||||
dpf::eval_point(c2, Input{10}));
|
||||
const dpf::fp61 cold =
|
||||
dpf::reconstruct_cmp_halves(dpf::eval_point(c3, Input{200}),
|
||||
dpf::eval_point(c2, Input{200}));
|
||||
//! [eval-dpf3-cmp]
|
||||
if (hot.raw() != beta || cold.raw() != 0)
|
||||
{
|
||||
std::cerr << "dpf3 cmp\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
//! [eval-dpf3-ic]
|
||||
auto [i1, i2, i3] = dpf::make_dpf3_ic(Input{10}, Input{20}, Input{40}, beta);
|
||||
// Interval is relative to the public shift `r`; x=35 is on for (20,40)@r=10.
|
||||
const dpf::fp61 inside =
|
||||
dpf::reconstruct_cmp_halves(dpf::eval_point(i1, Input{35}),
|
||||
dpf::eval_point(i2, Input{35}));
|
||||
//! [eval-dpf3-ic]
|
||||
if (inside.raw() != beta)
|
||||
{
|
||||
std::cerr << "dpf3 ic\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << hot.raw() << "\n";
|
||||
return 0;
|
||||
}
|
||||
36
examples/evaluation/eval_dpf3_doerner_shelat.cpp
Normal file
36
examples/evaluation/eval_dpf3_doerner_shelat.cpp
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#include <cstdint>
|
||||
#include <iostream>
|
||||
|
||||
#include "dpf.hpp"
|
||||
|
||||
/// Dual-spine Doerner–Shelat (2,3) keygen: XOR shares of `α`, same clear `β`
|
||||
/// as honest-dealer `make_dpf3(α, β)`.
|
||||
int main()
|
||||
{
|
||||
using Input = std::uint8_t;
|
||||
const Input alpha = 0x2a;
|
||||
const Input x0 = 0x13;
|
||||
const Input x1 = static_cast<Input>(alpha ^ x0);
|
||||
const dpf::fp61 beta{99};
|
||||
|
||||
//! [eval-dpf3-ds]
|
||||
auto [d1, d2, d3] = dpf::make_dpf3(alpha, beta);
|
||||
auto [s1, s2, s3] = dpf::make_dpf3_doerner_shelat(x0, x1, beta);
|
||||
const dpf::fp61 dealer = dpf::reconstruct(
|
||||
dpf::as_share(d1, dpf::eval_point(d1, alpha)),
|
||||
dpf::as_share(d2, dpf::eval_point(d2, alpha)),
|
||||
dpf::as_share(d3, dpf::eval_point(d3, alpha)));
|
||||
const dpf::fp61 dual = dpf::reconstruct(
|
||||
dpf::as_share(s1, dpf::eval_point(s1, alpha)),
|
||||
dpf::as_share(s2, dpf::eval_point(s2, alpha)),
|
||||
dpf::as_share(s3, dpf::eval_point(s3, alpha)));
|
||||
//! [eval-dpf3-ds]
|
||||
if (dealer != beta || dual != beta)
|
||||
{
|
||||
std::cerr << "dealer vs dual-spine disagree\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << dual.raw() << "\n";
|
||||
return 0;
|
||||
}
|
||||
42
examples/evaluation/eval_dpf3_point.cpp
Normal file
42
examples/evaluation/eval_dpf3_point.cpp
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
#include <cstdint>
|
||||
#include <iostream>
|
||||
|
||||
#include "dpf.hpp"
|
||||
|
||||
/// Three-evaluator point DPF (ePrint 2024/1658 Fig. 3). Each key is a Shamir
|
||||
/// share; open with any two (or all three) via `dpf::reconstruct`.
|
||||
int main()
|
||||
{
|
||||
using Input = std::uint8_t;
|
||||
const Input alpha = 42;
|
||||
const dpf::fp61 beta{7};
|
||||
|
||||
//! [eval-dpf3-point]
|
||||
auto [k1, k2, k3] = dpf::make_dpf3(alpha, beta);
|
||||
const dpf::fp61 y1 = dpf::eval_point(k1, alpha);
|
||||
const dpf::fp61 y2 = dpf::eval_point(k2, alpha);
|
||||
const dpf::fp61 y3 = dpf::eval_point(k3, alpha);
|
||||
const dpf::fp61 opened = dpf::reconstruct(
|
||||
dpf::as_share(k1, y1), dpf::as_share(k2, y2), dpf::as_share(k3, y3));
|
||||
//! [eval-dpf3-point]
|
||||
if (opened != beta)
|
||||
{
|
||||
std::cerr << "dpf3 at the programmed input\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
const dpf::fp61 z1 = dpf::eval_point(k1, Input{41});
|
||||
const dpf::fp61 z2 = dpf::eval_point(k2, Input{41});
|
||||
const dpf::fp61 z3 = dpf::eval_point(k3, Input{41});
|
||||
if (dpf::reconstruct(dpf::as_share(k1, z1), dpf::as_share(k2, z2),
|
||||
dpf::as_share(k3, z3))
|
||||
.raw()
|
||||
!= 0)
|
||||
{
|
||||
std::cerr << "dpf3 off the programmed input\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << opened.raw() << "\n";
|
||||
return 0;
|
||||
}
|
||||
102
examples/evaluation/eval_inner_product.cpp
Normal file
102
examples/evaluation/eval_inner_product.cpp
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "dpf.hpp"
|
||||
|
||||
/// Fused inner product: do not materialize the DPF vector.
|
||||
/// A scalar weight vector dots with one output. A row of a tuple or
|
||||
/// `std::array` dots with several outputs, including an ancestor slot
|
||||
/// and the leaf, read off one path.
|
||||
int main()
|
||||
{
|
||||
using In = std::uint8_t;
|
||||
|
||||
//! [eval-inner-product-scalar]
|
||||
// Trivial: sum_x DPF(x) * w[x] over a short interval.
|
||||
const In alpha = 42;
|
||||
const std::uint64_t beta = 7;
|
||||
auto [k0, k1] = dpf::make_dpf(alpha, beta);
|
||||
const In from = 40;
|
||||
const In to = 50;
|
||||
std::vector<std::uint64_t> w(to - from + 1);
|
||||
for (std::size_t i = 0; i < w.size(); ++i)
|
||||
w[i] = i + 1;
|
||||
const auto s0 = dpf::eval_inner_product(dpf::paired, k0, from, to, w);
|
||||
const auto s1 = dpf::eval_inner_product(dpf::paired, k1, from, to, w);
|
||||
//! [eval-inner-product-scalar]
|
||||
if (dpf::reconstruct(s0, s1) != beta * w[alpha - from])
|
||||
{
|
||||
std::cerr << "scalar interval\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
//! [eval-inner-product-full]
|
||||
// Trivial full domain. Only α contributes.
|
||||
std::vector<std::uint64_t> wall(256, 1);
|
||||
const auto f0 = dpf::eval_full_inner_product(dpf::paired, k0, wall);
|
||||
const auto f1 = dpf::eval_full_inner_product(dpf::paired, k1, wall);
|
||||
//! [eval-inner-product-full]
|
||||
if (dpf::reconstruct(f0, f1) != beta)
|
||||
{
|
||||
std::cerr << "full\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
//! [eval-inner-product-paired]
|
||||
// Two outputs on the same leaf. rows[i] = {weight for output 0, output 1}.
|
||||
auto [p0, p1] = dpf::make_dpf(In{9}, std::uint32_t{3}, std::uint32_t{5});
|
||||
std::vector<std::array<std::uint32_t, 2>> rows;
|
||||
for (In x = 8;; ++x)
|
||||
{
|
||||
rows.push_back({std::uint32_t{1}, std::uint32_t{x}});
|
||||
if (x == 10)
|
||||
break;
|
||||
}
|
||||
const auto a0 = dpf::eval_inner_product<0, 1>(dpf::paired, p0, In{8}, In{10}, rows);
|
||||
const auto a1 = dpf::eval_inner_product<0, 1>(dpf::paired, p1, In{8}, In{10}, rows);
|
||||
//! [eval-inner-product-paired]
|
||||
// x=9 is hot: output0 * 1 + output1 * 9.
|
||||
if (dpf::reconstruct(a0, a1) != std::uint64_t{3} * 1u + std::uint64_t{5} * 9u)
|
||||
{
|
||||
std::cerr << "paired leaf\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
//! [eval-inner-product-ancestor]
|
||||
// Prefix slot at<4> and the full-domain leaf, one path per point.
|
||||
// 0x2a and 0x2b share the high nibble 0x2, so both see payload 5 there.
|
||||
// 0x10 is a different nibble. Only 0x2a is hot on the leaf.
|
||||
auto [h0, h1] = dpf::make_dpf(In{0x2a}, dpf::at<4>(std::uint8_t{5}), std::uint8_t{9});
|
||||
const std::vector<In> pts{0x10, 0x2a, 0x2b};
|
||||
const std::vector<std::tuple<std::uint32_t, std::uint32_t>> hw{
|
||||
{1u, 0u}, {1u, 1u}, {2u, 4u}};
|
||||
const auto q0 = dpf::eval_sequence_inner_product<0, 1>(h0, pts.begin(), pts.end(), hw);
|
||||
const auto q1 = dpf::eval_sequence_inner_product<0, 1>(h1, pts.begin(), pts.end(), hw);
|
||||
//! [eval-inner-product-ancestor]
|
||||
// 0x10 is off. 0x2a: 5*1 + 9*1. 0x2b: prefix still 5, leaf 0, times (2, 4).
|
||||
const std::uint64_t ancestor_expect = 5u * 1u + 9u * 1u + 5u * 2u;
|
||||
if (dpf::reconstruct(q0, q1) != ancestor_expect)
|
||||
{
|
||||
std::cerr << "ancestor\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
//! [eval-inner-product-recipe]
|
||||
const auto recipe = dpf::make_sequence_recipe<decltype(h0)>(pts.begin(), pts.end());
|
||||
const auto r0 = dpf::eval_sequence_inner_product<0, 1>(
|
||||
h0, recipe, pts.begin(), pts.end(), hw);
|
||||
const auto r1 = dpf::eval_sequence_inner_product<0, 1>(
|
||||
h1, recipe, pts.begin(), pts.end(), hw);
|
||||
//! [eval-inner-product-recipe]
|
||||
if (dpf::reconstruct(r0, r1) != ancestor_expect)
|
||||
{
|
||||
std::cerr << "recipe\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << dpf::reconstruct(s0, s1) << "\n";
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue