libp2p / go-libp2p-pubsub

The PubSub implementation for go-libp2p
https://github.com/libp2p/specs/tree/master/pubsub
Other
319 stars 185 forks source link

Handle Multiple Graft Topics Correctly #386

Closed nisdas closed 4 years ago

nisdas commented 4 years ago

Background

With every iteration of the heartbeat routine for a peer running gossipsub, it will ascertain whether it has enough peers in its mesh for a topic. If there are not enough peers it will retrieve the relevant peers and add them to its mesh. Doing this for the same peer for multiple topics, we can batch all the GRAFT messages for the different topics into a single RPC message.

Problem

In sendGraftPrune while looping through all the topics to send a message out for, we take the pointer to string value of the topic and utilize that in our control message. Unfortunately in a loop that reference doesn't hold for each topic, instead changing for each iteration in a loop. So we instead end up referring to the last element in the original topic slice for all the GRAFT topic ids in our new ControlGraft message. To illustrate this:

https://play.golang.org/p/1cPEh5fYIvx

Solution

The solution is simple where we copy each topic before referencing them, this mitigates the problem with the other topics being overwritten in the message. Also a regression test has been added to test this exact case. There maybe more cases like this in the repo but I couldn't find anything similar so far when I scanned though the code.

vyzo commented 4 years ago

test fails with data race; can you run locally with -race and fix it?