Batch Serialization (#283)
* feat: batchSerialization banderwagon elements * tests for Batch Serialize * fix: removed failure point in batchOperation * fix: changed to allocStackArray * Update constantine/math/elliptic/ec_twistededwards_batch_ops.nim Co-authored-by: Mamy Ratsimbazafy <mamy_github@numforge.co> * fix: removed return to bool & changed to debug --------- Co-authored-by: Mamy Ratsimbazafy <mamy_github@numforge.co>
This commit is contained in:
parent
3e27f1e831
commit
999482092b
|
@ -115,9 +115,9 @@ func batchInvert*[F](
|
|||
dst[i] *= accumulator
|
||||
accumulator *= elements[i]
|
||||
|
||||
func batchInvert*[F](dst: openArray[F], source: openArray[F]): bool {.inline.} =
|
||||
if dst.len != source.len:
|
||||
return false
|
||||
let N = dst.len
|
||||
batchInvert(dst.asUnchecked(), source.asUnchecked(), N)
|
||||
return true
|
||||
func batchInvert*[F](dst: var openArray[F], source: openArray[F]) {.inline.} =
|
||||
debug: doAssert dst.len == source.len
|
||||
batchInvert(dst.asUnchecked(), source.asUnchecked(), dst.len)
|
||||
|
||||
func batchInvert*[N: static int, F](dst: var array[N, F], src: array[N, F]) =
|
||||
batchInvert(dst.asUnchecked(), src.asUnchecked(), N)
|
||||
|
|
|
@ -17,7 +17,8 @@ import
|
|||
../math/config/curves,
|
||||
../math/elliptic/[
|
||||
ec_twistededwards_affine,
|
||||
ec_twistededwards_projective
|
||||
ec_twistededwards_projective,
|
||||
ec_twistededwards_batch_ops
|
||||
],
|
||||
../math/[
|
||||
extension_fields,
|
||||
|
@ -110,4 +111,44 @@ func deserialize*(dst: var EC_Prj, src: array[32, byte]): CttCodecEccStatus =
|
|||
if not(bool dst.isInSubgroup()):
|
||||
return cttCodecEcc_PointNotInSubgroup
|
||||
|
||||
return cttCodecEcc_Success
|
||||
return cttCodecEcc_Success
|
||||
|
||||
## ############################################################
|
||||
##
|
||||
## Banderwagon Batch Serialization
|
||||
##
|
||||
## ############################################################
|
||||
|
||||
func serializeBatch*(
|
||||
dst: ptr UncheckedArray[array[32, byte]],
|
||||
points: ptr UncheckedArray[EC_Prj],
|
||||
N: int,
|
||||
) : CttCodecEccStatus {.noInline.} =
|
||||
|
||||
# collect all the z coordinates
|
||||
var zs = allocStackArray(Fp[Banderwagon], N)
|
||||
var zs_inv = allocStackArray(Fp[Banderwagon], N)
|
||||
for i in 0 ..< N:
|
||||
zs[i] = points[i].z
|
||||
|
||||
zs_inv.batchInvert(zs, N)
|
||||
|
||||
for i in 0 ..< N:
|
||||
var X: Fp[Banderwagon]
|
||||
var Y: Fp[Banderwagon]
|
||||
|
||||
X.prod(points[i].x, zs_inv[i])
|
||||
Y.prod(points[i].y, zs_inv[i])
|
||||
|
||||
let lexicographicallyLargest = Y.toBig() >= Fp[Banderwagon].getPrimeMinus1div2()
|
||||
if not lexicographicallyLargest.bool():
|
||||
X.neg()
|
||||
|
||||
dst[i].marshal(X, bigEndian)
|
||||
|
||||
return cttCodecEcc_Success
|
||||
|
||||
func serializeBatch*[N: static int](
|
||||
dst: var array[N, array[32, byte]],
|
||||
points: array[N, EC_Prj]): CttCodecEccStatus {.inline.} =
|
||||
return serializeBatch(dst.asUnchecked(), points.asUnchecked(), N)
|
|
@ -303,7 +303,7 @@ suite "Batch Operations on Banderwagon":
|
|||
one.double()
|
||||
|
||||
var arr_fp_inv: array[n, Fp[Banderwagon]]
|
||||
doAssert arr_fp_inv.batchInvert(arr_fp) == true
|
||||
arr_fp_inv.batchInvert(arr_fp)
|
||||
|
||||
# Checking the correspondence with singular element inversion
|
||||
for i in 0 ..< n:
|
||||
|
@ -340,4 +340,28 @@ suite "Batch Operations on Banderwagon":
|
|||
doAssert (expected_a == scalars[0]).bool(), "expected scalar for point `A` is incorrect"
|
||||
doAssert (expected_b == scalars[1]).bool(), "expected scalar for point `B` is incorrect"
|
||||
|
||||
testBatchMapToBaseField()
|
||||
testBatchMapToBaseField()
|
||||
|
||||
## Check encoding if it is as expected or not
|
||||
test "Test Batch Encoding from Fixed Vectors":
|
||||
proc testBatchSerialize(len: static int) =
|
||||
# First the point is set to generator P
|
||||
# then with each iteration 2P, 4P, . . . doubling
|
||||
var points: array[len, EC]
|
||||
var point {.noInit.}: EC
|
||||
point.fromAffine(generator)
|
||||
|
||||
for i in 0 ..< len:
|
||||
points[i] = point
|
||||
point.double() #doubling the point
|
||||
|
||||
var arr: array[len, Bytes]
|
||||
let stat = arr.serializeBatch(points)
|
||||
|
||||
# Check if the serialization took place and in expected way
|
||||
doAssert stat == cttCodecEcc_Success, "Serialization Failed"
|
||||
|
||||
for i in 0 ..< len:
|
||||
doAssert expected_bit_strings[i] == arr[i].toHex(), "bit string does not match expected"
|
||||
|
||||
testBatchSerialize(expected_bit_strings.len)
|
Loading…
Reference in New Issue