bulletproofs 0.4.0 → 1.0.0
raw patch · 20 files changed
+488/−466 lines, 20 filesdep +galois-fielddep +pairingdep ~basedep ~protolude
Dependencies added: galois-field, pairing
Dependency ranges changed: base, protolude
Files
- Bulletproofs/ArithmeticCircuit/Internal.hs +78/−32
- Bulletproofs/ArithmeticCircuit/Prover.hs +11/−10
- Bulletproofs/ArithmeticCircuit/Verifier.hs +7/−6
- Bulletproofs/Curve.hs +28/−7
- Bulletproofs/Fq.hs +47/−87
- Bulletproofs/InnerProductProof/Prover.hs +14/−13
- Bulletproofs/InnerProductProof/Verifier.hs +12/−7
- Bulletproofs/MultiRangeProof/Prover.hs +22/−24
- Bulletproofs/MultiRangeProof/Verifier.hs +15/−14
- Bulletproofs/RangeProof/Internal.hs +33/−32
- Bulletproofs/RangeProof/Prover.hs +7/−7
- Bulletproofs/RangeProof/Verifier.hs +13/−12
- Bulletproofs/Utils.hs +12/−28
- ChangeLog.md +21/−13
- LICENSE +1/−1
- README.md +5/−5
- bulletproofs.cabal +10/−3
- tests/TestArithCircuitProtocol.hs +122/−132
- tests/TestField.hs +0/−4
- tests/TestProtocol.hs +30/−29
Bulletproofs/ArithmeticCircuit/Internal.hs view
@@ -7,6 +7,8 @@ import Data.List (head) import qualified Data.List as List import qualified Data.Map as Map+import Test.QuickCheck+import PrimeField (PrimeField(..), toInt) import System.Random.Shuffle (shuffleM) import qualified Crypto.Random.Types as Crypto (MonadRandom(..))@@ -103,10 +105,10 @@ aRNew = padToNearestPowerOfTwo aR aONew = padToNearestPowerOfTwo aO -delta :: (Eq f, Field f) => Integer -> f -> [f] -> [f] -> f+delta :: (KnownNat p) => Integer -> PrimeField p -> [PrimeField p] -> [PrimeField p] -> PrimeField p delta n y zwL zwR= (powerVector (recip y) n `hadamardp` zwR) `dot` zwL -commitBitVector :: (AsInteger f) => f -> [f] -> [f] -> Crypto.Point+commitBitVector :: (KnownNat p) => PrimeField p -> [PrimeField p] -> [PrimeField p] -> Crypto.Point commitBitVector vBlinding vL vR = vLG `addP` vRH `addP` vBlindingH where vBlindingH = vBlinding `mulP` h@@ -115,13 +117,13 @@ shamirGxGxG :: (Show f, Num f) => Crypto.Point -> Crypto.Point -> Crypto.Point -> f shamirGxGxG p1 p2 p3- = fromInteger $ oracle $ show q <> pointToBS p1 <> pointToBS p2 <> pointToBS p3+ = fromInteger $ oracle $ show _q <> pointToBS p1 <> pointToBS p2 <> pointToBS p3 shamirGs :: (Show f, Num f) => [Crypto.Point] -> f-shamirGs ps = fromInteger $ oracle $ show q <> foldMap pointToBS ps+shamirGs ps = fromInteger $ oracle $ show _q <> foldMap pointToBS ps shamirZ :: (Show f, Num f) => f -> f-shamirZ z = fromInteger $ oracle $ show q <> show z+shamirZ z = fromInteger $ oracle $ show _q <> show z --------------------------------------------- -- Polynomials@@ -180,30 +182,7 @@ genZeroMatrix :: (Num f) => Integer -> Integer -> [[f]] genZeroMatrix (fromIntegral -> n) (fromIntegral -> m) = replicate n (replicate m 0) -generateWv :: (Num f, MonadRandom m) => Integer -> Integer -> m [[f]]-generateWv lConstraints m- | lConstraints < m = panic "Number of constraints must be bigger than m"- | otherwise = shuffleM (genIdenMatrix m ++ genZeroMatrix (lConstraints - m) m)--generateGateWeights :: (Crypto.MonadRandom m, Num f) => Integer -> Integer -> m (GateWeights f)-generateGateWeights lConstraints n = do- let genVec = ((\i -> insertAt (fromIntegral i) (oneVector n) (replicate (fromIntegral lConstraints - 1) (zeroVector n))) <$> generateMax (fromIntegral lConstraints))- wL <- genVec- wR <- genVec- wO <- genVec- pure $ GateWeights wL wR wO- where- zeroVector x = replicate (fromIntegral x) 0- oneVector x = replicate (fromIntegral x) 1--generateRandomAssignment :: forall f m . (Num f, AsInteger f, Crypto.MonadRandom m) => Integer -> m (Assignment f)-generateRandomAssignment n = do- aL <- replicateM (fromIntegral n) ((fromInteger :: Integer -> f) <$> generateMax (2^n))- aR <- replicateM (fromIntegral n) ((fromInteger :: Integer -> f) <$> generateMax (2^n))- let aO = aL `hadamardp` aR- pure $ Assignment aL aR aO--computeInputValues :: (Field f, Eq f) => GateWeights f -> [[f]] -> Assignment f -> [f] -> [f]+computeInputValues :: (KnownNat p) => GateWeights (PrimeField p) -> [[PrimeField p]] -> Assignment (PrimeField p) -> [PrimeField p] -> [PrimeField p] computeInputValues GateWeights{..} wV Assignment{..} cs = solveLinearSystem $ zipWith (\row s -> reverse $ s : row) wV solutions where@@ -212,7 +191,7 @@ ^+^ vectorMatrixProductT aO wO ^-^ cs -gaussianReduce :: (Field f, Eq f) => [[f]] -> [[f]]+gaussianReduce :: (KnownNat p) => [[PrimeField p]] -> [[PrimeField p]] gaussianReduce matrix = fixlastrow $ foldl reduceRow matrix [0..length matrix-1] where -- Swaps element at position a with element at position b.@@ -247,7 +226,7 @@ nz = List.last (List.init row) -- Solve a matrix (must already be in REF form) by back substitution.-substituteMatrix :: (Field f, Eq f) => [[f]] -> [f]+substituteMatrix :: (KnownNat p) => [[PrimeField p]] -> [PrimeField p] substituteMatrix matrix = foldr next [List.last (List.last matrix)] (List.init matrix) where next row found = let@@ -255,5 +234,72 @@ solution = List.last row - sum (zipWith (*) found subpart) in solution : found -solveLinearSystem :: (Field f, Eq f) => [[f]] -> [f]+solveLinearSystem :: (KnownNat p) => [[PrimeField p]] -> [PrimeField p] solveLinearSystem = reverse . substituteMatrix . gaussianReduce++-------------------------+-- Arbitrary instances --+-------------------------++instance (KnownNat p) => Arbitrary (ArithCircuit (PrimeField p)) where+ arbitrary = do+ n <- choose (1, 100)+ m <- choose (1, n)+ arithCircuitGen n m++arithCircuitGen :: forall p. (KnownNat p) => Integer -> Integer -> Gen (ArithCircuit (PrimeField p))+arithCircuitGen n m = do+ -- TODO: Can lConstraints be a different value?+ let lConstraints = m++ cs <- vectorOf (fromIntegral m) arbitrary++ weights@GateWeights{..} <- gateWeightsGen lConstraints n+ let gateWeights = GateWeights wL wR wO++ commitmentWeights <- wvGen lConstraints m+ pure $ ArithCircuit gateWeights commitmentWeights cs+ where+ gateWeightsGen :: Integer -> Integer -> Gen (GateWeights (PrimeField p))+ gateWeightsGen lConstraints n = do+ let genVec = ((\i -> insertAt i (oneVector n) (replicate (fromIntegral lConstraints - 1) (zeroVector n))) <$> choose (0, fromIntegral lConstraints))+ wL <- genVec+ wR <- genVec+ wO <- genVec+ pure $ GateWeights wL wR wO++ wvGen :: Integer -> Integer -> Gen [[PrimeField p]]+ wvGen lConstraints m+ | lConstraints < m = panic "Number of constraints must be bigger than m"+ | otherwise = shuffle (genIdenMatrix m ++ genZeroMatrix (lConstraints - m) m)+ zeroVector x = replicate (fromIntegral x) 0+ oneVector x = replicate (fromIntegral x) 1+++instance (KnownNat p) => Arbitrary (Assignment (PrimeField p)) where+ arbitrary = do+ n <- (arbitrary :: Gen Integer)+ arithAssignmentGen n++arithAssignmentGen :: (KnownNat p) => Integer -> Gen (Assignment (PrimeField p))+arithAssignmentGen n = do+ aL <- vectorOf (fromIntegral n) (fromInteger <$> choose (0, 2^n))+ aR <- vectorOf (fromIntegral n) (fromInteger <$> choose (0, 2^n))+ let aO = aL `hadamardp` aR+ pure $ Assignment aL aR aO++instance (KnownNat p) => Arbitrary (ArithWitness (PrimeField p)) where+ arbitrary = do+ n <- choose (1, 100)+ m <- choose (1, n)+ arithCircuit <- arithCircuitGen n m+ assignment <- arithAssignmentGen n+ arithWitnessGen assignment arithCircuit m++arithWitnessGen :: (KnownNat p) => Assignment (PrimeField p) -> ArithCircuit (PrimeField p) -> Integer -> Gen (ArithWitness (PrimeField p))+arithWitnessGen assignment arith@ArithCircuit{..} m = do+ commitBlinders <- vectorOf (fromIntegral m) arbitrary+ let vs = computeInputValues weights commitmentWeights assignment cs+ commitments = zipWith commit vs commitBlinders+ pure $ ArithWitness assignment commitments commitBlinders+
Bulletproofs/ArithmeticCircuit/Prover.hs view
@@ -7,6 +7,7 @@ import Crypto.Number.Generate (generateMax) import qualified Crypto.PubKey.ECC.Prim as Crypto import qualified Crypto.PubKey.ECC.Types as Crypto+import PrimeField (PrimeField(..), toInt) import Bulletproofs.Curve import Bulletproofs.Utils hiding (shamirZ)@@ -16,15 +17,15 @@ -- | Generate a zero-knowledge proof of computation -- for an arithmetic circuit with a valid witness generateProof- :: forall f m- . (MonadRandom m, AsInteger f, Field f, Show f, Eq f)- => ArithCircuit f- -> ArithWitness f- -> m (ArithCircuitProof f)+ :: forall p m+ . (MonadRandom m, KnownNat p)+ => ArithCircuit (PrimeField p)+ -> ArithWitness (PrimeField p)+ -> m (ArithCircuitProof (PrimeField p)) generateProof (padCircuit -> ArithCircuit{..}) ArithWitness{..} = do let GateWeights{..} = weights Assignment{..} = padAssignment assignment- genBlinding = (fromInteger :: Integer -> f) <$> generateMax q+ genBlinding = (fromInteger :: Integer -> PrimeField p) <$> generateMax _q aiBlinding <- genBlinding aoBlinding <- genBlinding sBlinding <- genBlinding@@ -57,7 +58,7 @@ + (zs `dot` w) + delta n y zwL zwR - tBlindings <- insertAt 2 0 . (:) 0 <$> replicateM 5 ((fromInteger :: Integer -> f) <$> generateMax q)+ tBlindings <- insertAt 2 0 . (:) 0 <$> replicateM 5 ((fromInteger :: Integer -> PrimeField p) <$> generateMax _q) let tCommits = zipWith commit tPoly tBlindings let x = shamirGs tCommits@@ -70,9 +71,9 @@ commitTimesWeigths = commitBlinders `vectorMatrixProductT` commitmentWeights zGamma = zs `dot` commitTimesWeigths tBlinding = sum (zipWith (\i blinding -> blinding * (x ^ i)) [0..] tBlindings)- + (fSquare x * zGamma)+ + ((x ^ 2) * zGamma) - mu = aiBlinding * x + aoBlinding * fSquare x + sBlinding * (x ^ 3)+ mu = aiBlinding * x + aoBlinding * (x ^ 2) + sBlinding * (x ^ 3) let uChallenge = shamirU tBlinding mu t u = uChallenge `mulP` g@@ -80,7 +81,7 @@ gExp = (*) x <$> (powerVector (recip y) n `hadamardp` zwR) hExp = (((*) x <$> zwL) ^+^ zwO) ^-^ ys commitmentLR = (x `mulP` aiCommit)- `addP` (fSquare x `mulP` aoCommit)+ `addP` ((x ^ 2) `mulP` aoCommit) `addP` ((x ^ 3)`mulP` sCommit) `addP` sumExps gExp gs `addP` sumExps hExp hs'
Bulletproofs/ArithmeticCircuit/Verifier.hs view
@@ -6,6 +6,7 @@ import qualified Crypto.PubKey.ECC.Prim as Crypto import qualified Crypto.PubKey.ECC.Types as Crypto+import PrimeField (PrimeField(..), toInt) import Bulletproofs.Curve import Bulletproofs.Utils hiding (shamirZ)@@ -17,10 +18,10 @@ -- | Verify that a zero-knowledge proof holds -- for an arithmetic circuit given committed input values verifyProof- :: (AsInteger f, Field f, Eq f, Show f)+ :: (KnownNat p) => [Crypto.Point]- -> ArithCircuitProof f- -> ArithCircuit f+ -> ArithCircuitProof (PrimeField p)+ -> ArithCircuit (PrimeField p) -> Bool verifyProof vCommits proof@ArithCircuitProof{..} (padCircuit -> ArithCircuit{..}) = verifyLRCommitment && verifyTPoly@@ -55,9 +56,9 @@ rhs = (gExp `mulP` g) `addP` tCommitsExpSum `addP` sumExps vExp vCommits- gExp = fSquare x * (k + cQ)+ gExp = (x ^ 2) * (k + cQ) cQ = zs `dot` cs- vExp = (*) (fSquare x) <$> (zs `vectorMatrixProduct` commitmentWeights)+ vExp = (*) (x ^ 2) <$> (zs `vectorMatrixProduct` commitmentWeights) k = delta n y zwL zwR xs = 0 : x : 0 : (((^) x) <$> [3..6]) tCommitsExpSum = sumExps xs tCommits@@ -72,7 +73,7 @@ gExp = (*) x <$> (powerVector (recip y) n `hadamardp` zwR) hExp = (((*) x <$> zwL) ^+^ zwO) ^-^ ys commitmentLR = (x `mulP` aiCommit)- `addP` (fSquare x `mulP` aoCommit)+ `addP` ((x ^ 2) `mulP` aoCommit) `addP` ((x ^ 3) `mulP` sCommit) `addP` sumExps gExp gs `addP` sumExps hExp hs'
Bulletproofs/Curve.hs view
@@ -1,5 +1,7 @@ module Bulletproofs.Curve (- q,+ _q,+ _a,+ _b, g, h, gs,@@ -23,6 +25,19 @@ import Numeric import qualified Data.List as L +-- Implementation using the elliptic curve secp256k12+-- which has 128 bit security.+-- Parameters as in Cryptonite:+-- SEC_p256k1 = CurveFP $ CurvePrime+-- 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f+-- (CurveCommon+-- { ecc_a = 0x0000000000000000000000000000000000000000000000000000000000000000+-- , ecc_b = 0x0000000000000000000000000000000000000000000000000000000000000007+-- , ecc_g = Point 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798+-- 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8+-- , ecc_n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141+-- , ecc_h = 1+-- }) curveName :: Crypto.CurveName curveName = Crypto.SEC_p256k1 @@ -30,9 +45,15 @@ curve = Crypto.getCurveByName curveName -- | Order of the curve-q :: Integer-q = Crypto.ecc_n . Crypto.common_curve $ curve+_q :: Integer+_q = Crypto.ecc_n . Crypto.common_curve $ curve +_b :: Integer+_b = Crypto.ecc_b . Crypto.common_curve $ curve++_a :: Integer+_a = Crypto.ecc_a . Crypto.common_curve $ curve+ -- | Generator of the curve g :: Crypto.Point g = Crypto.ecc_g $ Crypto.common_curve curve@@ -64,8 +85,8 @@ pointToBS (Crypto.Point x y) = show x <> show y -- | Characteristic of the underlying finite field of the elliptic curve-p :: Integer-p = Crypto.ecc_p cp+_p :: Integer+_p = Crypto.ecc_p cp where cp = case curve of Crypto.CurveFP c -> c@@ -82,6 +103,6 @@ then Crypto.Point x y else generateH basePoint (toS $ '1':extra) where- x = oracle (pointToBS basePoint <> toS extra) `mod` p- yM = sqrtModP (x ^ 3 + 7) p+ x = oracle (pointToBS basePoint <> toS extra) `mod` _p+ yM = sqrtModP (x ^ 3 + 7) _p
Bulletproofs/Fq.hs view
@@ -1,108 +1,68 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE TypeFamilies #-}+-- | Prime field with characteristic _q, over which the elliptic curve+-- is defined and the other finite field extensions.+--+-- * Fq+-- * Fq2 := Fq[u]/u^2 + 1+-- * Fq6 := Fq2[v]/v^3 - (9 + u)+-- * Fq12 := Fq6[w]/w^2 - v -module Bulletproofs.Fq where+module Bulletproofs.Fq+ ( Fq+ , PF+ , fqRandom+ , fqPow+ , fqSqrt+ , toInt+ ) where import Protolude import Crypto.Random (MonadRandom) import Crypto.Number.Generate (generateMax)-+import Math.NumberTheory.Moduli.Class (powMod)+import PrimeField (PrimeField(..), toInt)+import Pairing.Modular import Bulletproofs.Curve + ------------------------------------------------------------------------------- -- Types ------------------------------------------------------------------------------- --- | Prime field with characteristic @_q@-newtype Fq = Fq Integer -- ^ Use @new@ instead of this constructor- deriving (Show, Eq, Bits, Ord, Generic, NFData)--instance Num Fq where- (+) = fqAdd- (*) = fqMul- abs = panic "There is no absolute value in a finite field"- signum = panic "This function doesn't make sense in a finite field"- negate = fqNeg- fromInteger = new--instance Fractional Fq where- (/) = fqDiv- fromRational (a :% b) = Fq a / Fq b---- | Turn an integer into an @Fq@ number, should be used instead of--- the @Fq@ constructor.-new :: Integer -> Fq-new a = Fq (a `mod` q)--{-# INLINE norm #-}-norm :: Fq -> Fq-norm (Fq a) = Fq (a `mod` q)--{-# INLINE fqAdd #-}-fqAdd :: Fq -> Fq -> Fq-fqAdd (Fq a) (Fq b) = norm (Fq (a+b))--{-# INLINE fqMul #-}-fqMul :: Fq -> Fq -> Fq-fqMul (Fq a) (Fq b) = norm (Fq (a*b))--{-# INLINE fqNeg #-}-fqNeg :: Fq -> Fq-fqNeg (Fq a) = Fq ((-a) `mod` q)--{-# INLINE fqDiv #-}-fqDiv :: Fq -> Fq -> Fq-fqDiv a b = fqMul a (inv b)--{-# INLINE fqInv #-}--- | Multiplicative inverse-fqInv :: Fq -> Fq-fqInv x = 1 / x--{-# INLINE fqZero #-}--- | Additive identity-fqZero :: Fq-fqZero = Fq 0--{-# INLINE fqOne #-}--- | Multiplicative identity-fqOne :: Fq-fqOne = Fq 1+-- | Prime field @Fq@ with characteristic @_q@+type Fq = PrimeField 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141 -fqSquare :: Fq -> Fq-fqSquare x = fqMul x x+-- | Type family to extract the characteristic of the prime field+type family PF a where+ PF (PrimeField k) = k -fqCube :: Fq -> Fq-fqCube x = fqMul x (fqMul x x)+-------------------------------------------------------------------------------+-- Instances+------------------------------------------------------------------------------- -fqPower :: Fq -> Integer -> Fq-fqPower base exp = fqPower' base exp (Fq 1)+instance Ord Fq where+ compare = on compare toInt -fqPower' :: Fq -> Integer -> Fq -> Fq-fqPower' base 0 acc = acc-fqPower' base exp acc = fqPower' base (exp - 1) (fqMul base acc)+-------------------------------------------------------------------------------+-- Random+------------------------------------------------------------------------------- -inv :: Fq -> Fq-inv (Fq a) = Fq $ euclidean a q `mod` q+fqRandom :: MonadRandom m => m Fq+fqRandom = fromInteger <$> generateMax _q -asInteger :: Fq -> Integer-asInteger (Fq n) = n+-------------------------------------------------------------------------------+-- Y for X+------------------------------------------------------------------------------- --- | Euclidean algorithm to compute inverse in an integral domain @a@-euclidean :: (Integral a) => a -> a -> a-euclidean a b = fst (inv' a b)+fqPow :: Integral e => Fq -> e -> Fq+fqPow a b = fromInteger (withQ (modUnOp (toInt a) (flip powMod b)))+{-# INLINE fqPow #-} -{-# INLINEABLE inv' #-}-{-# SPECIALISE inv' :: Integer -> Integer -> (Integer, Integer) #-}-inv' :: (Integral a) => a -> a -> (a, a)-inv' a b =- case b of- 1 -> (0, 1)- _ -> let (e, f) = inv' b d- in (f, e - c*f)- where c = a `div` b- d = a `mod` b+fqSqrt :: Bool -> Fq -> Maybe Fq+fqSqrt largestY a = do+ (y1, y2) <- withQM (modUnOpMTup (toInt a) bothSqrtOf)+ return (fromInteger ((if largestY then max else min) y1 y2)) -random :: MonadRandom m => m Fq-random = Fq <$> generateMax q+fqYforX :: Fq -> Bool -> Maybe Fq+fqYforX x largestY = fqSqrt largestY (x `fqPow` 3 + fromInteger _b)
Bulletproofs/InnerProductProof/Prover.hs view
@@ -11,6 +11,7 @@ import qualified Data.Map as Map import qualified Crypto.PubKey.ECC.Types as Crypto+import PrimeField (PrimeField(..), toInt) import Bulletproofs.Curve import Bulletproofs.Utils@@ -20,25 +21,25 @@ -- | Generate proof that a witness l, r satisfies the inner product relation -- on public input (Gs, Hs, h) generateProof- :: (AsInteger f, Eq f, Field f)+ :: KnownNat p => InnerProductBase -- ^ Generators Gs, Hs, h -> Crypto.Point -- ^ Commitment P = A + xS − zG + (z*y^n + z^2 * 2^n) * hs' of vectors l and r -- whose inner product is t- -> InnerProductWitness f+ -> InnerProductWitness (PrimeField p) -- ^ Vectors l and r that hide bit vectors aL and aR, respectively- -> InnerProductProof f+ -> InnerProductProof (PrimeField p) generateProof productBase commitmentLR witness = generateProof' productBase commitmentLR witness [] [] generateProof'- :: (AsInteger f, Eq f, Field f)+ :: KnownNat p => InnerProductBase -> Crypto.Point- -> InnerProductWitness f+ -> InnerProductWitness (PrimeField p) -> [Crypto.Point] -> [Crypto.Point]- -> InnerProductProof f+ -> InnerProductProof (PrimeField p) generateProof' InnerProductBase{ bGs, bHs, bH } commitmentLR@@ -92,9 +93,9 @@ rs' = ((*) xInv <$> rsLeft) ^+^ ((*) x <$> rsRight) commitmentLR'- = (fSquare x `mulP` lCommit)+ = ((x ^ 2) `mulP` lCommit) `addP`- (fSquare xInv `mulP` rCommit)+ ((xInv ^ 2) `mulP` rCommit) `addP` commitmentLR @@ -122,23 +123,23 @@ == sumExps ls bGs `addP`- (fSquare x `mulP` aL')+ ((x ^ 2) `mulP` aL') `addP`- (fSquare xInv `mulP` aR')+ ((xInv ^ 2) `mulP` aR') checkRHs = rHs' == sumExps rs bHs `addP`- (fSquare x `mulP` bR')+ ((x ^ 2) `mulP` bR') `addP`- (fSquare xInv `mulP` bL')+ ((xInv ^ 2) `mulP` bL') checkLBs = dot ls' rs' ==- dot ls rs + fSquare x * cL + fSquare xInv * cR+ dot ls rs + (x ^ 2) * cL + (xInv ^ 2) * cR checkC = commitmentLR
Bulletproofs/InnerProductProof/Verifier.hs view
@@ -10,6 +10,7 @@ import qualified Data.Map as Map import qualified Crypto.PubKey.ECC.Types as Crypto+import PrimeField (PrimeField(..), toInt) import Bulletproofs.Curve import Bulletproofs.Utils@@ -18,11 +19,11 @@ -- | Optimized non-interactive verifier using multi-exponentiation and batch verification verifyProof- :: (AsInteger f, Field f)+ :: KnownNat p => Integer -- ^ Range upper bound -> InnerProductBase -- ^ Generators Gs, Hs, h -> Crypto.Point -- ^ Commitment P- -> InnerProductProof f+ -> InnerProductProof (PrimeField p) -- ^ Proof that a secret committed value lies in a certain interval -> Bool verifyProof n productBase@InnerProductBase{..} commitmentLR productProof@InnerProductProof{ l, r }@@ -40,19 +41,23 @@ gsCommit = sumExps otherExponents bGs hsCommit = sumExps (reverse otherExponents) bHs -mkChallenges :: (AsInteger f, Field f) => InnerProductProof f -> Crypto.Point -> ([f], [f], Crypto.Point)+mkChallenges+ :: KnownNat p+ => InnerProductProof (PrimeField p)+ -> Crypto.Point+ -> ([PrimeField p], [PrimeField p], Crypto.Point) mkChallenges InnerProductProof{ lCommits, rCommits } commitmentLR = foldl' (\(xs, xsInv, accC) (li, ri) -> let x = shamirX' accC li ri xInv = recip x- c = (fSquare x `mulP` li) `addP` (fSquare xInv `mulP` ri) `addP` accC+ c = ((x ^ 2) `mulP` li) `addP` ((xInv ^ 2) `mulP` ri) `addP` accC in (x:xs, xInv:xsInv, c) ) ([], [], commitmentLR) (zip lCommits rCommits) -mkOtherExponents :: forall f . (AsInteger f, Field f) => Integer -> [f] -> [f]+mkOtherExponents :: forall p . KnownNat p => Integer -> [PrimeField p] -> [PrimeField p] mkOtherExponents n challenges = Map.elems $ foldl' f@@ -62,14 +67,14 @@ n' = n `div` 2 f acc i = foldl' (f' i) acc [0..logBase2 n-1] - f' :: Integer -> Map.Map Integer f -> Integer -> Map.Map Integer f+ f' :: Integer -> Map.Map Integer (PrimeField p) -> Integer -> Map.Map Integer (PrimeField p) f' i acc' j = let i1 = (2^j) + i in if | i1 >= n -> acc' | Map.member i1 acc' -> acc' | otherwise -> Map.insert i1- (acc' Map.! i * fSquare (challenges L.!! fromIntegral j))+ (acc' Map.! i * ((challenges L.!! fromIntegral j) ^ 2)) acc'
Bulletproofs/MultiRangeProof/Prover.hs view
@@ -12,6 +12,7 @@ import qualified Crypto.PubKey.ECC.Generate as Crypto import qualified Crypto.PubKey.ECC.Prim as Crypto import qualified Crypto.PubKey.ECC.Types as Crypto+import PrimeField (PrimeField(..), toInt) import Bulletproofs.Curve import Bulletproofs.Utils@@ -22,13 +23,13 @@ -- | Prove that a list of values lies in a specific range generateProof- :: (AsInteger f, Eq f, Field f, Show f, MonadRandom m)+ :: (KnownNat p, MonadRandom m) => Integer -- ^ Upper bound of the range we want to prove- -> [(Integer, Integer)]+ -> [(PrimeField p, PrimeField p)] -- ^ Values we want to prove in range and their blinding factors- -> ExceptT RangeProofError m (RangeProof f)+ -> ExceptT (RangeProofError (PrimeField p)) m (RangeProof (PrimeField p)) generateProof upperBound vsAndvBlindings = do- unless (upperBound < q) $ throwE $ UpperBoundTooLarge upperBound+ unless (upperBound < _q) $ throwE $ UpperBoundTooLarge upperBound case doubleLogM of Nothing -> throwE $ NNotPowerOf2 upperBound@@ -52,29 +53,26 @@ -- | Generate range proof from valid inputs generateProofUnsafe- :: forall f m- . (AsInteger f, Eq f, Field f, Show f, MonadRandom m)+ :: forall p m+ . (KnownNat p, MonadRandom m) => Integer -- ^ Upper bound of the range we want to prove- -> [(Integer, Integer)]+ -> [(PrimeField p, PrimeField p)] -- ^ Values we want to prove in range and their blinding factors- -> m (RangeProof f)+ -> m (RangeProof (PrimeField p)) generateProofUnsafe upperBound vsAndvBlindings = do let n = logBase2 upperBound m = fromIntegral $ length vsAndvBlindings nm = n * m - vsF :: [f]- vsF = (fromInteger . fst) <$> vsAndvBlindings-- vBlindingsF :: [f]- vBlindingsF = (fromInteger . snd) <$> vsAndvBlindings+ vsF = fst <$> vsAndvBlindings+ vBlindingsF = snd <$> vsAndvBlindings let aL = reversedEncodeBitMulti n vsF aR = complementaryVector aL (sL, sR) <- chooseBlindingVectors nm - let genBlinding = (fromInteger :: Integer -> f) <$> generateMax q+ let genBlinding = (fromInteger :: Integer -> (PrimeField p)) <$> generateMax _q aBlinding <- genBlinding sBlinding <- genBlinding@@ -99,7 +97,7 @@ let ls = l0 ^+^ ((*) x <$> l1) rs = r0 ^+^ ((*) x <$> r1)- t = t0 + (t1 * x) + (t2 * fSquare x)+ t = t0 + (t1 * x) + (t2 * (x ^ 2)) unless (t == dot ls rs) $ panic "Error on: t = dot l r"@@ -108,7 +106,7 @@ panic "Error on: t1 = dot l1 r0 + dot l0 r1" let tBlinding = sum (zipWith (\vBlindingF j -> (z ^ (j + 1)) * vBlindingF) vBlindingsF [1..m])- + (t2Blinding * fSquare x)+ + (t2Blinding * (x ^ 2)) + (t1Blinding * x) mu = aBlinding + (sBlinding * x) @@ -141,16 +139,16 @@ -- l(x) = (a L − z1 n ) + s L x -- r(x) = y^n ◦ (aR + z * 1^n + sR * x) + z^2 * 2^n computeLRPolys- :: (Eq f, Num f)+ :: (KnownNat p) => Integer -> Integer- -> [f]- -> [f]- -> [f]- -> [f]- -> f- -> f- -> LRPolys f+ -> [PrimeField p]+ -> [PrimeField p]+ -> [PrimeField p]+ -> [PrimeField p]+ -> PrimeField p+ -> PrimeField p+ -> LRPolys (PrimeField p) computeLRPolys n m aL aR sL sR y z = LRPolys { l0 = aL ^-^ ((*) z <$> powerVector 1 nm)
Bulletproofs/MultiRangeProof/Verifier.hs view
@@ -12,6 +12,7 @@ import qualified Crypto.PubKey.ECC.Generate as Crypto import qualified Crypto.PubKey.ECC.Prim as Crypto import qualified Crypto.PubKey.ECC.Types as Crypto+import PrimeField (PrimeField(..), toInt) import Bulletproofs.RangeProof.Internal import Bulletproofs.Curve@@ -22,10 +23,10 @@ -- | Verify that a commitment was computed from a value in a given range verifyProof- :: (AsInteger f, Eq f, Field f, Show f)+ :: KnownNat p => Integer -- ^ Range upper bound -> [Crypto.Point] -- ^ Commitments of in-range values- -> RangeProof f+ -> RangeProof (PrimeField p) -- ^ Proof that a secret committed value lies in a certain interval -> Bool verifyProof upperBound vCommits proof@RangeProof{..}@@ -48,14 +49,14 @@ -- t = t(x) = t0 + t1*x + t2*x^2 -- This is what binds the proof to the actual original Pedersen commitment V to the actual value verifyTPoly- :: (AsInteger f, Eq f, Field f)+ :: KnownNat p => Integer -- ^ Dimension n of the vectors -> [Crypto.Point] -- ^ Commitments of in-range values- -> RangeProof f+ -> RangeProof (PrimeField p) -- ^ Proof that a secret committed value lies in a certain interval- -> f -- ^ Challenge x- -> f -- ^ Challenge y- -> f -- ^ Challenge z+ -> PrimeField p -- ^ Challenge x+ -> PrimeField p -- ^ Challenge y+ -> PrimeField p -- ^ Challenge z -> Bool verifyTPoly n vCommits proof@RangeProof{..} x y z = lhs == rhs@@ -63,24 +64,24 @@ m = fromIntegral $ length vCommits lhs = commit t tBlinding rhs =- sumExps ((*) (fSquare z) <$> powerVector z m) vCommits+ sumExps ((*) (z ^ 2) <$> powerVector z m) vCommits `addP` (delta n m y z `mulP` g) `addP` (x `mulP` t1Commit) `addP`- (fSquare x `mulP` t2Commit)+ ((x ^ 2) `mulP` t2Commit) -- | Verify the inner product argument for the vectors l and r that form t verifyLRCommitment- :: (AsInteger f, Eq f, Field f, Show f)+ :: KnownNat p => Integer -- ^ Dimension n of the vectors -> Integer- -> RangeProof f+ -> RangeProof (PrimeField p) -- ^ Proof that a secret committed value lies in a certain interval- -> f -- ^ Challenge x- -> f -- ^ Challenge y- -> f -- ^ Challenge z+ -> PrimeField p -- ^ Challenge x+ -> PrimeField p -- ^ Challenge y+ -> PrimeField p -- ^ Challenge z -> Bool verifyLRCommitment n m proof@RangeProof{..} x y z = IPP.verifyProof
Bulletproofs/RangeProof/Internal.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE DeriveGeneric, DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric, DeriveAnyClass, ViewPatterns #-} module Bulletproofs.RangeProof.Internal where import Protolude@@ -10,6 +10,7 @@ import Crypto.Random.Types (MonadRandom(..)) import qualified Crypto.PubKey.ECC.Prim as Crypto import qualified Crypto.PubKey.ECC.Types as Crypto+import PrimeField (PrimeField(..), toInt) import Bulletproofs.Utils import Bulletproofs.Curve@@ -40,10 +41,10 @@ -- has vectors l, r ∈ Z^n for which P = l · G + r · H + ( l, r ) · U } deriving (Show, Eq, Generic, NFData) -data RangeProofError+data RangeProofError f = UpperBoundTooLarge Integer -- ^ The upper bound of the range is too large- | ValueNotInRange Integer -- ^ Value is not within the range required- | ValuesNotInRange [Integer] -- ^ Values are not within the range required+ | ValueNotInRange f -- ^ Value is not within the range required+ | ValuesNotInRange [f] -- ^ Values are not within the range required | NNotPowerOf2 Integer -- ^ Dimension n is required to be a power of 2 deriving (Show, Eq, Generic, NFData) @@ -73,16 +74,16 @@ -- | Encode the value v into a bit representation. Let aL be a vector -- of bits such that <aL, 2^n> = v (put more simply, the components of a L are the -- binary digits of v).-encodeBit :: (AsInteger f, Num f) => Integer -> f -> [f]-encodeBit n v = fillWithZeros n $ fromIntegral . digitToInt <$> showIntAtBase 2 intToDigit (asInteger v) ""+encodeBit :: KnownNat p => Integer -> PrimeField p -> [PrimeField p]+encodeBit n v = fillWithZeros n $ fromIntegral . digitToInt <$> showIntAtBase 2 intToDigit (toInt v) "" -- | Bits of v reversed. -- v = <a, 2^n> = a_0 * 2^0 + ... + a_n-1 * 2^(n-1)-reversedEncodeBit :: (AsInteger f, Num f) => Integer -> f -> [f]+reversedEncodeBit :: KnownNat p => Integer -> PrimeField p -> [PrimeField p] reversedEncodeBit n = reverse . encodeBit n -- TODO: Test it-reversedEncodeBitMulti :: (AsInteger f, Num f) => Integer -> [f] -> [f]+reversedEncodeBitMulti :: KnownNat p => Integer -> [PrimeField p] -> [PrimeField p] reversedEncodeBitMulti n = foldl' (\acc v -> acc ++ reversedEncodeBit n v) [] -- | In order to prove that v is in range, each element of aL is either 0 or 1.@@ -102,9 +103,9 @@ -- | Obfuscate encoded bits with challenges y and z. -- z^2 * <aL, 2^n> + z * <aL − 1^n − aR, y^n> + <aL, aR · y^n> = (z^2) * v -- The property holds because <aL − 1^n − aR, y^n> = 0 and <aL · aR, y^n> = 0-obfuscateEncodedBits :: (Eq f, Field f) => Integer -> [f] -> [f] -> f -> f -> f+obfuscateEncodedBits :: KnownNat p => Integer -> [PrimeField p] -> [PrimeField p] -> PrimeField p -> PrimeField p -> PrimeField p obfuscateEncodedBits n aL aR y z- = (fSquare z * dot aL (powerVector 2 n))+ = ((z ^ 2) * dot aL (powerVector 2 n)) + (z * dot ((aL ^-^ powerVector 1 n) ^-^ aR) yN) + dot (hadamardp aL aR) yN where@@ -115,11 +116,11 @@ -- what’s important is that the aL , aR terms be kept inside -- (since they can’t be shared with the Verifier): -- <aL − z * 1^n , y^n ◦ (aR + z * 1^n) + z^2 * 2^n> = z 2 v + δ(y, z)-obfuscateEncodedBitsSingle :: (Eq f, Field f) => Integer -> [f] -> [f] -> f -> f -> f+obfuscateEncodedBitsSingle :: KnownNat p => Integer -> [PrimeField p] -> [PrimeField p] -> PrimeField p -> PrimeField p -> PrimeField p obfuscateEncodedBitsSingle n aL aR y z = dot (aL ^-^ z1n)- (hadamardp (powerVector y n) (aR ^+^ z1n) ^+^ ((*) (fSquare z) <$> powerVector 2 n))+ (hadamardp (powerVector y n) (aR ^+^ z1n) ^+^ ((*) (z ^ 2) <$> powerVector 2 n)) where z1n = (*) z <$> powerVector 1 n @@ -128,13 +129,13 @@ -- Prover can send commitments to these vectors; -- these are properly blinded vector Pedersen commitments: commitBitVectors- :: (MonadRandom m, AsInteger f)- => f- -> f- -> [f]- -> [f]- -> [f]- -> [f]+ :: (MonadRandom m)+ => PrimeField p+ -> PrimeField p+ -> [PrimeField p]+ -> [PrimeField p]+ -> [PrimeField p]+ -> [PrimeField p] -> m (Crypto.Point, Crypto.Point) commitBitVectors aBlinding sBlinding aL aR sL sR = do let aLG = sumExps aL gs@@ -153,35 +154,35 @@ pure (aCommit, sCommit) -- | (z − z^2) * <1^n, y^n> − z^3 * <1^n, 2^n>-delta :: (Eq f, Field f) => Integer -> Integer -> f -> f -> f+delta :: KnownNat p => Integer -> Integer -> PrimeField p -> PrimeField p -> PrimeField p delta n m y z- = ((z - fSquare z) * dot (powerVector 1 nm) (powerVector y nm))+ = ((z - (z ^ 2)) * dot (powerVector 1 nm) (powerVector y nm)) - foldl' (\acc j -> acc + ((z ^ (j + 2)) * dot (powerVector 1 n) (powerVector 2 n))) 0 [1..m] where nm = n * m -- | Check that a value is in a specific range-checkRange :: Integer -> Integer -> Bool-checkRange n v = v >= 0 && v < 2 ^ n+checkRange :: Integer -> PrimeField p -> Bool+checkRange n (toInt -> v) = v >= 0 && v < 2 ^ n -- | Check that a value is in a specific range-checkRanges :: Integer -> [Integer] -> Bool-checkRanges n vs = and $ fmap (\v -> v >= 0 && v < 2 ^ n) vs+checkRanges :: Integer -> [PrimeField p] -> Bool+checkRanges n vs = and $ fmap (\(toInt -> v) -> v >= 0 && v < 2 ^ n) vs -- | Compute commitment of linear vector polynomials l and r -- P = A + xS − zG + (z*y^n + z^2 * 2^n) * hs' computeLRCommitment- :: (AsInteger f, Eq f, Num f, Show f)+ :: KnownNat p => Integer -> Integer -> Crypto.Point -> Crypto.Point- -> f- -> f- -> f- -> f- -> f- -> f+ -> PrimeField p+ -> PrimeField p+ -> PrimeField p+ -> PrimeField p+ -> PrimeField p+ -> PrimeField p -> [Crypto.Point] -> Crypto.Point computeLRCommitment n m aCommit sCommit t tBlinding mu x y z hs'
Bulletproofs/RangeProof/Prover.hs view
@@ -6,28 +6,28 @@ import Protolude import Crypto.Random.Types (MonadRandom(..))+import PrimeField (PrimeField(..), toInt) -import Bulletproofs.Utils (AsInteger, Field) import Bulletproofs.RangeProof.Internal import qualified Bulletproofs.MultiRangeProof.Prover as MRP -- | Prove that a value lies in a specific range generateProof- :: (AsInteger f, Eq f, Field f, Show f, MonadRandom m)+ :: (KnownNat p, MonadRandom m) => Integer -- ^ Upper bound of the range we want to prove- -> (Integer, Integer)+ -> (PrimeField p, PrimeField p) -- ^ Values we want to prove in range and their blinding factors- -> ExceptT RangeProofError m (RangeProof f)+ -> ExceptT (RangeProofError (PrimeField p)) m (RangeProof (PrimeField p)) generateProof upperBound (v, vBlinding) = MRP.generateProof upperBound [(v, vBlinding)] -- | Generate range proof from valid inputs generateProofUnsafe- :: (AsInteger f, Eq f, Field f, Show f, MonadRandom m)+ :: (KnownNat p, MonadRandom m) => Integer -- ^ Upper bound of the range we want to prove- -> (Integer, Integer)+ -> (PrimeField p, PrimeField p) -- ^ Values we want to prove in range and their blinding factors- -> m (RangeProof f)+ -> m (RangeProof (PrimeField p)) generateProofUnsafe upperBound (v, vBlinding) = MRP.generateProofUnsafe upperBound [(v, vBlinding)]
Bulletproofs/RangeProof/Verifier.hs view
@@ -9,6 +9,7 @@ import Protolude import qualified Crypto.PubKey.ECC.Types as Crypto+import PrimeField (PrimeField(..), toInt) import Bulletproofs.RangeProof.Internal import Bulletproofs.Curve@@ -18,10 +19,10 @@ -- | Verify that a commitment was computed from a value in a given range verifyProof- :: (AsInteger f, Eq f, Field f, Show f)+ :: KnownNat p => Integer -- ^ Range upper bound -> Crypto.Point -- ^ Commitments of in-range values- -> RangeProof f+ -> RangeProof (PrimeField p) -- ^ Proof that a secret committed value lies in a certain interval -> Bool verifyProof upperBound vCommit proof@RangeProof{..}@@ -31,27 +32,27 @@ -- t = t(x) = t0 + t1*x + t2*x^2 -- This is what binds the proof to the actual original Pedersen commitment V to the actual value verifyTPoly- :: (AsInteger f, Eq f, Field f, Show f)+ :: KnownNat p => Integer -- ^ Dimension n of the vectors -> Crypto.Point -- ^ Commitment of in-range value- -> RangeProof f+ -> RangeProof (PrimeField p) -- ^ Proof that a secret committed value lies in a certain interval- -> f -- ^ Challenge x- -> f -- ^ Challenge y- -> f -- ^ Challenge z+ -> PrimeField p -- ^ Challenge x+ -> PrimeField p -- ^ Challenge y+ -> PrimeField p -- ^ Challenge z -> Bool verifyTPoly n vCommit = MRP.verifyTPoly n [vCommit] -- | Verify the inner product argument for the vectors l and r that form t verifyLRCommitment- :: (AsInteger f, Eq f, Field f, Show f)+ :: KnownNat p => Integer -- ^ Dimension n of the vectors- -> RangeProof f+ -> RangeProof (PrimeField p) -- ^ Proof that a secret committed value lies in a certain interval- -> f -- ^ Challenge x- -> f -- ^ Challenge y- -> f -- ^ Challenge z+ -> PrimeField p -- ^ Challenge x+ -> PrimeField p -- ^ Challenge y+ -> PrimeField p -- ^ Challenge z -> Bool verifyLRCommitment n = MRP.verifyLRCommitment n 1
Bulletproofs/Utils.hs view
@@ -6,27 +6,11 @@ import qualified Crypto.PubKey.ECC.Types as Crypto import Crypto.Random (MonadRandom) import Crypto.Number.Generate (generateMax)+import PrimeField (PrimeField, toInt) import Bulletproofs.Fq as Fq hiding (asInteger) import Bulletproofs.Curve -class AsInteger a where- asInteger :: a -> Integer--instance AsInteger Fq where- asInteger (Fq x) = x--instance AsInteger Integer where- asInteger x = x---- Class for specialisations of field operations that may have--- optimised implementations.-class (Num f, Fractional f) => Field f where- fSquare :: f -> f--instance Field Fq where- fSquare = Fq.fqSquare- -- | Return a vector containing the first n powers of a powerVector :: (Eq f, Num f) => f -> Integer -> [f] powerVector a x@@ -55,15 +39,15 @@ subP x y = Crypto.pointAdd curve x (Crypto.pointNegate curve y) -- | Multiply a scalar and a point in an elliptic curve-mulP :: AsInteger f => f -> Crypto.Point -> Crypto.Point-mulP x = Crypto.pointMul curve (asInteger x)+mulP :: PrimeField p -> Crypto.Point -> Crypto.Point+mulP x = Crypto.pointMul curve (toInt x) -- | Double exponentiation (Shamir's trick): g0^x0 + g1^x1-addTwoMulP :: AsInteger f => f -> Crypto.Point -> f -> Crypto.Point -> Crypto.Point-addTwoMulP exp0 pt0 exp1 pt1 = Crypto.pointAddTwoMuls curve (asInteger exp0) pt0 (asInteger exp1) pt1+addTwoMulP :: PrimeField p -> Crypto.Point -> PrimeField p -> Crypto.Point -> Crypto.Point+addTwoMulP exp0 pt0 exp1 pt1 = Crypto.pointAddTwoMuls curve (toInt exp0) pt0 (toInt exp1) pt1 -- | Raise every point to the corresponding exponent, sum up results-sumExps :: AsInteger f => [f] -> [Crypto.Point] -> Crypto.Point+sumExps :: [PrimeField p] -> [Crypto.Point] -> Crypto.Point sumExps (exp0:exp1:exps) (pt0:pt1:pts) = addTwoMulP exp0 pt0 exp1 pt1 `addP` sumExps exps pts sumExps (exp:_) (pt:_) = mulP exp pt -- this also catches cases where either list is longer than the other@@ -71,7 +55,7 @@ -- | Create a Pedersen commitment to a value given -- a value and a blinding factor-commit :: AsInteger f => f -> f -> Crypto.Point+commit :: PrimeField p -> PrimeField p -> Crypto.Point commit x r = addTwoMulP x g r h isLogBase2 :: Integer -> Bool@@ -135,12 +119,12 @@ shamirY :: Num f => Crypto.Point -> Crypto.Point -> f shamirY aCommit sCommit = fromInteger $ oracle $- show q <> pointToBS aCommit <> pointToBS sCommit+ show _q <> pointToBS aCommit <> pointToBS sCommit shamirZ :: (Show f, Num f) => Crypto.Point -> Crypto.Point -> f -> f shamirZ aCommit sCommit y = fromInteger $ oracle $- show q <> pointToBS aCommit <> pointToBS sCommit <> show y+ show _q <> pointToBS aCommit <> pointToBS sCommit <> show y shamirX :: (Show f, Num f)@@ -153,7 +137,7 @@ -> f shamirX aCommit sCommit t1Commit t2Commit y z = fromInteger $ oracle $- show q <> pointToBS aCommit <> pointToBS sCommit <> pointToBS t1Commit <> pointToBS t2Commit <> show y <> show z+ show _q <> pointToBS aCommit <> pointToBS sCommit <> pointToBS t1Commit <> pointToBS t2Commit <> show y <> show z shamirX' :: Num f@@ -163,9 +147,9 @@ -> f shamirX' commitmentLR l' r' = fromInteger $ oracle $- show q <> pointToBS l' <> pointToBS r' <> pointToBS commitmentLR+ show _q <> pointToBS l' <> pointToBS r' <> pointToBS commitmentLR shamirU :: (Show f, Num f) => f -> f -> f -> f shamirU tBlinding mu t = fromInteger $ oracle $- show q <> show tBlinding <> show mu <> show t+ show _q <> show tBlinding <> show mu <> show t
ChangeLog.md view
@@ -1,12 +1,23 @@ # Changelog for bulletproofs -## 0.1+## 1.0 -* Initial release.-* Implementation of the Bulletproofs protocol for range proofs-* Use of the improved inner-product argument to reduce the communication complexity-* Support for SECp256k1 curve+* Use galois-field library as dependency+* Remove custom definition of Fq+* Remove Fractional constraints and use PrimeField instead+* Update interface of rangeproofs to guarantee the use of prime fields +## 0.4++* Use double exponentiation to improve performance.+* Use Control.Exception.assert to make sure debugging assertions are not checked+ when compiled with optimisations.+* Add benchmarks for rangeproofs.++## 0.3++* Update dependencies+ ## 0.2 * Prove and verify computations of arithmetic circuits using Bulletproofs@@ -16,13 +27,10 @@ * Provide examples for using aggregated range proofs. * Add multi-range proofs documentation. -## 0.3--* Update dependencies+## 0.1 -## 0.4+* Initial release.+* Implementation of the Bulletproofs protocol for range proofs+* Use of the improved inner-product argument to reduce the communication complexity+* Support for SECp256k1 curve -* Use double exponentiation to improve performance.-* Use Control.Exception.assert to make sure debugging assertions are not checked- when compiled with optimisations.-* Add benchmarks for rangeproofs.
LICENSE view
@@ -1,4 +1,4 @@-Copyright Adjoint Inc. (c) 2018+Copyright Adjoint Inc. (c) 2018-2019 All rights reserved.
README.md view
@@ -100,7 +100,7 @@ ```haskell import qualified Bulletproofs.RangeProof as RP -testSingleRangeProof :: (Integer, Integer) -> IO Bool+testSingleRangeProof :: (Fq, Fq) -> IO Bool testSingleRangeProof (v, vBlinding) = do let vCommit = commit v vBlinding -- n needs to be a power of 2@@ -113,7 +113,7 @@ -- Verifier case proofE of Left err -> panic $ show err- Right (proof@RangeProof{..})+ Right (proof@RP.RangeProof{..}) -> pure $ RP.verifyProof upperBound vCommit proof ``` @@ -123,7 +123,7 @@ ```haskell import qualified Bulletproofs.MultiRangeProof as MRP -testMultiRangeProof :: [(Integer, Integer)] -> IO Bool+testMultiRangeProof :: [(Fq, Fq)] -> IO Bool testMultiRangeProof vsAndvBlindings = do let vCommits = fmap (uncurry commit) vsAndvBlindings -- n needs to be a power of 2@@ -136,7 +136,7 @@ -- Verifier case proofE of Left err -> panic $ show err- Right (proof@RangeProof{..})+ Right (proof@RP.RangeProof{..}) -> pure $ MRP.verifyProof upperBound vCommits proof ``` @@ -205,7 +205,7 @@ v0 = sum aL v1 = sum aR - commitBlinders <- replicateM m Fq.random+ commitBlinders <- replicateM m fqRandom let commitments = zipWith commit [v0, v1] commitBlinders let arithWitness = ArithWitness
bulletproofs.cabal view
@@ -2,10 +2,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 45ba76c7c1825f4c36913fb81f9c8f6c9691748248208ec2ff4d1bbb54c9a836+-- hash: c3039f817828e381dba02b51b3dd24480614dfa32254ebae4b12992e2d2a126e name: bulletproofs-version: 0.4.0+version: 1.0.0 description: Please see the README on GitHub at <https://github.com/adjoint-io/bulletproofs#readme> category: Cryptography homepage: https://github.com/adjoint-io/bulletproofs#readme@@ -47,14 +47,17 @@ Paths_bulletproofs hs-source-dirs: ./.- default-extensions: OverloadedStrings NoImplicitPrelude+ default-extensions: LambdaCase RecordWildCards OverloadedStrings NoImplicitPrelude FlexibleInstances ExplicitForAll RankNTypes DataKinds KindSignatures GeneralizedNewtypeDeriving TypeApplications ExistentialQuantification ScopedTypeVariables DeriveGeneric BangPatterns FlexibleContexts build-depends: MonadRandom+ , QuickCheck , arithmoi , base >=4.7 && <5 , containers , cryptonite+ , galois-field , memory+ , pairing , protolude >=0.2 , random-shuffle , text@@ -80,7 +83,9 @@ , bulletproofs , containers , cryptonite+ , galois-field , memory+ , pairing , protolude >=0.2 , random-shuffle , tasty@@ -106,7 +111,9 @@ , containers , criterion >=1.5.1.0 , cryptonite+ , galois-field , memory+ , pairing , protolude >=0.2 , random-shuffle , tasty
tests/TestArithCircuitProtocol.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE ViewPatterns, RecordWildCards #-}+{-# LANGUAGE ViewPatterns, RecordWildCards, TypeApplications #-} module TestArithCircuitProtocol where @@ -34,28 +34,17 @@ -- wL * aL + wR * aR + wO * aO - c = wV * v test_arithCircuitProof_arbitrary :: TestTree test_arithCircuitProof_arbitrary = localOption (QuickCheckTests 10) $- testProperty "Arbitrary arithmetic circuit proof" $ QCM.monadicIO $ do- n <- QCM.run $ generateBetween 1 100- m <- QCM.run $ generateBetween 1 n- let lConstraints = m-- weights@GateWeights{..} <- QCM.run $ generateGateWeights lConstraints n- commitmentWeights <- QCM.run $ generateWv lConstraints m- Assignment{..} <- QCM.run $ generateRandomAssignment n-- cs <- QCM.run $ replicateM (fromIntegral m) Fq.random- commitBlinders <- QCM.run $ replicateM (fromIntegral m) Fq.random-- let gateWeights = GateWeights wL wR wO- gateInputs = Assignment aL aR aO- vs = computeInputValues weights commitmentWeights gateInputs cs- commitments = zipWith commit vs commitBlinders- arithCircuit = ArithCircuit gateWeights commitmentWeights cs- arithWitness = ArithWitness gateInputs commitments commitBlinders-- proof <- QCM.run $ generateProof arithCircuit arithWitness-- QCM.assert $ verifyProof commitments proof arithCircuit+ testProperty "Arbitrary arithmetic circuit proof" $ go+ where+ go :: Property+ go = forAll (arbitrary `suchThat` ((<) 100))+ $ \n -> forAll (arbitrary `suchThat` (\m -> m > 0 && m < n))+ $ \m -> forAll (arithCircuitGen @(PF Fq) n m)+ $ \arithCircuit@ArithCircuit{..} -> forAll (arithAssignmentGen n)+ $ \assignment@Assignment{..} -> forAll (arithWitnessGen assignment arithCircuit m)+ $ \arithWitness@ArithWitness{..} -> QCM.monadicIO $ do+ proof <- QCM.run $ generateProof arithCircuit arithWitness+ QCM.assert $ verifyProof commitments proof arithCircuit -- | Test hadamard product relation -- 2 linear constraints (q = 2):@@ -67,40 +56,40 @@ -- 2 input values (m = 2) test_arithCircuitProof_hadamardp :: TestTree test_arithCircuitProof_hadamardp = localOption (QuickCheckTests 20) $- testProperty "Arithmetic circuit proof. Hadamard product relation" $ QCM.monadicIO $ do-- let n = 16- aL <- QCM.run $ replicateM (fromIntegral n) Fq.random- aR <- QCM.run $ replicateM (fromIntegral n) Fq.random- let aO = aL `hadamardp` aR+ testProperty "Arithmetic circuit proof. Hadamard product relation" go+ where+ n = 16+ go :: Fq -> Fq -> Property+ go r s = forAll (vectorOf n (arbitrary @Fq))+ $ \aL -> forAll (vectorOf n arbitrary)+ $ \aR -> QCM.monadicIO $ do+ let aO = aL `hadamardp` aR - r <- QCM.run Fq.random- s <- QCM.run Fq.random- let v0 = sum aL- v1 = sum aR+ let v0 = sum aL+ v1 = sum aR - let v0Commit = commit v0 r- v1Commit = commit v1 s+ let v0Commit = commit v0 r+ v1Commit = commit v1 s - let zeroVector = replicate (fromIntegral n) 0- oneVector = replicate (fromIntegral n) 1+ let zeroVector = replicate (fromIntegral n) 0+ oneVector = replicate (fromIntegral n) 1 - let wL = [oneVector, zeroVector]- wR = [zeroVector, oneVector]- wO = [zeroVector, zeroVector]+ let wL = [oneVector, zeroVector]+ wR = [zeroVector, oneVector]+ wO = [zeroVector, zeroVector] - commitmentWeights = [[1, 0], [0, 1]]- cs = [0, 0]- commitments = [v0Commit, v1Commit]- commitBlinders = [r, s]- gateWeights = GateWeights wL wR wO- gateInputs = Assignment aL aR aO- arithCircuit = ArithCircuit gateWeights commitmentWeights cs- arithWitness = ArithWitness gateInputs commitments commitBlinders+ commitmentWeights = [[1, 0], [0, 1]]+ cs = [0, 0]+ commitments = [v0Commit, v1Commit]+ commitBlinders = [r, s]+ gateWeights = GateWeights wL wR wO+ gateInputs = Assignment aL aR aO+ arithCircuit = ArithCircuit gateWeights commitmentWeights cs+ arithWitness = ArithWitness gateInputs commitments commitBlinders - proof <- QCM.run $ generateProof arithCircuit arithWitness+ proof <- QCM.run $ generateProof arithCircuit arithWitness - QCM.assert $ verifyProof commitments proof arithCircuit+ QCM.assert $ verifyProof commitments proof arithCircuit -- | Test that an addition circuit without multiplication gates succeeds -- 1 linear constraints (q = 1):@@ -111,30 +100,31 @@ -- 3 input values (m = 3) test_arithCircuitProof_no_mult_gates :: TestTree test_arithCircuitProof_no_mult_gates = localOption (QuickCheckTests 20) $- testProperty "Arithmetic circuit proof. n = 0, m = 3, q = 1"- $ QCM.monadicIO $ do- let n = 0- m = 3-- commitBlinders <- QCM.run $ replicateM m Fq.random- let wL = [[]]- wR = [[]]- wO = [[]]- cs = [0]- aL = []- aR = []- aO = []- commitmentWeights = [[1, 1, -1]]- vs = [2, 5, 7]- commitments = zipWith commit vs commitBlinders- gateWeights = GateWeights wL wR wO- gateInputs = Assignment aL aR aO- arithCircuit = ArithCircuit gateWeights commitmentWeights cs- arithWitness = ArithWitness gateInputs commitments commitBlinders+ testProperty "Arithmetic circuit proof. n = 0, m = 3, q = 1" go+ where+ m = 3+ go :: Property+ go = forAll (vectorOf (fromIntegral m) (arbitrary @Fq))+ $ \commitBlinders -> QCM.monadicIO $ do+ let n = 0+ let wL = [[]]+ wR = [[]]+ wO = [[]]+ cs = [0]+ aL = []+ aR = []+ aO = []+ commitmentWeights = [[1, 1, -1]]+ vs = [2, 5, 7]+ commitments = zipWith commit vs commitBlinders+ gateWeights = GateWeights wL wR wO+ gateInputs = Assignment aL aR aO+ arithCircuit = ArithCircuit gateWeights commitmentWeights cs+ arithWitness = ArithWitness gateInputs commitments commitBlinders - proof <- QCM.run $ generateProof arithCircuit arithWitness+ proof <- QCM.run $ generateProof arithCircuit arithWitness - QCM.assert $ verifyProof commitments proof arithCircuit+ QCM.assert $ verifyProof commitments proof arithCircuit -- | Test that a circuit with a single multiplication gate -- with linear contraints and not committed values succeeds@@ -149,31 +139,30 @@ -- 0 input values (m = 0) test_arithCircuitProof_no_input_values :: TestTree test_arithCircuitProof_no_input_values = localOption (QuickCheckTests 20) $- testProperty "Arithmetic circuit proof. n = 1, m = 0, q = 3"- $ QCM.monadicIO $ do- let n = 1- m = 0-- commitBlinders <- QCM.run $ replicateM m Fq.random- let wL = [[0], [0], [1]]- wR = [[0], [1], [0]]- wO = [[1], [0], [0]]- cs = [35, 5, 7]- aL = [7]- aR = [5]- aO = [35]- commitmentWeights = [[], [], []]- vs = []- commitments = zipWith commit vs commitBlinders- gateWeights = GateWeights wL wR wO- gateInputs = Assignment aL aR aO- arithCircuit = ArithCircuit gateWeights commitmentWeights cs- arithWitness = ArithWitness gateInputs commitments commitBlinders-- proof <- QCM.run $ generateProof arithCircuit arithWitness-- QCM.assert $ verifyProof commitments proof arithCircuit+ testProperty "Arithmetic circuit proof. n = 1, m = 0, q = 3" go+ where+ m = 0+ go :: Property+ go = forAll (vectorOf (fromIntegral m) (arbitrary @Fq))+ $ \commitBlinders -> QCM.monadicIO $ do+ let n = 1 + let wL = [[0], [0], [1]]+ wR = [[0], [1], [0]]+ wO = [[1], [0], [0]]+ cs = [35, 5, 7]+ aL = [7]+ aR = [5]+ aO = [35]+ commitmentWeights = [[], [], []]+ vs = []+ commitments = zipWith commit vs commitBlinders+ gateWeights = GateWeights wL wR wO+ gateInputs = Assignment aL aR aO+ arithCircuit = ArithCircuit gateWeights commitmentWeights cs+ arithWitness = ArithWitness gateInputs commitments commitBlinders+ proof <- QCM.run $ generateProof arithCircuit arithWitness+ QCM.assert $ verifyProof commitments proof arithCircuit -- 5 linear constraints (q = 5): -- aO[0] = aO[1]@@ -189,42 +178,43 @@ -- 4 input values (m = 4) test_arithCircuitProof_shuffle_circuit :: TestTree test_arithCircuitProof_shuffle_circuit = localOption (QuickCheckTests 20) $- testProperty "Arithmetic circuit proof. n = 2, m = 4, q = 5" $ QCM.monadicIO $ do- z <- QCM.run Fq.random- commitBlinders <- QCM.run $ replicateM 4 Fq.random-- let wL = [[0, 0]- ,[1, 0]- ,[0, 1]- ,[0, 0]- ,[0, 0]]- wR = [[0, 0]- ,[0, 0]- ,[0, 0]- ,[1, 0]- ,[0, 1]]- wO = [[1, -1]- ,[0, 0]- ,[0, 0]- ,[0, 0]- ,[0, 0]]- wV = [[0, 0, 0, 0]- ,[1, 0, 0, 0]- ,[0, 0, 1, 0]- ,[0, 1, 0 ,0]- ,[0, 0, 0, 1]]- cs = [0, -z, -z, -z, -z]- aL = [4 - z, 9 - z]- aR = [9 - z, 4 - z]- aO = aL `hadamardp` aR- vs = [4, 9, 9, 4]- commitments = zipWith commit vs commitBlinders- gateWeights = GateWeights wL wR wO- gateInputs = Assignment aL aR aO- arithCircuit = ArithCircuit gateWeights wV cs- arithWitness = ArithWitness gateInputs commitments commitBlinders+ testProperty "Arithmetic circuit proof. n = 2, m = 4, q = 5" $ go+ where+ go :: Fq -> Property+ go z = forAll (vectorOf 4 (arbitrary @Fq))+ $ \commitBlinders -> QCM.monadicIO $ do - proof <- QCM.run $ generateProof arithCircuit arithWitness+ let wL = [[0, 0]+ ,[1, 0]+ ,[0, 1]+ ,[0, 0]+ ,[0, 0]]+ wR = [[0, 0]+ ,[0, 0]+ ,[0, 0]+ ,[1, 0]+ ,[0, 1]]+ wO = [[1, -1]+ ,[0, 0]+ ,[0, 0]+ ,[0, 0]+ ,[0, 0]]+ wV = [[0, 0, 0, 0]+ ,[1, 0, 0, 0]+ ,[0, 0, 1, 0]+ ,[0, 1, 0 ,0]+ ,[0, 0, 0, 1]]+ cs = [0, -z, -z, -z, -z]+ aL = [4 - z, 9 - z]+ aR = [9 - z, 4 - z]+ aO = aL `hadamardp` aR+ vs = [4, 9, 9, 4]+ commitments = zipWith commit vs commitBlinders+ gateWeights = GateWeights wL wR wO+ gateInputs = Assignment aL aR aO+ arithCircuit = ArithCircuit gateWeights wV cs+ arithWitness = ArithWitness gateInputs commitments commitBlinders - QCM.assert $ verifyProof commitments proof arithCircuit+ proof <- QCM.run $ generateProof arithCircuit arithWitness+ QCM.assert $ verifyProof commitments proof arithCircuit
tests/TestField.hs view
@@ -16,9 +16,6 @@ import TestCommon -instance Arbitrary Fq where- arbitrary = Fq.new <$> arbitrary- prop_addMod :: Fq -> Fq -> Property prop_addMod x y = (x + y) `mulP` g === (x `mulP` g) `addP` (y `mulP` g)@@ -26,7 +23,6 @@ prop_subMod :: Fq -> Fq -> Property prop_subMod x y = (x - y) `mulP` g === (x `mulP` g) `addP` Crypto.pointNegate curve (y `mulP` g)- ------------------------------------------------------------------------------- -- Laws of field operations
tests/TestProtocol.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE ViewPatterns, RecordWildCards, TypeApplications #-}+{-# LANGUAGE ViewPatterns, RecordWildCards, TypeApplications, ScopedTypeVariables #-} module TestProtocol where @@ -14,6 +14,7 @@ import qualified Crypto.PubKey.ECC.Generate as Crypto import qualified Crypto.PubKey.ECC.Prim as Crypto import qualified Crypto.PubKey.ECC.Types as Crypto+import GaloisField (GaloisField(..)) import Bulletproofs.Curve import qualified Bulletproofs.RangeProof as RP@@ -47,16 +48,16 @@ prop_dot_aL2n :: Property prop_dot_aL2n = QCM.monadicIO $ do n <- QCM.run $ (2 ^) <$> generateMax 8- v <- QCM.run $ randomN n- QCM.assert $ RP.reversedEncodeBit n v `dot` powerVector 2 n == v+ v <- QCM.run $ fromInteger <$> randomN n+ QCM.assert $ RP.reversedEncodeBit @(PF Fq) n v `dot` powerVector 2 n == v prop_challengeComplementaryVector :: Property prop_challengeComplementaryVector = QCM.monadicIO $ do n <- QCM.run $ (2 ^) <$> generateMax 8- v <- QCM.run $ randomN n- let aL = RP.reversedEncodeBit n v+ v <- QCM.run $ fromInteger <$> randomN n+ let aL = RP.reversedEncodeBit @(PF Fq) n v aR = RP.complementaryVector aL- y <- QCM.run $ randomN n+ y <- QCM.run $ fromInteger <$> randomN n QCM.assert $ dot ((aL ^-^ powerVector 1 n) ^-^ aR)@@ -67,19 +68,19 @@ prop_reversedEncodeBitAggr :: Int -> Property prop_reversedEncodeBitAggr x = QCM.monadicIO $ do n <- QCM.run $ (2 ^) <$> generateMax 8- vs <- QCM.run $ replicateM x $ randomN n+ vs <- QCM.run $ ((<$>) fromInteger) <$> replicateM x (randomN n) let m = fromIntegral $ length vs- reversed = RP.reversedEncodeBitMulti n vs+ reversed = RP.reversedEncodeBitMulti @(PF Fq) n vs QCM.assert $ vs == fmap (\j -> dot (slice n j reversed) (powerVector 2 n)) [1..m] prop_challengeComplementaryVectorAggr :: Int -> Property prop_challengeComplementaryVectorAggr x = QCM.monadicIO $ do n <- QCM.run $ (2 ^) <$> generateMax 8- vs <- QCM.run $ replicateM 3 $ randomN n- let aL = RP.reversedEncodeBitMulti n vs+ vs <- QCM.run $ ((<$>) fromInteger) <$> replicateM 3 (randomN n)+ let aL = RP.reversedEncodeBitMulti @(PF Fq) n vs aR = RP.complementaryVector aL m = length vs- y <- QCM.run $ randomN n+ y <- QCM.run $ fromInteger <$> randomN n QCM.assert $ replicate m 0 ==@@ -92,11 +93,11 @@ prop_obfuscateEncodedBits y z = QCM.monadicIO $ do n <- QCM.run $ (2 ^) <$> generateMax 8- v <- QCM.run $ Fq.new <$> randomN n+ v <- QCM.run $ fromInteger <$> randomN n let aL = RP.reversedEncodeBit n v aR = RP.complementaryVector aL - QCM.assert $ RP.obfuscateEncodedBits n aL aR y z == fSquare z * v+ QCM.assert $ RP.obfuscateEncodedBits n aL aR y z == (z ^ 2) * v prop_singleInnerProduct :: Fq@@ -105,18 +106,18 @@ prop_singleInnerProduct y z = QCM.monadicIO $ do n <- QCM.run $ (2 ^) <$> generateMax 8- v <- QCM.run $ Fq.new <$> randomN n+ v <- QCM.run $ fromInteger <$> randomN n let aL = RP.reversedEncodeBit n v aR = RP.complementaryVector aL - QCM.assert $ RP.obfuscateEncodedBitsSingle n aL aR y z == (fSquare z * v) + RP.delta n 1 y z+ QCM.assert $ RP.obfuscateEncodedBitsSingle n aL aR y z == ((z ^ 2) * v) + RP.delta n 1 y z -setupV :: MonadRandom m => Integer -> m ((Integer, Integer), Crypto.Point)+setupV :: MonadRandom m => Integer -> m ((Fq, Fq), Crypto.Point) setupV n = do- v <- generateMax (2^n)- vBlinding <- Crypto.scalarGenerate curve- let vCommit = commit (Fq.new v) (Fq.new vBlinding)+ v <- fromInteger <$> generateMax (2^n)+ vBlinding <- fromInteger <$> Crypto.scalarGenerate curve+ let vCommit = commit v vBlinding pure ((v, vBlinding), vCommit) test_verifyTPolynomial :: TestTree@@ -159,9 +160,9 @@ n <- QCM.run $ (2 ^) <$> generateMax 8 ((v, vBlinding), vCommit) <- QCM.run $ setupV n let upperBound = getUpperBound n- vNotInRange = v + upperBound+ vNotInRange = fromInteger (toInt v + upperBound) - proofE <- QCM.run $ runExceptT $ MRP.generateProof @Fq upperBound [(vNotInRange, vBlinding)]+ proofE <- QCM.run $ runExceptT $ MRP.generateProof upperBound [(vNotInRange, vBlinding)] case proofE of Left err -> QCM.assert $ RP.ValuesNotInRange [vNotInRange] == err@@ -172,8 +173,8 @@ prop_invalidUpperBound = QCM.monadicIO $ do n <- QCM.run $ (2 ^) <$> generateMax 8 ((v, vBlinding), vCommit) <- QCM.run $ setupV n- let invalidUpperBound = q + 1- proofE <- QCM.run $ runExceptT $ MRP.generateProof @Fq invalidUpperBound [(v, vBlinding)]+ let invalidUpperBound = _q + 1+ proofE <- QCM.run $ runExceptT $ MRP.generateProof invalidUpperBound [(v, vBlinding)] case proofE of Left err -> QCM.assert $ RP.UpperBoundTooLarge invalidUpperBound == err@@ -184,7 +185,7 @@ prop_differentUpperBound (Positive upperBound') = expectFailure . QCM.monadicIO $ do n <- QCM.run $ (2 ^) <$> generateMax 8 ((v, vBlinding), vCommit) <- QCM.run $ setupV n- proofE <- QCM.run $ runExceptT $ MRP.generateProof @Fq (getUpperBound n) [(v, vBlinding)]+ proofE <- QCM.run $ runExceptT $ MRP.generateProof @(PF Fq) (getUpperBound n) [(v, vBlinding)] case proofE of Left err -> panic $ show err Right (proof@RP.RangeProof{..}) ->@@ -195,12 +196,12 @@ testProperty "Check invalid commitment" $ QCM.monadicIO $ do n <- QCM.run $ (2 ^) <$> generateMax 8 ((v, vBlinding), vCommit) <- QCM.run $ setupV n- let invalidVCommit = commit (Fq.new $ v + 1) (Fq.new vBlinding)+ let invalidVCommit = commit (v + 1) vBlinding upperBound = getUpperBound n- proofE <- QCM.run $ runExceptT $ MRP.generateProof @Fq upperBound [(v, vBlinding)]+ proofE <- QCM.run $ runExceptT $ MRP.generateProof @(PF Fq) upperBound [(v, vBlinding)] case proofE of Left err -> panic $ show err- Right (proof@RP.RangeProof{..}) ->+ Right (proof@(RP.RangeProof{..})) -> QCM.assert $ not $ MRP.verifyProof upperBound [invalidVCommit] proof test_multiRangeProof_completeness :: TestTree@@ -211,7 +212,7 @@ ctx <- QCM.run $ replicateM (fromIntegral m) (setupV n) let upperBound = getUpperBound n - proofE <- QCM.run $ runExceptT $ MRP.generateProof @Fq (getUpperBound n) (fst <$> ctx)+ proofE <- QCM.run $ runExceptT $ MRP.generateProof @(PF Fq) (getUpperBound n) (fst <$> ctx) case proofE of Left err -> panic $ show err Right (proof@RP.RangeProof{..}) ->@@ -224,7 +225,7 @@ ((v, vBlinding), vCommit) <- QCM.run $ setupV n let upperBound = getUpperBound n - proofE <- QCM.run $ runExceptT $ RP.generateProof @Fq (getUpperBound n) (v, vBlinding)+ proofE <- QCM.run $ runExceptT $ RP.generateProof @(PF Fq) (getUpperBound n) (v, vBlinding) case proofE of Left err -> panic $ show err Right (proof@RP.RangeProof{..}) ->