Skip to content

Commit

Permalink
refactor: remove eccvm functionality to update the op queue and ensur…
Browse files Browse the repository at this point in the history
…e ultra ops are populated through function (#5084)

Resolves #897.

Add API functionality so we don't populate the `ultra_ops` manually in
the circuit builder and ensure ECCVM cannot update the op_queue and is
always constructed from existing `op_queue`.

Opens #899 as
ultimately we might want to have the `ultra_ops` and `raw_ops` only
accessible and modifiable by funcitons.
  • Loading branch information
maramihali authored and AztecBot committed Mar 9, 2024
1 parent 31b940b commit c729b3c
Show file tree
Hide file tree
Showing 9 changed files with 181 additions and 211 deletions.
20 changes: 10 additions & 10 deletions cpp/src/barretenberg/benchmark/goblin_bench/eccvm.bench.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace {

Builder generate_trace(size_t target_num_gates)
{
Builder builder;
std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();
using G1 = typename Flavor::CycleGroup;
using Fr = typename G1::Fr;

Expand All @@ -26,20 +26,20 @@ Builder generate_trace(size_t target_num_gates)
Fr x = Fr::random_element();
Fr y = Fr::random_element();

typename G1::element expected_1 = (a * x) + a + a + (b * y) + (b * x) + (b * x);

// Each loop adds 163 gates. Note: builder.get_num_gates() is very expensive here (bug?) and it's actually painful
// to use a `while` loop
size_t num_iterations = target_num_gates / 163;
for (size_t _ = 0; _ < num_iterations; _++) {
builder.add_accumulate(a);
builder.mul_accumulate(a, x);
builder.mul_accumulate(b, x);
builder.mul_accumulate(b, y);
builder.add_accumulate(a);
builder.mul_accumulate(b, x);
builder.eq_and_reset(expected_1);
op_queue->add_accumulate(a);
op_queue->mul_accumulate(a, x);
op_queue->mul_accumulate(b, x);
op_queue->mul_accumulate(b, y);
op_queue->add_accumulate(a);
op_queue->mul_accumulate(b, x);
op_queue->eq();
}

Builder builder{ op_queue };
return builder;
}

Expand Down
64 changes: 34 additions & 30 deletions cpp/src/barretenberg/eccvm/eccvm_composer.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ TYPED_TEST_SUITE(ECCVMComposerTests, FlavorTypes);
namespace {
auto& engine = numeric::get_debug_randomness();
}
template <typename Flavor> ECCVMCircuitBuilder<Flavor> generate_trace(numeric::RNG* engine = nullptr)
template <typename Flavor> ECCVMCircuitBuilder<Flavor> generate_circuit(numeric::RNG* engine = nullptr)
{
ECCVMCircuitBuilder<Flavor> result;
std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();
using G1 = typename Flavor::CycleGroup;
using Fr = typename G1::Fr;

Expand All @@ -47,38 +47,35 @@ template <typename Flavor> ECCVMCircuitBuilder<Flavor> generate_trace(numeric::R
Fr x = Fr::random_element(engine);
Fr y = Fr::random_element(engine);

typename G1::element expected_1 = (a * x) + a + a + (b * y) + (b * x) + (b * x);
typename G1::element expected_2 = (a * x) + c + (b * x);

result.add_accumulate(a);
result.mul_accumulate(a, x);
result.mul_accumulate(b, x);
result.mul_accumulate(b, y);
result.add_accumulate(a);
result.mul_accumulate(b, x);
result.eq_and_reset(expected_1);
result.add_accumulate(c);
result.mul_accumulate(a, x);
result.mul_accumulate(b, x);
result.eq_and_reset(expected_2);
result.mul_accumulate(a, x);
result.mul_accumulate(b, x);
result.mul_accumulate(c, x);

return result;
op_queue->add_accumulate(a);
op_queue->mul_accumulate(a, x);
op_queue->mul_accumulate(b, x);
op_queue->mul_accumulate(b, y);
op_queue->add_accumulate(a);
op_queue->mul_accumulate(b, x);
op_queue->eq();
op_queue->add_accumulate(c);
op_queue->mul_accumulate(a, x);
op_queue->mul_accumulate(b, x);
op_queue->eq();
op_queue->mul_accumulate(a, x);
op_queue->mul_accumulate(b, x);
op_queue->mul_accumulate(c, x);
ECCVMCircuitBuilder<Flavor> builder{ op_queue };
return builder;
}

TYPED_TEST(ECCVMComposerTests, BaseCase)
{
using Flavor = TypeParam;

auto circuit_constructor = generate_trace<Flavor>(&engine);
auto builder = generate_circuit<Flavor>(&engine);

auto composer = ECCVMComposer_<Flavor>();
auto prover = composer.create_prover(circuit_constructor);
auto prover = composer.create_prover(builder);

auto proof = prover.construct_proof();
auto verifier = composer.create_verifier(circuit_constructor);
auto verifier = composer.create_verifier(builder);
bool verified = verifier.verify_proof(proof);

ASSERT_TRUE(verified);
Expand All @@ -87,16 +84,23 @@ TYPED_TEST(ECCVMComposerTests, BaseCase)
TYPED_TEST(ECCVMComposerTests, EqFails)
{
using Flavor = TypeParam;

using G1 = typename Flavor::CycleGroup;
auto circuit_constructor = generate_trace<Flavor>(&engine);
// create an eq opcode that is not satisfied
circuit_constructor.eq_and_reset(G1::affine_one);
using ECCVMOperation = eccvm::VMOperation<G1>;
auto builder = generate_circuit<Flavor>(&engine);
// Tamper with the eq op such that the expected value is incorect
builder.op_queue->raw_ops.emplace_back(ECCVMOperation{ .add = false,
.mul = false,
.eq = true,
.reset = true,
.base_point = G1::affine_one,
.z1 = 0,
.z2 = 0,
.mul_scalar_full = 0 });
auto composer = ECCVMComposer_<Flavor>();
auto prover = composer.create_prover(circuit_constructor);
auto prover = composer.create_prover(builder);

auto proof = prover.construct_proof();
auto verifier = composer.create_verifier(circuit_constructor);
auto verifier = composer.create_verifier(builder);
bool verified = verifier.verify_proof(proof);
ASSERT_FALSE(verified);
}
37 changes: 17 additions & 20 deletions cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ template <typename Flavor> class ECCVMTranscriptTests : public ::testing::Test {
}
ECCVMCircuitBuilder<Flavor> generate_trace(numeric::RNG* engine = nullptr)
{
ECCVMCircuitBuilder<Flavor> result;
std::shared_ptr<ECCOpQueue> op_queue = std::make_shared<ECCOpQueue>();
using G1 = typename Flavor::CycleGroup;
using Fr = typename G1::Fr;

Expand All @@ -197,25 +197,22 @@ template <typename Flavor> class ECCVMTranscriptTests : public ::testing::Test {
Fr x = Fr::random_element(engine);
Fr y = Fr::random_element(engine);

typename G1::element expected_1 = (a * x) + a + a + (b * y) + (b * x) + (b * x);
typename G1::element expected_2 = (a * x) + c + (b * x);

result.add_accumulate(a);
result.mul_accumulate(a, x);
result.mul_accumulate(b, x);
result.mul_accumulate(b, y);
result.add_accumulate(a);
result.mul_accumulate(b, x);
result.eq_and_reset(expected_1);
result.add_accumulate(c);
result.mul_accumulate(a, x);
result.mul_accumulate(b, x);
result.eq_and_reset(expected_2);
result.mul_accumulate(a, x);
result.mul_accumulate(b, x);
result.mul_accumulate(c, x);

return result;
op_queue->add_accumulate(a);
op_queue->mul_accumulate(a, x);
op_queue->mul_accumulate(b, x);
op_queue->mul_accumulate(b, y);
op_queue->add_accumulate(a);
op_queue->mul_accumulate(b, x);
op_queue->eq();
op_queue->add_accumulate(c);
op_queue->mul_accumulate(a, x);
op_queue->mul_accumulate(b, x);
op_queue->eq();
op_queue->mul_accumulate(a, x);
op_queue->mul_accumulate(b, x);
op_queue->mul_accumulate(c, x);
ECCVMCircuitBuilder<Flavor> builder{ op_queue };
return builder;
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,6 @@ template <typename Flavor> class ECCVMCircuitBuilder {
using ScalarMul = bb::eccvm::ScalarMul<CycleGroup>;
using ProverPolynomials = typename Flavor::ProverPolynomials;

ECCVMCircuitBuilder()
: op_queue(std::make_shared<ECCOpQueue>()){};

ECCVMCircuitBuilder(std::shared_ptr<ECCOpQueue>& op_queue)
: op_queue(op_queue){};

Expand Down Expand Up @@ -177,68 +174,6 @@ template <typename Flavor> class ECCVMCircuitBuilder {
return result;
}

void add_accumulate(const AffineElement& to_add)
{
op_queue->raw_ops.emplace_back(VMOperation{
.add = true,
.mul = false,
.eq = false,
.reset = false,
.base_point = to_add,
.z1 = 0,
.z2 = 0,
.mul_scalar_full = 0,
});
}

void mul_accumulate(const AffineElement& to_mul, const CycleScalar& scalar)
{
CycleScalar z1 = 0;
CycleScalar z2 = 0;
auto converted = scalar.from_montgomery_form();
CycleScalar::split_into_endomorphism_scalars(converted, z1, z2);
z1 = z1.to_montgomery_form();
z2 = z2.to_montgomery_form();
op_queue->raw_ops.emplace_back(VMOperation{
.add = false,
.mul = true,
.eq = false,
.reset = false,
.base_point = to_mul,
.z1 = z1,
.z2 = z2,
.mul_scalar_full = scalar,
});
}

void eq_and_reset(const AffineElement& expected)
{
op_queue->raw_ops.emplace_back(VMOperation{
.add = false,
.mul = false,
.eq = true,
.reset = true,
.base_point = expected,
.z1 = 0,
.z2 = 0,
.mul_scalar_full = 0,
});
}

void empty_row()
{
op_queue->raw_ops.emplace_back(VMOperation{
.add = false,
.mul = false,
.eq = false,
.reset = false,
.base_point = CycleGroup::affine_point_at_infinity,
.z1 = 0,
.z2 = 0,
.mul_scalar_full = 0,
});
}

/**
* @brief Compute the ECCVM flavor polynomial data required to generate an ECCVM Proof
*
Expand Down
Loading

0 comments on commit c729b3c

Please sign in to comment.