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

feat!: add support for ROM and RAM ACVM opcodes #417

Merged
merged 7 commits into from
May 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
25 changes: 25 additions & 0 deletions cpp/src/barretenberg/dsl/acir_format/acir_format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ void create_circuit(Composer& composer, const acir_format& constraint_system)
for (const auto& constraint : constraint_system.hash_to_field_constraints) {
create_hash_to_field_constraints(composer, constraint);
}

// Add block constraints
for (const auto& constraint : constraint_system.block_constraints) {
create_block_constraints(composer, constraint);
}
}

Composer create_circuit(const acir_format& constraint_system,
Expand Down Expand Up @@ -173,6 +178,11 @@ Composer create_circuit(const acir_format& constraint_system,
create_hash_to_field_constraints(composer, constraint);
}

// Add block constraints
for (const auto& constraint : constraint_system.block_constraints) {
create_block_constraints(composer, constraint);
}

return composer;
}

Expand Down Expand Up @@ -262,6 +272,11 @@ Composer create_circuit_with_witness(const acir_format& constraint_system,
create_hash_to_field_constraints(composer, constraint);
}

// Add block constraints
for (const auto& constraint : constraint_system.block_constraints) {
create_block_constraints(composer, constraint);
}

return composer;
}
Composer create_circuit_with_witness(const acir_format& constraint_system, std::vector<fr> witness)
Expand Down Expand Up @@ -348,6 +363,11 @@ Composer create_circuit_with_witness(const acir_format& constraint_system, std::
create_hash_to_field_constraints(composer, constraint);
}

// Add block constraints
for (const auto& constraint : constraint_system.block_constraints) {
create_block_constraints(composer, constraint);
}

return composer;
}
void create_circuit_with_witness(Composer& composer, const acir_format& constraint_system, std::vector<fr> witness)
Expand Down Expand Up @@ -431,6 +451,11 @@ void create_circuit_with_witness(Composer& composer, const acir_format& constrai
for (const auto& constraint : constraint_system.hash_to_field_constraints) {
create_hash_to_field_constraints(composer, constraint);
}

// Add block constraints
for (const auto& constraint : constraint_system.block_constraints) {
create_block_constraints(composer, constraint);
}
}

} // namespace acir_format
4 changes: 4 additions & 0 deletions cpp/src/barretenberg/dsl/acir_format/acir_format.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "schnorr_verify.hpp"
#include "ecdsa_secp256k1.hpp"
#include "compute_merkle_root_constraint.hpp"
#include "block_constraint.hpp"
#include "pedersen.hpp"
#include "hash_to_field.hpp"
#include "barretenberg/dsl/types.hpp"
Expand All @@ -31,6 +32,7 @@ struct acir_format {
std::vector<HashToFieldConstraint> hash_to_field_constraints;
std::vector<PedersenConstraint> pedersen_constraints;
std::vector<ComputeMerkleRootConstraint> compute_merkle_root_constraints;
std::vector<BlockConstraint> block_constraints;
// A standard plonk arithmetic constraint, as defined in the poly_triple struct, consists of selector values
// for q_M,q_L,q_R,q_O,q_C and indices of three variables taking the role of left, right and output wire
std::vector<poly_triple> constraints;
Expand Down Expand Up @@ -71,6 +73,7 @@ template <typename B> inline void read(B& buf, acir_format& data)
read(buf, data.hash_to_field_constraints);
read(buf, data.fixed_base_scalar_mul_constraints);
read(buf, data.constraints);
read(buf, data.block_constraints);
}

template <typename B> inline void write(B& buf, acir_format const& data)
Expand All @@ -90,6 +93,7 @@ template <typename B> inline void write(B& buf, acir_format const& data)
write(buf, data.hash_to_field_constraints);
write(buf, data.fixed_base_scalar_mul_constraints);
write(buf, data.constraints);
write(buf, data.block_constraints);
}

} // namespace acir_format
3 changes: 3 additions & 0 deletions cpp/src/barretenberg/dsl/acir_format/acir_format.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ TEST(acir_format, test_logic_gate_from_noir_circuit)
.hash_to_field_constraints = {},
.pedersen_constraints = {},
.compute_merkle_root_constraints = {},
.block_constraints = {},
.constraints = { expr_a, expr_b, expr_c, expr_d },
};

Expand Down Expand Up @@ -156,6 +157,7 @@ TEST(acir_format, test_schnorr_verify_pass)
.hash_to_field_constraints = {},
.pedersen_constraints = {},
.compute_merkle_root_constraints = {},
.block_constraints = {},
.constraints = { poly_triple{
.a = schnorr_constraint.result,
.b = schnorr_constraint.result,
Expand Down Expand Up @@ -226,6 +228,7 @@ TEST(acir_format, test_schnorr_verify_small_range)
.hash_to_field_constraints = {},
.pedersen_constraints = {},
.compute_merkle_root_constraints = {},
.block_constraints = {},
.constraints = { poly_triple{
.a = schnorr_constraint.result,
.b = schnorr_constraint.result,
Expand Down
60 changes: 60 additions & 0 deletions cpp/src/barretenberg/dsl/acir_format/block_constraint.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include "block_constraint.hpp"
#include "barretenberg/stdlib/primitives/memory/rom_table.hpp"
#include "barretenberg/stdlib/primitives/memory/ram_table.hpp"

using namespace proof_system::plonk;

namespace acir_format {
field_ct poly_to_field_ct(const poly_triple poly, Composer& composer)
{
ASSERT(poly.q_m == 0);
ASSERT(poly.q_r == 0);
ASSERT(poly.q_o == 0);
if (poly.q_l == 0) {
return field_ct(poly.q_c);
}
field_ct x = field_ct::from_witness_index(&composer, poly.a);
x.additive_constant = poly.q_c;
x.multiplicative_constant = poly.q_l;
return x;
}

void create_block_constraints(Composer& composer, const BlockConstraint constraint)
vezenovm marked this conversation as resolved.
Show resolved Hide resolved
{
std::vector<field_ct> init;
for (auto i : constraint.init) {
field_ct value = poly_to_field_ct(i, composer);
init.push_back(value);
}

switch (constraint.type) {
case BlockType::ROM: {

rom_table_ct table(init);
for (auto& op : constraint.trace) {
ASSERT(op.access_type == 0);
field_ct value = poly_to_field_ct(op.value, composer);
field_ct index = poly_to_field_ct(op.index, composer);
value.assert_equal(table[index]);
}
} break;
case BlockType::RAM: {
ram_table_ct table(init);
for (auto& op : constraint.trace) {
field_ct value = poly_to_field_ct(op.value, composer);
field_ct index = poly_to_field_ct(op.index, composer);
if (op.access_type == 0) {
value.assert_equal(table.read(index));
} else {
ASSERT(op.access_type == 1);
table.write(index, value);
}
}
} break;
default:
ASSERT(false);
break;
}
}

} // namespace acir_format
62 changes: 62 additions & 0 deletions cpp/src/barretenberg/dsl/acir_format/block_constraint.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#pragma once
#include <cstdint>
#include <vector>
#include "barretenberg/plonk/composer/ultra_composer.hpp"
#include "barretenberg/stdlib/primitives/field/field.hpp"
#include "barretenberg/dsl/types.hpp"

namespace acir_format {

struct MemOp {
uint8_t access_type;
poly_triple index;
poly_triple value;
};

enum BlockType {
ROM = 0,
RAM = 1,
};

struct BlockConstraint {
std::vector<poly_triple> init;
std::vector<MemOp> trace;
BlockType type;
};

void create_block_constraints(Composer& composer, const BlockConstraint constraint);

template <typename B> inline void read(B& buf, MemOp& mem_op)
{
using serialize::read;
read(buf, mem_op.access_type);
read(buf, mem_op.index);
read(buf, mem_op.value);
}

template <typename B> inline void write(B& buf, MemOp const& mem_op)
{
using serialize::write;
write(buf, mem_op.access_type);
write(buf, mem_op.index);
write(buf, mem_op.value);
}

template <typename B> inline void read(B& buf, BlockConstraint& constraint)
{
using serialize::read;
read(buf, constraint.init);
read(buf, constraint.trace);
uint8_t type;
read(buf, type);
constraint.type = static_cast<BlockType>(type);
}

template <typename B> inline void write(B& buf, BlockConstraint const& constraint)
{
using serialize::write;
write(buf, constraint.init);
write(buf, constraint.trace);
write(buf, static_cast<uint8_t>(constraint.type));
}
} // namespace acir_format
130 changes: 130 additions & 0 deletions cpp/src/barretenberg/dsl/acir_format/block_constraint.test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#include "acir_format.hpp"
#include "block_constraint.hpp"
#include "barretenberg/plonk/proof_system/types/proof.hpp"
#include "barretenberg/plonk/proof_system/verification_key/verification_key.hpp"

#include <gtest/gtest.h>
#include <vector>

size_t generate_block_constraint(acir_format::BlockConstraint& constraint, std::vector<fr>& witness_values)
{
size_t witness_len = 1;
witness_values.emplace_back(1);
witness_len++;

fr two = fr::one() + fr::one();
poly_triple a0 = poly_triple{
.a = 1,
.b = 0,
.c = 0,
.q_m = 0,
.q_l = two,
.q_r = 0,
.q_o = 0,
.q_c = 0,
};
fr three = fr::one() + two;
poly_triple a1 = poly_triple{
.a = 0,
.b = 0,
.c = 0,
.q_m = 0,
.q_l = 0,
.q_r = 0,
.q_o = 0,
.q_c = three,
};
poly_triple r1 = poly_triple{
.a = 1,
.b = 0,
.c = 0,
.q_m = 0,
.q_l = fr::one(),
.q_r = 0,
.q_o = 0,
.q_c = fr::neg_one(),
};
poly_triple r2 = poly_triple{
.a = 1,
.b = 0,
.c = 0,
.q_m = 0,
.q_l = two,
.q_r = 0,
.q_o = 0,
.q_c = fr::neg_one(),
};
poly_triple y = poly_triple{
.a = 2,
.b = 0,
.c = 0,
.q_m = 0,
.q_l = fr::one(),
.q_r = 0,
.q_o = 0,
.q_c = 0,
};
witness_values.emplace_back(2);
witness_len++;
poly_triple z = poly_triple{
.a = 3,
.b = 0,
.c = 0,
.q_m = 0,
.q_l = fr::one(),
.q_r = 0,
.q_o = 0,
.q_c = 0,
};
witness_values.emplace_back(3);
witness_len++;
acir_format::MemOp op1 = acir_format::MemOp{
.access_type = 0,
.index = r1,
.value = y,
};
acir_format::MemOp op2 = acir_format::MemOp{
.access_type = 0,
.index = r2,
.value = z,
};
constraint = acir_format::BlockConstraint{
.init = { a0, a1 },
.trace = { op1, op2 },
.type = acir_format::BlockType::ROM,
};

return witness_len;
}

TEST(up_ram, TestBlockConstraint)
{
acir_format::BlockConstraint block;
std::vector<fr> witness_values;
size_t num_variables = generate_block_constraint(block, witness_values);
acir_format::acir_format constraint_system{
.varnum = static_cast<uint32_t>(num_variables),
.public_inputs = {},
.fixed_base_scalar_mul_constraints = {},
.logic_constraints = {},
.range_constraints = {},
.schnorr_constraints = {},
.ecdsa_constraints = {},
.sha256_constraints = {},
.blake2s_constraints = {},
.keccak_constraints = {},
.hash_to_field_constraints = {},
.pedersen_constraints = {},
.compute_merkle_root_constraints = {},
.block_constraints = { block },
.constraints = {},
};

auto composer = acir_format::create_circuit_with_witness(constraint_system, witness_values);

auto prover = composer.create_prover();

auto proof = prover.construct_proof();
auto verifier = composer.create_verifier();
EXPECT_EQ(verifier.verify_proof(proof), true);
}
2 changes: 2 additions & 0 deletions cpp/src/barretenberg/dsl/acir_format/ecdsa_secp256k1.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ TEST(ECDSASecp256k1, TestECDSAConstraintSucceed)
.hash_to_field_constraints = {},
.pedersen_constraints = {},
.compute_merkle_root_constraints = {},
.block_constraints = {},
.constraints = {},
};

Expand Down Expand Up @@ -130,6 +131,7 @@ TEST(ECDSASecp256k1, TestECDSAConstraintFail)
.hash_to_field_constraints = {},
.pedersen_constraints = {},
.compute_merkle_root_constraints = {},
.block_constraints = {},
.constraints = {},
};

Expand Down
Loading