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

Mc/hash vk #306

Merged
merged 7 commits into from
Apr 4, 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
Original file line number Diff line number Diff line change
@@ -1,10 +1,44 @@
#include "barretenberg/crypto/sha256/sha256.hpp"
#include "barretenberg/crypto/pedersen_commitment/pedersen.hpp"
#include "barretenberg/crypto/pedersen_commitment/pedersen_lookup.hpp"
#include "barretenberg/polynomials/evaluation_domain.hpp"
#include "verification_key.hpp"
#include "../../plonk/proof_system/constants.hpp"

namespace bonk {

/**
* @brief Hashes the evaluation domain to match the 'circuit' approach taken in
* stdlib/recursion/verification_key/verification_key.hpp.
* @note: in that reference file, the circuit-equivalent of this function is a _method_ of the `evaluation_domain'
* struct. But we cannot do that with the native `barretenberg::evaluation_domain` type unfortunately, because it's
* defined in polynomials/evaluation_domain.hpp, and `polynomial` is a bberg library which does not depend on `crypto`
* in its CMakeLists.txt file. (We'd need `crypto` to be able to call native pedersen functions).
*
* @param domain to compress
* @param composer_type to use when choosing pedersen compression function
* @return barretenberg::fr compression of the evaluation domain as a field
*/
barretenberg::fr compress_native_evaluation_domain(barretenberg::evaluation_domain const& domain,
plonk::ComposerType composer_type)
{
barretenberg::fr out;
if (composer_type == plonk::ComposerType::PLOOKUP) {
out = crypto::pedersen_commitment::lookup::compress_native({
domain.root,
domain.domain,
domain.generator,
});
} else {
out = crypto::pedersen_commitment::compress_native({
domain.root,
domain.domain,
domain.generator,
});
}
return out;
}

/**
* @brief Compress the verification key data.
*
Expand All @@ -17,15 +51,46 @@ namespace bonk {
*/
barretenberg::fr verification_key_data::compress_native(const size_t hash_index)
{
barretenberg::evaluation_domain domain = evaluation_domain(circuit_size);
barretenberg::fr compressed_domain = compress_native_evaluation_domain(domain, plonk::ComposerType(composer_type));

constexpr size_t num_limb_bits = plonk::NUM_LIMB_BITS_IN_FIELD_SIMULATION;

const auto split_bigfield_limbs = [](const uint256_t& element) {
std::vector<barretenberg::fr> limbs;
limbs.push_back(element.slice(0, num_limb_bits));
limbs.push_back(element.slice(num_limb_bits, num_limb_bits * 2));
limbs.push_back(element.slice(num_limb_bits * 2, num_limb_bits * 3));
limbs.push_back(element.slice(num_limb_bits * 3, num_limb_bits * 4));
return limbs;
};

std::vector<barretenberg::fr> preimage_data;
preimage_data.emplace_back(composer_type);
preimage_data.emplace_back(circuit_size);
preimage_data.emplace_back(compressed_domain);
preimage_data.emplace_back(num_public_inputs);
for (auto& commitment_entry : commitments) {
preimage_data.emplace_back(commitment_entry.second.x);
preimage_data.emplace_back(commitment_entry.second.y);
for (const auto& [tag, selector] : commitments) {
const auto x_limbs = split_bigfield_limbs(selector.x);
const auto y_limbs = split_bigfield_limbs(selector.y);

preimage_data.push_back(x_limbs[0]);
preimage_data.push_back(x_limbs[1]);
preimage_data.push_back(x_limbs[2]);
preimage_data.push_back(x_limbs[3]);

preimage_data.push_back(y_limbs[0]);
preimage_data.push_back(y_limbs[1]);
preimage_data.push_back(y_limbs[2]);
preimage_data.push_back(y_limbs[3]);
}

barretenberg::fr compressed_key;
if (plonk::ComposerType(composer_type) == plonk::ComposerType::PLOOKUP) {
compressed_key = crypto::pedersen_commitment::lookup::compress_native(preimage_data, hash_index);
} else {
compressed_key = crypto::pedersen_commitment::compress_native(preimage_data, hash_index);
}
return crypto::pedersen_commitment::compress_native(preimage_data, hash_index);
return compressed_key;
}

verification_key::verification_key(const size_t num_gates,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,12 @@ template <typename B> inline void write(B& buf, verification_key const& key)

inline std::ostream& operator<<(std::ostream& os, verification_key const& key)
{
return os
<< "key.composer_type: " << key.composer_type << "\n"
<< "key.circuit_size: " << static_cast<uint32_t>(key.circuit_size) << "\n"
<< "key.num_public_inputs: " << static_cast<uint32_t>(key.num_public_inputs) << "\n"
<< "key.commitments: " << key.commitments << "\n"
<< "key.contains_recursive_proof: " << key.contains_recursive_proof << "\n"
<< "key.recursive_proof_public_input_indices: " << key.recursive_proof_public_input_indices << "\n";
return os << "key.composer_type: " << key.composer_type << "\n"
<< "key.circuit_size: " << static_cast<uint32_t>(key.circuit_size) << "\n"
<< "key.num_public_inputs: " << static_cast<uint32_t>(key.num_public_inputs) << "\n"
<< "key.commitments: " << key.commitments << "\n"
<< "key.contains_recursive_proof: " << key.contains_recursive_proof << "\n"
<< "key.recursive_proof_public_input_indices: " << key.recursive_proof_public_input_indices << "\n";
};

} // namespace bonk
Original file line number Diff line number Diff line change
@@ -1,43 +1,154 @@
#include "barretenberg/common/test.hpp"
#include "barretenberg/common/streams.hpp"
#include "barretenberg/numeric/random/engine.hpp"
#include "verification_key.hpp"

namespace {
auto& engine = numeric::random::get_debug_engine();
}

using namespace barretenberg;
using namespace bonk;

/**
suyash67 marked this conversation as resolved.
Show resolved Hide resolved
* @brief generated a random vk data for use in tests
*
* @return verification_key_data randomly generated
*/
verification_key_data rand_vk_data()
{
verification_key_data key_data;
key_data.composer_type = static_cast<uint32_t>(plonk::ComposerType::STANDARD);
key_data.circuit_size = 1024; // not random - must be power of 2
key_data.num_public_inputs = engine.get_random_uint32();
key_data.commitments["test1"] = g1::element::random_element();
key_data.commitments["test2"] = g1::element::random_element();
key_data.commitments["foo1"] = g1::element::random_element();
key_data.commitments["foo2"] = g1::element::random_element();
return key_data;
}

/**
* @brief expect that two vk data compressions are equal for a few different hash indices
*
* @param key0_data
* @param key1_data
*/
void expect_compressions_eq(verification_key_data key0_data, verification_key_data key1_data)
{
// 0 hash index
EXPECT_EQ(key0_data.compress_native(0), key1_data.compress_native(0));
// nonzero hash index
EXPECT_EQ(key0_data.compress_native(15), key1_data.compress_native(15));
}

/**
* @brief expect that two vk data compressions are not-equal for a few different hash indices
*
* @param key0_data
* @param key1_data
*/
void expect_compressions_ne(verification_key_data key0_data, verification_key_data key1_data)
{
EXPECT_NE(key0_data.compress_native(0), key1_data.compress_native(0));
EXPECT_NE(key0_data.compress_native(15), key1_data.compress_native(15));
// ne hash indeces still lead to ne compressions
EXPECT_NE(key0_data.compress_native(0), key1_data.compress_native(15));
EXPECT_NE(key0_data.compress_native(14), key1_data.compress_native(15));
}

TEST(verification_key, buffer_serialization)
{
verification_key_data key;
key.composer_type = static_cast<uint32_t>(plonk::ComposerType::STANDARD);
key.circuit_size = 1234;
key.num_public_inputs = 10;
key.commitments["test1"] = g1::element::random_element();
key.commitments["test2"] = g1::element::random_element();
key.commitments["foo1"] = g1::element::random_element();
key.commitments["foo2"] = g1::element::random_element();
verification_key_data key_data = rand_vk_data();

auto buf = to_buffer(key);
auto buf = to_buffer(key_data);
auto result = from_buffer<verification_key_data>(buf);

EXPECT_EQ(key, result);
EXPECT_EQ(key_data, result);
}

TEST(verification_key, stream_serialization)
{
verification_key_data key;
key.composer_type = static_cast<uint32_t>(plonk::ComposerType::STANDARD);
key.circuit_size = 1234;
key.num_public_inputs = 10;
key.commitments["test1"] = g1::element::random_element();
key.commitments["test2"] = g1::element::random_element();
key.commitments["foo1"] = g1::element::random_element();
key.commitments["foo2"] = g1::element::random_element();
verification_key_data key_data = rand_vk_data();

std::stringstream s;
write(s, key);
write(s, key_data);

verification_key_data result;
read(static_cast<std::istream&>(s), result);

EXPECT_EQ(key, result);
EXPECT_EQ(key_data, result);
}

TEST(verification_key, basic_compression_equality)
{
verification_key_data key0_data = rand_vk_data();
verification_key_data key1_data = key0_data; // copy
expect_compressions_eq(key0_data, key1_data);
}

TEST(verification_key, compression_inequality_index_mismatch)
{
verification_key_data key0_data = rand_vk_data();
verification_key_data key1_data = key0_data; // copy
// inquality on hash index mismatch
EXPECT_NE(key0_data.compress_native(0), key1_data.compress_native(15));
EXPECT_NE(key0_data.compress_native(14), key1_data.compress_native(15));
}

TEST(verification_key, compression_inequality_composer_type)
{
verification_key_data key0_data = rand_vk_data();
verification_key_data key1_data = key0_data; // copy
key0_data.composer_type = static_cast<uint32_t>(plonk::ComposerType::PLOOKUP);
expect_compressions_ne(key0_data, key1_data);
}

TEST(verification_key, compression_inequality_different_circuit_size)
{
verification_key_data key0_data = rand_vk_data();
verification_key_data key1_data = key0_data;
key0_data.circuit_size = 4096;
expect_compressions_ne(key0_data, key1_data);
}

TEST(verification_key, compression_inequality_different_num_public_inputs)
{
verification_key_data key0_data = rand_vk_data();
verification_key_data key1_data = key0_data;
key0_data.num_public_inputs = 42;
expect_compressions_ne(key0_data, key1_data);
}

TEST(verification_key, compression_inequality_different_commitments)
{
verification_key_data key0_data = rand_vk_data();
verification_key_data key1_data = key0_data;
key0_data.commitments["test1"] = g1::element::random_element();
expect_compressions_ne(key0_data, key1_data);
}

TEST(verification_key, compression_inequality_different_num_commitments)
{
verification_key_data key0_data = rand_vk_data();
verification_key_data key1_data = key0_data;
key0_data.commitments["new"] = g1::element::random_element();
expect_compressions_ne(key0_data, key1_data);
}

TEST(verification_key, compression_equality_different_contains_recursive_proof)
{
verification_key_data key0_data = rand_vk_data();
verification_key_data key1_data = key0_data;
key0_data.contains_recursive_proof = false;
key1_data.contains_recursive_proof = true;
expect_compressions_eq(key0_data, key1_data);
}

TEST(verification_key, compression_equality_different_recursive_proof_public_input_indices)
{
verification_key_data key0_data = rand_vk_data();
verification_key_data key1_data = key0_data;
key1_data.recursive_proof_public_input_indices.push_back(42);
expect_compressions_eq(key0_data, key1_data);
}
2 changes: 1 addition & 1 deletion cpp/src/barretenberg/stdlib/primitives/address/address.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ template <typename B> void read(B& it, address& addr)
using serialize::read;
fr address_field;
read(it, address_field);
addr = address_field;
addr = address(address_field);
}

template <typename B> void write(B& buf, address const& addr)
Expand Down
2 changes: 1 addition & 1 deletion cpp/src/barretenberg/stdlib/recursion/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
barretenberg_module(stdlib_recursion ecc plonk stdlib_primitives stdlib_pedersen_commitment stdlib_blake3s)
barretenberg_module(stdlib_recursion ecc proof_system stdlib_primitives stdlib_pedersen_commitment stdlib_blake3s)
Loading