Skip to content

Commit

Permalink
Mc/hash vk (#306)
Browse files Browse the repository at this point in the history
* align native and circuit vk hashing methods

* fix: pass hash_index to circuit vk  function

* add some of the composer_type/plookup toggling for vk compress. Add some vk/eval-domain comments

* rename key_witnesses->preimage_data and composer type compression to circuit-compress of recursion vk

* some native verification_key_data tests

* add native and recursive vk compress test.

* change test name.

---------

Co-authored-by: dbanks12 <[email protected]>
Co-authored-by: Suyash Bagad <[email protected]>

js vk change.
  • Loading branch information
iAmMichaelConnor authored and suyash67 committed Apr 4, 2023
1 parent 08e02b6 commit 97fcf84
Show file tree
Hide file tree
Showing 8 changed files with 284 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -803,7 +803,7 @@ TEST_F(join_split_tests, test_0_input_notes_and_detect_circuit_change)
// The below part detects any changes in the join-split circuit
constexpr uint32_t CIRCUIT_GATE_COUNT = 64000;
constexpr uint32_t GATES_NEXT_POWER_OF_TWO = 65536;
const uint256_t VK_HASH("75c4ddd01f9e97c6a8cabd0b6040570f4a319f87111b69523c384e1a28265671");
const uint256_t VK_HASH("095cbe8f1b09690713d5161708b5ea77119575884e3cfab14f7364b9f1ba7faa");

auto number_of_gates_js = result.number_of_gates;
auto vk_hash_js = get_verification_key()->sha256_hash();
Expand Down
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;

/**
* @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

0 comments on commit 97fcf84

Please sign in to comment.