f6e77fba24
Adds Secp256k1.ecdhXOnly(xOnlyPub, scalar) that directly computes the x-coordinate of scalar·P from a 32-byte x-only public key. This replaces the previous pubKeyTweakMulCompact path that went through: h02 + pubKey → pubKeyTweakMul → serializeCompressed → copyOfRange(1,33) The new path eliminates 4 ByteArray allocations per call (h02 concat, parsePublicKey's copyOfRange, serializeCompressed, final copyOfRange). The square root for y-decompression is still needed (EC point operations require both coordinates), but the x-coordinate of the result is the same regardless of y sign since k·(-P) = -(k·P) and negation preserves x. A Montgomery ladder (x-only arithmetic without y) would eliminate the sqrt entirely but requires a complete algorithm rewrite. Analysis of remaining pubKeyTweakMul cost vs C: - sqrt for y-decompression: ~267 ops (C doesn't need — key already parsed) - inv for Jacobian→affine: ~270 ops (both C and Kotlin do this) - 8×32 limbs: 64 products/mul vs C's 25 (JVM ceiling) - Full Jacobian P-side addition: 11M+5S vs C's mixed 8M+3S https://claude.ai/code/session_01BhU63WUe9AhikZxRdw3Lpg