diff --git a/CHANGELOG.md b/CHANGELOG.md index c5ecce4a1..f76fdc0ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,7 @@ * ndb: bump `nostr-ndb` to 0.4 ([Yuki Kishimoto]) * pool: add `PingTracker` and improve relay ping management ([Yuki Kishimoto]) * pool: cleanup relay `Error` variants ([Yuki Kishimoto]) +* sdk: refactor POW difficulty management ([Yuki Kishimoto]) ### Added @@ -71,6 +72,7 @@ * nostr: remove redundant NIP10 tags from `EventBuilder::text_note_reply` ([Yuki Kishimoto]) * sdk: fix NIP42 authentication for auto-closing REQ ([Yuki Kishimoto]) +* sdk: fix min POW is not updated to already existing relays ([Yuki Kishimoto]) * bindings: allow passing empty string as relay url without return an error ([Yuki Kishimoto]) * flutter: fix `default` is reserved in dart ([J. Azad EMERY]) diff --git a/bindings/nostr-sdk-ffi/src/relay/options.rs b/bindings/nostr-sdk-ffi/src/relay/options.rs index 1d768e8a0..f5e8701dc 100644 --- a/bindings/nostr-sdk-ffi/src/relay/options.rs +++ b/bindings/nostr-sdk-ffi/src/relay/options.rs @@ -112,18 +112,6 @@ impl RelayOptions { builder } - /// Minimum POW for received events (default: 0) - pub fn pow(&self, difficulty: u8) -> Self { - let mut builder = self.clone(); - builder.inner = builder.inner.pow(difficulty); - builder - } - - /// Update `pow` option - pub fn update_pow_difficulty(&self, difficulty: u8) { - self.inner.update_pow_difficulty(difficulty); - } - /// Enable/disable auto reconnection (default: true) pub fn reconnect(&self, reconnect: bool) -> Self { let mut builder = self.clone(); diff --git a/bindings/nostr-sdk-js/src/relay/options.rs b/bindings/nostr-sdk-js/src/relay/options.rs index d58b29f56..0dc347ed8 100644 --- a/bindings/nostr-sdk-js/src/relay/options.rs +++ b/bindings/nostr-sdk-js/src/relay/options.rs @@ -62,16 +62,6 @@ impl JsRelayOptions { self.inner.ping(ping).into() } - /// Minimum POW for received events (default: 0) - pub fn pow(self, difficulty: u8) -> Self { - self.inner.pow(difficulty).into() - } - - /// Update `pow` option - pub fn update_pow_difficulty(&self, difficulty: u8) { - self.inner.update_pow_difficulty(difficulty); - } - /// Enable/disable auto reconnection (default: true) pub fn reconnect(self, reconnect: bool) -> Self { self.inner.reconnect(reconnect).into() diff --git a/crates/nostr-relay-pool/src/relay/inner.rs b/crates/nostr-relay-pool/src/relay/inner.rs index 851ff85cf..9b3fb5b92 100644 --- a/crates/nostr-relay-pool/src/relay/inner.rs +++ b/crates/nostr-relay-pool/src/relay/inner.rs @@ -995,7 +995,7 @@ impl InnerRelay { } // Check min POW - let difficulty: u8 = self.opts.get_pow_difficulty(); + let difficulty: u8 = self.state.minimum_pow_difficulty(); if difficulty > 0 && !partial_event.id.check_pow(difficulty) { return Err(Error::PowDifficultyTooLow { min: difficulty }); } diff --git a/crates/nostr-relay-pool/src/relay/options.rs b/crates/nostr-relay-pool/src/relay/options.rs index 44ae828db..7c9648f92 100644 --- a/crates/nostr-relay-pool/src/relay/options.rs +++ b/crates/nostr-relay-pool/src/relay/options.rs @@ -4,8 +4,6 @@ //! Relay options -use std::sync::atomic::{AtomicU8, Ordering}; -use std::sync::Arc; use std::time::Duration; use async_wsocket::ConnectionMode; @@ -21,8 +19,6 @@ use crate::RelayLimits; pub struct RelayOptions { pub(super) connection_mode: ConnectionMode, pub(super) flags: RelayServiceFlags, - // TODO: what to do with this atomic? - pow: Arc, pub(super) reconnect: bool, pub(super) retry_interval: Duration, pub(super) adjust_retry_interval: bool, @@ -36,7 +32,6 @@ impl Default for RelayOptions { Self { connection_mode: ConnectionMode::default(), flags: RelayServiceFlags::default(), - pow: Arc::new(AtomicU8::new(0)), reconnect: true, retry_interval: DEFAULT_RETRY_INTERVAL, adjust_retry_interval: true, @@ -98,20 +93,11 @@ impl RelayOptions { } /// Minimum POW for received events (default: 0) - pub fn pow(mut self, difficulty: u8) -> Self { - self.pow = Arc::new(AtomicU8::new(difficulty)); + #[deprecated(since = "0.38.0")] + pub fn pow(self, _difficulty: u8) -> Self { self } - pub(crate) fn get_pow_difficulty(&self) -> u8 { - self.pow.load(Ordering::SeqCst) - } - - /// Set `pow` option - pub fn update_pow_difficulty(&self, difficulty: u8) { - self.pow.store(difficulty, Ordering::SeqCst); - } - /// Enable/disable auto reconnection (default: true) pub fn reconnect(mut self, reconnect: bool) -> Self { self.reconnect = reconnect; diff --git a/crates/nostr-relay-pool/src/shared.rs b/crates/nostr-relay-pool/src/shared.rs index 82132d303..1ac897db4 100644 --- a/crates/nostr-relay-pool/src/shared.rs +++ b/crates/nostr-relay-pool/src/shared.rs @@ -3,7 +3,7 @@ // Distributed under the MIT software license use std::fmt; -use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::atomic::{AtomicBool, AtomicU8, Ordering}; use std::sync::Arc; use nostr::prelude::IntoNostrSigner; @@ -35,6 +35,7 @@ pub struct SharedState { pub(crate) database: Arc, signer: Arc>>>, nip42_auto_authentication: Arc, + min_pow_difficulty: Arc, pub(crate) filtering: RelayFiltering, } @@ -44,6 +45,7 @@ impl Default for SharedState { database: MemoryDatabase::new().into_nostr_database(), signer: Arc::new(RwLock::new(None)), nip42_auto_authentication: Arc::new(AtomicBool::new(true)), + min_pow_difficulty: Arc::new(AtomicU8::new(0)), filtering: RelayFiltering::default(), } } @@ -55,12 +57,14 @@ impl SharedState { signer: Option>, filtering_mode: RelayFilteringMode, nip42_auto_authentication: bool, + min_pow_difficulty: u8, ) -> Self { Self { database, signer: Arc::new(RwLock::new(signer)), nip42_auto_authentication: Arc::new(AtomicBool::new(nip42_auto_authentication)), filtering: RelayFiltering::new(filtering_mode), + min_pow_difficulty: Arc::new(AtomicU8::new(min_pow_difficulty)), } } @@ -78,6 +82,21 @@ impl SharedState { .store(enable, Ordering::SeqCst); } + /// Minimum POW difficulty for received events + /// + /// All received events must have a difficulty equal or greater than the set one. + /// + /// + #[inline] + pub fn set_pow(&self, difficulty: u8) { + self.min_pow_difficulty.store(difficulty, Ordering::SeqCst); + } + + #[inline] + pub(crate) fn minimum_pow_difficulty(&self) -> u8 { + self.min_pow_difficulty.load(Ordering::SeqCst) + } + /// Get database #[inline] pub fn database(&self) -> &Arc { diff --git a/crates/nostr-sdk/src/client/mod.rs b/crates/nostr-sdk/src/client/mod.rs index eab051119..6f7914bd9 100644 --- a/crates/nostr-sdk/src/client/mod.rs +++ b/crates/nostr-sdk/src/client/mod.rs @@ -163,6 +163,7 @@ impl Client { builder.signer, builder.opts.filtering_mode, builder.opts.nip42_auto_authentication, + builder.opts.min_pow_difficulty, ); // Construct client @@ -179,16 +180,16 @@ impl Client { #[deprecated(since = "0.38.0")] pub fn update_difficulty(&self, _difficulty: u8) {} + #[inline] + fn state(&self) -> &SharedState { + self.pool.state() + } + /// Update minimum POW difficulty for received events /// /// Events with a POW lower than the current value will be ignored to prevent resources exhaustion. pub fn update_min_pow_difficulty(&self, difficulty: u8) { - self.opts.update_min_pow_difficulty(difficulty); - } - - #[inline] - fn state(&self) -> &SharedState { - self.pool.state() + self.state().set_pow(difficulty); } /// Auto authenticate to relays (default: true) @@ -366,10 +367,8 @@ impl Client { }, }; - // Set min POW difficulty and limits - // TODO: when min POW is updated in the client, the relays POW is not updated! - opts.pow(self.opts.get_min_pow_difficulty()) - .limits(self.opts.relay_limits.clone()) + // Set limits + opts.limits(self.opts.relay_limits.clone()) .max_avg_latency(self.opts.max_avg_latency) } diff --git a/crates/nostr-sdk/src/client/options.rs b/crates/nostr-sdk/src/client/options.rs index 53fc398c5..718a46e10 100644 --- a/crates/nostr-sdk/src/client/options.rs +++ b/crates/nostr-sdk/src/client/options.rs @@ -8,8 +8,6 @@ use std::net::SocketAddr; #[cfg(all(feature = "tor", any(target_os = "android", target_os = "ios")))] use std::path::Path; -use std::sync::atomic::{AtomicU8, Ordering}; -use std::sync::Arc; use std::time::Duration; use nostr_relay_pool::prelude::*; @@ -18,7 +16,7 @@ use nostr_relay_pool::prelude::*; #[derive(Debug, Clone)] pub struct Options { pub(super) autoconnect: bool, - min_pow_difficulty: Arc, + pub(super) min_pow_difficulty: u8, pub(super) req_filters_chunk_size: u8, pub(super) nip42_auto_authentication: bool, pub(super) gossip: bool, @@ -34,7 +32,7 @@ impl Default for Options { fn default() -> Self { Self { autoconnect: false, - min_pow_difficulty: Arc::new(AtomicU8::new(0)), + min_pow_difficulty: 0, req_filters_chunk_size: 10, nip42_auto_authentication: true, gossip: false, @@ -70,24 +68,13 @@ impl Options { self } - /// Minimum POW difficulty for received events + /// Minimum POW difficulty for received events (default: 0) #[inline] pub fn min_pow(mut self, difficulty: u8) -> Self { - self.min_pow_difficulty = Arc::new(AtomicU8::new(difficulty)); + self.min_pow_difficulty = difficulty; self } - #[inline] - pub(crate) fn get_min_pow_difficulty(&self) -> u8 { - self.min_pow_difficulty.load(Ordering::SeqCst) - } - - /// Update minimum POW difficulty for received events - #[inline] - pub fn update_min_pow_difficulty(&self, difficulty: u8) { - self.min_pow_difficulty.store(difficulty, Ordering::SeqCst); - } - /// REQ filters chunk size (default: 10) #[inline] pub fn req_filters_chunk_size(mut self, size: u8) -> Self {