Skip to content

Incorrect result when adding back an encrypted input after a multiplication chain #1309

Description

@zooiik

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions