{-# 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.
module Crypto.Secp256k1
  ( -- * Context
    Ctx (..),
    withContext,
    randomizeContext,
    createContext,
    cloneContext,
    destroyContext,

    -- * Messages
    Msg (..),
    msg,

    -- * Secret Keys
    SecKey (..),
    secKey,
    derivePubKey,

    -- * Public Keys
    PubKey (..),
    pubKey,
    importPubKey,
    exportPubKey,

    -- * Signatures
    Sig (..),
    sig,
    signMsg,
    verifySig,
    normalizeSig,

    -- ** DER
    importSig,
    exportSig,

    -- ** Compact
    CompactSig (..),
    compactSig,
    exportCompactSig,
    importCompactSig,

    -- * Addition & Multiplication
    Tweak (..),
    tweak,
    tweakAddSecKey,
    tweakMulSecKey,
    tweakAddPubKey,
    tweakMulPubKey,
    combinePubKeys,
    tweakNegate,
  )
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 {Ctx -> Ptr LCtx
get :: Ptr LCtx}

newtype PubKey = PubKey {PubKey -> ByteString
get :: ByteString}
  deriving (PubKey -> PubKey -> Bool
(PubKey -> PubKey -> Bool)
-> (PubKey -> PubKey -> Bool) -> Eq PubKey
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PubKey -> PubKey -> Bool
== :: PubKey -> PubKey -> Bool
$c/= :: PubKey -> PubKey -> Bool
/= :: PubKey -> PubKey -> Bool
Eq, (forall x. PubKey -> Rep PubKey x)
-> (forall x. Rep PubKey x -> PubKey) -> Generic PubKey
forall x. Rep PubKey x -> PubKey
forall x. PubKey -> Rep PubKey x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. PubKey -> Rep PubKey x
from :: forall x. PubKey -> Rep PubKey x
$cto :: forall x. Rep PubKey x -> PubKey
to :: forall x. Rep PubKey x -> PubKey
Generic, Eq PubKey
Eq PubKey
-> (Int -> PubKey -> Int) -> (PubKey -> Int) -> Hashable PubKey
Int -> PubKey -> Int
PubKey -> Int
forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
$chashWithSalt :: Int -> PubKey -> Int
hashWithSalt :: Int -> PubKey -> Int
$chash :: PubKey -> Int
hash :: PubKey -> Int
Hashable, PubKey -> ()
(PubKey -> ()) -> NFData PubKey
forall a. (a -> ()) -> NFData a
$crnf :: PubKey -> ()
rnf :: PubKey -> ()
NFData)

newtype Msg = Msg {Msg -> ByteString
get :: ByteString}
  deriving (Msg -> Msg -> Bool
(Msg -> Msg -> Bool) -> (Msg -> Msg -> Bool) -> Eq Msg
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Msg -> Msg -> Bool
== :: Msg -> Msg -> Bool
$c/= :: Msg -> Msg -> Bool
/= :: Msg -> Msg -> Bool
Eq, (forall x. Msg -> Rep Msg x)
-> (forall x. Rep Msg x -> Msg) -> Generic Msg
forall x. Rep Msg x -> Msg
forall x. Msg -> Rep Msg x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Msg -> Rep Msg x
from :: forall x. Msg -> Rep Msg x
$cto :: forall x. Rep Msg x -> Msg
to :: forall x. Rep Msg x -> Msg
Generic, Eq Msg
Eq Msg -> (Int -> Msg -> Int) -> (Msg -> Int) -> Hashable Msg
Int -> Msg -> Int
Msg -> Int
forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
$chashWithSalt :: Int -> Msg -> Int
hashWithSalt :: Int -> Msg -> Int
$chash :: Msg -> Int
hash :: Msg -> Int
Hashable, Msg -> ()
(Msg -> ()) -> NFData Msg
forall a. (a -> ()) -> NFData a
$crnf :: Msg -> ()
rnf :: Msg -> ()
NFData)

newtype Sig = Sig {Sig -> ByteString
get :: ByteString}
  deriving (Sig -> Sig -> Bool
(Sig -> Sig -> Bool) -> (Sig -> Sig -> Bool) -> Eq Sig
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Sig -> Sig -> Bool
== :: Sig -> Sig -> Bool
$c/= :: Sig -> Sig -> Bool
/= :: Sig -> Sig -> Bool
Eq, (forall x. Sig -> Rep Sig x)
-> (forall x. Rep Sig x -> Sig) -> Generic Sig
forall x. Rep Sig x -> Sig
forall x. Sig -> Rep Sig x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Sig -> Rep Sig x
from :: forall x. Sig -> Rep Sig x
$cto :: forall x. Rep Sig x -> Sig
to :: forall x. Rep Sig x -> Sig
Generic, Eq Sig
Eq Sig -> (Int -> Sig -> Int) -> (Sig -> Int) -> Hashable Sig
Int -> Sig -> Int
Sig -> Int
forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
$chashWithSalt :: Int -> Sig -> Int
hashWithSalt :: Int -> Sig -> Int
$chash :: Sig -> Int
hash :: Sig -> Int
Hashable, Sig -> ()
(Sig -> ()) -> NFData Sig
forall a. (a -> ()) -> NFData a
$crnf :: Sig -> ()
rnf :: Sig -> ()
NFData)

newtype SecKey = SecKey {SecKey -> ByteString
get :: ByteString}
  deriving (SecKey -> SecKey -> Bool
(SecKey -> SecKey -> Bool)
-> (SecKey -> SecKey -> Bool) -> Eq SecKey
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SecKey -> SecKey -> Bool
== :: SecKey -> SecKey -> Bool
$c/= :: SecKey -> SecKey -> Bool
/= :: SecKey -> SecKey -> Bool
Eq, (forall x. SecKey -> Rep SecKey x)
-> (forall x. Rep SecKey x -> SecKey) -> Generic SecKey
forall x. Rep SecKey x -> SecKey
forall x. SecKey -> Rep SecKey x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. SecKey -> Rep SecKey x
from :: forall x. SecKey -> Rep SecKey x
$cto :: forall x. Rep SecKey x -> SecKey
to :: forall x. Rep SecKey x -> SecKey
Generic, Eq SecKey
Eq SecKey
-> (Int -> SecKey -> Int) -> (SecKey -> Int) -> Hashable SecKey
Int -> SecKey -> Int
SecKey -> Int
forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
$chashWithSalt :: Int -> SecKey -> Int
hashWithSalt :: Int -> SecKey -> Int
$chash :: SecKey -> Int
hash :: SecKey -> Int
Hashable, SecKey -> ()
(SecKey -> ()) -> NFData SecKey
forall a. (a -> ()) -> NFData a
$crnf :: SecKey -> ()
rnf :: SecKey -> ()
NFData)

newtype Tweak = Tweak {Tweak -> ByteString
get :: ByteString}
  deriving (Tweak -> Tweak -> Bool
(Tweak -> Tweak -> Bool) -> (Tweak -> Tweak -> Bool) -> Eq Tweak
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Tweak -> Tweak -> Bool
== :: Tweak -> Tweak -> Bool
$c/= :: Tweak -> Tweak -> Bool
/= :: Tweak -> Tweak -> Bool
Eq, (forall x. Tweak -> Rep Tweak x)
-> (forall x. Rep Tweak x -> Tweak) -> Generic Tweak
forall x. Rep Tweak x -> Tweak
forall x. Tweak -> Rep Tweak x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Tweak -> Rep Tweak x
from :: forall x. Tweak -> Rep Tweak x
$cto :: forall x. Rep Tweak x -> Tweak
to :: forall x. Rep Tweak x -> Tweak
Generic, Eq Tweak
Eq Tweak
-> (Int -> Tweak -> Int) -> (Tweak -> Int) -> Hashable Tweak
Int -> Tweak -> Int
Tweak -> Int
forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
$chashWithSalt :: Int -> Tweak -> Int
hashWithSalt :: Int -> Tweak -> Int
$chash :: Tweak -> Int
hash :: Tweak -> Int
Hashable, Tweak -> ()
(Tweak -> ()) -> NFData Tweak
forall a. (a -> ()) -> NFData a
$crnf :: Tweak -> ()
rnf :: Tweak -> ()
NFData)

newtype CompactSig = CompactSig {CompactSig -> ByteString
get :: ByteString}
  deriving (CompactSig -> CompactSig -> Bool
(CompactSig -> CompactSig -> Bool)
-> (CompactSig -> CompactSig -> Bool) -> Eq CompactSig
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CompactSig -> CompactSig -> Bool
== :: CompactSig -> CompactSig -> Bool
$c/= :: CompactSig -> CompactSig -> Bool
/= :: CompactSig -> CompactSig -> Bool
Eq, (forall x. CompactSig -> Rep CompactSig x)
-> (forall x. Rep CompactSig x -> CompactSig) -> Generic CompactSig
forall x. Rep CompactSig x -> CompactSig
forall x. CompactSig -> Rep CompactSig x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. CompactSig -> Rep CompactSig x
from :: forall x. CompactSig -> Rep CompactSig x
$cto :: forall x. Rep CompactSig x -> CompactSig
to :: forall x. Rep CompactSig x -> CompactSig
Generic, Eq CompactSig
Eq CompactSig
-> (Int -> CompactSig -> Int)
-> (CompactSig -> Int)
-> Hashable CompactSig
Int -> CompactSig -> Int
CompactSig -> Int
forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
$chashWithSalt :: Int -> CompactSig -> Int
hashWithSalt :: Int -> CompactSig -> Int
$chash :: CompactSig -> Int
hash :: CompactSig -> Int
Hashable, CompactSig -> ()
(CompactSig -> ()) -> NFData CompactSig
forall a. (a -> ()) -> NFData a
$crnf :: CompactSig -> ()
rnf :: CompactSig -> ()
NFData)

decodeHex :: (ConvertibleStrings a ByteString) => a -> Maybe ByteString
decodeHex :: forall a. ConvertibleStrings a ByteString => a -> Maybe ByteString
decodeHex a
str =
  if ByteString -> Bool
isBase16 (ByteString -> Bool) -> ByteString -> Bool
forall a b. (a -> b) -> a -> b
$ a -> ByteString
forall a b. ConvertibleStrings a b => a -> b
cs a
str
    then ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just (ByteString -> Maybe ByteString)
-> (Base16 ByteString -> ByteString)
-> Base16 ByteString
-> Maybe ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Base16 ByteString -> ByteString
decodeBase16 (Base16 ByteString -> Maybe ByteString)
-> Base16 ByteString -> Maybe ByteString
forall a b. (a -> b) -> a -> b
$ ByteString -> Base16 ByteString
forall a. a -> Base16 a
assertBase16 (ByteString -> Base16 ByteString)
-> ByteString -> Base16 ByteString
forall a b. (a -> b) -> a -> b
$ a -> ByteString
forall a b. ConvertibleStrings a b => a -> b
cs a
str
    else Maybe ByteString
forall a. Maybe a
Nothing

instance Read PubKey where
  readPrec :: ReadPrec PubKey
readPrec = ReadPrec PubKey -> ReadPrec PubKey
forall a. ReadPrec a -> ReadPrec a
parens (ReadPrec PubKey -> ReadPrec PubKey)
-> ReadPrec PubKey -> ReadPrec PubKey
forall a b. (a -> b) -> a -> b
$ do
    String String
str <- ReadPrec Lexeme
lexP
    ReadPrec PubKey
-> (PubKey -> ReadPrec PubKey) -> Maybe PubKey -> ReadPrec PubKey
forall b a. b -> (a -> b) -> Maybe a -> b
maybe ReadPrec PubKey
forall a. ReadPrec a
pfail PubKey -> ReadPrec PubKey
forall a. a -> ReadPrec a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe PubKey -> ReadPrec PubKey)
-> Maybe PubKey -> ReadPrec PubKey
forall a b. (a -> b) -> a -> b
$ ByteString -> Maybe PubKey
pubKey (ByteString -> Maybe PubKey) -> Maybe ByteString -> Maybe PubKey
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< String -> Maybe ByteString
forall a. ConvertibleStrings a ByteString => a -> Maybe ByteString
decodeHex String
str

instance IsString PubKey where
  fromString :: String -> PubKey
fromString = PubKey -> Maybe PubKey -> PubKey
forall a. a -> Maybe a -> a
fromMaybe PubKey
forall {a}. a
e (Maybe PubKey -> PubKey)
-> (String -> Maybe PubKey) -> String -> PubKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString -> Maybe PubKey
pubKey (ByteString -> Maybe PubKey)
-> (String -> Maybe ByteString) -> String -> Maybe PubKey
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< String -> Maybe ByteString
forall a. ConvertibleStrings a ByteString => a -> Maybe ByteString
decodeHex)
    where
      e :: a
e = String -> a
forall a. HasCallStack => String -> a
error String
"Could not decode public key from hex string"

instance Show PubKey where
  showsPrec :: Int -> PubKey -> ShowS
showsPrec Int
_ = Text -> ShowS
forall a. Show a => a -> ShowS
shows (Text -> ShowS) -> (PubKey -> Text) -> PubKey -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Base16 Text -> Text
forall a. Base16 a -> a
extractBase16 (Base16 Text -> Text) -> (PubKey -> Base16 Text) -> PubKey -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Base16 Text
encodeBase16 (ByteString -> Base16 Text)
-> (PubKey -> ByteString) -> PubKey -> Base16 Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (.get)

instance Read Msg where
  readPrec :: ReadPrec Msg
readPrec = ReadPrec Msg -> ReadPrec Msg
forall a. ReadPrec a -> ReadPrec a
parens (ReadPrec Msg -> ReadPrec Msg) -> ReadPrec Msg -> ReadPrec Msg
forall a b. (a -> b) -> a -> b
$ do
    String String
str <- ReadPrec Lexeme
lexP
    ReadPrec Msg -> (Msg -> ReadPrec Msg) -> Maybe Msg -> ReadPrec Msg
forall b a. b -> (a -> b) -> Maybe a -> b
maybe ReadPrec Msg
forall a. ReadPrec a
pfail Msg -> ReadPrec Msg
forall a. a -> ReadPrec a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe Msg -> ReadPrec Msg) -> Maybe Msg -> ReadPrec Msg
forall a b. (a -> b) -> a -> b
$ ByteString -> Maybe Msg
msg (ByteString -> Maybe Msg) -> Maybe ByteString -> Maybe Msg
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< String -> Maybe ByteString
forall a. ConvertibleStrings a ByteString => a -> Maybe ByteString
decodeHex String
str

instance IsString Msg where
  fromString :: String -> Msg
fromString = Msg -> Maybe Msg -> Msg
forall a. a -> Maybe a -> a
fromMaybe Msg
forall {a}. a
e (Maybe Msg -> Msg) -> (String -> Maybe Msg) -> String -> Msg
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString -> Maybe Msg
msg (ByteString -> Maybe Msg)
-> (String -> Maybe ByteString) -> String -> Maybe Msg
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< String -> Maybe ByteString
forall a. ConvertibleStrings a ByteString => a -> Maybe ByteString
decodeHex)
    where
      e :: a
e = String -> a
forall a. HasCallStack => String -> a
error String
"Could not decode message from hex string"

instance Show Sig where
  showsPrec :: Int -> Sig -> ShowS
showsPrec Int
_ = Text -> ShowS
forall a. Show a => a -> ShowS
shows (Text -> ShowS) -> (Sig -> Text) -> Sig -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Base16 Text -> Text
forall a. Base16 a -> a
extractBase16 (Base16 Text -> Text) -> (Sig -> Base16 Text) -> Sig -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Base16 Text
encodeBase16 (ByteString -> Base16 Text)
-> (Sig -> ByteString) -> Sig -> Base16 Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (.get)

instance Read Sig where
  readPrec :: ReadPrec Sig
readPrec = ReadPrec Sig -> ReadPrec Sig
forall a. ReadPrec a -> ReadPrec a
parens (ReadPrec Sig -> ReadPrec Sig) -> ReadPrec Sig -> ReadPrec Sig
forall a b. (a -> b) -> a -> b
$ do
    String String
str <- ReadPrec Lexeme
lexP
    ReadPrec Sig -> (Sig -> ReadPrec Sig) -> Maybe Sig -> ReadPrec Sig
forall b a. b -> (a -> b) -> Maybe a -> b
maybe ReadPrec Sig
forall a. ReadPrec a
pfail Sig -> ReadPrec Sig
forall a. a -> ReadPrec a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe Sig -> ReadPrec Sig) -> Maybe Sig -> ReadPrec Sig
forall a b. (a -> b) -> a -> b
$ ByteString -> Maybe Sig
sig (ByteString -> Maybe Sig) -> Maybe ByteString -> Maybe Sig
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< String -> Maybe ByteString
forall a. ConvertibleStrings a ByteString => a -> Maybe ByteString
decodeHex String
str

instance IsString Sig where
  fromString :: String -> Sig
fromString = Sig -> Maybe Sig -> Sig
forall a. a -> Maybe a -> a
fromMaybe Sig
forall {a}. a
e (Maybe Sig -> Sig) -> (String -> Maybe Sig) -> String -> Sig
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString -> Maybe Sig
sig (ByteString -> Maybe Sig)
-> (String -> Maybe ByteString) -> String -> Maybe Sig
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< String -> Maybe ByteString
forall a. ConvertibleStrings a ByteString => a -> Maybe ByteString
decodeHex)
    where
      e :: a
e = String -> a
forall a. HasCallStack => String -> a
error String
"Could not decode signature from hex string"

instance Show Msg where
  showsPrec :: Int -> Msg -> ShowS
showsPrec Int
_ = Text -> ShowS
forall a. Show a => a -> ShowS
shows (Text -> ShowS) -> (Msg -> Text) -> Msg -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Base16 Text -> Text
forall a. Base16 a -> a
extractBase16 (Base16 Text -> Text) -> (Msg -> Base16 Text) -> Msg -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Base16 Text
encodeBase16 (ByteString -> Base16 Text)
-> (Msg -> ByteString) -> Msg -> Base16 Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (.get)

instance Read SecKey where
  readPrec :: ReadPrec SecKey
readPrec = ReadPrec SecKey -> ReadPrec SecKey
forall a. ReadPrec a -> ReadPrec a
parens (ReadPrec SecKey -> ReadPrec SecKey)
-> ReadPrec SecKey -> ReadPrec SecKey
forall a b. (a -> b) -> a -> b
$ do
    String String
str <- ReadPrec Lexeme
lexP
    ReadPrec SecKey
-> (SecKey -> ReadPrec SecKey) -> Maybe SecKey -> ReadPrec SecKey
forall b a. b -> (a -> b) -> Maybe a -> b
maybe ReadPrec SecKey
forall a. ReadPrec a
pfail SecKey -> ReadPrec SecKey
forall a. a -> ReadPrec a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe SecKey -> ReadPrec SecKey)
-> Maybe SecKey -> ReadPrec SecKey
forall a b. (a -> b) -> a -> b
$ ByteString -> Maybe SecKey
secKey (ByteString -> Maybe SecKey) -> Maybe ByteString -> Maybe SecKey
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< String -> Maybe ByteString
forall a. ConvertibleStrings a ByteString => a -> Maybe ByteString
decodeHex String
str

instance IsString SecKey where
  fromString :: String -> SecKey
fromString = SecKey -> Maybe SecKey -> SecKey
forall a. a -> Maybe a -> a
fromMaybe SecKey
forall {a}. a
e (Maybe SecKey -> SecKey)
-> (String -> Maybe SecKey) -> String -> SecKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString -> Maybe SecKey
secKey (ByteString -> Maybe SecKey)
-> (String -> Maybe ByteString) -> String -> Maybe SecKey
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< String -> Maybe ByteString
forall a. ConvertibleStrings a ByteString => a -> Maybe ByteString
decodeHex)
    where
      e :: a
e = String -> a
forall a. HasCallStack => String -> a
error String
"Colud not decode secret key from hex string"

instance Show SecKey where
  showsPrec :: Int -> SecKey -> ShowS
showsPrec Int
_ = Text -> ShowS
forall a. Show a => a -> ShowS
shows (Text -> ShowS) -> (SecKey -> Text) -> SecKey -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Base16 Text -> Text
forall a. Base16 a -> a
extractBase16 (Base16 Text -> Text) -> (SecKey -> Base16 Text) -> SecKey -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Base16 Text
encodeBase16 (ByteString -> Base16 Text)
-> (SecKey -> ByteString) -> SecKey -> Base16 Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (.get)

instance Read Tweak where
  readPrec :: ReadPrec Tweak
readPrec = ReadPrec Tweak -> ReadPrec Tweak
forall a. ReadPrec a -> ReadPrec a
parens (ReadPrec Tweak -> ReadPrec Tweak)
-> ReadPrec Tweak -> ReadPrec Tweak
forall a b. (a -> b) -> a -> b
$ do
    String String
str <- ReadPrec Lexeme
lexP
    ReadPrec Tweak
-> (Tweak -> ReadPrec Tweak) -> Maybe Tweak -> ReadPrec Tweak
forall b a. b -> (a -> b) -> Maybe a -> b
maybe ReadPrec Tweak
forall a. ReadPrec a
pfail Tweak -> ReadPrec Tweak
forall a. a -> ReadPrec a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe Tweak -> ReadPrec Tweak) -> Maybe Tweak -> ReadPrec Tweak
forall a b. (a -> b) -> a -> b
$ ByteString -> Maybe Tweak
tweak (ByteString -> Maybe Tweak) -> Maybe ByteString -> Maybe Tweak
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< String -> Maybe ByteString
forall a. ConvertibleStrings a ByteString => a -> Maybe ByteString
decodeHex String
str

instance IsString Tweak where
  fromString :: String -> Tweak
fromString = Tweak -> Maybe Tweak -> Tweak
forall a. a -> Maybe a -> a
fromMaybe Tweak
forall {a}. a
e (Maybe Tweak -> Tweak)
-> (String -> Maybe Tweak) -> String -> Tweak
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString -> Maybe Tweak
tweak (ByteString -> Maybe Tweak)
-> (String -> Maybe ByteString) -> String -> Maybe Tweak
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< String -> Maybe ByteString
forall a. ConvertibleStrings a ByteString => a -> Maybe ByteString
decodeHex)
    where
      e :: a
e = String -> a
forall a. HasCallStack => String -> a
error String
"Could not decode tweak from hex string"

instance Show Tweak where
  showsPrec :: Int -> Tweak -> ShowS
showsPrec Int
_ = Text -> ShowS
forall a. Show a => a -> ShowS
shows (Text -> ShowS) -> (Tweak -> Text) -> Tweak -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Base16 Text -> Text
forall a. Base16 a -> a
extractBase16 (Base16 Text -> Text) -> (Tweak -> Base16 Text) -> Tweak -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Base16 Text
encodeBase16 (ByteString -> Base16 Text)
-> (Tweak -> ByteString) -> Tweak -> Base16 Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (.get)

randomizeContext :: Ctx -> IO ()
randomizeContext :: Ctx -> IO ()
randomizeContext (Ctx Ptr LCtx
ctx) = do
  CInt
ret <- (Ptr Seed32 -> IO CInt) -> IO CInt
forall a. (Ptr Seed32 -> IO a) -> IO a
withRandomSeed ((Ptr Seed32 -> IO CInt) -> IO CInt)
-> (Ptr Seed32 -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ Ptr LCtx -> Ptr Seed32 -> IO CInt
contextRandomize Ptr LCtx
ctx
  Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (CInt -> Bool
isSuccess CInt
ret) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> IO ()
forall a. HasCallStack => String -> a
error String
"Could not randomize context"

createContext :: IO Ctx
createContext :: IO Ctx
createContext = Ptr LCtx -> Ctx
Ctx (Ptr LCtx -> Ctx) -> IO (Ptr LCtx) -> IO Ctx
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> CtxFlags -> IO (Ptr LCtx)
contextCreate CtxFlags
signVerify

cloneContext :: Ctx -> IO Ctx
cloneContext :: Ctx -> IO Ctx
cloneContext = (Ptr LCtx -> Ctx) -> IO (Ptr LCtx) -> IO Ctx
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Ptr LCtx -> Ctx
Ctx (IO (Ptr LCtx) -> IO Ctx)
-> (Ctx -> IO (Ptr LCtx)) -> Ctx -> IO Ctx
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ptr LCtx -> IO (Ptr LCtx)
contextClone (Ptr LCtx -> IO (Ptr LCtx))
-> (Ctx -> Ptr LCtx) -> Ctx -> IO (Ptr LCtx)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (.get)

destroyContext :: Ctx -> IO ()
destroyContext :: Ctx -> IO ()
destroyContext = Ptr LCtx -> IO ()
contextDestroy (Ptr LCtx -> IO ()) -> (Ctx -> Ptr LCtx) -> Ctx -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (.get)

withContext :: (Ctx -> IO a) -> IO a
withContext :: forall a. (Ctx -> IO a) -> IO a
withContext = IO Ctx -> (Ctx -> IO ()) -> (Ctx -> IO a) -> IO a
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket IO Ctx
create Ctx -> IO ()
destroy
  where
    create :: IO Ctx
create = do
      Ctx
ctx <- IO Ctx
createContext
      Ctx -> IO ()
randomizeContext Ctx
ctx
      Ctx -> IO Ctx
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Ctx
ctx
    destroy :: Ctx -> IO ()
destroy = Ctx -> IO ()
destroyContext

sig :: ByteString -> Maybe Sig
sig :: ByteString -> Maybe Sig
sig ByteString
bs
  | ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
64 = Sig -> Maybe Sig
forall a. a -> Maybe a
Just (ByteString -> Sig
Sig ByteString
bs)
  | Bool
otherwise = Maybe Sig
forall a. Maybe a
Nothing

pubKey :: ByteString -> Maybe PubKey
pubKey :: ByteString -> Maybe PubKey
pubKey ByteString
bs
  | ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
64 = PubKey -> Maybe PubKey
forall a. a -> Maybe a
Just (ByteString -> PubKey
PubKey ByteString
bs)
  | Bool
otherwise = Maybe PubKey
forall a. Maybe a
Nothing

-- | Import 32-byte 'ByteString' as 'Msg'.
msg :: ByteString -> Maybe Msg
msg :: ByteString -> Maybe Msg
msg ByteString
bs
  | ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
32 = Msg -> Maybe Msg
forall a. a -> Maybe a
Just (ByteString -> Msg
Msg ByteString
bs)
  | Bool
otherwise = Maybe Msg
forall a. Maybe a
Nothing

-- | Import 32-byte 'ByteString' as 'SecKey'.
secKey :: ByteString -> Maybe SecKey
secKey :: ByteString -> Maybe SecKey
secKey ByteString
bs
  | ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
32 = SecKey -> Maybe SecKey
forall a. a -> Maybe a
Just (ByteString -> SecKey
SecKey ByteString
bs)
  | Bool
otherwise = Maybe SecKey
forall a. Maybe a
Nothing

compactSig :: ByteString -> Maybe CompactSig
compactSig :: ByteString -> Maybe CompactSig
compactSig ByteString
bs
  | ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
64 = CompactSig -> Maybe CompactSig
forall a. a -> Maybe a
Just (ByteString -> CompactSig
CompactSig ByteString
bs)
  | Bool
otherwise = Maybe CompactSig
forall a. Maybe a
Nothing

-- | Convert signature to a normalized lower-S form. 'Nothing' indicates that it
-- was already normal.
normalizeSig :: Ctx -> Sig -> Maybe Sig
normalizeSig :: Ctx -> Sig -> Maybe Sig
normalizeSig (Ctx Ptr LCtx
ctx) (Sig ByteString
sig) = IO (Maybe Sig) -> Maybe Sig
forall a. IO a -> a
unsafePerformIO (IO (Maybe Sig) -> Maybe Sig) -> IO (Maybe Sig) -> Maybe Sig
forall a b. (a -> b) -> a -> b
$
  ByteString
-> ((Ptr Sig64, CSize) -> IO (Maybe Sig)) -> IO (Maybe Sig)
forall a b. ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
unsafeUseByteString ByteString
sig (((Ptr Sig64, CSize) -> IO (Maybe Sig)) -> IO (Maybe Sig))
-> ((Ptr Sig64, CSize) -> IO (Maybe Sig)) -> IO (Maybe Sig)
forall a b. (a -> b) -> a -> b
$ \(Ptr Sig64
sig_in, CSize
_) -> do
    Ptr Sig64
sig_out <- Int -> IO (Ptr Sig64)
forall a. Int -> IO (Ptr a)
mallocBytes Int
64
    CInt
ret <- Ptr LCtx -> Ptr Sig64 -> Ptr Sig64 -> IO CInt
ecdsaSignatureNormalize Ptr LCtx
ctx Ptr Sig64
sig_out Ptr Sig64
sig_in
    if CInt -> Bool
isSuccess CInt
ret
      then do
        ByteString
bs <- (Ptr Sig64, CSize) -> IO ByteString
forall a. (Ptr a, CSize) -> IO ByteString
unsafePackByteString (Ptr Sig64
sig_out, CSize
64)
        Maybe Sig -> IO (Maybe Sig)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Sig -> Maybe Sig
forall a. a -> Maybe a
Just (ByteString -> Sig
Sig ByteString
bs))
      else do
        Ptr Sig64 -> IO ()
forall a. Ptr a -> IO ()
free Ptr Sig64
sig_out
        Maybe Sig -> IO (Maybe Sig)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Sig
forall a. Maybe a
Nothing

-- | 32-Byte 'ByteString' as 'Tweak'.
tweak :: ByteString -> Maybe Tweak
tweak :: ByteString -> Maybe Tweak
tweak ByteString
bs
  | ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
32 = Tweak -> Maybe Tweak
forall a. a -> Maybe a
Just (ByteString -> Tweak
Tweak ByteString
bs)
  | Bool
otherwise = Maybe Tweak
forall a. Maybe a
Nothing

-- | Import DER-encoded public key.
importPubKey :: Ctx -> ByteString -> Maybe PubKey
importPubKey :: Ctx -> ByteString -> Maybe PubKey
importPubKey (Ctx Ptr LCtx
ctx) ByteString
bs
  | ByteString -> Bool
BS.null ByteString
bs = Maybe PubKey
forall a. Maybe a
Nothing
  | Bool
otherwise = IO (Maybe PubKey) -> Maybe PubKey
forall a. IO a -> a
unsafePerformIO (IO (Maybe PubKey) -> Maybe PubKey)
-> IO (Maybe PubKey) -> Maybe PubKey
forall a b. (a -> b) -> a -> b
$
      ByteString
-> ((Ptr CUChar, CSize) -> IO (Maybe PubKey)) -> IO (Maybe PubKey)
forall a b. ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
unsafeUseByteString ByteString
bs (((Ptr CUChar, CSize) -> IO (Maybe PubKey)) -> IO (Maybe PubKey))
-> ((Ptr CUChar, CSize) -> IO (Maybe PubKey)) -> IO (Maybe PubKey)
forall a b. (a -> b) -> a -> b
$ \(Ptr CUChar
input, CSize
len) -> do
        Ptr PubKey64
pub_key <- Int -> IO (Ptr PubKey64)
forall a. Int -> IO (Ptr a)
mallocBytes Int
64
        CInt
ret <- Ptr LCtx -> Ptr PubKey64 -> Ptr CUChar -> CSize -> IO CInt
ecPubKeyParse Ptr LCtx
ctx Ptr PubKey64
pub_key Ptr CUChar
input CSize
len
        if CInt -> Bool
isSuccess CInt
ret
          then do
            ByteString
out <- (Ptr PubKey64, CSize) -> IO ByteString
forall a. (Ptr a, CSize) -> IO ByteString
unsafePackByteString (Ptr PubKey64
pub_key, CSize
64)
            Maybe PubKey -> IO (Maybe PubKey)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (PubKey -> Maybe PubKey
forall a. a -> Maybe a
Just (ByteString -> PubKey
PubKey ByteString
out))
          else do
            Ptr PubKey64 -> IO ()
forall a. Ptr a -> IO ()
free Ptr PubKey64
pub_key
            Maybe PubKey -> IO (Maybe PubKey)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe PubKey
forall a. Maybe a
Nothing

-- | Encode public key as DER. First argument 'True' for compressed output.
exportPubKey :: Ctx -> Bool -> PubKey -> ByteString
exportPubKey :: Ctx -> Bool -> PubKey -> ByteString
exportPubKey (Ctx Ptr LCtx
ctx) Bool
compress (PubKey ByteString
in_bs) = IO ByteString -> ByteString
forall a. IO a -> a
unsafePerformIO (IO ByteString -> ByteString) -> IO ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$
  ByteString
-> ((Ptr PubKey64, CSize) -> IO ByteString) -> IO ByteString
forall a b. ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
unsafeUseByteString ByteString
in_bs (((Ptr PubKey64, CSize) -> IO ByteString) -> IO ByteString)
-> ((Ptr PubKey64, CSize) -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \(Ptr PubKey64
in_ptr, CSize
_) ->
    (Ptr CSize -> IO ByteString) -> IO ByteString
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr CSize -> IO ByteString) -> IO ByteString)
-> (Ptr CSize -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr CSize
len_ptr ->
      Int -> (Ptr CUChar -> IO ByteString) -> IO ByteString
forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes Int
len ((Ptr CUChar -> IO ByteString) -> IO ByteString)
-> (Ptr CUChar -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr CUChar
out_ptr -> do
        Ptr CSize -> CSize -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr CSize
len_ptr (CSize -> IO ()) -> CSize -> IO ()
forall a b. (a -> b) -> a -> b
$ Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
len
        CInt
ret <- Ptr LCtx
-> Ptr CUChar -> Ptr CSize -> Ptr PubKey64 -> CtxFlags -> IO CInt
ecPubKeySerialize Ptr LCtx
ctx Ptr CUChar
out_ptr Ptr CSize
len_ptr Ptr PubKey64
in_ptr CtxFlags
flags
        Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (CInt -> Bool
isSuccess CInt
ret) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> IO ()
forall a. HasCallStack => String -> a
error String
"could not serialize public key"
        CSize
final_len <- Ptr CSize -> IO CSize
forall a. Storable a => Ptr a -> IO a
peek Ptr CSize
len_ptr
        (Ptr CUChar, CSize) -> IO ByteString
forall a. (Ptr a, CSize) -> IO ByteString
packByteString (Ptr CUChar
out_ptr, CSize
final_len)
  where
    len :: Int
len = if Bool
compress then Int
33 else Int
65
    flags :: CtxFlags
flags = if Bool
compress then CtxFlags
compressed else CtxFlags
uncompressed

exportCompactSig :: Ctx -> Sig -> CompactSig
exportCompactSig :: Ctx -> Sig -> CompactSig
exportCompactSig (Ctx Ptr LCtx
ctx) (Sig ByteString
sig_bs) = IO CompactSig -> CompactSig
forall a. IO a -> a
unsafePerformIO (IO CompactSig -> CompactSig) -> IO CompactSig -> CompactSig
forall a b. (a -> b) -> a -> b
$
  ByteString
-> ((Ptr Sig64, CSize) -> IO CompactSig) -> IO CompactSig
forall a b. ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
unsafeUseByteString ByteString
sig_bs (((Ptr Sig64, CSize) -> IO CompactSig) -> IO CompactSig)
-> ((Ptr Sig64, CSize) -> IO CompactSig) -> IO CompactSig
forall a b. (a -> b) -> a -> b
$ \(Ptr Sig64
sig_ptr, CSize
_) -> do
    Ptr Compact64
out_ptr <- Int -> IO (Ptr Compact64)
forall a. Int -> IO (Ptr a)
mallocBytes Int
64
    CInt
ret <- Ptr LCtx -> Ptr Compact64 -> Ptr Sig64 -> IO CInt
ecdsaSignatureSerializeCompact Ptr LCtx
ctx Ptr Compact64
out_ptr Ptr Sig64
sig_ptr
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (CInt -> Bool
isSuccess CInt
ret) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
      Ptr Compact64 -> IO ()
forall a. Ptr a -> IO ()
free Ptr Compact64
out_ptr
      String -> IO ()
forall a. HasCallStack => String -> a
error String
"Could not obtain compact signature"
    ByteString
out_bs <- (Ptr Compact64, CSize) -> IO ByteString
forall a. (Ptr a, CSize) -> IO ByteString
unsafePackByteString (Ptr Compact64
out_ptr, CSize
64)
    CompactSig -> IO CompactSig
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (CompactSig -> IO CompactSig) -> CompactSig -> IO CompactSig
forall a b. (a -> b) -> a -> b
$ ByteString -> CompactSig
CompactSig ByteString
out_bs

importCompactSig :: Ctx -> CompactSig -> Maybe Sig
importCompactSig :: Ctx -> CompactSig -> Maybe Sig
importCompactSig (Ctx Ptr LCtx
ctx) (CompactSig ByteString
compact_sig) = IO (Maybe Sig) -> Maybe Sig
forall a. IO a -> a
unsafePerformIO (IO (Maybe Sig) -> Maybe Sig) -> IO (Maybe Sig) -> Maybe Sig
forall a b. (a -> b) -> a -> b
$
  ByteString
-> ((Ptr Compact64, CSize) -> IO (Maybe Sig)) -> IO (Maybe Sig)
forall a b. ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
unsafeUseByteString ByteString
compact_sig (((Ptr Compact64, CSize) -> IO (Maybe Sig)) -> IO (Maybe Sig))
-> ((Ptr Compact64, CSize) -> IO (Maybe Sig)) -> IO (Maybe Sig)
forall a b. (a -> b) -> a -> b
$ \(Ptr Compact64
compact_ptr, CSize
_) -> do
    Ptr Sig64
out_sig <- Int -> IO (Ptr Sig64)
forall a. Int -> IO (Ptr a)
mallocBytes Int
64
    CInt
ret <- Ptr LCtx -> Ptr Sig64 -> Ptr Compact64 -> IO CInt
ecdsaSignatureParseCompact Ptr LCtx
ctx Ptr Sig64
out_sig Ptr Compact64
compact_ptr
    if CInt -> Bool
isSuccess CInt
ret
      then do
        ByteString
out_bs <- (Ptr Sig64, CSize) -> IO ByteString
forall a. (Ptr a, CSize) -> IO ByteString
unsafePackByteString (Ptr Sig64
out_sig, CSize
64)
        Maybe Sig -> IO (Maybe Sig)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Sig -> Maybe Sig
forall a. a -> Maybe a
Just (ByteString -> Sig
Sig ByteString
out_bs))
      else do
        Ptr Sig64 -> IO ()
forall a. Ptr a -> IO ()
free Ptr Sig64
out_sig
        Maybe Sig -> IO (Maybe Sig)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Sig
forall a. Maybe a
Nothing

-- | Import DER-encoded signature.
importSig :: Ctx -> ByteString -> Maybe Sig
importSig :: Ctx -> ByteString -> Maybe Sig
importSig (Ctx Ptr LCtx
ctx) ByteString
bs
  | ByteString -> Bool
BS.null ByteString
bs = Maybe Sig
forall a. Maybe a
Nothing
  | Bool
otherwise = IO (Maybe Sig) -> Maybe Sig
forall a. IO a -> a
unsafePerformIO (IO (Maybe Sig) -> Maybe Sig) -> IO (Maybe Sig) -> Maybe Sig
forall a b. (a -> b) -> a -> b
$
      ByteString
-> ((Ptr CUChar, CSize) -> IO (Maybe Sig)) -> IO (Maybe Sig)
forall a b. ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
unsafeUseByteString ByteString
bs (((Ptr CUChar, CSize) -> IO (Maybe Sig)) -> IO (Maybe Sig))
-> ((Ptr CUChar, CSize) -> IO (Maybe Sig)) -> IO (Maybe Sig)
forall a b. (a -> b) -> a -> b
$ \(Ptr CUChar
in_ptr, CSize
in_len) -> do
        Ptr Sig64
out_sig <- Int -> IO (Ptr Sig64)
forall a. Int -> IO (Ptr a)
mallocBytes Int
64
        CInt
ret <- Ptr LCtx -> Ptr Sig64 -> Ptr CUChar -> CSize -> IO CInt
ecdsaSignatureParseDer Ptr LCtx
ctx Ptr Sig64
out_sig Ptr CUChar
in_ptr CSize
in_len
        if CInt -> Bool
isSuccess CInt
ret
          then do
            ByteString
out_bs <- (Ptr Sig64, CSize) -> IO ByteString
forall a. (Ptr a, CSize) -> IO ByteString
unsafePackByteString (Ptr Sig64
out_sig, CSize
64)
            Maybe Sig -> IO (Maybe Sig)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Sig -> Maybe Sig
forall a. a -> Maybe a
Just (ByteString -> Sig
Sig ByteString
out_bs))
          else do
            Ptr Sig64 -> IO ()
forall a. Ptr a -> IO ()
free Ptr Sig64
out_sig
            Maybe Sig -> IO (Maybe Sig)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Sig
forall a. Maybe a
Nothing

-- | Encode signature as strict DER.
exportSig :: Ctx -> Sig -> ByteString
exportSig :: Ctx -> Sig -> ByteString
exportSig (Ctx Ptr LCtx
ctx) (Sig ByteString
in_sig) = IO ByteString -> ByteString
forall a. IO a -> a
unsafePerformIO (IO ByteString -> ByteString) -> IO ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$
  ByteString
-> ((Ptr Sig64, CSize) -> IO ByteString) -> IO ByteString
forall a b. ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
unsafeUseByteString ByteString
in_sig (((Ptr Sig64, CSize) -> IO ByteString) -> IO ByteString)
-> ((Ptr Sig64, CSize) -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \(Ptr Sig64
in_ptr, CSize
_) ->
    (Ptr CSize -> IO ByteString) -> IO ByteString
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr CSize -> IO ByteString) -> IO ByteString)
-> (Ptr CSize -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr CSize
out_len ->
      Int -> (Ptr CUChar -> IO ByteString) -> IO ByteString
forall a b. Int -> (Ptr a -> IO b) -> IO b
allocaBytes Int
72 ((Ptr CUChar -> IO ByteString) -> IO ByteString)
-> (Ptr CUChar -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr CUChar
out_ptr -> do
        Ptr CSize -> CSize -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke Ptr CSize
out_len CSize
72
        CInt
ret <- Ptr LCtx -> Ptr CUChar -> Ptr CSize -> Ptr Sig64 -> IO CInt
ecdsaSignatureSerializeDer Ptr LCtx
ctx Ptr CUChar
out_ptr Ptr CSize
out_len Ptr Sig64
in_ptr
        Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (CInt -> Bool
isSuccess CInt
ret) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> IO ()
forall a. HasCallStack => String -> a
error String
"could not serialize signature"
        CSize
final_len <- Ptr CSize -> IO CSize
forall a. Storable a => Ptr a -> IO a
peek Ptr CSize
out_len
        (Ptr CUChar, CSize) -> IO ByteString
forall a. (Ptr a, CSize) -> IO ByteString
packByteString (Ptr CUChar
out_ptr, CSize
final_len)

-- | Verify message signature. 'True' means that the signature is correct.
verifySig :: Ctx -> PubKey -> Sig -> Msg -> Bool
verifySig :: Ctx -> PubKey -> Sig -> Msg -> Bool
verifySig (Ctx Ptr LCtx
ctx) (PubKey ByteString
pub_key) (Sig ByteString
sig) (Msg ByteString
m) = IO Bool -> Bool
forall a. IO a -> a
unsafePerformIO (IO Bool -> Bool) -> IO Bool -> Bool
forall a b. (a -> b) -> a -> b
$
  ByteString -> ((Ptr PubKey64, CSize) -> IO Bool) -> IO Bool
forall a b. ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
unsafeUseByteString ByteString
pub_key (((Ptr PubKey64, CSize) -> IO Bool) -> IO Bool)
-> ((Ptr PubKey64, CSize) -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \(Ptr PubKey64
pub_key_ptr, CSize
_) ->
    ByteString -> ((Ptr Sig64, CSize) -> IO Bool) -> IO Bool
forall a b. ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
unsafeUseByteString ByteString
sig (((Ptr Sig64, CSize) -> IO Bool) -> IO Bool)
-> ((Ptr Sig64, CSize) -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \(Ptr Sig64
sig_ptr, CSize
_) ->
      ByteString -> ((Ptr Msg32, CSize) -> IO Bool) -> IO Bool
forall a b. ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
unsafeUseByteString ByteString
m (((Ptr Msg32, CSize) -> IO Bool) -> IO Bool)
-> ((Ptr Msg32, CSize) -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \(Ptr Msg32
msg_ptr, CSize
_) ->
        CInt -> Bool
isSuccess (CInt -> Bool) -> IO CInt -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr LCtx -> Ptr Sig64 -> Ptr Msg32 -> Ptr PubKey64 -> IO CInt
ecdsaVerify Ptr LCtx
ctx Ptr Sig64
sig_ptr Ptr Msg32
msg_ptr Ptr PubKey64
pub_key_ptr

signMsg :: Ctx -> SecKey -> Msg -> Sig
signMsg :: Ctx -> SecKey -> Msg -> Sig
signMsg (Ctx Ptr LCtx
ctx) (SecKey ByteString
sec_key) (Msg ByteString
m) = IO Sig -> Sig
forall a. IO a -> a
unsafePerformIO (IO Sig -> Sig) -> IO Sig -> Sig
forall a b. (a -> b) -> a -> b
$
  ByteString -> ((Ptr SecKey32, CSize) -> IO Sig) -> IO Sig
forall a b. ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
unsafeUseByteString ByteString
sec_key (((Ptr SecKey32, CSize) -> IO Sig) -> IO Sig)
-> ((Ptr SecKey32, CSize) -> IO Sig) -> IO Sig
forall a b. (a -> b) -> a -> b
$ \(Ptr SecKey32
sec_key_ptr, CSize
_) ->
    ByteString -> ((Ptr Msg32, CSize) -> IO Sig) -> IO Sig
forall a b. ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
unsafeUseByteString ByteString
m (((Ptr Msg32, CSize) -> IO Sig) -> IO Sig)
-> ((Ptr Msg32, CSize) -> IO Sig) -> IO Sig
forall a b. (a -> b) -> a -> b
$ \(Ptr Msg32
msg_ptr, CSize
_) -> do
      Ptr Sig64
sig_ptr <- Int -> IO (Ptr Sig64)
forall a. Int -> IO (Ptr a)
mallocBytes Int
64
      CInt
ret <- Ptr LCtx
-> Ptr Sig64
-> Ptr Msg32
-> Ptr SecKey32
-> FunPtr (NonceFun Any)
-> Ptr Any
-> IO CInt
forall a.
Ptr LCtx
-> Ptr Sig64
-> Ptr Msg32
-> Ptr SecKey32
-> FunPtr (NonceFun a)
-> Ptr a
-> IO CInt
ecdsaSign Ptr LCtx
ctx Ptr Sig64
sig_ptr Ptr Msg32
msg_ptr Ptr SecKey32
sec_key_ptr FunPtr (NonceFun Any)
forall a. FunPtr a
nullFunPtr Ptr Any
forall a. Ptr a
nullPtr
      Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (CInt -> Bool
isSuccess CInt
ret) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
        Ptr Sig64 -> IO ()
forall a. Ptr a -> IO ()
free Ptr Sig64
sig_ptr
        String -> IO ()
forall a. HasCallStack => String -> a
error String
"could not sign message"
      ByteString -> Sig
Sig (ByteString -> Sig) -> IO ByteString -> IO Sig
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Ptr Sig64, CSize) -> IO ByteString
forall a. (Ptr a, CSize) -> IO ByteString
unsafePackByteString (Ptr Sig64
sig_ptr, CSize
64)

derivePubKey :: Ctx -> SecKey -> PubKey
derivePubKey :: Ctx -> SecKey -> PubKey
derivePubKey (Ctx Ptr LCtx
ctx) (SecKey ByteString
sec_key) = IO PubKey -> PubKey
forall a. IO a -> a
unsafePerformIO (IO PubKey -> PubKey) -> IO PubKey -> PubKey
forall a b. (a -> b) -> a -> b
$
  ByteString -> ((Ptr SecKey32, CSize) -> IO PubKey) -> IO PubKey
forall a b. ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
unsafeUseByteString ByteString
sec_key (((Ptr SecKey32, CSize) -> IO PubKey) -> IO PubKey)
-> ((Ptr SecKey32, CSize) -> IO PubKey) -> IO PubKey
forall a b. (a -> b) -> a -> b
$ \(Ptr SecKey32
sec_key_ptr, CSize
_) -> do
    Ptr PubKey64
pub_key_ptr <- Int -> IO (Ptr PubKey64)
forall a. Int -> IO (Ptr a)
mallocBytes Int
64
    CInt
ret <- Ptr LCtx -> Ptr PubKey64 -> Ptr SecKey32 -> IO CInt
ecPubKeyCreate Ptr LCtx
ctx Ptr PubKey64
pub_key_ptr Ptr SecKey32
sec_key_ptr
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (CInt -> Bool
isSuccess CInt
ret) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
      Ptr PubKey64 -> IO ()
forall a. Ptr a -> IO ()
free Ptr PubKey64
pub_key_ptr
      String -> IO ()
forall a. HasCallStack => String -> a
error String
"could not compute public key"
    ByteString -> PubKey
PubKey (ByteString -> PubKey) -> IO ByteString -> IO PubKey
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Ptr PubKey64, CSize) -> IO ByteString
forall a. (Ptr a, CSize) -> IO ByteString
unsafePackByteString (Ptr PubKey64
pub_key_ptr, CSize
64)

-- | Add tweak to secret key.
tweakAddSecKey :: Ctx -> SecKey -> Tweak -> Maybe SecKey
tweakAddSecKey :: Ctx -> SecKey -> Tweak -> Maybe SecKey
tweakAddSecKey (Ctx Ptr LCtx
ctx) (SecKey ByteString
sec_key) (Tweak ByteString
t) = IO (Maybe SecKey) -> Maybe SecKey
forall a. IO a -> a
unsafePerformIO (IO (Maybe SecKey) -> Maybe SecKey)
-> IO (Maybe SecKey) -> Maybe SecKey
forall a b. (a -> b) -> a -> b
$
  ByteString
-> ((Ptr SecKey32, CSize) -> IO (Maybe SecKey))
-> IO (Maybe SecKey)
forall a b. ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
unsafeUseByteString ByteString
new_bs (((Ptr SecKey32, CSize) -> IO (Maybe SecKey)) -> IO (Maybe SecKey))
-> ((Ptr SecKey32, CSize) -> IO (Maybe SecKey))
-> IO (Maybe SecKey)
forall a b. (a -> b) -> a -> b
$ \(Ptr SecKey32
sec_key_ptr, CSize
_) ->
    ByteString
-> ((Ptr Tweak32, CSize) -> IO (Maybe SecKey)) -> IO (Maybe SecKey)
forall a b. ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
unsafeUseByteString ByteString
t (((Ptr Tweak32, CSize) -> IO (Maybe SecKey)) -> IO (Maybe SecKey))
-> ((Ptr Tweak32, CSize) -> IO (Maybe SecKey)) -> IO (Maybe SecKey)
forall a b. (a -> b) -> a -> b
$ \(Ptr Tweak32
tweak_ptr, CSize
_) -> do
      CInt
ret <- Ptr LCtx -> Ptr SecKey32 -> Ptr Tweak32 -> IO CInt
ecSecKeyTweakAdd Ptr LCtx
ctx Ptr SecKey32
sec_key_ptr Ptr Tweak32
tweak_ptr
      if CInt -> Bool
isSuccess CInt
ret
        then Maybe SecKey -> IO (Maybe SecKey)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (SecKey -> Maybe SecKey
forall a. a -> Maybe a
Just (ByteString -> SecKey
SecKey ByteString
new_bs))
        else Maybe SecKey -> IO (Maybe SecKey)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe SecKey
forall a. Maybe a
Nothing
  where
    new_bs :: ByteString
new_bs = ByteString -> ByteString
BS.copy ByteString
sec_key

-- | Multiply secret key by tweak.
tweakMulSecKey :: Ctx -> SecKey -> Tweak -> Maybe SecKey
tweakMulSecKey :: Ctx -> SecKey -> Tweak -> Maybe SecKey
tweakMulSecKey (Ctx Ptr LCtx
ctx) (SecKey ByteString
sec_key) (Tweak ByteString
t) = IO (Maybe SecKey) -> Maybe SecKey
forall a. IO a -> a
unsafePerformIO (IO (Maybe SecKey) -> Maybe SecKey)
-> IO (Maybe SecKey) -> Maybe SecKey
forall a b. (a -> b) -> a -> b
$
  ByteString
-> ((Ptr SecKey32, CSize) -> IO (Maybe SecKey))
-> IO (Maybe SecKey)
forall a b. ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
unsafeUseByteString ByteString
new_bs (((Ptr SecKey32, CSize) -> IO (Maybe SecKey)) -> IO (Maybe SecKey))
-> ((Ptr SecKey32, CSize) -> IO (Maybe SecKey))
-> IO (Maybe SecKey)
forall a b. (a -> b) -> a -> b
$ \(Ptr SecKey32
sec_key_ptr, CSize
_) ->
    ByteString
-> ((Ptr Tweak32, CSize) -> IO (Maybe SecKey)) -> IO (Maybe SecKey)
forall a b. ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
unsafeUseByteString ByteString
t (((Ptr Tweak32, CSize) -> IO (Maybe SecKey)) -> IO (Maybe SecKey))
-> ((Ptr Tweak32, CSize) -> IO (Maybe SecKey)) -> IO (Maybe SecKey)
forall a b. (a -> b) -> a -> b
$ \(Ptr Tweak32
tweak_ptr, CSize
_) -> do
      CInt
ret <- Ptr LCtx -> Ptr SecKey32 -> Ptr Tweak32 -> IO CInt
ecSecKeyTweakMul Ptr LCtx
ctx Ptr SecKey32
sec_key_ptr Ptr Tweak32
tweak_ptr
      if CInt -> Bool
isSuccess CInt
ret
        then Maybe SecKey -> IO (Maybe SecKey)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (SecKey -> Maybe SecKey
forall a. a -> Maybe a
Just (ByteString -> SecKey
SecKey ByteString
new_bs))
        else Maybe SecKey -> IO (Maybe SecKey)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe SecKey
forall a. Maybe a
Nothing
  where
    new_bs :: ByteString
new_bs = ByteString -> ByteString
BS.copy ByteString
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 -> PubKey -> Tweak -> Maybe PubKey
tweakAddPubKey (Ctx Ptr LCtx
ctx) (PubKey ByteString
pub_key) (Tweak ByteString
t) = IO (Maybe PubKey) -> Maybe PubKey
forall a. IO a -> a
unsafePerformIO (IO (Maybe PubKey) -> Maybe PubKey)
-> IO (Maybe PubKey) -> Maybe PubKey
forall a b. (a -> b) -> a -> b
$
  ByteString
-> ((Ptr PubKey64, CSize) -> IO (Maybe PubKey))
-> IO (Maybe PubKey)
forall a b. ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
unsafeUseByteString ByteString
new_bs (((Ptr PubKey64, CSize) -> IO (Maybe PubKey)) -> IO (Maybe PubKey))
-> ((Ptr PubKey64, CSize) -> IO (Maybe PubKey))
-> IO (Maybe PubKey)
forall a b. (a -> b) -> a -> b
$ \(Ptr PubKey64
pub_key_ptr, CSize
_) ->
    ByteString
-> ((Ptr Tweak32, CSize) -> IO (Maybe PubKey)) -> IO (Maybe PubKey)
forall a b. ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
unsafeUseByteString ByteString
t (((Ptr Tweak32, CSize) -> IO (Maybe PubKey)) -> IO (Maybe PubKey))
-> ((Ptr Tweak32, CSize) -> IO (Maybe PubKey)) -> IO (Maybe PubKey)
forall a b. (a -> b) -> a -> b
$ \(Ptr Tweak32
tweak_ptr, CSize
_) -> do
      CInt
ret <- Ptr LCtx -> Ptr PubKey64 -> Ptr Tweak32 -> IO CInt
ecPubKeyTweakAdd Ptr LCtx
ctx Ptr PubKey64
pub_key_ptr Ptr Tweak32
tweak_ptr
      if CInt -> Bool
isSuccess CInt
ret
        then Maybe PubKey -> IO (Maybe PubKey)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (PubKey -> Maybe PubKey
forall a. a -> Maybe a
Just (ByteString -> PubKey
PubKey ByteString
new_bs))
        else Maybe PubKey -> IO (Maybe PubKey)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe PubKey
forall a. Maybe a
Nothing
  where
    new_bs :: ByteString
new_bs = ByteString -> ByteString
BS.copy ByteString
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 -> PubKey -> Tweak -> Maybe PubKey
tweakMulPubKey (Ctx Ptr LCtx
ctx) (PubKey ByteString
pub_key) (Tweak ByteString
t) = IO (Maybe PubKey) -> Maybe PubKey
forall a. IO a -> a
unsafePerformIO (IO (Maybe PubKey) -> Maybe PubKey)
-> IO (Maybe PubKey) -> Maybe PubKey
forall a b. (a -> b) -> a -> b
$
  ByteString
-> ((Ptr PubKey64, CSize) -> IO (Maybe PubKey))
-> IO (Maybe PubKey)
forall a b. ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
unsafeUseByteString ByteString
new_bs (((Ptr PubKey64, CSize) -> IO (Maybe PubKey)) -> IO (Maybe PubKey))
-> ((Ptr PubKey64, CSize) -> IO (Maybe PubKey))
-> IO (Maybe PubKey)
forall a b. (a -> b) -> a -> b
$ \(Ptr PubKey64
pub_key_ptr, CSize
_) ->
    ByteString
-> ((Ptr Tweak32, CSize) -> IO (Maybe PubKey)) -> IO (Maybe PubKey)
forall a b. ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
unsafeUseByteString ByteString
t (((Ptr Tweak32, CSize) -> IO (Maybe PubKey)) -> IO (Maybe PubKey))
-> ((Ptr Tweak32, CSize) -> IO (Maybe PubKey)) -> IO (Maybe PubKey)
forall a b. (a -> b) -> a -> b
$ \(Ptr Tweak32
tweak_ptr, CSize
_) -> do
      CInt
ret <- Ptr LCtx -> Ptr PubKey64 -> Ptr Tweak32 -> IO CInt
ecPubKeyTweakMul Ptr LCtx
ctx Ptr PubKey64
pub_key_ptr Ptr Tweak32
tweak_ptr
      if CInt -> Bool
isSuccess CInt
ret
        then Maybe PubKey -> IO (Maybe PubKey)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (PubKey -> Maybe PubKey
forall a. a -> Maybe a
Just (ByteString -> PubKey
PubKey ByteString
new_bs))
        else Maybe PubKey -> IO (Maybe PubKey)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe PubKey
forall a. Maybe a
Nothing
  where
    new_bs :: ByteString
new_bs = ByteString -> ByteString
BS.copy ByteString
pub_key

-- | Add multiple public keys together.
combinePubKeys :: Ctx -> [PubKey] -> Maybe PubKey
combinePubKeys :: Ctx -> [PubKey] -> Maybe PubKey
combinePubKeys Ctx
_ [] = Maybe PubKey
forall a. Maybe a
Nothing
combinePubKeys (Ctx Ptr LCtx
ctx) [PubKey]
pubs = IO (Maybe PubKey) -> Maybe PubKey
forall a. IO a -> a
unsafePerformIO (IO (Maybe PubKey) -> Maybe PubKey)
-> IO (Maybe PubKey) -> Maybe PubKey
forall a b. (a -> b) -> a -> b
$
  [Ptr PubKey64]
-> [PubKey]
-> ([Ptr PubKey64] -> IO (Maybe PubKey))
-> IO (Maybe PubKey)
forall {a} {b}. [Ptr a] -> [PubKey] -> ([Ptr a] -> IO b) -> IO b
pointers [] [PubKey]
pubs (([Ptr PubKey64] -> IO (Maybe PubKey)) -> IO (Maybe PubKey))
-> ([Ptr PubKey64] -> IO (Maybe PubKey)) -> IO (Maybe PubKey)
forall a b. (a -> b) -> a -> b
$ \[Ptr PubKey64]
ps ->
    Int
-> (Ptr (Ptr PubKey64) -> IO (Maybe PubKey)) -> IO (Maybe PubKey)
forall a b. Storable a => Int -> (Ptr a -> IO b) -> IO b
allocaArray ([Ptr PubKey64] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Ptr PubKey64]
ps) ((Ptr (Ptr PubKey64) -> IO (Maybe PubKey)) -> IO (Maybe PubKey))
-> (Ptr (Ptr PubKey64) -> IO (Maybe PubKey)) -> IO (Maybe PubKey)
forall a b. (a -> b) -> a -> b
$ \Ptr (Ptr PubKey64)
a -> do
      Ptr PubKey64
out <- Int -> IO (Ptr PubKey64)
forall a. Int -> IO (Ptr a)
mallocBytes Int
64
      Ptr (Ptr PubKey64) -> [Ptr PubKey64] -> IO ()
forall a. Storable a => Ptr a -> [a] -> IO ()
pokeArray Ptr (Ptr PubKey64)
a [Ptr PubKey64]
ps
      CInt
ret <- Ptr LCtx -> Ptr PubKey64 -> Ptr (Ptr PubKey64) -> CInt -> IO CInt
ecPubKeyCombine Ptr LCtx
ctx Ptr PubKey64
out Ptr (Ptr PubKey64)
a (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> CInt) -> Int -> CInt
forall a b. (a -> b) -> a -> b
$ [Ptr PubKey64] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Ptr PubKey64]
ps)
      if CInt -> Bool
isSuccess CInt
ret
        then do
          ByteString
bs <- (Ptr PubKey64, CSize) -> IO ByteString
forall a. (Ptr a, CSize) -> IO ByteString
unsafePackByteString (Ptr PubKey64
out, CSize
64)
          Maybe PubKey -> IO (Maybe PubKey)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (PubKey -> Maybe PubKey
forall a. a -> Maybe a
Just (ByteString -> PubKey
PubKey ByteString
bs))
        else do
          Ptr PubKey64 -> IO ()
forall a. Ptr a -> IO ()
free Ptr PubKey64
out
          Maybe PubKey -> IO (Maybe PubKey)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe PubKey
forall a. Maybe a
Nothing
  where
    pointers :: [Ptr a] -> [PubKey] -> ([Ptr a] -> IO b) -> IO b
pointers [Ptr a]
ps [] [Ptr a] -> IO b
f = [Ptr a] -> IO b
f [Ptr a]
ps
    pointers [Ptr a]
ps (PubKey ByteString
pub_key : [PubKey]
pub_keys) [Ptr a] -> IO b
f =
      ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
forall a b. ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
unsafeUseByteString ByteString
pub_key (((Ptr a, CSize) -> IO b) -> IO b)
-> ((Ptr a, CSize) -> IO b) -> IO b
forall a b. (a -> b) -> a -> b
$ \(Ptr a
p, CSize
_) ->
        [Ptr a] -> [PubKey] -> ([Ptr a] -> IO b) -> IO b
pointers (Ptr a
p Ptr a -> [Ptr a] -> [Ptr a]
forall a. a -> [a] -> [a]
: [Ptr a]
ps) [PubKey]
pub_keys [Ptr a] -> IO b
f

tweakNegate :: Ctx -> Tweak -> Maybe Tweak
tweakNegate :: Ctx -> Tweak -> Maybe Tweak
tweakNegate (Ctx Ptr LCtx
ctx) (Tweak ByteString
t) = IO (Maybe Tweak) -> Maybe Tweak
forall a. IO a -> a
unsafePerformIO (IO (Maybe Tweak) -> Maybe Tweak)
-> IO (Maybe Tweak) -> Maybe Tweak
forall a b. (a -> b) -> a -> b
$
  ByteString
-> ((Ptr Tweak32, CSize) -> IO (Maybe Tweak)) -> IO (Maybe Tweak)
forall a b. ByteString -> ((Ptr a, CSize) -> IO b) -> IO b
unsafeUseByteString ByteString
new (((Ptr Tweak32, CSize) -> IO (Maybe Tweak)) -> IO (Maybe Tweak))
-> ((Ptr Tweak32, CSize) -> IO (Maybe Tweak)) -> IO (Maybe Tweak)
forall a b. (a -> b) -> a -> b
$ \(Ptr Tweak32
out, CSize
_) -> do
    CInt
ret <- Ptr LCtx -> Ptr Tweak32 -> IO CInt
ecTweakNegate Ptr LCtx
ctx Ptr Tweak32
out
    if CInt -> Bool
isSuccess CInt
ret
      then Maybe Tweak -> IO (Maybe Tweak)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Tweak -> Maybe Tweak
forall a. a -> Maybe a
Just (ByteString -> Tweak
Tweak ByteString
new))
      else Maybe Tweak -> IO (Maybe Tweak)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Tweak
forall a. Maybe a
Nothing
  where
    new :: ByteString
new = ByteString -> ByteString
BS.copy ByteString
t

instance Arbitrary Msg where
  arbitrary :: Gen Msg
arbitrary = Gen Msg
gen_msg
    where
      valid_bs :: Gen (Maybe Msg)
valid_bs = Gen (Maybe Msg)
bs_gen Gen (Maybe Msg) -> (Maybe Msg -> Bool) -> Gen (Maybe Msg)
forall a. Gen a -> (a -> Bool) -> Gen a
`suchThat` Maybe Msg -> Bool
forall a. Maybe a -> Bool
isJust
      bs_gen :: Gen (Maybe Msg)
bs_gen = ByteString -> Maybe Msg
msg (ByteString -> Maybe Msg)
-> ([Word8] -> ByteString) -> [Word8] -> Maybe Msg
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Word8] -> ByteString
BS.pack ([Word8] -> Maybe Msg) -> Gen [Word8] -> Gen (Maybe Msg)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Gen Word8 -> Gen [Word8]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
32 Gen Word8
forall a. (Bounded a, Random a) => Gen a
arbitraryBoundedRandom
      gen_msg :: Gen Msg
gen_msg = Maybe Msg -> Msg
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe Msg -> Msg) -> Gen (Maybe Msg) -> Gen Msg
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (Maybe Msg)
valid_bs

instance Arbitrary SecKey where
  arbitrary :: Gen SecKey
arbitrary = Gen SecKey
gen_key
    where
      valid_bs :: Gen (Maybe SecKey)
valid_bs = Gen (Maybe SecKey)
bs_gen Gen (Maybe SecKey) -> (Maybe SecKey -> Bool) -> Gen (Maybe SecKey)
forall a. Gen a -> (a -> Bool) -> Gen a
`suchThat` Maybe SecKey -> Bool
forall a. Maybe a -> Bool
isJust
      bs_gen :: Gen (Maybe SecKey)
bs_gen = ByteString -> Maybe SecKey
secKey (ByteString -> Maybe SecKey)
-> ([Word8] -> ByteString) -> [Word8] -> Maybe SecKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Word8] -> ByteString
BS.pack ([Word8] -> Maybe SecKey) -> Gen [Word8] -> Gen (Maybe SecKey)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Gen Word8 -> Gen [Word8]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
32 Gen Word8
forall a. (Bounded a, Random a) => Gen a
arbitraryBoundedRandom
      gen_key :: Gen SecKey
gen_key = Maybe SecKey -> SecKey
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe SecKey -> SecKey) -> Gen (Maybe SecKey) -> Gen SecKey
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (Maybe SecKey)
valid_bs