Skip to content

Commit 0043f6b

Browse files
authored
feat: add max-radius param with 5% default (#1647)
1 parent 3b5056d commit 0043f6b

File tree

12 files changed

+100
-31
lines changed

12 files changed

+100
-31
lines changed

bin/trin/src/cli.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use clap::{
99
};
1010
use ethportal_api::{
1111
types::{
12+
distance::Distance,
1213
network::Subnetwork,
1314
portal_wire::{NetworkSpec, MAINNET},
1415
},
@@ -25,11 +26,14 @@ use portalnet::{
2526
use rpc::config::RpcConfig;
2627
use trin_storage::config::StorageCapacityConfig;
2728
use trin_utils::cli::{
28-
check_private_key_length, network_parser, subnetwork_parser, Web3TransportType,
29+
check_private_key_length, max_radius_parser, network_parser, subnetwork_parser,
30+
Web3TransportType,
2931
};
3032
use url::Url;
3133

3234
const DEFAULT_SUBNETWORKS: &str = "history";
35+
/// Default max radius value percentage out of 100.
36+
const DEFAULT_MAX_RADIUS: &str = "5";
3337
pub const DEFAULT_STORAGE_CAPACITY_MB: &str = "1000";
3438
pub const DEFAULT_WEB3_TRANSPORT: &str = "ipc";
3539

@@ -204,6 +208,14 @@ pub struct TrinConfig {
204208
default_value_t = DEFAULT_UTP_TRANSFER_LIMIT,
205209
)]
206210
pub utp_transfer_limit: usize,
211+
212+
#[arg(
213+
long,
214+
help = "The maximum radius our node will use. The default is 5% of the network size. The max is 100%",
215+
default_value = DEFAULT_MAX_RADIUS,
216+
value_parser = max_radius_parser,
217+
)]
218+
pub max_radius: Distance,
207219
}
208220

209221
impl Default for TrinConfig {
@@ -235,6 +247,8 @@ impl Default for TrinConfig {
235247
ws_port: DEFAULT_WEB3_WS_PORT,
236248
utp_transfer_limit: DEFAULT_UTP_TRANSFER_LIMIT,
237249
network: MAINNET.clone(),
250+
max_radius: max_radius_parser(DEFAULT_MAX_RADIUS)
251+
.expect("Parsing static DEFAULT_MAX_RADIUS to work"),
238252
}
239253
}
240254
}

bin/trin/src/lib.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ use std::sync::Arc;
77

88
use cli::TrinConfig;
99
use ethportal_api::{
10-
types::network::Subnetwork, utils::bytes::hex_encode, version::get_trin_version,
10+
types::{distance::Distance, network::Subnetwork},
11+
utils::bytes::hex_encode,
12+
version::get_trin_version,
1113
};
1214
use portalnet::{
1315
discovery::{Discovery, Discv5UdpSocket},
@@ -103,7 +105,7 @@ pub async fn run_trin(
103105
&discovery,
104106
utp_socket.clone(),
105107
portalnet_config.clone(),
106-
storage_config_factory.create(&Subnetwork::State)?,
108+
storage_config_factory.create(&Subnetwork::State, trin_config.max_radius)?,
107109
header_oracle.clone(),
108110
)
109111
.await?
@@ -123,7 +125,7 @@ pub async fn run_trin(
123125
&discovery,
124126
utp_socket.clone(),
125127
portalnet_config.clone(),
126-
storage_config_factory.create(&Subnetwork::Beacon)?,
128+
storage_config_factory.create(&Subnetwork::Beacon, Distance::MAX)?,
127129
header_oracle.clone(),
128130
)
129131
.await?
@@ -146,7 +148,7 @@ pub async fn run_trin(
146148
&discovery,
147149
utp_socket.clone(),
148150
portalnet_config.clone(),
149-
storage_config_factory.create(&Subnetwork::History)?,
151+
storage_config_factory.create(&Subnetwork::History, trin_config.max_radius)?,
150152
header_oracle.clone(),
151153
)
152154
.await?

crates/storage/src/config.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::path::PathBuf;
22

33
use discv5::enr::NodeId;
4-
use ethportal_api::types::network::Subnetwork;
4+
use ethportal_api::types::{distance::Distance, network::Subnetwork};
55
use r2d2::Pool;
66
use r2d2_sqlite::SqliteConnectionManager;
77

@@ -54,6 +54,7 @@ impl PortalStorageConfigFactory {
5454
pub fn create(
5555
&self,
5656
subnetwork: &Subnetwork,
57+
max_radius: Distance,
5758
) -> Result<PortalStorageConfig, ContentStoreError> {
5859
let capacity_bytes = match &self.capacity_config {
5960
StorageCapacityConfig::Combined {
@@ -104,6 +105,7 @@ impl PortalStorageConfigFactory {
104105
node_data_dir: self.node_data_dir.clone(),
105106
distance_fn: DistanceFunction::Xor,
106107
sql_connection_pool: self.sql_connection_pool.clone(),
108+
max_radius,
107109
})
108110
}
109111

@@ -124,6 +126,7 @@ pub struct PortalStorageConfig {
124126
pub node_data_dir: PathBuf,
125127
pub distance_fn: DistanceFunction,
126128
pub sql_connection_pool: Pool<SqliteConnectionManager>,
129+
pub max_radius: Distance,
127130
}
128131

129132
#[cfg(test)]
@@ -167,11 +170,11 @@ mod tests {
167170
.unwrap();
168171
match expected_capacity_bytes {
169172
Some(expected_capacity_bytes) => {
170-
let config = factory.create(&subnetwork).unwrap();
173+
let config = factory.create(&subnetwork, Distance::MAX).unwrap();
171174
assert_eq!(config.storage_capacity_bytes, expected_capacity_bytes);
172175
}
173176
None => assert!(
174-
factory.create(&subnetwork).is_err(),
177+
factory.create(&subnetwork, Distance::MAX).is_err(),
175178
"Storage config is expected to fail"
176179
),
177180
}
@@ -193,21 +196,21 @@ mod tests {
193196
.unwrap();
194197
assert_eq!(
195198
factory
196-
.create(&Subnetwork::Beacon)
199+
.create(&Subnetwork::Beacon, Distance::MAX)
197200
.unwrap()
198201
.storage_capacity_bytes,
199202
100_000_000,
200203
);
201204
assert_eq!(
202205
factory
203-
.create(&Subnetwork::History)
206+
.create(&Subnetwork::History, Distance::MAX)
204207
.unwrap()
205208
.storage_capacity_bytes,
206209
200_000_000,
207210
);
208211
assert_eq!(
209212
factory
210-
.create(&Subnetwork::State)
213+
.create(&Subnetwork::State, Distance::MAX)
211214
.unwrap()
212215
.storage_capacity_bytes,
213216
300_000_000,
@@ -230,17 +233,17 @@ mod tests {
230233
.unwrap();
231234
assert_eq!(
232235
factory
233-
.create(&Subnetwork::History)
236+
.create(&Subnetwork::History, Distance::MAX)
234237
.unwrap()
235238
.storage_capacity_bytes,
236239
100_000_000,
237240
);
238241
assert!(
239-
factory.create(&Subnetwork::Beacon).is_err(),
242+
factory.create(&Subnetwork::Beacon, Distance::MAX).is_err(),
240243
"Creating for Beacon should fail"
241244
);
242245
assert!(
243-
factory.create(&Subnetwork::State).is_err(),
246+
factory.create(&Subnetwork::State, Distance::MAX).is_err(),
244247
"Creating for State should fail"
245248
);
246249
temp_dir.close().unwrap();
@@ -261,19 +264,19 @@ mod tests {
261264
.unwrap();
262265
assert_eq!(
263266
factory
264-
.create(&Subnetwork::Beacon)
267+
.create(&Subnetwork::Beacon, Distance::MAX)
265268
.unwrap()
266269
.storage_capacity_bytes,
267270
0,
268271
);
269272
assert_eq!(
270273
factory
271-
.create(&Subnetwork::History)
274+
.create(&Subnetwork::History, Distance::MAX)
272275
.unwrap()
273276
.storage_capacity_bytes,
274277
100_000_000,
275278
);
276-
assert!(factory.create(&Subnetwork::State).is_err());
279+
assert!(factory.create(&Subnetwork::State, Distance::MAX).is_err());
277280
temp_dir.close().unwrap();
278281
}
279282
}

crates/storage/src/test_utils.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use discv5::enr::NodeId;
2-
use ethportal_api::types::network::Subnetwork;
2+
use ethportal_api::types::{distance::Distance, network::Subnetwork};
33
use tempfile::TempDir;
44

55
use crate::{
@@ -21,7 +21,7 @@ pub fn create_test_portal_storage_config_with_capacity(
2121
temp_dir.path().to_path_buf(),
2222
)
2323
.unwrap()
24-
.create(&Subnetwork::History)
24+
.create(&Subnetwork::History, Distance::MAX)
2525
.unwrap();
2626
Ok((temp_dir, config))
2727
}

crates/storage/src/versioned/id_indexed_v1/config.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::path::PathBuf;
22

33
use discv5::enr::NodeId;
4-
use ethportal_api::types::network::Subnetwork;
4+
use ethportal_api::types::{distance::Distance, network::Subnetwork};
55
use r2d2::Pool;
66
use r2d2_sqlite::SqliteConnectionManager;
77

@@ -19,6 +19,7 @@ pub struct IdIndexedV1StoreConfig {
1919
pub sql_connection_pool: Pool<SqliteConnectionManager>,
2020
pub distance_fn: DistanceFunction,
2121
pub pruning_config: PruningConfig,
22+
pub max_radius: Distance,
2223
}
2324

2425
impl IdIndexedV1StoreConfig {
@@ -37,6 +38,7 @@ impl IdIndexedV1StoreConfig {
3738
distance_fn: config.distance_fn,
3839
// consider making this a parameter if we start using non-default value
3940
pruning_config: PruningConfig::default(),
41+
max_radius: config.max_radius,
4042
}
4143
}
4244
}

crates/storage/src/versioned/id_indexed_v1/pruning_strategy.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ mod tests {
196196
use std::path::PathBuf;
197197

198198
use discv5::enr::NodeId;
199-
use ethportal_api::types::network::Subnetwork;
199+
use ethportal_api::types::{distance::Distance, network::Subnetwork};
200200
use r2d2::Pool;
201201
use r2d2_sqlite::SqliteConnectionManager;
202202
use rstest::rstest;
@@ -220,6 +220,7 @@ mod tests {
220220
sql_connection_pool: Pool::new(SqliteConnectionManager::memory()).unwrap(),
221221
distance_fn: DistanceFunction::Xor,
222222
pruning_config: PruningConfig::default(),
223+
max_radius: Distance::MAX,
223224
};
224225
PruningStrategy::new(config)
225226
}

crates/storage/src/versioned/id_indexed_v1/store.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::marker::PhantomData;
1+
use std::{cmp::min, marker::PhantomData};
22

33
use ethportal_api::{types::distance::Distance, OverlayContentKey, RawContentValue};
44
use r2d2::Pool;
@@ -84,12 +84,12 @@ impl<TContentKey: OverlayContentKey> VersionedContentStore for IdIndexedV1Store<
8484
let pruning_strategy = PruningStrategy::new(config.clone());
8585

8686
let mut store = Self {
87-
config,
88-
radius: Distance::MAX,
87+
radius: config.max_radius,
8988
pruning_strategy,
9089
usage_stats: UsageStats::default(),
9190
metrics: StorageMetricsReporter::new(subnetwork),
9291
_phantom_content_key: PhantomData,
92+
config,
9393
};
9494
store.init()?;
9595
Ok(store)
@@ -133,11 +133,12 @@ impl<TContentKey: OverlayContentKey> IdIndexedV1Store<TContentKey> {
133133
} else {
134134
debug!(
135135
Db = %self.config.content_type,
136-
"Used capacity ({}) is below target capacity ({}) -> Using MAX radius",
136+
"Used capacity ({}) is below target capacity ({}) -> Using MAX radius ({})",
137137
self.usage_stats.total_entry_size_bytes,
138-
self.pruning_strategy.target_capacity_bytes()
138+
self.pruning_strategy.target_capacity_bytes(),
139+
self.config.max_radius,
139140
);
140-
self.radius = Distance::MAX;
141+
self.radius = self.config.max_radius;
141142
self.metrics.report_radius(self.radius);
142143
}
143144

@@ -420,7 +421,7 @@ impl<TContentKey: OverlayContentKey> IdIndexedV1Store<TContentKey> {
420421

421422
/// Sets `self.radius` to the distance to the farthest stored content.
422423
///
423-
/// If no content is found, it sets radius to `Distance::MAX`.
424+
/// If no content is found, it sets radius to `config.max_radius`.
424425
fn set_radius_to_farthest(&mut self) -> Result<(), ContentStoreError> {
425426
match self.lookup_farthest()? {
426427
None => {
@@ -432,11 +433,14 @@ impl<TContentKey: OverlayContentKey> IdIndexedV1Store<TContentKey> {
432433
self.radius = Distance::ZERO;
433434
} else {
434435
error!(Db = %self.config.content_type, "Farthest not found!");
435-
self.radius = Distance::MAX;
436+
self.radius = self.config.max_radius;
436437
}
437438
}
438439
Some(farthest) => {
439-
self.radius = self.distance_to_content_id(&farthest.content_id);
440+
self.radius = min(
441+
self.distance_to_content_id(&farthest.content_id),
442+
self.config.max_radius,
443+
);
440444
}
441445
}
442446
self.metrics.report_radius(self.radius);
@@ -572,6 +576,7 @@ mod tests {
572576
sql_connection_pool: setup_sql(temp_dir.path()).unwrap(),
573577
storage_capacity_bytes,
574578
pruning_config: PruningConfig::default(),
579+
max_radius: Distance::MAX,
575580
}
576581
}
577582

crates/utils/src/cli.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use core::fmt;
22
use std::{str::FromStr, sync::Arc};
33

4-
use alloy::primitives::B256;
4+
use alloy::primitives::{B256, U256};
55
use ethportal_api::types::{
6+
distance::Distance,
67
network::Subnetwork,
78
portal_wire::{NetworkSpec, ANGELFOOD, MAINNET},
89
};
@@ -72,3 +73,30 @@ pub fn subnetwork_parser(subnetwork_string: &str) -> Result<Arc<Vec<Subnetwork>>
7273

7374
Ok(Arc::new(subnetworks))
7475
}
76+
77+
pub fn max_radius_parser(max_radius_str: &str) -> Result<Distance, String> {
78+
let max_radius_percentage = match max_radius_str.parse::<U256>() {
79+
Ok(val) => val,
80+
Err(err) => {
81+
return Err(format!(
82+
"Invalid max radius percentage, expected a number, received: {err}"
83+
))
84+
}
85+
};
86+
87+
if max_radius_percentage > U256::from(100) {
88+
return Err(format!(
89+
"Invalid max radius percentage, expected 0 to 100, received: {max_radius_percentage}"
90+
));
91+
}
92+
93+
// If the max radius is 100% return it, as arithmetic multiplication loses precision and will be
94+
// off by 5.
95+
if max_radius_percentage == U256::from(100) {
96+
return Ok(Distance::MAX);
97+
}
98+
99+
Ok(Distance::from(
100+
U256::MAX / U256::from(100) * max_radius_percentage,
101+
))
102+
}

testing/ethportal-peertest/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ fn generate_trin_config(
108108
"--unsafe-private-key",
109109
private_key.as_str(),
110110
"--ephemeral",
111+
"--max-radius",
112+
"100",
111113
];
112114
TrinConfig::new_from(trin_config_args).unwrap()
113115
}

testing/ethportal-peertest/src/scenarios/put_content.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,8 @@ fn fresh_node_config() -> (String, TrinConfig) {
365365
test_discovery_port.to_string().as_ref(),
366366
"--bootnodes",
367367
"none",
368+
"--max-radius",
369+
"100",
368370
"--unsafe-private-key",
369371
// node id: 0x27128939ed60d6f4caef0374da15361a2c1cd6baa1a5bccebac1acd18f485900
370372
"0x9ca7889c09ef1162132251b6284bd48e64bd3e71d75ea33b959c37be0582a2fd",

0 commit comments

Comments
 (0)