Skip to content

Commit 94ff1c5

Browse files
gdijkstrasdiehl
authored andcommitted
Double exponentiation optimisation (#13)
* Benchmark and profile rangeproofs * Use `Control.Exception.assert` in order for debugging assertions to be optimised away * Use double exponentiation in various places * Ignore some files * Replace refutable patterns with irrefutable patterns
1 parent 1dd2b81 commit 94ff1c5

File tree

15 files changed

+177
-74
lines changed

15 files changed

+177
-74
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,8 @@
22
.stack-work/
33
bulletproofs.cabal
44
*~
5+
*.hi
6+
*.o
7+
*.prof
8+
*.prof.html
9+
Rangeproof

Bulletproofs/ArithmeticCircuit/Internal.hs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
module Bulletproofs.ArithmeticCircuit.Internal where
55

66
import Protolude hiding (head)
7-
import Control.Monad.Fail
87
import Data.List (head)
98
import qualified Data.List as List
109
import qualified Data.Map as Map
@@ -111,8 +110,8 @@ commitBitVector :: (AsInteger f) => f -> [f] -> [f] -> Crypto.Point
111110
commitBitVector vBlinding vL vR = vLG `addP` vRH `addP` vBlindingH
112111
where
113112
vBlindingH = vBlinding `mulP` h
114-
vLG = foldl' addP Crypto.PointO ( zipWith mulP vL gs )
115-
vRH = foldl' addP Crypto.PointO ( zipWith mulP vR hs )
113+
vLG = sumExps vL gs
114+
vRH = sumExps vR hs
116115

117116
shamirGxGxG :: (Show f, Num f) => Crypto.Point -> Crypto.Point -> Crypto.Point -> f
118117
shamirGxGxG p1 p2 p3
@@ -186,9 +185,12 @@ generateWv lConstraints m
186185
| lConstraints < m = panic "Number of constraints must be bigger than m"
187186
| otherwise = shuffleM (genIdenMatrix m ++ genZeroMatrix (lConstraints - m) m)
188187

189-
generateGateWeights :: (Crypto.MonadRandom m, Num f, MonadFail m) => Integer -> Integer -> m (GateWeights f)
188+
generateGateWeights :: (Crypto.MonadRandom m, Num f) => Integer -> Integer -> m (GateWeights f)
190189
generateGateWeights lConstraints n = do
191-
[wL, wR, wO] <- replicateM 3 ((\i -> insertAt (fromIntegral i) (oneVector n) (replicate (fromIntegral lConstraints - 1) (zeroVector n))) <$> generateMax (fromIntegral lConstraints))
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
192194
pure $ GateWeights wL wR wO
193195
where
194196
zeroVector x = replicate (fromIntegral x) 0

Bulletproofs/ArithmeticCircuit/Prover.hs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ module Bulletproofs.ArithmeticCircuit.Prover where
33

44
import Protolude
55

6-
import Control.Monad.Fail
76
import Crypto.Random.Types (MonadRandom(..))
87
import Crypto.Number.Generate (generateMax)
98
import qualified Crypto.PubKey.ECC.Prim as Crypto
@@ -18,14 +17,17 @@ import Bulletproofs.ArithmeticCircuit.Internal
1817
-- for an arithmetic circuit with a valid witness
1918
generateProof
2019
:: forall f m
21-
. (MonadRandom m, MonadFail m, AsInteger f, Field f, Show f, Eq f)
20+
. (MonadRandom m, AsInteger f, Field f, Show f, Eq f)
2221
=> ArithCircuit f
2322
-> ArithWitness f
2423
-> m (ArithCircuitProof f)
2524
generateProof (padCircuit -> ArithCircuit{..}) ArithWitness{..} = do
2625
let GateWeights{..} = weights
27-
let Assignment{..} = padAssignment assignment
28-
[aiBlinding, aoBlinding, sBlinding] <- replicateM 3 ((fromInteger :: Integer -> f) <$> generateMax q)
26+
Assignment{..} = padAssignment assignment
27+
genBlinding = (fromInteger :: Integer -> f) <$> generateMax q
28+
aiBlinding <- genBlinding
29+
aoBlinding <- genBlinding
30+
sBlinding <- genBlinding
2931
let n = fromIntegral $ length aL
3032
aiCommit = commitBitVector aiBlinding aL aR -- commitment to aL, aR
3133
aoCommit = commitBitVector aoBlinding aO [] -- commitment to aO
@@ -43,7 +45,7 @@ generateProof (padCircuit -> ArithCircuit{..}) ArithWitness{..} = do
4345
zwO = zs `vectorMatrixProduct` wO
4446

4547
-- Polynomials
46-
[lPoly, rPoly] = computePolynomials n aL aR aO sL sR y zwL zwR zwO
48+
(lPoly, rPoly) = computePolynomials n aL aR aO sL sR y zwL zwR zwO
4749
tPoly = multiplyPoly lPoly rPoly
4850

4951
w = (aL `vectorMatrixProductT` wL)
@@ -59,7 +61,7 @@ generateProof (padCircuit -> ArithCircuit{..}) ArithWitness{..} = do
5961
let tCommits = zipWith commit tPoly tBlindings
6062

6163
let x = shamirGs tCommits
62-
evalTCommit = foldl' addP Crypto.PointO (zipWith mulP (powerVector x 7) tCommits)
64+
evalTCommit = sumExps (powerVector x 7) tCommits
6365

6466
let ls = evaluatePolynomial n lPoly x
6567
rs = evaluatePolynomial n rPoly x
@@ -80,8 +82,8 @@ generateProof (padCircuit -> ArithCircuit{..}) ArithWitness{..} = do
8082
commitmentLR = (x `mulP` aiCommit)
8183
`addP` (fSquare x `mulP` aoCommit)
8284
`addP` ((x ^ 3)`mulP` sCommit)
83-
`addP` foldl' addP Crypto.PointO (zipWith mulP gExp gs)
84-
`addP` foldl' addP Crypto.PointO (zipWith mulP hExp hs')
85+
`addP` sumExps gExp gs
86+
`addP` sumExps hExp hs'
8587
`addP` Crypto.pointNegate curve (mu `mulP` h)
8688
`addP` (t `mulP` u)
8789

@@ -103,9 +105,9 @@ generateProof (padCircuit -> ArithCircuit{..}) ArithWitness{..} = do
103105
where
104106
qLen = fromIntegral $ length commitmentWeights
105107
computePolynomials n aL aR aO sL sR y zwL zwR zwO
106-
= [ [l0, l1, l2, l3]
108+
= ( [l0, l1, l2, l3]
107109
, [r0, r1, r2, r3]
108-
]
110+
)
109111
where
110112
l0 = replicate (fromIntegral n) 0
111113
l1 = aL ^+^ (powerVector (recip y) n `hadamardp` zwR)

Bulletproofs/ArithmeticCircuit/Verifier.hs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ verifyProof vCommits proof@ArithCircuitProof{..} (padCircuit -> ArithCircuit{..}
4141

4242
hs' = zipWith mulP (powerVector (recip y) n) hs
4343

44-
wLCommit = foldl' addP Crypto.PointO (zipWith mulP (zs `vectorMatrixProduct` wL) hs')
45-
wRCommit = foldl' addP Crypto.PointO (zipWith mulP wRExp gs)
46-
wOCommit = foldl' addP Crypto.PointO (zipWith mulP (zs `vectorMatrixProduct` wO) hs')
44+
wLCommit = sumExps (zs `vectorMatrixProduct` wL) hs'
45+
wRCommit = sumExps wRExp gs
46+
wOCommit = sumExps (zs `vectorMatrixProduct` wO) hs'
4747
wRExp = powerVector (recip y) n `hadamardp` (zs `vectorMatrixProduct` wL)
4848

4949
uChallenge = shamirU tBlinding mu t
@@ -54,13 +54,13 @@ verifyProof vCommits proof@ArithCircuitProof{..} (padCircuit -> ArithCircuit{..}
5454
lhs = commit t tBlinding
5555
rhs = (gExp `mulP` g)
5656
`addP` tCommitsExpSum
57-
`addP` foldl' addP Crypto.PointO ( zipWith mulP vExp vCommits )
57+
`addP` sumExps vExp vCommits
5858
gExp = fSquare x * (k + cQ)
5959
cQ = zs `dot` cs
6060
vExp = (*) (fSquare x) <$> (zs `vectorMatrixProduct` commitmentWeights)
6161
k = delta n y zwL zwR
6262
xs = 0 : x : 0 : (((^) x) <$> [3..6])
63-
tCommitsExpSum = foldl' addP Crypto.PointO (zipWith mulP xs tCommits)
63+
tCommitsExpSum = sumExps xs tCommits
6464

6565
verifyLRCommitment
6666
= IPP.verifyProof
@@ -74,7 +74,7 @@ verifyProof vCommits proof@ArithCircuitProof{..} (padCircuit -> ArithCircuit{..}
7474
commitmentLR = (x `mulP` aiCommit)
7575
`addP` (fSquare x `mulP` aoCommit)
7676
`addP` ((x ^ 3) `mulP` sCommit)
77-
`addP` foldl' addP Crypto.PointO (zipWith mulP gExp gs)
78-
`addP` foldl' addP Crypto.PointO (zipWith mulP hExp hs')
77+
`addP` sumExps gExp gs
78+
`addP` sumExps hExp hs'
7979
`addP` Crypto.pointNegate curve (mu `mulP` h)
8080
`addP` (t `mulP` u)

Bulletproofs/InnerProductProof/Prover.hs

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ module Bulletproofs.InnerProductProof.Prover (
66

77
import Protolude
88

9+
import Control.Exception (assert)
910
import qualified Data.List as L
1011
import qualified Data.Map as Map
1112

@@ -47,17 +48,13 @@ generateProof'
4748
= case (ls, rs) of
4849
([], []) -> InnerProductProof [] [] 0 0
4950
([l], [r]) -> InnerProductProof (reverse lCommits) (reverse rCommits) l r
50-
_ -> if | not checkLGs -> panic "Error in: l' * Gs' == l * Gs + x^2 * A_L + x^(-2) * A_R"
51-
| not checkRHs -> panic "Error in: r' * Hs' == r * Hs + x^2 * B_L + x^(-2) * B_R"
52-
| not checkLBs -> panic "Error in: l' * r' == l * r + x^2 * (lsLeft * rsRight) + x^-2 * (lsRight * rsLeft)"
53-
| not checkC -> panic "Error in: C == zG + aG + bH'"
54-
| not checkC' -> panic "Error in: C' = C + x^2 L + x^-2 R == z'G + a'G + b'H'"
55-
| otherwise -> generateProof'
56-
InnerProductBase { bGs = gs'', bHs = hs'', bH = bH }
57-
commitmentLR'
58-
InnerProductWitness { ls = ls', rs = rs' }
59-
(lCommit:lCommits)
60-
(rCommit:rCommits)
51+
_ -> assert (checkLGs && checkRHs && checkLBs && checkC && checkC')
52+
$ generateProof'
53+
InnerProductBase { bGs = gs'', bHs = hs'', bH = bH }
54+
commitmentLR'
55+
InnerProductWitness { ls = ls', rs = rs' }
56+
(lCommit:lCommits)
57+
(rCommit:rCommits)
6158
where
6259
n' = fromIntegral $ length ls
6360
nPrime = n' `div` 2
@@ -70,15 +67,15 @@ generateProof'
7067
cL = dot lsLeft rsRight
7168
cR = dot lsRight rsLeft
7269

73-
lCommit = foldl' addP Crypto.PointO (zipWith mulP lsLeft gsRight)
70+
lCommit = sumExps lsLeft gsRight
7471
`addP`
75-
foldl' addP Crypto.PointO (zipWith mulP rsRight hsLeft)
72+
sumExps rsRight hsLeft
7673
`addP`
7774
(cL `mulP` bH)
7875

79-
rCommit = foldl' addP Crypto.PointO (zipWith mulP lsRight gsLeft)
76+
rCommit = sumExps lsRight gsLeft
8077
`addP`
81-
foldl' addP Crypto.PointO (zipWith mulP rsLeft hsRight)
78+
sumExps rsLeft hsRight
8279
`addP`
8380
(cR `mulP` bH)
8481

@@ -88,8 +85,8 @@ generateProof'
8885
xs = replicate nPrime x
8986
xsInv = replicate nPrime xInv
9087

91-
gs'' = zipWith addP (zipWith mulP xsInv gsLeft) (zipWith mulP xs gsRight)
92-
hs'' = zipWith addP (zipWith mulP xs hsLeft) (zipWith mulP xsInv hsRight)
88+
gs'' = zipWith (\(exp0, pt0) (exp1, pt1) -> addTwoMulP exp0 pt0 exp1 pt1) (zip xsInv gsLeft) (zip xs gsRight)
89+
hs'' = zipWith (\(exp0, pt0) (exp1, pt1) -> addTwoMulP exp0 pt0 exp1 pt1) (zip xs hsLeft) (zip xsInv hsRight)
9390

9491
ls' = ((*) x <$> lsLeft) ^+^ ((*) xInv <$> lsRight)
9592
rs' = ((*) xInv <$> rsLeft) ^+^ ((*) x <$> rsRight)
@@ -105,25 +102,25 @@ generateProof'
105102
-- Checks
106103
-----------------------------
107104

108-
aL' = foldl' addP Crypto.PointO (zipWith mulP lsLeft gsRight)
109-
aR' = foldl' addP Crypto.PointO (zipWith mulP lsRight gsLeft)
105+
aL' = sumExps lsLeft gsRight
106+
aR' = sumExps lsRight gsLeft
110107

111-
bL' = foldl' addP Crypto.PointO (zipWith mulP rsLeft hsRight)
112-
bR' = foldl' addP Crypto.PointO (zipWith mulP rsRight hsLeft)
108+
bL' = sumExps rsLeft hsRight
109+
bR' = sumExps rsRight hsLeft
113110

114111
z = dot ls rs
115112
z' = dot ls' rs'
116113

117-
lGs = foldl' addP Crypto.PointO (zipWith mulP ls bGs)
118-
rHs = foldl' addP Crypto.PointO (zipWith mulP rs bHs)
114+
lGs = sumExps ls bGs
115+
rHs = sumExps rs bHs
119116

120-
lGs' = foldl' addP Crypto.PointO (zipWith mulP ls' gs'')
121-
rHs' = foldl' addP Crypto.PointO (zipWith mulP rs' hs'')
117+
lGs' = sumExps ls' gs''
118+
rHs' = sumExps rs' hs''
122119

123120
checkLGs
124121
= lGs'
125122
==
126-
foldl' addP Crypto.PointO (zipWith mulP ls bGs)
123+
sumExps ls bGs
127124
`addP`
128125
(fSquare x `mulP` aL')
129126
`addP`
@@ -132,7 +129,7 @@ generateProof'
132129
checkRHs
133130
= rHs'
134131
==
135-
foldl' addP Crypto.PointO (zipWith mulP rs bHs)
132+
sumExps rs bHs
136133
`addP`
137134
(fSquare x `mulP` bR')
138135
`addP`
@@ -160,5 +157,3 @@ generateProof'
160157
lGs'
161158
`addP`
162159
rHs'
163-
164-

Bulletproofs/InnerProductProof/Verifier.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ verifyProof n productBase@InnerProductBase{..} commitmentLR productProof@InnerPr
3737
`addP`
3838
((l * r) `mulP` bH)
3939

40-
gsCommit = foldl' addP Crypto.PointO (zipWith mulP otherExponents bGs)
41-
hsCommit = foldl' addP Crypto.PointO (zipWith mulP (reverse otherExponents) bHs)
40+
gsCommit = sumExps otherExponents bGs
41+
hsCommit = sumExps (reverse otherExponents) bHs
4242

4343
mkChallenges :: (AsInteger f, Field f) => InnerProductProof f -> Crypto.Point -> ([f], [f], Crypto.Point)
4444
mkChallenges InnerProductProof{ lCommits, rCommits } commitmentLR

Bulletproofs/MultiRangeProof/Prover.hs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ module Bulletproofs.MultiRangeProof.Prover (
77

88
import Protolude
99

10-
import Control.Monad.Fail
1110
import Crypto.Random.Types (MonadRandom(..))
1211
import Crypto.Number.Generate (generateMax)
1312
import qualified Crypto.PubKey.ECC.Generate as Crypto
@@ -23,7 +22,7 @@ import qualified Bulletproofs.InnerProductProof as IPP
2322

2423
-- | Prove that a list of values lies in a specific range
2524
generateProof
26-
:: (AsInteger f, Eq f, Field f, Show f, MonadRandom m, MonadFail m)
25+
:: (AsInteger f, Eq f, Field f, Show f, MonadRandom m)
2726
=> Integer -- ^ Upper bound of the range we want to prove
2827
-> [(Integer, Integer)]
2928
-- ^ Values we want to prove in range and their blinding factors
@@ -54,7 +53,7 @@ generateProof upperBound vsAndvBlindings = do
5453
-- | Generate range proof from valid inputs
5554
generateProofUnsafe
5655
:: forall f m
57-
. (AsInteger f, Eq f, Field f, Show f, MonadRandom m, MonadFail m)
56+
. (AsInteger f, Eq f, Field f, Show f, MonadRandom m)
5857
=> Integer -- ^ Upper bound of the range we want to prove
5958
-> [(Integer, Integer)]
6059
-- ^ Values we want to prove in range and their blinding factors
@@ -75,8 +74,10 @@ generateProofUnsafe upperBound vsAndvBlindings = do
7574

7675
(sL, sR) <- chooseBlindingVectors nm
7776

78-
[aBlinding, sBlinding]
79-
<- replicateM 2 ((fromInteger :: Integer -> f) <$> generateMax q)
77+
let genBlinding = (fromInteger :: Integer -> f) <$> generateMax q
78+
79+
aBlinding <- genBlinding
80+
sBlinding <- genBlinding
8081

8182
(aCommit, sCommit) <- commitBitVectors aBlinding sBlinding aL aR sL sR
8283

@@ -87,9 +88,8 @@ generateProofUnsafe upperBound vsAndvBlindings = do
8788
let lrPoly@LRPolys{..} = computeLRPolys n m aL aR sL sR y z
8889
tPoly@TPoly{..} = computeTPoly lrPoly
8990

90-
[t1Blinding, t2Blinding]
91-
<- replicateM 2 ((fromInteger :: Integer -> f) <$> generateMax q)
92-
91+
t1Blinding <- genBlinding
92+
t2Blinding <- genBlinding
9393

9494
let t1Commit = commit t1 t1Blinding
9595
t2Commit = commit t2 t2Blinding

Bulletproofs/MultiRangeProof/Verifier.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ verifyTPoly n vCommits proof@RangeProof{..} x y z
6363
m = fromIntegral $ length vCommits
6464
lhs = commit t tBlinding
6565
rhs =
66-
foldl' addP Crypto.PointO ( zipWith mulP ((*) (fSquare z) <$> powerVector z m) vCommits )
66+
sumExps ((*) (fSquare z) <$> powerVector z m) vCommits
6767
`addP`
6868
(delta n m y z `mulP` g)
6969
`addP`

Bulletproofs/RangeProof/Internal.hs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{-# LANGUAGE DeriveGeneric, DeriveAnyClass #-}
12
module Bulletproofs.RangeProof.Internal where
23

34
import Protolude
@@ -37,14 +38,14 @@ data RangeProof f
3738
, productProof :: InnerProductProof f
3839
-- ^ Inner product argument to prove that a commitment P
3940
-- has vectors l, r ∈ Z^n for which P = l · G + r · H + ( l, r ) · U
40-
} deriving (Show, Eq)
41+
} deriving (Show, Eq, Generic, NFData)
4142

4243
data RangeProofError
4344
= UpperBoundTooLarge Integer -- ^ The upper bound of the range is too large
4445
| ValueNotInRange Integer -- ^ Value is not within the range required
4546
| ValuesNotInRange [Integer] -- ^ Values are not within the range required
4647
| NNotPowerOf2 Integer -- ^ Dimension n is required to be a power of 2
47-
deriving (Show, Eq)
48+
deriving (Show, Eq, Generic, NFData)
4849

4950
-----------------------------
5051
-- Polynomials
@@ -136,10 +137,10 @@ commitBitVectors
136137
-> [f]
137138
-> m (Crypto.Point, Crypto.Point)
138139
commitBitVectors aBlinding sBlinding aL aR sL sR = do
139-
let aLG = foldl' addP Crypto.PointO ( zipWith mulP aL gs )
140-
aRH = foldl' addP Crypto.PointO ( zipWith mulP aR hs )
141-
sLG = foldl' addP Crypto.PointO ( zipWith mulP sL gs )
142-
sRH = foldl' addP Crypto.PointO ( zipWith mulP sR hs )
140+
let aLG = sumExps aL gs
141+
aRH = sumExps aR hs
142+
sLG = sumExps sL gs
143+
sRH = sumExps sR hs
143144
aBlindingH = mulP aBlinding h
144145
sBlindingH = mulP sBlinding h
145146

@@ -190,10 +191,10 @@ computeLRCommitment n m aCommit sCommit t tBlinding mu x y z hs'
190191
`addP`
191192
Crypto.pointNegate curve (z `mulP` gsSum) -- (- zG)
192193
`addP`
193-
foldl' addP Crypto.PointO (zipWith mulP hExp hs') -- (hExp Hs')
194+
sumExps hExp hs' -- (hExp Hs')
194195
`addP`
195196
foldl'
196-
(\acc j -> acc `addP` foldl' addP Crypto.PointO (zipWith mulP (hExp' j) (sliceHs' j)))
197+
(\acc j -> acc `addP` sumExps (hExp' j) (sliceHs' j))
197198
Crypto.PointO
198199
[1..m]
199200
`addP`

0 commit comments

Comments
 (0)