feat: add batch verify to Android benchmark + expose in Secp256k1InstanceOurs
Add verifySchnorrBatch to Secp256k1InstanceOurs wrapper and add Android benchmark tests for batch(8) and batch(16). To get per-event cost: ns/op ÷ batchSize. JVM benchmark showed 4-7× speedup over individual verify. Android results TBD. https://claude.ai/code/session_01EMY5RnXb9rnsyU2KbXrSaY
This commit is contained in:
+34
@@ -164,4 +164,38 @@ class Secp256k1Benchmark {
|
|||||||
assertNotNull(Secp256k1InstanceOurs.pubKeyTweakMulCompact(pubKey2XOnly, privKey))
|
assertNotNull(Secp256k1InstanceOurs.pubKeyTweakMulCompact(pubKey2XOnly, privKey))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ==================== Batch verification (Pure Kotlin) ====================
|
||||||
|
// Same pubkey, n events — the typical Nostr pattern (feed from one author).
|
||||||
|
// Each iteration verifies the entire batch. Compare per-event cost:
|
||||||
|
// ns/op ÷ batchSize = per-event cost
|
||||||
|
// JVM benchmark showed 4-7× speedup over individual verify.
|
||||||
|
|
||||||
|
private fun buildBatch(size: Int): Pair<List<ByteArray>, List<ByteArray>> {
|
||||||
|
val sigs = mutableListOf<ByteArray>()
|
||||||
|
val msgs = mutableListOf<ByteArray>()
|
||||||
|
for (i in 0 until size) {
|
||||||
|
val m = ByteArray(32) { (i * 7 + it).toByte() }
|
||||||
|
sigs.add(Secp256k1InstanceOurs.signSchnorr(m, privKey, auxRand))
|
||||||
|
msgs.add(m)
|
||||||
|
}
|
||||||
|
return Pair(sigs, msgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val batch8 = buildBatch(8)
|
||||||
|
private val batch16 = buildBatch(16)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun verifyBatch8Ours() {
|
||||||
|
benchmarkRule.measureRepeated {
|
||||||
|
assertTrue(Secp256k1InstanceOurs.verifySchnorrBatch(xOnlyPub, batch8.first, batch8.second))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun verifyBatch16Ours() {
|
||||||
|
benchmarkRule.measureRepeated {
|
||||||
|
assertTrue(Secp256k1InstanceOurs.verifySchnorrBatch(xOnlyPub, batch16.first, batch16.second))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,6 +72,16 @@ object Secp256k1InstanceOurs {
|
|||||||
pubKey: ByteArray,
|
pubKey: ByteArray,
|
||||||
): Boolean = Secp256k1.verifySchnorrFast(signature, hash, pubKey)
|
): Boolean = Secp256k1.verifySchnorrFast(signature, hash, pubKey)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Batch-verify multiple signatures from the same pubkey.
|
||||||
|
* Uses scalar+point summation — one mulDoubleG for the whole batch.
|
||||||
|
*/
|
||||||
|
fun verifySchnorrBatch(
|
||||||
|
pubKey: ByteArray,
|
||||||
|
signatures: List<ByteArray>,
|
||||||
|
messages: List<ByteArray>,
|
||||||
|
): Boolean = Secp256k1.verifySchnorrBatch(pubKey, signatures, messages)
|
||||||
|
|
||||||
fun privateKeyAdd(
|
fun privateKeyAdd(
|
||||||
first: ByteArray,
|
first: ByteArray,
|
||||||
second: ByteArray,
|
second: ByteArray,
|
||||||
|
|||||||
Reference in New Issue
Block a user