diff --git a/pallets/networks/Cargo.toml b/pallets/networks/Cargo.toml index eb7944f..13fae09 100644 --- a/pallets/networks/Cargo.toml +++ b/pallets/networks/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ghost-networks" -version = "0.1.8" +version = "0.1.9" license.workspace = true authors.workspace = true edition.workspace = true diff --git a/pallets/networks/src/benchmarking.rs b/pallets/networks/src/benchmarking.rs index 70bb6de..f726a3e 100644 --- a/pallets/networks/src/benchmarking.rs +++ b/pallets/networks/src/benchmarking.rs @@ -32,6 +32,7 @@ fn prepare_network( topic_name, network_type: NetworkType::Evm, finality_delay: 69, + rate_limit_delay: 69, block_distance: 69, incoming_fee: 0, outgoing_fee: 0, @@ -120,6 +121,20 @@ benchmarks! { assert_ne!(GhostNetworks::::networks(chain_id.clone()), prev_network); } + update_network_rate_limit_delay { + let rate_limit = 1337; + let (chain_id, network) = prepare_network::(1, 1); + let authority = T::UpdateOrigin::try_successful_origin() + .map_err(|_| BenchmarkError::Weightless)?; + let prev_network = create_network::(chain_id.clone(), network.clone())?; + }: _(authority, chain_id.clone(), rate_limit) + verify { + assert_last_event::(Event::NetworkRateLimitDelayUpdated { + chain_id: chain_id.clone(), rate_limit_delay: rate_limit, + }.into()); + assert_ne!(GhostNetworks::::networks(chain_id.clone()), prev_network); + } + update_network_block_distance { let block_distance = 1337; let (chain_id, network) = prepare_network::(1, 1); diff --git a/pallets/networks/src/lib.rs b/pallets/networks/src/lib.rs index 596ae65..3c61883 100644 --- a/pallets/networks/src/lib.rs +++ b/pallets/networks/src/lib.rs @@ -56,6 +56,7 @@ pub struct NetworkData { pub topic_name: Vec, pub network_type: NetworkType, pub finality_delay: u64, + pub rate_limit_delay: u64, pub block_distance: u64, pub incoming_fee: u32, pub outgoing_fee: u32, @@ -158,6 +159,7 @@ pub mod module { NetworkNameUpdated { chain_id: T::NetworkId, chain_name: Vec }, NetworkEndpointUpdated { chain_id: T::NetworkId, default_endpoint: Vec }, NetworkFinalityDelayUpdated { chain_id: T::NetworkId, finality_delay: u64 }, + NetworkRateLimitDelayUpdated { chain_id: T::NetworkId, rate_limit_delay: u64 }, NetworkBlockDistanceUpdated { chain_id: T::NetworkId, block_distance: u64 }, NetworkTypeUpdated { chain_id: T::NetworkId, network_type: NetworkType }, NetworkGatekeeperUpdated { chain_id: T::NetworkId, gatekeeper: Vec }, @@ -303,6 +305,20 @@ pub mod module { } #[pallet::call_index(4)] + #[pallet::weight(T::WeightInfo::update_network_rate_limit_delay())] + pub fn update_network_rate_limit_delay( + origin: OriginFor, + chain_id: T::NetworkId, + rate_limit_delay: u64, + ) -> DispatchResult { + T::UpdateOrigin::ensure_origin_or_root(origin)?; + Self::do_update_network_rate_limit_delay( + chain_id, + rate_limit_delay, + ) + } + + #[pallet::call_index(5)] #[pallet::weight(T::WeightInfo::update_network_block_distance())] pub fn update_network_block_distance( origin: OriginFor, @@ -316,7 +332,7 @@ pub mod module { ) } - #[pallet::call_index(5)] + #[pallet::call_index(6)] #[pallet::weight(T::WeightInfo::update_network_type())] pub fn update_network_type( origin: OriginFor, @@ -330,7 +346,7 @@ pub mod module { ) } - #[pallet::call_index(6)] + #[pallet::call_index(7)] #[pallet::weight(T::WeightInfo::update_network_gatekeeper())] pub fn update_network_gatekeeper( origin: OriginFor, @@ -344,7 +360,7 @@ pub mod module { ) } - #[pallet::call_index(7)] + #[pallet::call_index(8)] #[pallet::weight(T::WeightInfo::update_network_topic_name())] pub fn update_network_topic_name( origin: OriginFor, @@ -358,7 +374,7 @@ pub mod module { ) } - #[pallet::call_index(8)] + #[pallet::call_index(9)] #[pallet::weight(T::WeightInfo::update_incoming_network_fee())] pub fn update_incoming_network_fee( origin: OriginFor, @@ -372,7 +388,7 @@ pub mod module { ) } - #[pallet::call_index(9)] + #[pallet::call_index(10)] #[pallet::weight(T::WeightInfo::update_outgoing_network_fee())] pub fn update_outgoing_network_fee( origin: OriginFor, @@ -386,7 +402,7 @@ pub mod module { ) } - #[pallet::call_index(10)] + #[pallet::call_index(11)] #[pallet::weight(T::WeightInfo::remove_network())] pub fn remove_network( origin: OriginFor, @@ -465,7 +481,7 @@ impl Pallet { Ok(()) } - /// Update existent network default endpoint. + /// Update existent network default finality delay. pub fn do_update_network_finality_delay( chain_id: T::NetworkId, finality_delay: u64, @@ -484,6 +500,25 @@ impl Pallet { Ok(()) } + /// Update existent network default rate limit delay. + pub fn do_update_network_rate_limit_delay( + chain_id: T::NetworkId, + rate_limit_delay: u64, + ) -> DispatchResult { + Networks::::try_mutate(&chain_id, |maybe_network| -> DispatchResult { + ensure!(maybe_network.is_some(), Error::::NetworkDoesNotExist); + let net = maybe_network.as_mut().unwrap(); + net.rate_limit_delay = rate_limit_delay; + *maybe_network = Some(net.clone()); + Ok(()) + })?; + Self::deposit_event(Event::::NetworkRateLimitDelayUpdated { + chain_id, + rate_limit_delay, + }); + Ok(()) + } + /// Update existent network default max distance between blocks. pub fn do_update_network_block_distance( chain_id: T::NetworkId, diff --git a/pallets/networks/src/tests.rs b/pallets/networks/src/tests.rs index cbedb92..c33e69c 100644 --- a/pallets/networks/src/tests.rs +++ b/pallets/networks/src/tests.rs @@ -12,6 +12,7 @@ fn prepare_network_data() -> (u32, NetworkData) { chain_name: "Ethereum".into(), default_endpoint: "https:://some-endpoint.my-server.com/v1/my-super-secret-key".into(), finality_delay: 69, + rate_limit_delay: 69, block_distance: 69, network_type: NetworkType::Evm, gatekeeper: b"0x1234567891234567891234567891234567891234".to_vec(), @@ -136,6 +137,27 @@ fn could_update_network_finality_delay_from_authority_account() { }); } +#[test] +fn could_update_network_rate_limit_delay_from_authority_account() { + ExtBuilder::build() + .execute_with(|| { + let new_rate_limit_delay = 1337; + let (chain_id, network) = prepare_network_data(); + register_and_check_network(chain_id, network.clone()); + assert_ok!(GhostNetworks::update_network_rate_limit_delay( + RuntimeOrigin::signed(UpdaterAccount::get()), + chain_id, new_rate_limit_delay)); + System::assert_last_event(RuntimeEvent::GhostNetworks( + crate::Event::NetworkRateLimitDelayUpdated { + chain_id, + rate_limit_delay: new_rate_limit_delay })); + let mut final_network = network.clone(); + final_network.rate_limit_delay = new_rate_limit_delay; + assert_eq!(Networks::::get(chain_id), Some(final_network.clone())); + assert_ne!(network, final_network); + }); +} + #[test] fn could_update_network_block_distance_from_authority_account() { ExtBuilder::build() @@ -329,6 +351,29 @@ fn could_not_update_network_finality_delay_from_random_account() { }); } +#[test] +fn could_not_update_network_rate_limit_delay_from_random_account() { + ExtBuilder::build() + .execute_with(|| { + let (chain_id, network) = prepare_network_data(); + let rate_limit_delay = 1337; + register_and_check_network(chain_id, network.clone()); + assert_err!(GhostNetworks::update_network_rate_limit_delay( + RuntimeOrigin::signed(RegistererAccount::get()), + chain_id, rate_limit_delay), + DispatchError::BadOrigin); + assert_err!(GhostNetworks::update_network_rate_limit_delay( + RuntimeOrigin::signed(RemoverAccount::get()), + chain_id, rate_limit_delay), + DispatchError::BadOrigin); + assert_err!(GhostNetworks::update_network_rate_limit_delay( + RuntimeOrigin::signed(RandomAccount::get()), + chain_id, rate_limit_delay), + DispatchError::BadOrigin); + assert_eq!(Networks::::get(chain_id), Some(network)); + }); +} + #[test] fn could_not_update_network_release_delay_from_random_account() { ExtBuilder::build() @@ -504,6 +549,20 @@ fn could_not_update_finality_delay_for_non_existent_network() { }); } +#[test] +fn could_not_update_rate_limit_delay_for_non_existent_network() { + ExtBuilder::build() + .execute_with(|| { + let chain_id: u32 = 1; + assert_eq!(Networks::::get(chain_id), None); + assert_err!(GhostNetworks::update_network_rate_limit_delay( + RuntimeOrigin::signed(UpdaterAccount::get()), + chain_id, 1337), + crate::Error::::NetworkDoesNotExist); + assert_eq!(Networks::::get(chain_id), None); + }); +} + #[test] fn could_not_update_release_delay_for_non_existent_network() { ExtBuilder::build() diff --git a/pallets/networks/src/weights.rs b/pallets/networks/src/weights.rs index 4aadf5a..ab3a6c1 100644 --- a/pallets/networks/src/weights.rs +++ b/pallets/networks/src/weights.rs @@ -53,6 +53,7 @@ pub trait WeightInfo { fn update_network_name(n: u32, ) -> Weight; fn update_network_endpoint(n: u32, ) -> Weight; fn update_network_finality_delay() -> Weight; + fn update_network_rate_limit_delay() -> Weight; fn update_network_block_distance() -> Weight; fn update_network_type() -> Weight; fn update_network_gatekeeper() -> Weight; @@ -125,6 +126,18 @@ impl WeightInfo for SubstrateWeight { } /// Storage: `GhostNetworks::Networks` (r:1 w:1) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn update_network_rate_limit_delay() -> Weight { + // Proof Size summary in bytes: + // Measured: `294` + // Estimated: `3759` + // Minimum execution time: 48_107_000 picoseconds. + Weight::from_parts(48_993_000, 0) + .saturating_add(Weight::from_parts(0, 3759)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `GhostNetworks::Networks` (r:1 w:1) + /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) fn update_network_block_distance() -> Weight { // Proof Size summary in bytes: // Measured: `294` @@ -270,6 +283,18 @@ impl WeightInfo for () { } /// Storage: `GhostNetworks::Networks` (r:1 w:1) /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn update_network_rate_limit_delay() -> Weight { + // Proof Size summary in bytes: + // Measured: `294` + // Estimated: `3759` + // Minimum execution time: 48_107_000 picoseconds. + Weight::from_parts(48_993_000, 0) + .saturating_add(Weight::from_parts(0, 3759)) + .saturating_add(RocksDbWeight::get().reads(1)) + .saturating_add(RocksDbWeight::get().writes(1)) + } + /// Storage: `GhostNetworks::Networks` (r:1 w:1) + /// Proof: `GhostNetworks::Networks` (`max_values`: None, `max_size`: None, mode: `Measured`) fn update_network_block_distance() -> Weight { // Proof Size summary in bytes: // Measured: `294`