-- | Point serialisation using https://tools.ietf.org/id/draft-jivsov-ecc-compact-05.html -- It is unclear if 02 is smallest y or not so the following is used in the first 2 bytes -- 01 - Point at infinity -- 02 - Compressed repr i.e. x only but use smallest y on decode -- 03 - Compressed repr i.e. x only but use largest y on decode -- 04 -- Uncompressed repr i.e. x & y module Pairing.Serialize.Jivsov where -- ( Jivsov(..) -- ) where -- -- import Protolude hiding (putByteString) -- import Pairing.Point -- import Pairing.Serialize.Types -- import Pairing.Fq -- import Data.ByteString.Builder -- import Data.ByteString as B hiding (length) -- import qualified Data.ByteString as B -- import Data.Binary.Get -- import Data.Binary.Put (Put, putWord8, putWord16le, runPut, putByteString) -- import Control.Error -- import Pairing.ByteRepr -- import Pairing.CyclicGroup -- -- data Jivsov = Jivsov -- -- instance MkCompressedForm Jivsov where -- serializeCompressed _ = toCompressedForm -- -- instance MkUncompressedForm Jivsov where -- serializePointUncompressed _ = toUncompressedForm -- serializeUncompressed _ = elementToUncompressedForm -- -- instance FromSerialisedForm Jivsov where -- unserializePoint _ = pointFromByteString -- -- instance FromUncompressedForm Jivsov where -- unserialize _ = elementReadUncompressed -- -- putCompressionType :: Word8 -> Put -- putCompressionType n = putWord8 0 >> putWord8 n -- -- getCompressionType :: Get Word8 -- getCompressionType = getWord8 >> getWord8 -- -- ------------------------------------------------------------------------------- -- -- Element specific Serailisation -- ------------------------------------------------------------------------------- -- -- elementToUncompressedForm :: (ByteRepr a) => a -> Maybe LByteString -- elementToUncompressedForm a = do -- repr <- mkRepr (ByteOrderLength MostSignificantFirst minReprLength) a -- pure $ runPut $ do -- putCompressionType 4 -- putByteString repr -- -- elementReadUncompressed :: (Validate a, Show a, ByteRepr a) => a -> LByteString -> Either Text a -- elementReadUncompressed ele = parseBS runc -- where -- runc = do -- ctype <- getCompressionType -- if ctype == 4 then do -- let xlen = calcReprLength ele minReprLength -- bs <- getByteString xlen -- pure (fromRepr (ByteOrderLength MostSignificantFirst minReprLength) ele bs) -- else -- pure Nothing -- -- ------------------------------------------------------------------------------- -- -- Point specific serialisation -- ------------------------------------------------------------------------------- -- -- toUncompressedForm :: (ByteRepr a) => Point a -> Maybe LByteString -- toUncompressedForm (Point x y) = do -- rx <- mkRepr (ByteOrderLength MostSignificantFirst minReprLength) x -- ry <- mkRepr (ByteOrderLength MostSignificantFirst minReprLength) y -- pure $ runPut $ do -- putCompressionType 4 -- putByteString rx -- putByteString ry -- toUncompressedForm Infinity = pure $ runPut (putCompressionType 1) -- -- toCompressedForm :: (ByteRepr a, FromX a, Ord a) => Point a -> Maybe LByteString -- toCompressedForm (Point x y) = do -- ny <- yFromX x max -- let yform = if ny == y then 3 else 2 -- rx <- mkRepr (ByteOrderLength MostSignificantFirst minReprLength) x -- pure (runPut $ do -- putCompressionType yform -- putByteString rx) -- toCompressedForm Infinity = Just (toLazyByteString (word8 0 <> word8 1)) -- -- pointFromByteString :: (Show a, Validate (Point a), ByteRepr a, FromX a, Ord a) => Point a -> LByteString -> Either Text (Point a) -- pointFromByteString (Point a _) bs = parseBS fromByteStringGet bs -- where -- fromByteStringGet = do -- ctype <- getCompressionType -- processCompressed a ctype -- pointFromByteString Infinity _ = Left "Cannot use infinity to extract from bytestring" -- -- processCompressed :: forall a . (ByteRepr a, FromX a, Ord a) => a -> Word8 -> Get (Maybe (Point a)) -- processCompressed one ct -- | ct == 4 = do -- xbs <- getByteString blen -- ybs <- getByteString blen -- pure (buildPoint one (ByteOrderLength MostSignificantFirst minReprLength) xbs (ByteOrderLength MostSignificantFirst minReprLength) ybs) -- | ct == 2 = fromCompressed False -- | ct == 3 = fromCompressed True -- | ct == 1 = pure (Just Infinity) -- | otherwise = pure Nothing -- where -- blen = calcReprLength one minReprLength -- fromCompressed largestY = runMaybeT $ do -- xbs <- lift $ getByteString blen -- x <- hoistMaybe $ fromRepr (ByteOrderLength MostSignificantFirst minReprLength) one xbs -- y <- hoistMaybe $ yFromX x (\y1 y2 -> if largestY then max y1 y2 else min y1 y2) -- pure (Point x y)