From 55dcd6c07216c01726515cd6b70e0561cb6f0ff9 Mon Sep 17 00:00:00 2001 From: David Kazlauskas Date: Fri, 6 Sep 2024 09:34:06 +0300 Subject: [PATCH] Ebytes 64/128/256 support --- .../coprocessor/src/tests/operators.rs | 31 +- .../fhevm-engine-common/src/tfhe_ops.rs | 583 +++++++++++++++++- fhevm-engine/fhevm-engine-common/src/types.rs | 114 ++++ 3 files changed, 700 insertions(+), 28 deletions(-) diff --git a/fhevm-engine/coprocessor/src/tests/operators.rs b/fhevm-engine/coprocessor/src/tests/operators.rs index fc368d61..75e4da78 100644 --- a/fhevm-engine/coprocessor/src/tests/operators.rs +++ b/fhevm-engine/coprocessor/src/tests/operators.rs @@ -45,6 +45,9 @@ fn supported_bits() -> &'static [i32] { 128, 160, 256, + 512, + 1024, + 2048, ] } @@ -59,6 +62,9 @@ fn supported_types() -> &'static [i32] { 6, // 128 bit 7, // 160 bit 8, // 256 bit + 9, // ebytes 64 + 10, // ebytes 128 + 11, // ebytes 256 ] } @@ -71,6 +77,9 @@ fn supported_bits_to_bit_type_in_db(inp: i32) -> i32 { 128 => 6, 160 => 7, 256 => 8, + 512 => 9, + 1024 => 10, + 2048 => 11, other => panic!("unknown supported bits: {other}"), } } @@ -671,17 +680,19 @@ fn generate_binary_test_cases() -> Vec { let bits = *bits; let mut shift_by = bits - 8; for op in SupportedFheOperations::iter() { - if op == SupportedFheOperations::FheMul { - // don't go out of bit bounds when multiplying two numbers, so we shift by less - shift_by /= 2; - } - if op.op_type() == FheOperationType::Binary { - if does_fhe_operation_support_both_encrypted_operands(&op) { - push_case(bits, false, shift_by, op); + if bits <= 256 || op.supports_ebytes_inputs() { + if op == SupportedFheOperations::FheMul { + // don't go out of bit bounds when multiplying two numbers, so we shift by less + shift_by /= 2; } - - if does_fhe_operation_support_scalar(&op) { - push_case(bits, true, shift_by, op); + if op.op_type() == FheOperationType::Binary { + if does_fhe_operation_support_both_encrypted_operands(&op) { + push_case(bits, false, shift_by, op); + } + + if does_fhe_operation_support_scalar(&op) && bits <= 256 { + push_case(bits, true, shift_by, op); + } } } } diff --git a/fhevm-engine/fhevm-engine-common/src/tfhe_ops.rs b/fhevm-engine/fhevm-engine-common/src/tfhe_ops.rs index 18370136..3e651cc6 100644 --- a/fhevm-engine/fhevm-engine-common/src/tfhe_ops.rs +++ b/fhevm-engine/fhevm-engine-common/src/tfhe_ops.rs @@ -1,8 +1,8 @@ -use crate::types::{FheOperationType, FhevmError, SupportedFheCiphertexts, SupportedFheOperations}; +use crate::types::{is_ebytes_type, FheOperationType, FhevmError, SupportedFheCiphertexts, SupportedFheOperations}; use tfhe::{ - integer::U256, prelude::{ + integer::{bigint::StaticUnsignedBigInt, U256}, prelude::{ CastInto, FheEq, FheMax, FheMin, FheOrd, FheTryTrivialEncrypt, IfThenElse, RotateLeft, RotateRight - }, FheBool, FheUint128, FheUint16, FheUint160, FheUint256, FheUint32, FheUint64, FheUint8 + }, FheBool, FheUint1024, FheUint128, FheUint16, FheUint160, FheUint2048, FheUint256, FheUint32, FheUint512, FheUint64, FheUint8 }; pub fn deserialize_fhe_ciphertext( @@ -50,6 +50,21 @@ pub fn deserialize_fhe_ciphertext( .map_err(|e| FhevmError::DeserializationError(e))?; Ok(SupportedFheCiphertexts::FheUint256(v)) } + 9 => { + let v: tfhe::FheUint512 = bincode::deserialize(input_bytes) + .map_err(|e| FhevmError::DeserializationError(e))?; + Ok(SupportedFheCiphertexts::FheBytes64(v)) + } + 10 => { + let v: tfhe::FheUint1024 = bincode::deserialize(input_bytes) + .map_err(|e| FhevmError::DeserializationError(e))?; + Ok(SupportedFheCiphertexts::FheBytes128(v)) + } + 11 => { + let v: tfhe::FheUint2048 = bincode::deserialize(input_bytes) + .map_err(|e| FhevmError::DeserializationError(e))?; + Ok(SupportedFheCiphertexts::FheBytes256(v)) + } _ => { return Err(FhevmError::UnknownFheType(input_type as i32)); } @@ -128,6 +143,39 @@ pub fn debug_trivial_encrypt_be_bytes( let output = FheUint256::try_encrypt_trivial(be).unwrap(); SupportedFheCiphertexts::FheUint256(output) } + 9 => { + let mut padded: [u8; 64] = [0; 64]; + let padded_len = padded.len(); + let copy_from = padded_len - input_bytes.len(); + let len = padded.len().min(input_bytes.len()); + padded[copy_from..padded_len].copy_from_slice(&input_bytes[0..len]); + let mut be: StaticUnsignedBigInt<8> = StaticUnsignedBigInt::<8>::ZERO; + be.copy_from_be_byte_slice(&padded); + let output = FheUint512::try_encrypt_trivial(be).unwrap(); + SupportedFheCiphertexts::FheBytes64(output) + } + 10 => { + let mut padded: [u8; 128] = [0; 128]; + let padded_len = padded.len(); + let copy_from = padded_len - input_bytes.len(); + let len = padded.len().min(input_bytes.len()); + padded[copy_from..padded_len].copy_from_slice(&input_bytes[0..len]); + let mut be: StaticUnsignedBigInt<16> = StaticUnsignedBigInt::<16>::ZERO; + be.copy_from_be_byte_slice(&padded); + let output = FheUint1024::try_encrypt_trivial(be).unwrap(); + SupportedFheCiphertexts::FheBytes128(output) + } + 11 => { + let mut padded: [u8; 256] = [0; 256]; + let padded_len = padded.len(); + let copy_from = padded_len - input_bytes.len(); + let len = padded.len().min(input_bytes.len()); + padded[copy_from..padded_len].copy_from_slice(&input_bytes[0..len]); + let mut be: StaticUnsignedBigInt<32> = StaticUnsignedBigInt::<32>::ZERO; + be.copy_from_be_byte_slice(&padded); + let output = FheUint2048::try_encrypt_trivial(be).unwrap(); + SupportedFheCiphertexts::FheBytes256(output) + } other => { panic!("Unknown input type for trivial encryption: {other}") } @@ -200,6 +248,30 @@ pub fn try_expand_ciphertext_list( res.push(SupportedFheCiphertexts::FheUint64(ct)); } + tfhe::FheTypes::Uint128 => { + let ct: tfhe::FheUint128 = expanded + .get(idx) + .expect("Index must exist") + .expect("Must succeed, we just checked this is the type"); + + res.push(SupportedFheCiphertexts::FheUint128(ct)); + } + tfhe::FheTypes::Uint160 => { + let ct: tfhe::FheUint160 = expanded + .get(idx) + .expect("Index must exist") + .expect("Must succeed, we just checked this is the type"); + + res.push(SupportedFheCiphertexts::FheUint160(ct)); + } + tfhe::FheTypes::Uint256 => { + let ct: tfhe::FheUint256 = expanded + .get(idx) + .expect("Index must exist") + .expect("Must succeed, we just checked this is the type"); + + res.push(SupportedFheCiphertexts::FheUint256(ct)); + } other => { return Err(FhevmError::CiphertextExpansionUnsupportedCiphertextKind( other, @@ -294,13 +366,35 @@ pub fn check_fhe_operand_types( }); } - // special case for div operation, rhs for scalar must be zero - if is_scalar && fhe_op == SupportedFheOperations::FheDiv { - let all_zeroes = input_handles[1].iter().all(|i| *i == 0u8); - if all_zeroes { - return Err(FhevmError::FheOperationScalarDivisionByZero { + // special case for div operation, rhs for scalar must not be zero + if is_scalar { + if fhe_op == SupportedFheOperations::FheDiv { + let all_zeroes = input_handles[1].iter().all(|i| *i == 0u8); + if all_zeroes { + return Err(FhevmError::FheOperationScalarDivisionByZero { + lhs_handle: format!("0x{}", hex::encode(&input_handles[0])), + rhs_value: format!("0x{}", hex::encode(&input_handles[1])), + fhe_operation, + fhe_operation_name: format!("{:?}", SupportedFheOperations::FheDiv), + }); + } + } + + if is_ebytes_type(input_types[0]) { + return Err(FhevmError::FheOperationDoesntSupportScalar { + fhe_operation, + fhe_operation_name: format!("{:?}", fhe_op), + scalar_requested: is_scalar, + scalar_supported: false, + }); + } + } + + if is_ebytes_type(input_types[0]) { + if !fhe_op.supports_ebytes_inputs() { + return Err(FhevmError::FheOperationDoesntSupportEbytesAsInput { lhs_handle: format!("0x{}", hex::encode(&input_handles[0])), - rhs_value: format!("0x{}", hex::encode(&input_handles[1])), + rhs_handle: format!("0x{}", hex::encode(&input_handles[1])), fhe_operation, fhe_operation_name: format!("{:?}", SupportedFheOperations::FheDiv), }); @@ -332,6 +426,17 @@ pub fn check_fhe_operand_types( }); } + if is_ebytes_type(input_types[0]) { + if !fhe_op.supports_ebytes_inputs() { + return Err(FhevmError::FheOperationDoesntSupportEbytesAsInput { + lhs_handle: format!("0x{}", hex::encode(&input_handles[0])), + rhs_handle: format!("0x{}", hex::encode(&input_handles[1])), + fhe_operation, + fhe_operation_name: format!("{:?}", SupportedFheOperations::FheDiv), + }); + } + } + return Ok(input_types[0]); } FheOperationType::Other => { @@ -433,7 +538,7 @@ pub fn validate_fhe_type(input_type: i32) -> Result<(), FhevmError> { .try_into() .or(Err(FhevmError::UnknownFheType(input_type)))?; match i16_type { - 0 | 2 | 3 | 4 | 5 | 6 | 7 | 8 => Ok(()), + 0 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 => Ok(()), _ => Err(FhevmError::UnknownFheType(input_type)), } } @@ -504,6 +609,15 @@ pub fn perform_fhe_operation( (SupportedFheCiphertexts::FheUint256(a), SupportedFheCiphertexts::FheUint256(b)) => { Ok(SupportedFheCiphertexts::FheUint256(a + b)) } + (SupportedFheCiphertexts::FheBytes64(a), SupportedFheCiphertexts::FheBytes64(b)) => { + Ok(SupportedFheCiphertexts::FheBytes64(a + b)) + } + (SupportedFheCiphertexts::FheBytes128(a), SupportedFheCiphertexts::FheBytes128(b)) => { + Ok(SupportedFheCiphertexts::FheBytes128(a + b)) + } + (SupportedFheCiphertexts::FheBytes256(a), SupportedFheCiphertexts::FheBytes256(b)) => { + Ok(SupportedFheCiphertexts::FheBytes256(a + b)) + } (SupportedFheCiphertexts::FheUint8(a), SupportedFheCiphertexts::Scalar(b)) => { let (l, _) = b.to_low_high_u128(); Ok(SupportedFheCiphertexts::FheUint8(a + (l as u8))) @@ -561,6 +675,15 @@ pub fn perform_fhe_operation( (SupportedFheCiphertexts::FheUint256(a), SupportedFheCiphertexts::FheUint256(b)) => { Ok(SupportedFheCiphertexts::FheUint256(a - b)) } + (SupportedFheCiphertexts::FheBytes64(a), SupportedFheCiphertexts::FheBytes64(b)) => { + Ok(SupportedFheCiphertexts::FheBytes64(a - b)) + } + (SupportedFheCiphertexts::FheBytes128(a), SupportedFheCiphertexts::FheBytes128(b)) => { + Ok(SupportedFheCiphertexts::FheBytes128(a - b)) + } + (SupportedFheCiphertexts::FheBytes256(a), SupportedFheCiphertexts::FheBytes256(b)) => { + Ok(SupportedFheCiphertexts::FheBytes256(a - b)) + } (SupportedFheCiphertexts::FheUint8(a), SupportedFheCiphertexts::Scalar(b)) => { let (l, _) = b.to_low_high_u128(); Ok(SupportedFheCiphertexts::FheUint8(a - (l as u8))) @@ -618,6 +741,15 @@ pub fn perform_fhe_operation( (SupportedFheCiphertexts::FheUint256(a), SupportedFheCiphertexts::FheUint256(b)) => { Ok(SupportedFheCiphertexts::FheUint256(a * b)) } + (SupportedFheCiphertexts::FheBytes64(a), SupportedFheCiphertexts::FheBytes64(b)) => { + Ok(SupportedFheCiphertexts::FheBytes64(a * b)) + } + (SupportedFheCiphertexts::FheBytes128(a), SupportedFheCiphertexts::FheBytes128(b)) => { + Ok(SupportedFheCiphertexts::FheBytes128(a * b)) + } + (SupportedFheCiphertexts::FheBytes256(a), SupportedFheCiphertexts::FheBytes256(b)) => { + Ok(SupportedFheCiphertexts::FheBytes256(a * b)) + } (SupportedFheCiphertexts::FheUint8(a), SupportedFheCiphertexts::Scalar(b)) => { let (l, _) = b.to_low_high_u128(); Ok(SupportedFheCiphertexts::FheUint8(a * (l as u8))) @@ -675,6 +807,15 @@ pub fn perform_fhe_operation( (SupportedFheCiphertexts::FheUint256(a), SupportedFheCiphertexts::FheUint256(b)) => { Ok(SupportedFheCiphertexts::FheUint256(a / b)) } + (SupportedFheCiphertexts::FheBytes64(a), SupportedFheCiphertexts::FheBytes64(b)) => { + Ok(SupportedFheCiphertexts::FheBytes64(a / b)) + } + (SupportedFheCiphertexts::FheBytes128(a), SupportedFheCiphertexts::FheBytes128(b)) => { + Ok(SupportedFheCiphertexts::FheBytes128(a / b)) + } + (SupportedFheCiphertexts::FheBytes256(a), SupportedFheCiphertexts::FheBytes256(b)) => { + Ok(SupportedFheCiphertexts::FheBytes256(a / b)) + } (SupportedFheCiphertexts::FheUint8(a), SupportedFheCiphertexts::Scalar(b)) => { let (l, _) = b.to_low_high_u128(); Ok(SupportedFheCiphertexts::FheUint8(a / (l as u8))) @@ -732,6 +873,15 @@ pub fn perform_fhe_operation( (SupportedFheCiphertexts::FheUint256(a), SupportedFheCiphertexts::FheUint256(b)) => { Ok(SupportedFheCiphertexts::FheUint256(a % b)) } + (SupportedFheCiphertexts::FheBytes64(a), SupportedFheCiphertexts::FheBytes64(b)) => { + Ok(SupportedFheCiphertexts::FheBytes64(a % b)) + } + (SupportedFheCiphertexts::FheBytes128(a), SupportedFheCiphertexts::FheBytes128(b)) => { + Ok(SupportedFheCiphertexts::FheBytes128(a % b)) + } + (SupportedFheCiphertexts::FheBytes256(a), SupportedFheCiphertexts::FheBytes256(b)) => { + Ok(SupportedFheCiphertexts::FheBytes256(a % b)) + } (SupportedFheCiphertexts::FheUint8(a), SupportedFheCiphertexts::Scalar(b)) => { let (l, _) = b.to_low_high_u128(); Ok(SupportedFheCiphertexts::FheUint8(a % (l as u8))) @@ -789,6 +939,15 @@ pub fn perform_fhe_operation( (SupportedFheCiphertexts::FheUint256(a), SupportedFheCiphertexts::FheUint256(b)) => { Ok(SupportedFheCiphertexts::FheUint256(a & b)) } + (SupportedFheCiphertexts::FheBytes128(a), SupportedFheCiphertexts::FheBytes128(b)) => { + Ok(SupportedFheCiphertexts::FheBytes128(a & b)) + } + (SupportedFheCiphertexts::FheBytes256(a), SupportedFheCiphertexts::FheBytes256(b)) => { + Ok(SupportedFheCiphertexts::FheBytes256(a & b)) + } + (SupportedFheCiphertexts::FheBytes64(a), SupportedFheCiphertexts::FheBytes64(b)) => { + Ok(SupportedFheCiphertexts::FheBytes64(a & b)) + } (SupportedFheCiphertexts::FheUint8(a), SupportedFheCiphertexts::Scalar(b)) => { let (l, _) = b.to_low_high_u128(); Ok(SupportedFheCiphertexts::FheUint8(a & (l as u8))) @@ -846,6 +1005,15 @@ pub fn perform_fhe_operation( (SupportedFheCiphertexts::FheUint256(a), SupportedFheCiphertexts::FheUint256(b)) => { Ok(SupportedFheCiphertexts::FheUint256(a | b)) } + (SupportedFheCiphertexts::FheBytes64(a), SupportedFheCiphertexts::FheBytes64(b)) => { + Ok(SupportedFheCiphertexts::FheBytes64(a | b)) + } + (SupportedFheCiphertexts::FheBytes128(a), SupportedFheCiphertexts::FheBytes128(b)) => { + Ok(SupportedFheCiphertexts::FheBytes128(a | b)) + } + (SupportedFheCiphertexts::FheBytes256(a), SupportedFheCiphertexts::FheBytes256(b)) => { + Ok(SupportedFheCiphertexts::FheBytes256(a | b)) + } (SupportedFheCiphertexts::FheUint8(a), SupportedFheCiphertexts::Scalar(b)) => { let (l, _) = b.to_low_high_u128(); Ok(SupportedFheCiphertexts::FheUint8(a | (l as u8))) @@ -903,6 +1071,15 @@ pub fn perform_fhe_operation( (SupportedFheCiphertexts::FheUint256(a), SupportedFheCiphertexts::FheUint256(b)) => { Ok(SupportedFheCiphertexts::FheUint256(a ^ b)) } + (SupportedFheCiphertexts::FheBytes64(a), SupportedFheCiphertexts::FheBytes64(b)) => { + Ok(SupportedFheCiphertexts::FheBytes64(a ^ b)) + } + (SupportedFheCiphertexts::FheBytes128(a), SupportedFheCiphertexts::FheBytes128(b)) => { + Ok(SupportedFheCiphertexts::FheBytes128(a ^ b)) + } + (SupportedFheCiphertexts::FheBytes256(a), SupportedFheCiphertexts::FheBytes256(b)) => { + Ok(SupportedFheCiphertexts::FheBytes256(a ^ b)) + } (SupportedFheCiphertexts::FheUint8(a), SupportedFheCiphertexts::Scalar(b)) => { let (l, _) = b.to_low_high_u128(); Ok(SupportedFheCiphertexts::FheUint8(a ^ (l as u8))) @@ -960,6 +1137,15 @@ pub fn perform_fhe_operation( (SupportedFheCiphertexts::FheUint256(a), SupportedFheCiphertexts::FheUint256(b)) => { Ok(SupportedFheCiphertexts::FheUint256(a << b)) } + (SupportedFheCiphertexts::FheBytes64(a), SupportedFheCiphertexts::FheBytes64(b)) => { + Ok(SupportedFheCiphertexts::FheBytes64(a << b)) + } + (SupportedFheCiphertexts::FheBytes128(a), SupportedFheCiphertexts::FheBytes128(b)) => { + Ok(SupportedFheCiphertexts::FheBytes128(a << b)) + } + (SupportedFheCiphertexts::FheBytes256(a), SupportedFheCiphertexts::FheBytes256(b)) => { + Ok(SupportedFheCiphertexts::FheBytes256(a << b)) + } (SupportedFheCiphertexts::FheUint8(a), SupportedFheCiphertexts::Scalar(b)) => { let (l, _) = b.to_low_high_u128(); Ok(SupportedFheCiphertexts::FheUint8(a << (l as u8))) @@ -1017,6 +1203,15 @@ pub fn perform_fhe_operation( (SupportedFheCiphertexts::FheUint256(a), SupportedFheCiphertexts::FheUint256(b)) => { Ok(SupportedFheCiphertexts::FheUint256(a >> b)) } + (SupportedFheCiphertexts::FheBytes64(a), SupportedFheCiphertexts::FheBytes64(b)) => { + Ok(SupportedFheCiphertexts::FheBytes64(a >> b)) + } + (SupportedFheCiphertexts::FheBytes128(a), SupportedFheCiphertexts::FheBytes128(b)) => { + Ok(SupportedFheCiphertexts::FheBytes128(a >> b)) + } + (SupportedFheCiphertexts::FheBytes256(a), SupportedFheCiphertexts::FheBytes256(b)) => { + Ok(SupportedFheCiphertexts::FheBytes256(a >> b)) + } (SupportedFheCiphertexts::FheUint8(a), SupportedFheCiphertexts::Scalar(b)) => { let (l, _) = b.to_low_high_u128(); Ok(SupportedFheCiphertexts::FheUint8(a >> (l as u8))) @@ -1074,6 +1269,15 @@ pub fn perform_fhe_operation( (SupportedFheCiphertexts::FheUint256(a), SupportedFheCiphertexts::FheUint256(b)) => { Ok(SupportedFheCiphertexts::FheUint256(a.rotate_left(b))) } + (SupportedFheCiphertexts::FheBytes64(a), SupportedFheCiphertexts::FheBytes64(b)) => { + Ok(SupportedFheCiphertexts::FheBytes64(a.rotate_left(b))) + } + (SupportedFheCiphertexts::FheBytes128(a), SupportedFheCiphertexts::FheBytes128(b)) => { + Ok(SupportedFheCiphertexts::FheBytes128(a.rotate_left(b))) + } + (SupportedFheCiphertexts::FheBytes256(a), SupportedFheCiphertexts::FheBytes256(b)) => { + Ok(SupportedFheCiphertexts::FheBytes256(a.rotate_left(b))) + } (SupportedFheCiphertexts::FheUint8(a), SupportedFheCiphertexts::Scalar(b)) => { let (l, _) = b.to_low_high_u128(); Ok(SupportedFheCiphertexts::FheUint8(a.rotate_left(l as u8))) @@ -1131,6 +1335,15 @@ pub fn perform_fhe_operation( (SupportedFheCiphertexts::FheUint256(a), SupportedFheCiphertexts::FheUint256(b)) => { Ok(SupportedFheCiphertexts::FheUint256(a.rotate_right(b))) } + (SupportedFheCiphertexts::FheBytes64(a), SupportedFheCiphertexts::FheBytes64(b)) => { + Ok(SupportedFheCiphertexts::FheBytes64(a.rotate_right(b))) + } + (SupportedFheCiphertexts::FheBytes128(a), SupportedFheCiphertexts::FheBytes128(b)) => { + Ok(SupportedFheCiphertexts::FheBytes128(a.rotate_right(b))) + } + (SupportedFheCiphertexts::FheBytes256(a), SupportedFheCiphertexts::FheBytes256(b)) => { + Ok(SupportedFheCiphertexts::FheBytes256(a.rotate_right(b))) + } (SupportedFheCiphertexts::FheUint8(a), SupportedFheCiphertexts::Scalar(b)) => { let (l, _) = b.to_low_high_u128(); Ok(SupportedFheCiphertexts::FheUint8(a.rotate_right(l as u8))) @@ -1188,6 +1401,15 @@ pub fn perform_fhe_operation( (SupportedFheCiphertexts::FheUint256(a), SupportedFheCiphertexts::FheUint256(b)) => { Ok(SupportedFheCiphertexts::FheUint256(a.min(b))) } + (SupportedFheCiphertexts::FheBytes64(a), SupportedFheCiphertexts::FheBytes64(b)) => { + Ok(SupportedFheCiphertexts::FheBytes64(a.min(b))) + } + (SupportedFheCiphertexts::FheBytes128(a), SupportedFheCiphertexts::FheBytes128(b)) => { + Ok(SupportedFheCiphertexts::FheBytes128(a.min(b))) + } + (SupportedFheCiphertexts::FheBytes256(a), SupportedFheCiphertexts::FheBytes256(b)) => { + Ok(SupportedFheCiphertexts::FheBytes256(a.min(b))) + } (SupportedFheCiphertexts::FheUint8(a), SupportedFheCiphertexts::Scalar(b)) => { let (l, _) = b.to_low_high_u128(); Ok(SupportedFheCiphertexts::FheUint8(a.min(l as u8))) @@ -1245,6 +1467,15 @@ pub fn perform_fhe_operation( (SupportedFheCiphertexts::FheUint256(a), SupportedFheCiphertexts::FheUint256(b)) => { Ok(SupportedFheCiphertexts::FheUint256(a.max(b))) } + (SupportedFheCiphertexts::FheBytes64(a), SupportedFheCiphertexts::FheBytes64(b)) => { + Ok(SupportedFheCiphertexts::FheBytes64(a.max(b))) + } + (SupportedFheCiphertexts::FheBytes128(a), SupportedFheCiphertexts::FheBytes128(b)) => { + Ok(SupportedFheCiphertexts::FheBytes128(a.max(b))) + } + (SupportedFheCiphertexts::FheBytes256(a), SupportedFheCiphertexts::FheBytes256(b)) => { + Ok(SupportedFheCiphertexts::FheBytes256(a.max(b))) + } (SupportedFheCiphertexts::FheUint8(a), SupportedFheCiphertexts::Scalar(b)) => { let (l, _) = b.to_low_high_u128(); Ok(SupportedFheCiphertexts::FheUint8(a.max(l as u8))) @@ -1305,6 +1536,15 @@ pub fn perform_fhe_operation( (SupportedFheCiphertexts::FheUint256(a), SupportedFheCiphertexts::FheUint256(b)) => { Ok(SupportedFheCiphertexts::FheBool(a.eq(b))) } + (SupportedFheCiphertexts::FheBytes64(a), SupportedFheCiphertexts::FheBytes64(b)) => { + Ok(SupportedFheCiphertexts::FheBool(a.eq(b))) + } + (SupportedFheCiphertexts::FheBytes128(a), SupportedFheCiphertexts::FheBytes128(b)) => { + Ok(SupportedFheCiphertexts::FheBool(a.eq(b))) + } + (SupportedFheCiphertexts::FheBytes256(a), SupportedFheCiphertexts::FheBytes256(b)) => { + Ok(SupportedFheCiphertexts::FheBool(a.eq(b))) + } (SupportedFheCiphertexts::FheBool(a), SupportedFheCiphertexts::Scalar(b)) => { let (l, h) = b.to_low_high_u128(); let non_zero = l > 0 || h > 0; @@ -1370,6 +1610,15 @@ pub fn perform_fhe_operation( (SupportedFheCiphertexts::FheUint256(a), SupportedFheCiphertexts::FheUint256(b)) => { Ok(SupportedFheCiphertexts::FheBool(a.ne(b))) } + (SupportedFheCiphertexts::FheBytes64(a), SupportedFheCiphertexts::FheBytes64(b)) => { + Ok(SupportedFheCiphertexts::FheBool(a.ne(b))) + } + (SupportedFheCiphertexts::FheBytes128(a), SupportedFheCiphertexts::FheBytes128(b)) => { + Ok(SupportedFheCiphertexts::FheBool(a.ne(b))) + } + (SupportedFheCiphertexts::FheBytes256(a), SupportedFheCiphertexts::FheBytes256(b)) => { + Ok(SupportedFheCiphertexts::FheBool(a.ne(b))) + } (SupportedFheCiphertexts::FheBool(a), SupportedFheCiphertexts::Scalar(b)) => { let (l, h) = b.to_low_high_u128(); let non_zero = l > 0 || h > 0; @@ -1432,6 +1681,15 @@ pub fn perform_fhe_operation( (SupportedFheCiphertexts::FheUint256(a), SupportedFheCiphertexts::FheUint256(b)) => { Ok(SupportedFheCiphertexts::FheBool(a.ge(b))) } + (SupportedFheCiphertexts::FheBytes64(a), SupportedFheCiphertexts::FheBytes64(b)) => { + Ok(SupportedFheCiphertexts::FheBool(a.ge(b))) + } + (SupportedFheCiphertexts::FheBytes128(a), SupportedFheCiphertexts::FheBytes128(b)) => { + Ok(SupportedFheCiphertexts::FheBool(a.ge(b))) + } + (SupportedFheCiphertexts::FheBytes256(a), SupportedFheCiphertexts::FheBytes256(b)) => { + Ok(SupportedFheCiphertexts::FheBool(a.ge(b))) + } (SupportedFheCiphertexts::FheUint8(a), SupportedFheCiphertexts::Scalar(b)) => { let (l, _) = b.to_low_high_u128(); Ok(SupportedFheCiphertexts::FheBool(a.ge(l as u8))) @@ -1489,6 +1747,15 @@ pub fn perform_fhe_operation( (SupportedFheCiphertexts::FheUint256(a), SupportedFheCiphertexts::FheUint256(b)) => { Ok(SupportedFheCiphertexts::FheBool(a.gt(b))) } + (SupportedFheCiphertexts::FheBytes64(a), SupportedFheCiphertexts::FheBytes64(b)) => { + Ok(SupportedFheCiphertexts::FheBool(a.gt(b))) + } + (SupportedFheCiphertexts::FheBytes128(a), SupportedFheCiphertexts::FheBytes128(b)) => { + Ok(SupportedFheCiphertexts::FheBool(a.gt(b))) + } + (SupportedFheCiphertexts::FheBytes256(a), SupportedFheCiphertexts::FheBytes256(b)) => { + Ok(SupportedFheCiphertexts::FheBool(a.gt(b))) + } (SupportedFheCiphertexts::FheUint8(a), SupportedFheCiphertexts::Scalar(b)) => { let (l, _) = b.to_low_high_u128(); Ok(SupportedFheCiphertexts::FheBool(a.gt(l as u8))) @@ -1546,6 +1813,15 @@ pub fn perform_fhe_operation( (SupportedFheCiphertexts::FheUint256(a), SupportedFheCiphertexts::FheUint256(b)) => { Ok(SupportedFheCiphertexts::FheBool(a.le(b))) } + (SupportedFheCiphertexts::FheBytes64(a), SupportedFheCiphertexts::FheBytes64(b)) => { + Ok(SupportedFheCiphertexts::FheBool(a.le(b))) + } + (SupportedFheCiphertexts::FheBytes128(a), SupportedFheCiphertexts::FheBytes128(b)) => { + Ok(SupportedFheCiphertexts::FheBool(a.le(b))) + } + (SupportedFheCiphertexts::FheBytes256(a), SupportedFheCiphertexts::FheBytes256(b)) => { + Ok(SupportedFheCiphertexts::FheBool(a.le(b))) + } (SupportedFheCiphertexts::FheUint8(a), SupportedFheCiphertexts::Scalar(b)) => { let (l, _) = b.to_low_high_u128(); Ok(SupportedFheCiphertexts::FheBool(a.le(l as u8))) @@ -1603,6 +1879,15 @@ pub fn perform_fhe_operation( (SupportedFheCiphertexts::FheUint256(a), SupportedFheCiphertexts::FheUint256(b)) => { Ok(SupportedFheCiphertexts::FheBool(a.lt(b))) } + (SupportedFheCiphertexts::FheBytes64(a), SupportedFheCiphertexts::FheBytes64(b)) => { + Ok(SupportedFheCiphertexts::FheBool(a.lt(b))) + } + (SupportedFheCiphertexts::FheBytes128(a), SupportedFheCiphertexts::FheBytes128(b)) => { + Ok(SupportedFheCiphertexts::FheBool(a.lt(b))) + } + (SupportedFheCiphertexts::FheBytes256(a), SupportedFheCiphertexts::FheBytes256(b)) => { + Ok(SupportedFheCiphertexts::FheBool(a.lt(b))) + } (SupportedFheCiphertexts::FheUint8(a), SupportedFheCiphertexts::Scalar(b)) => { let (l, _) = b.to_low_high_u128(); Ok(SupportedFheCiphertexts::FheBool(a.lt(l as u8))) @@ -1647,6 +1932,9 @@ pub fn perform_fhe_operation( SupportedFheCiphertexts::FheUint128(a) => Ok(SupportedFheCiphertexts::FheUint128(!a)), SupportedFheCiphertexts::FheUint160(a) => Ok(SupportedFheCiphertexts::FheUint160(!a)), SupportedFheCiphertexts::FheUint256(a) => Ok(SupportedFheCiphertexts::FheUint256(!a)), + SupportedFheCiphertexts::FheBytes64(a) => Ok(SupportedFheCiphertexts::FheBytes64(!a)), + SupportedFheCiphertexts::FheBytes128(a) => Ok(SupportedFheCiphertexts::FheBytes128(!a)), + SupportedFheCiphertexts::FheBytes256(a) => Ok(SupportedFheCiphertexts::FheBytes256(!a)), _ => { panic!("Unsupported fhe types"); } @@ -1663,6 +1951,9 @@ pub fn perform_fhe_operation( SupportedFheCiphertexts::FheUint128(a) => Ok(SupportedFheCiphertexts::FheUint128(-a)), SupportedFheCiphertexts::FheUint160(a) => Ok(SupportedFheCiphertexts::FheUint160(-a)), SupportedFheCiphertexts::FheUint256(a) => Ok(SupportedFheCiphertexts::FheUint256(-a)), + SupportedFheCiphertexts::FheBytes64(a) => Ok(SupportedFheCiphertexts::FheBytes64(-a)), + SupportedFheCiphertexts::FheBytes128(a) => Ok(SupportedFheCiphertexts::FheBytes128(-a)), + SupportedFheCiphertexts::FheBytes256(a) => Ok(SupportedFheCiphertexts::FheBytes256(-a)), _ => { panic!("Unsupported fhe types"); } @@ -1708,6 +1999,18 @@ pub fn perform_fhe_operation( let res = flag.select(a, b); Ok(SupportedFheCiphertexts::FheUint256(res)) } + (SupportedFheCiphertexts::FheBytes64(a), SupportedFheCiphertexts::FheBytes64(b)) => { + let res = flag.select(a, b); + Ok(SupportedFheCiphertexts::FheBytes64(res)) + } + (SupportedFheCiphertexts::FheBytes128(a), SupportedFheCiphertexts::FheBytes128(b)) => { + let res = flag.select(a, b); + Ok(SupportedFheCiphertexts::FheBytes128(res)) + } + (SupportedFheCiphertexts::FheBytes256(a), SupportedFheCiphertexts::FheBytes256(b)) => { + let res = flag.select(a, b); + Ok(SupportedFheCiphertexts::FheBytes256(res)) + } _ => { panic!("Mismatch between cmux operand types") } @@ -1716,7 +2019,6 @@ pub fn perform_fhe_operation( SupportedFheOperations::FheCast => match (&input_operands[0], &input_operands[1]) { (SupportedFheCiphertexts::FheBool(inp), SupportedFheCiphertexts::Scalar(op)) => { let (l, h) = op.to_low_high_u128(); - assert_eq!(h, 0, "Not supported yet"); let l = l as i16; let type_id = input_operands[0].type_num(); if l == type_id { @@ -1751,13 +2053,24 @@ pub fn perform_fhe_operation( let out: tfhe::FheUint256 = inp.clone().cast_into(); Ok(SupportedFheCiphertexts::FheUint256(out)) } + 9 => { + let out: tfhe::FheUint512 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes64(out)) + } + 10 => { + let out: tfhe::FheUint1024 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes128(out)) + } + 11 => { + let out: tfhe::FheUint2048 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes256(out)) + } other => panic!("unexpected type: {other}"), } } } (SupportedFheCiphertexts::FheUint8(inp), SupportedFheCiphertexts::Scalar(op)) => { let (l, h) = op.to_low_high_u128(); - assert_eq!(h, 0, "Not supported yet"); let l = l as i16; let type_id = input_operands[0].type_num(); if l == type_id { @@ -1792,13 +2105,24 @@ pub fn perform_fhe_operation( let out: tfhe::FheUint256 = inp.clone().cast_into(); Ok(SupportedFheCiphertexts::FheUint256(out)) } + 9 => { + let out: tfhe::FheUint512 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes64(out)) + } + 10 => { + let out: tfhe::FheUint1024 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes128(out)) + } + 11 => { + let out: tfhe::FheUint2048 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes256(out)) + } other => panic!("unexpected type: {other}"), } } } (SupportedFheCiphertexts::FheUint16(inp), SupportedFheCiphertexts::Scalar(op)) => { let (l, h) = op.to_low_high_u128(); - assert_eq!(h, 0, "Not supported yet"); let l = l as i16; let type_id = input_operands[0].type_num(); if l == type_id { @@ -1833,13 +2157,24 @@ pub fn perform_fhe_operation( let out: tfhe::FheUint256 = inp.clone().cast_into(); Ok(SupportedFheCiphertexts::FheUint256(out)) } + 9 => { + let out: tfhe::FheUint512 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes64(out)) + } + 10 => { + let out: tfhe::FheUint1024 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes128(out)) + } + 11 => { + let out: tfhe::FheUint2048 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes256(out)) + } other => panic!("unexpected type: {other}"), } } } (SupportedFheCiphertexts::FheUint32(inp), SupportedFheCiphertexts::Scalar(op)) => { let (l, h) = op.to_low_high_u128(); - assert_eq!(h, 0, "Not supported yet"); let l = l as i16; let type_id = input_operands[0].type_num(); if l == type_id { @@ -1874,13 +2209,24 @@ pub fn perform_fhe_operation( let out: tfhe::FheUint256 = inp.clone().cast_into(); Ok(SupportedFheCiphertexts::FheUint256(out)) } + 9 => { + let out: tfhe::FheUint512 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes64(out)) + } + 10 => { + let out: tfhe::FheUint1024 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes128(out)) + } + 11 => { + let out: tfhe::FheUint2048 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes256(out)) + } other => panic!("unexpected type: {other}"), } } } (SupportedFheCiphertexts::FheUint64(inp), SupportedFheCiphertexts::Scalar(op)) => { let (l, h) = op.to_low_high_u128(); - assert_eq!(h, 0, "Not supported yet"); let l = l as i16; let type_id = input_operands[0].type_num(); if l == type_id { @@ -1915,13 +2261,24 @@ pub fn perform_fhe_operation( let out: tfhe::FheUint256 = inp.clone().cast_into(); Ok(SupportedFheCiphertexts::FheUint256(out)) } + 9 => { + let out: tfhe::FheUint512 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes64(out)) + } + 10 => { + let out: tfhe::FheUint1024 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes128(out)) + } + 11 => { + let out: tfhe::FheUint2048 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes256(out)) + } other => panic!("unexpected type: {other}"), } } } (SupportedFheCiphertexts::FheUint128(inp), SupportedFheCiphertexts::Scalar(op)) => { let (l, h) = op.to_low_high_u128(); - assert_eq!(h, 0, "Not supported yet"); let l = l as i16; let type_id = input_operands[0].type_num(); if l == type_id { @@ -1956,13 +2313,24 @@ pub fn perform_fhe_operation( let out: tfhe::FheUint256 = inp.clone().cast_into(); Ok(SupportedFheCiphertexts::FheUint256(out)) } + 9 => { + let out: tfhe::FheUint512 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes64(out)) + } + 10 => { + let out: tfhe::FheUint1024 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes128(out)) + } + 11 => { + let out: tfhe::FheUint2048 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes256(out)) + } other => panic!("unexpected type: {other}"), } } } (SupportedFheCiphertexts::FheUint160(inp), SupportedFheCiphertexts::Scalar(op)) => { let (l, h) = op.to_low_high_u128(); - assert_eq!(h, 0, "Not supported yet"); let l = l as i16; let type_id = input_operands[0].type_num(); if l == type_id { @@ -1997,13 +2365,24 @@ pub fn perform_fhe_operation( let out: tfhe::FheUint256 = inp.clone().cast_into(); Ok(SupportedFheCiphertexts::FheUint256(out)) } + 9 => { + let out: tfhe::FheUint512 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes64(out)) + } + 10 => { + let out: tfhe::FheUint1024 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes128(out)) + } + 11 => { + let out: tfhe::FheUint2048 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes256(out)) + } other => panic!("unexpected type: {other}"), } } } (SupportedFheCiphertexts::FheUint256(inp), SupportedFheCiphertexts::Scalar(op)) => { let (l, h) = op.to_low_high_u128(); - assert_eq!(h, 0, "Not supported yet"); let l = l as i16; let type_id = input_operands[0].type_num(); if l == type_id { @@ -2038,6 +2417,174 @@ pub fn perform_fhe_operation( let out: tfhe::FheUint160 = inp.clone().cast_into(); Ok(SupportedFheCiphertexts::FheUint160(out)) } + 9 => { + let out: tfhe::FheUint512 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes64(out)) + } + 10 => { + let out: tfhe::FheUint1024 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes128(out)) + } + 11 => { + let out: tfhe::FheUint2048 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes256(out)) + } + other => panic!("unexpected type: {other}"), + } + } + } + (SupportedFheCiphertexts::FheBytes64(inp), SupportedFheCiphertexts::Scalar(op)) => { + let (l, h) = op.to_low_high_u128(); + let l = l as i16; + let type_id = input_operands[0].type_num(); + if l == type_id { + return Ok(SupportedFheCiphertexts::FheBytes64(inp.clone())); + } else { + match l { + 0 => { + let out: tfhe::FheBool = inp.gt(0); + Ok(SupportedFheCiphertexts::FheBool(out)) + } + 2 => { + let out: tfhe::FheUint8 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheUint8(out)) + } + 3 => { + let out: tfhe::FheUint16 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheUint16(out)) + } + 4 => { + let out: tfhe::FheUint32 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheUint32(out)) + } + 5 => { + let out: tfhe::FheUint64 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheUint64(out)) + } + 6 => { + let out: tfhe::FheUint128 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheUint128(out)) + } + 7 => { + let out: tfhe::FheUint160 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheUint160(out)) + } + 8 => { + let out: tfhe::FheUint256 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheUint256(out)) + } + 10 => { + let out: tfhe::FheUint1024 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes128(out)) + } + 11 => { + let out: tfhe::FheUint2048 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes256(out)) + } + other => panic!("unexpected type: {other}"), + } + } + } + (SupportedFheCiphertexts::FheBytes128(inp), SupportedFheCiphertexts::Scalar(op)) => { + let (l, h) = op.to_low_high_u128(); + let l = l as i16; + let type_id = input_operands[0].type_num(); + if l == type_id { + return Ok(SupportedFheCiphertexts::FheBytes128(inp.clone())); + } else { + match l { + 0 => { + let out: tfhe::FheBool = inp.gt(0); + Ok(SupportedFheCiphertexts::FheBool(out)) + } + 2 => { + let out: tfhe::FheUint8 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheUint8(out)) + } + 3 => { + let out: tfhe::FheUint16 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheUint16(out)) + } + 4 => { + let out: tfhe::FheUint32 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheUint32(out)) + } + 5 => { + let out: tfhe::FheUint64 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheUint64(out)) + } + 6 => { + let out: tfhe::FheUint128 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheUint128(out)) + } + 7 => { + let out: tfhe::FheUint160 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheUint160(out)) + } + 8 => { + let out: tfhe::FheUint256 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheUint256(out)) + } + 9 => { + let out: tfhe::FheUint512 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes64(out)) + } + 11 => { + let out: tfhe::FheUint2048 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes256(out)) + } + other => panic!("unexpected type: {other}"), + } + } + } + (SupportedFheCiphertexts::FheBytes256(inp), SupportedFheCiphertexts::Scalar(op)) => { + let (l, h) = op.to_low_high_u128(); + let l = l as i16; + let type_id = input_operands[0].type_num(); + if l == type_id { + return Ok(SupportedFheCiphertexts::FheBytes256(inp.clone())); + } else { + match l { + 0 => { + let out: tfhe::FheBool = inp.gt(0); + Ok(SupportedFheCiphertexts::FheBool(out)) + } + 2 => { + let out: tfhe::FheUint8 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheUint8(out)) + } + 3 => { + let out: tfhe::FheUint16 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheUint16(out)) + } + 4 => { + let out: tfhe::FheUint32 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheUint32(out)) + } + 5 => { + let out: tfhe::FheUint64 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheUint64(out)) + } + 6 => { + let out: tfhe::FheUint128 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheUint128(out)) + } + 7 => { + let out: tfhe::FheUint160 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheUint160(out)) + } + 8 => { + let out: tfhe::FheUint256 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheUint256(out)) + } + 9 => { + let out: tfhe::FheUint512 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes64(out)) + } + 10 => { + let out: tfhe::FheUint1024 = inp.clone().cast_into(); + Ok(SupportedFheCiphertexts::FheBytes128(out)) + } other => panic!("unexpected type: {other}"), } } diff --git a/fhevm-engine/fhevm-engine-common/src/types.rs b/fhevm-engine/fhevm-engine-common/src/types.rs index 0b5dfdcf..b201dbf0 100644 --- a/fhevm-engine/fhevm-engine-common/src/types.rs +++ b/fhevm-engine/fhevm-engine-common/src/types.rs @@ -1,5 +1,6 @@ use anyhow::Result; use bigdecimal::num_bigint::BigInt; +use tfhe::integer::bigint::StaticUnsignedBigInt; use tfhe::integer::U256; use tfhe::prelude::FheDecrypt; use tfhe::{CompressedCiphertextList, CompressedCiphertextListBuilder}; @@ -38,6 +39,12 @@ pub enum FhevmError { fhe_operation: i32, fhe_operation_name: String, }, + FheOperationDoesntSupportEbytesAsInput { + lhs_handle: String, + rhs_handle: String, + fhe_operation: i32, + fhe_operation_name: String, + }, UnexpectedOperandCountForFheOperation { fhe_operation: i32, fhe_operation_name: String, @@ -125,6 +132,14 @@ impl std::fmt::Display for FhevmError { } => { write!(f, "zero on the right side of scalar division, lhs handle: {lhs_handle}, rhs value: {rhs_value}, fhe operation: {fhe_operation} fhe operation name:{fhe_operation_name}") } + Self::FheOperationDoesntSupportEbytesAsInput { + lhs_handle, + rhs_handle: rhs_value, + fhe_operation, + fhe_operation_name, + } => { + write!(f, "zero on the right side of scalar division, lhs handle: {lhs_handle}, rhs value: {rhs_value}, fhe operation: {fhe_operation} fhe operation name:{fhe_operation_name}") + } Self::UnexpectedOperandCountForFheOperation { fhe_operation, fhe_operation_name, @@ -210,6 +225,9 @@ pub enum SupportedFheCiphertexts { FheUint128(tfhe::FheUint128), FheUint160(tfhe::FheUint160), FheUint256(tfhe::FheUint256), + FheBytes64(tfhe::FheUint512), + FheBytes128(tfhe::FheUint1024), + FheBytes256(tfhe::FheUint2048), Scalar(U256), } @@ -264,6 +282,9 @@ impl SupportedFheCiphertexts { SupportedFheCiphertexts::FheUint128(v) => (type_num, bincode::serialize(v).unwrap()), SupportedFheCiphertexts::FheUint160(v) => (type_num, bincode::serialize(v).unwrap()), SupportedFheCiphertexts::FheUint256(v) => (type_num, bincode::serialize(v).unwrap()), + SupportedFheCiphertexts::FheBytes64(v) => (type_num, bincode::serialize(v).unwrap()), + SupportedFheCiphertexts::FheBytes128(v) => (type_num, bincode::serialize(v).unwrap()), + SupportedFheCiphertexts::FheBytes256(v) => (type_num, bincode::serialize(v).unwrap()), SupportedFheCiphertexts::Scalar(_) => { panic!("we should never need to serialize scalar") } @@ -282,6 +303,9 @@ impl SupportedFheCiphertexts { SupportedFheCiphertexts::FheUint128(_) => 6, SupportedFheCiphertexts::FheUint160(_) => 7, SupportedFheCiphertexts::FheUint256(_) => 8, + SupportedFheCiphertexts::FheBytes64(_) => 9, + SupportedFheCiphertexts::FheBytes128(_) => 10, + SupportedFheCiphertexts::FheBytes256(_) => 11, SupportedFheCiphertexts::Scalar(_) => { panic!("we should never need to serialize scalar") } @@ -319,6 +343,24 @@ impl SupportedFheCiphertexts { dec.copy_to_be_byte_slice(&mut slice); BigInt::from_bytes_be(bigdecimal::num_bigint::Sign::Plus, &slice).to_string() }, + SupportedFheCiphertexts::FheBytes64(v) => { + let dec = FheDecrypt::>::decrypt(v, client_key); + let mut slice: [u8; 64] = [0; 64]; + dec.copy_to_be_byte_slice(&mut slice); + BigInt::from_bytes_be(bigdecimal::num_bigint::Sign::Plus, &slice).to_string() + }, + SupportedFheCiphertexts::FheBytes128(v) => { + let dec = FheDecrypt::>::decrypt(v, client_key); + let mut slice: [u8; 128] = [0; 128]; + dec.copy_to_be_byte_slice(&mut slice); + BigInt::from_bytes_be(bigdecimal::num_bigint::Sign::Plus, &slice).to_string() + }, + SupportedFheCiphertexts::FheBytes256(v) => { + let dec = FheDecrypt::>::decrypt(v, client_key); + let mut slice: [u8; 256] = [0; 256]; + dec.copy_to_be_byte_slice(&mut slice); + BigInt::from_bytes_be(bigdecimal::num_bigint::Sign::Plus, &slice).to_string() + }, SupportedFheCiphertexts::Scalar(v) => { let (l, h) = v.to_low_high_u128(); format!("{l}{h}") @@ -337,6 +379,9 @@ impl SupportedFheCiphertexts { SupportedFheCiphertexts::FheUint128(c) => builder.push(c), SupportedFheCiphertexts::FheUint160(c) => builder.push(c), SupportedFheCiphertexts::FheUint256(c) => builder.push(c), + SupportedFheCiphertexts::FheBytes64(c) => builder.push(c), + SupportedFheCiphertexts::FheBytes128(c) => builder.push(c), + SupportedFheCiphertexts::FheBytes256(c) => builder.push(c), SupportedFheCiphertexts::Scalar(_) => { // TODO: Need to fix that, scalars are not ciphertexts. panic!("cannot compress a scalar"); @@ -364,9 +409,38 @@ impl SupportedFheCiphertexts { 5 => Ok(SupportedFheCiphertexts::FheUint64( list.get(0)?.ok_or(FhevmError::MissingTfheRsData)?, )), + 6 => Ok(SupportedFheCiphertexts::FheUint128( + list.get(0)?.ok_or(FhevmError::MissingTfheRsData)?, + )), + 7 => Ok(SupportedFheCiphertexts::FheUint160( + list.get(0)?.ok_or(FhevmError::MissingTfheRsData)?, + )), + 8 => Ok(SupportedFheCiphertexts::FheUint256( + list.get(0)?.ok_or(FhevmError::MissingTfheRsData)?, + )), + 9 => Ok(SupportedFheCiphertexts::FheBytes64( + list.get(0)?.ok_or(FhevmError::MissingTfheRsData)?, + )), _ => Err(FhevmError::UnknownFheType(ct_type as i32).into()), } } + + pub fn is_ebytes(&self) -> bool { + match self { + SupportedFheCiphertexts::FheBytes64(_) + | SupportedFheCiphertexts::FheBytes128(_) + | SupportedFheCiphertexts::FheBytes256(_) => true, + SupportedFheCiphertexts::FheBool(_) + | SupportedFheCiphertexts::FheUint8(_) + | SupportedFheCiphertexts::FheUint16(_) + | SupportedFheCiphertexts::FheUint32(_) + | SupportedFheCiphertexts::FheUint64(_) + | SupportedFheCiphertexts::FheUint128(_) + | SupportedFheCiphertexts::FheUint160(_) + | SupportedFheCiphertexts::FheUint256(_) + | SupportedFheCiphertexts::Scalar(_) => false, + } + } } impl SupportedFheOperations { @@ -425,6 +499,42 @@ impl SupportedFheOperations { _ => false, } } + + pub fn supports_ebytes_inputs(&self) -> bool { + match self { + SupportedFheOperations::FheBitAnd + | SupportedFheOperations::FheBitOr + | SupportedFheOperations::FheBitXor + | SupportedFheOperations::FheShl + | SupportedFheOperations::FheShr + | SupportedFheOperations::FheRotl + | SupportedFheOperations::FheRotr + | SupportedFheOperations::FheEq + | SupportedFheOperations::FheNe + | SupportedFheOperations::FheGe + | SupportedFheOperations::FheGt + | SupportedFheOperations::FheLe + | SupportedFheOperations::FheLt + | SupportedFheOperations::FheMin + | SupportedFheOperations::FheMax + | SupportedFheOperations::FheNot + | SupportedFheOperations::FheNeg + | SupportedFheOperations::FheIfThenElse + | SupportedFheOperations::FheCast => { + true + }, + SupportedFheOperations::FheAdd + | SupportedFheOperations::FheSub + | SupportedFheOperations::FheMul + | SupportedFheOperations::FheDiv + | SupportedFheOperations::FheRem + | SupportedFheOperations::FheRand + | SupportedFheOperations::FheRandBounded + | SupportedFheOperations::FheGetInputCiphertext => { + false + }, + } + } } impl TryFrom for SupportedFheOperations { @@ -502,3 +612,7 @@ pub fn get_ct_type(handle: &[u8]) -> Result { _ => Err(FhevmError::InvalidHandle), } } + +pub fn is_ebytes_type(inp: i16) -> bool { + inp >= 9 && inp <= 11 +} \ No newline at end of file