From d1e51ec7278a94ff21999d97b2130587e251e541 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 5 Feb 2022 14:12:59 +0000 Subject: [PATCH 01/29] Don't check stanford certificate --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 481c1600..951d0e51 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,7 +11,7 @@ ENV B 16 RUN apt-get update && apt-get -y install bison flex libgmp-dev libmpc-dev -RUN wget https://crypto.stanford.edu/pbc/files/pbc-0.5.14.tar.gz +RUN wget --no-check-certificate https://crypto.stanford.edu/pbc/files/pbc-0.5.14.tar.gz RUN tar -xvf pbc-0.5.14.tar.gz RUN cd pbc-0.5.14 && ./configure && make && make install From 35a429e541e68f1292a699c76b722c7278890288 Mon Sep 17 00:00:00 2001 From: Tomer Date: Sat, 5 Feb 2022 16:11:11 +0000 Subject: [PATCH 02/29] Added ImprovedHB for two nodes --- honeybadgerbft/core/honeybadger.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/honeybadgerbft/core/honeybadger.py b/honeybadgerbft/core/honeybadger.py index f7e8fa1a..3eed1c5c 100644 --- a/honeybadgerbft/core/honeybadger.py +++ b/honeybadgerbft/core/honeybadger.py @@ -38,11 +38,17 @@ def broadcast_receiver(recv_func, recv_queues): recv_queue.put_nowait((sender, msg)) + ://github.com/1337samuels/HoneyBadgerBFT-Python, def broadcast_receiver_loop(recv_func, recv_queues): while True: broadcast_receiver(recv_func, recv_queues) +class ImprovedHoneyBadgerBFT(HoneyBadgerBFT): + def _prepare_transaction_buffer(self): + self.transaction_buffer = sorted(self.transaction_buffer, key=len, reverse=(self.pid%2 == 1)) + + class HoneyBadgerBFT(): r"""HoneyBadgerBFT object used to run the protocol. @@ -89,6 +95,9 @@ def submit_tx(self, tx): print('submit_tx', self.pid, tx) self.transaction_buffer.append(tx) + def _prepare_transaction_buffer(self): + pass + def run(self): """Run the HoneyBadgerBFT protocol.""" @@ -121,6 +130,7 @@ def _recv(): self._per_round_recv[r] = Queue() # Select all the transactions (TODO: actual random selection) + self._prepare_transaction_buffer() tx_to_send = self.transaction_buffer[:self.B] # TODO: Wait a bit if transaction buffer is not full From e17fb5023c637e5c14d8f25c97fbbf2da3181a2e Mon Sep 17 00:00:00 2001 From: samuels Date: Sat, 5 Feb 2022 16:13:58 +0000 Subject: [PATCH 03/29] Runs our test, weird our_start.sh --- honeybadgerbft/core/honeybadger.py | 6 +- test/__init__.py | 0 test/byzantine.py | 393 ----------------- test/conftest.py | 57 --- test/crypto/conftest.py | 84 ---- test/crypto/ecdsa/test_generate_keys_ecdsa.py | 21 - test/crypto/threshenc/test_tpke.py | 90 ---- test/crypto/threshsig/test_boldyreva.py | 77 ---- test/crypto/threshsig/test_boldyreva_gipc.py | 120 ----- test/crypto/threshsig/test_boldyreva_pool.py | 51 --- .../crypto/threshsig/test_generate_enckeys.py | 22 - .../crypto/threshsig/test_generate_sigkeys.py | 22 - test/crypto/threshsig/test_millerrabin.py | 48 -- test/demo_attack_issue59.py | 57 --- test/test_binaryagreement.py | 415 ------------------ test/test_commoncoin.py | 138 ------ test/test_commonsubset.py | 151 ------- test/test_honeybadger.py | 147 ------- test/test_honeybadger_block.py | 210 --------- test/test_rbc.py | 320 -------------- test/test_threshenc.py | 52 --- 21 files changed, 3 insertions(+), 2478 deletions(-) delete mode 100644 test/__init__.py delete mode 100644 test/byzantine.py delete mode 100644 test/conftest.py delete mode 100644 test/crypto/conftest.py delete mode 100644 test/crypto/ecdsa/test_generate_keys_ecdsa.py delete mode 100644 test/crypto/threshenc/test_tpke.py delete mode 100644 test/crypto/threshsig/test_boldyreva.py delete mode 100644 test/crypto/threshsig/test_boldyreva_gipc.py delete mode 100644 test/crypto/threshsig/test_boldyreva_pool.py delete mode 100644 test/crypto/threshsig/test_generate_enckeys.py delete mode 100644 test/crypto/threshsig/test_generate_sigkeys.py delete mode 100644 test/crypto/threshsig/test_millerrabin.py delete mode 100644 test/demo_attack_issue59.py delete mode 100644 test/test_binaryagreement.py delete mode 100644 test/test_commoncoin.py delete mode 100644 test/test_commonsubset.py delete mode 100644 test/test_honeybadger.py delete mode 100644 test/test_honeybadger_block.py delete mode 100644 test/test_rbc.py delete mode 100644 test/test_threshenc.py diff --git a/honeybadgerbft/core/honeybadger.py b/honeybadgerbft/core/honeybadger.py index f7e8fa1a..8f506a3f 100644 --- a/honeybadgerbft/core/honeybadger.py +++ b/honeybadgerbft/core/honeybadger.py @@ -86,7 +86,7 @@ def submit_tx(self, tx): :param tx: Transaction to append to the buffer. """ - print('submit_tx', self.pid, tx) + ##print('submit_tx', self.pid, tx) self.transaction_buffer.append(tx) def run(self): @@ -133,7 +133,7 @@ def _send(j, o): send_r = _make_send(r) recv_r = self._per_round_recv[r].get new_tx = self._run_round(r, tx_to_send[0], send_r, recv_r) - print('new_tx:', new_tx) + #print('new_tx:', new_tx) # Remove all of the new transactions from the buffer self.transaction_buffer = [_tx for _tx in self.transaction_buffer if _tx not in new_tx] @@ -174,7 +174,7 @@ def broadcast(o): rbc_outputs = [Queue(1) for _ in range(N)] my_rbc_input = Queue(1) - print(pid, r, 'tx_to_send:', tx_to_send) + #print(pid, r, 'tx_to_send:', tx_to_send) def _setup(j): """Setup the sub protocols RBC, BA and common coin. diff --git a/test/__init__.py b/test/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/byzantine.py b/test/byzantine.py deleted file mode 100644 index d8ba74c0..00000000 --- a/test/byzantine.py +++ /dev/null @@ -1,393 +0,0 @@ -import logging -from collections import defaultdict - -import gevent -from gevent.event import AsyncResult, Event -from gevent.queue import Queue - -from honeybadgerbft.exceptions import RedundantMessageError - - -logger = logging.getLogger(__name__) - -a0, a1, bob, x = 0, 1, 2, 3 - - -def byz_ba_issue_59(sid, pid, N, f, coin, input, decide, broadcast, receive): - """Modified binary consensus from [MMR14], so that it exhibits a - byzantine behavior as per issue #59 - (see https://github.com/amiller/HoneyBadgerBFT/issues/59). - - :param sid: session identifier - :param pid: my id number - :param N: the number of parties - :param f: the number of byzantine parties - :param coin: a ``common coin(r)`` is called to block until receiving a bit - :param input: ``input()`` is called to receive an input - :param decide: ``decide(0)`` or ``output(1)`` is eventually called - :param broadcast: broadcast channel - :param receive: receive channel - :return: blocks until - """ - # Messages received are routed to either a shared coin, the broadcast, or AUX - est_values = defaultdict(lambda: [set(), set()]) - aux_values = defaultdict(lambda: [set(), set()]) - conf_values = defaultdict(lambda: {(0,): set(), (1,): set(), (0, 1): set()}) - est_sent = defaultdict(lambda: [False, False]) - conf_sent = defaultdict(lambda: {(0,): False, (1,): False, (0, 1): False}) - bin_values = defaultdict(set) - - # This event is triggered whenever bin_values or aux_values changes - bv_signal = Event() - - def _recv(): - while True: # not finished[pid]: - (sender, msg) = receive() - logger.debug(f'receive {msg} from node {sender}', - extra={'nodeid': pid, 'epoch': msg[1]}) - assert sender in range(N) - if msg[0] == 'EST': - # BV_Broadcast message - _, r, v = msg - assert v in (0, 1) - if sender in est_values[r][v]: - print('Redundant EST received', msg) - raise RedundantMessageError( - 'Redundant EST received {}'.format(msg)) - - est_values[r][v].add(sender) - # Relay after reaching first threshold - if len(est_values[r][v]) >= f + 1 and not est_sent[r][v]: - est_sent[r][v] = True - for receiver in range(N): - logger.debug( - f"broadcast {('EST', r, v)} to node {receiver}", - extra={'nodeid': pid, 'epoch': r}) - if receiver != 2: - broadcast(('EST', r, v), receiver=receiver) - - # Output after reaching second threshold - if len(est_values[r][v]) >= 2 * f + 1: - logger.debug( - f'add v = {v} to bin_value[{r}] = {bin_values[r]}', - extra={'nodeid': pid, 'epoch': r}, - ) - bin_values[r].add(v) - logger.debug(f'bin_values[{r}] is now: {bin_values[r]}', - extra={'nodeid': pid, 'epoch': r}) - bv_signal.set() - - elif msg[0] == 'AUX': - # Aux message - _, r, v = msg - assert v in (0, 1) - if sender in aux_values[r][v]: - print('Redundant AUX received', msg) - raise RedundantMessageError( - 'Redundant AUX received {}'.format(msg)) - - aux_values[r][v].add(sender) - logger.debug( - f'add v = {v} to aux_value[{r}] = {aux_values[r]}', - extra={'nodeid': pid, 'epoch': r}, - ) - - bv_signal.set() - - elif msg[0] == 'CONF': - # CONF message - _, r, v = msg - assert v in ((0,), (1,), (0, 1)) - if sender in conf_values[r][v]: - # FIXME: raise or continue? For now will raise just - # because it appeared first, but maybe the protocol simply - # needs to continue. - print(f'Redundant CONF received {msg} by {sender}') - raise RedundantMessageError( - f'Redundant CONF received {msg} by {sender}') - - conf_values[r][v].add(sender) - logger.debug( - f'add v = {v} to conf_value[{r}] = {conf_values[r]}', - extra={'nodeid': pid, 'epoch': r}, - ) - - bv_signal.set() - - # Run the receive loop in the background - gevent.spawn(_recv) - - # Block waiting for the input - vi = input() - assert vi in (0, 1) - est = vi - r = 0 - while True: # Unbounded number of rounds - logger.info(f'starting round {r} with est set to {est}', - extra={'nodeid': pid, 'epoch': r}) - not_est = int(not bool(est)) - if not est_sent[r][est]: - est_sent[r][est] = True - est_sent[r][not_est] = True - logger.debug( - f"broadcast {('EST', r, int(not bool(est)))} to node {0}", - extra={'nodeid': pid, 'epoch': r}, - ) - broadcast(('EST', r, int(not bool(est))), receiver=0) - logger.debug( - f"broadcast {('EST', r, est)} to node {1}", - extra={'nodeid': pid, 'epoch': r}, - ) - broadcast(('EST', r, est), receiver=1) - - while len(bin_values[r]) == 0: - # Block until a value is output - bv_signal.clear() - bv_signal.wait() - - w = next(iter(bin_values[r])) # take an element - logger.debug(f"broadcast {('AUX', r, w)}", - extra={'nodeid': pid, 'epoch': r}) - for receiver in range(N): - if receiver != 2: - broadcast(('AUX', r, w), receiver=receiver) - - # After this all messages within A are delivered and x sends both - # BVAL(0) and BVAL(1) to every node in A. Thus every node in A - # broadcasts both BVAL(0) and BVAL(1) and sets bin_values={0,1}. - logger.debug( - 'x sends both BVAL(0) and BVAL(1) to every node in A.', - extra={'nodeid': pid, 'epoch': r}, - ) - broadcast(('EST', r, est), receiver=0) - broadcast(('EST', r, int(not bool(est))), receiver=1) - - # XXX CONF phase - if not conf_sent[r][(0, 1)]: - conf_sent[r][(0, 1)] = True - logger.debug(f"broadcast {('CONF', r, (0, 1))}", - extra={'nodeid': pid, 'epoch': r}) - broadcast(('CONF', r, (0, 1))) - - logger.info( - f'Block until receiving the common coin value', - extra={'nodeid': pid, 'epoch': r}, - ) - # Block until receiving the common coin value - s = coin(r) - logger.debug(f's = coin(r) | s = {s}, r = {r}', - extra={'nodeid': pid, 'epoch': r}) - not_s = int(not bool(s)) - - logger.debug(f"broadcast {('EST', r, not_s)} to node 2", - extra={'nodeid': pid, 'epoch': r}) - broadcast(('EST', r, not_s), receiver=2) - logger.debug(f"broadcast {('AUX', r, not_s)} to node 2", - extra={'nodeid': pid, 'epoch': r}) - broadcast(('AUX', r, not_s), receiver=2) - logger.info(f'exiting round {r}, setting est = s ({s})', - extra={'nodeid': pid, 'epoch': r}) - est = s - r += 1 - - -class SendCondition(Event): - - epoch = 0 - priority = None - value = None - - -class NetworkScheduler: - COIN_PHASE_BEGIN = 18 - LAST = 24 - NO_DELAY = None - - def __init__(self, *, receivers): - self.queues = [Queue() for _ in range(4)] - self.receivers = receivers - self.events = defaultdict(SendCondition) - self.coins = defaultdict(AsyncResult) - self.initial_values = defaultdict(AsyncResult) - self.initial_values[0].set(0) - - def consume_queue(self, queue): - for m in queue: - gevent.spawn(self.schedule, m) - - def schedule(self, message): - # TODO once get_events() is implemented - # event, next_event = self.get_events(message) - sender, receiver, (tag, epoch, bin_value) = message - priority = self.get_priority(message) - - if priority == self.COIN_PHASE_BEGIN: - coin = int(not bool(bin_value)) - self.coins[epoch].set(coin) - self.initial_values[epoch + 1].set(coin) - - if priority == self.LAST: - next_event_priority = 0 - next_event_epoch = epoch + 1 - elif priority is not self.NO_DELAY: - next_event_priority = priority + 1 - next_event_epoch = epoch - - try: - next_event = self.events[next_event_epoch, next_event_priority] - except NameError: - next_event = None - else: - next_event.priority = next_event_priority - next_event.epoch = next_event_epoch - - event = self.events[epoch, priority] - event.epoch = epoch - event.priority = priority - event.value = bin_value - - logger.debug(f'Schedule message {message} with priority {priority}.', - extra={'nodeid': message[0], 'epoch': message[2][1]}) - gevent.spawn(self.send, message, event=event, next_event=next_event) - - def send(self, message, *, event, next_event): - sender, receiver, (tag, epoch, value) = message - logger.info( - f'Wait for condition {event} with priority {event.priority} for' - f'epoch {event.epoch} and value {event.value}', - extra={'nodeid': sender, 'epoch': epoch}, - ) - event.wait() - logger.info(f'Send message {message} --- PRIORITY: {event.priority}', - extra={'nodeid': sender, 'epoch': epoch}) - self.receivers[receiver].put((sender, (tag, epoch, value))) - if next_event: - logger.info( - f'Set (ready) condition {next_event} with priority' - f'{next_event.priority} for epoch {next_event.epoch}' - f'and value {event.value}', - extra={'nodeid': sender, 'epoch': epoch}, - ) - next_event.set() - - # Move to next round. - if next_event.priority == self.LAST: - self.events[next_event.epoch + 1, self.NO_DELAY].set() - - def get_priority(self, message): - message_map = self.get_message_map(message) - _, receiver, (tag, epoch, _) = message - try: - priority = message_map[message] - except KeyError: - if tag == 'CONF' or receiver == x: - priority = self.NO_DELAY - else: - priority = self.LAST - return priority - - def get_events(self, message): - raise NotImplementedError - - def get_message_map(self, message): - sender, receiver, (tag, epoch, _) = message - if self.is_a_coin_dependent_message( - sender=sender, receiver=receiver, tag=tag): - message_map = self.coin_dependent_message_map(epoch) - else: - message_map = self.coin_independent_message_map(epoch) - return message_map - - def coin_independent_message_map(self, epoch): - r = epoch - v = self.initial_values[r].get() - not_v = int(not bool(v)) - msg_map = { - (x, a0, ('EST', r, not_v)): 0, - (x, a1, ('EST', r, v)): 1, - (bob, a0, ('EST', r, not_v)): 2, - (bob, a1, ('EST', r, not_v)): 3, - (a0, a0, ('EST', r, v)): 4, - (a0, a0, ('EST', r, not_v)): 5, - # ... - (a1, a1, ('EST', r, v)): 6, - (a0, a1, ('EST', r, v)): 7, - # ... - (a1, a0, ('EST', r, v)): 8, - (a0, a1, ('EST', r, not_v)): 9, - (a0, a0, ('AUX', r, not_v)): 10, - (a0, a1, ('AUX', r, not_v)): 11, - (a1, a0, ('AUX', r, v)): 12, - (a1, a1, ('AUX', r, v)): 13, - # ... - (x, a0, ('EST', r, v)): 14, - (x, a1, ('EST', r, not_v)): 15, - (x, a0, ('AUX', r, not_v)): 16, - (x, a1, ('AUX', r, not_v)): 17, - # not_coin phase - one of these two messages is sent to B, such - # that the value is the boolean NOT of the coin value - (x, bob, ('EST', r, 0)): 18, - (x, bob, ('EST', r, 1)): 18, - } - return msg_map - - def coin_dependent_message_map(self, epoch): - """Messages for which the scheduling depends on the value of - the coin. - """ - coin = self.coins[epoch].get() - not_coin = int(not bool(coin)) - return { - (a0, bob, ('EST', epoch, not_coin)): 19, - (a1, bob, ('EST', epoch, not_coin)): 20, - (a0, bob, ('AUX', epoch, not_coin)): 21, - (a1, bob, ('AUX', epoch, not_coin)): 21, - (bob, bob, ('AUX', epoch, not_coin)): 22, - (x, bob, ('AUX', epoch, not_coin)): 23, - } - - def is_a_coin_dependent_message(self, *, sender, receiver, tag): - """Checks if the message depends on the value of the coin for - its scheduling. - """ - return receiver == bob and (tag == 'AUX' or - sender in (a0, a1) and tag == 'EST') - - def start(self): - for queue in self.queues: - gevent.spawn(self.consume_queue, queue) - self.events[0, 0].set() - self.events[0, self.NO_DELAY].set() - - -def broadcast_router(N): - """Router controlled by an adversary such that incoming messages are - redirected to the queues of an adversarial network scheduler. - - :return: (receives, sends) - """ - queues = [Queue() for _ in range(N)] - ns = NetworkScheduler(receivers=queues) - ns.start() - - def makeBroadcast(i): - def _send(j, o): - ns.queues[i].put((i, j, o)) - - def _bc(o, receiver=None): - if receiver is not None: - _send(receiver, o) - else: - for j in range(N): - _send(j, o) - - return _bc - - def makeRecv(j): - def _recv(): - i, o = queues[j].get() - return i, o - return _recv - - return ([makeBroadcast(i) for i in range(N)], - [makeRecv(j) for j in range(N)]) diff --git a/test/conftest.py b/test/conftest.py deleted file mode 100644 index 4b725e0e..00000000 --- a/test/conftest.py +++ /dev/null @@ -1,57 +0,0 @@ -import logging - -from logutils.colorize import ColorizingStreamHandler - -import pytest - - -def pytest_collection_modifyitems(config, items): - if config.getoption('-m') == 'demo': - # do not skip demo tests - return - skip_demo = pytest.mark.skip(reason='need "-m demo" option to run') - for item in items: - if 'demo' in item.keywords: - item.add_marker(skip_demo) - - -class BadgerColoredLogs(ColorizingStreamHandler): - - nodeid_map = { - 0: (None, 'green', False), - 1: (None, 'cyan', False), - 2: (None, 'blue', False), - 3: (None, 'magenta', False), - } - - def colorize(self, message, record): - """ - Colorize a message for a logging event. - - This implementation uses the ``level_map`` class attribute to - map the LogRecord's level to a colour/intensity setting, which is - then applied to the whole message. - - :param message: The message to colorize. - :param record: The ``LogRecord`` for the message. - """ - if record.nodeid in self.nodeid_map: - bg, fg, bold = self.nodeid_map[record.nodeid] - params = [] - if bg in self.color_map: - params.append(str(self.color_map[bg] + 40)) - if fg in self.color_map: - params.append(str(self.color_map[fg] + 30)) - if bold: - params.append('1') - if params: - message = ''.join((self.csi, ';'.join(params), - 'm', message, self.reset)) - return message - - -logging.basicConfig( - format='node %(nodeid)s|round %(epoch)s> %(module)s:%(funcName)s (%(lineno)d) %(message)s', - level=logging.DEBUG, - handlers=[BadgerColoredLogs()], -) diff --git a/test/crypto/conftest.py b/test/crypto/conftest.py deleted file mode 100644 index 158bd3c5..00000000 --- a/test/crypto/conftest.py +++ /dev/null @@ -1,84 +0,0 @@ -from charm.toolbox.pairinggroup import PairingGroup, ZR, G2 -from pytest import fixture - - -@fixture -def pairing_group_MNT224(): - return PairingGroup('MNT224') - -@fixture -def pairing_group_SS512(): - return PairingGroup('SS512') - - -@fixture -def pairing_group(request): - curve = request.param - return PairingGroup(curve) - - -@fixture -def g(): - return ( - b'm\n\x9f\xcc\xb8\xd9(4\x07\xee\xcd\xdeF\xf9\x14\x1c^\\&\x02\xff' - b'\xbd\x8e\xaa\x99\xe9b{\xb7\xa1\xa2\x90&hA\xe7\xf0\xc69\x139\xcc' - b'\xd4\xfbz\xcd\xd1\x14 {\x88w\x11\xae\x04&k2\xeea\x8f\xbe\x91W\x00' - ) - - -@fixture -def g2_mnt224(pairing_group_MNT224): - g2 = pairing_group_MNT224.hash('geng2', G2) - g2.initPP() - return g2 - - -@fixture(params=({'count': 5, 'seed': None},)) -def polynomial_coefficients(request, pairing_group_MNT224): - return pairing_group_MNT224.random(ZR, **request.param) - - -@fixture(params=(10,)) -def sks(request, polynomial_coefficients): - from honeybadgerbft.crypto.threshsig.boldyreva import polynom_eval - players = request.param - return [polynom_eval(i, polynomial_coefficients) - for i in range(1, players+1)] - - -@fixture -def vk(g2_mnt224, polynomial_coefficients): - return g2_mnt224 ** polynomial_coefficients[0] - - -@fixture -def vks(g2_mnt224, sks): - return [g2_mnt224 ** sk for sk in sks] - - -@fixture -def tbls_public_key(vk, vks): - from honeybadgerbft.crypto.threshsig.boldyreva import TBLSPublicKey - players = 10 # TODO bind to fixtures - count = 5 # TODO bind to fixtures - return TBLSPublicKey(players, count, vk, vks) - - -@fixture -def tbls_private_keys(vk, vks, sks): - from honeybadgerbft.crypto.threshsig.boldyreva import TBLSPrivateKey - players = 10 # TODO bind to fixtures - count = 5 # TODO bind to fixtures - return [TBLSPrivateKey(players, count, vk, vks, sk, i) - for i, sk in enumerate(sks)] - - -@fixture -def serialized_tbls_public_key_dict(tbls_public_key): - from honeybadgerbft.crypto.threshsig.boldyreva import serialize - return { - 'l': tbls_public_key.l, - 'k': tbls_public_key.k, - 'VK': serialize(tbls_public_key.VK), - 'VKs': [serialize(vk) for vk in tbls_public_key.VKs], - } diff --git a/test/crypto/ecdsa/test_generate_keys_ecdsa.py b/test/crypto/ecdsa/test_generate_keys_ecdsa.py deleted file mode 100644 index c8155944..00000000 --- a/test/crypto/ecdsa/test_generate_keys_ecdsa.py +++ /dev/null @@ -1,21 +0,0 @@ -from collections import namedtuple - -from pytest import mark - - -def test_generate_key_list(): - from honeybadgerbft.crypto.ecdsa.generate_keys_ecdsa import generate_key_list - keylist = generate_key_list(10) - assert len(keylist) == 10 - - -def test_main(monkeypatch): - from honeybadgerbft.crypto.ecdsa.generate_keys_ecdsa import main - - def mock_parse_args(players): - Args = namedtuple('Args', ('players',)) - args = Args(players) - return args - - monkeypatch.setattr('argparse.ArgumentParser.parse_args', lambda s: mock_parse_args(10)) - main() diff --git a/test/crypto/threshenc/test_tpke.py b/test/crypto/threshenc/test_tpke.py deleted file mode 100644 index 95578f93..00000000 --- a/test/crypto/threshenc/test_tpke.py +++ /dev/null @@ -1,90 +0,0 @@ -from base64 import encodestring, decodestring -from random import shuffle - -from Crypto.Hash import SHA256 -from charm.toolbox.pairinggroup import PairingGroup, ZR, G1, G2, pair -from pytest import mark - - -def test_tpke(): - from honeybadgerbft.crypto.threshenc.tpke import dealer - PK, SKs = dealer(players=100, k=35) - - m = SHA256.new(b'how').digest() - ciphertext = PK.encrypt(m) - U, V, W = ciphertext - assert PK.verify_ciphertext(U, V, W) - - shares = [sk.decrypt_share(U, V, W) for sk in SKs] - for i, share in enumerate(shares): - assert PK.verify_share(i, share, U, V, W) - - SS = list(range(PK.l)) - for i in range(1): - shuffle(SS) - S = set(SS[:PK.k]) - m_ = PK.combine_shares(U, V, W, dict((s, shares[s]) for s in S)) - assert m_ == m - - -def test_ciphertext_generation(): - from honeybadgerbft.crypto.threshenc.tpke import TPKEPublicKey - players = 10 - k = 5 - group = PairingGroup('SS512') - ZERO = group.random(ZR)*0 - ONE = group.random(ZR)*0 + 1 - g1 = group.hash('geng1', G1) - g1.initPP() - g2 = g1 - - coefficients = [group.random(ZR) for _ in range(k)] - secret = coefficients[0] - - # Polynomial evaluation - def f(x): - y = ZERO - xx = ONE - for coeff in coefficients: - y += coeff * xx - xx *= x - return y - - # Shares of master secret key - SKs = [f(i) for i in range(1, players+1)] - assert f(0) == secret - - # Verification keys - VK = g2 ** secret - VKs = [g2 ** xx for xx in SKs] - - public_key = TPKEPublicKey(players, k, VK, VKs) - message_digest = SHA256.new(b'abc123').digest() - ciphertext = public_key.encrypt(message_digest) - U, V, W = ciphertext - - assert len(V) == 32 - UV = decodestring(group.serialize(U)[2:]) + V - H = group.hash(UV, G2) - assert pair(g1, W) == pair(U, H) - - -def test_xor(): - from honeybadgerbft.crypto.threshenc.tpke import xor - x = (b'l\xa1=R\xcap\xc8\x83\xe0\xf0\xbb\x10\x1eBZ\x89' - b'\xe8bM\xe5\x1d\xb2\xd29%\x93\xafj\x84\x11\x80\x90') - y = (b'\xb2\xdf\xfeQ3 J7H\xe8yU6S\x05zU\x85\xd3' - b'\xc1o\xa8E\xa9\xef\x02\x98\x05\xe46\xbf\x9c') - expected_result = (b"\xde~\xc3\x03\xf9P\x82\xb4\xa8\x18\xc2E(\x11_" - b"\xf3\xbd\xe7\x9e$r\x1a\x97\x90\xca\x917o`'?\x0c") - assert xor(x, y) == expected_result - - -@mark.parametrize('n', (0, 1, 2)) -@mark.parametrize('pairing_group', ('SS512',), indirect=('pairing_group',)) -def test_deserialize(pairing_group, n, g): - from honeybadgerbft.crypto.threshenc import tpke - deserialize_func = getattr(tpke, 'deserialize{}'.format(n)) - base64_encoded_data = '{}:{}'.format(n, encodestring(g).decode()) - assert (deserialize_func(g) == - pairing_group.deserialize(base64_encoded_data.encode())) diff --git a/test/crypto/threshsig/test_boldyreva.py b/test/crypto/threshsig/test_boldyreva.py deleted file mode 100644 index 69f1f92d..00000000 --- a/test/crypto/threshsig/test_boldyreva.py +++ /dev/null @@ -1,77 +0,0 @@ -import pickle -import random -from base64 import encodestring - -from charm.core.math.pairing import pc_element -from pytest import mark - -from honeybadgerbft.crypto.threshsig.boldyreva import dealer - - -class TestTBLSPublicKey: - - def test_init(self, vk, vks): - from honeybadgerbft.crypto.threshsig.boldyreva import TBLSPublicKey - players = 10 # TODO bind to fixtures - count = 5 # TODO bind to fixtures - public_key = TBLSPublicKey(players, count, vk, vks) - assert public_key.l == players - assert public_key.k == count - assert public_key.VK == vk - assert public_key.VKs == vks - - def test_getstate(self, tbls_public_key, serialized_tbls_public_key_dict): - original_dict = tbls_public_key.__dict__.copy() - state_dict = tbls_public_key.__getstate__() - assert len(state_dict) == len(serialized_tbls_public_key_dict) - assert state_dict['k'] == serialized_tbls_public_key_dict['k'] - assert state_dict['l'] == serialized_tbls_public_key_dict['l'] - assert state_dict['VK'] == serialized_tbls_public_key_dict['VK'] - assert state_dict['VKs'] == serialized_tbls_public_key_dict['VKs'] - assert tbls_public_key.__dict__ == original_dict - - def test_setstate(self, tbls_public_key, serialized_tbls_public_key_dict): - from honeybadgerbft.crypto.threshsig.boldyreva import TBLSPublicKey - unset_public_key = TBLSPublicKey(None, None, None, None) - unset_public_key.__setstate__(serialized_tbls_public_key_dict) - assert len(unset_public_key.__dict__) == len(tbls_public_key.__dict__) - assert unset_public_key.__dict__['k'] == tbls_public_key.__dict__['k'] - assert unset_public_key.__dict__['l'] == tbls_public_key.__dict__['l'] - assert unset_public_key.__dict__['VK'] == tbls_public_key.__dict__['VK'] - assert unset_public_key.__dict__['VKs'] == tbls_public_key.__dict__['VKs'] - - def test_pickling_and_unpickling(self, tbls_public_key): - pickled_obj = pickle.dumps(tbls_public_key) - unpickled_obj = pickle.loads(pickled_obj) - assert unpickled_obj.__dict__ == tbls_public_key.__dict__ - - -def test_boldyreva(): - global PK, SKs - PK, SKs = dealer(players=16,k=5) - - global sigs,h - sigs = {} - h = PK.hash_message('hi') - h.initPP() - - for SK in SKs: - sigs[SK.i] = SK.sign(h) - - SS = list(range(PK.l)) - for i in range(10): - random.shuffle(SS) - S = set(SS[:PK.k]) - sig = PK.combine_shares(dict((s,sigs[s]) for s in S)) - assert PK.verify_signature(sig, h) - - -@mark.parametrize('n', (0, 1, 2)) -def test_deserialize_arg(n, g, mocker): - from honeybadgerbft.crypto.threshsig import boldyreva - mocked_deserialize = mocker.patch.object( - boldyreva.group, 'deserialize', autospec=True) - deserialize_func = getattr(boldyreva, 'deserialize{}'.format(n)) - base64_encoded_data = '{}:{}'.format(n, encodestring(g).decode()) - deserialize_func(g) - mocked_deserialize.assert_called_once_with(base64_encoded_data.encode()) diff --git a/test/crypto/threshsig/test_boldyreva_gipc.py b/test/crypto/threshsig/test_boldyreva_gipc.py deleted file mode 100644 index e352dc3e..00000000 --- a/test/crypto/threshsig/test_boldyreva_gipc.py +++ /dev/null @@ -1,120 +0,0 @@ -import time -from importlib import reload - -import gevent -import gipc - -from pytest import raises - - -def test_worker(tbls_public_key, tbls_private_keys): - from honeybadgerbft.crypto.threshsig.boldyreva_gipc import _worker - from honeybadgerbft.crypto.threshsig.boldyreva import serialize, deserialize1 - r_pipe, w_pipe = gipc.pipe(duplex=True) - h = tbls_public_key.hash_message('hi') - h.initPP() - signature_shares = {sk.i: sk.sign(h) for sk in tbls_private_keys} - serialized_h = serialize(h) - serialized_signature_shares = { - k: serialize(v) for k, v in signature_shares.items() - if k in list(signature_shares.keys())[:tbls_public_key.k] - } - w_pipe.put((serialized_h, serialized_signature_shares)) - _worker(tbls_public_key, r_pipe) - siganture_verification_result, serialized_signature = w_pipe.get() - assert siganture_verification_result is True - deserialized_signature_shares = { - k: deserialize1(v) for k, v in serialized_signature_shares.items()} - expected_serialized_signature = serialize( - tbls_public_key.combine_shares(deserialized_signature_shares)) - assert serialized_signature == expected_serialized_signature - - -def test_worker_loop(mocker, tbls_public_key): - from honeybadgerbft.crypto.threshsig import boldyreva_gipc - mocked_worker = mocker.patch.object( - boldyreva_gipc, '_worker', autospec=True) - max_calls = 3 - mocked_worker.side_effect = ErrorAfter(max_calls) - r_pipe, _ = gipc.pipe(duplex=True) - with raises(CallableExhausted) as err: - boldyreva_gipc.worker_loop(tbls_public_key, r_pipe) - mocked_worker.call_count == max_calls + 1 - mocked_worker.assert_called_with(tbls_public_key, r_pipe) - - -def test_pool(): - from honeybadgerbft.crypto.threshsig.boldyreva import dealer - from honeybadgerbft.crypto.threshsig import boldyreva_gipc - from honeybadgerbft.crypto.threshsig.boldyreva_gipc import ( - initialize, combine_and_verify) - global PK, SKs - PK, SKs = dealer(players=64, k=17) - - global sigs,h - sigs = {} - h = PK.hash_message('hi') - h.initPP() - for SK in SKs: - sigs[SK.i] = SK.sign(h) - - assert not boldyreva_gipc._procs - initialize(PK) - assert boldyreva_gipc._procs - - sigs = dict(list(sigs.items())[:PK.k]) - - # Combine 100 times - if 1: - #promises = [pool.apply_async(_combine_and_verify, - # (_h, sigs2)) - # for i in range(100)] - threads = [] - for i in range(3): - threads.append(gevent.spawn(combine_and_verify, h, sigs)) - print('launched', time.time()) - greenlets = gevent.joinall(threads, timeout=3) - #for p in promises: assert p.get() == True - for greenlet in greenlets: - assert greenlet.value[0] # TODO check the value - process = greenlet.value[1] - process.terminate() - process.join() - print('done', time.time()) - - # Combine 100 times - if 0: - print('launched', time.time()) - for i in range(10): - # XXX Since _combine_and_verify is not defined, use - # combine_and_verify instead, although not sure if that was the - # initial intention. - #_combine_and_verify(_h, sigs2) - combine_and_verify(_h, sigs2) - print('done', time.time()) - - print('work done') - assert boldyreva_gipc._procs - reload(boldyreva_gipc) - assert not boldyreva_gipc._procs - - -class ErrorAfter(object): - """Callable that will raise ``CallableExhausted`` - exception after ``limit`` calls. - - credit: Igor Sobreira - http://igorsobreira.com/2013/03/17/testing-infinite-loops.html - """ - def __init__(self, limit): - self.limit = limit - self.calls = 0 - - def __call__(self, x, y): - self.calls += 1 - if self.calls > self.limit: - raise CallableExhausted - - -class CallableExhausted(Exception): - pass diff --git a/test/crypto/threshsig/test_boldyreva_pool.py b/test/crypto/threshsig/test_boldyreva_pool.py deleted file mode 100644 index bd3bd595..00000000 --- a/test/crypto/threshsig/test_boldyreva_pool.py +++ /dev/null @@ -1,51 +0,0 @@ -from multiprocessing.pool import Pool - -from pytest import mark - - -def test_initialize(tbls_public_key): - from honeybadgerbft.crypto.threshsig.boldyreva_pool import ( - initialize, _pool, _pool_PK) - assert _pool is None - assert _pool_PK is None - initialize(tbls_public_key) - from honeybadgerbft.crypto.threshsig.boldyreva_pool import _pool, _pool_PK - assert isinstance(_pool, Pool) - assert _pool_PK == tbls_public_key - _pool.terminate() - - -def test_combine_and_verify(tbls_public_key, tbls_private_keys): - from honeybadgerbft.crypto.threshsig.boldyreva_pool import ( - initialize, combine_and_verify) - h = tbls_public_key.hash_message('hi') - h.initPP() - signature_shares = {sk.i: sk.sign(h) for sk in tbls_private_keys} - signature_shares = { - k: v for k, v in signature_shares.items() - if k in list(signature_shares.keys())[:tbls_public_key.k] - } - initialize(tbls_public_key) - from honeybadgerbft.crypto.threshsig.boldyreva_pool import _pool - combine_and_verify(h, signature_shares) - _pool.terminate() - - -def test__combine_and_verify(tbls_public_key, tbls_private_keys): - from honeybadgerbft.crypto.threshsig.boldyreva import serialize - from honeybadgerbft.crypto.threshsig.boldyreva_pool import _combine_and_verify - h = tbls_public_key.hash_message('hi') - h.initPP() - serialized_h = serialize(h) - signature_shares = {sk.i: sk.sign(h) for sk in tbls_private_keys} - serialized_signature_shares = { - k: serialize(v) for k, v in signature_shares.items() - if k in list(signature_shares.keys())[:tbls_public_key.k] - } - _combine_and_verify( - serialized_h, serialized_signature_shares, pk=tbls_public_key) - - -def test_pool(): - from honeybadgerbft.crypto.threshsig.boldyreva_pool import pool_test - pool_test() diff --git a/test/crypto/threshsig/test_generate_enckeys.py b/test/crypto/threshsig/test_generate_enckeys.py deleted file mode 100644 index b59981e0..00000000 --- a/test/crypto/threshsig/test_generate_enckeys.py +++ /dev/null @@ -1,22 +0,0 @@ -from collections import namedtuple - -from pytest import mark - - -@mark.parametrize('k', (None, 3)) -def test_generate_keys(k): - from honeybadgerbft.crypto.threshenc.generate_keys import _generate_keys - keys = _generate_keys(10, k) - assert len(keys) == 5 - - -def test_main(monkeypatch): - from honeybadgerbft.crypto.threshenc.generate_keys import main - - def mock_parse_args(players, k): - Args = namedtuple('Args', ('players', 'k')) - args = Args(players, k) - return args - - monkeypatch.setattr('argparse.ArgumentParser.parse_args', lambda s: mock_parse_args(10, 4)) - main() diff --git a/test/crypto/threshsig/test_generate_sigkeys.py b/test/crypto/threshsig/test_generate_sigkeys.py deleted file mode 100644 index 81df76a5..00000000 --- a/test/crypto/threshsig/test_generate_sigkeys.py +++ /dev/null @@ -1,22 +0,0 @@ -from collections import namedtuple - -from pytest import mark - - -@mark.parametrize('k', (None, 3)) -def test_generate_keys(k): - from honeybadgerbft.crypto.threshsig.generate_keys import _generate_keys - keys = _generate_keys(10, k) - assert len(keys) == 5 - - -def test_main(monkeypatch): - from honeybadgerbft.crypto.threshsig.generate_keys import main - - def mock_parse_args(players, k): - Args = namedtuple('Args', ('players', 'k')) - args = Args(players, k) - return args - - monkeypatch.setattr('argparse.ArgumentParser.parse_args', lambda s: mock_parse_args(10, 4)) - main() diff --git a/test/crypto/threshsig/test_millerrabin.py b/test/crypto/threshsig/test_millerrabin.py deleted file mode 100644 index d28e5ae6..00000000 --- a/test/crypto/threshsig/test_millerrabin.py +++ /dev/null @@ -1,48 +0,0 @@ -from pytest import mark, raises - - -@mark.parametrize('n', (-1, 0, 1)) -def test_is_probable_prime_raises(n): - from honeybadgerbft.crypto.threshsig.millerrabin import is_probable_prime - with raises(AssertionError): - is_probable_prime(n) - - -@mark.parametrize('n,is_prime', ( - (2, True), - (3, True), - (4, False), - (5, True), - (123456789, False), - (int('64380800680355443923012985496149269915138610753401343' - '29180734395241382648423706300613697153947391340909229' - '37332590384720397133335969549256322620979036686633213' - '903952966175107096769180017646161851573147596390153'), True), - (int('74380800680355443923012985496149269915138610753401343' - '29180734395241382648423706300613697153947391340909229' - '37332590384720397133335969549256322620979036686633213' - '903952966175107096769180017646161851573147596390153'), False), -)) -def test_is_probable_prime(n, is_prime): - from honeybadgerbft.crypto.threshsig.millerrabin import is_probable_prime - assert is_probable_prime(n) is is_prime - - -def test_is_probable_prime_under_1000(): - from honeybadgerbft.crypto.threshsig.millerrabin import is_probable_prime - primes_under_1000 = [i for i in range(2, 1000) if is_probable_prime(i)] - assert len(primes_under_1000) == 168 - assert primes_under_1000[-10:] == [937, 941, 947, 953, 967, - 971, 977, 983, 991, 997] - - -@mark.parametrize('bit_length', range(12, 120, 12)) -def test_generate_large_prime(bit_length): - from honeybadgerbft.crypto.threshsig.millerrabin import generateLargePrime - assert generateLargePrime(bit_length) - - -def test_generate_large_prime_fails(monkeypatch): - from honeybadgerbft.crypto.threshsig import millerrabin - monkeypatch.setattr(millerrabin, 'is_probable_prime', lambda k: False) - assert millerrabin.generateLargePrime(1) == 'Failure after 100.0 tries.' diff --git a/test/demo_attack_issue59.py b/test/demo_attack_issue59.py deleted file mode 100644 index 6cf38a98..00000000 --- a/test/demo_attack_issue59.py +++ /dev/null @@ -1,57 +0,0 @@ -import random - -import gevent -from gevent.queue import Queue -from pytest import mark - - -@mark.demo -def test_issue59_attack_demo(mocker, monkeypatch): - from .byzantine import byz_ba_issue_59, broadcast_router - from .test_binaryagreement import _make_coins - from honeybadgerbft.core import binaryagreement - - def mocked_conf_message_receiver(**kwargs): - pass - - def mocked_conf_phase_handler(**kwargs): - return kwargs['values'] - - monkeypatch.setattr( - binaryagreement, 'handle_conf_messages', mocked_conf_message_receiver) - monkeypatch.setattr( - binaryagreement, 'wait_for_conf_values', mocked_conf_phase_handler) - - N = 4 - f = 1 - seed = None - sid = 'sidA' - rnd = random.Random(seed) - sends, recvs = broadcast_router(N) - threads = [] - inputs = [] - outputs = [] - - coins_seed = rnd.random() - coins = _make_coins(sid+'COIN', N, f, coins_seed) - - for i in range(4): - inputs.append(Queue()) - outputs.append(Queue()) - - byz_thread = gevent.spawn(byz_ba_issue_59, sid, 3, N, f, coins[3], - inputs[3].get, outputs[3].put_nowait, sends[3], recvs[3]) - threads.append(byz_thread) - - for i in (2, 0, 1): - t = gevent.spawn(binaryagreement.binaryagreement, sid, i, N, f, coins[i], - inputs[i].get, outputs[i].put_nowait, sends[i], recvs[i]) - threads.append(t) - - inputs[0].put(0) # A_0 - inputs[1].put(0) # A_1 - inputs[2].put(1) # B - inputs[3].put(0) # F (x) - - for i in range(N): - outputs[i].get() diff --git a/test/test_binaryagreement.py b/test/test_binaryagreement.py deleted file mode 100644 index 46ada4dd..00000000 --- a/test/test_binaryagreement.py +++ /dev/null @@ -1,415 +0,0 @@ -import logging -import unittest -import gevent -import random - -from gevent.event import Event -from gevent.queue import Queue -from honeybadgerbft.core.commoncoin import shared_coin -from honeybadgerbft.core.binaryagreement import binaryagreement -from honeybadgerbft.crypto.threshsig.boldyreva import dealer -from collections import defaultdict - -from pytest import mark, raises - -logger = logging.getLogger(__name__) - -def simple_broadcast_router(N, maxdelay=0.005, seed=None): - """Builds a set of connected channels, with random delay - @return (receives, sends) - """ - rnd = random.Random(seed) - #if seed is not None: print 'ROUTER SEED: %f' % (seed,) - - queues = [Queue() for _ in range(N)] - _threads = [] - - def makeBroadcast(i): - def _send(j, o): - delay = rnd.random() * maxdelay - #print 'SEND %8s [%2d -> %2d] %2.1f' % (o[0], i, j, delay*1000), o[1:] - gevent.spawn_later(delay, queues[j].put, (i,o)) - #queues[j].put((i, o)) - def _bc(o): - #print 'BCAST %8s [%2d -> *]' % (o[0], i), o[1] - for j in range(N): _send(j, o) - return _bc - - def makeRecv(j): - def _recv(): - (i,o) = queues[j].get() - #print 'RECV %8s [%2d -> %2d]' % (o[0], i, j) - return (i,o) - return _recv - - return ([makeBroadcast(i) for i in range(N)], - [makeRecv(j) for j in range(N)]) - - -def byzantine_broadcast_router(N, maxdelay=0.005, seed=None, **byzargs): - """Builds a set of connected channels, with random delay. - - :return: (receives, sends) endpoints. - """ - rnd = random.Random(seed) - queues = [Queue() for _ in range(N)] - _threads = [] - - def makeBroadcast(i): - def _send(j, o): - delay = rnd.random() * maxdelay - if j == byzargs.get('byznode'): - try: - byz_tag = byzargs['byz_message_type'] - except KeyError: - pass - else: - o = list(o) - o[0] = byz_tag - o = tuple(o) - - gevent.spawn_later(delay, queues[j].put, (i, o)) - - if (j == byzargs.get('byznode') and - o[0] == byzargs.get('redundant_msg_type')): - gevent.spawn_later(delay, queues[j].put, (i, o)) - - def _bc(o): - for j in range(N): - _send(j, o) - - return _bc - - def makeRecv(j): - def _recv(): - (i,o) = queues[j].get() - return (i,o) - - return _recv - - return ([makeBroadcast(i) for i in range(N)], - [makeRecv(j) for j in range(N)]) - - -def release_held_messages(q, receivers): - for m in q: - receivers[m['receiver']].put((m['sender'], m['msg'])) - - -def dummy_coin(sid, N, f): - counter = defaultdict(int) - events = defaultdict(Event) - def getCoin(round): - # Return a pseudorandom number depending on the round, without blocking - counter[round] += 1 - if counter[round] == f+1: events[round].set() - events[round].wait() - return hash((sid,round)) % 2 - return getCoin - - -### Test binary agreement with a dummy coin -def _test_binaryagreement_dummy(N=4, f=1, seed=None): - # Generate keys - sid = 'sidA' - # Test everything when runs are OK - #if seed is not None: print 'SEED:', seed - rnd = random.Random(seed) - router_seed = rnd.random() - sends, recvs = simple_broadcast_router(N, seed=seed) - - threads = [] - inputs = [] - outputs = [] - coin = dummy_coin(sid, N, f) # One dummy coin function for all nodes - - for i in range(N): - inputs.append(Queue()) - outputs.append(Queue()) - - t = gevent.spawn(binaryagreement, sid, i, N, f, coin, - inputs[i].get, outputs[i].put_nowait, sends[i], recvs[i]) - threads.append(t) - - for i in range(N): - inputs[i].put(random.randint(0,1)) - #gevent.killall(threads[N-f:]) - #gevent.sleep(3) - #for i in range(N-f, N): - # inputs[i].put(0) - try: - outs = [outputs[i].get() for i in range(N)] - assert len(set(outs)) == 1 - try: gevent.joinall(threads) - except gevent.hub.LoopExit: pass - except KeyboardInterrupt: - gevent.killall(threads) - raise - - -def test_binaryagreement_dummy(): - _test_binaryagreement_dummy() - - -@mark.parametrize('msg_type', ('EST', 'AUX', 'CONF')) -@mark.parametrize('byznode', (1, 2, 3)) -def test_binaryagreement_dummy_with_redundant_messages(byznode, msg_type): - N = 4 - f = 1 - seed = None - sid = 'sidA' - rnd = random.Random(seed) - router_seed = rnd.random() - sends, recvs = byzantine_broadcast_router( - N, seed=seed, byznode=byznode, redundant_msg_type=msg_type) - threads = [] - inputs = [] - outputs = [] - coin = dummy_coin(sid, N, f) # One dummy coin function for all nodes - - for i in range(N): - inputs.append(Queue()) - outputs.append(Queue()) - t = gevent.spawn(binaryagreement, sid, i, N, f, coin, - inputs[i].get, outputs[i].put_nowait, sends[i], recvs[i]) - threads.append(t) - - for i in range(N): - inputs[i].put(random.randint(0,1)) - - outs = [outputs[i].get() for i in range(N) if i != byznode] - assert all(v in (0, 1) and v == outs[0] for v in outs) - - try: - gevent.joinall(threads) - except gevent.hub.LoopExit: - pass - - -@mark.parametrize('byznode', (1, 2, 3)) -def test_binaryagreement_dummy_with_byz_message_type(byznode): - N = 4 - f = 1 - seed = None - sid = 'sidA' - rnd = random.Random(seed) - router_seed = rnd.random() - sends, recvs = byzantine_broadcast_router( - N, seed=seed, byznode=byznode, byz_message_type='BUG') - threads = [] - inputs = [] - outputs = [] - coin = dummy_coin(sid, N, f) # One dummy coin function for all nodes - - for i in range(N): - inputs.append(Queue()) - outputs.append(Queue()) - t = gevent.spawn(binaryagreement, sid, i, N, f, coin, - inputs[i].get, outputs[i].put_nowait, sends[i], recvs[i]) - threads.append(t) - - for i in range(N): - inputs[i].put(random.randint(0,1)) - - outs = [outputs[i].get() for i in range(N) if i != byznode] - assert all(v in (0, 1) and v == outs[0] for v in outs) - - try: - gevent.joinall(threads) - except gevent.hub.LoopExit: - pass - - -### Test binary agreement with boldyreva coin -def _make_coins(sid, N, f, seed): - # Generate keys - PK, SKs = dealer(N, f+1) - rnd = random.Random(seed) - router_seed = rnd.random() - sends, recvs = simple_broadcast_router(N, seed=seed) - coins = [shared_coin(sid, i, N, f, PK, SKs[i], sends[i], recvs[i]) for i in range(N)] - return coins - -def _test_binaryagreement(N=4, f=1, seed=None): - # Generate keys - sid = 'sidA' - # Test everything when runs are OK - #if seed is not None: print 'SEED:', seed - rnd = random.Random(seed) - - # Instantiate the common coin - coins_seed = rnd.random() - coins = _make_coins(sid+'COIN', N, f, coins_seed) - - # Router - router_seed = rnd.random() - sends, recvs = simple_broadcast_router(N, seed=seed) - - threads = [] - inputs = [] - outputs = [] - - for i in range(N): - inputs.append(Queue()) - outputs.append(Queue()) - - t = gevent.spawn(binaryagreement, sid, i, N, f, coins[i], - inputs[i].get, outputs[i].put_nowait, sends[i], recvs[i]) - threads.append(t) - - for i in range(N): - inputs[i].put(random.randint(0,1)) - #gevent.killall(threads[N-f:]) - #gevent.sleep(3) - #for i in range(N-f, N): - # inputs[i].put(0) - try: - outs = [outputs[i].get() for i in range(N)] - assert len(set(outs)) == 1 - try: gevent.joinall(threads) - except gevent.hub.LoopExit: pass - except KeyboardInterrupt: - gevent.killall(threads) - raise - -def test_binaryagreement(): - for i in range(5): _test_binaryagreement(seed=i) - - -@mark.parametrize('values,s,already_decided,expected_est,' - 'expected_already_decided,expected_output', ( - ({0}, 0, None, 0, 0, 0), - ({1}, 1, None, 1, 1, 1), -)) -def test_set_next_round_estimate_with_decision(values, s, already_decided, - expected_est, expected_already_decided, expected_output): - from honeybadgerbft.core.binaryagreement import set_new_estimate - decide = Queue() - updated_est, updated_already_decided = set_new_estimate( - values=values, - s=s, - already_decided=already_decided, - decide=decide.put, - ) - assert updated_est == expected_est - assert updated_already_decided == expected_already_decided - assert decide.get() == expected_output - - -@mark.parametrize('values,s,already_decided,' - 'expected_est,expected_already_decided', ( - ({0}, 0, 1, 0, 1), - ({0}, 1, None, 0, None), - ({0}, 1, 0, 0, 0), - ({0}, 1, 1, 0, 1), - ({1}, 0, None, 1, None), - ({1}, 0, 0, 1, 0), - ({1}, 0, 1, 1, 1), - ({1}, 1, 0, 1, 0), - ({0, 1}, 0, None, 0, None), - ({0, 1}, 0, 0, 0, 0), - ({0, 1}, 0, 1, 0, 1), - ({0, 1}, 1, None, 1, None), - ({0, 1}, 1, 0, 1, 0), - ({0, 1}, 1, 1, 1, 1), -)) -def test_set_next_round_estimate(values, s, already_decided, - expected_est, expected_already_decided): - from honeybadgerbft.core.binaryagreement import set_new_estimate - decide = Queue() - updated_est, updated_already_decided = set_new_estimate( - values=values, - s=s, - already_decided=already_decided, - decide=decide.put, - ) - assert updated_est == expected_est - assert updated_already_decided == expected_already_decided - assert decide.empty() - - -@mark.parametrize('values,s,already_decided', ( - ({0}, 0, 0), - ({1}, 1, 1), -)) -def test_set_next_round_estimate_raises(values, s, already_decided): - from honeybadgerbft.core.binaryagreement import set_new_estimate - from honeybadgerbft.exceptions import AbandonedNodeError - with raises(AbandonedNodeError): - updated_est, updated_already_decided = set_new_estimate( - values=values, - s=s, - already_decided=already_decided, - decide=None, - ) - - -def test_issue59_attack(caplog): - from .byzantine import byz_ba_issue_59, broadcast_router - N = 4 - f = 1 - seed = None - sid = 'sidA' - rnd = random.Random(seed) - sends, recvs = broadcast_router(N) - threads = [] - inputs = [] - outputs = [] - - coins_seed = rnd.random() - coins = _make_coins(sid+'COIN', N, f, coins_seed) - - for i in range(4): - inputs.append(Queue()) - outputs.append(Queue()) - - t = gevent.spawn(byz_ba_issue_59, sid, 3, N, f, coins[3], - inputs[3].get, outputs[3].put_nowait, sends[3], recvs[3]) - threads.append(t) - - for i in (2, 0, 1): - t = gevent.spawn(binaryagreement, sid, i, N, f, coins[i], - inputs[i].get, outputs[i].put_nowait, sends[i], recvs[i]) - threads.append(t) - - inputs[0].put(0) # A_0 - inputs[1].put(0) # A_1 - inputs[2].put(1) # B - inputs[3].put(0) # F (x) - - try: - outs = [outputs[i].get() for i in range(N)] - except gevent.hub.LoopExit: - ba_node_2_log_records = [ - record for record in caplog.records - if record.nodeid == 2 and record.module == 'binaryagreement' - ] - round_0_records = [ - record for record in ba_node_2_log_records if record.epoch == 0 - ] - round_1_records = [ - record for record in ba_node_2_log_records if record.epoch == 1 - ] - conf_phase_record = [ - record for record in round_0_records - if record.message == 'Completed CONF phase with values = {0, 1}' - ] - assert len(conf_phase_record) == 1 - coin_value_record = [ - record for record in round_0_records - if record.message.startswith('Received coin with value = ') - ] - assert len(coin_value_record) == 1 - coin_value = coin_value_record[0].message.split('=')[1] - round_1_begin_log = [ - record for record in round_1_records - if record.message.startswith('Starting with est = ') - ] - assert len(round_1_begin_log) == 1 - est_value_round_1 = round_1_begin_log[0].message.split('=')[1] - assert est_value_round_1 == coin_value - - try: - gevent.joinall(threads) - except gevent.hub.LoopExit: - pass diff --git a/test/test_commoncoin.py b/test/test_commoncoin.py deleted file mode 100644 index f227bc12..00000000 --- a/test/test_commoncoin.py +++ /dev/null @@ -1,138 +0,0 @@ -import unittest -import gevent -import random -from gevent.queue import Queue -from honeybadgerbft.core.commoncoin import shared_coin -from honeybadgerbft.crypto.threshsig.boldyreva import dealer - -def simple_router(N, maxdelay=0.01, seed=None): - """Builds a set of connected channels, with random delay - @return (receives, sends) - """ - rnd = random.Random(seed) - #if seed is not None: print 'ROUTER SEED: %f' % (seed,) - - queues = [Queue() for _ in range(N)] - - def makeBroadcast(i): - def _send(j, o): - delay = rnd.random() * maxdelay - #print 'BC %8s [%2d -> %2d] %2.1f' % (o[0], i, j, delay*1000) - gevent.spawn_later(delay, queues[j].put, (i,o)) - #queues[j].put((i, o)) - def _bc(o): - for j in range(N): _send(j, o) - return _bc - - def makeRecv(j): - def _recv(): - (i,o) = queues[j].get() - #print 'RECV %8s [%2d -> %2d]' % (o[0], i, j) - return (i,o) - return _recv - - return ([makeBroadcast(i) for i in range(N)], - [makeRecv(j) for j in range(N)]) - - -def byzantine_router(N, maxdelay=0.01, seed=None, **byzargs): - """Builds a set of connected channels, with random delay. - - :return: (receives, sends) endpoints. - """ - rnd = random.Random(seed) - #if seed is not None: print 'ROUTER SEED: %f' % (seed,) - - queues = [Queue() for _ in range(N)] - - def makeBroadcast(i): - def _send(j, o): - delay = rnd.random() * maxdelay - gevent.spawn_later(delay, queues[j].put, (i,o)) - def _bc(o): - for j in range(N): _send(j, o) - return _bc - - def makeRecv(j): - def _recv(): - return queues[j].get() - - def _recv_redundant(): - i, o = queues[j].get() - if i == 3 and o[1] == 3: - o = list(o) - o[1] -= 1 - o = tuple(o) - return (i,o) - - def _recv_fail_pk_verify_share(): - (i,o) = queues[j].get() - if i == 3 and o[1] == 3: - o = list(o) - o[1] += 1 - o = tuple(o) - return (i,o) - - if j == byzargs.get('node') and byzargs.get('sig_redundant'): - return _recv_redundant - if j == byzargs.get('node') and byzargs.get('sig_err'): - return _recv_fail_pk_verify_share - return _recv - - return ([makeBroadcast(i) for i in range(N)], - [makeRecv(j) for j in range(N)]) - - -### Test -def _test_commoncoin(N=4, f=1, seed=None): - # Generate keys - PK, SKs = dealer(N, f+1) - sid = 'sidA' - # Test everything when runs are OK - #if seed is not None: print 'SEED:', seed - rnd = random.Random(seed) - router_seed = rnd.random() - sends, recvs = simple_router(N, seed=seed) - coins = [shared_coin(sid, i, N, f, PK, SKs[i], sends[i], recvs[i]) for i in range(N)] - - for i in range(10): - threads = [gevent.spawn(c, i) for c in coins] - gevent.joinall(threads) - assert len(set([t.value for t in threads])) == 1 - return True - - -def test_commoncoin(): - _test_commoncoin() - - -def test_when_signature_share_verify_fails(): - N = 4 - f = 1 - seed = None - PK, SKs = dealer(N, f+1) - sid = 'sidA' - rnd = random.Random(seed) - router_seed = rnd.random() - sends, recvs = byzantine_router(N, seed=seed, node=2, sig_err=True) - coins = [shared_coin(sid, i, N, f, PK, SKs[i], sends[i], recvs[i]) for i in range(N)] - for i in range(10): - threads = [gevent.spawn(c, i) for c in coins] - gevent.joinall(threads) - assert len(set([t.value for t in threads])) == 1 - - -def test_when_redundant_signature_share_is_received(): - N = 4 - f = 1 - seed = None - PK, SKs = dealer(N, f+1) - sid = 'sidA' - rnd = random.Random(seed) - router_seed = rnd.random() - sends, recvs = byzantine_router(N, seed=seed, node=2, sig_redundant=True) - coins = [shared_coin(sid, i, N, f, PK, SKs[i], sends[i], recvs[i]) for i in range(N)] - for i in range(10): - threads = [gevent.spawn(c, i) for c in coins] - gevent.joinall(threads) - assert len(set([t.value for t in threads])) == 1 diff --git a/test/test_commonsubset.py b/test/test_commonsubset.py deleted file mode 100644 index f5ac804b..00000000 --- a/test/test_commonsubset.py +++ /dev/null @@ -1,151 +0,0 @@ -import unittest -import gevent -import random -from gevent.event import Event -from gevent.queue import Queue -from honeybadgerbft.core.commoncoin import shared_coin -from honeybadgerbft.core.binaryagreement import binaryagreement -from honeybadgerbft.core.reliablebroadcast import reliablebroadcast -from honeybadgerbft.core.commonsubset import commonsubset -from honeybadgerbft.crypto.threshsig.boldyreva import dealer -from collections import defaultdict - -from pytest import mark - - -def simple_router(N, maxdelay=0.005, seed=None): - """Builds a set of connected channels, with random delay - @return (receives, sends) - """ - rnd = random.Random(seed) - #if seed is not None: print('ROUTER SEED: %f' % (seed,)) - - queues = [Queue() for _ in range(N)] - _threads = [] - - def makeSend(i): - def _send(j, o): - delay = rnd.random() * maxdelay - #delay = 0.1 - #print('SEND %8s [%2d -> %2d] %2.1f' % (o[0], i, j, delay*1000), o[1:]) - gevent.spawn_later(delay, queues[j].put_nowait, (i,o)) - return _send - - def makeRecv(j): - def _recv(): - (i,o) = queues[j].get() - #print('RECV %8s [%2d -> %2d]' % (o[0], i, j)) - return (i,o) - return _recv - - return ([makeSend(i) for i in range(N)], - [makeRecv(j) for j in range(N)]) - - - -### Make the threshold signature common coins -def _make_commonsubset(sid, pid, N, f, PK, SK, input, send, recv): - - def broadcast(o): - for j in range(N): send(j, o) - - coin_recvs = [None] * N - aba_recvs = [None] * N - rbc_recvs = [None] * N - - aba_inputs = [Queue(1) for _ in range(N)] - aba_outputs = [Queue(1) for _ in range(N)] - rbc_outputs = [Queue(1) for _ in range(N)] - - def _setup(j): - def coin_bcast(o): - broadcast(('ACS_COIN', j, o)) - - coin_recvs[j] = Queue() - coin = shared_coin(sid + 'COIN' + str(j), pid, N, f, PK, SK, - coin_bcast, coin_recvs[j].get) - - def aba_bcast(o): - broadcast(('ACS_ABA', j, o)) - - aba_recvs[j] = Queue() - aba = gevent.spawn(binaryagreement, sid+'ABA'+str(j), pid, N, f, coin, - aba_inputs[j].get, aba_outputs[j].put_nowait, - aba_bcast, aba_recvs[j].get) - - def rbc_send(k, o): - send(k, ('ACS_RBC', j, o)) - - # Only leader gets input - rbc_input = input if j == pid else None - rbc_recvs[j] = Queue() - rbc = gevent.spawn(reliablebroadcast, sid+'RBC'+str(j), pid, N, f, j, - rbc_input, rbc_recvs[j].get, rbc_send) - rbc_outputs[j] = rbc.get # block for output from rbc - - for j in range(N): _setup(j) - - def _recv(): - while True: - (sender, (tag, j, msg)) = recv() - if tag == 'ACS_COIN': coin_recvs[j].put_nowait((sender,msg)) - elif tag == 'ACS_RBC' : rbc_recvs [j].put_nowait((sender,msg)) - elif tag == 'ACS_ABA' : aba_recvs [j].put_nowait((sender,msg)) - else: - print('Unknown tag!!', tag) - raise - gevent.spawn(_recv) - - return commonsubset(pid, N, f, rbc_outputs, - [_.put_nowait for _ in aba_inputs], - [_.get for _ in aba_outputs]) - -### Test asynchronous common subset -def _test_commonsubset(N=4, f=1, seed=None): - # Generate keys - sid = 'sidA' - PK, SKs = dealer(N, f+1, seed=seed) - rnd = random.Random(seed) - #print('SEED:', seed) - router_seed = rnd.random() - sends, recvs = simple_router(N, seed=router_seed) - - inputs = [None] * N - threads = [None] * N - for i in range(N): - inputs[i] = Queue(1) - - threads[i] = gevent.spawn(_make_commonsubset, sid, i, N, f, - PK, SKs[i], - inputs[i].get, sends[i], recvs[i]) - - for i in range(N): - if i == 1: continue - inputs[i].put('<[ACS Input %d]>' % i) - - #gevent.killall(threads[N-f:]) - #gevent.sleep(3) - #for i in range(N-f, N): - # inputs[i].put(0) - try: - outs = [threads[i].get() for i in range(N)] - - # Consistency check - assert len(set(outs)) == 1 - - except KeyboardInterrupt: - gevent.killall(threads) - raise - -from nose2.tools import params - -#@params(*range(100)) -#def test_commonsubset(i): -# _test_commonsubset(seed=i) - #_test_commonsubset(seed=1) - - -#@mark.skip('python 3 problem with gevent') -def test_commonsubset(): - _test_commonsubset() - diff --git a/test/test_honeybadger.py b/test/test_honeybadger.py deleted file mode 100644 index 28cdfe29..00000000 --- a/test/test_honeybadger.py +++ /dev/null @@ -1,147 +0,0 @@ -import random -from collections import defaultdict - -import gevent -from gevent.event import Event -from gevent.queue import Queue -from pytest import fixture, mark, raises - -import honeybadgerbft.core.honeybadger -#reload(honeybadgerbft.core.honeybadger) -from honeybadgerbft.core.honeybadger import HoneyBadgerBFT -from honeybadgerbft.crypto.threshsig.boldyreva import dealer -from honeybadgerbft.crypto.threshenc import tpke -from honeybadgerbft.core.honeybadger import BroadcastTag - - -@fixture -def recv_queues(request): - from honeybadgerbft.core.honeybadger import BroadcastReceiverQueues - number_of_nodes = getattr(request, 'N', 4) - queues = { - tag.value: [Queue() for _ in range(number_of_nodes)] - for tag in BroadcastTag if tag != BroadcastTag.TPKE - } - queues[BroadcastTag.TPKE.value] = Queue() - return BroadcastReceiverQueues(**queues) - - -from pytest import mark - - -def simple_router(N, maxdelay=0.005, seed=None): - """Builds a set of connected channels, with random delay - - :return: (receives, sends) - """ - rnd = random.Random(seed) - #if seed is not None: print 'ROUTER SEED: %f' % (seed,) - - queues = [Queue() for _ in range(N)] - _threads = [] - - def makeSend(i): - def _send(j, o): - delay = rnd.random() * maxdelay - if not i%3: - delay *= 1000 - #delay = 0.1 - #print 'SEND %8s [%2d -> %2d] %2.1f' % (o[0], i, j, delay*1000), o[1:] - gevent.spawn_later(delay, queues[j].put_nowait, (i,o)) - return _send - - def makeRecv(j): - def _recv(): - (i,o) = queues[j].get() - #print 'RECV %8s [%2d -> %2d]' % (o[0], i, j) - return (i,o) - return _recv - - return ([makeSend(i) for i in range(N)], - [makeRecv(j) for j in range(N)]) - - -### Test asynchronous common subset -def _test_honeybadger(N=4, f=1, seed=None): - sid = 'sidA' - # Generate threshold sig keys - sPK, sSKs = dealer(N, f+1, seed=seed) - # Generate threshold enc keys - ePK, eSKs = tpke.dealer(N, f+1) - - rnd = random.Random(seed) - #print 'SEED:', seed - router_seed = rnd.random() - sends, recvs = simple_router(N, seed=router_seed) - - badgers = [None] * N - threads = [None] * N - for i in range(N): - badgers[i] = HoneyBadgerBFT(sid, i, 1, N, f, - sPK, sSKs[i], ePK, eSKs[i], - sends[i], recvs[i]) - threads[i] = gevent.spawn(badgers[i].run) - - for i in range(N): - #if i == 1: continue - badgers[i].submit_tx('<[HBBFT Input %d]>' % i) - - for i in range(N): - badgers[i].submit_tx('<[HBBFT Input %d]>' % (i+10)) - - for i in range(N): - badgers[i].submit_tx('<[HBBFT Input %d]>' % (i+20)) - - #gevent.killall(threads[N-f:]) - #gevent.sleep(3) - #for i in range(N-f, N): - # inputs[i].put(0) - try: - outs = [threads[i].get() for i in range(N)] - - # Consistency check - assert len(set(outs)) == 1 - - except KeyboardInterrupt: - gevent.killall(threads) - raise - - -#@mark.skip('python 3 problem with gevent') -def test_honeybadger(): - _test_honeybadger() - - -@mark.parametrize('message', ('broadcast message',)) -@mark.parametrize('node_id', range(4)) -@mark.parametrize('tag', [e.value for e in BroadcastTag]) -@mark.parametrize('sender', range(4)) -def test_broadcast_receiver_loop(sender, tag, node_id, message, recv_queues): - from honeybadgerbft.core.honeybadger import broadcast_receiver_loop - recv = Queue() - recv.put((sender, (tag, node_id, message))) - gevent.spawn(broadcast_receiver_loop, recv.get, recv_queues) - recv_queue = getattr(recv_queues, tag) - if tag != BroadcastTag.TPKE.value: - recv_queue = recv_queue[node_id] - assert recv_queue,get() == (sender, message) - - -@mark.parametrize('message', ('broadcast message',)) -@mark.parametrize('node_id', range(4)) -@mark.parametrize('tag', ('BogusTag', None, 123)) -@mark.parametrize('sender', range(4)) -def test_broadcast_receiver_loop_raises(sender, tag, node_id, message, recv_queues): - from honeybadgerbft.core.honeybadger import broadcast_receiver_loop - from honeybadgerbft.exceptions import UnknownTagError - recv = Queue() - recv.put((sender, (tag, node_id, message))) - with raises(UnknownTagError) as exc: - broadcast_receiver_loop(recv.get, recv_queues) - expected_err_msg = 'Unknown tag: {}! Must be one of {}.'.format( - tag, BroadcastTag.__members__.keys()) - assert exc.value.args[0] == expected_err_msg - recv_queues_dict = recv_queues._asdict() - tpke_queue = recv_queues_dict.pop(BroadcastTag.TPKE.value) - assert tpke_queue.empty() - assert all([q.empty() for queues in recv_queues_dict.values() for q in queues]) diff --git a/test/test_honeybadger_block.py b/test/test_honeybadger_block.py deleted file mode 100644 index fbf3ac3c..00000000 --- a/test/test_honeybadger_block.py +++ /dev/null @@ -1,210 +0,0 @@ -import unittest -import gevent -import random -from gevent.event import Event -from gevent.queue import Queue -from honeybadgerbft.core.commoncoin import shared_coin -from honeybadgerbft.core.binaryagreement import binaryagreement -from honeybadgerbft.core.reliablebroadcast import reliablebroadcast -from honeybadgerbft.core.commonsubset import commonsubset -import honeybadgerbft.core.honeybadger_block -#reload(honeybadgerbft.core.honeybadger_block) -from honeybadgerbft.core.honeybadger_block import honeybadger_block -from honeybadgerbft.crypto.threshsig.boldyreva import dealer -from honeybadgerbft.crypto.threshenc import tpke -from collections import defaultdict - -from pytest import mark - - -def simple_router(N, maxdelay=0.005, seed=None): - """Builds a set of connected channels, with random delay - @return (receives, sends) - """ - rnd = random.Random(seed) - #if seed is not None: print('ROUTER SEED: %f' % (seed,)) - - queues = [Queue() for _ in range(N)] - _threads = [] - - def makeSend(i): - def _send(j, o): - delay = rnd.random() * maxdelay - #delay = 0.1 - #print('SEND %8s [%2d -> %2d] %2.1f' % (o[0], i, j, delay*1000), o[1:]) - gevent.spawn_later(delay, queues[j].put_nowait, (i,o)) - return _send - - def makeRecv(j): - def _recv(): - (i,o) = queues[j].get() - #print('RECV %8s [%2d -> %2d]' % (o[0], i, j) - return (i,o) - return _recv - - return ([makeSend(i) for i in range(N)], - [makeRecv(j) for j in range(N)]) - - -### Make the threshold signature common coins -def _make_honeybadger(sid, pid, N, f, sPK, sSK, ePK, eSK, input, send, recv): - from honeybadgerbft.core.honeybadger import (BroadcastTag, - BroadcastReceiverQueues, - broadcast_receiver_loop) - - def broadcast(o): - for j in range(N): send(j, o) - - coin_recvs = [None] * N - aba_recvs = [None] * N - rbc_recvs = [None] * N - - aba_inputs = [Queue(1) for _ in range(N)] - aba_outputs = [Queue(1) for _ in range(N)] - rbc_outputs = [Queue(1) for _ in range(N)] - - my_rbc_input = Queue(1) - - def _setup(j): - def coin_bcast(o): - broadcast(('ACS_COIN', j, o)) - - coin_recvs[j] = Queue() - coin = shared_coin(sid + 'COIN' + str(j), pid, N, f, sPK, sSK, - coin_bcast, coin_recvs[j].get) - - def aba_bcast(o): - broadcast(('ACS_ABA', j, o)) - - aba_recvs[j] = Queue() - aba = gevent.spawn(binaryagreement, sid+'ABA'+str(j), pid, N, f, coin, - aba_inputs[j].get, aba_outputs[j].put_nowait, - aba_bcast, aba_recvs[j].get) - - def rbc_send(k, o): - send(k, ('ACS_RBC', j, o)) - - # Only leader gets input - rbc_input = my_rbc_input.get if j == pid else None - rbc_recvs[j] = Queue() - rbc = gevent.spawn(reliablebroadcast, sid+'RBC'+str(j), pid, N, f, j, - rbc_input, rbc_recvs[j].get, rbc_send) - rbc_outputs[j] = rbc.get # block for output from rbc - - # N instances of ABA, RBC - for j in range(N): _setup(j) - - # One instance of TPKE - def tpke_bcast(o): - broadcast(('TPKE', 0, o)) - - tpke_recv = Queue() - - # One instance of ACS - acs = gevent.spawn(commonsubset, pid, N, f, rbc_outputs, - [_.put_nowait for _ in aba_inputs], - [_.get for _ in aba_outputs]) - - recv_queues = BroadcastReceiverQueues(**{ - BroadcastTag.ACS_COIN.value: coin_recvs, - BroadcastTag.ACS_RBC.value: rbc_recvs, - BroadcastTag.ACS_ABA.value: aba_recvs, - BroadcastTag.TPKE.value: tpke_recv, - }) - gevent.spawn(broadcast_receiver_loop, recv, recv_queues) - - return honeybadger_block(pid, N, f, ePK, eSK, input, - acs_in=my_rbc_input.put_nowait, acs_out=acs.get, - tpke_bcast=tpke_bcast, tpke_recv=tpke_recv.get) - - -### Test asynchronous common subset -def _test_honeybadger(N=4, f=1, seed=None): - # Generate threshold sig keys - sid = 'sidA' - sPK, sSKs = dealer(N, f+1, seed=seed) - ePK, eSKs = tpke.dealer(N, f+1) - - rnd = random.Random(seed) - #print('SEED:', seed) - router_seed = rnd.random() - sends, recvs = simple_router(N, seed=router_seed) - - inputs = [None] * N - threads = [None] * N - for i in range(N): - inputs[i] = Queue(1) - threads[i] = gevent.spawn(_make_honeybadger, sid, i, N, f, - sPK, sSKs[i], - ePK, eSKs[i], - inputs[i].get, sends[i], recvs[i]) - - for i in range(N): - #if i == 1: continue - inputs[i].put('<[HBBFT Input %d]>' % i) - - #gevent.killall(threads[N-f:]) - #gevent.sleep(3) - #for i in range(N-f, N): - # inputs[i].put(0) - try: - outs = [threads[i].get() for i in range(N)] - - # Consistency check - assert len(set(outs)) == 1 - - except KeyboardInterrupt: - gevent.killall(threads) - raise - - -#@mark.skip('python 3 problem with gevent') -def test_honeybadger(): - _test_honeybadger() - - -def test_honeybadger_block_with_missing_input(): - N = 4 - f = 1 - seed = None - sid = 'sidA' - sPK, sSKs = dealer(N, f+1, seed=seed) - ePK, eSKs = tpke.dealer(N, f+1) - rnd = random.Random(seed) - router_seed = rnd.random() - sends, recvs = simple_router(N, seed=router_seed) - inputs = [None] * N - threads = [None] * N - for i in range(N): - inputs[i] = Queue(1) - threads[i] = gevent.spawn(_make_honeybadger, sid, i, N, f, - sPK, sSKs[i], - ePK, eSKs[i], - inputs[i].get, sends[i], recvs[i]) - - for i in range(N): - if i != 1: - inputs[i].put('<[HBBFT Input %d]>' % i) - - gevent.joinall(threads, timeout=0.5) - assert all([t.value is None for t in threads]) - - -def broadcast_receiver_duplicates_share(recv_func, recv_queues): - from honeybadgerbft.core.honeybadger import BroadcastTag - sender, (tag, j, msg) = recv_func() - recv_queue = getattr(recv_queues, tag) - - if tag == BroadcastTag.TPKE.value: - recv_queue.put_nowait((sender, msg)) - recv_queue.put_nowait((sender, msg)) - else: - recv_queue = recv_queue[j] - recv_queue.put_nowait((sender, msg)) - - -def test_when_duplicate_share_is_received(monkeypatch): - from honeybadgerbft.core import honeybadger - monkeypatch.setattr( - honeybadger, 'broadcast_receiver', broadcast_receiver_duplicates_share) - _test_honeybadger() diff --git a/test/test_rbc.py b/test/test_rbc.py deleted file mode 100644 index 4cfbd771..00000000 --- a/test/test_rbc.py +++ /dev/null @@ -1,320 +0,0 @@ -import random - -import gevent -from gevent import Greenlet -from gevent.queue import Queue -from pytest import mark, raises - -from honeybadgerbft.core.reliablebroadcast import reliablebroadcast, encode, decode -from honeybadgerbft.core.reliablebroadcast import hash, merkleTree, getMerkleBranch, merkleVerify - - -### Merkle tree -def test_merkletree0(): - mt = merkleTree(["hello"]) - assert mt == [b'', hash("hello")] - -def test_merkletree1(): - strList = ["hello","hi","ok"] - mt = merkleTree(strList) - roothash = mt[1] - assert len(mt) == 8 - for i in range(3): - val = strList[i] - branch = getMerkleBranch(i, mt) - assert merkleVerify(3, val, roothash, branch, i) - -### Zfec -def test_zfec1(): - K = 3 - N = 10 - m = b"hello this is a test string" - stripes = encode(K, N, m) - assert decode(K, N, stripes) == m - _s = list(stripes) - # Test by setting some to None - _s[0] = _s[1] = _s[4] = _s[5] = _s[6] = None - assert decode(K, N, _s) == m - _s[3] = _s[7] = None - assert decode(K, N, _s) == m - _s[8] = None - with raises(ValueError) as exc: - decode(K, N, _s) - assert exc.value.args[0] == 'Too few to recover' - -### RBC -def simple_router(N, maxdelay=0.01, seed=None): - """Builds a set of connected channels, with random delay - @return (receives, sends) - """ - rnd = random.Random(seed) - #if seed is not None: print 'ROUTER SEED: %f' % (seed,) - - queues = [Queue() for _ in range(N)] - - def makeSend(i): - def _send(j, o): - delay = rnd.random() * maxdelay - #print 'SEND %8s [%2d -> %2d] %.2f' % (o[0], i, j, delay) - gevent.spawn_later(delay, queues[j].put, (i,o)) - #queues[j].put((i, o)) - return _send - - def makeRecv(j): - def _recv(): - (i,o) = queues[j].get() - #print 'RECV %8s [%2d -> %2d]' % (o[0], i, j) - return (i,o) - return _recv - - return ([makeSend(i) for i in range(N)], - [makeRecv(j) for j in range(N)]) - - -def byzantine_router(N, maxdelay=0.01, seed=None, **byzargs): - """Builds a set of connected channels, with random delay, - and possibly byzantine behavior. - """ - rnd = random.Random(seed) - queues = [Queue() for _ in range(N)] - - def makeSend(i): - def _send(j, o): - delay = rnd.random() * maxdelay - if i == byzargs.get('byznode'): - if o[0] == byzargs.get('message_type'): - screwed_up = list(o) - if o[0] in ('VAL', 'ECHO'): - screwed_up[3] = 'screw it' - o = tuple(screwed_up) - if byzargs.get('invalid_message_type'): - byz_o = list(o) - byz_o[0] = byzargs.get('invalid_message_type') - o = tuple(byz_o) - if (byzargs.get('fake_sender') and - o[0] == 'VAL' and i == byzargs.get('byznode')): - gevent.spawn_later(delay, queues[j].put, ((i + 1) % 4, o)) - elif byzargs.get('slow_echo') and i != 2: - if o[0] == 'READY': - gevent.spawn_later(delay*0.001, queues[j].put, (i, o)) - elif o[0] == 'ECHO': - gevent.spawn_later(delay*10, queues[j].put, (i, o)) - else: - gevent.spawn_later(delay, queues[j].put, (i, o)) - else: - gevent.spawn_later(delay, queues[j].put, (i, o)) - if byzargs.get('redundant_message_type') == o[0]: - gevent.spawn_later(delay, queues[j].put, (i, o)) - - return _send - - def makeRecv(j): - def _recv(): - i, o = queues[j].get() - return i ,o - return _recv - - return ([makeSend(i) for i in range(N)], - [makeRecv(j) for j in range(N)]) - - -def _test_rbc1(N=4, f=1, leader=None, seed=None): - # Test everything when runs are OK - #if seed is not None: print 'SEED:', seed - sid = 'sidA' - rnd = random.Random(seed) - router_seed = rnd.random() - if leader is None: leader = rnd.randint(0,N-1) - sends, recvs = simple_router(N, seed=seed) - threads = [] - leader_input = Queue(1) - for i in range(N): - input = leader_input.get if i == leader else None - t = Greenlet(reliablebroadcast, sid, i, N, f, leader, input, recvs[i], sends[i]) - t.start() - threads.append(t) - - m = b"Hello! This is a test message." - leader_input.put(m) - gevent.joinall(threads) - assert [t.value for t in threads] == [m]*N - - -@mark.parametrize('seed', range(20)) -@mark.parametrize('N,f', ((4, 1), (5, 1), (8, 2))) -def test_rbc1(N, f, seed): - _test_rbc1(N=N, f=f, seed=seed) - - -def _test_rbc2(N=4, f=1, leader=None, seed=None): - # Crash up to f nodes - #if seed is not None: print 'SEED:', seed - sid = 'sidA' - rnd = random.Random(seed) - router_seed = rnd.random() - if leader is None: leader = rnd.randint(0,N-1) - sends, recvs = simple_router(N, seed=router_seed) - threads = [] - leader_input = Queue(1) - - for i in range(N): - input = leader_input.get if i == leader else None - t = Greenlet(reliablebroadcast, sid, i, N, f, leader, input, recvs[i], sends[i]) - t.start() - threads.append(t) - - m = b"Hello!asdfasdfasdfasdfasdfsadf" - leader_input.put(m) - gevent.sleep(0) # Let the leader get out its first message - - # Crash f of the nodes - crashed = set() - #print 'Leader:', leader - for _ in range(f): - i = rnd.choice(range(N)) - crashed.add(i) - threads[i].kill() - threads[i].join() - #print 'Crashed:', crashed - gevent.joinall(threads) - for i,t in enumerate(threads): - if i not in crashed: assert t.value == m - - -@mark.parametrize('seed', range(20)) -@mark.parametrize('N,f', ((4, 1), (5, 1), (8, 2))) -def test_rbc2(N, f, seed): - _test_rbc2(N=N, f=f, seed=seed) - - -@mark.parametrize('seed', range(20)) -@mark.parametrize('tag', ('VAL', 'ECHO')) -@mark.parametrize('N,f', ((4, 1), (5, 1), (8, 2))) -def test_rbc_when_merkle_verify_fails(N, f, tag, seed): - rnd = random.Random(seed) - leader = rnd.randint(0, N-1) - byznode = 1 - sends, recvs = byzantine_router( - N, seed=seed, byznode=byznode, message_type=tag) - threads = [] - leader_input = Queue(1) - for pid in range(N): - sid = 'sid{}'.format(leader) - input = leader_input.get if pid == leader else None - t = Greenlet(reliablebroadcast, sid, pid, N, f, leader, input, recvs[pid], sends[pid]) - t.start() - threads.append(t) - - m = b"Hello! This is a test message." - leader_input.put(m) - completed_greenlets = gevent.joinall(threads, timeout=0.5) - expected_rbc_result = None if leader == byznode and tag == 'VAL' else m - assert all([t.value == expected_rbc_result for t in threads]) - - -@mark.parametrize('seed', range(3)) -@mark.parametrize('N,f', ((4, 1), (5, 1), (8, 2))) -def test_rbc_receives_val_from_sender_not_leader(N, f, seed): - rnd = random.Random(seed) - leader = rnd.randint(0, N-1) - sends, recvs = byzantine_router( - N, seed=seed, fake_sender=True, byznode=leader) - threads = [] - leader_input = Queue(1) - for pid in range(N): - sid = 'sid{}'.format(leader) - input = leader_input.get if pid == leader else None - t = Greenlet(reliablebroadcast, sid, pid, N, f, leader, input, recvs[pid], sends[pid]) - t.start() - threads.append(t) - - m = "Hello! This is a test message." - leader_input.put(m) - completed_greenlets = gevent.joinall(threads, timeout=0.5) - expected_rbc_result = None - assert all([t.value == expected_rbc_result for t in threads]) - - -@mark.parametrize('seed', range(2)) -@mark.parametrize('tag', ('ECHO', 'READY')) -@mark.parametrize('N,f', ((4, 1),)) -def test_rbc_with_redundant_message(N, f, tag, seed): - rnd = random.Random(seed) - leader = rnd.randint(0, N-1) - sends, recvs = byzantine_router(N, seed=seed, redundant_message_type=tag) - threads = [] - leader_input = Queue(1) - for pid in range(N): - sid = 'sid{}'.format(leader) - input = leader_input.get if pid == leader else None - t = Greenlet(reliablebroadcast, sid, pid, N, f, - leader, input, recvs[pid], sends[pid]) - t.start() - threads.append(t) - - m = b"Hello! This is a test message." - leader_input.put(m) - completed_greenlets = gevent.joinall(threads, timeout=0.5) - expected_rbc_result = m - assert all([t.value == expected_rbc_result for t in threads]) - - -@mark.parametrize('seed', range(1)) -@mark.parametrize('N,f', ((4, 1),)) -def test_rbc_decode_in_echo_handling_step(N, f, seed): - """The goal of this test is to simply force the decode operation - to take place upon rception of an ECHO message, (when other - necessary conditions are met), as opposed to the operation taking - place upon reception of a READY message. - - The test is perhaps hackish at best, but nevertheless does achieve - its intent. - - The test slows down the broadcasting of ECHO messages, meanwhile - speeding up the broadcasting of READY messages. - """ - rnd = random.Random(seed) - leader = rnd.randint(0, N-1) - sends, recvs = byzantine_router(N, seed=seed, slow_echo=True) - threads = [] - leader_input = Queue(1) - for pid in range(N): - sid = 'sid{}'.format(leader) - input = leader_input.get if pid == leader else None - t = Greenlet(reliablebroadcast, sid, pid, N, f, - leader, input, recvs[pid], sends[pid]) - t.start() - threads.append(t) - - m = b"Hello! This is a test message." - leader_input.put(m) - completed_greenlets = gevent.joinall(threads, timeout=1) - expected_rbc_result = m - assert all([t.value == expected_rbc_result for t in threads]) - - -@mark.parametrize('seed', range(2)) -@mark.parametrize('tag', ('CHECKTHISOUT!', 'LETSGO!')) -@mark.parametrize('N,f', ((4, 1),)) -def test_rbc_with_invalid_message(N, f, tag, seed): - rnd = random.Random(seed) - leader = rnd.randint(0, N-1) - sends, recvs = byzantine_router(N, seed=seed, invalid_message_type=tag) - threads = [] - leader_input = Queue(1) - for pid in range(N): - sid = 'sid{}'.format(leader) - input = leader_input.get if pid == leader else None - t = Greenlet(reliablebroadcast, sid, pid, N, f, - leader, input, recvs[pid], sends[pid]) - t.start() - threads.append(t) - - m = "Hello! This is a test message." - leader_input.put(m) - completed_greenlets = gevent.joinall(threads, timeout=0.5) - expected_rbc_result = None - assert all([t.value == expected_rbc_result for t in threads]) - - -# TODO: Test more edge cases, like Byzantine behavior diff --git a/test/test_threshenc.py b/test/test_threshenc.py deleted file mode 100644 index 48c8d5fc..00000000 --- a/test/test_threshenc.py +++ /dev/null @@ -1,52 +0,0 @@ -import unittest -from charm.toolbox.pairinggroup import PairingGroup,ZR,G1,G2,GT,pair -import random -from honeybadgerbft.crypto.threshenc.tpke import TPKEPublicKey, TPKEPrivateKey, dealer -from Crypto.Hash import SHA256 -from Crypto import Random -from Crypto.Cipher import AES - -def test_threshenc(): - PK, SKs = dealer(players=100,k=35) - - m = SHA256.new(b'hello world').digest() - C = PK.encrypt(m) - - assert PK.verify_ciphertext(*C) - - shares = [sk.decrypt_share(*C) for sk in SKs] - for i,share in enumerate(shares): - assert PK.verify_share(i, share, *C) - - SS = list(range(PK.l)) - for i in range(1): - random.shuffle(SS) - S = set(SS[:PK.k]) - - m_ = PK.combine_shares(*C, dict((s,shares[s]) for s in S)) - assert m_ == m - -def test_threshenc2(): - # Failure cases - PK, SKs = dealer(players=100,k=35) - - m = SHA256.new(b'hello world').digest() - C = PK.encrypt(m) - - assert PK.verify_ciphertext(*C) - - shares = [sk.decrypt_share(*C) for sk in SKs] - for i,share in enumerate(shares): - assert PK.verify_share(i, share, *C) - - SS = list(range(PK.l)) - random.shuffle(SS) - # Perturb one of the keys - shares[SS[0]] += shares[SS[0]] - S = set(SS[:PK.k]) - - try: - m_ = PK.combine_shares(*C, dict((s,shares[s]) for s in S)) - assert m_ == m - except AssertionError: pass - else: assert False, "Combine shares should have raised an error" From 11c996ec950fb2cbd0178e0ba9b5b44b1b58324c Mon Sep 17 00:00:00 2001 From: samuels Date: Sat, 5 Feb 2022 16:14:30 +0000 Subject: [PATCH 04/29] Now really added our_start.sh --- our_start.sh | 10 +++++ test/my_test.py | 115 ++++++++++++++++++++++++++++++++++++++++++++++++ test/utils.py | 5 +++ 3 files changed, 130 insertions(+) create mode 100755 our_start.sh create mode 100755 test/my_test.py create mode 100644 test/utils.py diff --git a/our_start.sh b/our_start.sh new file mode 100755 index 00000000..ea872492 --- /dev/null +++ b/our_start.sh @@ -0,0 +1,10 @@ +#!/bin/bash +echo "Killing running dockers" +kill -9 `ps | grep docker-compose | awk '{print $1}'` +sleep 1 +echo "Running docker" +docker-compose run honeybadger >/dev/null 2>/dev/null & +sleep 1 +echo "Running my_test.py" +docker exec -it `docker ps | tail -n 1 | awk '{print $1}'` /bin/bash -c "python our_tests/my_test.py" +echo "Done!" diff --git a/test/my_test.py b/test/my_test.py new file mode 100755 index 00000000..2db28a74 --- /dev/null +++ b/test/my_test.py @@ -0,0 +1,115 @@ +import random +from collections import defaultdict +import math +from datetime import datetime + +import gevent +from gevent.event import Event +from gevent.queue import Queue +from pytest import fixture, mark, raises + +import honeybadgerbft.core.honeybadger +#reload(honeybadgerbft.core.honeybadger) +from honeybadgerbft.core.honeybadger import HoneyBadgerBFT +from honeybadgerbft.crypto.threshsig.boldyreva import dealer +from honeybadgerbft.crypto.threshenc import tpke +from honeybadgerbft.core.honeybadger import BroadcastTag +from utils import log + +@fixture +def recv_queues(request): + from honeybadgerbft.core.honeybadger import BroadcastReceiverQueues + number_of_nodes = getattr(request, 'N', 4) + queues = { + tag.value: [Queue() for _ in range(number_of_nodes)] + for tag in BroadcastTag if tag != BroadcastTag.TPKE + } + queues[BroadcastTag.TPKE.value] = Queue() + return BroadcastReceiverQueues(**queues) + + + +def simple_router(N, maxdelay=0.005, seed=None): + """Builds a set of connected channels, with random delay + + :return: (receives, sends) + """ + rnd = random.Random(seed) + #if seed is not None: print 'ROUTER SEED: %f' % (seed,) + + queues = [Queue() for _ in range(N)] + _threads = [] + + def makeSend(i): + def _send(j, o): + delay = rnd.random() * maxdelay + delay *= math.log(len(o)) * 7.5 + gevent.spawn_later(delay, queues[j].put_nowait, (i,o)) + return _send + + def makeRecv(j): + def _recv(): + (i,o) = queues[j].get() + #print 'RECV %8s [%2d -> %2d]' % (o[0], i, j) + return (i,o) + return _recv + + return ([makeSend(i) for i in range(N)], + [makeRecv(j) for j in range(N)]) + + +### Test asynchronous common subset +def test_honeybadger(N=4, f=1, seed=None): + sid = 'sidA' + # Generate threshold sig keys + sPK, sSKs = dealer(N, f+1, seed=seed) + # Generate threshold enc keys + ePK, eSKs = tpke.dealer(N, f+1) + + rnd = random.Random(seed) + #print 'SEED:', seed + router_seed = rnd.random() + sends, recvs = simple_router(N, seed=router_seed) + + badgers = [None] * N + threads = [None] * N + for i in range(N): + badgers[i] = HoneyBadgerBFT(sid, i, 1, N, f, + sPK, sSKs[i], ePK, eSKs[i], + sends[i], recvs[i]) + threads[i] = gevent.spawn(badgers[i].run) + + time_at_start = datetime.now().timestamp() + log(f"Time at start: {time_at_start}") + + for i in range(N): + #if i == 1: continue + badgers[i].submit_tx('<[HBBFT Input {}]>'.format(i)*100000) + log("Done submitting big input") + for i in range(N): + badgers[i].submit_tx('<[HBBFT Input %d]>' % (i+10)) + + for i in range(N): + badgers[i].submit_tx('<[HBBFT Input %d]>' % (i+20)) + + #gevent.killall(threads[N-f:]) + #gevent.sleep(3) + #for i in range(N-f, N): + # inputs[i].put(0) + try: + outs = [threads[i].get() for i in range(N)] + + # Consistency check + assert len(set(outs)) == 1 + + time_at_end = datetime.now().timestamp() + time_diff = time_at_end - time_at_start + log(f"Time passed: {time_diff}") + + except KeyboardInterrupt: + gevent.killall(threads) + raise + +log("Starting!") +test_honeybadger() +log("Finished test!") diff --git a/test/utils.py b/test/utils.py new file mode 100644 index 00000000..a07b9d55 --- /dev/null +++ b/test/utils.py @@ -0,0 +1,5 @@ +LOG_PATH = "./test_log.txt" +def log(msg): + print(msg) + with open(LOG_PATH, 'a') as f: + f.write(msg) From f41fe90414a9578d91bb9d173fe60aae00bb4160 Mon Sep 17 00:00:00 2001 From: samuels Date: Sat, 5 Feb 2022 16:21:19 +0000 Subject: [PATCH 05/29] Use logs and test normally --- our_start.sh | 10 ---------- test/my_test.py | 3 --- test/utils.py | 7 ++++++- 3 files changed, 6 insertions(+), 14 deletions(-) delete mode 100755 our_start.sh diff --git a/our_start.sh b/our_start.sh deleted file mode 100755 index ea872492..00000000 --- a/our_start.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -echo "Killing running dockers" -kill -9 `ps | grep docker-compose | awk '{print $1}'` -sleep 1 -echo "Running docker" -docker-compose run honeybadger >/dev/null 2>/dev/null & -sleep 1 -echo "Running my_test.py" -docker exec -it `docker ps | tail -n 1 | awk '{print $1}'` /bin/bash -c "python our_tests/my_test.py" -echo "Done!" diff --git a/test/my_test.py b/test/my_test.py index 2db28a74..49105a0c 100755 --- a/test/my_test.py +++ b/test/my_test.py @@ -110,6 +110,3 @@ def test_honeybadger(N=4, f=1, seed=None): gevent.killall(threads) raise -log("Starting!") -test_honeybadger() -log("Finished test!") diff --git a/test/utils.py b/test/utils.py index a07b9d55..d984600c 100644 --- a/test/utils.py +++ b/test/utils.py @@ -1,5 +1,10 @@ -LOG_PATH = "./test_log.txt" +import os +LOG_DIR = "./logs" +LOG_PATH = LOG_DIR + "/test_log.txt" def log(msg): print(msg) + msg += "\n" + if not os.path.isdir(LOG_DIR): + os.mkdir(LOG_DIR) with open(LOG_PATH, 'a') as f: f.write(msg) From 3272ff22776e81c8827ec315e11ecfea26e0b494 Mon Sep 17 00:00:00 2001 From: samuels Date: Sat, 5 Feb 2022 16:37:40 +0000 Subject: [PATCH 06/29] Amazing logging --- .gitignore | 23 +---------------------- test/consts.py | 4 ++++ test/my_test.py | 13 +++++++++---- test/utils.py | 33 ++++++++++++++++++++++++++------- 4 files changed, 40 insertions(+), 33 deletions(-) create mode 100644 test/consts.py diff --git a/.gitignore b/.gitignore index 427d6888..333c1e91 100644 --- a/.gitignore +++ b/.gitignore @@ -1,22 +1 @@ -# IDE junk files -.idea/* -*.pyc -*~ -#*# -tmp* -ec2/logs/* -ec2/logs_old/* -ec2/hosts -*_keys -*.keys - -# Unit test / coverage reports -.cache -.coverage -.coverage.* -coverage.xml -htmlcov/ -.pytest_cache - -# Sphinx documentation -docs/_build/ +logs/ diff --git a/test/consts.py b/test/consts.py new file mode 100644 index 00000000..5edc8f33 --- /dev/null +++ b/test/consts.py @@ -0,0 +1,4 @@ +LOG_DIR = './logs' +LOG_PATH = LOG_DIR + '/ssh_detector_{}_{}_{}_{}_{}_{}.log' +LOGGER_NAME = 'ssh_detector_logger' + diff --git a/test/my_test.py b/test/my_test.py index 49105a0c..19b3d9bd 100755 --- a/test/my_test.py +++ b/test/my_test.py @@ -14,7 +14,9 @@ from honeybadgerbft.crypto.threshsig.boldyreva import dealer from honeybadgerbft.crypto.threshenc import tpke from honeybadgerbft.core.honeybadger import BroadcastTag -from utils import log +from logging import getLogger +from utils import setup_logging +from consts import * @fixture def recv_queues(request): @@ -60,6 +62,9 @@ def _recv(): ### Test asynchronous common subset def test_honeybadger(N=4, f=1, seed=None): + setup_logging() + logger = getLogger(LOGGER_NAME) + sid = 'sidA' # Generate threshold sig keys sPK, sSKs = dealer(N, f+1, seed=seed) @@ -80,12 +85,12 @@ def test_honeybadger(N=4, f=1, seed=None): threads[i] = gevent.spawn(badgers[i].run) time_at_start = datetime.now().timestamp() - log(f"Time at start: {time_at_start}") + logger.info(f"Time at start: {time_at_start}") for i in range(N): #if i == 1: continue badgers[i].submit_tx('<[HBBFT Input {}]>'.format(i)*100000) - log("Done submitting big input") + logger.debug("Done submitting big input") for i in range(N): badgers[i].submit_tx('<[HBBFT Input %d]>' % (i+10)) @@ -104,7 +109,7 @@ def test_honeybadger(N=4, f=1, seed=None): time_at_end = datetime.now().timestamp() time_diff = time_at_end - time_at_start - log(f"Time passed: {time_diff}") + logger.info(f"Time passed: {time_diff}") except KeyboardInterrupt: gevent.killall(threads) diff --git a/test/utils.py b/test/utils.py index d984600c..aa056045 100644 --- a/test/utils.py +++ b/test/utils.py @@ -1,10 +1,29 @@ import os -LOG_DIR = "./logs" -LOG_PATH = LOG_DIR + "/test_log.txt" -def log(msg): - print(msg) - msg += "\n" +import logging +from consts import * +import datetime + +def setup_logging(): if not os.path.isdir(LOG_DIR): os.mkdir(LOG_DIR) - with open(LOG_PATH, 'a') as f: - f.write(msg) + + + logger = logging.getLogger(LOGGER_NAME) + logger.setLevel(logging.DEBUG) + + formatter = logging.Formatter('(%(asctime)s) %(levelname)s: %(message)s', datefmt='%H:%M:%S') + + ch = logging.StreamHandler() + ch.setLevel(logging.INFO) + + cur_time = datetime.datetime.now() + fi = logging.FileHandler(LOG_PATH.format(cur_time.year, cur_time.month, cur_time.day, cur_time.hour, + cur_time.minute, cur_time.second)) + fi.setLevel(logging.DEBUG) + fi.setFormatter(formatter) + + logger.addHandler(ch) + logger.addHandler(fi) + + + From 2baf481f2dbe66f25bdccc39ecccb0e0f70bd803 Mon Sep 17 00:00:00 2001 From: samuels Date: Sat, 5 Feb 2022 16:41:07 +0000 Subject: [PATCH 07/29] Move files --- our_srcs/__pycache__/consts.cpython-37.pyc | Bin 0 -> 250 bytes our_srcs/__pycache__/utils.cpython-37.pyc | Bin 0 -> 830 bytes {test => our_srcs}/consts.py | 0 {test => our_srcs}/utils.py | 2 +- test/my_test.py | 4 ++-- 5 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 our_srcs/__pycache__/consts.cpython-37.pyc create mode 100644 our_srcs/__pycache__/utils.cpython-37.pyc rename {test => our_srcs}/consts.py (100%) rename {test => our_srcs}/utils.py (95%) diff --git a/our_srcs/__pycache__/consts.cpython-37.pyc b/our_srcs/__pycache__/consts.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f98bdaa64f7e79e15ce8f9e5fb256888bcbfce4d GIT binary patch literal 250 zcmZ?b<>g`kg2T)HB^Cqe#~=<2Faa43KwK;WBvKfn7*ZKh7{wW)7*m*{m{OR788lg{ z*!1*s^3#i}l=X{?GvZTHOHz|d@{8iDYtfJ%P*s#LiW;CudTNoMCi5+JAAk3F7tf$u z93V!3V~EEsZXnCuH7MTC(bsh)LlFzm1z_TrfqrRm5zx-$#2o$NqGWxK{Jhjkr^FPX uQBH0l`uU|r@j&5X{p9?-;*w&$g34PQHo5sJr8%i~j3B>&Ok!c=U<3dytw%-x literal 0 HcmV?d00001 diff --git a/our_srcs/__pycache__/utils.cpython-37.pyc b/our_srcs/__pycache__/utils.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5d795f2d107adc3f3a1f69329a3c5f541514afd5 GIT binary patch literal 830 zcmYjP%We}f6tz8%Owyz+uTl_;f)puJq0T-+h=w*zr8Y%P*vuxf#%?-c9+B+W(T5Gs3JdW>!GHPHGV9KSWLjY5+-f7m)oAn;tK#5VsuTted)g+hN9#eI#omjG1gr&2K zlflvHrFPN}fORR!hr>7<>hh4QGpM=H8^Ad^z8rK9&yTeyp>JHZb9CH#f1=CnT%=Sf zAl7zaB)>f8((i`nK;cG_d8TWUG{f>68mMYqwa4KM!JcAi6 zMkm_7&I_U4G|mdewJUj)XG~XNj635BWo)hKJK8m80RQqz(@aL9>(Gk|F<1^luHtV< z?7~#tKAR4dH`)16e>>S!FZx;U|fs`>uYk&pY#k8 z!c|A9hMuhN_q P34e_NNu%K5 Date: Sat, 5 Feb 2022 16:47:09 +0000 Subject: [PATCH 08/29] Correct log file name --- .gitignore | 3 +++ our_srcs/consts.py | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 333c1e91..341d5f52 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ logs/ +*__pycache__* +.coverage +docs/_build/ diff --git a/our_srcs/consts.py b/our_srcs/consts.py index 5edc8f33..7fbad711 100644 --- a/our_srcs/consts.py +++ b/our_srcs/consts.py @@ -1,4 +1,4 @@ LOG_DIR = './logs' -LOG_PATH = LOG_DIR + '/ssh_detector_{}_{}_{}_{}_{}_{}.log' -LOGGER_NAME = 'ssh_detector_logger' +LOG_PATH = LOG_DIR + '/honeybadger_test_{}_{}_{}_{}_{}_{}.log' +LOGGER_NAME = 'honeybadger_test_logger' From 037cc6fb4d80e35ec5deb2604ddf7c1c21b59068 Mon Sep 17 00:00:00 2001 From: 1337samuels Date: Sat, 5 Feb 2022 16:59:31 +0000 Subject: [PATCH 09/29] Remove redundant logs --- test/my_test.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/test/my_test.py b/test/my_test.py index 4e22dac0..7e409168 100755 --- a/test/my_test.py +++ b/test/my_test.py @@ -85,22 +85,18 @@ def test_honeybadger(N=4, f=1, seed=None): threads[i] = gevent.spawn(badgers[i].run) time_at_start = datetime.now().timestamp() - logger.info(f"Time at start: {time_at_start}") for i in range(N): #if i == 1: continue badgers[i].submit_tx('<[HBBFT Input {}]>'.format(i)*100000) - logger.debug("Done submitting big input") for i in range(N): badgers[i].submit_tx('<[HBBFT Input %d]>' % (i+10)) - + for i in range(N): badgers[i].submit_tx('<[HBBFT Input %d]>' % (i+20)) - #gevent.killall(threads[N-f:]) - #gevent.sleep(3) - #for i in range(N-f, N): - # inputs[i].put(0) + logger.debug("Done submitting all inputs") + try: outs = [threads[i].get() for i in range(N)] From ab001dfea133aa0254ab3455bfc874745fd8823d Mon Sep 17 00:00:00 2001 From: Tomer Date: Sat, 5 Feb 2022 17:01:58 +0000 Subject: [PATCH 10/29] Split tests --- honeybadgerbft/core/honeybadger.py | 9 +++++---- test/my_test.py | 16 ++++++++++++---- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/honeybadgerbft/core/honeybadger.py b/honeybadgerbft/core/honeybadger.py index 77963a64..a6a12433 100644 --- a/honeybadgerbft/core/honeybadger.py +++ b/honeybadgerbft/core/honeybadger.py @@ -38,15 +38,11 @@ def broadcast_receiver(recv_func, recv_queues): recv_queue.put_nowait((sender, msg)) - ://github.com/1337samuels/HoneyBadgerBFT-Python, def broadcast_receiver_loop(recv_func, recv_queues): while True: broadcast_receiver(recv_func, recv_queues) -class ImprovedHoneyBadgerBFT(HoneyBadgerBFT): - def _prepare_transaction_buffer(self): - self.transaction_buffer = sorted(self.transaction_buffer, key=len, reverse=(self.pid%2 == 1)) class HoneyBadgerBFT(): @@ -259,3 +255,8 @@ def tpke_bcast(o): _input.get, acs_in=my_rbc_input.put_nowait, acs_out=acs.get, tpke_bcast=tpke_bcast, tpke_recv=tpke_recv.get) + + +class ImprovedHoneyBadgerBFT(HoneyBadgerBFT): + def _prepare_transaction_buffer(self): + self.transaction_buffer = sorted(self.transaction_buffer, key=len, reverse=(self.pid%2 == 1)) diff --git a/test/my_test.py b/test/my_test.py index 4e22dac0..bb5647d5 100755 --- a/test/my_test.py +++ b/test/my_test.py @@ -10,7 +10,7 @@ import honeybadgerbft.core.honeybadger #reload(honeybadgerbft.core.honeybadger) -from honeybadgerbft.core.honeybadger import HoneyBadgerBFT +from honeybadgerbft.core.honeybadger import HoneyBadgerBFT, ImprovedHoneyBadgerBFT from honeybadgerbft.crypto.threshsig.boldyreva import dealer from honeybadgerbft.crypto.threshenc import tpke from honeybadgerbft.core.honeybadger import BroadcastTag @@ -60,11 +60,19 @@ def _recv(): [makeRecv(j) for j in range(N)]) -### Test asynchronous common subset -def test_honeybadger(N=4, f=1, seed=None): +def test_HB(N=4, f=1, seed=None): setup_logging() logger = getLogger(LOGGER_NAME) + logger.info("Testing original HB:") + _test_honeybadger(HoneyBadgerBFT, N, f, seed) + logger.info("Testing improved HB:") + _test_honeybadger(ImprovedHoneyBadgerBFT, N, f, seed) + + +### Test asynchronous common subset +def _test_honeybadger(HB, N=8, f=1, seed=None): + logger=getLogger(LOGGER_NAME) sid = 'sidA' # Generate threshold sig keys sPK, sSKs = dealer(N, f+1, seed=seed) @@ -79,7 +87,7 @@ def test_honeybadger(N=4, f=1, seed=None): badgers = [None] * N threads = [None] * N for i in range(N): - badgers[i] = HoneyBadgerBFT(sid, i, 1, N, f, + badgers[i] = HB(sid, i, 1, N, f, sPK, sSKs[i], ePK, eSKs[i], sends[i], recvs[i]) threads[i] = gevent.spawn(badgers[i].run) From 7cb8979a543fa7f3bd6c8e796b996a470bbb7eb1 Mon Sep 17 00:00:00 2001 From: 1337samuels Date: Mon, 7 Feb 2022 14:18:33 +0000 Subject: [PATCH 11/29] Revert print removals --- .gitignore | 1 + honeybadgerbft/core/honeybadger.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 341d5f52..80427e1b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ logs/ *__pycache__* .coverage docs/_build/ +*.pyc diff --git a/honeybadgerbft/core/honeybadger.py b/honeybadgerbft/core/honeybadger.py index 8f506a3f..f7e8fa1a 100644 --- a/honeybadgerbft/core/honeybadger.py +++ b/honeybadgerbft/core/honeybadger.py @@ -86,7 +86,7 @@ def submit_tx(self, tx): :param tx: Transaction to append to the buffer. """ - ##print('submit_tx', self.pid, tx) + print('submit_tx', self.pid, tx) self.transaction_buffer.append(tx) def run(self): @@ -133,7 +133,7 @@ def _send(j, o): send_r = _make_send(r) recv_r = self._per_round_recv[r].get new_tx = self._run_round(r, tx_to_send[0], send_r, recv_r) - #print('new_tx:', new_tx) + print('new_tx:', new_tx) # Remove all of the new transactions from the buffer self.transaction_buffer = [_tx for _tx in self.transaction_buffer if _tx not in new_tx] @@ -174,7 +174,7 @@ def broadcast(o): rbc_outputs = [Queue(1) for _ in range(N)] my_rbc_input = Queue(1) - #print(pid, r, 'tx_to_send:', tx_to_send) + print(pid, r, 'tx_to_send:', tx_to_send) def _setup(j): """Setup the sub protocols RBC, BA and common coin. From 5a562e1ce138d5023387d12de9263dd268896dde Mon Sep 17 00:00:00 2001 From: 1337samuels Date: Mon, 7 Feb 2022 14:58:00 +0000 Subject: [PATCH 12/29] Initial commit, test 2 different node sizes --- our_srcs/__pycache__/consts.cpython-37.pyc | Bin 250 -> 724 bytes our_srcs/__pycache__/utils.cpython-37.pyc | Bin 830 -> 830 bytes our_srcs/consts.py | 13 +++++++- test/my_test.py | 35 ++++++++++++++------- 4 files changed, 35 insertions(+), 13 deletions(-) diff --git a/our_srcs/__pycache__/consts.cpython-37.pyc b/our_srcs/__pycache__/consts.cpython-37.pyc index f98bdaa64f7e79e15ce8f9e5fb256888bcbfce4d..8e9b1c6326ca05dd14bc15b1eec818c745db76e7 100644 GIT binary patch literal 724 zcmZ`$O>fgc5Z$$1$N8kRs1;nwt;)ql;))Osb{b2m9mURpy{wY##*LK3)!IQy5I=~& zv{z343tV8=wA%X=In2NZ`#f(OY{A;bEg_+ zRRb+}UeGUJpS(6G$>l#fV8NtRW0$4^I1p6o080eq5}{L6{)E_{k9oRXO~vc#Cmy`^ zXQQcD7Q16E>~`eUk&x?S za!aE=4I|H|(I^R`FeX>O$-wi&B>3nKX%LPkN&F~ybr3wzK}dtdAG@lXG%GEQ1LDWz zh3EI($uOZuHnF^Z!v4=ko*jgL_LQwb6#Acft_L&3-;j8&W>xUxjkC=KT-kiOa&j?u xs*`-YW+&SU3UuzwvrS&)_We#;@75XHuK0Tl{rLsJsb=UFHn4?TfDOp%`33n-&OZPE delta 166 zcmcb@`irsNiIkEUVwqgV'.format(i)*100000) + badgers[i].submit_tx('<[HBBFT Input {}]>'.format(i)) for i in range(N): badgers[i].submit_tx('<[HBBFT Input %d]>' % (i+10)) From e2f6abb226e853ef3f05046eaf5de1edc5f7ace5 Mon Sep 17 00:00:00 2001 From: Tomer Date: Mon, 7 Feb 2022 15:27:47 +0000 Subject: [PATCH 13/29] added permuted HB --- honeybadgerbft/core/honeybadger.py | 7 +++++++ our_srcs/__pycache__/consts.cpython-37.pyc | Bin 250 -> 258 bytes our_srcs/__pycache__/utils.cpython-37.pyc | Bin 830 -> 830 bytes test/my_test.py | 4 +++- 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/honeybadgerbft/core/honeybadger.py b/honeybadgerbft/core/honeybadger.py index a6a12433..367ac5de 100644 --- a/honeybadgerbft/core/honeybadger.py +++ b/honeybadgerbft/core/honeybadger.py @@ -257,6 +257,13 @@ def tpke_bcast(o): tpke_bcast=tpke_bcast, tpke_recv=tpke_recv.get) +def permute_list(lst, index): + return lst[index:] + lst[:index] + class ImprovedHoneyBadgerBFT(HoneyBadgerBFT): def _prepare_transaction_buffer(self): self.transaction_buffer = sorted(self.transaction_buffer, key=len, reverse=(self.pid%2 == 1)) + +class PermutedHoneyBadgerBFT(HoneyBadgerBFT): + def _prepare_transaction_buffer(self): + self.transaction_buffer = sorted(self.transaction_buffer, key=len) diff --git a/our_srcs/__pycache__/consts.cpython-37.pyc b/our_srcs/__pycache__/consts.cpython-37.pyc index f98bdaa64f7e79e15ce8f9e5fb256888bcbfce4d..f7537b3d8bbc81c6e2866e54d6884a448f8186e1 100644 GIT binary patch delta 83 zcmeyx*u=!^#LLUY00b-6{!6T$$ZKPzuAh;gms**Wn3A4a6kn2BToPYhi-z=a^3$Wl K(bY|?t_J|Mr5{iL delta 75 zcmZo-`o+lW#LLUY00f7Z{YxyK$ZKPytY2K55ucJ;lA2tSUldWB>pF diff --git a/test/my_test.py b/test/my_test.py index 680103e6..b6d0091d 100755 --- a/test/my_test.py +++ b/test/my_test.py @@ -10,7 +10,7 @@ import honeybadgerbft.core.honeybadger #reload(honeybadgerbft.core.honeybadger) -from honeybadgerbft.core.honeybadger import HoneyBadgerBFT, ImprovedHoneyBadgerBFT +from honeybadgerbft.core.honeybadger import HoneyBadgerBFT, ImprovedHoneyBadgerBFT, PermutedHoneyBadgerBFT from honeybadgerbft.crypto.threshsig.boldyreva import dealer from honeybadgerbft.crypto.threshenc import tpke from honeybadgerbft.core.honeybadger import BroadcastTag @@ -67,6 +67,8 @@ def test_HB(N=4, f=1, seed=None): _test_honeybadger(HoneyBadgerBFT, N, f, seed) logger.info("Testing improved HB:") _test_honeybadger(ImprovedHoneyBadgerBFT, N, f, seed) + logger.info("Testing permuted HB:") + _test_honeybadger(PermutedHoneyBadgerBFT, N, f, seed) ### Test asynchronous common subset From e525f706d4fde2513a960f60691637d4f8824311 Mon Sep 17 00:00:00 2001 From: 1337samuels Date: Mon, 7 Feb 2022 15:52:53 +0000 Subject: [PATCH 14/29] Move HB logic to utils.py --- our_srcs/consts.py | 2 +- our_srcs/utils.py | 56 ++++++++++++++++++++++++++++++++ test/my_test.py | 80 ++++++++++------------------------------------ 3 files changed, 73 insertions(+), 65 deletions(-) diff --git a/our_srcs/consts.py b/our_srcs/consts.py index fae88f54..294823e0 100644 --- a/our_srcs/consts.py +++ b/our_srcs/consts.py @@ -6,7 +6,7 @@ LOG_PATH = LOG_DIR + '/honeybadger_test_{}_{}_{}_{}_{}_{}.log' LOGGER_NAME = 'honeybadger_test_logger' NUM_OF_NODE_OPTIONS = [4, 6] -NUM_OF_IDENTICAL_INPUTS_OPTIONS = [0, 2, 4, 6] +NUM_OF_IDENTICAL_INPUTS_OPTIONS = [0, 2, 4] NUM_OF_INPUTS_IN_ITERATION = 3 INPUT_SIZES = [2, 1024, 1024*1024] DEFAULT_NUM_OF_NODES = NUM_OF_NODE_OPTIONS[-1] diff --git a/our_srcs/utils.py b/our_srcs/utils.py index f9f200f5..71d0b09c 100644 --- a/our_srcs/utils.py +++ b/our_srcs/utils.py @@ -2,6 +2,15 @@ import logging from our_srcs.consts import * import datetime +import random +import math + +from honeybadgerbft.crypto.threshsig.boldyreva import dealer +from honeybadgerbft.crypto.threshenc import tpke +import gevent +from gevent.event import Event +from gevent.queue import Queue + def setup_logging(): if not os.path.isdir(LOG_DIR): @@ -25,5 +34,52 @@ def setup_logging(): logger.addHandler(ch) logger.addHandler(fi) +def setup_honeybadgers(honeybadger_class, N): + sid = 'sidA' + # Generate threshold sig keys + sPK, sSKs = dealer(N, 2, seed=None) + # Generate threshold enc keys + ePK, eSKs = tpke.dealer(N, 2) + + rnd = random.Random(None) + #print 'SEED:', seed + router_seed = rnd.random() + sends, recvs = simple_router(N, seed=router_seed) + + badgers = [None] * N + threads = [None] * N + for i in range(N): + badgers[i] = HB(sid, i, 1, N, 1, + sPK, sSKs[i], ePK, eSKs[i], + sends[i], recvs[i]) + threads[i] = gevent.spawn(badgers[i].run) + +def simple_router(N, maxdelay=0.005, seed=None): + """Builds a set of connected channels, with random delay + + :return: (receives, sends) + """ + rnd = random.Random(seed) + #if seed is not None: print 'ROUTER SEED: %f' % (seed,) + + queues = [Queue() for _ in range(N)] + _threads = [] + + def makeSend(i): + def _send(j, o): + delay = rnd.random() * maxdelay + delay *= math.log(len(o)) * 7.5 + gevent.spawn_later(delay, queues[j].put_nowait, (i,o)) + return _send + + def makeRecv(j): + def _recv(): + (i,o) = queues[j].get() + #print 'RECV %8s [%2d -> %2d]' % (o[0], i, j) + return (i,o) + return _recv + + return ([makeSend(i) for i in range(N)], + [makeRecv(j) for j in range(N)]) diff --git a/test/my_test.py b/test/my_test.py index 2df6a5d5..2b5f9515 100755 --- a/test/my_test.py +++ b/test/my_test.py @@ -1,81 +1,32 @@ import random from collections import defaultdict import math -from datetime import datetime +import datetime import gevent from gevent.event import Event from gevent.queue import Queue from pytest import fixture, mark, raises -import honeybadgerbft.core.honeybadger -#reload(honeybadgerbft.core.honeybadger) -from honeybadgerbft.core.honeybadger import HoneyBadgerBFT, ImprovedHoneyBadgerBFT -from honeybadgerbft.crypto.threshsig.boldyreva import dealer -from honeybadgerbft.crypto.threshenc import tpke -from honeybadgerbft.core.honeybadger import BroadcastTag from logging import getLogger -from our_srcs.utils import setup_logging +from our_srcs.utils import * from our_srcs.consts import * -@fixture -def recv_queues(request): - from honeybadgerbft.core.honeybadger import BroadcastReceiverQueues - number_of_nodes = getattr(request, 'N', 4) - queues = { - tag.value: [Queue() for _ in range(number_of_nodes)] - for tag in BroadcastTag if tag != BroadcastTag.TPKE - } - queues[BroadcastTag.TPKE.value] = Queue() - return BroadcastReceiverQueues(**queues) - - - -def simple_router(N, maxdelay=0.005, seed=None): - """Builds a set of connected channels, with random delay - - :return: (receives, sends) - """ - rnd = random.Random(seed) - #if seed is not None: print 'ROUTER SEED: %f' % (seed,) - - queues = [Queue() for _ in range(N)] - _threads = [] - - def makeSend(i): - def _send(j, o): - delay = rnd.random() * maxdelay - delay *= math.log(len(o)) * 7.5 - gevent.spawn_later(delay, queues[j].put_nowait, (i,o)) - return _send - - def makeRecv(j): - def _recv(): - (i,o) = queues[j].get() - #print 'RECV %8s [%2d -> %2d]' % (o[0], i, j) - return (i,o) - return _recv - - return ([makeSend(i) for i in range(N)], - [makeRecv(j) for j in range(N)]) - +setup_logging() +logger = getLogger(LOGGER_NAME) def test_main(): - setup_logging() - logger = getLogger(LOGGER_NAME) _test_num_of_nodes() #_test_num_of_identical_inputs() #_test_input_sizes() def _test_num_of_nodes(): - logger = getLogger(LOGGER_NAME) logger.info("Testing Number of Nodes") for num_of_nodes in NUM_OF_NODE_OPTIONS: _test_honeybadgers(num_of_nodes, DEFAULT_NUM_OF_IDENTICAL_INPUTS_OPTIONS, DEFAULT_INPUT_SIZE) def _test_honeybadgers(num_of_nodes, identical_input, input_size): - logger = getLogger(LOGGER_NAME) logger.info(f"Test Honeybadgers with N={num_of_nodes}, id={identical_input}, size={input_size}") for hb_tuple in HONEYBADGERS: logger.info("Testing Honeybadger: {}".format(hb_tuple[0])) @@ -83,7 +34,7 @@ def _test_honeybadgers(num_of_nodes, identical_input, input_size): ### Test asynchronous common subset def _test_honeybadger_full(HB, N, identical_inputs, input_sizes): - logger=getLogger(LOGGER_NAME) + assert N >= identical_inputs, "There can't be more identical_inputs than number of nodes" sid = 'sidA' # Generate threshold sig keys sPK, sSKs = dealer(N, 2, seed=None) @@ -103,16 +54,17 @@ def _test_honeybadger_full(HB, N, identical_inputs, input_sizes): sends[i], recvs[i]) threads[i] = gevent.spawn(badgers[i].run) - time_at_start = datetime.now().timestamp() - - for i in range(N): - #if i == 1: continue - badgers[i].submit_tx('<[HBBFT Input {}]>'.format(i)) - for i in range(N): - badgers[i].submit_tx('<[HBBFT Input %d]>' % (i+10)) + time_at_start = datetime.datetime.now().timestamp() - for i in range(N): - badgers[i].submit_tx('<[HBBFT Input %d]>' % (i+20)) + for iter_index in range(NUM_OF_INPUTS_IN_ITERATION): + identical_hbs = random.sample(range(N), identical_inputs) + logger.debug(f"At epoch {iter_index} chose identical_inputs {identical_hbs}") + for node_index in range(N): + if node_index in identical_hbs: + badgers[node_index].submit_tx(f' ' + 'a'*input_sizes) + else: + badgers[node_index].submit_tx(f' Date: Mon, 7 Feb 2022 16:06:56 +0000 Subject: [PATCH 15/29] added debug prints and removing messages from transaction_buffer --- honeybadgerbft/core/honeybadger.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/honeybadgerbft/core/honeybadger.py b/honeybadgerbft/core/honeybadger.py index 367ac5de..e6b563f5 100644 --- a/honeybadgerbft/core/honeybadger.py +++ b/honeybadgerbft/core/honeybadger.py @@ -10,6 +10,8 @@ from honeybadgerbft.core.commonsubset import commonsubset from honeybadgerbft.core.honeybadger_block import honeybadger_block from honeybadgerbft.exceptions import UnknownTagError +from our_srcs.consts import * +from logging import getLogger; logger=getLogger(LOGGER_NAME) class BroadcastTag(Enum): @@ -122,6 +124,8 @@ def _recv(): while True: # For each round... r = self.round + logger.info(f"AAAAA round number: {self.round}") + logger.info(f"BBBBB transaction buffer with len: {len(self.transaction_buffer)}") if r not in self._per_round_recv: self._per_round_recv[r] = Queue() @@ -142,10 +146,11 @@ def _send(j, o): #print('new_tx:', new_tx) # Remove all of the new transactions from the buffer - self.transaction_buffer = [_tx for _tx in self.transaction_buffer if _tx not in new_tx] + self.transaction_buffer = [_tx for _tx in self.transaction_buffer if _tx not in new_tx and _tx not in tx_to_send] self.round += 1 # Increment the round - if self.round >= 3: + if not self.transaction_buffer: + logger.info(f"CCCCC finished with rounds: {self.round}") break # Only run one round for now def _run_round(self, r, tx_to_send, send, recv): From bc974547e80c8c1433d7274e4d7aee1ba98ae1e9 Mon Sep 17 00:00:00 2001 From: 1337samuels Date: Mon, 7 Feb 2022 16:08:00 +0000 Subject: [PATCH 16/29] Updated params --- our_srcs/consts.py | 3 ++- our_srcs/utils.py | 3 ++- test/my_test.py | 29 +++++++++-------------------- 3 files changed, 13 insertions(+), 22 deletions(-) diff --git a/our_srcs/consts.py b/our_srcs/consts.py index 294823e0..bf5f6de3 100644 --- a/our_srcs/consts.py +++ b/our_srcs/consts.py @@ -6,7 +6,8 @@ LOG_PATH = LOG_DIR + '/honeybadger_test_{}_{}_{}_{}_{}_{}.log' LOGGER_NAME = 'honeybadger_test_logger' NUM_OF_NODE_OPTIONS = [4, 6] -NUM_OF_IDENTICAL_INPUTS_OPTIONS = [0, 2, 4] +#NUM_OF_IDENTICAL_INPUTS_OPTIONS = [0, 2, 4] +NUM_OF_IDENTICAL_INPUTS_OPTIONS = [0, 4] NUM_OF_INPUTS_IN_ITERATION = 3 INPUT_SIZES = [2, 1024, 1024*1024] DEFAULT_NUM_OF_NODES = NUM_OF_NODE_OPTIONS[-1] diff --git a/our_srcs/utils.py b/our_srcs/utils.py index 71d0b09c..bbe5d80d 100644 --- a/our_srcs/utils.py +++ b/our_srcs/utils.py @@ -49,10 +49,11 @@ def setup_honeybadgers(honeybadger_class, N): badgers = [None] * N threads = [None] * N for i in range(N): - badgers[i] = HB(sid, i, 1, N, 1, + badgers[i] = honeybadger_class(sid, i, 1, N, 1, sPK, sSKs[i], ePK, eSKs[i], sends[i], recvs[i]) threads[i] = gevent.spawn(badgers[i].run) + return badgers, threads def simple_router(N, maxdelay=0.005, seed=None): """Builds a set of connected channels, with random delay diff --git a/test/my_test.py b/test/my_test.py index 2b5f9515..51f51337 100755 --- a/test/my_test.py +++ b/test/my_test.py @@ -16,8 +16,8 @@ logger = getLogger(LOGGER_NAME) def test_main(): - _test_num_of_nodes() - #_test_num_of_identical_inputs() + #_test_num_of_nodes() + _test_num_of_identical_inputs() #_test_input_sizes() @@ -26,6 +26,11 @@ def _test_num_of_nodes(): for num_of_nodes in NUM_OF_NODE_OPTIONS: _test_honeybadgers(num_of_nodes, DEFAULT_NUM_OF_IDENTICAL_INPUTS_OPTIONS, DEFAULT_INPUT_SIZE) +def _test_num_of_identical_inputs(): + logger.info("Testing different identical inputs") + for num_of_identical_inputs in NUM_OF_IDENTICAL_INPUTS_OPTIONS: + _test_honeybadgers(DEFAULT_NUM_OF_NODES, num_of_identical_inputs, DEFAULT_INPUT_SIZE) + def _test_honeybadgers(num_of_nodes, identical_input, input_size): logger.info(f"Test Honeybadgers with N={num_of_nodes}, id={identical_input}, size={input_size}") for hb_tuple in HONEYBADGERS: @@ -35,24 +40,8 @@ def _test_honeybadgers(num_of_nodes, identical_input, input_size): ### Test asynchronous common subset def _test_honeybadger_full(HB, N, identical_inputs, input_sizes): assert N >= identical_inputs, "There can't be more identical_inputs than number of nodes" - sid = 'sidA' - # Generate threshold sig keys - sPK, sSKs = dealer(N, 2, seed=None) - # Generate threshold enc keys - ePK, eSKs = tpke.dealer(N, 2) - - rnd = random.Random(None) - #print 'SEED:', seed - router_seed = rnd.random() - sends, recvs = simple_router(N, seed=router_seed) - - badgers = [None] * N - threads = [None] * N - for i in range(N): - badgers[i] = HB(sid, i, 1, N, 1, - sPK, sSKs[i], ePK, eSKs[i], - sends[i], recvs[i]) - threads[i] = gevent.spawn(badgers[i].run) + + badgers, threads = setup_honeybadgers(HB, N) time_at_start = datetime.datetime.now().timestamp() From 98fd39c0be18b269fae07869ec0be2ae2a432f2a Mon Sep 17 00:00:00 2001 From: 1337samuels Date: Mon, 7 Feb 2022 16:15:29 +0000 Subject: [PATCH 17/29] Finish tests --- our_srcs/consts.py | 2 +- test/my_test.py | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/our_srcs/consts.py b/our_srcs/consts.py index bf5f6de3..06c6f1ad 100644 --- a/our_srcs/consts.py +++ b/our_srcs/consts.py @@ -10,7 +10,7 @@ NUM_OF_IDENTICAL_INPUTS_OPTIONS = [0, 4] NUM_OF_INPUTS_IN_ITERATION = 3 INPUT_SIZES = [2, 1024, 1024*1024] -DEFAULT_NUM_OF_NODES = NUM_OF_NODE_OPTIONS[-1] +DEFAULT_NUM_OF_NODES = NUM_OF_NODE_OPTIONS[-2] DEFAULT_NUM_OF_IDENTICAL_INPUTS_OPTIONS = NUM_OF_IDENTICAL_INPUTS_OPTIONS[-1] DEFAULT_INPUT_SIZE = INPUT_SIZES[-1] HONEYBADGERS = [("Regular Honeybadger", HoneyBadgerBFT), ("Parity Honeybadger", ImprovedHoneyBadgerBFT)] diff --git a/test/my_test.py b/test/my_test.py index 51f51337..d4355080 100755 --- a/test/my_test.py +++ b/test/my_test.py @@ -31,6 +31,11 @@ def _test_num_of_identical_inputs(): for num_of_identical_inputs in NUM_OF_IDENTICAL_INPUTS_OPTIONS: _test_honeybadgers(DEFAULT_NUM_OF_NODES, num_of_identical_inputs, DEFAULT_INPUT_SIZE) +def _test_input_sizes(): + logger.info("Testing different input sizes") + for inputs_size in INPUT_SIZES: + _test_honeybadgers(DEFAULT_NUM_OF_NODES, DEFAULT_NUM_OF_IDENTICAL_INPUTS_OPTIONS, inputs_size) + def _test_honeybadgers(num_of_nodes, identical_input, input_size): logger.info(f"Test Honeybadgers with N={num_of_nodes}, id={identical_input}, size={input_size}") for hb_tuple in HONEYBADGERS: From e96eb35d1d16d56aca58e0b1f7ba579ee013ecba Mon Sep 17 00:00:00 2001 From: Tomer Date: Mon, 7 Feb 2022 17:01:31 +0000 Subject: [PATCH 18/29] changed to sort lexicographically --- honeybadgerbft/core/honeybadger.py | 13 +++++++++---- our_srcs/__pycache__/consts.cpython-37.pyc | Bin 258 -> 542 bytes our_srcs/__pycache__/utils.cpython-37.pyc | Bin 830 -> 3040 bytes our_srcs/consts.py | 5 ++--- test/my_test.py | 5 ++++- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/honeybadgerbft/core/honeybadger.py b/honeybadgerbft/core/honeybadger.py index 38e3b066..aeb14a10 100644 --- a/honeybadgerbft/core/honeybadger.py +++ b/honeybadgerbft/core/honeybadger.py @@ -120,7 +120,6 @@ def _recv(): # round and will stop participating! self._recv_thread = gevent.spawn(_recv) - while True: # For each round... r = self.round @@ -132,6 +131,8 @@ def _recv(): # Select all the transactions (TODO: actual random selection) self._prepare_transaction_buffer() tx_to_send = self.transaction_buffer[:self.B] + logger.debug(f"EEEEE transaction_buffer: {[t[:40] for t in self.transaction_buffer]}") + logger.debug(f"Chosen tx_to_send for {self.pid} is {tx_to_send[0][:40]}") # TODO: Wait a bit if transaction buffer is not full @@ -143,7 +144,8 @@ def _send(j, o): send_r = _make_send(r) recv_r = self._per_round_recv[r].get new_tx = self._run_round(r, tx_to_send[0], send_r, recv_r) - print('new_tx:', new_tx) + for nino in new_tx: + logger.debug(f'Node id {self.pid} got from his friends: {nino[:40]}') # Remove all of the new transactions from the buffer self.transaction_buffer = [_tx for _tx in self.transaction_buffer if _tx not in new_tx and _tx not in tx_to_send] @@ -267,8 +269,11 @@ def permute_list(lst, index): class ImprovedHoneyBadgerBFT(HoneyBadgerBFT): def _prepare_transaction_buffer(self): - self.transaction_buffer = sorted(self.transaction_buffer, key=len, reverse=(self.pid%2 == 1)) + self.transaction_buffer = sorted(self.transaction_buffer, key=str.lower, reverse=(self.pid%2 == 1)) + logger.debug(f"DDDD transaction_buffer: {[t[:40] for t in self.transaction_buffer]}") class PermutedHoneyBadgerBFT(HoneyBadgerBFT): def _prepare_transaction_buffer(self): - self.transaction_buffer = sorted(self.transaction_buffer, key=len) + self.transaction_buffer = sorted(self.transaction_buffer, key=str.lower) + self.transaction_buffer = permute_list(self.transaction_buffer, self.pid) + logger.debug(f"DDDD transaction_buffer: {[t[:40] for t in self.transaction_buffer]}") diff --git a/our_srcs/__pycache__/consts.cpython-37.pyc b/our_srcs/__pycache__/consts.cpython-37.pyc index f7537b3d8bbc81c6e2866e54d6884a448f8186e1..a40b7aaa2e9f4ff2defdcce33d766e9412177456 100644 GIT binary patch literal 542 zcmZ`#!A`$Hj*jJrE;W?$ay%uc&nEhAV@1W#WuLa*6nw`2&e!9)*$BZ_>)aUD_2B`R^5 zD}h91E(e$@yg&wH15jiQD_E0MNx@~T G!Ttc>pqhgK delta 135 zcmbQo(!}K8#LLUY00b-6{!6R|(vLwL7+?Z29Dul31W2SXL@}f?q%evzL@}l?MKPr? z2Qz50Of2!z@zZ3!#qQ(p9`E8Abc+MT2yhJXxWx@*xw{6%`#Ji$u4E`;0h&?7GWiIj PJuf53Oc0-ik%JKc%!?Xz diff --git a/our_srcs/__pycache__/utils.cpython-37.pyc b/our_srcs/__pycache__/utils.cpython-37.pyc index 65d0b67ca6e44a24bdb738349facbff7dffbd95e..93c6ba34acdb1e85cbea155668f906c39a46564f 100644 GIT binary patch literal 3040 zcmbtWTW=f36`t7}mlP?W+V5WE+0~DHtZo_%OHqjv zkC%qSa#XfBPb*OcG(VjiR->w=1!-+KAI$?ViSPxB7DQQ8ur7*uQ5CfpJh~?ME^92j zf-S7o;D&zy5QrpB6A8@I2Tu~L{?=iVX+l09C*!0;>@<8#y6VT6>Yo6b?enRl-7~IM zG@E*aai;xgpi5_b!g4kZwZC63sQVScg(KW=oe2le+!>oVxnnu1mZP>`o6dvk;_HH5 zoL{pB@Co*&l#Y76LDn40rzRxrWU+Cx(K9o*JxG%oM--Cw&+hE)n4oK= z81E>FC5#zmu+bIqk@5PYu{6POkd1X>0+n<|nJ`tDaiO>p3o(<~@J&E>fc|nJlPq&O z{V42=W!oC!bO--n@;xNL_v`CpCD+qYCr;Ou?5yvMvgBwp7C67Ty|)h4ZIIRaSPxRw zJUB8nC>|fQXKq@cO!_$h<5ga9E4=E=J0W0&U+42g118_c_l`qc81u7flknfz2tIK% z%PF-`FW6ijDIkUq-~`@4@xoZ(88-U8=&%Wv^gH6 zLe=9s?o=Oj>nNWr>F7k%JN+1Fsy?be8|Z$$2vS`nX?#?v)G;4!#|GsiF z9Vp!y4G(T@k|>fJu;X7|NtfnLTdnFAkaO-UmXN34qT?$7C-4_}vs-vNoS;OIxNhrp zJ(A&Ml|6C`$f-MJXY7 zFV)$(Ie!F`jTY>n#ISUGX}N*zF6OMpeyWn&5CtXovHU>E-h~q65|xAekif41klVi@ z+-BGsuqbTLnsRXkzmRBcznX@{Ek42-x{0DkmH8ESiF?jssajg*lD;A0f56geEXfe7 ztOA&Y^GCgjR;aX+2LCIgITS7rpx? z{v_+zH?XMrYVpK1?L#MhvgVv*i`uqF`**>1aiI&VQFEAVo6~PX3%7P z2~y*y$#{!VYvV(4CPszHKbf2v*(TdEt41jSr8HTKSb$U!2aveMpI=%OUtE-2te2dh pS6otDBmj~EDJxPyB@}_&TO2mI`6;D2sdkJ&UNOi74n{C!0sz-VBBcNT diff --git a/our_srcs/consts.py b/our_srcs/consts.py index 06c6f1ad..99c710b1 100644 --- a/our_srcs/consts.py +++ b/our_srcs/consts.py @@ -1,4 +1,3 @@ -from honeybadgerbft.core.honeybadger import HoneyBadgerBFT, ImprovedHoneyBadgerBFT LOG_DIR = './logs' @@ -7,10 +6,10 @@ LOGGER_NAME = 'honeybadger_test_logger' NUM_OF_NODE_OPTIONS = [4, 6] #NUM_OF_IDENTICAL_INPUTS_OPTIONS = [0, 2, 4] -NUM_OF_IDENTICAL_INPUTS_OPTIONS = [0, 4] +NUM_OF_IDENTICAL_INPUTS_OPTIONS = [4] + NUM_OF_INPUTS_IN_ITERATION = 3 INPUT_SIZES = [2, 1024, 1024*1024] DEFAULT_NUM_OF_NODES = NUM_OF_NODE_OPTIONS[-2] DEFAULT_NUM_OF_IDENTICAL_INPUTS_OPTIONS = NUM_OF_IDENTICAL_INPUTS_OPTIONS[-1] DEFAULT_INPUT_SIZE = INPUT_SIZES[-1] -HONEYBADGERS = [("Regular Honeybadger", HoneyBadgerBFT), ("Parity Honeybadger", ImprovedHoneyBadgerBFT)] diff --git a/test/my_test.py b/test/my_test.py index d10bd949..9da4b7e5 100755 --- a/test/my_test.py +++ b/test/my_test.py @@ -9,9 +9,11 @@ from pytest import fixture, mark, raises from logging import getLogger -from our_srcs.utils import * from our_srcs.consts import * +from our_srcs.utils import * +from honeybadgerbft.core.honeybadger import HoneyBadgerBFT, ImprovedHoneyBadgerBFT, PermutedHoneyBadgerBFT +HONEYBADGERS = [("Regular Honeybadger", HoneyBadgerBFT), ("Parity Honeybadger", ImprovedHoneyBadgerBFT), ("Permuted Honeybadger", PermutedHoneyBadgerBFT)] setup_logging() logger = getLogger(LOGGER_NAME) @@ -29,6 +31,7 @@ def _test_num_of_nodes(): def _test_num_of_identical_inputs(): logger.info("Testing different identical inputs") for num_of_identical_inputs in NUM_OF_IDENTICAL_INPUTS_OPTIONS: + _test_honeybadgers(DEFAULT_NUM_OF_NODES, num_of_identical_inputs, DEFAULT_INPUT_SIZE) def _test_input_sizes(): logger.info("Testing different input sizes") From 2b6fbb01dcca88db366b0cbaee3948889f0b0cdb Mon Sep 17 00:00:00 2001 From: 1337samuels Date: Mon, 7 Feb 2022 17:53:27 +0000 Subject: [PATCH 19/29] Tests run and have a meaning --- honeybadgerbft/core/honeybadger.py | 11 +++++++---- our_srcs/__pycache__/consts.cpython-37.pyc | Bin 542 -> 544 bytes our_srcs/__pycache__/utils.cpython-37.pyc | Bin 3040 -> 3027 bytes our_srcs/consts.py | 2 +- our_srcs/utils.py | 2 +- test/my_test.py | 6 ++++-- 6 files changed, 13 insertions(+), 8 deletions(-) diff --git a/honeybadgerbft/core/honeybadger.py b/honeybadgerbft/core/honeybadger.py index aeb14a10..625ea588 100644 --- a/honeybadgerbft/core/honeybadger.py +++ b/honeybadgerbft/core/honeybadger.py @@ -131,7 +131,7 @@ def _recv(): # Select all the transactions (TODO: actual random selection) self._prepare_transaction_buffer() tx_to_send = self.transaction_buffer[:self.B] - logger.debug(f"EEEEE transaction_buffer: {[t[:40] for t in self.transaction_buffer]}") + logger.debug(f"EEEEE transaction_buffer for id {self.pid}: {[t[:40] for t in self.transaction_buffer]}") logger.debug(f"Chosen tx_to_send for {self.pid} is {tx_to_send[0][:40]}") # TODO: Wait a bit if transaction buffer is not full @@ -148,7 +148,8 @@ def _send(j, o): logger.debug(f'Node id {self.pid} got from his friends: {nino[:40]}') # Remove all of the new transactions from the buffer - self.transaction_buffer = [_tx for _tx in self.transaction_buffer if _tx not in new_tx and _tx not in tx_to_send] + self.transaction_buffer = [_tx for _tx in self.transaction_buffer if _tx not in [t.decode('utf-8') for t in new_tx] and _tx not in tx_to_send] + logger.debug(f"New transaction buffer after getting messages for id {self.pid}: {[t[:40] for t in self.transaction_buffer]}") self.round += 1 # Increment the round if not self.transaction_buffer: @@ -270,10 +271,12 @@ def permute_list(lst, index): class ImprovedHoneyBadgerBFT(HoneyBadgerBFT): def _prepare_transaction_buffer(self): self.transaction_buffer = sorted(self.transaction_buffer, key=str.lower, reverse=(self.pid%2 == 1)) - logger.debug(f"DDDD transaction_buffer: {[t[:40] for t in self.transaction_buffer]}") class PermutedHoneyBadgerBFT(HoneyBadgerBFT): def _prepare_transaction_buffer(self): self.transaction_buffer = sorted(self.transaction_buffer, key=str.lower) self.transaction_buffer = permute_list(self.transaction_buffer, self.pid) - logger.debug(f"DDDD transaction_buffer: {[t[:40] for t in self.transaction_buffer]}") + +class RandomizedHoneyBadgerBFT(HoneyBadgerBFT): + def _prepare_transaction(self): + self.transaction_buffer = random.sample(self.transaction_buffer, len(self.transaction_buffer)) diff --git a/our_srcs/__pycache__/consts.cpython-37.pyc b/our_srcs/__pycache__/consts.cpython-37.pyc index a40b7aaa2e9f4ff2defdcce33d766e9412177456..112d7fb9b7b8c0a49e48a4478e52caa8ff9e7779 100644 GIT binary patch delta 89 zcmbQovVeuxiIQYYOW`ziKunpz4>*8_&Bka&a)RFmf?+03iV4)(_+W delta 87 zcmZ3$GLMDViIun+P8 diff --git a/our_srcs/__pycache__/utils.cpython-37.pyc b/our_srcs/__pycache__/utils.cpython-37.pyc index 93c6ba34acdb1e85cbea155668f906c39a46564f..e99d7967394e84af1e2881102acdcb48f6f75f58 100644 GIT binary patch delta 624 zcmZXR%Syvg5Qd%9T-q9hq7`T_J*mkOq9(NxOyHEBTKq$Z9n)FJ$ zhAH`>oj|@2n(2<|k zW;A46+hPt>6fFvOWIcJBSA5*L#NTo(A)D-@Fm@~QJz2i_2Xhd?+kaqs-J_q-NDQ8X z?+#~JW=Y(BoMW%1E08;|{LV23)w)nET|G)vXZUpm{HLSC;>qV!Zowlt@j6 yicJy@w!7#HtO>8yZi$Y-VJ@jdl;uGB0E+S`T^P^v?h*?pMbrL_NSFASE`9^Ot$1Gm delta 600 zcmZXRO-lk%6o$Q5of$_5AvB4;!4YRNF(C`XurIMiLJ$OQ#G2`g3c8a}h_v$$++Pr_ zT1EIj+O(TZZCkl+5p~WTA*q3R@0oL-d(M02z9!xi+PbExK6p|Ua?pO(`h?W^7wLeu zX@?~FCp{&p-l6}Vgp+_VAv%u+OQg`-367B&%ov18xKNj7b1rFk*nsUyU9!qGc`{&; zn2($CY?RiH0f%R*Y{<;yyK;dB zS``Q#?CT>DGRj}%yeZ63hE>=Wh~Z}&7;mCr5pXItb#5w;6Czy0G-YK(1UK;ASE}A{ zgT1PE91*A@aGmdm&eDQMfhx Date: Mon, 7 Feb 2022 18:02:12 +0000 Subject: [PATCH 20/29] Store and log results properly --- test/my_test.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/test/my_test.py b/test/my_test.py index 98058fcd..b8da25c0 100755 --- a/test/my_test.py +++ b/test/my_test.py @@ -27,18 +27,24 @@ def test_main(): def _test_num_of_nodes(): logger.info("Testing Number of Nodes") + results = [] for num_of_nodes in NUM_OF_NODE_OPTIONS: - _test_honeybadgers(num_of_nodes, DEFAULT_NUM_OF_IDENTICAL_INPUTS_OPTIONS, DEFAULT_INPUT_SIZE) + results.append((num_of_nodes,_test_honeybadgers(num_of_nodes, DEFAULT_NUM_OF_IDENTICAL_INPUTS_OPTIONS, DEFAULT_INPUT_SIZE)) + logger.critical(f"Results for different number of nodes: {results}") def _test_num_of_identical_inputs(): logger.info("Testing different identical inputs") + results = [] for num_of_identical_inputs in NUM_OF_IDENTICAL_INPUTS_OPTIONS: - _test_honeybadgers(DEFAULT_NUM_OF_NODES, num_of_identical_inputs, DEFAULT_INPUT_SIZE) + results.append((num_of_identical_inputs,_test_honeybadgers(DEFAULT_NUM_OF_NODES, num_of_identical_inputs, DEFAULT_INPUT_SIZE))) + logger.critical(f"Results for different number of identical inputs: {results}") def _test_input_sizes(): logger.info("Testing different input sizes") + results = [] for inputs_size in INPUT_SIZES: - _test_honeybadgers(DEFAULT_NUM_OF_NODES, DEFAULT_NUM_OF_IDENTICAL_INPUTS_OPTIONS, inputs_size) + results.append((inputs_size,_test_honeybadgers(DEFAULT_NUM_OF_NODES, DEFAULT_NUM_OF_IDENTICAL_INPUTS_OPTIONS, inputs_size)) + logger.critical(f"Results for different number of input sizes: {results}") def _test_honeybadgers(num_of_nodes, identical_input, input_size): logger.info(f"Test Honeybadgers with N={num_of_nodes}, id={identical_input}, size={input_size}") @@ -75,6 +81,7 @@ def _test_honeybadger_full(HB, N, identical_inputs, input_sizes): time_at_end = datetime.datetime.now().timestamp() time_diff = time_at_end - time_at_start logger.info(f"Time passed: {time_diff}") + return str(time_diff[:4]) except KeyboardInterrupt: gevent.killall(threads) From 2458d2598115fc2c3bf1402b24b4940e10b7b64d Mon Sep 17 00:00:00 2001 From: 1337samuels Date: Tue, 8 Feb 2022 15:28:13 +0000 Subject: [PATCH 21/29] Parametrized tests --- README.md | 7 +++ honeybadgerbft/core/honeybadger.py | 6 +-- our_srcs/__pycache__/consts.cpython-37.pyc | Bin 544 -> 544 bytes our_srcs/__pycache__/utils.cpython-37.pyc | Bin 3027 -> 3027 bytes test/my_test.py | 55 ++++++--------------- 5 files changed, 25 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 87172d63..60a30795 100644 --- a/README.md +++ b/README.md @@ -59,3 +59,10 @@ If the above went all well, you should be setup for developing ## License This is released under the CRAPL academic license. See ./CRAPL-LICENSE.txt Other licenses may be issued at the authors' discretion. + + +### Our added documentation +# To watch log results being written live + ```bash + grep -v DEBUG logs/`ls -t logs | head -n 1` + ``` diff --git a/honeybadgerbft/core/honeybadger.py b/honeybadgerbft/core/honeybadger.py index 625ea588..f2120024 100644 --- a/honeybadgerbft/core/honeybadger.py +++ b/honeybadgerbft/core/honeybadger.py @@ -123,8 +123,8 @@ def _recv(): while True: # For each round... r = self.round - logger.info(f"AAAAA round number: {self.round}") - logger.info(f"BBBBB transaction buffer with len: {len(self.transaction_buffer)}") + logger.debug(f"AAAAA round number: {self.round}") + logger.debug(f"BBBBB transaction buffer with len: {len(self.transaction_buffer)}") if r not in self._per_round_recv: self._per_round_recv[r] = Queue() @@ -153,7 +153,7 @@ def _send(j, o): self.round += 1 # Increment the round if not self.transaction_buffer: - logger.info(f"CCCCC finished with rounds: {self.round}") + logger.debug(f"CCCCC finished with rounds: {self.round}") break # Only run one round for now def _run_round(self, r, tx_to_send, send, recv): diff --git a/our_srcs/__pycache__/consts.cpython-37.pyc b/our_srcs/__pycache__/consts.cpython-37.pyc index 112d7fb9b7b8c0a49e48a4478e52caa8ff9e7779..b63963b81726bcee48c70761914ba4027188a64f 100644 GIT binary patch delta 20 acmZ3$vVeu#iI= identical_inputs, "There can't be more identical_inputs than number of nodes" +@mark.parametrize("HB", HONEYBADGERS) +@mark.parametrize("N", NUM_OF_NODE_OPTIONS) +@mark.parametrize("identical_inputs", NUM_OF_IDENTICAL_INPUTS_OPTIONS) +@mark.parametrize("input_sizes", INPUT_SIZES) +def test_honeybadger_full(HB, N, identical_inputs, input_sizes): + if N < identical_inputs: + logger.debug("There can't be more identical_inputs than number of nodes, skipping test") + return - badgers, threads = setup_honeybadgers(HB, N) + logger.info(f"Running Honeybadger test with parameters:\n\tHoneyBadger: {HB[0]}\n\tNumber of Nodes: {N}\n\tNumber of Identical Inputs: {identical_inputs}\n\tInput Sizes: {input_sizes}") + + badgers, threads = setup_honeybadgers(HB[1], N) time_at_start = datetime.datetime.now().timestamp() @@ -81,7 +54,9 @@ def _test_honeybadger_full(HB, N, identical_inputs, input_sizes): time_at_end = datetime.datetime.now().timestamp() time_diff = time_at_end - time_at_start logger.info(f"Time passed: {time_diff}") - return str(time_diff[:4]) + result = str(time_diff)[:4] + logger.critical(f"Result: {result} (params {HB[0]}, {N}, {identical_inputs}, {input_sizes})") + return str(time_diff)[:4] except KeyboardInterrupt: gevent.killall(threads) From f462e38a47288480fc54db3af0fa56d62d07e62a Mon Sep 17 00:00:00 2001 From: 1337samuels Date: Tue, 8 Feb 2022 19:36:01 +0000 Subject: [PATCH 22/29] Added analyze_results.py --- our_srcs/__pycache__/consts.cpython-37.pyc | Bin 544 -> 511 bytes our_srcs/analyze_results.py | 74 +++++++++++++++++++++ our_srcs/consts.py | 9 ++- test/my_test.py | 5 +- 4 files changed, 82 insertions(+), 6 deletions(-) create mode 100644 our_srcs/analyze_results.py diff --git a/our_srcs/__pycache__/consts.cpython-37.pyc b/our_srcs/__pycache__/consts.cpython-37.pyc index b63963b81726bcee48c70761914ba4027188a64f..ca4faed7a860acddc6a9f7e1521172884aa48c33 100644 GIT binary patch delta 208 zcmZ3$@}F7ViI`|;K zY$+TmoaxL_Y$+^J>?v$f96-#O!WGP*$vv?wR03qgOC}J(3?wocfJS99FbFVAe9`PK z5bPQf?-%MD@9!4x=kMYgd`lWh#M8yqFT~T?(I?*1FCa7|_!b{X63mVd_Kb2}$xy@x XG_r_q@-aq#Zblv^7Dg^c79a!wStu+t delta 214 zcmey*ynsdBiI%{X!1M+sCqKpbMLNK1EUqEO`e6VMf c>q>?qexRvE{F9e5`g1dJFtIRlF>(MQ05n)KKmY&$ diff --git a/our_srcs/analyze_results.py b/our_srcs/analyze_results.py new file mode 100644 index 00000000..4d618125 --- /dev/null +++ b/our_srcs/analyze_results.py @@ -0,0 +1,74 @@ +import sys +from matplotlib import pyplot as plt +import pandas +import re + +RESULT_REGEX = "\(\d\d:\d\d:\d\d\) CRITICAL: Result: (?P\d\d.\d) \(params (?P[a-zA-Z]* [a-zA-Z]*), (?P\d*), (?P\d*), (?P\d*)\)" + +SET_PARAMS = {"N": 6, "id": 2, "sz": 2}#1024*1024} +PARAMS = ['N', 'id', 'sz'] + + +def get_result_line(line): + return "CRITICAL" in line + + +def update_dict_by_param(full_dict, result_dict, param): + if result_dict['HB'] not in full_dict: + full_dict[result_dict['HB']] = {} + full_dict[result_dict['HB']][result_dict[param]] = result_dict['result_value'] + + +def extract_data(log_file): + data_by_nodes = {} + data_by_id = {} + data_by_size = {} + dicts_by_param = {'N': data_by_nodes, 'id': data_by_id, 'sz': data_by_size} + + with open(log_file, 'r') as f: + all_lines = f.readlines() + for l in all_lines: + regex_match = re.match(RESULT_REGEX, l) + if regex_match is None: + continue + rd = regex_match.groupdict() + for k in rd.keys(): + if k != 'HB': + rd[k] = float(rd[k]) + + for p in PARAMS: + should_add_point = True + # If all other params except this one are at the default state, add the point + for q in PARAMS: + if p != q and rd[q] != SET_PARAMS[q]: + should_add_point = False + print(f"{p}:{rd[p]}, {q}:{rd[q]}") + break + + if should_add_point: + update_dict_by_param(dicts_by_param[p], rd, p) + print(dicts_by_param) + return dicts_by_param + + +def analyze_data(pds): + ax = {} + fig, (ax['N'], ax['id'], ax['sz']) = plt.subplots(1, 3, sharey=True) + for p in pds.keys(): + for hb in pds[p]: + print(f"Plotting by honeybadger {hb}") + ax[p].plot(pds[p][hb].keys(), pds[p][hb].values()) + ax[p].set_title(p) + ax[p].legend(pds[p].keys()) + ax['sz'].set_xscale('log') + plt.show() + + +def main(): + assert len(sys.argv) == 2, "Give log file parameter please" + pbs = extract_data(sys.argv[1]) + analyze_data(pbs) + + +main() + diff --git a/our_srcs/consts.py b/our_srcs/consts.py index 836158ee..2e92e202 100644 --- a/our_srcs/consts.py +++ b/our_srcs/consts.py @@ -5,11 +5,10 @@ LOG_PATH = LOG_DIR + '/honeybadger_test_{}_{}_{}_{}_{}_{}.log' LOGGER_NAME = 'honeybadger_test_logger' NUM_OF_NODE_OPTIONS = [4, 6] -#NUM_OF_IDENTICAL_INPUTS_OPTIONS = [0, 2, 4] -NUM_OF_IDENTICAL_INPUTS_OPTIONS = [2, 4] +NUM_OF_IDENTICAL_INPUTS_OPTIONS = [0, 2, 4, 6] NUM_OF_INPUTS_IN_ITERATION = 3 INPUT_SIZES = [2, 1024, 1024*1024] -DEFAULT_NUM_OF_NODES = NUM_OF_NODE_OPTIONS[-2] -DEFAULT_NUM_OF_IDENTICAL_INPUTS_OPTIONS = NUM_OF_IDENTICAL_INPUTS_OPTIONS[-1] -DEFAULT_INPUT_SIZE = INPUT_SIZES[-1] +SET_NUM_OF_NODES = 6 +SET_NUM_OF_IDENTICAL_INPUTS = 2 +SET_INPUT_SIZE = 2 # TODO: Change to 1024*1024 diff --git a/test/my_test.py b/test/my_test.py index a962bdd6..55d30b92 100755 --- a/test/my_test.py +++ b/test/my_test.py @@ -25,7 +25,10 @@ def test_honeybadger_full(HB, N, identical_inputs, input_sizes): if N < identical_inputs: logger.debug("There can't be more identical_inputs than number of nodes, skipping test") - return + return + if (N != SET_NUM_OF_NODES and identical_inputs != SET_NUM_OF_IDENTICAL_INPUTS) or (N != SET_NUM_OF_NODES and input_sizes != SET_INPUT_SIZE) or (identical_inputs != SET_NUM_OF_IDENTICAL_INPUTS and input_sizes != SET_INPUT_SIZE): + logger.debug("Not an interesting test, skipping") + return logger.info(f"Running Honeybadger test with parameters:\n\tHoneyBadger: {HB[0]}\n\tNumber of Nodes: {N}\n\tNumber of Identical Inputs: {identical_inputs}\n\tInput Sizes: {input_sizes}") From 277039510fdee130e094d666b2154207c2d3292d Mon Sep 17 00:00:00 2001 From: Dor Aharonson Date: Wed, 9 Feb 2022 14:22:48 +0200 Subject: [PATCH 23/29] Change gevent use --- experiments/honest_party_test_EC2.py | 4 ++-- experiments/run_local_tor.py | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/experiments/honest_party_test_EC2.py b/experiments/honest_party_test_EC2.py index dc698a37..115166a6 100755 --- a/experiments/honest_party_test_EC2.py +++ b/experiments/honest_party_test_EC2.py @@ -1,6 +1,6 @@ #!/usr/bin/python __author__ = 'aluex' -from gevent import monkey +from gevent import monkey, sleep monkey.patch_all() from gevent.queue import * @@ -267,7 +267,7 @@ def toBeScheduled(): finally: print "Consensus Finished" - s = sched.scheduler(time.time, time.sleep) + s = sched.scheduler(time.time, sleep) time_now = time.time() delay = options.delaytime - time_now diff --git a/experiments/run_local_tor.py b/experiments/run_local_tor.py index 6fb2916b..af3056b8 100644 --- a/experiments/run_local_tor.py +++ b/experiments/run_local_tor.py @@ -1,6 +1,7 @@ __author__ = 'aluex' import subprocess32 as subprocess +from gevent import sleep import time def runOnTransaction(N, t, Tx): retry = True @@ -15,7 +16,7 @@ def runOnTransaction(N, t, Tx): retry = False except subprocess.TimeoutExpired: retry = True - time.sleep(2) + sleep(2) q = subprocess.check_output(['python', 'process.py', 'msglog.TorMultiple']) print N, t, Tx, q.replace('\n', ' ') From 4bd822137249d3101491c839777e0d83ad147370 Mon Sep 17 00:00:00 2001 From: Dor Aharonson Date: Wed, 9 Feb 2022 14:23:09 +0200 Subject: [PATCH 24/29] Change gevent use --- misc/includeTransaction.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/misc/includeTransaction.py b/misc/includeTransaction.py index 6f8bd0be..7e503574 100644 --- a/misc/includeTransaction.py +++ b/misc/includeTransaction.py @@ -1,6 +1,7 @@ __author__ = 'aluex' - -from gevent import Greenlet +from gevent import monkey +monkey.patch_all() +from gevent import Greenlet, sleep from gevent.queue import Queue, Empty from bkr_acs import acs from utils import mylog, MonitoredInt, callBackWrap, greenletFunction, \ @@ -321,7 +322,7 @@ def listener(): broadcast(eval(msg)) # now the msg is something we mannually send mylog("timestampB (%d, %lf)" % (pid, time.time()), verboseLevel=-2) if len(transactionCache) < B: # Let's wait for many transactions. : ) - time.sleep(0.5) + sleep(0.5) print "Not enough transactions", len(transactionCache) continue From 709c48a85c8230bc8622d7cc98021f267529507f Mon Sep 17 00:00:00 2001 From: Dor Aharonson Date: Wed, 9 Feb 2022 14:29:58 +0200 Subject: [PATCH 25/29] Fixed hanging --- honeybadgerbft/core/binaryagreement.py | 2 ++ honeybadgerbft/core/commonsubset.py | 5 ++++ honeybadgerbft/core/honeybadger.py | 37 ++++++++++++++---------- honeybadgerbft/core/honeybadger_block.py | 5 ++-- our_srcs/utils.py | 7 +++-- test/my_test.py | 21 +++++++++----- 6 files changed, 49 insertions(+), 28 deletions(-) diff --git a/honeybadgerbft/core/binaryagreement.py b/honeybadgerbft/core/binaryagreement.py index 5925a603..38731a5a 100644 --- a/honeybadgerbft/core/binaryagreement.py +++ b/honeybadgerbft/core/binaryagreement.py @@ -1,3 +1,5 @@ +from gevent import monkey +monkey.patch_all() import gevent from gevent.event import Event diff --git a/honeybadgerbft/core/commonsubset.py b/honeybadgerbft/core/commonsubset.py index 050ec3c8..63526229 100644 --- a/honeybadgerbft/core/commonsubset.py +++ b/honeybadgerbft/core/commonsubset.py @@ -1,6 +1,11 @@ +from gevent import monkey +monkey.patch_all() import gevent +from our_srcs.consts import * +from logging import getLogger; logger=getLogger(LOGGER_NAME) + def commonsubset(pid, N, f, rbc_out, aba_in, aba_out): """The BKR93 algorithm for asynchronous common subset. diff --git a/honeybadgerbft/core/honeybadger.py b/honeybadgerbft/core/honeybadger.py index f2120024..3c16e4f8 100644 --- a/honeybadgerbft/core/honeybadger.py +++ b/honeybadgerbft/core/honeybadger.py @@ -1,9 +1,11 @@ from collections import namedtuple from enum import Enum - +from gevent import monkey +monkey.patch_all() import gevent from gevent.queue import Queue + from honeybadgerbft.core.commoncoin import shared_coin from honeybadgerbft.core.binaryagreement import binaryagreement from honeybadgerbft.core.reliablebroadcast import reliablebroadcast @@ -68,7 +70,7 @@ class HoneyBadgerBFT(): :param recv: """ - def __init__(self, sid, pid, B, N, f, sPK, sSK, ePK, eSK, send, recv): + def __init__(self, sid, pid, B, N, f, sPK, sSK, ePK, eSK, send, recv, amount=-1): self.sid = sid self.pid = pid self.B = B @@ -80,10 +82,12 @@ def __init__(self, sid, pid, B, N, f, sPK, sSK, ePK, eSK, send, recv): self.eSK = eSK self._send = send self._recv = recv + self.amount = amount self.round = 0 # Current block number self.transaction_buffer = [] self._per_round_recv = {} # Buffer of incoming messages + self.messages_seen = set() def submit_tx(self, tx): """Appends the given transaction to the transaction buffer. @@ -123,16 +127,19 @@ def _recv(): while True: # For each round... r = self.round - logger.debug(f"AAAAA round number: {self.round}") - logger.debug(f"BBBBB transaction buffer with len: {len(self.transaction_buffer)}") + logger.debug(str(self.pid) + f"AAAAA round number: {self.round}") + logger.debug(str(self.pid) + f"BBBBB transaction buffer with len: {len(self.transaction_buffer)}") if r not in self._per_round_recv: self._per_round_recv[r] = Queue() # Select all the transactions (TODO: actual random selection) self._prepare_transaction_buffer() - tx_to_send = self.transaction_buffer[:self.B] - logger.debug(f"EEEEE transaction_buffer for id {self.pid}: {[t[:40] for t in self.transaction_buffer]}") - logger.debug(f"Chosen tx_to_send for {self.pid} is {tx_to_send[0][:40]}") + if len(self.transaction_buffer): + tx_to_send = self.transaction_buffer[:self.B] + logger.debug(str(self.pid) + f"Chosen tx_to_send for {self.pid} is {tx_to_send[0][:40]}") + else: + tx_to_send = [''] + logger.debug(str(self.pid) + f"EEEEE transaction_buffer for id {self.pid}: {[t[:40] for t in self.transaction_buffer]}") # TODO: Wait a bit if transaction buffer is not full @@ -145,15 +152,19 @@ def _send(j, o): recv_r = self._per_round_recv[r].get new_tx = self._run_round(r, tx_to_send[0], send_r, recv_r) for nino in new_tx: - logger.debug(f'Node id {self.pid} got from his friends: {nino[:40]}') + if nino != b'': + logger.debug(str(self.pid) + f'Node id {self.pid} got from his friends: {nino[:40]}') + self.messages_seen.add(nino) # Remove all of the new transactions from the buffer self.transaction_buffer = [_tx for _tx in self.transaction_buffer if _tx not in [t.decode('utf-8') for t in new_tx] and _tx not in tx_to_send] - logger.debug(f"New transaction buffer after getting messages for id {self.pid}: {[t[:40] for t in self.transaction_buffer]}") + logger.debug(str(self.pid) + f"New transaction buffer after getting messages for id {self.pid}: {[t[:40] for t in self.transaction_buffer]}") self.round += 1 # Increment the round - if not self.transaction_buffer: - logger.debug(f"CCCCC finished with rounds: {self.round}") + # if not self.transaction_buffer: + logger.debug(f"{self.pid} Up to now: {len(set(self.messages_seen))} out of {self.amount}") + if len(set(self.messages_seen)) == self.amount: + logger.debug(str(self.pid) + f"CCCCC finished with rounds: {self.round}") break # Only run one round for now def _run_round(self, r, tx_to_send, send, recv): @@ -236,19 +247,16 @@ def rbc_send(k, o): # N instances of ABA, RBC for j in range(N): _setup(j) - # One instance of TPKE def tpke_bcast(o): """Threshold encryption broadcast.""" broadcast(('TPKE', 0, o)) tpke_recv = Queue() - # One instance of ACS acs = gevent.spawn(commonsubset, pid, N, f, rbc_outputs, [_.put_nowait for _ in aba_inputs], [_.get for _ in aba_outputs]) - recv_queues = BroadcastReceiverQueues( ACS_COIN=coin_recvs, ACS_ABA=aba_recvs, @@ -256,7 +264,6 @@ def tpke_bcast(o): TPKE=tpke_recv, ) gevent.spawn(broadcast_receiver_loop, recv, recv_queues) - _input = Queue(1) _input.put(tx_to_send) return honeybadger_block(pid, self.N, self.f, self.ePK, self.eSK, diff --git a/honeybadgerbft/core/honeybadger_block.py b/honeybadgerbft/core/honeybadger_block.py index 0f6848ee..c19e3ca5 100644 --- a/honeybadgerbft/core/honeybadger_block.py +++ b/honeybadgerbft/core/honeybadger_block.py @@ -1,5 +1,7 @@ from ..crypto.threshenc import tpke import os +from our_srcs.consts import * +from logging import getLogger; logger=getLogger(LOGGER_NAME) def serialize_UVW(U, V, W): @@ -70,7 +72,6 @@ def honeybadger_block(pid, N, f, PK, SK, propose_in, acs_in, acs_out, tpke_bcast share = SK.decrypt_share(*tkey) # share is of the form: U_i, an element of group1 my_shares.append(share) - tpke_bcast(my_shares) # Receive everyone's shares @@ -82,7 +83,6 @@ def honeybadger_block(pid, N, f, PK, SK, propose_in, acs_in, acs_out, tpke_bcast print('Received a duplicate decryption share from', j) continue shares_received[j] = shares - assert len(shares_received) >= f+1 # TODO: Accountability # If decryption fails at this point, we will have evidence of misbehavior, @@ -100,5 +100,4 @@ def honeybadger_block(pid, N, f, PK, SK, propose_in, acs_in, acs_out, tpke_bcast plain = tpke.decrypt(key, ciph) decryptions.append(plain) # print 'Done!', decryptions - return tuple(decryptions) diff --git a/our_srcs/utils.py b/our_srcs/utils.py index 5de24594..45452c22 100644 --- a/our_srcs/utils.py +++ b/our_srcs/utils.py @@ -4,7 +4,8 @@ import datetime import random import math - +from gevent import monkey +monkey.patch_all() from honeybadgerbft.crypto.threshsig.boldyreva import dealer from honeybadgerbft.crypto.threshenc import tpke import gevent @@ -34,7 +35,7 @@ def setup_logging(): logger.addHandler(ch) logger.addHandler(fi) -def setup_honeybadgers(honeybadger_class, N): +def setup_honeybadgers(honeybadger_class, N, amount=-1): sid = 'sidA' # Generate threshold sig keys sPK, sSKs = dealer(N, 2, seed=None) @@ -51,7 +52,7 @@ def setup_honeybadgers(honeybadger_class, N): for i in range(N): badgers[i] = honeybadger_class(sid, i, 1, N, 1, sPK, sSKs[i], ePK, eSKs[i], - sends[i], recvs[i]) + sends[i], recvs[i], amount=amount) threads[i] = gevent.spawn(badgers[i].run) return badgers, threads diff --git a/test/my_test.py b/test/my_test.py index 55d30b92..d43ddc22 100755 --- a/test/my_test.py +++ b/test/my_test.py @@ -2,7 +2,8 @@ from collections import defaultdict import math import datetime - +from gevent import monkey +monkey.patch_all() import gevent from gevent.event import Event from gevent.queue import Queue @@ -32,19 +33,25 @@ def test_honeybadger_full(HB, N, identical_inputs, input_sizes): logger.info(f"Running Honeybadger test with parameters:\n\tHoneyBadger: {HB[0]}\n\tNumber of Nodes: {N}\n\tNumber of Identical Inputs: {identical_inputs}\n\tInput Sizes: {input_sizes}") - badgers, threads = setup_honeybadgers(HB[1], N) - - time_at_start = datetime.datetime.now().timestamp() - + txs_to_submit = [[] for i in range(N)] for iter_index in range(NUM_OF_INPUTS_IN_ITERATION): identical_hbs = random.sample(range(N), identical_inputs) logger.debug(f"At epoch {iter_index} chose identical_inputs {identical_hbs}") for node_index in range(N): if node_index in identical_hbs: - badgers[node_index].submit_tx(f' ' + 'a'*input_sizes) + txs_to_submit[node_index].append(f' ' + 'a'*input_sizes) else: - badgers[node_index].submit_tx(f' Date: Thu, 10 Feb 2022 17:30:06 +0200 Subject: [PATCH 26/29] Some impovements but nothing works --- honeybadgerbft/core/honeybadger.py | 22 +++++++++++++++++++--- our_srcs/analyze_results.py | 4 ++-- our_srcs/consts.py | 16 ++++++++-------- our_srcs/utils.py | 5 ++++- test/my_test.py | 19 +++++++++++-------- 5 files changed, 44 insertions(+), 22 deletions(-) diff --git a/honeybadgerbft/core/honeybadger.py b/honeybadgerbft/core/honeybadger.py index 3c16e4f8..38d18638 100644 --- a/honeybadgerbft/core/honeybadger.py +++ b/honeybadgerbft/core/honeybadger.py @@ -4,6 +4,7 @@ monkey.patch_all() import gevent from gevent.queue import Queue +import hashlib from honeybadgerbft.core.commoncoin import shared_coin @@ -275,15 +276,30 @@ def tpke_bcast(o): def permute_list(lst, index): return lst[index:] + lst[:index] +def sha256(s): + return hashlib.sha256(s.encode()).digest().hex() + +def distance(frac): + def dist(s): + return abs(int((2**256) * frac) - int.from_bytes(hashlib.sha256(s.encode()).digest(), 'big')) + return dist + class ImprovedHoneyBadgerBFT(HoneyBadgerBFT): def _prepare_transaction_buffer(self): - self.transaction_buffer = sorted(self.transaction_buffer, key=str.lower, reverse=(self.pid%2 == 1)) + self.transaction_buffer = sorted(self.transaction_buffer, key=sha256, reverse=(self.pid%2 == 1)) class PermutedHoneyBadgerBFT(HoneyBadgerBFT): def _prepare_transaction_buffer(self): - self.transaction_buffer = sorted(self.transaction_buffer, key=str.lower) - self.transaction_buffer = permute_list(self.transaction_buffer, self.pid) + self.transaction_buffer = sorted(self.transaction_buffer, key=sha256) + self.transaction_buffer = permute_list(self.transaction_buffer, int((self.pid / self.N) * self.N)) + logger.debug("permutating") class RandomizedHoneyBadgerBFT(HoneyBadgerBFT): def _prepare_transaction(self): self.transaction_buffer = random.sample(self.transaction_buffer, len(self.transaction_buffer)) + +class DistanceHoneyBadgerBFT(HoneyBadgerBFT): + def _prepare_transaction(self): + self.transaction_buffer = sorted(self.transaction_buffer, key=distance(self.pid / self.N)) + logger.debug("permutating with distance") + diff --git a/our_srcs/analyze_results.py b/our_srcs/analyze_results.py index 4d618125..fb3818d1 100644 --- a/our_srcs/analyze_results.py +++ b/our_srcs/analyze_results.py @@ -3,9 +3,9 @@ import pandas import re -RESULT_REGEX = "\(\d\d:\d\d:\d\d\) CRITICAL: Result: (?P\d\d.\d) \(params (?P[a-zA-Z]* [a-zA-Z]*), (?P\d*), (?P\d*), (?P\d*)\)" +RESULT_REGEX = "\(\d\d:\d\d:\d\d\) CRITICAL: Result: (?P[\d]+.?[\d]*) \(params (?P[a-zA-Z]* [a-zA-Z]*), (?P\d*), (?P\d*), (?P\d*)\)" -SET_PARAMS = {"N": 6, "id": 2, "sz": 2}#1024*1024} +SET_PARAMS = {"N": 10, "id": 6, "sz": 2**20} PARAMS = ['N', 'id', 'sz'] diff --git a/our_srcs/consts.py b/our_srcs/consts.py index 2e92e202..08fc4f02 100644 --- a/our_srcs/consts.py +++ b/our_srcs/consts.py @@ -4,11 +4,11 @@ LOG_PATH = LOG_DIR + '/honeybadger_test_{}_{}_{}_{}_{}_{}.log' LOGGER_NAME = 'honeybadger_test_logger' -NUM_OF_NODE_OPTIONS = [4, 6] -NUM_OF_IDENTICAL_INPUTS_OPTIONS = [0, 2, 4, 6] - -NUM_OF_INPUTS_IN_ITERATION = 3 -INPUT_SIZES = [2, 1024, 1024*1024] -SET_NUM_OF_NODES = 6 -SET_NUM_OF_IDENTICAL_INPUTS = 2 -SET_INPUT_SIZE = 2 # TODO: Change to 1024*1024 +NUM_OF_NODE_OPTIONS = [4, 6, 8, 10] +NUM_OF_IDENTICAL_INPUTS_OPTIONS = [0, 2, 4, 6, 8, 10] + +NUM_OF_INPUTS_IN_ITERATION = 6 +INPUT_SIZES = [2, 2**2, 2**4, 2**8, 2**16, 2**20, 2**24] +SET_NUM_OF_NODES = 10 +SET_NUM_OF_IDENTICAL_INPUTS = 6 +SET_INPUT_SIZE = 2**16 diff --git a/our_srcs/utils.py b/our_srcs/utils.py index 45452c22..40375de0 100644 --- a/our_srcs/utils.py +++ b/our_srcs/utils.py @@ -12,6 +12,8 @@ from gevent.event import Event from gevent.queue import Queue +from our_srcs.consts import * +from logging import getLogger; logger=getLogger(LOGGER_NAME) def setup_logging(): if not os.path.isdir(LOG_DIR): @@ -70,7 +72,8 @@ def simple_router(N, maxdelay=0.005, seed=None): def makeSend(i): def _send(j, o): delay = rnd.random() * maxdelay - delay *= math.log(len(o)) + messageLen = sum([len(s) if type(s) is str else 0 for s in o[1][2]]) + delay *= math.log(messageLen) if messageLen != 0 else 1 gevent.spawn_later(delay, queues[j].put_nowait, (i,o)) return _send diff --git a/test/my_test.py b/test/my_test.py index d43ddc22..7438a3f9 100755 --- a/test/my_test.py +++ b/test/my_test.py @@ -13,16 +13,20 @@ from our_srcs.consts import * from our_srcs.utils import * -from honeybadgerbft.core.honeybadger import HoneyBadgerBFT, ImprovedHoneyBadgerBFT, PermutedHoneyBadgerBFT, RandomizedHoneyBadgerBFT -HONEYBADGERS = [("Ordered Honeybadger", HoneyBadgerBFT), ("Permuted Honeybadger", PermutedHoneyBadgerBFT), ("Randomized Honeybadger", RandomizedHoneyBadgerBFT), ("Parity Honeybadger", ImprovedHoneyBadgerBFT)] +from honeybadgerbft.core.honeybadger import HoneyBadgerBFT, ImprovedHoneyBadgerBFT, PermutedHoneyBadgerBFT, RandomizedHoneyBadgerBFT, DistanceHoneyBadgerBFT +HONEYBADGERS = [("Ordered Honeybadger", HoneyBadgerBFT), ("Permuted Honeybadger", PermutedHoneyBadgerBFT), ("Randomized Honeybadger", RandomizedHoneyBadgerBFT), ("Parity Honeybadger", ImprovedHoneyBadgerBFT), ("Distance Honeybadger", DistanceHoneyBadgerBFT)] setup_logging() logger = getLogger(LOGGER_NAME) ### Test asynchronous common subset -@mark.parametrize("HB", HONEYBADGERS) -@mark.parametrize("N", NUM_OF_NODE_OPTIONS) -@mark.parametrize("identical_inputs", NUM_OF_IDENTICAL_INPUTS_OPTIONS) -@mark.parametrize("input_sizes", INPUT_SIZES) +# @mark.parametrize("HB", HONEYBADGERS) +# @mark.parametrize("N", NUM_OF_NODE_OPTIONS) +# @mark.parametrize("identical_inputs", NUM_OF_IDENTICAL_INPUTS_OPTIONS) +# @mark.parametrize("input_sizes", INPUT_SIZES) +@mark.parametrize("HB", HONEYBADGERS[1:2]) +@mark.parametrize("N", [10]) +@mark.parametrize("identical_inputs", [6]) +@mark.parametrize("input_sizes", [2]) def test_honeybadger_full(HB, N, identical_inputs, input_sizes): if N < identical_inputs: logger.debug("There can't be more identical_inputs than number of nodes, skipping test") @@ -57,14 +61,13 @@ def test_honeybadger_full(HB, N, identical_inputs, input_sizes): try: outs = [threads[i].get() for i in range(N)] - # Consistency check assert len(set(outs)) == 1 time_at_end = datetime.datetime.now().timestamp() time_diff = time_at_end - time_at_start logger.info(f"Time passed: {time_diff}") - result = str(time_diff)[:4] + result = str(round(time_diff, 2)) logger.critical(f"Result: {result} (params {HB[0]}, {N}, {identical_inputs}, {input_sizes})") return str(time_diff)[:4] From 159c2b064d79b9baf0f08b3e07c9816610d9810d Mon Sep 17 00:00:00 2001 From: Dor Aharonson Date: Mon, 14 Feb 2022 07:40:53 +0200 Subject: [PATCH 27/29] Update --- honeybadgerbft/core/honeybadger.py | 6 +++--- test/my_test.py | 12 ++++-------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/honeybadgerbft/core/honeybadger.py b/honeybadgerbft/core/honeybadger.py index 38d18638..d34b4632 100644 --- a/honeybadgerbft/core/honeybadger.py +++ b/honeybadgerbft/core/honeybadger.py @@ -5,7 +5,7 @@ import gevent from gevent.queue import Queue import hashlib - +import random from honeybadgerbft.core.commoncoin import shared_coin from honeybadgerbft.core.binaryagreement import binaryagreement @@ -295,11 +295,11 @@ def _prepare_transaction_buffer(self): logger.debug("permutating") class RandomizedHoneyBadgerBFT(HoneyBadgerBFT): - def _prepare_transaction(self): + def _prepare_transaction_buffer(self): self.transaction_buffer = random.sample(self.transaction_buffer, len(self.transaction_buffer)) class DistanceHoneyBadgerBFT(HoneyBadgerBFT): - def _prepare_transaction(self): + def _prepare_transaction_buffer(self): self.transaction_buffer = sorted(self.transaction_buffer, key=distance(self.pid / self.N)) logger.debug("permutating with distance") diff --git a/test/my_test.py b/test/my_test.py index 7438a3f9..a0ef04dc 100755 --- a/test/my_test.py +++ b/test/my_test.py @@ -19,14 +19,10 @@ logger = getLogger(LOGGER_NAME) ### Test asynchronous common subset -# @mark.parametrize("HB", HONEYBADGERS) -# @mark.parametrize("N", NUM_OF_NODE_OPTIONS) -# @mark.parametrize("identical_inputs", NUM_OF_IDENTICAL_INPUTS_OPTIONS) -# @mark.parametrize("input_sizes", INPUT_SIZES) -@mark.parametrize("HB", HONEYBADGERS[1:2]) -@mark.parametrize("N", [10]) -@mark.parametrize("identical_inputs", [6]) -@mark.parametrize("input_sizes", [2]) +@mark.parametrize("HB", HONEYBADGERS) +@mark.parametrize("N", NUM_OF_NODE_OPTIONS) +@mark.parametrize("identical_inputs", NUM_OF_IDENTICAL_INPUTS_OPTIONS) +@mark.parametrize("input_sizes", INPUT_SIZES) def test_honeybadger_full(HB, N, identical_inputs, input_sizes): if N < identical_inputs: logger.debug("There can't be more identical_inputs than number of nodes, skipping test") From 8c802e47b1adde20c0b5522b3e4e2d4c5ea0dac2 Mon Sep 17 00:00:00 2001 From: 1337samuels Date: Mon, 14 Feb 2022 14:14:48 +0000 Subject: [PATCH 28/29] Run both tests --- .gitignore | 3 ++ honeybadgerbft/core/honeybadger.py | 26 ++++++++++------ our_srcs/__pycache__/consts.cpython-37.pyc | Bin 511 -> 0 bytes our_srcs/__pycache__/utils.cpython-37.pyc | Bin 3027 -> 0 bytes our_srcs/analyze_results.py | 29 ++++++++++++++---- our_srcs/consts.py | 9 ++++-- ...{my_test.py => throughput_latency_test.py} | 16 +++++++--- 7 files changed, 60 insertions(+), 23 deletions(-) delete mode 100644 our_srcs/__pycache__/consts.cpython-37.pyc delete mode 100644 our_srcs/__pycache__/utils.cpython-37.pyc rename test/{my_test.py => throughput_latency_test.py} (87%) diff --git a/.gitignore b/.gitignore index 80427e1b..0e9be5aa 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,6 @@ logs/ .coverage docs/_build/ *.pyc +important_logs/ +backup_tests/ +our_srcs/__pycache__/ diff --git a/honeybadgerbft/core/honeybadger.py b/honeybadgerbft/core/honeybadger.py index d34b4632..5e7c802a 100644 --- a/honeybadgerbft/core/honeybadger.py +++ b/honeybadgerbft/core/honeybadger.py @@ -89,15 +89,19 @@ def __init__(self, sid, pid, B, N, f, sPK, sSK, ePK, eSK, send, recv, amount=-1) self.transaction_buffer = [] self._per_round_recv = {} # Buffer of incoming messages self.messages_seen = set() + self.bytes_sent = 0 def submit_tx(self, tx): """Appends the given transaction to the transaction buffer. :param tx: Transaction to append to the buffer. """ - print('submit_tx', self.pid, tx) self.transaction_buffer.append(tx) + def get_bytes_sent(self): + """Returns the ammount of non empty messages sent""" + return self.bytes_sent + def _prepare_transaction_buffer(self): pass @@ -128,8 +132,8 @@ def _recv(): while True: # For each round... r = self.round - logger.debug(str(self.pid) + f"AAAAA round number: {self.round}") - logger.debug(str(self.pid) + f"BBBBB transaction buffer with len: {len(self.transaction_buffer)}") + logger.debug(str(self.pid) + f" round number: {self.round}") + logger.debug(str(self.pid) + f" transaction buffer with len: {len(self.transaction_buffer)}") if r not in self._per_round_recv: self._per_round_recv[r] = Queue() @@ -138,6 +142,9 @@ def _recv(): if len(self.transaction_buffer): tx_to_send = self.transaction_buffer[:self.B] logger.debug(str(self.pid) + f"Chosen tx_to_send for {self.pid} is {tx_to_send[0][:40]}") + for t in tx_to_send: + self.bytes_sent += len(t) + else: tx_to_send = [''] logger.debug(str(self.pid) + f"EEEEE transaction_buffer for id {self.pid}: {[t[:40] for t in self.transaction_buffer]}") @@ -152,10 +159,10 @@ def _send(j, o): send_r = _make_send(r) recv_r = self._per_round_recv[r].get new_tx = self._run_round(r, tx_to_send[0], send_r, recv_r) - for nino in new_tx: - if nino != b'': - logger.debug(str(self.pid) + f'Node id {self.pid} got from his friends: {nino[:40]}') - self.messages_seen.add(nino) + for msg_recvd in new_tx: + if msg_recvd != b'': + logger.debug(str(self.pid) + f'Node id {self.pid} got from his friends: {msg_recvd[:40]}') + self.messages_seen.add(msg_recvd) # Remove all of the new transactions from the buffer self.transaction_buffer = [_tx for _tx in self.transaction_buffer if _tx not in [t.decode('utf-8') for t in new_tx] and _tx not in tx_to_send] @@ -165,8 +172,8 @@ def _send(j, o): # if not self.transaction_buffer: logger.debug(f"{self.pid} Up to now: {len(set(self.messages_seen))} out of {self.amount}") if len(set(self.messages_seen)) == self.amount: - logger.debug(str(self.pid) + f"CCCCC finished with rounds: {self.round}") - break # Only run one round for now + logger.debug(str(self.pid) + f" finished with rounds: {self.round}") + break def _run_round(self, r, tx_to_send, send, recv): """Run one protocol round. @@ -200,7 +207,6 @@ def broadcast(o): rbc_outputs = [Queue(1) for _ in range(N)] my_rbc_input = Queue(1) - print(pid, r, 'tx_to_send:', tx_to_send) def _setup(j): """Setup the sub protocols RBC, BA and common coin. diff --git a/our_srcs/__pycache__/consts.cpython-37.pyc b/our_srcs/__pycache__/consts.cpython-37.pyc deleted file mode 100644 index ca4faed7a860acddc6a9f7e1521172884aa48c33..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 511 zcmZWl%}&BV5Z<KrU{+t!Voyo znITSuS#Zp-C^5COL^&~-DKIMulUa~uVTY($*_th9ktT9`?L4N-cr%@dB+mFMmMi}9 zdbC>LWQ~75P@!k1-nKIpK%$+lzyO#dsLTKBhZHHvTG_D|0hT#vBQ7@70tv8LL2+WO_1M_vZY%`>23Zhe_V6JO zhje#SUMa&vU?Y+bd&obajsb%Ffc%uc1vv!%3wzqHdh|>X=a3<~y1Kf$s=8jy&04L( z@O}D6=h>vp*gt7;@wq^Lg`xfgAei7Oi;9^?9BU_a_KUR}xpv=+JUjc5kJ(LwVJRwc z;_=dOSdPjT=V>LXfaa%j!)jEuv>>ew=c9SxB@w=6(Sj(83g$&IFRG&Unn$+;-(!u1 zx3Gn^8r<-Y00NQ3X(EAndi*@W>~9?=nI_~nlVp-~h@CzkgRc5HhWaajW(R!cX!ne( zJDSZr!Z_3ZEYPJhK4m$Zh1x$T7u17_;KC8^x6YJm?#zZus9A^cGp*)tgr0B3ndZjq&w7&_l+}B#v8}FZ~TE0 z18GW+zuaj*{NkzchtKUg9rb#HtY^x-L_Y?eNHYhXovo+s)`KToCRCu4R^vb1+WhT~ zDQ}PDFxDE3wLLA9c(@y90s%4J7p?6tO-S0wV&i6`mu7BzkR}%#A!+~W!TzoZx>kzu zj*?iym{A5BT@fD{uRoed6ATC0L?cUoK>lWlpCb zg`J6PTSJ`g;4e&mhy?g6((AwcSyc9Bsw|=Qp?a*Pyx$vRa$yL8_YL zBU6Lo$+&&)rUlBR9|AC5hq&;~pAVaaf5$@bsiRp= zsfBv^*8RORb*G-@GfO*ju=b~cc4nwAq)jO=%^W0IsJ)!$A*CZY%2QNRkLP@uP3JDL z>Noq^&-p9r9t@|wUo3^(`k+C7&0d0^+Vg%yIY=JL6`w!w5TD-m{&9fW5* zuM+J=_je4mYS%$Z`mM-Q1M%Q3U5*M+C5d>;X;GHcI;00+0*Q)bgNGhd1fQh?xe9&hPNUYS^>U#1pRxDROBXv zCO~m66VY5Dx=r>(zDhEoB3~w*LuE>ZEFij%Y!#3gNQsXpq~Q9fDH(TS*c`Z3T{eO!Mz(EWN5q`FAb_^48;<6D==b(yW#SK+#3aF~GA z`m$lSI}~X8DEf4_Jq)!3&_fsdx`HmrUa>zrFTA~?+8SI2*ljq*X?|jO``_IDU1cL3 zDBT$i$M-i$6v++P@sDn#OLN0ktGW;5g8POglJsig0Sb_;& z&^xB&&p^JGratmJ6Wbsvx&if|C4SueFYX$~&yzjyUpdeoxAGc}RVjBMrQymgOp@eU zjR+grBW-EGs6q_!DDpMqOWyGZ|3m4G2$9RJyD3*FLS4t!!L{g+T>2;lXjt~UKu-B7 zJWmlq*JB8$jQ~Ol-*e;Q)w;OL=imlTnN-~6L&EGO{5JK1Cs?1~V9|M}+n$2^n%n5` zh1;z7Uy~|swP3QOD`(N+$5*Q6-|Z~ozTvFPbY6xGTUga8d_Wm_t+X!8p#-+kf*rer zUtU^nV7Z5JURM9F61pXnJo-;1`&UYkOH>Z>Cj{02klQ~c+-BHEz@o5y-iM1T_=QAk z`^_}8p_5IVp-U=yN10!7m$>IFma3&?Zub!J&#=*IEXfeFtO1yXi+8+>jwP3}|IRqq3Y{PO2iQTzDc!K-d~C%pYV D4(Hpx diff --git a/our_srcs/analyze_results.py b/our_srcs/analyze_results.py index fb3818d1..12d5cb2a 100644 --- a/our_srcs/analyze_results.py +++ b/our_srcs/analyze_results.py @@ -1,11 +1,12 @@ import sys +import os from matplotlib import pyplot as plt import pandas import re -RESULT_REGEX = "\(\d\d:\d\d:\d\d\) CRITICAL: Result: (?P[\d]+.?[\d]*) \(params (?P[a-zA-Z]* [a-zA-Z]*), (?P\d*), (?P\d*), (?P\d*)\)" +RESULT_REGEX = "\(\d\d:\d\d:\d\d\) CRITICAL: Result: bytes_sent=(?P\d+),total_time=(?P[\d]+.?[\d]*) \(params (?P[a-zA-Z]* [a-zA-Z]*), (?P\d*), (?P\d*), (?P\d*)\)" -SET_PARAMS = {"N": 10, "id": 6, "sz": 2**20} +SET_PARAMS = {"N": 8, "id": 6, "sz": 2**16} PARAMS = ['N', 'id', 'sz'] @@ -16,8 +17,23 @@ def get_result_line(line): def update_dict_by_param(full_dict, result_dict, param): if result_dict['HB'] not in full_dict: full_dict[result_dict['HB']] = {} - full_dict[result_dict['HB']][result_dict[param]] = result_dict['result_value'] - + full_dict[result_dict['HB']][result_dict[param]] = result_dict['total_time'] + +def get_lines(log_file): + all_lines = [] + if os.path.isfile(log_file): + with open(log_file, 'r') as f: + all_lines += f.readlines() + elif os.path.isdir(log_file): + log_files = os.listdir(log_file) + for file_name in log_files: + cur_full_file = '\\'.join([log_file, file_name]) + if os.path.isfile(cur_full_file): + with open(cur_full_file, 'r') as f: + all_lines += f.readlines() + else: + assert False, f"what is {log_file}??" + return all_lines def extract_data(log_file): data_by_nodes = {} @@ -25,8 +41,8 @@ def extract_data(log_file): data_by_size = {} dicts_by_param = {'N': data_by_nodes, 'id': data_by_id, 'sz': data_by_size} - with open(log_file, 'r') as f: - all_lines = f.readlines() + all_lines = get_lines(log_file) + for l in all_lines: regex_match = re.match(RESULT_REGEX, l) if regex_match is None: @@ -72,3 +88,4 @@ def main(): main() + diff --git a/our_srcs/consts.py b/our_srcs/consts.py index 08fc4f02..b703804a 100644 --- a/our_srcs/consts.py +++ b/our_srcs/consts.py @@ -5,10 +5,13 @@ LOG_PATH = LOG_DIR + '/honeybadger_test_{}_{}_{}_{}_{}_{}.log' LOGGER_NAME = 'honeybadger_test_logger' NUM_OF_NODE_OPTIONS = [4, 6, 8, 10] +#NUM_OF_NODE_OPTIONS = [6] NUM_OF_IDENTICAL_INPUTS_OPTIONS = [0, 2, 4, 6, 8, 10] +#NUM_OF_IDENTICAL_INPUTS_OPTIONS = [4] -NUM_OF_INPUTS_IN_ITERATION = 6 -INPUT_SIZES = [2, 2**2, 2**4, 2**8, 2**16, 2**20, 2**24] -SET_NUM_OF_NODES = 10 +NUM_OF_INPUTS_IN_ITERATION = 4 +#INPUT_SIZES = [2, 2**2, 2**4, 2**8, 2**16, 2**20, 2**24] +INPUT_SIZES = [2**4, 2**8, 2**16, 2**24] +SET_NUM_OF_NODES = 8 SET_NUM_OF_IDENTICAL_INPUTS = 6 SET_INPUT_SIZE = 2**16 diff --git a/test/my_test.py b/test/throughput_latency_test.py similarity index 87% rename from test/my_test.py rename to test/throughput_latency_test.py index a0ef04dc..e12c4a34 100755 --- a/test/my_test.py +++ b/test/throughput_latency_test.py @@ -19,6 +19,7 @@ logger = getLogger(LOGGER_NAME) ### Test asynchronous common subset +#@mark.parametrize("HB", HONEYBADGERS) @mark.parametrize("HB", HONEYBADGERS) @mark.parametrize("N", NUM_OF_NODE_OPTIONS) @mark.parametrize("identical_inputs", NUM_OF_IDENTICAL_INPUTS_OPTIONS) @@ -43,7 +44,7 @@ def test_honeybadger_full(HB, N, identical_inputs, input_sizes): else: txs_to_submit[node_index].append(f' Date: Mon, 14 Feb 2022 16:00:42 +0000 Subject: [PATCH 29/29] All tests pass and are analyzed! --- our_srcs/analyze_results.py | 17 +++++++++-------- our_srcs/consts.py | 5 +---- test/throughput_latency_test.py | 2 -- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/our_srcs/analyze_results.py b/our_srcs/analyze_results.py index 12d5cb2a..416c5475 100644 --- a/our_srcs/analyze_results.py +++ b/our_srcs/analyze_results.py @@ -17,7 +17,7 @@ def get_result_line(line): def update_dict_by_param(full_dict, result_dict, param): if result_dict['HB'] not in full_dict: full_dict[result_dict['HB']] = {} - full_dict[result_dict['HB']][result_dict[param]] = result_dict['total_time'] + full_dict[result_dict['HB']][result_dict[param]] = {'total_time': result_dict['total_time'], 'bytes_sent': result_dict['bytes_sent']} def get_lines(log_file): all_lines = [] @@ -58,7 +58,6 @@ def extract_data(log_file): for q in PARAMS: if p != q and rd[q] != SET_PARAMS[q]: should_add_point = False - print(f"{p}:{rd[p]}, {q}:{rd[q]}") break if should_add_point: @@ -67,24 +66,26 @@ def extract_data(log_file): return dicts_by_param -def analyze_data(pds): +def analyze_data(pds, objective): ax = {} - fig, (ax['N'], ax['id'], ax['sz']) = plt.subplots(1, 3, sharey=True) + fig, (ax['N'], ax['id'], ax['sz']) = plt.subplots(1, 3, sharey=False) for p in pds.keys(): for hb in pds[p]: - print(f"Plotting by honeybadger {hb}") - ax[p].plot(pds[p][hb].keys(), pds[p][hb].values()) + x_vals, y_vals = (list(t) for t in zip(*sorted(zip(pds[p][hb].keys(), [results[objective] for results in pds[p][hb].values()])))) + ax[p].plot(x_vals, y_vals) ax[p].set_title(p) ax[p].legend(pds[p].keys()) ax['sz'].set_xscale('log') + if objective == 'bytes_sent': + ax['sz'].set_yscale('log') plt.show() def main(): assert len(sys.argv) == 2, "Give log file parameter please" pbs = extract_data(sys.argv[1]) - analyze_data(pbs) - + analyze_data(pbs, 'total_time') + analyze_data(pbs, 'bytes_sent') main() diff --git a/our_srcs/consts.py b/our_srcs/consts.py index b703804a..92870814 100644 --- a/our_srcs/consts.py +++ b/our_srcs/consts.py @@ -5,13 +5,10 @@ LOG_PATH = LOG_DIR + '/honeybadger_test_{}_{}_{}_{}_{}_{}.log' LOGGER_NAME = 'honeybadger_test_logger' NUM_OF_NODE_OPTIONS = [4, 6, 8, 10] -#NUM_OF_NODE_OPTIONS = [6] NUM_OF_IDENTICAL_INPUTS_OPTIONS = [0, 2, 4, 6, 8, 10] -#NUM_OF_IDENTICAL_INPUTS_OPTIONS = [4] NUM_OF_INPUTS_IN_ITERATION = 4 -#INPUT_SIZES = [2, 2**2, 2**4, 2**8, 2**16, 2**20, 2**24] -INPUT_SIZES = [2**4, 2**8, 2**16, 2**24] +INPUT_SIZES = [2, 2**2, 2**4, 2**8, 2**16, 2**20, 2**24] SET_NUM_OF_NODES = 8 SET_NUM_OF_IDENTICAL_INPUTS = 6 SET_INPUT_SIZE = 2**16 diff --git a/test/throughput_latency_test.py b/test/throughput_latency_test.py index e12c4a34..1c1d5185 100755 --- a/test/throughput_latency_test.py +++ b/test/throughput_latency_test.py @@ -18,8 +18,6 @@ setup_logging() logger = getLogger(LOGGER_NAME) -### Test asynchronous common subset -#@mark.parametrize("HB", HONEYBADGERS) @mark.parametrize("HB", HONEYBADGERS) @mark.parametrize("N", NUM_OF_NODE_OPTIONS) @mark.parametrize("identical_inputs", NUM_OF_IDENTICAL_INPUTS_OPTIONS)