packages feed

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 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{..}) ->