Esempio n. 1
0
def setup_all():
    config = ExampleConfig.get_config()
    ConfigProvider.set_config(config)
    Web3Provider.init_web3(
        provider=get_web3_connection_provider(config.network_url))
    ContractHandler.set_artifacts_path(config.artifacts_path)

    network = Web3Helper.get_network_name()
    wallet = get_ganache_wallet()
    if network in ["ganache", "development"] and wallet:

        print(
            f"sender: {wallet.key}, {wallet.address}, {wallet.password}, {wallet.keysStr()}"
        )
        print(
            f"sender balance: {Web3Helper.from_wei(Web3Helper.get_ether_balance(wallet.address))}"
        )
        assert Web3Helper.from_wei(Web3Helper.get_ether_balance(
            wallet.address)) > 10

        from ocean_lib.models.data_token import DataToken

        OCEAN_token = DataToken(get_ocean_token_address(network))
        amt_distribute = 1000
        amt_distribute_base = to_base_18(float(amt_distribute))
        for w in (get_publisher_wallet(), get_consumer_wallet()):
            if Web3Helper.from_wei(Web3Helper.get_ether_balance(
                    w.address)) < 2:
                Web3Helper.send_ether(wallet, w.address, 4)

            if OCEAN_token.token_balance(w.address) < 100:
                OCEAN_token.transfer(w.address,
                                     amt_distribute_base,
                                     from_wallet=wallet)
def get_network_name():
    try:
        network_name = os.getenv('NETWORK_NAME')
        if not network_name:
            network_name = Web3Helper.get_network_name().lower()
    except Exception:
        network = os.getenv('EVENTS_RPC')
        if network.startswith('wss://'):
            network_name = network[len('wss://'):].split('.')[0]
        elif not network.startswith('http'):
            network_name = network
        else:
            network_name = os.getenv('NETWORK_NAME')

        if not network_name:
            raise AssertionError(f'Cannot figure out the network name.')

    return network_name
Esempio n. 3
0
    def __init__(self, config=None, data_provider=None):
        """Initialize Ocean class.

           >> # Make a new Ocean instance
           >> ocean = Ocean({...})

        This class provides the main top-level functions in ocean protocol:
         * Publish assets metadata and associated services
            * Each asset is assigned a unique DID and a DID Document (DDO)
            * The DDO contains the asset's services including the metadata
            * The DID is registered on-chain with a URL of the metadata store
              to retrieve the DDO from

            >> asset = ocean.assets.create(metadata, publisher_wallet)

         * Discover/Search assets via the current configured metadata store (Aquarius)
            >> assets_list = ocean.assets.search('search text')

        An instance of Ocean is parameterized by a `Config` instance.

        :param config: Config instance
        :param data_provider: DataServiceProvider instance
        """
        # Configuration information for the market is stored in the Config class
        # config = Config(filename=config_file, options_dict=config_dict)
        if not config:
            try:
                config = ConfigProvider.get_config()
            except AssertionError:
                config = Config(os.getenv(ENV_CONFIG_FILE))
                ConfigProvider.set_config(config)
        if isinstance(config, dict):
            # fallback to metadataStoreUri
            cache_key = ("metadataCacheUri" if ("metadataCacheUri" in config)
                         else "metadataStoreUri")
            aqua_url = config.get(
                cache_key, config.get("aquarius.url", "http://localhost:5000"))
            config_dict = {
                "eth-network": {
                    "network": config.get("network", "")
                },
                "resources": {
                    "aquarius.url":
                    aqua_url,
                    "provider.url":
                    config.get("providerUri", "http://localhost:8030"),
                },
            }
            config = Config(options_dict=config_dict)
        ConfigProvider.set_config(config)
        self._config = config
        ContractHandler.set_artifacts_path(self._config.artifacts_path)
        Web3Provider.init_web3(
            provider=get_web3_connection_provider(self._config.network_url))

        self._web3 = Web3Provider.get_web3()

        if not data_provider:
            data_provider = DataServiceProvider

        network = Web3Helper.get_network_name()
        addresses = get_contracts_addresses(network, self._config)
        self.assets = OceanAssets(
            self._config, data_provider,
            addresses.get(MetadataContract.CONTRACT_NAME))
        self.services = OceanServices()
        self.auth = OceanAuth(self._config.storage_path)
        self.compute = OceanCompute(self.auth, self._config, data_provider)

        ocean_address = get_ocean_token_address(network)
        self.pool = OceanPool(ocean_address, get_bfactory_address(network))
        self.exchange = OceanExchange(
            ocean_address,
            FixedRateExchange.configured_address(
                network or Web3Helper.get_network_name(),
                ConfigProvider.get_config().address_file,
            ),
            self.config,
        )

        logger.debug("Ocean instance initialized: ")
Esempio n. 4
0
 def get_dtfactory(self, dtfactory_address: str = "") -> DTFactory:
     dtf_address = dtfactory_address or DTFactory.configured_address(
         Web3Helper.get_network_name(), self._config.address_file)
     return DTFactory(dtf_address)
Esempio n. 5
0
 def OCEAN_address(self):
     return get_ocean_token_address(Web3Helper.get_network_name())
Esempio n. 6
0
    def create(
        self,
        metadata: dict,
        publisher_wallet: Wallet,
        service_descriptors: list = None,
        owner_address: str = None,
        data_token_address: str = None,
        provider_uri=None,
        dt_name: str = None,
        dt_symbol: str = None,
        dt_blob: str = None,
        dt_cap: float = None,
    ) -> (Asset, None):
        """
        Register an asset on-chain by 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 service_descriptors: list of ServiceDescriptor tuples of length 2.
            The first item must be one of ServiceTypes and the second
            item is a dict of parameters and values required by the service
        :param 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: float
        :return: DDO instance
        """
        assert isinstance(
            metadata,
            dict), f"Expected metadata of type dict, got {type(metadata)}"
        assert service_descriptors is None or isinstance(
            service_descriptors, list
        ), f"bad type of `service_descriptors` {type(service_descriptors)}"

        # 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}"
        if not plecos.is_valid_dict_local(metadata_copy):
            errors = plecos.list_errors_dict_local(metadata_copy)
            msg = f"Metadata has validation errors: {errors}"
            logger.error(msg)
            raise ValueError(msg)

        service_descriptors = service_descriptors or []

        services = self._process_service_descriptors(service_descriptors,
                                                     metadata_copy,
                                                     provider_uri,
                                                     publisher_wallet)

        stype_to_service = {s.type: s for s in services}
        checksum_dict = dict()
        for service in services:
            checksum_dict[str(service.index)] = checksum(service.main)

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

        #################
        # DataToken
        address = DTFactory.configured_address(Web3Helper.get_network_name(),
                                               self._config.address_file)
        dtfactory = DTFactory(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,
                                          to_base_18(_cap),
                                          from_wallet=publisher_wallet)
            data_token = DataToken(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:
            # verify data_token_address
            dt = DataToken(data_token_address)
            minter = dt.contract_concise.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."
                )
            elif not dtfactory.verify_data_token(data_token_address):
                raise AssertionError(
                    f"datatoken address {data_token_address} is not found in the DTFactory events."
                )

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

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

        md_service = stype_to_service[ServiceTypes.METADATA]
        ddo_service_endpoint = md_service.service_endpoint
        if "{did}" in ddo_service_endpoint:
            ddo_service_endpoint = ddo_service_endpoint.replace("{did}", did)
            md_service.set_service_endpoint(ddo_service_endpoint)

        # Populate the ddo services
        asset.add_service(md_service)
        access_service = stype_to_service.get(ServiceTypes.ASSET_ACCESS, None)
        compute_service = stype_to_service.get(ServiceTypes.CLOUD_COMPUTE,
                                               None)

        if access_service:
            asset.add_service(access_service)
        if compute_service:
            asset.add_service(compute_service)

        asset.proof["signatureValue"] = Web3Helper.sign_hash(
            add_ethereum_prefix_and_hash_msg(asset.asset_id), publisher_wallet)

        # Add public key and authentication
        asset.add_public_key(did, publisher_wallet.address)

        asset.add_authentication(did, PUBLIC_KEY_TYPE_RSA)

        # 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, self._config)
        _, 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

        try:
            # publish the new ddo in ocean-db/Aquarius
            ddo_registry = self.ddo_registry()
            web3 = Web3Provider.get_web3()
            tx_id = ddo_registry.create(
                asset.asset_id,
                bytes([1]),
                lzma.compress(web3.toBytes(text=asset.as_text())),
                publisher_wallet,
            )
            if not ddo_registry.verify_tx(tx_id):
                raise AssertionError(
                    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
Esempio n. 7
0
def get_ocean_token_address(network=None):
    addresses = get_contracts_addresses(
        network or Web3Helper.get_network_name(), ConfigProvider.get_config())
    return addresses.get("Ocean") if addresses else None
Esempio n. 8
0
def get_bfactory_address(network=None):
    return BFactory.configured_address(
        network or Web3Helper.get_network_name(),
        ConfigProvider.get_config().address_file,
    )
Esempio n. 9
0
def test_get_OCEAN_address(publisher_ocean_instance):
    """Tests OCEAN address retrieval."""
    network = Web3Helper.get_network_name()
    assert publisher_ocean_instance.pool.get_OCEAN_address(
    ) == get_ocean_token_address(network)