Skip to content

Commit

Permalink
feat: add max-radius param with 5% default (ethereum#1647)
Browse files Browse the repository at this point in the history
  • Loading branch information
KolbyML authored Feb 4, 2025
1 parent 3b5056d commit 0043f6b
Show file tree
Hide file tree
Showing 12 changed files with 100 additions and 31 deletions.
16 changes: 15 additions & 1 deletion bin/trin/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use clap::{
};
use ethportal_api::{
types::{
distance::Distance,
network::Subnetwork,
portal_wire::{NetworkSpec, MAINNET},
},
Expand All @@ -25,11 +26,14 @@ use portalnet::{
use rpc::config::RpcConfig;
use trin_storage::config::StorageCapacityConfig;
use trin_utils::cli::{
check_private_key_length, network_parser, subnetwork_parser, Web3TransportType,
check_private_key_length, max_radius_parser, network_parser, subnetwork_parser,
Web3TransportType,
};
use url::Url;

const DEFAULT_SUBNETWORKS: &str = "history";
/// Default max radius value percentage out of 100.
const DEFAULT_MAX_RADIUS: &str = "5";
pub const DEFAULT_STORAGE_CAPACITY_MB: &str = "1000";
pub const DEFAULT_WEB3_TRANSPORT: &str = "ipc";

Expand Down Expand Up @@ -204,6 +208,14 @@ pub struct TrinConfig {
default_value_t = DEFAULT_UTP_TRANSFER_LIMIT,
)]
pub utp_transfer_limit: usize,

#[arg(
long,
help = "The maximum radius our node will use. The default is 5% of the network size. The max is 100%",
default_value = DEFAULT_MAX_RADIUS,
value_parser = max_radius_parser,
)]
pub max_radius: Distance,
}

impl Default for TrinConfig {
Expand Down Expand Up @@ -235,6 +247,8 @@ impl Default for TrinConfig {
ws_port: DEFAULT_WEB3_WS_PORT,
utp_transfer_limit: DEFAULT_UTP_TRANSFER_LIMIT,
network: MAINNET.clone(),
max_radius: max_radius_parser(DEFAULT_MAX_RADIUS)
.expect("Parsing static DEFAULT_MAX_RADIUS to work"),
}
}
}
Expand Down
10 changes: 6 additions & 4 deletions bin/trin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ use std::sync::Arc;

use cli::TrinConfig;
use ethportal_api::{
types::network::Subnetwork, utils::bytes::hex_encode, version::get_trin_version,
types::{distance::Distance, network::Subnetwork},
utils::bytes::hex_encode,
version::get_trin_version,
};
use portalnet::{
discovery::{Discovery, Discv5UdpSocket},
Expand Down Expand Up @@ -103,7 +105,7 @@ pub async fn run_trin(
&discovery,
utp_socket.clone(),
portalnet_config.clone(),
storage_config_factory.create(&Subnetwork::State)?,
storage_config_factory.create(&Subnetwork::State, trin_config.max_radius)?,
header_oracle.clone(),
)
.await?
Expand All @@ -123,7 +125,7 @@ pub async fn run_trin(
&discovery,
utp_socket.clone(),
portalnet_config.clone(),
storage_config_factory.create(&Subnetwork::Beacon)?,
storage_config_factory.create(&Subnetwork::Beacon, Distance::MAX)?,
header_oracle.clone(),
)
.await?
Expand All @@ -146,7 +148,7 @@ pub async fn run_trin(
&discovery,
utp_socket.clone(),
portalnet_config.clone(),
storage_config_factory.create(&Subnetwork::History)?,
storage_config_factory.create(&Subnetwork::History, trin_config.max_radius)?,
header_oracle.clone(),
)
.await?
Expand Down
27 changes: 15 additions & 12 deletions crates/storage/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::path::PathBuf;

use discv5::enr::NodeId;
use ethportal_api::types::network::Subnetwork;
use ethportal_api::types::{distance::Distance, network::Subnetwork};
use r2d2::Pool;
use r2d2_sqlite::SqliteConnectionManager;

Expand Down Expand Up @@ -54,6 +54,7 @@ impl PortalStorageConfigFactory {
pub fn create(
&self,
subnetwork: &Subnetwork,
max_radius: Distance,
) -> Result<PortalStorageConfig, ContentStoreError> {
let capacity_bytes = match &self.capacity_config {
StorageCapacityConfig::Combined {
Expand Down Expand Up @@ -104,6 +105,7 @@ impl PortalStorageConfigFactory {
node_data_dir: self.node_data_dir.clone(),
distance_fn: DistanceFunction::Xor,
sql_connection_pool: self.sql_connection_pool.clone(),
max_radius,
})
}

Expand All @@ -124,6 +126,7 @@ pub struct PortalStorageConfig {
pub node_data_dir: PathBuf,
pub distance_fn: DistanceFunction,
pub sql_connection_pool: Pool<SqliteConnectionManager>,
pub max_radius: Distance,
}

#[cfg(test)]
Expand Down Expand Up @@ -167,11 +170,11 @@ mod tests {
.unwrap();
match expected_capacity_bytes {
Some(expected_capacity_bytes) => {
let config = factory.create(&subnetwork).unwrap();
let config = factory.create(&subnetwork, Distance::MAX).unwrap();
assert_eq!(config.storage_capacity_bytes, expected_capacity_bytes);
}
None => assert!(
factory.create(&subnetwork).is_err(),
factory.create(&subnetwork, Distance::MAX).is_err(),
"Storage config is expected to fail"
),
}
Expand All @@ -193,21 +196,21 @@ mod tests {
.unwrap();
assert_eq!(
factory
.create(&Subnetwork::Beacon)
.create(&Subnetwork::Beacon, Distance::MAX)
.unwrap()
.storage_capacity_bytes,
100_000_000,
);
assert_eq!(
factory
.create(&Subnetwork::History)
.create(&Subnetwork::History, Distance::MAX)
.unwrap()
.storage_capacity_bytes,
200_000_000,
);
assert_eq!(
factory
.create(&Subnetwork::State)
.create(&Subnetwork::State, Distance::MAX)
.unwrap()
.storage_capacity_bytes,
300_000_000,
Expand All @@ -230,17 +233,17 @@ mod tests {
.unwrap();
assert_eq!(
factory
.create(&Subnetwork::History)
.create(&Subnetwork::History, Distance::MAX)
.unwrap()
.storage_capacity_bytes,
100_000_000,
);
assert!(
factory.create(&Subnetwork::Beacon).is_err(),
factory.create(&Subnetwork::Beacon, Distance::MAX).is_err(),
"Creating for Beacon should fail"
);
assert!(
factory.create(&Subnetwork::State).is_err(),
factory.create(&Subnetwork::State, Distance::MAX).is_err(),
"Creating for State should fail"
);
temp_dir.close().unwrap();
Expand All @@ -261,19 +264,19 @@ mod tests {
.unwrap();
assert_eq!(
factory
.create(&Subnetwork::Beacon)
.create(&Subnetwork::Beacon, Distance::MAX)
.unwrap()
.storage_capacity_bytes,
0,
);
assert_eq!(
factory
.create(&Subnetwork::History)
.create(&Subnetwork::History, Distance::MAX)
.unwrap()
.storage_capacity_bytes,
100_000_000,
);
assert!(factory.create(&Subnetwork::State).is_err());
assert!(factory.create(&Subnetwork::State, Distance::MAX).is_err());
temp_dir.close().unwrap();
}
}
4 changes: 2 additions & 2 deletions crates/storage/src/test_utils.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use discv5::enr::NodeId;
use ethportal_api::types::network::Subnetwork;
use ethportal_api::types::{distance::Distance, network::Subnetwork};
use tempfile::TempDir;

use crate::{
Expand All @@ -21,7 +21,7 @@ pub fn create_test_portal_storage_config_with_capacity(
temp_dir.path().to_path_buf(),
)
.unwrap()
.create(&Subnetwork::History)
.create(&Subnetwork::History, Distance::MAX)
.unwrap();
Ok((temp_dir, config))
}
Expand Down
4 changes: 3 additions & 1 deletion crates/storage/src/versioned/id_indexed_v1/config.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::path::PathBuf;

use discv5::enr::NodeId;
use ethportal_api::types::network::Subnetwork;
use ethportal_api::types::{distance::Distance, network::Subnetwork};
use r2d2::Pool;
use r2d2_sqlite::SqliteConnectionManager;

Expand All @@ -19,6 +19,7 @@ pub struct IdIndexedV1StoreConfig {
pub sql_connection_pool: Pool<SqliteConnectionManager>,
pub distance_fn: DistanceFunction,
pub pruning_config: PruningConfig,
pub max_radius: Distance,
}

impl IdIndexedV1StoreConfig {
Expand All @@ -37,6 +38,7 @@ impl IdIndexedV1StoreConfig {
distance_fn: config.distance_fn,
// consider making this a parameter if we start using non-default value
pruning_config: PruningConfig::default(),
max_radius: config.max_radius,
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ mod tests {
use std::path::PathBuf;

use discv5::enr::NodeId;
use ethportal_api::types::network::Subnetwork;
use ethportal_api::types::{distance::Distance, network::Subnetwork};
use r2d2::Pool;
use r2d2_sqlite::SqliteConnectionManager;
use rstest::rstest;
Expand All @@ -220,6 +220,7 @@ mod tests {
sql_connection_pool: Pool::new(SqliteConnectionManager::memory()).unwrap(),
distance_fn: DistanceFunction::Xor,
pruning_config: PruningConfig::default(),
max_radius: Distance::MAX,
};
PruningStrategy::new(config)
}
Expand Down
23 changes: 14 additions & 9 deletions crates/storage/src/versioned/id_indexed_v1/store.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::marker::PhantomData;
use std::{cmp::min, marker::PhantomData};

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

let mut store = Self {
config,
radius: Distance::MAX,
radius: config.max_radius,
pruning_strategy,
usage_stats: UsageStats::default(),
metrics: StorageMetricsReporter::new(subnetwork),
_phantom_content_key: PhantomData,
config,
};
store.init()?;
Ok(store)
Expand Down Expand Up @@ -133,11 +133,12 @@ impl<TContentKey: OverlayContentKey> IdIndexedV1Store<TContentKey> {
} else {
debug!(
Db = %self.config.content_type,
"Used capacity ({}) is below target capacity ({}) -> Using MAX radius",
"Used capacity ({}) is below target capacity ({}) -> Using MAX radius ({})",
self.usage_stats.total_entry_size_bytes,
self.pruning_strategy.target_capacity_bytes()
self.pruning_strategy.target_capacity_bytes(),
self.config.max_radius,
);
self.radius = Distance::MAX;
self.radius = self.config.max_radius;
self.metrics.report_radius(self.radius);
}

Expand Down Expand Up @@ -420,7 +421,7 @@ impl<TContentKey: OverlayContentKey> IdIndexedV1Store<TContentKey> {

/// Sets `self.radius` to the distance to the farthest stored content.
///
/// If no content is found, it sets radius to `Distance::MAX`.
/// If no content is found, it sets radius to `config.max_radius`.
fn set_radius_to_farthest(&mut self) -> Result<(), ContentStoreError> {
match self.lookup_farthest()? {
None => {
Expand All @@ -432,11 +433,14 @@ impl<TContentKey: OverlayContentKey> IdIndexedV1Store<TContentKey> {
self.radius = Distance::ZERO;
} else {
error!(Db = %self.config.content_type, "Farthest not found!");
self.radius = Distance::MAX;
self.radius = self.config.max_radius;
}
}
Some(farthest) => {
self.radius = self.distance_to_content_id(&farthest.content_id);
self.radius = min(
self.distance_to_content_id(&farthest.content_id),
self.config.max_radius,
);
}
}
self.metrics.report_radius(self.radius);
Expand Down Expand Up @@ -572,6 +576,7 @@ mod tests {
sql_connection_pool: setup_sql(temp_dir.path()).unwrap(),
storage_capacity_bytes,
pruning_config: PruningConfig::default(),
max_radius: Distance::MAX,
}
}

Expand Down
30 changes: 29 additions & 1 deletion crates/utils/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use core::fmt;
use std::{str::FromStr, sync::Arc};

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

Ok(Arc::new(subnetworks))
}

pub fn max_radius_parser(max_radius_str: &str) -> Result<Distance, String> {
let max_radius_percentage = match max_radius_str.parse::<U256>() {
Ok(val) => val,
Err(err) => {
return Err(format!(
"Invalid max radius percentage, expected a number, received: {err}"
))
}
};

if max_radius_percentage > U256::from(100) {
return Err(format!(
"Invalid max radius percentage, expected 0 to 100, received: {max_radius_percentage}"
));
}

// If the max radius is 100% return it, as arithmetic multiplication loses precision and will be
// off by 5.
if max_radius_percentage == U256::from(100) {
return Ok(Distance::MAX);
}

Ok(Distance::from(
U256::MAX / U256::from(100) * max_radius_percentage,
))
}
2 changes: 2 additions & 0 deletions testing/ethportal-peertest/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ fn generate_trin_config(
"--unsafe-private-key",
private_key.as_str(),
"--ephemeral",
"--max-radius",
"100",
];
TrinConfig::new_from(trin_config_args).unwrap()
}
Expand Down
2 changes: 2 additions & 0 deletions testing/ethportal-peertest/src/scenarios/put_content.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,8 @@ fn fresh_node_config() -> (String, TrinConfig) {
test_discovery_port.to_string().as_ref(),
"--bootnodes",
"none",
"--max-radius",
"100",
"--unsafe-private-key",
// node id: 0x27128939ed60d6f4caef0374da15361a2c1cd6baa1a5bccebac1acd18f485900
"0x9ca7889c09ef1162132251b6284bd48e64bd3e71d75ea33b959c37be0582a2fd",
Expand Down
Loading

0 comments on commit 0043f6b

Please sign in to comment.