discv5: decide on proof-of-work for node identities
- Dominant language
- JavaScript
- Stars
- 1.1k
- Forks
- 297
- Avg merge
- 5h 50m
- Merged PRs (30d)
- 1
Description
This issue attempts to collect our options regarding proof-of-work on node identities.
This isn't a complete solution just yet, more a place where we can dump thoughts and
collect research.
First, let's describe what the problem is:
discv5 is a Kademlia-inspired system. As such, it relies on the XOR distance measure to
establish routing tables, forming an overlay network. All known structured overlay
networks are known to be susceptible to attacks (such as the eclipse attack) based on
attacker-chosen node IDs. Proof-of-work is one solution to this problem. If generating a
new node identity required a certain amount of computational work, attackers would have a
harder time creating chosen node IDs to influence routing tables.
Another solution is to design an overlay network that doesn't use node IDs for routing, or
using an unstructured network topology. If such a design exists, and fulfills the
requirements we have for node discovery, I'd strongly prefer to use it instead of adding
proof-of-work. Unfortunately I don't know of any overlay design with those properties.
### How much work?
Creating a new node identity is a one time process for most users, but a repeated task for
the attacker. The kind of attacker we want to rule out is one using many cheap cloud
servers. These are typically memory-constrained. If creating a new node required 4GB of
memory, it'd be harder to parallelize this operation at the cost of raising the barrier of
entry into the network. We are less concerned with CPU time consumption of the
proof-of-work function. Computation times up to ten seconds are no issue for most people,
especially for a one-time task.
### Suitable proof-of-work functions
Since all network participants should verify the proof-of-work value if provided, the
function chosen must be asymmetric, i.e. verification should take very little effort. We
also need to consider that the chosen function must be simple to implement in multiple
programming languages. It'd be best to choose something that's already available.
There aren't a lot of functions to choose from here, so we might as well look at all the
current options:
- Ethash. This is widely implemented across languages already. A huge downside with ethash
is the verification time. We're already struggling with ethash verification performance
for Ethereum block validation on smaller devices.
- Equihash. This function is used for zcash and several other currencies. One issue here
was that I couldn't find many implementations.
- Cuckoo Cycle. This one is used by grin, and also in bitcoin's peer-to-peer networking
layer. It's really simple to implement the algorithm and verification is essentially
free. One downside with this function is the proof size. Cuckoo cycle proofs are L * 4
bytes, where L is typically > 20. This makes it unsuitable for inclusion in ENR (see
below).
### Implementation Ideas
In discv5, node IDs are derived from node records using an 'identity scheme'. This is good
because any piece of metadata can be attached to the node and relayed in discovery, or
even across multiple discovery systems. This additional metadata can also be used to
derive the overlay node ID.
There are multiple ways to integrate proof-of-work into ENR, depending on how much
flexibility we want. If the proof-of-work value would influence the node ID directly, we'd
need to define a new identity scheme for it. We could also leave the identity scheme as-is
and add an attribute containing a value related to the ID created by any scheme. I am
strongly leaning toward the latter approach, since it allows us to keep improving the PoW
while keeping the ID stable.
If we were to choose Cuckoo Cycle, an additional complication would be transmitting the
proof value in the discovery protocol. I [did research this a bit](https://gist.github.com/fjl/8bbba84de9f1b8a995ef440f8a48d619): to make this work,
we'd add an ENR attribute containing an 8-byte PoW nonce. This attribute would simply
signal support for proof-of-work. To actually create the proof, we'd basically try random
nonces until a cuckoo cycle is found for the `sha256(node-id || nonce)` input value. The
proof would have to be transmitted in a new protocol message or during the handshake.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.