def __init__(self, config): super().__init__() self._config = config self._worker_registry_list = None self._worker_instance = JRPCWorkerRegistryImpl(self._config) self._work_order_instance = JRPCWorkOrderImpl(self._config) self._work_order_receipt = JRPCWorkOrderReceiptImpl(self._config)
def _create_work_order_receipt_instance(blockchain_type, config): # create work order receipt instance for direct/proxy model if blockchain_type == 'ethereum': # TODO need to implement return None else: return JRPCWorkOrderReceiptImpl(config)
def __init__(self, config_file=None, config=None): """ Parameters: config_file Optional configuration file path as a string config Optional dictionary loaded from config_file Either one of config_file or config needs to be passed. If both are passed, then config takes precedence. """ if (config is not None): self.__config = config else: if not isfile(config_file): raise FileNotFoundError("File not found at path: {0}".format( realpath(config_file))) try: with open(config_file) as fd: self.__config = toml.load(fd) except IOError as e: """ Catch the exception related to toml file format except for the File does not exist exception. """ if e.errno != errno.ENOENT: raise Exception('Could not open config file: %s' % e) self.__blockchain_type = self.__config['blockchain']['type'] if self.__blockchain_type.lower() == "ethereum": self.__worker_registry_list = EthereumWorkerRegistryListImpl( self.__config) else: self.__worker_registry_list = None self.__worker_registry = JRPCWorkerRegistryImpl(self.__config) self.__work_order = JRPCWorkOrderImpl(self.__config) self.__work_order_receipts = JRPCWorkOrderReceiptImpl(self.__config)
def _create_work_order_receipt_instance(blockchain_type, config): # create work order receipt instance for direct/proxy model if constants.proxy_mode and blockchain_type == 'fabric': return None elif constants.proxy_mode and blockchain_type == 'ethereum': # TODO need to implement return None else: logger.info("Direct SDK code path\n") return JRPCWorkOrderReceiptImpl(config)
def Main(args=None): options = _parse_command_line(args) config = _parse_config_file(options.config) if config is None: logger.error("\n Error in parsing config file: {}\n".format( options.config)) sys.exit(-1) # mode should be one of listing or registry (default) mode = options.mode # Http JSON RPC listener uri uri = options.uri if uri: config["tcf"]["json_rpc_uri"] = uri # Address of smart contract address = options.address if address: if mode == "listing": config["ethereum"]["direct_registry_contract_address"] = \ address elif mode == "registry": logger.error( "\n Only Worker registry listing address is supported." + "Worker registry address is unsupported \n") sys.exit(-1) # worker id worker_id = options.worker_id worker_id_hex = options.worker_id_hex worker_id = worker_id_hex if not worker_id \ else hex_utils.get_worker_id_from_name(worker_id) # work load id of worker workload_id = options.workload_id if not workload_id: logger.error("\nWorkload id is mandatory\n") sys.exit(-1) # work order input data in_data = options.in_data # Option to send input data in plain text in_data_plain_text = options.in_data_plain # show receipt in output show_receipt = options.receipt # show decrypted result in output show_decrypted_output = options.decrypted_output # requester signature for work order requests requester_signature = options.requester_signature # setup logging config["Logging"] = {"LogFile": "__screen__", "LogLevel": "INFO"} plogger.setup_loggers(config.get("Logging", {})) sys.stdout = plogger.stream_to_logger(logging.getLogger("STDOUT"), logging.DEBUG) sys.stderr = plogger.stream_to_logger(logging.getLogger("STDERR"), logging.WARN) logger.info("******* Hyperledger Avalon Generic client *******") if mode == "registry" and address: logger.error("\n Worker registry contract address is unsupported \n") sys.exit(-1) # Retrieve JSON RPC uri from registry list if not uri and mode == "listing": uri = _retrieve_uri_from_registry_list(config) if uri is None: logger.error("\n Unable to get http JSON RPC uri \n") sys.exit(-1) # Prepare worker # JRPC request id. Choose any integer value jrpc_req_id = 31 worker_registry = JRPCWorkerRegistryImpl(config) if not worker_id: # Get first worker from worker registry worker_id = _lookup_first_worker(worker_registry, jrpc_req_id) if worker_id is None: logger.error("\n Unable to get worker \n") sys.exit(-1) # Retrieve worker details jrpc_req_id += 1 worker_retrieve_result = worker_registry.worker_retrieve( worker_id, jrpc_req_id) logger.info("\n Worker retrieve response: {}\n".format( json.dumps(worker_retrieve_result, indent=4))) if "error" in worker_retrieve_result: logger.error("Unable to retrieve worker details\n") sys.exit(1) # Create session key and iv to sign work order request session_key = crypto_utility.generate_key() session_iv = crypto_utility.generate_iv() # Initializing Worker Object worker_obj = worker_details.SGXWorkerDetails() worker_obj.load_worker(worker_retrieve_result['result']['details']) # Do worker verification _do_worker_verification(worker_obj) logger.info( "**********Worker details Updated with Worker ID" + "*********\n%s\n", worker_id) # Create work order if in_data_plain_text: # As per TC spec, if encryptedDataEncryptionKey is "-" then # input data is not encrypted encrypted_data_encryption_key = "-" else: # As per TC spec, if encryptedDataEncryptionKey is not # provided then set it to None which means # use default session key to encrypt input data encrypted_data_encryption_key = None wo_params = _create_work_order_params(worker_id, workload_id, in_data, worker_obj.encryption_key, session_key, session_iv, encrypted_data_encryption_key) client_private_key = crypto_utility.generate_signing_keys() if requester_signature: # Add requester signature and requester verifying_key if wo_params.add_requester_signature(client_private_key) is False: logger.info("Work order request signing failed") exit(1) # Submit work order logger.info("Work order submit request : %s, \n \n ", wo_params.to_jrpc_string(jrpc_req_id)) work_order = JRPCWorkOrderImpl(config) jrpc_req_id += 1 response = work_order.work_order_submit(wo_params.get_work_order_id(), wo_params.get_worker_id(), wo_params.get_requester_id(), wo_params.to_string(), id=jrpc_req_id) logger.info("Work order submit response : {}\n ".format( json.dumps(response, indent=4))) if "error" in response and response["error"]["code"] != \ WorkOrderStatus.PENDING: sys.exit(1) # Create receipt wo_receipt = JRPCWorkOrderReceiptImpl(config) if show_receipt: jrpc_req_id += 1 _create_work_order_receipt(wo_receipt, wo_params, client_private_key, jrpc_req_id) # Retrieve work order result jrpc_req_id += 1 res = work_order.work_order_get_result(wo_params.get_work_order_id(), jrpc_req_id) logger.info("Work order get result : {}\n ".format( json.dumps(res, indent=4))) # Check if result field is present in work order response if "result" in res: # Verify work order response signature if _verify_wo_res_signature(res['result'], worker_obj.verification_key, wo_params.get_requester_nonce()) is False: logger.error("Work order response signature verification Failed") sys.exit(1) # Decrypt work order response if show_decrypted_output: decrypted_res = crypto_utility.decrypted_response( res['result'], session_key, session_iv) logger.info("\nDecrypted response:\n {}".format(decrypted_res)) else: logger.error("\n Work order get result failed {}\n".format(res)) sys.exit(1) if show_receipt: # Retrieve receipt jrpc_req_id += 1 retrieve_wo_receipt \ = _retrieve_work_order_receipt(wo_receipt, wo_params, jrpc_req_id) # Verify receipt signature if "result" in retrieve_wo_receipt: if _verify_receipt_signature(retrieve_wo_receipt) is False: logger.error("Receipt signature verification Failed") sys.exit(1) else: logger.info("Work Order receipt retrieve failed") sys.exit(1)
class DirectModelGenericClient(BaseGenericClient): """ Generic client class to test end to end flow for direct model. """ def __init__(self, config): super().__init__() self._config = config self._worker_registry_list = None self._worker_instance = JRPCWorkerRegistryImpl(self._config) self._work_order_instance = JRPCWorkOrderImpl(self._config) self._work_order_receipt = JRPCWorkOrderReceiptImpl(self._config) def _get_random_jrpc_id(self): return random.randint(1, 10000) def retrieve_uri_from_registry_list(self, config): # Retrieve Http JSON RPC listener uri from registry # in case of direct model logging.info("\n Retrieve Http JSON RPC listener uri from registry \n") # Get block chain type blockchain_type = config['blockchain']['type'] if blockchain_type == "Ethereum": self._worker_registry_list = EthereumWorkerRegistryListImpl(config) else: logging.error("\n Worker registry list is currently " "supported only for " "ethereum block chain \n") return None # Lookup returns tuple, first element is number of registries and # second is element is lookup tag and # third is list of organization ids. registry_count, lookup_tag, registry_list = \ self._worker_registry_list.registry_lookup() logging.info("\n Registry lookup response: registry count: {} " "lookup tag: {} registry list: {}\n".format( registry_count, lookup_tag, registry_list)) if (registry_count == 0): logging.error("No registries found") return None # Retrieve the fist registry details. registry_retrieve_result = \ self._worker_registry_list.registry_retrieve( registry_list[0]) logging.info("\n Registry retrieve response: {}\n".format( registry_retrieve_result)) return registry_retrieve_result[0] def get_worker_details(self, worker_id): """ Fetch worker details for given worker id """ worker_retrieve_res = self._worker_instance.worker_retrieve( worker_id, self._get_random_jrpc_id()) if worker_retrieve_res and "result" in worker_retrieve_res: status = worker_retrieve_res["result"]["status"] details = worker_retrieve_res["result"]["details"] logging.info("\n Worker retrieve: worker status {} " "details : {}\n".format(status, json.dumps(details, indent=4))) if status == WorkerStatus.ACTIVE.value: # Initializing Worker Object worker_obj = SGXWorkerDetails() worker_obj.load_worker(details) return worker_obj else: logging.error("Worker is not active") else: return None def get_work_order_result(self, work_order_id): """ Retrieve work order result for given work order id """ work_order_res = self._work_order_instance.work_order_get_result( work_order_id, self._get_random_jrpc_id()) logging.info("Work order get result {}".format( json.dumps(work_order_res, indent=4))) if work_order_res and "result" in work_order_res: return True, work_order_res return False, work_order_res def submit_work_order(self, wo_params): """ Submit work order request """ jrpc_id = self._get_random_jrpc_id() wo_request = wo_params.to_string() logging.info("\n Work order sumbit request {}\n".format( wo_params.to_jrpc_string(jrpc_id))) wo_submit_res = self._work_order_instance.work_order_submit( wo_params.get_work_order_id(), wo_params.get_worker_id(), wo_params.get_requester_id(), wo_request, jrpc_id) logging.info("Work order submit response : {}\n ".format( json.dumps(wo_submit_res, indent=4))) if wo_submit_res: # in asynchronous mode if "error" in wo_submit_res: if wo_submit_res["error"]["code"] == WorkOrderStatus.PENDING: return True, wo_submit_res # in synchronous mode elif "result" in wo_submit_res: return True, wo_submit_res else: return False, wo_submit_res else: return False, wo_submit_res def create_work_order_receipt(self, wo_params, client_private_key): # Create a work order receipt object using # WorkOrderReceiptRequest class. # This function will send a WorkOrderReceiptCreate # JSON RPC request. wo_request = json.loads( wo_params.to_jrpc_string(self._get_random_jrpc_id())) wo_receipt_request_obj = WorkOrderReceiptRequest() wo_create_receipt = wo_receipt_request_obj.create_receipt( wo_request, ReceiptCreateStatus.PENDING.value, client_private_key) logging.info("Work order create receipt request : {} \n \n ".format( json.dumps(wo_create_receipt, indent=4))) # Submit work order create receipt jrpc request wo_receipt_resp = self._work_order_receipt.work_order_receipt_create( wo_create_receipt["workOrderId"], wo_create_receipt["workerServiceId"], wo_create_receipt["workerId"], wo_create_receipt["requesterId"], wo_create_receipt["receiptCreateStatus"], wo_create_receipt["workOrderRequestHash"], wo_create_receipt["requesterGeneratedNonce"], wo_create_receipt["requesterSignature"], wo_create_receipt["signatureRules"], wo_create_receipt["receiptVerificationKey"], self._get_random_jrpc_id()) logging.info("Work order create receipt response : {} \n \n ".format( wo_receipt_resp)) def retrieve_work_order_receipt(self, wo_id): """ Retrieve work order receipt for given work order id """ receipt_res = self._work_order_receipt.work_order_receipt_retrieve( wo_id, id=self._get_random_jrpc_id()) logging.info("\n Retrieve receipt response:\n {}".format( json.dumps(receipt_res, indent=4))) # Retrieve last update to receipt by passing 0xFFFFFFFF receipt_update_retrieve = \ self._work_order_receipt.work_order_receipt_update_retrieve( wo_id, None, 1 << 32, id=self._get_random_jrpc_id()) logging.info("\n Last update to receipt receipt is:\n {}".format( json.dumps(receipt_update_retrieve, indent=4))) return receipt_update_retrieve def verify_receipt_signature(self, receipt_update_retrieve): """ Verify work order receipt signature """ signer = worker_signing.WorkerSign() status = signer.verify_update_receipt_signature( receipt_update_retrieve['result']) if status == SignatureStatus.PASSED: logging.info( "Work order receipt retrieve signature verification " + "successful") else: logging.error( "Work order receipt retrieve signature verification failed!!") return False return True