Files
precompile/FHE_MUTEX_FIX_PLAN.md
zeekay 5405979295 reconcile: carry FHE+attestation mutex-fix analysis onto refactored main
WIP main was an orphaned old base; remote main is the canonical refactor
(p3q/+starkfri/ split, slot 0x012205=P3Q, newer dep pins) and already
contains the P3Q work. The only genuinely-new, non-superseded WIP artifact
is this still-relevant data-race analysis (remote fhe/*.go still has no
mutex). dex/engine_embedded.go intentionally dropped: remote refactor
removed the embedded AMM in favor of the inert default and added
inert_no_embedded_test.go asserting it is gone.

Full WIP preserved on branch wip/local + tag backup/pre-reconcile-main.
2026-06-20 18:33:16 +00:00

3.3 KiB
Raw Permalink Blame History

FHE + Attestation Mutex Fix Plan

Status: Analysis complete (agent a0677f0c, 2026-04-10). Implementation blocked by usage limit.

Threat Model

  • Assets: Consensus determinism across validator nodes
  • Adversary: Concurrent EVM transaction execution within a block
  • Attack: Unprotected map writes → data races → non-determinism → chain split

Findings

REAL bugs requiring fix

  1. FHE — /Users/z/work/lux/precompile/fhe/contract.go

    • ciphertextStore — no lock
    • ciphertextTypes — no lock
    • Pattern: every operation reads & writes → heavy R+W
    • Fix: sync.RWMutex (reads are more frequent)
      • getCiphertext called 2× per binary op → RLock
      • storeCiphertext called 1× → Lock
  2. attestation — /Users/z/work/lux/precompile/attestation/

    • globalVerifier — from luxfi/ai library, no visible internal locking
    • nvtrustVerifier — same, no guard
    • Library Verifier has internal mutable state (device registrations, job completions)
    • Fix: Wrap calls in package-level sync.RWMutex, OR upstream the fix to luxfi/ai

Already protected (no fix needed)

Package Lock Notes
zk/stark.go starkVerifiersMu OK
zk/pedersen.go sync.RWMutex on pointCache + globalPedersen OK
zk/poseidon.go cacheMu OK
zk/verifier.go internal mu OK
frost liftXCacheMu OK
quantum qv.mu OK
dex per-struct mu; HookSignatures read-only after init OK
bridge gateway.go + signer.go have internal mu OK
graph OracleQueries + AMMQueries + PredefinedQueries are read-only literals OK
ai privacyMultipliers read-only; baseRewardPerMinute only .Set() reads OK
threshold only error sentinels (immutable) OK

Implementation

// fhe/contract.go additions:
var (
    ciphertextStoreMu sync.RWMutex
    ciphertextStore   = make(map[string]*tfhe.Ciphertext)
    ciphertextTypes   = make(map[string]int)
)

func storeCiphertext(key string, ct *tfhe.Ciphertext, fheType int) {
    ciphertextStoreMu.Lock()
    defer ciphertextStoreMu.Unlock()
    ciphertextStore[key] = ct
    ciphertextTypes[key] = fheType
}

func getCiphertext(key string) (*tfhe.Ciphertext, int, bool) {
    ciphertextStoreMu.RLock()
    defer ciphertextStoreMu.RUnlock()
    ct, ok := ciphertextStore[key]
    if !ok {
        return nil, 0, false
    }
    return ct, ciphertextTypes[key], true
}

Test (must add)

// fhe/concurrency_test.go
func TestFHE_ConcurrentAccess(t *testing.T) {
    const N = 100
    var wg sync.WaitGroup
    wg.Add(N)
    for i := 0; i < N; i++ {
        go func(i int) {
            defer wg.Done()
            // perform FHE op that reads+writes maps
            _, _ = runFheOp(/* ... */)
        }(i)
    }
    wg.Wait()
}

Run with: go test -race -run TestFHE_ConcurrentAccess

Out-of-scope packages

Per analysis, all other packages already have proper synchronization. Do NOT add mutexes where not needed — that's just noise.

Commits expected

  1. fhe: add sync.RWMutex to ciphertextStore and ciphertextTypes (prevents consensus split)
  2. attestation: protect globalVerifier + nvtrustVerifier with sync.RWMutex
  3. precompile: add concurrency tests for fhe + attestation