Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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