module Bulletproofs.Curve (
_q,
_a,
_b,
g,
h,
gs,
hs,
curve,
oracle,
pointToBS,
) where
import Protolude hiding (hash)
import Data.Maybe (fromJust)
import Crypto.Hash
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 qualified Data.ByteArray as BA
import Crypto.Number.Serialize (os2ip)
import Math.NumberTheory.Moduli.Sqrt (sqrtsModPrime)
import Math.NumberTheory.UniqueFactorisation (isPrime)
import Numeric
import qualified Data.List as L
curveName :: Crypto.CurveName
curveName = Crypto.SEC_p256k1
curve :: Crypto.Curve
curve = Crypto.getCurveByName curveName
_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
g :: Crypto.Point
g = Crypto.ecc_g $ Crypto.common_curve curve
h :: Crypto.Point
h = generateH g ""
gs :: [Crypto.Point]
gs = Crypto.pointBaseMul curve . oracle . (<> pointToBS g) . show <$> [1..]
hs :: [Crypto.Point]
hs = Crypto.pointBaseMul curve . oracle . (<> pointToBS h) . show <$> [1..]
oracle :: ByteString -> Integer
oracle x = os2ip (sha256 x)
sha256 :: ByteString -> ByteString
sha256 bs = BA.convert (hash bs :: Digest SHA3_256)
pointToBS :: Crypto.Point -> ByteString
pointToBS Crypto.PointO = ""
pointToBS (Crypto.Point x y) = show x <> show y
_p :: Integer
_p = Crypto.ecc_p cp
where
cp = case curve of
Crypto.CurveFP c -> c
Crypto.CurveF2m _ -> panic "Not a FP curve"
generateH :: Crypto.Point -> [Char] -> Crypto.Point
generateH basePoint extra =
case yM of
[] -> generateH basePoint (toS $ '1':extra)
(y:_) -> if Crypto.isPointValid curve (Crypto.Point x y)
then Crypto.Point x y
else generateH basePoint (toS $ '1':extra)
where
x = oracle (pointToBS basePoint <> toS extra) `mod` _p
yM = sqrtsModPrime (fromInteger (x ^ 3 + 7)) ((fromJust (isPrime _p)))