Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bgv-to-lattigo: lower client-interface and plain op #1226

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

ZenithalHourlyRate
Copy link
Collaborator

With this PR we can lower the dot_product_8 example with client interface. The emitter/tests has not been added as there are hacks in this pass that needs discussion.

lwe-add-client-interface will add helper function for encryption/decryption, and the function signature is __encrypt(value, sk/pk). However, this is only for openfhe backend, as openfhe needs CryptoContext and sk/pk to encrypt/decrypt, and openfhe lowering will add its own CryptoContext arg.

For lattigo, things are different in that we have evaluator/encryptor/decryptor/encoder/decoder instead of one context, and all of them should be passed on-demand.

This brings the complicacy that a lot of predicating is needed to make sure things are added in correct order, otherwise the function signature is not stable.

Currently I add evaluator in a specified order with predicate, so we can have more predictable function signature.

With --mlir-to-secret-arithmetic --secret-insert-mgmt-bgv --secret-distribute-generic --secret-to-bgv="poly-mod-degree=8" --lwe-add-client-interface --bgv-to-lwe --bgv-to-lattigo we can get the following IR (of course with some ASM trick locally #1219)

  func.func @dot_product(%evaluator: !evaluator, %params: !params, %encoder: !encoder, %ct: !ct, %ct_0: !ct) -> !ct
  
  func.func @dot_product__encrypt(%evaluator: !evaluator, %params: !params, %encoder: !encoder, %encryptor: !encryptor, %arg0: tensor<8xi16>, %arg1: tensor<8xi16>, %skey: !skey) -> (!ct, !ct) {
    %pt = lattigo.bgv.new_plaintext %params : (!params) -> !pt
    %pt_0 = lattigo.bgv.encode %encoder, %arg0, %pt : (!encoder, tensor<8xi16>, !pt) -> !pt
    %ct = lattigo.rlwe.encrypt %encryptor, %pt_0 : (!encryptor, !pt) -> !ct
    %pt_1 = lattigo.bgv.new_plaintext %params : (!params) -> !pt
    %pt_2 = lattigo.bgv.encode %encoder, %arg1, %pt_1 : (!encoder, tensor<8xi16>, !pt) -> !pt
    %ct_3 = lattigo.rlwe.encrypt %encryptor, %pt_2 : (!encryptor, !pt) -> !ct
    return %ct, %ct_3 : !ct, !ct
  }

    func.func @dot_product__decrypt(%evaluator: !evaluator, %params: !params, %encoder: !encoder, %decryptor: !decryptor, %ct: !ct, %skey: !skey) -> i16 {
    %pt = lattigo.rlwe.decrypt %decryptor, %ct : (!decryptor, !ct) -> !pt
    %cst = arith.constant dense<0> : tensor<1xi16>
    %0 = lattigo.bgv.decode %encoder, %pt, %cst : (!encoder, !pt, tensor<1xi16>) -> tensor<1xi16>
    %c0 = arith.constant 0 : index
    %extracted = tensor.extract %0[%c0] : tensor<1xi16>
    return %extracted : i16
  }

Discussion

  • in __encrypt/decrypt the skey is not needed. This is produced by lwe-add-client-interface but not used by furthur backend pass, so should we either not produce it or detele it here. (involves some ordering/validity check of function signature update)
  • This should be re-organized in similar style to Merge --<bgv/ckks>-to-openfhe into --lwe-to-openfhe #1196 as a --lwe-to-lattigo.
  • lwe.reinterpret_underlying_type should be moved earlier (packing pipeline). Backend should not care about them (only care about ct types but not pt types). It used to work because we forward lwe type to openfhe dialect, but not this way for lattigo dialect. Similarly bgv.extract should be moved earlier, which I used bgv-to-lwe to handle it (Use tensor_ext::ExtractOp for extracting an element out of a slot of a single ciphertext #1174).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant