diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,9 @@
 # Changelog
 
+## 0.1.1 (2025-12-22)
+
+* Bump `ppad-secp256k1` to 0.5.0. More efficient and faster EC operations.
+
 ## 0.1.0 (2025-09-20)
 
-* Initial release, full BIP327 support except [Deterministic and Stateless Signing for a Single Signer](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki#user-content-Deterministic_and_Stateless_Signing_for_a_Single_Signer)
+* Initial release, full BIP-0327 support except [Deterministic and Stateless Signing for a Single Signer](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki#user-content-Deterministic_and_Stateless_Signing_for_a_Single_Signer)
diff --git a/lib/Crypto/Curve/Secp256k1/MuSig2.hs b/lib/Crypto/Curve/Secp256k1/MuSig2.hs
--- a/lib/Crypto/Curve/Secp256k1/MuSig2.hs
+++ b/lib/Crypto/Curve/Secp256k1/MuSig2.hs
@@ -37,8 +37,8 @@
 > let sec2 = MuSig2.SecKey 0x68E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF
 >
 > -- derive public keys
-> let pub1 = Secp256k1.derive_pub 0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF
-> let pub2 = Secp256k1.derive_pub 0x68E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF
+> let Just pub1 = Secp256k1.derive_pub 0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF
+> let Just pub2 = Secp256k1.derive_pub 0x68E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF
 > let pubkeys = [pub1, pub2]
 >
 > -- create key aggregation context
@@ -188,7 +188,7 @@
     -- gaccVal == 1 means no negation, gaccVal == n-1 means negation
     parityFromGacc = gaccVal /= 1
     d = if parityFromGacc /= oddAggPk then _CURVE_Q - d' else d'
-    p = derive_pub d' -- Use original secret key for public key derivation
+    p = fromMaybe (error "musig2 (sign): failed to derive public key") $ derive_pub d' -- Use original secret key for public key derivation
     a = computeKeyAggCoef p publicKeys
     -- if has_even_Y(R):
     --   k = k1 + b*k2
@@ -198,7 +198,9 @@
     b = getSigningNonceCoeff ctx
     k = if isEvenPub nonce then k1 + b * k2 else _CURVE_Q - (k1 + b * k2)
     s = modQ (k + e * a * d)
-    pubNonce' = PubNonce (mul _CURVE_G secnonce.k1) (mul _CURVE_G secnonce.k2)
+    r1' = fromMaybe (error "musig2 (sign): failed to compute r1") $ mul _CURVE_G secnonce.k1
+    r2' = fromMaybe (error "musig2 (sign): failed to compute r2") $ mul _CURVE_G secnonce.k2
+    pubNonce' = PubNonce r1' r2'
    in
     if partialSigVerifyInternal s pubNonce' p ctx then s else error "musig2 (sign): could not verify partial signature against public nonce, public key and session context"
 
@@ -264,7 +266,8 @@
     finalNonce = getSigningNonce ctx -- This is the final aggregate nonce used for evenness check
     s = if partial < 0 || partial >= _CURVE_Q then error "musig2 (partialSigVerifyInternal): partial signature must be within curve order." else partial
     -- Reconstruct the individual's effective nonce: R_s1 + b * R_s2
-    re' = add r1' $ mul r2' b
+    r2b = fromMaybe (error "musig2 (partialSigVerifyInternal): failed to compute r2 * b") $ mul r2' b
+    re' = add r1' r2b
     -- Negate individual nonce if final aggregate nonce has odd Y
     re = if isEvenPub finalNonce then re' else neg re'
     a = computeKeyAggCoef pk publicKeys
@@ -272,8 +275,9 @@
     g = if oddAggPk then _CURVE_Q - 1 else 1
     -- Apply parity accumulator: gacc is accumulated parity factor
     g' = modQ (g * gaccVal)
-    sG = mul _CURVE_G s
-    sG' = re `add` mul pk (modQ (e * a * g'))
+    sG = fromMaybe (error "musig2 (partialSigVerifyInternal): failed to compute s * G") $ mul _CURVE_G s
+    pkMul = fromMaybe (error "musig2 (partialSigVerifyInternal): failed to compute pk multiplication") $ mul pk (modQ (e * a * g'))
+    sG' = re `add` pkMul
    in
     sG == sG'
 
@@ -394,7 +398,7 @@
   checkOrder = (>= _CURVE_Q) . getTweak
 
 {- | Gets the signing nonce as a 'Projective' following
-[BIP327 algorithm and recommendations](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki#dealing-with-infinity-in-nonce-aggregation).
+[BIP-0327 algorithm and recommendations](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki#dealing-with-infinity-in-nonce-aggregation).
 -}
 getSigningNonce :: SessionContext -> Projective
 getSigningNonce ctx =
@@ -402,12 +406,13 @@
     b = getSigningNonceCoeff ctx
     aggNonce = ctx.aggNonce
     aggNonce' = if aggNonce.r1 == _CURVE_ZERO then PubNonce _CURVE_G aggNonce.r2 else aggNonce
-    finalNonce = add aggNonce'.r1 (mul aggNonce'.r2 b)
+    r2b = fromMaybe (error "musig2 (getSigningNonce): failed to compute r2 * b") $ mul aggNonce'.r2 b
+    finalNonce = add aggNonce'.r1 r2b
    in
     if finalNonce == _CURVE_ZERO then _CURVE_G else finalNonce
 
 {- | Gets the signing nonce coefficient following
-[BIP327 algorithm and recommendations](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki#dealing-with-infinity-in-nonce-aggregation).
+[BIP-0327 algorithm and recommendations](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki#dealing-with-infinity-in-nonce-aggregation).
 -}
 getSigningNonceCoeff :: SessionContext -> Integer
 getSigningNonceCoeff ctx =
@@ -428,11 +433,11 @@
     bytesToInteger $ hashTagModQ "MuSig/noncecoef" preimage
 
 {- | Gets the signing challenge hash as a 'ByteString' following
-[BIP327 algorithm](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki).
+[BIP-0327 algorithm](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki).
 
 Note that the signing challenge hash is the naming convention from the
 [MuSig2 paper, page 6](https://eprint.iacr.org/2020/1261).
-In the BIP327 it is referred as @e@.
+In the BIP-0327 it is referred as @e@.
 -}
 getSigningHash :: SessionContext -> ByteString
 getSigningHash ctx =
@@ -453,11 +458,13 @@
 
 -- | Tweak that can be added to an aggregated 'Pub'key.
 data Tweak
-  = -- | X-only tweak required by Taproot tweaking to add script paths to a Taproot output.
-    -- See [BIP341](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki).
+  = {- | X-only tweak required by Taproot tweaking to add script paths to a Taproot output.
+    See [BIP341](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki).
+    -}
     XOnlyTweak !Integer
-  | -- | Plain tweak that can be used to derive child aggregated 'Pub'keys per
-    -- [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)
+  | {- | Plain tweak that can be used to derive child aggregated 'Pub'keys per
+    [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki)
+    -}
     PlainTweak !Integer
   deriving (Read, Show, Eq, Ord, Generic)
 
@@ -466,7 +473,7 @@
 getTweak (XOnlyTweak int) = int
 getTweak (PlainTweak int) = int
 
--- | Applies a tweak to a KeyAggContext and returns a new KeyAggContext following [BIP327](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki).
+-- | Applies a tweak to a KeyAggContext and returns a new KeyAggContext following [BIP-0327](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki).
 applyTweak :: KeyAggContext -> Tweak -> KeyAggContext
 applyTweak ctx newTweak =
   let pubkey = q ctx
@@ -477,7 +484,9 @@
         PlainTweak t ->
           -- Plain tweak: g = 1, Q' = g*Q + t*G, tacc' = t + g*tacc, gacc' = g*gacc
           let g = 1
-              tweakedPk = add (mul pubkey g) (mul _CURVE_G t)
+              pubkeyMul = fromMaybe (error "musig2 (applyTweak): failed to compute pubkey * g") $ mul pubkey g
+              tG = fromMaybe (error "musig2 (applyTweak): failed to compute t * G") $ mul _CURVE_G t
+              tweakedPk = add pubkeyMul tG
               newAccTweak = modQ (t + (g * accTweakVal))
               newGacc = modQ (g * gaccIn)
            in if tweakedPk == _CURVE_ZERO
@@ -486,7 +495,9 @@
         XOnlyTweak t ->
           -- X-only tweak: g = 1 if even Y, g = n-1 if odd Y, tacc' = t + g*tacc
           let g = if isEvenPub pubkey then 1 else _CURVE_Q - 1
-              tweakedPk = add (mul pubkey g) (mul _CURVE_G t)
+              pubkeyMul = fromMaybe (error "musig2 (applyTweak): failed to compute pubkey * g") $ mul pubkey g
+              tG = fromMaybe (error "musig2 (applyTweak): failed to compute t * G") $ mul _CURVE_G t
+              tweakedPk = add pubkeyMul tG
               newAccTweak = modQ (t + (g * accTweakVal))
               newGacc = modQ (g * gaccIn)
            in if tweakedPk == _CURVE_ZERO
@@ -523,7 +534,7 @@
 compute the private key used to create both signatures.
 
 If you want to follow
-[BIP327](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki)
+[BIP-0327](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki)
 suggestions, then use 'secNonceGen' otherwise use 'mkSecNonce'.
 -}
 data SecNonce = SecNonce
@@ -544,7 +555,7 @@
 this function.
 
 Note that this does not follow the
-[BIP327](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki)
+[BIP-0327](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki)
 algorithm.
 -}
 mkSecNonce :: IO SecNonce
@@ -581,7 +592,16 @@
     }
 
 {- | Generates a 'SecNonce' using the inputs and algorithms from
-[BIP327](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki).
+[BIP-0327](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki).
+
+Tries to get the entropy from the system's underlying Cryptographic Secure
+Pseudorandom Number Generator (CSPRNG) using the
+[@entropy@](https://hackage.haskell.org/package/entropy) package.
+
+== WARNING
+
+Make sure that you have access to a good CSPRNG in your system before calling
+this function.
 -}
 secNonceGen :: SecNonceGenParams -> IO SecNonce
 secNonceGen params = loop
@@ -596,7 +616,7 @@
 
 {- | Generates a 'SecNonce' using a given random 'ByteString' and the inputs and
 algorithms from
-[BIP327](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki).
+[BIP-0327](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki).
 
 == WARNING
 
@@ -664,7 +684,10 @@
 
 -- | Generates a 'PubNonce' from a 'SecNonce'.
 publicNonce :: SecNonce -> PubNonce
-publicNonce secNonce = PubNonce (mul _CURVE_G (k1 secNonce)) (mul _CURVE_G (k2 secNonce))
+publicNonce secNonce =
+  let r1' = fromMaybe (error "musig2 (publicNonce): failed to compute r1") $ mul _CURVE_G (k1 secNonce)
+      r2' = fromMaybe (error "musig2 (publicNonce): failed to compute r2") $ mul _CURVE_G (k2 secNonce)
+   in PubNonce r1' r2'
 
 -- | 'Data.Semigroup' implementation of 'PubNonce' for algebraic sound combination of public nonces.
 instance Semigroup PubNonce where
@@ -680,7 +703,7 @@
   mempty = PubNonce _CURVE_ZERO _CURVE_ZERO
 
 {- | Aggregates a 'Traversable' of 'PubNonce's using the
-[Nonce Aggregation algorithm in BIP327](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki).
+[Nonce Aggregation algorithm in BIP-0327](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki).
 -}
 aggNonces :: (Traversable t) => t PubNonce -> Maybe PubNonce
 aggNonces nonces
diff --git a/lib/Crypto/Curve/Secp256k1/MuSig2/Internal.hs b/lib/Crypto/Curve/Secp256k1/MuSig2/Internal.hs
--- a/lib/Crypto/Curve/Secp256k1/MuSig2/Internal.hs
+++ b/lib/Crypto/Curve/Secp256k1/MuSig2/Internal.hs
@@ -44,7 +44,7 @@
 import Data.Traversable ()
 
 {- | Aggregates a 'Traversable' of 'Pub'keys using the
-[Key Aggregation algorithm in BIP327](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki).
+[Key Aggregation algorithm in BIP-0327](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki).
 
 The algorith can be briefly described as
 
@@ -63,7 +63,9 @@
 aggPublicKeys :: (Traversable t) => t Pub -> Maybe Pub
 aggPublicKeys pks
   | Seq.null pksSeq = Nothing
-  | otherwise = Just $ fold1WithDefault _CURVE_ZERO (Seq.zipWith aggPk coefs pksSeq)
+  | otherwise = do
+      mulResults <- traverse (uncurry aggPk) (Seq.zip coefs pksSeq)
+      pure $ fold1WithDefault _CURVE_ZERO mulResults
  where
   pksSeq = Seq.fromList (toList pks)
   coefs = fmap (`computeKeyAggCoef` pksSeq) pksSeq
@@ -104,7 +106,7 @@
  where
   byteStrings = fmap serialize_point ps
 
-{- | Tagged hashes used in [BIP327](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki).
+{- | Tagged hashes used in [BIP-0327](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki).
 
 Takes a tag and a string.
 -}
@@ -113,7 +115,7 @@
  where
   taggedHash = hash t
 
-{- | Tagged hashes used in [BIP327](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki)
+{- | Tagged hashes used in [BIP-0327](https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki)
 modulo the curve order.
 
 Takes a tag and a string.
diff --git a/musig2.cabal b/musig2.cabal
--- a/musig2.cabal
+++ b/musig2.cabal
@@ -1,6 +1,6 @@
 cabal-version:   3.0
 name:            musig2
-version:         0.1.0
+version:         0.1.1
 synopsis:        MuSig2 library
 license:         MIT
 license-file:    LICENSE
@@ -9,7 +9,7 @@
 homepage:        https://github.com/storopoli/musig2
 category:        Cryptography
 build-type:      Simple
-tested-with:     GHC ==9.8.4
+tested-with:     GHC ==9.8.4 || ==9.10.3
 extra-doc-files: CHANGELOG
 description:
   Pure BIP0327 MuSig2 (partial)signatures with tweak support on the elliptic curve secp256k1.
@@ -31,7 +31,7 @@
     , bytestring         >=0.9  && <0.13
     , containers         >=0.6  && <0.9
     , entropy            >=0.4  && <0.5
-    , ppad-secp256k1     >=0.3  && <0.5
+    , ppad-secp256k1     >=0.3  && <0.6
     , ppad-sha256        >=0.2  && <0.3.0
 
 test-suite musig2-tests
diff --git a/test/AggNonces.hs b/test/AggNonces.hs
--- a/test/AggNonces.hs
+++ b/test/AggNonces.hs
@@ -9,7 +9,7 @@
 import Test.Tasty.HUnit
 import Util (parsePoint, parsePubNonce)
 
--- | Input 'PubNonce's from BIP327 test vectors
+-- | Input 'PubNonce's from BIP-0327 test vectors
 inputPubNonces :: [PubNonce]
 inputPubNonces =
   map
@@ -31,13 +31,13 @@
 -- | Creates test case from vector data.
 makeTestCase :: Int -> ([Int], PubNonce) -> TestTree
 makeTestCase i (indices, expected) =
-  testCase ("BIP327 test vector " <> show (i + 1)) $
+  testCase ("BIP-0327 test vector " <> show (i + 1)) $
     fromJust aggNonce @=? expected
  where
   selectedNonces = map (inputPubNonces !!) indices
   aggNonce = aggNonces selectedNonces
 
--- | Test vectors from [BIP327 `nonce_agg_vectors.json`](https://github.com/bitcoin/bips/blob/master/bip-0327/vectors/nonce_agg_vectors.json).
+-- | Test vectors from [BIP-0327 `nonce_agg_vectors.json`](https://github.com/bitcoin/bips/blob/master/bip-0327/vectors/nonce_agg_vectors.json).
 testAggNonces :: TestTree
 testAggNonces =
   testGroup "aggregating pubkeys" $
diff --git a/test/AggPartials.hs b/test/AggPartials.hs
--- a/test/AggPartials.hs
+++ b/test/AggPartials.hs
@@ -24,7 +24,7 @@
   }
   deriving (Show)
 
--- | Global test data from BIP327 sig_agg_vectors.json
+-- | Global test data from BIP-0327 @sig_agg_vectors.json@
 pubkeys :: [Pub]
 pubkeys =
   [ parsePoint "03935F972DA013F80AE011890FA89B67A27B7BE6CCB24D3274D18B2D4067F261A9"
@@ -43,7 +43,7 @@
   , parsePubNonce "02D97DDA5988461DF58C5897444F116A7C74E5711BF77A9446E27806563F3B6C47020CBAD9C363A7737F99FA06B6BE093CEAFF5397316C5AC46915C43767AE867C00"
   ]
 
--- | Raw tweak values from BIP327 test vectors
+-- | Raw tweak values from BIP-0327 test vectors
 tweakValues :: [Integer]
 tweakValues =
   [ parseScalar "B511DA492182A91B0FFB9A98020D55F260AE86D7ECBD0399C7383D59A5F2AF7C"
@@ -67,7 +67,7 @@
 msg :: ByteString
 msg = decodeHex "599C67EA410D005B9DA90817CF03ED3B1C868E4DA4EDF00A5880B0082C237869"
 
--- | Test vectors - valid cases from BIP327 JSON
+-- | Test vectors - valid cases from BIP-0327 JSON
 validTestVectors :: [SigAggTestVector]
 validTestVectors =
   [ SigAggTestVector
@@ -112,7 +112,7 @@
       }
   ]
 
--- | Test vectors - error cases from BIP327 JSON
+-- | Test vectors - error cases from BIP-0327 JSON
 errorTestVectors :: [SigAggTestVector]
 errorTestVectors =
   [ SigAggTestVector
@@ -138,7 +138,7 @@
 -- | Creates a test case for valid signature aggregation.
 makeValidTestCase :: Int -> SigAggTestVector -> TestTree
 makeValidTestCase i SigAggTestVector{..} =
-  testCase ("BIP327 SigAgg Valid Vector " ++ show (i + 1)) $ do
+  testCase ("BIP-0327 SigAgg Valid Vector " ++ show (i + 1)) $ do
     let selectedKeys = map (pubkeys !!) keyIndices
     let selectedTweaks = buildTweaks tweakIndices isXOnly
     let selectedPsigs = map (psigs !!) psigIndices
@@ -151,7 +151,7 @@
 -- | Creates a test case for error signature aggregation.
 makeErrorTestCase :: Int -> SigAggTestVector -> TestTree
 makeErrorTestCase i SigAggTestVector{..} =
-  testCase ("BIP327 SigAgg Error Vector " ++ show (i + 1)) $ do
+  testCase ("BIP-0327 SigAgg Error Vector " ++ show (i + 1)) $ do
     -- For the error case, we expect aggPartials to fail due to invalid partial signature
     -- The test vector has psig[8] which is FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
     -- This exceeds the curve order and should cause validation to fail
@@ -161,7 +161,7 @@
 testAggPartials :: TestTree
 testAggPartials =
   testGroup
-    "BIP327 Signature Aggregation Vectors"
+    "BIP-0327 Signature Aggregation Vectors"
     [ testGroup "Valid Cases" $ zipWith makeValidTestCase [0 ..] validTestVectors
     , testGroup "Error Cases" $ zipWith makeErrorTestCase [0 ..] errorTestVectors
     ]
diff --git a/test/AggPartialsProperty.hs b/test/AggPartialsProperty.hs
--- a/test/AggPartialsProperty.hs
+++ b/test/AggPartialsProperty.hs
@@ -6,7 +6,7 @@
 import Crypto.Curve.Secp256k1.MuSig2 (SecKey (..), SecNonce (..), aggNonces, aggPartials, mkSessionContext, partialSigVerify, publicNonce, sign)
 import Data.ByteString (ByteString)
 import qualified Data.ByteString as BS
-import Data.Maybe (fromJust)
+import Data.Maybe (fromJust, fromMaybe)
 import Test.Tasty
 import Test.Tasty.QuickCheck as QC
 import Util ()
@@ -24,8 +24,8 @@
 -- | Property: Aggregating valid partial signatures produces a consistent result
 prop_aggValidPartials :: SecNonce -> SecKey -> SecNonce -> SecKey -> ByteString -> Property
 prop_aggValidPartials secNonce1 secKey1 secNonce2 secKey2 msg =
-  let pubkey1 = derive_pub (case secKey1 of SecKey sk -> sk)
-      pubkey2 = derive_pub (case secKey2 of SecKey sk -> sk)
+  let pubkey1 = fromMaybe (error "Failed to derive pubkey1") $ derive_pub (case secKey1 of SecKey sk -> sk)
+      pubkey2 = fromMaybe (error "Failed to derive pubkey2") $ derive_pub (case secKey2 of SecKey sk -> sk)
       pubkeys = [pubkey1, pubkey2]
       pubNonces = [publicNonce secNonce1, publicNonce secNonce2]
       aggNonce = fromJust $ aggNonces pubNonces
@@ -38,8 +38,8 @@
 -- | Property: Aggregation is deterministic - same inputs produce same output
 prop_aggDeterministic :: SecNonce -> SecKey -> SecNonce -> SecKey -> ByteString -> Property
 prop_aggDeterministic secNonce1 secKey1 secNonce2 secKey2 msg =
-  let pubkey1 = derive_pub (case secKey1 of SecKey sk -> sk)
-      pubkey2 = derive_pub (case secKey2 of SecKey sk -> sk)
+  let pubkey1 = fromMaybe (error "Failed to derive pubkey1") $ derive_pub (case secKey1 of SecKey sk -> sk)
+      pubkey2 = fromMaybe (error "Failed to derive pubkey2") $ derive_pub (case secKey2 of SecKey sk -> sk)
       pubkeys = [pubkey1, pubkey2]
       pubNonces = [publicNonce secNonce1, publicNonce secNonce2]
       aggNonce = fromJust $ aggNonces pubNonces
@@ -54,8 +54,8 @@
 -- | Property: All partial signatures should verify individually before aggregation
 prop_partialsVerifyBeforeAgg :: SecNonce -> SecKey -> SecNonce -> SecKey -> ByteString -> Property
 prop_partialsVerifyBeforeAgg secNonce1 secKey1 secNonce2 secKey2 msg =
-  let pubkey1 = derive_pub (case secKey1 of SecKey sk -> sk)
-      pubkey2 = derive_pub (case secKey2 of SecKey sk -> sk)
+  let pubkey1 = fromMaybe (error "Failed to derive pubkey1") $ derive_pub (case secKey1 of SecKey sk -> sk)
+      pubkey2 = fromMaybe (error "Failed to derive pubkey2") $ derive_pub (case secKey2 of SecKey sk -> sk)
       pubkeys = [pubkey1, pubkey2]
       pubNonces = [publicNonce secNonce1, publicNonce secNonce2]
       aggNonce = fromJust $ aggNonces pubNonces
@@ -69,7 +69,7 @@
 -- | Property: For a single signer, aggregation should work correctly
 prop_singleSignerAgg :: SecNonce -> SecKey -> ByteString -> Property
 prop_singleSignerAgg secNonce secKey@(SecKey sk) msg =
-  let pubkey = derive_pub sk
+  let pubkey = fromMaybe (error "Failed to derive pubkey") $ derive_pub sk
       pubNonce = publicNonce secNonce
       pubNonces = [pubNonce]
       pubkeys = [pubkey]
diff --git a/test/AggPubkeys.hs b/test/AggPubkeys.hs
--- a/test/AggPubkeys.hs
+++ b/test/AggPubkeys.hs
@@ -10,7 +10,7 @@
 import Test.Tasty.HUnit
 import Util (decodeHex, extractXOnly, parsePoint)
 
--- | Input public keys from BIP327 test vectors
+-- | Input public keys from BIP-0327 test vectors
 inputPubkeys :: [Pub]
 inputPubkeys =
   map
@@ -33,7 +33,7 @@
   , ([0, 0, 1, 1], decodeHex "69BC22BFA5D106306E48A20679DE1D7389386124D07571D0D872686028C26A3E")
   ]
 
--- | Tweak test vectors from BIP327.
+-- | Tweak test vectors from BIP-0327.
 tweaks :: [Integer]
 tweaks =
   [ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 -- curve order (invalid)
@@ -50,7 +50,7 @@
 -- | Creates test case from vector data.
 makeTestCase :: Int -> ([Int], ByteString) -> TestTree
 makeTestCase i (indices, expected) =
-  testCase ("BIP327 test vector " <> show (i + 1)) $
+  testCase ("BIP-0327 test vector " <> show (i + 1)) $
     extractXOnly aggPk @=? expected
  where
   selectedKeys = map (inputPubkeys !!) indices
@@ -60,7 +60,7 @@
 -- | Creates error test case from vector data.
 makeErrorTestCase :: Int -> ([Int], Int, Bool, String) -> TestTree
 makeErrorTestCase i (keyIndices, tweakIndex, isXOnly, expectedMsg) =
-  testCase ("BIP327 error test vector " <> show (i + 1)) $ do
+  testCase ("BIP-0327 error test vector " <> show (i + 1)) $ do
     result <- try $ evaluate $ mkKeyAggContext selectedKeys (Just tweak)
     case result of
       Left (ErrorCall msg) -> assertBool ("Expected '" <> expectedMsg <> "' in error message, got: " <> msg) (expectedMsg `isSubsequenceOf` msg)
@@ -77,7 +77,7 @@
     | x == y = isSubsequenceOf xs ys
     | otherwise = isSubsequenceOf (x : xs) ys
 
--- | Test vectors from [BIP327 `key_agg_vectors.json`](https://github.com/bitcoin/bips/blob/master/bip-0327/vectors/key_agg_vectors.json).
+-- | Test vectors from [BIP-0327 `key_agg_vectors.json`](https://github.com/bitcoin/bips/blob/master/bip-0327/vectors/key_agg_vectors.json).
 testAggPubkeys :: TestTree
 testAggPubkeys =
   testGroup "aggregating pubkeys" $
diff --git a/test/NonceGen.hs b/test/NonceGen.hs
--- a/test/NonceGen.hs
+++ b/test/NonceGen.hs
@@ -26,7 +26,7 @@
   , expected_r2 :: Pub
   }
 
--- | Hardcoded test vectors from bip-0327/vectors/nonce_gen_vectors.json.
+-- | Hardcoded test vectors from @bip-0327/vectors/nonce_gen_vectors.json@.
 testVectors :: [NonceGenTestVector]
 testVectors =
   [ NonceGenTestVector
@@ -82,7 +82,7 @@
 -- | Creates a test case from a test vector.
 makeNonceGenTestCase :: Int -> NonceGenTestVector -> TestTree
 makeNonceGenTestCase i NonceGenTestVector{..} =
-  testCase ("BIP327 NonceGen Vector " ++ show (i + 1)) $ do
+  testCase ("BIP-0327 NonceGen Vector " ++ show (i + 1)) $ do
     let params =
           SecNonceGenParams
             { _pk = pk
@@ -101,5 +101,5 @@
 -- | Main test group for NonceGen.
 testNonceGen :: TestTree
 testNonceGen =
-  testGroup "BIP327 NonceGen Vectors" $
+  testGroup "BIP-0327 NonceGen Vectors" $
     zipWith makeNonceGenTestCase [0 ..] testVectors
diff --git a/test/NonceGenProperty.hs b/test/NonceGenProperty.hs
--- a/test/NonceGenProperty.hs
+++ b/test/NonceGenProperty.hs
@@ -7,6 +7,7 @@
 import Crypto.Curve.Secp256k1.MuSig2 (PubNonce (..), SecKey (..), SecNonce (..), SecNonceGenParams (..), publicNonce, secNonceGenWithRand)
 import Crypto.Curve.Secp256k1.MuSig2.Internal (hashTag, integerToBytes32, xorByteStrings)
 import Data.ByteString ()
+import Data.Maybe (fromMaybe)
 import Test.Tasty
 import Test.Tasty.QuickCheck as QC
 import Util (Rand32 (..), Scalar (..))
@@ -31,7 +32,7 @@
 prop_correctPubNonce (Rand32 rand) params =
   let sn@SecNonce{..} = secNonceGenWithRand rand params
       PubNonce r1 r2 = publicNonce sn
-   in r1 === mul _CURVE_G k1 .&&. r2 === mul _CURVE_G k2
+   in r1 === fromMaybe (error "Failed to multiply scalar by generator") (mul _CURVE_G k1) .&&. r2 === fromMaybe (error "Failed to multiply scalar by generator") (mul _CURVE_G k2)
 
 -- | Property: Generating with sk provided is equivalent to XORing rand with the aux hash and generating without sk
 prop_skConsistency :: Rand32 -> SecNonceGenParams -> Scalar -> Property
diff --git a/test/ParityPub.hs b/test/ParityPub.hs
--- a/test/ParityPub.hs
+++ b/test/ParityPub.hs
@@ -7,7 +7,7 @@
 import Test.Tasty.HUnit
 import Util (parsePoint)
 
--- | Some examples from [BIP327 test vectors](https://github.com/bitcoin/bips/tree/master/bip-0327/vectors).
+-- | Some examples from [BIP-0327 test vectors](https://github.com/bitcoin/bips/tree/master/bip-0327/vectors).
 testParityPub :: TestTree
 testParityPub =
   testGroup
diff --git a/test/SignVerify.hs b/test/SignVerify.hs
--- a/test/SignVerify.hs
+++ b/test/SignVerify.hs
@@ -14,7 +14,7 @@
 import Test.Tasty.HUnit
 import Util (decodeHex, parsePoint, parsePubNonce)
 
--- | Input public keys from BIP327 test vectors
+-- | Input public keys from BIP-0327 test vectors.
 inputPubkeys :: [Pub]
 inputPubkeys =
   map
@@ -25,7 +25,7 @@
     , "020000000000000000000000000000000000000000000000000000000000000007"
     ]
 
--- | Public nonces from BIP327 test vectors
+-- | Public nonces from BIP-0327 test vectors.
 inputPubNonces :: [PubNonce]
 inputPubNonces =
   map
@@ -37,7 +37,7 @@
     , "0200000000000000000000000000000000000000000000000000000000000000090287BF891D2A6DEAEBADC909352AA9405D1428C15F4B75F04DAE642A95C2548480"
     ]
 
--- | Messages from BIP327 test vectors
+-- | Messages from BIP-0327 test vectors.
 testMessages :: [ByteString]
 testMessages =
   [ decodeHex "F95466D086770E689964664219266FE5ED215C92AE20BAB5C9D79ADDDDF3C0CF"
@@ -70,31 +70,31 @@
   , (decodeHex "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", [0, 1, 2], [0, 1, 2], 0, 0, "Signature exceeds group size")
   ]
 
--- | Valid secret key from BIP327 test vectors
+-- | Valid secret key from BIP-0327 test vectors.
 testSecKey :: SecKey
 testSecKey = SecKey $ bytesToInteger $ decodeHex "7FB9E0E687ADA1EEBF7ECFE2F21E73EBDB51A7D450948DFE8D76D7F2D1007671"
 
--- | Invalid secret nonce with k1 = 0 (from BIP327 test vectors secnonce index 1)
+-- | Invalid secret nonce with k1 = 0 (from BIP-0327 test vectors secnonce index 1)
 invalidSecNonce :: SecNonce
 invalidSecNonce = SecNonce{k1 = 0, k2 = 0}
 
--- | Creates test case from valid test vector data
+-- | Creates test case from valid test vector data.
 makeValidTestCase :: Int -> ([Int], [Int], Int, Int, ByteString) -> TestTree
 makeValidTestCase i (keyIndices, nonceIndices, msgIndex, signerIndex, expectedSig) =
-  testCase ("BIP327 valid test vector " <> show (i + 1)) $ do
+  testCase ("BIP-0327 valid test vector " <> show (i + 1)) $ do
     let selectedKeys = map (inputPubkeys !!) keyIndices
         selectedNonces = map (inputPubNonces !!) nonceIndices
         msg = testMessages !! msgIndex
         signature = bytesToInteger expectedSig
 
-    -- Test that the valid signature verifies
+    -- Test that the valid signature verifies.
     let result = partialSigVerify signature selectedNonces selectedKeys [] msg signerIndex
     assertBool "Valid signature should verify" result
 
--- | Creates test case from invalid test vector data
+-- | Creates test case from invalid test vector data.
 makeInvalidTestCase :: Int -> (ByteString, [Int], [Int], Int, Int, String) -> TestTree
 makeInvalidTestCase i (sigBytes, keyIndices, nonceIndices, msgIndex, signerIndex, comment) =
-  testCase ("BIP327 invalid test vector " <> show (i + 1) <> ": " <> comment) $ do
+  testCase ("BIP-0327 invalid test vector " <> show (i + 1) <> ": " <> comment) $ do
     let selectedKeys = map (inputPubkeys !!) keyIndices
         selectedNonces = map (inputPubNonces !!) nonceIndices
         msg = testMessages !! msgIndex
@@ -107,7 +107,7 @@
 -- | Creates test case from error test vector data
 makeErrorTestCase :: Int -> (ByteString, [Int], [Int], Int, Int, String) -> TestTree
 makeErrorTestCase i (sigBytes, keyIndices, nonceIndices, msgIndex, signerIndex, comment) =
-  testCase ("BIP327 error test vector " <> show (i + 1) <> ": " <> comment) $ do
+  testCase ("BIP-0327 error test vector " <> show (i + 1) <> ": " <> comment) $ do
     let selectedKeys = map (inputPubkeys !!) keyIndices
         selectedNonces = map (inputPubNonces !!) nonceIndices
         msg = testMessages !! msgIndex
@@ -119,10 +119,10 @@
       Left (ErrorCall _) -> return () -- Expected error
       Right _ -> assertFailure ("Expected error but verification succeeded: " <> comment)
 
--- | Test case for invalid secret nonce (k1 = 0) from BIP327 sign_error_test_cases
+-- | Test case for invalid secret nonce (k1 = 0) from BIP-0327 sign_error_test_cases
 testInvalidSecNonce :: TestTree
 testInvalidSecNonce =
-  testCase "BIP327 sign error: first secnonce value is out of range" $ do
+  testCase "BIP-0327 sign error: first secnonce value is out of range" $ do
     let selectedKeys = take 3 inputPubkeys -- [0, 1, 2]
         selectedNonces = take 3 inputPubNonces -- [0, 1, 2]
         msg = head testMessages -- msg_index 0
@@ -137,7 +137,7 @@
           ("first secret scalar k1 is zero" `isInfixOf` errMsg)
       Right _ -> assertFailure "Expected error but signing succeeded"
 
--- | Test vectors from [BIP327 `sign_verify_vectors.json`](https://github.com/bitcoin/bips/blob/master/bip-0327/vectors/sign_verify_vectors.json)
+-- | Test vectors from [BIP-0327 `sign_verify_vectors.json`](https://github.com/bitcoin/bips/blob/master/bip-0327/vectors/sign_verify_vectors.json)
 testSignVerify :: TestTree
 testSignVerify =
   testGroup "sign and verify" $
diff --git a/test/SignVerifyProperty.hs b/test/SignVerifyProperty.hs
--- a/test/SignVerifyProperty.hs
+++ b/test/SignVerifyProperty.hs
@@ -5,7 +5,7 @@
 import Crypto.Curve.Secp256k1 (derive_pub, _CURVE_Q)
 import Crypto.Curve.Secp256k1.MuSig2 (SecKey (..), SecNonce (..), aggNonces, mkSessionContext, partialSigVerify, publicNonce, sign)
 import Data.ByteString (ByteString)
-import Data.Maybe (fromJust)
+import Data.Maybe (fromJust, fromMaybe)
 import Test.Tasty
 import Test.Tasty.QuickCheck as QC
 import Util ()
@@ -23,7 +23,7 @@
 -- | Property: Generated signatures are in the valid range \([0, Q-1]\).
 prop_validSignatureRange :: SecNonce -> SecKey -> ByteString -> Property
 prop_validSignatureRange secNonce secKey@(SecKey sk) msg =
-  let pubkey = derive_pub sk
+  let pubkey = fromMaybe (error "Failed to derive pubkey") $ derive_pub sk
       pubNonce = publicNonce secNonce
       pubNonces = [pubNonce]
       pubkeys = [pubkey]
@@ -35,7 +35,7 @@
 -- | Property: A signature created with sign verifies with 'partialSigVerify'.
 prop_signVerifyRoundtrip :: SecNonce -> SecKey -> ByteString -> Property
 prop_signVerifyRoundtrip secNonce secKey@(SecKey sk) msg =
-  let pubkey = derive_pub sk
+  let pubkey = fromMaybe (error "Failed to derive pubkey") $ derive_pub sk
       pubNonce = publicNonce secNonce
       pubNonces = [pubNonce]
       pubkeys = [pubkey]
@@ -49,7 +49,7 @@
 -- | Property: Signing the same message with the same parameters produces the same signature.
 prop_signatureDeterminism :: SecNonce -> SecKey -> ByteString -> Property
 prop_signatureDeterminism secNonce secKey@(SecKey sk) msg =
-  let pubkey = derive_pub sk
+  let pubkey = fromMaybe (error "Failed to derive pubkey") $ derive_pub sk
       pubNonce = publicNonce secNonce
       pubNonces = [pubNonce]
       pubkeys = [pubkey]
@@ -62,7 +62,7 @@
 -- | Property: Using an invalid signer index should fail verification.
 prop_invalidSignerIndex :: SecNonce -> SecKey -> ByteString -> Property
 prop_invalidSignerIndex secNonce secKey@(SecKey sk) msg =
-  let pubkey = derive_pub sk
+  let pubkey = fromMaybe (error "Failed to derive pubkey") $ derive_pub sk
       pubNonce = publicNonce secNonce
       pubNonces = [pubNonce]
       pubkeys = [pubkey]
diff --git a/test/SignVerifyTweakProperty.hs b/test/SignVerifyTweakProperty.hs
--- a/test/SignVerifyTweakProperty.hs
+++ b/test/SignVerifyTweakProperty.hs
@@ -5,7 +5,7 @@
 import Crypto.Curve.Secp256k1 (derive_pub, _CURVE_Q)
 import Crypto.Curve.Secp256k1.MuSig2 (SecKey (..), SecNonce (..), Tweak (..), aggNonces, mkSessionContext, partialSigVerify, publicNonce, sign)
 import Data.ByteString (ByteString)
-import Data.Maybe (fromJust)
+import Data.Maybe (fromJust, fromMaybe)
 import Test.Tasty
 import Test.Tasty.QuickCheck
 import Util ()
@@ -26,7 +26,7 @@
 prop_validSignatureRangeWithTweaks secNonce secKey@(SecKey sk) =
   forAll (resize 5 $ listOf arbitrary) $ \tweaks ->
     forAll arbitrary $ \msg ->
-      let pubkey = derive_pub sk
+      let pubkey = fromMaybe (error "Failed to derive pubkey") $ derive_pub sk
           pubNonce = publicNonce secNonce
           pubNonces = [pubNonce]
           pubkeys = [pubkey]
@@ -40,7 +40,7 @@
 prop_signVerifyRoundtripWithTweaks secNonce secKey@(SecKey sk) =
   forAll (resize 5 $ listOf arbitrary) $ \tweaks ->
     forAll arbitrary $ \msg ->
-      let pubkey = derive_pub sk
+      let pubkey = fromMaybe (error "Failed to derive pubkey") $ derive_pub sk
           pubNonce = publicNonce secNonce
           pubNonces = [pubNonce]
           pubkeys = [pubkey]
@@ -56,7 +56,7 @@
 prop_signatureDeterminismWithTweaks secNonce secKey@(SecKey sk) =
   forAll (resize 5 $ listOf arbitrary) $ \tweaks ->
     forAll arbitrary $ \msg ->
-      let pubkey = derive_pub sk
+      let pubkey = fromMaybe (error "Failed to derive pubkey") $ derive_pub sk
           pubNonce = publicNonce secNonce
           pubNonces = [pubNonce]
           pubkeys = [pubkey]
@@ -69,7 +69,7 @@
 -- | Property: Empty tweaks should produce the same result as no tweaks.
 prop_emptyTweaksEqualsNoTweaks :: SecNonce -> SecKey -> ByteString -> Property
 prop_emptyTweaksEqualsNoTweaks secNonce secKey@(SecKey sk) msg =
-  let pubkey = derive_pub sk
+  let pubkey = fromMaybe (error "Failed to derive pubkey") $ derive_pub sk
       pubNonce = publicNonce secNonce
       pubNonces = [pubNonce]
       pubkeys = [pubkey]
@@ -93,7 +93,7 @@
     && t2 < _CURVE_Q
     && t1
       /= t2
-    ==> let pubkey = derive_pub sk
+    ==> let pubkey = fromMaybe (error "Failed to derive pubkey") $ derive_pub sk
             pubNonce = publicNonce secNonce
             pubNonces = [pubNonce]
             pubkeys = [pubkey]
diff --git a/test/SortPubkeys.hs b/test/SortPubkeys.hs
--- a/test/SortPubkeys.hs
+++ b/test/SortPubkeys.hs
@@ -35,9 +35,9 @@
       , "03DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659"
       ]
 
--- | Test vectors from [BIP327 `key_sort_vectors.json`](https://github.com/bitcoin/bips/blob/master/bip-0327/vectors/key_sort_vectors.json)
+-- | Test vectors from [BIP-0327 `key_sort_vectors.json`](https://github.com/bitcoin/bips/blob/master/bip-0327/vectors/key_sort_vectors.json)
 testSortPubkeys :: TestTree
 testSortPubkeys =
   testGroup
     "sorting pubkeys"
-    [testCase "BIP327 test vector" $ sortPublicKeys parsePoints @=? parsePointsSorted]
+    [testCase "BIP-0327 test vector" $ sortPublicKeys parsePoints @=? parsePointsSorted]
diff --git a/test/Tweak.hs b/test/Tweak.hs
--- a/test/Tweak.hs
+++ b/test/Tweak.hs
@@ -14,11 +14,11 @@
 import Test.Tasty.HUnit
 import Util (decodeHex, parsePoint, parsePubNonce, parseScalar)
 
--- | Secret key from BIP327 test vectors
+-- | Secret key from BIP-0327 test vectors.
 testSecKey :: SecKey
 testSecKey = SecKey $ parseScalar "7FB9E0E687ADA1EEBF7ECFE2F21E73EBDB51A7D450948DFE8D76D7F2D1007671"
 
--- | Secret nonce from BIP327 test vectors
+-- | Secret nonce from BIP-0327 test vectors.
 testSecNonce :: SecNonce
 testSecNonce =
   SecNonce
@@ -26,7 +26,7 @@
     , k2 = parseScalar "FA27FD49B1D50085B481285E1CA205D55C82CC1B31FF5CD54A489829355901F7"
     }
 
--- | Input public keys from BIP327 test vectors
+-- | Input public keys from BIP-0327 test vectors.
 inputPubkeys :: [Pub]
 inputPubkeys =
   map
@@ -36,7 +36,7 @@
     , "02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659"
     ]
 
--- | Public nonces from BIP327 test vectors
+-- | Public nonces from BIP-0327 test vectors.
 inputPubNonces :: [PubNonce]
 inputPubNonces =
   map
@@ -46,7 +46,7 @@
     , "032DE2662628C90B03F5E720284EB52FF7D71F4284F627B68A853D78C78E1FFE9303E4C5524E83FFE1493B9077CF1CA6BEB2090C93D930321071AD40B2F44E599046"
     ]
 
--- | Test tweaks from BIP327 test vectors
+-- | Test tweaks from BIP-0327 test vectors.
 testTweaks :: [Integer]
 testTweaks =
   map
@@ -58,11 +58,11 @@
     , "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"
     ]
 
--- | Test message from BIP327 test vectors
+-- | Test message from BIP-0327 test vectors.
 testMessage :: ByteString
 testMessage = decodeHex "F95466D086770E689964664219266FE5ED215C92AE20BAB5C9D79ADDDDF3C0CF"
 
--- | Valid test vector data: (key indices, nonce indices, tweak indices, is_xonly flags, signer index, expected signature, comment)
+-- | Valid test vector data: (key indices, nonce indices, tweak indices, is_xonly flags, signer index, expected signature, comment).
 validTestVectors :: [([Int], [Int], [Int], [Bool], Int, ByteString, String)]
 validTestVectors =
   [ ([1, 2, 0], [1, 2, 0], [0], [True], 2, decodeHex "E28A5C66E61E178C2BA19DB77B6CF9F7E2F0F56C17918CD13135E60CC848FE91", "A single x-only tweak")
@@ -72,13 +72,13 @@
   , ([1, 2, 0], [1, 2, 0], [0, 1, 2, 3], [True, False, True, False], 2, decodeHex "B255FDCAC27B40C7CE7848E2D3B7BF5EA0ED756DA81565AC804CCCA3E1D5D239", "Four tweaks: x-only, plain, x-only, plain. If an implementation prohibits applying plain tweaks after x-only tweaks, it can skip this test vector or return an error.")
   ]
 
--- | Error test vector data: (tweak indices, is_xonly flags, expected error message, comment)
+-- | Error test vector data: (tweak indices, is_xonly flags, expected error message, comment).
 errorTestVectors :: [([Int], [Bool], String, String)]
 errorTestVectors =
   [ ([4], [False], "tweaks must be less than curve order", "Tweak is invalid because it exceeds group size")
   ]
 
--- | Creates tweaks from indices and xonly flags
+-- | Creates tweaks from indices and xonly flags.
 createTweaks :: [Int] -> [Bool] -> [Tweak]
 createTweaks = zipWith createTweak
  where
@@ -86,10 +86,10 @@
     let tweakValue = testTweaks !! i
      in if isXOnly then XOnlyTweak tweakValue else PlainTweak tweakValue
 
--- | Creates test case from valid test vector data
+-- | Creates test case from valid test vector data.
 makeValidTestCase :: Int -> ([Int], [Int], [Int], [Bool], Int, ByteString, String) -> TestTree
 makeValidTestCase i (keyIndices, nonceIndices, tweakIndices, isXOnly, signerIndex, expectedSig, comment) =
-  testCase ("BIP327 valid test vector " <> show (i + 1) <> ": " <> comment) $ do
+  testCase ("BIP-0327 valid test vector " <> show (i + 1) <> ": " <> comment) $ do
     let selectedKeys = map (inputPubkeys !!) keyIndices
         selectedNonces = map (inputPubNonces !!) nonceIndices
         tweaks = createTweaks tweakIndices isXOnly
@@ -97,46 +97,46 @@
         aggNonce = fromJust $ aggNonces selectedNonces
         ctx = mkSessionContext aggNonce selectedKeys tweaks testMessage
 
-    -- Test 1: Generate signature using the sign function (with error handling)
+    -- Test 1: Generate signature using the sign function (with error handling).
     signResult <- try $ evaluate $ sign testSecNonce testSecKey ctx
     case signResult of
       Left (ErrorCall errMsg) -> do
-        -- If sign fails, this indicates a potential bug in the implementation
+        -- If sign fails, this indicates a potential bug in the implementation.
         assertFailure ("POTENTIAL BUG: Sign function failed: " <> errMsg <> " for test: " <> comment)
       Right generatedSig -> do
-        -- Test 2: Verify that the generated signature is valid
+        -- Test 2: Verify that the generated signature is valid.
         let generatedSigVerifies = partialSigVerify generatedSig selectedNonces selectedKeys tweaks testMessage signerIndex
         assertBool ("Generated signature should verify: " <> comment) generatedSigVerifies
 
-        -- Test 3: Check if the expected signature from BIP327 test vectors verifies
+        -- Test 3: Check if the expected signature from BIP-0327 test vectors verifies.
         let expectedSigVerifies = partialSigVerify expectedSignature selectedNonces selectedKeys tweaks testMessage signerIndex
 
-        -- Test 4: Compare generated signature with expected signature
-        -- Note: If they don't match, it could indicate a difference in implementation or test vector interpretation
+        -- Test 4: Compare generated signature with expected signature.
+        -- Note: If they don't match, it could indicate a difference in implementation or test vector interpretation.
         if expectedSigVerifies
           then do
-            -- If the expected signature verifies, we can compare it with our generated one
+            -- If the expected signature verifies, we can compare it with our generated one.
             if generatedSig == expectedSignature
               then assertBool ("Generated signature matches expected: " <> comment) True
               else do
-                -- They don't match - this could be due to different nonce generation or other implementation details
+                -- They don't match - this could be due to different nonce generation or other implementation details.
                 -- For now, we accept this as long as both signatures verify correctly
                 assertBool ("Different but valid signatures (implementation variation): " <> comment) True
           else do
-            -- Expected signature doesn't verify - this suggests our interpretation might be wrong
+            -- Expected signature doesn't verify - this suggests our interpretation might be wrong.
             -- But if our generated signature verifies, the core functionality works
             assertBool ("Expected signature from test vector doesn't verify, but generated signature does: " <> comment) generatedSigVerifies
 
--- | Creates test case from error test vector data
+-- | Creates test case from error test vector data.
 makeErrorTestCase :: Int -> ([Int], [Bool], String, String) -> TestTree
 makeErrorTestCase i (tweakIndices, isXOnly, expectedError, comment) =
-  testCase ("BIP327 error test vector " <> show (i + 1) <> ": " <> comment) $ do
+  testCase ("BIP-0327 error test vector " <> show (i + 1) <> ": " <> comment) $ do
     let selectedKeys = [inputPubkeys !! 1, inputPubkeys !! 2, head inputPubkeys] -- [1, 2, 0]
         selectedNonces = [inputPubNonces !! 1, inputPubNonces !! 2, head inputPubNonces] -- [1, 2, 0]
         tweaks = createTweaks tweakIndices isXOnly
         aggNonce = fromJust $ aggNonces selectedNonces
 
-    -- Test that creating a session context with invalid tweaks causes an error
+    -- Test that creating a session context with invalid tweaks causes an error.
     result <- try $ evaluate $ mkSessionContext aggNonce selectedKeys tweaks testMessage
     case result of
       Left (ErrorCall errMsg) ->
@@ -145,7 +145,7 @@
           (expectedError `isInfixOf` errMsg)
       Right _ -> assertFailure ("Expected error but session context creation succeeded: " <> comment)
 
--- | Test vectors from [BIP327 `tweak_vectors.json`](https://github.com/bitcoin/bips/blob/master/bip-0327/vectors/tweak_vectors.json)
+-- | Test vectors from [BIP-0327 `tweak_vectors.json`](https://github.com/bitcoin/bips/blob/master/bip-0327/vectors/tweak_vectors.json).
 testTweak :: TestTree
 testTweak =
   testGroup "tweak vectors" $
diff --git a/test/Util.hs b/test/Util.hs
--- a/test/Util.hs
+++ b/test/Util.hs
@@ -10,7 +10,7 @@
 import Data.ByteString (ByteString)
 import qualified Data.ByteString as BS
 import qualified Data.ByteString.Base16 as B16
-import Data.Maybe (fromJust)
+import Data.Maybe (fromJust, fromMaybe)
 import Test.Tasty.QuickCheck (Arbitrary (..), Gen, choose, frequency, vectorOf)
 
 {- | Parses a 'ByteString' into a 'Pub'key.
@@ -51,7 +51,7 @@
         ( 99
         , do
             scalar <- choose (0, _CURVE_Q)
-            return (mul _CURVE_G scalar)
+            return (fromMaybe (error "Failed to multiply scalar by generator") $ mul _CURVE_G scalar)
         )
       ]
 
@@ -166,7 +166,7 @@
 
 {- | Parses a 'ByteString' into a 'PubNonce'.
 
-Mostly used to parse BIP327 test vectors.
+Mostly used to parse BIP-0327 test vectors.
 -}
 parsePubNonce :: ByteString -> PubNonce
 parsePubNonce bs = PubNonce{r1 = r1', r2 = r2'}
