Blog Index

iroh v0.90 - The Canary Series 🐥

by ramfox

Welcome to a new release of iroh, a library for building on direct connections between devices, putting more control in the hands of your users.

TL;DR: We’re jumping to v0.90 as the canary release series leading to 1.0. If you’re cool working on the bleeding edge, use 0.90. If you want to wait for 1.0, stick with v0.35.x. until we cut 1.0 toward the end of the year.

Last time we published a release blog, we said our next release would be our release candidate for 1.0. But, while working through all of our breaking changes and updates, we realized that waiting until we had everything worked through and finished before releasing was not actually the best way for us to get a stable release into the hands of our users.

In the pre 1.0 era, we’d found that 3 week release cycles were the sweet spot for our team. Not only did 3-week cycles help our working cadence, but it also made sure we got user feedback quickly, and allowed us to move forward with confidence. We want that confidence more than ever going into 1.0.

So, we’ve decided that along with maintaining the 0.35 release (as well as the public infrastructure that supports 0.35), we will be doing a series of releases that we will refer to as the “canary” releases. They will be versioned releases starting with 0.90, and continuing up until we are ready for our 1.0-rc.

The biggest difference between the way we are thinking about our new series of releases is, starting with 0.90, we are not guaranteeing network/protocol level stability until we make it to 1.0-rc.

So for those who:

  • are starting fresh with iroh
  • want to be on the cutting edge
  • do not need worry about backwards-compatibility for their networks
  • are still in the prototyping stage, or have small, easily updated deployments

We highly recommend coming along with us on our 0.90 canary journey. Our 0.90, for example, already includes performance improvements, and we want you to benefit from these kinds of changes ASAP.

But, if your network cannot tolerate multiple breaking changes over a short period of time (on the order of months), then stay on the 0.35 series until we have a release candidate.

We appreciate your patience as we figure out the best way to get to a stable 1.0 as soon as possible!

There are MANY breaking changes in this release, please do check out the “Breaking Changes” section below to see what those changes are in detail. Below are the highlights:

💥 Concrete Errors 💥

All of our APIs now return concrete errors!

This is going to be most obvious for those of you who have implemented versions of Discovery Services, or written your own protocols on iroh.

PLEASE give us feedback on our new concrete errors. This was a large change that touched most of the codebase and we are still lacking some documentation. But we want to make sure that this change works for you.

🚧 TLS x509 certificate option removed 🚧

As described in our last release blog post, we no longer support x509 TLS certifications in iroh . We have removed the iroh::endpoint::Builder::tls_x509 and the iroh::endpoint::Builder::tls_raw_public_keys endpoint builder options, since we now default to using raw public keys.

😯 iroh-relays no longer support STUN 😯

iroh no longer uses the STUN protocol to learn about our external addresses. We now rely on QUIC address discovery to to that. To that effect, the iroh-relays starting from 0.90 no longer support the STUN protocol. Our iroh configuration has also changed, as the RelayNode now only has quic configuration options.

👀 n0-watcher crate, and the Watcher trait 👀

Many of APIs now return impl Watcher , like the Endpoint::node_addr method. Knowing your node’s NodeAddr may take a few milliseconds, since it needs to do some probing to discover its own public facing addresses (if any exist). Returning a Watcher here allows our users to “wait” for the NodeAddr value to “initialize” and also watch for any potential changes to our NodeAddr, in case the user needs to inform other processes about any address changes.

Take a look at the n0-watcher crate docs for more info, but just know that the Watcher trait is re-exported in iroh, so if you want to use the Endpoint::node_addr or Endpoint::home_relay methods in iroh, you will also need to import the iroh::Watcher trait.

⚠️ Breaking Changes

  • iroh
    • removed

      • iroh::endpoint::Builder:: tls_x509 removed, this is the tls mechanism that has been removed
      • iroh::endpoint::Builder:: tls_raw_public_keys  removed, this is the default mechanism now, so not needed anymore
      • Display implementation was removed for SecretKey, use .to_bytes() and encode as hex to get the previous bytes explicitly, for example:
      let encoded_key = data_encoding::HEXLOWER.encode(&secret_key.to_bytes())
      
      • removed iroh_relay::protos::stun::StunError
      • removed iroh_relay::server::testing::stun_config
      • removed iroh_relay::protos::stun
      • removed iroh_relay::quic::QuicClient::get_addr_and_latency
      • removed DEFAULT_STUN_PORT
      • Removed iroh::discovery::dns::DnsDiscovery::new, use DnsDiscovery::builder instead
      • Removed iroh::discovery::pkarr::PkarrPublisher::new, use PkarrPublisher::builder instead
      • Removed iroh::discovery::pkarr::PkarrPublisher::with_options, use PkarrPublisher::builder instead
      • Removed iroh::discovery::pkarr::PkarrResolver::new, use PkarrResolver::builder instead
    • changed

      • all public APIs return concrete error types, rather than anyhow::Error
      • iroh::protocol::ProtocolHandler methods now return impl Future instead of BoxFuture. You can simply remove the Box::pin(async move {}) from the implementations and instead implement the methods as async fn. See the updated documentation for the iroh::protocol module for an example.
      • iroh::protocol::ProtocolHandler is no longer dyn-compatible. If you need a dyn-compatible version, you need to build your own dyn-compatible wrapper trait. See the (non-public) DynProtocolHandler in iroh::protocol as an example.
      • iroh::watcher is now its own crate n0-watcher, but the Watcher trait is still a top level export in iroh
      • iroh::endpoint::Endpoint::node_addr now returns impl Watcher<Value = Option<NodeAddr>>
      • iroh::endpoint::Endpoint::home_relay now returns impl Watcher<Value = Vec<RelayUrl>>
      • iroh::endpoint::Endpoint::bound_sockets now returns Vec<SocketAddr>
      • iroh-quinn is updated to 0.14.0
      • iroh::protocol::RouterBuilder::accept now takes impl Into<Box<dyn DynProtocolHandler>> instead of impl ProtocolHandler. Because of a blanket From impl this change does not need any changes by users: you can still pass any impl ProtocolHandler to accept. Additionally, if you have your own builder struct upstream, you can now also pass a Box<dyn DynProtocolHandler> to accept, which wasn't possible previously.
      • iroh::discovery::Lagged changed from a tuple to a struct
      • iroh::watcher::Disconnected is changed from a tuple to a struct
      • iroh::watcher::Disconnected is no longer UnwindSafe or RefUnwindSafe
      • iroh::watcher::InitializedFut is no longer RefUnwindSafeiroh-base
      • iroh::endpoint::Builder::add_discovery now takes an impl iroh::discovery::IntoDiscovery argument instead of a closure that returns a Discovery. You can implement that on a builder struct, and any T: Discovery has an auto-impl of IntoDiscovery.
      • iroh::discovery::Discovery::resolve no longer gets a &Endpoint argument. If you need an endpoint in your discovery service, add a builder struct and implement IntoDiscovery for it, which gives you an endpoint that you can clone into your service
      • iroh::discovery::pkarr::PkarrPublisher::n0_dns now takes no arguments and returns a PkarrPublisherBuilder. The secret key is set on PkarrPublisherBuilder::build instead.
  • iroh-base
    • changed
      • iroh_base::ticket::Error is renamed to iroh_base::ticket::ParseError
      • iroh_base::key::KeyParsingError has changed from a thiserror error to a snafu erroriroh-relay
  • iroh-relay
    • changed
      • iroh_relay::node_info::MaxLengthExceededError is no longer UnwindSafe or RefUnwindSafe
      • iroh_relay::node_info::MaxLengthExceededError was changed from a thiserror to a snafu error
      • iroh_relay::client::ConnSendError is now iroh_relay::client::SendError
      • iroh_relay::protos::stun::Error is now iroh_relay::protos::stun::StunError

But wait, there's more!

Many bugs were squashed, and smaller features were added. For all those details, check out the full changelog: https://github.com/n0-computer/iroh/releases/tag/v0.90.0.

If you want to know what is coming up, check out the v0.99.0 milestone, and if you have any wishes, let us know about the issues! If you need help using iroh or just want to chat, please join us on discord! And to keep up with all things iroh, check out our Twitter.

Iroh is a dial-any-device networking library that just works. Compose from an ecosystem of ready-made protocols to get the features you need, or go fully custom on a clean abstraction over dumb pipes. Iroh is open source, and already running in production on hundreds of thousands of devices.
To get started, take a look at our docs, dive directly into the code, or chat with us in our discord channel.