Example #1
0
    def add_unconfirmed_block(self, unconfirmed_block: Block, round_: int):
        """

        :param unconfirmed_block:
        :param round_:
        :return:
        """
        self.__validate_epoch_of_unconfirmed_block(unconfirmed_block, round_)
        self.__validate_duplication_of_unconfirmed_block(unconfirmed_block)

        last_unconfirmed_block: Block = self.blockchain.last_unconfirmed_block

        # TODO After the v0.4 update, remove this version parsing.
        if parse_version(
                unconfirmed_block.header.version) >= parse_version("0.4"):
            ratio = conf.VOTING_RATIO
        else:
            ratio = conf.LEADER_COMPLAIN_RATIO

        if unconfirmed_block.header.reps_hash:
            reps = self.blockchain.find_preps_addresses_by_roothash(
                unconfirmed_block.header.reps_hash)
            leader_votes = LeaderVotes(reps, ratio,
                                       unconfirmed_block.header.height, None,
                                       unconfirmed_block.body.leader_votes)
            need_to_confirm = leader_votes.get_result() is None
        elif unconfirmed_block.body.confirm_prev_block:
            need_to_confirm = True
        else:
            need_to_confirm = False

        try:
            if need_to_confirm:
                self.blockchain.confirm_prev_block(unconfirmed_block)
                if unconfirmed_block.header.is_unrecorded:
                    self.blockchain.last_unconfirmed_block = None
                    raise UnrecordedBlock("It's an unnecessary block to vote.")
            elif last_unconfirmed_block is None:
                if self.blockchain.last_block.header.hash != unconfirmed_block.header.prev_hash:
                    raise BlockchainError(
                        f"last block is not previous block. block={unconfirmed_block}"
                    )

                self.blockchain.last_unconfirmed_block = unconfirmed_block
        except BlockchainError as e:
            util.logger.warning(
                f"BlockchainError while confirm_block({e}), retry block_height_sync"
            )
            self.__channel_service.state_machine.block_sync()
            raise InvalidUnconfirmedBlock(e)
Example #2
0
    def test_leader_invalid_vote(self):
        ratio = 0.67

        old_leader = self.reps[0]
        new_leader = self.reps[1]
        leader_votes = LeaderVotes(self.reps, ratio, 0, 0, old_leader)

        invalid_leader_vote = LeaderVote.new(self.signers[0], 0, 1, 0,
                                             old_leader, new_leader)
        self.assertRaises(RuntimeError, leader_votes.add_vote,
                          invalid_leader_vote)

        invalid_leader_vote = LeaderVote.new(self.signers[0], 0, 0, 1,
                                             old_leader, new_leader)
        self.assertRaises(RuntimeError, leader_votes.add_vote,
                          invalid_leader_vote)

        invalid_leader_vote = LeaderVote.new(self.signers[0], 0, 0, 0,
                                             new_leader, new_leader)
        self.assertRaises(RuntimeError, leader_votes.add_vote,
                          invalid_leader_vote)

        invalid_leader_vote = LeaderVote(rep=self.reps[0],
                                         timestamp=0,
                                         signature=Signature(os.urandom(65)),
                                         block_height=0,
                                         round_=0,
                                         new_leader=new_leader,
                                         old_leader=old_leader)
        self.assertRaises(RuntimeError, leader_votes.add_vote,
                          invalid_leader_vote)

        leader_vote = LeaderVote.new(self.signers[0], 0, 0, 0, old_leader,
                                     new_leader)
        leader_votes.add_vote(leader_vote)
        duplicate_leader_vote = LeaderVote.new(self.signers[0], 0, 0, 0,
                                               old_leader, self.reps[2])
        self.assertRaises(votes.VoteDuplicateError, leader_votes.add_vote,
                          duplicate_leader_vote)
Example #3
0
    def new_votes(self):
        self.reps_hash = self.__blockchain.last_block.header.revealed_next_reps_hash or \
                         ObjectManager().channel_service.peer_manager.prepared_reps_hash
        self.reps = self.__blockchain.find_preps_addresses_by_roothash(self.reps_hash)

        # TODO After the v0.4 update, remove this version parsing.
        if parse_version(self.__blockchain.last_block.header.version) >= parse_version("0.4"):
            ratio = conf.VOTING_RATIO
        else:
            ratio = conf.LEADER_COMPLAIN_RATIO

        leader_votes = LeaderVotes(self.reps,
                                   ratio,
                                   self.height,
                                   self.round,
                                   ExternalAddress.fromhex_address(self.leader_id))
        self.complain_votes[self.round] = leader_votes
Example #4
0
    def makeup_block(self,
                     complain_votes: LeaderVotes,
                     prev_votes,
                     new_term: bool = False,
                     skip_add_tx: bool = False):
        last_block = self.__blockchain.last_unconfirmed_block or self.__blockchain.last_block
        block_height = last_block.header.height + 1
        block_version = self.__blockchain.block_versioner.get_version(block_height)
        block_builder = BlockBuilder.new(block_version, self.__blockchain.tx_versioner)
        block_builder.fixed_timestamp = int(time.time() * 1_000_000)
        block_builder.prev_votes = prev_votes
        if complain_votes and complain_votes.get_result():
            block_builder.leader_votes = complain_votes.votes

        if new_term:
            block_builder.next_leader = None
            block_builder.reps = None
        elif skip_add_tx:
            utils.logger.debug(f"skip_add_tx for block height({self.height})")
        else:
            self.__add_tx_to_block(block_builder)

        return block_builder
Example #5
0
    def test_leader_votes(self):
        ratio = 0.67
        old_leader = self.reps[0]
        new_leaders = [self.reps[1], self.reps[2], self.reps[3], self.reps[4]]

        leader_votes = LeaderVotes(self.reps, ratio, 0, 0, old_leader)
        for i, (rep, signer) in enumerate(zip(self.reps, self.signers)):
            mod = i % 10
            if mod < 1:
                new_leader = new_leaders[1]
            elif mod < 2:
                new_leader = new_leaders[2]
            elif mod < 3:
                new_leader = new_leaders[3]
            else:
                new_leader = new_leaders[0]
            leader_vote = LeaderVote.new(signer, 0, 0, 0, old_leader,
                                         new_leader)
            leader_votes.add_vote(leader_vote)

        logging.info(leader_votes)
        self.assertEqual(leader_votes.is_completed(), True)
        self.assertEqual(leader_votes.get_result(), new_leaders[0])
Example #6
0
    def test_leader_votes_completed(self):
        ratio = 0.67
        old_leader = self.reps[0]
        new_leaders = [self.reps[1], self.reps[2]]

        leader_votes = LeaderVotes(self.reps, ratio, 0, 0, old_leader)
        for i, (rep,
                signer) in enumerate(zip(self.reps[:25], self.signers[:25])):
            new_leader = new_leaders[0]
            leader_vote = LeaderVote.new(signer, 0, 0, 0, old_leader,
                                         new_leader)
            leader_votes.add_vote(leader_vote)

        self.assertEqual(leader_votes.is_completed(), False)
        self.assertEqual(leader_votes.get_result(), None)

        for i, (rep,
                signer) in enumerate(zip(self.reps[25:50],
                                         self.signers[25:50])):
            new_leader = new_leaders[1]
            leader_vote = LeaderVote.new(signer, 0, 0, 0, old_leader,
                                         new_leader)
            leader_votes.add_vote(leader_vote)

        self.assertEqual(leader_votes.is_completed(), False)
        self.assertEqual(leader_votes.get_result(), None)

        for i, (rep,
                signer) in enumerate(zip(self.reps[50:75],
                                         self.signers[50:75])):
            new_leader = new_leaders[0]
            leader_vote = LeaderVote.new(signer, 0, 0, 0, old_leader,
                                         new_leader)
            leader_votes.add_vote(leader_vote)

        self.assertEqual(leader_votes.is_completed(), False)
        self.assertEqual(leader_votes.get_result(), None)

        for i, (rep,
                signer) in enumerate(zip(self.reps[75:90],
                                         self.signers[75:90])):
            new_leader = new_leaders[1]
            leader_vote = LeaderVote.new(signer, 0, 0, 0, old_leader,
                                         new_leader)
            leader_votes.add_vote(leader_vote)

        self.assertEqual(leader_votes.is_completed(), True)
        self.assertEqual(leader_votes.get_result(), None)
Example #7
0
    def test_leader_votes_completed_with_out_of_round(self):
        ratio = 0.51
        old_leader = self.reps[0]
        next_leader = self.reps[1]
        by_higher_rounder = ExternalAddress.empty()

        leader_votes = LeaderVotes(self.reps, ratio, 0, 0, old_leader)
        for i, (rep,
                signer) in enumerate(zip(self.reps[:26], self.signers[:26])):
            leader_vote = LeaderVote.new(signer, 0, 0, 0, old_leader,
                                         next_leader)
            leader_votes.add_vote(leader_vote)

        leader_votes.get_summary()
        print(f"leader_votes.is_completed(): {leader_votes.is_completed()}")
        print(f"leader_votes.get_result(): {leader_votes.get_result()}")
        self.assertEqual(leader_votes.is_completed(), False)
        self.assertEqual(leader_votes.get_result(), None)

        for i, (rep,
                signer) in enumerate(zip(self.reps[26:55],
                                         self.signers[26:55])):
            leader_vote = LeaderVote.new(signer, 0, 0, 0, old_leader,
                                         by_higher_rounder)
            leader_votes.add_vote(leader_vote)

        leader_votes.get_summary()
        print(f"leader_votes.is_completed(): {leader_votes.is_completed()}")
        print(f"leader_votes.get_result(): {leader_votes.get_result()}")
        self.assertEqual(leader_votes.is_completed(), True)
        self.assertEqual(leader_votes.get_result(), next_leader)