mirror of
https://github.com/logos-storage/plonky2-verifier.git
synced 2026-01-02 13:53:07 +00:00
150 lines
3.8 KiB
Haskell
150 lines
3.8 KiB
Haskell
|
|
-- | Reference (simple, but very slow) implementation of the Goldilocks prime field
|
|
|
|
{-# LANGUAGE BangPatterns, NumericUnderscores #-}
|
|
module Goldilocks where
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
import Prelude hiding ( div )
|
|
import qualified Prelude
|
|
|
|
import Data.Bits
|
|
import Data.Word
|
|
import Data.Ratio
|
|
import Data.Array
|
|
|
|
import Text.Printf
|
|
|
|
import System.Random
|
|
|
|
import GHC.Generics
|
|
import Data.Aeson ( ToJSON(..), FromJSON(..) )
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
type F = Goldilocks
|
|
|
|
fromF :: F -> Word64
|
|
fromF (Goldilocks x) = fromInteger x
|
|
|
|
toF :: Word64 -> F
|
|
toF = mkGoldilocks . fromIntegral
|
|
|
|
rndF :: IO F
|
|
rndF = Goldilocks <$> randomRIO ( 0 , 0xffff_ffff_0000_0000 )
|
|
|
|
-- | The generator of the multiplicative subgroup of F used by Plonky2
|
|
multGen :: F
|
|
multGen = 0xc65c18b67785d900
|
|
|
|
-- | The generator of the largest 2-adic subgroup of F used by Plonky2
|
|
twoAdicGen :: F
|
|
twoAdicGen = 0x64fdd1a46201e246
|
|
|
|
-- | Sage code:
|
|
--
|
|
-- > p = 2^64-2^32+1
|
|
-- > F = GF(p)
|
|
-- > g = F(0xc65c18b67785d900)
|
|
-- > print( g.multiplicative_order() == p-1 )
|
|
-- > h = g ^ ( (p-1) / 2^32 )
|
|
-- > print( h == F(0x64fdd1a46201e246) )
|
|
-- > [ h^(2^(32-k)) for k in range(33) ]
|
|
--
|
|
rootsOfUnity :: Array Int Goldilocks
|
|
rootsOfUnity = listArray (0,32) $ reverse $ go twoAdicGen where
|
|
go 1 = [1]
|
|
go x = x : go (x*x)
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
newtype Goldilocks
|
|
= Goldilocks Integer
|
|
deriving (Eq,Generic)
|
|
|
|
asInteger :: Goldilocks -> Integer
|
|
asInteger (Goldilocks x) = x
|
|
|
|
instance Show Goldilocks where
|
|
show (Goldilocks x) = show x -- decimal
|
|
-- show (Goldilocks x) = printf "0x%016x" x -- hex
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
instance ToJSON Goldilocks where
|
|
toJSON x = toJSON (asInteger x)
|
|
|
|
instance FromJSON Goldilocks where
|
|
parseJSON o = mkGoldilocks <$> parseJSON o
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
instance Num Goldilocks where
|
|
fromInteger = mkGoldilocks
|
|
negate = neg
|
|
(+) = add
|
|
(-) = sub
|
|
(*) = mul
|
|
abs = id
|
|
signum _ = Goldilocks 1
|
|
|
|
square :: Goldilocks -> Goldilocks
|
|
square x = x*x
|
|
|
|
instance Fractional Goldilocks where
|
|
fromRational y = fromInteger (numerator y) `div` fromInteger (denominator y)
|
|
recip = inv
|
|
(/) = div
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- | @p = 2^64 - 2^32 + 1@
|
|
goldilocksPrime :: Integer
|
|
goldilocksPrime = 0x_ffff_ffff_0000_0001
|
|
|
|
modp :: Integer -> Integer
|
|
modp a = mod a goldilocksPrime
|
|
|
|
mkGoldilocks :: Integer -> Goldilocks
|
|
mkGoldilocks = Goldilocks . modp
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
neg :: Goldilocks -> Goldilocks
|
|
neg (Goldilocks k) = mkGoldilocks (negate k)
|
|
|
|
add :: Goldilocks -> Goldilocks -> Goldilocks
|
|
add (Goldilocks a) (Goldilocks b) = mkGoldilocks (a+b)
|
|
|
|
sub :: Goldilocks -> Goldilocks -> Goldilocks
|
|
sub (Goldilocks a) (Goldilocks b) = mkGoldilocks (a-b)
|
|
|
|
sqr :: Goldilocks -> Goldilocks
|
|
sqr x = mul x x
|
|
|
|
mul :: Goldilocks -> Goldilocks -> Goldilocks
|
|
mul (Goldilocks a) (Goldilocks b) = mkGoldilocks (a*b)
|
|
|
|
inv :: Goldilocks -> Goldilocks
|
|
inv x = pow x (goldilocksPrime - 2)
|
|
|
|
div :: Goldilocks -> Goldilocks -> Goldilocks
|
|
div a b = mul a (inv b)
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
pow :: Goldilocks -> Integer -> Goldilocks
|
|
pow x e
|
|
| e == 0 = 1
|
|
| e < 0 = pow (inv x) (negate e)
|
|
| otherwise = go 1 x e
|
|
where
|
|
go !acc _ 0 = acc
|
|
go !acc !s !expo = case expo .&. 1 of
|
|
0 -> go acc (sqr s) (shiftR expo 1)
|
|
_ -> go (acc*s) (sqr s) (shiftR expo 1)
|
|
|
|
--------------------------------------------------------------------------------
|
|
|