mc_oblivious_ram/
lib.rs

1//! One of the main ideas in PathORAM is to use a position map, which is
2//! recursively an ORAM. The position map is built on top of an ORAM
3//! implementation.
4//!
5//! Tuning the characteristics of the position map is important for overall
6//! performance, and the PathORAM doesn't really care about those details.
7//! So in this implementation, PathORAM contains Box<dyn PositionMap>, which
8//! allows for sizing and tuning to be done at runtime.
9//!
10//! PositionMap also has slightly different initialization from ORAM.
11//! You want the PositionMap to begin in a random state, not a zeroed state.
12//! But writing random values to all the position maps on initialization is
13//! slow. To avoid the need for this, we "implicitly" initialize each position
14//! to a value which is the output of a secure block cipher.
15//!
16//! The core PathORAM implementation, using PositionMap as a block box,
17//! appears in the path_oram module. PathORAM must also use the ORAMStorage
18//! to fetch, scan, and return branches in the storage and execute the path ORAM
19//! eviction algorithm.
20
21#![no_std]
22#![deny(missing_docs)]
23#![deny(unsafe_code)]
24
25extern crate alloc;
26
27use aligned_cmov::typenum::{U1024, U2, U2048, U32, U4, U4096, U64};
28use core::marker::PhantomData;
29use mc_oblivious_traits::{ORAMCreator, ORAMStorageCreator};
30use rand_core::{CryptoRng, RngCore};
31
32mod position_map;
33pub use position_map::{ORAMU32PositionMap, TrivialPositionMap, U32PositionMapCreator};
34
35mod evictor;
36pub use evictor::{
37    CircuitOramDeterministicEvictor, CircuitOramDeterministicEvictorCreator,
38    PathOramDeterministicEvictor, PathOramDeterministicEvictorCreator,
39};
40mod path_oram;
41pub use path_oram::PathORAM;
42
43/// For Circuit ORAM to have linear stash size growth at least 2 additional
44/// branches that are sufficiently non overlapping must be evicted every time.
45/// This constant is passed into the evictor creator to specify the number of
46/// additional branches to evict per eviction
47const CIRCUIT_ORAM_ADDITIONAL_BRANCHES_TO_EVICT: usize = 2;
48/// Creator for PathORAM based on 4096-sized blocks of storage and bucket size
49/// (Z) of 2, and a basic recursive position map implementation
50///
51/// XXX: This config is broken
52/// (Chris) I sometimes see stash overflow with this config, use Z=4
53struct PathORAM4096Z2Creator<R, SC>
54where
55    R: RngCore + CryptoRng + 'static,
56    SC: ORAMStorageCreator<U4096, U32>,
57{
58    _rng: PhantomData<fn() -> R>,
59    _sc: PhantomData<fn() -> SC>,
60}
61
62impl<R, SC> ORAMCreator<U2048, R> for PathORAM4096Z2Creator<R, SC>
63where
64    R: RngCore + CryptoRng + Send + Sync + 'static,
65    SC: ORAMStorageCreator<U4096, U32>,
66{
67    type Output = PathORAM<U2048, U2, SC::Output, R, PathOramDeterministicEvictor>;
68
69    fn create<M: 'static + FnMut() -> R>(
70        size: u64,
71        stash_size: usize,
72        rng_maker: &mut M,
73    ) -> Self::Output {
74        // Number of additional branches to evict is 0 because Path ORAM densely packs
75        // the branch which contains the accessed element, and thus no additional
76        // branches need to be evicted to maintain performance.
77        let evictor_factory = PathOramDeterministicEvictorCreator::new(0);
78
79        PathORAM::new::<
80            U32PositionMapCreator<U2048, R, Self>,
81            SC,
82            M,
83            PathOramDeterministicEvictorCreator,
84        >(size, stash_size, rng_maker, evictor_factory)
85    }
86}
87
88/// Creator for PathORAM based on 4096-sized blocks of storage and bucket size
89/// (Z) of 4, and a basic recursive position map implementation
90pub struct PathORAM4096Z4Creator<R, SC>
91where
92    R: RngCore + CryptoRng + 'static,
93    SC: ORAMStorageCreator<U4096, U64>,
94{
95    _rng: PhantomData<fn() -> R>,
96    _sc: PhantomData<fn() -> SC>,
97}
98
99impl<R, SC> ORAMCreator<U1024, R> for PathORAM4096Z4Creator<R, SC>
100where
101    R: RngCore + CryptoRng + Send + Sync + 'static,
102    SC: ORAMStorageCreator<U4096, U64>,
103{
104    type Output = PathORAM<U1024, U4, SC::Output, R, PathOramDeterministicEvictor>;
105
106    fn create<M: 'static + FnMut() -> R>(
107        size: u64,
108        stash_size: usize,
109        rng_maker: &mut M,
110    ) -> Self::Output {
111        // Number of additional branches to evict is 0 because Path ORAM densely packs
112        // the branch which contains the accessed element, and thus no additional
113        // branches need to be evicted to maintain performance.
114        let evictor_factory = PathOramDeterministicEvictorCreator::new(0);
115
116        PathORAM::new::<
117            U32PositionMapCreator<U1024, R, Self>,
118            SC,
119            M,
120            PathOramDeterministicEvictorCreator,
121        >(size, stash_size, rng_maker, evictor_factory)
122    }
123}
124
125/// Creator for CircuitORAM based on 4096-sized blocks of storage
126/// and bucket size (Z) of 4, and a basic recursive position map implementation
127pub struct CircuitORAM4096Z4Creator<R, SC>
128where
129    R: RngCore + CryptoRng + 'static,
130    SC: ORAMStorageCreator<U4096, U64>,
131{
132    _rng: PhantomData<fn() -> R>,
133    _sc: PhantomData<fn() -> SC>,
134}
135
136impl<R, SC> ORAMCreator<U1024, R> for CircuitORAM4096Z4Creator<R, SC>
137where
138    R: RngCore + CryptoRng + Send + Sync + 'static,
139    SC: ORAMStorageCreator<U4096, U64>,
140{
141    type Output = PathORAM<U1024, U4, SC::Output, R, CircuitOramDeterministicEvictor>;
142
143    fn create<M: 'static + FnMut() -> R>(
144        size: u64,
145        stash_size: usize,
146        rng_maker: &mut M,
147    ) -> Self::Output {
148        let evictor_factory =
149            CircuitOramDeterministicEvictorCreator::new(CIRCUIT_ORAM_ADDITIONAL_BRANCHES_TO_EVICT);
150        PathORAM::new::<
151            U32PositionMapCreator<U1024, R, Self>,
152            SC,
153            M,
154            CircuitOramDeterministicEvictorCreator,
155        >(size, stash_size, rng_maker, evictor_factory)
156    }
157}
158
159/// Creator for CircuitORAM based on 4096-sized blocks of storage
160/// and bucket size (Z) of 2, and a basic recursive position map implementation
161pub struct CircuitORAM4096Z2Creator<R, SC>
162where
163    R: RngCore + CryptoRng + 'static,
164    SC: ORAMStorageCreator<U4096, U32>,
165{
166    _rng: PhantomData<fn() -> R>,
167    _sc: PhantomData<fn() -> SC>,
168}
169
170impl<R, SC> ORAMCreator<U2048, R> for CircuitORAM4096Z2Creator<R, SC>
171where
172    R: RngCore + CryptoRng + Send + Sync + 'static,
173    SC: ORAMStorageCreator<U4096, U32>,
174{
175    type Output = PathORAM<U2048, U2, SC::Output, R, CircuitOramDeterministicEvictor>;
176
177    fn create<M: 'static + FnMut() -> R>(
178        size: u64,
179        stash_size: usize,
180        rng_maker: &mut M,
181    ) -> Self::Output {
182        let evictor_factory =
183            CircuitOramDeterministicEvictorCreator::new(CIRCUIT_ORAM_ADDITIONAL_BRANCHES_TO_EVICT);
184        PathORAM::new::<
185            U32PositionMapCreator<U2048, R, Self>,
186            SC,
187            M,
188            CircuitOramDeterministicEvictorCreator,
189        >(size, stash_size, rng_maker, evictor_factory)
190    }
191}
192
193#[cfg(test)]
194mod testing {
195    use super::*;
196
197    use aligned_cmov::{A64Bytes, ArrayLength};
198    use mc_oblivious_traits::{rng_maker, testing, HeapORAMStorageCreator, ORAM};
199    use test_helper::{run_with_several_seeds, RngType};
200
201    const STASH_SIZE: usize = 16;
202
203    // Helper to make tests more succinct
204    fn a64_bytes<N: ArrayLength<u8>>(src: u8) -> A64Bytes<N> {
205        let mut result = A64Bytes::<N>::default();
206        for byte in result.iter_mut() {
207            *byte = src;
208        }
209        result
210    }
211
212    // Sanity check the standard z2 Path ORAM
213    #[test]
214    fn sanity_check_path_oram_z2_1024() {
215        run_with_several_seeds(|rng| {
216            let mut oram = PathORAM4096Z2Creator::<RngType, HeapORAMStorageCreator>::create(
217                1024,
218                STASH_SIZE,
219                &mut rng_maker(rng),
220            );
221            assert_eq!(a64_bytes(0), oram.write(0, &a64_bytes(1)));
222            assert_eq!(a64_bytes(1), oram.write(0, &a64_bytes(2)));
223            assert_eq!(a64_bytes(2), oram.write(0, &a64_bytes(3)));
224            assert_eq!(a64_bytes(0), oram.write(2, &a64_bytes(4)));
225            assert_eq!(a64_bytes(4), oram.write(2, &a64_bytes(5)));
226            assert_eq!(a64_bytes(3), oram.write(0, &a64_bytes(6)));
227            assert_eq!(a64_bytes(6), oram.write(0, &a64_bytes(7)));
228            assert_eq!(a64_bytes(0), oram.write(9, &a64_bytes(8)));
229            assert_eq!(a64_bytes(5), oram.write(2, &a64_bytes(10)));
230            assert_eq!(a64_bytes(7), oram.write(0, &a64_bytes(11)));
231            assert_eq!(a64_bytes(8), oram.write(9, &a64_bytes(12)));
232            assert_eq!(a64_bytes(12), oram.read(9));
233        })
234    }
235
236    // Sanity check the standard z2 Path oram
237    #[test]
238    fn sanity_check_path_oram_z2_8192() {
239        run_with_several_seeds(|rng| {
240            let mut oram = PathORAM4096Z2Creator::<RngType, HeapORAMStorageCreator>::create(
241                8192,
242                STASH_SIZE,
243                &mut rng_maker(rng),
244            );
245            assert_eq!(a64_bytes(0), oram.write(0, &a64_bytes(1)));
246            assert_eq!(a64_bytes(1), oram.write(0, &a64_bytes(2)));
247            assert_eq!(a64_bytes(2), oram.write(0, &a64_bytes(3)));
248            assert_eq!(a64_bytes(0), oram.write(2, &a64_bytes(4)));
249            assert_eq!(a64_bytes(4), oram.write(2, &a64_bytes(5)));
250            assert_eq!(a64_bytes(3), oram.write(0, &a64_bytes(6)));
251            assert_eq!(a64_bytes(6), oram.write(0, &a64_bytes(7)));
252            assert_eq!(a64_bytes(0), oram.write(9, &a64_bytes(8)));
253            assert_eq!(a64_bytes(5), oram.write(2, &a64_bytes(10)));
254            assert_eq!(a64_bytes(7), oram.write(0, &a64_bytes(11)));
255            assert_eq!(a64_bytes(8), oram.write(9, &a64_bytes(12)));
256            assert_eq!(a64_bytes(12), oram.read(9));
257        })
258    }
259
260    // Sanity check the standard z2 Path ORAM
261    #[test]
262    fn sanity_check_path_oram_z2_32768() {
263        run_with_several_seeds(|rng| {
264            let mut oram = PathORAM4096Z2Creator::<RngType, HeapORAMStorageCreator>::create(
265                32768,
266                STASH_SIZE,
267                &mut rng_maker(rng),
268            );
269            assert_eq!(a64_bytes(0), oram.write(0, &a64_bytes(1)));
270            assert_eq!(a64_bytes(1), oram.write(0, &a64_bytes(2)));
271            assert_eq!(a64_bytes(2), oram.write(0, &a64_bytes(3)));
272            assert_eq!(a64_bytes(0), oram.write(2, &a64_bytes(4)));
273            assert_eq!(a64_bytes(4), oram.write(2, &a64_bytes(5)));
274            assert_eq!(a64_bytes(3), oram.write(0, &a64_bytes(6)));
275            assert_eq!(a64_bytes(6), oram.write(0, &a64_bytes(7)));
276            assert_eq!(a64_bytes(0), oram.write(9, &a64_bytes(8)));
277            assert_eq!(a64_bytes(5), oram.write(2, &a64_bytes(10)));
278            assert_eq!(a64_bytes(7), oram.write(0, &a64_bytes(11)));
279            assert_eq!(a64_bytes(8), oram.write(9, &a64_bytes(12)));
280            assert_eq!(a64_bytes(12), oram.read(9));
281        })
282    }
283
284    // Sanity check the standard z2 Path ORAM
285    #[test]
286    fn sanity_check_path_oram_z2_262144() {
287        run_with_several_seeds(|rng| {
288            let mut oram = PathORAM4096Z2Creator::<RngType, HeapORAMStorageCreator>::create(
289                262144,
290                STASH_SIZE,
291                &mut rng_maker(rng),
292            );
293            assert_eq!(a64_bytes(0), oram.write(0, &a64_bytes(1)));
294            assert_eq!(a64_bytes(1), oram.write(0, &a64_bytes(2)));
295            assert_eq!(a64_bytes(2), oram.write(0, &a64_bytes(3)));
296            assert_eq!(a64_bytes(0), oram.write(2, &a64_bytes(4)));
297            assert_eq!(a64_bytes(4), oram.write(2, &a64_bytes(5)));
298            assert_eq!(a64_bytes(3), oram.write(0, &a64_bytes(6)));
299            assert_eq!(a64_bytes(6), oram.write(0, &a64_bytes(7)));
300            assert_eq!(a64_bytes(0), oram.write(9, &a64_bytes(8)));
301            assert_eq!(a64_bytes(5), oram.write(2, &a64_bytes(10)));
302            assert_eq!(a64_bytes(7), oram.write(0, &a64_bytes(11)));
303            assert_eq!(a64_bytes(8), oram.write(9, &a64_bytes(12)));
304            assert_eq!(a64_bytes(12), oram.read(9));
305        })
306    }
307
308    // Sanity check the standard z4 Path ORAM of size 1
309    #[test]
310    fn sanity_check_path_oram_z4_1() {
311        run_with_several_seeds(|rng| {
312            let mut oram = PathORAM4096Z4Creator::<RngType, HeapORAMStorageCreator>::create(
313                1,
314                STASH_SIZE,
315                &mut rng_maker(rng),
316            );
317            assert_eq!(a64_bytes(0), oram.write(0, &a64_bytes(1)));
318            assert_eq!(a64_bytes(1), oram.write(0, &a64_bytes(2)));
319            assert_eq!(a64_bytes(2), oram.write(0, &a64_bytes(3)));
320        })
321    }
322
323    // Sanity check the standard z4 Path ORAM
324    #[test]
325    fn sanity_check_path_oram_z4_1024() {
326        run_with_several_seeds(|rng| {
327            let mut oram = PathORAM4096Z4Creator::<RngType, HeapORAMStorageCreator>::create(
328                1024,
329                STASH_SIZE,
330                &mut rng_maker(rng),
331            );
332            assert_eq!(a64_bytes(0), oram.write(0, &a64_bytes(1)));
333            assert_eq!(a64_bytes(1), oram.write(0, &a64_bytes(2)));
334            assert_eq!(a64_bytes(2), oram.write(0, &a64_bytes(3)));
335            assert_eq!(a64_bytes(0), oram.write(2, &a64_bytes(4)));
336            assert_eq!(a64_bytes(4), oram.write(2, &a64_bytes(5)));
337            assert_eq!(a64_bytes(3), oram.write(0, &a64_bytes(6)));
338            assert_eq!(a64_bytes(6), oram.write(0, &a64_bytes(7)));
339            assert_eq!(a64_bytes(0), oram.write(9, &a64_bytes(8)));
340            assert_eq!(a64_bytes(5), oram.write(2, &a64_bytes(10)));
341            assert_eq!(a64_bytes(7), oram.write(0, &a64_bytes(11)));
342            assert_eq!(a64_bytes(8), oram.write(9, &a64_bytes(12)));
343            assert_eq!(a64_bytes(12), oram.read(9));
344        })
345    }
346
347    // Sanity check the standard z4 path oram
348    #[test]
349    fn sanity_check_path_oram_z4_8192() {
350        run_with_several_seeds(|rng| {
351            let mut oram = PathORAM4096Z4Creator::<RngType, HeapORAMStorageCreator>::create(
352                8192,
353                STASH_SIZE,
354                &mut rng_maker(rng),
355            );
356            assert_eq!(a64_bytes(0), oram.write(0, &a64_bytes(1)));
357            assert_eq!(a64_bytes(1), oram.write(0, &a64_bytes(2)));
358            assert_eq!(a64_bytes(2), oram.write(0, &a64_bytes(3)));
359            assert_eq!(a64_bytes(0), oram.write(2, &a64_bytes(4)));
360            assert_eq!(a64_bytes(4), oram.write(2, &a64_bytes(5)));
361            assert_eq!(a64_bytes(3), oram.write(0, &a64_bytes(6)));
362            assert_eq!(a64_bytes(6), oram.write(0, &a64_bytes(7)));
363            assert_eq!(a64_bytes(0), oram.write(9, &a64_bytes(8)));
364            assert_eq!(a64_bytes(5), oram.write(2, &a64_bytes(10)));
365            assert_eq!(a64_bytes(7), oram.write(0, &a64_bytes(11)));
366            assert_eq!(a64_bytes(8), oram.write(9, &a64_bytes(12)));
367            assert_eq!(a64_bytes(12), oram.read(9));
368        })
369    }
370
371    // Sanity check the standard z4 path oram
372    #[test]
373    fn sanity_check_path_oram_z4_32768() {
374        run_with_several_seeds(|rng| {
375            let mut oram = PathORAM4096Z4Creator::<RngType, HeapORAMStorageCreator>::create(
376                32768,
377                STASH_SIZE,
378                &mut rng_maker(rng),
379            );
380            assert_eq!(a64_bytes(0), oram.write(0, &a64_bytes(1)));
381            assert_eq!(a64_bytes(1), oram.write(0, &a64_bytes(2)));
382            assert_eq!(a64_bytes(2), oram.write(0, &a64_bytes(3)));
383            assert_eq!(a64_bytes(0), oram.write(2, &a64_bytes(4)));
384            assert_eq!(a64_bytes(4), oram.write(2, &a64_bytes(5)));
385            assert_eq!(a64_bytes(3), oram.write(0, &a64_bytes(6)));
386            assert_eq!(a64_bytes(6), oram.write(0, &a64_bytes(7)));
387            assert_eq!(a64_bytes(0), oram.write(9, &a64_bytes(8)));
388            assert_eq!(a64_bytes(5), oram.write(2, &a64_bytes(10)));
389            assert_eq!(a64_bytes(7), oram.write(0, &a64_bytes(11)));
390            assert_eq!(a64_bytes(8), oram.write(9, &a64_bytes(12)));
391            assert_eq!(a64_bytes(12), oram.read(9));
392        })
393    }
394
395    // Sanity check the standard z4 path oram
396    #[test]
397    fn sanity_check_path_oram_z4_262144() {
398        run_with_several_seeds(|rng| {
399            let mut oram = PathORAM4096Z4Creator::<RngType, HeapORAMStorageCreator>::create(
400                262144,
401                STASH_SIZE,
402                &mut rng_maker(rng),
403            );
404            assert_eq!(a64_bytes(0), oram.write(0, &a64_bytes(1)));
405            assert_eq!(a64_bytes(1), oram.write(0, &a64_bytes(2)));
406            assert_eq!(a64_bytes(2), oram.write(0, &a64_bytes(3)));
407            assert_eq!(a64_bytes(0), oram.write(2, &a64_bytes(4)));
408            assert_eq!(a64_bytes(4), oram.write(2, &a64_bytes(5)));
409            assert_eq!(a64_bytes(3), oram.write(0, &a64_bytes(6)));
410            assert_eq!(a64_bytes(6), oram.write(0, &a64_bytes(7)));
411            assert_eq!(a64_bytes(0), oram.write(9, &a64_bytes(8)));
412            assert_eq!(a64_bytes(5), oram.write(2, &a64_bytes(10)));
413            assert_eq!(a64_bytes(7), oram.write(0, &a64_bytes(11)));
414            assert_eq!(a64_bytes(8), oram.write(9, &a64_bytes(12)));
415            assert_eq!(a64_bytes(12), oram.read(9));
416        })
417    }
418
419    // Run the exercise ORAM tests for 20,000 rounds in 8192 sized z4 ORAM
420    #[test]
421    fn exercise_path_oram_z4_8192() {
422        run_with_several_seeds(|rng| {
423            let mut maker = rng_maker(rng);
424            let mut rng = maker();
425            let mut oram = PathORAM4096Z4Creator::<RngType, HeapORAMStorageCreator>::create(
426                8192, STASH_SIZE, &mut maker,
427            );
428            testing::exercise_oram(20_000, &mut oram, &mut rng);
429        });
430    }
431
432    // Run the exercise ORAM consecutive tests for 20,000 rounds in 8192 sized z4
433    // ORAM
434    #[test]
435    fn exercise_consecutive_path_oram_z4_8192() {
436        run_with_several_seeds(|rng| {
437            let mut maker = rng_maker(rng);
438            let mut rng = maker();
439            let mut oram = PathORAM4096Z4Creator::<RngType, HeapORAMStorageCreator>::create(
440                8192, STASH_SIZE, &mut maker,
441            );
442            testing::exercise_oram_consecutive(20_000, &mut oram, &mut rng);
443        });
444    }
445
446    // Sanity check the z4 Circuit ORAM
447    #[test]
448    fn sanity_check_circuit_oram_z4_262144() {
449        run_with_several_seeds(|rng| {
450            let mut oram = CircuitORAM4096Z4Creator::<RngType, HeapORAMStorageCreator>::create(
451                262144,
452                STASH_SIZE,
453                &mut rng_maker(rng),
454            );
455            assert_eq!(a64_bytes(0), oram.write(0, &a64_bytes(1)));
456            assert_eq!(a64_bytes(1), oram.write(0, &a64_bytes(2)));
457            assert_eq!(a64_bytes(2), oram.write(0, &a64_bytes(3)));
458            assert_eq!(a64_bytes(0), oram.write(2, &a64_bytes(4)));
459            assert_eq!(a64_bytes(4), oram.write(2, &a64_bytes(5)));
460            assert_eq!(a64_bytes(3), oram.write(0, &a64_bytes(6)));
461            assert_eq!(a64_bytes(6), oram.write(0, &a64_bytes(7)));
462            assert_eq!(a64_bytes(0), oram.write(9, &a64_bytes(8)));
463            assert_eq!(a64_bytes(5), oram.write(2, &a64_bytes(10)));
464            assert_eq!(a64_bytes(7), oram.write(0, &a64_bytes(11)));
465            assert_eq!(a64_bytes(8), oram.write(9, &a64_bytes(12)));
466            assert_eq!(a64_bytes(12), oram.read(9));
467        })
468    }
469
470    // Run the exercise ORAM tests for 20,000 rounds in 8192 sized z4 Circuit
471    // ORAM
472    #[test]
473    fn exercise_circuit_oram_z4_8192() {
474        run_with_several_seeds(|rng| {
475            let mut maker = rng_maker(rng);
476            let mut rng = maker();
477            let mut oram = CircuitORAM4096Z4Creator::<RngType, HeapORAMStorageCreator>::create(
478                8192, STASH_SIZE, &mut maker,
479            );
480            testing::exercise_oram(20_000, &mut oram, &mut rng);
481        });
482    }
483
484    // Run the exercise ORAM tests for 20,000 rounds in 8192 sized z4 Circuit
485    // ORAM
486    #[test]
487    fn exercise_consecutive_circuit_oram_z4_8192() {
488        run_with_several_seeds(|rng| {
489            let mut maker = rng_maker(rng);
490            let mut rng = maker();
491            let mut oram = CircuitORAM4096Z4Creator::<RngType, HeapORAMStorageCreator>::create(
492                8192, STASH_SIZE, &mut maker,
493            );
494            testing::exercise_oram_consecutive(20_000, &mut oram, &mut rng);
495        });
496    }
497
498    // Sanity check the z4 Circuit ORAM
499    #[test]
500    fn sanity_check_circuit_oram_z2_262144() {
501        run_with_several_seeds(|rng| {
502            let mut oram = CircuitORAM4096Z2Creator::<RngType, HeapORAMStorageCreator>::create(
503                262144,
504                STASH_SIZE,
505                &mut rng_maker(rng),
506            );
507            assert_eq!(a64_bytes(0), oram.write(0, &a64_bytes(1)));
508            assert_eq!(a64_bytes(1), oram.write(0, &a64_bytes(2)));
509            assert_eq!(a64_bytes(2), oram.write(0, &a64_bytes(3)));
510            assert_eq!(a64_bytes(0), oram.write(2, &a64_bytes(4)));
511            assert_eq!(a64_bytes(4), oram.write(2, &a64_bytes(5)));
512            assert_eq!(a64_bytes(3), oram.write(0, &a64_bytes(6)));
513            assert_eq!(a64_bytes(6), oram.write(0, &a64_bytes(7)));
514            assert_eq!(a64_bytes(0), oram.write(9, &a64_bytes(8)));
515            assert_eq!(a64_bytes(5), oram.write(2, &a64_bytes(10)));
516            assert_eq!(a64_bytes(7), oram.write(0, &a64_bytes(11)));
517            assert_eq!(a64_bytes(8), oram.write(9, &a64_bytes(12)));
518            assert_eq!(a64_bytes(12), oram.read(9));
519        })
520    }
521
522    // Run the exercise ORAM tests for 20,000 rounds in 8192 sized z4 Circuit
523    // ORAM
524    #[test]
525    fn exercise_circuit_oram_z2_8192() {
526        run_with_several_seeds(|rng| {
527            let mut maker = rng_maker(rng);
528            let mut rng = maker();
529            let mut oram = CircuitORAM4096Z2Creator::<RngType, HeapORAMStorageCreator>::create(
530                8192, STASH_SIZE, &mut maker,
531            );
532            testing::exercise_oram(20_000, &mut oram, &mut rng);
533        });
534    }
535
536    // Run the exercise ORAM tests for 20,000 rounds in 8192 sized z4 Circuit
537    // ORAM
538    #[test]
539    fn exercise_consecutive_circuit_oram_z2_8192() {
540        run_with_several_seeds(|rng| {
541            let mut maker = rng_maker(rng);
542            let mut rng = maker();
543            let mut oram = CircuitORAM4096Z2Creator::<RngType, HeapORAMStorageCreator>::create(
544                8192, STASH_SIZE, &mut maker,
545            );
546            testing::exercise_oram_consecutive(20_000, &mut oram, &mut rng);
547        });
548    }
549
550    // Run the exercise ORAM tests for 50,000 rounds in 32768 sized z4 ORAM
551    #[test]
552    #[cfg(not(debug_assertions))]
553    fn exercise_path_oram_z4_32768() {
554        run_with_several_seeds(|rng| {
555            let mut maker = rng_maker(rng);
556            let mut rng = maker();
557            let mut oram = PathORAM4096Z4Creator::<RngType, HeapORAMStorageCreator>::create(
558                32768, STASH_SIZE, &mut maker,
559            );
560            testing::exercise_oram(50_000, &mut oram, &mut rng);
561        });
562    }
563
564    // Run the exercise ORAM tests for 60,000 rounds in 131072 sized z4 ORAM
565    #[test]
566    #[cfg(not(debug_assertions))]
567    fn exercise_path_oram_z4_131072() {
568        run_with_several_seeds(|rng| {
569            let mut maker = rng_maker(rng);
570            let mut rng = maker();
571            let mut oram = PathORAM4096Z4Creator::<RngType, HeapORAMStorageCreator>::create(
572                131072, STASH_SIZE, &mut maker,
573            );
574            testing::exercise_oram(60_000, &mut oram, &mut rng);
575        });
576    }
577
578    // Run the exercise ORAM consecutive tests for 100,000 rounds in 1024 sized z4
579    // ORAM
580    #[test]
581    #[cfg(not(debug_assertions))]
582    fn exercise_consecutive_path_oram_z4_1024() {
583        run_with_several_seeds(|rng| {
584            let mut maker = rng_maker(rng);
585            let mut rng = maker();
586            let mut oram = PathORAM4096Z4Creator::<RngType, HeapORAMStorageCreator>::create(
587                1024, STASH_SIZE, &mut maker,
588            );
589            testing::exercise_oram_consecutive(100_000, &mut oram, &mut rng);
590        });
591    }
592}