From b7710ebe4d636441c9b829b3d64409216f684861 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Tue, 15 Oct 2019 10:06:17 +0200 Subject: [PATCH] Automatically merged updates to draft EIP(s) 1459 (#2313) Hi, I'm a bot! This change was automatically merged because: - It only modifies existing Draft or Last Call EIP(s) - The PR was approved or written by at least one author of each modified EIP - The build is passing --- EIPS/eip-1459.md | 140 +++++++++++++++++++++++++++-------------------- 1 file changed, 82 insertions(+), 58 deletions(-) diff --git a/EIPS/eip-1459.md b/EIPS/eip-1459.md index 4c05b41fab20c7..6e7aa39e1c053a 100644 --- a/EIPS/eip-1459.md +++ b/EIPS/eip-1459.md @@ -12,8 +12,8 @@ discussions-to: https://github.com/ethereum/devp2p/issues/50 # Abstract -This document describes a scheme for authenticated, updateable Ethereum node lists -retrievable via DNS. +This document describes a scheme for authenticated, updateable Ethereum node +lists retrievable via DNS. # Motivation @@ -24,86 +24,104 @@ 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. DNS node lists may also be -useful to Ethereum peering providers because their customers can configure the -client to use the provider's list. Finally, the scheme serves as a fallback -option for nodes which can't join the node discovery DHT. +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 -### DNS Record Structure +A 'node list' is a list of [node records](eip-778) 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. -Node lists are encoded as TXT records. The records form a merkle tree. The root -of the tree is a record with content: +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 of the compressed 32-byte binary public key. - enrtree-root=v1 hash= seq= sig= +Example: -`roothash` is the abbreviated root hash of the tree in base32 encoding. `seqnum` -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, -encoded as URL-safe base64. + enrtree://AM5FCQLWIZX2QFPNJAP7VUERCCRNGRHWZG3YYHIUV7BVDQ5FDPRT2@nodes.example.org -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. +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= l= seq= sig= -- `enrtree=,,...,` is an intermediate tree containing further hash - subdomains. -- `enrtree-link=@` is a leaf pointing to a different list located at - another fully qualified domain name. The key is the expected signer of the - remote list, a base32 encoded secp256k1 public key, -- `enr=` is a leaf containing a node record [as defined in EIP-778][eip-778]. - The node record is encoded as a URL-safe base64 string. +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. + +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:,,...,` is an intermediate tree entry containing + hashes of subtree entries. +- `enrtree://@` 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:` 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 a `enrtree=` -entry. +packets. This limits the number of hashes that can be placed into an +`enrtree-branch` entry. Example in zone file format: ```text ; name ttl class type content -@ 60 IN TXT "enrtree-root=v1 hash=TO4Q75OQ2N7DX4EOOR7X66A6OM seq=3 sig=N-YY6UB9xD0hFx1Gmnt7v0RfSxch5tKyry2SRDoLx7B4GfPXagwLxQqyf7gAMvApFn_ORwZQekMWa_pXrcGCtwE=" -TO4Q75OQ2N7DX4EOOR7X66A6OM 86900 IN TXT "enrtree=F4YWVKW4N6B2DDZWFS4XCUQBHY,JTNOVTCP6XZUMXDRANXA6SWXTM,JGUFMSAGI7KZYB3P7IZW4S5Y3A" -F4YWVKW4N6B2DDZWFS4XCUQBHY 86900 IN TXT "enr=-H24QI0fqW39CMBZjJvV-EJZKyBYIoqvh69kfkF4X8DsJuXOZC6emn53SrrZD8P4v9Wp7NxgDYwtEUs3zQkxesaGc6UBgmlkgnY0gmlwhMsAcQGJc2VjcDI1NmsxoQPKY0yuDUmstAHYpMa2_oxVtw0RW_QAdpzBQA8yWM0xOA==" -JTNOVTCP6XZUMXDRANXA6SWXTM 86900 IN TXT "enr=-H24QDquAsLj8mCMzJh8ka2BhVFg3n4V9efBJBiaXHcoL31vRJJef-lAseMhuQBEVpM_8Zrin0ReuUXJE7Fs8jy9FtwBgmlkgnY0gmlwhMYzZGOJc2VjcDI1NmsxoQLtfC0F55K2s1egRhrc6wWX5dOYjqla-OuKCELP92O3kA==" -JGUFMSAGI7KZYB3P7IZW4S5Y3A 86900 IN TXT "enrtree-link=AM5FCQLWIZX2QFPNJAP7VUERCCRNGRHWZG3YYHIUV7BVDQ5FDPRT2@morenodes.example.org" +@ 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 ``` -### Referencing Trees by URL - -When referencing a record tree, e.g. in source code, the preferred form is a -URL. References should use the scheme `enrtree://` and encode the DNS domain in -the hostname. The expected public key that signs the tree should be encoded in -33-byte compressed form as a base32 string in the username portion of the URL. - -Example: - -```text -enrtree://AP62DT7WOTEQZGQZOU474PP3KMEGVTTE7A7NPRXKX3DUD57TQHGIA@nodes.example.org -``` - -### Client Protocol +## 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 root hash contained in the entry is - "CFZUWDU7JNQR4VTCZVOJZ5ROV4". -2. Optionally verify the signature on the root against a 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. + "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`: parse the list of hashes and continue resolving those (step 3). - - for `enrtree-link`: continue traversal on the linked domain (step 1). + - 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 should track hashes and domains which are already -resolved to avoid going into an infinite loop. +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 @@ -131,17 +149,23 @@ 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 `enrtree-link` exist? +### 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. + # References 1. The base64 and base32 encodings used to represent binary data are defined in - RFC 4648 (https://tools.ietf.org/html/rfc4648). No padding is used for base32. + RFC 4648 (https://tools.ietf.org/html/rfc4648). No padding is used for base64 + and base32 data. [eip-778]: https://eips.ethereum.org/EIPS/eip-778