Skip to content

Commit

Permalink
feat: added poseidon2 hash function to barretenberg/crypto (#3118)
Browse files Browse the repository at this point in the history
Preliminary work to add Poseidon2 hash function as a standard library
primitive (https://eprint.iacr.org/2023/323.pdf)

Adds Poseidon2 to crypto module, following paper + specification at
https://github.com/C2SP/C2SP/blob/792c1254124f625d459bfe34417e8f6bdd02eb28/poseidon-sponge.md

---------

Co-authored-by: lucasxia01 <[email protected]>
  • Loading branch information
2 people authored and Maddiaa0 committed Nov 28, 2023
1 parent 9b7f47c commit 1541283
Show file tree
Hide file tree
Showing 14 changed files with 1,730 additions and 6 deletions.
1 change: 1 addition & 0 deletions barretenberg/cpp/src/barretenberg/crypto/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ add_subdirectory(schnorr)
add_subdirectory(sha256)
add_subdirectory(ecdsa)
add_subdirectory(aes128)
add_subdirectory(poseidon2)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
barretenberg_module(crypto_poseidon2 ecc numeric)
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include "./poseidon2.hpp"
#include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp"
#include <benchmark/benchmark.h>

using namespace benchmark;

grumpkin::fq poseidon_function(const size_t count)
{
std::vector<grumpkin::fq> inputs(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);
return inputs[0];
}

void native_poseidon2_commitment_bench(State& state) noexcept
{
for (auto _ : state) {
const size_t count = (static_cast<size_t>(state.range(0)));
(poseidon_function(count));
}
}
BENCHMARK(native_poseidon2_commitment_bench)->Arg(10)->Arg(1000)->Arg(10000);

BENCHMARK_MAIN();
// } // namespace crypto
16 changes: 16 additions & 0 deletions barretenberg/cpp/src/barretenberg/crypto/poseidon2/poseidon2.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

#include "poseidon2_params.hpp"
#include "poseidon2_permutation.hpp"
#include "sponge/sponge.hpp"

namespace crypto {

template <typename Params> class Poseidon2 {
public:
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); }
};
} // namespace crypto
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include "poseidon2.hpp"
#include "barretenberg/crypto/poseidon2/poseidon2_params.hpp"
#include "barretenberg/ecc/curves/bn254/bn254.hpp"
#include <gtest/gtest.h>

using namespace barretenberg;

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

namespace poseidon2_tests {
TEST(Poseidon2, BasicTests)
{

barretenberg::fr a = barretenberg::fr::random_element(&engine);
barretenberg::fr b = barretenberg::fr::random_element(&engine);
barretenberg::fr c = barretenberg::fr::random_element(&engine);
barretenberg::fr d = barretenberg::fr::random_element(&engine);

std::vector<barretenberg::fr> input1{ a, b, c, d };
std::vector<barretenberg::fr> input2{ d, c, b, a };

auto r0 = crypto::Poseidon2<crypto::Poseidon2Bn254ScalarFieldParams>::hash(input1);
auto r1 = crypto::Poseidon2<crypto::Poseidon2Bn254ScalarFieldParams>::hash(input1);
auto r2 = crypto::Poseidon2<crypto::Poseidon2Bn254ScalarFieldParams>::hash(input2);

EXPECT_EQ(r0, r1);
EXPECT_NE(r0, r2);
}

// N.B. these hardcoded values were extracted from the algorithm being tested. These are NOT independent test vectors!
// TODO(@zac-williamson #3132): find independent test vectors we can compare against! (very hard to find given
// flexibility of Poseidon's parametrisation)
TEST(Poseidon2, ConsistencyCheck)
{
barretenberg::fr a(std::string("9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789"));
barretenberg::fr b(std::string("9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789"));
barretenberg::fr c(std::string("0x9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789"));
barretenberg::fr d(std::string("0x9a807b615c4d3e2fa0b1c2d3e4f56789fedcba9876543210abcdef0123456789"));

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

barretenberg::fr expected(std::string("0x150c19ae11b3290c137c7a4d760d9482a6581d731535f560c3601d6a766b0937"));

EXPECT_EQ(result, expected);
}
} // namespace poseidon2_tests
Loading

0 comments on commit 1541283

Please sign in to comment.