// Copyright (C) 2014 by Xiao Shaun Wang package com.oblivm.backend.oram; import com.oblivm.backend.circuits.BitonicSortLib; import com.oblivm.backend.flexsc.CompEnv; public class BucketLib extends BitonicSortLib { public Block dummyBlock; protected int lengthOfIden; protected int lengthOfPos; protected int lengthOfData; public BucketLib(int lengthOfIden, int lengthOfPos, int lengthOfData, CompEnv e) { super(e); this.lengthOfData = lengthOfData; this.lengthOfIden = lengthOfIden; this.lengthOfPos = lengthOfPos; dummyBlock = new Block(zeros(lengthOfIden), zeros(lengthOfPos), zeros(lengthOfData), SIGNAL_ONE); } public T isFull(Block[] bucket) { T res = SIGNAL_ONE; for (int i = 0; i < bucket.length; ++i) { res = and(res, not(bucket[i].isDummy)); } return res; } public T isEmpty(Block[] bucket) { T res = SIGNAL_ONE; for (int i = 0; i < bucket.length; ++i) { res = and(res, bucket[i].isDummy); } return res; } public Block conditionalReadAndRemove(Block[] bucket, T[] iden, T condition) { Block result = dummyBlock; for (int i = 0; i < bucket.length; ++i) { T match = eq(iden, bucket[i].iden); match = and(match, not(bucket[i].isDummy)); match = and(match, condition); result = mux(result, bucket[i], match); bucket[i].isDummy = mux(bucket[i].isDummy, SIGNAL_ONE, match); } return result; } public Block readAndRemove(Block[] bucket, T[] iden) { Block result = dummyBlock; for (int i = 0; i < bucket.length; ++i) { T match = eq(iden, bucket[i].iden); match = and(match, not(bucket[i].isDummy)); result = mux(result, bucket[i], match); bucket[i].isDummy = mux(bucket[i].isDummy, SIGNAL_ONE, match); } return result; } public Block conditionalReadAndRemove(Block[][] blocks, T[] iden, T condition) { Block[] res = newBlockArray(blocks.length); for (int i = 0; i < blocks.length; ++i) res[i] = conditionalReadAndRemove(blocks[i], iden, condition); return conditionalReadAndRemove(res, iden, condition); } public Block readAndRemove(Block[][] blocks, T[] iden) { Block[] res = newBlockArray(blocks.length); for (int i = 0; i < blocks.length; ++i) res[i] = readAndRemove(blocks[i], iden); return readAndRemove(res, iden); } public void conditionalAdd(Block[] bucket, Block newBlock, T condition) { T added = not(condition); for (int i = 0; i < bucket.length; ++i) { T match = and(not(bucket[i].isDummy), eq(newBlock.iden, bucket[i].iden)); added = or(match, added); } for (int i = 0; i < bucket.length; ++i) { T match = bucket[i].isDummy; T shouldAdd = and(not(added), match); added = or(added, shouldAdd); bucket[i] = mux(bucket[i], newBlock, shouldAdd); } } public void add(Block[] bucket, Block newBlock) { T added = SIGNAL_ZERO; for (int i = 0; i < bucket.length; ++i) { T match = and(not(bucket[i].isDummy), eq(newBlock.iden, bucket[i].iden)); added = or(match, added); } for (int i = 0; i < bucket.length; ++i) { T match = bucket[i].isDummy; T shouldAdd = and(not(added), match); added = or(added, shouldAdd); bucket[i] = mux(bucket[i], newBlock, shouldAdd); } } public Block pop(Block[] bucket) { Block result = dummyBlock; T poped = SIGNAL_ZERO;// condition=T => shouldpop => set to poped; for (int i = 0; i < bucket.length; ++i) { T notDummy = not(bucket[i].isDummy); T shouldPop = and(not(poped), notDummy); poped = or(poped, shouldPop); result = mux(result, bucket[i], shouldPop); bucket[i].isDummy = mux(bucket[i].isDummy, SIGNAL_ONE, shouldPop); } return result; } public Block conditionalPop(Block[] bucket, T condition) { Block result = dummyBlock; T poped = not(condition);// condition=T => shouldpop => set to poped; for (int i = 0; i < bucket.length; ++i) { T notDummy = not(bucket[i].isDummy); T shouldPop = and(not(poped), notDummy); poped = or(poped, shouldPop); result = mux(result, bucket[i], shouldPop); bucket[i].isDummy = mux(bucket[i].isDummy, SIGNAL_ONE, shouldPop); } return result; } public Block mux(Block a, Block b, T choose) { T[] iden = mux(a.iden, b.iden, choose); T[] pos = mux(a.pos, b.pos, choose); T[] data = mux(a.data, b.data, choose); T isDummy = mux(a.isDummy, b.isDummy, choose); return new Block(iden, pos, data, isDummy); } public Block xor(Block a, Block b) { T[] iden = xor(a.iden, b.iden); T[] pos = xor(a.pos, b.pos); T[] data = xor(a.data, b.data); T isDummy = xor(a.isDummy, b.isDummy); return new Block(iden, pos, data, isDummy); } public Block[] xor(Block[] a, Block[] b) { assert (a.length == b.length) : "xor Blocks error"; Block[] result = newBlockArray(b.length); for (int i = 0; i < a.length; ++i) result[i] = xor(a[i], b[i]); return result; } public Block[][] xor(Block[][] a, Block[][] b) { assert (a.length == b.length) : "xor Blocks error"; Block[][] result = newBlockMatrix(a.length); for (int i = 0; i < a.length; ++i) { result[i] = newBlockArray(a[i].length); for (int j = 0; j < a[i].length; ++j) result[i][j] = xor(a[i][j], b[i][j]); } return result; } public Block copy(Block b) { return new Block(b.iden, b.pos, b.data, b.isDummy); } @SuppressWarnings("unchecked") public Block[] newBlockArray(int len) { return new Block[len]; } @SuppressWarnings("unchecked") public Block[][] newBlockMatrix(int x, int y) { return new Block[x][y]; } @SuppressWarnings("unchecked") public Block[][] newBlockMatrix(int x) { return new Block[x][]; } }