{-|
Module      : Crypto.PastaCurves.PastaCurves
Description : Provides the overall Pasta curve and field functionality.
Copyright   : (c) Eric Schorn, 2022
Maintainer  : eric.schorn@nccgroup.com
Stability   : experimental
Portability : GHC
SPDX-License-Identifier: MIT

This module provides the Pasta Curves consisting of: the `Pallas` curve and its `Fp` 
field element, the `Vesta` curve  and its `Fq` field element, and a variety of 
supporting functionality such as point/element arithmetic, serialization, and 
hash-to-curve. The algorithms are NOT constant time; Safety and simplicity are the top 
priorities.

\[
\text{Pallas: } y^2 = x^3 + 5 \text{ over } F_p(0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001)
\]
    
\[
\text{Vesta:  }  y^2 = x^3 + 5 \text{ over } F_q(0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001)
\]

The order of the Pallas curve is 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001.

The order of the Vesta curve is 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001.

The curves are designed such that the order of one matches the field characteristic of
the other. For a brief introduction, see the Zcash blog titled "The Pasta Curves for Halo 
2 and Beyond" at <https://electriccoin.co/blog/the-pasta-curves-for-halo-2-and-beyond/>.
The reference Rust implementation (which inspired this implementation) can be found at:
<https://github.com/zcash/pasta_curves>.

Example usage of this library implementation:

@
$ cabal repl

ghci> a = 9 :: Fp

ghci> a*a
0x0000000000000000000000000000000000000000000000000000000000000051

ghci> pointMul a base :: Vesta
Projective {_px = 0x3CDC6A090F2BB3B52714C083929B620FE24ADBCBBD420752108CD7C29E543E5E, 
            _py = 0x08795CD330B3CE5AA63BD2B18DE155AE3C96E8AF9DA2CC742C6BA1464E490161, 
            _pz = 0x1FA26F58F3A641ADFE81775D3D53378D6178B6CCBF14F9BD4AB5F10DEE28D878}
@

-}

{-# LANGUAGE DataKinds, NoImplicitPrelude, Safe #-}

module PastaCurves (Fp, Fq, Pallas, Vesta, CurvePt(..), Curve(..), hashToPallas, 
  hashToVesta, rndPallas, rndVesta, Field(..), pallasPrime, vestaPrime, exampleFp, 
  exampleFq, examplePallasPt, exampleVestaPt, Num(..)) where

import Pasta (Fp, Fq, Num(..), Pallas, Vesta, CurvePt(..), Curve(..), Field(..), 
  hashToPallas, hashToVesta, rndPallas, rndVesta, pallasPrime, vestaPrime)
import Data.ByteString.UTF8 (fromString)


-- | An example `Fp` element (8).
exampleFp :: Fp
exampleFp :: Fp
exampleFp = Fp
8


-- | An example `Fq` element (999).
exampleFq :: Fq
exampleFq :: Fq
exampleFq = Fq
999


-- | An example `Pallas` point generated by hashing a message.
examplePallasPt :: Pallas
examplePallasPt :: Pallas
examplePallasPt = ByteString -> Pallas
hashToPallas (String -> ByteString
fromString String
"A message to hash")


-- | An example `Vesta` point (base * 8).
exampleVestaPt :: Vesta
exampleVestaPt :: Vesta
exampleVestaPt = forall a b. Curve a b => b -> a -> a
pointMul Fp
exampleFp forall a. CurvePt a => a
base