#!/bin/bash

# Reproduce the 3-party Circuit ORAM experiments from our paper:

# Adithya Vadapalli, Ryan Henry, Ian Goldberg. Duoram: A
# Bandwidth-Efficient Distributed ORAM for 2- and 3-Party Computation.
# USENIX Security Symposium 2023.

# cd into the directory containing this script (from the bash faq 028)
if [[ $BASH_SOURCE = */* ]]; then
  cd -- "${BASH_SOURCE%/*}/" || exit
fi

# If the master NUMA commands are set, use them for Circuit ORAM
if [ "$NUMA_P0" != "" ]; then
    export ORAM_NUMA_C="$NUMA_P0"
fi
if [ "$NUMA_P1" != "" ]; then
    export ORAM_NUMA_D="$NUMA_P1"
fi
if [ "$NUMA_P2" != "" ]; then
    export ORAM_NUMA_E="$NUMA_P2"
fi

# Allow running only subsets of the experiment suite.  Valid values are
# "test", "small", "large", "all", "none".  ("none" is useful if you
# just want to re-parse the output of existing logs.)  You can also say
# "single" followed by all the arguments to "run" (below) to run a
# single experiment; for example:
# ./repro single 20 1us 100gbit 128
if [ "$1" == "" ]; then
    whichexps="test"
else
    whichexps="$1"
fi

# The number of operations per run; the graphs in the paper use 128
if [ "$whichexps" == "single" -o "$2" == "" ]; then
    # If there's an explicit experiment on the command line, don't read
    # the next argument as the number of operations.  $numops will be
    # ignored, anyway, since it will be specified as part of the
    # command.
    numops=128
else
    numops="$2"
fi

# Run one experiment
# Arguments:
# $1: depth (the ORAM has 2^depth elements)
# $2: latency (e.g., 30ms)
# $3: bandwidth (e.g., 100mbit)
# $4: number of operations (e.g., 128)
run() {
    now=`date`
    echo "$now: Running $1 $2 $3 $4 ..."
    logfile="read_${2}_${3}_${4}.out${LOGSUFFIX}"
    ./set-networking $2 $3
    echo "Network setup: $2 $3" >> $logfile
    ./run-experiment $1 $4 >> $logfile
}

# Parse the output logs.  We run this in the docker in case you don't
# have perl installed on the host.
# Arguments: a list of logfiles
parse() {
    cat $* | docker exec -w /root/oram/docker -i oram_C ./parse_logs
}

# A very small kick-the-tires test to ensure everything compiled and
# built properly
if [ "$whichexps" == "test" ]; then
    echo "Running test experiment..."
    run 16 1us 100gbit 2
    parse read_1us_100gbit_2.out${LOGSUFFIX}
    exit
fi

# Be able to run a single experiment specified on the command line
if [ "$whichexps" == "single" ]; then
    echo "Running single experiment..."
    shift
    run $*
    exit
fi

now=`date`
echo "$now: Starting experiments"

if [ "$whichexps" == "small" -o "$whichexps" == "all" ]; then
    echo "Running small experiments..."
    # Figure 9(a)
    run 16 30ms 100mbit ${numops}
    run 18 30ms 100mbit ${numops}
    run 20 30ms 100mbit ${numops}
    run 22 30ms 100mbit ${numops}
    run 24 30ms 100mbit ${numops}
    run 26 30ms 100mbit ${numops}
    # Figures 9(b) and 9(c)
    # Note that we set the latency to 1us, which really means "don't add
    # artificial latency", but we measure the one-way latency to
    # actually be 30us, which is what we report in the paper. (pings
    # from one docker to the other take about 60us round trip.)
    run 16 1us 100gbit ${numops}
    run 18 1us 100gbit ${numops}
    run 20 1us 100gbit ${numops}
    run 22 1us 100gbit ${numops}
    run 24 1us 100gbit ${numops}
    run 26 1us 100gbit ${numops}
fi
if [ "$whichexps" == "large" -o "$whichexps" == "all" ]; then
    echo "Running large experiments..."
    # Figure 9(a)
    run 28 30ms 100mbit ${numops}
    run 30 30ms 100mbit ${numops}
    run 32 30ms 100mbit ${numops}
    # Figures 9(b) and 9(c)
    run 28 1us 100gbit ${numops}
    run 30 1us 100gbit ${numops}
    run 32 1us 100gbit ${numops}
fi

now=`date`
echo "$now: Experiments complete"

# If you specified a custom log suffix, you're going to be parsing the
# outputs differently.
if [ "$LOGSUFFIX" == "" ]; then

parse *_${numops}.out > oram_${numops}.dat

echo
echo "# Figure 9(a)"
egrep 'CircuitORAMOnln read .* 30ms 100mbit .* s$' oram_${numops}.dat | sort -k3 -n
echo
egrep 'CircuitORAMTotl read .* 30ms 100mbit .* s$' oram_${numops}.dat | sort -k3 -n
echo
echo "# Figure 9(b)"
egrep 'CircuitORAMOnln read .* 1us 100gbit .* s$' oram_${numops}.dat | sort -k3 -n
echo
egrep 'CircuitORAMTotl read .* 1us 100gbit .* s$' oram_${numops}.dat | sort -k3 -n
echo
echo "# Figure 9(c)"
egrep 'CircuitORAMOnln read .* 1us 100gbit .* KiB$' oram_${numops}.dat | sort -k3 -n
echo
egrep 'CircuitORAMTotl read .* 1us 100gbit .* KiB$' oram_${numops}.dat | sort -k3 -n

fi