mirror of
https://github.com/zama-ai/tfhe-rs.git
synced 2026-01-05 04:44:41 -05:00
chore: test vector generation tool for core algorithms
This commit is contained in:
committed by
Nicolas Sarlin
parent
f45b7a9fdc
commit
fc78450245
@@ -15,6 +15,7 @@ members = [
|
||||
"utils/param_dedup",
|
||||
"tests",
|
||||
"mockups/tfhe-hpu-mockup",
|
||||
"apps/test-vectors",
|
||||
]
|
||||
|
||||
exclude = [
|
||||
|
||||
25
Makefile
25
Makefile
@@ -25,6 +25,7 @@ BENCH_CUSTOM_COMMAND:=
|
||||
NODE_VERSION=22.6
|
||||
BACKWARD_COMPAT_DATA_DIR=utils/tfhe-backward-compat-data
|
||||
BACKWARD_COMPAT_DATA_GEN_VERSION:=$(TFHE_VERSION)
|
||||
TEST_VECTORS_DIR=apps/test-vectors
|
||||
CURRENT_TFHE_VERSION:=$(shell grep '^version[[:space:]]*=' tfhe/Cargo.toml | cut -d '=' -f 2 | xargs)
|
||||
WASM_PACK_VERSION="0.13.1"
|
||||
WASM_BINDGEN_VERSION:=$(shell cargo tree --target wasm32-unknown-unknown -e all --prefix none | grep "wasm-bindgen v" | head -n 1 | cut -d 'v' -f2)
|
||||
@@ -525,11 +526,16 @@ clippy_backward_compat_data: install_rs_check_toolchain # the toolchain is selec
|
||||
echo "Cannot run clippy for backward compat crate on non x86 platform for now."; \
|
||||
fi
|
||||
|
||||
.PHONY: clippy_test_vectors # Run clippy lints on the test vectors app
|
||||
clippy_test_vectors: install_rs_check_toolchain
|
||||
cd apps/test-vectors; RUSTFLAGS="$(RUSTFLAGS)" cargo "$(CARGO_RS_CHECK_TOOLCHAIN)" clippy --all-targets \
|
||||
-p tfhe-test-vectors -- --no-deps -D warnings
|
||||
|
||||
.PHONY: clippy_all # Run all clippy targets
|
||||
clippy_all: clippy_rustdoc clippy clippy_boolean clippy_shortint clippy_integer clippy_all_targets \
|
||||
clippy_c_api clippy_js_wasm_api clippy_tasks clippy_core clippy_tfhe_csprng clippy_zk_pok clippy_trivium \
|
||||
clippy_versionable clippy_tfhe_lints clippy_ws_tests clippy_bench clippy_param_dedup \
|
||||
clippy_backward_compat_data
|
||||
clippy_test_vectors clippy_backward_compat_data
|
||||
|
||||
.PHONY: clippy_fast # Run main clippy targets
|
||||
clippy_fast: clippy_rustdoc clippy clippy_all_targets clippy_c_api clippy_js_wasm_api clippy_tasks \
|
||||
@@ -1184,6 +1190,17 @@ test_backward_compatibility_ci: install_rs_build_toolchain
|
||||
.PHONY: test_backward_compatibility # Same as test_backward_compatibility_ci but tries to clone the data repo first if needed
|
||||
test_backward_compatibility: pull_backward_compat_data test_backward_compatibility_ci
|
||||
|
||||
# Generate the test vectors and update the hash file
|
||||
.PHONY: gen_test_vectors
|
||||
gen_test_vectors:
|
||||
./scripts/test_vectors.sh generate apps/test-vectors
|
||||
|
||||
# Generate the test vectors and check that the content matches the hash file
|
||||
# `comm` is used to compare the checksums, and will also notify of any added file
|
||||
.PHONY: check_test_vectors
|
||||
check_test_vectors:
|
||||
./scripts/test_vectors.sh check apps/test-vectors
|
||||
|
||||
.PHONY: doc # Build rust doc
|
||||
doc: install_rs_check_toolchain
|
||||
@# Even though we are not in docs.rs, this allows to "just" build the doc
|
||||
@@ -1723,6 +1740,10 @@ pull_backward_compat_data:
|
||||
pull_hpu_files:
|
||||
./scripts/pull_lfs_data.sh backends/tfhe-hpu-backend/
|
||||
|
||||
.PHONY: pull_test_vectors # Pull the data files needed for backward compatibility tests
|
||||
pull_test_vectors:
|
||||
./scripts/pull_lfs_data.sh $(TEST_VECTORS_DIR)
|
||||
|
||||
#
|
||||
# Real use case examples
|
||||
#
|
||||
@@ -1774,6 +1795,8 @@ pcc_batch_2:
|
||||
$(call run_recipe_with_details,clippy)
|
||||
$(call run_recipe_with_details,clippy_all_targets)
|
||||
$(call run_recipe_with_details,check_fmt_js)
|
||||
$(call run_recipe_with_details,clippy_test_vectors)
|
||||
$(call run_recipe_with_details,check_test_vectors)
|
||||
|
||||
.PHONY: pcc_batch_3 # duration: 6'50''
|
||||
pcc_batch_3:
|
||||
|
||||
11
apps/test-vectors/Cargo.toml
Normal file
11
apps/test-vectors/Cargo.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "tfhe-test-vectors"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
rust-version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
ciborium = "0.2"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tfhe = { path = "../../tfhe", features = ["experimental-force_fft_algo_dif4"] }
|
||||
tfhe-csprng = { path = "../../tfhe-csprng" }
|
||||
11
apps/test-vectors/README.md
Normal file
11
apps/test-vectors/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Test vectors for TFHE
|
||||
This folder contains test vectors for the core TFHE-rs algorithms.
|
||||
|
||||
The test vectors are located in `data`, and are generated using the sample program in `src/main.rs`.
|
||||
|
||||
To re-generate the test vectors, assuming you have [rustup](https://rust-lang.org/tools/install/) installed on your system, simply run the following command in the current folder:
|
||||
```
|
||||
cargo run --release
|
||||
```
|
||||
|
||||
See [the data folder](data/README.md) for more information about the generated values.
|
||||
28
apps/test-vectors/checksums.sha256
Normal file
28
apps/test-vectors/checksums.sha256
Normal file
@@ -0,0 +1,28 @@
|
||||
2abec9dc5d399ece68ac227f67f7cafcb9a6acac36ed734fe3d5244021eb1cda data/toy_params/glwe_after_spec_br.cbor
|
||||
2c70d1d78cc3760733850a353ace2b9c4705e840141b75841739e90e51247e18 data/valid_params_128/small_lwe_secret_key.cbor
|
||||
36c9080b636475fcacca503ce041bbfeee800fd3e1890dee559ea18defff9fe8 data/toy_params/glwe_after_id_br.cbor
|
||||
377761beeb4216cf5aa2624a8b64b8259f5a75c32d28e850be8bced3a0cdd6f5 data/toy_params/ksk.cbor
|
||||
59dba26d457f96478eda130cab5301fce86f23c6a8807de42f2a1e78c4985ca7 data/valid_params_128/lwe_ks.cbor
|
||||
656f0009c7834c5bcb61621e222047516054b9bc5d0593d474ab8f1c086b67a6 data/valid_params_128/lwe_after_id_pbs.cbor
|
||||
699580ca92b9c2f9e1f57fb1e312c9e8cb29714f7acdef9d2ba05f798546751f data/toy_params/lwe_sum.cbor
|
||||
6e54ab41056984595b077baff70236d934308cf5c0c33b4482fbfb129b3756c6 data/valid_params_128/glwe_after_id_br.cbor
|
||||
70f5e5728822de05b49071efb5ec28551b0f5cc87aa709a455d8e7f04b9c96ee data/toy_params/lwe_after_id_pbs.cbor
|
||||
7cc6803f5fbc3d5a1bf597f2b979ce17eecd3d6baca12183dea21022a7b65c52 data/toy_params/bsk.cbor
|
||||
7f3c40a134623b44779a556212477fea26eaed22450f3b6faeb8721d63699972 data/valid_params_128/lwe_sum.cbor
|
||||
837b3bd3245d4d0534ed255fdef896fb4fa6998a258a14543dfdadd0bfc9b6dd data/toy_params/lwe_prod.cbor
|
||||
8ee68ed99dd9103fb62b1e2c7c8cf483706ae2071b792d4bd16f9f93f64871f9 data/toy_params/lwe_after_spec_pbs.cbor
|
||||
99a19c5d6d5f4fd81d9164d0ff96719ef362eabda256bce6a55cba6cb69e42bf data/valid_params_128/glwe_after_spec_br.cbor
|
||||
aa44aea29efd6d9e4d35a21a625d9cba155672e3f7ed3eddee1e211e62ad146b data/valid_params_128/lwe_ms.cbor
|
||||
b7a037b9eaa88d6385167579b93e26a0cb6976d9b8967416fd1173e113bda199 data/valid_params_128/large_lwe_secret_key.cbor
|
||||
c6df98676de04fe54b5ffc2eb30a82ebb706c9d7d5a4e0ed509700fec88761f7 data/toy_params/lwe_ms.cbor
|
||||
c7d5a864d5616a7d8ad50bbf40416e41e6c9b60c546dc14d4aa8fc40a418baa7 data/toy_params/large_lwe_secret_key.cbor
|
||||
c806533b325b1009db38be2f9bef5f3b2fad6b77b4c71f2855ccc9d3b4162e98 data/valid_params_128/lwe_b.cbor
|
||||
c9eb75bd2993639348a679cf48c06e3c38d1a513f48e5b0ce0047cea8cff6bbc data/toy_params/lwe_a.cbor
|
||||
d6da5baef0e787f6be56e218d8354e26904652602db964844156fdff08350ce6 data/toy_params/lwe_ks.cbor
|
||||
e44ffa6e5a50a03d32721180a051c8ce62f1791d4853aeaebed0200c183a57cf data/valid_params_128/lwe_after_spec_pbs.cbor
|
||||
e591ab9af1b6a0aede273f9a3abb65a4c387feb5fa06a6959e9314058ca0f7e5 data/valid_params_128/ksk.cbor
|
||||
e69d2d2c064fc8c0460b39191ca65338146990349954f5ec5ebd01d93610e7eb data/valid_params_128/lwe_a.cbor
|
||||
e76c24b2a0c9a842ad13dda35473c2514f9e7d20983b5ea0759c4521a91626d9 data/valid_params_128/lwe_prod.cbor
|
||||
e9afe7019acba5cda926f13e06df9930571611729d2f2e8ce41956e1f5e1db6f data/valid_params_128/bsk.cbor
|
||||
eadf2eff35133ffba075df11faecddd6e7af9ddc398011ec4568e5528812b3e2 data/toy_params/lwe_b.cbor
|
||||
ee9fcf45f1379ca3a7d7bf2b0e7a1cc920ceb496c0217e8604b0b58d2831749e data/toy_params/small_lwe_secret_key.cbor
|
||||
102
apps/test-vectors/data/README.md
Normal file
102
apps/test-vectors/data/README.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# Test vectors for TFHE
|
||||
These test vectors are generated using [TFHE-rs](https://github.com/zama-ai/tfhe-rs), with the git tag `tfhe-test-vectors-0.1.0`.
|
||||
|
||||
They are TFHE-rs objects serialized in the [cbor format](https://cbor.io/). You can deserialize them using any cbor library for the language of your choice. For example, using the [cbor2](https://pypi.org/project/cbor2/) program, run: `cbor2 --pretty toy_params/lwe_a.cbor`.
|
||||
|
||||
You will find 2 folders with test vectors for different parameter sets:
|
||||
- `valid_params_128`: valid classical PBS parameters using a gaussian noise distribution, providing 128bits of security in the IND-CPA model and a bootstrapping probability of failure of 2^{-64}.
|
||||
- `toy_params`: insecure parameters that yield smaller values
|
||||
|
||||
The values are generated for the keyswitch -> bootstrap (KS-PBS) atomic pattern. The cleartext inputs are 2 values, A and B defined below.
|
||||
|
||||
All the random values are generated from a fixed seed, that can be found in the `RAND_SEED` constant below. The PRNG used is the one based on the AES block cipher in counter mode, from tfhe `tfhe-csprng` crate.
|
||||
|
||||
The programmable bootstrap is applied twice, with 2 different lut, the identity lut and a specific one (currently a x2 operation)
|
||||
|
||||
## Vectors
|
||||
The following values are generated:
|
||||
|
||||
### Keys
|
||||
| name | description | TFHE-rs type |
|
||||
|------------------------|---------------------------------------------------------------------------------------|-----------------------------|
|
||||
| `large_lwe_secret_key` | Encryption secret key, before the KS and after the PBS | `LweSecretKey<Vec<u64>>` |
|
||||
| `small_lwe_secret_key` | Secret key encrypting ciphertexts between the KS and the PBS | `LweSecretKey<Vec<u64>>` |
|
||||
| `ksk` | The keyswitching key to convert a ct from the large key to the small one | `LweKeyswitchKey<Vec<u64>>` |
|
||||
| `bsk` | the bootstrapping key to perform a programmable bootstrap on the keyswitched ciphertext | `LweBootstrapKey<Vec<u64>>` |
|
||||
|
||||
|
||||
### Ciphertexts
|
||||
| name | description | TFHE-rs type | Cleartext |
|
||||
|----------------------|--------------------------------------------------------------------------------------------------------------|----------------------------|--------------|
|
||||
| `lwe_a` | Lwe encryption of A | `LweCiphertext<Vec<u64>>` | `A` |
|
||||
| `lwe_b` | Lwe encryption of B | `LweCiphertext<Vec<u64>>` | `B` |
|
||||
| `lwe_sum` | Lwe encryption of A plus lwe encryption of B | `LweCiphertext<Vec<u64>>` | `A+B` |
|
||||
| `lwe_prod` | Lwe encryption of A times cleartext B | `LweCiphertext<Vec<u64>>` | `A*B` |
|
||||
| `lwe_ms` | The lwe ciphertext after the modswitch part of the PBS ([note](#non-native-encoding)) | `LweCiphertext<Vec<u64>>` | `A` |
|
||||
| `lwe_ks` | The lwe ciphertext after the keyswitch | `LweCiphertext<Vec<u64>>` | `A` |
|
||||
| `glwe_after_id_br` | The glwe returned by the application of the identity blind rotation on the mod switched ciphertexts. | `GlweCiphertext<Vec<u64>>` | rot id LUT |
|
||||
| `lwe_after_id_pbs` | The lwe returned by the application of the sample extract operation on the output of the id blind rotation | `LweCiphertext<Vec<u64>>` | `A` |
|
||||
| `glwe_after_spec_br` | The glwe returned by the application of the spec blind rotation on the mod switched ciphertexts. | `GlweCiphertext<Vec<u64>>` | rot spec LUT |
|
||||
| `lwe_after_spec_pbs` | The lwe returned by the application of the sample extract operation on the output of the spec blind rotation | `LweCiphertext<Vec<u64>>` | `spec(A)` |
|
||||
|
||||
### Encodings
|
||||
#### Non native encoding
|
||||
Warning: TFHE-rs uses a specific encoding for non native (ie: u32, u64) power of two ciphertext modulus. This encoding puts the encoded value in the high bits of the native integer.
|
||||
For example, the value 37 with a modulus of 64 will be encoded as `0b1001010000000000000000000000000000000000000000000000000000000000`. This matters for the post modswitch lwe ciphertext.
|
||||
|
||||
#### Ciphertext modulus
|
||||
The ciphertext modulus encoding use a specific value for the native modulus: 0. For example, if values are stored on u64 integers, 0 means a ciphertext modulus of 2^64.
|
||||
|
||||
## Operations
|
||||
|
||||
| name | inputs | outputs |
|
||||
|-------------------------|-------------------------------------------------------------------|------------------------|
|
||||
| large secret key gen | PARAMS, RAND_SEED | `large_lwe_secret_key` |
|
||||
| small secret key gen | PARAMS, RAND_SEED | `small_lwe_secret_key` |
|
||||
| keyswitch key gen | PARAMS, RAND_SEED, `large_lwe_secret_key`, `small_lwe_secret_key` | `ksk` |
|
||||
| bootstrap key gen | PARAMS, RAND_SEED, `small_lwe_secret_key`, `large_lwe_secret_key` | `bsk` |
|
||||
| encryption A | A, `large_lwe_secret_key` | `lwe_a` |
|
||||
| encryption B | B, `large_lwe_secret_key` | `lwe_b` |
|
||||
| `E(A)+E(B)` | `lwe_a`, `lwe_b` | `lwe_sum` |
|
||||
| `E(A)*B` | `lwe_a`, B | `lwe_prod` |
|
||||
| keyswitch | `lwe_a`, `ksk` | `lwe_ks` |
|
||||
| modulus switch | `lwe_ks` | `lwe_ms` |
|
||||
| blind rotation id lut | ID_LUT, `lwe_ms`, `bsk` | `glwe_after_id_br` |
|
||||
| sample extract id lut | `glwe_after_id_br` | `lwe_after_id_pbs` |
|
||||
| blind rotation spec lut | SPEC_LUT, `lwe_ms`, `bsk` | `glwe_after_spec_br` |
|
||||
| sample extract spec lut | `glwe_after_spec_br` | `lwe_after_spec_pbs` |
|
||||
|
||||
## Parameters
|
||||
|
||||
```rust
|
||||
const RAND_SEED: u128 = 0x74666865;
|
||||
|
||||
const MSG_A: u64 = 4;
|
||||
const MSG_B: u64 = 3;
|
||||
|
||||
const VALID_LWE_DIMENSION: LweDimension = LweDimension(833);
|
||||
const VALID_GLWE_DIMENSION: GlweDimension = GlweDimension(1);
|
||||
const VALID_POLYNOMIAL_SIZE: PolynomialSize = PolynomialSize(2048);
|
||||
const VALID_GAUSSIAN_LWE_NOISE_STDDEV: f64 = 3.6158408373309336e-06;
|
||||
const VALID_GAUSSIAN_GLWE_NOISE_STDDEV: f64 = 2.845267479601915e-15;
|
||||
const VALID_PBS_DECOMPOSITION_BASE_LOG: DecompositionBaseLog = DecompositionBaseLog(23);
|
||||
const VALID_PBS_DECOMPOSITION_LEVEL_COUNT: DecompositionLevelCount = DecompositionLevelCount(1);
|
||||
const VALID_KS_DECOMPOSITION_BASE_LOG: DecompositionBaseLog = DecompositionBaseLog(3);
|
||||
const VALID_KS_DECOMPOSITION_LEVEL_COUNT: DecompositionLevelCount = DecompositionLevelCount(5);
|
||||
|
||||
const TOY_LWE_DIMENSION: LweDimension = LweDimension(10);
|
||||
const TOY_GLWE_DIMENSION: GlweDimension = GlweDimension(1);
|
||||
const TOY_POLYNOMIAL_SIZE: PolynomialSize = PolynomialSize(256);
|
||||
const TOY_GAUSSIAN_LWE_NOISE_STDDEV: f64 = 0.;
|
||||
const TOY_GAUSSIAN_GLWE_NOISE_STDDEV: f64 = 0.;
|
||||
const TOY_PBS_DECOMPOSITION_BASE_LOG: DecompositionBaseLog = DecompositionBaseLog(24);
|
||||
const TOY_PBS_DECOMPOSITION_LEVEL_COUNT: DecompositionLevelCount = DecompositionLevelCount(1);
|
||||
const TOY_KS_DECOMPOSITION_BASE_LOG: DecompositionBaseLog = DecompositionBaseLog(37);
|
||||
const TOY_KS_DECOMPOSITION_LEVEL_COUNT: DecompositionLevelCount = DecompositionLevelCount(1);
|
||||
|
||||
const CIPHERTEXT_MODULUS: CiphertextModulus<u64> = CiphertextModulus::new_native();
|
||||
const MSG_BITS: usize = 4;
|
||||
|
||||
const SPEC_LUT: fn(u64) -> u64 = |x| (x * 2) % (1u64 << MSG_BITS);
|
||||
const ID_LUT: fn(u64) -> u64 = |x| x;
|
||||
```
|
||||
3
apps/test-vectors/data/toy_params/bsk.cbor
Normal file
3
apps/test-vectors/data/toy_params/bsk.cbor
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7cc6803f5fbc3d5a1bf597f2b979ce17eecd3d6baca12183dea21022a7b65c52
|
||||
size 92291
|
||||
3
apps/test-vectors/data/toy_params/glwe_after_id_br.cbor
Normal file
3
apps/test-vectors/data/toy_params/glwe_after_id_br.cbor
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:36c9080b636475fcacca503ce041bbfeee800fd3e1890dee559ea18defff9fe8
|
||||
size 4679
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2abec9dc5d399ece68ac227f67f7cafcb9a6acac36ed734fe3d5244021eb1cda
|
||||
size 4679
|
||||
3
apps/test-vectors/data/toy_params/ksk.cbor
Normal file
3
apps/test-vectors/data/toy_params/ksk.cbor
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:377761beeb4216cf5aa2624a8b64b8259f5a75c32d28e850be8bced3a0cdd6f5
|
||||
size 25451
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c7d5a864d5616a7d8ad50bbf40416e41e6c9b60c546dc14d4aa8fc40a418baa7
|
||||
size 265
|
||||
3
apps/test-vectors/data/toy_params/lwe_a.cbor
Normal file
3
apps/test-vectors/data/toy_params/lwe_a.cbor
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c9eb75bd2993639348a679cf48c06e3c38d1a513f48e5b0ce0047cea8cff6bbc
|
||||
size 2365
|
||||
3
apps/test-vectors/data/toy_params/lwe_after_id_pbs.cbor
Normal file
3
apps/test-vectors/data/toy_params/lwe_after_id_pbs.cbor
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:70f5e5728822de05b49071efb5ec28551b0f5cc87aa709a455d8e7f04b9c96ee
|
||||
size 2365
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8ee68ed99dd9103fb62b1e2c7c8cf483706ae2071b792d4bd16f9f93f64871f9
|
||||
size 2365
|
||||
3
apps/test-vectors/data/toy_params/lwe_b.cbor
Normal file
3
apps/test-vectors/data/toy_params/lwe_b.cbor
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:eadf2eff35133ffba075df11faecddd6e7af9ddc398011ec4568e5528812b3e2
|
||||
size 2365
|
||||
3
apps/test-vectors/data/toy_params/lwe_ks.cbor
Normal file
3
apps/test-vectors/data/toy_params/lwe_ks.cbor
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d6da5baef0e787f6be56e218d8354e26904652602db964844156fdff08350ce6
|
||||
size 149
|
||||
3
apps/test-vectors/data/toy_params/lwe_ms.cbor
Normal file
3
apps/test-vectors/data/toy_params/lwe_ms.cbor
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c6df98676de04fe54b5ffc2eb30a82ebb706c9d7d5a4e0ed509700fec88761f7
|
||||
size 143
|
||||
3
apps/test-vectors/data/toy_params/lwe_prod.cbor
Normal file
3
apps/test-vectors/data/toy_params/lwe_prod.cbor
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:837b3bd3245d4d0534ed255fdef896fb4fa6998a258a14543dfdadd0bfc9b6dd
|
||||
size 2365
|
||||
3
apps/test-vectors/data/toy_params/lwe_sum.cbor
Normal file
3
apps/test-vectors/data/toy_params/lwe_sum.cbor
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:699580ca92b9c2f9e1f57fb1e312c9e8cb29714f7acdef9d2ba05f798546751f
|
||||
size 2365
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ee9fcf45f1379ca3a7d7bf2b0e7a1cc920ceb496c0217e8604b0b58d2831749e
|
||||
size 17
|
||||
3
apps/test-vectors/data/valid_params_128/bsk.cbor
Normal file
3
apps/test-vectors/data/valid_params_128/bsk.cbor
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e9afe7019acba5cda926f13e06df9930571611729d2f2e8ce41956e1f5e1db6f
|
||||
size 61415556
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6e54ab41056984595b077baff70236d934308cf5c0c33b4482fbfb129b3756c6
|
||||
size 36935
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:99a19c5d6d5f4fd81d9164d0ff96719ef362eabda256bce6a55cba6cb69e42bf
|
||||
size 36935
|
||||
3
apps/test-vectors/data/valid_params_128/ksk.cbor
Normal file
3
apps/test-vectors/data/valid_params_128/ksk.cbor
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e591ab9af1b6a0aede273f9a3abb65a4c387feb5fa06a6959e9314058ca0f7e5
|
||||
size 76861550
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b7a037b9eaa88d6385167579b93e26a0cb6976d9b8967416fd1173e113bda199
|
||||
size 2057
|
||||
3
apps/test-vectors/data/valid_params_128/lwe_a.cbor
Normal file
3
apps/test-vectors/data/valid_params_128/lwe_a.cbor
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e69d2d2c064fc8c0460b39191ca65338146990349954f5ec5ebd01d93610e7eb
|
||||
size 18493
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:656f0009c7834c5bcb61621e222047516054b9bc5d0593d474ab8f1c086b67a6
|
||||
size 18493
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e44ffa6e5a50a03d32721180a051c8ce62f1791d4853aeaebed0200c183a57cf
|
||||
size 18493
|
||||
3
apps/test-vectors/data/valid_params_128/lwe_b.cbor
Normal file
3
apps/test-vectors/data/valid_params_128/lwe_b.cbor
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c806533b325b1009db38be2f9bef5f3b2fad6b77b4c71f2855ccc9d3b4162e98
|
||||
size 18493
|
||||
3
apps/test-vectors/data/valid_params_128/lwe_ks.cbor
Normal file
3
apps/test-vectors/data/valid_params_128/lwe_ks.cbor
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:59dba26d457f96478eda130cab5301fce86f23c6a8807de42f2a1e78c4985ca7
|
||||
size 7558
|
||||
3
apps/test-vectors/data/valid_params_128/lwe_ms.cbor
Normal file
3
apps/test-vectors/data/valid_params_128/lwe_ms.cbor
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:aa44aea29efd6d9e4d35a21a625d9cba155672e3f7ed3eddee1e211e62ad146b
|
||||
size 7552
|
||||
3
apps/test-vectors/data/valid_params_128/lwe_prod.cbor
Normal file
3
apps/test-vectors/data/valid_params_128/lwe_prod.cbor
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e76c24b2a0c9a842ad13dda35473c2514f9e7d20983b5ea0759c4521a91626d9
|
||||
size 18493
|
||||
3
apps/test-vectors/data/valid_params_128/lwe_sum.cbor
Normal file
3
apps/test-vectors/data/valid_params_128/lwe_sum.cbor
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7f3c40a134623b44779a556212477fea26eaed22450f3b6faeb8721d63699972
|
||||
size 18493
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2c70d1d78cc3760733850a353ace2b9c4705e840141b75841739e90e51247e18
|
||||
size 842
|
||||
344
apps/test-vectors/src/main.rs
Normal file
344
apps/test-vectors/src/main.rs
Normal file
@@ -0,0 +1,344 @@
|
||||
use serde::Serialize;
|
||||
use std::fs::{File, create_dir_all, read_dir, remove_dir_all, remove_file};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use tfhe::core_crypto::commons::generators::DeterministicSeeder;
|
||||
use tfhe::core_crypto::commons::math::random::Seed;
|
||||
use tfhe::core_crypto::prelude::*;
|
||||
use tfhe_csprng::generators::SoftwareRandomGenerator;
|
||||
|
||||
// If you modify the content of these parameters, don't forget to also update `data/README.md`
|
||||
const RAND_SEED: u128 = 0x74666865;
|
||||
|
||||
const MSG_A: u64 = 4;
|
||||
const MSG_B: u64 = 3;
|
||||
|
||||
const VALID_LWE_DIMENSION: LweDimension = LweDimension(833);
|
||||
const VALID_GLWE_DIMENSION: GlweDimension = GlweDimension(1);
|
||||
const VALID_POLYNOMIAL_SIZE: PolynomialSize = PolynomialSize(2048);
|
||||
const VALID_GAUSSIAN_LWE_NOISE_STDDEV: f64 = 3.6158408373309336e-06;
|
||||
const VALID_GAUSSIAN_GLWE_NOISE_STDDEV: f64 = 2.845267479601915e-15;
|
||||
const VALID_PBS_DECOMPOSITION_BASE_LOG: DecompositionBaseLog = DecompositionBaseLog(23);
|
||||
const VALID_PBS_DECOMPOSITION_LEVEL_COUNT: DecompositionLevelCount = DecompositionLevelCount(1);
|
||||
const VALID_KS_DECOMPOSITION_BASE_LOG: DecompositionBaseLog = DecompositionBaseLog(3);
|
||||
const VALID_KS_DECOMPOSITION_LEVEL_COUNT: DecompositionLevelCount = DecompositionLevelCount(5);
|
||||
|
||||
const TOY_LWE_DIMENSION: LweDimension = LweDimension(10);
|
||||
const TOY_GLWE_DIMENSION: GlweDimension = GlweDimension(1);
|
||||
const TOY_POLYNOMIAL_SIZE: PolynomialSize = PolynomialSize(256);
|
||||
const TOY_GAUSSIAN_LWE_NOISE_STDDEV: f64 = 0.;
|
||||
const TOY_GAUSSIAN_GLWE_NOISE_STDDEV: f64 = 0.;
|
||||
const TOY_PBS_DECOMPOSITION_BASE_LOG: DecompositionBaseLog = DecompositionBaseLog(24);
|
||||
const TOY_PBS_DECOMPOSITION_LEVEL_COUNT: DecompositionLevelCount = DecompositionLevelCount(1);
|
||||
const TOY_KS_DECOMPOSITION_BASE_LOG: DecompositionBaseLog = DecompositionBaseLog(37);
|
||||
const TOY_KS_DECOMPOSITION_LEVEL_COUNT: DecompositionLevelCount = DecompositionLevelCount(1);
|
||||
|
||||
const ENCODING: Encoding = Encoding {
|
||||
ciphertext_modulus: CiphertextModulus::new_native(),
|
||||
msg_bits: 4,
|
||||
};
|
||||
|
||||
const SPEC_LUT: fn(u64) -> u64 = |x| (x * 2) & (1u64 << ENCODING.msg_bits);
|
||||
const ID_LUT: fn(u64) -> u64 = |x| x;
|
||||
|
||||
const DATA_DIR: &str = "./data";
|
||||
|
||||
struct Encoding {
|
||||
ciphertext_modulus: CiphertextModulus<u64>,
|
||||
msg_bits: usize,
|
||||
}
|
||||
|
||||
impl Encoding {
|
||||
fn log_delta(&self) -> usize {
|
||||
self.ciphertext_modulus.into_modulus_log().0 - self.msg_bits - 1
|
||||
}
|
||||
|
||||
const fn msg_modulus(&self) -> usize {
|
||||
1 << self.msg_bits
|
||||
}
|
||||
|
||||
fn encode(&self, msg: u64) -> Plaintext<u64> {
|
||||
Plaintext(msg << self.log_delta())
|
||||
}
|
||||
|
||||
fn decode(&self, plaintext: Plaintext<u64>) -> u64 {
|
||||
let decomposer = SignedDecomposer::new(
|
||||
DecompositionBaseLog(self.msg_bits + 1),
|
||||
DecompositionLevelCount(1),
|
||||
);
|
||||
let decoded = decomposer.decode_plaintext(plaintext);
|
||||
|
||||
decoded.0
|
||||
}
|
||||
|
||||
fn encode_lut(
|
||||
&self,
|
||||
glwe_dimension: GlweDimension,
|
||||
polynomial_size: PolynomialSize,
|
||||
f: impl Fn(u64) -> u64,
|
||||
) -> GlweCiphertext<Vec<u64>> {
|
||||
generate_programmable_bootstrap_glwe_lut(
|
||||
polynomial_size,
|
||||
glwe_dimension.to_glwe_size(),
|
||||
self.msg_modulus(),
|
||||
self.ciphertext_modulus,
|
||||
1 << self.log_delta(),
|
||||
f,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn modswitched_to_lwe(
|
||||
modswitched: &LazyStandardModulusSwitchedLweCiphertext<u64, usize, Vec<u64>>,
|
||||
) -> LweCiphertextOwned<usize> {
|
||||
let cont = modswitched
|
||||
.mask()
|
||||
.chain(std::iter::once(modswitched.body()))
|
||||
// The coefficients are converted to use the power of two encoding
|
||||
.map(|coeff| coeff << (usize::BITS as usize - modswitched.log_modulus().0))
|
||||
.collect();
|
||||
|
||||
LweCiphertext::from_container(
|
||||
cont,
|
||||
CiphertextModulus::new(1 << modswitched.log_modulus().0),
|
||||
)
|
||||
}
|
||||
|
||||
fn store_data<Data: Serialize, P: AsRef<Path>>(path: P, data: &Data, name: &str) {
|
||||
let mut path = path.as_ref().to_path_buf();
|
||||
path.push(format!("{}.cbor", name));
|
||||
|
||||
let mut file = File::create(path).unwrap();
|
||||
ciborium::ser::into_writer(data, &mut file).unwrap();
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn generate_test_vectors<P: AsRef<Path>>(
|
||||
path: P,
|
||||
lwe_dimension: LweDimension,
|
||||
glwe_dimension: GlweDimension,
|
||||
polynomial_size: PolynomialSize,
|
||||
lwe_noise_stddev: f64,
|
||||
glwe_noise_stddev: f64,
|
||||
pbs_decomp_base_log: DecompositionBaseLog,
|
||||
pbs_decomp_level_count: DecompositionLevelCount,
|
||||
ks_decomp_base_log: DecompositionBaseLog,
|
||||
ks_decomp_level_count: DecompositionLevelCount,
|
||||
encoding: Encoding,
|
||||
) {
|
||||
let path = path.as_ref();
|
||||
create_dir_all(path).unwrap();
|
||||
|
||||
let mut secret_generator =
|
||||
SecretRandomGenerator::<SoftwareRandomGenerator>::new(Seed(RAND_SEED));
|
||||
let mut encryption_generator = EncryptionRandomGenerator::<SoftwareRandomGenerator>::new(
|
||||
Seed(RAND_SEED),
|
||||
&mut DeterministicSeeder::<SoftwareRandomGenerator>::new(Seed(RAND_SEED)),
|
||||
);
|
||||
|
||||
let glwe_secret_key: GlweSecretKey<Vec<u64>> =
|
||||
GlweSecretKey::generate_new_binary(glwe_dimension, polynomial_size, &mut secret_generator);
|
||||
let large_lwe_secret_key = glwe_secret_key.as_lwe_secret_key();
|
||||
store_data(path, &large_lwe_secret_key, "large_lwe_secret_key");
|
||||
|
||||
let small_lwe_secret_key: LweSecretKey<Vec<u64>> =
|
||||
LweSecretKey::generate_new_binary(lwe_dimension, &mut secret_generator);
|
||||
store_data(path, &small_lwe_secret_key, "small_lwe_secret_key");
|
||||
|
||||
let lwe_noise_distribution = Gaussian::from_standard_dev(StandardDev(lwe_noise_stddev), 0.);
|
||||
let glwe_noise_distribution = Gaussian::from_standard_dev(StandardDev(glwe_noise_stddev), 0.);
|
||||
|
||||
let plaintext_a = encoding.encode(MSG_A);
|
||||
let lwe_a = allocate_and_encrypt_new_lwe_ciphertext(
|
||||
&large_lwe_secret_key,
|
||||
plaintext_a,
|
||||
glwe_noise_distribution,
|
||||
encoding.ciphertext_modulus,
|
||||
&mut encryption_generator,
|
||||
);
|
||||
store_data(path, &lwe_a, "lwe_a");
|
||||
|
||||
let plaintext_b = encoding.encode(MSG_B);
|
||||
let lwe_b = allocate_and_encrypt_new_lwe_ciphertext(
|
||||
&large_lwe_secret_key,
|
||||
plaintext_b,
|
||||
glwe_noise_distribution,
|
||||
encoding.ciphertext_modulus,
|
||||
&mut encryption_generator,
|
||||
);
|
||||
store_data(path, &lwe_b, "lwe_b");
|
||||
|
||||
let mut lwe_sum = LweCiphertext::new(
|
||||
0u64,
|
||||
glwe_dimension
|
||||
.to_equivalent_lwe_dimension(polynomial_size)
|
||||
.to_lwe_size(),
|
||||
encoding.ciphertext_modulus,
|
||||
);
|
||||
lwe_ciphertext_add(&mut lwe_sum, &lwe_a, &lwe_b);
|
||||
let decrypted_sum = decrypt_lwe_ciphertext(&large_lwe_secret_key, &lwe_sum);
|
||||
let res = encoding.decode(decrypted_sum);
|
||||
|
||||
assert_eq!(res, MSG_A + MSG_B);
|
||||
store_data(path, &lwe_sum, "lwe_sum");
|
||||
|
||||
let mut lwe_prod = LweCiphertext::new(
|
||||
0u64,
|
||||
glwe_dimension
|
||||
.to_equivalent_lwe_dimension(polynomial_size)
|
||||
.to_lwe_size(),
|
||||
encoding.ciphertext_modulus,
|
||||
);
|
||||
lwe_ciphertext_cleartext_mul(&mut lwe_prod, &lwe_a, Cleartext(MSG_B));
|
||||
let decrypted_prod = decrypt_lwe_ciphertext(&large_lwe_secret_key, &lwe_prod);
|
||||
let res = encoding.decode(decrypted_prod);
|
||||
|
||||
assert_eq!(res, MSG_A * MSG_B);
|
||||
store_data(path, &lwe_prod, "lwe_prod");
|
||||
|
||||
let ksk = allocate_and_generate_new_lwe_keyswitch_key(
|
||||
&large_lwe_secret_key,
|
||||
&small_lwe_secret_key,
|
||||
ks_decomp_base_log,
|
||||
ks_decomp_level_count,
|
||||
lwe_noise_distribution,
|
||||
encoding.ciphertext_modulus,
|
||||
&mut encryption_generator,
|
||||
);
|
||||
store_data(path, &ksk, "ksk");
|
||||
|
||||
let mut lwe_ks = LweCiphertext::new(
|
||||
0u64,
|
||||
lwe_dimension.to_lwe_size(),
|
||||
encoding.ciphertext_modulus,
|
||||
);
|
||||
keyswitch_lwe_ciphertext(&ksk, &lwe_a, &mut lwe_ks);
|
||||
|
||||
let decrypted_ks = decrypt_lwe_ciphertext(&small_lwe_secret_key, &lwe_ks);
|
||||
let res = encoding.decode(decrypted_ks);
|
||||
|
||||
assert_eq!(res, MSG_A);
|
||||
store_data(path, &lwe_ks, "lwe_ks");
|
||||
|
||||
let bsk = par_allocate_and_generate_new_lwe_bootstrap_key(
|
||||
&small_lwe_secret_key,
|
||||
&glwe_secret_key,
|
||||
pbs_decomp_base_log,
|
||||
pbs_decomp_level_count,
|
||||
glwe_noise_distribution,
|
||||
encoding.ciphertext_modulus,
|
||||
&mut encryption_generator,
|
||||
);
|
||||
store_data(path, &bsk, "bsk");
|
||||
|
||||
let mut fourier_bsk = FourierLweBootstrapKey::new(
|
||||
bsk.input_lwe_dimension(),
|
||||
bsk.glwe_size(),
|
||||
bsk.polynomial_size(),
|
||||
bsk.decomposition_base_log(),
|
||||
bsk.decomposition_level_count(),
|
||||
);
|
||||
par_convert_standard_lwe_bootstrap_key_to_fourier(&bsk, &mut fourier_bsk);
|
||||
|
||||
let lwe_in_ms =
|
||||
LweCiphertext::from_container(lwe_ks.as_ref().to_vec(), lwe_ks.ciphertext_modulus());
|
||||
let log_modulus = polynomial_size.to_blind_rotation_input_modulus_log();
|
||||
|
||||
let modswitched = lwe_ciphertext_modulus_switch(lwe_in_ms, log_modulus);
|
||||
let lwe_ms = modswitched_to_lwe(&modswitched);
|
||||
store_data(path, &lwe_ms, "lwe_ms");
|
||||
|
||||
let mut id_lut = encoding.encode_lut(glwe_dimension, polynomial_size, ID_LUT);
|
||||
|
||||
blind_rotate_assign(&modswitched, &mut id_lut, &fourier_bsk);
|
||||
store_data(path, &id_lut, "glwe_after_id_br");
|
||||
|
||||
let mut lwe_pbs_id = LweCiphertext::new(
|
||||
0u64,
|
||||
glwe_dimension
|
||||
.to_equivalent_lwe_dimension(polynomial_size)
|
||||
.to_lwe_size(),
|
||||
encoding.ciphertext_modulus,
|
||||
);
|
||||
|
||||
extract_lwe_sample_from_glwe_ciphertext(&id_lut, &mut lwe_pbs_id, MonomialDegree(0));
|
||||
|
||||
let decrypted_pbs_id = decrypt_lwe_ciphertext(&large_lwe_secret_key, &lwe_pbs_id);
|
||||
let res = encoding.decode(decrypted_pbs_id);
|
||||
|
||||
assert_eq!(res, MSG_A);
|
||||
store_data(path, &lwe_pbs_id, "lwe_after_id_pbs");
|
||||
|
||||
let mut spec_lut = encoding.encode_lut(glwe_dimension, polynomial_size, SPEC_LUT);
|
||||
|
||||
blind_rotate_assign(&modswitched, &mut spec_lut, &fourier_bsk);
|
||||
store_data(path, &spec_lut, "glwe_after_spec_br");
|
||||
|
||||
let mut lwe_pbs_spec = LweCiphertext::new(
|
||||
0u64,
|
||||
glwe_dimension
|
||||
.to_equivalent_lwe_dimension(polynomial_size)
|
||||
.to_lwe_size(),
|
||||
encoding.ciphertext_modulus,
|
||||
);
|
||||
|
||||
extract_lwe_sample_from_glwe_ciphertext(&spec_lut, &mut lwe_pbs_spec, MonomialDegree(0));
|
||||
|
||||
let decrypted_pbs_spec = decrypt_lwe_ciphertext(&large_lwe_secret_key, &lwe_pbs_spec);
|
||||
let res = encoding.decode(decrypted_pbs_spec);
|
||||
|
||||
assert_eq!(res, SPEC_LUT(MSG_A));
|
||||
store_data(path, &lwe_pbs_spec, "lwe_after_spec_pbs");
|
||||
}
|
||||
|
||||
fn rm_dir_except_readme<P: AsRef<Path>>(dir: P) {
|
||||
let dir = dir.as_ref();
|
||||
|
||||
for entry_result in read_dir(dir).unwrap() {
|
||||
let entry = entry_result.unwrap();
|
||||
let path = entry.path();
|
||||
|
||||
// Skip the README.md file at the root.
|
||||
if entry.file_name() == "README.md" {
|
||||
continue;
|
||||
}
|
||||
|
||||
if path.is_dir() {
|
||||
remove_dir_all(&path).unwrap();
|
||||
} else {
|
||||
remove_file(&path).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
rm_dir_except_readme(DATA_DIR);
|
||||
|
||||
generate_test_vectors(
|
||||
PathBuf::from(DATA_DIR).join("valid_params_128"),
|
||||
VALID_LWE_DIMENSION,
|
||||
VALID_GLWE_DIMENSION,
|
||||
VALID_POLYNOMIAL_SIZE,
|
||||
VALID_GAUSSIAN_LWE_NOISE_STDDEV,
|
||||
VALID_GAUSSIAN_GLWE_NOISE_STDDEV,
|
||||
VALID_PBS_DECOMPOSITION_BASE_LOG,
|
||||
VALID_PBS_DECOMPOSITION_LEVEL_COUNT,
|
||||
VALID_KS_DECOMPOSITION_BASE_LOG,
|
||||
VALID_KS_DECOMPOSITION_LEVEL_COUNT,
|
||||
ENCODING,
|
||||
);
|
||||
|
||||
generate_test_vectors(
|
||||
PathBuf::from(DATA_DIR).join("toy_params"),
|
||||
TOY_LWE_DIMENSION,
|
||||
TOY_GLWE_DIMENSION,
|
||||
TOY_POLYNOMIAL_SIZE,
|
||||
TOY_GAUSSIAN_LWE_NOISE_STDDEV,
|
||||
TOY_GAUSSIAN_GLWE_NOISE_STDDEV,
|
||||
TOY_PBS_DECOMPOSITION_BASE_LOG,
|
||||
TOY_PBS_DECOMPOSITION_LEVEL_COUNT,
|
||||
TOY_KS_DECOMPOSITION_BASE_LOG,
|
||||
TOY_KS_DECOMPOSITION_LEVEL_COUNT,
|
||||
ENCODING,
|
||||
);
|
||||
}
|
||||
@@ -3,14 +3,14 @@
|
||||
set -e
|
||||
|
||||
if [ $# -lt 1 ]; then
|
||||
echo "invalid arguments, usage:\n"
|
||||
echo "$0 <data_path>"
|
||||
exit 1
|
||||
echo "invalid arguments, usage:\n"
|
||||
echo "$0 <data_path>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! git lfs env 2>/dev/null >/dev/null; then
|
||||
echo "git lfs is not installed, please install it and try again"
|
||||
exit 1
|
||||
echo "git lfs is not installed, please install it and try again"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git lfs pull --include="$1/*" --exclude=""
|
||||
|
||||
59
scripts/test_vectors.sh
Executable file
59
scripts/test_vectors.sh
Executable file
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# This script generates or checks the SHA256 for the test vectors in `apps/test-vectors`
|
||||
|
||||
set -e
|
||||
|
||||
MODE="$1"
|
||||
TARGET_DIR="$2"
|
||||
CHECKSUM_FILE="checksums.sha256"
|
||||
|
||||
if [ -z "$MODE" ] || [ -z "$TARGET_DIR" ]; then
|
||||
echo "Usage: $0 <mode> <target dir>"
|
||||
echo "Modes:"
|
||||
echo " generate Generate the vectors and update the checksum file"
|
||||
echo " check Generate the vectors and compare their content with the checksum file"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d "$TARGET_DIR" ]; then
|
||||
echo "Error: Directory '$TARGET_DIR' not found."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
checksum () {
|
||||
find data -name '*.cbor' -type f -exec sha256sum {} + | sort
|
||||
}
|
||||
|
||||
# Generate the test vectors
|
||||
echo "Generating test-vectors in $TARGET_DIR..."
|
||||
cd $TARGET_DIR
|
||||
cargo run --release
|
||||
|
||||
if [ "$MODE" == "generate" ]; then
|
||||
echo "Generating hashes in $TARGET_DIR/$CHECKSUM_FILE..."
|
||||
checksum > "$CHECKSUM_FILE"
|
||||
echo "Done."
|
||||
|
||||
elif [ "$MODE" == "check" ]; then
|
||||
echo "Checking vectors integrity against $TARGET_DIR/$CHECKSUM_FILE..."
|
||||
|
||||
if [ ! -f "$CHECKSUM_FILE" ]; then
|
||||
echo "Error: Checksum file $CHECKSUM_FILE not found."
|
||||
echo "Run 'generate' mode first."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
diffs=$(comm -3 checksums.sha256 <(checksum))
|
||||
if [ -n "$diffs" ]; then
|
||||
echo "Error: Checksum file and generated vectors do not match."
|
||||
echo $diffs
|
||||
exit 1
|
||||
fi
|
||||
echo "Done."
|
||||
|
||||
else
|
||||
echo "Error: Invalid mode '$MODE'."
|
||||
echo "Mode must be 'generate' or 'check'."
|
||||
exit 1
|
||||
fi
|
||||
@@ -3,7 +3,7 @@ use std::collections::HashSet;
|
||||
use std::io::{Error, ErrorKind};
|
||||
|
||||
// TODO use .gitignore or git to resolve ignored files
|
||||
const DIR_TO_IGNORE: [&str; 2] = [".git", "target"];
|
||||
const DIR_TO_IGNORE: [&str; 3] = [".git", "target", "apps/test-vectors"];
|
||||
|
||||
const FILES_TO_IGNORE: [&str; 9] = [
|
||||
// This contains fragments of code that are unrelated to TFHE-rs
|
||||
|
||||
Reference in New Issue
Block a user