Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Browser integration of prover #10

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ cabal.project.local~
.ghc.environment.*
rust-wrapper/target/
rust-wrapper/Cargo.lock
lib.so
*.so
*.data
*.svg
*.nix
*.rlib
44 changes: 29 additions & 15 deletions Setup.hs
Original file line number Diff line number Diff line change
@@ -1,36 +1,50 @@
{-# LANGUAGE TemplateHaskell #-}
import Control.Exception (throwIO)
import Control.Monad
import Data.Char (isSpace)
import Data.List (dropWhile, isPrefixOf)
import Data.List (dropWhile, find, findIndex, isPrefixOf, tails)
import Data.Maybe (fromJust)
import Distribution.Simple
import Distribution.Types.HookedBuildInfo
import PseudoMacros
import System.Directory
import System.Exit
import System.Process (readProcess, system)

main :: IO ()
main = defaultMainWithHooks simpleUserHooks
{ preConf = buildRustLib
{
preConf = buildRustLib
}

buildRustLib :: Args -> a -> IO HookedBuildInfo
buildRustLib _ flags = do

buildResult <- system "cargo +nightly cbuild --release --manifest-path rust-wrapper/Cargo.toml"
case buildResult of
ExitSuccess -> return ()
ExitFailure exitCode -> throwIO $ userError $ "Build rust library failed with exit code " <> show exitCode
let file = $__FILE__
let pathToDistNewstyle = take (fromJust $ findIndex (isPrefixOf "dist-newstyle") (tails file)) file

isNotDependency <- doesFileExist (pathToDistNewstyle ++ "rust-wrapper/Cargo.toml")

output <- readProcess "rustc" ["--version", "--verbose"] ""
case filter ("host: " `isPrefixOf`) (lines output) of
[line] -> do
let host = dropWhile isSpace $ drop 5 line
pathToLib = "rust-wrapper/target/" <> host <> "/release/librust_wrapper.so"
pathToRustWrapper <- if isNotDependency
then return pathToDistNewstyle
else do
contents <- listDirectory (pathToDistNewstyle ++ "dist-newstyle/src/")
print $ contents
depLibs <- filterM (\p -> do
let prefixCond = isPrefixOf "zkfold-pr" p
dirCond <- doesDirectoryExist (pathToDistNewstyle ++ "dist-newstyle/src/" ++ p)
return $ dirCond && prefixCond) contents
print $ depLibs
return $ pathToDistNewstyle ++ "dist-newstyle/src/" ++ (head depLibs) ++ "/"

libExist <- doesFileExist pathToLib
unless libExist $ throwIO $ userError "Can't find rust library"
buildResult <- system ("cargo +nightly build --release " ++
"--manifest-path " ++ pathToRustWrapper ++ "rust-wrapper/Cargo.toml " ++
"--artifact-dir=" ++ pathToDistNewstyle ++ "libs/ -Z unstable-options"
)

copyFile pathToLib "./lib.so"
case buildResult of
ExitSuccess -> return ()
ExitFailure exitCode -> do
throwIO $ userError $ "Build rust library failed with exit code " <> show exitCode

_ -> throwIO $ userError "Can't find default rust target"
return emptyHookedBuildInfo
4 changes: 2 additions & 2 deletions bench/BenchMSM.hs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ main = do
(Vector s) <- generate arbitrary :: IO (Vector Length (ScalarField BLS12_381_G1))

let
points = V.fromList p
scalars = toPolyVec @(ScalarField BLS12_381_G1) @Length $ V.fromList s
points = p
scalars = toPolyVec @(ScalarField BLS12_381_G1) @Length s

defaultMain
[
Expand Down
51 changes: 51 additions & 0 deletions bench/BenchPolyDiv.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

module Main where

import Control.DeepSeq (force)
import Control.Exception (evaluate)
import Control.Monad (replicateM)
import Data.Tuple.Extra
import qualified Data.Vector as V
import Foreign
import Prelude hiding (sum, (*), (+), (-), (/), (^))
import qualified Prelude as P
import RustFunctions (rustDivFft)
import System.Random (randomIO)
import Test.Tasty.Bench

import ZkFold.Base.Algebra.Basic.Class
import ZkFold.Base.Algebra.Basic.Field
import ZkFold.Base.Algebra.Basic.Number (Prime)
import ZkFold.Base.Algebra.EllipticCurve.BLS12_381
import ZkFold.Base.Algebra.Polynomials.Univariate
-- | Generate random polynomials of given size
--
polynomials :: forall a. Prime a => Int -> IO (Poly (Zp a), Poly (Zp a))
polynomials size = do
coeffs1 <- replicateM size (toZp @a <$> randomIO)
coeffs2 <- replicateM size (toZp @a <$> randomIO)
evaluatedCoeffs1 <- evaluate . force . V.fromList $ coeffs1
evaluatedCoeffs2 <- evaluate . force . V.fromList $ coeffs2
pure (toPoly evaluatedCoeffs1, toPoly evaluatedCoeffs2)

sizes :: [Int]
sizes = ((2 :: Int) P.^) <$> [10 .. 14 :: Int]

ops :: forall a . (Eq a, Field a, Storable a) => [(String, Poly a -> Poly a -> (Poly a, Poly a))]
ops = [ ("Haskell division", qr)
, ("Rust division", \x y -> both toPoly (rustDivFft @a (fromPoly x) (fromPoly y)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am getting an unexpected result that Rust implementation slower than the Haskell one. Does it make sense to compare qr with polynomial division using FFT?

]

benchOps :: Prime a => Int -> [(String, Poly (Zp a) -> Poly (Zp a) -> (Poly (Zp a), Poly (Zp a)) )] -> Benchmark
benchOps size testOps = env (polynomials size) $ \ ~(p1, p2) ->
bgroup ("Multiplying polynomials of size " <> show size) $
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bench description should be updated.

flip fmap testOps $ \(desc, op) -> bench desc $ nf (uncurry op) (p1, p2)

main :: IO ()
main = do
defaultMain
[ bgroup "Field without roots of unity" $ flip fmap sizes $ \s -> benchOps @BLS12_381_Base s ops
, bgroup "Field with roots of unity" $ flip fmap sizes $ \s -> benchOps @BLS12_381_Scalar s ops
]
19 changes: 15 additions & 4 deletions bench/BenchProve.hs
Original file line number Diff line number Diff line change
@@ -1,21 +1,32 @@
{-# OPTIONS_GHC -Wno-orphans #-}
module Main where

import qualified Data.ByteString as BS
import GHC.Generics (U1 (U1))
import Prelude hiding (Num (..), length, sum, take, (-))
import RustBLS (RustBLS12_381_G1, RustBLS12_381_G2)
import RustFunctions (RustCore)
import Test.QuickCheck (Arbitrary (arbitrary), generate)
import Test.QuickCheck.Arbitrary (Arbitrary1 (liftArbitrary))
import Test.Tasty.Bench

import ZkFold.Base.Algebra.EllipticCurve.BLS12_381 (BLS12_381_G1, BLS12_381_G2)
import ZkFold.Base.Protocol.ARK.Plonk (Plonk)
import ZkFold.Base.Data.Vector (Vector)
import ZkFold.Base.Protocol.NonInteractiveProof
import ZkFold.Base.Protocol.Plonk (Plonk)

type PlonkSizeBS = 128
type PlonkBS n = Plonk PlonkSizeBS n BLS12_381_G1 BLS12_381_G2 BS.ByteString
type PlonkBS n = Plonk U1 (Vector 1) 32 (Vector n) RustBLS12_381_G1 RustBLS12_381_G2 BS.ByteString

instance Arbitrary (U1 a) where
arbitrary = return U1

instance Arbitrary1 U1 where
liftArbitrary _ = return U1

main :: IO ()
main = do
(TestData a w) <- generate arbitrary :: IO (NonInteractiveProofTestData (PlonkBS 2) HaskellCore)
a <- generate arbitrary :: IO (PlonkBS 2)
w <- generate arbitrary :: IO (Witness (PlonkBS 2))

let spHaskell = setupProve @(PlonkBS 2) @HaskellCore a
spRust = setupProve @(PlonkBS 2) @RustCore a
Expand Down
8 changes: 2 additions & 6 deletions cabal.project
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
packages: .

source-repository-package
type: git
location: https://github.com/BeFunctional/haskell-foreign-rust.git
tag: 90b1c210ae4e753c39481a5f3b141b74e6b6d96e

source-repository-package
type: git
location: https://github.com/zkFold/zkfold-base.git
tag: 204a983ce39dd683c1776a0c54a6fb02e53305f6
tag: c8d4695e7f5e0140b76d819f82c4d41d1510b385
subdir: symbolic-base
Loading