Skip to content

Commit

Permalink
Remove IDNA processing in favor of UTS46
Browse files Browse the repository at this point in the history
  • Loading branch information
kclowes committed Jul 10, 2019
1 parent 609b465 commit 90af64d
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 46 deletions.
2 changes: 0 additions & 2 deletions ens/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,4 @@
EMPTY_SHA3_BYTES = b'\0' * 32
EMPTY_ADDR_HEX = '0x' + '00' * 20

MIN_ETH_LABEL_LENGTH = 7

REVERSE_REGISTRAR_DOMAIN = 'addr.reverse'
38 changes: 3 additions & 35 deletions ens/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@
AUCTION_START_GAS_CONSTANT,
AUCTION_START_GAS_MARGINAL,
EMPTY_SHA3_BYTES,
MIN_ETH_LABEL_LENGTH,
REVERSE_REGISTRAR_DOMAIN,
)
from ens.exceptions import (
InvalidLabel,
InvalidName,
)

Expand Down Expand Up @@ -81,10 +79,11 @@ def normalize_name(name):
return name
elif isinstance(name, (bytes, bytearray)):
name = name.decode('utf-8')

try:
return idna.decode(name, uts46=True, std3_rules=True)
return idna.uts46_remap(name, std3_rules=True)
except idna.IDNAError as exc:
raise InvalidName("%s is an invalid name, because %s" % (name, exc)) from exc
raise InvalidName(f"{name} is an invalid name, because {exc}") from exc


def is_valid_name(name):
Expand All @@ -104,37 +103,6 @@ def is_valid_name(name):
return False


def name_to_label(name, registrar):
name = normalize_name(name)
if '.' not in name:
label = name
else:
name_pieces = name.split('.')
registrar_pieces = registrar.split('.')
if len(name_pieces) != len(registrar_pieces) + 1:
raise ValueError(
"You must specify a label, like 'tickets' "
"or a fully-qualified name, like 'tickets.%s'" % registrar
)
label, *label_registrar = name_pieces
if label_registrar != registrar_pieces:
raise ValueError("This interface only manages names under .%s " % registrar)
return label


def dot_eth_label(name):
"""
Convert from a name, like 'ethfinex.eth', to a label, like 'ethfinex'
If name is already a label, this should be a noop, except for converting to a string
and validating the name syntax.
"""
label = name_to_label(name, registrar='eth')
if len(label) < MIN_ETH_LABEL_LENGTH:
raise InvalidLabel('name %r is too short' % label)
else:
return label


def to_utc_datetime(timestamp):
if timestamp:
return datetime.datetime.fromtimestamp(timestamp, datetime.timezone.utc)
Expand Down
2 changes: 0 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
get_open_port,
)

pytest_plugins = ["pytest_ethereum.plugins"]


@pytest.fixture(scope="module", params=[lambda x: to_bytes(hexstr=x), identity])
def address_conversion_func(request):
Expand Down
4 changes: 2 additions & 2 deletions tests/core/utilities/test_abi_is_encodable.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@
('dennisthepeasant.eth', 'address', True), # passes because eth_utils converts to bytes :/
('autonomouscollective.eth', 'address', True),
('all-TLDs-valid-now.test', 'address', True),
('-rejects-invalid-names.test', 'address', False),
('ff', 'address', True), # this could theoretically be a top-level domain (TLD)
('0xname.eth', 'address', True), # 0x in name is fine, if it is not a TLD
('rejects_invalid_names.eth', 'address', False), # no underscore in domain names
# Special bytes<M> behavior
('12', 'bytes2', True), # undersize OK
Expand Down Expand Up @@ -66,7 +66,7 @@
(('1', 0), '(bytes,int128)', False),
(('dennisthepeasant.eth', 0), '(address,int128)', True),
(('-rejects-invalid-names.test', 0), '(address,int128)', False),
(('rejects_invalid_domains.eth', 0), '(address,int128)', False),
((b'anything', 0), '(string,int128)', True),
((b'\x80', 0), '(string,int128)', False),
Expand Down
23 changes: 18 additions & 5 deletions tests/ens/test_nameprep.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,25 @@ def test_nameprep_basic_unicode(ens):
assert ens.nameprep("öbb.at") == "öbb.at"
assert ens.nameprep("Öbb.at") == "öbb.at"
assert ens.nameprep("O\u0308bb.at") == "öbb.at"
assert ens.nameprep("xn--bb-eka.at") == "öbb.at"
assert ens.nameprep("faß.de") == "faß.de"
assert ens.nameprep("fass.de") == "fass.de"
assert ens.nameprep("xn--fa-hia.de") == "faß.de"
assert ens.nameprep("🌈rainbow.eth") == "🌈rainbow.eth"
assert ens.nameprep("🐔🐔.tk") == "🐔🐔.tk"
assert ens.nameprep("√.com") == "√.com"
assert ens.nameprep("ԛәлп.com") == "ԛәлп.com"
assert ens.nameprep("test\u200btest.com") == "testtest.com"
assert ens.nameprep("-test.com") == "-test.com"
assert ens.nameprep("1test.com") == "1test.com"
assert ens.nameprep("test.1com") == "test.1com"


def test_nameprep_std3_rules(ens):
with pytest.raises(InvalidName):
ens.nameprep("not=std3")
@pytest.mark.parametrize(
'url', [
('not=std3'),
('not_std3.eth'), # underscores not allowed
]
)
def test_nameprep_std3_rules(ens, url):
with pytest.raises(InvalidName,
match=f'{url} is an invalid name'):
ens.nameprep(url)

0 comments on commit 90af64d

Please sign in to comment.