commit e7f61dd076cfb19baeec5c8929a3353a23a6e0a8
parent 6e7966341c1bc5fa1feb333570a05c97e34a6b7e
Author: Jared Tobin <jared@jtobin.io>
Date: Sun, 7 Jun 2026 17:31:52 -0230
lib: remove vestigial fake point in scalar mul
The original "soft" constant-time implementation of this function
included in early library versions relied on a fake/dummy accumulator
in order to perform a constant amount of work. When I later introduced
the stricter, fully-branchless constant time version, I kept the dummy
point around, but it's not actually necessary to do that. The branchless
constant-time select forces work on every iteration, so the dummy
accumulator doesn't actually do anything useful for us.
Removing it saves 14 field multiplications per iteration (~3.6k field
multiplications in total), shaving off about 50 microseconds from the
total time. The constant time semantics are unaffected.
Diffstat:
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/lib/Crypto/Curve/Secp256k1.hs b/lib/Crypto/Curve/Secp256k1.hs
@@ -567,18 +567,16 @@ mul# :: Proj -> Limb4 -> (# () | Proj #)
mul# (# px, py, pz #) s
| CT.decide (CT.not (ge# s)) = (# () | #)
| otherwise =
- let !(P gx gy gz) = _CURVE_G
- !(C.Montgomery o) = C.one
- in loop (0 :: Int) (# Z, o, Z #) (# gx, gy, gz #) (# px, py, pz #) s
+ let !(C.Montgomery o) = C.one
+ in loop (0 :: Int) (# Z, o, Z #) (# px, py, pz #) s
where
- loop !j !a !f !d !_SECRET
+ loop !j !a !d !_SECRET
| j == _CURVE_Q_BITS = (# | a #)
| otherwise =
let !nd = double# d
!(# nm, lsb_set #) = W.shr1_c# _SECRET
!nacc = select_proj# a (add_proj# a d) lsb_set
- !nf = select_proj# (add_proj# f d) f lsb_set
- in loop (succ j) nacc nf nd nm
+ in loop (succ j) nacc nd nm
{-# INLINE mul# #-}
mul_vartime# :: Proj -> Limb4 -> (# () | Proj #)