Skip to content

Commit

Permalink
git subrepo pull (merge) circuits/cpp/barretenberg
Browse files Browse the repository at this point in the history
subrepo:
  subdir:   "circuits/cpp/barretenberg"
  merged:   "d0e4f0018"
upstream:
  origin:   "https://github.com/AztecProtocol/barretenberg"
  branch:   "master"
  commit:   "4bb7559d0"
git-subrepo:
  version:  "0.4.6"
  origin:   "???"
  commit:   "???"
  • Loading branch information
ludamad0 authored and AztecBot committed Sep 6, 2023
1 parent 4bb7559 commit 3da1da1
Show file tree
Hide file tree
Showing 17 changed files with 450 additions and 261 deletions.
17 changes: 9 additions & 8 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ if(FUZZING)
endif()

if(UNDEFINED_BEHAVIOUR_SANITIZER)
set(SANITIZER_OPTIONS ${SANITIZER_OPTIONS} -fsanitize=undefined -fno-sanitize=alignment)
set(SANITIZER_OPTIONS ${SANITIZER_OPTIONS} -fsanitize=undefined -fno-sanitize=alignment)
endif()

add_compile_options(-fsanitize=fuzzer-no-link ${SANITIZER_OPTIONS})
Expand Down Expand Up @@ -81,15 +81,15 @@ set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
set(CMAKE_CXX_EXTENSIONS ON)

if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "10")
message(WARNING "Clang <10 is not supported")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "14")
message(WARNING "Clang <14 is not supported")
endif()
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "10")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "10")
message(WARNING "GCC <10 is not supported")
endif()
else()
message(WARNING "Unsuported compiler, use Clang >10 or GCC >10")
message(WARNING "Unsuported compiler, use Clang >14 or GCC >10")
endif()

if(COVERAGE)
Expand All @@ -105,13 +105,15 @@ if(COVERAGE)
# Find llvm-profdata
set(PROFDATA_EXECUTABLE_NAME "llvm-profdata-${CLANG_VERSION_MAJOR}")
find_program(PROFDATA_EXECUTABLE ${PROFDATA_EXECUTABLE_NAME})

if(PROFDATA_EXECUTABLE MATCHES "NOTFOUND")
message(FATAL_ERROR "Couldn't find ${PROFDATA_EXECUTABLE_NAME}")
endif()

# Find llvm-cov
set(COV_EXECUTABLE_NAME "llvm-cov-${CLANG_VERSION_MAJOR}")
find_program(COV_EXECUTABLE ${COV_EXECUTABLE_NAME})

if(COV_EXECUTABLE MATCHES "NOTFOUND")
message(FATAL_ERROR "Couldn't find ${COV_EXECUTABLE_NAME}")
endif()
Expand All @@ -121,12 +123,11 @@ if(COVERAGE)

# Add a custom target for creating the report
add_custom_target(create_full_coverage_report
COMMAND "${CMAKE_SOURCE_DIR}/scripts/collect_coverage_information.sh" ${PROFDATA_EXECUTABLE} ${COV_EXECUTABLE}
VERBATIM
COMMAND "${CMAKE_SOURCE_DIR}/scripts/collect_coverage_information.sh" ${PROFDATA_EXECUTABLE} ${COV_EXECUTABLE}
VERBATIM
)
endif()


include(cmake/build.cmake)
include(GNUInstallDirs)
include(cmake/arch.cmake)
Expand Down
3 changes: 2 additions & 1 deletion cpp/src/barretenberg/common/serialize.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ __extension__ using uint128_t = unsigned __int128;
// NOLINTBEGIN(cppcoreguidelines-pro-type-reinterpret-cast, cert-dcl58-cpp)
// clang-format on

template <typename T> concept IntegralOrEnum = std::integral<T> || std::is_enum_v<T>;
template <typename T>
concept IntegralOrEnum = std::integral<T> || std::is_enum_v<T>;

namespace serialize {
// Forward declare derived msgpack methods
Expand Down
1 change: 0 additions & 1 deletion cpp/src/barretenberg/honk/flavor/ultra_recursive.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ class UltraRecursive {
public:
using CircuitBuilder = UltraCircuitBuilder;
using Curve = plonk::stdlib::bn254<CircuitBuilder>;
using PCS = pcs::kzg::KZG<Curve>;
using GroupElement = Curve::Element;
using Commitment = Curve::Element;
using CommitmentHandle = Curve::Element;
Expand Down
38 changes: 24 additions & 14 deletions cpp/src/barretenberg/honk/pcs/gemini/gemini.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ template <typename Curve> class GeminiProver_ {
const Fr& r_challenge);
}; // namespace proof_system::honk::pcs::gemini

template <typename Curve> class GeminiVerifier_ {
template <typename Curve, bool goblin_flag = false> class GeminiVerifier_ {
using Fr = typename Curve::ScalarField;
using GroupElement = typename Curve::Element;
using Commitment = typename Curve::AffineElement;
Expand Down Expand Up @@ -232,21 +232,31 @@ template <typename Curve> class GeminiVerifier_ {
Fr r)
{
// C₀ᵣ₊ = [F] + r⁻¹⋅[G]
GroupElement C0_r_pos = batched_f;
GroupElement C0_r_pos;
// C₀ᵣ₋ = [F] - r⁻¹⋅[G]
GroupElement C0_r_neg = batched_f;
Fr r_inv = r.invert();
GroupElement C0_r_neg;
Fr r_inv = r.invert(); // r⁻¹

// TODO(luke): reinstate some kind of !batched_g.is_point_at_infinity() check for stdlib types? This is mostly
// relevant for Gemini unit tests since in practice batched_g != zero (i.e. we will always have shifted polys).
bool batched_g_is_point_at_infinity = false;
if constexpr (!Curve::is_stdlib_type) { // Note: required for Gemini tests with no shifts
batched_g_is_point_at_infinity = batched_g.is_point_at_infinity();
}
if (!batched_g_is_point_at_infinity) {
batched_g = batched_g * r_inv;
C0_r_pos += batched_g;
C0_r_neg -= batched_g;
// If in a recursive setting, perform a batch mul. Otherwise, accumulate directly.
// TODO(#673): The following if-else represents the stldib/native code paths. Once the "native" verifier is
// achieved through a builder Simulator, the stdlib codepath should become the only codepath.
if constexpr (Curve::is_stdlib_type) {
std::vector<GroupElement> commitments = { batched_f, batched_g };
auto builder = r.get_context();
auto one = Fr(builder, 1);
// TODO(#707): these batch muls include the use of 1 as a scalar. This is handled appropriately as a non-mul
// (add-accumulate) in the goblin batch_mul but is done inefficiently as a scalar mul in the conventional
// emulated batch mul.
C0_r_pos = GroupElement::template batch_mul<goblin_flag>(commitments, { one, r_inv });
C0_r_neg = GroupElement::template batch_mul<goblin_flag>(commitments, { one, -r_inv });
} else {
C0_r_pos = batched_f;
C0_r_neg = batched_f;
if (!batched_g.is_point_at_infinity()) {
batched_g = batched_g * r_inv;
C0_r_pos += batched_g;
C0_r_neg -= batched_g;
}
}

return { C0_r_pos, C0_r_neg };
Expand Down
29 changes: 16 additions & 13 deletions cpp/src/barretenberg/honk/pcs/kzg/kzg.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

namespace proof_system::honk::pcs::kzg {

template <typename Curve> class KZG {
template <typename Curve, bool goblin_flag = false> class KZG {
using CK = CommitmentKey<Curve>;
using VK = VerifierCommitmentKey<Curve>;
using Fr = typename Curve::ScalarField;
Expand Down Expand Up @@ -72,31 +72,34 @@ template <typename Curve> class KZG {
*
* @param claim OpeningClaim ({r, v}, C)
* @return {P₀, P₁} where
* - P₀ = C − v⋅[1]₁ + r⋅[x]₁
* - P₁ = [Q(x)]₁
* - P₀ = C − v⋅[1]₁ + r⋅[W(x)]₁
* - P₁ = [W(x)]₁
*/
static std::array<GroupElement, 2> compute_pairing_points(const OpeningClaim<Curve>& claim,
auto& verifier_transcript)
{
auto quotient_commitment = verifier_transcript.template receive_from_prover<Commitment>("KZG:W");

auto lhs = claim.commitment + (quotient_commitment * claim.opening_pair.challenge);
// Add the evaluation point contribution v⋅[1]₁.
GroupElement P_0;
// Note: In the recursive setting, we only add the contribution if it is not the point at infinity (i.e. if the
// evaluation is not equal to zero).
// TODO(luke): What is the proper way to handle this? Contraints to show scalar (evaluation) is zero?
if constexpr (Curve::is_stdlib_type) {
if (!claim.opening_pair.evaluation.get_value().is_zero()) {
auto ctx = verifier_transcript.builder;
lhs -= GroupElement::one(ctx) * claim.opening_pair.evaluation;
}
auto builder = verifier_transcript.builder;
auto one = Fr(builder, 1);
std::vector<GroupElement> commitments = { claim.commitment, quotient_commitment };
std::vector<Fr> scalars = { one, claim.opening_pair.challenge };
P_0 = GroupElement::template batch_mul<goblin_flag>(commitments, scalars);
// Note: This implementation assumes the evaluation is zero (as is the case for shplonk).
ASSERT(claim.opening_pair.evaluation.get_value() == 0);
} else {
lhs -= GroupElement::one() * claim.opening_pair.evaluation;
P_0 = claim.commitment;
P_0 += quotient_commitment * claim.opening_pair.challenge;
P_0 -= GroupElement::one() * claim.opening_pair.evaluation;
}

auto rhs = -quotient_commitment;
auto P_1 = -quotient_commitment;

return { lhs, rhs };
return { P_0, P_1 };
};
};
} // namespace proof_system::honk::pcs::kzg
131 changes: 74 additions & 57 deletions cpp/src/barretenberg/honk/pcs/shplonk/shplonk.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ template <typename Curve> class ShplonkProver_ {
* @brief Shplonk Verifier
*
*/
template <typename Curve> class ShplonkVerifier_ {
template <typename Curve, bool goblin_flag = false> class ShplonkVerifier_ {
using Fr = typename Curve::ScalarField;
using GroupElement = typename Curve::Element;
using Commitment = typename Curve::AffineElement;
Expand Down Expand Up @@ -174,84 +174,101 @@ template <typename Curve> class ShplonkVerifier_ {

const Fr z_challenge = transcript.get_challenge("Shplonk:z");

// [G] = [Q] - ∑ⱼ ρʲ / ( r − xⱼ )⋅[fⱼ] + G₀⋅[1]
// = [Q] - [∑ⱼ ρʲ ⋅ ( fⱼ(X) − vⱼ) / ( r − xⱼ )]
GroupElement G_commitment;

// compute simulated commitment to [G] as a linear combination of
// [Q], { [fⱼ] }, [1]:
// [G] = [Q] - ∑ⱼ (1/zⱼ(r))[Bⱼ] + ( ∑ⱼ (1/zⱼ(r)) Tⱼ(r) )[1]
// = [Q] - ∑ⱼ (1/zⱼ(r))[Bⱼ] + G₀ [1]

// G₀ = ∑ⱼ ρʲ ⋅ vⱼ / ( r − xⱼ )
auto G_commitment_constant = Fr(0);

// [G] = [Q] - ∑ⱼ ρʲ / ( r − xⱼ )⋅[fⱼ] + G₀⋅[1]
// = [Q] - [∑ⱼ ρʲ ⋅ ( fⱼ(X) − vⱼ) / ( r − xⱼ )]
GroupElement G_commitment = Q_commitment;

// Compute {ẑⱼ(r)}ⱼ , where ẑⱼ(r) = 1/zⱼ(r) = 1/(r - xⱼ)
std::vector<Fr> vanishing_evals;
vanishing_evals.reserve(num_claims);
for (const auto& claim : claims) {
vanishing_evals.emplace_back(z_challenge - claim.opening_pair.challenge);
}
// If recursion, invert elements individually, otherwise batch invert. (Inversion is cheap in circuits since we
// need only prove the correctness of a known inverse, we do not emulate its computation. Hence no need for
// batch inversion).
std::vector<Fr> inverse_vanishing_evals;
// TODO(#673): The recursive and non-recursive (native) logic is completely separated via the following
// conditional. Much of the logic could be shared, but I've chosen to do it this way since soon the "else"
// branch should be removed in its entirety, and "native" verification will utilize the recursive code paths
// using a builder Simulator.
if constexpr (Curve::is_stdlib_type) {
for (const auto& val : vanishing_evals) {
inverse_vanishing_evals.emplace_back(val.invert());
auto builder = nu.get_context();

// Containers for the inputs to the final batch mul
std::vector<Commitment> commitments;
std::vector<Fr> scalars;

// [G] = [Q] - ∑ⱼ ρʲ / ( r − xⱼ )⋅[fⱼ] + G₀⋅[1]
// = [Q] - [∑ⱼ ρʲ ⋅ ( fⱼ(X) − vⱼ) / ( r − xⱼ )]
commitments.emplace_back(Q_commitment);
scalars.emplace_back(Fr(builder, 1)); // Fr(1)

// Compute {ẑⱼ(r)}ⱼ , where ẑⱼ(r) = 1/zⱼ(r) = 1/(r - xⱼ)
std::vector<Fr> inverse_vanishing_evals;
inverse_vanishing_evals.reserve(num_claims);
for (const auto& claim : claims) {
// Note: no need for batch inversion; emulated inverison is cheap. (just show known inverse is valid)
inverse_vanishing_evals.emplace_back((z_challenge - claim.opening_pair.challenge).invert());
}
} else {
Fr::batch_invert(vanishing_evals);
inverse_vanishing_evals = vanishing_evals;
}

auto current_nu = Fr(1);
// Note: commitments and scalars vectors used only in recursion setting for batch mul
std::vector<Commitment> commitments;
std::vector<Fr> scalars;
for (size_t j = 0; j < num_claims; ++j) {
// (Cⱼ, xⱼ, vⱼ)
const auto& [opening_pair, commitment] = claims[j];
auto current_nu = Fr(1);
// Note: commitments and scalars vectors used only in recursion setting for batch mul
for (size_t j = 0; j < num_claims; ++j) {
// (Cⱼ, xⱼ, vⱼ)
const auto& [opening_pair, commitment] = claims[j];

Fr scaling_factor = current_nu * inverse_vanishing_evals[j]; // = ρʲ / ( r − xⱼ )
Fr scaling_factor = current_nu * inverse_vanishing_evals[j]; // = ρʲ / ( r − xⱼ )

// G₀ += ρʲ / ( r − xⱼ ) ⋅ vⱼ
G_commitment_constant += scaling_factor * opening_pair.evaluation;

// G₀ += ρʲ / ( r − xⱼ ) ⋅ vⱼ
G_commitment_constant += scaling_factor * opening_pair.evaluation;
current_nu *= nu;

// If recursion, store MSM inputs for batch mul, otherwise accumulate directly
if constexpr (Curve::is_stdlib_type) {
// Store MSM inputs for batch mul
commitments.emplace_back(commitment);
scalars.emplace_back(scaling_factor);
} else {
// [G] -= ρʲ / ( r − xⱼ )⋅[fⱼ]
G_commitment -= commitment * scaling_factor;
scalars.emplace_back(-scaling_factor);
}

current_nu *= nu;
}
commitments.emplace_back(GroupElement::one(builder));
scalars.emplace_back(G_commitment_constant);

// If recursion, do batch mul to compute [G] -= ∑ⱼ ρʲ / ( r − xⱼ )⋅[fⱼ]
if constexpr (Curve::is_stdlib_type) {
G_commitment -= GroupElement::batch_mul(commitments, scalars);
}
// [G] += G₀⋅[1] = [G] + (∑ⱼ ρʲ ⋅ vⱼ / ( r − xⱼ ))⋅[1]
G_commitment = GroupElement::template batch_mul<goblin_flag>(commitments, scalars);

// [G] += G₀⋅[1] = [G] + (∑ⱼ ρʲ ⋅ vⱼ / ( r − xⱼ ))⋅[1]
Fr evaluation_zero; // 0 \in Fr
GroupElement group_one; // [1]
if constexpr (Curve::is_stdlib_type) {
auto ctx = transcript.builder;
evaluation_zero = Fr::from_witness(ctx, 0);
group_one = GroupElement::one(ctx);
} else {
// GroupElement sort_of_one{ x, y };
evaluation_zero = Fr(0);
group_one = vk->srs->get_first_g1();
}
// [G] = [Q] - ∑ⱼ ρʲ / ( r − xⱼ )⋅[fⱼ] + G₀⋅[1]
// = [Q] - [∑ⱼ ρʲ ⋅ ( fⱼ(X) − vⱼ) / ( r − xⱼ )]
G_commitment = Q_commitment;

// Compute {ẑⱼ(r)}ⱼ , where ẑⱼ(r) = 1/zⱼ(r) = 1/(r - xⱼ)
std::vector<Fr> inverse_vanishing_evals;
inverse_vanishing_evals.reserve(num_claims);
for (const auto& claim : claims) {
inverse_vanishing_evals.emplace_back(z_challenge - claim.opening_pair.challenge);
}
Fr::batch_invert(inverse_vanishing_evals);

auto current_nu = Fr(1);
// Note: commitments and scalars vectors used only in recursion setting for batch mul
for (size_t j = 0; j < num_claims; ++j) {
// (Cⱼ, xⱼ, vⱼ)
const auto& [opening_pair, commitment] = claims[j];

G_commitment += group_one * G_commitment_constant;
Fr scaling_factor = current_nu * inverse_vanishing_evals[j]; // = ρʲ / ( r − xⱼ )

// G₀ += ρʲ / ( r − xⱼ ) ⋅ vⱼ
G_commitment_constant += scaling_factor * opening_pair.evaluation;

// [G] -= ρʲ / ( r − xⱼ )⋅[fⱼ]
G_commitment -= commitment * scaling_factor;

current_nu *= nu;
}

// [G] += G₀⋅[1] = [G] + (∑ⱼ ρʲ ⋅ vⱼ / ( r − xⱼ ))⋅[1]
G_commitment += vk->srs->get_first_g1() * G_commitment_constant;
}

// Return opening pair (z, 0) and commitment [G]
return { { z_challenge, evaluation_zero }, G_commitment };
return { { z_challenge, Fr(0) }, G_commitment };
};
};
} // namespace proof_system::honk::pcs::shplonk
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ struct ecc_op_tuple {
uint32_t x_hi;
uint32_t y_lo;
uint32_t y_hi;
uint32_t z_lo;
uint32_t z_hi;
uint32_t z_1;
uint32_t z_2;
};

template <typename B, typename FF> inline void read(B& buf, poly_triple_<FF>& constraint)
Expand Down
Loading

0 comments on commit 3da1da1

Please sign in to comment.