Rename Fq -> Fp
This commit is contained in:
parent
3bd70991d4
commit
6b05c69652
|
@ -8,17 +8,21 @@
|
||||||
|
|
||||||
# ############################################################
|
# ############################################################
|
||||||
#
|
#
|
||||||
# Fq: Finite Field arithmetic over Q
|
# Fp: Finite Field arithmetic with prime field modulus P
|
||||||
#
|
#
|
||||||
# ############################################################
|
# ############################################################
|
||||||
|
|
||||||
# We assume that q is known at compile-time
|
# Constraints:
|
||||||
# We assume that q is not even:
|
# - We assume that p is known at compile-time
|
||||||
# - Operations are done in the Montgomery domain
|
# - We assume that p is not even:
|
||||||
# - The Montgomery domain introduce a Montgomery constant that must be coprime
|
# - Operations are done in the Montgomery domain
|
||||||
# with the field modulus.
|
# - The Montgomery domain introduce a Montgomery constant that must be coprime
|
||||||
# - The constant is chosen a power of 2
|
# with the field modulus.
|
||||||
# => to be coprime with a power of 2, q must be odd
|
# - The constant is chosen a power of 2
|
||||||
|
# => to be coprime with a power of 2, p must be odd
|
||||||
|
# - We assume that p is a prime
|
||||||
|
# - Modular inversion uses the Fermat's little theorem
|
||||||
|
# which requires a prime
|
||||||
|
|
||||||
import
|
import
|
||||||
../primitives/constant_time,
|
../primitives/constant_time,
|
||||||
|
@ -28,21 +32,21 @@ import
|
||||||
from ../io/io_bigints import exportRawUint # for "pow"
|
from ../io/io_bigints import exportRawUint # for "pow"
|
||||||
|
|
||||||
# type
|
# type
|
||||||
# `Fq`*[C: static Curve] = object
|
# `Fp`*[C: static Curve] = object
|
||||||
# ## All operations on a field are modulo P
|
# ## All operations on a field are modulo P
|
||||||
# ## P being the prime modulus of the Curve C
|
# ## P being the prime modulus of the Curve C
|
||||||
# ## Internally, data is stored in Montgomery n-residue form
|
# ## Internally, data is stored in Montgomery n-residue form
|
||||||
# ## with the magic constant chosen for convenient division (a power of 2 depending on P bitsize)
|
# ## with the magic constant chosen for convenient division (a power of 2 depending on P bitsize)
|
||||||
# mres*: matchingBigInt(C)
|
# mres*: matchingBigInt(C)
|
||||||
export Fq # defined in ../config/curves to avoid recursive module dependencies
|
export Fp # defined in ../config/curves to avoid recursive module dependencies
|
||||||
|
|
||||||
debug:
|
debug:
|
||||||
func `==`*(a, b: Fq): CTBool[Word] =
|
func `==`*(a, b: Fp): CTBool[Word] =
|
||||||
## Returns true if 2 big ints are equal
|
## Returns true if 2 big ints are equal
|
||||||
a.mres == b.mres
|
a.mres == b.mres
|
||||||
|
|
||||||
func `$`*[C: static Curve](a: Fq[C]): string =
|
func `$`*[C: static Curve](a: Fp[C]): string =
|
||||||
result = "Fq[" & $C
|
result = "Fp[" & $C
|
||||||
result.add "]("
|
result.add "]("
|
||||||
result.add $a.mres
|
result.add $a.mres
|
||||||
result.add ')'
|
result.add ')'
|
||||||
|
@ -57,18 +61,18 @@ debug:
|
||||||
#
|
#
|
||||||
# ############################################################
|
# ############################################################
|
||||||
|
|
||||||
func fromBig*[C: static Curve](T: type Fq[C], src: BigInt): Fq[C] {.noInit.} =
|
func fromBig*[C: static Curve](T: type Fp[C], src: BigInt): Fp[C] {.noInit.} =
|
||||||
## Convert a BigInt to its Montgomery form
|
## Convert a BigInt to its Montgomery form
|
||||||
result.mres.montyResidue(src, C.Mod.mres, C.getR2modP(), C.getNegInvModWord())
|
result.mres.montyResidue(src, C.Mod.mres, C.getR2modP(), C.getNegInvModWord())
|
||||||
|
|
||||||
func fromBig*[C: static Curve](dst: var Fq[C], src: BigInt) {.noInit.} =
|
func fromBig*[C: static Curve](dst: var Fp[C], src: BigInt) {.noInit.} =
|
||||||
## Convert a BigInt to its Montgomery form
|
## Convert a BigInt to its Montgomery form
|
||||||
dst.mres.montyResidue(src, C.Mod.mres, C.getR2modP(), C.getNegInvModWord())
|
dst.mres.montyResidue(src, C.Mod.mres, C.getR2modP(), C.getNegInvModWord())
|
||||||
|
|
||||||
func toBig*(src: Fq): auto {.noInit.} =
|
func toBig*(src: Fp): auto {.noInit.} =
|
||||||
## Convert a finite-field element to a BigInt in natral representation
|
## Convert a finite-field element to a BigInt in natral representation
|
||||||
var r {.noInit.}: typeof(src.mres)
|
var r {.noInit.}: typeof(src.mres)
|
||||||
r.redc(src.mres, Fq.C.Mod.mres, Fq.C.getNegInvModWord())
|
r.redc(src.mres, Fp.C.Mod.mres, Fp.C.getNegInvModWord())
|
||||||
return r
|
return r
|
||||||
|
|
||||||
# ############################################################
|
# ############################################################
|
||||||
|
@ -77,7 +81,7 @@ func toBig*(src: Fq): auto {.noInit.} =
|
||||||
#
|
#
|
||||||
# ############################################################
|
# ############################################################
|
||||||
|
|
||||||
template add(a: var Fq, b: Fq, ctl: CTBool[Word]): CTBool[Word] =
|
template add(a: var Fp, b: Fp, ctl: CTBool[Word]): CTBool[Word] =
|
||||||
## Constant-time big integer in-place optional addition
|
## Constant-time big integer in-place optional addition
|
||||||
## The addition is only performed if ctl is "true"
|
## The addition is only performed if ctl is "true"
|
||||||
## The result carry is always computed.
|
## The result carry is always computed.
|
||||||
|
@ -86,7 +90,7 @@ template add(a: var Fq, b: Fq, ctl: CTBool[Word]): CTBool[Word] =
|
||||||
## a and b MUST have the same announced bitlength (i.e. `bits` static parameters)
|
## a and b MUST have the same announced bitlength (i.e. `bits` static parameters)
|
||||||
add(a.mres, b.mres, ctl)
|
add(a.mres, b.mres, ctl)
|
||||||
|
|
||||||
template sub(a: var Fq, b: Fq, ctl: CTBool[Word]): CTBool[Word] =
|
template sub(a: var Fp, b: Fp, ctl: CTBool[Word]): CTBool[Word] =
|
||||||
## Constant-time big integer in-place optional substraction
|
## Constant-time big integer in-place optional substraction
|
||||||
## The substraction is only performed if ctl is "true"
|
## The substraction is only performed if ctl is "true"
|
||||||
## The result carry is always computed.
|
## The result carry is always computed.
|
||||||
|
@ -109,46 +113,46 @@ template sub(a: var Fq, b: Fq, ctl: CTBool[Word]): CTBool[Word] =
|
||||||
# - Golden Primes (φ^2 - φ - 1 with φ = 2^k for example Ed448-Goldilocks: 2^448 - 2^224 - 1)
|
# - Golden Primes (φ^2 - φ - 1 with φ = 2^k for example Ed448-Goldilocks: 2^448 - 2^224 - 1)
|
||||||
# exist and can be implemented with compile-time specialization.
|
# exist and can be implemented with compile-time specialization.
|
||||||
|
|
||||||
func `+=`*(a: var Fq, b: Fq) =
|
func `+=`*(a: var Fp, b: Fp) =
|
||||||
## Addition over Fq
|
## Addition over Fp
|
||||||
var ctl = add(a, b, CtTrue)
|
var ctl = add(a, b, CtTrue)
|
||||||
ctl = ctl or not sub(a, Fq.C.Mod, CtFalse)
|
ctl = ctl or not sub(a, Fp.C.Mod, CtFalse)
|
||||||
discard sub(a, Fq.C.Mod, ctl)
|
discard sub(a, Fp.C.Mod, ctl)
|
||||||
|
|
||||||
func `-=`*(a: var Fq, b: Fq) =
|
func `-=`*(a: var Fp, b: Fp) =
|
||||||
## Substraction over Fq
|
## Substraction over Fp
|
||||||
let ctl = sub(a, b, CtTrue)
|
let ctl = sub(a, b, CtTrue)
|
||||||
discard add(a, Fq.C.Mod, ctl)
|
discard add(a, Fp.C.Mod, ctl)
|
||||||
|
|
||||||
func `*`*(a, b: Fq): Fq {.noInit.} =
|
func `*`*(a, b: Fp): Fp {.noInit.} =
|
||||||
## Multiplication over Fq
|
## Multiplication over Fp
|
||||||
##
|
##
|
||||||
## It is recommended to assign with {.noInit.}
|
## It is recommended to assign with {.noInit.}
|
||||||
## as Fq elements are usually large and this
|
## as Fp elements are usually large and this
|
||||||
## routine will zero init internally the result.
|
## routine will zero init internally the result.
|
||||||
result.mres.montyMul(a.mres, b.mres, Fq.C.Mod.mres, Fq.C.getNegInvModWord())
|
result.mres.montyMul(a.mres, b.mres, Fp.C.Mod.mres, Fp.C.getNegInvModWord())
|
||||||
|
|
||||||
func square*(a: Fq): Fq {.noInit.} =
|
func square*(a: Fp): Fp {.noInit.} =
|
||||||
## Squaring over Fq
|
## Squaring over Fp
|
||||||
##
|
##
|
||||||
## It is recommended to assign with {.noInit.}
|
## It is recommended to assign with {.noInit.}
|
||||||
## as Fq elements are usually large and this
|
## as Fp elements are usually large and this
|
||||||
## routine will zero init internally the result.
|
## routine will zero init internally the result.
|
||||||
result.mres.montySquare(a.mres, Fq.C.Mod.mres, Fq.C.getNegInvModWord())
|
result.mres.montySquare(a.mres, Fp.C.Mod.mres, Fp.C.getNegInvModWord())
|
||||||
|
|
||||||
func pow*(a: var Fq, exponent: BigInt) =
|
func pow*(a: var Fp, exponent: BigInt) =
|
||||||
## Exponentiation over Fq
|
## Exponentiation over Fp
|
||||||
## ``a``: a field element to be exponentiated
|
## ``a``: a field element to be exponentiated
|
||||||
## ``exponent``: a big integer
|
## ``exponent``: a big integer
|
||||||
const windowSize = 5 # TODO: find best window size for each curves
|
const windowSize = 5 # TODO: find best window size for each curves
|
||||||
a.mres.montyPow(
|
a.mres.montyPow(
|
||||||
exponent,
|
exponent,
|
||||||
Fq.C.Mod.mres, Fq.C.getMontyOne(),
|
Fp.C.Mod.mres, Fp.C.getMontyOne(),
|
||||||
Fq.C.getNegInvModWord(), windowSize
|
Fp.C.getNegInvModWord(), windowSize
|
||||||
)
|
)
|
||||||
|
|
||||||
func powUnsafeExponent*(a: var Fq, exponent: BigInt) =
|
func powUnsafeExponent*(a: var Fp, exponent: BigInt) =
|
||||||
## Exponentiation over Fq
|
## Exponentiation over Fp
|
||||||
## ``a``: a field element to be exponentiated
|
## ``a``: a field element to be exponentiated
|
||||||
## ``exponent``: a big integer
|
## ``exponent``: a big integer
|
||||||
##
|
##
|
||||||
|
@ -161,17 +165,17 @@ func powUnsafeExponent*(a: var Fq, exponent: BigInt) =
|
||||||
const windowSize = 5 # TODO: find best window size for each curves
|
const windowSize = 5 # TODO: find best window size for each curves
|
||||||
a.mres.montyPowUnsafeExponent(
|
a.mres.montyPowUnsafeExponent(
|
||||||
exponent,
|
exponent,
|
||||||
Fq.C.Mod.mres, Fq.C.getMontyOne(),
|
Fp.C.Mod.mres, Fp.C.getMontyOne(),
|
||||||
Fq.C.getNegInvModWord(), windowSize
|
Fp.C.getNegInvModWord(), windowSize
|
||||||
)
|
)
|
||||||
|
|
||||||
func inv*(a: var Fq) =
|
func inv*(a: var Fp) =
|
||||||
## Modular inversion
|
## Modular inversion
|
||||||
## Warning ⚠️ :
|
## Warning ⚠️ :
|
||||||
## - This assumes that `Fq` is a prime field
|
## - This assumes that `Fp` is a prime field
|
||||||
const windowSize = 5 # TODO: find best window size for each curves
|
const windowSize = 5 # TODO: find best window size for each curves
|
||||||
a.mres.montyPowUnsafeExponent(
|
a.mres.montyPowUnsafeExponent(
|
||||||
Fq.C.getInvModExponent(),
|
Fp.C.getInvModExponent(),
|
||||||
Fq.C.Mod.mres, Fq.C.getMontyOne(),
|
Fp.C.Mod.mres, Fp.C.getMontyOne(),
|
||||||
Fq.C.getNegInvModWord(), windowSize
|
Fp.C.getNegInvModWord(), windowSize
|
||||||
)
|
)
|
||||||
|
|
|
@ -59,7 +59,7 @@ macro declareCurves*(curves: untyped): untyped =
|
||||||
var CurveBitSize = nnKBracket.newTree()
|
var CurveBitSize = nnKBracket.newTree()
|
||||||
var curveModStmts = newStmtList()
|
var curveModStmts = newStmtList()
|
||||||
|
|
||||||
let Fq = ident"Fq"
|
let Fp = ident"Fp"
|
||||||
|
|
||||||
for curveDesc in curves:
|
for curveDesc in curves:
|
||||||
curveDesc.expectKind(nnkCommand)
|
curveDesc.expectKind(nnkCommand)
|
||||||
|
@ -87,12 +87,12 @@ macro declareCurves*(curves: untyped): untyped =
|
||||||
curve, bitSize
|
curve, bitSize
|
||||||
)
|
)
|
||||||
|
|
||||||
# const BN254_Modulus = Fq[BN254](value: fromHex(BigInt[254], "0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"))
|
# const BN254_Modulus = Fp[BN254](value: fromHex(BigInt[254], "0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"))
|
||||||
let modulusID = ident($curve & "_Modulus")
|
let modulusID = ident($curve & "_Modulus")
|
||||||
curveModStmts.add newConstStmt(
|
curveModStmts.add newConstStmt(
|
||||||
modulusID,
|
modulusID,
|
||||||
nnkObjConstr.newTree(
|
nnkObjConstr.newTree(
|
||||||
nnkBracketExpr.newTree(Fq, curve),
|
nnkBracketExpr.newTree(Fp, curve),
|
||||||
nnkExprColonExpr.newTree(
|
nnkExprColonExpr.newTree(
|
||||||
ident"mres",
|
ident"mres",
|
||||||
newCall(
|
newCall(
|
||||||
|
@ -136,7 +136,7 @@ macro declareCurves*(curves: untyped): untyped =
|
||||||
)
|
)
|
||||||
|
|
||||||
# type
|
# type
|
||||||
# `Fq`*[C: static Curve] = object
|
# `Fp`*[C: static Curve] = object
|
||||||
# ## All operations on a field are modulo P
|
# ## All operations on a field are modulo P
|
||||||
# ## P being the prime modulus of the Curve C
|
# ## P being the prime modulus of the Curve C
|
||||||
# ## Internally, data is stored in Montgomery n-residue form
|
# ## Internally, data is stored in Montgomery n-residue form
|
||||||
|
@ -144,7 +144,7 @@ macro declareCurves*(curves: untyped): untyped =
|
||||||
# mres*: matchingBigInt(C)
|
# mres*: matchingBigInt(C)
|
||||||
result.add nnkTypeSection.newTree(
|
result.add nnkTypeSection.newTree(
|
||||||
nnkTypeDef.newTree(
|
nnkTypeDef.newTree(
|
||||||
nnkPostfix.newTree(ident"*", Fq),
|
nnkPostfix.newTree(ident"*", Fp),
|
||||||
nnkGenericParams.newTree(newIdentDefs(
|
nnkGenericParams.newTree(newIdentDefs(
|
||||||
C, nnkStaticTy.newTree(Curve), newEmptyNode()
|
C, nnkStaticTy.newTree(Curve), newEmptyNode()
|
||||||
)),
|
)),
|
||||||
|
|
|
@ -21,7 +21,7 @@ import
|
||||||
#
|
#
|
||||||
# ############################################################
|
# ############################################################
|
||||||
|
|
||||||
func fromUint*(dst: var Fq,
|
func fromUint*(dst: var Fp,
|
||||||
src: SomeUnsignedInt) =
|
src: SomeUnsignedInt) =
|
||||||
## Parse a regular unsigned integer
|
## Parse a regular unsigned integer
|
||||||
## and store it into a BigInt of size `bits`
|
## and store it into a BigInt of size `bits`
|
||||||
|
@ -29,7 +29,7 @@ func fromUint*(dst: var Fq,
|
||||||
dst.fromBig(raw)
|
dst.fromBig(raw)
|
||||||
|
|
||||||
func exportRawUint*(dst: var openarray[byte],
|
func exportRawUint*(dst: var openarray[byte],
|
||||||
src: Fq,
|
src: Fp,
|
||||||
dstEndianness: static Endianness) =
|
dstEndianness: static Endianness) =
|
||||||
## Serialize a finite field element to its canonical big-endian or little-endian
|
## Serialize a finite field element to its canonical big-endian or little-endian
|
||||||
## representation
|
## representation
|
||||||
|
@ -42,7 +42,7 @@ func exportRawUint*(dst: var openarray[byte],
|
||||||
## I.e least significant bit is aligned to buffer boundary
|
## I.e least significant bit is aligned to buffer boundary
|
||||||
exportRawUint(dst, src.toBig(), dstEndianness)
|
exportRawUint(dst, src.toBig(), dstEndianness)
|
||||||
|
|
||||||
func toHex*(f: Fq, order: static Endianness = bigEndian): string =
|
func toHex*(f: Fp, order: static Endianness = bigEndian): string =
|
||||||
## Stringify a finite field element to hex.
|
## Stringify a finite field element to hex.
|
||||||
## Note. Leading zeros are not removed.
|
## Note. Leading zeros are not removed.
|
||||||
## Result is prefixed with 0x
|
## Result is prefixed with 0x
|
||||||
|
@ -53,7 +53,7 @@ func toHex*(f: Fq, order: static Endianness = bigEndian): string =
|
||||||
## - no leaks
|
## - no leaks
|
||||||
result = f.toBig().toHex(order)
|
result = f.toBig().toHex(order)
|
||||||
|
|
||||||
func fromHex*(dst: var Fq, s: string) {.raises: [ValueError].}=
|
func fromHex*(dst: var Fp, s: string) {.raises: [ValueError].}=
|
||||||
## Convert a hex string to a element of Fq
|
## Convert a hex string to a element of Fp
|
||||||
let raw {.noinit.} = fromHex(dst.mres.typeof, s)
|
let raw {.noinit.} = fromHex(dst.mres.typeof, s)
|
||||||
dst.fromBig(raw)
|
dst.fromBig(raw)
|
||||||
|
|
|
@ -19,7 +19,7 @@ proc main() =
|
||||||
suite "Basic arithmetic over finite fields":
|
suite "Basic arithmetic over finite fields":
|
||||||
test "Addition mod 101":
|
test "Addition mod 101":
|
||||||
block:
|
block:
|
||||||
var x, y, z: Fq[Fake101]
|
var x, y, z: Fp[Fake101]
|
||||||
|
|
||||||
x.fromUint(80'u32)
|
x.fromUint(80'u32)
|
||||||
y.fromUint(10'u32)
|
y.fromUint(10'u32)
|
||||||
|
@ -37,7 +37,7 @@ proc main() =
|
||||||
90'u64 == cast[uint64](x_bytes)
|
90'u64 == cast[uint64](x_bytes)
|
||||||
|
|
||||||
block:
|
block:
|
||||||
var x, y, z: Fq[Fake101]
|
var x, y, z: Fp[Fake101]
|
||||||
|
|
||||||
x.fromUint(80'u32)
|
x.fromUint(80'u32)
|
||||||
y.fromUint(21'u32)
|
y.fromUint(21'u32)
|
||||||
|
@ -55,7 +55,7 @@ proc main() =
|
||||||
0'u64 == cast[uint64](x_bytes)
|
0'u64 == cast[uint64](x_bytes)
|
||||||
|
|
||||||
block:
|
block:
|
||||||
var x, y, z: Fq[Fake101]
|
var x, y, z: Fp[Fake101]
|
||||||
|
|
||||||
x.fromUint(80'u32)
|
x.fromUint(80'u32)
|
||||||
y.fromUint(22'u32)
|
y.fromUint(22'u32)
|
||||||
|
@ -74,7 +74,7 @@ proc main() =
|
||||||
|
|
||||||
test "Substraction mod 101":
|
test "Substraction mod 101":
|
||||||
block:
|
block:
|
||||||
var x, y, z: Fq[Fake101]
|
var x, y, z: Fp[Fake101]
|
||||||
|
|
||||||
x.fromUint(80'u32)
|
x.fromUint(80'u32)
|
||||||
y.fromUint(10'u32)
|
y.fromUint(10'u32)
|
||||||
|
@ -92,7 +92,7 @@ proc main() =
|
||||||
70'u64 == cast[uint64](x_bytes)
|
70'u64 == cast[uint64](x_bytes)
|
||||||
|
|
||||||
block:
|
block:
|
||||||
var x, y, z: Fq[Fake101]
|
var x, y, z: Fp[Fake101]
|
||||||
|
|
||||||
x.fromUint(80'u32)
|
x.fromUint(80'u32)
|
||||||
y.fromUint(80'u32)
|
y.fromUint(80'u32)
|
||||||
|
@ -110,7 +110,7 @@ proc main() =
|
||||||
0'u64 == cast[uint64](x_bytes)
|
0'u64 == cast[uint64](x_bytes)
|
||||||
|
|
||||||
block:
|
block:
|
||||||
var x, y, z: Fq[Fake101]
|
var x, y, z: Fp[Fake101]
|
||||||
|
|
||||||
x.fromUint(80'u32)
|
x.fromUint(80'u32)
|
||||||
y.fromUint(81'u32)
|
y.fromUint(81'u32)
|
||||||
|
@ -129,7 +129,7 @@ proc main() =
|
||||||
|
|
||||||
test "Multiplication mod 101":
|
test "Multiplication mod 101":
|
||||||
block:
|
block:
|
||||||
var x, y, z: Fq[Fake101]
|
var x, y, z: Fp[Fake101]
|
||||||
|
|
||||||
x.fromUint(10'u32)
|
x.fromUint(10'u32)
|
||||||
y.fromUint(10'u32)
|
y.fromUint(10'u32)
|
||||||
|
@ -147,7 +147,7 @@ proc main() =
|
||||||
100'u64 == cast[uint64](r_bytes)
|
100'u64 == cast[uint64](r_bytes)
|
||||||
|
|
||||||
block:
|
block:
|
||||||
var x, y, z: Fq[Fake101]
|
var x, y, z: Fp[Fake101]
|
||||||
|
|
||||||
x.fromUint(10'u32)
|
x.fromUint(10'u32)
|
||||||
y.fromUint(11'u32)
|
y.fromUint(11'u32)
|
||||||
|
@ -166,7 +166,7 @@ proc main() =
|
||||||
|
|
||||||
test "Addition mod 2^61 - 1":
|
test "Addition mod 2^61 - 1":
|
||||||
block:
|
block:
|
||||||
var x, y, z: Fq[Mersenne61]
|
var x, y, z: Fp[Mersenne61]
|
||||||
|
|
||||||
x.fromUint(80'u64)
|
x.fromUint(80'u64)
|
||||||
y.fromUint(10'u64)
|
y.fromUint(10'u64)
|
||||||
|
@ -185,7 +185,7 @@ proc main() =
|
||||||
new_x == 90'u64
|
new_x == 90'u64
|
||||||
|
|
||||||
block:
|
block:
|
||||||
var x, y, z: Fq[Mersenne61]
|
var x, y, z: Fp[Mersenne61]
|
||||||
|
|
||||||
x.fromUint(1'u64 shl 61 - 2)
|
x.fromUint(1'u64 shl 61 - 2)
|
||||||
y.fromUint(1'u32)
|
y.fromUint(1'u32)
|
||||||
|
@ -204,7 +204,7 @@ proc main() =
|
||||||
new_x == 0'u64
|
new_x == 0'u64
|
||||||
|
|
||||||
block:
|
block:
|
||||||
var x, y, z: Fq[Mersenne61]
|
var x, y, z: Fp[Mersenne61]
|
||||||
|
|
||||||
x.fromUint(1'u64 shl 61 - 2)
|
x.fromUint(1'u64 shl 61 - 2)
|
||||||
y.fromUint(2'u64)
|
y.fromUint(2'u64)
|
||||||
|
@ -224,7 +224,7 @@ proc main() =
|
||||||
|
|
||||||
test "Substraction mod 2^61 - 1":
|
test "Substraction mod 2^61 - 1":
|
||||||
block:
|
block:
|
||||||
var x, y, z: Fq[Mersenne61]
|
var x, y, z: Fp[Mersenne61]
|
||||||
|
|
||||||
x.fromUint(80'u64)
|
x.fromUint(80'u64)
|
||||||
y.fromUint(10'u64)
|
y.fromUint(10'u64)
|
||||||
|
@ -243,7 +243,7 @@ proc main() =
|
||||||
new_x == 70'u64
|
new_x == 70'u64
|
||||||
|
|
||||||
block:
|
block:
|
||||||
var x, y, z: Fq[Mersenne61]
|
var x, y, z: Fp[Mersenne61]
|
||||||
|
|
||||||
x.fromUint(0'u64)
|
x.fromUint(0'u64)
|
||||||
y.fromUint(1'u64)
|
y.fromUint(1'u64)
|
||||||
|
@ -263,7 +263,7 @@ proc main() =
|
||||||
|
|
||||||
test "Multiplication mod 2^61 - 1":
|
test "Multiplication mod 2^61 - 1":
|
||||||
block:
|
block:
|
||||||
var x, y, z: Fq[Mersenne61]
|
var x, y, z: Fp[Mersenne61]
|
||||||
|
|
||||||
x.fromUint(10'u32)
|
x.fromUint(10'u32)
|
||||||
y.fromUint(10'u32)
|
y.fromUint(10'u32)
|
||||||
|
@ -282,7 +282,7 @@ proc main() =
|
||||||
cast[uint64](r_bytes) == 100'u64
|
cast[uint64](r_bytes) == 100'u64
|
||||||
|
|
||||||
block:
|
block:
|
||||||
var x, y, z: Fq[Mersenne61]
|
var x, y, z: Fp[Mersenne61]
|
||||||
|
|
||||||
x.fromUint(1'u32 shl 31)
|
x.fromUint(1'u32 shl 31)
|
||||||
y.fromUint(1'u32 shl 31)
|
y.fromUint(1'u32 shl 31)
|
||||||
|
|
|
@ -21,7 +21,7 @@ proc main() =
|
||||||
let exponent = BigInt[64].fromUint(2'u64)
|
let exponent = BigInt[64].fromUint(2'u64)
|
||||||
|
|
||||||
block: # 1^2 mod 101
|
block: # 1^2 mod 101
|
||||||
var n, expected: Fq[Fake101]
|
var n, expected: Fp[Fake101]
|
||||||
|
|
||||||
n.fromUint(1'u32)
|
n.fromUint(1'u32)
|
||||||
expected = n
|
expected = n
|
||||||
|
@ -39,7 +39,7 @@ proc main() =
|
||||||
1'u64 == r
|
1'u64 == r
|
||||||
|
|
||||||
block: # 2^2 mod 101
|
block: # 2^2 mod 101
|
||||||
var n, expected: Fq[Fake101]
|
var n, expected: Fp[Fake101]
|
||||||
|
|
||||||
n.fromUint(2'u32)
|
n.fromUint(2'u32)
|
||||||
expected.fromUint(4'u32)
|
expected.fromUint(4'u32)
|
||||||
|
@ -57,7 +57,7 @@ proc main() =
|
||||||
4'u64 == r
|
4'u64 == r
|
||||||
|
|
||||||
block: # 10^2 mod 101
|
block: # 10^2 mod 101
|
||||||
var n, expected: Fq[Fake101]
|
var n, expected: Fp[Fake101]
|
||||||
|
|
||||||
n.fromUint(10'u32)
|
n.fromUint(10'u32)
|
||||||
expected.fromUint(100'u32)
|
expected.fromUint(100'u32)
|
||||||
|
@ -75,7 +75,7 @@ proc main() =
|
||||||
100'u64 == r
|
100'u64 == r
|
||||||
|
|
||||||
block: # 11^2 mod 101
|
block: # 11^2 mod 101
|
||||||
var n, expected: Fq[Fake101]
|
var n, expected: Fp[Fake101]
|
||||||
|
|
||||||
n.fromUint(11'u32)
|
n.fromUint(11'u32)
|
||||||
expected.fromUint(20'u32)
|
expected.fromUint(20'u32)
|
||||||
|
@ -94,7 +94,7 @@ proc main() =
|
||||||
|
|
||||||
test "x^(p-2) mod p (modular inversion if p prime)":
|
test "x^(p-2) mod p (modular inversion if p prime)":
|
||||||
block:
|
block:
|
||||||
var x: Fq[BLS12_381]
|
var x: Fp[BLS12_381]
|
||||||
|
|
||||||
# BN254 field modulus
|
# BN254 field modulus
|
||||||
x.fromHex("0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47")
|
x.fromHex("0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47")
|
||||||
|
@ -110,7 +110,7 @@ proc main() =
|
||||||
computed == expected
|
computed == expected
|
||||||
|
|
||||||
block:
|
block:
|
||||||
var x: Fq[BLS12_381]
|
var x: Fp[BLS12_381]
|
||||||
|
|
||||||
# BN254 field modulus
|
# BN254 field modulus
|
||||||
x.fromHex("0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47")
|
x.fromHex("0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47")
|
||||||
|
@ -127,7 +127,7 @@ proc main() =
|
||||||
|
|
||||||
suite "Modular inversion over prime fields":
|
suite "Modular inversion over prime fields":
|
||||||
test "x^(-1) mod p":
|
test "x^(-1) mod p":
|
||||||
var x: Fq[BLS12_381]
|
var x: Fp[BLS12_381]
|
||||||
|
|
||||||
# BN254 field modulus
|
# BN254 field modulus
|
||||||
x.fromHex("0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47")
|
x.fromHex("0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47")
|
||||||
|
|
|
@ -94,8 +94,8 @@ proc mainMul() =
|
||||||
doAssert len >= bW, "Expected at most " & $len & " bytes but wrote " & $bW & " for " & toHex(bBuf) & " (little-endian)"
|
doAssert len >= bW, "Expected at most " & $len & " bytes but wrote " & $bW & " for " & toHex(bBuf) & " (little-endian)"
|
||||||
|
|
||||||
# Build the bigint - TODO more fields codecs
|
# Build the bigint - TODO more fields codecs
|
||||||
let aTest = Fq[curve].fromBig BigInt[bits].fromRawUint(aBuf, littleEndian)
|
let aTest = Fp[curve].fromBig BigInt[bits].fromRawUint(aBuf, littleEndian)
|
||||||
let bTest = Fq[curve].fromBig BigInt[bits].fromRawUint(bBuf, littleEndian)
|
let bTest = Fp[curve].fromBig BigInt[bits].fromRawUint(bBuf, littleEndian)
|
||||||
|
|
||||||
#########################################################
|
#########################################################
|
||||||
# Modular multiplication
|
# Modular multiplication
|
||||||
|
@ -169,7 +169,7 @@ proc mainInv() =
|
||||||
doAssert len >= aW, "Expected at most " & $len & " bytes but wrote " & $aW & " for " & toHex(aBuf) & " (little-endian)"
|
doAssert len >= aW, "Expected at most " & $len & " bytes but wrote " & $aW & " for " & toHex(aBuf) & " (little-endian)"
|
||||||
|
|
||||||
# Build the bigint - TODO more fields codecs
|
# Build the bigint - TODO more fields codecs
|
||||||
let aTest = Fq[curve].fromBig BigInt[bits].fromRawUint(aBuf[0 ..< aW], bigEndian)
|
let aTest = Fp[curve].fromBig BigInt[bits].fromRawUint(aBuf[0 ..< aW], bigEndian)
|
||||||
|
|
||||||
#########################################################
|
#########################################################
|
||||||
# Modular inversion
|
# Modular inversion
|
||||||
|
|
|
@ -22,7 +22,7 @@ proc main() =
|
||||||
# "Little-endian" - 0
|
# "Little-endian" - 0
|
||||||
let x = 0'u64
|
let x = 0'u64
|
||||||
let x_bytes = cast[array[8, byte]](x)
|
let x_bytes = cast[array[8, byte]](x)
|
||||||
var f: Fq[Mersenne61]
|
var f: Fp[Mersenne61]
|
||||||
f.fromUint(x)
|
f.fromUint(x)
|
||||||
|
|
||||||
var r_bytes: array[8, byte]
|
var r_bytes: array[8, byte]
|
||||||
|
@ -33,7 +33,7 @@ proc main() =
|
||||||
# "Little-endian" - 1
|
# "Little-endian" - 1
|
||||||
let x = 1'u64
|
let x = 1'u64
|
||||||
let x_bytes = cast[array[8, byte]](x)
|
let x_bytes = cast[array[8, byte]](x)
|
||||||
var f: Fq[Mersenne61]
|
var f: Fp[Mersenne61]
|
||||||
f.fromUint(x)
|
f.fromUint(x)
|
||||||
|
|
||||||
var r_bytes: array[8, byte]
|
var r_bytes: array[8, byte]
|
||||||
|
@ -44,7 +44,7 @@ proc main() =
|
||||||
# "Little-endian" - 2^31
|
# "Little-endian" - 2^31
|
||||||
let x = 1'u64 shl 31
|
let x = 1'u64 shl 31
|
||||||
let x_bytes = cast[array[8, byte]](x)
|
let x_bytes = cast[array[8, byte]](x)
|
||||||
var f: Fq[Mersenne61]
|
var f: Fp[Mersenne61]
|
||||||
f.fromUint(x)
|
f.fromUint(x)
|
||||||
|
|
||||||
var r_bytes: array[8, byte]
|
var r_bytes: array[8, byte]
|
||||||
|
@ -55,7 +55,7 @@ proc main() =
|
||||||
# "Little-endian" - 2^32
|
# "Little-endian" - 2^32
|
||||||
let x = 1'u64 shl 32
|
let x = 1'u64 shl 32
|
||||||
let x_bytes = cast[array[8, byte]](x)
|
let x_bytes = cast[array[8, byte]](x)
|
||||||
var f: Fq[Mersenne61]
|
var f: Fp[Mersenne61]
|
||||||
f.fromUint(x)
|
f.fromUint(x)
|
||||||
|
|
||||||
var r_bytes: array[8, byte]
|
var r_bytes: array[8, byte]
|
||||||
|
@ -67,7 +67,7 @@ proc main() =
|
||||||
# "Little-endian" - 2^63
|
# "Little-endian" - 2^63
|
||||||
let x = 1'u64 shl 63
|
let x = 1'u64 shl 63
|
||||||
let x_bytes = cast[array[8, byte]](x)
|
let x_bytes = cast[array[8, byte]](x)
|
||||||
var f: Fq[Mersenne127]
|
var f: Fp[Mersenne127]
|
||||||
f.fromUint(x)
|
f.fromUint(x)
|
||||||
|
|
||||||
var r_bytes: array[16, byte]
|
var r_bytes: array[16, byte]
|
||||||
|
@ -77,7 +77,7 @@ proc main() =
|
||||||
block: # "Little-endian" - single random
|
block: # "Little-endian" - single random
|
||||||
let x = uint64 rand(0..high(int))
|
let x = uint64 rand(0..high(int))
|
||||||
let x_bytes = cast[array[8, byte]](x)
|
let x_bytes = cast[array[8, byte]](x)
|
||||||
var f: Fq[Mersenne127]
|
var f: Fp[Mersenne127]
|
||||||
f.fromUint(x)
|
f.fromUint(x)
|
||||||
|
|
||||||
var r_bytes: array[16, byte]
|
var r_bytes: array[16, byte]
|
||||||
|
@ -88,7 +88,7 @@ proc main() =
|
||||||
for _ in 0 ..< 10:
|
for _ in 0 ..< 10:
|
||||||
let x = uint64 rand(0..high(int))
|
let x = uint64 rand(0..high(int))
|
||||||
let x_bytes = cast[array[8, byte]](x)
|
let x_bytes = cast[array[8, byte]](x)
|
||||||
var f: Fq[Mersenne127]
|
var f: Fp[Mersenne127]
|
||||||
f.fromUint(x)
|
f.fromUint(x)
|
||||||
|
|
||||||
var r_bytes: array[16, byte]
|
var r_bytes: array[16, byte]
|
||||||
|
@ -98,7 +98,7 @@ proc main() =
|
||||||
test "Round trip on large constant":
|
test "Round trip on large constant":
|
||||||
block: # 2^126
|
block: # 2^126
|
||||||
const p = "0x40000000000000000000000000000000"
|
const p = "0x40000000000000000000000000000000"
|
||||||
let x = Fq[Mersenne127].fromBig BigInt[127].fromHex(p)
|
let x = Fp[Mersenne127].fromBig BigInt[127].fromHex(p)
|
||||||
let hex = x.toHex(bigEndian)
|
let hex = x.toHex(bigEndian)
|
||||||
|
|
||||||
check: p == hex
|
check: p == hex
|
||||||
|
|
Loading…
Reference in New Issue