viff

changeset 1212:2daaf0e7a1f6

Make increment_pc mostly obsolete. Instead of calling increment_pc on every method entry to allocate a sub-program counter, we now let schedule_callback take care of this.
author Martin Geisler <mg@cs.au.dk>
date Fri, 18 Sep 2009 14:41:44 +0200
parents b94ff92ee1d9
children 7610deb0ebab
files viff/active.py viff/aes.py viff/comparison.py viff/paillier.py viff/passive.py viff/runtime.py viff/test/test_basic_runtime.py
diffstat 7 files changed, 19 insertions(+), 94 deletions(-) [+]
line diff
     1.1 --- a/viff/active.py	Thu Sep 17 15:48:01 2009 +0200
     1.2 +++ b/viff/active.py	Fri Sep 18 14:41:44 2009 +0200
     1.3 @@ -141,7 +141,6 @@
     1.4  
     1.5          return result
     1.6  
     1.7 -    @increment_pc
     1.8      def broadcast(self, senders, message=None):
     1.9          """Perform one or more Bracha broadcast(s).
    1.10  
    1.11 @@ -186,7 +185,6 @@
    1.12      #: to :const:`None` here and update it as necessary.
    1.13      _hyper = None
    1.14  
    1.15 -    @increment_pc
    1.16      def single_share_random(self, T, degree, field):
    1.17          """Share a random secret.
    1.18  
    1.19 @@ -273,7 +271,6 @@
    1.20          self.schedule_callback(result, exchange)
    1.21          return result
    1.22  
    1.23 -    @increment_pc
    1.24      def double_share_random(self, T, d1, d2, field):
    1.25          """Double-share a random secret using two polynomials.
    1.26  
    1.27 @@ -376,7 +373,6 @@
    1.28          self.schedule_callback(result, exchange)
    1.29          return result
    1.30  
    1.31 -    @increment_pc
    1.32      @preprocess("generate_triples")
    1.33      def get_triple(self, field):
    1.34          # This is a waste, but this function is only called if there
    1.35 @@ -385,7 +381,6 @@
    1.36          result.addCallback(lambda triples: triples[0])
    1.37          return result
    1.38  
    1.39 -    @increment_pc
    1.40      def generate_triples(self, field):
    1.41          """Generate multiplication triples.
    1.42  
    1.43 @@ -425,14 +420,12 @@
    1.44  class TriplesPRSSMixin:
    1.45      """Mixin class for generating multiplication triples using PRSS."""
    1.46  
    1.47 -    @increment_pc
    1.48      @preprocess("generate_triples")
    1.49      def get_triple(self, field):
    1.50          count, result = self.generate_triples(field)
    1.51          result.addCallback(lambda triples: triples[0])
    1.52          return result
    1.53  
    1.54 -    @increment_pc
    1.55      def generate_triples(self, field):
    1.56          """Generate a multiplication triple using PRSS.
    1.57  
    1.58 @@ -467,7 +460,6 @@
    1.59      :class:`ActiveRuntime` instead.
    1.60      """
    1.61  
    1.62 -    @increment_pc
    1.63      def mul(self, share_x, share_y):
    1.64          """Multiplication of shares.
    1.65  
     2.1 --- a/viff/aes.py	Thu Sep 17 15:48:01 2009 +0200
     2.2 +++ b/viff/aes.py	Fri Sep 18 14:41:44 2009 +0200
     2.3 @@ -24,7 +24,7 @@
     2.4  import operator
     2.5  
     2.6  from viff.field import GF256
     2.7 -from viff.runtime import Share, gather_shares, increment_pc
     2.8 +from viff.runtime import Share, gather_shares
     2.9  from viff.matrix import Matrix
    2.10  
    2.11  
    2.12 @@ -319,7 +319,6 @@
    2.13                      "or of shares thereof."
    2.14              return input
    2.15  
    2.16 -    @increment_pc
    2.17      def encrypt(self, cleartext, key, benchmark=False, prepare_at_once=False):
    2.18          """Rijndael encryption.
    2.19  
     3.1 --- a/viff/comparison.py	Thu Sep 17 15:48:01 2009 +0200
     3.2 +++ b/viff/comparison.py	Fri Sep 18 14:41:44 2009 +0200
     3.3 @@ -25,7 +25,7 @@
     3.4  import math
     3.5  
     3.6  from viff.util import rand, profile
     3.7 -from viff.runtime import Share, gather_shares, increment_pc
     3.8 +from viff.runtime import Share, gather_shares
     3.9  from viff.passive import PassiveRuntime
    3.10  from viff.active import ActiveRuntime
    3.11  from viff.field import GF256, FieldElement
    3.12 @@ -34,7 +34,6 @@
    3.13  class ComparisonToft05Mixin:
    3.14      """Comparison by Tomas Toft, 2005."""
    3.15  
    3.16 -    @increment_pc
    3.17      def convert_bit_share(self, share, dst_field):
    3.18          """Convert a 0/1 share into dst_field."""
    3.19          bit = rand.randint(0, 1)
    3.20 @@ -67,7 +66,6 @@
    3.21          return int_b, bit_bits
    3.22  
    3.23      @profile
    3.24 -    @increment_pc
    3.25      def greater_than_equal(self, share_a, share_b):
    3.26          """Compute ``share_a >= share_b``.
    3.27  
    3.28 @@ -100,7 +98,6 @@
    3.29          self.schedule_callback(result, self._finish_greater_than_equal, l)
    3.30          return result
    3.31  
    3.32 -    @increment_pc
    3.33      def _finish_greater_than_equal(self, results, l):
    3.34          """Finish the calculation."""
    3.35          T = results[0]
    3.36 @@ -128,7 +125,6 @@
    3.37  
    3.38          return GF256(T.bit(l)) ^ (bit_bits[l] ^ vec[0][1])
    3.39  
    3.40 -    @increment_pc
    3.41      def _diamond(self, (top_a, bot_a), (top_b, bot_b)):
    3.42          """The "diamond-operator".
    3.43  
    3.44 @@ -160,7 +156,6 @@
    3.45      elements and gives a secret result shared over Zp.
    3.46      """
    3.47  
    3.48 -    @increment_pc
    3.49      def convert_bit_share(self, share, dst_field):
    3.50          """Convert a 0/1 share into *dst_field*."""
    3.51          l = self.options.security_parameter + math.log(dst_field.modulus, 2)
    3.52 @@ -188,7 +183,6 @@
    3.53          return tmp - full_mask
    3.54  
    3.55      @profile
    3.56 -    @increment_pc
    3.57      def greater_than_equal_preproc(self, field, smallField=None):
    3.58          """Preprocessing for :meth:`greater_than_equal`."""
    3.59          if smallField is None:
    3.60 @@ -243,7 +237,6 @@
    3.61          ##################################################
    3.62  
    3.63      @profile
    3.64 -    @increment_pc
    3.65      def greater_than_equal_online(self, share_a, share_b, preproc, field):
    3.66          """Compute ``share_a >= share_b``. Result is secret shared."""
    3.67          # increment l as a, b are increased
    3.68 @@ -272,7 +265,6 @@
    3.69                                 r_modl, r_bits, z)
    3.70          return c
    3.71  
    3.72 -    @increment_pc
    3.73      def _finish_greater_than_equal(self, c, field, smallField, s_bit, s_sign,
    3.74                                 mask, r_modl, r_bits, z):
    3.75          """Finish the calculation."""
    3.76 @@ -316,7 +308,6 @@
    3.77          return (z - result) * ~field(2**l)
    3.78      # END _finish_greater_than
    3.79  
    3.80 -    @increment_pc
    3.81      def greater_than_equal(self, share_a, share_b):
    3.82          """Compute ``share_a >= share_b``.
    3.83  
     4.1 --- a/viff/paillier.py	Thu Sep 17 15:48:01 2009 +0200
     4.2 +++ b/viff/paillier.py	Fri Sep 18 14:41:44 2009 +0200
     4.3 @@ -27,7 +27,7 @@
     4.4  from twisted.internet.defer import Deferred, gatherResults
     4.5  import gmpy
     4.6  
     4.7 -from viff.runtime import Runtime, increment_pc, Share, gather_shares
     4.8 +from viff.runtime import Runtime, Share, gather_shares
     4.9  from viff.runtime import PAILLIER
    4.10  from viff.util import rand, find_random_prime
    4.11  
    4.12 @@ -78,7 +78,6 @@
    4.13          else:
    4.14              self.peer = player
    4.15  
    4.16 -    @increment_pc
    4.17      def prss_share_random(self, field):
    4.18          """Generate a share of a uniformly random element."""
    4.19          prfs = self.players[self.id].prfs(field.modulus)
    4.20 @@ -94,7 +93,6 @@
    4.21          """
    4.22          return self.share(inputters, field, number)
    4.23  
    4.24 -    @increment_pc
    4.25      def share(self, inputters, field, number=None):
    4.26          """Share *number* additively."""
    4.27          assert number is None or self.id in inputters
    4.28 @@ -121,7 +119,6 @@
    4.29      def output(self, share, receivers=None):
    4.30          return self.open(share, receivers)
    4.31  
    4.32 -    @increment_pc
    4.33      def open(self, share, receivers=None):
    4.34          """Open *share* to *receivers* (defaults to both players)."""
    4.35  
     5.1 --- a/viff/passive.py	Thu Sep 17 15:48:01 2009 +0200
     5.2 +++ b/viff/passive.py	Fri Sep 18 14:41:44 2009 +0200
     5.3 @@ -54,7 +54,6 @@
     5.4      def output(self, share, receivers=None, threshold=None):
     5.5          return self.open(share, receivers, threshold)
     5.6  
     5.7 -    @increment_pc
     5.8      def open(self, share, receivers=None, threshold=None):
     5.9          """Open a secret sharing.
    5.10  
    5.11 @@ -172,7 +171,6 @@
    5.12          return result
    5.13  
    5.14      @profile
    5.15 -    @increment_pc
    5.16      def mul(self, share_a, share_b):
    5.17          """Multiplication of shares.
    5.18  
    5.19 @@ -229,7 +227,6 @@
    5.20          else:
    5.21              return share * (share ** (exponent-1))
    5.22  
    5.23 -    @increment_pc
    5.24      def xor(self, share_a, share_b):
    5.25          field = share_a.field
    5.26          if not isinstance(share_b, Share):
    5.27 @@ -242,7 +239,6 @@
    5.28          else:
    5.29              return share_a + share_b - 2 * share_a * share_b
    5.30  
    5.31 -    @increment_pc
    5.32      def prss_share(self, inputters, field, element=None):
    5.33          """Creates pseudo-random secret sharings.
    5.34  
    5.35 @@ -351,7 +347,6 @@
    5.36          self.schedule_callback(result, finish, share, binary)
    5.37          return result
    5.38  
    5.39 -    @increment_pc
    5.40      def prss_share_random_multi(self, field, quantity, binary=False):
    5.41          """Does the same as calling *quantity* times :meth:`prss_share_random`,
    5.42          but with less calls to the PRF. Sampling of a binary element is only
    5.43 @@ -374,7 +369,6 @@
    5.44                              modulus, quantity)
    5.45          return [Share(self, field, share) for share in shares]
    5.46  
    5.47 -    @increment_pc
    5.48      def prss_share_zero(self, field):
    5.49          """Generate shares of the zero element from the field given.
    5.50  
    5.51 @@ -387,7 +381,6 @@
    5.52                                 field, prfs, prss_key)
    5.53          return Share(self, field, zero_share)
    5.54  
    5.55 -    @increment_pc
    5.56      def prss_double_share(self, field):
    5.57          """Make a double-sharing using PRSS.
    5.58  
    5.59 @@ -398,7 +391,6 @@
    5.60          z_2t = self.prss_share_zero(field)
    5.61          return (r_t, r_t + z_2t)
    5.62  
    5.63 -    @increment_pc
    5.64      def prss_share_bit_double(self, field):
    5.65          """Share a random bit over *field* and GF256.
    5.66  
    5.67 @@ -423,7 +415,6 @@
    5.68          # Use r_lsb to flip b as needed.
    5.69          return (b_p, b ^ r_lsb)
    5.70  
    5.71 -    @increment_pc
    5.72      def prss_shamir_share_bit_double(self, field):
    5.73          """Shamir share a random bit over *field* and GF256."""
    5.74          n = self.num_players
    5.75 @@ -455,7 +446,6 @@
    5.76          """
    5.77          return self.shamir_share(inputters, field, number, threshold)
    5.78  
    5.79 -    @increment_pc
    5.80      def shamir_share(self, inputters, field, number=None, threshold=None):
    5.81          """Secret share *number* over *field* using Shamir's method.
    5.82  
     6.1 --- a/viff/runtime.py	Thu Sep 17 15:48:01 2009 +0200
     6.2 +++ b/viff/runtime.py	Fri Sep 18 14:41:44 2009 +0200
     6.3 @@ -617,7 +617,6 @@
     6.4          dl = DeferredList(vars)
     6.5          self.schedule_callback(dl, lambda _: self.shutdown())
     6.6  
     6.7 -    @increment_pc
     6.8      def schedule_callback(self, deferred, func, *args, **kwargs):
     6.9          """Schedule a callback on a deferred with the correct program
    6.10          counter.
    6.11 @@ -631,7 +630,9 @@
    6.12          Any extra arguments are passed to the callback as with
    6.13          :meth:`addCallback`.
    6.14          """
    6.15 +        self.program_counter[-1] += 1
    6.16          saved_pc = self.program_counter[:]
    6.17 +        saved_pc.append(0)
    6.18  
    6.19          @wrapper(func)
    6.20          def callback_wrapper(*args, **kwargs):
    6.21 @@ -667,7 +668,6 @@
    6.22          deferred.addCallback(queue_callback, self, fork)
    6.23          return self.schedule_callback(fork, func, *args, **kwargs)
    6.24  
    6.25 -    @increment_pc
    6.26      def synchronize(self):
    6.27          """Introduce a synchronization point.
    6.28  
    6.29 @@ -723,7 +723,6 @@
    6.30          self._expect_data(peer_id, SHARE, share)
    6.31          return share
    6.32  
    6.33 -    @increment_pc
    6.34      def preprocess(self, program):
    6.35          """Generate preprocess material.
    6.36  
     7.1 --- a/viff/test/test_basic_runtime.py	Thu Sep 17 15:48:01 2009 +0200
     7.2 +++ b/viff/test/test_basic_runtime.py	Fri Sep 18 14:41:44 2009 +0200
     7.3 @@ -18,7 +18,6 @@
     7.4  from twisted.internet.defer import Deferred, gatherResults
     7.5  
     7.6  from viff.test.util import RuntimeTestCase, protocol
     7.7 -from viff.runtime import increment_pc
     7.8  
     7.9  
    7.10  class ProgramCounterTest(RuntimeTestCase):
    7.11 @@ -32,26 +31,14 @@
    7.12      def test_simple_operation(self, runtime):
    7.13          """Test an operation which makes no further calls.
    7.14  
    7.15 -        Each call should increment the program counter by one.
    7.16 +        No callbacks are scheduled, and so the program counter is not
    7.17 +        increased.
    7.18          """
    7.19 +        self.assertEquals(runtime.program_counter, [0])
    7.20          runtime.synchronize()
    7.21 -        self.assertEquals(runtime.program_counter, [1])
    7.22 +        self.assertEquals(runtime.program_counter, [0])
    7.23          runtime.synchronize()
    7.24 -        self.assertEquals(runtime.program_counter, [2])
    7.25 -
    7.26 -    @protocol
    7.27 -    def test_complex_operation(self, runtime):
    7.28 -        """Test an operation which makes nested calls.
    7.29 -
    7.30 -        This verifies that the program counter is only incremented by
    7.31 -        one, even for a complex operation.
    7.32 -        """
    7.33 -        # Exclusive-or is calculated as x + y - 2 * x * y, so add,
    7.34 -        # sub, and mul are called.
    7.35 -        runtime.xor(self.Zp(0), self.Zp(1))
    7.36 -        self.assertEquals(runtime.program_counter, [1])
    7.37 -        runtime.xor(self.Zp(0), self.Zp(1))
    7.38 -        self.assertEquals(runtime.program_counter, [2])
    7.39 +        self.assertEquals(runtime.program_counter, [0])
    7.40  
    7.41      @protocol
    7.42      def test_callback(self, runtime):
    7.43 @@ -62,62 +49,32 @@
    7.44          """
    7.45  
    7.46          def verify_program_counter(_):
    7.47 +            # The callback is run with its own sub-program counter.
    7.48              self.assertEquals(runtime.program_counter, [1, 0])
    7.49  
    7.50          d = Deferred()
    7.51 +
    7.52 +        self.assertEquals(runtime.program_counter, [0])
    7.53 +
    7.54 +        # Scheduling a callback increases the program counter.
    7.55          runtime.schedule_callback(d, verify_program_counter)
    7.56 -
    7.57 -        runtime.synchronize()
    7.58 -        self.assertEquals(runtime.program_counter, [2])
    7.59 +        self.assertEquals(runtime.program_counter, [1])
    7.60  
    7.61          # Now trigger verify_program_counter.
    7.62          d.callback(None)
    7.63  
    7.64      @protocol
    7.65 -    def test_nested_calls(self, runtime):
    7.66 -        """Test Runtime methods that call other methods.
    7.67 -
    7.68 -        We create a couple of functions that are used as fake methods.
    7.69 -        """
    7.70 -
    7.71 -        @increment_pc
    7.72 -        def method_a(runtime):
    7.73 -            # First top-level call, so first entry is 1. No calls to
    7.74 -            # other methods decorated with increment_pc has been made,
    7.75 -            # so the second entry is 0.
    7.76 -            self.assertEquals(runtime.program_counter, [1, 0])
    7.77 -            method_b(runtime, 1)
    7.78 -
    7.79 -            self.assertEquals(runtime.program_counter, [1, 1])
    7.80 -            method_b(runtime, 2)
    7.81 -
    7.82 -            # At this point two sub-calls has been made:
    7.83 -            self.assertEquals(runtime.program_counter, [1, 2])
    7.84 -
    7.85 -        @increment_pc
    7.86 -        def method_b(runtime, count):
    7.87 -            # This method is called twice from method_a:
    7.88 -            self.assertEquals(runtime.program_counter, [1, count, 0])
    7.89 -
    7.90 -        # Zero top-level calls:
    7.91 -        self.assertEquals(runtime.program_counter, [0])
    7.92 -        method_a(runtime)
    7.93 -
    7.94 -        # One top-level call:
    7.95 -        self.assertEquals(runtime.program_counter, [1])
    7.96 -
    7.97 -    @protocol
    7.98      def test_multiple_callbacks(self, runtime):
    7.99  
   7.100          d1 = Deferred()
   7.101          d2 = Deferred()
   7.102  
   7.103          def verify_program_counter(_, count):
   7.104 -            self.assertEquals(runtime.program_counter, [1, count, 0])
   7.105 +            self.assertEquals(runtime.program_counter, [count, 0])
   7.106  
   7.107 -        @increment_pc
   7.108          def method_a(runtime):
   7.109 -            self.assertEquals(runtime.program_counter, [1, 0])
   7.110 +            # No calls to schedule_callback yet.
   7.111 +            self.assertEquals(runtime.program_counter, [0])
   7.112  
   7.113              runtime.schedule_callback(d1, verify_program_counter, 1)
   7.114              runtime.schedule_callback(d2, verify_program_counter, 2)