Summary
What happened: In this simple program below, the plaintext result is stable, but the decrypted FHE result does not match it when I return var11 + x as the final result. If I instead return only var11 (without adding x), the FHE result matches the plaintext result.
What you expected to happen: Correct results whether or not I add back the encrypted input x at the end.
Description
versions affected: 2.11.0
minimal POC to trigger the bug:
from concrete import fhe
import numpy as np
@fhe.compiler({"x": "encrypted", "y": "encrypted"})
def test(x, y):
var2 = y - x
var3 = (x > var2) * 1
var4 = 3 + var3
var7 = -10 * var4
var8 = var7 - 13
var9 = var8 * 13
var11 = 13 * var9
return var11 + x
x, y = -60, 2
circuit = test.compile(fhe.inputset(fhe.int8, fhe.int8, size=100000))
circuit.keygen()
enc_res = circuit.run(circuit.encrypt(x, y))
result = circuit.decrypt(enc_res)
print(f"Plaintext VS. FHE Computation: {test(x, y)} VS. {result}")
print(circuit)
Output:
Plaintext VS. FHE Computation: -7327 VS. -13762
%0 = x # EncryptedScalar<int8> ∈ [-128, 127]
%1 = y # EncryptedScalar<int8> ∈ [-128, 127]
%2 = subtract(%1, %0) # EncryptedScalar<int9> ∈ [-255, 254]
%3 = greater(%0, %2) # EncryptedScalar<uint1> ∈ [0, 1]
%4 = 1 # ClearScalar<uint1> ∈ [1, 1]
%5 = multiply(%3, %4) # EncryptedScalar<uint1> ∈ [0, 1]
%6 = 3 # ClearScalar<uint2> ∈ [3, 3]
%7 = add(%6, %5) # EncryptedScalar<uint3> ∈ [3, 4]
%8 = -10 # ClearScalar<int5> ∈ [-10, -10]
%9 = multiply(%8, %7) # EncryptedScalar<int7> ∈ [-40, -30]
%10 = 13 # ClearScalar<uint4> ∈ [13, 13]
%11 = subtract(%9, %10) # EncryptedScalar<int7> ∈ [-53, -43]
%12 = 13 # ClearScalar<uint4> ∈ [13, 13]
%13 = multiply(%11, %12) # EncryptedScalar<int11> ∈ [-689, -559]
%14 = 13 # ClearScalar<uint4> ∈ [13, 13]
%15 = multiply(%14, %13) # EncryptedScalar<int15> ∈ [-8957, -7267]
%16 = add(%15, %0) # EncryptedScalar<int15> ∈ [-9020, -7204]
return %16
If I instead return only var11, the FHE result matches the plaintext result (both are -7267). So this bug only appears when I add back the encrypted input x at the end, which might be related to how the final addition with an encrypted input is handled after a long multiplication chain.
Summary
What happened: In this simple program below, the plaintext result is stable, but the decrypted FHE result does not match it when I return
var11 + xas the final result. If I instead return onlyvar11(without addingx), the FHE result matches the plaintext result.What you expected to happen: Correct results whether or not I add back the encrypted input
xat the end.Description
versions affected: 2.11.0
minimal POC to trigger the bug:
Output:
If I instead return only
var11, the FHE result matches the plaintext result (both are-7267). So this bug only appears when I add back the encrypted inputxat the end, which might be related to how the final addition with an encrypted input is handled after a long multiplication chain.