Mikkel Krøigård <[EMAIL PROTECTED]> writes:
Cool, thank you for attacking this long-standing bug...
Could you please split up the patch so that the change of the
data_type from strings to integers is one patch, and the replacements
of the marshal module is another.
> # HG changeset patch
> # User Mikkel Krøigård <[EMAIL PROTECTED]>
> # Date 1223542718 -7200
> # Node ID da39016c1284776802e9a23b64384c207b29f3e0
> # Parent 19013451fcdd87acc6146fc7ca42d32f388be523
> Replaced marshal module
>
> diff --git a/viff/active.py b/viff/active.py
> --- a/viff/active.py
> +++ b/viff/active.py
> @@ -26,7 +26,8 @@
> from viff import shamir
> from viff.util import rand
> from viff.matrix import Matrix, hyper
> -from viff.runtime import Runtime, Share, increment_pc, preprocess,
> gather_shares
> +from viff.runtime import READY, ECHO, SEND, SHARE, Runtime, Share, \
> + increment_pc, preprocess, gather_shares
>
>
> class BrachaBroadcastMixin:
> @@ -79,7 +80,7 @@
> ids.append(peer_id)
> if len(ids) >= ceil((n+t+1)/2) and not ready:
> bracha_sent_ready[message] = True
> - unsafe_broadcast("ready", message)
> + unsafe_broadcast(READY, message)
> ready_received(message, self.id)
>
> def ready_received(message, peer_id):
> @@ -94,7 +95,7 @@
> ids.append(peer_id)
> if len(ids) == t+1 and not ready:
> bracha_sent_ready[message] = True
> - unsafe_broadcast("ready", message)
> + unsafe_broadcast(READY, message)
> ready_received(message, self.id)
>
> elif len(ids) == 2*t+1 and not delivered:
> @@ -106,7 +107,7 @@
> # by sending an echo message to each player. Since the
> # unsafe broadcast doesn't send a message to this player,
> # we simulate it by calling the echo_received function.
> - unsafe_broadcast("echo", message)
> + unsafe_broadcast(ECHO, message)
> echo_received(message, self.id)
>
>
> @@ -116,20 +117,20 @@
> for peer_id in self.players:
> if peer_id != self.id:
> d_echo = Deferred().addCallback(echo_received, peer_id)
> - self._expect_data(peer_id, "echo", d_echo)
> + self._expect_data(peer_id, ECHO, d_echo)
>
> d_ready = Deferred().addCallback(ready_received, peer_id)
> - self._expect_data(peer_id, "ready", d_ready)
> + self._expect_data(peer_id, READY, d_ready)
>
> # If this player is the sender, we transmit a send message to
> # each player. We send one to this player by calling the
> # send_received function.
> if self.id == sender:
> - unsafe_broadcast("send", message)
> + unsafe_broadcast(SEND, message)
> send_received(message)
> else:
> d_send = Deferred().addCallback(send_received)
> - self._expect_data(sender, "send", d_send)
> + self._expect_data(sender, SEND, d_send)
>
>
> return result
> diff --git a/viff/runtime.py b/viff/runtime.py
> --- a/viff/runtime.py
> +++ b/viff/runtime.py
> @@ -34,9 +34,11 @@
> __docformat__ = "restructuredtext"
>
> import time
> -import marshal
> +import struct
> from optparse import OptionParser, OptionGroup
> from collections import deque
> +
> +from gmpy import mpz
Not used anymore, I think...
> from viff import shamir
> from viff.prss import prss, prss_lsb, prss_zero
> @@ -50,6 +52,10 @@
> from twisted.internet.protocol import ReconnectingClientFactory,
> ServerFactory
> from twisted.protocols.basic import Int16StringReceiver
>
> +SHARE = 0
> +ECHO = 1
> +READY = 2
> +SEND = 3
We need a big fat comment here which explains them. And some
documentation in doc/runtime.txt.
> class Share(Deferred):
> """A shared number.
> @@ -295,7 +301,18 @@
> self.transport.loseConnection()
> self.factory.identify_peer(self)
> else:
> - program_counter, data_type, data = marshal.loads(string)
We need a comment which describes the packet format too.
> + # TODO: we cannot handle the empty string
> + # also note that we cannot handle pcs longer than 256
> + pc_size = ord(string[0])
> + fmt = (pc_size + 1)*'i'
I think we can use the repeat count here: "%di" % (pc_size + 1)
> + predata_size = struct.calcsize(fmt) + 1
> + fmt = "%s%is" % (fmt, len(string)-predata_size)
> +
> + unpacked = struct.unpack(fmt, string[1:])
> +
Empty line not needed.
> + program_counter = unpacked[:pc_size]
> + data_type, data = unpacked[-2:]
> +
> key = (program_counter, data_type)
>
> deq = self.incoming_data.setdefault(key, deque())
> @@ -311,8 +328,11 @@
> # TypeError. They should be handled somehow.
>
> def sendData(self, program_counter, data_type, data):
> - send_data = (program_counter, data_type, data)
> - self.sendString(marshal.dumps(send_data))
> + pc_size = len(program_counter)
> + fmt = "%s%is" % ((pc_size + 1)*'i', len(data))
> + data_tuple = program_counter + (data_type, data)
> +
> + self.sendString(chr(pc_size) + struct.pack(fmt, *data_tuple))
>
> def sendShare(self, program_counter, share):
> """Send a share.
> @@ -320,8 +340,8 @@
> The program counter and the share are marshalled and sent to
> the peer.
> """
> - self.sendData(program_counter, "share", share.value)
> -
> + self.sendData(program_counter, SHARE, hex(share.value))
> +
> def loseConnection(self):
> """Disconnect this protocol instance."""
> self.transport.loseConnection()
> @@ -613,9 +633,13 @@
> return share
>
> def _expect_share(self, peer_id, field):
> +
> + def unpack_share(value_string):
> + return field(long(value_string, 16))
> +
> share = Share(self, field)
> - share.addCallback(lambda value: field(value))
> - self._expect_data(peer_id, "share", share)
> + share.addCallback(unpack_share)
> + self._expect_data(peer_id, SHARE, share)
> return share
>
> @increment_pc
> @@ -630,7 +654,7 @@
> ``int`` tells us how many items of pre-processed data the
> :class:`Deferred` will yield.
>
> - - The Deferred must yield a list of the promissed length.
> + - The Deferred must yield a list of the promised length.
Unrelated change -- please put it in a separate patch.
>
> - The list contains the actual data. This data can be either a
> Deferred or a tuple of Deferreds.
> diff --git a/viff/test/test_basic_runtime.py b/viff/test/test_basic_runtime.py
> --- a/viff/test/test_basic_runtime.py
> +++ b/viff/test/test_basic_runtime.py
> @@ -140,20 +140,20 @@
> for peer_id in range(1, self.num_players+1):
> if peer_id != runtime.id:
> pc = tuple(runtime.program_counter)
> - runtime.protocols[peer_id].sendData(pc, "test", 100)
> - runtime.protocols[peer_id].sendData(pc, "test", 200)
> - runtime.protocols[peer_id].sendData(pc, "test", 300)
> + runtime.protocols[peer_id].sendData(pc, 42, '100')
> + runtime.protocols[peer_id].sendData(pc, 42, '200')
> + runtime.protocols[peer_id].sendData(pc, 42, '300')
>
> # Then receive the data.
> deferreds = []
> for peer_id in range(1, self.num_players+1):
> if peer_id != runtime.id:
> - d100 = Deferred().addCallback(self.assertEquals, 100)
> - d200 = Deferred().addCallback(self.assertEquals, 200)
> - d300 = Deferred().addCallback(self.assertEquals, 300)
> - runtime._expect_data(peer_id, "test", d100)
> - runtime._expect_data(peer_id, "test", d200)
> - runtime._expect_data(peer_id, "test", d300)
> + d100 = Deferred().addCallback(self.assertEquals, '100')
> + d200 = Deferred().addCallback(self.assertEquals, '200')
> + d300 = Deferred().addCallback(self.assertEquals, '300')
> + runtime._expect_data(peer_id, 42, d100)
> + runtime._expect_data(peer_id, 42, d200)
> + runtime._expect_data(peer_id, 42, d300)
> deferreds.extend([d100, d200, d300])
--
Martin Geisler
VIFF (Virtual Ideal Functionality Framework) brings easy and efficient
SMPC (Secure Multi-Party Computation) to Python. See: http://viff.dk/.
_______________________________________________
viff-patches mailing list
[email protected]
http://lists.viff.dk/listinfo.cgi/viff-patches-viff.dk