Example #1
0
    def _repair_asset_file(self, asset_group_id, asset_id, need_check=True):
        """Repair forged asset_file by getting legitimate one from other nodes

        Args:
            asset_group_id (bytes): asset_group_id of the asset
            asset_id (bytes): asset_id of the asset
            need_check (bool): If True, check the digest of the asset file
        """
        #print("_repair_asset_file:")
        if self.data_handler.use_external_storage:
            return
        if need_check:
            asset_file = self.data_handler.get_in_storage(asset_group_id, asset_id)
            if asset_file is not None and asset_id == hashlib.sha256(asset_file).digest():
                return

        random_nonce = bbclib.get_random_value(4)
        while random_nonce in self.requesting_list:
            random_nonce = bbclib.get_random_value(4)
        self.requesting_list[random_nonce] = {
            "asset_group_id": asset_group_id.hex(),
            "asset_id": asset_id.hex(),
            "request_at": int(time.time())
        }
        msg = {
            KeyType.domain_id: self.domain_id,
            KeyType.infra_msg_type: InfraMessageCategory.CATEGORY_DATA,
            KeyType.infra_command: DataHandler.REPAIR_TRANSACTION_DATA,
            KeyType.command: RepairManager.REQUEST_TO_SEND_ASSET_FILE,
            KeyType.asset_group_id: asset_group_id,
            KeyType.asset_id: asset_id,
            KeyType.nonce: random_nonce,
        }
        self.network.broadcast_message_in_network(domain_id=self.domain_id,
                                                  payload_type=PayloadType.Type_any, msg=msg)
Example #2
0
    def _repair_transaction_data(self, transaction_id):
        """Repair forged transaction_data or asset_file by getting legitimate one from other nodes

        Args:
            transaction_id (bytes): target transaction_id
        """
        #print("_repair_transaction_data:")
        self.stats.update_stats_increment("transaction", "repair_request", 1)
        forged_asset_files = set()
        if len(self.data_handler.db_adaptors) > 1:
            valid_txobj = None
            db_nums_with_invalid_data = list()
            for idx in range(1, len(self.data_handler.db_adaptors)):
                result_txobj, result_asset_files = self.data_handler.search_transaction(transaction_id=transaction_id, db_num=idx)
                txobj_is_valid, valid_assets, invalid_assets = bbclib.validate_transaction_object(result_txobj[0],
                                                                                                  result_asset_files)
                if txobj_is_valid and valid_txobj is None:
                    valid_txobj = result_txobj[0]
                if not txobj_is_valid:
                    db_nums_with_invalid_data.append(idx)
                if len(invalid_assets) > 0:
                    for ent in invalid_assets:
                        forged_asset_files.add(ent)
            if valid_txobj is None:
                self.stats.update_stats_increment("transaction", "fail_to_repair_in_local", 1)
                self.logger.fatal("Failed to repair transaction locally (transaction_id=%s in domain=%s)" %
                                  (transaction_id.hex(), self.domain_id.hex()))
            else:
                for i in db_nums_with_invalid_data:
                    self.data_handler.restore_transaction_data(db_num=i, transaction_id=transaction_id, txobj=valid_txobj)
                self.stats.update_stats_increment("transaction", "success_repair", 1)
            self._output_log({"transaction_id": transaction_id.hex(), "request_at": int(time.time()),
                             "repaired_by": "locally", "repaired_at": int(time.time())})

        if len(forged_asset_files) > 0:
            for asgid, ast in forged_asset_files:
                self._repair_asset_file(asset_group_id=asgid, asset_id=ast, need_check=False)

        if self.data_handler.replication_strategy == DataHandler.REPLICATION_EXT:
            return

        random_nonce = bbclib.get_random_value(4)
        while random_nonce in self.requesting_list:
            random_nonce = bbclib.get_random_value(4)
        self.requesting_list[random_nonce] = {
            "transaction_id": transaction_id.hex(),
            "request_at": int(time.time())
        }
        msg = {
            KeyType.domain_id: self.domain_id,
            KeyType.infra_msg_type: InfraMessageCategory.CATEGORY_DATA,
            KeyType.infra_command: DataHandler.REPAIR_TRANSACTION_DATA,
            KeyType.command: RepairManager.REQUEST_TO_SEND_TRANSACTION_DATA,
            KeyType.transaction_id: transaction_id,
            KeyType.nonce: random_nonce,
        }
        self.network.broadcast_message_in_network(domain_id=self.domain_id,
                                                  payload_type=PayloadType.Type_any, msg=msg)
        return
Example #3
0
    def get_forwarding_list(self):
        """Get forwarding_list of the domain in the core node

        Returns:
            bytes: query_id
        """
        dat = self._make_message_structure(MsgType.REQUEST_GET_FORWARDING_LIST)
        admin_info = {KeyType.random: bbclib.get_random_value(32)}
        self.include_admin_info(dat, admin_info, self.node_keypair)
        return self._send_msg(dat)
Example #4
0
    def get_stats(self):
        """Get statistics of bbc_core

        Returns:
            bytes: query_id
        """
        dat = self._make_message_structure(MsgType.REQUEST_GET_STATS)
        admin_info = {KeyType.random: bbclib.get_random_value(32)}
        self.include_admin_info(dat, admin_info, self.node_keypair)
        return self._send_msg(dat)
Example #5
0
    def get_domain_list(self):
        """Get domain_id list in bbc_core

        Returns:
            bytes: query_id
        """
        dat = self._make_message_structure(MsgType.REQUEST_GET_DOMAINLIST)
        admin_info = {KeyType.random: bbclib.get_random_value(32)}
        self.include_admin_info(dat, admin_info, self.node_keypair)
        return self._send_msg(dat)
Example #6
0
    def get_user_list(self):
        """Get user_ids in the domain that are connecting to the core node

        Returns:
            bytes: query_id
        """
        dat = self._make_message_structure(MsgType.REQUEST_GET_USERS)
        admin_info = {KeyType.random: bbclib.get_random_value(32)}
        self.include_admin_info(dat, admin_info, self.node_keypair)
        return self._send_msg(dat)
Example #7
0
    def get_notification_list(self):
        """Get notification_list of the core node

        Returns:
            bytes: query_id
        """
        dat = self._make_message_structure(
            MsgType.REQUEST_GET_NOTIFICATION_LIST)
        admin_info = {KeyType.random: bbclib.get_random_value(32)}
        self.include_admin_info(dat, admin_info, self.node_keypair)
        return self._send_msg(dat)
Example #8
0
    def notify_domain_key_update(self):
        """Notify update of bbc_core

        This method should be used by a system administrator.

        Returns:
            bytes: query_id
        """
        dat = self._make_message_structure(MsgType.NOTIFY_DOMAIN_KEY_UPDATE)
        admin_info = {KeyType.random: bbclib.get_random_value(32)}
        self.include_admin_info(dat, admin_info, self.node_keypair)
        return self._send_msg(dat)
Example #9
0
    def get_bbc_config(self):
        """Get config file of bbc_core

        This method should be used by a system administrator.

        Returns:
            bytes: query_id
        """
        dat = self._make_message_structure(MsgType.REQUEST_GET_CONFIG)
        admin_info = {KeyType.random: bbclib.get_random_value(32)}
        self.include_admin_info(dat, admin_info, self.node_keypair)
        return self._send_msg(dat)
Example #10
0
    def get_domain_neighborlist(self, domain_id):
        """Get peer list of the domain from the core node

        This method should be used by a system administrator.

        Args:
            domain_id (bytes): domain_id of the neighbor list
        Returns:
            bytes: query_id
        """
        dat = self._make_message_structure(MsgType.REQUEST_GET_NEIGHBORLIST)
        dat[KeyType.domain_id] = domain_id
        admin_info = {KeyType.random: bbclib.get_random_value(32)}
        self.include_admin_info(dat, admin_info, self.node_keypair)
        return self._send_msg(dat)
Example #11
0
    def remove_domain(self, domain_id=ZEROS):
        """Leave the domain and remove it

        Args:
            domain_id (bytes): target domain_id to remove
        Returns:
            bool: True if successful
        """
        if domain_id not in self.domains:
            return False
        self.domains[domain_id]['topology'].stop_all_timers()
        self.domains[domain_id]['user'].stop_all_timers()
        self.domains[domain_id]['repair'].exit_loop()
        for nd in self.domains[domain_id]["neighbor"].nodeinfo_list.values():
            nd.key_manager.stop_all_timers()

        msg = {
            KeyType.infra_msg_type: InfraMessageCategory.CATEGORY_NETWORK,
            KeyType.domain_id: domain_id,
            KeyType.command: BBcNetwork.NOTIFY_LEAVE,
        }
        admin_info = {
            KeyType.source_node_id:
            self.domains[domain_id]["neighbor"].my_node_id,
            KeyType.nonce:
            bbclib.get_random_value(32)  # just for randomization
        }
        self.include_admin_info_into_message_if_needed(domain_id, msg,
                                                       admin_info)
        self.broadcast_message_in_network(domain_id=domain_id, msg=msg)

        if domain_id == ZEROS:
            self.domain0manager.stop_all_timers()
            for dm in self.domains.keys():
                if dm != ZEROS:
                    self.domains[dm]['neighbor'].my_info.update(domain0=False)
                    self.domains[dm]['topology'].update_refresh_timer_entry(1)
        del self.domains[domain_id]
        if self.domain0manager is not None:
            self.domain0manager.update_domain_belong_to()
        self.config.remove_domain_config(domain_id)
        self.stats.update_stats_decrement("network", "num_domains", 1)
        self.logger.info("Domain %s is removed" % (domain_id.hex()))
        return True
Example #12
0
    def manipulate_ledger_subsystem(self, enable=False, domain_id=None):
        """Start/stop ledger_subsystem on the bbc_core

        This method should be used by a system administrator.

        Args:
            enable (bool): True->start, False->stop
            domain_id (bytes): target domain_id to enable/disable ledger_subsystem
        Returns:
            bytes: query_id
        """
        dat = self._make_message_structure(MsgType.REQUEST_MANIP_LEDGER_SUBSYS)
        dat[KeyType.domain_id] = domain_id
        admin_info = {
            KeyType.ledger_subsys_manip: enable,
            KeyType.random: bbclib.get_random_value(32)
        }
        self.include_admin_info(dat, admin_info, self.node_keypair)
        return self._send_msg(dat)
Example #13
0
    def domain_close(self, domain_id=None):
        """Close domain leading to remove_domain in the core

        Args:
            domain_id (bytes): domain_id to delete
        Returns:
            bytes: query_id
        """
        if domain_id is None and self.domain_id is not None:
            domain_id = self.domain_id
        if domain_id is None:
            return None
        dat = self._make_message_structure(MsgType.REQUEST_CLOSE_DOMAIN)
        admin_info = {
            KeyType.domain_id: domain_id,
            KeyType.random: bbclib.get_random_value(32)
        }
        self.include_admin_info(dat, admin_info, self.node_keypair)
        return self._send_msg(dat)
Example #14
0
    def domain_setup(self, domain_id, config=None):
        """Set up domain with the specified network module and storage

        This method should be used by a system administrator.

        Args:
            domain_id (bytes): domain_id to create
            config (str): system config in json format
        Returns:
            bytes: query_id
        """
        dat = self._make_message_structure(MsgType.REQUEST_SETUP_DOMAIN)
        admin_info = {
            KeyType.domain_id: domain_id,
            KeyType.random: bbclib.get_random_value(32)
        }
        if config is not None:
            admin_info[KeyType.bbc_configuration] = config
        self.include_admin_info(dat, admin_info, self.node_keypair)
        return self._send_msg(dat)