[viff-devel] Weird behaviour

Janus Dam Nielsen janus.nielsen at alexandra.dk
Mon Aug 10 07:04:43 PDT 2009


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 <janus.nielsen at alexandra.dk> 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 <Share at 0xaa88bec  current result: {42}>
> 1 values before: []
> 1 append x: {42} a: <Share at 0xaa88bec  current result: {42}>
>                 r: <Share at 0xaa8f36c  current result: {42}>
> 1 values after: [<Share at 0xaa8f36c  current result: None>]
> 1 next_card return <Share at 0xaa88bec  current result: {42}>
>
> 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/)
> viff-devel at viff.dk
> 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 janus.nielsen at alexandra.dk
W alexandra.dk
____________________________________________________

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.viff.dk/pipermail/viff-devel-viff.dk/attachments/20090810/19af441a/attachment.htm>


More information about the viff-devel mailing list