fix(hpu): fix whitepaper erc20 for HPU using if_then_zero

This commit is contained in:
pgardratzama
2025-12-19 17:57:22 +01:00
committed by Pierre Gardrat
parent 917bb5e1ef
commit 569abd9a3b
4 changed files with 64 additions and 7 deletions

View File

@@ -29,12 +29,13 @@ pub fn transfer_whitepaper<FheType>(
) -> (FheType, FheType)
where
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>,
{
let has_enough_funds = (from_amount).ge(amount);
let zero_amount = FheType::encrypt_trivial(0u64);
let amount_to_transfer = has_enough_funds.select(amount, &zero_amount);
//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.if_then_zero(amount);
let new_to_amount = to_amount + &amount_to_transfer;
let new_from_amount = from_amount - &amount_to_transfer;
@@ -51,12 +52,13 @@ pub fn par_transfer_whitepaper<FheType>(
where
FheType:
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>,
{
let has_enough_funds = (from_amount).ge(amount);
let zero_amount = FheType::encrypt_trivial(0u64);
let amount_to_transfer = has_enough_funds.select(amount, &zero_amount);
//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.if_then_zero(amount);
let (new_to_amount, new_from_amount) = rayon::join(
|| to_amount + &amount_to_transfer,

View File

@@ -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::re_randomization::ReRandomizationMetadata;
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::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 {
/// Conditional selection.
///

View File

@@ -11,6 +11,7 @@ pub use crate::high_level_api::traits::{
FheOrd, FheTrivialEncrypt, FheTryEncrypt, FheTryTrivialEncrypt, FheWait, Flip, IfThenElse,
OverflowingAdd, OverflowingMul, OverflowingNeg, OverflowingSub, ReRandomize, RotateLeft,
RotateLeftAssign, RotateRight, RotateRightAssign, ScalarIfThenElse, SquashNoise, Tagged,
IfThenZero,
};
#[cfg(feature = "hpu")]
pub use crate::high_level_api::traits::{FheHpu, HpuHandle};

View File

@@ -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> {
type Output;