From 87be8e5ee81b6ee297fbe8b79941b6ea6e08de88 Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Tue, 16 Apr 2024 18:00:37 +0300 Subject: [PATCH 01/24] Introduce network backend agnostic `Multiaddr` & `Multihash` types --- substrate/client/network/types/src/lib.rs | 7 +- .../client/network/types/src/multiaddr.rs | 133 ++++++++++++++ .../network/types/src/multiaddr/protocol.rs | 138 +++++++++++++++ .../client/network/types/src/multihash.rs | 164 ++++++++++++++++++ 4 files changed, 441 insertions(+), 1 deletion(-) create mode 100644 substrate/client/network/types/src/multiaddr.rs create mode 100644 substrate/client/network/types/src/multiaddr/protocol.rs create mode 100644 substrate/client/network/types/src/multihash.rs diff --git a/substrate/client/network/types/src/lib.rs b/substrate/client/network/types/src/lib.rs index 9a126c48c7ea..1dd09f0573e0 100644 --- a/substrate/client/network/types/src/lib.rs +++ b/substrate/client/network/types/src/lib.rs @@ -13,6 +13,11 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -mod peer_id; +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +pub mod multiaddr; +pub mod multihash; +mod peer_id; pub use peer_id::PeerId; diff --git a/substrate/client/network/types/src/multiaddr.rs b/substrate/client/network/types/src/multiaddr.rs new file mode 100644 index 000000000000..1e4c6473fe19 --- /dev/null +++ b/substrate/client/network/types/src/multiaddr.rs @@ -0,0 +1,133 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use litep2p::types::multiaddr::{ + Error as LiteP2pError, Iter as LiteP2pIter, Multiaddr as LiteP2pMultiaddr, +}; +use std::{ + fmt::{self, Debug, Display}, + str::FromStr, +}; + +mod protocol; +pub use protocol::Protocol; + +/// [`Multiaddr`] type used in Substrate. Converted to libp2p's `Multiaddr` +/// or litep2p's `Multiaddr` when passed to the corresponding network backend. + +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Hash)] +pub struct Multiaddr { + multiaddr: LiteP2pMultiaddr, +} + +impl Multiaddr { + /// Adds an address component to the end of this multiaddr. + pub fn push(&mut self, p: Protocol<'_>) { + self.multiaddr.push(p.into()) + } + + /// Pops the last `Protocol` of this multiaddr, or `None` if the multiaddr is empty. + pub fn pop<'a>(&mut self) -> Option> { + self.multiaddr.pop().map(Into::into) + } + + /// Like [`Multiaddr::push`] but consumes `self`. + pub fn with(self, p: Protocol<'_>) -> Self { + self.multiaddr.with(p.into()).into() + } +} + +impl Display for Multiaddr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Display::fmt(&self.multiaddr, f) + } +} + +/// Remove an extra layer of nestedness by deferring to the wrapped value's [`Debug`]. +impl Debug for Multiaddr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Debug::fmt(&self.multiaddr, f) + } +} + +impl AsRef<[u8]> for Multiaddr { + fn as_ref(&self) -> &[u8] { + self.multiaddr.as_ref() + } +} + +impl From for Multiaddr { + fn from(multiaddr: LiteP2pMultiaddr) -> Self { + Self { multiaddr } + } +} + +impl From for LiteP2pMultiaddr { + fn from(multiaddr: Multiaddr) -> Self { + multiaddr.multiaddr + } +} + +/// Error when parsing a [`Multiaddr`] from string. +#[derive(Debug, thiserror::Error)] +pub enum ParseError { + /// Invalid multiaddress. + #[error("invalid multiaddress")] + InvalidMultiaddr, + /// Invalid protocol specification. + #[error("invalid protocol string")] + InvalidProtocolString, + /// Unknown protocol identifier. + #[error("unknown protocol '{0}'")] + UnknownProtocol(String), + /// Other error emitted when parsing into the wrapped type. + /// Never generated as of multiaddr-0.17.0. + #[error("multiaddr parsing error: {0}")] + Other(Box), +} + +impl From for ParseError { + fn from(error: LiteP2pError) -> Self { + match error { + LiteP2pError::InvalidMultiaddr => ParseError::InvalidMultiaddr, + LiteP2pError::InvalidProtocolString => ParseError::InvalidProtocolString, + LiteP2pError::UnknownProtocolString(s) => ParseError::UnknownProtocol(s), + error @ _ => ParseError::Other(Box::new(error)), + } + } +} + +impl FromStr for Multiaddr { + type Err = ParseError; + + fn from_str(s: &str) -> Result { + let multiaddr = LiteP2pMultiaddr::from_str(s)?; + Ok(Self { multiaddr }) + } +} + +/// Iterator over `Multiaddr` [`Protocol`]s. +pub struct Iter<'a>(LiteP2pIter<'a>); + +impl<'a> Iterator for Iter<'a> { + type Item = Protocol<'a>; + + fn next(&mut self) -> Option { + self.0.next().map(Into::into) + } +} diff --git a/substrate/client/network/types/src/multiaddr/protocol.rs b/substrate/client/network/types/src/multiaddr/protocol.rs new file mode 100644 index 000000000000..3b5466ea6786 --- /dev/null +++ b/substrate/client/network/types/src/multiaddr/protocol.rs @@ -0,0 +1,138 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use crate::multihash::Multihash; +use litep2p::types::multiaddr::Protocol as LiteP2pProtocol; +use std::{ + borrow::Cow, + net::{Ipv4Addr, Ipv6Addr}, +}; + +/// [`Protocol`] describes all possible multiaddress protocols. +#[derive(PartialEq, Eq, Clone, Debug)] +pub enum Protocol<'a> { + Dccp(u16), + Dns(Cow<'a, str>), + Dns4(Cow<'a, str>), + Dns6(Cow<'a, str>), + Dnsaddr(Cow<'a, str>), + Http, + Https, + Ip4(Ipv4Addr), + Ip6(Ipv6Addr), + P2pWebRtcDirect, + P2pWebRtcStar, + WebRTC, + Certhash(Multihash), + P2pWebSocketStar, + /// Contains the "port" to contact. Similar to TCP or UDP, 0 means "assign me a port". + Memory(u64), + Onion(Cow<'a, [u8; 10]>, u16), + Onion3(Cow<'a, [u8; 35]>, u16), + P2p(Multihash), + P2pCircuit, + Quic, + QuicV1, + Sctp(u16), + Tcp(u16), + Tls, + Noise, + Udp(u16), + Udt, + Unix(Cow<'a, str>), + Utp, + Ws(Cow<'a, str>), + Wss(Cow<'a, str>), +} + +impl<'a> From> for Protocol<'a> { + fn from(protocol: LiteP2pProtocol<'a>) -> Self { + match protocol { + LiteP2pProtocol::Dccp(port) => Protocol::Dccp(port), + LiteP2pProtocol::Dns(str) => Protocol::Dns(str), + LiteP2pProtocol::Dns4(str) => Protocol::Dns4(str), + LiteP2pProtocol::Dns6(str) => Protocol::Dns6(str), + LiteP2pProtocol::Dnsaddr(str) => Protocol::Dnsaddr(str), + LiteP2pProtocol::Http => Protocol::Http, + LiteP2pProtocol::Https => Protocol::Https, + LiteP2pProtocol::Ip4(ipv4_addr) => Protocol::Ip4(ipv4_addr), + LiteP2pProtocol::Ip6(ipv6_addr) => Protocol::Ip6(ipv6_addr), + LiteP2pProtocol::P2pWebRtcDirect => Protocol::P2pWebRtcDirect, + LiteP2pProtocol::P2pWebRtcStar => Protocol::P2pWebRtcStar, + LiteP2pProtocol::WebRTC => Protocol::WebRTC, + LiteP2pProtocol::Certhash(multihash) => Protocol::Certhash(multihash.into()), + LiteP2pProtocol::P2pWebSocketStar => Protocol::P2pWebSocketStar, + LiteP2pProtocol::Memory(port) => Protocol::Memory(port), + LiteP2pProtocol::Onion(str, port) => Protocol::Onion(str, port), + LiteP2pProtocol::Onion3(addr) => + Protocol::Onion3(Cow::Owned(addr.hash().clone()), addr.port()), + LiteP2pProtocol::P2p(multihash) => Protocol::P2p(multihash.into()), + LiteP2pProtocol::P2pCircuit => Protocol::P2pCircuit, + LiteP2pProtocol::Quic => Protocol::Quic, + LiteP2pProtocol::QuicV1 => Protocol::QuicV1, + LiteP2pProtocol::Sctp(port) => Protocol::Sctp(port), + LiteP2pProtocol::Tcp(port) => Protocol::Tcp(port), + LiteP2pProtocol::Tls => Protocol::Tls, + LiteP2pProtocol::Noise => Protocol::Noise, + LiteP2pProtocol::Udp(port) => Protocol::Udp(port), + LiteP2pProtocol::Udt => Protocol::Udt, + LiteP2pProtocol::Unix(str) => Protocol::Unix(str), + LiteP2pProtocol::Utp => Protocol::Utp, + LiteP2pProtocol::Ws(str) => Protocol::Ws(str), + LiteP2pProtocol::Wss(str) => Protocol::Wss(str), + } + } +} + +impl<'a> From> for LiteP2pProtocol<'a> { + fn from(protocol: Protocol<'a>) -> Self { + match protocol { + Protocol::Dccp(port) => LiteP2pProtocol::Dccp(port), + Protocol::Dns(str) => LiteP2pProtocol::Dns(str), + Protocol::Dns4(str) => LiteP2pProtocol::Dns4(str), + Protocol::Dns6(str) => LiteP2pProtocol::Dns6(str), + Protocol::Dnsaddr(str) => LiteP2pProtocol::Dnsaddr(str), + Protocol::Http => LiteP2pProtocol::Http, + Protocol::Https => LiteP2pProtocol::Https, + Protocol::Ip4(ipv4_addr) => LiteP2pProtocol::Ip4(ipv4_addr), + Protocol::Ip6(ipv6_addr) => LiteP2pProtocol::Ip6(ipv6_addr), + Protocol::P2pWebRtcDirect => LiteP2pProtocol::P2pWebRtcDirect, + Protocol::P2pWebRtcStar => LiteP2pProtocol::P2pWebRtcStar, + Protocol::WebRTC => LiteP2pProtocol::WebRTC, + Protocol::Certhash(multihash) => LiteP2pProtocol::Certhash(multihash.into()), + Protocol::P2pWebSocketStar => LiteP2pProtocol::P2pWebSocketStar, + Protocol::Memory(port) => LiteP2pProtocol::Memory(port), + Protocol::Onion(str, port) => LiteP2pProtocol::Onion(str, port), + Protocol::Onion3(str, port) => LiteP2pProtocol::Onion3((str.into_owned(), port).into()), + Protocol::P2p(multihash) => LiteP2pProtocol::P2p(multihash.into()), + Protocol::P2pCircuit => LiteP2pProtocol::P2pCircuit, + Protocol::Quic => LiteP2pProtocol::Quic, + Protocol::QuicV1 => LiteP2pProtocol::QuicV1, + Protocol::Sctp(port) => LiteP2pProtocol::Sctp(port), + Protocol::Tcp(port) => LiteP2pProtocol::Tcp(port), + Protocol::Tls => LiteP2pProtocol::Tls, + Protocol::Noise => LiteP2pProtocol::Noise, + Protocol::Udp(port) => LiteP2pProtocol::Udp(port), + Protocol::Udt => LiteP2pProtocol::Udt, + Protocol::Unix(str) => LiteP2pProtocol::Unix(str), + Protocol::Utp => LiteP2pProtocol::Utp, + Protocol::Ws(str) => LiteP2pProtocol::Ws(str), + Protocol::Wss(str) => LiteP2pProtocol::Wss(str), + } + } +} diff --git a/substrate/client/network/types/src/multihash.rs b/substrate/client/network/types/src/multihash.rs new file mode 100644 index 000000000000..5aaae556c93a --- /dev/null +++ b/substrate/client/network/types/src/multihash.rs @@ -0,0 +1,164 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! [`Multihash`] implemenattion used by substrate. Currently it's a wrapper over +//! multihash used by litep2p, but it can be switched to other implementation if needed. + +use litep2p::types::multihash::{ + Code as LiteP2pCode, Error as LiteP2pError, Multihash as LiteP2pMultihash, + MultihashDigest as LiteP2pDigest, +}; +use std::fmt::{self, Debug}; + +/// Default [`Multihash`] implementations. Only hashes used by substrate are defined. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Code { + /// Identity hasher. + Identity, + /// SHA-256 (32-byte hash size). + Sha2_256, +} + +impl Code { + /// Calculate digest using this [`Code`]'s hashing algorithm. + pub fn digest(&self, input: &[u8]) -> Multihash { + LiteP2pCode::from(*self).digest(input).into() + } +} + +/// Error generated when converting to [`Code`]. +#[derive(Debug, thiserror::Error)] +pub enum CodeError { + /// The multihash code is not supported. + #[error("unsupported multihash code '{0}'")] + UsupportedCode(u64), + /// Catch-all for other errors emitted when converting `u64` code to enum. + /// Never generated as of multihash-0.17.0. + #[error("multihash code conversion error: {0}")] + Other(Box), +} + +impl From for LiteP2pCode { + fn from(code: Code) -> Self { + match code { + Code::Identity => LiteP2pCode::Identity, + Code::Sha2_256 => LiteP2pCode::Sha2_256, + } + } +} + +impl TryFrom for Code { + type Error = CodeError; + + fn try_from(code: LiteP2pCode) -> Result { + match code { + LiteP2pCode::Identity => Ok(Code::Identity), + LiteP2pCode::Sha2_256 => Ok(Code::Sha2_256), + _ => Err(CodeError::UsupportedCode(code.into())), + } + } +} + +impl TryFrom for Code { + type Error = CodeError; + + fn try_from(code: u64) -> Result { + match LiteP2pCode::try_from(code) { + Ok(code) => code.try_into(), + Err(LiteP2pError::UnsupportedCode(code)) => Err(CodeError::UsupportedCode(code)), + Err(e) => Err(CodeError::Other(Box::new(e))), + } + } +} + +impl From for u64 { + fn from(code: Code) -> Self { + LiteP2pCode::from(code).into() + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Ord, PartialOrd)] +pub struct Multihash { + multihash: LiteP2pMultihash, +} + +impl Multihash { + /// Multihash code. + pub fn code(&self) -> u64 { + self.multihash.code() + } + + /// Multihash digest. + pub fn digest(&self) -> &[u8] { + self.multihash.digest() + } +} + +/// Remove extra layer of nestedness by deferring to the wrapped value's [`Debug`]. +impl Debug for Multihash { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Debug::fmt(&self.multihash, f) + } +} + +impl From for Multihash { + fn from(multihash: LiteP2pMultihash) -> Self { + Multihash { multihash } + } +} + +impl From for LiteP2pMultihash { + fn from(multihash: Multihash) -> Self { + multihash.multihash + } +} + +// TODO: uncomment this after upgrading `multihash` crate to v0.19.1. +// +// impl From> for Multihash { +// fn from(generic: multihash::MultihashGeneric<64>) -> Self { +// LiteP2pMultihash::wrap(generic.code(), generic.digest()) +// .expect("both have size 64; qed") +// .into() +// } +// } +// +// impl From for multihash::Multihash<64> { +// fn from(multihash: Multihash) -> Self { +// multihash::Multihash::<64>::wrap(multihash.code(), multihash.digest()) +// .expect("both have size 64; qed") +// } +// } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn code_from_u64() { + assert_eq!(Code::try_from(0x00).unwrap(), Code::Identity); + assert_eq!(Code::try_from(0x12).unwrap(), Code::Sha2_256); + assert!(matches!(Code::try_from(0x01).unwrap_err(), CodeError::UsupportedCode(0x01))); + } + + #[test] + fn code_into_u64() { + assert_eq!(u64::from(Code::Identity), 0x00); + assert_eq!(u64::from(Code::Sha2_256), 0x12); + } +} From 584038e6290535d9a0bac76ba43890f3128256ce Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Fri, 19 Apr 2024 17:16:14 +0300 Subject: [PATCH 02/24] Extend substrate's `Multihash`, make substrate's `PeerId` use it --- .../client/network/types/src/multiaddr.rs | 16 ++++++ .../client/network/types/src/multihash.rs | 55 ++++++++++++++----- substrate/client/network/types/src/peer_id.rs | 8 ++- 3 files changed, 63 insertions(+), 16 deletions(-) diff --git a/substrate/client/network/types/src/multiaddr.rs b/substrate/client/network/types/src/multiaddr.rs index 1e4c6473fe19..fc3c29f4fb76 100644 --- a/substrate/client/network/types/src/multiaddr.rs +++ b/substrate/client/network/types/src/multiaddr.rs @@ -36,6 +36,11 @@ pub struct Multiaddr { } impl Multiaddr { + /// Create a new, empty multiaddress. + pub fn empty() -> Self { + Self { multiaddr: LiteP2pMultiaddr::empty() } + } + /// Adds an address component to the end of this multiaddr. pub fn push(&mut self, p: Protocol<'_>) { self.multiaddr.push(p.into()) @@ -50,6 +55,11 @@ impl Multiaddr { pub fn with(self, p: Protocol<'_>) -> Self { self.multiaddr.with(p.into()).into() } + + /// Returns the components of this multiaddress. + pub fn iter(&self) -> Iter<'_> { + self.multiaddr.iter().into() + } } impl Display for Multiaddr { @@ -131,3 +141,9 @@ impl<'a> Iterator for Iter<'a> { self.0.next().map(Into::into) } } + +impl<'a> From> for Iter<'a> { + fn from(iter: LiteP2pIter<'a>) -> Self { + Self(iter) + } +} diff --git a/substrate/client/network/types/src/multihash.rs b/substrate/client/network/types/src/multihash.rs index 5aaae556c93a..02e69dc1166a 100644 --- a/substrate/client/network/types/src/multihash.rs +++ b/substrate/client/network/types/src/multihash.rs @@ -43,16 +43,29 @@ impl Code { /// Error generated when converting to [`Code`]. #[derive(Debug, thiserror::Error)] -pub enum CodeError { +pub enum Error { + /// Invalid multihash size. + #[error("invalid multihash size '{0}'")] + InvalidSize(u64), /// The multihash code is not supported. - #[error("unsupported multihash code '{0}'")] - UsupportedCode(u64), - /// Catch-all for other errors emitted when converting `u64` code to enum. - /// Never generated as of multihash-0.17.0. - #[error("multihash code conversion error: {0}")] + #[error("unsupported multihash code '{0:x}'")] + UnsupportedCode(u64), + /// Catch-all for other errors emitted when converting `u64` code to enum or parsing multihash + /// from bytes. Never generated as of multihash-0.17.0. + #[error("other error: {0}")] Other(Box), } +impl From for Error { + fn from(error: LiteP2pError) -> Self { + match error { + LiteP2pError::InvalidSize(s) => Self::InvalidSize(s), + LiteP2pError::UnsupportedCode(c) => Self::UnsupportedCode(c), + e @ _ => Self::Other(Box::new(e)), + } + } +} + impl From for LiteP2pCode { fn from(code: Code) -> Self { match code { @@ -63,25 +76,24 @@ impl From for LiteP2pCode { } impl TryFrom for Code { - type Error = CodeError; + type Error = Error; fn try_from(code: LiteP2pCode) -> Result { match code { LiteP2pCode::Identity => Ok(Code::Identity), LiteP2pCode::Sha2_256 => Ok(Code::Sha2_256), - _ => Err(CodeError::UsupportedCode(code.into())), + _ => Err(Error::UnsupportedCode(code.into())), } } } impl TryFrom for Code { - type Error = CodeError; + type Error = Error; fn try_from(code: u64) -> Result { match LiteP2pCode::try_from(code) { Ok(code) => code.try_into(), - Err(LiteP2pError::UnsupportedCode(code)) => Err(CodeError::UsupportedCode(code)), - Err(e) => Err(CodeError::Other(Box::new(e))), + Err(e) => Err(e.into()), } } } @@ -92,7 +104,7 @@ impl From for u64 { } } -#[derive(Clone, Copy, PartialEq, Eq, Ord, PartialOrd)] +#[derive(Clone, Copy, Hash, PartialEq, Eq, Ord, PartialOrd)] pub struct Multihash { multihash: LiteP2pMultihash, } @@ -107,6 +119,23 @@ impl Multihash { pub fn digest(&self) -> &[u8] { self.multihash.digest() } + + /// Wraps the digest in a multihash. + pub fn wrap(code: u64, input_digest: &[u8]) -> Result { + LiteP2pMultihash::wrap(code, input_digest).map(Into::into).map_err(Into::into) + } + + /// Parses a multihash from bytes. + /// + /// You need to make sure the passed in bytes have the length of 64. + pub fn from_bytes(bytes: &[u8]) -> Result { + LiteP2pMultihash::from_bytes(bytes).map(Into::into).map_err(Into::into) + } + + /// Returns the bytes of a multihash. + pub fn to_bytes(&self) -> Vec { + self.multihash.to_bytes() + } } /// Remove extra layer of nestedness by deferring to the wrapped value's [`Debug`]. @@ -153,7 +182,7 @@ mod tests { fn code_from_u64() { assert_eq!(Code::try_from(0x00).unwrap(), Code::Identity); assert_eq!(Code::try_from(0x12).unwrap(), Code::Sha2_256); - assert!(matches!(Code::try_from(0x01).unwrap_err(), CodeError::UsupportedCode(0x01))); + assert!(matches!(Code::try_from(0x01).unwrap_err(), Error::UnsupportedCode(0x01))); } #[test] diff --git a/substrate/client/network/types/src/peer_id.rs b/substrate/client/network/types/src/peer_id.rs index 14ac4a1e9aae..076be0a66c7b 100644 --- a/substrate/client/network/types/src/peer_id.rs +++ b/substrate/client/network/types/src/peer_id.rs @@ -16,8 +16,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use multiaddr::{Multiaddr, Protocol}; -use multihash::{Code, Error, Multihash}; +use crate::{ + multiaddr::{Multiaddr, Protocol}, + multihash::{Code, Error, Multihash}, +}; use rand::Rng; use std::{fmt, hash::Hash, str::FromStr}; @@ -185,7 +187,7 @@ pub enum ParseError { #[error("unsupported multihash code '{0}'")] UnsupportedCode(u64), #[error("invalid multihash")] - InvalidMultihash(#[from] multihash::Error), + InvalidMultihash(#[from] crate::multihash::Error), } impl FromStr for PeerId { From 8100f7f41528187b9c6321963217c04e7b6b0099 Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Fri, 19 Apr 2024 17:36:26 +0300 Subject: [PATCH 03/24] Allow constructing `Multiaddr` from iterator of protocols --- .../client/network/types/src/multiaddr.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/substrate/client/network/types/src/multiaddr.rs b/substrate/client/network/types/src/multiaddr.rs index fc3c29f4fb76..8487b2488986 100644 --- a/substrate/client/network/types/src/multiaddr.rs +++ b/substrate/client/network/types/src/multiaddr.rs @@ -147,3 +147,21 @@ impl<'a> From> for Iter<'a> { Self(iter) } } + +impl<'a> IntoIterator for &'a Multiaddr { + type Item = Protocol<'a>; + type IntoIter = Iter<'a>; + + fn into_iter(self) -> Iter<'a> { + self.multiaddr.into_iter().into() + } +} + +impl<'a> FromIterator> for Multiaddr { + fn from_iter(iter: T) -> Self + where + T: IntoIterator>, + { + LiteP2pMultiaddr::from_iter(iter.into_iter().map(Into::into)).into() + } +} From ea85860f1b422692042dc988664fe03d53ade684 Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Fri, 19 Apr 2024 17:37:37 +0300 Subject: [PATCH 04/24] Convert network config to use substrate's `Multiaddr` --- substrate/client/network/src/config.rs | 28 ++++++++++++++++---------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/substrate/client/network/src/config.rs b/substrate/client/network/src/config.rs index e6cc9de56942..69772ee813d9 100644 --- a/substrate/client/network/src/config.rs +++ b/substrate/client/network/src/config.rs @@ -38,9 +38,11 @@ pub use crate::{ pub use libp2p::{ build_multiaddr, identity::{self, ed25519, Keypair}, - multiaddr, Multiaddr, }; -use sc_network_types::PeerId; +use sc_network_types::{ + multiaddr::{self, Multiaddr}, + PeerId, +}; use crate::service::{ensure_addresses_consistent_with_transport, traits::NetworkBackend}; use codec::Encode; @@ -187,7 +189,7 @@ impl TryFrom for MultiaddrWithPeerId { #[derive(Debug)] pub enum ParseErr { /// Error while parsing the multiaddress. - MultiaddrParse(multiaddr::Error), + MultiaddrParse(multiaddr::ParseError), /// Multihash of the peer ID is invalid. InvalidPeerId, /// The peer ID is missing from the address. @@ -214,8 +216,8 @@ impl std::error::Error for ParseErr { } } -impl From for ParseErr { - fn from(err: multiaddr::Error) -> ParseErr { +impl From for ParseErr { + fn from(err: multiaddr::ParseError) -> ParseErr { Self::MultiaddrParse(err) } } @@ -846,11 +848,11 @@ impl> FullNetworkConfig /// Verify addresses are consistent with enabled transports. pub fn sanity_check_addresses(&self) -> Result<(), crate::error::Error> { ensure_addresses_consistent_with_transport( - self.network_config.listen_addresses.iter(), + self.network_config.listen_addresses.iter().map(|addr| &addr.to_owned().into()), &self.network_config.transport, )?; ensure_addresses_consistent_with_transport( - self.network_config.boot_nodes.iter().map(|x| &x.multiaddr), + self.network_config.boot_nodes.iter().map(|x| &x.multiaddr.into()), &self.network_config.transport, )?; ensure_addresses_consistent_with_transport( @@ -858,18 +860,22 @@ impl> FullNetworkConfig .default_peers_set .reserved_nodes .iter() - .map(|x| &x.multiaddr), + .map(|x| &x.multiaddr.into()), &self.network_config.transport, )?; for notification_protocol in &self.notification_protocols { ensure_addresses_consistent_with_transport( - notification_protocol.set_config().reserved_nodes.iter().map(|x| &x.multiaddr), + notification_protocol + .set_config() + .reserved_nodes + .iter() + .map(|x| &x.multiaddr.into()), &self.network_config.transport, )?; } ensure_addresses_consistent_with_transport( - self.network_config.public_addresses.iter(), + self.network_config.public_addresses.iter().map(|addr| &addr.to_owned().into()), &self.network_config.transport, )?; @@ -887,7 +893,7 @@ impl> FullNetworkConfig .find(|o| o.peer_id != bootnode.peer_id) { Err(crate::error::Error::DuplicateBootnode { - address: bootnode.multiaddr.clone(), + address: bootnode.multiaddr.clone().into(), first_id: bootnode.peer_id.into(), second_id: other.peer_id.into(), }) From 94af781b15542b2f13d4011f48cb6a1531cc363e Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Tue, 23 Apr 2024 18:03:21 +0300 Subject: [PATCH 05/24] Add `ed25519` types to `sc-network-types` --- substrate/client/network/types/Cargo.toml | 5 + substrate/client/network/types/src/ed25519.rs | 374 ++++++++++++++++++ substrate/client/network/types/src/lib.rs | 1 + .../client/network/types/src/multiaddr.rs | 30 ++ 4 files changed, 410 insertions(+) create mode 100644 substrate/client/network/types/src/ed25519.rs diff --git a/substrate/client/network/types/Cargo.toml b/substrate/client/network/types/Cargo.toml index d8f03939ab96..430adbac5092 100644 --- a/substrate/client/network/types/Cargo.toml +++ b/substrate/client/network/types/Cargo.toml @@ -11,9 +11,14 @@ documentation = "https://docs.rs/sc-network-types" [dependencies] bs58 = "0.4.0" +ed25519-dalek = "2.1" libp2p-identity = { version = "0.1.3", features = ["ed25519", "peerid"] } litep2p = { git = "https://github.com/paritytech/litep2p", branch = "master" } multiaddr = "0.17.0" multihash = { version = "0.17.0", default-features = false, features = ["identity", "multihash-impl", "sha2", "std"] } rand = "0.8.5" thiserror = "1.0.48" +zeroize = { version = "1.7.0", default-features = false } + +[dev-dependencies] +quickcheck = "1.0.3" diff --git a/substrate/client/network/types/src/ed25519.rs b/substrate/client/network/types/src/ed25519.rs new file mode 100644 index 000000000000..aa769fba3703 --- /dev/null +++ b/substrate/client/network/types/src/ed25519.rs @@ -0,0 +1,374 @@ +// This file is part of Substrate. +// This file is based on libp2p and therefore licensed under both MIT & GPL. + +// Copyright 2019 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: MIT +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Ed25519 keys. + +use crate::PeerId; +use core::{cmp, fmt, hash}; +use ed25519_dalek::{self as ed25519, Signer as _, Verifier as _}; +use libp2p_identity::ed25519 as libp2p_ed25519; +use litep2p::crypto::ed25519 as litep2p_ed25519; +use zeroize::Zeroize; + +/// An Ed25519 keypair. +#[derive(Clone)] +pub struct Keypair(ed25519::SigningKey); + +impl Keypair { + /// Generate a new random Ed25519 keypair. + pub fn generate() -> Keypair { + Keypair::from(SecretKey::generate()) + } + + /// Convert the keypair into a byte array by concatenating the bytes + /// of the secret scalar and the compressed public point, + /// an informal standard for encoding Ed25519 keypairs. + pub fn to_bytes(&self) -> [u8; 64] { + self.0.to_keypair_bytes() + } + + /// Try to parse a keypair from the [binary format](https://datatracker.ietf.org/doc/html/rfc8032#section-5.1.5) + /// produced by [`Keypair::to_bytes`], zeroing the input on success. + /// + /// Note that this binary format is the same as `ed25519_dalek`'s and `ed25519_zebra`'s. + pub fn try_from_bytes(kp: &mut [u8]) -> Result { + let bytes = <[u8; 64]>::try_from(&*kp) + .map_err(|e| DecodingError::KeypairParseError(Box::new(e)))?; + + ed25519::SigningKey::from_keypair_bytes(&bytes) + .map(|k| { + kp.zeroize(); + Keypair(k) + }) + .map_err(|e| DecodingError::KeypairParseError(Box::new(e))) + } + + /// Sign a message using the private key of this keypair. + pub fn sign(&self, msg: &[u8]) -> Vec { + self.0.sign(msg).to_bytes().to_vec() + } + + /// Get the public key of this keypair. + pub fn public(&self) -> PublicKey { + PublicKey(self.0.verifying_key()) + } + + /// Get the secret key of this keypair. + pub fn secret(&self) -> SecretKey { + SecretKey(self.0.to_bytes()) + } +} + +impl fmt::Debug for Keypair { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Keypair").field("public", &self.0.verifying_key()).finish() + } +} + +impl From for Keypair { + fn from(kp: litep2p_ed25519::Keypair) -> Self { + Self::try_from_bytes(&mut kp.encode()) + .expect("ed25519_dalek in substrate & litep2p to use the same format") + } +} + +impl From for litep2p_ed25519::Keypair { + fn from(kp: Keypair) -> Self { + Self::decode(&mut kp.to_bytes()) + .expect("ed25519_dalek in substrate & litep2p to use the same format") + } +} + +impl From for Keypair { + fn from(kp: libp2p_ed25519::Keypair) -> Self { + Self::try_from_bytes(&mut kp.to_bytes()) + .expect("ed25519_dalek in substrate & libp2p to use the same format") + } +} + +impl From for libp2p_ed25519::Keypair { + fn from(kp: Keypair) -> Self { + Self::try_from_bytes(&mut kp.to_bytes()) + .expect("ed25519_dalek in substrate & libp2p to use the same format") + } +} + +/// Demote an Ed25519 keypair to a secret key. +impl From for SecretKey { + fn from(kp: Keypair) -> SecretKey { + SecretKey(kp.0.to_bytes()) + } +} + +/// Promote an Ed25519 secret key into a keypair. +impl From for Keypair { + fn from(sk: SecretKey) -> Keypair { + let signing = ed25519::SigningKey::from_bytes(&sk.0); + Keypair(signing) + } +} + +/// An Ed25519 public key. +#[derive(Eq, Clone)] +pub struct PublicKey(ed25519::VerifyingKey); + +impl fmt::Debug for PublicKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("PublicKey(compressed): ")?; + for byte in self.0.as_bytes() { + write!(f, "{byte:x}")?; + } + Ok(()) + } +} + +impl cmp::PartialEq for PublicKey { + fn eq(&self, other: &Self) -> bool { + self.0.as_bytes().eq(other.0.as_bytes()) + } +} + +impl hash::Hash for PublicKey { + fn hash(&self, state: &mut H) { + self.0.as_bytes().hash(state); + } +} + +impl cmp::PartialOrd for PublicKey { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl cmp::Ord for PublicKey { + fn cmp(&self, other: &Self) -> cmp::Ordering { + self.0.as_bytes().cmp(other.0.as_bytes()) + } +} + +impl PublicKey { + /// Verify the Ed25519 signature on a message using the public key. + pub fn verify(&self, msg: &[u8], sig: &[u8]) -> bool { + ed25519::Signature::try_from(sig).and_then(|s| self.0.verify(msg, &s)).is_ok() + } + + /// Convert the public key to a byte array in compressed form, i.e. + /// where one coordinate is represented by a single bit. + pub fn to_bytes(&self) -> [u8; 32] { + self.0.to_bytes() + } + + /// Try to parse a public key from a byte array containing the actual key as produced by + /// `to_bytes`. + pub fn try_from_bytes(k: &[u8]) -> Result { + let k = + <[u8; 32]>::try_from(k).map_err(|e| DecodingError::PublicKeyParseError(Box::new(e)))?; + ed25519::VerifyingKey::from_bytes(&k) + .map_err(|e| DecodingError::PublicKeyParseError(Box::new(e))) + .map(PublicKey) + } + + /// Convert public key to `PeerId`. + pub fn to_peer_id(&self) -> PeerId { + litep2p::PeerId::from(litep2p::crypto::PublicKey::Ed25519(self.clone().into())).into() + } +} + +impl From for PublicKey { + fn from(k: litep2p_ed25519::PublicKey) -> Self { + Self::try_from_bytes(&k.encode()) + .expect("ed25519_dalek in substrate & litep2p to use the same format") + } +} + +impl From for litep2p_ed25519::PublicKey { + fn from(k: PublicKey) -> Self { + Self::decode(&k.to_bytes()) + .expect("ed25519_dalek in substrate & litep2p to use the same format") + } +} + +impl From for PublicKey { + fn from(k: libp2p_ed25519::PublicKey) -> Self { + Self::try_from_bytes(&k.to_bytes()) + .expect("ed25519_dalek in substrate & libp2p to use the same format") + } +} + +impl From for libp2p_ed25519::PublicKey { + fn from(k: PublicKey) -> Self { + Self::try_from_bytes(&k.to_bytes()) + .expect("ed25519_dalek in substrate & libp2p to use the same format") + } +} + +/// An Ed25519 secret key. +#[derive(Clone)] +pub struct SecretKey(ed25519::SecretKey); + +/// View the bytes of the secret key. +impl AsRef<[u8]> for SecretKey { + fn as_ref(&self) -> &[u8] { + &self.0[..] + } +} + +impl fmt::Debug for SecretKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "SecretKey") + } +} + +impl SecretKey { + /// Generate a new Ed25519 secret key. + pub fn generate() -> SecretKey { + let signing = ed25519::SigningKey::generate(&mut rand::rngs::OsRng); + SecretKey(signing.to_bytes()) + } + + /// Try to parse an Ed25519 secret key from a byte slice + /// containing the actual key, zeroing the input on success. + /// If the bytes do not constitute a valid Ed25519 secret key, an error is + /// returned. + pub fn try_from_bytes(mut sk_bytes: impl AsMut<[u8]>) -> Result { + let sk_bytes = sk_bytes.as_mut(); + let secret = <[u8; 32]>::try_from(&*sk_bytes) + .map_err(|e| DecodingError::SecretKeyParseError(Box::new(e)))?; + sk_bytes.zeroize(); + Ok(SecretKey(secret)) + } + + pub fn to_bytes(&self) -> [u8; 32] { + self.0 + } +} + +impl Drop for SecretKey { + fn drop(&mut self) { + self.0.zeroize(); + } +} + +impl From for SecretKey { + fn from(sk: litep2p_ed25519::SecretKey) -> Self { + Self::try_from_bytes(&mut sk.to_bytes()).expect("Ed25519 key to be 32 bytes length") + } +} + +impl From for litep2p_ed25519::SecretKey { + fn from(sk: SecretKey) -> Self { + Self::from_bytes(&mut sk.to_bytes()) + .expect("litep2p `SecretKey` to accept 32 bytes as Ed25519 key") + } +} + +impl From for SecretKey { + fn from(sk: libp2p_ed25519::SecretKey) -> Self { + Self::try_from_bytes(&mut sk.as_ref().to_owned()) + .expect("Ed25519 key to be 32 bytes length") + } +} + +impl From for libp2p_ed25519::SecretKey { + fn from(sk: SecretKey) -> Self { + Self::try_from_bytes(&mut sk.to_bytes()) + .expect("libp2p `SecretKey` to accept 32 bytes as Ed25519 key") + } +} + +/// Error when decoding `ed25519`-related types. +#[derive(Debug, thiserror::Error)] +pub enum DecodingError { + #[error("failed to parse Ed25519 keypair: {0}")] + KeypairParseError(Box), + #[error("failed to parse Ed25519 secret key: {0}")] + SecretKeyParseError(Box), + #[error("failed to parse Ed25519 public key: {0}")] + PublicKeyParseError(Box), +} + +#[cfg(test)] +mod tests { + use super::*; + use quickcheck::*; + + fn eq_keypairs(kp1: &Keypair, kp2: &Keypair) -> bool { + kp1.public() == kp2.public() && kp1.0.to_bytes() == kp2.0.to_bytes() + } + + #[test] + fn ed25519_keypair_encode_decode() { + fn prop() -> bool { + let kp1 = Keypair::generate(); + let mut kp1_enc = kp1.to_bytes(); + let kp2 = Keypair::try_from_bytes(&mut kp1_enc).unwrap(); + eq_keypairs(&kp1, &kp2) && kp1_enc.iter().all(|b| *b == 0) + } + QuickCheck::new().tests(10).quickcheck(prop as fn() -> _); + } + + #[test] + fn ed25519_keypair_from_secret() { + fn prop() -> bool { + let kp1 = Keypair::generate(); + let mut sk = kp1.0.to_bytes(); + let kp2 = Keypair::from(SecretKey::try_from_bytes(&mut sk).unwrap()); + eq_keypairs(&kp1, &kp2) && sk == [0u8; 32] + } + QuickCheck::new().tests(10).quickcheck(prop as fn() -> _); + } + + #[test] + fn ed25519_signature() { + let kp = Keypair::generate(); + let pk = kp.public(); + + let msg = "hello world".as_bytes(); + let sig = kp.sign(msg); + assert!(pk.verify(msg, &sig)); + + let mut invalid_sig = sig.clone(); + invalid_sig[3..6].copy_from_slice(&[10, 23, 42]); + assert!(!pk.verify(msg, &invalid_sig)); + + let invalid_msg = "h3ll0 w0rld".as_bytes(); + assert!(!pk.verify(invalid_msg, &sig)); + } +} diff --git a/substrate/client/network/types/src/lib.rs b/substrate/client/network/types/src/lib.rs index 1dd09f0573e0..5684e38ab2e8 100644 --- a/substrate/client/network/types/src/lib.rs +++ b/substrate/client/network/types/src/lib.rs @@ -16,6 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +pub mod ed25519; pub mod multiaddr; pub mod multihash; diff --git a/substrate/client/network/types/src/multiaddr.rs b/substrate/client/network/types/src/multiaddr.rs index 8487b2488986..dd43401a6126 100644 --- a/substrate/client/network/types/src/multiaddr.rs +++ b/substrate/client/network/types/src/multiaddr.rs @@ -165,3 +165,33 @@ impl<'a> FromIterator> for Multiaddr { LiteP2pMultiaddr::from_iter(iter.into_iter().map(Into::into)).into() } } + +/// Easy way for a user to create a `Multiaddr`. +/// +/// Example: +/// +/// ```rust +/// # use multiaddr::multiaddr; +/// let addr = build_multiaddr!(Ip4([127, 0, 0, 1]), Tcp(10500u16)); +/// ``` +/// +/// Each element passed to `multiaddr!` should be a variant of the `Protocol` enum. The +/// optional parameter is turned into the proper type with the `Into` trait. +/// +/// For example, `Ip4([127, 0, 0, 1])` works because `Ipv4Addr` implements `From<[u8; 4]>`. +#[macro_export] +macro_rules! build_multiaddr { + ($($comp:ident $(($param:expr))*),+) => { + { + use std::iter; + let elem = iter::empty::<$crate::multiaddr::Protocol>(); + $( + let elem = { + let cmp = $crate::multiaddr::Protocol::$comp $(( $param.into() ))*; + elem.chain(iter::once(cmp)) + }; + )+ + elem.collect::<$crate::multiaddr::Multiaddr>() + } + } +} From aa4d28d24bf21170b003e130a4bc0329b4f589aa Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Tue, 23 Apr 2024 19:30:01 +0300 Subject: [PATCH 06/24] cargo update litep2p --- Cargo.lock | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2339aff34bcd..d38d973a9f03 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1947,7 +1947,7 @@ dependencies = [ "bp-parachains", "bp-polkadot-core", "bp-runtime", - "ed25519-dalek 2.1.0", + "ed25519-dalek 2.1.1", "finality-grandpa", "parity-scale-codec", "sp-application-crypto", @@ -5026,9 +5026,9 @@ dependencies = [ [[package]] name = "ed25519-dalek" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ "curve25519-dalek 4.1.2", "ed25519 2.2.2", @@ -7726,7 +7726,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "276bb57e7af15d8f100d3c11cbdd32c6752b7eef4ba7a18ecf464972c07abcce" dependencies = [ "bs58 0.4.0", - "ed25519-dalek 2.1.0", + "ed25519-dalek 2.1.1", "log", "multiaddr", "multihash 0.17.0", @@ -8150,7 +8150,7 @@ dependencies = [ [[package]] name = "litep2p" version = "0.3.0" -source = "git+https://github.com/paritytech/litep2p?branch=master#b142c9eb611fb2fe78d2830266a3675b37299ceb" +source = "git+https://github.com/paritytech/litep2p?branch=master#08112ca642cea3809625ae0abde05dc0dc46b4f3" dependencies = [ "async-trait", "bs58 0.4.0", @@ -17244,12 +17244,15 @@ name = "sc-network-types" version = "0.10.0-dev" dependencies = [ "bs58 0.4.0", + "ed25519-dalek 2.1.1", "libp2p-identity", "litep2p", "multiaddr", "multihash 0.17.0", + "quickcheck", "rand 0.8.5", "thiserror", + "zeroize", ] [[package]] @@ -19520,7 +19523,7 @@ name = "sp-io" version = "30.0.0" dependencies = [ "bytes", - "ed25519-dalek 2.1.0", + "ed25519-dalek 2.1.1", "libsecp256k1", "log", "parity-scale-codec", @@ -19845,7 +19848,7 @@ version = "10.0.0" dependencies = [ "aes-gcm 0.10.3", "curve25519-dalek 4.1.2", - "ed25519-dalek 2.1.0", + "ed25519-dalek 2.1.1", "hkdf", "parity-scale-codec", "rand 0.8.5", @@ -20394,9 +20397,9 @@ dependencies = [ [[package]] name = "str0m" -version = "0.2.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee48572247f422dcbe68630c973f8296fbd5157119cd36a3223e48bf83d47727" +checksum = "d3f10d3f68e60168d81110410428a435dbde28cc5525f5f7c6fdec92dbdc2800" dependencies = [ "combine", "crc", From da59b29345bd3998617e741a3ce4f6e344c9e248 Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Wed, 24 Apr 2024 14:28:58 +0300 Subject: [PATCH 07/24] Make `Check licenses` check happy --- substrate/client/network/types/src/ed25519.rs | 28 ++----------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/substrate/client/network/types/src/ed25519.rs b/substrate/client/network/types/src/ed25519.rs index aa769fba3703..40d1d12c5af9 100644 --- a/substrate/client/network/types/src/ed25519.rs +++ b/substrate/client/network/types/src/ed25519.rs @@ -1,40 +1,18 @@ // This file is part of Substrate. -// This file is based on libp2p and therefore licensed under both MIT & GPL. - -// Copyright 2019 Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: MIT -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. // Copyright (C) Parity Technologies (UK) Ltd. // SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 -// + // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. -// + // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -// + // You should have received a copy of the GNU General Public License // along with this program. If not, see . From f61410666f1284e6b65d784af406ce7a1c690ca0 Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Wed, 24 Apr 2024 15:37:47 +0300 Subject: [PATCH 08/24] Make network config use substrate-specific types --- substrate/client/network/src/config.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/substrate/client/network/src/config.rs b/substrate/client/network/src/config.rs index 69772ee813d9..6e76cbce7109 100644 --- a/substrate/client/network/src/config.rs +++ b/substrate/client/network/src/config.rs @@ -35,10 +35,7 @@ pub use crate::{ types::ProtocolName, }; -pub use libp2p::{ - build_multiaddr, - identity::{self, ed25519, Keypair}, -}; +pub use sc_network_types::{build_multiaddr, ed25519}; use sc_network_types::{ multiaddr::{self, Multiaddr}, PeerId, @@ -345,10 +342,10 @@ impl NodeKeyConfig { /// /// * If the secret is configured to be new, it is generated and the corresponding keypair is /// returned. - pub fn into_keypair(self) -> io::Result { + pub fn into_keypair(self) -> io::Result { use NodeKeyConfig::*; match self { - Ed25519(Secret::New) => Ok(Keypair::generate_ed25519()), + Ed25519(Secret::New) => Ok(ed25519::Keypair::generate()), Ed25519(Secret::Input(k)) => Ok(ed25519::Keypair::from(k).into()), @@ -367,8 +364,7 @@ impl NodeKeyConfig { ed25519::SecretKey::generate, |b| b.as_ref().to_vec(), ) - .map(ed25519::Keypair::from) - .map(Keypair::from), + .map(ed25519::Keypair::from), } } } From ce321a952befa7f34aab3a4463b68517ba5f8fcb Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Wed, 24 Apr 2024 15:38:28 +0300 Subject: [PATCH 09/24] Convert substrate-specific types for libp2p backend --- substrate/client/network/src/service.rs | 63 ++++++++++++++++--------- 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/substrate/client/network/src/service.rs b/substrate/client/network/src/service.rs index 807c5b5a80af..e9ed08d119b3 100644 --- a/substrate/client/network/src/service.rs +++ b/substrate/client/network/src/service.rs @@ -55,24 +55,26 @@ use crate::{ }, transport, types::ProtocolName, - Multiaddr, NotificationService, PeerId, ReputationChange, + NotificationService, ReputationChange, }; use codec::DecodeAll; use either::Either; use futures::{channel::oneshot, prelude::*}; +use libp2p::identity::ed25519; #[allow(deprecated)] use libp2p::{ connection_limits::Exceeded, core::{upgrade, ConnectedPoint, Endpoint}, identify::Info as IdentifyInfo, kad::record::Key as KademliaKey, - multiaddr, + multiaddr::{self, Multiaddr}, ping::Failure as PingFailure, swarm::{ AddressScore, ConnectionError, ConnectionId, ConnectionLimits, DialError, Executor, ListenError, NetworkBehaviour, Swarm, SwarmBuilder, SwarmEvent, THandlerErr, }, + PeerId, }; use log::{debug, error, info, trace, warn}; use metrics::{Histogram, MetricSources, Metrics}; @@ -269,6 +271,15 @@ where let local_public = local_identity.public(); let local_peer_id = local_public.to_peer_id(); + // Convert to libp2p types. + let local_identity: ed25519::Keypair = local_identity.into(); + let local_public: ed25519::PublicKey = local_public.into(); + let local_peer_id: PeerId = local_peer_id.into(); + let listen_addresses: Vec = + network_config.listen_addresses.iter().cloned().map(Into::into).collect(); + let public_addresses: Vec = + network_config.public_addresses.iter().cloned().map(Into::into).collect(); + network_config.boot_nodes = network_config .boot_nodes .into_iter() @@ -294,25 +305,33 @@ where // Ensure the listen addresses are consistent with the transport. ensure_addresses_consistent_with_transport( - network_config.listen_addresses.iter(), + listen_addresses.iter(), &network_config.transport, )?; ensure_addresses_consistent_with_transport( - network_config.boot_nodes.iter().map(|x| &x.multiaddr), + network_config.boot_nodes.iter().map(|x| &x.multiaddr.into()), &network_config.transport, )?; ensure_addresses_consistent_with_transport( - network_config.default_peers_set.reserved_nodes.iter().map(|x| &x.multiaddr), + network_config + .default_peers_set + .reserved_nodes + .iter() + .map(|x| &x.multiaddr.into()), &network_config.transport, )?; for notification_protocol in ¬ification_protocols { ensure_addresses_consistent_with_transport( - notification_protocol.set_config().reserved_nodes.iter().map(|x| &x.multiaddr), + notification_protocol + .set_config() + .reserved_nodes + .iter() + .map(|x| &x.multiaddr.into()), &network_config.transport, )?; } ensure_addresses_consistent_with_transport( - network_config.public_addresses.iter(), + public_addresses.iter(), &network_config.transport, )?; @@ -370,7 +389,7 @@ where }; transport::build_transport( - local_identity.clone(), + local_identity.clone().into(), config_mem, network_config.yamux_window_size, yamux_maximum_buffer_size, @@ -462,7 +481,7 @@ where .find(|o| o.peer_id != bootnode.peer_id) { Err(Error::DuplicateBootnode { - address: bootnode.multiaddr.clone(), + address: bootnode.multiaddr.clone().into(), first_id: bootnode.peer_id.into(), second_id: other.peer_id.into(), }) @@ -478,7 +497,7 @@ where boot_node_ids .entry(bootnode.peer_id.into()) .or_default() - .push(bootnode.multiaddr.clone()); + .push(bootnode.multiaddr.clone().into()); } let boot_node_ids = Arc::new(boot_node_ids); @@ -502,11 +521,11 @@ where format!("{} ({})", network_config.client_version, network_config.node_name); let discovery_config = { - let mut config = DiscoveryConfig::new(local_public.to_peer_id()); + let mut config = DiscoveryConfig::new(local_peer_id); config.with_permanent_addresses( known_addresses .iter() - .map(|(peer, address)| (peer.into(), address.clone())) + .map(|(peer, address)| (peer.into(), address.clone().into())) .collect::>(), ); config.discovery_limit(u64::from(network_config.default_peers_set.out_peers) + 15); @@ -544,7 +563,7 @@ where let result = Behaviour::new( protocol, user_agent, - local_public, + local_public.into(), discovery_config, request_response_protocols, Arc::clone(&peer_store_handle), @@ -604,14 +623,14 @@ where }; // Listen on multiaddresses. - for addr in &network_config.listen_addresses { + for addr in &listen_addresses { if let Err(err) = Swarm::>::listen_on(&mut swarm, addr.clone()) { warn!(target: "sub-libp2p", "Can't listen on {} because: {:?}", addr, err) } } // Add external addresses. - for addr in &network_config.public_addresses { + for addr in &public_addresses { Swarm::>::add_external_address( &mut swarm, addr.clone(), @@ -619,15 +638,15 @@ where ); } - let listen_addresses = Arc::new(Mutex::new(HashSet::new())); + let listen_addresses_set = Arc::new(Mutex::new(HashSet::new())); let service = Arc::new(NetworkService { bandwidth, external_addresses, - listen_addresses: listen_addresses.clone(), + listen_addresses: listen_addresses_set.clone(), num_connected: num_connected.clone(), local_peer_id, - local_identity, + local_identity: local_identity.into(), to_worker, notification_protocol_ids, protocol_handles, @@ -638,7 +657,7 @@ where }); Ok(NetworkWorker { - listen_addresses, + listen_addresses: listen_addresses_set, num_connected, network_service: swarm, service, @@ -1034,7 +1053,7 @@ where let _ = self.to_worker.unbounded_send(ServiceToWorkerMsg::AddKnownAddress( peer.peer_id.into(), - peer.multiaddr, + peer.multiaddr.into(), )); self.sync_protocol_handle.add_reserved_peer(peer.peer_id.into()); @@ -1723,8 +1742,8 @@ where { if let DialError::WrongPeerId { obtained, endpoint } = &error { if let ConnectedPoint::Dialer { address, role_override: _ } = endpoint { - let address_without_peer_id = parse_addr(address.clone()) - .map_or_else(|_| address.clone(), |r| r.1); + let address_without_peer_id = parse_addr(address.clone().into()) + .map_or_else(|_| address.clone(), |r| r.1.into()); // Only report for address of boot node that was added at startup of // the node and not for any address that the node learned of the From a0373ae7ab51359e9272a3fa40c1b235715257cb Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Wed, 24 Apr 2024 16:20:37 +0300 Subject: [PATCH 10/24] Convert substrate-specific types for litep2p backend --- substrate/client/network/src/config.rs | 14 +++----- substrate/client/network/src/error.rs | 2 +- .../client/network/src/litep2p/discovery.rs | 9 +++-- substrate/client/network/src/litep2p/mod.rs | 35 +++++++++---------- .../client/network/src/litep2p/service.rs | 14 +++++--- substrate/client/network/src/service.rs | 28 ++++++--------- 6 files changed, 47 insertions(+), 55 deletions(-) diff --git a/substrate/client/network/src/config.rs b/substrate/client/network/src/config.rs index 6e76cbce7109..ea69fef41681 100644 --- a/substrate/client/network/src/config.rs +++ b/substrate/client/network/src/config.rs @@ -844,11 +844,11 @@ impl> FullNetworkConfig /// Verify addresses are consistent with enabled transports. pub fn sanity_check_addresses(&self) -> Result<(), crate::error::Error> { ensure_addresses_consistent_with_transport( - self.network_config.listen_addresses.iter().map(|addr| &addr.to_owned().into()), + self.network_config.listen_addresses.iter(), &self.network_config.transport, )?; ensure_addresses_consistent_with_transport( - self.network_config.boot_nodes.iter().map(|x| &x.multiaddr.into()), + self.network_config.boot_nodes.iter().map(|x| &x.multiaddr), &self.network_config.transport, )?; ensure_addresses_consistent_with_transport( @@ -856,22 +856,18 @@ impl> FullNetworkConfig .default_peers_set .reserved_nodes .iter() - .map(|x| &x.multiaddr.into()), + .map(|x| &x.multiaddr), &self.network_config.transport, )?; for notification_protocol in &self.notification_protocols { ensure_addresses_consistent_with_transport( - notification_protocol - .set_config() - .reserved_nodes - .iter() - .map(|x| &x.multiaddr.into()), + notification_protocol.set_config().reserved_nodes.iter().map(|x| &x.multiaddr), &self.network_config.transport, )?; } ensure_addresses_consistent_with_transport( - self.network_config.public_addresses.iter().map(|addr| &addr.to_owned().into()), + self.network_config.public_addresses.iter(), &self.network_config.transport, )?; diff --git a/substrate/client/network/src/error.rs b/substrate/client/network/src/error.rs index b776e3e1ad9d..376b8461be4e 100644 --- a/substrate/client/network/src/error.rs +++ b/substrate/client/network/src/error.rs @@ -20,7 +20,7 @@ use crate::{config::TransportConfig, types::ProtocolName}; -use libp2p::{Multiaddr, PeerId}; +use sc_network_types::{multiaddr::Multiaddr, PeerId}; use std::fmt; diff --git a/substrate/client/network/src/litep2p/discovery.rs b/substrate/client/network/src/litep2p/discovery.rs index 27f4d5473722..bda703def775 100644 --- a/substrate/client/network/src/litep2p/discovery.rs +++ b/substrate/client/network/src/litep2p/discovery.rs @@ -227,7 +227,7 @@ impl Discovery { let (identify_config, identify_event_stream) = IdentifyConfig::new( "/substrate/1.0".to_string(), Some(user_agent), - config.public_addresses.clone(), + config.public_addresses.clone().into_iter().map(Into::into).collect(), ); let (mdns_config, mdns_event_stream) = match config.transport { @@ -266,7 +266,7 @@ impl Discovery { duration_to_next_find_query: Duration::from_secs(1), address_confirmations: LruMap::new(ByLength::new(8)), allow_non_global_addresses: config.allow_non_globals_in_dht, - public_addresses: config.public_addresses.iter().cloned().collect(), + public_addresses: config.public_addresses.iter().cloned().map(Into::into).collect(), next_kad_query: Some(Delay::new(KADEMLIA_QUERY_INTERVAL)), local_protocols: HashSet::from_iter([ kademlia_protocol_name(genesis_hash, fork_id), @@ -462,7 +462,10 @@ impl Stream for Discovery { "`GET_RECORD` succeeded for {query_id:?}: {record:?}", ); - return Poll::Ready(Some(DiscoveryEvent::GetRecordSuccess { query_id, record })); + return Poll::Ready(Some(DiscoveryEvent::GetRecordSuccess { + query_id, + record: record.record, + })); }, Poll::Ready(Some(KademliaEvent::PutRecordSucess { query_id, key: _ })) => return Poll::Ready(Some(DiscoveryEvent::PutRecordSuccess { query_id })), diff --git a/substrate/client/network/src/litep2p/mod.rs b/substrate/client/network/src/litep2p/mod.rs index 1137c73b56db..0c98e1350566 100644 --- a/substrate/client/network/src/litep2p/mod.rs +++ b/substrate/client/network/src/litep2p/mod.rs @@ -54,7 +54,7 @@ use futures::StreamExt; use libp2p::kad::RecordKey; use litep2p::{ config::ConfigBuilder, - crypto::ed25519::{Keypair, SecretKey}, + crypto::ed25519::Keypair, executor::Executor, protocol::{ libp2p::{bitswap::Config as BitswapConfig, kademlia::QueryId}, @@ -81,7 +81,7 @@ use std::{ collections::{hash_map::Entry, HashMap, HashSet}, fs, future::Future, - io, iter, + iter, pin::Pin, sync::{ atomic::{AtomicUsize, Ordering}, @@ -200,12 +200,12 @@ impl Litep2pNetworkBackend { Protocol::Ip4(_), ) => match address.iter().find(|protocol| std::matches!(protocol, Protocol::P2p(_))) { - Some(Protocol::P2p(multihash)) => PeerId::from_multihash(multihash) + Some(Protocol::P2p(multihash)) => PeerId::from_multihash(multihash.into()) .map_or(None, |peer| Some((peer, Some(address)))), _ => None, }, Some(Protocol::P2p(multihash)) => - PeerId::from_multihash(multihash).map_or(None, |peer| Some((peer, None))), + PeerId::from_multihash(multihash.into()).map_or(None, |peer| Some((peer, None))), _ => None, }) .fold(HashMap::new(), |mut acc, (peer, maybe_address)| { @@ -244,16 +244,9 @@ impl Litep2pNetworkBackend { impl Litep2pNetworkBackend { /// Get `litep2p` keypair from `NodeKeyConfig`. fn get_keypair(node_key: &NodeKeyConfig) -> Result<(Keypair, litep2p::PeerId), Error> { - let secret = libp2p::identity::Keypair::try_into_ed25519(node_key.clone().into_keypair()?) - .map_err(|error| { - log::error!(target: LOG_TARGET, "failed to convert to ed25519: {error:?}"); - Error::Io(io::ErrorKind::InvalidInput.into()) - })? - .secret(); - - let mut secret = secret.as_ref().iter().cloned().collect::>(); - let secret = SecretKey::from_bytes(&mut secret) - .map_err(|_| Error::Io(io::ErrorKind::InvalidInput.into()))?; + let secret: litep2p::crypto::ed25519::SecretKey = + node_key.clone().into_keypair()?.secret().into(); + let local_identity = Keypair::from(secret); let local_public = local_identity.public(); let local_peer_id = local_public.to_peer_id(); @@ -327,6 +320,8 @@ impl Litep2pNetworkBackend { .listen_addresses .iter() .filter_map(|address| { + use sc_network_types::multiaddr::Protocol; + let mut iter = address.iter(); match iter.next() { @@ -367,12 +362,12 @@ impl Litep2pNetworkBackend { config_builder .with_websocket(WebSocketTransportConfig { - listen_addresses: websocket.into_iter().flatten().collect(), + listen_addresses: websocket.into_iter().flatten().map(Into::into).collect(), yamux_config: yamux_config.clone(), ..Default::default() }) .with_tcp(TcpTransportConfig { - listen_addresses: tcp.into_iter().flatten().collect(), + listen_addresses: tcp.into_iter().flatten().map(Into::into).collect(), yamux_config, ..Default::default() }) @@ -522,6 +517,8 @@ impl NetworkBackend for Litep2pNetworkBac // collect known addresses let known_addresses: HashMap> = known_addresses.into_iter().fold(HashMap::new(), |mut acc, (peer, address)| { + use sc_network_types::multiaddr::Protocol; + let address = match address.iter().last() { Some(Protocol::Ws(_) | Protocol::Wss(_) | Protocol::Tcp(_)) => address.with(Protocol::P2p(peer.into())), @@ -529,7 +526,7 @@ impl NetworkBackend for Litep2pNetworkBac _ => return acc, }; - acc.entry(peer.into()).or_default().push(address); + acc.entry(peer.into()).or_default().push(address.into()); peer_store_handle.add_known_peer(peer); acc @@ -567,7 +564,7 @@ impl NetworkBackend for Litep2pNetworkBac Litep2p::new(config_builder.build()).map_err(|error| Error::Litep2p(error))?; let external_addresses: Arc>> = Arc::new(RwLock::new( - HashSet::from_iter(network_config.public_addresses.iter().cloned()), + HashSet::from_iter(network_config.public_addresses.iter().cloned().map(Into::into)), )); litep2p.listen_addresses().for_each(|address| { log::debug!(target: LOG_TARGET, "listening on: {address}"); @@ -724,7 +721,7 @@ impl NetworkBackend for Litep2pNetworkBac } NetworkServiceCommand::AddKnownAddress { peer, mut address } => { if !address.iter().any(|protocol| std::matches!(protocol, Protocol::P2p(_))) { - address.push(Protocol::P2p(peer.into())); + address.push(Protocol::P2p(litep2p::PeerId::from(peer).into())); } if self.litep2p.add_known_address(peer.into(), iter::once(address.clone())) == 0usize { diff --git a/substrate/client/network/src/litep2p/service.rs b/substrate/client/network/src/litep2p/service.rs index 86f11aa6e142..1d1d0c6ae96f 100644 --- a/substrate/client/network/src/litep2p/service.rs +++ b/substrate/client/network/src/litep2p/service.rs @@ -24,7 +24,6 @@ use crate::{ notification::{config::ProtocolControlHandle, peerset::PeersetCommand}, request_response::OutboundRequest, }, - multiaddr::Protocol, network_state::NetworkState, peer_store::PeerStoreProvider, service::out_events, @@ -35,8 +34,11 @@ use crate::{ use codec::DecodeAll; use futures::{channel::oneshot, stream::BoxStream}; -use libp2p::{identity::SigningError, kad::record::Key as KademliaKey, Multiaddr}; -use litep2p::crypto::ed25519::Keypair; +use libp2p::{identity::SigningError, kad::record::Key as KademliaKey}; +use litep2p::{ + crypto::ed25519::Keypair, + types::multiaddr::{Multiaddr, Protocol}, +}; use parking_lot::RwLock; use sc_network_common::{ @@ -273,7 +275,9 @@ impl NetworkPeers for Litep2pNetworkService { protocol: self.block_announce_protocol.clone(), peers: peers .into_iter() - .map(|peer| Multiaddr::empty().with(Protocol::P2p(peer.into()))) + .map(|peer| { + Multiaddr::empty().with(Protocol::P2p(litep2p::PeerId::from(peer).into())) + }) .collect(), }); } @@ -322,7 +326,7 @@ impl NetworkPeers for Litep2pNetworkService { fn add_reserved_peer(&self, peer: MultiaddrWithPeerId) -> Result<(), String> { let _ = self.cmd_tx.unbounded_send(NetworkServiceCommand::AddPeersToReservedSet { protocol: self.block_announce_protocol.clone(), - peers: HashSet::from_iter([peer.concat()]), + peers: HashSet::from_iter([peer.concat().into()]), }); Ok(()) diff --git a/substrate/client/network/src/service.rs b/substrate/client/network/src/service.rs index e9ed08d119b3..e3acd2e5b46a 100644 --- a/substrate/client/network/src/service.rs +++ b/substrate/client/network/src/service.rs @@ -305,33 +305,25 @@ where // Ensure the listen addresses are consistent with the transport. ensure_addresses_consistent_with_transport( - listen_addresses.iter(), + network_config.listen_addresses.iter(), &network_config.transport, )?; ensure_addresses_consistent_with_transport( - network_config.boot_nodes.iter().map(|x| &x.multiaddr.into()), + network_config.boot_nodes.iter().map(|x| &x.multiaddr), &network_config.transport, )?; ensure_addresses_consistent_with_transport( - network_config - .default_peers_set - .reserved_nodes - .iter() - .map(|x| &x.multiaddr.into()), + network_config.default_peers_set.reserved_nodes.iter().map(|x| &x.multiaddr), &network_config.transport, )?; for notification_protocol in ¬ification_protocols { ensure_addresses_consistent_with_transport( - notification_protocol - .set_config() - .reserved_nodes - .iter() - .map(|x| &x.multiaddr.into()), + notification_protocol.set_config().reserved_nodes.iter().map(|x| &x.multiaddr), &network_config.transport, )?; } ensure_addresses_consistent_with_transport( - public_addresses.iter(), + network_config.public_addresses.iter(), &network_config.transport, )?; @@ -1879,14 +1871,14 @@ where } pub(crate) fn ensure_addresses_consistent_with_transport<'a>( - addresses: impl Iterator, + addresses: impl Iterator, transport: &TransportConfig, ) -> Result<(), Error> { + use sc_network_types::multiaddr::Protocol; + if matches!(transport, TransportConfig::MemoryOnly) { let addresses: Vec<_> = addresses - .filter(|x| { - x.iter().any(|y| !matches!(y, libp2p::core::multiaddr::Protocol::Memory(_))) - }) + .filter(|x| x.iter().any(|y| !matches!(y, Protocol::Memory(_)))) .cloned() .collect(); @@ -1898,7 +1890,7 @@ pub(crate) fn ensure_addresses_consistent_with_transport<'a>( } } else { let addresses: Vec<_> = addresses - .filter(|x| x.iter().any(|y| matches!(y, libp2p::core::multiaddr::Protocol::Memory(_)))) + .filter(|x| x.iter().any(|y| matches!(y, Protocol::Memory(_)))) .cloned() .collect(); From 2bb54482647eba20817f620c614cabf3eedcc3bf Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Wed, 24 Apr 2024 17:20:38 +0300 Subject: [PATCH 11/24] Cleaner separation between backend-specific types --- .../client/mixnet/src/sync_with_runtime.rs | 7 +++-- substrate/client/network/src/lib.rs | 6 +++- .../client/network/src/litep2p/discovery.rs | 3 +- substrate/client/network/src/litep2p/mod.rs | 14 ++++++---- .../client/network/src/litep2p/service.rs | 26 ++++++++--------- substrate/client/network/src/peer_store.rs | 3 +- .../src/protocol/notifications/service/mod.rs | 2 +- .../client/network/src/protocol_controller.rs | 6 ++-- substrate/client/network/src/service.rs | 28 +++++++++++-------- .../client/network/src/service/traits.rs | 4 +-- .../client/network/sync/src/service/mock.rs | 4 +-- .../client/network/types/src/multiaddr.rs | 3 ++ 12 files changed, 59 insertions(+), 47 deletions(-) diff --git a/substrate/client/mixnet/src/sync_with_runtime.rs b/substrate/client/mixnet/src/sync_with_runtime.rs index 46c2334ceb46..0071ce13b33a 100644 --- a/substrate/client/mixnet/src/sync_with_runtime.rs +++ b/substrate/client/mixnet/src/sync_with_runtime.rs @@ -25,8 +25,10 @@ use mixnet::core::{ Mixnet, Mixnode as CoreMixnode, MixnodesErr as CoreMixnodesErr, RelSessionIndex, SessionPhase as CoreSessionPhase, SessionStatus as CoreSessionStatus, }; -use multiaddr::{multiaddr, Multiaddr, Protocol}; -use sc_network_types::PeerId; +use sc_network_types::{ + multiaddr::{multiaddr, Multiaddr, Protocol}, + PeerId, +}; use sp_api::{ApiError, ApiRef}; use sp_mixnet::{ runtime_api::MixnetApi, @@ -196,7 +198,6 @@ where #[cfg(test)] mod tests { use super::*; - use multiaddr::multiaddr; #[test] fn fixup_empty_external_addresses() { diff --git a/substrate/client/network/src/lib.rs b/substrate/client/network/src/lib.rs index 8f479825c8d7..99a972f914e2 100644 --- a/substrate/client/network/src/lib.rs +++ b/substrate/client/network/src/lib.rs @@ -272,6 +272,10 @@ pub use sc_network_common::{ role::{ObservedRole, Roles}, types::ReputationChange, }; +pub use sc_network_types::{ + multiaddr::{self, Multiaddr}, + PeerId, +}; pub use service::{ metrics::NotificationMetrics, signature::Signature, @@ -285,7 +289,7 @@ pub use service::{ DecodingError, Keypair, NetworkService, NetworkWorker, NotificationSender, OutboundFailure, PublicKey, }; -pub use types::{multiaddr, Multiaddr, PeerId, ProtocolName}; +pub use types::ProtocolName; /// The maximum allowed number of established connections per peer. /// diff --git a/substrate/client/network/src/litep2p/discovery.rs b/substrate/client/network/src/litep2p/discovery.rs index bda703def775..b10d11f750b2 100644 --- a/substrate/client/network/src/litep2p/discovery.rs +++ b/substrate/client/network/src/litep2p/discovery.rs @@ -20,9 +20,7 @@ use crate::{ config::{NetworkConfiguration, ProtocolId}, - multiaddr::Protocol, peer_store::PeerStoreProvider, - Multiaddr, }; use array_bytes::bytes2hex; @@ -42,6 +40,7 @@ use litep2p::{ }, mdns::{Config as MdnsConfig, MdnsEvent}, }, + types::multiaddr::{Multiaddr, Protocol}, PeerId, ProtocolName, }; use parking_lot::RwLock; diff --git a/substrate/client/network/src/litep2p/mod.rs b/substrate/client/network/src/litep2p/mod.rs index 0c98e1350566..67085a81a5c8 100644 --- a/substrate/client/network/src/litep2p/mod.rs +++ b/substrate/client/network/src/litep2p/mod.rs @@ -38,7 +38,6 @@ use crate::{ request_response::{RequestResponseConfig, RequestResponseProtocol}, }, }, - multiaddr::{Multiaddr, Protocol}, peer_store::PeerStoreProvider, protocol, service::{ @@ -64,7 +63,10 @@ use litep2p::{ tcp::config::Config as TcpTransportConfig, websocket::config::Config as WebSocketTransportConfig, Endpoint, }, - types::ConnectionId, + types::{ + multiaddr::{Multiaddr, Protocol}, + ConnectionId, + }, Error as Litep2pError, Litep2p, Litep2pEvent, ProtocolName as Litep2pProtocolName, }; use parking_lot::RwLock; @@ -710,7 +712,7 @@ impl NetworkBackend for Litep2pNetworkBac protocol, peers, } => { - let peers = self.add_addresses(peers.into_iter()); + let peers = self.add_addresses(peers.into_iter().map(Into::into)); match self.peerset_handles.get(&protocol) { Some(handle) => { @@ -719,7 +721,9 @@ impl NetworkBackend for Litep2pNetworkBac None => log::warn!(target: LOG_TARGET, "protocol {protocol} doens't exist"), }; } - NetworkServiceCommand::AddKnownAddress { peer, mut address } => { + NetworkServiceCommand::AddKnownAddress { peer, address } => { + let mut address: Multiaddr = address.into(); + if !address.iter().any(|protocol| std::matches!(protocol, Protocol::P2p(_))) { address.push(Protocol::P2p(litep2p::PeerId::from(peer).into())); } @@ -732,7 +736,7 @@ impl NetworkBackend for Litep2pNetworkBac } }, NetworkServiceCommand::SetReservedPeers { protocol, peers } => { - let peers = self.add_addresses(peers.into_iter()); + let peers = self.add_addresses(peers.into_iter().map(Into::into)); match self.peerset_handles.get(&protocol) { Some(handle) => { diff --git a/substrate/client/network/src/litep2p/service.rs b/substrate/client/network/src/litep2p/service.rs index 1d1d0c6ae96f..09b869abdf5f 100644 --- a/substrate/client/network/src/litep2p/service.rs +++ b/substrate/client/network/src/litep2p/service.rs @@ -35,17 +35,17 @@ use crate::{ use codec::DecodeAll; use futures::{channel::oneshot, stream::BoxStream}; use libp2p::{identity::SigningError, kad::record::Key as KademliaKey}; -use litep2p::{ - crypto::ed25519::Keypair, - types::multiaddr::{Multiaddr, Protocol}, -}; +use litep2p::{crypto::ed25519::Keypair, types::multiaddr::Multiaddr as LiteP2pMultiaddr}; use parking_lot::RwLock; use sc_network_common::{ role::{ObservedRole, Roles}, types::ReputationChange, }; -use sc_network_types::PeerId; +use sc_network_types::{ + multiaddr::{Multiaddr, Protocol}, + PeerId, +}; use sc_utils::mpsc::TracingUnboundedSender; use std::{ @@ -167,10 +167,10 @@ pub struct Litep2pNetworkService { request_response_protocols: HashMap>, /// Listen addresses. - listen_addresses: Arc>>, + listen_addresses: Arc>>, /// External addresses. - external_addresses: Arc>>, + external_addresses: Arc>>, } impl Litep2pNetworkService { @@ -183,8 +183,8 @@ impl Litep2pNetworkService { peerset_handles: HashMap, block_announce_protocol: ProtocolName, request_response_protocols: HashMap>, - listen_addresses: Arc>>, - external_addresses: Arc>>, + listen_addresses: Arc>>, + external_addresses: Arc>>, ) -> Self { Self { local_peer_id, @@ -275,9 +275,7 @@ impl NetworkPeers for Litep2pNetworkService { protocol: self.block_announce_protocol.clone(), peers: peers .into_iter() - .map(|peer| { - Multiaddr::empty().with(Protocol::P2p(litep2p::PeerId::from(peer).into())) - }) + .map(|peer| Multiaddr::empty().with(Protocol::P2p(peer.into()))) .collect(), }); } @@ -419,11 +417,11 @@ impl NetworkEventStream for Litep2pNetworkService { impl NetworkStateInfo for Litep2pNetworkService { fn external_addresses(&self) -> Vec { - self.external_addresses.read().iter().cloned().collect() + self.external_addresses.read().iter().cloned().map(Into::into).collect() } fn listen_addresses(&self) -> Vec { - self.listen_addresses.read().iter().cloned().collect() + self.listen_addresses.read().iter().cloned().map(Into::into).collect() } fn local_peer_id(&self) -> PeerId { diff --git a/substrate/client/network/src/peer_store.rs b/substrate/client/network/src/peer_store.rs index a4c739f1448e..987405500dc9 100644 --- a/substrate/client/network/src/peer_store.rs +++ b/substrate/client/network/src/peer_store.rs @@ -19,8 +19,9 @@ //! [`PeerStore`] manages peer reputations and provides connection candidates to //! [`crate::protocol_controller::ProtocolController`]. -use crate::{service::traits::PeerStore as PeerStoreT, PeerId}; +use crate::service::traits::PeerStore as PeerStoreT; +use libp2p::PeerId; use log::trace; use parking_lot::Mutex; use partial_sort::PartialSort; diff --git a/substrate/client/network/src/protocol/notifications/service/mod.rs b/substrate/client/network/src/protocol/notifications/service/mod.rs index 15d289d170ee..4f6d32ae3b35 100644 --- a/substrate/client/network/src/protocol/notifications/service/mod.rs +++ b/substrate/client/network/src/protocol/notifications/service/mod.rs @@ -28,13 +28,13 @@ use crate::{ }, }, types::ProtocolName, - PeerId, }; use futures::{ stream::{FuturesUnordered, Stream}, StreamExt, }; +use libp2p::PeerId; use parking_lot::Mutex; use tokio::sync::{mpsc, oneshot}; use tokio_stream::wrappers::ReceiverStream; diff --git a/substrate/client/network/src/protocol_controller.rs b/substrate/client/network/src/protocol_controller.rs index 2c3e6744e328..e78ea9339f46 100644 --- a/substrate/client/network/src/protocol_controller.rs +++ b/substrate/client/network/src/protocol_controller.rs @@ -41,12 +41,10 @@ //! Even though this does not guarantee that `ProtocolController` and `Notifications` have the same //! view of the peers' states at any given moment, the eventual consistency is maintained. -use crate::{ - peer_store::{PeerStoreProvider, ProtocolHandle as ProtocolHandleT}, - PeerId, -}; +use crate::peer_store::{PeerStoreProvider, ProtocolHandle as ProtocolHandleT}; use futures::{channel::oneshot, future::Either, FutureExt, StreamExt}; +use libp2p::PeerId; use log::{debug, error, trace, warn}; use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; use sp_arithmetic::traits::SaturatedConversion; diff --git a/substrate/client/network/src/service.rs b/substrate/client/network/src/service.rs index e3acd2e5b46a..1aaa63191a81 100644 --- a/substrate/client/network/src/service.rs +++ b/substrate/client/network/src/service.rs @@ -891,13 +891,13 @@ where H: ExHashT, { /// Returns the local external addresses. - fn external_addresses(&self) -> Vec { - self.external_addresses.lock().iter().cloned().collect() + fn external_addresses(&self) -> Vec { + self.external_addresses.lock().iter().cloned().map(Into::into).collect() } /// Returns the listener addresses (without trailing `/p2p/` with our `PeerId`). - fn listen_addresses(&self) -> Vec { - self.listen_addresses.lock().iter().cloned().collect() + fn listen_addresses(&self) -> Vec { + self.listen_addresses.lock().iter().cloned().map(Into::into).collect() } /// Returns the local Peer ID. @@ -1009,10 +1009,14 @@ where self.sync_protocol_handle.set_reserved_only(reserved_only); } - fn add_known_address(&self, peer_id: sc_network_types::PeerId, addr: Multiaddr) { + fn add_known_address( + &self, + peer_id: sc_network_types::PeerId, + addr: sc_network_types::multiaddr::Multiaddr, + ) { let _ = self .to_worker - .unbounded_send(ServiceToWorkerMsg::AddKnownAddress(peer_id.into(), addr)); + .unbounded_send(ServiceToWorkerMsg::AddKnownAddress(peer_id.into(), addr.into())); } fn report_peer(&self, peer_id: sc_network_types::PeerId, cost_benefit: ReputationChange) { @@ -1059,16 +1063,16 @@ where fn set_reserved_peers( &self, protocol: ProtocolName, - peers: HashSet, + peers: HashSet, ) -> Result<(), String> { let Some(set_id) = self.notification_protocol_ids.get(&protocol) else { return Err(format!("Cannot set reserved peers for unknown protocol: {}", protocol)) }; + let peers: HashSet = peers.into_iter().map(Into::into).collect(); let peers_addrs = self.split_multiaddr_and_peer_id(peers)?; - let mut peers: HashSet = - HashSet::with_capacity(peers_addrs.len()); + let mut peers: HashSet = HashSet::with_capacity(peers_addrs.len()); for (peer_id, addr) in peers_addrs.into_iter() { // Make sure the local peer ID is never added to the PSM. @@ -1085,8 +1089,7 @@ where } } - self.protocol_handles[usize::from(*set_id)] - .set_reserved_peers(peers.iter().map(|peer| (*peer).into()).collect()); + self.protocol_handles[usize::from(*set_id)].set_reserved_peers(peers); Ok(()) } @@ -1094,7 +1097,7 @@ where fn add_peers_to_reserved_set( &self, protocol: ProtocolName, - peers: HashSet, + peers: HashSet, ) -> Result<(), String> { let Some(set_id) = self.notification_protocol_ids.get(&protocol) else { return Err(format!( @@ -1103,6 +1106,7 @@ where )) }; + let peers: HashSet = peers.into_iter().map(Into::into).collect(); let peers = self.split_multiaddr_and_peer_id(peers)?; for (peer_id, addr) in peers.into_iter() { diff --git a/substrate/client/network/src/service/traits.rs b/substrate/client/network/src/service/traits.rs index 9bbaeb1026f9..d1ea9a2ed568 100644 --- a/substrate/client/network/src/service/traits.rs +++ b/substrate/client/network/src/service/traits.rs @@ -28,7 +28,7 @@ use crate::{ request_responses::{IfDisconnected, RequestFailure}, service::{metrics::NotificationMetrics, signature::Signature, PeerStoreProvider}, types::ProtocolName, - Multiaddr, ReputationChange, + ReputationChange, }; use futures::{channel::oneshot, Stream}; @@ -36,7 +36,7 @@ use prometheus_endpoint::Registry; use sc_client_api::BlockBackend; use sc_network_common::{role::ObservedRole, ExHashT}; -use sc_network_types::PeerId; +use sc_network_types::{multiaddr::Multiaddr, PeerId}; use sp_runtime::traits::Block as BlockT; use std::{collections::HashSet, fmt::Debug, future::Future, pin::Pin, sync::Arc, time::Duration}; diff --git a/substrate/client/network/sync/src/service/mock.rs b/substrate/client/network/sync/src/service/mock.rs index 2e7e12af53d5..141edc7c8841 100644 --- a/substrate/client/network/sync/src/service/mock.rs +++ b/substrate/client/network/sync/src/service/mock.rs @@ -23,10 +23,10 @@ use sc_network::{ config::MultiaddrWithPeerId, request_responses::{IfDisconnected, RequestFailure}, types::ProtocolName, - Multiaddr, NetworkPeers, NetworkRequest, NetworkSyncForkRequest, ReputationChange, + NetworkPeers, NetworkRequest, NetworkSyncForkRequest, ReputationChange, }; use sc_network_common::role::ObservedRole; -use sc_network_types::PeerId; +use sc_network_types::{multiaddr::Multiaddr, PeerId}; use sp_runtime::traits::{Block as BlockT, NumberFor}; use std::collections::HashSet; diff --git a/substrate/client/network/types/src/multiaddr.rs b/substrate/client/network/types/src/multiaddr.rs index dd43401a6126..b928d353c484 100644 --- a/substrate/client/network/types/src/multiaddr.rs +++ b/substrate/client/network/types/src/multiaddr.rs @@ -27,6 +27,9 @@ use std::{ mod protocol; pub use protocol::Protocol; +// Re-export the macro under shorter name under `multiaddr`. +pub use crate::build_multiaddr as multiaddr; + /// [`Multiaddr`] type used in Substrate. Converted to libp2p's `Multiaddr` /// or litep2p's `Multiaddr` when passed to the corresponding network backend. From bd7df2ea225bd1b88fe207b3522d314926a261a3 Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Wed, 24 Apr 2024 18:00:34 +0300 Subject: [PATCH 12/24] Make authority-discovery use substrate-specific types --- .../client/authority-discovery/src/error.rs | 4 +- .../client/authority-discovery/src/worker.rs | 6 ++- .../client/network/types/src/multiaddr.rs | 39 ++++++++++++++++--- .../client/network/types/src/multihash.rs | 3 +- 4 files changed, 40 insertions(+), 12 deletions(-) diff --git a/substrate/client/authority-discovery/src/error.rs b/substrate/client/authority-discovery/src/error.rs index 6f791237c2f2..d2c567d77afc 100644 --- a/substrate/client/authority-discovery/src/error.rs +++ b/substrate/client/authority-discovery/src/error.rs @@ -35,7 +35,7 @@ pub enum Error { VerifyingDhtPayload, #[error("Failed to hash the authority id to be used as a dht key.")] - HashingAuthorityId(#[from] sc_network::multiaddr::multihash::Error), + HashingAuthorityId(#[from] sc_network_types::multihash::Error), #[error("Failed calling into the Substrate runtime: {0}")] CallingRuntime(#[from] sp_blockchain::Error), @@ -53,7 +53,7 @@ pub enum Error { EncodingDecodingScale(#[from] codec::Error), #[error("Failed to parse a libp2p multi address.")] - ParsingMultiaddress(#[from] sc_network::multiaddr::Error), + ParsingMultiaddress(#[from] sc_network::multiaddr::ParseError), #[error("Failed to parse a libp2p key: {0}")] ParsingLibp2pIdentity(String), diff --git a/substrate/client/authority-discovery/src/worker.rs b/substrate/client/authority-discovery/src/worker.rs index 53418d2d38c4..d89083100aa3 100644 --- a/substrate/client/authority-discovery/src/worker.rs +++ b/substrate/client/authority-discovery/src/worker.rs @@ -35,7 +35,6 @@ use addr_cache::AddrCache; use codec::{Decode, Encode}; use ip_network::IpNetwork; use linked_hash_set::LinkedHashSet; -use multihash::{Code, Multihash, MultihashDigest}; use log::{debug, error, log_enabled}; use prometheus_endpoint::{register, Counter, CounterVec, Gauge, Opts, U64}; @@ -46,7 +45,10 @@ use sc_network::{ event::DhtEvent, multiaddr, KademliaKey, Multiaddr, NetworkDHTProvider, NetworkSigner, NetworkStateInfo, }; -use sc_network_types::PeerId; +use sc_network_types::{ + multihash::{Code, Multihash}, + PeerId, +}; use sp_api::{ApiError, ProvideRuntimeApi}; use sp_authority_discovery::{ AuthorityDiscoveryApi, AuthorityId, AuthorityPair, AuthoritySignature, diff --git a/substrate/client/network/types/src/multiaddr.rs b/substrate/client/network/types/src/multiaddr.rs index b928d353c484..f598583f6e3d 100644 --- a/substrate/client/network/types/src/multiaddr.rs +++ b/substrate/client/network/types/src/multiaddr.rs @@ -63,6 +63,11 @@ impl Multiaddr { pub fn iter(&self) -> Iter<'_> { self.multiaddr.iter().into() } + + /// Return a copy of this [`Multiaddr`]'s byte representation. + pub fn to_vec(&self) -> Vec { + self.multiaddr.to_vec() + } } impl Display for Multiaddr { @@ -96,31 +101,53 @@ impl From for LiteP2pMultiaddr { } } +impl TryFrom> for Multiaddr { + // TODO: extend `ParseError` variants to cover conversion from bytes. + type Error = ParseError; + + fn try_from(v: Vec) -> Result { + let multiaddr = LiteP2pMultiaddr::try_from(v)?; + Ok(Self { multiaddr }) + } +} + /// Error when parsing a [`Multiaddr`] from string. #[derive(Debug, thiserror::Error)] pub enum ParseError { + /// Less data provided than indicated by length. + #[error("less data than indicated by length")] + DataLessThanLen, /// Invalid multiaddress. #[error("invalid multiaddress")] InvalidMultiaddr, /// Invalid protocol specification. #[error("invalid protocol string")] InvalidProtocolString, - /// Unknown protocol identifier. + /// Unknown protocol string identifier. #[error("unknown protocol '{0}'")] - UnknownProtocol(String), + UnknownProtocolString(String), + /// Unknown protocol numeric id. + #[error("unknown protocol id {0}")] + UnknownProtocolId(u32), + /// Failed to decode unsigned varint. + #[error("failed to decode unsigned varint: {0}")] + InvalidUvar(Box), /// Other error emitted when parsing into the wrapped type. - /// Never generated as of multiaddr-0.17.0. #[error("multiaddr parsing error: {0}")] - Other(Box), + ParsingError(Box), } impl From for ParseError { fn from(error: LiteP2pError) -> Self { match error { + LiteP2pError::DataLessThanLen => ParseError::DataLessThanLen, LiteP2pError::InvalidMultiaddr => ParseError::InvalidMultiaddr, LiteP2pError::InvalidProtocolString => ParseError::InvalidProtocolString, - LiteP2pError::UnknownProtocolString(s) => ParseError::UnknownProtocol(s), - error @ _ => ParseError::Other(Box::new(error)), + LiteP2pError::UnknownProtocolString(s) => ParseError::UnknownProtocolString(s), + LiteP2pError::UnknownProtocolId(n) => ParseError::UnknownProtocolId(n), + LiteP2pError::InvalidUvar(e) => ParseError::InvalidUvar(Box::new(e)), + LiteP2pError::ParsingError(e) => ParseError::ParsingError(e), + error @ _ => ParseError::ParsingError(Box::new(error)), } } } diff --git a/substrate/client/network/types/src/multihash.rs b/substrate/client/network/types/src/multihash.rs index 02e69dc1166a..4b7ba87ec6ba 100644 --- a/substrate/client/network/types/src/multihash.rs +++ b/substrate/client/network/types/src/multihash.rs @@ -20,8 +20,7 @@ //! multihash used by litep2p, but it can be switched to other implementation if needed. use litep2p::types::multihash::{ - Code as LiteP2pCode, Error as LiteP2pError, Multihash as LiteP2pMultihash, - MultihashDigest as LiteP2pDigest, + Code as LiteP2pCode, Error as LiteP2pError, Multihash as LiteP2pMultihash, MultihashDigest as _, }; use std::fmt::{self, Debug}; From 7c29f747fc95accaa36f93d18dc052c813309273 Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Thu, 16 May 2024 12:40:24 +0300 Subject: [PATCH 13/24] Make telemetry use libp2p-only `Multiaddr` --- substrate/client/telemetry/src/endpoints.rs | 2 +- substrate/client/telemetry/src/lib.rs | 2 +- substrate/client/telemetry/src/node.rs | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/substrate/client/telemetry/src/endpoints.rs b/substrate/client/telemetry/src/endpoints.rs index c7a60726a565..c49b114152ae 100644 --- a/substrate/client/telemetry/src/endpoints.rs +++ b/substrate/client/telemetry/src/endpoints.rs @@ -16,7 +16,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use sc_network::{multiaddr, Multiaddr}; +use libp2p::multiaddr::{self, Multiaddr}; use serde::{Deserialize, Deserializer, Serialize}; /// List of telemetry servers we want to talk to. Contains the URL of the server, and the diff --git a/substrate/client/telemetry/src/lib.rs b/substrate/client/telemetry/src/lib.rs index f8a201e7611c..7e3a4ee86393 100644 --- a/substrate/client/telemetry/src/lib.rs +++ b/substrate/client/telemetry/src/lib.rs @@ -37,9 +37,9 @@ #![warn(missing_docs)] use futures::{channel::mpsc, prelude::*}; +use libp2p::Multiaddr; use log::{error, warn}; use parking_lot::Mutex; -use sc_network::Multiaddr; use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedReceiver, TracingUnboundedSender}; use serde::Serialize; use std::{ diff --git a/substrate/client/telemetry/src/node.rs b/substrate/client/telemetry/src/node.rs index 9b2443799d3d..0bbdbfb622ef 100644 --- a/substrate/client/telemetry/src/node.rs +++ b/substrate/client/telemetry/src/node.rs @@ -18,9 +18,8 @@ use crate::TelemetryPayload; use futures::{channel::mpsc, prelude::*}; -use libp2p::core::transport::Transport; +use libp2p::{core::transport::Transport, Multiaddr}; use rand::Rng as _; -use sc_network::Multiaddr; use std::{ fmt, mem, pin::Pin, From 2162dac6d08a7c73216f333e135951ebbea25820 Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Thu, 16 May 2024 12:48:25 +0300 Subject: [PATCH 14/24] Make `cli` use `sc_network::config::ed25519` --- substrate/client/cli/src/params/node_key_params.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/substrate/client/cli/src/params/node_key_params.rs b/substrate/client/cli/src/params/node_key_params.rs index 7058af19f1d4..0e12c7a2a2d3 100644 --- a/substrate/client/cli/src/params/node_key_params.rs +++ b/substrate/client/cli/src/params/node_key_params.rs @@ -17,7 +17,7 @@ // along with this program. If not, see . use clap::Args; -use sc_network::config::{identity::ed25519, NodeKeyConfig}; +use sc_network::config::{ed25519, NodeKeyConfig}; use sc_service::Role; use sp_core::H256; use std::{path::PathBuf, str::FromStr}; @@ -148,7 +148,7 @@ fn parse_ed25519_secret(hex: &str) -> error::Result Date: Thu, 16 May 2024 16:39:54 +0300 Subject: [PATCH 15/24] Make authority-discovery tests use proper types --- .../authority-discovery/src/worker/addr_cache.rs | 2 +- .../client/authority-discovery/src/worker/tests.rs | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/substrate/client/authority-discovery/src/worker/addr_cache.rs b/substrate/client/authority-discovery/src/worker/addr_cache.rs index 6e3b3c8af201..77cdfbd4f150 100644 --- a/substrate/client/authority-discovery/src/worker/addr_cache.rs +++ b/substrate/client/authority-discovery/src/worker/addr_cache.rs @@ -176,8 +176,8 @@ fn addresses_to_peer_ids(addresses: &HashSet) -> HashSet { mod tests { use super::*; - use multihash::{self, Multihash}; use quickcheck::{Arbitrary, Gen, QuickCheck, TestResult}; + use sc_network_types::multihash::Multihash; use sp_authority_discovery::{AuthorityId, AuthorityPair}; use sp_core::crypto::Pair; diff --git a/substrate/client/authority-discovery/src/worker/tests.rs b/substrate/client/authority-discovery/src/worker/tests.rs index caeac56c5407..70107c89a851 100644 --- a/substrate/client/authority-discovery/src/worker/tests.rs +++ b/substrate/client/authority-discovery/src/worker/tests.rs @@ -29,11 +29,15 @@ use futures::{ sink::SinkExt, task::LocalSpawn, }; -use libp2p::{core::multiaddr, identity::SigningError, kad::record::Key as KademliaKey, PeerId}; +use libp2p::{identity::SigningError, kad::record::Key as KademliaKey}; use prometheus_endpoint::prometheus::default_registry; use sc_client_api::HeaderBackend; use sc_network::{service::signature::Keypair, Signature}; +use sc_network_types::{ + multiaddr::{Multiaddr, Protocol}, + PeerId, +}; use sp_api::{ApiRef, ProvideRuntimeApi}; use sp_keystore::{testing::MemoryKeystore, Keystore}; use sp_runtime::traits::{Block as BlockT, NumberFor, Zero}; @@ -168,7 +172,7 @@ impl NetworkSigner for TestNetwork { let public_key = libp2p::identity::PublicKey::try_decode_protobuf(&public_key) .map_err(|error| error.to_string())?; let peer_id: PeerId = peer_id.into(); - let remote: libp2p::PeerId = public_key.to_peer_id(); + let remote: PeerId = public_key.to_peer_id().into(); Ok(peer_id == remote && public_key.verify(message, signature)) } @@ -435,7 +439,7 @@ fn dont_stop_polling_dht_event_stream_after_bogus_event() { let peer_id = PeerId::random(); let address: Multiaddr = "/ip6/2001:db8:0:0:0:0:0:1/tcp/30333".parse().unwrap(); - address.with(multiaddr::Protocol::P2p(peer_id.into())) + address.with(Protocol::P2p(peer_id.into())) }; let remote_key_store = MemoryKeystore::new(); let remote_public_key: AuthorityId = remote_key_store From 9fc3f80f772ef5fb77e3050c096a270bddf44b9d Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Thu, 16 May 2024 17:52:11 +0300 Subject: [PATCH 16/24] Fix tests --- substrate/client/network/src/config.rs | 10 ++------ .../protocol/notifications/service/tests.rs | 2 +- .../client/network/src/protocol_controller.rs | 3 ++- substrate/client/network/test/src/fuzz.rs | 3 ++- substrate/client/network/test/src/lib.rs | 9 ++++--- .../client/network/types/src/multiaddr.rs | 25 +++++++++++++++++++ 6 files changed, 37 insertions(+), 15 deletions(-) diff --git a/substrate/client/network/src/config.rs b/substrate/client/network/src/config.rs index ea69fef41681..7272a43d9d8f 100644 --- a/substrate/client/network/src/config.rs +++ b/substrate/client/network/src/config.rs @@ -945,14 +945,8 @@ mod tests { tempfile::Builder::new().prefix(prefix).tempdir().unwrap() } - fn secret_bytes(kp: Keypair) -> Vec { - kp.try_into_ed25519() - .expect("ed25519 keypair") - .secret() - .as_ref() - .iter() - .cloned() - .collect() + fn secret_bytes(kp: ed25519::Keypair) -> Vec { + kp.secret().to_bytes().into() } #[test] diff --git a/substrate/client/network/src/protocol/notifications/service/tests.rs b/substrate/client/network/src/protocol/notifications/service/tests.rs index f0157f6d28dd..32ccb3348adf 100644 --- a/substrate/client/network/src/protocol/notifications/service/tests.rs +++ b/substrate/client/network/src/protocol/notifications/service/tests.rs @@ -200,7 +200,7 @@ async fn send_async_notification_to_non_existent_peer() { if let Err(error::Error::PeerDoesntExist(peer_id)) = notif.send_async_notification(&peer.into(), vec![1, 3, 3, 7]).await { - assert_eq!(peer, peer_id); + assert_eq!(peer, peer_id.into()); } else { panic!("invalid error received from `send_async_notification()`"); } diff --git a/substrate/client/network/src/protocol_controller.rs b/substrate/client/network/src/protocol_controller.rs index e78ea9339f46..da51a7a4f9f4 100644 --- a/substrate/client/network/src/protocol_controller.rs +++ b/substrate/client/network/src/protocol_controller.rs @@ -858,8 +858,9 @@ mod tests { use super::*; use crate::{ peer_store::{PeerStoreProvider, ProtocolHandle as ProtocolHandleT}, - PeerId, ReputationChange, + ReputationChange, }; + use libp2p::PeerId; use sc_network_common::role::ObservedRole; use sc_utils::mpsc::{tracing_unbounded, TryRecvError}; use std::collections::HashSet; diff --git a/substrate/client/network/test/src/fuzz.rs b/substrate/client/network/test/src/fuzz.rs index 69d08d47d26a..b0cd6dcf9993 100644 --- a/substrate/client/network/test/src/fuzz.rs +++ b/substrate/client/network/test/src/fuzz.rs @@ -20,6 +20,7 @@ //! and `PeerStore` to discover possible inconsistencies in peer management. use futures::prelude::*; +use libp2p::PeerId; use rand::{ distributions::{Distribution, Uniform, WeightedIndex}, seq::IteratorRandom, @@ -27,7 +28,7 @@ use rand::{ use sc_network::{ peer_store::{PeerStore, PeerStoreProvider}, protocol_controller::{IncomingIndex, Message, ProtoSetConfig, ProtocolController, SetId}, - PeerId, ReputationChange, + ReputationChange, }; use sc_utils::mpsc::tracing_unbounded; use std::{ diff --git a/substrate/client/network/test/src/lib.rs b/substrate/client/network/test/src/lib.rs index 48a4b3d6e6e1..8a8f9608051a 100644 --- a/substrate/client/network/test/src/lib.rs +++ b/substrate/client/network/test/src/lib.rs @@ -35,7 +35,7 @@ use std::{ }; use futures::{channel::oneshot, future::BoxFuture, pin_mut, prelude::*}; -use libp2p::{build_multiaddr, PeerId}; +use libp2p::PeerId; use log::trace; use parking_lot::Mutex; use sc_block_builder::{BlockBuilder, BlockBuilderBuilder}; @@ -57,8 +57,8 @@ use sc_network::{ peer_store::PeerStore, request_responses::ProtocolConfig as RequestResponseConfig, types::ProtocolName, - Multiaddr, NetworkBlock, NetworkService, NetworkStateInfo, NetworkSyncForkRequest, - NetworkWorker, NotificationMetrics, NotificationService, + NetworkBlock, NetworkService, NetworkStateInfo, NetworkSyncForkRequest, NetworkWorker, + NotificationMetrics, NotificationService, }; use sc_network_common::role::Roles; use sc_network_light::light_client_requests::handler::LightClientRequestHandler; @@ -71,6 +71,7 @@ use sc_network_sync::{ }, warp_request_handler, }; +use sc_network_types::{build_multiaddr, multiaddr::Multiaddr}; use sc_service::client::Client; use sp_blockchain::{ Backend as BlockchainBackend, HeaderBackend, Info as BlockchainInfo, Result as ClientResult, @@ -985,7 +986,7 @@ pub trait TestNetFactory: Default + Sized + Send { for peer in peers.iter_mut() { peer.network.add_known_address( network.service().local_peer_id().into(), - listen_addr.clone(), + listen_addr.clone().into(), ); } diff --git a/substrate/client/network/types/src/multiaddr.rs b/substrate/client/network/types/src/multiaddr.rs index f598583f6e3d..5ff0fd125606 100644 --- a/substrate/client/network/types/src/multiaddr.rs +++ b/substrate/client/network/types/src/multiaddr.rs @@ -18,6 +18,7 @@ use litep2p::types::multiaddr::{ Error as LiteP2pError, Iter as LiteP2pIter, Multiaddr as LiteP2pMultiaddr, + Protocol as LiteP2pProtocol, }; use std::{ fmt::{self, Debug, Display}, @@ -161,6 +162,22 @@ impl FromStr for Multiaddr { } } +impl TryFrom for Multiaddr { + type Error = ParseError; + + fn try_from(s: String) -> Result { + Self::from_str(&s) + } +} + +impl<'a> TryFrom<&'a str> for Multiaddr { + type Error = ParseError; + + fn try_from(s: &'a str) -> Result { + Self::from_str(s) + } +} + /// Iterator over `Multiaddr` [`Protocol`]s. pub struct Iter<'a>(LiteP2pIter<'a>); @@ -196,6 +213,14 @@ impl<'a> FromIterator> for Multiaddr { } } +impl<'a> From> for Multiaddr { + fn from(p: Protocol<'a>) -> Multiaddr { + let protocol: LiteP2pProtocol = p.into(); + let multiaddr: LiteP2pMultiaddr = protocol.into(); + multiaddr.into() + } +} + /// Easy way for a user to create a `Multiaddr`. /// /// Example: From 036aac7279aa85250455a6509a7a72740f374b7f Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Fri, 17 May 2024 12:45:11 +0300 Subject: [PATCH 17/24] Make clippy happy --- substrate/client/network/types/src/multiaddr.rs | 2 +- substrate/client/network/types/src/multiaddr/protocol.rs | 2 +- substrate/client/network/types/src/multihash.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/substrate/client/network/types/src/multiaddr.rs b/substrate/client/network/types/src/multiaddr.rs index 5ff0fd125606..dc5d5957d77e 100644 --- a/substrate/client/network/types/src/multiaddr.rs +++ b/substrate/client/network/types/src/multiaddr.rs @@ -148,7 +148,7 @@ impl From for ParseError { LiteP2pError::UnknownProtocolId(n) => ParseError::UnknownProtocolId(n), LiteP2pError::InvalidUvar(e) => ParseError::InvalidUvar(Box::new(e)), LiteP2pError::ParsingError(e) => ParseError::ParsingError(e), - error @ _ => ParseError::ParsingError(Box::new(error)), + error => ParseError::ParsingError(Box::new(error)), } } } diff --git a/substrate/client/network/types/src/multiaddr/protocol.rs b/substrate/client/network/types/src/multiaddr/protocol.rs index 3b5466ea6786..800d08fe36bd 100644 --- a/substrate/client/network/types/src/multiaddr/protocol.rs +++ b/substrate/client/network/types/src/multiaddr/protocol.rs @@ -80,7 +80,7 @@ impl<'a> From> for Protocol<'a> { LiteP2pProtocol::Memory(port) => Protocol::Memory(port), LiteP2pProtocol::Onion(str, port) => Protocol::Onion(str, port), LiteP2pProtocol::Onion3(addr) => - Protocol::Onion3(Cow::Owned(addr.hash().clone()), addr.port()), + Protocol::Onion3(Cow::Owned(*addr.hash()), addr.port()), LiteP2pProtocol::P2p(multihash) => Protocol::P2p(multihash.into()), LiteP2pProtocol::P2pCircuit => Protocol::P2pCircuit, LiteP2pProtocol::Quic => Protocol::Quic, diff --git a/substrate/client/network/types/src/multihash.rs b/substrate/client/network/types/src/multihash.rs index 4b7ba87ec6ba..91f5b6353a71 100644 --- a/substrate/client/network/types/src/multihash.rs +++ b/substrate/client/network/types/src/multihash.rs @@ -60,7 +60,7 @@ impl From for Error { match error { LiteP2pError::InvalidSize(s) => Self::InvalidSize(s), LiteP2pError::UnsupportedCode(c) => Self::UnsupportedCode(c), - e @ _ => Self::Other(Box::new(e)), + e => Self::Other(Box::new(e)), } } } From 685de87a1c5f7a186d243dd30195cfaad8907ff6 Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Fri, 17 May 2024 16:37:41 +0300 Subject: [PATCH 18/24] Add tests for ed25519 types conversion between libs --- substrate/client/network/types/src/ed25519.rs | 199 ++++++++++++++++++ 1 file changed, 199 insertions(+) diff --git a/substrate/client/network/types/src/ed25519.rs b/substrate/client/network/types/src/ed25519.rs index 40d1d12c5af9..87adbca4ed1f 100644 --- a/substrate/client/network/types/src/ed25519.rs +++ b/substrate/client/network/types/src/ed25519.rs @@ -349,4 +349,203 @@ mod tests { let invalid_msg = "h3ll0 w0rld".as_bytes(); assert!(!pk.verify(invalid_msg, &sig)); } + + #[test] + fn substrate_kp_to_libs() { + let kp = Keypair::generate(); + let kp_bytes = kp.to_bytes(); + let kp1: libp2p_ed25519::Keypair = kp.clone().into(); + let kp2: litep2p_ed25519::Keypair = kp.clone().into(); + let kp3 = libp2p_ed25519::Keypair::try_from_bytes(&mut kp_bytes.clone()).unwrap(); + let kp4 = litep2p_ed25519::Keypair::decode(&mut kp_bytes.clone()).unwrap(); + + assert_eq!(kp_bytes, kp1.to_bytes()); + assert_eq!(kp_bytes, kp2.encode()); + + let msg = "hello world".as_bytes(); + let sig = kp.sign(msg); + let sig1 = kp1.sign(msg); + let sig2 = kp2.sign(msg); + let sig3 = kp3.sign(msg); + let sig4 = kp4.sign(msg); + + assert_eq!(sig, sig1); + assert_eq!(sig, sig2); + assert_eq!(sig, sig3); + assert_eq!(sig, sig4); + + let pk1 = kp1.public(); + let pk2 = kp2.public(); + let pk3 = kp3.public(); + let pk4 = kp4.public(); + + assert!(pk1.verify(msg, &sig)); + assert!(pk2.verify(msg, &sig)); + assert!(pk3.verify(msg, &sig)); + assert!(pk4.verify(msg, &sig)); + } + + #[test] + fn litep2p_kp_to_substrate_kp() { + let kp = litep2p_ed25519::Keypair::generate(); + let kp1: Keypair = kp.clone().into(); + let kp2 = Keypair::try_from_bytes(&mut kp.encode()).unwrap(); + + assert_eq!(kp.encode(), kp1.to_bytes()); + + let msg = "hello world".as_bytes(); + let sig = kp.sign(msg); + let sig1 = kp1.sign(msg); + let sig2 = kp2.sign(msg); + + assert_eq!(sig, sig1); + assert_eq!(sig, sig2); + + let pk1 = kp1.public(); + let pk2 = kp2.public(); + + assert!(pk1.verify(msg, &sig)); + assert!(pk2.verify(msg, &sig)); + } + + #[test] + fn libp2p_kp_to_substrate_kp() { + let kp = libp2p_ed25519::Keypair::generate(); + let kp1: Keypair = kp.clone().into(); + let kp2 = Keypair::try_from_bytes(&mut kp.to_bytes()).unwrap(); + + assert_eq!(kp.to_bytes(), kp1.to_bytes()); + + let msg = "hello world".as_bytes(); + let sig = kp.sign(msg); + let sig1 = kp1.sign(msg); + let sig2 = kp2.sign(msg); + + assert_eq!(sig, sig1); + assert_eq!(sig, sig2); + + let pk1 = kp1.public(); + let pk2 = kp2.public(); + + assert!(pk1.verify(msg, &sig)); + assert!(pk2.verify(msg, &sig)); + } + + #[test] + fn substrate_pk_to_libs() { + let kp = Keypair::generate(); + let pk = kp.public(); + let pk_bytes = pk.to_bytes(); + let pk1: libp2p_ed25519::PublicKey = pk.clone().into(); + let pk2: litep2p_ed25519::PublicKey = pk.clone().into(); + let pk3 = libp2p_ed25519::PublicKey::try_from_bytes(&mut pk_bytes.clone()).unwrap(); + let pk4 = litep2p_ed25519::PublicKey::decode(&mut pk_bytes.clone()).unwrap(); + + assert_eq!(pk_bytes, pk1.to_bytes()); + assert_eq!(pk_bytes, pk2.encode()); + + let msg = "hello world".as_bytes(); + let sig = kp.sign(msg); + + assert!(pk.verify(msg, &sig)); + assert!(pk1.verify(msg, &sig)); + assert!(pk2.verify(msg, &sig)); + assert!(pk3.verify(msg, &sig)); + assert!(pk4.verify(msg, &sig)); + } + + #[test] + fn litep2p_pk_to_substrate_pk() { + let kp = litep2p_ed25519::Keypair::generate(); + let pk = kp.public(); + let pk_bytes = pk.clone().encode(); + let pk1: PublicKey = pk.clone().into(); + let pk2 = PublicKey::try_from_bytes(&pk_bytes).unwrap(); + + assert_eq!(pk_bytes, pk1.to_bytes()); + + let msg = "hello world".as_bytes(); + let sig = kp.sign(msg); + + assert!(pk.verify(msg, &sig)); + assert!(pk1.verify(msg, &sig)); + assert!(pk2.verify(msg, &sig)); + } + + #[test] + fn libp2p_pk_to_substrate_pk() { + let kp = libp2p_ed25519::Keypair::generate(); + let pk = kp.public(); + let pk_bytes = pk.clone().to_bytes(); + let pk1: PublicKey = pk.clone().into(); + let pk2 = PublicKey::try_from_bytes(&pk_bytes).unwrap(); + + assert_eq!(pk_bytes, pk1.to_bytes()); + + let msg = "hello world".as_bytes(); + let sig = kp.sign(msg); + + assert!(pk.verify(msg, &sig)); + assert!(pk1.verify(msg, &sig)); + assert!(pk2.verify(msg, &sig)); + } + + #[test] + fn substrate_sk_to_libs() { + let sk = SecretKey::generate(); + let sk_bytes = sk.to_bytes(); + let sk1: libp2p_ed25519::SecretKey = sk.clone().into(); + let sk2: litep2p_ed25519::SecretKey = sk.clone().into(); + let sk3 = libp2p_ed25519::SecretKey::try_from_bytes(&mut sk_bytes.clone()).unwrap(); + let sk4 = litep2p_ed25519::SecretKey::from_bytes(&mut sk_bytes.clone()).unwrap(); + + let kp: Keypair = sk.into(); + let kp1: libp2p_ed25519::Keypair = sk1.into(); + let kp2: litep2p_ed25519::Keypair = sk2.into(); + let kp3: libp2p_ed25519::Keypair = sk3.into(); + let kp4: litep2p_ed25519::Keypair = sk4.into(); + + let msg = "hello world".as_bytes(); + let sig = kp.sign(msg); + + assert_eq!(sig, kp1.sign(msg)); + assert_eq!(sig, kp2.sign(msg)); + assert_eq!(sig, kp3.sign(msg)); + assert_eq!(sig, kp4.sign(msg)); + } + + #[test] + fn litep2p_sk_to_substrate_sk() { + let sk = litep2p_ed25519::SecretKey::generate(); + let sk1: SecretKey = sk.clone().into(); + let sk2 = SecretKey::try_from_bytes(&mut sk.to_bytes()).unwrap(); + + let kp: litep2p_ed25519::Keypair = sk.into(); + let kp1: Keypair = sk1.into(); + let kp2: Keypair = sk2.into(); + + let msg = "hello world".as_bytes(); + let sig = kp.sign(msg); + + assert_eq!(sig, kp1.sign(msg)); + assert_eq!(sig, kp2.sign(msg)); + } + + #[test] + fn libp2p_sk_to_substrate_sk() { + let sk = libp2p_ed25519::SecretKey::generate(); + let sk_bytes = sk.as_ref().to_owned(); + let sk1: SecretKey = sk.clone().into(); + let sk2 = SecretKey::try_from_bytes(sk_bytes).unwrap(); + + let kp: libp2p_ed25519::Keypair = sk.into(); + let kp1: Keypair = sk1.into(); + let kp2: Keypair = sk2.into(); + + let msg = "hello world".as_bytes(); + let sig = kp.sign(msg); + + assert_eq!(sig, kp1.sign(msg)); + assert_eq!(sig, kp2.sign(msg)); + } } From dabbd9606634eb5c634bf96e6b9173af2903bc1a Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Fri, 17 May 2024 16:56:11 +0300 Subject: [PATCH 19/24] Make clippy happy again --- substrate/client/network/types/src/ed25519.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/substrate/client/network/types/src/ed25519.rs b/substrate/client/network/types/src/ed25519.rs index 87adbca4ed1f..e85f405b1306 100644 --- a/substrate/client/network/types/src/ed25519.rs +++ b/substrate/client/network/types/src/ed25519.rs @@ -438,8 +438,8 @@ mod tests { let pk_bytes = pk.to_bytes(); let pk1: libp2p_ed25519::PublicKey = pk.clone().into(); let pk2: litep2p_ed25519::PublicKey = pk.clone().into(); - let pk3 = libp2p_ed25519::PublicKey::try_from_bytes(&mut pk_bytes.clone()).unwrap(); - let pk4 = litep2p_ed25519::PublicKey::decode(&mut pk_bytes.clone()).unwrap(); + let pk3 = libp2p_ed25519::PublicKey::try_from_bytes(&pk_bytes).unwrap(); + let pk4 = litep2p_ed25519::PublicKey::decode(&pk_bytes).unwrap(); assert_eq!(pk_bytes, pk1.to_bytes()); assert_eq!(pk_bytes, pk2.encode()); From a66016c452e61f2511b842df877052094302ece9 Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Fri, 17 May 2024 17:12:00 +0300 Subject: [PATCH 20/24] Add PRDoc --- prdoc/pr_4198.prdoc | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 prdoc/pr_4198.prdoc diff --git a/prdoc/pr_4198.prdoc b/prdoc/pr_4198.prdoc new file mode 100644 index 000000000000..a35983f4a0d1 --- /dev/null +++ b/prdoc/pr_4198.prdoc @@ -0,0 +1,29 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Replace `Multiaddr` & related types with substrate-specific types + +doc: + - audience: Node Dev + description: | + Introduce custom types / substrate wrappers for `Multiaddr`, `multiaddr::Protocol`, + `Multihash`, `ed25519::*` and supplementary types like errors and iterators. + + Common code in substrate uses these custom types, while `libp2p` & `litep2p` network + backends use their corresponding libraries types. + + This is needed to independently upgrade `libp2p` & `litep2p` dependencies. + +crates: + - name: sc-network-types + bump: minor + - name: sc-network + bump: minor + - name: sc-authority-discovery + bump: patch + - name: sc-cli + bump: patch + - name: sc-mixnet + bump: patch + - name: sc-telemetry + bump: patch From 41ffe22305fa2568e4cdcc546eb4f487b28d31f6 Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Fri, 17 May 2024 17:23:51 +0300 Subject: [PATCH 21/24] Fix doctest --- substrate/client/network/types/src/multiaddr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/client/network/types/src/multiaddr.rs b/substrate/client/network/types/src/multiaddr.rs index dc5d5957d77e..55fed48fc521 100644 --- a/substrate/client/network/types/src/multiaddr.rs +++ b/substrate/client/network/types/src/multiaddr.rs @@ -226,7 +226,7 @@ impl<'a> From> for Multiaddr { /// Example: /// /// ```rust -/// # use multiaddr::multiaddr; +/// use sc_network_types::build_multiaddr; /// let addr = build_multiaddr!(Ip4([127, 0, 0, 1]), Tcp(10500u16)); /// ``` /// From 086f389ef85dbd943b9febb472d56d030928c82f Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Mon, 20 May 2024 16:03:44 +0300 Subject: [PATCH 22/24] Apply review suggestions --- substrate/client/network/types/src/multiaddr.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/substrate/client/network/types/src/multiaddr.rs b/substrate/client/network/types/src/multiaddr.rs index 55fed48fc521..312bef9baab1 100644 --- a/substrate/client/network/types/src/multiaddr.rs +++ b/substrate/client/network/types/src/multiaddr.rs @@ -103,7 +103,6 @@ impl From for LiteP2pMultiaddr { } impl TryFrom> for Multiaddr { - // TODO: extend `ParseError` variants to cover conversion from bytes. type Error = ParseError; fn try_from(v: Vec) -> Result { From 7547c4942a887029c11cbcfd5103f6d8315ab95c Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Mon, 20 May 2024 16:04:21 +0300 Subject: [PATCH 23/24] Update semver in PRDoc --- prdoc/pr_4198.prdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prdoc/pr_4198.prdoc b/prdoc/pr_4198.prdoc index a35983f4a0d1..82ab151cccdb 100644 --- a/prdoc/pr_4198.prdoc +++ b/prdoc/pr_4198.prdoc @@ -20,7 +20,7 @@ crates: - name: sc-network bump: minor - name: sc-authority-discovery - bump: patch + bump: minor - name: sc-cli bump: patch - name: sc-mixnet From b1bea172e538f4b9a08ec0c2fe3d904c22c92a67 Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Mon, 20 May 2024 17:26:02 +0300 Subject: [PATCH 24/24] Fix CI --- prdoc/pr_4198.prdoc | 2 ++ substrate/client/network/src/config.rs | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/prdoc/pr_4198.prdoc b/prdoc/pr_4198.prdoc index 82ab151cccdb..cff956812606 100644 --- a/prdoc/pr_4198.prdoc +++ b/prdoc/pr_4198.prdoc @@ -19,6 +19,8 @@ crates: bump: minor - name: sc-network bump: minor + - name: sc-network-sync + bump: minor - name: sc-authority-discovery bump: minor - name: sc-cli diff --git a/substrate/client/network/src/config.rs b/substrate/client/network/src/config.rs index 7272a43d9d8f..100a1e9dfb38 100644 --- a/substrate/client/network/src/config.rs +++ b/substrate/client/network/src/config.rs @@ -99,7 +99,7 @@ impl fmt::Debug for ProtocolId { /// # Example /// /// ``` -/// # use libp2p::{Multiaddr, PeerId}; +/// # use sc_network_types::{multiaddr::Multiaddr, PeerId}; /// use sc_network::config::parse_str_addr; /// let (peer_id, addr) = parse_str_addr( /// "/ip4/198.51.100.19/tcp/30333/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV" @@ -130,7 +130,7 @@ pub fn parse_addr(mut addr: Multiaddr) -> Result<(PeerId, Multiaddr), ParseErr> /// # Example /// /// ``` -/// # use libp2p::{Multiaddr, PeerId}; +/// # use sc_network_types::{multiaddr::Multiaddr, PeerId}; /// use sc_network::config::MultiaddrWithPeerId; /// let addr: MultiaddrWithPeerId = /// "/ip4/198.51.100.19/tcp/30333/p2p/QmSk5HQbn6LhUwDiNMseVUjuRYhEtYj4aUZ6WfWoGURpdV".parse().unwrap();