mirror of
https://github.com/zama-ai/tfhe-rs.git
synced 2026-04-28 03:01:21 -04:00
Compare commits
1 Commits
am/chore/m
...
tm/shuffle
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88241fee21 |
@@ -4,6 +4,9 @@ ignore = [
|
||||
"RUSTSEC-2024-0436",
|
||||
# Ignoring unmaintained 'bincode' crate. Getting rid of it would be too complex on the short term.
|
||||
"RUSTSEC-2025-0141",
|
||||
# Ignoring unsoundness in 'rand' with custom logger. Rand update is currently blocked by
|
||||
# arkworks and we do not use custom loggers.
|
||||
"RUSTSEC-2026-0097",
|
||||
]
|
||||
|
||||
[output]
|
||||
|
||||
4
.github/workflows/aws_data_tests.yml
vendored
4
.github/workflows/aws_data_tests.yml
vendored
@@ -54,7 +54,7 @@ jobs:
|
||||
|
||||
- name: Retrieve data from cache
|
||||
id: retrieve-data-cache
|
||||
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae #v5.0.5
|
||||
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 #v5.0.4
|
||||
with:
|
||||
path: |
|
||||
utils/tfhe-backward-compat-data/**/*.cbor
|
||||
@@ -89,7 +89,7 @@ jobs:
|
||||
- name: Store data in cache
|
||||
if: steps.retrieve-data-cache.outputs.cache-hit != 'true'
|
||||
continue-on-error: true
|
||||
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae #v5.0.5
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 #v5.0.4
|
||||
with:
|
||||
path: |
|
||||
utils/tfhe-backward-compat-data/**/*.cbor
|
||||
|
||||
6
.github/workflows/aws_tfhe_fast_tests.yml
vendored
6
.github/workflows/aws_tfhe_fast_tests.yml
vendored
@@ -69,7 +69,7 @@ jobs:
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
dependencies:
|
||||
@@ -200,7 +200,7 @@ jobs:
|
||||
|
||||
- name: Node cache restoration
|
||||
id: node-cache
|
||||
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae #v5.0.5
|
||||
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 #v5.0.4
|
||||
with:
|
||||
path: |
|
||||
~/.nvm
|
||||
@@ -213,7 +213,7 @@ jobs:
|
||||
make install_node
|
||||
|
||||
- name: Node cache save
|
||||
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae #v5.0.5
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 #v5.0.4
|
||||
if: steps.node-cache.outputs.cache-hit != 'true'
|
||||
with:
|
||||
path: |
|
||||
|
||||
2
.github/workflows/aws_tfhe_integer_tests.yml
vendored
2
.github/workflows/aws_tfhe_integer_tests.yml
vendored
@@ -56,7 +56,7 @@ jobs:
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
integer:
|
||||
|
||||
@@ -57,7 +57,7 @@ jobs:
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
integer:
|
||||
|
||||
2
.github/workflows/aws_tfhe_tests.yml
vendored
2
.github/workflows/aws_tfhe_tests.yml
vendored
@@ -78,7 +78,7 @@ jobs:
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
dependencies:
|
||||
|
||||
6
.github/workflows/aws_tfhe_wasm_tests.yml
vendored
6
.github/workflows/aws_tfhe_wasm_tests.yml
vendored
@@ -45,7 +45,7 @@ jobs:
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
wasm:
|
||||
@@ -92,7 +92,7 @@ jobs:
|
||||
|
||||
- name: Node cache restoration
|
||||
id: node-cache
|
||||
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae #v5.0.5
|
||||
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 #v5.0.4
|
||||
with:
|
||||
path: |
|
||||
~/.nvm
|
||||
@@ -105,7 +105,7 @@ jobs:
|
||||
make install_node
|
||||
|
||||
- name: Node cache save
|
||||
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae #v5.0.5
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 #v5.0.4
|
||||
if: steps.node-cache.outputs.cache-hit != 'true'
|
||||
with:
|
||||
path: |
|
||||
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
backward:
|
||||
|
||||
@@ -204,7 +204,7 @@ jobs:
|
||||
uses: foundry-rs/foundry-toolchain@8789b3e21e6c11b2697f5eb56eddae542f746c10
|
||||
|
||||
- name: Cache cargo
|
||||
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
@@ -232,7 +232,7 @@ jobs:
|
||||
working-directory: fhevm/coprocessor/fhevm-engine/tfhe-worker
|
||||
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||
with:
|
||||
node-version: 20.x
|
||||
|
||||
|
||||
2
.github/workflows/benchmark_wasm_client.yml
vendored
2
.github/workflows/benchmark_wasm_client.yml
vendored
@@ -46,7 +46,7 @@ jobs:
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
wasm_bench:
|
||||
|
||||
@@ -124,7 +124,7 @@ jobs:
|
||||
|
||||
- name: Node cache restoration
|
||||
id: node-cache
|
||||
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae #v5.0.5
|
||||
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 #v5.0.4
|
||||
with:
|
||||
path: |
|
||||
~/.nvm
|
||||
@@ -137,7 +137,7 @@ jobs:
|
||||
make install_node
|
||||
|
||||
- name: Node cache save
|
||||
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae #v5.0.5
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 #v5.0.4
|
||||
if: steps.node-cache.outputs.cache-hit != 'true'
|
||||
with:
|
||||
path: |
|
||||
|
||||
4
.github/workflows/cargo_build_common.yml
vendored
4
.github/workflows/cargo_build_common.yml
vendored
@@ -138,7 +138,7 @@ jobs:
|
||||
- name: Node cache restoration
|
||||
if: inputs.run-pcc-cpu-batch == 'pcc_batch_2'
|
||||
id: node-cache
|
||||
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae #v5.0.5
|
||||
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 #v5.0.4
|
||||
with:
|
||||
path: |
|
||||
~/.nvm
|
||||
@@ -151,7 +151,7 @@ jobs:
|
||||
make install_node
|
||||
|
||||
- name: Node cache save
|
||||
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae #v5.0.5
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 #v5.0.4
|
||||
if: inputs.run-pcc-cpu-batch == 'pcc_batch_2' && steps.node-cache.outputs.cache-hit != 'true'
|
||||
with:
|
||||
path: |
|
||||
|
||||
2
.github/workflows/cargo_test_fft.yml
vendored
2
.github/workflows/cargo_test_fft.yml
vendored
@@ -40,7 +40,7 @@ jobs:
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
fft:
|
||||
|
||||
2
.github/workflows/cargo_test_ntt.yml
vendored
2
.github/workflows/cargo_test_ntt.yml
vendored
@@ -42,7 +42,7 @@ jobs:
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
ntt:
|
||||
|
||||
2
.github/workflows/ci_lint.yml
vendored
2
.github/workflows/ci_lint.yml
vendored
@@ -43,7 +43,7 @@ jobs:
|
||||
echo "version=$(make zizmor_version)" >> "${GITHUB_OUTPUT}"
|
||||
|
||||
- name: Check workflows security
|
||||
uses: zizmorcore/zizmor-action@b1d7e1fb5de872772f31590499237e7cce841e8e # v0.5.3
|
||||
uses: zizmorcore/zizmor-action@71321a20a9ded102f6e9ce5718a2fcec2c4f70d8 # v0.5.2
|
||||
with:
|
||||
advanced-security: 'false' # Print results directly in logs
|
||||
persona: pedantic
|
||||
|
||||
2
.github/workflows/code_coverage.yml
vendored
2
.github/workflows/code_coverage.yml
vendored
@@ -44,7 +44,7 @@ jobs:
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
tfhe:
|
||||
|
||||
@@ -46,7 +46,7 @@ jobs:
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
csprng:
|
||||
|
||||
2
.github/workflows/gpu_core_h100_tests.yml
vendored
2
.github/workflows/gpu_core_h100_tests.yml
vendored
@@ -49,7 +49,7 @@ jobs:
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
gpu:
|
||||
|
||||
2
.github/workflows/gpu_fast_tests.yml
vendored
2
.github/workflows/gpu_fast_tests.yml
vendored
@@ -47,7 +47,7 @@ jobs:
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
gpu:
|
||||
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
gpu:
|
||||
|
||||
2
.github/workflows/gpu_hlapi_h100_tests.yml
vendored
2
.github/workflows/gpu_hlapi_h100_tests.yml
vendored
@@ -49,7 +49,7 @@ jobs:
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
gpu:
|
||||
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
gpu:
|
||||
|
||||
2
.github/workflows/gpu_memory_sanitizer.yml
vendored
2
.github/workflows/gpu_memory_sanitizer.yml
vendored
@@ -48,7 +48,7 @@ jobs:
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
gpu:
|
||||
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
gpu:
|
||||
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
gpu:
|
||||
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
gpu:
|
||||
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
gpu:
|
||||
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
gpu:
|
||||
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
gpu:
|
||||
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
gpu:
|
||||
|
||||
2
.github/workflows/gpu_zk_tests.yml
vendored
2
.github/workflows/gpu_zk_tests.yml
vendored
@@ -47,7 +47,7 @@ jobs:
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
gpu:
|
||||
|
||||
2
.github/workflows/hpu_hlapi_tests.yml
vendored
2
.github/workflows/hpu_hlapi_tests.yml
vendored
@@ -41,7 +41,7 @@ jobs:
|
||||
|
||||
- name: Check for file changes
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # v47.0.6
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
|
||||
with:
|
||||
files_yaml: |
|
||||
hpu:
|
||||
|
||||
2
.github/workflows/make_release_tfhe.yml
vendored
2
.github/workflows/make_release_tfhe.yml
vendored
@@ -89,7 +89,7 @@ jobs:
|
||||
make build_web_js_api_parallel
|
||||
|
||||
- name: Authenticate on NPM
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
|
||||
with:
|
||||
node-version: '24'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
4
.github/workflows/parameters_check.yml
vendored
4
.github/workflows/parameters_check.yml
vendored
@@ -53,7 +53,7 @@ jobs:
|
||||
|
||||
- name: Restore Sagemath image from cache
|
||||
id: docker-cache
|
||||
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae #v5.0.5
|
||||
uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 #v5.0.4
|
||||
with:
|
||||
path: /tmp/sagemath_image
|
||||
key: sagemath-image-${{ env.SAGEMATH_VERSION }}-${{ github.sha }}
|
||||
@@ -76,7 +76,7 @@ jobs:
|
||||
- name: Store Sagemath image in cache
|
||||
if: steps.docker-cache.outputs.cache-hit != 'true'
|
||||
continue-on-error: true
|
||||
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae #v5.0.5
|
||||
uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 #v5.0.4
|
||||
with:
|
||||
path: /tmp/sagemath_image
|
||||
key: sagemath-image-${{ env.SAGEMATH_VERSION }}-${{ github.sha }}
|
||||
|
||||
2
Makefile
2
Makefile
@@ -360,7 +360,7 @@ check_fmt_toml: install_taplo
|
||||
|
||||
.PHONY: check_typos # Check for typos in codebase
|
||||
check_typos: install_typos_checker
|
||||
@git ls-files ":!*.png" ":!*.cbor" ":!*.bcode" ":!*.ico" ":!*/twiddles.cu" ":!*.hpu" | typos --file-list - && echo "No typos found"
|
||||
@git ls-files ":!*.png" ":!*.cbor" ":!*.bcode" ":!*.ico" ":!*/twiddles.cu" | typos --file-list - && echo "No typos found"
|
||||
|
||||
.PHONY: clippy_gpu # Run clippy lints on tfhe with "gpu" enabled
|
||||
clippy_gpu: install_rs_check_toolchain
|
||||
|
||||
@@ -156,7 +156,7 @@ impl HpuVarWrapped {
|
||||
{
|
||||
let mut inner = var.inner.lock().unwrap();
|
||||
|
||||
for (slot, ct) in std::iter::zip(inner.bundle.iter_mut(), ct) {
|
||||
for (slot, ct) in std::iter::zip(inner.bundle.iter_mut(), ct.into_iter()) {
|
||||
#[cfg(feature = "io-dump")]
|
||||
let params = ct.params().clone();
|
||||
for (id, cut) in ct.into_container().iter().enumerate() {
|
||||
|
||||
@@ -1 +1 @@
|
||||
nightly-2026-04-22
|
||||
nightly-2026-01-14
|
||||
|
||||
@@ -97,6 +97,12 @@ path = "benches/high_level_api/erc7984.rs"
|
||||
harness = false
|
||||
required-features = ["integer", "internal-keycache"]
|
||||
|
||||
[[bench]]
|
||||
name = "hlapi-bitonic-shuffle"
|
||||
path = "benches/high_level_api/bitonic_shuffle.rs"
|
||||
harness = false
|
||||
required-features = ["integer", "internal-keycache"]
|
||||
|
||||
[[bench]]
|
||||
name = "hlapi-dex"
|
||||
path = "benches/high_level_api/dex.rs"
|
||||
|
||||
53
tfhe-benchmark/benches/high_level_api/bitonic_shuffle.rs
Normal file
53
tfhe-benchmark/benches/high_level_api/bitonic_shuffle.rs
Normal file
@@ -0,0 +1,53 @@
|
||||
use benchmark::params_aliases::BENCH_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
use criterion::{black_box, criterion_group, Criterion};
|
||||
use rand::Rng;
|
||||
use tfhe::core_crypto::seeders::UnixSeeder;
|
||||
use tfhe::prelude::*;
|
||||
use tfhe::{bitonic_shuffle, set_server_key, ClientKey, ConfigBuilder, FheUint64, ServerKey};
|
||||
|
||||
fn bitonic_shuffle_bench(c: &mut Criterion, bench_name: &str, cks: &ClientKey) {
|
||||
let mut bench_group = c.benchmark_group(bench_name);
|
||||
bench_group.sample_size(10);
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
for num_elements in [16, 32] {
|
||||
let clear_values: Vec<u64> = (0..num_elements).map(|_| rng.gen()).collect();
|
||||
let encrypted: Vec<FheUint64> = clear_values
|
||||
.iter()
|
||||
.map(|&v| FheUint64::encrypt(v, cks))
|
||||
.collect();
|
||||
|
||||
let bench_id = format!("{bench_name}::n_{num_elements}");
|
||||
|
||||
bench_group.bench_function(&bench_id, |b| {
|
||||
b.iter(|| {
|
||||
let mut seeder = UnixSeeder::new(0);
|
||||
let result = bitonic_shuffle(
|
||||
encrypted.clone(),
|
||||
tfhe::integer::server_key::BitonicShuffleKeySize::NumBlocks(16),
|
||||
&mut seeder,
|
||||
)
|
||||
.expect("shuffle failed");
|
||||
black_box(result);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
bench_group.finish();
|
||||
}
|
||||
|
||||
pub fn bitonic_shuffle_cpu(c: &mut Criterion) {
|
||||
let param = BENCH_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let config = ConfigBuilder::with_custom_parameters(param).build();
|
||||
let cks = ClientKey::generate(config);
|
||||
let sks = ServerKey::new(&cks);
|
||||
|
||||
rayon::broadcast(|_| set_server_key(sks.clone()));
|
||||
set_server_key(sks);
|
||||
|
||||
bitonic_shuffle_bench(c, "hlapi::bitonic_shuffle_cpu", &cks);
|
||||
}
|
||||
|
||||
criterion_group!(bitonic_shuffle_group, bitonic_shuffle_cpu);
|
||||
criterion::criterion_main!(bitonic_shuffle_group);
|
||||
@@ -168,7 +168,7 @@ mod generic_tests {
|
||||
fn test_xof_seed_getters() {
|
||||
let seed_bytes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
|
||||
let bits = u128::from_le_bytes(seed_bytes);
|
||||
let dsep = *b"tfheksps";
|
||||
let dsep = [b't', b'f', b'h', b'e', b'k', b's', b'p', b's'];
|
||||
let seed = XofSeed::new_u128(bits, dsep);
|
||||
|
||||
let s = u128::from_le_bytes(seed.seed().try_into().unwrap());
|
||||
|
||||
@@ -64,7 +64,7 @@ tfhe-fft = { version = "0.10.1", path = "../tfhe-fft", features = [
|
||||
"serde",
|
||||
"fft128",
|
||||
] }
|
||||
tfhe-ntt = { version = "0.7.1", path = "../tfhe-ntt" }
|
||||
tfhe-ntt = { version = "0.7.0", path = "../tfhe-ntt" }
|
||||
pulp = { workspace = true, features = ["default"] }
|
||||
tfhe-cuda-backend = { version = "0.14.0", path = "../backends/tfhe-cuda-backend", optional = true }
|
||||
aligned-vec = { workspace = true, features = ["default", "serde"] }
|
||||
|
||||
@@ -75,11 +75,11 @@
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="420.0">121 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="420.0">165 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="460.0">Leading / Trailing zeros/ones</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="460.0">67.2 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="460.0">70.6 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="460.0">89.8 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="460.0">92.6 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="460.0">113 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="460.0">88.4 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="460.0">148 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="460.0">169 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="460.0">222 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="460.0">275 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="500.0">Log2</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="500.0">110 ms</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="500.0">163 ms</text>
|
||||
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
@@ -75,11 +75,11 @@
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="420.0">32.5 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="420.0">14.0 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="460.0">Leading / Trailing zeros/ones</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="460.0">824 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="460.0">487 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="460.0">222 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="460.0">119 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="460.0">57.8 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="460.0">625 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="460.0">247 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="510.0" y="460.0">108 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="594.0" y="460.0">44.1 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="678.0" y="460.0">19.0 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="start" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="6" y="500.0">Log2</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="342.0" y="500.0">542 ops/s</text>
|
||||
<text dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="14" font-weight="normal" fill="black" x="426.0" y="500.0">220 ops/s</text>
|
||||
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
@@ -85,7 +85,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
let public_key = tfhe::CompactPublicKey::try_new(&client_key).unwrap();
|
||||
// This can be left empty, but if provided allows to tie the proof to arbitrary data
|
||||
let metadata = b"TFHE-rs";
|
||||
let metadata = [b'T', b'F', b'H', b'E', b'-', b'r', b's'];
|
||||
|
||||
let clear_a = random::<u64>();
|
||||
let clear_b = random::<u64>();
|
||||
@@ -93,7 +93,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let proven_compact_list = tfhe::ProvenCompactCiphertextList::builder(&public_key)
|
||||
.push(clear_a)
|
||||
.push(clear_b)
|
||||
.build_with_proof_packed(&crs, metadata, ZkComputeLoad::Verify)?;
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Verify)?;
|
||||
|
||||
// Server side
|
||||
let result = {
|
||||
@@ -101,7 +101,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
// Verify the proofs and expand the ciphertexts
|
||||
let expander =
|
||||
proven_compact_list.verify_and_expand(&crs, &public_key, metadata)?;
|
||||
proven_compact_list.verify_and_expand(&crs, &public_key, &metadata)?;
|
||||
let a: tfhe::FheUint64 = expander.get(0)?.unwrap();
|
||||
let b: tfhe::FheUint64 = expander.get(1)?.unwrap();
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ pub fn main() {
|
||||
let rerand_domain_separator = *b"TFHE_Rrd";
|
||||
|
||||
let crs = CompactPkeCrs::from_config(config, 2048).unwrap();
|
||||
let metadata = b"rerand";
|
||||
let metadata = [b'r', b'e', b'r', b'a', b'n', b'd'];
|
||||
|
||||
set_server_key(sks);
|
||||
|
||||
@@ -132,7 +132,7 @@ pub fn main() {
|
||||
.push(clear_a)
|
||||
.push(clear_b)
|
||||
.push(false)
|
||||
.build_with_proof_packed(&crs, metadata, ZkComputeLoad::Proof)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
// Simulate a 256 bits nonce
|
||||
@@ -151,7 +151,7 @@ pub fn main() {
|
||||
|
||||
// Verify, re_randomize and expand
|
||||
let expander = compact_list
|
||||
.verify_re_randomize_and_expand(&crs, &cpk, metadata, seed_gen.next_seed().unwrap())
|
||||
.verify_re_randomize_and_expand(&crs, &cpk, &metadata, seed_gen.next_seed().unwrap())
|
||||
.unwrap();
|
||||
|
||||
let a: FheUint64 = expander.get(0).unwrap().unwrap();
|
||||
|
||||
@@ -46,7 +46,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let server_key = tfhe::ServerKey::new(&client_key);
|
||||
let public_key = tfhe::CompactPublicKey::try_new(&client_key).unwrap();
|
||||
// This can be left empty, but if provided allows to tie the proof to arbitrary data
|
||||
let metadata = b"TFHE-rs";
|
||||
let metadata = [b'T', b'F', b'H', b'E', b'-', b'r', b's'];
|
||||
|
||||
let clear_a = rng.gen::<u64>();
|
||||
let clear_b = rng.gen::<u64>();
|
||||
@@ -54,7 +54,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let proven_compact_list = tfhe::ProvenCompactCiphertextList::builder(&public_key)
|
||||
.push(clear_a)
|
||||
.push(clear_b)
|
||||
.build_with_proof_packed(&crs, metadata, ZkComputeLoad::Verify)?;
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Verify)?;
|
||||
|
||||
// Server side
|
||||
let result = {
|
||||
@@ -62,7 +62,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
// Verify the ciphertexts
|
||||
let expander =
|
||||
proven_compact_list.verify_and_expand(&crs, &public_key, metadata)?;
|
||||
proven_compact_list.verify_and_expand(&crs, &public_key, &metadata)?;
|
||||
let a: tfhe::FheUint64 = expander.get(0)?.unwrap();
|
||||
let b: tfhe::FheUint64 = expander.get(1)?.unwrap();
|
||||
|
||||
@@ -118,7 +118,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let server_key = tfhe::ServerKey::new(&client_key);
|
||||
let public_key = tfhe::CompactPublicKey::try_new(&client_key).unwrap();
|
||||
// This can be left empty, but if provided allows to tie the proof to arbitrary data
|
||||
let metadata = b"TFHE-rs";
|
||||
let metadata = [b'T', b'F', b'H', b'E', b'-', b'r', b's'];
|
||||
|
||||
let clear_a = rng.gen::<u64>();
|
||||
let clear_b = rng.gen::<u64>();
|
||||
@@ -126,7 +126,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let proven_compact_list = tfhe::ProvenCompactCiphertextList::builder(&public_key)
|
||||
.push(clear_a)
|
||||
.push(clear_b)
|
||||
.build_with_proof_packed(&crs, metadata, ZkComputeLoad::Verify)?;
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Verify)?;
|
||||
|
||||
// Server side
|
||||
let result = {
|
||||
@@ -134,7 +134,7 @@ pub fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
// Verify the ciphertexts
|
||||
let expander =
|
||||
proven_compact_list.verify_and_expand(&crs, &public_key, metadata)?;
|
||||
proven_compact_list.verify_and_expand(&crs, &public_key, &metadata)?;
|
||||
let a: tfhe::FheUint64 = expander.get(0)?.unwrap();
|
||||
let b: tfhe::FheUint64 = expander.get(1)?.unwrap();
|
||||
|
||||
|
||||
@@ -252,7 +252,9 @@ where
|
||||
))
|
||||
}
|
||||
|
||||
const NON_ESCAPABLE_SYMBOLS: [u8; 14] = *b"&;:,`~-_!@#%'\"";
|
||||
const NON_ESCAPABLE_SYMBOLS: [u8; 14] = [
|
||||
b'&', b';', b':', b',', b'`', b'~', b'-', b'_', b'!', b'@', b'#', b'%', b'\'', b'\"',
|
||||
];
|
||||
|
||||
fn atom<Input>() -> impl Parser<Input, Output = RegExpr>
|
||||
where
|
||||
|
||||
@@ -1251,7 +1251,7 @@ pub fn encrypt_lwe_ciphertext_iterator_with_seeded_public_key<Scalar, KeyCont, O
|
||||
}
|
||||
}
|
||||
|
||||
for (output_ct, plaintext) in output.iter_mut().zip(encoded) {
|
||||
for (output_ct, plaintext) in output.iter_mut().zip(encoded.into_iter()) {
|
||||
lwe_ciphertext_plaintext_add_assign(output_ct, plaintext);
|
||||
}
|
||||
}
|
||||
@@ -2123,7 +2123,7 @@ pub fn encrypt_lwe_ciphertext_with_compact_public_key<
|
||||
///
|
||||
/// // We can add custom metadata that will be required for verification, allowing to tie the proof
|
||||
/// // to some arbitrary data.
|
||||
/// let metadata = b"TFHE-rs";
|
||||
/// let metadata = [b'T', b'F', b'H', b'E', b'-', b'r', b's'];
|
||||
///
|
||||
/// // Create the PRNG
|
||||
/// let mut seeder = new_seeder();
|
||||
@@ -2170,14 +2170,14 @@ pub fn encrypt_lwe_ciphertext_with_compact_public_key<
|
||||
/// glwe_noise_distribution,
|
||||
/// encryption_generator.noise_generator_mut(),
|
||||
/// &crs,
|
||||
/// metadata,
|
||||
/// &metadata,
|
||||
/// ZkComputeLoad::Proof,
|
||||
/// )
|
||||
/// .unwrap();
|
||||
///
|
||||
/// // verify the ciphertext list with the proof
|
||||
/// assert!(
|
||||
/// verify_lwe_ciphertext(&lwe, &lwe_compact_public_key, &proof, &crs, metadata).is_valid()
|
||||
/// verify_lwe_ciphertext(&lwe, &lwe_compact_public_key, &proof, &crs, &metadata).is_valid()
|
||||
/// );
|
||||
///
|
||||
/// let decrypted_plaintext = decrypt_lwe_ciphertext(&lwe_secret_key, &lwe);
|
||||
@@ -2572,7 +2572,7 @@ pub fn encrypt_lwe_compact_ciphertext_list_with_compact_public_key<
|
||||
///
|
||||
/// // We can add custom metadata that will be required for verification, allowing to tie the proof
|
||||
/// // to some arbitrary data.
|
||||
/// let metadata = b"TFHE-rs";
|
||||
/// let metadata = [b'T', b'F', b'H', b'E', b'-', b'r', b's'];
|
||||
///
|
||||
/// // Create the PRNG
|
||||
/// let mut seeder = new_seeder();
|
||||
@@ -2623,7 +2623,7 @@ pub fn encrypt_lwe_compact_ciphertext_list_with_compact_public_key<
|
||||
/// glwe_noise_distribution,
|
||||
/// encryption_generator.noise_generator_mut(),
|
||||
/// &crs,
|
||||
/// metadata,
|
||||
/// &metadata,
|
||||
/// ZkComputeLoad::Proof,
|
||||
/// )
|
||||
/// .unwrap();
|
||||
@@ -2634,7 +2634,7 @@ pub fn encrypt_lwe_compact_ciphertext_list_with_compact_public_key<
|
||||
/// &lwe_compact_public_key,
|
||||
/// &proof,
|
||||
/// &crs,
|
||||
/// metadata,
|
||||
/// &metadata,
|
||||
/// )
|
||||
/// .is_valid());
|
||||
///
|
||||
@@ -3045,7 +3045,7 @@ pub fn par_encrypt_lwe_compact_ciphertext_list_with_compact_public_key<
|
||||
///
|
||||
/// // We can add custom metadata that will be required for verification, allowing to tie the proof
|
||||
/// // to some arbitrary data.
|
||||
/// let metadata = b"TFHE-rs";
|
||||
/// let metadata = [b'T', b'F', b'H', b'E', b'-', b'r', b's'];
|
||||
///
|
||||
/// // Create the PRNG
|
||||
/// let mut seeder = new_seeder();
|
||||
@@ -3096,7 +3096,7 @@ pub fn par_encrypt_lwe_compact_ciphertext_list_with_compact_public_key<
|
||||
/// glwe_noise_distribution,
|
||||
/// encryption_generator.noise_generator_mut(),
|
||||
/// &crs,
|
||||
/// metadata,
|
||||
/// &metadata,
|
||||
/// ZkComputeLoad::Proof,
|
||||
/// )
|
||||
/// .unwrap();
|
||||
@@ -3107,7 +3107,7 @@ pub fn par_encrypt_lwe_compact_ciphertext_list_with_compact_public_key<
|
||||
/// &lwe_compact_public_key,
|
||||
/// &proof,
|
||||
/// &crs,
|
||||
/// metadata,
|
||||
/// &metadata,
|
||||
/// )
|
||||
/// .is_valid());
|
||||
///
|
||||
|
||||
@@ -1010,7 +1010,7 @@ fn lwe_compact_public_encrypt_prove_verify_decrypt_custom_mod<Scalar>(
|
||||
let message_modulus_log = params.message_modulus_log;
|
||||
let encoding_with_padding = get_encoding_with_padding(ciphertext_modulus);
|
||||
|
||||
let metadata = b"core";
|
||||
let metadata = [b'c', b'o', b'r', b'e'];
|
||||
|
||||
let mut rsc = TestResources::new();
|
||||
let mut random_generator = RandomGenerator::<DefaultRandomGenerator>::new(rsc.seeder.seed());
|
||||
@@ -1073,7 +1073,7 @@ fn lwe_compact_public_encrypt_prove_verify_decrypt_custom_mod<Scalar>(
|
||||
glwe_noise_distribution,
|
||||
rsc.encryption_random_generator.noise_generator_mut(),
|
||||
crs,
|
||||
metadata,
|
||||
&metadata,
|
||||
ZkComputeLoad::Proof,
|
||||
)
|
||||
.unwrap();
|
||||
@@ -1090,13 +1090,13 @@ fn lwe_compact_public_encrypt_prove_verify_decrypt_custom_mod<Scalar>(
|
||||
assert_eq!(msg, decoded);
|
||||
|
||||
// Verify the proof
|
||||
assert!(verify_lwe_ciphertext(&ct, &pk, &proof, crs, metadata).is_valid());
|
||||
assert!(verify_lwe_ciphertext(&ct, &pk, &proof, crs, &metadata).is_valid());
|
||||
|
||||
// verify proof with invalid ciphertext
|
||||
let index = random_generator.gen::<usize>() % ct.as_ref().len();
|
||||
let value_to_add = random_generator.gen::<Scalar>();
|
||||
ct.as_mut()[index] = ct.as_mut()[index].wrapping_add(value_to_add);
|
||||
assert!(verify_lwe_ciphertext(&ct, &pk, &proof, crs, metadata).is_invalid());
|
||||
assert!(verify_lwe_ciphertext(&ct, &pk, &proof, crs, &metadata).is_invalid());
|
||||
}
|
||||
|
||||
// In coverage, we break after one while loop iteration, changing message values does
|
||||
@@ -1122,7 +1122,7 @@ fn test_par_compact_lwe_list_public_key_encryption_and_proof() {
|
||||
let glwe_noise_distribution = TUniform::new(9);
|
||||
let ciphertext_modulus = CiphertextModulus::new_native();
|
||||
|
||||
let metadata = b"core";
|
||||
let metadata = [b'c', b'o', b'r', b'e'];
|
||||
|
||||
let delta_log = 59;
|
||||
let delta = 1u64 << delta_log;
|
||||
@@ -1195,7 +1195,7 @@ fn test_par_compact_lwe_list_public_key_encryption_and_proof() {
|
||||
glwe_noise_distribution,
|
||||
encryption_random_generator.noise_generator_mut(),
|
||||
&crs,
|
||||
metadata,
|
||||
&metadata,
|
||||
ZkComputeLoad::Proof,
|
||||
)
|
||||
.unwrap();
|
||||
@@ -1205,7 +1205,7 @@ fn test_par_compact_lwe_list_public_key_encryption_and_proof() {
|
||||
&compact_lwe_pk,
|
||||
&proof,
|
||||
&crs,
|
||||
metadata
|
||||
&metadata
|
||||
)
|
||||
.is_valid());
|
||||
|
||||
@@ -1236,7 +1236,7 @@ fn test_par_compact_lwe_list_public_key_encryption_and_proof() {
|
||||
&compact_lwe_pk,
|
||||
&proof,
|
||||
&crs,
|
||||
metadata
|
||||
&metadata
|
||||
)
|
||||
.is_invalid());
|
||||
|
||||
@@ -1284,7 +1284,7 @@ fn test_par_compact_lwe_list_public_key_encryption_and_proof() {
|
||||
glwe_noise_distribution,
|
||||
encryption_random_generator.noise_generator_mut(),
|
||||
&crs,
|
||||
metadata,
|
||||
&metadata,
|
||||
ZkComputeLoad::Proof,
|
||||
)
|
||||
.unwrap();
|
||||
@@ -1294,7 +1294,7 @@ fn test_par_compact_lwe_list_public_key_encryption_and_proof() {
|
||||
&compact_lwe_pk,
|
||||
&proof,
|
||||
&crs,
|
||||
metadata
|
||||
&metadata
|
||||
)
|
||||
.is_valid());
|
||||
|
||||
@@ -1325,7 +1325,7 @@ fn test_par_compact_lwe_list_public_key_encryption_and_proof() {
|
||||
&compact_lwe_pk,
|
||||
&proof,
|
||||
&crs,
|
||||
metadata
|
||||
&metadata
|
||||
)
|
||||
.is_invalid());
|
||||
|
||||
|
||||
@@ -538,5 +538,4 @@ macro_rules! create_parameterized_test_with_non_native_parameters {
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) use create_parameterized_test;
|
||||
pub(crate) use create_parameterized_test_with_non_native_parameters;
|
||||
pub(crate) use {create_parameterized_test, create_parameterized_test_with_non_native_parameters};
|
||||
|
||||
@@ -19,7 +19,7 @@ pub fn pbs_variance_132_bits_security_gaussian(
|
||||
lwe_dimension.0 as f64,
|
||||
glwe_dimension.0 as f64,
|
||||
polynomial_size.0 as f64,
|
||||
var_min.0,
|
||||
var_min.0 as f64,
|
||||
decomposition_level_count.0 as f64,
|
||||
decomposition_base_log.0 as f64,
|
||||
ciphertext_modulus,
|
||||
@@ -45,7 +45,7 @@ pub fn pbs_variance_132_bits_security_tuniform(
|
||||
lwe_dimension.0 as f64,
|
||||
glwe_dimension.0 as f64,
|
||||
polynomial_size.0 as f64,
|
||||
var_min.0,
|
||||
var_min.0 as f64,
|
||||
decomposition_level_count.0 as f64,
|
||||
decomposition_base_log.0 as f64,
|
||||
ciphertext_modulus,
|
||||
|
||||
@@ -53,7 +53,7 @@ macro_rules! implement_gaussian {
|
||||
for a in uniform_rand_bytes_v.iter_mut() {
|
||||
*a = generator.generate_next();
|
||||
}
|
||||
let size = <$T as crate::core_crypto::commons::numeric::Numeric>::BITS as i32;
|
||||
let size = <$T>::BITS as i32;
|
||||
let mut u: $T = <$S>::from_le_bytes(uniform_rand_bytes_u).cast_into();
|
||||
u *= <$T>::TWO.powi(-size + 1);
|
||||
let mut v: $T = <$S>::from_le_bytes(uniform_rand_bytes_v).cast_into();
|
||||
|
||||
@@ -102,7 +102,7 @@ macro_rules! implement {
|
||||
self.floor()
|
||||
}
|
||||
fn to_bit_string(&self) -> String {
|
||||
if <Self as Numeric>::BITS == 32 {
|
||||
if Self::BITS == 32 {
|
||||
let mut bit_string = format!("{:032b}", self.to_bits());
|
||||
bit_string.insert(1, ' ');
|
||||
bit_string.insert(10, ' ');
|
||||
|
||||
@@ -108,14 +108,14 @@ fn plans() -> &'static PlanMap {
|
||||
}
|
||||
|
||||
pub fn setup_custom_fft_plan(plan: Plan) {
|
||||
let fft_size = FourierPolynomialSize(plan.fft_size());
|
||||
let std_poly_size = fft_size.to_standard_polynomial_size();
|
||||
let base_n = FourierPolynomialSize(plan.fft_size());
|
||||
let n = base_n.to_standard_polynomial_size();
|
||||
|
||||
let plan = Arc::new((Twisties::new(fft_size.0), plan));
|
||||
let plan = Arc::new((Twisties::new(base_n.0), plan));
|
||||
|
||||
let global_plans = plans();
|
||||
|
||||
global_plans.set(std_poly_size, plan);
|
||||
global_plans.set(n, plan);
|
||||
}
|
||||
|
||||
/// Return the input slice, cast to the same type.
|
||||
|
||||
@@ -99,6 +99,7 @@ macro_rules! create_gpu_multi_bit_ks32_parameterized_test{
|
||||
}
|
||||
use crate::core_crypto::gpu::algorithms::test::params::MultiBitTestKS32Params;
|
||||
use crate::core_crypto::gpu::lwe_packing_keyswitch_key::CudaLwePackingKeyswitchKey;
|
||||
use create_gpu_multi_bit_ks32_parameterized_test;
|
||||
use create_gpu_multi_bit_parameterized_test;
|
||||
use create_gpu_parameterized_test;
|
||||
use {
|
||||
create_gpu_multi_bit_ks32_parameterized_test, create_gpu_multi_bit_parameterized_test,
|
||||
create_gpu_parameterized_test,
|
||||
};
|
||||
|
||||
@@ -870,7 +870,7 @@ mod zk {
|
||||
let crs = CompactPkeCrs::from_config(config.into(), 64).unwrap();
|
||||
let public_key = crate::CompactPublicKey::try_new(&client_key).unwrap();
|
||||
|
||||
let metadata = b"TFHE-rs";
|
||||
let metadata = [b'T', b'F', b'H', b'E', b'-', b'r', b's'];
|
||||
|
||||
let clear_a = rng.gen::<u64>();
|
||||
let clear_b = rng.gen::<bool>();
|
||||
@@ -878,7 +878,7 @@ mod zk {
|
||||
let proven_compact_list = crate::ProvenCompactCiphertextList::builder(&public_key)
|
||||
.push(clear_a)
|
||||
.push(clear_b)
|
||||
.build_with_proof_packed(&crs, metadata, ZkComputeLoad::Proof)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
let params =
|
||||
@@ -1628,7 +1628,7 @@ mod tests {
|
||||
// Intentionally low so that we test when multiple lists and proofs are needed
|
||||
let crs = CompactPkeCrs::from_config(config, 32).unwrap();
|
||||
|
||||
let metadata = b"hlapi";
|
||||
let metadata = [b'h', b'l', b'a', b'p', b'i'];
|
||||
|
||||
let compact_list = ProvenCompactCiphertextList::builder(&pk)
|
||||
.push(17u32)
|
||||
@@ -1636,12 +1636,14 @@ mod tests {
|
||||
.push(false)
|
||||
.push_with_num_bits(3u32, 2)
|
||||
.unwrap()
|
||||
.build_with_proof_packed(&crs, metadata, ZkComputeLoad::Proof)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
let serialized = bincode::serialize(&compact_list).unwrap();
|
||||
let compact_list: ProvenCompactCiphertextList = bincode::deserialize(&serialized).unwrap();
|
||||
let expander = compact_list.verify_and_expand(&crs, &pk, metadata).unwrap();
|
||||
let expander = compact_list
|
||||
.verify_and_expand(&crs, &pk, &metadata)
|
||||
.unwrap();
|
||||
|
||||
{
|
||||
let a: FheUint32 = expander.get(0).unwrap().unwrap();
|
||||
@@ -1707,7 +1709,7 @@ mod tests {
|
||||
set_server_key(sks);
|
||||
|
||||
let crs = CompactPkeCrs::from_config(config, 32).unwrap();
|
||||
let metadata = b"seed";
|
||||
let metadata = [b's', b'e', b'e', b'd'];
|
||||
|
||||
let mut rng = thread_rng();
|
||||
let seed_a: [u8; 16] = rng.gen();
|
||||
@@ -1719,7 +1721,7 @@ mod tests {
|
||||
.push(17u32)
|
||||
.push(-1i64)
|
||||
.push(false)
|
||||
.build_with_proof_packed_seeded(&crs, metadata, ZkComputeLoad::Proof, seed)
|
||||
.build_with_proof_packed_seeded(&crs, &metadata, ZkComputeLoad::Proof, seed)
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
@@ -1736,7 +1738,7 @@ mod tests {
|
||||
"different seeds must produce different output"
|
||||
);
|
||||
|
||||
let expander = list_a1.verify_and_expand(&crs, &pk, metadata).unwrap();
|
||||
let expander = list_a1.verify_and_expand(&crs, &pk, &metadata).unwrap();
|
||||
let a: FheUint32 = expander.get(0).unwrap().unwrap();
|
||||
let b: FheInt64 = expander.get(1).unwrap().unwrap();
|
||||
let c: FheBool = expander.get(2).unwrap().unwrap();
|
||||
@@ -1767,13 +1769,15 @@ mod tests {
|
||||
|
||||
let crs = CompactPkeCrs::from_config(config, 32).unwrap();
|
||||
|
||||
let metadata = b"hlapi";
|
||||
let metadata = [b'h', b'l', b'a', b'p', b'i'];
|
||||
|
||||
let compact_list = CompactCiphertextList::builder(&pk)
|
||||
.build_with_proof_packed(&crs, metadata, ZkComputeLoad::Proof)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
let expander = compact_list.verify_and_expand(&crs, &pk, metadata).unwrap();
|
||||
let expander = compact_list
|
||||
.verify_and_expand(&crs, &pk, &metadata)
|
||||
.unwrap();
|
||||
|
||||
assert!(expander.get::<FheBool>(0).unwrap().is_none());
|
||||
}
|
||||
@@ -1814,7 +1818,7 @@ mod tests {
|
||||
// Intentionally low so that we test when multiple lists and proofs are needed
|
||||
let crs = CompactPkeCrs::from_config(config, 32).unwrap();
|
||||
|
||||
let metadata = b"hlapi";
|
||||
let metadata = [b'h', b'l', b'a', b'p', b'i'];
|
||||
|
||||
let compact_list = ProvenCompactCiphertextList::builder(&pk)
|
||||
.push(17u32)
|
||||
@@ -1822,13 +1826,15 @@ mod tests {
|
||||
.push(false)
|
||||
.push_with_num_bits(3u32, 2)
|
||||
.unwrap()
|
||||
.build_with_proof_packed(&crs, metadata, ZkComputeLoad::Proof)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
let serialized = bincode::serialize(&compact_list).unwrap();
|
||||
let compact_list: ProvenCompactCiphertextList =
|
||||
bincode::deserialize(&serialized).unwrap();
|
||||
let expander = compact_list.verify_and_expand(&crs, &pk, metadata).unwrap();
|
||||
let expander = compact_list
|
||||
.verify_and_expand(&crs, &pk, &metadata)
|
||||
.unwrap();
|
||||
|
||||
{
|
||||
let a: FheUint32 = expander.get(0).unwrap().unwrap();
|
||||
|
||||
@@ -49,6 +49,7 @@ pub use signed::{CompressedFheInt, FheInt, FheIntId, SquashedNoiseFheInt};
|
||||
pub use unsigned::{CompressedFheUint, FheUint, FheUintId, SquashedNoiseFheUint};
|
||||
|
||||
pub mod oprf;
|
||||
pub mod shuffle;
|
||||
pub(super) mod signed;
|
||||
pub(super) mod unsigned;
|
||||
|
||||
|
||||
121
tfhe/src/high_level_api/integers/shuffle.rs
Normal file
121
tfhe/src/high_level_api/integers/shuffle.rs
Normal file
@@ -0,0 +1,121 @@
|
||||
use crate::high_level_api::global_state;
|
||||
use crate::high_level_api::integers::FheIntegerType;
|
||||
use crate::high_level_api::keys::InternalServerKey;
|
||||
use crate::high_level_api::re_randomization::ReRandomizationMetadata;
|
||||
use crate::integer::server_key::radix_parallel::bitonic_shuffle::BitonicShuffleKeySize;
|
||||
use tfhe_csprng::seeders::Seeder;
|
||||
|
||||
/// Shuffles `data` into a uniformly random permutation using a bitonic
|
||||
/// sorting network with OPRF-generated random keys.
|
||||
///
|
||||
/// `key_size` controls the bit-width of the random sort keys used internally,
|
||||
/// either by specifying a target collision probability or by passing a raw
|
||||
/// block count. Larger keys reduce collision probability (improving shuffle
|
||||
/// uniformity) at the cost of more computation per comparison.
|
||||
///
|
||||
/// The re-randomization metadata of the input elements is not preserved
|
||||
/// through the shuffle.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the resolved key block count is 0, or if the Cuda/Hpu
|
||||
/// backend is active (not yet supported).
|
||||
pub fn bitonic_shuffle<T, S>(
|
||||
data: Vec<T>,
|
||||
key_size: BitonicShuffleKeySize,
|
||||
seeder: &mut S,
|
||||
) -> Result<Vec<T>, crate::Error>
|
||||
where
|
||||
T: FheIntegerType,
|
||||
S: Seeder,
|
||||
{
|
||||
global_state::with_internal_keys(|key| match key {
|
||||
InternalServerKey::Cpu(cpu_key) => {
|
||||
let inner = data.into_iter().map(|v| v.into_cpu()).collect();
|
||||
let result =
|
||||
cpu_key
|
||||
.pbs_key()
|
||||
.bitonic_shuffle(&cpu_key.oprf_key(), inner, key_size, seeder)?;
|
||||
Ok(result
|
||||
.into_iter()
|
||||
.map(|ct| T::from_cpu(ct, cpu_key.tag.clone(), ReRandomizationMetadata::default()))
|
||||
.collect())
|
||||
}
|
||||
#[cfg(feature = "gpu")]
|
||||
InternalServerKey::Cuda(_) => Err(crate::Error::new(
|
||||
"bitonic_shuffle is not supported on Cuda".to_string(),
|
||||
)),
|
||||
#[cfg(feature = "hpu")]
|
||||
InternalServerKey::Hpu(_) => Err(crate::Error::new(
|
||||
"bitonic_shuffle is not supported on Hpu".to_string(),
|
||||
)),
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{bitonic_shuffle, BitonicShuffleKeySize};
|
||||
use crate::core_crypto::commons::generators::DeterministicSeeder;
|
||||
use crate::core_crypto::prelude::new_seeder;
|
||||
use crate::high_level_api::prelude::*;
|
||||
use crate::high_level_api::tests::setup_default_cpu;
|
||||
use crate::{FheInt8, FheUint8};
|
||||
use rand::Rng;
|
||||
use tfhe_csprng::generators::DefaultRandomGenerator;
|
||||
|
||||
#[test]
|
||||
fn test_bitonic_shuffle_fheuint() {
|
||||
let cks = setup_default_cpu();
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut clear_values: Vec<u8> = (0..15).map(|_| rng.gen()).collect();
|
||||
|
||||
let encrypted: Vec<FheUint8> = clear_values
|
||||
.iter()
|
||||
.map(|&v| FheUint8::try_encrypt(v, &cks).unwrap())
|
||||
.collect();
|
||||
|
||||
let seed = new_seeder().seed();
|
||||
println!("seed: {seed:?}");
|
||||
let mut seeder = DeterministicSeeder::<DefaultRandomGenerator>::new(seed);
|
||||
let shuffled = bitonic_shuffle(
|
||||
encrypted,
|
||||
BitonicShuffleKeySize::num_blocks(16),
|
||||
&mut seeder,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut decrypted: Vec<u8> = shuffled.iter().map(|ct| ct.decrypt(&cks)).collect();
|
||||
|
||||
clear_values.sort_unstable();
|
||||
decrypted.sort_unstable();
|
||||
assert_eq!(decrypted, clear_values);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bitonic_shuffle_fheint() {
|
||||
let cks = setup_default_cpu();
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut clear_values: Vec<i8> = (0..15).map(|_| rng.gen()).collect();
|
||||
|
||||
let encrypted: Vec<FheInt8> = clear_values
|
||||
.iter()
|
||||
.map(|&v| FheInt8::try_encrypt(v, &cks).unwrap())
|
||||
.collect();
|
||||
|
||||
let seed = new_seeder().seed();
|
||||
println!("seed: {seed:?}");
|
||||
let mut seeder = DeterministicSeeder::<DefaultRandomGenerator>::new(seed);
|
||||
let shuffled = bitonic_shuffle(
|
||||
encrypted,
|
||||
BitonicShuffleKeySize::num_blocks(16),
|
||||
&mut seeder,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut decrypted: Vec<i8> = shuffled.iter().map(|ct| ct.decrypt(&cks)).collect();
|
||||
|
||||
clear_values.sort_unstable();
|
||||
decrypted.sort_unstable();
|
||||
assert_eq!(decrypted, clear_values);
|
||||
}
|
||||
}
|
||||
@@ -260,7 +260,7 @@ impl SignedRadixCiphertext {
|
||||
}
|
||||
#[cfg(feature = "hpu")]
|
||||
(_, Device::Hpu) => {
|
||||
panic!("Hpu device do not support signed integer yet")
|
||||
panic!("Hpu device do not support signed integer yet",)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,8 +47,9 @@ macro_rules! export_concrete_array_types {
|
||||
};
|
||||
}
|
||||
|
||||
pub use crate::core_crypto::commons::math::random::{Seed, XofSeed};
|
||||
pub use crate::core_crypto::commons::math::random::{Seed, Seeder, XofSeed};
|
||||
pub use crate::high_level_api::integers::oprf::RangeForRandom;
|
||||
pub use crate::high_level_api::integers::shuffle::bitonic_shuffle;
|
||||
pub use crate::integer::server_key::MatchValues;
|
||||
pub use crate::shortint::OprfSeed;
|
||||
use crate::{error, Error, Versionize};
|
||||
@@ -70,8 +71,8 @@ pub use integers::{
|
||||
pub use keys::CudaServerKey;
|
||||
pub use keys::{
|
||||
generate_keys, ClientKey, CompactPublicKey, CompressedCompactPublicKey, CompressedPublicKey,
|
||||
CompressedReRandomizationKey, CompressedReRandomizationKeySwitchingKey, CompressedServerKey,
|
||||
KeySwitchingKey, PublicKey, ReRandomizationKey, ReRandomizationKeySwitchingKey, ServerKey,
|
||||
CompressedReRandomizationKeySwitchingKey, CompressedServerKey, KeySwitchingKey, PublicKey,
|
||||
ReRandomizationKeySwitchingKey, ServerKey,
|
||||
};
|
||||
use strum::FromRepr;
|
||||
|
||||
|
||||
@@ -347,7 +347,7 @@ mod zk {
|
||||
|
||||
// Intentionally low so that we test when multiple lists and proofs are needed
|
||||
let crs = CompactPkeCrs::from_config(config, 32).unwrap();
|
||||
let metadata = b"rerand";
|
||||
let metadata = [b'r', b'e', b'r', b'a', b'n', b'd'];
|
||||
|
||||
// Case where we want to re-randomize a CompactCiphertextList containing
|
||||
// FheUint64, FheInt8, and FheBool
|
||||
@@ -359,7 +359,7 @@ mod zk {
|
||||
.push(clear_a)
|
||||
.push(clear_b)
|
||||
.push(false)
|
||||
.build_with_proof_packed(&crs, metadata, ZkComputeLoad::Proof)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
// Simulate a 256 bits nonce
|
||||
@@ -378,7 +378,12 @@ mod zk {
|
||||
|
||||
// Verify, re_randomize and expand
|
||||
let expander = compact_list
|
||||
.verify_re_randomize_and_expand(&crs, &cpk, metadata, seed_gen.next_seed().unwrap())
|
||||
.verify_re_randomize_and_expand(
|
||||
&crs,
|
||||
&cpk,
|
||||
&metadata,
|
||||
seed_gen.next_seed().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let a: FheUint64 = expander.get(0).unwrap().unwrap();
|
||||
@@ -402,7 +407,7 @@ mod zk {
|
||||
.push(clear_a)
|
||||
.push(clear_b)
|
||||
.push(false)
|
||||
.build_with_proof_packed(&crs, metadata, ZkComputeLoad::Proof)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
let nonce: [u8; 256 / 8] = core::array::from_fn(|_| rand::random());
|
||||
|
||||
@@ -47,7 +47,7 @@ fn test_tag_propagation_zk_pok() {
|
||||
.build();
|
||||
let crs = crate::zk::CompactPkeCrs::from_config(config, (2 * 32) + (2 * 64) + 2).unwrap();
|
||||
|
||||
let metadata = b"hlapi";
|
||||
let metadata = [b'h', b'l', b'a', b'p', b'i'];
|
||||
|
||||
let mut cks = ClientKey::generate(config);
|
||||
let tag_value = random();
|
||||
@@ -70,13 +70,15 @@ fn test_tag_propagation_zk_pok() {
|
||||
.push(i64::MIN)
|
||||
.push(false)
|
||||
.push(true)
|
||||
.build_with_proof_packed(&crs, metadata, crate::zk::ZkComputeLoad::Proof)
|
||||
.build_with_proof_packed(&crs, &metadata, crate::zk::ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
let list_packed: ProvenCompactCiphertextList = serialize_then_deserialize(&list_packed);
|
||||
assert_eq!(list_packed.tag(), cks.tag());
|
||||
|
||||
let expander = list_packed.verify_and_expand(&crs, &cpk, metadata).unwrap();
|
||||
let expander = list_packed
|
||||
.verify_and_expand(&crs, &cpk, &metadata)
|
||||
.unwrap();
|
||||
|
||||
{
|
||||
let au32: FheUint32 = expander.get(0).unwrap().unwrap();
|
||||
@@ -155,7 +157,7 @@ fn test_tag_propagation_zk_pok_gpu() {
|
||||
.build();
|
||||
let crs = crate::zk::CompactPkeCrs::from_config(config, (2 * 32) + (2 * 64) + 2).unwrap();
|
||||
|
||||
let metadata = b"hlapi";
|
||||
let metadata = [b'h', b'l', b'a', b'p', b'i'];
|
||||
|
||||
let mut cks = ClientKey::generate(config);
|
||||
let tag_value = random();
|
||||
@@ -180,10 +182,12 @@ fn test_tag_propagation_zk_pok_gpu() {
|
||||
.push(i64::MIN)
|
||||
.push(false)
|
||||
.push(true)
|
||||
.build_with_proof_packed(&crs, metadata, crate::zk::ZkComputeLoad::Proof)
|
||||
.build_with_proof_packed(&crs, &metadata, crate::zk::ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
let expander = list_packed.verify_and_expand(&crs, &cpk, metadata).unwrap();
|
||||
let expander = list_packed
|
||||
.verify_and_expand(&crs, &cpk, &metadata)
|
||||
.unwrap();
|
||||
|
||||
{
|
||||
let au32: FheUint32 = expander.get(0).unwrap().unwrap();
|
||||
|
||||
@@ -1403,7 +1403,7 @@ mod zk_pok_tests {
|
||||
let ksk_params = PARAM_KEYSWITCH_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let fhe_params = PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
let metadata = b"integer";
|
||||
let metadata = [b'i', b'n', b't', b'e', b'g', b'e', b'r'];
|
||||
|
||||
let num_blocks = 4usize;
|
||||
let modulus = pke_params
|
||||
@@ -1433,11 +1433,11 @@ mod zk_pok_tests {
|
||||
|
||||
let proven_ct = if is_packed {
|
||||
builder
|
||||
.build_with_proof_packed(&crs, metadata, ZkComputeLoad::Proof)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap()
|
||||
} else {
|
||||
builder
|
||||
.build_with_proof(&crs, metadata, ZkComputeLoad::Proof)
|
||||
.build_with_proof(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
@@ -1452,7 +1452,7 @@ mod zk_pok_tests {
|
||||
.verify_and_expand(
|
||||
&crs,
|
||||
&pk,
|
||||
metadata,
|
||||
&metadata,
|
||||
IntegerCompactCiphertextListExpansionMode::CastAndUnpackIfNecessary(ksk.as_view()),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -1495,7 +1495,7 @@ mod zk_pok_tests {
|
||||
let ksk_params = PARAM_KEYSWITCH_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let fhe_params = PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
let metadata = b"integer";
|
||||
let metadata = [b'i', b'n', b't', b'e', b'g', b'e', b'r'];
|
||||
|
||||
let crs = CompactPkeCrs::from_shortint_params(pke_params, LweCiphertextCount(512)).unwrap();
|
||||
let cks = ClientKey::new(fhe_params);
|
||||
@@ -1514,13 +1514,13 @@ mod zk_pok_tests {
|
||||
let proven_ct = CompactCiphertextList::builder(&pk)
|
||||
.push_with_num_blocks(1u8, 0)
|
||||
.push_with_num_blocks(-1i8, 0)
|
||||
.build_with_proof_packed(&crs, metadata, ZkComputeLoad::Proof)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
assert!(proven_ct.is_empty());
|
||||
assert_eq!(proven_ct.len(), 0);
|
||||
assert_eq!(
|
||||
proven_ct.verify(&crs, &pk, metadata),
|
||||
proven_ct.verify(&crs, &pk, &metadata),
|
||||
ZkVerificationOutcome::Valid
|
||||
);
|
||||
assert!(proven_ct.is_conformant(&conformance_params));
|
||||
@@ -1528,7 +1528,7 @@ mod zk_pok_tests {
|
||||
proven_ct.verify_and_expand(
|
||||
&crs,
|
||||
&pk,
|
||||
metadata,
|
||||
&metadata,
|
||||
IntegerCompactCiphertextListExpansionMode::CastAndUnpackIfNecessary(ksk.as_view()),
|
||||
),
|
||||
Ok(vec) if vec.is_empty()
|
||||
@@ -1538,13 +1538,13 @@ mod zk_pok_tests {
|
||||
// Test by pushing with nothing
|
||||
{
|
||||
let proven_ct = CompactCiphertextList::builder(&pk)
|
||||
.build_with_proof_packed(&crs, metadata, ZkComputeLoad::Proof)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
assert!(proven_ct.is_empty());
|
||||
assert_eq!(proven_ct.len(), 0);
|
||||
assert_eq!(
|
||||
proven_ct.verify(&crs, &pk, metadata),
|
||||
proven_ct.verify(&crs, &pk, &metadata),
|
||||
ZkVerificationOutcome::Valid
|
||||
);
|
||||
assert!(proven_ct.is_conformant(&conformance_params));
|
||||
@@ -1552,7 +1552,7 @@ mod zk_pok_tests {
|
||||
proven_ct.verify_and_expand(
|
||||
&crs,
|
||||
&pk,
|
||||
metadata,
|
||||
&metadata,
|
||||
IntegerCompactCiphertextListExpansionMode::CastAndUnpackIfNecessary(ksk.as_view()),
|
||||
),
|
||||
Ok(vec) if vec.is_empty()
|
||||
@@ -1564,7 +1564,7 @@ mod zk_pok_tests {
|
||||
let mut proven_ct = CompactCiphertextList::builder(&pk)
|
||||
.push(1u8)
|
||||
.push(-1i8)
|
||||
.build_with_proof_packed(&crs, metadata, ZkComputeLoad::Proof)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
proven_ct.ct_list.proved_lists = Vec::new();
|
||||
@@ -1577,7 +1577,7 @@ mod zk_pok_tests {
|
||||
let mut proven_ct = CompactCiphertextList::builder(&pk)
|
||||
.push(1u8)
|
||||
.push(-1i8)
|
||||
.build_with_proof_packed(&crs, metadata, ZkComputeLoad::Proof)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
proven_ct.info = Vec::new();
|
||||
@@ -1647,7 +1647,7 @@ mod zk_pok_tests {
|
||||
let ksk_params = PARAM_KEYSWITCH_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let fhe_params = PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
let metadata = b"integer";
|
||||
let metadata = [b'i', b'n', b't', b'e', b'g', b'e', b'r'];
|
||||
|
||||
let crs = CompactPkeCrs::from_shortint_params(pke_params, LweCiphertextCount(2)).unwrap();
|
||||
let cks = ClientKey::new(fhe_params);
|
||||
@@ -1664,7 +1664,7 @@ mod zk_pok_tests {
|
||||
let mut proven_ct = CompactCiphertextList::builder(&pk)
|
||||
.push_with_num_blocks(1u8, 4)
|
||||
.push_with_num_blocks(-1i8, 4)
|
||||
.build_with_proof_packed(&crs, metadata, ZkComputeLoad::Proof)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(proven_ct.len(), 2);
|
||||
@@ -1684,14 +1684,14 @@ mod zk_pok_tests {
|
||||
assert!(!proven_ct.is_conformant(&conformance_params));
|
||||
assert!(proven_ct.is_empty());
|
||||
assert_eq!(
|
||||
proven_ct.verify(&crs, &pk, metadata),
|
||||
proven_ct.verify(&crs, &pk, &metadata),
|
||||
ZkVerificationOutcome::Valid
|
||||
);
|
||||
assert!(matches!(
|
||||
proven_ct.verify_and_expand(
|
||||
&crs,
|
||||
&pk,
|
||||
metadata,
|
||||
&metadata,
|
||||
IntegerCompactCiphertextListExpansionMode::CastAndUnpackIfNecessary(ksk.
|
||||
as_view()),
|
||||
),
|
||||
@@ -1706,14 +1706,14 @@ mod zk_pok_tests {
|
||||
assert!(!proven_ct.is_empty());
|
||||
assert!(proven_ct.is_packed());
|
||||
assert_eq!(
|
||||
proven_ct.verify(&crs, &pk, metadata),
|
||||
proven_ct.verify(&crs, &pk, &metadata),
|
||||
ZkVerificationOutcome::Valid
|
||||
);
|
||||
assert!(proven_ct
|
||||
.verify_and_expand(
|
||||
&crs,
|
||||
&pk,
|
||||
metadata,
|
||||
&metadata,
|
||||
IntegerCompactCiphertextListExpansionMode::CastAndUnpackIfNecessary(ksk.as_view())
|
||||
)
|
||||
.is_err());
|
||||
@@ -1729,14 +1729,14 @@ mod zk_pok_tests {
|
||||
assert!(!proven_ct.is_empty());
|
||||
assert!(proven_ct.is_packed());
|
||||
assert_eq!(
|
||||
proven_ct.verify(&crs, &pk, metadata),
|
||||
proven_ct.verify(&crs, &pk, &metadata),
|
||||
ZkVerificationOutcome::Valid
|
||||
);
|
||||
assert!(proven_ct
|
||||
.verify_and_expand(
|
||||
&crs,
|
||||
&pk,
|
||||
metadata,
|
||||
&metadata,
|
||||
IntegerCompactCiphertextListExpansionMode::CastAndUnpackIfNecessary(ksk.as_view())
|
||||
)
|
||||
.is_ok());
|
||||
@@ -1748,14 +1748,14 @@ mod zk_pok_tests {
|
||||
assert!(!proven_ct.is_empty());
|
||||
assert!(proven_ct.is_packed());
|
||||
assert_eq!(
|
||||
proven_ct.verify(&crs, &pk, metadata),
|
||||
proven_ct.verify(&crs, &pk, &metadata),
|
||||
ZkVerificationOutcome::Valid
|
||||
);
|
||||
assert!(proven_ct
|
||||
.verify_and_expand(
|
||||
&crs,
|
||||
&pk,
|
||||
metadata,
|
||||
&metadata,
|
||||
IntegerCompactCiphertextListExpansionMode::CastAndUnpackIfNecessary(ksk.as_view())
|
||||
)
|
||||
.is_err());
|
||||
@@ -1767,7 +1767,7 @@ mod zk_pok_tests {
|
||||
let ksk_params = PARAM_KEYSWITCH_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let fhe_params = PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
let metadata = b"integer";
|
||||
let metadata = [b'i', b'n', b't', b'e', b'g', b'e', b'r'];
|
||||
|
||||
let crs = CompactPkeCrs::from_shortint_params(pke_params, LweCiphertextCount(2)).unwrap();
|
||||
let cks = ClientKey::new(fhe_params);
|
||||
@@ -1784,7 +1784,7 @@ mod zk_pok_tests {
|
||||
let mut proven_ct = CompactCiphertextList::builder(&pk)
|
||||
.push_with_num_blocks(1u8, 4)
|
||||
.push_with_num_blocks(-1i8, 4)
|
||||
.build_with_proof_packed(&crs, metadata, ZkComputeLoad::Proof)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
assert!(proven_ct.is_conformant(&conformance_params));
|
||||
@@ -1803,7 +1803,7 @@ mod zk_pok_tests {
|
||||
let expander = proven_ct.verify_and_expand(
|
||||
&crs,
|
||||
&pk,
|
||||
metadata,
|
||||
&metadata,
|
||||
IntegerCompactCiphertextListExpansionMode::CastAndUnpackIfNecessary(ksk.as_view()),
|
||||
);
|
||||
assert!(expander.is_err());
|
||||
@@ -1817,7 +1817,7 @@ mod zk_pok_tests {
|
||||
TEST_PARAM_KEYSWITCH_PKE_TO_BIG_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128_ZKV1;
|
||||
let fhe_params = PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
let metadata = b"integer";
|
||||
let metadata = [b'i', b'n', b't', b'e', b'g', b'e', b'r'];
|
||||
|
||||
let num_blocks = 4usize;
|
||||
let modulus = pke_params
|
||||
@@ -1839,14 +1839,14 @@ mod zk_pok_tests {
|
||||
|
||||
let proven_ct = CompactCiphertextList::builder(&pk)
|
||||
.extend_with_num_blocks(msgs.iter().copied(), num_blocks)
|
||||
.build_with_proof_packed(&crs, metadata, ZkComputeLoad::Proof)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
let expander = proven_ct
|
||||
.verify_and_expand(
|
||||
&crs,
|
||||
&pk,
|
||||
metadata,
|
||||
&metadata,
|
||||
IntegerCompactCiphertextListExpansionMode::CastAndUnpackIfNecessary(ksk.as_view()),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -1879,7 +1879,7 @@ mod zk_pok_tests {
|
||||
let ksk_params = PARAM_KEYSWITCH_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let fhe_params = PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
let metadata = b"integer";
|
||||
let metadata = [b'i', b'n', b't', b'e', b'g', b'e', b'r'];
|
||||
|
||||
let crs_blocks_for_64_bits =
|
||||
64 / ((pke_params.message_modulus.0 * pke_params.carry_modulus.0).ilog2() as usize);
|
||||
@@ -1900,14 +1900,14 @@ mod zk_pok_tests {
|
||||
|
||||
let proven_ct = CompactCiphertextList::builder(&pk)
|
||||
.extend_with_num_blocks(msgs.iter().copied(), encryption_num_blocks)
|
||||
.build_with_proof_packed(&crs, metadata, ZkComputeLoad::Proof)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
let expander = proven_ct
|
||||
.verify_and_expand(
|
||||
&crs,
|
||||
&pk,
|
||||
metadata,
|
||||
&metadata,
|
||||
IntegerCompactCiphertextListExpansionMode::CastAndUnpackIfNecessary(ksk.as_view()),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -1942,7 +1942,7 @@ mod zk_pok_tests {
|
||||
let ksk_params = PARAM_KEYSWITCH_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
let fhe_params = PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
let metadata = b"integer";
|
||||
let metadata = [b'i', b'n', b't', b'e', b'g', b'e', b'r'];
|
||||
|
||||
let crs_blocks_for_64_bits =
|
||||
64 / ((pke_params.message_modulus.0 * pke_params.carry_modulus.0).ilog2() as usize);
|
||||
@@ -1963,7 +1963,7 @@ mod zk_pok_tests {
|
||||
|
||||
let proven_ct = CompactCiphertextList::builder(&pk)
|
||||
.extend_with_num_blocks(msgs.iter().copied(), encryption_num_blocks)
|
||||
.build_with_proof_packed(&crs, metadata, ZkComputeLoad::Proof)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
let infos_block_count = {
|
||||
@@ -2023,7 +2023,7 @@ mod zk_pok_tests {
|
||||
.verify_and_expand(
|
||||
&crs,
|
||||
&pk,
|
||||
metadata,
|
||||
&metadata,
|
||||
IntegerCompactCiphertextListExpansionMode::CastAndUnpackIfNecessary(ksk.as_view()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@@ -245,7 +245,7 @@ mod zk {
|
||||
let fhe_params = TEST_PARAM_MESSAGE_2_CARRY_2_KS_PBS_TUNIFORM_2M128;
|
||||
|
||||
let num_blocks = 4usize;
|
||||
let metadata = *b"test";
|
||||
let metadata = [b't', b'e', b's', b't'];
|
||||
let rerand_domain_separator = *b"TFHE_Rrd";
|
||||
let compact_public_encryption_domain_separator = *b"TFHE_Enc";
|
||||
|
||||
@@ -403,7 +403,7 @@ mod zk {
|
||||
|
||||
// Intentionally low so that we test when multiple lists and proofs are needed
|
||||
let crs = CompactPkeCrs::from_shortint_params(pke_params, LweCiphertextCount(8)).unwrap();
|
||||
let metadata = b"rerand";
|
||||
let metadata = [b'r', b'e', b'r', b'a', b'n', b'd'];
|
||||
|
||||
let clear_a = rand::random::<u64>();
|
||||
let clear_b = rand::random::<i8>();
|
||||
@@ -412,7 +412,7 @@ mod zk {
|
||||
.push(clear_a)
|
||||
.push(clear_b)
|
||||
.push(false)
|
||||
.build_with_proof_packed(&crs, metadata, ZkComputeLoad::Proof)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
// Clone the list so both CPU and GPU start from the same state
|
||||
|
||||
@@ -68,9 +68,8 @@ macro_rules! create_gpu_parameterized_stringified_test{
|
||||
}
|
||||
|
||||
use crate::integer::gpu::server_key::radix::tests_signed::GpuMultiDeviceFunctionExecutor;
|
||||
pub(crate) use create_gpu_parameterized_stringified_test;
|
||||
pub(crate) use create_gpu_parameterized_test;
|
||||
use tfhe_csprng::seeders::Seed;
|
||||
pub(crate) use {create_gpu_parameterized_stringified_test, create_gpu_parameterized_test};
|
||||
|
||||
pub(crate) struct GpuContext {
|
||||
pub(crate) streams: CudaStreams,
|
||||
|
||||
@@ -271,7 +271,7 @@ mod tests {
|
||||
];
|
||||
|
||||
for (ksk_params, pke_params, fhe_params) in params {
|
||||
let metadata = b"integer";
|
||||
let metadata = [b'i', b'n', b't', b'e', b'g', b'e', b'r'];
|
||||
|
||||
let num_blocks = 4usize;
|
||||
let modulus = pke_params
|
||||
@@ -304,7 +304,7 @@ mod tests {
|
||||
|
||||
let proven_ct = CompactCiphertextList::builder(&pk)
|
||||
.extend_with_num_blocks(msgs.iter().copied(), num_blocks)
|
||||
.build_with_proof_packed(&crs, metadata, ZkComputeLoad::Proof)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
let gpu_proven_ct =
|
||||
CudaProvenCompactCiphertextList::from_proven_compact_ciphertext_list(
|
||||
@@ -312,7 +312,7 @@ mod tests {
|
||||
);
|
||||
|
||||
let gpu_expander = gpu_proven_ct
|
||||
.verify_and_expand(&crs, &pk, metadata, &d_ksk, &streams)
|
||||
.verify_and_expand(&crs, &pk, &metadata, &d_ksk, &streams)
|
||||
.unwrap();
|
||||
|
||||
for (idx, msg) in msgs.iter().copied().enumerate() {
|
||||
@@ -362,7 +362,7 @@ mod tests {
|
||||
];
|
||||
|
||||
for (ksk_params, pke_params, fhe_params) in params {
|
||||
let metadata = b"integer";
|
||||
let metadata = [b'i', b'n', b't', b'e', b'g', b'e', b'r'];
|
||||
|
||||
let crs_blocks_for_64_bits =
|
||||
64 / ((pke_params.message_modulus.0 * pke_params.carry_modulus.0).ilog2() as usize);
|
||||
@@ -392,7 +392,7 @@ mod tests {
|
||||
|
||||
let proven_ct = CompactCiphertextList::builder(&pk)
|
||||
.extend_with_num_blocks(msgs.iter().copied(), encryption_num_blocks)
|
||||
.build_with_proof_packed(&crs, metadata, ZkComputeLoad::Proof)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
let gpu_proven_ct =
|
||||
CudaProvenCompactCiphertextList::from_proven_compact_ciphertext_list(
|
||||
@@ -400,7 +400,7 @@ mod tests {
|
||||
);
|
||||
|
||||
let gpu_expander = gpu_proven_ct
|
||||
.verify_and_expand(&crs, &pk, metadata, &d_ksk, &streams)
|
||||
.verify_and_expand(&crs, &pk, &metadata, &d_ksk, &streams)
|
||||
.unwrap();
|
||||
|
||||
for (idx, msg) in msgs.iter().copied().enumerate() {
|
||||
@@ -452,7 +452,7 @@ mod tests {
|
||||
];
|
||||
|
||||
for (ksk_params, pke_params, fhe_params) in params {
|
||||
let metadata = b"integer";
|
||||
let metadata = [b'i', b'n', b't', b'e', b'g', b'e', b'r'];
|
||||
|
||||
let crs_blocks_for_64_bits =
|
||||
64 / ((pke_params.message_modulus.0 * pke_params.carry_modulus.0).ilog2() as usize);
|
||||
@@ -482,7 +482,7 @@ mod tests {
|
||||
|
||||
let proven_ct = CompactCiphertextList::builder(&pk)
|
||||
.extend_with_num_blocks(msgs.iter().copied(), encryption_num_blocks)
|
||||
.build_with_proof_packed(&crs, metadata, ZkComputeLoad::Proof)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Proof)
|
||||
.unwrap();
|
||||
|
||||
let infos_block_count = {
|
||||
@@ -543,7 +543,7 @@ mod tests {
|
||||
);
|
||||
|
||||
let gpu_expander = gpu_proven_ct
|
||||
.verify_and_expand(&crs, &pk, metadata, &d_ksk, &streams)
|
||||
.verify_and_expand(&crs, &pk, &metadata, &d_ksk, &streams)
|
||||
.unwrap();
|
||||
|
||||
for idx in boolean_block_idx.iter().copied() {
|
||||
@@ -595,7 +595,7 @@ mod tests {
|
||||
|
||||
let crs = CompactPkeCrs::from_config(config, 64).unwrap();
|
||||
let public_key = crate::CompactPublicKey::try_new(&client_key).unwrap();
|
||||
let metadata = b"TFHE-rs";
|
||||
let metadata = [b'T', b'F', b'H', b'E', b'-', b'r', b's'];
|
||||
|
||||
// Create a proven compact list with 6 items (matching user's scenario)
|
||||
let m0 = true;
|
||||
@@ -611,7 +611,7 @@ mod tests {
|
||||
.push(m3)
|
||||
.push(m4)
|
||||
.push(m5)
|
||||
.build_with_proof_packed(&crs, metadata, ZkComputeLoad::Verify)
|
||||
.build_with_proof_packed(&crs, &metadata, ZkComputeLoad::Verify)
|
||||
.unwrap();
|
||||
|
||||
// Set GPU server key
|
||||
@@ -619,7 +619,7 @@ mod tests {
|
||||
|
||||
// Verify and expand on GPU
|
||||
let expander = proven_compact_list
|
||||
.verify_and_expand(&crs, &public_key, metadata)
|
||||
.verify_and_expand(&crs, &public_key, &metadata)
|
||||
.unwrap();
|
||||
|
||||
// The expander should have length 6 (number of data items), not 66 (total blocks)
|
||||
|
||||
@@ -20,7 +20,9 @@ pub use crate::shortint::CheckError;
|
||||
use crate::shortint::{CarryModulus, MessageModulus};
|
||||
pub use radix::scalar_mul::ScalarMultiplier;
|
||||
pub use radix::scalar_sub::TwosComplementNegation;
|
||||
pub use radix_parallel::{MatchValues, MiniUnsignedInteger, Reciprocable};
|
||||
pub use radix_parallel::{
|
||||
BitonicShuffleKeySize, CollisionProbability, MatchValues, MiniUnsignedInteger, Reciprocable,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tfhe_versionable::Versionize;
|
||||
|
||||
|
||||
@@ -247,14 +247,15 @@ impl ServerKey {
|
||||
/// let res: u64 = cks.decrypt(&ct1);
|
||||
/// assert_eq!(7, res);
|
||||
/// ```
|
||||
pub fn extend_radix_with_trivial_zero_blocks_msb_assign(
|
||||
&self,
|
||||
ct: &mut RadixCiphertext,
|
||||
num_blocks: usize,
|
||||
) {
|
||||
pub fn extend_radix_with_trivial_zero_blocks_msb_assign<T>(&self, ct: &mut T, num_blocks: usize)
|
||||
where
|
||||
T: IntegerRadixCiphertext,
|
||||
{
|
||||
// Swap out blocks via a no-alloc empty sentinel (blocks_mut is a slice, can't resize)
|
||||
let mut blocks = std::mem::replace(ct, T::from_blocks(vec![])).into_blocks();
|
||||
let block_trivial_zero = self.key.create_trivial(0);
|
||||
ct.blocks
|
||||
.resize(ct.blocks.len() + num_blocks, block_trivial_zero);
|
||||
blocks.resize(blocks.len() + num_blocks, block_trivial_zero);
|
||||
*ct = T::from_blocks(blocks);
|
||||
}
|
||||
|
||||
/// Append trivial zero MSB blocks to an existing [`RadixCiphertext`] and returns the result as
|
||||
|
||||
291
tfhe/src/integer/server_key/radix_parallel/bitonic_shuffle.rs
Normal file
291
tfhe/src/integer/server_key/radix_parallel/bitonic_shuffle.rs
Normal file
@@ -0,0 +1,291 @@
|
||||
//! Bitonic sorting network generator.
|
||||
//!
|
||||
//! A bitonic sorting network for n=2^k elements has k*(k+1)/2 stages,
|
||||
//! each with n/2 comparators. It sorts any input sequence.
|
||||
use crate::core_crypto::prelude::Container;
|
||||
use crate::integer::oprf::GenericOprfServerKey;
|
||||
use crate::integer::{IntegerRadixCiphertext, RadixCiphertext, ServerKey};
|
||||
use crate::shortint::MessageModulus;
|
||||
use rayon::prelude::*;
|
||||
use tfhe_csprng::seeders::Seeder;
|
||||
use tfhe_fft::c64;
|
||||
|
||||
/// Generates a bitonic sorting network for n elements (n must be a power of 2).
|
||||
///
|
||||
/// Returns a list of stages, where each stage contains disjoint (i, j, ascending) triples.
|
||||
/// Each triple represents a compare-and-swap: if ascending, put the smaller element at i;
|
||||
/// if descending, put the larger element at i.
|
||||
pub(crate) fn bitonic_network(n: usize) -> Vec<Vec<(usize, usize, bool)>> {
|
||||
assert!(
|
||||
n.is_power_of_two() && n >= 2,
|
||||
"bitonic_network requires n to be a power of 2 and >= 2, got n={n}"
|
||||
);
|
||||
let log_n = n.trailing_zeros() as usize;
|
||||
let mut stages = Vec::new();
|
||||
|
||||
for phase in 0..log_n {
|
||||
for step in (0..=phase).rev() {
|
||||
let mut comparators = Vec::new();
|
||||
for i in 0..n {
|
||||
let j = i ^ (1 << step);
|
||||
if j > i {
|
||||
let ascending = (i >> (phase + 1)) & 1 == 0;
|
||||
comparators.push((i, j, ascending));
|
||||
}
|
||||
}
|
||||
stages.push(comparators);
|
||||
}
|
||||
}
|
||||
|
||||
stages
|
||||
}
|
||||
|
||||
/// Returns the next power of 2 >= n (or n itself if already a power of 2).
|
||||
fn padded_size(n: usize) -> usize {
|
||||
n.next_power_of_two()
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
pub struct CollisionProbability(f64);
|
||||
|
||||
impl CollisionProbability {
|
||||
pub fn try_new(proba: f64) -> Option<Self> {
|
||||
if 0.0 < proba && proba < 1.0 {
|
||||
Some(Self(proba))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(proba: f64) -> Self {
|
||||
Self::try_new(proba).expect("Invalid probability, it must be in ]0, 1.0[")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
pub enum BitonicShuffleKeySize {
|
||||
CollisionProbability(CollisionProbability),
|
||||
NumBlocks(u32),
|
||||
}
|
||||
|
||||
impl BitonicShuffleKeySize {
|
||||
pub fn try_collision_probability(proba: f64) -> Option<Self> {
|
||||
CollisionProbability::try_new(proba).map(Self::CollisionProbability)
|
||||
}
|
||||
|
||||
pub fn collision_probability(proba: f64) -> Self {
|
||||
Self::CollisionProbability(CollisionProbability::new(proba))
|
||||
}
|
||||
|
||||
pub fn num_blocks(num_blocks: u32) -> Self {
|
||||
Self::NumBlocks(num_blocks)
|
||||
}
|
||||
|
||||
fn num_blocks_of_keys(&self, num_elements: usize, msg_mod: MessageModulus) -> u32 {
|
||||
match self {
|
||||
Self::CollisionProbability(CollisionProbability(proba)) => {
|
||||
let n_squared = (num_elements * num_elements) as f64;
|
||||
let bits = (n_squared / (2.0 * proba)).log2().ceil() as u32;
|
||||
bits.div_ceil(msg_mod.0.ilog2())
|
||||
}
|
||||
Self::NumBlocks(n) => *n,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ServerKey {
|
||||
/// Shuffles `data` into a uniformly random permutation using a bitonic sorting network
|
||||
/// with random sort keys.
|
||||
///
|
||||
/// `key_size` controls the bit-width of the random sort keys used internally, either
|
||||
/// by specifying a target collision probability or by passing a raw block count.
|
||||
/// Larger keys reduce collision probability — and thus improve shuffle uniformity —
|
||||
/// at the cost of more computation per comparison/swap.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the resolved key block count is 0.
|
||||
pub fn bitonic_shuffle<T, S, C>(
|
||||
&self,
|
||||
oprf_key: &GenericOprfServerKey<C>,
|
||||
data: Vec<T>,
|
||||
key_size: BitonicShuffleKeySize,
|
||||
seeder: &mut S,
|
||||
) -> Result<Vec<T>, crate::Error>
|
||||
where
|
||||
T: IntegerRadixCiphertext,
|
||||
S: Seeder,
|
||||
C: Container<Element = c64> + Sync,
|
||||
{
|
||||
let key_num_blocks = key_size.num_blocks_of_keys(data.len(), self.message_modulus()) as u64;
|
||||
|
||||
if key_num_blocks == 0 {
|
||||
return Err(crate::Error::new(
|
||||
"key_num_blocks must be at least 1".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
if data.len() <= 1 {
|
||||
return Ok(data);
|
||||
}
|
||||
|
||||
let keys: Vec<_> = (0..data.len())
|
||||
.map(|_| {
|
||||
oprf_key.par_generate_oblivious_pseudo_random_unsigned_integer(
|
||||
seeder.seed(),
|
||||
key_num_blocks,
|
||||
self,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
self.bitonic_shuffle_with_keys(data, keys)
|
||||
}
|
||||
|
||||
/// Shuffles `data` using a bitonic sorting network keyed by `keys`.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if `data` and `keys` have different lengths, or if
|
||||
/// elements within `data` (or within `keys`) have inconsistent block counts.
|
||||
pub fn bitonic_shuffle_with_keys<T>(
|
||||
&self,
|
||||
mut data: Vec<T>,
|
||||
mut keys: Vec<RadixCiphertext>,
|
||||
) -> Result<Vec<T>, crate::Error>
|
||||
where
|
||||
T: IntegerRadixCiphertext,
|
||||
{
|
||||
if data.len() != keys.len() {
|
||||
return Err(crate::Error::new(format!(
|
||||
"data and keys must have the same length, got {} and {}",
|
||||
data.len(),
|
||||
keys.len()
|
||||
)));
|
||||
}
|
||||
|
||||
if data.len() <= 1 {
|
||||
return Ok(data);
|
||||
}
|
||||
|
||||
let data_num_blocks = data[0].blocks().len();
|
||||
if data[1..]
|
||||
.iter()
|
||||
.any(|d| d.blocks().len() != data_num_blocks)
|
||||
{
|
||||
return Err(crate::Error::new(
|
||||
"all data elements must have the same number of blocks".to_string(),
|
||||
));
|
||||
}
|
||||
let key_num_blocks = keys[0].blocks.len();
|
||||
if keys[1..].iter().any(|k| k.blocks.len() != key_num_blocks) {
|
||||
return Err(crate::Error::new(
|
||||
"all keys must have the same number of blocks".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
rayon::join(
|
||||
|| {
|
||||
data.par_iter_mut()
|
||||
.for_each(|value| self.clean_inplace_for_default_op(value));
|
||||
},
|
||||
|| {
|
||||
keys.par_iter_mut()
|
||||
.for_each(|value| self.clean_inplace_for_default_op(value));
|
||||
},
|
||||
);
|
||||
|
||||
let mut data = self.unchecked_bitonic_shuffle_with_keys(data, keys);
|
||||
|
||||
data.par_iter_mut().for_each(|radix| {
|
||||
radix
|
||||
.blocks_mut()
|
||||
.par_iter_mut()
|
||||
.for_each(|block| self.key.message_extract_assign(block))
|
||||
});
|
||||
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
/// Performs a bitonic shuffle without cleaning inputs or outputs.
|
||||
///
|
||||
/// # Preconditions
|
||||
///
|
||||
/// * `data` and `keys` must have the same length and consistent block counts.
|
||||
/// * Data blocks must have no carries and noise budget for `unchecked_flip_parallelized`.
|
||||
/// * Key blocks must have no carries and noise budget for `unchecked_lt/gt`.
|
||||
///
|
||||
/// Output blocks have no carries but non-nominal noise level.
|
||||
pub fn unchecked_bitonic_shuffle_with_keys<T>(
|
||||
&self,
|
||||
mut data: Vec<T>,
|
||||
mut keys: Vec<RadixCiphertext>,
|
||||
) -> Vec<T>
|
||||
where
|
||||
T: IntegerRadixCiphertext,
|
||||
{
|
||||
assert_eq!(
|
||||
data.len(),
|
||||
keys.len(),
|
||||
"data.len()={} != keys.len()={}",
|
||||
data.len(),
|
||||
keys.len()
|
||||
);
|
||||
let n = data.len();
|
||||
if n <= 1 {
|
||||
return data;
|
||||
}
|
||||
|
||||
let padded_n = padded_size(n);
|
||||
let network = bitonic_network(padded_n);
|
||||
|
||||
let mut key_num_blocks = keys[0].blocks.len();
|
||||
let data_num_blocks = data[0].blocks().len();
|
||||
|
||||
let pad = padded_n - n;
|
||||
if pad > 0 {
|
||||
// We need to pad with some trivial (key=MAX, data=0)
|
||||
// However it could be that a key is already=MAX, so to protect us from that case
|
||||
// we add an extra block to the keys
|
||||
key_num_blocks += 1;
|
||||
for key in &mut keys {
|
||||
self.extend_radix_with_trivial_zero_blocks_msb_assign(key, 1);
|
||||
}
|
||||
|
||||
for _ in 0..pad {
|
||||
keys.push(self.create_trivial_max_radix(key_num_blocks));
|
||||
data.push(self.create_trivial_zero_radix(data_num_blocks));
|
||||
}
|
||||
}
|
||||
|
||||
let mut stage_results = Vec::with_capacity(padded_n / 2);
|
||||
for stage in network {
|
||||
stage
|
||||
.into_par_iter()
|
||||
.map(|(i, j, ascending)| {
|
||||
let cmp = if ascending {
|
||||
self.unchecked_gt_parallelized(&keys[i], &keys[j])
|
||||
} else {
|
||||
self.unchecked_lt_parallelized(&keys[i], &keys[j])
|
||||
};
|
||||
let ((new_ki, new_kj), (new_di, new_dj)) = rayon::join(
|
||||
|| self.unchecked_flip_parallelized(&cmp, &keys[i], &keys[j]),
|
||||
|| self.unchecked_flip_parallelized(&cmp, &data[i], &data[j]),
|
||||
);
|
||||
|
||||
(i, j, new_ki, new_kj, new_di, new_dj)
|
||||
})
|
||||
.collect_into_vec(&mut stage_results);
|
||||
|
||||
for (i, j, new_ki, new_kj, new_di, new_dj) in stage_results.drain(..) {
|
||||
keys[i] = new_ki;
|
||||
keys[j] = new_kj;
|
||||
data[i] = new_di;
|
||||
data[j] = new_dj;
|
||||
}
|
||||
}
|
||||
|
||||
data.truncate(n);
|
||||
data
|
||||
}
|
||||
}
|
||||
@@ -121,96 +121,17 @@ where
|
||||
"Inputs must have the same number of blocks"
|
||||
);
|
||||
|
||||
// To make use if many_lut, we require 1 bit, 1 more bit is required to pack
|
||||
// the condition. Thus 2 bits of carry are required.
|
||||
//
|
||||
// Otherwise we call if_then_else twice, which is less efficient.
|
||||
if self.carry_modulus().0 < (1 << 2) {
|
||||
return rayon::join(
|
||||
|| self.if_then_else_parallelized(condition, b, a),
|
||||
|| self.if_then_else_parallelized(condition, a, b),
|
||||
);
|
||||
}
|
||||
|
||||
let (a, b) = rayon::join(
|
||||
|| self.clean_for_default_op(a),
|
||||
|| self.clean_for_default_op(b),
|
||||
);
|
||||
let (mut a, mut b) = self.unchecked_flip_parallelized(condition, &*a, &*b);
|
||||
a.blocks_mut()
|
||||
.par_iter_mut()
|
||||
.chain(b.blocks_mut().par_iter_mut())
|
||||
.for_each(|block| self.key.message_extract_assign(block));
|
||||
|
||||
let zero_out_if_true_fn = |packed| {
|
||||
let condition = (packed / self.message_modulus().0) & 1;
|
||||
let value = packed % self.message_modulus().0;
|
||||
(1 - condition) * value
|
||||
};
|
||||
|
||||
let zero_out_if_false_fn = |packed| {
|
||||
let condition = (packed / self.message_modulus().0) & 1;
|
||||
let value = packed % self.message_modulus().0;
|
||||
condition * value
|
||||
};
|
||||
|
||||
let lut = self
|
||||
.key
|
||||
.generate_many_lookup_table(&[&zero_out_if_true_fn, &zero_out_if_false_fn]);
|
||||
|
||||
let scaled_condition = self
|
||||
.key
|
||||
.unchecked_scalar_mul(&condition.0, self.message_modulus().0 as u8);
|
||||
|
||||
let map_condition_lut_on_blocks =
|
||||
|blocks: &[Ciphertext]| -> (Vec<Ciphertext>, Vec<Ciphertext>) {
|
||||
let mut left = Vec::with_capacity(blocks.len());
|
||||
let mut right = Vec::with_capacity(blocks.len());
|
||||
blocks
|
||||
.par_iter()
|
||||
.map(|block| {
|
||||
let block = self.key.unchecked_add(block, &scaled_condition);
|
||||
let mut resulting_blocks = self.key.apply_many_lookup_table(&block, &lut);
|
||||
|
||||
let second_result = resulting_blocks.pop().unwrap();
|
||||
let first_result = resulting_blocks.pop().unwrap();
|
||||
|
||||
(first_result, second_result)
|
||||
})
|
||||
.unzip_into_vecs(&mut left, &mut right);
|
||||
(left, right)
|
||||
};
|
||||
|
||||
let (
|
||||
(mut a_blocks_if_cond, mut a_blocks_if_not_cond),
|
||||
(b_blocks_if_cond, b_blocks_if_not_cond),
|
||||
) = rayon::join(
|
||||
|| map_condition_lut_on_blocks(a.blocks()),
|
||||
|| map_condition_lut_on_blocks(b.blocks()),
|
||||
);
|
||||
|
||||
let clean_lut = self
|
||||
.key
|
||||
.generate_lookup_table(|x| x % self.message_modulus().0);
|
||||
|
||||
let inplace_add_then_clean_blocks =
|
||||
|lhs_blocks: &mut [Ciphertext], rhs_blocks: &[Ciphertext]| {
|
||||
lhs_blocks
|
||||
.par_iter_mut()
|
||||
.zip(rhs_blocks.par_iter())
|
||||
.for_each(|(lhs, rhs)| {
|
||||
self.key.unchecked_add_assign(lhs, rhs);
|
||||
self.key.apply_lookup_table_assign(lhs, &clean_lut);
|
||||
});
|
||||
};
|
||||
rayon::join(
|
||||
|| {
|
||||
inplace_add_then_clean_blocks(&mut a_blocks_if_cond, &b_blocks_if_not_cond);
|
||||
},
|
||||
|| {
|
||||
inplace_add_then_clean_blocks(&mut a_blocks_if_not_cond, &b_blocks_if_cond);
|
||||
},
|
||||
);
|
||||
|
||||
(
|
||||
T::from_blocks(a_blocks_if_cond),
|
||||
T::from_blocks(a_blocks_if_not_cond),
|
||||
)
|
||||
(a, b)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -987,6 +908,122 @@ impl ServerKey {
|
||||
});
|
||||
}
|
||||
|
||||
/// Performs `if condition { (b, a) } else { (a, b) }` in fhe
|
||||
///
|
||||
/// * Blocks of both `a` and `b` must have no carries and noise_level <= 2
|
||||
/// * Outputs will have no carries but noise_level == 2
|
||||
pub(crate) fn unchecked_flip_parallelized<T>(
|
||||
&self,
|
||||
condition: &BooleanBlock,
|
||||
a: &T,
|
||||
b: &T,
|
||||
) -> (T, T)
|
||||
where
|
||||
T: IntegerRadixCiphertext,
|
||||
{
|
||||
assert_eq!(
|
||||
a.blocks().len(),
|
||||
b.blocks().len(),
|
||||
"Inputs must have the same number of blocks"
|
||||
);
|
||||
|
||||
// To make use if many_lut, we require 1 bit, 1 more bit is required to pack
|
||||
// the condition. Thus 2 bits of carry are required.
|
||||
//
|
||||
// Otherwise we call if_then_else twice, which is less efficient.
|
||||
if self.carry_modulus().0 < (1 << 2) {
|
||||
let unchecked_if_then_else_parallelized_no_cleanup =
|
||||
|condition: &BooleanBlock, true_ct, false_ct| {
|
||||
let condition_block = &condition.0;
|
||||
let do_clean_message = false;
|
||||
self.unchecked_programmable_if_then_else_parallelized(
|
||||
condition_block,
|
||||
true_ct,
|
||||
false_ct,
|
||||
|x| x == 1,
|
||||
do_clean_message,
|
||||
)
|
||||
};
|
||||
return rayon::join(
|
||||
|| unchecked_if_then_else_parallelized_no_cleanup(condition, b, a),
|
||||
|| unchecked_if_then_else_parallelized_no_cleanup(condition, a, b),
|
||||
);
|
||||
}
|
||||
|
||||
// We move the block message by one bit: it is the most flexible option (at least for 2_2)
|
||||
// as it allows the block to have noise_level <= 2 or the condition block to have
|
||||
// noise_level <= 2.
|
||||
//
|
||||
// A drawback is that everyblock needs to be cloned to be shifted, as opposed to
|
||||
// only the condition block, but it's an ok drawback
|
||||
assert!(a.blocks().iter().chain(b.blocks().iter()).all(|block| {
|
||||
self.key
|
||||
.max_noise_level
|
||||
.validate(block.noise_level() * 2 + condition.0.noise_level())
|
||||
.is_ok()
|
||||
}));
|
||||
|
||||
let zero_out_if_true_fn = |packed| {
|
||||
let condition = packed & 1;
|
||||
let value = packed / 2;
|
||||
(1 - condition) * value
|
||||
};
|
||||
|
||||
let zero_out_if_false_fn = |packed| {
|
||||
let condition = packed & 1;
|
||||
let value = packed / 2;
|
||||
condition * value
|
||||
};
|
||||
|
||||
let lut = self
|
||||
.key
|
||||
.generate_many_lookup_table(&[&zero_out_if_true_fn, &zero_out_if_false_fn]);
|
||||
|
||||
let map_condition_lut_on_blocks =
|
||||
|blocks: &[Ciphertext]| -> (Vec<Ciphertext>, Vec<Ciphertext>) {
|
||||
let mut left = Vec::with_capacity(blocks.len());
|
||||
let mut right = Vec::with_capacity(blocks.len());
|
||||
blocks
|
||||
.par_iter()
|
||||
.map(|block| {
|
||||
let mut block = self.key.unchecked_scalar_mul(block, 2);
|
||||
self.key.unchecked_add_assign(&mut block, &condition.0);
|
||||
let mut resulting_blocks = self.key.apply_many_lookup_table(&block, &lut);
|
||||
|
||||
let second_result = resulting_blocks.pop().unwrap();
|
||||
let first_result = resulting_blocks.pop().unwrap();
|
||||
|
||||
(first_result, second_result)
|
||||
})
|
||||
.unzip_into_vecs(&mut left, &mut right);
|
||||
(left, right)
|
||||
};
|
||||
|
||||
let (
|
||||
(mut a_blocks_if_cond, mut a_blocks_if_not_cond),
|
||||
(b_blocks_if_cond, b_blocks_if_not_cond),
|
||||
) = rayon::join(
|
||||
|| map_condition_lut_on_blocks(a.blocks()),
|
||||
|| map_condition_lut_on_blocks(b.blocks()),
|
||||
);
|
||||
|
||||
for (a, b) in a_blocks_if_cond.iter_mut().zip(b_blocks_if_not_cond.iter()) {
|
||||
self.key.unchecked_add_assign(a, b);
|
||||
// By construction, one of the two input encrypts only zeros
|
||||
a.degree.0 = self.message_modulus().0 - 1;
|
||||
}
|
||||
for (a, b) in a_blocks_if_not_cond.iter_mut().zip(b_blocks_if_cond.iter()) {
|
||||
self.key.unchecked_add_assign(a, b);
|
||||
// By construction, one of the two input encrypts only zeros
|
||||
a.degree.0 = self.message_modulus().0 - 1;
|
||||
}
|
||||
|
||||
(
|
||||
T::from_blocks(a_blocks_if_cond),
|
||||
T::from_blocks(a_blocks_if_not_cond),
|
||||
)
|
||||
}
|
||||
|
||||
fn scalar_flip_parallelized<T, Scalar>(
|
||||
&self,
|
||||
condition: &BooleanBlock,
|
||||
|
||||
@@ -112,6 +112,7 @@ impl ServerKey {
|
||||
/// * inputs must have the same number of blocks
|
||||
/// * block carries of both inputs must be empty
|
||||
/// * carry modulus == message modulus
|
||||
/// * blocks of the inputs a and b must have a noise_level such that a[i] - b[i] is possible
|
||||
fn compare<T>(&self, a: &T, b: &T, compare: ComparisonKind) -> BooleanBlock
|
||||
where
|
||||
T: IntegerRadixCiphertext,
|
||||
|
||||
@@ -570,7 +570,7 @@ mod test {
|
||||
for num_blocks in 1..64 {
|
||||
let num_bits = 2 * num_blocks;
|
||||
|
||||
println!("num_bits: {num_bits}");
|
||||
println!("num_bits: {num_bits}",);
|
||||
|
||||
for target_result in 0..=num_bits {
|
||||
for _ in 0..10 {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
mod abs;
|
||||
mod add;
|
||||
mod bit_extractor;
|
||||
pub(crate) mod bitonic_shuffle;
|
||||
mod bitwise_op;
|
||||
mod block_shift;
|
||||
pub(crate) mod cmux;
|
||||
@@ -47,6 +48,7 @@ use crate::integer::ciphertext::IntegerRadixCiphertext;
|
||||
use crate::integer::RadixCiphertext;
|
||||
use crate::shortint::ciphertext::{Ciphertext, NoiseLevel};
|
||||
pub(crate) use add::OutputFlag;
|
||||
pub use bitonic_shuffle::{BitonicShuffleKeySize, CollisionProbability};
|
||||
use rayon::prelude::*;
|
||||
pub use scalar_div_mod::{MiniUnsignedInteger, Reciprocable};
|
||||
pub use vector_find::MatchValues;
|
||||
@@ -323,4 +325,18 @@ impl ServerKey {
|
||||
Cow::Borrowed(ct)
|
||||
}
|
||||
}
|
||||
|
||||
/// Cleans the input inplace so that it is ready to be used in a default ops
|
||||
pub(crate) fn clean_inplace_for_default_op<T>(&self, ct: &mut T)
|
||||
where
|
||||
T: IntegerRadixCiphertext,
|
||||
{
|
||||
if ct
|
||||
.blocks()
|
||||
.iter()
|
||||
.any(|block| !block.carry_is_empty() || block.noise_level() != NoiseLevel::NOMINAL)
|
||||
{
|
||||
self.full_propagate_parallelized(ct);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ mod modulus_switch_compression;
|
||||
pub(crate) mod test_add;
|
||||
pub(crate) mod test_aes;
|
||||
pub(crate) mod test_aes256;
|
||||
pub(crate) mod test_bitonic_shuffle;
|
||||
pub(crate) mod test_bitwise_op;
|
||||
mod test_block_rotate;
|
||||
mod test_block_shift;
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
use crate::integer::keycache::KEY_CACHE;
|
||||
use crate::integer::server_key::radix_parallel::bitonic_shuffle::bitonic_network;
|
||||
use crate::integer::server_key::radix_parallel::tests_cases_unsigned::FunctionExecutor;
|
||||
use crate::integer::server_key::radix_parallel::tests_unsigned::CpuFunctionExecutor;
|
||||
use crate::integer::tests::create_parameterized_test;
|
||||
use crate::integer::{IntegerKeyKind, RadixCiphertext, RadixClientKey, ServerKey};
|
||||
#[cfg(tarpaulin)]
|
||||
use crate::shortint::parameters::coverage_parameters::*;
|
||||
use crate::shortint::parameters::test_params::*;
|
||||
use crate::shortint::parameters::*;
|
||||
use rand::Rng;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Clear reference: sorts data by keys using the same bitonic network
|
||||
/// as `ServerKey::bitonic_shuffle_with_keys`.
|
||||
fn clear_bitonic_shuffle_with_keys(data: &[u32], keys: &[u32]) -> Vec<u32> {
|
||||
assert_eq!(data.len(), keys.len());
|
||||
let n = data.len();
|
||||
if n <= 1 {
|
||||
return data.to_vec();
|
||||
}
|
||||
|
||||
let padded_n = n.next_power_of_two();
|
||||
let mut keys = keys.iter().copied().map(u64::from).collect::<Vec<_>>();
|
||||
let mut data = data.to_vec();
|
||||
|
||||
// Pad with MAX keys and zero data, so padding sorts to the end and is truncated
|
||||
for _ in 0..(padded_n - n) {
|
||||
keys.push(u64::MAX);
|
||||
data.push(0u32);
|
||||
}
|
||||
|
||||
let network = bitonic_network(padded_n);
|
||||
for stage in &network {
|
||||
let swaps: Vec<_> = stage
|
||||
.iter()
|
||||
.map(|&(i, j, ascending)| {
|
||||
let should_swap = if ascending {
|
||||
keys[i] > keys[j]
|
||||
} else {
|
||||
keys[i] < keys[j]
|
||||
};
|
||||
(i, j, should_swap)
|
||||
})
|
||||
.collect();
|
||||
|
||||
for (i, j, should_swap) in swaps {
|
||||
if should_swap {
|
||||
keys.swap(i, j);
|
||||
data.swap(i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data.truncate(n);
|
||||
data
|
||||
}
|
||||
|
||||
create_parameterized_test!(integer_bitonic_shuffle_with_keys);
|
||||
|
||||
fn integer_bitonic_shuffle_with_keys<P>(param: P)
|
||||
where
|
||||
P: Into<TestParameters>,
|
||||
{
|
||||
let executor =
|
||||
CpuFunctionExecutor::new(&ServerKey::bitonic_shuffle_with_keys::<RadixCiphertext>);
|
||||
bitonic_shuffle_with_keys_test(param, executor);
|
||||
}
|
||||
|
||||
pub(crate) fn bitonic_shuffle_with_keys_test<P, T>(param: P, mut executor: T)
|
||||
where
|
||||
P: Into<TestParameters>,
|
||||
T: for<'a> FunctionExecutor<
|
||||
(Vec<RadixCiphertext>, Vec<RadixCiphertext>),
|
||||
Result<Vec<RadixCiphertext>, crate::Error>,
|
||||
>,
|
||||
{
|
||||
let param = param.into();
|
||||
let (cks, sks) = KEY_CACHE.get_from_params(param, IntegerKeyKind::Radix);
|
||||
let num_blocks = 32usize.div_ceil(cks.parameters().message_modulus().0.ilog2() as usize);
|
||||
let cks = RadixClientKey::from((cks, num_blocks));
|
||||
let sks = Arc::new(sks);
|
||||
|
||||
executor.setup(&cks, sks);
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
for _ in 0..4 {
|
||||
let len = rng.gen_range(1..=16usize).next_power_of_two();
|
||||
let clear_keys: Vec<u32> = (0..len).map(|_| rng.gen::<u32>()).collect();
|
||||
let mut clear_data: Vec<u32> = (0..len).map(|_| rng.gen::<u32>()).collect();
|
||||
println!("clear_keys: {clear_keys:?}, clear_data: {clear_data:?}");
|
||||
|
||||
let enc_keys = clear_keys.iter().map(|&v| cks.encrypt(v as u64)).collect();
|
||||
let enc_data = clear_data.iter().map(|&v| cks.encrypt(v as u64)).collect();
|
||||
|
||||
let result = executor.execute((enc_data, enc_keys)).unwrap();
|
||||
|
||||
let mut decrypted: Vec<u32> = result
|
||||
.iter()
|
||||
.map(|ct| cks.decrypt::<u64>(ct) as u32)
|
||||
.collect();
|
||||
|
||||
// Check the encrypted implementation matches the clear one
|
||||
let expected = clear_bitonic_shuffle_with_keys(&clear_data, &clear_keys);
|
||||
assert_eq!(decrypted, expected);
|
||||
|
||||
// Check that the permutation did not lose any of the data
|
||||
decrypted.sort_unstable();
|
||||
clear_data.sort_unstable();
|
||||
assert_eq!(decrypted, clear_data, "permutation lost data");
|
||||
}
|
||||
|
||||
{
|
||||
let len = 17;
|
||||
let mut clear_keys: Vec<u32> = (0..len).map(|_| rng.gen::<u32>()).collect();
|
||||
let mut clear_data: Vec<u32> = (0..len).map(|_| rng.gen::<u32>()).collect();
|
||||
clear_keys[3] = u32::MAX;
|
||||
assert!(!clear_keys.len().is_power_of_two());
|
||||
println!("clear_keys: {clear_keys:?}, clear_data: {clear_data:?}");
|
||||
|
||||
let enc_keys = clear_keys.iter().map(|&v| cks.encrypt(v as u64)).collect();
|
||||
let enc_data = clear_data.iter().map(|&v| cks.encrypt(v as u64)).collect();
|
||||
|
||||
let result = executor.execute((enc_data, enc_keys)).unwrap();
|
||||
|
||||
let mut decrypted: Vec<u32> = result
|
||||
.iter()
|
||||
.map(|ct| cks.decrypt::<u64>(ct) as u32)
|
||||
.collect();
|
||||
|
||||
// Check the encrypted implementation matches the clear one
|
||||
let expected = clear_bitonic_shuffle_with_keys(&clear_data, &clear_keys);
|
||||
assert_eq!(decrypted, expected);
|
||||
|
||||
// Check that the permutation did not lose any of the data
|
||||
decrypted.sort_unstable();
|
||||
clear_data.sort_unstable();
|
||||
assert_eq!(decrypted, clear_data, "permutation lost data");
|
||||
}
|
||||
}
|
||||
@@ -75,5 +75,4 @@ macro_rules! create_parameterized_test_classical_params {
|
||||
});
|
||||
};
|
||||
}
|
||||
pub(crate) use create_parameterized_test;
|
||||
pub(crate) use create_parameterized_test_classical_params;
|
||||
pub(crate) use {create_parameterized_test, create_parameterized_test_classical_params};
|
||||
|
||||
@@ -667,7 +667,7 @@ mod test {
|
||||
let pubk = CompactPublicKey::new(&privk);
|
||||
|
||||
let crs = CompactPkeCrs::from_shortint_params(cpk_params, LweCiphertextCount(4)).unwrap();
|
||||
let metadata = b"shortint";
|
||||
let metadata = [b's', b'h', b'o', b'r', b't', b'i', b'n', b't'];
|
||||
|
||||
let ksk_builder = KeySwitchingKeyBuildHelper::new((&privk, None), (&cks, &sks), ks_params);
|
||||
let casting_key: KeySwitchingKeyView<'_> = ksk_builder.as_key_switching_key_view();
|
||||
@@ -688,7 +688,7 @@ mod test {
|
||||
.encrypt_and_prove_slice(
|
||||
&messages,
|
||||
&crs,
|
||||
metadata,
|
||||
&metadata,
|
||||
ZkComputeLoad::Verify,
|
||||
cpk_params.message_modulus.0,
|
||||
)
|
||||
|
||||
@@ -192,7 +192,7 @@ impl ProvenCompactCiphertextList {
|
||||
let expanded = self
|
||||
.proved_lists
|
||||
.iter()
|
||||
.zip(per_list_casting_mode)
|
||||
.zip(per_list_casting_mode.into_iter())
|
||||
.map(|((ct_list, _proof), casting_mode)| ct_list.expand(casting_mode))
|
||||
.collect::<Result<Vec<Vec<_>>, _>>()?
|
||||
.into_iter()
|
||||
@@ -385,7 +385,7 @@ mod tests {
|
||||
|
||||
let functions = vec![Some(vec![dyn_id; 1]); 1];
|
||||
|
||||
let metadata = b"shortint";
|
||||
let metadata = [b's', b'h', b'o', b'r', b't', b'i', b'n', b't'];
|
||||
|
||||
let msg = random::<u64>() % pke_params.message_modulus.0;
|
||||
// No packing
|
||||
@@ -395,7 +395,7 @@ mod tests {
|
||||
.encrypt_and_prove(
|
||||
msg,
|
||||
&crs,
|
||||
metadata,
|
||||
&metadata,
|
||||
ZkComputeLoad::Proof,
|
||||
encryption_modulus,
|
||||
)
|
||||
@@ -417,7 +417,7 @@ mod tests {
|
||||
let proven_ct = proven_ct.verify_and_expand(
|
||||
&crs,
|
||||
&pub_key,
|
||||
metadata,
|
||||
&metadata,
|
||||
ShortintCompactCiphertextListCastingMode::CastIfNecessary {
|
||||
casting_key: ksk.as_view(),
|
||||
functions: Some(functions.as_slice()),
|
||||
@@ -447,7 +447,7 @@ mod tests {
|
||||
|
||||
let functions = vec![Some(vec![dyn_id; 1]); 512];
|
||||
|
||||
let metadata = b"shortint";
|
||||
let metadata = [b's', b'h', b'o', b'r', b't', b'i', b'n', b't'];
|
||||
|
||||
let msgs = (0..512)
|
||||
.map(|_| random::<u64>() % params.message_modulus.0)
|
||||
@@ -457,18 +457,18 @@ mod tests {
|
||||
.encrypt_and_prove_slice(
|
||||
&msgs,
|
||||
&crs,
|
||||
metadata,
|
||||
&metadata,
|
||||
ZkComputeLoad::Proof,
|
||||
params.message_modulus.0,
|
||||
)
|
||||
.unwrap();
|
||||
assert!(proven_ct.verify(&crs, &pub_key, metadata).is_valid());
|
||||
assert!(proven_ct.verify(&crs, &pub_key, &metadata).is_valid());
|
||||
|
||||
let expanded = proven_ct
|
||||
.verify_and_expand(
|
||||
&crs,
|
||||
&pub_key,
|
||||
metadata,
|
||||
&metadata,
|
||||
ShortintCompactCiphertextListCastingMode::CastIfNecessary {
|
||||
casting_key: ksk.as_view(),
|
||||
functions: Some(functions.as_slice()),
|
||||
@@ -496,7 +496,7 @@ mod tests {
|
||||
let sk = ServerKey::new(&ck);
|
||||
let ksk = KeySwitchingKey::new((&priv_key, None), (&ck, &sk), ksk_params);
|
||||
|
||||
let metadata = b"shortint";
|
||||
let metadata = [b's', b'h', b'o', b'r', b't', b'i', b'n', b't'];
|
||||
|
||||
let msgs = (0..512)
|
||||
.map(|_| random::<u64>() % params.message_modulus.0)
|
||||
@@ -506,18 +506,18 @@ mod tests {
|
||||
.encrypt_and_prove_slice(
|
||||
&msgs,
|
||||
&crs,
|
||||
metadata,
|
||||
&metadata,
|
||||
ZkComputeLoad::Proof,
|
||||
params.message_modulus.0,
|
||||
)
|
||||
.unwrap();
|
||||
assert!(proven_ct.verify(&crs, &pub_key, metadata).is_valid());
|
||||
assert!(proven_ct.verify(&crs, &pub_key, &metadata).is_valid());
|
||||
|
||||
let expanded = proven_ct
|
||||
.verify_and_expand(
|
||||
&crs,
|
||||
&pub_key,
|
||||
metadata,
|
||||
&metadata,
|
||||
ShortintCompactCiphertextListCastingMode::CastIfNecessary {
|
||||
casting_key: ksk.as_view(),
|
||||
functions: None,
|
||||
@@ -544,7 +544,7 @@ mod tests {
|
||||
let priv_key = CompactPrivateKey::new(pke_params);
|
||||
let pub_key = CompactPublicKey::new(&priv_key);
|
||||
|
||||
let metadata = b"shortint";
|
||||
let metadata = [b's', b'h', b'o', b'r', b't', b'i', b'n', b't'];
|
||||
|
||||
let msgs = (0..total_lwe_count)
|
||||
.map(|_| random::<u64>() % params.message_modulus.0)
|
||||
@@ -554,12 +554,12 @@ mod tests {
|
||||
.encrypt_and_prove_slice(
|
||||
&msgs,
|
||||
&crs,
|
||||
metadata,
|
||||
&metadata,
|
||||
ZkComputeLoad::Verify,
|
||||
params.message_modulus.0 * params.carry_modulus.0,
|
||||
)
|
||||
.unwrap();
|
||||
assert!(proven_ct.verify(&crs, &pub_key, metadata).is_valid());
|
||||
assert!(proven_ct.verify(&crs, &pub_key, &metadata).is_valid());
|
||||
|
||||
let zk_conformance_params = CompactPkeProofConformanceParams::new(crs.scheme_version());
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ impl<Scalar: UnsignedInteger + CastFrom<u64>> ShortintEncoding<Scalar> {
|
||||
}
|
||||
|
||||
impl<Scalar: UnsignedInteger + CastFrom<u64>> ShortintEncoding<Scalar> {
|
||||
/// Return the cleartext space including the space for the [`Self::padding_bit`] if it is set to
|
||||
/// Return the cleatext space including the space for the [`Self::padding_bit`] if it is set to
|
||||
/// [`PaddingBit::Yes`].
|
||||
pub(crate) fn full_cleartext_space(&self) -> Scalar {
|
||||
let cleartext_modulus = self.cleartext_space_without_padding();
|
||||
@@ -69,7 +69,7 @@ impl<Scalar: UnsignedInteger + CastFrom<u64>> ShortintEncoding<Scalar> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the cleartext space defined by the [`Self::message_modulus`] and
|
||||
/// Return the cleatext space defined by the [`Self::message_modulus`] and
|
||||
/// [`Self::carry_modulus`], not taking the value of the [`Self::padding_bit`] into account.
|
||||
pub(crate) fn cleartext_space_without_padding(&self) -> Scalar {
|
||||
(self.message_modulus.0 * self.carry_modulus.0).cast_into()
|
||||
|
||||
@@ -1130,7 +1130,7 @@ pub mod test_utils {
|
||||
/// to 0 to keep the carry free.
|
||||
/// output_modulus: the output cleartext space, continuing the above example, it must contain
|
||||
/// the padding bit, so for 4 bits of cleartext this is actually 2^(1 + 4)==32
|
||||
pub fn cleartext_prf(
|
||||
pub fn cleatext_prf(
|
||||
input_cleartext: u64,
|
||||
random_bits_count: u64,
|
||||
output_modulus: u64,
|
||||
@@ -1163,7 +1163,7 @@ pub mod test_utils {
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod test {
|
||||
use super::test_utils::cleartext_prf;
|
||||
use super::test_utils::cleatext_prf;
|
||||
use super::*;
|
||||
use crate::core_crypto::commons::math::random::Seed;
|
||||
use crate::core_crypto::prelude::{decrypt_lwe_ciphertext, CastInto, LweSecretKeyView};
|
||||
@@ -1244,7 +1244,7 @@ pub(crate) mod test {
|
||||
|
||||
// includes padding bit
|
||||
let output_modulus = 2 * params.message_modulus().0 * params.carry_modulus().0;
|
||||
let expected_output = cleartext_prf(
|
||||
let expected_output = cleatext_prf(
|
||||
plain_prf_input,
|
||||
random_bits_count,
|
||||
output_modulus,
|
||||
|
||||
@@ -167,7 +167,7 @@ impl MetaParameters {
|
||||
return self;
|
||||
}
|
||||
|
||||
panic!("Invalid MetaParameters");
|
||||
panic!("Invalid MetaParameters",);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ impl<AP: AtomicPattern> GenericServerKey<AP> {
|
||||
pub fn unchecked_div_assign(&self, ct_left: &mut Ciphertext, ct_right: &Ciphertext) {
|
||||
let value_on_div_by_zero = ct_left.message_modulus.0 - 1;
|
||||
self.unchecked_evaluate_bivariate_function_assign(ct_left, ct_right, |x, y| {
|
||||
x.checked_div(y).unwrap_or(value_on_div_by_zero)
|
||||
safe_division(x, y, value_on_div_by_zero)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ impl<AP: AtomicPattern> GenericServerKey<AP> {
|
||||
pub fn smart_div(&self, ct_left: &mut Ciphertext, ct_right: &mut Ciphertext) -> Ciphertext {
|
||||
let value_on_div_by_zero = ct_left.message_modulus.0 - 1;
|
||||
self.smart_evaluate_bivariate_function(ct_left, ct_right, |x, y| {
|
||||
x.checked_div(y).unwrap_or(value_on_div_by_zero)
|
||||
safe_division(x, y, value_on_div_by_zero)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -257,7 +257,16 @@ impl<AP: AtomicPattern> GenericServerKey<AP> {
|
||||
pub fn smart_div_assign(&self, ct_left: &mut Ciphertext, ct_right: &mut Ciphertext) {
|
||||
let value_on_div_by_zero = ct_left.message_modulus.0 - 1;
|
||||
self.smart_evaluate_bivariate_function_assign(ct_left, ct_right, |x, y| {
|
||||
x.checked_div(y).unwrap_or(value_on_div_by_zero)
|
||||
safe_division(x, y, value_on_div_by_zero)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Specific division function returning value_on_div_by_zero in case of a division by 0
|
||||
pub(crate) fn safe_division(x: u64, y: u64, value_on_div_by_zero: u64) -> u64 {
|
||||
if y == 0 {
|
||||
value_on_div_by_zero
|
||||
} else {
|
||||
x / y
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,8 +97,7 @@ macro_rules! create_parameterized_test{
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) use create_parameterized_stringified_test;
|
||||
pub(crate) use create_parameterized_test;
|
||||
pub(crate) use {create_parameterized_stringified_test, create_parameterized_test};
|
||||
|
||||
//These functions are compatible with all parameter sets.
|
||||
create_parameterized_test!(shortint_encrypt_decrypt);
|
||||
|
||||
@@ -266,15 +266,15 @@ impl<T: Borrow<IntegerServerKey> + Sync> ServerKey<T> {
|
||||
match self.length_checks(str, &trivial_or_enc_from) {
|
||||
IsMatch::Clear(false) => return result,
|
||||
|
||||
// If `from` is empty and str too, there's only one match and one replacement
|
||||
IsMatch::Clear(true) if str.is_empty() => {
|
||||
match count {
|
||||
UIntArg::Clear(_) => {
|
||||
IsMatch::Clear(true) => {
|
||||
// If `from` is empty and str too, there's only one match and one replacement
|
||||
if str.is_empty() {
|
||||
if let UIntArg::Clear(_) = count {
|
||||
return to.clone();
|
||||
}
|
||||
|
||||
// We have to take into account that encrypted n could be 0
|
||||
UIntArg::Enc(enc_n) => {
|
||||
if let UIntArg::Enc(enc_n) = count {
|
||||
let n_is_zero = sk.scalar_eq_parallelized(enc_n.cipher(), 0);
|
||||
|
||||
let mut re = self.conditional_string(&n_is_zero, &result, to);
|
||||
@@ -290,22 +290,21 @@ impl<T: Borrow<IntegerServerKey> + Sync> ServerKey<T> {
|
||||
// This happens when str is empty, so it's again one replacement if there's match or
|
||||
// if there isn't we return the str
|
||||
IsMatch::Cipher(val) => {
|
||||
match count {
|
||||
UIntArg::Clear(_) => {
|
||||
return self.conditional_string(&val, to, str);
|
||||
}
|
||||
UIntArg::Enc(enc_n) => {
|
||||
let n_not_zero = sk.scalar_ne_parallelized(enc_n.cipher(), 0);
|
||||
let and_val = sk.boolean_bitand(&n_not_zero, &val);
|
||||
if let UIntArg::Clear(_) = count {
|
||||
return self.conditional_string(&val, to, str);
|
||||
}
|
||||
|
||||
let mut re = self.conditional_string(&and_val, to, str);
|
||||
if let UIntArg::Enc(enc_n) = count {
|
||||
let n_not_zero = sk.scalar_ne_parallelized(enc_n.cipher(), 0);
|
||||
let and_val = sk.boolean_bitand(&n_not_zero, &val);
|
||||
|
||||
// When result or to are empty we get padding via the conditional_string
|
||||
// (pad_ciphertexts_lsb). And the condition result may or may not have
|
||||
// padding in this case.
|
||||
re.append_null(self);
|
||||
return re;
|
||||
}
|
||||
let mut re = self.conditional_string(&and_val, to, str);
|
||||
|
||||
// When result or to are empty we get padding via the conditional_string
|
||||
// (pad_ciphertexts_lsb). And the condition result may or may not have
|
||||
// padding in this case.
|
||||
re.append_null(self);
|
||||
return re;
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
@@ -384,9 +383,11 @@ impl<T: Borrow<IntegerServerKey> + Sync> ServerKey<T> {
|
||||
|
||||
match self.length_checks(str, &trivial_or_enc_from) {
|
||||
IsMatch::Clear(false) => return result,
|
||||
// If `from` is empty and str too, there's only one match and one replacement
|
||||
IsMatch::Clear(true) if str.is_empty() => {
|
||||
return to.clone();
|
||||
IsMatch::Clear(true) => {
|
||||
// If `from` is empty and str too, there's only one match and one replacement
|
||||
if str.is_empty() {
|
||||
return to.clone();
|
||||
}
|
||||
}
|
||||
// This happens when str is empty, so it's again one replacement if there's match or
|
||||
// if there isn't we return the str
|
||||
|
||||
@@ -16,7 +16,7 @@ use tfhe::zk::CompactPkeCrs;
|
||||
use tfhe::{ClientKey, CompactPublicKey, ConfigBuilder, ProvenCompactCiphertextList};
|
||||
|
||||
const SIZE_LIMIT: u64 = 1024 * 1024 * 1024;
|
||||
const METADATA: [u8; 6] = *b"wasm64";
|
||||
const METADATA: [u8; 6] = [b'w', b'a', b's', b'm', b'6', b'4'];
|
||||
|
||||
fn gen_key_and_crs() -> (CompactPublicKey, CompactPkeCrs) {
|
||||
println!("Generating keys");
|
||||
|
||||
@@ -635,9 +635,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.6"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
|
||||
@@ -710,9 +710,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.6"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
|
||||
@@ -635,9 +635,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.6"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
|
||||
@@ -719,9 +719,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.6"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
|
||||
@@ -721,9 +721,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.6"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
|
||||
@@ -721,9 +721,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.6"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
|
||||
@@ -763,9 +763,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.6"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
|
||||
@@ -779,9 +779,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.6"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
|
||||
@@ -781,9 +781,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.6"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
@@ -977,7 +977,6 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tfhe"
|
||||
version = "1.6.0"
|
||||
source = "git+https://github.com/zama-ai/tfhe-rs.git?tag=tfhe-rs-1.6.0#7b174b1865736e3291b5e35294acfe02946c42db"
|
||||
dependencies = [
|
||||
"aligned-vec",
|
||||
"bincode",
|
||||
@@ -1016,7 +1015,6 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tfhe-csprng"
|
||||
version = "0.9.0"
|
||||
source = "git+https://github.com/zama-ai/tfhe-rs.git?tag=tfhe-rs-1.6.0#7b174b1865736e3291b5e35294acfe02946c42db"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"getrandom",
|
||||
@@ -1029,7 +1027,6 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tfhe-fft"
|
||||
version = "0.10.1"
|
||||
source = "git+https://github.com/zama-ai/tfhe-rs.git?tag=tfhe-rs-1.6.0#7b174b1865736e3291b5e35294acfe02946c42db"
|
||||
dependencies = [
|
||||
"aligned-vec",
|
||||
"bytemuck",
|
||||
@@ -1043,7 +1040,6 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tfhe-ntt"
|
||||
version = "0.7.1"
|
||||
source = "git+https://github.com/zama-ai/tfhe-rs.git?tag=tfhe-rs-1.6.0#7b174b1865736e3291b5e35294acfe02946c42db"
|
||||
dependencies = [
|
||||
"aligned-vec",
|
||||
"bytemuck",
|
||||
@@ -1053,7 +1049,6 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tfhe-safe-serialize"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zama-ai/tfhe-rs.git?tag=tfhe-rs-1.6.0#7b174b1865736e3291b5e35294acfe02946c42db"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"serde",
|
||||
@@ -1063,7 +1058,6 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tfhe-versionable"
|
||||
version = "0.7.0"
|
||||
source = "git+https://github.com/zama-ai/tfhe-rs.git?tag=tfhe-rs-1.6.0#7b174b1865736e3291b5e35294acfe02946c42db"
|
||||
dependencies = [
|
||||
"aligned-vec",
|
||||
"num-complex",
|
||||
@@ -1074,7 +1068,6 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tfhe-versionable-derive"
|
||||
version = "0.7.0"
|
||||
source = "git+https://github.com/zama-ai/tfhe-rs.git?tag=tfhe-rs-1.6.0#7b174b1865736e3291b5e35294acfe02946c42db"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1084,7 +1077,6 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tfhe-zk-pok"
|
||||
version = "0.8.1"
|
||||
source = "git+https://github.com/zama-ai/tfhe-rs.git?tag=tfhe-rs-1.6.0#7b174b1865736e3291b5e35294acfe02946c42db"
|
||||
dependencies = [
|
||||
"ark-bls12-381",
|
||||
"ark-ec",
|
||||
|
||||
@@ -10,13 +10,23 @@ license = "BSD-3-Clause-Clear"
|
||||
clap = { version = "4.5", features = ["derive"] }
|
||||
|
||||
# TFHE-rs
|
||||
tfhe = { git = "https://github.com/zama-ai/tfhe-rs.git", tag = "tfhe-rs-1.6.0", features = [
|
||||
tfhe = { features = [
|
||||
"boolean",
|
||||
"integer",
|
||||
"shortint",
|
||||
"zk-pok",
|
||||
"experimental-force_fft_algo_dif4",
|
||||
] }
|
||||
tfhe-versionable = { git = "https://github.com/zama-ai/tfhe-rs.git", tag = "tfhe-rs-1.6.0" }
|
||||
], path = "../../../../tfhe" }
|
||||
tfhe-versionable = { path = "../../../tfhe-versionable" }
|
||||
|
||||
# Uncomment this and remove the lines above once the current tfhe-rs version has been released
|
||||
# tfhe = { git = "https://github.com/zama-ai/tfhe-rs.git", tag = "tfhe-rs-1.6.0", features = [
|
||||
# "boolean",
|
||||
# "integer",
|
||||
# "shortint",
|
||||
# "zk-pok",
|
||||
# "experimental-force_fft_algo_dif4",
|
||||
# ] }
|
||||
# tfhe-versionable = { git = "https://github.com/zama-ai/tfhe-rs.git", tag = "tfhe-rs-1.6.0" }
|
||||
|
||||
tfhe-backward-compat-data = { path = "../.." }
|
||||
|
||||
Reference in New Issue
Block a user