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
149
test/tests/leaf_later_test.cpp
Normal file
149
test/tests/leaf_later_test.cpp
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "dpf.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// Full-block payload ⇒ outputs_per_leaf = 1, so a single public F matches the
|
||||
// leaf correction word share-for-share.
|
||||
using input_t = std::uint8_t;
|
||||
using output_t = simde_uint128;
|
||||
constexpr std::size_t n = 256;
|
||||
|
||||
output_t leaf_cw_as_output(const dpf::utils::dpf_type_t<dpf::prg::aes128,
|
||||
dpf::prg::aes128, input_t, output_t> & key)
|
||||
{
|
||||
using exterior = typename std::decay_t<decltype(key)>::exterior_node;
|
||||
return dpf::extract_leaf<exterior, output_t>(key.template leaf<0>(), 0);
|
||||
}
|
||||
|
||||
// party_key wrappers from make_dpf
|
||||
template <typename Key>
|
||||
output_t leaf_cw_as_output(const Key & key)
|
||||
{
|
||||
using exterior = typename Key::exterior_node;
|
||||
return dpf::extract_leaf<exterior, output_t>(key.template leaf<0>(), 0);
|
||||
}
|
||||
|
||||
output_t make_payload(std::uint64_t lo)
|
||||
{
|
||||
return output_t{lo};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(LeafLater, MatchesCorrectedImmediately)
|
||||
{
|
||||
const input_t alpha = 42;
|
||||
const output_t beta = make_payload(7);
|
||||
|
||||
auto [k0, k1] = dpf::make_dpf(alpha, beta);
|
||||
// Public leaf CW (same on both keys); applying it recovers the immediate path.
|
||||
const output_t F = leaf_cw_as_output(k0);
|
||||
EXPECT_EQ(F, leaf_cw_as_output(k1));
|
||||
|
||||
auto full0 = dpf::eval_full(k0);
|
||||
auto full1 = dpf::eval_full(k1);
|
||||
|
||||
std::vector<output_t> buf0(n), buf1(n);
|
||||
std::vector<std::uint8_t> c0(n), c1(n);
|
||||
dpf::eval_full(buf0, c0, k0, dpf::leaf_later{});
|
||||
dpf::eval_full(buf1, c1, k1, dpf::leaf_later{});
|
||||
dpf::apply_leaf_correction(buf0, c0, F);
|
||||
dpf::apply_leaf_correction(buf1, c1, F);
|
||||
|
||||
auto it0 = std::begin(full0.second);
|
||||
auto it1 = std::begin(full1.second);
|
||||
for (std::size_t i = 0; i < n; ++i, ++it0, ++it1)
|
||||
{
|
||||
const auto imm0 = dpf::detail_walk::group_value(*it0);
|
||||
const auto imm1 = dpf::detail_walk::group_value(*it1);
|
||||
EXPECT_EQ(buf0[i], imm0) << "party0 @" << i;
|
||||
EXPECT_EQ(buf1[i], imm1) << "party1 @" << i;
|
||||
EXPECT_EQ(buf0[i] - buf1[i], imm0 - imm1) << i;
|
||||
const auto got = buf0[i] - buf1[i];
|
||||
if (i == alpha)
|
||||
EXPECT_EQ(got, beta);
|
||||
else
|
||||
EXPECT_EQ(got, output_t{0});
|
||||
}
|
||||
}
|
||||
|
||||
TEST(LeafLater, ApplyAfterRotateMatchesCorrectThenRotate)
|
||||
{
|
||||
const input_t alpha = 10;
|
||||
const output_t beta = make_payload(99);
|
||||
const std::size_t s = 32;
|
||||
|
||||
auto [k0, k1] = dpf::make_dpf(alpha, beta);
|
||||
const output_t F = leaf_cw_as_output(k0);
|
||||
|
||||
auto full0 = dpf::eval_full(k0);
|
||||
auto full1 = dpf::eval_full(k1);
|
||||
std::vector<output_t> early0(n), early1(n);
|
||||
{
|
||||
auto a = std::begin(full0.second);
|
||||
auto b = std::begin(full1.second);
|
||||
for (std::size_t i = 0; i < n; ++i, ++a, ++b)
|
||||
{
|
||||
early0[i] = dpf::detail_walk::group_value(*a);
|
||||
early1[i] = dpf::detail_walk::group_value(*b);
|
||||
}
|
||||
}
|
||||
early0 = dpf::cyclic_shift(early0, s);
|
||||
early1 = dpf::cyclic_shift(early1, s);
|
||||
|
||||
std::vector<output_t> late0(n), late1(n);
|
||||
std::vector<std::uint8_t> c0(n), c1(n);
|
||||
dpf::eval_full(late0, c0, k0, dpf::leaf_later{});
|
||||
dpf::eval_full(late1, c1, k1, dpf::leaf_later{});
|
||||
dpf::cyclic_shift_pair(late0, c0, s);
|
||||
dpf::cyclic_shift_pair(late1, c1, s);
|
||||
dpf::apply_leaf_correction(late0, c0, F);
|
||||
dpf::apply_leaf_correction(late1, c1, F);
|
||||
|
||||
for (std::size_t i = 0; i < n; ++i)
|
||||
{
|
||||
EXPECT_EQ(late0[i], early0[i]) << i;
|
||||
EXPECT_EQ(late1[i], early1[i]) << i;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(LeafLater, DuoramShapedUpdate)
|
||||
{
|
||||
// Unit at r, rotate by i*−r, then apply a public F built from the leaf CW
|
||||
// of a key keyed at the online message (same as correcting immediately for
|
||||
// that message). Neighbours stay unchanged.
|
||||
const input_t r = 10;
|
||||
const input_t i_star = 42;
|
||||
const std::size_t shift = static_cast<std::size_t>(i_star - r);
|
||||
const output_t message = make_payload(7);
|
||||
|
||||
auto [k0, k1] = dpf::make_dpf(r, message);
|
||||
const output_t F = leaf_cw_as_output(k0);
|
||||
|
||||
std::vector<output_t> mem0(n), mem1(n);
|
||||
mem0[i_star] = make_payload(100);
|
||||
|
||||
std::vector<output_t> v0(n), v1(n);
|
||||
std::vector<std::uint8_t> t0(n), t1(n);
|
||||
dpf::eval_full_add_into(v0, t0, k0, dpf::leaf_later{}, dpf::rotate{shift});
|
||||
dpf::eval_full_add_into(v1, t1, k1, dpf::leaf_later{}, dpf::rotate{shift});
|
||||
dpf::apply_leaf_correction(v0, t0, F);
|
||||
dpf::apply_leaf_correction(v1, t1, F);
|
||||
|
||||
for (std::size_t i = 0; i < n; ++i)
|
||||
{
|
||||
mem0[i] = mem0[i] + v0[i];
|
||||
mem1[i] = mem1[i] + v1[i];
|
||||
}
|
||||
|
||||
EXPECT_EQ(mem0[i_star] - mem1[i_star], make_payload(100) + message);
|
||||
EXPECT_EQ(mem0[r] - mem1[r], output_t{0});
|
||||
EXPECT_EQ(mem0[0] - mem1[0], output_t{0});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue