146 lines
4.2 KiB
C++
146 lines
4.2 KiB
C++
|
|
/// @file examples/protocol/stream_dpf3_smoke.cpp
|
||
|
|
/// @brief Local DPF3 eval plus trio-shaped stream edges (peer / rss_next / dealer).
|
||
|
|
#include <cstdint>
|
||
|
|
#include <cstring>
|
||
|
|
#include <iostream>
|
||
|
|
#include <thread>
|
||
|
|
#include <type_traits>
|
||
|
|
#include <vector>
|
||
|
|
|
||
|
|
#include "dpf.hpp"
|
||
|
|
#include "dpf/net/stream_array.hpp"
|
||
|
|
#include "dpf/net/stream_mesh.hpp"
|
||
|
|
#include "dpf/protocol_factory.hpp"
|
||
|
|
|
||
|
|
namespace
|
||
|
|
{
|
||
|
|
|
||
|
|
struct trio_edge_ping
|
||
|
|
{
|
||
|
|
std::uint32_t from = 0;
|
||
|
|
std::uint32_t to = 0;
|
||
|
|
std::uint64_t nonce = 0;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct trio_party_streams
|
||
|
|
{
|
||
|
|
dpf::net::memory_stream_array & peer;
|
||
|
|
dpf::net::memory_stream_array & rss_next;
|
||
|
|
dpf::net::memory_stream_array & dealer;
|
||
|
|
};
|
||
|
|
|
||
|
|
template <typename T>
|
||
|
|
void exchange_pod(dpf::net::memory_stream_array & link, std::size_t stream,
|
||
|
|
const T & mine, T & theirs)
|
||
|
|
{
|
||
|
|
static_assert(std::is_trivially_copyable_v<T>, "pod");
|
||
|
|
link.write(stream, &mine, sizeof(T));
|
||
|
|
link.flush(stream);
|
||
|
|
link.read(stream, &theirs, sizeof(T));
|
||
|
|
}
|
||
|
|
|
||
|
|
void ping_edge(trio_party_streams s, unsigned me, unsigned peer_id,
|
||
|
|
std::uint64_t nonce, std::size_t stream_idx)
|
||
|
|
{
|
||
|
|
trio_edge_ping mine{me, peer_id, nonce};
|
||
|
|
trio_edge_ping theirs{};
|
||
|
|
exchange_pod(s.peer, stream_idx, mine, theirs);
|
||
|
|
if (theirs.from != peer_id || theirs.to != me)
|
||
|
|
throw std::runtime_error("stream_dpf3_smoke: peer edge");
|
||
|
|
}
|
||
|
|
|
||
|
|
} // namespace
|
||
|
|
|
||
|
|
int main()
|
||
|
|
{
|
||
|
|
using Input = std::uint8_t;
|
||
|
|
const Input alpha = 42;
|
||
|
|
const dpf::fp61 beta{7};
|
||
|
|
|
||
|
|
auto [k1, k2, k3] = dpf::make_dpf3(alpha, beta);
|
||
|
|
const dpf::fp61 y1 = dpf::eval_point(k1, alpha);
|
||
|
|
const dpf::fp61 y2 = dpf::eval_point(k2, alpha);
|
||
|
|
const dpf::fp61 y3 = dpf::eval_point(k3, alpha);
|
||
|
|
const dpf::fp61 opened = dpf::reconstruct(
|
||
|
|
dpf::as_share(k1, y1), dpf::as_share(k2, y2), dpf::as_share(k3, y3));
|
||
|
|
if (opened != beta)
|
||
|
|
{
|
||
|
|
std::cerr << "dpf3 local eval\n";
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Dealer delivers a keyed marker on stream 0 to each evaluator.
|
||
|
|
auto dealer0 = dpf::net::make_memory_stream_pair(1);
|
||
|
|
auto dealer1 = dpf::net::make_memory_stream_pair(1);
|
||
|
|
struct key_delivery
|
||
|
|
{
|
||
|
|
std::uint32_t party = 0;
|
||
|
|
std::uint64_t beta_raw = 0;
|
||
|
|
};
|
||
|
|
key_delivery m0{0, beta.raw()}, m1{1, beta.raw()};
|
||
|
|
dealer0.first.write(0, &m0, sizeof(m0));
|
||
|
|
dealer0.first.flush(0);
|
||
|
|
dealer1.first.write(0, &m1, sizeof(m1));
|
||
|
|
dealer1.first.flush(0);
|
||
|
|
key_delivery got0{}, got1{};
|
||
|
|
dealer0.second.read(0, &got0, sizeof(got0));
|
||
|
|
dealer1.second.read(0, &got1, sizeof(got1));
|
||
|
|
if (got0.beta_raw != beta.raw() || got1.beta_raw != beta.raw())
|
||
|
|
{
|
||
|
|
std::cerr << "dealer stream delivery\n";
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Trio-shaped edges on a 3-party clique (p2 = dealer): peer + rss_next + dealer.
|
||
|
|
constexpr std::size_t k_peer = 0;
|
||
|
|
constexpr std::size_t k_rss = 1;
|
||
|
|
auto clique = dpf::net::make_memory_stream_clique(3, 2);
|
||
|
|
std::exception_ptr err;
|
||
|
|
std::thread t0([&] {
|
||
|
|
try
|
||
|
|
{
|
||
|
|
trio_party_streams s{clique.end(0, 1), clique.end(0, 1), clique.end(0, 2)};
|
||
|
|
ping_edge(s, 0, 1, 11, k_peer);
|
||
|
|
const trio_edge_ping rss_out{0, 1, 99};
|
||
|
|
s.rss_next.write(k_rss, &rss_out, sizeof(rss_out));
|
||
|
|
s.rss_next.flush(k_rss);
|
||
|
|
}
|
||
|
|
catch (...)
|
||
|
|
{
|
||
|
|
err = std::current_exception();
|
||
|
|
}
|
||
|
|
});
|
||
|
|
std::thread t1([&] {
|
||
|
|
try
|
||
|
|
{
|
||
|
|
trio_party_streams s{clique.end(1, 0), clique.end(1, 0), clique.end(1, 2)};
|
||
|
|
ping_edge(s, 1, 0, 22, k_peer);
|
||
|
|
trio_edge_ping rss_in{};
|
||
|
|
s.rss_next.read(k_rss, &rss_in, sizeof(rss_in));
|
||
|
|
if (rss_in.from != 0u)
|
||
|
|
throw std::runtime_error("stream_dpf3_smoke: rss_next");
|
||
|
|
const trio_edge_ping dealer_out{1, 2, 88};
|
||
|
|
s.dealer.write(k_rss, &dealer_out, sizeof(dealer_out));
|
||
|
|
s.dealer.flush(k_rss);
|
||
|
|
}
|
||
|
|
catch (...)
|
||
|
|
{
|
||
|
|
err = std::current_exception();
|
||
|
|
}
|
||
|
|
});
|
||
|
|
t0.join();
|
||
|
|
t1.join();
|
||
|
|
if (err)
|
||
|
|
std::rethrow_exception(err);
|
||
|
|
trio_edge_ping dealer_in{};
|
||
|
|
clique.end(2, 1).read(k_rss, &dealer_in, sizeof(dealer_in));
|
||
|
|
if (dealer_in.from != 1u || dealer_in.to != 2u)
|
||
|
|
{
|
||
|
|
std::cerr << "dealer edge\n";
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
std::cout << "stream_trio_ok\n";
|
||
|
|
return 0;
|
||
|
|
}
|