mirror of
https://github.com/simplex-chat/simplexmq.git
synced 2026-10-23 06:32:22 +00:00
resolver: reduce comments
This commit is contained in:
1 parent
e670d9fa37
commit
ad4077bf14
4 files changed
+30
-62
No files matched your search
@@ -306,8 +306,8 @@ jobs:
|
||||
# Resolver test job
|
||||
# =============================
|
||||
|
||||
# The SNRC resolver is Python and stdlib-only apart from keccak, so it needs
|
||||
# none of the Haskell toolchain above and runs independently of it.
|
||||
# The SNRC resolver is Python, so this job needs none of the Haskell toolchain
|
||||
# above and runs independently of it.
|
||||
|
||||
resolver-test:
|
||||
name: "resolver (python)"
|
||||
@@ -323,8 +323,7 @@ jobs:
|
||||
python-version: "3.13"
|
||||
|
||||
- name: Install resolver dependencies
|
||||
# The only runtime dependency; declared in
|
||||
# scripts/resolver/service/pyproject.toml.
|
||||
# Must match scripts/resolver/service/pyproject.toml.
|
||||
run: python -m pip install "eth-hash[pycryptodome]>=0.7"
|
||||
|
||||
- name: Test
|
||||
|
||||
+15
-21
@@ -131,36 +131,30 @@ identically (`bar.foobar.testing`).
|
||||
|
||||
### Querying by labelhash
|
||||
|
||||
A client that asks whether a name is free is usually about to register it.
|
||||
Whoever runs the resolver sees that question and could register the name first.
|
||||
To avoid that, send the keccak hash of the label instead of the label itself,
|
||||
written in ENS's `[<64 hex>]` form. The answer is the same:
|
||||
A client asking whether a name is free is usually about to register it, and
|
||||
whoever runs the resolver could register it first. To avoid that, send the
|
||||
keccak hash of the label in ENS's `[<64 hex>]` form instead of the label:
|
||||
|
||||
```sh
|
||||
# instead of /resolve/acme.testing
|
||||
curl -s "http://127.0.0.1:8000/resolve/[$(printf acme | keccak-256sum | cut -d' ' -f1)].testing"
|
||||
```
|
||||
|
||||
This works because namehash is `keccak(parent || keccak(label))`. Passing
|
||||
`keccak(label)` gives the same node, so the resolver reads the same record. It
|
||||
learns which name you meant only if it guesses the label and hashes it.
|
||||
namehash is `keccak(parent || keccak(label))`, so this reaches the same node and
|
||||
returns the same record. The resolver learns the name only by guessing the label
|
||||
and hashing it.
|
||||
|
||||
Brackets keep the two forms from colliding. `[` and `]` are not valid in a
|
||||
normalised ENS name, and the dApp normalises before it registers, so no name
|
||||
registered through it can look like this. Nothing on chain checks the character
|
||||
set, but a `[<64 hex>]` label is 66 bytes and the registrar's `maxLabelLength`
|
||||
is 63, so it cannot be registered directly either. ENS uses this same encoding
|
||||
for a label whose preimage it does not know. A plain `0x…` label would not work
|
||||
here, because that is an ordinary name anyone can register.
|
||||
Brackets cannot collide with a real name: they are invalid in a normalised ENS
|
||||
name, and a `[<64 hex>]` label is 66 bytes against the registrar's
|
||||
`maxLabelLength` of 63. A plain `0x…` label is not treated as a hash, since that
|
||||
is an ordinary, registrable name.
|
||||
|
||||
Only 2LDs can be queried by hash. A 2LD is what a registration buys, so it is
|
||||
the only name worth hiding. Subnames are left out because nobody can race you
|
||||
for one: the owner of the 2LD creates them. In a subname the resolver hashes a
|
||||
`[<64 hex>]` label as written instead of decoding it, so such a query points at
|
||||
a node nobody can own.
|
||||
Only 2LDs can be queried this way, as only a 2LD can be raced for: subnames are
|
||||
created by the 2LD's owner. A bracket label in a subname is hashed as written,
|
||||
so it points at a node nobody can own.
|
||||
|
||||
This hides your interest in a name, and nothing more. The registration itself
|
||||
is public, and the controller's commit-reveal protects that step.
|
||||
This hides interest in a name and nothing else: the registration itself is
|
||||
public, and commit-reveal covers that step.
|
||||
|
||||
### Status codes
|
||||
|
||||
|
||||
@@ -124,14 +124,8 @@ def namehash(name: str) -> bytes:
|
||||
return node
|
||||
|
||||
|
||||
# ENS writes a label whose preimage it does not know as `[<64 hex>]`, and that
|
||||
# is the form reused here for a label the caller deliberately withholds. The
|
||||
# brackets are what keep the two forms apart: `[` and `]` are outside the
|
||||
# normalised character set, so no registrable name can take this shape, and the
|
||||
# ecosystem already reads it back as a hash (ensjs `isEncodedLabelhash`; the
|
||||
# subgraph refuses any real label containing a bracket). A bare `0x…` label
|
||||
# would not be safe this way - that is an ordinary, registrable name, kept from
|
||||
# clashing only by a registrar length cap that its owner can raise.
|
||||
# ENS's encoding for a label whose preimage is unknown. Brackets are outside
|
||||
# the normalised character set, so it cannot collide with a registrable name.
|
||||
ENCODED_LABELHASH_LEN = 66 # "[" + 64 hex + "]"
|
||||
|
||||
|
||||
@@ -147,17 +141,11 @@ def is_encoded_labelhash(label: str) -> bool:
|
||||
def node_of(name: str) -> bytes:
|
||||
"""namehash, accepting an encoded labelhash in place of a 2LD's label.
|
||||
|
||||
A client checking whether a name is free is usually about to register it,
|
||||
so the question itself is worth front-running. namehash is defined as
|
||||
keccak(parent || keccak(label)), so a caller who supplies keccak(label)
|
||||
reaches the same node having never sent the label.
|
||||
|
||||
Only 2LDs may be queried this way: that is the name a registration is
|
||||
bought for, so the only one worth hiding. Subnames of any depth are
|
||||
excluded - a subname is created by the 2LD's owner, nobody can race a
|
||||
caller for one, so there is nothing to front-run. A label in `[<64 hex>]`
|
||||
form there is hashed literally, not decoded; as brackets cannot occur in a
|
||||
real registration, such a query names a node nobody can own.
|
||||
keccak(parent || keccak(label)) reaches the same node without the label,
|
||||
so a caller can check a 2LD without disclosing which one they are about to
|
||||
register. Subnames are excluded - only the 2LD's owner creates them, so
|
||||
there is nothing to front-run - and a bracket label there is hashed as
|
||||
written.
|
||||
"""
|
||||
labels = name.split(".")
|
||||
if len(labels) == 2 and is_encoded_labelhash(labels[0]):
|
||||
|
||||
@@ -83,18 +83,11 @@ class SplitLinksTests(unittest.TestCase):
|
||||
|
||||
|
||||
class EncodedLabelhashTests(unittest.TestCase):
|
||||
"""Querying by labelhash instead of by label.
|
||||
"""`node_of` accepts a 2LD's label as an encoded labelhash `[<64 hex>]`,
|
||||
reaching the same node as the label itself."""
|
||||
|
||||
A client asking whether a name is free is usually about to register it, so
|
||||
the question itself is worth front-running by whoever runs the resolver.
|
||||
namehash is keccak(parent || keccak(label)), so supplying keccak(label)
|
||||
yields the same node and the same answer, having never sent the label.
|
||||
|
||||
The encoding is ENS's own `[<64 hex>]`, which cannot collide with a real
|
||||
name: brackets are outside the normalised character set."""
|
||||
|
||||
# keccak-256("alice") = 9c0257114eb9399a2985f8e75dad7600c5d89fe3824ffa99ec1c3eb8bf3b0501
|
||||
# - written out in full wherever a test needs a real labelhash.
|
||||
# keccak-256("alice"), written out in full wherever a test needs it.
|
||||
# 9c0257114eb9399a2985f8e75dad7600c5d89fe3824ffa99ec1c3eb8bf3b0501
|
||||
|
||||
def test_the_encoded_form_is_recognised(self):
|
||||
self.assertTrue(
|
||||
@@ -110,9 +103,8 @@ class EncodedLabelhashTests(unittest.TestCase):
|
||||
|
||||
def test_non_hex_between_the_brackets_is_not(self):
|
||||
self.assertFalse(snrc.is_encoded_labelhash("[" + "z" * 64 + "]"))
|
||||
# uppercase hex is not it either: the handler lowercases the whole name
|
||||
# uppercase is rejected because the handler lowercases the whole name
|
||||
self.assertFalse(snrc.is_encoded_labelhash("[" + "A" * 64 + "]"))
|
||||
# explicitly disallowed prefix
|
||||
self.assertFalse(snrc.is_encoded_labelhash("[0x9c0257114eb9399a2985f8e75dad7600c5d89fe3824ffa99ec1c3eb8bf3b0501]"))
|
||||
|
||||
def test_the_wrong_length_is_not(self):
|
||||
@@ -132,9 +124,6 @@ class EncodedLabelhashTests(unittest.TestCase):
|
||||
self.assertEqual(snrc.node_of("alice.testing"), snrc.namehash("alice.testing"))
|
||||
|
||||
def test_an_encoded_subname_is_not_the_name_it_would_decode_to(self):
|
||||
"""Only 2LDs are queried by hash. If a label in `[<64 hex>]` form were
|
||||
decoded in a subname, that subname would silently be the name the hash
|
||||
stands for - here `alice.alice.testing`."""
|
||||
self.assertNotEqual(
|
||||
snrc.node_of(
|
||||
"[9c0257114eb9399a2985f8e75dad7600c5d89fe3824ffa99ec1c3eb8bf3b0501]"
|
||||
@@ -152,8 +141,6 @@ class EncodedLabelhashTests(unittest.TestCase):
|
||||
)
|
||||
|
||||
def test_a_0x_prefixed_label_is_taken_literally(self):
|
||||
"""`0x<64 hex>` is a registrable name, not a hash - the brackets are
|
||||
what make the hashed form unambiguous."""
|
||||
name = "0x9c0257114eb9399a2985f8e75dad7600c5d89fe3824ffa99ec1c3eb8bf3b0501.testing"
|
||||
self.assertEqual(snrc.node_of(name), snrc.namehash(name))
|
||||
self.assertNotEqual(snrc.node_of(name), snrc.node_of("alice.testing"))
|
||||
|
||||
Reference in new issue
Block a user