{-# LANGUAGE BangPatterns #-} module Main where import Control.Monad import Control.Applicative import System.Random import Data.Maybe import Data.Time.Clock import Network.Haskoin.Crypto.ECDSA import Network.Haskoin.Crypto.Keys import Network.Haskoin.Crypto.Point import Network.Haskoin.Crypto.Ring import Network.Haskoin.Crypto.Curve bench :: Int -> String -> IO a -> IO a bench n s f = do start <- getCurrentTime !r <- f end <- getCurrentTime let t = (diffUTCTime end start) putStrLn $ "----------------------------" putStrLn $ s ++ " (" ++ (show n) ++ " samples)" putStrLn $ "Total time: " ++ (show t) putStrLn $ "Op/sec : " ++ (show $ (fromIntegral n)/t) seq r $ return r main :: IO () main = do _ <- bench (10^(7 :: Int)) "Ring multiplication (mod n)" (return $ testRing $ 10^(7 :: Int)) _ <- bench (10^(5 :: Int)) "Ring inversion (mod n)" (return $ invRing $ 10^(5 :: Int)) let elems = 2000 msg = fromInteger $ curveN - 10 !priv <- replicateM elems $ (fromJust . makePrvKey) <$> getStdRandom (randomR (1, curveN)) !pub <- bench elems "Point multiplications" $ forM priv $ \x -> return $! derivePubKey x _ <- bench 100000 "Point additions" $ forM (take 100000 $ cycle pub) $ \x -> do let !a = pubKeyPoint x return $! addPoint a a _ <- bench 100000 "Point doubling" $ forM (take 100000 $ cycle pub) $ \x -> do let !a = pubKeyPoint x return $! doublePoint a _ <- bench elems "Shamirs trick" $ forM (priv `zip` pub) $ \(d,q) -> do let !a = prvKeyFieldN d !b = pubKeyPoint q return $! shamirsTrick a b a b !sigs <- bench elems "Signature creations" $ withSource devURandom $! forM priv (signMsg msg) _ <- bench elems "Signature verifications" $ forM (sigs `zip` pub) $ \(s,q) -> return $! verifySig msg s q return () testRing :: Int -> FieldN testRing maxVal = go 2 0 where go i n | n < maxVal = go (i*i) (n + 1) | otherwise = i invRing :: Int -> FieldN invRing maxVal = go 1 0 where go i n | n < maxVal = go ((inverseN i) + 1) (n + 1) | otherwise = i