packages feed

secp256k1-haskell 1.0.0 → 1.0.1

raw patch · 11 files changed

+826/−709 lines, 11 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- 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.CompactSig
- 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.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.SecKey
- Crypto.Secp256k1.Internal: compressed :: SerFlags
- Crypto.Secp256k1.Internal: contextClone :: Ptr LCtx -> IO (Ptr LCtx)
- Crypto.Secp256k1.Internal: contextCreate :: CtxFlags -> IO (Ptr LCtx)
- Crypto.Secp256k1.Internal: contextDestroy :: Ptr LCtx -> IO ()
- Crypto.Secp256k1.Internal: contextRandomize :: Ptr LCtx -> Ptr Seed32 -> IO Ret
- Crypto.Secp256k1.Internal: data Compact64
- Crypto.Secp256k1.Internal: data LCtx
- Crypto.Secp256k1.Internal: data Msg32
- Crypto.Secp256k1.Internal: data PubKey64
- Crypto.Secp256k1.Internal: data SecKey32
- Crypto.Secp256k1.Internal: data Seed32
- Crypto.Secp256k1.Internal: data Sig64
- Crypto.Secp256k1.Internal: data Tweak32
- Crypto.Secp256k1.Internal: ecPubKeyCombine :: Ptr LCtx -> Ptr PubKey64 -> Ptr (Ptr PubKey64) -> CInt -> IO Ret
- Crypto.Secp256k1.Internal: ecPubKeyCreate :: Ptr LCtx -> Ptr PubKey64 -> Ptr SecKey32 -> IO Ret
- Crypto.Secp256k1.Internal: ecPubKeyParse :: Ptr LCtx -> Ptr PubKey64 -> Ptr CUChar -> CSize -> IO Ret
- Crypto.Secp256k1.Internal: ecPubKeySerialize :: Ptr LCtx -> Ptr CUChar -> Ptr CSize -> Ptr PubKey64 -> SerFlags -> IO Ret
- Crypto.Secp256k1.Internal: ecPubKeyTweakAdd :: Ptr LCtx -> Ptr PubKey64 -> Ptr Tweak32 -> IO Ret
- Crypto.Secp256k1.Internal: ecPubKeyTweakMul :: Ptr LCtx -> Ptr PubKey64 -> Ptr Tweak32 -> IO Ret
- Crypto.Secp256k1.Internal: ecSecKeyTweakAdd :: Ptr LCtx -> Ptr SecKey32 -> Ptr Tweak32 -> IO Ret
- Crypto.Secp256k1.Internal: ecSecKeyTweakMul :: Ptr LCtx -> Ptr SecKey32 -> Ptr Tweak32 -> IO Ret
- Crypto.Secp256k1.Internal: ecSecKeyVerify :: Ptr LCtx -> Ptr SecKey32 -> IO Ret
- Crypto.Secp256k1.Internal: ecTweakNegate :: Ptr LCtx -> Ptr Tweak32 -> IO Ret
- Crypto.Secp256k1.Internal: ecdsaSign :: Ptr LCtx -> Ptr Sig64 -> Ptr Msg32 -> Ptr SecKey32 -> FunPtr (NonceFun a) -> Ptr a -> IO Ret
- Crypto.Secp256k1.Internal: ecdsaSignatureNormalize :: Ptr LCtx -> Ptr Sig64 -> Ptr Sig64 -> IO Ret
- Crypto.Secp256k1.Internal: ecdsaSignatureParseCompact :: Ptr LCtx -> Ptr Sig64 -> Ptr Compact64 -> IO Ret
- Crypto.Secp256k1.Internal: ecdsaSignatureParseDer :: Ptr LCtx -> Ptr Sig64 -> Ptr CUChar -> CSize -> IO Ret
- Crypto.Secp256k1.Internal: ecdsaSignatureSerializeCompact :: Ptr LCtx -> Ptr Compact64 -> Ptr Sig64 -> IO Ret
- Crypto.Secp256k1.Internal: ecdsaSignatureSerializeDer :: Ptr LCtx -> Ptr CUChar -> Ptr CSize -> Ptr Sig64 -> IO Ret
- Crypto.Secp256k1.Internal: ecdsaVerify :: Ptr LCtx -> Ptr Sig64 -> Ptr Msg32 -> Ptr PubKey64 -> IO Ret
- Crypto.Secp256k1.Internal: isSuccess :: Ret -> Bool
- Crypto.Secp256k1.Internal: packByteString :: (Ptr a, CSize) -> IO ByteString
- Crypto.Secp256k1.Internal: setErrorCallback :: Ptr LCtx -> FunPtr (CString -> Ptr a -> IO ()) -> Ptr a -> IO ()
- Crypto.Secp256k1.Internal: setIllegalCallback :: Ptr LCtx -> FunPtr (CString -> Ptr a -> IO ()) -> Ptr a -> IO ()
- Crypto.Secp256k1.Internal: sign :: CtxFlags
- Crypto.Secp256k1.Internal: signVerify :: CtxFlags
- Crypto.Secp256k1.Internal: type CtxFlags = CUInt
- Crypto.Secp256k1.Internal: type NonceFun a = Ptr CUChar -> Ptr CUChar -> Ptr CUChar -> Ptr CUChar -> Ptr a -> CInt -> IO CInt
- Crypto.Secp256k1.Internal: type Ret = CInt
- Crypto.Secp256k1.Internal: type SerFlags = CUInt
- Crypto.Secp256k1.Internal: uncompressed :: SerFlags
- 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.Internal: verify :: CtxFlags
- Crypto.Secp256k1.Internal: withRandomSeed :: (Ptr Seed32 -> IO a) -> IO a
+ Crypto.Secp256k1.Internal.Base: CompactSig :: ByteString -> CompactSig
+ Crypto.Secp256k1.Internal.Base: Msg :: ByteString -> Msg
+ Crypto.Secp256k1.Internal.Base: PubKey :: ByteString -> PubKey
+ Crypto.Secp256k1.Internal.Base: SecKey :: ByteString -> SecKey
+ Crypto.Secp256k1.Internal.Base: Sig :: ByteString -> Sig
+ Crypto.Secp256k1.Internal.Base: Tweak :: ByteString -> Tweak
+ Crypto.Secp256k1.Internal.Base: [$sel:get:CompactSig] :: CompactSig -> ByteString
+ Crypto.Secp256k1.Internal.Base: [$sel:get:Msg] :: Msg -> ByteString
+ Crypto.Secp256k1.Internal.Base: [$sel:get:PubKey] :: PubKey -> ByteString
+ Crypto.Secp256k1.Internal.Base: [$sel:get:SecKey] :: SecKey -> ByteString
+ Crypto.Secp256k1.Internal.Base: [$sel:get:Sig] :: Sig -> ByteString
+ Crypto.Secp256k1.Internal.Base: [$sel:get:Tweak] :: Tweak -> ByteString
+ Crypto.Secp256k1.Internal.Base: combinePubKeys :: Ctx -> [PubKey] -> Maybe PubKey
+ Crypto.Secp256k1.Internal.Base: compactSig :: ByteString -> Maybe CompactSig
+ Crypto.Secp256k1.Internal.Base: derivePubKey :: Ctx -> SecKey -> PubKey
+ Crypto.Secp256k1.Internal.Base: exportCompactSig :: Ctx -> Sig -> CompactSig
+ Crypto.Secp256k1.Internal.Base: exportPubKey :: Ctx -> Bool -> PubKey -> ByteString
+ Crypto.Secp256k1.Internal.Base: exportSig :: Ctx -> Sig -> ByteString
+ Crypto.Secp256k1.Internal.Base: importCompactSig :: Ctx -> CompactSig -> Maybe Sig
+ Crypto.Secp256k1.Internal.Base: importPubKey :: Ctx -> ByteString -> Maybe PubKey
+ Crypto.Secp256k1.Internal.Base: importSig :: Ctx -> ByteString -> Maybe Sig
+ Crypto.Secp256k1.Internal.Base: instance Control.DeepSeq.NFData Crypto.Secp256k1.Internal.Base.CompactSig
+ Crypto.Secp256k1.Internal.Base: instance Control.DeepSeq.NFData Crypto.Secp256k1.Internal.Base.Msg
+ Crypto.Secp256k1.Internal.Base: instance Control.DeepSeq.NFData Crypto.Secp256k1.Internal.Base.PubKey
+ Crypto.Secp256k1.Internal.Base: instance Control.DeepSeq.NFData Crypto.Secp256k1.Internal.Base.SecKey
+ Crypto.Secp256k1.Internal.Base: instance Control.DeepSeq.NFData Crypto.Secp256k1.Internal.Base.Sig
+ Crypto.Secp256k1.Internal.Base: instance Control.DeepSeq.NFData Crypto.Secp256k1.Internal.Base.Tweak
+ Crypto.Secp256k1.Internal.Base: instance Data.Hashable.Class.Hashable Crypto.Secp256k1.Internal.Base.CompactSig
+ Crypto.Secp256k1.Internal.Base: instance Data.Hashable.Class.Hashable Crypto.Secp256k1.Internal.Base.Msg
+ Crypto.Secp256k1.Internal.Base: instance Data.Hashable.Class.Hashable Crypto.Secp256k1.Internal.Base.PubKey
+ Crypto.Secp256k1.Internal.Base: instance Data.Hashable.Class.Hashable Crypto.Secp256k1.Internal.Base.SecKey
+ Crypto.Secp256k1.Internal.Base: instance Data.Hashable.Class.Hashable Crypto.Secp256k1.Internal.Base.Sig
+ Crypto.Secp256k1.Internal.Base: instance Data.Hashable.Class.Hashable Crypto.Secp256k1.Internal.Base.Tweak
+ Crypto.Secp256k1.Internal.Base: instance Data.String.IsString Crypto.Secp256k1.Internal.Base.Msg
+ Crypto.Secp256k1.Internal.Base: instance Data.String.IsString Crypto.Secp256k1.Internal.Base.PubKey
+ Crypto.Secp256k1.Internal.Base: instance Data.String.IsString Crypto.Secp256k1.Internal.Base.SecKey
+ Crypto.Secp256k1.Internal.Base: instance Data.String.IsString Crypto.Secp256k1.Internal.Base.Sig
+ Crypto.Secp256k1.Internal.Base: instance Data.String.IsString Crypto.Secp256k1.Internal.Base.Tweak
+ Crypto.Secp256k1.Internal.Base: instance GHC.Classes.Eq Crypto.Secp256k1.Internal.Base.CompactSig
+ Crypto.Secp256k1.Internal.Base: instance GHC.Classes.Eq Crypto.Secp256k1.Internal.Base.Msg
+ Crypto.Secp256k1.Internal.Base: instance GHC.Classes.Eq Crypto.Secp256k1.Internal.Base.PubKey
+ Crypto.Secp256k1.Internal.Base: instance GHC.Classes.Eq Crypto.Secp256k1.Internal.Base.SecKey
+ Crypto.Secp256k1.Internal.Base: instance GHC.Classes.Eq Crypto.Secp256k1.Internal.Base.Sig
+ Crypto.Secp256k1.Internal.Base: instance GHC.Classes.Eq Crypto.Secp256k1.Internal.Base.Tweak
+ Crypto.Secp256k1.Internal.Base: instance GHC.Generics.Generic Crypto.Secp256k1.Internal.Base.CompactSig
+ Crypto.Secp256k1.Internal.Base: instance GHC.Generics.Generic Crypto.Secp256k1.Internal.Base.Msg
+ Crypto.Secp256k1.Internal.Base: instance GHC.Generics.Generic Crypto.Secp256k1.Internal.Base.PubKey
+ Crypto.Secp256k1.Internal.Base: instance GHC.Generics.Generic Crypto.Secp256k1.Internal.Base.SecKey
+ Crypto.Secp256k1.Internal.Base: instance GHC.Generics.Generic Crypto.Secp256k1.Internal.Base.Sig
+ Crypto.Secp256k1.Internal.Base: instance GHC.Generics.Generic Crypto.Secp256k1.Internal.Base.Tweak
+ Crypto.Secp256k1.Internal.Base: instance GHC.Read.Read Crypto.Secp256k1.Internal.Base.Msg
+ Crypto.Secp256k1.Internal.Base: instance GHC.Read.Read Crypto.Secp256k1.Internal.Base.PubKey
+ Crypto.Secp256k1.Internal.Base: instance GHC.Read.Read Crypto.Secp256k1.Internal.Base.SecKey
+ Crypto.Secp256k1.Internal.Base: instance GHC.Read.Read Crypto.Secp256k1.Internal.Base.Sig
+ Crypto.Secp256k1.Internal.Base: instance GHC.Read.Read Crypto.Secp256k1.Internal.Base.Tweak
+ Crypto.Secp256k1.Internal.Base: instance GHC.Show.Show Crypto.Secp256k1.Internal.Base.Msg
+ Crypto.Secp256k1.Internal.Base: instance GHC.Show.Show Crypto.Secp256k1.Internal.Base.PubKey
+ Crypto.Secp256k1.Internal.Base: instance GHC.Show.Show Crypto.Secp256k1.Internal.Base.SecKey
+ Crypto.Secp256k1.Internal.Base: instance GHC.Show.Show Crypto.Secp256k1.Internal.Base.Sig
+ Crypto.Secp256k1.Internal.Base: instance GHC.Show.Show Crypto.Secp256k1.Internal.Base.Tweak
+ Crypto.Secp256k1.Internal.Base: instance Test.QuickCheck.Arbitrary.Arbitrary Crypto.Secp256k1.Internal.Base.Msg
+ Crypto.Secp256k1.Internal.Base: instance Test.QuickCheck.Arbitrary.Arbitrary Crypto.Secp256k1.Internal.Base.SecKey
+ Crypto.Secp256k1.Internal.Base: msg :: ByteString -> Maybe Msg
+ Crypto.Secp256k1.Internal.Base: newtype CompactSig
+ Crypto.Secp256k1.Internal.Base: newtype Msg
+ Crypto.Secp256k1.Internal.Base: newtype PubKey
+ Crypto.Secp256k1.Internal.Base: newtype SecKey
+ Crypto.Secp256k1.Internal.Base: newtype Sig
+ Crypto.Secp256k1.Internal.Base: newtype Tweak
+ Crypto.Secp256k1.Internal.Base: normalizeSig :: Ctx -> Sig -> Maybe Sig
+ Crypto.Secp256k1.Internal.Base: pubKey :: ByteString -> Maybe PubKey
+ Crypto.Secp256k1.Internal.Base: secKey :: ByteString -> Maybe SecKey
+ Crypto.Secp256k1.Internal.Base: sig :: ByteString -> Maybe Sig
+ Crypto.Secp256k1.Internal.Base: signMsg :: Ctx -> SecKey -> Msg -> Sig
+ Crypto.Secp256k1.Internal.Base: tweak :: ByteString -> Maybe Tweak
+ Crypto.Secp256k1.Internal.Base: tweakAddPubKey :: Ctx -> PubKey -> Tweak -> Maybe PubKey
+ Crypto.Secp256k1.Internal.Base: tweakAddSecKey :: Ctx -> SecKey -> Tweak -> Maybe SecKey
+ Crypto.Secp256k1.Internal.Base: tweakMulPubKey :: Ctx -> PubKey -> Tweak -> Maybe PubKey
+ Crypto.Secp256k1.Internal.Base: tweakMulSecKey :: Ctx -> SecKey -> Tweak -> Maybe SecKey
+ Crypto.Secp256k1.Internal.Base: tweakNegate :: Ctx -> Tweak -> Maybe Tweak
+ Crypto.Secp256k1.Internal.Base: verifySig :: Ctx -> PubKey -> Sig -> Msg -> Bool
+ Crypto.Secp256k1.Internal.BaseOps: ecPubKeyCombine :: Ptr LCtx -> Ptr PubKey64 -> Ptr (Ptr PubKey64) -> CInt -> IO Ret
+ Crypto.Secp256k1.Internal.BaseOps: ecPubKeyCreate :: Ptr LCtx -> Ptr PubKey64 -> Ptr SecKey32 -> IO Ret
+ Crypto.Secp256k1.Internal.BaseOps: ecPubKeyParse :: Ptr LCtx -> Ptr PubKey64 -> Ptr CUChar -> CSize -> IO Ret
+ Crypto.Secp256k1.Internal.BaseOps: ecPubKeySerialize :: Ptr LCtx -> Ptr CUChar -> Ptr CSize -> Ptr PubKey64 -> SerFlags -> IO Ret
+ Crypto.Secp256k1.Internal.BaseOps: ecPubKeyTweakAdd :: Ptr LCtx -> Ptr PubKey64 -> Ptr Tweak32 -> IO Ret
+ Crypto.Secp256k1.Internal.BaseOps: ecPubKeyTweakMul :: Ptr LCtx -> Ptr PubKey64 -> Ptr Tweak32 -> IO Ret
+ Crypto.Secp256k1.Internal.BaseOps: ecSecKeyTweakAdd :: Ptr LCtx -> Ptr SecKey32 -> Ptr Tweak32 -> IO Ret
+ Crypto.Secp256k1.Internal.BaseOps: ecSecKeyTweakMul :: Ptr LCtx -> Ptr SecKey32 -> Ptr Tweak32 -> IO Ret
+ Crypto.Secp256k1.Internal.BaseOps: ecSecKeyVerify :: Ptr LCtx -> Ptr SecKey32 -> IO Ret
+ Crypto.Secp256k1.Internal.BaseOps: ecTweakNegate :: Ptr LCtx -> Ptr Tweak32 -> IO Ret
+ Crypto.Secp256k1.Internal.BaseOps: ecdsaSign :: Ptr LCtx -> Ptr Sig64 -> Ptr Msg32 -> Ptr SecKey32 -> FunPtr (NonceFun a) -> Ptr a -> IO Ret
+ Crypto.Secp256k1.Internal.BaseOps: ecdsaSignatureNormalize :: Ptr LCtx -> Ptr Sig64 -> Ptr Sig64 -> IO Ret
+ Crypto.Secp256k1.Internal.BaseOps: ecdsaSignatureParseCompact :: Ptr LCtx -> Ptr Sig64 -> Ptr Compact64 -> IO Ret
+ Crypto.Secp256k1.Internal.BaseOps: ecdsaSignatureParseDer :: Ptr LCtx -> Ptr Sig64 -> Ptr CUChar -> CSize -> IO Ret
+ Crypto.Secp256k1.Internal.BaseOps: ecdsaSignatureSerializeCompact :: Ptr LCtx -> Ptr Compact64 -> Ptr Sig64 -> IO Ret
+ Crypto.Secp256k1.Internal.BaseOps: ecdsaSignatureSerializeDer :: Ptr LCtx -> Ptr CUChar -> Ptr CSize -> Ptr Sig64 -> IO Ret
+ Crypto.Secp256k1.Internal.BaseOps: ecdsaVerify :: Ptr LCtx -> Ptr Sig64 -> Ptr Msg32 -> Ptr PubKey64 -> IO Ret
+ Crypto.Secp256k1.Internal.Context: Ctx :: Ptr LCtx -> Ctx
+ Crypto.Secp256k1.Internal.Context: [$sel:get:Ctx] :: Ctx -> Ptr LCtx
+ Crypto.Secp256k1.Internal.Context: cloneContext :: Ctx -> IO Ctx
+ Crypto.Secp256k1.Internal.Context: contextClone :: Ptr LCtx -> IO (Ptr LCtx)
+ Crypto.Secp256k1.Internal.Context: contextCreate :: CtxFlags -> IO (Ptr LCtx)
+ Crypto.Secp256k1.Internal.Context: contextDestroy :: Ptr LCtx -> IO ()
+ Crypto.Secp256k1.Internal.Context: contextRandomize :: Ptr LCtx -> Ptr Seed32 -> IO Ret
+ Crypto.Secp256k1.Internal.Context: createContext :: IO Ctx
+ Crypto.Secp256k1.Internal.Context: destroyContext :: Ctx -> IO ()
+ Crypto.Secp256k1.Internal.Context: newtype Ctx
+ Crypto.Secp256k1.Internal.Context: randomizeContext :: Ctx -> IO ()
+ Crypto.Secp256k1.Internal.Context: setErrorCallback :: Ptr LCtx -> FunPtr (CString -> Ptr a -> IO ()) -> Ptr a -> IO ()
+ Crypto.Secp256k1.Internal.Context: setIllegalCallback :: Ptr LCtx -> FunPtr (CString -> Ptr a -> IO ()) -> Ptr a -> IO ()
+ Crypto.Secp256k1.Internal.Context: sign :: CtxFlags
+ Crypto.Secp256k1.Internal.Context: signVerify :: CtxFlags
+ Crypto.Secp256k1.Internal.Context: verify :: CtxFlags
+ Crypto.Secp256k1.Internal.Context: withContext :: (Ctx -> IO a) -> IO a
+ Crypto.Secp256k1.Internal.ForeignTypes: compressed :: SerFlags
+ Crypto.Secp256k1.Internal.ForeignTypes: data Compact64
+ Crypto.Secp256k1.Internal.ForeignTypes: data LCtx
+ Crypto.Secp256k1.Internal.ForeignTypes: data Msg32
+ Crypto.Secp256k1.Internal.ForeignTypes: data PubKey64
+ Crypto.Secp256k1.Internal.ForeignTypes: data RecSig65
+ Crypto.Secp256k1.Internal.ForeignTypes: data SecKey32
+ Crypto.Secp256k1.Internal.ForeignTypes: data Seed32
+ Crypto.Secp256k1.Internal.ForeignTypes: data Sig64
+ Crypto.Secp256k1.Internal.ForeignTypes: data Tweak32
+ Crypto.Secp256k1.Internal.ForeignTypes: isSuccess :: Ret -> Bool
+ Crypto.Secp256k1.Internal.ForeignTypes: type CtxFlags = CUInt
+ Crypto.Secp256k1.Internal.ForeignTypes: type NonceFun a = Ptr CUChar -> Ptr CUChar -> Ptr CUChar -> Ptr CUChar -> Ptr a -> CInt -> IO CInt
+ Crypto.Secp256k1.Internal.ForeignTypes: type Ret = CInt
+ Crypto.Secp256k1.Internal.ForeignTypes: type SerFlags = CUInt
+ Crypto.Secp256k1.Internal.ForeignTypes: uncompressed :: SerFlags
+ Crypto.Secp256k1.Internal.Util: decodeHex :: ConvertibleStrings a ByteString => a -> Maybe ByteString
+ Crypto.Secp256k1.Internal.Util: packByteString :: (Ptr a, CSize) -> IO ByteString
+ Crypto.Secp256k1.Internal.Util: showsHex :: ByteString -> ShowS
+ Crypto.Secp256k1.Internal.Util: unsafePackByteString :: (Ptr a, CSize) -> IO ByteString
+ Crypto.Secp256k1.Internal.Util: unsafeUseByteString :: ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
+ Crypto.Secp256k1.Internal.Util: useByteString :: ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
+ Crypto.Secp256k1.Internal.Util: withRandomSeed :: (Ptr Seed32 -> IO a) -> IO a

Files

CHANGELOG.md view
@@ -4,6 +4,12 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [1.0.1] - 2023-09-20++### Changed++- Reworked the structure of the Internal modules to allow having add-on packages for optional libsecp256k1 features.+ ## [1.0.0] - 2023-07-28  ### Changed
− README.md
@@ -1,6 +0,0 @@-[![Build Status](https://travis-ci.org/haskoin/secp256k1-haskell.svg?branch=master)](https://travis-ci.org/haskoin/secp256k1-haskell)--# Haskell bindings for secp256k1--This project contains Haskell bindings for the-[secp256k1](https://github.com/bitcoin-core/secp256k1) library.
secp256k1-haskell.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           secp256k1-haskell-version:        1.0.0+version:        1.0.1 synopsis:       Bindings for secp256k1 description:    Sign and verify signatures using the secp256k1 library. category:       Crypto@@ -19,7 +19,6 @@ build-type:     Simple extra-source-files:     CHANGELOG.md-    README.md  source-repository head   type: git@@ -28,7 +27,11 @@ library   exposed-modules:       Crypto.Secp256k1-      Crypto.Secp256k1.Internal+      Crypto.Secp256k1.Internal.Base+      Crypto.Secp256k1.Internal.BaseOps+      Crypto.Secp256k1.Internal.Context+      Crypto.Secp256k1.Internal.ForeignTypes+      Crypto.Secp256k1.Internal.Util       Paths_secp256k1_haskell   autogen-modules:       Paths_secp256k1_haskell
src/Crypto/Secp256k1.hs view
@@ -1,12 +1,3 @@-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE DuplicateRecordFields #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE ImportQualifiedPost #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE OverloadedRecordDot #-}-{-# LANGUAGE NoFieldSelectors #-}- -- | -- Module      : Crypto.Secp256k1 -- License     : UNLICENSE@@ -68,412 +59,5 @@   ) where -import Control.DeepSeq (NFData)-import Control.Exception (bracket)-import Control.Monad (replicateM, unless, (<=<))-import Crypto.Secp256k1.Internal-import Data.Base16.Types (assertBase16, extractBase16)-import Data.ByteString (ByteString)-import Data.ByteString qualified as BS-import Data.ByteString.Base16 (decodeBase16, encodeBase16, isBase16)-import Data.Hashable (Hashable (..))-import Data.Maybe (fromJust, fromMaybe, isJust)-import Data.String (IsString (..))-import Data.String.Conversions (ConvertibleStrings, cs)-import Foreign-  ( Bits (bitSize),-    Ptr,-    alloca,-    allocaArray,-    allocaBytes,-    free,-    mallocBytes,-    nullFunPtr,-    nullPtr,-    peek,-    poke,-    pokeArray,-  )-import GHC.Generics (Generic)-import System.IO.Unsafe (unsafePerformIO)-import Test.QuickCheck-  ( Arbitrary (..),-    arbitraryBoundedRandom,-    suchThat,-  )-import Text.Read-  ( Lexeme (String),-    lexP,-    parens,-    pfail,-    readPrec,-  )--newtype Ctx = Ctx {get :: Ptr LCtx}--newtype PubKey = PubKey {get :: ByteString}-  deriving (Eq, Generic, Hashable, NFData)--newtype Msg = Msg {get :: ByteString}-  deriving (Eq, Generic, Hashable, NFData)--newtype Sig = Sig {get :: ByteString}-  deriving (Eq, Generic, Hashable, NFData)--newtype SecKey = SecKey {get :: ByteString}-  deriving (Eq, Generic, Hashable, NFData)--newtype Tweak = Tweak {get :: ByteString}-  deriving (Eq, Generic, Hashable, NFData)--newtype CompactSig = CompactSig {get :: ByteString}-  deriving (Eq, Generic, Hashable, NFData)--decodeHex :: (ConvertibleStrings a ByteString) => a -> Maybe ByteString-decodeHex str =-  if isBase16 $ cs str-    then Just . decodeBase16 $ assertBase16 $ cs str-    else Nothing--instance Read PubKey where-  readPrec = parens $ do-    String str <- lexP-    maybe pfail return $ pubKey =<< decodeHex str--instance IsString PubKey where-  fromString = fromMaybe e . (pubKey <=< decodeHex)-    where-      e = error "Could not decode public key from hex string"--instance Show PubKey where-  showsPrec _ = shows . extractBase16 . encodeBase16 . (.get)--instance Read Msg where-  readPrec = parens $ do-    String str <- lexP-    maybe pfail return $ msg =<< decodeHex str--instance IsString Msg where-  fromString = fromMaybe e . (msg <=< decodeHex)-    where-      e = error "Could not decode message from hex string"--instance Show Sig where-  showsPrec _ = shows . extractBase16 . encodeBase16 . (.get)--instance Read Sig where-  readPrec = parens $ do-    String str <- lexP-    maybe pfail return $ sig =<< decodeHex str--instance IsString Sig where-  fromString = fromMaybe e . (sig <=< decodeHex)-    where-      e = error "Could not decode signature from hex string"--instance Show Msg where-  showsPrec _ = shows . extractBase16 . encodeBase16 . (.get)--instance Read SecKey where-  readPrec = parens $ do-    String str <- lexP-    maybe pfail return $ secKey =<< decodeHex str--instance IsString SecKey where-  fromString = fromMaybe e . (secKey <=< decodeHex)-    where-      e = error "Colud not decode secret key from hex string"--instance Show SecKey where-  showsPrec _ = shows . extractBase16 . encodeBase16 . (.get)--instance Read Tweak where-  readPrec = parens $ do-    String str <- lexP-    maybe pfail return $ tweak =<< decodeHex str--instance IsString Tweak where-  fromString = fromMaybe e . (tweak <=< decodeHex)-    where-      e = error "Could not decode tweak from hex string"--instance Show Tweak where-  showsPrec _ = shows . extractBase16 . encodeBase16 . (.get)--randomizeContext :: Ctx -> IO ()-randomizeContext (Ctx ctx) = do-  ret <- withRandomSeed $ contextRandomize ctx-  unless (isSuccess ret) $ error "Could not randomize context"--createContext :: IO Ctx-createContext = Ctx <$> contextCreate signVerify--cloneContext :: Ctx -> IO Ctx-cloneContext = fmap Ctx . contextClone . (.get)--destroyContext :: Ctx -> IO ()-destroyContext = contextDestroy . (.get)--withContext :: (Ctx -> IO a) -> IO a-withContext = bracket create destroy-  where-    create = do-      ctx <- createContext-      randomizeContext ctx-      return ctx-    destroy = destroyContext--sig :: ByteString -> Maybe Sig-sig bs-  | BS.length bs == 64 = Just (Sig bs)-  | otherwise = Nothing--pubKey :: ByteString -> Maybe PubKey-pubKey bs-  | BS.length bs == 64 = Just (PubKey bs)-  | otherwise = Nothing---- | Import 32-byte 'ByteString' as 'Msg'.-msg :: ByteString -> Maybe Msg-msg bs-  | BS.length bs == 32 = Just (Msg bs)-  | otherwise = Nothing---- | Import 32-byte 'ByteString' as 'SecKey'.-secKey :: ByteString -> Maybe SecKey-secKey bs-  | BS.length bs == 32 = Just (SecKey bs)-  | otherwise = Nothing--compactSig :: ByteString -> Maybe CompactSig-compactSig bs-  | BS.length bs == 64 = Just (CompactSig bs)-  | otherwise = Nothing---- | Convert signature to a normalized lower-S form. 'Nothing' indicates that it--- was already normal.-normalizeSig :: Ctx -> Sig -> Maybe Sig-normalizeSig (Ctx ctx) (Sig sig) = unsafePerformIO $-  unsafeUseByteString sig $ \(sig_in, _) -> do-    sig_out <- mallocBytes 64-    ret <- ecdsaSignatureNormalize ctx sig_out sig_in-    if isSuccess ret-      then do-        bs <- unsafePackByteString (sig_out, 64)-        return (Just (Sig bs))-      else do-        free sig_out-        return Nothing---- | 32-Byte 'ByteString' as 'Tweak'.-tweak :: ByteString -> Maybe Tweak-tweak bs-  | BS.length bs == 32 = Just (Tweak bs)-  | otherwise = Nothing---- | Import DER-encoded public key.-importPubKey :: Ctx -> ByteString -> Maybe PubKey-importPubKey (Ctx ctx) bs-  | BS.null bs = Nothing-  | otherwise = unsafePerformIO $-      unsafeUseByteString bs $ \(input, len) -> do-        pub_key <- mallocBytes 64-        ret <- ecPubKeyParse ctx pub_key input len-        if isSuccess ret-          then do-            out <- unsafePackByteString (pub_key, 64)-            return (Just (PubKey out))-          else do-            free pub_key-            return Nothing---- | Encode public key as DER. First argument 'True' for compressed output.-exportPubKey :: Ctx -> Bool -> PubKey -> ByteString-exportPubKey (Ctx ctx) compress (PubKey in_bs) = unsafePerformIO $-  unsafeUseByteString in_bs $ \(in_ptr, _) ->-    alloca $ \len_ptr ->-      allocaBytes len $ \out_ptr -> do-        poke len_ptr $ fromIntegral len-        ret <- ecPubKeySerialize ctx out_ptr len_ptr in_ptr flags-        unless (isSuccess ret) $ error "could not serialize public key"-        final_len <- peek len_ptr-        packByteString (out_ptr, final_len)-  where-    len = if compress then 33 else 65-    flags = if compress then compressed else uncompressed--exportCompactSig :: Ctx -> Sig -> CompactSig-exportCompactSig (Ctx ctx) (Sig sig_bs) = unsafePerformIO $-  unsafeUseByteString sig_bs $ \(sig_ptr, _) -> do-    out_ptr <- mallocBytes 64-    ret <- ecdsaSignatureSerializeCompact ctx out_ptr sig_ptr-    unless (isSuccess ret) $ do-      free out_ptr-      error "Could not obtain compact signature"-    out_bs <- unsafePackByteString (out_ptr, 64)-    return $ CompactSig out_bs--importCompactSig :: Ctx -> CompactSig -> Maybe Sig-importCompactSig (Ctx ctx) (CompactSig compact_sig) = unsafePerformIO $-  unsafeUseByteString compact_sig $ \(compact_ptr, _) -> do-    out_sig <- mallocBytes 64-    ret <- ecdsaSignatureParseCompact ctx out_sig compact_ptr-    if isSuccess ret-      then do-        out_bs <- unsafePackByteString (out_sig, 64)-        return (Just (Sig out_bs))-      else do-        free out_sig-        return Nothing---- | Import DER-encoded signature.-importSig :: Ctx -> ByteString -> Maybe Sig-importSig (Ctx ctx) bs-  | BS.null bs = Nothing-  | otherwise = unsafePerformIO $-      unsafeUseByteString bs $ \(in_ptr, in_len) -> do-        out_sig <- mallocBytes 64-        ret <- ecdsaSignatureParseDer ctx out_sig in_ptr in_len-        if isSuccess ret-          then do-            out_bs <- unsafePackByteString (out_sig, 64)-            return (Just (Sig out_bs))-          else do-            free out_sig-            return Nothing---- | Encode signature as strict DER.-exportSig :: Ctx -> Sig -> ByteString-exportSig (Ctx ctx) (Sig in_sig) = unsafePerformIO $-  unsafeUseByteString in_sig $ \(in_ptr, _) ->-    alloca $ \out_len ->-      allocaBytes 72 $ \out_ptr -> do-        poke out_len 72-        ret <- ecdsaSignatureSerializeDer ctx out_ptr out_len in_ptr-        unless (isSuccess ret) $ error "could not serialize signature"-        final_len <- peek out_len-        packByteString (out_ptr, final_len)---- | Verify message signature. 'True' means that the signature is correct.-verifySig :: Ctx -> PubKey -> Sig -> Msg -> Bool-verifySig (Ctx ctx) (PubKey pub_key) (Sig sig) (Msg m) = unsafePerformIO $-  unsafeUseByteString pub_key $ \(pub_key_ptr, _) ->-    unsafeUseByteString sig $ \(sig_ptr, _) ->-      unsafeUseByteString m $ \(msg_ptr, _) ->-        isSuccess <$> ecdsaVerify ctx sig_ptr msg_ptr pub_key_ptr--signMsg :: Ctx -> SecKey -> Msg -> Sig-signMsg (Ctx ctx) (SecKey sec_key) (Msg m) = unsafePerformIO $-  unsafeUseByteString sec_key $ \(sec_key_ptr, _) ->-    unsafeUseByteString m $ \(msg_ptr, _) -> do-      sig_ptr <- mallocBytes 64-      ret <- ecdsaSign ctx sig_ptr msg_ptr sec_key_ptr nullFunPtr nullPtr-      unless (isSuccess ret) $ do-        free sig_ptr-        error "could not sign message"-      Sig <$> unsafePackByteString (sig_ptr, 64)--derivePubKey :: Ctx -> SecKey -> PubKey-derivePubKey (Ctx ctx) (SecKey sec_key) = unsafePerformIO $-  unsafeUseByteString sec_key $ \(sec_key_ptr, _) -> do-    pub_key_ptr <- mallocBytes 64-    ret <- ecPubKeyCreate ctx pub_key_ptr sec_key_ptr-    unless (isSuccess ret) $ do-      free pub_key_ptr-      error "could not compute public key"-    PubKey <$> unsafePackByteString (pub_key_ptr, 64)---- | Add tweak to secret key.-tweakAddSecKey :: Ctx -> SecKey -> Tweak -> Maybe SecKey-tweakAddSecKey (Ctx ctx) (SecKey sec_key) (Tweak t) = unsafePerformIO $-  unsafeUseByteString new_bs $ \(sec_key_ptr, _) ->-    unsafeUseByteString t $ \(tweak_ptr, _) -> do-      ret <- ecSecKeyTweakAdd ctx sec_key_ptr tweak_ptr-      if isSuccess ret-        then return (Just (SecKey new_bs))-        else return Nothing-  where-    new_bs = BS.copy sec_key---- | Multiply secret key by tweak.-tweakMulSecKey :: Ctx -> SecKey -> Tweak -> Maybe SecKey-tweakMulSecKey (Ctx ctx) (SecKey sec_key) (Tweak t) = unsafePerformIO $-  unsafeUseByteString new_bs $ \(sec_key_ptr, _) ->-    unsafeUseByteString t $ \(tweak_ptr, _) -> do-      ret <- ecSecKeyTweakMul ctx sec_key_ptr tweak_ptr-      if isSuccess ret-        then return (Just (SecKey new_bs))-        else return Nothing-  where-    new_bs = BS.copy sec_key---- | Add tweak to public key. Tweak is multiplied first by G to obtain a point.-tweakAddPubKey :: Ctx -> PubKey -> Tweak -> Maybe PubKey-tweakAddPubKey (Ctx ctx) (PubKey pub_key) (Tweak t) = unsafePerformIO $-  unsafeUseByteString new_bs $ \(pub_key_ptr, _) ->-    unsafeUseByteString t $ \(tweak_ptr, _) -> do-      ret <- ecPubKeyTweakAdd ctx pub_key_ptr tweak_ptr-      if isSuccess ret-        then return (Just (PubKey new_bs))-        else return Nothing-  where-    new_bs = BS.copy pub_key---- | Multiply public key by tweak. Tweak is multiplied first by G to obtain a--- point.-tweakMulPubKey :: Ctx -> PubKey -> Tweak -> Maybe PubKey-tweakMulPubKey (Ctx ctx) (PubKey pub_key) (Tweak t) = unsafePerformIO $-  unsafeUseByteString new_bs $ \(pub_key_ptr, _) ->-    unsafeUseByteString t $ \(tweak_ptr, _) -> do-      ret <- ecPubKeyTweakMul ctx pub_key_ptr tweak_ptr-      if isSuccess ret-        then return (Just (PubKey new_bs))-        else return Nothing-  where-    new_bs = BS.copy pub_key---- | Add multiple public keys together.-combinePubKeys :: Ctx -> [PubKey] -> Maybe PubKey-combinePubKeys _ [] = Nothing-combinePubKeys (Ctx ctx) pubs = unsafePerformIO $-  pointers [] pubs $ \ps ->-    allocaArray (length ps) $ \a -> do-      out <- mallocBytes 64-      pokeArray a ps-      ret <- ecPubKeyCombine ctx out a (fromIntegral $ length ps)-      if isSuccess ret-        then do-          bs <- 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 =-      unsafeUseByteString pub_key $ \(p, _) ->-        pointers (p : ps) pub_keys f--tweakNegate :: Ctx -> Tweak -> Maybe Tweak-tweakNegate (Ctx ctx) (Tweak t) = unsafePerformIO $-  unsafeUseByteString new $ \(out, _) -> do-    ret <- ecTweakNegate ctx out-    if isSuccess ret-      then return (Just (Tweak new))-      else return Nothing-  where-    new = BS.copy t--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--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+import Crypto.Secp256k1.Internal.Base+import Crypto.Secp256k1.Internal.Context
− src/Crypto/Secp256k1/Internal.hs
@@ -1,280 +0,0 @@-{-# LANGUAGE ImportQualifiedPost #-}---- |--- Module      : Crypto.Secp256k1.Internal--- License     : UNLICENSE--- Maintainer  : Jean-Pierre Rupp <jprupp@protonmail.ch>--- Stability   : experimental--- Portability : POSIX------ The API for this module may change at any time. This is an internal module only--- exposed for hacking and experimentation.-module Crypto.Secp256k1.Internal where--import Data.ByteString (ByteString)-import Data.ByteString qualified as BS-import Data.ByteString.Unsafe qualified as BU-import Foreign (FunPtr, Ptr, castPtr)-import Foreign.C-  ( CInt (..),-    CSize (..),-    CString,-    CUChar,-    CUInt (..),-  )-import GHC.Generics (Selector (selDecidedStrictness))-import System.Entropy (getEntropy)--data LCtx--data PubKey64--data Msg32--data Sig64--data Seed32--data Compact64--data SecKey32--data Tweak32--type CtxFlags = CUInt--type SerFlags = CUInt--type Ret = CInt--type NonceFun a =-  Ptr CUChar ->-  Ptr CUChar ->-  Ptr CUChar ->-  Ptr CUChar ->-  Ptr a ->-  CInt ->-  IO CInt--verify :: CtxFlags-verify = 0x0101--sign :: CtxFlags-sign = 0x0201--signVerify :: CtxFlags-signVerify = 0x0301--compressed :: SerFlags-compressed = 0x0102--uncompressed :: SerFlags-uncompressed = 0x0002--isSuccess :: Ret -> Bool-isSuccess 0 = False-isSuccess 1 = True-isSuccess n = error $ "isSuccess expected 0 or 1 but got " ++ show n--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)--withRandomSeed :: (Ptr Seed32 -> IO a) -> IO a-withRandomSeed go = do-  bs <- getEntropy 32-  useByteString bs $ go . fst--foreign import ccall safe "secp256k1.h secp256k1_context_create"-  contextCreate ::-    CtxFlags ->-    IO (Ptr LCtx)--foreign import ccall safe "secp256k1.h secp256k1_context_clone"-  contextClone ::-    Ptr LCtx ->-    IO (Ptr LCtx)--foreign import ccall safe "secp256k1.h secp256k1_context_destroy"-  contextDestroy ::-    Ptr LCtx ->-    IO ()--foreign import ccall safe "secp256k1.h secp256k1_context_set_illegal_callback"-  setIllegalCallback ::-    Ptr LCtx ->-    -- | message, data-    FunPtr (CString -> Ptr a -> IO ()) ->-    -- | data-    Ptr a ->-    IO ()--foreign import ccall safe "secp256k1.h secp256k1_context_set_error_callback"-  setErrorCallback ::-    Ptr LCtx ->-    -- | message, data-    FunPtr (CString -> Ptr a -> IO ()) ->-    -- | data-    Ptr a ->-    IO ()--foreign import ccall safe "secp256k1.h secp256k1_ec_pubkey_parse"-  ecPubKeyParse ::-    Ptr LCtx ->-    Ptr PubKey64 ->-    -- | encoded public key array-    Ptr CUChar ->-    -- | size of encoded public key array-    CSize ->-    IO Ret--foreign import ccall safe "secp256k1.h secp256k1_ec_pubkey_serialize"-  ecPubKeySerialize ::-    Ptr LCtx ->-    -- | array for encoded public key, must be large enough-    Ptr CUChar ->-    -- | size of encoded public key, will be updated-    Ptr CSize ->-    Ptr PubKey64 ->-    SerFlags ->-    IO Ret--foreign import ccall safe "secp256k1.h secp256k1_ecdsa_signature_parse_compact"-  ecdsaSignatureParseCompact ::-    Ptr LCtx ->-    Ptr Sig64 ->-    Ptr Compact64 ->-    IO Ret--foreign import ccall safe "secp256k1.h secp256k1_ecdsa_signature_parse_der"-  ecdsaSignatureParseDer ::-    Ptr LCtx ->-    Ptr Sig64 ->-    -- | encoded DER signature-    Ptr CUChar ->-    -- | size of encoded signature-    CSize ->-    IO Ret--foreign import ccall safe "secp256k1.h secp256k1_ecdsa_signature_serialize_der"-  ecdsaSignatureSerializeDer ::-    Ptr LCtx ->-    -- | array for encoded signature, must be large enough-    Ptr CUChar ->-    -- | size of encoded signature, will be updated-    Ptr CSize ->-    Ptr Sig64 ->-    IO Ret--foreign import ccall safe "secp256k1.h secp256k1_ecdsa_signature_serialize_compact"-  ecdsaSignatureSerializeCompact ::-    Ptr LCtx ->-    Ptr Compact64 ->-    Ptr Sig64 ->-    IO Ret--foreign import ccall safe "secp256k1.h secp256k1_ecdsa_verify"-  ecdsaVerify ::-    Ptr LCtx ->-    Ptr Sig64 ->-    Ptr Msg32 ->-    Ptr PubKey64 ->-    IO Ret--foreign import ccall safe "secp256k1.h secp256k1_ecdsa_signature_normalize"-  ecdsaSignatureNormalize ::-    Ptr LCtx ->-    -- | output-    Ptr Sig64 ->-    -- | input-    Ptr Sig64 ->-    IO Ret--foreign import ccall safe "secp256k1.h secp256k1_ecdsa_sign"-  ecdsaSign ::-    Ptr LCtx ->-    Ptr Sig64 ->-    Ptr Msg32 ->-    Ptr SecKey32 ->-    FunPtr (NonceFun a) ->-    -- | nonce data-    Ptr a ->-    IO Ret--foreign import ccall safe "secp256k1.h secp256k1_ec_seckey_verify"-  ecSecKeyVerify ::-    Ptr LCtx ->-    Ptr SecKey32 ->-    IO Ret--foreign import ccall safe "secp256k1.h secp256k1_ec_pubkey_create"-  ecPubKeyCreate ::-    Ptr LCtx ->-    Ptr PubKey64 ->-    Ptr SecKey32 ->-    IO Ret--foreign import ccall safe "secp256k1.h secp256k1_ec_privkey_tweak_add"-  ecSecKeyTweakAdd ::-    Ptr LCtx ->-    Ptr SecKey32 ->-    Ptr Tweak32 ->-    IO Ret--foreign import ccall safe "secp256k1.h secp256k1_ec_privkey_negate"-  ecTweakNegate ::-    Ptr LCtx ->-    Ptr Tweak32 ->-    IO Ret--foreign import ccall unsafe "secp256k1.h secp256k1_ec_pubkey_tweak_add"-  ecPubKeyTweakAdd ::-    Ptr LCtx ->-    Ptr PubKey64 ->-    Ptr Tweak32 ->-    IO Ret--foreign import ccall safe "secp256k1.h secp256k1_ec_privkey_tweak_mul"-  ecSecKeyTweakMul ::-    Ptr LCtx ->-    Ptr SecKey32 ->-    Ptr Tweak32 ->-    IO Ret--foreign import ccall safe "secp256k1.h secp256k1_ec_pubkey_tweak_mul"-  ecPubKeyTweakMul ::-    Ptr LCtx ->-    Ptr PubKey64 ->-    Ptr Tweak32 ->-    IO Ret--foreign import ccall safe "secp256k1.h secp256k1_context_randomize"-  contextRandomize ::-    Ptr LCtx ->-    Ptr Seed32 ->-    IO Ret--foreign import ccall safe "secp256k1.h secp256k1_ec_pubkey_combine"-  ecPubKeyCombine ::-    Ptr LCtx ->-    -- | pointer to public key storage-    Ptr PubKey64 ->-    -- | pointer to array of public keys-    Ptr (Ptr PubKey64) ->-    -- | number of public keys-    CInt ->-    IO Ret
+ src/Crypto/Secp256k1/Internal/Base.hs view
@@ -0,0 +1,430 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DuplicateRecordFields #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE ImportQualifiedPost #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedRecordDot #-}+{-# LANGUAGE NoFieldSelectors #-}++-- |+-- Module      : Crypto.Secp256k1+-- License     : UNLICENSE+-- Maintainer  : Jean-Pierre Rupp <jprupp@protonmail.ch>+-- Stability   : experimental+-- Portability : POSIX+--+-- Crytpographic functions from Bitcoin’s secp256k1 library.+--+-- The API for this module may change at any time. This is an internal module only+-- exposed for hacking and experimentation.+module Crypto.Secp256k1.Internal.Base where++import Control.DeepSeq (NFData)+import Control.Exception (bracket)+import Control.Monad (replicateM, unless, (<=<))+import Crypto.Secp256k1.Internal.BaseOps+  ( ecPubKeyCombine,+    ecPubKeyCreate,+    ecPubKeyParse,+    ecPubKeySerialize,+    ecPubKeyTweakAdd,+    ecPubKeyTweakMul,+    ecSecKeyTweakAdd,+    ecSecKeyTweakMul,+    ecTweakNegate,+    ecdsaSign,+    ecdsaSignatureNormalize,+    ecdsaSignatureParseCompact,+    ecdsaSignatureParseDer,+    ecdsaSignatureSerializeCompact,+    ecdsaSignatureSerializeDer,+    ecdsaVerify,+  )+import Crypto.Secp256k1.Internal.Context (Ctx (..))+import Crypto.Secp256k1.Internal.ForeignTypes+  ( LCtx,+    compressed,+    isSuccess,+    uncompressed,+  )+import Crypto.Secp256k1.Internal.Util+  ( decodeHex,+    packByteString,+    showsHex,+    unsafePackByteString,+    unsafeUseByteString,+  )+import Data.ByteString (ByteString)+import Data.ByteString qualified as BS+import Data.Hashable (Hashable (..))+import Data.Maybe (fromJust, fromMaybe, isJust)+import Data.String (IsString (..))+import Foreign+  ( Bits (bitSize),+    Ptr,+    alloca,+    allocaArray,+    allocaBytes,+    free,+    mallocBytes,+    nullFunPtr,+    nullPtr,+    peek,+    poke,+    pokeArray,+  )+import GHC.Generics (Generic)+import System.IO.Unsafe (unsafePerformIO)+import Test.QuickCheck+  ( Arbitrary (..),+    arbitraryBoundedRandom,+    suchThat,+  )+import Text.Read+  ( Lexeme (String),+    lexP,+    parens,+    pfail,+    readPrec,+  )++newtype PubKey = PubKey {get :: ByteString}+  deriving (Eq, Generic, Hashable, NFData)++newtype Msg = Msg {get :: ByteString}+  deriving (Eq, Generic, Hashable, NFData)++newtype Sig = Sig {get :: ByteString}+  deriving (Eq, Generic, Hashable, NFData)++newtype SecKey = SecKey {get :: ByteString}+  deriving (Eq, Generic, Hashable, NFData)++newtype Tweak = Tweak {get :: ByteString}+  deriving (Eq, Generic, Hashable, NFData)++newtype CompactSig = CompactSig {get :: ByteString}+  deriving (Eq, Generic, Hashable, NFData)++instance Read PubKey where+  readPrec = parens $ do+    String str <- lexP+    maybe pfail return $ pubKey =<< decodeHex str++instance IsString PubKey where+  fromString = fromMaybe e . (pubKey <=< decodeHex)+    where+      e = error "Could not decode public key from hex string"++instance Show PubKey where+  showsPrec _ = showsHex . (.get)++instance Read Msg where+  readPrec = parens $ do+    String str <- lexP+    maybe pfail return $ msg =<< decodeHex str++instance IsString Msg where+  fromString = fromMaybe e . (msg <=< decodeHex)+    where+      e = error "Could not decode message from hex string"++instance Show Msg where+  showsPrec _ = showsHex . (.get)++instance Read Sig where+  readPrec = parens $ do+    String str <- lexP+    maybe pfail return $ sig =<< decodeHex str++instance IsString Sig where+  fromString = fromMaybe e . (sig <=< decodeHex)+    where+      e = error "Could not decode signature from hex string"++instance Show Sig where+  showsPrec _ = showsHex . (.get)++instance Read SecKey where+  readPrec = parens $ do+    String str <- lexP+    maybe pfail return $ secKey =<< decodeHex str++instance IsString SecKey where+  fromString = fromMaybe e . (secKey <=< decodeHex)+    where+      e = error "Colud not decode secret key from hex string"++instance Show SecKey where+  showsPrec _ = showsHex . (.get)++instance Read Tweak where+  readPrec = parens $ do+    String str <- lexP+    maybe pfail return $ tweak =<< decodeHex str++instance IsString Tweak where+  fromString = fromMaybe e . (tweak <=< decodeHex)+    where+      e = error "Could not decode tweak from hex string"++instance Show Tweak where+  showsPrec _ = showsHex . (.get)++-- | Import 64-byte 'ByteString' as 'Sig'.+sig :: ByteString -> Maybe Sig+sig bs+  | BS.length bs == 64 = Just (Sig bs)+  | otherwise = Nothing++-- | Import 64-byte 'ByteString' as 'PubKey'.+pubKey :: ByteString -> Maybe PubKey+pubKey bs+  | BS.length bs == 64 = Just (PubKey bs)+  | otherwise = Nothing++-- | Import 32-byte 'ByteString' as 'Msg'.+msg :: ByteString -> Maybe Msg+msg bs+  | BS.length bs == 32 = Just (Msg bs)+  | otherwise = Nothing++-- | Import 32-byte 'ByteString' as 'SecKey'.+secKey :: ByteString -> Maybe SecKey+secKey bs+  | BS.length bs == 32 = Just (SecKey bs)+  | otherwise = Nothing++compactSig :: ByteString -> Maybe CompactSig+compactSig bs+  | BS.length bs == 64 = Just (CompactSig bs)+  | otherwise = Nothing++-- | Convert signature to a normalized lower-S form. 'Nothing' indicates that it+-- was already normal.+normalizeSig :: Ctx -> Sig -> Maybe Sig+normalizeSig (Ctx ctx) (Sig sig) = unsafePerformIO $+  unsafeUseByteString sig $ \(sig_in, _) -> do+    sig_out <- mallocBytes 64+    ret <- ecdsaSignatureNormalize ctx sig_out sig_in+    if isSuccess ret+      then do+        bs <- unsafePackByteString (sig_out, 64)+        return (Just (Sig bs))+      else do+        free sig_out+        return Nothing++-- | 32-Byte 'ByteString' as 'Tweak'.+tweak :: ByteString -> Maybe Tweak+tweak bs+  | BS.length bs == 32 = Just (Tweak bs)+  | otherwise = Nothing++-- | Import DER-encoded public key.+importPubKey :: Ctx -> ByteString -> Maybe PubKey+importPubKey (Ctx ctx) bs+  | BS.null bs = Nothing+  | otherwise = unsafePerformIO $+      unsafeUseByteString bs $ \(input, len) -> do+        pub_key <- mallocBytes 64+        ret <- ecPubKeyParse ctx pub_key input len+        if isSuccess ret+          then do+            out <- unsafePackByteString (pub_key, 64)+            return (Just (PubKey out))+          else do+            free pub_key+            return Nothing++-- | Encode public key as DER. First argument 'True' for compressed output.+exportPubKey :: Ctx -> Bool -> PubKey -> ByteString+exportPubKey (Ctx ctx) compress (PubKey in_bs) = unsafePerformIO $+  unsafeUseByteString in_bs $ \(in_ptr, _) ->+    alloca $ \len_ptr ->+      allocaBytes len $ \out_ptr -> do+        poke len_ptr $ fromIntegral len+        ret <- ecPubKeySerialize ctx out_ptr len_ptr in_ptr flags+        unless (isSuccess ret) $ error "could not serialize public key"+        final_len <- peek len_ptr+        packByteString (out_ptr, final_len)+  where+    len = if compress then 33 else 65+    flags = if compress then compressed else uncompressed++exportCompactSig :: Ctx -> Sig -> CompactSig+exportCompactSig (Ctx ctx) (Sig sig_bs) = unsafePerformIO $+  unsafeUseByteString sig_bs $ \(sig_ptr, _) -> do+    out_ptr <- mallocBytes 64+    ret <- ecdsaSignatureSerializeCompact ctx out_ptr sig_ptr+    unless (isSuccess ret) $ do+      free out_ptr+      error "Could not obtain compact signature"+    out_bs <- unsafePackByteString (out_ptr, 64)+    return $ CompactSig out_bs++importCompactSig :: Ctx -> CompactSig -> Maybe Sig+importCompactSig (Ctx ctx) (CompactSig compact_sig) = unsafePerformIO $+  unsafeUseByteString compact_sig $ \(compact_ptr, _) -> do+    out_sig <- mallocBytes 64+    ret <- ecdsaSignatureParseCompact ctx out_sig compact_ptr+    if isSuccess ret+      then do+        out_bs <- unsafePackByteString (out_sig, 64)+        return (Just (Sig out_bs))+      else do+        free out_sig+        return Nothing++-- | Import DER-encoded signature.+importSig :: Ctx -> ByteString -> Maybe Sig+importSig (Ctx ctx) bs+  | BS.null bs = Nothing+  | otherwise = unsafePerformIO $+      unsafeUseByteString bs $ \(in_ptr, in_len) -> do+        out_sig <- mallocBytes 64+        ret <- ecdsaSignatureParseDer ctx out_sig in_ptr in_len+        if isSuccess ret+          then do+            out_bs <- unsafePackByteString (out_sig, 64)+            return (Just (Sig out_bs))+          else do+            free out_sig+            return Nothing++-- | Encode signature as strict DER.+exportSig :: Ctx -> Sig -> ByteString+exportSig (Ctx ctx) (Sig in_sig) = unsafePerformIO $+  unsafeUseByteString in_sig $ \(in_ptr, _) ->+    alloca $ \out_len ->+      allocaBytes 72 $ \out_ptr -> do+        poke out_len 72+        ret <- ecdsaSignatureSerializeDer ctx out_ptr out_len in_ptr+        unless (isSuccess ret) $ error "could not serialize signature"+        final_len <- peek out_len+        packByteString (out_ptr, final_len)++-- | Verify message signature. 'True' means that the signature is correct.+verifySig :: Ctx -> PubKey -> Sig -> Msg -> Bool+verifySig (Ctx ctx) (PubKey pub_key) (Sig sig) (Msg m) = unsafePerformIO $+  unsafeUseByteString pub_key $ \(pub_key_ptr, _) ->+    unsafeUseByteString sig $ \(sig_ptr, _) ->+      unsafeUseByteString m $ \(msg_ptr, _) ->+        isSuccess <$> ecdsaVerify ctx sig_ptr msg_ptr pub_key_ptr++signMsg :: Ctx -> SecKey -> Msg -> Sig+signMsg (Ctx ctx) (SecKey sec_key) (Msg m) = unsafePerformIO $+  unsafeUseByteString sec_key $ \(sec_key_ptr, _) ->+    unsafeUseByteString m $ \(msg_ptr, _) -> do+      sig_ptr <- mallocBytes 64+      ret <- ecdsaSign ctx sig_ptr msg_ptr sec_key_ptr nullFunPtr nullPtr+      unless (isSuccess ret) $ do+        free sig_ptr+        error "could not sign message"+      Sig <$> unsafePackByteString (sig_ptr, 64)++derivePubKey :: Ctx -> SecKey -> PubKey+derivePubKey (Ctx ctx) (SecKey sec_key) = unsafePerformIO $+  unsafeUseByteString sec_key $ \(sec_key_ptr, _) -> do+    pub_key_ptr <- mallocBytes 64+    ret <- ecPubKeyCreate ctx pub_key_ptr sec_key_ptr+    unless (isSuccess ret) $ do+      free pub_key_ptr+      error "could not compute public key"+    PubKey <$> unsafePackByteString (pub_key_ptr, 64)++-- | Add tweak to secret key.+tweakAddSecKey :: Ctx -> SecKey -> Tweak -> Maybe SecKey+tweakAddSecKey (Ctx ctx) (SecKey sec_key) (Tweak t) = unsafePerformIO $+  unsafeUseByteString new_bs $ \(sec_key_ptr, _) ->+    unsafeUseByteString t $ \(tweak_ptr, _) -> do+      ret <- ecSecKeyTweakAdd ctx sec_key_ptr tweak_ptr+      if isSuccess ret+        then return (Just (SecKey new_bs))+        else return Nothing+  where+    new_bs = BS.copy sec_key++-- | Multiply secret key by tweak.+tweakMulSecKey :: Ctx -> SecKey -> Tweak -> Maybe SecKey+tweakMulSecKey (Ctx ctx) (SecKey sec_key) (Tweak t) = unsafePerformIO $+  unsafeUseByteString new_bs $ \(sec_key_ptr, _) ->+    unsafeUseByteString t $ \(tweak_ptr, _) -> do+      ret <- ecSecKeyTweakMul ctx sec_key_ptr tweak_ptr+      if isSuccess ret+        then return (Just (SecKey new_bs))+        else return Nothing+  where+    new_bs = BS.copy sec_key++-- | Add tweak to public key. Tweak is multiplied first by G to obtain a point.+tweakAddPubKey :: Ctx -> PubKey -> Tweak -> Maybe PubKey+tweakAddPubKey (Ctx ctx) (PubKey pub_key) (Tweak t) = unsafePerformIO $+  unsafeUseByteString new_bs $ \(pub_key_ptr, _) ->+    unsafeUseByteString t $ \(tweak_ptr, _) -> do+      ret <- ecPubKeyTweakAdd ctx pub_key_ptr tweak_ptr+      if isSuccess ret+        then return (Just (PubKey new_bs))+        else return Nothing+  where+    new_bs = BS.copy pub_key++-- | Multiply public key by tweak. Tweak is multiplied first by G to obtain a+-- point.+tweakMulPubKey :: Ctx -> PubKey -> Tweak -> Maybe PubKey+tweakMulPubKey (Ctx ctx) (PubKey pub_key) (Tweak t) = unsafePerformIO $+  unsafeUseByteString new_bs $ \(pub_key_ptr, _) ->+    unsafeUseByteString t $ \(tweak_ptr, _) -> do+      ret <- ecPubKeyTweakMul ctx pub_key_ptr tweak_ptr+      if isSuccess ret+        then return (Just (PubKey new_bs))+        else return Nothing+  where+    new_bs = BS.copy pub_key++-- | Add multiple public keys together.+combinePubKeys :: Ctx -> [PubKey] -> Maybe PubKey+combinePubKeys _ [] = Nothing+combinePubKeys (Ctx ctx) pubs = unsafePerformIO $+  pointers [] pubs $ \ps ->+    allocaArray (length ps) $ \a -> do+      out <- mallocBytes 64+      pokeArray a ps+      ret <- ecPubKeyCombine ctx out a (fromIntegral $ length ps)+      if isSuccess ret+        then do+          bs <- 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 =+      unsafeUseByteString pub_key $ \(p, _) ->+        pointers (p : ps) pub_keys f++tweakNegate :: Ctx -> Tweak -> Maybe Tweak+tweakNegate (Ctx ctx) (Tweak t) = unsafePerformIO $+  unsafeUseByteString new $ \(out, _) -> do+    ret <- ecTweakNegate ctx out+    if isSuccess ret+      then return (Just (Tweak new))+      else return Nothing+  where+    new = BS.copy t++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++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
+ src/Crypto/Secp256k1/Internal/BaseOps.hs view
@@ -0,0 +1,172 @@+-- |+-- Module      : Crypto.Secp256k1.Internal.BaseOps+-- License     : UNLICENSE+-- Maintainer  : Jean-Pierre Rupp <jprupp@protonmail.ch>+-- Stability   : experimental+-- Portability : POSIX+--+-- The API for this module may change at any time. This is an internal module only+-- exposed for hacking and experimentation.+module Crypto.Secp256k1.Internal.BaseOps where++import Crypto.Secp256k1.Internal.ForeignTypes+  ( Compact64,+    LCtx,+    Msg32,+    NonceFun,+    PubKey64,+    Ret,+    SecKey32,+    Seed32,+    SerFlags,+    Sig64,+    Tweak32,+  )+import Foreign (FunPtr, Ptr)+import Foreign.C+  ( CInt (..),+    CSize (..),+    CUChar,+    CUInt (..),+  )++foreign import ccall safe "secp256k1.h secp256k1_ec_pubkey_parse"+  ecPubKeyParse ::+    Ptr LCtx ->+    Ptr PubKey64 ->+    -- | encoded public key array+    Ptr CUChar ->+    -- | size of encoded public key array+    CSize ->+    IO Ret++foreign import ccall safe "secp256k1.h secp256k1_ec_pubkey_serialize"+  ecPubKeySerialize ::+    Ptr LCtx ->+    -- | array for encoded public key, must be large enough+    Ptr CUChar ->+    -- | size of encoded public key, will be updated+    Ptr CSize ->+    Ptr PubKey64 ->+    SerFlags ->+    IO Ret++foreign import ccall safe "secp256k1.h secp256k1_ecdsa_signature_parse_compact"+  ecdsaSignatureParseCompact ::+    Ptr LCtx ->+    Ptr Sig64 ->+    Ptr Compact64 ->+    IO Ret++foreign import ccall safe "secp256k1.h secp256k1_ecdsa_signature_parse_der"+  ecdsaSignatureParseDer ::+    Ptr LCtx ->+    Ptr Sig64 ->+    -- | encoded DER signature+    Ptr CUChar ->+    -- | size of encoded signature+    CSize ->+    IO Ret++foreign import ccall safe "secp256k1.h secp256k1_ecdsa_signature_serialize_der"+  ecdsaSignatureSerializeDer ::+    Ptr LCtx ->+    -- | array for encoded signature, must be large enough+    Ptr CUChar ->+    -- | size of encoded signature, will be updated+    Ptr CSize ->+    Ptr Sig64 ->+    IO Ret++foreign import ccall safe "secp256k1.h secp256k1_ecdsa_signature_serialize_compact"+  ecdsaSignatureSerializeCompact ::+    Ptr LCtx ->+    Ptr Compact64 ->+    Ptr Sig64 ->+    IO Ret++foreign import ccall safe "secp256k1.h secp256k1_ecdsa_verify"+  ecdsaVerify ::+    Ptr LCtx ->+    Ptr Sig64 ->+    Ptr Msg32 ->+    Ptr PubKey64 ->+    IO Ret++foreign import ccall safe "secp256k1.h secp256k1_ecdsa_signature_normalize"+  ecdsaSignatureNormalize ::+    Ptr LCtx ->+    -- | output+    Ptr Sig64 ->+    -- | input+    Ptr Sig64 ->+    IO Ret++foreign import ccall safe "secp256k1.h secp256k1_ecdsa_sign"+  ecdsaSign ::+    Ptr LCtx ->+    Ptr Sig64 ->+    Ptr Msg32 ->+    Ptr SecKey32 ->+    FunPtr (NonceFun a) ->+    -- | nonce data+    Ptr a ->+    IO Ret++foreign import ccall safe "secp256k1.h secp256k1_ec_seckey_verify"+  ecSecKeyVerify ::+    Ptr LCtx ->+    Ptr SecKey32 ->+    IO Ret++foreign import ccall safe "secp256k1.h secp256k1_ec_pubkey_create"+  ecPubKeyCreate ::+    Ptr LCtx ->+    Ptr PubKey64 ->+    Ptr SecKey32 ->+    IO Ret++foreign import ccall safe "secp256k1.h secp256k1_ec_privkey_tweak_add"+  ecSecKeyTweakAdd ::+    Ptr LCtx ->+    Ptr SecKey32 ->+    Ptr Tweak32 ->+    IO Ret++foreign import ccall safe "secp256k1.h secp256k1_ec_privkey_negate"+  ecTweakNegate ::+    Ptr LCtx ->+    Ptr Tweak32 ->+    IO Ret++foreign import ccall unsafe "secp256k1.h secp256k1_ec_pubkey_tweak_add"+  ecPubKeyTweakAdd ::+    Ptr LCtx ->+    Ptr PubKey64 ->+    Ptr Tweak32 ->+    IO Ret++foreign import ccall safe "secp256k1.h secp256k1_ec_privkey_tweak_mul"+  ecSecKeyTweakMul ::+    Ptr LCtx ->+    Ptr SecKey32 ->+    Ptr Tweak32 ->+    IO Ret++foreign import ccall safe "secp256k1.h secp256k1_ec_pubkey_tweak_mul"+  ecPubKeyTweakMul ::+    Ptr LCtx ->+    Ptr PubKey64 ->+    Ptr Tweak32 ->+    IO Ret++foreign import ccall safe "secp256k1.h secp256k1_ec_pubkey_combine"+  ecPubKeyCombine ::+    Ptr LCtx ->+    -- | pointer to public key storage+    Ptr PubKey64 ->+    -- | pointer to array of public keys+    Ptr (Ptr PubKey64) ->+    -- | number of public keys+    CInt ->+    IO Ret
+ src/Crypto/Secp256k1/Internal/Context.hs view
@@ -0,0 +1,94 @@+{-# LANGUAGE OverloadedRecordDot #-}+{-# LANGUAGE NoFieldSelectors #-}++-- |+-- Module      : Crypto.Secp256k1.Internal.Context+-- License     : UNLICENSE+-- Maintainer  : Jean-Pierre Rupp <jprupp@protonmail.ch>+-- Stability   : experimental+-- Portability : POSIX+--+-- The API for this module may change at any time. This is an internal module only+-- exposed for hacking and experimentation.+module Crypto.Secp256k1.Internal.Context where++import Control.Exception (bracket)+import Control.Monad (unless)+import Crypto.Secp256k1.Internal.ForeignTypes (CtxFlags, LCtx, Ret, Seed32, isSuccess)+import Crypto.Secp256k1.Internal.Util (withRandomSeed)+import Foreign (FunPtr, Ptr)+import Foreign.C (CInt (..), CString, CUInt (..))+import System.IO.Unsafe (unsafePerformIO)++newtype Ctx = Ctx {get :: Ptr LCtx}++randomizeContext :: Ctx -> IO ()+randomizeContext (Ctx ctx) = do+  ret <- withRandomSeed $ contextRandomize ctx+  unless (isSuccess ret) $ error "Could not randomize context"++createContext :: IO Ctx+createContext = Ctx <$> contextCreate signVerify++cloneContext :: Ctx -> IO Ctx+cloneContext = fmap Ctx . contextClone . (.get)++destroyContext :: Ctx -> IO ()+destroyContext = contextDestroy . (.get)++withContext :: (Ctx -> IO a) -> IO a+withContext = bracket create destroy+  where+    create = do+      ctx <- createContext+      randomizeContext ctx+      return ctx+    destroy = destroyContext++verify :: CtxFlags+verify = 0x0101++sign :: CtxFlags+sign = 0x0201++signVerify :: CtxFlags+signVerify = 0x0301++foreign import ccall safe "secp256k1.h secp256k1_context_create"+  contextCreate ::+    CtxFlags ->+    IO (Ptr LCtx)++foreign import ccall safe "secp256k1.h secp256k1_context_clone"+  contextClone ::+    Ptr LCtx ->+    IO (Ptr LCtx)++foreign import ccall safe "secp256k1.h secp256k1_context_destroy"+  contextDestroy ::+    Ptr LCtx ->+    IO ()++foreign import ccall safe "secp256k1.h secp256k1_context_set_illegal_callback"+  setIllegalCallback ::+    Ptr LCtx ->+    -- | message, data+    FunPtr (CString -> Ptr a -> IO ()) ->+    -- | data+    Ptr a ->+    IO ()++foreign import ccall safe "secp256k1.h secp256k1_context_set_error_callback"+  setErrorCallback ::+    Ptr LCtx ->+    -- | message, data+    FunPtr (CString -> Ptr a -> IO ()) ->+    -- | data+    Ptr a ->+    IO ()++foreign import ccall safe "secp256k1.h secp256k1_context_randomize"+  contextRandomize ::+    Ptr LCtx ->+    Ptr Seed32 ->+    IO Ret
+ src/Crypto/Secp256k1/Internal/ForeignTypes.hs view
@@ -0,0 +1,57 @@+-- |+-- Module      : Crypto.Secp256k1.Internal.ForeignTypes+-- License     : UNLICENSE+-- Maintainer  : Jean-Pierre Rupp <jprupp@protonmail.ch>+-- Stability   : experimental+-- Portability : POSIX+--+-- The API for this module may change at any time. This is an internal module only+-- exposed for hacking and experimentation.+module Crypto.Secp256k1.Internal.ForeignTypes where++import Foreign (Ptr)+import Foreign.C (CInt (..), CUChar, CUInt (..))++data LCtx++data PubKey64++data Msg32++data Sig64++data Seed32++data Compact64++data SecKey32++data Tweak32++data RecSig65++type CtxFlags = CUInt++type SerFlags = CUInt++type Ret = CInt++type NonceFun a =+  Ptr CUChar ->+  Ptr CUChar ->+  Ptr CUChar ->+  Ptr CUChar ->+  Ptr a ->+  CInt ->+  IO CInt++compressed :: SerFlags+compressed = 0x0102++uncompressed :: SerFlags+uncompressed = 0x0002++isSuccess :: Ret -> Bool+isSuccess 0 = False+isSuccess 1 = True+isSuccess n = error $ "isSuccess expected 0 or 1 but got " ++ show n
+ src/Crypto/Secp256k1/Internal/Util.hs view
@@ -0,0 +1,55 @@+{-# LANGUAGE FlexibleContexts #-}++-- |+-- Module      : Crypto.Secp256k1.Internal.Util+-- License     : UNLICENSE+-- Maintainer  : Jean-Pierre Rupp <jprupp@protonmail.ch>+-- Stability   : experimental+-- Portability : POSIX+--+-- The API for this module may change at any time. This is an internal module only+-- exposed for hacking and experimentation.+module Crypto.Secp256k1.Internal.Util where++import Crypto.Secp256k1.Internal.ForeignTypes (Seed32)+import Data.Base16.Types (assertBase16, extractBase16)+import Data.ByteString (ByteString)+import qualified Data.ByteString as BS+import Data.ByteString.Base16 (decodeBase16, encodeBase16, isBase16)+import qualified Data.ByteString.Unsafe as BU+import Data.String.Conversions (ConvertibleStrings, cs)+import Foreign (Ptr, castPtr)+import Foreign.C (CSize (..))+import System.Entropy (getEntropy)++decodeHex :: (ConvertibleStrings a ByteString) => a -> Maybe ByteString+decodeHex str =+  if isBase16 $ cs str+    then Just . decodeBase16 $ assertBase16 $ cs str+    else Nothing++showsHex :: ByteString -> ShowS+showsHex = shows . extractBase16 . encodeBase16++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)++withRandomSeed :: (Ptr Seed32 -> IO a) -> IO a+withRandomSeed go = do+  bs <- getEntropy 32+  useByteString bs $ go . fst
test/Crypto/Secp256k1/InternalSpec.hs view
@@ -5,7 +5,10 @@ import Control.Exception import Control.Monad import Control.Monad.Trans-import Crypto.Secp256k1.Internal+import Crypto.Secp256k1.Internal.BaseOps+import Crypto.Secp256k1.Internal.Context+import Crypto.Secp256k1.Internal.ForeignTypes+import Crypto.Secp256k1.Internal.Util import Data.Base16.Types (assertBase16) import Data.ByteString   ( ByteString,@@ -14,7 +17,6 @@     useAsCStringLen,   ) import Data.ByteString.Base16 (decodeBase16)-import Data.Either (fromRight) import Foreign import System.Entropy import Test.HUnit (Assertion, assertBool, assertEqual)