From 6d1656904340e126bc35185aac2d555bcd824dec Mon Sep 17 00:00:00 2001 From: Arthur Meyre Date: Tue, 27 Aug 2024 13:30:37 +0200 Subject: [PATCH 1/2] feat(tfhe): allow unpacking packed compact ciphertext lists in js/wasm --- tfhe/Cargo.toml | 2 +- tfhe/js_on_wasm_tests/test-hlapi-signed.js | 2 +- .../js_on_wasm_api/js_high_level_api/keys.rs | 19 +++++++ tfhe/web_wasm_parallel_tests/worker.js | 54 ++++++++++++++++--- 4 files changed, 67 insertions(+), 10 deletions(-) diff --git a/tfhe/Cargo.toml b/tfhe/Cargo.toml index 37e2200dc0..6d2e41152e 100644 --- a/tfhe/Cargo.toml +++ b/tfhe/Cargo.toml @@ -62,7 +62,7 @@ lazy_static = { version = "1.4.0", optional = true } serde = { version = "1.0", features = ["derive"] } rayon = { version = "1.5.0" } bincode = "1.3.3" -concrete-fft = { version = "0.5.0", features = ["serde", "fft128"] } +concrete-fft = { version = "0.5.1", features = ["serde", "fft128"] } concrete-ntt = { version = "0.2.0" } pulp = "0.18.22" tfhe-cuda-backend = { version = "0.4.0-alpha.0", path = "../backends/tfhe-cuda-backend", optional = true } diff --git a/tfhe/js_on_wasm_tests/test-hlapi-signed.js b/tfhe/js_on_wasm_tests/test-hlapi-signed.js index e4c296a51b..4fa8ebf69a 100644 --- a/tfhe/js_on_wasm_tests/test-hlapi-signed.js +++ b/tfhe/js_on_wasm_tests/test-hlapi-signed.js @@ -520,5 +520,5 @@ test('hlapi_compact_ciphertext_list_with_proof', (t) => { assert.deepStrictEqual(deserialized.get_kind_of(2), FheTypes.Bool); assert.deepStrictEqual(deserialized.get_kind_of(3), FheTypes.Uint256); - // We cannot verify packed ZK in wasm + // Verifying and expanding is too slow for single threaded node tests. }); diff --git a/tfhe/src/js_on_wasm_api/js_high_level_api/keys.rs b/tfhe/src/js_on_wasm_api/js_high_level_api/keys.rs index 8b1fc3bf3a..80e90ef03f 100644 --- a/tfhe/src/js_on_wasm_api/js_high_level_api/keys.rs +++ b/tfhe/src/js_on_wasm_api/js_high_level_api/keys.rs @@ -72,6 +72,25 @@ impl TfheCompressedServerKey { } } +#[wasm_bindgen] +pub struct TfheServerKey(pub(crate) hlapi::ServerKey); + +#[wasm_bindgen] +impl TfheServerKey { + #[wasm_bindgen] + pub fn new(client_key: &TfheClientKey) -> Result { + catch_panic_result(|| Ok(Self(hlapi::ServerKey::new(&client_key.0)))) + } +} + +#[wasm_bindgen] +pub fn set_server_key(server_key: &TfheServerKey) -> Result<(), JsError> { + catch_panic_result(|| { + crate::set_server_key(server_key.0.clone()); + Ok(()) + }) +} + #[wasm_bindgen] pub struct TfhePublicKey(pub(crate) hlapi::PublicKey); diff --git a/tfhe/web_wasm_parallel_tests/worker.js b/tfhe/web_wasm_parallel_tests/worker.js index cc2b9439dc..b4ccc9add2 100644 --- a/tfhe/web_wasm_parallel_tests/worker.js +++ b/tfhe/web_wasm_parallel_tests/worker.js @@ -2,10 +2,12 @@ import * as Comlink from "comlink"; import init, { initThreadPool, init_panic_hook, + set_server_key, ShortintParametersName, ShortintParameters, TfheClientKey, TfhePublicKey, + TfheServerKey, TfheCompressedPublicKey, TfheCompressedServerKey, TfheCompressedCompactPublicKey, @@ -254,8 +256,11 @@ async function compactPublicKeyWithCastingTest256Bit() { .build(); let clientKey = TfheClientKey.generate(config); + let serverKey = TfheServerKey.new(clientKey); let publicKey = TfheCompactPublicKey.new(clientKey); + set_server_key(serverKey); + let clear_u2 = 3; let clear_i32 = -3284; let clear_bool = true; @@ -271,7 +276,7 @@ async function compactPublicKeyWithCastingTest256Bit() { console.log("Numb bits in compact list: ", num_bits_encrypted); console.time("CompactCiphertextList Encrypt"); - let list = builder.build(); + let list = builder.build_packed(); console.timeEnd("CompactCiphertextList Encrypt"); let serialized = list.safe_serialize(BigInt(10000000)); @@ -281,7 +286,15 @@ async function compactPublicKeyWithCastingTest256Bit() { BigInt(10000000), ); - // Cannot expand + let expander = deserialized.expand(); + + assert_eq(expander.get_uint2(0).decrypt(clientKey), clear_u2); + + assert_eq(expander.get_int32(1).decrypt(clientKey), clear_i32); + + assert_eq(expander.get_bool(2).decrypt(clientKey), clear_bool); + + assert_eq(expander.get_uint256(3).decrypt(clientKey), clear_u256); } async function compressedCompactPublicKeyWithCastingTest256Bit() { @@ -298,9 +311,12 @@ async function compressedCompactPublicKeyWithCastingTest256Bit() { .build(); let clientKey = TfheClientKey.generate(config); + let serverKey = TfheServerKey.new(clientKey); let compressedPublicKey = TfheCompressedCompactPublicKey.new(clientKey); let publicKey = compressedPublicKey.decompress(); + set_server_key(serverKey); + let clear_u2 = 3; let clear_i32 = -3284; let clear_bool = true; @@ -316,7 +332,7 @@ async function compressedCompactPublicKeyWithCastingTest256Bit() { console.log("Numb bits in compact list: ", num_bits_encrypted); console.time("CompactCiphertextList Encrypt"); - let list = builder.build(); + let list = builder.build_packed(); console.timeEnd("CompactCiphertextList Encrypt"); let serialized = list.safe_serialize(BigInt(10000000)); @@ -326,7 +342,15 @@ async function compressedCompactPublicKeyWithCastingTest256Bit() { BigInt(10000000), ); - // Cannot expand + let expander = deserialized.expand(); + + assert_eq(expander.get_uint2(0).decrypt(clientKey), clear_u2); + + assert_eq(expander.get_int32(1).decrypt(clientKey), clear_i32); + + assert_eq(expander.get_bool(2).decrypt(clientKey), clear_bool); + + assert_eq(expander.get_uint256(3).decrypt(clientKey), clear_u256); } async function compactPublicKeyZeroKnowledge() { @@ -343,8 +367,11 @@ async function compactPublicKeyZeroKnowledge() { .build(); let clientKey = TfheClientKey.generate(config); + let serverKey = TfheServerKey.new(clientKey); let publicKey = TfheCompactPublicKey.new(clientKey); + set_server_key(serverKey); + console.log("Start CRS generation"); console.time("CRS generation"); let crs = CompactPkeCrs.from_config(config, 4 * 64); @@ -368,10 +395,13 @@ async function compactPublicKeyZeroKnowledge() { " ms", ); - let bytes = list.serialize(); - console.log("CompactCiphertextList size:", bytes.length); + let serialized = list.serialize(); + console.log("CompactCiphertextList size:", serialized.length); + let deserialized = ProvenCompactCiphertextList.deserialize(serialized); - // We cannot expand a packed list in WASM + let expander = deserialized.verify_and_expand(public_params, publicKey); + + assert_eq(expander.get_uint64(0).decrypt(clientKey), input); } { @@ -397,7 +427,15 @@ async function compactPublicKeyZeroKnowledge() { " ms", ); - // We cannot expand a packed list in WASM + let expander = encrypted.verify_and_expand(public_params, publicKey); + + assert_eq(expander.get_uint64(0).decrypt(clientKey), inputs[0]); + + assert_eq(expander.get_uint64(1).decrypt(clientKey), inputs[1]); + + assert_eq(expander.get_uint64(2).decrypt(clientKey), inputs[2]); + + assert_eq(expander.get_uint64(3).decrypt(clientKey), inputs[3]); } } From ea50687195a20f2a661c37da3dab02ba4b331d72 Mon Sep 17 00:00:00 2001 From: Arthur Meyre Date: Fri, 6 Sep 2024 12:05:38 +0200 Subject: [PATCH 2/2] chore(js): increase timeout for ZK test as it can be surpassed - this seemed to cause the test runner to hang forever - also add a timeout in the GitHub workflow, to avoid having the test runner wait forever (or in this case 6 hours because of default timeout) --- .github/workflows/aws_tfhe_wasm_tests.yml | 1 + tfhe/web_wasm_parallel_tests/test/compact-public-key.test.js | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/aws_tfhe_wasm_tests.yml b/.github/workflows/aws_tfhe_wasm_tests.yml index d55633b5d4..9053a9843a 100644 --- a/.github/workflows/aws_tfhe_wasm_tests.yml +++ b/.github/workflows/aws_tfhe_wasm_tests.yml @@ -71,6 +71,7 @@ jobs: make test_nodejs_wasm_api_in_docker - name: Run parallel wasm tests + timeout-minutes: 60 run: | make test_web_js_api_parallel_ci diff --git a/tfhe/web_wasm_parallel_tests/test/compact-public-key.test.js b/tfhe/web_wasm_parallel_tests/test/compact-public-key.test.js index ff7fdce606..d7f6d16f39 100644 --- a/tfhe/web_wasm_parallel_tests/test/compact-public-key.test.js +++ b/tfhe/web_wasm_parallel_tests/test/compact-public-key.test.js @@ -23,8 +23,8 @@ it( async () => { await runTestAttachedToButton("compactPublicKeyZeroKnowledge"); }, - 1200 * 1000, -); // 20 minutes timeout + 3600 * 1000, +); // 60 minutes timeout it( "Compact Public Key Bench 64 Bit With ZeroKnowledge",