iroh v0.90 - The Canary Series 🐥
by ramfoxWelcome 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 three-week release cycles were the sweet spot for our team. Not only did three-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 “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
release, 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-relay
s 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 our APIs now return impl Watcher
, like the Endpoint::node_addr
method. Knowing all of the details of your node’s NodeAddr
may take a few milliseconds.. Something like the local address may be almost instant, but knowing it's home RelayUrl
or it's publically available addresses may take more time, since it needs to do some external probing to discover.
Returning a Watcher
here allows our users to “wait” for the NodeAddr
in the way that is most useful for them. If you just want the earliest value, let's say because you know you are on an local network, call initialize
to get the first value that appears.
If you want updates, let's say because you need to know the RelayUrl
or public facing addresses, you can call stream
to get updates when new information comes in.
use iroh::Endpoint;
use n0_watcher::Watcher;
let endpoint = Endpoint::builder()
.alpns(vec![b"my-alpn".to_vec()])
.bind()
.await?;
let node_addr = endpoint.node_addr().initialized().await?;
let stream = endpoint.node_addr().stream();
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.
❗ Subtle expectation changes around Endpoint::node_addr
and Endpoint::home_relay
❗
With some shifting of internals, two specific methods have changed in a subtle way, without changing names.
Endpoint::node_addr
used to wait until a full net-report ran, so the first update to node_addr
would usually include a RelayUrl
. Now, node_addr
returns whatever direct addresses we know about ASAP, without waiting for a relay_url
. If you had code that relied on the existance of a RelayUrl
in the NodeAddr
, you must now listen for updates to check for its existence, or just use the Endpoint::home_relay
method.
Also, previously the home_relay
and node_addr
updated at the same time, which means that previously you could use the existance of one to imply the existence of the other. This is no longer the case, so make sure that your code does not rely on this logic.
⚠️ Breaking Changes
- iroh
-
removed
iroh::endpoint::Builder:: tls_x509
removed, this is the tls mechanism that has been removediroh::endpoint::Builder:: tls_raw_public_keys
removed, this is the default mechanism now, so not needed anymoreDisplay
implementation was removed forSecretKey
, 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
, useDnsDiscovery::builder
instead - Removed
iroh::discovery::pkarr::PkarrPublisher::new
, usePkarrPublisher::builder
instead - Removed
iroh::discovery::pkarr::PkarrPublisher::with_options
, usePkarrPublisher::builder
instead - Removed
iroh::discovery::pkarr::PkarrResolver::new
, usePkarrResolver::builder
instead
-
changed
- all public APIs return concrete error types, rather than
anyhow::Error
iroh::protocol::ProtocolHandler
methods now returnimpl Future
instead ofBoxFuture
. You can simply remove theBox::pin(async move {})
from the implementations and instead implement the methods asasync fn
. See the updated documentation for theiroh::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
iniroh::protocol
as an example.iroh::watcher
is now its own craten0-watcher
, but theWatcher
trait is still a top level export iniroh
iroh::endpoint::Endpoint::node_addr
now returnsimpl Watcher<Value = Option<NodeAddr>>
iroh::endpoint::Endpoint::home_relay
now returnsimpl Watcher<Value = Vec<RelayUrl>>
iroh::endpoint::Endpoint::bound_sockets
now returnsVec<SocketAddr>
iroh-quinn
is updated to0.14.0
iroh::protocol::RouterBuilder::accept
now takesimpl Into<Box<dyn DynProtocolHandler>>
instead ofimpl ProtocolHandler
. Because of a blanketFrom
impl this change does not need any changes by users: you can still pass anyimpl ProtocolHandler
toaccept
. Additionally, if you have your own builder struct upstream, you can now also pass aBox<dyn DynProtocolHandler>
toaccept
, which wasn't possible previously.iroh::discovery::Lagged
changed from a tuple to a structiroh::watcher::Disconnected
is changed from a tuple to a structiroh::watcher::Disconnected
is no longerUnwindSafe
orRefUnwindSafe
iroh::watcher::InitializedFut
is no longerRefUnwindSafeiroh-base
iroh::endpoint::Builder::add_discovery
now takes animpl iroh::discovery::IntoDiscovery
argument instead of a closure that returns aDiscovery
. You can implement that on a builder struct, and anyT: Discovery
has an auto-impl ofIntoDiscovery
.iroh::discovery::Discovery::resolve
no longer gets a&Endpoint
argument. If you need an endpoint in your discovery service, add a builder struct and implementIntoDiscovery
for it, which gives you an endpoint that you can clone into your serviceiroh::discovery::pkarr::PkarrPublisher::n0_dns
now takes no arguments and returns aPkarrPublisherBuilder
. The secret key is set onPkarrPublisherBuilder::build
instead.
- all public APIs return concrete error types, rather than
-
iroh-base
changed
iroh_base::ticket::Error
is renamed toiroh_base::ticket::ParseError
iroh_base::key::KeyParsingError
has changed from athiserror
error to asnafu
erroriroh-relay
iroh-relay
changed
iroh_relay::node_info::MaxLengthExceededError
is no longerUnwindSafe
orRefUnwindSafe
iroh_relay::node_info::MaxLengthExceededError
was changed from athiserror
to asnafu
erroriroh_relay::client::ConnSendError
is nowiroh_relay::client::SendError
iroh_relay::protos::stun::Error
is nowiroh_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.
To get started, take a look at our docs, dive directly into the code, or chat with us in our discord channel.