From b465581ae5c762d277fb2c99c601405e0215d265 Mon Sep 17 00:00:00 2001 From: iAmMichaelConnor Date: Mon, 3 Apr 2023 11:52:45 +0000 Subject: [PATCH 01/11] align native and circuit vk hashing methods --- .../polynomials/evaluation_domain.hpp | 2 +- .../verification_key/verification_key.cpp | 52 +++++++++++++++++-- .../stdlib/primitives/address/address.hpp | 2 +- .../verification_key/verification_key.hpp | 30 ++++++----- 4 files changed, 66 insertions(+), 20 deletions(-) diff --git a/cpp/src/barretenberg/polynomials/evaluation_domain.hpp b/cpp/src/barretenberg/polynomials/evaluation_domain.hpp index 4dd908ff7a..1bb955cf04 100644 --- a/cpp/src/barretenberg/polynomials/evaluation_domain.hpp +++ b/cpp/src/barretenberg/polynomials/evaluation_domain.hpp @@ -38,7 +38,7 @@ template class EvaluationDomain { const std::vector& get_round_roots() const { return round_roots; }; const std::vector& get_inverse_round_roots() const { return inverse_round_roots; } - + size_t size; // n, always a power of 2 size_t num_threads; // num_threads * thread_size = size size_t thread_size; diff --git a/cpp/src/barretenberg/proof_system/verification_key/verification_key.cpp b/cpp/src/barretenberg/proof_system/verification_key/verification_key.cpp index 0209bc3a0c..8a13f69f09 100644 --- a/cpp/src/barretenberg/proof_system/verification_key/verification_key.cpp +++ b/cpp/src/barretenberg/proof_system/verification_key/verification_key.cpp @@ -1,10 +1,23 @@ #include "barretenberg/crypto/sha256/sha256.hpp" #include "barretenberg/crypto/pedersen_commitment/pedersen.hpp" +#include "barretenberg/polynomials/evaluation_domain.hpp" #include "verification_key.hpp" #include "../../plonk/proof_system/constants.hpp" namespace bonk { +barretenberg::fr compress_native_evaluation_domain(barretenberg::evaluation_domain const& domain) { + barretenberg::fr out; + + out = crypto::pedersen_commitment::compress_native({ + domain.root, + domain.domain, + domain.generator, + }); + + return out; +} + /** * @brief Compress the verification key data. * @@ -17,14 +30,45 @@ 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); + + constexpr size_t num_limb_bits = plonk::NUM_LIMB_BITS_IN_FIELD_SIMULATION; + + const auto split_bigfield_limbs = [](const uint256_t& element) { + std::vector 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 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 (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] : this->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]); } + + // NOTE: this does not do the PLOOKUP version of the hash. + // TODO: implement this! return crypto::pedersen_commitment::compress_native(preimage_data, hash_index); } diff --git a/cpp/src/barretenberg/stdlib/primitives/address/address.hpp b/cpp/src/barretenberg/stdlib/primitives/address/address.hpp index f50c890f0c..fb2dd57d39 100644 --- a/cpp/src/barretenberg/stdlib/primitives/address/address.hpp +++ b/cpp/src/barretenberg/stdlib/primitives/address/address.hpp @@ -54,7 +54,7 @@ template void read(B& it, address& addr) using serialize::read; fr address_field; read(it, address_field); - addr = address_field; + addr = address(address_field); } template void write(B& buf, address const& addr) diff --git a/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.hpp b/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.hpp index df8e5b21b0..066a9e39c8 100644 --- a/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.hpp +++ b/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.hpp @@ -215,7 +215,7 @@ template struct verification_key { return compressed_key; } - static barretenberg::fr compress_native(const std::shared_ptr& key) + static barretenberg::fr compress_native(const std::shared_ptr& key, const size_t hash_index = 0) { barretenberg::fr compressed_domain = evaluation_domain::compress_native(key->domain); @@ -229,28 +229,30 @@ template struct verification_key { return limbs; }; - std::vector key_witnesses; - key_witnesses.push_back(compressed_domain); - key_witnesses.push_back(key->num_public_inputs); + std::vector preimage_data; + // TODO: put composer type in here. + preimage_data.push_back(Composer::type); + preimage_data.push_back(compressed_domain); + preimage_data.push_back(key->num_public_inputs); for (const auto& [tag, selector] : key->commitments) { const auto x_limbs = split_bigfield_limbs(selector.x); const auto y_limbs = split_bigfield_limbs(selector.y); - key_witnesses.push_back(x_limbs[0]); - key_witnesses.push_back(x_limbs[1]); - key_witnesses.push_back(x_limbs[2]); - key_witnesses.push_back(x_limbs[3]); + 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]); - key_witnesses.push_back(y_limbs[0]); - key_witnesses.push_back(y_limbs[1]); - key_witnesses.push_back(y_limbs[2]); - key_witnesses.push_back(y_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 constexpr (Composer::type == ComposerType::PLOOKUP) { - compressed_key = crypto::pedersen_commitment::lookup::compress_native(key_witnesses); + compressed_key = crypto::pedersen_commitment::lookup::compress_native(preimage_data, hash_index); } else { - compressed_key = crypto::pedersen_commitment::compress_native(key_witnesses); + compressed_key = crypto::pedersen_commitment::compress_native(preimage_data, hash_index); // TODO: we need a hash index here! } return compressed_key; } From 89249dbe2fd184cb2f4b7b8a7b673179e674fde1 Mon Sep 17 00:00:00 2001 From: iAmMichaelConnor Date: Mon, 3 Apr 2023 12:01:20 +0000 Subject: [PATCH 02/11] fix: pass hash_index to circuit vk function --- .../stdlib/recursion/verification_key/verification_key.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.hpp b/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.hpp index 066a9e39c8..1123807728 100644 --- a/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.hpp +++ b/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.hpp @@ -188,7 +188,7 @@ template struct verification_key { } public: - field_t compress() + field_t compress(size_t const hash_index = 0) { field_t compressed_domain = domain.compress(); @@ -208,9 +208,9 @@ template struct verification_key { field_t compressed_key; if constexpr (Composer::type == ComposerType::PLOOKUP) { - compressed_key = pedersen_plookup_commitment::compress(key_witnesses); + compressed_key = pedersen_plookup_commitment::compress(key_witnesses, hash_index); } else { - compressed_key = pedersen_commitment::compress(key_witnesses); + compressed_key = pedersen_commitment::compress(key_witnesses, hash_index); } return compressed_key; } From 54e02161593ced9ffaf780b88ff8537e8dc8ea33 Mon Sep 17 00:00:00 2001 From: dbanks12 Date: Mon, 3 Apr 2023 16:06:07 +0000 Subject: [PATCH 03/11] add some of the composer_type/plookup toggling for vk compress. Add some vk/eval-domain comments --- .../polynomials/evaluation_domain.hpp | 2 +- .../verification_key/verification_key.cpp | 46 ++++++++++++------- .../verification_key/verification_key.hpp | 3 +- 3 files changed, 32 insertions(+), 19 deletions(-) diff --git a/cpp/src/barretenberg/polynomials/evaluation_domain.hpp b/cpp/src/barretenberg/polynomials/evaluation_domain.hpp index 1bb955cf04..4dd908ff7a 100644 --- a/cpp/src/barretenberg/polynomials/evaluation_domain.hpp +++ b/cpp/src/barretenberg/polynomials/evaluation_domain.hpp @@ -38,7 +38,7 @@ template class EvaluationDomain { const std::vector& get_round_roots() const { return round_roots; }; const std::vector& get_inverse_round_roots() const { return inverse_round_roots; } - + size_t size; // n, always a power of 2 size_t num_threads; // num_threads * thread_size = size size_t thread_size; diff --git a/cpp/src/barretenberg/proof_system/verification_key/verification_key.cpp b/cpp/src/barretenberg/proof_system/verification_key/verification_key.cpp index 8a13f69f09..3e1c400a3c 100644 --- a/cpp/src/barretenberg/proof_system/verification_key/verification_key.cpp +++ b/cpp/src/barretenberg/proof_system/verification_key/verification_key.cpp @@ -6,15 +6,29 @@ namespace bonk { -barretenberg::fr compress_native_evaluation_domain(barretenberg::evaluation_domain const& domain) { +/** + * @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; - - out = crypto::pedersen_commitment::compress_native({ - domain.root, - domain.domain, - domain.generator, - }); - + 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; } @@ -31,7 +45,7 @@ barretenberg::fr compress_native_evaluation_domain(barretenberg::evaluation_doma 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); + 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; @@ -48,10 +62,6 @@ barretenberg::fr verification_key_data::compress_native(const size_t hash_index) preimage_data.emplace_back(composer_type); 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] : this->commitments) { const auto x_limbs = split_bigfield_limbs(selector.x); const auto y_limbs = split_bigfield_limbs(selector.y); @@ -67,9 +77,13 @@ barretenberg::fr verification_key_data::compress_native(const size_t hash_index) preimage_data.push_back(y_limbs[3]); } - // NOTE: this does not do the PLOOKUP version of the hash. - // TODO: implement this! - return crypto::pedersen_commitment::compress_native(preimage_data, hash_index); + 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 compressed_key; } verification_key::verification_key(const size_t num_gates, diff --git a/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.hpp b/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.hpp index 1123807728..a7ada5fb3e 100644 --- a/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.hpp +++ b/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.hpp @@ -230,7 +230,6 @@ template struct verification_key { }; std::vector preimage_data; - // TODO: put composer type in here. preimage_data.push_back(Composer::type); preimage_data.push_back(compressed_domain); preimage_data.push_back(key->num_public_inputs); @@ -252,7 +251,7 @@ template struct verification_key { if constexpr (Composer::type == 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); // TODO: we need a hash index here! + compressed_key = crypto::pedersen_commitment::compress_native(preimage_data, hash_index); } return compressed_key; } From 16af1d818c8ebeaef7b4812cadb91a928baa3441 Mon Sep 17 00:00:00 2001 From: dbanks12 Date: Mon, 3 Apr 2023 16:14:55 +0000 Subject: [PATCH 04/11] rename key_witnesses->preimage_data and composer type compression to circuit-compress of recursion vk --- .../verification_key/verification_key.cpp | 1 + .../verification_key/verification_key.hpp | 27 ++++++++++--------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/cpp/src/barretenberg/proof_system/verification_key/verification_key.cpp b/cpp/src/barretenberg/proof_system/verification_key/verification_key.cpp index 3e1c400a3c..0aefdef36f 100644 --- a/cpp/src/barretenberg/proof_system/verification_key/verification_key.cpp +++ b/cpp/src/barretenberg/proof_system/verification_key/verification_key.cpp @@ -1,5 +1,6 @@ #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" diff --git a/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.hpp b/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.hpp index a7ada5fb3e..2017ee901c 100644 --- a/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.hpp +++ b/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.hpp @@ -192,25 +192,26 @@ template struct verification_key { { field_t compressed_domain = domain.compress(); - std::vector> key_witnesses; - key_witnesses.push_back(compressed_domain); - key_witnesses.push_back(num_public_inputs); + std::vector> preimage_data; + preimage_data.push_back(Composer::type); + preimage_data.push_back(compressed_domain); + preimage_data.push_back(num_public_inputs); for (const auto& [tag, selector] : commitments) { - key_witnesses.push_back(selector.x.binary_basis_limbs[0].element); - key_witnesses.push_back(selector.x.binary_basis_limbs[1].element); - key_witnesses.push_back(selector.x.binary_basis_limbs[2].element); - key_witnesses.push_back(selector.x.binary_basis_limbs[3].element); - key_witnesses.push_back(selector.y.binary_basis_limbs[0].element); - key_witnesses.push_back(selector.y.binary_basis_limbs[1].element); - key_witnesses.push_back(selector.y.binary_basis_limbs[2].element); - key_witnesses.push_back(selector.y.binary_basis_limbs[3].element); + preimage_data.push_back(selector.x.binary_basis_limbs[0].element); + preimage_data.push_back(selector.x.binary_basis_limbs[1].element); + preimage_data.push_back(selector.x.binary_basis_limbs[2].element); + preimage_data.push_back(selector.x.binary_basis_limbs[3].element); + preimage_data.push_back(selector.y.binary_basis_limbs[0].element); + preimage_data.push_back(selector.y.binary_basis_limbs[1].element); + preimage_data.push_back(selector.y.binary_basis_limbs[2].element); + preimage_data.push_back(selector.y.binary_basis_limbs[3].element); } field_t compressed_key; if constexpr (Composer::type == ComposerType::PLOOKUP) { - compressed_key = pedersen_plookup_commitment::compress(key_witnesses, hash_index); + compressed_key = pedersen_plookup_commitment::compress(preimage_data, hash_index); } else { - compressed_key = pedersen_commitment::compress(key_witnesses, hash_index); + compressed_key = pedersen_commitment::compress(preimage_data, hash_index); } return compressed_key; } From f43895f50fcdc20a4084816f50657d8111992f27 Mon Sep 17 00:00:00 2001 From: dbanks12 Date: Mon, 3 Apr 2023 21:00:45 +0000 Subject: [PATCH 05/11] some native verification_key_data tests --- .../verification_key.test.cpp | 150 +++++++++++++++--- 1 file changed, 130 insertions(+), 20 deletions(-) diff --git a/cpp/src/barretenberg/proof_system/verification_key/verification_key.test.cpp b/cpp/src/barretenberg/proof_system/verification_key/verification_key.test.cpp index 8f74d875d6..8689bcb410 100644 --- a/cpp/src/barretenberg/proof_system/verification_key/verification_key.test.cpp +++ b/cpp/src/barretenberg/proof_system/verification_key/verification_key.test.cpp @@ -1,43 +1,153 @@ #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(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(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(buf); - EXPECT_EQ(key, result); + EXPECT_EQ(key_data, result); } TEST(verification_key, stream_serialization) { - verification_key_data key; - key.composer_type = static_cast(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(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(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); } From 5b2dca0d11dea6e947eeea22d3689a905426eea3 Mon Sep 17 00:00:00 2001 From: Michael Connor Date: Tue, 4 Apr 2023 02:20:36 +0100 Subject: [PATCH 06/11] Mc/hash vk (#306) * 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 Co-authored-by: Suyash Bagad --- .../verification_key/verification_key.cpp | 75 ++++++++- .../verification_key/verification_key.hpp | 13 +- .../verification_key.test.cpp | 151 +++++++++++++++--- .../stdlib/primitives/address/address.hpp | 2 +- .../stdlib/recursion/CMakeLists.txt | 2 +- .../verification_key/verification_key.hpp | 61 +++---- .../verification_key.test.cpp | 42 +++++ 7 files changed, 283 insertions(+), 63 deletions(-) create mode 100644 cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.test.cpp diff --git a/cpp/src/barretenberg/proof_system/verification_key/verification_key.cpp b/cpp/src/barretenberg/proof_system/verification_key/verification_key.cpp index 0209bc3a0c..e2582efacc 100644 --- a/cpp/src/barretenberg/proof_system/verification_key/verification_key.cpp +++ b/cpp/src/barretenberg/proof_system/verification_key/verification_key.cpp @@ -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. * @@ -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 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 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, diff --git a/cpp/src/barretenberg/proof_system/verification_key/verification_key.hpp b/cpp/src/barretenberg/proof_system/verification_key/verification_key.hpp index fc0e326863..bc3a77929f 100644 --- a/cpp/src/barretenberg/proof_system/verification_key/verification_key.hpp +++ b/cpp/src/barretenberg/proof_system/verification_key/verification_key.hpp @@ -116,13 +116,12 @@ template 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(key.circuit_size) << "\n" - << "key.num_public_inputs: " << static_cast(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(key.circuit_size) << "\n" + << "key.num_public_inputs: " << static_cast(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 diff --git a/cpp/src/barretenberg/proof_system/verification_key/verification_key.test.cpp b/cpp/src/barretenberg/proof_system/verification_key/verification_key.test.cpp index 8f74d875d6..abc5e277c6 100644 --- a/cpp/src/barretenberg/proof_system/verification_key/verification_key.test.cpp +++ b/cpp/src/barretenberg/proof_system/verification_key/verification_key.test.cpp @@ -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(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(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(buf); - EXPECT_EQ(key, result); + EXPECT_EQ(key_data, result); } TEST(verification_key, stream_serialization) { - verification_key_data key; - key.composer_type = static_cast(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(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(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); } diff --git a/cpp/src/barretenberg/stdlib/primitives/address/address.hpp b/cpp/src/barretenberg/stdlib/primitives/address/address.hpp index f50c890f0c..fb2dd57d39 100644 --- a/cpp/src/barretenberg/stdlib/primitives/address/address.hpp +++ b/cpp/src/barretenberg/stdlib/primitives/address/address.hpp @@ -54,7 +54,7 @@ template void read(B& it, address& addr) using serialize::read; fr address_field; read(it, address_field); - addr = address_field; + addr = address(address_field); } template void write(B& buf, address const& addr) diff --git a/cpp/src/barretenberg/stdlib/recursion/CMakeLists.txt b/cpp/src/barretenberg/stdlib/recursion/CMakeLists.txt index c5d1124e59..325069d446 100644 --- a/cpp/src/barretenberg/stdlib/recursion/CMakeLists.txt +++ b/cpp/src/barretenberg/stdlib/recursion/CMakeLists.txt @@ -1 +1 @@ -barretenberg_module(stdlib_recursion ecc plonk stdlib_primitives stdlib_pedersen_commitment stdlib_blake3s) \ No newline at end of file +barretenberg_module(stdlib_recursion ecc proof_system stdlib_primitives stdlib_pedersen_commitment stdlib_blake3s) \ No newline at end of file diff --git a/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.hpp b/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.hpp index df8e5b21b0..68c7abc620 100644 --- a/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.hpp +++ b/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.hpp @@ -5,7 +5,6 @@ #include "barretenberg/proof_system/types/polynomial_manifest.hpp" -#include "barretenberg/plonk/proof_system/utils/kate_verification.hpp" #include "barretenberg/plonk/proof_system/public_inputs/public_inputs.hpp" #include "barretenberg/polynomials/polynomial_arithmetic.hpp" @@ -188,34 +187,36 @@ template struct verification_key { } public: - field_t compress() + field_t compress(size_t const hash_index = 0) { field_t compressed_domain = domain.compress(); - std::vector> key_witnesses; - key_witnesses.push_back(compressed_domain); - key_witnesses.push_back(num_public_inputs); + std::vector> preimage_data; + preimage_data.push_back(Composer::type); + preimage_data.push_back(compressed_domain); + preimage_data.push_back(num_public_inputs); for (const auto& [tag, selector] : commitments) { - key_witnesses.push_back(selector.x.binary_basis_limbs[0].element); - key_witnesses.push_back(selector.x.binary_basis_limbs[1].element); - key_witnesses.push_back(selector.x.binary_basis_limbs[2].element); - key_witnesses.push_back(selector.x.binary_basis_limbs[3].element); - key_witnesses.push_back(selector.y.binary_basis_limbs[0].element); - key_witnesses.push_back(selector.y.binary_basis_limbs[1].element); - key_witnesses.push_back(selector.y.binary_basis_limbs[2].element); - key_witnesses.push_back(selector.y.binary_basis_limbs[3].element); + preimage_data.push_back(selector.x.binary_basis_limbs[0].element); + preimage_data.push_back(selector.x.binary_basis_limbs[1].element); + preimage_data.push_back(selector.x.binary_basis_limbs[2].element); + preimage_data.push_back(selector.x.binary_basis_limbs[3].element); + preimage_data.push_back(selector.y.binary_basis_limbs[0].element); + preimage_data.push_back(selector.y.binary_basis_limbs[1].element); + preimage_data.push_back(selector.y.binary_basis_limbs[2].element); + preimage_data.push_back(selector.y.binary_basis_limbs[3].element); } field_t compressed_key; if constexpr (Composer::type == ComposerType::PLOOKUP) { - compressed_key = pedersen_plookup_commitment::compress(key_witnesses); + compressed_key = pedersen_plookup_commitment::compress(preimage_data, hash_index); } else { - compressed_key = pedersen_commitment::compress(key_witnesses); + compressed_key = pedersen_commitment::compress(preimage_data, hash_index); } return compressed_key; } - static barretenberg::fr compress_native(const std::shared_ptr& key) + static barretenberg::fr compress_native(const std::shared_ptr& key, + const size_t hash_index = 0) { barretenberg::fr compressed_domain = evaluation_domain::compress_native(key->domain); @@ -229,28 +230,30 @@ template struct verification_key { return limbs; }; - std::vector key_witnesses; - key_witnesses.push_back(compressed_domain); - key_witnesses.push_back(key->num_public_inputs); + std::vector preimage_data; + preimage_data.push_back(Composer::type); + preimage_data.push_back(compressed_domain); + preimage_data.push_back(key->num_public_inputs); for (const auto& [tag, selector] : key->commitments) { const auto x_limbs = split_bigfield_limbs(selector.x); const auto y_limbs = split_bigfield_limbs(selector.y); - key_witnesses.push_back(x_limbs[0]); - key_witnesses.push_back(x_limbs[1]); - key_witnesses.push_back(x_limbs[2]); - key_witnesses.push_back(x_limbs[3]); + 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]); - key_witnesses.push_back(y_limbs[0]); - key_witnesses.push_back(y_limbs[1]); - key_witnesses.push_back(y_limbs[2]); - key_witnesses.push_back(y_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 constexpr (Composer::type == ComposerType::PLOOKUP) { - compressed_key = crypto::pedersen_commitment::lookup::compress_native(key_witnesses); + compressed_key = crypto::pedersen_commitment::lookup::compress_native(preimage_data, hash_index); } else { - compressed_key = crypto::pedersen_commitment::compress_native(key_witnesses); + compressed_key = crypto::pedersen_commitment::compress_native(preimage_data, hash_index); } return compressed_key; } diff --git a/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.test.cpp b/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.test.cpp new file mode 100644 index 0000000000..b30a0d64d4 --- /dev/null +++ b/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.test.cpp @@ -0,0 +1,42 @@ +#include "verification_key.hpp" +#include + +#include "barretenberg/ecc/curves/bn254/fr.hpp" +#include "barretenberg/ecc/curves/bn254/g1.hpp" +#include "barretenberg/proof_system/verification_key/verification_key.hpp" +#include "barretenberg/plonk/proof_system/constants.hpp" +#include "barretenberg/stdlib/types/types.hpp" + +using namespace plonk; + +namespace { +auto& engine = numeric::random::get_debug_engine(); +} + +verification_key_data rand_vk_data(plonk::ComposerType composer_type) +{ + verification_key_data key_data; + key_data.composer_type = static_cast(composer_type); + key_data.circuit_size = 1024; // not random - must be power of 2 + key_data.num_public_inputs = engine.get_random_uint16(); + 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; +} + +TEST(stdlib_verification_key, compress_native_comparison) +{ + // Compute compression of native verification key (i.e. vk_data) + auto crs = std::make_unique("../srs_db/ignition"); + verification_key_data vk_data = rand_vk_data(stdlib::types::Composer::type); + const size_t hash_idx = 10; + auto native_vk_compression = vk_data.compress_native(hash_idx); + + // Compute compression of recursive verification key + auto verification_key = std::make_shared(std::move(vk_data), crs->get_verifier_crs()); + auto recursive_vk_compression = + stdlib::recursion::verification_key::compress_native(verification_key, hash_idx); + EXPECT_EQ(native_vk_compression, recursive_vk_compression); +} \ No newline at end of file From 5b88780c2c60580a7fb50e512dd0bf0cef1af9ab Mon Sep 17 00:00:00 2001 From: dbanks12 Date: Tue, 4 Apr 2023 01:27:39 +0000 Subject: [PATCH 07/11] verification key tests --- .../verification_key/verification_key.cpp | 2 +- .../verification_key.test.cpp | 131 +++++++++--------- .../verification_key.test.cpp | 100 +++++++++++++ 3 files changed, 167 insertions(+), 66 deletions(-) create mode 100644 cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.test.cpp diff --git a/cpp/src/barretenberg/proof_system/verification_key/verification_key.cpp b/cpp/src/barretenberg/proof_system/verification_key/verification_key.cpp index 0aefdef36f..3076c3bc52 100644 --- a/cpp/src/barretenberg/proof_system/verification_key/verification_key.cpp +++ b/cpp/src/barretenberg/proof_system/verification_key/verification_key.cpp @@ -63,7 +63,7 @@ barretenberg::fr verification_key_data::compress_native(const size_t hash_index) preimage_data.emplace_back(composer_type); preimage_data.emplace_back(compressed_domain); preimage_data.emplace_back(num_public_inputs); - for (const auto& [tag, selector] : this->commitments) { + for (const auto& [tag, selector] : commitments) { const auto x_limbs = split_bigfield_limbs(selector.x); const auto y_limbs = split_bigfield_limbs(selector.y); diff --git a/cpp/src/barretenberg/proof_system/verification_key/verification_key.test.cpp b/cpp/src/barretenberg/proof_system/verification_key/verification_key.test.cpp index 8689bcb410..1af4aae3d3 100644 --- a/cpp/src/barretenberg/proof_system/verification_key/verification_key.test.cpp +++ b/cpp/src/barretenberg/proof_system/verification_key/verification_key.test.cpp @@ -5,149 +5,150 @@ namespace { auto& engine = numeric::random::get_debug_engine(); -} +} // namespace using namespace barretenberg; using namespace bonk; /** - * @brief generated a random vk data for use in tests + * @brief generate 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(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; + verification_key_data vk_data; + vk_data.composer_type = static_cast(plonk::ComposerType::STANDARD); + vk_data.circuit_size = 1024; // not random - must be power of 2 + vk_data.num_public_inputs = engine.get_random_uint32(); + vk_data.commitments["test1"] = g1::element::random_element(); + vk_data.commitments["test2"] = g1::element::random_element(); + vk_data.commitments["foo1"] = g1::element::random_element(); + vk_data.commitments["foo2"] = g1::element::random_element(); + info("test0 vk_data commitments: ", vk_data.commitments); + return vk_data; } /** * @brief expect that two vk data compressions are equal for a few different hash indices * - * @param key0_data - * @param key1_data + * @param vk0_data + * @param vk1_data */ -void expect_compressions_eq(verification_key_data key0_data, verification_key_data key1_data) +void expect_compressions_eq(verification_key_data vk0_data, verification_key_data vk1_data) { // 0 hash index - EXPECT_EQ(key0_data.compress_native(0), key1_data.compress_native(0)); + EXPECT_EQ(vk0_data.compress_native(0), vk1_data.compress_native(0)); // nonzero hash index - EXPECT_EQ(key0_data.compress_native(15), key1_data.compress_native(15)); + EXPECT_EQ(vk0_data.compress_native(15), vk1_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 + * @param vk0_data + * @param vk1_data */ -void expect_compressions_ne(verification_key_data key0_data, verification_key_data key1_data) +void expect_compressions_ne(verification_key_data vk0_data, verification_key_data vk1_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)); + EXPECT_NE(vk0_data.compress_native(0), vk1_data.compress_native(0)); + EXPECT_NE(vk0_data.compress_native(15), vk1_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)); + EXPECT_NE(vk0_data.compress_native(0), vk1_data.compress_native(15)); + EXPECT_NE(vk0_data.compress_native(14), vk1_data.compress_native(15)); } TEST(verification_key, buffer_serialization) { - verification_key_data key_data = rand_vk_data(); + verification_key_data vk_data = rand_vk_data(); - auto buf = to_buffer(key_data); + auto buf = to_buffer(vk_data); auto result = from_buffer(buf); - EXPECT_EQ(key_data, result); + EXPECT_EQ(vk_data, result); } TEST(verification_key, stream_serialization) { - verification_key_data key_data = rand_vk_data(); + verification_key_data vk_data = rand_vk_data(); std::stringstream s; - write(s, key_data); + write(s, vk_data); verification_key_data result; read(static_cast(s), result); - EXPECT_EQ(key_data, result); + EXPECT_EQ(vk_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); + verification_key_data vk0_data = rand_vk_data(); + verification_key_data vk1_data = vk0_data; // copy + expect_compressions_eq(vk0_data, vk1_data); } TEST(verification_key, compression_inequality_index_mismatch) { - verification_key_data key0_data = rand_vk_data(); - verification_key_data key1_data = key0_data; // copy + verification_key_data vk0_data = rand_vk_data(); + verification_key_data vk1_data = vk0_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)); + EXPECT_NE(vk0_data.compress_native(0), vk1_data.compress_native(15)); + EXPECT_NE(vk0_data.compress_native(14), vk1_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(plonk::ComposerType::PLOOKUP); - expect_compressions_ne(key0_data, key1_data); + verification_key_data vk0_data = rand_vk_data(); + verification_key_data vk1_data = vk0_data; // copy + vk0_data.composer_type = static_cast(plonk::ComposerType::PLOOKUP); + expect_compressions_ne(vk0_data, vk1_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); + verification_key_data vk0_data = rand__data(); + verification_key_data vk1_data = vk0_data; + vk0_data.circuit_size = 4096; + expect_compressions_ne(vk0_data, vk1_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); + verification_key_data vk0_data = rand_vk_data(); + verification_key_data vk1_data = vk0_data; + vk0_data.num_public_inputs = 42; + expect_compressions_ne(vk0_data, vk1_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); + verification_key_data vk0_data = rand_vk_data(); + verification_key_data vk1_data = vk0_data; + vk0_data.commitments["test1"] = g1::element::random_element(); + expect_compressions_ne(vk0_data, vk1_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); + verification_key_data vk0_data = rand_vk_data(); + verification_key_data vk1_data = vk0_data; + vk0_data.commitments["new"] = g1::element::random_element(); + expect_compressions_ne(vk0_data, vk1_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); + verification_key_data vk0_data = rand_vk_data(); + verification_key_data vk1_data = vk0_data; + vk0_data.contains_recursive_proof = false; + vk1_data.contains_recursive_proof = true; + expect_compressions_eq(vk0_data, vk1_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); + verification_key_data vk0_data = rand_vk_data(); + verification_key_data vk1_data = vk0_data; + vk1_data.recursive_proof_public_input_indices.push_back(42); + expect_compressions_eq(vk0_data, vk1_data); } diff --git a/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.test.cpp b/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.test.cpp new file mode 100644 index 0000000000..371f235eb6 --- /dev/null +++ b/cpp/src/barretenberg/stdlib/recursion/verification_key/verification_key.test.cpp @@ -0,0 +1,100 @@ +#include "barretenberg/common/test.hpp" +#include "barretenberg/proof_system/verification_key/verification_key.hpp" +#include "barretenberg/plonk/composer/standard_composer.hpp" +#include "barretenberg/plonk/composer/turbo_composer.hpp" +#include "barretenberg/plonk/composer/ultra_composer.hpp" +#include "verification_key.hpp" + +namespace { +auto& engine = numeric::random::get_debug_engine(); +} // namespace + +/** + * @brief A test fixture that will let us generate VK data and run tests + * for all composer types + * + * @tparam Composer + */ +template class VerificationKeyFixture : public testing::Test { + public: + using Curve = stdlib::bn254; + using RecursVk = plonk::stdlib::recursion::verification_key; + + static Composer init_composer() { + return Composer("../srs_db/ignition"); + } + + /** + * @brief generate a random vk data for use in tests + * + * @return verification_key_data randomly generated + */ + static verification_key_data rand_vk_data() { + verification_key_data vk_data; + vk_data.composer_type = static_cast(Composer::type); + vk_data.circuit_size = 1024; // not random - must be power of 2 + vk_data.num_public_inputs = engine.get_random_uint32(); + vk_data.commitments["test1"] = g1::element::random_element(); + vk_data.commitments["test2"] = g1::element::random_element(); + vk_data.commitments["foo1"] = g1::element::random_element(); + vk_data.commitments["foo2"] = g1::element::random_element(); + return vk_data; + } +}; + +// Each test will run for all composer types +using ComposerTypes = testing::Types; +TYPED_TEST_SUITE(VerificationKeyFixture, ComposerTypes); + +TYPED_TEST(VerificationKeyFixture, vk_data_vs_recursion_compress_native) +{ + using RecursVk = typename TestFixture::RecursVk; + auto composer = TestFixture::init_composer(); + + verification_key_data vk_data = TestFixture::rand_vk_data(); + verification_key_data vk_data_copy = vk_data; + + auto file_crs = std::make_unique("../srs_db/ignition"); + auto file_verifier = file_crs->get_verifier_crs(); + + auto native_vk = std::make_shared(std::move(vk_data_copy), file_verifier); + auto recurs_vk = RecursVk::from_witness(&composer, native_vk); + + EXPECT_EQ(vk_data.compress_native(0), RecursVk::compress_native(native_vk, 0)); + EXPECT_EQ(vk_data.compress_native(15), RecursVk::compress_native(native_vk, 15)); + // ne hash indeces still lead to ne compressions + EXPECT_NE(vk_data.compress_native(0), RecursVk::compress_native(native_vk, 15)); + EXPECT_NE(vk_data.compress_native(14), RecursVk::compress_native(native_vk, 15)); +} + +TYPED_TEST(VerificationKeyFixture, compress_vs_compress_native) +{ + using RecursVk = typename TestFixture::RecursVk; + auto composer = TestFixture::init_composer(); + + verification_key_data vk_data = TestFixture::rand_vk_data(); + + auto file_crs = std::make_unique("../srs_db/ignition"); + auto file_verifier = file_crs->get_verifier_crs(); + + auto native_vk = std::make_shared(std::move(vk_data), file_verifier); + auto recurs_vk = RecursVk::from_witness(&composer, native_vk); + + EXPECT_EQ( + recurs_vk->compress(0).get_value(), + RecursVk::compress_native(native_vk, 0) + ); + EXPECT_EQ( + recurs_vk->compress(15).get_value(), + RecursVk::compress_native(native_vk, 15) + ); + // ne hash indeces still lead to ne compressions + EXPECT_NE( + recurs_vk->compress(0).get_value(), + RecursVk::compress_native(native_vk, 15) + ); + EXPECT_NE( + recurs_vk->compress(14).get_value(), + RecursVk::compress_native(native_vk, 15) + ); +} From 6c101be134bbea01deed88a5085ebd35e6f62796 Mon Sep 17 00:00:00 2001 From: Suyash Bagad Date: Tue, 4 Apr 2023 02:43:59 +0100 Subject: [PATCH 08/11] inc num_generators_per_hash_index to 128. (#309) --- cpp/src/barretenberg/crypto/generators/generator_data.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/src/barretenberg/crypto/generators/generator_data.cpp b/cpp/src/barretenberg/crypto/generators/generator_data.cpp index db6c676336..7970dfe659 100644 --- a/cpp/src/barretenberg/crypto/generators/generator_data.cpp +++ b/cpp/src/barretenberg/crypto/generators/generator_data.cpp @@ -13,7 +13,7 @@ constexpr size_t num_hash_indices = 32; #else constexpr size_t num_default_generators = 2048; constexpr size_t num_hash_indices = 32; -constexpr size_t num_generators_per_hash_index = 64; +constexpr size_t num_generators_per_hash_index = 128; #endif constexpr size_t hash_indices_generator_offset = 2048; From df4d08db59103a5ca95429b43b65afc2ff96b712 Mon Sep 17 00:00:00 2001 From: dbanks12 Date: Tue, 4 Apr 2023 03:02:14 +0000 Subject: [PATCH 09/11] revert bad changes to eval domain --- .../proof_system/verification_key/verification_key.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cpp/src/barretenberg/proof_system/verification_key/verification_key.cpp b/cpp/src/barretenberg/proof_system/verification_key/verification_key.cpp index 5e1f0e9348..e2582efacc 100644 --- a/cpp/src/barretenberg/proof_system/verification_key/verification_key.cpp +++ b/cpp/src/barretenberg/proof_system/verification_key/verification_key.cpp @@ -21,9 +21,12 @@ namespace bonk { */ 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 { From 313c803580e188d9202a487560bf1fbacb1ef153 Mon Sep 17 00:00:00 2001 From: dbanks12 Date: Tue, 4 Apr 2023 03:16:28 +0000 Subject: [PATCH 10/11] add vk recursion tests to CI, remove old info in vk test --- .circleci/config.yml | 12 ++++++++++++ .../verification_key/verification_key.test.cpp | 1 - 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c4618ddcca..1cf99aa9fa 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -209,6 +209,18 @@ jobs: command: cond_spot_run_tests barretenberg-x86_64-linux-clang-assert 3 stdlib_recursion_tests --gtest_filter=-*turbo* - *save_logs + stdlib-verification-key-tests: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Test" + command: cond_spot_run_tests barretenberg-x86_64-linux-clang-assert 3 stdlib_recursion_tests --gtest_filter=-*verification_key* + - *save_logs + join-split-tests: docker: - image: aztecprotocol/alpine-build-image diff --git a/cpp/src/barretenberg/proof_system/verification_key/verification_key.test.cpp b/cpp/src/barretenberg/proof_system/verification_key/verification_key.test.cpp index 8e6a68ad05..8fbd316f4a 100644 --- a/cpp/src/barretenberg/proof_system/verification_key/verification_key.test.cpp +++ b/cpp/src/barretenberg/proof_system/verification_key/verification_key.test.cpp @@ -24,7 +24,6 @@ verification_key_data rand_vk_data() { vk_data.commitments["test2"] = g1::element::random_element(); vk_data.commitments["foo1"] = g1::element::random_element(); vk_data.commitments["foo2"] = g1::element::random_element(); - info("test0 vk_data commitments: ", vk_data.commitments); return vk_data; } From 10fd0d06590b4df94d7ed15cdce61568e301fa88 Mon Sep 17 00:00:00 2001 From: David Banks <47112877+dbanks12@users.noreply.github.com> Date: Wed, 5 Apr 2023 11:11:16 -0400 Subject: [PATCH 11/11] Remove new CI job in config.yml --- .circleci/config.yml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1cf99aa9fa..c4618ddcca 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -209,18 +209,6 @@ jobs: command: cond_spot_run_tests barretenberg-x86_64-linux-clang-assert 3 stdlib_recursion_tests --gtest_filter=-*turbo* - *save_logs - stdlib-verification-key-tests: - docker: - - image: aztecprotocol/alpine-build-image - resource_class: small - steps: - - *checkout - - *setup_env - - run: - name: "Test" - command: cond_spot_run_tests barretenberg-x86_64-linux-clang-assert 3 stdlib_recursion_tests --gtest_filter=-*verification_key* - - *save_logs - join-split-tests: docker: - image: aztecprotocol/alpine-build-image