Exemplo n.º 1
0
 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")
Exemplo n.º 2
0
 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")
Exemplo n.º 3
0
 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")
Exemplo n.º 5
0
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
Exemplo n.º 6
0
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
Exemplo n.º 7
0
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
Exemplo n.º 8
0
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))
Exemplo n.º 9
0
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
Exemplo n.º 10
0
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
Exemplo n.º 11
0
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