tox-rs / tox

toxcore implementation in Rust
GNU General Public License v3.0
442 stars 31 forks source link

Onion human documentation #37

Open kurnevsky opened 6 years ago

kurnevsky commented 6 years ago

Onion module allows nodes to announce their long term public keys and find friends by their long term public keys. There are two basic onion requests - AnnounceRequest and OnionDataRequest. They are enclosed to OnionRequest packets and sent though the onion path to prevent nodes finding out long term public key when they know only temporary DHT public key. There are three types of OnionRequest packets: OnionRequest0, OnionRequest1 and OnionRequest2. AnnounceRequest and OnionDataRequest when created are enclosed to OnionRequest2, OnionRequest2 is enclosed to OnionRequest1 and OnionRequest1 is enclosed to OnionRequest0. When DHT node receives OnionRequest packet it decrypts inner packet and sends it to the next node.

+--------+                       +--------+                       +--------+                       +--------+   +------------------+   +------------+
|        |   +---------------+   |        |   +---------------+   |        |   +---------------+   |        |   | AnnounceRequest  |   |            |
| Sender |---| OnionRequest0 |-->| Node 1 |---| OnionRequest1 |-->| Node 2 |---| OnionRequest2 |-->| Node 3 |---+------------------+-->| Onion node |
|        |   +---------------+   |        |   +---------------+   |        |   +---------------+   |        |   | OnionDataRequest |   |            |
+--------+                       +--------+                       +--------+                       +--------+   +------------------+   +------------+

Similarly to requests there are responses AnnounceResponse and OnionDataResponse that enclosed to three kind of OnionRespose packets: OnionResponse3, OnionResponse2 and OnionResponse1. OnionResponse packets are processed in the same way but with reverse ordering.

+------------+                        +--------+                        +--------+                        +--------+   +-------------------+   +----------+
|            |   +----------------+   |        |   +----------------+   |        |   +----------------+   |        |   | AnnounceResponse  |   |          |
| Onion node |---| OnionResponse3 |-->| Node 3 |---| OnionResponse2 |-->| Node 2 |---| OnionResponse1 |-->| Node 1 |---+-------------------+-->| Receiver |
|            |   +----------------+   |        |   +----------------+   |        |   +----------------+   |        |   | OnionDataResponse |   |          |
+------------+                        +--------+                        +--------+                        +--------+   +-------------------+   +----------+

When onion node handles AnnounceRequest packet it sends answer to original sender using the same onion path with the help of received onion return addresses. But when it handles OnionDataRequest packet it should send response packet to another destination node by its long term public key. That means that when onion node should store long term public keys of announced node along with onion return addresses.

OnionRequest0

OnionRequest1

OnionRequest2

AnnounceRequest

It's used for announcing ourselves to onion node and for looking for other announced nodes. If we want to announce ourselves we should send one AnnounceRequest packet with PingId set to 0 to acquire correct PingId of onion node. Then using this PingId we can send another AnnounceRequest to be added to onion nodes list. If AnnounceRequest succeed we will get AnnounceResponse with is_stored set to 2. Otherwise is_stored will be set to 0. If we are looking for another node we should send AnnounceRequest packet with PingId set to 0 and with PublicKey of this node. If node is found we will get AnnounceResponse with is_stored set to 1. Otherwise is_stored will be set to 0.

PingId is a sha256 hash of random secret bytes, current time divided by a 20 second timeout, PublicKey and IpPort of sender.

AnnounceResponse

It's used to respond to AnnounceRequest packet. is_stored variable contains the result of sent request. It might have values:

OnionDataRequest

It's used to send data requests to dht node using onion paths. When DHT node receives OnionDataRequest it sends OnionDataResponse to destination node for which data request is intended. Thus, data request will go through 7 intermediate nodes until destination node gets it.

OnionDataResponse

When onion node receives OnionDataRequest packet it converts it to OnionDataResponse and sends to destination node if it announced itself and is contained in onion nodes list.

OnionResponse3

OnionResponse2

OnionResponse1

Notes

kpp commented 5 years ago

Move this chapter to https://github.com/tox-rs/book

algor1th commented 5 years ago

Why is the request numbered 0,1,2 but the response is numbered 1,2,3?

suhr commented 5 years ago

@algor1th

algor1th commented 5 years ago

But what is the reason they are indexed in such a way? Wouldn't it be clearer to number them the same way?

suhr commented 5 years ago

OnionRequest[i] is a package from i'th node in the chain, OnionResponse[i] is a package to i'th node in the chain.

I believe it's rather reasonable. Also, this name scheme is symmetric (OnionRequest1 — OnionResponse1) on the sequence diagram.