示例#1
0
    def __init__(self, name: str, validators: List[str], primary_name: str,
                 timer: TimerService, bus: InternalBus, network: ExternalBus,
                 write_manager: WriteRequestManager,
                 bls_bft_replica: BlsBftReplica=None):
        self._data = ConsensusSharedData(name, validators, 0)
        self._data.primary_name = primary_name
        config = getConfig()
        stasher = StashingRouter(config.REPLICA_STASH_LIMIT, buses=[bus, network])
        self._orderer = OrderingService(data=self._data,
                                        timer=timer,
                                        bus=bus,
                                        network=network,
                                        write_manager=write_manager,
                                        bls_bft_replica=bls_bft_replica,
                                        freshness_checker=FreshnessChecker(
                                            freshness_timeout=config.STATE_FRESHNESS_UPDATE_INTERVAL),
                                        stasher=stasher)
        self._checkpointer = CheckpointService(self._data, bus, network, stasher,
                                               write_manager.database_manager)
        self._view_changer = ViewChangeService(self._data, timer, bus, network, stasher)

        # TODO: This is just for testing purposes only
        self._data.checkpoints.append(
            Checkpoint(instId=0, viewNo=0, seqNoStart=0, seqNoEnd=0,
                       digest='4F7BsTMVPKFshM1MwLf6y23cid6fL3xMpazVoF9krzUw'))
示例#2
0
def test_stashing_router_can_stash_and_sort_messages():
    calls = []

    def handler(message: SomeMessage):
        calls.append(message)
        return STASH

    def sort_key(message: SomeMessage):
        return message.int_field

    bus = InternalBus()
    router = StashingRouter(10)
    router.set_sorted_stasher(STASH, key=sort_key)
    router.subscribe(SomeMessage, handler)
    router.subscribe_to(bus)

    messages = [create_some_message() for _ in range(10)]
    for msg in messages:
        bus.send(msg)

    assert calls == messages

    calls.clear()
    router.process_all_stashed()
    assert calls == sorted(messages, key=sort_key)
示例#3
0
def test_stashing_router_can_stash_messages_with_metadata():
    stash_count = 3
    calls = []

    def handler(msg, frm):
        nonlocal stash_count
        calls.append((msg, frm))
        if stash_count > 0:
            stash_count -= 1
            return STASH

    bus = InternalBus()
    router = StashingRouter(10)
    router.subscribe(SomeMessage, handler)
    router.subscribe_to(bus)

    msg_a = create_some_message()
    msg_b = create_some_message()
    bus.send(msg_a, 'A')
    bus.send(msg_b, 'B')
    assert router.stash_size() == 2
    assert calls == [(msg_a, 'A'), (msg_b, 'B')]

    router.process_all_stashed()
    assert router.stash_size() == 1
    assert calls == [(msg_a, 'A'), (msg_b, 'B'), (msg_a, 'A'), (msg_b, 'B')]

    router.process_all_stashed()
    assert router.stash_size() == 0
    assert calls == [(msg_a, 'A'), (msg_b, 'B'), (msg_a, 'A'), (msg_b, 'B'), (msg_a, 'A')]

    router.process_all_stashed()
    assert router.stash_size() == 0
    assert calls == [(msg_a, 'A'), (msg_b, 'B'), (msg_a, 'A'), (msg_b, 'B'), (msg_a, 'A')]
示例#4
0
def test_stashing_router_can_stash_messages():
    stash_count = 3
    calls = []

    def handler(msg):
        nonlocal stash_count
        calls.append(msg)
        if stash_count > 0:
            stash_count -= 1
            return STASH, "reason"
        else:
            return None, None

    bus = InternalBus()
    router = StashingRouter(10, buses=[bus])
    router.subscribe(SomeMessage, handler)

    msg_a = create_some_message()
    msg_b = create_some_message()
    bus.send(msg_a)
    bus.send(msg_b)
    assert router.stash_size() == 2
    assert calls == [msg_a, msg_b]

    router.process_all_stashed()
    assert router.stash_size() == 1
    assert calls == [msg_a, msg_b, msg_a, msg_b]

    router.process_all_stashed()
    assert router.stash_size() == 0
    assert calls == [msg_a, msg_b, msg_a, msg_b, msg_a]

    router.process_all_stashed()
    assert router.stash_size() == 0
    assert calls == [msg_a, msg_b, msg_a, msg_b, msg_a]
示例#5
0
 def _init_checkpoint_service(self) -> CheckpointService:
     return TestCheckpointService(data=self._consensus_data,
                                  bus=self.node.internal_bus,
                                  network=self._external_bus,
                                  stasher=StashingRouter(self.config.REPLICA_STASH_LIMIT),
                                  db_manager=self.node.db_manager,
                                  old_stasher=self.stasher,
                                  metrics=self.metrics)
示例#6
0
    def __init__(self,
                 name: str,
                 validators: List[str],
                 primary_name: str,
                 timer: TimerService,
                 bus: InternalBus,
                 network: ExternalBus,
                 write_manager: WriteRequestManager,
                 bls_bft_replica: BlsBftReplica = None):
        # ToDo: Maybe ConsensusSharedData should be initiated before and passed already prepared?
        self._internal_bus = bus
        self._data = ConsensusSharedData(name, validators, 0)
        self._data.primary_name = generateName(primary_name,
                                               self._data.inst_id)
        self.config = getConfig()
        self.stasher = StashingRouter(self.config.REPLICA_STASH_LIMIT,
                                      buses=[bus, network])
        self._write_manager = write_manager
        self._primaries_selector = RoundRobinNodeRegPrimariesSelector(
            self._write_manager.node_reg_handler)
        self._orderer = OrderingService(
            data=self._data,
            timer=timer,
            bus=bus,
            network=network,
            write_manager=self._write_manager,
            bls_bft_replica=bls_bft_replica,
            freshness_checker=FreshnessChecker(
                freshness_timeout=self.config.STATE_FRESHNESS_UPDATE_INTERVAL),
            primaries_selector=self._primaries_selector,
            stasher=self.stasher)
        self._checkpointer = CheckpointService(self._data, bus, network,
                                               self.stasher,
                                               write_manager.database_manager)
        self._view_changer = ViewChangeService(self._data, timer, bus, network,
                                               self.stasher,
                                               self._primaries_selector)
        self._message_requestor = MessageReqService(self._data, bus, network)

        self._add_ledgers()

        # TODO: This is just for testing purposes only
        self._data.checkpoints.append(
            Checkpoint(instId=0,
                       viewNo=0,
                       seqNoStart=0,
                       seqNoEnd=0,
                       digest='4F7BsTMVPKFshM1MwLf6y23cid6fL3xMpazVoF9krzUw'))

        # ToDo: it should be done in Zero-view stage.
        write_manager.on_catchup_finished()
        self._data.primaries = self._view_changer._primaries_selector.select_primaries(
            self._data.view_no)

        # ToDo: ugly way to understand node_reg changing
        self._previous_node_reg = self._write_manager.node_reg_handler.committed_node_reg

        bus.subscribe(Ordered, self.emulate_ordered_processing)
示例#7
0
def test_stashing_router_correctly_handles_multiple_arguments():
    handler = Mock(return_value=(PROCESS, ""))

    bus = InternalBus()
    router = StashingRouter(10, buses=[bus])
    router.subscribe(SomeMessage, handler)

    message = create_some_message()
    bus.send(message, 'hello')
    handler.assert_called_once_with(message, 'hello')
示例#8
0
def test_stashing_router_can_process_stashed_until_first_restash():
    calls = []

    def handler(msg):
        calls.append(msg)
        if len(calls) % 2 != 0:
            return STASH, "reason"
        else:
            return None, None

    bus = InternalBus()
    router = StashingRouter(10, buses=[bus])
    router.subscribe(SomeMessage, handler)

    msg_a = create_some_message()
    msg_b = create_some_message()
    msg_c = create_some_message()
    msg_d = create_some_message()
    msg_e = create_some_message()
    bus.send(msg_a)
    bus.send(msg_b)
    bus.send(msg_c)
    bus.send(msg_d)
    bus.send(msg_e)
    assert router.stash_size() == 3
    assert calls == [msg_a, msg_b, msg_c, msg_d, msg_e]

    # Stash contains A, C, E, going to stop on C
    router.process_stashed_until_first_restash()
    assert router.stash_size() == 2
    assert calls == [msg_a, msg_b, msg_c, msg_d, msg_e, msg_a, msg_c]

    # Stash contains E, C, going to stop on C
    router.process_stashed_until_first_restash()
    assert router.stash_size() == 1
    assert calls == [
        msg_a, msg_b, msg_c, msg_d, msg_e, msg_a, msg_c, msg_e, msg_c
    ]

    # Stash contains C, not going to stop
    router.process_stashed_until_first_restash()
    assert router.stash_size() == 0
    assert calls == [
        msg_a, msg_b, msg_c, msg_d, msg_e, msg_a, msg_c, msg_e, msg_c, msg_c
    ]

    # Stash doesn't contain anything
    router.process_stashed_until_first_restash()
    assert router.stash_size() == 0
    assert calls == [
        msg_a, msg_b, msg_c, msg_d, msg_e, msg_a, msg_c, msg_e, msg_c, msg_c
    ]
示例#9
0
    def __init__(self, data: ConsensusDataProvider, timer: TimerService, bus: InternalBus, network: ExternalBus):
        self._config = getConfig()
        self._logger = getlogger()

        self._data = data
        self._timer = timer
        self._bus = bus
        self._network = network
        self._stasher = StashingRouter(self._config.VIEW_CHANGE_SERVICE_STASH_LIMIT)
        self._votes = ViewChangeVotesForView(self._data.quorums)

        self._stasher.subscribe(ViewChange, self.process_view_change_message)
        self._stasher.subscribe(ViewChangeAck, self.process_view_change_ack_message)
        self._stasher.subscribe(NewView, self.process_new_view_message)
        self._stasher.subscribe_to(network)
示例#10
0
def test_process_stashed_until_restash_doesnt_do_anything_when_there_are_no_items_in_stash(
):
    handler = Mock(return_value=(PROCESS, ""))

    bus = InternalBus()
    router = StashingRouter(10, buses=[bus])
    router.subscribe(SomeMessage, handler)

    router.process_stashed_until_first_restash()
    handler.assert_not_called()

    message = create_some_message()
    bus.send(message, 'hello')
    handler.assert_called_once_with(message, 'hello')

    router.process_stashed_until_first_restash()
    handler.assert_called_once_with(message, 'hello')
示例#11
0
def test_process_all_stashed_doesnt_do_anything_when_there_are_no_items_in_stash():
    handler = Mock(return_value=PROCESS)

    bus = InternalBus()
    router = StashingRouter(10)
    router.subscribe(SomeMessage, handler)
    router.subscribe_to(bus)

    router.process_all_stashed()
    handler.assert_not_called()

    message = create_some_message()
    bus.send(message, 'hello')
    handler.assert_called_once_with(message, 'hello')

    router.process_all_stashed()
    handler.assert_called_once_with(message, 'hello')
示例#12
0
    def __init__(self, data: ConsensusSharedData, timer: TimerService, bus: InternalBus, network: ExternalBus):
        self._config = getConfig()
        self._logger = getlogger()

        self._data = data
        self._new_view_builder = NewViewBuilder(self._data)
        self._timer = timer
        self._bus = bus
        self._network = network
        self._router = StashingRouter(self._config.VIEW_CHANGE_SERVICE_STASH_LIMIT)
        self._votes = ViewChangeVotesForView(self._data.quorums)
        self._new_view = None  # type: Optional[NewView]

        self._router.subscribe(ViewChange, self.process_view_change_message)
        self._router.subscribe(ViewChangeAck, self.process_view_change_ack_message)
        self._router.subscribe(NewView, self.process_new_view_message)
        self._router.subscribe_to(network)

        self._old_prepared = {}  # type: Dict[int, BatchID]
        self._old_preprepared = {}  # type: Dict[int, List[BatchID]]
示例#13
0
def test_stashing_router_correctly_routes_messages():
    some_handler = Mock(return_value=(PROCESS, ""))
    other_handler = Mock(return_value=(DISCARD, ""))

    bus = InternalBus()
    router = StashingRouter(10, buses=[bus])
    router.subscribe(SomeMessage, some_handler)
    router.subscribe(OtherMessage, other_handler)

    some_handler.assert_not_called()
    other_handler.assert_not_called()

    some_message = create_some_message()
    bus.send(some_message)
    some_handler.assert_called_once_with(some_message)
    other_handler.assert_not_called()

    other_message = create_other_message()
    bus.send(other_message)
    some_handler.assert_called_once_with(some_message)
    other_handler.assert_called_once_with(other_message)
示例#14
0
def test_stashing_router_can_stash_messages_with_different_reasons():
    calls = []

    def handler(message: SomeMessage):
        calls.append(message)
        if message.int_field % 2 == 0:
            return STASH + 0, "reason"
        else:
            return STASH + 1, "reason"

    bus = InternalBus()
    router = StashingRouter(10, buses=[bus])
    router.subscribe(SomeMessage, handler)

    messages = [create_some_message() for _ in range(10)]
    for msg in messages:
        bus.send(msg)
    assert router.stash_size() == len(messages)
    assert router.stash_size(STASH +
                             0) + router.stash_size(STASH +
                                                    1) == router.stash_size()

    calls.clear()
    router.process_all_stashed()
    assert router.stash_size() == len(messages)
    assert calls == sorted(messages, key=lambda m: m.int_field % 2)

    calls.clear()
    router.process_all_stashed(STASH + 0)
    assert router.stash_size() == len(messages)
    assert router.stash_size(STASH + 0) == len(calls)
    assert all(msg.int_field % 2 == 0 for msg in calls)
    assert all(msg in messages for msg in calls)

    calls.clear()
    router.process_all_stashed(STASH + 1)
    assert router.stash_size() == len(messages)
    assert router.stash_size(STASH + 1) == len(calls)
    assert all(msg.int_field % 2 != 0 for msg in calls)
    assert all(msg in messages for msg in calls)
示例#15
0
    def __init__(self,
                 name: str,
                 validators: List[str],
                 primary_name: str,
                 timer: TimerService,
                 bus: InternalBus,
                 network: ExternalBus,
                 write_manager: WriteRequestManager,
                 bls_bft_replica: BlsBftReplica = None):
        self._data = ConsensusSharedData(name, validators, 0)
        self._data.primary_name = primary_name
        config = getConfig()
        stasher = StashingRouter(config.REPLICA_STASH_LIMIT)
        self._orderer = OrderingService(data=self._data,
                                        timer=timer,
                                        bus=bus,
                                        network=network,
                                        write_manager=write_manager,
                                        bls_bft_replica=bls_bft_replica,
                                        stasher=stasher)
        self._checkpointer = CheckpointService(
            self._data,
            bus,
            network,
            stasher,
            write_manager.database_manager,
            old_stasher=FakeSomething(unstash_watermarks=lambda: None))
        self._view_changer = ViewChangeService(self._data, timer, bus, network)

        # TODO: This is just for testing purposes only
        self._data.checkpoints.append(
            Checkpoint(instId=0,
                       viewNo=0,
                       seqNoStart=0,
                       seqNoEnd=0,
                       digest='empty'))
示例#16
0
def stasher(internal_bus, external_bus):
    return StashingRouter(limit=100000, buses=[internal_bus, external_bus])
示例#17
0
 def _init_replica_stasher(self):
     return StashingRouter(self.config.REPLICA_STASH_LIMIT,
                           buses=[self.internal_bus, self._external_bus],
                           unstash_handler=self._add_to_inbox)
示例#18
0
def stasher(tconf):
    return StashingRouter(tconf.REPLICA_STASH_LIMIT)
示例#19
0
    def __init__(self, name: str, validators: List[str], primary_name: str,
                 timer: TimerService, bus: InternalBus, network: ExternalBus,
                 write_manager: WriteRequestManager,
                 bls_bft_replica: BlsBftReplica = None):
        # ToDo: Maybe ConsensusSharedData should be initiated before and passed already prepared?
        self._network = network
        self._data = ConsensusSharedData(name, validators, 0)
        self._data.primary_name = generateName(primary_name, self._data.inst_id)
        self._timer = timer
        self.config = getConfig()
        self.stasher = StashingRouter(self.config.REPLICA_STASH_LIMIT, buses=[bus, network])
        self._write_manager = write_manager
        self._primaries_selector = RoundRobinNodeRegPrimariesSelector(self._write_manager.node_reg_handler)

        self._freshness_checker = FreshnessChecker(freshness_timeout=self.config.STATE_FRESHNESS_UPDATE_INTERVAL)
        for ledger_id in [POOL_LEDGER_ID, DOMAIN_LEDGER_ID, CONFIG_LEDGER_ID]:
            self._freshness_checker.register_ledger(ledger_id=ledger_id,
                                                    initial_time=self.get_time_for_3pc_batch())

        self._orderer = OrderingService(data=self._data,
                                        timer=self._timer,
                                        bus=bus,
                                        network=network,
                                        write_manager=self._write_manager,
                                        bls_bft_replica=bls_bft_replica,
                                        freshness_checker=self._freshness_checker,
                                        get_time_for_3pc_batch=self.get_time_for_3pc_batch,
                                        stasher=self.stasher)
        self._checkpointer = CheckpointService(self._data, bus, network, self.stasher,
                                               write_manager.database_manager)
        self._view_changer = ViewChangeService(self._data, self._timer, bus, network, self.stasher, self._primaries_selector)
        self._view_change_trigger = ViewChangeTriggerService(data=self._data,
                                                             timer=self._timer,
                                                             bus=bus,
                                                             network=network,
                                                             db_manager=write_manager.database_manager,
                                                             is_master_degraded=lambda: False,
                                                             stasher=self.stasher)
        self._primary_connection_monitor = PrimaryConnectionMonitorService(data=self._data,
                                                                           timer=self._timer,
                                                                           bus=bus,
                                                                           network=network)
        self._freshness_monitor = FreshnessMonitorService(data=self._data,
                                                          timer=self._timer,
                                                          bus=bus,
                                                          network=network,
                                                          freshness_checker=self._freshness_checker,
                                                          get_time_for_3pc_batch=self.get_time_for_3pc_batch)
        self._message_requestor = MessageReqService(self._data, bus, network)

        self._add_ledgers()

        # TODO: This is just for testing purposes only
        self._data.checkpoints.append(
            Checkpoint(instId=0, viewNo=0, seqNoStart=0, seqNoEnd=0,
                       digest='4F7BsTMVPKFshM1MwLf6y23cid6fL3xMpazVoF9krzUw'))

        # ToDo: it should be done in Zero-view stage.
        write_manager.on_catchup_finished()

        # Simulate node behavior
        self._internal_bus = bus
        self._internal_bus.subscribe(NodeNeedViewChange, self.process_node_need_view_change)
        self._internal_bus.subscribe(Ordered, self.emulate_ordered_processing)

        # ToDo: ugly way to understand node_reg changing
        self._previous_node_reg = self._write_manager.node_reg_handler.committed_node_reg