예제 #1
0
def validate_single_matching_uri(all_blockchain_uris: List[str],
                                 w3: Web3) -> str:
    """
    Return a single block URI after validating that it is the *only* URI in
    all_blockchain_uris that matches the w3 instance.
    """
    matching_uris = [
        uri for uri in all_blockchain_uris
        if check_if_chain_matches_chain_uri(w3, uri)
    ]

    if not matching_uris:
        raise ValidationError("Package has no matching URIs on chain.")
    elif len(matching_uris) != 1:
        raise ValidationError(
            f"Package has too many ({len(matching_uris)}) matching URIs: {matching_uris}."
        )
    return matching_uris[0]
예제 #2
0
def validate_link_ref(offset: int, length: int, bytecode: str) -> str:
    slot_length = offset + length
    slot = bytecode[offset:slot_length]
    if slot[:2] != "__" and slot[-2:] != "__":
        raise ValidationError(
            f"Slot: {slot}, at offset: {offset} of length: {length} is not a valid "
            "link_ref that can be replaced."
        )
    return bytecode
예제 #3
0
 def fetch_uri_contents(self, uri: str) -> bytes:
     ipfs_hash = extract_ipfs_path_from_uri(uri)
     contents = self.client.cat(ipfs_hash)
     validation_hash = generate_file_hash(contents)
     if validation_hash != ipfs_hash:
         raise ValidationError(
             f"Hashed IPFS contents retrieved from uri: {uri} do not match its content hash."
         )
     return contents
def validate_package_against_schema(package_data: Dict[str, Any]) -> None:
    """
    Load and validate package json against schema
    located at RELEASE_PACKAGE_SCHEMA_PATH.
    """
    schema_data = _load_schema_data()
    try:
        validate(package_data, schema_data)
    except jsonValidationError:
        raise ValidationError("Package:{0} invalid for schema:{1}".format(
            package_data, RELEASE_PACKAGE_SCHEMA_PATH))
예제 #5
0
def validate_registry_uri_authority(auth: str) -> None:
    """
    Raise an exception if the authority is not a valid ENS domain
    or a valid checksummed contract address.
    """
    try:
        address, chain_id = auth.split(':')
    except ValueError:
        raise ValidationError(f"{auth} is not a valid registry URI authority. "
                              "Please try again with a valid registry URI.")

    if is_ens_domain(address) is False and not is_checksum_address(address):
        raise ValidationError(f"{address} is not a valid registry address. "
                              "Please try again with a valid registry URI.")

    if not is_supported_chain_id(to_int(text=chain_id)):
        raise ValidationError(
            f"Chain ID: {chain_id} is not supported. Supported chain ids include: "
            "1 (mainnet), 3 (ropsten), 4 (rinkeby), 5 (goerli) and 42 (kovan). "
            "Please try again with a valid registry URI.")
예제 #6
0
def validate_empty_bytes(offset: int, length: int, bytecode: bytes) -> None:
    """
    Validates that segment [`offset`:`offset`+`length`] of
    `bytecode` is comprised of empty bytes (b'\00').
    """
    slot_length = offset + length
    slot = bytecode[offset:slot_length]
    if slot != bytearray(length):
        raise ValidationError(
            f"Bytecode segment: [{offset}:{slot_length}] is not comprised of empty bytes, "
            f"rather: {slot}.")
예제 #7
0
def validate_manifest_against_schema(manifest: Dict[str, Any]) -> None:
    """
    Load and validate manifest against schema
    located at MANIFEST_SCHEMA_PATH.
    """
    schema_data = _load_schema_data()
    try:
        validate(manifest, schema_data)
    except jsonValidationError:
        raise ValidationError("Manifest:{0} invalid for schema:{1}".format(
            manifest, MANIFEST_SCHEMA_PATH))
예제 #8
0
def validate_meta_object(meta: Dict[str, Any],
                         allow_extra_meta_fields: bool) -> None:
    """
    Validates that every key is one of `META_FIELDS` and has a value of the expected type.
    """
    for key, value in meta.items():
        if key in META_FIELDS:
            if type(value) is not META_FIELDS[key]:
                raise ValidationError(
                    f"Values for {key} are expected to have the type {META_FIELDS[key]}, "
                    f"instead got {type(value)}.")
        elif allow_extra_meta_fields:
            if key[:2] != "x-":
                raise ValidationError(
                    "Undefined meta fields need to begin with 'x-', "
                    f"{key} is not a valid undefined meta field.")
        else:
            raise ValidationError(
                f"{key} is not a permitted meta field. To allow undefined fields, "
                "set `allow_extra_meta_fields` to True.")
예제 #9
0
def validate_manifest_against_schema(manifest: Dict[str, Any]) -> None:
    """
    Load and validate manifest against schema
    located at MANIFEST_SCHEMA_PATH.
    """
    schema_data = _load_schema_data()
    try:
        validate(manifest, schema_data)
    except jsonValidationError as e:
        raise ValidationError(
            f"Manifest invalid for schema version {schema_data['version']}. "
            f"Reason: {e.message}")
예제 #10
0
def validate_minimal_contract_data_present(contract_data):
    """
    Validate that contract data contains at least one of the following keys
    necessary to generate contract factory.

    "abi", "bytecode", "runtime_bytecode"
    """
    if not any(key in contract_data.keys()
               for key in ("abi", "bytecode", "runtime_bytecode")):
        raise ValidationError(
            "Minimum required contract data (abi/bytecode/runtime_bytecode) not found."
        )
예제 #11
0
def validate_uri_contents(contents: bytes, validation_hash: str) -> None:
    """
    Validate that the keccak(contents) matches the validation_hash.
    """
    hashed_contents = keccak(contents)
    decoded_validation = decode_hex(validation_hash)
    if hashed_contents != decoded_validation:
        raise ValidationError(
            "Invalid content-addressed URI. "
            f"Validation hash:{to_hex(decoded_validation)} does not match the "
            f"hash of URI contents: {to_hex(hashed_contents)}."
        )
예제 #12
0
    def _validate_name_and_references(self, name: str) -> None:
        validate_contract_name(name)

        if name not in self.deployment_data:
            raise KeyError(
                "Contract name not found in deployment data. "
                f"Available deployments include: {list(sorted(self.deployment_data.keys()))}."
            )

        contract_type = self.deployment_data[name]["contract_type"]
        if contract_type not in self.contract_factories:
            raise ValidationError(
                f"Contract type: {contract_type} for alias: {name} not found. "
                f"Available contract types include: {list(sorted(self.contract_factories.keys()))}."
            )
예제 #13
0
파일: manifest.py 프로젝트: gsmadi/py-ethpm
def validate_manifest_deployments(manifest: Dict[str, Any]) -> None:
    """
    Validate that a manifest's deployments contracts reference existing contract_types.
    """
    if set(("contract_types", "deployments")).issubset(manifest):
        all_contract_types = list(manifest["contract_types"].keys())
        all_deployments = list(manifest["deployments"].values())
        all_deployment_names = extract_contract_types_from_deployments(all_deployments)
        missing_contract_types = set(all_deployment_names).difference(
            all_contract_types
        )
        if missing_contract_types:
            raise ValidationError(
                f"Manifest missing references to contracts: {missing_contract_types}."
            )
예제 #14
0
def validate_blob_uri_contents(contents: bytes, blob_uri: str) -> None:
    """
    Raises an exception if the sha1 hash of the contents does not match the hash found in te
    blob_uri. Formula for how git calculates the hash found here:
    http://alblue.bandlem.com/2011/08/git-tip-of-week-objects.html
    """
    blob_path = parse.urlparse(blob_uri).path
    blob_hash = blob_path.split("/")[-1]
    contents_str = to_text(contents)
    content_length = len(contents_str)
    hashable_contents = "blob " + str(content_length) + "\0" + contents_str
    hash_object = hashlib.sha1(to_bytes(text=hashable_contents))
    if hash_object.hexdigest() != blob_hash:
        raise ValidationError(
            f"Hash of contents fetched from {blob_uri} do not match its hash: {blob_hash}."
        )
예제 #15
0
def validate_package_deployments(package_data: Dict[str, Any]) -> None:
    """
    Validate that a package's deployments contracts reference existing contract_types.
    """
    if set(("contract_types", "deployments")).issubset(package_data):
        all_contract_types = list(package_data["contract_types"].keys())
        all_deployments = list(package_data["deployments"].values())
        all_deployment_names = set(
            itertools.chain.from_iterable(deployment
                                          for deployment in all_deployments))

        missing_contract_types = set(all_deployment_names).difference(
            all_contract_types)
        if missing_contract_types:
            raise ValidationError(
                "Package missing references to contracts: {0}.".format(
                    missing_contract_types))
예제 #16
0
def validate_linked_references(link_deps: Tuple[Tuple[int, bytes], ...],
                               bytecode: bytes) -> None:
    """
    Validates that normalized linked_references (offset, expected_bytes)
    match the corresponding bytecode.
    """
    offsets, values = zip(*link_deps)
    for idx, offset in enumerate(offsets):
        value = values[idx]
        # https://github.com/python/mypy/issues/4975
        offset_value = int(offset)  # type: ignore
        dep_length = len(value)  # type: ignore
        end_of_bytes = offset_value + dep_length
        # Ignore b/c whitespace around ':' conflict b/w black & flake8
        actual_bytes = bytecode[offset_value:end_of_bytes]  # noqa: E203
        if actual_bytes != values[idx]:
            raise ValidationError("Error validating linked reference. "
                                  f"Offset: {offset} "
                                  f"Value: {values[idx]} "
                                  f"Bytecode: {bytecode} .")
예제 #17
0
def validate_registry_uri(uri: str) -> None:
    """
    Raise an exception if the URI does not conform to the registry URI scheme.
    """
    parsed = parse.urlparse(uri)
    scheme, authority, pkg_path, version = (
        parsed.scheme,
        parsed.netloc,
        parsed.path,
        parsed.query,
    )
    validate_registry_uri_scheme(scheme)
    validate_registry_uri_authority(authority)
    pkg_name = pkg_path.lstrip("/")
    if pkg_name:
        validate_package_name(pkg_name)
    if not pkg_name and version:
        raise ValidationError(
            "Registry URIs cannot provide a version without a package name.")
    if version:
        validate_registry_uri_version(version)
예제 #18
0
    def get_contract_type(self, name: str, w3: Web3 = None) -> Contract:
        """
        API to generate a contract factory class.
        """
        current_w3 = None

        if w3 is not None:
            current_w3 = w3
        else:
            current_w3 = self.w3

        validate_contract_name(name)
        validate_w3_instance(current_w3)

        if name in self.package_data['contract_types']:
            contract_data = self.package_data['contract_types'][name]
            validate_minimal_contract_data_present(contract_data)
            contract_kwargs = generate_contract_factory_kwargs(contract_data)
            contract_factory = current_w3.eth.contract(**contract_kwargs)
            return contract_factory
        raise ValidationError(
            "Package does not have contract by name: {}.".format(name))
예제 #19
0
파일: manifest.py 프로젝트: gsmadi/py-ethpm
def validate_raw_manifest_format(raw_manifest: str) -> None:
    """
    Raise a ValidationError if a manifest ...
    - is not tightly packed (i.e. no linebreaks or extra whitespace)
    - does not have alphabetically sorted keys
    - has duplicate keys
    - is not UTF-8 encoded
    - has a trailing newline
    """
    try:
        manifest_dict = json.loads(raw_manifest, encoding="UTF-8")
    except json.JSONDecodeError as err:
        raise json.JSONDecodeError(
            "Failed to load package data. File is not a valid JSON document.",
            err.doc,
            err.pos,
        )
    compact_manifest = json.dumps(manifest_dict, sort_keys=True, separators=(",", ":"))
    if raw_manifest != compact_manifest:
        raise ValidationError(
            "The manifest appears to be malformed. Please ensure that it conforms to the "
            "EthPM-Spec for document format. "
            "http://ethpm.github.io/ethpm-spec/package-spec.html#document-format "
        )
예제 #20
0
def validate_ipfs_uri(uri: str) -> None:
    """
    Raise an exception if the provided URI is not a valid IPFS URI.
    """
    if not is_ipfs_uri(uri):
        raise ValidationError(f"URI: {uri} is not a valid IPFS URI.")
예제 #21
0
def validate_deployments_are_present(manifest: Dict[str, Any]) -> None:
    if "deployments" not in manifest:
        raise ValidationError("Manifest doesn't have a deployments key.")

    if not manifest["deployments"]:
        raise ValidationError("Manifest's deployments key is empty.")
예제 #22
0
def validate_registry_uri_scheme(scheme: str) -> None:
    """
    Raise an exception if the scheme is not the valid registry URI scheme ('ercXXX').
    """
    if scheme != REGISTRY_URI_SCHEME:
        raise ValidationError(f"{scheme} is not a valid registry URI scheme.")
예제 #23
0
파일: manifest.py 프로젝트: gsmadi/py-ethpm
def validate_build_dependencies_are_present(manifest: Dict[str, Any]) -> None:
    if "build_dependencies" not in manifest:
        raise ValidationError("Manifest doesn't have any build dependencies.")

    if not manifest["build_dependencies"]:
        raise ValidationError("Manifest's build dependencies key is empty.")
예제 #24
0
def validate_deployments_are_present(package_data: Dict[str, Any]) -> None:
    if "deployments" not in package_data:
        raise ValidationError("Package doesn't have a deployments key.")

    if not package_data["deployments"]:
        raise ValidationError("Package's deployments key is empty.")
예제 #25
0
def validate_contract_name(name):
    if not CONTRACT_NAME_REGEX.match(name):
        raise ValidationError("Contract name: {0} is not valid.".format(name))
예제 #26
0
def validate_contract_name(name: str) -> None:
    if not CONTRACT_NAME_REGEX.match(name):
        raise ValidationError(f"Contract name: {name} is not valid.")