Skip to content

Releases: libp2p/rust-libp2p

libp2p-v0.52.0

20 Jun 11:59
libp2p-v0.52.0
ce98211
Compare
Choose a tag to compare

Automatic kademlia client/server mode

Let's get the biggest one out the way first, I promise the other points are easier explained but equally exciting. The tl;dr is: Healthier Kademlia routing tables and an improved developer experience.

If you don't know about Kademlia's client/server mode, checkout the specs.

With the v0.52 release, rust-libp2p automatically configures Kademlia in client or server mode depending on our external addresses. If we have a confirmed, external address, we will operate in server-mode, otherwise client-mode. This is entirely configuration-free (yay!) although follow-up work is under-way to allow setting this manually in certain situations: #4074.

We can now do the following:

  1. As soon as we learn about an external address (e.g. via AutoNAT), we activate server mode of Kademlia.
  2. Activating server-mode means we allow inbound requests, this is a change in our set of supported protocols.
  3. The change is detected automatically and reported to all protocols as ConnectionEvent::LocalProtocolsChange.
  4. libp2p-identify picks up this change and pushes it to all connected remote nodes.
  5. Remote nodes can instantly put us into their routing table.

To implement this, several other features/issues had to be fixed. If you are interested in the details, read on:

  • Simplify the scoring mechanism of external addresses: #3954

    As a consequence, the observed address reported by identify is no longer considered an external address but just an address candidate. Checkout the changelog-entry for a way of restoring the old behaviour.

  • Changes to the supported protocols are now detected at runtime and communicated to all protocols: #3651.

    Previously, a protocol could retrieve the supported protocols via PollParameters::supported_protocols. This list however was computed at start-up and was static. Now, ConnectionEvent has two new variants:

    pub enum ConnectionEvent<'a> {
      // existing variants omitted ...
    
      /// The local [`ConnectionHandler`] added or removed support for one or more protocols.
      LocalProtocolsChange(ProtocolsChange<'a>),
      /// The remote [`ConnectionHandler`] now supports a different set of protocols.
      RemoteProtocolsChange(ProtocolsChange<'a>),
    }
    
    pub enum ProtocolsChange<'a> {
      Added(ProtocolsAdded<'a>),
      Removed(ProtocolsRemoved<'a>),
    }

    ProtocolsAdded and ProtocolsRemoved are iterators over a (new) type called StreamProtocol.

  • Protocols are now enforced to be valid UTF-8 strings: #3746.

    This was always the case in the specs but the rust-libp2p implementation was lagging behind here and improperly represented them as bytes internally.

  • Local changes to our protocols (i.e. a node going from Kademlia server to client mode) are now immediately pushed to the remote via the /ipfs/id/push/1.0.0 protocol: #3980.

Not only does this work out-of-the-box and thus improves the developer experience of rust-libp2p, it should also result in a much more useful and up-to-date routing table for all nodes on a Kademlia DHT.

Type-safe /p2p multiaddresses

The /p2p protocol of multiaddresses specifies the identity of a peer in the form of a PeerId such as 12D3KooWETLZBFBfkzvH3BQEtA1TJZPmjb4a18ss5TpwNU7DHDX6. Yet for the longest time, the type-definition of the /p2p protocol looked like this:

pub enum Protocol<'a> {
    // omitted other variants ...
    P2p(Multihash),
}

Every PeerId is a valid Multihash but not vice-versa. Dang! That is a lot of "impossible" errors that the type-system should avoid.

Thanks to a lot of work, it now looks like this:

pub enum Protocol<'a> {
    // omitted other variants ...
    P2p(PeerId),
}

More consistent event/command naming

Naming is hard and humans are creatures of habit. Thus, once familiar with certain names, it is often hard to see how they make absolutely no sense at all to newcomers.

In the v0.52 release we renamed several associated types and enums which hopefully make the message-passing system implemented in rust-libp2p easier to grasp.

A quick recap:

  • A NetworkBehaviour represent a protocol's state across all peers and connections.
  • A ConnectionHandler represents a protocol's state for a single connection to a peer.
  • Multiple NetworkBehaviours are composed into a tree using #[derive(NetworkBehaviour)] and run inside a Swarm

NetworkBehaviours can emit events to the Swarm. This used to be called OutEvent. Now, its aptly named ToSwarm:

pub trait NetworkBehaviour {
    type ToSwarm;
  
    // functions and other types omitted ...
}

Returning one of these events was previously done with a NetworkBehaviourAction::GenerateEvent, a type-name so long you were grateful for autocomplete. These actions are essentially commands that are issued to the swarm. What could possibly be a good name for that? I present:

pub enum ToSwarm<TOutEvent, TInEvent> {
    GenerateEvent(TOutEvent),
    
    // other variants omitted ..
}

We followed the same strategy for ConnectionHandler. A ConnectionHandler can receive messages from a NetworkBehaviour via ToSwarm::NotifyHandler (gosh, that was so much easier to write, why didn't we do this earlier?) and send message to its NetworkBehaviour. The associated types defining these messages are now called ToBehaviour and FromBehaviour, representing where the message is going / coming from. Previously, they carried the generic names InEvent and OutEvent which had me utterly confused when I first started working on rust-libp2p.

To wrap it all up, the ConnectionHandlerEvent::Custom variant is now called ConnectionHandlerEvent::NotifyBehaviour, making it clear what happens to types returned here.

Improved ergonomics around stream errors

Oh, isn't this one of my favourites!

Ever wondered why ConnectionHandlerUpgrErr had what felt like 10 layers of nested enums? So did we and went ahead and fixed this in #3882.

This is what it looked like before:

pub enum ConnectionHandlerUpgrErr<TUpgrErr> {
    Timeout,
    Timer,
    Upgrade(UpgradeError<TUpgrErr>),
}

pub enum UpgradeError<E> {
  Select(NegotiationError),
  Apply(E),
}

pub enum NegotiationError {
  ProtocolError(ProtocolError),
  Failed,
}

pub enum ProtocolError {
  IoError(io::Error),
  InvalidMessage,
  InvalidProtocol,
  TooManyProtocols,
}

Now, it looks like this:

pub enum StreamUpgradeError<TUpgrErr> {
    Timeout,
    Apply(TUpgrErr),
    NegotiationFailed,
    Io(io::Error),
}

But that is not it!

Previously, we would give you one of these ConnectionHandlerUpgrErr when an inbound stream failed. But, what exactly does ProtocolError::InvalidMessage for example mean for an inbound stream? How would we even figure out, which protocol (read ConnectionHandler) this should be dispatched to if we failed to negotiate the protocols?

Well, you might have guessed it. It is impossible to dispatch this to the correct one, so we just informed all protocols. But that was pretty useless. If we don't know, which stream a protocol belongs to, we shouldn't just inform all of them. Thus, in #3605 we stopped this which removes several "impossible" error paths.

Simpler noise interface

Since its introduction, the libp2p-noise crate supported a wide range of handshake patterns. The libp2p specs however only documents the XX handshake: libp2p/specs/noise.

Supporting additional patterns introduced significant complexity to the codebase. We decided to deprecate and remove them. This significantly reduced the complexity of the libp2p-noise implementation (-1000 LoC!). Additionally, it allowed us to finally adopt the naming conventions we have been pursuing across the workspace for libp2p-noise.

Using the noise handshake is now as simple as:

let config = libp2p::noise::Config::new(&keypair).unwrap();

Request-response protocols using serde

A simple, yet impactful contribution was made by @dgarus in #3952:

  • libp2p::request_response::cbor::Behaviour<Req, Res>
  • libp2p::request_response::json::Behaviour<Req, Res>

These two, new type-aliases come with a pre-configured CBOR/JSON codec and only need to be parameterised by the Req and Res types. The only requirement is that the types implement serde::{Serialize,Deserialize}. Defining a request-response protocol has never been easier in rust-libp2p!

As with any code that serializes data structures, be aware that any changes to it ca...

Read more

libp2p-v0.51.3

13 Apr 16:37
libp2p-v0.51.3
3c5940a
Compare
Choose a tag to compare

See individual changelogs for details.

libp2p-v0.51.2

29 Mar 14:23
libp2p-v0.51.2
be42f21
Compare
Choose a tag to compare

See individual changelogs for details.

libp2p-v0.51.1

12 Mar 15:56
libp2p-v0.51.1
3959b2c
Compare
Choose a tag to compare

See individual changelogs for details.

v0.51.0

24 Feb 14:32
v0.51.0
1a9cf4f
Compare
Choose a tag to compare

Large release. See individual changelogs for details.

Thanks to the many folks involved!

v0.50.0

25 Nov 11:06
v0.50.0
5b4eab7
Compare
Choose a tag to compare

This is a large release. After > 4 years, rust-libp2p ships with an (alpha) QUIC
implementation
. The necessary TLS logic is extracted into
its own crate
, and can thus be used detached from QUIC, e.g.
on top of TCP as an alternative to Noise. In addition to these two transports, this release adds
a third, namely WebRTC (browser-to-server). But that is
definitely not it. See below for the many other changes packed into this release.

See individual changelogs for details.

Thanks to the many folks involved!

v0.49.0

14 Oct 16:17
v0.49.0
b5612dc
Compare
Choose a tag to compare

This is a large release with a couple of breaking changes. As always, please read the changelogs.

Feel free to tag us (maintainers) on your upgrade pull request for a review or general help.

Thanks to the many folks involved!

v0.48.0

07 Sep 08:18
v0.48.0
83c6795
Compare
Choose a tag to compare

Most notable changes:

  • libp2p-swarm
  • libp2p-core
    • Make RSA keypair support optional. To enable RSA support, rsa feature should be enabled.
      See PR 2860.

  • libp2p-mdns
    • Allow users to choose between async-io and tokio runtime
      in the mdns protocol implementation. async-io is a default
      feature, with an additional tokio feature (see PR 2748)

For all other changes, see individual changelogs for details.

Thanks to the many folks involved!

v0.47.0

22 Aug 03:52
v0.47.0
4253080
Compare
Choose a tag to compare

Most notable change is the deprecation of NetworkBehaviourEventProcess. See corresponding changelog entry on how to migrate.

Also rust-libp2p v0.47.0 updates to prost v0.11.0 which no longer installs the protoc Protobuf compiler. Thus to build rust-libp2p you will need protoc installed locally. On CI you can use the arduino/setup-protoc GitHub action:

- name: Install Protoc
  uses: arduino/setup-protoc@v1

For all other changes, see individual changelogs for details.

v0.46.1

11 Jul 03:11
v0.46.1
2f2b7cb
Compare
Choose a tag to compare

See individual changelogs for details.