40 const std::vector<Fr>& scalars,
41 [[maybe_unused]]
const size_t max_num_bits,
42 [[maybe_unused]]
const bool handle_edge_cases,
43 [[maybe_unused]]
const Fr& masking_scalar)
45 auto builder = validate_context<C>(validate_context<C>(points), validate_context<C>(scalars));
47 BB_ASSERT(
builder !=
nullptr,
"biggroup_goblin: builder context is invalid.");
48 BB_ASSERT(points.size() == scalars.size(),
"biggroup_goblin: points and scalars lengths not equal.");
54 size_t num_points = points.size();
57 for (
size_t i = 0; i < num_points; ++i) {
58 auto& point = points[i];
59 auto& scalar = scalars[i];
63 tag_union =
OriginTag(tag_union,
OriginTag(point.get_origin_tag(), scalar.get_origin_tag()));
66 bool scalar_is_constant_equal_one = scalar.is_constant() && scalar.get_value() == 1;
67 if (scalar_is_constant_equal_one) {
68 op_tuple =
builder->queue_ecc_add_accum(point.get_value());
70 op_tuple =
builder->queue_ecc_mul_accum(point.get_value(), scalar.get_value());
76 auto x_lo = Fr::from_witness_index(
builder, op_tuple.
x_lo);
77 auto x_hi = Fr::from_witness_index(
builder, op_tuple.
x_hi);
78 auto y_lo = Fr::from_witness_index(
builder, op_tuple.
y_lo);
79 auto y_hi = Fr::from_witness_index(
builder, op_tuple.
y_hi);
83 if (!point.get_value().is_point_at_infinity()) {
87 x_lo.assert_equal(point._x.limbs[0]);
88 x_hi.assert_equal(point._x.limbs[1]);
89 y_lo.assert_equal(point._y.limbs[0]);
90 y_hi.assert_equal(point._y.limbs[1]);
93 if (!scalar_is_constant_equal_one) {
94 auto z_1 = Fr::from_witness_index(
builder, op_tuple.
z_1);
95 auto z_2 = Fr::from_witness_index(
builder, op_tuple.
z_2);
97 scalar.assert_equal(z_1 - z_2 * beta);
105 if (scalar_is_constant_equal_one) {
106 builder->update_used_witnesses({ op_tuple.
z_1, op_tuple.
z_2 });
110 auto op_tuple =
builder->queue_ecc_eq();
114 builder->update_used_witnesses({ op_tuple.z_1, op_tuple.z_2 });
116 auto x_lo = Fr::from_witness_index(
builder, op_tuple.x_lo);
117 auto x_hi = Fr::from_witness_index(
builder, op_tuple.x_hi);
118 auto y_lo = Fr::from_witness_index(
builder, op_tuple.y_lo);
119 auto y_hi = Fr::from_witness_index(
builder, op_tuple.y_hi);
120 Fq point_x(x_lo, x_hi);
121 Fq point_y(y_lo, y_hi);
128 auto op2_is_infinity = (x_lo.add_two(x_hi, y_lo) + y_hi).is_zero();
static goblin_element batch_mul(const std::vector< goblin_element > &points, const std::vector< Fr > &scalars, const size_t max_num_bits=0, const bool handle_edge_cases=false, const Fr &masking_scalar=Fr(1))
Goblin style batch multiplication.