// Copyright (C) 2010 by Yan Huang package YaoGC; import java.math.*; import java.io.*; import sprout.communication.Communication; import sprout.util.Timing; abstract public class Circuit implements TransitiveObserver { public static boolean isForGarbling; public Wire[] inputWires; public Wire[] outputWires; protected int inDegree, outDegree; protected String name; public static ObjectOutputStream oos = null; public static ObjectInputStream ois = null; public static Communication sender = null; public static Communication receiver = null; public static Timing timing = null; // public boolean sendOutBitsLookup = false; public static void setSender(Communication s) { sender = s; } public static void setReceiver(Communication r) { receiver = r; } private int inputWireCount = 0; public Circuit(int inDegree, int outDegree, String name) { this.inDegree = inDegree; this.outDegree = outDegree; this.name = name; inputWires = new Wire[inDegree]; outputWires = new Wire[outDegree]; } public static void setIOStream(ObjectInputStream ois, ObjectOutputStream oos) { Circuit.ois = ois; Circuit.oos = oos; } abstract public void build() throws Exception; protected void createInputWires() { for (int i = 0; i < inDegree; i++) { inputWires[i] = new Wire(); } } public void startExecuting(int[] vals, boolean[] invd, BigInteger[] glbs) throws Exception { if (vals.length != invd.length || invd.length != glbs.length || glbs.length != this.inDegree) throw new Exception("Unmatched number of input labels."); for (int i = 0; i < this.inDegree; i++) { inputWires[i].value = vals[i]; inputWires[i].invd = invd[i]; inputWires[i].setLabel(glbs[i]); inputWires[i].setReady(true); } } public void receiveTruthTables() { for (int i = 0; i < this.inDegree; i++) { inputWires[i].setReady(false); } } public void sendTruthTables(State s) { if (s.getWidth() != this.inDegree) { Exception e = new Exception("Unmatched number of input labels." + s.getWidth() + " != " + inDegree); e.printStackTrace(); System.exit(1); } for (int i = 0; i < this.inDegree; i++) { inputWires[i].value = s.wires[i].value; inputWires[i].invd = s.wires[i].invd; inputWires[i].setLabel(s.wires[i].lbl); inputWires[i].setReady(false); } } public State startExecuting(State s) { if (s.getWidth() != this.inDegree) { Exception e = new Exception("Unmatched number of input labels." + s.getWidth() + " != " + inDegree); e.printStackTrace(); System.exit(1); } for (int i = 0; i < this.inDegree; i++) { inputWires[i].value = s.wires[i].value; inputWires[i].invd = s.wires[i].invd; inputWires[i].setLabel(s.wires[i].lbl); inputWires[i].setReady(true); } return State.fromWires(this.outputWires); } public BigInteger interpretOutputELabels(BigInteger[] eLabels) throws Exception { if (eLabels.length != outDegree) throw new Exception("Length Error."); BigInteger output = BigInteger.ZERO; for (int i = 0; i < this.outDegree; i++) { if (outputWires[i].value != Wire.UNKNOWN_SIG) { if (outputWires[i].value == 1) output = output.setBit(i); } else if (eLabels[i] .equals(outputWires[i].invd ? outputWires[i].lbl : outputWires[i].lbl.xor(Wire.R.shiftLeft(1) .setBit(0)))) { output = output.setBit(i); } else if (!eLabels[i] .equals(outputWires[i].invd ? outputWires[i].lbl.xor(Wire.R .shiftLeft(1).setBit(0)) : outputWires[i].lbl)) throw new Exception("Bad Label encountered at ouputWire[" + i + "]:\n" + eLabels[i] + " is neither " + outputWires[i].lbl + " nor " + outputWires[i].lbl.xor(Wire.R.shiftLeft(1).setBit(0))); } return output; } public void update(boolean evaluate, TransitiveObservable o, Object arg) { inputWireCount++; if (inputWireCount % inDegree == 0) execute(evaluate); } abstract protected void compute(); abstract protected void execute(boolean evaluate); // abstract public void sendOutBitsLookup(boolean send); }