From 3e3f57a76de58bbcf65856224534d10525366a5c Mon Sep 17 00:00:00 2001 From: Mamy Ratsimbazafy Date: Sat, 29 Jun 2024 22:36:24 +0200 Subject: [PATCH] feat(ux): out-of-place syntactic sugar --- ARCHITECTURE.md | 18 +++ PLANNING.md | 44 +++---- constantine/hash_to_curve/hash_to_curve.nim | 8 +- constantine/lowlevel_elliptic_curves.nim | 13 ++ constantine/lowlevel_fields.nim | 15 +++ constantine/math/arithmetic/finite_fields.nim | 51 +++++++- constantine/math/elliptic/ec_scalar_mul.nim | 52 ++++++++ .../math/elliptic/ec_scalar_mul_vartime.nim | 62 ++++++++++ .../elliptic/ec_shortweierstrass_jacobian.nim | 117 ++++++++++++++++++ .../ec_shortweierstrass_projective.nim | 101 +++++++++++++++ .../elliptic/ec_twistededwards_projective.nim | 117 ++++++++++++++++++ constantine/math/extension_fields/towers.nim | 38 ++++++ constantine/math/polynomials/polynomials.nim | 2 +- .../math/polynomials/polynomials_parallel.nim | 2 +- tests/math_fields/t_finite_fields.nim | 6 +- 15 files changed, 606 insertions(+), 40 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 3243383c..5125e3be 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -30,6 +30,24 @@ and prefer mutable out parameters. on large inputs like `Fp12[BLS12_381]` 48\*12 bytes = 576 bytes. 4. As we sometimes return SecretBool or status code, this keeps the API consistent. +Syntactic sugar through out-of-place arithmetic functions like `+` and `*` +is available for rapid prototyping, testing and debugging. + +For elliptic curves, variable time functions are prefixed with a tilde like +`~+` `~-` and `~*`. + +They SHOULD NOT be use in performance-critical or stack space critical +subroutines. +- They should be tagged {.inline, noInit.} and just forward to the in-place function + to guarantee copy elision. (and even then it's not guaranteed) +- Issues: + - Extremely inefficient codegen in Constantine itself https://github.com/mratsim/constantine/issues/145 + with useless moves instead of in-place construction. + - In other languages like Rust, users have seen a dramatic 20% increase in performance by moving from out-of-place to in-place mutation: https://www.reddit.com/r/rust/comments/kfs0oe/comment/ggc0dui/ + - And they are struggling with GCE (Guarenteed Copy Elision) and NRVO/RVO(Named) Return Value Optimization + - https://github.com/rust-lang/rust/pull/76986 + - https://github.com/rust-lang/rfcs/pull/2884 + ## Code organization TBD diff --git a/PLANNING.md b/PLANNING.md index a4a8cbe1..cfeae65c 100644 --- a/PLANNING.md +++ b/PLANNING.md @@ -12,20 +12,20 @@ Other tracks are stretch goals, contributions towards them are accepted. - [Constantine's planning](#constantines-planning) - - [Table of Contents](#table-of-contents) - - [Tracks](#tracks) - - [Tech debt track](#tech-debt-track) - - [Ethereum Consensus Track](#ethereum-consensus-track) - - [Ethereum Execution Track](#ethereum-execution-track) - - [Proving Ethereum track](#proving-ethereum-track) - - [Optimization track](#optimization-track) - - [User Experience track](#user-experience-track) - - [Technical marketing track](#technical-marketing-track) - - [ZK and proof systems track](#zk-and-proof-systems-track) - - [Multi-party computation MPC track](#multi-party-computation-mpc-track) - - [Core crypto track](#core-crypto-track) - - [Fully-Homomorphic encryption FHE track](#fully-homomorphic-encryption-fhe-track) - - [Post-Quantum cryptography PQC track](#post-quantum-cryptography-pqc-track) + - [Table of Contents](#table-of-contents) + - [Tracks](#tracks) + - [Tech debt track](#tech-debt-track) + - [Ethereum Consensus Track](#ethereum-consensus-track) + - [Ethereum Execution Track](#ethereum-execution-track) + - [Proving Ethereum track](#proving-ethereum-track) + - [Optimization track](#optimization-track) + - [User Experience track](#user-experience-track) + - [Technical marketing track](#technical-marketing-track) + - [ZK and proof systems track](#zk-and-proof-systems-track) + - [Multi-party computation (MPC) track](#multi-party-computation-mpc-track) + - [Core crypto track](#core-crypto-track) + - [Fully-Homomorphic encryption (FHE) track](#fully-homomorphic-encryption-fhe-track) + - [Post-Quantum cryptography (PQC) track](#post-quantum-cryptography-pqc-track) @@ -102,21 +102,7 @@ Other tracks are stretch goals, contributions towards them are accepted. ### User Experience track -- Provide curves_sugar and fields_sugar higher-level with - out-of-place functions like `+` and `*`. - - They should be tagged {.inline, noInit.} and just forward to the in-place function - to guarantee copy elision. - - Mention lack of control over stack space - - Guaranteed optimization issue - - with even up to a dramatic 20% perf: - - https://www.reddit.com/r/rust/comments/kfs0oe/comment/ggc0dui/ - - past Constantine large copy bug: - - out-of-place function lead to bad codegen: - - https://github.com/mratsim/constantine/issues/145 - - https://github.com/nim-lang/Nim/issues/16897 - - Mention Rust GCE and NRVO / RVO - - https://github.com/rust-lang/rust/pull/76986 - - https://github.com/rust-lang/rfcs/pull/2884 +Create a "Constantine book" to introduce Constantine concepts and walkthrough available protocols. ### Technical marketing track diff --git a/constantine/hash_to_curve/hash_to_curve.nim b/constantine/hash_to_curve/hash_to_curve.nim index 2c89f525..e33db164 100644 --- a/constantine/hash_to_curve/hash_to_curve.nim +++ b/constantine/hash_to_curve/hash_to_curve.nim @@ -54,11 +54,11 @@ func mapToCurve_svdw[F, G]( tv1 *= h2cConst(F.Name, svdw, G, curve_eq_rhs_Z) tv2 = tv1 when F is Fp: - tv2 += F(mres: F.getMontyOne()) - tv1.diff(F(mres: F.getMontyOne()), tv1) + tv2 += F.getOne() + tv1.diff(F.getOne(), tv1) else: - tv2.c0 += Fp[F.F.Name](mres: Fp[F.F.Name].getMontyOne()) - tv1.c0.diff(Fp[F.F.Name](mres: Fp[F.F.Name].getMontyOne()), tv1.c0) + tv2.c0 += Fp[F.F.Name].getOne() + tv1.c0.diff(Fp[F.F.Name].getOne(), tv1.c0) tv1.c1.neg() tv3.prod(tv1, tv2) tv3.inv() diff --git a/constantine/lowlevel_elliptic_curves.nim b/constantine/lowlevel_elliptic_curves.nim index e1b39cc6..d1430498 100644 --- a/constantine/lowlevel_elliptic_curves.nim +++ b/constantine/lowlevel_elliptic_curves.nim @@ -85,3 +85,16 @@ export zoo_subgroups.isInSubgroup # ------------------------------------------------------------ export hash_to_curve.hash_to_curve + +# Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers +# tend to generate useless memory moves or have difficulties to minimize stack allocation +# and our types might be large (Fp12 ...) +# See: https://github.com/mratsim/constantine/issues/145 +# +# They are intended for rapid prototyping, testing and debugging. +export ec_shortweierstrass.`+` +export ec_shortweierstrass.`-` +export ec_shortweierstrass.`~+` +export ec_shortweierstrass.`~-` +export ec_shortweierstrass.`*` +export ec_shortweierstrass.`~*` diff --git a/constantine/lowlevel_fields.nim b/constantine/lowlevel_fields.nim index 230dd315..c5f87fc8 100644 --- a/constantine/lowlevel_fields.nim +++ b/constantine/lowlevel_fields.nim @@ -73,6 +73,10 @@ export arithmetic.setZero export arithmetic.setOne export arithmetic.setMinusOne +export arithmetic.getZero +export arithmetic.getOne +export arithmetic.getMinusOne + export arithmetic.neg export arithmetic.sum export arithmetic.`+=` @@ -102,3 +106,14 @@ export arithmetic.sqrt_invsqrt_if_square export arithmetic.sqrt_if_square export arithmetic.invsqrt_if_square export arithmetic.sqrt_ratio_if_square + + +# Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers +# tend to generate useless memory moves or have difficulties to minimize stack allocation +# and our types might be large (Fp12 ...) +# See: https://github.com/mratsim/constantine/issues/145 +# +# They are intended for rapid prototyping, testing and debugging. +export arithmetic.`+` +export arithmetic.`-` +export arithmetic.`*` diff --git a/constantine/math/arithmetic/finite_fields.nim b/constantine/math/arithmetic/finite_fields.nim index e8210984..25dab2f6 100644 --- a/constantine/math/arithmetic/finite_fields.nim +++ b/constantine/math/arithmetic/finite_fields.nim @@ -150,7 +150,6 @@ func setMinusOne*(a: var FF) = # Check if the compiler optimizes it away a.mres = FF.getMontyPrimeMinus1() - func neg*(r: var FF, a: FF) {.meter.} = ## Negate modulo p when UseASM_X86_64 and a.mres.limbs.len <= 6: # TODO: handle spilling @@ -872,3 +871,53 @@ func batchInv_vartime*[F](dst: var openArray[F], source: openArray[F]) {.inline. func batchInv_vartime*[N: static int, F](dst: var array[N, F], src: array[N, F]) = batchInv_vartime(dst.asUnchecked(), src.asUnchecked(), N) + +# ############################################################ +# +# Out-of-Place functions +# +# ############################################################ +# +# Except from the constant function getZero, getOne, getMinusOne +# out-of-place functions are intended for rapid prototyping, debugging and testing. +# +# They SHOULD NOT be used in performance-critical subroutines as compilers +# tend to generate useless memory moves or have difficulties to minimize stack allocation +# and our types might be large (Fp12 ...) +# See: https://github.com/mratsim/constantine/issues/145 + +func getZero*(T: type FF): T {.inline.} = + discard + +func getOne*(T: type FF): T {.noInit, inline.} = + cast[ptr T](T.getMontyOne().unsafeAddr)[] + +func getMinusOne*(T: type FF): T {.noInit, inline.} = + cast[ptr T](T.getMontyPrimeMinus1().unsafeAddr)[] + +func `+`*(a, b: FF): FF {.noInit, inline.} = + ## Finite Field addition + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.sum(a, b) + +func `-`*(a, b: FF): FF {.noInit, inline.} = + ## Finite Field addition + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.diff(a, b) + +func `*`*(a, b: FF): FF {.noInit, inline.} = + ## Finite Field substraction + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.prod(a, b) diff --git a/constantine/math/elliptic/ec_scalar_mul.nim b/constantine/math/elliptic/ec_scalar_mul.nim index 76b3de5f..4a8b0554 100644 --- a/constantine/math/elliptic/ec_scalar_mul.nim +++ b/constantine/math/elliptic/ec_scalar_mul.nim @@ -291,3 +291,55 @@ func scalarMul*[EC; Ecaff: not EC](R: var EC, scalar: Fr or BigInt, P: ECaff) {. ## Those will be assumed to maintain constant-time property R.fromAffine(P) R.scalarMul(scalar) + +# ############################################################ +# +# Out-of-Place functions +# +# ############################################################ +# +# Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers +# tend to generate useless memory moves or have difficulties to minimize stack allocation +# and our types might be large (Fp12 ...) +# See: https://github.com/mratsim/constantine/issues/145 + +func `*`*[EC: EC_ShortW_Jac or EC_ShortW_Prj or EC_TwEdw_Prj]( + scalar: Fr or BigInt, P: EC): EC {.noInit, inline.} = + ## Elliptic Curve Scalar Multiplication + ## + ## R <- [k] P + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.scalarMul(scalar, P) + +func `*`*[F, G]( + scalar: Fr or BigInt, + P: EC_ShortW_Aff[F, G], + T: typedesc[EC_ShortW_Jac[F, G] or EC_ShortW_Prj[F, G]] + ): T {.noInit, inline.} = + ## Elliptic Curve Scalar Multiplication + ## + ## R <- [k] P + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.scalarMul(scalar, P) + +func `*`*[F, G]( + scalar: Fr or BigInt, + P: EC_ShortW_Aff[F, G] + ): EC_ShortW_Jac[F, G] {.noInit, inline.} = + ## Elliptic Curve Scalar Multiplication + ## + ## R <- [k] P + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.scalarMul(scalar, P) diff --git a/constantine/math/elliptic/ec_scalar_mul_vartime.nim b/constantine/math/elliptic/ec_scalar_mul_vartime.nim index 7e6f9a54..397c6e5e 100644 --- a/constantine/math/elliptic/ec_scalar_mul_vartime.nim +++ b/constantine/math/elliptic/ec_scalar_mul_vartime.nim @@ -11,6 +11,8 @@ import ./ec_shortweierstrass_affine, ./ec_shortweierstrass_jacobian, ./ec_shortweierstrass_projective, + ./ec_twistededwards_affine, + ./ec_twistededwards_projective, ./ec_endomorphism_accel, ./ec_shortweierstrass_batch_ops, ./ec_twistededwards_batch_ops, @@ -409,3 +411,63 @@ func scalarMul_vartime*[EC; Ecaff: not EC](R: var EC, scalar: Fr or BigInt, P: E ## Those conditions will be assumed. R.fromAffine(P) R.scalarMul_vartime(scalar) + +# ############################################################ +# +# Out-of-Place functions +# +# ############################################################ +# +# Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers +# tend to generate useless memory moves or have difficulties to minimize stack allocation +# and our types might be large (Fp12 ...) +# See: https://github.com/mratsim/constantine/issues/145 + +func `~*`*[EC: EC_ShortW_Jac or EC_ShortW_Prj or EC_TwEdw_Prj]( + scalar: Fr or BigInt, P: EC): EC {.noInit, inline.} = + ## Elliptic Curve variable-time Scalar Multiplication + ## + ## R <- [k] P + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.scalarMul_vartime(scalar, P) + +func `~*`*[F, G]( + scalar: Fr or BigInt, + P: EC_ShortW_Aff[F, G], + T: typedesc[EC_ShortW_Jac[F, G] or EC_ShortW_Prj[F, G]] + ): T {.noInit, inline.} = + ## Elliptic Curve variable-time Scalar Multiplication + ## + ## R <- [k] P + ## + ## This MUST NOT be used with secret data. + ## + ## This is highly VULNERABLE to timing attacks and power analysis attacks. + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.scalarMul_vartime(scalar, P) + +func `~*`*[F, G]( + scalar: Fr or BigInt, + P: EC_ShortW_Aff[F, G], + ): EC_ShortW_Jac[F, G] {.noInit, inline.} = + ## Elliptic Curve variable-time Scalar Multiplication + ## + ## R <- [k] P + ## + ## This MUST NOT be used with secret data. + ## + ## This is highly VULNERABLE to timing attacks and power analysis attacks. + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.scalarMul_vartime(scalar, P) diff --git a/constantine/math/elliptic/ec_shortweierstrass_jacobian.nim b/constantine/math/elliptic/ec_shortweierstrass_jacobian.nim index b944aae0..19936e0c 100644 --- a/constantine/math/elliptic/ec_shortweierstrass_jacobian.nim +++ b/constantine/math/elliptic/ec_shortweierstrass_jacobian.nim @@ -935,3 +935,120 @@ template `~-=`*(P: var EC_ShortW_Jac, Q: EC_ShortW_Jac) = template `~-=`*(P: var EC_ShortW_Jac, Q: EC_ShortW_Aff) = P.mixedDiff_vartime(P, Q) + +# ############################################################ +# +# Out-of-Place functions +# +# ############################################################ +# +# Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers +# tend to generate useless memory moves or have difficulties to minimize stack allocation +# and our types might be large (Fp12 ...) +# See: https://github.com/mratsim/constantine/issues/145 + +func `+`*(a, b: EC_ShortW_Jac): EC_ShortW_Jac {.noInit, inline.} = + ## Elliptic curve addition + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.sum(a, b) + +func `+`*(a: EC_ShortW_Jac, b: EC_ShortW_Aff): EC_ShortW_Jac {.noInit, inline.} = + ## Elliptic curve addition + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.mixedSum(a, b) + +func `~+`*(a, b: EC_ShortW_Jac): EC_ShortW_Jac {.noInit, inline.} = + ## Elliptic curve variable-time addition + ## + ## This MUST NOT be used with secret data. + ## + ## This is highly VULNERABLE to timing attacks and power analysis attacks. + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.sum_vartime(a, b) + +func `~+`*(a: EC_ShortW_Jac, b: EC_ShortW_Aff): EC_ShortW_Jac {.noInit, inline.} = + ## Elliptic curve variable-time addition + ## + ## This MUST NOT be used with secret data. + ## + ## This is highly VULNERABLE to timing attacks and power analysis attacks. + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.mixedSum_vartime(a, b) + +func `-`*(a, b: EC_ShortW_Jac): EC_ShortW_Jac {.noInit, inline.} = + ## Elliptic curve substraction + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.diff(a, b) + +func `-`*(a: EC_ShortW_Jac, b: EC_ShortW_Aff): EC_ShortW_Jac {.noInit, inline.} = + ## Elliptic curve addition + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.mixedDiff(a, b) + +func `~-`*(a, b: EC_ShortW_Jac): EC_ShortW_Jac {.noInit, inline.} = + ## Elliptic curve variable-time substraction + ## + ## This MUST NOT be used with secret data. + ## + ## This is highly VULNERABLE to timing attacks and power analysis attacks. + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.diff_vartime(a, b) + +func `~-`*(a: EC_ShortW_Jac, b: EC_ShortW_Aff): EC_ShortW_Jac {.noInit, inline.} = + ## Elliptic curve variable-time substraction + ## + ## This MUST NOT be used with secret data. + ## + ## This is highly VULNERABLE to timing attacks and power analysis attacks.] + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.mixedDiff_vartime(a, b) + +func getAffine*[F, G](jac: EC_ShortW_Jac[F, G]): EC_ShortW_Aff[F, G] {.noInit, inline.} = + ## Jacobian to Affine conversion + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.affine(jac) + +func getJacobian*[F, G](aff: EC_ShortW_Aff[F, G]): EC_ShortW_Jac[F, G] {.noInit, inline.} = + ## Affine to Jacobian conversion + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.fromAffine(aff) diff --git a/constantine/math/elliptic/ec_shortweierstrass_projective.nim b/constantine/math/elliptic/ec_shortweierstrass_projective.nim index 0364ca5b..d4c68f1f 100644 --- a/constantine/math/elliptic/ec_shortweierstrass_projective.nim +++ b/constantine/math/elliptic/ec_shortweierstrass_projective.nim @@ -698,3 +698,104 @@ template `~-=`*(P: var EC_ShortW_Prj, Q: EC_ShortW_Prj) = template `~-=`*(P: var EC_ShortW_Prj, Q: EC_ShortW_Aff) = P.mixedDiff_vartime(P, Q) + +# ############################################################ +# +# Out-of-Place functions +# +# ############################################################ +# +# Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers +# tend to generate useless memory moves or have difficulties to minimize stack allocation +# and our types might be large (Fp12 ...) +# See: https://github.com/mratsim/constantine/issues/145 + +func `+`*(a, b: EC_ShortW_Prj): EC_ShortW_Prj {.noInit, inline.} = + ## Elliptic curve addition + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.sum(a, b) + +func `+`*(a: EC_ShortW_Prj, b: EC_ShortW_Aff): EC_ShortW_Prj {.noInit, inline.} = + ## Elliptic curve addition + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.mixedSum(a, b) + +func `~+`*(a, b: EC_ShortW_Prj): EC_ShortW_Prj {.noInit, inline.} = + ## Elliptic curve variable-time addition + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.sum_vartime(a, b) + +func `~+`*(a: EC_ShortW_Prj, b: EC_ShortW_Aff): EC_ShortW_Prj {.noInit, inline.} = + ## Elliptic curve variable-time addition + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.mixedSum_vartime(a, b) + +func `-`*(a, b: EC_ShortW_Prj): EC_ShortW_Prj {.noInit, inline.} = + ## Elliptic curve substraction + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.diff(a, b) + +func `-`*(a: EC_ShortW_Prj, b: EC_ShortW_Aff): EC_ShortW_Prj {.noInit, inline.} = + ## Elliptic curve substraction + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.mixedDiff(a, b) + +func `~-`*(a, b: EC_ShortW_Prj): EC_ShortW_Prj {.noInit, inline.} = + ## Elliptic curve variable-time substraction + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.diff_vartime(a, b) + +func `~-`*(a: EC_ShortW_Prj, b: EC_ShortW_Aff): EC_ShortW_Prj {.noInit, inline.} = + ## Elliptic curve variable-time substraction + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.mixedDiff_vartime(a, b) + +func getAffine*[F, G](prj: EC_ShortW_Prj[F, G]): EC_ShortW_Aff[F, G] {.noInit, inline.} = + ## Projective to Affine conversion + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.affine(prj) + +func getProjective*[F, G](aff: EC_ShortW_Aff[F, G]): EC_ShortW_Prj[F, G] {.noInit, inline.} = + ## Affine to Projective conversion + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.fromAffine(aff) diff --git a/constantine/math/elliptic/ec_twistededwards_projective.nim b/constantine/math/elliptic/ec_twistededwards_projective.nim index f16313a2..7fedf1d4 100644 --- a/constantine/math/elliptic/ec_twistededwards_projective.nim +++ b/constantine/math/elliptic/ec_twistededwards_projective.nim @@ -539,3 +539,120 @@ func isNeutral*(P: EC_TwEdw_Prj[Fp[Banderwagon]]): SecretBool {.inline.} = # TODO: Rename the function result = P.x.isZero() + +# ############################################################ +# +# Out-of-Place functions +# +# ############################################################ +# +# Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers +# tend to generate useless memory moves or have difficulties to minimize stack allocation +# and our types might be large (Fp12 ...) +# See: https://github.com/mratsim/constantine/issues/145 + +func `+`*(a, b: EC_TwEdw_Prj): EC_TwEdw_Prj {.noInit, inline.} = + ## Elliptic curve addition + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.sum(a, b) + +func `+`*(a: EC_TwEdw_Prj, b: EC_TwEdw_Aff): EC_TwEdw_Prj {.noInit, inline.} = + ## Elliptic curve addition + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.mixedSum(a, b) + +func `~+`*(a, b: EC_TwEdw_Prj): EC_TwEdw_Prj {.noInit, inline.} = + ## Elliptic curve variable-time addition + ## + ## This MUST NOT be used with secret data. + ## + ## This is highly VULNERABLE to timing attacks and power analysis attacks. + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.sum_vartime(a, b) + +func `~+`*(a: EC_TwEdw_Prj, b: EC_TwEdw_Aff): EC_TwEdw_Prj {.noInit, inline.} = + ## Elliptic curve variable-time addition + ## + ## This MUST NOT be used with secret data. + ## + ## This is highly VULNERABLE to timing attacks and power analysis attacks. + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.mixedSum_vartime(a, b) + +func `-`*(a, b: EC_TwEdw_Prj): EC_TwEdw_Prj {.noInit, inline.} = + ## Elliptic curve substraction + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.diff(a, b) + +func `-`*(a: EC_TwEdw_Prj, b: EC_TwEdw_Aff): EC_TwEdw_Prj {.noInit, inline.} = + ## Elliptic curve substraction + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.mixedDiff(a, b) + +func `~-`*(a, b: EC_TwEdw_Prj): EC_TwEdw_Prj {.noInit, inline.} = + ## Elliptic curve variable-time substraction + ## + ## This MUST NOT be used with secret data. + ## + ## This is highly VULNERABLE to timing attacks and power analysis attacks. + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.diff_vartime(a, b) + +func `~-`*(a: EC_TwEdw_Prj, b: EC_TwEdw_Aff): EC_TwEdw_Prj {.noInit, inline.} = + ## Elliptic curve variable-time substraction + ## + ## This MUST NOT be used with secret data. + ## + ## This is highly VULNERABLE to timing attacks and power analysis attacks. + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.mixedDiff_vartime(a, b) + +func getAffine*[F](prj: EC_TwEdw_Prj[F]): EC_TwEdw_Aff[F] {.noInit, inline.} = + ## Projective to Affine conversion + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.affine(prj) + +func getProjective*[F](aff: EC_TwEdw_Aff[F]): EC_TwEdw_Prj[F] {.noInit, inline.} = + ## Affine to Projective conversion + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.fromAffine(aff) diff --git a/constantine/math/extension_fields/towers.nim b/constantine/math/extension_fields/towers.nim index d2768473..b70fa255 100644 --- a/constantine/math/extension_fields/towers.nim +++ b/constantine/math/extension_fields/towers.nim @@ -2250,5 +2250,43 @@ func inv_vartime*(a: var ExtensionField) {.tags:[VarTime].} = ## to affine for elliptic curve a.invImpl(a, useVartime = true) +# ############################################################ +# +# Out-of-Place functions +# +# ############################################################ +# +# They SHOULD NOT be used in performance-critical subroutines as compilers +# tend to generate useless memory moves or have difficulties to minimize stack allocation +# and our types might be large (Fp12 ...) +# See: https://github.com/mratsim/constantine/issues/145 + +func `+`*(a, b: ExtensionField): ExtensionField {.noInit, inline.} = + ## Finite Field addition + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.sum(a, b) + +func `-`*(a, b: ExtensionField): ExtensionField {.noInit, inline.} = + ## Finite Field addition + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.diff(a, b) + +func `*`*(a, b: ExtensionField): ExtensionField {.noInit, inline.} = + ## Finite Field substraction + ## + ## Out-of-place functions SHOULD NOT be used in performance-critical subroutines as compilers + ## tend to generate useless memory moves or have difficulties to minimize stack allocation + ## and our types might be large (Fp12 ...) + ## See: https://github.com/mratsim/constantine/issues/145 + result.prod(a, b) + {.pop.} # inline {.pop.} # raises no exceptions diff --git a/constantine/math/polynomials/polynomials.nim b/constantine/math/polynomials/polynomials.nim index e6e6fb36..b74406a0 100644 --- a/constantine/math/polynomials/polynomials.nim +++ b/constantine/math/polynomials/polynomials.nim @@ -300,7 +300,7 @@ func evalPolyOffDomainAt*[N: static int, Field]( t = z const numDoublings = log2_vartime(uint32 N) # N is a power of 2 t.square_repeated(int numDoublings) # exponentiation by a power of 2 - t.diff(Field(mres: Field.getMontyOne()), t) # TODO: refactor getMontyOne to getOne and return a field element. + t.diff(Field.getOne(), t) r *= t r *= domain.invMaxDegree diff --git a/constantine/math/polynomials/polynomials_parallel.nim b/constantine/math/polynomials/polynomials_parallel.nim index 50cac08b..17397ca2 100644 --- a/constantine/math/polynomials/polynomials_parallel.nim +++ b/constantine/math/polynomials/polynomials_parallel.nim @@ -60,7 +60,7 @@ proc evalPolyOffDomainAt_parallel*[N: static int, Field]( t = z[] const numDoublings = log2_vartime(uint32 N) # N is a power of 2 t.square_repeated(int numDoublings) # exponentiation by a power of 2 - t.diff(Field(mres: Field.getMontyOne()), t) # TODO: refactor getMontyOne to getOne and return a field element. + t.diff(Field.getOne(), t) r.prod(t, domain.invMaxDegree) r *= sync(globalSum) diff --git a/tests/math_fields/t_finite_fields.nim b/tests/math_fields/t_finite_fields.nim index 07742fe4..cdbbb52f 100644 --- a/tests/math_fields/t_finite_fields.nim +++ b/tests/math_fields/t_finite_fields.nim @@ -320,8 +320,7 @@ proc largeField() = test "fromMont doesn't need a final substraction with 256-bit prime (full word used)": block: - var a: Fp[Secp256k1] - a.mres = Fp[Secp256k1].getMontyPrimeMinus1() + let a = Fp[Secp256k1].getOne() let expected = BigInt[256].fromHex"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2E" var r: BigInt[256] @@ -345,8 +344,7 @@ proc largeField() = test "fromMont doesn't need a final substraction with 255-bit prime (1 spare bit)": block: - var a: Fp[Edwards25519] - a.mres = Fp[Edwards25519].getMontyPrimeMinus1() + let a = Fp[Edwards25519].getOne() let expected = BigInt[255].fromHex"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffec" var r: BigInt[255]