{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ViewPatterns #-}

-- |
-- Module: Crypto.Curve.Secp256k1
-- Copyright: (c) 2024 Jared Tobin
-- License: MIT
-- Maintainer: Jared Tobin <jared@ppad.tech>
--
-- Bindings to bitcoin-core/secp256k1, a C library supporting digital
-- signatures and other cryptographic primitives on the secp256k1
-- elliptic curve.
--
-- This library exposes a minimal subset of functionality, primarily
-- supporting ECDSA/Schnorr signatures and ECDH secret computation.
--
-- We're interacting with a C library here, and we don't pretend that we
-- aren't. 'IO' is prevalent and unhidden, and asynchronous exceptions
-- (in the form of 'Secp256k1Exception') are the error-handling method
-- of choice.

module Crypto.Curve.Secp256k1 (
    Context(..)
  , wcontext
  , wrcontext

  , Sig
  , sign_ecdsa
  , verify_ecdsa
  , sign_schnorr
  , verify_schnorr
  , ecdh

  , parse_der
  , serialize_der
  , parse_compact
  , serialize_compact

  , Pub(..)
  , derive_pub
  , parse_pub
  , tweak_pub_add
  , tweak_pub_mul
  , tweak_sec_add
  , tweak_sec_mul
  , serialize_pub
  , serialize_pub_u
  , XOnlyPub(..)
  , xonly
  , parse_xonly
  , serialize_xonly
  , KeyPair
  , keypair
  , keypair_pub
  , keypair_sec

  , Secp256k1Exception(..)
  ) where

import Control.Exception (Exception, bracket, throwIO)
import Control.Monad (when)
import Crypto.Curve.Secp256k1.Internal hiding (Context, wcontext)
import qualified Crypto.Curve.Secp256k1.Internal as I (Context)
import GHC.Generics
import qualified Data.ByteString as BS
import qualified Foreign.Marshal.Alloc as A (alloca, allocaBytes)
import Foreign.Ptr (Ptr)
import qualified Foreign.Ptr as F (castPtr, nullPtr)
import qualified Foreign.Storable as S (poke, peek)

-- | A bitcoin-core/secp256k1 context.
--
--   bitcoin-core/secp256k1 computations typically require a context,
--   the primary purpose of which is to store randomization data as
--   increased protection against side-channel attacks (and the second
--   of which is boring pointer storage to various library callbacks).
--
--   You should create and use values of this type via 'wrcontext' or
--   'wcontext'.
--
--   The data constructor is exported only to make the implementation
--   easier to benchmark. You should /not/ pattern match on or
--   manipulate context values.
newtype Context = Context (Ptr I.Context)
  deriving stock (forall x. Context -> Rep Context x)
-> (forall x. Rep Context x -> Context) -> Generic Context
forall x. Rep Context x -> Context
forall x. Context -> Rep Context x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Context -> Rep Context x
from :: forall x. Context -> Rep Context x
$cto :: forall x. Rep Context x -> Context
to :: forall x. Rep Context x -> Context
Generic

instance Show Context where
  show :: Context -> String
show (Context Ptr Context
tex) = String
"<bitcoin-core/secp256k1 context " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Ptr Context -> String
forall a. Show a => a -> String
show Ptr Context
tex String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
">"

-- | A bitcoin-core/secp256k1-internal public key.
--
--   Create a value of this type by parsing a compressed or uncompressed
--   public key via 'parse_pub', deriving one from a secret key via
--   'create_pub', or extracting one from a keypair via 'keypair_pub'.
newtype Pub = Pub BS.ByteString
  deriving stock (forall x. Pub -> Rep Pub x)
-> (forall x. Rep Pub x -> Pub) -> Generic Pub
forall x. Rep Pub x -> Pub
forall x. Pub -> Rep Pub x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Pub -> Rep Pub x
from :: forall x. Pub -> Rep Pub x
$cto :: forall x. Rep Pub x -> Pub
to :: forall x. Rep Pub x -> Pub
Generic

instance Show Pub where
  show :: Pub -> String
show Pub
_ = String
"<bitcoin-core/secp256k1 public key>"

-- | A bitcoin-core/secp256k1-internal x-only public key.
--
--   An "x-only" public key corresponds to a public key with even
--   y-coordinate.
--
--   Create a value of this type from a 'Pub' via 'xonly', or parse one
--   directly via 'parse_xonly'.
newtype XOnlyPub = XOnlyPub BS.ByteString
  deriving stock (forall x. XOnlyPub -> Rep XOnlyPub x)
-> (forall x. Rep XOnlyPub x -> XOnlyPub) -> Generic XOnlyPub
forall x. Rep XOnlyPub x -> XOnlyPub
forall x. XOnlyPub -> Rep XOnlyPub x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. XOnlyPub -> Rep XOnlyPub x
from :: forall x. XOnlyPub -> Rep XOnlyPub x
$cto :: forall x. Rep XOnlyPub x -> XOnlyPub
to :: forall x. Rep XOnlyPub x -> XOnlyPub
Generic

instance Show XOnlyPub where
  show :: XOnlyPub -> String
show XOnlyPub
_ = String
"<bitcoin-core/secp256k1 x-only public key>"

-- | A bitcoin-core/secp256k1-internal keypair.
--
--   Create a value of this type by passing a secret key to
--   'keypair'.
newtype KeyPair = KeyPair BS.ByteString
  deriving stock (forall x. KeyPair -> Rep KeyPair x)
-> (forall x. Rep KeyPair x -> KeyPair) -> Generic KeyPair
forall x. Rep KeyPair x -> KeyPair
forall x. KeyPair -> Rep KeyPair x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. KeyPair -> Rep KeyPair x
from :: forall x. KeyPair -> Rep KeyPair x
$cto :: forall x. Rep KeyPair x -> KeyPair
to :: forall x. Rep KeyPair x -> KeyPair
Generic

instance Show KeyPair where
  show :: KeyPair -> String
show KeyPair
_ = String
"<bitcoin-core/secp256k1 keypair>"

-- | A bitcoin-core/secp256k1-internal ECDSA signature.
--
--   Create a value of this type via 'sign', or parse a DER-encoded
--   signature via 'parse_der'.
newtype Sig = Sig BS.ByteString
  deriving stock (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

instance Show Sig where
  show :: Sig -> String
show Sig
_ = String
"<bitcoin-core/secp256k1 signature>"

-- exceptions

-- | A catch-all exception type.
--
data Secp256k1Exception =
    -- | Thrown when a bitcoin-core/secp256k1 function returns a value
    --   indicating failure.
    Secp256k1Error
    -- | Thrown when a csecp256k1 function has been passed a bad (i.e.,
    --   incorrectly-sized) input.
  | CSecp256k1Error
  deriving Int -> Secp256k1Exception -> ShowS
[Secp256k1Exception] -> ShowS
Secp256k1Exception -> String
(Int -> Secp256k1Exception -> ShowS)
-> (Secp256k1Exception -> String)
-> ([Secp256k1Exception] -> ShowS)
-> Show Secp256k1Exception
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Secp256k1Exception -> ShowS
showsPrec :: Int -> Secp256k1Exception -> ShowS
$cshow :: Secp256k1Exception -> String
show :: Secp256k1Exception -> String
$cshowList :: [Secp256k1Exception] -> ShowS
showList :: [Secp256k1Exception] -> ShowS
Show

instance Exception Secp256k1Exception

-- context

-- | Execute the supplied continuation within a fresh
--   bitcoin-core/secp256k1 context. The context will be destroyed
--   afterwards.
--
--   This function executes the supplied continuation in a context
--   that has /not/ been randomized, and so /doesn't/ offer additional
--   side-channel attack protection. For that, use 'wrcontext'.
--
--   >>> wcontext $ \tex -> parse_pub tex bytestring
--   "<bitcoin-core/secp256k1 public key>"
wcontext
  :: (Context -> IO ()) -- ^ continuation to run in the context
  -> IO ()
wcontext :: (Context -> IO ()) -> IO ()
wcontext = IO Context -> (Context -> IO ()) -> (Context -> IO ()) -> IO ()
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket IO Context
create Context -> IO ()
destroy where
  create :: IO Context
create = do
    Ptr Context
tex <- CUInt -> IO (Ptr Context)
secp256k1_context_create CUInt
forall a. Integral a => a
_SECP256K1_CONTEXT_NONE
    Context -> IO Context
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Ptr Context -> Context
Context Ptr Context
tex)

  destroy :: Context -> IO ()
destroy (Context Ptr Context
tex) =
    Ptr Context -> IO ()
secp256k1_context_destroy Ptr Context
tex

-- | Same as 'wcontext', but randomize the bitcoin-core/secp256k1
--   context with the provided 32 bytes of entropy before executing the
--   supplied continuation.
--
--   Use this function to execute computations that may benefit from
--   additional side-channel attack protection.
--
--   >>> wrcontext entropy $ \tex -> sign tex sec msg
--   "<bitcoin-core/secp256k1 signature>"
wrcontext
  :: BS.ByteString     -- ^ 32 bytes of fresh entropy
  -> (Context -> IO ()) -- ^ continuation to run in the context
  -> IO ()
wrcontext :: ByteString -> (Context -> IO ()) -> IO ()
wrcontext ByteString
enn Context -> IO ()
con
    | ByteString -> Int
BS.length ByteString
enn Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
32 = Secp256k1Exception -> IO ()
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
CSecp256k1Error
    | Bool
otherwise = IO Context -> (Context -> IO ()) -> (Context -> IO ()) -> IO ()
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket IO Context
create Context -> IO ()
destroy Context -> IO ()
con
  where
    create :: IO Context
create = do
      Ptr Context
tex <- CUInt -> IO (Ptr Context)
secp256k1_context_create CUInt
forall a. Integral a => a
_SECP256K1_CONTEXT_NONE
      ByteString -> (CString -> IO Context) -> IO Context
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
enn ((CString -> IO Context) -> IO Context)
-> (CString -> IO Context) -> IO Context
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr Seed32
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr Seed32
sed) -> do
        CInt
suc <- Ptr Context -> Ptr Seed32 -> IO CInt
secp256k1_context_randomize Ptr Context
tex Ptr Seed32
sed
        Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CInt
suc CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Secp256k1Exception -> IO ()
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
Secp256k1Error
        Context -> IO Context
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Ptr Context -> Context
Context Ptr Context
tex)

    destroy :: Context -> IO ()
destroy (Context Ptr Context
tex) =
      Ptr Context -> IO ()
secp256k1_context_destroy Ptr Context
tex

-- ec

-- | Derive a public key from a 32-byte secret key.
--
--   >>> wrcontext entropy $ \tex -> derive_pub tex sec
--   "<bitcoin-core/secp256k1 public key>"
derive_pub
  :: Context
  -> BS.ByteString -- ^ 32-byte secret key
  -> IO Pub
derive_pub :: Context -> ByteString -> IO Pub
derive_pub (Context Ptr Context
tex) ByteString
bs
  | ByteString -> Int
BS.length ByteString
bs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
32 = Secp256k1Exception -> IO Pub
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
CSecp256k1Error
  | Bool
otherwise = ByteString -> (CString -> IO Pub) -> IO Pub
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
bs ((CString -> IO Pub) -> IO Pub) -> (CString -> IO Pub) -> IO Pub
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr SecKey32
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr SecKey32
sec) ->
      Int -> (Ptr PubKey64 -> IO Pub) -> IO Pub
forall a b. Int -> (Ptr a -> IO b) -> IO b
A.allocaBytes Int
_PUB_BYTES_INTERNAL ((Ptr PubKey64 -> IO Pub) -> IO Pub)
-> (Ptr PubKey64 -> IO Pub) -> IO Pub
forall a b. (a -> b) -> a -> b
$ \Ptr PubKey64
out -> do
        CInt
suc <- Ptr Context -> Ptr PubKey64 -> Ptr SecKey32 -> IO CInt
secp256k1_ec_pubkey_create Ptr Context
tex Ptr PubKey64
out Ptr SecKey32
sec
        Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CInt
suc CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Secp256k1Exception -> IO ()
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
Secp256k1Error
        let pub :: Ptr b
pub = Ptr PubKey64 -> Ptr b
forall a b. Ptr a -> Ptr b
F.castPtr Ptr PubKey64
out
        ByteString
key <- CStringLen -> IO ByteString
BS.packCStringLen (CString
forall {b}. Ptr b
pub, Int
_PUB_BYTES_INTERNAL)
        Pub -> IO Pub
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteString -> Pub
Pub ByteString
key)

-- | Parse a compressed (33-byte) or uncompressed (65-byte) public key.
--
--   >>> wcontext $ \tex -> parse_pub tex bs
--   "<bitcoin-core/secp256k1 public key>"
parse_pub
  :: Context
  -> BS.ByteString -- ^ compressed or uncompressed public key
  -> IO Pub
parse_pub :: Context -> ByteString -> IO Pub
parse_pub (Context Ptr Context
tex) ByteString
bs =
  ByteString -> (CStringLen -> IO Pub) -> IO Pub
forall a. ByteString -> (CStringLen -> IO a) -> IO a
BS.useAsCStringLen ByteString
bs ((CStringLen -> IO Pub) -> IO Pub)
-> (CStringLen -> IO Pub) -> IO Pub
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr CUChar
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr CUChar
pub, Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral -> CSize
len) ->
    Int -> (Ptr PubKey64 -> IO Pub) -> IO Pub
forall a b. Int -> (Ptr a -> IO b) -> IO b
A.allocaBytes Int
_PUB_BYTES_INTERNAL ((Ptr PubKey64 -> IO Pub) -> IO Pub)
-> (Ptr PubKey64 -> IO Pub) -> IO Pub
forall a b. (a -> b) -> a -> b
$ \Ptr PubKey64
out -> do
      CInt
suc <- Ptr Context -> Ptr PubKey64 -> Ptr CUChar -> CSize -> IO CInt
secp256k1_ec_pubkey_parse Ptr Context
tex Ptr PubKey64
out Ptr CUChar
pub CSize
len
      Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CInt
suc CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Secp256k1Exception -> IO ()
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
Secp256k1Error
      let par :: Ptr b
par = Ptr PubKey64 -> Ptr b
forall a b. Ptr a -> Ptr b
F.castPtr Ptr PubKey64
out
      ByteString
key <- CStringLen -> IO ByteString
BS.packCStringLen (CString
forall {b}. Ptr b
par, Int
_PUB_BYTES_INTERNAL)
      Pub -> IO Pub
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteString -> Pub
Pub ByteString
key)

data PubFormat =
    Compressed
  | Uncompressed

-- | Serialize a public key into a compressed (33-byte) bytestring
--   representation.
--
--   >>> wcontext $ \tex -> serialize_pub tex pub
serialize_pub
  :: Context
  -> Pub
  -> IO BS.ByteString -- ^ serialized compressed public key
serialize_pub :: Context -> Pub -> IO ByteString
serialize_pub = PubFormat -> Context -> Pub -> IO ByteString
serialize_pub_in PubFormat
Compressed

-- | Serialize a public key into an uncompressed (65-byte) bytestring
--   represention.
--
--   >>> wcontext $ \tex -> serialize_pub_u tex pub
serialize_pub_u
  :: Context
  -> Pub
  -> IO BS.ByteString -- ^ serialized uncompressed public key
serialize_pub_u :: Context -> Pub -> IO ByteString
serialize_pub_u = PubFormat -> Context -> Pub -> IO ByteString
serialize_pub_in PubFormat
Uncompressed

serialize_pub_in :: PubFormat -> Context -> Pub -> IO BS.ByteString
serialize_pub_in :: PubFormat -> Context -> Pub -> IO ByteString
serialize_pub_in PubFormat
for (Context Ptr Context
tex) (Pub ByteString
pub) =
    ByteString -> (CString -> IO ByteString) -> IO ByteString
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
pub ((CString -> IO ByteString) -> IO ByteString)
-> (CString -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr PubKey64
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr PubKey64
key) ->
      (Ptr CSize -> IO ByteString) -> IO ByteString
forall a b. Storable a => (Ptr a -> IO b) -> IO b
A.alloca ((Ptr CSize -> IO ByteString) -> IO ByteString)
-> (Ptr CSize -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr CSize
len ->
        Int -> (Ptr CUChar -> IO ByteString) -> IO ByteString
forall a b. Int -> (Ptr a -> IO b) -> IO b
A.allocaBytes Int
bys ((Ptr CUChar -> IO ByteString) -> IO ByteString)
-> (Ptr CUChar -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr CUChar
out -> do
          let siz :: CSize
siz = Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
bys
          Ptr CSize -> CSize -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
S.poke Ptr CSize
len CSize
siz
          CInt
suc <- Ptr Context
-> Ptr CUChar -> Ptr CSize -> Ptr PubKey64 -> CUInt -> IO CInt
secp256k1_ec_pubkey_serialize Ptr Context
tex Ptr CUChar
out Ptr CSize
len Ptr PubKey64
key CUInt
fal
          Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CInt
suc CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Secp256k1Exception -> IO ()
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
Secp256k1Error
          CSize
pec <- Ptr CSize -> IO CSize
forall a. Storable a => Ptr a -> IO a
S.peek Ptr CSize
len
          let enc :: Ptr b
enc = Ptr CUChar -> Ptr b
forall a b. Ptr a -> Ptr b
F.castPtr Ptr CUChar
out
              nel :: Int
nel = CSize -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
pec
          CStringLen -> IO ByteString
BS.packCStringLen (CString
forall {b}. Ptr b
enc, Int
nel)
  where
    bys :: Int
bys = case PubFormat
for of
      PubFormat
Compressed -> Int
_PUB_BYTES_COMPRESSED
      PubFormat
Uncompressed -> Int
_PUB_BYTES_UNCOMPRESSED

    fal :: CUInt
fal = case PubFormat
for of
      PubFormat
Compressed -> CUInt
_COMPRESSED_FLAG
      PubFormat
Uncompressed -> CUInt
_UNCOMPRESSED_FLAG

-- | Additively tweak a public key with the supplied 32-byte tweak.
--
--   >>> wrcontext $ \tex -> tweak_pub_add pub tweak
tweak_pub_add
  :: Context
  -> Pub
  -> BS.ByteString -- ^ 32-byte tweak value
  -> IO Pub
tweak_pub_add :: Context -> Pub -> ByteString -> IO Pub
tweak_pub_add (Context Ptr Context
tex) (Pub ByteString
pub) ByteString
wee
  | ByteString -> Int
BS.length ByteString
wee Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
32 = Secp256k1Exception -> IO Pub
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
CSecp256k1Error
  | Bool
otherwise = do
      let cop :: ByteString
cop = ByteString -> ByteString
BS.copy ByteString
pub
      ByteString -> (CString -> IO Pub) -> IO Pub
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
cop ((CString -> IO Pub) -> IO Pub) -> (CString -> IO Pub) -> IO Pub
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr PubKey64
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr PubKey64
out) ->
        ByteString -> (CString -> IO Pub) -> IO Pub
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
wee ((CString -> IO Pub) -> IO Pub) -> (CString -> IO Pub) -> IO Pub
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr Tweak32
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr Tweak32
eek) -> do
          CInt
suc <- Ptr Context -> Ptr PubKey64 -> Ptr Tweak32 -> IO CInt
secp256k1_ec_pubkey_tweak_add Ptr Context
tex Ptr PubKey64
out Ptr Tweak32
eek
          Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CInt
suc CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Secp256k1Exception -> IO ()
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
Secp256k1Error
          let enc :: Ptr b
enc = Ptr PubKey64 -> Ptr b
forall a b. Ptr a -> Ptr b
F.castPtr Ptr PubKey64
out
          ByteString
key <- CStringLen -> IO ByteString
BS.packCStringLen (CString
forall {b}. Ptr b
enc, Int
_PUB_BYTES_INTERNAL)
          Pub -> IO Pub
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteString -> Pub
Pub ByteString
key)

-- | Multiplicatively tweak a public key with the supplied 32-byte
--   tweak.
--
--   >>> wrcontext $ \tex -> tweak_pub_mul pub tweak
tweak_pub_mul
  :: Context
  -> Pub
  -> BS.ByteString -- ^ 32-byte tweak value
  -> IO Pub
tweak_pub_mul :: Context -> Pub -> ByteString -> IO Pub
tweak_pub_mul (Context Ptr Context
tex) (Pub ByteString
pub) ByteString
wee
  | ByteString -> Int
BS.length ByteString
wee Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
32 = Secp256k1Exception -> IO Pub
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
CSecp256k1Error
  | Bool
otherwise = do
      let cop :: ByteString
cop = ByteString -> ByteString
BS.copy ByteString
pub
      ByteString -> (CString -> IO Pub) -> IO Pub
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
cop ((CString -> IO Pub) -> IO Pub) -> (CString -> IO Pub) -> IO Pub
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr PubKey64
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr PubKey64
out) ->
        ByteString -> (CString -> IO Pub) -> IO Pub
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
wee ((CString -> IO Pub) -> IO Pub) -> (CString -> IO Pub) -> IO Pub
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr Tweak32
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr Tweak32
eek) -> do
          CInt
suc <- Ptr Context -> Ptr PubKey64 -> Ptr Tweak32 -> IO CInt
secp256k1_ec_pubkey_tweak_mul Ptr Context
tex Ptr PubKey64
out Ptr Tweak32
eek
          Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CInt
suc CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Secp256k1Exception -> IO ()
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
Secp256k1Error
          let enc :: Ptr b
enc = Ptr PubKey64 -> Ptr b
forall a b. Ptr a -> Ptr b
F.castPtr Ptr PubKey64
out
          ByteString
key <- CStringLen -> IO ByteString
BS.packCStringLen (CString
forall {b}. Ptr b
enc, Int
_PUB_BYTES_INTERNAL)
          Pub -> IO Pub
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteString -> Pub
Pub ByteString
key)

-- | Additively tweak a secret key with the supplied 32-byte tweak.
--
--   >>> wrcontext $ \tex -> tweak_sec_add sec tweak
tweak_sec_add
  :: Context
  -> BS.ByteString    -- ^ 32-byte secret key
  -> BS.ByteString    -- ^ 32-byte tweak value
  -> IO BS.ByteString -- ^ 32-byte secret key
tweak_sec_add :: Context -> ByteString -> ByteString -> IO ByteString
tweak_sec_add (Context Ptr Context
tex) ByteString
key ByteString
wee
  | ByteString -> Int
BS.length ByteString
key Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
32 Bool -> Bool -> Bool
|| ByteString -> Int
BS.length ByteString
wee Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
32 = Secp256k1Exception -> IO ByteString
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
CSecp256k1Error
  | Bool
otherwise = do
      let sec :: ByteString
sec = ByteString -> ByteString
BS.copy ByteString
key
      ByteString -> (CString -> IO ByteString) -> IO ByteString
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
sec ((CString -> IO ByteString) -> IO ByteString)
-> (CString -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr SecKey32
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr SecKey32
out) ->
        ByteString -> (CString -> IO ByteString) -> IO ByteString
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
wee ((CString -> IO ByteString) -> IO ByteString)
-> (CString -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr Tweak32
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr Tweak32
eek) -> do
          CInt
suc <- Ptr Context -> Ptr SecKey32 -> Ptr Tweak32 -> IO CInt
secp256k1_ec_seckey_tweak_add Ptr Context
tex Ptr SecKey32
out Ptr Tweak32
eek
          Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CInt
suc CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Secp256k1Exception -> IO ()
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
Secp256k1Error
          let enc :: Ptr b
enc = Ptr SecKey32 -> Ptr b
forall a b. Ptr a -> Ptr b
F.castPtr Ptr SecKey32
out
          CStringLen -> IO ByteString
BS.packCStringLen (CString
forall {b}. Ptr b
enc, Int
_SEC_BYTES)

-- | Multiplicatively tweak a secret key with the supplied 32-byte
--   tweak.
--
--   >>> wrcontext $ \tex -> tweak_sec_mul sec tweak
tweak_sec_mul
  :: Context
  -> BS.ByteString    -- ^ 32-byte secret key
  -> BS.ByteString    -- ^ 32-byte tweak value
  -> IO BS.ByteString -- ^ 32-byte secret key
tweak_sec_mul :: Context -> ByteString -> ByteString -> IO ByteString
tweak_sec_mul (Context Ptr Context
tex) ByteString
key ByteString
wee
  | ByteString -> Int
BS.length ByteString
key Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
32 Bool -> Bool -> Bool
|| ByteString -> Int
BS.length ByteString
wee Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
32 = Secp256k1Exception -> IO ByteString
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
CSecp256k1Error
  | Bool
otherwise = do
      let sec :: ByteString
sec = ByteString -> ByteString
BS.copy ByteString
key
      ByteString -> (CString -> IO ByteString) -> IO ByteString
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
sec ((CString -> IO ByteString) -> IO ByteString)
-> (CString -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr SecKey32
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr SecKey32
out) ->
        ByteString -> (CString -> IO ByteString) -> IO ByteString
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
wee ((CString -> IO ByteString) -> IO ByteString)
-> (CString -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr Tweak32
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr Tweak32
eek) -> do
          CInt
suc <- Ptr Context -> Ptr SecKey32 -> Ptr Tweak32 -> IO CInt
secp256k1_ec_seckey_tweak_mul Ptr Context
tex Ptr SecKey32
out Ptr Tweak32
eek
          Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CInt
suc CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Secp256k1Exception -> IO ()
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
Secp256k1Error
          let enc :: Ptr b
enc = Ptr SecKey32 -> Ptr b
forall a b. Ptr a -> Ptr b
F.castPtr Ptr SecKey32
out
          CStringLen -> IO ByteString
BS.packCStringLen (CString
forall {b}. Ptr b
enc, Int
_SEC_BYTES)

-- ecdsa

-- | Sign a 32-byte message hash with the provided secret key.
--
--   >>> wrcontext entropy $ \tex -> sign tex sec msg
--   "<bitcoin-core/secp256k1 signature>"
sign_ecdsa
  :: Context
  -> BS.ByteString -- ^ 32-byte secret key
  -> BS.ByteString -- ^ 32-byte message hash
  -> IO Sig
sign_ecdsa :: Context -> ByteString -> ByteString -> IO Sig
sign_ecdsa (Context Ptr Context
tex) ByteString
key ByteString
msg
  | ByteString -> Int
BS.length ByteString
key Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
32 Bool -> Bool -> Bool
|| ByteString -> Int
BS.length ByteString
msg Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
32 = Secp256k1Exception -> IO Sig
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
CSecp256k1Error
  | Bool
otherwise = Int -> (Ptr Sig64 -> IO Sig) -> IO Sig
forall a b. Int -> (Ptr a -> IO b) -> IO b
A.allocaBytes Int
_SIG_BYTES ((Ptr Sig64 -> IO Sig) -> IO Sig)
-> (Ptr Sig64 -> IO Sig) -> IO Sig
forall a b. (a -> b) -> a -> b
$ \Ptr Sig64
out ->
      ByteString -> (CString -> IO Sig) -> IO Sig
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
msg ((CString -> IO Sig) -> IO Sig) -> (CString -> IO Sig) -> IO Sig
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr MsgHash32
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr MsgHash32
has) ->
        ByteString -> (CString -> IO Sig) -> IO Sig
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
key ((CString -> IO Sig) -> IO Sig) -> (CString -> IO Sig) -> IO Sig
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr SecKey32
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr SecKey32
sec) -> do
          CInt
suc <- Ptr Context
-> Ptr Sig64
-> Ptr MsgHash32
-> Ptr SecKey32
-> Ptr Any
-> Ptr Any
-> IO CInt
forall a b.
Ptr Context
-> Ptr Sig64
-> Ptr MsgHash32
-> Ptr SecKey32
-> Ptr a
-> Ptr b
-> IO CInt
secp256k1_ecdsa_sign Ptr Context
tex Ptr Sig64
out Ptr MsgHash32
has Ptr SecKey32
sec Ptr Any
forall {b}. Ptr b
F.nullPtr Ptr Any
forall {b}. Ptr b
F.nullPtr
          Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CInt
suc CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Secp256k1Exception -> IO ()
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
Secp256k1Error
          let sig :: Ptr b
sig = Ptr Sig64 -> Ptr b
forall a b. Ptr a -> Ptr b
F.castPtr Ptr Sig64
out
          ByteString
enc <- CStringLen -> IO ByteString
BS.packCStringLen (CString
forall {b}. Ptr b
sig, Int
_SIG_BYTES)
          Sig -> IO Sig
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteString -> Sig
Sig ByteString
enc)

-- | Verify an ECDSA signature for the provided message hash with the
--   supplied public key.
--
--   Returns 'True' for a verifying signature, 'False' otherwise.
--
--   >>> wcontext $ \tex -> verify tex pub msg good_sig
--   True
--   >>> wcontext $ \tex -> verify tex pub msg bad_sig
--   False
verify_ecdsa
  :: Context
  -> Pub
  -> BS.ByteString -- ^ 32-byte message hash
  -> Sig
  -> IO Bool
verify_ecdsa :: Context -> Pub -> ByteString -> Sig -> IO Bool
verify_ecdsa (Context Ptr Context
tex) (Pub ByteString
pub) ByteString
msg (Sig ByteString
sig)
  | ByteString -> Int
BS.length ByteString
msg Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
32 = Secp256k1Exception -> IO Bool
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
CSecp256k1Error
  | Bool
otherwise = ByteString -> (CString -> IO Bool) -> IO Bool
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
pub ((CString -> IO Bool) -> IO Bool)
-> (CString -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr PubKey64
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr PubKey64
key) ->
      ByteString -> (CString -> IO Bool) -> IO Bool
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
sig ((CString -> IO Bool) -> IO Bool)
-> (CString -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr Sig64
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr Sig64
sip) ->
        ByteString -> (CString -> IO Bool) -> IO Bool
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
msg ((CString -> IO Bool) -> IO Bool)
-> (CString -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr MsgHash32
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr MsgHash32
has) -> do
          CInt
suc <- Ptr Context
-> Ptr Sig64 -> Ptr MsgHash32 -> Ptr PubKey64 -> IO CInt
secp256k1_ecdsa_verify Ptr Context
tex Ptr Sig64
sip Ptr MsgHash32
has Ptr PubKey64
key
          Bool -> IO Bool
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CInt
suc CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
1)

-- | Parse a DER-encoded bytestring into a signature.
--
--   >>> wcontext $ \tex -> parse_der tex bytestring
--   "<bitcoin-core/secp256k1 signature>"
--   >>> wcontext $ \tex -> parse_der tex bad_bytestring
--   *** Exception: Secp256k1Error
parse_der
  :: Context
  -> BS.ByteString -- ^ DER-encoded signature
  -> IO Sig
parse_der :: Context -> ByteString -> IO Sig
parse_der (Context Ptr Context
tex) ByteString
bs =
  ByteString -> (CStringLen -> IO Sig) -> IO Sig
forall a. ByteString -> (CStringLen -> IO a) -> IO a
BS.useAsCStringLen ByteString
bs ((CStringLen -> IO Sig) -> IO Sig)
-> (CStringLen -> IO Sig) -> IO Sig
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr CUChar
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr CUChar
der, Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral -> CSize
len) ->
    Int -> (Ptr Sig64 -> IO Sig) -> IO Sig
forall a b. Int -> (Ptr a -> IO b) -> IO b
A.allocaBytes Int
_SIG_BYTES ((Ptr Sig64 -> IO Sig) -> IO Sig)
-> (Ptr Sig64 -> IO Sig) -> IO Sig
forall a b. (a -> b) -> a -> b
$ \Ptr Sig64
out -> do
      CInt
suc <- Ptr Context -> Ptr Sig64 -> Ptr CUChar -> CSize -> IO CInt
secp256k1_ecdsa_signature_parse_der Ptr Context
tex Ptr Sig64
out Ptr CUChar
der CSize
len
      Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CInt
suc CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Secp256k1Exception -> IO ()
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
Secp256k1Error
      let par :: Ptr b
par = Ptr Sig64 -> Ptr b
forall a b. Ptr a -> Ptr b
F.castPtr Ptr Sig64
out
      ByteString
sig <- CStringLen -> IO ByteString
BS.packCStringLen (CString
forall {b}. Ptr b
par, Int
_SIG_BYTES)
      Sig -> IO Sig
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteString -> Sig
Sig ByteString
sig)

-- | Serialize a signature into a DER-encoded bytestring.
--
--   >>> wcontext $ \tex -> serialize_der tex sig
serialize_der
  :: Context
  -> Sig
  -> IO BS.ByteString -- ^ DER-encoded signature
serialize_der :: Context -> Sig -> IO ByteString
serialize_der (Context Ptr Context
tex) (Sig ByteString
sig) =
  (Ptr CSize -> IO ByteString) -> IO ByteString
forall a b. Storable a => (Ptr a -> IO b) -> IO b
A.alloca ((Ptr CSize -> IO ByteString) -> IO ByteString)
-> (Ptr CSize -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr CSize
len ->
    Int -> (Ptr CUChar -> IO ByteString) -> IO ByteString
forall a b. Int -> (Ptr a -> IO b) -> IO b
A.allocaBytes Int
_DER_BYTES ((Ptr CUChar -> IO ByteString) -> IO ByteString)
-> (Ptr CUChar -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr CUChar
out ->
      ByteString -> (CString -> IO ByteString) -> IO ByteString
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
sig ((CString -> IO ByteString) -> IO ByteString)
-> (CString -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr Sig64
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr Sig64
sip) -> do
        let siz :: CSize
siz = Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
_DER_BYTES
        Ptr CSize -> CSize -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
S.poke Ptr CSize
len CSize
siz
        CInt
suc <- Ptr Context -> Ptr CUChar -> Ptr CSize -> Ptr Sig64 -> IO CInt
secp256k1_ecdsa_signature_serialize_der Ptr Context
tex Ptr CUChar
out Ptr CSize
len Ptr Sig64
sip
        Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CInt
suc CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Secp256k1Exception -> IO ()
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
Secp256k1Error
        CSize
pek <- Ptr CSize -> IO CSize
forall a. Storable a => Ptr a -> IO a
S.peek Ptr CSize
len
        let der :: Ptr b
der = Ptr CUChar -> Ptr b
forall a b. Ptr a -> Ptr b
F.castPtr Ptr CUChar
out
            nel :: Int
nel = CSize -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
pek
        CStringLen -> IO ByteString
BS.packCStringLen (CString
forall {b}. Ptr b
der, Int
nel)

-- | Parse a bytestring encoding a compact (64-byte) signature.
--
--   >>> wcontext $ \tex -> parse_compact tex bytestring
parse_compact
  :: Context
  -> BS.ByteString -- ^ bytestring encoding a 64-byte compact signature
  -> IO Sig
parse_compact :: Context -> ByteString -> IO Sig
parse_compact (Context Ptr Context
tex) ByteString
bs =
  ByteString -> (CString -> IO Sig) -> IO Sig
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
bs ((CString -> IO Sig) -> IO Sig) -> (CString -> IO Sig) -> IO Sig
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr CUChar
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr CUChar
com) ->
    Int -> (Ptr Sig64 -> IO Sig) -> IO Sig
forall a b. Int -> (Ptr a -> IO b) -> IO b
A.allocaBytes Int
_SIG_BYTES ((Ptr Sig64 -> IO Sig) -> IO Sig)
-> (Ptr Sig64 -> IO Sig) -> IO Sig
forall a b. (a -> b) -> a -> b
$ \Ptr Sig64
out -> do
      CInt
suc <- Ptr Context -> Ptr Sig64 -> Ptr CUChar -> IO CInt
secp256k1_ecdsa_signature_parse_compact Ptr Context
tex Ptr Sig64
out Ptr CUChar
com
      Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CInt
suc CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Secp256k1Exception -> IO ()
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
Secp256k1Error
      let par :: Ptr b
par = Ptr Sig64 -> Ptr b
forall a b. Ptr a -> Ptr b
F.castPtr Ptr Sig64
out
      ByteString
enc <- CStringLen -> IO ByteString
BS.packCStringLen (CString
forall {b}. Ptr b
par, Int
_SIG_BYTES)
      Sig -> IO Sig
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteString -> Sig
Sig ByteString
enc)

-- | Serialize a signature into a compact (64-byte) bytestring.
--
--   >>> wcontext $ \tex -> serialize_compact tex sig
serialize_compact
  :: Context
  -> Sig
  -> IO BS.ByteString
serialize_compact :: Context -> Sig -> IO ByteString
serialize_compact (Context Ptr Context
tex) (Sig ByteString
sig) =
  ByteString -> (CString -> IO ByteString) -> IO ByteString
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
sig ((CString -> IO ByteString) -> IO ByteString)
-> (CString -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr Sig64
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr Sig64
sip) ->
    Int -> (Ptr CUChar -> IO ByteString) -> IO ByteString
forall a b. Int -> (Ptr a -> IO b) -> IO b
A.allocaBytes Int
_SIG_BYTES ((Ptr CUChar -> IO ByteString) -> IO ByteString)
-> (Ptr CUChar -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr CUChar
out -> do
      -- always returns 1
      CInt
_ <- Ptr Context -> Ptr CUChar -> Ptr Sig64 -> IO CInt
secp256k1_ecdsa_signature_serialize_compact Ptr Context
tex Ptr CUChar
out Ptr Sig64
sip
      let enc :: Ptr b
enc = Ptr CUChar -> Ptr b
forall a b. Ptr a -> Ptr b
F.castPtr Ptr CUChar
out
      CStringLen -> IO ByteString
BS.packCStringLen (CString
forall {b}. Ptr b
enc, Int
_SIG_BYTES)

-- extrakeys

-- | Convert a public key into an x-only public key (i.e. one with even
--   y coordinate).
--
--   >>> wcontext $ \tex -> xonly tex pub
--   "<bitcoin-core/secp256k1 x-only public key>"
xonly :: Context -> Pub -> IO XOnlyPub
xonly :: Context -> Pub -> IO XOnlyPub
xonly (Context Ptr Context
tex) (Pub ByteString
pub) =
  Int -> (Ptr XOnlyPublicKey64 -> IO XOnlyPub) -> IO XOnlyPub
forall a b. Int -> (Ptr a -> IO b) -> IO b
A.allocaBytes Int
_PUB_BYTES_INTERNAL ((Ptr XOnlyPublicKey64 -> IO XOnlyPub) -> IO XOnlyPub)
-> (Ptr XOnlyPublicKey64 -> IO XOnlyPub) -> IO XOnlyPub
forall a b. (a -> b) -> a -> b
$ \Ptr XOnlyPublicKey64
out ->
    ByteString -> (CString -> IO XOnlyPub) -> IO XOnlyPub
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
pub ((CString -> IO XOnlyPub) -> IO XOnlyPub)
-> (CString -> IO XOnlyPub) -> IO XOnlyPub
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr PubKey64
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr PubKey64
pup) -> do
      -- returns 1 always
      CInt
_ <- Ptr Context
-> Ptr XOnlyPublicKey64 -> Ptr CInt -> Ptr PubKey64 -> IO CInt
secp256k1_xonly_pubkey_from_pubkey Ptr Context
tex Ptr XOnlyPublicKey64
out Ptr CInt
forall {b}. Ptr b
F.nullPtr Ptr PubKey64
pup
      let key :: Ptr b
key = Ptr XOnlyPublicKey64 -> Ptr b
forall a b. Ptr a -> Ptr b
F.castPtr Ptr XOnlyPublicKey64
out
      ByteString
pux <- CStringLen -> IO ByteString
BS.packCStringLen (CString
forall {b}. Ptr b
key, Int
_PUB_BYTES_INTERNAL)
      XOnlyPub -> IO XOnlyPub
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteString -> XOnlyPub
XOnlyPub ByteString
pux)

-- | Parse a compressed (33-byte) or uncompressed (65-byte) public key into
--   an x-only public key.
--
--   >>> wcontext $ \tex -> parse_xonly tex bytestring
--   "<bitcoin-core/secp256k1 x-only public key>"
parse_xonly
  :: Context
  -> BS.ByteString -- ^ compressed or uncompressed public key
  -> IO XOnlyPub
parse_xonly :: Context -> ByteString -> IO XOnlyPub
parse_xonly (Context Ptr Context
tex) ByteString
bs =
  Int -> (Ptr XOnlyPublicKey64 -> IO XOnlyPub) -> IO XOnlyPub
forall a b. Int -> (Ptr a -> IO b) -> IO b
A.allocaBytes Int
_PUB_BYTES_INTERNAL ((Ptr XOnlyPublicKey64 -> IO XOnlyPub) -> IO XOnlyPub)
-> (Ptr XOnlyPublicKey64 -> IO XOnlyPub) -> IO XOnlyPub
forall a b. (a -> b) -> a -> b
$ \Ptr XOnlyPublicKey64
out ->
    ByteString -> (CString -> IO XOnlyPub) -> IO XOnlyPub
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
bs ((CString -> IO XOnlyPub) -> IO XOnlyPub)
-> (CString -> IO XOnlyPub) -> IO XOnlyPub
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr CUChar
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr CUChar
pub) -> do
      CInt
suc <- Ptr Context -> Ptr XOnlyPublicKey64 -> Ptr CUChar -> IO CInt
secp256k1_xonly_pubkey_parse Ptr Context
tex Ptr XOnlyPublicKey64
out Ptr CUChar
pub
      Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CInt
suc CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Secp256k1Exception -> IO ()
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
Secp256k1Error
      let key :: Ptr b
key = Ptr XOnlyPublicKey64 -> Ptr b
forall a b. Ptr a -> Ptr b
F.castPtr Ptr XOnlyPublicKey64
out
      ByteString
pux <- CStringLen -> IO ByteString
BS.packCStringLen (CString
forall {b}. Ptr b
key, Int
_PUB_BYTES_INTERNAL)
      XOnlyPub -> IO XOnlyPub
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteString -> XOnlyPub
XOnlyPub ByteString
pux)

-- | Serialize an x-only public key into a 32-byte bytestring
--   representation.
--
--   >>> wcontext $ \tex -> serialize_xonly tex xonly
serialize_xonly
  :: Context
  -> XOnlyPub
  -> IO BS.ByteString -- ^ serialized x-only public key
serialize_xonly :: Context -> XOnlyPub -> IO ByteString
serialize_xonly (Context Ptr Context
tex) (XOnlyPub ByteString
pux) =
  Int -> (Ptr CUChar -> IO ByteString) -> IO ByteString
forall a b. Int -> (Ptr a -> IO b) -> IO b
A.allocaBytes Int
_PUB_BYTES_XONLY ((Ptr CUChar -> IO ByteString) -> IO ByteString)
-> (Ptr CUChar -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr CUChar
out -> do
    ByteString -> (CString -> IO ByteString) -> IO ByteString
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
pux ((CString -> IO ByteString) -> IO ByteString)
-> (CString -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr XOnlyPublicKey64
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr XOnlyPublicKey64
pub) -> do
      -- returns 1 always
      CInt
_ <- Ptr Context -> Ptr CUChar -> Ptr XOnlyPublicKey64 -> IO CInt
secp256k1_xonly_pubkey_serialize Ptr Context
tex Ptr CUChar
out Ptr XOnlyPublicKey64
pub
      let enc :: Ptr b
enc = Ptr CUChar -> Ptr b
forall a b. Ptr a -> Ptr b
F.castPtr Ptr CUChar
out
      CStringLen -> IO ByteString
BS.packCStringLen (CString
forall {b}. Ptr b
enc, Int
_PUB_BYTES_XONLY)

-- | Derive a keypair from the provided 32-byte secret key.
--
--   >>> wrcontext entropy $ \tex -> keypair tex sec
--   "<bitcoin-core/secp256k1 keypair>"
keypair
  :: Context
  -> BS.ByteString -- ^ 32-byte secret key
  -> IO KeyPair
keypair :: Context -> ByteString -> IO KeyPair
keypair (Context Ptr Context
tex) ByteString
sec
  | ByteString -> Int
BS.length ByteString
sec Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
32 = Secp256k1Exception -> IO KeyPair
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
CSecp256k1Error
  | Bool
otherwise = Int -> (Ptr KeyPair96 -> IO KeyPair) -> IO KeyPair
forall a b. Int -> (Ptr a -> IO b) -> IO b
A.allocaBytes Int
_KEYPAIR_BYTES ((Ptr KeyPair96 -> IO KeyPair) -> IO KeyPair)
-> (Ptr KeyPair96 -> IO KeyPair) -> IO KeyPair
forall a b. (a -> b) -> a -> b
$ \Ptr KeyPair96
out ->
      ByteString -> (CString -> IO KeyPair) -> IO KeyPair
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
sec ((CString -> IO KeyPair) -> IO KeyPair)
-> (CString -> IO KeyPair) -> IO KeyPair
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr SecKey32
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr SecKey32
key) -> do
        CInt
suc <- Ptr Context -> Ptr KeyPair96 -> Ptr SecKey32 -> IO CInt
secp256k1_keypair_create Ptr Context
tex Ptr KeyPair96
out Ptr SecKey32
key
        Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CInt
suc CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Secp256k1Exception -> IO ()
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
Secp256k1Error
        let enc :: Ptr b
enc = Ptr KeyPair96 -> Ptr b
forall a b. Ptr a -> Ptr b
F.castPtr Ptr KeyPair96
out
        ByteString
per <- CStringLen -> IO ByteString
BS.packCStringLen (CString
forall {b}. Ptr b
enc, Int
_KEYPAIR_BYTES)
        KeyPair -> IO KeyPair
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteString -> KeyPair
KeyPair ByteString
per)

-- | Extract a public key from a keypair.
--
--   >>> wrcontext entropy $ \tex -> keypair_pub tex keypair
--   "<bitcoin-core/secp256k1 public key>"
keypair_pub :: Context -> KeyPair -> IO Pub
keypair_pub :: Context -> KeyPair -> IO Pub
keypair_pub (Context Ptr Context
tex) (KeyPair ByteString
per) =
  Int -> (Ptr PubKey64 -> IO Pub) -> IO Pub
forall a b. Int -> (Ptr a -> IO b) -> IO b
A.allocaBytes Int
_PUB_BYTES_INTERNAL ((Ptr PubKey64 -> IO Pub) -> IO Pub)
-> (Ptr PubKey64 -> IO Pub) -> IO Pub
forall a b. (a -> b) -> a -> b
$ \Ptr PubKey64
out ->
    ByteString -> (CString -> IO Pub) -> IO Pub
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
per ((CString -> IO Pub) -> IO Pub) -> (CString -> IO Pub) -> IO Pub
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr KeyPair96
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr KeyPair96
par) -> do
      -- returns 1 always
      CInt
_ <- Ptr Context -> Ptr PubKey64 -> Ptr KeyPair96 -> IO CInt
secp256k1_keypair_pub Ptr Context
tex Ptr PubKey64
out Ptr KeyPair96
par
      let enc :: Ptr b
enc = Ptr PubKey64 -> Ptr b
forall a b. Ptr a -> Ptr b
F.castPtr Ptr PubKey64
out
      ByteString
pub <- CStringLen -> IO ByteString
BS.packCStringLen (CString
forall {b}. Ptr b
enc, Int
_PUB_BYTES_INTERNAL)
      Pub -> IO Pub
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ByteString -> Pub
Pub ByteString
pub)

-- | Extract a secret key from a keypair.
--
--   >>> wrcontext entropy $ \tex -> keypair_sec tex keypair
keypair_sec
  :: Context
  -> KeyPair
  -> IO BS.ByteString -- ^ 32-byte secret key
keypair_sec :: Context -> KeyPair -> IO ByteString
keypair_sec (Context Ptr Context
tex) (KeyPair ByteString
per) =
  Int -> (Ptr SecKey32 -> IO ByteString) -> IO ByteString
forall a b. Int -> (Ptr a -> IO b) -> IO b
A.allocaBytes Int
_SEC_BYTES ((Ptr SecKey32 -> IO ByteString) -> IO ByteString)
-> (Ptr SecKey32 -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr SecKey32
out ->
    ByteString -> (CString -> IO ByteString) -> IO ByteString
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
per ((CString -> IO ByteString) -> IO ByteString)
-> (CString -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr KeyPair96
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr KeyPair96
par) -> do
      CInt
_ <- Ptr Context -> Ptr SecKey32 -> Ptr KeyPair96 -> IO CInt
secp256k1_keypair_sec Ptr Context
tex Ptr SecKey32
out Ptr KeyPair96
par
      let enc :: Ptr b
enc = Ptr SecKey32 -> Ptr b
forall a b. Ptr a -> Ptr b
F.castPtr Ptr SecKey32
out
      CStringLen -> IO ByteString
BS.packCStringLen (CString
forall {b}. Ptr b
enc, Int
_SEC_BYTES)

-- ecdh

-- | Compute an ECDH secret key from the provided public key and
--   (32-byte) secret key.
--
--   >>> wrcontext entropy $ \tex -> ecdh tex pub sec
ecdh
  :: Context
  -> Pub
  -> BS.ByteString    -- ^ 32-byte secret key
  -> IO BS.ByteString -- ^ 32-byte secret key
ecdh :: Context -> Pub -> ByteString -> IO ByteString
ecdh (Context Ptr Context
tex) (Pub ByteString
pub) ByteString
sec
  | ByteString -> Int
BS.length ByteString
sec Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
32 = Secp256k1Exception -> IO ByteString
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
CSecp256k1Error
  | Bool
otherwise =
      Int -> (Ptr CUChar -> IO ByteString) -> IO ByteString
forall a b. Int -> (Ptr a -> IO b) -> IO b
A.allocaBytes Int
_SEC_BYTES ((Ptr CUChar -> IO ByteString) -> IO ByteString)
-> (Ptr CUChar -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr CUChar
out ->
        ByteString -> (CString -> IO ByteString) -> IO ByteString
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
pub ((CString -> IO ByteString) -> IO ByteString)
-> (CString -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr PubKey64
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr PubKey64
pup) ->
          ByteString -> (CString -> IO ByteString) -> IO ByteString
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
sec ((CString -> IO ByteString) -> IO ByteString)
-> (CString -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr SecKey32
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr SecKey32
sep) -> do
            CInt
suc <- Ptr Context
-> Ptr CUChar
-> Ptr PubKey64
-> Ptr SecKey32
-> Ptr Any
-> Ptr Any
-> IO CInt
forall a b.
Ptr Context
-> Ptr CUChar
-> Ptr PubKey64
-> Ptr SecKey32
-> Ptr a
-> Ptr b
-> IO CInt
secp256k1_ecdh Ptr Context
tex Ptr CUChar
out Ptr PubKey64
pup Ptr SecKey32
sep Ptr Any
forall {b}. Ptr b
F.nullPtr Ptr Any
forall {b}. Ptr b
F.nullPtr
            Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CInt
suc CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Secp256k1Exception -> IO ()
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
Secp256k1Error
            let key :: Ptr b
key = Ptr CUChar -> Ptr b
forall a b. Ptr a -> Ptr b
F.castPtr Ptr CUChar
out
            CStringLen -> IO ByteString
BS.packCStringLen (CString
forall {b}. Ptr b
key, Int
_SEC_BYTES)

-- schnorr

-- | Sign a 32-byte message hash with the provided secret key, using the
--   provided 32 bytes of fresh auxiliary entropy.
--
--   BIP340 recommends that 32 bytes of fresh auxiliary entropy be
--   generated and added at signing time as additional protection
--   against side-channel attacks (namely, to thwart so-called "fault
--   injection" attacks). This entropy is /supplemental/ to security,
--   and the cryptographic security of the signature scheme itself does
--   not rely on it, so it is not strictly required; 32 zero bytes can
--   be used in its stead.
--
--   The resulting 64-byte Schnorr signature is portable, and so is not
--   wrapped in a newtype.
--
--   >>> import qualified System.Entropy as E  -- example entropy source
--   >>> enn <- E.getEntropy 32
--   >>> aux <- E.getEntropy 32
--   >>> wrcontext enn $ \tex -> sign_schnorr tex msg sec aux
sign_schnorr
  :: Context
  -> BS.ByteString    -- ^ 32-byte message hash
  -> BS.ByteString    -- ^ 32-byte secret key
  -> BS.ByteString    -- ^ 32 bytes of fresh entropy
  -> IO BS.ByteString -- ^ 64-byte signature
sign_schnorr :: Context -> ByteString -> ByteString -> ByteString -> IO ByteString
sign_schnorr c :: Context
c@(Context Ptr Context
tex) ByteString
msg ByteString
sec ByteString
aux
  | ByteString -> Int
BS.length ByteString
msg Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
32 Bool -> Bool -> Bool
|| ByteString -> Int
BS.length ByteString
sec Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
32 Bool -> Bool -> Bool
|| ByteString -> Int
BS.length ByteString
aux Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
32 =
      Secp256k1Exception -> IO ByteString
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
CSecp256k1Error
  | Bool
otherwise = Int -> (Ptr Sig64 -> IO ByteString) -> IO ByteString
forall a b. Int -> (Ptr a -> IO b) -> IO b
A.allocaBytes Int
_SIG_BYTES ((Ptr Sig64 -> IO ByteString) -> IO ByteString)
-> (Ptr Sig64 -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr Sig64
out ->
      ByteString -> (CString -> IO ByteString) -> IO ByteString
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
msg ((CString -> IO ByteString) -> IO ByteString)
-> (CString -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr MsgHash32
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr MsgHash32
has) ->
        ByteString -> (CString -> IO ByteString) -> IO ByteString
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
aux ((CString -> IO ByteString) -> IO ByteString)
-> (CString -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr CUChar
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr CUChar
enn) -> do
          KeyPair ByteString
per <- Context -> ByteString -> IO KeyPair
keypair Context
c ByteString
sec
          ByteString -> (CString -> IO ByteString) -> IO ByteString
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
per ((CString -> IO ByteString) -> IO ByteString)
-> (CString -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr KeyPair96
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr KeyPair96
pur) -> do
            CInt
suc <- Ptr Context
-> Ptr Sig64
-> Ptr MsgHash32
-> Ptr KeyPair96
-> Ptr CUChar
-> IO CInt
secp256k1_schnorrsig_sign32 Ptr Context
tex Ptr Sig64
out Ptr MsgHash32
has Ptr KeyPair96
pur Ptr CUChar
enn
            Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CInt
suc CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
/= CInt
1) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Secp256k1Exception -> IO ()
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
Secp256k1Error
            let enc :: Ptr b
enc = Ptr Sig64 -> Ptr b
forall a b. Ptr a -> Ptr b
F.castPtr Ptr Sig64
out
            CStringLen -> IO ByteString
BS.packCStringLen (CString
forall {b}. Ptr b
enc, Int
_SIG_BYTES)

-- | Verify a 64-byte Schnorr signature for the provided 32-byte message
--   hash with the supplied public key.
--
--   >>> wrcontext entropy $ \tex -> verify_schnorr tex pub msg sig
verify_schnorr
  :: Context
  -> Pub
  -> BS.ByteString -- ^ 32-byte message hash
  -> BS.ByteString -- ^ 64-byte signature
  -> IO Bool
verify_schnorr :: Context -> Pub -> ByteString -> ByteString -> IO Bool
verify_schnorr c :: Context
c@(Context Ptr Context
tex) Pub
pub ByteString
msg ByteString
sig
  | ByteString -> Int
BS.length ByteString
msg Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
32 Bool -> Bool -> Bool
|| ByteString -> Int
BS.length ByteString
sig Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
64 = Secp256k1Exception -> IO Bool
forall e a. Exception e => e -> IO a
throwIO Secp256k1Exception
CSecp256k1Error
  | Bool
otherwise =
    ByteString -> (CString -> IO Bool) -> IO Bool
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
sig ((CString -> IO Bool) -> IO Bool)
-> (CString -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr Sig64
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr Sig64
sip) ->
      ByteString -> (CStringLen -> IO Bool) -> IO Bool
forall a. ByteString -> (CStringLen -> IO a) -> IO a
BS.useAsCStringLen ByteString
msg ((CStringLen -> IO Bool) -> IO Bool)
-> (CStringLen -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr CUChar
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr CUChar
has, Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral -> CSize
len) -> do
        XOnlyPub ByteString
pux <- Context -> Pub -> IO XOnlyPub
xonly Context
c Pub
pub
        ByteString -> (CString -> IO Bool) -> IO Bool
forall a. ByteString -> (CString -> IO a) -> IO a
BS.useAsCString ByteString
pux ((CString -> IO Bool) -> IO Bool)
-> (CString -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \(CString -> Ptr XOnlyPublicKey64
forall a b. Ptr a -> Ptr b
F.castPtr -> Ptr XOnlyPublicKey64
pax) -> do
          CInt
suc <- Ptr Context
-> Ptr Sig64
-> Ptr CUChar
-> CSize
-> Ptr XOnlyPublicKey64
-> IO CInt
secp256k1_schnorrsig_verify Ptr Context
tex Ptr Sig64
sip Ptr CUChar
has CSize
len Ptr XOnlyPublicKey64
pax
          Bool -> IO Bool
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CInt
suc CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
1)