From ba6dbd5f7ca4934ce2c78e8feb70b10c9f7242f7 Mon Sep 17 00:00:00 2001 From: Nicolas Sarlin Date: Tue, 25 Jun 2024 15:29:45 +0200 Subject: [PATCH 1/6] feat(zk): zk perf improvements co-authored by: sarah el kazdadi --- tfhe-zk-pok/Cargo.toml | 6 +- tfhe-zk-pok/src/curve_api/bls12_446.rs | 277 ++++++++++++++++++------- 2 files changed, 205 insertions(+), 78 deletions(-) diff --git a/tfhe-zk-pok/Cargo.toml b/tfhe-zk-pok/Cargo.toml index 9d1a65bf98..e351141361 100644 --- a/tfhe-zk-pok/Cargo.toml +++ b/tfhe-zk-pok/Cargo.toml @@ -13,9 +13,9 @@ description = "tfhe-zk-pok: An implementation of zero-knowledge proofs of encryp [dependencies] ark-bls12-381 = { package = "tfhe-ark-bls12-381", version = "0.4.0" } -ark-ec = { package = "tfhe-ark-ec", version = "0.4.2" } -ark-ff = { package = "tfhe-ark-ff", version = "0.4.3" } -ark-poly = { package = "tfhe-ark-poly", version = "0.4.2" } +ark-ec = { package = "tfhe-ark-ec", version = "0.4.2", features = ["parallel"] } +ark-ff = { package = "tfhe-ark-ff", version = "0.4.3", features = ["parallel"] } +ark-poly = { package = "tfhe-ark-poly", version = "0.4.2", features = ["parallel"] } ark-serialize = { version = "0.4.2" } rand = "0.8.5" rayon = "1.8.0" diff --git a/tfhe-zk-pok/src/curve_api/bls12_446.rs b/tfhe-zk-pok/src/curve_api/bls12_446.rs index 1ea2aa572c..f2450389bd 100644 --- a/tfhe-zk-pok/src/curve_api/bls12_446.rs +++ b/tfhe-zk-pok/src/curve_api/bls12_446.rs @@ -242,6 +242,96 @@ mod g2 { .unwrap(), } } + + // m is an intermediate variable that's used in both the curve point addition and pairing + // functions. we cache it since it requires a Zp division + // https://hackmd.io/@tazAymRSQCGXTUKkbh1BAg/Sk27liTW9#Math-Formula-for-Point-Addition + pub(crate) fn compute_m(self, other: G2Affine) -> Option { + let zero = crate::curve_446::Fq2::ZERO; + + // in the context of elliptic curves, the point at infinity is the zero element of the + // group + if self.inner.infinity || other.inner.infinity { + return None; + } + + if self == other { + let x = self.inner.x; + let y = self.inner.y; + if y == zero { + None + } else { + let xx = x.square(); + Some((xx.double() + xx) / y.double()) + } + } else { + let x1 = self.inner.x; + let y1 = self.inner.y; + let x2 = other.inner.x; + let y2 = other.inner.y; + + let x_delta = x2 - x1; + let y_delta = y2 - y1; + + if x_delta == zero { + None + } else { + Some(y_delta / x_delta) + } + } + } + + pub(crate) fn double(self, m: Option) -> Self { + // in the context of elliptic curves, the point at infinity is the zero element of the + // group + if self.inner.infinity { + return self; + } + + let mut result = self; + + let x = self.inner.x; + let y = self.inner.y; + + if let Some(m) = m { + let x3 = m.square() - x.double(); + let y3 = m * (x - x3) - y; + + (result.inner.x, result.inner.y) = (x3, y3); + } else { + result.inner.infinity = true; + } + + result + } + + pub(crate) fn add_unequal(self, other: G2Affine, m: Option) -> Self { + // in the context of elliptic curves, the point at infinity is the zero element of the + // group + if self.inner.infinity { + return other; + } + if other.inner.infinity { + return self; + } + + let mut result = self; + + let x1 = self.inner.x; + let y1 = self.inner.y; + let x2 = other.inner.x; + + if let Some(m) = m { + let x3 = m.square() - x1 - x2; + let y3 = m * (x1 - x3) - y1; + + (result.inner.x, result.inner.y) = (x3, y3); + } else { + result.inner.infinity = true; + } + + result + } } #[derive( @@ -373,9 +463,9 @@ mod g2 { } pub fn double(self) -> Self { - Self { - inner: self.inner.double(), - } + let mut this = self; + this.inner.double_in_place(); + this } } @@ -431,51 +521,79 @@ mod g2 { } mod gt { + use crate::curve_446::{Fq, Fq12, Fq2}; + use super::*; - use ark_ec::bls12::Bls12Config; use ark_ec::pairing::{MillerLoopOutput, Pairing}; - use ark_ff::{CubicExtField, Fp12, Fp2, QuadExtField}; + use ark_ff::{CubicExtField, QuadExtField}; type Bls = crate::curve_446::Bls12_446; - type Config = crate::curve_446::Config; - const ONE: Fp2<::Fp2Config> = QuadExtField { - c0: MontFp!("1"), - c1: MontFp!("0"), - }; - const ZERO: Fp2<::Fp2Config> = QuadExtField { + const ZERO: Fq2 = QuadExtField { c0: MontFp!("0"), c1: MontFp!("0"), }; - const U1: Fp12<::Fp12Config> = QuadExtField { - c0: CubicExtField { - c0: ZERO, - c1: ZERO, - c2: ZERO, - }, - c1: CubicExtField { - c0: ONE, - c1: ZERO, - c2: ZERO, - }, + // computed by copying the result from + // let two: Fq = MontFp!("2"); println!("{}", two.inverse().unwrap()), which we can't compute in + // a const context; + const TWO_INV: Fq = { + MontFp!("86412351771428577990035638289747981121746346761394949218917418178192828331138736448451251370148591845087981000773214233672031082665302") }; - const U3: Fp12<::Fp12Config> = QuadExtField { - c0: CubicExtField { - c0: ZERO, - c1: ZERO, - c2: ZERO, - }, - c1: CubicExtField { - c0: ZERO, - c1: ONE, - c2: ZERO, - }, + const TWO_INV_MINUS_1: Fq = { + MontFp!("86412351771428577990035638289747981121746346761394949218917418178192828331138736448451251370148591845087981000773214233672031082665301") }; - const fn fp2_to_fp12( - x: Fp2<::Fp2Config>, - ) -> Fp12<::Fp12Config> { + // the only non zero value in inv(U1) and inv(U3), which come from Olivier's equations. + const C: Fq2 = QuadExtField { + c0: TWO_INV, + c1: TWO_INV_MINUS_1, + }; + + fn fp2_mul_c(x: Fq2) -> Fq2 { + let x0_c0 = x.c0 * C.c0; + let x1_c0 = x.c1 * C.c0; + + let x0_c1 = x0_c0 - x.c0; + let x1_c1 = x1_c0 - x.c1; + + QuadExtField { + c0: x0_c0 - x1_c1, + c1: x0_c1 + x1_c0, + } + } + + fn fp2_mul_u1_inv(x: Fq2) -> Fq12 { + QuadExtField { + c0: CubicExtField { + c0: ZERO, + c1: ZERO, + c2: ZERO, + }, + c1: CubicExtField { + c0: ZERO, + c1: ZERO, + c2: fp2_mul_c(x), + }, + } + } + + fn fp2_mul_u3_inv(x: Fq2) -> Fq12 { + QuadExtField { + c0: CubicExtField { + c0: ZERO, + c1: ZERO, + c2: ZERO, + }, + c1: CubicExtField { + c0: ZERO, + c1: fp2_mul_c(x), + c2: ZERO, + }, + } + } + + const fn fp2_to_fp12(x: Fq2) -> Fq12 { QuadExtField { c0: CubicExtField { c0: x, @@ -490,52 +608,59 @@ mod gt { } } - const fn fp_to_fp12( - x: ::Fp, - ) -> Fp12<::Fp12Config> { - fp2_to_fp12(QuadExtField { + const fn fp_to_fp2(x: Fq) -> Fq2 { + QuadExtField { c0: x, c1: MontFp!("0"), - }) + } } - fn ate_tangent_ev(qt: G2, evpt: G1) -> Fp12<::Fp12Config> { - let qt = qt.inner.into_affine(); - let evpt = evpt.inner.into_affine(); + const fn fp_to_fp12(x: Fq) -> Fq12 { + fp2_to_fp12(fp_to_fp2(x)) + } + + fn ate_tangent_ev(qt: G2Affine, evpt: G1Affine, m: Fq2) -> Fq12 { + let qt = qt.inner; + let evpt = evpt.inner; let (xt, yt) = (qt.x, qt.y); let (xe, ye) = (evpt.x, evpt.y); - let xt = fp2_to_fp12(xt); - let yt = fp2_to_fp12(yt); - let xe = fp_to_fp12(xe); - let ye = fp_to_fp12(ye); + let l = m; + let mut l_xe = l; + l_xe.c0 *= xe; + l_xe.c1 *= xe; + + let mut r0 = fp_to_fp12(ye); + let r1 = fp2_mul_u1_inv(l_xe); + let r2 = fp2_mul_u3_inv(l * xt - yt); - let three = fp_to_fp12(MontFp!("3")); - let two = fp_to_fp12(MontFp!("2")); + r0.c1.c1 = r2.c1.c1; + r0.c1.c2 = -r1.c1.c2; - let l = three * xt.square() / (two * yt); - ye - (l * xe) / U1 + (l * xt - yt) / U3 + r0 } - fn ate_line_ev(q1: G2, q2: G2, evpt: G1) -> Fp12<::Fp12Config> { - let q1 = q1.inner.into_affine(); - let q2 = q2.inner.into_affine(); - let evpt = evpt.inner.into_affine(); + fn ate_line_ev(q1: G2Affine, evpt: G1Affine, m: Fq2) -> Fq12 { + let q1 = q1.inner; + let evpt = evpt.inner; let (x1, y1) = (q1.x, q1.y); - let (x2, y2) = (q2.x, q2.y); let (xe, ye) = (evpt.x, evpt.y); - let x1 = fp2_to_fp12(x1); - let y1 = fp2_to_fp12(y1); - let x2 = fp2_to_fp12(x2); - let y2 = fp2_to_fp12(y2); - let xe = fp_to_fp12(xe); - let ye = fp_to_fp12(ye); + let l = m; + let mut l_xe = l; + l_xe.c0 *= xe; + l_xe.c1 *= xe; - let l = (y2 - y1) / (x2 - x1); - ye - (l * xe) / U1 + (l * x1 - y1) / U3 + let mut r0 = fp_to_fp12(ye); + let r1 = fp2_mul_u1_inv(l * fp_to_fp2(xe)); + let r2 = fp2_mul_u3_inv(l * x1 - y1); + + r0.c1.c1 = r2.c1.c1; + r0.c1.c2 = -r1.c1.c2; + + r0 } #[allow(clippy::needless_range_loop)] @@ -544,22 +669,24 @@ mod gt { let t_bits = b"110000000001000001000000100000000000000000000000000000000100000000000000001"; let mut fk = fp_to_fp12(MontFp!("1")); + let p = p.normalize(); + let q = q.normalize(); + let mut qk = q; for k in 1..t_log2 { - let lkk = ate_tangent_ev(qk, p); - qk = qk + qk; + let m = qk.compute_m(qk).unwrap(); + let lkk = ate_tangent_ev(qk, p, m); + qk = qk.double(Some(m)); fk = fk.square() * lkk; if t_bits[k] == b'1' { - assert_ne!(q, qk); - let lkp1 = if q != -qk { - ate_line_ev(q, qk, p) - } else { - fp_to_fp12(MontFp!("1")) - }; - qk += q; - fk *= lkp1; + let m = q.compute_m(qk); + let new_qk = q.add_unequal(qk, m); + if !new_qk.inner.infinity { + fk *= ate_line_ev(q, p, m.unwrap()); + } + qk = new_qk; } } let mlo = MillerLoopOutput(fk); From 5aa9cabf4e49c19040666c5f2874ca93a5ca698d Mon Sep 17 00:00:00 2001 From: Arthur Meyre Date: Wed, 26 Jun 2024 13:50:31 +0200 Subject: [PATCH 2/6] chore(zk): bump version to 0.2.1 for perf patch release --- tfhe-zk-pok/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tfhe-zk-pok/Cargo.toml b/tfhe-zk-pok/Cargo.toml index e351141361..08656fe85e 100644 --- a/tfhe-zk-pok/Cargo.toml +++ b/tfhe-zk-pok/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tfhe-zk-pok" -version = "0.2.0" +version = "0.2.1" edition = "2021" keywords = ["zero", "knowledge", "proof", "vector-commitments"] homepage = "https://zama.ai/" From 641cb9f0126f0a3263282e9f894db0bde33ffe8a Mon Sep 17 00:00:00 2001 From: Nicolas Sarlin Date: Wed, 30 Oct 2024 10:49:17 +0100 Subject: [PATCH 3/6] fix(zk): proof compatiblity between 32/64b platforms --- tfhe-zk-pok/src/proofs/pke.rs | 4 ++-- tfhe-zk-pok/src/proofs/range.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tfhe-zk-pok/src/proofs/pke.rs b/tfhe-zk-pok/src/proofs/pke.rs index c2f3a3ddd7..db11b7c312 100644 --- a/tfhe-zk-pok/src/proofs/pke.rs +++ b/tfhe-zk-pok/src/proofs/pke.rs @@ -332,7 +332,7 @@ pub fn prove( let x_bytes = &*[ q.to_le_bytes().as_slice(), - d.to_le_bytes().as_slice(), + (d as u64).to_le_bytes().as_slice(), b_i.to_le_bytes().as_slice(), t.to_le_bytes().as_slice(), &*a.iter().flat_map(|&x| x.to_le_bytes()).collect::>(), @@ -745,7 +745,7 @@ pub fn verify( let x_bytes = &*[ q.to_le_bytes().as_slice(), - d.to_le_bytes().as_slice(), + (d as u64).to_le_bytes().as_slice(), b_i.to_le_bytes().as_slice(), t.to_le_bytes().as_slice(), &*a.iter().flat_map(|&x| x.to_le_bytes()).collect::>(), diff --git a/tfhe-zk-pok/src/proofs/range.rs b/tfhe-zk-pok/src/proofs/range.rs index 565cf41a42..c51aba2bf2 100644 --- a/tfhe-zk-pok/src/proofs/range.rs +++ b/tfhe-zk-pok/src/proofs/range.rs @@ -221,7 +221,7 @@ pub fn prove( core::slice::from_mut(s), &[ hash_s, - &i.to_le_bytes(), + &(i as u64).to_le_bytes(), v_hat.to_bytes().as_ref(), c_hat.to_bytes().as_ref(), c_y.to_bytes().as_ref(), @@ -328,7 +328,7 @@ pub fn verify( core::slice::from_mut(s), &[ hash_s, - &i.to_le_bytes(), + &(i as u64).to_le_bytes(), v_hat.to_bytes().as_ref(), c_hat.to_bytes().as_ref(), c_y.to_bytes().as_ref(), From 7aab4f1b9da8a3a3fd7b1a7d225f030597f621ae Mon Sep 17 00:00:00 2001 From: Arthur Meyre Date: Thu, 10 Oct 2024 13:51:49 +0200 Subject: [PATCH 4/6] chore(ci): the original build fix was not conservative enough - this makes sure we honour the original requirement while making sure we don't pull the broken dep in --- tfhe/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tfhe/Cargo.toml b/tfhe/Cargo.toml index 2878bda5ba..6ad735630d 100644 --- a/tfhe/Cargo.toml +++ b/tfhe/Cargo.toml @@ -80,7 +80,7 @@ tfhe-zk-pok = { version = "0.2.0", path = "../tfhe-zk-pok", optional = true } tfhe-versionable = { version = "0.2.0", path = "../utils/tfhe-versionable" } # wasm deps -wasm-bindgen = { version = "0.2.86", features = [ +wasm-bindgen = { version = ">=0.2.86,<0.2.94", features = [ "serde-serialize", ], optional = true } wasm-bindgen-rayon = { version = "1.0", optional = true } From d9c943afd4d343ef23c05369b1495cfefa34aa56 Mon Sep 17 00:00:00 2001 From: Nicolas Sarlin Date: Wed, 30 Oct 2024 10:53:51 +0100 Subject: [PATCH 5/6] chore(zk): bump version to 0.2.2 --- tfhe-zk-pok/Cargo.toml | 2 +- tfhe/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tfhe-zk-pok/Cargo.toml b/tfhe-zk-pok/Cargo.toml index 08656fe85e..784dfe645c 100644 --- a/tfhe-zk-pok/Cargo.toml +++ b/tfhe-zk-pok/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tfhe-zk-pok" -version = "0.2.1" +version = "0.2.2" edition = "2021" keywords = ["zero", "knowledge", "proof", "vector-commitments"] homepage = "https://zama.ai/" diff --git a/tfhe/Cargo.toml b/tfhe/Cargo.toml index 6ad735630d..4a3b2cf5b0 100644 --- a/tfhe/Cargo.toml +++ b/tfhe/Cargo.toml @@ -76,7 +76,7 @@ sha3 = { version = "0.10", optional = true } # While we wait for repeat_n in rust standard library itertools = "0.11.0" rand_core = { version = "0.6.4", features = ["std"] } -tfhe-zk-pok = { version = "0.2.0", path = "../tfhe-zk-pok", optional = true } +tfhe-zk-pok = { version = "0.2.2", path = "../tfhe-zk-pok", optional = true } tfhe-versionable = { version = "0.2.0", path = "../utils/tfhe-versionable" } # wasm deps From 44bd45f9a4cb60b0cc5783ad8810c6a7bef77680 Mon Sep 17 00:00:00 2001 From: Nicolas Sarlin Date: Wed, 30 Oct 2024 14:00:20 +0100 Subject: [PATCH 6/6] chore(tfhe): prepare release 0.7.5 --- tfhe/Cargo.toml | 2 +- tfhe/docs/fundamentals/serialization.md | 2 +- tfhe/docs/getting_started/installation.md | 4 ++-- tfhe/docs/getting_started/quick_start.md | 2 +- tfhe/docs/guides/data_versioning.md | 2 +- tfhe/docs/guides/run_on_gpu.md | 4 ++-- tfhe/docs/references/core-crypto-api/tutorial.md | 8 ++++---- tfhe/docs/tutorials/ascii_fhe_string.md | 2 +- tfhe/docs/tutorials/parity_bit.md | 2 +- 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/tfhe/Cargo.toml b/tfhe/Cargo.toml index 4a3b2cf5b0..3f45c7bbfb 100644 --- a/tfhe/Cargo.toml +++ b/tfhe/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tfhe" -version = "0.7.4" +version = "0.7.5" edition = "2021" readme = "../README.md" keywords = ["fully", "homomorphic", "encryption", "fhe", "cryptography"] diff --git a/tfhe/docs/fundamentals/serialization.md b/tfhe/docs/fundamentals/serialization.md index bb5a68657b..ecc99e4cd0 100644 --- a/tfhe/docs/fundamentals/serialization.md +++ b/tfhe/docs/fundamentals/serialization.md @@ -15,7 +15,7 @@ Here is a full example: [dependencies] # ... -tfhe = { version = "0.7.4", features = ["integer","x86_64-unix"]} +tfhe = { version = "0.7.5", features = ["integer","x86_64-unix"]} bincode = "1.3.3" ``` diff --git a/tfhe/docs/getting_started/installation.md b/tfhe/docs/getting_started/installation.md index 4990ec2e59..544795cc87 100644 --- a/tfhe/docs/getting_started/installation.md +++ b/tfhe/docs/getting_started/installation.md @@ -9,13 +9,13 @@ First, add **TFHE-rs** as a dependency in your `Cargo.toml`. **For `x86_64` machine running a Unix-like OS:** ```toml -tfhe = { version = "0.7.4", features = [ "boolean", "shortint", "integer", "x86_64-unix" ] } +tfhe = { version = "0.7.5", features = [ "boolean", "shortint", "integer", "x86_64-unix" ] } ``` **For `ARM` machine running a Unix-like OS:** ```toml -tfhe = { version = "0.7.4", features = [ "boolean", "shortint", "integer", "aarch64-unix" ] } +tfhe = { version = "0.7.5", features = [ "boolean", "shortint", "integer", "aarch64-unix" ] } ``` **For `x86_64` machines with the** [**`rdseed instruction`**](https://en.wikipedia.org/wiki/RDRAND) **running Windows:** diff --git a/tfhe/docs/getting_started/quick_start.md b/tfhe/docs/getting_started/quick_start.md index 48ef007424..80d33f3df1 100644 --- a/tfhe/docs/getting_started/quick_start.md +++ b/tfhe/docs/getting_started/quick_start.md @@ -47,7 +47,7 @@ fn main() { The default configuration for x86 Unix machines is as follows: ```toml -tfhe = { version = "0.7.4", features = ["integer", "x86_64-unix"]} +tfhe = { version = "0.7.5", features = ["integer", "x86_64-unix"]} ``` Refer to the [installation documentation](installation.md) for configuration options of different platforms.Learn more about homomorphic types features in the [configuration documentation.](../guides/rust\_configuration.md) diff --git a/tfhe/docs/guides/data_versioning.md b/tfhe/docs/guides/data_versioning.md index feb897eb4b..6a9ac5c044 100644 --- a/tfhe/docs/guides/data_versioning.md +++ b/tfhe/docs/guides/data_versioning.md @@ -16,7 +16,7 @@ You can load serialized data with the `unversionize` function, even in newer ver [dependencies] # ... -tfhe = { version = "0.7.4", features = ["integer","x86_64-unix"]} +tfhe = { version = "0.7.5", features = ["integer","x86_64-unix"]} tfhe-versionable = "0.2.0" bincode = "1.3.3" ``` diff --git a/tfhe/docs/guides/run_on_gpu.md b/tfhe/docs/guides/run_on_gpu.md index 198ae88fad..177bcf4fe1 100644 --- a/tfhe/docs/guides/run_on_gpu.md +++ b/tfhe/docs/guides/run_on_gpu.md @@ -19,13 +19,13 @@ To use the **TFHE-rs** GPU backend in your project, add the following dependency If you are using an `x86` machine: ```toml -tfhe = { version = "0.7.4", features = [ "boolean", "shortint", "integer", "x86_64-unix", "gpu" ] } +tfhe = { version = "0.7.5", features = [ "boolean", "shortint", "integer", "x86_64-unix", "gpu" ] } ``` If you are using an `ARM` machine: ```toml -tfhe = { version = "0.7.4", features = [ "boolean", "shortint", "integer", "aarch64-unix", "gpu" ] } +tfhe = { version = "0.7.5", features = [ "boolean", "shortint", "integer", "aarch64-unix", "gpu" ] } ``` {% hint style="success" %} diff --git a/tfhe/docs/references/core-crypto-api/tutorial.md b/tfhe/docs/references/core-crypto-api/tutorial.md index 7e084ffbda..0551a20f08 100644 --- a/tfhe/docs/references/core-crypto-api/tutorial.md +++ b/tfhe/docs/references/core-crypto-api/tutorial.md @@ -9,7 +9,7 @@ Welcome to this tutorial about `TFHE-rs` `core_crypto` module. To use `TFHE-rs`, it first has to be added as a dependency in the `Cargo.toml`: ```toml -tfhe = { version = "0.7.4", features = [ "x86_64-unix" ] } +tfhe = { version = "0.7.5", features = [ "x86_64-unix" ] } ``` This enables the `x86_64-unix` feature to have efficient implementations of various algorithms for `x86_64` CPUs on a Unix-like system. The 'unix' suffix indicates that the `UnixSeeder`, which uses `/dev/random` to generate random numbers, is activated as a fallback if no hardware number generator is available (like `rdseed` on `x86_64` or if the [`Randomization Services`](https://developer.apple.com/documentation/security/1399291-secrandomcopybytes?language=objc) on Apple platforms are not available). To avoid having the `UnixSeeder` as a potential fallback or to run on non-Unix systems (e.g., Windows), the `x86_64` feature is sufficient. @@ -19,19 +19,19 @@ For Apple Silicon, the `aarch64-unix` or `aarch64` feature should be enabled. `a In short: For `x86_64`-based machines running Unix-like OSes: ```toml -tfhe = { version = "0.7.4", features = ["x86_64-unix"] } +tfhe = { version = "0.7.5", features = ["x86_64-unix"] } ``` For Apple Silicon or aarch64-based machines running Unix-like OSes: ```toml -tfhe = { version = "0.7.4", features = ["aarch64-unix"] } +tfhe = { version = "0.7.5", features = ["aarch64-unix"] } ``` For `x86_64`-based machines with the [`rdseed instruction`](https://en.wikipedia.org/wiki/RDRAND) running Windows: ```toml -tfhe = { version = "0.7.4", features = ["x86_64"] } +tfhe = { version = "0.7.5", features = ["x86_64"] } ``` ### Commented code to double a 2-bit message in a leveled fashion and using a PBS with the `core_crypto` module. diff --git a/tfhe/docs/tutorials/ascii_fhe_string.md b/tfhe/docs/tutorials/ascii_fhe_string.md index f0d2fd4aa2..3f416d12f8 100644 --- a/tfhe/docs/tutorials/ascii_fhe_string.md +++ b/tfhe/docs/tutorials/ascii_fhe_string.md @@ -25,7 +25,7 @@ To use the `FheUint8` type, enable the `integer` feature: [dependencies] # Default configuration for x86 Unix machines: -tfhe = { version = "0.7.4", features = ["integer", "x86_64-unix"]} +tfhe = { version = "0.7.5", features = ["integer", "x86_64-unix"]} ``` Refer to the [installation guide](../getting\_started/installation.md) for other configurations. diff --git a/tfhe/docs/tutorials/parity_bit.md b/tfhe/docs/tutorials/parity_bit.md index dfc2ff289f..c602447874 100644 --- a/tfhe/docs/tutorials/parity_bit.md +++ b/tfhe/docs/tutorials/parity_bit.md @@ -18,7 +18,7 @@ This function returns a Boolean (`true` or `false`) so that the total count of ` # Cargo.toml # Default configuration for x86 Unix machines: -tfhe = { version = "0.7.4", features = ["integer", "x86_64-unix"]} +tfhe = { version = "0.7.5", features = ["integer", "x86_64-unix"]} ``` Refer to the [installation](../getting\_started/installation.md) for other configurations.