{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE RankNTypes #-}
module Crypto.Secp256k1.Prim where
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Unsafe as BU
import Foreign (FunPtr, Ptr, castPtr)
import Foreign.C (
CInt (..),
CSize (..),
CString,
CUChar,
CUInt (..),
)
import GHC.TypeNats (Nat)
import System.IO.Unsafe (unsafePerformIO)
data LCtx
data Pubkey64
data XonlyPubkey64
data Keypair96
data Msg32
data RecSig65
data Sig64
data Compact64
data Seed32
data Seckey32
data Tweak32
data
data Scratch
data Bytes (n :: Nat)
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
type NonceFunHardened a =
Ptr CUChar ->
Ptr CUChar ->
CSize ->
Ptr CUChar ->
Ptr CUChar ->
Ptr CUChar ->
CSize ->
Ptr a ->
IO CInt
type EcdhHashFun a =
Ptr CUChar ->
Ptr CUChar ->
Ptr CUChar ->
Ptr a ->
IO CInt
type Ctx = Ptr LCtx
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)
ctx :: Ctx
ctx :: Ctx
ctx = IO Ctx -> Ctx
forall a. IO a -> a
unsafePerformIO (IO Ctx -> Ctx) -> IO Ctx -> Ctx
forall a b. (a -> b) -> a -> b
$ SerFlags -> IO Ctx
contextCreate SerFlags
signVerify
{-# NOINLINE ctx #-}
foreign import ccall safe "secp256k1.h secp256k1_context_clone"
contextClone :: Ctx -> IO Ctx
foreign import ccall safe "secp256k1.h secp256k1_context_create"
contextCreate :: CtxFlags -> IO Ctx
foreign import ccall safe "secp256k1.h &secp256k1_context_destroy"
contextDestroy :: FunPtr (Ctx -> IO ())
foreign import ccall safe "secp256k1.h secp256k1_context_no_precomp"
contextNoPrecomp :: Ctx
foreign import ccall safe "secp256k1.h secp256k1_context_preallocated_clone"
contextPreallocatedClone :: Ctx -> Ptr (Bytes n) -> IO Ctx
foreign import ccall safe "secp256k1.h secp256k1_context_preallocated_clone_size"
contextPreallocatedCloneSize :: Ctx -> IO CSize
foreign import ccall safe "secp256k1.h secp256k1_context_preallocated_create"
contextPreallocatedCreate :: Ptr (Bytes n) -> CUInt -> IO Ctx
foreign import ccall safe "secp256k1.h secp256k1_context_preallocated_destroy"
contextPreallocatedDestroy :: Ctx -> IO ()
foreign import ccall safe "secp256k1.h secp256k1_context_preallocated_size"
contextPreallocatedSize :: CUInt -> IO CSize
foreign import ccall safe "secp256k1.h secp256k1_context_randomize"
contextRandomize :: Ctx -> Ptr Seed32 -> IO Ret
foreign import ccall safe "secp256k1.h secp256k1_context_set_error_callback"
setErrorCallback ::
Ctx ->
FunPtr (CString -> Ptr a -> IO ()) ->
Ptr a ->
IO ()
foreign import ccall safe "secp256k1.h secp256k1_context_set_illegal_callback"
setIllegalCallback ::
Ctx ->
FunPtr (CString -> Ptr a -> IO ()) ->
Ptr a ->
IO ()
foreign import ccall safe "secp256k1.h secp256k1_ecdh"
ecdh :: Ctx -> Ptr (Bytes n) -> Ptr Pubkey64 -> Ptr Seckey32 -> FunPtr (EcdhHashFun a) -> Ptr a -> IO Ret
foreign import ccall safe "secp256k1.h &secp256k1_ecdh_hash_function_default"
ecdhHashFunctionDefault :: FunPtr (EcdhHashFun a)
foreign import ccall safe "secp256k1.h &secp256k1_ecdh_hash_sha256"
ecdhHashSha256 :: FunPtr (EcdhHashFun a)
foreign import ccall safe "secp256k1.h secp256k1_ecdsa_recover"
ecdsaRecover :: Ctx -> Ptr Pubkey64 -> Ptr RecSig65 -> Ptr Msg32 -> IO Ret
foreign import ccall safe "secp256k1.h secp256k1_ecdsa_recoverable_signature_convert"
ecdsaRecoverableSignatureConvert :: Ctx -> Ptr Sig64 -> Ptr RecSig65 -> IO Ret
foreign import ccall safe "secp256k1.h secp256k1_ecdsa_recoverable_signature_parse_compact"
ecdsaRecoverableSignatureParseCompact :: Ctx -> Ptr RecSig65 -> Ptr (Bytes 64) -> CInt -> IO Ret
foreign import ccall safe "secp256k1.h secp256k1_ecdsa_recoverable_signature_serialize_compact"
ecdsaRecoverableSignatureSerializeCompact :: Ctx -> Ptr (Bytes 64) -> Ptr CInt -> Ptr RecSig65 -> IO Ret
foreign import ccall safe "secp256k1.h secp256k1_ecdsa_sign"
ecdsaSign ::
Ctx ->
Ptr Sig64 ->
Ptr Msg32 ->
Ptr Seckey32 ->
FunPtr (NonceFun a) ->
Ptr a ->
IO Ret
foreign import ccall safe "secp256k1.h secp256k1_ecdsa_signature_normalize"
ecdsaSignatureNormalize ::
Ctx ->
Ptr Sig64 ->
Ptr Sig64 ->
IO Ret
foreign import ccall safe "secp256k1.h secp256k1_ecdsa_signature_parse_compact"
ecdsaSignatureParseCompact ::
Ctx ->
Ptr Sig64 ->
Ptr Compact64 ->
IO Ret
foreign import ccall safe "secp256k1.h secp256k1_ecdsa_signature_parse_der"
ecdsaSignatureParseDer ::
Ctx ->
Ptr Sig64 ->
Ptr (Bytes n) ->
CSize ->
IO Ret
foreign import ccall safe "secp256k1.h secp256k1_ecdsa_signature_serialize_compact"
ecdsaSignatureSerializeCompact ::
Ctx ->
Ptr Compact64 ->
Ptr Sig64 ->
IO Ret
foreign import ccall safe "secp256k1.h secp256k1_ecdsa_signature_serialize_der"
ecdsaSignatureSerializeDer ::
Ctx ->
Ptr (Bytes n) ->
Ptr CSize ->
Ptr Sig64 ->
IO Ret
foreign import ccall safe "secp256k1.h secp256k1_ecdsa_sign_recoverable"
ecdsaSignRecoverable ::
Ctx -> Ptr RecSig65 -> Ptr Msg32 -> Ptr Seckey32 -> FunPtr (NonceFun a) -> Ptr a -> IO Ret
foreign import ccall safe "secp256k1.h secp256k1_ecdsa_verify"
ecdsaVerify ::
Ctx ->
Ptr Sig64 ->
Ptr Msg32 ->
Ptr Pubkey64 ->
IO Ret
{-# DEPRECATED ecPrivkeyNegate "use ecSeckeyNegate instead" #-}
foreign import ccall safe "secp256k1.h secp256k1_ec_privkey_negate"
ecPrivkeyNegate ::
Ctx ->
Ptr Tweak32 ->
IO Ret
{-# DEPRECATED ecPrivkeyTweakAdd "use ecSeckeyTweakAdd instead" #-}
foreign import ccall safe "secp256k1.h secp256k1_ec_privkey_tweak_add"
ecPrivkeyTweakAdd ::
Ctx ->
Ptr Seckey32 ->
Ptr Tweak32 ->
IO Ret
{-# DEPRECATED ecPrivkeyTweakMul "use ecSeckeyTweakMul instead" #-}
foreign import ccall safe "secp256k1.h secp256k1_ec_privkey_tweak_mul"
ecPrivkeyTweakMul ::
Ctx ->
Ptr Seckey32 ->
Ptr Tweak32 ->
IO Ret
foreign import ccall safe "secp256k1.h secp256k1_ec_pubkey_cmp"
ecPubkeyCmp ::
Ctx ->
Ptr Pubkey64 ->
Ptr Pubkey64
foreign import ccall safe "secp256k1.h secp256k1_ec_pubkey_combine"
ecPubKeyCombine ::
Ctx ->
Ptr Pubkey64 ->
Ptr (Ptr Pubkey64) ->
CInt ->
IO Ret
foreign import ccall safe "secp256k1.h secp256k1_ec_pubkey_create"
ecPubKeyCreate ::
Ctx ->
Ptr Pubkey64 ->
Ptr Seckey32 ->
IO Ret
foreign import ccall safe "secp256k1.h secp256k1_ec_pubkey_negate"
ecPubkeyNegate :: Ctx -> Ptr Pubkey64 -> IO Ret
foreign import ccall safe "secp256k1.h secp256k1_ec_pubkey_parse"
ecPubkeyParse ::
Ctx ->
Ptr Pubkey64 ->
Ptr (Bytes n) ->
CSize ->
IO Ret
foreign import ccall safe "secp256k1.h secp256k1_ec_pubkey_serialize"
ecPubKeySerialize ::
Ctx ->
Ptr (Bytes n) ->
Ptr CSize ->
Ptr Pubkey64 ->
SerFlags ->
IO Ret
foreign import ccall unsafe "secp256k1.h secp256k1_ec_pubkey_tweak_add"
ecPubKeyTweakAdd ::
Ctx ->
Ptr Pubkey64 ->
Ptr Tweak32 ->
IO Ret
foreign import ccall safe "secp256k1.h secp256k1_ec_pubkey_tweak_mul"
ecPubKeyTweakMul ::
Ctx ->
Ptr Pubkey64 ->
Ptr Tweak32 ->
IO Ret
foreign import ccall safe "secp256k1.h secp256k1_ec_seckey_negate"
ecSeckeyNegate :: Ctx -> Ptr Seckey32 -> IO Ret
foreign import ccall safe "secp256k1.h secp256k1_ec_seckey_tweak_add"
ecSeckeyTweakAdd :: Ctx -> Ptr Seckey32 -> Ptr Tweak32 -> IO Ret
foreign import ccall safe "secp256k1.h secp256k1_ec_seckey_tweak_mul"
ecSeckeyTweakMul :: Ctx -> Ptr Seckey32 -> Ptr Tweak32 -> IO Ret
foreign import ccall safe "secp256k1.h secp256k1_ec_seckey_verify"
ecSecKeyVerify ::
Ctx ->
Ptr Seckey32 ->
IO Ret
foreign import ccall safe "secp256k1.h secp256k1_keypair_create"
keypairCreate :: Ctx -> Ptr Keypair96 -> Ptr Seckey32 -> IO Ret
foreign import ccall safe "secp256k1.h secp256k1_keypair_pub"
keypairPub :: Ctx -> Ptr Pubkey64 -> Ptr Keypair96 -> IO Ret
foreign import ccall safe "secp256k1.h secp256k1_keypair_sec"
keypairSec :: Ctx -> Ptr Seckey32 -> Ptr Keypair96 -> IO Ret
foreign import ccall safe "secp256k1.h secp256k1_keypair_xonly_pub"
keypairXonlyPub :: Ctx -> Ptr XonlyPubkey64 -> Ptr CInt -> Ptr Keypair96 -> IO Ret
foreign import ccall safe "secp256k1.h secp256k1_keypair_xonly_tweak_add"
keypairXonlyTweakAdd :: Ctx -> Ptr Keypair96 -> Ptr Tweak32 -> IO Ret
foreign import ccall safe "secp256k1.h &secp256k1_nonce_function_bip340"
nonceFunctionBip340 :: FunPtr (NonceFunHardened a)
foreign import ccall safe "secp256k1.h &secp256k1_nonce_function_default"
nonceFunctionDefault :: FunPtr (NonceFun a)
foreign import ccall safe "secp256k1.h &secp256k1_nonce_function_rfc6979"
nonceFunctionRfc6979 :: FunPtr (NonceFun a)
foreign import ccall safe "secp256k1.h secp256k1_schnorrsig_sign"
schnorrsigSign :: Ctx -> Ptr Sig64 -> Ptr Msg32 -> Ptr Keypair96 -> Ptr (Bytes 32) -> IO Ret
foreign import ccall safe "secp256k1.h secp256k1_schnorrsig_sign_custom"
schnorrsigSignCustom :: Ctx -> Ptr Sig64 -> Ptr (Bytes n) -> CSize -> Ptr Keypair96 -> Ptr SchnorrExtra -> IO Ret
foreign import ccall safe "secp256k1.h secp256k1_schnorrsig_verify"
schnorrSigSignVerify :: Ctx -> Ptr Sig64 -> Ptr (Bytes n) -> CSize -> Ptr XonlyPubkey64 -> IO Ret
foreign import ccall safe "secp256k1.h secp256k1_scratch_space_create"
scratchSpaceCreate :: Ctx -> CSize -> IO (Ptr Scratch)
foreign import ccall safe "secp256k1.h secp256k1_scratch_space_destroy"
scratchSpaceDestroy :: Ctx -> Ptr Scratch -> IO ()
foreign import ccall safe "secp256k1.h secp256k1_tagged_sha256"
taggedSha256 :: Ctx -> Ptr (Bytes 32) -> Ptr (Bytes n) -> CSize -> Ptr (Bytes n) -> CSize -> IO Ret
foreign import ccall safe "secp256k1.h secp256k1_xonly_pubkey_cmp"
xonlyPubkeyCmp :: Ctx -> Ptr XonlyPubkey64 -> Ptr XonlyPubkey64 -> IO Ret
foreign import ccall safe "secp256k1.h secp256k1_xonly_pubkey_from_pubkey"
xonlyPubkeyFromPubkey :: Ctx -> Ptr XonlyPubkey64 -> Ptr CInt -> Ptr Pubkey64 -> IO Ret
foreign import ccall safe "secp256k1.h secp256k1_xonly_pubkey_parse"
xonlyPubkeyParse :: Ctx -> Ptr XonlyPubkey64 -> Ptr (Bytes 32) -> IO Ret
foreign import ccall safe "secp256k1.h secp256k1_xonly_pubkey_serialize"
xonlyPubkeySerialize :: Ctx -> Ptr (Bytes 32) -> Ptr XonlyPubkey64 -> IO Ret
foreign import ccall safe "secp256k1.h secp256k1_xonly_pubkey_tweak_add"
xonlyPubkeyTweakAdd :: Ctx -> Ptr Pubkey64 -> Ptr XonlyPubkey64 -> Ptr Tweak32 -> IO Ret
foreign import ccall safe "secp256k1.h secp256k1_xonly_pubkey_tweak_add_check"
xonlyPubkeyTweakAddCheck :: Ctx -> Ptr (Bytes 32) -> CInt -> Ptr XonlyPubkey64 -> Ptr Tweak32 -> IO Ret