Skip to content

Commit

Permalink
Merge pull request #107 from kroma-network/feat/implement-poseidon-tr…
Browse files Browse the repository at this point in the history
…anscript

feat: implement poseidon transcript
  • Loading branch information
fakedev9999 authored Oct 25, 2023
2 parents 6979e74 + abf97b8 commit 433e827
Show file tree
Hide file tree
Showing 15 changed files with 540 additions and 50 deletions.
1 change: 1 addition & 0 deletions tachyon/base/buffer/string_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class TACHYON_EXPORT StringBuffer : public Buffer {
: Buffer(std::move(other)),
owned_buffer_(std::move(other.owned_buffer_)) {}
StringBuffer& operator=(StringBuffer&& other) {
Buffer::operator=(std::move(other));
owned_buffer_ = std::move(other.owned_buffer_);
return *this;
}
Expand Down
3 changes: 2 additions & 1 deletion tachyon/base/buffer/vector_buffer.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#ifndef TACHYON_BASE_BUFFER_VECTOR_BUFFER_H_
#define TACHYON_BASE_BUFFER_VECTOR_BUFFER_H_

#include <vector>
#include <utility>
#include <vector>

#include "tachyon/base/buffer/buffer.h"

Expand All @@ -17,6 +17,7 @@ class TACHYON_EXPORT VectorBuffer : public Buffer {
: Buffer(std::move(other)),
owned_buffer_(std::move(other.owned_buffer_)) {}
VectorBuffer& operator=(VectorBuffer&& other) {
Buffer::operator=(std::move(other));
owned_buffer_ = std::move(other.owned_buffer_);
return *this;
}
Expand Down
1 change: 1 addition & 0 deletions tachyon/crypto/hashes/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ tachyon_cc_library(
"//tachyon/base/buffer",
"//tachyon/math/base:big_int",
"//tachyon/math/finite_fields:finite_field_traits",
"@com_google_absl//absl/container:inlined_vector",
],
)

Expand Down
24 changes: 24 additions & 0 deletions tachyon/crypto/hashes/prime_field_serializable.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
#ifndef TACHYON_CRYPTO_HASHES_PRIME_FIELD_SERIALIZABLE_H_
#define TACHYON_CRYPTO_HASHES_PRIME_FIELD_SERIALIZABLE_H_

#include <array>
#include <type_traits>
#include <vector>

#include "absl/container/inlined_vector.h"
#include "absl/types/span.h"

#include "tachyon/math/base/big_int.h"
Expand Down Expand Up @@ -69,6 +71,28 @@ class PrimeFieldSerializable<std::vector<T>> {
}
};

template <typename T, size_t N>
class PrimeFieldSerializable<absl::InlinedVector<T, N>> {
public:
template <typename PrimeFieldTy>
constexpr static bool ToPrimeField(const absl::InlinedVector<T, N>& values,
std::vector<PrimeFieldTy>* fields) {
return PrimeFieldSerializable<T>::BatchToPrimeField(
absl::MakeConstSpan(values), fields);
}
};

template <typename T, size_t N>
class PrimeFieldSerializable<std::array<T, N>> {
public:
template <typename PrimeFieldTy>
constexpr static bool ToPrimeField(const std::array<T, N>& values,
std::vector<PrimeFieldTy>* fields) {
return PrimeFieldSerializable<T>::BatchToPrimeField(
absl::MakeConstSpan(values), fields);
}
};

template <typename T, typename PrimeFieldTy>
constexpr bool SerializeToFieldElements(const T& value,
std::vector<PrimeFieldTy>* fields) {
Expand Down
30 changes: 30 additions & 0 deletions tachyon/crypto/hashes/prime_field_serializable_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,36 @@ TEST_F(PrimeFieldSerializableTest, SerializeSingleValueToField) {
EXPECT_EQ(fields, expected);
}

TEST_F(PrimeFieldSerializableTest, SerializeVectorToField) {
std::vector<int64_t> values = {1, 2, 3, 4, 5};
std::vector<math::GF7> fields;
ASSERT_TRUE(SerializeToFieldElements(values, &fields));
std::vector<math::GF7> expected = {
math::GF7(1), math::GF7(2), math::GF7(3), math::GF7(4), math::GF7(5),
};
EXPECT_EQ(fields, expected);
}

TEST_F(PrimeFieldSerializableTest, SerializeArrayToField) {
std::array<int64_t, 5> values = {1, 2, 3, 4, 5};
std::vector<math::GF7> fields;
ASSERT_TRUE(SerializeToFieldElements(values, &fields));
std::vector<math::GF7> expected = {
math::GF7(1), math::GF7(2), math::GF7(3), math::GF7(4), math::GF7(5),
};
EXPECT_EQ(fields, expected);
}

TEST_F(PrimeFieldSerializableTest, SerializeInlinedVectorToField) {
absl::InlinedVector<int64_t, 5> values = {1, 2, 3, 4, 5};
std::vector<math::GF7> fields;
ASSERT_TRUE(SerializeToFieldElements(values, &fields));
std::vector<math::GF7> expected = {
math::GF7(1), math::GF7(2), math::GF7(3), math::GF7(4), math::GF7(5),
};
EXPECT_EQ(fields, expected);
}

TEST_F(PrimeFieldSerializableTest, SerializeBatchToField) {
std::vector<int64_t> values = {1, 2, 3, 4, 5};
std::vector<math::GF7> fields;
Expand Down
10 changes: 10 additions & 0 deletions tachyon/crypto/hashes/sponge/poseidon/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ tachyon_cc_library(
],
)

tachyon_cc_library(
name = "halo2_poseidon",
hdrs = ["halo2_poseidon.h"],
deps = [
":poseidon",
"@local_config_gmp//:gmp",
],
)

tachyon_cc_library(
name = "poseidon_config",
hdrs = ["poseidon_config.h"],
Expand Down Expand Up @@ -43,5 +52,6 @@ tachyon_cc_unittest(
":poseidon",
":poseidon_config",
"//tachyon/math/elliptic_curves/bls/bls12_381:fr",
"//tachyon/math/elliptic_curves/bn/bn254:fr",
],
)
59 changes: 59 additions & 0 deletions tachyon/crypto/hashes/sponge/poseidon/halo2_poseidon.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright 2020-2022 The Electric Coin Company
// Copyright 2022 The Halo2 developers
// Use of this source code is governed by a MIT/Apache-2.0 style license that
// can be found in the LICENSE-MIT.halo2 and the LICENCE-APACHE.halo2
// file.

#ifndef TACHYON_CRYPTO_HASHES_SPONGE_POSEIDON_HALO2_POSEIDON_H_
#define TACHYON_CRYPTO_HASHES_SPONGE_POSEIDON_HALO2_POSEIDON_H_

#include <vector>

#include "third_party/gmp/include/gmpxx.h"

#include "tachyon/crypto/hashes/sponge/poseidon/poseidon.h"

namespace tachyon::crypto {

template <typename PrimeFieldTy>
struct Halo2PoseidonSponge : public PoseidonSponge<PrimeFieldTy> {
using F = PrimeFieldTy;

Halo2PoseidonSponge() = default;
explicit Halo2PoseidonSponge(const PoseidonConfig<F>& config)
: PoseidonSponge<PrimeFieldTy>(config) {
this->state.elements[0] = F::FromMpzClass(mpz_class(1) << 64);
}

// FieldBasedCryptographicSponge methods
std::vector<F> SqueezeNativeFieldElements(size_t num_elements) {
std::vector<F> ret = base::CreateVector(num_elements, F::Zero());
size_t squeeze_index = this->state.mode.next_index;
if (squeeze_index == this->config.rate) {
squeeze_index = 0;
}
this->state[squeeze_index + 1] = F::One();
switch (this->state.mode.type) {
case DuplexSpongeMode::Type::kAbsorbing: {
this->Permute();
this->SqueezeInternal(0, &ret);
return ret;
}
case DuplexSpongeMode::Type::kSqueezing: {
size_t squeeze_index = this->state.mode.next_index;
if (squeeze_index == this->config.rate) {
this->Permute();
squeeze_index = 0;
}
this->SqueezeInternal(squeeze_index, &ret);
return ret;
}
}
NOTREACHED();
return {};
}
};

} // namespace tachyon::crypto

#endif // TACHYON_CRYPTO_HASHES_SPONGE_POSEIDON_HALO2_POSEIDON_H_
3 changes: 3 additions & 0 deletions tachyon/crypto/hashes/sponge/poseidon/poseidon.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ struct PoseidonSponge
// Sponge State
State state;

PoseidonSponge() = default;
explicit PoseidonSponge(const PoseidonConfig<F>& config)
: config(config), state(config.rate + config.capacity) {}
PoseidonSponge(const PoseidonConfig<F>& config, const State& state)
Expand Down Expand Up @@ -241,6 +242,8 @@ struct PoseidonSponge
}

// FieldBasedCryptographicSponge methods
// NOTE(TomTaehoonKim): If you ever update this, please update
// |Halo2PoseidonSponge| for consistency.
std::vector<F> SqueezeNativeFieldElements(size_t num_elements) {
std::vector<F> ret =
base::CreateVector(num_elements, []() { return F::Zero(); });
Expand Down
79 changes: 42 additions & 37 deletions tachyon/crypto/hashes/sponge/poseidon/poseidon_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ namespace tachyon::crypto {
template <typename PrimeFieldTy>
struct PoseidonConfig;

// An entry in the default Poseidon config
struct TACHYON_EXPORT PoseidonDefaultConfigEntry {
// An entry in the Poseidon config
struct TACHYON_EXPORT PoseidonConfigEntry {
// The rate (in terms of number of field elements).
size_t rate;

Expand All @@ -37,12 +37,9 @@ struct TACHYON_EXPORT PoseidonDefaultConfigEntry {
// https://extgit.iaik.tugraz.at/krypto/hadeshash/-/blob/master/code/generate_parameters_grain.sage
size_t skip_matrices;

constexpr PoseidonDefaultConfigEntry()
: PoseidonDefaultConfigEntry(0, 0, 0, 0, 0) {}
constexpr PoseidonDefaultConfigEntry(size_t rate, uint64_t alpha,
size_t full_rounds,
size_t partial_rounds,
size_t skip_matrices)
constexpr PoseidonConfigEntry() : PoseidonConfigEntry(0, 0, 0, 0, 0) {}
constexpr PoseidonConfigEntry(size_t rate, uint64_t alpha, size_t full_rounds,
size_t partial_rounds, size_t skip_matrices)
: rate(rate),
alpha(alpha),
full_rounds(full_rounds),
Expand All @@ -63,32 +60,29 @@ struct TACHYON_EXPORT PoseidonDefaultConfigEntry {
PoseidonConfig<PrimeFieldTy> ToPoseidonConfig() const;
};

// An array of the config optimized for constraints
// An array of the default config optimized for constraints
// (rate, alpha, full_rounds, partial_rounds, skip_matrices)
// for rate = 2, 3, 4, 5, 6, 7, 8
// Here, |skip_matrices| denotes how many matrices to skip before finding one
// that satisfy all the requirements.
constexpr const PoseidonDefaultConfigEntry kOptimizedConstraintsParams[] = {
PoseidonDefaultConfigEntry(2, 17, 8, 31, 0),
PoseidonDefaultConfigEntry(3, 5, 8, 56, 0),
PoseidonDefaultConfigEntry(4, 5, 8, 56, 0),
PoseidonDefaultConfigEntry(5, 5, 8, 57, 0),
PoseidonDefaultConfigEntry(6, 5, 8, 57, 0),
PoseidonDefaultConfigEntry(7, 5, 8, 57, 0),
PoseidonDefaultConfigEntry(8, 5, 8, 57, 0),
constexpr const PoseidonConfigEntry kOptimizedConstraintsDefaultParams[] = {
PoseidonConfigEntry(2, 17, 8, 31, 0), PoseidonConfigEntry(3, 5, 8, 56, 0),
PoseidonConfigEntry(4, 5, 8, 56, 0), PoseidonConfigEntry(5, 5, 8, 57, 0),
PoseidonConfigEntry(6, 5, 8, 57, 0), PoseidonConfigEntry(7, 5, 8, 57, 0),
PoseidonConfigEntry(8, 5, 8, 57, 0),
};

// An array of the config optimized for weights
// An array of the default config optimized for weights
// (rate, alpha, full_rounds, partial_rounds, skip_matrices)
// for rate = 2, 3, 4, 5, 6, 7, 8
constexpr const PoseidonDefaultConfigEntry kOptimizedWeightsParams[] = {
PoseidonDefaultConfigEntry(2, 257, 8, 13, 0),
PoseidonDefaultConfigEntry(3, 257, 8, 13, 0),
PoseidonDefaultConfigEntry(4, 257, 8, 13, 0),
PoseidonDefaultConfigEntry(5, 257, 8, 13, 0),
PoseidonDefaultConfigEntry(6, 257, 8, 13, 0),
PoseidonDefaultConfigEntry(7, 257, 8, 13, 0),
PoseidonDefaultConfigEntry(8, 257, 8, 13, 0),
constexpr const PoseidonConfigEntry kOptimizedWeightsDefaultParams[] = {
PoseidonConfigEntry(2, 257, 8, 13, 0),
PoseidonConfigEntry(3, 257, 8, 13, 0),
PoseidonConfigEntry(4, 257, 8, 13, 0),
PoseidonConfigEntry(5, 257, 8, 13, 0),
PoseidonConfigEntry(6, 257, 8, 13, 0),
PoseidonConfigEntry(7, 257, 8, 13, 0),
PoseidonConfigEntry(8, 257, 8, 13, 0),
};

// ARK(AddRoundKey) is a matrix that contains an ARC(AddRoundConstant) array in
Expand Down Expand Up @@ -157,16 +151,15 @@ struct PoseidonConfig {
size_t capacity = 0;

static PoseidonConfig CreateDefault(size_t rate, bool optimized_for_weights) {
absl::Span<const PoseidonDefaultConfigEntry> param_set =
absl::Span<const PoseidonConfigEntry> param_set =
optimized_for_weights
? absl::MakeConstSpan(kOptimizedWeightsParams)
: absl::MakeConstSpan(kOptimizedConstraintsParams);

auto it =
base::ranges::find_if(param_set.begin(), param_set.end(),
[rate](const PoseidonDefaultConfigEntry& param) {
return param.rate == rate;
});
? absl::MakeConstSpan(kOptimizedWeightsDefaultParams)
: absl::MakeConstSpan(kOptimizedConstraintsDefaultParams);

auto it = base::ranges::find_if(param_set.begin(), param_set.end(),
[rate](const PoseidonConfigEntry& param) {
return param.rate == rate;
});
CHECK_NE(it, param_set.end());
PoseidonConfig ret = it->template ToPoseidonConfig<PrimeFieldTy>();
FindPoseidonArkAndMds<PrimeFieldTy>(
Expand All @@ -175,6 +168,19 @@ struct PoseidonConfig {
return ret;
}

constexpr static PoseidonConfig CreateCustom(size_t rate, uint64_t alpha,
size_t full_rounds,
size_t partial_rounds,
size_t skip_matrices) {
PoseidonConfigEntry config_entry(rate, alpha, full_rounds, partial_rounds,
skip_matrices);
PoseidonConfig ret = config_entry.ToPoseidonConfig<PrimeFieldTy>();
FindPoseidonArkAndMds<PrimeFieldTy>(
config_entry.ToPoseidonGrainLFSRConfig<PrimeFieldTy>(), skip_matrices,
&ret.ark, &ret.mds);
return ret;
}

bool IsValid() const {
return static_cast<size_t>(ark.rows()) == full_rounds + partial_rounds &&
static_cast<size_t>(ark.cols()) == rate + capacity &&
Expand All @@ -184,8 +190,7 @@ struct PoseidonConfig {
};

template <typename PrimeFieldTy>
PoseidonConfig<PrimeFieldTy> PoseidonDefaultConfigEntry::ToPoseidonConfig()
const {
PoseidonConfig<PrimeFieldTy> PoseidonConfigEntry::ToPoseidonConfig() const {
PoseidonConfig<PrimeFieldTy> config;
config.full_rounds = full_rounds;
config.partial_rounds = partial_rounds;
Expand Down
Loading

0 comments on commit 433e827

Please sign in to comment.