From 7d7420a54217e1072219ebb2e71613d9cc550503 Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Thu, 10 Oct 2024 10:50:11 +0200 Subject: [PATCH 1/6] replace fakeAssert by raiseAssert and doAssert --- goldilocks_hash/monolith/sponge.nim | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/goldilocks_hash/monolith/sponge.nim b/goldilocks_hash/monolith/sponge.nim index 34bb925..0df67d9 100644 --- a/goldilocks_hash/monolith/sponge.nim +++ b/goldilocks_hash/monolith/sponge.nim @@ -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,27 +15,19 @@ 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 state: F12 lenModRate: uint -func numberOfBits(T: static typedesc): int = +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" ) + raiseAssert("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)" ) + doAssert(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; From 55346e51643746fa05a3ddb9ad7759d588546faa Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Thu, 10 Oct 2024 10:51:17 +0200 Subject: [PATCH 2/6] whitespace formatting --- goldilocks_hash/monolith/compress.nim | 2 -- goldilocks_hash/monolith/sponge.nim | 4 ++-- goldilocks_hash/types.nim | 8 ++++---- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/goldilocks_hash/monolith/compress.nim b/goldilocks_hash/monolith/compress.nim index 36858d3..d2e8177 100644 --- a/goldilocks_hash/monolith/compress.nim +++ b/goldilocks_hash/monolith/compress.nim @@ -10,5 +10,3 @@ func compress*(a, b: Digest, key: uint64 = 0) : Digest = var output: Digest c_compress(x,y,key,output) return output - - diff --git a/goldilocks_hash/monolith/sponge.nim b/goldilocks_hash/monolith/sponge.nim index 0df67d9..fbb454a 100644 --- a/goldilocks_hash/monolith/sponge.nim +++ b/goldilocks_hash/monolith/sponge.nim @@ -30,7 +30,7 @@ func initialize[T: static typedesc, rate: static int](sponge: var Sponge[T,rate] doAssert(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; + sponge.state[8] = IV; #--------------------------------------- @@ -59,7 +59,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".} diff --git a/goldilocks_hash/types.nim b/goldilocks_hash/types.nim index aca34a5..a986028 100644 --- a/goldilocks_hash/types.nim +++ b/goldilocks_hash/types.nim @@ -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) From 30083a16be3d2aab2f43692e398c3647fe7baaff Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Thu, 10 Oct 2024 10:57:58 +0200 Subject: [PATCH 3/6] replace runtime checks with compile time checks --- goldilocks_hash/monolith/sponge.nim | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/goldilocks_hash/monolith/sponge.nim b/goldilocks_hash/monolith/sponge.nim index fbb454a..5c00b50 100644 --- a/goldilocks_hash/monolith/sponge.nim +++ b/goldilocks_hash/monolith/sponge.nim @@ -20,16 +20,21 @@ type 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 - raiseAssert("unsupported input type for sponge construction" ) +func numberOfBits(T: static typedesc): 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]) = - doAssert(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) + when not rate >= 1 and rate <= 8: + {.error: "with t=12, rate must be at most 8 (and positive)".} + const nbits = numberOfBits(T) + const IV = toF( 0x10000*uint64(nbits) + 0x100*12 + uint64(rate) ) # domain separation IV := (65536*nbits + 256*t + r) sponge.state[8] = IV; #--------------------------------------- From 268eabbc20e15723cfdcd8f0c53f67d1e0e76e38 Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Thu, 10 Oct 2024 10:59:13 +0200 Subject: [PATCH 4/6] replace `new` by `init`; Sponge is not a reference type --- goldilocks_hash/monolith/sponge.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/goldilocks_hash/monolith/sponge.nim b/goldilocks_hash/monolith/sponge.nim index 5c00b50..3956fd4 100644 --- a/goldilocks_hash/monolith/sponge.nim +++ b/goldilocks_hash/monolith/sponge.nim @@ -72,7 +72,7 @@ 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 initSponge*[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".} var sponge: Sponge[T,rate] @@ -83,7 +83,7 @@ func newSponge*[T: static typedesc, rate: static int = 8](): Sponge[T,rate] = # 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[typedesc[F],rate] = initSponge[typedesc[F],rate]() for element in elements: sponge.update(element) return sponge.finish() From 8b2cb52bf041d82bad3ac30ff40448cb2baa1ee0 Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Thu, 10 Oct 2024 11:07:30 +0200 Subject: [PATCH 5/6] remove cast to ptr UncheckedArray --- goldilocks_hash/monolith/sponge.nim | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/goldilocks_hash/monolith/sponge.nim b/goldilocks_hash/monolith/sponge.nim index 3956fd4..c96b40a 100644 --- a/goldilocks_hash/monolith/sponge.nim +++ b/goldilocks_hash/monolith/sponge.nim @@ -97,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) From ec42ffb42ffd8d802d77353d8bd9419a6d302da6 Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Thu, 10 Oct 2024 11:51:11 +0200 Subject: [PATCH 6/6] simplify type parameters --- goldilocks_hash/monolith/sponge.nim | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/goldilocks_hash/monolith/sponge.nim b/goldilocks_hash/monolith/sponge.nim index c96b40a..739fe75 100644 --- a/goldilocks_hash/monolith/sponge.nim +++ b/goldilocks_hash/monolith/sponge.nim @@ -16,11 +16,11 @@ import ./permutation #------------------------------------------------------------------------------- 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 {.compileTime.} = +func numberOfBits(T: type): int {.compileTime.} = when T is F: 63 elif T is byte: @@ -30,32 +30,32 @@ func numberOfBits(T: static typedesc): int {.compileTime.} = else: {.error: "unsupported input type for sponge construction".} -func initialize[T: static typedesc, rate: static int](sponge: var Sponge[T,rate]) = - when not rate >= 1 and rate <= 8: +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(T) - const IV = toF( 0x10000*uint64(nbits) + 0x100*12 + uint64(rate) ) # domain separation IV := (65536*nbits + 256*t + r) + 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): @@ -72,18 +72,18 @@ func finish*[T: static typedesc, rate:static int](sponge: var Sponge[T,rate]): D # initialize[T,rate](sponge) # return sponge -func initSponge*[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] = initSponge[typedesc[F],rate]() + var sponge : Sponge[F,rate] = Sponge.init(F, rate) for element in elements: sponge.update(element) return sponge.finish()