示例#1
0
    def _receive_transaction_data_from_others(self, dat):
        """Receive transaction data from other core_nodes and check its validity

        Args:
            dat (dict): received message
        """
        #print("_receive_transaction_data_from_others:")
        if KeyType.transaction_data not in dat or KeyType.transaction_id not in dat or KeyType.nonce not in dat:
            return
        if dat[KeyType.nonce] not in self.requesting_list:
            return
        asset_files = dict()
        if KeyType.all_asset_files in dat:
            asset_files = dat[KeyType.all_asset_files]
        txobj, fmt_type = bbclib.deserialize(dat[KeyType.transaction_data])
        if txobj.transaction_data is None:
            return

        txobj_is_valid, valid_assets, invalid_assets = bbclib.validate_transaction_object(
            txobj, asset_files)
        if txobj_is_valid:
            self.stats.update_stats_increment("transaction", "success_repair",
                                              1)
            for idx in range(len(self.data_handler.db_adaptors)):
                self.data_handler.restore_transaction_data(
                    db_num=idx,
                    transaction_id=txobj.transaction_id,
                    txobj=txobj)
            add_info = {
                "repaired_by": dat[KeyType.source_node_id].hex(),
                "repaired_at": int(time.time())
            }
            self.requesting_list[dat[KeyType.nonce]].update(add_info)
            self._output_log(self.requesting_list[dat[KeyType.nonce]])
            del self.requesting_list[dat[KeyType.nonce]]
示例#2
0
    def _send_asset_file(self, dat):
        """Send the asset file if having valid one

        Args:
            dat (dict): received message
        """
        #print("_send_asset_file::")
        asset_group_id = dat[KeyType.asset_group_id]
        asset_id = dat[KeyType.asset_id]
        asset_file = self.data_handler.get_in_storage(asset_group_id, asset_id)
        if asset_file is None:
            return
        result_txobj, result_asset_files = self.data_handler.search_transaction(
            asset_group_id=asset_group_id, asset_id=asset_id)
        txobj = next(iter(result_txobj.values()))
        txobj_is_valid, valid_assets, invalid_assets = bbclib.validate_transaction_object(
            txobj, result_asset_files)

        if (asset_group_id, asset_id) in valid_assets:
            dat[KeyType.command] = RepairManager.RESPONSE_ASSET_FILE
            dat[KeyType.asset_group_id] = asset_group_id
            dat[KeyType.asset_id] = asset_id
            dat[KeyType.asset_file] = asset_file
            dat[KeyType.destination_node_id] = dat[KeyType.source_node_id]
            self.network.send_message_in_network(None,
                                                 domain_id=self.domain_id,
                                                 msg=dat)
示例#3
0
 def _get_transaction_data_for_verification(self, domain_id,
                                            transaction_id):
     """Get transaction object and verify it"""
     txobjs, asts = self.networking.domains[domain_id][
         'data'].search_transaction(transaction_id=transaction_id)
     if transaction_id not in txobjs:
         return None
     txobj = txobjs[transaction_id]
     if txobj.WITH_WIRE:
         self.logger.info(
             "To use cross_reference the transaction object must not be in bson/msgpack format"
         )
         return None
     txobj_is_valid, valid_assets, invalid_assets = bbclib.validate_transaction_object(
         txobj, asts)
     if not txobj_is_valid:
         msg = {
             KeyType.command:
             repair_manager.RepairManager.REQUEST_REPAIR_TRANSACTION,
             KeyType.transaction_id: transaction_id,
         }
         self.networking.domains[domain_id]['repair'].put_message(msg)
         return None
     txobj.digest()
     cross_ref_dat = txobj.cross_ref.pack()
     sigdata = txobj.signatures[0].pack()
     return txobj.transaction_base_digest, cross_ref_dat, sigdata
示例#4
0
    def _receive_asset_file_from_others(self, dat):
        """Receive asset file from other core_nodes and check its validity

        Args:
            dat (dict): received message
        """
        #print("_receive_asset_file_from_others:")
        if KeyType.nonce not in dat or dat[KeyType.nonce] not in self.requesting_list:
            return
        if KeyType.asset_group_id not in dat or KeyType.asset_id not in dat or KeyType.asset_file not in dat:
            return

        asset_group_id = dat[KeyType.asset_group_id]
        asset_id = dat[KeyType.asset_id]
        asset_file = dat[KeyType.asset_file]
        if asset_file is None:
            return
        asset_files = {asset_id: asset_file}
        result_txobj, result_asset_files = self.data_handler.search_transaction(asset_group_id=asset_group_id,
                                                                                asset_id=asset_id)
        txobj = next(iter(result_txobj.values()))

        txobj_is_valid, valid_assets, invalid_assets = bbclib.validate_transaction_object(txobj, asset_files)

        if (asset_group_id, asset_id) in valid_assets:

            self.data_handler.store_in_storage(asset_group_id, asset_id, asset_file, do_overwrite=True)
            add_info = {
                "repaired_by": dat[KeyType.source_node_id].hex(),
                "repaired_at": int(time.time())
            }
            self.requesting_list[dat[KeyType.nonce]].update(add_info)
            self._output_log(self.requesting_list[dat[KeyType.nonce]])
            del self.requesting_list[dat[KeyType.nonce]]
示例#5
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
示例#6
0
 def _send_transaction_data(self, dat):
     """Send transaction data if having valid one"""
     #print("_send_transaction_data::")
     transaction_id = dat[KeyType.transaction_id]
     for idx in range(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[transaction_id])
         if txobj_is_valid:
             dat[KeyType.command] = RepairManager.RESPONSE_TRANSACTION_DATA
             dat[KeyType.transaction_data] = result_txobj[transaction_id].transaction_data
             dat[KeyType.destination_node_id] = dat[KeyType.source_node_id]
             self.network.send_message_in_network(None, domain_id=self.domain_id, msg=dat)
             return
示例#7
0
 def _get_transaction_data_for_verification(self, domain_id, transaction_id):
     """Get transaction object and verify it"""
     txobjs, asts = self.networking.domains[domain_id]['data'].search_transaction(transaction_id=transaction_id)
     if transaction_id not in txobjs:
         return None
     txobj = txobjs[transaction_id]
     txobj_is_valid, valid_assets, invalid_assets = bbclib.validate_transaction_object(txobj, asts)
     if not txobj_is_valid:
         msg = {
             KeyType.command: repair_manager.RepairManager.REQUEST_REPAIR_TRANSACTION,
             KeyType.transaction_id: transaction_id,
         }
         self.networking.domains[domain_id]['repair'].put_message(msg)
         return None
     txobj.digest()
     if txobj.format_type in [bbclib.BBcFormat.FORMAT_BSON, bbclib.BBcFormat.FORMAT_BSON_COMPRESS_BZ2]:
         cross_ref_dat = bson.dumps(txobj.cross_ref.serialize())
         sigdata = bson.dumps(txobj.signatures[0].serialize())
     else:
         cross_ref_dat = txobj.cross_ref.serialize()
         sigdata = txobj.signatures[0].serialize()
     return txobj.transaction_base_digest, cross_ref_dat, sigdata, txobj.format_type