csecp256k1

Haskell FFI bindings to bitcoin-core/secp256k1.
git clone git://git.ppad.tech/csecp256k1.git
Log | Files | Refs | README | LICENSE

commit 170449937142108cad5ad16d88ec20f0e0706eab
parent 16396d6d51a96c45b1523d509f46acdd167f743d
Author: Jared Tobin <jared@jtobin.io>
Date:   Fri,  8 Mar 2024 17:00:16 +0400

bench: add benchmarks

Diffstat:
Abench/Main.hs | 48++++++++++++++++++++++++++++++++++++++++++++++++
Mflake.nix | 8+++++---
Mlib/Crypto/Secp256k1.hs | 7+++++++
Mppad-csecp256k1.cabal | 17++++++++++++++++-
4 files changed, 76 insertions(+), 4 deletions(-)

diff --git a/bench/Main.hs b/bench/Main.hs @@ -0,0 +1,48 @@ +{-# LANGUAGE OverloadedStrings #-} + +module Main where + +import Control.DeepSeq +import Criterion.Main +import qualified Crypto.Secp256k1 as S +import qualified Data.ByteString as BS + +instance NFData S.KeyPair +instance NFData S.Pub +instance NFData S.Sig +instance NFData S.XOnlyPub + +main :: IO () +main = defaultMain [ + sign + ] + +sign :: Benchmark +sign = bgroup "sign" [ + bench "sign" . nfIO $ sign_bench _HAS _SEC + , bench "sign_schnorr" . nfIO $ + sign_schnorr_bench _HAS _SEC (BS.replicate 32 0) + ] + where + sign_bench has sec = S.wcontext $ \tex -> + S.sign tex sec has + + sign_schnorr_bench has sec enn = S.wcontext $ \tex -> + S.sign_schnorr tex has sec enn + +-- inputs + +-- a 32-byte message hash +_HAS :: BS.ByteString +_HAS = mconcat [ + "\245\203\231\216\129\130\164\184\228\NUL\249k\ACK\DC2\137!\134J" + , "\CAN\CAN}\DC1L\138\232T\ESCVl\138\206\NUL" + ] + +-- a 32-byte secret key +_SEC :: BS.ByteString +_SEC = mconcat [ + "\246RU\tMws\237\141\212\ETB\186\220\159\192E\193\248\SI\220[-%\ETB" + , "+\ETX\FS\230\147>\ETX\154" + ] + diff --git a/flake.nix b/flake.nix @@ -29,13 +29,13 @@ # dependencies like secp256k1-sys, so enable it manually packages.${lib} = hlib.doHaddock hpkgs.${lib}; - defaultPackage = self.packages.${system}.${lib}; + packages."${lib}-bench" = hlib.doBenchmark hpkgs.${lib}; - hpkgs = hpkgs; + defaultPackage = self.packages.${system}.${lib}; devShells.default = hpkgs.shellFor { packages = p: [ - p.${lib} + (hlib.doBenchmark p.${lib}) ]; buildInputs = [ @@ -45,6 +45,8 @@ inputsFrom = builtins.attrValues self.packages.${system}; + doBenchmark = true; + shellHook = '' PS1="[${lib}] \w$ " echo "entering ${system} shell, using" diff --git a/lib/Crypto/Secp256k1.hs b/lib/Crypto/Secp256k1.hs @@ -1,3 +1,5 @@ +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ViewPatterns #-} @@ -56,6 +58,7 @@ import Control.Exception (Exception, bracket, throwIO) import Control.Monad (when) import Crypto.Secp256k1.Internal hiding (Context) import qualified Crypto.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) @@ -82,6 +85,7 @@ instance Show Context where -- 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 Generic instance Show Pub where show _ = "<bitcoin-core/secp256k1 public key>" @@ -94,6 +98,7 @@ instance Show Pub where -- 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 Generic instance Show XOnlyPub where show _ = "<bitcoin-core/secp256k1 x-only public key>" @@ -103,6 +108,7 @@ instance Show XOnlyPub where -- Create a value of this type by passing a secret key to -- 'keypair'. newtype KeyPair = KeyPair BS.ByteString + deriving stock Generic instance Show KeyPair where show _ = "<bitcoin-core/secp256k1 keypair>" @@ -112,6 +118,7 @@ instance Show KeyPair where -- Create a value of this type via 'sign', or parse a DER-encoded -- signature via 'parse_der'. newtype Sig = Sig BS.ByteString + deriving stock Generic instance Show Sig where show _ = "<bitcoin-core/secp256k1 signature>" diff --git a/ppad-csecp256k1.cabal b/ppad-csecp256k1.cabal @@ -95,8 +95,23 @@ test-suite csecp256k1-tests build-depends: base , bytestring - , entropy , ppad-csecp256k1 , tasty , tasty-hunit +benchmark csecp256k1-bench + type: exitcode-stdio-1.0 + default-language: Haskell2010 + hs-source-dirs: bench + main-is: Main.hs + + ghc-options: + -rtsopts -O2 -Wall + + build-depends: + base + , bytestring + , criterion + , deepseq + , ppad-csecp256k1 +