go-libp2p-examples
go-libp2p-examples copied to clipboard
questions about chat-with-rendezvous
Background
I started 4 chat-with-rendezvous locally with port 3000, 4000, 5000, 6000 respectively.
./chat -listen /ip4/127.0.0.1/tcp/3000
My forked example repo: https://github.com/lzl124631x/go-libp2p-examples/commit/adb0eb38bef472749742ada537c431490c019005
Question 1
Sometimes I saw log like this:
20:20:39.958 INFO rendezvous: Connected to: {<peer.ID Qm*UB48gJ> []} chat.go:183
while other times I saw:
20:20:59.372 INFO rendezvous: Connected to: {<peer.ID Qm*UB48gJ> [/p2p-circuit /ip4/127.0.0.1/tcp/3000 /ip4/73.225.14.166/tcp/3000]} chat.go:183
So sometimes I can see the multiaddr but sometimes not. Why?
Question 2
I saw message like this:
// For node 5000
20:33:51.088 INFO rendezvous: Host created. I'm /ip4/127.0.0.1/tcp/5000/ipfs/Qmf4Rh2JY5DfPMrR2YjKUsLhAoeG6X4cKfTxiR1NrVaHW3 chat.go:107
20:33:57.021 INFO rendezvous: Got a new stream! local /ip4/127.0.0.1/tcp/5000 remote /ip4/127.0.0.1/tcp/59919 chat.go:25
// For node 6000
20:33:57.021 INFO rendezvous: Connected to: local [/p2p-circuit /ip4/127.0.0.1/tcp/6000] remote {<peer.ID Qm*rVaHW3> []} chat.go:183
20:35:54.115 INFO rendezvous: Got a new stream! local /ip4/127.0.0.1/tcp/59919 remote /ip4/127.0.0.1/tcp/5000 chat.go:25
Why was there a host with port 59919 created for 5000?
@Stebalien @upperwal @vyzo
So sometimes I can see the multiaddr but sometimes not. Why?
not sure about that.
Why was there a host with port 59919 created for 5000?
that's an ephemeral port, it is created by the kernel when you make an outbound connection.
@lzl124631x What OS?
@anacrolix
Richards-MacBook-Pro:~ ricl$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.14.1
BuildVersion: 18B75
I've forgotten why I asked that, but it was relevant at the time.
Hey @lzl124631x. With reference to your first question:
Task:
- Set yourself as a provider to id "key".
- Find other peers with id "key".
Note: Locally known (cached) providers are stored in something called a providerSet. A call to FindProviders, FindProvidersAsync or Provide will be responsible for updating any new peer to the providerSet. (there might be other functions which can update providerSet)
The situation you are facing arises when your node, say X tries to connect to some other node, say Y which is already connected to the bootstrap node, B (or any node common to X and Y).
- To begin with,
Ywants to connect toB. After successfully connecting,BstoresYin its closest peers list and vice versa.Yalso calledY.dht.Provide("key")to be a provider for "key". - Now when
Xconnects toB, they connect successfully. - When
X.dht.Provide()is called: 3.1Xadds itself to theproviderSetbut with empty address i.e. []. (This is important) 3.2 It then callsX.dht.GetClosestPeerswhich fetches second degree peers from theNearestPeersi.e.Bfor now. 3.3Bwill returnYalong with its addresses. Now,Xwill connect toY. [I think this step was added to improve your connections automatically. A node will automatically connect to its second degree nodes if you have insufficient number of connections.] 3.4 At this point nodeXandYare connected to each other. AlthoughYis not added in theproviderSetofXand vice versa. - When
X.dht.FindProvider("key")is called: 4.1Xwill run a query to find ifNearestPeerscan be a provider for "key". 4.2NearestPeerstoXat this time areBandYand both will return a list of peers they know can be a provider for "key". 4.3Ywill return itself as it can be a provider for "key" but it will return empty list of address for itself.Balso returnsYasBknows thatYcan be a provider but becauseBknowsY'saddresses,Breturns a full list of addresses ofY. 4.4 Now the problem is which query returns first. If the answer fromYis returned first it will be an empty list of address and ifBreturns you will get a full list of addresses. Although you can overwrite the empty list butPeerSet.TryAddused here does not add the peer to the provider set if its already in the set even if the addresses are empty.
When FindProvider returns an empty list, under above circumstances, you are already connected to that peer so host.Connect will be successful. Hence, Connected to: {<peer.ID Qm*UB48gJ> []} chat.go:183.
I think this can be reported as a bug. Ideally, a node should replace an empty list of addresses with addresses known from some other peer but findProvidersAsyncRoutine uses a chan pstore.PeerInfo for output and a result is immediately written to this chan. This means whichever query returns the result first will be written to the chan and subsequent results will be ignored.