# # the `alt-bn128` elliptic curve # # See for example # # p = 21888242871839275222246405745257275088696311157297823662689037894645226208583 # r = 21888242871839275222246405745257275088548364400416034343698204186575808495617 # # equation: y^2 = x^3 + 3 # import sugar import std/bitops import std/strutils import std/sequtils import std/streams import std/random import constantine/math/arithmetic import constantine/math/io/io_fields import constantine/math/io/io_bigints import constantine/math/config/curves import constantine/math/config/type_ff as tff import constantine/math/extension_fields/towers as ext import constantine/math/elliptic/ec_shortweierstrass_affine as aff import constantine/math/elliptic/ec_shortweierstrass_projective as prj import constantine/math/pairings/pairings_bn as ate import constantine/math/elliptic/ec_scalar_mul as scl # import constantine/math/elliptic/ec_multi_scalar_mul as msm #------------------------------------------------------------------------------- type B* = BigInt[256] type Fr* = tff.Fr[BN254Snarks] type Fp* = tff.Fp[BN254Snarks] type Fp2* = ext.QuadraticExt[Fp] type Fp12* = ext.Fp12[BN254Snarks] type G1* = aff.ECP_ShortW_Aff[Fp , aff.G1] type G2* = aff.ECP_ShortW_Aff[Fp2, aff.G2] type ProjG1* = prj.ECP_ShortW_Prj[Fp , prj.G1] type ProjG2* = prj.ECP_ShortW_Prj[Fp2, prj.G2] func mkFp2* (i: Fp, u: Fp) : Fp2 = let c : array[2, Fp] = [i,u] return ext.QuadraticExt[Fp]( coords: c ) func unsafeMkG1* ( X, Y: Fp ) : G1 = return aff.ECP_ShortW_Aff[Fp, aff.G1](x: X, y: Y) func unsafeMkG2* ( X, Y: Fp2 ) : G2 = return aff.ECP_ShortW_Aff[Fp2, aff.G2](x: X, y: Y) #------------------------------------------------------------------------------- func pairing* (p: G1, q: G2) : Fp12 = var t : Fp12 pairing_bn( t, p, q ) return t #------------------------------------------------------------------------------- const primeP* : B = fromHex( B, "0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47", bigEndian ) const primeR* : B = fromHex( B, "0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001", bigEndian ) #------------------------------------------------------------------------------- const zeroFp* : Fp = fromHex( Fp, "0x00" ) const zeroFr* : Fr = fromHex( Fr, "0x00" ) const oneFp* : Fp = fromHex( Fp, "0x01" ) const oneFr* : Fr = fromHex( Fr, "0x01" ) const zeroFp2* : Fp2 = mkFp2( zeroFp, zeroFp ) const oneFp2* : Fp2 = mkFp2( oneFp , zeroFp ) const infG1* : G1 = unsafeMkG1( zeroFp , zeroFp ) const infG2* : G2 = unsafeMkG2( zeroFp2 , zeroFp2 ) #------------------------------------------------------------------------------- func intToFp*(a: int): Fp = var y : Fp y.fromInt(a) return y func intToFr*(a: int): Fr = var y : Fr y.fromInt(a) return y #------------------------------------------------------------------------------- func isZeroFp*(x: Fp): bool = bool(isZero(x)) func isZeroFr*(x: Fr): bool = bool(isZero(x)) func isEquaLFp*(x, y: Fp): bool = bool(x == y) func isEquaLFr*(x, y: Fr): bool = bool(x == y) #------------------------------------------------------------------------------- func `+`*(x, y: Fp): Fp = ( var z : Fp = x ; z += y ; return z ) func `+`*(x, y: Fr): Fr = ( var z : Fr = x ; z += y ; return z ) func `-`*(x, y: Fp): Fp = ( var z : Fp = x ; z -= y ; return z ) func `-`*(x, y: Fr): Fr = ( var z : Fr = x ; z -= y ; return z ) func `*`*(x, y: Fp): Fp = ( var z : Fp = x ; z *= y ; return z ) func `*`*(x, y: Fr): Fr = ( var z : Fr = x ; z *= y ; return z ) func negFp*(y: Fp): Fp = ( var z : Fp = zeroFp ; z -= y ; return z ) func negFr*(y: Fr): Fr = ( var z : Fr = zeroFr ; z -= y ; return z ) func invFp*(y: Fp): Fp = ( var z : Fp = y ; inv(z) ; return z ) func invFr*(y: Fr): Fr = ( var z : Fr = y ; inv(z) ; return z ) # template/generic instantiation of `pow_vartime` from here # /Users/bkomuves/.nimble/pkgs/constantine-0.0.1/constantine/math/arithmetic/finite_fields.nim(389, 7) template/generic instantiation of `fieldMod` from here # /Users/bkomuves/.nimble/pkgs/constantine-0.0.1/constantine/math/config/curves_prop_field_derived.nim(67, 5) Error: undeclared identifier: 'getCurveOrder' # ... func smallPowFr*(base: Fr, expo: uint): Fr = var a : Fr = oneFr var s : Fr = base var e : uint = expo while (e > 0): if bitand(e,1) > 0: a *= s e = (e shr 1) square(s) return a func smallPowFr*(base: Fr, expo: int): Fr = if expo >= 0: return smallPowFr( base, uint(expo) ) else: return smallPowFr( invFr(base) , uint(-expo) ) #------------------------------------------------------------------------------- func toDecimalBig*[n](a : BigInt[n]): string = var s : string = toDecimal(a) s = s.strip( leading=true, trailing=false, chars={'0'} ) if s.len == 0: s="0" return s func toDecimalFp*(a : Fp): string = var s : string = toDecimal(a) s = s.strip( leading=true, trailing=false, chars={'0'} ) if s.len == 0: s="0" return s func toDecimalFr*(a : Fr): string = var s : string = toDecimal(a) s = s.strip( leading=true, trailing=false, chars={'0'} ) if s.len == 0: s="0" return s #------------------------------------------------------------------------------- proc debugPrintFp*(prefix: string, x: Fp) = echo(prefix & toDecimalFp(x)) proc debugPrintFp2*(prefix: string, z: Fp2) = echo(prefix & " 1 ~> " & toDecimalFp(z.coords[0])) echo(prefix & " u ~> " & toDecimalFp(z.coords[1])) proc debugPrintFr*(prefix: string, x: Fr) = echo(prefix & toDecimalFr(x)) proc debugPrintFrSeq*(msg: string, xs: seq[Fr]) = echo "---------------------" echo msg for x in xs: debugPrintFr( " " , x ) proc debugPrintG1*(msg: string, pt: G1) = echo(msg & ":") debugPrintFp( " x = ", pt.x ) debugPrintFp( " y = ", pt.y ) proc debugPrintG2*(msg: string, pt: G2) = echo(msg & ":") debugPrintFp2( " x = ", pt.x ) debugPrintFp2( " y = ", pt.y ) #------------------------------------------------------------------------------- # Montgomery batch inversion func batchInverse*( xs: seq[Fr] ) : seq[Fr] = let n = xs.len assert(n>0) var us : seq[Fr] = newSeq[Fr](n+1) var a = xs[0] us[0] = oneFr us[1] = a for i in 1..