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
179
include/dpf/net/memory_sink.hpp
Normal file
179
include/dpf/net/memory_sink.hpp
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
/// @file dpf/net/memory_sink.hpp
|
||||
/// @brief In-process paired RoundSink for correctness tests.
|
||||
#ifndef LIBDPF_INCLUDE_DPF_NET_MEMORY_SINK_HPP__
|
||||
#define LIBDPF_INCLUDE_DPF_NET_MEMORY_SINK_HPP__
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "dpf/net/round_sink.hpp"
|
||||
|
||||
namespace dpf
|
||||
{
|
||||
namespace net
|
||||
{
|
||||
|
||||
/// @brief Shared state between the two ends of a memory sink pair.
|
||||
struct memory_sink_hub
|
||||
{
|
||||
std::size_t count = 0;
|
||||
std::vector<std::size_t> slot_bytes;
|
||||
std::vector<round_window> a;
|
||||
std::vector<round_window> b;
|
||||
mutable std::mutex mu;
|
||||
|
||||
explicit memory_sink_hub(std::size_t n, std::vector<std::size_t> slots)
|
||||
: count(n), slot_bytes(std::move(slots))
|
||||
{
|
||||
a.reserve(slot_bytes.size());
|
||||
b.reserve(slot_bytes.size());
|
||||
for (std::size_t sb : slot_bytes)
|
||||
{
|
||||
a.emplace_back(count, sb);
|
||||
b.emplace_back(count, sb);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// @brief One end of a memory-paired RoundSink.
|
||||
class memory_sink : public RoundSink
|
||||
{
|
||||
public:
|
||||
memory_sink(std::shared_ptr<memory_sink_hub> hub, bool side_a)
|
||||
: hub_(std::move(hub)), side_a_(side_a)
|
||||
{
|
||||
if (!hub_)
|
||||
throw std::invalid_argument("memory_sink needs a hub");
|
||||
}
|
||||
|
||||
std::size_t count() const noexcept override { return hub_->count; }
|
||||
std::size_t rounds() const noexcept override
|
||||
{
|
||||
return hub_->slot_bytes.size();
|
||||
}
|
||||
|
||||
std::size_t slot_bytes(std::uint16_t round) const override
|
||||
{
|
||||
if (round >= hub_->slot_bytes.size())
|
||||
throw std::out_of_range("memory_sink round");
|
||||
return hub_->slot_bytes[round];
|
||||
}
|
||||
|
||||
void submit(std::uint16_t round, std::size_t index,
|
||||
const std::uint8_t * bytes, std::size_t n) override
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(hub_->mu);
|
||||
mine(round).submit(index, bytes, n);
|
||||
}
|
||||
|
||||
bool peer_ready(std::uint16_t round, std::size_t index) const override
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(hub_->mu);
|
||||
return mine(round).peer_ready(index);
|
||||
}
|
||||
|
||||
void read_peer(std::uint16_t round, std::size_t index, std::uint8_t * out,
|
||||
std::size_t n) const override
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(hub_->mu);
|
||||
mine(round).read_peer(index, out, n);
|
||||
}
|
||||
|
||||
void flush() override
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(hub_->mu);
|
||||
flush_unlocked();
|
||||
}
|
||||
|
||||
void flush_round(std::uint16_t round) override
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(hub_->mu);
|
||||
flush_round_unlocked(round);
|
||||
}
|
||||
|
||||
void poll() override {}
|
||||
|
||||
private:
|
||||
void flush_unlocked()
|
||||
{
|
||||
for (std::uint16_t r = 0; r < hub_->slot_bytes.size(); ++r)
|
||||
{
|
||||
std::size_t begin = 0;
|
||||
std::size_t n = 0;
|
||||
mine(r).pending_out(begin, n);
|
||||
if (n != 0)
|
||||
{
|
||||
flush_round_unlocked(r);
|
||||
continue;
|
||||
}
|
||||
peer(r).pending_out(begin, n);
|
||||
if (n != 0)
|
||||
flush_round_unlocked(r);
|
||||
}
|
||||
}
|
||||
|
||||
void flush_round_unlocked(std::uint16_t round)
|
||||
{
|
||||
if (round >= hub_->slot_bytes.size())
|
||||
throw std::out_of_range("memory_sink flush_round");
|
||||
auto & local = mine(round);
|
||||
auto & remote = peer(round);
|
||||
std::size_t begin_l = 0;
|
||||
std::size_t n_l = 0;
|
||||
const std::uint8_t * pend_l = local.pending_out(begin_l, n_l);
|
||||
std::size_t begin_r = 0;
|
||||
std::size_t n_r = 0;
|
||||
const std::uint8_t * pend_r = remote.pending_out(begin_r, n_r);
|
||||
if (n_l != 0)
|
||||
{
|
||||
remote.accept_peer_at(begin_l, pend_l, n_l);
|
||||
local.mark_flushed(n_l);
|
||||
}
|
||||
if (n_r != 0)
|
||||
{
|
||||
local.accept_peer_at(begin_r, pend_r, n_r);
|
||||
remote.mark_flushed(n_r);
|
||||
}
|
||||
}
|
||||
round_window & mine(std::uint16_t round)
|
||||
{
|
||||
if (round >= hub_->slot_bytes.size())
|
||||
throw std::out_of_range("memory_sink round");
|
||||
return side_a_ ? hub_->a[round] : hub_->b[round];
|
||||
}
|
||||
|
||||
const round_window & mine(std::uint16_t round) const
|
||||
{
|
||||
if (round >= hub_->slot_bytes.size())
|
||||
throw std::out_of_range("memory_sink round");
|
||||
return side_a_ ? hub_->a[round] : hub_->b[round];
|
||||
}
|
||||
|
||||
round_window & peer(std::uint16_t round)
|
||||
{
|
||||
if (round >= hub_->slot_bytes.size())
|
||||
throw std::out_of_range("memory_sink round");
|
||||
return side_a_ ? hub_->b[round] : hub_->a[round];
|
||||
}
|
||||
|
||||
std::shared_ptr<memory_sink_hub> hub_;
|
||||
bool side_a_ = true;
|
||||
};
|
||||
|
||||
/// @brief Build a connected pair of memory sinks that share one hub.
|
||||
inline std::pair<memory_sink, memory_sink> make_memory_sink_pair(
|
||||
std::size_t count, std::vector<std::size_t> slot_bytes)
|
||||
{
|
||||
auto hub = std::make_shared<memory_sink_hub>(count, std::move(slot_bytes));
|
||||
return {memory_sink(hub, true), memory_sink(hub, false)};
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace dpf
|
||||
|
||||
#endif // LIBDPF_INCLUDE_DPF_NET_MEMORY_SINK_HPP__
|
||||
Loading…
Add table
Add a link
Reference in a new issue