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

@ -23,6 +23,7 @@
#include "dpf/bit.hpp"
#include "dpf/bitstring.hpp"
#include "dpf/blob.hpp"
#include "dpf/packed_lane_arithmetic.hpp"
#include "dpf/wildcard.hpp"
#include "dpf/xor_wrapper.hpp"
@ -90,6 +91,83 @@ static constexpr auto subtract_leaf = leaf_arithmetic::subtract_t<OutputT, void>
static constexpr auto multiply_leaf = leaf_arithmetic::multiply_t<void, void>{};
/// @brief Scalar add in the leaf output group.
/// @details `float`/`double` use XOR of the IEEE bit pattern (same as
/// `add_t` on packed leaves), not IEEE floating-point addition.
/// \complexity O(1) for a scalar. A packed node walks its bytes once (`add_t` / the lane loops): O(sizeof node) and the carry stays inside a `twobit` or `nyble` lane.
template <typename T>
HEDLEY_ALWAYS_INLINE
HEDLEY_NO_THROW
HEDLEY_PURE
T leaf_group_add(const T & a, const T & b) noexcept
{
if constexpr (std::is_same_v<T, float> || std::is_same_v<T, double>)
{
using bits_t = std::conditional_t<sizeof(T) == 4, psnip_uint32_t, psnip_uint64_t>;
bits_t aa{}, bb{};
utils::raw_memcpy(&aa, &a, sizeof(T));
utils::raw_memcpy(&bb, &b, sizeof(T));
bits_t cc = static_cast<bits_t>(aa ^ bb);
T out{};
utils::raw_memcpy(&out, &cc, sizeof(T));
return out;
}
else
{
return static_cast<T>(a + b);
}
}
/// @brief Scalar multiply in the leaf output group (`float`/`double`: AND of bits).
template <typename T>
HEDLEY_ALWAYS_INLINE
HEDLEY_NO_THROW
HEDLEY_PURE
T leaf_group_mul(const T & a, const T & b) noexcept
{
if constexpr (std::is_same_v<T, float> || std::is_same_v<T, double>)
{
using bits_t = std::conditional_t<sizeof(T) == 4, psnip_uint32_t, psnip_uint64_t>;
bits_t aa{}, bb{};
utils::raw_memcpy(&aa, &a, sizeof(T));
utils::raw_memcpy(&bb, &b, sizeof(T));
bits_t cc = static_cast<bits_t>(aa & bb);
T out{};
utils::raw_memcpy(&out, &cc, sizeof(T));
return out;
}
else
{
return static_cast<T>(a * b);
}
}
/// @brief Multiplicative identity for leaf scaling (all-ones for XOR/AND groups).
template <typename T>
HEDLEY_ALWAYS_INLINE
HEDLEY_NO_THROW
HEDLEY_PURE
T leaf_group_one() noexcept
{
if constexpr (std::is_same_v<T, float> || std::is_same_v<T, double>)
{
using bits_t = std::conditional_t<sizeof(T) == 4, psnip_uint32_t, psnip_uint64_t>;
bits_t ones = static_cast<bits_t>(~bits_t{0});
T out{};
utils::raw_memcpy(&out, &ones, sizeof(T));
return out;
}
else if constexpr (utils::is_xor_wrapper_v<T>)
{
using u = typename T::value_type;
return T{static_cast<u>(~u{0})};
}
else
{
return T{1};
}
}
namespace leaf_arithmetic
{
@ -260,10 +338,10 @@ struct add_array_t<OutputT, std::enable_if_t<dpf::utils::has_operators_plus_minu
"arithmetic leaf array and output type must be the same size");
std::array<T, N> c;
output_type a_, b_;
std::memcpy(&a_, std::data(a), sizeof(a_));
std::memcpy(&b_, std::data(b), sizeof(b_));
utils::raw_memcpy(&a_, std::data(a), sizeof(a_));
utils::raw_memcpy(&b_, std::data(b), sizeof(b_));
output_type c_ = a_ + b_;
std::memcpy(std::data(c), &c_, sizeof(c_));
utils::raw_memcpy(std::data(c), &c_, sizeof(c_));
return c;
}
};
@ -294,10 +372,10 @@ template <> struct add_t<simde_int128, simde__m128i> final
{
simde__m128i ret;
simde_int128 lhs_, rhs_;
std::memcpy(&lhs_, &lhs, sizeof(simde_int128));
std::memcpy(&rhs_, &rhs, sizeof(simde_int128));
utils::raw_memcpy(&lhs_, &lhs, sizeof(simde_int128));
utils::raw_memcpy(&rhs_, &rhs, sizeof(simde_int128));
simde_int128 sum = lhs_ + rhs_;
std::memcpy(&ret, &sum, sizeof(simde__m128i));
utils::raw_memcpy(&ret, &sum, sizeof(simde__m128i));
return ret;
}
};
@ -307,10 +385,10 @@ template <> struct add_t<simde_uint128, simde__m128i> final
{
simde__m128i ret;
simde_uint128 lhs_, rhs_;
std::memcpy(&lhs_, &lhs, sizeof(simde_uint128));
std::memcpy(&rhs_, &rhs, sizeof(simde_uint128));
utils::raw_memcpy(&lhs_, &lhs, sizeof(simde_uint128));
utils::raw_memcpy(&rhs_, &rhs, sizeof(simde_uint128));
simde_uint128 sum = lhs_ + rhs_;
std::memcpy(&ret, &sum, sizeof(simde__m128i));
utils::raw_memcpy(&ret, &sum, sizeof(simde__m128i));
return ret;
}
};
@ -335,10 +413,10 @@ template <> struct add_t<simde_int128, simde__m256i> final
{
simde__m256i ret;
simde_int128 lhs_[2], rhs_[2];
std::memcpy(&lhs_, &lhs, sizeof(simde_int128) * 2);
std::memcpy(&rhs_, &rhs, sizeof(simde_int128) * 2);
utils::raw_memcpy(&lhs_, &lhs, sizeof(simde_int128) * 2);
utils::raw_memcpy(&rhs_, &rhs, sizeof(simde_int128) * 2);
simde_int128 sum[2] = { lhs_[0] + rhs_[0], lhs_[1] + rhs_[1] };
std::memcpy(&ret, &sum, sizeof(simde__m256i));
utils::raw_memcpy(&ret, &sum, sizeof(simde__m256i));
return ret;
}
};
@ -348,21 +426,28 @@ template <> struct add_t<simde_uint128, simde__m256i> final
{
simde__m256i ret;
simde_uint128 lhs_[2], rhs_[2];
std::memcpy(&lhs_, &lhs, sizeof(simde_uint128) * 2);
std::memcpy(&rhs_, &rhs, sizeof(simde_uint128) * 2);
utils::raw_memcpy(&lhs_, &lhs, sizeof(simde_uint128) * 2);
utils::raw_memcpy(&rhs_, &rhs, sizeof(simde_uint128) * 2);
simde_uint128 sum[2] = { lhs_[0] + rhs_[0], lhs_[1] + rhs_[1] };
std::memcpy(&ret, &sum, sizeof(simde__m256i));
utils::raw_memcpy(&ret, &sum, sizeof(simde__m256i));
return ret;
}
};
template <typename OutputT, typename NodeT, std::size_t N> struct add_t<OutputT, std::array<NodeT, N>> final : public detail::add_array_t<OutputT> {};
template <std::size_t Nbits, typename WordT> struct add_t<dpf::bitstring<Nbits, WordT>, void> final : public detail::bitstring_xor_t<Nbits, WordT> {};
template <std::size_t N> struct add_t<dpf::blob<N>, void> final : public detail::bitstring_xor_t<N * 8, unsigned char> {};
template <std::size_t N, typename NodeT>
struct add_t<dpf::blob<N>, NodeT> final : public detail::bitstring_xor_t<N * 8, unsigned char> {};
/// @brief Bitwise XOR, not IEEE addition. Float addition does not form an
/// exact secret-sharing group; XOR of the representation does.
/// @tparam NodeT GGM node type
template <typename NodeT> struct add_t<float, NodeT> final : public std::bit_xor<> {};
template <typename NodeT> struct add_t<double, NodeT> final : public std::bit_xor<> {};
/// @tparam NodeT GGM node type (not `void`; that selects the scalar wrapper)
template <typename NodeT>
struct add_t<float, NodeT, std::enable_if_t<!std::is_void_v<NodeT>>>
final : public std::bit_xor<> {};
template <typename NodeT>
struct add_t<double, NodeT, std::enable_if_t<!std::is_void_v<NodeT>>>
final : public std::bit_xor<> {};
template <> struct add_t<dpf::bit, void> final : public std::bit_xor<> {};
template <typename NodeT> struct add_t<dpf::bit, NodeT> final : public std::bit_xor<> {};
template <typename T> struct add_t<xor_wrapper<T>, void> final : public std::bit_xor<> {};
@ -546,10 +631,10 @@ struct sub_array_t<OutputT, std::enable_if_t<dpf::utils::has_operators_plus_minu
"arithmetic leaf array and output type must be the same size");
std::array<T, N> c;
output_type a_, b_;
std::memcpy(&a_, std::data(a), sizeof(a_));
std::memcpy(&b_, std::data(b), sizeof(b_));
utils::raw_memcpy(&a_, std::data(a), sizeof(a_));
utils::raw_memcpy(&b_, std::data(b), sizeof(b_));
output_type c_ = a_ - b_;
std::memcpy(std::data(c), &c_, sizeof(c_));
utils::raw_memcpy(std::data(c), &c_, sizeof(c_));
return c;
}
};
@ -580,10 +665,10 @@ template <> struct subtract_t<simde_int128, simde__m128i> final
{
simde__m128i ret;
simde_int128 lhs_, rhs_;
std::memcpy(&lhs_, &lhs, sizeof(simde_int128));
std::memcpy(&rhs_, &rhs, sizeof(simde_int128));
utils::raw_memcpy(&lhs_, &lhs, sizeof(simde_int128));
utils::raw_memcpy(&rhs_, &rhs, sizeof(simde_int128));
simde_int128 sum = lhs_ - rhs_;
std::memcpy(&ret, &sum, sizeof(simde__m128i));
utils::raw_memcpy(&ret, &sum, sizeof(simde__m128i));
return ret;
}
};
@ -593,10 +678,10 @@ template <> struct subtract_t<simde_uint128, simde__m128i> final
{
simde__m128i ret;
simde_uint128 lhs_, rhs_;
std::memcpy(&lhs_, &lhs, sizeof(simde_uint128));
std::memcpy(&rhs_, &rhs, sizeof(simde_uint128));
utils::raw_memcpy(&lhs_, &lhs, sizeof(simde_uint128));
utils::raw_memcpy(&rhs_, &rhs, sizeof(simde_uint128));
simde_uint128 sum = lhs_ - rhs_;
std::memcpy(&ret, &sum, sizeof(simde__m128i));
utils::raw_memcpy(&ret, &sum, sizeof(simde__m128i));
return ret;
}
};
@ -622,10 +707,10 @@ template <> struct subtract_t<simde_int128, simde__m256i> final
{
simde__m256i ret;
simde_int128 lhs_[2], rhs_[2];
std::memcpy(&lhs_, &lhs, sizeof(simde_int128) * 2);
std::memcpy(&rhs_, &rhs, sizeof(simde_int128) * 2);
utils::raw_memcpy(&lhs_, &lhs, sizeof(simde_int128) * 2);
utils::raw_memcpy(&rhs_, &rhs, sizeof(simde_int128) * 2);
simde_int128 sum[2] = { lhs_[0] - rhs_[0], lhs_[1] - rhs_[1] };
std::memcpy(&ret, &sum, sizeof(simde__m256i));
utils::raw_memcpy(&ret, &sum, sizeof(simde__m256i));
return ret;
}
};
@ -635,20 +720,27 @@ template <> struct subtract_t<simde_uint128, simde__m256i> final
{
simde__m256i ret;
simde_uint128 lhs_[2], rhs_[2];
std::memcpy(&lhs_, &lhs, sizeof(simde_uint128) * 2);
std::memcpy(&rhs_, &rhs, sizeof(simde_uint128) * 2);
utils::raw_memcpy(&lhs_, &lhs, sizeof(simde_uint128) * 2);
utils::raw_memcpy(&rhs_, &rhs, sizeof(simde_uint128) * 2);
simde_uint128 sum[2] = { lhs_[0] - rhs_[0], lhs_[1] - rhs_[1] };
std::memcpy(&ret, &sum, sizeof(simde__m256i));
utils::raw_memcpy(&ret, &sum, sizeof(simde__m256i));
return ret;
}
};
template <typename OutputT, typename NodeT, std::size_t N> struct subtract_t<OutputT, std::array<NodeT, N>> final : public detail::sub_array_t<OutputT> {};
template <std::size_t Nbits, typename WordT> struct subtract_t<dpf::bitstring<Nbits, WordT>, void> final : public detail::bitstring_xor_t<Nbits, WordT> {};
template <std::size_t N> struct subtract_t<dpf::blob<N>, void> final : public detail::bitstring_xor_t<N * 8, unsigned char> {};
template <std::size_t N, typename NodeT>
struct subtract_t<dpf::blob<N>, NodeT> final : public detail::bitstring_xor_t<N * 8, unsigned char> {};
/// @brief Bitwise XOR, not IEEE subtraction.
/// @tparam NodeT GGM node type
template <typename NodeT> struct subtract_t<float, NodeT> final : public std::bit_xor<> {};
template <typename NodeT> struct subtract_t<double, NodeT> final : public std::bit_xor<> {};
template <typename NodeT>
struct subtract_t<float, NodeT, std::enable_if_t<!std::is_void_v<NodeT>>>
final : public std::bit_xor<> {};
template <typename NodeT>
struct subtract_t<double, NodeT, std::enable_if_t<!std::is_void_v<NodeT>>>
final : public std::bit_xor<> {};
template <typename NodeT> struct subtract_t<dpf::bit, NodeT> final : public std::bit_xor<> {};
template <> struct subtract_t<dpf::bit, void> final : public std::bit_xor<> {};
template <typename T> struct subtract_t<xor_wrapper<T>, void> final : public std::bit_xor<> {};
@ -847,9 +939,9 @@ template <> struct multiply_t<simde_int128, simde__m128i> final
{
simde_int128 a_;
simde__m128i c;
std::memcpy(&a_, &a, sizeof(simde_int128));
utils::raw_memcpy(&a_, &a, sizeof(simde_int128));
simde_int128 c_ = a_ * b;
std::memcpy(&c, &c_, sizeof(simde__m128i));
utils::raw_memcpy(&c, &c_, sizeof(simde__m128i));
return c;
}
};
@ -860,9 +952,9 @@ template <> struct multiply_t<simde_uint128, simde__m128i> final
{
simde_uint128 a_;
simde__m128i c;
std::memcpy(&a_, &a, sizeof(simde_uint128));
utils::raw_memcpy(&a_, &a, sizeof(simde_uint128));
simde_uint128 c_ = a_ * b;
std::memcpy(&c, &c_, sizeof(simde__m128i));
utils::raw_memcpy(&c, &c_, sizeof(simde__m128i));
return c;
}
};
@ -908,8 +1000,8 @@ struct multiply_t<xor_wrapper<T>, simde__m128i> final
} else {
alignas(simde__m128i) unsigned char buf[sizeof(simde__m128i)]{};
for (std::size_t off = 0; off + sizeof(val_t) <= sizeof(buf); off += sizeof(val_t))
std::memcpy(buf + off, &v, sizeof(val_t));
std::memcpy(&bb, buf, sizeof(bb));
utils::raw_memcpy(buf + off, &v, sizeof(val_t));
utils::raw_memcpy(&bb, buf, sizeof(bb));
}
return simde_mm_and_si128(a, bb);
}
@ -933,8 +1025,8 @@ struct multiply_t<xor_wrapper<T>, simde__m256i> final
} else {
alignas(simde__m256i) unsigned char buf[sizeof(simde__m256i)]{};
for (std::size_t off = 0; off + sizeof(val_t) <= sizeof(buf); off += sizeof(val_t))
std::memcpy(buf + off, &v, sizeof(val_t));
std::memcpy(&bb, buf, sizeof(bb));
utils::raw_memcpy(buf + off, &v, sizeof(val_t));
utils::raw_memcpy(&bb, buf, sizeof(bb));
}
return simde_mm256_and_si256(a, bb);
}
@ -986,7 +1078,7 @@ struct multiply_t<float, simde__m128i> final
{
static_assert(sizeof(float) == 4, "float must be 32 bits");
psnip_uint32_t bits = 0;
std::memcpy(&bits, &b, sizeof(bits));
utils::raw_memcpy(&bits, &b, sizeof(bits));
return simde_mm_and_si128(a, simde_mm_set1_epi32(static_cast<int>(bits)));
}
};
@ -998,7 +1090,7 @@ struct multiply_t<float, simde__m256i> final
{
static_assert(sizeof(float) == 4, "float must be 32 bits");
psnip_uint32_t bits = 0;
std::memcpy(&bits, &b, sizeof(bits));
utils::raw_memcpy(&bits, &b, sizeof(bits));
return simde_mm256_and_si256(a, simde_mm256_set1_epi32(static_cast<int>(bits)));
}
};
@ -1010,7 +1102,7 @@ struct multiply_t<double, simde__m128i> final
{
static_assert(sizeof(double) == 8, "double must be 64 bits");
psnip_uint64_t bits = 0;
std::memcpy(&bits, &b, sizeof(bits));
utils::raw_memcpy(&bits, &b, sizeof(bits));
return simde_mm_and_si128(a, simde_mm_set1_epi64x(static_cast<long long>(bits)));
}
};
@ -1022,7 +1114,7 @@ struct multiply_t<double, simde__m256i> final
{
static_assert(sizeof(double) == 8, "double must be 64 bits");
psnip_uint64_t bits = 0;
std::memcpy(&bits, &b, sizeof(bits));
utils::raw_memcpy(&bits, &b, sizeof(bits));
return simde_mm256_and_si256(a, simde_mm256_set1_epi64x(static_cast<long long>(bits)));
}
};