Skip to content

Commit

Permalink
feat: add trivial encryption as computation operation
Browse files Browse the repository at this point in the history
  • Loading branch information
david-zk committed Sep 23, 2024
1 parent b325965 commit 9898a53
Show file tree
Hide file tree
Showing 13 changed files with 970 additions and 366 deletions.
2 changes: 1 addition & 1 deletion fhevm-engine/coprocessor/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ impl coprocessor::fhevm_coprocessor_server::FhevmCoprocessor for CoprocessorServ
handle_types.push(-1);
this_comp_inputs.push(sc.clone());
is_scalar_op_vec.push(true);
assert!(idx == 1 || fhe_op.is_random(), "we should have checked earlier that only second operand can be scalar");
assert!(idx == 1 || fhe_op.does_have_more_than_one_scalar(), "we should have checked earlier that only second operand can be scalar");
}
}
}
Expand Down
111 changes: 111 additions & 0 deletions fhevm-engine/coprocessor/src/tests/operators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,117 @@ async fn test_fhe_casts() -> Result<(), Box<dyn std::error::Error>> {
Ok(())
}

#[tokio::test]
async fn test_op_trivial_encrypt() -> Result<(), Box<dyn std::error::Error>> {
let app = setup_test_app().await?;
let pool = sqlx::postgres::PgPoolOptions::new()
.max_connections(2)
.connect(app.db_url())
.await?;
let mut client = FhevmCoprocessorClient::connect(app.app_url().to_string()).await?;

let mut handle_counter = random_handle();
let mut next_handle = || {
let out: u64 = handle_counter;
handle_counter += 1;
out.to_be_bytes().to_vec()
};

let api_key_header = format!("bearer {}", default_api_key());

struct TrivialEncryptionTestCase {
inp_type: i32,
inp: BigInt,
}

let mut test_cases: Vec<TrivialEncryptionTestCase> = Vec::new();
test_cases.push(TrivialEncryptionTestCase {
inp_type: 0,
inp: BigInt::from(1),
});

let max_num: BigInt = BigInt::from(1) << 256 - 1;
for bits in supported_bits() {
let bits = *bits;
let inp_type = supported_bits_to_bit_type_in_db(bits);
let shift_by = bits - 1;
let mut inp = BigInt::from(1);
inp <<= shift_by;
let inp = inp.min(max_num.clone());
test_cases.push(TrivialEncryptionTestCase { inp_type, inp });
}

let mut async_computations = Vec::new();
let mut output_handles = Vec::new();
for case in &test_cases {
let output_handle = next_handle();
let (_, be_bytes) = case.inp.to_bytes_be();
output_handles.push(output_handle.clone());
async_computations.push(AsyncComputation {
operation: FheOperation::FheTrivialEncrypt.into(),
output_handle,
inputs: vec![
AsyncComputationInput {
input: Some(Input::Scalar(be_bytes)),
},
AsyncComputationInput {
input: Some(Input::Scalar(vec![case.inp_type as u8])),
},
],
});
}

println!("Scheduling computations...");
let mut compute_request = tonic::Request::new(AsyncComputeRequest {
computations: async_computations,
});
compute_request.metadata_mut().append(
"authorization",
MetadataValue::from_str(&api_key_header).unwrap(),
);
let _resp = client.async_compute(compute_request).await?;

println!("Computations scheduled, waiting upon completion...");

wait_until_all_ciphertexts_computed(&app).await?;

let decrypt_request = output_handles.clone();
let resp = decrypt_ciphertexts(&pool, 1, decrypt_request).await?;

assert_eq!(
resp.len(),
output_handles.len(),
"Outputs length doesn't match"
);
for (idx, co) in test_cases.iter().enumerate() {
let decr_response = &resp[idx];
let value_to_compare = match decr_response.value.as_str() {
// for FheBool outputs
"true" => "1",
"false" => "0",
other => other,
};
println!(
"Checking trivial encryption input:{} type:{}",
co.inp, co.inp_type
);
println!(
"Response output type: {}, response result: {}",
decr_response.output_type, decr_response.value
);
assert_eq!(
decr_response.output_type, co.inp_type as i16,
"operand types not equal"
);
assert_eq!(
value_to_compare, co.inp.to_string(),
"operand output values not equal"
);
}

Ok(())
}

#[tokio::test]
async fn test_fhe_if_then_else() -> Result<(), Box<dyn std::error::Error>> {
let app = setup_test_app().await?;
Expand Down
8 changes: 4 additions & 4 deletions fhevm-engine/coprocessor/src/tfhe_worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ async fn tfhe_worker_cycle(
NOT c.is_scalar
OR c.is_scalar AND NOT elems.dep_index = 2
)
-- ignore fhe random operations, all inputs are scalars
AND NOT c.fhe_operation = ANY(ARRAY[26, 27])
-- ignore fhe random, trivial encrypt operations, all inputs are scalars
AND NOT c.fhe_operation = ANY(ARRAY[24, 26, 27])
)
LIMIT $1
FOR UPDATE SKIP LOCKED
Expand Down Expand Up @@ -156,7 +156,7 @@ async fn tfhe_worker_cycle(
let mut work_ciphertexts: Vec<(i16, Vec<u8>)> =
Vec::with_capacity(w.dependencies.len());
for (idx, dh) in w.dependencies.iter().enumerate() {
let is_operand_scalar = w.is_scalar && idx == 1 || fhe_op.is_random();
let is_operand_scalar = w.is_scalar && idx == 1 || fhe_op.does_have_more_than_one_scalar();
if is_operand_scalar {
work_ciphertexts.push((-1, dh.clone()));
} else {
Expand Down Expand Up @@ -190,7 +190,7 @@ async fn tfhe_worker_cycle(
let mut deserialized_cts: Vec<SupportedFheCiphertexts> =
Vec::with_capacity(work_ciphertexts.len());
for (idx, (ct_type, ct_bytes)) in work_ciphertexts.iter().enumerate() {
let is_operand_scalar = w.is_scalar && idx == 1 || fhe_op.is_random();
let is_operand_scalar = w.is_scalar && idx == 1 || fhe_op.does_have_more_than_one_scalar();
if is_operand_scalar {
let mut the_int = tfhe::integer::U256::default();
assert!(
Expand Down
2 changes: 1 addition & 1 deletion fhevm-engine/coprocessor/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ pub fn sort_computations_by_dependencies<'a>(
}
Input::Scalar(sc_bytes) => {
check_valid_ciphertext_handle(&sc_bytes)?;
if dep_idx != 1 && !fhe_op.is_random() {
if dep_idx != 1 && !fhe_op.does_have_more_than_one_scalar() {
// TODO: remove wrapping after refactor
return Err(CoprocessorError::FhevmError(
FhevmError::FheOperationOnlySecondOperandCanBeScalar {
Expand Down
Loading

0 comments on commit 9898a53

Please sign in to comment.