Beispiel #1
0
    def download(self,
                 did,
                 service_index,
                 owner_account,
                 destination,
                 index=None):
        """
        Download the asset data.

        Using the service endpoint defined in the ddo's service pointed to by service_definition_id.
        Consumer's permissions is checked implicitly by the secret-store during decryption
        of the contentUrls.
        The service endpoint is expected to also verify that `owner_account` is the actual owner
        of the asset.
        This method downloads and saves the asset datafiles to disk.

        :param did: DID, str
        :param service_index: identifier of the service inside the asset DDO, str
        :param owner_account: Account instance of the owner
        :param destination: str path
        :param index: Index of the document that is going to be downloaded, int
        :return: str path to saved files
        """
        ddo = self.resolve(did)
        if index is not None:
            assert isinstance(index,
                              int), logger.error('index has to be an integer.')
            assert index >= 0, logger.error(
                'index has to be 0 or a positive integer.')
        return self._asset_consumer.download(
            service_index, ddo, owner_account, destination,
            GatewayProvider.get_gateway(),
            self._get_secret_store(owner_account), self._config, index)
Beispiel #2
0
    def execute(self, agreement_id, did, index, consumer_account, workflow_did):
        """

        :param agreement_id:representation of `bytes32` id, hexstr
        :param did: computing service did, str
        :param index: id of the service within the asset DDO, str
        :param consumer_account: Account instance of the consumer ordering the service
        :param workflow_did: the asset did (of `workflow` type) which consist of `did:nv:` and
        the assetId hex str (without `0x` prefix), str
        :return: the id of the compute job, str
        """
        workflow_ddo = self.resolve(workflow_did)
        compute_ddo = self.resolve(did)
        if index is not None:
            assert isinstance(index, int), logger.error('index has to be an integer.')
            assert index >= 0, logger.error('index has to be 0 or a positive integer.')
        return self._asset_executor.execute(
            agreement_id,
            compute_ddo,
            workflow_ddo,
            consumer_account,
            GatewayProvider.get_gateway(),
            index,
            self._config
        )
Beispiel #3
0
    def create_compute(self, metadata, publisher_account, asset_rewards={"_amounts": [], "_receivers": []},
                       service_descriptors=None, providers=None,
                       authorization_type=ServiceAuthorizationTypes.PSK_RSA, use_secret_store=False):
        """
        Register a compute to the data asset in both the keeper's DIDRegistry (on-chain) and in
        the Metadata store.

        :param metadata: dict conforming to the Metadata accepted by Nevermined Protocol.
        :param publisher_account: Account of the publisher registering this asset
        :param asset_rewards: Asset rewards distribution including amounts and receivers
        :param service_descriptors: list of ServiceDescriptor tuples of length 2.
            The first item must be one of ServiceTypes and the second
            item is a dict of parameters and values required by the service
        :param providers: list of addresses of providers of this asset (a provider is
            an ethereum account that is authorized to provide asset services)
        :param authorization_type: str indicate the authorization type that is going to be used
        to encrypt the urls.
            SecretStore, PSK-RSA and PSK-ECDSA are supported.
        :param use_secret_store: bool indicate whether to use the secret store directly for
            encrypting urls (Uses Gateway provider service if set to False)
        :return: DDO instance
        """

        metadata_copy = copy.deepcopy(metadata)
        gateway = GatewayProvider.get_gateway()

        compute_service_attributes = self._build_compute(metadata_copy, publisher_account, asset_rewards)
        service_descriptor = ServiceDescriptor.compute_service_descriptor(
            compute_service_attributes, gateway.get_execute_endpoint(self._config))

        return self.create(metadata, publisher_account, service_descriptors=[service_descriptor],
                           providers=providers, authorization_type=authorization_type,
                           use_secret_store=use_secret_store)
Beispiel #4
0
def get_consumer_instance(init_tokens=True,
                          use_ss_mock=True,
                          use_gateway_mock=True):
    nevermined = Nevermined()
    account = get_consumer_account()
    nevermined.main_account = account
    if init_tokens:
        init_ocn_tokens(nevermined, nevermined.main_account)
    if use_ss_mock:
        SecretStoreProvider.set_secret_store_class(SecretStoreMock)
    else:
        SecretStoreProvider.set_secret_store_class(SecretStore)
    if use_gateway_mock:
        GatewayProvider.set_gateway_class(GatewayMock)
    else:
        Gateway.set_http_client(get_requests_session())
        GatewayProvider.set_gateway_class(Gateway)

    return nevermined
Beispiel #5
0
    def upload_filecoin(self, file_path):
        """Upload a file to Filecoin

        param file_path: The path to the file to upload, str
        return: The url with the cid, str
        """
        path = pathlib.Path(file_path)
        if not path.is_file():
            raise ValueError(f'File {file_path} not found or not a file')

        with path.open('rb') as f:
            gateway = GatewayProvider.get_gateway()
            response = gateway.upload_filecoin(f, self._config)
            return response['url']
Beispiel #6
0
    def compute_status(self, service_agreement_id, execution_id, account):
        """
        Get the status of a compute workflow.

        :param service_agreement_id: The id of the service agreement that ordered the compute job, str
        :param execution_id: The id of the compute job, str
        :param account: Account instance that ordered the execution of the compute job
        :return: str compute status
        """
        return self._asset_consumer.compute_status(
            service_agreement_id,
            execution_id,
            account,
            GatewayProvider.get_gateway(),
            self._config,
        )
Beispiel #7
0
    def create(self,
               metadata,
               publisher_account,
               service_descriptors=None,
               providers=None,
               authorization_type=ServiceAuthorizationTypes.PSK_RSA,
               use_secret_store=False,
               activity_id=None,
               attributes=None,
               asset_rewards={
                   "_amounts": [],
                   "_receivers": []
               },
               cap=None,
               royalties=None):
        """
        Register an asset in both the keeper's DIDRegistry (on-chain) and in the Metadata store.

        :param metadata: dict conforming to the Metadata accepted by Nevermined Protocol.
        :param publisher_account: Account of the publisher registering this asset
        :param service_descriptors: list of ServiceDescriptor tuples of length 2.
            The first item must be one of ServiceTypes and the second
            item is a dict of parameters and values required by the service
        :param providers: list of addresses of providers of this asset (a provider is
            an ethereum account that is authorized to provide asset services)
        :param authorization_type: str indicate the authorization type that is going to be used
        to encrypt the urls.
            SecretStore, PSK-RSA and PSK-ECDSA are supported.
        :param use_secret_store: bool indicate whether to use the secret store directly for
            encrypting urls (Uses Gateway provider service if set to False)
        :param activity_id: identifier of the activity creating the new entity
        :param attributes: attributes associated with the action
        :param asset_rewards: rewards distribution including the amounts and the receivers
        :param cap: max cap of nfts that can be minted for the asset
        :param royalties: royalties in the secondary market going to the original creator
        :return: DDO instance
        """
        assert isinstance(
            metadata,
            dict), f'Expected metadata of type dict, got {type(metadata)}'

        # copy metadata so we don't change the original
        metadata_copy = copy.deepcopy(metadata)

        # Create a DDO object
        ddo = DDO()
        gateway = GatewayProvider.get_gateway()
        ddo_service_endpoint = self._get_metadata_provider(
        ).get_service_endpoint()
        metadata_service_desc = ServiceDescriptor.metadata_service_descriptor(
            metadata_copy, ddo_service_endpoint)
        if metadata_copy['main']['type'] == 'dataset' or metadata_copy['main'][
                'type'] == 'algorithm':
            access_service_attributes = self._build_access(
                metadata_copy, publisher_account, asset_rewards)
            if not service_descriptors:
                if authorization_type == ServiceAuthorizationTypes.PSK_RSA:
                    service_descriptors = [
                        ServiceDescriptor.authorization_service_descriptor(
                            self._build_authorization(
                                authorization_type,
                                public_key=gateway.get_rsa_public_key(
                                    self._config)),
                            gateway.get_access_endpoint(self._config))
                    ]
                elif authorization_type == ServiceAuthorizationTypes.PSK_ECDSA:
                    service_descriptors = [
                        ServiceDescriptor.authorization_service_descriptor(
                            self._build_authorization(
                                authorization_type,
                                public_key=gateway.get_ecdsa_public_key(
                                    self._config)),
                            gateway.get_access_endpoint(self._config))
                    ]
                else:
                    service_descriptors = [
                        ServiceDescriptor.authorization_service_descriptor(
                            self._build_authorization(authorization_type,
                                                      threshold=0),
                            self._config.secret_store_url)
                    ]
                service_descriptors += [
                    ServiceDescriptor.access_service_descriptor(
                        access_service_attributes,
                        gateway.get_access_endpoint(self._config))
                ]
            else:
                service_types = set(map(lambda x: x[0], service_descriptors))
                if ServiceTypes.AUTHORIZATION not in service_types:
                    if authorization_type == ServiceAuthorizationTypes.PSK_RSA:
                        service_descriptors += [
                            ServiceDescriptor.authorization_service_descriptor(
                                self._build_authorization(
                                    authorization_type,
                                    public_key=gateway.get_rsa_public_key(
                                        self._config)),
                                gateway.get_access_endpoint(self._config))
                        ]
                    elif authorization_type == ServiceAuthorizationTypes.PSK_ECDSA:
                        service_descriptors += [
                            ServiceDescriptor.authorization_service_descriptor(
                                self._build_authorization(
                                    authorization_type,
                                    public_key=gateway.get_ecdsa_public_key(
                                        self._config)),
                                gateway.get_access_endpoint(self._config))
                        ]
                    else:
                        service_descriptors += [
                            ServiceDescriptor.authorization_service_descriptor(
                                self._build_authorization(authorization_type,
                                                          threshold=0),
                                self._config.secret_store_url)
                        ]
                else:
                    service_descriptors += [
                        ServiceDescriptor.access_service_descriptor(
                            access_service_attributes,
                            gateway.get_access_endpoint(self._config))
                    ]
        else:
            if not service_descriptors:
                service_descriptors = []
            else:
                service_descriptors += []
            logger.info('registering a workflow.')
        # Add all services to ddo
        service_descriptors = [metadata_service_desc] + service_descriptors

        services = ServiceFactory.build_services(service_descriptors)
        checksums = dict()
        for service in services:
            checksums[str(service.index)] = checksum(service.main)

        # Adding proof to the ddo.
        ddo.add_proof(checksums, publisher_account)

        # Generating the did and adding to the ddo.
        did = ddo.assign_did(DID.did(ddo.proof['checksum']))
        logger.debug(f'Generating new did: {did}')
        # Check if it's already registered first!
        if did in self._get_metadata_provider().list_assets():
            raise DIDAlreadyExist(
                f'Asset id {did} is already registered to another asset.')

        for service in services:
            if service.type == ServiceTypes.ASSET_ACCESS:
                access_service = ServiceFactory.complete_access_service(
                    did, gateway.get_access_endpoint(self._config),
                    access_service_attributes,
                    self._keeper.access_template.address,
                    self._keeper.escrow_payment_condition.address)
                ddo.add_service(access_service)
            elif service.type == ServiceTypes.METADATA:
                ddo_service_endpoint = service.service_endpoint.replace(
                    '{did}', did)
                service.set_service_endpoint(ddo_service_endpoint)
                ddo.add_service(service)
            elif service.type == ServiceTypes.CLOUD_COMPUTE:
                compute_service = ServiceFactory.complete_compute_service(
                    did, service.service_endpoint, service.attributes,
                    self._keeper.compute_execution_condition.address,
                    self._keeper.escrow_payment_condition.address)
                ddo.add_service(compute_service)
            else:
                ddo.add_service(service)

        ddo.proof['signatureValue'] = self._keeper.sign_hash(
            add_ethereum_prefix_and_hash_msg(did_to_id_bytes(did)),
            publisher_account)

        # Add public key and authentication
        ddo.add_public_key(did, publisher_account.address)

        ddo.add_authentication(did, PUBLIC_KEY_TYPE_RSA)

        # Setup metadata service
        # First compute files_encrypted
        if metadata_copy['main']['type'] in ['dataset', 'algorithm']:
            assert metadata_copy['main'][
                'files'], 'files is required in the metadata main attributes.'
            logger.debug('Encrypting content urls in the metadata.')
            if not use_secret_store:
                encrypt_endpoint = gateway.get_encrypt_endpoint(self._config)
                files_encrypted = gateway.encrypt_files_dict(
                    metadata_copy['main']['files'], encrypt_endpoint,
                    ddo.asset_id, authorization_type)
            else:
                files_encrypted = self._get_secret_store(publisher_account) \
                    .encrypt_document(
                    did_to_id(did),
                    json.dumps(metadata_copy['main']['files']),
                )
            # only assign if the encryption worked
            if files_encrypted:
                logger.debug(
                    f'Content urls encrypted successfully {files_encrypted}')
                index = 0
                for file in metadata_copy['main']['files']:
                    file['index'] = index
                    index = index + 1
                    del file['url']
                metadata_copy['encryptedFiles'] = files_encrypted
            else:
                raise AssertionError('Encrypting the files failed.')

        # DDO url and `Metadata` service

        logger.debug(f'Generated ddo and services, DID is {ddo.did},'
                     f' metadata service @{ddo_service_endpoint}.')
        response = None

        # register on-chain
        registered_on_chain = self._keeper.did_registry.register(
            ddo.asset_id,
            checksum=Web3Provider.get_web3().toBytes(hexstr=ddo.asset_id),
            url=ddo_service_endpoint,
            account=publisher_account,
            cap=cap,
            royalties=royalties,
            providers=providers,
            activity_id=activity_id,
            attributes=attributes)
        if registered_on_chain is False:
            logger.warning(f'Registering {did} on-chain failed.')
            return None
        logger.info(f'Successfully registered DDO (DID={did}) on chain.')
        try:
            # publish the new ddo
            response = self._get_metadata_provider().publish_asset_ddo(ddo)
            logger.info('Asset/ddo published successfully in Metadata.')
        except ValueError as ve:
            raise ValueError(
                f'Invalid value to publish in the metadata: {str(ve)}')
        except Exception as e:
            logger.error(f'Publish asset in Metadata failed: {str(e)}')
        if not response:
            return None
        return ddo