Annotate noexcept and constexpr with HEDLEY, and add interval containment, ChaCha, and the dyadic range tables.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
875f09fec1
commit
0d8a5a8131
97 changed files with 9212 additions and 1159 deletions
|
|
@ -362,110 +362,87 @@ TEST(Geneval, EmptySequence)
|
|||
EXPECT_TRUE(g.correction_words.empty());
|
||||
}
|
||||
|
||||
TEST(Geneval, WildcardPointMatchesShiftedEval)
|
||||
TEST(Geneval, ArithPointMatchesDealerAtQuery)
|
||||
{
|
||||
using in_t = uint16_t;
|
||||
using out_t = uint16_t;
|
||||
in_t x = 0x1357;
|
||||
in_t x0 = 0x0100;
|
||||
in_t x1 = static_cast<in_t>(x - x0);
|
||||
in_t alpha = 0xabcd;
|
||||
in_t query = 0x2000;
|
||||
out_t y = 99;
|
||||
const in_t delta = static_cast<in_t>(alpha - x);
|
||||
const in_t shifted = static_cast<in_t>(query + delta);
|
||||
|
||||
reset_roots();
|
||||
auto keys = dpf::make_dpf(alpha, dpf::root_sampler_t<dpf::prg::aes128>{take_root}, y);
|
||||
auto keys = dpf::make_dpf(x, dpf::root_sampler_t<dpf::prg::aes128>{take_root}, y);
|
||||
reset_roots();
|
||||
auto g = dpf::geneval_point(dpf::wildcard_input, x0, x1, query, rng<in_t>(),
|
||||
[&] { return alpha; }, y);
|
||||
auto g = dpf::geneval_point(dpf::arith_input, x0, x1, query, rng<in_t>(), y);
|
||||
|
||||
using key_t = std::decay_t<decltype(keys.first)>;
|
||||
const auto live = live_through_lcp(
|
||||
lcp_bits(leaf_of<key_t>(alpha), leaf_of<key_t>(shifted), key_t::depth),
|
||||
lcp_bits(leaf_of<key_t>(x), leaf_of<key_t>(query), key_t::depth),
|
||||
key_t::depth);
|
||||
EXPECT_EQ(g.live_levels, live);
|
||||
EXPECT_LT(live, key_t::depth);
|
||||
expect_prefix_words(keys.first, g.correction_words, g.correction_advice,
|
||||
g.live_levels, g.leaf_live, &g.leaf, sizeof(g.leaf));
|
||||
|
||||
auto e0 = ev(keys.first, shifted);
|
||||
auto e1 = ev(keys.second, shifted);
|
||||
auto e0 = ev(keys.first, query);
|
||||
auto e1 = ev(keys.second, query);
|
||||
EXPECT_EQ(recon(g.party0[0], g.party1[0]), recon(e0, e1));
|
||||
|
||||
dpf::wildcard_value<in_t> slot{alpha};
|
||||
reset_roots();
|
||||
auto wild = dpf::make_dpf(slot, dpf::root_sampler_t<dpf::prg::aes128>{take_root}, y);
|
||||
auto s0 = wild.first.offset_x.compute_and_get_share(x0);
|
||||
auto s1 = wild.second.offset_x.compute_and_get_share(x1);
|
||||
wild.first.offset_x.reconstruct(s1);
|
||||
wild.second.offset_x.reconstruct(s0);
|
||||
auto w0 = ev(wild.first, query);
|
||||
auto w1 = ev(wild.second, query);
|
||||
EXPECT_EQ(recon(g.party0[0], g.party1[0]), recon(w0, w1));
|
||||
expect_prefix_words(wild.first, g.correction_words, g.correction_advice,
|
||||
g.live_levels, false, nullptr, 0);
|
||||
}
|
||||
|
||||
TEST(Geneval, WildcardPointOnSecretIsFullKey)
|
||||
TEST(Geneval, ArithPointOnSecretIsFullKey)
|
||||
{
|
||||
using in_t = uint16_t;
|
||||
using out_t = uint16_t;
|
||||
in_t x = 0x42;
|
||||
in_t x0 = 0x10;
|
||||
in_t x1 = static_cast<in_t>(x - x0);
|
||||
in_t alpha = 0x1111;
|
||||
out_t y = 8;
|
||||
|
||||
reset_roots();
|
||||
auto keys = dpf::make_dpf(alpha, dpf::root_sampler_t<dpf::prg::aes128>{take_root}, y);
|
||||
auto keys = dpf::make_dpf(x, dpf::root_sampler_t<dpf::prg::aes128>{take_root}, y);
|
||||
reset_roots();
|
||||
auto g = dpf::geneval_point(dpf::wildcard_input, x0, x1, x, rng<in_t>(),
|
||||
[&] { return alpha; }, y);
|
||||
auto g = dpf::geneval_point(dpf::arith_input, x0, x1, x, rng<in_t>(), y);
|
||||
|
||||
using key_t = std::decay_t<decltype(keys.first)>;
|
||||
EXPECT_EQ(g.live_levels, key_t::depth);
|
||||
EXPECT_TRUE(g.leaf_live);
|
||||
expect_prefix_words(keys.first, g.correction_words, g.correction_advice,
|
||||
g.live_levels, true, &g.leaf, sizeof(g.leaf));
|
||||
auto e0 = ev(keys.first, alpha);
|
||||
auto e1 = ev(keys.second, alpha);
|
||||
auto e0 = ev(keys.first, x);
|
||||
auto e1 = ev(keys.second, x);
|
||||
EXPECT_EQ(g.party0[0], e0);
|
||||
EXPECT_EQ(g.party1[0], e1);
|
||||
EXPECT_EQ(recon(g.party0[0], g.party1[0]), y);
|
||||
}
|
||||
|
||||
TEST(Geneval, WildcardIntervalAndSequence)
|
||||
TEST(Geneval, ArithIntervalAndSequence)
|
||||
{
|
||||
using in_t = uint8_t;
|
||||
using out_t = uint8_t;
|
||||
in_t x = 40;
|
||||
in_t x0 = 7;
|
||||
in_t x1 = static_cast<in_t>(x - x0);
|
||||
in_t alpha = 200;
|
||||
out_t y = 3;
|
||||
const in_t delta = static_cast<in_t>(alpha - x);
|
||||
|
||||
reset_roots();
|
||||
auto keys = dpf::make_dpf(alpha, dpf::root_sampler_t<dpf::prg::aes128>{take_root}, y);
|
||||
auto keys = dpf::make_dpf(x, dpf::root_sampler_t<dpf::prg::aes128>{take_root}, y);
|
||||
reset_roots();
|
||||
auto iv = dpf::geneval_interval(dpf::wildcard_input, x0, x1, in_t{10}, in_t{20},
|
||||
rng<in_t>(), [&] { return alpha; }, y);
|
||||
auto iv = dpf::geneval_interval(dpf::arith_input, x0, x1, in_t{10}, in_t{20},
|
||||
rng<in_t>(), y);
|
||||
|
||||
using key_t = std::decay_t<decltype(keys.first)>;
|
||||
ASSERT_EQ(iv.party0.size(), 11u);
|
||||
for (in_t q = 10; q <= 20; ++q)
|
||||
{
|
||||
const in_t shifted = static_cast<in_t>(q + delta);
|
||||
const std::size_t i = static_cast<std::size_t>(q - 10);
|
||||
auto e0 = ev(keys.first, shifted);
|
||||
auto e1 = ev(keys.second, shifted);
|
||||
auto e0 = ev(keys.first, q);
|
||||
auto e1 = ev(keys.second, q);
|
||||
EXPECT_EQ(recon(iv.party0[i], iv.party1[i]), recon(e0, e1)) << int(q);
|
||||
}
|
||||
const in_t shifted_from = static_cast<in_t>(10 + delta);
|
||||
const auto live = live_through_lcp(
|
||||
lcp_bits(leaf_of<key_t>(alpha), leaf_of<key_t>(shifted_from), key_t::depth),
|
||||
lcp_bits(leaf_of<key_t>(x), leaf_of<key_t>(in_t{10}), key_t::depth),
|
||||
key_t::depth);
|
||||
EXPECT_EQ(iv.live_levels, live);
|
||||
expect_prefix_words(keys.first, iv.correction_words, iv.correction_advice,
|
||||
|
|
@ -473,8 +450,8 @@ TEST(Geneval, WildcardIntervalAndSequence)
|
|||
|
||||
const in_t seq[] = {1, x, 255, 2};
|
||||
reset_roots();
|
||||
auto sq = dpf::geneval_sequence(dpf::wildcard_input, x0, x1,
|
||||
std::begin(seq), std::end(seq), rng<in_t>(), [&] { return alpha; }, y);
|
||||
auto sq = dpf::geneval_sequence(dpf::arith_input, x0, x1,
|
||||
std::begin(seq), std::end(seq), rng<in_t>(), y);
|
||||
ASSERT_EQ(sq.party0.size(), 4u);
|
||||
EXPECT_TRUE(sq.leaf_live);
|
||||
EXPECT_EQ(sq.live_levels, key_t::depth);
|
||||
|
|
@ -482,31 +459,27 @@ TEST(Geneval, WildcardIntervalAndSequence)
|
|||
sq.live_levels, true, &sq.leaf, sizeof(sq.leaf));
|
||||
for (std::size_t i = 0; i < 4; ++i)
|
||||
{
|
||||
const in_t shifted = static_cast<in_t>(seq[i] + delta);
|
||||
auto e0 = ev(keys.first, shifted);
|
||||
auto e1 = ev(keys.second, shifted);
|
||||
auto e0 = ev(keys.first, seq[i]);
|
||||
auto e1 = ev(keys.second, seq[i]);
|
||||
EXPECT_EQ(sq.party0[i], e0);
|
||||
EXPECT_EQ(sq.party1[i], e1);
|
||||
EXPECT_EQ(recon(sq.party0[i], sq.party1[i]), seq[i] == x ? y : out_t{0});
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geneval, WildcardFullRotates)
|
||||
TEST(Geneval, ArithFullMatchesDealer)
|
||||
{
|
||||
using in_t = uint8_t;
|
||||
using out_t = uint8_t;
|
||||
in_t x = 40;
|
||||
in_t x0 = 7;
|
||||
in_t x1 = static_cast<in_t>(x - x0);
|
||||
in_t alpha = 200;
|
||||
out_t y = 3;
|
||||
const in_t delta = static_cast<in_t>(alpha - x);
|
||||
|
||||
reset_roots();
|
||||
auto keys = dpf::make_dpf(alpha, dpf::root_sampler_t<dpf::prg::aes128>{take_root}, y);
|
||||
auto keys = dpf::make_dpf(x, dpf::root_sampler_t<dpf::prg::aes128>{take_root}, y);
|
||||
reset_roots();
|
||||
auto g = dpf::geneval_full(dpf::wildcard_input, x0, x1, rng<in_t>(),
|
||||
[&] { return alpha; }, y);
|
||||
auto g = dpf::geneval_full(dpf::arith_input, x0, x1, rng<in_t>(), y);
|
||||
|
||||
using key_t = std::decay_t<decltype(keys.first)>;
|
||||
EXPECT_EQ(g.party0.size(), 256u);
|
||||
|
|
@ -517,9 +490,8 @@ TEST(Geneval, WildcardFullRotates)
|
|||
EXPECT_EQ(recon(g.party0[x], g.party1[x]), y);
|
||||
for (int q = 0; q < 256; ++q)
|
||||
{
|
||||
const in_t shifted = static_cast<in_t>(static_cast<in_t>(q) + delta);
|
||||
auto e0 = ev(keys.first, shifted);
|
||||
auto e1 = ev(keys.second, shifted);
|
||||
auto e0 = ev(keys.first, static_cast<in_t>(q));
|
||||
auto e1 = ev(keys.second, static_cast<in_t>(q));
|
||||
EXPECT_EQ(g.party0[q], e0);
|
||||
EXPECT_EQ(g.party1[q], e1);
|
||||
}
|
||||
|
|
@ -919,7 +891,7 @@ TEST(Geneval, SignedPointIntervalAndCrossZero)
|
|||
(void)near;
|
||||
}
|
||||
|
||||
TEST(Geneval, SignedFullAndWildcardFull)
|
||||
TEST(Geneval, SignedFullAndArithFull)
|
||||
{
|
||||
using in_t = int8_t;
|
||||
using out_t = int8_t;
|
||||
|
|
@ -945,13 +917,11 @@ TEST(Geneval, SignedFullAndWildcardFull)
|
|||
in_t secret = -20;
|
||||
in_t a0 = 100;
|
||||
in_t a1 = static_cast<in_t>(secret - a0);
|
||||
in_t target = 40;
|
||||
const in_t delta = static_cast<in_t>(target - secret);
|
||||
ASSERT_EQ(static_cast<in_t>(a0 + a1), secret);
|
||||
reset_roots();
|
||||
auto wkeys = dpf::make_dpf(target, dpf::root_sampler_t<dpf::prg::aes128>{take_root}, y);
|
||||
auto wkeys = dpf::make_dpf(secret, dpf::root_sampler_t<dpf::prg::aes128>{take_root}, y);
|
||||
reset_roots();
|
||||
auto w = dpf::geneval_full(dpf::wildcard_input, a0, a1, rng<in_t>(),
|
||||
[&] { return target; }, y);
|
||||
auto w = dpf::geneval_full(dpf::arith_input, a0, a1, rng<in_t>(), y);
|
||||
ASSERT_EQ(w.party0.size(), 256u);
|
||||
EXPECT_EQ(w.live_levels, std::decay_t<decltype(wkeys.first)>::depth);
|
||||
expect_prefix_words(wkeys.first, w.correction_words, w.correction_advice,
|
||||
|
|
@ -959,16 +929,15 @@ TEST(Geneval, SignedFullAndWildcardFull)
|
|||
for (int q = -128; q <= 127; ++q)
|
||||
{
|
||||
in_t v = static_cast<in_t>(q);
|
||||
in_t shifted = static_cast<in_t>(v + delta);
|
||||
const std::size_t i = static_cast<std::size_t>(to_int(v));
|
||||
EXPECT_EQ(w.party0[i], ev(wkeys.first, shifted)) << q;
|
||||
EXPECT_EQ(w.party1[i], ev(wkeys.second, shifted)) << q;
|
||||
EXPECT_EQ(w.party0[i], ev(wkeys.first, v)) << q;
|
||||
EXPECT_EQ(w.party1[i], ev(wkeys.second, v)) << q;
|
||||
}
|
||||
EXPECT_EQ(recon(w.party0[static_cast<std::size_t>(to_int(secret))],
|
||||
w.party1[static_cast<std::size_t>(to_int(secret))]), y);
|
||||
}
|
||||
|
||||
TEST(Geneval, WildcardShareOverflowAndWrappingInterval)
|
||||
TEST(Geneval, ArithShareOverflowAndWrappingInterval)
|
||||
{
|
||||
using in_t = uint8_t;
|
||||
using out_t = uint8_t;
|
||||
|
|
@ -976,15 +945,12 @@ TEST(Geneval, WildcardShareOverflowAndWrappingInterval)
|
|||
in_t x0 = 200;
|
||||
in_t x1 = 66;
|
||||
ASSERT_EQ(static_cast<in_t>(x0 + x1), secret);
|
||||
in_t alpha = 5;
|
||||
out_t y = 17;
|
||||
const in_t delta = static_cast<in_t>(alpha - secret);
|
||||
|
||||
reset_roots();
|
||||
auto keys = dpf::make_dpf(alpha, dpf::root_sampler_t<dpf::prg::aes128>{take_root}, y);
|
||||
auto keys = dpf::make_dpf(secret, dpf::root_sampler_t<dpf::prg::aes128>{take_root}, y);
|
||||
reset_roots();
|
||||
auto on = dpf::geneval_point(dpf::wildcard_input, x0, x1, secret, rng<in_t>(),
|
||||
[&] { return alpha; }, y);
|
||||
auto on = dpf::geneval_point(dpf::arith_input, x0, x1, secret, rng<in_t>(), y);
|
||||
using key_t = std::decay_t<decltype(keys.first)>;
|
||||
EXPECT_EQ(on.live_levels, key_t::depth);
|
||||
EXPECT_TRUE(on.leaf_live);
|
||||
|
|
@ -993,36 +959,33 @@ TEST(Geneval, WildcardShareOverflowAndWrappingInterval)
|
|||
EXPECT_EQ(recon(on.party0[0], on.party1[0]), y);
|
||||
|
||||
in_t query = 250;
|
||||
const in_t shifted = static_cast<in_t>(query + delta);
|
||||
reset_roots();
|
||||
auto off = dpf::geneval_point(dpf::wildcard_input, x0, x1, query, rng<in_t>(),
|
||||
[&] { return alpha; }, y);
|
||||
auto off = dpf::geneval_point(dpf::arith_input, x0, x1, query, rng<in_t>(), y);
|
||||
const auto live = live_through_lcp(
|
||||
lcp_bits(leaf_of<key_t>(alpha), leaf_of<key_t>(shifted), key_t::depth),
|
||||
lcp_bits(leaf_of<key_t>(secret), leaf_of<key_t>(query), key_t::depth),
|
||||
key_t::depth);
|
||||
EXPECT_EQ(off.live_levels, live);
|
||||
expect_prefix_words(keys.first, off.correction_words, off.correction_advice,
|
||||
off.live_levels, off.leaf_live, &off.leaf, sizeof(off.leaf));
|
||||
EXPECT_EQ(recon(off.party0[0], off.party1[0]),
|
||||
recon(ev(keys.first, shifted), ev(keys.second, shifted)));
|
||||
recon(ev(keys.first, query), ev(keys.second, query)));
|
||||
|
||||
in_t from = 250;
|
||||
in_t to = 10;
|
||||
EXPECT_THROW((dpf::geneval_interval(dpf::wildcard_input, x0, x1, from, to,
|
||||
rng<in_t>(), [&] { return alpha; }, y)), std::invalid_argument);
|
||||
EXPECT_THROW((dpf::geneval_interval(dpf::arith_input, x0, x1, from, to,
|
||||
rng<in_t>(), y)), std::invalid_argument);
|
||||
|
||||
from = 250;
|
||||
to = 255;
|
||||
reset_roots();
|
||||
auto iv = dpf::geneval_interval(dpf::wildcard_input, x0, x1, from, to,
|
||||
rng<in_t>(), [&] { return alpha; }, y);
|
||||
auto iv = dpf::geneval_interval(dpf::arith_input, x0, x1, from, to,
|
||||
rng<in_t>(), y);
|
||||
ASSERT_EQ(iv.party0.size(), 6u);
|
||||
for (in_t q = from; ; ++q)
|
||||
{
|
||||
const std::size_t i = static_cast<std::size_t>(static_cast<in_t>(q - from));
|
||||
const in_t s = static_cast<in_t>(q + delta);
|
||||
EXPECT_EQ(recon(iv.party0[i], iv.party1[i]),
|
||||
recon(ev(keys.first, s), ev(keys.second, s))) << int(q);
|
||||
recon(ev(keys.first, q), ev(keys.second, q))) << int(q);
|
||||
if (q == to)
|
||||
break;
|
||||
}
|
||||
|
|
@ -1099,26 +1062,19 @@ TEST(Geneval, SignedRegressionsFromTheCornerPass)
|
|||
EXPECT_EQ(full.party0[bit], ev(keys.first, v)) << q;
|
||||
}
|
||||
|
||||
// Negative target, additive shares that wrap, bound through a real
|
||||
// wildcard key so the raw offset bits are what geneval subtracts.
|
||||
// Negative secret, additive shares that wrap through the signed MSB.
|
||||
in_t secret = -20;
|
||||
in_t a0 = 100;
|
||||
in_t a1 = static_cast<in_t>(secret - a0);
|
||||
ASSERT_EQ(static_cast<in_t>(a0 + a1), secret);
|
||||
in_t target = -90;
|
||||
in_t query = 60;
|
||||
reset_roots();
|
||||
dpf::wildcard_value<in_t> slot{target};
|
||||
auto wild = dpf::make_dpf(slot, dpf::root_sampler_t<dpf::prg::aes128>{take_root}, y);
|
||||
auto s0 = wild.first.offset_x.compute_and_get_share(a0);
|
||||
auto s1 = wild.second.offset_x.compute_and_get_share(a1);
|
||||
wild.first.offset_x.reconstruct(s1);
|
||||
wild.second.offset_x.reconstruct(s0);
|
||||
auto akeys = dpf::make_dpf(secret, dpf::root_sampler_t<dpf::prg::aes128>{take_root}, y);
|
||||
reset_roots();
|
||||
auto g = dpf::geneval_point(dpf::wildcard_input, a0, a1, query, rng<in_t>(),
|
||||
[&] { return target; }, y);
|
||||
EXPECT_EQ(recon(g.party0[0], g.party1[0]), recon(ev(wild.first, query), ev(wild.second, query)));
|
||||
expect_prefix_words(wild.first, g.correction_words, g.correction_advice,
|
||||
auto g = dpf::geneval_point(dpf::arith_input, a0, a1, query, rng<in_t>(), y);
|
||||
EXPECT_EQ(recon(g.party0[0], g.party1[0]),
|
||||
recon(ev(akeys.first, query), ev(akeys.second, query)));
|
||||
expect_prefix_words(akeys.first, g.correction_words, g.correction_advice,
|
||||
g.live_levels, g.leaf_live, &g.leaf, sizeof(g.leaf));
|
||||
}
|
||||
|
||||
|
|
@ -1223,3 +1179,211 @@ TEST(Geneval, CmpLtIsTheComplementOfTheStrictUpperSet)
|
|||
EXPECT_EQ(opened, ends[i] < alpha ? 4u : 0u) << int(ends[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geneval, DoernerShelatOnTargetSharesMatch)
|
||||
{
|
||||
using in_t = uint16_t;
|
||||
using out_t = uint16_t;
|
||||
const in_t alpha = 0x55aa;
|
||||
const in_t x0 = 0x1234;
|
||||
const in_t x1 = static_cast<in_t>(alpha ^ x0);
|
||||
const out_t y = 0x9f3c;
|
||||
|
||||
reset_roots();
|
||||
dpf::ds_randomness<simde__m128i (*)(), Pad> ds_rng{take_root, Pad{}};
|
||||
auto ds = dpf::make_dpf_doerner_shelat(x0, x1, ds_rng, y);
|
||||
reset_roots();
|
||||
auto g = dpf::geneval_point(x0, x1, alpha, rng<in_t>(), y);
|
||||
|
||||
using key_t = std::decay_t<decltype(ds.first)>;
|
||||
EXPECT_EQ(g.live_levels, key_t::depth);
|
||||
EXPECT_TRUE(g.leaf_live);
|
||||
expect_prefix_words(ds.first, g.correction_words, g.correction_advice,
|
||||
g.live_levels, true, &g.leaf, sizeof(g.leaf));
|
||||
EXPECT_EQ(g.party0[0], ev(ds.first, alpha));
|
||||
EXPECT_EQ(g.party1[0], ev(ds.second, alpha));
|
||||
EXPECT_EQ(recon(g.party0[0], g.party1[0]), y);
|
||||
}
|
||||
|
||||
TEST(Geneval, WideLiveFrontierMatchesDealer)
|
||||
{
|
||||
using in_t = uint16_t;
|
||||
using out_t = uint16_t;
|
||||
const in_t alpha = 0x00ff;
|
||||
const in_t x0 = 0x0f0f;
|
||||
const in_t x1 = static_cast<in_t>(alpha ^ x0);
|
||||
const out_t y = 0xabcd;
|
||||
const in_t from = 0;
|
||||
const in_t to = 0x00ff;
|
||||
|
||||
reset_roots();
|
||||
auto keys = dpf::make_dpf(alpha, dpf::root_sampler_t<dpf::prg::aes128>{take_root}, y);
|
||||
reset_roots();
|
||||
auto g = dpf::geneval_interval(x0, x1, from, to, rng<in_t>(), y);
|
||||
|
||||
using key_t = std::decay_t<decltype(keys.first)>;
|
||||
EXPECT_EQ(g.live_levels, key_t::depth);
|
||||
EXPECT_TRUE(g.leaf_live);
|
||||
expect_prefix_words(keys.first, g.correction_words, g.correction_advice,
|
||||
g.live_levels, true, &g.leaf, sizeof(g.leaf));
|
||||
ASSERT_EQ(g.party0.size(), static_cast<std::size_t>(to - from) + 1);
|
||||
for (in_t q = from; ; ++q)
|
||||
{
|
||||
const std::size_t i = static_cast<std::size_t>(q - from);
|
||||
EXPECT_EQ(g.party0[i], ev(keys.first, q)) << q;
|
||||
EXPECT_EQ(g.party1[i], ev(keys.second, q)) << q;
|
||||
const out_t opened = recon(g.party0[i], g.party1[i]);
|
||||
EXPECT_EQ(opened, q == alpha ? y : out_t{0}) << q;
|
||||
if (q == to)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geneval, CmpLeqGeqNonzeroElseAndDomainMin)
|
||||
{
|
||||
using in_t = uint8_t;
|
||||
const in_t alpha = 10;
|
||||
const in_t x0 = 3;
|
||||
const in_t x1 = static_cast<in_t>(alpha ^ x0);
|
||||
const std::vector<in_t> ends{0, 9, 10, 11, 255};
|
||||
|
||||
auto check = [&](auto spec, auto pred) {
|
||||
auto spec_ds = spec;
|
||||
auto spec_g = spec;
|
||||
reset_roots();
|
||||
dpf::ds_randomness<simde__m128i (*)(), Pad> ds_rng{take_root, Pad{}};
|
||||
auto ds = dpf::make_dpf_doerner_shelat(x0, x1, ds_rng, spec_ds);
|
||||
reset_roots();
|
||||
auto g = dpf::geneval_cmp(x0, x1, ends.begin(), ends.end(), rng<in_t>(), spec_g);
|
||||
using key_t = std::decay_t<decltype(ds.first)>;
|
||||
EXPECT_EQ(g.live_levels, key_t::depth);
|
||||
EXPECT_EQ(g.correction_words.size(), key_t::depth);
|
||||
for (std::size_t level = 0; level < key_t::depth; ++level)
|
||||
{
|
||||
EXPECT_EQ(std::memcmp(&g.correction_words[level],
|
||||
&ds.first.correction_word(level), sizeof(simde__m128i)), 0) << level;
|
||||
EXPECT_EQ(g.correction_advice[level], ds.first.correction_advice(level));
|
||||
}
|
||||
for (std::size_t i = 0; i < ends.size(); ++i)
|
||||
{
|
||||
const uint64_t opened = (g.party0[i] + g.party1[i]) & g.mask;
|
||||
const uint64_t from_key =
|
||||
(dpf::eval_point(dpf::cmp, ds.first, ends[i]).raw()
|
||||
+ dpf::eval_point(dpf::cmp, ds.second, ends[i]).raw())
|
||||
& ds.first.cmp().mask;
|
||||
EXPECT_EQ(opened, from_key) << int(ends[i]);
|
||||
EXPECT_EQ(opened, pred(ends[i])) << int(ends[i]);
|
||||
}
|
||||
};
|
||||
|
||||
check(dpf::leq(uint64_t{5}, uint64_t{2}), [&](in_t e) {
|
||||
return e <= alpha ? uint64_t{5} : uint64_t{2};
|
||||
});
|
||||
check(dpf::geq(uint64_t{5}, uint64_t{2}), [&](in_t e) {
|
||||
return e >= alpha ? uint64_t{5} : uint64_t{2};
|
||||
});
|
||||
|
||||
using wide = int16_t;
|
||||
const wide amin = std::numeric_limits<wide>::min();
|
||||
const wide w0 = 1;
|
||||
const wide w1 = static_cast<wide>(amin ^ w0);
|
||||
const std::vector<wide> wends{amin, static_cast<wide>(amin + 1), wide{-1}, wide{0},
|
||||
std::numeric_limits<wide>::max()};
|
||||
reset_roots();
|
||||
auto g = dpf::geneval_cmp(w0, w1, wends.begin(), wends.end(), rng<wide>(),
|
||||
dpf::gt(uint64_t{3}));
|
||||
for (std::size_t i = 0; i < wends.size(); ++i)
|
||||
{
|
||||
const uint64_t opened = (g.party0[i] + g.party1[i]) & g.mask;
|
||||
EXPECT_EQ(opened, wends[i] > amin ? 3u : 0u) << wends[i];
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Geneval, ArithSignedMsbAndCarryAcrossPowerOfTwo)
|
||||
{
|
||||
using in_t = int8_t;
|
||||
using out_t = int8_t;
|
||||
const in_t secret = -20;
|
||||
const in_t a0 = 100;
|
||||
const in_t a1 = static_cast<in_t>(secret - a0);
|
||||
ASSERT_EQ(static_cast<in_t>(a0 + a1), secret);
|
||||
const out_t y = -7;
|
||||
|
||||
reset_roots();
|
||||
auto keys = dpf::make_dpf(secret, dpf::root_sampler_t<dpf::prg::aes128>{take_root}, y);
|
||||
reset_roots();
|
||||
auto g = dpf::geneval_point(dpf::arith_input, a0, a1, secret, rng<in_t>(), y);
|
||||
using key_t = std::decay_t<decltype(keys.first)>;
|
||||
EXPECT_EQ(g.live_levels, key_t::depth);
|
||||
EXPECT_TRUE(g.leaf_live);
|
||||
expect_prefix_words(keys.first, g.correction_words, g.correction_advice,
|
||||
g.live_levels, true, &g.leaf, sizeof(g.leaf));
|
||||
EXPECT_EQ(g.party0[0], ev(keys.first, secret));
|
||||
EXPECT_EQ(g.party1[0], ev(keys.second, secret));
|
||||
EXPECT_EQ(recon(g.party0[0], g.party1[0]), y);
|
||||
|
||||
// Carry across 2^k: shares that wrap the unsigned modulus.
|
||||
using u8 = uint8_t;
|
||||
const u8 usecret = 7;
|
||||
const u8 x0 = 200;
|
||||
const u8 x1 = static_cast<u8>(usecret - x0);
|
||||
ASSERT_EQ(static_cast<u8>(x0 + x1), usecret);
|
||||
const u8 uy = 9;
|
||||
|
||||
reset_roots();
|
||||
auto ukeys = dpf::make_dpf(usecret, dpf::root_sampler_t<dpf::prg::aes128>{take_root}, uy);
|
||||
reset_roots();
|
||||
auto iv = dpf::geneval_interval(dpf::arith_input, x0, x1, u8{0}, u8{3},
|
||||
rng<u8>(), uy);
|
||||
ASSERT_EQ(iv.party0.size(), 4u);
|
||||
for (u8 q = 0; q <= 3; ++q)
|
||||
{
|
||||
const std::size_t i = static_cast<std::size_t>(q);
|
||||
EXPECT_EQ(iv.party0[i], ev(ukeys.first, q)) << int(q);
|
||||
EXPECT_EQ(iv.party1[i], ev(ukeys.second, q)) << int(q);
|
||||
EXPECT_EQ(recon(iv.party0[i], iv.party1[i]),
|
||||
recon(ev(ukeys.first, q), ev(ukeys.second, q))) << int(q);
|
||||
}
|
||||
using ukey_t = std::decay_t<decltype(ukeys.first)>;
|
||||
EXPECT_EQ(iv.live_levels,
|
||||
live_through_lcp(
|
||||
lcp_bits(leaf_of<ukey_t>(usecret), leaf_of<ukey_t>(u8{0}), ukey_t::depth),
|
||||
ukey_t::depth));
|
||||
}
|
||||
|
||||
TEST(Geneval, ArithDoernerShelatAndCmpMatchDealer)
|
||||
{
|
||||
using in_t = uint8_t;
|
||||
const in_t secret = 40;
|
||||
const in_t a0 = 250;
|
||||
const in_t a1 = static_cast<in_t>(secret - a0);
|
||||
ASSERT_EQ(static_cast<in_t>(a0 + a1), secret);
|
||||
const uint64_t beta = 7;
|
||||
const std::vector<in_t> ends{0, 1, 10, 40, 200, 255};
|
||||
|
||||
reset_roots();
|
||||
auto dealer = dpf::make_dpf(secret, dpf::root_sampler_t<dpf::prg::aes128>{take_root},
|
||||
dpf::gt(beta));
|
||||
reset_roots();
|
||||
auto ds = dpf::make_dpf_doerner_shelat(dpf::arith_input, a0, a1, rng<in_t>(),
|
||||
dpf::gt(beta));
|
||||
using key_t = std::decay_t<decltype(dealer.first)>;
|
||||
for (std::size_t level = 0; level < key_t::depth; ++level)
|
||||
{
|
||||
EXPECT_EQ(std::memcmp(&ds.first.correction_word(level),
|
||||
&dealer.first.correction_word(level), sizeof(simde__m128i)), 0) << level;
|
||||
EXPECT_EQ(ds.first.correction_advice(level),
|
||||
dealer.first.correction_advice(level)) << level;
|
||||
EXPECT_EQ(ds.first.value_cw(level), dealer.first.value_cw(level)) << level;
|
||||
}
|
||||
|
||||
reset_roots();
|
||||
auto g = dpf::geneval_cmp(dpf::arith_input, a0, a1, ends.begin(), ends.end(),
|
||||
rng<in_t>(), beta);
|
||||
EXPECT_EQ(g.live_levels, key_t::depth);
|
||||
for (std::size_t i = 0; i < ends.size(); ++i)
|
||||
{
|
||||
const uint64_t opened = (g.party0[i] + g.party1[i]) & g.mask;
|
||||
EXPECT_EQ(opened, ends[i] > secret ? beta : 0u) << int(ends[i]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue