module Bulletproofs.Utils ( dotp, addP, subP, mulP, shamirU, shamirX, shamirX', shamirY, shamirZ, commit, hadamardp, powerVector, logBase2, logBase2M, ) where import Protolude import qualified Crypto.PubKey.ECC.Prim as Crypto import qualified Crypto.PubKey.ECC.Types as Crypto import Bulletproofs.Fq as Fq import Bulletproofs.Curve -- | Return a vector containing the first n powers of a powerVector :: Fq -> Integer -> [Fq] powerVector (Fq a) x = (\i -> Fq.new (a ^ i)) <$> [0..x-1] -- | Inner product between two vector polynomials dotp :: Num a => [a] -> [a] -> a dotp a b = foldl' (+) 0 (hadamardp a b) -- | Hadamard product or entry wise multiplication of two vectors hadamardp :: Num a => [a] -> [a] -> [a] hadamardp a b | length a == length b = zipWith (*) a b | otherwise = panic "Vector sizes must match" -- | Add two points of the same curve addP :: Crypto.Point -> Crypto.Point -> Crypto.Point addP = Crypto.pointAdd curve -- | Substract two points of the same curve subP :: Crypto.Point -> Crypto.Point -> Crypto.Point subP x y = Crypto.pointAdd curve x (Crypto.pointNegate curve y) -- | Multiply a scalar and a point in an elliptic curve mulP :: Fq -> Crypto.Point -> Crypto.Point mulP (Fq x) = Crypto.pointMul curve x -- | Create a Pedersen commitment to a value given -- a value and a blinding factor commit :: Fq -> Fq -> Crypto.Point commit x r = (x `mulP` g) `addP` (r `mulP` h) isLogBase2 :: Integer -> Bool isLogBase2 x | x == 1 = True | x == 0 || (x `mod` 2 /= 0) = False | otherwise = isLogBase2 (x `div` 2) logBase2 :: Integer -> Integer logBase2 = floor . logBase 2.0 . fromIntegral logBase2M :: Integer -> Maybe Integer logBase2M x = if isLogBase2 x then Just (logBase2 x) else Nothing -------------------------------------------------- -- Fiat-Shamir transformations -------------------------------------------------- shamirY :: Crypto.Point -> Crypto.Point -> Fq shamirY aCommit sCommit = Fq.new $ oracle $ show q <> pointToBS aCommit <> pointToBS sCommit shamirZ :: Crypto.Point -> Crypto.Point -> Fq -> Fq shamirZ aCommit sCommit y = Fq.new $ oracle $ show q <> pointToBS aCommit <> pointToBS sCommit <> show y shamirX :: Crypto.Point -> Crypto.Point -> Crypto.Point -> Crypto.Point -> Fq -> Fq -> Fq shamirX aCommit sCommit t1Commit t2Commit y z = Fq.new $ oracle $ show q <> pointToBS aCommit <> pointToBS sCommit <> pointToBS t1Commit <> pointToBS t2Commit <> show y <> show z shamirX' :: Crypto.Point -> Crypto.Point -> Crypto.Point -> Fq shamirX' commitmentLR l' r' = Fq.new $ oracle $ show q <> pointToBS l' <> pointToBS r' <> pointToBS commitmentLR shamirU :: Fq -> Fq -> Fq -> Fq shamirU tBlinding mu t = Fq.new $ oracle $ show q <> show tBlinding <> show mu <> show t