mirror of
https://github.com/logos-storage/nim-poseidon2.git
synced 2026-01-05 15:13:12 +00:00
move unmarshal into its own module called 'io'
Includes separate tests for unmarshalling that were previously tested as part of the merkleRoot calculation. Includes tests for unmarshalling little endian and big endian byte arrays.
This commit is contained in:
parent
e19a08e6c3
commit
43c2aab913
@ -1,13 +1,10 @@
|
||||
|
||||
# import std/sugar
|
||||
|
||||
import
|
||||
constantine/math/arithmetic,
|
||||
constantine/math/io/io_bigints,
|
||||
constantine/math/config/curves
|
||||
|
||||
import poseidon2/types
|
||||
import poseidon2/roundconst
|
||||
import poseidon2/io
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
@ -100,20 +97,5 @@ proc merkleRoot*(xs: openArray[F]) : F =
|
||||
|
||||
return merkleRoot(ys)
|
||||
|
||||
proc unmarshal(
|
||||
_: type F,
|
||||
bytes: openArray[byte],
|
||||
endian: static Endianness): seq[F] =
|
||||
const chunkLen = 31
|
||||
var elements: seq[F]
|
||||
var i = 0
|
||||
while i < bytes.len:
|
||||
let chunk = bytes[i..<min(i + chunkLen, bytes.len)]
|
||||
let bigint = B.unmarshal(chunk, endian)
|
||||
let element = F.fromBig(bigint)
|
||||
elements.add(element)
|
||||
i += chunkLen
|
||||
return elements
|
||||
|
||||
proc merkleRoot*(bytes: openArray[byte]): F =
|
||||
merkleRoot(F.unmarshal(bytes, littleEndian))
|
||||
|
||||
18
poseidon2/io.nim
Normal file
18
poseidon2/io.nim
Normal file
@ -0,0 +1,18 @@
|
||||
import ./types
|
||||
import constantine/math/arithmetic
|
||||
import constantine/math/io/io_bigints
|
||||
|
||||
proc unmarshal*(
|
||||
_: type F,
|
||||
bytes: openArray[byte],
|
||||
endian: static Endianness): seq[F] =
|
||||
const chunkLen = 31
|
||||
var elements: seq[F]
|
||||
var i = 0
|
||||
while i < bytes.len:
|
||||
let chunk = bytes[i..<min(i + chunkLen, bytes.len)]
|
||||
let bigint = B.unmarshal(chunk, endian)
|
||||
let element = F.fromBig(bigint)
|
||||
elements.add(element)
|
||||
i += chunkLen
|
||||
return elements
|
||||
36
tests/poseidon2/testIo.nim
Normal file
36
tests/poseidon2/testIo.nim
Normal file
@ -0,0 +1,36 @@
|
||||
import std/unittest
|
||||
import std/sequtils
|
||||
import constantine/math/io/io_bigints
|
||||
import constantine/math/arithmetic
|
||||
import poseidon2/types
|
||||
import poseidon2/io
|
||||
|
||||
suite "unmarshalling":
|
||||
|
||||
const F123456 = F.fromBig(B.fromHex("0x123456", bigEndian))
|
||||
|
||||
test "converts big endian bytes into field elements":
|
||||
let bytes = [0x12'u8, 0x34'u8, 0x56'u8]
|
||||
var padded: array[31, byte]
|
||||
padded[^3..^1] = bytes
|
||||
check bool(F.unmarshal(bytes, bigEndian)[0] == F123456)
|
||||
check bool(F.unmarshal(padded, bigEndian)[0] == F123456)
|
||||
|
||||
test "converts little endian bytes into field elements":
|
||||
let bytes = [0x56'u8, 0x34'u8, 0x12'u8]
|
||||
var padded: array[31, byte]
|
||||
padded[0..<3] = bytes
|
||||
check bool(F.unmarshal(bytes, littleEndian)[0] == F123456)
|
||||
check bool(F.unmarshal(padded, littleEndian)[0] == F123456)
|
||||
|
||||
test "converts every 31 bytes into a field element":
|
||||
let bytes = toSeq 1'u8..80'u8
|
||||
let element1 = F.fromBig(B.unmarshal(toSeq 1'u8..31'u8, bigEndian))
|
||||
let element2 = F.fromBig(B.unmarshal(toSeq 32'u8..62'u8, bigEndian))
|
||||
let element3 = F.fromBig(B.unmarshal(toSeq 63'u8..80'u8, bigEndian))
|
||||
let elements = F.unmarshal(bytes, bigEndian)
|
||||
check elements.len == 3
|
||||
check bool(elements[0] == element1)
|
||||
check bool(elements[1] == element2)
|
||||
check bool(elements[2] == element3)
|
||||
|
||||
39
tests/poseidon2/testPoseidon2.nim
Normal file
39
tests/poseidon2/testPoseidon2.nim
Normal file
@ -0,0 +1,39 @@
|
||||
import std/unittest
|
||||
import std/math
|
||||
import std/sequtils
|
||||
|
||||
import constantine/math/arithmetic
|
||||
import constantine/math/io/io_fields
|
||||
import constantine/math/io/io_bigints
|
||||
import constantine/math/config/curves
|
||||
|
||||
import poseidon2/types
|
||||
import poseidon2
|
||||
|
||||
suite "poseidon2":
|
||||
|
||||
test "permutation in place":
|
||||
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 "merkle root of field elements":
|
||||
let m = 17
|
||||
let n = 2^m
|
||||
var xs: seq[F]
|
||||
for i in 1..n:
|
||||
xs.add( toF(i) )
|
||||
|
||||
let root = merkleRoot(xs)
|
||||
check root.toHex == "0x1eabbb64b76d5aecd393601c4a01878450e23f45fe8b2748bb63a615351b11d1"
|
||||
|
||||
test "merkle root of bytes":
|
||||
let bytes = toSeq 1'u8..80'u8
|
||||
let root = merkleRoot(bytes)
|
||||
check root.toHex == "0x2d2d6f27d20a9e5597e20a888a4deac0e0600f92f0b9691ace0fdfab2fc1f500"
|
||||
@ -1,70 +1,4 @@
|
||||
import std/unittest
|
||||
import std/math
|
||||
import std/strutils
|
||||
import std/sequtils
|
||||
import ./poseidon2/testPoseidon2
|
||||
import ./poseidon2/testIo
|
||||
|
||||
import constantine/math/arithmetic
|
||||
import constantine/math/io/io_fields
|
||||
import constantine/math/io/io_bigints
|
||||
import constantine/math/config/curves
|
||||
|
||||
import poseidon2/types
|
||||
import poseidon2
|
||||
|
||||
suite "poseidon2":
|
||||
|
||||
test "permutation in place":
|
||||
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 "merkle root of field elements":
|
||||
let m = 17
|
||||
let n = 2^m
|
||||
var xs: seq[F]
|
||||
for i in 1..n:
|
||||
xs.add( toF(i) )
|
||||
|
||||
let root = merkleRoot(xs)
|
||||
check root.toHex == "0x1eabbb64b76d5aecd393601c4a01878450e23f45fe8b2748bb63a615351b11d1"
|
||||
|
||||
test "merkle root of bytes":
|
||||
let bytes = toSeq 1'u8..80'u8
|
||||
let root = merkleRoot(bytes)
|
||||
check root.toHex == "0x2d2d6f27d20a9e5597e20a888a4deac0e0600f92f0b9691ace0fdfab2fc1f500"
|
||||
|
||||
test "merkle root converts every 31 bytes to a field element":
|
||||
let hex = [ # 31 bytes per field element
|
||||
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E",
|
||||
"1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D",
|
||||
"3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C"
|
||||
]
|
||||
let padded = [ # padded to 32 bytes
|
||||
hex[0] & "00",
|
||||
hex[1] & "00",
|
||||
hex[2] & "00"
|
||||
]
|
||||
let bytes = cast[seq[byte]](parseHexStr(hex.join()))
|
||||
let elements = arrayFromHex(padded, littleEndian)
|
||||
check merkleRoot(bytes).toHex == merkleRoot(elements).toHex
|
||||
|
||||
test "merkle root of bytes whose length is not a not multiple of 31":
|
||||
let hex = [ # 31 bytes per field element
|
||||
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E",
|
||||
"1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D",
|
||||
"3E3F404142434445464748494A4B4C4D4E4F505152535455565758"
|
||||
]
|
||||
let padded = [ # padded to 32 bytes
|
||||
hex[0] & "00",
|
||||
hex[1] & "00",
|
||||
hex[2] & "0000000000"
|
||||
]
|
||||
let bytes = cast[seq[byte]](parseHexStr(hex.join()))
|
||||
let elements = arrayFromHex(padded, littleEndian)
|
||||
check merkleRoot(bytes).toHex == merkleRoot(elements).toHex
|
||||
{.warning[UnusedImport]: off.}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user