mirror of
https://github.com/logos-storage/nim-poseidon2.git
synced 2026-02-17 12:13:36 +00:00
add Griffin permutation
This commit is contained in:
parent
d381c00874
commit
47df39467c
3
bench/.gitignore
vendored
Normal file
3
bench/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
.DS_Store
|
||||
bench_perm
|
||||
bench_griffin
|
||||
51
bench/bench_griffin.nim
Normal file
51
bench/bench_griffin.nim
Normal file
@ -0,0 +1,51 @@
|
||||
|
||||
#
|
||||
# nimble build -d:release
|
||||
#
|
||||
|
||||
import strformat
|
||||
# import strutils
|
||||
|
||||
import constantine/math/arithmetic
|
||||
import constantine/math/io/io_fields
|
||||
import constantine/math/io/io_bigints
|
||||
|
||||
import poseidon2/types
|
||||
import poseidon2/io
|
||||
import griffin/permutation
|
||||
|
||||
import ./shared
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
proc iteratePerm(n: int) =
|
||||
|
||||
var x: F = toF(0)
|
||||
var y: F = toF(1)
|
||||
var z: F = toF(2)
|
||||
|
||||
for i in 0..<n:
|
||||
permInPlace(x, y, z)
|
||||
|
||||
echo "x = ", toDecimal(x)
|
||||
echo "y = ", toDecimal(y)
|
||||
echo "z = ", toDecimal(z)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
when isMainModule:
|
||||
|
||||
testGriffin()
|
||||
echo "----------------------------------"
|
||||
|
||||
echo "quick & dirty Griffin benchmark"
|
||||
|
||||
let n: int = 100000
|
||||
|
||||
let text = fmt"{n} Grffin permutations"
|
||||
withMeasureTime(true,text):
|
||||
iteratePerm(n)
|
||||
|
||||
let mb = float64(n)*62.0/1024/1024
|
||||
echo fmt"that corresponds to about {mb:.2f} megabytes of linear hashing"
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
#
|
||||
|
||||
import strformat
|
||||
import times, os, strutils
|
||||
#import strutils
|
||||
|
||||
import constantine/math/arithmetic
|
||||
import constantine/math/io/io_fields
|
||||
@ -14,22 +14,7 @@ import poseidon2/types
|
||||
import poseidon2/io
|
||||
import poseidon2/permutation
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
func seconds*(x: float): string = fmt"{x:.4f} seconds"
|
||||
|
||||
func quoted*(s: string): string = fmt"`{s:s}`"
|
||||
|
||||
template withMeasureTime*(doPrint: bool, text: string, code: untyped) =
|
||||
block:
|
||||
if doPrint:
|
||||
let t0 = epochTime()
|
||||
code
|
||||
let elapsed = epochTime() - t0
|
||||
let elapsedStr = elapsed.formatFloat(format = ffDecimal, precision = 4)
|
||||
echo ( text & " took " & elapsedStr & " seconds" )
|
||||
else:
|
||||
code
|
||||
import ./shared
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
23
bench/shared.nim
Normal file
23
bench/shared.nim
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
import strformat
|
||||
import times, strutils
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
func seconds*(x: float): string = fmt"{x:.4f} seconds"
|
||||
|
||||
func quoted*(s: string): string = fmt"`{s:s}`"
|
||||
|
||||
template withMeasureTime*(doPrint: bool, text: string, code: untyped) =
|
||||
block:
|
||||
if doPrint:
|
||||
let t0 = epochTime()
|
||||
code
|
||||
let elapsed = epochTime() - t0
|
||||
let elapsedStr = elapsed.formatFloat(format = ffDecimal, precision = 4)
|
||||
echo ( text & " took " & elapsedStr & " seconds" )
|
||||
else:
|
||||
code
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
10
griffin/compress.nim
Normal file
10
griffin/compress.nim
Normal file
@ -0,0 +1,10 @@
|
||||
import ./types
|
||||
import ./permutation
|
||||
|
||||
# 2-to-1 compression
|
||||
func compress*(a, b : F, key = zero) : F =
|
||||
var x = a
|
||||
var y = b
|
||||
var z = key
|
||||
permInPlace(x, y, z)
|
||||
return x
|
||||
106
griffin/permutation.nim
Normal file
106
griffin/permutation.nim
Normal file
@ -0,0 +1,106 @@
|
||||
|
||||
import
|
||||
constantine/math/arithmetic,
|
||||
constantine/math/io/io_fields,
|
||||
constantine/math/io/io_bigints
|
||||
|
||||
import ../poseidon2/types
|
||||
import ./roundconst
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
const expo_inv : B = fromHex(B,"0x26b6a528b427b35493736af8679aad17535cb9d394945a0dcfe7f7a98ccccccd")
|
||||
|
||||
const alpha : F = fromHex(F,"0x146ecffb34a66316fae66609f78d1310bc14ad7208082ca7943afebb1da4aa4a")
|
||||
const beta : F = fromHex(F,"0x2b568115d544c7e941eff6ccc935384619b0fb7d2c5ba6c078c34cf81697ee1c")
|
||||
|
||||
const roundConstArray : array[33, F] = arrayFromHex( roundConstStr )
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
# inplace sbox, x => x^5
|
||||
proc pow5(x: var F) : void =
|
||||
var y = x
|
||||
square(y)
|
||||
square(y)
|
||||
x *= y
|
||||
|
||||
# inplace sbox, x => x^(1/5)
|
||||
proc powInv5(x: var F) : void =
|
||||
x = fastPow(x, expo_inv)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
proc sbox(x, y, z: var F) =
|
||||
x.powInv5()
|
||||
y.pow5()
|
||||
let u : F = x + y
|
||||
var m = beta
|
||||
m += sqr(u)
|
||||
m += alpha * u # m = u^2 + alpha*u + beta
|
||||
z *= m
|
||||
|
||||
proc addRC(round: int, x, y, z: var F) =
|
||||
if (round > 0):
|
||||
let j = (round-1) * 3
|
||||
x += roundConstArray[ j ]
|
||||
y += roundConstArray[ j+1 ]
|
||||
z += roundConstArray[ j+2 ]
|
||||
|
||||
proc linear(x, y, z : var F) =
|
||||
var s = x ; s += y ; s += z
|
||||
x += s
|
||||
y += s
|
||||
z += s
|
||||
|
||||
proc roundFun(round: int, x, y, z: var F) =
|
||||
addRC(round,x,y,z)
|
||||
sbox(x,y,z)
|
||||
linear(x,y,z)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
# the Griffin permutation (mutable, in-place version)
|
||||
proc permInPlace*(x, y, z : var F) =
|
||||
linear(x, y, z)
|
||||
for j in 0..<12:
|
||||
roundFun(j, x, y, z)
|
||||
|
||||
# the Griffin permutation (pure version)
|
||||
func perm*(xyz: S) : S =
|
||||
var (x,y,z) = xyz
|
||||
permInPlace(x, y, z)
|
||||
return (x,y,z)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
# known-answer test: the expected permutation of (0,1,2)
|
||||
const kat: S =
|
||||
( F.fromHex("0x2311cdb3076c3a7ee37fd5a271e0f3a8a3cc38057d0cea37b78951f43b1b6ff6")
|
||||
, F.fromHex("0x1d3aaed9ea361e899e667abd18e5328555b97b5c3890d52b261f940d6ab4df58")
|
||||
, F.fromHex("0x22614a0ac719cb623a636adac3bac1b85b5a7a418fcf8ab3a3ae0787fb4bed9d")
|
||||
)
|
||||
|
||||
proc sanityCheckExpoInv*() =
|
||||
let x0 : F = F.fromHex("0x666")
|
||||
var x : F = x0
|
||||
x.pow5()
|
||||
x.powInv5()
|
||||
echo "sanity check /a = " & $(x == x0)
|
||||
let y0 : F = F.fromHex("0x777017")
|
||||
var y : F = y0
|
||||
y.powInv5()
|
||||
y.pow5()
|
||||
echo "sanity check /b = " & $(y == y0)
|
||||
|
||||
proc testGriffin*() =
|
||||
sanityCheckExpoInv()
|
||||
let inp: S = (zero,one,two)
|
||||
let candidate = perm(inp)
|
||||
let (x,y,z) = candidate
|
||||
echo "x = " & $x.toDecimal()
|
||||
echo "y = " & $y.toDecimal()
|
||||
echo "z = " & $z.toDecimal()
|
||||
echo "KAT ok = " & $(candidate == kat)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
41
griffin/roundconst.nim
Normal file
41
griffin/roundconst.nim
Normal file
@ -0,0 +1,41 @@
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
const roundConstStr* : array[33, string] =
|
||||
[ "0x2fb30cafdb1f76156dfabf0cd0af4b895e764ac2a84386c9d0d7aed6a7f4eac9"
|
||||
, "0x282927892ce324572f19abb14871d2b539a80d8a5800cdb87a81e1697a94b6c9"
|
||||
, "0x03d0f3f2711dd59e3d97fc797261300cd3fee33b95cf710a32edf42aa2bc0905"
|
||||
, "0x036a8b3eb9ef35c74ea5a367ed279ee6d043d4ff69817f192c7251b91dcbb03d"
|
||||
, "0x2a626d396e7fa8ce8d6339bb37bd48491d56db0c7ac0afb5008a7464d5776a26"
|
||||
, "0x0cc9dfabbeaef7982543453ea3ac37ef2bfefd35a7e7070aa39b021035852d5b"
|
||||
, "0x2a1951149e2568ab28e972a2ceddc49eff0cae8e1cddcf4b0684a73a1b4ef61b"
|
||||
, "0x2d0ff8e9158b2fd7ae3afe01cf09d4ce9ff81e6127e441eb6cbc79d21f22be9e"
|
||||
, "0x1cc315b7ea0c1efb538f0c3248a7da062309a9e41af5a555c9ea9e8a10930cb5"
|
||||
, "0x03cb10093ea62fb3f6e5680a128d07112ee566f1b424558f2ec9d86892e13a80"
|
||||
, "0x12e7bb50ae7e9e90f1765c073eb61c4be4956c424930233ce497d2722a458868"
|
||||
, "0x006b1367547937ae71e2e9b55d2f90c90131f9e6784ce3de0eb314ec748871e7"
|
||||
, "0x1ffff572c53442c58809aeca02287839b11df1420deb0e99fde2baad8b86fa9c"
|
||||
, "0x13aefd685e7739f9a8b4ccdbfc5ef9e566149af4d54d6b746058ea44cb422840"
|
||||
, "0x1ea6c3ea93fe6f4ed0186941650de76ff94ab0e6e8a583996b67ba026dd2b7a5"
|
||||
, "0x288f120288f9225643de833c5c15e22aadd358132bbdc12c75109048a158c9f4"
|
||||
, "0x0f638114cd7c781ab299e5233338b00cf2996df962347a00146a22103d9ad91a"
|
||||
, "0x14eeca5fa2c18999ea25ddf44237d6ac3cb8757ea452f67e2590a46f7d5b1e4f"
|
||||
, "0x102d1a099e8cd107dc056e72370e340b0316d237b72d99ef6261761f7eb2d61c"
|
||||
, "0x0ef741fc2fcda50f207c759dbd844a4d630cc0e4062ca80f3ffba2cce2d3f51d"
|
||||
, "0x0989b9f642485692a1f91a4b207db64f38ae545bf3e0622f3862967d27f563db"
|
||||
, "0x1eb4d812c80ce04784a80c89fbcc5aab89db274c62602bdd30f3223655e6cf8a"
|
||||
, "0x0124a9400253731facd46e21f41016aed69a79087f81665bc5d29a34e4e924dd"
|
||||
, "0x2520bfa6b70e6ba7ad380aaf9015b71983868a9c53e66e685ed6e48692c185a8"
|
||||
, "0x1bd62b5bfa02667ac08d51d9e77bb3ab8dbd19e7a701442a20e23f7d3d6b28b4"
|
||||
, "0x1ae2f0d09fffc6bb869ebc639484a7c2084cfa3c1f88a7440713b1b154e5f952"
|
||||
, "0x0cd06e16a0d570c3799d800d92a25efbd44a795ed5b9114a28f5f869a57d9ba1"
|
||||
, "0x00691740e313922521fe8c4843355eff8de0f93d4f62df0fe48755b897881c39"
|
||||
, "0x19903aa449fe9c27ee9c8320e6915b50c2822e61ce894be72b47a449c5705762"
|
||||
, "0x126e801aae44016a35deceaa3eba6ccc341fa3c2a65ab3d021fcd39abd170e1b"
|
||||
, "0x1b0a98be27b54ac9d5d72b94187c991c1872cb2c7777c0e880f439c133971e8d"
|
||||
, "0x1e10a35afda2e5a173d4f3edecf29dacf51d8fac33d6bfb4088cc787ec647605"
|
||||
, "0x1793cda85abe2782ea8e911ce92bab59a8c68e0dd561a57b064bb233f109cc57"
|
||||
]
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
version = "0.1.0"
|
||||
author = "nim-poseidon2 authors"
|
||||
version = "0.1.0"
|
||||
author = "nim-poseidon2 authors"
|
||||
description = "Poseidon2 hash function"
|
||||
license = "MIT"
|
||||
license = "MIT"
|
||||
|
||||
requires "https://github.com/mratsim/constantine#bc3845aa492b52f7fef047503b1592e830d1a774"
|
||||
installExt = @["nim"]
|
||||
|
||||
bin = @["bench/bench_perm"]
|
||||
#requires "https://github.com/mratsim/constantine#bc3845aa492b52f7fef047503b1592e830d1a774"
|
||||
requires "https://github.com/mratsim/constantine#782d838e7a073262750eff593af6dfff3ff832dd"
|
||||
|
||||
bin = @["bench/bench_perm", "bench/bench_griffin"]
|
||||
@ -22,6 +22,7 @@ func getZero*() : F =
|
||||
|
||||
const zero* : F = getZero()
|
||||
const one* : F = fromHex(F,"0x01") # note: `fromUint()` does not work at compile time
|
||||
const two* : F = fromHex(F,"0x02")
|
||||
|
||||
const twoToThe64* : F = fromHex(F,"0x10000000000000000")
|
||||
|
||||
@ -39,5 +40,32 @@ func arrayFromHex*[N](
|
||||
tmp[i] = hexToF(inp[i], endian)
|
||||
return tmp
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
func `+`*(x, y: F): F = ( var z: F = x ; z += y ; return z )
|
||||
func `-`*(x, y: F): F = ( var z: F = x ; z -= y ; return z )
|
||||
func `*`*(x, y: F): F = ( var z: F = x ; z *= y ; return z )
|
||||
|
||||
func `==`*(a, b: F): bool =
|
||||
bool(arithmetic.`==`(a, b))
|
||||
|
||||
func sqr*(x : F): F =
|
||||
var y = x
|
||||
y.square()
|
||||
return y
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
func fastPow*(base: F, expo: B): F =
|
||||
var s : F = base
|
||||
var a : F = one
|
||||
var e : B = expo
|
||||
for i in 0..<254:
|
||||
if bool(isOdd(e)):
|
||||
a *= s
|
||||
s.square()
|
||||
e.div2()
|
||||
return a
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user