viff

changeset 1234:82e3597871ae

Replace the current implementation of _get_triple with a call to random triple. Implement the preprocessing interface.
author Janus Dam Nielsen <janus.nielsen@alexandra.dk>
date Wed, 07 Oct 2009 12:02:20 +0200
parents a3d5284eea19
children 3fba16c51e71
files viff/orlandi.py viff/test/test_orlandi_runtime.py
diffstat 2 files changed, 128 insertions(+), 29 deletions(-) [+]
line diff
     1.1 --- a/viff/orlandi.py	Wed Oct 07 12:02:12 2009 +0200
     1.2 +++ b/viff/orlandi.py	Wed Oct 07 12:02:20 2009 +0200
     1.3 @@ -495,8 +495,17 @@
     1.4  
     1.5          field = getattr(share_x, "field", getattr(share_y, "field", None))
     1.6  
     1.7 -        a, b, c = self._get_triple(field)
     1.8 -        return self._basic_multiplication(share_x, share_y, a, b, c)
     1.9 +        def finish_mul((a, b, c)):
    1.10 +            return self._basic_multiplication(share_x, share_y, a, b, c)
    1.11 +
    1.12 +        # This will be the result, a Share object.
    1.13 +        result = Share(self, share_x.field)
    1.14 +        # This is the Deferred we will do processing on.
    1.15 +        triple = self._get_triple(field)
    1.16 +        triple = self.schedule_complex_callback(triple, finish_mul)
    1.17 +        # We add the result to the chains in triple.
    1.18 +        triple.chainDeferred(result)
    1.19 +        return result
    1.20  
    1.21      def _additive_constant(self, zero, field_element):
    1.22          """Greate an additive constant.
    1.23 @@ -588,14 +597,11 @@
    1.24          return c
    1.25  
    1.26      def _get_triple(self, field):
    1.27 -        n = field(0)
    1.28 -        Ca = commitment.commit(6, 0, 0)
    1.29 -        a = OrlandiShare(self, field, field(2), (n, n), Ca)
    1.30 -        Cb = commitment.commit(12, 0, 0)
    1.31 -        b = OrlandiShare(self, field, field(4), (n, n), Cb)
    1.32 -        Cc = commitment.commit(72, 0, 0)
    1.33 -        c = OrlandiShare(self, field, field(24), (n, n), Cc)
    1.34 -        return (a, b, c)
    1.35 +        c, d = self.random_triple(field, 1)
    1.36 +        def f(ls):
    1.37 +            return ls[0]
    1.38 +        d.addCallbacks(f, self.error_handler)
    1.39 +        return d
    1.40  
    1.41      def _basic_multiplication(self, share_x, share_y, triple_a, triple_b, triple_c):
    1.42          """Multiplication of shares give a triple.
    1.43 @@ -1011,7 +1017,7 @@
    1.44  
    1.45          return result
    1.46  
    1.47 -    def random_triple(self, field):
    1.48 +    def random_triple(self, field, number_of_requested_triples):
    1.49          """Generate a list of triples ``(a, b, c)`` where ``c = a * b``.
    1.50  
    1.51          The triple ``(a, b, c)`` is secure in the Fcrs-hybrid model.
    1.52 @@ -1019,15 +1025,16 @@
    1.53          """
    1.54          self.program_counter[-1] += 1
    1.55  
    1.56 -        number_of_multiplications = 1
    1.57          M = []
    1.58 -        
    1.59 -        for x in xrange((1 + self.s_lambda) * (2 * self.d + 1) * number_of_multiplications):
    1.60 +
    1.61 +# print "Generating %i triples... relax, have a brak..." % ((1 + self.s_lambda) * (2 * self.d + 1) * number_of_requested_triples)
    1.62 +
    1.63 +        for x in xrange((1 + self.s_lambda) * (2 * self.d + 1) * number_of_requested_triples):
    1.64              M.append(self.triple_test(field))
    1.65  
    1.66          def step3(ls):
    1.67              """Coin-flip a subset test_set of M of size lambda(2d + 1)M."""
    1.68 -            size = self.s_lambda * (2 * self.d + 1) * number_of_multiplications
    1.69 +            size = self.s_lambda * (2 * self.d + 1) * number_of_requested_triples
    1.70              inx = 0
    1.71              p_half = field.modulus // 2
    1.72              def coin_flip(v, ls, test_set):
    1.73 @@ -1235,18 +1242,18 @@
    1.74              return dls_all
    1.75  
    1.76          def step6(M_without_test_set):
    1.77 -            """Partition M without test_set in number_of_multiplications
    1.78 +            """Partition M without test_set in number_of_requested_triples
    1.79              random subsets M_i of size (2d + 1).
    1.80              """
    1.81              subsets = []
    1.82              size = 2 * self.d + 1
    1.83 -            for x in xrange(number_of_multiplications):
    1.84 +            for x in xrange(number_of_requested_triples):
    1.85                  subsets.append([])
    1.86  
    1.87              def put_in_set(v, M_without_test_set, subsets):
    1.88                  if 0 == len(M_without_test_set):
    1.89                      return subsets
    1.90 -                v = v.value % number_of_multiplications
    1.91 +                v = v.value % number_of_requested_triples
    1.92                  if size > len(subsets[v]):
    1.93                      subsets[v].append(M_without_test_set.pop(0))
    1.94                  r = self.random_share(field)
    1.95 @@ -1295,8 +1302,11 @@
    1.96          # do actual communication
    1.97          self.activate_reactor()
    1.98  
    1.99 -        return result
   1.100 -
   1.101 +        s = Share(self, field)
   1.102 +        def f(ls, s):
   1.103 +            s.callback(ls)
   1.104 +        result.addCallbacks(f, self.error_handler, callbackArgs=(s,))
   1.105 +        return number_of_requested_triples, s
   1.106  
   1.107      def error_handler(self, ex):
   1.108          print "Error: ", ex
     2.1 --- a/viff/test/test_orlandi_runtime.py	Wed Oct 07 12:02:12 2009 +0200
     2.2 +++ b/viff/test/test_orlandi_runtime.py	Wed Oct 07 12:02:20 2009 +0200
     2.3 @@ -261,7 +261,7 @@
     2.4   
     2.5      runtime_class = OrlandiRuntime
     2.6  
     2.7 -    timeout = 60
     2.8 +    timeout = 800
     2.9  
    2.10      @protocol
    2.11      def test_shift(self, runtime):
    2.12 @@ -556,13 +556,15 @@
    2.13          x2 = runtime.shift([1], self.Zp, x1)
    2.14          y2 = runtime.shift([2], self.Zp, y1)
    2.15  
    2.16 -        M = []
    2.17 -        for j in xrange(1, 2*runtime.d + 2):
    2.18 -            M.append(_get_triple(self, self.Zp))
    2.19 -        z2 = runtime.leak_tolerant_mul(x2, y2, M)
    2.20 -        d = runtime.open(z2)
    2.21 -        d.addCallback(check)
    2.22 -        return d
    2.23 +        c, sls = runtime.random_triple(self.Zp, 2*runtime.d + 1)
    2.24 +
    2.25 +        def cont(M):
    2.26 +            z2 = runtime.leak_tolerant_mul(x2, y2, M)
    2.27 +            d = runtime.open(z2)
    2.28 +            d.addCallback(check)
    2.29 +            return d
    2.30 +        sls.addCallbacks(cont, runtime.error_handler)
    2.31 +        return sls
    2.32  
    2.33          z2 = runtime._cmul(y2, x2, self.Zp)
    2.34          self.assertEquals(z2, None)
    2.35 @@ -672,7 +674,94 @@
    2.36              d = gatherResults(ds)
    2.37              d.addCallback(check)
    2.38              return d
    2.39 -        d = runtime.random_triple(self.Zp)
    2.40 +        c, d = runtime.random_triple(self.Zp, 1)
    2.41          d.addCallbacks(open, runtime.error_handler)
    2.42          return d
    2.43  
    2.44 +    @protocol
    2.45 +    def test_random_triple3_parallel(self, runtime):
    2.46 +        """Test the triple_combiner command."""
    2.47 +
    2.48 +        self.Zp = GF(6277101735386680763835789423176059013767194773182842284081)
    2.49 +
    2.50 +        def check(ls):
    2.51 +            for x in xrange(len(ls) // 3):
    2.52 +                a = ls[x * 3]
    2.53 +                b = ls[x * 3 + 1]
    2.54 +                c = ls[x * 3 + 2]
    2.55 +                self.assertEquals(c, a * b)
    2.56 +
    2.57 +        def open(ls):
    2.58 +            ds = []
    2.59 +            for [(a, b, c)] in ls:
    2.60 +                d1 = runtime.open(a)
    2.61 +                d2 = runtime.open(b)
    2.62 +                d3 = runtime.open(c)
    2.63 +                ds.append(d1)
    2.64 +                ds.append(d2)
    2.65 +                ds.append(d3)
    2.66 +
    2.67 +            d = gatherResults(ds)
    2.68 +            d.addCallback(check)
    2.69 +            return d
    2.70 +        ac, a = runtime.random_triple(self.Zp, 1)
    2.71 +        bc, b = runtime.random_triple(self.Zp, 1)
    2.72 +        cc, c = runtime.random_triple(self.Zp, 1)
    2.73 +        d = gather_shares([a, b, c])
    2.74 +        d.addCallbacks(open, runtime.error_handler)
    2.75 +        return d
    2.76 +
    2.77 +    @protocol
    2.78 +    def test_random_triple_parallel(self, runtime):
    2.79 +        """Test the triple_combiner command."""
    2.80 +
    2.81 +        self.Zp = GF(6277101735386680763835789423176059013767194773182842284081)
    2.82 +
    2.83 +        def check(ls):
    2.84 +            for x in xrange(len(ls) // 3):
    2.85 +                a = ls[x * 3]
    2.86 +                b = ls[x * 3 + 1]
    2.87 +                c = ls[x * 3 + 2]
    2.88 +                self.assertEquals(c, a * b)
    2.89 +
    2.90 +        def open(ls):
    2.91 +            ds = []
    2.92 +            for [(a, b, c)] in ls:
    2.93 +                d1 = runtime.open(a)
    2.94 +                d2 = runtime.open(b)
    2.95 +                d3 = runtime.open(c)
    2.96 +                ds.append(d1)
    2.97 +                ds.append(d2)
    2.98 +                ds.append(d3)
    2.99 +
   2.100 +            d = gatherResults(ds)
   2.101 +            d.addCallback(check)
   2.102 +            return d
   2.103 +
   2.104 +        a_shares = []
   2.105 +        b_shares = []
   2.106 +        c_shares = []
   2.107 +
   2.108 +        def cont(x):
   2.109 +            while a_shares and b_shares:
   2.110 +                a = a_shares.pop()
   2.111 +                b = b_shares.pop()
   2.112 +                c_shares.append(runtime.mul(a, b))
   2.113 +            done = gather_shares(c_shares)
   2.114 +            return done
   2.115 +
   2.116 +        count = 5
   2.117 +
   2.118 +        for i in range(count):
   2.119 +            inputter = (i % len(runtime.players)) + 1
   2.120 +            if inputter == runtime.id:
   2.121 +                a = rand.randint(0, self.Zp.modulus)
   2.122 +                b = rand.randint(0, self.Zp.modulus)
   2.123 +            else:
   2.124 +                a, b = None, None
   2.125 +            a_shares.append(runtime.input([inputter], self.Zp, a))
   2.126 +            b_shares.append(runtime.input([inputter], self.Zp, b))
   2.127 +        shares_ready = gather_shares(a_shares + b_shares)
   2.128 +
   2.129 +        runtime.schedule_callback(shares_ready, cont)
   2.130 +        return shares_ready