Skip to content

Commit

Permalink
C-API missing features (#338)
Browse files Browse the repository at this point in the history
* c-api: add scalar mul on G1 and G2 - followup #332

* add conversion/codecs procs between bigints and field elements

* update Rust bindings
  • Loading branch information
mratsim authored Jan 11, 2024
1 parent 89d32a9 commit 2aac21d
Show file tree
Hide file tree
Showing 13 changed files with 401 additions and 53 deletions.
99 changes: 60 additions & 39 deletions bindings/c_curve_decls.nim
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,39 @@ export curves, curves_primitives, extension_fields
#
# This files provides template for C bindings generation

template genBindingsField*(Field: untyped) =
template genBindingsBig*(Big: untyped) =
when appType == "lib":
{.push noconv, dynlib, exportc, raises: [].} # No exceptions allowed
else:
{.push noconv, exportc, raises: [].} # No exceptions allowed

func `ctt _ Big _ unmarshalBE`(dst: var Big, src: openarray[byte]): bool =
unmarshalBE(dst, src)

func `ctt _ Big _ marshalBE`(dst: var openarray[byte], src: Big): bool =
marshalBE(dst, src)

{.pop.}

template genBindingsField*(Big, Field: untyped) =
when appType == "lib":
{.push noconv, dynlib, exportc, raises: [].} # No exceptions allowed
else:
{.push noconv, exportc, raises: [].} # No exceptions allowed

func `ctt _ Big _ from _ Field`(dst: var Big, src: Field) =
fromField(dst, src)

func `ctt _ Field _ from _ Big`(dst: var Field, src: Big) =
## Note: conversion will not fail if the bigint is bigger than the modulus,
## It will be reduced modulo the field modulus.
## For protocol that want to prevent this malleability
## use `unmarchalBE` to convert directly from bytes to field elements instead of
## bytes -> bigint -> field element
fromBig(dst, src)

# --------------------------------------------------------------------------------------
func `ctt _ Field _ unmarshalBE`(dst: var Field, src: openarray[byte]): bool =
## Deserialize
unmarshalBE(dst, src)

func `ctt _ Field _ marshalBE`(dst: var openarray[byte], src: Field): bool =
Expand Down Expand Up @@ -359,54 +384,50 @@ template genBindings_EC_ShortW_NonAffine*(ECP, ECP_Aff, ScalarBig, ScalarField:
func `ctt _ ECP _ batch_affine`(dst: ptr UncheckedArray[ECP_Aff], src: ptr UncheckedArray[ECP], n: csize_t) =
dst.batchAffine(src, cast[int](n))

when ECP.G == G1:
# Workaround gensym issue in templates like mulCheckSparse
# for {.noInit.} temporaries and probably generic sandwich

func `ctt _ ECP _ scalar_mul_big_coef`(
P: var ECP, scalar: ScalarBig) =
func `ctt _ ECP _ scalar_mul_big_coef`(
P: var ECP, scalar: ScalarBig) =

P.scalarMul(scalar)
P.scalarMul(scalar)

func `ctt _ ECP _ scalar_mul_fr_coef`(
P: var ECP, scalar: ScalarField) =
func `ctt _ ECP _ scalar_mul_fr_coef`(
P: var ECP, scalar: ScalarField) =

var big: ScalarBig # TODO: {.noInit.}
big.fromField(scalar)
P.scalarMul(big)
var big: ScalarBig # TODO: {.noInit.}
big.fromField(scalar)
P.scalarMul(big)

func `ctt _ ECP _ scalar_mul_big_coef_vartime`(
P: var ECP, scalar: ScalarBig) =
func `ctt _ ECP _ scalar_mul_big_coef_vartime`(
P: var ECP, scalar: ScalarBig) =

P.scalarMul_vartime(scalar)
P.scalarMul_vartime(scalar)

func `ctt _ ECP _ scalar_mul_fr_coef_vartime`(
P: var ECP, scalar: ScalarField) =
func `ctt _ ECP _ scalar_mul_fr_coef_vartime`(
P: var ECP, scalar: ScalarField) =

var big: ScalarBig # TODO: {.noInit.}
big.fromField(scalar)
P.scalarMul_vartime(big)
var big: ScalarBig # TODO: {.noInit.}
big.fromField(scalar)
P.scalarMul_vartime(big)

func `ctt _ ECP _ multi_scalar_mul_big_coefs_vartime`(
r: var ECP,
coefs: ptr UncheckedArray[ScalarBig],
points: ptr UncheckedArray[ECP_Aff],
len: csize_t) =
r.multiScalarMul_vartime(coefs, points, cast[int](len))
func `ctt _ ECP _ multi_scalar_mul_big_coefs_vartime`(
r: var ECP,
coefs: ptr UncheckedArray[ScalarBig],
points: ptr UncheckedArray[ECP_Aff],
len: csize_t) =
r.multiScalarMul_vartime(coefs, points, cast[int](len))

func `ctt _ ECP _ multi_scalar_mul_fr_coefs_vartime`(
r: var ECP,
coefs: ptr UncheckedArray[ScalarField],
points: ptr UncheckedArray[ECP_Aff],
len: csize_t)=
func `ctt _ ECP _ multi_scalar_mul_fr_coefs_vartime`(
r: var ECP,
coefs: ptr UncheckedArray[ScalarField],
points: ptr UncheckedArray[ECP_Aff],
len: csize_t)=

let n = cast[int](len)
let coefs_fr = allocHeapArrayAligned(ScalarBig, n, alignment = 64)
let n = cast[int](len)
let coefs_fr = allocHeapArrayAligned(ScalarBig, n, alignment = 64)

for i in 0 ..< n:
coefs_fr[i].fromField(coefs[i])
r.multiScalarMul_vartime(coefs_fr, points, n)
for i in 0 ..< n:
coefs_fr[i].fromField(coefs[i])
r.multiScalarMul_vartime(coefs_fr, points, n)

freeHeapAligned(coefs_fr)
freeHeapAligned(coefs_fr)

{.pop.}
22 changes: 14 additions & 8 deletions bindings/lib_curves.nim
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ export c_curve_decls, c_curve_decls_parallel
type
big254 = BigInt[254]
big255 = BigInt[255]
big381 = BigInt[381]

collectBindings(cBindings_big):
genBindingsBig(big254)
genBindingsBig(big255)
genBindingsBig(big381)

# ----------------------------------------------------------

Expand All @@ -36,8 +42,8 @@ type
bls12_381_g2_prj = ECP_ShortW_Prj[Fp2[BLS12_381], G2]

collectBindings(cBindings_bls12_381):
genBindingsField(bls12_381_fr)
genBindingsField(bls12_381_fp)
genBindingsField(big255, bls12_381_fr)
genBindingsField(big381, bls12_381_fp)
genBindingsFieldSqrt(bls12_381_fp)
genBindingsExtField(bls12_381_fp2)
genBindingsExtFieldSqrt(bls12_381_fp2)
Expand Down Expand Up @@ -65,8 +71,8 @@ type
bn254_snarks_g2_prj = ECP_ShortW_Prj[Fp2[BN254_Snarks], G2]

collectBindings(cBindings_bn254_snarks):
genBindingsField(bn254_snarks_fr)
genBindingsField(bn254_snarks_fp)
genBindingsField(big254, bn254_snarks_fr)
genBindingsField(big254, bn254_snarks_fp)
genBindingsFieldSqrt(bn254_snarks_fp)
genBindingsExtField(bn254_snarks_fp2)
genBindingsExtFieldSqrt(bn254_snarks_fp2)
Expand All @@ -91,8 +97,8 @@ type
pallas_ec_prj = ECP_ShortW_Prj[Fp[Pallas], G1]

collectBindings(cBindings_pallas):
genBindingsField(pallas_fr)
genBindingsField(pallas_fp)
genBindingsField(big255, pallas_fr)
genBindingsField(big255, pallas_fp)
genBindingsFieldSqrt(pallas_fp)
genBindings_EC_ShortW_Affine(pallas_ec_aff, pallas_fp)
genBindings_EC_ShortW_NonAffine(pallas_ec_jac, pallas_ec_aff, big255, pallas_fr)
Expand All @@ -110,8 +116,8 @@ type
vesta_ec_prj = ECP_ShortW_Prj[Fp[Vesta], G1]

collectBindings(cBindings_vesta):
genBindingsField(vesta_fr)
genBindingsField(vesta_fp)
genBindingsField(big255, vesta_fr)
genBindingsField(big255, vesta_fp)
genBindingsFieldSqrt(vesta_fp)
genBindings_EC_ShortW_Affine(vesta_ec_aff, vesta_fp)
genBindings_EC_ShortW_NonAffine(vesta_ec_jac, vesta_ec_aff, big255, vesta_fr)
Expand Down
8 changes: 6 additions & 2 deletions bindings/lib_headers.nim
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ proc writeParallelHeader(dirPath: string, C: static Curve, curve_decls: string)
writeFile(relPath, header)
echo "Generated header: ", relPath

proc writeBigIntHeader(dirPath: string, bigSizes: IntSet) =
proc writeBigIntHeader(dirPath: string, bigSizes: IntSet, big_codecs: string) =
let relPath = dirPath/"constantine"/"curves"/"bigints.h"

var header = "\n"
Expand All @@ -117,6 +117,9 @@ proc writeBigIntHeader(dirPath: string, bigSizes: IntSet) =
header &= genBigInt(size)
header &= '\n'

header &= big_codecs
header &= '\n'

header = "\n" & genCpp(header)
header = genHeaderGuardAndInclude("BIGINTS", header)
header = genHeaderLicense() & header
Expand Down Expand Up @@ -151,9 +154,10 @@ proc writeCurveParallelHeaders(dir: string) =

staticFor i, 0, curveMappings.len:
writeParallelHeader(dir, curveMappings[i][0], curveMappings[i][1])
bigSizes.incl(curveMappings[i][0].getCurveBitWidth())
bigSizes.incl(curveMappings[i][0].getCurveOrderBitWidth())

dir.writeBigIntHeader(bigSizes)
dir.writeBigIntHeader(bigSizes, cBindings_big)

when isMainModule:
proc main() {.inline.} =
Expand Down
102 changes: 102 additions & 0 deletions constantine-rust/constantine-sys/src/bindings32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,36 @@ extern "C" {
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct big381 {
limbs: [secret_word; 12usize],
}
#[test]
fn bindgen_test_layout_big381() {
const UNINIT: ::core::mem::MaybeUninit<big381> = ::core::mem::MaybeUninit::uninit();
let ptr = UNINIT.as_ptr();
assert_eq!(
::core::mem::size_of::<big381>(),
48usize,
concat!("Size of: ", stringify!(big381))
);
assert_eq!(
::core::mem::align_of::<big381>(),
4usize,
concat!("Alignment of ", stringify!(big381))
);
assert_eq!(
unsafe { ::core::ptr::addr_of!((*ptr).limbs) as usize - ptr as usize },
0usize,
concat!(
"Offset of field: ",
stringify!(big381),
"::",
stringify!(limbs)
)
);
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct big255 {
limbs: [secret_word; 8usize],
}
Expand Down Expand Up @@ -182,6 +212,30 @@ fn bindgen_test_layout_big254() {
)
);
}
extern "C" {
#[must_use]
pub fn ctt_big254_unmarshalBE(dst: *mut big254, src: *const byte, src_len: isize) -> bool;
}
extern "C" {
#[must_use]
pub fn ctt_big254_marshalBE(dst: *mut byte, dst_len: isize, src: *const big254) -> bool;
}
extern "C" {
#[must_use]
pub fn ctt_big255_unmarshalBE(dst: *mut big255, src: *const byte, src_len: isize) -> bool;
}
extern "C" {
#[must_use]
pub fn ctt_big255_marshalBE(dst: *mut byte, dst_len: isize, src: *const big255) -> bool;
}
extern "C" {
#[must_use]
pub fn ctt_big381_unmarshalBE(dst: *mut big381, src: *const byte, src_len: isize) -> bool;
}
extern "C" {
#[must_use]
pub fn ctt_big381_marshalBE(dst: *mut byte, dst_len: isize, src: *const big381) -> bool;
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct bls12_381_fr {
Expand Down Expand Up @@ -562,6 +616,12 @@ fn bindgen_test_layout_bls12_381_g2_prj() {
)
);
}
extern "C" {
pub fn ctt_big255_from_bls12_381_fr(dst: *mut big255, src: *const bls12_381_fr);
}
extern "C" {
pub fn ctt_bls12_381_fr_from_big255(dst: *mut bls12_381_fr, src: *const big255);
}
extern "C" {
#[must_use]
pub fn ctt_bls12_381_fr_unmarshalBE(
Expand Down Expand Up @@ -685,6 +745,12 @@ extern "C" {
ctl: secret_bool,
);
}
extern "C" {
pub fn ctt_big381_from_bls12_381_fp(dst: *mut big381, src: *const bls12_381_fp);
}
extern "C" {
pub fn ctt_bls12_381_fp_from_big381(dst: *mut bls12_381_fp, src: *const big381);
}
extern "C" {
#[must_use]
pub fn ctt_bls12_381_fp_unmarshalBE(
Expand Down Expand Up @@ -1850,6 +1916,12 @@ fn bindgen_test_layout_bn254_snarks_g2_prj() {
)
);
}
extern "C" {
pub fn ctt_big254_from_bn254_snarks_fr(dst: *mut big254, src: *const bn254_snarks_fr);
}
extern "C" {
pub fn ctt_bn254_snarks_fr_from_big254(dst: *mut bn254_snarks_fr, src: *const big254);
}
extern "C" {
#[must_use]
pub fn ctt_bn254_snarks_fr_unmarshalBE(
Expand Down Expand Up @@ -1984,6 +2056,12 @@ extern "C" {
ctl: secret_bool,
);
}
extern "C" {
pub fn ctt_big254_from_bn254_snarks_fp(dst: *mut big254, src: *const bn254_snarks_fp);
}
extern "C" {
pub fn ctt_bn254_snarks_fp_from_big254(dst: *mut bn254_snarks_fp, src: *const big254);
}
extern "C" {
#[must_use]
pub fn ctt_bn254_snarks_fp_unmarshalBE(
Expand Down Expand Up @@ -3017,6 +3095,12 @@ fn bindgen_test_layout_pallas_ec_prj() {
)
);
}
extern "C" {
pub fn ctt_big255_from_pallas_fr(dst: *mut big255, src: *const pallas_fr);
}
extern "C" {
pub fn ctt_pallas_fr_from_big255(dst: *mut pallas_fr, src: *const big255);
}
extern "C" {
#[must_use]
pub fn ctt_pallas_fr_unmarshalBE(dst: *mut pallas_fr, src: *const byte, src_len: isize)
Expand Down Expand Up @@ -3113,6 +3197,12 @@ extern "C" {
extern "C" {
pub fn ctt_pallas_fr_csub_in_place(a: *mut pallas_fr, b: *const pallas_fr, ctl: secret_bool);
}
extern "C" {
pub fn ctt_big255_from_pallas_fp(dst: *mut big255, src: *const pallas_fp);
}
extern "C" {
pub fn ctt_pallas_fp_from_big255(dst: *mut pallas_fp, src: *const big255);
}
extern "C" {
#[must_use]
pub fn ctt_pallas_fp_unmarshalBE(dst: *mut pallas_fp, src: *const byte, src_len: isize)
Expand Down Expand Up @@ -3668,6 +3758,12 @@ fn bindgen_test_layout_vesta_ec_prj() {
)
);
}
extern "C" {
pub fn ctt_big255_from_vesta_fr(dst: *mut big255, src: *const vesta_fr);
}
extern "C" {
pub fn ctt_vesta_fr_from_big255(dst: *mut vesta_fr, src: *const big255);
}
extern "C" {
#[must_use]
pub fn ctt_vesta_fr_unmarshalBE(dst: *mut vesta_fr, src: *const byte, src_len: isize) -> bool;
Expand Down Expand Up @@ -3763,6 +3859,12 @@ extern "C" {
extern "C" {
pub fn ctt_vesta_fr_csub_in_place(a: *mut vesta_fr, b: *const vesta_fr, ctl: secret_bool);
}
extern "C" {
pub fn ctt_big255_from_vesta_fp(dst: *mut big255, src: *const vesta_fp);
}
extern "C" {
pub fn ctt_vesta_fp_from_big255(dst: *mut vesta_fp, src: *const big255);
}
extern "C" {
#[must_use]
pub fn ctt_vesta_fp_unmarshalBE(dst: *mut vesta_fp, src: *const byte, src_len: isize) -> bool;
Expand Down
Loading

0 comments on commit 2aac21d

Please sign in to comment.