예제 #1
0
def test_ddo_address_utilities():
    sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample_with_credentials.json")
    assert sample_ddo_path.exists(), "{} does not exist!".format(sample_ddo_path)

    ddo = V3Asset(json_filename=sample_ddo_path)

    assert ddo.allowed_addresses == ["0x123", "0x456a"]

    ddo.add_address_to_allow_list("0xAbc12")
    assert ddo.allowed_addresses == ["0x123", "0x456a", "0xabc12"]
    ddo.remove_address_from_allow_list("0xAbc12")
    assert ddo.allowed_addresses == ["0x123", "0x456a"]
    ddo.remove_address_from_allow_list("0x123")
    assert ddo.allowed_addresses == ["0x456a"]
    ddo.remove_address_from_allow_list("0x456a")
    assert ddo.allowed_addresses == []

    assert ddo.denied_addresses == ["0x2222", "0x333"]
    # does not exist
    ddo.remove_address_from_deny_list("0xasfaweg")
    assert ddo.denied_addresses == ["0x2222", "0x333"]
    ddo.add_address_to_deny_list("0xasfaweg")
    assert ddo.denied_addresses == ["0x2222", "0x333", "0xasfaweg"]

    ddo = V3Asset()
    assert ddo.allowed_addresses == []
    ddo.add_address_to_allow_list("0xAbc12")
    assert ddo.allowed_addresses == ["0xabc12"]
    # double adding
    ddo.add_address_to_allow_list("0xAbc12")
    assert ddo.allowed_addresses == ["0xabc12"]
예제 #2
0
def test_pay_for_service_insufficient_balance(publisher_ocean_instance):
    """Tests if balance is lower than the purchased amount."""
    ocn = publisher_ocean_instance
    alice = get_publisher_wallet()

    sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample.json")
    asset = V3Asset(json_filename=sample_ddo_path)
    asset.metadata["main"]["files"][0]["checksum"] = str(uuid.uuid4())

    token = ocn.create_data_token("DataToken1",
                                  "DT1",
                                  from_wallet=alice,
                                  blob="foo_blob")

    with pytest.raises(InsufficientBalance):
        ocn.assets.pay_for_service(
            ocn.web3,
            10000000000000,
            token.address,
            asset.did,
            0,
            ZERO_ADDRESS,
            alice,
            alice.address,
        )
예제 #3
0
def resolve_asset(
    did: str,
    metadata_cache_uri: Optional[str] = None,
    web3: Optional[Web3] = None,
    token_address: Optional[str] = None,
) -> V3Asset:
    """Resolve a DID to an URL/DDO or later an internal/external DID.

    :param did: the asset id to resolve, this is part of the ocean
        DID did:op:<32 byte value>
    :param metadata_cache_uri: str the url of the metadata store
    :param web3: Web3 instance
    :param token_address: str the address of the DataToken smart contract

    :return Asset: the resolved DID
    """
    assert metadata_cache_uri or (
        web3 and token_address
    ), "Either metadata_cache_uri or (web3 and token_address) is required."

    if not metadata_cache_uri:
        metadata_cache_uri = DataToken(web3, token_address).get_metadata_url()

    logger.debug(f"found did {did} -> url={metadata_cache_uri}")
    ddo = AquariusProvider.get_aquarius(metadata_cache_uri).get_asset_ddo(did)

    if ddo:
        return V3Asset(dictionary=ddo.as_dictionary())
예제 #4
0
def test_ddo_connection(config):
    ddo = V3Asset("did:op:testdid")
    provider_uri = config.provider_url
    assert (
        ddo.is_consumable(with_connectivity_check=True, provider_uri=provider_uri)
        == ConsumableCodes.CONNECTIVITY_FAIL
    )
예제 #5
0
def create_asset(ocean, publisher, encrypt=False):
    """Helper function for asset creation based on ddo_sa_sample.json."""
    sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample.json")
    assert sample_ddo_path.exists(), "{} does not exist!".format(
        sample_ddo_path)

    asset = V3Asset(json_filename=sample_ddo_path)
    asset.metadata["main"]["files"][0]["checksum"] = str(uuid.uuid4())
    return ocean.assets.create(asset.metadata, publisher, [], encrypt=encrypt)
예제 #6
0
def test_create_asset_with_owner_address(publisher_ocean_instance):
    """Tests that an asset can be created with owner address."""
    ocn = publisher_ocean_instance
    alice = get_publisher_wallet()

    sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample.json")
    asset = V3Asset(json_filename=sample_ddo_path)
    asset.metadata["main"]["files"][0]["checksum"] = str(uuid.uuid4())

    assert ocn.assets.create(
        asset.metadata, alice, [], owner_address=alice.address
    ), "Asset creation failed with the specified owner address."
예제 #7
0
def test_create_asset_without_dt_address(publisher_ocean_instance):
    """Tests creation of the asset which has not the data token address."""
    ocn = publisher_ocean_instance
    alice = get_publisher_wallet()

    sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample.json")
    asset = V3Asset(json_filename=sample_ddo_path)
    asset.metadata["main"]["files"][0]["checksum"] = str(uuid.uuid4())

    assert ocn.assets.create(
        asset.metadata, alice, [], data_token_address=None
    ), "Asset creation failed with the specified datatoken address."
예제 #8
0
def test_ddo_unlisting():
    sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample.json")
    assert sample_ddo_path.exists(), "{} does not exist!".format(sample_ddo_path)

    ddo = V3Asset(json_filename=sample_ddo_path)
    assert ddo.is_listed

    ddo.unlist()
    assert not ddo.is_listed

    ddo.list()
    assert ddo.is_listed
예제 #9
0
def test_ddo_retiring():
    sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample.json")
    assert sample_ddo_path.exists(), "{} does not exist!".format(sample_ddo_path)

    ddo = V3Asset(json_filename=sample_ddo_path)
    assert not ddo.is_retired

    ddo.retire()
    assert ddo.is_retired
    assert ddo.is_consumable() == ConsumableCodes.ASSET_DISABLED

    ddo.unretire()
    assert not ddo.is_retired
예제 #10
0
    def get_asset_ddo(self, did: str) -> Optional[V3Asset]:
        """
        Retrieve asset ddo for a given did.

        :param did: Asset DID string
        :return: V3Asset instance
        """
        response = self.requests_session.get(f"{self.base_url}/ddo/{did}")

        if response.status_code == 200:
            return V3Asset(dictionary=response.json())

        return None
예제 #11
0
def test_ddo_credentials_disabled():
    sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample_disabled.json")
    assert sample_ddo_path.exists(), "{} does not exist!".format(sample_ddo_path)

    ddo = V3Asset(json_filename=sample_ddo_path)
    assert ddo.is_disabled
    assert not ddo.is_enabled

    ddo.enable()
    assert not ddo.is_disabled
    assert ddo.is_enabled

    ddo.disable()
    assert ddo.is_consumable() == ConsumableCodes.ASSET_DISABLED
예제 #12
0
    def query(self, query: dict, metadata_cache_uri: Optional[str] = None) -> list:
        """
        Search an asset in oceanDB using search query.

        :param query: dict with query parameters
            (e.g.) https://github.com/oceanprotocol/aquarius/blob/develop/docs/for_api_users/API.md
        :param metadata_cache_uri: Url of the aquarius where you want to search. If there is not
            provided take the default
        :return: List of assets that match with the query.
        """
        logger.info(f"Searching asset query: {query}")
        aquarius = self._get_aquarius(metadata_cache_uri)
        return [
            V3Asset(dictionary=ddo_dict) for ddo_dict in aquarius.query_search(query)
        ]
예제 #13
0
    def search(self, text: str, metadata_cache_uri: Optional[str] = None) -> list:
        """
        Search an asset in oceanDB using aquarius.

        :param text: String with the value that you are searching
        :param metadata_cache_uri: Url of the aquarius where you want to search. If there is not
            provided take the default
        :return: List of assets that match with the query
        """
        logger.info(f"Searching asset containing: {text}")
        return [
            V3Asset(dictionary=ddo_dict)
            for ddo_dict in self._get_aquarius(metadata_cache_uri).query_search(
                {"query": {"query_string": {"query": text}}}
            )
        ]
예제 #14
0
def get_ddo_sample(datatoken_address):
    """Helper function to get a sample ddo for testing."""
    did = f"did:op:{remove_0x_prefix(datatoken_address)}"
    sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample.json")
    assert sample_ddo_path.exists(), "{} does not exist!".format(sample_ddo_path)

    asset = V3Asset(json_filename=sample_ddo_path)
    asset.metadata["main"]["files"][0]["checksum"] = str(uuid.uuid4())

    checksum_dict = dict()
    for service in asset.services:
        checksum_dict[str(service.index)] = checksum(service.main)

    asset.add_proof(checksum_dict, get_publisher_wallet())
    asset.did = did
    return asset
예제 #15
0
def test_ddo_credentials_addresses_both():
    """Tests DDO credentials when both deny and allow lists exist on the asset."""
    sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample_with_credentials.json")
    assert sample_ddo_path.exists(), "{} does not exist!".format(sample_ddo_path)

    ddo = V3Asset(json_filename=sample_ddo_path)
    address_credential = AddressCredential(ddo)
    assert address_credential.get_addresses_of_class("allow") == ["0x123", "0x456a"]
    assert address_credential.get_addresses_of_class("deny") == ["0x2222", "0x333"]
    assert (
        address_credential.validate_access({"type": "address", "value": "0x111"})
        == ConsumableCodes.CREDENTIAL_NOT_IN_ALLOW_LIST
    )
    assert (
        address_credential.validate_access({"type": "address", "value": "0x456A"})
        == ConsumableCodes.OK
    )
예제 #16
0
def test_create_asset_with_address(publisher_ocean_instance):
    """Tests that an asset can be created with specific DT address."""
    ocn = publisher_ocean_instance
    alice = get_publisher_wallet()

    sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample.json")
    asset = V3Asset(json_filename=sample_ddo_path)
    asset.metadata["main"]["files"][0]["checksum"] = str(uuid.uuid4())

    token = ocn.create_data_token("DataToken1",
                                  "DT1",
                                  from_wallet=alice,
                                  blob="foo_blob")

    assert ocn.assets.create(
        asset.metadata, alice, [], data_token_address=token.address
    ), "Asset creation failed with the specified datatoken address."
예제 #17
0
def test_ddo_dict():
    """Tests DDO creation from dictionary."""
    sample_ddo_path = get_resource_path("ddo", "ddo_sample_algorithm.json")
    assert sample_ddo_path.exists(), f"{sample_ddo_path} does not exist!"

    ddo1 = V3Asset(json_filename=sample_ddo_path)
    assert ddo1.did == "did:op:8d1b4d73e7af4634958f071ab8dfe7ab0df14019"

    ddo1.add_proof({"checksum": "test"}, get_publisher_wallet())

    ddo_dict = ddo1.as_dictionary()
    assert ddo_dict["publicKey"][0]["id"] == ddo1.did
    assert ddo_dict["publicKey"][0]["owner"] == get_publisher_wallet().address
    assert ddo_dict["publicKey"][0]["type"] == "EthereumECDSAKey"

    assert ddo_dict["authentication"][0] == {
        "type": "RsaSignatureAuthentication2018",
        "publicKey": ddo1.did,
    }
예제 #18
0
def test_creating_asset_from_scratch():
    """Tests creating an Asset from scratch."""
    # create an empty ddo
    ddo = V3Asset()
    assert ddo.did is None
    assert ddo.asset_id is None
    assert ddo.created is not None, "DDO has not been created."

    did = DID.did({"0": "0x99999999999999999"})
    ddo.did = did
    assert ddo.did == did

    ddo.add_service(TEST_SERVICE_TYPE, TEST_SERVICE_URL)

    pub_acc = get_publisher_wallet()

    ddo.add_proof({"checksum": "test"}, pub_acc)
    ddo_text_proof = ddo.as_text()
    assert ddo_text_proof
예제 #19
0
def test_ddo_credentials_addresses_no_access_list():
    """Tests DDO credentials when neither deny, nor allow lists exist on the asset."""
    sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample_with_credentials.json")
    assert sample_ddo_path.exists(), "{} does not exist!".format(sample_ddo_path)

    # if "allow" OR "deny" exist, we need a credential,
    # so remove both to test the behaviour of no credential supplied
    ddo = V3Asset(json_filename=sample_ddo_path)
    address_credential = AddressCredential(ddo)
    ddo.credentials.pop("allow")
    ddo.credentials.pop("deny")

    assert address_credential.validate_access() == ConsumableCodes.OK

    # test that we can use another credential if address is not required
    assert (
        ddo.is_consumable(
            {"type": "somethingelse", "value": "test"}, with_connectivity_check=False
        )
        == ConsumableCodes.OK
    )
예제 #20
0
def test_verify_order_tx(alice_address, bob_address, alice_ocean,
                         alice_wallet):
    """Tests verify_order_tx function."""
    token = alice_ocean.create_data_token("DataToken1",
                                          "DT1",
                                          from_wallet=alice_wallet,
                                          blob="foo_blob")

    token.mint(alice_address, to_wei(100), from_wallet=alice_wallet)
    token.approve(bob_address, to_wei(1), from_wallet=alice_wallet)
    transfer_tx_id = token.transfer(bob_address,
                                    to_wei(5),
                                    from_wallet=alice_wallet)

    with pytest.raises(TimeExhausted):
        with patch("ocean_lib.models.data_token.DataToken.get_tx_receipt"
                   ) as mock:
            # dummy tx id which is not found in the chain
            # catches TimeExhausted exception from web3
            mock.side_effect = TimeExhausted()
            token.verify_order_tx("0x0", "some_did", "some_index",
                                  "some_amount", alice_address)

    transfer_tx_id = token.transfer(bob_address,
                                    to_wei(5),
                                    from_wallet=alice_wallet)
    with pytest.raises(AssertionError):
        # tx id is from transfer, not order
        token.verify_order_tx(transfer_tx_id, "some_did", "some_index",
                              "some_amount", alice_address)

    sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample.json")
    asset = V3Asset(json_filename=sample_ddo_path)
    order_tx_id = token.startOrder(alice_address, to_wei(1), 1, ZERO_ADDRESS,
                                   alice_wallet)

    with pytest.raises(AssertionError):
        # the wrong asset did, this is a sample
        token.verify_order_tx(order_tx_id, asset.did, "some_index",
                              "some_amount", alice_address)
예제 #21
0
def test_InsufficientBalance(publisher_ocean_instance):
    alice = get_publisher_wallet()
    sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample.json")
    asset = V3Asset(json_filename=sample_ddo_path)
    asset.metadata["main"]["files"][0]["checksum"] = str(uuid.uuid4())

    token = publisher_ocean_instance.create_data_token("DataToken1",
                                                       "DT1",
                                                       from_wallet=alice,
                                                       blob="foo_blob")

    with pytest.raises(InsufficientBalance):
        publisher_ocean_instance.assets.pay_for_service(
            publisher_ocean_instance.web3,
            to_wei("12345678999999.9"),
            token.address,
            asset.did,
            0,
            ZERO_ADDRESS,
            alice,
            alice.address,
        )
예제 #22
0
def test_ddo_credentials_addresses_only_deny():
    """Tests DDO credentials when only the deny list exists on the asset."""
    sample_ddo_path = get_resource_path("ddo", "ddo_sa_sample_with_credentials.json")
    assert sample_ddo_path.exists(), "{} does not exist!".format(sample_ddo_path)
    # remove allow to test the behaviour of deny
    ddo = V3Asset(json_filename=sample_ddo_path)
    ddo.credentials.pop("allow")

    address_credential = AddressCredential(ddo)
    assert address_credential.get_addresses_of_class("allow") == []
    assert address_credential.get_addresses_of_class("deny") == ["0x2222", "0x333"]
    assert (
        address_credential.validate_access({"type": "address", "value": "0x111"})
        == ConsumableCodes.OK
    )
    assert (
        address_credential.validate_access({"type": "address", "value": "0x333"})
        == ConsumableCodes.CREDENTIAL_IN_DENY_LIST
    )

    credential = {"type": "address", "value": ""}
    with pytest.raises(MalformedCredential):
        address_credential.validate_access(credential)
예제 #23
0
    def create(
        self,
        metadata: dict,
        publisher_wallet: Wallet,
        services: Optional[list] = None,
        owner_address: Optional[str] = None,
        data_token_address: Optional[str] = None,
        provider_uri: Optional[str] = None,
        dt_name: Optional[str] = None,
        dt_symbol: Optional[str] = None,
        dt_blob: Optional[str] = None,
        dt_cap: Optional[int] = None,
        encrypt: Optional[bool] = False,
    ) -> Optional[V3Asset]:
        """Register an asset on-chain.

        Creating/deploying a DataToken contract and in the Metadata store (Aquarius).

        :param metadata: dict conforming to the Metadata accepted by Ocean Protocol.
        :param publisher_wallet: Wallet of the publisher registering this asset
        :param services: list of Service objects.
        :param owner_address: hex str the ethereum address to assign asset ownership to. After
            registering the asset on-chain, the ownership is transferred to this address
        :param data_token_address: hex str the address of the data token smart contract. The new
            asset will be associated with this data token address.
        :param provider_uri: str URL of service provider. This will be used as base to
            construct the serviceEndpoint for the `access` (download) service
        :param dt_name: str name of DataToken if creating a new one
        :param dt_symbol: str symbol of DataToken if creating a new one
        :param dt_blob: str blob of DataToken if creating a new one. A `blob` is any text
            to be stored with the ERC20 DataToken contract for any purpose.
        :param dt_cap: int amount of DataTokens to mint, denoted in wei
        :return: DDO instance
        """
        assert isinstance(
            metadata, dict
        ), f"Expected metadata of type dict, got {type(metadata)}"

        # copy metadata so we don't change the original
        metadata_copy = copy.deepcopy(metadata)
        asset_type = metadata_copy["main"]["type"]
        assert asset_type in (
            "dataset",
            "algorithm",
        ), f"Invalid/unsupported asset type {asset_type}"

        validation_result, validation_errors = self.validate(metadata)
        if not validation_result:
            msg = f"Metadata has validation errors: {validation_errors}"
            logger.error(msg)
            raise ValueError(msg)

        urls = [item["url"] for item in metadata["main"]["files"]]
        if not provider_uri:
            provider_uri = DataServiceProvider.get_url(self._config)
        for url in urls:
            if not DataServiceProvider.check_single_file_info(url, provider_uri):
                msg = f"The URL of this service can not be accessed: {url}."
                logger.error(msg)
                raise ValueError(msg)

        services = services or []
        services = self._add_defaults(
            services, metadata_copy, provider_uri, publisher_wallet
        )

        checksum_dict = dict()
        for service in services:
            checksum_dict[str(service.index)] = checksum(service.main)

        # Create a DDO object
        asset = V3Asset()
        # Adding proof to the ddo.
        asset.add_proof(checksum_dict, publisher_wallet)

        #################
        # DataToken
        address = DTFactory.configured_address(
            get_network_name(web3=self._web3), self._config.address_file
        )
        dtfactory = DTFactory(self._web3, address)
        if not data_token_address:
            blob = dt_blob or ""
            name = dt_name or metadata["main"]["name"]
            symbol = dt_symbol or name
            # register on-chain
            _cap = dt_cap if dt_cap else DataToken.DEFAULT_CAP
            tx_id = dtfactory.createToken(
                blob, name, symbol, _cap, from_wallet=publisher_wallet
            )
            data_token = DataToken(self._web3, dtfactory.get_token_address(tx_id))
            if not data_token:
                logger.warning("Creating new data token failed.")
                return None

            data_token_address = data_token.address

            logger.info(
                f"Successfully created data token with address "
                f"{data_token.address} for new dataset asset."
            )
            # owner_address is set as minter only if creating new data token. So if
            # `data_token_address` is set `owner_address` has no effect.
            if owner_address:
                data_token.proposeMinter(owner_address, from_wallet=publisher_wallet)
        else:
            if not dtfactory.verify_data_token(data_token_address):
                raise ContractNotFound(
                    f"datatoken address {data_token_address} is not found in the DTFactory events."
                )
            # verify data_token_address
            dt = DataToken(self._web3, data_token_address)
            minter = dt.contract.caller.minter()
            if not minter:
                raise AssertionError(
                    f"datatoken address {data_token_address} does not seem to be a valid DataToken contract."
                )
            elif minter.lower() != publisher_wallet.address.lower():
                raise AssertionError(
                    f"Minter of datatoken {data_token_address} is not the same as the publisher."
                )

        assert (
            data_token_address
        ), "data_token_address is required for publishing a dataset asset."

        # Generating the did and adding to the ddo.
        did = f"did:op:{remove_0x_prefix(data_token_address)}"
        asset.did = did
        logger.debug(f"Using datatoken address as did: {did}")
        # Check if it's already registered first!
        if self._get_aquarius().ddo_exists(did):
            raise AquariusError(
                f"Asset id {did} is already registered to another asset."
            )

        for service in services:
            if service.type == ServiceTypes.METADATA:
                ddo_service_endpoint = service.service_endpoint
                if "{did}" in ddo_service_endpoint:
                    ddo_service_endpoint = ddo_service_endpoint.replace("{did}", did)
                    service.service_endpoint = ddo_service_endpoint

            asset.add_service(service)

        asset.proof["signatureValue"] = sign_hash(
            encode_defunct(text=asset.asset_id), publisher_wallet
        )

        # Setup metadata service
        # First compute files_encrypted
        assert metadata_copy["main"][
            "files"
        ], "files is required in the metadata main attributes."
        logger.debug("Encrypting content urls in the metadata.")

        publisher_signature = self._data_provider.sign_message(
            publisher_wallet, asset.asset_id, provider_uri=provider_uri
        )
        _, encrypt_endpoint = self._data_provider.build_encrypt_endpoint(provider_uri)
        files_encrypted = self._data_provider.encrypt_files_dict(
            metadata_copy["main"]["files"],
            encrypt_endpoint,
            asset.asset_id,
            publisher_wallet.address,
            publisher_signature,
        )

        # only assign if the encryption worked
        if files_encrypted:
            logger.debug(f"Content urls encrypted successfully {files_encrypted}")
            index = 0
            for file in metadata_copy["main"]["files"]:
                file["index"] = index
                index = index + 1
                del file["url"]
            metadata_copy["encryptedFiles"] = files_encrypted
        else:
            raise AssertionError("Encrypting the files failed.")

        logger.debug(
            f"Generated asset and services, DID is {asset.did},"
            f" metadata service @{ddo_service_endpoint}."
        )

        # Set datatoken address in the asset
        asset.data_token_address = data_token_address
        flags, asset_contents = self._build_asset_contents(asset, encrypt)

        try:
            # publish the new ddo in ocean-db/Aquarius
            ddo_registry = self.ddo_registry()
            tx_id = ddo_registry.create(
                asset.asset_id, flags, asset_contents, publisher_wallet
            )
            if not ddo_registry.verify_tx(tx_id):
                raise VerifyTxFailed(
                    f"create DDO on-chain failed, transaction status is 0. Transaction hash is {tx_id}"
                )
            logger.info("Asset/ddo published on-chain successfully.")
        except ValueError as ve:
            raise ValueError(f"Invalid value to publish in the metadata: {str(ve)}")
        except Exception as e:
            logger.error(f"Publish asset on-chain failed: {str(e)}")
            raise

        return asset
예제 #24
0
def test_ddo_on_chain(config, web3):
    """Tests chain operations on a DDO."""
    ddo_address = get_contracts_addresses(config.address_file, "ganache")[
        MetadataContract.CONTRACT_NAME
    ]
    dtfactory_address = get_contracts_addresses(config.address_file, "ganache")[
        DTFactory.CONTRACT_NAME
    ]
    ddo_registry = MetadataContract(web3, ddo_address)
    wallet = get_publisher_wallet()

    dtfactory = DTFactory(web3, dtfactory_address)
    tx_id = dtfactory.createToken("", "dt1", "dt1", 1000, wallet)
    dt = DataToken(web3, dtfactory.get_token_address(tx_id))

    # test create ddo
    asset = get_ddo_sample(dt.address)
    old_name = asset.metadata["main"]["name"]
    txid = ddo_registry.create(
        asset.asset_id, b"", lzma.compress(Web3.toBytes(text=asset.as_text())), wallet
    )
    assert ddo_registry.verify_tx(txid), f"create ddo failed: txid={txid}"
    logs = ddo_registry.event_MetadataCreated.processReceipt(
        ddo_registry.get_tx_receipt(web3, txid), errors=DISCARD
    )
    assert logs, f"no logs found for create ddo tx {txid}"
    log = logs[0]
    assert add_0x_prefix(log.args.dataToken) == asset.asset_id
    # read back the asset ddo from the event log
    ddo_text = Web3.toText(lzma.decompress(log.args.data))
    assert ddo_text == asset.as_text(), "ddo text does not match original."

    _asset = V3Asset(json_text=ddo_text)
    assert _asset.did == asset.did, "did does not match."
    name = _asset.metadata["main"]["name"]
    assert name == old_name, f"name does not match: {name} != {old_name}"

    # test_update ddo
    asset.metadata["main"]["name"] = "updated name for test"
    txid = ddo_registry.update(
        asset.asset_id, b"", lzma.compress(Web3.toBytes(text=asset.as_text())), wallet
    )
    assert ddo_registry.verify_tx(txid), f"update ddo failed: txid={txid}"
    logs = ddo_registry.event_MetadataUpdated.processReceipt(
        ddo_registry.get_tx_receipt(web3, txid), errors=DISCARD
    )
    assert logs, f"no logs found for update ddo tx {txid}"
    log = logs[0]
    assert add_0x_prefix(log.args.dataToken) == asset.asset_id
    # read back the asset ddo from the event log
    ddo_text = Web3.toText(lzma.decompress(log.args.data))
    assert ddo_text == asset.as_text(), "ddo text does not match original."
    _asset = V3Asset(json_text=ddo_text)
    assert (
        _asset.metadata["main"]["name"] == "updated name for test"
    ), "name does not seem to be updated."
    assert DataToken(web3, asset.asset_id).contract.caller.isMinter(wallet.address)

    # test update fails from wallet other than the original publisher
    bob = get_consumer_wallet()
    try:
        txid = ddo_registry.update(
            asset.asset_id, b"", lzma.compress(Web3.toBytes(text=asset.as_text())), bob
        )
        assert ddo_registry.verify_tx(txid) is False, f"update ddo failed: txid={txid}"
        logs = ddo_registry.event_MetadataUpdated.processReceipt(
            ddo_registry.get_tx_receipt(web3, txid), errors=DISCARD
        )
        assert (
            not logs
        ), f"should be no logs for MetadataUpdated, but seems there are some logs: tx {txid}, logs {logs}"
    except ValueError:
        print("as expected, only owner can update a published ddo.")

    # test ddoOwner
    assert DataToken(web3, asset.asset_id).contract.caller.isMinter(wallet.address), (
        f"ddo owner does not match the expected publisher address {wallet.address}, "
        f"owner is {DataToken(web3, asset.asset_id).contract.caller.minter(wallet.address)}"
    )
예제 #25
0
def download_asset_files(
    service_index: int,
    asset: V3Asset,
    consumer_wallet: Wallet,
    destination: str,
    token_address: str,
    order_tx_id: str,
    data_provider: Type[DataServiceProvider],
    index: Optional[int] = None,
    userdata: Optional[dict] = None,
) -> str:
    """Download asset data files or result files from a compute job.

    :param service_index: identifier of the service inside the asset DDO, str
    :param asset: V3Asset instance
    :param consumer_wallet: Wallet instance of the consumer
    :param destination: Path, str
    :param token_address: hex str the address of the DataToken smart contract
    :param order_tx_id: hex str the transaction hash of the startOrder tx
    :param data_provider: DataServiceProvider class object
    :param index: Index of the document that is going to be downloaded, int
    :return: asset folder path, str
    """
    _files = asset.metadata["main"]["files"]
    sa = asset.get_service(ServiceTypes.ASSET_ACCESS)
    service_endpoint = sa.service_endpoint
    if not service_endpoint:
        logger.error(
            'Consume asset failed, service definition is missing the "serviceEndpoint".'
        )
        raise AssertionError(
            'Consume asset failed, service definition is missing the "serviceEndpoint".'
        )

    _, service_endpoint = data_provider.build_download_endpoint(service_endpoint)
    if not os.path.isabs(destination):
        destination = os.path.abspath(destination)
    if not os.path.exists(destination):
        os.mkdir(destination)

    asset_folder = os.path.join(
        destination, f"datafile.{asset.asset_id}.{service_index}"
    )
    if not os.path.exists(asset_folder):
        os.mkdir(asset_folder)

    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(_files), logger.error(
            "index can not be bigger than the number of files"
        )
        indexes = [index]
    else:
        indexes = range(len(_files))

    for i in indexes:
        data_provider.download_service(
            asset.did,
            service_endpoint,
            consumer_wallet,
            _files,
            asset_folder,
            service_index,
            token_address,
            order_tx_id,
            i,
            userdata,
        )
    return asset_folder
예제 #26
0
def get_algorithm_meta():
    algorithm_ddo_path = get_resource_path("ddo", "ddo_algorithm.json")
    algo_main = V3Asset(json_filename=algorithm_ddo_path).metadata["main"]
    algo_meta_dict = algo_main["algorithm"].copy()
    algo_meta_dict["url"] = algo_main["files"][0]["url"]
    return AlgorithmMetadata(algo_meta_dict)
예제 #27
0
def get_sample_algorithm_ddo() -> V3Asset:
    return V3Asset(json_filename=get_resource_path("ddo", "ddo_algorithm.json"))
예제 #28
0
def get_sample_ddo_with_compute_service() -> V3Asset:
    return V3Asset(
        json_filename=get_resource_path("ddo", "ddo_with_compute_service.json")
    )
예제 #29
0
def get_sample_ddo(file_name="ddo_sa_sample.json") -> V3Asset:
    return V3Asset(json_filename=get_resource_path("ddo", file_name))
예제 #30
0
    def _build_asset_contents(self, asset: V3Asset, encrypt: bool = False):
        if not encrypt:
            return bytes([1]), lzma.compress(Web3.toBytes(text=asset.as_text()))

        return bytes([2]), self._get_aquarius().encrypt(asset.as_text())