libdpf/include/dpf/factory_tapes.hpp

108 lines
4 KiB
C++
Raw Normal View History

/// @file dpf/factory_tapes.hpp
/// @brief Dealer stream layouts for `factory_gadgets` online tapes (A2B, trunc, GT).
#ifndef LIBDPF_INCLUDE_DPF_FACTORY_TAPES_HPP__
#define LIBDPF_INCLUDE_DPF_FACTORY_TAPES_HPP__
#include <cstddef>
#include <cstdint>
#include <stdexcept>
#include <type_traits>
#include <utility>
#include "dpf/protocol_factory.hpp"
namespace dpf
{
namespace factory
{
namespace detail
{
inline std::pair<gmw_and_blind, gmw_and_blind> deal_gmw_and_blind_pair()
{
auto t = deal_bit_triple();
gmw_and_blind v0{t.first.a, t.first.b, t.first.c};
gmw_and_blind v1{t.second.a, t.second.b, t.second.c};
return {v0, v1};
}
template <typename F>
inline void deal_tape_pod(net::stream_array & party0, net::stream_array & party1,
std::size_t stream, std::size_t count, F && f)
{
if (stream >= party0.size() || stream >= party1.size())
throw std::invalid_argument("deal_tape_pod: stream index");
for (std::size_t j = 0; j < count; ++j)
{
auto views = f();
using V0 = std::decay_t<decltype(views.first)>;
using V1 = std::decay_t<decltype(views.second)>;
static_assert(std::is_trivially_copyable_v<V0>
&& std::is_trivially_copyable_v<V1>,
"deal_tape_pod views must be trivially copyable");
if (sizeof(V0) != sizeof(V1))
throw std::logic_error("deal_tape_pod: unequal view sizes");
detail::write_pod(party0, stream, views.first);
detail::write_pod(party1, stream, views.second);
}
party0.flush(stream);
party1.flush(stream);
}
} // namespace detail
/// @brief Sequential dabits then AND blinds for one `a2b_online` pass.
inline void deal_a2b_tape(unsigned width, std::uint16_t limb,
net::stream_array & party0, net::stream_array & party1,
std::size_t dabit_stream = 0, std::size_t and_blind_stream = 1)
{
if (width == 0 || width > 64)
throw std::invalid_argument("deal_a2b_tape width");
const std::size_t need =
1 + (dabit_stream > and_blind_stream ? dabit_stream : and_blind_stream);
if (party0.size() < need || party1.size() < need)
throw std::invalid_argument("deal_a2b_tape: not enough streams");
detail::deal_tape_pod(party0, party1, dabit_stream, width,
[limb] { return deal_dabit(limb); });
detail::deal_tape_pod(party0, party1, and_blind_stream, width,
[] { return detail::deal_gmw_and_blind_pair(); });
}
/// @brief `s + 1` dabits (low mask + B2A wrap) and `s` AND blinds for trunc.
inline void deal_trunc_tape(unsigned n, unsigned s, std::uint16_t limb,
net::stream_array & party0, net::stream_array & party1,
std::size_t dabit_stream = 0, std::size_t and_blind_stream = 1)
{
if (s >= n || n > 64)
throw std::invalid_argument("deal_trunc_tape");
const std::size_t need =
1 + (dabit_stream > and_blind_stream ? dabit_stream : and_blind_stream);
if (party0.size() < need || party1.size() < need)
throw std::invalid_argument("deal_trunc_tape: not enough streams");
detail::deal_tape_pod(party0, party1, dabit_stream, s + 1u,
[limb] { return deal_dabit(limb); });
detail::deal_tape_pod(party0, party1, and_blind_stream, s,
[] { return detail::deal_gmw_and_blind_pair(); });
}
/// @brief Dealer layout for `gt_online`: streams 0–1 (x A2B), 2–3 (y), 4 compare.
inline void deal_gt_tape(unsigned width, std::uint16_t limb,
net::stream_array & party0, net::stream_array & party1)
{
if (width == 0 || width > 64)
throw std::invalid_argument("deal_gt_tape width");
constexpr std::size_t k_gt_streams = 5;
if (party0.size() < k_gt_streams || party1.size() < k_gt_streams)
throw std::invalid_argument("deal_gt_tape: need 5 dealer streams");
deal_a2b_tape(width, limb, party0, party1, 0, 1);
deal_a2b_tape(width, limb, party0, party1, 2, 3);
detail::deal_tape_pod(party0, party1, 4, 3u * width,
[] { return detail::deal_gmw_and_blind_pair(); });
}
} // namespace factory
} // namespace dpf
#endif