Ejemplo n.º 1
0
def test_agreement_hash(ddo_sample):
    """
    This test verifies generating agreement hash using fixed inputs and ddo example.
    This will make it easier to compare the hash generated from different languages.
    """
    w3 = Web3
    did = "did:nv:0c184915b07b44c888d468be85a9b28253e80070e5294b1aaed81c2f0264e430"
    template_id = w3.toChecksumAddress(
        "0x00bd138abd70e2f00903268f3db08f2d25677c9e")
    agreement_id = '0xf136d6fadecb48fdb2fc1fb420f5a5d1c32d22d9424e47ab9461556e058fefaa'
    sa = ServiceAgreement.from_service_dict(
        ddo_sample.get_service(ServiceTypes.ASSET_ACCESS).as_dictionary())
    sa.service_agreement_template.set_template_id(template_id)
    assert template_id == sa.template_id, ''
    assert did == ddo_sample.did
    # Don't generate condition ids, use fixed ids so we get consistent hash
    # (access_id, lock_id, escrow_id) = sa.generate_agreement_condition_ids(
    #     agreement_id, ddo.asset_id, consumer, publisher, keeper)
    access_id = '0x2d7c1d60dc0c3f52aa9bd71ffdbe434a0e58435571e64c893bc9646fea7f6ec1'
    lock_id = '0x1e265c434c14e668695dda1555088f0ea4356f596bdecb8058812e7dcba9ee73'
    escrow_id = '0xe487fa6d435c2f09ef14b65b34521302f1532ac82ba8f6c86116acd8566e2da3'
    print(f'condition ids: \n'
          f'{access_id} \n'
          f'{lock_id} \n'
          f'{escrow_id}')
    agreement_hash = ServiceAgreement.generate_service_agreement_hash(
        sa.template_id, (access_id, lock_id, escrow_id),
        sa.conditions_timelocks, sa.conditions_timeouts, agreement_id,
        generate_multi_value_hash)
    print('agreement hash: ', agreement_hash.hex())
    expected = '0x96732b390dacec0f19ad304ac176b3407968a0184d01b3262687fd23a3f0995e'
    print('expected hash: ', expected)
    assert agreement_hash.hex() == expected, 'hash does not match.'
Ejemplo n.º 2
0
def test_nft_access(client, provider_account, consumer_account):
    keeper = keeper_instance()
    ddo = get_nft_ddo(provider_account, providers=[provider_account.address])
    asset_id = ddo.asset_id
    nft_amounts = 1

    keeper.nft_upgradeable.transfer_nft(asset_id, consumer_account.address,
                                        nft_amounts, provider_account)

    assert keeper.nft_upgradeable.balance(consumer_account.address,
                                          asset_id) >= nft_amounts

    nft_access_service_agreement = ServiceAgreement.from_ddo(
        ServiceTypes.NFT_ACCESS, ddo)
    agreement_id = ServiceAgreement.create_new_agreement_id()

    (nft_access_cond_id, nft_holder_cond_id
     ) = nft_access_service_agreement.generate_agreement_condition_ids(
         agreement_id, asset_id, consumer_account.address, keeper)

    print('NFT_ACCESS_DID: ' + asset_id)

    keeper.nft_access_template.create_agreement(
        agreement_id, asset_id, [nft_holder_cond_id, nft_access_cond_id],
        nft_access_service_agreement.conditions_timelocks,
        nft_access_service_agreement.conditions_timeouts,
        consumer_account.address, consumer_account)
    event = keeper.nft_access_template.subscribe_agreement_created(
        agreement_id, 15, None, (), wait=True, from_block=0)
    assert event, "Agreement event is not found, check the keeper node's logs"

    # generate the grant token
    grant_token = generate_access_grant_token(consumer_account,
                                              agreement_id,
                                              ddo.did,
                                              uri="/nft-access")

    # request access token
    response = client.post("/api/v1/gateway/services/oauth/token",
                           data={
                               "grant_type":
                               NeverminedJWTBearerGrant.GRANT_TYPE,
                               "assertion": grant_token
                           })
    access_token = response.get_json()["access_token"]
    index = 0
    endpoint = BaseURLs.ASSETS_URL + '/nft-access/%s/%d' % (agreement_id,
                                                            index)
    response = client.get(endpoint,
                          headers={"Authorization": f"Bearer {access_token}"})

    assert response.status == '200 OK'
    assert len(
        keeper.did_registry.get_provenance_method_events(
            'USED', did_bytes=did_to_id_bytes(ddo.did))) >= 1
Ejemplo n.º 3
0
    def access(service_agreement_id,
               service_index,
               ddo,
               consumer_account,
               destination,
               gateway,
               secret_store,
               config,
               index=None):
        """
        Download asset data files or result files from a compute job.

        :param service_agreement_id: Service agreement id, str
        :param service_index: identifier of the service inside the asset DDO, str
        :param ddo: DDO
        :param consumer_account: Account instance of the consumer
        :param destination: Path, str
        :param gateway: Gateway instance
        :param secret_store: SecretStore instance
        :param config: Sdk configuration instance
        :param index: Index of the document that is going to be downloaded, int
        :return: Asset folder path, str
        """
        did = ddo.did
        sa = ServiceAgreement.from_ddo(ServiceTypes.ASSET_ACCESS, ddo)
        consume_url = sa.service_endpoint
        if not consume_url:
            logger.error(
                'Consume asset failed, service definition is missing the "serviceEndpoint".'
            )
            raise AssertionError(
                'Consume asset failed, service definition is missing the "serviceEndpoint".'
            )

        if ddo.get_service(ServiceTypes.AUTHORIZATION):
            secret_store_service = ddo.get_service(
                service_type=ServiceTypes.AUTHORIZATION)
            secret_store_url = secret_store_service.service_endpoint
            secret_store.set_secret_store_url(secret_store_url)

        asset_folder = create_asset_folder(did, service_index, destination)

        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.')
            assert index < len(ddo.metadata['main']['files']), logger.error(
                'index can not be bigger than the number of files')
        if index is not None:
            gateway.access_service(did, service_agreement_id, consume_url,
                                   consumer_account, asset_folder, config,
                                   index)
        else:
            for i, _file in enumerate(ddo.metadata['main']['files']):
                gateway.access_service(did, service_agreement_id, consume_url,
                                       consumer_account, asset_folder, config,
                                       i)

        return asset_folder
Ejemplo n.º 4
0
def test_assets_consumed(publisher_instance, consumer_instance, ddo_sample):
    acct = consumer_instance.main_account
    consumed_assets = len(publisher_instance.assets.consumer_assets(acct.address))
    asset = create_asset(publisher_instance, ddo_sample)
    service = asset.get_service(service_type=ServiceTypes.ASSET_ACCESS)
    service_dict = service.as_dictionary()
    sa = ServiceAgreement.from_service_dict(service_dict)
    keeper = publisher_instance.keeper

    def grant_access(event, instance, agr_id, did, cons_address, account):
        instance.agreements.conditions.grant_access(
            agr_id, add_0x_prefix(did_to_id(did)), cons_address, account)

    agreement_id = consumer_instance.assets.order(
        asset.did, sa.index, acct, acct)
    keeper.lock_payment_condition.subscribe_condition_fulfilled(
        agreement_id,
        15,
        grant_access,
        (publisher_instance, agreement_id, asset.did,
         acct.address, publisher_instance.main_account),
        wait=True
    )

    keeper.access_condition.subscribe_condition_fulfilled(
        agreement_id,
        15,
        log_event(keeper.access_condition.FULFILLED_EVENT),
        (),
        wait=True
    )
    assert publisher_instance.agreements.is_access_granted(agreement_id, asset.did, acct.address)

    assert len(publisher_instance.assets.consumer_assets(acct.address)) == consumed_assets + 1
    publisher_instance.assets.retire(asset.did)
Ejemplo n.º 5
0
def test_consume(client, provider_account, consumer_account):
    endpoint = BaseURLs.ASSETS_URL + '/consume'

    for method in constants.ConfigSections.DECRYPTION_METHODS:
        print('Testing Consume with Authorization Method: ' + method)
        ddo = get_registered_ddo(provider_account,
                                 providers=[provider_account.address],
                                 auth_service=method)

        # initialize an agreement
        agreement_id = place_order(provider_account, ddo, consumer_account,
                                   ServiceTypes.ASSET_ACCESS)
        payload = dict({
            'serviceAgreementId': agreement_id,
            'consumerAddress': consumer_account.address
        })

        print('Provider: ' + provider_account.address)
        print('Consumer: ' + consumer_account.address)

        keeper = keeper_instance()
        agr_id_hash = add_ethereum_prefix_and_hash_msg(agreement_id)
        signature = keeper.sign_hash(agr_id_hash, consumer_account)
        index = 0

        event = keeper.access_template.subscribe_agreement_created(
            agreement_id, 15, None, (), wait=True, from_block=0)
        assert event, "Agreement event is not found, check the keeper node's logs"

        consumer_balance = keeper.token.get_token_balance(
            consumer_account.address)
        if consumer_balance < 50:
            keeper.dispenser.request_tokens(50 - consumer_balance,
                                            consumer_account)

        sa = ServiceAgreement.from_ddo(ServiceTypes.ASSET_ACCESS, ddo)
        lock_payment(agreement_id, ddo.asset_id, sa, amounts, receivers,
                     consumer_account)
        event = keeper.lock_payment_condition.subscribe_condition_fulfilled(
            agreement_id, 15, None, (), wait=True, from_block=0)
        assert event, "Lock reward condition fulfilled event is not found, check the keeper " \
                      "node's logs"

        grant_access(agreement_id, ddo, consumer_account, provider_account)
        event = keeper.access_condition.subscribe_condition_fulfilled(
            agreement_id, 15, None, (), wait=True, from_block=0)
        assert event or keeper.access_condition.check_permissions(
            ddo.asset_id, consumer_account.address
        ), f'Failed to get access permission: agreement_id={agreement_id}, ' \
           f'did={ddo.did}, consumer={consumer_account.address}'

        # Consume using url index and signature (let the gateway do the decryption)
        payload['signature'] = signature
        payload['index'] = index
        request_url = endpoint + '?' + '&'.join(
            [f'{k}={v}' for k, v in payload.items()])
        response = client.get(request_url)
        assert response.status == '200 OK'
Ejemplo n.º 6
0
def setup_nft_sales_agreements_environment():
    consumer_acc = get_consumer_account()
    publisher_acc = get_publisher_account()
    keeper = Keeper.get_instance()

    ddo = get_ddo_nft_sample()

    did_seed = generate_prefixed_id()
    asset_id = keeper.did_registry.hash_did(did_seed, publisher_acc.address)
    ddo._did = DID.did(asset_id)

    keeper.did_registry.register_mintable_did(
        did_seed,
        checksum=Web3Provider.get_web3().toBytes(hexstr=ddo.asset_id),
        url='http://172.17.0.1:5000',
        cap=10,
        royalties=10,
        account=publisher_acc,
        providers=None)

    keeper.did_registry.mint(ddo.asset_id, 10, account=publisher_acc)

    service_agreement = ServiceAgreement.from_ddo(ServiceTypes.NFT_SALES, ddo)
    agreement_id = ServiceAgreement.create_new_agreement_id()
    price = service_agreement.get_price()
    (access_cond_id, lock_cond_id,
     escrow_cond_id) = service_agreement.generate_agreement_condition_ids(
         agreement_id, asset_id, consumer_acc.address, keeper)

    nft_access_service_agreement = ServiceAgreement.from_ddo(
        ServiceTypes.NFT_ACCESS, ddo)
    nft_access_agreement_id = ServiceAgreement.create_new_agreement_id()

    (nft_access_cond_id, nft_holder_cond_id
     ) = nft_access_service_agreement.generate_agreement_condition_ids(
         nft_access_agreement_id, asset_id, consumer_acc.address, keeper)

    return (keeper, ddo, publisher_acc, consumer_acc, agreement_id,
            nft_access_agreement_id, asset_id, price, service_agreement,
            nft_access_service_agreement, (lock_cond_id, access_cond_id,
                                           escrow_cond_id),
            (nft_access_cond_id, nft_holder_cond_id))
Ejemplo n.º 7
0
 def order(self, did, index, consumer_account, account):
     agreement_id = ServiceAgreement.create_new_agreement_id()
     logger.debug(f'about to request create agreement: {agreement_id}')
     self._agreements.create(
         did,
         index,
         agreement_id,
         consumer_account.address,
         account
     )
     return agreement_id
Ejemplo n.º 8
0
    def prepare(self, did, consumer_account, service_index):
        """

        :param did: str representation fo the asset DID. Use this to retrieve the asset DDO.
        :param consumer_account: Account instance of the consumer
        :param service_index: int identifies the specific service in
         the ddo to use in this agreement.
        :return: tuple (agreement_id: str, signature: hex str)
        """
        agreement_id = ServiceAgreement.create_new_agreement_id()
        signature = self._sign(agreement_id, did, consumer_account, service_index)
        return agreement_id, signature
Ejemplo n.º 9
0
    def validate_nft_access(self, agreement_id, did, consumer_address):
        keeper = keeper_instance()

        asset = DIDResolver(keeper.did_registry).resolve(did)

        # check which nft access service type is on the ddo
        service_type = ServiceTypes.NFT_ACCESS
        if asset.get_service(ServiceTypes.NFT721_ACCESS) is not None:
            service_type = ServiceTypes.NFT721_ACCESS

        sa = ServiceAgreement.from_ddo(service_type, asset)
        return self._validate_nft_access(agreement_id, did, consumer_address, sa, service_type)
Ejemplo n.º 10
0
def test_store_and_retrieve_service(metadata_instance, json_service):
    agreement_id = ServiceAgreement.create_new_agreement_id()
    service = Service.from_json(json_service)

    # store the service agreement
    result = metadata_instance.store_service_agreement(agreement_id, service)
    assert result is True

    result = metadata_instance.get_service_agreement(agreement_id)
    assert result.type == service.type
    assert result.index == service.index
    assert result.service_endpoint == service.service_endpoint
    assert result.attributes == service.attributes
Ejemplo n.º 11
0
def place_order(provider_account,
                ddo,
                consumer_account,
                service_type=ServiceTypes.ASSET_ACCESS):
    keeper = keeper_instance()
    agreement_id = ServiceAgreement.create_new_agreement_id()

    if service_type == ServiceTypes.ASSET_ACCESS:
        agreement_template = keeper.access_template
    elif service_type == ServiceTypes.ASSET_ACCESS_PROOF:
        agreement_template = keeper.access_proof_template
    elif service_type == ServiceTypes.NFT_SALES:
        agreement_template = keeper.nft_sales_template
    elif service_type == ServiceTypes.CLOUD_COMPUTE:
        agreement_template = keeper.escrow_compute_execution_template
    else:
        raise NotImplementedError(
            "The agreement template could not be created.")

    publisher_address = provider_account.address

    service_agreement = ServiceAgreement.from_ddo(service_type, ddo)

    if service_type == ServiceTypes.ASSET_ACCESS_PROOF:
        consumer_pub = get_buyer_public_key()
        condition_ids = service_agreement.generate_agreement_condition_ids(
            agreement_id, ddo.asset_id, consumer_pub, keeper)
    else:
        condition_ids = service_agreement.generate_agreement_condition_ids(
            agreement_id, ddo.asset_id, consumer_account.address, keeper)

    time_locks = service_agreement.conditions_timelocks
    time_outs = service_agreement.conditions_timeouts
    agreement_template.create_agreement(agreement_id, ddo.asset_id,
                                        condition_ids, time_locks, time_outs,
                                        consumer_account.address,
                                        consumer_account)

    return agreement_id
Ejemplo n.º 12
0
    def complete_access_service(did,
                                service_endpoint,
                                attributes,
                                template_id,
                                reward_contract_address=None,
                                service_type=ServiceTypes.ASSET_ACCESS):
        """
        Build the access service.

        :param did: DID, str
        :param service_endpoint: identifier of the service inside the asset DDO, str
        :param template_id: id of the template use to create the service, str
        :param reward_contract_address: hex str ethereum address of deployed reward condition
            smart contract
        :return: ServiceAgreement
        """
        param_map = {
            '_documentId': did_to_id(did),
            '_amount': attributes['main']['price']
        }

        if reward_contract_address is not None:
            param_map['_rewardAddress'] = reward_contract_address

        try:
            param_map['_did'] = did_to_id(did)
            param_map['_amounts'] = attributes['main']['_amounts']
            param_map['_receivers'] = attributes['main']['_receivers']
            param_map['_tokenAddress'] = attributes['main']['_tokenAddress']
            param_map['_numberNfts'] = attributes['main']['_numberNfts']
        except KeyError as e:
            logger.error(f'Error mapping field {e}')

        sla_template_dict = get_sla_template(service_type)
        sla_template = ServiceAgreementTemplate(template_id, service_type,
                                                attributes['main']['creator'],
                                                sla_template_dict)
        sla_template.template_id = template_id
        conditions = sla_template.conditions[:]

        for cond in conditions:
            for param in cond.parameters:
                param.value = param_map.get(param.name, '')

            if cond.timeout > 0:
                cond.timeout = attributes['main']['timeout']

        sla_template.set_conditions(conditions)
        sa = ServiceAgreement(attributes, sla_template, service_endpoint,
                              service_type)
        return sa
Ejemplo n.º 13
0
    def _validate_nft_access(self, agreement_id, did, consumer_address, service_agreement, service_type):
        keeper = keeper_instance()

        asset = DIDResolver(keeper.did_registry).resolve(did)
        asset_id = asset.asset_id
        sa_name = service_agreement.main['name']
        erc721_address = service_agreement.get_param_value_by_name('_contractAddress')

        access_granted = False

        if agreement_id is None or agreement_id == '0x':
            if sa_name == 'nftAccessAgreement':
                access_granted = is_nft_holder(keeper, asset_id, service_agreement.get_number_nfts(), consumer_address)
            elif sa_name == 'nft721AccessAgreement':
                access_granted = is_nft721_holder(keeper, asset_id, consumer_address, erc721_address)
        else:
            agreement = keeper.agreement_manager.get_agreement(agreement_id)
            cond_ids = agreement.condition_ids
            access_cond_id = cond_ids[1]
            ddo = DIDResolver(keeper.did_registry).resolve(did)

            nft_access_service_agreement = ServiceAgreement.from_ddo(service_type, ddo)

            (nft_access_cond_id, nft_holder_cond_id) = nft_access_service_agreement.generate_agreement_condition_ids(agreement_id, asset_id, consumer_address, keeper)
            if [nft_holder_cond_id, nft_access_cond_id] != cond_ids:
                raise InvalidClientError(f"ServiceAgreement {agreement_id} doesn't match ddo")

            if not is_nft_access_condition_fulfilled(
                    agreement_id,
                    access_cond_id,
                    consumer_address,
                    keeper):
                # If not granted, verification of agreement and conditions and fulfill
                # access_granted = is_nft_holder(keeper, asset_id, sa.get_number_nfts(), consumer_address)
                access_granted = fulfill_nft_holder_and_access_condition(
                    keeper,
                    agreement_id,
                    cond_ids,
                    asset_id,
                    service_agreement.get_number_nfts(),
                    consumer_address,
                    self.provider_account
                )
        if not access_granted:
            msg = ('Checking access permissions failed. Either consumer address does not have '
                   'permission to consume this NFT or consumer address and/or service '
                   'agreement '
                   'id is invalid.')
            logger.warning(msg)
            raise InvalidClientError(msg)
Ejemplo n.º 14
0
 def _read_dict(self, dictionary):
     """Import a JSON dict into this DDO."""
     values = dictionary
     self._did = values['id']
     self._created = values.get('created', None)
     if 'publicKey' in values:
         self._public_keys = []
         for value in values['publicKey']:
             if isinstance(value, str):
                 value = json.loads(value)
             self._public_keys.append(
                 DDO.create_public_key_from_json(value))
     if 'authentication' in values:
         self._authentications = []
         for value in values['authentication']:
             if isinstance(value, str):
                 value = json.loads(value)
             self._authentications.append(
                 DDO.create_authentication_from_json(value))
     if 'service' in values:
         self._services = []
         for value in values['service']:
             if isinstance(value, str):
                 value = json.loads(value)
             if value['type'] == ServiceTypes.ASSET_ACCESS:
                 service = ServiceAgreement.from_service_dict(value)
             elif value['type'] == ServiceTypes.ASSET_ACCESS_PROOF:
                 service = ServiceAgreement.from_service_dict(value)
             elif value['type'] == ServiceTypes.CLOUD_COMPUTE:
                 service = ServiceAgreement.from_service_dict(value)
             elif value['type'] == ServiceTypes.NFT_SALES:
                 service = ServiceAgreement.from_service_dict(value)
             else:
                 service = Service.from_json(value)
             self._services.append(service)
     if 'proof' in values:
         self._proof = values['proof']
Ejemplo n.º 15
0
def test_access_endpoint_bad_signature(client, provider_account,
                                       consumer_account):
    # The provider_account will place the order and consumer_account
    # will try to request access to it

    # order access
    keeper = keeper_instance()
    ddo = get_registered_ddo(provider_account,
                             providers=[provider_account.address])
    agreement_id = place_order(provider_account, ddo, provider_account)

    event = keeper.access_template.subscribe_agreement_created(agreement_id,
                                                               15,
                                                               None, (),
                                                               wait=True,
                                                               from_block=0)
    assert event, "Agreement event is not found, check the keeper node's logs"

    consumer_balance = keeper.token.get_token_balance(consumer_account.address)
    if consumer_balance < 50:
        keeper.dispenser.request_tokens(50 - consumer_balance,
                                        consumer_account)

    sa = ServiceAgreement.from_ddo(ServiceTypes.ASSET_ACCESS, ddo)
    lock_payment(agreement_id, ddo.asset_id, sa, amounts, receivers,
                 consumer_account)

    event = keeper.lock_payment_condition.subscribe_condition_fulfilled(
        agreement_id, 15, None, (), wait=True, from_block=0)
    assert event, "Lock reward condition fulfilled event is not found, check the keeper node's logs"

    # create jwt bearer grant
    jwk = account_to_jwk(consumer_account)
    assertion = NeverminedJWTBearerGrant.sign(jwk,
                                              issuer=consumer_account.address,
                                              audience=BaseURLs.ASSETS_URL +
                                              '/access',
                                              subject=agreement_id,
                                              claims={"did": ddo.did},
                                              header={"alg": "ES256K"})

    response = client.post("/api/v1/gateway/services/oauth/token",
                           data={
                               "grant_type":
                               NeverminedJWTBearerGrant.GRANT_TYPE,
                               "assertion": assertion
                           })
    assert response.status_code == 400
    assert response.get_json()["error"] == "invalid_client"
Ejemplo n.º 16
0
def setup_did_sales_agreements_environment():
    consumer_acc = get_consumer_account()
    publisher_acc = get_publisher_account()
    keeper = Keeper.get_instance()

    ddo = get_ddo_did_sales_sample()

    did_seed = generate_prefixed_id()
    asset_id = keeper.did_registry.hash_did(did_seed, publisher_acc.address)
    ddo._did = DID.did(asset_id)

    keeper.did_registry.register(
        did_seed,
        checksum=Web3Provider.get_web3().toBytes(hexstr=ddo.asset_id),
        url='metadata:5000',
        account=publisher_acc,
        providers=None)

    service_agreement = ServiceAgreement.from_ddo(ServiceTypes.DID_SALES, ddo)
    agreement_id = ServiceAgreement.create_new_agreement_id()
    price = service_agreement.get_price()
    (access_cond_id, lock_cond_id,
     escrow_cond_id) = service_agreement.generate_agreement_condition_ids(
         agreement_id, asset_id, consumer_acc.address, keeper)

    return (
        keeper,
        ddo,
        publisher_acc,
        consumer_acc,
        agreement_id,
        asset_id,
        price,
        service_agreement,
        (lock_cond_id, access_cond_id, escrow_cond_id),
    )
Ejemplo n.º 17
0
def setup_agreements_environment(ddo_sample):
    consumer_acc = get_consumer_account()
    publisher_acc = get_publisher_account()
    keeper = Keeper.get_instance()

    ddo = ddo_sample
    ddo._did = DID.did({"0": generate_prefixed_id()})

    keeper.did_registry.register(
        ddo.asset_id,
        checksum=Web3Provider.get_web3().toBytes(hexstr=ddo.asset_id),
        url='localhost:5000',
        account=publisher_acc,
        providers=None
    )

    registered_ddo = ddo
    asset_id = registered_ddo.asset_id
    service_agreement = ServiceAgreement.from_ddo(ServiceTypes.ASSET_ACCESS, ddo)
    agreement_id = ServiceAgreement.create_new_agreement_id()
    price = service_agreement.get_price()
    access_cond_id, lock_cond_id, escrow_cond_id = \
        service_agreement.generate_agreement_condition_ids(
            agreement_id, asset_id, consumer_acc.address, publisher_acc.address, keeper
        )

    return (
        keeper,
        publisher_acc,
        consumer_acc,
        agreement_id,
        asset_id,
        price,
        service_agreement,
        (lock_cond_id, access_cond_id, escrow_cond_id),
    )
Ejemplo n.º 18
0
def test_execute_endpoint(client, provider_account, consumer_account):
    ddo_compute = get_registered_compute_ddo(
        provider_account, providers=[provider_account.address])
    ddo_algorithm = get_registered_algorithm_ddo(
        consumer_account, providers=[provider_account.address])
    ddo_workflow = get_registered_workflow_ddo(
        consumer_account,
        ddo_compute.did,
        ddo_algorithm.did,
        providers=[provider_account.address])

    # initialize agreement
    agreement_id = place_order(provider_account,
                               ddo_compute,
                               consumer_account,
                               service_type=ServiceTypes.CLOUD_COMPUTE)
    sa = ServiceAgreement.from_ddo(ServiceTypes.CLOUD_COMPUTE, ddo_compute)
    lock_payment(agreement_id, ddo_compute.asset_id, sa, amounts, receivers,
                 consumer_account)

    keeper = keeper_instance()
    event = keeper.lock_payment_condition.subscribe_condition_fulfilled(
        agreement_id, 60, None, (), wait=True)
    assert event is not None, "Reward condition is not found"

    # create jwt bearer grant
    jwk = account_to_jwk(consumer_account)
    assertion = NeverminedJWTBearerGrant.sign(jwk,
                                              issuer=consumer_account.address,
                                              subject=agreement_id,
                                              audience=BaseURLs.ASSETS_URL +
                                              '/execute',
                                              claims={"did": ddo_workflow.did},
                                              header={"alg": "ES256K"})

    response = client.post("/api/v1/gateway/services/oauth/token",
                           data={
                               "grant_type":
                               NeverminedJWTBearerGrant.GRANT_TYPE,
                               "assertion": assertion
                           })
    assert response.status_code == 200

    # use jwt access token to execute the compute
    access_token = response.get_json()["access_token"]
    response = client.post(f"/api/v1/gateway/services/execute/{agreement_id}",
                           headers={"Authorization": f"Bearer {access_token}"})
    assert response.status_code == 200
Ejemplo n.º 19
0
def test_agreement():
    template_id = Web3.toChecksumAddress('0x' + ('f' * 40))
    agreement_id = '0x' + ('e' * 64)
    access_id = '0x' + ('a' * 64)
    lock_id = '0x' + ('b' * 64)
    escrow_id = '0x' + ('c' * 64)

    signature = ServiceAgreement.generate_service_agreement_hash(
        template_id, [access_id, lock_id, escrow_id], [0, 0, 0], [0, 0, 0],
        agreement_id, generate_multi_value_hash)

    print({signature})
    assert (signature == Web3.toBytes(
        hexstr=
        "0x67901517c18a3d23e05806fff7f04235cc8ae3b1f82345b8bfb3e4b02b5800c7")
            ), "The signature is not correct."
Ejemplo n.º 20
0
def test_compute_logs(publisher_instance_no_init, consumer_instance_no_init,
                      metadata, algorithm_ddo, workflow_ddo):
    consumer = publisher_instance_no_init.main_account
    publisher = consumer_instance_no_init.main_account

    # publish compute
    ddo_computing = publisher_instance_no_init.assets.create_compute(
        metadata, publisher)

    # publish algorithm
    metadata = algorithm_ddo['service'][0]
    ddo_algorithm = consumer_instance_no_init.assets.create(
        metadata['attributes'], consumer)

    metadata = workflow_ddo['service'][0]
    metadata['attributes']['main']['workflow']['stages'][0]['input'][0][
        'id'] = ddo_computing.did
    metadata['attributes']['main']['workflow']['stages'][0]['transformation'][
        'id'] = ddo_algorithm.did
    workflow_ddo = consumer_instance_no_init.assets.create(
        metadata['attributes'], publisher)
    assert workflow_ddo

    # order compute asset
    service = ddo_computing.get_service(
        service_type=ServiceTypes.CLOUD_COMPUTE)
    sa = ServiceAgreement.from_service_dict(service.as_dictionary())
    agreement_id = consumer_instance_no_init.assets.order(
        ddo_computing.did, sa.index, consumer, consumer)

    keeper = Keeper.get_instance()
    event = keeper.lock_payment_condition.subscribe_condition_fulfilled(
        agreement_id, 60, None, (), wait=True)
    assert event is not None, "Reward condition is not found"

    # execute workflow
    execution_id = consumer_instance_no_init.assets.execute(
        agreement_id, ddo_computing.did, sa.index, consumer, workflow_ddo.did)

    # get logs
    logs = consumer_instance_no_init.assets.compute_logs(
        agreement_id, execution_id, consumer)
    assert logs

    publisher_instance_no_init.assets.retire(ddo_computing.did)
    publisher_instance_no_init.assets.retire(ddo_algorithm.did)
    publisher_instance_no_init.assets.retire(workflow_ddo.did)
Ejemplo n.º 21
0
    def execute(agreement_id, compute_ddo, workflow_ddo, consumer_account,
                gateway, index, config):
        """

        :param agreement_id:
        :param workflow_ddo:
        :param consumer_account:
        :param index:
        :return: the id of the compute job
        """
        service_endpoint = ServiceAgreement.from_ddo(
            ServiceTypes.CLOUD_COMPUTE, compute_ddo).service_endpoint
        response = gateway.execute_compute_service(agreement_id,
                                                   service_endpoint,
                                                   consumer_account,
                                                   workflow_ddo, config)

        return response.json()["workflowId"]
Ejemplo n.º 22
0
    def complete_compute_service(did, service_endpoint, attributes,
                                 template_id, reward_contract_address):
        """
        Build the access service.

        :param did: DID, str
        :param service_endpoint: identifier of the service inside the asset DDO, str
        :param template_id: id of the template use to create the service, str
        :param reward_contract_address: hex str ethereum address of deployed reward condition
            smart contract
        :return: ServiceAgreement
        """
        param_map = {
            '_documentId': did_to_id(did),
            '_amount': attributes['main']['price'],
            '_rewardAddress': reward_contract_address
        }

        try:
            param_map['_amounts'] = attributes['main']['_amounts']
            param_map['_receivers'] = attributes['main']['_receivers']
        except KeyError:
            pass

        sla_template_dict = get_sla_template(ServiceTypes.CLOUD_COMPUTE)
        sla_template = ServiceAgreementTemplate(template_id,
                                                ServiceTypes.CLOUD_COMPUTE,
                                                attributes['main']['creator'],
                                                sla_template_dict)
        sla_template.template_id = template_id
        conditions = sla_template.conditions[:]
        for cond in conditions:
            for param in cond.parameters:
                param.value = param_map.get(param.name, '')

            if cond.timeout > 0:
                cond.timeout = attributes['main']['timeout']

        sla_template.set_conditions(conditions)
        sa = ServiceAgreement(attributes, sla_template, service_endpoint,
                              ServiceTypes.CLOUD_COMPUTE)
        return sa
Ejemplo n.º 23
0
def test_nfts_flow(publisher_instance_no_init, consumer_instance_no_init):
    config = ExampleConfig.get_config()
    ConfigProvider.set_config(config)
    keeper = Keeper.get_instance()

    pub_acc = get_publisher_account()

    # Register ddo
    ddo = get_registered_ddo_nft(publisher_instance_no_init, pub_acc)
    asset_id = ddo.asset_id
    nft_amounts = 1
    assert isinstance(ddo, DDO)

    consumer_account = get_consumer_account()

    consumer_instance_no_init.accounts.request_tokens(consumer_account, 100)

    service_sales = ddo.get_service(service_type=ServiceTypes.NFT_SALES)
    sa_sales = ServiceAgreement.from_service_dict(
        service_sales.as_dictionary())

    amounts = sa_sales.get_amounts_int()
    receivers = sa_sales.get_receivers()
    number_nfts = sa_sales.get_number_nfts()
    token_address = keeper.token.address

    sales_agreement_id = consumer_instance_no_init.assets.order(
        ddo.did, sa_sales.index, consumer_account, consumer_account)

    sales_agreement = keeper.agreement_manager.get_agreement(
        sales_agreement_id)
    assert sales_agreement.did == asset_id, ''

    lock_cond_id = sales_agreement.condition_ids[0]
    access_cond_id = sales_agreement.condition_ids[1]
    escrow_cond_id = sales_agreement.condition_ids[2]

    # transfer the nft
    keeper.transfer_nft_condition.fulfill(sales_agreement_id, asset_id,
                                          consumer_account.address,
                                          nft_amounts, lock_cond_id, pub_acc)

    # escrow payment
    keeper.escrow_payment_condition.fulfill(
        sales_agreement_id, asset_id, amounts, receivers,
        keeper.escrow_payment_condition.address, token_address, lock_cond_id,
        access_cond_id, pub_acc)

    assert keeper.condition_manager.get_condition_state(lock_cond_id) == 2, ''
    assert keeper.condition_manager.get_condition_state(
        access_cond_id) == 2, ''
    assert keeper.condition_manager.get_condition_state(
        escrow_cond_id) == 2, ''

    assert keeper.did_registry.balance(consumer_account.address,
                                       asset_id) >= number_nfts

    # CHECK ACCESS CREATING THE AGREEMENT
    nft_access_service_agreement = ServiceAgreement.from_ddo(
        ServiceTypes.NFT_ACCESS, ddo)
    sa_access = ddo.get_service(service_type=ServiceTypes.NFT_ACCESS)
    nft_access_agreement_id = consumer_instance_no_init.assets.order(
        ddo.did, sa_access.index, consumer_account, consumer_account)

    event = keeper.nft_access_template.subscribe_agreement_created(
        nft_access_agreement_id,
        10,
        log_event(keeper.nft_access_template.AGREEMENT_CREATED_EVENT), (),
        wait=True)
    assert event, 'no event for AgreementCreated '

    time.sleep(3)
    keeper.nft_holder_condition.fulfill(nft_access_agreement_id, asset_id,
                                        consumer_account.address, number_nfts,
                                        consumer_account)
    time.sleep(3)
    keeper.nft_access_condition.fulfill(nft_access_agreement_id, asset_id,
                                        consumer_account.address, pub_acc)
    time.sleep(3)

    access_agreement = keeper.agreement_manager.get_agreement(
        nft_access_agreement_id)
    assert access_agreement.did == asset_id, ''

    nft_holder_cond_id = access_agreement.condition_ids[0]
    nft_access_cond_id = access_agreement.condition_ids[1]

    assert keeper.condition_manager.get_condition_state(
        nft_access_cond_id) == 2, ''
    assert keeper.condition_manager.get_condition_state(
        nft_holder_cond_id) == 2, ''

    # AND HERE TESTING WITHOUT CREATING THE AGREEMENT
    service_access = ddo.get_service(service_type=ServiceTypes.NFT_ACCESS)

    no_agreement_id = '0x'

    assert consumer_instance_no_init.assets.access(
        no_agreement_id,
        ddo.did,
        service_access.index,
        consumer_account,
        config.downloads_path,
        service_type=ServiceTypes.NFT_ACCESS)

    # AND HERE CHECKING CREATING AN AGREEMENT FIRST
    nft_access_service_agreement = ServiceAgreement.from_ddo(
        ServiceTypes.NFT_ACCESS, ddo)
    nft_access_agreement_id = ServiceAgreement.create_new_agreement_id()
    (nft_access_cond_id, nft_holder_cond_id
     ) = nft_access_service_agreement.generate_agreement_condition_ids(
         nft_access_agreement_id, asset_id, consumer_account.address, keeper)

    keeper.nft_access_template.create_agreement(
        nft_access_agreement_id, asset_id,
        [nft_holder_cond_id, nft_access_cond_id],
        nft_access_service_agreement.conditions_timelocks,
        nft_access_service_agreement.conditions_timeouts,
        consumer_account.address, pub_acc)

    event = keeper.nft_access_template.subscribe_agreement_created(
        nft_access_agreement_id,
        10,
        log_event(keeper.nft_access_template.AGREEMENT_CREATED_EVENT), (),
        wait=True)
    assert event, 'no event for AgreementCreated '

    # This is because in this test the gateway is executed using the same account than the consumer
    keeper.did_registry.add_provider(asset_id, consumer_account.address,
                                     pub_acc)
    time.sleep(3)

    assert consumer_instance_no_init.assets.access(
        nft_access_agreement_id,
        ddo.did,
        service_access.index,
        consumer_account,
        config.downloads_path,
        index=0,
        service_type=ServiceTypes.NFT_ACCESS)
Ejemplo n.º 24
0
def test_access_proof(client, provider_account, consumer_account):
    for method in constants.ConfigSections.DECRYPTION_METHODS:
        ddo = get_proof_ddo(provider_account,
                            providers=[provider_account.address],
                            auth_service=method)

        # initialize an agreement
        agreement_id = place_order(provider_account, ddo, consumer_account,
                                   ServiceTypes.ASSET_ACCESS_PROOF)

        print(ddo.did)

        keeper = keeper_instance()
        index = 0

        event = keeper.access_proof_template.subscribe_agreement_created(
            agreement_id, 15, None, (), wait=True, from_block=0)
        assert event, "Agreement event is not found, check the keeper node's logs"

        consumer_balance = keeper.token.get_token_balance(
            consumer_account.address)
        if consumer_balance < 50:
            keeper.dispenser.request_tokens(50 - consumer_balance,
                                            consumer_account)

        sa = ServiceAgreement.from_ddo(ServiceTypes.ASSET_ACCESS_PROOF, ddo)
        lock_payment(agreement_id, ddo.asset_id, sa, amounts, receivers,
                     consumer_account)
        event = keeper.lock_payment_condition.subscribe_condition_fulfilled(
            agreement_id, 15, None, (), wait=True, from_block=0)
        assert event, "Lock reward condition fulfilled event is not found, check the keeper node's logs"

        # Consume using url index

        # generate the grant token
        grant_token = generate_access_proof_grant_token(
            consumer_account, agreement_id, ddo.did, get_buyer_secret_key(),
            "/access-proof")

        # request access token
        response = client.post("/api/v1/gateway/services/oauth/token",
                               data={
                                   "grant_type":
                                   NeverminedJWTBearerGrant.GRANT_TYPE,
                                   "assertion": grant_token
                               })
        access_token = response.get_json()["access_token"]

        agreement = keeper.agreement_manager.get_agreement(agreement_id)
        cond_ids = agreement.condition_ids
        assert keeper.condition_manager.get_condition_state(
            cond_ids[0]) == ConditionState.Fulfilled.value
        assert keeper.condition_manager.get_condition_state(
            cond_ids[1]) == ConditionState.Fulfilled.value
        assert keeper.condition_manager.get_condition_state(
            cond_ids[2]) == ConditionState.Fulfilled.value

        endpoint = BaseURLs.ASSETS_URL + '/access-proof/%s/%d' % (agreement_id,
                                                                  index)
        response = client.get(
            endpoint, headers={"Authorization": f"Bearer {access_token}"})

        assert response.status == '200 OK'
        assert len(
            keeper.did_registry.get_provenance_method_events(
                'USED', did_bytes=did_to_id_bytes(ddo.did))) == 1
Ejemplo n.º 25
0
def test_sign_agreement(publisher_instance, consumer_instance, registered_ddo):
    # point consumer_instance's Gateway mock to the publisher's nevermined instance
    Gateway.set_http_client(
        GatewayMock(publisher_instance, publisher_instance.main_account))

    consumer_acc = consumer_instance.main_account
    keeper = Keeper.get_instance()

    publisher_acc = publisher_instance.main_account

    did = registered_ddo.did
    asset_id = registered_ddo.asset_id
    ddo = consumer_instance.assets.resolve(did)
    service_agreement = ServiceAgreement.from_ddo(ServiceTypes.ASSET_ACCESS,
                                                  ddo)

    price = service_agreement.get_price()

    # Give consumer some tokens
    keeper.dispenser.request_vodkas(price * 2, consumer_acc)

    agreement_id, signature = consumer_instance.agreements.prepare(
        did, consumer_acc, ServiceTypesIndices.DEFAULT_ACCESS_INDEX)

    success = publisher_instance.agreements.create(
        did, ServiceTypesIndices.DEFAULT_ACCESS_INDEX, agreement_id,
        consumer_acc.address, publisher_acc)
    assert success, 'createAgreement failed.'

    # Verify condition types (condition contracts)
    agreement_values = keeper.agreement_manager.get_agreement(agreement_id)
    assert agreement_values.did == asset_id, ''
    cond_types = keeper.access_template.get_condition_types()
    for i, cond_id in enumerate(agreement_values.condition_ids):
        cond = keeper.condition_manager.get_condition(cond_id)
        assert cond.type_ref == cond_types[i]

    access_cond_id, lock_cond_id, escrow_cond_id = agreement_values.condition_ids

    # Fulfill lock_payment_condition is done automatically when create agreement is done correctly
    assert 2 == keeper.condition_manager.get_condition_state(lock_cond_id), ''
    assert 1 == keeper.condition_manager.get_condition_state(
        access_cond_id), ''
    assert 1 == keeper.condition_manager.get_condition_state(
        escrow_cond_id), ''

    # Fulfill access_condition
    tx_hash = keeper.access_condition.fulfill(agreement_id, asset_id,
                                              consumer_acc.address,
                                              publisher_acc)
    keeper.access_condition.get_tx_receipt(tx_hash)
    assert 2 == keeper.condition_manager.get_condition_state(
        access_cond_id), ''
    event = keeper.access_condition.subscribe_condition_fulfilled(
        agreement_id,
        10,
        log_event(keeper.access_condition.FULFILLED_EVENT), (),
        wait=True)
    assert event, 'no event for AccessSecretStoreCondition.Fulfilled'

    # Fulfill escrow_payment_condition

    amounts = service_agreement.get_amounts_int()
    receivers = service_agreement.get_receivers()

    tx_hash = keeper.escrow_payment_condition.fulfill(
        agreement_id, asset_id, amounts, receivers,
        keeper.escrow_payment_condition.address, lock_cond_id, access_cond_id,
        publisher_acc)
    keeper.escrow_payment_condition.get_tx_receipt(tx_hash)
    assert 2 == keeper.condition_manager.get_condition_state(
        escrow_cond_id), ''
    event = keeper.escrow_payment_condition.subscribe_condition_fulfilled(
        agreement_id,
        10,
        log_event(keeper.escrow_payment_condition.FULFILLED_EVENT), (),
        wait=True)
    assert event, 'no event for EscrowReward.Fulfilled'
    publisher_instance.assets.retire(did)
Ejemplo n.º 26
0
    def create(self, did, index, agreement_id, consumer_address, account):
        """
        Execute the service agreement on-chain using keeper's ServiceAgreement contract.

        The on-chain executeAgreement method requires the following arguments:
        templateId, signature, consumer, hashes, timeouts, serviceAgreementId, did.
        `agreement_message_hash` is necessary to verify the signature.
        The consumer `signature` includes the conditions timeouts and parameters values which
        is usedon-chain to verify that the values actually match the signed hashes.

        :param did: str representation fo the asset DID. Use this to retrieve the asset DDO.
        :param index: str identifies the specific service in
         the ddo to use in this agreement.
        :param agreement_id: 32 bytes identifier created by the consumer and will be used
         on-chain for the executed agreement.
         conditions and their parameters values and other details of the agreement.
        :param consumer_address: ethereum account address of consumer, hex str
        :param account: Account instance creating the agreement. Can be either the
            consumer, publisher or provider
        :return: dict the `executeAgreement` transaction receipt
        """
        assert consumer_address and Web3Provider.get_web3().isChecksumAddress(
            consumer_address), f'Invalid consumer address {consumer_address}'
        assert account.address in self._keeper.accounts, \
            f'Unrecognized account address {account.address}'

        payment_involved = True
        asset = self._asset_resolver.resolve(did)
        asset_id = asset.asset_id
        service = asset.get_service_by_index(index)
        if service.type == ServiceTypes.ASSET_ACCESS:
            agreement_template = self._keeper.access_template
            template_address = self._keeper.access_template.address
        elif service.type == ServiceTypes.CLOUD_COMPUTE:
            agreement_template = self._keeper.escrow_compute_execution_template
            template_address = self._keeper.escrow_compute_execution_template.address
        elif service.type == ServiceTypes.NFT_SALES:
            agreement_template = self._keeper.nft_sales_template
            template_address = self._keeper.nft_sales_template.address
        elif service.type == ServiceTypes.NFT_ACCESS:
            payment_involved = False
            agreement_template = self._keeper.nft_access_template
            template_address = self._keeper.nft_access_template.address
        else:
            raise Exception('The agreement could not be created. Review the index of your service.')

        agreement_template_approved = self._keeper.template_manager.is_template_approved(template_address)
        if not agreement_template_approved:
            msg = (f'The Service Agreement Template contract at address '
                   f'{template_address} is not '
                   f'approved and cannot be used for creating service agreements.')
            logger.warning(msg)
            raise InvalidAgreementTemplate(msg)

        if agreement_template.get_agreement_consumer(agreement_id) != ZERO_ADDRESS:
            raise ServiceAgreementExists(
                f'Service agreement {agreement_id} already exists, cannot reuse '
                f'the same agreement id.')

        service_agreement = ServiceAgreement.from_service_index(index, asset)
        token_address = check_token_address(
            self._keeper, service_agreement.get_param_value_by_name('_tokenAddress'))

        publisher_address = Web3Provider.get_web3().toChecksumAddress(asset.publisher)
        condition_ids = service_agreement.generate_agreement_condition_ids(
            agreement_id, asset_id, consumer_address, self._keeper, token_address=token_address)

        time_locks = service_agreement.conditions_timelocks
        time_outs = service_agreement.conditions_timeouts

        if payment_involved and service_agreement.get_price() > self._keeper.token.get_token_balance(consumer_address):
            return Exception(
                f'The consumer balance is '
                f'{self._keeper.token.get_token_balance(consumer_address)}. '
                f'This balance is lower that the asset price {service_agreement.get_price()}.')

        if service.type == ServiceTypes.NFT_SALES:
            conditions_ordered = [condition_ids[1], condition_ids[0], condition_ids[2]]
        elif service.type == ServiceTypes.NFT_ACCESS:
            conditions_ordered = [condition_ids[1], condition_ids[0]]
        else:
            conditions_ordered = condition_ids

        success = agreement_template.create_agreement(
            agreement_id,
            asset_id,
            conditions_ordered,
            time_locks,
            time_outs,
            consumer_address,
            account
        )

        if success:
            if payment_involved:
                self.conditions.lock_payment(
                    agreement_id,
                    asset_id,
                    service_agreement.get_amounts_int(),
                    service_agreement.get_receivers(),
                    token_address,
                    account)
                return self._is_condition_fulfilled(agreement_id, 'lockReward')
            return True
        return False
Ejemplo n.º 27
0
def demo():
    """The Nevermined Federated Learning demo.

    This demo showcases the nevermined Federated Learning capabilities.
    FLow:
        1. Setup nevermined
        2. Setup accounts
        3. Publish compute to the data assets
        4. Publish algorithm
        5. Publish workflows
        6. Order computations
        7. Execute workflows

    """

    print("Setting up...\n")

    date_created = dates_generator()

    # 1. Setup nevermined
    nevermined = Nevermined(Config("config.ini"))
    keeper = Keeper.get_instance()
    provider = "0x068Ed00cF0441e4829D9784fCBe7b9e26D4BD8d0"

    # 2. Setup accounts
    acc = Account(Web3.toChecksumAddress(PARITY_ADDRESS), PARITY_PASSWORD,
                  PARITY_KEYFILE)
    nevermined.accounts.request_tokens(acc, 100)
    provider_data0 = acc
    provider_data1 = acc
    provider_coordinator = acc
    consumer = acc

    # 3. Publish compute to the data
    with open("resources/metadata/metadata0.json") as f:
        metadata_data0 = json.load(f)
        metadata_data0["main"]["dateCreated"] = next(date_created)
    with open("resources/metadata/metadata1.json") as f:
        metadata_data1 = json.load(f)
        metadata_data1["main"]["dateCreated"] = next(date_created)

    ddo_compute0 = nevermined.assets.create_compute(
        metadata_data0,
        provider_data0,
        providers=[provider],
    )
    assert ddo_compute0 is not None, "Creating asset compute0 on-chain failed"
    print(
        f"[DATA_PROVIDER0 --> NEVERMINED] Publishing compute to the data asset for asset0: {ddo_compute0.did}"
    )

    ddo_compute1 = nevermined.assets.create_compute(
        metadata_data1,
        provider_data1,
        providers=[provider],
    )
    assert ddo_compute1 is not None, "Creating asset compute1 on-chain failed"
    print(
        f"[DATA_PROVIDER1 --> NEVERMINED] Publishing compute to the data asset for asset1: {ddo_compute1.did}"
    )

    with open("resources/metadata/metadata_compute_coordinator.json") as f:
        metadata_compute_coordinator = json.load(f)
        metadata_compute_coordinator["main"]["dateCreated"] = next(
            date_created)

    ddo_compute_coordinator = nevermined.assets.create_compute(
        metadata_compute_coordinator,
        provider_coordinator,
        providers=[provider],
    )
    assert (ddo_compute_coordinator
            is not None), "Creating asset compute_coordinator on-chain failed"
    print(
        f"[COORDINATOR_PROVIDER --> NEVERMINED] Publishing coordinator compute asset: {ddo_compute_coordinator.did}"
    )

    # 4. Publish algorithm
    with open("resources/metadata/metadata_transformation.json") as f:
        metadata_transformation = json.load(f)
        metadata_transformation["main"]["dateCreated"] = next(date_created)

    ddo_transformation = nevermined.assets.create(
        metadata_transformation,
        consumer,
        providers=[provider],
    )
    assert (ddo_transformation
            is not None), "Creating asset transformation on-chain failed"
    print(
        f"[DATA_SCIENTIST --> NEVERMINED] Publishing algorithm asset: {ddo_transformation.did}"
    )

    # 5. Publish the workflows
    with open("resources/metadata/metadata_workflow.json") as f:
        metadata_workflow = json.load(f)
    with open("resources/metadata/metadata_workflow_coordinator.json") as f:
        metadata_workflow_coordinator = json.load(f)

    metadata_workflow0 = copy.deepcopy(metadata_workflow)
    metadata_workflow0["main"]["workflow"]["stages"][0]["input"][0][
        "id"] = ddo_compute0.did
    metadata_workflow0["main"]["workflow"]["stages"][0]["transformation"][
        "id"] = ddo_transformation.did

    metadata_workflow1 = copy.deepcopy(metadata_workflow)
    metadata_workflow1["main"]["workflow"]["stages"][0]["input"][0][
        "id"] = ddo_compute1.did
    metadata_workflow1["main"]["workflow"]["stages"][0]["transformation"][
        "id"] = ddo_transformation.did

    metadata_workflow_coordinator["main"]["dateCreated"] = next(date_created)

    ddo_workflow0 = nevermined.assets.create(
        metadata_workflow0,
        consumer,
        providers=[provider],
    )
    assert ddo_workflow0 is not None, "Creating asset workflow0 on-chain failed"
    print(
        f"[DATA_SCIENTIST --> NEVERMINED] Publishing compute workflow for asset0: {ddo_workflow0.did}"
    )

    ddo_workflow1 = nevermined.assets.create(
        metadata_workflow1,
        consumer,
        providers=[provider],
    )
    assert ddo_workflow1 is not None, "Creating asset workflow1 on-chain failed"
    print(
        f"[DATA_SCIENTIST --> NEVERMINED] Publishing compute workflow for asset1: {ddo_workflow1.did}"
    )

    ddo_workflow_coordinator = nevermined.assets.create(
        metadata_workflow_coordinator,
        consumer,
        providers=[provider],
    )
    assert (ddo_workflow_coordinator
            is not None), "Creating asset workflow_coordinator on-chain failed"
    print(
        f"[DATA_SCIENTIST --> NEVERMINED] Publishing compute workflow for coordinator: {ddo_workflow_coordinator.did}"
    )

    # 6. Order computations
    service0 = ddo_compute0.get_service(
        service_type=ServiceTypes.CLOUD_COMPUTE)
    service_agreement0 = ServiceAgreement.from_service_dict(
        service0.as_dictionary())
    agreement_id0 = nevermined.assets.order(ddo_compute0.did,
                                            service_agreement0.index, consumer,
                                            consumer)
    print(
        f"[DATA_SCIENTIST --> DATA_PROVIDER0] Requesting an agreement for compute to the data for asset0: {agreement_id0}"
    )

    event = keeper.lock_reward_condition.subscribe_condition_fulfilled(
        agreement_id0, 60, None, (), wait=True)
    assert event is not None, "Reward condition is not found"

    event = keeper.compute_execution_condition.subscribe_condition_fulfilled(
        agreement_id0, 60, None, (), wait=True)
    assert event is not None, "Execution condition not found"

    service1 = ddo_compute1.get_service(
        service_type=ServiceTypes.CLOUD_COMPUTE)
    service_agreement1 = ServiceAgreement.from_service_dict(
        service1.as_dictionary())
    agreement_id1 = nevermined.assets.order(ddo_compute1.did,
                                            service_agreement1.index, consumer,
                                            consumer)
    print(
        f"[DATA_SCIENTIST --> DATA_PROVIDER1] Requesting an agreement for compute to the data for asset1: {agreement_id1}"
    )

    event = keeper.lock_reward_condition.subscribe_condition_fulfilled(
        agreement_id1, 60, None, (), wait=True)
    assert event is not None, "Reward condition is not found"

    event = keeper.compute_execution_condition.subscribe_condition_fulfilled(
        agreement_id1, 60, None, (), wait=True)
    assert event is not None, "Execution condition not found"

    service_coordinator = ddo_compute_coordinator.get_service(
        service_type=ServiceTypes.CLOUD_COMPUTE)
    service_agreement_coordinator = ServiceAgreement.from_service_dict(
        service_coordinator.as_dictionary())
    agreement_id_coordinator = nevermined.assets.order(
        ddo_compute_coordinator.did, service_agreement_coordinator.index,
        consumer, consumer)
    print(
        f"[DATA_SCIENTIST --> COORDINATOR_PROVIDER] Requesting an agreement for coordinator compute: {agreement_id_coordinator}"
    )

    event = keeper.lock_reward_condition.subscribe_condition_fulfilled(
        agreement_id_coordinator, 60, None, (), wait=True)
    assert event is not None, "Reward condition is not found"

    event = keeper.compute_execution_condition.subscribe_condition_fulfilled(
        agreement_id_coordinator, 60, None, (), wait=True)
    assert event is not None, "Execution condition not found"

    # 7. Execute workflows
    compute_coordinator_id = nevermined.assets.execute(
        agreement_id_coordinator,
        ddo_compute_coordinator.did,
        service_agreement_coordinator.index,
        consumer,
        ddo_workflow_coordinator.did,
    )
    print(
        f"[DATA_SCIENTIST --> COORDINATOR_PROVIDER] Requesting execution for coordinator compute: {compute_coordinator_id}"
    )

    compute_asset0_id = nevermined.assets.execute(
        agreement_id0,
        ddo_compute0.did,
        service_agreement0.index,
        consumer,
        ddo_workflow0.did,
    )
    print(
        f"[DATA_SCIENTIST --> DATA_PROVIDER0] Requesting execution for compute to data for asset0: {compute_asset0_id}"
    )

    compute_asset1_id = nevermined.assets.execute(
        agreement_id1,
        ddo_compute1.did,
        service_agreement1.index,
        consumer,
        ddo_workflow1.did,
    )
    print(
        f"[DATA_SCIENTIST --> DATA_PROVIDER1] Requesting execution for compute to data for asset1: {compute_asset1_id}"
    )

    jobs = [
        (agreement_id_coordinator, compute_coordinator_id),
        (agreement_id0, compute_asset0_id),
        (agreement_id1, compute_asset1_id),
    ]
    return jobs
Ejemplo n.º 28
0
def nft_transfer():
    """Allows the provider transfer and release the rewards.
    swagger_from_file: docs/nft_transfer.yml
    """
    required_attributes = [
        'agreementId', 'nftHolder', 'nftReceiver', 'nftAmount'
    ]
    data = request.json

    msg, status = check_required_attributes(required_attributes, data,
                                            'nft-transfer')
    if msg:
        return msg, status

    agreement_id = data.get('agreementId')
    nft_holder_address = data.get('nftHolder')
    nft_receiver_address = data.get('nftReceiver')
    nft_amount = data.get('nftAmount')

    keeper = keeper_instance()
    agreement = keeper.agreement_manager.get_agreement(agreement_id)
    did = id_to_did(agreement.did)
    ddo = DIDResolver(keeper.did_registry).resolve(did)

    try:
        ServiceAgreement.from_ddo(ServiceTypes.NFT_SALES, ddo)
    except ValueError as e:
        logger.error('nft-sales service not found on ddo for %s', did)
        return str(e), 400

    (lock_payment_condition_id, nft_transfer_condition_id,
     escrow_payment_condition_id) = agreement.condition_ids

    if not is_nft_holder(keeper, agreement.did, nft_amount,
                         nft_holder_address):
        msg = f'Holder {nft_holder_address} does not have enough NFTs to transfer'
        logger.warning(msg)
        return msg, 406

    if not is_lock_payment_condition_fulfilled(lock_payment_condition_id,
                                               keeper):
        msg = f'lockPayment condition for agreement_id={agreement_id} is not fulfilled'
        logger.warning(msg)
        return msg, 402

    if not is_nft_transfer_approved(nft_holder_address,
                                    get_provider_account().address, keeper):
        msg = f'Gateway ({get_provider_account().address}) is not approved to transfer nfts from {nft_holder_address}'
        logger.warning(msg)
        return msg, 405

    # fulfill transferNFT condition
    if not is_nft_transfer_condition_fulfilled(nft_transfer_condition_id,
                                               keeper):
        logger.debug('NFTTransfer condition not fulfilled')
        result = fulfill_for_delegate_nft_transfer_condition(
            agreement_id, agreement.did,
            Web3.toChecksumAddress(nft_holder_address),
            Web3.toChecksumAddress(nft_receiver_address), nft_amount,
            lock_payment_condition_id, keeper)
        if result is False:
            msg = f'There was an error fulfilling the NFTTransfer condition for agreement_id={agreement_id}'
            logger.error(msg)
            return msg, 500

    # fulfill escrowPayment condition
    if not is_escrow_payment_condition_fulfilled(escrow_payment_condition_id,
                                                 keeper):
        logger.debug('EscrowPayment condition not fulfilled')
        result = fulfill_escrow_payment_condition(
            keeper,
            agreement_id, [
                nft_transfer_condition_id, lock_payment_condition_id,
                escrow_payment_condition_id
            ],
            ddo,
            get_provider_account(),
            service_type=ServiceTypes.NFT_SALES)
        if result is False:
            msg = f'There was an error fulfilling the EscrowPayment condition for agreement_id={agreement_id}'
            logger.error(msg)
            return msg, 500

    return 'success', 200
Ejemplo n.º 29
0
def test_buy_asset(publisher_instance_no_init, consumer_instance_no_init):
    config = ExampleConfig.get_config()
    ConfigProvider.set_config(config)
    keeper = Keeper.get_instance()
    # :TODO: enable the actual SecretStore
    # SecretStoreProvider.set_secret_store_class(SecretStore)
    w3 = Web3Provider.get_web3()
    pub_acc = get_publisher_account()

    # Register ddo
    ddo = get_registered_ddo(publisher_instance_no_init, pub_acc)
    assert isinstance(ddo, DDO)
    # nevermined here will be used only to publish the asset. Handling the asset by the publisher
    # will be performed by the Gateway server running locally

    # restore the http client because we want the actual Gateway server to do the work
    # not the GatewayMock.
    # Gateway.set_http_client(requests)
    consumer_account = get_consumer_account()

    downloads_path_elements = len(
        os.listdir(consumer_instance_no_init._config.downloads_path)) if os.path.exists(
        consumer_instance_no_init._config.downloads_path) else 0
    # sign agreement using the registered asset did above
    service = ddo.get_service(service_type=ServiceTypes.ASSET_ACCESS)
    sa = ServiceAgreement.from_service_dict(service.as_dictionary())
    # This will send the access request to Gateway which in turn will execute the agreement on-chain
    consumer_instance_no_init.accounts.request_tokens(consumer_account, 100)

    agreement_id = consumer_instance_no_init.assets.order(
        ddo.did, sa.index, consumer_account, consumer_account)

    event_wait_time = 10
    event = keeper.lock_payment_condition.subscribe_condition_fulfilled(
        agreement_id,
        event_wait_time,
        log_event(keeper.lock_payment_condition.FULFILLED_EVENT),
        (),
        wait=True
    )
    assert event, 'no event for LockRewardCondition.Fulfilled'

    # give access
    publisher_instance_no_init.agreements.conditions.grant_access(
        agreement_id, ddo.asset_id, consumer_account.address, pub_acc)
    event = keeper.access_condition.subscribe_condition_fulfilled(
        agreement_id,
        event_wait_time,
        log_event(keeper.access_condition.FULFILLED_EVENT),
        (),
        wait=True
    )
    assert event, 'no event for AccessSecretStoreCondition.Fulfilled'
    assert consumer_instance_no_init.agreements.is_access_granted(agreement_id, ddo.did, consumer_account.address)

    amounts = list(map(int, service.get_param_value_by_name('_amounts')))
    receivers = service.get_param_value_by_name('_receivers')

    publisher_instance_no_init.agreements.conditions.release_reward(
        agreement_id, ddo.asset_id, amounts, receivers, pub_acc)

    assert consumer_instance_no_init.assets.access(
        agreement_id,
        ddo.did,
        sa.index,
        consumer_account,
        config.downloads_path)

    assert len(os.listdir(config.downloads_path)) == downloads_path_elements + 1

    # Check that we can access only an specific file in passing the index.
    assert consumer_instance_no_init.assets.access(
        agreement_id,
        ddo.did,
        sa.index,
        consumer_account,
        config.downloads_path,
        1
    )
    assert len(os.listdir(config.downloads_path)) == downloads_path_elements + 1

    with pytest.raises(AssertionError):
        consumer_instance_no_init.assets.access(
            agreement_id,
            ddo.did,
            sa.index,
            consumer_account,
            config.downloads_path,
            -2
        )

    with pytest.raises(AssertionError):
        consumer_instance_no_init.assets.access(
            agreement_id,
            ddo.did,
            sa.index,
            consumer_account,
            config.downloads_path,
            3
        )

    # decrypt the contentUrls using the publisher account instead of consumer account.
    # if the secret store is working and ACL check is enabled, this should fail
    # since SecretStore decrypt will fail the checkPermissions check and the gateway will return
    # an http error code back
    with pytest.raises(ValueError) as e:
        consumer_instance_no_init.assets.access(
            agreement_id,
            ddo.did,
            sa.index,
            pub_acc,
            config.downloads_path
        )
        print(e)
Ejemplo n.º 30
0
def test_buy_asset_no_secret_store(publisher_instance_gateway, consumer_instance_gateway):
    config = ExampleConfig.get_config()
    ConfigProvider.set_config(config)
    keeper = Keeper.get_instance()

    w3 = Web3Provider.get_web3()
    pub_acc = get_publisher_account()

    for method in [ServiceAuthorizationTypes.SECRET_STORE, ServiceAuthorizationTypes.PSK_ECDSA, ServiceAuthorizationTypes.PSK_RSA]:
        # Register ddo
        ddo = get_registered_with_psk(publisher_instance_gateway, pub_acc, auth_method=method)
        assert isinstance(ddo, DDO)
        # nevermined here will be used only to publish the asset. Handling the asset by the publisher
        # will be performed by the Gateway server running locally

        # restore the http client because we want the actual Gateway server to do the work
        # not the GatewayMock.
        # Gateway.set_http_client(requests)
        consumer_account = get_consumer_account()

        downloads_path_elements = len(
            os.listdir(consumer_instance_gateway._config.downloads_path)) if os.path.exists(
            consumer_instance_gateway._config.downloads_path) else 0
        # sign agreement using the registered asset did above
        service = ddo.get_service(service_type=ServiceTypes.ASSET_ACCESS)
        sa = ServiceAgreement.from_service_dict(service.as_dictionary())
        # This will send the access request to Gateway which in turn will execute the agreement on-chain
        consumer_instance_gateway.accounts.request_tokens(consumer_account, 100)
        agreement_id = consumer_instance_gateway.assets.order(
            ddo.did, sa.index, consumer_account, consumer_account)

        event_wait_time = 10
        event = keeper.access_template.subscribe_agreement_created(
            agreement_id,
            event_wait_time,
            log_event(keeper.access_template.AGREEMENT_CREATED_EVENT),
            (),
            wait=True
        )
        assert event, 'no event for EscrowAccessSecretStoreTemplate.AgreementCreated'

        event = keeper.lock_payment_condition.subscribe_condition_fulfilled(
            agreement_id,
            event_wait_time,
            log_event(keeper.lock_payment_condition.FULFILLED_EVENT),
            (),
            wait=True
        )
        assert event, 'no event for LockRewardCondition.Fulfilled'

        # give access
        publisher_instance_gateway.agreements.conditions.grant_access(
            agreement_id, ddo.asset_id, consumer_account.address, pub_acc)
        event = keeper.access_condition.subscribe_condition_fulfilled(
            agreement_id,
            event_wait_time,
            log_event(keeper.access_condition.FULFILLED_EVENT),
            (),
            wait=True
        )
        assert event, 'no event for AccessSecretStoreCondition.Fulfilled'
        assert consumer_instance_gateway.agreements.is_access_granted(agreement_id, ddo.did, consumer_account.address)

        publisher_instance_gateway.agreements.conditions.release_reward(
            agreement_id, ddo.asset_id, sa.get_amounts_int(), sa.get_receivers(), pub_acc)

        assert consumer_instance_gateway.assets.access(
            agreement_id,
            ddo.did,
            sa.index,
            consumer_account,
            config.downloads_path)

        assert len(os.listdir(config.downloads_path)) == downloads_path_elements + 1

        with pytest.raises(AssertionError):
            consumer_instance_gateway.assets.access(
                agreement_id,
                ddo.did,
                sa.index,
                consumer_account,
                config.downloads_path,
                -2
            )

        with pytest.raises(AssertionError):
            consumer_instance_gateway.assets.access(
                agreement_id,
                ddo.did,
                sa.index,
                consumer_account,
                config.downloads_path,
                3
            )