Skip to content

Commit 8523a1b

Browse files
committed
rate-limit return delay error
1 parent 5d8c7ff commit 8523a1b

File tree

13 files changed

+395
-261
lines changed

13 files changed

+395
-261
lines changed

asset-registry/src/mock/para.rs

+9-16
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@ use frame_support::{
1111
};
1212
use frame_system::{EnsureRoot, EnsureSignedBy};
1313
use orml_traits::{
14-
define_combined_delayed_task,
15-
delay_tasks::DelayedTask,
14+
define_combined_task,
1615
location::{AbsoluteReserveProvider, RelativeReserveProvider},
17-
parameter_type_with_key, FixedConversionRateProvider, MultiCurrency,
16+
parameter_type_with_key,
17+
task::{DispatchableTask, TaskResult},
18+
FixedConversionRateProvider, MultiCurrency,
1819
};
1920
use orml_xcm_support::{IsNativeConcrete, MultiCurrencyAdapter, MultiNativeAsset};
20-
use orml_xtokens::XtokensDelayedTask;
21+
use orml_xtokens::XtokensTask;
2122
use pallet_xcm::XcmPassthrough;
2223
use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
2324
use polkadot_parachain_primitives::primitives::Sibling;
@@ -314,18 +315,13 @@ parameter_type_with_key! {
314315
};
315316
}
316317

317-
define_combined_delayed_task! {
318+
define_combined_task! {
318319
#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)]
319320
pub enum DelayedTasks {
320-
XtokensDelayedTask(XtokensDelayedTask<Runtime>),
321+
Xtokens(XtokensTask<Runtime>),
321322
}
322323
}
323324

324-
parameter_types! {
325-
pub const GetDelayBlocks: u64 = 1000;
326-
pub const GetReserveId: [u8; 8] = *b"xtokensr";
327-
}
328-
329325
impl orml_xtokens::Config for Runtime {
330326
type RuntimeEvent = RuntimeEvent;
331327
type Balance = Balance;
@@ -343,11 +339,8 @@ impl orml_xtokens::Config for Runtime {
343339
type ReserveProvider = RelativeReserveProvider;
344340
type RateLimiter = ();
345341
type RateLimiterId = ();
346-
type DelayedTask = DelayedTasks;
347-
type DelayTasks = orml_xtokens::DisabledTransferAssets<Runtime>;
348-
type DelayBlocks = GetDelayBlocks;
349-
type Currency = Tokens;
350-
type ReserveId = GetReserveId;
342+
type Task = ();
343+
type DelayTasks = orml_xtokens::DisabledDelayTask<Runtime>;
351344
}
352345

353346
impl orml_xcm::Config for Runtime {

delay-tasks/src/mock.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
use super::*;
66
use frame_support::{construct_runtime, derive_impl};
77
use frame_system::EnsureRoot;
8-
use orml_traits::define_combined_delayed_task;
8+
use orml_traits::define_combined_task;
99
use sp_runtime::{traits::IdentityLookup, BuildStorage, DispatchError};
1010
use sp_std::cell::RefCell;
1111

@@ -35,7 +35,7 @@ pub(crate) fn reset_delay_process_records() {
3535
ON_CANCEL.with(|v| *v.borrow_mut() = false);
3636
}
3737

38-
define_combined_delayed_task! {
38+
define_combined_task! {
3939
#[derive(Clone, Encode, Decode, PartialEq, RuntimeDebug, TypeInfo)]
4040
pub enum MockDelayedTaskType {
4141
Success(SuccessTask),

rate-limit/src/lib.rs

+63-18
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ pub mod module {
112112
/// Exceed the allowed maximum number of KeyFilter configured to a
113113
/// RateLimiterId.
114114
MaxFilterExceeded,
115+
/// Delay block must not be zero.
116+
ZeroDelayBlock,
115117
}
116118

117119
#[pallet::event]
@@ -129,6 +131,10 @@ pub mod module {
129131
WhitelistFilterRemoved { rate_limiter_id: T::RateLimiterId },
130132
/// The whitelist of bypass rate limit has been reset.
131133
WhitelistFilterReset { rate_limiter_id: T::RateLimiterId },
134+
AllowDelayBlockChanged {
135+
rate_limiter_id: T::RateLimiterId,
136+
update: Option<BlockNumberFor<T>>,
137+
},
132138
}
133139

134140
/// The rate limit rule for specific RateLimiterId and encoded key.
@@ -156,6 +162,12 @@ pub mod module {
156162
pub type LimitWhitelist<T: Config> =
157163
StorageMap<_, Twox64Concat, T::RateLimiterId, OrderedSet<KeyFilter, T::MaxWhitelistFilterCount>, ValueQuery>;
158164

165+
/// Allow delay (not consume quota) when limit check for specific
166+
/// RateLimiterId
167+
#[pallet::storage]
168+
#[pallet::getter(fn allow_delay)]
169+
pub type AllowDelay<T: Config> = StorageMap<_, Twox64Concat, T::RateLimiterId, BlockNumberFor<T>, OptionQuery>;
170+
159171
#[pallet::pallet]
160172
#[pallet::without_storage_info]
161173
pub struct Pallet<T>(_);
@@ -317,6 +329,37 @@ pub mod module {
317329
Self::deposit_event(Event::WhitelistFilterReset { rate_limiter_id });
318330
Ok(())
319331
}
332+
333+
/// Allow delayed when limit check.
334+
///
335+
/// Requires `GovernanceOrigin`
336+
///
337+
/// Parameters:
338+
/// - `rate_limiter_id`: rate limiter id.
339+
/// - `allow_delayed_block`: allow delay when limit check.
340+
#[pallet::call_index(4)]
341+
#[pallet::weight(T::WeightInfo::reset_whitelist())]
342+
#[transactional]
343+
pub fn allow_delay_block(
344+
origin: OriginFor<T>,
345+
rate_limiter_id: T::RateLimiterId,
346+
allow_delayed_block: Option<BlockNumberFor<T>>,
347+
) -> DispatchResult {
348+
T::GovernanceOrigin::ensure_origin(origin)?;
349+
350+
if let Some(dely_block) = allow_delayed_block {
351+
ensure!(!dely_block.is_zero(), Error::<T>::ZeroDelayBlock);
352+
AllowDelay::<T>::insert(rate_limiter_id, dely_block);
353+
} else {
354+
AllowDelay::<T>::remove(rate_limiter_id);
355+
}
356+
357+
Self::deposit_event(Event::AllowDelayBlockChanged {
358+
rate_limiter_id,
359+
update: allow_delayed_block,
360+
});
361+
Ok(())
362+
}
320363
}
321364

322365
impl<T: Config> Pallet<T> {
@@ -381,7 +424,7 @@ pub mod module {
381424
}
382425
}
383426

384-
impl<T: Config> RateLimiter for Pallet<T> {
427+
impl<T: Config> RateLimiter<BlockNumberFor<T>> for Pallet<T> {
385428
type RateLimiterId = T::RateLimiterId;
386429

387430
fn is_whitelist(limiter_id: Self::RateLimiterId, key: impl Encode) -> bool {
@@ -410,31 +453,33 @@ pub mod module {
410453
false
411454
}
412455

413-
fn can_consume(limiter_id: Self::RateLimiterId, key: impl Encode, value: u128) -> Result<(), RateLimiterError> {
456+
fn can_consume(
457+
limiter_id: Self::RateLimiterId,
458+
key: impl Encode,
459+
value: u128,
460+
) -> Result<(), RateLimiterError<BlockNumberFor<T>>> {
414461
let encoded_key: Vec<u8> = key.encode();
415462

416-
let allowed = match RateLimitRules::<T>::get(limiter_id, &encoded_key) {
463+
match RateLimitRules::<T>::get(limiter_id, &encoded_key) {
417464
Some(rate_limit_rule @ RateLimitRule::PerPeriod { .. })
418465
| Some(rate_limit_rule @ RateLimitRule::TokenBucket { .. }) => {
419466
let remainer_quota =
420467
Self::access_remainer_quota_after_update(rate_limit_rule, &limiter_id, &encoded_key);
421468

422-
value <= remainer_quota
423-
}
424-
Some(RateLimitRule::Unlimited) => true,
425-
Some(RateLimitRule::NotAllowed) => {
426-
// always return false, even if the value is zero.
427-
false
428-
}
429-
None => {
430-
// if doesn't rate limit rule, always return true.
431-
true
432-
}
433-
};
434-
435-
ensure!(allowed, RateLimiterError::ExceedLimit);
469+
if value > remainer_quota {
470+
if let Some(delay_block) = AllowDelay::<T>::get(limiter_id) {
471+
return Err(RateLimiterError::Delay { duration: delay_block });
472+
} else {
473+
return Err(RateLimiterError::Deny);
474+
}
475+
}
436476

437-
Ok(())
477+
Ok(())
478+
}
479+
Some(RateLimitRule::Unlimited) => Ok(()),
480+
Some(RateLimitRule::NotAllowed) => Err(RateLimiterError::Deny),
481+
None => Ok(()),
482+
}
438483
}
439484

440485
fn consume(limiter_id: Self::RateLimiterId, key: impl Encode, value: u128) {

rate-limit/src/tests.rs

+46-6
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,37 @@ fn reset_whitelist_work() {
392392
});
393393
}
394394

395+
#[test]
396+
fn allow_delay_block_work() {
397+
ExtBuilder::default().build().execute_with(|| {
398+
assert_noop!(
399+
RateLimit::allow_delay_block(RuntimeOrigin::signed(ALICE), 0, Some(1),),
400+
BadOrigin
401+
);
402+
403+
// delay block is zero
404+
assert_noop!(
405+
RateLimit::allow_delay_block(RuntimeOrigin::root(), 0, Some(0),),
406+
Error::<Runtime>::ZeroDelayBlock
407+
);
408+
409+
assert_eq!(RateLimit::allow_delay(0), None);
410+
assert_ok!(RateLimit::allow_delay_block(RuntimeOrigin::root(), 0, Some(100),));
411+
System::assert_last_event(RuntimeEvent::RateLimit(crate::Event::AllowDelayBlockChanged {
412+
rate_limiter_id: 0,
413+
update: Some(100),
414+
}));
415+
assert_eq!(RateLimit::allow_delay(0), Some(100));
416+
417+
assert_ok!(RateLimit::allow_delay_block(RuntimeOrigin::root(), 0, None,));
418+
System::assert_last_event(RuntimeEvent::RateLimit(crate::Event::AllowDelayBlockChanged {
419+
rate_limiter_id: 0,
420+
update: None,
421+
}));
422+
assert_eq!(RateLimit::allow_delay(0), None);
423+
});
424+
}
425+
395426
#[test]
396427
fn is_whitelist_work() {
397428
ExtBuilder::default().build().execute_with(|| {
@@ -799,12 +830,12 @@ fn can_consume_work() {
799830

800831
assert_eq!(RateLimit::rate_limit_quota(0, DOT.encode()), (0, 0));
801832
assert_ok!(RateLimit::can_consume(0, DOT, 0));
802-
assert_eq!(RateLimit::can_consume(0, DOT, 500), Err(RateLimiterError::ExceedLimit),);
833+
assert_eq!(RateLimit::can_consume(0, DOT, 500), Err(RateLimiterError::Deny),);
803834
assert_eq!(RateLimit::rate_limit_quota(0, DOT.encode()), (0, 0));
804835

805836
assert_eq!(RateLimit::rate_limit_quota(1, DOT.encode()), (0, 0));
806837
assert_ok!(RateLimit::can_consume(1, DOT, 0));
807-
assert_eq!(RateLimit::can_consume(1, DOT, 501), Err(RateLimiterError::ExceedLimit),);
838+
assert_eq!(RateLimit::can_consume(1, DOT, 501), Err(RateLimiterError::Deny),);
808839
assert_eq!(RateLimit::rate_limit_quota(1, DOT.encode()), (0, 0));
809840

810841
System::set_block_number(100);
@@ -813,20 +844,29 @@ fn can_consume_work() {
813844
assert_eq!(RateLimit::rate_limit_quota(0, DOT.encode()), (0, 0));
814845
assert_ok!(RateLimit::can_consume(0, DOT, 500));
815846
assert_eq!(RateLimit::rate_limit_quota(0, DOT.encode()), (100, 500));
816-
assert_eq!(RateLimit::can_consume(0, DOT, 501), Err(RateLimiterError::ExceedLimit),);
847+
assert_eq!(RateLimit::can_consume(0, DOT, 501), Err(RateLimiterError::Deny),);
817848
assert_eq!(RateLimit::rate_limit_quota(0, DOT.encode()), (100, 500));
818849

819850
assert_eq!(RateLimit::rate_limit_quota(1, DOT.encode()), (0, 0));
820851
assert_ok!(RateLimit::can_consume(1, DOT, 501));
821852
assert_eq!(RateLimit::rate_limit_quota(1, DOT.encode()), (100, 1000));
822-
assert_eq!(RateLimit::can_consume(1, DOT, 1001), Err(RateLimiterError::ExceedLimit),);
853+
assert_eq!(RateLimit::can_consume(1, DOT, 1001), Err(RateLimiterError::Deny),);
823854
assert_eq!(RateLimit::rate_limit_quota(1, DOT.encode()), (100, 1000));
824855

856+
// if config allow delay for rate limit id 0, return RateLimiterError::Delay
857+
assert_ok!(RateLimit::allow_delay_block(RuntimeOrigin::root(), 0, Some(10000),));
858+
assert_eq!(RateLimit::rate_limit_quota(0, DOT.encode()), (100, 500));
859+
assert_ok!(RateLimit::can_consume(0, DOT, 500));
860+
assert_eq!(
861+
RateLimit::can_consume(0, DOT, 501),
862+
Err(RateLimiterError::Delay { duration: 10000 })
863+
);
864+
825865
// NotAllowed always return error, even if value is 0
826866
RateLimitQuota::<Runtime>::mutate(0, BTC.encode(), |(_, remainer_quota)| *remainer_quota = 10000);
827867
assert_eq!(RateLimit::rate_limit_quota(0, BTC.encode()), (0, 10000));
828-
assert_eq!(RateLimit::can_consume(0, BTC, 0), Err(RateLimiterError::ExceedLimit),);
829-
assert_eq!(RateLimit::can_consume(0, BTC, 100), Err(RateLimiterError::ExceedLimit),);
868+
assert_eq!(RateLimit::can_consume(0, BTC, 0), Err(RateLimiterError::Deny),);
869+
assert_eq!(RateLimit::can_consume(0, BTC, 100), Err(RateLimiterError::Deny),);
830870

831871
// Unlimited always return true
832872
assert_eq!(RateLimit::rate_limit_quota(1, BTC.encode()), (0, 0));

traits/src/delay_tasks.rs

-70
This file was deleted.

traits/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ pub mod asset_registry;
3232
pub mod auction;
3333
pub mod currency;
3434
pub mod data_provider;
35-
pub mod delay_tasks;
3635
pub mod get_by_key;
3736
pub mod location;
3837
pub mod multi_asset;
@@ -41,6 +40,7 @@ pub mod parameters;
4140
pub mod price;
4241
pub mod rate_limit;
4342
pub mod rewards;
43+
pub mod task;
4444
pub mod xcm_transfer;
4545

4646
/// New data handler

0 commit comments

Comments
 (0)