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
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "dpf/utils.hpp"
|
||||
#include "dpf/secret_share.hpp"
|
||||
#include "dpf/verifiable.hpp"
|
||||
|
||||
namespace dpf
|
||||
{
|
||||
|
|
@ -67,6 +68,7 @@ struct path_memoizer_base
|
|||
/// written for the current input. Callers pass this object to `eval_point`;
|
||||
/// they do not call `assign_x` themselves.
|
||||
/// @tparam DpfKey DPF key type
|
||||
/// \complexity O(n) nodes, one per level (`arr_` has `depth + 1` slots). `assign_x` is O(1) after a common-prefix XOR.
|
||||
template <typename DpfKey>
|
||||
struct alignas(alignof(typename path_memoizer_key_t<DpfKey>::interior_node))
|
||||
basic_path_memoizer final
|
||||
|
|
@ -170,6 +172,7 @@ HEDLEY_PRAGMA(GCC diagnostic pop)
|
|||
|
||||
/// @brief A single interior node. Every `assign_x` restarts at the root.
|
||||
/// @tparam DpfKey DPF key type
|
||||
/// \complexity O(1) space (one node). Every `assign_x` restarts at the root, so `eval_point` still walks n levels.
|
||||
template <typename DpfKey>
|
||||
struct nonmemoizing_path_memoizer final
|
||||
: public path_memoizer_base<path_memoizer_key_t<DpfKey>>
|
||||
|
|
@ -271,27 +274,72 @@ void path_note_filled_to(PathMemoizer & path, std::size_t level)
|
|||
}
|
||||
|
||||
/// @brief Walk interior nodes so `path[0..to_level]` is valid for `x`.
|
||||
/// @details When `pi` is non-null and the key is verifiable, each newly
|
||||
/// traversed node is folded into the proof token (LightShark-style
|
||||
/// path authentication on aggregate walks). When `fold_cached` is
|
||||
/// true, nodes already held by the memoizer are hashed into `pi`
|
||||
/// without re-expanding the PRG — required after `init_proof` on a
|
||||
/// warm path. Leave `fold_cached` false when continuing one
|
||||
/// accumulator that already contains those nodes.
|
||||
/// @tparam DpfKey DPF key type
|
||||
/// @tparam PathMemoizer path memoizer type
|
||||
/// @param dpf the DPF key
|
||||
/// @param x the `x`
|
||||
/// @param path the root-to-leaf path
|
||||
/// @param to_level the `to_level`
|
||||
/// @param pi optional VDPF proof accumulator
|
||||
/// @param fold_cached whether to fold memoized prefix nodes into a fresh token
|
||||
template <typename DpfKey, typename PathMemoizer>
|
||||
void ensure_level(const DpfKey & dpf, typename DpfKey::input_type x,
|
||||
PathMemoizer & path, std::size_t to_level)
|
||||
PathMemoizer & path, std::size_t to_level, proof_token * pi = nullptr,
|
||||
bool fold_cached = false)
|
||||
{
|
||||
auto level_index = path_resume_for_level(path, dpf, x, to_level);
|
||||
DPF_UNROLL_LOOP
|
||||
for (auto mask = dpf.msb_mask >> (level_index - 1);
|
||||
level_index <= to_level; ++level_index, mask >>= 1)
|
||||
if constexpr (DpfKey::is_verifiable)
|
||||
{
|
||||
bool bit = !!(mask & x);
|
||||
auto cw = dpf.correction_word(level_index - 1, bit);
|
||||
const bool is_last = DpfKey::tree::is_last_level(level_index - 1,
|
||||
dpf.depth);
|
||||
path[level_index] =
|
||||
DpfKey::traverse_interior(path[level_index - 1], cw, bit, is_last);
|
||||
if (pi != nullptr && fold_cached && level_index > 1)
|
||||
{
|
||||
for (std::size_t li = 1; li < level_index && li <= to_level; ++li)
|
||||
{
|
||||
const auto x_bits = static_cast<psnip_uint64_t>(
|
||||
utils::to_integral_type<typename DpfKey::input_type>{}(x)
|
||||
>> (utils::bitlength_of_v<typename DpfKey::input_type>
|
||||
- li));
|
||||
detail::vdpf::fold_node(*pi, li - 1, x_bits, path[li],
|
||||
dpf.correction_seeds()[li - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Resume past `to_level` means the spine is already valid. Do not form
|
||||
// `msb_mask >> (level_index - 1)` in that case: for a full-width domain
|
||||
// (`to_level == input_bits`) that shift is exactly the type width (UB).
|
||||
if (level_index <= to_level)
|
||||
{
|
||||
DPF_UNROLL_LOOP
|
||||
for (auto mask = dpf.msb_mask >> (level_index - 1);
|
||||
level_index <= to_level; ++level_index, mask >>= 1)
|
||||
{
|
||||
bool bit = !!(mask & x);
|
||||
auto cw = dpf.correction_word(level_index - 1, bit);
|
||||
const bool is_last = DpfKey::tree::is_last_level(level_index - 1,
|
||||
dpf.depth);
|
||||
path[level_index] =
|
||||
DpfKey::traverse_interior(path[level_index - 1], cw, bit,
|
||||
is_last);
|
||||
if constexpr (DpfKey::is_verifiable)
|
||||
{
|
||||
if (pi != nullptr)
|
||||
{
|
||||
const auto x_bits = static_cast<psnip_uint64_t>(
|
||||
utils::to_integral_type<typename DpfKey::input_type>{}(x)
|
||||
>> (utils::bitlength_of_v<typename DpfKey::input_type>
|
||||
- level_index));
|
||||
detail::vdpf::fold_node(*pi, level_index - 1, x_bits,
|
||||
path[level_index],
|
||||
dpf.correction_seeds()[level_index - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
path_note_filled_to(path, to_level);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue