packages feed

libsecp256k1 0.0.1 → 0.0.2

raw patch · 4 files changed

+799/−486 lines, 4 filesdep +cryptonitedep +memorydep +transformersdep −QuickCheckdep −base16dep −cerealPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: cryptonite, memory, transformers

Dependencies removed: QuickCheck, base16, cereal, deepseq, entropy, hashable, string-conversions, unliftio-core

API changes (from Hackage documentation)

- Crypto.Secp256k1: combinePubKeys :: [PubKey] -> Maybe PubKey
- Crypto.Secp256k1: compactSig :: ByteString -> Maybe CompactSig
- Crypto.Secp256k1: data CompactSig
- Crypto.Secp256k1: data Msg
- Crypto.Secp256k1: data PubKey
- Crypto.Secp256k1: data Sig
- Crypto.Secp256k1: exportCompactSig :: Sig -> CompactSig
- Crypto.Secp256k1: exportPubKey :: Bool -> PubKey -> ByteString
- Crypto.Secp256k1: exportSig :: Sig -> ByteString
- Crypto.Secp256k1: getCompactSig :: CompactSig -> ByteString
- Crypto.Secp256k1: getMsg :: Msg -> ByteString
- Crypto.Secp256k1: getSecKey :: SecKey -> ByteString
- Crypto.Secp256k1: getTweak :: Tweak -> ByteString
- Crypto.Secp256k1: importCompactSig :: CompactSig -> Maybe Sig
- Crypto.Secp256k1: importPubKey :: ByteString -> Maybe PubKey
- Crypto.Secp256k1: importSig :: ByteString -> Maybe Sig
- Crypto.Secp256k1: instance Control.DeepSeq.NFData Crypto.Secp256k1.CompactSig
- Crypto.Secp256k1: instance Control.DeepSeq.NFData Crypto.Secp256k1.Msg
- Crypto.Secp256k1: instance Control.DeepSeq.NFData Crypto.Secp256k1.PubKey
- Crypto.Secp256k1: instance Control.DeepSeq.NFData Crypto.Secp256k1.SecKey
- Crypto.Secp256k1: instance Control.DeepSeq.NFData Crypto.Secp256k1.Sig
- Crypto.Secp256k1: instance Control.DeepSeq.NFData Crypto.Secp256k1.Tweak
- Crypto.Secp256k1: instance Data.Hashable.Class.Hashable Crypto.Secp256k1.Msg
- Crypto.Secp256k1: instance Data.Hashable.Class.Hashable Crypto.Secp256k1.PubKey
- Crypto.Secp256k1: instance Data.Hashable.Class.Hashable Crypto.Secp256k1.SecKey
- Crypto.Secp256k1: instance Data.Hashable.Class.Hashable Crypto.Secp256k1.Sig
- Crypto.Secp256k1: instance Data.Hashable.Class.Hashable Crypto.Secp256k1.Tweak
- Crypto.Secp256k1: instance Data.Serialize.Serialize Crypto.Secp256k1.CompactSig
- Crypto.Secp256k1: instance Data.Serialize.Serialize Crypto.Secp256k1.Msg
- Crypto.Secp256k1: instance Data.Serialize.Serialize Crypto.Secp256k1.PubKey
- Crypto.Secp256k1: instance Data.Serialize.Serialize Crypto.Secp256k1.SecKey
- Crypto.Secp256k1: instance Data.Serialize.Serialize Crypto.Secp256k1.Sig
- Crypto.Secp256k1: instance Data.Serialize.Serialize Crypto.Secp256k1.Tweak
- Crypto.Secp256k1: instance Data.String.IsString Crypto.Secp256k1.Msg
- Crypto.Secp256k1: instance Data.String.IsString Crypto.Secp256k1.PubKey
- Crypto.Secp256k1: instance Data.String.IsString Crypto.Secp256k1.SecKey
- Crypto.Secp256k1: instance Data.String.IsString Crypto.Secp256k1.Sig
- Crypto.Secp256k1: instance Data.String.IsString Crypto.Secp256k1.Tweak
- Crypto.Secp256k1: instance GHC.Classes.Eq Crypto.Secp256k1.CompactSig
- Crypto.Secp256k1: instance GHC.Classes.Eq Crypto.Secp256k1.Msg
- Crypto.Secp256k1: instance GHC.Classes.Eq Crypto.Secp256k1.PubKey
- Crypto.Secp256k1: instance GHC.Classes.Eq Crypto.Secp256k1.SecKey
- Crypto.Secp256k1: instance GHC.Classes.Eq Crypto.Secp256k1.Sig
- Crypto.Secp256k1: instance GHC.Classes.Eq Crypto.Secp256k1.Tweak
- Crypto.Secp256k1: instance GHC.Generics.Generic Crypto.Secp256k1.CompactSig
- Crypto.Secp256k1: instance GHC.Generics.Generic Crypto.Secp256k1.Msg
- Crypto.Secp256k1: instance GHC.Generics.Generic Crypto.Secp256k1.PubKey
- Crypto.Secp256k1: instance GHC.Generics.Generic Crypto.Secp256k1.SecKey
- Crypto.Secp256k1: instance GHC.Generics.Generic Crypto.Secp256k1.Sig
- Crypto.Secp256k1: instance GHC.Generics.Generic Crypto.Secp256k1.Tweak
- Crypto.Secp256k1: instance GHC.Read.Read Crypto.Secp256k1.Msg
- Crypto.Secp256k1: instance GHC.Read.Read Crypto.Secp256k1.PubKey
- Crypto.Secp256k1: instance GHC.Read.Read Crypto.Secp256k1.SecKey
- Crypto.Secp256k1: instance GHC.Read.Read Crypto.Secp256k1.Sig
- Crypto.Secp256k1: instance GHC.Read.Read Crypto.Secp256k1.Tweak
- Crypto.Secp256k1: instance GHC.Show.Show Crypto.Secp256k1.Msg
- Crypto.Secp256k1: instance GHC.Show.Show Crypto.Secp256k1.PubKey
- Crypto.Secp256k1: instance GHC.Show.Show Crypto.Secp256k1.SecKey
- Crypto.Secp256k1: instance GHC.Show.Show Crypto.Secp256k1.Sig
- Crypto.Secp256k1: instance GHC.Show.Show Crypto.Secp256k1.Tweak
- Crypto.Secp256k1: instance Test.QuickCheck.Arbitrary.Arbitrary Crypto.Secp256k1.Msg
- Crypto.Secp256k1: instance Test.QuickCheck.Arbitrary.Arbitrary Crypto.Secp256k1.PubKey
- Crypto.Secp256k1: instance Test.QuickCheck.Arbitrary.Arbitrary Crypto.Secp256k1.SecKey
- Crypto.Secp256k1: msg :: ByteString -> Maybe Msg
- Crypto.Secp256k1: normalizeSig :: Sig -> Maybe Sig
- Crypto.Secp256k1: secKey :: ByteString -> Maybe SecKey
- Crypto.Secp256k1: signMsg :: SecKey -> Msg -> Sig
- Crypto.Secp256k1: tweak :: ByteString -> Maybe Tweak
- Crypto.Secp256k1: tweakAddPubKey :: PubKey -> Tweak -> Maybe PubKey
- Crypto.Secp256k1: tweakAddSecKey :: SecKey -> Tweak -> Maybe SecKey
- Crypto.Secp256k1: tweakMulPubKey :: PubKey -> Tweak -> Maybe PubKey
- Crypto.Secp256k1: tweakMulSecKey :: SecKey -> Tweak -> Maybe SecKey
- Crypto.Secp256k1: verifySig :: PubKey -> Sig -> Msg -> Bool
- Crypto.Secp256k1.Prim: compressed :: SerFlags
- Crypto.Secp256k1.Prim: ctx :: Ctx
- Crypto.Secp256k1.Prim: data Compact64
- Crypto.Secp256k1.Prim: ecdhHashSha256 :: FunPtr (EcdhHashFun a)
- Crypto.Secp256k1.Prim: isSuccess :: Ret -> Bool
- Crypto.Secp256k1.Prim: packByteString :: (Ptr a, CSize) -> IO ByteString
- Crypto.Secp256k1.Prim: schnorrSigSignVerify :: Ctx -> Ptr Sig64 -> Ptr (Bytes n) -> CSize -> Ptr XonlyPubkey64 -> IO Ret
- Crypto.Secp256k1.Prim: sign :: CtxFlags
- Crypto.Secp256k1.Prim: signVerify :: CtxFlags
- Crypto.Secp256k1.Prim: type CtxFlags = CUInt
- Crypto.Secp256k1.Prim: type SerFlags = CUInt
- Crypto.Secp256k1.Prim: uncompressed :: SerFlags
- Crypto.Secp256k1.Prim: unsafePackByteString :: (Ptr a, CSize) -> IO ByteString
- Crypto.Secp256k1.Prim: unsafeUseByteString :: ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
- Crypto.Secp256k1.Prim: useByteString :: ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
- Crypto.Secp256k1.Prim: verify :: CtxFlags
+ Crypto.Secp256k1: SchnorrExtra :: (ByteString -> SecKey -> PubKeyXO -> ByteString -> a -> Maybe (SizedByteArray 32 ByteString)) -> a -> SchnorrExtra a
+ Crypto.Secp256k1: [schnorrExtraData] :: SchnorrExtra a -> a
+ Crypto.Secp256k1: [schnorrExtraNonceFunHardened] :: SchnorrExtra a -> ByteString -> SecKey -> PubKeyXO -> ByteString -> a -> Maybe (SizedByteArray 32 ByteString)
+ Crypto.Secp256k1: data KeyPair
+ Crypto.Secp256k1: data PubKeyXO
+ Crypto.Secp256k1: data PubKeyXY
+ Crypto.Secp256k1: data RecoverableSignature
+ Crypto.Secp256k1: data SchnorrExtra a
+ Crypto.Secp256k1: data Signature
+ Crypto.Secp256k1: ecSecKeyTweakAdd :: SecKey -> Tweak -> Maybe SecKey
+ Crypto.Secp256k1: ecSecKeyTweakMul :: SecKey -> Tweak -> Maybe SecKey
+ Crypto.Secp256k1: ecdh :: SecKey -> PubKeyXY -> Digest SHA256
+ Crypto.Secp256k1: ecdsaRecover :: RecoverableSignature -> ByteString -> Maybe PubKeyXY
+ Crypto.Secp256k1: ecdsaSign :: SecKey -> ByteString -> Maybe Signature
+ Crypto.Secp256k1: ecdsaSignRecoverable :: SecKey -> ByteString -> Maybe RecoverableSignature
+ Crypto.Secp256k1: ecdsaVerify :: ByteString -> PubKeyXY -> Signature -> Bool
+ Crypto.Secp256k1: exportPubKeyXO :: PubKeyXO -> ByteString
+ Crypto.Secp256k1: exportPubKeyXY :: Bool -> PubKeyXY -> ByteString
+ Crypto.Secp256k1: exportRecoverableSignature :: RecoverableSignature -> ByteString
+ Crypto.Secp256k1: exportSignatureCompact :: Signature -> ByteString
+ Crypto.Secp256k1: exportSignatureDer :: Signature -> ByteString
+ Crypto.Secp256k1: importPubKeyXO :: ByteString -> Maybe PubKeyXO
+ Crypto.Secp256k1: importPubKeyXY :: ByteString -> Maybe PubKeyXY
+ Crypto.Secp256k1: importRecoverableSignature :: ByteString -> Maybe RecoverableSignature
+ Crypto.Secp256k1: importSecKey :: ByteString -> Maybe SecKey
+ Crypto.Secp256k1: importSignature :: ByteString -> Maybe Signature
+ Crypto.Secp256k1: importTweak :: ByteString -> Maybe Tweak
+ Crypto.Secp256k1: keyPairCreate :: SecKey -> KeyPair
+ Crypto.Secp256k1: keyPairPubKeyXO :: KeyPair -> (PubKeyXO, Bool)
+ Crypto.Secp256k1: keyPairPubKeyXOTweakAdd :: KeyPair -> Tweak -> Maybe KeyPair
+ Crypto.Secp256k1: keyPairPubKeyXY :: KeyPair -> PubKeyXY
+ Crypto.Secp256k1: pubKeyCombine :: [PubKeyXY] -> Maybe PubKeyXY
+ Crypto.Secp256k1: pubKeyNegate :: PubKeyXY -> PubKeyXY
+ Crypto.Secp256k1: pubKeyTweakAdd :: PubKeyXY -> Tweak -> Maybe PubKeyXY
+ Crypto.Secp256k1: pubKeyTweakMul :: PubKeyXY -> Tweak -> Maybe PubKeyXY
+ Crypto.Secp256k1: pubKeyXOTweakAdd :: PubKeyXO -> Tweak -> Maybe PubKeyXY
+ Crypto.Secp256k1: pubKeyXOTweakAddCheck :: PubKeyXO -> Bool -> PubKeyXO -> Tweak -> Bool
+ Crypto.Secp256k1: recSigToSig :: RecoverableSignature -> Signature
+ Crypto.Secp256k1: schnorrSign :: KeyPair -> ByteString -> Maybe Signature
+ Crypto.Secp256k1: schnorrSignCustom :: forall a. KeyPair -> ByteString -> SchnorrExtra a -> Maybe Signature
+ Crypto.Secp256k1: schnorrVerify :: PubKeyXO -> ByteString -> Signature -> Bool
+ Crypto.Secp256k1: secKeyNegate :: SecKey -> SecKey
+ Crypto.Secp256k1: taggedSha256 :: ByteString -> ByteString -> Digest SHA256
+ Crypto.Secp256k1: xyToXO :: PubKeyXY -> (PubKeyXO, Bool)
+ Crypto.Secp256k1.Internal: isSuccess :: Ret -> Bool
+ Crypto.Secp256k1.Internal: packByteString :: (Ptr a, CSize) -> IO ByteString
+ Crypto.Secp256k1.Internal: unsafePackByteString :: (Ptr a, CSize) -> IO ByteString
+ Crypto.Secp256k1.Internal: unsafeUseByteString :: ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
+ Crypto.Secp256k1.Internal: useByteString :: ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
+ Crypto.Secp256k1.Prim: ecdhHashFunctionSha256 :: FunPtr (EcdhHashFun a)
+ Crypto.Secp256k1.Prim: flagsBitCompression :: CompressionFlags
+ Crypto.Secp256k1.Prim: flagsBitContextDeclassify :: ContextFlags
+ Crypto.Secp256k1.Prim: flagsBitContextSign :: ContextFlags
+ Crypto.Secp256k1.Prim: flagsBitContextVerify :: ContextFlags
+ Crypto.Secp256k1.Prim: flagsContextDeclassify :: ContextFlags
+ Crypto.Secp256k1.Prim: flagsContextNone :: ContextFlags
+ Crypto.Secp256k1.Prim: flagsContextSign :: ContextFlags
+ Crypto.Secp256k1.Prim: flagsContextVerify :: ContextFlags
+ Crypto.Secp256k1.Prim: flagsEcCompressed :: CompressionFlags
+ Crypto.Secp256k1.Prim: flagsEcUncompressed :: CompressionFlags
+ Crypto.Secp256k1.Prim: flagsTagPubkeyEven :: PubkeyFlags
+ Crypto.Secp256k1.Prim: flagsTagPubkeyHybridEven :: PubkeyFlags
+ Crypto.Secp256k1.Prim: flagsTagPubkeyHybridOdd :: PubkeyFlags
+ Crypto.Secp256k1.Prim: flagsTagPubkeyOdd :: PubkeyFlags
+ Crypto.Secp256k1.Prim: flagsTagPubkeyUncompressed :: PubkeyFlags
+ Crypto.Secp256k1.Prim: flagsTypeCompression :: CompressionFlags
+ Crypto.Secp256k1.Prim: flagsTypeContext :: ContextFlags
+ Crypto.Secp256k1.Prim: flagsTypeMask :: CUInt
+ Crypto.Secp256k1.Prim: schnorrsigSignVerify :: Ctx -> Ptr Sig64 -> Ptr (Bytes n) -> CSize -> Ptr XonlyPubkey64 -> IO Ret
+ Crypto.Secp256k1.Prim: type CompressionFlags = CUInt
+ Crypto.Secp256k1.Prim: type ContextFlags = CUInt
+ Crypto.Secp256k1.Prim: type PubkeyFlags = CUInt
- Crypto.Secp256k1: derivePubKey :: SecKey -> PubKey
+ Crypto.Secp256k1: derivePubKey :: SecKey -> PubKeyXY
- Crypto.Secp256k1.Prim: contextCreate :: CtxFlags -> IO Ctx
+ Crypto.Secp256k1.Prim: contextCreate :: ContextFlags -> IO Ctx
- Crypto.Secp256k1.Prim: ecPubkeySerialize :: Ctx -> Ptr (Bytes n) -> Ptr CSize -> Ptr Pubkey64 -> SerFlags -> IO Ret
+ Crypto.Secp256k1.Prim: ecPubkeySerialize :: Ctx -> Ptr (Bytes n) -> Ptr CSize -> Ptr Pubkey64 -> CompressionFlags -> IO Ret
- Crypto.Secp256k1.Prim: ecdsaSignatureParseCompact :: Ctx -> Ptr Sig64 -> Ptr Compact64 -> IO Ret
+ Crypto.Secp256k1.Prim: ecdsaSignatureParseCompact :: Ctx -> Ptr Sig64 -> Ptr (Bytes 64) -> IO Ret
- Crypto.Secp256k1.Prim: ecdsaSignatureSerializeCompact :: Ctx -> Ptr Compact64 -> Ptr Sig64 -> IO Ret
+ Crypto.Secp256k1.Prim: ecdsaSignatureSerializeCompact :: Ctx -> Ptr (Bytes 64) -> Ptr Sig64 -> IO Ret
- Crypto.Secp256k1.Prim: xonlyPubkeyTweakAddCheck :: Ctx -> Ptr (Bytes 32) -> CInt -> Ptr XonlyPubkey64 -> Ptr Tweak32 -> IO Ret
+ Crypto.Secp256k1.Prim: xonlyPubkeyTweakAddCheck :: Ctx -> Ptr XonlyPubkey64 -> CInt -> Ptr XonlyPubkey64 -> Ptr Tweak32 -> IO Ret

Files

libsecp256k1.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           libsecp256k1-version:        0.0.1+version:        0.0.2 synopsis:       Bindings for secp256k1 description:    Sign and verify signatures using the secp256k1 library. category:       Crypto@@ -28,6 +28,7 @@ library   exposed-modules:       Crypto.Secp256k1+      Crypto.Secp256k1.Internal       Crypto.Secp256k1.Prim       Paths_libsecp256k1   autogen-modules:@@ -37,16 +38,11 @@   pkgconfig-depends:       libsecp256k1   build-depends:-      QuickCheck >=2.9.2 && <2.15-    , base >=4.9 && <5-    , base16 >=0.3.0.1+      base >=4.9 && <5     , bytestring >=0.10.8 && <0.12-    , cereal >=0.5.4 && <0.6-    , deepseq >=1.4.2 && <1.5-    , entropy >=0.3.8 && <0.5-    , hashable >=1.2.6 && <1.5-    , string-conversions ==0.4.*-    , unliftio-core >=0.1.0 && <0.3+    , cryptonite+    , memory+    , transformers   default-language: Haskell2010  test-suite spec@@ -61,19 +57,14 @@   ghc-options: -threaded -rtsopts -with-rtsopts=-N   build-depends:       HUnit-    , QuickCheck >=2.9.2 && <2.15     , base >=4.9 && <5-    , base16 >=0.3.0.1     , bytestring >=0.10.8 && <0.12-    , cereal >=0.5.4 && <0.6-    , deepseq >=1.4.2 && <1.5-    , entropy >=0.3.8 && <0.5-    , hashable >=1.2.6 && <1.5+    , cryptonite     , hspec+    , memory     , monad-par     , mtl     , secp256k1-haskell-    , string-conversions ==0.4.*-    , unliftio-core >=0.1.0 && <0.3+    , transformers   default-language: Haskell2010   build-tool-depends: hspec-discover:hspec-discover
src/Crypto/Secp256k1.hs view
@@ -1,8 +1,16 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TypeApplications #-}+{-# OPTIONS_GHC -fno-show-valid-hole-fits #-}  -- | -- Module      : Crypto.Secp256k1@@ -13,84 +21,123 @@ -- -- Crytpographic functions from Bitcoin’s secp256k1 library. module Crypto.Secp256k1 (-    -- * Messages-    Msg,-    msg,-    getMsg,--    -- * Secret Keys+    -- * Core Types     SecKey,-    secKey,-    getSecKey,-    derivePubKey,+    PubKeyXY,+    PubKeyXO,+    KeyPair,+    Signature,+    RecoverableSignature,+    Tweak, -    -- * Public Keys-    PubKey,-    importPubKey,-    exportPubKey,+    -- * Parsing and Serialization+    importSecKey,+    importPubKeyXY,+    exportPubKeyXY,+    importPubKeyXO,+    exportPubKeyXO,+    importSignature,+    exportSignatureCompact,+    exportSignatureDer,+    importRecoverableSignature,+    exportRecoverableSignature,+    importTweak, -    -- * Signatures-    Sig,-    signMsg,-    verifySig,-    normalizeSig,+    -- * ECDSA Operations+    ecdsaVerify,+    ecdsaSign,+    ecdsaSignRecoverable,+    ecdsaRecover, -    -- ** DER-    importSig,-    exportSig,+    -- * Conversions+    recSigToSig,+    derivePubKey,+    keyPairCreate,+    keyPairPubKeyXY,+    keyPairPubKeyXO,+    xyToXO, -    -- ** Compact-    CompactSig,-    getCompactSig,-    compactSig,-    exportCompactSig,-    importCompactSig,+    -- * Tweaks+    ecSecKeyTweakAdd,+    ecSecKeyTweakMul,+    keyPairPubKeyXOTweakAdd,+    pubKeyCombine,+    pubKeyNegate,+    secKeyNegate,+    pubKeyTweakAdd,+    pubKeyTweakMul,+    pubKeyXOTweakAdd,+    pubKeyXOTweakAddCheck, -    -- * Addition & Multiplication-    Tweak,-    tweak,-    getTweak,-    tweakAddSecKey,-    tweakMulSecKey,-    tweakAddPubKey,-    tweakMulPubKey,-    combinePubKeys,+    -- * Schnorr Operations+    schnorrSign,+    SchnorrExtra (..),+    schnorrSignCustom,+    schnorrVerify,++    -- * Other+    taggedSha256,+    ecdh, ) where -import Control.DeepSeq (NFData) import Control.Monad (replicateM, unless, (<=<))+import Control.Monad.Trans.Class (lift)+import Control.Monad.Trans.Cont (ContT (..), evalContT)+import Crypto.Secp256k1.Internal+import Crypto.Secp256k1.Prim (flagsEcUncompressed) import qualified Crypto.Secp256k1.Prim as Prim+import Data.ByteArray.Sized import Data.ByteString (ByteString) import qualified Data.ByteString as BS-import qualified Data.ByteString.Base16 as B16-import Data.Hashable (Hashable (..))++-- import qualified Data.ByteString.Base16 as B16+import Data.ByteString.Unsafe (unsafePackCStringLen, unsafePackMallocCStringLen)+import Data.Functor (($>))++-- import Data.Hashable (Hashable (..)) import Data.Maybe (fromJust, fromMaybe, isJust)-import Data.Serialize (-    Serialize (..),-    getByteString,-    putByteString,- ) import Data.String (IsString (..))-import Data.String.Conversions (ConvertibleStrings, cs)++-- import Data.String.Conversions (ConvertibleStrings, cs)++import Crypto.Hash (Digest, SHA256, digestFromByteString)+import Data.Foldable (for_) import Foreign (+    Bits (..),+    ForeignPtr,+    FunPtr,+    Ptr,+    Storable,+    Word8,     alloca,     allocaArray,     allocaBytes,+    castForeignPtr,+    castPtr,+    finalizerFree,     free,+    freeHaskellFunPtr,+    malloc,     mallocBytes,+    newForeignPtr,+    newForeignPtr_,     nullFunPtr,     nullPtr,     peek,+    peekByteOff,+    peekElemOff,+    plusPtr,     poke,     pokeArray,+    pokeByteOff,+    pokeElemOff,+    sizeOf,+    withForeignPtr,  )+import Foreign.C (CInt (..), CSize (..)) import GHC.Generics (Generic)+import GHC.IO.Handle.Text (memcpy) import System.IO.Unsafe (unsafePerformIO)-import Test.QuickCheck (-    Arbitrary (..),-    arbitraryBoundedRandom,-    suchThat,- ) import Text.Read (     Lexeme (String),     lexP,@@ -100,411 +147,548 @@  )  -newtype PubKey = PubKey {getPubKey :: ByteString}-    deriving (Eq, Generic, NFData)-newtype Msg = Msg {getMsg :: ByteString}-    deriving (Eq, Generic, NFData)-newtype Sig = Sig {getSig :: ByteString}-    deriving (Eq, Generic, NFData)-newtype SecKey = SecKey {getSecKey :: ByteString}-    deriving (Eq, Generic, NFData)-newtype Tweak = Tweak {getTweak :: ByteString}-    deriving (Eq, Generic, NFData)-newtype CompactSig = CompactSig {getCompactSig :: ByteString}-    deriving (Eq, Generic, NFData)---instance Serialize PubKey where-    put (PubKey bs) = putByteString bs-    get = PubKey <$> getByteString 64---instance Serialize Msg where-    put (Msg m) = putByteString m-    get = Msg <$> getByteString 32---instance Serialize Sig where-    put (Sig bs) = putByteString bs-    get = Sig <$> getByteString 64---instance Serialize SecKey where-    put (SecKey bs) = putByteString bs-    get = SecKey <$> getByteString 32---instance Serialize Tweak where-    put (Tweak bs) = putByteString bs-    get = Tweak <$> getByteString 32+newtype SecKey = SecKey {secKeyFPtr :: ForeignPtr Prim.Seckey32}+newtype PubKeyXY = PubKeyXY {pubKeyXYFPtr :: ForeignPtr Prim.Pubkey64}+newtype PubKeyXO = PubKeyXO {pubKeyXOFPtr :: ForeignPtr Prim.XonlyPubkey64}+newtype KeyPair = KeyPair {keyPairFPtr :: ForeignPtr Prim.Keypair96}+newtype Signature = Signature {signatureFPtr :: ForeignPtr Prim.Sig64}+newtype RecoverableSignature = RecoverableSignature {recoverableSignatureFPtr :: ForeignPtr Prim.RecSig65}+newtype Tweak = Tweak {tweakFPtr :: ForeignPtr Prim.Tweak32}  -instance Serialize CompactSig where-    put (CompactSig bs) = putByteString bs-    get = CompactSig <$> getByteString 64+-- | Preinitialized context for signing and verification+ctx :: Prim.Ctx+ctx = unsafePerformIO $ Prim.contextCreate (Prim.flagsContextSign .|. Prim.flagsContextVerify)+{-# NOINLINE ctx #-}  -decodeHex :: ConvertibleStrings a ByteString => a -> Maybe ByteString-decodeHex str = case B16.decodeBase16 $ cs str of-    Right bs -> Just bs-    Left _ -> Nothing+-- | Parses 'SecKey', will be @Nothing@ if the @ByteString@ corresponds to 0{32} or is not 32 bytes in length+importSecKey :: ByteString -> Maybe SecKey+importSecKey bs+    | BS.length bs /= 32 = Nothing+    | otherwise = unsafePerformIO $ do+        unsafeUseByteString bs $ \(ptr, len) -> do+            ret <- Prim.ecSecKeyVerify ctx ptr+            if isSuccess ret+                then do+                    newPtr <- mallocBytes 32+                    memcpy newPtr ptr 32+                    Just . SecKey <$> newForeignPtr finalizerFree newPtr+                else pure Nothing  -instance Read PubKey where-    readPrec = do-        String str <- lexP-        maybe pfail return $ importPubKey =<< decodeHex str+-- | Parses a 33 or 65 byte 'PubKeyXY', all other lengths will result in @Nothing@+importPubKeyXY :: ByteString -> Maybe PubKeyXY+importPubKeyXY bs = unsafePerformIO $+    unsafeUseByteString bs $ \(input, len) -> do+        pubkeyOutputBuf <- mallocBytes 64+        if len == 33 || len == 65+            then do+                ret <- Prim.ecPubkeyParse ctx (castPtr pubkeyOutputBuf) input len+                if isSuccess ret+                    then Just . PubKeyXY <$> newForeignPtr finalizerFree (castPtr pubkeyOutputBuf)+                    else free pubkeyOutputBuf $> Nothing+            else pure Nothing  -instance Hashable PubKey where-    i `hashWithSalt` k = i `hashWithSalt` exportPubKey True k+-- | Serialize 'PubKeyXY'. First argument @True@ for compressed output (33 bytes), @False@ for uncompressed (65 bytes).+exportPubKeyXY :: Bool -> PubKeyXY -> ByteString+exportPubKeyXY compress (PubKeyXY fptr) = unsafePerformIO $ do+    let flags = if compress then Prim.flagsEcCompressed else Prim.flagsEcUncompressed+    let sz = if compress then 33 else 65+    buf <- mallocBytes sz+    alloca $ \written -> do+        -- always succeeds so we don't need to check+        _ret <- withForeignPtr fptr $ \ptr -> Prim.ecPubkeySerialize ctx buf written ptr flags+        len <- peek written+        unsafePackMallocCStringLen (castPtr buf, fromIntegral len)  -instance IsString PubKey where-    fromString = fromMaybe e . (importPubKey <=< decodeHex)-        where-            e = error "Could not decode public key from hex string"+-- | Parses 'PubKeyXO' from @ByteString@, will be @Nothing@ if the pubkey corresponds to the Point at Infinity or the+-- the @ByteString@ is not 32 bytes long+importPubKeyXO :: ByteString -> Maybe PubKeyXO+importPubKeyXO bs+    | BS.length bs /= 32 = Nothing+    | otherwise = unsafePerformIO $ do+        outBuf <- mallocBytes 64+        unsafeUseByteString bs $ \(ptr, _) -> do+            ret <- Prim.xonlyPubkeyParse ctx outBuf ptr+            if isSuccess ret+                then Just . PubKeyXO <$> newForeignPtr finalizerFree outBuf+                else pure Nothing  -instance Show PubKey where-    showsPrec _ = shows . B16.encodeBase16 . exportPubKey True+-- | Serializes 'PubKeyXO' to 32 byte @ByteString@+exportPubKeyXO :: PubKeyXO -> ByteString+exportPubKeyXO (PubKeyXO pkFPtr) = unsafePerformIO $ do+    outBuf <- mallocBytes 32+    _ret <- withForeignPtr pkFPtr $ Prim.xonlyPubkeySerialize ctx outBuf+    unsafePackByteString (outBuf, 32)  -instance Read Msg where-    readPrec = parens $ do-        String str <- lexP-        maybe pfail return $ msg =<< decodeHex str+-- | Parses 'Signature' from DER (71 | 72 | 73 bytes) or Compact (64 bytes) representations.+importSignature :: ByteString -> Maybe Signature+importSignature bs = unsafePerformIO $+    unsafeUseByteString bs $ \(inBuf, len) -> do+        outBuf <- mallocBytes 64+        ret <-+            if+                    -- compact+                    | len == 64 -> Prim.ecdsaSignatureParseCompact ctx outBuf inBuf+                    -- der+                    | len >= 71 && len <= 73 -> Prim.ecdsaSignatureParseDer ctx outBuf inBuf len+                    -- invalid+                    | otherwise -> pure 0+        if isSuccess ret+            then Just . Signature <$> newForeignPtr finalizerFree (castPtr outBuf)+            else free outBuf $> Nothing  -instance Hashable Msg where-    i `hashWithSalt` m = i `hashWithSalt` getMsg m+-- | Serializes 'Signature' to Compact (64 byte) representation+exportSignatureCompact :: Signature -> ByteString+exportSignatureCompact (Signature fptr) = unsafePerformIO $ do+    outBuf <- mallocBytes 64+    -- always succeeds+    _ret <- withForeignPtr fptr $ Prim.ecdsaSignatureSerializeCompact ctx outBuf+    unsafePackByteString (outBuf, 64)  -instance IsString Msg where-    fromString = fromMaybe e . (msg <=< decodeHex)-        where-            e = error "Could not decode message from hex string"+-- | Serializes 'Signature' to DER (71 | 72 bytes) representation+exportSignatureDer :: Signature -> ByteString+exportSignatureDer (Signature fptr) = unsafePerformIO $ do+    -- as of Q4'2015 73 byte sigs became nonstandard so we will never create one that big+    outBuf <- mallocBytes 72+    alloca $ \written -> do+        -- always succeeds+        _ret <- withForeignPtr fptr $ Prim.ecdsaSignatureSerializeDer ctx outBuf written+        len <- peek written+        unsafePackByteString (outBuf, len)  -instance Show Msg where-    showsPrec _ = shows . B16.encodeBase16 . getMsg+-- | Parses 'RecoverableSignature' from Compact (65 byte) representation+importRecoverableSignature :: ByteString -> Maybe RecoverableSignature+importRecoverableSignature bs+    | BS.length bs /= 65 = Nothing+    | otherwise = unsafePerformIO . evalContT $ do+        outBuf <- lift (mallocBytes 65)+        (ptr, len) <- ContT (unsafeUseByteString bs)+        recId <- lift (peekByteOff @Word8 ptr 64)+        let recIdCInt = fromIntegral recId+        ret <- lift (Prim.ecdsaRecoverableSignatureParseCompact ctx outBuf ptr recIdCInt)+        lift $+            if isSuccess ret+                then Just . RecoverableSignature <$> newForeignPtr finalizerFree outBuf+                else free outBuf $> Nothing  -instance Read Sig where-    readPrec = parens $ do-        String str <- lexP-        maybe pfail return $ importSig =<< decodeHex str+-- | Serializes 'RecoverableSignature' to Compact (65 byte) representation+exportRecoverableSignature :: RecoverableSignature -> ByteString+exportRecoverableSignature RecoverableSignature{..} = unsafePerformIO . evalContT $ do+    recSigPtr <- ContT (withForeignPtr recoverableSignatureFPtr)+    lift $ do+        outBuf <- mallocBytes 65+        recIdPtr <- malloc+        _ret <- Prim.ecdsaRecoverableSignatureSerializeCompact ctx outBuf recIdPtr recSigPtr+        recId <- peek recIdPtr+        unsafePackByteString (outBuf, 65)  -instance IsString Sig where-    fromString = fromMaybe e . (importSig <=< decodeHex)-        where-            e = error "Could not decode signature from hex string"+-- | Parses 'Tweak' from 32 byte @ByteString@. If the @ByteString@ is an invalid 'SecKey' then this will yield @Nothing@+importTweak :: ByteString -> Maybe Tweak+importTweak = fmap (Tweak . castForeignPtr . secKeyFPtr) . importSecKey  -instance Hashable Sig where-    i `hashWithSalt` s = i `hashWithSalt` exportSig s+-- | Verify message signature. 'True' means that the signature is correct.+ecdsaVerify :: ByteString -> PubKeyXY -> Signature -> Bool+ecdsaVerify msgHash (PubKeyXY pkFPtr) (Signature sigFPtr) = unsafePerformIO $+    evalContT $ do+        pkPtr <- ContT (withForeignPtr pkFPtr)+        sigPtr <- ContT (withForeignPtr sigFPtr)+        (msgHashPtr, n) <- ContT (unsafeUseByteString msgHash)+        lift $ isSuccess <$> Prim.ecdsaVerify ctx sigPtr msgHashPtr pkPtr  -instance Show Sig where-    showsPrec _ = shows . B16.encodeBase16 . exportSig+-- | Signs @ByteString@ with 'SecKey' only if @ByteString@ is 32 bytes.+ecdsaSign :: SecKey -> ByteString -> Maybe Signature+ecdsaSign (SecKey skFPtr) msgHash+    | BS.length msgHash /= 32 = Nothing+    | otherwise = unsafePerformIO $+        evalContT $ do+            skPtr <- ContT (withForeignPtr skFPtr)+            (msgHashPtr, _) <- ContT (unsafeUseByteString msgHash)+            sigBuf <- lift $ mallocBytes 64+            ret <- lift $ Prim.ecdsaSign ctx sigBuf msgHashPtr skPtr Prim.nonceFunctionDefault nullPtr+            lift $+                if isSuccess ret+                    then Just . Signature <$> newForeignPtr finalizerFree sigBuf+                    else free sigBuf $> Nothing  -instance Read SecKey where-    readPrec = parens $ do-        String str <- lexP-        maybe pfail return $ secKey =<< decodeHex str+-- | Signs @ByteString@ with 'SecKey' only if @ByteString@ is 32 bytes. Retains ability to compute 'PubKeyXY' from the+-- 'RecoverableSignature' and the original message (@ByteString@)+ecdsaSignRecoverable :: SecKey -> ByteString -> Maybe RecoverableSignature+ecdsaSignRecoverable SecKey{..} bs+    | BS.length bs /= 32 = Nothing+    | otherwise = unsafePerformIO . evalContT $ do+        (msgHashPtr, _) <- ContT (unsafeUseByteString bs)+        secKeyPtr <- ContT (withForeignPtr secKeyFPtr)+        lift $ do+            recSigBuf <- mallocBytes 65+            ret <- Prim.ecdsaSignRecoverable ctx recSigBuf msgHashPtr secKeyPtr Prim.nonceFunctionDefault nullPtr+            if isSuccess ret+                then Just . RecoverableSignature <$> newForeignPtr finalizerFree recSigBuf+                else free recSigBuf $> Nothing  -instance Hashable SecKey where-    i `hashWithSalt` k = i `hashWithSalt` getSecKey k+-- | Computes 'PubKeyXY' from 'RecoverableSignature' and the original message that was signed (must be 32 bytes).+ecdsaRecover :: RecoverableSignature -> ByteString -> Maybe PubKeyXY+ecdsaRecover RecoverableSignature{..} msgHash+    | BS.length msgHash /= 32 = Nothing+    | otherwise = unsafePerformIO . evalContT $ do+        recSigPtr <- ContT (withForeignPtr recoverableSignatureFPtr)+        (msgHashPtr, _) <- ContT (unsafeUseByteString msgHash)+        lift $ do+            pubKeyBuf <- mallocBytes 64+            ret <- Prim.ecdsaRecover ctx pubKeyBuf recSigPtr msgHashPtr+            if isSuccess ret+                then Just . PubKeyXY <$> newForeignPtr finalizerFree pubKeyBuf+                else free pubKeyBuf $> Nothing  -instance IsString SecKey where-    fromString = fromMaybe e . (secKey <=< decodeHex)-        where-            e = error "Colud not decode secret key from hex string"+-- | Forgets the recovery id of a signature+recSigToSig :: RecoverableSignature -> Signature+recSigToSig RecoverableSignature{..} = unsafePerformIO . evalContT $ do+    recSigPtr <- ContT (withForeignPtr recoverableSignatureFPtr)+    lift $ do+        sigBuf <- mallocBytes 64+        _ret <- Prim.ecdsaRecoverableSignatureConvert ctx sigBuf recSigPtr+        Signature <$> newForeignPtr finalizerFree sigBuf  -instance Show SecKey where-    showsPrec _ = shows . B16.encodeBase16 . getSecKey+-- | Use 'SecKey' to compute the corresponding 'PubKeyXY'+derivePubKey :: SecKey -> PubKeyXY+derivePubKey (SecKey skFPtr) = unsafePerformIO $ do+    outBuf <- mallocBytes 64+    ret <- withForeignPtr skFPtr $ Prim.ecPubkeyCreate ctx outBuf+    unless (isSuccess ret) $ do+        free outBuf+        error "Bug: Invalid SecKey Constructed"+    PubKeyXY <$> newForeignPtr finalizerFree outBuf  -instance Hashable Tweak where-    i `hashWithSalt` t = i `hashWithSalt` getTweak t+-- | Compute a shared secret using ECDH and SHA256. This algorithm uses your own 'SecKey', your counterparty's 'PubKeyXY'+-- and results in a 32 byte SHA256 Digest.+ecdh :: SecKey -> PubKeyXY -> Digest SHA256+ecdh SecKey{..} PubKeyXY{..} = unsafePerformIO . evalContT $ do+    outBuf <- lift (mallocBytes 32)+    sk <- ContT (withForeignPtr secKeyFPtr)+    pk <- ContT (withForeignPtr pubKeyXYFPtr)+    ret <- lift (Prim.ecdh ctx outBuf pk sk Prim.ecdhHashFunctionSha256 nullPtr)+    if isSuccess ret+        then do+            bs <- lift $ unsafePackByteString (outBuf, 32)+            let Just digest = digestFromByteString bs+            pure digest+        else lift (free outBuf) *> error "Bug: Invalid Scalar or Overflow"  -instance Read Tweak where-    readPrec = parens $ do-        String str <- lexP-        maybe pfail return $ tweak =<< decodeHex str+-- -- | Add 'Tweak' to 'SecKey'.+ecSecKeyTweakAdd :: SecKey -> Tweak -> Maybe SecKey+ecSecKeyTweakAdd SecKey{..} Tweak{..} = unsafePerformIO . evalContT $ do+    skPtr <- ContT (withForeignPtr secKeyFPtr)+    skOut <- lift (mallocBytes 32)+    lift (memcpy skOut skPtr 32)+    twkPtr <- ContT (withForeignPtr tweakFPtr)+    ret <- lift (Prim.ecSeckeyTweakAdd ctx skOut twkPtr)+    lift $+        if isSuccess ret+            then Just . SecKey <$> newForeignPtr finalizerFree skOut+            else free skOut $> Nothing  -instance IsString Tweak where-    fromString = fromMaybe e . (tweak <=< decodeHex)-        where-            e = error "Could not decode tweak from hex string"+-- | Multiply 'SecKey' by 'Tweak'.+ecSecKeyTweakMul :: SecKey -> Tweak -> Maybe SecKey+ecSecKeyTweakMul SecKey{..} Tweak{..} = unsafePerformIO . evalContT $ do+    skPtr <- ContT (withForeignPtr secKeyFPtr)+    skOut <- lift (mallocBytes 32)+    lift (memcpy skOut skPtr 32)+    twkPtr <- ContT (withForeignPtr tweakFPtr)+    ret <- lift (Prim.ecSeckeyTweakMul ctx skOut twkPtr)+    lift $+        if isSuccess ret+            then Just . SecKey <$> newForeignPtr finalizerFree skOut+            else free skOut $> Nothing  -instance Show Tweak where-    showsPrec _ = shows . B16.encodeBase16 . getTweak+-- | Compute 'KeyPair' structure from 'SecKey'+keyPairCreate :: SecKey -> KeyPair+keyPairCreate SecKey{..} = unsafePerformIO $ do+    keyPairBuf <- mallocBytes 96+    ret <- withForeignPtr secKeyFPtr $ Prim.keypairCreate ctx keyPairBuf+    unless (isSuccess ret) $ do+        free keyPairBuf+        error "Bug: Invalid SecKey Constructed"+    KeyPair <$> newForeignPtr finalizerFree keyPairBuf  --- | Import 32-byte 'ByteString' as 'Msg'.-msg :: ByteString -> Maybe Msg-msg bs-    | BS.length bs == 32 = Just (Msg bs)-    | otherwise = Nothing+-- | Project 'PubKeyXY' from 'KeyPair'+keyPairPubKeyXY :: KeyPair -> PubKeyXY+keyPairPubKeyXY KeyPair{..} = unsafePerformIO $ do+    pubKeyBuf <- mallocBytes 64+    ret <- withForeignPtr keyPairFPtr $ Prim.keypairPub ctx pubKeyBuf+    unless (isSuccess ret) $ do+        free pubKeyBuf+        error "Bug: Invalid KeyPair Constructed"+    PubKeyXY <$> newForeignPtr finalizerFree pubKeyBuf  --- | Import 32-byte 'ByteString' as 'SecKey'.-secKey :: ByteString -> Maybe SecKey-secKey bs-    | BS.length bs == 32 = Just (SecKey bs)-    | otherwise = Nothing+-- | Project 'SecKey' from 'KeyPair'+keyPairSecKey :: KeyPair -> SecKey+keyPairSecKey KeyPair{..} = unsafePerformIO $ do+    secKeyBuf <- mallocBytes 32+    ret <- withForeignPtr keyPairFPtr $ Prim.keypairSec ctx secKeyBuf+    unless (isSuccess ret) $ do+        free secKeyBuf+        error "Bug: Invalid KeyPair Constructed"+    SecKey <$> newForeignPtr finalizerFree secKeyBuf  -compactSig :: ByteString -> Maybe CompactSig-compactSig bs-    | BS.length bs == 64 = Just (CompactSig bs)-    | otherwise = Nothing+-- | Project 'PubKeyXO' from 'KeyPair' as well as parity bit. @True@ indicates that the public key is the same as it+-- would be if you had serialized the 'PubKeyXO' and it was prefixed with 'Prim.flagsTagPubkeyOdd'. @False@ indicates+-- it would be prefixed by 'Prim.flagsTagPubkeyEven'+keyPairPubKeyXO :: KeyPair -> (PubKeyXO, Bool)+keyPairPubKeyXO KeyPair{..} = unsafePerformIO $ do+    pubKeyBuf <- mallocBytes 64+    parityPtr <- malloc+    ret <- withForeignPtr keyPairFPtr $ Prim.keypairXonlyPub ctx pubKeyBuf parityPtr+    unless (isSuccess ret) $ do+        free pubKeyBuf+        free parityPtr+        error "Bug: Invalid KeyPair Constructed"+    parity <- peek parityPtr+    negated <- case parity of+        0 -> pure False+        1 -> pure True+        _ -> do+            free pubKeyBuf+            free parityPtr+            error "Bug: Invalid pk_parity result from Prim"+    (,negated) . PubKeyXO <$> newForeignPtr finalizerFree pubKeyBuf  --- | Convert signature to a normalized lower-S form. 'Nothing' indicates that it--- was already normal.-normalizeSig :: Sig -> Maybe Sig-normalizeSig (Sig sig) = unsafePerformIO $-    Prim.unsafeUseByteString sig $ \(sig_in, _) -> do-        sig_out <- mallocBytes 64-        ret <- Prim.ecdsaSignatureNormalize Prim.ctx sig_out sig_in-        if Prim.isSuccess ret-            then do-                bs <- Prim.unsafePackByteString (sig_out, 64)-                return (Just (Sig bs))-            else do-                free sig_out-                return Nothing+-- | Tweak a 'KeyPair' with a 'Tweak'. If the resulting 'KeyPair' is invalid (0, Infinity), then the result is @Nothing@+keyPairPubKeyXOTweakAdd :: KeyPair -> Tweak -> Maybe KeyPair+keyPairPubKeyXOTweakAdd KeyPair{..} Tweak{..} = unsafePerformIO . evalContT $ do+    keyPairPtr <- ContT (withForeignPtr keyPairFPtr)+    tweakPtr <- ContT (withForeignPtr tweakFPtr)+    lift $ do+        keyPairOut <- (mallocBytes 96)+        _ <- (memcpy keyPairOut keyPairPtr 96)+        ret <- Prim.keypairXonlyTweakAdd ctx keyPairOut tweakPtr+        if isSuccess ret+            then Just . KeyPair <$> newForeignPtr finalizerFree keyPairOut+            else free keyPairOut $> Nothing  --- | 32-Byte 'ByteString' as 'Tweak'.-tweak :: ByteString -> Maybe Tweak-tweak bs-    | BS.length bs == 32 = Just (Tweak bs)-    | otherwise = Nothing+-- | Compute a schnorr signature using a 'KeyPair'. The @ByteString@ must be 32 bytes long to get a @Just@ out of this+-- function+schnorrSign :: KeyPair -> ByteString -> Maybe Signature+schnorrSign KeyPair{..} bs+    | BS.length bs /= 32 = Nothing+    | otherwise = unsafePerformIO . evalContT $ do+        (msgHashPtr, _) <- ContT (unsafeUseByteString bs)+        keyPairPtr <- ContT (withForeignPtr keyPairFPtr)+        lift $ do+            sigBuf <- mallocBytes 64+            -- TODO: provide randomness here instead of supplying a null pointer+            ret <- Prim.schnorrsigSign ctx sigBuf msgHashPtr keyPairPtr nullPtr+            if isSuccess ret+                then Just . Signature <$> newForeignPtr finalizerFree sigBuf+                else free sigBuf $> Nothing  --- | Import DER-encoded public key.-importPubKey :: ByteString -> Maybe PubKey-importPubKey bs-    | BS.null bs = Nothing-    | otherwise = unsafePerformIO $-        Prim.unsafeUseByteString bs $ \(input, len) -> do-            pub_key <- mallocBytes 64-            ret <- Prim.ecPubkeyParse Prim.ctx pub_key input len-            if Prim.isSuccess ret-                then do-                    out <- Prim.unsafePackByteString (pub_key, 64)-                    return (Just (PubKey out))-                else do-                    free pub_key-                    return Nothing+-- | Extra parameters object for alternative nonce generation+data SchnorrExtra a = Storable a =>+    SchnorrExtra+    { schnorrExtraNonceFunHardened :: ByteString -> SecKey -> PubKeyXO -> ByteString -> a -> Maybe (SizedByteArray 32 ByteString)+    , schnorrExtraData :: a+    }  --- | Encode public key as DER. First argument 'True' for compressed output.-exportPubKey :: Bool -> PubKey -> ByteString-exportPubKey compress (PubKey in_bs) = unsafePerformIO $-    Prim.unsafeUseByteString in_bs $ \(in_ptr, _) ->-        alloca $ \len_ptr ->-            allocaBytes len $ \out_ptr -> do-                poke len_ptr $ fromIntegral len-                ret <- Prim.ecPubkeySerialize Prim.ctx out_ptr len_ptr in_ptr flags-                unless (Prim.isSuccess ret) $ error "could not serialize public key"-                final_len <- peek len_ptr-                Prim.packByteString (out_ptr, final_len)+-- | Compute a schnorr signature with an alternative scheme for generating nonces, it is not recommended you use this+-- unless you know what you are doing. Instead, favor the usage of 'schnorrSign'+schnorrSignCustom :: forall a. KeyPair -> ByteString -> SchnorrExtra a -> Maybe Signature+schnorrSignCustom KeyPair{..} msg SchnorrExtra{..} = unsafePerformIO . evalContT $ do+    (msgPtr, msgLen) <- ContT (unsafeUseByteString msg)+    keyPairPtr <- ContT (withForeignPtr keyPairFPtr)+    lift $ do+        sigBuf <- mallocBytes 64+        -- convert fn into funptr+        funptr <- mkNonceFunHardened primFn+        -- allocate memory for extra data ptr+        dataptr <- malloc+        -- copy data to new pointer+        poke dataptr schnorrExtraData+        -- allocate extraparams structure+        extraPtr <- mallocBytes (4 + sizeOf funptr + sizeOf dataptr)+        -- fill magic+        pokeByteOff extraPtr 0 (0xDA :: Word8)+        pokeByteOff extraPtr 1 (0x6F :: Word8)+        pokeByteOff extraPtr 2 (0xB3 :: Word8)+        pokeByteOff extraPtr 3 (0x8C :: Word8)+        -- fill funptr+        pokeByteOff extraPtr 4 funptr+        -- fill dataptr+        pokeByteOff extraPtr (4 + sizeOf funptr) dataptr+        ret <- Prim.schnorrsigSignCustom ctx sigBuf msgPtr msgLen keyPairPtr extraPtr+        freeHaskellFunPtr funptr+        free dataptr+        free extraPtr+        if isSuccess ret+            then Just . Signature <$> newForeignPtr finalizerFree sigBuf+            else free sigBuf $> Nothing     where-        len = if compress then 33 else 65-        flags = if compress then Prim.compressed else Prim.uncompressed---exportCompactSig :: Sig -> CompactSig-exportCompactSig (Sig sig_bs) = unsafePerformIO $-    Prim.unsafeUseByteString sig_bs $ \(sig_ptr, _) -> do-        out_ptr <- mallocBytes 64-        ret <- Prim.ecdsaSignatureSerializeCompact Prim.ctx out_ptr sig_ptr-        unless (Prim.isSuccess ret) $ do-            free out_ptr-            error "Could not obtain compact signature"-        out_bs <- Prim.unsafePackByteString (out_ptr, 64)-        return $ CompactSig out_bs---importCompactSig :: CompactSig -> Maybe Sig-importCompactSig (CompactSig compact_sig) = unsafePerformIO $-    Prim.unsafeUseByteString compact_sig $ \(compact_ptr, _) -> do-        out_sig <- mallocBytes 64-        ret <- Prim.ecdsaSignatureParseCompact Prim.ctx out_sig compact_ptr-        if Prim.isSuccess ret-            then do-                out_bs <- Prim.unsafePackByteString (out_sig, 64)-                return (Just (Sig out_bs))-            else do-                free out_sig-                return Nothing----- | Import DER-encoded signature.-importSig :: ByteString -> Maybe Sig-importSig bs-    | BS.null bs = Nothing-    | otherwise = unsafePerformIO $-        Prim.unsafeUseByteString bs $ \(in_ptr, in_len) -> do-            out_sig <- mallocBytes 64-            ret <- Prim.ecdsaSignatureParseDer Prim.ctx out_sig in_ptr in_len-            if Prim.isSuccess ret-                then do-                    out_bs <- Prim.unsafePackByteString (out_sig, 64)-                    return (Just (Sig out_bs))-                else do-                    free out_sig-                    return Nothing----- | Encode signature as strict DER.-exportSig :: Sig -> ByteString-exportSig (Sig in_sig) = unsafePerformIO $-    Prim.unsafeUseByteString in_sig $ \(in_ptr, _) ->-        alloca $ \out_len ->-            allocaBytes 72 $ \out_ptr -> do-                poke out_len 72-                ret <- Prim.ecdsaSignatureSerializeDer Prim.ctx out_ptr out_len in_ptr-                unless (Prim.isSuccess ret) $ error "could not serialize signature"-                final_len <- peek out_len-                Prim.packByteString (out_ptr, final_len)+        primFn :: Storable a => Prim.NonceFunHardened a+        primFn outBuf msgPtr msgLen sk xopk algo algolen dataPtr = do+            msg <- unsafePackByteString (msgPtr, msgLen)+            sk <- SecKey <$> newForeignPtr_ (castPtr sk)+            xopk <- PubKeyXO <$> newForeignPtr_ (castPtr xopk)+            algo <- unsafePackByteString (algo, algolen)+            extra <- peek dataPtr+            case schnorrExtraNonceFunHardened msg sk xopk algo extra of+                Nothing -> pure 0+                Just bs -> evalContT $ do+                    (hashPtr, _) <- ContT (unsafeUseByteString (unSizedByteArray bs))+                    lift (memcpy outBuf hashPtr 32)+                    pure 1  --- | Verify message signature. 'True' means that the signature is correct.-verifySig :: PubKey -> Sig -> Msg -> Bool-verifySig (PubKey pub_key) (Sig sig) (Msg m) = unsafePerformIO $-    Prim.unsafeUseByteString pub_key $ \(pub_key_ptr, _) ->-        Prim.unsafeUseByteString sig $ \(sig_ptr, _) ->-            Prim.unsafeUseByteString m $ \(msg_ptr, _) ->-                Prim.isSuccess <$> Prim.ecdsaVerify Prim.ctx sig_ptr msg_ptr pub_key_ptr+-- | Verify the authenticity of a schnorr signature. @True@ means the 'Signature' is correct.+schnorrVerify :: PubKeyXO -> ByteString -> Signature -> Bool+schnorrVerify PubKeyXO{..} bs Signature{..} = unsafePerformIO . evalContT $ do+    pubKeyPtr <- ContT (withForeignPtr pubKeyXOFPtr)+    signaturePtr <- ContT (withForeignPtr signatureFPtr)+    (msgPtr, msgLen) <- ContT (unsafeUseByteString bs)+    lift $ isSuccess <$> Prim.schnorrsigSignVerify ctx signaturePtr msgPtr msgLen pubKeyPtr  -signMsg :: SecKey -> Msg -> Sig-signMsg (SecKey sec_key) (Msg m) = unsafePerformIO $-    Prim.unsafeUseByteString sec_key $ \(sec_key_ptr, _) ->-        Prim.unsafeUseByteString m $ \(msg_ptr, _) -> do-            sig_ptr <- mallocBytes 64-            ret <- Prim.ecdsaSign Prim.ctx sig_ptr msg_ptr sec_key_ptr nullFunPtr nullPtr-            unless (Prim.isSuccess ret) $ do-                free sig_ptr-                error "could not sign message"-            Sig <$> Prim.unsafePackByteString (sig_ptr, 64)+-- | Generate a tagged sha256 digest as specified in BIP340+taggedSha256 :: ByteString -> ByteString -> Digest SHA256+taggedSha256 tag msg = unsafePerformIO . evalContT $ do+    (tagBuf, tagLen) <- ContT (unsafeUseByteString tag)+    (msgBuf, msgLen) <- ContT (unsafeUseByteString msg)+    lift $ do+        hashBuf <- mallocBytes 32+        ret <- Prim.taggedSha256 ctx hashBuf tagBuf tagLen msgBuf msgLen+        unless (isSuccess ret) $ do+            free hashBuf+            error "Bug: Invalid use of C Lib"+        bs <- unsafePackByteString (hashBuf, 32)+        let Just digest = digestFromByteString bs+        pure digest  -derivePubKey :: SecKey -> PubKey-derivePubKey (SecKey sec_key) = unsafePerformIO $-    Prim.unsafeUseByteString sec_key $ \(sec_key_ptr, _) -> do-        pub_key_ptr <- mallocBytes 64-        ret <- Prim.ecPubkeyCreate Prim.ctx pub_key_ptr sec_key_ptr-        unless (Prim.isSuccess ret) $ do-            free pub_key_ptr-            error "could not compute public key"-        PubKey <$> Prim.unsafePackByteString (pub_key_ptr, 64)+-- | Combine a list of 'PubKeyXY's into a single 'PubKeyXY'. This will result in @Nothing@ if the group operation results+-- in the Point at Infinity+pubKeyCombine :: [PubKeyXY] -> Maybe PubKeyXY+pubKeyCombine keys = unsafePerformIO $ do+    let n = length keys+    keysBuf <- mallocBytes (64 * n)+    for_ (zip [0 ..] keys) $ \(i, PubKeyXY{..}) ->+        withForeignPtr pubKeyXYFPtr $ pokeElemOff keysBuf i+    outBuf <- mallocBytes 64+    ret <- Prim.ecPubkeyCombine ctx outBuf keysBuf (fromIntegral n)+    if isSuccess ret+        then Just . PubKeyXY <$> newForeignPtr finalizerFree outBuf+        else free outBuf $> Nothing  --- | Add tweak to secret key.-tweakAddSecKey :: SecKey -> Tweak -> Maybe SecKey-tweakAddSecKey (SecKey sec_key) (Tweak t) = unsafePerformIO $-    Prim.unsafeUseByteString new_bs $ \(sec_key_ptr, _) ->-        Prim.unsafeUseByteString t $ \(tweak_ptr, _) -> do-            ret <- Prim.ecSeckeyTweakAdd Prim.ctx sec_key_ptr tweak_ptr-            if Prim.isSuccess ret-                then return (Just (SecKey new_bs))-                else return Nothing-    where-        new_bs = BS.copy sec_key+-- | Negate a 'PubKeyXY'+pubKeyNegate :: PubKeyXY -> PubKeyXY+pubKeyNegate PubKeyXY{..} = unsafePerformIO $ do+    outBuf <- mallocBytes 64+    withForeignPtr pubKeyXYFPtr $ flip (memcpy outBuf) 64+    _ret <- Prim.ecPubkeyNegate ctx outBuf+    PubKeyXY <$> newForeignPtr finalizerFree outBuf  --- | Multiply secret key by tweak.-tweakMulSecKey :: SecKey -> Tweak -> Maybe SecKey-tweakMulSecKey (SecKey sec_key) (Tweak t) = unsafePerformIO $-    Prim.unsafeUseByteString new_bs $ \(sec_key_ptr, _) ->-        Prim.unsafeUseByteString t $ \(tweak_ptr, _) -> do-            ret <- Prim.ecSeckeyTweakMul Prim.ctx sec_key_ptr tweak_ptr-            if Prim.isSuccess ret-                then return (Just (SecKey new_bs))-                else return Nothing-    where-        new_bs = BS.copy sec_key+-- | Add 'Tweak' to 'PubKeyXY'. This will result in @Nothing@ if the group operation results in the Point at Infinity+pubKeyTweakAdd :: PubKeyXY -> Tweak -> Maybe PubKeyXY+pubKeyTweakAdd PubKeyXY{..} Tweak{..} = unsafePerformIO . evalContT $ do+    pubKeyPtr <- ContT (withForeignPtr pubKeyXYFPtr)+    tweakPtr <- ContT (withForeignPtr tweakFPtr)+    lift $ do+        pubKeyOutBuf <- mallocBytes 64+        memcpy pubKeyOutBuf pubKeyPtr 64+        ret <- Prim.ecPubkeyTweakAdd ctx pubKeyOutBuf tweakPtr+        if isSuccess ret+            then Just . PubKeyXY <$> newForeignPtr finalizerFree pubKeyOutBuf+            else free pubKeyOutBuf $> Nothing  --- | Add tweak to public key. Tweak is multiplied first by G to obtain a point.-tweakAddPubKey :: PubKey -> Tweak -> Maybe PubKey-tweakAddPubKey (PubKey pub_key) (Tweak t) = unsafePerformIO $-    Prim.unsafeUseByteString new_bs $ \(pub_key_ptr, _) ->-        Prim.unsafeUseByteString t $ \(tweak_ptr, _) -> do-            ret <- Prim.ecPubkeyTweakAdd Prim.ctx pub_key_ptr tweak_ptr-            if Prim.isSuccess ret-                then return (Just (PubKey new_bs))-                else return Nothing-    where-        new_bs = BS.copy pub_key+-- | Multiply 'PubKeyXY' by 'Tweak'. This will result in @Nothing@ if the group operation results in the Point at Infinity+pubKeyTweakMul :: PubKeyXY -> Tweak -> Maybe PubKeyXY+pubKeyTweakMul PubKeyXY{..} Tweak{..} = unsafePerformIO . evalContT $ do+    pubKeyPtr <- ContT (withForeignPtr pubKeyXYFPtr)+    tweakPtr <- ContT (withForeignPtr tweakFPtr)+    lift $ do+        pubKeyOutBuf <- mallocBytes 64+        memcpy pubKeyOutBuf pubKeyPtr 64+        ret <- Prim.ecPubkeyTweakMul ctx pubKeyOutBuf tweakPtr+        if isSuccess ret+            then Just . PubKeyXY <$> newForeignPtr finalizerFree pubKeyOutBuf+            else free pubKeyOutBuf $> Nothing  --- | Multiply public key by tweak. Tweak is multiplied first by G to obtain a--- point.-tweakMulPubKey :: PubKey -> Tweak -> Maybe PubKey-tweakMulPubKey (PubKey pub_key) (Tweak t) = unsafePerformIO $-    Prim.unsafeUseByteString new_bs $ \(pub_key_ptr, _) ->-        Prim.unsafeUseByteString t $ \(tweak_ptr, _) -> do-            ret <- Prim.ecPubkeyTweakMul Prim.ctx pub_key_ptr tweak_ptr-            if Prim.isSuccess ret-                then return (Just (PubKey new_bs))-                else return Nothing-    where-        new_bs = BS.copy pub_key+-- | Negate a 'SecKey'+secKeyNegate :: SecKey -> SecKey+secKeyNegate SecKey{..} = unsafePerformIO $ do+    outBuf <- mallocBytes 32+    withForeignPtr secKeyFPtr $ flip (memcpy outBuf) 32+    _ret <- Prim.ecSeckeyNegate ctx outBuf+    SecKey <$> newForeignPtr finalizerFree outBuf  --- | Add multiple public keys together.-combinePubKeys :: [PubKey] -> Maybe PubKey-combinePubKeys [] = Nothing-combinePubKeys pubs = unsafePerformIO $-    pointers [] pubs $ \ps ->-        allocaArray (length ps) $ \a -> do-            out <- mallocBytes 64-            pokeArray a ps-            ret <- Prim.ecPubkeyCombine Prim.ctx out a (fromIntegral $ length ps)-            if Prim.isSuccess ret-                then do-                    bs <- Prim.unsafePackByteString (out, 64)-                    return (Just (PubKey bs))-                else do-                    free out-                    return Nothing-    where-        pointers ps [] f = f ps-        pointers ps (PubKey pub_key : pub_keys) f =-            Prim.unsafeUseByteString pub_key $ \(p, _) ->-                pointers (p : ps) pub_keys f+-- | Convert 'PubKeyXY' to 'PubKeyXO'. See 'keyPairPubKeyXO' for more information on how to interpret the parity bit.+xyToXO :: PubKeyXY -> (PubKeyXO, Bool)+xyToXO PubKeyXY{..} = unsafePerformIO $ do+    outBuf <- mallocBytes 64+    parityPtr <- malloc+    ret <- withForeignPtr pubKeyXYFPtr $ Prim.xonlyPubkeyFromPubkey ctx outBuf parityPtr+    unless (isSuccess ret) $ do+        free outBuf+        error "Bug: Couldn't convert xy to xo"+    parity <- peek parityPtr+    negated <- case parity of+        0 -> pure False+        1 -> pure True+        _ -> free outBuf *> error "Bug: Invalid pk_parity from Prim"+    (,negated) . PubKeyXO <$> newForeignPtr finalizerFree outBuf  -instance Arbitrary Msg where-    arbitrary = gen_msg-        where-            valid_bs = bs_gen `suchThat` isJust-            bs_gen = msg . BS.pack <$> replicateM 32 arbitraryBoundedRandom-            gen_msg = fromJust <$> valid_bs+-- | Add 'Tweak' to 'PubKeyXO'. This will result in @Nothing@ if the group operation results in the Point at Infinity+pubKeyXOTweakAdd :: PubKeyXO -> Tweak -> Maybe PubKeyXY+pubKeyXOTweakAdd PubKeyXO{..} Tweak{..} = unsafePerformIO . evalContT $ do+    pubKeyXOPtr <- ContT (withForeignPtr pubKeyXOFPtr)+    tweakPtr <- ContT (withForeignPtr tweakFPtr)+    lift $ do+        outBuf <- mallocBytes 64+        ret <- Prim.xonlyPubkeyTweakAdd ctx outBuf pubKeyXOPtr tweakPtr+        if isSuccess ret+            then Just . PubKeyXY <$> newForeignPtr finalizerFree outBuf+            else free outBuf $> Nothing  -instance Arbitrary SecKey where-    arbitrary = gen_key-        where-            valid_bs = bs_gen `suchThat` isJust-            bs_gen = secKey . BS.pack <$> replicateM 32 arbitraryBoundedRandom-            gen_key = fromJust <$> valid_bs+-- | Check that a 'PubKeyXO' is the result of the specified tweak operation. @True@ means it was.+pubKeyXOTweakAddCheck :: PubKeyXO -> Bool -> PubKeyXO -> Tweak -> Bool+pubKeyXOTweakAddCheck PubKeyXO{pubKeyXOFPtr = tweakedFPtr} parity PubKeyXO{pubKeyXOFPtr = origFPtr} Tweak{..} =+    unsafePerformIO . evalContT $ do+        tweakedPtr <- ContT (withForeignPtr tweakedFPtr)+        origPtr <- ContT (withForeignPtr origFPtr)+        tweakPtr <- ContT (withForeignPtr tweakFPtr)+        let parityInt = if parity then 1 else 0+        lift $ isSuccess <$> Prim.xonlyPubkeyTweakAddCheck ctx tweakedPtr parityInt origPtr tweakPtr  -instance Arbitrary PubKey where-    arbitrary = derivePubKey <$> arbitrary+foreign import ccall "wrapper"+    mkNonceFunHardened :: Prim.NonceFunHardened a -> IO (FunPtr (Prim.NonceFunHardened a))
+ src/Crypto/Secp256k1/Internal.hs view
@@ -0,0 +1,36 @@+module Crypto.Secp256k1.Internal where++import Crypto.Secp256k1.Prim+import Data.ByteString (ByteString)+import qualified Data.ByteString as BS+import qualified Data.ByteString.Unsafe as BU+import Foreign (Ptr, castPtr)+import Foreign.C (CSize)+++unsafeUseByteString :: ByteString -> ((Ptr a, CSize) -> IO b) -> IO b+unsafeUseByteString bs f =+    BU.unsafeUseAsCStringLen bs $ \(b, l) ->+        f (castPtr b, fromIntegral l)+++useByteString :: ByteString -> ((Ptr a, CSize) -> IO b) -> IO b+useByteString bs f =+    BS.useAsCStringLen bs $ \(b, l) ->+        f (castPtr b, fromIntegral l)+++unsafePackByteString :: (Ptr a, CSize) -> IO ByteString+unsafePackByteString (b, l) =+    BU.unsafePackMallocCStringLen (castPtr b, fromIntegral l)+++packByteString :: (Ptr a, CSize) -> IO ByteString+packByteString (b, l) =+    BS.packCStringLen (castPtr b, fromIntegral l)+++isSuccess :: Ret -> Bool+isSuccess 0 = False+isSuccess 1 = True+isSuccess n = error $ "isSuccess expected 0 or 1 but got " ++ show n
src/Crypto/Secp256k1/Prim.hs view
@@ -1,4 +1,6 @@ {-# LANGUAGE DataKinds #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE RankNTypes #-} @@ -16,7 +18,7 @@ import Data.ByteString (ByteString) import qualified Data.ByteString as BS import qualified Data.ByteString.Unsafe as BU-import Foreign (FunPtr, Ptr, castPtr)+import Foreign (Bits (..), FunPtr, Ptr, castPtr) import Foreign.C (     CInt (..),     CSize (..),@@ -28,68 +30,176 @@ import System.IO.Unsafe (unsafePerformIO)  -type Ctx = Ptr LCtx-type CtxFlags = CUInt-type SerFlags = CUInt+-- | Return type of C Lib functions type Ret = CInt  -verify :: CtxFlags-verify = 0x0101+type ContextFlags = CUInt+type CompressionFlags = CUInt+type PubkeyFlags = CUInt  -sign :: CtxFlags-sign = 0x0201+-- * Flags  -signVerify :: CtxFlags-signVerify = 0x0301+-- ** Flag Types  -compressed :: SerFlags-compressed = 0x0102+-- $flagTypes All flags' lower 8 bits indicate what they're for. Do not use directly.  -uncompressed :: SerFlags-uncompressed = 0x0002+-- | Mask to isolate the type of flags+flagsTypeMask :: CUInt+flagsTypeMask = (1 `shiftL` 8) - 1+{-# DEPRECATED flagsTypeMask "Do not use Flag Types directly" #-}  -isSuccess :: Ret -> Bool-isSuccess 0 = False-isSuccess 1 = True-isSuccess n = error $ "isSuccess expected 0 or 1 but got " ++ show n+-- | This bit indicates that the flags are to be used to initialize context+flagsTypeContext :: ContextFlags+flagsTypeContext = 1 `shiftL` 0+{-# DEPRECATED flagsTypeContext "Do not use Flag Types directly" #-}  -unsafeUseByteString :: ByteString -> ((Ptr a, CSize) -> IO b) -> IO b-unsafeUseByteString bs f =-    BU.unsafeUseAsCStringLen bs $ \(b, l) ->-        f (castPtr b, fromIntegral l)+-- | This bit indicates that the flags are to be used to assess compression+flagsTypeCompression :: CompressionFlags+flagsTypeCompression = 1 `shiftL` 1+{-# DEPRECATED flagsTypeCompression "Do not use Flag Types directly" #-}  -useByteString :: ByteString -> ((Ptr a, CSize) -> IO b) -> IO b-useByteString bs f =-    BS.useAsCStringLen bs $ \(b, l) ->-        f (castPtr b, fromIntegral l)+-- ** Flag Operations  -unsafePackByteString :: (Ptr a, CSize) -> IO ByteString-unsafePackByteString (b, l) =-    BU.unsafePackMallocCStringLen (castPtr b, fromIntegral l)+-- $flagOperations+-- The higher bits contain the actual data. Do not use directly. */  -packByteString :: (Ptr a, CSize) -> IO ByteString-packByteString (b, l) =-    BS.packCStringLen (castPtr b, fromIntegral l)+-- | This bit indicates that the context should be initialized for verification+flagsBitContextVerify :: ContextFlags+flagsBitContextVerify = 1 `shiftL` 8+{-# DEPRECATED flagsBitContextVerify "Do not use Flag Operations directly" #-}  -ctx :: Ctx-ctx = unsafePerformIO $ contextCreate signVerify-{-# NOINLINE ctx #-}+-- | This bit indicates that the context should be initialized for signing+flagsBitContextSign :: ContextFlags+flagsBitContextSign = 1 `shiftL` 9+{-# DEPRECATED flagsBitContextSign "Do not use Flag Operations directly" #-}  +-- | This bit indicates that the context should be initialized for declassification+flagsBitContextDeclassify :: ContextFlags+flagsBitContextDeclassify = 1 `shiftL` 10+{-# DEPRECATED flagsBitContextDeclassify "Do not use Flag Operations directly" #-}+++-- | This bit indicates that things should be serialized in a compressed format+flagsBitCompression :: CompressionFlags+flagsBitCompression = 1 `shiftL` 8+{-# DEPRECATED flagsBitCompression "Do not use Flag Operations directly" #-}+++-- ** Composite Flags+++-- *** Context Initialization Flags+++-- $ciFlags+-- Flags to pass to 'contextCreate', 'contextPreallocatedSize', and 'contextPreallocatedCreate'.+++-- | Initialize context for verification+flagsContextVerify :: ContextFlags+flagsContextVerify = flagsTypeContext .|. flagsBitContextVerify+++-- | Initialize context for signing+flagsContextSign :: ContextFlags+flagsContextSign = flagsTypeContext .|. flagsBitContextSign+++-- | Initialize context for declassifying+flagsContextDeclassify :: ContextFlags+flagsContextDeclassify = flagsTypeContext .|. flagsBitContextDeclassify+++-- | Initialize context for primitive operations+flagsContextNone :: ContextFlags+flagsContextNone = flagsTypeContext+++-- *** Pubkey Serialization Flags+++-- $psFlags+-- Flags to pass to 'ecPubkeySerialize'.+++-- | Serialize EC keys compressed+flagsEcCompressed :: CompressionFlags+flagsEcCompressed = flagsTypeCompression .|. flagsBitCompression+++-- | Serialize EC keys uncompressed+flagsEcUncompressed :: CompressionFlags+flagsEcUncompressed = flagsTypeCompression+++-- *** Pubkey Tags+++-- $pkTags+-- Prefix byte used to tag various encoded curvepoints for specific purposes+++-- | Pubkey is even+flagsTagPubkeyEven :: PubkeyFlags+flagsTagPubkeyEven = 0x02+++-- | Pubkey is odd+flagsTagPubkeyOdd :: PubkeyFlags+flagsTagPubkeyOdd = 0x03+++-- | Pubkey is uncompressed+flagsTagPubkeyUncompressed :: PubkeyFlags+flagsTagPubkeyUncompressed = 0x04+++-- | Pubkey is even and uncompressed+flagsTagPubkeyHybridEven :: PubkeyFlags+flagsTagPubkeyHybridEven = flagsTagPubkeyEven .|. flagsTagPubkeyUncompressed+++-- | Pubkey is odd and uncompressed+flagsTagPubkeyHybridOdd :: PubkeyFlags+flagsTagPubkeyHybridOdd = flagsTagPubkeyOdd .|. flagsTagPubkeyUncompressed++ -- * Context Operations  +-- | Opaque data structure that holds context information (precomputed tables etc.).+--+--  The purpose of context structures is to cache large precomputed data tables+--  that are expensive to construct, and also to maintain the randomization data+--  for blinding.+--+--  Do not create a new context object for each operation, as construction is+--  far slower than all other API calls (~100 times slower than an ECDSA+--  verification).+--+--  A constructed context can safely be used from multiple threads+--  simultaneously, but API calls that take a non-const pointer to a context+--  need exclusive access to it. In particular this is the case for+--  'contextDestroy', 'contextPreallocatedDestroy',+--  and 'contextRandomize'.+--+--  Regarding randomization, either do it once at creation time (in which case+--  you do not need any locking for the other calls), or use a read-write lock.+type Ctx = Ptr LCtx++ -- | Updates the context randomization to protect against side-channel leakage. -- -- While secp256k1 code is written to be constant-time no matter what secret@@ -146,7 +256,7 @@ foreign import ccall safe "secp256k1.h secp256k1_context_create"     contextCreate ::         -- | __Input:__ which parts of the context to initialize.-        CtxFlags ->+        ContextFlags ->         -- | __Returns:__ a newly created context object.         IO Ctx @@ -171,7 +281,7 @@   -- $preallocated--- functions in this secion are intended for settings in which it+-- Functions in this secion are intended for settings in which it -- is not possible or desirable to rely on dynamic memory allocation. It provides -- functions for creating, cloning, and destroying secp256k1 context objects in a -- contiguous fixed-size block of memory provided by the caller.@@ -340,8 +450,10 @@ --  USE_EXTERNAL_DEFAULT_CALLBACKS is defined, which is the case if the build --  has been configured with @--enable-external-default-callbacks@. Then the --  following two symbols must be provided to link against:---   - void secp256k1_default_illegal_callback_fn(const char* message, void* data);---   - void secp256k1_default_error_callback_fn(const char* message, void* data);+--+--   - @void secp256k1_default_illegal_callback_fn(const char* message, void* data);@+--   - @void secp256k1_default_error_callback_fn(const char* message, void* data);@+-- --  The library can call these default handlers even before a proper callback data --  pointer could have been set using 'contextSetIllegalCallback' or --  'contextSetErrorCallback', e.g., when the creation of a context@@ -393,8 +505,8 @@  -- | An implementation of SHA256 hash function that applies to compressed public key. -- Populates the output parameter with 32 bytes.-foreign import ccall safe "secp256k1.h &secp256k1_ecdh_hash_sha256"-    ecdhHashSha256 :: FunPtr (EcdhHashFun a)+foreign import ccall safe "secp256k1.h &secp256k1_ecdh_hash_function_sha256"+    ecdhHashFunctionSha256 :: FunPtr (EcdhHashFun a)   -- * ECDSA@@ -462,35 +574,35 @@ -- | Serialize an ECDSA signature in compact format (64 bytes + recovery id). foreign import ccall safe "secp256k1.h secp256k1_ecdsa_recoverable_signature_serialize_compact"     ecdsaRecoverableSignatureSerializeCompact ::-        --  Args: ctx:      a secp256k1 context object+        -- | a secp256k1 context object         Ctx ->-        --  Out:  output64: a pointer to a 64-byte array of the compact signature (cannot be NULL)+        -- | __Output:__ a pointer to a 64-byte array of the compact signature (cannot be NULL)         Ptr (Bytes 64) ->-        --        recid:    a pointer to an integer to hold the recovery id (can be NULL).+        -- | __Output:__ a pointer to an integer to hold the recovery id (can be NULL).         Ptr CInt ->-        --  In:   sig:      a pointer to an initialized signature object (cannot be NULL)+        -- | __Input:__ a pointer to an initialized signature object (cannot be NULL)         Ptr RecSig65 ->-        --  Returns: 1+        -- | __Returns:__ 1         IO Ret   -- | Create a recoverable ECDSA signature. foreign import ccall safe "secp256k1.h secp256k1_ecdsa_sign_recoverable"     ecdsaSignRecoverable ::-        --  Args:    ctx:       pointer to a context object, initialized for signing (cannot be NULL)+        -- | pointer to a context object, initialized for signing (cannot be NULL)         Ctx ->-        --  Out:     sig:       pointer to an array where the signature will be placed (cannot be NULL)+        -- | __Output:__ pointer to an array where the signature will be placed (cannot be NULL)         Ptr RecSig65 ->-        --  In:      msghash32: the 32-byte message hash being signed (cannot be NULL)+        -- | __Input:__ the 32-byte message hash being signed (cannot be NULL)         Ptr Msg32 ->-        --           seckey:    pointer to a 32-byte secret key (cannot be NULL)+        -- | __Input:__ pointer to a 32-byte secret key (cannot be NULL)         Ptr Seckey32 ->-        --           noncefp:   pointer to a nonce generation function. If NULL, 'nonceFunctionDefault' is used+        -- | __Input:__ pointer to a nonce generation function. If NULL, 'nonceFunctionDefault' is used         FunPtr (NonceFun a) ->-        --           ndata:     pointer to arbitrary data used by the nonce generation function (can be NULL)+        -- | __Input:__ pointer to arbitrary data used by the nonce generation function (can be NULL)         Ptr a ->-        --  Returns: 1: signature created-        --           0: the nonce generation function failed, or the secret key was invalid.+        -- | __Returns:__ 1: signature created+        -- 0: the nonce generation function failed, or the secret key was invalid.         IO Ret  @@ -618,7 +730,7 @@         -- | __Output:__ a pointer to a signature object         Ptr Sig64 ->         -- | __Input:__ a pointer to the 64-byte array to parse-        Ptr Compact64 ->+        Ptr (Bytes 64) ->         -- | __Returns:__ 1 when the signature could be parsed, 0 otherwise.         IO Ret @@ -653,7 +765,7 @@         -- | __Input:__ a secp256k1 context object         Ctx ->         -- | __Output:__ a pointer to a 64-byte array to store the compact serialization-        Ptr Compact64 ->+        Ptr (Bytes 64) ->         -- | __Input:__ a pointer to an initialized signature object         Ptr Sig64 ->         -- | __Returns:__ 1@@ -774,7 +886,7 @@         Ptr Pubkey64 ->         -- | __Input:__ 'compressed' if serialization should be in         -- compressed format, otherwise 'uncompressed'.-        SerFlags ->+        CompressionFlags ->         --  Returns: 1 always.         IO Ret @@ -933,22 +1045,21 @@ -- --  This is the same as calling 'keypairPub' and then --  'xonlyPubkeyFromPubkey'.------  Returns: 0 if the arguments are invalid. 1 otherwise.---  Args:   ctx: pointer to a context object (cannot be NULL)---  Out: pubkey: pointer to an xonly_pubkey object. If 1 is returned, it is set---               to the keypair public key after converting it to an---               xonly_pubkey. If not, it's set to an invalid value (cannot be---               NULL).---    pk_parity: pointer to an integer that will be set to the pk_parity---               argument of 'xonlyPubkeyFromPubkey' (can be NULL).---  In: keypair: pointer to a keypair (cannot be NULL) foreign import ccall safe "secp256k1.h secp256k1_keypair_xonly_pub"     keypairXonlyPub ::+        -- | pointer to a context object (cannot be NULL)         Ctx ->+        -- | __Output:__ pointer to an xonly_pubkey object. If 1 is returned, it is set+        -- to the keypair public key after converting it to an+        -- xonly_pubkey. If not, it's set to an invalid value (cannot be+        -- NULL).         Ptr XonlyPubkey64 ->+        --    pk_parity: pointer to an integer that will be set to the pk_parity+        --               argument of 'xonlyPubkeyFromPubkey' (can be NULL).         Ptr CInt ->+        --  In: keypair: pointer to a keypair (cannot be NULL)         Ptr Keypair96 ->+        --  Returns: 0 if the arguments are invalid. 1 otherwise.         IO Ret  @@ -958,25 +1069,20 @@ --  Calling this function and then 'keypairPub' results in the same --  public key as calling 'keypairXonlyPub' and then --  'xonlyPubkeyTweakAdd'.------  Returns: 0 if the arguments are invalid or the resulting keypair would be---           invalid (only when the tweak is the negation of the keypair's---           secret key). 1 otherwise.------  Args:       ctx: pointer to a context object initialized for verification---                   (cannot be NULL)---  In/Out: keypair: pointer to a keypair to apply the tweak to. Will be set to---                   an invalid value if this function returns 0 (cannot be---                   NULL).---  In:     tweak32: pointer to a 32-byte tweak. If the tweak is invalid according---                   to 'ecSeckeyVerify', this function returns 0. For---                   uniformly random 32-byte arrays the chance of being invalid---                   is negligible (around 1 in 2^128) (cannot be NULL). foreign import ccall safe "secp256k1.h secp256k1_keypair_xonly_tweak_add"     keypairXonlyTweakAdd ::+        -- | pointer to a context object initialized for verification+        -- (cannot be NULL)         Ctx ->+        -- | __Mutates:__ pointer to a keypair to apply the tweak to. Will be set to+        -- an invalid value if this function returns 0 (cannot be NULL).         Ptr Keypair96 ->+        -- | __Input:__ pointer to a 32-byte tweak. If the tweak is invalid according+        -- to 'ecSeckeyVerify', this function returns 0. For uniformly random 32-byte+        -- arrays the chance of being invalid is negligible (around 1 in 2^128) (cannot be NULL).         Ptr Tweak32 ->+        -- | __Returns:__ 0 if the arguments are invalid or the resulting keypair would be+        -- invalid (only when the tweak is the negation of the keypair's secret key). 1 otherwise.         IO Ret  @@ -1047,10 +1153,7 @@         Ptr (Bytes n) ->         -- | __Input:__ length of the message         CSize ->-        -- | __Input:__ 32 bytes of fresh randomness. While recommended to provide-        -- this, it is only supplemental to security and can be NULL. See-        -- BIP-340 "Default Signing" for a full explanation of this-        -- argument and for guidance if randomness is expensive.+        -- | __Input:__ pointer to an initialized keypair (cannot be NULL)         Ptr Keypair96 ->         -- | __Input:__ pointer to a extraparams object (can be NULL)         Ptr SchnorrExtra ->@@ -1060,7 +1163,7 @@  -- | Verify a Schnorr signature. foreign import ccall safe "secp256k1.h secp256k1_schnorrsig_verify"-    schnorrSigSignVerify ::+    schnorrsigSignVerify ::         -- | a secp256k1 context object, initialized for verification.         Ctx ->         -- | __Input:__ pointer to the 64-byte signature to verify (cannot be NULL)@@ -1126,7 +1229,7 @@         -- | __Output:__ pointer to an x-only public key object for placing the         -- converted public key (cannot be NULL)         Ptr XonlyPubkey64 ->-        -- __Mutates:__ pointer to an integer that will be set to 1 if the point+        -- __Output:__ pointer to an integer that will be set to 1 if the point         -- encoded by xonly_pubkey is the negation of the pubkey and         -- set to 0 otherwise. (can be NULL)         Ptr CInt ->@@ -1199,7 +1302,7 @@   -- | Checks that a tweaked pubkey is the result of calling--- 'xonlyPubkeyTweakAdd' with internal_pubkey and tweak32.+-- 'xonlyPubkeyTweakAdd' with the pubkey and tweak. -- --  The tweaked pubkey is represented by its 32-byte x-only serialization and --  its pk_parity, which can both be obtained by converting the result of@@ -1214,11 +1317,11 @@         -- (cannot be NULL)         Ctx ->         -- | __Input:__ pointer to a serialized xonly_pubkey (cannot be NULL)-        Ptr (Bytes 32) ->+        Ptr XonlyPubkey64 ->         -- | __Input:__ the parity of the tweaked pubkey (whose serialization         -- is passed in as tweaked_pubkey32). This must match the         -- pk_parity value that is returned when calling-        -- 'XonlyPubkey64' with the tweaked pubkey, or+        -- 'xonlyPubkey' with the tweaked pubkey, or         -- this function will fail.         CInt ->         -- | __Input__ pointer to an x-only public key object to apply the@@ -1293,7 +1396,6 @@ data Msg32 data RecSig65 data Sig64-data Compact64 data Seed32 data Seckey32 data Tweak32