word_types -> primitives + delete the "config" file / debug template
This commit is contained in:
parent
57ee2cb6bd
commit
153e898263
|
@ -16,7 +16,7 @@ proc test(fakeCurves: string, path: string, lang = "c") =
|
||||||
|
|
||||||
### tasks
|
### tasks
|
||||||
task test, "Run all tests":
|
task test, "Run all tests":
|
||||||
test "", "tests/test_word_types.nim"
|
test "", "tests/test_primitives.nim"
|
||||||
test "", "tests/test_io.nim"
|
test "", "tests/test_io.nim"
|
||||||
test "", "tests/test_bigints.nim"
|
test "", "tests/test_bigints.nim"
|
||||||
test " -d:testingCurves", "tests/test_field_fp.nim"
|
test " -d:testingCurves", "tests/test_field_fp.nim"
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
# So the least significant limb is limb[0]
|
# So the least significant limb is limb[0]
|
||||||
# This is independent from the base type endianness.
|
# This is independent from the base type endianness.
|
||||||
|
|
||||||
import ./word_types, ./config
|
import ./primitives, ./config
|
||||||
|
|
||||||
type Word* = Ct[uint64]
|
type Word* = Ct[uint64]
|
||||||
type BaseType* = uint64 # Exported type for conversion in "normal integers"
|
type BaseType* = uint64 # Exported type for conversion in "normal integers"
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
# Constantine
|
|
||||||
# Copyright (c) 2018-2019 Status Research & Development GmbH
|
|
||||||
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
|
|
||||||
# Licensed and distributed under either of
|
|
||||||
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
|
|
||||||
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
||||||
|
|
||||||
# ############################################################
|
|
||||||
#
|
|
||||||
# Common configuration
|
|
||||||
#
|
|
||||||
# ############################################################
|
|
||||||
|
|
||||||
template debug*(body: untyped): untyped =
|
|
||||||
when defined(debugConstantine):
|
|
||||||
body
|
|
|
@ -14,8 +14,7 @@
|
||||||
|
|
||||||
# We assume that p is prime known at compile-time
|
# We assume that p is prime known at compile-time
|
||||||
|
|
||||||
import ./word_types, ./bigints, ./curves_config
|
import ./primitives, ./bigints, ./curves_config
|
||||||
from ./private/word_types_internal import unsafe_div2n1n
|
|
||||||
|
|
||||||
type
|
type
|
||||||
Fp*[C: static Curve] = object
|
Fp*[C: static Curve] = object
|
||||||
|
@ -71,96 +70,3 @@ func `+`*(a, b: Fp): Fp {.noInit.}=
|
||||||
var ctl = add(result, b, CtTrue)
|
var ctl = add(result, b, CtTrue)
|
||||||
ctl = ctl or not sub(result, Fp.C.Mod, CtFalse)
|
ctl = ctl or not sub(result, Fp.C.Mod, CtFalse)
|
||||||
sub(result, Fp.C.Mod, ctl)
|
sub(result, Fp.C.Mod, ctl)
|
||||||
|
|
||||||
func shiftAdd*(a: var Fp, c: Word) =
|
|
||||||
## Shift-accumulate
|
|
||||||
## Shift input `a` by a word and add `c`.
|
|
||||||
##
|
|
||||||
## With a word W = 2^WordBitSize and a field Fp
|
|
||||||
## Does a <- a * W + c (mod p)
|
|
||||||
const len = a.value.limbs.len
|
|
||||||
|
|
||||||
when Fp.C.Mod.bits <= WordBitSize:
|
|
||||||
# If the prime fits in a single limb
|
|
||||||
var q: Word
|
|
||||||
|
|
||||||
# (hi, lo) = a * 2^63 + c
|
|
||||||
let hi = a[0] shr 1 # 64 - 63 = 1
|
|
||||||
let lo = (a[0] shl WordBitSize) or c # Assumes most-significant bit in c is not set
|
|
||||||
unsafeDiv2n1n(q, a[0], hi, lo, Fp.C.Mod.limbs[0]) # (hi, lo) mod P
|
|
||||||
return
|
|
||||||
|
|
||||||
else:
|
|
||||||
## Multiple limbs
|
|
||||||
let hi = a[^1] # Save the high word to detect carries
|
|
||||||
const R = Fp.C.Mod.bits and WordBitSize # R = bits mod 64
|
|
||||||
|
|
||||||
when R == 0: # If the number of bits is a multiple of 64
|
|
||||||
let a1 = a[^2] #
|
|
||||||
let a0 = a[^1] #
|
|
||||||
moveMem(a[1], a[0], (len-1) * Word.sizeof) # we can just shift words
|
|
||||||
a[0] = c # and replace the first one by c
|
|
||||||
const p0 = Fp.C.Mod[^1]
|
|
||||||
else: # Need to deal with partial word shifts at the edge.
|
|
||||||
let a1 = ((a[^2] shl (WordBitSize-R)) or (a[^3] shr R)) and MaxWord
|
|
||||||
let a0 = ((a[^1] shl (WordBitSize-R)) or (a[^2] shr R)) and MaxWord
|
|
||||||
moveMem(a[1], a[0], (len-1) * Word.sizeof)
|
|
||||||
a[0] = c
|
|
||||||
const p0 = ((Fp.C.Mod[^1] shl (WordBitSize-R)) or (Fp.C.Mod[^2] shr R)) and MaxWord
|
|
||||||
|
|
||||||
# p0 has its high bit set. (a0, a1)/p0 fits in a limb.
|
|
||||||
# Get a quotient q, at most we will be 2 iterations off
|
|
||||||
# from the true quotient
|
|
||||||
|
|
||||||
let
|
|
||||||
a_hi = a0 shr 1 # 64 - 63 = 1
|
|
||||||
a_lo = (a0 shl WordBitSize) or a1
|
|
||||||
var q, r: Word
|
|
||||||
q = unsafeDiv2n1n(q, r, a_hi, a_lo, p0) # Estimate quotient
|
|
||||||
q = mux( # If n_hi == divisor
|
|
||||||
a0 == b0, MaxWord, # Quotient == MaxWord (0b0111...1111)
|
|
||||||
mux(
|
|
||||||
q == 0, 0, # elif q == 0, true quotient = 0
|
|
||||||
q - 1 # else instead of being of by 0, 1 or 2
|
|
||||||
) # we returning q-1 to be off by -1, 0 or 1
|
|
||||||
)
|
|
||||||
|
|
||||||
# Now substract a*2^63 - q*p
|
|
||||||
var carry = Word(0)
|
|
||||||
var over_p = Word(1) # Track if quotient than the modulus
|
|
||||||
|
|
||||||
for i in static(0 ..< Fp.C.Mod.limbs.len):
|
|
||||||
var qp_lo: Word
|
|
||||||
|
|
||||||
block: # q*p
|
|
||||||
qp_hi: Word
|
|
||||||
unsafeExtendedPrecMul(qp_hi, qp_lo, q, Fp.C.Mod[i]) # q * p
|
|
||||||
assert qp_lo.isMsbSet.not
|
|
||||||
assert carry.isMsbSet.not
|
|
||||||
qp_lo += carry # Add carry from previous limb
|
|
||||||
let qp_carry = qp_lo.isMsbSet
|
|
||||||
carry = mux(qp_carry, qp_hi + Word(1), qp_hi) # New carry
|
|
||||||
|
|
||||||
qp_lo = qp_lo and MaxWord # Normalize to u63
|
|
||||||
|
|
||||||
block: # a*2^63 - q*p
|
|
||||||
a[i] -= qp_lo
|
|
||||||
carry += Word(a[i].isMsbSet) # Adjust if borrow
|
|
||||||
a[i] = a[i] and MaxWord # Normalize to u63
|
|
||||||
|
|
||||||
over_p = mux(
|
|
||||||
a[i] == Fp.C.Mod[i], over_p,
|
|
||||||
a[i] > Fp.C.Mod[i]
|
|
||||||
)
|
|
||||||
|
|
||||||
# Fix quotient, the true quotient is either q-1, q or q+1
|
|
||||||
#
|
|
||||||
# if carry < q or carry == q and over_p we must do "a -= p"
|
|
||||||
# if carry > hi (negative result) we must do "a+= p"
|
|
||||||
|
|
||||||
let neg = carry < hi
|
|
||||||
let tooBig = not neg and (over_p or (carry < hi))
|
|
||||||
|
|
||||||
add(a, Fp.C.Mod, neg)
|
|
||||||
sub(a, Fp.C.Mod, tooBig)
|
|
||||||
return
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
endians,
|
endians,
|
||||||
./word_types, ./bigints
|
./primitives, ./bigints
|
||||||
|
|
||||||
# ############################################################
|
# ############################################################
|
||||||
#
|
#
|
||||||
|
@ -20,6 +20,8 @@ import
|
||||||
#
|
#
|
||||||
# ############################################################
|
# ############################################################
|
||||||
|
|
||||||
|
# TODO: tag/remove exceptions raised.
|
||||||
|
|
||||||
func fromRawUintLE(
|
func fromRawUintLE(
|
||||||
T: type BigInt,
|
T: type BigInt,
|
||||||
src: openarray[byte]): T =
|
src: openarray[byte]): T =
|
||||||
|
@ -73,6 +75,9 @@ func fromUint*(
|
||||||
src: SomeUnsignedInt): T =
|
src: SomeUnsignedInt): T =
|
||||||
## 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`
|
||||||
|
static:
|
||||||
|
doAssert T.bits >= sizeof(src) * 8, "The BigInt bitsize (" & $T.bits &
|
||||||
|
") must be greater or equal the source integer bitsize (" & $(sizeof(src) * 8) & ')'
|
||||||
fromRawUint(T, cast[array[sizeof(src), byte]](src), cpuEndian)
|
fromRawUint(T, cast[array[sizeof(src), byte]](src), cpuEndian)
|
||||||
|
|
||||||
# ############################################################
|
# ############################################################
|
||||||
|
@ -154,8 +159,7 @@ func dumpRawUint*(
|
||||||
## or zero-padded right for little-endian.
|
## or zero-padded right for little-endian.
|
||||||
## I.e least significant bit is aligned to buffer boundary
|
## I.e least significant bit is aligned to buffer boundary
|
||||||
|
|
||||||
if dst.len < static(BigInt.bits div 8):
|
assert dst.len >= static(BigInt.bits div 8), "BigInt -> Raw int conversion: destination buffer is too small"
|
||||||
raise newException(ValueError, "BigInt -> Raw int conversion: destination buffer is too small")
|
|
||||||
|
|
||||||
when BigInt.bits == 0:
|
when BigInt.bits == 0:
|
||||||
zeroMem(dst, dst.len)
|
zeroMem(dst, dst.len)
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
# ############################################################
|
# ############################################################
|
||||||
|
|
||||||
import
|
import
|
||||||
./word_types, ./bigints, ./field_fp, ./curves_config
|
./primitives, ./bigints, ./field_fp, ./curves_config
|
||||||
|
|
||||||
# No exceptions allowed
|
# No exceptions allowed
|
||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
# ############################################################
|
# ############################################################
|
||||||
|
|
||||||
import
|
import
|
||||||
./word_types, ./bigints
|
./primitives, ./bigints
|
||||||
|
|
||||||
from bitops import fastLog2
|
from bitops import fastLog2
|
||||||
# This will only be used at compile-time
|
# This will only be used at compile-time
|
||||||
|
|
|
@ -6,6 +6,12 @@
|
||||||
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
# ############################################################
|
||||||
|
#
|
||||||
|
# Constant-time primitives
|
||||||
|
#
|
||||||
|
# ############################################################
|
||||||
|
|
||||||
type
|
type
|
||||||
BaseUint* = SomeUnsignedInt or byte
|
BaseUint* = SomeUnsignedInt or byte
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#
|
#
|
||||||
# ############################################################
|
# ############################################################
|
||||||
|
|
||||||
import ../word_types
|
import ../primitives
|
||||||
|
|
||||||
func asm_x86_64_extMul(hi, lo: var uint64, a, b: uint64) {.inline.}=
|
func asm_x86_64_extMul(hi, lo: var uint64, a, b: uint64) {.inline.}=
|
||||||
## Extended precision multiplication uint64 * uint64 --> uint128
|
## Extended precision multiplication uint64 * uint64 --> uint128
|
|
@ -7,7 +7,7 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import unittest, random,
|
import unittest, random,
|
||||||
../constantine/[io, bigints, word_types]
|
../constantine/[io, bigints, primitives]
|
||||||
|
|
||||||
suite "isZero":
|
suite "isZero":
|
||||||
test "isZero for zero":
|
test "isZero for zero":
|
||||||
|
|
|
@ -7,4 +7,4 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import unittest, random,
|
import unittest, random,
|
||||||
../constantine/[io, bigints, word_types, field_fp]
|
../constantine/[io, bigints, primitives, field_fp]
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import unittest, random, math,
|
import unittest, random, math,
|
||||||
../constantine/word_types
|
../constantine/primitives
|
||||||
|
|
||||||
# Random seed for reproducibility
|
# Random seed for reproducibility
|
||||||
randomize(0xDEADBEEF)
|
randomize(0xDEADBEEF)
|
Loading…
Reference in New Issue