-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: expose Grumpkin commitment computation (PROOF-882) (#33)
* feat: initial check in of Grumpkin API * refactor: update grumpkin code to match latest arkworks crates
- Loading branch information
1 parent
5980588
commit afc8e67
Showing
10 changed files
with
261 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
95 changes: 95 additions & 0 deletions
95
docs/commitments/compute_grumpkin_commitments_with_generators.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
Computes the Pedersen commitment for a given input data using `grumpkin` curve elements. | ||
|
||
In total, the function computes `data.len()` commitments, | ||
which is related to the total number of columns in the data table. The commitment | ||
results are stored as 512-bit `grumpkin` curve point in affine form in the `commitments` variable. | ||
|
||
The `j`-th Pedersen commitment is a 512-bit `grumpkin` curve point `C_j` over the | ||
`grumpin` elliptic curve that is cryptographically binded to a data message vector `M_j`. This `M_j` vector is populated according to the type of the `data` given. | ||
|
||
For an input data table specified as a [crate::sequence::Sequence] slice view, we populate `M_j` as follows: | ||
|
||
```text | ||
let el_size = data[j].element_size; // sizeof of each element in the current j-th column | ||
let num_rows = data[j].data_slice.len() / el_size; // number of rows in the j-th column | ||
let M_j = [ | ||
data[j].data_slice[0:el_size], | ||
data[j].data_slice[el_size:2*el_size], | ||
data[j].data_slice[2*el_size:3*el_size], | ||
., | ||
., | ||
., | ||
data[j].data_slice[(num_rows-1)*el_size:num_rows*el_size] | ||
]; | ||
``` | ||
|
||
This message `M_j` cannot be decrypted from `C_j`. The curve point `C_j` | ||
is generated in a unique way using `M_j` and a | ||
set of 768-bit `grumpkin` curve elements in projective form `G_i`, called row generators. | ||
Although our GPU code uses 768-bit generators during the scalar | ||
multiplication, these generators are passed as 512-bit `grumpkin` curve elements in affine form | ||
and only converted to 768-bit projective elements inside the GPU/CPU. | ||
|
||
The total number of generators used to compute `C_j` is equal to | ||
the number of `num_rows` in the `data[j]` sequence. The following formula | ||
is specified to obtain the `C_j` commitment when the input table is a | ||
[crate::sequence::Sequence] view: | ||
|
||
```text | ||
let C_j_temp = 0; // this is a 768-bit grumpkin curve element in projective form | ||
for j in 0..num_rows { | ||
let G_i = generators[j].decompress(); // we decompress to convert 512-bit to 768-bit points | ||
let curr_data_ji = data[j].data_slice[i*el_size:(i + 1)*el_size]; | ||
C_j_temp = C_j_temp + curr_data_ji * G_i; | ||
} | ||
let C_j = into_affine(C_j_temp); // this is a 512-bit grumpkin point | ||
``` | ||
|
||
Ps: the above is only illustrative code. It will not compile. | ||
|
||
Here `curr_data_ji` are simply 256-bit scalars, `C_j_temp` and `G_i` are | ||
768-bit `grumpkin` curve elements in projective form and `C_j` is a 512-bit `grumpkin` point in affine form. | ||
|
||
Given `M_j` and `G_i`, it is easy to verify that the Pedersen | ||
commitment `C_j` is the correctly generated output. However, | ||
the Pedersen commitment generated from `M_j` and `G_i` is cryptographically | ||
binded to the message `M_j` because finding alternative inputs `M_j*` and | ||
`G_i*` for which the Pedersen commitment generates the same point `C_j` | ||
requires an infeasible amount of computation. | ||
|
||
To guarantee proper execution, so that the backend is correctly set, | ||
this `compute_grumpkin_commitments_with_generators` always calls the `init_backend()` function. | ||
|
||
Portions of this documentation were extracted from | ||
[here](findora.org/faq/crypto/pedersen-commitment-with-elliptic-curves/) | ||
|
||
# Arguments | ||
|
||
* `commitments` - A sliced view of an un compressed `grumpkin` curve element memory area where the | ||
512-bit point results will be written to. Please, | ||
you need to guarantee that this slice captures exactly | ||
`data.len()` element positions. | ||
|
||
* `data` - A generic sliced view `T` of a [crate::sequence::Sequence], | ||
which captures the slices of contiguous `u8` memory elements. | ||
You need to guarantee that the contiguous `u8` slice view | ||
captures the correct amount of bytes that can reflect | ||
your desired amount of `num_rows` in the sequence. After all, | ||
we infer the `num_rows` from `data[i].data_slice.len() / data[i].element_size`. | ||
|
||
* `generators` - A sliced view of a `grumpkin` curve affine element memory area where the | ||
512-bit point generators used in the commitment computation are | ||
stored. Bear in mind that the size of this slice must always be greater | ||
or equal to the longest sequence, in terms of rows, in the table. | ||
|
||
# Asserts | ||
|
||
If the longest sequence in the input data is bigger than the generators length, or if | ||
the `data.len()` value is different from the `commitments.len()` value. | ||
|
||
# Panics | ||
|
||
If the compute commitments execution in the GPU / CPU fails. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// Copyright 2023-present Space and Time Labs, Inc. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
use ark_ec::{CurveGroup, VariableBaseMSM}; | ||
use ark_grumpkin::{Affine, Fr, Projective}; | ||
use ark_std::UniformRand; | ||
|
||
extern crate blitzar; | ||
use blitzar::compute::*; | ||
|
||
fn main() { | ||
///////////////////////////////////////////// | ||
// For the following data, we have: | ||
// commitment[0] = gs[0]*data[0] + gs[1]*data[1] + gs[2]*data[2] + gs[3]*data[3] | ||
// | ||
// Those generators `gs` are automatically generated by our CPU/GPU code. | ||
// So we provide an interface to access them. We use the offset to get only | ||
// a subset of the generators used in the gpu/cpu code. | ||
// | ||
// Alternatively, in this example, we provide a generator vector `gs`. | ||
///////////////////////////////////////////// | ||
let data: Vec<u16> = vec![2, 3, 1, 5, 4, 7, 6, 8, 9, 10]; | ||
|
||
///////////////////////////////////////////// | ||
// randomly obtain the generator points | ||
///////////////////////////////////////////// | ||
let mut rng = ark_std::test_rng(); | ||
let generator_points: Vec<Affine> = (0..data.len()).map(|_| Affine::rand(&mut rng)).collect(); | ||
|
||
///////////////////////////////////////////// | ||
// Do the actual commitment computation | ||
///////////////////////////////////////////// | ||
let mut commitments = vec![Affine::default(); 1]; | ||
compute_grumpkin_uncompressed_commitments_with_generators( | ||
&mut commitments, | ||
&[(&data).into()], | ||
&generator_points, | ||
); | ||
|
||
///////////////////////////////////////////// | ||
// Then we use the above generators `gs`, | ||
// as well as the data as scalars | ||
// to verify that those generators `gs` | ||
// are indeed the ones used during the | ||
// commitment computation | ||
///////////////////////////////////////////// | ||
let mut scalar_data: Vec<Fr> = Vec::new(); | ||
for d in &data { | ||
scalar_data.push(Fr::from(*d)); | ||
} | ||
|
||
///////////////////////////////////////////// | ||
// Compute the commitment using Arkworks | ||
///////////////////////////////////////////// | ||
let ark_commitment = Projective::msm(&generator_points, &scalar_data).unwrap(); | ||
|
||
///////////////////////////////////////////// | ||
// Compare Arkworks and our CPU/GPU commitment | ||
///////////////////////////////////////////// | ||
println!("Computed Commitment: {:?}\n", commitments[0]); | ||
println!("Expected Commitment: {:?}\n", ark_commitment.into_affine()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters