Skip to content

Commit

Permalink
sdk: refactor POW difficulty management
Browse files Browse the repository at this point in the history
Moving min POW from `Options` to `SharedState`. This change allows changing min POW of all relays from `Client`

Signed-off-by: Yuki Kishimoto <[email protected]>
  • Loading branch information
yukibtc committed Dec 10, 2024
1 parent be0a602 commit 36dd68a
Show file tree
Hide file tree
Showing 8 changed files with 38 additions and 67 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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])

Expand Down
12 changes: 0 additions & 12 deletions bindings/nostr-sdk-ffi/src/relay/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
10 changes: 0 additions & 10 deletions bindings/nostr-sdk-js/src/relay/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion crates/nostr-relay-pool/src/relay/inner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
}
Expand Down
18 changes: 2 additions & 16 deletions crates/nostr-relay-pool/src/relay/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

//! Relay options
use std::sync::atomic::{AtomicU8, Ordering};
use std::sync::Arc;
use std::time::Duration;

use async_wsocket::ConnectionMode;
Expand All @@ -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<AtomicU8>,
pub(super) reconnect: bool,
pub(super) retry_interval: Duration,
pub(super) adjust_retry_interval: bool,
Expand All @@ -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,
Expand Down Expand Up @@ -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;
Expand Down
21 changes: 20 additions & 1 deletion crates/nostr-relay-pool/src/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -35,6 +35,7 @@ pub struct SharedState {
pub(crate) database: Arc<dyn NostrDatabase>,
signer: Arc<RwLock<Option<Arc<dyn NostrSigner>>>>,
nip42_auto_authentication: Arc<AtomicBool>,
min_pow_difficulty: Arc<AtomicU8>,
pub(crate) filtering: RelayFiltering,
}

Expand All @@ -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(),
}
}
Expand All @@ -55,12 +57,14 @@ impl SharedState {
signer: Option<Arc<dyn NostrSigner>>,
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)),
}
}

Expand All @@ -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.
///
/// <https://github.com/nostr-protocol/nips/blob/master/42.md>
#[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<dyn NostrDatabase> {
Expand Down
19 changes: 9 additions & 10 deletions crates/nostr-sdk/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ impl Client {
builder.signer,
builder.opts.filtering_mode,
builder.opts.nip42_auto_authentication,
builder.opts.min_pow_difficulty,
);

// Construct client
Expand All @@ -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)
Expand Down Expand Up @@ -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)
}

Expand Down
21 changes: 4 additions & 17 deletions crates/nostr-sdk/src/client/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;
Expand All @@ -18,7 +16,7 @@ use nostr_relay_pool::prelude::*;
#[derive(Debug, Clone)]
pub struct Options {
pub(super) autoconnect: bool,
min_pow_difficulty: Arc<AtomicU8>,
pub(super) min_pow_difficulty: u8,
pub(super) req_filters_chunk_size: u8,
pub(super) nip42_auto_authentication: bool,
pub(super) gossip: bool,
Expand All @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit 36dd68a

Please sign in to comment.