{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}
module PlutusCore.Crypto.BLS12_381.G2
( Element (..)
, add
, neg
, scalarMul
, hashToGroup
, compress
, uncompress
, offchain_zero
, compressed_zero
, compressed_generator
, memSizeBytes
, compressedSizeBytes
, multiScalarMul
) where
import Cardano.Crypto.EllipticCurve.BLS12_381 qualified as BlstBindings
import Cardano.Crypto.EllipticCurve.BLS12_381.Internal qualified as BlstBindings.Internal
import PlutusCore.Builtin.Result (BuiltinResult (..))
import PlutusCore.Crypto.BLS12_381.Bounds (msmScalarOutOfBounds)
import PlutusCore.Crypto.BLS12_381.Error (BLS12_381_Error (..))
import PlutusCore.Crypto.Utils (byteStringAsHex)
import PlutusCore.Pretty.PrettyConst (ConstConfig)
import Text.PrettyBy (PrettyBy)
import Control.DeepSeq
( NFData
, rnf
, rwhnf
)
import Data.ByteString
( ByteString
, length
)
import Data.Coerce (coerce)
import Data.Hashable
import Data.Proxy (Proxy (..))
import PlutusCore.Flat
import Prettyprinter
newtype Element = Element {Element -> Point Curve2
unElement :: BlstBindings.Point2}
deriving newtype (Element -> Element -> Bool
(Element -> Element -> Bool)
-> (Element -> Element -> Bool) -> Eq Element
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Element -> Element -> Bool
== :: Element -> Element -> Bool
$c/= :: Element -> Element -> Bool
/= :: Element -> Element -> Bool
Eq)
instance Show Element where
show :: Element -> String
show = ByteString -> String
byteStringAsHex (ByteString -> String)
-> (Element -> ByteString) -> Element -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Element -> ByteString
compress
instance Pretty Element where
pretty :: forall ann. Element -> Doc ann
pretty = String -> Doc ann
forall ann. String -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty (String -> Doc ann) -> (Element -> String) -> Element -> Doc ann
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Element -> String
forall a. Show a => a -> String
show
instance PrettyBy ConstConfig Element
instance Flat Element where
decode :: Get Element
decode = String -> Get Element
forall a. String -> Get a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Flat decoding is not supported for objects of type bls12_381_G2_element: use bls12_381_G2_uncompress on a bytestring instead."
encode :: Element -> Encoding
encode = String -> Element -> Encoding
forall a. HasCallStack => String -> a
error String
"Flat encoding is not supported for objects of type bls12_381_G2_element: use bls12_381_G2_compress to obtain a bytestring instead."
size :: Element -> Int -> Int
size Element
_ = Int -> Int
forall a. a -> a
id
instance NFData Element where
rnf :: Element -> ()
rnf (Element Point Curve2
x) = Point Curve2 -> ()
forall a. a -> ()
rwhnf Point Curve2
x
instance Hashable Element where
hashWithSalt :: Int -> Element -> Int
hashWithSalt Int
salt = Int -> ByteString -> Int
forall a. Hashable a => Int -> a -> Int
hashWithSalt Int
salt (ByteString -> Int) -> (Element -> ByteString) -> Element -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Element -> ByteString
compress
add :: Element -> Element -> Element
add :: Element -> Element -> Element
add = (Point Curve2 -> Point Curve2 -> Point Curve2)
-> Element -> Element -> Element
forall a b. Coercible a b => a -> b
coerce (forall curve.
BLS curve =>
Point curve -> Point curve -> Point curve
BlstBindings.blsAddOrDouble @BlstBindings.Curve2)
{-# INLINE add #-}
neg :: Element -> Element
neg :: Element -> Element
neg = (Point Curve2 -> Point Curve2) -> Element -> Element
forall a b. Coercible a b => a -> b
coerce (forall curve. BLS curve => Point curve -> Point curve
BlstBindings.blsNeg @BlstBindings.Curve2)
{-# INLINE neg #-}
scalarMul :: Integer -> Element -> Element
scalarMul :: Integer -> Element -> Element
scalarMul = (Integer -> Point Curve2 -> Point Curve2)
-> Integer -> Element -> Element
forall a b. Coercible a b => a -> b
coerce ((Integer -> Point Curve2 -> Point Curve2)
-> Integer -> Element -> Element)
-> (Integer -> Point Curve2 -> Point Curve2)
-> Integer
-> Element
-> Element
forall a b. (a -> b) -> a -> b
$ (Point Curve2 -> Integer -> Point Curve2)
-> Integer -> Point Curve2 -> Point Curve2
forall a b c. (a -> b -> c) -> b -> a -> c
flip (forall curve. BLS curve => Point curve -> Integer -> Point curve
BlstBindings.blsMult @BlstBindings.Curve2)
{-# INLINE scalarMul #-}
compress :: Element -> ByteString
compress :: Element -> ByteString
compress = (Point Curve2 -> ByteString) -> Element -> ByteString
forall a b. Coercible a b => a -> b
coerce (forall curve. BLS curve => Point curve -> ByteString
BlstBindings.blsCompress @BlstBindings.Curve2)
{-# INLINE compress #-}
uncompress :: ByteString -> Either BlstBindings.BLSTError Element
uncompress :: ByteString -> Either BLSTError Element
uncompress = (ByteString -> Either BLSTError (Point Curve2))
-> ByteString -> Either BLSTError Element
forall a b. Coercible a b => a -> b
coerce (forall curve.
BLS curve =>
ByteString -> Either BLSTError (Point curve)
BlstBindings.blsUncompress @BlstBindings.Curve2)
{-# INLINE uncompress #-}
hashToGroup :: ByteString -> ByteString -> Either BLS12_381_Error Element
hashToGroup :: ByteString -> ByteString -> Either BLS12_381_Error Element
hashToGroup ByteString
msg ByteString
dst =
if ByteString -> Int
Data.ByteString.length ByteString
dst Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
255
then BLS12_381_Error -> Either BLS12_381_Error Element
forall a b. a -> Either a b
Left BLS12_381_Error
HashToCurveDstTooBig
else Element -> Either BLS12_381_Error Element
forall a b. b -> Either a b
Right (Element -> Either BLS12_381_Error Element)
-> (Point Curve2 -> Element)
-> Point Curve2
-> Either BLS12_381_Error Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Point Curve2 -> Element
Element (Point Curve2 -> Either BLS12_381_Error Element)
-> Point Curve2 -> Either BLS12_381_Error Element
forall a b. (a -> b) -> a -> b
$ forall curve.
BLS curve =>
ByteString -> Maybe ByteString -> Maybe ByteString -> Point curve
BlstBindings.blsHash @BlstBindings.Curve2 ByteString
msg (ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
dst) Maybe ByteString
forall a. Maybe a
Nothing
offchain_zero :: Element
offchain_zero :: Element
offchain_zero = Point Curve2 -> Element
forall a b. Coercible a b => a -> b
coerce (forall curve. BLS curve => Point curve
BlstBindings.Internal.blsZero @BlstBindings.Curve2)
compressed_zero :: ByteString
compressed_zero :: ByteString
compressed_zero = Element -> ByteString
compress (Element -> ByteString) -> Element -> ByteString
forall a b. (a -> b) -> a -> b
$ Point Curve2 -> Element
forall a b. Coercible a b => a -> b
coerce (forall curve. BLS curve => Point curve
BlstBindings.Internal.blsZero @BlstBindings.Curve2)
compressed_generator :: ByteString
compressed_generator :: ByteString
compressed_generator = Element -> ByteString
compress (Element -> ByteString) -> Element -> ByteString
forall a b. (a -> b) -> a -> b
$ Point Curve2 -> Element
forall a b. Coercible a b => a -> b
coerce (forall curve. BLS curve => Point curve
BlstBindings.Internal.blsGenerator @BlstBindings.Curve2)
memSizeBytes :: Int
memSizeBytes :: Int
memSizeBytes = Proxy Curve2 -> Int
forall curve. BLS curve => Proxy curve -> Int
BlstBindings.Internal.sizePoint (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @BlstBindings.Curve2)
compressedSizeBytes :: Int
compressedSizeBytes :: Int
compressedSizeBytes = Proxy Curve2 -> Int
forall curve. BLS curve => Proxy curve -> Int
BlstBindings.Internal.compressedSizePoint (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @BlstBindings.Curve2)
multiScalarMul :: [Integer] -> [Element] -> BuiltinResult Element
multiScalarMul :: [Integer] -> [Element] -> BuiltinResult Element
multiScalarMul [Integer]
ss [Element]
p
| (Integer -> Bool) -> [Integer] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Integer -> Bool
msmScalarOutOfBounds [Integer]
ss = String -> BuiltinResult Element
forall a. String -> BuiltinResult a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Scalar exceeds 512-byte bound for G2.multiScalarMul"
| Bool
otherwise = Element -> BuiltinResult Element
forall a. a -> BuiltinResult a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Element -> BuiltinResult Element)
-> (Point Curve2 -> Element)
-> Point Curve2
-> BuiltinResult Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Point Curve2 -> Element
forall a b. Coercible a b => a -> b
coerce (Point Curve2 -> BuiltinResult Element)
-> Point Curve2 -> BuiltinResult Element
forall a b. (a -> b) -> a -> b
$ forall curve. BLS curve => [(Integer, Point curve)] -> Point curve
BlstBindings.blsMSM @BlstBindings.Curve2 ([Integer] -> [Point Curve2] -> [(Integer, Point Curve2)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Integer]
ss ([Element] -> [Point Curve2]
forall a b. Coercible a b => a -> b
coerce [Element]
p))