瀏覽代碼

oram: add doc comments

Lennart Braun 1 年之前
父節點
當前提交
bf09d1800f
共有 11 個文件被更改,包括 299 次插入13 次删除
  1. 4 0
      oram/examples/bench_doprf.rs
  2. 4 0
      oram/examples/bench_doram.rs
  3. 15 0
      oram/src/common.rs
  4. 141 1
      oram/src/doprf.rs
  5. 4 0
      oram/src/lib.rs
  6. 14 0
      oram/src/mask_index.rs
  7. 27 0
      oram/src/oram.rs
  8. 37 0
      oram/src/p_ot.rs
  9. 8 2
      oram/src/select.rs
  10. 27 7
      oram/src/stash.rs
  11. 18 3
      oram/src/tools.rs

+ 4 - 0
oram/examples/bench_doprf.rs

@@ -1,3 +1,7 @@
+//! Benchmarking program for the DOPRF protocols.
+//!
+//! Use --help to see available options.
+
 use clap::{CommandFactory, Parser};
 use communicator::tcp::{make_tcp_communicator, NetworkOptions, NetworkPartyInfo};
 use communicator::AbstractCommunicator;

+ 4 - 0
oram/examples/bench_doram.rs

@@ -1,3 +1,7 @@
+//! Benchmarking program for the DORAM protocol.
+//!
+//! Use --help to see available options.
+
 use clap::{CommandFactory, Parser};
 use communicator::tcp::{make_tcp_communicator, NetworkOptions, NetworkPartyInfo};
 use communicator::{AbstractCommunicator, CommunicationStats};

+ 15 - 0
oram/src/common.rs

@@ -1,18 +1,27 @@
+//! Basic types for the DORAM implementation.
 use communicator::Error as CommunicationError;
 use ff::PrimeField;
 
+/// Type of an access operation.
 pub enum Operation {
+    /// Read from the memory.
     Read,
+    /// Write to the memory.
     Write,
 }
 
 impl Operation {
+    /// Encode an access operation as field element.
+    ///
+    /// Read is encoded as 0, and Write is encoded as 1.
     pub fn encode<F: PrimeField>(&self) -> F {
         match self {
             Self::Read => F::ZERO,
             Self::Write => F::ONE,
         }
     }
+
+    /// Decode an encoded operation again.
     pub fn decode<F: PrimeField>(encoded_op: F) -> Self {
         if encoded_op == F::ZERO {
             Self::Read
@@ -24,15 +33,21 @@ impl Operation {
     }
 }
 
+/// Define an additive share of an access instruction.
 #[derive(Clone, Copy, Debug, Default)]
 pub struct InstructionShare<F: PrimeField> {
+    /// Whether it is a read (0) or a write (1).
     pub operation: F,
+    /// The address to access.
     pub address: F,
+    /// The value that should (possibly) be written into memory.
     pub value: F,
 }
 
+/// Custom error type used in this library.
 #[derive(Debug)]
 pub enum Error {
+    /// Wrap a [`communicator::Error`].
     CommunicationError(CommunicationError),
 }
 

+ 141 - 1
oram/src/doprf.rs

@@ -1,3 +1,7 @@
+//! Implementation of the Legendre PRF and protocols for the distributed oblivious PRF evaluation.
+//!
+//! Contains the unmasked and the masked variants.
+
 use crate::common::Error;
 use bincode;
 use bitvec;
@@ -10,26 +14,31 @@ use rand_chacha::ChaChaRng;
 use std::iter::repeat;
 use utils::field::LegendreSymbol;
 
+/// Bit vector.
 pub type BitVec = bitvec::vec::BitVec<u8>;
 type BitSlice = bitvec::slice::BitSlice<u8>;
 
+/// Key for a [`LegendrePrf`].
 #[derive(Clone, Debug, Eq, PartialEq, bincode::Encode, bincode::Decode)]
 pub struct LegendrePrfKey<F: LegendreSymbol> {
+    /// Keys for each output bit.
     pub keys: Vec<F>,
 }
 
 impl<F: LegendreSymbol> LegendrePrfKey<F> {
+    /// Return the number of bits output by the PRF.
     pub fn get_output_bitsize(&self) -> usize {
         self.keys.len()
     }
 }
 
-/// Legendre PRF: F x F -> {0,1}^k
+/// Multi-bit Legendre PRF: `F x F -> {0,1}^k`.
 pub struct LegendrePrf<F> {
     _phantom: PhantomData<F>,
 }
 
 impl<F: LegendreSymbol> LegendrePrf<F> {
+    /// Generate a Legendre PRF key for the given number of output bits.
     pub fn key_gen(output_bitsize: usize) -> LegendrePrfKey<F> {
         LegendrePrfKey {
             keys: (0..output_bitsize)
@@ -38,6 +47,7 @@ impl<F: LegendreSymbol> LegendrePrf<F> {
         }
     }
 
+    /// Evaluate the PRF to obtain an iterator of bits.
     pub fn eval(key: &LegendrePrfKey<F>, input: F) -> impl Iterator<Item = bool> + '_ {
         key.keys.iter().map(move |&k| {
             let ls = F::legendre_symbol(k + input);
@@ -46,12 +56,14 @@ impl<F: LegendreSymbol> LegendrePrf<F> {
         })
     }
 
+    /// Evaluate the PRF to obtain a bit vector.
     pub fn eval_bits(key: &LegendrePrfKey<F>, input: F) -> BitVec {
         let mut output = BitVec::with_capacity(key.keys.len());
         output.extend(Self::eval(key, input));
         output
     }
 
+    /// Evaluate the PRF to obtain an integer.
     pub fn eval_to_uint<T: Unsigned>(key: &LegendrePrfKey<F>, input: F) -> T {
         assert!(key.keys.len() <= T::BITS as usize);
         let mut output = T::ZERO;
@@ -80,6 +92,7 @@ fn to_uint<T: Unsigned>(vs: impl IntoIterator<Item = impl IntoIterator<Item = bo
 
 type SharedSeed = [u8; 32];
 
+/// Party 1 of the *unmasked* DOPRF protocol.
 pub struct DOPrfParty1<F: LegendreSymbol> {
     _phantom: PhantomData<F>,
     output_bitsize: usize,
@@ -96,6 +109,7 @@ impl<F> DOPrfParty1<F>
 where
     F: LegendreSymbol,
 {
+    /// Create a new instance with the given `output_bitsize`.
     pub fn new(output_bitsize: usize) -> Self {
         assert!(output_bitsize > 0);
         Self {
@@ -111,22 +125,26 @@ where
         }
     }
 
+    /// Create an instance from an existing Legendre PRF key.
     pub fn from_legendre_prf_key(legendre_prf_key: LegendrePrfKey<F>) -> Self {
         let mut new = Self::new(legendre_prf_key.keys.len());
         new.legendre_prf_key = Some(legendre_prf_key);
         new
     }
 
+    /// Reset this instance.
     pub fn reset(&mut self) {
         *self = Self::new(self.output_bitsize)
     }
 
+    /// Delete all preprocessed data.
     pub fn reset_preprocessing(&mut self) {
         self.num_preprocessed_invocations = 0;
         self.preprocessed_squares = Default::default();
         self.preprocessed_mt_c1 = Default::default();
     }
 
+    /// Step 0 of the initialization protocol.
     pub fn init_round_0(&mut self) -> (SharedSeed, ()) {
         assert!(!self.is_initialized);
         // sample and share a PRF key with Party 2
@@ -134,6 +152,7 @@ where
         (self.shared_prg_1_2.as_ref().unwrap().get_seed(), ())
     }
 
+    /// Step 1 of the initialization protocol.
     pub fn init_round_1(&mut self, _: (), shared_prg_seed_1_3: SharedSeed) {
         assert!(!self.is_initialized);
         // receive shared PRF key from Party 3
@@ -145,6 +164,7 @@ where
         self.is_initialized = true;
     }
 
+    /// Run the initialization protocol.
     pub fn init<C: AbstractCommunicator>(&mut self, comm: &mut C) -> Result<(), Error> {
         let fut_3_1 = comm.receive_previous()?;
         let (msg_1_2, _) = self.init_round_0();
@@ -153,16 +173,21 @@ where
         Ok(())
     }
 
+    /// Return the Legendre PRF key.
     pub fn get_legendre_prf_key(&self) -> LegendrePrfKey<F> {
         assert!(self.legendre_prf_key.is_some());
         self.legendre_prf_key.as_ref().unwrap().clone()
     }
 
+    /// Set the Legendre PRF key.
+    ///
+    /// Can only done before the initialization protocol is run.
     pub fn set_legendre_prf_key(&mut self, legendre_prf_key: LegendrePrfKey<F>) {
         assert!(!self.is_initialized);
         self.legendre_prf_key = Some(legendre_prf_key);
     }
 
+    /// Step 0 of the preprocessing protocol.
     pub fn preprocess_round_0(&mut self, num: usize) -> ((), ()) {
         assert!(self.is_initialized);
         let n = num * self.output_bitsize;
@@ -171,6 +196,7 @@ where
         ((), ())
     }
 
+    /// Step 1 of the preprocessing protocol.
     pub fn preprocess_round_1(&mut self, num: usize, preprocessed_mt_c1: Vec<F>, _: ()) {
         assert!(self.is_initialized);
         let n = num * self.output_bitsize;
@@ -179,6 +205,7 @@ where
         self.num_preprocessed_invocations += num;
     }
 
+    /// Run the preprocessing protocol for `num` evaluations.
     pub fn preprocess<C: AbstractCommunicator>(
         &mut self,
         comm: &mut C,
@@ -193,14 +220,19 @@ where
         Ok(())
     }
 
+    /// Return the number of preprocessed invocations available.
     pub fn get_num_preprocessed_invocations(&self) -> usize {
         self.num_preprocessed_invocations
     }
 
+    /// Return the preprocessed data.
+    #[doc(hidden)]
     pub fn get_preprocessed_data(&self) -> (&[F], &[F]) {
         (&self.preprocessed_squares, &self.preprocessed_mt_c1)
     }
 
+    /// Perform some self-test of the preprocessed data.
+    #[doc(hidden)]
     pub fn check_preprocessing(&self) {
         let num = self.num_preprocessed_invocations;
         let n = num * self.output_bitsize;
@@ -208,6 +240,7 @@ where
         assert_eq!(self.preprocessed_mt_c1.len(), n);
     }
 
+    /// Step 1 of the evaluation protocol.
     pub fn eval_round_1(
         &mut self,
         num: usize,
@@ -244,6 +277,7 @@ where
         ((), output_shares_z1)
     }
 
+    /// Run the evaluation protocol.
     pub fn eval<C: AbstractCommunicator>(
         &mut self,
         comm: &mut C,
@@ -262,6 +296,7 @@ where
     }
 }
 
+/// Party 2 of the *unmasked* DOPRF protocol.
 pub struct DOPrfParty2<F: LegendreSymbol> {
     _phantom: PhantomData<F>,
     output_bitsize: usize,
@@ -276,6 +311,7 @@ impl<F> DOPrfParty2<F>
 where
     F: LegendreSymbol,
 {
+    /// Create a new instance with the given `output_bitsize`.
     pub fn new(output_bitsize: usize) -> Self {
         assert!(output_bitsize > 0);
         Self {
@@ -289,21 +325,25 @@ where
         }
     }
 
+    /// Reset this instance.
     pub fn reset(&mut self) {
         *self = Self::new(self.output_bitsize)
     }
 
+    /// Delete all preprocessed data.
     pub fn reset_preprocessing(&mut self) {
         self.num_preprocessed_invocations = 0;
         self.preprocessed_rerand_m2 = Default::default();
     }
 
+    /// Step 0 of the initialization protocol.
     pub fn init_round_0(&mut self) -> ((), SharedSeed) {
         assert!(!self.is_initialized);
         self.shared_prg_2_3 = Some(ChaChaRng::from_seed(thread_rng().gen()));
         ((), self.shared_prg_2_3.as_ref().unwrap().get_seed())
     }
 
+    /// Step 1 of the initialization protocol.
     pub fn init_round_1(&mut self, shared_prg_seed_1_2: SharedSeed, _: ()) {
         assert!(!self.is_initialized);
         // receive shared PRF key from Party 1
@@ -311,6 +351,7 @@ where
         self.is_initialized = true;
     }
 
+    /// Run the initialization protocol.
     pub fn init<C: AbstractCommunicator>(&mut self, comm: &mut C) -> Result<(), Error> {
         let fut_1_2 = comm.receive_previous()?;
         let (_, msg_2_3) = self.init_round_0();
@@ -319,6 +360,7 @@ where
         Ok(())
     }
 
+    /// Step 0 of the preprocessing protocol.
     pub fn preprocess_round_0(&mut self, num: usize) -> (Vec<F>, ()) {
         assert!(self.is_initialized);
         let n = num * self.output_bitsize;
@@ -351,10 +393,12 @@ where
         (preprocessed_c1, ())
     }
 
+    /// Step 1 of the preprocessing protocol.
     pub fn preprocess_round_1(&mut self, _: usize, _: (), _: ()) {
         assert!(self.is_initialized);
     }
 
+    /// Run the preprocessing protocol for `num` evaluations.
     pub fn preprocess<C: AbstractCommunicator>(
         &mut self,
         comm: &mut C,
@@ -369,19 +413,25 @@ where
         Ok(())
     }
 
+    /// Return the number of preprocessed invocations available.
     pub fn get_num_preprocessed_invocations(&self) -> usize {
         self.num_preprocessed_invocations
     }
 
+    /// Return the preprocessed data.
+    #[doc(hidden)]
     pub fn get_preprocessed_data(&self) -> &[F] {
         &self.preprocessed_rerand_m2
     }
 
+    /// Perform some self-test of the preprocessed data.
+    #[doc(hidden)]
     pub fn check_preprocessing(&self) {
         let num = self.num_preprocessed_invocations;
         assert_eq!(self.preprocessed_rerand_m2.len(), num);
     }
 
+    /// Step 0 of the evaluation protocol.
     pub fn eval_round_0(&mut self, num: usize, shares2: &[F]) -> (Vec<F>, ()) {
         assert!(num <= self.num_preprocessed_invocations);
         assert_eq!(shares2.len(), num);
@@ -393,6 +443,7 @@ where
         (masked_shares2, ())
     }
 
+    /// Run the evaluation protocol.
     pub fn eval<C: AbstractCommunicator>(
         &mut self,
         comm: &mut C,
@@ -409,6 +460,7 @@ where
     }
 }
 
+/// Party 3 of the *unmasked* DOPRF protocol.
 pub struct DOPrfParty3<F: LegendreSymbol> {
     _phantom: PhantomData<F>,
     output_bitsize: usize,
@@ -427,6 +479,7 @@ impl<F> DOPrfParty3<F>
 where
     F: LegendreSymbol,
 {
+    /// Create a new instance with the given `output_bitsize`.
     pub fn new(output_bitsize: usize) -> Self {
         assert!(output_bitsize > 0);
         Self {
@@ -444,10 +497,12 @@ where
         }
     }
 
+    /// Reset this instance.
     pub fn reset(&mut self) {
         *self = Self::new(self.output_bitsize)
     }
 
+    /// Delete all preprocessed data.
     pub fn reset_preprocessing(&mut self) {
         self.num_preprocessed_invocations = 0;
         self.preprocessed_rerand_m3 = Default::default();
@@ -457,17 +512,20 @@ where
         self.mult_e = Default::default();
     }
 
+    /// Step 0 of the initialization protocol.
     pub fn init_round_0(&mut self) -> (SharedSeed, ()) {
         assert!(!self.is_initialized);
         self.shared_prg_1_3 = Some(ChaChaRng::from_seed(thread_rng().gen()));
         (self.shared_prg_1_3.as_ref().unwrap().get_seed(), ())
     }
 
+    /// Step 1 of the initialization protocol.
     pub fn init_round_1(&mut self, _: (), shared_prg_seed_2_3: SharedSeed) {
         self.shared_prg_2_3 = Some(ChaChaRng::from_seed(shared_prg_seed_2_3));
         self.is_initialized = true;
     }
 
+    /// Run the initialization protocol.
     pub fn init<C: AbstractCommunicator>(&mut self, comm: &mut C) -> Result<(), Error> {
         let fut_2_3 = comm.receive_previous()?;
         let (msg_3_1, _) = self.init_round_0();
@@ -476,6 +534,7 @@ where
         Ok(())
     }
 
+    /// Step 0 of the preprocessing protocol.
     pub fn preprocess_round_0(&mut self, num: usize) -> ((), ()) {
         assert!(self.is_initialized);
         let n = num * self.output_bitsize;
@@ -491,11 +550,13 @@ where
         ((), ())
     }
 
+    /// Step 1 of the preprocessing protocol.
     pub fn preprocess_round_1(&mut self, num: usize, _: (), _: ()) {
         assert!(self.is_initialized);
         self.num_preprocessed_invocations += num;
     }
 
+    /// Run the preprocessing protocol for `num` evaluations.
     pub fn preprocess<C: AbstractCommunicator>(
         &mut self,
         _comm: &mut C,
@@ -509,10 +570,13 @@ where
         Ok(())
     }
 
+    /// Return the number of preprocessed invocations available.
     pub fn get_num_preprocessed_invocations(&self) -> usize {
         self.num_preprocessed_invocations
     }
 
+    /// Return the preprocessed data.
+    #[doc(hidden)]
     pub fn get_preprocessed_data(&self) -> (&[F], &[F], &[F], &[F]) {
         (
             &self.preprocessed_rerand_m3,
@@ -522,6 +586,8 @@ where
         )
     }
 
+    /// Perform some self-test of the preprocessed data.
+    #[doc(hidden)]
     pub fn check_preprocessing(&self) {
         let num = self.num_preprocessed_invocations;
         let n = num * self.output_bitsize;
@@ -531,6 +597,7 @@ where
         assert_eq!(self.preprocessed_mult_d.len(), n);
     }
 
+    /// Step 0 of the evaluation protocol.
     pub fn eval_round_0(&mut self, num: usize, shares3: &[F]) -> (Vec<F>, ()) {
         assert!(num <= self.num_preprocessed_invocations);
         assert_eq!(shares3.len(), num);
@@ -544,6 +611,7 @@ where
         (self.mult_e.clone(), ())
     }
 
+    /// Step 2 of the evaluation protocol.
     pub fn eval_round_2(
         &mut self,
         num: usize,
@@ -590,6 +658,7 @@ where
         output
     }
 
+    /// Run the evaluation protocol to obtain bit vectors.
     pub fn eval<C: AbstractCommunicator>(
         &mut self,
         comm: &mut C,
@@ -607,6 +676,7 @@ where
         Ok(output)
     }
 
+    /// Run the evaluation protocol to obtain integers.
     pub fn eval_to_uint<C: AbstractCommunicator, T: Unsigned>(
         &mut self,
         comm: &mut C,
@@ -621,6 +691,8 @@ where
     }
 }
 
+/// Combination of three instances of the *unmasked* DOPRF protocol such that this party acts as
+/// each role 1, 2, 3 in the different instances.
 pub struct JointDOPrf<F: LegendreSymbol> {
     output_bitsize: usize,
     doprf_p1_prev: DOPrfParty1<F>,
@@ -629,6 +701,7 @@ pub struct JointDOPrf<F: LegendreSymbol> {
 }
 
 impl<F: LegendreSymbol + Serializable> JointDOPrf<F> {
+    /// Create a new instance with the given `output_bitsize`.
     pub fn new(output_bitsize: usize) -> Self {
         Self {
             output_bitsize,
@@ -638,18 +711,24 @@ impl<F: LegendreSymbol + Serializable> JointDOPrf<F> {
         }
     }
 
+    /// Reset this instance.
     pub fn reset(&mut self) {
         *self = Self::new(self.output_bitsize);
     }
 
+    /// Return the Legendre PRF key.
     pub fn get_legendre_prf_key_prev(&self) -> LegendrePrfKey<F> {
         self.doprf_p1_prev.get_legendre_prf_key()
     }
 
+    /// Set the Legendre PRF key.
+    ///
+    /// Can only done before the initialization protocol is run.
     pub fn set_legendre_prf_key_prev(&mut self, legendre_prf_key: LegendrePrfKey<F>) {
         self.doprf_p1_prev.set_legendre_prf_key(legendre_prf_key)
     }
 
+    /// Run the initialization protocol.
     pub fn init<C: AbstractCommunicator>(&mut self, comm: &mut C) -> Result<(), Error> {
         let fut_prev = comm.receive_previous()?;
         let (msg_1_2, _) = self.doprf_p1_prev.init_round_0();
@@ -663,6 +742,7 @@ impl<F: LegendreSymbol + Serializable> JointDOPrf<F> {
         Ok(())
     }
 
+    /// Run the preprocessing protocol for `num` evaluations.
     pub fn preprocess<C: AbstractCommunicator>(
         &mut self,
         comm: &mut C,
@@ -680,6 +760,7 @@ impl<F: LegendreSymbol + Serializable> JointDOPrf<F> {
         Ok(())
     }
 
+    /// Run the evaluation protocol to obtain integers.
     pub fn eval_to_uint<C: AbstractCommunicator, T: Unsigned>(
         &mut self,
         comm: &mut C,
@@ -710,6 +791,7 @@ impl<F: LegendreSymbol + Serializable> JointDOPrf<F> {
     }
 }
 
+/// Party 1 of the *masked* DOPRF protocol.
 pub struct MaskedDOPrfParty1<F: LegendreSymbol> {
     _phantom: PhantomData<F>,
     output_bitsize: usize,
@@ -729,6 +811,7 @@ impl<F> MaskedDOPrfParty1<F>
 where
     F: LegendreSymbol,
 {
+    /// Create a new instance with the given `output_bitsize`.
     pub fn new(output_bitsize: usize) -> Self {
         assert!(output_bitsize > 0);
         Self {
@@ -747,16 +830,19 @@ where
         }
     }
 
+    /// Create an instance from an existing Legendre PRF key.
     pub fn from_legendre_prf_key(legendre_prf_key: LegendrePrfKey<F>) -> Self {
         let mut new = Self::new(legendre_prf_key.keys.len());
         new.legendre_prf_key = Some(legendre_prf_key);
         new
     }
 
+    /// Reset this instance.
     pub fn reset(&mut self) {
         *self = Self::new(self.output_bitsize)
     }
 
+    /// Delete all preprocessed data.
     pub fn reset_preprocessing(&mut self) {
         self.num_preprocessed_invocations = 0;
         self.preprocessed_rerand_m1 = Default::default();
@@ -765,6 +851,7 @@ where
         self.preprocessed_mult_e = Default::default();
     }
 
+    /// Step 0 of the initialization protocol.
     pub fn init_round_0(&mut self) -> (SharedSeed, ()) {
         assert!(!self.is_initialized);
         // sample and share a PRF key with Party 2
@@ -772,6 +859,7 @@ where
         (self.shared_prg_1_2.as_ref().unwrap().get_seed(), ())
     }
 
+    /// Step 1 of the initialization protocol.
     pub fn init_round_1(&mut self, _: (), shared_prg_seed_1_3: SharedSeed) {
         assert!(!self.is_initialized);
         // receive shared PRF key from Party 3
@@ -783,6 +871,7 @@ where
         self.is_initialized = true;
     }
 
+    /// Run the initialization protocol.
     pub fn init<C: AbstractCommunicator>(&mut self, comm: &mut C) -> Result<(), Error> {
         let fut_3_1 = comm.receive_previous()?;
         let (msg_1_2, _) = self.init_round_0();
@@ -791,11 +880,13 @@ where
         Ok(())
     }
 
+    /// Return the Legendre PRF key.
     pub fn get_legendre_prf_key(&self) -> LegendrePrfKey<F> {
         assert!(self.is_initialized);
         self.legendre_prf_key.as_ref().unwrap().clone()
     }
 
+    /// Step 0 of the preprocessing protocol.
     pub fn preprocess_round_0(&mut self, num: usize) -> ((), ()) {
         assert!(self.is_initialized);
         let n = num * self.output_bitsize;
@@ -810,11 +901,13 @@ where
         ((), ())
     }
 
+    /// Step 1 of the preprocessing protocol.
     pub fn preprocess_round_1(&mut self, num: usize, _: (), _: ()) {
         assert!(self.is_initialized);
         self.num_preprocessed_invocations += num;
     }
 
+    /// Run the preprocessing protocol for `num` evaluations.
     pub fn preprocess<C: AbstractCommunicator>(
         &mut self,
         _comm: &mut C,
@@ -825,10 +918,13 @@ where
         Ok(())
     }
 
+    /// Return the number of preprocessed invocations available.
     pub fn get_num_preprocessed_invocations(&self) -> usize {
         self.num_preprocessed_invocations
     }
 
+    /// Return the preprocessed data.
+    #[doc(hidden)]
     pub fn get_preprocessed_data(&self) -> (&[F], &[F], &[F], &[F]) {
         (
             &self.preprocessed_rerand_m1,
@@ -838,6 +934,8 @@ where
         )
     }
 
+    /// Perform some self-test of the preprocessed data.
+    #[doc(hidden)]
     pub fn check_preprocessing(&self) {
         let num = self.num_preprocessed_invocations;
         let n = num * self.output_bitsize;
@@ -847,6 +945,7 @@ where
         assert_eq!(self.preprocessed_mult_e.len(), n);
     }
 
+    /// Step 0 of the evaluation protocol.
     pub fn eval_round_0(&mut self, num: usize, shares1: &[F]) -> ((), Vec<F>) {
         assert!(num <= self.num_preprocessed_invocations);
         assert_eq!(shares1.len(), num);
@@ -869,6 +968,7 @@ where
         ((), self.mult_d.clone())
     }
 
+    /// Step 2 of the evaluation protocol.
     pub fn eval_round_2(
         &mut self,
         num: usize,
@@ -915,6 +1015,7 @@ where
         output
     }
 
+    /// Run the evaluation protocol to obtain bit vectors.
     pub fn eval<C: AbstractCommunicator>(
         &mut self,
         comm: &mut C,
@@ -932,6 +1033,7 @@ where
         Ok(output)
     }
 
+    /// Run the evaluation protocol to obtain integers.
     pub fn eval_to_uint<C: AbstractCommunicator, T: Unsigned>(
         &mut self,
         comm: &mut C,
@@ -946,6 +1048,7 @@ where
     }
 }
 
+/// Party 2 of the *masked* DOPRF protocol.
 pub struct MaskedDOPrfParty2<F: LegendreSymbol> {
     _phantom: PhantomData<F>,
     output_bitsize: usize,
@@ -961,6 +1064,7 @@ impl<F> MaskedDOPrfParty2<F>
 where
     F: LegendreSymbol,
 {
+    /// Create a new instance with the given `output_bitsize`.
     pub fn new(output_bitsize: usize) -> Self {
         assert!(output_bitsize > 0);
         Self {
@@ -975,21 +1079,25 @@ where
         }
     }
 
+    /// Reset this instance.
     pub fn reset(&mut self) {
         *self = Self::new(self.output_bitsize)
     }
 
+    /// Delete all preprocessed data.
     pub fn reset_preprocessing(&mut self) {
         self.num_preprocessed_invocations = 0;
         self.preprocessed_rerand_m2 = Default::default();
     }
 
+    /// Step 0 of the initialization protocol.
     pub fn init_round_0(&mut self) -> ((), SharedSeed) {
         assert!(!self.is_initialized);
         self.shared_prg_2_3 = Some(ChaChaRng::from_seed(thread_rng().gen()));
         ((), self.shared_prg_2_3.as_ref().unwrap().get_seed())
     }
 
+    /// Step 1 of the initialization protocol.
     pub fn init_round_1(&mut self, shared_prg_seed_1_2: SharedSeed, _: ()) {
         assert!(!self.is_initialized);
         // receive shared PRF key from Party 1
@@ -997,6 +1105,7 @@ where
         self.is_initialized = true;
     }
 
+    /// Run the initialization protocol.
     pub fn init<C: AbstractCommunicator>(&mut self, comm: &mut C) -> Result<(), Error> {
         let fut_1_2 = comm.receive_previous()?;
         let (_, msg_2_3) = self.init_round_0();
@@ -1005,6 +1114,7 @@ where
         Ok(())
     }
 
+    /// Step 0 of the preprocessing protocol.
     pub fn preprocess_round_0(&mut self, num: usize) -> ((), Vec<F>) {
         assert!(self.is_initialized);
         let n = num * self.output_bitsize;
@@ -1050,10 +1160,12 @@ where
         ((), preprocessed_c3)
     }
 
+    /// Step 1 of the preprocessing protocol.
     pub fn preprocess_round_1(&mut self, _: usize, _: (), _: ()) {
         assert!(self.is_initialized);
     }
 
+    /// Run the preprocessing protocol for `num` evaluations.
     pub fn preprocess<C: AbstractCommunicator>(
         &mut self,
         comm: &mut C,
@@ -1068,19 +1180,25 @@ where
         Ok(())
     }
 
+    /// Return the number of preprocessed invocations available.
     pub fn get_num_preprocessed_invocations(&self) -> usize {
         self.num_preprocessed_invocations
     }
 
+    /// Return the preprocessed data.
+    #[doc(hidden)]
     pub fn get_preprocessed_data(&self) -> (&BitSlice, &[F]) {
         (&self.preprocessed_r, &self.preprocessed_rerand_m2)
     }
 
+    /// Perform some self-test of the preprocessed data.
+    #[doc(hidden)]
     pub fn check_preprocessing(&self) {
         let num = self.num_preprocessed_invocations;
         assert_eq!(self.preprocessed_rerand_m2.len(), num);
     }
 
+    /// Step 0 of the evaluation protocol.
     pub fn eval_round_0(&mut self, num: usize, shares2: &[F]) -> ((), Vec<F>) {
         assert!(num <= self.num_preprocessed_invocations);
         assert_eq!(shares2.len(), num);
@@ -1092,6 +1210,7 @@ where
         ((), masked_shares2)
     }
 
+    /// Final step of the evaluation protocol.
     pub fn eval_get_output(&mut self, num: usize) -> Vec<BitVec> {
         assert!(num <= self.num_preprocessed_invocations);
         let n = num * self.output_bitsize;
@@ -1109,6 +1228,7 @@ where
         output
     }
 
+    /// Run the evaluation protocol to obtain bit vectors.
     pub fn eval<C: AbstractCommunicator>(
         &mut self,
         comm: &mut C,
@@ -1125,6 +1245,7 @@ where
         Ok(output)
     }
 
+    /// Run the evaluation protocol to obtain integers.
     pub fn eval_to_uint<C: AbstractCommunicator, T: Unsigned>(
         &mut self,
         comm: &mut C,
@@ -1139,6 +1260,7 @@ where
     }
 }
 
+/// Party 3 of the *masked* DOPRF protocol.
 pub struct MaskedDOPrfParty3<F: LegendreSymbol> {
     _phantom: PhantomData<F>,
     output_bitsize: usize,
@@ -1155,6 +1277,7 @@ impl<F> MaskedDOPrfParty3<F>
 where
     F: LegendreSymbol,
 {
+    /// Create a new instance with the given `output_bitsize`.
     pub fn new(output_bitsize: usize) -> Self {
         assert!(output_bitsize > 0);
         Self {
@@ -1170,27 +1293,32 @@ where
         }
     }
 
+    /// Reset this instance.
     pub fn reset(&mut self) {
         *self = Self::new(self.output_bitsize)
     }
 
+    /// Delete all preprocessed data.
     pub fn reset_preprocessing(&mut self) {
         self.num_preprocessed_invocations = 0;
         self.preprocessed_t = Default::default();
         self.preprocessed_mt_c3 = Default::default();
     }
 
+    /// Step 0 of the initialization protocol.
     pub fn init_round_0(&mut self) -> (SharedSeed, ()) {
         assert!(!self.is_initialized);
         self.shared_prg_1_3 = Some(ChaChaRng::from_seed(thread_rng().gen()));
         (self.shared_prg_1_3.as_ref().unwrap().get_seed(), ())
     }
 
+    /// Step 1 of the initialization protocol.
     pub fn init_round_1(&mut self, _: (), shared_prg_seed_2_3: SharedSeed) {
         self.shared_prg_2_3 = Some(ChaChaRng::from_seed(shared_prg_seed_2_3));
         self.is_initialized = true;
     }
 
+    /// Run the initialization protocol.
     pub fn init<C: AbstractCommunicator>(&mut self, comm: &mut C) -> Result<(), Error> {
         let fut_2_3 = comm.receive_previous()?;
         let (msg_3_1, _) = self.init_round_0();
@@ -1199,6 +1327,7 @@ where
         Ok(())
     }
 
+    /// Step 0 of the preprocessing protocol.
     pub fn preprocess_round_0(&mut self, num: usize) -> ((), ()) {
         assert!(self.is_initialized);
         let n = num * self.output_bitsize;
@@ -1224,6 +1353,7 @@ where
         ((), ())
     }
 
+    /// Step 1 of the preprocessing protocol.
     pub fn preprocess_round_1(&mut self, num: usize, _: (), preprocessed_mt_c3: Vec<F>) {
         assert!(self.is_initialized);
         let n = num * self.output_bitsize;
@@ -1232,6 +1362,7 @@ where
         self.num_preprocessed_invocations += num;
     }
 
+    /// Run the preprocessing protocol for `num` evaluations.
     pub fn preprocess<C: AbstractCommunicator>(
         &mut self,
         comm: &mut C,
@@ -1246,10 +1377,13 @@ where
         Ok(())
     }
 
+    /// Return the number of preprocessed invocations available.
     pub fn get_num_preprocessed_invocations(&self) -> usize {
         self.num_preprocessed_invocations
     }
 
+    /// Return the preprocessed data.
+    #[doc(hidden)]
     pub fn get_preprocessed_data(&self) -> (&BitSlice, &[F], &[F]) {
         (
             &self.preprocessed_r,
@@ -1258,6 +1392,8 @@ where
         )
     }
 
+    /// Perform some self-test of the preprocessed data.
+    #[doc(hidden)]
     pub fn check_preprocessing(&self) {
         let num = self.num_preprocessed_invocations;
         let n = num * self.output_bitsize;
@@ -1265,6 +1401,7 @@ where
         assert_eq!(self.preprocessed_mt_c3.len(), n);
     }
 
+    /// Step 1 of the evaluation protocol.
     pub fn eval_round_1(
         &mut self,
         num: usize,
@@ -1293,6 +1430,7 @@ where
         (output_shares_z3, ())
     }
 
+    /// Final step of the evaluation protocol.
     pub fn eval_get_output(&mut self, num: usize) -> Vec<BitVec> {
         assert!(num <= self.num_preprocessed_invocations);
         let n = num * self.output_bitsize;
@@ -1310,6 +1448,7 @@ where
         output
     }
 
+    /// Run the evaluation protocol to obtain bit vectors.
     pub fn eval<C: AbstractCommunicator>(
         &mut self,
         comm: &mut C,
@@ -1328,6 +1467,7 @@ where
         Ok(output)
     }
 
+    /// Run the evaluation protocol to obtain integers.
     pub fn eval_to_uint<C: AbstractCommunicator, T: Unsigned>(
         &mut self,
         comm: &mut C,

+ 4 - 0
oram/src/lib.rs

@@ -1,3 +1,7 @@
+//! Implementation of the [Ramen distributed oblivious RAM
+//! protocol](https://eprint.iacr.org/2023/310).
+#![warn(missing_docs)]
+
 pub mod common;
 pub mod doprf;
 pub mod mask_index;

+ 14 - 0
oram/src/mask_index.rs

@@ -1,9 +1,22 @@
+//! Implementation of a protocol to convert a secret shared index in Fp into an equvalent secret
+//! sharing over modulo 2^k.
+//!
+//! The k-bit index is relatively small compared to p. First two parties add a large mask to the
+//! shared index, that statistically hides it, but does not overflow modulo p. The masked index is
+//! reconstruct for the third party.  Finally, all parties locally reduce their mask or masked
+//! value modulo 2^k.
+//!
+//! The protocol runs three instances of this such that at the end each party holds one masked
+//! index and the masks corresponding to the other two parties.
+
 use crate::common::Error;
 use communicator::{AbstractCommunicator, Fut, Serializable};
 use ff::PrimeField;
 use rand::{thread_rng, Rng};
 
+/// Interface specification.
 pub trait MaskIndex<F> {
+    /// Run the mask index protocol where the shared index is at most `index_bits` big.
     fn mask_index<C: AbstractCommunicator>(
         comm: &mut C,
         index_bits: u32,
@@ -11,6 +24,7 @@ pub trait MaskIndex<F> {
     ) -> Result<(u16, u16, u16), Error>;
 }
 
+/// Protocol implementation.
 pub struct MaskIndexProtocol {}
 
 impl<F> MaskIndex<F> for MaskIndexProtocol

+ 27 - 0
oram/src/oram.rs

@@ -1,3 +1,5 @@
+//! Implementation of the main distributed oblivious RAM protocol.
+
 use crate::common::{Error, InstructionShare};
 use crate::doprf::{JointDOPrf, LegendrePrf, LegendrePrfKey};
 use crate::p_ot::JointPOTParties;
@@ -19,28 +21,37 @@ use strum::IntoEnumIterator;
 use utils::field::{FromPrf, LegendreSymbol};
 use utils::permutation::FisherYatesPermutation;
 
+/// Specification of the DORAM interface.
 pub trait DistributedOram<F>
 where
     F: PrimeField,
 {
+    /// Get the current parties ID.
     fn get_party_id(&self) -> usize;
 
+    /// Get the database size.
     fn get_db_size(&self) -> usize;
 
+    /// Run the initialization protocol using the given database share.
     fn init<C: AbstractCommunicator>(&mut self, comm: &mut C, db_share: &[F]) -> Result<(), Error>;
 
+    /// Run the preprocessing protocol for the given `number_epochs`.
     fn preprocess<C: AbstractCommunicator>(
         &mut self,
         comm: &mut C,
         number_epochs: usize,
     ) -> Result<(), Error>;
 
+    /// Run the access protocol for the given shared instruction.
     fn access<C: AbstractCommunicator>(
         &mut self,
         comm: &mut C,
         instruction: InstructionShare<F>,
     ) -> Result<F, Error>;
 
+    /// Get the share of the database.
+    ///
+    /// If `rerandomize_shares` is true, perform extra rerandomization.
     fn get_db<C: AbstractCommunicator>(
         &mut self,
         comm: &mut C,
@@ -56,6 +67,8 @@ fn compute_oram_prf_output_bitsize(memory_size: usize) -> usize {
     (usize::BITS - memory_size.leading_zeros()) as usize + 40
 }
 
+/// Steps of the DORAM protocol.
+#[allow(missing_docs)]
 #[derive(Debug, Clone, Copy, PartialEq, Eq, strum_macros::EnumIter, strum_macros::Display)]
 pub enum ProtocolStep {
     Preprocess = 0,
@@ -90,6 +103,7 @@ pub enum ProtocolStep {
     RefreshReceivingShare,
 }
 
+/// Collection of accumulated runtimes for the protocol steps.
 #[derive(Debug, Default, Clone, Copy)]
 pub struct Runtimes {
     durations: [Duration; 30],
@@ -97,23 +111,28 @@ pub struct Runtimes {
 }
 
 impl Runtimes {
+    /// Add another duration to the accumulated runtimes for a protocol step.
     #[inline(always)]
     pub fn record(&mut self, id: ProtocolStep, duration: Duration) {
         self.durations[id as usize] += duration;
     }
 
+    /// Get a copy of the recorded runtimes of the stash protocol,
     pub fn get_stash_runtimes(&self) -> StashRuntimes {
         self.stash_runtimes
     }
 
+    /// Set the recorded runtimes of the stash protocol,
     pub fn set_stash_runtimes(&mut self, stash_runtimes: StashRuntimes) {
         self.stash_runtimes = stash_runtimes;
     }
 
+    /// Get the accumulated durations for a protocol step.
     pub fn get(&self, id: ProtocolStep) -> Duration {
         self.durations[id as usize]
     }
 
+    /// Pretty-print the recorded runtimes amortized over `num_accesses`.
     pub fn print(&self, party_id: usize, num_accesses: usize) {
         println!("==================== Party {party_id} ====================");
         println!("- times per access over {num_accesses} accesses in total");
@@ -190,6 +209,7 @@ impl Runtimes {
     }
 }
 
+/// Implementation of the DORAM protocol.
 pub struct DistributedOramProtocol<F, MPDPF, SPDPF>
 where
     F: FromPrf + LegendreSymbol + Serializable,
@@ -245,6 +265,7 @@ where
     SPDPF: SinglePointDpf<Value = F> + Sync,
     SPDPF::Key: Serializable + Sync,
 {
+    /// Create a new instance.
     pub fn new(party_id: usize, db_size: usize) -> Self {
         assert!(party_id < 3);
         let stash_size = (db_size as f64).sqrt().round() as usize;
@@ -290,14 +311,17 @@ where
         }
     }
 
+    /// Get the current access counter.
     pub fn get_access_counter(&self) -> usize {
         self.stash.as_ref().unwrap().get_access_counter()
     }
 
+    /// Get a reference to the stash protocol instance.
     pub fn get_stash(&self) -> &StashProtocol<F, SPDPF> {
         self.stash.as_ref().unwrap()
     }
 
+    /// Return the size of the stash.
     pub fn get_stash_size(&self) -> usize {
         self.stash_size
     }
@@ -465,6 +489,7 @@ where
         Ok(runtimes)
     }
 
+    /// Run the preprocessing protocol and collect runtime data.
     pub fn preprocess_with_runtimes<C: AbstractCommunicator>(
         &mut self,
         comm: &mut C,
@@ -726,6 +751,7 @@ where
         Ok(runtimes)
     }
 
+    /// Run the refresh protocol at the end of an epoch.
     fn refresh<C: AbstractCommunicator>(
         &mut self,
         comm: &mut C,
@@ -873,6 +899,7 @@ where
         Ok(runtimes)
     }
 
+    /// Run the access protocol and collect runtime data.
     pub fn access_with_runtimes<C: AbstractCommunicator>(
         &mut self,
         comm: &mut C,

+ 37 - 0
oram/src/p_ot.rs

@@ -1,3 +1,10 @@
+//! Implementation of the 3-OT protocol.
+//!
+//! 3-OT is a variant of random oblivious transfer for three parties K, C, and R. K samples a PRF
+//! key that defines a pseudorandom vector.  Then C can repeatedly choose an index in this vector,
+//! and R receives the vector entry at that index without learning anything about the index or the
+//! other entries in the vector.
+
 use crate::common::Error;
 use communicator::{AbstractCommunicator, Fut, Serializable};
 use core::marker::PhantomData;
@@ -6,6 +13,7 @@ use rayon::prelude::*;
 use utils::field::FromPrf;
 use utils::permutation::Permutation;
 
+/// Party that holds the PRF key.
 pub struct POTKeyParty<F: FromPrf, Perm> {
     /// log of the database size
     domain_size: usize,
@@ -26,6 +34,7 @@ where
     F::PrfKey: Sync,
     Perm: Permutation + Sync,
 {
+    /// Create a new instance.
     pub fn new(domain_size: usize) -> Self {
         Self {
             domain_size,
@@ -37,14 +46,17 @@ where
         }
     }
 
+    /// Test if the party has been initialized.
     pub fn is_initialized(&self) -> bool {
         self.is_initialized
     }
 
+    /// Reset the instance to be used again.
     pub fn reset(&mut self) {
         *self = Self::new(self.domain_size);
     }
 
+    /// Steps of the initialization protocol without communication.
     pub fn init(&mut self) -> ((F::PrfKey, Perm::Key), F::PrfKey) {
         assert!(!self.is_initialized);
         self.prf_key_i = Some(F::prf_key_gen());
@@ -58,6 +70,7 @@ where
         )
     }
 
+    /// Run the initialization protocol.
     pub fn run_init<C: AbstractCommunicator>(&mut self, comm: &mut C) -> Result<(), Error>
     where
         <F as FromPrf>::PrfKey: Serializable,
@@ -69,6 +82,7 @@ where
         Ok(())
     }
 
+    /// Expand the PRF key into a pseudorandom vector.
     pub fn expand(&self) -> Vec<F> {
         assert!(self.is_initialized);
         (0..self.domain_size)
@@ -82,6 +96,7 @@ where
     }
 }
 
+/// Party that chooses the index.
 pub struct POTIndexParty<F: FromPrf, Perm> {
     /// log of the database size
     domain_size: usize,
@@ -95,6 +110,7 @@ pub struct POTIndexParty<F: FromPrf, Perm> {
 }
 
 impl<F: Field + FromPrf, Perm: Permutation> POTIndexParty<F, Perm> {
+    /// Create a new instance.
     pub fn new(domain_size: usize) -> Self {
         Self {
             domain_size,
@@ -105,14 +121,17 @@ impl<F: Field + FromPrf, Perm: Permutation> POTIndexParty<F, Perm> {
         }
     }
 
+    /// Test if the party has been initialized.
     pub fn is_initialized(&self) -> bool {
         self.is_initialized
     }
 
+    /// Reset the instance to be used again.
     pub fn reset(&mut self) {
         *self = Self::new(self.domain_size);
     }
 
+    /// Steps of the initialization protocol without communication.
     pub fn init(&mut self, prf_key_i: F::PrfKey, permutation_key: Perm::Key) {
         assert!(!self.is_initialized);
         self.prf_key_i = Some(prf_key_i);
@@ -120,6 +139,7 @@ impl<F: Field + FromPrf, Perm: Permutation> POTIndexParty<F, Perm> {
         self.is_initialized = true;
     }
 
+    /// Run the initialization protocol.
     pub fn run_init<C: AbstractCommunicator>(&mut self, comm: &mut C) -> Result<(), Error>
     where
         <F as FromPrf>::PrfKey: Serializable,
@@ -130,12 +150,14 @@ impl<F: Field + FromPrf, Perm: Permutation> POTIndexParty<F, Perm> {
         Ok(())
     }
 
+    /// Steps of the access protocol without communication.
     pub fn access(&self, index: usize) -> (usize, F) {
         assert!(index < self.domain_size);
         let pi_x = self.permutation.as_ref().unwrap().permute(index);
         (pi_x, F::prf(&self.prf_key_i.unwrap(), pi_x as u64))
     }
 
+    /// Run the access protocol.
     pub fn run_access<C: AbstractCommunicator>(
         &self,
         comm: &mut C,
@@ -150,6 +172,7 @@ impl<F: Field + FromPrf, Perm: Permutation> POTIndexParty<F, Perm> {
     }
 }
 
+/// Party that receives the output.
 pub struct POTReceiverParty<F: FromPrf> {
     /// log of the database size
     domain_size: usize,
@@ -161,6 +184,7 @@ pub struct POTReceiverParty<F: FromPrf> {
 }
 
 impl<F: Field + FromPrf> POTReceiverParty<F> {
+    /// Create a new instance.
     pub fn new(domain_size: usize) -> Self {
         Self {
             domain_size,
@@ -170,20 +194,24 @@ impl<F: Field + FromPrf> POTReceiverParty<F> {
         }
     }
 
+    /// Test if the party has been initialized.
     pub fn is_initialized(&self) -> bool {
         self.is_initialized
     }
 
+    /// Reset the instance to be used again.
     pub fn reset(&mut self) {
         *self = Self::new(self.domain_size);
     }
 
+    /// Steps of the initialization protocol without communication.
     pub fn init(&mut self, prf_key_r: F::PrfKey) {
         assert!(!self.is_initialized);
         self.prf_key_r = Some(prf_key_r);
         self.is_initialized = true;
     }
 
+    /// Run the initialization protocol.
     pub fn run_init<C: AbstractCommunicator>(&mut self, comm: &mut C) -> Result<(), Error>
     where
         <F as FromPrf>::PrfKey: Serializable,
@@ -193,11 +221,13 @@ impl<F: Field + FromPrf> POTReceiverParty<F> {
         Ok(())
     }
 
+    /// Steps of the access protocol without communication.
     pub fn access(&self, permuted_index: usize, output_share: F) -> F {
         assert!(permuted_index < self.domain_size);
         F::prf(&self.prf_key_r.unwrap(), permuted_index as u64) + output_share
     }
 
+    /// Run the access protocol.
     pub fn run_access<C: AbstractCommunicator>(&self, comm: &mut C) -> Result<F, Error>
     where
         F: Serializable,
@@ -208,6 +238,7 @@ impl<F: Field + FromPrf> POTReceiverParty<F> {
     }
 }
 
+/// Combination of three 3-OT instances, where each party takes each role once.
 pub struct JointPOTParties<F: FromPrf, Perm> {
     key_party: POTKeyParty<F, Perm>,
     index_party: POTIndexParty<F, Perm>,
@@ -220,6 +251,7 @@ where
     F::PrfKey: Sync,
     Perm: Permutation + Sync,
 {
+    /// Create a new instance.
     pub fn new(domain_size: usize) -> Self {
         Self {
             key_party: POTKeyParty::new(domain_size),
@@ -228,10 +260,12 @@ where
         }
     }
 
+    /// Reset this instance.
     pub fn reset(&mut self) {
         *self = Self::new(self.key_party.domain_size);
     }
 
+    /// Run the inititialization for all three 3-OT instances.
     pub fn init<C: AbstractCommunicator>(&mut self, comm: &mut C) -> Result<(), Error>
     where
         <F as FromPrf>::PrfKey: Serializable,
@@ -242,6 +276,8 @@ where
         self.receiver_party.run_init(comm)
     }
 
+    /// Run the access protocol for the 3-OT instances where the this party chooses the index or
+    /// receives the output.
     pub fn access<C: AbstractCommunicator>(&self, comm: &mut C, my_index: usize) -> Result<F, Error>
     where
         F: Serializable,
@@ -250,6 +286,7 @@ where
         self.receiver_party.run_access(comm)
     }
 
+    /// Expands the PRF key for the instances where this party holds the key.
     pub fn expand(&self) -> Vec<F> {
         self.key_party.expand()
     }

+ 8 - 2
oram/src/select.rs

@@ -1,3 +1,5 @@
+//! Implementation of an oblivious selection protocol.
+
 use crate::common::Error;
 use communicator::{AbstractCommunicator, Fut, Serializable};
 use ff::Field;
@@ -6,17 +8,20 @@ use rand::{thread_rng, Rng, SeedableRng};
 use rand_chacha::ChaChaRng;
 use std::collections::VecDeque;
 
-/// Select between two shared value <a>, <b> based on a shared condition bit <c>:
-/// Output <w> <- if <c> then <a> else <b>.
+/// Select between two shared values `<a>`, `<b>` based on a shared condition bit `<c>`:
+/// Output `<w> <- if <c> then <a> else <b>`.
 pub trait Select<F> {
+    /// Initialize the protocol instance.
     fn init<C: AbstractCommunicator>(&mut self, comm: &mut C) -> Result<(), Error>;
 
+    /// Run the preprocessing for `num` invocations.
     fn preprocess<C: AbstractCommunicator>(
         &mut self,
         comm: &mut C,
         num: usize,
     ) -> Result<(), Error>;
 
+    /// Run the online protocol for one select operation.
     fn select<C: AbstractCommunicator>(
         &mut self,
         comm: &mut C,
@@ -38,6 +43,7 @@ fn other_compute_party(my_id: usize) -> usize {
     }
 }
 
+/// Implementation of the select protocol.
 #[derive(Default)]
 pub struct SelectProtocol<F> {
     shared_prg_1: Option<ChaChaRng>,

+ 27 - 7
oram/src/stash.rs

@@ -1,3 +1,5 @@
+//! Stash protocol implementation.
+
 use crate::common::{Error, InstructionShare};
 use crate::doprf::{
     DOPrfParty1, DOPrfParty2, DOPrfParty3, LegendrePrf, MaskedDOPrfParty1, MaskedDOPrfParty2,
@@ -14,20 +16,20 @@ use std::marker::PhantomData;
 use std::time::{Duration, Instant};
 use utils::field::LegendreSymbol;
 
-#[derive(Clone, Copy, Debug, Default)]
-pub struct StashEntryShare<F: PrimeField> {
-    pub address: F,
-    pub value: F,
-    pub old_value: F,
-}
-
+/// Result of a stash read.
+///
+/// All values are shared.
 #[derive(Clone, Copy, Debug, Default)]
 pub struct StashStateShare<F: PrimeField> {
+    /// Share of 1 if the searched address was present in the stash, and share of 0 otherwise.
     pub flag: F,
+    /// Possible location of the found entry in the stash.
     pub location: F,
+    /// Possible value of the found entry.
     pub value: F,
 }
 
+/// State of the stash protocol.
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 enum State {
     New,
@@ -40,23 +42,31 @@ const PARTY_1: usize = 0;
 const PARTY_2: usize = 1;
 const PARTY_3: usize = 2;
 
+/// Definition of the stash interface.
 pub trait Stash<F: PrimeField> {
+    /// Return ID of the current party.
     fn get_party_id(&self) -> usize;
 
+    /// Return capacity of the stash.
     fn get_stash_size(&self) -> usize;
 
+    /// Return current access counter.
     fn get_access_counter(&self) -> usize;
 
+    /// Reset the data structure to be used again.
     fn reset(&mut self);
 
+    /// Initialize the stash.
     fn init<C: AbstractCommunicator>(&mut self, comm: &mut C) -> Result<(), Error>;
 
+    /// Perform a read from the stash.
     fn read<C: AbstractCommunicator>(
         &mut self,
         comm: &mut C,
         instruction: InstructionShare<F>,
     ) -> Result<StashStateShare<F>, Error>;
 
+    /// Perform a write into the stash.
     fn write<C: AbstractCommunicator>(
         &mut self,
         comm: &mut C,
@@ -66,6 +76,7 @@ pub trait Stash<F: PrimeField> {
         db_value_share: F,
     ) -> Result<(), Error>;
 
+    /// Get an additive share of the stash.
     fn get_stash_share(&self) -> (&[F], &[F], &[F]);
 }
 
@@ -73,6 +84,8 @@ fn compute_stash_prf_output_bitsize(stash_size: usize) -> usize {
     (usize::BITS - stash_size.leading_zeros()) as usize + 40
 }
 
+/// Protocol steps of the stash initialization, read, and write.
+#[allow(missing_docs)]
 #[derive(Debug, Clone, Copy, PartialEq, Eq, strum_macros::EnumIter, strum_macros::Display)]
 pub enum ProtocolStep {
     Init = 0,
@@ -94,22 +107,26 @@ pub enum ProtocolStep {
     WriteDpfEvaluations,
 }
 
+/// Collection of accumulated runtimes for the protocol steps.
 #[derive(Debug, Default, Clone, Copy)]
 pub struct Runtimes {
     durations: [Duration; 17],
 }
 
 impl Runtimes {
+    /// Add another duration to the accumulated runtimes for a protocol step.
     #[inline(always)]
     pub fn record(&mut self, id: ProtocolStep, duration: Duration) {
         self.durations[id as usize] += duration;
     }
 
+    /// Get the accumulated durations for a protocol step.
     pub fn get(&self, id: ProtocolStep) -> Duration {
         self.durations[id as usize]
     }
 }
 
+/// Implementation of the stash protocol.
 pub struct StashProtocol<F, SPDPF>
 where
     F: PrimeField + LegendreSymbol + Serializable,
@@ -139,6 +156,7 @@ where
     SPDPF: SinglePointDpf<Value = F>,
     SPDPF::Key: Serializable + Sync,
 {
+    /// Create new instance of the stash protocol for a party `{0, 1, 2}` and given size.
     pub fn new(party_id: usize, stash_size: usize) -> Self {
         assert!(party_id < 3);
         assert!(stash_size > 0);
@@ -233,6 +251,7 @@ where
         Ok(runtimes)
     }
 
+    /// Perform a stash read and collect runtime data.
     pub fn read_with_runtimes<C: AbstractCommunicator>(
         &mut self,
         comm: &mut C,
@@ -482,6 +501,7 @@ where
         ))
     }
 
+    /// Perform a stash write and collect runtime data.
     pub fn write_with_runtimes<C: AbstractCommunicator>(
         &mut self,
         comm: &mut C,

+ 18 - 3
oram/src/tools.rs

@@ -1,20 +1,30 @@
+//! Tools to collect benchmark metadata.
+
 use git_version::git_version;
 use serde::Serialize;
 use std::fs::{read_to_string, File};
 use std::io::{BufRead, BufReader};
 use std::process;
 
+/// Collection of metadata for benchmarks.
 #[derive(Clone, Debug, Serialize)]
 pub struct BenchmarkMetaData {
+    /// The hostname of the system.
     pub hostname: String,
+    /// The username of the current user.
     pub username: String,
+    /// A timestamp.
     pub timestamp: String,
+    /// How this program was executed.
     pub cmdline: Vec<String>,
+    /// The process ID.
     pub pid: u32,
+    /// The git version of this software.
     pub git_version: String,
 }
 
 impl BenchmarkMetaData {
+    /// Collect the metadata.
     pub fn collect() -> Self {
         BenchmarkMetaData {
             hostname: get_hostname(),
@@ -27,7 +37,7 @@ impl BenchmarkMetaData {
     }
 }
 
-pub fn run_command_with_args(cmd: &str, args: &[&str]) -> String {
+fn run_command_with_args(cmd: &str, args: &[&str]) -> String {
     String::from_utf8(
         process::Command::new(cmd)
             .args(args)
@@ -40,7 +50,7 @@ pub fn run_command_with_args(cmd: &str, args: &[&str]) -> String {
     .to_string()
 }
 
-pub fn run_command(cmd: &str) -> String {
+fn run_command(cmd: &str) -> String {
     String::from_utf8(
         process::Command::new(cmd)
             .output()
@@ -52,22 +62,26 @@ pub fn run_command(cmd: &str) -> String {
     .to_string()
 }
 
-pub fn read_file(path: &str) -> String {
+fn read_file(path: &str) -> String {
     read_to_string(path).expect("read_to_string failed")
 }
 
+/// Get the username of the current user.
 pub fn get_username() -> String {
     run_command("whoami")
 }
 
+/// Get the hostname of this machine.
 pub fn get_hostname() -> String {
     read_file("/proc/sys/kernel/hostname").trim().to_string()
 }
 
+/// Get a current timestamp.
 pub fn get_timestamp() -> String {
     run_command_with_args("date", &["--iso-8601=s"])
 }
 
+/// Get command line arguments used to run this program.
 pub fn get_cmdline() -> Vec<String> {
     let f = File::open("/proc/self/cmdline").expect("cannot open file");
     let mut reader = BufReader::new(f);
@@ -84,6 +98,7 @@ pub fn get_cmdline() -> Vec<String> {
     cmdline
 }
 
+/// Get process ID (PID) of the current process.
 pub fn get_pid() -> u32 {
     process::id()
 }