#include #include "dpf.hpp" #include #include namespace { simde__m128i g_roots[16]; int g_ri = 0; simde__m128i take_root() { return g_roots[g_ri++]; } struct Pad { uint64_t n = 1; simde__m128i block() { auto v = simde_mm_set_epi64x(static_cast(n), static_cast(n * 9 + 3)); n += 2; return v; } uint8_t bit() { return static_cast(n++ & 1u); } }; void reset_roots() { g_ri = 0; for (int i = 0; i < 16; ++i) g_roots[i] = simde_mm_set_epi64x(0x2222 * (i + 1), 0xBEEF0000u + i * 13); } template T bare(const T & v) { return v; } template T bare(const dpf::secret_share & s) { return s.raw(); } template auto recon(const A & a, const B & b) { using T = decltype(bare(a)); return static_cast(bare(a) - bare(b)); } template auto ev(const Key & key, In x) { return bare(*dpf::eval_point(key, x)); } } // namespace TEST(ArithPayload, DsXorIndexMatchesDealer) { using in_t = std::uint8_t; using out_t = std::uint32_t; const in_t alpha = 0x2a; const in_t x0 = 0x55; const in_t x1 = static_cast(alpha ^ x0); const out_t beta = 0x01020304; const out_t y0 = 0x00010002; const out_t y1 = static_cast(beta - y0); reset_roots(); auto dealer = dpf::make_dpf(alpha, dpf::root_sampler_t{take_root}, beta); reset_roots(); HEDLEY_PRAGMA(GCC diagnostic push) HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes") dpf::ds_randomness rng{take_root, Pad{}}; HEDLEY_PRAGMA(GCC diagnostic pop) auto ds = dpf::make_dpf_doerner_shelat(dpf::arith_output, x0, x1, rng, y0, y1); using key_t = std::decay_t; EXPECT_EQ(std::memcmp(&dealer.first.root(), &ds.first.root(), sizeof(simde__m128i)), 0); EXPECT_EQ(std::memcmp(&dealer.second.root(), &ds.second.root(), sizeof(simde__m128i)), 0); for (std::size_t i = 0; i < key_t::depth; ++i) { EXPECT_EQ(std::memcmp(&dealer.first.correction_word(i), &ds.first.correction_word(i), sizeof(simde__m128i)), 0) << "cw " << i; EXPECT_EQ(dealer.first.correction_advice(i), ds.first.correction_advice(i)) << "advice " << i; } EXPECT_EQ(std::memcmp(&dealer.first.leaf(), &ds.first.leaf(), sizeof(dealer.first.leaf())), 0); for (int i = 0; i < 256; ++i) { const in_t q = static_cast(i); EXPECT_EQ(recon(ev(ds.first, q), ev(ds.second, q)), q == alpha ? beta : out_t{}) << i; EXPECT_EQ(ev(ds.first, q), ev(dealer.first, q)) << "p0 " << i; EXPECT_EQ(ev(ds.second, q), ev(dealer.second, q)) << "p1 " << i; } } TEST(ArithPayload, DsArithIndexMatchesDealer) { using in_t = std::uint8_t; using out_t = std::uint16_t; const in_t alpha = 0xc0; const in_t x0 = 0x40; const in_t x1 = static_cast(alpha - x0); const out_t beta = 9; const out_t y0 = 3; const out_t y1 = 6; reset_roots(); auto dealer = dpf::make_dpf(alpha, dpf::root_sampler_t{take_root}, beta); reset_roots(); HEDLEY_PRAGMA(GCC diagnostic push) HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes") dpf::ds_randomness rng{take_root, Pad{}}; HEDLEY_PRAGMA(GCC diagnostic pop) auto ds = dpf::make_dpf_doerner_shelat(dpf::arith_input, dpf::arith_output, x0, x1, rng, y0, y1); for (int i = 0; i < 256; ++i) { const in_t q = static_cast(i); EXPECT_EQ(recon(ev(ds.first, q), ev(ds.second, q)), q == alpha ? beta : out_t{}) << i; EXPECT_EQ(ev(ds.first, q), ev(dealer.first, q)) << "p0 " << i; EXPECT_EQ(ev(ds.second, q), ev(dealer.second, q)) << "p1 " << i; } } TEST(ArithPayload, GenevalXorSharedBeta) { using in_t = std::uint8_t; using out_t = std::uint16_t; const in_t alpha = 0x33; const in_t x0 = 0x0f; const in_t x1 = static_cast(alpha ^ x0); const out_t beta = 0x77; const out_t y0 = 0x10; const out_t y1 = static_cast(beta - y0); reset_roots(); auto keys = dpf::make_dpf(alpha, dpf::root_sampler_t{take_root}, beta); reset_roots(); HEDLEY_PRAGMA(GCC diagnostic push) HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes") dpf::ds_randomness g_rng{take_root, Pad{}}; HEDLEY_PRAGMA(GCC diagnostic pop) auto g = dpf::geneval_point(dpf::arith_output, x0, x1, alpha, g_rng, y0, y1); EXPECT_TRUE(g.leaf_live); ASSERT_EQ(g.party0.size(), 1u); EXPECT_EQ(recon(g.party0[0], g.party1[0]), beta); EXPECT_EQ(g.party0[0], ev(keys.first, alpha)); EXPECT_EQ(g.party1[0], ev(keys.second, alpha)); } TEST(ArithPayload, GenevalArithSharedBeta) { using in_t = std::uint8_t; using out_t = std::uint16_t; const in_t alpha = 0x90; const in_t x0 = 0x20; const in_t x1 = static_cast(alpha - x0); const out_t beta = 3; const out_t y0 = 1; const out_t y1 = 2; reset_roots(); auto keys = dpf::make_dpf(alpha, dpf::root_sampler_t{take_root}, beta); reset_roots(); HEDLEY_PRAGMA(GCC diagnostic push) HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes") dpf::ds_randomness g_rng{take_root, Pad{}}; HEDLEY_PRAGMA(GCC diagnostic pop) auto g = dpf::geneval_point(dpf::arith_input, dpf::arith_output, x0, x1, alpha, g_rng, y0, y1); EXPECT_TRUE(g.leaf_live); ASSERT_EQ(g.party0.size(), 1u); EXPECT_EQ(recon(g.party0[0], g.party1[0]), beta); EXPECT_EQ(g.party0[0], ev(keys.first, alpha)); EXPECT_EQ(g.party1[0], ev(keys.second, alpha)); } TEST(ArithPayload, XorWrapperSharesMatchDealer) { using in_t = std::uint8_t; using out_t = dpf::xor_wrapper; const in_t alpha = 0x11; const in_t x0 = 0x55; const in_t x1 = static_cast(alpha ^ x0); const out_t beta{0x0a0b0c0du}; const out_t y0{0x01020304u}; const out_t y1 = beta ^ y0; reset_roots(); auto dealer = dpf::make_dpf(alpha, dpf::root_sampler_t{take_root}, beta); reset_roots(); HEDLEY_PRAGMA(GCC diagnostic push) HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes") dpf::ds_randomness rng{take_root, Pad{}}; HEDLEY_PRAGMA(GCC diagnostic pop) auto ds = dpf::make_dpf_doerner_shelat(dpf::arith_output, x0, x1, rng, y0, y1); for (int i = 0; i < 256; ++i) { const in_t q = static_cast(i); const auto got = dpf::reconstruct(*dpf::eval_point(ds.first, q), *dpf::eval_point(ds.second, q)); const auto expect = dpf::reconstruct(*dpf::eval_point(dealer.first, q), *dpf::eval_point(dealer.second, q)); EXPECT_EQ(got, expect) << i; EXPECT_EQ(got, q == alpha ? beta : out_t{}) << i; } reset_roots(); HEDLEY_PRAGMA(GCC diagnostic push) HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes") dpf::ds_randomness g_rng{take_root, Pad{}}; HEDLEY_PRAGMA(GCC diagnostic pop) auto g = dpf::geneval_point(dpf::arith_output, x0, x1, alpha, g_rng, y0, y1); EXPECT_TRUE(g.leaf_live); ASSERT_EQ(g.party0.size(), 1u); EXPECT_EQ(g.party0[0] ^ g.party1[0], beta); } TEST(ArithPayload, MultiBlockUint256MatchesDealer) { using in_t = std::uint8_t; using out_t = uint256_t; const in_t alpha = 0x2a; const in_t x0 = 0x0f; const in_t x1 = static_cast(alpha ^ x0); const out_t beta = (out_t{1} << 200) + out_t{0xabcdefu}; const out_t y0 = (out_t{1} << 180) + out_t{0x1111u}; const out_t y1 = beta - y0; HEDLEY_PRAGMA(GCC diagnostic push) HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes") EXPECT_GT((dpf::block_length_of_leaf_v), 1u); HEDLEY_PRAGMA(GCC diagnostic pop) reset_roots(); auto dealer = dpf::make_dpf(alpha, dpf::root_sampler_t{take_root}, beta); reset_roots(); HEDLEY_PRAGMA(GCC diagnostic push) HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes") dpf::ds_randomness rng{take_root, Pad{}}; HEDLEY_PRAGMA(GCC diagnostic pop) auto ds = dpf::make_dpf_doerner_shelat(dpf::arith_output, x0, x1, rng, y0, y1); EXPECT_EQ(std::memcmp(&dealer.first.leaf(), &ds.first.leaf(), sizeof(dealer.first.leaf())), 0); for (int i = 0; i < 256; i += 17) { const in_t q = static_cast(i); EXPECT_EQ(recon(ev(ds.first, q), ev(ds.second, q)), q == alpha ? beta : out_t{}) << i; EXPECT_EQ(ev(ds.first, q), ev(dealer.first, q)) << "p0 " << i; EXPECT_EQ(ev(ds.second, q), ev(dealer.second, q)) << "p1 " << i; } } TEST(ArithPayload, IncrementalMultiSlotArithBeta) { using in_t = std::uint8_t; const in_t alpha = 0x44; const in_t x0 = 0x12; const in_t x1 = static_cast(alpha ^ x0); const std::uint16_t b0 = 0x1111; const std::uint16_t b1 = 0x2222; const std::uint16_t y00 = 0x0100; const std::uint16_t y01 = static_cast(b0 - y00); const std::uint16_t y10 = 0x0003; const std::uint16_t y11 = static_cast(b1 - y10); reset_roots(); auto dealer = dpf::make_dpf(alpha, dpf::root_sampler_t{take_root}, dpf::at<8>(b0, b1)); reset_roots(); HEDLEY_PRAGMA(GCC diagnostic push) HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes") dpf::ds_randomness rng{take_root, Pad{}}; HEDLEY_PRAGMA(GCC diagnostic pop) auto ds = dpf::make_dpf_doerner_shelat(dpf::arith_output, x0, x1, rng, dpf::at<8>(dpf::arith_beta{y00, y01}, dpf::arith_beta{y10, y11})); auto r0 = [&](auto & k0, auto & k1, in_t q) { return recon(*dpf::eval_point(dpf::out<0, 8>, k0, q), *dpf::eval_point(dpf::out<0, 8>, k1, q)); }; auto r1 = [&](auto & k0, auto & k1, in_t q) { return recon(*dpf::eval_point(dpf::out<1, 8>, k0, q), *dpf::eval_point(dpf::out<1, 8>, k1, q)); }; for (int i = 0; i < 256; i += 13) { const in_t q = static_cast(i); EXPECT_EQ(r0(ds.first, ds.second, q), r0(dealer.first, dealer.second, q)) << "s0 " << i; EXPECT_EQ(r1(ds.first, ds.second, q), r1(dealer.first, dealer.second, q)) << "s1 " << i; EXPECT_EQ(r0(ds.first, ds.second, q), q == alpha ? b0 : std::uint16_t{0}) << i; EXPECT_EQ(r1(ds.first, ds.second, q), q == alpha ? b1 : std::uint16_t{0}) << i; } } TEST(ArithPayload, MixedArithBetaAndWildcard) { using in_t = std::uint8_t; const in_t alpha = 0x70; const in_t x0 = 0x01; const in_t x1 = static_cast(alpha ^ x0); const std::uint8_t beta = 9; const std::uint8_t y0 = 2; const std::uint8_t y1 = 7; reset_roots(); auto dealer = dpf::make_dpf(alpha, dpf::root_sampler_t{take_root}, dpf::at<8>(beta, dpf::wildcard_value{})); reset_roots(); HEDLEY_PRAGMA(GCC diagnostic push) HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes") dpf::ds_randomness rng{take_root, Pad{}}; HEDLEY_PRAGMA(GCC diagnostic pop) auto ds = dpf::make_dpf_doerner_shelat(dpf::arith_output, x0, x1, rng, dpf::at<8>(dpf::arith_beta{y0, y1}, dpf::wildcard_value{})); using key_t = std::decay_t; static_assert(dpf::is_wildcard_v>); for (int i = 0; i < 256; i += 19) { const in_t q = static_cast(i); const auto got = recon(*dpf::eval_point(dpf::out<0, 8>, ds.first, q), *dpf::eval_point(dpf::out<0, 8>, ds.second, q)); const auto expect = recon(*dpf::eval_point(dpf::out<0, 8>, dealer.first, q), *dpf::eval_point(dpf::out<0, 8>, dealer.second, q)); EXPECT_EQ(got, expect) << i; EXPECT_EQ(got, q == alpha ? beta : std::uint8_t{0}) << i; } }