Skip to content

Commit a2f4717

Browse files
committed
test(coprocessor): add dependent whitepaper benchmark
1 parent f24326e commit a2f4717

File tree

1 file changed

+215
-0
lines changed
  • coprocessor/fhevm-engine/coprocessor/benches

1 file changed

+215
-0
lines changed

coprocessor/fhevm-engine/coprocessor/benches/erc20.rs

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,19 @@ fn main() {
9191
));
9292
});
9393

94+
group.throughput(Throughput::Elements(num_elems));
95+
let bench_id = format!(
96+
"{bench_name}::throughput::dependent_whitepaper::FHEUint64::{num_elems}_elems::{bench_optimization_target}"
97+
);
98+
group.bench_with_input(bench_id.clone(), &num_elems, move |b, &num_elems| {
99+
let _ = Runtime::new()
100+
.unwrap()
101+
.block_on(schedule_dependent_erc20_whitepaper(
102+
b,
103+
num_elems as usize,
104+
bench_id.clone(),
105+
));
106+
});
94107
group.throughput(Throughput::Elements(num_elems));
95108
let bench_id = format!(
96109
"{bench_name}::throughput::dependent_no_cmux::FHEUint64::{num_elems}_elems::{bench_optimization_target}"
@@ -466,6 +479,208 @@ async fn schedule_erc20_no_cmux(
466479
Ok(())
467480
}
468481

482+
async fn schedule_dependent_erc20_whitepaper(
483+
bencher: &mut Bencher<'_, WallTime>,
484+
num_tx: usize,
485+
bench_id: String,
486+
) -> Result<(), Box<dyn std::error::Error>> {
487+
let app = setup_test_app().await?;
488+
let pool = sqlx::postgres::PgPoolOptions::new()
489+
.max_connections(2)
490+
.connect(app.db_url())
491+
.await?;
492+
let mut client = FhevmCoprocessorClient::connect(app.app_url().to_string()).await?;
493+
494+
let mut handle_counter: u64 = random_handle();
495+
let mut next_handle = || {
496+
let out: u64 = handle_counter;
497+
handle_counter += 1;
498+
out.to_be_bytes().to_vec()
499+
};
500+
let api_key_header = format!("bearer {}", default_api_key());
501+
502+
let mut output_handles = vec![];
503+
let mut async_computations = vec![];
504+
let mut num_samples: usize = num_tx;
505+
let samples = std::env::var("FHEVM_TEST_NUM_SAMPLES");
506+
if let Ok(samples) = samples {
507+
num_samples = samples.parse::<usize>().unwrap();
508+
}
509+
510+
let keys = query_tenant_keys(vec![default_tenant_id()], &pool)
511+
.await
512+
.map_err(|e| {
513+
let e: Box<dyn std::error::Error> = e;
514+
e
515+
})?;
516+
let keys = &keys[0];
517+
518+
let mut builder = tfhe::ProvenCompactCiphertextList::builder(&keys.pks);
519+
let the_list = builder
520+
.push(20_u64) // Initial balance destination
521+
.build_with_proof_packed(&keys.public_params, &[], tfhe::zk::ZkComputeLoad::Proof)
522+
.unwrap();
523+
let serialized = safe_serialize(&the_list);
524+
let mut input_request = tonic::Request::new(InputUploadBatch {
525+
input_ciphertexts: vec![InputToUpload {
526+
input_payload: serialized,
527+
signatures: Vec::new(),
528+
user_address: test_random_user_address(),
529+
contract_address: test_random_contract_address(),
530+
}],
531+
});
532+
input_request.metadata_mut().append(
533+
"authorization",
534+
MetadataValue::from_str(&api_key_header).unwrap(),
535+
);
536+
let resp = client.upload_inputs(input_request).await?;
537+
let resp = resp.get_ref();
538+
assert_eq!(resp.upload_responses.len(), 1);
539+
let first_resp = &resp.upload_responses[0];
540+
assert_eq!(first_resp.input_handles.len(), 1);
541+
let handle_bald = first_resp.input_handles[0].handle.clone();
542+
let mut bald = AsyncComputationInput {
543+
input: Some(Input::InputHandle(handle_bald.clone())),
544+
};
545+
546+
let mut builder = tfhe::ProvenCompactCiphertextList::builder(&keys.pks);
547+
let the_list = builder
548+
.push(100_u64) // Balance source
549+
.push(10_u64) // Transfer amount
550+
.build_with_proof_packed(&keys.public_params, &[], tfhe::zk::ZkComputeLoad::Proof)
551+
.unwrap();
552+
553+
let serialized = safe_serialize(&the_list);
554+
let mut input_request = tonic::Request::new(InputUploadBatch {
555+
input_ciphertexts: vec![InputToUpload {
556+
input_payload: serialized,
557+
signatures: Vec::new(),
558+
user_address: test_random_user_address(),
559+
contract_address: test_random_contract_address(),
560+
}],
561+
});
562+
input_request.metadata_mut().append(
563+
"authorization",
564+
MetadataValue::from_str(&api_key_header).unwrap(),
565+
);
566+
let resp = client.upload_inputs(input_request).await?;
567+
let resp = resp.get_ref();
568+
assert_eq!(resp.upload_responses.len(), 1);
569+
let first_resp = &resp.upload_responses[0];
570+
assert_eq!(first_resp.input_handles.len(), 2);
571+
572+
for _ in 0..=(num_samples - 1) as u32 {
573+
let handle_bals = first_resp.input_handles[0].handle.clone();
574+
let bals = AsyncComputationInput {
575+
input: Some(Input::InputHandle(handle_bals.clone())),
576+
};
577+
let handle_trxa = first_resp.input_handles[1].handle.clone();
578+
let trxa = AsyncComputationInput {
579+
input: Some(Input::InputHandle(handle_trxa.clone())),
580+
};
581+
582+
let has_enough_funds_handle = next_handle();
583+
output_handles.push(has_enough_funds_handle.clone());
584+
let new_to_amount_target_handle = next_handle();
585+
output_handles.push(new_to_amount_target_handle.clone());
586+
let new_to_amount_handle = next_handle();
587+
output_handles.push(new_to_amount_handle.clone());
588+
let new_from_amount_target_handle = next_handle();
589+
output_handles.push(new_from_amount_target_handle.clone());
590+
let new_from_amount_handle = next_handle();
591+
output_handles.push(new_from_amount_handle.clone());
592+
593+
async_computations.push(AsyncComputation {
594+
operation: FheOperation::FheGe.into(),
595+
output_handle: has_enough_funds_handle.clone(),
596+
inputs: vec![bals.clone(), trxa.clone()],
597+
});
598+
async_computations.push(AsyncComputation {
599+
operation: FheOperation::FheAdd.into(),
600+
output_handle: new_to_amount_target_handle.clone(),
601+
inputs: vec![bald.clone(), trxa.clone()],
602+
});
603+
async_computations.push(AsyncComputation {
604+
operation: FheOperation::FheIfThenElse.into(),
605+
output_handle: new_to_amount_handle.clone(),
606+
inputs: vec![
607+
AsyncComputationInput {
608+
input: Some(Input::InputHandle(has_enough_funds_handle.clone())),
609+
},
610+
AsyncComputationInput {
611+
input: Some(Input::InputHandle(new_to_amount_target_handle.clone())),
612+
},
613+
bald.clone(),
614+
],
615+
});
616+
async_computations.push(AsyncComputation {
617+
operation: FheOperation::FheSub.into(),
618+
output_handle: new_from_amount_target_handle.clone(),
619+
inputs: vec![bals.clone(), trxa.clone()],
620+
});
621+
async_computations.push(AsyncComputation {
622+
operation: FheOperation::FheIfThenElse.into(),
623+
output_handle: new_from_amount_handle.clone(),
624+
inputs: vec![
625+
AsyncComputationInput {
626+
input: Some(Input::InputHandle(has_enough_funds_handle.clone())),
627+
},
628+
AsyncComputationInput {
629+
input: Some(Input::InputHandle(new_from_amount_target_handle.clone())),
630+
},
631+
bals.clone(),
632+
],
633+
});
634+
635+
bald = AsyncComputationInput {
636+
input: Some(Input::InputHandle(new_to_amount_handle.clone())),
637+
};
638+
}
639+
640+
let mut compute_request = tonic::Request::new(AsyncComputeRequest {
641+
computations: async_computations,
642+
});
643+
compute_request.metadata_mut().append(
644+
"authorization",
645+
MetadataValue::from_str(&api_key_header).unwrap(),
646+
);
647+
let _resp = client.clone().async_compute(compute_request).await.unwrap();
648+
let app_ref = &app;
649+
bencher
650+
.to_async(FuturesExecutor)
651+
.iter_custom(|iters| async move {
652+
let db_url = app_ref.db_url().to_string();
653+
let now = SystemTime::now();
654+
let _ = tokio::task::spawn_blocking(move || {
655+
Runtime::new()
656+
.unwrap()
657+
.block_on(async { wait_until_all_ciphertexts_computed(db_url).await.unwrap() });
658+
println!(
659+
"Execution time: {} -- {}",
660+
now.elapsed().unwrap().as_millis(),
661+
TIMING.load(std::sync::atomic::Ordering::SeqCst) / 1000
662+
);
663+
})
664+
.await;
665+
std::time::Duration::from_micros(
666+
TIMING.swap(0, std::sync::atomic::Ordering::SeqCst) * iters,
667+
)
668+
});
669+
670+
let params = keys.cks.computation_parameters();
671+
write_to_json::<u64, _>(
672+
&bench_id,
673+
params,
674+
"",
675+
"erc20-transfer",
676+
&OperatorType::Atomic,
677+
64,
678+
vec![],
679+
);
680+
681+
Ok(())
682+
}
683+
469684
async fn schedule_dependent_erc20_no_cmux(
470685
bencher: &mut Bencher<'_, WallTime>,
471686
num_tx: usize,

0 commit comments

Comments
 (0)