def __init__(self, config): """ config is dict containing fabric specific parameters. """ self.__fabric_wrapper = None # Chain code name self.CHAIN_CODE = 'worker' if config is not None: self.__fabric_wrapper = FabricWrapper(config) else: raise Exception("config is none")
def __init__(self, config): """ Parameters: config Dict containing Fabric-specific parameters. """ self.__fabric_wrapper = None # Chain code name self.CHAIN_CODE = 'receipt' if config is not None: self.__fabric_wrapper = FabricWrapper(config) else: raise Exception("config is none")
def __init__(self, config): """ config is dict containing fabric specific parameters. """ self.__fabric_wrapper = None # Chain code name self.CHAIN_CODE = 'order' self.WORK_ORDER_SUBMITTED_EVENT_NAME = 'workOrderSubmitted' self.WORK_ORDER_COMPLETED_EVENT_NAME = 'workOrderCompleted' if config is not None: self.__fabric_wrapper = FabricWrapper(config) else: raise Exception("config is none")
def __init__(self, config): """ Parameters: config Dictionary containing Fabric-specific parameters """ self.__fabric_wrapper = None # Chain code name self.CHAIN_CODE = 'order' self.WORK_ORDER_SUBMITTED_EVENT_NAME = 'workOrderSubmitted' self.WORK_ORDER_COMPLETED_EVENT_NAME = 'workOrderCompleted' self.WAIT_TIME = 30 self.__wo_resp = '' if config is not None: self.__fabric_wrapper = FabricWrapper(config) else: raise Exception("config is none")
class FabricWorkerRegistryImpl(WorkerRegistry): """ This class provide worker APIs which interact with Fabric blockchain. Detail method description will be available in WorkerRegistry interface """ def __init__(self, config): """ config is dict containing fabric specific parameters. """ self.__fabric_wrapper = None # Chain code name self.CHAIN_CODE = 'worker' if config is not None: self.__fabric_wrapper = FabricWrapper(config) else: raise Exception("config is none") def worker_lookup(self, worker_type=None, org_id=None, application_id=None, id=None): """ Lookup a worker identified worker_type, org_id and application_id all fields are optional and if present condition should match for all fields. If none passed it should return all workers. Returns tuple containing workers count, lookup tag and list of worker ids or on error returns None. """ if (self.__fabric_wrapper is not None): params = [] if worker_type is None: params.append(str(0)) else: params.append(str(worker_type.value)) if org_id is None: params.append('') else: params.append(org_id) if application_id is None: params.append('') else: params.append(application_id) logging.info("Worker loookup args {}".format(params)) lookupResult = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workerLookUp', params) return lookupResult else: logging.error("Fabric wrapper instance is not initialized") return None def worker_retrieve(self, worker_id, id=None): """ Retrieve the worker identified by worker id Returns tuple containing worker status, worker type, organization id, list of application ids and worker details(json string) On error returns None """ if (self.__fabric_wrapper is not None): params = [] params.append(worker_id) workerDetails = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workerRetrieve', params) return workerDetails else: logging.error("Fabric wrapper instance is not initialized") return None def worker_lookup_next(self, worker_type, org_id, application_id, lookup_tag, id=None): """ Getting Additional Worker Lookup Results Inputs 1. worker_type is a characteristic of Workers for which you may wish to search. 2. organization_id is an organization to which a Worker belongs. 3. application_type_id is an application type that has to be supported by the Worker. 4. lookup_tag is returned by a previous call to either this function or to worker_lookup. 5. id is used for json rpc request Outputs tuple containing following. 1. total_count is a total number of entries matching this lookup criteria. If this number is larger than the number of ids returned so far, the caller should use lookupTag to call workerLookUpNext to retrieve the rest of the ids. 2. new_lookup_tag is an optional parameter. If it is returned, it means that there are more matching Worker ids than can be retrieved by calling this function again with this tag as an input parameter. 3. ids is an array of the Worker ids that match the input parameters. On error returns None. """ if (self.__fabric_wrapper is not None): params = [] params.append(str(worker_type.value)) params.append(org_id) params.append(application_id) params.append(lookup_tag) lookupResult = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workerLookUpNext', params) return lookupResult else: logging.error("Fabric wrapper instance is not initialized") return None def worker_register( self, worker_id, worker_type, org_id, application_ids, details, id=None): """ Register new worker with details of worker Inputs 1. worker_id is a worker id, e.g. an Fabric address or a value derived from the worker's DID. 2. worker_type defines the type of Worker. Currently defined types are: 1. indicates "TEE-SGX": an Intel SGX Trusted Execution Environment 2. indicates "MPC": Multi-Party Compute 3. indicates "ZK": Zero-Knowledge 3. organization_id is an optional parameter representing the organization that hosts the Worker, e.g. a bank in the consortium or anonymous entity. 4. application_type_ids is an optional parameter that defines application types supported by the Worker. 5. details is detailed information about the worker in JSON format as defined in https://entethalliance.github.io/trusted-computing/spec.html #common-data-for-all-worker-types Returns transaction receipt on success or None on error. """ if (self.__fabric_wrapper is not None): params = [] params.append(worker_id) params.append(str(worker_type.value)) params.append(org_id) params.append(','.join(application_ids)) params.append(details) txn_status = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workerRegister', params) return txn_status else: logging.error("Fabric wrapper instance is not initialized") return None def worker_set_status(self, worker_id, status, id=None): """ Set the registry status identified by worker id status is worker type enum type Returns transaction receipt on success or None on error. """ if (self.__fabric_wrapper is not None): params.append(worker_id) params.append(str(status)) txn_status = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workerSetStatus', params) return txn_status else: logging.error("Fabric wrapper instance is not initialized") return None def worker_update(self, worker_id, details, id=None): """ Update the worker with details data which is json string Updating a Worker Inputs 1. worker_id is a worker id, e.g. an Fabric address or a value derived from the worker's DID. 2. details is detailed information about the worker in JSON format Returns transaction receipt on success or None on error. """ if (self.__fabric_wrapper is not None): params = [] params.append(worker_id) params.append(details) txn_status = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workerUpdate', params) return txn_status else: logging.error("Fabric wrapper instance is not initialized") return None
class FabricWorkOrderReceiptImpl(WorkOrderReceipt): """ This class provide work order receipt management APIs which interact with Fabric blockchain. Detail method description will be available in WorkOrderReceipt interface """ def __init__(self, config): """ config is dict containing fabric specific parameters. """ self.__fabric_wrapper = None # Chain code name self.CHAIN_CODE = 'receipt' if config is not None: self.__fabric_wrapper = FabricWrapper(config) else: raise Exception("config is none") def work_order_receipt_create(self, work_order_id, worker_id, worker_service_id, requester_id, receipt_create_status, work_order_request_hash): """ Function to create work order receipt in fabric block chain. Params work_order_id is an id of the Work Order. worker_id is the Worker id that should execute the Work Order. worker_service_id is an id of the Worker Service that hosts the Worker. requester_id is the id of the requester. receipt_create_status is an initial receipt status defined in EEA spec 7.1.1 Returns 0 on success and -1 on error. """ if (self.__fabric_wrapper is not None): if not is_valid_hex_str( binascii.hexlify(work_order_id).decode("utf8")): logging.info("Invalid work order id {}".format(work_order_id)) return -1 if not is_valid_hex_str( binascii.hexlify(worker_id).decode("utf8")): logging.info("Invalid worker id {}".format(worker_id)) return -1 if not is_valid_hex_str( binascii.hexlify(requester_id).decode("utf8")): logging.info("Invalid requester id {}".format(requester_id)) return -1 if not is_valid_hex_str( binascii.hexlify(worker_service_id).decode("utf8")): logging.info("Invalid service id {}".format(worker_service_id)) return -1 if work_order_request_hash is None: logging.info("work order request hash is None") return -1 params = [] params.append(work_order_id) params.append(worker_id) params.append(worker_service_id) params.append(requester_id) params.append(receipt_create_status) params.append(work_order_request_hash) txn_status = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workOrderReceiptCreate', params) if txn_status is True: return 0 else: return -1 else: logging.error("Fabric wrapper instance is not initialized) return -1 def work_order_receipt_update(self, work_order_id, updater_id, update_type, update_data, update_signature=None, signature_rules=None): """ Updating a Work Order Receipt Params work_order_id is a Work Order id that was sent in the corresponding work_order_submit request. updater_id is an id of the updating entity. It is optional update_type is from 0 to 255, the update sets the receipt status to update_type value update_data are update specific data that depends on updater type defined in EEA spec 7.1.2 update_signature is an optional signature of work_order_id, update_type, and update_data. signature_rules defines hashing and signing algorithms, that are separated by forward slash '/' Returns -1 on error, 0 on Success. """ if (self.__fabric_wrapper is not None): if not is_valid_hex_str( binascii.hexlify(work_order_id).decode("utf8")): logging.info("Invalid work order id {}".format(work_order_id)) return -1 if not is_valid_hex_str( binascii.hexlify(updater_id).decode("utf8")): logging.info("Invalid updater id {}".format(updater_id)) return -1 params = [] params.append(work_order_id) params.append(updater_id) params.append(update_type) params.append(update_data) if update_signature is not None: params.append(update_signature) params.append(signature_rules) receipt_status = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workOrderReceiptUpdate', params) if receipt_status is True: return 0 else: return -1 else: logging.error( "Fabric wrapper instance is not initialized") return -1 def work_order_receipt_retrieve(self, work_order_id): """ Retrieving a Work Order Receipt Inputs: work_order_id is the id of the Work Order to be retrieved. id is used for json rpc request Outputs: worker_service_id, requester_id, work_order_id, receipt_create_status, and work_order_request_hash are defined in work_order_receipt_create(). -1 on error """ if (self.__fabric_wrapper is not None): if not is_valid_hex_str( binascii.hexlify(work_order_id).decode("utf8")): logging.info("Invalid work order id {}".format(work_order_id)) return -1 params = [] params.append(work_order_id) retrieve_result = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workOrderReceiptRetrieve', params) if retrieve_result is not None: return retrieve_result else: return -1 else: logging.error( "Fabric wrapper instance is not initialized") return -1 def work_order_receipt_update_retrieve(self, work_order_id, updater_id, update_index): """ Function to retrieve update to receipt Params work_order_id is a Work Order id that was sent in the corresponding work_order_submit request. updater_id is an id of the updating entity. It is optional update_index is an index of the update to retrieve. Value "0xFFFFFFFF" is reserved to retrieve the last received update. Returns On success return updater_id, update_type, update_data, update_signature and signature_rules are defined work_order_receipt_update(). On error returns -1 """ if (self.__fabric_wrapper is not None): if not is_valid_hex_str( binascii.hexlify(work_order_id).decode("utf8")): logging.info("Invalid work order id {}".format(work_order_id)) return -1 if not is_valid_hex_str( binascii.hexlify(updater_id).decode("utf8")): logging.info("Invalid updater id {}".format(updater_id)) return -1 params = [] params.append(work_order_id) params.append(updater_id) params.append(update_index) receipt_result = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workOrderReceiptUpdateRetrieve', params) if receipt_result is not None: return receipt_result else: return -1 else: logging.error( "Fabric wrapper instance is not initialized") return -1 def work_order_receipt_lookup(self, worker_service_id, worker_id, requester_id, receipt_status): """ Function to lookup receipts Inputs: worker_service_id is a Worker Service id whose receipts will be retrieved. worker_id is the Worker Id whose receipts are requested. requester_id is the id of the entity requesting receipts. receipt_status defines the status of the receipts retrieved. id is used for json rpc request Outputs: total_count is the total number of receipts matching the lookup criteria. If this number is bigger than the size of the ids array, the caller should use a lookup_tag to call work_order_receipt_lookup_next() to retrieve the rest of the receipt ids. ids is an array of the Work Order receipt ids that match the input parameters On error returns -1 """ if (self.__fabric_wrapper is not None): if not is_valid_hex_str( binascii.hexlify(worker_id).decode("utf8")): logging.info("Invalid worker id {}".format(worker_id)) return -1 if not is_valid_hex_str( binascii.hexlify(worker_service_id).decode("utf8")): logging.info("Invalid service id {}".format(worker_service_id)) return -1 if not is_valid_hex_str( binascii.hexlify(requester_id).decode("utf8")): logging.info("Invalid requester id {}".format(requester_id)) return -1 params = [] params.append(worker_service_id) params.append(worker_id) params.append(requester_id) params.append(receipt_status) receipt_result = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workOrderReceiptLookUp', params) if receipt_result is not None: return receipt_result else: return -1 else: logging.error( "Fabric wrapper instance is not initialized") return -1 def work_order_receipt_lookup_next(self, worker_service_id, worker_id, requester_id, receipt_status, last_lookup_tag): """ Work Order Receipt Lookup Next Inputs: worker_service_id, worker_id, and requester_id are input parameters and last_lookup_tag is one of the output parameters for function work_order_receipt_lookup() defined in section Work Order Receipt Lookup. id is used for json rpc request Outputs: 1. total_count is the total number of receipts matching the lookup criteria. 2. lookup_tag is an optional parameter. If it is returned, it means that there are more matching receipts that can be retrieved by calling this function again and with this tag as an input parameter. 3. ids is an array of the Work Order receipt ids that match the input criteria from the corresponding call to work_order_receipt_lookup(). Returns tuple containing total count, look up tag and list of work order ids on success return -1 on error """ if (self.__fabric_wrapper is not None): if not is_valid_hex_str( binascii.hexlify(worker_id).decode("utf8")): logging.info("Invalid worker id {}".format(worker_id)) return -1 if not is_valid_hex_str( binascii.hexlify(worker_service_id).decode("utf8")): logging.info("Invalid service id {}".format(worker_service_id)) return -1 if not is_valid_hex_str( binascii.hexlify(requester_id).decode("utf8")): logging.info("Invalid requester id {}".format(requester_id)) return -1 params = [] params.append(worker_service_id) params.append(worker_id) params.append(requester_id) params.append(receipt_status) params.append(last_lookup_tag) receipt_result = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workOrderReceiptLookUpNext', params) if receipt_result is not None: return receipt_result else: return -1 else: logging.error( "Fabric wrapper instance is not initialized") return -1
class FabricWorkerRegistryImpl(WorkerRegistry): """ This class provide worker APIs which interact with the Hyperledger Fabric blockchain. Detailed method descriptions are available in the WorkerRegistry interface. """ def __init__(self, config): """ Parameters: config Dictionary containing Fabric-specific parameters """ self.__fabric_wrapper = None # Chain code name self.CHAIN_CODE = 'worker' if config is not None: self.__fabric_wrapper = FabricWrapper(config) else: raise Exception("config is none") def worker_lookup(self, worker_type=None, org_id=None, application_id=None, id=None): """ Lookup a worker identified worker_type, org_id, and application_id. All fields are optional and, if present, condition should match for all fields. If none are passed it should return all workers. If the list is too large to fit into a single response (the maximum number of entries in a single response is implementation specific), the smart contract should return the first batch of the results and provide a lookup_tag that can be used by the caller to retrieve the next batch by calling worker_lookup_next. Parameters: worker_type Optional characteristic of workers for which you may wish to search org_id Optional organization ID to which a worker belongs application_id Optional application type ID that is supported by the worker id Optional JSON RPC request ID Returns: Tuple containing workers count, lookup tag, and list of worker IDs: total_count Total number of entries matching a specified lookup criteria. If this number is larger than the size of the IDs array, the caller should use lookupTag to call worker_lookup_next to retrieve the rest of the IDs lookup_tag Optional parameter. If it is returned, it means that there are more matching worker IDs, which can then be retrieved by calling function worker_lookup_next with this tag as an input parameter ids Array of the worker IDs that match the input parameters On error returns None. """ if (self.__fabric_wrapper is not None): params = [] if worker_type is None: params.append(str(0)) else: params.append(str(worker_type.value)) if org_id is None: params.append("") else: params.append(org_id) if application_id is None: params.append("") else: params.append(application_id) logging.info("Worker lookup args {}".format(params)) lookupResult = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workerLookUp', params) return lookupResult else: logging.error("Fabric wrapper instance is not initialized") return None def worker_retrieve(self, worker_id, id=None): """ Retrieve the worker identified by worker ID. Parameters: worker_id Worker ID of the registry whose details are requested id Optional Optional JSON RPC request ID Returns: Tuple containing worker status (defined in worker_set_status), worker type, organization ID, list of application IDs, and worker details (JSON RPC string). On error returns None. """ if (self.__fabric_wrapper is not None): params = [] params.append(worker_id) workerDetails = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workerRetrieve', params) return workerDetails else: logging.error("Fabric wrapper instance is not initialized") return None def worker_lookup_next(self, worker_type, org_id, application_id, lookup_tag, id=None): """ Retrieve additional worker lookup results after calling worker_lookup. Parameters: worker_type Characteristic of Workers for which you may wish to search. org_id Organization ID to which a worker belongs application_id Optional application type ID that is supported by the worker lookup_tag is returned by a previous call to either this function or to worker_lookup id Optional Optional JSON RPC request ID Returns: Tuple containing the following: total_count Total number of entries matching this lookup criteria. If this number is larger than the number of IDs returned so far, the caller should use lookupTag to call worker_lookup_next to retrieve the rest of the IDs new_lookup_tag Optional parameter. If it is returned, it means that there are more matching worker IDs that can be retrieved by calling this function again with this tag as an input parameter ids Array of the worker IDs that match the input parameters On error returns None. """ if (self.__fabric_wrapper is not None): params = [] params.append(str(worker_type.value)) params.append(org_id) params.append(application_id) params.append(lookup_tag) lookupResult = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workerLookUpNext', params) return lookupResult else: logging.error("Fabric wrapper instance is not initialized") return None def worker_register(self, worker_id, worker_type, org_id, application_ids, details, id=None): """ Register a new worker with details of the worker. Parameters: worker_id Worker ID value. E.g., a Fabric address worker_type Type of Worker. Currently defined types are: * "TEE-SGX": an Intel SGX Trusted Execution Environment * "MPC": Multi-Party Compute * "ZK": Zero-Knowledge org_id Optional parameter representing the organization that hosts the Worker, e.g. a bank in the consortium or anonymous entity application_ids Optional parameter that defines application types supported by the Worker details Detailed information about the worker in JSON RPC format as defined in https://entethalliance.github.io/trusted-computing/spec.html #common-data-for-all-worker-types id Optional Optional JSON RPC request ID Returns: ContractResponse.SUCCESS on success or ContractResponse.ERROR on error. """ if (self.__fabric_wrapper is not None): params = [] params.append(worker_id) params.append(str(worker_type.value)) params.append(org_id) params.append(','.join(application_ids)) params.append(details) txn_status = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workerRegister', params) return txn_status else: logging.error("Fabric wrapper instance is not initialized") return ContractResponse.ERROR def worker_set_status(self, worker_id, status, id=None): """ Set the registry status identified by worker ID Parameters: worker_id Worker ID value. E.g., a Fabric address status Worker status. The currently defined values are: 1 - worker is active 2 - worker is temporarily "off-line" 3 - worker is decommissioned 4 - worker is compromised id Optional Optional JSON RPC request ID Returns: ContractResponse.SUCCESS on success or ContractResponse.ERROR on error. """ if (self.__fabric_wrapper is not None): params = [] params.append(worker_id) params.append(str(status.value)) txn_status = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workerSetStatus', params) return txn_status else: logging.error("Fabric wrapper instance is not initialized") return ContractResponse.ERROR def worker_update(self, worker_id, details, id=None): """ Update a worker with details data. Parameters: worker_id Worker ID, e.g. a Fabric address details Detailed information about the worker in JSON format id Optional Optional JSON RPC request ID Returns: ContractResponse.SUCCESS on success or ContractResponse.ERROR on error. """ if (self.__fabric_wrapper is not None): params = [] params.append(worker_id) params.append(details) txn_status = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workerUpdate', params) return txn_status else: logging.error("Fabric wrapper instance is not initialized") return ContractResponse.ERROR
class FabricWorkOrderImpl(WorkOrderProxy): """ This class provide work order management APIs which interact with Fabric blockchain. Detail method description will be available in WorkOrder interface """ def __init__(self, config): """ config is dict containing fabric specific parameters. """ self.__fabric_wrapper = None # Chain code name self.CHAIN_CODE = 'order' self.WORK_ORDER_SUBMITTED_EVENT_NAME = 'workOrderSubmitted' self.WORK_ORDER_COMPLETED_EVENT_NAME = 'workOrderCompleted' self.WAIT_TIME = 30 self.__wo_resp = '' if config is not None: self.__fabric_wrapper = FabricWrapper(config) else: raise Exception("config is none") def work_order_submit(self, work_order_id, worker_id, requester_id, work_order_request, id=None): """ Submit work order request to fabric block chain. Params work_order_id is unique id of the work order request worker_id is identifier for the worker requester_id is unique id to identify the requester work_order_request is json string work order request defined in EEA specification 6.1.1. Returns 0 on success and non zero on error. """ if (self.__fabric_wrapper is not None): params = [] params.append(work_order_id) params.append(worker_id) params.append(requester_id) params.append(work_order_request) txn_status = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workOrderSubmit', params) return txn_status else: logging.error("Fabric wrapper instance is not initialized") return ContractResponse.ERROR def work_order_get_result(self, work_order_id, id=None): """ Function to query blockchain to get work order result. Params work_order_id is a Work Order id that was sent in the corresponding work_order_submit request. Returns None on error, result on Success. """ # Calling the contract workOrderGet() will result in error # work order id doesn't exist. This is because committing will # take some time to commit to chain. # Instead of calling contract api to get result chosen the # event based approach. event_handler = \ self.get_work_order_completed_event_handler( self.handle_fabric_event) if event_handler: tasks = [ event_handler.start_event_handling(), event_handler.stop_event_handling(int(self.WAIT_TIME)) ] loop = asyncio.get_event_loop() loop.run_until_complete( asyncio.wait(tasks, return_when=asyncio.ALL_COMPLETED)) loop.close() return self.__wo_resp else: logging.info("Failed while creating event handler") return None def work_order_complete(self, work_order_id, work_order_response): """ This function is called by the Worker Service to complete a Work Order successfully or in error. This API is for proxy model. params work_order_id is unique id to identify the work order request work_order_response is the Work Order response data in string Returns errorCode is a result of operation. """ if (self.__fabric_wrapper is not None): if work_order_response is None: logging.info("Work order response is empty") return ContractResponse.ERROR params = [] params.append(work_order_id) params.append(work_order_response) txn_status = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workOrderComplete', params) return txn_status else: logging.error("Fabric wrapper instance is not initialized") return ContractResponse.ERROR def encryption_key_start(self, tag): """ Function to initiate to set the encryption key of worker. """ logging.error("This API is not supported") return None def encryption_key_get(self, worker_id, requester_id, last_used_key_nonce=None, tag=None, signature_nonce=None, signature=None): """ Function to worker's key from fabric block chain. """ logging.error("This API is not supported") return None def encryption_key_set(self, worker_id, encryption_key, encryption_nonce, tag, signature): """ Function to set worker's encryption key. """ logging.error("This API is not supported") return None def get_work_order_submitted_event_handler(self, handler_func): """ Function to start event handler loop for workOrderSubmitted event params: handler_func is call back function name as string returns: event handler object """ if (self.__fabric_wrapper is not None): event_handler = self.__fabric_wrapper.get_event_handler( self.WORK_ORDER_SUBMITTED_EVENT_NAME, self.CHAIN_CODE, handler_func) return event_handler else: logging.error("Fabric wrapper instance is not initialized") return None def get_work_order_completed_event_handler(self, handler_func): """ Function to start event handler loop for workOrderCompleted event params: handler_func is call back function name as string """ if (self.__fabric_wrapper is not None): event_handler = self.__fabric_wrapper.get_event_handler( self.WORK_ORDER_COMPLETED_EVENT_NAME, self.CHAIN_CODE, handler_func) return event_handler else: logging.error("Fabric wrapper instance is not initialized") return None def handle_fabric_event(self, event, block_num, txn_id, status): """ callback function for fabric event handler """ payload = event['payload'].decode("utf-8") resp = json.loads(payload) self.__wo_resp = json.loads(resp["workOrderResponse"]) logging.debug("Work order response from event : {}".format( self.__wo_resp))
class FabricWorkOrderReceiptImpl(WorkOrderReceipt): """ This class provides work order receipt management APIs which interact with the Fabric blockchain. Detailed method descriptions are available in the WorkOrderReceipt interface. """ def __init__(self, config): """ Parameters: config Dict containing Fabric-specific parameters. """ self.__fabric_wrapper = None # Chain code name self.CHAIN_CODE = 'receipt' if config is not None: self.__fabric_wrapper = FabricWrapper(config) else: raise Exception("config is none") def work_order_receipt_create(self, work_order_id, worker_id, worker_service_id, requester_id, receipt_create_status, work_order_request_hash): """ Create work order receipt in the Fabric block chain. Parameters: work_order_id ID of the Work Order worker_id Worker id that should execute the Work Order worker_service_id ID of the Worker Service that hosts the Worker requester_id ID of the requester receipt_create_status Initial receipt status defined in EEA spec 7.1.1 work_order_request_hash Hash value of the work order request as defined in EEA spec 6.7 Returns: 0 on success and -1 on error. """ if (self.__fabric_wrapper is not None): if not is_valid_hex_str( binascii.hexlify(work_order_id).decode("utf8")): logging.info("Invalid work order id {}".format(work_order_id)) return -1 if not is_valid_hex_str( binascii.hexlify(worker_id).decode("utf8")): logging.info("Invalid worker id {}".format(worker_id)) return -1 if not is_valid_hex_str( binascii.hexlify(requester_id).decode("utf8")): logging.info("Invalid requester id {}".format(requester_id)) return -1 if not is_valid_hex_str( binascii.hexlify(worker_service_id).decode("utf8")): logging.info("Invalid service id {}".format(worker_service_id)) return -1 if work_order_request_hash is None: logging.info("work order request hash is None") return -1 params = [] params.append(work_order_id) params.append(worker_id) params.append(worker_service_id) params.append(requester_id) params.append(receipt_create_status) params.append(work_order_request_hash) txn_status = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workOrderReceiptCreate', params) if txn_status is True: return 0 else: return -1 else: logging.error("Fabric wrapper instance is not initialized") return -1 def work_order_receipt_update(self, work_order_id, updater_id, update_type, update_data, update_signature=None, signature_rules=None): """ Update a Work Order Receipt. Parameters: work_order_id Work Order ID that was sent in the corresponding work_order_submit request updater_id ID of the updating entity. It is optional if it is the same as the transaction sender address update_type Type of the Work Order update that defines how the update should be handled update_data Update-specific data that depends on the updater type defined in EEA spec 7.1.2 update_signature Optional signature of concatenated work_order_id, update_type, and update_data signature_rules Defines hashing and signing algorithms, that are separated by forward slash '/' Returns: 0 on success, -1 on error. """ if (self.__fabric_wrapper is not None): if not is_valid_hex_str( binascii.hexlify(work_order_id).decode("utf8")): logging.info("Invalid work order id {}".format(work_order_id)) return -1 if not is_valid_hex_str( binascii.hexlify(updater_id).decode("utf8")): logging.info("Invalid updater id {}".format(updater_id)) return -1 params = [] params.append(work_order_id) params.append(updater_id) params.append(update_type) params.append(update_data) if update_signature is not None: params.append(update_signature) params.append(signature_rules) receipt_status = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workOrderReceiptUpdate', params) if receipt_status is True: return 0 else: return -1 else: logging.error("Fabric wrapper instance is not initialized") return -1 def work_order_receipt_retrieve(self, work_order_id): """ Retrieve a Work Order Receipt. Parameters: work_order_id ID of the Work Order to be retrieved id Optional JSON RPC request ID Returns: worker_service_id, requester_id, work_order_id, receipt_create_status, and work_order_request_hash, as defined in work_order_receipt_create(). Return -1 on error. """ if (self.__fabric_wrapper is not None): if not is_valid_hex_str( binascii.hexlify(work_order_id).decode("utf8")): logging.info("Invalid work order id {}".format(work_order_id)) return -1 params = [] params.append(work_order_id) retrieve_result = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workOrderReceiptRetrieve', params) if retrieve_result is not None: return retrieve_result else: return -1 else: logging.error("Fabric wrapper instance is not initialized") return -1 def work_order_receipt_update_retrieve(self, work_order_id, updater_id, update_index): """ Retrieve an update to a work order receipt. Parameters: work_order_id Work Order ID that was sent in the corresponding work_order_submit request updater_id ID of the updating entity. Ignored if null update_index Index of the update to retrieve Value "0xFFFFFFFF" is reserved to retrieve the last received update Returns: On success, return updater_id, update_type, update_data, update_signature, signature_rules, as defined in work_order_receipt_update(), and update_count. On error, return -1. """ if (self.__fabric_wrapper is not None): if not is_valid_hex_str( binascii.hexlify(work_order_id).decode("utf8")): logging.info("Invalid work order id {}".format(work_order_id)) return -1 if not is_valid_hex_str( binascii.hexlify(updater_id).decode("utf8")): logging.info("Invalid updater id {}".format(updater_id)) return -1 params = [] params.append(work_order_id) params.append(updater_id) params.append(update_index) receipt_result = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workOrderReceiptUpdateRetrieve', params) if receipt_result is not None: return receipt_result else: return -1 else: logging.error("Fabric wrapper instance is not initialized") return -1 def work_order_receipt_lookup(self, worker_service_id, worker_id, requester_id, receipt_status): """ Lookup a work order receipt. Parameters: worker_service_id Worker Service ID whose receipts will be retrieved worker_id Worker Id whose receipts are requested requester_id ID of the entity requesting receipts receipt_status Defines the status of the receipts retrieve id Optional JSON RPC request ID Returns: Tuple containing total count, last_lookup_tag, and list of work order IDs, on success: total_count Total number of receipts matching the lookup criteria. If this number is bigger than the size of the ids array, the caller should use a lookup_tag to call work_order_receipt_lookup_next() to retrieve the rest of the receipt IDs. last_lookup_tag Optional lookup_tag when the receipts exceed the ids array size ids Array of work order receipt ids that match the input On error, returns -1. """ if (self.__fabric_wrapper is not None): if not is_valid_hex_str( binascii.hexlify(worker_id).decode("utf8")): logging.info("Invalid worker id {}".format(worker_id)) return -1 if not is_valid_hex_str( binascii.hexlify(worker_service_id).decode("utf8")): logging.info("Invalid service id {}".format(worker_service_id)) return -1 if not is_valid_hex_str( binascii.hexlify(requester_id).decode("utf8")): logging.info("Invalid requester id {}".format(requester_id)) return -1 params = [] params.append(worker_service_id) params.append(worker_id) params.append(requester_id) params.append(receipt_status) receipt_result = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workOrderReceiptLookUp', params) if receipt_result is not None: return receipt_result else: return -1 else: logging.error("Fabric wrapper instance is not initialized") return -1 def work_order_receipt_lookup_next(self, worker_service_id, worker_id, requester_id, receipt_status, last_lookup_tag): """ Retrieve subsequent work order receipts after calling work_order_receipt_lookup(). Parameters: worker_service_id Worker Service ID worker_id Worker ID value derived from the worker's DID requester_id Requester ID last_lookup_tag One of the output parameters for function work_order_receipt_lookup() id Optional JSON RPC request ID Returns: On success, return a tuple containing total count, look up tag, and list of work order IDs: total_count Total number of receipts matching the lookup criteria lookup_tag Optional parameter. If it is returned, it means that there are more matching receipts that can be retrieved by calling this function again and with this tag as an input parameter. ids Array of the Work Order receipt IDs that match the input criteria from the corresponding call to work_order_receipt_lookup(). Return -1 on error. """ if (self.__fabric_wrapper is not None): if not is_valid_hex_str( binascii.hexlify(worker_id).decode("utf8")): logging.info("Invalid worker id {}".format(worker_id)) return -1 if not is_valid_hex_str( binascii.hexlify(worker_service_id).decode("utf8")): logging.info("Invalid service id {}".format(worker_service_id)) return -1 if not is_valid_hex_str( binascii.hexlify(requester_id).decode("utf8")): logging.info("Invalid requester id {}".format(requester_id)) return -1 params = [] params.append(worker_service_id) params.append(worker_id) params.append(requester_id) params.append(receipt_status) params.append(last_lookup_tag) receipt_result = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workOrderReceiptLookUpNext', params) if receipt_result is not None: return receipt_result else: return -1 else: logging.error("Fabric wrapper instance is not initialized") return -1
class FabricWorkerRegistryListImpl(WorkerRegistryList): """ This class provide APIs to read/write registry entries of workers, which is stored in the Hyperledger Fabric blockchain. """ def __init__(self, config): """ Parameters: config Dictionary containing Fabric-specific parameters. """ self.__fabric_wrapper = None # Chain code name self.CHAIN_CODE = 'registry' if config is not None: self.__fabric_wrapper = FabricWrapper(config) else: raise Exception("config is none") def registry_lookup(self, app_type_id=None): """ Registry Lookup identified by application type ID Parameters: app_type_id Application type ID to lookup in the registry Returns: Tuple containing totalCount, lookupTag, and ids on success: totalCount Total number of entries matching a specified lookup criteria. If this number is larger than the size of the ids array, the caller should use the lookupTag to call registry_lookup_next to retrieve the rest of the IDs lookupTag Optional parameter. If it is returned, it means that there are more matching registry IDs that can be retrieved by calling the function registry_lookup_next with this tag as an input parameter. ids Array of the registry organization ids that match the input parameters. Returns None on error. """ if (self.__fabric_wrapper is not None): if app_type_id is not None: if is_valid_hex_str( binascii.hexlify(app_type_id).decode("utf8")): params = [] params.append(byte_array_to_hex_str(app_type_id)) lookupResult = \ self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'registryLookUp', params) else: logging.info( "Invalid application type id {}".format(app_type_id)) return None else: logging.error("Fabric wrapper instance is not initialized") return None def registry_retrieve(self, org_id): """ Retrieve registry information identified by the organization ID. Parameters: org_id Organization ID to lookup Returns: Tuple containing following on success: uri String defines a URI for this registry that supports the Off-Chain Worker Registry JSON RPC API. It will be None for the proxy model sc_addr Fabric address for worker registry smart contract address application_type_ids List of application ids (array of byte[]) status Status of the registry Returns None on error. """ if (self.__fabric_wrapper is not None): if (is_valid_hex_str(binascii.hexlify(org_id).decode("utf8")) is False): logging.info("Invalid Org id {}".format(org_id)) return None else: params = [] params.append(byte_array_to_hex_str(org_id)) registryDetails = \ self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'registryRetrieve', params ) return registryDetails else: logging.error("Fabric wrapper instance is not initialized") return None def registry_lookup_next(self, app_type_id, lookup_tag): """ Get additional registry lookup results. This function is called to retrieve additional results of the Registry lookup initiated by the registry_lookup call. Parameters: app_type_id Application type ID that has to be supported by the workers retrieved lookup_tag Returned by a previous call to either this function or to registry_lookup Returns: Outputs a tuple on success containing the following: total_count Total number of entries matching the lookup criteria. If this number is larger than the number of IDs returned so far, the caller should use lookup_tag to call registry_lookup_next to retrieve the rest of the IDs new_lookup_tag is an optional parameter. If it is returned, it means that there are more matching registry IDs that can be retrieved by calling this function again with this tag as an input parameter ids Array of the registry IDs that match the input parameters Returns None on error. """ if (self.__fabric_wrapper is not None): if is_valid_hex_str(binascii.hexlify(app_type_id).decode("utf8")): params = [] params.append(byte_array_to_hex_str(app_type_id)) params.append(lookup_tag) lookupResult = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'registryLookUpNext', params) else: logging.info( "Invalid application type id {}".format(app_type_id)) return None else: logging.error("Fabric wrapper instance is not initialized") return None def registry_add(self, org_id, uri, sc_addr, app_type_ids): """ Add a new registry. Parameters: org_id bytes[] identifies organization that hosts the registry, e.g. a bank in the consortium or an anonymous entity uri String defining a URI for this registry that supports the Off-Chain Worker Registry JSON RPC API sc_addr bytes[] defines a Fabric chain code name that runs the Worker Registry Smart Contract API smart contract for this registry app_type_ids []bytes[] is an optional parameter that defines application types supported by the worker managed by the registry Returns: Transaction receipt on success or None on error. """ if (self.__fabric_wrapper is not None): if (is_valid_hex_str(binascii.hexlify(org_id).decode("utf8")) is False): logging.info("Invalid Org id {}".format(org_id)) return None if (sc_addr is not None and is_valid_hex_str( binascii.hexlify(sc_addr).decode("utf8")) is False): logging.info("Invalid smart contract name {}") return None if (not uri): logging.info("Empty uri {}".format(uri)) return None app_ids = [] for aid in app_type_ids: if (is_valid_hex_str(binascii.hexlify(aid).decode("utf8")) is False): logging.info("Invalid application id {}".format(aid)) return None else: app_ids.append(byte_array_to_hex_str(aid)) params = [] params.append(byte_array_to_hex_str(org_id)) params.append(uri) params.append(byte_array_to_hex_str(sc_addr)) params.append(','.join(app_ids)) txn_status = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'registryAdd', params) return txn_status else: logging.error("Fabric wrapper instance is not initialized") return None def registry_update(self, org_id, uri, sc_addr, app_type_ids): """ Update a registry. Parameters: org_id bytes[] identifies organization that hosts the registry, e.g. a bank in the consortium or an anonymous entity uri string that defines a URI for this registry that supports the Off-Chain Worker Registry JSON RPC API sc_addr bytes[] defines a Fabric chain code name that runs the Worker Registry Smart Contract API smart contract for this registry app_type_ids []bytes[] is an optional parameter that defines application types supported by the worker managed by the registry Returns: Transaction receipt on success or None on error. """ if (self.__fabric_wrapper is not None): if (is_valid_hex_str(binascii.hexlify(org_id).decode("utf8")) is False): logging.error("Invalid Org id {}".format(org_id)) return None if (sc_addr is not None and is_valid_hex_str( binascii.hexlify(sc_addr).decode("utf8")) is False): logging.error( "Invalid smart contract address {}".format(sc_addr)) return None if (not uri): logging.error("Empty uri {}".format(uri)) return None app_ids = [] for aid in app_type_ids: if (is_valid_hex_str(binascii.hexlify(aid).decode("utf8")) is False): logging.error("Invalid application id {}".format(aid)) return None else: app_ids.append(byte_array_to_hex_str(aid)) params = [] params.append(byte_array_to_hex_str(org_id)) params.append(uri) params.append(byte_array_to_hex_str(sc_addr)) params.append(','.join(app_ids)) txn_status = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'registryUpdate', params) return txn_status else: logging.error("Fabric wrapper instance is not initialized") return None def registry_set_status(self, org_id, status): """ Set registry status. Parameters: org_id bytes[] identifies organization that hosts the registry, e.g. a bank in the consortium or an anonymous entity status Defines the registry status to set. The currently defined values are: 1 - the registry is active 2 - the registry is temporarily "off-line" 3 - the registry is decommissioned Returns: Transaction receipt on success or None on error. """ if (self.__fabric_wrapper is not None): if (is_valid_hex_str(binascii.hexlify(org_id).decode("utf8")) is False): logging.info("Invalid Org id {}".format(org_id)) return None if not isinstance(status, RegistryStatus): logging.info("Invalid registry status {}".format(status)) return None params = [] params.append(byte_array_to_hex_str(org_id)) params.append(str(status)) txn_status = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'registrySetStatus', params) return txn_status else: logging.error("Fabric wrapper instance is not initialized") return None
class FabricWorkOrderImpl(WorkOrderProxy): """ This class provide work order management APIs which interact with Fabric blockchain. Detail method description will be available in WorkOrder interface """ def __init__(self, config): """ config is dict containing fabric specific parameters. """ self.__fabric_wrapper = None # Chain code name self.CHAIN_CODE = 'order' self.WORK_ORDER_SUBMITTED_EVENT_NAME = 'workOrderSubmitted' self.WORK_ORDER_COMPLETED_EVENT_NAME = 'workOrderCompleted' if config is not None: self.__fabric_wrapper = FabricWrapper(config) else: raise Exception("config is none") def work_order_submit(self, work_order_id, worker_id, requester_id, work_order_request, id=None): """ Submit work order request to fabric block chain. Params work_order_id is unique id of the work order request worker_id is identifier for the worker requester_id is unique id to identify the requester work_order_request is json string work order request defined in EEA specification 6.1.1. Returns 0 on success and non zero on error. """ if (self.__fabric_wrapper is not None): params = [] params.append(work_order_id) params.append(worker_id) params.append(requester_id) params.append(work_order_request) txn_status = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workOrderSubmit', params) if txn_status is True: return 0 else: return -1 else: logging.error("Fabric wrapper instance is not initialized") return -1 def work_order_get_result(self, work_order_id, id=None): """ Function to query blockchain to get work order result. Params work_order_id is a Work Order id that was sent in the corresponding work_order_submit request. Returns -1 on error, result on Success. """ if (self.__fabric_wrapper is not None): params = [] params.append(work_order_id) work_order_result = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workOrderGetResult', params) if work_order_result is not None: return work_order_result else: return -1 else: logging.error("Fabric wrapper instance is not initialized") return -1 def work_order_complete(self, work_order_id, work_order_response): """ This function is called by the Worker Service to complete a Work Order successfully or in error. This API is for proxy model. params work_order_id is unique id to identify the work order request work_order_response is the Work Order response data in string Returns errorCode is a result of operation. """ if (self.__fabric_wrapper is not None): if work_order_response is None: logging.info("Work order response is empty") return -1 params = [] params.append(work_order_id) params.append(work_order_response) txn_status = self.__fabric_wrapper.invoke_chaincode( self.CHAIN_CODE, 'workOrderComplete', params) if txn_status is True: return 0 else: return -1 else: logging.error("Fabric wrapper instance is not initialized") return -1 def encryption_key_start(self, tag): """ Function to initiate to set the encryption key of worker. """ logging.error("This API is not supported") return None def encryption_key_get(self, worker_id, requester_id, last_used_key_nonce=None, tag=None, signature_nonce=None, signature=None): """ Function to worker's key from fabric block chain. """ logging.error("This API is not supported") return None def encryption_key_set(self, worker_id, encryption_key, encryption_nonce, tag, signature): """ Function to set worker's encryption key. """ logging.error("This API is not supported") return None def get_work_order_submitted_event_handler(self, handler_func): """ Function to start event handler loop for workOrderSubmitted event params: handler_func is call back function name as string returns: event handler object """ if (self.__fabric_wrapper is not None): event_handler = self.__fabric_wrapper.get_event_handler( self.WORK_ORDER_SUBMITTED_EVENT_NAME, self.CHAIN_CODE, handler_func) return event_handler else: logging.error("Fabric wrapper instance is not initialized") return None def get_work_order_completed_event_handler(self, handler_func): """ Function to start event handler loop for workOrderCompleted event params: handler_func is call back function name as string """ if (self.__fabric_wrapper is not None): event_handler = self.__fabric_wrapper.get_event_handler( self.WORK_ORDER_COMPLETED_EVENT_NAME, self.CHAIN_CODE, handler_func) return event_handler else: logging.error("Fabric wrapper instance is not initialized") return None