Skip to content

Commit

Permalink
array_push for Generic Type (#291)
Browse files Browse the repository at this point in the history
* test wip

* fix tests.

* Make `compress_native` static in recursive vk.

* Add comments.
  • Loading branch information
suyash67 authored Mar 29, 2023
1 parent 6353f24 commit b5da2f8
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 2 deletions.
2 changes: 2 additions & 0 deletions cpp/src/barretenberg/stdlib/primitives/address/address.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ template <typename Composer> class address_t {

bool_t<Composer> operator==(const address_t& other) const { return this->to_field() == other.to_field(); }

bool_t<Composer> operator!=(const address_t& other) const { return this->to_field() != other.to_field(); }

field_t<Composer> to_field() const { return address_; }

fr get_value() const { return address_.get_value(); };
Expand Down
24 changes: 24 additions & 0 deletions cpp/src/barretenberg/stdlib/primitives/field/array.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ void array_push(std::array<field_t<Composer>, SIZE>& arr, field_t<Composer> cons
already_pushed.assert_equal(true, "array_push cannot push to a full array");
};

/**
* Note: this assumes `0` always means 'not used', so be careful. If you actually want `0` to be counted, you'll need
* something else.
*/
template <typename Composer, size_t SIZE>
inline size_t array_push(std::array<std::optional<field_t<Composer>>, SIZE>& arr, field_t<Composer> const& value)
{
Expand All @@ -73,6 +77,10 @@ inline size_t array_push(std::array<std::optional<field_t<Composer>>, SIZE>& arr
throw_or_abort("array_push cannot push to a full array");
};

/**
* Note: this assumes `0` always means 'not used', so be careful. If you actually want `0` to be counted, you'll need
* something else.
*/
template <typename T, size_t SIZE>
inline size_t array_push(std::array<std::shared_ptr<T>, SIZE>& arr, std::shared_ptr<T> const& value)
{
Expand All @@ -85,6 +93,22 @@ inline size_t array_push(std::array<std::shared_ptr<T>, SIZE>& arr, std::shared_
throw_or_abort("array_push cannot push to a full array");
};

/**
* Note: this assumes `0` always means 'not used', so be careful. If you actually want `0` to be counted, you'll need
* something else.
*/
template <typename Composer, typename T, size_t SIZE> inline void array_push(std::array<T, SIZE>& arr, T const& value)
{
bool_t<Composer> already_pushed = false;
for (size_t i = 0; i < arr.size(); ++i) {
bool_t<Composer> is_zero = arr[i].is_empty();
arr[i].conditional_select(!already_pushed && is_zero, value);

already_pushed |= is_zero;
}
already_pushed.assert_equal(true, "array_push cannot push to a full array");
};

/**
* Note: this assumes `0` always means 'not used', so be careful. If you actually want `0` to be counted, you'll need
* something else.
Expand Down
84 changes: 84 additions & 0 deletions cpp/src/barretenberg/stdlib/primitives/field/field.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "array.hpp"
#include "barretenberg/plonk/proof_system/constants.hpp"
#include <gtest/gtest.h>
#include <utility>
#include "barretenberg/honk/composer/standard_honk_composer.hpp"
#include "barretenberg/plonk/composer/standard_composer.hpp"
#include "barretenberg/plonk/composer/ultra_composer.hpp"
Expand Down Expand Up @@ -1235,6 +1236,81 @@ template <typename Composer> class stdlib_field : public testing::Test {
EXPECT_EQ(composer.failed(), true);
EXPECT_EQ(composer.err(), "push_array_to_array target array capacity exceeded");
}

class MockClass {
public:
MockClass()
: m_a(field_ct(0))
, m_b(field_ct(0))
{}
MockClass(field_ct a, field_ct b)
: m_a(a)
, m_b(b)
{}

bool_ct is_empty() const { return m_a == 0 && m_b == 0; }

std::pair<field_ct, field_ct> get_values() { return std::make_pair(m_a, m_b); }

void conditional_select(bool_ct const& condition, MockClass const& other)
{
m_a = field_ct::conditional_assign(condition, other.m_a, m_a);
m_b = field_ct::conditional_assign(condition, other.m_b, m_b);
}

private:
field_ct m_a;
field_ct m_b;
};

void test_array_push_generic()
{
Composer composer = Composer();

constexpr size_t SIZE = 5;
std::array<MockClass, SIZE> arr{};

// Push values into the array
plonk::stdlib::array_push<Composer>(arr, MockClass(witness_ct(&composer, 1), witness_ct(&composer, 10)));
plonk::stdlib::array_push<Composer>(arr, MockClass(witness_ct(&composer, 2), witness_ct(&composer, 20)));
plonk::stdlib::array_push<Composer>(arr, MockClass(witness_ct(&composer, 3), witness_ct(&composer, 30)));

// Check the values in the array
EXPECT_EQ(arr[0].get_values().first.get_value(), 1);
EXPECT_EQ(arr[0].get_values().second.get_value(), 10);
EXPECT_EQ(arr[1].get_values().first.get_value(), 2);
EXPECT_EQ(arr[1].get_values().second.get_value(), 20);
EXPECT_EQ(arr[2].get_values().first.get_value(), 3);
EXPECT_EQ(arr[2].get_values().second.get_value(), 30);

auto prover = composer.create_prover();
auto verifier = composer.create_verifier();
auto proof = prover.construct_proof();
info("composer gates = ", composer.get_num_gates());
bool proof_result = verifier.verify_proof(proof);
EXPECT_EQ(proof_result, true);
}

void test_array_push_generic_full()
{
Composer composer = Composer();

constexpr size_t SIZE = 5;
std::array<MockClass, SIZE> arr{};

// Push values into the array
plonk::stdlib::array_push<Composer>(arr, MockClass(witness_ct(&composer, 1), witness_ct(&composer, 10)));
plonk::stdlib::array_push<Composer>(arr, MockClass(witness_ct(&composer, 2), witness_ct(&composer, 20)));
plonk::stdlib::array_push<Composer>(arr, MockClass(witness_ct(&composer, 3), witness_ct(&composer, 30)));
plonk::stdlib::array_push<Composer>(arr, MockClass(witness_ct(&composer, 4), witness_ct(&composer, 40)));
plonk::stdlib::array_push<Composer>(arr, MockClass(witness_ct(&composer, 5), witness_ct(&composer, 50)));

// Try to push into a full array
plonk::stdlib::array_push<Composer>(arr, MockClass(witness_ct(&composer, 6), witness_ct(&composer, 60)));

EXPECT_EQ(composer.failed(), true);
EXPECT_EQ(composer.err(), "array_push cannot push to a full array");
}
};

typedef testing::Types<plonk::UltraComposer, plonk::TurboComposer, plonk::StandardComposer, honk::StandardHonkComposer>
Expand Down Expand Up @@ -1382,6 +1458,14 @@ TYPED_TEST(stdlib_field, test_array_push_optional)
{
TestFixture::test_array_push_optional();
}
TYPED_TEST(stdlib_field, test_array_push_generic)
{
TestFixture::test_array_push_generic();
}
TYPED_TEST(stdlib_field, test_array_push_generic_full)
{
TestFixture::test_array_push_generic_full();
}
TYPED_TEST(stdlib_field, test_array_push_array_to_array)
{
TestFixture::test_push_array_to_array();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ template <typename Curve> struct verification_key {
}
}

private:
public:
field_t<Composer> compress()
{
field_t<Composer> compressed_domain = domain.compress();
Expand Down Expand Up @@ -215,7 +215,7 @@ template <typename Curve> struct verification_key {
return compressed_key;
}

barretenberg::fr compress_native(const std::shared_ptr<bonk::verification_key>& key)
static barretenberg::fr compress_native(const std::shared_ptr<bonk::verification_key>& key)
{
barretenberg::fr compressed_domain = evaluation_domain<Composer>::compress_native(key->domain);

Expand Down

0 comments on commit b5da2f8

Please sign in to comment.