33
44module Main where
55
6- import Accumulator (Accumulator , Element (.. ), addElement , emptyAccumulator , removeElement )
6+ import Accumulator (Accumulator , Element (.. ), addElement , buildAccumulator , emptyAccumulator , removeElement )
77import Bindings (getPolyCommitOverG1 , getPolyCommitOverG2 )
88import Cardano.Crypto.EllipticCurve.BLS12_381.Internal (
99 Point1 (.. ),
@@ -21,7 +21,7 @@ import Cardano.Crypto.EllipticCurve.BLS12_381.Internal (
2121 )
2222import Criterion.Main
2323import qualified Data.ByteString as B
24- import Data.List ( nub )
24+ import qualified Data.Set as Set
2525import qualified Field as F
2626import GHC.IO (unsafePerformIO )
2727import PlutusTx.Numeric (
@@ -33,30 +33,35 @@ import PlutusTx.Numeric (
3333 MultiplicativeSemigroup (.. ),
3434 )
3535import System.Random (randomRIO )
36+ import Text.Printf (printf )
3637
37- -- Helper function to generate a random ByteString of a given length
38+ -- | Helper function to convert a ByteString to a hex string
39+ byteStringAsHex :: B. ByteString -> String
40+ byteStringAsHex bs = " 0x" ++ concat (B. foldr' (\ w s -> printf " %02x" w : s) [] bs)
41+
42+ -- | Helper function to generate a random ByteString of a given length
3843generateRandomByteString :: Int -> IO B. ByteString
3944generateRandomByteString n = B. pack <$> mapM (\ _ -> randomRIO (0 , 255 )) [1 .. n]
4045
41- -- Generate a random set of N ByteStrings
46+ -- | Generate a random set of N ByteStrings
4247generateRandomSet :: Int -> IO [Element ]
4348generateRandomSet n = mapM (\ _ -> generateRandomByteString 32 ) [1 .. n]
4449
45- -- Helper function to pick n random elements from a list
50+ -- | Helper function to pick n random elements from a list
4651pickRandomElements :: Int -> [a ] -> IO [a ]
4752pickRandomElements n xs = mapM (\ _ -> (xs !! ) <$> randomRIO (0 , length xs Prelude. - 1 )) [1 .. n]
4853
49- -- Create test setup with a set of elements and a subset of that set
50- mkTestSetup :: Int -> Int -> IO (Accumulator , [Element ], [Point1 ], [Point2 ])
51- mkTestSetup setSize subSetSize = do
54+ -- | Create test setup with a set of elements and a subset of that set
55+ generateTestSetup :: Int -> Int -> IO (Accumulator , [Element ], [Point1 ], [Point2 ])
56+ generateTestSetup setSize subSetSize = do
5257 -- Generate a random set of ByteStrings
5358 set <- generateRandomSet setSize
54- let setMap = foldl addElement emptyAccumulator set :: Accumulator
59+ let accumulator = buildAccumulator set
5560
56- -- Define a tau
61+ -- Define a tau (a large secret value that no one knows)
5762 let tau = F. Scalar 22_435_875_175_126_190_499_447_740_508_185_965_837_690_552_500_527_637_822_603_658_699_938_581_184_511
5863
59- -- Define powers of tau
64+ -- Define powers of tau (tau^0, tau^1, ..., tau^setSize+1 over the field)
6065 let powerOfTauField = map (F. powModScalar tau) [0 .. (fromIntegral setSize)]
6166
6267 -- Convert the powers of tau to integers back
@@ -75,72 +80,88 @@ mkTestSetup setSize subSetSize = do
7580
7681 -- Randomly pick subSetSize elements from the set
7782 subsetNonUnique <- pickRandomElements subSetSize set
78- let subset = nub subsetNonUnique
83+ -- let subset = nub subsetNonUnique
84+ let subset = Set. toList $ Set. fromList subsetNonUnique
7985
80- return (setMap , subset, crsG1, crsG2)
86+ return (accumulator , subset, crsG1, crsG2)
8187
82- -- Helper to extract the result or force an error
88+ -- | Helper to extract the result or force an error
8389benchmarkProofG1 :: [Element ] -> Accumulator -> [Point1 ] -> IO ()
8490benchmarkProofG1 subSet setMap crsG1 = do
8591 result <- getPolyCommitOverG1 subSet setMap crsG1
8692 case result of
8793 Left err -> error err -- Force an error to trigger computation
8894 Right _ -> return ()
8995
96+ -- | Helper to extract the result or force an error
9097benchmarkProofG2 :: [Element ] -> Accumulator -> [Point2 ] -> IO ()
9198benchmarkProofG2 subSet setMap crsG2 = do
9299 result <- getPolyCommitOverG2 subSet setMap crsG2
93100 case result of
94101 Left err -> error err -- Force an error to trigger computation
95102 Right _ -> return ()
96103
97- -- Main function with benchmarking
98- main :: IO ()
99- main = do
100- -- Create a test setup with 1_000 elements and a subset of 1 (the proof is over the set minus the subset)
101- (setMap, subSet, crsG1, crsG2) <- mkTestSetup 10 2
102-
103- -- Benchmark the two calculations
104+ -- | Run benchmarks for proof calculations
105+ runBenchmarks :: IO ()
106+ runBenchmarks = do
107+ (accumulator, subSet, crsG1, crsG2) <- generateTestSetup 1_000 0
104108 defaultMain
105109 [ bgroup
106110 " proof calculations"
107- [ bench " getProofOverG1" $ nfIO (benchmarkProofG1 subSet setMap crsG1)
108- , bench " getProofOverG2" $ nfIO (benchmarkProofG2 subSet setMap crsG2)
111+ [ bench " getProofOverG1" $ nfIO (benchmarkProofG1 subSet accumulator crsG1)
112+ , bench " getProofOverG2" $ nfIO (benchmarkProofG2 subSet accumulator crsG2)
109113 ]
110114 ]
111115
112- -- An basic E2E example.
116+ -- | Run an end-to-end example
117+ runE2EExample :: IO ()
118+ runE2EExample = do
119+ -- Create a test setup with 1_000 elements and a subset of size 0 (the proof is over the set minus the subset, so this is a good test case)
120+ (accumulator, subSet, crsG1, crsG2) <- generateTestSetup 1_000 0
113121
114- -- Say we have this set of elements (note that the first argument of the mkTestSetup function call above
115- -- should be bigger than the length of this set)
116- let mySet = [" element1" , " element2" , " element3" , " element4" ] :: [Element ]
122+ -- Say we have this set of elements (note that the first argument of the generateTestSetup function call above
123+ -- should be bigger than the length of this set, as we use the CRS from there )
124+ let mySet = [" element1" , " element2" , " element3" , " element4" , " element5 " , " element6 " , " element7 " , " element8 " , " element9 " , " element10 " ] :: [Element ]
117125 -- We can get the offchain explicit accumulator via
118- myAcc = foldl addElement emptyAccumulator mySet :: Accumulator
126+ myAcc = buildAccumulator mySet
119127
120128 -- Then we can calculate the onchain representation of our accumulator via
121129 accCommit <- getPolyCommitOverG2 [] myAcc crsG2
122130
123131 -- Say we want to proof the subset of the set
124- let mySubset = [" element1 " , " element4 " ] :: [Element ]
132+ let mySubset = [" element3 " , " element9 " ] :: [Element ]
125133
126134 -- then the proof can be calculated via
127135 proof <- getPolyCommitOverG2 mySubset myAcc crsG2
128136
129137 -- Verify the proof onchain (but doing it with offchain code)
130- case accCommit of
131- Left err -> print $ err ++ " for accumulator"
132- Right g2AccCommit -> case proof of
133- Left err -> print $ err ++ " for proof"
134- Right g2ProofCommit -> do
135- let subsetAcc = foldl addElement emptyAccumulator mySubset :: Accumulator
136- g1 = blsGenerator :: Point1
137- subsetCommit <- getPolyCommitOverG1 [] subsetAcc crsG1
138- case subsetCommit of
139- Left err -> print $ err ++ " for subset accumulator"
140- Right g1SubsetCommit -> do
141- let pt1 = millerLoop g1 g2AccCommit
142- pt2 = millerLoop g1SubsetCommit g2ProofCommit
143- pairingCheck = ptFinalVerify pt1 pt2
144- print pairingCheck
145-
146- print " Run complete"
138+ case (accCommit, proof) of
139+ (Left err, _) -> print $ err ++ " for accumulator"
140+ (_, Left err) -> print $ err ++ " for proof"
141+ (Right g2AccCommit, Right g2ProofCommit) -> do
142+ let subsetAcc = buildAccumulator mySubset
143+ subsetCommit <- getPolyCommitOverG1 [] subsetAcc crsG1
144+ case subsetCommit of
145+ Left err -> print $ err ++ " for subset accumulator"
146+ Right g1SubsetCommit -> do
147+ let g1 = blsGenerator :: Point1
148+ pt1 = millerLoop g1 g2AccCommit
149+ pt2 = millerLoop g1SubsetCommit g2ProofCommit
150+ pairingCheck = ptFinalVerify pt1 pt2
151+ accBS = blsCompress g2AccCommit
152+ proofBS = blsCompress g2ProofCommit
153+ print " Proving that the subset is in the set for:"
154+ print $ " Subset: " ++ show mySubset
155+ print $ " With proof: " ++ show (byteStringAsHex proofBS)
156+ print $ " Set: " ++ show mySet
157+ print $ " With accumulator commitment: " ++ show (byteStringAsHex accBS)
158+ print $ " The proof is: " ++ show pairingCheck
159+
160+ -- Verify the proof onchain (but doing it with offchain code)
161+ print " E2E run complete"
162+
163+ -- Main function with benchmarking and an E2E example
164+ main :: IO ()
165+ main = do
166+ runBenchmarks
167+ runE2EExample
0 commit comments