DCIPs/EIPS/eip-778.md

160 lines
6.5 KiB
Markdown

---
eip: 778
title: Ethereum Node Records (ENR)
author: Felix Lange <fjl@ethereum.org>
type: Standards Track
category: Networking
status: Final
created: 2017-11-23
discussions-to: https://github.com/ethereum/devp2p/issues/43
---
# Abstract
This EIP defines Ethereum Node Records, an open format for p2p connectivity information.
# Motivation
Ethereum nodes discover each other through the node discovery protocol. The purpose of
that protocol is relaying node identity public keys (on the secp256k1 curve), their IP
address and two port numbers. No other information can be relayed.
This specification seeks to lift the restrictions of the discovery v4 protocol by defining
a flexible format, the *node record*, for connectivity-related information. Node records
can be relayed through a future version of the node discovery protocol. They can also be
relayed through arbitrary other mechanisms such as DNS, ENS, a devp2p subprotocol, etc.
Node records improve cryptographic agility and handling of protocol upgrades. A record can
contain information about arbitrary transport protocols and public key material associated
with them.
Another goal of the new format is to provide authoritative updates of connectivity
information. If a node changes its endpoint and publishes a new record, other nodes should
be able to determine which record is newer.
# Specification
The components of a node record are:
- `signature`: cryptographic signature of record contents
- `seq`: The sequence number, a 64-bit unsigned integer. Nodes should increase the number
whenever the record changes and republish the record.
- The remainder of the record consists of arbitrary key/value pairs
A record's signature is made and validated according to an *identity scheme*. The identity
scheme is also responsible for deriving a node's address in the DHT.
The key/value pairs must be sorted by key and must be unique, i.e. any key may be present
only once. The keys can technically be any byte sequence, but ASCII text is preferred. Key
names in the table below have pre-defined meaning.
| Key | Value |
|:------------|:-------------------------------------------|
| `id` | name of identity scheme, e.g. "v4" |
| `secp256k1` | compressed secp256k1 public key, 33 bytes |
| `ip` | IPv4 address, 4 bytes |
| `tcp` | TCP port, big endian integer |
| `udp` | UDP port, big endian integer |
| `ip6` | IPv6 address, 16 bytes |
| `tcp6` | IPv6-specific TCP port, big endian integer |
| `udp6` | IPv6-specific UDP port, big endian integer |
All keys except `id` are optional, including IP addresses and ports. A record without
endpoint information is still valid as long as its signature is valid. If no `tcp6` /
`udp6` port is provided, the `tcp` / `udp` port applies to both IP addresses. Declaring
the same port number in both `tcp`, `tcp6` or `udp`, `udp6` should be avoided but doesn't
render the record invalid.
### RLP Encoding
The canonical encoding of a node record is an RLP list of `[signature, seq, k, v, ...]`.
The maximum encoded size of a node record is 300 bytes. Implementations should reject
records larger than this size.
Records are signed and encoded as follows:
content = [seq, k, v, ...]
signature = sign(content)
record = [signature, seq, k, v, ...]
### Text Encoding
The textual form of a node record is the base64 encoding of its RLP representation,
prefixed by `enr:`. Implementations should use the [URL-safe base64 alphabet][base64url]
and omit padding characters.
### "v4" Identity Scheme
This specification defines a single identity scheme to be used as the default until other
schemes are defined by further EIPs. The "v4" scheme is backwards-compatible with the
cryptosystem used by Node Discovery v4.
- To sign record `content` with this scheme, apply the keccak256 hash function (as used by
the EVM) to `content`, then create a signature of the hash. The resulting 64-byte
signature is encoded as the concatenation of the `r` and `s` signature values (the
recovery ID `v` is omitted).
- To verify a record, check that the signature was made by the public key in the
"secp256k1" key/value pair of the record.
- To derive a node address, take the keccak256 hash of the uncompressed public key.
# Rationale
The format is meant to suit future needs in two ways:
- Adding new key/value pairs: This is always possible and doesn't require implementation
consensus. Existing clients will accept any key/value pairs regardless of whether they
can interpret their content.
- Adding identity schemes: these need implementation consensus because the network won't
accept the signature otherwise. To introduce a new identity scheme, propose an EIP and
get it implemented. The scheme can be used as soon as most clients accept it.
The size of a record is limited because records are relayed frequently and may be included
in size-constrained protocols such as DNS. A record containing a IPv4 address, when signed
using the "v4" scheme occupies roughly 120 bytes, leaving plenty of room for additional
metadata.
You might wonder about the need for so many pre-defined keys related to IP addresses and
ports. This need arises because residential and mobile network setups often put IPv4
behind NAT while IPv6 traffic—if supported—is directly routed to the same host. Declaring
both address types ensures a node is reachable from IPv4-only locations and those
supporting both protocols.
# Test Vectors
This is an example record containing the IPv4 address `127.0.0.1` and UDP port `30303`.
The node ID is `a448f24c6d18e575453db13171562b71999873db5b286df957af199ec94617f7`.
```text
enr:-IS4QHCYrYZbAKWCBRlAy5zzaDZXJBGkcnh4MHcBFZntXNFrdvJjX04jRzjzCBOonrkTfj499SZuOh8R33Ls8RRcy5wBgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQPKY0yuDUmstAHYpMa2_oxVtw0RW_QAdpzBQA8yWM0xOIN1ZHCCdl8
```
The record is signed using the "v4" identity scheme using sequence number `1` and this
private key:
```text
b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291
```
The RLP structure of the record is:
```text
[
7098ad865b00a582051940cb9cf36836572411a47278783077011599ed5cd16b76f2635f4e234738f30813a89eb9137e3e3df5266e3a1f11df72ecf1145ccb9c,
01,
"id",
"v4",
"ip",
7f000001,
"secp256k1",
03ca634cae0d49acb401d8a4c6b6fe8c55b70d115bf400769cc1400f3258cd3138,
"udp",
765f,
]
```
# Copyright
Copyright and related rights waived via [CC0](../LICENSE.md).
[base64url]: https://tools.ietf.org/html/rfc4648#section-5