diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/claim.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/claim.hpp index 882610ffe893..31cdc134346b 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/claim.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/claim.hpp @@ -111,30 +111,21 @@ template class OpeningClaim { * @note Implemented for native curve::Grumpkin for use with IPA. * */ - static OpeningClaim reconstruct_from_public(const std::span& ipa_claim_limbs) + static OpeningClaim reconstruct_from_public(const std::span& ipa_claim_limbs) requires(std::is_same_v) { - constexpr size_t NUM_LIMBS = 4; - - const auto recover_fq_from_limbs = [](std::array limbs) { - const uint256_t limb = uint256_t(limbs[0]) + - (uint256_t(limbs[1]) << stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION) + - (uint256_t(limbs[2]) << (stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION * 2)) + - (uint256_t(limbs[3]) << (stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION * 3)); - return typename Curve::ScalarField(limb); - }; - - std::array challenge_limbs; - std::array evaluation_limbs; + std::vector challenge_limbs; + std::vector evaluation_limbs; - for (size_t k = 0; k < NUM_LIMBS; k++) { - challenge_limbs[k] = ipa_claim_limbs[k]; - evaluation_limbs[k] = ipa_claim_limbs[NUM_LIMBS + k]; + for (size_t k = 0; k < FQ_PUBLIC_INPUT_SIZE; k++) { + challenge_limbs.emplace_back(ipa_claim_limbs[k]); + evaluation_limbs.emplace_back(ipa_claim_limbs[FQ_PUBLIC_INPUT_SIZE + k]); } - auto challenge = recover_fq_from_limbs(challenge_limbs); - auto evaluation = recover_fq_from_limbs(evaluation_limbs); - typename Curve::AffineElement commitment = { ipa_claim_limbs[8], ipa_claim_limbs[9] }; + auto challenge = fq::reconstruct_from_public(std::span(challenge_limbs)); + auto evaluation = fq::reconstruct_from_public(std::span(evaluation_limbs)); + typename Curve::AffineElement commitment = Curve::AffineElement::reconstruct_from_public( + std::span(ipa_claim_limbs).subspan(2 * FQ_PUBLIC_INPUT_SIZE, 2 * FR_PUBLIC_INPUTS_SIZE)); return OpeningClaim{ { challenge, evaluation }, commitment }; } diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/pairing_points.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/pairing_points.hpp index c12fdc224e42..d4dc6ff7fb30 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/pairing_points.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/pairing_points.hpp @@ -43,32 +43,10 @@ class PairingPoints { * @brief Reconstruct the pairing points from limbs stored on the public inputs. * */ - static PairingPoints reconstruct_from_public(const std::span& limbs_in) + static PairingPoints reconstruct_from_public(const std::span& limbs_in) { - const size_t FRS_PER_FQ = 4; - const auto recover_fq_from_limbs = [](std::array limbs) { - const uint256_t limb = uint256_t(limbs[0]) + - (uint256_t(limbs[1]) << stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION) + - (uint256_t(limbs[2]) << (stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION * 2)) + - (uint256_t(limbs[3]) << (stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION * 3)); - return Fq(limb); - }; - - const auto extract_limbs = [&](size_t start_idx) { - std::array result; - for (size_t i = 0; i < FRS_PER_FQ; ++i) { - result[i] = limbs_in[start_idx + i]; - } - return result; - }; - - Fq P0_x = recover_fq_from_limbs(extract_limbs(0)); - Fq P0_y = recover_fq_from_limbs(extract_limbs(1 * FRS_PER_FQ)); - Fq P1_x = recover_fq_from_limbs(extract_limbs(2 * FRS_PER_FQ)); - Fq P1_y = recover_fq_from_limbs(extract_limbs(3 * FRS_PER_FQ)); - - Point P0{ P0_x, P0_y }; - Point P1{ P1_x, P1_y }; + Point P0 = Point::reconstruct_from_public(limbs_in.subspan(0, 2 * FQ_PUBLIC_INPUT_SIZE)); + Point P1 = Point::reconstruct_from_public(limbs_in.subspan(2 * FQ_PUBLIC_INPUT_SIZE, 2 * FQ_PUBLIC_INPUT_SIZE)); return PairingPoints{ P0, P1 }; } diff --git a/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/fq.hpp b/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/fq.hpp index 274c53d90165..499478708850 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/fq.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/fq.hpp @@ -10,9 +10,15 @@ #include #include "../../fields/field.hpp" +#include "barretenberg/ecc/curves/bn254/fr.hpp" +#include "barretenberg/stdlib/primitives/bigfield/constants.hpp" // NOLINTBEGIN(cppcoreguidelines-avoid-c-arrays) namespace bb { + +// A point in Fq is represented with 4 public inputs +static constexpr size_t FQ_PUBLIC_INPUT_SIZE = 4; + class Bn254FqParams { // There is a helper script in ecc/fields/parameter_helper.py that can be used to extract these parameters from the // source code @@ -162,6 +168,19 @@ class Bn254FqParams { using fq = field; +template <> template <> inline fq fq::reconstruct_from_public(const std::span& limbs) +{ + // A point in Fq is represented with 4 public inputs + BB_ASSERT_EQ(limbs.size(), FQ_PUBLIC_INPUT_SIZE, "Incorrect number of limbs"); + + const uint256_t limb = static_cast(limbs[0]) + + (static_cast(limbs[1]) << bb::stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION) + + (static_cast(limbs[2]) << (bb::stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION * 2)) + + (static_cast(limbs[3]) << (bb::stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION * 3)); + + return fq(limb); +} + } // namespace bb // NOLINTEND(cppcoreguidelines-avoid-c-arrays) diff --git a/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/fr.hpp b/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/fr.hpp index a61d12dfddae..7c0fc6a48636 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/fr.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/fr.hpp @@ -15,6 +15,10 @@ // NOLINTBEGIN(cppcoreguidelines-avoid-c-arrays) namespace bb { + +// A point in Fr is represented with 1 public input +static constexpr size_t FR_PUBLIC_INPUTS_SIZE = 1; + class Bn254FrParams { // There is a helper script in ecc/fields/parameter_helper.py that can be used to extract these parameters from the public: @@ -168,6 +172,14 @@ class Bn254FrParams { using fr = field; +template <> template <> inline fr fr::reconstruct_from_public(const std::span& limbs) +{ + + BB_ASSERT_EQ(limbs.size(), FR_PUBLIC_INPUTS_SIZE, "Incorrect number of limbs"); + + return fr(limbs[0]); +} + } // namespace bb // NOLINTEND(cppcoreguidelines-avoid-c-arrays) diff --git a/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/g1.hpp b/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/g1.hpp index 0362e9e712ec..8d7304f2721f 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/g1.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/curves/bn254/g1.hpp @@ -40,3 +40,24 @@ inline std::string msgpack_schema_name(bb::g1::affine_element const& /*unused*/) { return "G1AffineElement"; } + +// Specialize the reconstruct from public method +template <> +inline bb::g1::affine_element bb::g1::affine_element::reconstruct_from_public(const std::span& limbs) +{ + BB_ASSERT_EQ(limbs.size(), 2 * FQ_PUBLIC_INPUT_SIZE, "Incorrect number of limbs"); + + auto x_limbs = limbs.subspan(0, FQ_PUBLIC_INPUT_SIZE); + auto y_limbs = limbs.subspan(FQ_PUBLIC_INPUT_SIZE, FQ_PUBLIC_INPUT_SIZE); + + affine_element result; + result.x = Fq::reconstruct_from_public(x_limbs); + result.y = Fq::reconstruct_from_public(y_limbs); + + if (result.x == Fq::zero() && result.y == Fq::zero()) { + result.self_set_infinity(); + } + + ASSERT(result.on_curve()); + return result; +} diff --git a/barretenberg/cpp/src/barretenberg/ecc/curves/grumpkin/grumpkin.hpp b/barretenberg/cpp/src/barretenberg/ecc/curves/grumpkin/grumpkin.hpp index b3103cf15d73..ea364419bd43 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/curves/grumpkin/grumpkin.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/curves/grumpkin/grumpkin.hpp @@ -79,3 +79,25 @@ class Grumpkin { static constexpr uint32_t LIBRA_UNIVARIATES_LENGTH = 3; }; } // namespace bb::curve + +// Specialize the reconstruct from public method +template <> +inline bb::grumpkin::g1::affine_element bb::grumpkin::g1::affine_element::reconstruct_from_public( + const std::span& limbs) +{ + BB_ASSERT_EQ(limbs.size(), 2 * FR_PUBLIC_INPUTS_SIZE, "Incorrect number of limbs"); + + auto x_limbs = limbs.subspan(0, FR_PUBLIC_INPUTS_SIZE); + auto y_limbs = limbs.subspan(FR_PUBLIC_INPUTS_SIZE, FR_PUBLIC_INPUTS_SIZE); + + affine_element result; + result.x = Fq::reconstruct_from_public(x_limbs); + result.y = Fq::reconstruct_from_public(y_limbs); + + if (result.x == Fq::zero() && result.y == Fq::zero()) { + result.self_set_infinity(); + } + + ASSERT(result.on_curve()); + return result; +} diff --git a/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp b/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp index 4c67b264b6f2..c676cca9a7bc 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/fields/field_declarations.hpp @@ -373,6 +373,8 @@ template struct alignas(32) field { static field serialize_from_buffer(const uint8_t* buffer) { return from_buffer(buffer); } + template static field reconstruct_from_public(const std::span>& limbs); + [[nodiscard]] BB_INLINE std::vector to_buffer() const { return ::to_buffer(*this); } struct wide_array { diff --git a/barretenberg/cpp/src/barretenberg/ecc/groups/affine_element.hpp b/barretenberg/cpp/src/barretenberg/ecc/groups/affine_element.hpp index b523e68132dc..a4aca870a48d 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/groups/affine_element.hpp +++ b/barretenberg/cpp/src/barretenberg/ecc/groups/affine_element.hpp @@ -8,6 +8,7 @@ #include "barretenberg/common/serialize.hpp" #include "barretenberg/ecc/curves/bn254/fq2.hpp" +#include "barretenberg/ecc/curves/bn254/fr.hpp" #include "barretenberg/numeric/uint256/uint256.hpp" #include "barretenberg/serialize/msgpack.hpp" #include @@ -170,6 +171,8 @@ template class alignas(64) affine return buffer; } + static affine_element reconstruct_from_public(const std::span& limbs); + friend std::ostream& operator<<(std::ostream& os, const affine_element& a) { os << "{ " << a.x << ", " << a.y << " }"; diff --git a/barretenberg/cpp/src/barretenberg/ecc/groups/affine_element.test.cpp b/barretenberg/cpp/src/barretenberg/ecc/groups/affine_element.test.cpp index 36fb2d02ef51..bc9088225e95 100644 --- a/barretenberg/cpp/src/barretenberg/ecc/groups/affine_element.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ecc/groups/affine_element.test.cpp @@ -8,6 +8,7 @@ #include "barretenberg/ecc/curves/secp256r1/secp256r1.hpp" #include "barretenberg/ecc/groups/element.hpp" #include "barretenberg/serialize/test_helper.hpp" +#include "barretenberg/stdlib/primitives/curves/bn254.hpp" #include "gmock/gmock.h" #include @@ -290,6 +291,50 @@ TYPED_TEST(TestAffineElement, MulWithEndomorphismMatchesMulWithoutEndomorphism) } } +TEST(AffineElementFromPublicInputs, Bn254FromPublicInputs) +{ + using Curve = curve::BN254; + using AffineElement = Curve::AffineElement; + + AffineElement point = AffineElement::random_element(); + uint256_t x(point.x); + uint256_t y(point.y); + + // Construct public inputs + std::vector public_inputs; + size_t index = 0; + for (size_t idx = 0; idx < FQ_PUBLIC_INPUT_SIZE; idx++) { + auto limb = x.slice(index, index + bb::stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION); + public_inputs.emplace_back(bb::fr(limb)); + index += bb::stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION; + } + index = 0; + for (size_t idx = 0; idx < FQ_PUBLIC_INPUT_SIZE; idx++) { + auto limb = y.slice(index, index + bb::stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION); + public_inputs.emplace_back(bb::fr(limb)); + index += bb::stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION; + } + + auto reconstructed = AffineElement::reconstruct_from_public(std::span(public_inputs)); + + EXPECT_EQ(reconstructed, point); +} + +TEST(AffineElementFromPublicInputs, GrumpkinFromPublicInputs) +{ + using Curve = curve::Grumpkin; + using AffineElement = Curve::AffineElement; + + AffineElement point = AffineElement::random_element(); + + // Construct public inputs + std::vector public_inputs = { point.x, point.y }; + + auto reconstructed = AffineElement::reconstruct_from_public(std::span(public_inputs)); + + EXPECT_EQ(reconstructed, point); +} + // TODO(https://github.com/AztecProtocol/barretenberg/issues/909): These tests are not typed for no reason // Multiplication of a point at infinity by a scalar should be a point at infinity TEST(AffineElement, InfinityMulByScalarIsInfinity) diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp index 805ede15d235..0ee14d2fe10b 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp @@ -34,8 +34,8 @@ template bool UltraVerifier_::verify_proof(const HonkP if constexpr (HasIPAAccumulator) { // Extract the public inputs containing the IPA claim and reconstruct const uint32_t start_idx = static_cast(verification_key->vk->num_public_inputs) - IPA_CLAIM_SIZE; - std::span ipa_claim_limbs{ verification_key->public_inputs.data() + start_idx, - IPA_CLAIM_SIZE }; + std::span ipa_claim_limbs{ verification_key->public_inputs.data() + start_idx, + IPA_CLAIM_SIZE }; auto ipa_claim = OpeningClaim::reconstruct_from_public(ipa_claim_limbs);