Skip to content

Circuit Relay Integration #209

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
vyzo opened this issue Jul 21, 2017 · 7 comments
Closed

Circuit Relay Integration #209

vyzo opened this issue Jul 21, 2017 · 7 comments
Labels
need/community-input Needs input from the wider community

Comments

@vyzo
Copy link
Contributor

vyzo commented Jul 21, 2017

The go-libp2p-circut relay code can integrate with any Host that has a swarm network by using the circuit.AddRelayTransport function.

This gives us some alternatives to integrating with go-libp2p:

  • We can integrate with BasicHost, as an option to NewBasicHost.
  • We can integrate with RoutedHost, by modifying the Wrap function or adding a new constructor.
  • We can keep relay separate and integrate at the application layer (eg go-ipfs can add the relay transport explicitly)

Ideally, we would want to integrate with libp2p so that it's always available, but there is a difference in the two integrations in terms of capabilities of the relay, modulo #207:

  • if RoutedHost.NewStream can do peer lookup (RoutedHost: NewStream ensures we have the means to connect to the peer #208), then it is preferable to integrate with RoutedHost so that we can support dialing to unspecific relay addresses and active relay
  • If RoutedHost.NewStream will not ever do peer address discovery,, then the distinction is moot and we can just integrate through options in the NewBasicHost constructor.

Let's discuss integration approach, in terms of code complexity it's all very straightforward.

@vyzo vyzo added the need/community-input Needs input from the wider community label Jul 21, 2017
@vyzo
Copy link
Contributor Author

vyzo commented Jul 21, 2017

Summoning @whyrusleeping @lgierth @Stebalien @diasdavid

@vyzo
Copy link
Contributor Author

vyzo commented Jul 21, 2017

cc @dryajov

@dryajov
Copy link
Member

dryajov commented Jul 21, 2017

I'm not familiar with the go terminology or codebase, so can't provide any insights into that, but I can provide a quick overview of where circuit integrates in the js code, and hopefully give some more perspective for the go implementation.

So, circuit is bootstrapped by libp2p, and receives the libp2p-swarm for dialing and listening. Right now relay is pretty dumb in that it either has an active connection to the dialing host, or if its an active relay it requires a full address to the host being dialed, otherwise it won't be able to dial it since we're bypassing the DHT. One question i've been meaning to bring up to the group is weather we should allow the relay part of circuit use the DHT, which would require passing libp2p instead of swarm to realy (Dialer/Listener would still use swarm). From the js implementation perspective, the interfaces of both swarm and libp2p are very similar so swapping them is not a big deal at all, not sure about Go land.

Other than that, during bootstrap, if no explicit /p2p-circuit address is provided it will prepend /p2p-circuit to the list of existing swarm addresses. The reasons for that are two fold, first internally the way that the protocols are chosen that logic relies on the presence of an address to activate the required transport, i.e. if a WS socket address is present, then libp2p will use the WS transport for listening/dialing, if not it won't be initialized. Another benefit is that those p2p-circuit addresses would get announced on the DHT.

These are some pretty arbitrary assumptions I had to resort to when implementing in order to be able to move it forward, but now that the spec is ready it might be a good point to reevaluate them.

To summarize:

  1. Relay isn't using the DHT in active mode to dial hosts
  2. All swarm addresses are dialable over /p2p-circuit and announced on the DHT, unless an explicit /p2p-circuit address is provided, at which point the host is dialable on circuit over that address ONLY, which also gets announced on the DHT.

@vyzo
Copy link
Contributor Author

vyzo commented Jul 21, 2017

This also brings up a secondary issue, which is address filtering.

Right now, when you register the relay as a transport (which plugs into swarm), it will also add a listen address /p2p-circuit/ipfs/QmId, which is the equivalent of INADDR_ANY in p2p-circuit land.
This address is reported by Host.Addrs(), which means it will need to be filtered.

There is no relay discovery, the relay-prefixed addresses will need to be added through the AddressFactory filter, which could also proceed to filter away the unspecific listen address.

@vyzo
Copy link
Contributor Author

vyzo commented Jul 23, 2017

Per discussion with @whyrusleeping on irc, we also need to consider whether we should filter the unspecific circuit address (/p2p-circuit/ipfs/QmId) or report them and allow connections to them.

One way to approach connecting to unspecific addresses, is to have the Relay act as a Notifee and receive connection events. Then for each connection, it can query the relay if it is a hop relay using CAN_HOP messages and build a list of hop relays in the background, The dialer can then use the list of hop relays to dial unspecific addresses by sequentially trying all the known relays. This is a form of passive relay discovery.

One problem with this approach is that we need a heuristic in the dialer as to when to use the relay address. Ideally, we want the relay address to be a fallback for when it's impossible to connect directly to the peer.

@vyzo
Copy link
Contributor Author

vyzo commented Jul 24, 2017

State of World

circuit v0.1.0 Implementation:

  • Relay implements a transport that can be hooked into any host that has a swarm network
  • Once hooked, Relay listens to /p2p-circuit/QmId, where Id is the identity of the host. This address is announced by the host in Addrs
  • specific relay addresses can be dialed: /ipfs/QmRelay/p2p-circuit/ipfs/QmDest and /transport/multiaddr/.../ipfs/QmRelay/p2p-circuit/QmDest.
  • When the transport address of a realy is omitted, the dialer's behaviour depends on the host:
    • When integrated with a BasicHost, it may only be able to dial if it has (had) a prior connection to the relay. It does not open any new connections however, which may be a desirable trait.
    • When integrated with a RoutedHost, the it can dial any specific relay by locating its addresses through Routing

PR#4: Relay Discovery and unspecific address dialing (libp2p/go-libp2p-circuit#4)

  • Relay adds a notifiee to the host that tracks opens connections to passively discover relays using CAN_HOP messages.
  • Dialer can dial unspecific relay address of the form /p2p-circuit/QmDest by trying connections through all known hop relays.

TBD:

  • Integration with libp2p BasicHost as options to NewBasicHost

@Stebalien
Copy link
Member

This has long since been implemented.

marten-seemann pushed a commit that referenced this issue Aug 17, 2022
* bump go.mod to Go 1.16 and run go fix

* run go mod tidy

* run gofmt -s

* update .github/workflows/automerge.yml

* update .github/workflows/go-test.yml

* update .github/workflows/go-check.yml

Co-authored-by: web3-bot <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
need/community-input Needs input from the wider community
Projects
None yet
Development

No branches or pull requests

3 participants