From 50e254a7939122366351be99d6feda542e16cb54 Mon Sep 17 00:00:00 2001 From: Nick Gheorghita Date: Mon, 8 Apr 2024 14:48:09 -0400 Subject: [PATCH] feat(bridge): cli flag for random era1 file with floor (#1245) --- portal-bridge/README.md | 1 + portal-bridge/src/bridge/era1.rs | 50 +++++++++++++++++++++++--------- portal-bridge/src/types/mode.rs | 26 +++++++++++++++-- portalnet/src/overlay/service.rs | 2 +- src/bin/historical_batch.rs | 1 + 5 files changed, 64 insertions(+), 16 deletions(-) diff --git a/portal-bridge/README.md b/portal-bridge/README.md index 1279ce498..1b16400ae 100644 --- a/portal-bridge/README.md +++ b/portal-bridge/README.md @@ -34,6 +34,7 @@ Current options include `"trin"` / `"fluffy"`. - `"--mode single:e100"`: gossip a single epoch #100 - `"--mode fourfours`: will randomly select era1 files from `era1.ethportal.net` and gossip them - `"--mode fourfours:random_epoch"`: will randomly select a single era1 file from `era1.ethportal.net` and then gossip it +- `"--mode fourfours:random_epoch:100"`: will randomly select a single era1 file from `era1.ethportal.net` that represents an epoch number greater than the floor provided and then gossip it - `"--mode fourfours:e600`: will select era1 file 600 from `era1.ethportal.net` and gossip it - `"--mode fourfours:r100-200`: will gossip a block range from an era1 file, range must be from the same epoch diff --git a/portal-bridge/src/bridge/era1.rs b/portal-bridge/src/bridge/era1.rs index ce9a8e8e2..c7495c71a 100644 --- a/portal-bridge/src/bridge/era1.rs +++ b/portal-bridge/src/bridge/era1.rs @@ -81,10 +81,13 @@ impl Era1Bridge { info!("Launching era1 bridge: {:?}", self.mode); match self.mode.clone() { BridgeMode::FourFours(FourFoursMode::Random) => self.launch_random().await, - BridgeMode::FourFours(FourFoursMode::RandomSingle) => self.launch_single(None).await, - BridgeMode::FourFours(FourFoursMode::Single(epoch)) => { - self.launch_single(Some(epoch)).await + BridgeMode::FourFours(FourFoursMode::RandomSingle) => { + self.launch_random_single(None).await } + BridgeMode::FourFours(FourFoursMode::RandomSingleWithFloor(floor)) => { + self.launch_random_single(Some(floor)).await + } + BridgeMode::FourFours(FourFoursMode::Single(epoch)) => self.launch_single(epoch).await, BridgeMode::FourFours(FourFoursMode::Range(start, end)) => { self.launch_range(start, end).await; } @@ -93,26 +96,47 @@ impl Era1Bridge { info!("Bridge mode: {:?} complete.", self.mode); } - pub async fn launch_random(&self) { + async fn launch_random(&self) { for era1_path in self.era1_files.clone().into_iter() { self.gossip_era1(era1_path, None).await; } } - pub async fn launch_single(&self, epoch: Option) { + async fn launch_single(&self, epoch: u64) { + let era1_path = self + .era1_files + .clone() + .into_iter() + .find(|file| file.contains(&format!("mainnet-{epoch:05}-"))) + .expect("to be able to find era1 file"); + self.gossip_era1(era1_path, None).await; + } + + async fn launch_random_single(&self, floor: Option) { let mut era1_files = self.era1_files.clone().into_iter(); - let era1_path = match epoch { - Some(epoch) => era1_files - .find(|file| file.contains(&format!("mainnet-{epoch:05}-"))) - .expect("to be able to find era1 file for requested epoch"), - None => era1_files + let era1_path = loop { + let era1_file = era1_files .next() - .expect("to be able to get first era1 file"), + .expect("to be able to get first era1 file"); + let epoch = era1_file + .split('-') + .nth(1) + .expect("to be able to get epoch from era1 file") + .parse::() + .expect("to be able to parse epoch from era1 file"); + match floor { + Some(floor) => { + if epoch >= floor { + break era1_file; + } + } + None => break era1_file, + } }; self.gossip_era1(era1_path, None).await; } - pub async fn launch_range(&self, start: u64, end: u64) { + async fn launch_range(&self, start: u64, end: u64) { let epoch = start / EPOCH_SIZE as u64; let era1_path = self.era1_files.clone().into_iter().find(|file| { @@ -125,7 +149,7 @@ impl Era1Bridge { } } - pub async fn gossip_era1(&self, era1_path: String, gossip_range: Option>) { + async fn gossip_era1(&self, era1_path: String, gossip_range: Option>) { info!("Processing era1 file at path: {era1_path:?}"); // We are using a semaphore to limit the amount of active gossip transfers to make sure // we don't overwhelm the trin client diff --git a/portal-bridge/src/types/mode.rs b/portal-bridge/src/types/mode.rs index 4fddabe43..8e1f9fe5a 100644 --- a/portal-bridge/src/types/mode.rs +++ b/portal-bridge/src/types/mode.rs @@ -169,6 +169,8 @@ pub enum FourFoursMode { Random, // Gossips a single, randomly selected epoch RandomSingle, + // Gossips a single, randomly selected epoch, with a floor epoch + RandomSingleWithFloor(u64), // Gossips the single epoch given Single(u64), // Gossips a block range from within a single epoch @@ -183,8 +185,19 @@ impl FromStr for FourFoursMode { if s.is_empty() { return Err("Invalid bridge fourfours mode arg: empty string".to_string()); } - if s == RANDOM_SINGLE_MODE { - return Ok(FourFoursMode::RandomSingle); + if s.starts_with(RANDOM_SINGLE_MODE) { + match s.split(':').nth(1) { + Some(floor_epoch) => { + let floor_epoch = floor_epoch + .parse() + .map_err(|_| "Invalid 4444s bridge mode arg: floor epoch number")?; + if floor_epoch > 1896 { + return Err(format!("Invalid 4444s bridge mode arg: era1 epoch greater than 1896 was given: {floor_epoch}")); + } + return Ok(FourFoursMode::RandomSingleWithFloor(floor_epoch)); + } + None => return Ok(FourFoursMode::RandomSingle), + } } match &s[..1] { "e" => { @@ -257,6 +270,12 @@ mod test { #[case(format!("fourfours:{RANDOM_SINGLE_MODE}"), BridgeMode::FourFours(FourFoursMode::RandomSingle) )] + #[case(format!("fourfours:{RANDOM_SINGLE_MODE}:0"), + BridgeMode::FourFours(FourFoursMode::RandomSingleWithFloor(0)) + )] + #[case(format!("fourfours:{RANDOM_SINGLE_MODE}:1500"), + BridgeMode::FourFours(FourFoursMode::RandomSingleWithFloor(1500)) + )] #[case("fourfours:e1", BridgeMode::FourFours(FourFoursMode::Single(1)))] #[case("fourfours:r1-10", BridgeMode::FourFours(FourFoursMode::Range(1, 10)))] #[case( @@ -288,6 +307,9 @@ mod test { #[case("fourfours:r1-10000")] // range is post-merge #[case("fourfours:r19000000-19000100")] + #[case("fourfours:random_epoch:")] + // epoch is post-merge + #[case("fourfours:random_epoch:1900")] fn test_invalid_mode_flag(#[case] actual: String) { let bridge_mode = BridgeMode::from_str(&actual); assert!(bridge_mode.is_err()); diff --git a/portalnet/src/overlay/service.rs b/portalnet/src/overlay/service.rs index fd24fa303..8c680344b 100644 --- a/portalnet/src/overlay/service.rs +++ b/portalnet/src/overlay/service.rs @@ -3144,7 +3144,7 @@ mod tests { let (_, enr1) = generate_random_remote_enr(); let (_, enr2) = generate_random_remote_enr(); - let peers = vec![enr1, enr2]; + let peers = [enr1, enr2]; let peer_node_ids: Vec = peers.iter().map(|p| p.node_id()).collect(); // No nodes in the routing table, so no commands should be in the channel. diff --git a/src/bin/historical_batch.rs b/src/bin/historical_batch.rs index 730507fea..beb0764f7 100644 --- a/src/bin/historical_batch.rs +++ b/src/bin/historical_batch.rs @@ -46,6 +46,7 @@ async fn main() -> anyhow::Result<()> { .read(true) .write(true) .create(true) + .truncate(true) .open(file_path.join("era_urls.txt")) .unwrap();