173 lines
8.4 KiB
Markdown
173 lines
8.4 KiB
Markdown
---
|
|
eip: 1459
|
|
title: Node Discovery via DNS
|
|
description: Scheme for authenticated updateable Ethereum node lists via DNS.
|
|
author: Felix Lange (@fjl), Péter Szilágyi (@karalabe)
|
|
discussions-to: https://github.com/ethereum/devp2p/issues/50
|
|
status: Draft
|
|
type: Standards Track
|
|
category: Networking
|
|
created: 2018-09-26
|
|
requires: 778
|
|
---
|
|
|
|
## Abstract
|
|
|
|
This document describes a scheme for authenticated, updateable Ethereum node
|
|
lists retrievable via DNS.
|
|
|
|
## Motivation
|
|
|
|
Many Ethereum clients contain hard-coded bootstrap node lists. Updating those
|
|
lists requires a software update. The current lists are small, giving the client
|
|
little choice of initial entry point into the Ethereum network. We would like to
|
|
maintain larger node lists containing hundreds of nodes, and update them
|
|
regularly.
|
|
|
|
The scheme described here is a replacement for client bootstrap node lists with
|
|
equivalent security and many additional benefits. Large lists populated by
|
|
traversing the node discovery DHT can serve as a fallback option for nodes which
|
|
can't join the DHT due to restrictive network policy. DNS-based node lists may
|
|
also be useful to Ethereum peering providers because their customers can
|
|
configure the client to use the provider's list.
|
|
|
|
## Specification
|
|
|
|
A 'node list' is a list of 'node records' [as defined by EIP-778](./eip-778.md)
|
|
of arbitrary length. Lists
|
|
may refer to other lists using links. The entire list is signed using a
|
|
secp256k1 private key. The corresponding public key must be known to the client
|
|
in order to verify the list.
|
|
|
|
To refer to a DNS node list, clients use a URL with 'enrtree' scheme. The URL
|
|
contains the DNS name on which the list can be found as well as the public key
|
|
that signed the list. The public key is contained in the username part of the
|
|
URL and is the base32 encoding (RFC-4648) of the compressed 32-byte binary public key.
|
|
|
|
Example:
|
|
|
|
enrtree://AM5FCQLWIZX2QFPNJAP7VUERCCRNGRHWZG3YYHIUV7BVDQ5FDPRT2@nodes.example.org
|
|
|
|
This URL refers to a node list at the DNS name 'nodes.example.org' and is signed
|
|
by the public key
|
|
`0x049f88229042fef9200246f49f94d9b77c4e954721442714e85850cb6d9e5daf2d880ea0e53cb3ac1a75f9923c2726a4f941f7d326781baa6380754a360de5c2b6`
|
|
|
|
### DNS Record Structure
|
|
|
|
The nodes in a list are encoded as a merkle tree for distribution via the DNS
|
|
protocol. Entries of the merkle tree are contained in DNS TXT records. The root
|
|
of the tree is a TXT record with the following content:
|
|
|
|
enrtree-root:v1 e=<enr-root> l=<link-root> seq=<sequence-number> sig=<signature>
|
|
|
|
where
|
|
|
|
- `enr-root` and `link-root` refer to the root hashes of subtrees containing
|
|
nodes and links subtrees.
|
|
- `sequence-number` is the tree's update sequence number, a decimal integer.
|
|
- `signature` is a 65-byte secp256k1 EC signature over the keccak256 hash of the
|
|
record content, excluding the `sig=` part, encoded as URL-safe base64 (RFC-4648).
|
|
|
|
Further TXT records on subdomains map hashes to one of three entry types. The
|
|
subdomain name of any entry is the base32 encoding of the (abbreviated)
|
|
keccak256 hash of its text content.
|
|
|
|
- `enrtree-branch:<h₁>,<h₂>,...,<hₙ>` is an intermediate tree entry containing
|
|
hashes of subtree entries.
|
|
- `enrtree://<key>@<fqdn>` is a leaf pointing to a different list located at
|
|
another fully qualified domain name. Note that this format matches the URL
|
|
encoding. This type of entry may only appear in the subtree pointed to by
|
|
`link-root`.
|
|
- `enr:<node-record>` is a leaf containing a node record. The node record is
|
|
encoded as a URL-safe base64 string. Note that this type of entry matches the
|
|
canonical ENR text encoding. It may only appear in the `enr-root` subtree.
|
|
|
|
No particular ordering or structure is defined for the tree. Whenever the tree
|
|
is updated, its sequence number should increase. The content of any TXT record
|
|
should be small enough to fit into the 512 byte limit imposed on UDP DNS
|
|
packets. This limits the number of hashes that can be placed into an
|
|
`enrtree-branch` entry.
|
|
|
|
Example in zone file format:
|
|
|
|
; name ttl class type content
|
|
@ 60 IN TXT enrtree-root:v1 e=JWXYDBPXYWG6FX3GMDIBFA6CJ4 l=C7HRFPF3BLGF3YR4DY5KX3SMBE seq=1 sig=o908WmNp7LibOfPsr4btQwatZJ5URBr2ZAuxvK4UWHlsB9sUOTJQaGAlLPVAhM__XJesCHxLISo94z5Z2a463gA
|
|
C7HRFPF3BLGF3YR4DY5KX3SMBE 86900 IN TXT enrtree://AM5FCQLWIZX2QFPNJAP7VUERCCRNGRHWZG3YYHIUV7BVDQ5FDPRT2@morenodes.example.org
|
|
JWXYDBPXYWG6FX3GMDIBFA6CJ4 86900 IN TXT enrtree-branch:2XS2367YHAXJFGLZHVAWLQD4ZY,H4FHT4B454P6UXFD7JCYQ5PWDY,MHTDO6TMUBRIA2XWG5LUDACK24
|
|
2XS2367YHAXJFGLZHVAWLQD4ZY 86900 IN TXT enr:-HW4QOFzoVLaFJnNhbgMoDXPnOvcdVuj7pDpqRvh6BRDO68aVi5ZcjB3vzQRZH2IcLBGHzo8uUN3snqmgTiE56CH3AMBgmlkgnY0iXNlY3AyNTZrMaECC2_24YYkYHEgdzxlSNKQEnHhuNAbNlMlWJxrJxbAFvA
|
|
H4FHT4B454P6UXFD7JCYQ5PWDY 86900 IN TXT enr:-HW4QAggRauloj2SDLtIHN1XBkvhFZ1vtf1raYQp9TBW2RD5EEawDzbtSmlXUfnaHcvwOizhVYLtr7e6vw7NAf6mTuoCgmlkgnY0iXNlY3AyNTZrMaECjrXI8TLNXU0f8cthpAMxEshUyQlK-AM0PW2wfrnacNI
|
|
MHTDO6TMUBRIA2XWG5LUDACK24 86900 IN TXT enr:-HW4QLAYqmrwllBEnzWWs7I5Ev2IAs7x_dZlbYdRdMUx5EyKHDXp7AV5CkuPGUPdvbv1_Ms1CPfhcGCvSElSosZmyoqAgmlkgnY0iXNlY3AyNTZrMaECriawHKWdDRk2xeZkrOXBQ0dfMFLHY4eENZwdufn1S1o
|
|
|
|
### Client Protocol
|
|
|
|
To find nodes at a given DNS name, say "mynodes.org":
|
|
|
|
1. Resolve the TXT record of the name and check whether it contains a valid
|
|
"enrtree-root=v1" entry. Let's say the `enr-root` hash contained in the entry
|
|
is "CFZUWDU7JNQR4VTCZVOJZ5ROV4".
|
|
2. Verify the signature on the root against the known public key and check
|
|
whether the sequence number is larger than or equal to any previous number
|
|
seen for that name.
|
|
3. Resolve the TXT record of the hash subdomain, e.g.
|
|
"CFZUWDU7JNQR4VTCZVOJZ5ROV4.mynodes.org" and verify whether the content
|
|
matches the hash.
|
|
4. The next step depends on the entry type found:
|
|
- for `enrtree-branch`: parse the list of hashes and continue resolving them (step 3).
|
|
- for `enr`: decode, verify the node record and import it to local node storage.
|
|
|
|
During traversal, the client must track hashes and domains which are already
|
|
resolved to avoid going into an infinite loop. It's in the client's best
|
|
interest to traverse the tree in random order.
|
|
|
|
Client implementations should avoid downloading the entire tree at once during
|
|
normal operation. It's much better to request entries via DNS when-needed, i.e.
|
|
at the time when the client is looking for peers.
|
|
|
|
## Rationale
|
|
|
|
### Why DNS?
|
|
|
|
We have chosen DNS as the distribution medium because it is always available,
|
|
even under restrictive network conditions. The protocol provides low latency and
|
|
answers to DNS queries can be cached by intermediate resolvers. No custom server
|
|
software is needed. Node lists can be deployed to any DNS provider such as
|
|
CloudFlare DNS, dnsimple, Amazon Route 53 using their respective client
|
|
libraries.
|
|
|
|
### Why is this a merkle tree?
|
|
|
|
Being a merkle tree, any node list can be authenticated by a single signature on
|
|
the root. Hash subdomains protect the integrity of the list. At worst
|
|
intermediate resolvers can block access to the list or disallow updates to it,
|
|
but cannot corrupt its content. The sequence number prevents replacing the root
|
|
with an older version.
|
|
|
|
Synchronizing updates on the client side can be done incrementally, which
|
|
matters for large lists. Individual entries of the tree are small enough to fit
|
|
into a single UDP packet, ensuring compatibility with environments where only
|
|
basic UDP DNS is available. The tree format also works well with caching
|
|
resolvers: only the root of the tree needs a short TTL. Intermediate entries and
|
|
leaves can be cached for days.
|
|
|
|
### Why does the link subtree exist?
|
|
|
|
Links between lists enable federation and web-of-trust functionality. The
|
|
operator of a large list can delegate maintenance to other list providers. If
|
|
two node lists link to each other, users can use either list and get nodes from
|
|
both.
|
|
|
|
The link subtree is separate from the tree containing ENRs. This is done to
|
|
enable client implementations to sync these trees independently. A client
|
|
wanting to get as many nodes as possible will sync the link tree first and add
|
|
all linked names to the sync horizon.
|
|
|
|
## Security Considerations
|
|
|
|
Discovery via DNS is less secure than via DHT, because it relies on a trusted
|
|
party to publish the records regularly. The actor could easily eclipse
|
|
bootstrapping nodes by only publishing node records that it controls.
|
|
|
|
## Copyright
|
|
|
|
Copyright and related rights waived via [CC0](../LICENSE.md).
|