Skip to content

Commit e4d67c5

Browse files
authored
fix(identify): Don't fail on unknown multiaddr protocol (libp2p#3279)
With this commit `libp2p-identify` no longer discards the whole identify payload in case a listen addr of the remote node is invalid, but instead logs the failure, skips the invalid multiaddr and parses the remaining identify payload. This is especially relevant when rolling out a new protocol to a live network. Say that most nodes of a network run on an implementation version v1. Say that the `multiaddr` implementation is not aware of the `webrtc/` protocol. Say that a new version (v2) is rolled out to the network with support for the `webrtc/` protocol, listening via `webrtc/` by default. In such case all v1 nodes would discard all identify payloads of v2 nodes, given that the v2 identify payloads would contain the `webrtc/` protocol in their `listen_addr` addresses. See libp2p#3244 for details.
1 parent 7dae650 commit e4d67c5

File tree

2 files changed

+49
-3
lines changed

2 files changed

+49
-3
lines changed

protocols/identify/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@
99

1010
[PR 3208]: https://github.com/libp2p/rust-libp2p/pull/3208
1111

12+
# 0.41.1
13+
14+
- Skip invalid multiaddr in `listen_addrs`. See [PR 3246].
15+
16+
[PR 3246]: https://github.com/libp2p/rust-libp2p/pull/3246
17+
1218
# 0.41.0
1319

1420
- Change default `cache_size` of `Config` to 100. See [PR 2995].

protocols/identify/src/protocol.rs

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use libp2p_core::{
2727
upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo},
2828
Multiaddr, PublicKey,
2929
};
30-
use log::trace;
30+
use log::{debug, trace};
3131
use std::convert::TryFrom;
3232
use std::{io, iter, pin::Pin};
3333
use thiserror::Error;
@@ -220,14 +220,25 @@ impl TryFrom<structs_proto::Identify> for Info {
220220
let listen_addrs = {
221221
let mut addrs = Vec::new();
222222
for addr in msg.listen_addrs.into_iter() {
223-
addrs.push(parse_multiaddr(addr)?);
223+
match parse_multiaddr(addr) {
224+
Ok(a) => addrs.push(a),
225+
Err(e) => {
226+
debug!("Unable to parse multiaddr: {e:?}");
227+
}
228+
}
224229
}
225230
addrs
226231
};
227232

228233
let public_key = PublicKey::from_protobuf_encoding(&msg.public_key.unwrap_or_default())?;
229234

230-
let observed_addr = parse_multiaddr(msg.observed_addr.unwrap_or_default())?;
235+
let observed_addr = match parse_multiaddr(msg.observed_addr.unwrap_or_default()) {
236+
Ok(a) => a,
237+
Err(e) => {
238+
debug!("Unable to parse multiaddr: {e:?}");
239+
Multiaddr::empty()
240+
}
241+
};
231242
let info = Info {
232243
public_key,
233244
protocol_version: msg.protocol_version.unwrap_or_default(),
@@ -349,4 +360,33 @@ mod tests {
349360
bg_task.await;
350361
});
351362
}
363+
364+
#[test]
365+
fn skip_invalid_multiaddr() {
366+
let valid_multiaddr: Multiaddr = "/ip6/2001:db8::/tcp/1234".parse().unwrap();
367+
let valid_multiaddr_bytes = valid_multiaddr.to_vec();
368+
369+
let invalid_multiaddr = {
370+
let a = vec![255; 8];
371+
assert!(Multiaddr::try_from(a.clone()).is_err());
372+
a
373+
};
374+
375+
let payload = structs_proto::Identify {
376+
agent_version: None,
377+
listen_addrs: vec![valid_multiaddr_bytes, invalid_multiaddr],
378+
observed_addr: None,
379+
protocol_version: None,
380+
protocols: vec![],
381+
public_key: Some(
382+
identity::Keypair::generate_ed25519()
383+
.public()
384+
.to_protobuf_encoding(),
385+
),
386+
};
387+
388+
let info = Info::try_from(payload).expect("not to fail");
389+
390+
assert_eq!(info.listen_addrs, vec![valid_multiaddr])
391+
}
352392
}

0 commit comments

Comments
 (0)