mirror of
https://github.com/vacp2p/vac.dev.git
synced 2026-01-09 14:47:59 -05:00
post: ambient peer discovery (#56)
This commit is contained in:
379
_posts/2022-04-21-ambient-peer-discovery.md
Normal file
379
_posts/2022-04-21-ambient-peer-discovery.md
Normal file
@@ -0,0 +1,379 @@
|
||||
---
|
||||
layout: post
|
||||
name: "Waku v2 Ambient Peer Discovery"
|
||||
title: "Waku v2 Ambient Peer Discovery"
|
||||
date: 2022-04-21 10:00:00 +0200
|
||||
author: Daniel
|
||||
published: true
|
||||
permalink: /wakuv2-apd-2022-21
|
||||
categories: research
|
||||
summary: Introducing and discussing ambient peer discovery methods currently used by Waku v2, as well as future plans in this area.
|
||||
image: /assets/img/waku_v2_discv5_random_walk_estimation.svg
|
||||
discuss: https://forum.vac.dev/t/discussion-waku-v2-ambient-peer-discovery/133
|
||||
---
|
||||
|
||||
[Waku v2](https://rfc.vac.dev/spec/10/) comprises a set of modular protocols for secure, privacy preserving communication.
|
||||
Avoiding centralization, these protocols exchange messages over a P2P network layer.
|
||||
In order to build a P2P network, participating nodes first have to discover peers within this network.
|
||||
This is where [*ambient peer discovery*](https://docs.libp2p.io/concepts/publish-subscribe/#discovery) comes into play:
|
||||
it allows nodes to find peers, making it an integral part of any decentralized application.
|
||||
|
||||
In this post the term *node* to refers to *our* endpoint or the endpoint that takes action,
|
||||
while the term *peer* refers to other endpoints in the P2P network.
|
||||
These endpoints can be any device connected to the Internet: e.g. servers, PCs, notebooks, mobile devices, or applications like a browser.
|
||||
As such, nodes and peers are the same. We use these terms for the ease of explanation without loss of generality.
|
||||
|
||||
|
||||
In Waku's modular design, ambient peer discovery is an umbrella term for mechanisms that allow nodes to find peers.
|
||||
Various ambient peer discovery mechanisms are supported, and each is specified as a separate protocol.
|
||||
Where do these protocols fit into Waku's protocol stack?
|
||||
The P2P layer of Waku v2 builds on [libp2p gossipsub](https://github.com/libp2p/specs/blob/10712c55ab309086a52eec7d25f294df4fa96528/pubsub/gossipsub/README.md).
|
||||
Nodes participating in a gossipsub protocol manage a mesh network that is used for routing messages.
|
||||
This mesh network is an [unstructured P2P network](https://en.wikipedia.org/wiki/Peer-to-peer#Unstructured_networks)
|
||||
offering high robustness and resilience against attacks.
|
||||
Gossipsub implements many improvements overcoming the shortcomings typically associated with unstructured P2P networks, e.g. inefficient flooding based routing.
|
||||
The gossipsub mesh network is managed in a decentralized way, which requires each node to know other participating peers.
|
||||
Waku v2 may use any combination of its ambient discovery protocols to find appropriate peers.
|
||||
|
||||
Summarizing, Waku v2 comprises a *peer management layer* based on libp2p gossipsub,
|
||||
which manages the peers of nodes, and an *ambient peer discovery layer*,
|
||||
which provides information about peers to the peer management layer.
|
||||
|
||||
We focus on ambient peer discovery methods that are in line with our goal of building a fully decentralized, generalized, privacy-preserving and censorship-resistant messaging protocol.
|
||||
Some of these protocols still need adjustments to adhere to our privacy and anonymity requirements. For now, we focus on operational stability and feasibility.
|
||||
However, when choosing techniques, we pay attention to selecting mechanisms that can feasibly be tweaked for privacy in future research efforts.
|
||||
Because of the modular design and the fact that Waku v2 has several discovery methods at its disposal, we could even remove a protocol in case future evaluation deems it not fitting our standards.
|
||||
|
||||
This post covers the current state and future considerations of ambient peer discovery for Waku v2,
|
||||
and gives reason for changes and modifications we made or plan to make.
|
||||
The ambient peer discovery protocols currently supported by Waku v2 are a modified version of Ethereum's [Discovery v5](https://github.com/ethereum/devp2p/blob/6b0abc3d956a626c28dce1307ee9f546db17b6bd/discv5/discv5.md)
|
||||
and [DNS-based discovery](https://vac.dev/dns-based-discovery).
|
||||
Waku v2 further supports [gossipsub's peer exchange protocol](https://github.com/libp2p/specs/blob/10712c55ab309086a52eec7d25f294df4fa96528/pubsub/gossipsub/gossipsub-v1.1.md#prune-backoff-and-peer-exchange).
|
||||
In addition, we plan to introduce protocols for general peer exchange and capability discovery, respectively.
|
||||
The former allows resource restricted nodes to outsource querying for peers to stronger peers,
|
||||
the latter allows querying peers for their supported capabilities.
|
||||
Besides these new protocols, we are working on integrating capability discovery in our existing ambient peer discovery protocols.
|
||||
|
||||
## Static Node Lists
|
||||
|
||||
The simplest method of learning about peers in a P2P network is via static node lists.
|
||||
These can be given to nodes as start-up parameters or listed in a config-file.
|
||||
They can also be provided in a script-parseable format, e.g. in JSON.
|
||||
While this method of providing bootstrap nodes is very easy to implement, it requires static peers, which introduce centralized elements.
|
||||
Also, updating static peer information introduces significant administrative overhead:
|
||||
code and/or config files have to be updated and released.
|
||||
Typically, static node lists only hold a small number of bootstrap nodes, which may lead to high load on these nodes.
|
||||
|
||||
|
||||
## DNS-based Discovery
|
||||
|
||||
Compared to static node lists,
|
||||
[DNS-based discovery](https://vac.dev/dns-based-discovery) (specified in [EIP-1459](https://eips.ethereum.org/EIPS/eip-1459))
|
||||
provides a more dynamic way of discovering bootstrap nodes.
|
||||
It is very efficient, can easily be handled by resource restricted devices and provides very good availability.
|
||||
In addition to a naive DNS approach, Ethereum's DNS-based discovery introduces efficient authentication leveraging [Merkle trees](https://en.wikipedia.org/wiki/Merkle_tree).
|
||||
|
||||
A further advantage over static node lists is the separation of code/release management and bootstrap node management.
|
||||
However, changing and updating the list of bootstrap nodes still requires administrative privileges because DNS records have to be added or updated.
|
||||
|
||||
While this method of discovery still requires centralized elements,
|
||||
node list management can be delegated to various DNS zones managed by other entities mitigating centralization.
|
||||
|
||||
|
||||
## Discovery V5
|
||||
|
||||
A much more dynamic method of ambient peer discovery is [Discovery v5](https://github.com/ethereum/devp2p/blob/6b0abc3d956a626c28dce1307ee9f546db17b6bd/discv5/discv5.md), which is Ethereum's peer discovery protocol.
|
||||
It is based on the [Kademlia](https://en.wikipedia.org/wiki/Kademlia) distributed hashtable (DHT).
|
||||
An [introduction to discv5 and its history](https://vac.dev/kademlia-to-discv5), and a [discv5 Waku v2 feasibility study](https://vac.dev/feasibility-discv5)
|
||||
can be found in previous posts on this research log.
|
||||
|
||||
We use Discovery v5 as an ambient peer discovery method for Waku v2 because it is decentralized, efficient, actively researched, and has web3 as its main application area.
|
||||
Discv5 also offers mitigation techniques for various attacks, which we cover later in this post.
|
||||
|
||||
Using a DHT (structured P2P network) as a means for ambient peer discovery, while using the gossipsub mesh network (unstructured P2P network) for transmitting actual messages,
|
||||
Waku v2 leverages advantages from both worlds.
|
||||
One of the main benefits of DHTs is offering a global view over participating nodes.
|
||||
This, in turn, allows sampling random sets of nodes which is important for equally distributing load.
|
||||
Gossipsub, on the other hand, offers great robustness and resilience against attacks.
|
||||
Even if discv5 discovery should not work in advent of a DoS attack, Waku v2 can still operate switching to different discovery methods.
|
||||
|
||||
Discovery methods that use separate P2P networks still depend on bootstrapping,
|
||||
which Waku v2 does via parameters on start-up or via DNS-based discovery.
|
||||
This might raise the question of why such discovery methods are beneficial?
|
||||
The answer lies in the aforementioned global view of DHTs. Without discv5 and similar methods, the bootstrap nodes are used as part of the gossipsub mesh.
|
||||
This might put heavy load on these nodes and further, might open pathways to inference attacks.
|
||||
Discv5, on the other hand, uses the bootstrap nodes merely as an entry to the discovery network and can provide random sets of nodes (sampled from a global view)
|
||||
for bootstrapping or expanding the mesh.
|
||||
|
||||
### DHT Background
|
||||
|
||||
Distributed Hash Tables are a class of structured P2P overlay networks.
|
||||
A DHT can be seen as a distributed node set of which each node is responsible for a part of the hash space.
|
||||
In contrast to unstructured P2P networks, e.g. the mesh network maintained by gossipsub,
|
||||
DHTs have a global view over the node set and the hash space (assuming the participating nodes behave well).
|
||||
|
||||
DHTs are susceptible to various kinds of attacks, especially [Sybil attacks](https://en.wikipedia.org/wiki/Sybil_attack)
|
||||
and [eclipse attacks](https://www.usenix.org/conference/usenixsecurity15/technical-sessions/presentation/heilman).
|
||||
While security aspects have been addressed in various research papers, general practical solutions are not available.
|
||||
However, discv5 introduced various practical mitigation techniques.
|
||||
|
||||
### Random Walk Discovery
|
||||
|
||||
While discv5 is based on the Kademlia DHT, it only uses the *distributed node set* aspect of DHTs.
|
||||
It does not map values (items) into the distributed hash space.
|
||||
This makes sense, because the main purpose of discv5 is discovering other nodes that support discv5, which are expected to be Ethereum nodes.
|
||||
Ethereum nodes that want to discover other Ethereum nodes simply query the discv5 network for a random set of peers.
|
||||
If Waku v2 would do the same, only a small subset of the retrieved nodes would support Waku v2.
|
||||
|
||||
A first naive solution for Waku v2 discv5 discovery is
|
||||
|
||||
* retrieve a random node set, which is achieved by querying for a set of randomly chosen node IDs
|
||||
* filter the returned nodes on the query path based on Waku v2 capability via the [Waku v2 ENR](https://rfc.vac.dev/spec/31/)
|
||||
* repeat until enough Waku v2 capable nodes are found
|
||||
|
||||
This query process boils down to random walk discovery, which is very resilient against attacks, but also very inefficient if the number of nodes supporting the desired capability is small.
|
||||
We refer to this as the needle-in-the-haystack problem.
|
||||
|
||||
### Random Walk Performance Estimation
|
||||
|
||||
This subsection provides a rough estimation of the overhead introduced by random walk discovery.
|
||||
|
||||
Given the following parameters:
|
||||
|
||||
* $n$ number of total nodes participating in discv5
|
||||
* $p$ percentage of nodes supporting Waku
|
||||
* $W$ the event of having at least one Waku node in a random sample
|
||||
* $k$ the size of a random sample (default = 16)
|
||||
* $\alpha$ the number of parallel queries started
|
||||
* $b$ bits per hop
|
||||
* $q$ the number of queries
|
||||
|
||||
A query takes $log_{2^b}n$ hops to retrieve a random sample of nodes.
|
||||
|
||||
$P(W) = 1 - (1-p/100)^k$ is the probability of having at least one Waku node in the sample.
|
||||
|
||||
$P(W^q) = 1 - (1-p/100)^{kq}$ is the probability of having at least one Waku node in the union of $q$ samples.
|
||||
|
||||
Expressing this in terms of $q$, we can write:
|
||||
$$P(W^q) = 1 - (1-p/100)^{kq} \iff q = log_{(1-p/100)^k}(1-P(W^q))$$
|
||||
|
||||
Figure 1 shows a log-log plot for $P(W^q) = 90\%$.
|
||||
|
||||
<p align="center">
|
||||
<img src="../assets/img/waku_v2_discv5_random_walk_estimation.svg" width="50%" />
|
||||
<br />
|
||||
Figure 1: log-log plot showing the number of queries necessary to retrieve a Waku v2 node with a probability of 90% in relation to the Waku v2 node concentration in the network.
|
||||
</p>
|
||||
|
||||
Assuming $p=0.1$, we would need
|
||||
|
||||
$$0.9 = 1 - (1-0.1/100)^{16q} => q \approx 144$$
|
||||
|
||||
queries to get a Waku node with 90% probability, which leads to $\approx 144 * 18 = 2592$ overlay hops.
|
||||
Choosing $b=3$ would reduce the number to $\approx 144 * 6 = 864$.
|
||||
Even when choosing $\alpha = 10$ we would have to wait at least 80 RTTs.
|
||||
This effort is just for retrieving a single Waku node. Ideally, we want at least 3 Waku nodes for bootstrapping a Waku relay.
|
||||
|
||||
[The discv5 doc](https://github.com/ethereum/devp2p/blob/6b0abc3d956a626c28dce1307ee9f546db17b6bd/discv5/discv5-theory.md#ad-placement-and-topic-radius) roughly estimates $p=1%$ to be the threshold for acceptably efficient random walk discovery.
|
||||
This is in line with our estimation:
|
||||
|
||||
$$0.9 = 1 - (1-1/100)^{16q} => q \approx 14$$
|
||||
|
||||
|
||||
The number of necessary queries is linearly dependent on the percentage $p$ of Waku nodes.
|
||||
The number of hops per query is logarithmically dependent on $n$.
|
||||
Thus, random walk searching is inefficient for small percentages $p$.
|
||||
Still, random walks are more resilient against attacks.
|
||||
|
||||
We can conclude that a Waku node concentration below 1% renders vanilla discv5 unfit for our needs.
|
||||
Our current solution and future plans for solving this issue are covered in the next subsections.
|
||||
|
||||
|
||||
### Simple Solution: Separate Discovery Network
|
||||
|
||||
The simple solution we currently use for [Waku v2 discv5](https://rfc.vac.dev/spec/33/) is a separate discv5 network.
|
||||
All (well behaving) nodes in this network support Waku v2, resulting in a very high query efficiency.
|
||||
However, this solution reduces resilience because the difficulty of attacking a DHT scales with the number of participating nodes.
|
||||
|
||||
|
||||
### Discv5 Topic Discovery
|
||||
|
||||
We did not base our solution on the [current version of discv5 topic discovery](https://github.com/ethereum/devp2p/blob/master/discv5/discv5-theory.md#topic-advertisement),
|
||||
because, similar to random walk discovery, it suffers from poor performance for relatively rare capabilities/topics.
|
||||
|
||||
However, there is [ongoing research](https://github.com/harnen/service-discovery-paper) in discv5 topic discovery which is close to ideas we explored when pondering efficient and resilient Waku discv5 solutions.
|
||||
We keep a close eye on this research, give feedback, and make suggestions, as we plan to switch to this version of topic discovery in the future.
|
||||
|
||||
In a nutshell, topic discovery will manage separate routing tables for each topic.
|
||||
These topic specific tables are initialized with nodes from the discv5 routing table.
|
||||
While the buckets of the discv5 routing table represent distance intervals from the node's `node ID`, the topic table buckets represent distance intervals from `topic ID`s.
|
||||
|
||||
Nodes that want to register a topic try to register that topic at one random peer per bucket.
|
||||
This leads to registering the topic at peers in closer and closer neighbourhoods around the topic ID, which
|
||||
yields a very efficient and resilient compromise between random walk discovery and DHT discovery.
|
||||
Peers in larger neighbourhoods around the topic ID are less efficient to discover, however more resilient against eclipse attacks and vice versa.
|
||||
|
||||
Further, this works well with the overload and DoS protection discv5 employs.
|
||||
Discv5 limits the amount of nodes registered per topic on a single peer. Further, discv5 enforces a waiting time before nodes can register topics at peers.
|
||||
So, for popular topics, a node might fail to register the topic in a close neighbourhood.
|
||||
However, because the topic is popular (has a high occurrence percentage $p$), it can still be efficiently discovered.
|
||||
|
||||
In the future, we also plan to integrate Waku v2 capability discovery, which will not only allow asking for nodes that support Waku v2,
|
||||
but asking for Waku v2 nodes supporting specific Waku v2 protocols like filter or store.
|
||||
For the store protocol we envision sub-capabilities reflecting message topics and time frames of messages.
|
||||
We will also investigate related security implications.
|
||||
|
||||
### Attacks on DHTs
|
||||
|
||||
In this post, we only briefly describe common attacks on DHTs.
|
||||
These attacks are mainly used for denial of service (DoS),
|
||||
but can also used as parts of more sophisticated attacks, e.g. deanonymization attacks.
|
||||
A future post on this research log will cover security aspects of ambient peer discovery with a focus on privacy and anonymity.
|
||||
|
||||
#### Sybil Attack
|
||||
|
||||
The power of an attacker in a DHT is proportional to the number of controlled nodes.
|
||||
Controlling nodes comes at a high resource cost and/or requires controlling a botnet via a preliminary attack.
|
||||
|
||||
In a Sybil attack, an attacker generates lots of virtual node identities.
|
||||
This allows the attacker to control a large portion of the ID space in a DHT at a relatively low cost.
|
||||
Sybil attacks are especially powerful when the attacker can freely choose the IDs of generated nodes,
|
||||
because this allows positioning at chosen points in the DHT.
|
||||
|
||||
Because Sybil attacks amplify the power of many attacks against DHTs,
|
||||
making Sybil attacks as difficult as possible is the basis for resilient DHT operation.
|
||||
The typical abstract mitigation approach is binding node identities to physical network interfaces.
|
||||
To some extend, this can be achieved by introducing IP address based limits.
|
||||
Further, generating node IDs can be bound by proof of work (PoW),
|
||||
which, however, comes with a set of shortcomings, e.g. relatively high costs on resource restricted devices.
|
||||
[The discv5 doc](https://github.com/ethereum/devp2p/blob/6b0abc3d956a626c28dce1307ee9f546db17b6bd/discv5/discv5-rationale.md#sybil-and-eclipse-attacks)
|
||||
describes both Sybil and eclipse attacks, as well as concrete mitigation techniques employed by discv5.
|
||||
|
||||
|
||||
#### Eclipse Attack
|
||||
|
||||
In an eclipse attack, nodes controlled by the attacker poison the routing tables of other nodes in way that parts of the DHT become eclipsed, i.e. invisible.
|
||||
When a controlled node is asked for the next step in a path,
|
||||
it provides another controlled node as the next step,
|
||||
effectively navigating the querying node around or away from certain areas of the DHT.
|
||||
While several mitigation techniques have been researched, there is no definitive protection against eclipse attacks available as of yet.
|
||||
One mitigation technique is increasing $\alpha$, the number of parallel queries, and following each concurrent path independently for the lookup.
|
||||
|
||||
The eclipse attack becomes very powerful in combination with a successful Sybil attack;
|
||||
especially when the attacker can freely choose the position of the Sybil nodes.
|
||||
|
||||
|
||||
The aforementioned new topic discovery of discv5 provides a good balance between protection against eclipse attacks and query performance.
|
||||
|
||||
## Peer Exchange Protocol
|
||||
|
||||
While discv5 based ambient peer discovery has many desirable properties, resource restricted nodes and nodes behind restrictive NAT setups cannot run discv5 satisfactory.
|
||||
With these nodes in mind, we started working on a simple *peer exchange protocol* based on ideas proposed [here](https://github.com/libp2p/specs/issues/222).
|
||||
The peer exchange protocol will allow nodes to ask peers for additional peers.
|
||||
Similar to discv5, the peer exchange protocol will also support capability discovery.
|
||||
|
||||
The new peer exchange protocol can be seen as a simple replacement for the [Rendezvous protocol](https://github.com/libp2p/specs/blob/10712c55ab309086a52eec7d25f294df4fa96528/rendezvous/README.md), which Waku v2 does not support.
|
||||
While the rendezvous protocol involves nodes registering at rendezvous peers, the peer exchange protocol simply allows nodes to ask any peer for a list of peers (with a certain set of capabilities).
|
||||
Rendezvous tends to introduce centralized elements as rendezvous peers have a super-peer role.
|
||||
|
||||
In the future, we will investigate resource usage of [Waku v2 discv5](https://rfc.vac.dev/spec/33/) and provide suggestions for minimal resources nodes should have to run discv5 satisfactory.
|
||||
|
||||
|
||||
## Further Protocols Related to Discovery
|
||||
|
||||
Waku v2 comprises further protocols related to ambient peer discovery. We shortly mention them for context, even though they are not strictly ambient peer discovery protocols.
|
||||
|
||||
|
||||
### Gossipsub Peer Exchange Protocol
|
||||
|
||||
Gossipsub provides an integrated [peer exchange](https://github.com/libp2p/specs/blob/10712c55ab309086a52eec7d25f294df4fa96528/pubsub/gossipsub/gossipsub-v1.1.md#prune-backoff-and-peer-exchange) mechanism which is also supported by Waku v2.
|
||||
Gossipsub peer exchange works in a *push* manner. Nodes send peer lists to peers they prune from the active mesh.
|
||||
This pruning is part of the gossipsub peer management, blurring the boundaries of *peer management* and *ambient peer discovery*.
|
||||
|
||||
We will investigate anonymity implications of this protocol and might disable it in favour of more anonymity-preserving protocols.
|
||||
Sending a list of peers discloses information about the sending node.
|
||||
We consider restricting these peer lists to cached peers that are currently not used in the active gossipsub mesh.
|
||||
|
||||
|
||||
### Capability Negotiation
|
||||
|
||||
Some of the ambient peer discovery methods used by Waku2 will support capability discovery.
|
||||
This allows to narrow down the set of retrieved peers to peers that support specific capabilities.
|
||||
This is efficient because it avoids establishing connections to nodes that we are not interested in.
|
||||
|
||||
However, the ambient discovery interface does not require capability discovery, which will lead to nodes having peers with unknown capabilities in their peer lists.
|
||||
We work on a *capability negotiation protocol* which allows nodes to ask peers
|
||||
|
||||
* for their complete list of capabilities, and
|
||||
* whether they support a specific capability
|
||||
|
||||
We will investigate security implications, especially when sending full capability lists.
|
||||
|
||||
## NAT traversal
|
||||
|
||||
For [NAT traversal](https://docs.libp2p.io/concepts/nat/), Waku v2 currently supports the port mapping protocols [UPnP](https://en.wikipedia.org/wiki/Universal_Plug_and_Play) and [NAT-PMP](https://datatracker.ietf.org/doc/html/rfc6886) / [PCP](https://datatracker.ietf.org/doc/html/rfc6887).
|
||||
|
||||
In the future, we plan to add support for parts of [ICE](https://datatracker.ietf.org/doc/html/rfc8445), e.g. [STUN](https://datatracker.ietf.org/doc/html/rfc7350).
|
||||
We do not plan to support [TURN](https://www.rfc-editor.org/rfc/rfc5928) because TURN relays would introduce a centralized element.
|
||||
A modified decentralized version of TURN featuring incentivization might be an option in the future;
|
||||
strong peers could offer a relay service similar to TURN.
|
||||
|
||||
There are [plans to integrate more NAT traversal into discv5](https://github.com/ethereum/devp2p/issues/199), in which we might participate.
|
||||
So far, the only traversal technique supported by discv5 is nodes receiving their external IP address in pong messages.
|
||||
|
||||
While NAT traversal is very important, adding more NAT traversal techniques is not a priority at the moment.
|
||||
Nodes behind restrictive symmetric NAT setups cannot be discovered, but they can still discover peers in less restrictive setups.
|
||||
While we wish to have as many nodes as possible to be discoverable via ambient peer discovery, two nodes behind a restrictive symmetric NAT can still exchange Waku v2 messages if they discovered a shared peer.
|
||||
This is one of the nice resilience related properties of flooding based routing algorithms.
|
||||
|
||||
For mobile nodes, which suffer from changing IP addresses and double NAT setups, we plan using the peer exchange protocol to ask peers for more peers.
|
||||
Besides saving resources on resource restricted devices, this approach works as long as peers are in less restrictive environments.
|
||||
|
||||
|
||||
## Conclusion and Future Prospects
|
||||
|
||||
*Ambient peer discovery* is an integral part of decentralized applications. It allows nodes to learn about peers in the network.
|
||||
As of yet, Waku v2 supports DNS-based discovery and a slightly modified version of discv5.
|
||||
We are working on further protocols, including a peer exchange protocol that allows resource restricted nodes to ask stronger peers for peer lists.
|
||||
Further, we are working on adding capability discovery to our ambient discovery protocols, allowing nodes to find peers with desired properties.
|
||||
|
||||
These protocols can be combined in a modular way and allow Waku v2 nodes to build a strong and resilient mesh network,
|
||||
even if some discovery methods are not available in a given situation.
|
||||
|
||||
We will investigate security properties of these discovery mechanisms with a focus on privacy and anonymity in a future post on this research log.
|
||||
As an outlook we can already state that DHT approaches typically allow inferring information about the querying node.
|
||||
Further, sending peer lists allows inferring the position of a node within the mesh, and by extension information about the node.
|
||||
Waku v2 already provides some mitigation, because the mesh for transmitting actual messages, and the peer discovery network are separate.
|
||||
To mitigate information leakage by transmitting peer lists, we plan to only reply with lists of peers that nodes do not use in their active meshes.
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [Waku v2](https://rfc.vac.dev/spec/10/)
|
||||
- [libp2p gossipsub](https://github.com/libp2p/specs/blob/10712c55ab309086a52eec7d25f294df4fa96528/pubsub/gossipsub/README.md)
|
||||
- [unstructured P2P network](https://en.wikipedia.org/wiki/Peer-to-peer#Unstructured_networks)
|
||||
- [ambient peer discovery](https://docs.libp2p.io/concepts/publish-subscribe/#discovery)
|
||||
- [Discovery v5](https://github.com/ethereum/devp2p/blob/6b0abc3d956a626c28dce1307ee9f546db17b6bd/discv5/discv5.md)
|
||||
- [Kademlia](https://en.wikipedia.org/wiki/Kademlia)
|
||||
- [Discv5 history](https://vac.dev/kademlia-to-discv5)
|
||||
- [Discv5 Waku v2 feasibility study](https://vac.dev/feasibility-discv5)
|
||||
- [DNS-based discovery](https://vac.dev/dns-based-discovery)
|
||||
- [EIP-1459](https://eips.ethereum.org/EIPS/eip-1459)
|
||||
- [Merkle trees](https://en.wikipedia.org/wiki/Merkle_tree)
|
||||
- [Sybil attack](https://en.wikipedia.org/wiki/Sybil_attack)
|
||||
- [eclipse attack](https://www.usenix.org/conference/usenixsecurity15/technical-sessions/presentation/heilman)
|
||||
- [Waku v2 ENR](https://rfc.vac.dev/spec/31/)
|
||||
- [Discv5 topic discovery](https://github.com/ethereum/devp2p/blob/6b0abc3d956a626c28dce1307ee9f546db17b6bd/discv5/discv5-theory.md#ad-placement-and-topic-radius)
|
||||
- [Discv5 paper](https://github.com/harnen/service-discovery-paper)
|
||||
- [Discv5 vs Sybil and eclipse attacks](https://github.com/ethereum/devp2p/blob/6b0abc3d956a626c28dce1307ee9f546db17b6bd/discv5/discv5-rationale.md#sybil-and-eclipse-attacks)
|
||||
- [peer exchange idea](https://github.com/libp2p/specs/issues/222)
|
||||
- [Rendezvous protocol](https://github.com/libp2p/specs/blob/10712c55ab309086a52eec7d25f294df4fa96528/rendezvous/README.md)
|
||||
- [Waku v2 discv5](https://rfc.vac.dev/spec/33/)
|
||||
- [Gossipsub peer exchange](https://github.com/libp2p/specs/blob/10712c55ab309086a52eec7d25f294df4fa96528/pubsub/gossipsub/gossipsub-v1.1.md#prune-backoff-and-peer-exchange)
|
||||
- [NAT traversal](https://docs.libp2p.io/concepts/nat/)
|
||||
- [UPnP](https://en.wikipedia.org/wiki/Universal_Plug_and_Play)
|
||||
- [NAT-PMP](https://datatracker.ietf.org/doc/html/rfc6886)
|
||||
- [PCP](https://datatracker.ietf.org/doc/html/rfc6887).
|
||||
- [Discv5 topic efficiency issue](https://github.com/ethereum/devp2p/issues/199)
|
||||
|
||||
230
assets/img/waku_v2_discv5_random_walk_estimation.svg
Normal file
230
assets/img/waku_v2_discv5_random_walk_estimation.svg
Normal file
@@ -0,0 +1,230 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="720pt" height="432pt" viewBox="0 0 720 432" version="1.1">
|
||||
<defs>
|
||||
<g>
|
||||
<symbol overflow="visible" id="glyph0-0">
|
||||
<path style="stroke:none;" d=""/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-1">
|
||||
<path style="stroke:none;" d="M 11.140625 -8.75 L 9.90625 -8.75 L 8.296875 -1.640625 L 6.296875 -8.75 L 5.09375 -8.75 L 3.15625 -1.640625 L 1.515625 -8.75 L 0.265625 -8.75 L 2.515625 0 L 3.734375 0 L 5.6875 -7.1875 L 7.703125 0 L 8.921875 0 Z M 11.140625 -8.75 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-2">
|
||||
<path style="stroke:none;" d="M 6.421875 -0.03125 L 6.421875 -0.78125 C 6.3125 -0.75 6.265625 -0.75 6.203125 -0.75 C 5.859375 -0.75 5.65625 -0.9375 5.65625 -1.25 L 5.65625 -4.75 C 5.65625 -5.875 4.84375 -6.46875 3.296875 -6.46875 C 1.78125 -6.46875 0.84375 -5.875 0.78125 -4.421875 L 1.78125 -4.421875 C 1.875 -5.203125 2.328125 -5.546875 3.265625 -5.546875 C 4.15625 -5.546875 4.671875 -5.203125 4.671875 -4.609375 L 4.671875 -4.34375 C 4.671875 -3.921875 4.421875 -3.75 3.625 -3.640625 C 2.203125 -3.46875 1.984375 -3.421875 1.609375 -3.265625 C 0.875 -2.96875 0.5 -2.40625 0.5 -1.625 C 0.5 -0.484375 1.296875 0.1875 2.5625 0.1875 C 3.375 0.1875 4.15625 -0.15625 4.703125 -0.75 C 4.8125 -0.265625 5.25 0.078125 5.734375 0.078125 C 5.9375 0.078125 6.09375 0.0625 6.421875 -0.03125 Z M 4.671875 -2.171875 C 4.671875 -1.265625 3.75 -0.703125 2.78125 -0.703125 C 2 -0.703125 1.546875 -0.96875 1.546875 -1.65625 C 1.546875 -2.3125 1.984375 -2.609375 3.0625 -2.765625 C 4.109375 -2.90625 4.328125 -2.953125 4.671875 -3.109375 Z M 4.671875 -2.171875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-3">
|
||||
<path style="stroke:none;" d="M 6.03125 0 L 3.453125 -4.109375 L 5.640625 -6.28125 L 4.359375 -6.28125 L 1.6875 -3.625 L 1.6875 -8.75 L 0.703125 -8.75 L 0.703125 0 L 1.6875 0 L 1.6875 -2.453125 L 2.65625 -3.40625 L 4.78125 0 Z M 6.03125 0 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-4">
|
||||
<path style="stroke:none;" d="M 5.78125 0 L 5.78125 -6.28125 L 4.78125 -6.28125 L 4.78125 -2.8125 C 4.78125 -1.53125 4.109375 -0.703125 3.078125 -0.703125 C 2.28125 -0.703125 1.78125 -1.171875 1.78125 -1.9375 L 1.78125 -6.28125 L 0.78125 -6.28125 L 0.78125 -1.53125 C 0.78125 -0.484375 1.5625 0.1875 2.78125 0.1875 C 3.703125 0.1875 4.296875 -0.140625 4.890625 -0.96875 L 4.890625 0 Z M 5.78125 0 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-5">
|
||||
<path style="stroke:none;" d=""/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-6">
|
||||
<path style="stroke:none;" d="M 5.84375 0 L 5.84375 -4.75 C 5.84375 -5.796875 5.0625 -6.46875 3.859375 -6.46875 C 2.921875 -6.46875 2.3125 -6.109375 1.765625 -5.234375 L 1.765625 -6.28125 L 0.84375 -6.28125 L 0.84375 0 L 1.84375 0 L 1.84375 -3.46875 C 1.84375 -4.75 2.53125 -5.59375 3.546875 -5.59375 C 4.34375 -5.59375 4.84375 -5.109375 4.84375 -4.359375 L 4.84375 0 Z M 5.84375 0 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-7">
|
||||
<path style="stroke:none;" d="M 6.125 -3.09375 C 6.125 -5.265625 5.078125 -6.46875 3.265625 -6.46875 C 1.5 -6.46875 0.4375 -5.25 0.4375 -3.140625 C 0.4375 -1.03125 1.484375 0.1875 3.28125 0.1875 C 5.046875 0.1875 6.125 -1.03125 6.125 -3.09375 Z M 5.078125 -3.109375 C 5.078125 -1.625 4.375 -0.75 3.28125 -0.75 C 2.15625 -0.75 1.46875 -1.625 1.46875 -3.140625 C 1.46875 -4.65625 2.15625 -5.546875 3.28125 -5.546875 C 4.40625 -5.546875 5.078125 -4.671875 5.078125 -3.109375 Z M 5.078125 -3.109375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-8">
|
||||
<path style="stroke:none;" d="M 5.9375 0 L 5.9375 -8.75 L 4.9375 -8.75 L 4.9375 -5.5 C 4.53125 -6.125 3.859375 -6.46875 3.015625 -6.46875 C 1.375 -6.46875 0.3125 -5.203125 0.3125 -3.203125 C 0.3125 -1.078125 1.359375 0.1875 3.046875 0.1875 C 3.90625 0.1875 4.515625 -0.140625 5.046875 -0.921875 L 5.046875 0 Z M 4.9375 -3.125 C 4.9375 -1.671875 4.25 -0.75 3.1875 -0.75 C 2.09375 -0.75 1.359375 -1.6875 1.359375 -3.140625 C 1.359375 -4.609375 2.09375 -5.53125 3.1875 -5.53125 C 4.265625 -5.53125 4.9375 -4.578125 4.9375 -3.125 Z M 4.9375 -3.125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-9">
|
||||
<path style="stroke:none;" d="M 6.15625 -2.859375 C 6.15625 -3.765625 6.078125 -4.34375 5.90625 -4.8125 C 5.5 -5.84375 4.53125 -6.46875 3.359375 -6.46875 C 1.609375 -6.46875 0.484375 -5.171875 0.484375 -3.109375 C 0.484375 -1.046875 1.578125 0.1875 3.34375 0.1875 C 4.78125 0.1875 5.765625 -0.640625 6.03125 -1.90625 L 5.015625 -1.90625 C 4.734375 -1.078125 4.171875 -0.75 3.375 -0.75 C 2.328125 -0.75 1.546875 -1.421875 1.53125 -2.859375 Z M 5.09375 -3.75 C 5.09375 -3.75 5.09375 -3.703125 5.078125 -3.671875 L 1.546875 -3.671875 C 1.625 -4.78125 2.34375 -5.546875 3.34375 -5.546875 C 4.328125 -5.546875 5.09375 -4.734375 5.09375 -3.75 Z M 5.09375 -3.75 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-10">
|
||||
<path style="stroke:none;" d="M 5.71875 -2.15625 L 4.71875 -2.15625 C 4.546875 -1.15625 4.03125 -0.75 3.1875 -0.75 C 2.078125 -0.75 1.421875 -1.59375 1.421875 -3.078125 C 1.421875 -4.65625 2.0625 -5.546875 3.15625 -5.546875 C 4 -5.546875 4.53125 -5.046875 4.640625 -4.171875 L 5.65625 -4.171875 C 5.53125 -5.71875 4.578125 -6.46875 3.171875 -6.46875 C 1.46875 -6.46875 0.375 -5.171875 0.375 -3.078125 C 0.375 -1.0625 1.453125 0.1875 3.15625 0.1875 C 4.65625 0.1875 5.609375 -0.71875 5.71875 -2.15625 Z M 5.71875 -2.15625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-11">
|
||||
<path style="stroke:none;" d="M 3.046875 0 L 3.046875 -0.84375 C 2.921875 -0.796875 2.765625 -0.796875 2.5625 -0.796875 C 2.140625 -0.796875 2.015625 -0.90625 2.015625 -1.359375 L 2.015625 -5.46875 L 3.046875 -5.46875 L 3.046875 -6.28125 L 2.015625 -6.28125 L 2.015625 -8.015625 L 1.015625 -8.015625 L 1.015625 -6.28125 L 0.171875 -6.28125 L 0.171875 -5.46875 L 1.015625 -5.46875 L 1.015625 -0.90625 C 1.015625 -0.28125 1.453125 0.078125 2.234375 0.078125 C 2.46875 0.078125 2.71875 0.0625 3.046875 0 Z M 3.046875 0 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-12">
|
||||
<path style="stroke:none;" d="M 3.859375 -5.40625 L 3.859375 -6.4375 C 3.6875 -6.453125 3.59375 -6.46875 3.46875 -6.46875 C 2.8125 -6.46875 2.328125 -6.078125 1.75 -5.140625 L 1.75 -6.28125 L 0.84375 -6.28125 L 0.84375 0 L 1.84375 0 L 1.84375 -3.265625 C 1.84375 -4.6875 2.296875 -5.390625 3.859375 -5.40625 Z M 3.859375 -5.40625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-13">
|
||||
<path style="stroke:none;" d="M 1.84375 0 L 1.84375 -6.28125 L 0.84375 -6.28125 L 0.84375 0 Z M 1.96875 -7.234375 L 1.96875 -8.484375 L 0.71875 -8.484375 L 0.71875 -7.234375 Z M 1.96875 -7.234375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-14">
|
||||
<path style="stroke:none;" d="M 6.078125 -4.09375 C 6.078125 -7.046875 5.140625 -8.515625 3.296875 -8.515625 C 1.46875 -8.515625 0.515625 -7.015625 0.515625 -4.15625 C 0.515625 -1.296875 1.46875 0.1875 3.296875 0.1875 C 5.09375 0.1875 6.078125 -1.296875 6.078125 -4.09375 Z M 5 -4.1875 C 5 -1.78125 4.453125 -0.703125 3.28125 -0.703125 C 2.15625 -0.703125 1.59375 -1.828125 1.59375 -4.15625 C 1.59375 -6.484375 2.15625 -7.578125 3.296875 -7.578125 C 4.4375 -7.578125 5 -6.46875 5 -4.1875 Z M 5 -4.1875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-15">
|
||||
<path style="stroke:none;" d="M 2.296875 0 L 2.296875 -1.25 L 1.046875 -1.25 L 1.046875 0 Z M 2.296875 0 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-16">
|
||||
<path style="stroke:none;" d="M 4.15625 0 L 4.15625 -8.515625 L 3.46875 -8.515625 C 3.09375 -7.203125 2.859375 -7.015625 1.21875 -6.8125 L 1.21875 -6.0625 L 3.109375 -6.0625 L 3.109375 0 Z M 4.15625 0 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph0-17">
|
||||
<path style="stroke:none;" d="M 4.4375 -6.140625 C 4.4375 -7.3125 3.546875 -8.21875 2.390625 -8.21875 C 1.265625 -8.21875 0.34375 -7.296875 0.34375 -6.171875 C 0.34375 -5.046875 1.265625 -4.109375 2.40625 -4.109375 C 3.515625 -4.109375 4.4375 -5.046875 4.4375 -6.140625 Z M 3.609375 -6.15625 C 3.609375 -5.5 3.0625 -4.953125 2.40625 -4.953125 C 1.734375 -4.953125 1.171875 -5.515625 1.171875 -6.171875 C 1.171875 -6.84375 1.734375 -7.375 2.390625 -7.375 C 3.078125 -7.375 3.609375 -6.84375 3.609375 -6.15625 Z M 8.09375 -8.515625 L 7.3125 -8.515625 L 2.5625 0.234375 L 3.359375 0.234375 Z M 10.3125 -1.796875 C 10.3125 -2.953125 9.40625 -3.859375 8.25 -3.859375 C 7.140625 -3.859375 6.21875 -2.9375 6.21875 -1.828125 C 6.21875 -0.703125 7.140625 0.234375 8.265625 0.234375 C 9.375 0.234375 10.3125 -0.703125 10.3125 -1.796875 Z M 9.484375 -1.796875 C 9.484375 -1.15625 8.921875 -0.609375 8.265625 -0.609375 C 7.59375 -0.609375 7.046875 -1.15625 7.046875 -1.828125 C 7.046875 -2.484375 7.59375 -3.03125 8.25 -3.03125 C 8.9375 -3.03125 9.484375 -2.484375 9.484375 -1.796875 Z M 9.484375 -1.796875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-0">
|
||||
<path style="stroke:none;" d=""/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-1">
|
||||
<path style="stroke:none;" d="M 0 -5.84375 L -4.75 -5.84375 C -5.796875 -5.84375 -6.46875 -5.0625 -6.46875 -3.859375 C -6.46875 -2.921875 -6.109375 -2.3125 -5.234375 -1.765625 L -6.28125 -1.765625 L -6.28125 -0.84375 L 0 -0.84375 L 0 -1.84375 L -3.46875 -1.84375 C -4.75 -1.84375 -5.59375 -2.53125 -5.59375 -3.546875 C -5.59375 -4.34375 -5.109375 -4.84375 -4.359375 -4.84375 L 0 -4.84375 Z M 0 -5.84375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-2">
|
||||
<path style="stroke:none;" d="M 0 -5.78125 L -6.28125 -5.78125 L -6.28125 -4.78125 L -2.8125 -4.78125 C -1.53125 -4.78125 -0.703125 -4.109375 -0.703125 -3.078125 C -0.703125 -2.28125 -1.171875 -1.78125 -1.9375 -1.78125 L -6.28125 -1.78125 L -6.28125 -0.78125 L -1.53125 -0.78125 C -0.484375 -0.78125 0.1875 -1.5625 0.1875 -2.78125 C 0.1875 -3.703125 -0.140625 -4.296875 -0.96875 -4.890625 L 0 -4.890625 Z M 0 -5.78125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-3">
|
||||
<path style="stroke:none;" d="M 0 -9.125 L -4.71875 -9.125 C -5.84375 -9.125 -6.46875 -8.5 -6.46875 -7.3125 C -6.46875 -6.484375 -6.21875 -5.96875 -5.515625 -5.390625 C -6.1875 -5.015625 -6.46875 -4.515625 -6.46875 -3.703125 C -6.46875 -2.859375 -6.15625 -2.296875 -5.40625 -1.765625 L -6.28125 -1.765625 L -6.28125 -0.859375 L 0 -0.859375 L 0 -1.84375 L -3.953125 -1.84375 C -4.859375 -1.84375 -5.59375 -2.515625 -5.59375 -3.328125 C -5.59375 -4.0625 -5.140625 -4.484375 -4.328125 -4.484375 L 0 -4.484375 L 0 -5.484375 L -3.953125 -5.484375 C -4.859375 -5.484375 -5.59375 -6.15625 -5.59375 -6.96875 C -5.59375 -7.703125 -5.125 -8.125 -4.328125 -8.125 L 0 -8.125 Z M 0 -9.125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-4">
|
||||
<path style="stroke:none;" d="M -3.21875 -6.28125 C -5.25 -6.28125 -6.46875 -5.25 -6.46875 -3.59375 C -6.46875 -2.71875 -6.140625 -2.109375 -5.4375 -1.640625 L -8.75 -1.640625 L -8.75 -0.640625 L 0 -0.640625 L 0 -1.546875 L -0.90625 -1.546875 C -0.171875 -2.03125 0.1875 -2.65625 0.1875 -3.546875 C 0.1875 -5.203125 -1.171875 -6.28125 -3.21875 -6.28125 Z M -3.15625 -5.234375 C -1.734375 -5.234375 -0.75 -4.484375 -0.75 -3.390625 C -0.75 -2.34375 -1.71875 -1.640625 -3.140625 -1.640625 C -4.625 -1.640625 -5.578125 -2.34375 -5.53125 -3.390625 C -5.53125 -4.515625 -4.5625 -5.234375 -3.15625 -5.234375 Z M -3.15625 -5.234375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-5">
|
||||
<path style="stroke:none;" d="M -2.859375 -6.15625 C -3.765625 -6.15625 -4.34375 -6.078125 -4.8125 -5.90625 C -5.84375 -5.5 -6.46875 -4.53125 -6.46875 -3.359375 C -6.46875 -1.609375 -5.171875 -0.484375 -3.109375 -0.484375 C -1.046875 -0.484375 0.1875 -1.578125 0.1875 -3.34375 C 0.1875 -4.78125 -0.640625 -5.765625 -1.90625 -6.03125 L -1.90625 -5.015625 C -1.078125 -4.734375 -0.75 -4.171875 -0.75 -3.375 C -0.75 -2.328125 -1.421875 -1.546875 -2.859375 -1.53125 Z M -3.75 -5.09375 C -3.75 -5.09375 -3.703125 -5.09375 -3.671875 -5.078125 L -3.671875 -1.546875 C -4.78125 -1.625 -5.546875 -2.34375 -5.546875 -3.34375 C -5.546875 -4.328125 -4.734375 -5.09375 -3.75 -5.09375 Z M -3.75 -5.09375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-6">
|
||||
<path style="stroke:none;" d="M -5.40625 -3.859375 L -6.4375 -3.859375 C -6.453125 -3.6875 -6.46875 -3.59375 -6.46875 -3.46875 C -6.46875 -2.8125 -6.078125 -2.328125 -5.140625 -1.75 L -6.28125 -1.75 L -6.28125 -0.84375 L 0 -0.84375 L 0 -1.84375 L -3.265625 -1.84375 C -4.6875 -1.84375 -5.390625 -2.296875 -5.40625 -3.859375 Z M -5.40625 -3.859375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-7">
|
||||
<path style="stroke:none;" d=""/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-8">
|
||||
<path style="stroke:none;" d="M -3.09375 -6.125 C -5.265625 -6.125 -6.46875 -5.078125 -6.46875 -3.265625 C -6.46875 -1.5 -5.25 -0.4375 -3.140625 -0.4375 C -1.03125 -0.4375 0.1875 -1.484375 0.1875 -3.28125 C 0.1875 -5.046875 -1.03125 -6.125 -3.09375 -6.125 Z M -3.109375 -5.078125 C -1.625 -5.078125 -0.75 -4.375 -0.75 -3.28125 C -0.75 -2.15625 -1.625 -1.46875 -3.140625 -1.46875 C -4.65625 -1.46875 -5.546875 -2.15625 -5.546875 -3.28125 C -5.546875 -4.40625 -4.671875 -5.078125 -3.109375 -5.078125 Z M -3.109375 -5.078125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-9">
|
||||
<path style="stroke:none;" d="M -5.46875 -3.09375 L -6.28125 -3.09375 L -6.28125 -2.046875 L -7.265625 -2.046875 C -7.6875 -2.046875 -7.90625 -2.296875 -7.90625 -2.75 C -7.90625 -2.828125 -7.90625 -2.875 -7.890625 -3.09375 L -8.71875 -3.09375 C -8.765625 -2.875 -8.78125 -2.734375 -8.78125 -2.53125 C -8.78125 -1.609375 -8.25 -1.0625 -7.359375 -1.0625 L -6.28125 -1.0625 L -6.28125 -0.21875 L -5.46875 -0.21875 L -5.46875 -1.0625 L 0 -1.0625 L 0 -2.046875 L -5.46875 -2.046875 Z M -5.46875 -3.09375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-10">
|
||||
<path style="stroke:none;" d="M 2.609375 -5.9375 L -6.28125 -5.9375 L -6.28125 -5.046875 L -5.453125 -5.046875 C -6.109375 -4.578125 -6.46875 -3.875 -6.46875 -3.046875 C -6.46875 -1.390625 -5.15625 -0.3125 -3.078125 -0.3125 C -1.03125 -0.3125 0.1875 -1.34375 0.1875 -3 C 0.1875 -3.875 -0.125 -4.46875 -0.8125 -4.9375 L 2.609375 -4.9375 Z M -3.109375 -4.9375 C -1.671875 -4.9375 -0.75 -4.25 -0.75 -3.1875 C -0.75 -2.09375 -1.6875 -1.359375 -3.140625 -1.359375 C -4.59375 -1.359375 -5.53125 -2.09375 -5.53125 -3.1875 C -5.53125 -4.265625 -4.578125 -4.9375 -3.109375 -4.9375 Z M -3.109375 -4.9375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-11">
|
||||
<path style="stroke:none;" d="M 0 -1.84375 L -6.28125 -1.84375 L -6.28125 -0.84375 L 0 -0.84375 Z M -7.234375 -1.96875 L -8.484375 -1.96875 L -8.484375 -0.71875 L -7.234375 -0.71875 Z M -7.234375 -1.96875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-12">
|
||||
<path style="stroke:none;" d="M -1.765625 -5.515625 C -2.703125 -5.515625 -3.171875 -4.984375 -3.46875 -3.734375 L -3.703125 -2.765625 C -3.890625 -1.953125 -4.15625 -1.609375 -4.59375 -1.609375 C -5.171875 -1.609375 -5.546875 -2.125 -5.546875 -2.9375 C -5.546875 -3.75 -5.203125 -4.171875 -4.53125 -4.203125 L -4.53125 -5.25 C -5.765625 -5.25 -6.46875 -4.421875 -6.46875 -2.96875 C -6.46875 -1.515625 -5.71875 -0.5625 -4.546875 -0.5625 C -3.5625 -0.5625 -3.09375 -1.0625 -2.734375 -2.5625 L -2.515625 -3.484375 C -2.34375 -4.1875 -2.140625 -4.46875 -1.6875 -4.46875 C -1.09375 -4.46875 -0.75 -3.875 -0.75 -3 C -0.75 -2.09375 -0.953125 -1.59375 -1.921875 -1.46875 L -1.921875 -0.40625 C -0.46875 -0.453125 0.1875 -1.265625 0.1875 -2.921875 C 0.1875 -4.5 -0.546875 -5.515625 -1.765625 -5.515625 Z M -1.765625 -5.515625 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-13">
|
||||
<path style="stroke:none;" d="M -5.046875 -2.296875 L -6.28125 -2.296875 L -6.28125 -1.0625 L -5.046875 -1.0625 Z M 0.1875 -2.296875 L -1.25 -2.296875 L -1.25 -1.046875 L 0 -1.046875 L 0 -1.765625 L 0.21875 -1.765625 C 1.046875 -1.765625 1.28125 -1.609375 1.3125 -1.046875 L 1.765625 -1.046875 C 1.765625 -1.890625 1.21875 -2.296875 0.1875 -2.296875 Z M 0.1875 -2.296875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-14">
|
||||
<path style="stroke:none;" d="M -3.078125 -6.28125 C -5.203125 -6.28125 -6.46875 -5.25 -6.46875 -3.578125 C -6.46875 -2.71875 -6.078125 -2.046875 -5.34375 -1.578125 L -6.28125 -1.578125 L -6.28125 -0.65625 L 2.609375 -0.65625 L 2.609375 -1.65625 L -0.75 -1.65625 C -0.109375 -2.1875 0.1875 -2.765625 0.1875 -3.59375 C 0.1875 -5.203125 -1.078125 -6.28125 -3.078125 -6.28125 Z M -3.109375 -5.234375 C -1.6875 -5.234375 -0.75 -4.5 -0.75 -3.40625 C -0.75 -2.359375 -1.625 -1.65625 -3.09375 -1.65625 C -4.578125 -1.65625 -5.53125 -2.359375 -5.53125 -3.40625 C -5.53125 -4.515625 -4.609375 -5.234375 -3.109375 -5.234375 Z M -3.109375 -5.234375 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-15">
|
||||
<path style="stroke:none;" d="M -3.6875 -6.1875 L -4.5 -6.1875 L -4.5 -0.8125 L -3.6875 -0.8125 Z M -1.5 -6.1875 L -2.3125 -6.1875 L -2.3125 -0.8125 L -1.5 -0.8125 Z M -1.5 -6.1875 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-16">
|
||||
<path style="stroke:none;" d="M -4.453125 -6.109375 C -7.109375 -6.109375 -8.515625 -5.1875 -8.515625 -3.234375 C -8.515625 -1.625 -7.359375 -0.453125 -5.6875 -0.453125 C -4.109375 -0.453125 -3.03125 -1.53125 -3.03125 -3.078125 C -3.03125 -3.875 -3.328125 -4.46875 -3.984375 -5.015625 C -1.90625 -5 -0.75 -4.328125 -0.75 -3.125 C -0.75 -2.375 -1.21875 -1.859375 -2.046875 -1.6875 L -2.046875 -0.640625 C -0.640625 -0.84375 0.1875 -1.75 0.1875 -3.046875 C 0.1875 -5.046875 -1.515625 -6.109375 -4.453125 -6.109375 Z M -5.71875 -4.953125 C -4.671875 -4.953125 -3.96875 -4.21875 -3.96875 -3.1875 C -3.96875 -2.171875 -4.625 -1.53125 -5.765625 -1.53125 C -6.859375 -1.53125 -7.578125 -2.25 -7.578125 -3.234375 C -7.578125 -4.21875 -6.8125 -4.953125 -5.71875 -4.953125 Z M -5.71875 -4.953125 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-17">
|
||||
<path style="stroke:none;" d="M -4.09375 -6.078125 C -7.046875 -6.078125 -8.515625 -5.140625 -8.515625 -3.296875 C -8.515625 -1.46875 -7.015625 -0.515625 -4.15625 -0.515625 C -1.296875 -0.515625 0.1875 -1.46875 0.1875 -3.296875 C 0.1875 -5.09375 -1.296875 -6.078125 -4.09375 -6.078125 Z M -4.1875 -5 C -1.78125 -5 -0.703125 -4.453125 -0.703125 -3.28125 C -0.703125 -2.15625 -1.828125 -1.59375 -4.15625 -1.59375 C -6.484375 -1.59375 -7.578125 -2.15625 -7.578125 -3.296875 C -7.578125 -4.4375 -6.46875 -5 -4.1875 -5 Z M -4.1875 -5 "/>
|
||||
</symbol>
|
||||
<symbol overflow="visible" id="glyph1-18">
|
||||
<path style="stroke:none;" d="M -6.140625 -4.4375 C -7.3125 -4.4375 -8.21875 -3.546875 -8.21875 -2.390625 C -8.21875 -1.265625 -7.296875 -0.34375 -6.171875 -0.34375 C -5.046875 -0.34375 -4.109375 -1.265625 -4.109375 -2.40625 C -4.109375 -3.515625 -5.046875 -4.4375 -6.140625 -4.4375 Z M -6.15625 -3.609375 C -5.5 -3.609375 -4.953125 -3.0625 -4.953125 -2.40625 C -4.953125 -1.734375 -5.515625 -1.171875 -6.171875 -1.171875 C -6.84375 -1.171875 -7.375 -1.734375 -7.375 -2.390625 C -7.375 -3.078125 -6.84375 -3.609375 -6.15625 -3.609375 Z M -8.515625 -8.09375 L -8.515625 -7.3125 L 0.234375 -2.5625 L 0.234375 -3.359375 Z M -1.796875 -10.3125 C -2.953125 -10.3125 -3.859375 -9.40625 -3.859375 -8.25 C -3.859375 -7.140625 -2.9375 -6.21875 -1.828125 -6.21875 C -0.703125 -6.21875 0.234375 -7.140625 0.234375 -8.265625 C 0.234375 -9.375 -0.703125 -10.3125 -1.796875 -10.3125 Z M -1.796875 -9.484375 C -1.15625 -9.484375 -0.609375 -8.921875 -0.609375 -8.265625 C -0.609375 -7.59375 -1.15625 -7.046875 -1.828125 -7.046875 C -2.484375 -7.046875 -3.03125 -7.59375 -3.03125 -8.25 C -3.03125 -8.9375 -2.484375 -9.484375 -1.796875 -9.484375 Z M -1.796875 -9.484375 "/>
|
||||
</symbol>
|
||||
</g>
|
||||
<clipPath id="clip1">
|
||||
<path d="M 82 71 L 667 71 L 667 358.558594 L 82 358.558594 Z M 82 71 "/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g id="surface1">
|
||||
<rect x="0" y="0" width="720" height="432" style="fill:rgb(100%,100%,100%);fill-opacity:1;stroke:none;"/>
|
||||
<g clip-path="url(#clip1)" clip-rule="nonzero">
|
||||
<path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 82.398438 71.707031 L 94.078125 78.691406 L 99.921875 82.183594 L 105.761719 85.679688 L 123.28125 96.15625 L 129.121094 99.652344 L 146.640625 110.128906 L 152.480469 113.625 L 164.160156 120.609375 L 170 124.105469 L 181.679688 131.089844 L 187.519531 134.585938 L 199.199219 141.570312 L 205.039062 145.066406 L 210.878906 148.558594 L 216.71875 152.054688 L 222.558594 155.546875 L 234.238281 162.539062 L 240.078125 166.03125 L 245.921875 169.527344 L 257.601562 176.519531 L 263.441406 180.011719 L 275.121094 187.003906 L 280.960938 190.503906 L 292.640625 197.496094 L 298.480469 200.996094 L 304.320312 204.492188 L 333.519531 221.992188 L 356.878906 236.007812 L 368.558594 243.023438 L 374.398438 246.535156 L 380.238281 250.042969 L 386.078125 253.558594 L 391.921875 257.074219 L 397.761719 260.589844 L 403.601562 264.109375 L 415.28125 271.15625 L 421.121094 274.683594 L 426.960938 278.214844 L 432.800781 281.75 L 444.480469 288.835938 L 450.320312 292.386719 L 456.160156 295.941406 L 462 299.5 L 467.839844 303.070312 L 473.679688 306.644531 L 479.519531 310.230469 L 485.359375 313.824219 L 491.199219 317.425781 L 497.039062 321.042969 L 502.878906 324.667969 L 508.71875 328.3125 L 514.558594 331.96875 L 520.398438 335.640625 L 526.238281 339.335938 L 532.078125 343.050781 L 537.921875 346.789062 L 543.761719 350.554688 L 549.601562 354.351562 L 555.441406 358.179688 L 561.28125 362.050781 L 567.121094 365.960938 L 572.960938 369.921875 L 578.800781 373.941406 L 584.640625 378.027344 L 590.480469 382.1875 L 596.320312 386.4375 L 602.160156 390.792969 L 608 395.273438 L 613.839844 399.902344 L 619.679688 404.71875 L 625.519531 409.769531 L 631.359375 415.117188 L 637.199219 420.859375 L 643.039062 427.164062 L 648.878906 434.3125 L 654.71875 442.898438 L 660.558594 454.660156 L 666.398438 556.183594 "/>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 59.039062 358.558594 L 689.761719 358.558594 L 689.761719 59.039062 L 59.039062 59.039062 Z M 59.039062 358.558594 "/>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-1" x="306.398438" y="413.057617"/>
|
||||
<use xlink:href="#glyph0-2" x="317.245117" y="413.057617"/>
|
||||
<use xlink:href="#glyph0-3" x="323.916992" y="413.057617"/>
|
||||
<use xlink:href="#glyph0-4" x="329.795898" y="413.057617"/>
|
||||
<use xlink:href="#glyph0-5" x="336.467773" y="413.057617"/>
|
||||
<use xlink:href="#glyph0-6" x="339.803711" y="413.057617"/>
|
||||
<use xlink:href="#glyph0-7" x="346.475586" y="413.057617"/>
|
||||
<use xlink:href="#glyph0-8" x="353.147461" y="413.057617"/>
|
||||
<use xlink:href="#glyph0-9" x="359.819336" y="413.057617"/>
|
||||
<use xlink:href="#glyph0-5" x="366.491211" y="413.057617"/>
|
||||
<use xlink:href="#glyph0-10" x="369.827148" y="413.057617"/>
|
||||
<use xlink:href="#glyph0-7" x="375.826172" y="413.057617"/>
|
||||
<use xlink:href="#glyph0-6" x="382.498047" y="413.057617"/>
|
||||
<use xlink:href="#glyph0-10" x="389.169922" y="413.057617"/>
|
||||
<use xlink:href="#glyph0-9" x="395.168945" y="413.057617"/>
|
||||
<use xlink:href="#glyph0-6" x="401.84082" y="413.057617"/>
|
||||
<use xlink:href="#glyph0-11" x="408.512695" y="413.057617"/>
|
||||
<use xlink:href="#glyph0-12" x="411.848633" y="413.057617"/>
|
||||
<use xlink:href="#glyph0-2" x="415.783203" y="413.057617"/>
|
||||
<use xlink:href="#glyph0-11" x="422.455078" y="413.057617"/>
|
||||
<use xlink:href="#glyph0-13" x="425.791016" y="413.057617"/>
|
||||
<use xlink:href="#glyph0-7" x="428.454102" y="413.057617"/>
|
||||
<use xlink:href="#glyph0-6" x="435.125977" y="413.057617"/>
|
||||
</g>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph1-1" x="12.737305" y="281.300781"/>
|
||||
<use xlink:href="#glyph1-2" x="12.737305" y="274.628906"/>
|
||||
<use xlink:href="#glyph1-3" x="12.737305" y="267.957031"/>
|
||||
<use xlink:href="#glyph1-4" x="12.737305" y="257.961914"/>
|
||||
<use xlink:href="#glyph1-5" x="12.737305" y="251.290039"/>
|
||||
<use xlink:href="#glyph1-6" x="12.737305" y="244.618164"/>
|
||||
<use xlink:href="#glyph1-7" x="12.737305" y="240.623047"/>
|
||||
<use xlink:href="#glyph1-8" x="12.737305" y="237.287109"/>
|
||||
<use xlink:href="#glyph1-9" x="12.737305" y="230.615234"/>
|
||||
<use xlink:href="#glyph1-7" x="12.737305" y="227.279297"/>
|
||||
<use xlink:href="#glyph1-10" x="12.737305" y="223.943359"/>
|
||||
<use xlink:href="#glyph1-2" x="12.737305" y="217.211914"/>
|
||||
<use xlink:href="#glyph1-5" x="12.737305" y="210.540039"/>
|
||||
<use xlink:href="#glyph1-6" x="12.737305" y="203.868164"/>
|
||||
<use xlink:href="#glyph1-11" x="12.737305" y="199.873047"/>
|
||||
<use xlink:href="#glyph1-5" x="12.737305" y="197.209961"/>
|
||||
<use xlink:href="#glyph1-12" x="12.737305" y="190.538086"/>
|
||||
<use xlink:href="#glyph1-13" x="12.737305" y="184.539062"/>
|
||||
<use xlink:href="#glyph1-7" x="12.737305" y="181.203125"/>
|
||||
<use xlink:href="#glyph1-7" x="12.737305" y="177.867188"/>
|
||||
<use xlink:href="#glyph1-14" x="12.737305" y="174.53125"/>
|
||||
<use xlink:href="#glyph1-15" x="12.737305" y="167.859375"/>
|
||||
<use xlink:href="#glyph1-16" x="12.737305" y="160.851562"/>
|
||||
<use xlink:href="#glyph1-17" x="12.737305" y="154.179688"/>
|
||||
<use xlink:href="#glyph1-18" x="12.737305" y="147.507812"/>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 82.398438 358.558594 L 520.398438 358.558594 "/>
|
||||
<path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 82.398438 358.558594 L 82.398438 365.761719 "/>
|
||||
<path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 228.398438 358.558594 L 228.398438 365.761719 "/>
|
||||
<path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 374.398438 358.558594 L 374.398438 365.761719 "/>
|
||||
<path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 520.398438 358.558594 L 520.398438 365.761719 "/>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-14" x="64.898438" y="384.256836"/>
|
||||
<use xlink:href="#glyph0-15" x="71.570312" y="384.256836"/>
|
||||
<use xlink:href="#glyph0-14" x="74.90625" y="384.256836"/>
|
||||
<use xlink:href="#glyph0-16" x="81.578125" y="384.256836"/>
|
||||
<use xlink:href="#glyph0-17" x="88.25" y="384.256836"/>
|
||||
</g>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-14" x="214.398438" y="384.256836"/>
|
||||
<use xlink:href="#glyph0-15" x="221.070312" y="384.256836"/>
|
||||
<use xlink:href="#glyph0-16" x="224.40625" y="384.256836"/>
|
||||
<use xlink:href="#glyph0-17" x="231.078125" y="384.256836"/>
|
||||
</g>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-16" x="365.398438" y="384.256836"/>
|
||||
<use xlink:href="#glyph0-17" x="372.070312" y="384.256836"/>
|
||||
</g>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-16" x="507.898438" y="384.256836"/>
|
||||
<use xlink:href="#glyph0-14" x="514.570312" y="384.256836"/>
|
||||
<use xlink:href="#glyph0-17" x="521.242188" y="384.256836"/>
|
||||
</g>
|
||||
<path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 59.039062 347.464844 L 59.039062 85.507812 "/>
|
||||
<path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 59.039062 347.464844 L 51.839844 347.464844 "/>
|
||||
<path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 59.039062 260.148438 L 51.839844 260.148438 "/>
|
||||
<path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 59.039062 172.828125 L 51.839844 172.828125 "/>
|
||||
<path style="fill:none;stroke-width:0.75;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 59.039062 85.507812 L 51.839844 85.507812 "/>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-16" x="37.640625" y="351.741211"/>
|
||||
</g>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-16" x="30.640625" y="264.424805"/>
|
||||
<use xlink:href="#glyph0-14" x="37.3125" y="264.424805"/>
|
||||
</g>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-16" x="23.640625" y="177.104492"/>
|
||||
<use xlink:href="#glyph0-14" x="30.3125" y="177.104492"/>
|
||||
<use xlink:href="#glyph0-14" x="36.984375" y="177.104492"/>
|
||||
</g>
|
||||
<g style="fill:rgb(0%,0%,0%);fill-opacity:1;">
|
||||
<use xlink:href="#glyph0-16" x="17.640625" y="89.78418"/>
|
||||
<use xlink:href="#glyph0-14" x="24.3125" y="89.78418"/>
|
||||
<use xlink:href="#glyph0-14" x="30.984375" y="89.78418"/>
|
||||
<use xlink:href="#glyph0-14" x="37.65625" y="89.78418"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 28 KiB |
Reference in New Issue
Block a user