2023-11-07 11:58:15 +01:00
|
|
|
import constantine/math/arithmetic
|
2023-07-28 22:10:14 +02:00
|
|
|
|
2023-10-24 13:57:47 +02:00
|
|
|
import poseidon2/types
|
2023-11-07 11:58:15 +01:00
|
|
|
import poseidon2/roundfun
|
2023-10-31 13:40:07 +01:00
|
|
|
import poseidon2/io
|
2023-07-28 22:10:14 +02:00
|
|
|
|
2023-11-02 10:31:26 +01:00
|
|
|
export toBytes
|
|
|
|
|
2023-07-28 22:10:14 +02:00
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
|
2023-11-07 11:58:15 +01:00
|
|
|
# the Poseidon2 permutation (mutable, in-place version)
|
|
|
|
proc permInplace*(x, y, z : var F) =
|
2023-11-13 11:34:19 +01:00
|
|
|
linearLayer(x, y, z)
|
2023-07-28 22:10:14 +02:00
|
|
|
for j in 0..3:
|
2023-10-24 14:16:54 +02:00
|
|
|
externalRound(j, x, y, z)
|
2023-07-28 22:10:14 +02:00
|
|
|
for j in 0..55:
|
2023-10-24 14:16:54 +02:00
|
|
|
internalRound(j, x, y, z)
|
2023-07-28 22:10:14 +02:00
|
|
|
for j in 4..7:
|
2023-10-24 14:16:54 +02:00
|
|
|
externalRound(j, x, y, z)
|
2023-07-28 22:10:14 +02:00
|
|
|
|
2023-11-07 11:58:15 +01:00
|
|
|
# the Poseidon2 permutation
|
2023-11-01 10:34:55 +01:00
|
|
|
func perm*(xyz: S) : S =
|
2023-07-28 22:10:14 +02:00
|
|
|
var (x,y,z) = xyz
|
2023-10-24 14:16:54 +02:00
|
|
|
permInplace(x, y, z)
|
2023-07-28 22:10:14 +02:00
|
|
|
return (x,y,z)
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
|
2023-11-13 11:34:19 +01:00
|
|
|
# sponge with rate=1 (capacity=2)
|
2023-11-07 11:58:15 +01:00
|
|
|
func spongeWithRate1*(xs: openArray[F]) : F =
|
|
|
|
var s0 : F = zero
|
|
|
|
var s1 : F = zero
|
2023-11-07 14:54:10 +01:00
|
|
|
var s2 : F = toF(0x0301) ; s2 += twoToThe64 # domain separation IV := (2^64 + 256*t + r)
|
2023-11-07 11:58:15 +01:00
|
|
|
|
2023-11-07 14:21:37 +01:00
|
|
|
for x in xs:
|
|
|
|
s0 += x
|
2023-11-07 11:58:15 +01:00
|
|
|
permInplace(s0,s1,s2)
|
|
|
|
|
|
|
|
# padding
|
2023-11-13 11:34:19 +01:00
|
|
|
s0 += one
|
2023-11-07 11:58:15 +01:00
|
|
|
permInplace(s0,s1,s2)
|
|
|
|
return s0
|
|
|
|
|
2023-11-13 11:34:19 +01:00
|
|
|
# sponge with rate=2 (capacity=1)
|
2023-11-07 11:58:15 +01:00
|
|
|
func spongeWithRate2*(xs: openArray[F]) : F =
|
|
|
|
let a = low(xs)
|
|
|
|
let b = high(xs)
|
|
|
|
let n = b-a+1
|
2023-11-13 11:34:19 +01:00
|
|
|
let halfn : int = n div 2
|
2023-11-07 11:58:15 +01:00
|
|
|
|
|
|
|
var s0 : F = zero
|
|
|
|
var s1 : F = zero
|
2023-11-07 14:54:10 +01:00
|
|
|
var s2 : F = toF(0x0302) ; s2 += twoToThe64 # domain separation IV := (2^64 + 256*t + r)
|
2023-11-07 11:58:15 +01:00
|
|
|
|
|
|
|
for i in 0..<halfn:
|
|
|
|
s0 += xs[a+2*i ]
|
|
|
|
s1 += xs[a+2*i+1]
|
|
|
|
permInplace(s0,s1,s2)
|
|
|
|
|
|
|
|
if (2*halfn == n):
|
|
|
|
# padding even input
|
|
|
|
s0 += one
|
|
|
|
s1 += zero
|
|
|
|
else:
|
|
|
|
# padding odd input
|
|
|
|
s0 += xs[b]
|
|
|
|
s1 += one
|
|
|
|
|
2023-11-13 11:34:19 +01:00
|
|
|
permInplace(s0,s1,s2)
|
2023-11-07 11:58:15 +01:00
|
|
|
return s0
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
# 2-to-1 compression
|
2023-11-01 10:34:55 +01:00
|
|
|
func compress*(a, b : F) : F =
|
2023-07-28 22:10:14 +02:00
|
|
|
var x = a
|
|
|
|
var y = b
|
|
|
|
var z : F ; setZero(z)
|
2023-10-24 14:16:54 +02:00
|
|
|
permInplace(x, y, z)
|
2023-07-28 22:10:14 +02:00
|
|
|
return x
|
|
|
|
|
2023-11-01 10:34:55 +01:00
|
|
|
func merkleRoot*(xs: openArray[F]) : F =
|
2023-07-28 22:10:14 +02:00
|
|
|
let a = low(xs)
|
|
|
|
let b = high(xs)
|
|
|
|
let m = b-a+1
|
|
|
|
|
|
|
|
if m==1:
|
|
|
|
return xs[a]
|
|
|
|
|
|
|
|
else:
|
|
|
|
let halfn : int = m div 2
|
|
|
|
let n : int = 2*halfn
|
2023-10-24 14:16:54 +02:00
|
|
|
let isOdd : bool = (n != m)
|
2023-10-24 13:55:04 +02:00
|
|
|
|
2023-11-09 10:20:10 +01:00
|
|
|
var ys : seq[F]
|
2023-10-24 14:16:54 +02:00
|
|
|
if not isOdd:
|
2023-11-09 10:20:10 +01:00
|
|
|
ys = newSeq[F](halfn)
|
2023-07-28 22:10:14 +02:00
|
|
|
else:
|
2023-11-09 10:20:10 +01:00
|
|
|
ys = newSeq[F](halfn+1)
|
|
|
|
|
|
|
|
for i in 0..<halfn:
|
|
|
|
ys[i] = compress( xs[a+2*i], xs[a+2*i+1] )
|
|
|
|
if isOdd:
|
|
|
|
ys[halfn] = compress( xs[n], zero )
|
2023-07-28 22:10:14 +02:00
|
|
|
|
2023-10-24 14:16:54 +02:00
|
|
|
return merkleRoot(ys)
|
2023-07-28 22:10:14 +02:00
|
|
|
|
2023-11-01 10:34:55 +01:00
|
|
|
func merkleRoot*(bytes: openArray[byte]): F =
|
2023-11-02 10:07:45 +01:00
|
|
|
merkleRoot(seq[F].fromBytes(bytes))
|
2023-11-07 11:58:15 +01:00
|
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|