mirror of
https://github.com/logos-storage/nim-poseidon2-bn254.git
synced 2026-05-19 20:39:40 +00:00
add option to use the "new" round constants for Poseidon2 (see #25)
This commit is contained in:
parent
eb29fca52b
commit
7ae5c9a22a
2
.gitignore
vendored
2
.gitignore
vendored
@ -3,4 +3,4 @@
|
||||
!*.*
|
||||
.nimble
|
||||
poseidon2.out
|
||||
.DS_store
|
||||
.DS_store
|
||||
|
||||
17
README.md
17
README.md
@ -39,6 +39,23 @@ let right = Sponge.digest([4'u8, 5'u8, 6'u8])
|
||||
let combination = compress(left, right)
|
||||
```
|
||||
|
||||
Compatbility
|
||||
------------
|
||||
|
||||
For Poseidon2, because of a historical accident, there are unfortunately TWO
|
||||
different sets of "standard" parameters, which is obviously bad for cross-project compatibility.
|
||||
|
||||
The switchover happened in commit #bb476b9ca38198cf5092487283c8b8c5d4317c4e in
|
||||
HorizenLab's reference repo. Both versions are safe to use though.
|
||||
|
||||
To resolve this issue, since version 0.1.1, we implement both sets (though the default
|
||||
is the "old" set of round constants, so that we are backward compatible. This may
|
||||
or may not change in the future.)
|
||||
|
||||
|
||||
Links
|
||||
-----
|
||||
|
||||
[1]: https://eprint.iacr.org/2023/323.pdf
|
||||
[2]: https://github.com/mratsim/constantine
|
||||
[3]: https://github.com/nim-lang/nimble
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
author = "nim-poseidon2 authors"
|
||||
description = "Poseidon2 hash function"
|
||||
license = "MIT"
|
||||
|
||||
@ -2,9 +2,9 @@ import ./types
|
||||
import ./permutation
|
||||
|
||||
# 2-to-1 compression
|
||||
func compress*(a, b : F, key = zero) : F =
|
||||
func compression*(a, b : F, key = zero, which: static Flavour = HorizenLabsOld) : F =
|
||||
var x = a
|
||||
var y = b
|
||||
var z = key
|
||||
permInPlace(x, y, z)
|
||||
permInPlace(x, y, z, which = which)
|
||||
return x
|
||||
|
||||
@ -4,41 +4,44 @@ import ./types
|
||||
import ./io
|
||||
import ./compress
|
||||
|
||||
const KeyNone = F.fromHex("0x0")
|
||||
const KeyBottomLayer = F.fromHex("0x1")
|
||||
const KeyOdd = F.fromHex("0x2")
|
||||
const KeyNone = F.fromHex("0x0")
|
||||
const KeyBottomLayer = F.fromHex("0x1")
|
||||
const KeyOdd = F.fromHex("0x2")
|
||||
const KeyOddAndBottomLayer = F.fromhex("0x3")
|
||||
|
||||
type Merkle* = object
|
||||
todo: seq[F] # nodes that haven't been combined yet
|
||||
width: int # width of the current subtree
|
||||
leafs: int # amount of leafs processed
|
||||
type Merkle*[flavour: static Flavour] = object
|
||||
todo: seq[F] # nodes that haven't been combined yet
|
||||
width: int # width of the current subtree
|
||||
leafs: int # amount of leafs processed
|
||||
|
||||
func init*(_: type Merkle): Merkle =
|
||||
Merkle(width: 2)
|
||||
func init[which](merkle: var Merkle[which]) =
|
||||
merkle.width = 2
|
||||
|
||||
func compress(merkle: var Merkle, odd: static bool) =
|
||||
func init*(_: type Merkle, which: static Flavour = HorizenLabsOld): Merkle[which] =
|
||||
result.init
|
||||
|
||||
func compress[which](merkle: var Merkle[which], odd: static bool) =
|
||||
when odd:
|
||||
let a = merkle.todo.pop()
|
||||
let b = zero
|
||||
let key = if merkle.width == 2: KeyOddAndBottomLayer else: KeyOdd
|
||||
merkle.todo.add(compress(a, b, key = key))
|
||||
merkle.todo.add(compression(a, b, key = key, which = which))
|
||||
merkle.leafs += merkle.width div 2 # zero node represents this many leafs
|
||||
else:
|
||||
let b = merkle.todo.pop()
|
||||
let a = merkle.todo.pop()
|
||||
let key = if merkle.width == 2: KeyBottomLayer else: KeyNone
|
||||
merkle.todo.add(compress(a, b, key = key))
|
||||
merkle.todo.add(compression(a, b, key = key, which = which))
|
||||
merkle.width *= 2
|
||||
|
||||
func update*(merkle: var Merkle, element: F) =
|
||||
func update*[which](merkle: var Merkle[which], element: F) =
|
||||
merkle.todo.add(element)
|
||||
inc merkle.leafs
|
||||
merkle.width = 2
|
||||
while merkle.width <= merkle.leafs and merkle.leafs mod merkle.width == 0:
|
||||
merkle.compress(odd = false)
|
||||
|
||||
func finish*(merkle: var Merkle): F =
|
||||
func finish*[which](merkle: var Merkle[which]): F =
|
||||
assert merkle.todo.len > 0, "merkle root of empty sequence is not defined"
|
||||
|
||||
if merkle.leafs == 1:
|
||||
@ -52,14 +55,14 @@ func finish*(merkle: var Merkle): F =
|
||||
|
||||
return merkle.todo[0]
|
||||
|
||||
func digest*(_: type Merkle, elements: openArray[F]): F =
|
||||
var merkle = Merkle.init()
|
||||
func digest*(_: type Merkle, elements: openArray[F], which: static Flavour = HorizenLabsOld): F =
|
||||
var merkle = Merkle.init(which = which)
|
||||
for element in elements:
|
||||
merkle.update(element)
|
||||
return merkle.finish()
|
||||
|
||||
func digest*(_: type Merkle, bytes: openArray[byte]): F =
|
||||
var merkle = Merkle.init()
|
||||
func digest*(_: type Merkle, bytes: openArray[byte], which: static Flavour = HorizenLabsOld): F =
|
||||
var merkle = Merkle.init(which = which)
|
||||
for element in bytes.elements(F):
|
||||
merkle.update(element)
|
||||
return merkle.finish()
|
||||
|
||||
@ -1,18 +1,57 @@
|
||||
import ./types
|
||||
import ./roundfun
|
||||
|
||||
# the Poseidon2 permutation (mutable, in-place version)
|
||||
proc permInPlace*(x, y, z : var F) =
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
# the Poseidon2 permutation, "old" round constants (mutable, in-place version)
|
||||
proc permInPlaceOld(x, y, z : var F) =
|
||||
linearLayer(x, y, z)
|
||||
for j in 0..3:
|
||||
externalRound(j, x, y, z)
|
||||
externalRoundOld(j, x, y, z)
|
||||
for j in 0..55:
|
||||
internalRound(j, x, y, z)
|
||||
internalRoundOld(j, x, y, z)
|
||||
for j in 4..7:
|
||||
externalRound(j, x, y, z)
|
||||
externalRoundOld(j, x, y, z)
|
||||
|
||||
# the Poseidon2 permutation
|
||||
func perm*(xyz: S) : S =
|
||||
# the Poseidon2 permutation, "old" ronud constants
|
||||
func permOld(xyz: S) : S =
|
||||
var (x,y,z) = xyz
|
||||
permInPlace(x, y, z)
|
||||
permInPlaceOld(x, y, z)
|
||||
return (x,y,z)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
# the Poseidon2 permutation, "new" round constants (mutable, in-place version)
|
||||
proc permInPlaceNew(x, y, z : var F) =
|
||||
linearLayer(x, y, z)
|
||||
for j in 0..3:
|
||||
externalRoundNew(j, x, y, z)
|
||||
for j in 0..55:
|
||||
internalRoundNew(j, x, y, z)
|
||||
for j in 4..7:
|
||||
externalRoundNew(j, x, y, z)
|
||||
|
||||
# the Poseidon2 permutation, "new" ronud constants
|
||||
func permNew(xyz: S) : S =
|
||||
var (x,y,z) = xyz
|
||||
permInPlaceNew(x, y, z)
|
||||
return (x,y,z)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# selectable round constants
|
||||
|
||||
# the Poseidon2 permutation (mutable, in-place version)
|
||||
proc permInPlace*(x, y, z: var F, which: static Flavour = HorizenLabsOld) =
|
||||
case which
|
||||
of HorizenLabsOld: permInPlaceOld(x,y,z)
|
||||
of HorizenLabsNew: permInPlaceNew(x,y,z)
|
||||
|
||||
# the Poseidon2 permutation, "old" ronud constants
|
||||
func perm*(xyz: S, which: static Flavour = HorizenLabsOld) : S =
|
||||
var (x,y,z) = xyz
|
||||
case which
|
||||
of HorizenLabsOld: permInPlaceOld(x,y,z)
|
||||
of HorizenLabsNew: permInPlaceNew(x,y,z)
|
||||
return (x,y,z)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
99
poseidon2/roundconst_new.nim
Normal file
99
poseidon2/roundconst_new.nim
Normal file
@ -0,0 +1,99 @@
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
const externalRoundConstNewStr* : array[24, string] =
|
||||
[ "0x1d066a255517b7fd8bddd3a93f7804ef7f8fcde48bb4c37a59a09a1a97052816" ,
|
||||
"0x29daefb55f6f2dc6ac3f089cebcc6120b7c6fef31367b68eb7238547d32c1610" ,
|
||||
"0x1f2cb1624a78ee001ecbd88ad959d7012572d76f08ec5c4f9e8b7ad7b0b4e1d1" ,
|
||||
#
|
||||
"0x0aad2e79f15735f2bd77c0ed3d14aa27b11f092a53bbc6e1db0672ded84f31e5" ,
|
||||
"0x2252624f8617738cd6f661dd4094375f37028a98f1dece66091ccf1595b43f28" ,
|
||||
"0x1a24913a928b38485a65a84a291da1ff91c20626524b2b87d49f4f2c9018d735" ,
|
||||
#
|
||||
"0x22fc468f1759b74d7bfc427b5f11ebb10a41515ddff497b14fd6dae1508fc47a" ,
|
||||
"0x1059ca787f1f89ed9cd026e9c9ca107ae61956ff0b4121d5efd65515617f6e4d" ,
|
||||
"0x02be9473358461d8f61f3536d877de982123011f0bf6f155a45cbbfae8b981ce" ,
|
||||
#
|
||||
"0x0ec96c8e32962d462778a749c82ed623aba9b669ac5b8736a1ff3a441a5084a4" ,
|
||||
"0x292f906e073677405442d9553c45fa3f5a47a7cdb8c99f9648fb2e4d814df57e" ,
|
||||
"0x274982444157b86726c11b9a0f5e39a5cc611160a394ea460c63f0b2ffe5657e" ,
|
||||
#
|
||||
"0x1acd63c67fbc9ab1626ed93491bda32e5da18ea9d8e4f10178d04aa6f8747ad0" ,
|
||||
"0x19f8a5d670e8ab66c4e3144be58ef6901bf93375e2323ec3ca8c86cd2a28b5a5" ,
|
||||
"0x1c0dc443519ad7a86efa40d2df10a011068193ea51f6c92ae1cfbb5f7b9b6893" ,
|
||||
#
|
||||
"0x14b39e7aa4068dbe50fe7190e421dc19fbeab33cb4f6a2c4180e4c3224987d3d" ,
|
||||
"0x1d449b71bd826ec58f28c63ea6c561b7b820fc519f01f021afb1e35e28b0795e" ,
|
||||
"0x1ea2c9a89baaddbb60fa97fe60fe9d8e89de141689d1252276524dc0a9e987fc" ,
|
||||
#
|
||||
"0x0478d66d43535a8cb57e9c1c3d6a2bd7591f9a46a0e9c058134d5cefdb3c7ff1" ,
|
||||
"0x19272db71eece6a6f608f3b2717f9cd2662e26ad86c400b21cde5e4a7b00bebe" ,
|
||||
"0x14226537335cab33c749c746f09208abb2dd1bd66a87ef75039be846af134166" ,
|
||||
#
|
||||
"0x01fd6af15956294f9dfe38c0d976a088b21c21e4a1c2e823f912f44961f9a9ce" ,
|
||||
"0x18e5abedd626ec307bca190b8b2cab1aaee2e62ed229ba5a5ad8518d4e5f2a57" ,
|
||||
"0x0fc1bbceba0590f5abbdffa6d3b35e3297c021a3a409926d0e2d54dc1c84fda6" ,
|
||||
]
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
const internalRoundConstNewStr* : array[56, string] =
|
||||
[ "0x1a1d063e54b1e764b63e1855bff015b8cedd192f47308731499573f23597d4b5" ,
|
||||
"0x26abc66f3fdf8e68839d10956259063708235dccc1aa3793b91b002c5b257c37" ,
|
||||
"0x0c7c64a9d887385381a578cfed5aed370754427aabca92a70b3c2b12ff4d7be8" ,
|
||||
"0x1cf5998769e9fab79e17f0b6d08b2d1eba2ebac30dc386b0edd383831354b495" ,
|
||||
"0x0f5e3a8566be31b7564ca60461e9e08b19828764a9669bc17aba0b97e66b0109" ,
|
||||
"0x18df6a9d19ea90d895e60e4db0794a01f359a53a180b7d4b42bf3d7a531c976e" ,
|
||||
"0x04f7bf2c5c0538ac6e4b782c3c6e601ad0ea1d3a3b9d25ef4e324055fa3123dc" ,
|
||||
"0x29c76ce22255206e3c40058523748531e770c0584aa2328ce55d54628b89ebe6" ,
|
||||
"0x198d425a45b78e85c053659ab4347f5d65b1b8e9c6108dbe00e0e945dbc5ff15" ,
|
||||
"0x25ee27ab6296cd5e6af3cc79c598a1daa7ff7f6878b3c49d49d3a9a90c3fdf74" ,
|
||||
"0x138ea8e0af41a1e024561001c0b6eb1505845d7d0c55b1b2c0f88687a96d1381" ,
|
||||
"0x306197fb3fab671ef6e7c2cba2eefd0e42851b5b9811f2ca4013370a01d95687" ,
|
||||
"0x1a0c7d52dc32a4432b66f0b4894d4f1a21db7565e5b4250486419eaf00e8f620" ,
|
||||
"0x2b46b418de80915f3ff86a8e5c8bdfccebfbe5f55163cd6caa52997da2c54a9f" ,
|
||||
"0x12d3e0dc0085873701f8b777b9673af9613a1af5db48e05bfb46e312b5829f64" ,
|
||||
"0x263390cf74dc3a8870f5002ed21d089ffb2bf768230f648dba338a5cb19b3a1f" ,
|
||||
"0x0a14f33a5fe668a60ac884b4ca607ad0f8abb5af40f96f1d7d543db52b003dcd" ,
|
||||
"0x28ead9c586513eab1a5e86509d68b2da27be3a4f01171a1dd847df829bc683b9" ,
|
||||
"0x1c6ab1c328c3c6430972031f1bdb2ac9888f0ea1abe71cffea16cda6e1a7416c" ,
|
||||
"0x1fc7e71bc0b819792b2500239f7f8de04f6decd608cb98a932346015c5b42c94" ,
|
||||
"0x03e107eb3a42b2ece380e0d860298f17c0c1e197c952650ee6dd85b93a0ddaa8" ,
|
||||
"0x2d354a251f381a4669c0d52bf88b772c46452ca57c08697f454505f6941d78cd" ,
|
||||
"0x094af88ab05d94baf687ef14bc566d1c522551d61606eda3d14b4606826f794b" ,
|
||||
"0x19705b783bf3d2dc19bcaeabf02f8ca5e1ab5b6f2e3195a9d52b2d249d1396f7" ,
|
||||
"0x09bf4acc3a8bce3f1fcc33fee54fc5b28723b16b7d740a3e60cef6852271200e" ,
|
||||
"0x1803f8200db6013c50f83c0c8fab62843413732f301f7058543a073f3f3b5e4e" ,
|
||||
"0x0f80afb5046244de30595b160b8d1f38bf6fb02d4454c0add41f7fef2faf3e5c" ,
|
||||
"0x126ee1f8504f15c3d77f0088c1cfc964abcfcf643f4a6fea7dc3f98219529d78" ,
|
||||
"0x23c203d10cfcc60f69bfb3d919552ca10ffb4ee63175ddf8ef86f991d7d0a591" ,
|
||||
"0x2a2ae15d8b143709ec0d09705fa3a6303dec1ee4eec2cf747c5a339f7744fb94" ,
|
||||
"0x07b60dee586ed6ef47e5c381ab6343ecc3d3b3006cb461bbb6b5d89081970b2b" ,
|
||||
"0x27316b559be3edfd885d95c494c1ae3d8a98a320baa7d152132cfe583c9311bd" ,
|
||||
"0x1d5c49ba157c32b8d8937cb2d3f84311ef834cc2a743ed662f5f9af0c0342e76" ,
|
||||
"0x2f8b124e78163b2f332774e0b850b5ec09c01bf6979938f67c24bd5940968488" ,
|
||||
"0x1e6843a5457416b6dc5b7aa09a9ce21b1d4cba6554e51d84665f75260113b3d5" ,
|
||||
"0x11cdf00a35f650c55fca25c9929c8ad9a68daf9ac6a189ab1f5bc79f21641d4b" ,
|
||||
"0x21632de3d3bbc5e42ef36e588158d6d4608b2815c77355b7e82b5b9b7eb560bc" ,
|
||||
"0x0de625758452efbd97b27025fbd245e0255ae48ef2a329e449d7b5c51c18498a" ,
|
||||
"0x2ad253c053e75213e2febfd4d976cc01dd9e1e1c6f0fb6b09b09546ba0838098" ,
|
||||
"0x1d6b169ed63872dc6ec7681ec39b3be93dd49cdd13c813b7d35702e38d60b077" ,
|
||||
"0x1660b740a143664bb9127c4941b67fed0be3ea70a24d5568c3a54e706cfef7fe" ,
|
||||
"0x0065a92d1de81f34114f4ca2deef76e0ceacdddb12cf879096a29f10376ccbfe" ,
|
||||
"0x1f11f065202535987367f823da7d672c353ebe2ccbc4869bcf30d50a5871040d" ,
|
||||
"0x26596f5c5dd5a5d1b437ce7b14a2c3dd3bd1d1a39b6759ba110852d17df0693e" ,
|
||||
"0x16f49bc727e45a2f7bf3056efcf8b6d38539c4163a5f1e706743db15af91860f" ,
|
||||
"0x1abe1deb45b3e3119954175efb331bf4568feaf7ea8b3dc5e1a4e7438dd39e5f" ,
|
||||
"0x0e426ccab66984d1d8993a74ca548b779f5db92aaec5f102020d34aea15fba59" ,
|
||||
"0x0e7c30c2e2e8957f4933bd1942053f1f0071684b902d534fa841924303f6a6c6" ,
|
||||
"0x0812a017ca92cf0a1622708fc7edff1d6166ded6e3528ead4c76e1f31d3fc69d" ,
|
||||
"0x21a5ade3df2bc1b5bba949d1db96040068afe5026edd7a9c2e276b47cf010d54" ,
|
||||
"0x01f3035463816c84ad711bf1a058c6c6bd101945f50e5afe72b1a5233f8749ce" ,
|
||||
"0x0b115572f038c0e2028c2aafc2d06a5e8bf2f9398dbd0fdf4dcaa82b0f0c1c8b" ,
|
||||
"0x1c38ec0b99b62fd4f0ef255543f50d2e27fc24db42bc910a3460613b6ef59e2f" ,
|
||||
"0x1c89c6d9666272e8425c3ff1f4ac737b2f5d314606a297d4b1d0b254d880c53e" ,
|
||||
"0x03326e643580356bf6d44008ae4c042a21ad4880097a5eb38b71e2311bb88f8f" ,
|
||||
"0x268076b0054fb73f67cee9ea0e51e3ad50f27a6434b5dceb5bdde2299910a4c9" ,
|
||||
]
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
@ -1,8 +1,7 @@
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
const externalRoundConstStr* : array[24, string] =
|
||||
const externalRoundConstOldStr* : array[24, string] =
|
||||
[ "0x2c4c51fd1bb9567c27e99f5712b49e0574178b41b6f0a476cddc41d242cf2b43" ,
|
||||
"0x1c5f8d18acb9c61ec6fcbfcda5356f1b3fdee7dc22c99a5b73a2750e5b054104" ,
|
||||
"0x2d3c1988b4541e4c045595b8d574e98a7c2820314a82e67a4e380f1c4541ba90" ,
|
||||
@ -38,7 +37,7 @@ const externalRoundConstStr* : array[24, string] =
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
const internalRoundConstStr* : array[56, string] =
|
||||
const internalRoundConstOldStr* : array[56, string] =
|
||||
[ "0x15ce7e5ae220e8623a40b3a3b22d441eff0c9be1ae1d32f1b777af84eea7e38c" ,
|
||||
"0x1bf60ac8bfff0f631983c93e218ca0d4a4059c254b4299b1d9984a07edccfaf0" ,
|
||||
"0x0fab0c9387cb2bec9dc11b2951088b9e1e1d2978542fc131f74a8f8fdac95b40" ,
|
||||
@ -3,12 +3,16 @@ import
|
||||
constantine/named/algebras
|
||||
|
||||
import ./types
|
||||
import ./roundconst
|
||||
import ./roundconst_old
|
||||
import ./roundconst_new
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
const externalRoundConst : array[24, F] = arrayFromHex( externalRoundConstStr )
|
||||
const internalRoundConst : array[56, F] = arrayFromHex( internalRoundConstStr )
|
||||
const externalRoundConstOld : array[24, F] = arrayFromHex( externalRoundConstOldStr )
|
||||
const internalRoundConstOld : array[56, F] = arrayFromHex( internalRoundConstOldStr )
|
||||
|
||||
const externalRoundConstNew : array[24, F] = arrayFromHex( externalRoundConstNewStr )
|
||||
const internalRoundConstNew : array[56, F] = arrayFromHex( internalRoundConstNewStr )
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
@ -25,8 +29,10 @@ func linearLayer*(x, y, z : var F) =
|
||||
y += s
|
||||
z += s
|
||||
|
||||
func internalRound*(j: int; x, y, z: var F) =
|
||||
x += internalRoundConst[j]
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
func internalRoundOld*(j: int; x, y, z: var F) =
|
||||
x += internalRoundConstOld[j]
|
||||
sbox(x)
|
||||
var s = x ; s += y ; s += z
|
||||
double(z)
|
||||
@ -34,10 +40,10 @@ func internalRound*(j: int; x, y, z: var F) =
|
||||
y += s
|
||||
z += s
|
||||
|
||||
func externalRound*(j: int; x, y, z : var F) =
|
||||
x += externalRoundConst[3*j+0]
|
||||
y += externalRoundConst[3*j+1]
|
||||
z += externalRoundConst[3*j+2]
|
||||
func externalRoundOld*(j: int; x, y, z : var F) =
|
||||
x += externalRoundConstOld[3*j+0]
|
||||
y += externalRoundConstOld[3*j+1]
|
||||
z += externalRoundConstOld[3*j+2]
|
||||
sbox(x) ; sbox(y) ; sbox(z)
|
||||
var s = x ; s += y ; s += z
|
||||
x += s
|
||||
@ -46,3 +52,23 @@ func externalRound*(j: int; x, y, z : var F) =
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
func internalRoundNew*(j: int; x, y, z: var F) =
|
||||
x += internalRoundConstNew[j]
|
||||
sbox(x)
|
||||
var s = x ; s += y ; s += z
|
||||
double(z)
|
||||
x += s
|
||||
y += s
|
||||
z += s
|
||||
|
||||
func externalRoundNew*(j: int; x, y, z : var F) =
|
||||
x += externalRoundConstNew[3*j+0]
|
||||
y += externalRoundConstNew[3*j+1]
|
||||
z += externalRoundConstNew[3*j+2]
|
||||
sbox(x) ; sbox(y) ; sbox(z)
|
||||
var s = x ; s += y ; s += z
|
||||
x += s
|
||||
y += s
|
||||
z += s
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
@ -5,31 +5,37 @@ import constantine/math/io/io_fields
|
||||
import constantine/math/arithmetic
|
||||
|
||||
type
|
||||
Sponge*[rate: static int] = object
|
||||
Sponge*[rate: static int, flavour: static Flavour] = object
|
||||
s0: F
|
||||
s1: F
|
||||
s2: F
|
||||
when rate == 2:
|
||||
even: bool
|
||||
|
||||
func init(sponge: var Sponge[1]) =
|
||||
#-------------------------------------------------------------------------------
|
||||
# rate = 1
|
||||
|
||||
func init[which](sponge: var Sponge[1,which]) =
|
||||
# domain separation IV := (2^64 + 256*t + r)
|
||||
const IV = F.fromHex("0x10000000000000301")
|
||||
sponge.s0 = zero
|
||||
sponge.s1 = zero
|
||||
sponge.s2 = IV
|
||||
|
||||
func update*(sponge: var Sponge[1], element: F) =
|
||||
func update*[which](sponge: var Sponge[1,which], element: F) = # , which: static Flavour = HorizenLabsOld) =
|
||||
sponge.s0 += element
|
||||
permInPlace(sponge.s0, sponge.s1, sponge.s2)
|
||||
permInPlace(sponge.s0, sponge.s1, sponge.s2, which = which)
|
||||
|
||||
func finish*(sponge: var Sponge[1]): F =
|
||||
func finish*[which](sponge: var Sponge[1,which]): F = # , which: static Flavour = HorizenLabsOld): F =
|
||||
# padding
|
||||
sponge.s0 += one
|
||||
permInPlace(sponge.s0, sponge.s1, sponge.s2)
|
||||
permInPlace(sponge.s0, sponge.s1, sponge.s2, which = which)
|
||||
return sponge.s0
|
||||
|
||||
func init(sponge: var Sponge[2]) =
|
||||
#-------------------------------------------------------------------------------
|
||||
# rate = 2
|
||||
|
||||
func init[which](sponge: var Sponge[2,which]) =
|
||||
# domain separation IV := (2^64 + 256*t + r)
|
||||
const IV = F.fromHex("0x10000000000000302")
|
||||
sponge.s0 = zero
|
||||
@ -37,15 +43,15 @@ func init(sponge: var Sponge[2]) =
|
||||
sponge.s2 = IV
|
||||
sponge.even = true
|
||||
|
||||
func update*(sponge: var Sponge[2], element: F) =
|
||||
func update*[which](sponge: var Sponge[2,which], element: F) = # , which: static Flavour = HorizenLabsOld) =
|
||||
if sponge.even:
|
||||
sponge.s0 += element
|
||||
else:
|
||||
sponge.s1 += element
|
||||
permInPlace(sponge.s0, sponge.s1, sponge.s2)
|
||||
permInPlace(sponge.s0, sponge.s1, sponge.s2, which = which)
|
||||
sponge.even = not sponge.even
|
||||
|
||||
func finish*(sponge: var Sponge[2]): F =
|
||||
func finish*[which](sponge: var Sponge[2,which]): F = #: static Flavour = HorizenLabsOld): F =
|
||||
if sponge.even:
|
||||
# padding even input
|
||||
sponge.s0 += one
|
||||
@ -53,22 +59,25 @@ func finish*(sponge: var Sponge[2]): F =
|
||||
else:
|
||||
# padding odd input
|
||||
sponge.s1 += one
|
||||
permInPlace(sponge.s0, sponge.s1, sponge.s2)
|
||||
permInPlace(sponge.s0, sponge.s1, sponge.s2, which = which)
|
||||
return sponge.s0
|
||||
|
||||
func init*(_: type Sponge, rate: static int = 2): Sponge[rate] =
|
||||
#-------------------------------------------------------------------------------
|
||||
# generic
|
||||
|
||||
func init*(_: type Sponge, rate: static int = 2, which: static Flavour = HorizenLabsOld): Sponge[rate,which] =
|
||||
when rate notin {1, 2}:
|
||||
{.error: "only rate 1 and 2 are supported".}
|
||||
result.init
|
||||
|
||||
func digest*(_: type Sponge, elements: openArray[F], rate: static int = 2): F =
|
||||
var sponge = Sponge.init(rate)
|
||||
func digest*(_: type Sponge, elements: openArray[F], rate: static int = 2, which: static Flavour = HorizenLabsOld): F =
|
||||
var sponge = Sponge.init(rate = rate, which = which)
|
||||
for element in elements:
|
||||
sponge.update(element)
|
||||
return sponge.finish()
|
||||
|
||||
func digest*(_: type Sponge, bytes: openArray[byte], rate: static int = 2): F =
|
||||
var sponge = Sponge.init(rate)
|
||||
func digest*(_: type Sponge, bytes: openArray[byte], rate: static int = 2, which: static Flavour = HorizenLabsOld): F =
|
||||
var sponge = Sponge.init(rate = rate, which = which)
|
||||
for element in bytes.elements(F):
|
||||
sponge.update(element)
|
||||
return sponge.finish()
|
||||
|
||||
@ -2,23 +2,26 @@ import ./types
|
||||
import ./merkle
|
||||
import ./sponge
|
||||
|
||||
type SpongeMerkle* = object
|
||||
merkle: Merkle
|
||||
type SpongeMerkle*[flavour: static Flavour] = object
|
||||
merkle: Merkle[flavour]
|
||||
|
||||
func init*(_: type SpongeMerkle): SpongeMerkle =
|
||||
SpongeMerkle(merkle: Merkle.init())
|
||||
func init[which](spongemerkle: var SpongeMerkle[which]) =
|
||||
spongemerkle.merkle = Merkle.init(which = which)
|
||||
|
||||
func update*(spongemerkle: var SpongeMerkle, chunk: openArray[byte]) =
|
||||
let digest = Sponge.digest(chunk, rate = 2)
|
||||
func init*(_: type SpongeMerkle, which: static Flavour = HorizenLabsOld): SpongeMerkle[which] =
|
||||
result.init
|
||||
|
||||
func update*[which](spongemerkle: var SpongeMerkle[which], chunk: openArray[byte]) =
|
||||
let digest = Sponge.digest(chunk, rate = 2, which = which)
|
||||
spongemerkle.merkle.update(digest)
|
||||
|
||||
func finish*(spongemerkle: var SpongeMerkle): F =
|
||||
func finish*[which](spongemerkle: var SpongeMerkle[which]): F =
|
||||
return spongemerkle.merkle.finish()
|
||||
|
||||
func digest*(_: type SpongeMerkle, bytes: openArray[byte], chunkSize: int): F =
|
||||
func digest*(_: type SpongeMerkle, bytes: openArray[byte], chunkSize: int, which: static Flavour = HorizenLabsOld): F =
|
||||
## Hashes chunks of data with a sponge of rate 2, and combines the
|
||||
## resulting chunk hashes in a merkle root.
|
||||
var spongemerkle = SpongeMerkle.init()
|
||||
var spongemerkle = SpongeMerkle.init(which = which)
|
||||
var index = 0
|
||||
while index < bytes.len:
|
||||
let start = index
|
||||
|
||||
@ -7,6 +7,25 @@ import
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
#
|
||||
# Note: Because of a historical accident, there are unfortunately TWO different sets
|
||||
# of "standard" parameters, which is obviously bad for cross-project compatibility.
|
||||
#
|
||||
# the switchover happened at 2023/06/23 in the commit
|
||||
# <https://github.com/HorizenLabs/poseidon2/commit/bb476b9ca38198cf5092487283c8b8c5d4317c4e>
|
||||
#
|
||||
# You can use this type to select between the two. The default is the "old" set.
|
||||
#
|
||||
type Flavour* = enum
|
||||
HorizenLabsOld # the "old" round constants
|
||||
HorizenLabsNew # the "new" round constants
|
||||
|
||||
type SpongeInput* = enum
|
||||
ByteString # the input of the hash is a sequence of bytes
|
||||
FieldElements # the input of the hash is a sequence of BN254 field elements
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
type B* = BigInt[254]
|
||||
type F* = Fr[BN254_Snarks]
|
||||
type S* = (F,F,F)
|
||||
|
||||
@ -5,11 +5,15 @@ import poseidon2/types
|
||||
import poseidon2/io
|
||||
import poseidon2/compress
|
||||
|
||||
const KeyNone = F.fromHex("0x0")
|
||||
const KeyBottomLayer = F.fromHex("0x1")
|
||||
const KeyOdd = F.fromHex("0x2")
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
const KeyNone = F.fromHex("0x0")
|
||||
const KeyBottomLayer = F.fromHex("0x1")
|
||||
const KeyOdd = F.fromHex("0x2")
|
||||
const KeyOddAndBottomLayer = F.fromhex("0x3")
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
# Reference implementation of merkle root algorithm
|
||||
# Only used in tests
|
||||
func merkleRoot(xs: openArray[F], isBottomLayer: static bool) : F =
|
||||
@ -36,10 +40,10 @@ func merkleRoot(xs: openArray[F], isBottomLayer: static bool) : F =
|
||||
|
||||
for i in 0..<halfn:
|
||||
const key = when isBottomLayer: KeyBottomLayer else: KeyNone
|
||||
ys[i] = compress( xs[a+2*i], xs[a+2*i+1], key = key )
|
||||
ys[i] = compression( xs[a+2*i], xs[a+2*i+1], key = key )
|
||||
if isOdd:
|
||||
const key = when isBottomLayer: KeyOddAndBottomLayer else: KeyOdd
|
||||
ys[halfn] = compress( xs[n], zero, key = key )
|
||||
ys[halfn] = compression( xs[n], zero, key = key )
|
||||
|
||||
return merkleRoot(ys, isBottomLayer = false)
|
||||
|
||||
@ -48,3 +52,5 @@ func merkleRoot*(xs: openArray[F]) : F =
|
||||
|
||||
func merkleRoot*(bytes: openArray[byte]): F =
|
||||
merkleRoot(toSeq bytes.elements(F))
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
@ -7,9 +7,9 @@ import poseidon2/compress
|
||||
suite "compress":
|
||||
|
||||
test "uses permutation to compress two elements":
|
||||
check bool(compress(1.toF, 2.toF) == (1.toF, 2.toF, 0.toF).perm[0])
|
||||
check bool(compress(3.toF, 4.toF) == (3.toF, 4.toF, 0.toF).perm[0])
|
||||
check bool(compression(1.toF, 2.toF) == (1.toF, 2.toF, 0.toF).perm[0])
|
||||
check bool(compression(3.toF, 4.toF) == (3.toF, 4.toF, 0.toF).perm[0])
|
||||
|
||||
test "allows for keyed compression":
|
||||
check bool(compress(1.toF, 2.toF, key=3.toF) == (1.toF, 2.toF, 3.toF).perm[0])
|
||||
check bool(compress(4.toF, 5.toF, key=6.toF) == (4.toF, 5.toF, 6.toF).perm[0])
|
||||
check bool(compression(1.toF, 2.toF, key=3.toF) == (1.toF, 2.toF, 3.toF).perm[0])
|
||||
check bool(compression(4.toF, 5.toF, key=6.toF) == (4.toF, 5.toF, 6.toF).perm[0])
|
||||
|
||||
@ -17,7 +17,9 @@ import poseidon2/merkle
|
||||
import ./fuzzing
|
||||
import ./reference
|
||||
|
||||
suite "merkle root":
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
suite "merkle root (old round constants)":
|
||||
|
||||
const isBottomLayer = 1
|
||||
const isOddNode = 2
|
||||
@ -34,17 +36,17 @@ suite "merkle root":
|
||||
|
||||
test "merkle root of even elements":
|
||||
let elements = toSeq(1..4).mapIt(toF(it))
|
||||
let expected = compress(
|
||||
compress(1.toF, 2.toF, key = isBottomLayer.toF),
|
||||
compress(3.toF, 4.toF, key = isBottomLayer.toF),
|
||||
let expected = compression(
|
||||
compression(1.toF, 2.toF, key = isBottomLayer.toF),
|
||||
compression(3.toF, 4.toF, key = isBottomLayer.toF),
|
||||
)
|
||||
check bool(Merkle.digest(elements) == expected)
|
||||
|
||||
test "merkle root of odd elements":
|
||||
let elements = toSeq(1..3).mapIt(toF(it))
|
||||
let expected = compress(
|
||||
compress(1.toF, 2.toF, key = isBottomLayer.toF),
|
||||
compress(3.toF, 0.toF, key = (isBottomLayer + isOddNode).toF)
|
||||
let expected = compression(
|
||||
compression(1.toF, 2.toF, key = isBottomLayer.toF),
|
||||
compression(3.toF, 0.toF, key = (isBottomLayer + isOddNode).toF)
|
||||
)
|
||||
check bool(Merkle.digest(elements) == expected)
|
||||
|
||||
@ -81,7 +83,30 @@ suite "merkle root":
|
||||
let empty = seq[byte].default
|
||||
check Merkle.digest(empty).toBytes.toHex == "0xcc8da1d157900e611b89e258d95450e707f4f9eec169422d7c26aba54f803c08"
|
||||
|
||||
suite "merkle root test vectors":
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
suite "merkle root probabilistic test (seed: " & $fuzzing.seed & ")":
|
||||
|
||||
test "merkle root algorithm matches reference implementation":
|
||||
|
||||
proc checkInput(input: seq[byte]) =
|
||||
let expected = reference.merkleRoot(input)
|
||||
check bool(Merkle.digest(input) == expected)
|
||||
|
||||
# a couple of tests with small input
|
||||
for _ in 0..<1000:
|
||||
let len = rand(1024)
|
||||
let input = newSeqwith(len, byte.rand())
|
||||
checkInput(input)
|
||||
|
||||
# one test with larger input
|
||||
let len = rand(1024 * 1024)
|
||||
let input = newSeqwith(len, byte.rand())
|
||||
checkInput(input)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
suite "merkle root test vectors (old round constants)":
|
||||
|
||||
test "field elements":
|
||||
|
||||
@ -224,21 +249,151 @@ suite "merkle root test vectors":
|
||||
let root = Merkle.digest(input)
|
||||
check root.toDecimal == expected[n]
|
||||
|
||||
suite "merkle root fuzzing (seed: " & $fuzzing.seed & ")":
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
test "merkle root algorithm matches reference implementation":
|
||||
suite "merkle root test vectors (new round constants)":
|
||||
|
||||
proc checkInput(input: seq[byte]) =
|
||||
let expected = reference.merkleRoot(input)
|
||||
check bool(Merkle.digest(input) == expected)
|
||||
test "field elements":
|
||||
|
||||
const expected = [
|
||||
"18732683119498402220900273862328991850071867550460350301906225211930820497246",
|
||||
"20044485856448945219360893405968170246210313782806884524691942318885527485620",
|
||||
"06879156331453065561412171404688536694163751033054206900049615566816845240638",
|
||||
"10573156824103477315213167903522304842945545228260194505071041398610725747027",
|
||||
"06384441629309812517061530283473905459834139895523812419737874603741167883751",
|
||||
"01971250361953534862485856004061479126145269783367209715512197349658074388513",
|
||||
"07880478051115466397651760556452850966415510478374824691540522067079012008848",
|
||||
"01588427217707334311194748465055445447386590515144208471159395360876596354896",
|
||||
"09845833165176316017310739746926711006998448994374103176753950446959241544949",
|
||||
"05401080693582495042221036612711192243397119342275570141068847210454146432971",
|
||||
"14979541340966695088021593909504702984608154332274504665382688317350089624983",
|
||||
"06607457335668542852281630717663887713758119594332918998385113363122923272454",
|
||||
"16944531731230336601405766048044116440488450625877275170244752673232813024368",
|
||||
"10505627725719291383716848804809239161132464233693421875021763993166626150955",
|
||||
"04903777673741595493881538453920061011471375126044729119229615357995429924907",
|
||||
"21181035192839738728235444431495555418889580879577305428953424496049840916480",
|
||||
"11221834706496996790865390579246001625017536676754935789453166684523452746294",
|
||||
"12238404452391357862009969266413532836848829207794340659891644015375290333575",
|
||||
"15708155082009131580754579627793300299188575609367253204313006197006278683451",
|
||||
"05517504412493805370300513465650653794195620677809004623411733389887578459282",
|
||||
"08080378887214146109958442876960165426094127534771411925984754489769775639602",
|
||||
"21516654090516357344488827195395654437927570305499499742967859768435792307023",
|
||||
"16287982214682712037347824797340080237681108979031916798200981723277747155615",
|
||||
"05685694773867255011952458685571219976401216436606262788193180342867328292265",
|
||||
"19526583356928859196877033020146794422218124413645406452689254965333914794652",
|
||||
"10848675323512546969760110872496371397468046019826794338866209820503017218094",
|
||||
"13098526947453076378732134736412645888623373165290562658402930812057369083031",
|
||||
"15807622910178811742015251785595269484031937827970627692880877492771583344913",
|
||||
"20947539376392019997058776157314032851916875769916485553613013444732706809995",
|
||||
"06753553250505666793155665320322498674458995022023435974225627770488883070427",
|
||||
"12913052272470117275730885267996789708916674339661588942669672432637118634497",
|
||||
"07140273523155025758656457959906703903322517942895250064763067836921533208395",
|
||||
"05096662479734546861171656420468400853646484716237537698088073264461873771495",
|
||||
"21847244193600328566028581147884321487732092052029068139956887865853549271044",
|
||||
"04009300188097479536921010252828669329555099893330885488914174883959723200864",
|
||||
"01108208796576758491952732089790509068885986934320479897801398052416369133702",
|
||||
"12022673388847471818443290403136143220719926934175085921434129203855416578111",
|
||||
"05819404042502021014554003343904170186243658973014335704550865178124828029416",
|
||||
"03431622978992796113672165915766558274905154096989369505325925792960764575098",
|
||||
"21197221572137839559575525886358498768936158674846428380707117122383064595523",
|
||||
]
|
||||
|
||||
for n in 1..40:
|
||||
let input = collect(newSeq, (for i in 1..n: i.toF))
|
||||
let root = Merkle.digest(input, which = HorizenLabsNew)
|
||||
check root.toDecimal == expected[n-1]
|
||||
|
||||
test "byte sequences":
|
||||
|
||||
const expected = [
|
||||
"18732683119498402220900273862328991850071867550460350301906225211930820497246",
|
||||
"13735371274317768426952305440092275471527240089113890985205909417533082052161",
|
||||
"01311071961332533862186884301632696142957410402596019316669626736502537000889",
|
||||
"02732096009327439956212066624821392049652901875129572813384220656784351269382",
|
||||
"15423519270040218946738369930755030045776747564707203916774547968486143247994",
|
||||
"16587777788369780003816229389975083731089468255710141313765204301889946667321",
|
||||
"15467495943722300538335131871441595157717335944259983129940442333130468249046",
|
||||
"12527384548927470515835422807488513691936613642840447225072462058897980963278",
|
||||
"01139622705334920884613960529662561931290307895998519853900505522690434305790",
|
||||
"16142107018442488373169352233589562161473473199353653887317707621603496902013",
|
||||
"01218040156344910251164083693083660612241041250293971471697358991836822822934",
|
||||
"14539670015608455813987910907856931443374437516459905847769109889483291930300",
|
||||
"13353935346055642659293878610542225936509964651938066706616162909789461560750",
|
||||
"19495252482428174907319709455764531263442594194178108741867624978172092574227",
|
||||
"17055391791505391005929832241289369835820574650534395529091050296974173444277",
|
||||
"10417815964043008188415968748256260933806143076096615775214277808070524853959",
|
||||
"17945990364004604436096932654837214363142551400871535149566763159356745021512",
|
||||
"05378474743511544609549364900907631460628411295768446396969606581840271320568",
|
||||
"10450818732527136839687818779067442575415758953761064564282786172271412091587",
|
||||
"16847813351440402327481696819486626114403025989665751639642247984422675096326",
|
||||
"16080420769027449065496681277508228557905448140947486066822638715407253102529",
|
||||
"08366919306715136985214953211615165017170848892014972526274387139637478691525",
|
||||
"19593395325880869057374643800035865356675830852145079290814753209650856975359",
|
||||
"00384182859815513385839420639647792149090846462738920946060726294059360780469",
|
||||
"02335931047212737616310219435914099319569437579961124983734763256150543971083",
|
||||
"17349766852945185312093195812550823004516165462687415856428045793735407024063",
|
||||
"01235143425552210458738643007111256946993802458731558186823661227715761468007",
|
||||
"20693990524627292843499617812340491230302068522547584302944531530021746113496",
|
||||
"18543804617969174119455058085898304136748236983116873040515022303109404769741",
|
||||
"13926603399214407946814826425691118516102928458497586045312244959900994096091",
|
||||
"16078981339237308383481231577786535454215521941758594174487496883608824711558",
|
||||
"17950345918051992105102682100290048318931240905222777741695436091652103456344",
|
||||
"09678874147582164379140871763209654777121789739582531437661370366499830892962",
|
||||
"13383628345880432589378013903652289170303171988979847033019029235910629261984",
|
||||
"06399788198102776237116949116572858190891055708099550677688992960248178791158",
|
||||
"12285638521053457620056734369275700401462483768944358177245989895025490940187",
|
||||
"11023910112243505257057851359408986450784351472530106441269959978534967412352",
|
||||
"10624778787578691366563571801850560225032213384911218497837418378958818487516",
|
||||
"12535534013320082535133438806894226954140008263818565396776040640374989498871",
|
||||
"19933288905658378276606393016274134348291434435644657680465855174415264542633",
|
||||
"06261150612607282233804570001150890371423227569588115985188186624749598110314",
|
||||
"14485422958846313827372029273530929972217133403908862421592563787636725012150",
|
||||
"12655195977124373992411099368455139921901944309142105714605662732356389040161",
|
||||
"14559778810504702456139696792145743036648283769314917401383198598644089445099",
|
||||
"12228495056709587360202879660468842743300166058897448810505310746824724390060",
|
||||
"20864102288287485825758511230410936572570242864092892632836899001360469365611",
|
||||
"08036843746026651704885811598854785242917910516698035692125001933569172974778",
|
||||
"02473994388543678509867095655309280072095060173737314045638436237839871815768",
|
||||
"16041637039328926785476935338433435740725771162819735004294804154626351596513",
|
||||
"17521465549586968141705974423416467389385988509692267225226615599418570155107",
|
||||
"09997532745735533430076017865915454770069450189257227272088477706570383058659",
|
||||
"12919418194728984703475519845421880597297152049285440089486588762412519942191",
|
||||
"13523007876706751682472404373209870560818417675183789073245402883976279224422",
|
||||
"07515347837520015754253656443014231071504485759795690381509678821970294600877",
|
||||
"10970160441525076388099216058743216953442053470534974095873799469283344672188",
|
||||
"06614735377319377745838393344721797713058517520450885046647342813882495568532",
|
||||
"12094237356602114373376154102675080427659391910583951611366612971336520849631",
|
||||
"15686434090519025535750972146665146115600132377233307706954662444115261939363",
|
||||
"07978521044324521560597166077142499104630513155826239482108808618557034953266",
|
||||
"16186118178373488391355704339907628420623148341096142998906468353458994363684",
|
||||
"01616094194920248549749929898850128903967843332816845679093076180633343237405",
|
||||
"12067961685825689214910905495339998018807791993775742376625563551520432086402",
|
||||
"16767265153622889582195925643547714403142560016144897632022578837961291923974",
|
||||
"13367520571996359147909127534086997240880862282175334655451694708276490166744",
|
||||
"12156833442707971504005454687813656406430681366873986160585845607076770190553",
|
||||
"06817123282892899799924074757891673569493005903737254117749908558580413251083",
|
||||
"11924134165483538600926542059306903275937269601056341080874171163482134362871",
|
||||
"16819859849486914771075103002949963250180871968861875173105453574215316415974",
|
||||
"03161143639269186112857240543778773953847165344056775149046085908262449132057",
|
||||
"01631545362633925293488685148251774574817863241018946006468038576386573965597",
|
||||
"01971328662008380114733067397701758302961082702641272074460886259250850887397",
|
||||
"17695224358631154506978339513738652852648999874890890040034188091482229051269",
|
||||
"19520521221908952578325184397091529060305659518835790012032359979413117963489",
|
||||
"13727476748410294673083242759556666609110006331156301177194324266617028346471",
|
||||
"14698827014679446278250011669216363784537291491609420066054426392958630097415",
|
||||
"10535097647307983569862114062272489681840622918699371842851022899585266172656",
|
||||
"11910779613629071438346203159111801031581811581576134374236444390950212635205",
|
||||
"11680156118951907362527459456638646286695732659238408806089172691700870170551",
|
||||
"07991451678780803665957836113028903779849744500818389985500383822437655878933",
|
||||
"09728454236166458320093247365334095846984379976435597324759765167979530078428",
|
||||
"03784046300336611178891289500943863446674516060395139310827961127099192748117",
|
||||
]
|
||||
|
||||
for n in 0..80:
|
||||
let input = collect(newSeq, (for i in 1..n: byte(i)))
|
||||
let root = Merkle.digest(input, which = HorizenLabsNew)
|
||||
check root.toDecimal == expected[n]
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
# a couple of tests with small input
|
||||
for _ in 0..<1000:
|
||||
let len = rand(1024)
|
||||
let input = newSeqwith(len, byte.rand())
|
||||
checkInput(input)
|
||||
|
||||
# one test with larger input
|
||||
let len = rand(1024 * 1024)
|
||||
let input = newSeqwith(len, byte.rand())
|
||||
checkInput(input)
|
||||
|
||||
@ -10,13 +10,29 @@ import poseidon2/permutation
|
||||
|
||||
suite "permutation":
|
||||
|
||||
test "permutation in place":
|
||||
test "permutation in place (default version)":
|
||||
var x: F = toF(0)
|
||||
var y: F = toF(1)
|
||||
var z: F = toF(2)
|
||||
|
||||
permInPlace(x, y, z)
|
||||
|
||||
check toDecimal(x) == "21882471761025344482456282050943515707267606647948403374880378562101343146243"
|
||||
check toDecimal(y) == "09030699330013392132529464674294378792132780497765201297316864012141442630280"
|
||||
check toDecimal(z) == "09137931384593657624554037900714196568304064431583163402259937475584578975855"
|
||||
|
||||
test "permutation in place (old version)":
|
||||
var x: F = toF(0)
|
||||
var y: F = toF(1)
|
||||
var z: F = toF(2)
|
||||
permInPlace(x, y, z, HorizenLabsOld)
|
||||
check toDecimal(x) == "21882471761025344482456282050943515707267606647948403374880378562101343146243"
|
||||
check toDecimal(y) == "09030699330013392132529464674294378792132780497765201297316864012141442630280"
|
||||
check toDecimal(z) == "09137931384593657624554037900714196568304064431583163402259937475584578975855"
|
||||
|
||||
test "permutation in place (new version)":
|
||||
var x: F = toF(0)
|
||||
var y: F = toF(1)
|
||||
var z: F = toF(2)
|
||||
permInPlace(x, y, z, HorizenLabsNew)
|
||||
check toDecimal(x) == "05297208644449048816064511434384511824916970985131888684874823260532015509555"
|
||||
check toDecimal(y) == "21816030159894113985964609355246484851575571273661473159848781012394295965040"
|
||||
check toDecimal(z) == "13940986381491601233448981668101586453321811870310341844570924906201623195336"
|
||||
|
||||
@ -9,6 +9,6 @@ let digest: F = Sponge.digest(input) # a field element
|
||||
|
||||
let output: array[32, byte] = digest.toBytes
|
||||
|
||||
let left = Sponge.digest([1'u8, 2'u8, 3'u8])
|
||||
let left = Sponge.digest([1'u8, 2'u8, 3'u8])
|
||||
let right = Sponge.digest([4'u8, 5'u8, 6'u8])
|
||||
let combination = compress(left, right)
|
||||
let combination = compression(left, right)
|
||||
|
||||
@ -10,7 +10,7 @@ import poseidon2
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
const expectedSpongeResultsRate1 : array[8, string] =
|
||||
const expectedSpongeResultsRate1_oldConstants : array[9, string] =
|
||||
[ "11474111961551684932675539562074905375756669035986300321099733737886849683321"
|
||||
, "12075737409606154890751050839468327529267137715708285489737384891841319770833"
|
||||
, "01607478768131843313297310704782442615640380643931196052095347138434114571392"
|
||||
@ -19,9 +19,10 @@ const expectedSpongeResultsRate1 : array[8, string] =
|
||||
, "16646216251577650555646508049064625507758601195307236539843683725095763921505"
|
||||
, "11914716034377431890952169039751213443286692885071871704776127977841051829452"
|
||||
, "20798492850731331785912281726856492405884190236464781409482377236764537088662"
|
||||
, "06540627055407175851799217748185038564362037151837725911893079868194265409140"
|
||||
]
|
||||
|
||||
const expectedSpongeResultsRate2 : array[8, string] =
|
||||
const expectedSpongeResultsRate2_oldConstants : array[9, string] =
|
||||
[ "15335097698975718583905618186682475632756177170667436996250626760551196078076"
|
||||
, "05101758095924000127790537496504070769319625501671400349336709520206095219618"
|
||||
, "07306734450287348725566606192910189982345130476287345231433021147457815478255"
|
||||
@ -30,30 +31,85 @@ const expectedSpongeResultsRate2 : array[8, string] =
|
||||
, "04630821736691665506072583795473163860465039714428126246168623896083265248907"
|
||||
, "02020506076765964149531002674962673761843846094901604358961533722934321735239"
|
||||
, "11732533243633999579592740965735640217427639382365959787508754341969556105663"
|
||||
, "10595863140043317128604467126415689825650822395227997061806436243673828413111"
|
||||
]
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
suite "sponge":
|
||||
const expectedSpongeResultsRate1_newConstants : array[9, string] =
|
||||
[ "16266571538186917378274620794715615871819075505012642331831740166402113589444"
|
||||
, "01491928274163660244001918443018649243011497181896253665026327205550900025133"
|
||||
, "02412839127042446155240125134683455485652987653749713765008668784861163705152"
|
||||
, "13542922135264044648018285414420351411417846004082653245814369808833670302952"
|
||||
, "07076213890494569790170137210157320757601820601990570639519400872306624103450"
|
||||
, "14352524674388170989103113995374854592404343519856765997715183437545150946627"
|
||||
, "09569766023135969668725409572485043887042089063331497639246627061832860243694"
|
||||
, "07085371443491523419928170734321525595867567352592425091735470317423982305101"
|
||||
, "08760489972278360817463581930800343241641769319369768058091167957311211828855"
|
||||
]
|
||||
|
||||
const expectedSpongeResultsRate2_newConstants : array[9, string] =
|
||||
[ "09046401272760514841637528652889990409326782162327754989145589039437684339646"
|
||||
, "15241474315923430535056537847443353616620358302434799334548590414322880571588"
|
||||
, "21072215602003532013851767027226990768339943605363951211799157616055680003388"
|
||||
, "01170974936269513349886180046259796461929600320496736075445632961164642599434"
|
||||
, "01558215443543426787363296590025566689264472540550531923588672734783818772596"
|
||||
, "09807480697990556434580623882838196982062075470026453062706673159266728569584"
|
||||
, "02822720935161078698932842003982797241316889894694232376768120398512081493835"
|
||||
, "02351886751449393975320062064400658126198560006081569452290595784036978037282"
|
||||
, "18286883995665455411199910174038826133816802309376680038108548762581403366251"
|
||||
]
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
suite "sponge (old round constants)":
|
||||
|
||||
test "sponge with rate=1":
|
||||
for n in 0..7:
|
||||
for n in 0..8:
|
||||
var xs: seq[F]
|
||||
for i in 1..n:
|
||||
xs.add( toF(i) )
|
||||
let h = Sponge.digest(xs, rate = 1)
|
||||
check toDecimal(h) == expectedSpongeResultsRate1[n]
|
||||
let h = Sponge.digest(xs, rate = 1, which = HorizenLabsOld)
|
||||
check toDecimal(h) == expectedSpongeResultsRate1_oldConstants[n]
|
||||
|
||||
test "sponge with rate=2":
|
||||
for n in 0..7:
|
||||
for n in 0..8:
|
||||
var xs: seq[F]
|
||||
for i in 1..n:
|
||||
xs.add( toF(i) )
|
||||
let h = Sponge.digest(xs, rate = 2)
|
||||
check toDecimal(h) == expectedSpongeResultsRate2[n]
|
||||
let h = Sponge.digest(xs, rate = 2, which = HorizenLabsOld)
|
||||
check toDecimal(h) == expectedSpongeResultsRate2_oldConstants[n]
|
||||
|
||||
test "sponge with byte array as input":
|
||||
let bytes = toSeq 1'u8..80'u8
|
||||
let elements = toSeq bytes.elements(F)
|
||||
let expected = Sponge.digest(elements, rate = 2)
|
||||
let expected = Sponge.digest(elements, rate = 2, which = HorizenLabsOld)
|
||||
check bool(Sponge.digest(bytes, rate = 2) == expected)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
suite "sponge (new round constants)":
|
||||
|
||||
test "sponge with rate=1":
|
||||
for n in 0..8:
|
||||
var xs: seq[F]
|
||||
for i in 1..n:
|
||||
xs.add( toF(i) )
|
||||
let h = Sponge.digest(xs, rate = 1, which = HorizenLabsNew)
|
||||
check toDecimal(h) == expectedSpongeResultsRate1_newConstants[n]
|
||||
|
||||
test "sponge with rate=2":
|
||||
for n in 0..8:
|
||||
var xs: seq[F]
|
||||
for i in 1..n:
|
||||
xs.add( toF(i) )
|
||||
let h = Sponge.digest(xs, rate = 2, which = HorizenLabsNew)
|
||||
check toDecimal(h) == expectedSpongeResultsRate2_newConstants[n]
|
||||
|
||||
test "sponge with byte array as input":
|
||||
let bytes = toSeq 1'u8..80'u8
|
||||
let elements = toSeq bytes.elements(F)
|
||||
let expected = Sponge.digest(elements, rate = 2, which = HorizenLabsNew)
|
||||
check bool(Sponge.digest(bytes, rate = 2, which = HorizenLabsNew) == expected)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
@ -5,8 +5,11 @@ import constantine/math/arithmetic
|
||||
import poseidon2/sponge
|
||||
import poseidon2/merkle
|
||||
import poseidon2/spongemerkle
|
||||
import poseidon2/types
|
||||
|
||||
suite "sponge - merkle root":
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
suite "sponge - merkle root (old round constants)":
|
||||
|
||||
const KB = 1024
|
||||
|
||||
@ -31,3 +34,33 @@ suite "sponge - merkle root":
|
||||
merkle.update(Sponge.digest(partialChunk, rate = 2))
|
||||
let expected = merkle.finish()
|
||||
check bool(SpongeMerkle.digest(bytes, chunkSize = 2*KB) == expected)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
suite "sponge - merkle root (new round constants)":
|
||||
|
||||
const KB = 1024
|
||||
|
||||
test "hashes chunks of data with sponge, and combines them in merkle root":
|
||||
let bytes = newSeqWith(64*KB, rand(byte))
|
||||
var merkle = Merkle.init(which = HorizenLabsNew)
|
||||
for i in 0..<32:
|
||||
let chunk = bytes[(i*2*KB)..<((i+1)*2*KB)]
|
||||
let digest = Sponge.digest(chunk, rate = 2, which = HorizenLabsNew)
|
||||
merkle.update(digest)
|
||||
let expected = merkle.finish()
|
||||
check bool(SpongeMerkle.digest(bytes, chunkSize = 2*KB, which = HorizenLabsNew) == expected)
|
||||
|
||||
test "handles partial chunk at the end":
|
||||
let bytes = newSeqWith(63*KB, rand(byte))
|
||||
var merkle = Merkle.init(which = HorizenLabsNew)
|
||||
for i in 0..<31:
|
||||
let chunk = bytes[(i*2*KB)..<((i+1)*2*KB)]
|
||||
let digest = Sponge.digest(chunk, rate = 2, which = HorizenLabsNew)
|
||||
merkle.update(digest)
|
||||
let partialChunk = bytes[(62*KB)..<(63*KB)]
|
||||
merkle.update(Sponge.digest(partialChunk, rate = 2, which = HorizenLabsNew))
|
||||
let expected = merkle.finish()
|
||||
check bool(SpongeMerkle.digest(bytes, chunkSize = 2*KB, which = HorizenLabsNew) == expected)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user