module ZkFold.Symbolic.Algorithms.Hash.MiMC.Constants (mimcConstants) where

import           Crypto.Hash.SHA256              (hash)
import           Data.Maybe                      (fromJust)
import           Prelude

import           ZkFold.Base.Algebra.Basic.Class (FromConstant (..))
import           ZkFold.Base.Data.ByteString

mimcSeed :: LittleEndian
mimcSeed :: LittleEndian
mimcSeed = LittleEndian
42

-- | The round constants ci are random elements of F_2n except for the first and
--   last round constants which are equal to 0.
--
mimcConstants :: forall a . FromConstant Integer a => [a]
mimcConstants :: forall a. FromConstant Integer a => [a]
mimcConstants =
  let
    getI :: ByteString -> Integer
getI = LittleEndian -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (LittleEndian -> Integer)
-> (ByteString -> LittleEndian) -> ByteString -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe LittleEndian -> LittleEndian
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe LittleEndian -> LittleEndian)
-> (ByteString -> Maybe LittleEndian) -> ByteString -> LittleEndian
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Binary a => ByteString -> Maybe a
fromByteString @LittleEndian
    cs :: [Integer]
cs = Int -> [Integer] -> [Integer]
forall a. Int -> [a] -> [a]
take Int
218 ([Integer] -> [Integer]) -> [Integer] -> [Integer]
forall a b. (a -> b) -> a -> b
$ (ByteString -> Integer) -> [ByteString] -> [Integer]
forall a b. (a -> b) -> [a] -> [b]
map ByteString -> Integer
getI ([ByteString] -> [Integer]) -> [ByteString] -> [Integer]
forall a b. (a -> b) -> a -> b
$ (ByteString -> ByteString) -> ByteString -> [ByteString]
forall a. (a -> a) -> a -> [a]
iterate ByteString -> ByteString
hash (ByteString -> [ByteString]) -> ByteString -> [ByteString]
forall a b. (a -> b) -> a -> b
$ LittleEndian -> ByteString
forall a. Binary a => a -> ByteString
toByteString LittleEndian
mimcSeed
  in (Integer -> a) -> [Integer] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map (forall a b. FromConstant a b => a -> b
fromConstant @Integer @a) (Integer
0 Integer -> [Integer] -> [Integer]
forall a. a -> [a] -> [a]
: [Integer]
cs [Integer] -> [Integer] -> [Integer]
forall a. [a] -> [a] -> [a]
++ [Integer
0])