Skip to content
This repository has been archived by the owner on Apr 29, 2024. It is now read-only.

Make the ipfs transport extensible. #3

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

cobward
Copy link
Collaborator

@cobward cobward commented Feb 14, 2022

I've implemented two methods to do this.

The first is with the build_transport and build_transport_with_upgrade methods. The latter of those creates a ipfs-compatible transport with custom transport layers and a single custom upgrade.

The second method is within the apply_upgrades submodule. This contains a macro (apply_upgrades) which allows the user to apply any number of upgrades when building the transport.

The first method is I think clearer and easier to use, however it doesn't allow more than one upgrade to be applies. The pros and cons are switched for the second method. Thoughts?

@cobward cobward requested a review from chunningham February 14, 2022 14:34
@chunningham
Copy link

chunningham commented Feb 15, 2022

IMO yeah agree the first method is clearer, overall I like the approach. Extending it to apply multiple upgrades I guess has typing issues that make the macro appropriate. Could the TransportUpgrader wrap an upgrade::Authenticated to allow .apply to be called several times in a builder style without a macro? then TransportBuilder.then calls .authenticate. maybe this faces similar type issues in practice

@cobward
Copy link
Collaborator Author

cobward commented Feb 15, 2022

I did try that and I think it introduced more issues with trait bounds. Will give it another go now because I can't remember why I gave up on it.

@cobward
Copy link
Collaborator Author

cobward commented Feb 15, 2022

Ah yeah I gave up on it yesterday because I couldn't figure out how to write the type T inside Authenticated<T>. With fresh eyes, and a bit of trial and error, I've figured it out. Thanks for the prompt on this!

@cobward
Copy link
Collaborator Author

cobward commented Feb 15, 2022

I've realised that for kepler we actually need to add upgrades pre-authentication, and there isn't a way to chain upgrades in this way in libp2p. So tomorrow I'll work on a solution to this, which I have a decent idea of.

@chunningham
Copy link

It seems like the "handshake" might require an implementation of in/outbound upgrades which satisfy the U bound on Builder::authenticate, which essentially augments NoiseAuthenticated (result of NoiseConfig::into_authenticated) with extra steps? to recap, my understanding is that we want to:

  • establish a noise-encrypted channel (NoiseAuthenticated impls of in/outbound upgrade)
  • use said channel to exchange authz proof, close channel if proof insufficient

Is it the case that the "per-connection" logic that gets actioned in an "handshake" way is the upgrade passed in to Builder::authenticate, so acts differently from the upgrades applied to Authenticated which are selected from when negotiating a protocol upgrade?

This would allow a user to implement additional checks on the peer id
(such as checking this peer is authorized to connect) before
establishing a connection.
@cobward
Copy link
Collaborator Author

cobward commented Feb 16, 2022

Yep that's pretty much what I've done, except:

use said channel to exchange authz proof

I haven't implemented it to be able to use the channel. For our purposes I think we don't need to communicate over the channel, we just need to establish whether the inbound PeerId is authorized to be part of the orbit. I may be misunderstanding how libp2p treats an error raised on the listening side however

@@ -61,7 +61,7 @@ pub async fn create_swarm<TIpfsTypes: IpfsTypes>(
let peer_id = options.peer_id;

// Set up an encrypted TCP transport over the Mplex protocol.
let transport = transport::build_transport(options.keypair.clone())?;
let transport = transport::TransportBuilder::new(options.keypair.clone())?.build();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we add a transport arg (either builder or TTransport) into this fn and UninitializedIpfs::start so it can be swapped out?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've got a version of kepler-staging in my fork where I've consolidated these changes with the behaviour and other changes for kepler. In particular this commit does as you suggest:
cobward@9f2b170

In terms of putting it on this PR, I think we will want to have a commit that breaks open the UninitialisedIpfs, which both the behaviour change and transport change can be based on, or else raise both changes in a single PR.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might make sense to do both in a single PR since there is some interdependency (e.g. relay transport requires adding relay to the behaviour), and they are in a similar spirit of making the underlying p2p behaviour extensible.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if they can be ordered or separated into PRs it would be easier for the reviewer but I see your point w.r.t. the interdependency

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants