Ejemplo n.º 1
0
    def leader_complain(self):
        complained_leader_id, new_leader_id = self.get_leader_ids_for_complaint(
        )
        version = self.blockchain.block_versioner.get_version(
            self.epoch.height)
        leader_vote = Vote.get_leader_vote_class(version).new(
            signer=ChannelProperty().peer_auth,
            block_height=self.epoch.height,
            round_=self.epoch.round,
            old_leader=ExternalAddress.fromhex_address(complained_leader_id),
            new_leader=ExternalAddress.fromhex_address(new_leader_id),
            timestamp=util.get_time_stamp())
        util.logger.info(
            f"LeaderVote : old_leader({complained_leader_id}), new_leader({new_leader_id}), round({self.epoch.round})"
        )
        self.add_complain(leader_vote)

        leader_vote_serialized = leader_vote.serialize()
        leader_vote_dumped = json.dumps(leader_vote_serialized)
        request = loopchain_pb2.ComplainLeaderRequest(
            complain_vote=leader_vote_dumped, channel=self.channel_name)

        util.logger.debug(f"leader complain "
                          f"complained_leader_id({complained_leader_id}), "
                          f"new_leader_id({new_leader_id})")

        reps_hash = self.blockchain.get_next_reps_hash_by_header(
            self.blockchain.last_block.header)
        self.__channel_service.broadcast_scheduler.schedule_broadcast(
            "ComplainLeader", request, reps_hash=reps_hash)
Ejemplo n.º 2
0
 def _deserialize(cls, data: dict):
     data_deserialized = super()._deserialize(data)
     data_deserialized["block_height"] = int(data["blockHeight"], 16)
     data_deserialized["round"] = int(data["round"], 16)
     data_deserialized["old_leader"] = ExternalAddress.fromhex_address(
         data["oldLeader"])
     data_deserialized["new_leader"] = ExternalAddress.fromhex_address(
         data["newLeader"])
     return data_deserialized
Ejemplo n.º 3
0
    def test_invoke(self):
        guard = self.guard
        value = f"hx{os.urandom(20).hex()}"
        address = ExternalAddress.fromhex_address(value)
        tx = MockTx(address)

        for i in range(self.guard_threshold):
            blocked: bool = guard.invoke(tx)
            assert not blocked
            assert not guard._is_update_denylist
            assert len(guard._denylist) == 0

        # The case when count > guard_threshold
        blocked: bool = guard.invoke(tx)
        assert blocked
        assert guard._is_update_denylist
        assert value in guard._denylist

        # Blocking is expired
        _sleep(self.block_duration + 1)
        guard._check_denylist()
        assert value not in guard._denylist

        blocked: bool = guard.invoke(tx)
        assert not blocked
        assert guard._is_update_denylist
        assert len(guard._denylist) == 0

        # Sleep for reset test
        _sleep(self.reset_time + 1)

        # Case when cur_time - expire_time > reset_time and count > 0 and not blocked
        blocked: bool = guard.invoke(tx)
        assert not blocked
        assert value not in guard._statistics
Ejemplo n.º 4
0
    async def init(self, **kwargs):
        """Initialize Channel Service

        :param kwargs: takes (peer_id, peer_port, peer_target, rest_target)
        within parameters
        :return: None
        """
        loggers.get_preset().peer_id = kwargs.get('peer_id')
        loggers.get_preset().update_logger()

        ChannelProperty().peer_port = kwargs.get('peer_port')
        ChannelProperty().peer_target = kwargs.get('peer_target')
        ChannelProperty().rest_target = kwargs.get('rest_target')
        ChannelProperty().peer_id = kwargs.get('peer_id')
        ChannelProperty().peer_address = ExternalAddress.fromhex_address(
            ChannelProperty().peer_id)
        ChannelProperty().node_type = conf.NodeType.CitizenNode
        ChannelProperty().rs_target = None

        self.__peer_manager = PeerManager()
        await self.__init_peer_auth()
        self.__init_broadcast_scheduler()
        self.__init_block_manager()

        await self.__init_score_container()
        await self.__inner_service.connect(conf.AMQP_CONNECTION_ATTEMPTS,
                                           conf.AMQP_RETRY_DELAY,
                                           exclusive=True)
        await self.__init_sub_services()
Ejemplo n.º 5
0
    def test_valid_timestamp(self):
        """Test for timestamp buffer in block verifier"""
        def block_maker(timestamp: int, height: int = 0, prev_hash=None):
            """Make dummy block"""
            tx_versioner = TransactionVersioner()

            dummy_receipts = {}
            block_builder = BlockBuilder.new("0.1a", tx_versioner)

            for i in range(1000):
                tx_builder = TransactionBuilder.new("0x3", None, tx_versioner)
                tx_builder.signer = test_signer
                tx_builder.to_address = ExternalAddress.new()
                tx_builder.step_limit = random.randint(0, 10000)
                tx_builder.value = random.randint(0, 10000)
                tx_builder.nid = 2
                tx = tx_builder.build()

                tx_serializer = TransactionSerializer.new(tx.version, tx.type(), tx_versioner)
                block_builder.transactions[tx.hash] = tx
                dummy_receipts[tx.hash.hex()] = {
                    "dummy_receipt": "dummy",
                    "tx_dumped": tx_serializer.to_full_data(tx)
                }

            block_builder.signer = test_signer
            block_builder.prev_hash = prev_hash
            block_builder.height = height
            block_builder.state_hash = Hash32(bytes(Hash32.size))
            block_builder.receipts = dummy_receipts
            block_builder.reps = [ExternalAddress.fromhex_address(test_signer.address)]
            block_builder.peer_id = ExternalAddress.fromhex(test_signer.address)
            block_builder.next_leader = ExternalAddress.fromhex(test_signer.address)
            block_builder.fixed_timestamp = timestamp

            b = block_builder.build()
            assert b.header.timestamp == timestamp

            return b

        test_signer = Signer.from_prikey(os.urandom(32))

        first_block = block_maker(height=0, timestamp=utils.get_time_stamp())
        second_block = block_maker(height=1, timestamp=utils.get_time_stamp() + 5, prev_hash=first_block.header.hash)
        third_block_from_far_future = block_maker(height=2, prev_hash=second_block.header.hash,
                                                  timestamp=utils.get_time_stamp() + conf.TIMESTAMP_BUFFER_IN_VERIFIER + 5_000_000)

        block_verifier = BlockVerifier.new("0.1a", TransactionVersioner())
        leader = first_block.header.peer_id
        reps = [ExternalAddress.fromhex_address(test_signer.address)]
        print("*---Normal time range")
        block_verifier.verify(block=second_block, prev_block=first_block,
                              blockchain=None, generator=leader, reps=reps)

        print("*---Abnormal time range")
        with self.assertRaises(Exception):
            block_verifier.verify(block=third_block_from_far_future, prev_block=second_block,
                                  blockchain=None, generator=leader, reps=reps)
Ejemplo n.º 6
0
    def build_peer_id(self):
        if self.peer_id is not None:
            return self.peer_id

        if self.signer is None:
            raise RuntimeError

        self.peer_id = ExternalAddress.fromhex_address(self.signer.address)
        return self.peer_id
Ejemplo n.º 7
0
    def build_from_address(self):
        if self.from_address:
            return self.from_address

        if self.signer is None:
            raise RuntimeError(f"'signer' or 'from_address' is required.")

        self.from_address = ExternalAddress.fromhex_address(self.signer.address)
        return self.from_address
Ejemplo n.º 8
0
    def reps_hash(self) -> Hash32:
        """return reps root hash.

        :return:
        """
        block_prover = BlockProver(
            (ExternalAddress.fromhex_address(peer.peer_id).extend()
             for peer in self._peer_list_data.peer_list.values()),
            BlockProverType.Rep)
        return block_prover.get_proof_root()
Ejemplo n.º 9
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
Ejemplo n.º 10
0
    def _init_properties(**kwargs):
        """Initialize properties

        :param kwargs: takes (peer_id, peer_port, peer_target, rest_target)
        within parameters
        :return: None
        """
        loggers.get_preset().peer_id = kwargs.get('peer_id')
        loggers.get_preset().update_logger()

        ChannelProperty().peer_port = kwargs.get('peer_port')
        ChannelProperty().peer_target = kwargs.get('peer_target')
        ChannelProperty().rest_target = kwargs.get('rest_target')
        ChannelProperty().peer_id = kwargs.get('peer_id')
        ChannelProperty().peer_address = ExternalAddress.fromhex_address(ChannelProperty().peer_id)
        ChannelProperty().node_type = conf.NodeType.CitizenNode
        ChannelProperty().rs_target = None
Ejemplo n.º 11
0
    def new_votes(self):
        self.reps_hash = self.__blockchain.last_block.header.revealed_next_reps_hash or \
                         ChannelProperty().crep_root_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

        version = self.__blockchain.block_versioner.get_version(self.height)
        leader_votes = Votes.get_leader_votes_class(version)(
            self.reps, ratio, self.height, self.round,
            ExternalAddress.fromhex_address(self.leader_id))
        self.complain_votes[self.round] = leader_votes
Ejemplo n.º 12
0
    def load():
        peers = PeerLoader._load_peers_from_db()
        if peers:
            utils.logger.info("Reps data loaded from DB")
        elif os.path.exists(conf.CHANNEL_MANAGE_DATA_PATH):
            utils.logger.info(
                f"Try to load reps data from {conf.CHANNEL_MANAGE_DATA_PATH}")
            peers = PeerLoader._load_peers_from_file()
        else:
            utils.logger.info("Try to load reps data from other reps")
            peers = PeerLoader._load_peers_from_rest_call()

        block_prover = BlockProver(
            (ExternalAddress.fromhex_address(peer['id']).extend()
             for peer in peers), BlockProverType.Rep)
        peer_root_hash = block_prover.get_proof_root()

        return peer_root_hash, peers
Ejemplo n.º 13
0
    def test_transaction_v2_unsigned(self):
        signer = Signer.new()

        tb = TransactionBuilder.new("0x2", None, self.tx_versioner)
        tb.fee = 1000000
        tb.value = 100000
        tb.from_address = ExternalAddress.fromhex_address(signer.address)
        tb.to_address = ExternalAddress(os.urandom(20))
        tb.nonce = random.randint(0, 100000)
        tx = tb.build(is_signing=False)

        tv = TransactionVerifier.new("0x2", tx.type(), self.tx_versioner)
        self.assertRaises(TransactionInvalidSignatureError, lambda: tv.verify(tx))
        self.assertRaises(TransactionInvalidSignatureError, lambda: tv.pre_verify(tx))

        tb.signer = signer
        signed_tx = tb.sign_transaction(tx)
        tv.verify(signed_tx)
        tv.pre_verify(signed_tx)
Ejemplo n.º 14
0
        def block_maker(timestamp: int, height: int = 0, prev_hash=None):
            """Make dummy block"""
            tx_versioner = TransactionVersioner()

            dummy_receipts = {}
            block_builder = BlockBuilder.new("0.1a", tx_versioner)

            for i in range(1000):
                tx_builder = TransactionBuilder.new("0x3", None, tx_versioner)
                tx_builder.signer = test_signer
                tx_builder.to_address = ExternalAddress.new()
                tx_builder.step_limit = random.randint(0, 10000)
                tx_builder.value = random.randint(0, 10000)
                tx_builder.nid = 2
                tx = tx_builder.build()

                tx_serializer = TransactionSerializer.new(
                    tx.version, tx.type(), tx_versioner)
                block_builder.transactions[tx.hash] = tx
                dummy_receipts[tx.hash.hex()] = {
                    "dummy_receipt": "dummy",
                    "tx_dumped": tx_serializer.to_full_data(tx)
                }

            block_builder.signer = test_signer
            block_builder.prev_hash = prev_hash
            block_builder.height = height
            block_builder.state_hash = Hash32(bytes(Hash32.size))
            block_builder.receipts = dummy_receipts
            block_builder.reps = [
                ExternalAddress.fromhex_address(test_signer.address)
            ]
            block_builder.peer_id = ExternalAddress.fromhex(
                test_signer.address)
            block_builder.next_leader = ExternalAddress.fromhex(
                test_signer.address)
            block_builder.fixed_timestamp = timestamp

            b = block_builder.build()
            assert b.header.timestamp == timestamp

            return b
Ejemplo n.º 15
0
    def __build_candidate_block(self, block_builder: 'BlockBuilder'):
        last_block = self._blockchain.last_block
        block_builder.height = last_block.header.height + 1
        block_builder.prev_hash = last_block.header.hash
        block_builder.signer = ChannelProperty().peer_auth
        block_builder.confirm_prev_block = (block_builder.version == '0.1a')

        if block_builder.version == '0.1a' or (not block_builder.next_leader
                                               and not block_builder.reps):
            block_builder.next_leader = ExternalAddress.fromhex_address(
                self._block_manager.epoch.leader_id)
            block_builder.reps = self._block_manager.epoch.reps

        try:
            if block_builder.next_reps is None:
                # to build temporary block (version >= 0.4)
                block_builder.next_reps = []
        except AttributeError as e:
            util.logger.info(f"block_version = {block_builder.version} : {e}")

        return block_builder.build()
Ejemplo n.º 16
0
    def test_transaction_v3_unsigned(self):
        signer = Signer.new()

        tb = TransactionBuilder.new("0x3", None, self.tx_versioner)
        tb.step_limit = 1000000
        tb.value = 100000
        tb.from_address = ExternalAddress.fromhex_address(signer.address)
        tb.to_address = ExternalAddress(os.urandom(20))
        tb.nid = 3
        tb.nonce = random.randint(0, 100000)
        tb.data = "test"
        tb.data_type = "message"
        tx = tb.build(False)

        tv = TransactionVerifier.new("0x3", tx.type(), self.tx_versioner)
        self.assertRaises(TransactionInvalidSignatureError, lambda: tv.verify(tx))
        self.assertRaises(TransactionInvalidSignatureError, lambda: tv.pre_verify(tx, nid=3))

        tb.signer = signer
        signed_tx = tb.sign_transaction(tx)
        tv.verify(signed_tx)
        tv.pre_verify(signed_tx, nid=3)
Ejemplo n.º 17
0
def pytest_configure():
    signers = [Signer.from_prikey(os.urandom(32)) for _ in range(100)]
    reps = [ExternalAddress.fromhex_address(signer.address) for signer in signers]

    pytest.SIGNERS: List[Signer] = signers
    pytest.REPS: List[ExternalAddress] = reps
Ejemplo n.º 18
0
    def test_block_v0_4(self):
        block_version = "0.4"
        test_signer = Signer.from_prikey(os.urandom(32))
        tx_versioner = TransactionVersioner()

        dummy_receipts = {}
        block_builder = BlockBuilder.new(block_version, tx_versioner)
        for i in range(5):
            tx_builder = TransactionBuilder.new("0x3", None, tx_versioner)
            tx_builder.signer = test_signer
            tx_builder.to_address = ExternalAddress.new()
            tx_builder.step_limit = random.randint(0, 10000)
            tx_builder.value = random.randint(0, 10000)
            tx_builder.nid = 2
            tx = tx_builder.build()

            tx_serializer = TransactionSerializer.new(tx.version, tx.type(),
                                                      tx_versioner)
            block_builder.transactions[tx.hash] = tx
            dummy_receipts[tx.hash.hex()] = {
                "dummy_receipt": "dummy",
                "tx_dumped": tx_serializer.to_full_data(tx)
            }

        next_leader = ExternalAddress.fromhex(
            "hx00112233445566778899aabbccddeeff00112233")

        block_builder.signer = test_signer
        block_builder.height = 0
        block_builder.prev_hash = Hash32(bytes(Hash32.size))
        block_builder.state_hash = Hash32(bytes(Hash32.size))
        block_builder.receipts = dummy_receipts
        block_builder.reps = [
            ExternalAddress.fromhex_address(test_signer.address)
        ]
        block_builder.next_leader = next_leader
        block_builder.next_reps = []

        vote = BlockVote.new(test_signer, utils.get_time_stamp(),
                             block_builder.height - 1, 0,
                             block_builder.prev_hash)
        votes = BlockVotes(block_builder.reps, conf.VOTING_RATIO,
                           block_builder.height - 1, 0,
                           block_builder.prev_hash)
        votes.add_vote(vote)
        block_builder.prev_votes = votes.votes

        block = block_builder.build()
        block_verifier = BlockVerifier.new(block_version, tx_versioner)

        block_verifier.invoke_func = lambda b, prev_b: (block, dummy_receipts)
        reps_getter = lambda _: block_builder.reps
        generator = ExternalAddress.fromhex_address(test_signer.address)
        block_verifier.verify(block,
                              None,
                              None,
                              generator=generator,
                              reps_getter=reps_getter)

        block_serializer = BlockSerializer.new(block_version, tx_versioner)
        block_serialized = block_serializer.serialize(block)
        logging.info(json.dumps(block_serialized, indent=4))
        block_deserialized = block_serializer.deserialize(block_serialized)
        logging.info(
            json.dumps(block_serializer.serialize(block_deserialized),
                       indent=4))

        assert block.header == block_deserialized.header
        assert block.body == block_deserialized.body

        tx_hashes = list(block.body.transactions)
        tx_index = random.randrange(0, len(tx_hashes))

        block_prover = BlockProver.new(block.header.version, tx_hashes,
                                       BlockProverType.Transaction)
        tx_proof = block_prover.get_proof(tx_index)
        assert block_prover.prove(tx_hashes[tx_index],
                                  block.header.transactions_hash, tx_proof)

        block_prover = BlockProver.new(block.header.version,
                                       block_builder.receipts,
                                       BlockProverType.Receipt)
        receipt_proof = block_prover.get_proof(tx_index)
        receipts_hash = block_prover.to_hash32(
            block_builder.receipts[tx_index])
        assert block_prover.prove(receipts_hash, block.header.receipts_hash,
                                  receipt_proof)
Ejemplo n.º 19
0
 def setUpClass(cls):
     cls.signers = [Signer.from_prikey(os.urandom(32)) for _ in range(100)]
     cls.reps = [
         ExternalAddress.fromhex_address(signer.address)
         for signer in cls.signers
     ]
Ejemplo n.º 20
0
 def _deserialize(cls, data: dict):
     return {
         "rep": ExternalAddress.fromhex_address(data["rep"]),
         "timestamp": int(data["timestamp"], 16),
         "signature": Signature.from_base64str(data["signature"])
     }