Esempio n. 1
0
        def _broadcast(v):
           def _deliver(j):
               buffers[j].put((i,v))

           for j in range(N):
               greenletPacker(Greenlet(_deliver, j),
                   'random_delay_acs._deliver', (N, t, inputs)).start_later(random.random()*maxdelay)
        def _broadcast(v):
            def _deliver(j):
                buffers[j].put((i, v))

            for j in range(N):
                greenletPacker(
                    Greenlet(_deliver, j), 'random_delay_acs._deliver',
                    (N, t, inputs)).start_later(random.random() * maxdelay)
Esempio n. 3
0
 def _callback(val): # Get notified for i
     # Greenlet(callBackWrap(binary_consensus, callbackFactory(i)), pid,
     #         N, t, 1, make_bc(i), reliableBroadcastReceiveQueue[i].get).start()
     if not i in receivedChannelsFlags:
         receivedChannelsFlags.append(i)
         # mylog('B[%d]binary consensus_%d_starts with 1 at %f' % (pid, i, time.time()), verboseLevel=-1)
         greenletPacker(Greenlet(binary_consensus, i, pid,
             N, t, 1, decideChannel[i], make_bc(i), reliableBroadcastReceiveQueue[i].get),
                 'acs.callbackFactory.binary_consensus', (pid, N, t, Q, broadcast, receive)).start()
Esempio n. 4
0
 def _listener():
     while True:
         sender, (tag, m) = receive()
         if tag == 'B':
             greenletPacker(Greenlet(CBChannel.put, (sender, m)),
                 'includeTransaction.CBChannel.put', (pid, N, t, setToInclude, broadcast, receive)).start()
         elif tag == 'A':
             greenletPacker(Greenlet(ACSChannel.put,
                 (sender, m)
             ), 'includeTransaction.ACSChannel.put', (pid, N, t, setToInclude, broadcast, receive)).start()
 def _listener():
     while True:
         sender, (tag, m) = receive()
         if tag == 'B':
             greenletPacker(Greenlet(CBChannel.put, (sender, m)),
                 'includeTransaction.CBChannel.put', (pid, N, t, setToInclude, broadcast, receive)).start()
         elif tag == 'A':
             greenletPacker(Greenlet(ACSChannel.put,
                 (sender, m)
             ), 'includeTransaction.ACSChannel.put', (pid, N, t, setToInclude, broadcast, receive)).start()
 def _callback(val):  # Get notified for i
     # Greenlet(callBackWrap(binary_consensus, callbackFactory(i)), pid,
     #         N, t, 1, make_bc(i), reliableBroadcastReceiveQueue[i].get).start()
     if not i in receivedChannelsFlags:
         receivedChannelsFlags.append(i)
         # mylog('B[%d]binary consensus_%d_starts with 1 at %f' % (pid, i, time.time()), verboseLevel=-1)
         greenletPacker(
             Greenlet(binary_consensus, i, pid, N, t, 1,
                      decideChannel[i], make_bc(i),
                      reliableBroadcastReceiveQueue[i].get),
             'acs.callbackFactory.binary_consensus',
             (pid, N, t, Q, broadcast, receive)).start()
Esempio n. 7
0
def includeTransaction(pid, N, t, setToInclude, broadcast, receive, send):
    CBChannel = Queue()
    ACSChannel = Queue()
    TXSet = [{} for _ in range(N)]

    def make_bc_br(i):
        def _bc_br(m):
            broadcast(('B', m))
        return _bc_br

    def make_acs_br(i):
        def _acs_br(m):
            broadcast(('A', m))
        return _acs_br

    def make_bc_send(i):
        def _layer_send(j, m):
            send(j, ('B', m))
        return _layer_send

    def _listener():
        while True:
            sender, (tag, m) = receive()
            if tag == 'B':
                greenletPacker(Greenlet(CBChannel.put, (sender, m)),
                    'includeTransaction.CBChannel.put', (pid, N, t, setToInclude, broadcast, receive)).start()
            elif tag == 'A':
                greenletPacker(Greenlet(ACSChannel.put,
                    (sender, m)
                ), 'includeTransaction.ACSChannel.put', (pid, N, t, setToInclude, broadcast, receive)).start()

    outputChannel = [Queue(1) for _ in range(N)]

    def outputCallBack(i):
        TXSet[i] = outputChannel[i].get()
        monitoredIntList[i].data = 1

    for i in range(N):
        greenletPacker(Greenlet(outputCallBack, i),
            'includeTransaction.outputCallBack', (pid, N, t, setToInclude, broadcast, receive)).start()

    def callbackFactoryACS():
        def _callback(commonSet):  # now I know player j has succeeded in broadcasting
            locker.put(commonSet)
        return _callback

    greenletPacker(Greenlet(_listener),
        'includeTransaction._listener', (pid, N, t, setToInclude, broadcast, receive)).start()

    locker = Queue(1)
    includeTransaction.callbackCounter = 0
    monitoredIntList = [MonitoredInt() for _ in range(N)]

    greenletPacker(Greenlet(consensusBroadcast, pid, N, t, setToInclude, make_bc_br(pid), CBChannel.get, outputChannel, make_bc_send(pid)),
        'includeTransaction.consensusBroadcast', (pid, N, t, setToInclude, broadcast, receive)).start()
    greenletPacker(Greenlet(callBackWrap(acs, callbackFactoryACS()), pid, N, t, monitoredIntList, make_acs_br(pid), ACSChannel.get),
        'includeTransaction.callBackWrap(acs, callbackFactoryACS())', (pid, N, t, setToInclude, broadcast, receive)).start()

    commonSet = locker.get()
    return commonSet, TXSet
def includeTransaction(pid, N, t, setToInclude, broadcast, receive, send):
    CBChannel = Queue()
    ACSChannel = Queue()
    TXSet = [{} for _ in range(N)]

    def make_bc_br(i):
        def _bc_br(m):
            broadcast(('B', m))
        return _bc_br

    def make_acs_br(i):
        def _acs_br(m):
            broadcast(('A', m))
        return _acs_br

    def make_bc_send(i):
        def _layer_send(j, m):
            send(j, ('B', m))
        return _layer_send

    def _listener():
        while True:
            sender, (tag, m) = receive()
            if tag == 'B':
                greenletPacker(Greenlet(CBChannel.put, (sender, m)),
                    'includeTransaction.CBChannel.put', (pid, N, t, setToInclude, broadcast, receive)).start()
            elif tag == 'A':
                greenletPacker(Greenlet(ACSChannel.put,
                    (sender, m)
                ), 'includeTransaction.ACSChannel.put', (pid, N, t, setToInclude, broadcast, receive)).start()

    outputChannel = [Queue(1) for _ in range(N)]

    def outputCallBack(i):
        TXSet[i] = outputChannel[i].get()
        monitoredIntList[i].data = 1

    for i in range(N):
        greenletPacker(Greenlet(outputCallBack, i),
            'includeTransaction.outputCallBack', (pid, N, t, setToInclude, broadcast, receive)).start()

    def callbackFactoryACS():
        def _callback(commonSet):  # now I know player j has succeeded in broadcasting
            locker.put(commonSet)
        return _callback

    greenletPacker(Greenlet(_listener),
        'includeTransaction._listener', (pid, N, t, setToInclude, broadcast, receive)).start()

    locker = Queue(1)
    includeTransaction.callbackCounter = 0
    monitoredIntList = [MonitoredInt() for _ in range(N)]

    greenletPacker(Greenlet(consensusBroadcast, pid, N, t, setToInclude, make_bc_br(pid), CBChannel.get, outputChannel, make_bc_send(pid)),
        'includeTransaction.consensusBroadcast', (pid, N, t, setToInclude, broadcast, receive)).start()
    greenletPacker(Greenlet(callBackWrap(acs, callbackFactoryACS()), pid, N, t, monitoredIntList, make_acs_br(pid), ACSChannel.get),
        'includeTransaction.callBackWrap(acs, callbackFactoryACS())', (pid, N, t, setToInclude, broadcast, receive)).start()

    commonSet = locker.get()
    return commonSet, TXSet
Esempio n. 9
0
def shared_coin(instance, pid, N, t, broadcast, receive):
    '''
    A dummy version of the Shared Coin
    :param pid: my id number
    :param N: the number of parties
    :param t: the number of byzantine parties
    :param broadcast: broadcast channel
    :param receive: receive channel
    :return: yield values b
    '''
    received = defaultdict(set)
    outputQueue = defaultdict(lambda: Queue(1))
    PK, SKs = getKeys()

    def _recv():
        while True:
            # New shares for some round r
            (i, (r, sig)) = receive()
            assert i in range(N)
            assert r >= 0
            received[r].add((i, serialize(sig)))

            # After reaching the threshold, compute the output and
            # make it available locally
            if len(received[r]) == t + 1:
                h = PK.hash_message(str((r, instance)))

                def tmpFunc(r, t):
                    combine_and_verify(
                        h,
                        dict(
                            tuple((t, deserialize1(sig))
                                  for t, sig in received[r])[:t + 1]))
                    outputQueue[r].put(ord(serialize(h)[0])
                                       & 1)  # explicitly convert to int

                Greenlet(tmpFunc, r, t).start()

    greenletPacker(Greenlet(_recv), 'shared_coin_dummy',
                   (pid, N, t, broadcast, receive)).start()

    def getCoin(round):
        broadcast((round, SKs[pid].sign(PK.hash_message(str(
            (round, instance))))))  # I have to do mapping to 1..l
        return outputQueue[round].get()

    return getCoin
Esempio n. 10
0
def random_delay_acs(N, t, inputs):

    assert (isinstance(inputs, list))

    maxdelay = 0.01

    # Instantiate the "broadcast" instruction
    def makeBroadcast(i):
        def _broadcast(v):
            def _deliver(j):
                buffers[j].put((i, v))

            for j in range(N):
                greenletPacker(
                    Greenlet(_deliver, j), 'random_delay_acs._deliver',
                    (N, t, inputs)).start_later(random.random() * maxdelay)

        return _broadcast

    def modifyMonitoredInt(monitoredInt):
        monitoredInt.data = 1

    while True:
        initBeforeBinaryConsensus()
        buffers = map(lambda _: Queue(1), range(N))
        ts = []
        for i in range(N):
            bc = makeBroadcast(i)
            recv = buffers[i].get
            input_clone = [MonitoredInt() for _ in range(N)]
            for j in range(N):
                greenletPacker(Greenlet(modifyMonitoredInt, input_clone[j]),
                               'random_delay_acs.modifyMonitoredInt',
                               (N, t, inputs)).start_later(maxdelay *
                                                           random.random())
            th = greenletPacker(Greenlet(acs, i, N, t, input_clone, bc, recv),
                                'random_delay_acs.acs', (N, t, inputs))
            th.start(
            )  # start_later(random.random() * maxdelay) is not necessary here
            ts.append(th)

        #if True:
        try:
            gevent.joinall(ts)
            break
        except gevent.hub.LoopExit:  # Manual fix for early stop
            print "End"
Esempio n. 11
0
def random_delay_acs(N, t, inputs):

    assert(isinstance(inputs, list))

    maxdelay = 0.01

    # Instantiate the "broadcast" instruction
    def makeBroadcast(i):
        def _broadcast(v):
           def _deliver(j):
               buffers[j].put((i,v))

           for j in range(N):
               greenletPacker(Greenlet(_deliver, j),
                   'random_delay_acs._deliver', (N, t, inputs)).start_later(random.random()*maxdelay)

        return _broadcast

    def modifyMonitoredInt(monitoredInt):
        monitoredInt.data = 1

    while True:
        initBeforeBinaryConsensus()
        buffers = map(lambda _: Queue(1), range(N))
        ts = []
        for i in range(N):
            bc = makeBroadcast(i)
            recv = buffers[i].get
            input_clone = [MonitoredInt() for _ in range(N)]
            for j in range(N):
                greenletPacker(Greenlet(modifyMonitoredInt, input_clone[j]),
                    'random_delay_acs.modifyMonitoredInt', (N, t, inputs)).start_later(maxdelay * random.random())
            th = greenletPacker(Greenlet(acs, i, N, t, input_clone, bc, recv), 'random_delay_acs.acs', (N, t, inputs))
            th.start() # start_later(random.random() * maxdelay) is not necessary here
            ts.append(th)

        #if True:
        try:
            gevent.joinall(ts)
            break
        except gevent.hub.LoopExit: # Manual fix for early stop
            print "End"
Esempio n. 12
0
def shared_coin(instance, pid, N, t, broadcast, receive):
    '''
    A dummy version of the Shared Coin
    :param pid: my id number
    :param N: the number of parties
    :param t: the number of byzantine parties
    :param broadcast: broadcast channel
    :param receive: receive channel
    :return: yield values b
    '''
    received = defaultdict(set)
    outputQueue = defaultdict(lambda: Queue(1))
    PK, SKs = getKeys()
    def _recv():
        while True:
            # New shares for some round r
            (i, (r, sig)) = receive()
            assert i in range(N)
            assert r >= 0
            received[r].add((i, serialize(sig)))

            # After reaching the threshold, compute the output and
            # make it available locally
            if len(received[r]) == t + 1:
                    h = PK.hash_message(str((r, instance)))
                    def tmpFunc(r, t):
                        combine_and_verify(h, dict(tuple((t, deserialize1(sig)) for t, sig in received[r])[:t+1]))
                        outputQueue[r].put(ord(serialize(h)[0]) & 1)  # explicitly convert to int
                    Greenlet(
                        tmpFunc, r, t
                    ).start()

    greenletPacker(Greenlet(_recv), 'shared_coin_dummy', (pid, N, t, broadcast, receive)).start()

    def getCoin(round):
        broadcast((round, SKs[pid].sign(PK.hash_message(str((round,instance))))))  # I have to do mapping to 1..l
        return outputQueue[round].get()

    return getCoin
Esempio n. 13
0
 def _recv():
     while True:  #not finished[pid]:
         (i, (tag, m)) = receive()
         if tag == 'B':
             # Broadcast message
             r, msg = m
             greenletPacker(Greenlet(bcQ[r].put, (i, msg)),
                 'binary_consensus.bcQ[%d].put' % r, (pid, N, t, vi, decide, broadcast, receive)).start() # In case they block the router
         elif tag == 'C':
             # A share of a coin
             greenletPacker(Greenlet(coinQ.put, (i, m)),
                 'binary_consensus.coinQ.put', (pid, N, t, vi, decide, broadcast, receive)).start()
         elif tag == 'A':
             # Aux message
             r, msg = m
             greenletPacker(Greenlet(auxQ[r].put, (i, msg)),
                   'binary_consensus.auxQ[%d].put' % r, (pid, N, t, vi, decide, broadcast, receive)).start()
             pass
Esempio n. 14
0
 def _recv():
     while True:  #not finished[pid]:
         (i, (tag, m)) = receive()
         if tag == 'B':
             # Broadcast message
             r, msg = m
             greenletPacker(Greenlet(bcQ[r].put, (i, msg)),
                 'binary_consensus.bcQ[%d].put' % r, (pid, N, t, vi, decide, broadcast, receive)).start() # In case they block the router
         elif tag == 'C':
             # A share of a coin
             greenletPacker(Greenlet(coinQ.put, (i, m)),
                 'binary_consensus.coinQ.put', (pid, N, t, vi, decide, broadcast, receive)).start()
         elif tag == 'A':
             # Aux message
             r, msg = m
             greenletPacker(Greenlet(auxQ[r].put, (i, msg)),
                   'binary_consensus.auxQ[%d].put' % r, (pid, N, t, vi, decide, broadcast, receive)).start()
             pass
Esempio n. 15
0
 def _release():
     greenletPacker(
         Greenlet(garbageCleaner,
                  channel), 'binary_consensus.garbageCleaner',
         (pid, N, t, vi, decide, broadcast, receive)).start()
Esempio n. 16
0
def binary_consensus(instance, pid, N, t, vi, decide, broadcast, receive):
    '''
    Binary consensus from [MMR 13]. It takes an input vi and will finally write the decided value into _decide_ channel.
    :param pid: my id number
    :param N: the number of parties
    :param t: the number of byzantine parties
    :param vi: input value, an integer
    :param decide: deciding channel
    :param broadcast: broadcast channel
    :param receive: receive channel
    :return:
    '''
    #print "********************Sisi step 5: BA,pid: %s, instance: %d******************"%(pid, instance)
    # Messages received are routed to either a shared coin, the broadcast, or AUX
    coinQ = Queue(1)
    bcQ = defaultdict(lambda: Queue(1))
    auxQ = defaultdict(lambda: Queue(1))

    def _recv():
        while True:  #not finished[pid]:
            (i, (tag, m)) = receive()
            if tag == 'B':
                # Broadcast message
                r, msg = m
                greenletPacker(
                    Greenlet(bcQ[r].put,
                             (i, msg)), 'binary_consensus.bcQ[%d].put' % r,
                    (pid, N, t, vi, decide, broadcast,
                     receive)).start()  # In case they block the router
            elif tag == 'C':
                # A share of a coin
                greenletPacker(
                    Greenlet(coinQ.put, (i, m)), 'binary_consensus.coinQ.put',
                    (pid, N, t, vi, decide, broadcast, receive)).start()
            elif tag == 'A':
                # Aux message
                r, msg = m
                greenletPacker(
                    Greenlet(auxQ[r].put,
                             (i, msg)), 'binary_consensus.auxQ[%d].put' % r,
                    (pid, N, t, vi, decide, broadcast, receive)).start()
                pass

    greenletPacker(Greenlet(_recv), 'binary_consensus._recv',
                   (pid, N, t, vi, decide, broadcast, receive)).start()

    def brcast_get(r):
        def _recv(*args, **kargs):
            return bcQ[r].get(*args, **kargs)

        return _recv

    received = [defaultdict(set), defaultdict(set)]

    coin = shared_coin(instance, pid, N, t,
                       makeBroadcastWithTag('C', broadcast), coinQ.get)

    def getWithProcessing(r, binValues, callBackWaiter):
        def _recv(*args, **kargs):
            sender, v = auxQ[r].get(*args, **kargs)
            assert v in (0, 1)
            assert sender in range(N)
            received[v][r].add(sender)
            # Check if conditions are satisfied
            threshold = N - t  # 2*t + 1 # N - t
            if True:  #not finished[pid]:
                if len(binValues) == 1:
                    if len(received[binValues[0]]
                           [r]) >= threshold and not callBackWaiter[r].full():
                        # Check passed
                        callBackWaiter[r].put(binValues)
                elif len(binValues) == 2:
                    if len(received[0][r].union(received[1][r])
                           ) >= threshold and not callBackWaiter[r].full():
                        callBackWaiter[r].put(binValues)
                    elif len(received[0][r]
                             ) >= threshold and not callBackWaiter[r].full():
                        callBackWaiter[r].put([0])
                    elif len(received[1][r]
                             ) >= threshold and not callBackWaiter[r].full():
                        callBackWaiter[r].put([1])
            return sender, v

        return _recv

    round = 0
    est = vi
    decided = False
    decidedNum = 0

    callBackWaiter = defaultdict(lambda: Queue(1))

    while True:  # checkFinishedWithGlobalState(N): <- for distributed experiment we don't need this
        round += 1
        # Broadcast EST
        # TODO: let bv_broadcast receive
        bvOutputHolder = Queue(2)  # 2 possible values
        binValues = []

        def bvOutput(m):
            if not m in binValues:
                binValues.append(m)
                bvOutputHolder.put(m)

        def getRelease(channel):
            def _release():
                greenletPacker(
                    Greenlet(garbageCleaner,
                             channel), 'binary_consensus.garbageCleaner',
                    (pid, N, t, vi, decide, broadcast, receive)).start()

            return _release

        br1 = greenletPacker(
            Greenlet(
                bv_broadcast(
                    pid, N, t,
                    makeBroadcastWithTagAndRound('B', broadcast, round),
                    brcast_get(round), bvOutput, getRelease(bcQ[round])), est),
            'binary_consensus.bv_broadcast(%d, %d, %d)' % (pid, N, t),
            (pid, N, t, vi, decide, broadcast, receive))
        br1.start()
        w = bvOutputHolder.get()  # Wait until output is not empty

        broadcast(('A', (round, w)))
        greenletPacker(
            Greenlet(
                loopWrapper(getWithProcessing(round, binValues,
                                              callBackWaiter))),
            'binary_consensus.loopWrapper(getWithProcessing(round, binValues, callBackWaiter))',
            (pid, N, t, vi, decide, broadcast, receive)).start()

        values = callBackWaiter[round].get(
        )  # wait until the conditions are satisfied
        s = coin(round)
        # Here corresponds to a proof that if one party decides at round r,
        # then in all the following rounds, everybody will propose r as an estimation. (Lemma 2, Lemma 1)
        # An abandoned party is a party who has decided but no enough peers to help him end the loop.
        # Lemma: # of abandoned party <= t
        if decided and decidedNum == s:  # infinite-message fix
            break
        if len(values) == 1:
            if values[0] == s:
                # decide s
                if not decided:
                    globalState[pid] = "%d" % s
                    decide.put(s)
                    decided = True
                    decidedNum = s

            else:
                pass
                # mylog('[%d] advances rounds from %d caused by values[0](%d)!=s(%d)' % (pid, round, values[0], s), verboseLevel=-1)
            est = values[0]
        else:
            # mylog('[%d] advances rounds from %d caused by len(values)>1 where values=%s' % (pid, round, repr(values)), verboseLevel=-1)
            est = s
Esempio n. 17
0
def mv84consensus(pid, N, t, vi, broadcast, receive):
    '''
    Implementation of the multivalue consensus of [TURPIN, COAN, 1984]
    This will achieve a consensus among all the inputs provided by honest parties,
    or raise an alert if failed to achieve one.
    :param pid: my id number
    :param N: the number of parties
    :param t: the number of byzantine parties
    :param vi: input value, an integer
    :param broadcast: broadcast channel
    :param receive: receive channel
    :return: decided value or 0 (default value if failed to reach a concensus)
    '''
    # initialize v and p (same meaning as in the paper)
    mv84v = defaultdict(lambda: 'Empty')
    mv84p = defaultdict(lambda: False)
    # Initialize the locks and local variables
    mv84WaiterLock = Queue()
    mv84WaiterLock2 = Queue()
    mv84ReceiveDiff = set()
    mv84GetPerplex = set()
    reliableBroadcastReceiveQueue = Queue()

    def _listener():  # Hard-working Router for this layer
        while True:
            sender, (tag, m) = receive()
            if tag == 'V':
                mv84v[sender] = m
                if m != vi:
                    mv84ReceiveDiff.add(sender)
                    if len(mv84ReceiveDiff) >= (N - t) / 2.0:
                        mv84WaiterLock.put(True)
                # Fast-Stop: We don't need to wait for the rest (possibly)
                # malicious parties.
                if len(mv84v.keys()) >= N - t:
                    mv84WaiterLock.put(False)
            elif tag == 'B':
                mv84p[sender] = m
                if m:
                    mv84GetPerplex.add(sender)
                    if len(mv84GetPerplex) >= N - 2 * t:
                        mv84WaiterLock2.put(True)
                # Fast-Stop: We don't need to wait for the rest (possibly)
                # malicious parties.
                if len(mv84p.keys()) >= N - t:
                    mv84WaiterLock2.put(False)
            else:  # Re-route the msg to inner layer
                reliableBroadcastReceiveQueue.put((sender, (tag, m)))

    greenletPacker(Greenlet(_listener), 'mv84consensus._listener',
                   (pid, N, t, vi, broadcast, receive)).start()

    makeBroadcastWithTag('V', broadcast)(vi)
    perplexed = mv84WaiterLock.get()  # See if I am perplexed

    makeBroadcastWithTag('B', broadcast)(perplexed)
    alert = mv84WaiterLock2.get() and 1 or 0  # See if we should alert

    decideChannel = Queue(1)
    greenletPacker(
        Greenlet(binary_consensus, pid, N, t, alert, decideChannel, broadcast,
                 reliableBroadcastReceiveQueue.get),
        'mv84consensus.binary_consensus',
        (pid, N, t, vi, broadcast, receive)).start()
    agreedAlert = decideChannel.get()

    if agreedAlert:
        return 0  # some pre-defined default consensus value
    else:
        return vi
Esempio n. 18
0
def acs(pid, N, t, Q, broadcast, receive):
    assert (isinstance(Q, list))
    assert (len(Q) == N)
    decideChannel = [Queue(1) for _ in range(N)]
    receivedChannelsFlags = []

    def callbackFactory(i):
        def _callback(val):  # Get notified for i
            # Greenlet(callBackWrap(binary_consensus, callbackFactory(i)), pid,
            #         N, t, 1, make_bc(i), reliableBroadcastReceiveQueue[i].get).start()
            if not i in receivedChannelsFlags:
                receivedChannelsFlags.append(i)
                # mylog('B[%d]binary consensus_%d_starts with 1 at %f' % (pid, i, time.time()), verboseLevel=-1)
                greenletPacker(
                    Greenlet(binary_consensus, i, pid, N, t, 1,
                             decideChannel[i], make_bc(i),
                             reliableBroadcastReceiveQueue[i].get),
                    'acs.callbackFactory.binary_consensus',
                    (pid, N, t, Q, broadcast, receive)).start()

        return _callback

    for i, q in enumerate(Q):
        assert (isinstance(q, MonitoredInt))
        q.registerSetCallBack(callbackFactory(i))

    def make_bc(i):
        def _bc(m):
            broadcast((i, m))

        return _bc

    reliableBroadcastReceiveQueue = [Queue() for x in range(N)]

    def _listener():
        while True:
            sender, (instance, m) = receive()
            reliableBroadcastReceiveQueue[instance].put((sender, m))

    greenletPacker(Greenlet(_listener), 'acs._listener',
                   (pid, N, t, Q, broadcast, receive)).start()

    BA = [0] * N
    locker = Queue(1)
    locker2 = Queue(1)
    callbackCounter = [0]

    def listenerFactory(i, channel):
        def _listener():
            BA[i] = channel.get()
            if callbackCounter[0] >= 2 * t and (not locker2.full()):
                locker2.put("Key")  # Now we've got 2t+1 1's
            callbackCounter[0] += 1
            if callbackCounter[0] == N and (
                    not locker.full()):  # if we have all of them responded
                locker.put("Key")

        return _listener

    for i in range(N):
        greenletPacker(Greenlet(listenerFactory(i, decideChannel[i])),
                       'acs.listenerFactory(i, decideChannel[i])',
                       (pid, N, t, Q, broadcast, receive)).start()

    locker2.get()
    # Now we feed 0 to all the other binary consensus protocols
    for i in range(N):
        if not i in receivedChannelsFlags:
            receivedChannelsFlags.append(i)
            greenletPacker(
                Greenlet(binary_consensus, i, pid, N, t, 0, decideChannel[i],
                         make_bc(i), reliableBroadcastReceiveQueue[i].get),
                'acs.binary_consensus',
                (pid, N, t, Q, broadcast, receive)).start()
    locker.get()  # Now we can check'''
    BA = checkBA(BA, N, t)
    return BA
Esempio n. 19
0
def multiSigBr(pid, N, t, msg, broadcast, receive, outputs, send):
    # Since all the parties we have are symmetric, so I implement this function for N instances of A-cast as a whole
    # Here msg is a set of transactions
    assert(isinstance(outputs, list))
    for i in outputs:
        assert(isinstance(i, Queue))

    keys = getECDSAKeys()
    Threshold = N - 2 * t
    Threshold2 = N - t
    zfecEncoder = zfec.Encoder(Threshold, N)
    zfecDecoder = zfec.Decoder(Threshold, N)

    def merkleTree(strList, someHash = coolSHA256Hash):
        # someHash is a mapping from a int to a int
        treeLength = 2 ** ceil(math.log(len(strList)) / math.log(2))
        mt = [0] * (treeLength * 2)  # find a place to put our leaves
        for i in range(len(strList)):
            mt[i + treeLength] = someHash(strList[i])  # TODO: need to change strList[i] from a string to an integer here.
        for i in range(treeLength - 1, 0, -1):  # 1, 2, 3, ..., treeLength - 1
            # mt[i] = someHash(''.join([chr(ord(a) ^ ord(b)) for a, b in zip(mt[i*2], mt[i*2+1])]))  # XOR is commutative
            mt[i] = someHash(mt[i*2] + mt[i*2+1])  # concat is not commutative
        return mt

    def getMerkleBranch(index, mt):
        res = []
        t = index + (len(mt) >> 1)
        while t > 1:
            res.append(mt[t ^ 1])  # we are picking up the sibling
            t /= 2
        return res

    def merkleVerify(val, rootHash, branch, someHash, index):
        # index has information on whether we are facing a left sibling or a right sibling
        tmp = someHash(val)
        tindex = index
        for br in branch:
            tmp = someHash((tindex & 1) and br + tmp or tmp + br)
            tindex >>= 1
        if tmp != rootHash:
            print "Verification failed with", someHash(val), rootHash, branch, tmp == rootHash
        return tmp == rootHash

    def Listener():
        opinions = [defaultdict(lambda: 0) for _ in range(N)]
        rootHashes = dict()
        readyCounter = [defaultdict(lambda: 0) for _ in range(N)]
        signed = [False]*N
        readySent = [False] * N
        reconstDone = [False] * N
        while True:  # main loop
            sender, msgBundle = receive()
            if msgBundle[0] == 'i' and not signed[sender]:
                if keys[sender].verify(sha1hash(''.join([msgBundle[1][0], msgBundle[1][1], ''.join(msgBundle[1][2])])), msgBundle[2]):
                    assert isinstance(msgBundle[1], tuple)
                    if not merkleVerify(msgBundle[1][0], msgBundle[1][1], msgBundle[1][2], coolSHA256Hash, pid):
                        continue
                    if sender in rootHashes:
                        if rootHashes[sender]!= msgBundle[1][1]:
                            print "Cheating caught, exiting"
                            sys.exit(0)
                    else:
                        rootHashes[sender] = msgBundle[1][1]
                    newBundle = (sender, msgBundle[1][0], msgBundle[1][1], msgBundle[1][2])  # assert each frag has a length of step
                    broadcast(('e', newBundle, keys[pid].sign(
                        sha1hash(''.join([str(newBundle[0]), newBundle[1], newBundle[2], ''.join(newBundle[3])]))
                    )))
                    signed[sender] = True
                else:
                    raise ECDSASignatureError()
            elif msgBundle[0] == 'e':
                if keys[sender].verify(sha1hash(''.join([str(msgBundle[1][0]), msgBundle[1][1], msgBundle[1][2], ''.join(msgBundle[1][3])])), msgBundle[2]):
                    originBundle = msgBundle[1]
                    if not merkleVerify(originBundle[1], originBundle[2], originBundle[3], coolSHA256Hash, sender):
                        continue
                    if originBundle[0] in rootHashes:
                        if rootHashes[originBundle[0]]!= originBundle[2]:
                            print "Cheating caught, exiting"
                            sys.exit(0)
                    else:
                        rootHashes[originBundle[0]] = originBundle[2]
                    opinions[originBundle[0]][sender] = originBundle[1]   # We are going to move this part to kekeketktktktk
                    if len(opinions[originBundle[0]]) >= Threshold2 and not readySent[originBundle[0]]:
                            readySent[originBundle[0]] = True
                            broadcast(('r', originBundle[0], originBundle[2]))  # We are broadcasting its hash
                else:
                    raise ECDSASignatureError()
            elif msgBundle[0] == 'r':
                readyCounter[msgBundle[1]][msgBundle[2]] += 1
                tmp = readyCounter[msgBundle[1]][msgBundle[2]]
                if tmp >= t+1 and not readySent[msgBundle[1]]:
                    readySent[msgBundle[1]] = True
                    broadcast(('r', msgBundle[1], msgBundle[2]))
                if tmp >= Threshold2 and not outputs[msgBundle[1]].full() and \
                        not reconstDone[msgBundle[1]] and len(opinions[msgBundle[1]]) >= Threshold:
                    reconstDone[msgBundle[1]] = True
                    if msgBundle[1] in rootHashes:
                        if rootHashes[msgBundle[1]]!= msgBundle[2]:
                            print "Cheating caught, exiting"
                            sys.exit(0)
                    else:
                        rootHashes[msgBundle[1]] = msgBundle[2]
                    if opinions[msgBundle[1]].values()[0] == '':
                        reconstruction = ['']
                    else:
                        reconstruction = zfecDecoder.decode(opinions[msgBundle[1]].values()[:Threshold],
                                opinions[msgBundle[1]].keys()[:Threshold])  # We only take the first [Threshold] fragments
                    rawbuf = ''.join(reconstruction)
                    buf = rawbuf[:-ord(rawbuf[-1])]
                    # Check root hash
                    step = len(buf) / Threshold + 1 # len(buf) % Threshold == 0 and len(buf) / Threshold or (len(buf) / Threshold + 1)
                    assert step * Threshold - len(buf) < 256  # assumption
                    buf_ = buf.ljust(step * Threshold - 1, '\xFF') + chr(step * Threshold - len(buf))
                    fragList = [buf_[i*step : (i+1)*step] for i in range(Threshold)]
                    encodedFragList = zfecEncoder.encode(fragList)
                    mt = merkleTree(encodedFragList, coolSHA256Hash)
                    assert rootHashes[msgBundle[1]] == mt[1]  # full binary tree
                    if outputs[msgBundle[1]].empty():
                        outputs[msgBundle[1]].put(buf)

    greenletPacker(Greenlet(Listener), 'multiSigBr.Listener', (pid, N, t, msg, broadcast, receive, outputs)).start()
    buf = msg  # We already assumed the proposals are byte strings

    step = len(buf) / Threshold + 1 # len(buf) % Threshold == 0 and len(buf) / Threshold or (len(buf) / Threshold + 1)
    assert step * Threshold - len(buf) < 256  # assumption
    buf = buf.ljust(step * Threshold - 1, '\xFF') + chr(step * Threshold - len(buf))
    fragList = [buf[i*step : (i+1)*step] for i in range(Threshold)]
    encodedFragList = zfecEncoder.encode(fragList)
    mt = merkleTree(encodedFragList, coolSHA256Hash)
    rootHash = mt[1]  # full binary tree
    for i in range(N):
        mb = getMerkleBranch(i, mt)  # notice that index starts from 1 and pid starts from 0
        newBundle = (encodedFragList[i], rootHash, mb)
        send(i, ('i', newBundle, keys[pid].sign(sha1hash(''.join([newBundle[0], newBundle[1], ''.join(newBundle[2])])))))
Esempio n. 20
0
def acs(pid, N, t, Q, broadcast, receive):
    assert(isinstance(Q, list))
    assert(len(Q) == N)
    decideChannel = [Queue(1) for _ in range(N)]
    receivedChannelsFlags = []

    def callbackFactory(i):
        def _callback(val): # Get notified for i
            # Greenlet(callBackWrap(binary_consensus, callbackFactory(i)), pid,
            #         N, t, 1, make_bc(i), reliableBroadcastReceiveQueue[i].get).start()
            if not i in receivedChannelsFlags:
                receivedChannelsFlags.append(i)
                # mylog('B[%d]binary consensus_%d_starts with 1 at %f' % (pid, i, time.time()), verboseLevel=-1)
                greenletPacker(Greenlet(binary_consensus, i, pid,
                    N, t, 1, decideChannel[i], make_bc(i), reliableBroadcastReceiveQueue[i].get),
                        'acs.callbackFactory.binary_consensus', (pid, N, t, Q, broadcast, receive)).start()
        return _callback

    for i, q in enumerate(Q):
        assert(isinstance(q, MonitoredInt))
        q.registerSetCallBack(callbackFactory(i))

    def make_bc(i):
        def _bc(m):
            broadcast(
                (i, m)
            )
        return _bc

    reliableBroadcastReceiveQueue = [Queue() for x in range(N)]

    def _listener():
        while True:
            sender, (instance, m) = receive()
            reliableBroadcastReceiveQueue[instance].put(
                    (sender, m)
                )

    greenletPacker(Greenlet(_listener), 'acs._listener', (pid, N, t, Q, broadcast, receive)).start()

    BA = [0]*N
    locker = Queue(1)
    locker2 = Queue(1)
    callbackCounter = [0]

    def listenerFactory(i, channel):
        def _listener():
            BA[i] = channel.get()
            if callbackCounter[0] >= 2*t and (not locker2.full()):
                        locker2.put("Key")  # Now we've got 2t+1 1's
            callbackCounter[0] += 1
            if callbackCounter[0] == N and (not locker.full()):  # if we have all of them responded
                        locker.put("Key")
        return _listener

    for i in range(N):
        greenletPacker(Greenlet(listenerFactory(i, decideChannel[i])),
            'acs.listenerFactory(i, decideChannel[i])', (pid, N, t, Q, broadcast, receive)).start()

    locker2.get()
    # Now we feed 0 to all the other binary consensus protocols
    for i in range(N):
        if not i in receivedChannelsFlags:
            receivedChannelsFlags.append(i)
            greenletPacker(Greenlet(binary_consensus, i, pid, N, t, 0,
                     decideChannel[i], make_bc(i), reliableBroadcastReceiveQueue[i].get),
                           'acs.binary_consensus', (pid, N, t, Q, broadcast, receive)).start()
    locker.get()  # Now we can check'''
    BA = checkBA(BA, N, t)
    return BA
Esempio n. 21
0
def mv84consensus(pid, N, t, vi, broadcast, receive):
    '''
    Implementation of the multivalue consensus of [TURPIN, COAN, 1984]
    This will achieve a consensus among all the inputs provided by honest parties,
    or raise an alert if failed to achieve one.
    :param pid: my id number
    :param N: the number of parties
    :param t: the number of byzantine parties
    :param vi: input value, an integer
    :param broadcast: broadcast channel
    :param receive: receive channel
    :return: decided value or 0 (default value if failed to reach a concensus)
    '''
    # initialize v and p (same meaning as in the paper)
    mv84v = defaultdict(lambda: 'Empty')
    mv84p = defaultdict(lambda: False)
    # Initialize the locks and local variables
    mv84WaiterLock = Queue()
    mv84WaiterLock2 = Queue()
    mv84ReceiveDiff = set()
    mv84GetPerplex = set()
    reliableBroadcastReceiveQueue = Queue()

    def _listener():  # Hard-working Router for this layer
        while True:
            sender, (tag, m) = receive()
            if tag == 'V':
                mv84v[sender] = m
                if m != vi:
                    mv84ReceiveDiff.add(sender)
                    if len(mv84ReceiveDiff) >= (N - t) / 2.0:
                        mv84WaiterLock.put(True)
                # Fast-Stop: We don't need to wait for the rest (possibly)
                # malicious parties.
                if len(mv84v.keys()) >= N - t:
                    mv84WaiterLock.put(False)
            elif tag == 'B':
                mv84p[sender] = m
                if m:
                    mv84GetPerplex.add(sender)
                    if len(mv84GetPerplex) >= N - 2 * t:
                        mv84WaiterLock2.put(True)
                # Fast-Stop: We don't need to wait for the rest (possibly)
                # malicious parties.
                if len(mv84p.keys()) >= N - t:
                    mv84WaiterLock2.put(False)
            else:  # Re-route the msg to inner layer
                reliableBroadcastReceiveQueue.put(
                    (sender, (tag, m))
                )

    greenletPacker(Greenlet(_listener), 'mv84consensus._listener', (pid, N, t, vi, broadcast, receive)).start()

    makeBroadcastWithTag('V', broadcast)(vi)
    perplexed = mv84WaiterLock.get()  # See if I am perplexed

    makeBroadcastWithTag('B', broadcast)(perplexed)
    alert = mv84WaiterLock2.get() and 1 or 0  # See if we should alert


    decideChannel = Queue(1)
    greenletPacker(Greenlet(binary_consensus, pid, N, t, alert, decideChannel, broadcast, reliableBroadcastReceiveQueue.get),
        'mv84consensus.binary_consensus', (pid, N, t, vi, broadcast, receive)).start()
    agreedAlert = decideChannel.get()

    if agreedAlert:
        return 0  # some pre-defined default consensus value
    else:
        return vi
Esempio n. 22
0
def multiSigBr(pid, N, t, msg, broadcast, receive, outputs, send):
    # Since all the parties we have are symmetric, so I implement this function for N instances of A-cast as a whole
    # Here msg is a set of transactions
    assert (isinstance(outputs, list))
    for i in outputs:
        assert (isinstance(i, Queue))

    keys = getECDSAKeys()
    Threshold = N - 2 * t
    Threshold2 = N - t
    zfecEncoder = zfec.Encoder(Threshold, N)
    zfecDecoder = zfec.Decoder(Threshold, N)

    def merkleTree(strList, someHash=coolSHA256Hash):
        # someHash is a mapping from a int to a int
        treeLength = 2**ceil(math.log(len(strList)) / math.log(2))
        mt = [0] * (treeLength * 2)  # find a place to put our leaves
        for i in range(len(strList)):
            mt[i + treeLength] = someHash(
                strList[i]
            )  # TODO: need to change strList[i] from a string to an integer here.
        for i in range(treeLength - 1, 0, -1):  # 1, 2, 3, ..., treeLength - 1
            # mt[i] = someHash(''.join([chr(ord(a) ^ ord(b)) for a, b in zip(mt[i*2], mt[i*2+1])]))  # XOR is commutative
            mt[i] = someHash(mt[i * 2] +
                             mt[i * 2 + 1])  # concat is not commutative
        return mt

    def getMerkleBranch(index, mt):
        res = []
        t = index + (len(mt) >> 1)
        while t > 1:
            res.append(mt[t ^ 1])  # we are picking up the sibling
            t /= 2
        return res

    def merkleVerify(val, rootHash, branch, someHash, index):
        # index has information on whether we are facing a left sibling or a right sibling
        tmp = someHash(val)
        tindex = index
        for br in branch:
            tmp = someHash((tindex & 1) and br + tmp or tmp + br)
            tindex >>= 1
        if tmp != rootHash:
            print "Verification failed with", someHash(
                val), rootHash, branch, tmp == rootHash
        return tmp == rootHash

    def Listener():
        opinions = [defaultdict(lambda: 0) for _ in range(N)]
        rootHashes = dict()
        readyCounter = [defaultdict(lambda: 0) for _ in range(N)]
        signed = [False] * N
        readySent = [False] * N
        reconstDone = [False] * N
        while True:  # main loop
            sender, msgBundle = receive()
            if msgBundle[0] == 'i' and not signed[sender]:
                if keys[sender].verify(
                        sha1hash(''.join([
                            msgBundle[1][0], msgBundle[1][1],
                            ''.join(msgBundle[1][2])
                        ])), msgBundle[2]):
                    assert isinstance(msgBundle[1], tuple)
                    if not merkleVerify(msgBundle[1][0], msgBundle[1][1],
                                        msgBundle[1][2], coolSHA256Hash, pid):
                        continue
                    if sender in rootHashes:
                        if rootHashes[sender] != msgBundle[1][1]:
                            print "Cheating caught, exiting"
                            sys.exit(0)
                    else:
                        rootHashes[sender] = msgBundle[1][1]
                    newBundle = (sender, msgBundle[1][0], msgBundle[1][1],
                                 msgBundle[1][2]
                                 )  # assert each frag has a length of step
                    broadcast(('e', newBundle, keys[pid].sign(
                        sha1hash(''.join([
                            str(newBundle[0]), newBundle[1], newBundle[2],
                            ''.join(newBundle[3])
                        ])))))
                    signed[sender] = True
                else:
                    raise ECDSASignatureError()
            elif msgBundle[0] == 'e':
                if keys[sender].verify(
                        sha1hash(''.join([
                            str(msgBundle[1][0]), msgBundle[1][1],
                            msgBundle[1][2], ''.join(msgBundle[1][3])
                        ])), msgBundle[2]):
                    originBundle = msgBundle[1]
                    if not merkleVerify(originBundle[1], originBundle[2],
                                        originBundle[3], coolSHA256Hash,
                                        sender):
                        continue
                    if originBundle[0] in rootHashes:
                        if rootHashes[originBundle[0]] != originBundle[2]:
                            print "Cheating caught, exiting"
                            sys.exit(0)
                    else:
                        rootHashes[originBundle[0]] = originBundle[2]
                    opinions[originBundle[0]][sender] = originBundle[
                        1]  # We are going to move this part to kekeketktktktk
                    if len(opinions[originBundle[0]]
                           ) >= Threshold2 and not readySent[originBundle[0]]:
                        readySent[originBundle[0]] = True
                        broadcast(
                            ('r', originBundle[0],
                             originBundle[2]))  # We are broadcasting its hash
                else:
                    raise ECDSASignatureError()
            elif msgBundle[0] == 'r':
                readyCounter[msgBundle[1]][msgBundle[2]] += 1
                tmp = readyCounter[msgBundle[1]][msgBundle[2]]
                if tmp >= t + 1 and not readySent[msgBundle[1]]:
                    readySent[msgBundle[1]] = True
                    broadcast(('r', msgBundle[1], msgBundle[2]))
                if tmp >= Threshold2 and not outputs[msgBundle[1]].full() and \
                        not reconstDone[msgBundle[1]] and len(opinions[msgBundle[1]]) >= Threshold:
                    reconstDone[msgBundle[1]] = True
                    if msgBundle[1] in rootHashes:
                        if rootHashes[msgBundle[1]] != msgBundle[2]:
                            print "Cheating caught, exiting"
                            sys.exit(0)
                    else:
                        rootHashes[msgBundle[1]] = msgBundle[2]
                    if opinions[msgBundle[1]].values()[0] == '':
                        reconstruction = ['']
                    else:
                        reconstruction = zfecDecoder.decode(
                            opinions[msgBundle[1]].values()[:Threshold],
                            opinions[msgBundle[1]].keys()[:Threshold]
                        )  # We only take the first [Threshold] fragments
                    rawbuf = ''.join(reconstruction)
                    buf = rawbuf[:-ord(rawbuf[-1])]
                    # Check root hash
                    step = len(
                        buf
                    ) / Threshold + 1  # len(buf) % Threshold == 0 and len(buf) / Threshold or (len(buf) / Threshold + 1)
                    assert step * Threshold - len(buf) < 256  # assumption
                    buf_ = buf.ljust(step * Threshold - 1,
                                     '\xFF') + chr(step * Threshold - len(buf))
                    fragList = [
                        buf_[i * step:(i + 1) * step] for i in range(Threshold)
                    ]
                    encodedFragList = zfecEncoder.encode(fragList)
                    mt = merkleTree(encodedFragList, coolSHA256Hash)
                    assert rootHashes[msgBundle[1]] == mt[
                        1]  # full binary tree
                    if outputs[msgBundle[1]].empty():
                        outputs[msgBundle[1]].put(buf)

    greenletPacker(Greenlet(Listener), 'multiSigBr.Listener',
                   (pid, N, t, msg, broadcast, receive, outputs)).start()
    buf = msg  # We already assumed the proposals are byte strings

    step = len(
        buf
    ) / Threshold + 1  # len(buf) % Threshold == 0 and len(buf) / Threshold or (len(buf) / Threshold + 1)
    assert step * Threshold - len(buf) < 256  # assumption
    buf = buf.ljust(step * Threshold - 1,
                    '\xFF') + chr(step * Threshold - len(buf))
    fragList = [buf[i * step:(i + 1) * step] for i in range(Threshold)]
    encodedFragList = zfecEncoder.encode(fragList)
    mt = merkleTree(encodedFragList, coolSHA256Hash)
    rootHash = mt[1]  # full binary tree
    for i in range(N):
        mb = getMerkleBranch(
            i, mt)  # notice that index starts from 1 and pid starts from 0
        newBundle = (encodedFragList[i], rootHash, mb)
        send(i, ('i', newBundle, keys[pid].sign(
            sha1hash(''.join(
                [newBundle[0], newBundle[1], ''.join(newBundle[2])])))))
Esempio n. 23
0
def binary_consensus(instance, pid, N, t, vi, decide, broadcast, receive):
    '''
    Binary consensus from [MMR 13]. It takes an input vi and will finally write the decided value into _decide_ channel.
    :param pid: my id number
    :param N: the number of parties
    :param t: the number of byzantine parties
    :param vi: input value, an integer
    :param decide: deciding channel
    :param broadcast: broadcast channel
    :param receive: receive channel
    :return:
    '''
    # Messages received are routed to either a shared coin, the broadcast, or AUX
    coinQ = Queue(1)
    bcQ = defaultdict(lambda: Queue(1))
    auxQ = defaultdict(lambda: Queue(1))

    def _recv():
        while True:  #not finished[pid]:
            (i, (tag, m)) = receive()
            if tag == 'B':
                # Broadcast message
                r, msg = m
                greenletPacker(Greenlet(bcQ[r].put, (i, msg)),
                    'binary_consensus.bcQ[%d].put' % r, (pid, N, t, vi, decide, broadcast, receive)).start() # In case they block the router
            elif tag == 'C':
                # A share of a coin
                greenletPacker(Greenlet(coinQ.put, (i, m)),
                    'binary_consensus.coinQ.put', (pid, N, t, vi, decide, broadcast, receive)).start()
            elif tag == 'A':
                # Aux message
                r, msg = m
                greenletPacker(Greenlet(auxQ[r].put, (i, msg)),
                      'binary_consensus.auxQ[%d].put' % r, (pid, N, t, vi, decide, broadcast, receive)).start()
                pass

    greenletPacker(Greenlet(_recv), 'binary_consensus._recv', (pid, N, t, vi, decide, broadcast, receive)).start()

    def brcast_get(r):
        def _recv(*args, **kargs):
            return bcQ[r].get(*args, **kargs)

        return _recv

    received = [defaultdict(set), defaultdict(set)]

    coin = shared_coin(instance, pid, N, t, makeBroadcastWithTag('C', broadcast), coinQ.get)

    def getWithProcessing(r, binValues, callBackWaiter):
        def _recv(*args, **kargs):
            sender, v = auxQ[r].get(*args, **kargs)
            assert v in (0, 1)
            assert sender in range(N)
            received[v][r].add(sender)
            # Check if conditions are satisfied
            threshold = N - t  # 2*t + 1 # N - t
            if True: #not finished[pid]:
                if len(binValues) == 1:
                    if len(received[binValues[0]][r]) >= threshold and not callBackWaiter[r].full():
                        # Check passed
                        callBackWaiter[r].put(binValues)
                elif len(binValues) == 2:
                    if len(received[0][r].union(received[1][r])) >= threshold and not callBackWaiter[r].full():
                        callBackWaiter[r].put(binValues)
                    elif len(received[0][r]) >= threshold and not callBackWaiter[r].full():
                        callBackWaiter[r].put([0])
                    elif len(received[1][r]) >= threshold and not callBackWaiter[r].full():
                        callBackWaiter[r].put([1])
            return sender, v

        return _recv

    round = 0
    est = vi
    decided = False
    decidedNum = 0

    callBackWaiter = defaultdict(lambda: Queue(1))

    while True: # checkFinishedWithGlobalState(N): <- for distributed experiment we don't need this
        round += 1
        # Broadcast EST
        # TODO: let bv_broadcast receive
        bvOutputHolder = Queue(2)  # 2 possible values
        binValues = []

        def bvOutput(m):
            if not m in binValues:
                binValues.append(m)
                bvOutputHolder.put(m)

        def getRelease(channel):
            def _release():
                greenletPacker(Greenlet(garbageCleaner, channel),
                    'binary_consensus.garbageCleaner', (pid, N, t, vi, decide, broadcast, receive)).start()
            return _release

        br1 = greenletPacker(Greenlet(
            bv_broadcast(
                pid, N, t, makeBroadcastWithTagAndRound('B', broadcast, round),
                brcast_get(round), bvOutput, getRelease(bcQ[round])),
            est), 'binary_consensus.bv_broadcast(%d, %d, %d)' % (pid, N, t), (pid, N, t, vi, decide, broadcast, receive))
        br1.start()
        w = bvOutputHolder.get()  # Wait until output is not empty

        broadcast(('A', (round, w)))
        greenletPacker(Greenlet(loopWrapper(getWithProcessing(round, binValues, callBackWaiter))),
            'binary_consensus.loopWrapper(getWithProcessing(round, binValues, callBackWaiter))',
                    (pid, N, t, vi, decide, broadcast, receive)).start()

        values = callBackWaiter[round].get()  # wait until the conditions are satisfied
        s = coin(round)
        # Here corresponds to a proof that if one party decides at round r,
        # then in all the following rounds, everybody will propose r as an estimation. (Lemma 2, Lemma 1)
        # An abandoned party is a party who has decided but no enough peers to help him end the loop.
        # Lemma: # of abandoned party <= t
        if decided and decidedNum == s:  # infinite-message fix
            break
        if len(values) == 1:
            if values[0] == s:
                # decide s
                if not decided:
                    globalState[pid] = "%d" % s
                    decide.put(s)
                    decided = True
                    decidedNum = s

            else:
                pass
                # mylog('[%d] advances rounds from %d caused by values[0](%d)!=s(%d)' % (pid, round, values[0], s), verboseLevel=-1)
            est = values[0]
        else:
            # mylog('[%d] advances rounds from %d caused by len(values)>1 where values=%s' % (pid, round, repr(values)), verboseLevel=-1)
            est = s
Esempio n. 24
0
 def _release():
     greenletPacker(Greenlet(garbageCleaner, channel),
         'binary_consensus.garbageCleaner', (pid, N, t, vi, decide, broadcast, receive)).start()