Пример #1
0
    def add_vote(self, vote: BlockVote):
        with self.__blocks_lock:
            if vote.block_hash != Hash32.empty() and vote.block_hash not in self.blocks:
                # util.logger.debug(f"-------------block_hash({block_hash}) self.blocks({self.blocks})")
                self.blocks[vote.block_hash] = CandidateBlock.from_hash(vote.block_hash, vote.block_height)

        if vote.block_hash != Hash32.empty():
            self.blocks[vote.block_hash].add_vote(vote)
        else:
            for block in self.blocks.values():
                if block.height == vote.block_height:
                    block.add_vote(vote)
Пример #2
0
    def add_vote(self, vote: 'BlockVote'):
        with self.__blocks_lock:
            if vote.block_hash != Hash32.empty(
            ) and vote.block_hash not in self.blocks:
                self.blocks[vote.block_hash] = CandidateBlock.from_hash(
                    vote.block_hash, vote.block_height)

        if vote.block_hash != Hash32.empty():
            self.blocks[vote.block_hash].add_vote(vote)
        else:
            for block in self.blocks.values():
                if block.height == vote.block_height:
                    block.add_vote(vote)
Пример #3
0
    def to_hash32(self, value: Union[Hash32, bytes, bytearray, int, bool,
                                     dict]):
        if value is None:
            return Hash32.empty()
        elif isinstance(value, Hash32):
            return value
        elif isinstance(value, (bytes, bytearray)) and len(value) == 32:
            return Hash32(value)

        if isinstance(value, bool):
            value = b'\x01' if value else b'\x00'
        elif isinstance(value, int):
            if value < 0:
                raise RuntimeError(f"value : {value} is negative.")
            value = value.to_bytes((value.bit_length() + 7) // 8, "big")
        elif isinstance(value, dict):
            if self.type == BlockProverType.Receipt:
                value = dict(value)
                value.pop("failure", None)
                value.pop("blockHash", None)

            hash_generator = self.get_hash_generator()
            value = hash_generator.generate_salted_origin(value)
            value = value.encode()
        return Hash32(hashlib.sha3_256(value).digest())
Пример #4
0
    def is_unrecorded(self) -> bool:
        """Return is unrecorded block

        :return: bool
        """
        return (self.next_leader == ExternalAddress.empty() and
                self.reps_hash == self.next_reps_hash == Hash32.empty())
Пример #5
0
    def vote_unconfirmed_block(self, block: Block, round_: int, is_validated):
        util.logger.debug(
            f"vote_unconfirmed_block() ({block.header.height}/{block.header.hash}/{is_validated})"
        )
        vote = Vote.get_block_vote_class(block.header.version).new(
            signer=ChannelProperty().peer_auth,
            block_height=block.header.height,
            round_=round_,
            block_hash=block.header.hash if is_validated else Hash32.empty(),
            timestamp=util.get_time_stamp())
        self.candidate_blocks.add_vote(vote)

        vote_serialized = vote.serialize()
        vote_dumped = json.dumps(vote_serialized)
        block_vote = loopchain_pb2.BlockVote(vote=vote_dumped,
                                             channel=ChannelProperty().name)

        target_reps_hash = block.header.reps_hash
        if not target_reps_hash:
            target_reps_hash = self.__channel_service.peer_manager.crep_root_hash

        self.__channel_service.broadcast_scheduler.schedule_broadcast(
            "VoteUnconfirmedBlock", block_vote, reps_hash=target_reps_hash)

        return vote
Пример #6
0
    def _build_transactions_hash(self):
        if not self.transactions:
            return Hash32.empty()

        block_prover = BlockProver(self.transactions.keys(),
                                   BlockProverType.Transaction)
        return block_prover.get_proof_root()
Пример #7
0
    def test_block_invalid_vote(self):
        ratio = 0.67
        block_hash = Hash32(os.urandom(Hash32.size))
        block_votes = BlockVotes(self.reps, ratio, 0, 0, block_hash)

        invalid_block_vote = BlockVote.new(self.signers[0], 0, 0, 1,
                                           block_hash)
        self.assertRaises(RuntimeError, block_votes.add_vote,
                          invalid_block_vote)

        invalid_block_vote = BlockVote.new(self.signers[0], 0, 1, 0,
                                           block_hash)
        self.assertRaises(RuntimeError, block_votes.add_vote,
                          invalid_block_vote)

        invalid_block_vote = BlockVote.new(self.signers[0], 0, 0, 0,
                                           Hash32(os.urandom(32)))
        self.assertRaises(RuntimeError, block_votes.add_vote,
                          invalid_block_vote)

        invalid_block_vote = BlockVote(rep=self.reps[0],
                                       timestamp=0,
                                       signature=Signature(os.urandom(65)),
                                       block_height=0,
                                       round_=0,
                                       block_hash=block_hash)
        self.assertRaises(RuntimeError, block_votes.add_vote,
                          invalid_block_vote)

        block_vote = BlockVote.new(self.signers[0], 0, 0, 0, block_hash)
        block_votes.add_vote(block_vote)
        duplicate_block_vote = BlockVote.new(self.signers[0], 0, 0, 0,
                                             Hash32.empty())
        self.assertRaises(votes.VoteDuplicateError, block_votes.add_vote,
                          duplicate_block_vote)
Пример #8
0
    def get_result(self):
        true_vote_count = sum(1 for vote in self.votes
                              if vote and vote.block_hash == self.block_hash)
        if true_vote_count >= self.quorum:
            return True

        false_vote_count = sum(1 for vote in self.votes
                               if vote and vote.block_hash == Hash32.empty())
        if false_vote_count >= len(self.reps) - self.quorum + 1:
            return False
        return None
Пример #9
0
    def verify_vote(self, vote: BlockVote):
        if vote.block_height != self.block_height:
            raise RuntimeError(f"Vote block_height not match. {vote.block_height} != {self.block_height}\n"
                               f"{vote}")

        if vote.round_ != self.round:
            raise RuntimeError(f"Vote round not match. {vote.round_} != {self.round}\n"
                               f"{vote}")

        if vote.block_hash != self.block_hash and vote.block_hash != Hash32.empty():
            raise RuntimeError(f"Vote block_hash not match. {vote.block_hash} != {self.block_hash}\n"
                               f"{vote}")
        super().verify_vote(vote)
Пример #10
0
    def test_block_votes_completed(self):
        ratio = 0.67
        block_hash = Hash32(os.urandom(Hash32.size))
        block_votes = BlockVotes(self.reps, ratio, 0, 0, block_hash)

        signers = list(enumerate(self.signers))
        for i, signer in signers[:25]:
            block_vote = BlockVote.new(signer, 0, 0, 0, block_hash)
            block_votes.add_vote(block_vote)

        logging.info(block_votes)
        self.assertEqual(block_votes.is_completed(), False)
        self.assertEqual(block_votes.get_result(), None)

        for i, signer in signers[25:50]:
            block_vote = BlockVote.new(signer, 0, 0, 0, block_hash)
            block_votes.add_vote(block_vote)

        logging.info(block_votes)
        self.assertEqual(block_votes.is_completed(), False)
        self.assertEqual(block_votes.get_result(), None)

        for i, signer in signers[50:75]:
            block_vote = BlockVote.new(signer, 0, 0, 0, Hash32.empty())
            block_votes.add_vote(block_vote)

        logging.info(block_votes)
        self.assertEqual(block_votes.is_completed(), False)
        self.assertEqual(block_votes.get_result(), None)

        for i, signer in signers[75:90]:
            block_vote = BlockVote.new(signer, 0, 0, 0, Hash32.empty())
            block_votes.add_vote(block_vote)

        logging.info(block_votes)
        self.assertEqual(block_votes.is_completed(), True)
        self.assertEqual(block_votes.get_result(), False)
Пример #11
0
    def test_block_votes_false(self):
        ratio = 0.67
        block_hash = Hash32(os.urandom(Hash32.size))
        block_votes = BlockVotes(self.reps, ratio, 0, 0, block_hash)

        for i, signer in enumerate(self.signers):
            if i % 4 == 0:
                block_vote = BlockVote.new(signer, 0, 0, 0, block_hash)
            else:
                block_vote = BlockVote.new(signer, 0, 0, 0, Hash32.empty())
            block_votes.add_vote(block_vote)

        logging.info(block_votes)
        self.assertEqual(block_votes.quorum, len(self.reps) * ratio)
        self.assertEqual(block_votes.get_result(), False)
Пример #12
0
    def test_block_votes_fail(self):
        ratio = 0.67
        block_hash = Hash32(os.urandom(Hash32.size))
        block_votes = BlockVotes(self.reps, ratio, 0, 0, block_hash)

        for i, signer in enumerate(self.signers):
            if i == 33:
                break

            block_vote = BlockVote.new(signer, 0, 0, 0, Hash32.empty())
            block_votes.add_vote(block_vote)

        self.assertEqual(block_votes.quorum, len(self.reps) * ratio)

        logging.info(block_votes)
        self.assertEqual(block_votes.is_completed(), False)
        self.assertEqual(block_votes.get_result(), None)

        block_vote = BlockVote.new(self.signers[99], 0, 0, 0, Hash32.empty())
        block_votes.add_vote(block_vote)

        logging.info(block_votes)
        self.assertEqual(block_votes.is_completed(), True)
        self.assertEqual(block_votes.get_result(), False)
Пример #13
0
    def _build_receipts_hash(self):
        if not self.receipts:
            return Hash32.empty()

        block_prover = BlockProver(self.receipts, BlockProverType.Receipt)
        return block_prover.get_proof_root()
Пример #14
0
 def empty(cls, rep: ExternalAddress, block_height: int):
     return cls(rep, 0, Signature.empty(), block_height, Hash32.empty())
Пример #15
0
 def result(self) -> bool:
     return self.block_hash != Hash32.empty()
Пример #16
0
    def prep_changed(self) -> bool:
        """Return reason for prep changed

        :return: False means there is no change.
        """
        return self.next_reps_hash != Hash32.empty()
Пример #17
0
 def complained(self):
     return self.leader_votes_hash != Hash32.empty()
Пример #18
0
 def get_proof_root(self) -> Hash32:
     if not self._merkle_tree.is_ready:
         self.make_tree()
     root = self._merkle_tree.get_merkle_root()
     return Hash32(root) if root is not None else Hash32.empty()
Пример #19
0
    def test_prep_is_not_changed_if_next_reps_hash_is_empty(self, header_factory):
        header = header_factory(next_leader=ExternalAddress(os.urandom(ExternalAddress.size)),
                                reps_hash=Hash32(os.urandom(Hash32.size)),
                                next_reps_hash=Hash32.empty())

        assert not header.prep_changed