Ejemplo n.º 1
0
def execute_compute_job():
    """Call the execution of a workflow.
    Method deprecated, it will be replaced by `/execute` in further versions
    swagger_from_file: docs/execute_compute_job.yml
    """
    data = request.args
    required_attributes = [
        'serviceAgreementId', 'consumerAddress', 'signature', 'workflowDID'
    ]
    msg, status = check_required_attributes(required_attributes, data,
                                            'consume')
    if msg:
        return msg, status

    if not (data.get('signature')):
        return f'`signature is required in the call to "consume".', 400

    try:
        agreement_id = data.get('serviceAgreementId')
        consumer_address = data.get('consumerAddress')
        asset_id = keeper_instance().agreement_manager.get_agreement(
            agreement_id).did
        did = id_to_did(asset_id)
        if not was_compute_triggered(agreement_id, did, consumer_address,
                                     keeper_instance()):
            msg = (
                'Checking if the compute was triggered failed. Either consumer address does not '
                'have permission to executre this workflow or consumer address and/or service '
                'agreement id is invalid.')
            logger.warning(msg)
            return msg, 401

        workflow = DIDResolver(keeper_instance().did_registry).resolve(
            data.get('workflowDID'))
        body = {
            "serviceAgreementId": agreement_id,
            "workflow": workflow.as_dictionary()
        }

        response = requests_session.post(
            get_config().compute_api_url +
            '/api/v1/nevermined-compute-api/init',
            data=json.dumps(body),
            headers={'content-type': 'application/json'})
        return jsonify({"workflowId": response.content.decode('utf-8')})
    except Exception as e:
        logger.error(f'Error- {str(e)}', exc_info=1)
        return f'Error : {str(e)}', 500
Ejemplo n.º 2
0
def get_external_contracts():
    keeper = keeper_instance()
    return {
        name: contract.address
        for (name,
             contract) in keeper.external_contract_name_to_instance.items()
    }
Ejemplo n.º 3
0
def test_nft_access_no_agreement(client, provider_account, consumer_account):
    ddo = get_nft_ddo(provider_account, providers=[provider_account.address])
    nft_amounts = 1

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

    no_agreement_id = '0x'
    # generate the grant token
    grant_token = generate_access_grant_token(consumer_account,
                                              no_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' % (no_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.º 4
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.º 5
0
def test_info_contracts(client):
    keeper = keeper_instance()
    expected_contracts = {
        name: contract.address
        for (name, contract) in keeper.contract_name_to_instance.items()
    }

    response = client.get('/')
    assert response.status_code == 200
    assert response.json['contracts'] == expected_contracts
Ejemplo n.º 6
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.º 7
0
    def validate_access(self, agreement_id, did, consumer_address):
        keeper = keeper_instance()

        if not is_access_granted(
                agreement_id,
                did,
                consumer_address,
                keeper):
            # 3. If not granted, verification of agreement and conditions
            agreement = keeper.agreement_manager.get_agreement(agreement_id)
            cond_ids = agreement.condition_ids
            asset = DIDResolver(keeper.did_registry).resolve(did)
            asset_id = f'0x{did.replace(NEVERMINED_PREFIX, "")}'
            self.check_ddo(did, agreement_id, asset_id, consumer_address, keeper, cond_ids, ServiceTypes.ASSET_ACCESS)

            access_condition_status = keeper.condition_manager.get_condition_state(cond_ids[0])
            lock_condition_status = keeper.condition_manager.get_condition_state(cond_ids[1])
            escrow_condition_status = keeper.condition_manager.get_condition_state(
                cond_ids[2])

            logger.debug('AccessCondition: %d' % access_condition_status)
            logger.debug('LockPaymentCondition: %d' % lock_condition_status)
            logger.debug('EscrowPaymentCondition: %d' % escrow_condition_status)

            if lock_condition_status != ConditionState.Fulfilled.value:
                logger.debug('ServiceAgreement %s was not paid. Forbidden' % agreement_id)
                raise InvalidClientError(
                    f"ServiceAgreement {agreement_id} was not paid, LockPaymentCondition status is {lock_condition_status}")

            fulfilled = fulfill_access_condition(keeper, agreement_id, cond_ids, asset_id, consumer_address,
                                                 self.provider_account)
            if not fulfilled:
                raise InvalidClientError('Server error fulfilling access condition')

            fulfill_escrow_payment_condition(keeper, agreement_id, cond_ids, asset,
                                             self.provider_account)

            iteration = 0
            access_granted = False
            while iteration < ConfigSections.PING_ITERATIONS:
                iteration = iteration + 1
                logger.debug('Checking if access was granted. Iteration %d' % iteration)
                if not is_access_granted(agreement_id, did, consumer_address, keeper):
                    time.sleep(ConfigSections.PING_SLEEP / 1000)
                else:
                    access_granted = True
                    break

            if not access_granted:
                msg = ('Checking access permissions failed. Either consumer address does not have '
                       'permission to consume this asset or consumer address and/or service '
                       'agreement '
                       'id is invalid.')
                logger.warning(msg)
                raise InvalidClientError(msg)
Ejemplo n.º 8
0
def execute(agreement_id):
    """Call the execution of a workflow.
    swagger_from_file: docs/execute.yml
    """

    consumer_address = current_token["client_id"]
    workflow_did = current_token["did"]
    agreement_id = current_token["sub"]

    try:
        keeper = keeper_instance()
        asset_id = keeper_instance().agreement_manager.get_agreement(
            agreement_id).did
        did = id_to_did(asset_id)

        signature = '0x00'

        workflow = DIDResolver(
            keeper_instance().did_registry).resolve(workflow_did)
        body = {
            "serviceAgreementId": agreement_id,
            "workflow": workflow.as_dictionary()
        }

        response = requests_session.post(
            get_config().compute_api_url +
            '/api/v1/nevermined-compute-api/init',
            data=json.dumps(body),
            headers={'content-type': 'application/json'})
        if response.status_code != 200:
            msg = f'The compute API was not able to create the workflow. {response.content}'
            logger.warning(msg)
            return msg, 401

        used_by(generate_random_id(), did, consumer_address, 'compute',
                signature, 'compute', provider_acc, keeper)
        return jsonify({"workflowId": response.content.decode('utf-8')})

    except Exception as e:
        logger.error(f'Error- {str(e)}', exc_info=1)
        return f'Error : {str(e)}', 500
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 validate_owner(self, did, consumer_address):
        keeper = keeper_instance()

        if not is_owner_granted(
                did,
                consumer_address,
                keeper):
            msg = ('Checking access permissions failed. Consumer address does not have '
                   'permission to download this asset or consumer address and/or did '
                   'is invalid.')
            logger.warning(msg)
            raise InvalidClientError(msg)
Ejemplo n.º 11
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.º 12
0
    def validate_execute(self, agreement_id, workflow_did, consumer_address):
        keeper = keeper_instance()

        asset_id = keeper.agreement_manager.get_agreement(agreement_id).did
        did = id_to_did(asset_id)
        asset = DIDResolver(keeper.did_registry).resolve(did)

        if not was_compute_triggered(agreement_id, did, consumer_address, keeper):

            agreement = keeper.agreement_manager.get_agreement(agreement_id)
            cond_ids = agreement.condition_ids
            self.check_ddo(did, agreement_id, asset_id, consumer_address, keeper, cond_ids, ServiceTypes.CLOUD_COMPUTE)

            compute_condition_status = keeper.condition_manager.get_condition_state(cond_ids[0])
            lock_condition_status = keeper.condition_manager.get_condition_state(cond_ids[1])
            escrow_condition_status = keeper.condition_manager.get_condition_state(
                cond_ids[2])
            logger.debug('ComputeExecutionCondition: %d' % compute_condition_status)
            logger.debug('LockPaymentCondition: %d' % lock_condition_status)
            logger.debug('EscrowPaymentCondition: %d' % escrow_condition_status)

            if lock_condition_status != ConditionState.Fulfilled.value:
                logger.debug('ServiceAgreement %s was not paid. Forbidden' % agreement_id)
                raise InvalidClaimError(
                    f"ServiceAgreement {agreement_id} was not paid, LockPaymentCondition status is {lock_condition_status}")

            fulfill_compute_condition(keeper, agreement_id, cond_ids, asset_id, consumer_address,
                                      self.provider_account)
            fulfill_escrow_payment_condition(keeper, agreement_id, cond_ids, asset,
                                             self.provider_account,
                                             ServiceTypes.CLOUD_COMPUTE)

            iteration = 0
            access_granted = False
            while iteration < ConfigSections.PING_ITERATIONS:
                iteration = iteration + 1
                logger.debug('Checking if compute was granted. Iteration %d' % iteration)
                if not was_compute_triggered(agreement_id, did, consumer_address, keeper):
                    time.sleep(ConfigSections.PING_SLEEP / 1000)
                else:
                    access_granted = True
                    break

            if not access_granted:
                msg = (
                    'Scheduling the compute execution failed. Either consumer address does not '
                    'have permission to execute this workflow or consumer address and/or service '
                    'agreement id is invalid.')
                logger.warning(msg)
                raise InvalidClientError(msg)
Ejemplo n.º 13
0
    def validate_access_proof(self, agreement_id, did, eth_address, consumer_address, jubjub_sig):
        consumer_pub = ['0x'+consumer_address[0:64], '0x'+consumer_address[64:128]]
        provider_pub = [self.provider_key.x, self.provider_key.y]

        if not keytransfer.verify([int(consumer_pub[0],16), int(consumer_pub[1],16)], int(eth_address,16), jubjub_sig):
            raise InvalidClientError(
                    f"ServiceAgreement {agreement_id}: babyjubjub signature doesn't match")

        keeper = keeper_instance()

        agreement = keeper.agreement_manager.get_agreement(agreement_id)
        cond_ids = agreement.condition_ids
        asset = DIDResolver(keeper.did_registry).resolve(did)
        asset_id = did.replace(NEVERMINED_PREFIX, "")
        self.check_ddo(did, agreement_id, asset_id, consumer_pub, keeper, cond_ids, ServiceTypes.ASSET_ACCESS_PROOF)

        access_condition_status = keeper.condition_manager.get_condition_state(cond_ids[0])
        lock_condition_status = keeper.condition_manager.get_condition_state(cond_ids[1])
        escrow_condition_status = keeper.condition_manager.get_condition_state(
                cond_ids[2])

        logger.info('AccessProofCondition: %d' % access_condition_status)
        logger.info('LockPaymentCondition: %d' % lock_condition_status)
        logger.info('EscrowPaymentCondition: %d' % escrow_condition_status)

        if lock_condition_status != ConditionState.Fulfilled.value:
            logger.debug('ServiceAgreement %s was not paid. Forbidden' % agreement_id)
            raise InvalidClientError(
                    f"ServiceAgreement {agreement_id} was not paid, LockPaymentCondition status is {lock_condition_status}")

        if escrow_condition_status != ConditionState.Fulfilled.value:
            # compute the proof
            auth_method = asset.authorization.main['service']
            url = '0x' + get_asset_url_at_index(0, asset, self.provider_account, auth_method)
            res = call_prover(consumer_pub, self.provider_key.secret, url)
            # check that the condition ID is correct
            cond_id = keeper.access_proof_condition.generate_id(
                agreement_id,
                ['bytes32', 'bytes32', 'bytes32', 'bytes32', 'bytes32'],
                [res['hash'], consumer_pub[0], consumer_pub[1], provider_pub[0], provider_pub[1]]
            )
            if cond_ids[0] != cond_id.hex():
                raise InvalidClientError(
                        f"ServiceAgreement {agreement_id}: public key doesn't match {consumer_address}")

            fulfill_access_proof_condition(keeper, agreement_id, cond_ids, res['hash'], consumer_pub, provider_pub, res['cipher'], res['proof'],
                                     self.provider_account)
            fulfill_escrow_payment_condition(keeper, agreement_id, cond_ids, asset,
                                             self.provider_account, ServiceTypes.ASSET_ACCESS_PROOF)
Ejemplo n.º 14
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.º 15
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.º 16
0
def test_publish(client):
    keeper = keeper_instance()
    account = get_provider_account()
    endpoint = BaseURLs.ASSETS_URL + '/publish'

    did_seed = generate_new_id()
    asset_id = keeper.did_registry.hash_did(did_seed, account.address)

    # did = DID.did({"0": str(uuid.uuid4())})
    # asset_id = did_to_id(did)
    test_urls = ['url 00', 'url 11', 'url 22']

    urls_json = json.dumps(test_urls)
    asset_id_hash = add_ethereum_prefix_and_hash_msg(asset_id)
    signature = keeper.sign_hash(asset_id_hash, account)
    address = web3().eth.account.recoverHash(asset_id_hash,
                                             signature=signature)
    assert address.lower() == account.address.lower()
    address = keeper.personal_ec_recover(asset_id, signature)
    assert address.lower() == account.address.lower()

    payload = {
        'documentId': asset_id,
        'signature': signature,
        'document': urls_json,
        'publisherAddress': account.address
    }
    post_response = client.post(endpoint,
                                data=json.dumps(payload),
                                content_type='application/json')
    encrypted_url = post_response.data.decode('utf-8')
    assert encrypted_url.startswith('0x')

    # publish using auth token
    signature = generate_token(account)
    payload['signature'] = signature
    # did = DID.did({"0": str(uuid.uuid4())})
    # asset_id = did_to_id(did)
    did_seed = generate_new_id()
    asset_id = keeper.did_registry.hash_did(did_seed, account.address)

    payload['documentId'] = add_0x_prefix(asset_id)
    post_response = client.post(endpoint,
                                data=json.dumps(payload),
                                content_type='application/json')
    encrypted_url = post_response.data.decode('utf-8')
    assert encrypted_url.startswith('0x')
Ejemplo n.º 17
0
def publish():
    """Encrypt document using the SecretStore and keyed by the given documentId.
    swagger_from_file: docs/publish.yml
    """
    required_attributes = [
        'documentId', 'signature', 'document', 'publisherAddress'
    ]
    data = request.json
    if 'signedDocumentId' in data and 'signature' not in data:
        data['signature'] = data['signedDocumentId']

    msg, status = check_required_attributes(required_attributes, data,
                                            'publish')
    if msg:
        return msg, status

    did = data.get('documentId')
    signature = data.get('signature')
    document = json.dumps(json.loads(data.get('document')),
                          separators=(',', ':'))
    publisher_address = data.get('publisherAddress')

    try:
        if not verify_signature(keeper_instance(), publisher_address,
                                signature, did):
            msg = f'Invalid signature {signature} for ' \
                  f'publisherAddress {publisher_address} and documentId {did}.'
            raise ValueError(msg)

        print('Document: ' + document)
        print('DID: ' + remove_0x_prefix(did))
        encrypted_document, public_key = rsa_encryption_from_file(
            document, get_rsa_public_key_file())
        logger.debug(f'encrypted urls {encrypted_document}, '
                     f'publisher {publisher_address}, '
                     f'documentId {did}')
        return encrypted_document, 201

    except (RPCError, Exception) as e:
        logger.error(
            f'Encryption Error: {e}. \n'
            f'providerAddress={provider_acc.address}\n'
            f'Payload was: documentId={did}, '
            f'publisherAddress={publisher_address},'
            f'signature={signature}',
            exc_info=1)
        return f'Error: {str(e)}', 500
Ejemplo n.º 18
0
def test_auth_token():
    token = "0x1d2741dee30e64989ef0203957c01b14f250f5d2f6ccb0" \
            "c88c9518816e4fcec16f84e545094eb3f377b7e214ded226" \
            "76fbde8ca2e41b4eb1b3565047ecd9acf300-1568372035"
    pub_address = "0x62C092047B01630FC7ABAf3Ab07f4b8aDa5EeB35"
    doc_id = "663516d306904651bbcf9fe45a00477c215c7303d8a24c5bad6005dd2f95e68e"
    assert is_token_valid(token), f'cannot recognize auth-token {token}'
    address = check_auth_token(token)
    assert address and address.lower() == pub_address.lower(), f'address mismatch, got {address}, ' \
                                                               f'' \
                                                               f'' \
                                                               f'' \
                                                               f'' \
                                                               f'' \
                                                               f'expected {pub_address}'
    good = verify_signature(keeper_instance(), pub_address, token, doc_id)
    assert good, f'invalid signature/auth-token {token}, {pub_address}, {doc_id}'
Ejemplo n.º 19
0
def lock_payment(agreement_id,
                 did,
                 service_agreement,
                 amounts,
                 receivers,
                 consumer_account,
                 token_address=None):
    keeper = keeper_instance()
    if token_address is None:
        token_address = keeper.token.address

    price = service_agreement.get_price()
    keeper.token.token_approve(keeper.lock_payment_condition.address, price,
                               consumer_account)
    tx_hash = keeper.lock_payment_condition.fulfill(
        agreement_id, did, keeper.escrow_payment_condition.address,
        token_address, amounts, receivers, consumer_account)
    keeper.lock_payment_condition.get_tx_receipt(tx_hash)
Ejemplo n.º 20
0
def access(agreement_id, index=0):
    """Allows to get access to an asset data file.
    swagger_from_file: docs/access.yml
    """

    consumer_address = current_token["client_id"]
    did = current_token["did"]
    agreement_id = current_token["sub"]

    logger.info(
        'Parameters:\nAgreementId: %s\nIndex: %d\nConsumerAddress: %s\n'
        'DID: %s\n' % (agreement_id, index, consumer_address, did))

    try:
        keeper = keeper_instance()
        asset = DIDResolver(keeper.did_registry).resolve(did)

        logger.debug('AgreementID :' + agreement_id)

        file_attributes = asset.metadata['main']['files'][index]
        content_type = file_attributes.get('contentType', None)

        try:
            auth_method = asset.authorization.main['service']
        except Exception:
            auth_method = constants.ConfigSections.DEFAULT_DECRYPTION_METHOD

        if auth_method not in constants.ConfigSections.DECRYPTION_METHODS:
            msg = (
                'The Authorization Method defined in the DDO is not part of the available '
                'methods supported'
                'by the Gateway: ' + auth_method)
            logger.warning(msg)
            return msg, 400

        url = get_asset_url_at_index(index, asset, provider_acc, auth_method)
        used_by(generate_random_id(), did, consumer_address, 'access', '0x00',
                'access', provider_acc, keeper)
        return get_asset(request, requests_session, content_type, url,
                         app.config['CONFIG_FILE'])

    except (ValueError, Exception) as e:
        logger.error(f'Error- {str(e)}', exc_info=1)
        return f'Error : {str(e)}', 500
Ejemplo n.º 21
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.º 22
0
def root_info():
    config = Config(filename=app.config['CONFIG_FILE'])
    keeper = keeper_instance()
    key = get_provider_babyjub_key()
    url_keeper = urlparse(config.keeper_url)
    info = {
        'software':
        Metadata.TITLE,
        'version':
        version.__version__,
        'keeper-url':
        url_keeper.scheme + '://' + url_keeper.netloc,
        'network':
        keeper.network_name,
        'contracts':
        get_contracts(),
        'external-contracts':
        get_external_contracts(),
        'keeper-version':
        keeper.did_registry.version,
        'provider-address':
        get_provider_account().address,
        'ecdsa-public-key':
        get_ecdsa_public_key_from_file(get_provider_key_file(),
                                       get_provider_password()),
        'babyjub-public-key': {
            'x': key.x,
            'y': key.y
        }
    }

    try:
        info['rsa-public-key'] = get_content_keyfile_from_path(
            get_rsa_public_key_file())
    except Exception as e:
        logger.warning(f'Unable to load RSA Public Key: {e}. ', exc_info=1)

    return jsonify(info)
Ejemplo n.º 23
0
def is_allowed_read_compute(agreement_id, execution_id, consumer_address, signature, has_bearer_token=False):
    keeper = keeper_instance()

    ## Access check
    if not has_bearer_token:
        if not verify_signature(keeper, consumer_address, signature, execution_id):
            msg = (f'Invalid signature {signature} for '
                f'consumerAddress {consumer_address} and executionId {execution_id}.')
            logger.error(msg)
            return msg, False

    asset_id = keeper.agreement_manager.get_agreement(agreement_id).did
    did = id_to_did(asset_id)

    if not was_compute_triggered(agreement_id, did, consumer_address, keeper):
        msg = (
            'Getting access failed. Either consumer address does not '
            'have permission to execute this agreement or consumer address and/or service '
            'agreement id is invalid.')
        logger.warning(msg)
        return msg, False

    return 'OK', True
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_nft_transfer(client, provider_account, consumer_account,
                      publisher_account):
    print('PROVIDER_ACCOUNT= ' + provider_account.address)
    print('PUBLISHER_ACCOUNT= ' + publisher_account.address)
    print('CONSUMER_ACCOUNT= ' + consumer_account.address)

    keeper = keeper_instance()
    ddo = get_nft_ddo(publisher_account, providers=[provider_account.address])
    asset_id = ddo.asset_id
    nft_amounts = 1
    agreement_id = ServiceAgreement.create_new_agreement_id()

    print('NFT_SALES_DID: ' + asset_id)

    nft_sales_service_agreement = ServiceAgreement.from_ddo(
        ServiceTypes.NFT_SALES, ddo)
    (transfer_nft_condition_id, lock_payment_condition_id,
     escrow_payment_condition_id
     ) = nft_sales_service_agreement.generate_agreement_condition_ids(
         agreement_id, asset_id, consumer_account.address, keeper)

    keeper.nft_sales_template.create_agreement(
        agreement_id, asset_id, [
            lock_payment_condition_id, transfer_nft_condition_id,
            escrow_payment_condition_id
        ], nft_sales_service_agreement.conditions_timelocks,
        nft_sales_service_agreement.conditions_timeouts,
        consumer_account.address, consumer_account)
    event = keeper.nft_sales_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"

    agreement = keeper.agreement_manager.get_agreement(agreement_id)
    cond_ids = agreement.condition_ids

    keeper.token.token_approve(keeper.lock_payment_condition.address,
                               nft_sales_service_agreement.get_price(),
                               consumer_account)

    keeper.dispenser.request_tokens(50, consumer_account)

    lock_payment(agreement_id, ddo.asset_id, nft_sales_service_agreement,
                 nft_sales_service_agreement.get_amounts_int(),
                 nft_sales_service_agreement.get_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"

    keeper.nft_upgradeable.set_approval_for_all(get_provider_account().address,
                                                True, publisher_account)

    time.sleep(10)

    is_approved = keeper.nft_upgradeable.is_approved_for_all(
        publisher_account.address, provider_account.address)
    assert is_approved is True

    response = client.post(BaseURLs.ASSETS_URL + '/nft-transfer',
                           json={
                               'agreementId': agreement_id,
                               'nftHolder': publisher_account.address,
                               'nftReceiver': consumer_account.address,
                               'nftAmount': nft_amounts
                           })
    assert response.status_code == 200

    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
Ejemplo n.º 26
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.º 27
0
def grant_access(agreement_id, ddo, consumer_account, provider_account):
    keeper = keeper_instance()
    tx_hash = keeper.access_condition.fulfill(agreement_id, ddo.asset_id,
                                              consumer_account.address,
                                              provider_account)
    keeper.access_condition.get_tx_receipt(tx_hash)
Ejemplo n.º 28
0
def consume():
    """Allows download of asset data file.
    Method deprecated, it will be replaced by `/access` in further versions
    swagger_from_file: docs/consume.yml
    """
    data = request.args
    required_attributes = [
        'serviceAgreementId', 'consumerAddress', 'signature', 'index'
    ]
    msg, status = check_required_attributes(required_attributes, data,
                                            'consume')
    if msg:
        return msg, status

    try:
        keeper = keeper_instance()
        agreement_id = data.get('serviceAgreementId')
        consumer_address = data.get('consumerAddress')
        asset_id = keeper.agreement_manager.get_agreement(agreement_id).did
        did = id_to_did(asset_id)

        if not is_access_granted(agreement_id, did, consumer_address, keeper):
            msg = (
                'Checking access permissions failed. Either consumer address does not have '
                'permission to consume this asset or consumer address and/or service agreement '
                'id is invalid.')
            logger.warning(msg)
            return msg, 401

        asset = DIDResolver(keeper.did_registry).resolve(did)
        signature = data.get('signature')
        index = int(data.get('index'))

        if not verify_signature(keeper, consumer_address, signature,
                                agreement_id):
            msg = f'Invalid signature {signature} for ' \
                  f'publisherAddress {consumer_address} and documentId {agreement_id}.'
            raise ValueError(msg)

        file_attributes = asset.metadata['main']['files'][index]
        content_type = file_attributes.get('contentType', None)

        try:
            auth_method = asset.authorization.main['service']
        except Exception:
            auth_method = constants.ConfigSections.DEFAULT_DECRYPTION_METHOD

        if auth_method not in constants.ConfigSections.DECRYPTION_METHODS:
            msg = (
                'The Authorization Method defined in the DDO is not part of the available '
                'methods supported'
                'by the Gateway: ' + auth_method)
            logger.warning(msg)
            return msg, 400

        url = get_asset_url_at_index(index, asset, provider_acc, auth_method)
        return get_asset(request, requests_session, content_type, url,
                         app.config['CONFIG_FILE'])
    except (ValueError, Exception) as e:
        logger.error(f'Error- {str(e)}', exc_info=1)
        return f'Error : {str(e)}', 500
Ejemplo n.º 29
0
def register_ddo(metadata,
                 account,
                 providers,
                 auth_service,
                 additional_service_descriptors,
                 royalties=None,
                 cap=None,
                 mint=0):
    keeper = keeper_instance()
    metadata_api = Metadata('http://172.17.0.1:5000')

    ddo = DDO()
    ddo_service_endpoint = metadata_api.get_service_endpoint()

    metadata_service_desc = ServiceDescriptor.metadata_service_descriptor(
        metadata, ddo_service_endpoint)
    authorization_service_attributes = {
        "main": {
            "service": auth_service,
            "publicKey": "0xd7"
        }
    }

    service_descriptors = [
        ServiceDescriptor.authorization_service_descriptor(
            authorization_service_attributes, 'http://localhost:12001')
    ]
    service_descriptors += [metadata_service_desc]
    service_descriptors += additional_service_descriptors

    services = ServiceFactory.build_services(service_descriptors)
    checksums = dict()
    for service in services:
        try:
            checksums[str(service.index)] = checksum(service.main)
        except Exception as e:
            pass

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

    did_seed = checksum(ddo.proof['checksum'])
    asset_id = keeper.did_registry.hash_did(did_seed, account.address)
    ddo._did = DID.did(asset_id)
    did = ddo._did

    for service in services:
        if service.type == ServiceTypes.ASSET_ACCESS or service.type == ServiceTypes.NFT_ACCESS or service.type == ServiceTypes.ASSET_ACCESS_PROOF:
            access_service = ServiceFactory.complete_access_service(
                did, service.service_endpoint, service.attributes,
                keeper.access_template.address,
                keeper.escrow_payment_condition.address, service.type)
            ddo.add_service(access_service)
        elif service.type == ServiceTypes.CLOUD_COMPUTE:
            compute_service = ServiceFactory.complete_compute_service(
                did, service.service_endpoint, service.attributes,
                keeper.compute_execution_condition.address,
                keeper.escrow_payment_condition.address)
            ddo.add_service(compute_service)
        elif service.type == ServiceTypes.NFT_SALES:
            nft_sales_service = ServiceFactory.complete_nft_sales_service(
                did, service.service_endpoint, service.attributes,
                keeper.nft_sales_template.address,
                keeper.escrow_payment_condition.address, service.type)
            ddo.add_service(nft_sales_service)
        else:
            ddo.add_service(service)

    ddo.proof['signatureValue'] = keeper.sign_hash(did_to_id_bytes(did),
                                                   account)

    ddo.add_public_key(did, account.address)

    ddo.add_authentication(did, PUBLIC_KEY_TYPE_RSA)

    try:
        _oldddo = metadata_api.get_asset_ddo(ddo.did)
        if _oldddo:
            metadata_api.retire_asset_ddo(ddo.did)
    except ValueError:
        pass

    if 'files' in metadata['main']:
        if auth_service == ServiceAuthorizationTypes.SECRET_STORE:
            encrypted_files = do_secret_store_encrypt(
                remove_0x_prefix(ddo.asset_id),
                json.dumps(metadata['main']['files']), account, get_config())
        elif auth_service == ServiceAuthorizationTypes.PSK_RSA:
            encrypted_files, public_key = rsa_encryption_from_file(
                json.dumps(metadata['main']['files']),
                get_rsa_public_key_file())
        else:
            encrypted_files, public_key = ecdsa_encryption_from_file(
                json.dumps(metadata['main']['files']), get_provider_key_file(),
                get_provider_password())

        _files = metadata['main']['files']
        # only assign if the encryption worked
        if encrypted_files:
            index = 0
            for file in metadata['main']['files']:
                file['index'] = index
                index = index + 1
                del file['url']
            metadata['encryptedFiles'] = encrypted_files

    ddo_with_did = DDO(did,
                       json_text=ddo.as_text().replace('/{did}', '/' + did))
    ddo_service_endpoint = ddo_service_endpoint.replace('/{did}', '/' + did)

    if mint > 0 or royalties is not None or cap is not None:
        keeper.did_registry.register_mintable_did(
            did_seed,
            checksum=web3().toBytes(hexstr=ddo.asset_id),
            url=ddo_service_endpoint,
            cap=cap,
            royalties=royalties,
            account=account,
            providers=providers)
        if mint > 0:
            keeper.did_registry.mint(ddo.asset_id, mint, account=account)
    else:
        keeper_instance().did_registry.register(
            did_seed,
            checksum=web3().toBytes(hexstr=ddo.asset_id),
            url=ddo_service_endpoint,
            account=account,
            providers=providers)
    metadata_api.publish_asset_ddo(ddo_with_did)
    return ddo_with_did