mirror of
https://github.com/zama-ai/tfhe-rs.git
synced 2026-01-09 22:57:59 -05:00
fix(hpu): fix whitepaper erc20 for HPU using if_then_zero
This commit is contained in:
committed by
Pierre Gardrat
parent
917bb5e1ef
commit
569abd9a3b
@@ -29,12 +29,13 @@ pub fn transfer_whitepaper<FheType>(
|
|||||||
) -> (FheType, FheType)
|
) -> (FheType, FheType)
|
||||||
where
|
where
|
||||||
FheType: Add<Output = FheType> + for<'a> FheOrd<&'a FheType> + FheTrivialEncrypt<u64>,
|
FheType: Add<Output = FheType> + for<'a> FheOrd<&'a FheType> + FheTrivialEncrypt<u64>,
|
||||||
FheBool: IfThenElse<FheType>,
|
FheBool: IfThenZero<FheType>,
|
||||||
for<'a> &'a FheType: Add<Output = FheType> + Sub<Output = FheType>,
|
for<'a> &'a FheType: Add<Output = FheType> + Sub<Output = FheType>,
|
||||||
{
|
{
|
||||||
let has_enough_funds = (from_amount).ge(amount);
|
let has_enough_funds = (from_amount).ge(amount);
|
||||||
let zero_amount = FheType::encrypt_trivial(0u64);
|
//let zero_amount = FheType::encrypt_trivial(0u64);
|
||||||
let amount_to_transfer = has_enough_funds.select(amount, &zero_amount);
|
//let amount_to_transfer = has_enough_funds.select(amount, &zero_amount);
|
||||||
|
let amount_to_transfer = has_enough_funds.if_then_zero(amount);
|
||||||
|
|
||||||
let new_to_amount = to_amount + &amount_to_transfer;
|
let new_to_amount = to_amount + &amount_to_transfer;
|
||||||
let new_from_amount = from_amount - &amount_to_transfer;
|
let new_from_amount = from_amount - &amount_to_transfer;
|
||||||
@@ -51,12 +52,13 @@ pub fn par_transfer_whitepaper<FheType>(
|
|||||||
where
|
where
|
||||||
FheType:
|
FheType:
|
||||||
Add<Output = FheType> + for<'a> FheOrd<&'a FheType> + Send + Sync + FheTrivialEncrypt<u64>,
|
Add<Output = FheType> + for<'a> FheOrd<&'a FheType> + Send + Sync + FheTrivialEncrypt<u64>,
|
||||||
FheBool: IfThenElse<FheType>,
|
FheBool: IfThenZero<FheType>,
|
||||||
for<'a> &'a FheType: Add<Output = FheType> + Sub<Output = FheType>,
|
for<'a> &'a FheType: Add<Output = FheType> + Sub<Output = FheType>,
|
||||||
{
|
{
|
||||||
let has_enough_funds = (from_amount).ge(amount);
|
let has_enough_funds = (from_amount).ge(amount);
|
||||||
let zero_amount = FheType::encrypt_trivial(0u64);
|
//let zero_amount = FheType::encrypt_trivial(0u64);
|
||||||
let amount_to_transfer = has_enough_funds.select(amount, &zero_amount);
|
//let amount_to_transfer = has_enough_funds.select(amount, &zero_amount);
|
||||||
|
let amount_to_transfer = has_enough_funds.if_then_zero(amount);
|
||||||
|
|
||||||
let (new_to_amount, new_from_amount) = rayon::join(
|
let (new_to_amount, new_from_amount) = rayon::join(
|
||||||
|| to_amount + &amount_to_transfer,
|
|| to_amount + &amount_to_transfer,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use crate::high_level_api::integers::{FheInt, FheIntId, FheUint, FheUintId};
|
|||||||
use crate::high_level_api::keys::InternalServerKey;
|
use crate::high_level_api::keys::InternalServerKey;
|
||||||
use crate::high_level_api::re_randomization::ReRandomizationMetadata;
|
use crate::high_level_api::re_randomization::ReRandomizationMetadata;
|
||||||
use crate::high_level_api::traits::{
|
use crate::high_level_api::traits::{
|
||||||
FheEq, Flip, IfThenElse, ReRandomize, ScalarIfThenElse, Tagged,
|
FheEq, Flip, IfThenElse, IfThenZero, ReRandomize, ScalarIfThenElse, Tagged,
|
||||||
};
|
};
|
||||||
use crate::high_level_api::{global_state, CompactPublicKey};
|
use crate::high_level_api::{global_state, CompactPublicKey};
|
||||||
use crate::integer::block_decomposition::DecomposableInto;
|
use crate::integer::block_decomposition::DecomposableInto;
|
||||||
@@ -552,6 +552,56 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<Id> IfThenZero<FheUint<Id>> for FheBool
|
||||||
|
where
|
||||||
|
Id: FheUintId,
|
||||||
|
{
|
||||||
|
/// Conditional selection.
|
||||||
|
///
|
||||||
|
/// The output value returned depends on the value of `self`.
|
||||||
|
///
|
||||||
|
/// - if `self` is true, the output will have the value of `ct_then`
|
||||||
|
/// - if `self` is false, the output will be an encryption of 0
|
||||||
|
fn if_then_zero(&self, ct_then: &FheUint<Id>) -> FheUint<Id> {
|
||||||
|
global_state::with_internal_keys(|sks| match sks {
|
||||||
|
InternalServerKey::Cpu(_) => {
|
||||||
|
panic!("CPU does not support if_then_zero at this point")
|
||||||
|
}
|
||||||
|
#[cfg(feature = "gpu")]
|
||||||
|
InternalServerKey::Cuda(_) => {
|
||||||
|
panic!("Cuda does not support if_then_zero at this point")
|
||||||
|
}
|
||||||
|
#[cfg(feature = "hpu")]
|
||||||
|
InternalServerKey::Hpu(device) => {
|
||||||
|
let hpu_then = ct_then.ciphertext.on_hpu(device);
|
||||||
|
let hpu_cond = self.ciphertext.on_hpu(device);
|
||||||
|
|
||||||
|
let (opcode, proto) = {
|
||||||
|
let asm_iop = &hpu_asm::iop::IOP_IF_THEN_ZERO;
|
||||||
|
(
|
||||||
|
asm_iop.opcode(),
|
||||||
|
&asm_iop.format().expect("Unspecified IOP format").proto,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
// These clones are cheap are they are just Arc
|
||||||
|
let hpu_result = HpuRadixCiphertext::exec(
|
||||||
|
proto,
|
||||||
|
opcode,
|
||||||
|
&[hpu_then.clone(), hpu_cond.clone()],
|
||||||
|
&[],
|
||||||
|
)
|
||||||
|
.pop()
|
||||||
|
.unwrap();
|
||||||
|
FheUint::new(
|
||||||
|
hpu_result,
|
||||||
|
device.tag.clone(),
|
||||||
|
ReRandomizationMetadata::default(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<Id: FheIntId> IfThenElse<FheInt<Id>> for FheBool {
|
impl<Id: FheIntId> IfThenElse<FheInt<Id>> for FheBool {
|
||||||
/// Conditional selection.
|
/// Conditional selection.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ pub use crate::high_level_api::traits::{
|
|||||||
FheOrd, FheTrivialEncrypt, FheTryEncrypt, FheTryTrivialEncrypt, FheWait, Flip, IfThenElse,
|
FheOrd, FheTrivialEncrypt, FheTryEncrypt, FheTryTrivialEncrypt, FheWait, Flip, IfThenElse,
|
||||||
OverflowingAdd, OverflowingMul, OverflowingNeg, OverflowingSub, ReRandomize, RotateLeft,
|
OverflowingAdd, OverflowingMul, OverflowingNeg, OverflowingSub, ReRandomize, RotateLeft,
|
||||||
RotateLeftAssign, RotateRight, RotateRightAssign, ScalarIfThenElse, SquashNoise, Tagged,
|
RotateLeftAssign, RotateRight, RotateRightAssign, ScalarIfThenElse, SquashNoise, Tagged,
|
||||||
|
IfThenZero,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "hpu")]
|
#[cfg(feature = "hpu")]
|
||||||
pub use crate::high_level_api::traits::{FheHpu, HpuHandle};
|
pub use crate::high_level_api::traits::{FheHpu, HpuHandle};
|
||||||
|
|||||||
@@ -149,6 +149,10 @@ pub trait IfThenElse<Ciphertext> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait IfThenZero<Ciphertext> {
|
||||||
|
fn if_then_zero(&self, ct_then: &Ciphertext) -> Ciphertext;
|
||||||
|
}
|
||||||
|
|
||||||
pub trait ScalarIfThenElse<Lhs, Rhs> {
|
pub trait ScalarIfThenElse<Lhs, Rhs> {
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user