diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/secp256k1/Glv.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/secp256k1/Glv.kt index 95d933c9d..bfda6d1d4 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/secp256k1/Glv.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/secp256k1/Glv.kt @@ -20,6 +20,8 @@ */ package com.vitorpamplona.quartz.utils.secp256k1 +import kotlin.jvm.JvmField + // ===================================================================================== // GLV ENDOMORPHISM AND WNAF ENCODING FOR secp256k1 // ===================================================================================== @@ -39,6 +41,7 @@ package com.vitorpamplona.quartz.utils.secp256k1 internal object Glv { /** β: cube root of unity mod p. φ(x,y) = (β·x, y). */ + @JvmField val BETA = longArrayOf( -4523465429756870162L, @@ -50,10 +53,10 @@ internal object Glv { // ==================== GLV Scalar Decomposition ==================== class Split( - val k1: LongArray, - val k2: LongArray, - val negK1: Boolean, - val negK2: Boolean, + @JvmField val k1: LongArray, + @JvmField val k2: LongArray, + @JvmField val negK1: Boolean, + @JvmField val negK2: Boolean, ) fun splitScalar(k: LongArray): Split { diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/secp256k1/PointTypes.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/secp256k1/PointTypes.kt index 037d3b354..8df709ec4 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/secp256k1/PointTypes.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/utils/secp256k1/PointTypes.kt @@ -20,6 +20,8 @@ */ package com.vitorpamplona.quartz.utils.secp256k1 +import kotlin.jvm.JvmField + /** * Mutable Jacobian point for in-place computation. * @@ -34,9 +36,9 @@ package com.vitorpamplona.quartz.utils.secp256k1 * multiplication, which performs thousands of doublings and additions per operation. */ internal class MutablePoint( - val x: LongArray = LongArray(4), - val y: LongArray = LongArray(4), - val z: LongArray = LongArray(4), + @JvmField val x: LongArray = LongArray(4), + @JvmField val y: LongArray = LongArray(4), + @JvmField val z: LongArray = LongArray(4), ) { fun isInfinity(): Boolean = U256.isZero(z) @@ -71,8 +73,8 @@ internal class MutablePoint( * Used for precomputed tables where we want compact storage and mixed addition. */ internal class AffinePoint( - val x: LongArray = LongArray(4), - val y: LongArray = LongArray(4), + @JvmField val x: LongArray = LongArray(4), + @JvmField val y: LongArray = LongArray(4), ) /** @@ -90,53 +92,71 @@ internal class AffinePoint( * scalar multiplication (~20-30ns each on JVM). */ internal class PointScratch { - val t = Array(12) { LongArray(4) } - val dblCopy = MutablePoint() // Copy buffer for in-place doubling (out === input) - val w = LongArray(8) // Wide buffer for FieldP.mul/sqr — shared, avoids ThreadLocal + @JvmField val t = Array(12) { LongArray(4) } - // Pre-allocated scratch for wNAF encoding (avoids IntArray allocation per call). - // Size 145 = 129 (max bits after GLV split) + 15 (max window) + 1 (headroom). - val wnaf1 = IntArray(145) - val wnaf2 = IntArray(145) - val wnaf3 = IntArray(145) // mulDoubleG needs 4 wNAF arrays - val wnaf4 = IntArray(145) - val wnafTmp = LongArray(4) // scratch for wnaf scalar copy (GLV scalars are up to 4 limbs) + @JvmField val dblCopy = MutablePoint() - // Pre-allocated scratch for wNAF mixed addition - val mixTmp = MutablePoint() - val mixNegY = LongArray(4) + @JvmField val w = LongArray(8) - // Pre-allocated P-side tables for mul/mulDoubleG (avoids ~80 LongArray allocs per call) - val pOddJac = Array(8) { MutablePoint() } - val pLamOddJac = Array(8) { MutablePoint() } - val pOddAff = Array(8) { AffinePoint() } - val pLamOddAff = Array(8) { AffinePoint() } - val p2 = MutablePoint() // doublePoint temp for table building + @JvmField val wnaf1 = IntArray(145) - // Pre-allocated batch inversion temps (avoids 12 LongArray allocs per call) - val cumZ = Array(8) { LongArray(4) } - val batchInv = LongArray(4) - val batchZInv = LongArray(4) - val batchZInv2 = LongArray(4) - val batchZInv3 = LongArray(4) + @JvmField val wnaf2 = IntArray(145) - // Pre-allocated scratch for Glv.splitScalar (avoids ~26 LongArray allocs per call) - val splitWide = LongArray(8) // mulShift384 and ScalarN.mulTo scratch - val splitT1 = LongArray(4) // temporary for mul results - val splitT2 = LongArray(4) // temporary for mul results - val splitK1 = LongArray(4) // output k1 - val splitK2 = LongArray(4) // output k2 + @JvmField val wnaf3 = IntArray(145) - // Pre-allocated scratch for toAffine / toAffineX (avoids 3 LongArray allocs per call) - val zInv = LongArray(4) - val zInv2 = LongArray(4) - val zInv3 = LongArray(4) + @JvmField val wnaf4 = IntArray(145) - // Pre-allocated scratch for Secp256k1 entry points (avoids per-call allocations) - val entryPx = LongArray(4) // liftX / parsePublicKey output - val entryPy = LongArray(4) - val entryPoint = MutablePoint() // pubkeyCreate, signSchnorr, ecdhXOnly - val entryResult = MutablePoint() // mulG / mul output - val entryTmp = LongArray(4) // liftX temp, auxrand XOR, nonce, etc. - val entryTmp2 = LongArray(4) // secondary temp for signSchnorr R-point + @JvmField val wnafTmp = LongArray(4) + + @JvmField val mixTmp = MutablePoint() + + @JvmField val mixNegY = LongArray(4) + + @JvmField val pOddJac = Array(8) { MutablePoint() } + + @JvmField val pLamOddJac = Array(8) { MutablePoint() } + + @JvmField val pOddAff = Array(8) { AffinePoint() } + + @JvmField val pLamOddAff = Array(8) { AffinePoint() } + + @JvmField val p2 = MutablePoint() + + @JvmField val cumZ = Array(8) { LongArray(4) } + + @JvmField val batchInv = LongArray(4) + + @JvmField val batchZInv = LongArray(4) + + @JvmField val batchZInv2 = LongArray(4) + + @JvmField val batchZInv3 = LongArray(4) + + @JvmField val splitWide = LongArray(8) + + @JvmField val splitT1 = LongArray(4) + + @JvmField val splitT2 = LongArray(4) + + @JvmField val splitK1 = LongArray(4) + + @JvmField val splitK2 = LongArray(4) + + @JvmField val zInv = LongArray(4) + + @JvmField val zInv2 = LongArray(4) + + @JvmField val zInv3 = LongArray(4) + + @JvmField val entryPx = LongArray(4) + + @JvmField val entryPy = LongArray(4) + + @JvmField val entryPoint = MutablePoint() + + @JvmField val entryResult = MutablePoint() + + @JvmField val entryTmp = LongArray(4) + + @JvmField val entryTmp2 = LongArray(4) }