|
@@ -254,12 +254,20 @@ inline address_t IfRegXS<RegXS>(address_t val) { return val; }
|
|
|
|
|
|
// Oblivious read from an additively or XOR shared index of Duoram memory
|
|
|
// T is the sharing type of the _values_ in the database; U is the
|
|
|
-// sharing type of the _indices_ in the database.
|
|
|
-template <typename T> template <typename U>
|
|
|
-Duoram<T>::Shape::MemRefS<U>::operator T()
|
|
|
+// sharing type of the _indices_ in the database. If we are referencing
|
|
|
+// an entire entry of type T, then the field type FT will equal T, and
|
|
|
+// the field selector type FST will be nullopt_t. If we are referencing
|
|
|
+// a particular field of T, then FT will be the type of the field (RegAS
|
|
|
+// or RegXS) and FST will be a pointer-to-member T::* type pointing to
|
|
|
+// that field. Sh is the specific Shape subtype used to create the
|
|
|
+// MemRefS.
|
|
|
+
|
|
|
+template <typename T>
|
|
|
+template <typename U,typename FT,typename FST,typename Sh>
|
|
|
+Duoram<T>::Shape::MemRefS<U,FT,FST,Sh>::operator FT()
|
|
|
{
|
|
|
- T res;
|
|
|
- Shape &shape = this->shape;
|
|
|
+ FT res;
|
|
|
+ Sh &shape = this->shape;
|
|
|
shape.explicitonly(false);
|
|
|
int player = shape.tio.player();
|
|
|
if (player < 2) {
|
|
@@ -293,21 +301,21 @@ Duoram<T>::Shape::MemRefS<U>::operator T()
|
|
|
ParallelEval pe(dp, IfRegAS<U>(indshift), IfRegXS<U>(indshift),
|
|
|
shape.shape_size, shape.tio.cpu_nthreads(),
|
|
|
shape.tio.aes_ops());
|
|
|
- T init;
|
|
|
- res = pe.reduce(init, [&dp, &shape] (int thread_num, address_t i,
|
|
|
- const RDPFPair::node &leaf) {
|
|
|
+ FT init;
|
|
|
+ res = pe.reduce(init, [this, &dp, &shape] (int thread_num,
|
|
|
+ address_t i, const RDPFPair::node &leaf) {
|
|
|
// The values from the two DPFs, which will each be of type T
|
|
|
- auto [V0, V1] = dp.unit<T>(leaf);
|
|
|
+ auto [V0, V1] = dp.unit<FT>(leaf);
|
|
|
// References to the appropriate cells in our database, our
|
|
|
// blind, and our copy of the peer's blinded database
|
|
|
- auto [DB, BL, PBD] = shape.get_comp(i);
|
|
|
+ auto [DB, BL, PBD] = shape.get_comp(i, fieldsel);
|
|
|
return (DB + PBD).mulshare(V0) - BL.mulshare(V1-V0);
|
|
|
});
|
|
|
|
|
|
shape.yield();
|
|
|
|
|
|
// Receive the cancellation term from the server
|
|
|
- T gamma;
|
|
|
+ FT gamma;
|
|
|
shape.tio.iostream_server() >> gamma;
|
|
|
res += gamma;
|
|
|
} else {
|
|
@@ -325,23 +333,23 @@ Duoram<T>::Shape::MemRefS<U>::operator T()
|
|
|
auto indshift = combine(p0indoffset, p1indoffset, shape.addr_size);
|
|
|
|
|
|
// Evaluate the DPFs to compute the cancellation terms
|
|
|
- std::tuple<T,T> init, gamma;
|
|
|
+ std::tuple<FT,FT> init, gamma;
|
|
|
ParallelEval pe(dp, IfRegAS<U>(indshift), IfRegXS<U>(indshift),
|
|
|
shape.shape_size, shape.tio.cpu_nthreads(),
|
|
|
shape.tio.aes_ops());
|
|
|
- gamma = pe.reduce(init, [&dp, &shape] (int thread_num, address_t i,
|
|
|
- const RDPFPair::node &leaf) {
|
|
|
- // The values from the two DPFs, each of type T
|
|
|
- auto [V0, V1] = dp.unit<T>(leaf);
|
|
|
+ gamma = pe.reduce(init, [this, &dp, &shape] (int thread_num,
|
|
|
+ address_t i, const RDPFPair::node &leaf) {
|
|
|
+ // The values from the two DPFs, each of type FT
|
|
|
+ auto [V0, V1] = dp.unit<FT>(leaf);
|
|
|
|
|
|
// shape.get_server(i) returns a pair of references to the
|
|
|
// appropriate cells in the two blinded databases
|
|
|
- auto [BL0, BL1] = shape.get_server(i);
|
|
|
+ auto [BL0, BL1] = shape.get_server(i, fieldsel);
|
|
|
return std::make_tuple(-BL0.mulshare(V1), -BL1.mulshare(V0));
|
|
|
});
|
|
|
|
|
|
// Choose a random blinding factor
|
|
|
- T rho;
|
|
|
+ FT rho;
|
|
|
rho.randomize();
|
|
|
|
|
|
std::get<0>(gamma) += rho;
|
|
@@ -357,13 +365,14 @@ Duoram<T>::Shape::MemRefS<U>::operator T()
|
|
|
}
|
|
|
|
|
|
// Oblivious update to a shared index of Duoram memory, only for
|
|
|
-// ST = RegAS or RegXS
|
|
|
-template <typename T> template <typename U> template <typename ST>
|
|
|
-typename Duoram<T>::Shape::template MemRefS<U>
|
|
|
- &Duoram<T>::Shape::MemRefS<U>::oram_update(const ST& M,
|
|
|
+// FT = RegAS or RegXS. The template parameters are as above.
|
|
|
+template <typename T>
|
|
|
+template <typename U, typename FT, typename FST, typename Sh>
|
|
|
+typename Duoram<T>::Shape::template MemRefS<U,FT,FST,Sh>
|
|
|
+ &Duoram<T>::Shape::MemRefS<U,FT,FST,Sh>::oram_update(const FT& M,
|
|
|
const prac_template_true &)
|
|
|
{
|
|
|
- Shape &shape = this->shape;
|
|
|
+ Sh &shape = this->shape;
|
|
|
shape.explicitonly(false);
|
|
|
int player = shape.tio.player();
|
|
|
if (player < 2) {
|
|
@@ -375,7 +384,7 @@ typename Duoram<T>::Shape::template MemRefS<U>
|
|
|
U indoffset = dt.target<U>();
|
|
|
indoffset -= idx;
|
|
|
auto Moffset = std::make_tuple(M, M, M);
|
|
|
- Moffset -= dt.scaled_value<ST>();
|
|
|
+ Moffset -= dt.scaled_value<FT>();
|
|
|
|
|
|
// Send them to the peer, and everything except the first offset
|
|
|
// to the server
|
|
@@ -389,7 +398,7 @@ typename Duoram<T>::Shape::template MemRefS<U>
|
|
|
|
|
|
// Receive the above from the peer
|
|
|
U peerindoffset;
|
|
|
- std::tuple<ST,ST,ST> peerMoffset;
|
|
|
+ std::tuple<FT,FT,FT> peerMoffset;
|
|
|
shape.tio.recv_peer(&peerindoffset, BITBYTES(shape.addr_size));
|
|
|
shape.tio.iostream_peer() >> peerMoffset;
|
|
|
|
|
@@ -402,13 +411,14 @@ typename Duoram<T>::Shape::template MemRefS<U>
|
|
|
shape.shape_size, shape.tio.cpu_nthreads(),
|
|
|
shape.tio.aes_ops());
|
|
|
int init = 0;
|
|
|
- pe.reduce(init, [&dt, &shape, &Mshift, player] (int thread_num,
|
|
|
+ pe.reduce(init, [this, &dt, &shape, &Mshift, player] (int thread_num,
|
|
|
address_t i, const RDPFTriple::node &leaf) {
|
|
|
// The values from the three DPFs
|
|
|
- auto [V0, V1, V2] = dt.scaled<ST>(leaf) + dt.unit<ST>(leaf) * Mshift;
|
|
|
+ auto [V0, V1, V2] =
|
|
|
+ dt.scaled<FT>(leaf) + dt.unit<FT>(leaf) * Mshift;
|
|
|
// References to the appropriate cells in our database, our
|
|
|
// blind, and our copy of the peer's blinded database
|
|
|
- auto [DB, BL, PBD] = shape.get_comp(i);
|
|
|
+ auto [DB, BL, PBD] = shape.get_comp(i,fieldsel);
|
|
|
DB += V0;
|
|
|
if (player == 0) {
|
|
|
BL -= V1;
|
|
@@ -424,7 +434,7 @@ typename Duoram<T>::Shape::template MemRefS<U>
|
|
|
|
|
|
RDPFPair dp = shape.tio.rdpfpair(shape.yield, shape.addr_size);
|
|
|
U p0indoffset, p1indoffset;
|
|
|
- std::tuple<ST,ST> p0Moffset, p1Moffset;
|
|
|
+ std::tuple<FT,FT> p0Moffset, p1Moffset;
|
|
|
|
|
|
shape.yield();
|
|
|
|
|
@@ -442,14 +452,14 @@ typename Duoram<T>::Shape::template MemRefS<U>
|
|
|
shape.shape_size, shape.tio.cpu_nthreads(),
|
|
|
shape.tio.aes_ops());
|
|
|
int init = 0;
|
|
|
- pe.reduce(init, [&dp, &shape, &Mshift] (int thread_num,
|
|
|
+ pe.reduce(init, [this, &dp, &shape, &Mshift] (int thread_num,
|
|
|
address_t i, const RDPFPair::node &leaf) {
|
|
|
// The values from the two DPFs
|
|
|
- auto V = dp.scaled<ST>(leaf) + dp.unit<ST>(leaf) * Mshift;
|
|
|
+ auto V = dp.scaled<FT>(leaf) + dp.unit<FT>(leaf) * Mshift;
|
|
|
// shape.get_server(i) returns a pair of references to the
|
|
|
// appropriate cells in the two blinded databases, so we can
|
|
|
// subtract the pair directly.
|
|
|
- shape.get_server(i) -= V;
|
|
|
+ shape.get_server(i,fieldsel) -= V;
|
|
|
return 0;
|
|
|
});
|
|
|
}
|
|
@@ -457,30 +467,36 @@ typename Duoram<T>::Shape::template MemRefS<U>
|
|
|
}
|
|
|
|
|
|
// Oblivious update to a shared index of Duoram memory, only for
|
|
|
-// ST not RegAS or RegXS
|
|
|
-template <typename T> template <typename U> template <typename ST>
|
|
|
-typename Duoram<T>::Shape::template MemRefS<U>
|
|
|
- &Duoram<T>::Shape::MemRefS<U>::oram_update(const ST& M,
|
|
|
+// FT not RegAS or RegXS. The template parameters are as above.
|
|
|
+template <typename T>
|
|
|
+template <typename U, typename FT, typename FST, typename Sh>
|
|
|
+typename Duoram<T>::Shape::template MemRefS<U,FT,FST,Sh>
|
|
|
+ &Duoram<T>::Shape::MemRefS<U,FT,FST,Sh>::oram_update(const FT& M,
|
|
|
const prac_template_false &)
|
|
|
{
|
|
|
+ T::update(shape, shape.yield, idx, M);
|
|
|
return *this;
|
|
|
}
|
|
|
|
|
|
-// Oblivious update to an additively or XOR shared index of Duoram memory
|
|
|
-template <typename T> template <typename U>
|
|
|
-typename Duoram<T>::Shape::template MemRefS<U>
|
|
|
- &Duoram<T>::Shape::MemRefS<U>::operator+=(const T& M)
|
|
|
+// Oblivious update to an additively or XOR shared index of Duoram
|
|
|
+// memory. The template parameters are as above.
|
|
|
+template <typename T>
|
|
|
+template <typename U, typename FT, typename FST, typename Sh>
|
|
|
+typename Duoram<T>::Shape::template MemRefS<U,FT,FST,Sh>
|
|
|
+ &Duoram<T>::Shape::MemRefS<U,FT,FST,Sh>::operator+=(const FT& M)
|
|
|
{
|
|
|
- return oram_update(M, prac_basic_Reg_S<T>());
|
|
|
+ return oram_update(M, prac_basic_Reg_S<FT>());
|
|
|
}
|
|
|
|
|
|
-// Oblivious write to an additively or XOR shared index of Duoram memory
|
|
|
-template <typename T> template <typename U>
|
|
|
-typename Duoram<T>::Shape::template MemRefS<U>
|
|
|
- &Duoram<T>::Shape::MemRefS<U>::operator=(const T& M)
|
|
|
+// Oblivious write to an additively or XOR shared index of Duoram
|
|
|
+// memory. The template parameters are as above.
|
|
|
+template <typename T>
|
|
|
+template <typename U, typename FT, typename FST, typename Sh>
|
|
|
+typename Duoram<T>::Shape::template MemRefS<U,FT,FST,Sh>
|
|
|
+ &Duoram<T>::Shape::MemRefS<U,FT,FST,Sh>::operator=(const FT& M)
|
|
|
{
|
|
|
- T oldval = *this;
|
|
|
- T update = M - oldval;
|
|
|
+ FT oldval = *this;
|
|
|
+ FT update = M - oldval;
|
|
|
*this += update;
|
|
|
return *this;
|
|
|
}
|
|
@@ -527,22 +543,22 @@ void Duoram<RegAS>::Flat::osort(const U &idx1, const V &idx2, bool dir)
|
|
|
}
|
|
|
|
|
|
// Explicit read from a given index of Duoram memory
|
|
|
-template <typename T>
|
|
|
-Duoram<T>::Shape::MemRefExpl::operator T()
|
|
|
+template <typename T> template <typename FT, typename FST>
|
|
|
+Duoram<T>::Shape::MemRefExpl<FT,FST>::operator FT()
|
|
|
{
|
|
|
Shape &shape = this->shape;
|
|
|
- T res;
|
|
|
+ FT res;
|
|
|
int player = shape.tio.player();
|
|
|
if (player < 2) {
|
|
|
- res = std::get<0>(shape.get_comp(idx));
|
|
|
+ res = std::get<0>(shape.get_comp(idx, fieldsel));
|
|
|
}
|
|
|
return res; // The server will always get 0
|
|
|
}
|
|
|
|
|
|
// Explicit update to a given index of Duoram memory
|
|
|
-template <typename T>
|
|
|
-typename Duoram<T>::Shape::MemRefExpl
|
|
|
- &Duoram<T>::Shape::MemRefExpl::operator+=(const T& M)
|
|
|
+template <typename T> template <typename FT, typename FST>
|
|
|
+typename Duoram<T>::Shape::MemRefExpl<FT,FST>
|
|
|
+ &Duoram<T>::Shape::MemRefExpl<FT,FST>::operator+=(const FT& M)
|
|
|
{
|
|
|
Shape &shape = this->shape;
|
|
|
int player = shape.tio.player();
|
|
@@ -550,7 +566,7 @@ typename Duoram<T>::Shape::MemRefExpl
|
|
|
// blinds and the blinded DB when we leave explicit-only mode.
|
|
|
if (shape.explicitmode) {
|
|
|
if (player < 2) {
|
|
|
- auto [ DB, BL, PBD ] = shape.get_comp(idx);
|
|
|
+ auto [ DB, BL, PBD ] = shape.get_comp(idx, fieldsel);
|
|
|
DB += M;
|
|
|
}
|
|
|
return *this;
|
|
@@ -559,7 +575,7 @@ typename Duoram<T>::Shape::MemRefExpl
|
|
|
// Computational players do this
|
|
|
|
|
|
// Pick a blinding factor
|
|
|
- T blind;
|
|
|
+ FT blind;
|
|
|
blind.randomize();
|
|
|
|
|
|
// Send the blind to the server, and the blinded value to the
|
|
@@ -570,11 +586,11 @@ typename Duoram<T>::Shape::MemRefExpl
|
|
|
shape.yield();
|
|
|
|
|
|
// Receive the peer's blinded value
|
|
|
- T peerblinded;
|
|
|
+ FT peerblinded;
|
|
|
shape.tio.iostream_peer() >> peerblinded;
|
|
|
|
|
|
// Our database, our blind, the peer's blinded database
|
|
|
- auto [ DB, BL, PBD ] = shape.get_comp(idx);
|
|
|
+ auto [ DB, BL, PBD ] = shape.get_comp(idx, fieldsel);
|
|
|
DB += M;
|
|
|
BL += blind;
|
|
|
PBD += peerblinded;
|
|
@@ -584,12 +600,12 @@ typename Duoram<T>::Shape::MemRefExpl
|
|
|
shape.yield();
|
|
|
|
|
|
// Receive the updates to the blinds
|
|
|
- T p0blind, p1blind;
|
|
|
+ FT p0blind, p1blind;
|
|
|
shape.tio.iostream_p0() >> p0blind;
|
|
|
shape.tio.iostream_p1() >> p1blind;
|
|
|
|
|
|
// The two computational parties' blinds
|
|
|
- auto [ BL0, BL1 ] = shape.get_server(idx);
|
|
|
+ auto [ BL0, BL1 ] = shape.get_server(idx, fieldsel);
|
|
|
BL0 += p0blind;
|
|
|
BL1 += p1blind;
|
|
|
}
|
|
@@ -597,12 +613,12 @@ typename Duoram<T>::Shape::MemRefExpl
|
|
|
}
|
|
|
|
|
|
// Explicit write to a given index of Duoram memory
|
|
|
-template <typename T>
|
|
|
-typename Duoram<T>::Shape::MemRefExpl
|
|
|
- &Duoram<T>::Shape::MemRefExpl::operator=(const T& M)
|
|
|
+template <typename T> template <typename FT, typename FST>
|
|
|
+typename Duoram<T>::Shape::MemRefExpl<FT,FST>
|
|
|
+ &Duoram<T>::Shape::MemRefExpl<FT,FST>::operator=(const FT& M)
|
|
|
{
|
|
|
- T oldval = *this;
|
|
|
- T update = M - oldval;
|
|
|
+ FT oldval = *this;
|
|
|
+ FT update = M - oldval;
|
|
|
*this += update;
|
|
|
return *this;
|
|
|
}
|