Skip to content

Commit 3048d08

Browse files
feat: Goblinize the final ecc ops in ZM (AztecProtocol#3741)
In the initial implementation of ZM I forgot to goblinize a couple of the final group operations in Zeromorph which was causing the gate count of the recursive verifier to blow up. We fix this. We implement the addition, subtraction, and single scalar multiplication operation inefficiently using the batch_mul methods. We disable some member functions that do not use Goblin when they could, and leave references to AztecProtocol/barretenberg#707 as a future optimization task. --------- Co-authored-by: codygunton <codygunton@gmail.com>
1 parent f924037 commit 3048d08

File tree

7 files changed

+212
-99
lines changed

7 files changed

+212
-99
lines changed

barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp

+21-2
Original file line numberDiff line numberDiff line change
@@ -692,7 +692,16 @@ template <typename Curve> class ZeroMorphVerifier_ {
692692
concatenation_group_commitments);
693693

694694
// Compute commitment C_{\zeta,Z}
695-
auto C_zeta_Z = C_zeta_x + C_Z_x * z_challenge;
695+
Commitment C_zeta_Z;
696+
if constexpr (Curve::is_stdlib_type) {
697+
// Express operation as a batch_mul in order to use Goblinization if available
698+
auto builder = rho.get_context();
699+
std::vector<FF> scalars = { FF(builder, 1), z_challenge };
700+
std::vector<Commitment> points = { C_zeta_x, C_Z_x };
701+
C_zeta_Z = Commitment::batch_mul(points, scalars);
702+
} else {
703+
C_zeta_Z = C_zeta_x + C_Z_x * z_challenge;
704+
}
696705

697706
// Receive proof commitment \pi
698707
auto C_pi = transcript->template receive_from_prover<Commitment>("ZM:PI");
@@ -702,7 +711,17 @@ template <typename Curve> class ZeroMorphVerifier_ {
702711
// e(C_{\zeta,Z}, [1]_2) = e(pi, [X - x]_2). This can be rearranged (e.g. see the plonk paper) as
703712
// e(C_{\zeta,Z} - x*pi, [1]_2) * e(-pi, [X]_2) = 1, or
704713
// e(P_0, [1]_2) * e(P_1, [X]_2) = 1
705-
auto P0 = C_zeta_Z + C_pi * x_challenge;
714+
Commitment P0;
715+
if constexpr (Curve::is_stdlib_type) {
716+
// Express operation as a batch_mul in order to use Goblinization if available
717+
auto builder = rho.get_context();
718+
std::vector<FF> scalars = { FF(builder, 1), x_challenge };
719+
std::vector<Commitment> points = { C_zeta_Z, C_pi };
720+
P0 = Commitment::batch_mul(points, scalars);
721+
} else {
722+
P0 = C_zeta_Z + C_pi * x_challenge;
723+
}
724+
706725
auto P1 = -C_pi;
707726

708727
return { P0, P1 };

barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.hpp

+30-15
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,21 @@
22

33
#include "../bigfield/bigfield.hpp"
44
#include "../byte_array/byte_array.hpp"
5-
#include "../field/field.hpp"
6-
#include "barretenberg/ecc/curves/bn254/g1.hpp"
7-
85
#include "../circuit_builders/circuit_builders_fwd.hpp"
6+
#include "../field/field.hpp"
97
#include "../memory/rom_table.hpp"
108
#include "../memory/twin_rom_table.hpp"
119
#include "barretenberg/ecc/curves/bn254/g1.hpp"
1210
#include "barretenberg/ecc/curves/secp256k1/secp256k1.hpp"
1311
#include "barretenberg/ecc/curves/secp256r1/secp256r1.hpp"
1412

15-
namespace proof_system::plonk {
16-
namespace stdlib {
13+
// TODO(https://github.com/AztecProtocol/barretenberg/issues/707) If using a a circuit builder with Goblin, which is
14+
// designed to have efficient barretenberg::g1 operations, a developer might accidentally write inefficient circuits
15+
// using biggroup functions that do not use the OpQueue. We use this concept to prevent compilation of such functions.
16+
template <typename Builder, typename NativeGroup>
17+
concept IsNotGoblinInefficiencyTrap = !(IsGoblinBuilder<Builder> && std::same_as<NativeGroup, barretenberg::g1>);
18+
19+
namespace proof_system::plonk::stdlib {
1720

1821
// ( ͡° ͜ʖ ͡°)
1922
template <class Builder, class Fq, class Fr, class NativeGroup> class element {
@@ -154,14 +157,22 @@ template <class Builder, class Fq, class Fr, class NativeGroup> class element {
154157
* We can chain repeated point additions together, where we only require 2 non-native field multiplications per
155158
* point addition, instead of 3
156159
**/
157-
static chain_add_accumulator chain_add_start(const element& p1, const element& p2);
158-
static chain_add_accumulator chain_add(const element& p1, const chain_add_accumulator& accumulator);
159-
static element chain_add_end(const chain_add_accumulator& accumulator);
160-
161-
element montgomery_ladder(const element& other) const;
162-
element montgomery_ladder(const chain_add_accumulator& accumulator);
163-
element multiple_montgomery_ladder(const std::vector<chain_add_accumulator>& to_add) const;
164-
element quadruple_and_add(const std::vector<element>& to_add) const;
160+
static chain_add_accumulator chain_add_start(const element& p1, const element& p2)
161+
requires(IsNotGoblinInefficiencyTrap<Builder, NativeGroup>);
162+
static chain_add_accumulator chain_add(const element& p1, const chain_add_accumulator& accumulator)
163+
requires(IsNotGoblinInefficiencyTrap<Builder, NativeGroup>);
164+
static element chain_add_end(const chain_add_accumulator& accumulator)
165+
requires(IsNotGoblinInefficiencyTrap<Builder, NativeGroup>);
166+
167+
element montgomery_ladder(const element& other) const
168+
requires(IsNotGoblinInefficiencyTrap<Builder, NativeGroup>);
169+
element montgomery_ladder(const chain_add_accumulator& accumulator)
170+
requires(IsNotGoblinInefficiencyTrap<Builder, NativeGroup>);
171+
element multiple_montgomery_ladder(const std::vector<chain_add_accumulator>& to_add) const
172+
requires(IsNotGoblinInefficiencyTrap<Builder, NativeGroup>);
173+
174+
element quadruple_and_add(const std::vector<element>& to_add) const
175+
requires(IsNotGoblinInefficiencyTrap<Builder, NativeGroup>);
165176

166177
typename NativeGroup::affine_element get_value() const
167178
{
@@ -179,6 +190,9 @@ template <class Builder, class Fq, class Fr, class NativeGroup> class element {
179190
static element batch_mul(const std::vector<element>& points,
180191
const std::vector<Fr>& scalars,
181192
const size_t max_num_bits = 0);
193+
194+
// TODO(https://github.com/AztecProtocol/barretenberg/issues/707) max_num_bits is unused; could implement and use
195+
// this to optimize other operations.
182196
static element goblin_batch_mul(const std::vector<element>& points,
183197
const std::vector<Fr>& scalars,
184198
const size_t max_num_bits = 0);
@@ -196,13 +210,15 @@ template <class Builder, class Fq, class Fr, class NativeGroup> class element {
196210
// i.e. for the bn254 curve, the template param is `typename = void`
197211
// for any other curve, there is no template param
198212
template <typename X = NativeGroup, typename = typename std::enable_if_t<std::is_same<X, barretenberg::g1>::value>>
213+
requires(IsNotGoblinBuilder<Builder>) // TODO(https://github.com/AztecProtocol/barretenberg/issues/707)
199214
static element bn254_endo_batch_mul(const std::vector<element>& big_points,
200215
const std::vector<Fr>& big_scalars,
201216
const std::vector<element>& small_points,
202217
const std::vector<Fr>& small_scalars,
203218
const size_t max_num_small_bits);
204219

205220
template <typename X = NativeGroup, typename = typename std::enable_if_t<std::is_same<X, barretenberg::g1>::value>>
221+
requires(IsNotGoblinBuilder<Builder>) // TODO(https://github.com/AztecProtocol/barretenberg/issues/707)
206222
static element bn254_endo_batch_mul_with_generator(const std::vector<element>& big_points,
207223
const std::vector<Fr>& big_scalars,
208224
const std::vector<element>& small_points,
@@ -889,8 +905,7 @@ inline std::ostream& operator<<(std::ostream& os, element<C, Fq, Fr, G> const& v
889905
{
890906
return os << "{ " << v.x << " , " << v.y << " }";
891907
}
892-
} // namespace stdlib
893-
} // namespace proof_system::plonk
908+
} // namespace proof_system::plonk::stdlib
894909

895910
#include "biggroup_batch_mul.hpp"
896911
#include "biggroup_bn254.hpp"

barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup.test.cpp

+64-20
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,14 @@
1-
#include "barretenberg/common/test.hpp"
2-
#include <type_traits>
3-
4-
#include "../bigfield/bigfield.hpp"
51
#include "../biggroup/biggroup.hpp"
2+
#include "../bigfield/bigfield.hpp"
63
#include "../bool/bool.hpp"
74
#include "../field/field.hpp"
5+
#include "barretenberg/common/test.hpp"
6+
#include "barretenberg/numeric/random/engine.hpp"
87
#include "barretenberg/stdlib/primitives/circuit_builders/circuit_builders.hpp"
9-
108
#include "barretenberg/stdlib/primitives/curves/bn254.hpp"
119
#include "barretenberg/stdlib/primitives/curves/secp256k1.hpp"
1210
#include "barretenberg/stdlib/primitives/curves/secp256r1.hpp"
1311

14-
#include "barretenberg/numeric/random/engine.hpp"
15-
#include <memory>
16-
1712
namespace test_stdlib_biggroup {
1813
namespace {
1914
auto& engine = numeric::random::get_debug_engine();
@@ -825,12 +820,17 @@ template <typename TestType> class stdlib_biggroup : public testing::Test {
825820

826821
enum UseBigfield { No, Yes };
827822
using TestTypes = testing::Types<TestType<stdlib::bn254<proof_system::StandardCircuitBuilder>, UseBigfield::No>,
828-
TestType<stdlib::bn254<proof_system::UltraCircuitBuilder>, UseBigfield::Yes>>;
823+
TestType<stdlib::bn254<proof_system::UltraCircuitBuilder>, UseBigfield::Yes>,
824+
TestType<stdlib::bn254<proof_system::GoblinUltraCircuitBuilder>, UseBigfield::No>>;
829825

830826
TYPED_TEST_SUITE(stdlib_biggroup, TestTypes);
831827

828+
template <typename T>
829+
concept HasGoblinBuilder = IsGoblinBuilder<typename T::Curve::Builder>;
830+
832831
TYPED_TEST(stdlib_biggroup, add)
833832
{
833+
834834
TestFixture::test_add();
835835
}
836836
TYPED_TEST(stdlib_biggroup, sub)
@@ -843,23 +843,39 @@ TYPED_TEST(stdlib_biggroup, dbl)
843843
}
844844
TYPED_TEST(stdlib_biggroup, montgomery_ladder)
845845
{
846-
TestFixture::test_montgomery_ladder();
846+
if constexpr (HasGoblinBuilder<TypeParam>) {
847+
GTEST_SKIP() << "https://github.com/AztecProtocol/barretenberg/issues/707";
848+
} else {
849+
TestFixture::test_montgomery_ladder();
850+
};
847851
}
848852
HEAVY_TYPED_TEST(stdlib_biggroup, mul)
849853
{
850854
TestFixture::test_mul();
851855
}
852856
HEAVY_TYPED_TEST(stdlib_biggroup, twin_mul)
853857
{
854-
TestFixture::test_twin_mul();
858+
if constexpr (HasGoblinBuilder<TypeParam>) {
859+
GTEST_SKIP() << "https://github.com/AztecProtocol/barretenberg/issues/707";
860+
} else {
861+
TestFixture::test_twin_mul();
862+
};
855863
}
856864
HEAVY_TYPED_TEST(stdlib_biggroup, triple_mul)
857865
{
858-
TestFixture::test_triple_mul();
866+
if constexpr (HasGoblinBuilder<TypeParam>) {
867+
GTEST_SKIP() << "https://github.com/AztecProtocol/barretenberg/issues/707";
868+
} else {
869+
TestFixture::test_triple_mul();
870+
};
859871
}
860872
HEAVY_TYPED_TEST(stdlib_biggroup, quad_mul)
861873
{
862-
TestFixture::test_quad_mul();
874+
if constexpr (HasGoblinBuilder<TypeParam>) {
875+
GTEST_SKIP() << "https://github.com/AztecProtocol/barretenberg/issues/707";
876+
} else {
877+
TestFixture::test_quad_mul();
878+
};
863879
}
864880
HEAVY_TYPED_TEST(stdlib_biggroup, one)
865881
{
@@ -872,12 +888,20 @@ HEAVY_TYPED_TEST(stdlib_biggroup, batch_mul)
872888
HEAVY_TYPED_TEST(stdlib_biggroup, chain_add)
873889
{
874890

875-
TestFixture::test_chain_add();
891+
if constexpr (HasGoblinBuilder<TypeParam>) {
892+
GTEST_SKIP() << "https://github.com/AztecProtocol/barretenberg/issues/707";
893+
} else {
894+
TestFixture::test_chain_add();
895+
};
876896
}
877897
HEAVY_TYPED_TEST(stdlib_biggroup, multiple_montgomery_ladder)
878898
{
879899

880-
TestFixture::test_multiple_montgomery_ladder();
900+
if constexpr (HasGoblinBuilder<TypeParam>) {
901+
GTEST_SKIP() << "https://github.com/AztecProtocol/barretenberg/issues/707";
902+
} else {
903+
TestFixture::test_multiple_montgomery_ladder();
904+
};
881905
}
882906

883907
HEAVY_TYPED_TEST(stdlib_biggroup, compute_naf)
@@ -897,7 +921,11 @@ HEAVY_TYPED_TEST(stdlib_biggroup, compute_naf)
897921
HEAVY_TYPED_TEST(stdlib_biggroup, wnaf_batch_mul)
898922
{
899923
if constexpr (HasPlookup<typename TypeParam::Curve::Builder>) {
900-
TestFixture::test_compute_wnaf();
924+
if constexpr (HasGoblinBuilder<TypeParam>) {
925+
GTEST_SKIP() << "https://github.com/AztecProtocol/barretenberg/issues/707";
926+
} else {
927+
TestFixture::test_compute_wnaf();
928+
};
901929
} else {
902930
GTEST_SKIP();
903931
}
@@ -921,15 +949,23 @@ HEAVY_TYPED_TEST(stdlib_biggroup, batch_mul_short_scalars)
921949
if constexpr (TypeParam::use_bigfield) {
922950
GTEST_SKIP();
923951
} else {
924-
TestFixture::test_batch_mul_short_scalars();
952+
if constexpr (HasGoblinBuilder<TypeParam>) {
953+
GTEST_SKIP() << "https://github.com/AztecProtocol/barretenberg/issues/707";
954+
} else {
955+
TestFixture::test_batch_mul_short_scalars();
956+
};
925957
}
926958
}
927959
HEAVY_TYPED_TEST(stdlib_biggroup, wnaf_batch_mul_128_bit)
928960
{
929961
if constexpr (TypeParam::use_bigfield) {
930962
GTEST_SKIP();
931963
} else {
932-
TestFixture::test_wnaf_batch_mul_128_bit();
964+
if constexpr (HasGoblinBuilder<TypeParam>) {
965+
GTEST_SKIP() << "https://github.com/AztecProtocol/barretenberg/issues/707";
966+
} else {
967+
TestFixture::test_wnaf_batch_mul_128_bit();
968+
};
933969
}
934970
}
935971
HEAVY_TYPED_TEST(stdlib_biggroup, wnaf_batch_4)
@@ -945,15 +981,23 @@ HEAVY_TYPED_TEST(stdlib_biggroup, wnaf_batch_4)
945981
HEAVY_TYPED_TEST(stdlib_biggroup, bn254_endo_batch_mul)
946982
{
947983
if constexpr (TypeParam::Curve::type == proof_system::CurveType::BN254 && !TypeParam::use_bigfield) {
948-
TestFixture::test_bn254_endo_batch_mul();
984+
if constexpr (HasGoblinBuilder<TypeParam>) {
985+
GTEST_SKIP() << "https://github.com/AztecProtocol/barretenberg/issues/707";
986+
} else {
987+
TestFixture::test_bn254_endo_batch_mul();
988+
};
949989
} else {
950990
GTEST_SKIP();
951991
}
952992
}
953993
HEAVY_TYPED_TEST(stdlib_biggroup, mixed_mul_bn254_endo)
954994
{
955995
if constexpr (TypeParam::Curve::type == proof_system::CurveType::BN254 && !TypeParam::use_bigfield) {
956-
TestFixture::test_mixed_mul_bn254_endo();
996+
if constexpr (HasGoblinBuilder<TypeParam>) {
997+
GTEST_SKIP() << "https://github.com/AztecProtocol/barretenberg/issues/707";
998+
} else {
999+
TestFixture::test_mixed_mul_bn254_endo();
1000+
};
9571001
} else {
9581002
GTEST_SKIP();
9591003
}

barretenberg/cpp/src/barretenberg/stdlib/primitives/biggroup/biggroup_bn254.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ namespace stdlib {
2222
**/
2323
template <class C, class Fq, class Fr, class G>
2424
template <typename, typename>
25+
requires(IsNotGoblinBuilder<C>)
2526
element<C, Fq, Fr, G> element<C, Fq, Fr, G>::bn254_endo_batch_mul_with_generator(
2627
const std::vector<element>& big_points,
2728
const std::vector<Fr>& big_scalars,
@@ -216,6 +217,7 @@ element<C, Fq, Fr, G> element<C, Fq, Fr, G>::bn254_endo_batch_mul_with_generator
216217
**/
217218
template <typename C, class Fq, class Fr, class G>
218219
template <typename, typename>
220+
requires(IsNotGoblinBuilder<C>)
219221
element<C, Fq, Fr, G> element<C, Fq, Fr, G>::bn254_endo_batch_mul(const std::vector<element>& big_points,
220222
const std::vector<Fr>& big_scalars,
221223
const std::vector<element>& small_points,

0 commit comments

Comments
 (0)