From 72c400913f2c374a36e6b6d18cfb670a6d475c7a Mon Sep 17 00:00:00 2001 From: Mikkel Wienberg Madsen Date: Fri, 10 May 2024 13:48:11 +0200 Subject: [PATCH 1/3] Marker traits --- src/algebra/poly.rs | 2 +- src/lib.rs | 3 + src/marker/exptree.rs | 91 +++++++++++++++++++++++ src/marker/mod.rs | 156 ++++++++++++++++++++++++++++++++++++++++ src/net/agency.rs | 65 ++++++++++++++++- src/net/mod.rs | 50 ++++++++----- src/net/network.rs | 25 +++++++ src/protocols/beaver.rs | 20 +++--- src/schemes/feldman.rs | 10 +-- src/schemes/mod.rs | 119 ++++++++++++++++++++++++------ src/schemes/pedersen.rs | 8 +-- src/schemes/rep3.rs | 6 +- src/schemes/shamir.rs | 12 ++-- src/testing/mock.rs | 2 +- 14 files changed, 498 insertions(+), 71 deletions(-) create mode 100644 src/marker/exptree.rs create mode 100644 src/marker/mod.rs diff --git a/src/algebra/poly.rs b/src/algebra/poly.rs index 89cdd11..48bdf8c 100644 --- a/src/algebra/poly.rs +++ b/src/algebra/poly.rs @@ -62,7 +62,7 @@ impl Polynomial { /// /// * `degree`: the degree of the polynomial /// * `rng`: random number generator to use - pub fn random(degree: usize, mut rng: &mut impl RngCore) -> Self { + pub fn random(degree: usize, mut rng: impl RngCore) -> Self { (0..=degree).map(|_| F::random(&mut rng)).collect() } } diff --git a/src/lib.rs b/src/lib.rs index 33e5583..5540876 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,8 @@ #![allow(refining_impl_trait)] #![allow(dead_code)] +#![feature(async_fn_traits)] + mod algebra; pub mod net; pub mod ot; @@ -11,3 +13,4 @@ pub mod schemes; mod help; #[cfg(test)] mod testing; +pub mod marker; diff --git a/src/marker/exptree.rs b/src/marker/exptree.rs new file mode 100644 index 0000000..a2d6205 --- /dev/null +++ b/src/marker/exptree.rs @@ -0,0 +1,91 @@ +use std::{collections::BTreeMap, ops::AsyncFn, sync::{atomic::{AtomicU32, Ordering::SeqCst}, Mutex}}; +use crate::net::Communicate; +#[derive(Clone)] +pub enum Status { + Verified, + Unverified { + parents: (u32, u32), + data: Option, + }, + Failure, +} + +pub struct ExpTree { + tree: Mutex>>, + issuer: AtomicU32, +} + +impl ExpTree { + fn issue(&self) -> u32 { + let curr = self.issuer.fetch_update(SeqCst, SeqCst, |n| Some(n + 1)); + curr.expect("Never fails since lambda always returns Some") + } + + pub fn add_dependent(&self, a: u32, b: u32) -> u32 { + let new = self.issue(); + let status : Status = Status::Unverified { parents: (a, b), data: None }; + { + let mut tree = self.tree.lock().unwrap(); + tree.insert(new, status); + } + new + } + + pub fn add_dependent_with(&self, a: u32, b: u32, data: T) -> u32 { + let new = self.issue(); + let data = Some(data); + let status = Status::Unverified { parents: (a, b), data }; + { + let mut tree = self.tree.lock().unwrap(); + tree.insert(new, status); + } + new + } + + pub fn add_root(&self) -> u32 { + let new = self.issue(); + let status = Status::Verified; + { + let mut tree = self.tree.lock().unwrap(); + tree.insert(new, status); + } + new + } + + pub async fn verify(&mut self, id: u32, verify_fn: F, coms: C) -> Option + where F: AsyncFn(Vec, C) -> Option, C: Communicate + { + let mut to_check = vec![]; + let mut datas: Vec = vec![]; + let mut checking = vec![]; + checking.push(id); + + let tree = self.tree.get_mut().unwrap(); + + while let Some(id) = checking.pop() { + let t = tree.get(&id)?; + match t { + Status::Failure => todo!("Taint dependent values -or- crash and burn"), + Status::Verified => (), + Status::Unverified{parents, data} => { + checking.push(parents.0); + checking.push(parents.1); + if let Some(data) = data { + datas.push(data.clone()); + } + to_check.push(id); + } + } + } + + let res = verify_fn.async_call((datas, coms)).await?; + let status = if res { Status::Verified } else { Status::Failure }; + + for id in to_check { + tree.insert(id, status.clone()); + } + + Some(res) + + } +} diff --git a/src/marker/mod.rs b/src/marker/mod.rs new file mode 100644 index 0000000..c189710 --- /dev/null +++ b/src/marker/mod.rs @@ -0,0 +1,156 @@ +mod exptree; + +use serde::{de::DeserializeOwned, Deserialize, Serialize}; + +use crate::{net::Communicate, schemes::{Shared, Verify}}; + + +#[repr(transparent)] +#[derive(Serialize, Debug, Clone)] +pub struct Verified(S); + +#[repr(transparent)] +#[derive(Serialize, Debug, Clone)] +pub struct Unverified(S); + +impl<'de, S: Shared + DeserializeOwned> Deserialize<'de> for Unverified { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + Deserialize::deserialize(deserializer).map(|s| Unverified(s)) + } +} + + +impl Unverified { + pub async fn verify(self, coms: impl Communicate, args: S::Args) -> Option> { + if self.0.verify(coms, args).await { + Some(Verified(self.0)) + } else { + None + } + } + + pub fn assume_verified(self) -> Verified { + Verified(self.0) + } +} + +impl From>> for Vec> { + fn from(value: Unverified>) -> Self { + value.0.into_iter().map(|t| Unverified(t)).collect() + } +} + +impl From>> for Vec> { + fn from(value: Verified>) -> Self { + value.0.into_iter().map(|t| Verified(t)).collect() + } +} + + +impl Unverified> { + pub async fn verify_all(self, coms: impl Communicate, args: S::Args) -> Verified>> { + let res = S::verify_many(&self.0, coms, args).await; + let res = res.into_iter().zip(self.0).map(|(verified, t)| { + verified.then_some(t) + }).collect(); + Verified(res) + } + + + pub fn assume_verified(self) -> Verified { + todo!() + } +} + +// Pure boring manual operator implementations +// Could be done with some macros instead. +mod ops { + use std::ops::{Add, Sub}; + + use crate::schemes::Shared; + + use super::*; + + impl Add for Verified { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + Self(self.0 + rhs.0) + } + } + + impl Sub for Verified { + type Output = Self; + + fn sub(self, rhs: Self) -> Self::Output { + Self(self.0 - rhs.0) + } + } + + impl Add> for Verified { + type Output = Unverified; + + fn add(self, rhs: Unverified) -> Self::Output { + Unverified(self.0 + rhs.0) + } + } + + impl Sub> for Verified { + type Output = Unverified; + + fn sub(self, rhs: Unverified) -> Self::Output { + Unverified(self.0 - rhs.0) + } + } + + impl Add for Unverified { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + Self(self.0 + rhs.0) + } + } + + impl Sub for Unverified { + type Output = Self; + + fn sub(self, rhs: Self) -> Self::Output { + Self(self.0 - rhs.0) + } + } +} + + +#[cfg(test)] +mod test { + use super::*; + + use rand::rngs; + + use crate::{ + algebra::element::Mod11, + testing::mock::{self, Share}, + }; + + #[test] + fn serdede() { + let ctx = mock::Context { + all_parties: 1, + me: 0, + }; + let mut rng = rngs::mock::StepRng::new(0, 0); + let s = mock::Share::share(&ctx, Mod11(3), &mut rng); + let s = Verified(s[0]); + let s0 = s.clone(); + let s = s0 + s; + + let to_send = bincode::serialize(&s).unwrap(); + // sending... + let back_again: Unverified> = bincode::deserialize(&to_send).unwrap(); + + println!("Hello again {back_again:?}"); + } +} diff --git a/src/net/agency.rs b/src/net/agency.rs index 0ed3e13..bfc85d8 100644 --- a/src/net/agency.rs +++ b/src/net/agency.rs @@ -28,7 +28,7 @@ use futures::Future; use itertools::Itertools; pub trait Broadcast { - type Error: Error + 'static; + type Error: Error + Send + 'static; // type Error: Error + 'static; /// Broadcast a message to all other parties. @@ -67,9 +67,40 @@ pub trait Broadcast { fn size(&self) -> usize; } +impl<'a, B: Broadcast> Broadcast for &'a mut B { + type Error = B::Error; + + fn broadcast( + &mut self, + msg: &(impl serde::Serialize + Sync), + ) -> impl std::future::Future> { + (**self).broadcast(msg) + } + + fn symmetric_broadcast( + &mut self, + msg: T, + ) -> impl Future, Self::Error>> + where + T: serde::Serialize + serde::de::DeserializeOwned + Sync { + (**self).symmetric_broadcast(msg) + } + + fn recv_from( + &mut self, + idx: usize, + ) -> impl Future> { + (**self).recv_from(idx) + } + + fn size(&self) -> usize { + (**self).size() + } +} + // TODO: Possible rename this trait as it's name is confusing. pub trait Unicast { - type Error: Error + 'static; + type Error: Error + Send + 'static; /// Unicast messages to each party /// @@ -110,6 +141,36 @@ pub trait Unicast { fn size(&self) -> usize; } +impl<'a, U: Unicast> Unicast for &'a mut U { + type Error = U::Error; + + fn size(&self) -> usize { + (**self).size() + } + + fn receive_all( + &mut self, + ) -> impl Future, Self::Error>> { + (**self).receive_all() + } + + fn unicast( + &mut self, + msgs: &[impl serde::Serialize + Sync], + ) -> impl std::future::Future> { + (**self).unicast(msgs) + } + + fn symmetric_unicast( + &mut self, + msgs: Vec, + ) -> impl Future, Self::Error>> + where + T: serde::Serialize + serde::de::DeserializeOwned + Sync { + (**self).symmetric_unicast(msgs) + } +} + use digest::Digest; use tracing::{event, Level}; diff --git a/src/net/mod.rs b/src/net/mod.rs index 826de45..95480ce 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -2,10 +2,7 @@ use std::error::Error; use futures::Future; -use crate::net::{ - connection::{Connection, ConnectionError, RecvBytes, SendBytes}, - network::Network, -}; +use crate::net::connection::{Connection, ConnectionError, RecvBytes, SendBytes}; pub mod agency; pub mod connection; @@ -56,9 +53,26 @@ pub trait SplitChannel: Channel { fn split(&mut self) -> (&mut Self::Sender, &mut Self::Receiver); } +impl<'a, C: Channel> Channel for &'a mut C { + type Error = C::Error; + + fn send( + &mut self, + msg: &T, + ) -> impl Future> + Send { + (**self).send(msg) + } + + fn recv( + &mut self, + ) -> impl Future> + Send { + (**self).recv() + } +} + /// Tune to a specific channel pub trait Tuneable { - type Error: Error + 'static; + type Error: Error + Send + 'static; fn id(&self) -> usize; @@ -74,27 +88,31 @@ pub trait Tuneable { ) -> impl std::future::Future>; } -impl Tuneable for Network { - type Error = C::Error; +impl<'a, R: Tuneable + ?Sized> Tuneable for &'a mut R { + type Error = R::Error; fn id(&self) -> usize { - self.index + (**self).id() } - async fn recv_from( + fn recv_from( &mut self, idx: usize, - ) -> Result { - let idx = self.id_to_index(idx); - self.connections[idx].recv().await + ) -> impl Future> { + (**self).recv_from(idx) } - async fn send_to( + fn send_to( &mut self, idx: usize, msg: &T, - ) -> Result<(), Self::Error> { - let idx = self.id_to_index(idx); - self.connections[idx].send(msg).await + ) -> impl std::future::Future> { + (**self).send_to(idx, msg) } } + + +/// General communication with support for most network functionality. +pub trait Communicate : agency::Broadcast + agency::Unicast + Tuneable + Send {} +impl<'a, C: Communicate> Communicate for &'a mut C { } + diff --git a/src/net/network.rs b/src/net/network.rs index 2b10136..cafca33 100644 --- a/src/net/network.rs +++ b/src/net/network.rs @@ -357,6 +357,31 @@ impl Broadcast for Network { } } +impl Tuneable for Network { + type Error = C::Error; + + fn id(&self) -> usize { + self.index + } + + async fn recv_from( + &mut self, + idx: usize, + ) -> Result { + let idx = self.id_to_index(idx); + self.connections[idx].recv().await + } + + async fn send_to( + &mut self, + idx: usize, + msg: &T, + ) -> Result<(), Self::Error> { + let idx = self.id_to_index(idx); + self.connections[idx].send(msg).await + } +} + /// Network containing only duplex connections. /// Used for local testing. pub type InMemoryNetwork = Network; diff --git a/src/protocols/beaver.rs b/src/protocols/beaver.rs index 2bf566d..c50ec5d 100644 --- a/src/protocols/beaver.rs +++ b/src/protocols/beaver.rs @@ -31,15 +31,15 @@ impl> BeaverTriple { let b = F::random(&mut rng); let c: F = a * b; // Share (preproccess) - let a = S::share(ctx, a, rng); - let b = S::share(ctx, b, rng); - let c = S::share(ctx, c, rng); + let a = S::share(ctx, a, &mut rng); + let b = S::share(ctx, b, &mut rng); + let c = S::share(ctx, c, &mut rng); itertools::izip!(a, b, c) .map(|(a, b, c)| Self { shares: (a, b, c) }) .collect() } - pub fn fake_many(ctx: &C, mut rng: &mut impl RngCore, count: usize) -> Vec> { + pub fn fake_many(ctx: &C, mut rng: impl RngCore, count: usize) -> Vec> { let zipped = iter::from_fn(|| { let a = F::random(&mut rng); let b = F::random(&mut rng); @@ -49,9 +49,9 @@ impl> BeaverTriple { .take(count); let (a, b, c): (Vec<_>, Vec<_>, Vec<_>) = multiunzip(zipped); // Share (preproccess) - let a = S::share_many(ctx, &a, rng); - let b = S::share_many(ctx, &b, rng); - let c = S::share_many(ctx, &c, rng); + let a = S::share_many(ctx, &a, &mut rng); + let b = S::share_many(ctx, &b, &mut rng); + let c = S::share_many(ctx, &c, &mut rng); itertools::izip!(a, b, c) .map(|(a, b, c)| { @@ -164,12 +164,12 @@ pub struct BeaverSquare { } impl> BeaverSquare { - pub fn fake(ctx: &C, mut rng: &mut impl RngCore) -> Vec { + pub fn fake(ctx: &C, mut rng: impl RngCore) -> Vec { let a = F::random(&mut rng); let c: F = a * a; // Share (preproccess) - let a = S::share(ctx, a, rng); - let c = S::share(ctx, c, rng); + let a = S::share(ctx, a, &mut rng); + let c = S::share(ctx, c, &mut rng); itertools::izip!(a, c) .map(|(a, c)| Self { val: a, diff --git a/src/schemes/feldman.rs b/src/schemes/feldman.rs index 7feb1a8..3b09775 100644 --- a/src/schemes/feldman.rs +++ b/src/schemes/feldman.rs @@ -38,7 +38,7 @@ pub fn share( val: F, ids: &[F], threshold: u64, - rng: &mut impl RngCore, + mut rng: impl RngCore, ) -> Vec> where G: std::ops::Mul, @@ -55,7 +55,7 @@ where // Sample random t-degree polynomial let n = ids.len(); - let poly = (1..threshold).map(|_| F::random(&mut *rng)); + let poly = (1..threshold).map(|_| F::random(&mut rng)); // I want to avoid this allocation :( let poly: Box<[F]> = iter::once(val).chain(poly).collect(); let mac_poly: Vector<_> = poly.iter().map(|a| G::generator() * *a).collect(); @@ -144,7 +144,7 @@ impl< type Context = ShamirParams; type Value = F; - fn share(ctx: &Self::Context, secret: F, rng: &mut impl RngCore) -> Vec { + fn share(ctx: &Self::Context, secret: F, rng: impl RngCore) -> Vec { share::(secret, &ctx.ids, ctx.threshold, rng) } @@ -267,7 +267,7 @@ pub fn share_many( vals: &[F], ids: &[F], threshold: u64, - rng: &mut impl RngCore, + mut rng: impl RngCore, ) -> Vec> // FIX: This `where` clause is a bit much, it does however work. where @@ -289,7 +289,7 @@ where let polys: Vec<_> = vals .iter() .map(|v| { - let mut p = Polynomial::::random(threshold as usize - 1, rng); + let mut p = Polynomial::::random(threshold as usize - 1, &mut rng); p.0[0] = *v; p }) diff --git a/src/schemes/mod.rs b/src/schemes/mod.rs index 867ae82..aca6f32 100644 --- a/src/schemes/mod.rs +++ b/src/schemes/mod.rs @@ -27,17 +27,14 @@ pub mod spdz; use std::{ error::Error, + future::Future, ops::{Add, Sub}, }; -use futures::Future; - use rand::RngCore; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; -use crate::net::{ - agency::{Broadcast, Unicast}, - Tuneable, -}; +use crate::net::Communicate; /// Currently unused trait, but might be a better way to represent that a share /// can be multiplied by a const, however, it could also just be baked into 'Shared' directly. @@ -73,7 +70,7 @@ pub trait Shared: /// * `secret`: secret value to share /// * `rng`: cryptographic secure random number generator /// - fn share(ctx: &Self::Context, secret: Self::Value, rng: &mut impl RngCore) -> Vec; + fn share(ctx: &Self::Context, secret: Self::Value, rng: impl RngCore) -> Vec; /// Recombine the shares back into a secret, /// returning an value if successfull. @@ -87,11 +84,11 @@ pub trait Shared: fn share_many( ctx: &Self::Context, secrets: &[Self::Value], - rng: &mut impl RngCore, + mut rng: impl RngCore, ) -> Vec> { let shares: Vec<_> = secrets .iter() - .map(|secret| Self::share(ctx, secret.clone(), rng)) + .map(|secret| Self::share(ctx, secret.clone(), &mut rng)) .collect(); crate::help::transpose(shares) } @@ -121,20 +118,7 @@ pub trait Shared: } } -pub trait SharedVec: - Sized - + Add - + Sub - + serde::Serialize - + serde::de::DeserializeOwned - + Clone -{ - type Value; - type Context: Send + Clone; - fn share(ctx: &Self::Context, secrets: &[Self::Value], rng: &mut impl RngCore) -> Self; - fn recombine(ctx: &Self::Context, shares: &[Self], rng: &mut impl RngCore) -> Vec; -} /// Support for multiplication of two shares for producing a share. /// @@ -151,10 +135,99 @@ pub trait InteractiveMult: Shared { /// /// Returns a result which contains the shared value corresponding /// to the multiplication of `a` and `b`. - fn interactive_mult( + fn interactive_mult( ctx: &Self::Context, net: &mut U, a: Self, b: Self, ) -> impl Future>>; } + +mod interactive { + use super::*; + impl InteractiveShared for S where S: Shared + Send, V: Send + Clone, C: Send + Sync + Clone { + type Context = S::Context; + type Value = V; + type Error = Box; + + async fn share( + ctx: &Self::Context, + secret: Self::Value, + rng: impl RngCore + Send, + mut coms: impl Communicate, + ) -> Result { + let shares = S::share(ctx, secret, rng); + let my_share = shares[coms.id()].clone(); + coms.unicast(&shares).await.map_err(|e| { + let e : Box = Box::new(e); + e + } + )?; + Ok(my_share) + } + + async fn recombine( + ctx: &Self::Context, + secret: Self, + mut coms: impl Communicate, + ) -> Result { + let shares = coms.symmetric_broadcast(secret).await.unwrap(); + Ok(Shared::recombine(ctx, &shares).unwrap()) + } + + async fn symmetric_share( + ctx: &Self::Context, + secret: Self::Value, + rng: impl RngCore + Send, + mut coms: impl Communicate, + ) -> Result, Self::Error> { + let shares = S::share(ctx, secret, rng); + let shared = coms.symmetric_unicast(shares).await.unwrap(); + Ok(shared) + } + } + + + pub trait InteractiveShared: + Sized + + Add + + Sub + + serde::Serialize + + serde::de::DeserializeOwned + + Clone + + Sync + { + type Context: Sync + Send + Clone; + type Value: Clone + Send; + type Error: Send + Sized + 'static; + + fn share( + ctx: &Self::Context, + secret: Self::Value, + rng: impl RngCore + Send, + coms: impl Communicate, + ) -> impl std::future::Future>; + + fn symmetric_share( + ctx: &Self::Context, + secret: Self::Value, + rng: impl RngCore + Send, + coms: impl Communicate, + ) -> impl std::future::Future, Self::Error>>; + + fn recombine( + ctx: &Self::Context, + secrets: Self, + coms: impl Communicate, + ) -> impl std::future::Future>; + } +} + +pub trait Verify: Sized { + type Args: Send; + + fn verify(&self, coms: impl Communicate, args: Self::Args) -> impl Future + Send; + + fn verify_many(batch: &[Self], coms: impl Communicate, args: Self::Args) -> impl Future> + Send; +} + diff --git a/src/schemes/pedersen.rs b/src/schemes/pedersen.rs index fa07a25..9275a4f 100644 --- a/src/schemes/pedersen.rs +++ b/src/schemes/pedersen.rs @@ -37,7 +37,7 @@ pub fn share( secret: F, ids: &[F], threshold: usize, - rng: &mut impl RngCore, + mut rng: impl RngCore, PedersenGenParams(g, h): &PedersenGenParams, ) -> Vec> where @@ -45,8 +45,8 @@ where F: Field, G: Group, { - let mut p1: Polynomial = Polynomial::random(threshold, rng); - let p2: Polynomial = Polynomial::random(threshold, rng); + let mut p1: Polynomial = Polynomial::random(threshold, &mut rng); + let p2: Polynomial = Polynomial::random(threshold, &mut rng); // secret `s` p1.0[0] = secret; // random secret `t` (left random) @@ -112,7 +112,7 @@ where type Value = F; - fn share(ctx: &Self::Context, secret: Self::Value, rng: &mut impl RngCore) -> Vec { + fn share(ctx: &Self::Context, secret: Self::Value, rng: impl RngCore) -> Vec { share(secret, &ctx.ids, ctx.threshold, rng, &ctx.pedersen_params) } diff --git a/src/schemes/rep3.rs b/src/schemes/rep3.rs index 56b394b..00a17d4 100644 --- a/src/schemes/rep3.rs +++ b/src/schemes/rep3.rs @@ -15,7 +15,7 @@ use crate::{net::Tuneable, schemes::InteractiveMult}; #[derive(Debug, Clone, Copy, Add, Sub, Serialize, Deserialize)] pub struct Share(F, F); -pub fn share(secret: F, mut rng: &mut impl RngCore) -> [Share; 3] { +pub fn share(secret: F, mut rng: impl RngCore) -> [Share; 3] { let mut shares = [0; 3].map(|_| F::random(&mut rng)); let sum = shares[0] + shares[1] + shares[2]; shares[0] += secret - sum; @@ -31,8 +31,8 @@ impl super::Shared for Share { type Context = (); type Value = F; - fn share(_ctx: &Self::Context, secret: F, rng: &mut impl RngCore) -> Vec { - share(secret, rng).to_vec() + fn share(_ctx: &Self::Context, secret: F, mut rng: impl RngCore) -> Vec { + share(secret, &mut rng).to_vec() } fn recombine(_ctx: &Self::Context, shares: &[Self]) -> Option { diff --git a/src/schemes/shamir.rs b/src/schemes/shamir.rs index c107e0a..36522b7 100644 --- a/src/schemes/shamir.rs +++ b/src/schemes/shamir.rs @@ -39,8 +39,8 @@ impl super::Shared fo type Context = ShamirParams; type Value = F; - fn share(ctx: &Self::Context, secret: F, rng: &mut impl RngCore) -> Vec { - share(secret, &ctx.ids, ctx.threshold, rng) + fn share(ctx: &Self::Context, secret: F, mut rng: impl RngCore) -> Vec { + share(secret, &ctx.ids, ctx.threshold, &mut rng) } fn recombine(ctx: &Self::Context, shares: &[Self]) -> Option { @@ -343,8 +343,8 @@ impl super::Shared for VecSh type Value = Vec; - fn share(ctx: &Self::Context, secret: Self::Value, rng: &mut impl RngCore) -> Vec { - share_many(&secret, &ctx.ids, ctx.threshold, rng) + fn share(ctx: &Self::Context, secret: Self::Value, mut rng: impl RngCore) -> Vec { + share_many(&secret, &ctx.ids, ctx.threshold, &mut rng) } fn recombine(ctx: &Self::Context, shares: &[Self]) -> Option { @@ -447,7 +447,7 @@ pub fn share_many( vs: &[F], ids: &[F], threshold: u64, - rng: &mut impl RngCore, + mut rng: impl RngCore, ) -> Vec> { // FIX: Code duplication with 'share' let n = ids.len(); @@ -461,7 +461,7 @@ pub fn share_many( let polynomials: Vec<_> = vs .iter() .map(|v| { - let mut p = Polynomial::random(threshold as usize - 1, rng); + let mut p = Polynomial::random(threshold as usize - 1, &mut rng); p.0[0] = *v; p }) diff --git a/src/testing/mock.rs b/src/testing/mock.rs index 4137a92..f250328 100644 --- a/src/testing/mock.rs +++ b/src/testing/mock.rs @@ -83,7 +83,7 @@ impl Shared for Shar fn share( ctx: &Self::Context, secret: Self::Value, - _rng: &mut impl rand::prelude::RngCore, + _rng: impl rand::prelude::RngCore, ) -> Vec { (0..ctx.all_parties) .map(|i| Share { From fd514d269dae61e61657f69a7f5c66e742eef823 Mon Sep 17 00:00:00 2001 From: Mikkel Wienberg Madsen Date: Mon, 13 May 2024 16:28:05 +0200 Subject: [PATCH 2/3] Blanket sharing for (Un)Ver --- pycare/Cargo.toml | 2 +- src/marker/exptree.rs | 1 + src/marker/mod.rs | 57 +++++++++++++++++++++++++++++++++++-------- src/schemes/mod.rs | 48 +++++++++++++++++++++++++++--------- 4 files changed, 86 insertions(+), 22 deletions(-) diff --git a/pycare/Cargo.toml b/pycare/Cargo.toml index aec93a3..2da0a53 100644 --- a/pycare/Cargo.toml +++ b/pycare/Cargo.toml @@ -9,5 +9,5 @@ name = "caring" crate-type = ["cdylib"] [dependencies] -pyo3 = { version = "0.21", features = ["abi3-py37", "generate-import-lib"]} +pyo3 = { version = "0.21", features = ["abi3-py37", "generate-import-lib", "extension-module"]} wecare = { path = "../wecare" } diff --git a/src/marker/exptree.rs b/src/marker/exptree.rs index a2d6205..2c24084 100644 --- a/src/marker/exptree.rs +++ b/src/marker/exptree.rs @@ -88,4 +88,5 @@ impl ExpTree { Some(res) } + } diff --git a/src/marker/mod.rs b/src/marker/mod.rs index c189710..8ceef16 100644 --- a/src/marker/mod.rs +++ b/src/marker/mod.rs @@ -1,8 +1,9 @@ mod exptree; +use rand::RngCore; use serde::{de::DeserializeOwned, Deserialize, Serialize}; -use crate::{net::Communicate, schemes::{Shared, Verify}}; +use crate::{net::Communicate, schemes::{interactive::InteractiveShared, Shared, Verify}}; #[repr(transparent)] @@ -31,12 +32,39 @@ impl Unverified { None } } +} +impl Unverified { pub fn assume_verified(self) -> Verified { Verified(self.0) } } + +impl Verified { + pub async fn open(self, ctx: &S::Context, coms: impl Communicate) -> Result { + S::recombine(ctx, self.0, coms).await + } + + pub async fn share(val: S::Value, ctx: &S::Context, rng: impl RngCore + Send, coms: impl Communicate) -> Result { + let s = S::share(ctx, val, rng, coms).await?; + Ok(Self(s)) + } + +} + +impl Unverified { + pub async fn share_symmetric(val: S::Value, ctx: &S::Context, rng: impl RngCore + Send, coms: impl Communicate) -> Result, S::Error> { + let s = S::symmetric_share(ctx, val, rng, coms).await?; + Ok(s.into_iter().map(Self).collect()) + } + + pub async fn receive_share(ctx: &S::Context, coms: impl Communicate, from: usize) -> Result { + let s = S::receive_share(ctx, coms, from).await?; + Ok(Self(s)) + } +} + impl From>> for Vec> { fn from(value: Unverified>) -> Self { value.0.into_iter().map(|t| Unverified(t)).collect() @@ -58,18 +86,12 @@ impl Unverified> { }).collect(); Verified(res) } - - - pub fn assume_verified(self) -> Verified { - todo!() - } } // Pure boring manual operator implementations // Could be done with some macros instead. mod ops { - use std::ops::{Add, Sub}; - + use std::ops::{Add, Mul, Sub}; use crate::schemes::Shared; use super::*; @@ -121,8 +143,23 @@ mod ops { Self(self.0 - rhs.0) } } -} + impl Mul for Verified where S: Mul { + type Output = Self; + + fn mul(self, rhs: S::Value) -> Self::Output { + Self(self.0 * rhs) + } + } + + impl Mul for Unverified where S: Mul { + type Output = Self; + + fn mul(self, rhs: S::Value) -> Self::Output { + Self(self.0 * rhs) + } + } +} #[cfg(test)] mod test { @@ -142,7 +179,7 @@ mod test { me: 0, }; let mut rng = rngs::mock::StepRng::new(0, 0); - let s = mock::Share::share(&ctx, Mod11(3), &mut rng); + let s = as Shared>::share(&ctx, Mod11(3), &mut rng); let s = Verified(s[0]); let s0 = s.clone(); let s = s0 + s; diff --git a/src/schemes/mod.rs b/src/schemes/mod.rs index aca6f32..405fe00 100644 --- a/src/schemes/mod.rs +++ b/src/schemes/mod.rs @@ -32,13 +32,12 @@ use std::{ }; use rand::RngCore; -use serde::{de::DeserializeOwned, Deserialize, Serialize}; use crate::net::Communicate; /// Currently unused trait, but might be a better way to represent that a share /// can be multiplied by a const, however, it could also just be baked into 'Shared' directly. -trait MulByConst: +pub trait MulByConst: Shared + std::ops::Mul + std::ops::MulAssign { } @@ -143,12 +142,27 @@ pub trait InteractiveMult: Shared { ) -> impl Future>>; } -mod interactive { +pub mod interactive { + use thiserror::Error; + + use crate::net::Tuneable; + + + #[derive(Debug, Error)] + #[error("Communication failure: {0}")] + pub struct CommunicationError(Box); + impl CommunicationError { + fn new(e: impl Error + Send + 'static) -> Self { + Self(Box::new(e)) + } + + } + use super::*; impl InteractiveShared for S where S: Shared + Send, V: Send + Clone, C: Send + Sync + Clone { type Context = S::Context; type Value = V; - type Error = Box; + type Error = CommunicationError; async fn share( ctx: &Self::Context, @@ -158,11 +172,7 @@ mod interactive { ) -> Result { let shares = S::share(ctx, secret, rng); let my_share = shares[coms.id()].clone(); - coms.unicast(&shares).await.map_err(|e| { - let e : Box = Box::new(e); - e - } - )?; + coms.unicast(&shares).await.map_err(CommunicationError::new)?; Ok(my_share) } @@ -171,7 +181,7 @@ mod interactive { secret: Self, mut coms: impl Communicate, ) -> Result { - let shares = coms.symmetric_broadcast(secret).await.unwrap(); + let shares = coms.symmetric_broadcast(secret).await.map_err(CommunicationError::new)?; Ok(Shared::recombine(ctx, &shares).unwrap()) } @@ -182,9 +192,19 @@ mod interactive { mut coms: impl Communicate, ) -> Result, Self::Error> { let shares = S::share(ctx, secret, rng); - let shared = coms.symmetric_unicast(shares).await.unwrap(); + let shared = coms.symmetric_unicast(shares).await.map_err(CommunicationError::new)?; Ok(shared) } + + async fn receive_share( + _ctx: &Self::Context, + mut coms: impl Communicate, + from: usize, + ) -> Result { + let s = Tuneable::recv_from(&mut coms, from).await; + let s = s.map_err(CommunicationError::new)?; + Ok(s) + } } @@ -215,6 +235,12 @@ mod interactive { coms: impl Communicate, ) -> impl std::future::Future, Self::Error>>; + fn receive_share( + ctx: &Self::Context, + coms: impl Communicate, + from: usize, + ) -> impl std::future::Future>; + fn recombine( ctx: &Self::Context, secrets: Self, From 5a4cc28c886591a9aa969b10d587a6e3896b69ae Mon Sep 17 00:00:00 2001 From: Mikkel Wienberg Madsen Date: Wed, 29 May 2024 11:24:47 +0200 Subject: [PATCH 3/3] Cargo fmt --- src/lib.rs | 3 +- src/marker/exptree.rs | 35 ++++++++++++----- src/marker/mod.rs | 64 +++++++++++++++++++++--------- src/net/agency.rs | 8 ++-- src/net/mod.rs | 6 +-- src/schemes/mod.rs | 90 ++++++++++++++++++++++++------------------- 6 files changed, 131 insertions(+), 75 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5540876..0e6fffa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,6 @@ #![deny(unsafe_code)] #![allow(refining_impl_trait)] #![allow(dead_code)] - #![feature(async_fn_traits)] mod algebra; @@ -11,6 +10,6 @@ mod protocols; pub mod schemes; mod help; +pub mod marker; #[cfg(test)] mod testing; -pub mod marker; diff --git a/src/marker/exptree.rs b/src/marker/exptree.rs index 2c24084..047c52a 100644 --- a/src/marker/exptree.rs +++ b/src/marker/exptree.rs @@ -1,5 +1,12 @@ -use std::{collections::BTreeMap, ops::AsyncFn, sync::{atomic::{AtomicU32, Ordering::SeqCst}, Mutex}}; use crate::net::Communicate; +use std::{ + collections::BTreeMap, + ops::AsyncFn, + sync::{ + atomic::{AtomicU32, Ordering::SeqCst}, + Mutex, + }, +}; #[derive(Clone)] pub enum Status { Verified, @@ -23,7 +30,10 @@ impl ExpTree { pub fn add_dependent(&self, a: u32, b: u32) -> u32 { let new = self.issue(); - let status : Status = Status::Unverified { parents: (a, b), data: None }; + let status: Status = Status::Unverified { + parents: (a, b), + data: None, + }; { let mut tree = self.tree.lock().unwrap(); tree.insert(new, status); @@ -34,7 +44,10 @@ impl ExpTree { pub fn add_dependent_with(&self, a: u32, b: u32, data: T) -> u32 { let new = self.issue(); let data = Some(data); - let status = Status::Unverified { parents: (a, b), data }; + let status = Status::Unverified { + parents: (a, b), + data, + }; { let mut tree = self.tree.lock().unwrap(); tree.insert(new, status); @@ -53,7 +66,9 @@ impl ExpTree { } pub async fn verify(&mut self, id: u32, verify_fn: F, coms: C) -> Option - where F: AsyncFn(Vec, C) -> Option, C: Communicate + where + F: AsyncFn(Vec, C) -> Option, + C: Communicate, { let mut to_check = vec![]; let mut datas: Vec = vec![]; @@ -63,11 +78,11 @@ impl ExpTree { let tree = self.tree.get_mut().unwrap(); while let Some(id) = checking.pop() { - let t = tree.get(&id)?; + let t = tree.get(&id)?; match t { Status::Failure => todo!("Taint dependent values -or- crash and burn"), Status::Verified => (), - Status::Unverified{parents, data} => { + Status::Unverified { parents, data } => { checking.push(parents.0); checking.push(parents.1); if let Some(data) = data { @@ -79,14 +94,16 @@ impl ExpTree { } let res = verify_fn.async_call((datas, coms)).await?; - let status = if res { Status::Verified } else { Status::Failure }; + let status = if res { + Status::Verified + } else { + Status::Failure + }; for id in to_check { tree.insert(id, status.clone()); } Some(res) - } - } diff --git a/src/marker/mod.rs b/src/marker/mod.rs index 8ceef16..ba7bea3 100644 --- a/src/marker/mod.rs +++ b/src/marker/mod.rs @@ -3,8 +3,10 @@ mod exptree; use rand::RngCore; use serde::{de::DeserializeOwned, Deserialize, Serialize}; -use crate::{net::Communicate, schemes::{interactive::InteractiveShared, Shared, Verify}}; - +use crate::{ + net::Communicate, + schemes::{interactive::InteractiveShared, Shared, Verify}, +}; #[repr(transparent)] #[derive(Serialize, Debug, Clone)] @@ -23,7 +25,6 @@ impl<'de, S: Shared + DeserializeOwned> Deserialize<'de> for Unverified { } } - impl Unverified { pub async fn verify(self, coms: impl Communicate, args: S::Args) -> Option> { if self.0.verify(coms, args).await { @@ -40,26 +41,42 @@ impl Unverified { } } - impl Verified { - pub async fn open(self, ctx: &S::Context, coms: impl Communicate) -> Result { + pub async fn open( + self, + ctx: &S::Context, + coms: impl Communicate, + ) -> Result { S::recombine(ctx, self.0, coms).await } - pub async fn share(val: S::Value, ctx: &S::Context, rng: impl RngCore + Send, coms: impl Communicate) -> Result { + pub async fn share( + val: S::Value, + ctx: &S::Context, + rng: impl RngCore + Send, + coms: impl Communicate, + ) -> Result { let s = S::share(ctx, val, rng, coms).await?; Ok(Self(s)) } - } impl Unverified { - pub async fn share_symmetric(val: S::Value, ctx: &S::Context, rng: impl RngCore + Send, coms: impl Communicate) -> Result, S::Error> { + pub async fn share_symmetric( + val: S::Value, + ctx: &S::Context, + rng: impl RngCore + Send, + coms: impl Communicate, + ) -> Result, S::Error> { let s = S::symmetric_share(ctx, val, rng, coms).await?; Ok(s.into_iter().map(Self).collect()) } - pub async fn receive_share(ctx: &S::Context, coms: impl Communicate, from: usize) -> Result { + pub async fn receive_share( + ctx: &S::Context, + coms: impl Communicate, + from: usize, + ) -> Result { let s = S::receive_share(ctx, coms, from).await?; Ok(Self(s)) } @@ -77,13 +94,18 @@ impl From>> for Vec> { } } - impl Unverified> { - pub async fn verify_all(self, coms: impl Communicate, args: S::Args) -> Verified>> { + pub async fn verify_all( + self, + coms: impl Communicate, + args: S::Args, + ) -> Verified>> { let res = S::verify_many(&self.0, coms, args).await; - let res = res.into_iter().zip(self.0).map(|(verified, t)| { - verified.then_some(t) - }).collect(); + let res = res + .into_iter() + .zip(self.0) + .map(|(verified, t)| verified.then_some(t)) + .collect(); Verified(res) } } @@ -91,8 +113,8 @@ impl Unverified> { // Pure boring manual operator implementations // Could be done with some macros instead. mod ops { - use std::ops::{Add, Mul, Sub}; use crate::schemes::Shared; + use std::ops::{Add, Mul, Sub}; use super::*; @@ -144,7 +166,10 @@ mod ops { } } - impl Mul for Verified where S: Mul { + impl Mul for Verified + where + S: Mul, + { type Output = Self; fn mul(self, rhs: S::Value) -> Self::Output { @@ -152,7 +177,10 @@ mod ops { } } - impl Mul for Unverified where S: Mul { + impl Mul for Unverified + where + S: Mul, + { type Output = Self; fn mul(self, rhs: S::Value) -> Self::Output { @@ -179,7 +207,7 @@ mod test { me: 0, }; let mut rng = rngs::mock::StepRng::new(0, 0); - let s = as Shared>::share(&ctx, Mod11(3), &mut rng); + let s = as Shared>::share(&ctx, Mod11(3), &mut rng); let s = Verified(s[0]); let s0 = s.clone(); let s = s0 + s; diff --git a/src/net/agency.rs b/src/net/agency.rs index bfc85d8..a6936ed 100644 --- a/src/net/agency.rs +++ b/src/net/agency.rs @@ -82,8 +82,9 @@ impl<'a, B: Broadcast> Broadcast for &'a mut B { msg: T, ) -> impl Future, Self::Error>> where - T: serde::Serialize + serde::de::DeserializeOwned + Sync { - (**self).symmetric_broadcast(msg) + T: serde::Serialize + serde::de::DeserializeOwned + Sync, + { + (**self).symmetric_broadcast(msg) } fn recv_from( @@ -166,7 +167,8 @@ impl<'a, U: Unicast> Unicast for &'a mut U { msgs: Vec, ) -> impl Future, Self::Error>> where - T: serde::Serialize + serde::de::DeserializeOwned + Sync { + T: serde::Serialize + serde::de::DeserializeOwned + Sync, + { (**self).symmetric_unicast(msgs) } } diff --git a/src/net/mod.rs b/src/net/mod.rs index 95480ce..0f5d3d1 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -111,8 +111,6 @@ impl<'a, R: Tuneable + ?Sized> Tuneable for &'a mut R { } } - /// General communication with support for most network functionality. -pub trait Communicate : agency::Broadcast + agency::Unicast + Tuneable + Send {} -impl<'a, C: Communicate> Communicate for &'a mut C { } - +pub trait Communicate: agency::Broadcast + agency::Unicast + Tuneable + Send {} +impl<'a, C: Communicate> Communicate for &'a mut C {} diff --git a/src/schemes/mod.rs b/src/schemes/mod.rs index 405fe00..b529273 100644 --- a/src/schemes/mod.rs +++ b/src/schemes/mod.rs @@ -117,8 +117,6 @@ pub trait Shared: } } - - /// Support for multiplication of two shares for producing a share. /// /// Note, that this is different to beaver multiplication as it does not require @@ -147,7 +145,6 @@ pub mod interactive { use crate::net::Tuneable; - #[derive(Debug, Error)] #[error("Communication failure: {0}")] pub struct CommunicationError(Box); @@ -155,11 +152,15 @@ pub mod interactive { fn new(e: impl Error + Send + 'static) -> Self { Self(Box::new(e)) } - } use super::*; - impl InteractiveShared for S where S: Shared + Send, V: Send + Clone, C: Send + Sync + Clone { + impl InteractiveShared for S + where + S: Shared + Send, + V: Send + Clone, + C: Send + Sync + Clone, + { type Context = S::Context; type Value = V; type Error = CommunicationError; @@ -172,7 +173,9 @@ pub mod interactive { ) -> Result { let shares = S::share(ctx, secret, rng); let my_share = shares[coms.id()].clone(); - coms.unicast(&shares).await.map_err(CommunicationError::new)?; + coms.unicast(&shares) + .await + .map_err(CommunicationError::new)?; Ok(my_share) } @@ -181,7 +184,10 @@ pub mod interactive { secret: Self, mut coms: impl Communicate, ) -> Result { - let shares = coms.symmetric_broadcast(secret).await.map_err(CommunicationError::new)?; + let shares = coms + .symmetric_broadcast(secret) + .await + .map_err(CommunicationError::new)?; Ok(Shared::recombine(ctx, &shares).unwrap()) } @@ -192,7 +198,10 @@ pub mod interactive { mut coms: impl Communicate, ) -> Result, Self::Error> { let shares = S::share(ctx, secret, rng); - let shared = coms.symmetric_unicast(shares).await.map_err(CommunicationError::new)?; + let shared = coms + .symmetric_unicast(shares) + .await + .map_err(CommunicationError::new)?; Ok(shared) } @@ -207,7 +216,6 @@ pub mod interactive { } } - pub trait InteractiveShared: Sized + Add @@ -216,44 +224,48 @@ pub mod interactive { + serde::de::DeserializeOwned + Clone + Sync - { - type Context: Sync + Send + Clone; - type Value: Clone + Send; - type Error: Send + Sized + 'static; + { + type Context: Sync + Send + Clone; + type Value: Clone + Send; + type Error: Send + Sized + 'static; - fn share( - ctx: &Self::Context, - secret: Self::Value, - rng: impl RngCore + Send, - coms: impl Communicate, - ) -> impl std::future::Future>; + fn share( + ctx: &Self::Context, + secret: Self::Value, + rng: impl RngCore + Send, + coms: impl Communicate, + ) -> impl std::future::Future>; - fn symmetric_share( - ctx: &Self::Context, - secret: Self::Value, - rng: impl RngCore + Send, - coms: impl Communicate, - ) -> impl std::future::Future, Self::Error>>; + fn symmetric_share( + ctx: &Self::Context, + secret: Self::Value, + rng: impl RngCore + Send, + coms: impl Communicate, + ) -> impl std::future::Future, Self::Error>>; - fn receive_share( - ctx: &Self::Context, - coms: impl Communicate, - from: usize, - ) -> impl std::future::Future>; + fn receive_share( + ctx: &Self::Context, + coms: impl Communicate, + from: usize, + ) -> impl std::future::Future>; - fn recombine( - ctx: &Self::Context, - secrets: Self, - coms: impl Communicate, - ) -> impl std::future::Future>; - } + fn recombine( + ctx: &Self::Context, + secrets: Self, + coms: impl Communicate, + ) -> impl std::future::Future>; + } } pub trait Verify: Sized { type Args: Send; - fn verify(&self, coms: impl Communicate, args: Self::Args) -> impl Future + Send; + fn verify(&self, coms: impl Communicate, args: Self::Args) + -> impl Future + Send; - fn verify_many(batch: &[Self], coms: impl Communicate, args: Self::Args) -> impl Future> + Send; + fn verify_many( + batch: &[Self], + coms: impl Communicate, + args: Self::Args, + ) -> impl Future> + Send; } -