1mod executor;
9mod network_sender;
10mod result;
11
12#[cfg(feature = "benchmarks")]
13pub use executor::{Executor, ExecutorMessage};
14#[cfg(not(feature = "benchmarks"))]
15use executor::{Executor, ExecutorMessage};
16use rand::thread_rng;
17pub use result::{ResultHandle, ResultId, ResultValue};
18
19use futures::executor::block_on;
20use tracing::log;
21
22use crossbeam::queue::SegQueue;
23use kanal::Sender as KanalSender;
24use std::{
25 fmt::{Debug, Formatter, Result as FmtResult},
26 sync::{
27 atomic::{AtomicUsize, Ordering},
28 Arc, Mutex,
29 },
30};
31use tokio::sync::broadcast::{self, Sender as BroadcastSender};
32
33use itertools::Itertools;
34
35use crate::{
36 algebra::{
37 authenticated_scalar::AuthenticatedScalarResult,
38 authenticated_stark_point::AuthenticatedStarkPointResult,
39 mpc_scalar::MpcScalarResult,
40 mpc_stark_point::MpcStarkPointResult,
41 scalar::{BatchScalarResult, Scalar, ScalarResult},
42 stark_curve::{BatchStarkPointResult, StarkPoint, StarkPointResult},
43 },
44 beaver::SharedValueSource,
45 network::{MpcNetwork, NetworkOutbound, NetworkPayload, PartyId},
46 PARTY0,
47};
48
49use self::{
50 network_sender::NetworkSender,
51 result::{OpResult, ResultWaiter},
52};
53
54const RESULT_ZERO: ResultId = 0;
56const RESULT_ONE: ResultId = 1;
58const RESULT_IDENTITY: ResultId = 2;
60
61const N_CONSTANT_RESULTS: usize = 3;
63
64const DEFAULT_SIZE_HINT: usize = 10_000;
66
67pub type OperationId = usize;
69
70#[derive(Clone)]
75pub struct Operation {
76 id: OperationId,
78 result_id: ResultId,
80 output_arity: usize,
82 inflight_args: usize,
84 args: Vec<ResultId>,
86 op_type: OperationType,
88}
89
90impl Operation {
91 pub fn result_ids(&self) -> Vec<ResultId> {
93 (self.result_id..self.result_id + self.output_arity).collect_vec()
94 }
95}
96
97impl Debug for Operation {
98 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
99 write!(f, "Operation {}", self.id)
100 }
101}
102
103pub enum OperationType {
105 Gate {
107 function: Box<dyn FnOnce(Vec<ResultValue>) -> ResultValue + Send + Sync>,
109 },
110 GateBatch {
114 function: Box<dyn FnOnce(Vec<ResultValue>) -> Vec<ResultValue> + Send + Sync>,
116 },
117 Network {
119 function: Box<dyn FnOnce(Vec<ResultValue>) -> NetworkPayload + Send + Sync>,
121 },
122}
123
124impl Clone for OperationType {
127 fn clone(&self) -> Self {
128 panic!("cannot clone `OperationType`")
129 }
130}
131
132impl Debug for OperationType {
133 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
134 match self {
135 OperationType::Gate { .. } => write!(f, "Gate"),
136 OperationType::GateBatch { .. } => write!(f, "GateBatch"),
137 OperationType::Network { .. } => write!(f, "Network"),
138 }
139 }
140}
141
142#[derive(Clone)]
150pub struct MpcFabric {
151 #[cfg(not(feature = "benchmarks"))]
153 inner: Arc<FabricInner>,
154 #[cfg(feature = "benchmarks")]
156 pub inner: Arc<FabricInner>,
157 #[cfg(not(feature = "benchmarks"))]
163 mac_key: Option<Arc<MpcScalarResult>>,
164 #[cfg(feature = "benchmarks")]
166 pub mac_key: Option<Arc<MpcScalarResult>>,
167 #[cfg(not(feature = "benchmarks"))]
169 shutdown: BroadcastSender<()>,
170 #[cfg(feature = "benchmarks")]
172 pub shutdown: BroadcastSender<()>,
173}
174
175impl Debug for MpcFabric {
176 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
177 write!(f, "MpcFabric")
178 }
179}
180
181#[derive(Clone)]
184pub struct FabricInner {
185 party_id: u64,
187 next_result_id: Arc<AtomicUsize>,
189 next_op_id: Arc<AtomicUsize>,
191 execution_queue: Arc<SegQueue<ExecutorMessage>>,
193 outbound_queue: KanalSender<NetworkOutbound>,
195 beaver_source: Arc<Mutex<Box<dyn SharedValueSource>>>,
197}
198
199impl Debug for FabricInner {
200 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
201 write!(f, "FabricInner")
202 }
203}
204
205impl FabricInner {
206 pub fn new<S: 'static + SharedValueSource>(
208 party_id: u64,
209 execution_queue: Arc<SegQueue<ExecutorMessage>>,
210 outbound_queue: KanalSender<NetworkOutbound>,
211 beaver_source: S,
212 ) -> Self {
213 let zero = ResultValue::Scalar(Scalar::zero());
216 let one = ResultValue::Scalar(Scalar::one());
217 let identity = ResultValue::Point(StarkPoint::identity());
218
219 for initial_result in vec![
220 OpResult {
221 id: RESULT_ZERO,
222 value: zero,
223 },
224 OpResult {
225 id: RESULT_ONE,
226 value: one,
227 },
228 OpResult {
229 id: RESULT_IDENTITY,
230 value: identity,
231 },
232 ]
233 .into_iter()
234 {
235 execution_queue.push(ExecutorMessage::Result(initial_result));
236 }
237
238 let next_result_id = Arc::new(AtomicUsize::new(N_CONSTANT_RESULTS));
239 let next_op_id = Arc::new(AtomicUsize::new(0));
240
241 Self {
242 party_id,
243 next_result_id,
244 next_op_id,
245 execution_queue,
246 outbound_queue,
247 beaver_source: Arc::new(Mutex::new(Box::new(beaver_source))),
248 }
249 }
250
251 pub(crate) fn register_waiter(&self, waiter: ResultWaiter) {
253 self.execution_queue
254 .push(ExecutorMessage::NewWaiter(waiter));
255 }
256
257 pub(crate) fn shutdown(&self) {
259 self.execution_queue.push(ExecutorMessage::Shutdown)
260 }
261
262 fn new_result_id(&self) -> ResultId {
268 self.next_result_id.fetch_add(1, Ordering::Relaxed)
269 }
270
271 fn new_op_id(&self) -> OperationId {
273 self.next_op_id.fetch_add(1, Ordering::Relaxed)
274 }
275
276 pub(crate) fn zero(&self) -> ResultId {
278 RESULT_ZERO
279 }
280
281 pub(crate) fn one(&self) -> ResultId {
283 RESULT_ONE
284 }
285
286 pub(crate) fn curve_identity(&self) -> ResultId {
288 RESULT_IDENTITY
289 }
290
291 pub(crate) fn allocate_value(&self, value: ResultValue) -> ResultId {
297 let id = self.new_result_id();
299 self.execution_queue
300 .push(ExecutorMessage::Result(OpResult { id, value }));
301
302 id
303 }
304
305 pub(crate) fn allocate_shared_value(
307 &self,
308 my_share: ResultValue,
309 their_share: ResultValue,
310 ) -> ResultId {
311 let id = self.new_result_id();
313 self.execution_queue.push(ExecutorMessage::Result(OpResult {
314 id,
315 value: my_share,
316 }));
317
318 if let Err(e) = self.outbound_queue.send(NetworkOutbound {
320 result_id: id,
321 payload: their_share.into(),
322 }) {
323 log::error!("error sending share to counterparty: {e:?}");
324 }
325
326 id
327 }
328
329 pub(crate) fn receive_value(&self) -> ResultId {
334 self.new_result_id()
335 }
336
337 pub(crate) fn new_op(
343 &self,
344 args: Vec<ResultId>,
345 output_arity: usize,
346 op_type: OperationType,
347 ) -> Vec<ResultId> {
348 if matches!(op_type, OperationType::Gate { .. }) {
349 assert_eq!(output_arity, 1, "gate operations must have arity 1");
350 }
351
352 let ids = (0..output_arity)
354 .map(|_| self.new_result_id())
355 .collect_vec();
356
357 let op = Operation {
359 id: self.new_op_id(),
360 result_id: ids[0],
361 output_arity,
362 args,
363 inflight_args: 0,
364 op_type,
365 };
366
367 self.execution_queue.push(ExecutorMessage::Op(op));
369 ids
370 }
371}
372
373impl MpcFabric {
374 pub fn new<N: 'static + MpcNetwork, S: 'static + SharedValueSource>(
376 network: N,
377 beaver_source: S,
378 ) -> Self {
379 Self::new_with_size_hint(DEFAULT_SIZE_HINT, network, beaver_source)
380 }
381
382 pub fn new_with_size_hint<N: 'static + MpcNetwork, S: 'static + SharedValueSource>(
385 size_hint: usize,
386 network: N,
387 beaver_source: S,
388 ) -> Self {
389 let execution_queue = Arc::new(SegQueue::new());
391
392 let (outbound_sender, outbound_receiver) = kanal::unbounded_async();
393 let (shutdown_sender, shutdown_receiver) = broadcast::channel(1 );
394
395 let fabric = FabricInner::new(
397 network.party_id(),
398 execution_queue.clone(),
399 outbound_sender.to_sync(),
400 beaver_source,
401 );
402
403 let network_sender = NetworkSender::new(
405 outbound_receiver,
406 execution_queue.clone(),
407 network,
408 shutdown_receiver,
409 );
410 tokio::task::spawn_blocking(move || block_on(network_sender.run()));
411
412 let executor = Executor::new(size_hint, execution_queue, fabric.clone());
413 tokio::task::spawn_blocking(move || executor.run());
414
415 let mut self_ = Self {
417 inner: Arc::new(fabric.clone()),
418 shutdown: shutdown_sender,
419 mac_key: None,
420 };
421
422 let mac_key_id = fabric.allocate_value(ResultValue::Scalar(
424 fabric
425 .beaver_source
426 .lock()
427 .expect("beaver source poisoned")
428 .next_shared_value(),
429 ));
430 let mac_key = MpcScalarResult::new_shared(ResultHandle::new(mac_key_id, self_.clone()));
431
432 self_.mac_key.replace(Arc::new(mac_key));
434
435 self_
436 }
437
438 pub fn party_id(&self) -> PartyId {
440 self.inner.party_id
441 }
442
443 pub fn shutdown(self) {
445 log::debug!("shutting down fabric");
446 self.inner.shutdown();
447 self.shutdown
448 .send(())
449 .expect("error sending shutdown signal");
450 }
451
452 pub fn register_waiter(&self, waiter: ResultWaiter) {
454 self.inner.register_waiter(waiter);
455 }
456
457 pub(crate) fn borrow_mac_key(&self) -> &MpcScalarResult {
459 self.mac_key.as_ref().unwrap()
461 }
462
463 pub fn zero(&self) -> ScalarResult {
469 ResultHandle::new(self.inner.zero(), self.clone())
470 }
471
472 fn zero_shared(&self) -> MpcScalarResult {
474 MpcScalarResult::new_shared(self.zero())
475 }
476
477 pub fn zero_authenticated(&self) -> AuthenticatedScalarResult {
481 let zero_value = self.zero();
482 let share_value = self.zero_shared();
483 let mac_value = self.zero_shared();
484
485 AuthenticatedScalarResult {
486 share: share_value,
487 mac: mac_value,
488 public_modifier: zero_value,
489 }
490 }
491
492 pub fn zeros_authenticated(&self, n: usize) -> Vec<AuthenticatedScalarResult> {
494 let val = self.zero_authenticated();
495 (0..n).map(|_| val.clone()).collect_vec()
496 }
497
498 pub fn one(&self) -> ScalarResult {
500 ResultHandle::new(self.inner.one(), self.clone())
501 }
502
503 fn one_shared(&self) -> MpcScalarResult {
505 MpcScalarResult::new_shared(self.one())
506 }
507
508 pub fn one_authenticated(&self) -> AuthenticatedScalarResult {
512 if self.party_id() == PARTY0 {
513 let zero_value = self.zero();
514 let share_value = self.zero_shared();
515 let mac_value = self.zero_shared();
516
517 AuthenticatedScalarResult {
518 share: share_value,
519 mac: mac_value,
520 public_modifier: zero_value,
521 }
522 } else {
523 let zero_value = self.zero();
524 let share_value = self.one_shared();
525 let mac_value = self.borrow_mac_key().clone();
526
527 AuthenticatedScalarResult {
528 share: share_value,
529 mac: mac_value,
530 public_modifier: zero_value,
531 }
532 }
533 }
534
535 pub fn ones_authenticated(&self, n: usize) -> Vec<AuthenticatedScalarResult> {
537 let val = self.one_authenticated();
538 (0..n).map(|_| val.clone()).collect_vec()
539 }
540
541 pub fn curve_identity(&self) -> ResultHandle<StarkPoint> {
543 ResultHandle::new(self.inner.curve_identity(), self.clone())
544 }
545
546 fn curve_identity_shared(&self) -> MpcStarkPointResult {
548 MpcStarkPointResult::new_shared(self.curve_identity())
549 }
550
551 pub fn curve_identity_authenticated(&self) -> AuthenticatedStarkPointResult {
555 let identity_val = self.curve_identity();
556 let share_value = self.curve_identity_shared();
557 let mac_value = self.curve_identity_shared();
558
559 AuthenticatedStarkPointResult {
560 share: share_value,
561 mac: mac_value,
562 public_modifier: identity_val,
563 }
564 }
565
566 fn allocate_shared_value<T: From<ResultValue>>(
572 &self,
573 my_share: ResultValue,
574 their_share: ResultValue,
575 ) -> ResultHandle<T> {
576 let id = self.inner.allocate_shared_value(my_share, their_share);
577 ResultHandle::new(id, self.clone())
578 }
579
580 pub fn share_scalar<T: Into<Scalar>>(
582 &self,
583 val: T,
584 sender: PartyId,
585 ) -> AuthenticatedScalarResult {
586 let scalar: ScalarResult = if self.party_id() == sender {
587 let scalar_val = val.into();
588 let mut rng = thread_rng();
589 let random = Scalar::random(&mut rng);
590
591 let (my_share, their_share) = (scalar_val - random, random);
592 self.allocate_shared_value(
593 ResultValue::Scalar(my_share),
594 ResultValue::Scalar(their_share),
595 )
596 } else {
597 self.receive_value()
598 };
599
600 AuthenticatedScalarResult::new_shared(scalar)
601 }
602
603 pub fn batch_share_scalar<T: Into<Scalar>>(
605 &self,
606 vals: Vec<T>,
607 sender: PartyId,
608 ) -> Vec<AuthenticatedScalarResult> {
609 let n = vals.len();
610 let shares: BatchScalarResult = if self.party_id() == sender {
611 let vals = vals.into_iter().map(|val| val.into()).collect_vec();
612 let mut rng = thread_rng();
613
614 let peer_shares = (0..vals.len())
615 .map(|_| Scalar::random(&mut rng))
616 .collect_vec();
617 let my_shares = vals
618 .iter()
619 .zip(peer_shares.iter())
620 .map(|(val, share)| val - share)
621 .collect_vec();
622
623 self.allocate_shared_value(
624 ResultValue::ScalarBatch(my_shares),
625 ResultValue::ScalarBatch(peer_shares),
626 )
627 } else {
628 self.receive_value()
629 };
630
631 AuthenticatedScalarResult::new_shared_from_batch_result(shares, n)
632 }
633
634 pub fn share_point(&self, val: StarkPoint, sender: PartyId) -> AuthenticatedStarkPointResult {
636 let point: StarkPointResult = if self.party_id() == sender {
637 let mut rng = thread_rng();
643 let random = Scalar::random(&mut rng);
644 let random_point = random * StarkPoint::generator();
645
646 let (my_share, their_share) = (val - random_point, random_point);
647 self.allocate_shared_value(
648 ResultValue::Point(my_share),
649 ResultValue::Point(their_share),
650 )
651 } else {
652 self.receive_value()
653 };
654
655 AuthenticatedStarkPointResult::new_shared(point)
656 }
657
658 pub fn batch_share_point(
660 &self,
661 vals: Vec<StarkPoint>,
662 sender: PartyId,
663 ) -> Vec<AuthenticatedStarkPointResult> {
664 let n = vals.len();
665 let shares: BatchStarkPointResult = if self.party_id() == sender {
666 let mut rng = thread_rng();
667 let generator = StarkPoint::generator();
668 let peer_shares = (0..vals.len())
669 .map(|_| {
670 let discrete_log = Scalar::random(&mut rng);
671 discrete_log * generator
672 })
673 .collect_vec();
674 let my_shares = vals
675 .iter()
676 .zip(peer_shares.iter())
677 .map(|(val, share)| val - share)
678 .collect_vec();
679
680 self.allocate_shared_value(
681 ResultValue::PointBatch(my_shares),
682 ResultValue::PointBatch(peer_shares),
683 )
684 } else {
685 self.receive_value()
686 };
687
688 AuthenticatedStarkPointResult::new_shared_from_batch_result(shares, n)
689 }
690
691 pub fn allocate_scalar<T: Into<Scalar>>(&self, value: T) -> ResultHandle<Scalar> {
693 let id = self.inner.allocate_value(ResultValue::Scalar(value.into()));
694 ResultHandle::new(id, self.clone())
695 }
696
697 pub fn allocate_scalars<T: Into<Scalar>>(&self, values: Vec<T>) -> Vec<ResultHandle<Scalar>> {
699 values
700 .into_iter()
701 .map(|value| self.allocate_scalar(value))
702 .collect_vec()
703 }
704
705 pub fn allocate_preshared_scalar<T: Into<Scalar>>(
707 &self,
708 value: T,
709 ) -> AuthenticatedScalarResult {
710 let allocated = self.allocate_scalar(value);
711 AuthenticatedScalarResult::new_shared(allocated)
712 }
713
714 pub fn batch_allocate_preshared_scalar<T: Into<Scalar>>(
716 &self,
717 values: Vec<T>,
718 ) -> Vec<AuthenticatedScalarResult> {
719 let values = self.allocate_scalars(values);
720 AuthenticatedScalarResult::new_shared_batch(&values)
721 }
722
723 pub fn allocate_point(&self, value: StarkPoint) -> ResultHandle<StarkPoint> {
725 let id = self.inner.allocate_value(ResultValue::Point(value));
726 ResultHandle::new(id, self.clone())
727 }
728
729 pub fn allocate_points(&self, values: Vec<StarkPoint>) -> Vec<ResultHandle<StarkPoint>> {
731 values
732 .into_iter()
733 .map(|value| self.allocate_point(value))
734 .collect_vec()
735 }
736
737 pub fn send_value<T: From<ResultValue> + Into<NetworkPayload>>(
739 &self,
740 value: ResultHandle<T>,
741 ) -> ResultHandle<T> {
742 self.new_network_op(vec![value.id], |mut args| args.remove(0).into())
743 }
744
745 pub fn send_values<T>(&self, values: &[ResultHandle<T>]) -> ResultHandle<Vec<T>>
747 where
748 T: From<ResultValue>,
749 Vec<T>: Into<NetworkPayload> + From<ResultValue>,
750 {
751 let ids = values.iter().map(|v| v.id).collect_vec();
752 self.new_network_op(ids, |args| {
753 let payload: Vec<T> = args.into_iter().map(|val| val.into()).collect();
754 payload.into()
755 })
756 }
757
758 pub fn receive_value<T: From<ResultValue>>(&self) -> ResultHandle<T> {
760 let id = self.inner.receive_value();
761 ResultHandle::new(id, self.clone())
762 }
763
764 pub fn exchange_value<T: From<ResultValue> + Into<NetworkPayload>>(
769 &self,
770 value: ResultHandle<T>,
771 ) -> ResultHandle<T> {
772 if self.party_id() == PARTY0 {
773 self.send_value(value);
775 self.receive_value()
776 } else {
777 let handle = self.receive_value();
779 self.send_value(value);
780 handle
781 }
782 }
783
784 pub fn exchange_values<T>(&self, values: &[ResultHandle<T>]) -> ResultHandle<Vec<T>>
787 where
788 T: From<ResultValue>,
789 Vec<T>: From<ResultValue> + Into<NetworkPayload>,
790 {
791 if self.party_id() == PARTY0 {
792 self.send_values(values);
793 self.receive_value()
794 } else {
795 let handle = self.receive_value();
796 self.send_values(values);
797 handle
798 }
799 }
800
801 pub fn share_plaintext<T>(&self, value: T, sender: PartyId) -> ResultHandle<T>
803 where
804 T: 'static + From<ResultValue> + Into<NetworkPayload> + Send + Sync,
805 {
806 if self.party_id() == sender {
807 self.new_network_op(vec![], move |_args| value.into())
808 } else {
809 self.receive_value()
810 }
811 }
812
813 pub fn batch_share_plaintext<T>(&self, values: Vec<T>, sender: PartyId) -> ResultHandle<Vec<T>>
815 where
816 T: 'static + From<ResultValue> + Send + Sync,
817 Vec<T>: Into<NetworkPayload> + From<ResultValue>,
818 {
819 self.share_plaintext(values, sender)
820 }
821
822 pub fn new_gate_op<F, T>(&self, args: Vec<ResultId>, function: F) -> ResultHandle<T>
829 where
830 F: 'static + FnOnce(Vec<ResultValue>) -> ResultValue + Send + Sync,
831 T: From<ResultValue>,
832 {
833 let function = Box::new(function);
834 let id = self.inner.new_op(
835 args,
836 1, OperationType::Gate { function },
838 )[0];
839 ResultHandle::new(id, self.clone())
840 }
841
842 pub fn new_batch_gate_op<F, T>(
848 &self,
849 args: Vec<ResultId>,
850 output_arity: usize,
851 function: F,
852 ) -> Vec<ResultHandle<T>>
853 where
854 F: 'static + FnOnce(Vec<ResultValue>) -> Vec<ResultValue> + Send + Sync,
855 T: From<ResultValue>,
856 {
857 let function = Box::new(function);
858 let ids = self
859 .inner
860 .new_op(args, output_arity, OperationType::GateBatch { function });
861 ids.into_iter()
862 .map(|id| ResultHandle::new(id, self.clone()))
863 .collect_vec()
864 }
865
866 pub fn new_network_op<F, T>(&self, args: Vec<ResultId>, function: F) -> ResultHandle<T>
869 where
870 F: 'static + FnOnce(Vec<ResultValue>) -> NetworkPayload + Send + Sync,
871 T: From<ResultValue>,
872 {
873 let function = Box::new(function);
874 let id = self.inner.new_op(
875 args,
876 1, OperationType::Network { function },
878 )[0];
879 ResultHandle::new(id, self.clone())
880 }
881
882 pub fn next_beaver_triple(&self) -> (MpcScalarResult, MpcScalarResult, MpcScalarResult) {
888 let (a, b, c) = self
890 .inner
891 .beaver_source
892 .lock()
893 .expect("beaver source poisoned")
894 .next_triplet();
895
896 let a_val = self.allocate_scalar(a);
897 let b_val = self.allocate_scalar(b);
898 let c_val = self.allocate_scalar(c);
899
900 (
901 MpcScalarResult::new_shared(a_val),
902 MpcScalarResult::new_shared(b_val),
903 MpcScalarResult::new_shared(c_val),
904 )
905 }
906
907 pub fn next_beaver_triple_batch(
909 &self,
910 n: usize,
911 ) -> (
912 Vec<MpcScalarResult>,
913 Vec<MpcScalarResult>,
914 Vec<MpcScalarResult>,
915 ) {
916 let (a_vals, b_vals, c_vals) = self
917 .inner
918 .beaver_source
919 .lock()
920 .expect("beaver source poisoned")
921 .next_triplet_batch(n);
922
923 let a_vals = self
924 .allocate_scalars(a_vals)
925 .into_iter()
926 .map(MpcScalarResult::new_shared)
927 .collect_vec();
928 let b_vals = self
929 .allocate_scalars(b_vals)
930 .into_iter()
931 .map(MpcScalarResult::new_shared)
932 .collect_vec();
933 let c_vals = self
934 .allocate_scalars(c_vals)
935 .into_iter()
936 .map(MpcScalarResult::new_shared)
937 .collect_vec();
938
939 (a_vals, b_vals, c_vals)
940 }
941
942 pub fn next_authenticated_triple(
947 &self,
948 ) -> (
949 AuthenticatedScalarResult,
950 AuthenticatedScalarResult,
951 AuthenticatedScalarResult,
952 ) {
953 let (a, b, c) = self
954 .inner
955 .beaver_source
956 .lock()
957 .expect("beaver source poisoned")
958 .next_triplet();
959
960 let a_val = self.allocate_scalar(a);
961 let b_val = self.allocate_scalar(b);
962 let c_val = self.allocate_scalar(c);
963
964 (
965 AuthenticatedScalarResult::new_shared(a_val),
966 AuthenticatedScalarResult::new_shared(b_val),
967 AuthenticatedScalarResult::new_shared(c_val),
968 )
969 }
970
971 pub fn next_authenticated_triple_batch(
973 &self,
974 n: usize,
975 ) -> (
976 Vec<AuthenticatedScalarResult>,
977 Vec<AuthenticatedScalarResult>,
978 Vec<AuthenticatedScalarResult>,
979 ) {
980 let (a_vals, b_vals, c_vals) = self
981 .inner
982 .beaver_source
983 .lock()
984 .expect("beaver source poisoned")
985 .next_triplet_batch(n);
986
987 let a_allocated = self.allocate_scalars(a_vals);
988 let b_allocated = self.allocate_scalars(b_vals);
989 let c_allocated = self.allocate_scalars(c_vals);
990
991 (
992 AuthenticatedScalarResult::new_shared_batch(&a_allocated),
993 AuthenticatedScalarResult::new_shared_batch(&b_allocated),
994 AuthenticatedScalarResult::new_shared_batch(&c_allocated),
995 )
996 }
997
998 pub fn random_shared_scalars(&self, n: usize) -> Vec<ScalarResult> {
1000 let values_raw = self
1001 .inner
1002 .beaver_source
1003 .lock()
1004 .expect("beaver source poisoned")
1005 .next_shared_value_batch(n);
1006
1007 values_raw
1009 .into_iter()
1010 .map(|value| self.allocate_scalar(value))
1011 .collect_vec()
1012 }
1013
1014 pub fn random_shared_scalars_authenticated(&self, n: usize) -> Vec<AuthenticatedScalarResult> {
1016 let values_raw = self
1017 .inner
1018 .beaver_source
1019 .lock()
1020 .expect("beaver source poisoned")
1021 .next_shared_value_batch(n);
1022
1023 values_raw
1025 .into_iter()
1026 .map(|value| {
1027 let value = self.allocate_scalar(value);
1028 AuthenticatedScalarResult::new_shared(value)
1029 })
1030 .collect_vec()
1031 }
1032
1033 pub fn random_inverse_pair(&self) -> (AuthenticatedScalarResult, AuthenticatedScalarResult) {
1035 let (l, r) = self
1036 .inner
1037 .beaver_source
1038 .lock()
1039 .unwrap()
1040 .next_shared_inverse_pair();
1041 (
1042 AuthenticatedScalarResult::new_shared(self.allocate_scalar(l)),
1043 AuthenticatedScalarResult::new_shared(self.allocate_scalar(r)),
1044 )
1045 }
1046
1047 pub fn random_inverse_pairs(
1049 &self,
1050 n: usize,
1051 ) -> (
1052 Vec<AuthenticatedScalarResult>,
1053 Vec<AuthenticatedScalarResult>,
1054 ) {
1055 let (left, right) = self
1056 .inner
1057 .beaver_source
1058 .lock()
1059 .unwrap()
1060 .next_shared_inverse_pair_batch(n);
1061
1062 let left_right = left.into_iter().chain(right.into_iter()).collect_vec();
1063 let allocated_left_right = self.allocate_scalars(left_right);
1064 let authenticated_left_right =
1065 AuthenticatedScalarResult::new_shared_batch(&allocated_left_right);
1066
1067 let (left, right) = authenticated_left_right.split_at(n);
1069 (left.to_vec(), right.to_vec())
1070 }
1071
1072 pub fn random_shared_bit(&self) -> AuthenticatedScalarResult {
1074 let bit = self
1075 .inner
1076 .beaver_source
1077 .lock()
1078 .expect("beaver source poisoned")
1079 .next_shared_bit();
1080
1081 let bit = self.allocate_scalar(bit);
1082 AuthenticatedScalarResult::new_shared(bit)
1083 }
1084
1085 pub fn random_shared_bits(&self, n: usize) -> Vec<AuthenticatedScalarResult> {
1087 let bits = self
1088 .inner
1089 .beaver_source
1090 .lock()
1091 .expect("beaver source poisoned")
1092 .next_shared_bit_batch(n);
1093
1094 let bits = self.allocate_scalars(bits);
1095 AuthenticatedScalarResult::new_shared_batch(&bits)
1096 }
1097}