diff --git a/cbits/goldilocks.c b/cbits/goldilocks.c index 8fcdeb5..71dc257 100644 --- a/cbits/goldilocks.c +++ b/cbits/goldilocks.c @@ -396,7 +396,7 @@ void goldilocks_poseidon2_permutation(uint64_t *state) { // compression function: input is two 4-element vector of field elements, // and the output is a vector of 4 field elements -void goldilocks_poseidon2_keyed_compress(uint64_t key, const uint64_t *x, const uint64_t *y, uint64_t *out) { +void goldilocks_poseidon2_keyed_compress(const uint64_t *x, const uint64_t *y, uint64_t key, uint64_t *out) { uint64_t state[12]; for(int i=0; i<4; i++) { state[i ] = x[i]; @@ -411,7 +411,7 @@ void goldilocks_poseidon2_keyed_compress(uint64_t key, const uint64_t *x, const } void goldilocks_poseidon2_compress(const uint64_t *x, const uint64_t *y, uint64_t *out) { - goldilocks_poseidon2_keyed_compress(0, x, y, out); + goldilocks_poseidon2_keyed_compress(x, y, 0, out); } //------------------------------------------------------------------------------ diff --git a/cbits/goldilocks.h b/cbits/goldilocks.h index 3bfc4ca..75dc63e 100644 --- a/cbits/goldilocks.h +++ b/cbits/goldilocks.h @@ -13,20 +13,11 @@ uint64_t goldilocks_sub(uint64_t x, uint64_t y); uint64_t goldilocks_mul(uint64_t x, uint64_t y); uint64_t goldilocks_mul_small(uint64_t x, uint32_t y); -uint64_t goldilocks_div_by_2(uint64_t x); -uint64_t goldilocks_div_by_3(uint64_t x); -uint64_t goldilocks_div_by_4(uint64_t x); - -uint64_t goldilocks_add3(uint64_t x, uint64_t y, uint64_t z); - -//uint64_t goldilocks_rdc(__uint128_t x); - //------------------------------------------------------------------------------ void goldilocks_poseidon2_permutation(uint64_t *state); -void goldilocks_monolith_permutation (uint64_t *state); -void monolith_print_sbox_table(); -void monolith_print_sbox_table_c_format(); +void goldilocks_poseidon2_keyed_compress(const uint64_t *x, const uint64_t *y, uint64_t key, uint64_t *out); +void goldilocks_poseidon2_compress (const uint64_t *x, const uint64_t *y, uint64_t *out); //------------------------------------------------------------------------------ diff --git a/poseidon2/compress.nim b/poseidon2/compress.nim new file mode 100644 index 0000000..765c1ff --- /dev/null +++ b/poseidon2/compress.nim @@ -0,0 +1,14 @@ + +import ./types + +proc c_compress(a, b: var Digest, key: uint64, output: var Digest) {. header: "../cbits/goldilocks.h", importc: "goldilocks_poseidon2_keyed_compress", cdecl .} + +# keyed compression function +func compress*(a, b: Digest, key: uint64 = 0) : Digest = + var x: Digest = a + var y: Digest = b + var output: Digest + c_compress(x,y,key,output) + return output + + diff --git a/poseidon2/permutation.nim b/poseidon2/permutation.nim new file mode 100644 index 0000000..3c7915f --- /dev/null +++ b/poseidon2/permutation.nim @@ -0,0 +1,11 @@ + +import ./types + +# the Poseidon2 permutation (mutable, in-place version) +proc permInPlace*(state: var State) {. header: "../cbits/goldilocks.h", importc: "goldilocks_poseidon2_permutation", cdecl .} + +# the Poseidon2 permutation (pure version) +func perm*(state: State): State = + var tmp = state + permInPlace(tmp) + return tmp diff --git a/poseidon2/types.nim b/poseidon2/types.nim index 9d3e5e5..8df0f35 100644 --- a/poseidon2/types.nim +++ b/poseidon2/types.nim @@ -26,4 +26,10 @@ 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 toDigest* (x : F4 ): Digest = Digest(x) +func toState* (x : F12): State = State(x) + #------------------------------------------------------------------------------- diff --git a/tests/poseidon2/testCompress.nim b/tests/poseidon2/testCompress.nim new file mode 100644 index 0000000..64e75a3 --- /dev/null +++ b/tests/poseidon2/testCompress.nim @@ -0,0 +1,83 @@ + +import std/unittest +# import std/sequtils + +import poseidon2/types +import poseidon2/compress + +#------------------------------------------------------------------------------- + +const refInp1: array[4,F] = + [ toF( 1'u64 ) + , toF( 2'u64 ) + , toF( 3'u64 ) + , toF( 4'u64 ) + ] + +const refInp2: array[4,F] = + [ toF( 5'u64 ) + , toF( 6'u64 ) + , toF( 7'u64 ) + , toF( 8'u64 ) + ] + +#--------------------------------------- + +const refOutKey0: array[4,F] = + [ toF( 0xc4a4082f411ba790'u64 ) + , toF( 0x98c2ed7546c44cce'u64 ) + , toF( 0xc9404f373b78c979'u64 ) + , toF( 0x65d6b3c998920f59'u64 ) + ] + +const refOutKey1: array[4,F] = + [ toF( 0xca47449a05283778'u64 ) + , toF( 0x08d3ced2020391ac'u64 ) + , toF( 0xda461ea45670fb12'u64 ) + , toF( 0x57f2c0b6c98a05c5'u64 ) + ] + +const refOutKey2: array[4,F] = + [ toF( 0xe6fcec96a7a7f4b0'u64 ) + , toF( 0x3002a22356daa551'u64 ) + , toF( 0x899e2c1075a45f3f'u64 ) + , toF( 0xf07e38ccb3ade312'u64 ) + ] + +const refOutKey3: array[4,F] = + [ toF( 0x9930cff752b046fb'u64 ) + , toF( 0x41570687cadcea0b'u64 ) + , toF( 0x3ac093a5a92066c7'u64 ) + , toF( 0xc45c75a3911cde87'u64 ) + ] + +#------------------------------------------------------------------------------- + +suite "compression": + + test "compression of [1..4] and [5..8] with key=0": + let input1 : Digest = toDigest(refInp1) + let input2 : Digest = toDigest(refInp2) + let output : Digest = compress(input1, input2) + check ( fromDigest(output) == refOutKey0 ) + + test "compression of [1..4] and [5..8] with key=1": + let input1 : Digest = toDigest(refInp1) + let input2 : Digest = toDigest(refInp2) + let output : Digest = compress(input1, input2, key=1) + check ( fromDigest(output) == refOutKey1 ) + + test "compression of [1..4] and [5..8] with key=2": + let input1 : Digest = toDigest(refInp1) + let input2 : Digest = toDigest(refInp2) + let output : Digest = compress(input1, input2, key=2) + check ( fromDigest(output) == refOutKey2 ) + + test "compression of [1..4] and [5..8] with key=3": + let input1 : Digest = toDigest(refInp1) + let input2 : Digest = toDigest(refInp2) + let output : Digest = compress(input1, input2, key=3) + check ( fromDigest(output) == refOutKey3 ) + +#------------------------------------------------------------------------------- + diff --git a/tests/poseidon2/testPermutation.nim b/tests/poseidon2/testPermutation.nim new file mode 100644 index 0000000..d7ba1d3 --- /dev/null +++ b/tests/poseidon2/testPermutation.nim @@ -0,0 +1,50 @@ + +import std/unittest +# import std/sequtils + +import poseidon2/types +import poseidon2/permutation + +#------------------------------------------------------------------------------- + +const refInp: F12 = + [ toF( 0'u64 ) + , toF( 1'u64 ) + , toF( 2'u64 ) + , toF( 3'u64 ) + , toF( 4'u64 ) + , toF( 5'u64 ) + , toF( 6'u64 ) + , toF( 7'u64 ) + , toF( 8'u64 ) + , toF( 9'u64 ) + , toF( 10'u64 ) + , toF( 11'u64 ) + ] + +const refOut: F12 = + [ toF( 0x01eaef96bdf1c0c1'u64 ) + , toF( 0x1f0d2cc525b2540c'u64 ) + , toF( 0x6282c1dfe1e0358d'u64 ) + , toF( 0xe780d721f698e1e6'u64 ) + , toF( 0x280c0b6f753d833b'u64 ) + , toF( 0x1b942dd5023156ab'u64 ) + , toF( 0x43f0df3fcccb8398'u64 ) + , toF( 0xe8e8190585489025'u64 ) + , toF( 0x56bdbf72f77ada22'u64 ) + , toF( 0x7911c32bf9dcd705'u64 ) + , toF( 0xec467926508fbe67'u64 ) + , toF( 0x6a50450ddf85a6ed'u64 ) + ] + +#------------------------------------------------------------------------------- + +suite "permutation": + + test "permutation of [0..11]": + var input = toState(refInp) + var output = perm(input); + check fromState(output) == refOut + +#------------------------------------------------------------------------------- + diff --git a/tests/test.nim b/tests/test.nim index dd76375..ec1f63f 100644 --- a/tests/test.nim +++ b/tests/test.nim @@ -7,5 +7,7 @@ #import ./poseidon2/testReadme import ./poseidon2/testField +import ./poseidon2/testPermutation +import ./poseidon2/testCompress {.warning[UnusedImport]: off.}