noise — error distribution and tracking

lattice security comes from noise. jali provides the noise model — generation, tracking, and bound estimation.

error distributions

sample_uniform(n: usize) → RingElement
  each coefficient uniform in [0, p)
  used for: public matrices A

sample_ternary(n: usize) → RingElement
  each coefficient in {-1, 0, 1}
  used for: secret keys, short vectors

sample_gaussian(n: usize, sigma: f64) → RingElement
  each coefficient from discrete Gaussian with standard deviation σ
  used for: LWE error terms

sample_cbd(n: usize, eta: usize) → RingElement
  centered binomial distribution with parameter η
  used for: ML-KEM noise (faster than Gaussian, similar security)

noise tracking

FHE operations increase noise in ciphertexts. when noise exceeds a threshold, decryption fails. tracking noise bounds is essential for correctness.

NoiseBudget {
  log_bound: u32     // log₂ of noise bound
}

noise_after_add(a: NoiseBudget, b: NoiseBudget) → NoiseBudget
  log_bound = max(a.log_bound, b.log_bound) + 1

noise_after_mul(a: NoiseBudget, b: NoiseBudget) → NoiseBudget
  log_bound = a.log_bound + b.log_bound + log₂(n)

noise_after_bootstrap() → NoiseBudget
  log_bound = bootstrap_noise    // fixed, determined by parameters

needs_bootstrap(budget: NoiseBudget, max_budget: u32) → bool
  budget.log_bound >= max_budget - safety_margin

noise in zheng proofs

zheng ring-aware proving tracks noise via running accumulator (not per-operation range checks):

generic:     64 constraints per coefficient per operation (range check)
             n coefficients × m operations = 64nm constraints

ring-aware:  running accumulator, fold noise bound per step
             check once at bootstrapping boundary
             ~30 field ops per fold

dependencies

  • nebu: F_p arithmetic for coefficient generation
  • jali::ring: RingElement type

Dimensions

noise
anything that moves focus distribution $\pi^*$ toward uniform. noise is the complement of syntropy the formal definition the cybergraph's total informational capacity over $|P|$ particles is $\log|P|$ bits. that capacity is always partitioned: $$\underbrace{J(\pi^*)}_{\text{syntropy}} +…

Local Graph