What changed, and why it matters
This commit is a performance optimization for Bitcoin's secp256k1 cryptographic library. It tells the compiler to always inline (embed directly into calling code) certain low-level multiplication and squaring routines used heavily in elliptic-curve operations. The stated goal is faster signature verification and key agreement, at the cost of slightly larger compiled binaries. There is no security fix or vulnerability indicated in the commit itself.
No security action required. Treat as a routine performance optimization. Reviewers may optionally verify that the new macro correctly falls back to plain inline in debug/MinSizeRel builds and that it does not trigger compiler warnings on supported toolchains.
Security signals we found
No security-relevant keywords in commit title or message
Change is purely compiler inlining directive and build-system guard
No modification to cryptographic algorithms, constants, or validation logic
No bounds-checking, memory-safety, or input-sanitization changes
No incident or disclosure references present in supplied materials
Evidence from the diff
The change introduces a new SECP256K1_FORCE_INLINE macro that maps to attribute((always_inline)) on GCC/Clang, forceinline on MSVC, or falls back to plain inline. It applies this macro to secp256k1_fe_impl_mul, secp256k1_fe_impl_sqr, and the int128-based inner helpers secp256k1_fe_mul_inner and secp256k1_fe_sqr_inner in the 5x52 field implementation. A CMake tweak defines __OPTIMIZE_SIZE=1 in MinSizeRel builds so the force-inline guard respects size-optimized configurations. The commit message frames this purely as a performance/code-size tradeoff with benchmark numbers; no security defect is mentioned.
Changed components
src/util.hsrc/field_5x52_impl.hsrc/field_5x52_int128_impl.hCMakeLists.txtInspect captured patch +17 / −4
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4ef69c0..a84305c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -147,6 +147,8 @@ if(MSVC)
string(REGEX REPLACE "/DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
string(REGEX REPLACE "/DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
string(REGEX REPLACE "/DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL}")
+ # Match GCC/Clang's size-optimization macro for the inline guard
+ add_compile_definitions($<$<CONFIG:MinSizeRel>:__OPTIMIZE_SIZE__=1>)
else()
string(REGEX REPLACE "-DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
string(REGEX REPLACE "-DNDEBUG[ \t\r\n]*" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
diff --git a/src/field_5x52_impl.h b/src/field_5x52_impl.h
index 3a97613..0e0e2d6 100644
--- a/src/field_5x52_impl.h
+++ b/src/field_5x52_impl.h
@@ -338,11 +338,11 @@ SECP256K1_INLINE static void secp256k1_fe_impl_add(secp256k1_fe *r, const secp25
r->n[4] += a->n[4];
}
-SECP256K1_INLINE static void secp256k1_fe_impl_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) {
+SECP256K1_FORCE_INLINE static void secp256k1_fe_impl_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) {
secp256k1_fe_mul_inner(r->n, a->n, b->n);
}
-SECP256K1_INLINE static void secp256k1_fe_impl_sqr(secp256k1_fe *r, const secp256k1_fe *a) {
+SECP256K1_FORCE_INLINE static void secp256k1_fe_impl_sqr(secp256k1_fe *r, const secp256k1_fe *a) {
secp256k1_fe_sqr_inner(r->n, a->n);
}
diff --git a/src/field_5x52_int128_impl.h b/src/field_5x52_int128_impl.h
index f23f8ee..8d1977b 100644
--- a/src/field_5x52_int128_impl.h
+++ b/src/field_5x52_int128_impl.h
@@ -15,7 +15,7 @@
#define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0)
#define VERIFY_BITS_128(x, n) VERIFY_CHECK(secp256k1_u128_check_bits((x), (n)))
-SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) {
+SECP256K1_FORCE_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) {
secp256k1_uint128 c, d;
uint64_t t3, t4, tx, u0;
uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4];
@@ -151,7 +151,7 @@ SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t
/* [r4 r3 r2 r1 r0] = [p8 p7 p6 p5 p4 p3 p2 p1 p0] */
}
-SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t *a) {
+SECP256K1_FORCE_INLINE static void secp256k1_fe_sqr_inner(uint64_t *r, const uint64_t *a) {
secp256k1_uint128 c, d;
uint64_t a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3], a4 = a[4];
uint64_t t3, t4, tx, u0;
diff --git a/src/util.h b/src/util.h
index 5d03e4c..492a592 100644
--- a/src/util.h
+++ b/src/util.h
@@ -57,6 +57,17 @@ static void print_buf_plain(const unsigned char *buf, size_t len) {
# define SECP256K1_INLINE inline
# endif
+# if !defined(_DEBUG) && !defined(__NO_INLINE__) && !defined(__OPTIMIZE_SIZE__)
+# if defined(__OPTIMIZE__) && (SECP256K1_GNUC_PREREQ(3, 0) || defined(__clang__))
+# define SECP256K1_FORCE_INLINE SECP256K1_INLINE __attribute__((always_inline))
+# elif defined(_MSC_VER)
+# define SECP256K1_FORCE_INLINE __forceinline
+# endif
+# endif
+# ifndef SECP256K1_FORCE_INLINE
+# define SECP256K1_FORCE_INLINE SECP256K1_INLINE
+# endif
+
/** Assert statically that expr is true.
*
* This is a statement-like macro and can only be used inside functions.
Why this scored 13/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.