{-# LANGUAGE ImportQualifiedPost #-}
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 :: SerFlags
verify = SerFlags
0x0101
sign :: CtxFlags
sign :: SerFlags
sign = SerFlags
0x0201
signVerify :: CtxFlags
signVerify :: SerFlags
signVerify = SerFlags
0x0301
compressed :: SerFlags
compressed :: SerFlags
compressed = SerFlags
0x0102
uncompressed :: SerFlags
uncompressed :: SerFlags
uncompressed = SerFlags
0x0002
isSuccess :: Ret -> Bool
isSuccess :: Ret -> Bool
isSuccess Ret
0 = Bool
False
isSuccess Ret
1 = Bool
True
isSuccess Ret
n = [Char] -> Bool
forall a. HasCallStack => [Char] -> a
error ([Char] -> Bool) -> [Char] -> Bool
forall a b. (a -> b) -> a -> b
$ [Char]
"isSuccess expected 0 or 1 but got " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Ret -> [Char]
forall a. Show a => a -> [Char]
show Ret
n
unsafeUseByteString :: ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
unsafeUseByteString :: forall a b. ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
unsafeUseByteString ByteString
bs (Ptr a, CSize) -> IO b
f =
ByteString -> (CStringLen -> IO b) -> IO b
forall a. ByteString -> (CStringLen -> IO a) -> IO a
BU.unsafeUseAsCStringLen ByteString
bs ((CStringLen -> IO b) -> IO b) -> (CStringLen -> IO b) -> IO b
forall a b. (a -> b) -> a -> b
$ \(Ptr CChar
b, Int
l) ->
(Ptr a, CSize) -> IO b
f (Ptr CChar -> Ptr a
forall a b. Ptr a -> Ptr b
castPtr Ptr CChar
b, Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
l)
useByteString :: ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
useByteString :: forall a b. ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
useByteString ByteString
bs (Ptr a, CSize) -> IO b
f =
ByteString -> (CStringLen -> IO b) -> IO b
forall a. ByteString -> (CStringLen -> IO a) -> IO a
BS.useAsCStringLen ByteString
bs ((CStringLen -> IO b) -> IO b) -> (CStringLen -> IO b) -> IO b
forall a b. (a -> b) -> a -> b
$ \(Ptr CChar
b, Int
l) ->
(Ptr a, CSize) -> IO b
f (Ptr CChar -> Ptr a
forall a b. Ptr a -> Ptr b
castPtr Ptr CChar
b, Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
l)
unsafePackByteString :: (Ptr a, CSize) -> IO ByteString
unsafePackByteString :: forall a. (Ptr a, CSize) -> IO ByteString
unsafePackByteString (Ptr a
b, CSize
l) =
CStringLen -> IO ByteString
BU.unsafePackMallocCStringLen (Ptr a -> Ptr CChar
forall a b. Ptr a -> Ptr b
castPtr Ptr a
b, CSize -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
l)
packByteString :: (Ptr a, CSize) -> IO ByteString
packByteString :: forall a. (Ptr a, CSize) -> IO ByteString
packByteString (Ptr a
b, CSize
l) =
CStringLen -> IO ByteString
BS.packCStringLen (Ptr a -> Ptr CChar
forall a b. Ptr a -> Ptr b
castPtr Ptr a
b, CSize -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
l)
withRandomSeed :: (Ptr Seed32 -> IO a) -> IO a
withRandomSeed :: forall a. (Ptr Seed32 -> IO a) -> IO a
withRandomSeed Ptr Seed32 -> IO a
go = do
ByteString
bs <- Int -> IO ByteString
getEntropy Int
32
ByteString -> ((Ptr Seed32, CSize) -> IO a) -> IO a
forall a b. ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
useByteString ByteString
bs (((Ptr Seed32, CSize) -> IO a) -> IO a)
-> ((Ptr Seed32, CSize) -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ Ptr Seed32 -> IO a
go (Ptr Seed32 -> IO a)
-> ((Ptr Seed32, CSize) -> Ptr Seed32)
-> (Ptr Seed32, CSize)
-> IO a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Ptr Seed32, CSize) -> Ptr Seed32
forall a b. (a, b) -> a
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 ->
FunPtr (CString -> Ptr a -> IO ()) ->
Ptr a ->
IO ()
foreign import ccall safe "secp256k1.h secp256k1_context_set_error_callback"
setErrorCallback ::
Ptr LCtx ->
FunPtr (CString -> Ptr a -> IO ()) ->
Ptr a ->
IO ()
foreign import ccall safe "secp256k1.h secp256k1_ec_pubkey_parse"
ecPubKeyParse ::
Ptr LCtx ->
Ptr PubKey64 ->
Ptr CUChar ->
CSize ->
IO Ret
foreign import ccall safe "secp256k1.h secp256k1_ec_pubkey_serialize"
ecPubKeySerialize ::
Ptr LCtx ->
Ptr CUChar ->
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 ->
Ptr CUChar ->
CSize ->
IO Ret
foreign import ccall safe "secp256k1.h secp256k1_ecdsa_signature_serialize_der"
ecdsaSignatureSerializeDer ::
Ptr LCtx ->
Ptr CUChar ->
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 ->
Ptr Sig64 ->
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) ->
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 ->
Ptr PubKey64 ->
Ptr (Ptr PubKey64) ->
CInt ->
IO Ret