def testHasViewChangeQuorum(): """ Checks method _hasViewChangeQuorum of SimpleSelector """ ledgerInfo = ( # ledger id, ledger length, merkle root (0, 10, '7toTJZHzaxQ7cGZv18MR4PMBfuUecdEQ1JRqJVeJBvmd'), (1, 5, 'Hs9n4M3CrmrkWGVviGq48vSbMpCrk6WgSBZ7sZAWbJy3')) selector = PrimarySelector(FakeNode()) assert not selector._hasViewChangeQuorum # Accessing _view_change_done directly to avoid influence of methods selector._view_change_done = {} def declare(replica_name): selector._view_change_done[replica_name] = ('Node2', ledgerInfo) declare('Node1') declare('Node3') declare('Node4') # Three nodes is enough for quorum, but there is no Node2:0 which is # expected to be next primary, so no quorum should be achieved assert selector._hasViewChangeQuorum assert not selector.has_view_change_from_primary declare('Node2') assert selector.has_view_change_from_primary
def test_has_view_change_quorum_number_propagate_primary(): """ Checks method _hasViewChangeQuorum of SimpleSelector It must have f+1 ViewChangeDone in the case of PrimaryPropagation Check it for a case of view change (view_change_in_progress = True, propagate_primary = True) """ ledgerInfo = ( # ledger id, ledger length, merkle root (0, 10, '7toTJZHzaxQ7cGZv18MR4PMBfuUecdEQ1JRqJVeJBvmd'), (1, 5, 'Hs9n4M3CrmrkWGVviGq48vSbMpCrk6WgSBZ7sZAWbJy3')) node = FakeNode() node.view_change_in_progress = True node.propagate_primary = True selector = PrimarySelector(node) assert not selector._hasViewChangeQuorum # Accessing _view_change_done directly to avoid influence of methods selector._view_change_done = {} def declare(replica_name): selector._view_change_done[replica_name] = ('Node2', ledgerInfo) # Declare the Primary first and check that f+1 are required declare('Node2') assert selector.has_view_change_from_primary assert not selector._hasViewChangeQuorum declare('Node1') assert selector._hasViewChangeQuorum assert selector.has_view_change_from_primary
def test_get_msgs_for_lagged_nodes(tmpdir): ledgerInfo = ( # ledger id, ledger length, merkle root (0, 10, '7toTJZHzaxQ7cGZv18MR4PMBfuUecdEQ1JRqJVeJBvmd'), (1, 5, 'Hs9n4M3CrmrkWGVviGq48vSbMpCrk6WgSBZ7sZAWbJy3'), ) messages = [ (ViewChangeDone( viewNo=0, name='Node2', ledgerInfo=ledgerInfo), 'Node1'), (ViewChangeDone( viewNo=0, name='Node3', ledgerInfo=ledgerInfo), 'Node2')] node = FakeNode(str(tmpdir)) selector = PrimarySelector(node) for message in messages: selector._processViewChangeDoneMessage(*message) messages_for_lagged = selector.get_msgs_for_lagged_nodes() assert {m for m in messages_for_lagged} == { m[0] for m in messages if m[1] == node.name}
def __init__(self, tmpdir, config=None): self.basedirpath = tmpdir self.name = 'Node1' self.f = 1 self.replicas = dict() self.requests = [] self.rank = None self.allNodeNames = [self.name, 'Node2', 'Node3', 'Node4'] self.nodeReg = { name: HA("127.0.0.1", 0) for name in self.allNodeNames } self.totalNodes = len(self.allNodeNames) self.mode = Mode.starting self.config = config or getConfigOnce() self.replicas = { 0: Replica(node=self, instId=0, isMaster=True, config=self.config), 1: Replica(node=self, instId=1, isMaster=False, config=self.config), 2: Replica(node=self, instId=2, isMaster=False, config=self.config), } self._found = False self.ledgerManager = LedgerManager(self, ownedByNode=True) ledger0 = FakeLedger(0, 10) ledger1 = FakeLedger(1, 5) self.ledgerManager.addLedger(0, ledger0) self.ledgerManager.addLedger(1, ledger1) self.quorums = Quorums(self.totalNodes) self.view_changer = ViewChanger(self) self.elector = PrimarySelector(self) self.metrics = NullMetricsCollector()
def __init__(self, tmpdir): self.basedirpath = tmpdir self.name = 'Node1' self.f = 1 self.replicas = [] self.rank = None self.allNodeNames = [self.name, 'Node2', 'Node3', 'Node4'] self.nodeReg = {name: HA("127.0.0.1", 0) for name in self.allNodeNames} self.totalNodes = len(self.allNodeNames) self.mode = Mode.starting self.replicas = [ Replica(node=self, instId=0, isMaster=True), Replica(node=self, instId=1, isMaster=False), Replica(node=self, instId=2, isMaster=False), ] self._found = False self.ledgerManager = LedgerManager(self, ownedByNode=True) ledger0 = FakeLedger(0, 10) ledger1 = FakeLedger(1, 5) self.ledgerManager.addLedger(0, ledger0) self.ledgerManager.addLedger(1, ledger1) self.quorums = Quorums(self.totalNodes) self.config = getConfig() # TODO do we need fake object here? self.view_changer = ViewChanger(self) self.elector = PrimarySelector(self)
def test_has_view_change_quorum_must_contain_primary(tmpdir): """ Checks method _hasViewChangeQuorum of SimpleSelector It must have n-f ViewChangeDone including a VCD from the next Primary Check it for a case of view change (view_change_in_progress = True, propagate_primary = False) """ ledgerInfo = ( # ledger id, ledger length, merkle root (0, 10, '7toTJZHzaxQ7cGZv18MR4PMBfuUecdEQ1JRqJVeJBvmd'), (1, 5, 'Hs9n4M3CrmrkWGVviGq48vSbMpCrk6WgSBZ7sZAWbJy3') ) node = FakeNode(str(tmpdir)) node.view_change_in_progress = True node.propagate_primary = False selector = PrimarySelector(node) assert not selector._hasViewChangeQuorum # Accessing _view_change_done directly to avoid influence of methods selector._view_change_done = {} def declare(replica_name): selector._view_change_done[replica_name] = ('Node2', ledgerInfo) declare('Node1') assert not selector._hasViewChangeQuorum assert not selector.has_view_change_from_primary declare('Node3') assert not selector._hasViewChangeQuorum assert not selector.has_view_change_from_primary declare('Node4') assert selector._hasViewChangeQuorum assert not selector.has_view_change_from_primary # Three nodes is enough for quorum, but there is no Node2:0 which is # expected to be next primary, so no quorum should be achieved declare('Node2') assert selector._hasViewChangeQuorum assert selector.has_view_change_from_primary
def test_send_view_change_done_message(): node = FakeNode() selector = PrimarySelector(node) instance_id = 0 view_no = selector.viewNo new_primary_name = selector.node.get_name_by_rank( selector._get_primary_id(view_no, instance_id)) selector._send_view_change_done_message() ledgerInfo = [ # ledger id, ledger length, merkle root (0, 10, '4F7BsTMVPKFshM1MwLf6y23cid6fL3xMpazVoF9krzUw'), (1, 5, '4K2V1kpVycZ6qSFsNdz2FtpNxnJs17eBNzf9rdCMcKoe'), ] messages = [ViewChangeDone(viewNo=0, name='Node2', ledgerInfo=ledgerInfo)] assert len(selector.outBox) == 1 print(list(selector.outBox)) print(messages) assert list(selector.outBox) == messages
def __init__(self, tmpdir, config=None): self.basedirpath = tmpdir self.name = 'Node1' self.internal_bus = InternalBus() self.db_manager = DatabaseManager() self.timer = QueueTimer() self.f = 1 self.replicas = dict() self.requests = Requests() self.rank = None self.allNodeNames = [self.name, 'Node2', 'Node3', 'Node4'] self.nodeReg = {name: HA("127.0.0.1", 0) for name in self.allNodeNames} self.nodeIds = [] self.totalNodes = len(self.allNodeNames) self.mode = Mode.starting self.config = config or getConfigOnce() self.nodeStatusDB = None self.replicas = { 0: Replica(node=self, instId=0, isMaster=True, config=self.config), 1: Replica(node=self, instId=1, isMaster=False, config=self.config), 2: Replica(node=self, instId=2, isMaster=False, config=self.config), } self._found = False self.ledgerManager = LedgerManager(self) ledger0 = FakeLedger(0, 10) ledger1 = FakeLedger(1, 5) self.ledgerManager.addLedger(0, ledger0) self.ledgerManager.addLedger(1, ledger1) self.quorums = Quorums(self.totalNodes) self.view_changer = create_view_changer(self) self.elector = PrimarySelector(self) self.metrics = NullMetricsCollector() # For catchup testing self.catchup_rounds_without_txns = 0 self.view_change_in_progress = False self.ledgerManager.last_caught_up_3PC = (0, 0) self.master_last_ordered_3PC = (0, 0) self.seqNoDB = {} # callbacks self.onBatchCreated = lambda self, *args, **kwargs: True
def testProcessViewChangeDone(): ledgerInfo = ( # ledger id, ledger length, merkle root (0, 10, '7toTJZHzaxQ7cGZv18MR4PMBfuUecdEQ1JRqJVeJBvmd'), (1, 5, 'Hs9n4M3CrmrkWGVviGq48vSbMpCrk6WgSBZ7sZAWbJy3')) msg = ViewChangeDone(viewNo=0, name='Node2', ledgerInfo=ledgerInfo) node = FakeNode() selector = PrimarySelector(node) quorum = selector.quorum for i in range(quorum): selector._processViewChangeDoneMessage(msg, 'Node2') assert selector._view_change_done assert not node.is_primary_found() selector._processViewChangeDoneMessage(msg, 'Node1') assert selector._view_change_done assert not node.is_primary_found() selector._processViewChangeDoneMessage(msg, 'Node3') assert selector._verify_primary(msg.name, msg.ledgerInfo) selector._startSelection() assert selector._view_change_done # Since the FakeNode does not have setting of mode # assert node.is_primary_found() selector.view_change_started(1) assert not selector._view_change_done