Skip to content

Commit

Permalink
test: more vk tests to compare circuit/native/vk_data (#310)
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

* 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 <[email protected]>
Co-authored-by: Suyash Bagad <[email protected]>

* verification key tests

* inc num_generators_per_hash_index to 128. (#309)

* revert bad changes to eval domain

* add vk recursion tests to CI, remove old info in vk test

* Remove new CI job in config.yml

---------

Co-authored-by: iAmMichaelConnor <[email protected]>
Co-authored-by: Suyash Bagad <[email protected]>
Co-authored-by: Suyash Bagad <[email protected]>
  • Loading branch information
4 people committed Apr 6, 2023
1 parent 22d37b0 commit 946f950
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 107 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,153 +5,152 @@

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

using namespace barretenberg;
using namespace proof_system::plonk;

namespace proof_system::plonk::test_verification_key {

/**
* @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<uint32_t>(proof_system::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 rand_vk_data() {
verification_key_data vk_data;
vk_data.composer_type = static_cast<uint32_t>(proof_system::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();
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));
// 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(0));
EXPECT_NE(vk0_data.compress_native(15), vk1_data.compress_native(15));
// ne hash indices still lead to ne compressions
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<verification_key_data>(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<std::istream&>(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<uint32_t>(proof_system::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<uint32_t>(proof_system::ComposerType::PLOOKUP);
expect_compressions_ne(vk0_data, vk1_data);
}

TEST(verification_key, compression_inequality_different_circuit_size)
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_vk_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)
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)
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)
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)
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)
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);
}
} // namespace proof_system::plonk::test_verification_key
Original file line number Diff line number Diff line change
@@ -1,42 +1,100 @@
#include "verification_key.hpp"
#include <gtest/gtest.h>

#include "barretenberg/ecc/curves/bn254/fr.hpp"
#include "barretenberg/ecc/curves/bn254/g1.hpp"
#include "barretenberg/common/test.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;
#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 <typename Composer> class VerificationKeyFixture : public testing::Test {
public:
using Curve = stdlib::bn254<Composer>;
using RecursVk = plonk::stdlib::recursion::verification_key<Curve>;

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<uint32_t>(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<plonk::StandardComposer, plonk::TurboComposer, plonk::UltraComposer, honk::StandardHonkComposer>;
TYPED_TEST_SUITE(VerificationKeyFixture, ComposerTypes);

verification_key_data rand_vk_data(plonk::ComposerType composer_type)
TYPED_TEST(VerificationKeyFixture, vk_data_vs_recursion_compress_native)
{
verification_key_data key_data;
key_data.composer_type = static_cast<uint32_t>(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;
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<bonk::FileReferenceStringFactory>("../srs_db/ignition");
auto file_verifier = file_crs->get_verifier_crs();

auto native_vk = std::make_shared<bonk::verification_key>(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));
}

TEST(stdlib_verification_key, compress_native_comparison)
TYPED_TEST(VerificationKeyFixture, compress_vs_compress_native)
{
// Compute compression of native verification key (i.e. vk_data)
auto crs = std::make_unique<bonk::FileReferenceStringFactory>("../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<bonk::verification_key>(std::move(vk_data), crs->get_verifier_crs());
auto recursive_vk_compression =
stdlib::recursion::verification_key<stdlib::types::bn254>::compress_native(verification_key, hash_idx);
EXPECT_EQ(native_vk_compression, recursive_vk_compression);
}
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<bonk::FileReferenceStringFactory>("../srs_db/ignition");
auto file_verifier = file_crs->get_verifier_crs();

auto native_vk = std::make_shared<bonk::verification_key>(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)
);
}

0 comments on commit 946f950

Please sign in to comment.