Skip to content

Commit 9f35ec5

Browse files
Acentellessdiehl
authored andcommitted
Integration with Galois field library (#15)
* Use galois-field library * Pass tests * Use Gen monad and create arbitrary instances for arithmetic circuits * Remove Fractional constraints in favor of PrimeField * Upgrade CircleCI * Remove redundant Fq type signatures * Ensure prime fields are used in range proofs * Update README * Update changelog
1 parent 3312b49 commit 9f35ec5

File tree

22 files changed

+513
-534
lines changed

22 files changed

+513
-534
lines changed

.circleci/config.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
version: 2
2+
jobs:
3+
build:
4+
docker:
5+
- image: fpco/stack-build:lts
6+
steps:
7+
- checkout
8+
- restore_cache:
9+
name: Restore Cached Dependencies
10+
keys:
11+
- pairing-{{ checksum "package.yaml" }}
12+
- run:
13+
name: Resolve/Update Dependencies
14+
command: stack setup
15+
- run:
16+
name: Run tests
17+
command: stack test
18+
- save_cache:
19+
name: Cache Dependencies
20+
key: pairing-{{ checksum "package.yaml" }}
21+
paths:
22+
- ".stack-work"

Bulletproofs/ArithmeticCircuit/Internal.hs

Lines changed: 78 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import Protolude hiding (head)
77
import Data.List (head)
88
import qualified Data.List as List
99
import qualified Data.Map as Map
10+
import Test.QuickCheck
11+
import PrimeField (PrimeField(..), toInt)
1012

1113
import System.Random.Shuffle (shuffleM)
1214
import qualified Crypto.Random.Types as Crypto (MonadRandom(..))
@@ -103,10 +105,10 @@ padAssignment Assignment{..}
103105
aRNew = padToNearestPowerOfTwo aR
104106
aONew = padToNearestPowerOfTwo aO
105107

106-
delta :: (Eq f, Field f) => Integer -> f -> [f] -> [f] -> f
108+
delta :: (KnownNat p) => Integer -> PrimeField p -> [PrimeField p] -> [PrimeField p] -> PrimeField p
107109
delta n y zwL zwR= (powerVector (recip y) n `hadamardp` zwR) `dot` zwL
108110

109-
commitBitVector :: (AsInteger f) => f -> [f] -> [f] -> Crypto.Point
111+
commitBitVector :: (KnownNat p) => PrimeField p -> [PrimeField p] -> [PrimeField p] -> Crypto.Point
110112
commitBitVector vBlinding vL vR = vLG `addP` vRH `addP` vBlindingH
111113
where
112114
vBlindingH = vBlinding `mulP` h
@@ -115,13 +117,13 @@ commitBitVector vBlinding vL vR = vLG `addP` vRH `addP` vBlindingH
115117

116118
shamirGxGxG :: (Show f, Num f) => Crypto.Point -> Crypto.Point -> Crypto.Point -> f
117119
shamirGxGxG p1 p2 p3
118-
= fromInteger $ oracle $ show q <> pointToBS p1 <> pointToBS p2 <> pointToBS p3
120+
= fromInteger $ oracle $ show _q <> pointToBS p1 <> pointToBS p2 <> pointToBS p3
119121

120122
shamirGs :: (Show f, Num f) => [Crypto.Point] -> f
121-
shamirGs ps = fromInteger $ oracle $ show q <> foldMap pointToBS ps
123+
shamirGs ps = fromInteger $ oracle $ show _q <> foldMap pointToBS ps
122124

123125
shamirZ :: (Show f, Num f) => f -> f
124-
shamirZ z = fromInteger $ oracle $ show q <> show z
126+
shamirZ z = fromInteger $ oracle $ show _q <> show z
125127

126128
---------------------------------------------
127129
-- Polynomials
@@ -180,30 +182,7 @@ genIdenMatrix size = (\x -> (\y -> fromIntegral (fromEnum (x == y))) <$> [1..siz
180182
genZeroMatrix :: (Num f) => Integer -> Integer -> [[f]]
181183
genZeroMatrix (fromIntegral -> n) (fromIntegral -> m) = replicate n (replicate m 0)
182184

183-
generateWv :: (Num f, MonadRandom m) => Integer -> Integer -> m [[f]]
184-
generateWv lConstraints m
185-
| lConstraints < m = panic "Number of constraints must be bigger than m"
186-
| otherwise = shuffleM (genIdenMatrix m ++ genZeroMatrix (lConstraints - m) m)
187-
188-
generateGateWeights :: (Crypto.MonadRandom m, Num f) => Integer -> Integer -> m (GateWeights f)
189-
generateGateWeights lConstraints n = do
190-
let genVec = ((\i -> insertAt (fromIntegral i) (oneVector n) (replicate (fromIntegral lConstraints - 1) (zeroVector n))) <$> generateMax (fromIntegral lConstraints))
191-
wL <- genVec
192-
wR <- genVec
193-
wO <- genVec
194-
pure $ GateWeights wL wR wO
195-
where
196-
zeroVector x = replicate (fromIntegral x) 0
197-
oneVector x = replicate (fromIntegral x) 1
198-
199-
generateRandomAssignment :: forall f m . (Num f, AsInteger f, Crypto.MonadRandom m) => Integer -> m (Assignment f)
200-
generateRandomAssignment n = do
201-
aL <- replicateM (fromIntegral n) ((fromInteger :: Integer -> f) <$> generateMax (2^n))
202-
aR <- replicateM (fromIntegral n) ((fromInteger :: Integer -> f) <$> generateMax (2^n))
203-
let aO = aL `hadamardp` aR
204-
pure $ Assignment aL aR aO
205-
206-
computeInputValues :: (Field f, Eq f) => GateWeights f -> [[f]] -> Assignment f -> [f] -> [f]
185+
computeInputValues :: (KnownNat p) => GateWeights (PrimeField p) -> [[PrimeField p]] -> Assignment (PrimeField p) -> [PrimeField p] -> [PrimeField p]
207186
computeInputValues GateWeights{..} wV Assignment{..} cs
208187
= solveLinearSystem $ zipWith (\row s -> reverse $ s : row) wV solutions
209188
where
@@ -212,7 +191,7 @@ computeInputValues GateWeights{..} wV Assignment{..} cs
212191
^+^ vectorMatrixProductT aO wO
213192
^-^ cs
214193

215-
gaussianReduce :: (Field f, Eq f) => [[f]] -> [[f]]
194+
gaussianReduce :: (KnownNat p) => [[PrimeField p]] -> [[PrimeField p]]
216195
gaussianReduce matrix = fixlastrow $ foldl reduceRow matrix [0..length matrix-1]
217196
where
218197
-- Swaps element at position a with element at position b.
@@ -247,13 +226,80 @@ gaussianReduce matrix = fixlastrow $ foldl reduceRow matrix [0..length matrix-1]
247226
nz = List.last (List.init row)
248227

249228
-- Solve a matrix (must already be in REF form) by back substitution.
250-
substituteMatrix :: (Field f, Eq f) => [[f]] -> [f]
229+
substituteMatrix :: (KnownNat p) => [[PrimeField p]] -> [PrimeField p]
251230
substituteMatrix matrix = foldr next [List.last (List.last matrix)] (List.init matrix)
252231
where
253232
next row found = let
254233
subpart = List.init $ drop (length matrix - length found) row
255234
solution = List.last row - sum (zipWith (*) found subpart)
256235
in solution : found
257236

258-
solveLinearSystem :: (Field f, Eq f) => [[f]] -> [f]
237+
solveLinearSystem :: (KnownNat p) => [[PrimeField p]] -> [PrimeField p]
259238
solveLinearSystem = reverse . substituteMatrix . gaussianReduce
239+
240+
-------------------------
241+
-- Arbitrary instances --
242+
-------------------------
243+
244+
instance (KnownNat p) => Arbitrary (ArithCircuit (PrimeField p)) where
245+
arbitrary = do
246+
n <- choose (1, 100)
247+
m <- choose (1, n)
248+
arithCircuitGen n m
249+
250+
arithCircuitGen :: forall p. (KnownNat p) => Integer -> Integer -> Gen (ArithCircuit (PrimeField p))
251+
arithCircuitGen n m = do
252+
-- TODO: Can lConstraints be a different value?
253+
let lConstraints = m
254+
255+
cs <- vectorOf (fromIntegral m) arbitrary
256+
257+
weights@GateWeights{..} <- gateWeightsGen lConstraints n
258+
let gateWeights = GateWeights wL wR wO
259+
260+
commitmentWeights <- wvGen lConstraints m
261+
pure $ ArithCircuit gateWeights commitmentWeights cs
262+
where
263+
gateWeightsGen :: Integer -> Integer -> Gen (GateWeights (PrimeField p))
264+
gateWeightsGen lConstraints n = do
265+
let genVec = ((\i -> insertAt i (oneVector n) (replicate (fromIntegral lConstraints - 1) (zeroVector n))) <$> choose (0, fromIntegral lConstraints))
266+
wL <- genVec
267+
wR <- genVec
268+
wO <- genVec
269+
pure $ GateWeights wL wR wO
270+
271+
wvGen :: Integer -> Integer -> Gen [[PrimeField p]]
272+
wvGen lConstraints m
273+
| lConstraints < m = panic "Number of constraints must be bigger than m"
274+
| otherwise = shuffle (genIdenMatrix m ++ genZeroMatrix (lConstraints - m) m)
275+
zeroVector x = replicate (fromIntegral x) 0
276+
oneVector x = replicate (fromIntegral x) 1
277+
278+
279+
instance (KnownNat p) => Arbitrary (Assignment (PrimeField p)) where
280+
arbitrary = do
281+
n <- (arbitrary :: Gen Integer)
282+
arithAssignmentGen n
283+
284+
arithAssignmentGen :: (KnownNat p) => Integer -> Gen (Assignment (PrimeField p))
285+
arithAssignmentGen n = do
286+
aL <- vectorOf (fromIntegral n) (fromInteger <$> choose (0, 2^n))
287+
aR <- vectorOf (fromIntegral n) (fromInteger <$> choose (0, 2^n))
288+
let aO = aL `hadamardp` aR
289+
pure $ Assignment aL aR aO
290+
291+
instance (KnownNat p) => Arbitrary (ArithWitness (PrimeField p)) where
292+
arbitrary = do
293+
n <- choose (1, 100)
294+
m <- choose (1, n)
295+
arithCircuit <- arithCircuitGen n m
296+
assignment <- arithAssignmentGen n
297+
arithWitnessGen assignment arithCircuit m
298+
299+
arithWitnessGen :: (KnownNat p) => Assignment (PrimeField p) -> ArithCircuit (PrimeField p) -> Integer -> Gen (ArithWitness (PrimeField p))
300+
arithWitnessGen assignment arith@ArithCircuit{..} m = do
301+
commitBlinders <- vectorOf (fromIntegral m) arbitrary
302+
let vs = computeInputValues weights commitmentWeights assignment cs
303+
commitments = zipWith commit vs commitBlinders
304+
pure $ ArithWitness assignment commitments commitBlinders
305+

Bulletproofs/ArithmeticCircuit/Prover.hs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import Crypto.Random.Types (MonadRandom(..))
77
import Crypto.Number.Generate (generateMax)
88
import qualified Crypto.PubKey.ECC.Prim as Crypto
99
import qualified Crypto.PubKey.ECC.Types as Crypto
10+
import PrimeField (PrimeField(..), toInt)
1011

1112
import Bulletproofs.Curve
1213
import Bulletproofs.Utils hiding (shamirZ)
@@ -16,15 +17,15 @@ import Bulletproofs.ArithmeticCircuit.Internal
1617
-- | Generate a zero-knowledge proof of computation
1718
-- for an arithmetic circuit with a valid witness
1819
generateProof
19-
:: forall f m
20-
. (MonadRandom m, AsInteger f, Field f, Show f, Eq f)
21-
=> ArithCircuit f
22-
-> ArithWitness f
23-
-> m (ArithCircuitProof f)
20+
:: forall p m
21+
. (MonadRandom m, KnownNat p)
22+
=> ArithCircuit (PrimeField p)
23+
-> ArithWitness (PrimeField p)
24+
-> m (ArithCircuitProof (PrimeField p))
2425
generateProof (padCircuit -> ArithCircuit{..}) ArithWitness{..} = do
2526
let GateWeights{..} = weights
2627
Assignment{..} = padAssignment assignment
27-
genBlinding = (fromInteger :: Integer -> f) <$> generateMax q
28+
genBlinding = (fromInteger :: Integer -> PrimeField p) <$> generateMax _q
2829
aiBlinding <- genBlinding
2930
aoBlinding <- genBlinding
3031
sBlinding <- genBlinding
@@ -57,7 +58,7 @@ generateProof (padCircuit -> ArithCircuit{..}) ArithWitness{..} = do
5758
+ (zs `dot` w)
5859
+ delta n y zwL zwR
5960

60-
tBlindings <- insertAt 2 0 . (:) 0 <$> replicateM 5 ((fromInteger :: Integer -> f) <$> generateMax q)
61+
tBlindings <- insertAt 2 0 . (:) 0 <$> replicateM 5 ((fromInteger :: Integer -> PrimeField p) <$> generateMax _q)
6162
let tCommits = zipWith commit tPoly tBlindings
6263

6364
let x = shamirGs tCommits
@@ -70,17 +71,17 @@ generateProof (padCircuit -> ArithCircuit{..}) ArithWitness{..} = do
7071
commitTimesWeigths = commitBlinders `vectorMatrixProductT` commitmentWeights
7172
zGamma = zs `dot` commitTimesWeigths
7273
tBlinding = sum (zipWith (\i blinding -> blinding * (x ^ i)) [0..] tBlindings)
73-
+ (fSquare x * zGamma)
74+
+ ((x ^ 2) * zGamma)
7475

75-
mu = aiBlinding * x + aoBlinding * fSquare x + sBlinding * (x ^ 3)
76+
mu = aiBlinding * x + aoBlinding * (x ^ 2) + sBlinding * (x ^ 3)
7677

7778
let uChallenge = shamirU tBlinding mu t
7879
u = uChallenge `mulP` g
7980
hs' = zipWith mulP (powerVector (recip y) n) hs
8081
gExp = (*) x <$> (powerVector (recip y) n `hadamardp` zwR)
8182
hExp = (((*) x <$> zwL) ^+^ zwO) ^-^ ys
8283
commitmentLR = (x `mulP` aiCommit)
83-
`addP` (fSquare x `mulP` aoCommit)
84+
`addP` ((x ^ 2) `mulP` aoCommit)
8485
`addP` ((x ^ 3)`mulP` sCommit)
8586
`addP` sumExps gExp gs
8687
`addP` sumExps hExp hs'

Bulletproofs/ArithmeticCircuit/Verifier.hs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import Data.List (head)
66

77
import qualified Crypto.PubKey.ECC.Prim as Crypto
88
import qualified Crypto.PubKey.ECC.Types as Crypto
9+
import PrimeField (PrimeField(..), toInt)
910

1011
import Bulletproofs.Curve
1112
import Bulletproofs.Utils hiding (shamirZ)
@@ -17,10 +18,10 @@ import Bulletproofs.ArithmeticCircuit.Internal
1718
-- | Verify that a zero-knowledge proof holds
1819
-- for an arithmetic circuit given committed input values
1920
verifyProof
20-
:: (AsInteger f, Field f, Eq f, Show f)
21+
:: (KnownNat p)
2122
=> [Crypto.Point]
22-
-> ArithCircuitProof f
23-
-> ArithCircuit f
23+
-> ArithCircuitProof (PrimeField p)
24+
-> ArithCircuit (PrimeField p)
2425
-> Bool
2526
verifyProof vCommits proof@ArithCircuitProof{..} (padCircuit -> ArithCircuit{..})
2627
= verifyLRCommitment && verifyTPoly
@@ -55,9 +56,9 @@ verifyProof vCommits proof@ArithCircuitProof{..} (padCircuit -> ArithCircuit{..}
5556
rhs = (gExp `mulP` g)
5657
`addP` tCommitsExpSum
5758
`addP` sumExps vExp vCommits
58-
gExp = fSquare x * (k + cQ)
59+
gExp = (x ^ 2) * (k + cQ)
5960
cQ = zs `dot` cs
60-
vExp = (*) (fSquare x) <$> (zs `vectorMatrixProduct` commitmentWeights)
61+
vExp = (*) (x ^ 2) <$> (zs `vectorMatrixProduct` commitmentWeights)
6162
k = delta n y zwL zwR
6263
xs = 0 : x : 0 : (((^) x) <$> [3..6])
6364
tCommitsExpSum = sumExps xs tCommits
@@ -72,7 +73,7 @@ verifyProof vCommits proof@ArithCircuitProof{..} (padCircuit -> ArithCircuit{..}
7273
gExp = (*) x <$> (powerVector (recip y) n `hadamardp` zwR)
7374
hExp = (((*) x <$> zwL) ^+^ zwO) ^-^ ys
7475
commitmentLR = (x `mulP` aiCommit)
75-
`addP` (fSquare x `mulP` aoCommit)
76+
`addP` ((x ^ 2) `mulP` aoCommit)
7677
`addP` ((x ^ 3) `mulP` sCommit)
7778
`addP` sumExps gExp gs
7879
`addP` sumExps hExp hs'

Bulletproofs/Curve.hs

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
module Bulletproofs.Curve (
2-
q,
2+
_q,
3+
_a,
4+
_b,
35
g,
46
h,
57
gs,
@@ -23,15 +25,34 @@ import Math.NumberTheory.Moduli.Sqrt (sqrtModP)
2325
import Numeric
2426
import qualified Data.List as L
2527

28+
-- Implementation using the elliptic curve secp256k12
29+
-- which has 128 bit security.
30+
-- Parameters as in Cryptonite:
31+
-- SEC_p256k1 = CurveFP $ CurvePrime
32+
-- 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
33+
-- (CurveCommon
34+
-- { ecc_a = 0x0000000000000000000000000000000000000000000000000000000000000000
35+
-- , ecc_b = 0x0000000000000000000000000000000000000000000000000000000000000007
36+
-- , ecc_g = Point 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
37+
-- 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
38+
-- , ecc_n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
39+
-- , ecc_h = 1
40+
-- })
2641
curveName :: Crypto.CurveName
2742
curveName = Crypto.SEC_p256k1
2843

2944
curve :: Crypto.Curve
3045
curve = Crypto.getCurveByName curveName
3146

3247
-- | Order of the curve
33-
q :: Integer
34-
q = Crypto.ecc_n . Crypto.common_curve $ curve
48+
_q :: Integer
49+
_q = Crypto.ecc_n . Crypto.common_curve $ curve
50+
51+
_b :: Integer
52+
_b = Crypto.ecc_b . Crypto.common_curve $ curve
53+
54+
_a :: Integer
55+
_a = Crypto.ecc_a . Crypto.common_curve $ curve
3556

3657
-- | Generator of the curve
3758
g :: Crypto.Point
@@ -64,8 +85,8 @@ pointToBS Crypto.PointO = ""
6485
pointToBS (Crypto.Point x y) = show x <> show y
6586

6687
-- | Characteristic of the underlying finite field of the elliptic curve
67-
p :: Integer
68-
p = Crypto.ecc_p cp
88+
_p :: Integer
89+
_p = Crypto.ecc_p cp
6990
where
7091
cp = case curve of
7192
Crypto.CurveFP c -> c
@@ -82,6 +103,6 @@ generateH basePoint extra =
82103
then Crypto.Point x y
83104
else generateH basePoint (toS $ '1':extra)
84105
where
85-
x = oracle (pointToBS basePoint <> toS extra) `mod` p
86-
yM = sqrtModP (x ^ 3 + 7) p
106+
x = oracle (pointToBS basePoint <> toS extra) `mod` _p
107+
yM = sqrtModP (x ^ 3 + 7) _p
87108

0 commit comments

Comments
 (0)