Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: decouple assignment from definition #78

Merged
merged 15 commits into from
Oct 24, 2023
1 change: 1 addition & 0 deletions garble/mpz-garble/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ aes = { workspace = true }
rayon = { workspace = true }
derive_builder.workspace = true
itybity.workspace = true
opaque-debug.workspace = true

[dev-dependencies]
mpz-ot = { workspace = true, features = ["mock"] }
Expand Down
29 changes: 15 additions & 14 deletions garble/mpz-garble/benches/deap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,12 @@ async fn bench_deap() {
let msg = [0u8; 16];

let leader_fut = {
let key_ref = leader_thread
.new_private_input::<[u8; 16]>("key", Some(key))
.unwrap();
let msg_ref = leader_thread
.new_private_input::<[u8; 16]>("msg", None)
.unwrap();
let key_ref = leader_thread.new_private_input::<[u8; 16]>("key").unwrap();
let msg_ref = leader_thread.new_blind_input::<[u8; 16]>("msg").unwrap();
let ciphertext_ref = leader_thread.new_output::<[u8; 16]>("ciphertext").unwrap();

leader_thread.assign(&key_ref, key).unwrap();

async {
leader_thread
.execute(
Expand All @@ -41,16 +39,16 @@ async fn bench_deap() {
};

let follower_fut = {
let key_ref = follower_thread
.new_private_input::<[u8; 16]>("key", None)
.unwrap();
let key_ref = follower_thread.new_blind_input::<[u8; 16]>("key").unwrap();
let msg_ref = follower_thread
.new_private_input::<[u8; 16]>("msg", Some(msg))
.new_private_input::<[u8; 16]>("msg")
.unwrap();
let ciphertext_ref = follower_thread
.new_output::<[u8; 16]>("ciphertext")
.unwrap();

follower_thread.assign(&msg_ref, msg).unwrap();

async {
follower_thread
.execute(
Expand All @@ -75,10 +73,13 @@ fn bench_aes_leader<T: Thread + Execute + Decode + Send>(
block: usize,
) -> Pin<Box<dyn Future<Output = Result<[u8; 16], VmError>> + Send + '_>> {
Box::pin(async move {
let key = thread.new_private_input(&format!("key/{block}"), Some([0u8; 16]))?;
let msg = thread.new_private_input(&format!("msg/{block}"), Some([0u8; 16]))?;
let key = thread.new_private_input::<[u8; 16]>(&format!("key/{block}"))?;
let msg = thread.new_private_input::<[u8; 16]>(&format!("msg/{block}"))?;
let ciphertext = thread.new_output::<[u8; 16]>(&format!("ciphertext/{block}"))?;

thread.assign(&key, [0u8; 16])?;
thread.assign(&msg, [0u8; 16])?;

thread
.execute(AES128.clone(), &[key, msg], &[ciphertext.clone()])
.await?;
Expand All @@ -94,8 +95,8 @@ fn bench_aes_follower<T: Thread + Execute + Decode + Send>(
block: usize,
) -> Pin<Box<dyn Future<Output = Result<[u8; 16], VmError>> + Send + '_>> {
Box::pin(async move {
let key = thread.new_private_input::<[u8; 16]>(&format!("key/{block}"), None)?;
let msg = thread.new_private_input::<[u8; 16]>(&format!("msg/{block}"), None)?;
let key = thread.new_blind_input::<[u8; 16]>(&format!("key/{block}"))?;
let msg = thread.new_blind_input::<[u8; 16]>(&format!("msg/{block}"))?;
let ciphertext = thread.new_output::<[u8; 16]>(&format!("ciphertext/{block}"))?;

thread
Expand Down
226 changes: 6 additions & 220 deletions garble/mpz-garble/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
//! Various configuration used in the protocol

use mpz_circuits::types::{StaticValueType, Value, ValueType};
use mpz_core::value::{ValueId, ValueRef};

/// Role in 2PC.
#[derive(Debug, Clone, Copy, PartialEq)]
#[allow(missing_docs)]
Expand All @@ -11,224 +8,13 @@ pub enum Role {
Follower,
}

#[derive(Debug)]
#[allow(missing_docs)]
#[allow(dead_code)]
pub struct ValueConfigError {
value_ref: ValueRef,
ty: ValueType,
value: Option<Value>,
visibility: Visibility,
}

/// Visibility of a value
#[derive(Debug, Clone, Copy)]
pub(crate) enum Visibility {
pub enum Visibility {
/// A value known to all parties
Public,
/// A private value known to this party.
Private,
}

/// Configuration of a value
#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub enum ValueConfig {
/// A value known to all parties
Public {
value_ref: ValueRef,
ty: ValueType,
value: Value,
},
/// A private value
Private {
value_ref: ValueRef,
ty: ValueType,
value: Option<Value>,
},
}

/// Configuration of a value
#[derive(Debug, Clone)]
#[allow(missing_docs)]
pub enum ValueIdConfig {
/// A value known to all parties
Public {
id: ValueId,
ty: ValueType,
value: Value,
},
/// A private value
Private {
id: ValueId,
ty: ValueType,
value: Option<Value>,
},
}

impl ValueConfig {
/// Creates a new public value config
pub fn new_public<T: StaticValueType>(
value_ref: ValueRef,
value: impl Into<Value>,
) -> Result<Self, ValueConfigError> {
let value = value.into();
let ty = value.value_type();
Self::new(value_ref, ty, Some(value), Visibility::Public)
}

/// Creates a new public array value config
pub fn new_public_array<T: StaticValueType>(
value_ref: ValueRef,
value: Vec<T>,
) -> Result<Self, ValueConfigError>
where
Vec<T>: Into<Value>,
{
let value = value.into();
let ty = value.value_type();
Self::new(value_ref, ty, Some(value), Visibility::Public)
}

/// Creates a new private value config
pub fn new_private<T: StaticValueType>(
value_ref: ValueRef,
value: Option<T>,
) -> Result<Self, ValueConfigError> {
let ty = T::value_type();
let value = value.map(|value| value.into());
Self::new(value_ref, ty, value, Visibility::Private)
}

/// Creates a new private array value config
pub fn new_private_array<T: StaticValueType>(
value_ref: ValueRef,
value: Option<Vec<T>>,
len: usize,
) -> Result<Self, ValueConfigError>
where
Vec<T>: Into<Value>,
{
let ty = ValueType::new_array::<T>(len);
let value = value.map(|value| value.into());
Self::new(value_ref, ty, value, Visibility::Private)
}

/// Creates a new value config
pub(crate) fn new(
value_ref: ValueRef,
ty: ValueType,
value: Option<Value>,
visibility: Visibility,
) -> Result<Self, ValueConfigError> {
// invariants:
// - public values are always set
// - types and lengths are consistent across `value_ref`, `ty`, and `value`
//
// the outer context must ensure that the provided `ty` is correct for the
// provided `value_ref`.
let is_ok = if !value_ref.is_array() && !ty.is_array() {
true
} else if let (ValueRef::Array(ids), ValueType::Array(_, len)) = (&value_ref, &ty) {
ids.len() == *len
} else {
false
};

match visibility {
Visibility::Public if is_ok && value.is_some() => Ok(Self::Public {
value_ref,
ty,
value: value.unwrap(),
}),
Visibility::Private if is_ok => Ok(Self::Private {
value_ref,
ty,
value,
}),
_ => Err(ValueConfigError {
value_ref,
ty,
value,
visibility,
}),
}
}

/// Flattens to a vector of `ValueIdConfig`
pub fn flatten(self) -> Vec<ValueIdConfig> {
match self {
ValueConfig::Public {
value_ref,
ty,
value,
} => match value_ref {
ValueRef::Value { id } => {
vec![ValueIdConfig::Public { id, ty, value }]
}
ValueRef::Array(ids) => {
let ValueType::Array(elem_ty, _) = ty else {
panic!("expected array type");
};

let elem_ty = *elem_ty;

let Value::Array(value) = value else {
panic!("expected array value");
};

ids.into_iter()
.zip(value)
.map(|(id, value)| ValueIdConfig::Public {
id,
ty: elem_ty.clone(),
value,
})
.collect()
}
},
ValueConfig::Private {
value_ref,
ty,
value,
} => match value_ref {
ValueRef::Value { id } => {
vec![ValueIdConfig::Private { id, ty, value }]
}
ValueRef::Array(ids) => {
let ValueType::Array(elem_ty, _) = ty else {
panic!("expected array type");
};

let elem_ty = *elem_ty;

let values = if let Some(value) = value {
let Value::Array(value) = value else {
panic!("expected array value");
};

value.into_iter().map(Option::Some).collect()
} else {
vec![None; ids.len()]
};

ids.into_iter()
.zip(values)
.map(|(id, value)| ValueIdConfig::Private {
id,
ty: elem_ty.clone(),
value,
})
.collect()
}
},
}
}
}

impl ValueIdConfig {
/// Returns the ID of the value
pub(crate) fn id(&self) -> &ValueId {
match self {
ValueIdConfig::Public { id, .. } => id,
ValueIdConfig::Private { id, .. } => id,
}
}
/// A private value not known to this party.
Blind,
}
4 changes: 2 additions & 2 deletions garble/mpz-garble/src/evaluator/error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use mpz_core::value::{ValueId, ValueRef};
use crate::value::{ValueId, ValueRef};

/// Errors that can occur while performing the role of an evaluator
#[derive(Debug, thiserror::Error)]
Expand All @@ -18,7 +18,7 @@ pub enum EvaluatorError {
#[error(transparent)]
ValueError(#[from] mpz_garble_core::ValueError),
#[error(transparent)]
EncodingRegistryError(#[from] crate::registry::EncodingRegistryError),
EncodingRegistryError(#[from] crate::memory::EncodingMemoryError),
#[error("missing active encoding for value")]
MissingEncoding(ValueRef),
#[error("duplicate decoding for value: {0:?}")]
Expand Down
Loading