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:
Ryan Henry 2026-09-28 05:59:19 -06:00
parent 695f8e84f7
commit 0d22946a0e
1835 changed files with 170291 additions and 2849 deletions

View file

@ -1,4 +1,8 @@
#include <gtest/gtest.h>
#include <tuple>
#include <cstring>
#include <cstdint>
#include "asio.hpp"
#define LIBDPF_HAS_ASIO
@ -591,7 +595,7 @@ TEST(WildcardTest, PackedSmallWildcardsAtNonTerminalAssignAll)
dpf::at<10>(w, w, w, w),
uint16_t{99});
ASSERT_THROW((void)dpf::eval_point(dpf::out<0, 10>, dpf0, x), std::runtime_error);
ASSERT_THROW(dpf::eval_point(dpf::out<0, 10>, dpf0, x), std::runtime_error);
ASSERT_EQ(static_cast<uint16_t>(
dpf::reconstruct(*dpf::eval_point(dpf::out<4>, dpf0, x), *dpf::eval_point(dpf::out<4>, dpf1, x))),
uint16_t{99});
@ -617,3 +621,189 @@ TEST(WildcardTest, PackedSmallWildcardsAtNonTerminalAssignAll)
static_cast<uint16_t>(x ^ (1u << 6))))),
concrete_t{0});
}
namespace
{
template <typename Bits, typename T>
T bits_as(Bits bits)
{
T out{};
std::memcpy(&out, &bits, sizeof(T));
return out;
}
template <typename T>
auto bits_of(T v)
{
using bits_t = std::conditional_t<sizeof(T) == 4, std::uint32_t, std::uint64_t>;
bits_t bits{};
std::memcpy(&bits, &v, sizeof(T));
return bits;
}
/// In-process assign for a wildcard leaf (same messages as asio, no socket).
template <std::size_t I = 0, typename DpfKey0, typename DpfKey1, typename ShareT>
void assign_leaf_local(DpfKey0 & dpf0, DpfKey1 & dpf1, const ShareT & shr0,
const ShareT & shr1)
{
auto & w0 = std::get<I>(dpf0.leaf_nodes);
auto & w1 = std::get<I>(dpf1.leaf_nodes);
if (w0.is_ready())
w0.begin_update();
if (w1.is_ready())
w1.begin_update();
const auto b0 = w0.compute_and_get_blinded_output_share(shr0);
const auto b1 = w1.compute_and_get_blinded_output_share(shr1);
const auto l0 = w0.compute_and_get_leaf_share(b1);
const auto l1 = w1.compute_and_get_leaf_share(b0);
w0.reconstruct_correction_word(l1);
w1.reconstruct_correction_word(l0);
}
} // namespace
TEST(WildcardTest, FullWidthXorDoesNotRevealBeta)
{
using input_type = uint8_t;
using concrete_type = dpf::xints::xint128_t;
using output_type = dpf::wildcard_value<concrete_type>;
input_type x = 0x42;
output_type y;
auto [dpf0, dpf1] = dpf::make_dpf(x, y);
auto & w0 = std::get<0>(dpf0.leaf_nodes);
auto & w1 = std::get<0>(dpf1.leaf_nodes);
// Scale Beaver must be planted even for a single full-width XOR lane.
EXPECT_EQ((dpf::outputs_per_leaf_v<concrete_type,
typename std::decay_t<decltype(dpf0)>::exterior_node>), 1u);
EXPECT_TRUE(dpf::utils::has_characteristic_two_v<concrete_type>);
concrete_type y_exp = concrete_type{0x0123456789ABCDEFull};
concrete_type y_shr0 = concrete_type{0x1111111111111111ull};
concrete_type y_shr1 = y_exp + y_shr0; // XOR group
const auto blinded0 = w0.compute_and_get_blinded_output_share(y_shr0);
const auto blinded1 = w1.compute_and_get_blinded_output_share(y_shr1);
// With a non-trivial output blind, the exchanged value is not the share.
EXPECT_NE(blinded0, y_shr0);
EXPECT_NE(blinded1, y_shr1);
// Finish the assign after the privacy check above (state is already blinded).
const auto l0 = w0.compute_and_get_leaf_share(blinded1);
const auto l1 = w1.compute_and_get_leaf_share(blinded0);
w0.reconstruct_correction_word(l1);
w1.reconstruct_correction_word(l0);
EXPECT_EQ(dpf::reconstruct(*dpf::eval_point(dpf0, x), *dpf::eval_point(dpf1, x)),
y_exp);
EXPECT_EQ(dpf::reconstruct(*dpf::eval_point(dpf0, static_cast<input_type>(x ^ 1)),
*dpf::eval_point(dpf1, static_cast<input_type>(x ^ 1))),
concrete_type{});
}
TEST(WildcardTest, FloatWildcardRoundTrip)
{
using input_type = uint8_t;
using concrete_type = float;
using output_type = dpf::wildcard_value<concrete_type>;
input_type x = 0x55;
output_type y;
auto [dpf0, dpf1] = dpf::make_dpf(x, y);
const concrete_type y_exp = 3.14159265f;
const auto y_bits = bits_of(y_exp);
const std::uint32_t shr0_bits = 0xA5A5A5A5u;
const concrete_type y_shr0 = bits_as<std::uint32_t, concrete_type>(shr0_bits);
const concrete_type y_shr1 =
bits_as<std::uint32_t, concrete_type>(y_bits ^ shr0_bits);
assign_leaf_local(dpf0, dpf1, y_shr0, y_shr1);
const auto got = dpf::reconstruct(*dpf::eval_point(dpf0, x), *dpf::eval_point(dpf1, x));
EXPECT_EQ(bits_of(got), y_bits);
EXPECT_EQ(bits_of(dpf::reconstruct(
*dpf::eval_point(dpf0, static_cast<input_type>(x ^ 1)),
*dpf::eval_point(dpf1, static_cast<input_type>(x ^ 1)))),
0u);
}
TEST(WildcardTest, SecondAssignUpdatesPayload)
{
using input_type = uint8_t;
using concrete_type = uint32_t;
using output_type = dpf::wildcard_value<concrete_type>;
input_type x = 0x11;
auto [dpf0, dpf1] = dpf::make_dpf(x, output_type{});
const concrete_type beta = 0xAAAAAAAAu;
const concrete_type beta2 = 0xBBBBBBBBu;
const concrete_type s0 = 0x12345678u;
assign_leaf_local(dpf0, dpf1, s0, static_cast<concrete_type>(beta - s0));
EXPECT_EQ(dpf::reconstruct(*dpf::eval_point(dpf0, x), *dpf::eval_point(dpf1, x)), beta);
// Second assign installs (beta2 - beta) on top of the ready leaf.
const concrete_type delta = static_cast<concrete_type>(beta2 - beta);
const concrete_type d0 = 0x01010101u;
assign_leaf_local(dpf0, dpf1, d0, static_cast<concrete_type>(delta - d0));
EXPECT_EQ(dpf::reconstruct(*dpf::eval_point(dpf0, x), *dpf::eval_point(dpf1, x)),
beta2);
}
TEST(WildcardTest, AssignWildcardInputOpensPublicShiftNotAlpha)
{
using input_type = uint8_t;
using output_type = uint32_t;
// Wildcard domain: dealer plants a random mask; parties later open (mask - alpha).
auto [dpf0, dpf1] = dpf::make_dpf(dpf::wildcard_value<input_type>{}, output_type{7});
const input_type mask = static_cast<input_type>(
dpf0.offset_x.raw() + dpf1.offset_x.raw());
const input_type alpha = 0xAAu;
const input_type a0 = 0x12u;
const input_type a1 = static_cast<input_type>(alpha - a0);
const auto sh0 = dpf0.offset_x.compute_and_get_share(a0);
const auto sh1 = dpf1.offset_x.compute_and_get_share(a1);
const auto open0 = dpf0.offset_x.reconstruct(sh1);
const auto open1 = dpf1.offset_x.reconstruct(sh0);
EXPECT_EQ(open0, open1);
const input_type want_shift = static_cast<input_type>(mask - alpha);
EXPECT_EQ(open0, want_shift);
EXPECT_NE(open0, alpha); // public value is the shift, not alpha
EXPECT_EQ(static_cast<input_type>(open0 + alpha), mask);
EXPECT_EQ(dpf::reconstruct(*dpf::eval_point(dpf0, alpha), *dpf::eval_point(dpf1, alpha)),
output_type{7});
EXPECT_EQ(dpf::reconstruct(*dpf::eval_point(dpf0, static_cast<input_type>(alpha ^ 1)),
*dpf::eval_point(dpf1, static_cast<input_type>(alpha ^ 1))),
output_type{0});
}
TEST(WildcardTest, UpdatableTagAssignsThenRewrites)
{
const std::uint8_t alpha = 0x2a;
auto [k0, k1] = dpf::make_dpf(alpha, std::uint64_t{7}, dpf::updatable{});
EXPECT_TRUE(k0.is_wildcard(0));
EXPECT_TRUE(k1.is_wildcard(0));
EXPECT_EQ(dpf::reconstruct(*dpf::eval_point(k0, alpha), *dpf::eval_point(k1, alpha)),
std::uint64_t{7});
EXPECT_EQ(dpf::reconstruct(*dpf::eval_point(k0, std::uint8_t{0}),
*dpf::eval_point(k1, std::uint8_t{0})),
std::uint64_t{0});
auto & w0 = std::get<0>(k0.leaf_nodes);
auto & w1 = std::get<0>(k1.leaf_nodes);
w0.begin_update();
w1.begin_update();
// A second assign installs the difference β' − β, not the new absolute payload.
const auto shares = dpf::additively_share(std::uint64_t{9} - std::uint64_t{7});
const auto b0 = w0.compute_and_get_blinded_output_share(shares.first.raw());
const auto b1 = w1.compute_and_get_blinded_output_share(shares.second.raw());
const auto l0 = w0.compute_and_get_leaf_share(b1);
const auto l1 = w1.compute_and_get_leaf_share(b0);
w0.reconstruct_correction_word(l1);
w1.reconstruct_correction_word(l0);
EXPECT_EQ(dpf::reconstruct(*dpf::eval_point(k0, alpha), *dpf::eval_point(k1, alpha)),
std::uint64_t{9});
}