Problem: Both field implementations serialize normalized elements with 32 separate byte assignments in secp256k1_fe_impl_get_b32.
They were introduced in #437 to unroll nested nibble loops for performance.
At the time, the endian write helpers did not exist, so the unrolling was expressed directly.
Fix: Keep both serializers unrolled by packing the 5x52 limbs into four 64-bit words and the 10x26 limbs into eight 32-bit words, then reuse the corresponding endian write helper. This matches the existing 4x64 and 8x32 scalar serializers. The serialized output is unchanged for normalized inputs, and benchmarks indicate no measurable performance regression.
Testing: Existing field conversion and reduced-boundary tests compare the serialized bytes directly.
Compiler Explorer compares the exact before and after serializers with GCC 16.1 and Clang 22.1 at -O2, in both native and -m32 modes.
<details><summary>Benchmarks</summary>
for cc in gcc clang; do \
echo; $cc --version | head -1; \
CC=$cc cmake -B build-$cc -GNinja -DCMAKE_BUILD_TYPE=Release >/dev/null 2>&1 && \
CC=$cc cmake -B build-$cc-10x26 -GNinja -DCMAKE_BUILD_TYPE=Release -DSECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY=int64 >/dev/null 2>&1 && \
for build in build-$cc build-$cc-10x26; do \
echo; echo $build; \
for rev in ebf594320dc838b9de1abb54d5ba98cef84f4297 e217ead5c46062ecda964ba858f7518b7e3bb5e7; do \
git fetch origin -q $rev && git checkout -q $rev && \
ninja -C $build bench >/dev/null 2>&1 && \
echo $rev && \
SECP256K1_BENCH_ITERS=10000 $build/bin/bench; \
done; \
done; \
done
gcc (Ubuntu 15.2.0-16ubuntu1) 15.2.0
build-gcc
ebf594320dc838b9de1abb54d5ba98cef84f4297
Benchmark , Min(us) , Avg(us) , Max(us)
ecdsa_verify , 33.9 , 34.0 , 34.0
ecdsa_sign , 21.6 , 21.6 , 21.6
ec_keygen , 15.2 , 15.2 , 15.3
ecdh , 33.4 , 33.5 , 33.5
schnorrsig_sign , 16.1 , 16.1 , 16.2
schnorrsig_verify , 34.3 , 34.3 , 34.4
ellswift_encode , 16.2 , 16.2 , 16.2
ellswift_decode , 7.21 , 7.22 , 7.24
ellswift_keygen , 31.5 , 31.5 , 31.5
ellswift_ecdh , 36.0 , 36.1 , 36.1
e217ead5c46062ecda964ba858f7518b7e3bb5e7
Benchmark , Min(us) , Avg(us) , Max(us)
ecdsa_verify , 34.0 , 34.1 , 34.4
ecdsa_sign , 21.6 , 21.6 , 21.6
ec_keygen , 15.3 , 15.3 , 15.3
ecdh , 33.3 , 33.4 , 33.6
schnorrsig_sign , 16.1 , 16.1 , 16.2
schnorrsig_verify , 34.4 , 34.4 , 34.5
ellswift_encode , 16.3 , 16.3 , 16.3
ellswift_decode , 7.24 , 7.24 , 7.25
ellswift_keygen , 31.5 , 31.6 , 31.7
ellswift_ecdh , 36.0 , 36.1 , 36.1
build-gcc-10x26
ebf594320dc838b9de1abb54d5ba98cef84f4297
Benchmark , Min(us) , Avg(us) , Max(us)
ecdsa_verify , 58.4 , 58.5 , 58.5
ecdsa_sign , 29.7 , 29.8 , 29.8
ec_keygen , 22.3 , 22.4 , 22.5
ecdh , 56.0 , 56.1 , 56.2
schnorrsig_sign , 23.4 , 23.4 , 23.5
schnorrsig_verify , 58.9 , 59.0 , 59.1
ellswift_encode , 22.7 , 22.7 , 22.7
ellswift_decode , 10.8 , 10.8 , 10.8
ellswift_keygen , 45.1 , 45.2 , 45.3
ellswift_ecdh , 59.6 , 59.7 , 59.8
e217ead5c46062ecda964ba858f7518b7e3bb5e7
Benchmark , Min(us) , Avg(us) , Max(us)
ecdsa_verify , 58.5 , 58.6 , 58.7
ecdsa_sign , 29.8 , 29.8 , 29.9
ec_keygen , 22.3 , 22.4 , 22.4
ecdh , 56.0 , 56.1 , 56.4
schnorrsig_sign , 23.5 , 23.5 , 23.5
schnorrsig_verify , 58.9 , 59.0 , 59.1
ellswift_encode , 22.9 , 22.9 , 22.9
ellswift_decode , 10.8 , 10.8 , 10.8
ellswift_keygen , 45.2 , 45.3 , 45.4
ellswift_ecdh , 59.6 , 59.8 , 59.9
Ubuntu clang version 21.1.8 (6ubuntu1)
build-clang
ebf594320dc838b9de1abb54d5ba98cef84f4297
Benchmark , Min(us) , Avg(us) , Max(us)
ecdsa_verify , 36.2 , 36.3 , 36.7
ecdsa_sign , 23.1 , 23.1 , 23.2
ec_keygen , 16.6 , 16.7 , 16.7
ecdh , 35.6 , 35.7 , 35.7
schnorrsig_sign , 17.6 , 17.6 , 17.6
schnorrsig_verify , 36.6 , 36.7 , 36.9
ellswift_encode , 16.6 , 16.6 , 16.7
ellswift_decode , 7.28 , 7.29 , 7.30
ellswift_keygen , 33.2 , 33.2 , 33.3
ellswift_ecdh , 38.5 , 38.5 , 38.6
e217ead5c46062ecda964ba858f7518b7e3bb5e7
Benchmark , Min(us) , Avg(us) , Max(us)
ecdsa_verify , 35.5 , 35.6 , 35.8
ecdsa_sign , 23.0 , 23.1 , 23.2
ec_keygen , 16.6 , 16.7 , 16.8
ecdh , 35.7 , 35.7 , 35.8
schnorrsig_sign , 17.6 , 17.6 , 17.7
schnorrsig_verify , 35.9 , 35.9 , 36.0
ellswift_encode , 16.4 , 16.4 , 16.4
ellswift_decode , 7.22 , 7.22 , 7.23
ellswift_keygen , 33.0 , 33.0 , 33.1
ellswift_ecdh , 38.5 , 38.6 , 38.8
build-clang-10x26
ebf594320dc838b9de1abb54d5ba98cef84f4297
Benchmark , Min(us) , Avg(us) , Max(us)
ecdsa_verify , 64.2 , 64.3 , 64.7
ecdsa_sign , 33.8 , 33.9 , 33.9
ec_keygen , 26.3 , 26.3 , 26.3
ecdh , 63.4 , 63.6 , 63.8
schnorrsig_sign , 27.2 , 27.3 , 27.3
schnorrsig_verify , 64.5 , 64.6 , 64.7
ellswift_encode , 22.1 , 22.1 , 22.1
ellswift_decode , 10.6 , 10.6 , 10.7
ellswift_keygen , 48.3 , 48.3 , 48.5
ellswift_ecdh , 67.0 , 67.0 , 67.1
e217ead5c46062ecda964ba858f7518b7e3bb5e7
Benchmark , Min(us) , Avg(us) , Max(us)
ecdsa_verify , 63.9 , 64.0 , 64.3
ecdsa_sign , 33.8 , 33.9 , 34.0
ec_keygen , 26.3 , 26.3 , 26.3
ecdh , 62.5 , 62.5 , 62.6
schnorrsig_sign , 27.2 , 27.3 , 27.4
schnorrsig_verify , 64.1 , 64.2 , 64.2
ellswift_encode , 22.1 , 22.2 , 22.3
ellswift_decode , 10.6 , 10.7 , 10.7
ellswift_keygen , 48.4 , 48.4 , 48.6
ellswift_ecdh , 66.2 , 66.3 , 66.4
</details>