Skip to content

Commit b56f7b1

Browse files
committed
pool: allow to set event limits per kind
Add `max_size_per_kind` and `max_num_tags_per_kind` hashmaps, to set specific limits per kind. Add methods to get limits per kind and automatically fallback to generic ones. Increase default kind 3 event limit to `840000` bytes and `10000` tags. Closes #430 Signed-off-by: Yuki Kishimoto <[email protected]>
1 parent e658a1b commit b56f7b1

File tree

10 files changed

+136
-11
lines changed

10 files changed

+136
-11
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,18 @@
77

88
## [Unreleased]
99

10+
### Summary
11+
12+
### Changed
13+
1014
### Added
1115

1216
* nostr: add `Tag::is_root` method ([Xiao Yu])
17+
* pool: allow to set event limits per kind ([Yuki Kishimoto])
18+
19+
### Fixed
20+
21+
### Removed
1322

1423
## [v0.31.0]
1524

bindings/nostr-sdk-ffi/src/client/options.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ impl Options {
110110
/// Set custom relay limits
111111
pub fn relay_limits(self: Arc<Self>, limits: &RelayLimits) -> Self {
112112
let mut builder = unwrap_or_clone_arc(self);
113-
builder.inner = builder.inner.relay_limits(**limits);
113+
builder.inner = builder.inner.relay_limits(limits.deref().clone());
114114
builder
115115
}
116116
}

bindings/nostr-sdk-ffi/src/relay/limits.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::ops::Deref;
66
use std::sync::Arc;
77

88
use nostr_ffi::helper::unwrap_or_clone_arc;
9+
use nostr_ffi::Kind;
910
use nostr_sdk::pool::relay;
1011
use uniffi::Object;
1112

@@ -56,10 +57,31 @@ impl RelayLimits {
5657
builder
5758
}
5859

60+
/// Maximum size per kind of normalised JSON, in bytes.
61+
pub fn event_max_size_per_kind(self: Arc<Self>, kind: &Kind, max_size: Option<u32>) -> Self {
62+
let mut builder = unwrap_or_clone_arc(self);
63+
builder.inner.events = builder.inner.events.set_max_size_per_kind(**kind, max_size);
64+
builder
65+
}
66+
5967
/// Maximum number of tags allowed (default: 2_000)
6068
pub fn event_max_num_tags(self: Arc<Self>, max_num_tags: Option<u16>) -> Self {
6169
let mut builder = unwrap_or_clone_arc(self);
6270
builder.inner.events.max_num_tags = max_num_tags;
6371
builder
6472
}
73+
74+
/// Maximum number of tags allowed per kind
75+
pub fn event_max_num_tags_per_kind(
76+
self: Arc<Self>,
77+
kind: &Kind,
78+
max_num_tags: Option<u16>,
79+
) -> Self {
80+
let mut builder = unwrap_or_clone_arc(self);
81+
builder.inner.events = builder
82+
.inner
83+
.events
84+
.set_max_num_tags_per_kind(**kind, max_num_tags);
85+
builder
86+
}
6587
}

bindings/nostr-sdk-ffi/src/relay/options.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ impl RelayOptions {
134134
/// Set custom limits
135135
pub fn limits(self: Arc<Self>, limits: &RelayLimits) -> Self {
136136
let mut builder = unwrap_or_clone_arc(self);
137-
builder.inner = builder.inner.limits(**limits);
137+
builder.inner = builder.inner.limits(limits.deref().clone());
138138
builder
139139
}
140140
}

bindings/nostr-sdk-js/src/client/options.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,6 @@ impl JsOptions {
9292
/// Set custom relay limits
9393
#[wasm_bindgen(js_name = relayLimits)]
9494
pub fn relay_limits(self, limits: &JsRelayLimits) -> Self {
95-
self.inner.relay_limits(**limits).into()
95+
self.inner.relay_limits(limits.deref().clone()).into()
9696
}
9797
}

bindings/nostr-sdk-js/src/relay/limits.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,30 @@ impl JsRelayLimits {
5252
self
5353
}
5454

55+
/// Maximum size per kind of normalised JSON, in bytes
56+
#[wasm_bindgen(js_name = eventMaxSizePerKind)]
57+
pub fn event_max_size_per_kind(mut self, kind: u16, max_size: Option<u32>) -> Self {
58+
self.inner.events = self
59+
.inner
60+
.events
61+
.set_max_size_per_kind(Kind::from(kind), max_size);
62+
self
63+
}
64+
5565
/// Maximum number of tags allowed (default: 2_000)
5666
#[wasm_bindgen(js_name = eventMaxNumTags)]
5767
pub fn event_max_num_tags(mut self, max_num_tags: Option<u16>) -> Self {
5868
self.inner.events.max_num_tags = max_num_tags;
5969
self
6070
}
71+
72+
/// Maximum number of tags per kind allowed
73+
#[wasm_bindgen(js_name = eventMaxNumTagsPerKind)]
74+
pub fn event_max_num_tags_per_kind(mut self, kind: u16, max_num_tags: Option<u16>) -> Self {
75+
self.inner.events = self
76+
.inner
77+
.events
78+
.set_max_num_tags_per_kind(Kind::from(kind), max_num_tags);
79+
self
80+
}
6181
}

bindings/nostr-sdk-js/src/relay/options.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ impl JsRelayOptions {
105105

106106
/// Set custom limits
107107
pub fn limits(self, limits: &JsRelayLimits) -> Self {
108-
self.inner.limits(**limits).into()
108+
self.inner.limits(limits.deref().clone()).into()
109109
}
110110
}
111111

crates/nostr-relay-pool/src/relay/internal.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use nostr::nips::nip01::Coordinate;
2323
use nostr::nips::nip11::RelayInformationDocument;
2424
use nostr::secp256k1::rand::{self, Rng};
2525
use nostr::{
26-
ClientMessage, Event, EventId, Filter, JsonUtil, Keys, MissingPartialEvent, PartialEvent,
26+
ClientMessage, Event, EventId, Filter, JsonUtil, Keys, Kind, MissingPartialEvent, PartialEvent,
2727
RawRelayMessage, RelayMessage, SubscriptionId, Timestamp, Url,
2828
};
2929
use nostr_database::{DynNostrDatabase, Order};
@@ -733,8 +733,10 @@ impl InternalRelay {
733733
subscription_id,
734734
event,
735735
} => {
736+
let kind: Kind = Kind::from(event.kind);
737+
736738
// Check event size
737-
if let Some(max_size) = self.opts.limits.events.max_size {
739+
if let Some(max_size) = self.opts.limits.events.get_max_size(&kind) {
738740
let size: usize = event.as_json().as_bytes().len();
739741
let max_size: usize = max_size as usize;
740742
if size > max_size {
@@ -743,7 +745,7 @@ impl InternalRelay {
743745
}
744746

745747
// Check tags limit
746-
if let Some(max_num_tags) = self.opts.limits.events.max_num_tags {
748+
if let Some(max_num_tags) = self.opts.limits.events.get_max_num_tags(&kind) {
747749
let size: usize = event.tags.len();
748750
let max_num_tags: usize = max_num_tags as usize;
749751
if size > max_num_tags {

crates/nostr-relay-pool/src/relay/limits.rs

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,15 @@
44

55
//! Relay limits
66
7+
use std::collections::HashMap;
8+
9+
use nostr::Kind;
10+
11+
const MAX_EVENT_SIZE: u32 = 70_000; // bytes
12+
const MAX_CONTACT_LIST_EVENT_SIZE: u32 = 840_000; // bytes
13+
714
/// Relay limits
8-
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
15+
#[derive(Debug, Clone, Default, PartialEq, Eq)]
916
pub struct RelayLimits {
1017
/// Message limits
1118
pub messages: RelayMessageLimits,
@@ -48,19 +55,31 @@ impl RelayMessageLimits {
4855
}
4956

5057
/// Events limits
51-
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
58+
#[derive(Debug, Clone, PartialEq, Eq)]
5259
pub struct RelayEventLimits {
5360
/// Maximum size of normalised JSON, in bytes (default: 70_000)
5461
pub max_size: Option<u32>,
62+
/// Maximum size of normalized JSON per [Kind], in bytes.
63+
pub max_size_per_kind: HashMap<Kind, Option<u32>>,
5564
/// Maximum number of tags allowed (default: 2_000)
5665
pub max_num_tags: Option<u16>,
66+
/// Maximum number of tags allowed per [Kind].
67+
pub max_num_tags_per_kind: HashMap<Kind, Option<u16>>,
5768
}
5869

5970
impl Default for RelayEventLimits {
6071
fn default() -> Self {
72+
let mut max_size_per_kind: HashMap<Kind, Option<u32>> = HashMap::with_capacity(1);
73+
max_size_per_kind.insert(Kind::ContactList, Some(MAX_CONTACT_LIST_EVENT_SIZE));
74+
75+
let mut max_num_tags_per_kind: HashMap<Kind, Option<u16>> = HashMap::with_capacity(1);
76+
max_num_tags_per_kind.insert(Kind::ContactList, Some(10_000));
77+
6178
Self {
62-
max_size: Some(70_000),
79+
max_size: Some(MAX_EVENT_SIZE),
80+
max_size_per_kind,
6381
max_num_tags: Some(2_000),
82+
max_num_tags_per_kind,
6483
}
6584
}
6685
}
@@ -71,7 +90,60 @@ impl RelayEventLimits {
7190
pub fn disable() -> Self {
7291
Self {
7392
max_size: None,
93+
max_size_per_kind: HashMap::new(),
7494
max_num_tags: None,
95+
max_num_tags_per_kind: HashMap::new(),
7596
}
7697
}
98+
99+
/// Add/Edit max size per [Kind]
100+
pub fn set_max_size_per_kind(mut self, kind: Kind, max_size: Option<u32>) -> Self {
101+
self.max_size_per_kind.insert(kind, max_size);
102+
self
103+
}
104+
105+
/// Add/Edit max number of tags per [Kind]
106+
pub fn set_max_num_tags_per_kind(mut self, kind: Kind, max_num_tags: Option<u16>) -> Self {
107+
self.max_num_tags_per_kind.insert(kind, max_num_tags);
108+
self
109+
}
110+
111+
/// Get max size for [Kind]
112+
///
113+
/// Fallback to `max_size` if no limit is specified for [Kind]
114+
pub fn get_max_size(&self, kind: &Kind) -> Option<u32> {
115+
match self.max_size_per_kind.get(kind).copied() {
116+
Some(limit) => limit,
117+
None => self.max_size,
118+
}
119+
}
120+
121+
/// Get max number of tags allowed for [Kind]
122+
///
123+
/// Fallback to `max_num_tags` if no limit is specified for [Kind]
124+
pub fn get_max_num_tags(&self, kind: &Kind) -> Option<u16> {
125+
match self.max_num_tags_per_kind.get(kind).copied() {
126+
Some(limit) => limit,
127+
None => self.max_num_tags,
128+
}
129+
}
130+
}
131+
132+
#[cfg(test)]
133+
mod tests {
134+
use super::*;
135+
136+
#[test]
137+
fn test_event_limits_get_max_size() {
138+
let limits = RelayLimits::default();
139+
140+
assert_eq!(
141+
limits.events.get_max_size(&Kind::TextNote),
142+
Some(MAX_EVENT_SIZE)
143+
);
144+
assert_eq!(
145+
limits.events.get_max_size(&Kind::ContactList),
146+
Some(MAX_CONTACT_LIST_EVENT_SIZE)
147+
);
148+
}
77149
}

crates/nostr-sdk/src/client/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ impl Client {
408408
// Set min POW difficulty and limits
409409
let opts: RelayOptions = opts
410410
.pow(self.opts.get_min_pow_difficulty())
411-
.limits(self.opts.relay_limits);
411+
.limits(self.opts.relay_limits.clone());
412412

413413
// Add relay
414414
self.add_relay_with_opts::<Url>(url, opts).await

0 commit comments

Comments
 (0)