libdpf/test/tests/blob_leaf_test.cpp
Ryan Henry 0d22946a0e 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>
2026-09-28 05:59:19 -06:00

109 lines
3.2 KiB
C++

#include <gtest/gtest.h>
#include <array>
#include <cstdint>
#include <cstring>
#include <utility>
#include <vector>
#include "dpf.hpp"
namespace
{
template <std::size_t N>
dpf::blob<N> make_blob_pattern(unsigned char seed)
{
dpf::blob<N> b{};
for (std::size_t i = 0; i < N; ++i)
b.bytes[i] = static_cast<unsigned char>(seed + static_cast<unsigned char>(i));
return b;
}
template <std::size_t N, typename InputT>
void expect_point_opens(InputT alpha, const dpf::blob<N> & beta)
{
auto [k0, k1] = dpf::make_dpf(alpha, beta);
auto open = [&](InputT x) {
return dpf::reconstruct(*dpf::eval_point(k0, x),
*dpf::eval_point(k1, x));
};
const auto s0 = *dpf::eval_point(k0, alpha);
const auto s1 = *dpf::eval_point(k1, alpha);
EXPECT_EQ(dpf::reconstruct(s0, s1), beta);
EXPECT_EQ(open(alpha), beta);
const dpf::blob<N> zero{};
const std::vector<InputT> offs = {
InputT{0},
InputT{1},
static_cast<InputT>(alpha + 1),
static_cast<InputT>(alpha ^ InputT{1}),
};
for (InputT x : offs)
{
if (x == alpha)
continue;
EXPECT_EQ(open(x), zero) << "off-point";
}
}
} // namespace
TEST(BlobLeaf, PointEvalUint32VariousN)
{
const std::uint32_t alpha = 0x00ab12cdu;
expect_point_opens<1>(alpha, make_blob_pattern<1>(0x11));
expect_point_opens<16>(alpha, make_blob_pattern<16>(0x22));
expect_point_opens<100>(alpha, make_blob_pattern<100>(0x33));
expect_point_opens<1000>(alpha, make_blob_pattern<1000>(0x44));
}
TEST(BlobLeaf, PointEvalUint128)
{
using input_t = simde_uint128;
const input_t alpha = (input_t{1} << 100) | input_t{0x55aau};
expect_point_opens<16>(alpha, make_blob_pattern<16>(0x7a));
expect_point_opens<100>(alpha, make_blob_pattern<100>(0x8b));
}
TEST(BlobLeaf, FullDomainMatchesPointShareForShare)
{
using input_t = std::uint8_t;
using blob_t = dpf::blob<100>;
const input_t alpha = 17;
const blob_t beta = make_blob_pattern<100>(0x9c);
auto [k0, k1] = dpf::make_dpf(alpha, beta);
auto full0 = dpf::eval_full(k0);
auto full1 = dpf::eval_full(k1);
auto & it0 = full0.second;
auto & it1 = full1.second;
auto a = std::begin(it0);
auto b = std::begin(it1);
for (std::size_t i = 0; a != std::end(it0) && b != std::end(it1);
++a, ++b, ++i)
{
const auto p0 = *dpf::eval_point(k0, static_cast<input_t>(i));
const auto p1 = *dpf::eval_point(k1, static_cast<input_t>(i));
EXPECT_EQ(dpf::reconstruct(*a, *b), dpf::reconstruct(p0, p1)) << i;
EXPECT_EQ(dpf::detail_walk::group_value(*a),
dpf::detail_walk::group_value(p0)) << "party0 @" << i;
EXPECT_EQ(dpf::detail_walk::group_value(*b),
dpf::detail_walk::group_value(p1)) << "party1 @" << i;
}
EXPECT_EQ(std::size_t(std::distance(std::begin(it0), std::end(it0))), 256u);
}
TEST(BlobLeaf, Domain128FullEvalThrows)
{
using input_t = simde_uint128;
using blob_t = dpf::blob<16>;
const input_t alpha = input_t{1} << 90;
const blob_t beta = make_blob_pattern<16>(1);
auto [k0, k1] = dpf::make_dpf(alpha, beta);
(void)k1;
EXPECT_THROW((void)dpf::eval_full(k0), std::exception);
}