// Copyright (C) 2014 by Xiao Shaun Wang package com.oblivm.backend.oram; import java.util.ArrayList; import java.util.Arrays; import com.oblivm.backend.flexsc.CompEnv; import com.oblivm.backend.flexsc.Party; public class RecursiveCircuitOram { public LinearScanOram baseOram; public ArrayList> clients = new ArrayList<>(); public int lengthOfIden; int recurFactor; int cutoff; int capacity; Party p; public RecursiveCircuitOram(CompEnv env, int N, int dataSize, int cutoff, int recurFactor, int capacity, int sp) { init(env, N, dataSize, cutoff, recurFactor, capacity, sp); } public RecursiveCircuitOram(CompEnv env, int N, int dataSize, int cutoff, int recurFactor) { init(env, N, dataSize, cutoff, recurFactor, 3, 80); } // with default params public RecursiveCircuitOram(CompEnv env, int N, int dataSize) { init(env, N, dataSize, 1 << 6, 8, 3, 80); } public void setInitialValue(int initial) { clients.get(0).setInitialValue(initial); } void init(CompEnv env, int N, int dataSize, int cutoff, int recurFactor, int capacity, int sp) { this.p = env.party; this.cutoff = cutoff; this.recurFactor = recurFactor; this.capacity = capacity; CircuitOram oram = new CircuitOram(env, N, dataSize, capacity, sp); lengthOfIden = oram.lengthOfIden; clients.add(oram); int newDataSize = oram.lengthOfPos * recurFactor, newN = (1 << oram.lengthOfIden) / recurFactor; while (newN > cutoff) { oram = new CircuitOram(env, newN, newDataSize, capacity, sp); clients.add(oram); newDataSize = oram.lengthOfPos * recurFactor; newN = (1 << oram.lengthOfIden) / recurFactor; } CircuitOram last = clients.get(clients.size() - 1); baseOram = new LinearScanOram(env, (1 << last.lengthOfIden), last.lengthOfPos); } public T[] read(T[] iden) { T[][] poses = travelToDeep(iden, 1); CircuitOram currentOram = clients.get(0); boolean[] oldPos = baseOram.lib.declassifyToBoth(poses[0]); T[] res = currentOram.read(iden, oldPos, poses[1]); return res; } public void write(T[] iden, T[] data) { T[][] poses = travelToDeep(iden, 1); CircuitOram currentOram = clients.get(0); boolean[] oldPos = baseOram.lib.declassifyToBoth(poses[0]); currentOram.write(iden, oldPos, poses[1], data); } public void write(T[] iden, T[] data, T dummy) { T[][] poses = travelToDeep(iden, 1); CircuitOram currentOram = clients.get(0); currentOram.write(iden, poses[0], poses[1], data, dummy); } public T[] access(T[] iden, T[] data, T op) { T[][] poses = travelToDeep(iden, 1); CircuitOram currentOram = clients.get(0); boolean[] oldPos = baseOram.lib.declassifyToBoth(poses[0]); return currentOram.access(iden, oldPos, poses[1], data, op); } public T[][] travelToDeep(T[] iden, int level) { if (level == clients.size()) { T[] baseMap = baseOram.readAndRemove(baseOram.lib.padSignal(iden, baseOram.lengthOfIden)); T[] ithPos = baseOram.lib.rightPublicShift(iden, baseOram.lengthOfIden);// iden>>baseOram.lengthOfIden; T[] pos = extract(baseMap, ithPos, clients.get(level - 1).lengthOfPos); T[] newPos = baseOram.lib.randBools(clients.get(level - 1).lengthOfPos); put(baseMap, ithPos, newPos); baseOram.putBack(baseOram.lib.padSignal(iden, baseOram.lengthOfIden), baseMap); T[][] result = baseOram.env.newTArray(2, 0); result[0] = pos; result[1] = newPos; return result; } else { CircuitOram currentOram = clients.get(level); T[][] poses = travelToDeep(subIdentifier(iden, currentOram), level + 1); boolean[] oldPos = baseOram.lib.declassifyToBoth(poses[0]); T[] data = currentOram.readAndRemove(subIdentifier(iden, currentOram), oldPos, true); T[] ithPos = currentOram.lib.rightPublicShift(iden, currentOram.lengthOfIden);// iden>>currentOram.lengthOfIden;//iden/(1< o) { // int a = iden & ((1<