|
@@ -1,479 +1,328 @@
|
|
|
#include <functional>
|
|
|
|
|
|
-#include "bst.hpp"
|
|
|
+#include "types.hpp"
|
|
|
+#include "duoram.hpp"
|
|
|
+#include "node.hpp"
|
|
|
|
|
|
|
|
|
|
|
|
-
|
|
|
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-std::tuple<RegBS, RegBS> compare_keys(MPCTIO tio, yield_t &yield, Node n1, Node n2) {
|
|
|
- CDPF cdpf = tio.cdpf(yield);
|
|
|
- auto [lt, eq, gt] = cdpf.compare(tio, yield, n2.key - n1.key, tio.aes_ops());
|
|
|
- RegBS lteq = lt^eq;
|
|
|
- return {lteq, gt};
|
|
|
-}
|
|
|
+struct Node {
|
|
|
+ RegAS key;
|
|
|
+ RegXS pointers;
|
|
|
+ RegXS value;
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
+
|
|
|
|
|
|
-inline RegXS extractLeftPtr(RegXS pointer){
|
|
|
- return ((pointer&(0xFFFFFFFF00000000))>>32);
|
|
|
-}
|
|
|
+#define NODE_KEY field(&Node::key)
|
|
|
+#define NODE_POINTERS field(&Node::pointers)
|
|
|
+#define NODE_VALUE field(&Node::value)
|
|
|
|
|
|
-inline RegXS extractRightPtr(RegXS pointer){
|
|
|
- return (pointer&(0x00000000FFFFFFFF));
|
|
|
-}
|
|
|
+
|
|
|
+ void dump() const {
|
|
|
+ printf("[%016lx %016lx %016lx]", key.share(), pointers.share(),
|
|
|
+ value.share());
|
|
|
+ }
|
|
|
|
|
|
-inline void setLeftPtr(RegXS &pointer, RegXS new_ptr){
|
|
|
- pointer&=(0x00000000FFFFFFFF);
|
|
|
- pointer+=(new_ptr<<32);
|
|
|
-}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
|
|
|
-inline void setRightPtr(RegXS &pointer, RegXS new_ptr){
|
|
|
- pointer&=(0xFFFFFFFF00000000);
|
|
|
- pointer+=(new_ptr);
|
|
|
-}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-void BST::pretty_print(const std::vector<Node> &R, value_t node,
|
|
|
- const std::string &prefix = "", bool is_left_child = false,
|
|
|
- bool is_right_child = false)
|
|
|
-{
|
|
|
- if (node == 0) {
|
|
|
-
|
|
|
- if (is_left_child) {
|
|
|
- printf("%s\xE2\x95\xA7\n", prefix.c_str());
|
|
|
- } else if (is_right_child) {
|
|
|
- printf("%s\xE2\x95\xA4\n", prefix.c_str());
|
|
|
- } else {
|
|
|
- printf("%s\xE2\x95\xA2\n", prefix.c_str());
|
|
|
- }
|
|
|
- return;
|
|
|
+ inline void zeronode() {
|
|
|
+ key.set(0);
|
|
|
+ pointers.set(0);
|
|
|
+ value.set(0);
|
|
|
}
|
|
|
- const Node &n = R[node];
|
|
|
- value_t left_ptr = extractLeftPtr(n.pointers).xshare;
|
|
|
- value_t right_ptr = extractRightPtr(n.pointers).xshare;
|
|
|
- std::string rightprefix(prefix), leftprefix(prefix),
|
|
|
- nodeprefix(prefix);
|
|
|
- if (is_left_child) {
|
|
|
- rightprefix.append("\xE2\x94\x82");
|
|
|
- leftprefix.append(" ");
|
|
|
- nodeprefix.append("\xE2\x94\x94");
|
|
|
- } else if (is_right_child) {
|
|
|
- rightprefix.append(" ");
|
|
|
- leftprefix.append("\xE2\x94\x82");
|
|
|
- nodeprefix.append("\xE2\x94\x8C");
|
|
|
- } else {
|
|
|
- rightprefix.append(" ");
|
|
|
- leftprefix.append(" ");
|
|
|
- nodeprefix.append("\xE2\x94\x80");
|
|
|
- }
|
|
|
- pretty_print(R, right_ptr, rightprefix, false, true);
|
|
|
- printf("%s\xE2\x94\xA4", nodeprefix.c_str());
|
|
|
- n.dump();
|
|
|
- printf("\n");
|
|
|
- pretty_print(R, left_ptr, leftprefix, true, false);
|
|
|
-}
|
|
|
|
|
|
-bool reconstruct_flag(MPCTIO &tio, yield_t &yield, RegBS flag) {
|
|
|
- RegBS peer_flag;
|
|
|
- RegBS reconstructed_flag;
|
|
|
- if (tio.player() == 1) {
|
|
|
- tio.queue_peer(&flag, sizeof(flag));
|
|
|
- } else {
|
|
|
- RegBS peer_flag;
|
|
|
- tio.recv_peer(&peer_flag, sizeof(peer_flag));
|
|
|
- reconstructed_flag ^= peer_flag;
|
|
|
+ inline void newnode() {
|
|
|
+ key.randomize(8);
|
|
|
+ pointers.set(0);
|
|
|
+ value.randomize();
|
|
|
}
|
|
|
|
|
|
- if (tio.player() == 0) {
|
|
|
- tio.queue_peer(&flag, sizeof(flag));
|
|
|
- } else {
|
|
|
- RegBS peer_flag;
|
|
|
- tio.recv_peer(&peer_flag, sizeof(peer_flag));
|
|
|
- reconstructed_flag ^= peer_flag;
|
|
|
+ inline void randomize() {
|
|
|
+ key.randomize();
|
|
|
+ pointers.randomize();
|
|
|
+ value.randomize();
|
|
|
}
|
|
|
-
|
|
|
- return reconstructed_flag.bshare;
|
|
|
-}
|
|
|
|
|
|
-void BST::pretty_print(MPCTIO &tio, yield_t &yield) {
|
|
|
- RegXS peer_root;
|
|
|
- RegXS reconstructed_root = root;
|
|
|
- if (tio.player() == 1) {
|
|
|
- tio.queue_peer(&root, sizeof(root));
|
|
|
- } else {
|
|
|
- RegXS peer_root;
|
|
|
- tio.recv_peer(&peer_root, sizeof(peer_root));
|
|
|
- reconstructed_root += peer_root;
|
|
|
+ inline Node &operator+=(const Node &rhs) {
|
|
|
+ this->key += rhs.key;
|
|
|
+ this->pointers += rhs.pointers;
|
|
|
+ this->value += rhs.value;
|
|
|
+ return *this;
|
|
|
}
|
|
|
|
|
|
- auto A = oram->flat(tio, yield);
|
|
|
- auto R = A.reconstruct();
|
|
|
- if(tio.player()==0) {
|
|
|
- pretty_print(R, reconstructed_root.xshare);
|
|
|
+ inline Node operator+(const Node &rhs) const {
|
|
|
+ Node res = *this;
|
|
|
+ res += rhs;
|
|
|
+ return res;
|
|
|
}
|
|
|
-}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-std::tuple<bool, address_t> BST::check_bst(const std::vector<Node> &R,
|
|
|
- value_t node, value_t min_key = 0, value_t max_key = ~0)
|
|
|
-{
|
|
|
- if (node == 0) {
|
|
|
- return { true, 0 };
|
|
|
+ inline Node &operator-=(const Node &rhs) {
|
|
|
+ this->key -= rhs.key;
|
|
|
+ this->pointers -= rhs.pointers;
|
|
|
+ this->value -= rhs.value;
|
|
|
+ return *this;
|
|
|
}
|
|
|
- const Node &n = R[node];
|
|
|
- value_t key = n.key.ashare;
|
|
|
- value_t left_ptr = extractLeftPtr(n.pointers).xshare;
|
|
|
- value_t right_ptr = extractRightPtr(n.pointers).xshare;
|
|
|
- auto [leftok, leftheight ] = check_bst(R, left_ptr, min_key, key);
|
|
|
- auto [rightok, rightheight ] = check_bst(R, right_ptr, key+1, max_key);
|
|
|
- address_t height = leftheight;
|
|
|
- if (rightheight > height) {
|
|
|
- height = rightheight;
|
|
|
+
|
|
|
+ inline Node operator-(const Node &rhs) const {
|
|
|
+ Node res = *this;
|
|
|
+ res -= rhs;
|
|
|
+ return res;
|
|
|
}
|
|
|
- height += 1;
|
|
|
- return { leftok && rightok && key >= min_key && key <= max_key,
|
|
|
- height };
|
|
|
-}
|
|
|
|
|
|
-void BST::check_bst(MPCTIO &tio, yield_t &yield) {
|
|
|
- auto A = oram->flat(tio, yield);
|
|
|
- auto R = A.reconstruct();
|
|
|
+ inline Node operator-() const {
|
|
|
+ Node res;
|
|
|
+ res.key = -this->key;
|
|
|
+ res.pointers = -this->pointers;
|
|
|
+ res.value = -this->value;
|
|
|
+ return res;
|
|
|
+ }
|
|
|
|
|
|
- auto [ ok, height ] = check_bst(R, root.xshare);
|
|
|
- printf("BST structure %s\nBST height = %u\n",
|
|
|
- ok ? "ok" : "NOT OK", height);
|
|
|
-}
|
|
|
+
|
|
|
+
|
|
|
+ inline Node mulshare(const Node &rhs) const {
|
|
|
+ Node res = *this;
|
|
|
+ res.key.mulshareeq(rhs.key);
|
|
|
+ res.pointers.mulshareeq(rhs.pointers);
|
|
|
+ res.value.mulshareeq(rhs.value);
|
|
|
+ return res;
|
|
|
+ }
|
|
|
|
|
|
-void newnode(Node &a) {
|
|
|
- a.key.randomize(8);
|
|
|
- a.pointers.set(0);
|
|
|
- a.value.randomize();
|
|
|
-}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ inline void unit(const RDPF &dpf, DPFnode leaf) {
|
|
|
+ key = dpf.unit_as(leaf);
|
|
|
+ pointers = dpf.unit_bs(leaf);
|
|
|
+ value = dpf.unit_bs(leaf);
|
|
|
+ }
|
|
|
|
|
|
-void BST::initialize(int num_players, size_t size) {
|
|
|
- this->MAX_SIZE = size;
|
|
|
- oram = new Duoram<Node>(num_players, size);
|
|
|
-}
|
|
|
+
|
|
|
+
|
|
|
+ template <typename Sh, typename U>
|
|
|
+ inline static void update(Sh &shape, yield_t ­ield, U idx,
|
|
|
+ const Node &M) {
|
|
|
+ run_coroutines(shyield,
|
|
|
+ [&shape, &idx, &M] (yield_t &yield) {
|
|
|
+ Sh Sh_coro = shape.context(yield);
|
|
|
+ Sh_coro[idx].NODE_KEY += M.key;
|
|
|
+ },
|
|
|
+ [&shape, &idx, &M] (yield_t &yield) {
|
|
|
+ Sh Sh_coro = shape.context(yield);
|
|
|
+ Sh_coro[idx].NODE_POINTERS += M.pointers;
|
|
|
+ },
|
|
|
+ [&shape, &idx, &M] (yield_t &yield) {
|
|
|
+ Sh Sh_coro = shape.context(yield);
|
|
|
+ Sh_coro[idx].NODE_VALUE += M.value;
|
|
|
+ });
|
|
|
+ }
|
|
|
+};
|
|
|
|
|
|
+
|
|
|
|
|
|
-std::tuple<RegXS, RegBS> BST::insert(MPCTIO &tio, yield_t &yield, RegXS ptr,
|
|
|
- const Node &new_node, Duoram<Node>::Flat &A, int TTL, RegBS isDummy) {
|
|
|
- if(TTL==0) {
|
|
|
- RegBS zero;
|
|
|
- return {ptr, zero};
|
|
|
- }
|
|
|
+template <typename T>
|
|
|
+T& operator>>(T& is, Node &x)
|
|
|
+{
|
|
|
+ is >> x.key >> x.pointers >> x.value;
|
|
|
+ return is;
|
|
|
+}
|
|
|
|
|
|
- RegBS isNotDummy = isDummy ^ (tio.player());
|
|
|
- Node cnode = A[ptr];
|
|
|
-
|
|
|
- auto [lteq, gt] = compare_keys(tio, yield, cnode, new_node);
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- RegXS left = extractLeftPtr(cnode.pointers);
|
|
|
- RegXS right = extractRightPtr(cnode.pointers);
|
|
|
-
|
|
|
- RegXS next_ptr;
|
|
|
- mpc_select(tio, yield, next_ptr, gt, left, right, 32);
|
|
|
-
|
|
|
- CDPF dpf = tio.cdpf(yield);
|
|
|
- size_t &aes_ops = tio.aes_ops();
|
|
|
-
|
|
|
- RegBS F_z = dpf.is_zero(tio, yield, next_ptr, aes_ops);
|
|
|
- RegBS F_i;
|
|
|
-
|
|
|
-
|
|
|
- mpc_and(tio, yield, F_i, (isNotDummy), F_z);
|
|
|
-
|
|
|
- isDummy^=F_i;
|
|
|
- auto [wptr, direction] = insert(tio, yield, next_ptr, new_node, A, TTL-1, isDummy);
|
|
|
-
|
|
|
- RegXS ret_ptr;
|
|
|
- RegBS ret_direction;
|
|
|
-
|
|
|
-
|
|
|
- mpc_select(tio, yield, ret_ptr, F_i, wptr, ptr);
|
|
|
-
|
|
|
- mpc_and(tio, yield, ret_direction, F_i, direction^gt);
|
|
|
- ret_direction^=direction;
|
|
|
-
|
|
|
- return {ret_ptr, ret_direction};
|
|
|
+template <typename T>
|
|
|
+T& operator<<(T& os, const Node &x)
|
|
|
+{
|
|
|
+ os << x.key << x.pointers << x.value;
|
|
|
+ return os;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
|
|
|
-
|
|
|
-void BST::insert(MPCTIO &tio, yield_t &yield, const Node &node, Duoram<Node>::Flat &A) {
|
|
|
- bool player0 = tio.player()==0;
|
|
|
-
|
|
|
- if(num_items==0) {
|
|
|
- Node zero;
|
|
|
- A[0] = zero;
|
|
|
- A[1] = node;
|
|
|
- (root).set(1*tio.player());
|
|
|
- num_items++;
|
|
|
-
|
|
|
- return;
|
|
|
- } else {
|
|
|
-
|
|
|
- int new_id = 1 + num_items;
|
|
|
- int TTL = num_items++;
|
|
|
- A[new_id] = node;
|
|
|
- RegXS new_addr;
|
|
|
- new_addr.set(new_id * tio.player());
|
|
|
- RegBS isDummy;
|
|
|
-
|
|
|
-
|
|
|
- auto [wptr, direction] = insert(tio, yield, root, node, A, TTL, isDummy);
|
|
|
-
|
|
|
-
|
|
|
- RegXS pointers = A[wptr].NODE_POINTERS;
|
|
|
- RegXS left_ptr = extractLeftPtr(pointers);
|
|
|
- RegXS right_ptr = extractRightPtr(pointers);
|
|
|
- RegXS new_right_ptr, new_left_ptr;
|
|
|
- mpc_select(tio, yield, new_right_ptr, direction, right_ptr, new_addr);
|
|
|
- if(player0) {
|
|
|
- direction^=1;
|
|
|
- }
|
|
|
- mpc_select(tio, yield, new_left_ptr, direction, left_ptr, new_addr);
|
|
|
- setLeftPtr(pointers, new_left_ptr);
|
|
|
- setRightPtr(pointers, new_right_ptr);
|
|
|
- A[wptr].NODE_POINTERS = pointers;
|
|
|
-
|
|
|
- }
|
|
|
-}
|
|
|
+DEFAULT_TUPLE_IO(Node)
|
|
|
|
|
|
+int num_items = 0;
|
|
|
+RegAS root;
|
|
|
|
|
|
-void BST::insert(MPCTIO &tio, yield_t &yield, Node &node) {
|
|
|
- auto A = oram->flat(tio, yield);
|
|
|
- auto R = A.reconstruct();
|
|
|
+std::tuple<RegBS, RegBS> compare_keys(Node n1, Node n2, MPCTIO tio, yield_t &yield) {
|
|
|
+ CDPF cdpf = tio.cdpf(yield);
|
|
|
+ auto [lt, eq, gt] = cdpf.compare(tio, yield, n2.key - n1.key, tio.aes_ops());
|
|
|
+ RegBS lteq = lt^eq;
|
|
|
+ return {lteq, gt};
|
|
|
+}
|
|
|
|
|
|
- insert(tio, yield, node, A);
|
|
|
-
|
|
|
-
|
|
|
- if (tio.player() == 0) {
|
|
|
- for(size_t i=0;i<R.size();++i) {
|
|
|
- printf("\n%04lx ", i);
|
|
|
- R[i].dump();
|
|
|
- }
|
|
|
- printf("\n");
|
|
|
- }
|
|
|
- pretty_print(R, 1);
|
|
|
- */
|
|
|
+RegBS check_key_zero(Node n1, MPCTIO tio, yield_t &yield) {
|
|
|
+ CDPF cdpf = tio.cdpf(yield);
|
|
|
+ RegAS zero;
|
|
|
+ auto [lt, eq, gt] = cdpf.compare(tio, yield, n1.key - zero, tio.aes_ops());
|
|
|
+ return eq;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-void mpc_or(MPCTIO &tio, yield_t &yield, RegBS &result, RegBS a, RegBS b) {
|
|
|
- int player0 = tio.player();
|
|
|
- if(player0) {
|
|
|
- a^=1;
|
|
|
- b^=1;
|
|
|
- }
|
|
|
-
|
|
|
- mpc_and(tio, yield, result, a, b);
|
|
|
- if(player0)
|
|
|
- result^=1;
|
|
|
+RegBS check_ptr_zero(RegXS ptr, MPCTIO tio, yield_t &yield) {
|
|
|
+ CDPF cdpf = tio.cdpf(yield);
|
|
|
+ RegAS ptr_as;
|
|
|
+ mpc_xs_to_as(tio, yield, ptr_as, ptr);
|
|
|
+ RegAS zero;
|
|
|
+ auto [lt, eq, gt] = cdpf.compare(tio, yield, ptr_as - zero, tio.aes_ops());
|
|
|
+ return eq;
|
|
|
}
|
|
|
-*/
|
|
|
-
|
|
|
-int BST::del(MPCTIO &tio, yield_t &yield, RegXS ptr, RegAS del_key,
|
|
|
- Duoram<Node>::Flat &A, RegBS af, RegBS fs, int TTL,
|
|
|
- del_return &ret_struct) {
|
|
|
-
|
|
|
- if(TTL==0) {
|
|
|
-
|
|
|
- bool af = reconstruct_flag(tio, yield, af);
|
|
|
- printf("Reconstructed flag = %d\n", af);
|
|
|
- return af;
|
|
|
- } else {
|
|
|
- bool player0 = tio.player()==0;
|
|
|
- Node node = A[ptr];
|
|
|
-
|
|
|
-
|
|
|
- CDPF cdpf = tio.cdpf(yield);
|
|
|
- auto [lt, eq, gt] = cdpf.compare(tio, yield, node.key - del_key, tio.aes_ops());
|
|
|
-
|
|
|
-
|
|
|
- RegBS c = gt;
|
|
|
-
|
|
|
- RegBS lf = eq;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- RegXS left = extractLeftPtr(node.pointers);
|
|
|
- RegXS right = extractRightPtr(node.pointers);
|
|
|
-
|
|
|
- CDPF dpf = tio.cdpf(yield);
|
|
|
- size_t &aes_ops = tio.aes_ops();
|
|
|
-
|
|
|
- RegBS l0 = dpf.is_zero(tio, yield, left, aes_ops);
|
|
|
- RegBS r0 = dpf.is_zero(tio, yield, right, aes_ops);
|
|
|
- RegBS F_0, F_1, F_2;
|
|
|
-
|
|
|
- mpc_and(tio, yield, F_0, l0, r0);
|
|
|
-
|
|
|
- F_1 = l0 ^ r0;
|
|
|
-
|
|
|
- F_2 = F_0 ^ F_1;
|
|
|
- if(player0)
|
|
|
- F_2^=1;
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- RegXS next_ptr;
|
|
|
- RegBS c_prime;
|
|
|
-
|
|
|
-
|
|
|
- RegBS F_c11, F_c12, F_c2, F_c3;
|
|
|
-
|
|
|
- mpc_and(tio, yield, F_c11, lf, F_1);
|
|
|
-
|
|
|
- mpc_and(tio, yield, F_c12, fs, F_1);
|
|
|
-
|
|
|
- mpc_select(tio, yield, c_prime, F_c1, c, l0);
|
|
|
- mpc_select(tio, yield, c_prime, F_c2, c, l0);
|
|
|
-
|
|
|
-
|
|
|
- RegBS s1, s0;
|
|
|
- s1.set(tio.player()==1);
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- mpc_and(tio, yield, F_c2, lf, F_2);
|
|
|
- mpc_select(tio, yield, c_prime, F_c2, c, s1);
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- mpc_and(tio, yield, F_c3, fs, F_2);
|
|
|
- mpc_select(tio, yield, c_prime, F_c3, c, s0);
|
|
|
-
|
|
|
-
|
|
|
- mpc_select(tio, yield, next_ptr, c_prime, left, right, 32);
|
|
|
-
|
|
|
- RegBS af_prime, fs_prime;
|
|
|
- mpc_or(tio, yield, af_prime, af, lf);
|
|
|
|
|
|
-
|
|
|
- mpc_or(tio, yield, fs_prime, fs, F_c2);
|
|
|
- int key_found = del(tio, yield, next_ptr, del_key, A, af_prime, fs_prime, TTL-1, ret_struct);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
|
|
|
-
|
|
|
- if(!key_found)
|
|
|
- return 0;
|
|
|
+inline RegXS extractLeftPtr(RegXS pointer){
|
|
|
+ return ((pointer&(0xFFFFFFFF00000000))>>32);
|
|
|
+}
|
|
|
|
|
|
-
|
|
|
+inline RegXS extractRightPtr(RegXS pointer){
|
|
|
+ return (pointer&(0x00000000FFFFFFFF));
|
|
|
+}
|
|
|
|
|
|
-
|
|
|
+inline void setLeftPtr(RegXS &pointer, RegXS new_ptr){
|
|
|
+ pointer&=(0x00000000FFFFFFFF);
|
|
|
+ pointer+=(new_ptr<<32);
|
|
|
+}
|
|
|
|
|
|
- }
|
|
|
+inline void setRightPtr(RegXS &pointer, RegXS new_ptr){
|
|
|
+ pointer&=(0xFFFFFFFF00000000);
|
|
|
+ pointer+=(new_ptr);
|
|
|
+}
|
|
|
|
|
|
- return 1;
|
|
|
+std::tuple<RegAS, RegBS> insert(RegAS &ptr, Node &new_node, auto A, int TTL, RegBS isDummy, MPCTIO &tio, yield_t &yield) {
|
|
|
+ if(TTL==0) {
|
|
|
+ RegBS zero;
|
|
|
+ return {ptr, zero};
|
|
|
+ }
|
|
|
+
|
|
|
+ Node cnode = A[ptr];
|
|
|
+
|
|
|
+ auto [lteq, gt] = compare_keys(cnode, new_node, tio, yield);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ RegXS left = extractLeftPtr(cnode.pointers);
|
|
|
+ RegXS right = extractRightPtr(cnode.pointers);
|
|
|
+
|
|
|
+ RegXS next_ptr;
|
|
|
+ mpc_select(tio, yield, next_ptr, gt, left, right, 32);
|
|
|
+
|
|
|
+ RegBS F_z = check_ptr_zero(next_ptr, tio, yield);
|
|
|
+ RegBS F_i;
|
|
|
+
|
|
|
+ if(tio.player()==0) {
|
|
|
+ isDummy^=1;
|
|
|
+ }
|
|
|
+ mpc_and(tio, yield, F_i, (isDummy), F_z);
|
|
|
+ if(tio.player()==0) {
|
|
|
+ isDummy^=1;
|
|
|
+ }
|
|
|
+
|
|
|
+ RegAS next_ptr_as;
|
|
|
+ mpc_xs_to_as(tio, yield, next_ptr_as, next_ptr, 32);
|
|
|
+ isDummy^=F_i;
|
|
|
+ auto [wptr, direction] = insert(next_ptr_as, new_node, A, TTL-1, isDummy, tio, yield);
|
|
|
+
|
|
|
+ RegAS ret_ptr;
|
|
|
+ RegBS ret_direction;
|
|
|
+ mpc_select(tio, yield, ret_ptr, F_i, wptr, ptr);
|
|
|
+
|
|
|
+ mpc_and(tio, yield, ret_direction, F_i, direction^gt);
|
|
|
+ ret_direction^=direction;
|
|
|
+
|
|
|
+ return {ret_ptr, ret_direction};
|
|
|
}
|
|
|
|
|
|
|
|
|
-int BST::del(MPCTIO &tio, yield_t &yield, RegAS del_key) {
|
|
|
- if(num_items==0)
|
|
|
- return 0;
|
|
|
- if(num_items==1) {
|
|
|
-
|
|
|
- auto A = oram->flat(tio, yield);
|
|
|
- Node zero;
|
|
|
- A[0] = zero;
|
|
|
- num_items--;
|
|
|
- return 1;
|
|
|
- } else {
|
|
|
- int TTL = num_items;
|
|
|
-
|
|
|
-
|
|
|
- RegBS af;
|
|
|
- RegBS fs;
|
|
|
- del_return ret_struct;
|
|
|
- auto A = oram->flat(tio, yield);
|
|
|
- int success = del(tio, yield, root, del_key, A, af, fs, TTL, ret_struct);
|
|
|
- printf ("Success = %d\n", success);
|
|
|
- return 1;
|
|
|
+
|
|
|
+void insert(RegAS &root, Node &node, auto A, MPCTIO &tio, yield_t &yield) {
|
|
|
+ if(num_items==0) {
|
|
|
+ Node zero;
|
|
|
+ zero.zeronode();
|
|
|
+ A[0] = zero;
|
|
|
+ A[1] = node;
|
|
|
+ (root).set(1*tio.player());
|
|
|
+ num_items++;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+
|
|
|
+ int new_id = 1 + num_items;
|
|
|
+ int TTL = num_items++;
|
|
|
+ A[new_id] = node;
|
|
|
+ RegXS new_addr;
|
|
|
+ new_addr.set(new_id * tio.player());
|
|
|
+ RegBS isDummy;
|
|
|
+ isDummy.set(0);
|
|
|
+
|
|
|
+
|
|
|
+ auto [wptr, direction] = insert(root, node, A, TTL, isDummy, tio, yield);
|
|
|
+
|
|
|
+
|
|
|
+ RegXS pointers = A[wptr].NODE_POINTERS;
|
|
|
+ RegXS left_ptr = extractLeftPtr(pointers);
|
|
|
+ RegXS right_ptr = extractRightPtr(pointers);
|
|
|
+ RegXS new_right_ptr, new_left_ptr;
|
|
|
+ mpc_select(tio, yield, new_right_ptr, direction, right_ptr, new_addr);
|
|
|
+ if(tio.player()==0) {
|
|
|
+ direction^=1;
|
|
|
}
|
|
|
+ mpc_select(tio, yield, new_left_ptr, direction, left_ptr, new_addr);
|
|
|
+ setLeftPtr(pointers, new_left_ptr);
|
|
|
+ setRightPtr(pointers, new_right_ptr);
|
|
|
+ A[wptr].NODE_POINTERS = pointers;
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+
|
|
|
|
|
|
+
|
|
|
void bst(MPCIO &mpcio,
|
|
|
const PRACOptions &opts, char **args)
|
|
|
{
|
|
|
- nbits_t depth=3;
|
|
|
+ nbits_t depth=5;
|
|
|
|
|
|
if (*args) {
|
|
|
depth = atoi(*args);
|
|
|
++args;
|
|
|
}
|
|
|
- size_t items = (size_t(1)<<depth)-1;
|
|
|
- if (*args) {
|
|
|
- items = atoi(*args);
|
|
|
- ++args;
|
|
|
- }
|
|
|
|
|
|
MPCTIO tio(mpcio, 0, opts.num_threads);
|
|
|
- run_coroutines(tio, [&tio, depth, items] (yield_t &yield) {
|
|
|
+ run_coroutines(tio, [&tio, depth] (yield_t &yield) {
|
|
|
size_t size = size_t(1)<<depth;
|
|
|
- BST tree(tio.player(), size);
|
|
|
-
|
|
|
-
|
|
|
- Node node;
|
|
|
- for(size_t i = 1; i<=items; i++) {
|
|
|
- newnode(node);
|
|
|
- node.key.set(i * tio.player());
|
|
|
- tree.insert(tio, yield, node);
|
|
|
+ Duoram<Node> oram(tio.player(), size);
|
|
|
+ auto A = oram.flat(tio, yield);
|
|
|
+
|
|
|
+ Node c;
|
|
|
+ for(int i = 0; i<30; i++) {
|
|
|
+ c.newnode();
|
|
|
+ insert(root, c, A, tio, yield);
|
|
|
}
|
|
|
-
|
|
|
- tree.pretty_print(tio, yield);
|
|
|
- */
|
|
|
|
|
|
- RegAS del_key;
|
|
|
- tree.del(tio, yield, del_key);
|
|
|
|
|
|
-
|
|
|
if (depth < 10) {
|
|
|
-
|
|
|
+ oram.dump();
|
|
|
auto R = A.reconstruct();
|
|
|
-
|
|
|
- if (tio.player() == 1) {
|
|
|
- tio.queue_peer(&root, sizeof(root));
|
|
|
- } else {
|
|
|
- RegXS peer_root;
|
|
|
- tio.recv_peer(&peer_root, sizeof(peer_root));
|
|
|
- root += peer_root;
|
|
|
- }
|
|
|
if (tio.player() == 0) {
|
|
|
for(size_t i=0;i<R.size();++i) {
|
|
|
printf("\n%04lx ", i);
|
|
|
R[i].dump();
|
|
|
}
|
|
|
printf("\n");
|
|
|
- pretty_print(R, root.xshare);
|
|
|
- auto [ ok, height ] = check_bst(R, root.xshare);
|
|
|
- printf("BST structure %s\nBST height = %u\n",
|
|
|
- ok ? "ok" : "NOT OK", height);
|
|
|
}
|
|
|
}
|
|
|
- */
|
|
|
});
|
|
|
}
|