viff

changeset 1320:fb09cb799cc8

Preprocess decorator returns data without deferreds.
author Marcel Keller <mkeller@cs.au.dk>
date Fri, 02 Oct 2009 16:39:19 +0200
parents 96e0f7de22b0
children 71f205befbbb
files apps/aes.py viff/active.py viff/aes.py viff/passive.py viff/runtime.py
diffstat 5 files changed, 44 insertions(+), 47 deletions(-) [+]
line diff
     1.1 --- a/apps/aes.py	Fri Oct 02 11:27:08 2009 +0200
     1.2 +++ b/apps/aes.py	Fri Oct 02 16:39:19 2009 +0200
     1.3 @@ -141,7 +141,7 @@
     1.4              pcs = [(1, 2 + 130 * options.count + 141 * i + j, 1, 0)
     1.5                     for i in range(10 * options.count)
     1.6                     for j in range(140)] + \
     1.7 -                  [(2, 18, k) + (81,) * i + (2 + 4 * j, 3, l, 1, 0)
     1.8 +                  [(2, 18, k) + (121,) * i + (4 + 6 * j, l, 1, 0)
     1.9                     for k in range(1, options.count + 1)
    1.10                     for i in range(10)
    1.11                     for j in range(20)
    1.12 @@ -154,7 +154,7 @@
    1.13          program_desc[("generate_triples", (GF256,))] = pcs
    1.14  
    1.15      if options.exponentiation == 4:
    1.16 -        pcs = [(2, 18, k) + (81,) * i + (1 + j * 4, 0)
    1.17 +        pcs = [(2, 18, k) + (121,) * i + (1 + j * 6, 0)
    1.18                 for k in range(1, options.count + 1)
    1.19                 for i in range(10)
    1.20                 for j in range(20)]
     2.1 --- a/viff/active.py	Fri Oct 02 11:27:08 2009 +0200
     2.2 +++ b/viff/active.py	Fri Oct 02 16:39:19 2009 +0200
     2.3 @@ -381,10 +381,10 @@
     2.4      def get_triple(self, field):
     2.5          # This is a waste, but this function is only called if there
     2.6          # are no pre-processed triples left.
     2.7 -        return self.generate_triples(field)[0]
     2.8 +        return self.generate_triples(field, gather=False)[0]
     2.9  
    2.10      @increment_pc
    2.11 -    def generate_triples(self, field):
    2.12 +    def generate_triples(self, field, gather=True):
    2.13          """Generate multiplication triples.
    2.14  
    2.15          These are random numbers *a*, *b*, and *c* such that ``c =
    2.16 @@ -411,14 +411,23 @@
    2.17              d = [self.open(d_2t[i], threshold=2*t) for i in range(T)]
    2.18              c_t = [r_t[i] + d[i] for i in range(T)]
    2.19  
    2.20 -            for triple, result in zip(zip(a_t, b_t, c_t), results):
    2.21 -                gatherResults(triple).chainDeferred(result)
    2.22 +            if gather:
    2.23 +                for triple, result in zip(zip(a_t, b_t, c_t), results):
    2.24 +                    gatherResults(triple).chainDeferred(result)
    2.25 +            else:
    2.26 +                for triple, result_triple in zip(zip(a_t, b_t, c_t), results):
    2.27 +                    for item, result_item in zip(triple, result_triple):
    2.28 +                        item.chainDeferred(result_item)
    2.29  
    2.30          single_a = self.single_share_random(T, t, field)
    2.31          single_b = self.single_share_random(T, t, field)
    2.32          double_c = self.double_share_random(T, t, 2*t, field)
    2.33  
    2.34 -        results = [Deferred() for i in range(T)]
    2.35 +        if gather:
    2.36 +            results = [Deferred() for i in range(T)]
    2.37 +        else:
    2.38 +            results = [[Share(self, field) for i in range(3)] for i in range(T)]
    2.39 +
    2.40          self.schedule_callback(gatherResults([single_a, single_b, double_c]), make_triple, results)
    2.41          return results
    2.42  
    2.43 @@ -428,11 +437,11 @@
    2.44      @increment_pc
    2.45      @preprocess("generate_triples")
    2.46      def get_triple(self, field):
    2.47 -        result = self.generate_triples(field, quantity=1)
    2.48 +        result = self.generate_triples(field, quantity=1, gather=False)
    2.49          return result[0]
    2.50  
    2.51      @increment_pc
    2.52 -    def generate_triples(self, field, quantity=20):
    2.53 +    def generate_triples(self, field, quantity=20, gather=True):
    2.54          """Generate *quantity* multiplication triples using PRSS.
    2.55  
    2.56          These are random numbers *a*, *b*, and *c* such that ``c =
    2.57 @@ -455,7 +464,10 @@
    2.58              d = self.open(d_2t, threshold=2*self.threshold)
    2.59              c_t[i] = r_t[i] + d
    2.60  
    2.61 -        return [gatherResults(triple) for triple in zip(a_t, b_t, c_t)]
    2.62 +        if gather:
    2.63 +            return [gatherResults(triple) for triple in zip(a_t, b_t, c_t)]
    2.64 +        else:
    2.65 +            return zip(a_t, b_t, c_t)
    2.66  
    2.67  
    2.68  class BasicActiveRuntime(PassiveRuntime):
    2.69 @@ -493,31 +505,21 @@
    2.70  
    2.71          # At this point both share_x and share_y must be Share
    2.72          # objects. We multiply them via a multiplication triple.
    2.73 -        def finish_mul(triple):
    2.74 -            a, b, c = triple
    2.75 -            d = self.open(share_x - a)
    2.76 -            e = self.open(share_y - b)
    2.77 +        a, b, c = self.get_triple(share_x.field)
    2.78 +        d = self.open(share_x - a)
    2.79 +        e = self.open(share_y - b)
    2.80  
    2.81 -            # TODO: We ought to be able to simply do
    2.82 -            #
    2.83 -            #   return d*e + d*y + e*x + c
    2.84 -            #
    2.85 -            # but that leads to infinite recursion since d and e are
    2.86 -            # Shares, not FieldElements. So we have to do a bit more
    2.87 -            # work... The following callback also leads to recursion, but
    2.88 -            # only one level since d and e are FieldElements now, which
    2.89 -            # means that we return in the above if statements.
    2.90 -            result = gather_shares([d, e])
    2.91 -            result.addCallback(lambda (d,e): d*e + d*b + e*a + c)
    2.92 -            return result
    2.93 -
    2.94 -        # This will be the result, a Share object.
    2.95 -        result = Share(self, share_x.field)
    2.96 -        # This is the Deferred we will do processing on.
    2.97 -        triple = self.get_triple(share_x.field)
    2.98 -        triple = self.schedule_callback(triple, finish_mul)
    2.99 -        # We add the result to the chains in triple.
   2.100 -        triple.chainDeferred(result)
   2.101 +        # TODO: We ought to be able to simply do
   2.102 +        #
   2.103 +        #   return d*e + d*y + e*x + c
   2.104 +        #
   2.105 +        # but that leads to infinite recursion since d and e are
   2.106 +        # Shares, not FieldElements. So we have to do a bit more
   2.107 +        # work... The following callback also leads to recursion, but
   2.108 +        # only one level since d and e are FieldElements now, which
   2.109 +        # means that we return in the above if statements.
   2.110 +        result = gather_shares([d, e])
   2.111 +        result.addCallback(lambda (d,e): d*e + d*b + e*a + c)
   2.112          return result
   2.113  
   2.114  
     3.1 --- a/viff/aes.py	Fri Oct 02 11:27:08 2009 +0200
     3.2 +++ b/viff/aes.py	Fri Oct 02 16:39:19 2009 +0200
     3.3 @@ -167,17 +167,12 @@
     3.4                  byte_powers.append(byte_powers.pop(0) * byte_powers.pop(0))
     3.5              return byte_powers[0]
     3.6  
     3.7 -        def open_and_exponentiate(random_powers):
     3.8 -            masked_byte = self.runtime.open(byte + random_powers[0])
     3.9 -            masked_powers = self.runtime.schedule_callback(masked_byte,
    3.10 -                lambda masked_byte: self.runtime.powerchain(masked_byte, 7))
    3.11 -            return self.runtime.schedule_callback(
    3.12 -                masked_powers, add_and_multiply, random_powers)
    3.13 -
    3.14 -        result = Share(self.runtime, GF256)
    3.15 -        self.runtime.prss_powerchain().chainDeferred(result)
    3.16 -        result = self.runtime.schedule_callback(result, open_and_exponentiate)
    3.17 -        return result
    3.18 +        random_powers = self.runtime.prss_powerchain()
    3.19 +        masked_byte = self.runtime.open(byte + random_powers[0])
    3.20 +        masked_powers = self.runtime.schedule_callback(masked_byte,
    3.21 +            lambda masked_byte: self.runtime.powerchain(masked_byte, 7))
    3.22 +        return self.runtime.schedule_callback(
    3.23 +            masked_powers, add_and_multiply, random_powers)
    3.24  
    3.25      def invert_by_exponentiation(self, byte):
    3.26          byte_2 = byte * byte
     4.1 --- a/viff/passive.py	Fri Oct 02 11:27:08 2009 +0200
     4.2 +++ b/viff/passive.py	Fri Oct 02 16:39:19 2009 +0200
     4.3 @@ -467,7 +467,7 @@
     4.4          """Generate a random secret share in GF256 and returns
     4.5          [*share*, *share*^2, *share*^4, ..., *share*^(i^max)]."""
     4.6          share = self.prss_share_random(GF256)
     4.7 -        return gatherResults(self.powerchain(share, max))
     4.8 +        return self.powerchain(share, max)
     4.9  
    4.10      def prss_powerchains(self, max=7, quantity=20):
    4.11          """Does *quantity* times the same as :meth:`prss_powerchain`.
     5.1 --- a/viff/runtime.py	Fri Oct 02 11:27:08 2009 +0200
     5.2 +++ b/viff/runtime.py	Fri Oct 02 16:39:19 2009 +0200
     5.3 @@ -446,7 +446,7 @@
     5.4          def preprocess_wrapper(self, *args, **kwargs):
     5.5              pc = tuple(self.program_counter)
     5.6              try:
     5.7 -                return succeed(self._pool.pop(pc))
     5.8 +                return self._pool.pop(pc)
     5.9              except KeyError:
    5.10                  key = (generator, args)
    5.11                  pcs = self._needed_data.setdefault(key, [])