mirror of
https://github.com/luxfi/precompile.git
synced 2026-09-24 00:26:21 +00:00
124 lines
3.9 KiB
Go
124 lines
3.9 KiB
Go
// Copyright (C) 2025-2026, Lux Industries, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package p3q
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/rand"
|
|
"testing"
|
|
|
|
"github.com/luxfi/crypto/mldsa"
|
|
"github.com/luxfi/geth/common"
|
|
)
|
|
|
|
// p3qBenchFixture pre-computes a signed-MLDSA65 payload + EncodeInput
|
|
// wire frame so each benchmark iteration only exercises the precompile
|
|
// dispatch + FIPS 204 verifier (no key-gen, no sign).
|
|
type p3qBenchFixture struct {
|
|
input []byte
|
|
gas uint64
|
|
pkBuf []byte
|
|
sigBuf []byte
|
|
hash []byte
|
|
}
|
|
|
|
func mkFixture(b *testing.B) *p3qBenchFixture {
|
|
b.Helper()
|
|
sk, err := mldsa.GenerateKey(rand.Reader, mldsa.MLDSA65)
|
|
if err != nil {
|
|
b.Fatalf("GenerateKey: %v", err)
|
|
}
|
|
hash := bytes.Repeat([]byte{0x42}, MessageHashSize)
|
|
sig, err := sk.SignCtx(rand.Reader, hash, PrecompileCtx)
|
|
if err != nil {
|
|
b.Fatalf("SignCtx: %v", err)
|
|
}
|
|
pk := sk.PublicKey.Bytes()
|
|
input := EncodeInput(ModeMLDSA65, sig, pk, hash)
|
|
gas := P3QVerifyPrecompile.RequiredGas(input)
|
|
return &p3qBenchFixture{input: input, gas: gas * 2, pkBuf: pk, sigBuf: sig, hash: hash}
|
|
}
|
|
|
|
// BenchmarkP3Q_Verify_Pulsar_MLDSA65 measures one full P3Q precompile
|
|
// dispatch (kind-byte dispatch + structural checks + FIPS 204 verify)
|
|
// for the canonical Pulsar / ML-DSA-65 happy path. b.N >= 10000 by
|
|
// default; the run wraps the existing TestP3Q_RoundTrip_RealMLDSA path.
|
|
func BenchmarkP3Q_Verify_Pulsar_MLDSA65(b *testing.B) {
|
|
f := mkFixture(b)
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
_, _, err := P3QVerifyPrecompile.Run(nil, common.Address{}, ContractP3QVerifyAddress, f.input, f.gas, true)
|
|
if err != nil {
|
|
b.Fatalf("Run: %v", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkP3Q_Verify_KindDispatch_N1 measures the per-call dispatch
|
|
// cost on a single-kind workload — every iteration is KindPulsar.
|
|
// Pairs with the N=64 / N=1024 batch variants below to show the
|
|
// kind-byte dispatch overhead vs a hypothetical single-kind slot.
|
|
func BenchmarkP3Q_Verify_KindDispatch_N1(b *testing.B) {
|
|
f := mkFixture(b)
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
_, _, _ = P3QVerifyPrecompile.Run(nil, common.Address{}, ContractP3QVerifyAddress, f.input, f.gas, true)
|
|
}
|
|
}
|
|
|
|
// BenchmarkP3Q_Verify_KindDispatch_N64 iterates a verify-batch of 64
|
|
// inside one b.N step. ns/op is per-batch; per-verify is ns/op / 64.
|
|
func BenchmarkP3Q_Verify_KindDispatch_N64(b *testing.B) {
|
|
f := mkFixture(b)
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
for j := 0; j < 64; j++ {
|
|
_, _, _ = P3QVerifyPrecompile.Run(nil, common.Address{}, ContractP3QVerifyAddress, f.input, f.gas, true)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkP3Q_Verify_KindDispatch_N1024 iterates a verify-batch of 1024.
|
|
// ns/op is per-batch; per-verify is ns/op / 1024.
|
|
func BenchmarkP3Q_Verify_KindDispatch_N1024(b *testing.B) {
|
|
f := mkFixture(b)
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
for j := 0; j < 1024; j++ {
|
|
_, _, _ = P3QVerifyPrecompile.Run(nil, common.Address{}, ContractP3QVerifyAddress, f.input, f.gas, true)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkP3Q_RequiredGas isolates the gas-only path (no verify) so
|
|
// the kind-byte dispatch + structural-check cost can be measured
|
|
// independently from the FIPS 204 verifier.
|
|
func BenchmarkP3Q_RequiredGas(b *testing.B) {
|
|
input := make([]byte, MinInputLength+MLDSA65SignatureSize+MLDSA65PublicKeySize)
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
_ = P3QVerifyPrecompile.RequiredGas(input)
|
|
}
|
|
}
|
|
|
|
// BenchmarkP3Q_Verify_Standalone measures the in-process Verify entry
|
|
// point (the off-chain pre-flight + chains/zkvm dispatch path) at
|
|
// MLDSA-65. This is the API path without precompile-level gas
|
|
// accounting and AccessibleState plumbing.
|
|
func BenchmarkP3Q_Verify_Standalone(b *testing.B) {
|
|
f := mkFixture(b)
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
if err := Verify(ModeMLDSA65, f.pkBuf, f.sigBuf, f.hash); err != nil {
|
|
b.Fatalf("Verify: %v", err)
|
|
}
|
|
}
|
|
}
|