Node Discovery via DNS

So with issue #32, we’ve discussed adding node discovery via DNS similarly to EIP-1459. Here is a write up of my suggestions how I think we should handle this based off of both EIP-1459 and how bitcoin does it along with minor changes.

Firstly, how do these 2 versions work:

  • Bitcoin: Here, the IPs of nodes are simply stored as A records for a given domain name.
  • Ethereum: This is a little more complicated. The @ record of the domain name contains the root hash and a signature used to validate that all the records are valid. Then other records contain a hash that needs to be resolved. We validate that the resolving the record names record contains the value of the hash. If we then see a branch we continue the process, if we see an enr, we decode, verify the node record and import it to local node storage.

Here is my suggestion on how we should do things, I believe we should go more like the Ethereum route however change it to make it fit into our “ecosystem” a bit more. Firstly I would propose changing the use of ENRs to multiaddrs.

Now the next suggestion can be avoided and we could just use the merkle root method used within the ethereum method. However instead of having a merkle root which requires to be updated whenever we change any of the records, I propose appending a signature at the end of the TXT record. This would contain a signature signed with by the Public Key recorded in the @ record. So what we would have is:

; name ttl     class type  content
@      60      IN    TXT   <PubKey>
0      86900   IN    TXT   addr=<multiaddr> sig=<Signature>
1      86900   IN    TXT   addr=<multiaddr> sig=<Signature>
2 Likes

Using DNS sounds like a good idea, much much better than what we have now.

a few things that need a bit more details:

I would explore a bit further the move from ENRs to multiaddrs, before making a call on which one we should use (benefits/disadvantages, how a ENRs would look like as a multiaddrss, size of the record etc).

Regarding merkle tree, there are some reasons why it was picked it instead of the method above, chiefly because it’s possible to validate the list as a whole.

If we chose the method above, we expose ourselves to some issues on the integrity of the list, for example an attacker could mix old and new records and create a different list, or add records that have been removed.

Not sure to which extent this is a concern, but we should explore a bit further before diverging from the EIP.

1 Like

The simplest example I can think of:

  1. Node A adds addrs B,Sign(A, B)
  2. Node B is compromised by M
  3. Node A removes B from the DNS record.

Now if M can intercept the requests, it can return a list that always contain B, and the client will not know (version numbers are not very useful in this case, as if you include all the versions number in the @ entry, then you basically have something similar to a merkle tree).

With the merkle tree method the issue is mitigated, as in step 3 a new version number would be issued (say 3), and as long as a client received an updated list at least once, it would be safe, as it would not be using anymore V2 (if the attacker prevents list version 3 to go out completely, then the attack is still valid)

Totally agree that we should look at this further, so maybe here is my rational as to why I believe in abandoning ENRs for multiaddrs. The main point is versatility, the ENR has a very narrow range of fields that can be modified. These are limited to id, secp256k1, ip, tcp, udp, ip6, tcp6, udp6. With multiaddr we additionally have access to things like dns meaning nodes could have dns names over IP addresses.

2 Likes

So, @cammellos mentioned good concerns about the merkle tree and being able to validate everything against the tree. I wonder if its not easier however to have a more simplified structure.

; name ttl     class type  content
@      60      IN    TXT   <PubKey> <Current-Nonce>
0      86900   IN    TXT   addr=<multiaddr> sig=<Signature>
1      86900   IN    TXT   addr=<multiaddr> sig=<Signature>

In this example we would validate against a nonce too, where we just include it into the signature. This would however allow for an attacker to delete records without noticing so maybe we can include a how many records there are number in the header too. This simplifies it drastically to not needing to crawl a tree imo.