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

@ -0,0 +1,283 @@
/// @file grotto/carry_plan.hpp
/// @brief Pure planner for carry-in, carry-out, and fused bitwidth corrections.
/// @details A request names the width change and what is known about the sign.
/// The recipe lists only the primitives that are still live after the
/// output modulus and a public incoming carry have killed the rest.
/// No keys are allocated here.
/// @copyright Copyright (c) 2019-2026 Ryan Henry and [others](@ref authors)
/// @license Released under a GNU General Public v2.0 (GPLv2) license.
#ifndef LIBDPF_INCLUDE_GROTTO_CARRY_PLAN_HPP__
#define LIBDPF_INCLUDE_GROTTO_CARRY_PLAN_HPP__
#include <cstdint>
#include <stdexcept>
#include "hedley/hedley.h"
namespace grotto
{
/// @brief Kind of bitwidth change the caller wants.
enum class carry_mode : std::uint8_t
{
/// Drop `s` low bits; result lives in `Z/2^{n-s}`. Only carry-in survives.
truncate_reduce = 0,
/// Arithmetic right shift that stays in `Z/2^n`. Carry-out (sign wrap).
same_ring = 1,
/// Signed extension from `n` bits to `out_n` bits. Biased wrap only.
extend = 2,
/// Digit / window of width `s` with an optional incoming carry.
window = 3
};
/// @brief What the caller already knows about `msb(x)`.
enum class sign_knowledge : std::uint8_t
{
unknown = 0,
nonnegative = 1,
negative = 2
};
/// @brief Inputs to the planner. Widths are in bits.
struct carry_request
{
/// @brief Source ring bitlength.
unsigned n = 0;
/// @brief Truncation / window width. Unused for plain `extend`.
unsigned s = 0;
/// @brief Output ring bitlength.
unsigned out_n = 0;
/// @brief Which width change to plan.
carry_mode mode = carry_mode::truncate_reduce;
/// @brief Sign knowledge for same-ring carry-out.
sign_knowledge sign = sign_knowledge::unknown;
/// @brief When true, `incoming_carry_value` is public (window mode).
bool incoming_carry_public = false;
/// @brief Public incoming carry when `incoming_carry_public`.
unsigned incoming_carry_value = 0;
/// @brief Ask for both carries when the mode would otherwise drop one.
/// A reduced-ring modulus still kills the sign term.
bool fuse = false;
};
/// @brief Primitives the evaluator must materialise for one request.
struct carry_recipe
{
carry_mode mode = carry_mode::truncate_reduce;
unsigned n = 0;
unsigned s = 0;
unsigned out_n = 0;
sign_knowledge sign = sign_knowledge::unknown;
/// @brief Low-limb overflow `1{v0+v1 >= 2^s}` (truncate-reduce / fused).
bool use_low_lt = false;
/// @brief Comparison of `x` against `2^{n-1}` (secret-sign carry-out).
bool use_msb_lt = false;
/// @brief Beaver AND of the two share MSBs (known-sign, or fused with msb).
bool use_share_msb_and = false;
/// @brief When true the AND is of the complemented share MSBs (NOR).
bool and_is_nor = false;
/// @brief Signed extension: wrap after the public bias `2^{n-1}`.
bool use_biased_wrap = false;
/// @brief Window: `1{p0+p1 >= 2^d}`.
bool use_window_overflow = false;
/// @brief Window: `1{p0+p1 == 2^d-1}` (only when incoming carry is secret).
bool use_window_eq = false;
/// @brief Window: product of equality bit and secret incoming carry.
bool use_window_product = false;
/// @brief Units of `±2^{n-s}` applied after the share-MSB AND.
std::int64_t and_unit = 0;
/// @brief Payload of the MSB comparison when it alone selects the unit.
std::int64_t msb_true_payload = 0;
/// @brief Payload for the biased wrap (`2^n` in the wide ring).
std::int64_t wrap_payload = 0;
/// @brief Window digit width (`s`).
unsigned window_d = 0;
/// @brief Public incoming carry absorbed locally when known.
unsigned public_incoming = 0;
/// @brief True when the recipe named at least one interactive step.
bool interactive() const noexcept
{
return use_low_lt || use_msb_lt || use_share_msb_and || use_biased_wrap
|| use_window_overflow || use_window_eq || use_window_product;
}
};
namespace carry_plan_detail
{
inline std::int64_t unit_pow2(unsigned e)
{
if (e >= 63u)
throw std::invalid_argument("carry_plan: unit does not fit in int64");
return std::int64_t{1} << e;
}
} // namespace carry_plan_detail
/// @brief Select the cheapest live primitives for `req`.
/// @param req the request
/// @return a recipe whose flags name only the corrections that survive
/// @throws std::invalid_argument on inconsistent widths
/// \complexity A constant number of comparisons of `n`, `s`, `out_n`, and `sign`. No allocation beyond the returned `carry_recipe`. `Θ(1)`.
/// @see grotto::make_carry_keys
HEDLEY_WARN_UNUSED_RESULT
inline carry_recipe plan_carry(const carry_request & req)
{
if (req.n == 0u)
throw std::invalid_argument("carry_plan: n must be positive");
if (req.out_n == 0u)
throw std::invalid_argument("carry_plan: out_n must be positive");
carry_recipe r{};
r.mode = req.mode;
r.n = req.n;
r.s = req.s;
r.out_n = req.out_n;
r.sign = req.sign;
const bool reduced_ring = (req.out_n + req.s == req.n) && (req.s > 0u);
const bool same_width = (req.out_n == req.n);
switch (req.mode)
{
case carry_mode::truncate_reduce:
{
if (req.s == 0u || req.s >= req.n)
throw std::invalid_argument("carry_plan: truncate_reduce needs 0 < s < n");
if (req.out_n != req.n - req.s)
throw std::invalid_argument(
"carry_plan: truncate_reduce out_n must equal n-s");
r.use_low_lt = true;
// Sign wrap is 0 in Z/2^{n-s}; never emit a carry-out term.
break;
}
case carry_mode::same_ring:
{
if (req.s >= req.n)
throw std::invalid_argument("carry_plan: same_ring needs s < n");
if (!same_width)
{
// Caller asked for a fused shift that reduces the ring: drop
// carry-out and keep only the low-limb correction.
if (req.out_n != req.n - req.s)
throw std::invalid_argument(
"carry_plan: same_ring out_n must be n or n-s");
r.use_low_lt = true;
break;
}
if (req.fuse || req.s > 0u)
r.use_low_lt = (req.s > 0u) && req.fuse;
if (req.sign == sign_knowledge::unknown)
{
r.use_msb_lt = true;
r.use_share_msb_and = true;
r.msb_true_payload = 1; // returns msb bit; combined with AND below
r.and_unit = carry_plan_detail::unit_pow2(req.n - req.s);
}
else if (req.sign == sign_knowledge::nonnegative)
{
r.use_share_msb_and = true;
r.and_is_nor = false;
r.and_unit = carry_plan_detail::unit_pow2(req.n - req.s);
}
else
{
r.use_share_msb_and = true;
r.and_is_nor = true;
r.and_unit = -carry_plan_detail::unit_pow2(req.n - req.s);
}
break;
}
case carry_mode::extend:
{
if (req.out_n <= req.n)
throw std::invalid_argument("carry_plan: extend needs out_n > n");
// Known sign does not switch to the share-MSB AND.
r.use_biased_wrap = true;
r.wrap_payload = carry_plan_detail::unit_pow2(req.n);
break;
}
case carry_mode::window:
{
if (req.s == 0u || req.s > req.n)
throw std::invalid_argument("carry_plan: window needs 0 < s <= n");
r.window_d = req.s;
r.use_window_overflow = true;
if (req.incoming_carry_public)
{
r.public_incoming = req.incoming_carry_value;
// Public carry 0 drops the equality; a public 1 still needs the
// all-ones test, but the product is local (multiply by 1).
if (req.incoming_carry_value != 0u)
r.use_window_eq = true;
}
else
{
r.use_window_eq = true;
r.use_window_product = true;
}
break;
}
}
// Fused same-ring request that somehow landed with a reduced modulus:
// the planner already dropped the sign term above via `!same_width`.
(void)reduced_ring;
return r;
}
/// @brief Fill a truncate-and-reduce request and plan it.
/// \complexity Fills a `carry_request` and calls `plan_carry`. `Θ(1)`.
/// @see grotto::plan_carry
HEDLEY_WARN_UNUSED_RESULT
inline carry_recipe plan_carry_in(unsigned n, unsigned s)
{
carry_request req{};
req.n = n;
req.s = s;
req.out_n = n - s;
req.mode = carry_mode::truncate_reduce;
return plan_carry(req);
}
/// @brief Fill a same-ring carry-out request and plan it.
/// \complexity Fills a `carry_request` and calls `plan_carry`. `Θ(1)`.
/// @see grotto::plan_carry
HEDLEY_WARN_UNUSED_RESULT
inline carry_recipe plan_carry_out(unsigned n, unsigned s, sign_knowledge sign)
{
carry_request req{};
req.n = n;
req.s = s;
req.out_n = n;
req.mode = carry_mode::same_ring;
req.sign = sign;
req.fuse = false;
return plan_carry(req);
}
/// @brief Fill a fused same-ring exact-shift request and plan it.
/// @details When `out_n == n-s` the sign term is dropped automatically.
/// \complexity Fills a `carry_request` and calls `plan_carry`. `Θ(1)`.
/// @see grotto::plan_carry
HEDLEY_WARN_UNUSED_RESULT
inline carry_recipe plan_carry_fused(unsigned n, unsigned s, unsigned out_n,
sign_knowledge sign = sign_knowledge::unknown)
{
carry_request req{};
req.n = n;
req.s = s;
req.out_n = out_n;
req.mode = carry_mode::same_ring;
req.sign = sign;
req.fuse = true;
return plan_carry(req);
}
} // namespace grotto
#endif // LIBDPF_INCLUDE_GROTTO_CARRY_PLAN_HPP__