mirror of
https://github.com/logos-storage/nim-goldilocks-hash.git
synced 2026-01-09 09:03:09 +00:00
commit
dfaf56f28d
@ -10,5 +10,3 @@ func compress*(a, b: Digest, key: uint64 = 0) : Digest =
|
||||
var output: Digest
|
||||
c_compress(x,y,key,output)
|
||||
return output
|
||||
|
||||
|
||||
|
||||
@ -8,8 +8,6 @@
|
||||
# as many zeros as required so that the final length is divisible by the rate)
|
||||
# both when hashing bytes and when hashing field elements
|
||||
|
||||
#import std/assertions # on 1.6.18 with an M2 i got "cannot open file: std/assertions" ....
|
||||
|
||||
import ../types
|
||||
import ../goldilocks
|
||||
import ./permutation
|
||||
@ -17,50 +15,47 @@ import ./permutation
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
# "import std/assertions" does not work
|
||||
# i got the error: "cannot open file: std/assertions"
|
||||
proc fakeAssert( cond: bool, msg: string ) =
|
||||
if not cond:
|
||||
raise newException(AssertionDefect, msg)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
type
|
||||
Sponge*[T: static typedesc, rate: static int] = object
|
||||
Sponge*[T: type, rate: static int] = object
|
||||
state: F12
|
||||
lenModRate: uint
|
||||
|
||||
func numberOfBits(T: static typedesc): int =
|
||||
if T is F: return 63
|
||||
if T is byte: return 8
|
||||
if T is bool: return 1
|
||||
fakeAssert( false , "unsupported input type for sponge construction" )
|
||||
func numberOfBits(T: type): int {.compileTime.} =
|
||||
when T is F:
|
||||
63
|
||||
elif T is byte:
|
||||
8
|
||||
elif T is bool:
|
||||
1
|
||||
else:
|
||||
{.error: "unsupported input type for sponge construction".}
|
||||
|
||||
func initialize[T: static typedesc, rate: static int](sponge: var Sponge[T,rate]) =
|
||||
fakeAssert( rate >= 1 and rate <= 8 , "with t=12, rate must be at most 8 (and positive)" )
|
||||
let nbits = numberOfBits(T)
|
||||
let IV = toF( 0x10000*uint64(nbits) + 0x100*12 + uint64(rate) ) # domain separation IV := (65536*nbits + 256*t + r)
|
||||
sponge.state[8] = IV;
|
||||
func initialize(sponge: var Sponge) =
|
||||
when not Sponge.rate >= 1 and Sponge.rate <= 8:
|
||||
{.error: "with t=12, rate must be at most 8 (and positive)".}
|
||||
const nbits = numberOfBits(Sponge.T)
|
||||
const IV = toF( 0x10000*uint64(nbits) + 0x100*12 + uint64(Sponge.rate) ) # domain separation IV := (65536*nbits + 256*t + r)
|
||||
sponge.state[8] = IV;
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
func extractDigestF4[T: static typedesc, rate: static int](sponge: var Sponge[T,rate]) : F4 =
|
||||
func extractDigestF4(sponge: var Sponge) : F4 =
|
||||
var digest : F4
|
||||
for i in 0..<4: digest[i] = sponge.state[i]
|
||||
return digest
|
||||
|
||||
func extractDigest[T: static typedesc, rate: static int](sponge: var Sponge[T,rate]) : Digest =
|
||||
func extractDigest(sponge: var Sponge) : Digest =
|
||||
return toDigest(sponge.extractDigestF4())
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
func update*[rate: static int](sponge: var Sponge[typedesc[F],rate], x: F) =
|
||||
func update*[rate](sponge: var Sponge[F, rate], x: F) =
|
||||
sponge.state[sponge.lenModRate] += x
|
||||
sponge.lenModRate = (sponge.lenModRate + 1) mod rate
|
||||
if (sponge.lenModRate == 0):
|
||||
permInPlaceF12( sponge.state );
|
||||
|
||||
func finish*[T: static typedesc, rate:static int](sponge: var Sponge[T,rate]): Digest =
|
||||
func finish*(sponge: var Sponge): Digest =
|
||||
# padding
|
||||
sponge.update(one)
|
||||
while( sponge.lenModRate != 0):
|
||||
@ -69,7 +64,7 @@ func finish*[T: static typedesc, rate:static int](sponge: var Sponge[T,rate]): D
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
# # _: type Sponge,
|
||||
# # _: type Sponge,
|
||||
#func init*( _: type Sponge, T: static typedesc, rate: static int = 8): Sponge[T,rate] =
|
||||
# when (rate < 1 or rate > 8):
|
||||
# {.error: "only rates between 1 and 8 are supported".}
|
||||
@ -77,18 +72,18 @@ func finish*[T: static typedesc, rate:static int](sponge: var Sponge[T,rate]): D
|
||||
# initialize[T,rate](sponge)
|
||||
# return sponge
|
||||
|
||||
func newSponge*[T: static typedesc, rate: static int = 8](): Sponge[T,rate] =
|
||||
func init*(_: type Sponge, T: type, rate: static int): Sponge[T,rate] =
|
||||
when (rate < 1 or rate > 8):
|
||||
{.error: "only rates between 1 and 8 are supported".}
|
||||
var sponge: Sponge[T,rate]
|
||||
initialize[T,rate](sponge)
|
||||
var sponge: Sponge[T, rate]
|
||||
initialize(sponge)
|
||||
return sponge
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
# digest a sequence of field elements
|
||||
func digestNim*(rate: static int = 8, elements: openArray[F]): Digest =
|
||||
var sponge : Sponge[typedesc[F],rate] = newSponge[typedesc[F],rate]()
|
||||
var sponge : Sponge[F,rate] = Sponge.init(F, rate)
|
||||
for element in elements:
|
||||
sponge.update(element)
|
||||
return sponge.finish()
|
||||
@ -102,18 +97,18 @@ func digestNim*(rate: static int = 8, elements: openArray[F]): Digest =
|
||||
|
||||
#---------------------------------------
|
||||
|
||||
proc digestFeltsRawC(rate: int, len: int, input: ptr UncheckedArray[F ], hash: var F4) {. header: "../cbits/goldilocks.h", importc: "goldilocks_monolith_felts_digest", cdecl .}
|
||||
proc digestBytesRawC(rate: int, len: int, input: ptr UncheckedArray[byte], hash: var F4) {. header: "../cbits/goldilocks.h", importc: "goldilocks_monolith_bytes_digest", cdecl .}
|
||||
proc digestFeltsRawC(rate: int, len: int, input: ptr F , hash: var F4) {. header: "../cbits/goldilocks.h", importc: "goldilocks_monolith_felts_digest", cdecl .}
|
||||
proc digestBytesRawC(rate: int, len: int, input: ptr byte, hash: var F4) {. header: "../cbits/goldilocks.h", importc: "goldilocks_monolith_bytes_digest", cdecl .}
|
||||
|
||||
func digestFeltsC*(rate: static int = 8, felts: openArray[F]): Digest =
|
||||
var digest : F4
|
||||
let input = cast[ptr UncheckedArray[F]]( felts.unsafeAddr )
|
||||
let input = if felts.len > 0: unsafeAddr felts[0] else: nil
|
||||
digestFeltsRawC(rate, felts.len, input, digest)
|
||||
return toDigest(digest)
|
||||
|
||||
func digestBytesC*(rate: static int = 8, bytes: openArray[byte]): Digest =
|
||||
var digest : F4
|
||||
let input = cast[ptr UncheckedArray[byte]]( bytes.unsafeAddr )
|
||||
let input = if bytes.len > 0: unsafeAddr bytes[0] else: nil
|
||||
digestBytesRawC(rate, bytes.len, input, digest)
|
||||
return toDigest(digest)
|
||||
|
||||
|
||||
@ -7,8 +7,8 @@ type F* = distinct uint64
|
||||
|
||||
func fromF* (x: F): uint64 = return uint64(x)
|
||||
func toF* (x: uint64): F = return F(x)
|
||||
func toF* (x: int ): F =
|
||||
assert(x >= 0)
|
||||
func toF* (x: int ): F =
|
||||
assert(x >= 0)
|
||||
return F(uint64(x))
|
||||
|
||||
func `==`* (x, y: F): bool = return (uint64(x) == uint64(y))
|
||||
@ -31,8 +31,8 @@ type F12* = array[12, F]
|
||||
type Digest* = distinct F4
|
||||
type State* = distinct F12
|
||||
|
||||
func fromDigest* (x : Digest): F4 = return F4(x)
|
||||
func fromState * (x : State): F12 = return F12(x)
|
||||
func fromDigest* (x : Digest): F4 = return F4(x)
|
||||
func fromState * (x : State): F12 = return F12(x)
|
||||
|
||||
func toDigest* (x : F4 ): Digest = Digest(x)
|
||||
func toState* (x : F12): State = State(x)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user