Skip to content

Commit

Permalink
Merge pull request #1393 from njgheorghita/web3-pm-management
Browse files Browse the repository at this point in the history
[ethPM] web3.pm management
  • Loading branch information
njgheorghita authored Jul 24, 2019
2 parents fdfe96f + c4c5f57 commit 8c12dc4
Show file tree
Hide file tree
Showing 24 changed files with 98 additions and 94 deletions.
2 changes: 1 addition & 1 deletion docs/ethpm.rst
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ By default, the manifest builder does *not* perform any validation that the gene
... validate(),
... )
Traceback (most recent call last):
ethpm.exceptions.ValidationError: Manifest invalid for schema version 2. Reason: '_InvalidPkgName' does not match '^[a-z][-a-z0-9]{0,255}$'
ethpm.exceptions.EthPMValidationError: Manifest invalid for schema version 2. Reason: '_InvalidPkgName' does not match '^[a-z][-a-z0-9]{0,255}$'


To write a manifest to disk
Expand Down
14 changes: 7 additions & 7 deletions ethpm/_utils/deployments.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

from ethpm.exceptions import (
BytecodeLinkingError,
ValidationError,
EthPMValidationError,
)
from web3 import Web3

Expand Down Expand Up @@ -60,7 +60,7 @@ def validate_linked_references(
# 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(
raise EthPMValidationError(
"Error validating linked reference. "
f"Offset: {offset} "
f"Value: {values[idx]} "
Expand Down Expand Up @@ -97,7 +97,7 @@ def validate_deployments_tx_receipt(
tx_address = tx_receipt["contractAddress"]

if tx_address is None and allow_missing_data is False:
raise ValidationError(
raise EthPMValidationError(
"No contract address found in tx receipt. Unable to verify "
"address found in tx receipt matches address in manifest's deployment data. "
"If this validation is not necessary, please enable `allow_missing_data` arg. "
Expand All @@ -106,27 +106,27 @@ def validate_deployments_tx_receipt(
if tx_address is not None and not is_same_address(
tx_address, data["address"]
):
raise ValidationError(
raise EthPMValidationError(
f"Error validating tx_receipt for {name} deployment. "
f"Address found in manifest's deployment data: {data['address']} "
f"Does not match address found on tx_receipt: {tx_address}."
)

if "block" in data:
if tx_receipt["blockHash"] != to_bytes(hexstr=data["block"]):
raise ValidationError(
raise EthPMValidationError(
f"Error validating tx_receipt for {name} deployment. "
f"Block found in manifest's deployment data: {data['block']} does not "
f"Does not match block found on tx_receipt: {tx_receipt['blockHash']}."
)
elif allow_missing_data is False:
raise ValidationError(
raise EthPMValidationError(
"No block hash found in deployment data. "
"Unable to verify block hash on tx receipt. "
"If this validation is not necessary, please enable `allow_missing_data` arg."
)
elif allow_missing_data is False:
raise ValidationError(
raise EthPMValidationError(
"No transaction hash found in deployment data. "
"Unable to validate tx_receipt. "
"If this validation is not necessary, please enable `allow_missing_data` arg."
Expand Down
15 changes: 9 additions & 6 deletions ethpm/backends/ipfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
)
from ethpm.exceptions import (
CannotHandleURI,
ValidationError,
EthPMValidationError,
)


Expand Down Expand Up @@ -80,11 +80,14 @@ def __init__(self) -> None:
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."
)
# Local validation of hashed contents only works for non-chunked files ~< 256kb
# Improved validation WIP @ https://github.com/ethpm/py-ethpm/pull/165
if len(contents) <= 262144:
validation_hash = generate_file_hash(contents)
if validation_hash != ipfs_hash:
raise EthPMValidationError(
f"Hashed IPFS contents retrieved from uri: {uri} do not match its content hash."
)
return contents

@property
Expand Down
4 changes: 2 additions & 2 deletions ethpm/backends/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
)
from ethpm.exceptions import (
CannotHandleURI,
ValidationError,
EthPMValidationError,
)
from ethpm.validation.uri import (
validate_registry_uri,
Expand Down Expand Up @@ -68,7 +68,7 @@ def is_valid_registry_uri(uri: str) -> bool:
"""
try:
validate_registry_uri(uri)
except ValidationError:
except EthPMValidationError:
return False
else:
return True
Expand Down
6 changes: 3 additions & 3 deletions ethpm/contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

from ethpm.exceptions import (
BytecodeLinkingError,
ValidationError,
EthPMValidationError,
)
from ethpm.validation.misc import (
validate_empty_bytes,
Expand Down Expand Up @@ -136,7 +136,7 @@ def is_prelinked_bytecode(bytecode: bytes, link_refs: List[Dict[str, Any]]) -> b
for offset in link_ref["offsets"]:
try:
validate_empty_bytes(offset, link_ref["length"], bytecode)
except ValidationError:
except EthPMValidationError:
return True
return False

Expand Down Expand Up @@ -165,7 +165,7 @@ def apply_link_ref(offset: int, length: int, value: bytes, bytecode: bytes) -> b
"""
try:
validate_empty_bytes(offset, length, bytecode)
except ValidationError:
except EthPMValidationError:
raise BytecodeLinkingError("Link references cannot be applied to bytecode")

address = value if is_canonical_address(value) else to_canonical_address(value)
Expand Down
4 changes: 2 additions & 2 deletions ethpm/deployments.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
)

from ethpm.exceptions import (
ValidationError,
EthPMValidationError,
)
from ethpm.validation.package import (
validate_contract_name,
Expand Down Expand Up @@ -79,7 +79,7 @@ def _validate_name_and_references(self, name: str) -> None:

contract_type = self.deployment_data[name]["contract_type"]
if contract_type not in self.contract_factories:
raise ValidationError(
raise EthPMValidationError(
f"Contract type: {contract_type} for alias: {name} not found. "
f"Available contract types include: {list(sorted(self.contract_factories.keys()))}."
)
2 changes: 1 addition & 1 deletion ethpm/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class InsufficientAssetsError(PyEthPMError):
pass


class ValidationError(PyEthPMError):
class EthPMValidationError(PyEthPMError):
"""
Raised when something does not pass a validation check.
"""
Expand Down
6 changes: 3 additions & 3 deletions ethpm/tools/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@
BaseIPFSBackend,
)
from ethpm.exceptions import (
EthPMValidationError,
ManifestBuildingError,
ValidationError,
)
from ethpm.package import (
format_manifest,
Expand Down Expand Up @@ -559,7 +559,7 @@ 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(
raise EthPMValidationError(
f"Slot: {slot}, at offset: {offset} of length: {length} is not a valid "
"link_ref that can be replaced."
)
Expand Down Expand Up @@ -734,7 +734,7 @@ def build_dependency(package_name: str, uri: URI) -> Manifest:
def _build_dependency(package_name: str, uri: URI, manifest: Manifest) -> Manifest:
validate_package_name(package_name)
if not is_supported_content_addressed_uri(uri):
raise ValidationError(
raise EthPMValidationError(
f"{uri} is not a supported content-addressed URI. "
"Currently only IPFS and Github blob uris are supported."
)
Expand Down
22 changes: 11 additions & 11 deletions ethpm/validation/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
SPEC_DIR,
)
from ethpm.exceptions import (
ValidationError,
EthPMValidationError,
)

MANIFEST_SCHEMA_PATH = SPEC_DIR / "package.spec.json"
Expand All @@ -37,18 +37,18 @@ def validate_meta_object(meta: Dict[str, Any], allow_extra_meta_fields: bool) ->
for key, value in meta.items():
if key in META_FIELDS:
if type(value) is not META_FIELDS[key]:
raise ValidationError(
raise EthPMValidationError(
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(
raise EthPMValidationError(
"Undefined meta fields need to begin with 'x-', "
f"{key} is not a valid undefined meta field."
)
else:
raise ValidationError(
raise EthPMValidationError(
f"{key} is not a permitted meta field. To allow undefined fields, "
"set `allow_extra_meta_fields` to True."
)
Expand Down Expand Up @@ -77,7 +77,7 @@ def validate_manifest_against_schema(manifest: Dict[str, Any]) -> None:
try:
validate(manifest, schema_data)
except jsonValidationError as e:
raise ValidationError(
raise EthPMValidationError(
f"Manifest invalid for schema version {schema_data['version']}. "
f"Reason: {e.message}"
)
Expand All @@ -91,10 +91,10 @@ def check_for_deployments(manifest: Dict[str, Any]) -> bool:

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.")
raise EthPMValidationError("Manifest doesn't have any build dependencies.")

if not manifest["build_dependencies"]:
raise ValidationError("Manifest's build dependencies key is empty.")
raise EthPMValidationError("Manifest's build dependencies key is empty.")


def validate_manifest_deployments(manifest: Dict[str, Any]) -> None:
Expand All @@ -109,7 +109,7 @@ def validate_manifest_deployments(manifest: Dict[str, Any]) -> None:
all_contract_types
)
if missing_contract_types:
raise ValidationError(
raise EthPMValidationError(
f"Manifest missing references to contracts: {missing_contract_types}."
)

Expand All @@ -119,14 +119,14 @@ def validate_manifest_exists(manifest_id: str) -> None:
Validate that manifest with manifest_id exists in ASSETS_DIR
"""
if not (ASSETS_DIR / manifest_id).is_file():
raise ValidationError(
raise EthPMValidationError(
f"Manifest not found in ASSETS_DIR with id: {manifest_id}"
)


def validate_raw_manifest_format(raw_manifest: str) -> None:
"""
Raise a ValidationError if a manifest ...
Raise a EthPMValidationError if a manifest ...
- is not tightly packed (i.e. no linebreaks or extra whitespace)
- does not have alphabetically sorted keys
- has duplicate keys
Expand All @@ -143,7 +143,7 @@ def validate_raw_manifest_format(raw_manifest: str) -> None:
)
compact_manifest = json.dumps(manifest_dict, sort_keys=True, separators=(",", ":"))
if raw_manifest != compact_manifest:
raise ValidationError(
raise EthPMValidationError(
"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 "
Expand Down
4 changes: 2 additions & 2 deletions ethpm/validation/misc.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from ethpm.exceptions import (
ValidationError,
EthPMValidationError,
)
from web3 import Web3

Expand All @@ -17,7 +17,7 @@ def validate_empty_bytes(offset: int, length: int, bytecode: bytes) -> None:
slot_length = offset + length
slot = bytecode[offset:slot_length]
if slot != bytearray(length):
raise ValidationError(
raise EthPMValidationError(
f"Bytecode segment: [{offset}:{slot_length}] is not comprised of empty bytes, "
f"rather: {slot}."
)
12 changes: 6 additions & 6 deletions ethpm/validation/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
PACKAGE_NAME_REGEX,
)
from ethpm.exceptions import (
EthPMValidationError,
InsufficientAssetsError,
ValidationError,
)


Expand All @@ -37,7 +37,7 @@ def validate_package_version(version: Any) -> None:
Validates that a package version is of text type.
"""
if not is_text(version):
raise ValidationError(
raise EthPMValidationError(
f"Expected a version of text type, instead received {type(version)}."
)

Expand All @@ -48,15 +48,15 @@ def validate_package_name(pkg_name: str) -> None:
as defined in the EthPM-Spec.
"""
if not bool(re.match(PACKAGE_NAME_REGEX, pkg_name)):
raise ValidationError(f"{pkg_name} is not a valid package name.")
raise EthPMValidationError(f"{pkg_name} is not a valid package name.")


def validate_manifest_version(version: str) -> None:
"""
Raise an exception if the version is not "2".
"""
if not version == "2":
raise ValidationError(
raise EthPMValidationError(
f"Py-EthPM does not support the provided specification version: {version}"
)

Expand All @@ -69,12 +69,12 @@ def validate_build_dependency(key: str, uri: str) -> None:
validate_package_name(key)
# validate is supported content-addressed uri
if not is_ipfs_uri(uri):
raise ValidationError(f"URI: {uri} is not a valid IPFS URI.")
raise EthPMValidationError(f"URI: {uri} is not a valid IPFS URI.")


CONTRACT_NAME_REGEX = re.compile("^[a-zA-Z][-a-zA-Z0-9_]{0,255}$")


def validate_contract_name(name: str) -> None:
if not CONTRACT_NAME_REGEX.match(name):
raise ValidationError(f"Contract name: {name} is not valid.")
raise EthPMValidationError(f"Contract name: {name} is not valid.")
Loading

0 comments on commit 8c12dc4

Please sign in to comment.