1#![allow(non_snake_case)]
3use std::{io, mem};
4
5use bytemuck::cast_slice_mut;
6use cryprot_codes::ex_conv::{ExConvCode, ExConvCodeConfig};
7use cryprot_core::{
8 AES_PAR_BLOCKS, Block, aes_hash::FIXED_KEY_HASH, alloc::HugePageMemory, buf::Buf,
9 random_oracle::Hash, tokio_rayon::spawn_compute,
10};
11use cryprot_net::{Connection, ConnectionError};
12use cryprot_pprf::{PprfConfig, RegularPprfReceiver, RegularPprfSender};
13use futures::{SinkExt, StreamExt};
14use rand::{Rng, SeedableRng, rngs::StdRng};
15use subtle::Choice;
16use tracing::Level;
17
18use crate::{
19 Connected, Malicious, MaliciousMarker, RandChoiceRotReceiver, RandChoiceRotSender, RotReceiver,
20 RotSender, Security, SemiHonest, SemiHonestMarker,
21 extension::{self, OtExtensionReceiver, OtExtensionSender},
22 noisy_vole::{self, NoisyVoleReceiver, NoisyVoleSender},
23 phase,
24};
25
26pub const SECURITY_PARAMETER: usize = 128;
27const SCALER: usize = 2;
28
29pub type SemiHonestSilentOtSender = SilentOtSender<SemiHonestMarker>;
30pub type SemiHonestSilentOtReceiver = SilentOtReceiver<SemiHonestMarker>;
31
32pub type MaliciousSilentOtSender = SilentOtSender<MaliciousMarker>;
33pub type MaliciousSilentOtReceiver = SilentOtReceiver<MaliciousMarker>;
34
35pub struct SilentOtSender<S> {
36 conn: Connection,
37 ot_sender: OtExtensionSender<S>,
38 rng: StdRng,
39}
40
41#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
42pub enum MultType {
43 #[default]
44 ExConv7x24,
45 ExConv21x24,
46}
47
48#[derive(thiserror::Error, Debug)]
49pub enum Error {
50 #[error("unable to perform base OTs for silent OTs")]
51 BaseOt(#[from] extension::Error),
52 #[error("error in pprf expansion for silent OTs")]
53 Pprf(#[from] cryprot_pprf::Error),
54 #[error("io error during malicious check")]
55 Io(#[from] io::Error),
56 #[error("error in connection to peer")]
57 Connection(#[from] ConnectionError),
58 #[error("error in noisy vole during malicious check")]
59 NoisyVole(#[from] noisy_vole::Error),
60 #[error("sender did not transmit hash in malicious check")]
61 MissingSenderHash,
62 #[error("receiver did not transmit seed in malicious check")]
63 MissingReceiverSeed,
64 #[error("malicious check failed")]
65 MaliciousCheck,
66}
67
68impl<S: Security> SilentOtSender<S> {
69 pub fn new(mut conn: Connection) -> Self {
70 let ot_sender = OtExtensionSender::new(conn.sub_connection());
71 Self {
72 conn,
73 ot_sender,
74 rng: StdRng::from_os_rng(),
75 }
76 }
77
78 pub fn ots_buf_size(count: usize) -> usize {
80 let conf = Config::configure(count, MultType::default());
81 let pprf_conf = PprfConfig::from(conf);
82 pprf_conf.size()
83 }
84
85 pub async fn random_send(&mut self, count: usize) -> Result<impl Buf<[Block; 2]>, Error> {
86 let mut ots = HugePageMemory::zeroed(count);
87 self.random_sent_into(count, &mut ots).await?;
88 Ok(ots)
89 }
90
91 #[tracing::instrument(target = "cryprot_metrics", level = Level::TRACE, skip_all, fields(phase = phase::SILENT_RANDOM_EXTENSION))]
92 pub async fn random_sent_into(
93 &mut self,
94 count: usize,
95 ots: &mut impl Buf<[Block; 2]>,
96 ) -> Result<(), Error> {
97 assert_eq!(count, ots.len());
98 let delta = self.rng.random();
99 let mut ots_buf = mem::take(ots);
100 let correlated = self.correlated_send(count, delta).await?;
101
102 let ots_buf = spawn_compute(move || {
103 let masked_delta = delta & Block::MASK_LSB;
104 for ((chunk_idx, ot_chunk), corr_chunk) in ots_buf
105 .chunks_mut(AES_PAR_BLOCKS)
106 .enumerate()
107 .zip(correlated.chunks(AES_PAR_BLOCKS))
108 {
109 for (ots, corr) in ot_chunk.iter_mut().zip(corr_chunk) {
110 let masked = *corr & Block::MASK_LSB;
111 *ots = [masked, masked ^ masked_delta]
112 }
113 if S::MALICIOUS_SECURITY {
114 FIXED_KEY_HASH.tccr_hash_slice_mut(cast_slice_mut(ot_chunk), |i| {
118 Block::from(chunk_idx * AES_PAR_BLOCKS + i / 2)
119 });
120 } else {
121 FIXED_KEY_HASH.cr_hash_slice_mut(cast_slice_mut(ot_chunk));
122 }
123 }
124 ots_buf
125 })
126 .await
127 .expect("worker panic");
128 *ots = ots_buf;
129 Ok(())
130 }
131
132 pub async fn correlated_send(
133 &mut self,
134 count: usize,
135 delta: Block,
136 ) -> Result<impl Buf<Block>, Error> {
137 let mut ots = HugePageMemory::zeroed(Self::ots_buf_size(count));
138 self.correlated_send_into(count, delta, &mut ots).await?;
139 Ok(ots)
140 }
141
142 #[tracing::instrument(target = "cryprot_metrics", level = Level::TRACE, skip_all, fields(phase = phase::SILENT_CORRELATED_EXTENSION))]
143 pub async fn correlated_send_into(
144 &mut self,
145 count: usize,
146 delta: Block,
147 ots: &mut impl Buf<Block>,
148 ) -> Result<(), Error> {
149 let mult_type = MultType::default();
150 let conf = Config::configure(count, mult_type);
151 let pprf_conf = PprfConfig::from(conf);
152 assert!(
153 ots.len() >= pprf_conf.size(),
154 "ots Buf not big enough. Allocate at least Self::ots_buf_size"
155 );
156
157 let mal_check_ot_count = S::MALICIOUS_SECURITY as usize * SECURITY_PARAMETER;
158 let base_ot_count = pprf_conf.base_ot_count().next_multiple_of(128) + mal_check_ot_count;
159
160 let mut base_ots = self.ot_sender.send(base_ot_count).await?;
162
163 let mal_check_ots = base_ots.split_off(base_ot_count - mal_check_ot_count);
164
165 base_ots.truncate(pprf_conf.base_ot_count());
166
167 let pprf_sender =
168 RegularPprfSender::new_with_conf(self.conn.sub_connection(), pprf_conf, base_ots);
169 let mut B = mem::take(ots);
170 pprf_sender
171 .expand(delta, self.rng.random(), conf.pprf_out_fmt(), &mut B)
172 .await?;
173
174 if S::MALICIOUS_SECURITY {
175 self.ferret_mal_check(delta, &mut B, mal_check_ots).await?;
176 }
177
178 let enc = Encoder::new(count, mult_type);
179 *ots = enc.send_compress(B).await;
180 Ok(())
181 }
182
183 #[tracing::instrument(target = "cryprot_metrics", level = Level::TRACE, skip_all, fields(phase = phase::MALICIOUS_CHECK))]
184 async fn ferret_mal_check(
185 &mut self,
186 delta: Block,
187 B: &mut impl Buf<Block>,
188 mal_check_ots: Vec<[Block; 2]>,
189 ) -> Result<(), Error> {
190 assert_eq!(SECURITY_PARAMETER, mal_check_ots.len());
191 let (mut tx, mut rx) = self.conn.request_response_stream().await?;
192 let mal_check_seed: Block = rx.next().await.ok_or(Error::MissingReceiverSeed)??;
193
194 let owned_B = mem::take(B);
195 let jh = spawn_compute(move || {
196 let mut xx = mal_check_seed;
197 let (sum_low, sum_high) = owned_B.iter().fold(
198 (Block::ZERO, Block::ZERO),
199 |(mut sum_low, mut sum_high), b| {
200 let (low, high) = xx.clmul(b);
201 sum_low ^= low;
202 sum_high ^= high;
203 xx = xx.gf_mul(&mal_check_seed);
204 (sum_low, sum_high)
205 },
206 );
207 (Block::gf_reduce(&sum_low, &sum_high), owned_B)
208 });
209
210 let mut receiver = NoisyVoleReceiver::new(self.conn.sub_connection());
211 let a = receiver.receive(vec![delta], mal_check_ots).await?;
212
213 let (my_sum, owned_B) = jh.await.expect("worker panic");
214 *B = owned_B;
215
216 let my_hash = (my_sum ^ a[0]).ro_hash();
217 tx.send(my_hash).await?;
218
219 Ok(())
220 }
221}
222
223pub struct SilentOtReceiver<S> {
224 conn: Connection,
225 ot_receiver: OtExtensionReceiver<S>,
226 rng: StdRng,
227}
228
229impl<S: Security> SilentOtReceiver<S> {
230 pub fn new(mut conn: Connection) -> Self {
231 let ot_receiver = OtExtensionReceiver::new(conn.sub_connection());
232 Self {
233 conn,
234 ot_receiver,
235 rng: StdRng::from_os_rng(),
236 }
237 }
238
239 pub fn ots_buf_size(count: usize) -> usize {
241 let conf = Config::configure(count, MultType::default());
242 let pprf_conf = PprfConfig::from(conf);
243 pprf_conf.size()
244 }
245
246 pub async fn random_receive(
247 &mut self,
248 count: usize,
249 ) -> Result<(impl Buf<Block>, Vec<Choice>), Error> {
250 let mut ots = HugePageMemory::zeroed(Self::ots_buf_size(count));
251 let choices = self.random_receive_into(count, &mut ots).await?;
252 Ok((ots, choices))
253 }
254
255 #[tracing::instrument(target = "cryprot_metrics", level = Level::TRACE, skip_all, fields(phase = phase::SILENT_RANDOM_EXTENSION))]
256 pub async fn random_receive_into(
257 &mut self,
258 count: usize,
259 ots: &mut impl Buf<Block>,
260 ) -> Result<Vec<Choice>, Error> {
261 self.internal_correlated_receive_into(count, ChoiceBitPacking::Packed, ots)
262 .await?;
263
264 let mut ots_buf = mem::take(ots);
265 let (ots_buf, choices) = spawn_compute(move || {
266 let choices = ots_buf
267 .iter_mut()
268 .map(|block| {
269 let choice = Choice::from(block.lsb() as u8);
270 *block &= Block::MASK_LSB;
271 choice
272 })
273 .collect();
274
275 if S::MALICIOUS_SECURITY {
276 FIXED_KEY_HASH.tccr_hash_slice_mut(&mut ots_buf, Block::from);
277 } else {
278 FIXED_KEY_HASH.cr_hash_slice_mut(&mut ots_buf);
279 }
280 (ots_buf, choices)
281 })
282 .await
283 .expect("worker panic");
284 *ots = ots_buf;
285 Ok(choices)
286 }
287
288 pub async fn correlated_receive(
289 &mut self,
290 count: usize,
291 ) -> Result<(impl Buf<Block>, Vec<Choice>), Error> {
292 let mut ots = HugePageMemory::zeroed(Self::ots_buf_size(count));
293 let choices = self.correlated_receive_into(count, &mut ots).await?;
294 Ok((ots, choices))
295 }
296
297 #[tracing::instrument(target = "cryprot_metrics", level = Level::TRACE, skip_all, fields(phase = phase::SILENT_CORRELATED_EXTENSION))]
298 pub async fn correlated_receive_into(
299 &mut self,
300 count: usize,
301 ots: &mut impl Buf<Block>,
302 ) -> Result<Vec<Choice>, Error> {
303 self.internal_correlated_receive_into(count, ChoiceBitPacking::NotPacked, ots)
304 .await
305 .map(|cb| cb.expect("not choice packed"))
306 }
307
308 async fn internal_correlated_receive_into(
309 &mut self,
310 count: usize,
311 cb_packing: ChoiceBitPacking,
312 ots: &mut impl Buf<Block>,
313 ) -> Result<Option<Vec<Choice>>, Error> {
314 let mult_type = MultType::default();
315 let conf = Config::configure(count, mult_type);
316 let pprf_conf = PprfConfig::from(conf);
317 assert_eq!(ots.len(), pprf_conf.size());
318
319 let base_choices = pprf_conf.sample_choice_bits(&mut self.rng);
320 let noisy_points = pprf_conf.get_points(conf.pprf_out_fmt(), &base_choices);
321
322 let mut base_choices_subtle: Vec<_> =
323 base_choices.iter().copied().map(Choice::from).collect();
324 base_choices_subtle.resize(
328 pprf_conf.base_ot_count().next_multiple_of(128),
329 Choice::from(0),
330 );
331
332 let mut mal_check_seed = Block::ZERO;
333 let mut mal_check_x = Block::ZERO;
334 if S::MALICIOUS_SECURITY {
335 mal_check_seed = self.rng.random();
336
337 for &p in &noisy_points {
338 mal_check_x ^= mal_check_seed.gf_pow(p as u64 + 1);
339 }
340 base_choices_subtle.extend(mal_check_x.bits().map(|b| Choice::from(b as u8)));
341 }
342
343 let mut base_ots = self.ot_receiver.receive(&base_choices_subtle).await?;
344 let mal_check_ots = base_ots
345 .split_off(base_ots.len() - (S::MALICIOUS_SECURITY as usize * SECURITY_PARAMETER));
346
347 base_ots.truncate(pprf_conf.base_ot_count());
348
349 let pprf_receiver = RegularPprfReceiver::new_with_conf(
350 self.conn.sub_connection(),
351 pprf_conf,
352 base_ots,
353 base_choices,
354 );
355 let mut A = mem::take(ots);
356 pprf_receiver.expand(conf.pprf_out_fmt(), &mut A).await?;
357
358 if S::MALICIOUS_SECURITY {
359 self.ferret_mal_check(&mut A, mal_check_seed, mal_check_x, mal_check_ots)
360 .await?;
361 }
362
363 let enc = Encoder::new(count, mult_type);
364 let (A, choices) = enc.receive_compress(A, noisy_points, cb_packing).await;
365 *ots = A;
366 Ok(choices)
367 }
368
369 #[tracing::instrument(target = "cryprot_metrics", level = Level::TRACE, skip_all, fields(phase = phase::MALICIOUS_CHECK))]
370 async fn ferret_mal_check(
371 &mut self,
372 A: &mut impl Buf<Block>,
373 mal_check_seed: Block,
374 mal_check_x: Block,
375 mal_check_ots: Vec<Block>,
376 ) -> Result<(), Error> {
377 assert_eq!(SECURITY_PARAMETER, mal_check_ots.len());
378 let (mut tx, mut rx) = self.conn.request_response_stream().await?;
379 tx.send(mal_check_seed).await?;
380
381 let owned_A = mem::take(A);
382 let jh = spawn_compute(move || {
383 let mut xx = mal_check_seed;
384 let (sum_low, sum_high) = owned_A.iter().fold(
385 (Block::ZERO, Block::ZERO),
386 |(mut sum_low, mut sum_high), a| {
387 let (low, high) = xx.clmul(a);
388 sum_low ^= low;
389 sum_high ^= high;
390 xx = xx.gf_mul(&mal_check_seed);
391 (sum_low, sum_high)
392 },
393 );
394 (Block::gf_reduce(&sum_low, &sum_high), owned_A)
395 });
396
397 let mut sender = NoisyVoleSender::new(self.conn.sub_connection());
398 let b = sender.send(1, mal_check_x, mal_check_ots).await?;
399
400 let (my_sum, owned_A) = jh.await.expect("worker panic");
401 *A = owned_A;
402
403 let my_hash = (my_sum ^ b[0]).ro_hash();
404
405 let their_hash: Hash = rx.next().await.ok_or(Error::MissingSenderHash)??;
406 if my_hash != their_hash {
407 return Err(Error::MaliciousCheck);
408 }
409 Ok(())
410 }
411}
412
413impl SemiHonest for SilentOtSender<SemiHonestMarker> {}
414impl SemiHonest for SilentOtReceiver<SemiHonestMarker> {}
415
416impl SemiHonest for SilentOtSender<MaliciousMarker> {}
417impl SemiHonest for SilentOtReceiver<MaliciousMarker> {}
418impl Malicious for SilentOtSender<MaliciousMarker> {}
419impl Malicious for SilentOtReceiver<MaliciousMarker> {}
420
421impl<S> Connected for SilentOtSender<S> {
422 fn connection(&mut self) -> &mut Connection {
423 &mut self.conn
424 }
425}
426
427impl<S: Security> RandChoiceRotSender for SilentOtSender<S> {}
428
429impl<S: Security> RotSender for SilentOtSender<S> {
430 type Error = Error;
431
432 async fn send_into(&mut self, ots: &mut impl Buf<[Block; 2]>) -> Result<(), Self::Error> {
433 self.random_sent_into(ots.len(), ots).await?;
434 Ok(())
435 }
436}
437
438impl<S> Connected for SilentOtReceiver<S> {
439 fn connection(&mut self) -> &mut Connection {
440 &mut self.conn
441 }
442}
443
444impl<S: Security> RandChoiceRotReceiver for SilentOtReceiver<S> {
445 type Error = Error;
446
447 async fn rand_choice_receive_into(
448 &mut self,
449 ots: &mut impl Buf<Block>,
450 ) -> Result<Vec<Choice>, Self::Error> {
451 let count = ots.len();
452 ots.grow_zeroed(Self::ots_buf_size(count));
453 let choices = self.random_receive_into(count, ots).await?;
454 Ok(choices)
455 }
456}
457
458#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
459enum ChoiceBitPacking {
460 #[default]
461 Packed,
462 NotPacked,
463}
464
465#[derive(Debug, Clone, Copy, PartialEq, Eq)]
466struct Config {
467 num_partitions: usize,
468 size_per: usize,
469 mult_type: MultType,
470}
471
472impl Config {
473 fn configure(num_ots: usize, mult_type: MultType) -> Self {
474 let min_dist = match mult_type {
475 MultType::ExConv7x24 => 0.15,
476 MultType::ExConv21x24 => 0.2,
477 };
478 let num_partitions = get_reg_noise_weight(min_dist, num_ots * SCALER, SECURITY_PARAMETER);
479 let size_per = 4.max(
480 (num_ots * SCALER)
481 .div_ceil(num_partitions)
482 .next_multiple_of(2),
483 );
484
485 Self {
486 num_partitions,
487 size_per,
488 mult_type,
489 }
490 }
491
492 fn pprf_out_fmt(&self) -> cryprot_pprf::OutFormat {
493 cryprot_pprf::OutFormat::Interleaved
494 }
495}
496
497impl From<Config> for PprfConfig {
498 fn from(value: Config) -> Self {
499 Self::new(value.size_per, value.num_partitions)
500 }
501}
502
503struct Encoder {
504 code: ExConvCode,
505}
506
507impl Encoder {
508 fn new(num_ots: usize, mult_type: MultType) -> Self {
509 let expander_weight = match mult_type {
510 MultType::ExConv7x24 => 7,
511 MultType::ExConv21x24 => 21,
512 };
513 let code = ExConvCode::new_with_conf(
514 num_ots,
515 ExConvCodeConfig {
516 code_size: num_ots * SCALER,
517 expander_weight,
518 ..Default::default()
519 },
520 );
521 assert_eq!(code.conf().accumulator_size, 24);
522 Self { code }
523 }
524
525 async fn send_compress<B: Buf<Block>>(self, mut b: B) -> B {
526 spawn_compute(move || {
527 self.code.dual_encode(&mut b[..self.code.conf().code_size]);
528 b.set_len(self.code.message_size());
529 b
530 })
531 .await
532 .expect("worker panic")
533 }
534
535 async fn receive_compress<B: Buf<Block>>(
536 self,
537 mut a: B,
538 noisy_points: Vec<usize>,
539 cb_packing: ChoiceBitPacking,
540 ) -> (B, Option<Vec<Choice>>) {
541 let jh = spawn_compute(move || {
542 let (mut a, cb) = if cb_packing == ChoiceBitPacking::Packed {
543 let mask_lsb = Block::ONES ^ Block::ONE;
545 for block in a.iter_mut() {
546 *block &= mask_lsb;
547 }
548
549 for idx in noisy_points {
550 a[idx] |= Block::ONE
551 }
552
553 self.code.dual_encode(&mut a[..self.code.conf().code_size]);
554 (a, None::<Vec<Choice>>)
555 } else {
556 self.code.dual_encode(&mut a[..self.code.conf().code_size]);
557 let mut choices = vec![0_u8; self.code.conf().code_size];
558 for idx in noisy_points {
559 if idx < choices.len() {
560 choices[idx] = 1;
561 }
562 }
563 self.code.dual_encode(&mut choices);
564 let mut choices: Vec<_> = choices.into_iter().map(Choice::from).collect();
565 choices.truncate(self.code.message_size());
566 (a, Some(choices))
567 };
568
569 a.set_len(self.code.message_size());
570 (a, cb)
571 });
572 jh.await.expect("worker panic")
573 }
574}
575
576#[allow(non_snake_case)]
577fn get_reg_noise_weight(min_dist_ratio: f64, N: usize, sec_param: usize) -> usize {
578 assert!(min_dist_ratio <= 0.5 && min_dist_ratio > 0.0);
579 let d = (1.0 - 2.0 * min_dist_ratio).log2();
580 let mut t = 40.max((-(sec_param as f64) / d) as usize);
581 if N < 512 {
582 t = t.max(64);
583 }
584 t.next_multiple_of(cryprot_pprf::PARALLEL_TREES)
585}
586
587#[cfg(test)]
588mod tests {
589 use cryprot_core::Block;
590 use cryprot_net::testing::{init_tracing, local_conn};
591 use subtle::Choice;
592
593 use crate::{
594 RandChoiceRotReceiver, RotSender,
595 silent_ot::{
596 MaliciousSilentOtReceiver, MaliciousSilentOtSender, SemiHonestSilentOtReceiver,
597 SemiHonestSilentOtSender,
598 },
599 };
600
601 fn check_correlated(a: &[Block], b: &[Block], choice: Option<&[Choice]>, delta: Block) {
602 {
603 let n = a.len();
604 assert_eq!(b.len(), n);
605 if let Some(choice) = choice {
606 assert_eq!(choice.len(), n)
607 }
608 let mask = if choice.is_some() {
609 Block::ONES
611 } else {
612 Block::ONES ^ Block::ONE
614 };
615
616 for i in 0..n {
617 let m1 = a[i];
618 let c = if let Some(choice) = choice {
619 choice[i].unwrap_u8() as usize
620 } else {
621 ((m1 & Block::ONE) == Block::ONE) as usize
623 };
624 let m1 = m1 & mask;
625 let m2a = b[i] & mask;
626 let m2b = (b[i] ^ delta) & mask;
627
628 let eqq = [m1 == m2a, m1 == m2b];
629 assert!(
630 eqq[c] && !eqq[c ^ 1],
631 "Blocks at {i} differ. Choice: {c} {m1:?}, {m2a:?}, {m2b:?}"
632 );
633 assert!(eqq[0] || eqq[1]);
634 }
635 }
636 }
637
638 fn check_random(count: usize, s_ot: &[[Block; 2]], r_ot: &[Block], c: &[Choice]) {
639 assert_eq!(s_ot.len(), count);
640 assert_eq!(r_ot.len(), count);
641 assert_eq!(c.len(), count);
642
643 for i in 0..count {
644 assert_eq!(
645 r_ot[i],
646 s_ot[i][c[i].unwrap_u8() as usize],
647 "Difference at OT {i}\nr_ot: {:?}\ns_ot: {:?}\nc: {}",
648 r_ot[i],
649 s_ot[i],
650 c[i].unwrap_u8()
651 );
652 }
653 }
654
655 #[tokio::test]
656 async fn correlated_silent_ot() {
657 let _g = init_tracing();
658 let (c1, c2) = local_conn().await.unwrap();
659
660 let mut sender = SemiHonestSilentOtSender::new(c1);
661 let mut receiver = SemiHonestSilentOtReceiver::new(c2);
662 let delta = Block::ONES;
663 let count = 2_usize.pow(11);
664
665 let (s_ot, (r_ot, choices)) = tokio::try_join!(
666 sender.correlated_send(count, delta),
667 receiver.correlated_receive(count)
668 )
669 .unwrap();
670
671 assert_eq!(s_ot.len(), count);
672 assert_eq!(r_ot.len(), count);
673
674 check_correlated(&r_ot, &s_ot, Some(&choices), delta);
675 }
676
677 #[tokio::test]
678 async fn random_silent_ot() {
679 let _g = init_tracing();
680 let (c1, c2) = local_conn().await.unwrap();
681
682 let mut sender = SemiHonestSilentOtSender::new(c1);
683 let mut receiver = SemiHonestSilentOtReceiver::new(c2);
684 let count = 2_usize.pow(11);
685
686 let (s_ot, (r_ot, choices)) =
687 tokio::try_join!(sender.random_send(count), receiver.random_receive(count)).unwrap();
688
689 check_random(count, &s_ot, &r_ot[..], &choices);
690 }
691
692 #[tokio::test]
693 async fn test_rot_trait_for_silent_ot() {
694 let _g = init_tracing();
695 let (c1, c2) = local_conn().await.unwrap();
696
697 let mut sender = SemiHonestSilentOtSender::new(c1);
698 let mut receiver = SemiHonestSilentOtReceiver::new(c2);
699 let count = 2_usize.pow(11);
700
701 let (s_ot, (r_ot, c)) =
702 tokio::try_join!(sender.send(count), receiver.rand_choice_receive(count)).unwrap();
703
704 check_random(count, &s_ot, &r_ot, &c);
705 }
706
707 #[tokio::test]
708 async fn test_malicious_silent_ot() {
709 let _g = init_tracing();
710 let (c1, c2) = local_conn().await.unwrap();
711
712 let mut sender = MaliciousSilentOtSender::new(c1);
713 let mut receiver = MaliciousSilentOtReceiver::new(c2);
714 let count = 2_usize.pow(11);
715
716 let (s_ot, (r_ot, choices)) =
717 tokio::try_join!(sender.random_send(count), receiver.random_receive(count)).unwrap();
718
719 check_random(count, &s_ot, &r_ot[..], &choices);
720 }
721
722 #[cfg(not(debug_assertions))]
723 #[tokio::test]
724 async fn silent_ot_comm() {
727 let _g = init_tracing();
728 let (c1, c2) = local_conn().await.unwrap();
729
730 let mut sender = SemiHonestSilentOtSender::new(c1);
731 let mut receiver = SemiHonestSilentOtReceiver::new(c2);
732 let delta = Block::ONES;
733 let count = 2_usize.pow(18);
734
735 let (s_ot, (r_ot, choices)) = tokio::try_join!(
736 sender.correlated_send(count, delta),
737 receiver.correlated_receive(count)
738 )
739 .unwrap();
740
741 assert_eq!(s_ot.len(), count);
742
743 check_correlated(&r_ot, &s_ot, Some(&choices), delta);
744 }
745}