Skip to content

Implement private networks#1385

Merged
tomaka merged 23 commits into
libp2p:masterfrom
Actyx:actyx/private-swarms
Jan 28, 2020
Merged

Implement private networks#1385
tomaka merged 23 commits into
libp2p:masterfrom
Actyx:actyx/private-swarms

Conversation

@rklaehn

@rklaehn rklaehn commented Jan 9, 2020

Copy link
Copy Markdown
Contributor

Implements private networks ( #476 )

This is meant to be interoperable with go-ipfs private swarms. For reference: the specification from PL is at https://github.com/libp2p/specs/blob/master/pnet/Private-Networks-PSK-V1.md , the implementation in go-ipfs is at https://github.com/libp2p/go-libp2p-pnet/ .

Tested by checking that two rust-ipfs nodes (pnet example) can chat with each other, and in addition checking that the pubsub traffic is visible in go-ipfs.

@rklaehn

rklaehn commented Jan 10, 2020

Copy link
Copy Markdown
Contributor Author

I think the basic encryption is now reasonably correct. Here is the spec for reference: https://github.com/libp2p/specs/blob/master/pnet/Private-Networks-PSK-V1.md

However, I tried getting the chat example to work with go-ipfs with a private swarm key, but could not get it to work.

This might be related to the UpgradeInfo. I used a made up protocol name because I had to put something there. b"/pnet/1.0.0". But I suspect that that is causing trouble. I tried implementing an UpgradeInfo that returns an empty iterator, but with that I could not get it to work at all...

Looking at the help for the method:

    /// Returns the list of protocols that are supported. Used during the negotiation process.
    fn protocol_info(&self) -> Self::InfoIter;

It seems that what happens is that my made up protocol name will now be part of the negotiation process. So obviously this won't work since the go-ipfs side does not know about my made up protocol name. Is there a way around this?

@tomaka

tomaka commented Jan 10, 2020

Copy link
Copy Markdown
Member

Oh I see, I didn't think about that.
I guess that you will have to apply the handshake manually over the connections that the Transport produces.
You can do that with transport.and_then(|socket, _| handshake(socket)).

@rklaehn

rklaehn commented Jan 10, 2020

Copy link
Copy Markdown
Contributor Author

Not exactly sure how to wire this up. I naively tried this:

pub fn build_tcp_ws_pnet_secio_mplex_yamux(keypair: identity::Keypair, psk: PSK)
    -> io::Result<impl Transport<Output = (PeerId, impl core::muxing::StreamMuxer<OutboundSubstream = impl Send, Substream = impl Send, Error = impl Into<io::Error>> + Send + Sync), Error = impl error::Error + Send, Listener = impl Send, Dial = impl Send, ListenerUpgrade = impl Send> + Clone>
{
    Ok(CommonTransport::new()?
        .and_then(|socket, endpoint| PnetConfig::new(psk).handshake(socket))
        // .and_then(move |io, endpoint| {
        //     libp2p_core::upgrade::apply(
        //         io,
        //         PnetConfig::new(psk),
        //         endpoint,
        //         libp2p_core::transport::upgrade::Version::V1,
        //     )
        // })
        .upgrade(core::upgrade::Version::V1)
        .authenticate(secio::SecioConfig::new(keypair))
        .multiplex(core::upgrade::SelectUpgrade::new(yamux::Config::default(), mplex::MplexConfig::new()))
        .map(|(peer, muxer), _| (peer, core::muxing::StreamMuxerBox::new(muxer)))
        .timeout(Duration::from_secs(20)))
}

...but then the result of the and_then is not a transport anymore so the .upgrade(core::upgrade::Version::V1) does not work anymore. I guess I have to call it a day...

@tomaka

tomaka commented Jan 10, 2020

Copy link
Copy Markdown
Member

...but then the result of the and_then is not a transport anymore

I think that's fixed by #1384
Your async function probably produces a non-Unpin future that aren't supported now (but will be after #1384)

@rklaehn

rklaehn commented Jan 10, 2020

Copy link
Copy Markdown
Contributor Author

Right. Got it to work now. Making handshake return a BoxFuture fixes it!

    pub fn pin_handshake<TSocket>(self, socket: TSocket) -> BoxFuture<'static, Result<PnetOutput<TSocket>, PnetError>>
        where
            TSocket: AsyncRead + AsyncWrite + Send + Unpin + 'static,
    {
        Box::pin(self.handshake(socket))
    }

Got the thing to talk to go-ipfs now. Thanks for helping me sort this out!

@rklaehn rklaehn marked this pull request as ready for review January 17, 2020 13:13
@rklaehn rklaehn changed the title WIP private swarms Implement private networks Jan 17, 2020
@rklaehn rklaehn force-pushed the actyx/private-swarms branch 2 times, most recently from 4d4b4a8 to 52ef77c Compare January 17, 2020 15:54
@rklaehn rklaehn requested a review from tomaka January 20, 2020 16:56
Comment thread protocols/pnet/Cargo.toml Outdated
Comment thread protocols/pnet/src/lib.rs Outdated
Comment thread protocols/pnet/src/lib.rs Outdated
Comment thread protocols/pnet/src/lib.rs Outdated
Comment thread protocols/pnet/src/lib.rs
Comment thread protocols/pnet/src/lib.rs Outdated
Comment thread protocols/pnet/tests/smoke.rs Outdated
Comment thread protocols/pnet/src/lib.rs Outdated
Comment thread examples/pnet.rs Outdated
@rklaehn rklaehn force-pushed the actyx/private-swarms branch 3 times, most recently from 0d99543 to 1202c67 Compare January 22, 2020 14:39
@rklaehn rklaehn requested a review from tomaka January 22, 2020 15:31
@rklaehn

rklaehn commented Jan 22, 2020

Copy link
Copy Markdown
Contributor Author

I will remove or replace the pnet example before merging this. Now just want to keep it in for testing.

@rklaehn rklaehn force-pushed the actyx/private-swarms branch from ec753e8 to 43a3dd0 Compare January 23, 2020 10:11
@tomaka

tomaka commented Jan 24, 2020

Copy link
Copy Markdown
Member

To me, multiple calls to poll_write should continue adding data at the end of the buffer, and only call poll_flush_buf if there is no space left.
However I think the current approach is fine as well.

Looks mostly good for me, except that pnet/src/lib.rs needs documentation.

@rklaehn rklaehn force-pushed the actyx/private-swarms branch 2 times, most recently from 484d798 to 9150a65 Compare January 25, 2020 09:05
tomaka
tomaka previously approved these changes Jan 27, 2020

@tomaka tomaka left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM. Please remove the example and let's merge!

@tomaka

tomaka commented Jan 27, 2020

Copy link
Copy Markdown
Member

Wait, I didn't realize that you had changed the logic of the buffer writing.

@tomaka tomaka dismissed their stale review January 27, 2020 12:45

Outdated

@rklaehn

rklaehn commented Jan 27, 2020

Copy link
Copy Markdown
Contributor Author

Happy to revert it if you want, but I think the new code is better.

Comment thread protocols/pnet/src/crypt_writer.rs Outdated
Comment thread protocols/pnet/src/crypt_writer.rs
Comment thread protocols/pnet/src/crypt_writer.rs
Comment thread protocols/pnet/src/crypt_writer.rs
Comment thread protocols/pnet/src/crypt_writer.rs
Comment thread protocols/pnet/src/crypt_writer.rs
Comment thread protocols/pnet/src/crypt_writer.rs
Comment thread protocols/pnet/src/crypt_writer.rs Outdated
@rklaehn rklaehn force-pushed the actyx/private-swarms branch from da4dbb9 to b61b92b Compare January 27, 2020 17:04

@tomaka tomaka left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The buffering logic still looks hard to read to me, hence these debug_assert!s, after which we should be good for merging.

Comment thread protocols/pnet/src/crypt_writer.rs
Comment thread protocols/pnet/src/crypt_writer.rs
Comment thread protocols/pnet/src/crypt_writer.rs Outdated
Comment thread protocols/pnet/src/crypt_writer.rs
rklaehn and others added 23 commits January 28, 2020 10:08
copied from plaintext protocol, since that seems to be the closest match
Also remove unneeded InboundUpgrade and OutboundUpgrade
To be able to check if a go-ipfs and rust-libp2p use the same key without
having to dump the actual key. Not sure if there is a spec for this anywhere,
but it is basically just copied from go-ipfs.
Basically a stripped down and modified version of async_std BufWriter that
also encrypts using the given cipher.
There will be a more elaborate and useful example in a different PR
also make doc text less ambiguous
Also, clarify the invariants in the comments of that method
@rklaehn rklaehn force-pushed the actyx/private-swarms branch from fbf88f6 to 9ca5961 Compare January 28, 2020 09:15
@rklaehn

rklaehn commented Jan 28, 2020

Copy link
Copy Markdown
Contributor Author

@tomaka I have taken all your suggestions and merged them into one commit, and rebased on current master.

@rklaehn rklaehn requested a review from tomaka January 28, 2020 09:31
@tomaka tomaka merged commit f5e7461 into libp2p:master Jan 28, 2020
@rklaehn rklaehn deleted the actyx/private-swarms branch January 28, 2020 12:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants