Skip to content

Commit

Permalink
Implements g2_add and g2_scalar_mul via garaga_rs
Browse files Browse the repository at this point in the history
  • Loading branch information
raugfer committed Aug 7, 2024
1 parent 330d46f commit 064c8f9
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 46 deletions.
1 change: 1 addition & 0 deletions tools/garaga_rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pyo3 = { version = "0.15", features = ["extension-module", "num-bigint"] }
num-bigint = "0.4"
ark-bn254 = "0.4"
ark-bls12-381 = "0.4"
ark-ec = "0.4"
ark-ff = "0.4"

lambdaworks-crypto = { git = "https://github.com/lambdaclass/lambdaworks.git" }
Expand Down
9 changes: 2 additions & 7 deletions tools/garaga_rs/src/bls12_381_final_exp_witness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ mod tests {
}

fn gcd(a: &BigInt, b: &BigInt) -> BigInt {
assert!(a > BigInt::from(0) && b > BigInt::from(0));
let mut a = a.clone();
let mut b = b.clone();
while b != BigInt::from(0) {
Expand All @@ -98,14 +99,8 @@ mod tests {
}

fn to_words_le(bigint: &BigInt) -> Vec<u64> {
let (sign, bytes) = bigint.to_bytes_le();
let (sign, words) = bigint.to_u64_digits();
assert!(sign != num_bigint::Sign::Minus);
let mut words = Vec::with_capacity((bytes.len() + 7) / 8);
for chunk in bytes.chunks(8) {
let mut word = [0u8; 8];
word[..chunk.len()].copy_from_slice(chunk);
words.push(u64::from_le_bytes(word));
}
return words;
}
}
9 changes: 2 additions & 7 deletions tools/garaga_rs/src/bn254_final_exp_witness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ mod tests {
}

fn gcd(a: &BigInt, b: &BigInt) -> BigInt {
assert!(a > BigInt::from(0) && b > BigInt::from(0));
let mut a = a.clone();
let mut b = b.clone();
while b != BigInt::from(0) {
Expand All @@ -197,14 +198,8 @@ mod tests {
}

fn to_words_le(bigint: &BigInt) -> Vec<u64> {
let (sign, bytes) = bigint.to_bytes_le();
let (sign, words) = bigint.to_u64_digits();
assert!(sign != num_bigint::Sign::Minus);
let mut words = Vec::with_capacity((bytes.len() + 7) / 8);
for chunk in bytes.chunks(8) {
let mut word = [0u8; 8];
word[..chunk.len()].copy_from_slice(chunk);
words.push(u64::from_le_bytes(word));
}
return words;
}

Expand Down
101 changes: 98 additions & 3 deletions tools/garaga_rs/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub mod bn254_final_exp_witness;
pub mod bls12_381_final_exp_witness;

use ark_ec::AffineRepr;
use ark_ff::PrimeField;
use num_bigint::BigUint;
use lambdaworks_crypto::hash::poseidon::{starknet::PoseidonCairoStark252, Poseidon};
Expand All @@ -11,17 +12,111 @@ use lambdaworks_math::{
traits::ByteConversion,
};
use pyo3::{
types::{PyBytes, PyList, PyTuple},
types::{PyBytes, PyInt, PyList, PyTuple},
{prelude::*, wrap_pyfunction},
};

#[pymodule]
fn garaga_rs(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(g2_add, m)?)?;
m.add_function(wrap_pyfunction!(g2_scalar_mul, m)?)?;
m.add_function(wrap_pyfunction!(get_final_exp_witness, m)?)?;
m.add_function(wrap_pyfunction!(hades_permutation, m)?)?;
Ok(())
}

const CURVE_BN254: usize = 0;
const CURVE_BLS12_381: usize = 1;

#[pyfunction]
fn g2_add(py: Python, curve_id: usize, py_tuple_1: &PyTuple, py_tuple_2: &PyTuple) -> PyResult<PyObject> {
let a_0: BigUint = py_tuple_1[0].extract()?;
let a_1: BigUint = py_tuple_1[1].extract()?;
let a_2: BigUint = py_tuple_1[2].extract()?;
let a_3: BigUint = py_tuple_1[3].extract()?;
let b_0: BigUint = py_tuple_2[0].extract()?;
let b_1: BigUint = py_tuple_2[1].extract()?;
let b_2: BigUint = py_tuple_2[2].extract()?;
let b_3: BigUint = py_tuple_2[3].extract()?;

if curve_id == CURVE_BN254 {
use ark_bn254::{Fq, Fq2, G2Affine};
let a = G2Affine::new(
Fq2::new(Fq::from(a_0), Fq::from(a_1)),
Fq2::new(Fq::from(a_2), Fq::from(a_3)),
);
let b = G2Affine::new(
Fq2::new(Fq::from(b_0), Fq::from(b_1)),
Fq2::new(Fq::from(b_2), Fq::from(b_3)),
);
let c: G2Affine = (a + b).into();
let py_tuple = PyTuple::new(py, [
BigUint::from(c.x.c0.into_bigint()), BigUint::from(c.x.c1.into_bigint()),
BigUint::from(c.y.c0.into_bigint()), BigUint::from(c.y.c1.into_bigint()),
]);
return Ok(py_tuple.into());
}

if curve_id == CURVE_BLS12_381 {
use ark_bls12_381::{Fq, Fq2, G2Affine};
let a = G2Affine::new(
Fq2::new(Fq::from(a_0), Fq::from(a_1)),
Fq2::new(Fq::from(a_2), Fq::from(a_3)),
);
let b = G2Affine::new(
Fq2::new(Fq::from(b_0), Fq::from(b_1)),
Fq2::new(Fq::from(b_2), Fq::from(b_3)),
);
let c: G2Affine = (a + b).into();
let py_tuple = PyTuple::new(py, [
BigUint::from(c.x.c0.into_bigint()), BigUint::from(c.x.c1.into_bigint()),
BigUint::from(c.y.c0.into_bigint()), BigUint::from(c.y.c1.into_bigint()),
]);
return Ok(py_tuple.into());
}

panic!("Curve ID {} not supported", curve_id);
}

#[pyfunction]
fn g2_scalar_mul(py: Python, curve_id: usize, py_tuple_1: &PyTuple, py_int_2: &PyInt) -> PyResult<PyObject> {
let a_0: BigUint = py_tuple_1[0].extract()?;
let a_1: BigUint = py_tuple_1[1].extract()?;
let a_2: BigUint = py_tuple_1[2].extract()?;
let a_3: BigUint = py_tuple_1[3].extract()?;
let k: BigUint = py_int_2.extract()?;

if curve_id == CURVE_BN254 {
use ark_bn254::{Fq, Fq2, G2Affine};
let a = G2Affine::new(
Fq2::new(Fq::from(a_0), Fq::from(a_1)),
Fq2::new(Fq::from(a_2), Fq::from(a_3)),
);
let c: G2Affine = a.mul_bigint(k.to_u64_digits()).into();
let py_tuple = PyTuple::new(py, [
BigUint::from(c.x.c0.into_bigint()), BigUint::from(c.x.c1.into_bigint()),
BigUint::from(c.y.c0.into_bigint()), BigUint::from(c.y.c1.into_bigint()),
]);
return Ok(py_tuple.into());
}

if curve_id == CURVE_BLS12_381 {
use ark_bls12_381::{Fq, Fq2, G2Affine};
let a = G2Affine::new(
Fq2::new(Fq::from(a_0), Fq::from(a_1)),
Fq2::new(Fq::from(a_2), Fq::from(a_3)),
);
let c: G2Affine = a.mul_bigint(k.to_u64_digits()).into();
let py_tuple = PyTuple::new(py, [
BigUint::from(c.x.c0.into_bigint()), BigUint::from(c.x.c1.into_bigint()),
BigUint::from(c.y.c0.into_bigint()), BigUint::from(c.y.c1.into_bigint()),
]);
return Ok(py_tuple.into());
}

panic!("Curve ID {} not supported", curve_id);
}

#[pyfunction]
fn get_final_exp_witness(py: Python, curve_id: usize, py_list: &PyList) -> PyResult<PyObject> {
let f_0: BigUint = py_list[0].extract()?;
Expand All @@ -37,7 +132,7 @@ fn get_final_exp_witness(py: Python, curve_id: usize, py_list: &PyList) -> PyRes
let f_10: BigUint = py_list[10].extract()?;
let f_11: BigUint = py_list[11].extract()?;

if curve_id == 0 { // BN254
if curve_id == CURVE_BN254 {
use ark_bn254::{Fq, Fq2, Fq6, Fq12};
let f = Fq12::new(
Fq6::new(
Expand Down Expand Up @@ -66,7 +161,7 @@ fn get_final_exp_witness(py: Python, curve_id: usize, py_list: &PyList) -> PyRes
return Ok(py_tuple.into());
}

if curve_id == 1 { // BLS12_381
if curve_id == CURVE_BLS12_381 {
use ark_bls12_381::{Fq, Fq2, Fq6, Fq12};
let f = Fq12::new(
Fq6::new(
Expand Down
35 changes: 6 additions & 29 deletions tools/gnark_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import subprocess
from hydra.definitions import G1Point, G2Point, CurveID, CURVES
from hydra.hints.tower_backup import E12

import garaga_rs

class GnarkCLI:
def __init__(self, curve_id: CurveID):
Expand Down Expand Up @@ -83,36 +83,13 @@ def g2_add(
p1: tuple[tuple[int, int], tuple[int, int]],
p2: tuple[tuple[int, int], tuple[int, int]],
):
args = [
"g2",
"add",
str(p1[0][0]),
str(p1[0][1]),
str(p1[1][0]),
str(p1[1][1]),
str(p2[0][0]),
str(p2[0][1]),
str(p2[1][0]),
str(p2[1][1]),
]
output = self.run_command(args)
res = self.parse_fp_elements(output)
assert len(res) == 4, f"Got {output}"
return (res[0], res[1], res[2], res[3])
arg1 = (p1[0][0], p1[0][1], p1[1][0], p1[1][1])
arg2 = (p2[0][0], p2[0][1], p2[1][0], p2[1][1])
return garaga_rs.g2_add(self.curve.id, arg1, arg2)

def g2_scalarmul(self, p1: tuple[tuple[int, int], tuple[int, int]], n: int):
args = [
"ng2",
str(p1[0][0]),
str(p1[0][1]),
str(p1[1][0]),
str(p1[1][1]),
str(n),
]
output = self.run_command(args)
res = self.parse_fp_elements(output)
assert len(res) == 4, f"Got {output}"
return (res[0], res[1], res[2], res[3])
arg1 = (p1[0][0], p1[0][1], p1[1][0], p1[1][1])
return garaga_rs.g2_scalar_mul(self.curve.id, arg1, n)

def nG1nG2_operation(
self, n1: int, n2: int, raw: bool = False
Expand Down

0 comments on commit 064c8f9

Please sign in to comment.