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
import           ZkFold.Symbolic.Types           (I)

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 I a) => [a]
mimcConstants :: forall a. FromConstant I a => [a]
mimcConstants =
  let
    getI :: ByteString -> I
getI = LittleEndian -> I
forall a b. (Integral a, Num b) => a -> b
fromIntegral (LittleEndian -> I)
-> (ByteString -> LittleEndian) -> ByteString -> I
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 :: [I]
cs = Int -> [I] -> [I]
forall a. Int -> [a] -> [a]
take Int
218 ([I] -> [I]) -> [I] -> [I]
forall a b. (a -> b) -> a -> b
$ (ByteString -> I) -> [ByteString] -> [I]
forall a b. (a -> b) -> [a] -> [b]
map ByteString -> I
getI ([ByteString] -> [I]) -> [ByteString] -> [I]
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 (I -> a) -> [I] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map (forall a b. FromConstant a b => a -> b
fromConstant @I @a) (I
0 I -> [I] -> [I]
forall a. a -> [a] -> [a]
: [I]
cs [I] -> [I] -> [I]
forall a. [a] -> [a] -> [a]
++ [I
0])