barretenberg
Loading...
Searching...
No Matches
biggroup_goblin.hpp
1#pragma once
2
3namespace proof_system::plonk {
4namespace stdlib {
5
29template <typename C, class Fq, class Fr, class G>
31 const std::vector<Fr>& scalars,
32 [[maybe_unused]] const size_t max_num_bits)
33{
34 auto builder = points[0].get_context();
35
36 // Check that the internal accumulator is zero?
37 ASSERT(builder->op_queue->get_accumulator().is_point_at_infinity());
38
39 // Loop over all points and scalars
40 size_t num_points = points.size();
41 for (size_t i = 0; i < num_points; ++i) {
42 auto& point = points[i];
43 auto& scalar = scalars[i];
44
45 // Populate the goblin-style ecc op gates for the given mul inputs
46 ecc_op_tuple op_tuple;
47 bool scalar_is_constant_equal_one = scalar.get_witness_index() == IS_CONSTANT && scalar.get_value() == 1;
48 if (scalar_is_constant_equal_one) { // if scalar is 1, there is no need to perform a mul
49 op_tuple = builder->queue_ecc_add_accum(point.get_value());
50 } else { // otherwise, perform a mul-then-accumulate
51 op_tuple = builder->queue_ecc_mul_accum(point.get_value(), scalar.get_value());
52 }
53
54 // Add constraints demonstrating that the EC point coordinates were decomposed faithfully. In particular, show
55 // that the lo-hi components that have been encoded in the op wires can be reconstructed via the limbs of the
56 // original point coordinates.
57 auto x_lo = Fr::from_witness_index(builder, op_tuple.x_lo);
58 auto x_hi = Fr::from_witness_index(builder, op_tuple.x_hi);
59 auto y_lo = Fr::from_witness_index(builder, op_tuple.y_lo);
60 auto y_hi = Fr::from_witness_index(builder, op_tuple.y_hi);
61 // Note: These constraints do not assume or enforce that the coordinates of the original point have been
62 // asserted to be in the field, only that they are less than the smallest power of 2 greater than the field
63 // modulus (a la the bigfield(lo, hi) constructor with can_overflow == false).
64 ASSERT(uint1024_t(point.x.get_maximum_value()) <= Fq::DEFAULT_MAXIMUM_REMAINDER);
65 ASSERT(uint1024_t(point.y.get_maximum_value()) <= Fq::DEFAULT_MAXIMUM_REMAINDER);
66 auto shift = Fr::from_witness(builder, Fq::shift_1);
67 x_lo.assert_equal(point.x.binary_basis_limbs[0].element + shift * point.x.binary_basis_limbs[1].element);
68 x_hi.assert_equal(point.x.binary_basis_limbs[2].element + shift * point.x.binary_basis_limbs[3].element);
69 y_lo.assert_equal(point.y.binary_basis_limbs[0].element + shift * point.y.binary_basis_limbs[1].element);
70 y_hi.assert_equal(point.y.binary_basis_limbs[2].element + shift * point.y.binary_basis_limbs[3].element);
71
72 // Add constraints demonstrating proper decomposition of scalar into endomorphism scalars
73 if (!scalar_is_constant_equal_one) {
74 auto z_1 = Fr::from_witness_index(builder, op_tuple.z_1);
75 auto z_2 = Fr::from_witness_index(builder, op_tuple.z_2);
76 auto beta = G::subgroup_field::cube_root_of_unity();
77 scalar.assert_equal(z_1 - z_2 * beta);
78 }
79 }
80
81 // Populate equality gates based on the internal accumulator point
82 auto op_tuple = builder->queue_ecc_eq();
83
84 // Reconstruct the result of the batch mul using indices into the variables array
85 auto x_lo = Fr::from_witness_index(builder, op_tuple.x_lo);
86 auto x_hi = Fr::from_witness_index(builder, op_tuple.x_hi);
87 auto y_lo = Fr::from_witness_index(builder, op_tuple.y_lo);
88 auto y_hi = Fr::from_witness_index(builder, op_tuple.y_hi);
89 Fq point_x(x_lo, x_hi);
90 Fq point_y(y_lo, y_hi);
91
92 return element(point_x, point_y);
93}
94
95} // namespace stdlib
96} // namespace proof_system::plonk
Definition: biggroup.hpp:22
static element goblin_batch_mul(const std::vector< element > &points, const std::vector< Fr > &scalars, const size_t max_num_bits=0)
Goblin style batch multiplication.
Definition: biggroup_goblin.hpp:30
Definition: widget.bench.cpp:13
Definition: gate_data.hpp:64