enzoh / go-revolver

A decentralized peer-to-peer broadcast network.
https://dfinity.org
49 stars 12 forks source link

Improve broadcast efficiency via structured broadcast #8

Open derekchiang opened 7 years ago

derekchiang commented 7 years ago

Currently, messages sent to the Send() channel are sent to every peer that the node connects to. This API allows for a very simple "flooding" scheme: to send a message to every node in the network, nodes simply forward whatever messages they receive. This pattern is implemented in the Chirp example.

Flooding, however, is inefficient in terms of the amount of messages generated, since each node can receive the same message multiple times from different neighbors. Since the nodes are connected in a Kademlia topology, we can in fact implement "structured broadcast", wherein nodes only forward messages to selected neighbors. When implemented correctly, structured broadcast can offer similar guarantees to flooding in terms of node coverage, while reducing the total number of messages generated and potentially improving latency. I've linked a couple relevant papers at the end of this issue.

For structured broadcast to work, however, this library needs to expose an API that's more powerful than Send() and Receive(). @enzoh made a good point that the decision on whether a message should be forwarded has to be made at the application level, which complicates the matter. My current thinking is along these lines:

type Client interface {
    ...
    Broadcast(artifact.Artifact)
    SetMessageHandler(func(artifact.Artifact) bool)
    ...
}

Basically, the SetMessageHandler API takes a callback that's invoked whenever a message is received. If the message is "valid" (according to the application), then the callback returns true, in which case the message is forwarded. Otherwise, the callback returns false and the message is not forwarded.

To reiterate:

Relevant papers:

Efficient Broadcast in Structured P2P Networks Debunking some myths about structured and unstructured overlays Evaluation of alternatives for the broadcast operation in Kademlia under churn

derekchiang commented 7 years ago

I would also like to add that we can also keep the Send() and Receive() API around so that flooding is still supported. In that case, each node would need to maintain two messages queues, one for Send/Receive and the other for Broadcast/SetMessageHandler. Having only one queue would be impossible because Receive wouldn't know to handle the broadcast header and vice versa.