Skip to content

Commit

Permalink
Merge pull request kroma-network#419 from kroma-network/feat/enable-c…
Browse files Browse the repository at this point in the history
…ircom-proof-generation-without-compilation

feat(circom): enable circom proof generation without compilation
  • Loading branch information
chokobole authored May 22, 2024
2 parents 3439208 + 09f238c commit 08f6253
Show file tree
Hide file tree
Showing 60 changed files with 1,544 additions and 844 deletions.
8 changes: 8 additions & 0 deletions tachyon/base/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ tachyon_cc_library(
hdrs = ["array_to_vector.h"],
)

tachyon_cc_library(
name = "auto_reset",
hdrs = ["auto_reset.h"],
deps = ["//tachyon/base:logging"],
)

tachyon_cc_library(
name = "bit_cast",
hdrs = ["bit_cast.h"],
Expand Down Expand Up @@ -144,6 +150,7 @@ tachyon_cc_library(
tachyon_cc_unittest(
name = "base_unittests",
srcs = [
"auto_reset_unittest.cc",
"bit_cast_unittest.cc",
"bits_unittest.cc",
"cxx20_is_constant_evaluated_unittest.cc",
Expand All @@ -156,6 +163,7 @@ tachyon_cc_unittest(
"scoped_generic_unittest.cc",
],
deps = [
":auto_reset",
":bit_cast",
":bits",
":cxx20_is_constant_evaluated",
Expand Down
69 changes: 69 additions & 0 deletions tachyon/base/auto_reset.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright 2011 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef TACHYON_BASE_AUTO_RESET_H_
#define TACHYON_BASE_AUTO_RESET_H_

#include <utility>

#include "tachyon/base/logging.h"
// #include "base/memory/raw_ptr_exclusion.h"

// base::AutoReset<> is useful for setting a variable to a new value only within
// a particular scope. An base::AutoReset<> object resets a variable to its
// original value upon destruction, making it an alternative to writing
// "var = false;" or "var = old_val;" at all of a block's exit points.
//
// This should be obvious, but note that an base::AutoReset<> instance should
// have a shorter lifetime than its scoped_variable, to prevent invalid memory
// writes when the base::AutoReset<> object is destroyed.

namespace tachyon::base {

template <typename T>
class [[maybe_unused, nodiscard]] AutoReset {
public:
template <typename U>
AutoReset(T* scoped_variable, U&& new_value)
: scoped_variable_(scoped_variable),
original_value_(
std::exchange(*scoped_variable_, std::forward<U>(new_value))) {}

// A constructor that's useful for asserting the old value of
// `scoped_variable`, especially when it's inconvenient to check this before
// constructing the AutoReset object (e.g. in a class member initializer
// list).
template <typename U>
AutoReset(T* scoped_variable, U&& new_value, const T& expected_old_value)
: AutoReset(scoped_variable, new_value) {
DCHECK_EQ(original_value_, expected_old_value);
}

AutoReset(AutoReset&& other)
: scoped_variable_(std::exchange(other.scoped_variable_, nullptr)),
original_value_(std::move(other.original_value_)) {}

AutoReset& operator=(AutoReset&& rhs) {
scoped_variable_ = std::exchange(rhs.scoped_variable_, nullptr);
original_value_ = std::move(rhs.original_value_);
return *this;
}

~AutoReset() {
if (scoped_variable_) *scoped_variable_ = std::move(original_value_);
}

private:
// `scoped_variable_` is not a raw_ptr<T> for performance reasons: Large
// number of non-PartitionAlloc pointees + AutoReset is typically short-lived
// (e.g. allocated on the stack).
// RAW_PTR_EXCLUSION T* scoped_variable_;
T* scoped_variable_;

T original_value_;
};

} // namespace tachyon::base

#endif // TACHYON_BASE_AUTO_RESET_H_
33 changes: 33 additions & 0 deletions tachyon/base/auto_reset_unittest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "tachyon/base/auto_reset.h"

#include <utility>

#include "gtest/gtest.h"

namespace tachyon::base {

TEST(AutoReset, Move) {
int value = 10;
{
AutoReset<int> resetter1{&value, 20};
EXPECT_EQ(20, value);
{
value = 15;
AutoReset<int> resetter2 = std::move(resetter1);
// Moving to a new resetter does not change the value;
EXPECT_EQ(15, value);
}
// Moved-to `resetter2` is out of scoped, and resets to the original value
// that was in moved-from `resetter1`.
EXPECT_EQ(10, value);
value = 105;
}
// Moved-from `resetter1` does not reset to anything.
EXPECT_EQ(105, value);
}

} // namespace tachyon::base
1 change: 0 additions & 1 deletion tachyon/crypto/transcripts/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ tachyon_cc_library(
deps = [
":transcript_traits",
"//tachyon/base/buffer:vector_buffer",
"//tachyon/math/base:big_int",
],
)

Expand Down
2 changes: 2 additions & 0 deletions tachyon/math/elliptic_curves/bls12/generator/curve.h.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ namespace %{namespace} {
template <typename Fq, typename Fq2, typename Fq6, typename Fq12, typename _G1Curve, typename _G2Curve>
class %{class}Config {
public:
constexpr static const char* kName = "%{namespace}::%{class}";
constexpr static BigInt<%{x_size}> kX = BigInt<%{x_size}>({
%{x}
});
Expand Down
2 changes: 2 additions & 0 deletions tachyon/math/elliptic_curves/bn/generator/curve.h.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ namespace %{namespace} {
template <typename Fq, typename Fq2, typename Fq6, typename Fq12, typename _G1Curve, typename _G2Curve>
class %{class}Config {
public:
constexpr static const char* kName = "%{namespace}::%{class}";
constexpr static BigInt<%{x_size}> kX = BigInt<%{x_size}>({
%{x}
});
Expand Down
13 changes: 7 additions & 6 deletions tachyon/math/elliptic_curves/short_weierstrass/affine_point.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,22 +235,22 @@ class Copyable<math::AffinePoint<
std::enable_if_t<Curve::kType == math::CurveType::kShortWeierstrass>>> {
public:
static bool WriteTo(const math::AffinePoint<Curve>& point, Buffer* buffer) {
return buffer->WriteMany(point.x(), point.y(), point.infinity());
return buffer->WriteMany(point.x(), point.y());
}

static bool ReadFrom(const ReadOnlyBuffer& buffer,
math::AffinePoint<Curve>* point) {
using BaseField = typename math::AffinePoint<Curve>::BaseField;
BaseField x, y;
bool infinity;
if (!buffer.ReadMany(&x, &y, &infinity)) return false;
if (!buffer.ReadMany(&x, &y)) return false;

*point = math::AffinePoint<Curve>(std::move(x), std::move(y), infinity);
*point = math::AffinePoint<Curve>(std::move(x), std::move(y),
x.IsZero() && y.IsZero());
return true;
}

static size_t EstimateSize(const math::AffinePoint<Curve>& point) {
return base::EstimateSize(point.x(), point.y(), point.infinity());
return base::EstimateSize(point.x(), point.y());
}
};

Expand All @@ -276,7 +276,8 @@ class RapidJsonValueConverter<math::AffinePoint<
Field y;
if (!ParseJsonElement(json_value, "x", &x, error)) return false;
if (!ParseJsonElement(json_value, "y", &y, error)) return false;
*value = math::AffinePoint<Curve>(std::move(x), std::move(y));
*value = math::AffinePoint<Curve>(std::move(x), std::move(y),
x.IsZero() && y.IsZero());
return true;
}
};
Expand Down
1 change: 1 addition & 0 deletions tachyon/math/finite_fields/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ tachyon_cc_unittest(
":modulus",
":prime_field_base",
":prime_field_gpu_debug",
"//tachyon/base:auto_reset",
"//tachyon/base:bits",
"//tachyon/base/buffer:vector_buffer",
"//tachyon/build:build_config",
Expand Down
69 changes: 62 additions & 7 deletions tachyon/math/finite_fields/prime_field_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,15 +161,31 @@ template <typename T>
class Copyable<
T, std::enable_if_t<std::is_base_of_v<math::PrimeFieldBase<T>, T>>> {
public:
static bool s_allow_value_greater_than_or_equal_to_modulus;
static bool s_is_in_montgomery;

static bool WriteTo(const T& prime_field, Buffer* buffer) {
return buffer->Write(prime_field.ToBigInt());
if (s_is_in_montgomery) {
return buffer->Write(prime_field.ToMontgomery());
} else {
return buffer->Write(prime_field.ToBigInt());
}
}

static bool ReadFrom(const ReadOnlyBuffer& buffer, T* prime_field) {
using BigInt = typename T::BigIntTy;
BigInt v;
if (!buffer.Read(&v)) return false;
*prime_field = T::FromBigInt(v);
if (s_allow_value_greater_than_or_equal_to_modulus) {
if (v >= T::Config::kModulus) {
v = v.Mod(T::Config::kModulus);
}
}
if (s_is_in_montgomery) {
*prime_field = T::FromMontgomery(v);
} else {
*prime_field = T::FromBigInt(v);
}
return true;
}

Expand All @@ -179,27 +195,66 @@ class Copyable<
}
};

// static
template <typename T>
bool Copyable<T,
std::enable_if_t<std::is_base_of_v<math::PrimeFieldBase<T>, T>>>::
s_allow_value_greater_than_or_equal_to_modulus = false;

// static
template <typename T>
bool Copyable<T, std::enable_if_t<std::is_base_of_v<math::PrimeFieldBase<T>,
T>>>::s_is_in_montgomery =
false;

template <typename T>
class RapidJsonValueConverter<
T, std::enable_if_t<std::is_base_of_v<math::PrimeFieldBase<T>, T>>> {
public:
static bool s_allow_value_greater_than_or_equal_to_modulus;
static bool s_is_in_montgomery;

template <typename Allocator>
static rapidjson::Value From(const T& value, Allocator& allocator) {
rapidjson::Value object(rapidjson::kObjectType);
AddJsonElement(object, "value", value.ToBigInt(), allocator);
if (s_is_in_montgomery) {
AddJsonElement(object, "value", value.ToMontgomery(), allocator);
} else {
AddJsonElement(object, "value", value.ToBigInt(), allocator);
}
return object;
}

static bool To(const rapidjson::Value& json_value, std::string_view key,
T* value, std::string* error) {
typename T::BigIntTy value_big_int;
if (!ParseJsonElement(json_value, "value", &value_big_int, error))
return false;
*value = T(std::move(value_big_int));
typename T::BigIntTy v;
if (!ParseJsonElement(json_value, "value", &v, error)) return false;
if (s_allow_value_greater_than_or_equal_to_modulus) {
if (v >= T::Config::kModulus) {
v = v.Mod(T::Config::kModulus);
}
}
if (s_is_in_montgomery) {
*value = T::FromMontgomery(v);
} else {
*value = T::FromBigInt(v);
}
return true;
}
};

// static
template <typename T>
bool RapidJsonValueConverter<
T, std::enable_if_t<std::is_base_of_v<math::PrimeFieldBase<T>, T>>>::
s_allow_value_greater_than_or_equal_to_modulus = false;

// static
template <typename T>
bool RapidJsonValueConverter<
T, std::enable_if_t<std::is_base_of_v<math::PrimeFieldBase<T>, T>>>::
s_is_in_montgomery = false;

} // namespace base
} // namespace tachyon

Expand Down
26 changes: 24 additions & 2 deletions tachyon/math/finite_fields/prime_field_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "tachyon/base/buffer/vector_buffer.h"
// #include "tachyon/math/finite_fields/prime_field_gpu_debug.h"
#include "tachyon/base/auto_reset.h"
#include "tachyon/math/finite_fields/test/finite_field_test.h"
#include "tachyon/math/finite_fields/test/gf7.h"

Expand Down Expand Up @@ -215,11 +216,32 @@ TYPED_TEST(PrimeFieldTest, Copyable) {

const F expected = F::Random();

for (size_t i = 0; i < 2; ++i) {
bool s_is_in_montgomery = i == 0;
SCOPED_TRACE(
absl::Substitute("s_is_in_montgomery: $0", s_is_in_montgomery));
base::AutoReset<bool> auto_reset(&base::Copyable<F>::s_is_in_montgomery,
s_is_in_montgomery);
base::Uint8VectorBuffer write_buf;
ASSERT_TRUE(write_buf.Grow(base::EstimateSize(expected)));
ASSERT_TRUE(write_buf.Write(expected));
ASSERT_TRUE(write_buf.Done());

write_buf.set_buffer_offset(0);

F value;
ASSERT_TRUE(write_buf.Read(&value));
EXPECT_EQ(expected, value);
}

base::Uint8VectorBuffer write_buf;
ASSERT_TRUE(write_buf.Grow(base::EstimateSize(expected)));
ASSERT_TRUE(write_buf.Write(expected));
ASSERT_TRUE(write_buf.Grow(sizeof(uint64_t)));
ASSERT_TRUE(write_buf.Write(expected.value() + F::Config::kModulus[0]));
ASSERT_TRUE(write_buf.Done());

base::AutoReset<bool> auto_reset(
&base::Copyable<F>::s_allow_value_greater_than_or_equal_to_modulus, true);

write_buf.set_buffer_offset(0);

F value;
Expand Down
1 change: 1 addition & 0 deletions third_party/rapidjson/rapidjson.BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ licenses(["notice"]) # MIT, BSD and JSON
cc_library(
name = "rapidjson",
hdrs = glob(["include/rapidjson/**/*.h"]),
defines = ["RAPIDJSON_HAS_STDSTRING"],
includes = ["include"],
)
22 changes: 22 additions & 0 deletions vendors/circom/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
load("@kroma_network_tachyon//bazel:tachyon_cc.bzl", "tachyon_cc_binary")

tachyon_cc_binary(
name = "prover_main",
srcs = ["prover_main.cc"],
deps = [
"//circomlib/circuit:quadratic_arithmetic_program",
"//circomlib/json",
"//circomlib/json:groth16_proof",
"//circomlib/json:prime_field",
"//circomlib/wtns",
"//circomlib/zkey",
"@kroma_network_tachyon//tachyon/base/console",
"@kroma_network_tachyon//tachyon/base/files:file_path_flag",
"@kroma_network_tachyon//tachyon/base/flag:flag_parser",
"@kroma_network_tachyon//tachyon/math/elliptic_curves/bls12/bls12_381",
"@kroma_network_tachyon//tachyon/math/elliptic_curves/bn/bn254",
"@kroma_network_tachyon//tachyon/math/polynomials/univariate:univariate_evaluation_domain_factory",
"@kroma_network_tachyon//tachyon/zk/r1cs/groth16:prove",
"@kroma_network_tachyon//tachyon/zk/r1cs/groth16:verify",
],
)
Loading

0 comments on commit 08f6253

Please sign in to comment.