Barretenberg
The ZK-SNARK library at the core of Aztec
|
#include <scalar_multiplication.hpp>
Classes | |
struct | AffineAdditionData |
Temp data structure, one created per thread! More... | |
struct | BucketAccumulators |
Temp data structure, one created per thread! More... | |
struct | JacobianBucketAccumulators |
struct | MSMData |
struct | MSMWorkUnit |
MSMWorkUnit describes an MSM that may be part of a larger MSM. More... | |
Public Types | |
using | Element = typename Curve::Element |
using | ScalarField = typename Curve::ScalarField |
using | BaseField = typename Curve::BaseField |
using | AffineElement = typename Curve::AffineElement |
using | G1 = AffineElement |
using | ThreadWorkUnits = std::vector< MSMWorkUnit > |
Static Public Member Functions | |
static size_t | get_num_rounds (size_t num_points) noexcept |
static void | add_affine_points (AffineElement *points, const size_t num_points, typename Curve::BaseField *scratch_space) noexcept |
static void | transform_scalar_and_get_nonzero_scalar_indices (std::span< typename Curve::ScalarField > scalars, std::vector< uint32_t > &consolidated_indices) noexcept |
Convert scalar out of Montgomery form. Populate consolidated_indices with nonzero scalar indices. | |
static std::vector< ThreadWorkUnits > | get_work_units (std::vector< std::span< ScalarField > > &scalars, std::vector< std::vector< uint32_t > > &msm_scalar_indices) noexcept |
Split a multiple multi-scalar-multiplication into equal units of work that can be processed by threads. | |
static uint32_t | get_scalar_slice (const ScalarField &scalar, size_t round, size_t normal_slice_size) noexcept |
Given a scalar that is NOT in Montgomery form, extract a slice_size -bit chunk. | |
static size_t | get_optimal_log_num_buckets (const size_t num_points) noexcept |
For a given number of points, compute the optimal Pippenger bucket size. | |
static bool | use_affine_trick (const size_t num_points, const size_t num_buckets) noexcept |
Given a number of points and an optimal bucket size, should we use the affine trick? | |
static Element | small_pippenger_low_memory_with_transformed_scalars (MSMData &msm_data) noexcept |
Top-level Pippenger algorithm where number of points is small and we are not using the Affine trick. | |
static Element | pippenger_low_memory_with_transformed_scalars (MSMData &msm_data) noexcept |
Top-level Pippenger algorithm. | |
static Element | evaluate_small_pippenger_round (MSMData &msm_data, const size_t round_index, JacobianBucketAccumulators &bucket_data, Element previous_round_output, const size_t bits_per_slice) noexcept |
Evaluate a single Pippenger round when we do not use the Affine trick. | |
static Element | evaluate_pippenger_round (MSMData &msm_data, const size_t round_index, AffineAdditionData &affine_data, BucketAccumulators &bucket_data, Element previous_round_output, const size_t bits_per_slice) noexcept |
Evaluate a single Pippenger round where we use the affine trick. | |
static void | consume_point_schedule (std::span< const uint64_t > point_schedule, std::span< const AffineElement > points, AffineAdditionData &affine_data, BucketAccumulators &bucket_data, size_t num_input_points_processed, size_t num_queued_affine_points) noexcept |
Given a list of points and target buckets to add into, perform required group operations. | |
static std::vector< AffineElement > | batch_multi_scalar_mul (std::vector< std::span< const AffineElement > > &points, std::vector< std::span< ScalarField > > &scalars, bool handle_edge_cases=true) noexcept |
Compute multiple multi-scalar multiplications. | |
static AffineElement | msm (std::span< const AffineElement > points, PolynomialSpan< const ScalarField > _scalars, bool handle_edge_cases=false) noexcept |
Helper method to evaluate a single MSM. Internally calls batch_multi_scalar_mul | |
template<typename BucketType > | |
static Element | accumulate_buckets (BucketType &bucket_accumulators) noexcept |
Static Public Attributes | |
static constexpr size_t | NUM_BITS_IN_FIELD = ScalarField::modulus.get_msb() + 1 |
Definition at line 15 of file scalar_multiplication.hpp.
using bb::scalar_multiplication::MSM< Curve >::AffineElement = typename Curve::AffineElement |
Definition at line 20 of file scalar_multiplication.hpp.
using bb::scalar_multiplication::MSM< Curve >::BaseField = typename Curve::BaseField |
Definition at line 19 of file scalar_multiplication.hpp.
using bb::scalar_multiplication::MSM< Curve >::Element = typename Curve::Element |
Definition at line 17 of file scalar_multiplication.hpp.
using bb::scalar_multiplication::MSM< Curve >::G1 = AffineElement |
Definition at line 22 of file scalar_multiplication.hpp.
using bb::scalar_multiplication::MSM< Curve >::ScalarField = typename Curve::ScalarField |
Definition at line 18 of file scalar_multiplication.hpp.
using bb::scalar_multiplication::MSM< Curve >::ThreadWorkUnits = std::vector<MSMWorkUnit> |
Definition at line 37 of file scalar_multiplication.hpp.
|
inlinestaticnoexcept |
Definition at line 132 of file scalar_multiplication.hpp.
|
staticnoexcept |
The trick is to compute the product x_1x_2...x_n , whilst storing all of the temporary products. i.e. we have an array A = [x_1, x_1x_2, ..., x_1x_2...x_n] We then compute a single inverse: I = 1 / x_1x_2...x_n Finally, we can use our accumulated products, to quotient out individual inverses. We can get an individual inverse at index i, by computing I.A_{i-1}.(x_nx_n-1...x_i+1) The last product term we can compute on-the-fly, as it grows by one element for each additional inverse that we require.
TLDR: amortized cost of a modular inverse is 3 field multiplications per inverse. Which means we can compute a point addition with SIX field multiplications in total. The traditional Jacobian-coordinate formula requires 11.
There is a catch though - we need large sequences of independent point additions! i.e. the output from one point addition in the sequence is NOT an input to any other point addition in the sequence.
We can re-arrange the Pippenger algorithm to get this property, but it's...complicated
Curve |
points | points to be added pairwise; result is stored in the latter half of the array |
num_points | |
scratch_space | coordinate field scratch space needed for batched inversion |
Definition at line 328 of file scalar_multiplication.cpp.
|
staticnoexcept |
Compute multiple multi-scalar multiplications.
If we need to perform multiple MSMs, this method will be more efficient than calling msm
repeatedly This is because this method will be able to dispatch equal work to all threads without splitting the input msms up so much. The Pippenger algorithm runtime is O(N/log(N)) so there will be slight gains as each inner-thread MSM will have a larger N
Curve |
points | |
scalars |
Definition at line 763 of file scalar_multiplication.cpp.
|
staticnoexcept |
Given a list of points and target buckets to add into, perform required group operations.
This algorithm uses exclusively affine group operations, using batch inversions to amortise costs
Curve |
point_schedule | |
points | |
affine_data | |
bucket_data | |
num_input_points_processed | |
num_queued_affine_points |
Definition at line 561 of file scalar_multiplication.cpp.
|
staticnoexcept |
Evaluate a single Pippenger round where we use the affine trick.
Curve |
msm_data | |
round_index | |
affine_data | |
bucket_data | |
previous_round_output | |
bits_per_slice |
Definition at line 497 of file scalar_multiplication.cpp.
|
staticnoexcept |
Evaluate a single Pippenger round when we do not use the Affine trick.
Curve |
msm_data | |
round_index | |
bucket_data | |
previous_round_output | |
bits_per_slice |
Definition at line 441 of file scalar_multiplication.cpp.
|
inlinestaticnoexcept |
Definition at line 85 of file scalar_multiplication.hpp.
|
staticnoexcept |
For a given number of points, compute the optimal Pippenger bucket size.
Curve |
num_points |
Definition at line 232 of file scalar_multiplication.cpp.
|
staticnoexcept |
Given a scalar that is NOT in Montgomery form, extract a slice_size
-bit chunk.
At round i, we extract slice_size * (i-1)
to slice_sice * i
most significant bits.
Curve |
scalar | |
round | |
normal_slice_size |
Definition at line 201 of file scalar_multiplication.cpp.
|
staticnoexcept |
Split a multiple multi-scalar-multiplication into equal units of work that can be processed by threads.
The goal is to compute the total number of multiplications needed, and assign each thread a set of MSMs such that each thread performs equivalent work. We will split up an MSM into multiple MSMs if this is required.
Curve |
scalars | |
msm_scalar_indices |
Definition at line 117 of file scalar_multiplication.cpp.
|
staticnoexcept |
Helper method to evaluate a single MSM. Internally calls batch_multi_scalar_mul
Curve |
points | |
_scalars |
Definition at line 846 of file scalar_multiplication.cpp.
|
staticnoexcept |
Top-level Pippenger algorithm.
Curve |
msm_data |
Definition at line 405 of file scalar_multiplication.cpp.
|
staticnoexcept |
Top-level Pippenger algorithm where number of points is small and we are not using the Affine trick.
Curve |
msm_data |
Definition at line 380 of file scalar_multiplication.cpp.
|
staticnoexcept |
Convert scalar out of Montgomery form. Populate consolidated_indices
with nonzero scalar indices.
Curve |
scalars | |
consolidated_indices |
Definition at line 55 of file scalar_multiplication.cpp.
|
staticnoexcept |
Given a number of points and an optimal bucket size, should we use the affine trick?
Curve |
num_points | |
num_buckets |
Definition at line 261 of file scalar_multiplication.cpp.
|
staticconstexpr |
Definition at line 23 of file scalar_multiplication.hpp.