Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update registry uri #169

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

@@ -80,16 +80,22 @@ way through the EIP process)

::

scheme://authority/package-name?version=x.x.x
scheme://address:chain_id/package-name?version=x.x.x

- URI must be a string type
- ``scheme``: ``ercxxx``
- ``authority``: Must be a valid ENS domain or a valid checksum address
- ``scheme``: ``erc1319``
- ``address``: Must be a valid ENS domain or a valid checksum address
pointing towards a registry contract.
- ``chain_id``: Chain ID of the chain on which the registry lives. Currently supported chains include...
- 1: Mainnet
- 3: Ropsten
- 4: Rinkeby
- 5: Goerli
- 42: Kovan
- ``package-name``: Must conform to the package-name as specified in
the
`EthPM-Spec <http://ethpm-spec.readthedocs.io/en/latest/package-spec.html#package-name>`__.
- ``version``: The URI escaped version string, *should* conform to the
`semver <http://semver.org/>`__ version numbering specification.

i.e. ``ercxxx://packages.zeppelinos.eth/owned?version=1.0.0``
i.e. ``erc1319://packages.zeppelinos.eth:1/owned?version=1.0.0``
@@ -1,11 +1,12 @@
import re
from typing import Tuple
from typing import Any, Tuple
from urllib import parse

from eth_typing import URI
from eth_utils import add_0x_prefix, remove_0x_prefix
from eth_utils import add_0x_prefix, is_integer, remove_0x_prefix
from web3 import Web3

from ethpm.constants import SUPPORTED_CHAIN_IDS

def get_genesis_block_hash(web3: Web3) -> str:
return web3.eth.getBlock(0)["hash"]
@@ -81,3 +82,12 @@ def create_BIP122_uri(

def create_block_uri(chain_id: str, block_identifier: str) -> URI:
return create_BIP122_uri(chain_id, "block", remove_0x_prefix(block_identifier))


def is_supported_chain_id(chain_id: Any) -> bool:
if not is_integer(chain_id):
return False

if chain_id not in SUPPORTED_CHAIN_IDS.keys():
return False
return True
@@ -9,12 +9,12 @@
from ethpm._utils.registry import fetch_standard_registry_abi
from ethpm.backends.base import BaseURIBackend
from ethpm.constants import INFURA_API_KEY
from ethpm.exceptions import ValidationError
from ethpm.exceptions import CannotHandleURI, ValidationError
from ethpm.validation.uri import validate_registry_uri

# TODO: Update registry ABI once ERC is finalized.
REGISTRY_ABI = fetch_standard_registry_abi()
RegistryURI = namedtuple("RegistryURI", ["auth", "name", "version"])
RegistryURI = namedtuple("RegistryURI", ["address", "chain_id", "name", "version"])


class RegistryURIBackend(BaseURIBackend):
@@ -39,7 +39,11 @@ def fetch_uri_contents(self, uri: str) -> URI:
"""
Return content-addressed URI stored at registry URI.
"""
address, pkg_name, pkg_version = parse_registry_uri(uri)
address, chain_id, pkg_name, pkg_version = parse_registry_uri(uri)
if chain_id != '1':
raise CannotHandleURI(
"Currently only mainnet registry uris are supported."
)
self.w3.enable_unstable_package_management_api()
self.w3.pm.set_registry(address)
_, _, manifest_uri = self.w3.pm.get_release_data(pkg_name, pkg_version)
@@ -65,7 +69,7 @@ def parse_registry_uri(uri: str) -> RegistryURI:
"""
validate_registry_uri(uri)
parsed_uri = parse.urlparse(uri)
authority = parsed_uri.netloc
address, chain_id = parsed_uri.netloc.split(":")
pkg_name = parsed_uri.path.strip("/")
pkg_version = parsed_uri.query.lstrip("version=").strip("/")
return RegistryURI(authority, pkg_name, pkg_version)
return RegistryURI(address, chain_id, pkg_name, pkg_version)
@@ -1,5 +1,4 @@
# TODO update once registry standard eip has been approved
REGISTRY_URI_SCHEME = "ercxxx"
REGISTRY_URI_SCHEME = "erc1319"

PACKAGE_NAME_REGEX = "[a-zA-Z][-_a-zA-Z0-9]{0,255}"

@@ -14,3 +13,11 @@
INFURA_GATEWAY_MULTIADDR = "/dns4/ipfs.infura.io/tcp/5001/https/"

GITHUB_API_AUTHORITY = "api.github.com"

SUPPORTED_CHAIN_IDS = {
1: "mainnet",
3: "ropsten",
4: "rinkeby",
5: "goerli",
42: "kovan",
}
@@ -2,10 +2,11 @@
from typing import List
from urllib import parse

from eth_utils import is_checksum_address, to_bytes, to_text
from eth_utils import is_checksum_address, to_bytes, to_int, to_text
from web3 import Web3

from ethpm._utils.ipfs import is_ipfs_uri
from ethpm._utils.chains import is_supported_chain_id
from ethpm._utils.registry import is_ens_domain
from ethpm.constants import REGISTRY_URI_SCHEME
from ethpm.exceptions import ValidationError
@@ -43,8 +44,26 @@ 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.
"""
if is_ens_domain(auth) is False and not is_checksum_address(auth):
raise ValidationError(f"{auth} is not a valid registry URI authority.")
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"{auth} 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."
)


def validate_registry_uri_scheme(scheme: str) -> None:
@@ -17,7 +17,7 @@
"ipfs://QmTKB75Y73zhNbD3Y73xeXGjYrZHmaXXNxoZqGCagu7r8u/",
(InfuraIPFSBackend, LocalIPFSBackend),
),
("ercXXX://packages.zeppelinos.eth/erc20?version=1.0.0", ()),
("erc1319://packages.zeppelinos.eth:1/erc20?version=1.0.0", ()),
),
)
def test_get_resolvable_backends_for_supported_uris(dummy_ipfs_backend, uri, backends):
@@ -28,7 +28,7 @@ def test_get_resolvable_backends_for_supported_uris(dummy_ipfs_backend, uri, bac
@pytest.mark.parametrize(
"uri,backends",
(
("ercXXX://packages.zeppelinos.eth/erc20?version=1.0.0", (RegistryURIBackend,)),
("erc1319://packages.zeppelinos.eth:1/erc20?version=1.0.0", (RegistryURIBackend,)),
("ipfs://QmTKB75Y73zhNbD3Y73xeXGjYrZHmaXXNxoZqGCagu7r8u/", ()),
),
)
@@ -46,7 +46,7 @@ def test_get_translatable_backends_for_supported_uris(
# filesystem
"file:///path_to_erc20.json",
# invalid registry URI scheme
"erc1128://packages.zeppelinos.eth/erc20/v1.0.0",
"erc1128://packages.zeppelinos.eth:1/erc20/v1.0.0",
# swarm
"bzz://da6adeeb4589d8652bbe5679aae6b6409ec85a20e92a8823c7c99e25dba9493d",
"bzz-immutable:://da6adeeb4589d8652bbe5679aae6b6409ec85a20e92a8823c7c99e25dba9493d",
@@ -1,6 +1,6 @@
import pytest

from ethpm._utils.chains import is_BIP122_block_uri, parse_BIP122_uri
from ethpm._utils.chains import is_BIP122_block_uri, is_supported_chain_id, parse_BIP122_uri

HASH_A = "0x1234567890123456789012345678901234567890123456789012345678901234"
HASH_A_NO_PREFIX = "1234567890123456789012345678901234567890123456789012345678901234"
@@ -36,3 +36,23 @@ def test_parse_BIP122_uri(value, expected_resource_type):
assert chain_id == HASH_A
assert resource_type == expected_resource_type
assert resource_identifier == HASH_B


@pytest.mark.parametrize(
"chain_id,expected",
(
(1, True),
(3, True),
(4, True),
(5, True),
(42, True),
(2, False),
("1", False),
({}, False),
(None, False),
(False, False),
)
)
def test_is_supported_chain_id(chain_id, expected):
actual = is_supported_chain_id(chain_id)
assert actual is expected
@@ -7,18 +7,18 @@
@pytest.mark.parametrize(
"uri",
(
("ercxxx://zeppelinos.eth/erc20/"),
("ercXXX://zeppelinos.eth/erc20/"),
("ercXXX://zeppelinos.eth/erc20//"),
("ercXXX://zeppelinos.eth/erc20?version=1.0.0"),
("ercXXX://zeppelinos.eth/erc20?version=1.0.0/"),
("ercXXX://packages.zeppelinos.eth/erc20?version="),
("ercXXX://packages.zeppelinos.eth/erc20?version=/"),
("ercXXX://packages.zeppelinos.eth/erc20?version=1.0.0"),
("ercXXX://packages.zeppelinos.eth/erc20?version=1.0.0/"),
("ercXXX://packages.ethereum.eth/greeter?version=%3E%3D1.0.2%2C%3C2"),
("ercXXX://0xd3CdA913deB6f67967B99D67aCDFa1712C293601/erc20?version=1.0.0"),
("ercXXX://0xd3CdA913deB6f67967B99D67aCDFa1712C293601/erc20?version=1.0.0/"),
("erc1319://zeppelinos.eth:1/erc20/"),
("erc1319://zeppelinos.eth:1/erc20/"),
("erc1319://zeppelinos.eth:1/erc20//"),
("erc1319://zeppelinos.eth:1/erc20?version=1.0.0"),
("erc1319://zeppelinos.eth:1/erc20?version=1.0.0/"),
("erc1319://packages.zeppelinos.eth:1/erc20?version="),
("erc1319://packages.zeppelinos.eth:1/erc20?version=/"),
("erc1319://packages.zeppelinos.eth:1/erc20?version=1.0.0"),
("erc1319://packages.zeppelinos.eth:1/erc20?version=1.0.0/"),
("erc1319://packages.ethereum.eth:1/greeter?version=%3E%3D1.0.2%2C%3C2"),
("erc1319://0xd3CdA913deB6f67967B99D67aCDFa1712C293601:1/erc20?version=1.0.0"),
("erc1319://0xd3CdA913deB6f67967B99D67aCDFa1712C293601:1/erc20?version=1.0.0/"),
),
)
def test_is_registry_uri_validates(uri):
@@ -29,34 +29,36 @@ def test_is_registry_uri_validates(uri):
"uri",
(
# invalid authority
("ercXXX://packages.zeppelinos.com/erc20?version=1.0.0"),
("ercXXX://package.manager.zeppelinos.eth/erc20?version=1.0.0"),
("ercXXX://packageszeppelinoseth/erc20?version=1.0.0"),
("ercXXX://0xd3cda913deb6f67967b99d67acdfa1712c293601/erc20?version=1.0.0"),
("erc1319://zeppelinos.eth/erc20?version=1.0.0"),
("erc1319://zeppelinos.eth:333/erc20?version=1.0.0"),
("erc1319://packages.zeppelinos.com:1/erc20?version=1.0.0"),
("erc1319://package.manager.zeppelinos.eth:1/erc20?version=1.0.0"),
("erc1319://packageszeppelinoseth:1/erc20?version=1.0.0"),
("erc1319://0xd3cda913deb6f67967b99d67acdfa1712c293601:1/erc20?version=1.0.0"),
# invalid package name
("ercXXX://packages.zeppelinos.eth/"),
("ercXXX://packages.zeppelinos.eth///"),
("ercXXX://packages.zeppelinos.eth/?version=1.0.0"),
("ercXXX://packages.zeppelinos.eth/!rc20?version=1.0.0"),
("erc1319://packages.zeppelinos.eth:1/"),
("erc1319://packages.zeppelinos.eth:1///"),
("erc1319://packages.zeppelinos.eth:1/?version=1.0.0"),
("erc1319://packages.zeppelinos.eth:1/!rc20?version=1.0.0"),
# invalid version param
("ercXXX://zeppelinos.eth/erc20?versions=1.0.0"),
("ercXXX://zeppelinos.eth/erc20?version1.0.0"),
("erc1319://zeppelinos.eth:1/erc20?versions=1.0.0"),
("erc1319://zeppelinos.eth:1/erc20?version1.0.0"),
# malformed
("ercXXXpackageszeppelinosetherc20version1.0.0"),
("ercXXX:packages.zeppelinos.eth/erc20?version=1.0.0"),
("ercXXX:packages.zeppelinos.eth/erc20?version=1.0.0/"),
("ercXXX:/packages.zeppelinos.eth/erc20?version=1.0.0"),
("ercXXX:/packages.zeppelinos.eth/erc20?version=1.0.0/"),
("ercXXX/packages.zeppelinos.eth/erc20?version=1.0.0"),
("ercXXX//packages.zeppelinos.eth/erc20?version=1.0.0"),
("ercXXXpackages.zeppelinos.eth/erc20?version=1.0.0"),
("erc1319packageszeppelinosetherc20version1.0.0"),
("erc1319:packages.zeppelinos.eth:1/erc20?version=1.0.0"),
("erc1319:packages.zeppelinos.eth:1/erc20?version=1.0.0/"),
("erc1319:/packages.zeppelinos.eth:1/erc20?version=1.0.0"),
("erc1319:/packages.zeppelinos.eth:1/erc20?version=1.0.0/"),
("erc1319/packages.zeppelinos.eth:1/erc20?version=1.0.0"),
("erc1319//packages.zeppelinos.eth:1/erc20?version=1.0.0"),
("erc1319packages.zeppelinos.eth:1/erc20?version=1.0.0"),
# wrong scheme
("http://packages.zeppelinos.eth/erc20?version=1.0.0"),
("ercXX://packages.zeppelinos.eth/erc20?version=1.0.0"),
("http://packages.zeppelinos.eth:1/erc20?version=1.0.0"),
("ercXX://packages.zeppelinos.eth:1/erc20?version=1.0.0"),
# no path
("ercXXX://"),
("erc1319://"),
# weird values
(b"ercXXX://zeppelinos.eth/erc20?version=1.0.0"),
(b"erc1319://zeppelinos.eth:1/erc20?version=1.0.0"),
("1234"),
({}),
),
@@ -0,0 +1,21 @@
from ethpm.backends.registry import RegistryURIBackend
from ethpm.exceptions import CannotHandleURI
import pytest


@pytest.fixture
def backend():
return RegistryURIBackend()


def test_registry_uri_backend(backend):
valid_uri = "erc1319://snakecharmers.eth:1/owned?version=1.0.0"
assert backend.can_translate_uri(valid_uri) is True
assert backend.can_resolve_uri(valid_uri) is False
assert backend.fetch_uri_contents(valid_uri) == 'ipfs://QmbeVyFLSuEUxiXKwSsEjef6icpdTdA4kGG9BcrJXKNKUW'


def test_registry_uri_backend_raises_exception_for_non_mainnet_chains(backend):
ropsten_uri = "erc1319://snakecharmers.eth:3/owned?version=1.0.0"
with pytest.raises(CannotHandleURI, match="Currently only mainnet"):
backend.fetch_uri_contents(ropsten_uri)
@@ -68,17 +68,18 @@ def test_create_github_uri():
"uri,expected",
(
(
"ercXXX://0x6b5DA3cA4286Baa7fBaf64EEEE1834C7d430B729/owned?version=1.0.0",
["0x6b5DA3cA4286Baa7fBaf64EEEE1834C7d430B729", "owned", "1.0.0"],
"erc1319://0x6b5DA3cA4286Baa7fBaf64EEEE1834C7d430B729:1/owned?version=1.0.0",
["0x6b5DA3cA4286Baa7fBaf64EEEE1834C7d430B729", "1", "owned", "1.0.0"],
),
(
"ercXXX://0x6b5DA3cA4286Baa7fBaf64EEEE1834C7d430B729/wallet?version=2.8.0/",
["0x6b5DA3cA4286Baa7fBaf64EEEE1834C7d430B729", "wallet", "2.8.0"],
"erc1319://0x6b5DA3cA4286Baa7fBaf64EEEE1834C7d430B729:1/wallet?version=2.8.0/",
["0x6b5DA3cA4286Baa7fBaf64EEEE1834C7d430B729", "1", "wallet", "2.8.0"],
),
),
)
def test_parse_registry_uri(uri, expected):
address, pkg_name, pkg_version = parse_registry_uri(uri)
address, chain_id, pkg_name, pkg_version = parse_registry_uri(uri)
assert address == expected[0]
assert pkg_name == expected[1]
assert pkg_version == expected[2]
assert chain_id == expected[1]
assert pkg_name == expected[2]
assert pkg_version == expected[3]
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.