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>
200 lines
6.2 KiB
C++
200 lines
6.2 KiB
C++
/// @file dpf/eval_target.hpp
|
|
/// @brief Eval channel tags for the unified DPF / iDPF / DCF surface.
|
|
/// @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_DPF_EVAL_TARGET_HPP__
|
|
#define LIBDPF_INCLUDE_DPF_EVAL_TARGET_HPP__
|
|
|
|
#include <cstddef>
|
|
#include <limits>
|
|
#include <type_traits>
|
|
|
|
#include "hedley/hedley.h"
|
|
|
|
namespace dpf
|
|
{
|
|
|
|
/// @brief Sentinel: deduce point-slot prefix from the key (`meta[I].prefix`).
|
|
inline constexpr std::size_t prefix_deduce =
|
|
std::numeric_limits<std::size_t>::max();
|
|
|
|
/// @brief Point-output channel: slot `I`, optional prefix check `N`.
|
|
/// @tparam I output index
|
|
/// @tparam N prefix length, or `prefix_deduce`
|
|
template <std::size_t I = 0, std::size_t N = prefix_deduce>
|
|
struct out_t
|
|
{
|
|
static constexpr std::size_t index = I;
|
|
static constexpr std::size_t prefix = N;
|
|
static constexpr bool prefix_fixed = (N != prefix_deduce);
|
|
};
|
|
|
|
template <std::size_t I = 0, std::size_t N = prefix_deduce>
|
|
inline constexpr out_t<I, N> out{};
|
|
|
|
/// @brief Comparison (DCF) channel.
|
|
struct cmp_t
|
|
{
|
|
};
|
|
inline constexpr cmp_t cmp{};
|
|
|
|
/// @brief Prefix of an `idcf` comparison. `L` is the number of leading bits.
|
|
/// @tparam L number of leading bits
|
|
template <std::size_t L>
|
|
struct cmp_prefix_t
|
|
{
|
|
static constexpr std::size_t length = L;
|
|
};
|
|
template <std::size_t L>
|
|
inline constexpr cmp_prefix_t<L> cmp_prefix{};
|
|
|
|
template <typename T>
|
|
struct is_out : std::false_type
|
|
{
|
|
};
|
|
template <std::size_t I, std::size_t N>
|
|
struct is_out<out_t<I, N>> : std::true_type
|
|
{
|
|
};
|
|
template <typename T>
|
|
inline constexpr bool is_out_v = is_out<std::decay_t<T>>::value;
|
|
|
|
template <typename T>
|
|
struct is_cmp_target : std::bool_constant<std::is_same_v<std::decay_t<T>, cmp_t>>
|
|
{
|
|
};
|
|
template <typename T>
|
|
inline constexpr bool is_cmp_target_v = is_cmp_target<T>::value;
|
|
|
|
template <typename T>
|
|
struct is_cmp_prefix_target : std::false_type
|
|
{
|
|
};
|
|
template <std::size_t L>
|
|
struct is_cmp_prefix_target<cmp_prefix_t<L>> : std::true_type
|
|
{
|
|
};
|
|
template <typename T>
|
|
inline constexpr bool is_cmp_prefix_target_v =
|
|
is_cmp_prefix_target<std::decay_t<T>>::value;
|
|
|
|
/// @brief True for channel tags that must not bind as the key in classic eval_*.
|
|
template <typename T>
|
|
inline constexpr bool is_eval_channel_tag_v =
|
|
is_out_v<T> || is_cmp_target_v<T> || is_cmp_prefix_target_v<T>;
|
|
|
|
template <typename T, typename = void>
|
|
struct looks_like_dpf_key : std::false_type
|
|
{
|
|
};
|
|
HEDLEY_PRAGMA(GCC diagnostic push)
|
|
HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes")
|
|
template <typename T>
|
|
struct looks_like_dpf_key<T,
|
|
std::void_t<typename T::input_type, typename T::interior_node>>
|
|
: std::true_type
|
|
{
|
|
};
|
|
HEDLEY_PRAGMA(GCC diagnostic pop)
|
|
template <typename T>
|
|
inline constexpr bool looks_like_dpf_key_v =
|
|
looks_like_dpf_key<std::decay_t<T>>::value;
|
|
|
|
template <typename T, typename = void>
|
|
struct is_incremental_dpf_key : std::false_type
|
|
{
|
|
};
|
|
template <typename T>
|
|
struct is_incremental_dpf_key<T,
|
|
std::void_t<decltype(T::cmp_depth), decltype(T::meta),
|
|
decltype(T::deepest_output)>> : std::true_type
|
|
{
|
|
};
|
|
template <typename T>
|
|
inline constexpr bool is_incremental_dpf_key_v =
|
|
is_incremental_dpf_key<std::decay_t<T>>::value;
|
|
|
|
/// @brief True only for keys that must use the slot-aware (multi-level / comparison)
|
|
/// eval path. Every key now carries a `slot_meta` table (so
|
|
/// `is_incremental_dpf_key_v` is true for all keys), but classic single-level
|
|
/// equal-width keys keep using the classic `eval_*` fast paths; they set
|
|
/// `is_multilevel == false`. Multi-level (`at<N>`) and comparison keys set it
|
|
/// to true.
|
|
/// @tparam T value type
|
|
template <typename T, typename = void>
|
|
struct is_multilevel_key : std::false_type
|
|
{
|
|
};
|
|
template <typename T>
|
|
struct is_multilevel_key<T, std::void_t<decltype(T::is_multilevel)>>
|
|
: std::bool_constant<T::is_multilevel>
|
|
{
|
|
};
|
|
template <typename T>
|
|
inline constexpr bool is_multilevel_key_v =
|
|
is_multilevel_key<std::decay_t<T>>::value;
|
|
|
|
/// @brief True when `T` stores its DPF key in a public member named `dpf_key`
|
|
/// and is not itself a DPF key.
|
|
/// @details Wrappers (`ic_key`, `vdpf_plus_key`, `dpf3_cmp_key`, `dpf3_ic_key`,
|
|
/// and the distributed `opened_*` envelopes) use that member name.
|
|
/// `party_key` inherits the DPF key, so it is not a wrapper.
|
|
template <typename T, typename = void>
|
|
struct has_embedded_dpf_key : std::false_type
|
|
{
|
|
};
|
|
template <typename T>
|
|
struct has_embedded_dpf_key<T,
|
|
std::void_t<decltype(std::declval<T &>().dpf_key)>>
|
|
: std::bool_constant<!looks_like_dpf_key_v<T>>
|
|
{
|
|
};
|
|
template <typename T>
|
|
inline constexpr bool has_embedded_dpf_key_v =
|
|
has_embedded_dpf_key<std::decay_t<T>>::value;
|
|
|
|
/// @brief The DPF key `T` evaluates as: `T` itself, or `T::dpf_key` peeled
|
|
/// until the result looks like a DPF key.
|
|
template <typename T, typename = void>
|
|
struct bare_dpf_key
|
|
{
|
|
using type = std::decay_t<T>;
|
|
};
|
|
template <typename T>
|
|
struct bare_dpf_key<T, std::enable_if_t<has_embedded_dpf_key_v<std::decay_t<T>>>>
|
|
: bare_dpf_key<std::decay_t<decltype(std::declval<std::decay_t<T> &>().dpf_key)>>
|
|
{
|
|
};
|
|
template <typename T>
|
|
using bare_dpf_key_t = typename bare_dpf_key<std::decay_t<T>>::type;
|
|
|
|
/// @brief Key-first protocol evals (`dpf3`, `dpf3_cmp`, `dpf3_ic`) keep their
|
|
/// own overloads. Peel does not replace those.
|
|
template <typename T, typename = void>
|
|
struct flag_is_dpf3 : std::false_type {};
|
|
template <typename T>
|
|
struct flag_is_dpf3<T, std::void_t<decltype(T::is_dpf3)>>
|
|
: std::bool_constant<T::is_dpf3> {};
|
|
|
|
template <typename T, typename = void>
|
|
struct flag_is_dpf3_cmp : std::false_type {};
|
|
template <typename T>
|
|
struct flag_is_dpf3_cmp<T, std::void_t<decltype(T::is_dpf3_cmp)>>
|
|
: std::bool_constant<T::is_dpf3_cmp> {};
|
|
|
|
template <typename T, typename = void>
|
|
struct flag_is_dpf3_ic : std::false_type {};
|
|
template <typename T>
|
|
struct flag_is_dpf3_ic<T, std::void_t<decltype(T::is_dpf3_ic)>>
|
|
: std::bool_constant<T::is_dpf3_ic> {};
|
|
|
|
template <typename T>
|
|
inline constexpr bool owns_protocol_eval_v =
|
|
flag_is_dpf3<std::decay_t<T>>::value
|
|
|| flag_is_dpf3_cmp<std::decay_t<T>>::value
|
|
|| flag_is_dpf3_ic<std::decay_t<T>>::value;
|
|
|
|
} // namespace dpf
|
|
|
|
#endif // LIBDPF_INCLUDE_DPF_EVAL_TARGET_HPP__
|