/// @file examples/protocol/share_runtime.cpp /// @brief Smoke demo: stream_array dealer/peer gadgets and clear sanity checks. /// @details Also drives a composed open on the stream framework /// (`drive_both_on_streams`). The same protocol runs unchanged over the /// truly asynchronous backends (`dpf::net::async_stream_array` + /// `dpf::async::overlapped_byte_protocol`, or `async_round_sink`), and /// on Linux over real SCTP (`async_sctp_stream_array`, index i -> SCTP /// stream i). The performance harness (experiment_bench) selects any of /// these with `DPF_TRANSPORT=memory|stream|async|mux|parallel|sctp`. #include #include #include #include #include #include "dpf/compose.hpp" #include "dpf/factory_gadgets.hpp" #include "dpf/net/stream_array.hpp" #include "dpf/protocol_factory.hpp" #include "dpf/rss_seed.hpp" int main() { auto bundle = dpf::rss::sample_seed_bundle(); auto z0 = dpf::rss::zero_share( dpf::rss::party_seeds::from_bundle(bundle, 0), 0); auto z1 = dpf::rss::zero_share( dpf::rss::party_seeds::from_bundle(bundle, 1), 0); auto z2 = dpf::rss::zero_share( dpf::rss::party_seeds::from_bundle(bundle, 2), 0); std::cout << "rss_zero_sum=" << (z0 + z1 + z2) << "\n"; // Dealer: one ring triple per party; peer: d and e opens. auto peer = dpf::net::make_memory_stream_pair(2); auto d0 = dpf::net::make_memory_stream_pair(1); auto d1 = dpf::net::make_memory_stream_pair(1); constexpr std::uint16_t limb = 8; dpf::factory::make_dealer(d0.first, d1.first, 1, [limb] { return dpf::factory::deal_ring_triple(limb); }); std::uint64_t prod0 = 0, prod1 = 0; std::thread t0([&] { prod0 = dpf::factory::beaver_mul_online(0, 6, 7, peer.first, d0.second, 0, 0, 1, limb); }); std::thread t1([&] { prod1 = dpf::factory::beaver_mul_online(1, 0, 0, peer.second, d1.second, 0, 0, 1, limb); }); t0.join(); t1.join(); std::cout << "beaver_mul_open=" << (prod0 + prod1) << "\n"; // GMW AND 1∧1 via make_protocol_factory. auto and_peer = dpf::net::make_memory_stream_pair(1); auto ad0 = dpf::net::make_memory_stream_pair(1); auto ad1 = dpf::net::make_memory_stream_pair(1); dpf::factory::make_dealer(ad0.first, ad1.first, 1, dpf::factory::make_gmw_and_dealer_functor()); std::uint8_t z0b = 0, z1b = 0; std::thread a0([&] { z0b = dpf::factory::gmw_and_online(0, 1, 1, and_peer.first, ad0.second); }); std::thread a1([&] { z1b = dpf::factory::gmw_and_online(1, 0, 0, and_peer.second, ad1.second); }); a0.join(); a1.join(); std::cout << "gmw_and_xor=" << static_cast(z0b ^ z1b) << "\n"; // Compose an open and drive both parties on the stream framework. This is // the same schedule the async backends run; here it uses in-process memory // stream arrays via drive_both_on_streams. { using dpf::protocol::domain; dpf::protocol::composer comp0(0), comp1(1); auto a = comp0.input(domain::a, 8); auto b = comp1.input(domain::a, 8); auto oa = comp0.exchange(a); auto ob = comp1.exchange(b); auto p0 = comp0.schedule(); auto p1 = comp1.schedule(); std::vector> va(p0.nodes().size()), vb(p1.nodes().size()); const std::uint64_t xa = 17, xb = 25; va[a.id].assign(8, 0); vb[b.id].assign(8, 0); std::memcpy(va[a.id].data(), &xa, 8); std::memcpy(vb[b.id].data(), &xb, 8); dpf::protocol::drive_both_on_streams(p0, p1, va, vb); std::uint64_t open0 = 0; std::memcpy(&open0, va[oa.id].data(), 8); (void)ob; std::cout << "compose_open_on_streams=" << open0 << "\n"; } return 0; }