mirror of
https://github.com/luxfi/lattice.git
synced 2026-09-24 00:25:44 +00:00
Static-checks job has been failing on every PR (including #3) due to a shell-interpolation bug in the Makefile + a build of accumulated lint findings the bug had been hiding. Cleaned up end-to-end so make checks runs green and PR #3 (security/readuint-slice-dos-2026-03-03) can land. 1. Makefile fmt-step: quote $$FMTOUT in `[ -z $$FMTOUT ]` test. Unquoted, multi-file go-fmt output word-splits and the test sees `[ -z FILE1 FILE2 ]` -> "/bin/sh: [: FILE2: unexpected operator". Same fix to the trailing `echo $$FMTOUT`. 2. go fmt sweep: gpu/gpu.go, gpu/gpu_test.go, types/reduction_test.go, types/trust_test.go had whitespace-only formatter findings that the crashing fmt-test step had been hiding. 3. ST1003 (mixed-case identifier): four wire-format-pinned consts in types/trust.go (TrustCpuGpuCompositeTEE / IOLevelCpu*) carry a //lint:ignore directive — their String() return values are part of the wire/log contract documented at line 80 ("do not rename"), so the Go-side identifiers must stay byte-aligned with the wire spelling. 4. ST1005 (capitalized error string): two error strings in gpu/gpu.go rephrased to lead with a noun ("ring degree N" / "modulus Q-1" instead of capital "N" / capital "Q") without changing semantics. 5. ST1000 (package comment): gpu/gpu_montgomery_*.go file header reformatted so the "Package gpu" line is the leading sentence. 6. G104 (unhandled errors): four `prng.Read(b)` call sites in gpu/gpu.go now `_, _ = prng.Read(b)` — the PRNG is keyed sampling output; read length is bounded by buffer length and a short read here is not a correctness issue. 7. G115 (int -> uint conversion): types/reduction.go switches `bitlen` to int (matches bits.Len64's return type, used only against literal small ints in the comparison ladder). gpu/gpu_montgomery_purego.go adds /* #nosec G115 */ on uint32(s.N) — s.N is validated >0 and bounded by ring degree above. 8. NO-STUB POLICY: gpu/gpu_montgomery_stub.go renamed to gpu/gpu_montgomery_purego.go and given a real pure-Go body that delegates to ring.SubRing.NTT / INTT (the canonical Go implementation in this repo). The "stub" name was misleading: there should never be a Lux Go file that returns "GPU unavailable" errors when the cgo+gpu build tag is unset — the pure-Go path is the canonical reference and always works. Output is byte-equal to the cgo+gpu path, identical semantics across build tags. Same rename for ring/ntt_simd_stub.go -> ring/ntt_simd_dispatch_purego.go with comment update: it's a dispatch hook (returns false to signal "use canonical scalar NTT below"), not an incomplete impl. Verification: * make checks: all 6 substeps PASS (go fmt / vet / goimports / staticcheck / govulncheck / gosec) on this branch. * go test -count=1 ./...: all packages green; ring + ringqp + schemes/bgv + schemes/ckks + multiparty + utils/* all pass.
243 lines
6.9 KiB
Go
243 lines
6.9 KiB
Go
// Copyright (c) 2026, Lux Industries Inc.
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package types
|
|
|
|
import (
|
|
"bytes"
|
|
"testing"
|
|
"unsafe"
|
|
)
|
|
|
|
// TestComputeTrustMode_StableValues pins the underlying integer values of
|
|
// every ComputeTrustMode variant. The C++ mirror at
|
|
// luxcpp/lattice/include/lux/lattice/types/trust.hpp asserts the same
|
|
// values; if either side drifts, dispatch silently misclassifies workers
|
|
// at the trust boundary.
|
|
func TestComputeTrustMode_StableValues(t *testing.T) {
|
|
cases := []struct {
|
|
mode ComputeTrustMode
|
|
want uint8
|
|
}{
|
|
{TrustPublicDeterministic, 0},
|
|
{TrustAttestedGpuOnly, 1},
|
|
{TrustCpuGpuCompositeTEE, 2},
|
|
{TrustConfidentialIO, 3},
|
|
{TrustZKOrFraudProofed, 4},
|
|
}
|
|
for _, c := range cases {
|
|
if uint8(c.mode) != c.want {
|
|
t.Errorf("%s: got %d want %d", c.mode, uint8(c.mode), c.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestComputeTrustMode_Order verifies that trust modes form a strict
|
|
// monotonic chain. Eligible() in the registry uses `>=` on this ordering;
|
|
// if two variants compare equal, the gate degrades to a substring match.
|
|
func TestComputeTrustMode_Order(t *testing.T) {
|
|
chain := []ComputeTrustMode{
|
|
TrustPublicDeterministic,
|
|
TrustAttestedGpuOnly,
|
|
TrustCpuGpuCompositeTEE,
|
|
TrustConfidentialIO,
|
|
TrustZKOrFraudProofed,
|
|
}
|
|
for i := 1; i < len(chain); i++ {
|
|
if !(chain[i] > chain[i-1]) {
|
|
t.Fatalf("trust ordering broken at %s -> %s", chain[i-1], chain[i])
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestComputeTrustMode_String(t *testing.T) {
|
|
cases := []struct {
|
|
mode ComputeTrustMode
|
|
want string
|
|
}{
|
|
{TrustPublicDeterministic, "PublicDeterministic"},
|
|
{TrustAttestedGpuOnly, "AttestedGpuOnly"},
|
|
{TrustCpuGpuCompositeTEE, "CpuGpuCompositeTEE"},
|
|
{TrustConfidentialIO, "ConfidentialIO"},
|
|
{TrustZKOrFraudProofed, "ZKOrFraudProofed"},
|
|
{ComputeTrustMode(99), "Unknown"},
|
|
}
|
|
for _, c := range cases {
|
|
if got := c.mode.String(); got != c.want {
|
|
t.Errorf("%d: got %q want %q", uint8(c.mode), got, c.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestComputeTrustMode_Valid(t *testing.T) {
|
|
for m := ComputeTrustMode(0); m <= TrustZKOrFraudProofed; m++ {
|
|
if !m.Valid() {
|
|
t.Errorf("expected %s to be valid", m)
|
|
}
|
|
}
|
|
if ComputeTrustMode(99).Valid() {
|
|
t.Error("expected 99 to be invalid")
|
|
}
|
|
}
|
|
|
|
// TestConfidentialIOLevel_StableValues pins the underlying integer values
|
|
// of every ConfidentialIOLevel variant. Mirrors the C++ static_assert on
|
|
// the same enum.
|
|
func TestConfidentialIOLevel_StableValues(t *testing.T) {
|
|
cases := []struct {
|
|
level ConfidentialIOLevel
|
|
want uint8
|
|
}{
|
|
{IOLevelNone, 0},
|
|
{IOLevelCpuTeeOnly, 1},
|
|
{IOLevelCpuGpuComposite, 2},
|
|
{IOLevelProtectedCpuGpuTransfer, 3},
|
|
{IOLevelFullDeviceIOAttested, 4},
|
|
}
|
|
for _, c := range cases {
|
|
if uint8(c.level) != c.want {
|
|
t.Errorf("%s: got %d want %d", c.level, uint8(c.level), c.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestConfidentialIOLevel_Order(t *testing.T) {
|
|
chain := []ConfidentialIOLevel{
|
|
IOLevelNone,
|
|
IOLevelCpuTeeOnly,
|
|
IOLevelCpuGpuComposite,
|
|
IOLevelProtectedCpuGpuTransfer,
|
|
IOLevelFullDeviceIOAttested,
|
|
}
|
|
for i := 1; i < len(chain); i++ {
|
|
if !(chain[i] > chain[i-1]) {
|
|
t.Fatalf("io level ordering broken at %s -> %s", chain[i-1], chain[i])
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestConfidentialIOLevel_String(t *testing.T) {
|
|
cases := []struct {
|
|
level ConfidentialIOLevel
|
|
want string
|
|
}{
|
|
{IOLevelNone, "None"},
|
|
{IOLevelCpuTeeOnly, "CpuTeeOnly"},
|
|
{IOLevelCpuGpuComposite, "CpuGpuComposite"},
|
|
{IOLevelProtectedCpuGpuTransfer, "ProtectedCpuGpuTransfer"},
|
|
{IOLevelFullDeviceIOAttested, "FullDeviceIOAttested"},
|
|
{ConfidentialIOLevel(99), "Unknown"},
|
|
}
|
|
for _, c := range cases {
|
|
if got := c.level.String(); got != c.want {
|
|
t.Errorf("%d: got %q want %q", uint8(c.level), got, c.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestConfidentialIOLevel_Valid(t *testing.T) {
|
|
for l := ConfidentialIOLevel(0); l <= IOLevelFullDeviceIOAttested; l++ {
|
|
if !l.Valid() {
|
|
t.Errorf("expected %s to be valid", l)
|
|
}
|
|
}
|
|
if ConfidentialIOLevel(99).Valid() {
|
|
t.Error("expected 99 to be invalid")
|
|
}
|
|
}
|
|
|
|
// TestWorkloadPrivacyClass_StableValues pins the underlying integer values
|
|
// of every WorkloadPrivacyClass variant.
|
|
func TestWorkloadPrivacyClass_StableValues(t *testing.T) {
|
|
cases := []struct {
|
|
class WorkloadPrivacyClass
|
|
want uint8
|
|
}{
|
|
{PrivacyPublic, 0},
|
|
{PrivacyPrivateUserData, 1},
|
|
{PrivacyPrivateModelWeights, 2},
|
|
{PrivacyValidatorKeyMaterial, 3},
|
|
{PrivacyRegulatedOrderflow, 4},
|
|
{PrivacyResearchContribution, 5},
|
|
}
|
|
for _, c := range cases {
|
|
if uint8(c.class) != c.want {
|
|
t.Errorf("%s: got %d want %d", c.class, uint8(c.class), c.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestWorkloadPrivacyClass_String(t *testing.T) {
|
|
cases := []struct {
|
|
class WorkloadPrivacyClass
|
|
want string
|
|
}{
|
|
{PrivacyPublic, "Public"},
|
|
{PrivacyPrivateUserData, "PrivateUserData"},
|
|
{PrivacyPrivateModelWeights, "PrivateModelWeights"},
|
|
{PrivacyValidatorKeyMaterial, "ValidatorKeyMaterial"},
|
|
{PrivacyRegulatedOrderflow, "RegulatedOrderflow"},
|
|
{PrivacyResearchContribution, "ResearchContribution"},
|
|
{WorkloadPrivacyClass(99), "Unknown"},
|
|
}
|
|
for _, c := range cases {
|
|
if got := c.class.String(); got != c.want {
|
|
t.Errorf("%d: got %q want %q", uint8(c.class), got, c.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestWorkloadPrivacyClass_Valid(t *testing.T) {
|
|
for c := WorkloadPrivacyClass(0); c <= PrivacyResearchContribution; c++ {
|
|
if !c.Valid() {
|
|
t.Errorf("expected %s to be valid", c)
|
|
}
|
|
}
|
|
if WorkloadPrivacyClass(99).Valid() {
|
|
t.Error("expected 99 to be invalid")
|
|
}
|
|
}
|
|
|
|
// trustTriple is a Go-side mirror of luxcpp/lattice/test/trust_test.cpp::
|
|
// TrustTriple. It is laid out as four bytes so the byte image is identical
|
|
// across Go and C++. The only purpose of this struct is the cross-language
|
|
// layout test; do not export it.
|
|
type trustTriple struct {
|
|
Trust ComputeTrustMode
|
|
IO ConfidentialIOLevel
|
|
Privacy WorkloadPrivacyClass
|
|
_pad uint8
|
|
}
|
|
|
|
// TestTrustEnum_CrossLangByteImage asserts that a {trust, io, privacy, pad}
|
|
// quadruple has identical byte representation between Go and C++. The
|
|
// matching C++ test is luxcpp/lattice/test/trust_test.cpp::
|
|
// test_trust_triple_byte_image. If either side changes enum width or value,
|
|
// both this Go test and the C++ memcmp test MUST be updated together.
|
|
func TestTrustEnum_CrossLangByteImage(t *testing.T) {
|
|
if got := unsafe.Sizeof(trustTriple{}); got != 4 {
|
|
t.Fatalf("trustTriple size: got %d want 4", got)
|
|
}
|
|
if got := unsafe.Offsetof(trustTriple{}.Trust); got != 0 {
|
|
t.Errorf("Trust offset: got %d want 0", got)
|
|
}
|
|
if got := unsafe.Offsetof(trustTriple{}.IO); got != 1 {
|
|
t.Errorf("IO offset: got %d want 1", got)
|
|
}
|
|
if got := unsafe.Offsetof(trustTriple{}.Privacy); got != 2 {
|
|
t.Errorf("Privacy offset: got %d want 2", got)
|
|
}
|
|
|
|
tt := trustTriple{
|
|
Trust: TrustConfidentialIO, // 3
|
|
IO: IOLevelProtectedCpuGpuTransfer, // 3
|
|
Privacy: PrivacyValidatorKeyMaterial, // 3
|
|
_pad: 0,
|
|
}
|
|
want := []byte{0x03, 0x03, 0x03, 0x00}
|
|
got := unsafe.Slice((*byte)(unsafe.Pointer(&tt)), unsafe.Sizeof(tt))
|
|
if !bytes.Equal(got, want) {
|
|
t.Fatalf("trustTriple byte image mismatch with C++ side\n got: %x\n want: %x", got, want)
|
|
}
|
|
}
|