Skip to content

refactor: revert encrypt workaround once upstream poulpy bug is fixed #24

@cedoor

Description

@cedoor

Problem

Context::encrypt currently uses a workaround pipeline because the upstream poulpy FheUint::encrypt_sk -> FheUintPrepared::prepare path produces incorrect ciphertexts in the pinned poulpy revision (see the crate::ciphertext module docs).

The workaround forces several deviations from squid's normal patterns:

  • Ciphertext carries an extra prepared: Option<FheUintPrepared> cache field (src/ciphertext.rs).
  • Context::encrypt routes through FheUintPrepared::encrypt_sk followed by FheUint::from_fhe_uint_prepared instead of the natural encrypt_sk -> prepare.
  • Context::encrypt allocates a hardcoded 1 << 22 (4 MiB) scratch arena (ENCRYPT_SCRATCH_BYTES) because poulpy exposes no wrapper-level *_tmp_bytes for the two workaround functions.
  • Context::eval_binary has a "chaining limitation": only freshly-encrypted ciphertexts can be operated on, because the prepared cache cannot be rebuilt from a serialized / op-output Ciphertext (the prepare path that would rebuild it is exactly the broken one).

Proposed fix

When the poulpy prepare bug is resolved upstream, revert squid's encrypt (and supporting types) back to the original pattern:

  1. FheUint::encrypt_sk (size via FheUint::encrypt_sk_tmp_bytes).
  2. FheUintPrepared::prepare on demand (size via Module::fhe_uint_prepare_tmp_bytes).

Then collapse the workaround scaffolding:

  • Drop Ciphertext::prepared; Ciphertext becomes a thin wrapper over FheUint again.
  • Replace ENCRYPT_SCRATCH_BYTES with a single max(...) of the two *_tmp_bytes helpers above (matches keygen / decrypt / eval_binary).
  • Remove the chaining-limitation panic and docs in Context::eval_binary and crate::ciphertext; rebuild the prepared form on the fly inside eval_binary from the packed FheUint.

Tradeoff

None expected — this is a pure regression-of-a-workaround. Memory drops (no per-Ciphertext prepared cache, smaller encrypt arena) and the API surface gets simpler (op outputs and deserialized ciphertexts become first-class operands again).

Before implementing

Confirm the upstream bug is fixed against squid's reproducer (tests/poulpy_manual_bdd.rs and the prepare_then_add test added in poulpy). Bump the poulpy pin, then do the revert in one PR.

Related code

  • src/context.rsContext::encrypt (with the TODO(poulpy-bug) comment), Context::eval_binary.
  • src/ciphertext.rsCiphertext struct + chaining-limitation docs.
  • tests/poulpy_manual_bdd.rs — local reproducer of the upstream bug.

Metadata

Metadata

Assignees

Labels

refactoringRelated to code restructuring without behavior change

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions