EC (Multi)-Scalar Multiplication
Last updated
Last updated
For a given elliptic curve, scalar multiplication consists of adding a point P
to itself s
times, where P
is a point satisfying the curve equation and s
a scalar.
k.P = P+P+P+...+P (k times)
Multi scalar multiplication consists of the sum of n
scalar multiplication with different points and scalars :
A single msm_g1
function in Garaga computes the multi-scalar multiplication for a given set of points and scalars for a given elliptic curve. Since it also works with n=1
, it is also able to compute a single scalar multiplication.
Additional points in the msm_g1 function are much less expensive than combining different msm_g1 with n=1
The function will be importable using
As you can see, this function not only needs points and scalars, but also additional information, to perform the computation much more efficiently.
Under tools/starknet/tests_and_calldata_generator/
, you will find in the file msm.py
some tools to generate a cairo test (using MSMCalldataBuilder.to_cairo1_test()
) for this function given some points and scalars, or directly the raw calldata for starknet usage (using MSMCalldataBuilder.serialize_to_calldata()
).
An example contract is already deployed on sepolia, solely holding an endpoint to this function.
The source code to the contract is here .
You can try this deployed contract on any supported curves modifying the msm.py
script at the end :
The options are :
include_digits_decomposition
. This needs 162 additional felt252 per additional scalar, but it saves a lot of cairo steps. If set to False
, the Cairo function will compute them directly in Cairo. If set to True
, the Cairo program will verify the correctness of the decomposition (which is cheaper) and use it.
include_points_and_scalars
: If set to False
, the input points, scalars, and curve_index
will not be part of the calldata.
serialize_as_pure_felt252_array
: If set to True
, preprend the total length of the calldata at the beginning.
The last two options are only useful when you want to use points and scalars from another source than the calldata.
For example, checkout the groth16 verifier contracts. It makes a delegated call to the endpoint msm_g1
using the already declared contract's class hash, and pushes the (fixed) points from the hardcoded verifying key, and the scalars from the groth16 proof. :
Here the msm_hint
is used with include_points_and_scalars=False
and serialize_as_pure_felt252_array=True
Then the points from ic
are pushed to the array, and the scalars from the groth16 proof's public inputs. Finally the curve identifier is pushed as well.
In our example, we'll leave the default parameters that will include everything for a direct endpoint call.
Simply run :
And copy paste the array in voyager to see!