From 1d826fbf7e745fd6bd19f374051b44fd4abc619e Mon Sep 17 00:00:00 2001 From: Uncle Stinky Date: Tue, 29 Jul 2025 12:42:36 +0300 Subject: [PATCH] rotate endpoints on each offchain worker exection Signed-off-by: Uncle Stinky --- pallets/slow-clap/Cargo.toml | 2 +- pallets/slow-clap/src/lib.rs | 31 ++++++++++++++++++++++++++----- pallets/slow-clap/src/tests.rs | 9 ++++++++- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/pallets/slow-clap/Cargo.toml b/pallets/slow-clap/Cargo.toml index 248ee78..ec35be7 100644 --- a/pallets/slow-clap/Cargo.toml +++ b/pallets/slow-clap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ghost-slow-clap" -version = "0.3.33" +version = "0.3.34" description = "Applause protocol for the EVM bridge" license.workspace = true authors.workspace = true diff --git a/pallets/slow-clap/src/lib.rs b/pallets/slow-clap/src/lib.rs index 2513b81..4f7b034 100644 --- a/pallets/slow-clap/src/lib.rs +++ b/pallets/slow-clap/src/lib.rs @@ -28,7 +28,7 @@ use sp_runtime::{ storage_lock::{StorageLock, Time}, HttpError, }, - traits::{BlockNumberProvider, Convert, Saturating}, + traits::{BlockNumberProvider, Convert, Saturating, TrailingZeroInput}, Perbill, RuntimeAppPublic, RuntimeDebug, SaturatedConversion, }; use sp_staking::{ @@ -692,14 +692,35 @@ impl Pallet { let block_distance_key = Self::create_storage_key(b"block-distance-", &network_id_encoded); let endpoint_key = Self::create_storage_key(b"endpoint-", &network_id_encoded); - let rpc_endpoint = Self::read_persistent_offchain_storage( - &endpoint_key, - network_data.default_endpoint.clone(), - ); let max_block_distance = Self::read_persistent_offchain_storage( &block_distance_key, network_data.block_distance, ); + let stored_endpoints = Self::read_persistent_offchain_storage( + &endpoint_key, + network_data.default_endpoints.clone(), + ); + + let random_seed = sp_io::offchain::random_seed(); + let random_number = ::decode( + &mut TrailingZeroInput::new(random_seed.as_ref()) + ).expect("input is padded with zeroes; qed"); + + let rpc_endpoint = if stored_endpoints.len() > 0 { + stored_endpoints + .iter() + .nth((random_number as usize) + .checked_rem(stored_endpoints.len()) + .unwrap_or_default()) + .expect("stored endpoint should be non empty; qed") + } else { + network_data.default_endpoints + .iter() + .nth((random_number as usize) + .checked_rem(network_data.default_endpoints.len()) + .unwrap_or_default()) + .expect("default endpoint should be non empty; qed") + }; StorageValueRef::persistent(&block_number_key) .mutate( diff --git a/pallets/slow-clap/src/tests.rs b/pallets/slow-clap/src/tests.rs index 4c6b09f..061b797 100644 --- a/pallets/slow-clap/src/tests.rs +++ b/pallets/slow-clap/src/tests.rs @@ -22,7 +22,7 @@ fn prepare_evm_network( ) -> NetworkData { let network_data = NetworkData { chain_name: "Ethereum".into(), - default_endpoint: get_rpc_endpoint(), + default_endpoints: get_rpc_endpoints(), finality_delay: 69, rate_limit_delay: 69, block_distance: 69, @@ -1041,6 +1041,13 @@ fn get_rpc_endpoint() -> Vec { b"https://rpc.endpoint.network.com".to_vec() } +fn get_rpc_endpoints() -> Vec> { + vec![ + get_rpc_endpoint(), + b"https://other.endpoint.network.com".to_vec(), + ] +} + fn get_gatekeeper() -> Vec { b"0x4d224452801ACEd8B2F0aebE155379bb5D594381".to_vec() }