Skip to content
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ grumpkin::fq poseidon_function(const size_t count)
for (size_t i = 0; i < count; ++i) {
inputs[i] = grumpkin::fq::random_element();
}
std::span tmp(inputs);
// hash count many field elements
inputs[0] = crypto::Poseidon2<crypto::Poseidon2Bn254ScalarFieldParams>::hash(tmp);
inputs[0] = crypto::Poseidon2<crypto::Poseidon2Bn254ScalarFieldParams>::hash(inputs);
return inputs[0];
}

Expand Down
39 changes: 38 additions & 1 deletion barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,43 @@ template <typename Params> class Poseidon2 {
using FF = typename Params::FF;

using Sponge = FieldSponge<FF, Params::t - 1, 1, Params::t, Poseidon2Permutation<Params>>;
static FF hash(std::span<FF> input) { return Sponge::hash_fixed_length(input); }
/* @brief Hashes a vector of field elements
*/
static FF hash(const std::vector<FF>& input)
{
auto input_span = input;
return Sponge::hash_fixed_length(input_span);
}
/* @brief Hashes vector of bytes by chunking it into 31 byte field elements and calling hash()
*/
static FF hash_buffer(const std::vector<uint8_t>& input)
{
const size_t num_bytes = input.size();
const size_t bytes_per_element = 31;
size_t num_elements = static_cast<size_t>(num_bytes % bytes_per_element != 0) + (num_bytes / bytes_per_element);

const auto slice = [](const std::vector<uint8_t>& data, const size_t start, const size_t slice_size) {
uint256_t result(0);
for (size_t i = 0; i < slice_size; ++i) {
result = (result << uint256_t(8));
result += uint256_t(data[i + start]);
}
return FF(result);
};

std::vector<FF> converted;
for (size_t i = 0; i < num_elements; ++i) {
size_t bytes_to_slice = 0;
if (i == num_elements - 1) {
bytes_to_slice = num_bytes - (i * bytes_per_element);
} else {
bytes_to_slice = bytes_per_element;
}
FF element = slice(input, i * bytes_per_element, bytes_to_slice);
converted.emplace_back(element);
}

return hash(converted);
}
};
} // namespace crypto
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ TEST(Poseidon2, ConsistencyCheck)
barretenberg::fr c(std::string("0x9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789"));
barretenberg::fr d(std::string("0x9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789"));

std::array<barretenberg::fr, 4> input{ a, b, c, d };
std::vector<barretenberg::fr> input{ a, b, c, d };
auto result = crypto::Poseidon2<crypto::Poseidon2Bn254ScalarFieldParams>::hash(input);

barretenberg::fr expected(std::string("0x150c19ae11b3290c137c7a4d760d9482a6581d731535f560c3601d6a766b0937"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,19 +133,29 @@ template <typename FF> struct ecc_dbl_gate_ {
uint32_t y3;
};

/* External gate data for poseidon2 external round*/
template <typename FF> struct poseidon2_external_gate_ {
uint32_t a;
uint32_t b;
uint32_t c;
uint32_t d;
uint32_t round_idx;
size_t round_idx;
};

/* Internal gate data for poseidon2 internal round*/
template <typename FF> struct poseidon2_internal_gate_ {
uint32_t a;
uint32_t b;
uint32_t c;
uint32_t d;
uint32_t round_idx;
size_t round_idx;
};

/* Last gate for poseidon2, needed because poseidon2 gates compare against the shifted wires. */
template <typename FF> struct poseidon2_end_gate_ {
uint32_t a;
uint32_t b;
uint32_t c;
uint32_t d;
};
} // namespace proof_system
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,8 @@ template <typename FF> void GoblinUltraCircuitBuilder_<FF>::populate_ecc_op_wire
num_ecc_op_gates += 2;
};

/* @brief Poseidon2 external round gate, activates the q_poseidon2_external selector and relation
*/
template <typename FF>
void GoblinUltraCircuitBuilder_<FF>::create_poseidon2_external_gate(const poseidon2_external_gate_<FF>& in)
{
Expand All @@ -270,6 +272,8 @@ void GoblinUltraCircuitBuilder_<FF>::create_poseidon2_external_gate(const poseid
++this->num_gates;
}

/* @brief Poseidon2 internal round gate, activates the q_poseidon2_internal selector and relation
*/
template <typename FF>
void GoblinUltraCircuitBuilder_<FF>::create_poseidon2_internal_gate(const poseidon2_internal_gate_<FF>& in)
{
Expand All @@ -294,6 +298,31 @@ void GoblinUltraCircuitBuilder_<FF>::create_poseidon2_internal_gate(const poseid
++this->num_gates;
}

/* @brief Poseidon2 end round gate, needed because poseidon2 rounds compare with shifted wires
*/
template <typename FF> void GoblinUltraCircuitBuilder_<FF>::create_poseidon2_end_gate(const poseidon2_end_gate_<FF>& in)
{
this->w_l.emplace_back(in.a);
this->w_r.emplace_back(in.b);
this->w_o.emplace_back(in.c);
this->w_4.emplace_back(in.d);
this->q_m.emplace_back(0);
this->q_1.emplace_back(0);
this->q_2.emplace_back(0);
this->q_3.emplace_back(0);
this->q_c.emplace_back(0);
this->q_arith.emplace_back(0);
this->q_4.emplace_back(0);
this->q_sort.emplace_back(0);
this->q_lookup_type.emplace_back(0);
this->q_elliptic.emplace_back(0);
this->q_aux.emplace_back(0);
this->q_busread().emplace_back(0);
this->q_poseidon2_external.emplace_back(0);
this->q_poseidon2_internal.emplace_back(0);
++this->num_gates;
}

template <typename FF>
inline FF GoblinUltraCircuitBuilder_<FF>::compute_poseidon2_external_identity(FF q_poseidon2_external_value,
FF q_1_value,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ template <typename FF> class GoblinUltraCircuitBuilder_ : public UltraCircuitBui
}
void create_poseidon2_external_gate(const poseidon2_external_gate_<FF>& in);
void create_poseidon2_internal_gate(const poseidon2_internal_gate_<FF>& in);
void create_poseidon2_end_gate(const poseidon2_end_gate_<FF>& in);

FF compute_poseidon2_external_identity(FF q_poseidon2_external_value,
FF q_1_value,
Expand Down
3 changes: 2 additions & 1 deletion barretenberg/cpp/src/barretenberg/stdlib/hash/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ add_subdirectory(blake3s)
add_subdirectory(pedersen)
add_subdirectory(sha256)
add_subdirectory(keccak)
add_subdirectory(benchmarks)
add_subdirectory(benchmarks)
add_subdirectory(poseidon2)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
barretenberg_module(stdlib_poseidon2 stdlib_primitives)
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include "barretenberg/stdlib/hash/poseidon2/poseidon2.hpp"
#include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp"
namespace proof_system::plonk::stdlib {

using namespace barretenberg;
using namespace proof_system;

/* Hash a vector of field_t.
*/
template <typename C> field_t<C> poseidon2<C>::hash(C& builder, const std::vector<field_t>& inputs)
{

/* Run the sponge by absorbing all the input and squeezing one output.
* This should just call the sponge variable length hash function
*
*/
auto input{ inputs };
return Sponge::hash_fixed_length(builder, input);
}

/**
* Hash a byte_array.
*
*/
template <typename C> field_t<C> poseidon2<C>::hash_buffer(C& builder, const stdlib::byte_array<C>& input)
{
const size_t num_bytes = input.size();
const size_t bytes_per_element = 31; // 31 bytes in a fr element
size_t num_elements = static_cast<size_t>(num_bytes % bytes_per_element != 0) + (num_bytes / bytes_per_element);

std::vector<field_t> elements;
for (size_t i = 0; i < num_elements; ++i) {
size_t bytes_to_slice = 0;
if (i == num_elements - 1) {
bytes_to_slice = num_bytes - (i * bytes_per_element);
} else {
bytes_to_slice = bytes_per_element;
}
auto element = static_cast<field_t>(input.slice(i * bytes_per_element, bytes_to_slice));
elements.emplace_back(element);
}
for (auto& x : elements) {
std::cout << x << std::endl;
}
return hash(builder, elements);
}
template class poseidon2<proof_system::GoblinUltraCircuitBuilder>;

} // namespace proof_system::plonk::stdlib
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#pragma once
#include "barretenberg/crypto/poseidon2/poseidon2_params.hpp"
#include "barretenberg/stdlib/hash/poseidon2/sponge/sponge.hpp"
#include "barretenberg/stdlib/primitives/byte_array/byte_array.hpp"
#include "barretenberg/stdlib/primitives/field/field.hpp"

#include "../../primitives/circuit_builders/circuit_builders.hpp"

namespace proof_system::plonk::stdlib {

using namespace barretenberg;
/**
* @brief stdlib class that evaluates in-circuit poseidon2 hashes, consistent with behavior in
* crypto::poseidon2
*
* @tparam Builder
*/
template <typename Builder> class poseidon2 {

private:
using field_t = stdlib::field_t<Builder>;
using bool_t = stdlib::bool_t<Builder>;
using Params = crypto::Poseidon2Bn254ScalarFieldParams;
using Permutation = Poseidon2Permutation<Params, Builder>;
using Sponge = FieldSponge<Params::t - 1, 1, Params::t, Permutation, Builder>;

public:
static field_t hash(Builder& builder, const std::vector<field_t>& in);
static field_t hash_buffer(Builder& builder, const stdlib::byte_array<Builder>& input);
};

extern template class poseidon2<proof_system::GoblinUltraCircuitBuilder>;

} // namespace proof_system::plonk::stdlib
Loading