From a5bd12e536b370a2cfbfac0d18a4d1d8ee86b44d Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Tue, 9 Sep 2025 14:25:40 +0300 Subject: [PATCH 01/13] Upgrade litep2p to support `PUT_VALUE`/`ADD_PROVIDER` success events --- Cargo.lock | 63 +++++++++---------- Cargo.toml | 2 +- substrate/client/network/src/event.rs | 2 - .../client/network/src/litep2p/discovery.rs | 41 +++++++++++- substrate/client/network/src/litep2p/mod.rs | 47 ++++++++++++++ .../client/network/src/litep2p/service.rs | 6 +- 6 files changed, 121 insertions(+), 40 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 95bdf735f4f42..bdbcf8dfe056f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1923,7 +1923,7 @@ dependencies = [ "bitflags 2.9.4", "cexpr", "clang-sys", - "itertools 0.13.0", + "itertools 0.11.0", "proc-macro2 1.0.95", "quote 1.0.40", "regex", @@ -7248,7 +7248,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f2f12607f92c69b12ed746fabf9ca4f5c482cba46679c1a75b874ed7c26adb" dependencies = [ "futures-io", - "rustls 0.23.18", + "rustls 0.23.23", "rustls-pki-types", ] @@ -7803,7 +7803,7 @@ dependencies = [ "ipnet", "once_cell", "rand 0.9.0", - "ring 0.17.8", + "ring 0.17.14", "thiserror 2.0.12", "tinyvec", "tokio", @@ -8031,7 +8031,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.5.9", + "socket2 0.4.9", "tokio", "tower-service", "tracing", @@ -8086,7 +8086,7 @@ dependencies = [ "hyper 1.6.0", "hyper-util", "log", - "rustls 0.23.18", + "rustls 0.23.23", "rustls-native-certs 0.8.0", "rustls-pki-types", "tokio", @@ -8784,7 +8784,7 @@ dependencies = [ "http 1.1.0", "jsonrpsee-core", "pin-project", - "rustls 0.23.18", + "rustls 0.23.23", "rustls-pki-types", "rustls-platform-verifier", "soketto", @@ -8837,7 +8837,7 @@ dependencies = [ "hyper-util", "jsonrpsee-core", "jsonrpsee-types", - "rustls 0.23.18", + "rustls 0.23.23", "rustls-platform-verifier", "serde", "serde_json", @@ -9529,8 +9529,8 @@ dependencies = [ "parking_lot 0.12.3", "quinn", "rand 0.8.5", - "ring 0.17.8", - "rustls 0.23.18", + "ring 0.17.14", + "rustls 0.23.23", "socket2 0.5.9", "thiserror 1.0.65", "tokio", @@ -9621,8 +9621,8 @@ dependencies = [ "libp2p-core", "libp2p-identity", "rcgen", - "ring 0.17.8", - "rustls 0.23.18", + "ring 0.17.14", + "rustls 0.23.23", "rustls-webpki 0.101.4", "thiserror 1.0.65", "x509-parser 0.16.0", @@ -9856,8 +9856,7 @@ checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "litep2p" version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c666ef772d123a7643323ad4979c30dd825e9c68ec1aa5b387a6c9a9871c11ea" +source = "git+https://github.com/paritytech/litep2p.git?branch=dm-add-provider-success#e6aad45f3f4acd9ef1bce21cd2b30cb129d79b0a" dependencies = [ "async-trait", "bs58", @@ -9878,6 +9877,7 @@ dependencies = [ "prost 0.13.5", "prost-build", "rand 0.8.5", + "ring 0.17.14", "serde", "sha2 0.10.9", "simple-dns", @@ -17755,7 +17755,7 @@ checksum = "f8650aabb6c35b860610e9cff5dc1af886c9e25073b7b1712a68972af4281302" dependencies = [ "bytes", "heck 0.5.0", - "itertools 0.13.0", + "itertools 0.11.0", "log", "multimap", "once_cell", @@ -17801,7 +17801,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools 0.14.0", + "itertools 0.11.0", "proc-macro2 1.0.95", "quote 1.0.40", "syn 2.0.98", @@ -17947,7 +17947,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash 2.1.1", - "rustls 0.23.18", + "rustls 0.23.23", "socket2 0.5.9", "thiserror 1.0.65", "tokio", @@ -17962,9 +17962,9 @@ checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" dependencies = [ "bytes", "rand 0.8.5", - "ring 0.17.8", + "ring 0.17.14", "rustc-hash 2.1.1", - "rustls 0.23.18", + "rustls 0.23.23", "slab", "thiserror 1.0.65", "tinyvec", @@ -18428,7 +18428,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.18", + "rustls 0.23.23", "rustls-pemfile 2.0.0", "rustls-pki-types", "serde", @@ -18698,15 +18698,14 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.8" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", "getrandom 0.2.10", "libc", - "spin 0.9.8", "untrusted 0.9.0", "windows-sys 0.52.0", ] @@ -19217,13 +19216,13 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.18" +version = "0.23.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9cc1d47e243d655ace55ed38201c19ae02c148ae56412ab8750e8f0166ab7f" +checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395" dependencies = [ "log", "once_cell", - "ring 0.17.8", + "ring 0.17.14", "rustls-pki-types", "rustls-webpki 0.102.8", "subtle 2.5.0", @@ -19304,7 +19303,7 @@ dependencies = [ "jni", "log", "once_cell", - "rustls 0.23.18", + "rustls 0.23.23", "rustls-native-certs 0.7.0", "rustls-platform-verifier-android", "rustls-webpki 0.102.8", @@ -19336,7 +19335,7 @@ version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ - "ring 0.17.8", + "ring 0.17.14", "rustls-pki-types", "untrusted 0.9.0", ] @@ -20418,7 +20417,7 @@ dependencies = [ "parity-scale-codec", "parking_lot 0.12.3", "rand 0.8.5", - "rustls 0.23.18", + "rustls 0.23.23", "sc-block-builder", "sc-client-api", "sc-client-db", @@ -21909,7 +21908,7 @@ dependencies = [ "chacha20poly1305", "curve25519-dalek", "rand_core 0.6.4", - "ring 0.17.8", + "ring 0.17.14", "rustc_version 0.4.0", "sha2 0.10.9", "subtle 2.5.0", @@ -25655,7 +25654,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.18", + "rustls 0.23.23", "rustls-pki-types", "tokio", ] @@ -25717,7 +25716,7 @@ checksum = "489a59b6730eda1b0171fcfda8b121f4bee2b35cba8645ca35c5f7ba3eb736c1" dependencies = [ "futures-util", "log", - "rustls 0.23.18", + "rustls 0.23.23", "rustls-native-certs 0.8.0", "rustls-pki-types", "tokio", @@ -26091,7 +26090,7 @@ dependencies = [ "httparse", "log", "rand 0.9.0", - "rustls 0.23.18", + "rustls 0.23.23", "rustls-pki-types", "sha1", "thiserror 2.0.12", diff --git a/Cargo.toml b/Cargo.toml index 3e9551138d12e..f36e98f191b36 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -898,7 +898,7 @@ linked-hash-map = { version = "0.5.4" } linked_hash_set = { version = "0.1.4" } linregress = { version = "0.5.1" } lite-json = { version = "0.2.0", default-features = false } -litep2p = { version = "0.10.0", features = ["websocket"] } +litep2p = { git = "https://github.com/paritytech/litep2p.git", branch = "dm-add-provider-success", features = ["websocket", "rsa"] } log = { version = "0.4.22", default-features = false } macro_magic = { version = "0.5.1" } maplit = { version = "1.0.2" } diff --git a/substrate/client/network/src/event.rs b/substrate/client/network/src/event.rs index f5a4b92aef5e3..bb4fa921c9493 100644 --- a/substrate/client/network/src/event.rs +++ b/substrate/client/network/src/event.rs @@ -48,14 +48,12 @@ pub enum DhtEvent { ValueNotFound(Key), /// The record has been successfully inserted into the DHT. - // TODO: this is not implemented with litep2p network backend. ValuePut(Key), /// An error has occurred while putting a record into the DHT. ValuePutFailed(Key), /// Successfully started providing the given key. - // TODO: this is not implemented with litep2p network backend. StartedProviding(Key), /// An error occured while registering as a content provider on the DHT. diff --git a/substrate/client/network/src/litep2p/discovery.rs b/substrate/client/network/src/litep2p/discovery.rs index 4a9b84b3a215a..01d4067ce1489 100644 --- a/substrate/client/network/src/litep2p/discovery.rs +++ b/substrate/client/network/src/litep2p/discovery.rs @@ -80,6 +80,16 @@ const MAX_EXTERNAL_ADDRESSES: u32 = 32; /// external. const MIN_ADDRESS_CONFIRMATIONS: usize = 3; +/// Quorum threshold to interpret `PUT_VALUE` & `ADD_PROVIDER` as successful. +/// +/// As opposed to libp2p, litep2p does not finish the query as soon as the required number of +/// peers have reached. Instead, it tries to put the record to all target peers (typically 20) and +/// uses the quorum setting only to determine the success of the query. +/// +/// We set the threshold to 50% of the target peers to account for unreachable peers. The actual +/// number of stored records may be higher. +const QUORUM_THRESHOLD: NonZeroUsize = NonZeroUsize::new(10).expect("10 > 0; qed"); + /// Discovery events. #[derive(Debug)] pub enum DiscoveryEvent { @@ -174,6 +184,14 @@ pub enum DiscoveryEvent { providers: Vec, }, + /// Provider was successfully published. + AddProviderSuccess { + /// Query ID. + query_id: QueryId, + /// Provided key. + provided_key: RecordKey, + }, + /// Query failed. QueryFailed { /// Query ID. @@ -401,7 +419,10 @@ impl Discovery { /// Publish value on the DHT using Kademlia `PUT_VALUE`. pub async fn put_value(&mut self, key: KademliaKey, value: Vec) -> QueryId { self.kademlia_handle - .put_record(Record::new(RecordKey::new(&key.to_vec()), value)) + .put_record( + Record::new(RecordKey::new(&key.to_vec()), value), + Quorum::N(QUORUM_THRESHOLD), + ) .await } @@ -417,6 +438,9 @@ impl Discovery { record, peers.into_iter().map(|peer| peer.into()).collect(), update_local_storage, + // These are the peers that just returned the record to us in authority-discovery, + // so we assume they are all reachable. + Quorum::All, ) .await } @@ -447,7 +471,9 @@ impl Discovery { /// Start providing `key`. pub async fn start_providing(&mut self, key: KademliaKey) { - self.kademlia_handle.start_providing(key.into()).await; + self.kademlia_handle + .start_providing(key.into(), Quorum::N(QUORUM_THRESHOLD)) + .await; } /// Stop providing `key`. @@ -680,6 +706,17 @@ impl Stream for Discovery { providers, })) }, + Poll::Ready(Some(KademliaEvent::AddProviderSuccess { query_id, provided_key })) => { + log::trace!( + target: LOG_TARGET, + "`ADD_PROVIDER` for {query_id:?} with {provided_key:?} succeeded", + ); + + return Poll::Ready(Some(DiscoveryEvent::AddProviderSuccess { + query_id, + provided_key, + })) + }, // We do not validate incoming providers. Poll::Ready(Some(KademliaEvent::IncomingProvider { .. })) => {}, } diff --git a/substrate/client/network/src/litep2p/mod.rs b/substrate/client/network/src/litep2p/mod.rs index 95229ad5ce126..972973fa214fb 100644 --- a/substrate/client/network/src/litep2p/mod.rs +++ b/substrate/client/network/src/litep2p/mod.rs @@ -153,6 +153,8 @@ enum KadQuery { PutValue(RecordKey, Instant), /// `GET_PROVIDERS` query for key and when it was initiated. GetProviders(RecordKey, Instant), + /// `ADD_PROVIDER` query for key and when it was initiated. + AddProvider(RecordKey, Instant), } /// Networking backend for `litep2p`. @@ -967,6 +969,34 @@ impl NetworkBackend for Litep2pNetworkBac } } } + Some(DiscoveryEvent::AddProviderSuccess { query_id, provided_key }) => { + match self.pending_queries.remove(&query_id) { + Some(KadQuery::GetProviders(key, started)) => { + log::trace!( + target: LOG_TARGET, + "`ADD_PROVIDER` for {provided_key:?} ({query_id:?}) succeeded", + ); + + self.event_streams.send(Event::Dht( + DhtEvent::StartedProviding(provided_key.into()) + )); + + if let Some(ref metrics) = self.metrics { + metrics + .kademlia_query_duration + .with_label_values(&["provider-add"]) + .observe(started.elapsed().as_secs_f64()); + } + } + query => { + log::error!( + target: LOG_TARGET, + "Missing/invalid pending query for `ADD_PROVIDER`: {query:?}" + ); + debug_assert!(false); + } + } + } Some(DiscoveryEvent::QueryFailed { query_id }) => { match self.pending_queries.remove(&query_id) { Some(KadQuery::FindNode(peer_id, started)) => { @@ -1037,6 +1067,23 @@ impl NetworkBackend for Litep2pNetworkBac .observe(started.elapsed().as_secs_f64()); } }, + Some(KadQuery::AddProvider(key, started)) => { + log::debug!( + target: LOG_TARGET, + "`ADD_PROVIDER` ({query_id:?}) failed with key {key:?}", + ); + + self.event_streams.send(Event::Dht( + DhtEvent::StartProvidingFailed(key) + )); + + if let Some(ref metrics) = self.metrics { + metrics + .kademlia_query_duration + .with_label_values(&["provider-add-failed"]) + .observe(started.elapsed().as_secs_f64()); + } + }, None => { log::warn!( target: LOG_TARGET, diff --git a/substrate/client/network/src/litep2p/service.rs b/substrate/client/network/src/litep2p/service.rs index c2a994d532956..6821e595777ea 100644 --- a/substrate/client/network/src/litep2p/service.rs +++ b/substrate/client/network/src/litep2p/service.rs @@ -264,11 +264,11 @@ impl NetworkSigner for Litep2pNetworkService { signature: &Vec, message: &Vec, ) -> Result { - let public_key = litep2p::crypto::PublicKey::from_protobuf_encoding(&public_key) + let identity = litep2p::PeerId::from_public_key_protobuf(&public_key); + let public_key = litep2p::crypto::RemotePublicKey::from_protobuf_encoding(&public_key) .map_err(|error| error.to_string())?; let peer: litep2p::PeerId = peer.into(); - - Ok(peer == public_key.to_peer_id() && public_key.verify(message, signature)) + Ok(peer == identity && public_key.verify(message, signature)) } } From 4cff323f5d4749d467c3e97fe9c93d89141783ad Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Tue, 9 Sep 2025 15:11:47 +0300 Subject: [PATCH 02/13] Track `ADD_PROVIDER` queries --- substrate/client/network/src/litep2p/discovery.rs | 13 ++++--------- substrate/client/network/src/litep2p/mod.rs | 9 +++++---- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/substrate/client/network/src/litep2p/discovery.rs b/substrate/client/network/src/litep2p/discovery.rs index 01d4067ce1489..08ee6ac33b116 100644 --- a/substrate/client/network/src/litep2p/discovery.rs +++ b/substrate/client/network/src/litep2p/discovery.rs @@ -188,8 +188,6 @@ pub enum DiscoveryEvent { AddProviderSuccess { /// Query ID. query_id: QueryId, - /// Provided key. - provided_key: RecordKey, }, /// Query failed. @@ -470,10 +468,10 @@ impl Discovery { } /// Start providing `key`. - pub async fn start_providing(&mut self, key: KademliaKey) { + pub async fn start_providing(&mut self, key: KademliaKey) -> QueryId { self.kademlia_handle .start_providing(key.into(), Quorum::N(QUORUM_THRESHOLD)) - .await; + .await } /// Stop providing `key`. @@ -706,16 +704,13 @@ impl Stream for Discovery { providers, })) }, - Poll::Ready(Some(KademliaEvent::AddProviderSuccess { query_id, provided_key })) => { + Poll::Ready(Some(KademliaEvent::AddProviderSuccess { query_id, provided_key: _ })) => { log::trace!( target: LOG_TARGET, "`ADD_PROVIDER` for {query_id:?} with {provided_key:?} succeeded", ); - return Poll::Ready(Some(DiscoveryEvent::AddProviderSuccess { - query_id, - provided_key, - })) + return Poll::Ready(Some(DiscoveryEvent::AddProviderSuccess { query_id })) }, // We do not validate incoming providers. Poll::Ready(Some(KademliaEvent::IncomingProvider { .. })) => {}, diff --git a/substrate/client/network/src/litep2p/mod.rs b/substrate/client/network/src/litep2p/mod.rs index 972973fa214fb..2b7497dac03fa 100644 --- a/substrate/client/network/src/litep2p/mod.rs +++ b/substrate/client/network/src/litep2p/mod.rs @@ -686,7 +686,8 @@ impl NetworkBackend for Litep2pNetworkBac self.discovery.store_record(key, value, publisher.map(Into::into), expires).await; } NetworkServiceCommand::StartProviding { key } => { - self.discovery.start_providing(key).await; + let query_id = self.discovery.start_providing(key.clone()).await; + self.pending_queries.insert(query_id, KadQuery::AddProvider(key, Instant::now())); } NetworkServiceCommand::StopProviding { key } => { self.discovery.stop_providing(key).await; @@ -969,16 +970,16 @@ impl NetworkBackend for Litep2pNetworkBac } } } - Some(DiscoveryEvent::AddProviderSuccess { query_id, provided_key }) => { + Some(DiscoveryEvent::AddProviderSuccess { query_id }) => { match self.pending_queries.remove(&query_id) { Some(KadQuery::GetProviders(key, started)) => { log::trace!( target: LOG_TARGET, - "`ADD_PROVIDER` for {provided_key:?} ({query_id:?}) succeeded", + "`ADD_PROVIDER` for {key:?} ({query_id:?}) succeeded", ); self.event_streams.send(Event::Dht( - DhtEvent::StartedProviding(provided_key.into()) + DhtEvent::StartedProviding(key.into()) )); if let Some(ref metrics) = self.metrics { From 5735c5acab09d2543d3d9657c17ae73f2ce1a8fb Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Tue, 9 Sep 2025 15:27:05 +0300 Subject: [PATCH 03/13] minor: missing field --- substrate/client/network/src/litep2p/discovery.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/client/network/src/litep2p/discovery.rs b/substrate/client/network/src/litep2p/discovery.rs index 08ee6ac33b116..8b762577528d1 100644 --- a/substrate/client/network/src/litep2p/discovery.rs +++ b/substrate/client/network/src/litep2p/discovery.rs @@ -704,7 +704,7 @@ impl Stream for Discovery { providers, })) }, - Poll::Ready(Some(KademliaEvent::AddProviderSuccess { query_id, provided_key: _ })) => { + Poll::Ready(Some(KademliaEvent::AddProviderSuccess { query_id, provided_key })) => { log::trace!( target: LOG_TARGET, "`ADD_PROVIDER` for {query_id:?} with {provided_key:?} succeeded", From ec705845f274a2a0eb4ee6c1c1137ec67424a801 Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Tue, 9 Sep 2025 17:14:20 +0300 Subject: [PATCH 04/13] cargo update litep2p --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bdbcf8dfe056f..675ff71cef234 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1923,7 +1923,7 @@ dependencies = [ "bitflags 2.9.4", "cexpr", "clang-sys", - "itertools 0.11.0", + "itertools 0.12.1", "proc-macro2 1.0.95", "quote 1.0.40", "regex", @@ -9856,7 +9856,7 @@ checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "litep2p" version = "0.10.0" -source = "git+https://github.com/paritytech/litep2p.git?branch=dm-add-provider-success#e6aad45f3f4acd9ef1bce21cd2b30cb129d79b0a" +source = "git+https://github.com/paritytech/litep2p.git?branch=dm-add-provider-success#d64e3b948524371d23a0d239575f8bc4b02914d9" dependencies = [ "async-trait", "bs58", @@ -17755,7 +17755,7 @@ checksum = "f8650aabb6c35b860610e9cff5dc1af886c9e25073b7b1712a68972af4281302" dependencies = [ "bytes", "heck 0.5.0", - "itertools 0.11.0", + "itertools 0.12.1", "log", "multimap", "once_cell", @@ -17801,7 +17801,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.12.1", "proc-macro2 1.0.95", "quote 1.0.40", "syn 2.0.98", From c58e7305f9ea8992ce19f3f564834c155177f19a Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Tue, 23 Sep 2025 16:18:28 +0300 Subject: [PATCH 05/13] Handle provider republish events --- substrate/client/network/src/litep2p/discovery.rs | 7 ++++++- substrate/client/network/src/litep2p/mod.rs | 13 +++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/substrate/client/network/src/litep2p/discovery.rs b/substrate/client/network/src/litep2p/discovery.rs index 8b762577528d1..b727688f5b514 100644 --- a/substrate/client/network/src/litep2p/discovery.rs +++ b/substrate/client/network/src/litep2p/discovery.rs @@ -188,6 +188,8 @@ pub enum DiscoveryEvent { AddProviderSuccess { /// Query ID. query_id: QueryId, + /// Provided key. + provided_key: RecordKey, }, /// Query failed. @@ -710,7 +712,10 @@ impl Stream for Discovery { "`ADD_PROVIDER` for {query_id:?} with {provided_key:?} succeeded", ); - return Poll::Ready(Some(DiscoveryEvent::AddProviderSuccess { query_id })) + return Poll::Ready(Some(DiscoveryEvent::AddProviderSuccess { + query_id, + provided_key, + })) }, // We do not validate incoming providers. Poll::Ready(Some(KademliaEvent::IncomingProvider { .. })) => {}, diff --git a/substrate/client/network/src/litep2p/mod.rs b/substrate/client/network/src/litep2p/mod.rs index 2b7497dac03fa..101130d4949c2 100644 --- a/substrate/client/network/src/litep2p/mod.rs +++ b/substrate/client/network/src/litep2p/mod.rs @@ -970,9 +970,11 @@ impl NetworkBackend for Litep2pNetworkBac } } } - Some(DiscoveryEvent::AddProviderSuccess { query_id }) => { + Some(DiscoveryEvent::AddProviderSuccess { query_id, provided_key }) => { match self.pending_queries.remove(&query_id) { Some(KadQuery::GetProviders(key, started)) => { + debug_assert_eq!(key, provided_key.into()); + log::trace!( target: LOG_TARGET, "`ADD_PROVIDER` for {key:?} ({query_id:?}) succeeded", @@ -990,11 +992,10 @@ impl NetworkBackend for Litep2pNetworkBac } } query => { - log::error!( + log::trace!( target: LOG_TARGET, - "Missing/invalid pending query for `ADD_PROVIDER`: {query:?}" + "`ADD_PROVIDER` for key {provided_key:?} ({query_id:?}) succeeded (republishing)", ); - debug_assert!(false); } } } @@ -1086,9 +1087,9 @@ impl NetworkBackend for Litep2pNetworkBac } }, None => { - log::warn!( + log::debug!( target: LOG_TARGET, - "non-existent query failed ({query_id:?})", + "non-existent query (likely republishing a provider) failed ({query_id:?})", ); } } From 9d5e3eef5fbb61fb5c023d179f72135444d9a8a4 Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Wed, 24 Sep 2025 11:26:52 +0300 Subject: [PATCH 06/13] minor: Log invalid queries for ADD_PROVIDER --- substrate/client/network/src/litep2p/mod.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/substrate/client/network/src/litep2p/mod.rs b/substrate/client/network/src/litep2p/mod.rs index 101130d4949c2..adb180035bedf 100644 --- a/substrate/client/network/src/litep2p/mod.rs +++ b/substrate/client/network/src/litep2p/mod.rs @@ -991,7 +991,14 @@ impl NetworkBackend for Litep2pNetworkBac .observe(started.elapsed().as_secs_f64()); } } - query => { + Some(_) => { + log::error!( + target: LOG_TARGET, + "Invalid pending query for `ADD_PROVIDER`: {query_id:?}" + ); + debug_assert!(false); + } + None => { log::trace!( target: LOG_TARGET, "`ADD_PROVIDER` for key {provided_key:?} ({query_id:?}) succeeded (republishing)", From 8a62df491d0985bd726f6285b0e92a9aabcd7971 Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Fri, 24 Oct 2025 17:13:11 +0300 Subject: [PATCH 07/13] minor: remove conflict markers --- substrate/client/network/src/litep2p/service.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/substrate/client/network/src/litep2p/service.rs b/substrate/client/network/src/litep2p/service.rs index b05c79a638f51..307d071cd00cb 100644 --- a/substrate/client/network/src/litep2p/service.rs +++ b/substrate/client/network/src/litep2p/service.rs @@ -268,10 +268,7 @@ impl NetworkSigner for Litep2pNetworkService { let public_key = litep2p::crypto::RemotePublicKey::from_protobuf_encoding(&public_key) .map_err(|error| error.to_string())?; let peer: litep2p::PeerId = peer.into(); -<<<<<<< HEAD -======= ->>>>>>> origin/master Ok(peer == identity && public_key.verify(message, signature)) } } From 017535725209201a7bcd13370bc201bb9b589f00 Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Fri, 24 Oct 2025 18:23:22 +0300 Subject: [PATCH 08/13] minor: make taplo happy --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index cb0f73d4d7017..4e0b333922682 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -908,7 +908,7 @@ linked-hash-map = { version = "0.5.4" } linked_hash_set = { version = "0.1.4" } linregress = { version = "0.5.1" } lite-json = { version = "0.2.0", default-features = false } -litep2p = { git = "https://github.com/paritytech/litep2p.git", branch = "dm-add-provider-success", features = ["websocket", "rsa"] } +litep2p = { git = "https://github.com/paritytech/litep2p.git", branch = "dm-add-provider-success", features = ["rsa", "websocket"] } log = { version = "0.4.22", default-features = false } macro_magic = { version = "0.5.1" } maplit = { version = "1.0.2" } From f45636b4dd5d4d829f8f55a703bb8453b7c96724 Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Mon, 27 Oct 2025 14:39:37 +0200 Subject: [PATCH 09/13] Fix getting pending ADD_PROVIDER query --- substrate/client/network/src/litep2p/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/client/network/src/litep2p/mod.rs b/substrate/client/network/src/litep2p/mod.rs index adb180035bedf..2c8a988294afb 100644 --- a/substrate/client/network/src/litep2p/mod.rs +++ b/substrate/client/network/src/litep2p/mod.rs @@ -972,7 +972,7 @@ impl NetworkBackend for Litep2pNetworkBac } Some(DiscoveryEvent::AddProviderSuccess { query_id, provided_key }) => { match self.pending_queries.remove(&query_id) { - Some(KadQuery::GetProviders(key, started)) => { + Some(KadQuery::AddProvider(key, started)) => { debug_assert_eq!(key, provided_key.into()); log::trace!( From 81906e3e60c6002b60a06bf3e1225b8df5b55ca7 Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Tue, 11 Nov 2025 15:52:15 +0200 Subject: [PATCH 10/13] Point litep2p to crates.io release 0.12.0 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 4e0b333922682..ba9aeeb34cf82 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -908,7 +908,7 @@ linked-hash-map = { version = "0.5.4" } linked_hash_set = { version = "0.1.4" } linregress = { version = "0.5.1" } lite-json = { version = "0.2.0", default-features = false } -litep2p = { git = "https://github.com/paritytech/litep2p.git", branch = "dm-add-provider-success", features = ["rsa", "websocket"] } +litep2p = { version = "0.12.0", features = ["rsa", "websocket"] } log = { version = "0.4.22", default-features = false } macro_magic = { version = "0.5.1" } maplit = { version = "1.0.2" } From 86018664f43899eb26b623b1a71e4f8b97f0df6c Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Tue, 11 Nov 2025 15:54:26 +0200 Subject: [PATCH 11/13] Update Cargo.lock for litep2p 0.12.0 --- Cargo.lock | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index de84595bfd7ab..e8d8a73ec72b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1985,7 +1985,7 @@ dependencies = [ "bitflags 2.9.4", "cexpr", "clang-sys", - "itertools 0.11.0", + "itertools 0.13.0", "proc-macro2 1.0.95", "quote 1.0.40", "regex", @@ -8209,7 +8209,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.9", + "socket2 0.5.9", "tokio", "tower-service", "tracing", @@ -10054,8 +10054,9 @@ checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "litep2p" -version = "0.11.0" -source = "git+https://github.com/paritytech/litep2p.git?branch=dm-add-provider-success#b42583f6aaedaf7bc6e5174a780271615655999f" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1da54ffe750994080fe48ccf5dd298a528406b26b3b544032ae9505ff4d7cbea" dependencies = [ "async-trait", "bs58", @@ -18086,7 +18087,7 @@ checksum = "f8650aabb6c35b860610e9cff5dc1af886c9e25073b7b1712a68972af4281302" dependencies = [ "bytes", "heck 0.5.0", - "itertools 0.11.0", + "itertools 0.13.0", "log", "multimap", "once_cell", @@ -18106,7 +18107,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac6c3320f9abac597dcbc668774ef006702672474aad53c6d596b62e487b40b1" dependencies = [ "heck 0.5.0", - "itertools 0.11.0", + "itertools 0.14.0", "log", "multimap", "once_cell", @@ -18152,7 +18153,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.14.0", "proc-macro2 1.0.95", "quote 1.0.40", "syn 2.0.98", @@ -18165,7 +18166,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.14.0", "proc-macro2 1.0.95", "quote 1.0.40", "syn 2.0.98", From 61f74086c9ee5bd6f00985d17a8f320cecdd800c Mon Sep 17 00:00:00 2001 From: "cmd[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 11 Nov 2025 14:08:28 +0000 Subject: [PATCH 12/13] Update from github-actions[bot] running command 'prdoc --bump major --audience node_dev' --- prdoc/pr_9685.prdoc | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 prdoc/pr_9685.prdoc diff --git a/prdoc/pr_9685.prdoc b/prdoc/pr_9685.prdoc new file mode 100644 index 0000000000000..a6542bad74963 --- /dev/null +++ b/prdoc/pr_9685.prdoc @@ -0,0 +1,10 @@ +title: Upgrade litep2p to v0.12.0 +doc: +- audience: Node Dev + description: litep2p v0.12.0 adds ability to track whether publishing a DHT record + or provider was successful. This PR brings this functionality to substrate. Particularly, + this fixes authority-discovery unnecessarily republishing DHT records due to litep2p + not emitting `KademliaEvent::PutRecordSuccess` before v0.12.0. +crates: +- name: sc-network + bump: major From c879ef3c4859acb48d17e6e7bd4123ff31ad3499 Mon Sep 17 00:00:00 2001 From: Dmitry Markin Date: Tue, 11 Nov 2025 16:26:02 +0200 Subject: [PATCH 13/13] minor: add sc-network-types to prdoc --- prdoc/pr_9685.prdoc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/prdoc/pr_9685.prdoc b/prdoc/pr_9685.prdoc index a6542bad74963..e3b416c3ae20d 100644 --- a/prdoc/pr_9685.prdoc +++ b/prdoc/pr_9685.prdoc @@ -8,3 +8,5 @@ doc: crates: - name: sc-network bump: major +- name: sc-network-types + bump: major