Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: ECCVM correctly handles points at infinity and group operation edge cases #6388

Merged
merged 30 commits into from
May 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
9f6b4ef
initial commit. biggroup objects track whether they are points at inf…
zac-williamson Apr 29, 2024
e4f45ba
initial commit. Updated transcript relations
zac-williamson May 2, 2024
223daa7
added tests for eccvm points at infinity
zac-williamson May 3, 2024
24a3c87
points at infinity now fully supported by eccvm
zac-williamson May 10, 2024
f22670e
eccvm: added comprehensive tests to handle points at infinity / point…
zac-williamson May 14, 2024
e435687
tidied eccvm code
zac-williamson May 14, 2024
cf5d93d
code tidy
zac-williamson May 14, 2024
212c6a0
formatting fix. uncommented parallelism in eccvm circuit builder
zac-williamson May 14, 2024
27c7534
removed unused code
zac-williamson May 14, 2024
b911c52
formatting
zac-williamson May 14, 2024
db9e070
Revert "initial commit. biggroup objects track whether they are point…
codygunton May 15, 2024
51b9589
Try to get earthly run
codygunton May 16, 2024
9ef05e8
Merge remote-tracking branch 'origin/master' into zw/eccvm-infinity
codygunton May 16, 2024
4bbb7ee
Partial builder merge
codygunton May 16, 2024
5f72432
Merge remote-tracking branch 'origin/master' into zw/eccvm-infinity
codygunton May 16, 2024
d6023b0
Temp avoid multithreading bug
codygunton May 16, 2024
cc3d261
ClientIVC test now fails consistently with:
codygunton May 16, 2024
00167fe
Trying to debug relation failure in ClientIVCTests.Full
codygunton May 16, 2024
132aea9
Merge remote-tracking branch 'origin/master' into zw/eccvm-infinity
codygunton May 20, 2024
959d550
Hide logs
codygunton May 20, 2024
31bb78f
Make test repeat
codygunton May 20, 2024
a1e5c0d
Merge remote-tracking branch 'origin/master' into zw/eccvm-infinity
codygunton May 21, 2024
3e4e288
Merge remote-tracking branch 'origin/master' into zw/eccvm-infinity
codygunton May 25, 2024
7ffad2a
Cleanup
codygunton May 25, 2024
3035062
Merge branch 'master' into zw/eccvm-infinity
codygunton May 26, 2024
49c71d4
Remove circuit checking in ASSERT
codygunton May 26, 2024
c2ef8a5
Manually merge msm_builder refactor
codygunton May 26, 2024
a726a11
Reinstate failing tests
codygunton May 26, 2024
0d76d08
Fix from Zac
codygunton May 21, 2024
6eb3665
Cleanup
codygunton May 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ BENCHMARK(execute_relation_for_values<ECCVMFlavor, ECCVMPointTableRelation<Fq>>)
BENCHMARK(execute_relation_for_values<ECCVMFlavor, ECCVMSetRelation<Fq>>);
BENCHMARK(execute_relation_for_values<ECCVMFlavor, ECCVMTranscriptRelation<Fq>>);
BENCHMARK(execute_relation_for_values<ECCVMFlavor, ECCVMWnafRelation<Fq>>);
BENCHMARK(execute_relation_for_values<ECCVMFlavor, ECCVMBoolsRelation<Fq>>);

} // namespace bb::benchmark::relations

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ TEST_F(ClientIVCTests, BasicFailure)
* @brief Prove and verify accumulation of an arbitrary set of circuits
*
*/
TEST_F(ClientIVCTests, DISABLED_BasicLarge)
TEST_F(ClientIVCTests, BasicLarge)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes in this PR allow us to reinstate these core tests.

{
ClientIVC ivc;

Expand All @@ -142,7 +142,7 @@ TEST_F(ClientIVCTests, DISABLED_BasicLarge)
* @brief Using a structured trace allows for the accumulation of circuits of varying size
*
*/
TEST_F(ClientIVCTests, DISABLED_BasicStructured)
TEST_F(ClientIVCTests, BasicStructured)
{
ClientIVC ivc;
ivc.structured_flag = true;
Expand Down
15 changes: 5 additions & 10 deletions barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,15 +120,10 @@ class ECCVMCircuitBuilder {
// populate opqueue and mul indices
for (const auto& op : raw_ops) {
if (op.mul) {
if (op.z1 != 0 || op.z2 != 0) {
if ((op.z1 != 0 || op.z2 != 0) && !op.base_point.is_point_at_infinity()) {
msm_opqueue_index.push_back(op_idx);
msm_mul_index.emplace_back(msm_count, active_mul_count);
}
if (op.z1 != 0) {
active_mul_count++;
}
if (op.z2 != 0) {
active_mul_count++;
active_mul_count += static_cast<size_t>(op.z1 != 0) + static_cast<size_t>(op.z2 != 0);
}
} else if (active_mul_count > 0) {
msm_sizes.push_back(active_mul_count);
Expand All @@ -138,7 +133,7 @@ class ECCVMCircuitBuilder {
op_idx++;
}
// if last op is a mul we have not correctly computed the total number of msms
if (raw_ops.back().mul) {
if (raw_ops.back().mul && active_mul_count > 0) {
msm_sizes.push_back(active_mul_count);
msm_count++;
}
Expand All @@ -152,7 +147,7 @@ class ECCVMCircuitBuilder {
for (size_t i = start; i < end; i++) {
const auto& op = raw_ops[msm_opqueue_index[i]];
auto [msm_index, mul_index] = msm_mul_index[i];
if (op.z1 != 0) {
if (op.z1 != 0 && !op.base_point.is_point_at_infinity()) {
ASSERT(result.size() > msm_index);
ASSERT(result[msm_index].size() > mul_index);
result[msm_index][mul_index] = (ScalarMul{
Expand All @@ -165,7 +160,7 @@ class ECCVMCircuitBuilder {
});
mul_index++;
}
if (op.z2 != 0) {
if (op.z2 != 0 && !op.base_point.is_point_at_infinity()) {
ASSERT(result.size() > msm_index);
ASSERT(result[msm_index].size() > mul_index);
auto endo_point = AffineElement{ op.base_point.x * FF::cube_root_of_unity(), -op.base_point.y };
Expand Down
204 changes: 204 additions & 0 deletions barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ TEST(ECCVMCircuitBuilderTests, BaseCase)
typename G1::element a = generators[0];
typename G1::element b = generators[1];
typename G1::element c = generators[2];
typename G1::element point_at_infinity = G1::point_at_infinity;
Fr x = Fr::random_element(&engine);
Fr y = Fr::random_element(&engine);
Fr zero_scalar = 0;

std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();

Expand All @@ -29,14 +31,49 @@ TEST(ECCVMCircuitBuilderTests, BaseCase)
op_queue->mul_accumulate(b, y);
op_queue->add_accumulate(a);
op_queue->mul_accumulate(b, x);
op_queue->no_op();
op_queue->add_accumulate(b);
op_queue->eq_and_reset();
op_queue->add_accumulate(c);
op_queue->mul_accumulate(a, x);
op_queue->mul_accumulate(point_at_infinity, x);
op_queue->mul_accumulate(b, x);
op_queue->eq_and_reset();
op_queue->mul_accumulate(a, x);
op_queue->mul_accumulate(b, x);
op_queue->mul_accumulate(point_at_infinity, zero_scalar);
op_queue->mul_accumulate(c, x);
op_queue->eq_and_reset();
op_queue->mul_accumulate(point_at_infinity, zero_scalar);
op_queue->mul_accumulate(point_at_infinity, x);
op_queue->mul_accumulate(point_at_infinity, zero_scalar);
op_queue->add_accumulate(a);
op_queue->eq_and_reset();
op_queue->add_accumulate(a);
op_queue->add_accumulate(point_at_infinity);
op_queue->eq_and_reset();
op_queue->add_accumulate(point_at_infinity);
op_queue->eq_and_reset();
op_queue->mul_accumulate(point_at_infinity, x);
op_queue->mul_accumulate(point_at_infinity, -x);
op_queue->eq_and_reset();
op_queue->add_accumulate(a);
op_queue->mul_accumulate(point_at_infinity, x);
op_queue->mul_accumulate(point_at_infinity, -x);
op_queue->add_accumulate(a);
op_queue->add_accumulate(a);
op_queue->eq_and_reset();

ECCVMCircuitBuilder circuit{ op_queue };
bool result = ECCVMTraceChecker::check(circuit);
EXPECT_EQ(result, true);
}

TEST(ECCVMCircuitBuilderTests, NoOp)
{
std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();

op_queue->no_op();

ECCVMCircuitBuilder circuit{ op_queue };
bool result = ECCVMTraceChecker::check(circuit, &engine);
Expand Down Expand Up @@ -72,6 +109,109 @@ TEST(ECCVMCircuitBuilderTests, Mul)
EXPECT_EQ(result, true);
}

TEST(ECCVMCircuitBuilderTests, MulInfinity)
{
std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();

auto generators = G1::derive_generators("test generators", 3);
typename G1::element a = generators[0];
Fr x = Fr::random_element(&engine);
G1::element b = -a * x;
// G1::affine_element c = G1::affine_point_at_infinity;
op_queue->add_accumulate(b);
op_queue->mul_accumulate(a, x);
op_queue->eq_and_reset();
ECCVMCircuitBuilder circuit{ op_queue };
bool result = ECCVMTraceChecker::check(circuit);
EXPECT_EQ(result, true);
}

// Validate we do not trigger edge cases of addition formulae when we have identical mul inputs
TEST(ECCVMCircuitBuilderTests, MulOverIdenticalInputs)
{
std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();

auto generators = G1::derive_generators("test generators", 3);
typename G1::element a = generators[0];
Fr x = Fr::random_element(&engine);
op_queue->mul_accumulate(a, x);
op_queue->mul_accumulate(a, x);
op_queue->eq_and_reset();
ECCVMCircuitBuilder circuit{ op_queue };
bool result = ECCVMTraceChecker::check(circuit);
EXPECT_EQ(result, true);
}

TEST(ECCVMCircuitBuilderTests, MSMProducesInfinity)
{
std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();

auto generators = G1::derive_generators("test generators", 3);
typename G1::element a = generators[0];
Fr x = Fr::random_element(&engine);
op_queue->add_accumulate(a);
op_queue->mul_accumulate(a, x);
op_queue->mul_accumulate(a, -x);
op_queue->eq_and_reset();
ECCVMCircuitBuilder circuit{ op_queue };
bool result = ECCVMTraceChecker::check(circuit);
EXPECT_EQ(result, true);
}

TEST(ECCVMCircuitBuilderTests, MSMOverPointAtInfinity)
{
std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();

auto generators = G1::derive_generators("test generators", 3);
typename G1::element point_at_infinity = G1::point_at_infinity;
typename G1::element b = generators[0];
Fr x = Fr::random_element(&engine);
Fr zero_scalar = 0;

// validate including points at infinity in a multiscalar multiplication does not effect result
{
op_queue->mul_accumulate(b, x);
op_queue->mul_accumulate(point_at_infinity, x);
op_queue->eq_and_reset();
ECCVMCircuitBuilder circuit{ op_queue };
bool result = ECCVMTraceChecker::check(circuit);
EXPECT_EQ(result, true);
}
// validate multiplying a point at infinity by nonzero scalar produces point at infinity
{
op_queue->mul_accumulate(point_at_infinity, x);
op_queue->eq_and_reset();
ECCVMCircuitBuilder circuit{ op_queue };
bool result = ECCVMTraceChecker::check(circuit);
EXPECT_EQ(result, true);
}
// validate multiplying a point by zero produces point at infinity
{
op_queue->mul_accumulate(b, zero_scalar);
op_queue->eq_and_reset();
ECCVMCircuitBuilder circuit{ op_queue };
bool result = ECCVMTraceChecker::check(circuit);
EXPECT_EQ(result, true);
}
// validate multiplying a point at infinity by zero produces a point at infinity
{
op_queue->mul_accumulate(point_at_infinity, zero_scalar);
op_queue->eq_and_reset();
ECCVMCircuitBuilder circuit{ op_queue };
bool result = ECCVMTraceChecker::check(circuit);
EXPECT_EQ(result, true);
}
// validate an MSM made entirely of points at infinity / zero scalars produces a point at infinity
{
op_queue->mul_accumulate(point_at_infinity, x);
op_queue->mul_accumulate(b, zero_scalar);
op_queue->eq_and_reset();
ECCVMCircuitBuilder circuit{ op_queue };
bool result = ECCVMTraceChecker::check(circuit);
EXPECT_EQ(result, true);
}
}

TEST(ECCVMCircuitBuilderTests, ShortMul)
{
std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();
Expand Down Expand Up @@ -243,3 +383,67 @@ TEST(ECCVMCircuitBuilderTests, MSM)
bool result = ECCVMTraceChecker::check(circuit, &engine);
EXPECT_EQ(result, true);
}

TEST(ECCVMCircuitBuilderTests, EqAgainstPointAtInfinity)
{
std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();

auto generators = G1::derive_generators("test generators", 3);
typename G1::element a = generators[0];
a.self_set_infinity();

op_queue->add_accumulate(a);
op_queue->eq_and_reset();

ECCVMCircuitBuilder circuit{ op_queue };
bool result = ECCVMTraceChecker::check(circuit);
EXPECT_EQ(result, true);
}

TEST(ECCVMCircuitBuilderTests, AddPointAtInfinity)
{
std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();

auto generators = G1::derive_generators("test generators", 3);
typename G1::element a = generators[0];
typename G1::element b = generators[0];
b.self_set_infinity();

op_queue->add_accumulate(a);
op_queue->add_accumulate(b);
op_queue->eq_and_reset();

ECCVMCircuitBuilder circuit{ op_queue };
bool result = ECCVMTraceChecker::check(circuit);
EXPECT_EQ(result, true);
}

TEST(ECCVMCircuitBuilderTests, AddProducesPointAtInfinity)
{
std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();

auto generators = G1::derive_generators("test generators", 3);
typename G1::element a = generators[0];

op_queue->add_accumulate(a);
op_queue->add_accumulate(-a);
op_queue->eq_and_reset();
ECCVMCircuitBuilder circuit{ op_queue };
bool result = ECCVMTraceChecker::check(circuit);
EXPECT_EQ(result, true);
}

TEST(ECCVMCircuitBuilderTests, AddProducesDouble)
{
std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();

auto generators = G1::derive_generators("test generators", 3);
typename G1::element a = generators[0];

op_queue->add_accumulate(a);
op_queue->add_accumulate(a);
op_queue->eq_and_reset();
ECCVMCircuitBuilder circuit{ op_queue };
bool result = ECCVMTraceChecker::check(circuit);
EXPECT_EQ(result, true);
}
Loading
Loading