module Bulletproofs.Curve (
q,
g,
h,
gs,
hs,
curve,
oracle,
pointToBS,
) where
import Protolude hiding (hash)
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 (sqrtModP)
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
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
Nothing -> generateH basePoint (toS $ '1':extra)
Just 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 = sqrtModP (x ^ 3 + 7) p