From 89233d8ce068de96809de065839374bd40f07b76 Mon Sep 17 00:00:00 2001 From: William J Date: Thu, 28 Jul 2022 12:55:05 -0400 Subject: [PATCH 01/22] Move Evictor to its own module --- mc-oblivious-ram/src/evictor/mod.rs | 67 +++++++++++++++++++++++++++ mc-oblivious-ram/src/lib.rs | 2 + mc-oblivious-ram/src/path_oram/mod.rs | 56 +--------------------- 3 files changed, 71 insertions(+), 54 deletions(-) create mode 100644 mc-oblivious-ram/src/evictor/mod.rs diff --git a/mc-oblivious-ram/src/evictor/mod.rs b/mc-oblivious-ram/src/evictor/mod.rs new file mode 100644 index 0000000..661ad2f --- /dev/null +++ b/mc-oblivious-ram/src/evictor/mod.rs @@ -0,0 +1,67 @@ +//! Evictor functions + +use aligned_cmov::A8Bytes; + +use aligned_cmov::A64Bytes; + +use aligned_cmov::typenum::Prod; + +use core::ops::Mul; + +use aligned_cmov::typenum::Unsigned; + +use aligned_cmov::typenum::U64; + +use aligned_cmov::typenum::U8; + +use aligned_cmov::typenum::PartialDiv; + +use aligned_cmov::ArrayLength; + +use crate::path_oram::{BranchCheckout, MetaSize}; + +/// Evictor trait conceptually is a mechanism for moving stash elements into +/// the oram. +pub trait Evictor +where + ValueSize: ArrayLength + PartialDiv + PartialDiv, + Z: Unsigned + Mul + Mul, + Prod: ArrayLength + PartialDiv, + Prod: ArrayLength + PartialDiv, +{ + /// Method that takes a branch and a stash and moves elements from the + /// stash into the branch. + fn evict_from_stash_to_branch( + &self, + stash_data: &mut [A64Bytes], + stash_meta: &mut [A8Bytes], + branch: &mut BranchCheckout, + ); +} +pub struct PathOramEvict {} +impl Evictor for PathOramEvict +where + ValueSize: ArrayLength + PartialDiv + PartialDiv, + Z: Unsigned + Mul + Mul, + Prod: ArrayLength + PartialDiv, + Prod: ArrayLength + PartialDiv, +{ + fn evict_from_stash_to_branch( + &self, + stash_data: &mut [A64Bytes], + stash_meta: &mut [A8Bytes], + branch: &mut BranchCheckout, + ) { + branch.pack(); + //Greedily place elements of the stash into the branch as close to the leaf as + // they can go. + for idx in 0..stash_data.len() { + branch.ct_insert(1.into(), &stash_data[idx], &mut stash_meta[idx]); + } + } +} +impl PathOramEvict { + pub fn new() -> Self { + Self {} + } +} diff --git a/mc-oblivious-ram/src/lib.rs b/mc-oblivious-ram/src/lib.rs index 9d44ebe..fb6363a 100644 --- a/mc-oblivious-ram/src/lib.rs +++ b/mc-oblivious-ram/src/lib.rs @@ -32,6 +32,8 @@ use rand_core::{CryptoRng, RngCore}; mod position_map; pub use position_map::{ORAMU32PositionMap, TrivialPositionMap, U32PositionMapCreator}; +mod evictor; + mod path_oram; pub use path_oram::PathORAM; diff --git a/mc-oblivious-ram/src/path_oram/mod.rs b/mc-oblivious-ram/src/path_oram/mod.rs index 9ca70ff..44fb077 100644 --- a/mc-oblivious-ram/src/path_oram/mod.rs +++ b/mc-oblivious-ram/src/path_oram/mod.rs @@ -15,7 +15,7 @@ use alloc::vec; -use self::evictor::{Evictor, PathOramEvict}; +use crate::evictor::{Evictor, PathOramEvict}; use aligned_cmov::{ subtle::{Choice, ConstantTimeEq, ConstantTimeLess}, typenum::{PartialDiv, Prod, Unsigned, U16, U64, U8}, @@ -35,7 +35,7 @@ use rand_core::{CryptoRng, RngCore}; /// In many cases block-num and leaf can be u32's. But I suspect that there will /// be other stuff in this metadata as well in the end so the savings isn't /// much. -type MetaSize = U16; +pub(crate) type MetaSize = U16; // A metadata object is always associated to any Value in the PathORAM // structure. A metadata consists of two fields: leaf_num and block_num @@ -543,55 +543,3 @@ mod details { } } } - -/// Evictor functions -pub mod evictor { - - use super::*; - - /// Evictor trait conceptually is a mechanism for moving stash elements into - /// the oram. - pub trait Evictor - where - ValueSize: ArrayLength + PartialDiv + PartialDiv, - Z: Unsigned + Mul + Mul, - Prod: ArrayLength + PartialDiv, - Prod: ArrayLength + PartialDiv, - { - /// Method that takes a branch and a stash and moves elements from the - /// stash into the branch. - fn evict_from_stash_to_branch( - &self, - stash_data: &mut [A64Bytes], - stash_meta: &mut [A8Bytes], - branch: &mut BranchCheckout, - ); - } - pub struct PathOramEvict {} - impl Evictor for PathOramEvict - where - ValueSize: ArrayLength + PartialDiv + PartialDiv, - Z: Unsigned + Mul + Mul, - Prod: ArrayLength + PartialDiv, - Prod: ArrayLength + PartialDiv, - { - fn evict_from_stash_to_branch( - &self, - stash_data: &mut [A64Bytes], - stash_meta: &mut [A8Bytes], - branch: &mut BranchCheckout, - ) { - branch.pack(); - //Greedily place elements of the stash into the branch as close to the leaf as - // they can go. - for idx in 0..stash_data.len() { - branch.ct_insert(1.into(), &stash_data[idx], &mut stash_meta[idx]); - } - } - } - impl PathOramEvict { - pub fn new() -> Self { - Self {} - } - } -} From 04726541528ea6c880f79858514c83d3399eb4df Mon Sep 17 00:00:00 2001 From: William J Date: Thu, 28 Jul 2022 14:22:11 -0400 Subject: [PATCH 02/22] Adding clarifying information for the Evictor module --- mc-oblivious-ram/src/evictor/mod.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mc-oblivious-ram/src/evictor/mod.rs b/mc-oblivious-ram/src/evictor/mod.rs index 661ad2f..0102c8f 100644 --- a/mc-oblivious-ram/src/evictor/mod.rs +++ b/mc-oblivious-ram/src/evictor/mod.rs @@ -1,4 +1,8 @@ -//! Evictor functions +//! Evictor functions for ORAM +//! +//! These are intended to be a module containing different eviction strategies +//! for tree based orams which include path oram and circuit oram. These +//! strategies will be used for evicting stash elements to the tree oram. use aligned_cmov::A8Bytes; From 44c78c58016d5cb7fac8a306ca114f750b24e381 Mon Sep 17 00:00:00 2001 From: William J Date: Fri, 29 Jul 2022 13:01:17 -0400 Subject: [PATCH 03/22] Refactor path_oram to take an evictor creator and add deterministic evictor --- mc-oblivious-ram/src/evictor/mod.rs | 233 ++++++++++++++++++++++++-- mc-oblivious-ram/src/lib.rs | 23 ++- mc-oblivious-ram/src/path_oram/mod.rs | 33 +++- no-asm-tests/src/main.rs | 21 ++- 4 files changed, 276 insertions(+), 34 deletions(-) diff --git a/mc-oblivious-ram/src/evictor/mod.rs b/mc-oblivious-ram/src/evictor/mod.rs index 0102c8f..f2d8e6e 100644 --- a/mc-oblivious-ram/src/evictor/mod.rs +++ b/mc-oblivious-ram/src/evictor/mod.rs @@ -9,6 +9,7 @@ use aligned_cmov::A8Bytes; use aligned_cmov::A64Bytes; use aligned_cmov::typenum::Prod; +use balanced_tree_index::TreeIndex; use core::ops::Mul; @@ -22,28 +23,120 @@ use aligned_cmov::typenum::PartialDiv; use aligned_cmov::ArrayLength; +use rand_core::CryptoRng; + use crate::path_oram::{BranchCheckout, MetaSize}; +use rand_core::RngCore; -/// Evictor trait conceptually is a mechanism for moving stash elements into -/// the oram. -pub trait Evictor +fn deterministic_get_next_branch_to_evict(num_bits_needed: u32, iteration: u64) -> u64 { + let leaf_significant_index: u64 = 1 << (num_bits_needed); + let test_position: u64 = + ((iteration).reverse_bits() >> (64 - num_bits_needed)) % leaf_significant_index; + leaf_significant_index + test_position +} + +/// An evictor that implements a random branch selection and the path oram +/// eviction strategy +pub struct PathOramRandomEvict +where + RngType: RngCore + CryptoRng + Send + Sync + 'static, +{ + rng: RngType, + number_of_additional_branches_to_evict: usize, + branches_evicted: u64, + tree_height: u32, +} +#[allow(dead_code)] +impl PathOramRandomEvict +where + RngType: RngCore + CryptoRng + Send + Sync + 'static, +{ + /// Create a new deterministic branch selector that will select + /// num_elements_to_evict branches per access + pub fn new( + number_of_additional_branches_to_evict: usize, + tree_height: u32, + rng: RngType, + ) -> Self { + Self { + rng, + number_of_additional_branches_to_evict, + tree_height, + branches_evicted: 0, + } + } +} + +impl BranchSelector for PathOramRandomEvict +where + RngType: RngCore + CryptoRng + Send + Sync + 'static, +{ + fn get_next_branch_to_evict(&mut self) -> u64 { + self.branches_evicted += 1; + 1u64.random_child_at_height(self.tree_height, &mut self.rng) + } + + fn get_number_of_additional_branches_to_evict(&self) -> usize { + self.number_of_additional_branches_to_evict + } +} +impl EvictionStrategy for PathOramRandomEvict where ValueSize: ArrayLength + PartialDiv + PartialDiv, Z: Unsigned + Mul + Mul, Prod: ArrayLength + PartialDiv, Prod: ArrayLength + PartialDiv, + RngType: RngCore + CryptoRng + Send + Sync + 'static, { - /// Method that takes a branch and a stash and moves elements from the - /// stash into the branch. fn evict_from_stash_to_branch( &self, stash_data: &mut [A64Bytes], stash_meta: &mut [A8Bytes], branch: &mut BranchCheckout, - ); + ) { + path_oram_eviction_strategy::(stash_data, stash_meta, branch); + } +} + +/// An evictor that implements a deterministc branch selection and the path +/// oram eviction strategy +pub struct PathOramDeterministicEvict { + number_of_additional_branches_to_evict: usize, + branches_evicted: u64, + tree_height: u32, + tree_size: u64, +} +impl PathOramDeterministicEvict { + /// Create a new deterministic branch selector that will select + /// num_elements_to_evict branches per access + pub fn new( + number_of_additional_branches_to_evict: usize, + tree_height: u32, + tree_size: u64, + ) -> Self { + Self { + number_of_additional_branches_to_evict, + tree_height, + tree_size, + branches_evicted: 0, + } + } +} + +impl BranchSelector for PathOramDeterministicEvict { + fn get_next_branch_to_evict(&mut self) -> u64 { + //The height of the root is 0, so the number of bits needed for the leaves is + // just the height + let iteration = self.branches_evicted; + self.branches_evicted = (self.branches_evicted + 1) % self.tree_size; + deterministic_get_next_branch_to_evict(self.tree_height, iteration) + } + + fn get_number_of_additional_branches_to_evict(&self) -> usize { + self.number_of_additional_branches_to_evict + } } -pub struct PathOramEvict {} -impl Evictor for PathOramEvict +impl EvictionStrategy for PathOramDeterministicEvict where ValueSize: ArrayLength + PartialDiv + PartialDiv, Z: Unsigned + Mul + Mul, @@ -56,16 +149,124 @@ where stash_meta: &mut [A8Bytes], branch: &mut BranchCheckout, ) { - branch.pack(); - //Greedily place elements of the stash into the branch as close to the leaf as - // they can go. - for idx in 0..stash_data.len() { - branch.ct_insert(1.into(), &stash_data[idx], &mut stash_meta[idx]); + path_oram_eviction_strategy::(stash_data, stash_meta, branch); + } +} + +/// Eviction algorithm defined in path oram. Packs the branch and greedily +/// tries to evict everything from the stash into the checked out branch +fn path_oram_eviction_strategy( + stash_data: &mut [A64Bytes], + stash_meta: &mut [A8Bytes], + branch: &mut BranchCheckout, +) where + ValueSize: ArrayLength + PartialDiv + PartialDiv, + Z: Unsigned + Mul + Mul, + Prod: ArrayLength + PartialDiv, + Prod: ArrayLength + PartialDiv, +{ + branch.pack(); + //Greedily place elements of the stash into the branch as close to the leaf as + // they can go. + for idx in 0..stash_data.len() { + branch.ct_insert(1.into(), &stash_data[idx], &mut stash_meta[idx]); + } +} + +pub trait BranchSelector { + /// Returns the leaf index of the next branch to call evict from stash + /// to branch on. + fn get_next_branch_to_evict(&mut self) -> u64; + + /// Returns the number of branches to call evict from stash to branch + /// on. + fn get_number_of_additional_branches_to_evict(&self) -> usize; +} + +/// Evictor trait conceptually is a mechanism for moving stash elements into +/// the oram. +pub trait EvictionStrategy +where + ValueSize: ArrayLength + PartialDiv + PartialDiv, + Z: Unsigned + Mul + Mul, + Prod: ArrayLength + PartialDiv, + Prod: ArrayLength + PartialDiv, +{ + /// Method that takes a branch and a stash and moves elements from the + /// stash into the branch. + fn evict_from_stash_to_branch( + &self, + stash_data: &mut [A64Bytes], + stash_meta: &mut [A8Bytes], + branch: &mut BranchCheckout, + ); +} + +/// A factory which creates an Evictor +pub trait EvictorCreator +where + ValueSize: ArrayLength + PartialDiv + PartialDiv, + Z: Unsigned + Mul + Mul, + Prod: ArrayLength + PartialDiv, + Prod: ArrayLength + PartialDiv, +{ + type Output: EvictionStrategy + BranchSelector + Send + Sync + 'static; + + fn create(&self, size: u64, height: u32) -> Self::Output; +} + +/// A factory which creates an PathOramDeterministicEvictor that evicts an +/// additional number_of_additional_branches_to_evict +pub struct PathOramDeterministicEvictCreator { + number_of_additional_branches_to_evict: usize, +} +impl PathOramDeterministicEvictCreator { + /// Create a factory for a deterministic branch selector that will evict + /// number_of_additional_branches_to_evict branches per access + pub fn new(number_of_additional_branches_to_evict: usize) -> Self { + Self { + number_of_additional_branches_to_evict, } } } -impl PathOramEvict { - pub fn new() -> Self { - Self {} + +impl EvictorCreator for PathOramDeterministicEvictCreator +where + ValueSize: ArrayLength + PartialDiv + PartialDiv, + Z: Unsigned + Mul + Mul, + Prod: ArrayLength + PartialDiv, + Prod: ArrayLength + PartialDiv, +{ + type Output = PathOramDeterministicEvict; + + fn create(&self, size: u64, height: u32) -> Self::Output { + PathOramDeterministicEvict::new(self.number_of_additional_branches_to_evict, height, size) + } +} + +#[cfg(test)] +mod internal_tests { + use super::*; + #[test] + // Check that deterministic oram correctly chooses leaf values + fn test_deterministic_oram_get_branches_to_evict() { + let test_branch = deterministic_get_next_branch_to_evict(3, 0); + assert_eq!(test_branch, 8); + let test_branch = deterministic_get_next_branch_to_evict(3, 1); + assert_eq!(test_branch, 12); + let test_branch = deterministic_get_next_branch_to_evict(3, 2); + assert_eq!(test_branch, 10); + let test_branch = deterministic_get_next_branch_to_evict(3, 3); + assert_eq!(test_branch, 14); + let test_branch = deterministic_get_next_branch_to_evict(3, 4); + assert_eq!(test_branch, 9); + let test_branch = deterministic_get_next_branch_to_evict(3, 5); + assert_eq!(test_branch, 13); + let test_branch = deterministic_get_next_branch_to_evict(3, 6); + assert_eq!(test_branch, 11); + let test_branch = deterministic_get_next_branch_to_evict(3, 7); + assert_eq!(test_branch, 15); + let test_branch = deterministic_get_next_branch_to_evict(3, 8); + assert_eq!(test_branch, 8); } } diff --git a/mc-oblivious-ram/src/lib.rs b/mc-oblivious-ram/src/lib.rs index fb6363a..2ab782c 100644 --- a/mc-oblivious-ram/src/lib.rs +++ b/mc-oblivious-ram/src/lib.rs @@ -33,6 +33,7 @@ mod position_map; pub use position_map::{ORAMU32PositionMap, TrivialPositionMap, U32PositionMapCreator}; mod evictor; +pub use evictor::{PathOramDeterministicEvict, PathOramDeterministicEvictCreator}; mod path_oram; pub use path_oram::PathORAM; @@ -56,14 +57,21 @@ where R: RngCore + CryptoRng + Send + Sync + 'static, SC: ORAMStorageCreator, { - type Output = PathORAM; + type Output = PathORAM; fn create R>( size: u64, stash_size: usize, rng_maker: &mut M, ) -> Self::Output { - PathORAM::new::, SC, M>(size, stash_size, rng_maker) + let evictor_factory = PathOramDeterministicEvictCreator::new(0); + + PathORAM::new::< + U32PositionMapCreator, + SC, + M, + PathOramDeterministicEvictCreator, + >(size, stash_size, rng_maker, evictor_factory) } } @@ -83,14 +91,21 @@ where R: RngCore + CryptoRng + Send + Sync + 'static, SC: ORAMStorageCreator, { - type Output = PathORAM; + type Output = PathORAM; fn create R>( size: u64, stash_size: usize, rng_maker: &mut M, ) -> Self::Output { - PathORAM::new::, SC, M>(size, stash_size, rng_maker) + let evictor_factory = PathOramDeterministicEvictCreator::new(0); + + PathORAM::new::< + U32PositionMapCreator, + SC, + M, + PathOramDeterministicEvictCreator, + >(size, stash_size, rng_maker, evictor_factory) } } diff --git a/mc-oblivious-ram/src/path_oram/mod.rs b/mc-oblivious-ram/src/path_oram/mod.rs index 44fb077..5091d61 100644 --- a/mc-oblivious-ram/src/path_oram/mod.rs +++ b/mc-oblivious-ram/src/path_oram/mod.rs @@ -15,7 +15,7 @@ use alloc::vec; -use crate::evictor::{Evictor, PathOramEvict}; +use crate::evictor::{BranchSelector, EvictionStrategy, EvictorCreator}; use aligned_cmov::{ subtle::{Choice, ConstantTimeEq, ConstantTimeLess}, typenum::{PartialDiv, Prod, Unsigned, U16, U64, U8}, @@ -83,12 +83,13 @@ fn meta_set_vacant(condition: Choice, src: &mut A8Bytes) { } /// An implementation of PathORAM, using u64 to represent leaves in metadata. -pub struct PathORAM +pub struct PathORAM where ValueSize: ArrayLength + PartialDiv + PartialDiv, Z: Unsigned + Mul + Mul, RngType: RngCore + CryptoRng + Send + Sync + 'static, StorageType: ORAMStorage, Prod> + Send + Sync + 'static, + EvictorType: EvictionStrategy + BranchSelector + Send + Sync + 'static, Prod: ArrayLength + PartialDiv, Prod: ArrayLength + PartialDiv, { @@ -107,15 +108,17 @@ where /// Our currently checked-out branch if any branch: BranchCheckout, /// Eviction strategy - evictor: Box + Send + Sync + 'static>, + evictor: EvictorType, } -impl PathORAM +impl + PathORAM where ValueSize: ArrayLength + PartialDiv + PartialDiv, Z: Unsigned + Mul + Mul, RngType: RngCore + CryptoRng + Send + Sync + 'static, StorageType: ORAMStorage, Prod> + Send + Sync + 'static, + EvictorType: EvictionStrategy + BranchSelector + Send + Sync + 'static, Prod: ArrayLength + PartialDiv, Prod: ArrayLength + PartialDiv, { @@ -129,10 +132,12 @@ where PMC: PositionMapCreator, SC: ORAMStorageCreator, Prod, Output = StorageType>, F: FnMut() -> RngType + 'static, + EVC: EvictorCreator, >( size: u64, stash_size: usize, rng_maker: &mut F, + evictor_factory: EVC, ) -> Self { assert!(size != 0, "size cannot be zero"); assert!(size & (size - 1) == 0, "size must be a power of two"); @@ -142,9 +147,9 @@ where // the height of the root to be 0, so in a tree where the lowest level // is h, there are 2^{h+1} nodes. let mut rng = rng_maker(); + let evictor = evictor_factory.create(size, height); let storage = SC::create(2u64 << height, &mut rng).expect("Storage failed"); let pos = PMC::create(size, height, stash_size, rng_maker); - let evictor = Box::new(PathOramEvict::new()); Self { height, storage, @@ -158,13 +163,14 @@ where } } -impl ORAM - for PathORAM +impl ORAM + for PathORAM where ValueSize: ArrayLength + PartialDiv + PartialDiv, Z: Unsigned + Mul + Mul, RngType: RngCore + CryptoRng + Send + Sync + 'static, StorageType: ORAMStorage, Prod> + Send + Sync + 'static, + EvictorType: EvictionStrategy + BranchSelector + Send + Sync + 'static, Prod: ArrayLength + PartialDiv, Prod: ArrayLength + PartialDiv, { @@ -251,6 +257,19 @@ where self.branch.checkin(&mut self.storage); debug_assert!(self.branch.leaf == 0); + for _ in 0..self.evictor.get_number_of_additional_branches_to_evict() { + let leaf = self.evictor.get_next_branch_to_evict(); + debug_assert!(leaf != 0); + self.branch.checkout(&mut self.storage, leaf); + self.evictor.evict_from_stash_to_branch( + &mut self.stash_data, + &mut self.stash_meta, + &mut self.branch, + ); + self.branch.checkin(&mut self.storage); + debug_assert!(self.branch.leaf == 0); + } + result } } diff --git a/no-asm-tests/src/main.rs b/no-asm-tests/src/main.rs index d45cafb..a85361d 100644 --- a/no-asm-tests/src/main.rs +++ b/no-asm-tests/src/main.rs @@ -5,7 +5,7 @@ use aligned_cmov::{ ArrayLength, }; use core::marker::PhantomData; -use mc_oblivious_ram::PathORAM; +use mc_oblivious_ram::{PathORAM, PathOramDeterministicEvict, PathOramDeterministicEvictCreator}; use mc_oblivious_traits::{ rng_maker, HeapORAMStorageCreator, ORAMCreator, ORAMStorageCreator, ORAM, }; @@ -48,7 +48,7 @@ where } } - return None; + None } pub fn main() { @@ -103,14 +103,20 @@ pub struct InsecurePathORAM4096Z4Creator> { impl> ORAMCreator for InsecurePathORAM4096Z4Creator { - type Output = PathORAM; + type Output = PathORAM; fn create RngType>( size: u64, stash_size: usize, rng_maker: &mut M, ) -> Self::Output { - PathORAM::new::, SC, M>(size, stash_size, rng_maker) + let evictor_factory = PathOramDeterministicEvictCreator::new(0); + PathORAM::new::, SC, M, PathOramDeterministicEvictCreator>( + size, + stash_size, + rng_maker, + evictor_factory, + ) } } @@ -121,7 +127,7 @@ mod tests { use core::convert::TryInto; use mc_oblivious_traits::{rng_maker, testing, HeapORAMStorageCreator, ORAMCreator}; use std::vec; - use test_helper::{run_with_several_seeds, run_with_one_seed}; + use test_helper::{run_with_one_seed, run_with_several_seeds}; // Run the exercise oram tests for 200,000 rounds in 131072 sized z4 oram #[test] @@ -211,7 +217,8 @@ mod tests { const VARIANCE_THRESHOLD: f64 = 0.15; run_with_one_seed(|rng| { - let mut oram_size_to_stash_size_by_count = BTreeMap::>::default(); + let mut oram_size_to_stash_size_by_count = + BTreeMap::>::default(); let mut maker = rng_maker(rng); for oram_power in (10..24).step_by(2) { let mut rng = maker(); @@ -229,7 +236,7 @@ mod tests { } for stash_num in 1..6 { let mut probability_of_stash_size = vec::Vec::new(); - for (_oram_power, stash_size_by_count) in &oram_size_to_stash_size_by_count { + for (_oram_power, stash_size_by_count) in &oram_size_to_stash_size_by_count { if let Some(stash_count) = stash_size_by_count.get(&stash_num) { let stash_count_probability = (NUM_ROUNDS as f64 / *stash_count as f64).log2(); From 30702440f36010298696baba4334e7e9a2a30e8b Mon Sep 17 00:00:00 2001 From: William J Date: Fri, 29 Jul 2022 13:28:08 -0400 Subject: [PATCH 04/22] Add clarifying comments, Shortcut deterministic get next branch to avoid overflow --- mc-oblivious-ram/src/evictor/mod.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/mc-oblivious-ram/src/evictor/mod.rs b/mc-oblivious-ram/src/evictor/mod.rs index f2d8e6e..52420a2 100644 --- a/mc-oblivious-ram/src/evictor/mod.rs +++ b/mc-oblivious-ram/src/evictor/mod.rs @@ -29,6 +29,13 @@ use crate::path_oram::{BranchCheckout, MetaSize}; use rand_core::RngCore; fn deterministic_get_next_branch_to_evict(num_bits_needed: u32, iteration: u64) -> u64 { + // Return 1 if the number of bits needed is 0. This is to shortcut the + // calculation furtherdown that would overflow, and does not leak + // information because the number of bits is structural information rather + // than query specific. + if num_bits_needed == 0 { + return 1; + } let leaf_significant_index: u64 = 1 << (num_bits_needed); let test_position: u64 = ((iteration).reverse_bits() >> (64 - num_bits_needed)) % leaf_significant_index; @@ -98,7 +105,8 @@ where } } -/// An evictor that implements a deterministc branch selection and the path +/// An evictor that implements a deterministic branch selection in reverse +/// lexicographic order and the path /// oram eviction strategy pub struct PathOramDeterministicEvict { number_of_additional_branches_to_evict: usize, @@ -215,8 +223,9 @@ where fn create(&self, size: u64, height: u32) -> Self::Output; } -/// A factory which creates an PathOramDeterministicEvictor that evicts an -/// additional number_of_additional_branches_to_evict +/// A factory which creates an PathOramDeterministicEvictor that evicts from the +/// stash into an additional number_of_additional_branches_to_evict branches in +/// addition to the currently checked out branch in reverse lexicographic order pub struct PathOramDeterministicEvictCreator { number_of_additional_branches_to_evict: usize, } From 39f13786ac786ee3534c218359b0fc1e05f759be Mon Sep 17 00:00:00 2001 From: William J Date: Fri, 12 Aug 2022 02:20:54 -0400 Subject: [PATCH 05/22] Fix formatting of use statements --- mc-oblivious-ram/src/evictor/mod.rs | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/mc-oblivious-ram/src/evictor/mod.rs b/mc-oblivious-ram/src/evictor/mod.rs index 0102c8f..bd4539a 100644 --- a/mc-oblivious-ram/src/evictor/mod.rs +++ b/mc-oblivious-ram/src/evictor/mod.rs @@ -4,24 +4,13 @@ //! for tree based orams which include path oram and circuit oram. These //! strategies will be used for evicting stash elements to the tree oram. -use aligned_cmov::A8Bytes; - -use aligned_cmov::A64Bytes; - -use aligned_cmov::typenum::Prod; +use aligned_cmov::{ + typenum::{PartialDiv, Prod, Unsigned, U64, U8}, + A64Bytes, A8Bytes, ArrayLength, +}; use core::ops::Mul; -use aligned_cmov::typenum::Unsigned; - -use aligned_cmov::typenum::U64; - -use aligned_cmov::typenum::U8; - -use aligned_cmov::typenum::PartialDiv; - -use aligned_cmov::ArrayLength; - use crate::path_oram::{BranchCheckout, MetaSize}; /// Evictor trait conceptually is a mechanism for moving stash elements into From a21c6a301541d362aef0ec7ffc2092dd52da7d0c Mon Sep 17 00:00:00 2001 From: William J Date: Fri, 12 Aug 2022 02:40:45 -0400 Subject: [PATCH 06/22] Add clarification around deterministic get next branch to evict --- mc-oblivious-ram/src/evictor/mod.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mc-oblivious-ram/src/evictor/mod.rs b/mc-oblivious-ram/src/evictor/mod.rs index 52420a2..e88c147 100644 --- a/mc-oblivious-ram/src/evictor/mod.rs +++ b/mc-oblivious-ram/src/evictor/mod.rs @@ -28,6 +28,9 @@ use rand_core::CryptoRng; use crate::path_oram::{BranchCheckout, MetaSize}; use rand_core::RngCore; +/// Selects branches in reverse lexicographic order. Num_bits_needed corresponds +/// to the number of possible branches that need to be explored. The iteration i +/// corresponds to the ith branch in reverse lexicographic order. fn deterministic_get_next_branch_to_evict(num_bits_needed: u32, iteration: u64) -> u64 { // Return 1 if the number of bits needed is 0. This is to shortcut the // calculation furtherdown that would overflow, and does not leak @@ -36,6 +39,8 @@ fn deterministic_get_next_branch_to_evict(num_bits_needed: u32, iteration: u64) if num_bits_needed == 0 { return 1; } + // This is the first index at which leafs exist, the most significant digit + // of all leafs is 1. let leaf_significant_index: u64 = 1 << (num_bits_needed); let test_position: u64 = ((iteration).reverse_bits() >> (64 - num_bits_needed)) % leaf_significant_index; From 766156910b37c1f7820263814645abf79c981403 Mon Sep 17 00:00:00 2001 From: William J Date: Fri, 12 Aug 2022 02:51:54 -0400 Subject: [PATCH 07/22] Remove dead code --- mc-oblivious-ram/src/evictor/mod.rs | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/mc-oblivious-ram/src/evictor/mod.rs b/mc-oblivious-ram/src/evictor/mod.rs index e88c147..5f5c5b7 100644 --- a/mc-oblivious-ram/src/evictor/mod.rs +++ b/mc-oblivious-ram/src/evictor/mod.rs @@ -58,26 +58,6 @@ where branches_evicted: u64, tree_height: u32, } -#[allow(dead_code)] -impl PathOramRandomEvict -where - RngType: RngCore + CryptoRng + Send + Sync + 'static, -{ - /// Create a new deterministic branch selector that will select - /// num_elements_to_evict branches per access - pub fn new( - number_of_additional_branches_to_evict: usize, - tree_height: u32, - rng: RngType, - ) -> Self { - Self { - rng, - number_of_additional_branches_to_evict, - tree_height, - branches_evicted: 0, - } - } -} impl BranchSelector for PathOramRandomEvict where From 2e3b3c96101870d413c9adbc95bc57f7152a8387 Mon Sep 17 00:00:00 2001 From: wjuan-mob Date: Tue, 23 Aug 2022 16:30:00 -0400 Subject: [PATCH 08/22] Update mc-oblivious-ram/src/evictor/mod.rs Co-authored-by: Nick Santana --- mc-oblivious-ram/src/evictor/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mc-oblivious-ram/src/evictor/mod.rs b/mc-oblivious-ram/src/evictor/mod.rs index bd4539a..4c796a1 100644 --- a/mc-oblivious-ram/src/evictor/mod.rs +++ b/mc-oblivious-ram/src/evictor/mod.rs @@ -1,3 +1,5 @@ +// Copyright (c) 2018-2022 The MobileCoin Foundation + //! Evictor functions for ORAM //! //! These are intended to be a module containing different eviction strategies From 19efeaa24d8fe793d2393e634814140a51701474 Mon Sep 17 00:00:00 2001 From: wjuan-mob Date: Tue, 23 Aug 2022 16:31:03 -0400 Subject: [PATCH 09/22] Update mc-oblivious-ram/src/evictor/mod.rs Co-authored-by: Nick Santana --- mc-oblivious-ram/src/evictor/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mc-oblivious-ram/src/evictor/mod.rs b/mc-oblivious-ram/src/evictor/mod.rs index 4c796a1..58d2181 100644 --- a/mc-oblivious-ram/src/evictor/mod.rs +++ b/mc-oblivious-ram/src/evictor/mod.rs @@ -2,9 +2,9 @@ //! Evictor functions for ORAM //! -//! These are intended to be a module containing different eviction strategies -//! for tree based orams which include path oram and circuit oram. These -//! strategies will be used for evicting stash elements to the tree oram. +//! A module containing different eviction strategies for tree based ORAMs which +//! include path ORAM and circuit ORAM. These strategies will be used for +//! evicting stash elements to the tree ORAM. use aligned_cmov::{ typenum::{PartialDiv, Prod, Unsigned, U64, U8}, From 3b5391f868486537c9f2b471cd2303cd89a81357 Mon Sep 17 00:00:00 2001 From: William J Date: Tue, 23 Aug 2022 17:21:09 -0400 Subject: [PATCH 10/22] Remove empty spaces from use statements to allow fmt to collapse them properly --- mc-oblivious-ram/src/evictor/mod.rs | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/mc-oblivious-ram/src/evictor/mod.rs b/mc-oblivious-ram/src/evictor/mod.rs index 5f5c5b7..a363fd7 100644 --- a/mc-oblivious-ram/src/evictor/mod.rs +++ b/mc-oblivious-ram/src/evictor/mod.rs @@ -4,28 +4,12 @@ //! for tree based orams which include path oram and circuit oram. These //! strategies will be used for evicting stash elements to the tree oram. -use aligned_cmov::A8Bytes; - -use aligned_cmov::A64Bytes; - -use aligned_cmov::typenum::Prod; -use balanced_tree_index::TreeIndex; - -use core::ops::Mul; - -use aligned_cmov::typenum::Unsigned; - -use aligned_cmov::typenum::U64; - -use aligned_cmov::typenum::U8; - -use aligned_cmov::typenum::PartialDiv; - -use aligned_cmov::ArrayLength; - -use rand_core::CryptoRng; - use crate::path_oram::{BranchCheckout, MetaSize}; +use aligned_cmov::{ + typenum::{PartialDiv, Prod, Unsigned, U64, U8}, + A64Bytes, A8Bytes, ArrayLength, +}; +use core::ops::Mul; use rand_core::RngCore; /// Selects branches in reverse lexicographic order. Num_bits_needed corresponds From 9293571e2fdb3236accbd97be7ef053e242e16f9 Mon Sep 17 00:00:00 2001 From: William J Date: Tue, 23 Aug 2022 17:25:11 -0400 Subject: [PATCH 11/22] Fix accidental delete of imports in previous commit --- mc-oblivious-ram/src/evictor/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mc-oblivious-ram/src/evictor/mod.rs b/mc-oblivious-ram/src/evictor/mod.rs index a363fd7..281f36b 100644 --- a/mc-oblivious-ram/src/evictor/mod.rs +++ b/mc-oblivious-ram/src/evictor/mod.rs @@ -9,8 +9,9 @@ use aligned_cmov::{ typenum::{PartialDiv, Prod, Unsigned, U64, U8}, A64Bytes, A8Bytes, ArrayLength, }; +use balanced_tree_index::TreeIndex; use core::ops::Mul; -use rand_core::RngCore; +use rand_core::{CryptoRng, RngCore}; /// Selects branches in reverse lexicographic order. Num_bits_needed corresponds /// to the number of possible branches that need to be explored. The iteration i From 06332121aec241d20ae36f8bb8fb681dfa2e4cd9 Mon Sep 17 00:00:00 2001 From: William J Date: Fri, 2 Sep 2022 10:38:50 -0400 Subject: [PATCH 12/22] Clarify comments about reverse lexicographic order --- mc-oblivious-ram/src/evictor/mod.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/mc-oblivious-ram/src/evictor/mod.rs b/mc-oblivious-ram/src/evictor/mod.rs index c9a221d..5fecadb 100644 --- a/mc-oblivious-ram/src/evictor/mod.rs +++ b/mc-oblivious-ram/src/evictor/mod.rs @@ -15,14 +15,20 @@ use balanced_tree_index::TreeIndex; use core::ops::Mul; use rand_core::{CryptoRng, RngCore}; -/// Selects branches in reverse lexicographic order. Num_bits_needed corresponds -/// to the number of possible branches that need to be explored. The iteration i -/// corresponds to the ith branch in reverse lexicographic order. +/// Selects branches in reverse lexicographic order, where the most significant +/// digit of the branch is always 1, corresponding to the leaf node that +/// represents that branch. +/// E.g. for a depth of 3: +/// 100, 110, 101, 111 +/// num_bits_needed corresponds to the number of possible branches that need to +/// be explored, and is 1 less than the number of bits in the leaf node. +/// The iteration i corresponds to the ith branch in reverse lexicographic +/// order. +/// fn deterministic_get_next_branch_to_evict(num_bits_needed: u32, iteration: u64) -> u64 { - // Return 1 if the number of bits needed is 0. This is to shortcut the - // calculation furtherdown that would overflow, and does not leak - // information because the number of bits is structural information rather - // than query specific. + // Return 1 if the number of bits needed is 0. Calculation furtherdown would + // overflow, and shortcutting here does not leak information because the + // number of bits is structural information rather than query specific. if num_bits_needed == 0 { return 1; } From c2df6a651ae135431658a1d92d559b870b4ea7c0 Mon Sep 17 00:00:00 2001 From: William J Date: Fri, 2 Sep 2022 10:52:21 -0400 Subject: [PATCH 13/22] Clarify tree size vs tree depth --- mc-oblivious-ram/src/evictor/mod.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mc-oblivious-ram/src/evictor/mod.rs b/mc-oblivious-ram/src/evictor/mod.rs index 5fecadb..8775889 100644 --- a/mc-oblivious-ram/src/evictor/mod.rs +++ b/mc-oblivious-ram/src/evictor/mod.rs @@ -86,8 +86,7 @@ where } /// An evictor that implements a deterministic branch selection in reverse -/// lexicographic order and the path -/// oram eviction strategy +/// lexicographic order and using the path oram eviction strategy pub struct PathOramDeterministicEvict { number_of_additional_branches_to_evict: usize, branches_evicted: u64, @@ -97,6 +96,9 @@ pub struct PathOramDeterministicEvict { impl PathOramDeterministicEvict { /// Create a new deterministic branch selector that will select /// num_elements_to_evict branches per access + /// tree height: corresponds to the height of tree + /// tree_size: corresponds to the number of elements that can be stored in + /// the tree (normal size of the tree*bucket size) pub fn new( number_of_additional_branches_to_evict: usize, tree_height: u32, From 554a1784219782be19d288341ab4e1640e313da9 Mon Sep 17 00:00:00 2001 From: William J Date: Fri, 2 Sep 2022 12:32:31 -0400 Subject: [PATCH 14/22] Remove size parameter from EvictorCreator and rename num_bits_needed, tree_size, internal_tests, and evict_creator --- mc-oblivious-ram/src/evictor/mod.rs | 39 +++++++++++++-------------- mc-oblivious-ram/src/lib.rs | 10 +++---- mc-oblivious-ram/src/path_oram/mod.rs | 2 +- 3 files changed, 25 insertions(+), 26 deletions(-) diff --git a/mc-oblivious-ram/src/evictor/mod.rs b/mc-oblivious-ram/src/evictor/mod.rs index 8775889..4ca16ed 100644 --- a/mc-oblivious-ram/src/evictor/mod.rs +++ b/mc-oblivious-ram/src/evictor/mod.rs @@ -17,26 +17,26 @@ use rand_core::{CryptoRng, RngCore}; /// Selects branches in reverse lexicographic order, where the most significant /// digit of the branch is always 1, corresponding to the leaf node that -/// represents that branch. +/// represents that branch. Reverse lexicographic ordering only on the `num_bits_to_be_reversed` /// E.g. for a depth of 3: /// 100, 110, 101, 111 -/// num_bits_needed corresponds to the number of possible branches that need to +/// `num_bits_to_be_reversed` corresponds to the number of possible branches that need to /// be explored, and is 1 less than the number of bits in the leaf node. /// The iteration i corresponds to the ith branch in reverse lexicographic /// order. /// -fn deterministic_get_next_branch_to_evict(num_bits_needed: u32, iteration: u64) -> u64 { +fn deterministic_get_next_branch_to_evict(num_bits_to_be_reversed: u32, iteration: u64) -> u64 { // Return 1 if the number of bits needed is 0. Calculation furtherdown would // overflow, and shortcutting here does not leak information because the // number of bits is structural information rather than query specific. - if num_bits_needed == 0 { + if num_bits_to_be_reversed == 0 { return 1; } // This is the first index at which leafs exist, the most significant digit // of all leafs is 1. - let leaf_significant_index: u64 = 1 << (num_bits_needed); + let leaf_significant_index: u64 = 1 << (num_bits_to_be_reversed); let test_position: u64 = - ((iteration).reverse_bits() >> (64 - num_bits_needed)) % leaf_significant_index; + ((iteration).reverse_bits() >> (64 - num_bits_to_be_reversed)) % leaf_significant_index; leaf_significant_index + test_position } @@ -91,23 +91,20 @@ pub struct PathOramDeterministicEvict { number_of_additional_branches_to_evict: usize, branches_evicted: u64, tree_height: u32, - tree_size: u64, + tree_breadth: u64, } impl PathOramDeterministicEvict { /// Create a new deterministic branch selector that will select /// num_elements_to_evict branches per access /// tree height: corresponds to the height of tree - /// tree_size: corresponds to the number of elements that can be stored in - /// the tree (normal size of the tree*bucket size) pub fn new( number_of_additional_branches_to_evict: usize, tree_height: u32, - tree_size: u64, ) -> Self { Self { number_of_additional_branches_to_evict, tree_height, - tree_size, + tree_breadth: 2u64^(tree_height as u64), branches_evicted: 0, } } @@ -118,7 +115,7 @@ impl BranchSelector for PathOramDeterministicEvict { //The height of the root is 0, so the number of bits needed for the leaves is // just the height let iteration = self.branches_evicted; - self.branches_evicted = (self.branches_evicted + 1) % self.tree_size; + self.branches_evicted = (self.branches_evicted + 1) % self.tree_breadth; deterministic_get_next_branch_to_evict(self.tree_height, iteration) } @@ -202,16 +199,18 @@ where { type Output: EvictionStrategy + BranchSelector + Send + Sync + 'static; - fn create(&self, size: u64, height: u32) -> Self::Output; + /// Creates an eviction strategy + /// height: height of the tree eviction will be called on, impacts branch selection. + fn create(&self, height: u32) -> Self::Output; } /// A factory which creates an PathOramDeterministicEvictor that evicts from the -/// stash into an additional number_of_additional_branches_to_evict branches in +/// stash into an additional `number_of_additional_branches_to_evict` branches in /// addition to the currently checked out branch in reverse lexicographic order -pub struct PathOramDeterministicEvictCreator { +pub struct PathOramDeterministicEvictorCreator { number_of_additional_branches_to_evict: usize, } -impl PathOramDeterministicEvictCreator { +impl PathOramDeterministicEvictorCreator { /// Create a factory for a deterministic branch selector that will evict /// number_of_additional_branches_to_evict branches per access pub fn new(number_of_additional_branches_to_evict: usize) -> Self { @@ -221,7 +220,7 @@ impl PathOramDeterministicEvictCreator { } } -impl EvictorCreator for PathOramDeterministicEvictCreator +impl EvictorCreator for PathOramDeterministicEvictorCreator where ValueSize: ArrayLength + PartialDiv + PartialDiv, Z: Unsigned + Mul + Mul, @@ -230,13 +229,13 @@ where { type Output = PathOramDeterministicEvict; - fn create(&self, size: u64, height: u32) -> Self::Output { - PathOramDeterministicEvict::new(self.number_of_additional_branches_to_evict, height, size) + fn create(&self, height: u32) -> Self::Output { + PathOramDeterministicEvict::new(self.number_of_additional_branches_to_evict, height) } } #[cfg(test)] -mod internal_tests { +mod tests { use super::*; #[test] // Check that deterministic oram correctly chooses leaf values diff --git a/mc-oblivious-ram/src/lib.rs b/mc-oblivious-ram/src/lib.rs index 2ab782c..12b8fd2 100644 --- a/mc-oblivious-ram/src/lib.rs +++ b/mc-oblivious-ram/src/lib.rs @@ -33,7 +33,7 @@ mod position_map; pub use position_map::{ORAMU32PositionMap, TrivialPositionMap, U32PositionMapCreator}; mod evictor; -pub use evictor::{PathOramDeterministicEvict, PathOramDeterministicEvictCreator}; +pub use evictor::{PathOramDeterministicEvict, PathOramDeterministicEvictorCreator}; mod path_oram; pub use path_oram::PathORAM; @@ -64,13 +64,13 @@ where stash_size: usize, rng_maker: &mut M, ) -> Self::Output { - let evictor_factory = PathOramDeterministicEvictCreator::new(0); + let evictor_factory = PathOramDeterministicEvictorCreator::new(0); PathORAM::new::< U32PositionMapCreator, SC, M, - PathOramDeterministicEvictCreator, + PathOramDeterministicEvictorCreator, >(size, stash_size, rng_maker, evictor_factory) } } @@ -98,13 +98,13 @@ where stash_size: usize, rng_maker: &mut M, ) -> Self::Output { - let evictor_factory = PathOramDeterministicEvictCreator::new(0); + let evictor_factory = PathOramDeterministicEvictorCreator::new(0); PathORAM::new::< U32PositionMapCreator, SC, M, - PathOramDeterministicEvictCreator, + PathOramDeterministicEvictorCreator, >(size, stash_size, rng_maker, evictor_factory) } } diff --git a/mc-oblivious-ram/src/path_oram/mod.rs b/mc-oblivious-ram/src/path_oram/mod.rs index 5091d61..df2c11a 100644 --- a/mc-oblivious-ram/src/path_oram/mod.rs +++ b/mc-oblivious-ram/src/path_oram/mod.rs @@ -147,7 +147,7 @@ where // the height of the root to be 0, so in a tree where the lowest level // is h, there are 2^{h+1} nodes. let mut rng = rng_maker(); - let evictor = evictor_factory.create(size, height); + let evictor = evictor_factory.create(height); let storage = SC::create(2u64 << height, &mut rng).expect("Storage failed"); let pos = PMC::create(size, height, stash_size, rng_maker); Self { From e0d485caef44d74ffd7712e3bbd861fa4d302450 Mon Sep 17 00:00:00 2001 From: wjuan-mob Date: Fri, 2 Sep 2022 12:55:30 -0400 Subject: [PATCH 15/22] Update mc-oblivious-ram/src/evictor/mod.rs Co-authored-by: Nick Santana --- mc-oblivious-ram/src/evictor/mod.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/mc-oblivious-ram/src/evictor/mod.rs b/mc-oblivious-ram/src/evictor/mod.rs index 4ca16ed..732441e 100644 --- a/mc-oblivious-ram/src/evictor/mod.rs +++ b/mc-oblivious-ram/src/evictor/mod.rs @@ -161,12 +161,13 @@ fn path_oram_eviction_strategy( } pub trait BranchSelector { - /// Returns the leaf index of the next branch to call evict from stash - /// to branch on. + /// Returns the leaf index of the next branch to call + /// [EvictionStrategy::evict_from_stash_to_branch] on. fn get_next_branch_to_evict(&mut self) -> u64; - /// Returns the number of branches to call evict from stash to branch - /// on. + /// Returns the number of branches to call + /// [EvictionStrategy::evict_from_stash_to_branch] on. + fn get_number_of_additional_branches_to_evict(&self) -> usize; } From 363f6cf2513bcc5e4036dd2ef7648f8090c852eb Mon Sep 17 00:00:00 2001 From: William J Date: Fri, 2 Sep 2022 12:59:21 -0400 Subject: [PATCH 16/22] Rename evict to evictor --- mc-oblivious-ram/src/evictor/mod.rs | 18 +++++++++--------- mc-oblivious-ram/src/lib.rs | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/mc-oblivious-ram/src/evictor/mod.rs b/mc-oblivious-ram/src/evictor/mod.rs index 4ca16ed..efc7c58 100644 --- a/mc-oblivious-ram/src/evictor/mod.rs +++ b/mc-oblivious-ram/src/evictor/mod.rs @@ -42,7 +42,7 @@ fn deterministic_get_next_branch_to_evict(num_bits_to_be_reversed: u32, iteratio /// An evictor that implements a random branch selection and the path oram /// eviction strategy -pub struct PathOramRandomEvict +pub struct PathOramRandomEvictor where RngType: RngCore + CryptoRng + Send + Sync + 'static, { @@ -52,7 +52,7 @@ where tree_height: u32, } -impl BranchSelector for PathOramRandomEvict +impl BranchSelector for PathOramRandomEvictor where RngType: RngCore + CryptoRng + Send + Sync + 'static, { @@ -65,7 +65,7 @@ where self.number_of_additional_branches_to_evict } } -impl EvictionStrategy for PathOramRandomEvict +impl EvictionStrategy for PathOramRandomEvictor where ValueSize: ArrayLength + PartialDiv + PartialDiv, Z: Unsigned + Mul + Mul, @@ -87,13 +87,13 @@ where /// An evictor that implements a deterministic branch selection in reverse /// lexicographic order and using the path oram eviction strategy -pub struct PathOramDeterministicEvict { +pub struct PathOramDeterministicEvictor { number_of_additional_branches_to_evict: usize, branches_evicted: u64, tree_height: u32, tree_breadth: u64, } -impl PathOramDeterministicEvict { +impl PathOramDeterministicEvictor { /// Create a new deterministic branch selector that will select /// num_elements_to_evict branches per access /// tree height: corresponds to the height of tree @@ -110,7 +110,7 @@ impl PathOramDeterministicEvict { } } -impl BranchSelector for PathOramDeterministicEvict { +impl BranchSelector for PathOramDeterministicEvictor { fn get_next_branch_to_evict(&mut self) -> u64 { //The height of the root is 0, so the number of bits needed for the leaves is // just the height @@ -123,7 +123,7 @@ impl BranchSelector for PathOramDeterministicEvict { self.number_of_additional_branches_to_evict } } -impl EvictionStrategy for PathOramDeterministicEvict +impl EvictionStrategy for PathOramDeterministicEvictor where ValueSize: ArrayLength + PartialDiv + PartialDiv, Z: Unsigned + Mul + Mul, @@ -227,10 +227,10 @@ where Prod: ArrayLength + PartialDiv, Prod: ArrayLength + PartialDiv, { - type Output = PathOramDeterministicEvict; + type Output = PathOramDeterministicEvictor; fn create(&self, height: u32) -> Self::Output { - PathOramDeterministicEvict::new(self.number_of_additional_branches_to_evict, height) + PathOramDeterministicEvictor::new(self.number_of_additional_branches_to_evict, height) } } diff --git a/mc-oblivious-ram/src/lib.rs b/mc-oblivious-ram/src/lib.rs index 12b8fd2..06b2844 100644 --- a/mc-oblivious-ram/src/lib.rs +++ b/mc-oblivious-ram/src/lib.rs @@ -33,7 +33,7 @@ mod position_map; pub use position_map::{ORAMU32PositionMap, TrivialPositionMap, U32PositionMapCreator}; mod evictor; -pub use evictor::{PathOramDeterministicEvict, PathOramDeterministicEvictorCreator}; +pub use evictor::{PathOramDeterministicEvictor, PathOramDeterministicEvictorCreator}; mod path_oram; pub use path_oram::PathORAM; @@ -57,7 +57,7 @@ where R: RngCore + CryptoRng + Send + Sync + 'static, SC: ORAMStorageCreator, { - type Output = PathORAM; + type Output = PathORAM; fn create R>( size: u64, @@ -91,7 +91,7 @@ where R: RngCore + CryptoRng + Send + Sync + 'static, SC: ORAMStorageCreator, { - type Output = PathORAM; + type Output = PathORAM; fn create R>( size: u64, From 31ab6bb0127659eaf84894332c848b826c5a04ce Mon Sep 17 00:00:00 2001 From: wjuan-mob Date: Fri, 2 Sep 2022 13:24:52 -0400 Subject: [PATCH 17/22] Update mc-oblivious-ram/src/evictor/mod.rs Co-authored-by: Nick Santana --- mc-oblivious-ram/src/evictor/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mc-oblivious-ram/src/evictor/mod.rs b/mc-oblivious-ram/src/evictor/mod.rs index e980945..5ef0e3e 100644 --- a/mc-oblivious-ram/src/evictor/mod.rs +++ b/mc-oblivious-ram/src/evictor/mod.rs @@ -213,7 +213,7 @@ pub struct PathOramDeterministicEvictorCreator { } impl PathOramDeterministicEvictorCreator { /// Create a factory for a deterministic branch selector that will evict - /// number_of_additional_branches_to_evict branches per access + /// `number_of_additional_branches_to_evict` branches per access pub fn new(number_of_additional_branches_to_evict: usize) -> Self { Self { number_of_additional_branches_to_evict, From 35b1e2f7879e78999bb97699d222349bc32b9fbb Mon Sep 17 00:00:00 2001 From: William J Date: Fri, 2 Sep 2022 14:54:14 -0400 Subject: [PATCH 18/22] Format evictor. --- mc-oblivious-ram/src/evictor/mod.rs | 31 +++++++++++++---------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/mc-oblivious-ram/src/evictor/mod.rs b/mc-oblivious-ram/src/evictor/mod.rs index 5ef0e3e..aeee87a 100644 --- a/mc-oblivious-ram/src/evictor/mod.rs +++ b/mc-oblivious-ram/src/evictor/mod.rs @@ -17,14 +17,13 @@ use rand_core::{CryptoRng, RngCore}; /// Selects branches in reverse lexicographic order, where the most significant /// digit of the branch is always 1, corresponding to the leaf node that -/// represents that branch. Reverse lexicographic ordering only on the `num_bits_to_be_reversed` -/// E.g. for a depth of 3: +/// represents that branch. Reverse lexicographic ordering only on the +/// `num_bits_to_be_reversed` E.g. for a depth of 3: /// 100, 110, 101, 111 -/// `num_bits_to_be_reversed` corresponds to the number of possible branches that need to -/// be explored, and is 1 less than the number of bits in the leaf node. -/// The iteration i corresponds to the ith branch in reverse lexicographic +/// `num_bits_to_be_reversed` corresponds to the number of possible branches +/// that need to be explored, and is 1 less than the number of bits in the leaf +/// node. `iteration` i corresponds to the ith branch in reverse lexicographic /// order. -/// fn deterministic_get_next_branch_to_evict(num_bits_to_be_reversed: u32, iteration: u64) -> u64 { // Return 1 if the number of bits needed is 0. Calculation furtherdown would // overflow, and shortcutting here does not leak information because the @@ -97,14 +96,11 @@ impl PathOramDeterministicEvictor { /// Create a new deterministic branch selector that will select /// num_elements_to_evict branches per access /// tree height: corresponds to the height of tree - pub fn new( - number_of_additional_branches_to_evict: usize, - tree_height: u32, - ) -> Self { + pub fn new(number_of_additional_branches_to_evict: usize, tree_height: u32) -> Self { Self { number_of_additional_branches_to_evict, tree_height, - tree_breadth: 2u64^(tree_height as u64), + tree_breadth: 2u64 ^ (tree_height as u64), branches_evicted: 0, } } @@ -161,13 +157,12 @@ fn path_oram_eviction_strategy( } pub trait BranchSelector { - /// Returns the leaf index of the next branch to call + /// Returns the leaf index of the next branch to call /// [EvictionStrategy::evict_from_stash_to_branch] on. fn get_next_branch_to_evict(&mut self) -> u64; - /// Returns the number of branches to call + /// Returns the number of branches to call /// [EvictionStrategy::evict_from_stash_to_branch] on. - fn get_number_of_additional_branches_to_evict(&self) -> usize; } @@ -201,13 +196,15 @@ where type Output: EvictionStrategy + BranchSelector + Send + Sync + 'static; /// Creates an eviction strategy - /// height: height of the tree eviction will be called on, impacts branch selection. + /// height: height of the tree eviction will be called on, impacts branch + /// selection. fn create(&self, height: u32) -> Self::Output; } /// A factory which creates an PathOramDeterministicEvictor that evicts from the -/// stash into an additional `number_of_additional_branches_to_evict` branches in -/// addition to the currently checked out branch in reverse lexicographic order +/// stash into an additional `number_of_additional_branches_to_evict` branches +/// in addition to the currently checked out branch in reverse lexicographic +/// order. pub struct PathOramDeterministicEvictorCreator { number_of_additional_branches_to_evict: usize, } From 7e19573a307aa126291cc1c086632859f137e1be Mon Sep 17 00:00:00 2001 From: William J Date: Fri, 2 Sep 2022 14:57:15 -0400 Subject: [PATCH 19/22] Add backticks around input variable names --- mc-oblivious-ram/src/evictor/mod.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mc-oblivious-ram/src/evictor/mod.rs b/mc-oblivious-ram/src/evictor/mod.rs index aeee87a..0b345d4 100644 --- a/mc-oblivious-ram/src/evictor/mod.rs +++ b/mc-oblivious-ram/src/evictor/mod.rs @@ -94,8 +94,9 @@ pub struct PathOramDeterministicEvictor { } impl PathOramDeterministicEvictor { /// Create a new deterministic branch selector that will select - /// num_elements_to_evict branches per access - /// tree height: corresponds to the height of tree + /// `number_of_additional_branches_to_evict`: branches per access in + /// excess of branch with accessed element. + /// `tree height`: corresponds to the height of tree pub fn new(number_of_additional_branches_to_evict: usize, tree_height: u32) -> Self { Self { number_of_additional_branches_to_evict, @@ -196,7 +197,7 @@ where type Output: EvictionStrategy + BranchSelector + Send + Sync + 'static; /// Creates an eviction strategy - /// height: height of the tree eviction will be called on, impacts branch + /// `height`: height of the tree eviction will be called on, impacts branch /// selection. fn create(&self, height: u32) -> Self::Output; } From 29f028bf4665d4421c6a8f4d48b2bda30f343c46 Mon Sep 17 00:00:00 2001 From: William J Date: Fri, 2 Sep 2022 14:59:53 -0400 Subject: [PATCH 20/22] Add clarifying comment on why path oram does not require additional branches to evict. --- mc-oblivious-ram/src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mc-oblivious-ram/src/lib.rs b/mc-oblivious-ram/src/lib.rs index 06b2844..c64aaa7 100644 --- a/mc-oblivious-ram/src/lib.rs +++ b/mc-oblivious-ram/src/lib.rs @@ -64,6 +64,9 @@ where stash_size: usize, rng_maker: &mut M, ) -> Self::Output { + // Number of additional branches to evict is 0 because path oram densely packs + // the branch which contains the accessed element, and thus no additional + // branches need to be evicted to maintain performance. let evictor_factory = PathOramDeterministicEvictorCreator::new(0); PathORAM::new::< @@ -98,6 +101,9 @@ where stash_size: usize, rng_maker: &mut M, ) -> Self::Output { + // Number of additional branches to evict is 0 because path oram densely packs + // the branch which contains the accessed element, and thus no additional + // branches need to be evicted to maintain performance. let evictor_factory = PathOramDeterministicEvictorCreator::new(0); PathORAM::new::< From 7345e17a3aa446d270a40aae11ea3b1d900c45c5 Mon Sep 17 00:00:00 2001 From: William J Date: Thu, 8 Sep 2022 02:54:43 -0400 Subject: [PATCH 21/22] Refactor evictor/mod.rs to evictor.r --- mc-oblivious-ram/src/evictor.rs | 231 ++++++++++++++++++++++-- mc-oblivious-ram/src/evictor/mod.rs | 261 ---------------------------- 2 files changed, 215 insertions(+), 277 deletions(-) delete mode 100644 mc-oblivious-ram/src/evictor/mod.rs diff --git a/mc-oblivious-ram/src/evictor.rs b/mc-oblivious-ram/src/evictor.rs index 58d2181..0b345d4 100644 --- a/mc-oblivious-ram/src/evictor.rs +++ b/mc-oblivious-ram/src/evictor.rs @@ -6,23 +6,71 @@ //! include path ORAM and circuit ORAM. These strategies will be used for //! evicting stash elements to the tree ORAM. +use crate::path_oram::{BranchCheckout, MetaSize}; use aligned_cmov::{ typenum::{PartialDiv, Prod, Unsigned, U64, U8}, A64Bytes, A8Bytes, ArrayLength, }; - +use balanced_tree_index::TreeIndex; use core::ops::Mul; +use rand_core::{CryptoRng, RngCore}; -use crate::path_oram::{BranchCheckout, MetaSize}; +/// Selects branches in reverse lexicographic order, where the most significant +/// digit of the branch is always 1, corresponding to the leaf node that +/// represents that branch. Reverse lexicographic ordering only on the +/// `num_bits_to_be_reversed` E.g. for a depth of 3: +/// 100, 110, 101, 111 +/// `num_bits_to_be_reversed` corresponds to the number of possible branches +/// that need to be explored, and is 1 less than the number of bits in the leaf +/// node. `iteration` i corresponds to the ith branch in reverse lexicographic +/// order. +fn deterministic_get_next_branch_to_evict(num_bits_to_be_reversed: u32, iteration: u64) -> u64 { + // Return 1 if the number of bits needed is 0. Calculation furtherdown would + // overflow, and shortcutting here does not leak information because the + // number of bits is structural information rather than query specific. + if num_bits_to_be_reversed == 0 { + return 1; + } + // This is the first index at which leafs exist, the most significant digit + // of all leafs is 1. + let leaf_significant_index: u64 = 1 << (num_bits_to_be_reversed); + let test_position: u64 = + ((iteration).reverse_bits() >> (64 - num_bits_to_be_reversed)) % leaf_significant_index; + leaf_significant_index + test_position +} -/// Evictor trait conceptually is a mechanism for moving stash elements into -/// the oram. -pub trait Evictor +/// An evictor that implements a random branch selection and the path oram +/// eviction strategy +pub struct PathOramRandomEvictor +where + RngType: RngCore + CryptoRng + Send + Sync + 'static, +{ + rng: RngType, + number_of_additional_branches_to_evict: usize, + branches_evicted: u64, + tree_height: u32, +} + +impl BranchSelector for PathOramRandomEvictor +where + RngType: RngCore + CryptoRng + Send + Sync + 'static, +{ + fn get_next_branch_to_evict(&mut self) -> u64 { + self.branches_evicted += 1; + 1u64.random_child_at_height(self.tree_height, &mut self.rng) + } + + fn get_number_of_additional_branches_to_evict(&self) -> usize { + self.number_of_additional_branches_to_evict + } +} +impl EvictionStrategy for PathOramRandomEvictor where ValueSize: ArrayLength + PartialDiv + PartialDiv, Z: Unsigned + Mul + Mul, Prod: ArrayLength + PartialDiv, Prod: ArrayLength + PartialDiv, + RngType: RngCore + CryptoRng + Send + Sync + 'static, { /// Method that takes a branch and a stash and moves elements from the /// stash into the branch. @@ -31,10 +79,48 @@ where stash_data: &mut [A64Bytes], stash_meta: &mut [A8Bytes], branch: &mut BranchCheckout, - ); + ) { + path_oram_eviction_strategy::(stash_data, stash_meta, branch); + } +} + +/// An evictor that implements a deterministic branch selection in reverse +/// lexicographic order and using the path oram eviction strategy +pub struct PathOramDeterministicEvictor { + number_of_additional_branches_to_evict: usize, + branches_evicted: u64, + tree_height: u32, + tree_breadth: u64, +} +impl PathOramDeterministicEvictor { + /// Create a new deterministic branch selector that will select + /// `number_of_additional_branches_to_evict`: branches per access in + /// excess of branch with accessed element. + /// `tree height`: corresponds to the height of tree + pub fn new(number_of_additional_branches_to_evict: usize, tree_height: u32) -> Self { + Self { + number_of_additional_branches_to_evict, + tree_height, + tree_breadth: 2u64 ^ (tree_height as u64), + branches_evicted: 0, + } + } } -pub struct PathOramEvict {} -impl Evictor for PathOramEvict + +impl BranchSelector for PathOramDeterministicEvictor { + fn get_next_branch_to_evict(&mut self) -> u64 { + //The height of the root is 0, so the number of bits needed for the leaves is + // just the height + let iteration = self.branches_evicted; + self.branches_evicted = (self.branches_evicted + 1) % self.tree_breadth; + deterministic_get_next_branch_to_evict(self.tree_height, iteration) + } + + fn get_number_of_additional_branches_to_evict(&self) -> usize { + self.number_of_additional_branches_to_evict + } +} +impl EvictionStrategy for PathOramDeterministicEvictor where ValueSize: ArrayLength + PartialDiv + PartialDiv, Z: Unsigned + Mul + Mul, @@ -47,16 +133,129 @@ where stash_meta: &mut [A8Bytes], branch: &mut BranchCheckout, ) { - branch.pack(); - //Greedily place elements of the stash into the branch as close to the leaf as - // they can go. - for idx in 0..stash_data.len() { - branch.ct_insert(1.into(), &stash_data[idx], &mut stash_meta[idx]); + path_oram_eviction_strategy::(stash_data, stash_meta, branch); + } +} + +/// Eviction algorithm defined in path oram. Packs the branch and greedily +/// tries to evict everything from the stash into the checked out branch +fn path_oram_eviction_strategy( + stash_data: &mut [A64Bytes], + stash_meta: &mut [A8Bytes], + branch: &mut BranchCheckout, +) where + ValueSize: ArrayLength + PartialDiv + PartialDiv, + Z: Unsigned + Mul + Mul, + Prod: ArrayLength + PartialDiv, + Prod: ArrayLength + PartialDiv, +{ + branch.pack(); + //Greedily place elements of the stash into the branch as close to the leaf as + // they can go. + for idx in 0..stash_data.len() { + branch.ct_insert(1.into(), &stash_data[idx], &mut stash_meta[idx]); + } +} + +pub trait BranchSelector { + /// Returns the leaf index of the next branch to call + /// [EvictionStrategy::evict_from_stash_to_branch] on. + fn get_next_branch_to_evict(&mut self) -> u64; + + /// Returns the number of branches to call + /// [EvictionStrategy::evict_from_stash_to_branch] on. + fn get_number_of_additional_branches_to_evict(&self) -> usize; +} + +/// Evictor trait conceptually is a mechanism for moving stash elements into +/// the oram. +pub trait EvictionStrategy +where + ValueSize: ArrayLength + PartialDiv + PartialDiv, + Z: Unsigned + Mul + Mul, + Prod: ArrayLength + PartialDiv, + Prod: ArrayLength + PartialDiv, +{ + /// Method that takes a branch and a stash and moves elements from the + /// stash into the branch. + fn evict_from_stash_to_branch( + &self, + stash_data: &mut [A64Bytes], + stash_meta: &mut [A8Bytes], + branch: &mut BranchCheckout, + ); +} + +/// A factory which creates an Evictor +pub trait EvictorCreator +where + ValueSize: ArrayLength + PartialDiv + PartialDiv, + Z: Unsigned + Mul + Mul, + Prod: ArrayLength + PartialDiv, + Prod: ArrayLength + PartialDiv, +{ + type Output: EvictionStrategy + BranchSelector + Send + Sync + 'static; + + /// Creates an eviction strategy + /// `height`: height of the tree eviction will be called on, impacts branch + /// selection. + fn create(&self, height: u32) -> Self::Output; +} + +/// A factory which creates an PathOramDeterministicEvictor that evicts from the +/// stash into an additional `number_of_additional_branches_to_evict` branches +/// in addition to the currently checked out branch in reverse lexicographic +/// order. +pub struct PathOramDeterministicEvictorCreator { + number_of_additional_branches_to_evict: usize, +} +impl PathOramDeterministicEvictorCreator { + /// Create a factory for a deterministic branch selector that will evict + /// `number_of_additional_branches_to_evict` branches per access + pub fn new(number_of_additional_branches_to_evict: usize) -> Self { + Self { + number_of_additional_branches_to_evict, } } } -impl PathOramEvict { - pub fn new() -> Self { - Self {} + +impl EvictorCreator for PathOramDeterministicEvictorCreator +where + ValueSize: ArrayLength + PartialDiv + PartialDiv, + Z: Unsigned + Mul + Mul, + Prod: ArrayLength + PartialDiv, + Prod: ArrayLength + PartialDiv, +{ + type Output = PathOramDeterministicEvictor; + + fn create(&self, height: u32) -> Self::Output { + PathOramDeterministicEvictor::new(self.number_of_additional_branches_to_evict, height) + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + // Check that deterministic oram correctly chooses leaf values + fn test_deterministic_oram_get_branches_to_evict() { + let test_branch = deterministic_get_next_branch_to_evict(3, 0); + assert_eq!(test_branch, 8); + let test_branch = deterministic_get_next_branch_to_evict(3, 1); + assert_eq!(test_branch, 12); + let test_branch = deterministic_get_next_branch_to_evict(3, 2); + assert_eq!(test_branch, 10); + let test_branch = deterministic_get_next_branch_to_evict(3, 3); + assert_eq!(test_branch, 14); + let test_branch = deterministic_get_next_branch_to_evict(3, 4); + assert_eq!(test_branch, 9); + let test_branch = deterministic_get_next_branch_to_evict(3, 5); + assert_eq!(test_branch, 13); + let test_branch = deterministic_get_next_branch_to_evict(3, 6); + assert_eq!(test_branch, 11); + let test_branch = deterministic_get_next_branch_to_evict(3, 7); + assert_eq!(test_branch, 15); + let test_branch = deterministic_get_next_branch_to_evict(3, 8); + assert_eq!(test_branch, 8); } } diff --git a/mc-oblivious-ram/src/evictor/mod.rs b/mc-oblivious-ram/src/evictor/mod.rs deleted file mode 100644 index 0b345d4..0000000 --- a/mc-oblivious-ram/src/evictor/mod.rs +++ /dev/null @@ -1,261 +0,0 @@ -// Copyright (c) 2018-2022 The MobileCoin Foundation - -//! Evictor functions for ORAM -//! -//! A module containing different eviction strategies for tree based ORAMs which -//! include path ORAM and circuit ORAM. These strategies will be used for -//! evicting stash elements to the tree ORAM. - -use crate::path_oram::{BranchCheckout, MetaSize}; -use aligned_cmov::{ - typenum::{PartialDiv, Prod, Unsigned, U64, U8}, - A64Bytes, A8Bytes, ArrayLength, -}; -use balanced_tree_index::TreeIndex; -use core::ops::Mul; -use rand_core::{CryptoRng, RngCore}; - -/// Selects branches in reverse lexicographic order, where the most significant -/// digit of the branch is always 1, corresponding to the leaf node that -/// represents that branch. Reverse lexicographic ordering only on the -/// `num_bits_to_be_reversed` E.g. for a depth of 3: -/// 100, 110, 101, 111 -/// `num_bits_to_be_reversed` corresponds to the number of possible branches -/// that need to be explored, and is 1 less than the number of bits in the leaf -/// node. `iteration` i corresponds to the ith branch in reverse lexicographic -/// order. -fn deterministic_get_next_branch_to_evict(num_bits_to_be_reversed: u32, iteration: u64) -> u64 { - // Return 1 if the number of bits needed is 0. Calculation furtherdown would - // overflow, and shortcutting here does not leak information because the - // number of bits is structural information rather than query specific. - if num_bits_to_be_reversed == 0 { - return 1; - } - // This is the first index at which leafs exist, the most significant digit - // of all leafs is 1. - let leaf_significant_index: u64 = 1 << (num_bits_to_be_reversed); - let test_position: u64 = - ((iteration).reverse_bits() >> (64 - num_bits_to_be_reversed)) % leaf_significant_index; - leaf_significant_index + test_position -} - -/// An evictor that implements a random branch selection and the path oram -/// eviction strategy -pub struct PathOramRandomEvictor -where - RngType: RngCore + CryptoRng + Send + Sync + 'static, -{ - rng: RngType, - number_of_additional_branches_to_evict: usize, - branches_evicted: u64, - tree_height: u32, -} - -impl BranchSelector for PathOramRandomEvictor -where - RngType: RngCore + CryptoRng + Send + Sync + 'static, -{ - fn get_next_branch_to_evict(&mut self) -> u64 { - self.branches_evicted += 1; - 1u64.random_child_at_height(self.tree_height, &mut self.rng) - } - - fn get_number_of_additional_branches_to_evict(&self) -> usize { - self.number_of_additional_branches_to_evict - } -} -impl EvictionStrategy for PathOramRandomEvictor -where - ValueSize: ArrayLength + PartialDiv + PartialDiv, - Z: Unsigned + Mul + Mul, - Prod: ArrayLength + PartialDiv, - Prod: ArrayLength + PartialDiv, - RngType: RngCore + CryptoRng + Send + Sync + 'static, -{ - /// Method that takes a branch and a stash and moves elements from the - /// stash into the branch. - fn evict_from_stash_to_branch( - &self, - stash_data: &mut [A64Bytes], - stash_meta: &mut [A8Bytes], - branch: &mut BranchCheckout, - ) { - path_oram_eviction_strategy::(stash_data, stash_meta, branch); - } -} - -/// An evictor that implements a deterministic branch selection in reverse -/// lexicographic order and using the path oram eviction strategy -pub struct PathOramDeterministicEvictor { - number_of_additional_branches_to_evict: usize, - branches_evicted: u64, - tree_height: u32, - tree_breadth: u64, -} -impl PathOramDeterministicEvictor { - /// Create a new deterministic branch selector that will select - /// `number_of_additional_branches_to_evict`: branches per access in - /// excess of branch with accessed element. - /// `tree height`: corresponds to the height of tree - pub fn new(number_of_additional_branches_to_evict: usize, tree_height: u32) -> Self { - Self { - number_of_additional_branches_to_evict, - tree_height, - tree_breadth: 2u64 ^ (tree_height as u64), - branches_evicted: 0, - } - } -} - -impl BranchSelector for PathOramDeterministicEvictor { - fn get_next_branch_to_evict(&mut self) -> u64 { - //The height of the root is 0, so the number of bits needed for the leaves is - // just the height - let iteration = self.branches_evicted; - self.branches_evicted = (self.branches_evicted + 1) % self.tree_breadth; - deterministic_get_next_branch_to_evict(self.tree_height, iteration) - } - - fn get_number_of_additional_branches_to_evict(&self) -> usize { - self.number_of_additional_branches_to_evict - } -} -impl EvictionStrategy for PathOramDeterministicEvictor -where - ValueSize: ArrayLength + PartialDiv + PartialDiv, - Z: Unsigned + Mul + Mul, - Prod: ArrayLength + PartialDiv, - Prod: ArrayLength + PartialDiv, -{ - fn evict_from_stash_to_branch( - &self, - stash_data: &mut [A64Bytes], - stash_meta: &mut [A8Bytes], - branch: &mut BranchCheckout, - ) { - path_oram_eviction_strategy::(stash_data, stash_meta, branch); - } -} - -/// Eviction algorithm defined in path oram. Packs the branch and greedily -/// tries to evict everything from the stash into the checked out branch -fn path_oram_eviction_strategy( - stash_data: &mut [A64Bytes], - stash_meta: &mut [A8Bytes], - branch: &mut BranchCheckout, -) where - ValueSize: ArrayLength + PartialDiv + PartialDiv, - Z: Unsigned + Mul + Mul, - Prod: ArrayLength + PartialDiv, - Prod: ArrayLength + PartialDiv, -{ - branch.pack(); - //Greedily place elements of the stash into the branch as close to the leaf as - // they can go. - for idx in 0..stash_data.len() { - branch.ct_insert(1.into(), &stash_data[idx], &mut stash_meta[idx]); - } -} - -pub trait BranchSelector { - /// Returns the leaf index of the next branch to call - /// [EvictionStrategy::evict_from_stash_to_branch] on. - fn get_next_branch_to_evict(&mut self) -> u64; - - /// Returns the number of branches to call - /// [EvictionStrategy::evict_from_stash_to_branch] on. - fn get_number_of_additional_branches_to_evict(&self) -> usize; -} - -/// Evictor trait conceptually is a mechanism for moving stash elements into -/// the oram. -pub trait EvictionStrategy -where - ValueSize: ArrayLength + PartialDiv + PartialDiv, - Z: Unsigned + Mul + Mul, - Prod: ArrayLength + PartialDiv, - Prod: ArrayLength + PartialDiv, -{ - /// Method that takes a branch and a stash and moves elements from the - /// stash into the branch. - fn evict_from_stash_to_branch( - &self, - stash_data: &mut [A64Bytes], - stash_meta: &mut [A8Bytes], - branch: &mut BranchCheckout, - ); -} - -/// A factory which creates an Evictor -pub trait EvictorCreator -where - ValueSize: ArrayLength + PartialDiv + PartialDiv, - Z: Unsigned + Mul + Mul, - Prod: ArrayLength + PartialDiv, - Prod: ArrayLength + PartialDiv, -{ - type Output: EvictionStrategy + BranchSelector + Send + Sync + 'static; - - /// Creates an eviction strategy - /// `height`: height of the tree eviction will be called on, impacts branch - /// selection. - fn create(&self, height: u32) -> Self::Output; -} - -/// A factory which creates an PathOramDeterministicEvictor that evicts from the -/// stash into an additional `number_of_additional_branches_to_evict` branches -/// in addition to the currently checked out branch in reverse lexicographic -/// order. -pub struct PathOramDeterministicEvictorCreator { - number_of_additional_branches_to_evict: usize, -} -impl PathOramDeterministicEvictorCreator { - /// Create a factory for a deterministic branch selector that will evict - /// `number_of_additional_branches_to_evict` branches per access - pub fn new(number_of_additional_branches_to_evict: usize) -> Self { - Self { - number_of_additional_branches_to_evict, - } - } -} - -impl EvictorCreator for PathOramDeterministicEvictorCreator -where - ValueSize: ArrayLength + PartialDiv + PartialDiv, - Z: Unsigned + Mul + Mul, - Prod: ArrayLength + PartialDiv, - Prod: ArrayLength + PartialDiv, -{ - type Output = PathOramDeterministicEvictor; - - fn create(&self, height: u32) -> Self::Output { - PathOramDeterministicEvictor::new(self.number_of_additional_branches_to_evict, height) - } -} - -#[cfg(test)] -mod tests { - use super::*; - #[test] - // Check that deterministic oram correctly chooses leaf values - fn test_deterministic_oram_get_branches_to_evict() { - let test_branch = deterministic_get_next_branch_to_evict(3, 0); - assert_eq!(test_branch, 8); - let test_branch = deterministic_get_next_branch_to_evict(3, 1); - assert_eq!(test_branch, 12); - let test_branch = deterministic_get_next_branch_to_evict(3, 2); - assert_eq!(test_branch, 10); - let test_branch = deterministic_get_next_branch_to_evict(3, 3); - assert_eq!(test_branch, 14); - let test_branch = deterministic_get_next_branch_to_evict(3, 4); - assert_eq!(test_branch, 9); - let test_branch = deterministic_get_next_branch_to_evict(3, 5); - assert_eq!(test_branch, 13); - let test_branch = deterministic_get_next_branch_to_evict(3, 6); - assert_eq!(test_branch, 11); - let test_branch = deterministic_get_next_branch_to_evict(3, 7); - assert_eq!(test_branch, 15); - let test_branch = deterministic_get_next_branch_to_evict(3, 8); - assert_eq!(test_branch, 8); - } -} From e07b60e1286bbbfbe735e23fa30ee0235ea160f9 Mon Sep 17 00:00:00 2001 From: William J Date: Thu, 8 Sep 2022 03:16:04 -0400 Subject: [PATCH 22/22] Update no-asm test for rename of evict-> evictor --- no-asm-tests/src/main.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/no-asm-tests/src/main.rs b/no-asm-tests/src/main.rs index a85361d..aa95654 100644 --- a/no-asm-tests/src/main.rs +++ b/no-asm-tests/src/main.rs @@ -5,7 +5,9 @@ use aligned_cmov::{ ArrayLength, }; use core::marker::PhantomData; -use mc_oblivious_ram::{PathORAM, PathOramDeterministicEvict, PathOramDeterministicEvictCreator}; +use mc_oblivious_ram::{ + PathORAM, PathOramDeterministicEvictor, PathOramDeterministicEvictorCreator, +}; use mc_oblivious_traits::{ rng_maker, HeapORAMStorageCreator, ORAMCreator, ORAMStorageCreator, ORAM, }; @@ -103,20 +105,20 @@ pub struct InsecurePathORAM4096Z4Creator> { impl> ORAMCreator for InsecurePathORAM4096Z4Creator { - type Output = PathORAM; + type Output = PathORAM; fn create RngType>( size: u64, stash_size: usize, rng_maker: &mut M, ) -> Self::Output { - let evictor_factory = PathOramDeterministicEvictCreator::new(0); - PathORAM::new::, SC, M, PathOramDeterministicEvictCreator>( - size, - stash_size, - rng_maker, - evictor_factory, - ) + let evictor_factory = PathOramDeterministicEvictorCreator::new(0); + PathORAM::new::< + InsecurePositionMapCreator, + SC, + M, + PathOramDeterministicEvictorCreator, + >(size, stash_size, rng_maker, evictor_factory) } }