Re: [viff-devel] Weird behaviour
A solution is to wrap the deferred in a datastructure, like an object, list, set, or what ever you prefer. On 10/08/2009, at 23.40, Martin Geisler wrote: Janus Dam Nielsen writes: Hi Martin Thanks for your thoughts on this. You're welcome, it took a me a while to figure out what was wrong here. I think the take-home message is that you have structured your code in an unusual way. Whenever you add a callback to a Deferred but keep referring to the Deferred inside the callback, then you're off track. At least that's my experience :-) Actually I think you are slightly off :) Lets look at what the example does: First, the Deferred a is created Second, the callback r is created, Third, a callback, append, is attached to a Forth, r is added to values Fifth, r is returned What seems to be the problem is the returning of a deferred from a callback in combination with holding on to a reference to it in the callback. Yes, when you return a Deferred, it loses its value. The value is transferred to the other Deferred. -- Martin Geisler VIFF (Virtual Ideal Functionality Framework) brings easy and efficient SMPC (Secure Multiparty Computation) to Python. See: http://viff.dk/. Janus Dam Nielsen R&D SCIENTIST, PhD. CENTRE FOR IT-SECURITY THE ALEXANDRA INSTITUTE LTD. T +45 42 22 93 56 E [email protected] W alexandra.dk ___ viff-devel mailing list (http://viff.dk/) [email protected] http://lists.viff.dk/listinfo.cgi/viff-devel-viff.dk
Re: [viff-devel] Weird behaviour
Janus Dam Nielsen writes: > Hi Martin > > Thanks for your thoughts on this. You're welcome, it took a me a while to figure out what was wrong here. >> I think the take-home message is that you have structured your code >> in an unusual way. Whenever you add a callback to a Deferred but keep >> referring to the Deferred inside the callback, then you're off track. >> At least that's my experience :-) > Actually I think you are slightly off :) > > Lets look at what the example does: > First, the Deferred a is created > Second, the callback r is created, > Third, a callback, append, is attached to a > Forth, r is added to values > Fifth, r is returned > > What seems to be the problem is the returning of a deferred from a > callback in combination with holding on to a reference to it in the > callback. Yes, when you return a Deferred, it loses its value. The value is transferred to the other Deferred. -- Martin Geisler VIFF (Virtual Ideal Functionality Framework) brings easy and efficient SMPC (Secure Multiparty Computation) to Python. See: http://viff.dk/. pgpoBGTSUGgbI.pgp Description: PGP signature ___ viff-devel mailing list (http://viff.dk/) [email protected] http://lists.viff.dk/listinfo.cgi/viff-devel-viff.dk
Re: [viff-devel] Weird behaviour
Hi Martin
Thanks for your thoughts on this.
I think the take-home message is that you have structured your code in
an unusual way. Whenever you add a callback to a Deferred but keep
referring to the Deferred inside the callback, then you're off
track. At
least that's my experience :-)
Actually I think you are slightly off :)
Lets look at what the example does:
First, the Deferred a is created
Second, the callback r is created,
Third, a callback, append, is attached to a
Forth, r is added to values
Fifth, r is returned
What seems to be the problem is the returning of a deferred from a
callback in combination with holding on to a reference to it in the
callback.
On 05/08/2009, at 11.47, Martin Geisler wrote:
Janus Dam Nielsen writes:
As you see when player 1 adds a share to the value list, the current
result of the share is 13. However when player 1 comes around to
add a
new share with current result 9, the current result of the share
already contained in the list has transformed into None! It is clear
from the hashcode that it is still the same object, so why does the
current value change??
I have tried to boil down the code as much as possible.
Here is an even simpler version of your code:
from viff.test.util import RuntimeTestCase, protocol
from viff.field import GF
Zp = GF(53)
class DealerTest(RuntimeTestCase):
@protocol
def test_next_three_cards(self, runtime):
values = []
print
def append(x, a, r):
print runtime.id, "append", "x:", x, "a:", a, "r:", r
values.append(r)
return r
def next_card(a):
print runtime.id, "next_card", a
r = runtime.input([1], Zp, runtime.id == 1 and 23 or None)
print runtime.id, "values before:", values
runtime.schedule_callback(a, append, a, r)
print runtime.id, "values after:", values
print runtime.id, "next_card return", a
return a
fourtwo = runtime.input([1], Zp, runtime.id == 1 and 42 or
None)
return next_card(fourtwo)
It gives output like this:
% trial test_dealer.py | grep '^1'
1 next_card
1 values before: []
1 append x: {42} a:
r:
1 values after: []
1 next_card return
Sure enough, the 0xaa8f36c Share in the values array is changed by the
append function. The reason is that append is used as a callback
returns
a Deferred (r). When a callback returns a Deferred, the final return
value becomes the value of the Deferred.
This is done in Deferred._runCallbacks, which loops through the
callbacks and updates self.result. It then has this code:
if isinstance(self.result, Deferred):
self.callbacks = cb
# note: this will cause _runCallbacks to be called
# "recursively" sometimes... this shouldn't cause any
# problems, since all the state has been set back to
# the way it's supposed to be, but it is useful to know
# in case something goes wrong. deferreds really ought
# not to return themselves from their callbacks.
self.pause()
self.result.addBoth(self._continue)
where
def _continue(self, result):
self.result = result
self.unpause()
So Deferred._continue is added as a callback to our r Deferred, and
since _continue return None, this becomes the value stored inside r.
I think the take-home message is that you have structured your code in
an unusual way. Whenever you add a callback to a Deferred but keep
referring to the Deferred inside the callback, then you're off
track. At
least that's my experience :-)
--
Martin Geisler
VIFF (Virtual Ideal Functionality Framework) brings easy and efficient
SMPC (Secure Multiparty Computation) to Python. See: http://viff.dk/.
___
viff-devel mailing list (http://viff.dk/)
[email protected]
http://lists.viff.dk/listinfo.cgi/viff-devel-viff.dk
Janus Dam Nielsen
R&D SCIENTIST, PhD.
CENTRE FOR IT-SECURITY
THE ALEXANDRA INSTITUTE LTD.
T +45 42 22 93 56
E [email protected]
W alexandra.dk
___
viff-devel mailing list (http://viff.dk/)
[email protected]
http://lists.viff.dk/listinfo.cgi/viff-devel-viff.dk
Re: [viff-devel] Weird behaviour
Janus Dam Nielsen writes:
> As you see when player 1 adds a share to the value list, the current
> result of the share is 13. However when player 1 comes around to add a
> new share with current result 9, the current result of the share
> already contained in the list has transformed into None! It is clear
> from the hashcode that it is still the same object, so why does the
> current value change??
>
> I have tried to boil down the code as much as possible.
Here is an even simpler version of your code:
from viff.test.util import RuntimeTestCase, protocol
from viff.field import GF
Zp = GF(53)
class DealerTest(RuntimeTestCase):
@protocol
def test_next_three_cards(self, runtime):
values = []
print
def append(x, a, r):
print runtime.id, "append", "x:", x, "a:", a, "r:", r
values.append(r)
return r
def next_card(a):
print runtime.id, "next_card", a
r = runtime.input([1], Zp, runtime.id == 1 and 23 or None)
print runtime.id, "values before:", values
runtime.schedule_callback(a, append, a, r)
print runtime.id, "values after:", values
print runtime.id, "next_card return", a
return a
fourtwo = runtime.input([1], Zp, runtime.id == 1 and 42 or None)
return next_card(fourtwo)
It gives output like this:
% trial test_dealer.py | grep '^1'
1 next_card
1 values before: []
1 append x: {42} a:
r:
1 values after: []
1 next_card return
Sure enough, the 0xaa8f36c Share in the values array is changed by the
append function. The reason is that append is used as a callback returns
a Deferred (r). When a callback returns a Deferred, the final return
value becomes the value of the Deferred.
This is done in Deferred._runCallbacks, which loops through the
callbacks and updates self.result. It then has this code:
if isinstance(self.result, Deferred):
self.callbacks = cb
# note: this will cause _runCallbacks to be called
# "recursively" sometimes... this shouldn't cause any
# problems, since all the state has been set back to
# the way it's supposed to be, but it is useful to know
# in case something goes wrong. deferreds really ought
# not to return themselves from their callbacks.
self.pause()
self.result.addBoth(self._continue)
where
def _continue(self, result):
self.result = result
self.unpause()
So Deferred._continue is added as a callback to our r Deferred, and
since _continue return None, this becomes the value stored inside r.
I think the take-home message is that you have structured your code in
an unusual way. Whenever you add a callback to a Deferred but keep
referring to the Deferred inside the callback, then you're off track. At
least that's my experience :-)
--
Martin Geisler
VIFF (Virtual Ideal Functionality Framework) brings easy and efficient
SMPC (Secure Multiparty Computation) to Python. See: http://viff.dk/.
___
viff-devel mailing list (http://viff.dk/)
[email protected]
http://lists.viff.dk/listinfo.cgi/viff-devel-viff.dk
