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

Merged

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).

@ZenithalHourlyRate ZenithalHourlyRate force-pushed the lattigo-context-upstream branch 2 times, most recently from 079e14a to e6c79ed Compare January 14, 2025 14:10
@ZenithalHourlyRate ZenithalHourlyRate marked this pull request as ready for review January 14, 2025 14:11
@ZenithalHourlyRate
Copy link
Collaborator Author

Ready for review now. This PR has been big enough.

Added mlir-to-lattigo-bgv pipeline, and we are able to e2e test dot_product_8 example for lattigo.

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)

Cleaned it up in conversion.

This should be re-organized in similar style to #1196 as a --lwe-to-lattigo.

Will leave it for future PR.

@@ -97,7 +97,7 @@ class Lattigo_BGVBinaryOp<string mnemonic> :
let arguments = (ins
Lattigo_BGVEvaluator:$evaluator,
Lattigo_RLWECiphertext:$lhs,
Lattigo_RLWECiphertext:$rhs
AnyType:$rhs
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we make this slightly more constrained than AnyType? I think this was changed because it's a union of ciphertext or plaintext type?

@ZenithalHourlyRate
Copy link
Collaborator Author

Rebased as #1257 merged.

Could we make this slightly more constrained than AnyType? I think this was changed because it's a union of ciphertext or plaintext type?

Added a Lattigo_RLWECiphertextOrPlaintext constraint.

@j2kun j2kun added the pull_ready Indicates whether a PR is ready to pull. The copybara worker will import for internal testing label Jan 15, 2025
@copybara-service copybara-service bot merged commit ae28ea7 into google:main Jan 17, 2025
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pull_ready Indicates whether a PR is ready to pull. The copybara worker will import for internal testing
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants