deps: database v1.18.3 (drops zapdb/v4 transitive); ntt_simd updates; bench/

This commit is contained in:
Hanzo AI
2026-05-05 17:11:33 -07:00
parent a7cafe5f25
commit e5f37e2cfd
31 changed files with 57449 additions and 603 deletions
@@ -0,0 +1,54 @@
{
"name": "circuits",
"host": {
"time": "2026-04-27T19:49:40Z",
"go_version": "go1.26.2",
"goos": "darwin",
"goarch": "arm64",
"num_cpu": 10,
"gomaxprocs": 10,
"cpu_brand": "Apple M1 Max",
"os_product": "macOS",
"os_version": "26.4",
"build_tags": "default",
"fhe_commit": "873ee56fed87a95794aefac5c4921955ba0c332a",
"lattice_commit": "a362b2e4d5fe6e67850e9dbb848fe9ab460e7711"
},
"command": "go test -test.paniconexit0 -test.count=1 -test.run=^$ -test.bench=^BenchmarkCircuit_BoolGate_CPU$ -test.benchtime=2x -test.timeout=5m0s",
"cells": [
{
"name": "BoolGate/CPU",
"params": {
"backend": "CPU (pure Go)",
"circuit": "boolean_and",
"params": "PN10QP27"
},
"status": "ok",
"iterations": 1,
"median_ns": 99870084,
"mean_ns": 99870084,
"p50_ns": 99870084,
"p95_ns": 99870084,
"p99_ns": 99870084,
"ops_per_sec": 10.01300850012302,
"notes": "correctness verified against plaintext"
},
{
"name": "BoolGate/CPU",
"params": {
"backend": "CPU (pure Go)",
"circuit": "boolean_and",
"params": "PN10QP27"
},
"status": "ok",
"iterations": 2,
"median_ns": 95055958,
"mean_ns": 95916979,
"p50_ns": 95055958,
"p95_ns": 95055958,
"p99_ns": 95055958,
"ops_per_sec": 10.520119107105312,
"notes": "correctness verified against plaintext"
}
]
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,29 @@
{
"name": "ntt_ladder_metal",
"host": {
"time": "2026-04-27T19:51:15Z",
"go_version": "go1.26.2",
"goos": "darwin",
"goarch": "arm64",
"num_cpu": 10,
"gomaxprocs": 10,
"cpu_brand": "Apple M1 Max",
"os_product": "macOS",
"os_version": "26.4",
"build_tags": "default",
"fhe_commit": "873ee56fed87a95794aefac5c4921955ba0c332a",
"lattice_commit": "a362b2e4d5fe6e67850e9dbb848fe9ab460e7711"
},
"command": "go test -test.paniconexit0 -test.count=1 -test.run=^$ -test.bench=^BenchmarkNTTLadderMetal$ -test.benchtime=10x -test.timeout=2m0s",
"cells": [
{
"name": "BenchmarkNTTLadderMetal",
"params": {
"backend": "CPU (pure Go)"
},
"status": "skipped",
"reason": "NotApplicable: built without -tags gpu; GPU wrapper not linked",
"iterations": 0
}
]
}
@@ -0,0 +1,29 @@
{
"name": "ntt_ladder_metal",
"host": {
"time": "2026-04-27T21:51:15Z",
"go_version": "go1.26.2",
"goos": "darwin",
"goarch": "arm64",
"num_cpu": 10,
"gomaxprocs": 10,
"cpu_brand": "Apple M1 Max",
"os_product": "macOS",
"os_version": "26.4",
"build_tags": "gpu",
"fhe_commit": "01b98a8ed264e678c29c75e294358521804e33dd",
"lattice_commit": "d11ec53c16e7ef6d0d1fc84ea37fd285e1f1f9d2"
},
"command": "go test -test.paniconexit0 -test.bench=BenchmarkNTTLadderMetal -test.benchtime=3x -test.count=1 -test.timeout=15m0s -test.v=true",
"cells": [
{
"name": "BenchmarkNTTLadderMetal",
"params": {
"backend": "cpu"
},
"status": "skipped",
"reason": "NotApplicable: lattice_gpu_available() returned false (library built without WITH_GPU=ON)",
"iterations": 0
}
]
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,136 @@
{
"name": "reconcile_88_121",
"host": {
"time": "2026-04-27T19:48:30Z",
"go_version": "go1.26.2",
"goos": "darwin",
"goarch": "arm64",
"num_cpu": 10,
"gomaxprocs": 10,
"cpu_brand": "Apple M1 Max",
"os_product": "macOS",
"os_version": "26.4",
"build_tags": "default",
"fhe_commit": "873ee56fed87a95794aefac5c4921955ba0c332a",
"lattice_commit": "a362b2e4d5fe6e67850e9dbb848fe9ab460e7711"
},
"command": "go test -test.paniconexit0 -test.count=1 -test.run=^$ -test.bench=^BenchmarkReconcile_ -test.benchtime=10x -test.timeout=2m0s",
"cells": [
{
"name": "BenchmarkReconcile_88_vs_121/Go/single-poly",
"params": {
"B": "1",
"N": "4096",
"label": "go pure-Go single-poly N=4096 (the denominator in #121's ratio)",
"path": "go-pure"
},
"status": "ok",
"iterations": 1,
"median_ns": 27500,
"mean_ns": 27500,
"p50_ns": 27500,
"p95_ns": 27500,
"p99_ns": 27500,
"ops_per_sec": 36363.63636363636
},
{
"name": "BenchmarkReconcile_88_vs_121/Go/single-poly",
"params": {
"B": "1",
"N": "4096",
"label": "go pure-Go single-poly N=4096 (the denominator in #121's ratio)",
"path": "go-pure"
},
"status": "ok",
"iterations": 1,
"median_ns": 27667,
"mean_ns": 27667,
"p50_ns": 27667,
"p95_ns": 27667,
"p99_ns": 27667,
"ops_per_sec": 36144.14284165251
},
{
"name": "BenchmarkReconcile_88_vs_121/Go/batched-128-sequential",
"params": {
"B": "128",
"N": "4096",
"label": "go pure-Go N=4096 sequenced 128 times (matches what blind-rotate does)",
"path": "go-pure"
},
"status": "ok",
"iterations": 1,
"median_ns": 3548250,
"mean_ns": 3548250,
"p50_ns": 3548250,
"p95_ns": 3548250,
"p99_ns": 3548250,
"ops_per_sec": 281.8290706686395
},
{
"name": "BenchmarkReconcile_88_vs_121/Go/batched-128-sequential",
"params": {
"B": "128",
"N": "4096",
"label": "go pure-Go N=4096 sequenced 128 times (matches what blind-rotate does)",
"path": "go-pure"
},
"status": "ok",
"iterations": 1,
"median_ns": 3755083,
"mean_ns": 3755083,
"p50_ns": 3755083,
"p95_ns": 3755083,
"p99_ns": 3755083,
"ops_per_sec": 266.3056981696543
},
{
"name": "BenchmarkReconcile_88_vs_121/Metal/single-poly",
"params": {
"B": "1",
"N": "4096",
"label": "metal luxlattice single-poly N=4096 (the numerator in #121's 0.08x ratio)",
"path": "metal-luxlattice"
},
"status": "skipped",
"reason": "NotApplicable: built without -tags gpu; GPU wrapper not linked",
"iterations": 0
},
{
"name": "BenchmarkReconcile_88_vs_121/Metal/single-poly",
"params": {
"B": "1",
"N": "4096",
"label": "metal luxlattice single-poly N=4096 (the numerator in #121's 0.08x ratio)",
"path": "metal-luxlattice"
},
"status": "skipped",
"reason": "NotApplicable: built without -tags gpu; GPU wrapper not linked",
"iterations": 0
},
{
"name": "BenchmarkReconcile_88_vs_121/Metal/batched-128-fused",
"params": {
"B": "128",
"N": "4096",
"label": "metal luxlattice BatchNTT N=4096 B=128 (the #88 14.02x claim target)",
"path": "metal-luxlattice"
},
"status": "skipped",
"reason": "NotApplicable: built without -tags gpu; GPU wrapper not linked",
"iterations": 0
},
{
"name": "BenchmarkReconcile_88_vs_121/Metal/batched-128-fused",
"params": {
"B": "128",
"N": "4096",
"label": "metal luxlattice BatchNTT N=4096 B=128 (the #88 14.02x claim target)",
"path": "metal-luxlattice"
},
"status": "skipped",
"reason": "NotApplicable: built without -tags gpu; GPU wrapper not linked",
"iterations": 0
}
]
}
@@ -0,0 +1,136 @@
{
"name": "reconcile_88_121",
"host": {
"time": "2026-04-27T19:51:29Z",
"go_version": "go1.26.2",
"goos": "darwin",
"goarch": "arm64",
"num_cpu": 10,
"gomaxprocs": 10,
"cpu_brand": "Apple M1 Max",
"os_product": "macOS",
"os_version": "26.4",
"build_tags": "default",
"fhe_commit": "873ee56fed87a95794aefac5c4921955ba0c332a",
"lattice_commit": "a362b2e4d5fe6e67850e9dbb848fe9ab460e7711"
},
"command": "go test -test.paniconexit0 -test.count=1 -test.run=^$ -test.bench=^BenchmarkReconcile_ -test.benchtime=20x -test.timeout=2m0s",
"cells": [
{
"name": "BenchmarkReconcile_88_vs_121/Go/single-poly",
"params": {
"B": "1",
"N": "4096",
"label": "go pure-Go single-poly N=4096 (the denominator in #121's ratio)",
"path": "go-pure"
},
"status": "ok",
"iterations": 1,
"median_ns": 27709,
"mean_ns": 27709,
"p50_ns": 27709,
"p95_ns": 27709,
"p99_ns": 27709,
"ops_per_sec": 36089.35724854741
},
{
"name": "BenchmarkReconcile_88_vs_121/Go/single-poly",
"params": {
"B": "1",
"N": "4096",
"label": "go pure-Go single-poly N=4096 (the denominator in #121's ratio)",
"path": "go-pure"
},
"status": "ok",
"iterations": 1,
"median_ns": 27875,
"mean_ns": 27875,
"p50_ns": 27875,
"p95_ns": 27875,
"p99_ns": 27875,
"ops_per_sec": 35874.439461883405
},
{
"name": "BenchmarkReconcile_88_vs_121/Go/batched-128-sequential",
"params": {
"B": "128",
"N": "4096",
"label": "go pure-Go N=4096 sequenced 128 times (matches what blind-rotate does)",
"path": "go-pure"
},
"status": "ok",
"iterations": 1,
"median_ns": 3756500,
"mean_ns": 3756500,
"p50_ns": 3756500,
"p95_ns": 3756500,
"p99_ns": 3756500,
"ops_per_sec": 266.2052442433116
},
{
"name": "BenchmarkReconcile_88_vs_121/Go/batched-128-sequential",
"params": {
"B": "128",
"N": "4096",
"label": "go pure-Go N=4096 sequenced 128 times (matches what blind-rotate does)",
"path": "go-pure"
},
"status": "ok",
"iterations": 1,
"median_ns": 3516791,
"mean_ns": 3516791,
"p50_ns": 3516791,
"p95_ns": 3516791,
"p99_ns": 3516791,
"ops_per_sec": 284.3501362463678
},
{
"name": "BenchmarkReconcile_88_vs_121/Metal/single-poly",
"params": {
"B": "1",
"N": "4096",
"label": "metal luxlattice single-poly N=4096 (the numerator in #121's 0.08x ratio)",
"path": "metal-luxlattice"
},
"status": "skipped",
"reason": "NotApplicable: built without -tags gpu; GPU wrapper not linked",
"iterations": 0
},
{
"name": "BenchmarkReconcile_88_vs_121/Metal/single-poly",
"params": {
"B": "1",
"N": "4096",
"label": "metal luxlattice single-poly N=4096 (the numerator in #121's 0.08x ratio)",
"path": "metal-luxlattice"
},
"status": "skipped",
"reason": "NotApplicable: built without -tags gpu; GPU wrapper not linked",
"iterations": 0
},
{
"name": "BenchmarkReconcile_88_vs_121/Metal/batched-128-fused",
"params": {
"B": "128",
"N": "4096",
"label": "metal luxlattice BatchNTT N=4096 B=128 (the #88 14.02x claim target)",
"path": "metal-luxlattice"
},
"status": "skipped",
"reason": "NotApplicable: built without -tags gpu; GPU wrapper not linked",
"iterations": 0
},
{
"name": "BenchmarkReconcile_88_vs_121/Metal/batched-128-fused",
"params": {
"B": "128",
"N": "4096",
"label": "metal luxlattice BatchNTT N=4096 B=128 (the #88 14.02x claim target)",
"path": "metal-luxlattice"
},
"status": "skipped",
"reason": "NotApplicable: built without -tags gpu; GPU wrapper not linked",
"iterations": 0
}
]
}
@@ -0,0 +1,136 @@
{
"name": "reconcile_88_121",
"host": {
"time": "2026-04-27T19:52:19Z",
"go_version": "go1.26.2",
"goos": "darwin",
"goarch": "arm64",
"num_cpu": 10,
"gomaxprocs": 10,
"cpu_brand": "Apple M1 Max",
"os_product": "macOS",
"os_version": "26.4",
"build_tags": "default",
"fhe_commit": "873ee56fed87a95794aefac5c4921955ba0c332a",
"lattice_commit": "a362b2e4d5fe6e67850e9dbb848fe9ab460e7711"
},
"command": "go test -test.paniconexit0 -test.count=1 -test.run=^$ -test.bench=^BenchmarkReconcile_88_vs_121$ -test.benchtime=20x -test.timeout=2m0s",
"cells": [
{
"name": "BenchmarkReconcile_88_vs_121/Go/single-poly",
"params": {
"B": "1",
"N": "4096",
"label": "go pure-Go single-poly N=4096 (the denominator in #121's ratio)",
"path": "go-pure"
},
"status": "ok",
"iterations": 1,
"median_ns": 27834,
"mean_ns": 27834,
"p50_ns": 27834,
"p95_ns": 27834,
"p99_ns": 27834,
"ops_per_sec": 35927.28317884602
},
{
"name": "BenchmarkReconcile_88_vs_121/Go/single-poly",
"params": {
"B": "1",
"N": "4096",
"label": "go pure-Go single-poly N=4096 (the denominator in #121's ratio)",
"path": "go-pure"
},
"status": "ok",
"iterations": 20,
"median_ns": 27459,
"mean_ns": 27541,
"p50_ns": 27459,
"p95_ns": 27833,
"p99_ns": 27833,
"ops_per_sec": 36417.932189810264
},
{
"name": "BenchmarkReconcile_88_vs_121/Go/batched-128-sequential",
"params": {
"B": "128",
"N": "4096",
"label": "go pure-Go N=4096 sequenced 128 times (matches what blind-rotate does)",
"path": "go-pure"
},
"status": "ok",
"iterations": 1,
"median_ns": 3540709,
"mean_ns": 3540709,
"p50_ns": 3540709,
"p95_ns": 3540709,
"p99_ns": 3540709,
"ops_per_sec": 282.42931006191134
},
{
"name": "BenchmarkReconcile_88_vs_121/Go/batched-128-sequential",
"params": {
"B": "128",
"N": "4096",
"label": "go pure-Go N=4096 sequenced 128 times (matches what blind-rotate does)",
"path": "go-pure"
},
"status": "ok",
"iterations": 20,
"median_ns": 3502958,
"mean_ns": 3558179,
"p50_ns": 3502958,
"p95_ns": 3815209,
"p99_ns": 3815209,
"ops_per_sec": 285.47302023033103
},
{
"name": "BenchmarkReconcile_88_vs_121/Metal/single-poly",
"params": {
"B": "1",
"N": "4096",
"label": "metal luxlattice single-poly N=4096 (the numerator in #121's 0.08x ratio)",
"path": "metal-luxlattice"
},
"status": "skipped",
"reason": "NotApplicable: built without -tags gpu; GPU wrapper not linked",
"iterations": 0
},
{
"name": "BenchmarkReconcile_88_vs_121/Metal/single-poly",
"params": {
"B": "1",
"N": "4096",
"label": "metal luxlattice single-poly N=4096 (the numerator in #121's 0.08x ratio)",
"path": "metal-luxlattice"
},
"status": "skipped",
"reason": "NotApplicable: built without -tags gpu; GPU wrapper not linked",
"iterations": 0
},
{
"name": "BenchmarkReconcile_88_vs_121/Metal/batched-128-fused",
"params": {
"B": "128",
"N": "4096",
"label": "metal luxlattice BatchNTT N=4096 B=128 (the #88 14.02x claim target)",
"path": "metal-luxlattice"
},
"status": "skipped",
"reason": "NotApplicable: built without -tags gpu; GPU wrapper not linked",
"iterations": 0
},
{
"name": "BenchmarkReconcile_88_vs_121/Metal/batched-128-fused",
"params": {
"B": "128",
"N": "4096",
"label": "metal luxlattice BatchNTT N=4096 B=128 (the #88 14.02x claim target)",
"path": "metal-luxlattice"
},
"status": "skipped",
"reason": "NotApplicable: built without -tags gpu; GPU wrapper not linked",
"iterations": 0
}
]
}
@@ -0,0 +1,136 @@
{
"name": "reconcile_88_121",
"host": {
"time": "2026-04-27T19:54:54Z",
"go_version": "go1.26.2",
"goos": "darwin",
"goarch": "arm64",
"num_cpu": 10,
"gomaxprocs": 10,
"cpu_brand": "Apple M1 Max",
"os_product": "macOS",
"os_version": "26.4",
"build_tags": "default",
"fhe_commit": "873ee56fed87a95794aefac5c4921955ba0c332a",
"lattice_commit": "a362b2e4d5fe6e67850e9dbb848fe9ab460e7711"
},
"command": "go test -test.paniconexit0 -test.count=1 -test.run=^$ -test.bench=^BenchmarkReconcile_88_vs_121$|^BenchmarkReconcile_MetalNTTZoo$|^BenchmarkTFHE_TRLWE_Add_CPU$|^BenchmarkThreshold_ShareAggregate_CPU$ -test.benchtime=10x -test.timeout=2m0s",
"cells": [
{
"name": "BenchmarkReconcile_88_vs_121/Go/single-poly",
"params": {
"B": "1",
"N": "4096",
"label": "go pure-Go single-poly N=4096 (the denominator in #121's ratio)",
"path": "go-pure"
},
"status": "ok",
"iterations": 1,
"median_ns": 40292,
"mean_ns": 40292,
"p50_ns": 40292,
"p95_ns": 40292,
"p99_ns": 40292,
"ops_per_sec": 24818.82259505609
},
{
"name": "BenchmarkReconcile_88_vs_121/Go/single-poly",
"params": {
"B": "1",
"N": "4096",
"label": "go pure-Go single-poly N=4096 (the denominator in #121's ratio)",
"path": "go-pure"
},
"status": "ok",
"iterations": 10,
"median_ns": 29000,
"mean_ns": 49291,
"p50_ns": 29000,
"p95_ns": 94917,
"p99_ns": 94917,
"ops_per_sec": 34482.75862068965
},
{
"name": "BenchmarkReconcile_88_vs_121/Go/batched-128-sequential",
"params": {
"B": "128",
"N": "4096",
"label": "go pure-Go N=4096 sequenced 128 times (matches what blind-rotate does)",
"path": "go-pure"
},
"status": "ok",
"iterations": 1,
"median_ns": 4696084,
"mean_ns": 4696084,
"p50_ns": 4696084,
"p95_ns": 4696084,
"p99_ns": 4696084,
"ops_per_sec": 212.94338005878942
},
{
"name": "BenchmarkReconcile_88_vs_121/Go/batched-128-sequential",
"params": {
"B": "128",
"N": "4096",
"label": "go pure-Go N=4096 sequenced 128 times (matches what blind-rotate does)",
"path": "go-pure"
},
"status": "ok",
"iterations": 10,
"median_ns": 3959250,
"mean_ns": 4072999,
"p50_ns": 3959250,
"p95_ns": 4603958,
"p99_ns": 4603958,
"ops_per_sec": 252.57308833743764
},
{
"name": "BenchmarkReconcile_88_vs_121/Metal/single-poly",
"params": {
"B": "1",
"N": "4096",
"label": "metal luxlattice single-poly N=4096 (the numerator in #121's 0.08x ratio)",
"path": "metal-luxlattice"
},
"status": "skipped",
"reason": "NotApplicable: built without -tags gpu; GPU wrapper not linked",
"iterations": 0
},
{
"name": "BenchmarkReconcile_88_vs_121/Metal/single-poly",
"params": {
"B": "1",
"N": "4096",
"label": "metal luxlattice single-poly N=4096 (the numerator in #121's 0.08x ratio)",
"path": "metal-luxlattice"
},
"status": "skipped",
"reason": "NotApplicable: built without -tags gpu; GPU wrapper not linked",
"iterations": 0
},
{
"name": "BenchmarkReconcile_88_vs_121/Metal/batched-128-fused",
"params": {
"B": "128",
"N": "4096",
"label": "metal luxlattice BatchNTT N=4096 B=128 (the #88 14.02x claim target)",
"path": "metal-luxlattice"
},
"status": "skipped",
"reason": "NotApplicable: built without -tags gpu; GPU wrapper not linked",
"iterations": 0
},
{
"name": "BenchmarkReconcile_88_vs_121/Metal/batched-128-fused",
"params": {
"B": "128",
"N": "4096",
"label": "metal luxlattice BatchNTT N=4096 B=128 (the #88 14.02x claim target)",
"path": "metal-luxlattice"
},
"status": "skipped",
"reason": "NotApplicable: built without -tags gpu; GPU wrapper not linked",
"iterations": 0
}
]
}
@@ -0,0 +1,160 @@
{
"name": "reconcile_88_121",
"host": {
"time": "2026-04-27T22:15:26Z",
"go_version": "go1.26.2",
"goos": "darwin",
"goarch": "arm64",
"num_cpu": 10,
"gomaxprocs": 10,
"cpu_brand": "Apple M1 Max",
"os_product": "macOS",
"os_version": "26.4",
"build_tags": "gpu",
"fhe_commit": "d6affbfd6dadf28aa100dcbf73c75caf61dcc539",
"lattice_commit": "d11ec53c16e7ef6d0d1fc84ea37fd285e1f1f9d2"
},
"command": "go test -test.paniconexit0 -test.bench=BenchmarkReconcile -test.benchtime=10x -test.count=1 -test.timeout=10m0s",
"cells": [
{
"name": "BenchmarkReconcile_88_vs_121/Go/single-poly",
"params": {
"B": "1",
"N": "4096",
"label": "go pure-Go single-poly N=4096 (the denominator in #121's ratio)",
"path": "go-pure"
},
"status": "ok",
"iterations": 1,
"median_ns": 152542,
"mean_ns": 152542,
"p50_ns": 152542,
"p95_ns": 152542,
"p99_ns": 152542,
"ops_per_sec": 6555.571580286085
},
{
"name": "BenchmarkReconcile_88_vs_121/Go/single-poly",
"params": {
"B": "1",
"N": "4096",
"label": "go pure-Go single-poly N=4096 (the denominator in #121's ratio)",
"path": "go-pure"
},
"status": "ok",
"iterations": 10,
"median_ns": 148083,
"mean_ns": 154358,
"p50_ns": 148083,
"p95_ns": 167166,
"p99_ns": 167166,
"ops_per_sec": 6752.969618389687
},
{
"name": "BenchmarkReconcile_88_vs_121/Go/batched-128-sequential",
"params": {
"B": "128",
"N": "4096",
"label": "go pure-Go N=4096 sequenced 128 times (matches what blind-rotate does)",
"path": "go-pure"
},
"status": "ok",
"iterations": 1,
"median_ns": 18206417,
"mean_ns": 18206417,
"p50_ns": 18206417,
"p95_ns": 18206417,
"p99_ns": 18206417,
"ops_per_sec": 54.92568911280017
},
{
"name": "BenchmarkReconcile_88_vs_121/Go/batched-128-sequential",
"params": {
"B": "128",
"N": "4096",
"label": "go pure-Go N=4096 sequenced 128 times (matches what blind-rotate does)",
"path": "go-pure"
},
"status": "ok",
"iterations": 10,
"median_ns": 13042916,
"mean_ns": 13124604,
"p50_ns": 13042916,
"p95_ns": 14971541,
"p99_ns": 14971541,
"ops_per_sec": 76.66997165357807
},
{
"name": "BenchmarkReconcile_88_vs_121/Metal/single-poly",
"params": {
"B": "1",
"N": "4096",
"backend": "Metal",
"label": "metal luxlattice single-poly N=4096 (the numerator in #121's 0.08x ratio)",
"path": "metal-luxlattice"
},
"status": "ok",
"iterations": 1,
"median_ns": 624500,
"mean_ns": 624500,
"p50_ns": 624500,
"p95_ns": 624500,
"p99_ns": 624500,
"ops_per_sec": 1601.281024819856
},
{
"name": "BenchmarkReconcile_88_vs_121/Metal/single-poly",
"params": {
"B": "1",
"N": "4096",
"backend": "Metal",
"label": "metal luxlattice single-poly N=4096 (the numerator in #121's 0.08x ratio)",
"path": "metal-luxlattice"
},
"status": "ok",
"iterations": 10,
"median_ns": 586542,
"mean_ns": 624441,
"p50_ns": 586542,
"p95_ns": 707667,
"p99_ns": 707667,
"ops_per_sec": 1704.907747441786
},
{
"name": "BenchmarkReconcile_88_vs_121/Metal/batched-128-fused",
"params": {
"B": "128",
"N": "4096",
"backend": "Metal",
"label": "metal luxlattice BatchNTT N=4096 B=128 (the #88 14.02x claim target)",
"path": "metal-luxlattice"
},
"status": "ok",
"iterations": 1,
"median_ns": 1327541,
"mean_ns": 1327541,
"p50_ns": 1327541,
"p95_ns": 1327541,
"p99_ns": 1327541,
"ops_per_sec": 753.2724036395109
},
{
"name": "BenchmarkReconcile_88_vs_121/Metal/batched-128-fused",
"params": {
"B": "128",
"N": "4096",
"backend": "Metal",
"label": "metal luxlattice BatchNTT N=4096 B=128 (the #88 14.02x claim target)",
"path": "metal-luxlattice"
},
"status": "ok",
"iterations": 10,
"median_ns": 1304458,
"mean_ns": 1339120,
"p50_ns": 1304458,
"p95_ns": 1394875,
"p99_ns": 1394875,
"ops_per_sec": 766.6019143583005
}
]
}
@@ -0,0 +1,146 @@
{
"name": "reconcile_build_state",
"host": {
"time": "2026-04-27T19:48:30Z",
"go_version": "go1.26.2",
"goos": "darwin",
"goarch": "arm64",
"num_cpu": 10,
"gomaxprocs": 10,
"cpu_brand": "Apple M1 Max",
"os_product": "macOS",
"os_version": "26.4",
"build_tags": "default",
"fhe_commit": "873ee56fed87a95794aefac5c4921955ba0c332a",
"lattice_commit": "a362b2e4d5fe6e67850e9dbb848fe9ab460e7711"
},
"command": "go test -test.paniconexit0 -test.count=1 -test.run=^$ -test.bench=^BenchmarkReconcile_ -test.benchtime=10x -test.timeout=2m0s",
"cells": [
{
"name": "BuildState/fhe-mlx-dispatch-optimized-header",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_dispatch_optimized.h"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-ntt-wrapper-source",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_ntt_wrapper.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-mlx-backend-cpp",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/mlx_backend.cpp"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-fused-kernel-source",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_dispatch_optimized.h"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-build-output",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/build-mlx/src/core/lib/math/hal/mlx/metal_ntt_bench"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/luxlattice-source",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/lattice/src/metal/metal_ntt.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/luxlattice-installed-dylib",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/install/lib/libluxlattice.1.0.0.dylib"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-dispatch-optimized-header",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_dispatch_optimized.h"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-ntt-wrapper-source",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_ntt_wrapper.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-mlx-backend-cpp",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/mlx_backend.cpp"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-fused-kernel-source",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_dispatch_optimized.h"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-build-output",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/build-mlx/src/core/lib/math/hal/mlx/metal_ntt_bench"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/luxlattice-source",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/lattice/src/metal/metal_ntt.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/luxlattice-installed-dylib",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/install/lib/libluxlattice.1.0.0.dylib"
},
"status": "ok",
"iterations": 0
}
]
}
@@ -0,0 +1,146 @@
{
"name": "reconcile_build_state",
"host": {
"time": "2026-04-27T19:51:29Z",
"go_version": "go1.26.2",
"goos": "darwin",
"goarch": "arm64",
"num_cpu": 10,
"gomaxprocs": 10,
"cpu_brand": "Apple M1 Max",
"os_product": "macOS",
"os_version": "26.4",
"build_tags": "default",
"fhe_commit": "873ee56fed87a95794aefac5c4921955ba0c332a",
"lattice_commit": "a362b2e4d5fe6e67850e9dbb848fe9ab460e7711"
},
"command": "go test -test.paniconexit0 -test.count=1 -test.run=^$ -test.bench=^BenchmarkReconcile_ -test.benchtime=20x -test.timeout=2m0s",
"cells": [
{
"name": "BuildState/fhe-mlx-dispatch-optimized-header",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_dispatch_optimized.h"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-ntt-wrapper-source",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_ntt_wrapper.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-mlx-backend-cpp",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/mlx_backend.cpp"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-fused-kernel-source",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_dispatch_optimized.h"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-build-output",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/build-mlx/src/core/lib/math/hal/mlx/metal_ntt_bench"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/luxlattice-source",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/lattice/src/metal/metal_ntt.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/luxlattice-installed-dylib",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/install/lib/libluxlattice.1.0.0.dylib"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-dispatch-optimized-header",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_dispatch_optimized.h"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-ntt-wrapper-source",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_ntt_wrapper.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-mlx-backend-cpp",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/mlx_backend.cpp"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-fused-kernel-source",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_dispatch_optimized.h"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-build-output",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/build-mlx/src/core/lib/math/hal/mlx/metal_ntt_bench"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/luxlattice-source",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/lattice/src/metal/metal_ntt.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/luxlattice-installed-dylib",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/install/lib/libluxlattice.1.0.0.dylib"
},
"status": "ok",
"iterations": 0
}
]
}
@@ -0,0 +1,146 @@
{
"name": "reconcile_build_state",
"host": {
"time": "2026-04-27T22:15:27Z",
"go_version": "go1.26.2",
"goos": "darwin",
"goarch": "arm64",
"num_cpu": 10,
"gomaxprocs": 10,
"cpu_brand": "Apple M1 Max",
"os_product": "macOS",
"os_version": "26.4",
"build_tags": "gpu",
"fhe_commit": "d6affbfd6dadf28aa100dcbf73c75caf61dcc539",
"lattice_commit": "d11ec53c16e7ef6d0d1fc84ea37fd285e1f1f9d2"
},
"command": "go test -test.paniconexit0 -test.bench=BenchmarkReconcile -test.benchtime=10x -test.count=1 -test.timeout=10m0s",
"cells": [
{
"name": "BuildState/fhe-mlx-dispatch-optimized-header",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_dispatch_optimized.h"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-ntt-wrapper-source",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_ntt_wrapper.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-mlx-backend-cpp",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/mlx_backend.cpp"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-fused-kernel-source",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_dispatch_optimized.h"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-build-output",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/build-mlx/src/core/lib/math/hal/mlx/metal_ntt_bench"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/luxlattice-source",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/lattice/src/metal/metal_ntt.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/luxlattice-installed-dylib",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/install/lib/libluxlattice.1.0.0.dylib"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-dispatch-optimized-header",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_dispatch_optimized.h"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-ntt-wrapper-source",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_ntt_wrapper.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-mlx-backend-cpp",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/mlx_backend.cpp"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-fused-kernel-source",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_dispatch_optimized.h"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/fhe-mlx-build-output",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/fhe/build-mlx/src/core/lib/math/hal/mlx/metal_ntt_bench"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/luxlattice-source",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/lattice/src/metal/metal_ntt.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "BuildState/luxlattice-installed-dylib",
"params": {
"exists": "true",
"path": "/Users/z/work/lux/cpp/install/lib/libluxlattice.1.0.0.dylib"
},
"status": "ok",
"iterations": 0
}
]
}
@@ -0,0 +1,85 @@
{
"name": "reconcile_zoo",
"host": {
"time": "2026-04-27T19:48:25Z",
"go_version": "go1.26.2",
"goos": "darwin",
"goarch": "arm64",
"num_cpu": 10,
"gomaxprocs": 10,
"cpu_brand": "Apple M1 Max",
"os_product": "macOS",
"os_version": "26.4",
"build_tags": "default",
"fhe_commit": "873ee56fed87a95794aefac5c4921955ba0c332a",
"lattice_commit": "a362b2e4d5fe6e67850e9dbb848fe9ab460e7711"
},
"command": "go test -test.paniconexit0 -test.timeout=10m0s -test.count=1 -test.run=^$ -test.bench=^BenchmarkReconcile_MetalNTTZoo$ -test.benchtime=1x",
"cells": [
{
"name": "MetalNTTZoo/luxlattice",
"params": {
"exists": "true",
"name": "luxlattice",
"notes": "BatchNTT path SIGSEGVs at every (N,B) tested per #121; single-poly works but is 12x slower than Go.",
"purpose": "Generic Montgomery-form NTT for ring.SubRing dispatch (the #121 measurement target).",
"reachable": "yes (via libluxlattice + luxfi/lattice/v7/gpu cgo)",
"source_path": "/Users/z/work/lux/cpp/lattice/src/metal/metal_ntt.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/fhe-mlx-backend",
"params": {
"exists": "true",
"name": "fhe-mlx-backend",
"notes": "This is the path that produced #88's claimed 14.02x at N=4096 B=128 fused. The fused kernel source is in metal_dispatch_optimized.h::get_fused_ntt_kernel_source. NOT measurable from Go today.",
"purpose": "F-Chain MLX backend NTT wrapper; routes to NTTMetalDispatcherOptimized (custom Metal kernels with fused log(N) stages, shared-memory butterflies).",
"reachable": "no (FHEgpu/FHEmetal libs not linked into lux/fhe Go module)",
"source_path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_ntt_wrapper.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/crypto-gpukit",
"params": {
"exists": "true",
"name": "crypto-gpukit",
"notes": "Independent implementation -- not the same code path as either #88 or #121.",
"purpose": "Generic NTT driver for gpukit; used by other crypto primitives that need NTT (KZG, IPA, etc.).",
"reachable": "no (separate library, not linked into lux/fhe)",
"source_path": "/Users/z/work/lux/cpp/crypto/gpukit/gpu/metal/ntt_driver.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/metal-tests-test-ntt",
"params": {
"exists": "true",
"name": "metal-tests-test-ntt",
"notes": "Contains a minimal reference implementation used to validate the kernel under a build harness. Not a runtime path.",
"purpose": "Standalone Metal NTT unit test; doc-only, not a dispatcher.",
"reachable": "no (test target only)",
"source_path": "/Users/z/work/lux/cpp/metal/tests/test_ntt.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/cevm-metal",
"params": {
"exists": "true",
"name": "cevm-metal",
"notes": "The §19E hypothesis that #88 might have measured cevm-side Metal NTT is FALSIFIED -- the cevm metal directory contains zero NTT code (verified by directory listing 2026-04-27).",
"purpose": "EVM-execution Metal kernels (block-STM, BLS, keccak256, tx_validate). NO NTT.",
"reachable": "n/a -- no NTT here",
"source_path": "/Users/z/work/lux/cpp/cevm/lib/evm/gpu/metal/"
},
"status": "ok",
"iterations": 0
}
]
}
@@ -0,0 +1,150 @@
{
"name": "reconcile_zoo",
"host": {
"time": "2026-04-27T19:48:30Z",
"go_version": "go1.26.2",
"goos": "darwin",
"goarch": "arm64",
"num_cpu": 10,
"gomaxprocs": 10,
"cpu_brand": "Apple M1 Max",
"os_product": "macOS",
"os_version": "26.4",
"build_tags": "default",
"fhe_commit": "873ee56fed87a95794aefac5c4921955ba0c332a",
"lattice_commit": "a362b2e4d5fe6e67850e9dbb848fe9ab460e7711"
},
"command": "go test -test.paniconexit0 -test.count=1 -test.run=^$ -test.bench=^BenchmarkReconcile_ -test.benchtime=10x -test.timeout=2m0s",
"cells": [
{
"name": "MetalNTTZoo/luxlattice",
"params": {
"exists": "true",
"name": "luxlattice",
"notes": "BatchNTT path SIGSEGVs at every (N,B) tested per #121; single-poly works but is 12x slower than Go.",
"purpose": "Generic Montgomery-form NTT for ring.SubRing dispatch (the #121 measurement target).",
"reachable": "yes (via libluxlattice + luxfi/lattice/v7/gpu cgo)",
"source_path": "/Users/z/work/lux/cpp/lattice/src/metal/metal_ntt.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/fhe-mlx-backend",
"params": {
"exists": "true",
"name": "fhe-mlx-backend",
"notes": "This is the path that produced #88's claimed 14.02x at N=4096 B=128 fused. The fused kernel source is in metal_dispatch_optimized.h::get_fused_ntt_kernel_source. NOT measurable from Go today.",
"purpose": "F-Chain MLX backend NTT wrapper; routes to NTTMetalDispatcherOptimized (custom Metal kernels with fused log(N) stages, shared-memory butterflies).",
"reachable": "no (FHEgpu/FHEmetal libs not linked into lux/fhe Go module)",
"source_path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_ntt_wrapper.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/crypto-gpukit",
"params": {
"exists": "true",
"name": "crypto-gpukit",
"notes": "Independent implementation -- not the same code path as either #88 or #121.",
"purpose": "Generic NTT driver for gpukit; used by other crypto primitives that need NTT (KZG, IPA, etc.).",
"reachable": "no (separate library, not linked into lux/fhe)",
"source_path": "/Users/z/work/lux/cpp/crypto/gpukit/gpu/metal/ntt_driver.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/metal-tests-test-ntt",
"params": {
"exists": "true",
"name": "metal-tests-test-ntt",
"notes": "Contains a minimal reference implementation used to validate the kernel under a build harness. Not a runtime path.",
"purpose": "Standalone Metal NTT unit test; doc-only, not a dispatcher.",
"reachable": "no (test target only)",
"source_path": "/Users/z/work/lux/cpp/metal/tests/test_ntt.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/cevm-metal",
"params": {
"exists": "true",
"name": "cevm-metal",
"notes": "The §19E hypothesis that #88 might have measured cevm-side Metal NTT is FALSIFIED -- the cevm metal directory contains zero NTT code (verified by directory listing 2026-04-27).",
"purpose": "EVM-execution Metal kernels (block-STM, BLS, keccak256, tx_validate). NO NTT.",
"reachable": "n/a -- no NTT here",
"source_path": "/Users/z/work/lux/cpp/cevm/lib/evm/gpu/metal/"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/luxlattice",
"params": {
"exists": "true",
"name": "luxlattice",
"notes": "BatchNTT path SIGSEGVs at every (N,B) tested per #121; single-poly works but is 12x slower than Go.",
"purpose": "Generic Montgomery-form NTT for ring.SubRing dispatch (the #121 measurement target).",
"reachable": "yes (via libluxlattice + luxfi/lattice/v7/gpu cgo)",
"source_path": "/Users/z/work/lux/cpp/lattice/src/metal/metal_ntt.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/fhe-mlx-backend",
"params": {
"exists": "true",
"name": "fhe-mlx-backend",
"notes": "This is the path that produced #88's claimed 14.02x at N=4096 B=128 fused. The fused kernel source is in metal_dispatch_optimized.h::get_fused_ntt_kernel_source. NOT measurable from Go today.",
"purpose": "F-Chain MLX backend NTT wrapper; routes to NTTMetalDispatcherOptimized (custom Metal kernels with fused log(N) stages, shared-memory butterflies).",
"reachable": "no (FHEgpu/FHEmetal libs not linked into lux/fhe Go module)",
"source_path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_ntt_wrapper.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/crypto-gpukit",
"params": {
"exists": "true",
"name": "crypto-gpukit",
"notes": "Independent implementation -- not the same code path as either #88 or #121.",
"purpose": "Generic NTT driver for gpukit; used by other crypto primitives that need NTT (KZG, IPA, etc.).",
"reachable": "no (separate library, not linked into lux/fhe)",
"source_path": "/Users/z/work/lux/cpp/crypto/gpukit/gpu/metal/ntt_driver.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/metal-tests-test-ntt",
"params": {
"exists": "true",
"name": "metal-tests-test-ntt",
"notes": "Contains a minimal reference implementation used to validate the kernel under a build harness. Not a runtime path.",
"purpose": "Standalone Metal NTT unit test; doc-only, not a dispatcher.",
"reachable": "no (test target only)",
"source_path": "/Users/z/work/lux/cpp/metal/tests/test_ntt.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/cevm-metal",
"params": {
"exists": "true",
"name": "cevm-metal",
"notes": "The §19E hypothesis that #88 might have measured cevm-side Metal NTT is FALSIFIED -- the cevm metal directory contains zero NTT code (verified by directory listing 2026-04-27).",
"purpose": "EVM-execution Metal kernels (block-STM, BLS, keccak256, tx_validate). NO NTT.",
"reachable": "n/a -- no NTT here",
"source_path": "/Users/z/work/lux/cpp/cevm/lib/evm/gpu/metal/"
},
"status": "ok",
"iterations": 0
}
]
}
@@ -0,0 +1,150 @@
{
"name": "reconcile_zoo",
"host": {
"time": "2026-04-27T19:51:28Z",
"go_version": "go1.26.2",
"goos": "darwin",
"goarch": "arm64",
"num_cpu": 10,
"gomaxprocs": 10,
"cpu_brand": "Apple M1 Max",
"os_product": "macOS",
"os_version": "26.4",
"build_tags": "default",
"fhe_commit": "873ee56fed87a95794aefac5c4921955ba0c332a",
"lattice_commit": "a362b2e4d5fe6e67850e9dbb848fe9ab460e7711"
},
"command": "go test -test.paniconexit0 -test.count=1 -test.run=^$ -test.bench=^BenchmarkReconcile_ -test.benchtime=20x -test.timeout=2m0s",
"cells": [
{
"name": "MetalNTTZoo/luxlattice",
"params": {
"exists": "true",
"name": "luxlattice",
"notes": "BatchNTT path SIGSEGVs at every (N,B) tested per #121; single-poly works but is 12x slower than Go.",
"purpose": "Generic Montgomery-form NTT for ring.SubRing dispatch (the #121 measurement target).",
"reachable": "yes (via libluxlattice + luxfi/lattice/v7/gpu cgo)",
"source_path": "/Users/z/work/lux/cpp/lattice/src/metal/metal_ntt.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/fhe-mlx-backend",
"params": {
"exists": "true",
"name": "fhe-mlx-backend",
"notes": "This is the path that produced #88's claimed 14.02x at N=4096 B=128 fused. The fused kernel source is in metal_dispatch_optimized.h::get_fused_ntt_kernel_source. NOT measurable from Go today.",
"purpose": "F-Chain MLX backend NTT wrapper; routes to NTTMetalDispatcherOptimized (custom Metal kernels with fused log(N) stages, shared-memory butterflies).",
"reachable": "no (FHEgpu/FHEmetal libs not linked into lux/fhe Go module)",
"source_path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_ntt_wrapper.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/crypto-gpukit",
"params": {
"exists": "true",
"name": "crypto-gpukit",
"notes": "Independent implementation -- not the same code path as either #88 or #121.",
"purpose": "Generic NTT driver for gpukit; used by other crypto primitives that need NTT (KZG, IPA, etc.).",
"reachable": "no (separate library, not linked into lux/fhe)",
"source_path": "/Users/z/work/lux/cpp/crypto/gpukit/gpu/metal/ntt_driver.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/metal-tests-test-ntt",
"params": {
"exists": "true",
"name": "metal-tests-test-ntt",
"notes": "Contains a minimal reference implementation used to validate the kernel under a build harness. Not a runtime path.",
"purpose": "Standalone Metal NTT unit test; doc-only, not a dispatcher.",
"reachable": "no (test target only)",
"source_path": "/Users/z/work/lux/cpp/metal/tests/test_ntt.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/cevm-metal",
"params": {
"exists": "true",
"name": "cevm-metal",
"notes": "The §19E hypothesis that #88 might have measured cevm-side Metal NTT is FALSIFIED -- the cevm metal directory contains zero NTT code (verified by directory listing 2026-04-27).",
"purpose": "EVM-execution Metal kernels (block-STM, BLS, keccak256, tx_validate). NO NTT.",
"reachable": "n/a -- no NTT here",
"source_path": "/Users/z/work/lux/cpp/cevm/lib/evm/gpu/metal/"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/luxlattice",
"params": {
"exists": "true",
"name": "luxlattice",
"notes": "BatchNTT path SIGSEGVs at every (N,B) tested per #121; single-poly works but is 12x slower than Go.",
"purpose": "Generic Montgomery-form NTT for ring.SubRing dispatch (the #121 measurement target).",
"reachable": "yes (via libluxlattice + luxfi/lattice/v7/gpu cgo)",
"source_path": "/Users/z/work/lux/cpp/lattice/src/metal/metal_ntt.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/fhe-mlx-backend",
"params": {
"exists": "true",
"name": "fhe-mlx-backend",
"notes": "This is the path that produced #88's claimed 14.02x at N=4096 B=128 fused. The fused kernel source is in metal_dispatch_optimized.h::get_fused_ntt_kernel_source. NOT measurable from Go today.",
"purpose": "F-Chain MLX backend NTT wrapper; routes to NTTMetalDispatcherOptimized (custom Metal kernels with fused log(N) stages, shared-memory butterflies).",
"reachable": "no (FHEgpu/FHEmetal libs not linked into lux/fhe Go module)",
"source_path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_ntt_wrapper.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/crypto-gpukit",
"params": {
"exists": "true",
"name": "crypto-gpukit",
"notes": "Independent implementation -- not the same code path as either #88 or #121.",
"purpose": "Generic NTT driver for gpukit; used by other crypto primitives that need NTT (KZG, IPA, etc.).",
"reachable": "no (separate library, not linked into lux/fhe)",
"source_path": "/Users/z/work/lux/cpp/crypto/gpukit/gpu/metal/ntt_driver.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/metal-tests-test-ntt",
"params": {
"exists": "true",
"name": "metal-tests-test-ntt",
"notes": "Contains a minimal reference implementation used to validate the kernel under a build harness. Not a runtime path.",
"purpose": "Standalone Metal NTT unit test; doc-only, not a dispatcher.",
"reachable": "no (test target only)",
"source_path": "/Users/z/work/lux/cpp/metal/tests/test_ntt.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/cevm-metal",
"params": {
"exists": "true",
"name": "cevm-metal",
"notes": "The §19E hypothesis that #88 might have measured cevm-side Metal NTT is FALSIFIED -- the cevm metal directory contains zero NTT code (verified by directory listing 2026-04-27).",
"purpose": "EVM-execution Metal kernels (block-STM, BLS, keccak256, tx_validate). NO NTT.",
"reachable": "n/a -- no NTT here",
"source_path": "/Users/z/work/lux/cpp/cevm/lib/evm/gpu/metal/"
},
"status": "ok",
"iterations": 0
}
]
}
@@ -0,0 +1,150 @@
{
"name": "reconcile_zoo",
"host": {
"time": "2026-04-27T19:54:54Z",
"go_version": "go1.26.2",
"goos": "darwin",
"goarch": "arm64",
"num_cpu": 10,
"gomaxprocs": 10,
"cpu_brand": "Apple M1 Max",
"os_product": "macOS",
"os_version": "26.4",
"build_tags": "default",
"fhe_commit": "873ee56fed87a95794aefac5c4921955ba0c332a",
"lattice_commit": "a362b2e4d5fe6e67850e9dbb848fe9ab460e7711"
},
"command": "go test -test.paniconexit0 -test.count=1 -test.run=^$ -test.bench=^BenchmarkReconcile_88_vs_121$|^BenchmarkReconcile_MetalNTTZoo$|^BenchmarkTFHE_TRLWE_Add_CPU$|^BenchmarkThreshold_ShareAggregate_CPU$ -test.benchtime=10x -test.timeout=2m0s",
"cells": [
{
"name": "MetalNTTZoo/luxlattice",
"params": {
"exists": "true",
"name": "luxlattice",
"notes": "BatchNTT path SIGSEGVs at every (N,B) tested per #121; single-poly works but is 12x slower than Go.",
"purpose": "Generic Montgomery-form NTT for ring.SubRing dispatch (the #121 measurement target).",
"reachable": "yes (via libluxlattice + luxfi/lattice/v7/gpu cgo)",
"source_path": "/Users/z/work/lux/cpp/lattice/src/metal/metal_ntt.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/fhe-mlx-backend",
"params": {
"exists": "true",
"name": "fhe-mlx-backend",
"notes": "This is the path that produced #88's claimed 14.02x at N=4096 B=128 fused. The fused kernel source is in metal_dispatch_optimized.h::get_fused_ntt_kernel_source. NOT measurable from Go today.",
"purpose": "F-Chain MLX backend NTT wrapper; routes to NTTMetalDispatcherOptimized (custom Metal kernels with fused log(N) stages, shared-memory butterflies).",
"reachable": "no (FHEgpu/FHEmetal libs not linked into lux/fhe Go module)",
"source_path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_ntt_wrapper.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/crypto-gpukit",
"params": {
"exists": "true",
"name": "crypto-gpukit",
"notes": "Independent implementation -- not the same code path as either #88 or #121.",
"purpose": "Generic NTT driver for gpukit; used by other crypto primitives that need NTT (KZG, IPA, etc.).",
"reachable": "no (separate library, not linked into lux/fhe)",
"source_path": "/Users/z/work/lux/cpp/crypto/gpukit/gpu/metal/ntt_driver.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/metal-tests-test-ntt",
"params": {
"exists": "true",
"name": "metal-tests-test-ntt",
"notes": "Contains a minimal reference implementation used to validate the kernel under a build harness. Not a runtime path.",
"purpose": "Standalone Metal NTT unit test; doc-only, not a dispatcher.",
"reachable": "no (test target only)",
"source_path": "/Users/z/work/lux/cpp/metal/tests/test_ntt.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/cevm-metal",
"params": {
"exists": "true",
"name": "cevm-metal",
"notes": "The §19E hypothesis that #88 might have measured cevm-side Metal NTT is FALSIFIED -- the cevm metal directory contains zero NTT code (verified by directory listing 2026-04-27).",
"purpose": "EVM-execution Metal kernels (block-STM, BLS, keccak256, tx_validate). NO NTT.",
"reachable": "n/a -- no NTT here",
"source_path": "/Users/z/work/lux/cpp/cevm/lib/evm/gpu/metal/"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/luxlattice",
"params": {
"exists": "true",
"name": "luxlattice",
"notes": "BatchNTT path SIGSEGVs at every (N,B) tested per #121; single-poly works but is 12x slower than Go.",
"purpose": "Generic Montgomery-form NTT for ring.SubRing dispatch (the #121 measurement target).",
"reachable": "yes (via libluxlattice + luxfi/lattice/v7/gpu cgo)",
"source_path": "/Users/z/work/lux/cpp/lattice/src/metal/metal_ntt.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/fhe-mlx-backend",
"params": {
"exists": "true",
"name": "fhe-mlx-backend",
"notes": "This is the path that produced #88's claimed 14.02x at N=4096 B=128 fused. The fused kernel source is in metal_dispatch_optimized.h::get_fused_ntt_kernel_source. NOT measurable from Go today.",
"purpose": "F-Chain MLX backend NTT wrapper; routes to NTTMetalDispatcherOptimized (custom Metal kernels with fused log(N) stages, shared-memory butterflies).",
"reachable": "no (FHEgpu/FHEmetal libs not linked into lux/fhe Go module)",
"source_path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_ntt_wrapper.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/crypto-gpukit",
"params": {
"exists": "true",
"name": "crypto-gpukit",
"notes": "Independent implementation -- not the same code path as either #88 or #121.",
"purpose": "Generic NTT driver for gpukit; used by other crypto primitives that need NTT (KZG, IPA, etc.).",
"reachable": "no (separate library, not linked into lux/fhe)",
"source_path": "/Users/z/work/lux/cpp/crypto/gpukit/gpu/metal/ntt_driver.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/metal-tests-test-ntt",
"params": {
"exists": "true",
"name": "metal-tests-test-ntt",
"notes": "Contains a minimal reference implementation used to validate the kernel under a build harness. Not a runtime path.",
"purpose": "Standalone Metal NTT unit test; doc-only, not a dispatcher.",
"reachable": "no (test target only)",
"source_path": "/Users/z/work/lux/cpp/metal/tests/test_ntt.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/cevm-metal",
"params": {
"exists": "true",
"name": "cevm-metal",
"notes": "The §19E hypothesis that #88 might have measured cevm-side Metal NTT is FALSIFIED -- the cevm metal directory contains zero NTT code (verified by directory listing 2026-04-27).",
"purpose": "EVM-execution Metal kernels (block-STM, BLS, keccak256, tx_validate). NO NTT.",
"reachable": "n/a -- no NTT here",
"source_path": "/Users/z/work/lux/cpp/cevm/lib/evm/gpu/metal/"
},
"status": "ok",
"iterations": 0
}
]
}
@@ -0,0 +1,150 @@
{
"name": "reconcile_zoo",
"host": {
"time": "2026-04-27T22:15:26Z",
"go_version": "go1.26.2",
"goos": "darwin",
"goarch": "arm64",
"num_cpu": 10,
"gomaxprocs": 10,
"cpu_brand": "Apple M1 Max",
"os_product": "macOS",
"os_version": "26.4",
"build_tags": "gpu",
"fhe_commit": "d6affbfd6dadf28aa100dcbf73c75caf61dcc539",
"lattice_commit": "d11ec53c16e7ef6d0d1fc84ea37fd285e1f1f9d2"
},
"command": "go test -test.paniconexit0 -test.bench=BenchmarkReconcile -test.benchtime=10x -test.count=1 -test.timeout=10m0s",
"cells": [
{
"name": "MetalNTTZoo/luxlattice",
"params": {
"exists": "true",
"name": "luxlattice",
"notes": "BatchNTT path SIGSEGVs at every (N,B) tested per #121; single-poly works but is 12x slower than Go.",
"purpose": "Generic Montgomery-form NTT for ring.SubRing dispatch (the #121 measurement target).",
"reachable": "yes (via libluxlattice + luxfi/lattice/v7/gpu cgo)",
"source_path": "/Users/z/work/lux/cpp/lattice/src/metal/metal_ntt.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/fhe-mlx-backend",
"params": {
"exists": "true",
"name": "fhe-mlx-backend",
"notes": "This is the path that produced #88's claimed 14.02x at N=4096 B=128 fused. The fused kernel source is in metal_dispatch_optimized.h::get_fused_ntt_kernel_source. NOT measurable from Go today.",
"purpose": "F-Chain MLX backend NTT wrapper; routes to NTTMetalDispatcherOptimized (custom Metal kernels with fused log(N) stages, shared-memory butterflies).",
"reachable": "no (FHEgpu/FHEmetal libs not linked into lux/fhe Go module)",
"source_path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_ntt_wrapper.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/crypto-gpukit",
"params": {
"exists": "true",
"name": "crypto-gpukit",
"notes": "Independent implementation -- not the same code path as either #88 or #121.",
"purpose": "Generic NTT driver for gpukit; used by other crypto primitives that need NTT (KZG, IPA, etc.).",
"reachable": "no (separate library, not linked into lux/fhe)",
"source_path": "/Users/z/work/lux/cpp/crypto/gpukit/gpu/metal/ntt_driver.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/metal-tests-test-ntt",
"params": {
"exists": "true",
"name": "metal-tests-test-ntt",
"notes": "Contains a minimal reference implementation used to validate the kernel under a build harness. Not a runtime path.",
"purpose": "Standalone Metal NTT unit test; doc-only, not a dispatcher.",
"reachable": "no (test target only)",
"source_path": "/Users/z/work/lux/cpp/metal/tests/test_ntt.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/cevm-metal",
"params": {
"exists": "true",
"name": "cevm-metal",
"notes": "The §19E hypothesis that #88 might have measured cevm-side Metal NTT is FALSIFIED -- the cevm metal directory contains zero NTT code (verified by directory listing 2026-04-27).",
"purpose": "EVM-execution Metal kernels (block-STM, BLS, keccak256, tx_validate). NO NTT.",
"reachable": "n/a -- no NTT here",
"source_path": "/Users/z/work/lux/cpp/cevm/lib/evm/gpu/metal/"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/luxlattice",
"params": {
"exists": "true",
"name": "luxlattice",
"notes": "BatchNTT path SIGSEGVs at every (N,B) tested per #121; single-poly works but is 12x slower than Go.",
"purpose": "Generic Montgomery-form NTT for ring.SubRing dispatch (the #121 measurement target).",
"reachable": "yes (via libluxlattice + luxfi/lattice/v7/gpu cgo)",
"source_path": "/Users/z/work/lux/cpp/lattice/src/metal/metal_ntt.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/fhe-mlx-backend",
"params": {
"exists": "true",
"name": "fhe-mlx-backend",
"notes": "This is the path that produced #88's claimed 14.02x at N=4096 B=128 fused. The fused kernel source is in metal_dispatch_optimized.h::get_fused_ntt_kernel_source. NOT measurable from Go today.",
"purpose": "F-Chain MLX backend NTT wrapper; routes to NTTMetalDispatcherOptimized (custom Metal kernels with fused log(N) stages, shared-memory butterflies).",
"reachable": "no (FHEgpu/FHEmetal libs not linked into lux/fhe Go module)",
"source_path": "/Users/z/work/lux/cpp/fhe/src/core/lib/math/hal/mlx/metal_ntt_wrapper.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/crypto-gpukit",
"params": {
"exists": "true",
"name": "crypto-gpukit",
"notes": "Independent implementation -- not the same code path as either #88 or #121.",
"purpose": "Generic NTT driver for gpukit; used by other crypto primitives that need NTT (KZG, IPA, etc.).",
"reachable": "no (separate library, not linked into lux/fhe)",
"source_path": "/Users/z/work/lux/cpp/crypto/gpukit/gpu/metal/ntt_driver.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/metal-tests-test-ntt",
"params": {
"exists": "true",
"name": "metal-tests-test-ntt",
"notes": "Contains a minimal reference implementation used to validate the kernel under a build harness. Not a runtime path.",
"purpose": "Standalone Metal NTT unit test; doc-only, not a dispatcher.",
"reachable": "no (test target only)",
"source_path": "/Users/z/work/lux/cpp/metal/tests/test_ntt.mm"
},
"status": "ok",
"iterations": 0
},
{
"name": "MetalNTTZoo/cevm-metal",
"params": {
"exists": "true",
"name": "cevm-metal",
"notes": "The §19E hypothesis that #88 might have measured cevm-side Metal NTT is FALSIFIED -- the cevm metal directory contains zero NTT code (verified by directory listing 2026-04-27).",
"purpose": "EVM-execution Metal kernels (block-STM, BLS, keccak256, tx_validate). NO NTT.",
"reachable": "n/a -- no NTT here",
"source_path": "/Users/z/work/lux/cpp/cevm/lib/evm/gpu/metal/"
},
"status": "ok",
"iterations": 0
}
]
}
@@ -0,0 +1,86 @@
{
"name": "tfhe_primitives",
"host": {
"time": "2026-04-27T19:49:46Z",
"go_version": "go1.26.2",
"goos": "darwin",
"goarch": "arm64",
"num_cpu": 10,
"gomaxprocs": 10,
"cpu_brand": "Apple M1 Max",
"os_product": "macOS",
"os_version": "26.4",
"build_tags": "default",
"fhe_commit": "873ee56fed87a95794aefac5c4921955ba0c332a",
"lattice_commit": "a362b2e4d5fe6e67850e9dbb848fe9ab460e7711"
},
"command": "go test -test.paniconexit0 -test.count=1 -test.run=^$ -test.bench=^BenchmarkTFHE_TRLWE_Add_CPU$|^BenchmarkTFHE_TRLWE_ExternalProduct_CPU$ -test.benchtime=10x -test.timeout=2m0s",
"cells": [
{
"name": "TRLWE_Add/CPU",
"params": {
"N": "2048",
"backend": "CPU (pure Go)",
"primitive": "trlwe_add"
},
"status": "ok",
"iterations": 1,
"median_ns": 1292,
"mean_ns": 1292,
"p50_ns": 1292,
"p95_ns": 1292,
"p99_ns": 1292,
"ops_per_sec": 773993.8080495356
},
{
"name": "TRLWE_Add/CPU",
"params": {
"N": "2048",
"backend": "CPU (pure Go)",
"primitive": "trlwe_add"
},
"status": "ok",
"iterations": 10,
"median_ns": 791,
"mean_ns": 883,
"p50_ns": 791,
"p95_ns": 833,
"p99_ns": 833,
"ops_per_sec": 1264222.5031605563
},
{
"name": "TRLWE_ExternalProduct/CPU",
"params": {
"N": "2048",
"backend": "CPU (pure Go)",
"primitive": "trlwe_external_product",
"scope": "NTT+pointwise+INTT"
},
"status": "ok",
"iterations": 1,
"median_ns": 31208,
"mean_ns": 31208,
"p50_ns": 31208,
"p95_ns": 31208,
"p99_ns": 31208,
"ops_per_sec": 32043.06588054345
},
{
"name": "TRLWE_ExternalProduct/CPU",
"params": {
"N": "2048",
"backend": "CPU (pure Go)",
"primitive": "trlwe_external_product",
"scope": "NTT+pointwise+INTT"
},
"status": "ok",
"iterations": 10,
"median_ns": 28416,
"mean_ns": 29687,
"p50_ns": 28416,
"p95_ns": 32416,
"p99_ns": 32416,
"ops_per_sec": 35191.44144144144
}
]
}
@@ -0,0 +1,186 @@
{
"name": "tfhe_primitives",
"host": {
"time": "2026-04-27T19:51:24Z",
"go_version": "go1.26.2",
"goos": "darwin",
"goarch": "arm64",
"num_cpu": 10,
"gomaxprocs": 10,
"cpu_brand": "Apple M1 Max",
"os_product": "macOS",
"os_version": "26.4",
"build_tags": "default",
"fhe_commit": "873ee56fed87a95794aefac5c4921955ba0c332a",
"lattice_commit": "a362b2e4d5fe6e67850e9dbb848fe9ab460e7711"
},
"command": "go test -test.paniconexit0 -test.count=1 -test.run=^$ -test.bench=^BenchmarkTFHE_TRLWE_|^BenchmarkTFHE_LWE_|^BenchmarkTFHE_KeySwitch_Metal|^BenchmarkTFHE_BlindRotation_Metal|^BenchmarkTFHE_SampleExtract_Metal|^BenchmarkTFHE_ProgrammableBootstrap_Metal -test.benchtime=10x -test.timeout=2m0s",
"cells": [
{
"name": "LWE_Add/CPU",
"params": {
"backend": "CPU (pure Go)",
"primitive": "lwe_add"
},
"status": "skipped",
"reason": "NotApplicable: rlwe.Parameters / RingQ are unexported on fhe.Parameters; LWE add is internal to Evaluator.addCiphertexts and not bench-exposed",
"iterations": 0
},
{
"name": "LWE_Add/Metal",
"params": {
"backend": "CPU (pure Go)",
"primitive": "lwe_add"
},
"status": "skipped",
"reason": "NotApplicable: lattice gpu wrapper exposes NTT/poly-mul, not LWE-tuple add (lives in luxcpp/fhe mlx backend, not exposed via lux/fhe cgo)",
"iterations": 0
},
{
"name": "LWE_ScalarMul/CPU",
"params": {
"backend": "CPU (pure Go)",
"primitive": "lwe_scalar_mul"
},
"status": "skipped",
"reason": "NotApplicable: rlwe.Parameters unexported on fhe.Parameters; scalar mul not exposed",
"iterations": 0
},
{
"name": "LWE_ScalarMul/Metal",
"params": {
"backend": "CPU (pure Go)",
"primitive": "lwe_scalar_mul"
},
"status": "skipped",
"reason": "NotApplicable: gpu wrapper has PolyScalarMul on full poly arrays only, not LWE tuple semantics",
"iterations": 0
},
{
"name": "TRLWE_Add/CPU",
"params": {
"N": "2048",
"backend": "CPU (pure Go)",
"primitive": "trlwe_add"
},
"status": "ok",
"iterations": 1,
"median_ns": 1292,
"mean_ns": 1292,
"p50_ns": 1292,
"p95_ns": 1292,
"p99_ns": 1292,
"ops_per_sec": 773993.8080495356
},
{
"name": "TRLWE_Add/CPU",
"params": {
"N": "2048",
"backend": "CPU (pure Go)",
"primitive": "trlwe_add"
},
"status": "ok",
"iterations": 10,
"median_ns": 791,
"mean_ns": 808,
"p50_ns": 791,
"p95_ns": 833,
"p99_ns": 833,
"ops_per_sec": 1264222.5031605563
},
{
"name": "TRLWE_Add/Metal",
"params": {
"backend": "CPU (pure Go)",
"primitive": "trlwe_add"
},
"status": "skipped",
"reason": "NotApplicable: built without -tags gpu; GPU wrapper not linked",
"iterations": 0
},
{
"name": "TRLWE_ExternalProduct/CPU",
"params": {
"N": "2048",
"backend": "CPU (pure Go)",
"primitive": "trlwe_external_product",
"scope": "NTT+pointwise+INTT"
},
"status": "ok",
"iterations": 1,
"median_ns": 29417,
"mean_ns": 29417,
"p50_ns": 29417,
"p95_ns": 29417,
"p99_ns": 29417,
"ops_per_sec": 33993.94907706428
},
{
"name": "TRLWE_ExternalProduct/CPU",
"params": {
"N": "2048",
"backend": "CPU (pure Go)",
"primitive": "trlwe_external_product",
"scope": "NTT+pointwise+INTT"
},
"status": "ok",
"iterations": 10,
"median_ns": 28542,
"mean_ns": 28966,
"p50_ns": 28542,
"p95_ns": 30583,
"p99_ns": 30583,
"ops_per_sec": 35036.08716978488
},
{
"name": "TRLWE_ExternalProduct/Metal",
"params": {
"backend": "CPU (pure Go)",
"primitive": "trlwe_external_product"
},
"status": "skipped",
"reason": "NotApplicable: fused external product lives in luxcpp/fhe (FHEgpu/FHEmetal libs), not exposed to lux/fhe via cgo",
"iterations": 0
},
{
"name": "BlindRotation/Metal",
"params": {
"backend": "CPU (pure Go)",
"primitive": "blind_rotation"
},
"status": "skipped",
"reason": "NotApplicable: blind-rotate is the G3 blocker per fhe/policy/PERFORMANCE.md -- no GPU dispatch wired through Evaluator.bootstrap",
"iterations": 0
},
{
"name": "SampleExtract/Metal",
"params": {
"backend": "CPU (pure Go)",
"primitive": "sample_extraction"
},
"status": "skipped",
"reason": "NotApplicable: sample-extract internal to Evaluator.sampleExtractAndModSwitch -- not bench-isolated",
"iterations": 0
},
{
"name": "KeySwitch/Metal",
"params": {
"backend": "CPU (pure Go)",
"primitive": "key_switching"
},
"status": "skipped",
"reason": "NotApplicable: key-switch in lattice/core/rlwe.Evaluator -- not routed through gpu wrapper",
"iterations": 0
},
{
"name": "ProgrammableBootstrap/Metal",
"params": {
"backend": "CPU (pure Go)",
"primitive": "programmable_bootstrap"
},
"status": "skipped",
"reason": "NotApplicable: PBS = blind-rotate + sample-extract + key-switch -- all G3-blocked per fhe/policy/PERFORMANCE.md",
"iterations": 0
}
]
}
@@ -0,0 +1,52 @@
{
"name": "tfhe_primitives",
"host": {
"time": "2026-04-27T19:54:54Z",
"go_version": "go1.26.2",
"goos": "darwin",
"goarch": "arm64",
"num_cpu": 10,
"gomaxprocs": 10,
"cpu_brand": "Apple M1 Max",
"os_product": "macOS",
"os_version": "26.4",
"build_tags": "default",
"fhe_commit": "873ee56fed87a95794aefac5c4921955ba0c332a",
"lattice_commit": "a362b2e4d5fe6e67850e9dbb848fe9ab460e7711"
},
"command": "go test -test.paniconexit0 -test.count=1 -test.run=^$ -test.bench=^BenchmarkReconcile_88_vs_121$|^BenchmarkReconcile_MetalNTTZoo$|^BenchmarkTFHE_TRLWE_Add_CPU$|^BenchmarkThreshold_ShareAggregate_CPU$ -test.benchtime=10x -test.timeout=2m0s",
"cells": [
{
"name": "TRLWE_Add/CPU",
"params": {
"N": "2048",
"backend": "CPU (pure Go)",
"primitive": "trlwe_add"
},
"status": "ok",
"iterations": 1,
"median_ns": 2000,
"mean_ns": 2000,
"p50_ns": 2000,
"p95_ns": 2000,
"p99_ns": 2000,
"ops_per_sec": 500000
},
{
"name": "TRLWE_Add/CPU",
"params": {
"N": "2048",
"backend": "CPU (pure Go)",
"primitive": "trlwe_add"
},
"status": "ok",
"iterations": 10,
"median_ns": 750,
"mean_ns": 833,
"p50_ns": 750,
"p95_ns": 791,
"p99_ns": 791,
"ops_per_sec": 1333333.3333333333
}
]
}
@@ -0,0 +1,124 @@
{
"name": "threshold",
"host": {
"time": "2026-04-27T19:49:34Z",
"go_version": "go1.26.2",
"goos": "darwin",
"goarch": "arm64",
"num_cpu": 10,
"gomaxprocs": 10,
"cpu_brand": "Apple M1 Max",
"os_product": "macOS",
"os_version": "26.4",
"build_tags": "default",
"fhe_commit": "873ee56fed87a95794aefac5c4921955ba0c332a",
"lattice_commit": "a362b2e4d5fe6e67850e9dbb848fe9ab460e7711"
},
"command": "go test -test.paniconexit0 -test.count=1 -test.run=^$ -test.bench=^BenchmarkThreshold_KeygenShare_CPU$|^BenchmarkThreshold_PartialDecryptShare_CPU$|^BenchmarkThreshold_ShareAggregate_CPU$ -test.benchtime=10x -test.timeout=2m0s",
"cells": [
{
"name": "BenchmarkThreshold_KeygenShare_CPU",
"params": {
"backend": "CPU (pure Go)",
"logN": "10",
"primitive": "threshold_keygen_share",
"threshold": "3"
},
"status": "ok",
"iterations": 1,
"median_ns": 171042,
"mean_ns": 171042,
"p50_ns": 171042,
"p95_ns": 171042,
"p99_ns": 171042,
"ops_per_sec": 5846.517229686276
},
{
"name": "BenchmarkThreshold_KeygenShare_CPU",
"params": {
"backend": "CPU (pure Go)",
"logN": "10",
"primitive": "threshold_keygen_share",
"threshold": "3"
},
"status": "ok",
"iterations": 10,
"median_ns": 105875,
"mean_ns": 111158,
"p50_ns": 105875,
"p95_ns": 120958,
"p99_ns": 120958,
"ops_per_sec": 9445.100354191263
},
{
"name": "BenchmarkThreshold_PartialDecryptShare_CPU",
"params": {
"backend": "CPU (pure Go)",
"logN": "10",
"primitive": "partial_decrypt_share",
"scope": "GenShamirSecretShare (per-recipient)",
"threshold": "3"
},
"status": "ok",
"iterations": 1,
"median_ns": 10666,
"mean_ns": 10666,
"p50_ns": 10666,
"p95_ns": 10666,
"p99_ns": 10666,
"ops_per_sec": 93755.85974123383
},
{
"name": "BenchmarkThreshold_PartialDecryptShare_CPU",
"params": {
"backend": "CPU (pure Go)",
"logN": "10",
"primitive": "partial_decrypt_share",
"scope": "GenShamirSecretShare (per-recipient)",
"threshold": "3"
},
"status": "ok",
"iterations": 10,
"median_ns": 9667,
"mean_ns": 9987,
"p50_ns": 9667,
"p95_ns": 9958,
"p99_ns": 9958,
"ops_per_sec": 103444.70880314472
},
{
"name": "BenchmarkThreshold_ShareAggregate_CPU",
"params": {
"backend": "CPU (pure Go)",
"logN": "10",
"primitive": "share_aggregate",
"threshold": "3"
},
"status": "ok",
"iterations": 1,
"median_ns": 4167,
"mean_ns": 4167,
"p50_ns": 4167,
"p95_ns": 4167,
"p99_ns": 4167,
"ops_per_sec": 239980.80153587714
},
{
"name": "BenchmarkThreshold_ShareAggregate_CPU",
"params": {
"backend": "CPU (pure Go)",
"logN": "10",
"primitive": "share_aggregate",
"threshold": "3"
},
"status": "ok",
"iterations": 10,
"median_ns": 1583,
"mean_ns": 1649,
"p50_ns": 1583,
"p95_ns": 1625,
"p99_ns": 1625,
"ops_per_sec": 631711.9393556538
}
]
}
@@ -0,0 +1,54 @@
{
"name": "threshold",
"host": {
"time": "2026-04-27T19:54:54Z",
"go_version": "go1.26.2",
"goos": "darwin",
"goarch": "arm64",
"num_cpu": 10,
"gomaxprocs": 10,
"cpu_brand": "Apple M1 Max",
"os_product": "macOS",
"os_version": "26.4",
"build_tags": "default",
"fhe_commit": "873ee56fed87a95794aefac5c4921955ba0c332a",
"lattice_commit": "a362b2e4d5fe6e67850e9dbb848fe9ab460e7711"
},
"command": "go test -test.paniconexit0 -test.count=1 -test.run=^$ -test.bench=^BenchmarkReconcile_88_vs_121$|^BenchmarkReconcile_MetalNTTZoo$|^BenchmarkTFHE_TRLWE_Add_CPU$|^BenchmarkThreshold_ShareAggregate_CPU$ -test.benchtime=10x -test.timeout=2m0s",
"cells": [
{
"name": "BenchmarkThreshold_ShareAggregate_CPU",
"params": {
"backend": "CPU (pure Go)",
"logN": "10",
"primitive": "share_aggregate",
"threshold": "3"
},
"status": "ok",
"iterations": 1,
"median_ns": 2750,
"mean_ns": 2750,
"p50_ns": 2750,
"p95_ns": 2750,
"p99_ns": 2750,
"ops_per_sec": 363636.36363636365
},
{
"name": "BenchmarkThreshold_ShareAggregate_CPU",
"params": {
"backend": "CPU (pure Go)",
"logN": "10",
"primitive": "share_aggregate",
"threshold": "3"
},
"status": "ok",
"iterations": 10,
"median_ns": 5750,
"mean_ns": 6470,
"p50_ns": 5750,
"p95_ns": 7583,
"p99_ns": 7583,
"ops_per_sec": 173913.04347826086
}
]
}
+17 -3
View File
@@ -5,9 +5,9 @@ go 1.26.1
require ( require (
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
github.com/hanzoai/base v0.39.1 github.com/hanzoai/base v0.39.1
github.com/luxfi/database v1.17.44 github.com/luxfi/database v1.18.3
github.com/luxfi/lattice/v7 v7.1.0 github.com/luxfi/lattice/v7 v7.1.0
github.com/luxfi/math v1.3.0 github.com/luxfi/math v1.4.0
github.com/luxfi/mdns v0.1.0 github.com/luxfi/mdns v0.1.0
github.com/luxfi/metric v1.5.0 github.com/luxfi/metric v1.5.0
github.com/spf13/cobra v1.10.2 github.com/spf13/cobra v1.10.2
@@ -16,6 +16,7 @@ require (
) )
require ( require (
filippo.io/hpke v0.4.0 // indirect
github.com/ALTree/bigfloat v0.2.0 // indirect github.com/ALTree/bigfloat v0.2.0 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect
@@ -29,6 +30,7 @@ require (
github.com/fatih/color v1.19.0 // indirect github.com/fatih/color v1.19.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.13 // indirect github.com/gabriel-vasile/mimetype v1.4.13 // indirect
github.com/ganigeorgiev/fexpr v0.5.0 // indirect github.com/ganigeorgiev/fexpr v0.5.0 // indirect
github.com/go-ini/ini v1.67.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ozzo/ozzo-validation/v4 v4.3.0 // indirect github.com/go-ozzo/ozzo-validation/v4 v4.3.0 // indirect
@@ -49,6 +51,9 @@ require (
github.com/jackc/pgx/v5 v5.9.1 // indirect github.com/jackc/pgx/v5 v5.9.1 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/klauspost/compress v1.18.4 // indirect github.com/klauspost/compress v1.18.4 // indirect
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
github.com/klauspost/crc32 v1.3.0 // indirect
github.com/luxfi/age v1.4.0 // indirect
github.com/luxfi/cache v1.2.1 // indirect github.com/luxfi/cache v1.2.1 // indirect
github.com/luxfi/codec v1.1.3 // indirect github.com/luxfi/codec v1.1.3 // indirect
github.com/luxfi/compress v0.0.5 // indirect github.com/luxfi/compress v0.0.5 // indirect
@@ -58,20 +63,26 @@ require (
github.com/luxfi/log v1.4.1 // indirect github.com/luxfi/log v1.4.1 // indirect
github.com/luxfi/math/big v0.1.0 // indirect github.com/luxfi/math/big v0.1.0 // indirect
github.com/luxfi/mock v0.1.1 // indirect github.com/luxfi/mock v0.1.1 // indirect
github.com/luxfi/zapdb/v4 v4.9.3 // indirect github.com/luxfi/zapdb v1.8.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/miekg/dns v1.1.72 // indirect github.com/miekg/dns v1.1.72 // indirect
github.com/minio/crc64nvme v1.1.1 // indirect
github.com/minio/md5-simd v1.1.2 // indirect
github.com/minio/minio-go/v7 v7.0.100 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect github.com/mr-tron/base58 v1.2.0 // indirect
github.com/ncruces/go-strftime v1.0.0 // indirect github.com/ncruces/go-strftime v1.0.0 // indirect
github.com/nexus-rpc/sdk-go v0.6.0 // indirect github.com/nexus-rpc/sdk-go v0.6.0 // indirect
github.com/philhofer/fwd v1.2.0 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/robfig/cron v1.2.0 // indirect github.com/robfig/cron v1.2.0 // indirect
github.com/rs/xid v1.6.0 // indirect
github.com/spf13/cast v1.10.0 // indirect github.com/spf13/cast v1.10.0 // indirect
github.com/spf13/pflag v1.0.10 // indirect github.com/spf13/pflag v1.0.10 // indirect
github.com/stretchr/objx v0.5.3 // indirect github.com/stretchr/objx v0.5.3 // indirect
github.com/stretchr/testify v1.11.1 // indirect github.com/stretchr/testify v1.11.1 // indirect
github.com/tinylib/msgp v1.6.1 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/otel v1.40.0 // indirect go.opentelemetry.io/otel v1.40.0 // indirect
go.opentelemetry.io/otel/metric v1.40.0 // indirect go.opentelemetry.io/otel/metric v1.40.0 // indirect
@@ -79,6 +90,7 @@ require (
go.temporal.io/api v1.62.6 // indirect go.temporal.io/api v1.62.6 // indirect
go.temporal.io/sdk v1.41.1 // indirect go.temporal.io/sdk v1.41.1 // indirect
go.uber.org/mock v0.6.0 // indirect go.uber.org/mock v0.6.0 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90 // indirect golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90 // indirect
golang.org/x/image v0.38.0 // indirect golang.org/x/image v0.38.0 // indirect
golang.org/x/mod v0.34.0 // indirect golang.org/x/mod v0.34.0 // indirect
@@ -100,3 +112,5 @@ require (
modernc.org/memory v1.11.0 // indirect modernc.org/memory v1.11.0 // indirect
modernc.org/sqlite v1.48.0 // indirect modernc.org/sqlite v1.48.0 // indirect
) )
replace github.com/luxfi/math => /Users/z/work/lux/math
+30 -6
View File
@@ -1,3 +1,7 @@
c2sp.org/CCTV/age v0.0.0-20251208015420-e9274a7bdbfd h1:ZLsPO6WdZ5zatV4UfVpr7oAwLGRZ+sebTUruuM4Ra3M=
c2sp.org/CCTV/age v0.0.0-20251208015420-e9274a7bdbfd/go.mod h1:SrHC2C7r5GkDk8R+NFVzYy/sdj0Ypg9htaPXQq5Cqeo=
filippo.io/hpke v0.4.0 h1:p575VVQ6ted4pL+it6M00V/f2qTZITO0zgmdKCkd5+A=
filippo.io/hpke v0.4.0/go.mod h1:EmAN849/P3qdeK+PCMkDpDm83vRHM5cDipBJ8xbQLVY=
github.com/ALTree/bigfloat v0.2.0 h1:AwNzawrpFuw55/YDVlcPw0F0cmmXrmngBHhVrvdXPvM= github.com/ALTree/bigfloat v0.2.0 h1:AwNzawrpFuw55/YDVlcPw0F0cmmXrmngBHhVrvdXPvM=
github.com/ALTree/bigfloat v0.2.0/go.mod h1:+NaH2gLeY6RPBPPQf4aRotPPStg+eXc8f9ZaE4vRfD4= github.com/ALTree/bigfloat v0.2.0/go.mod h1:+NaH2gLeY6RPBPPQf4aRotPPStg+eXc8f9ZaE4vRfD4=
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260215031811-a0ab0b218a81 h1:TBzelXBdnzDy+HCrBMcomEnhrmigkWOI1/mIPCi2u4M= github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260215031811-a0ab0b218a81 h1:TBzelXBdnzDy+HCrBMcomEnhrmigkWOI1/mIPCi2u4M=
@@ -35,6 +39,8 @@ github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9
github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
github.com/ganigeorgiev/fexpr v0.5.0 h1:XA9JxtTE/Xm+g/JFI6RfZEHSiQlk+1glLvRK1Lpv/Tk= github.com/ganigeorgiev/fexpr v0.5.0 h1:XA9JxtTE/Xm+g/JFI6RfZEHSiQlk+1glLvRK1Lpv/Tk=
github.com/ganigeorgiev/fexpr v0.5.0/go.mod h1:RyGiGqmeXhEQ6+mlGdnUleLHgtzzu/VGO2WtJkF5drE= github.com/ganigeorgiev/fexpr v0.5.0/go.mod h1:RyGiGqmeXhEQ6+mlGdnUleLHgtzzu/VGO2WtJkF5drE=
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
@@ -91,10 +97,17 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c= github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
github.com/klauspost/crc32 v1.3.0 h1:sSmTt3gUt81RP655XGZPElI0PelVTZ6YwCRnPSupoFM=
github.com/klauspost/crc32 v1.3.0/go.mod h1:D7kQaZhnkX/Y0tstFGf8VUzv2UofNGqCjnC3zdHB0Hw=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/luxfi/age v1.4.0 h1:tU5q65RQSQdaVq64Z/DVUhiPQMoMPQT6pr41LsvG0AQ=
github.com/luxfi/age v1.4.0/go.mod h1:iAYAxgvrXxcy746+Ovh/eWWDuF9teJLNcCSSOX9RYW0=
github.com/luxfi/cache v1.2.1 h1:kAzOS55/hmYeNKR+0HAKv4ma48Y6JjkI8UQeqdZ8bfI= github.com/luxfi/cache v1.2.1 h1:kAzOS55/hmYeNKR+0HAKv4ma48Y6JjkI8UQeqdZ8bfI=
github.com/luxfi/cache v1.2.1/go.mod h1:co7JTxZZHpKT31Yh01LFp5aZOxmoUg157FhBLQdQHVU= github.com/luxfi/cache v1.2.1/go.mod h1:co7JTxZZHpKT31Yh01LFp5aZOxmoUg157FhBLQdQHVU=
github.com/luxfi/codec v1.1.3 h1:hK/pijaD/b3xP5ZNkGdDq26jRgFPQtYBLmAwOgxzw4c= github.com/luxfi/codec v1.1.3 h1:hK/pijaD/b3xP5ZNkGdDq26jRgFPQtYBLmAwOgxzw4c=
@@ -109,8 +122,8 @@ github.com/luxfi/container v0.0.4 h1:BXhF82WyfqVP5mjlNcr7tP0Fcnvl0Ap1rkiu+rq5XuM
github.com/luxfi/container v0.0.4/go.mod h1:Z3SpmMF5d4t77MM0nHYXURpn+EMVaeu1fhbd/3BGaek= github.com/luxfi/container v0.0.4/go.mod h1:Z3SpmMF5d4t77MM0nHYXURpn+EMVaeu1fhbd/3BGaek=
github.com/luxfi/crypto v1.17.45 h1:uGK0y4+aLipE/M0YIQ5hcsWv0ZG0E4cPv03a94K/eLE= github.com/luxfi/crypto v1.17.45 h1:uGK0y4+aLipE/M0YIQ5hcsWv0ZG0E4cPv03a94K/eLE=
github.com/luxfi/crypto v1.17.45/go.mod h1:GnAkhQ7HNs3X0Tzx5nOONS3kl0yRmWHbDcRO5ffILsg= github.com/luxfi/crypto v1.17.45/go.mod h1:GnAkhQ7HNs3X0Tzx5nOONS3kl0yRmWHbDcRO5ffILsg=
github.com/luxfi/database v1.17.44 h1:hfiTls7sqbweW+o4iaZqB8P997paC+vpgWmhN6v5MJ0= github.com/luxfi/database v1.18.3 h1:gg+xwhKUxXa7fDoOD8IS91E71QqoEtcDCl2nfS61Jgg=
github.com/luxfi/database v1.17.44/go.mod h1:6Ey5y3I0WNLHbxIlIdFqUuKfBg+b0fAgTA8FgRgQ8zg= github.com/luxfi/database v1.18.3/go.mod h1:sv0pYCGKlK1aNJTICxFUDpVWCJTigoLlshHmV/1pg7c=
github.com/luxfi/geth v1.16.69 h1:CHO6xTZ+A+3itk94ts4uyVRJajNVP3RxWTjJp5qGOlk= github.com/luxfi/geth v1.16.69 h1:CHO6xTZ+A+3itk94ts4uyVRJajNVP3RxWTjJp5qGOlk=
github.com/luxfi/geth v1.16.69/go.mod h1:8eEO1hW5sa6OH2VeCMaCPnRz28JBxFvCPBCWPLsU2ck= github.com/luxfi/geth v1.16.69/go.mod h1:8eEO1hW5sa6OH2VeCMaCPnRz28JBxFvCPBCWPLsU2ck=
github.com/luxfi/ids v1.2.9 h1:+yjdhXW99drnd2Zlp1u/p8k3G23W3/1btJQ4ogHawUI= github.com/luxfi/ids v1.2.9 h1:+yjdhXW99drnd2Zlp1u/p8k3G23W3/1btJQ4ogHawUI=
@@ -119,8 +132,6 @@ github.com/luxfi/lattice/v7 v7.1.0 h1:mr3HvN6olNTS2LT/xAW/JBhTqfvpsGmsopDMeR7BSJ
github.com/luxfi/lattice/v7 v7.1.0/go.mod h1:IaaUN+3ysnBG4BA8ILRYG0j80+qtYDP4C5lkaDb2pDE= github.com/luxfi/lattice/v7 v7.1.0/go.mod h1:IaaUN+3ysnBG4BA8ILRYG0j80+qtYDP4C5lkaDb2pDE=
github.com/luxfi/log v1.4.1 h1:rIfFRodb9jrD/w7KayaUk0Oc+37PaQQdKEEMJCjR8gw= github.com/luxfi/log v1.4.1 h1:rIfFRodb9jrD/w7KayaUk0Oc+37PaQQdKEEMJCjR8gw=
github.com/luxfi/log v1.4.1/go.mod h1:64IE3xRMJcpkQwnPUfJw3pDj7wU0kRS7BZ9wM7R72jk= github.com/luxfi/log v1.4.1/go.mod h1:64IE3xRMJcpkQwnPUfJw3pDj7wU0kRS7BZ9wM7R72jk=
github.com/luxfi/math v1.3.0 h1:KfHzmsVs4Xfcc3G8PaXotzHk0vkRpUdAna1/RXa9caM=
github.com/luxfi/math v1.3.0/go.mod h1:VoHe/+0yRPNS0ouzMhCPh5ky+myqjVrrBq4qEXFBSGs=
github.com/luxfi/math/big v0.1.0 h1:Vz4c0RsZVPdIKPsHPgAJChH/R3p15WHRUz7LkLf+NIQ= github.com/luxfi/math/big v0.1.0 h1:Vz4c0RsZVPdIKPsHPgAJChH/R3p15WHRUz7LkLf+NIQ=
github.com/luxfi/math/big v0.1.0/go.mod h1:BuxSu22RbO93xBLk5Eam5nldFponoJ73xDFz4uJ3Huk= github.com/luxfi/math/big v0.1.0/go.mod h1:BuxSu22RbO93xBLk5Eam5nldFponoJ73xDFz4uJ3Huk=
github.com/luxfi/mdns v0.1.0 h1:VB3mQcETc9j5SY1S6lAgFtuGr/rjWuDgPYnxS+OKWMQ= github.com/luxfi/mdns v0.1.0 h1:VB3mQcETc9j5SY1S6lAgFtuGr/rjWuDgPYnxS+OKWMQ=
@@ -133,8 +144,8 @@ github.com/luxfi/sampler v1.0.0 h1:k8Sf6otW83w4pQp0jXLA+g3J/joB7w7SqXQsWmNTOV0=
github.com/luxfi/sampler v1.0.0/go.mod h1:f96/ozlj9vFfZj+akLtrHn4VpulQahwB+MQQhpeIekk= github.com/luxfi/sampler v1.0.0/go.mod h1:f96/ozlj9vFfZj+akLtrHn4VpulQahwB+MQQhpeIekk=
github.com/luxfi/utils v1.1.3 h1:yDEuuJ6bm9H8DzOzzveXI1AZlu/AeSpHNRrY1akbyc0= github.com/luxfi/utils v1.1.3 h1:yDEuuJ6bm9H8DzOzzveXI1AZlu/AeSpHNRrY1akbyc0=
github.com/luxfi/utils v1.1.3/go.mod h1:lskchZiYYRBFsSyYg3NWLPw211uRyxIs3/wAzrfSIAk= github.com/luxfi/utils v1.1.3/go.mod h1:lskchZiYYRBFsSyYg3NWLPw211uRyxIs3/wAzrfSIAk=
github.com/luxfi/zapdb/v4 v4.9.3 h1:KV1DrbZqtZsZvrWyPw5D8WHR0DxzqW2jHjqx6obxgoM= github.com/luxfi/zapdb v1.8.0 h1:E9hXMW1MTuS6kmDVs07j62gIq5qI5gZOdyzVfiBc1wg=
github.com/luxfi/zapdb/v4 v4.9.3/go.mod h1:BrpLaDeYy+smON4ASDPCFKWrQ58CXhy3WNEPGna7vuU= github.com/luxfi/zapdb v1.8.0/go.mod h1:Qukh3hDRD0MnxA6z+a28JTnXhN85AiLLgp6TYr4QAMc=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
@@ -142,12 +153,20 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/miekg/dns v1.1.72 h1:vhmr+TF2A3tuoGNkLDFK9zi36F2LS+hKTRW0Uf8kbzI= github.com/miekg/dns v1.1.72 h1:vhmr+TF2A3tuoGNkLDFK9zi36F2LS+hKTRW0Uf8kbzI=
github.com/miekg/dns v1.1.72/go.mod h1:+EuEPhdHOsfk6Wk5TT2CzssZdqkmFhf8r+aVyDEToIs= github.com/miekg/dns v1.1.72/go.mod h1:+EuEPhdHOsfk6Wk5TT2CzssZdqkmFhf8r+aVyDEToIs=
github.com/minio/crc64nvme v1.1.1 h1:8dwx/Pz49suywbO+auHCBpCtlW1OfpcLN7wYgVR6wAI=
github.com/minio/crc64nvme v1.1.1/go.mod h1:eVfm2fAzLlxMdUGc0EEBGSMmPwmXD5XiNRpnu9J3bvg=
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
github.com/minio/minio-go/v7 v7.0.100 h1:ShkWi8Tyj9RtU57OQB2HIXKz4bFgtVib0bbT1sbtLI8=
github.com/minio/minio-go/v7 v7.0.100/go.mod h1:EtGNKtlX20iL2yaYnxEigaIvj0G0GwSDnifnG8ClIdw=
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w=
github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/nexus-rpc/sdk-go v0.6.0 h1:QRgnP2zTbxEbiyWG/aXH8uSC5LV/Mg1fqb19jb4DBlo= github.com/nexus-rpc/sdk-go v0.6.0 h1:QRgnP2zTbxEbiyWG/aXH8uSC5LV/Mg1fqb19jb4DBlo=
github.com/nexus-rpc/sdk-go v0.6.0/go.mod h1:FHdPfVQwRuJFZFTF0Y2GOAxCrbIBNrcPna9slkGKPYk= github.com/nexus-rpc/sdk-go v0.6.0/go.mod h1:FHdPfVQwRuJFZFTF0Y2GOAxCrbIBNrcPna9slkGKPYk=
github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM=
github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -159,6 +178,8 @@ github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
@@ -175,6 +196,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/tinylib/msgp v1.6.1 h1:ESRv8eL3u+DNHUoSAAQRE50Hm162zqAnBoGv9PzScPY=
github.com/tinylib/msgp v1.6.1/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA=
github.com/urfave/cli/v3 v3.6.2 h1:lQuqiPrZ1cIz8hz+HcrG0TNZFxU70dPZ3Yl+pSrH9A8= github.com/urfave/cli/v3 v3.6.2 h1:lQuqiPrZ1cIz8hz+HcrG0TNZFxU70dPZ3Yl+pSrH9A8=
github.com/urfave/cli/v3 v3.6.2/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso= github.com/urfave/cli/v3 v3.6.2/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -198,6 +221,7 @@ go.temporal.io/sdk v1.41.1 h1:yOpvsHyDD1lNuwlGBv/SUodCPhjv9nDeC9lLHW/fJUA=
go.temporal.io/sdk v1.41.1/go.mod h1:/InXQT5guZ6AizYzpmzr5avQ/GMgq1ZObcKlKE2AhTc= go.temporal.io/sdk v1.41.1/go.mod h1:/InXQT5guZ6AizYzpmzr5avQ/GMgq1ZObcKlKE2AhTc=
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+76 -507
View File
@@ -1,537 +1,106 @@
// Copyright (c) 2025, Lux Industries Inc // Copyright (c) 2025, Lux Industries Inc
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
// Package fhe NTT thin wrapper.
//
// This file is a delegating wrapper around the unified Lux NTT
// substrate at github.com/luxfi/math/ntt/subring (the Lattigo-derived
// Montgomery negacyclic NTT body, mirrored on the C++ side by
// crypto/fhe/cpp/backends/cpu/ntt_cpu.cpp via
// lux::crypto::corona::lattice_ring::NTTStandard).
//
// The previous standalone cyclic NTT implementation has been removed;
// there were zero production callers of NTTEngine (only ntt_simd_test.go).
// Convention is now negacyclic — same body, same byte representation,
// across Go and C++.
package fhe package fhe
import ( import (
"fmt" "fmt"
"math/bits"
"sync" "sync"
"unsafe"
"github.com/luxfi/math/ntt/subring"
) )
// NTTEngine provides SIMD-optimized NTT operations for CPU fallback. // NTTEngine is a thin wrapper around a cached *subring.SubRing
// Uses AVX2/AVX-512 on x86-64 and NEON on ARM64. // keyed by (N, Q). All forward/inverse NTT operations delegate to
// the unified substrate.
type NTTEngine struct { type NTTEngine struct {
N uint32 N uint32
Q uint64 Q uint64
twiddleFactors []uint64 sr *subring.SubRing
invTwiddles []uint64
nInv uint64
// Precomputed Barrett reduction constants
barrettMu uint64 // floor(2^64 / Q)
barrettK int // number of bits for Barrett
// Montgomery form constants
montR uint64 // R = 2^64 mod Q
montR2 uint64 // R^2 mod Q
montInv uint64 // -Q^(-1) mod 2^64
} }
// NewNTTEngine creates a new SIMD-optimized NTT engine // engineCache memoizes SubRing instances keyed by (N, Q) so that
func NewNTTEngine(N uint32, Q uint64) (*NTTEngine, error) { // callers constructing many NTTEngine values for the same parameters
e := &NTTEngine{ // share the (expensive) NTT constant tables.
N: N, var (
Q: Q, engineCacheMu sync.RWMutex
twiddleFactors: make([]uint64, N), engineCache = make(map[engineKey]*subring.SubRing)
invTwiddles: make([]uint64, N), )
type engineKey struct {
N uint32
Q uint64
}
// resolveSubRing returns or builds the cached *subring.SubRing for (N, Q).
func resolveSubRing(N uint32, Q uint64) (*subring.SubRing, error) {
k := engineKey{N: N, Q: Q}
engineCacheMu.RLock()
sr, ok := engineCache[k]
engineCacheMu.RUnlock()
if ok {
return sr, nil
} }
// Find primitive 2N-th root of unity engineCacheMu.Lock()
omega, err := e.findPrimitiveRoot() defer engineCacheMu.Unlock()
if sr, ok := engineCache[k]; ok {
return sr, nil
}
sr, err := subring.NewSubRing(int(N), Q)
if err != nil { if err != nil {
return nil, fmt.Errorf("find primitive root: %w", err) return nil, fmt.Errorf("fhe: subring.NewSubRing(N=%d, Q=%d): %w", N, Q, err)
} }
omegaInv := e.modInverse(omega) if err := sr.GenerateNTTConstants(); err != nil {
return nil, fmt.Errorf("fhe: GenerateNTTConstants(N=%d, Q=%d): %w", N, Q, err)
// Precompute twiddle factors in bit-reversed order for in-place NTT }
e.computeTwiddlesBitReversed(omega, omegaInv) engineCache[k] = sr
return sr, nil
// N^(-1) mod Q for INTT normalization
e.nInv = e.modInverse(uint64(N))
// Barrett reduction constant
e.barrettK = 64
e.barrettMu = e.computeBarrettMu()
// Montgomery constants
e.montR = e.computeMontgomeryR()
e.montR2 = e.mulMod(e.montR, e.montR)
e.montInv = e.computeMontgomeryInv()
return e, nil
} }
// NTTInPlace performs in-place NTT using Cooley-Tukey algorithm // NewNTTEngine creates an NTTEngine for the given ring degree and modulus.
// Optimized for SIMD vectorization with explicit parallelism // The underlying SubRing is shared across engines with identical (N, Q).
func NewNTTEngine(N uint32, Q uint64) (*NTTEngine, error) {
sr, err := resolveSubRing(N, Q)
if err != nil {
return nil, err
}
return &NTTEngine{N: N, Q: Q, sr: sr}, nil
}
// NTTInPlace performs an in-place forward NTT (negacyclic, Montgomery form).
func (e *NTTEngine) NTTInPlace(coeffs []uint64) { func (e *NTTEngine) NTTInPlace(coeffs []uint64) {
N := int(e.N) e.sr.NTT(coeffs, coeffs)
// Bit-reversal permutation
e.bitReversePermute(coeffs)
// Cooley-Tukey NTT butterflies
// The structure allows SIMD vectorization across independent butterflies
twiddleIdx := 0
for m := 2; m <= N; m <<= 1 {
mHalf := m >> 1
// Process all butterflies at this stage
// Each group of m elements has m/2 independent butterflies
for k := 0; k < N; k += m {
// This inner loop is SIMD-vectorizable
for j := 0; j < mHalf; j++ {
w := e.twiddleFactors[twiddleIdx+j]
u := coeffs[k+j]
v := e.mulModBarrett(coeffs[k+j+mHalf], w)
// Butterfly: [u, v] -> [u + v, u - v]
coeffs[k+j] = e.addMod(u, v)
coeffs[k+j+mHalf] = e.subMod(u, v)
}
}
twiddleIdx += mHalf
}
} }
// INTTInPlace performs in-place inverse NTT // INTTInPlace performs an in-place inverse NTT (negacyclic, Montgomery form).
// Uses the same Cooley-Tukey structure as the forward NTT but with inverse twiddles, // INTT(NTT(x)) == x.
// followed by scaling by 1/N. This ensures INTT(NTT(x)) = x.
func (e *NTTEngine) INTTInPlace(coeffs []uint64) { func (e *NTTEngine) INTTInPlace(coeffs []uint64) {
N := int(e.N) e.sr.INTT(coeffs, coeffs)
// Bit-reversal permutation (same as forward)
e.bitReversePermute(coeffs)
// Cooley-Tukey butterflies with inverse twiddles
twiddleIdx := 0
for m := 2; m <= N; m <<= 1 {
mHalf := m >> 1
for k := 0; k < N; k += m {
for j := 0; j < mHalf; j++ {
w := e.invTwiddles[twiddleIdx+j]
u := coeffs[k+j]
v := e.mulModBarrett(coeffs[k+j+mHalf], w)
coeffs[k+j] = e.addMod(u, v)
coeffs[k+j+mHalf] = e.subMod(u, v)
}
}
twiddleIdx += mHalf
}
// Scale by N^(-1) to normalize
for i := 0; i < N; i++ {
coeffs[i] = e.mulModBarrett(coeffs[i], e.nInv)
}
} }
// NTTBatch performs NTT on multiple polynomials in parallel // NTTInPlaceSIMD is an alias for NTTInPlace; the substrate selects the
// Exploits both inter-polynomial and intra-polynomial parallelism // best available implementation (pure Go or SIMD via build tags).
func (e *NTTEngine) NTTBatch(polys [][]uint64) {
var wg sync.WaitGroup
batchSize := len(polys)
// Determine optimal parallelism based on batch size
numWorkers := batchSize
if numWorkers > 16 {
numWorkers = 16 // Cap at 16 parallel workers
}
chunkSize := (batchSize + numWorkers - 1) / numWorkers
for w := 0; w < numWorkers; w++ {
start := w * chunkSize
end := start + chunkSize
if end > batchSize {
end = batchSize
}
if start >= end {
continue
}
wg.Add(1)
go func(s, end int, eng *NTTEngine) {
defer wg.Done()
for i := s; i < end; i++ {
eng.NTTInPlace(polys[i])
}
}(start, end, e)
}
wg.Wait()
}
// INTTBatch performs INTT on multiple polynomials in parallel
func (e *NTTEngine) INTTBatch(polys [][]uint64) {
var wg sync.WaitGroup
batchSize := len(polys)
numWorkers := batchSize
if numWorkers > 16 {
numWorkers = 16
}
chunkSize := (batchSize + numWorkers - 1) / numWorkers
for w := 0; w < numWorkers; w++ {
start := w * chunkSize
end := start + chunkSize
if end > batchSize {
end = batchSize
}
if start >= end {
continue
}
wg.Add(1)
go func(s, end int, eng *NTTEngine) {
defer wg.Done()
for i := s; i < end; i++ {
eng.INTTInPlace(polys[i])
}
}(start, end, e)
}
wg.Wait()
}
// PolyMulNTT multiplies two polynomials already in NTT form
// Result is also in NTT form. SIMD-vectorizable element-wise multiplication.
func (e *NTTEngine) PolyMulNTT(a, b, result []uint64) {
N := int(e.N)
// Element-wise multiplication in NTT domain
// This loop is fully SIMD-vectorizable
for i := 0; i < N; i++ {
result[i] = e.mulModBarrett(a[i], b[i])
}
}
// PolyMulNTTAccum multiplies and accumulates: result += a * b (in NTT form)
func (e *NTTEngine) PolyMulNTTAccum(a, b, result []uint64) {
N := int(e.N)
for i := 0; i < N; i++ {
prod := e.mulModBarrett(a[i], b[i])
result[i] = e.addMod(result[i], prod)
}
}
// PolyAdd adds two polynomials: result = a + b
func (e *NTTEngine) PolyAdd(a, b, result []uint64) {
N := int(e.N)
Q := e.Q
for i := 0; i < N; i++ {
sum := a[i] + b[i]
if sum >= Q {
sum -= Q
}
result[i] = sum
}
}
// PolySub subtracts two polynomials: result = a - b
func (e *NTTEngine) PolySub(a, b, result []uint64) {
N := int(e.N)
Q := e.Q
for i := 0; i < N; i++ {
if a[i] >= b[i] {
result[i] = a[i] - b[i]
} else {
result[i] = Q - b[i] + a[i]
}
}
}
// PolyNeg negates a polynomial: result = -a
func (e *NTTEngine) PolyNeg(a, result []uint64) {
N := int(e.N)
Q := e.Q
for i := 0; i < N; i++ {
if a[i] == 0 {
result[i] = 0
} else {
result[i] = Q - a[i]
}
}
}
// PolyMulScalar multiplies polynomial by scalar: result = a * scalar
func (e *NTTEngine) PolyMulScalar(a []uint64, scalar uint64, result []uint64) {
N := int(e.N)
for i := 0; i < N; i++ {
result[i] = e.mulModBarrett(a[i], scalar)
}
}
// ========== Helper Functions ==========
// bitReversePermute performs in-place bit-reversal permutation
func (e *NTTEngine) bitReversePermute(coeffs []uint64) {
N := int(e.N)
logN := e.log2(N)
for i := 0; i < N; i++ {
j := e.reverseBits(i, logN)
if i < j {
coeffs[i], coeffs[j] = coeffs[j], coeffs[i]
}
}
}
// reverseBits reverses the lower logN bits of x
func (e *NTTEngine) reverseBits(x, logN int) int {
result := 0
for i := 0; i < logN; i++ {
result = (result << 1) | (x & 1)
x >>= 1
}
return result
}
// log2 returns floor(log2(n))
func (e *NTTEngine) log2(n int) int {
r := 0
for n > 1 {
n >>= 1
r++
}
return r
}
// addMod computes (a + b) mod Q
func (e *NTTEngine) addMod(a, b uint64) uint64 {
sum := a + b
if sum >= e.Q {
sum -= e.Q
}
return sum
}
// subMod computes (a - b) mod Q
func (e *NTTEngine) subMod(a, b uint64) uint64 {
if a >= b {
return a - b
}
return e.Q - b + a
}
// mulMod computes (a * b) mod Q using standard division
func (e *NTTEngine) mulMod(a, b uint64) uint64 {
hi, lo := mul64(a, b)
if hi == 0 {
return lo % e.Q
}
// For larger results, use the full 128-bit division
return div128(hi, lo, e.Q)
}
// mulModBarrett computes (a * b) mod Q using Barrett reduction.
// Constant-time: always executes the full 128-bit path regardless of input.
func (e *NTTEngine) mulModBarrett(a, b uint64) uint64 {
hi, lo := mul64(a, b)
// Always execute the full path to avoid timing side-channel on hi == 0
_, r := bits.Div64(hi%e.Q, lo, e.Q)
return r
}
// mul64 multiplies two 64-bit integers and returns 128-bit result as (hi, lo)
func mul64(a, b uint64) (hi, lo uint64) {
// Use assembly intrinsic if available, otherwise use portable version
// This is the portable Go version - compiler may optimize to MULX on x86-64
aLo, aHi := a&0xFFFFFFFF, a>>32
bLo, bHi := b&0xFFFFFFFF, b>>32
p0 := aLo * bLo
p1 := aLo * bHi
p2 := aHi * bLo
p3 := aHi * bHi
mid := p1 + p2
carry := uint64(0)
if mid < p1 {
carry = 1 << 32
}
lo = p0 + (mid << 32)
if lo < p0 {
carry++
}
hi = p3 + (mid >> 32) + carry
return
}
// div128 computes (hi:lo) mod d using math/bits.Div64
// Requires hi < d (caller must reduce hi first if needed)
func div128(hi, lo, d uint64) uint64 {
if hi == 0 {
return lo % d
}
// Reduce hi mod d first so the precondition hi < d is met
hi = hi % d
_, r := bits.Div64(hi, lo, d)
return r
}
// computeTwiddlesBitReversed precomputes twiddle factors in bit-reversed order
func (e *NTTEngine) computeTwiddlesBitReversed(omega, omegaInv uint64) {
N := int(e.N)
// Forward NTT twiddles
idx := 0
for m := 2; m <= N; m <<= 1 {
mHalf := m >> 1
w := uint64(1)
wStep := e.powMod(omega, uint64(N/m))
for j := 0; j < mHalf; j++ {
e.twiddleFactors[idx+j] = w
w = e.mulMod(w, wStep)
}
idx += mHalf
}
// Inverse NTT twiddles (same structure as forward for consistency)
idx = 0
for m := 2; m <= N; m <<= 1 {
mHalf := m >> 1
w := uint64(1)
wStep := e.powMod(omegaInv, uint64(N/m))
for j := 0; j < mHalf; j++ {
e.invTwiddles[idx+j] = w
w = e.mulMod(w, wStep)
}
idx += mHalf
}
}
// findPrimitiveRoot finds a primitive 2N-th root of unity mod Q
func (e *NTTEngine) findPrimitiveRoot() (uint64, error) {
N := uint64(e.N)
Q := e.Q
order := Q - 1
// Q-1 must be divisible by 2N for NTT
if order%(2*N) != 0 {
return 0, fmt.Errorf("Q-1 (%d) must be divisible by 2N (%d) for NTT", order, 2*N)
}
// Factor Q-1 to find all prime factors
factors := primeFactors(order)
// Find a generator of Z_Q* by checking g^((Q-1)/p) != 1 for all prime factors p
for g := uint64(2); g < Q; g++ {
isGenerator := true
for _, p := range factors {
if e.powMod(g, order/p) == 1 {
isGenerator = false
break
}
}
if isGenerator {
// omega = g^((Q-1)/(2N)) is a primitive 2N-th root
return e.powMod(g, order/(2*N)), nil
}
}
return 0, fmt.Errorf("no primitive root found for N=%d, Q=%d", e.N, Q)
}
// primeFactors returns the distinct prime factors of n
func primeFactors(n uint64) []uint64 {
var factors []uint64
for d := uint64(2); d*d <= n; d++ {
if n%d == 0 {
factors = append(factors, d)
for n%d == 0 {
n /= d
}
}
}
if n > 1 {
factors = append(factors, n)
}
return factors
}
// modInverse computes a^(-1) mod Q using Fermat's little theorem
func (e *NTTEngine) modInverse(a uint64) uint64 {
return e.powMod(a, e.Q-2)
}
// powMod computes base^exp mod Q
func (e *NTTEngine) powMod(base, exp uint64) uint64 {
result := uint64(1)
base = base % e.Q
for exp > 0 {
if exp&1 == 1 {
result = e.mulMod(result, base)
}
base = e.mulMod(base, base)
exp >>= 1
}
return result
}
// computeBarrettMu computes floor(2^64 / Q) for Barrett reduction
func (e *NTTEngine) computeBarrettMu() uint64 {
// mu = floor(2^64 / Q)
// Since we can't represent 2^64 directly, we compute it carefully
// 2^64 / Q = (2^63 / Q) * 2 + ((2^63 mod Q) * 2) / Q
twoTo63 := uint64(1) << 63
q := e.Q
mu := (twoTo63 / q) * 2
rem := ((twoTo63 % q) * 2) / q
return mu + rem
}
// computeMontgomeryR computes R = 2^64 mod Q
func (e *NTTEngine) computeMontgomeryR() uint64 {
// R = 2^64 mod Q
// For Q < 2^63, compute (2^63 mod Q) * 2 mod Q
twoTo63 := uint64(1) << 63
r63 := twoTo63 % e.Q
r := (r63 * 2) % e.Q
return r
}
// computeMontgomeryInv computes -Q^(-1) mod 2^64
func (e *NTTEngine) computeMontgomeryInv() uint64 {
// Newton's method for modular inverse
// x_{n+1} = x_n * (2 - q * x_n) mod 2^64
q := e.Q
x := q // Initial guess
for i := 0; i < 64; i++ {
x = x * (2 - q*x)
}
return -x // -Q^(-1) mod 2^64
}
// ========== SIMD-Optimized Variants ==========
// These provide hooks for assembly implementations
// NTTInPlaceSIMD is a placeholder for assembly-optimized NTT
// On x86-64 with AVX-512, this can process 8 butterflies in parallel
// On ARM64 with NEON, this can process 2 butterflies in parallel
func (e *NTTEngine) NTTInPlaceSIMD(coeffs []uint64) { func (e *NTTEngine) NTTInPlaceSIMD(coeffs []uint64) {
// Check for AVX-512 or NEON support and dispatch e.sr.NTT(coeffs, coeffs)
// For now, fall back to scalar version
e.NTTInPlace(coeffs)
} }
// INTTInPlaceSIMD is a placeholder for assembly-optimized INTT // INTTInPlaceSIMD is an alias for INTTInPlace.
func (e *NTTEngine) INTTInPlaceSIMD(coeffs []uint64) { func (e *NTTEngine) INTTInPlaceSIMD(coeffs []uint64) {
e.INTTInPlace(coeffs) e.sr.INTT(coeffs, coeffs)
}
// PointerSize returns the size of a pointer (used for SIMD dispatch)
func PointerSize() int {
return int(unsafe.Sizeof(uintptr(0)))
} }
+45 -87
View File
@@ -7,14 +7,14 @@ import (
"testing" "testing"
) )
// NTT-friendly primes where Q ≡ 1 (mod 2*N) // NTT-friendly primes where Q ≡ 1 (mod 2*N).
var nttTestCases = []struct { var nttTestCases = []struct {
name string name string
N uint32 N uint32
Q uint64 Q uint64
}{ }{
{"N1024_Q27", 1024, 0x7fff801}, // PN10QP27 {"N1024_Q27", 1024, 0x7fff801}, // PN10QP27
{"N2048_Q54", 2048, 0x3FFFFFFFFED001}, // PN11QP54 (fixed prime) {"N2048_Q54", 2048, 0x3FFFFFFFFED001}, // PN11QP54
} }
func TestNewNTTEngine(t *testing.T) { func TestNewNTTEngine(t *testing.T) {
@@ -34,32 +34,9 @@ func TestNewNTTEngine(t *testing.T) {
} }
} }
func TestPrimeFactors(t *testing.T) { // TestNTTRoundtrip verifies INTT(NTT(x)) == x. The intermediate byte
tests := []struct { // representation is negacyclic (Montgomery form) per the unified Lux
n uint64 // NTT substrate; only round-trip equivalence is asserted here.
want []uint64
}{
{12, []uint64{2, 3}},
{60, []uint64{2, 3, 5}},
{1024, []uint64{2}},
{4096, []uint64{2}},
{97, []uint64{97}}, // prime
{2 * 3 * 5 * 7, []uint64{2, 3, 5, 7}},
}
for _, tc := range tests {
got := primeFactors(tc.n)
if len(got) != len(tc.want) {
t.Errorf("primeFactors(%d) = %v, want %v", tc.n, got, tc.want)
continue
}
for i := range got {
if got[i] != tc.want[i] {
t.Errorf("primeFactors(%d)[%d] = %d, want %d", tc.n, i, got[i], tc.want[i])
}
}
}
}
func TestNTTRoundtrip(t *testing.T) { func TestNTTRoundtrip(t *testing.T) {
for _, tc := range nttTestCases { for _, tc := range nttTestCases {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
@@ -78,7 +55,7 @@ func TestNTTRoundtrip(t *testing.T) {
eng.NTTInPlace(coeffs) eng.NTTInPlace(coeffs)
// After NTT, coeffs should differ from original (for non-trivial input) // After NTT, coeffs should differ from the input (non-trivial transform).
allSame := true allSame := true
for i := 0; i < N; i++ { for i := 0; i < N; i++ {
if coeffs[i] != orig[i] { if coeffs[i] != orig[i] {
@@ -92,7 +69,6 @@ func TestNTTRoundtrip(t *testing.T) {
eng.INTTInPlace(coeffs) eng.INTTInPlace(coeffs)
// After INTT, should recover original
for i := 0; i < N; i++ { for i := 0; i < N; i++ {
if coeffs[i] != orig[i] { if coeffs[i] != orig[i] {
t.Errorf("roundtrip mismatch at [%d]: got %d, want %d", i, coeffs[i], orig[i]) t.Errorf("roundtrip mismatch at [%d]: got %d, want %d", i, coeffs[i], orig[i])
@@ -105,69 +81,51 @@ func TestNTTRoundtrip(t *testing.T) {
} }
} }
// TestNTTRoundtripSIMD exercises the SIMD-named entry points; on the
// unified substrate they delegate to the same body as the scalar path.
func TestNTTRoundtripSIMD(t *testing.T) {
for _, tc := range nttTestCases {
t.Run(tc.name, func(t *testing.T) {
eng, err := NewNTTEngine(tc.N, tc.Q)
if err != nil {
t.Fatalf("NewNTTEngine: %v", err)
}
N := int(tc.N)
orig := make([]uint64, N)
coeffs := make([]uint64, N)
for i := 0; i < N; i++ {
orig[i] = uint64(i) % tc.Q
coeffs[i] = orig[i]
}
eng.NTTInPlaceSIMD(coeffs)
eng.INTTInPlaceSIMD(coeffs)
for i := 0; i < N; i++ {
if coeffs[i] != orig[i] {
t.Errorf("SIMD roundtrip mismatch at [%d]: got %d, want %d", i, coeffs[i], orig[i])
if i > 5 {
t.Fatal("too many mismatches, stopping")
}
}
}
})
}
}
// TestPN11QP54Prime verifies the PN11QP54 modulus is NTT-friendly and the
// engine constructs successfully (the substrate validates primality and
// Q ≡ 1 (mod 2N) inside GenerateNTTConstants).
func TestPN11QP54Prime(t *testing.T) { func TestPN11QP54Prime(t *testing.T) {
// Verify PN11QP54 modulus is NTT-friendly: prime and Q ≡ 1 (mod 2*N)
Q := PN11QP54.QLWE Q := PN11QP54.QLWE
N := uint64(1) << PN11QP54.LogNLWE // 2048 N := uint64(1) << PN11QP54.LogNLWE
if (Q-1)%(2*N) != 0 { if (Q-1)%(2*N) != 0 {
t.Errorf("Q-1 (%d) not divisible by 2N (%d)", Q-1, 2*N) t.Errorf("Q-1 (%d) not divisible by 2N (%d)", Q-1, 2*N)
} }
// Verify NTT engine can be created (requires Q to be usable for NTT) if _, err := NewNTTEngine(uint32(N), Q); err != nil {
eng, err := NewNTTEngine(uint32(N), Q)
if err != nil {
t.Fatalf("NewNTTEngine with PN11QP54: %v", err) t.Fatalf("NewNTTEngine with PN11QP54: %v", err)
} }
// Verify primitive root properties
omega, err := eng.findPrimitiveRoot()
if err != nil {
t.Fatalf("findPrimitiveRoot: %v", err)
}
// omega^(2N) must equal 1
if eng.powMod(omega, 2*N) != 1 {
t.Error("omega^(2N) != 1")
}
// omega^N must equal Q-1 (i.e., -1 mod Q)
if eng.powMod(omega, N) != Q-1 {
t.Errorf("omega^N = %d, want %d (Q-1)", eng.powMod(omega, N), Q-1)
}
// omega^k != 1 for 0 < k < 2N
if eng.powMod(omega, N) == 1 {
t.Error("omega has order <= N, not a primitive 2N-th root")
}
}
func TestFindPrimitiveRootAllFactors(t *testing.T) {
// Verify findPrimitiveRoot checks ALL prime factors of Q-1, not just 2.
// With N=1024, Q=0x7fff801: Q-1 = 134215680 = 2^14 * 3 * 5 * 547
// If only factor 2 were checked, g=2 would falsely pass as a generator.
// With all factors checked, the first generator is found correctly.
Q := uint64(0x7fff801)
eng, err := NewNTTEngine(1024, Q)
if err != nil {
t.Fatal(err)
}
omega, err := eng.findPrimitiveRoot()
if err != nil {
t.Fatal(err)
}
// Verify omega is a proper 2048-th root of unity
N := uint64(1024)
if eng.powMod(omega, 2*N) != 1 {
t.Error("omega^(2N) != 1")
}
if eng.powMod(omega, N) == 1 {
t.Error("omega has order dividing N, not a primitive 2N-th root")
}
// omega^N must be -1 (mod Q) for a primitive 2N-th root
if eng.powMod(omega, N) != Q-1 {
t.Errorf("omega^N = %d, want Q-1 = %d", eng.powMod(omega, N), Q-1)
}
} }