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
221
include/dpf/net/dealer_cursor.hpp
Normal file
221
include/dpf/net/dealer_cursor.hpp
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
/// @file dpf/net/dealer_cursor.hpp
|
||||
/// @brief Per-(round, index) correction words for a batch session.
|
||||
#ifndef LIBDPF_INCLUDE_DPF_NET_DEALER_CURSOR_HPP__
|
||||
#define LIBDPF_INCLUDE_DPF_NET_DEALER_CURSOR_HPP__
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "dpf/net/stream_array.hpp"
|
||||
|
||||
namespace dpf
|
||||
{
|
||||
namespace net
|
||||
{
|
||||
|
||||
/// @brief Empty correction / blind marker. Protocols that need no dealer
|
||||
/// material specialize on this type and skip the cursor.
|
||||
struct empty_pad
|
||||
{
|
||||
};
|
||||
|
||||
/// @brief Seekable table of dealer corrections, one lane per round.
|
||||
/// @details Size is fixed at construction: `count` instances and one slot
|
||||
/// width per round. Live dealers and inbox tapes both fill this
|
||||
/// table before the online session runs, or fill it lazily through
|
||||
/// `put`. Sessions read with `at(round, index)`.
|
||||
class dealer_cursor
|
||||
{
|
||||
public:
|
||||
dealer_cursor() = default;
|
||||
|
||||
dealer_cursor(std::size_t count, std::vector<std::size_t> slot_bytes)
|
||||
: count_(count),
|
||||
slot_bytes_(std::move(slot_bytes)),
|
||||
offsets_(slot_bytes_.size() + 1, 0)
|
||||
{
|
||||
for (std::size_t r = 0; r < slot_bytes_.size(); ++r)
|
||||
offsets_[r + 1] = offsets_[r] + count_ * slot_bytes_[r];
|
||||
store_.assign(offsets_.back(), 0);
|
||||
ready_.assign(slot_bytes_.size() * count_, false);
|
||||
}
|
||||
|
||||
std::size_t count() const noexcept { return count_; }
|
||||
std::size_t rounds() const noexcept { return slot_bytes_.size(); }
|
||||
|
||||
std::size_t slot_bytes(std::uint16_t round) const
|
||||
{
|
||||
if (round >= slot_bytes_.size())
|
||||
throw std::out_of_range("dealer_cursor round");
|
||||
return slot_bytes_[round];
|
||||
}
|
||||
|
||||
void put(std::uint16_t round, std::size_t index, const std::uint8_t * bytes,
|
||||
std::size_t n)
|
||||
{
|
||||
check(round, index, n);
|
||||
std::memcpy(ptr(round, index), bytes, n);
|
||||
ready_[ready_index(round, index)] = true;
|
||||
}
|
||||
|
||||
/// @brief Fill every index of `round` from a contiguous dealer tape.
|
||||
void put_round(std::uint16_t round, const std::uint8_t * bytes,
|
||||
std::size_t nbytes)
|
||||
{
|
||||
if (round >= slot_bytes_.size())
|
||||
throw std::out_of_range("dealer_cursor round");
|
||||
const std::size_t need = count_ * slot_bytes_[round];
|
||||
if (nbytes != need)
|
||||
throw std::invalid_argument("dealer_cursor put_round size");
|
||||
if (need != 0)
|
||||
std::memcpy(store_.data() + offsets_[round], bytes, need);
|
||||
for (std::size_t i = 0; i < count_; ++i)
|
||||
ready_[ready_index(round, i)] = true;
|
||||
}
|
||||
|
||||
bool ready(std::uint16_t round, std::size_t index) const
|
||||
{
|
||||
if (round >= slot_bytes_.size() || index >= count_)
|
||||
return false;
|
||||
if (slot_bytes_[round] == 0)
|
||||
return true;
|
||||
return ready_[ready_index(round, index)];
|
||||
}
|
||||
|
||||
void at(std::uint16_t round, std::size_t index, std::uint8_t * out,
|
||||
std::size_t n) const
|
||||
{
|
||||
check(round, index, n);
|
||||
if (n == 0)
|
||||
return;
|
||||
if (!ready_[ready_index(round, index)])
|
||||
throw std::logic_error("dealer_cursor not ready");
|
||||
std::memcpy(out, ptr(round, index), n);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T at(std::uint16_t round, std::size_t index) const
|
||||
{
|
||||
static_assert(std::is_trivially_copyable_v<T>,
|
||||
"dealer_cursor::at requires a trivially copyable type");
|
||||
if constexpr (std::is_same_v<T, empty_pad>)
|
||||
{
|
||||
(void)round;
|
||||
(void)index;
|
||||
return empty_pad{};
|
||||
}
|
||||
else
|
||||
{
|
||||
T out{};
|
||||
at(round, index, reinterpret_cast<std::uint8_t *>(&out), sizeof(T));
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Load each round from consecutive stream indexes (one tape per round).
|
||||
static dealer_cursor from_streams(stream_array & src, std::size_t count,
|
||||
std::vector<std::size_t> slot_bytes, std::size_t first_stream = 0)
|
||||
{
|
||||
dealer_cursor out(count, std::move(slot_bytes));
|
||||
for (std::uint16_t r = 0; r < out.rounds(); ++r)
|
||||
{
|
||||
const std::size_t need = count * out.slot_bytes(r);
|
||||
if (need == 0)
|
||||
continue;
|
||||
std::vector<std::uint8_t> buf(need);
|
||||
src.read(first_stream + r, buf.data(), need);
|
||||
out.put_round(r, buf.data(), need);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private:
|
||||
void check(std::uint16_t round, std::size_t index, std::size_t n) const
|
||||
{
|
||||
if (round >= slot_bytes_.size() || index >= count_)
|
||||
throw std::out_of_range("dealer_cursor index");
|
||||
if (n != slot_bytes_[round])
|
||||
throw std::invalid_argument("dealer_cursor size");
|
||||
}
|
||||
|
||||
std::size_t ready_index(std::uint16_t round, std::size_t index) const noexcept
|
||||
{
|
||||
return static_cast<std::size_t>(round) * count_ + index;
|
||||
}
|
||||
|
||||
std::uint8_t * ptr(std::uint16_t round, std::size_t index) noexcept
|
||||
{
|
||||
return store_.data() + offsets_[round] + index * slot_bytes_[round];
|
||||
}
|
||||
|
||||
const std::uint8_t * ptr(std::uint16_t round, std::size_t index) const noexcept
|
||||
{
|
||||
return store_.data() + offsets_[round] + index * slot_bytes_[round];
|
||||
}
|
||||
|
||||
std::size_t count_ = 0;
|
||||
std::vector<std::size_t> slot_bytes_;
|
||||
std::vector<std::size_t> offsets_;
|
||||
std::vector<std::uint8_t> store_;
|
||||
std::vector<bool> ready_;
|
||||
};
|
||||
|
||||
/// @brief Prefetch a full dealer table from `stream_array` tapes (see `from_streams`).
|
||||
class stream_dealer_cursor
|
||||
{
|
||||
public:
|
||||
stream_dealer_cursor(stream_array & src, std::size_t count,
|
||||
std::vector<std::size_t> slot_bytes, std::size_t first_stream = 0)
|
||||
: inner_(dealer_cursor::from_streams(src, count, std::move(slot_bytes),
|
||||
first_stream))
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t count() const noexcept { return inner_.count(); }
|
||||
std::size_t rounds() const noexcept { return inner_.rounds(); }
|
||||
|
||||
std::size_t slot_bytes(std::uint16_t round) const
|
||||
{
|
||||
return inner_.slot_bytes(round);
|
||||
}
|
||||
|
||||
bool ready(std::uint16_t round, std::size_t index) const
|
||||
{
|
||||
return inner_.ready(round, index);
|
||||
}
|
||||
|
||||
void at(std::uint16_t round, std::size_t index, std::uint8_t * out,
|
||||
std::size_t n) const
|
||||
{
|
||||
inner_.at(round, index, out, n);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T at(std::uint16_t round, std::size_t index) const
|
||||
{
|
||||
return inner_.at<T>(round, index);
|
||||
}
|
||||
|
||||
const dealer_cursor & cursor() const noexcept { return inner_; }
|
||||
dealer_cursor & cursor() noexcept { return inner_; }
|
||||
|
||||
private:
|
||||
dealer_cursor inner_;
|
||||
};
|
||||
|
||||
/// @brief One-round table: `nbytes` must equal `count * slot_bytes[0]`.
|
||||
inline dealer_cursor dealer_cursor_from_stream(stream_array & a,
|
||||
std::size_t stream_index, std::size_t count, std::size_t slot_nbytes)
|
||||
{
|
||||
return dealer_cursor::from_streams(a, count, {slot_nbytes}, stream_index);
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace dpf
|
||||
|
||||
#endif // LIBDPF_INCLUDE_DPF_NET_DEALER_CURSOR_HPP__
|
||||
Loading…
Add table
Add a link
Reference in a new issue