def test_update_prep_grades_on_sub_prep_unregistration(self):
        context = Mock()

        old_term = self.term
        old_preps = self.preps
        new_term = old_term.copy()
        new_preps = old_preps.copy(mutable=True)

        # Unregister a sub P-Rep
        index = len(old_term.main_preps)
        prep = new_preps.get_by_index(index)
        assert prep.grade == PRepGrade.SUB
        assert prep.address in old_term

        dirty_prep = prep.copy()
        dirty_prep.status = PRepStatus.UNREGISTERED
        new_preps.replace(dirty_prep)
        assert new_preps.is_dirty()

        assert old_preps.get_by_index(index) == prep
        assert new_preps.get_by_index(index) != prep

        new_term.update_invalid_elected_preps([dirty_prep])
        PRepEngine._update_prep_grades(context, new_preps, old_term, new_term)
        _check_prep_grades(new_preps, len(new_term.main_preps), len(new_term))
        assert len(new_term.main_preps) == self.main_prep_count
        assert len(new_term.sub_preps) == self.sub_prep_count - 1
        assert len(context.storage.prep.put_prep.mock_calls) == 1

        for old_snapshot, new_snapshot in zip(old_term.main_preps, new_term.main_preps):
            assert old_snapshot == new_snapshot
        for i, new_snapshot in enumerate(new_term.sub_preps):
            assert new_snapshot == old_term.sub_preps[i + 1]
    def test_update_prep_grades_on_main_prep_unregistration(self):
        context = Mock()

        old_term = self.term
        old_preps = self.preps
        new_term = old_term.copy()
        new_preps = old_preps.copy(mutable=True)

        # Unregister 0-index main P-Rep
        prep = new_preps.get_by_index(0)
        assert prep.grade == PRepGrade.MAIN
        assert prep.address in old_term

        dirty_prep = prep.copy()
        dirty_prep.status = PRepStatus.UNREGISTERED
        new_preps.replace(dirty_prep)
        assert new_preps.is_dirty()

        assert old_preps.get_by_index(0) == prep
        assert new_preps.get_by_index(0) != prep

        # Replace main P-Rep0 with sub P-Rep0
        new_term.update_invalid_elected_preps([dirty_prep])
        PRepEngine._update_prep_grades(context, new_preps, old_term, new_term)
        assert len(new_term.main_preps) == self.main_prep_count
        assert len(new_term.sub_preps) == self.sub_prep_count - 1
        assert len(context.storage.prep.put_prep.mock_calls) == 2

        _check_prep_grades(new_preps, self.main_prep_count, len(new_term))
        _check_prep_grades2(new_preps, new_term)
        assert old_term.sub_preps[0] == new_term.main_preps[0]
Exemple #3
0
    def test_update_prep_grades_on_disqualification(self):
        context = Mock()

        states = [
            PRepStatus.DISQUALIFIED, PRepStatus.DISQUALIFIED, PRepStatus.ACTIVE
        ]
        penalties = [
            PenaltyReason.PREP_DISQUALIFICATION,
            PenaltyReason.LOW_PRODUCTIVITY, PenaltyReason.BLOCK_VALIDATION
        ]

        for i in range(len(states)):
            old_term = self.term
            old_preps = self.preps
            new_term = old_term.copy()
            new_preps = old_preps.copy(mutable=True)

            # Disqualify a main P-PRep
            index = random.randint(0, len(old_term.main_preps) - 1)
            prep = new_preps.get_by_index(index)
            assert prep.grade == PRepGrade.MAIN
            assert prep.address in old_term

            dirty_prep = prep.copy()
            dirty_prep.status = states[i]
            dirty_prep.penalty = penalties[i]
            new_preps.replace(dirty_prep)
            assert new_preps.is_dirty()

            assert old_preps.get_by_index(index) == prep
            assert new_preps.get_by_index(index) != prep

            new_term.update_invalid_elected_preps([dirty_prep])
            PRepEngine._update_prep_grades(context, new_preps, old_term,
                                           new_term)
            if penalties[i] != PenaltyReason.BLOCK_VALIDATION:
                _check_prep_grades(new_preps, len(new_term.main_preps),
                                   len(new_term))
            _check_prep_grades2(new_preps, new_term)
            assert len(new_term.main_preps) == self.main_prep_count
            assert len(new_term.sub_preps) == self.sub_prep_count - 1

            j = 0
            for old_snapshot, new_snapshot in zip(old_term.main_preps,
                                                  new_term.main_preps):
                if j == index:
                    old_snapshot = old_term.sub_preps[0]

                assert old_snapshot == new_snapshot
                j += 1

            for j, new_snapshot in enumerate(new_term.sub_preps):
                assert new_snapshot == old_term.sub_preps[j + 1]

        assert len(context.storage.prep.put_prep.mock_calls) == len(states) * 2
Exemple #4
0
    def setUp(self) -> None:
        context = Mock()

        self.total_supply = icx_to_loop(800_460_000)
        self.total_delegated = 0

        main_prep_count = PREP_MAIN_PREPS
        elected_prep_count = PREP_MAIN_AND_SUB_PREPS
        sub_prep_count = elected_prep_count - main_prep_count

        new_preps: 'PRepContainer' = _create_preps(size=elected_prep_count * 2)
        term = Term(sequence=0,
                    start_block_height=100,
                    period=43120,
                    irep=icx_to_loop(50000),
                    total_supply=self.total_supply,
                    total_delegated=self.total_delegated)
        term.set_preps(new_preps, main_prep_count, elected_prep_count)
        assert len(term.main_preps) == main_prep_count
        assert len(term.sub_preps) == elected_prep_count - main_prep_count
        assert len(term) == elected_prep_count

        # Case 0: Network has just decentralized without any delegation
        PRepEngine._update_prep_grades(context,
                                       new_preps=new_preps,
                                       old_term=None,
                                       new_term=term)
        assert len(term.main_preps) == main_prep_count
        assert len(term.sub_preps) == sub_prep_count
        assert len(term) == elected_prep_count
        assert len(term) == len(context.storage.prep.put_prep.mock_calls)

        _check_prep_grades(new_preps, main_prep_count, len(term))

        self.term = term
        self.preps = new_preps
        self.main_prep_count = PREP_MAIN_PREPS
        self.elected_prep_count = PREP_MAIN_AND_SUB_PREPS
        self.sub_prep_count = PREP_MAIN_AND_SUB_PREPS - PREP_MAIN_PREPS
    def test_update_prep_grades_on_multiple_cases(self):
        context = Mock()

        old_term = self.term
        old_preps = self.preps
        new_term = old_term.copy()
        new_preps = old_preps.copy(mutable=True)

        # Main P-Reps
        cases = [
            (PRepStatus.UNREGISTERED, PenaltyReason.NONE),
            (PRepStatus.DISQUALIFIED, PenaltyReason.PREP_DISQUALIFICATION),
            (PRepStatus.DISQUALIFIED, PenaltyReason.LOW_PRODUCTIVITY),
            (PRepStatus.ACTIVE, PenaltyReason.BLOCK_VALIDATION)
        ]
        for case in cases:
            index = random.randint(0, len(new_term.main_preps) - 1)
            prep = new_preps.get_by_index(index)

            dirty_prep = prep.copy()
            dirty_prep.status = case[0]
            dirty_prep.penalty = case[1]
            new_preps.replace(dirty_prep)

            assert new_preps.is_dirty()
            assert old_preps.get_by_address(prep.address) == prep
            assert new_preps.get_by_address(prep.address) != prep
            assert new_preps.get_by_address(prep.address) == dirty_prep

            new_term.update_invalid_elected_preps([dirty_prep])

        # Sub P-Rep
        main_prep_count = len(new_term.main_preps)
        assert main_prep_count == len(old_term.main_preps)
        assert len(new_term) == len(old_term) - len(cases)

        for _ in range(3):
            index = random.randint(0, len(new_term.sub_preps) - 1)
            sub_snapshot = new_term.sub_preps[index]
            address = sub_snapshot.address

            prep = new_preps.get_by_address(address)
            assert prep.grade == PRepGrade.SUB

            dirty_prep = prep.copy()
            dirty_prep.status = PRepStatus.UNREGISTERED
            new_preps.replace(dirty_prep)
            assert new_preps.is_dirty()
            assert old_preps.get_by_address(address) == prep
            assert new_preps.get_by_address(address) != prep
            assert new_preps.get_by_address(address) == dirty_prep

            new_term.update_invalid_elected_preps([dirty_prep])

        # Candidate P-Rep
        for _ in range(3):
            index = random.randint(1, new_preps.size(active_prep_only=True) - len(new_term) - 1)

            prep = new_preps.get_by_index(len(new_term) + index)
            address = prep.address
            assert prep.grade == PRepGrade.CANDIDATE

            dirty_prep = prep.copy()
            dirty_prep.status = PRepStatus.UNREGISTERED
            new_preps.replace(dirty_prep)
            assert new_preps.is_dirty()
            assert old_preps.get_by_address(address) == prep
            assert new_preps.get_by_address(address) != prep
            assert new_preps.get_by_address(address) == dirty_prep

        PRepEngine._update_prep_grades(context, new_preps, old_term, new_term)
        _check_prep_grades2(new_preps, new_term)

        assert len(new_term.main_preps) == self.main_prep_count
        assert len(new_term.sub_preps) == self.sub_prep_count - 7
        assert new_preps.size(active_prep_only=True) == old_preps.size(active_prep_only=True) - 9
        assert new_preps.size() == old_preps.size()