Skip to content
Snippets Groups Projects
Unverified Commit 11191abe authored by brettkolodny's avatar brettkolodny Committed by GitHub
Browse files

Add BoundedVec to gradually-update (#498)

* Converted Vec storage to BoundedVec

* Test for exceeding max gradually updates

* Converted storage key and value to BoundedVec
parent 7c9fd1c7
No related branches found
No related tags found
No related merge requests found
...@@ -25,11 +25,12 @@ use frame_support::{ ...@@ -25,11 +25,12 @@ use frame_support::{
ensure, ensure,
pallet_prelude::*, pallet_prelude::*,
storage, storage,
traits::{EnsureOrigin, Get}, traits::{EnsureOrigin, Get, MaxEncodedLen},
BoundedVec,
}; };
use frame_system::pallet_prelude::*; use frame_system::pallet_prelude::*;
use sp_runtime::{traits::SaturatedConversion, DispatchResult, RuntimeDebug}; use sp_runtime::{traits::SaturatedConversion, DispatchResult, RuntimeDebug};
use sp_std::prelude::Vec; use sp_std::convert::TryInto;
mod default_weight; mod default_weight;
mod mock; mod mock;
...@@ -38,14 +39,11 @@ mod tests; ...@@ -38,14 +39,11 @@ mod tests;
/// Gradually update a value stored at `key` to `target_value`, /// Gradually update a value stored at `key` to `target_value`,
/// change `per_block` * `T::UpdateFrequency` per `T::UpdateFrequency` /// change `per_block` * `T::UpdateFrequency` per `T::UpdateFrequency`
/// blocks. /// blocks.
#[derive(Encode, Decode, Clone, Eq, PartialEq, RuntimeDebug)] #[derive(Encode, Decode, Clone, Eq, PartialEq, MaxEncodedLen, RuntimeDebug)]
pub struct GraduallyUpdate { pub struct GraduallyUpdate<Key, Value> {
/// The storage key of the value to update pub key: Key,
pub key: StorageKeyBytes, pub target_value: Value,
/// The target value pub per_block: Value,
pub target_value: StorageValueBytes,
/// The amount of the value to update per one block
pub per_block: StorageValueBytes,
} }
pub use module::*; pub use module::*;
...@@ -60,8 +58,10 @@ pub mod module { ...@@ -60,8 +58,10 @@ pub mod module {
fn on_finalize(u: u32) -> Weight; fn on_finalize(u: u32) -> Weight;
} }
pub(crate) type StorageKeyBytes = Vec<u8>; pub(crate) type StorageKeyBytes<T> = BoundedVec<u8, <T as Config>::MaxStorageKeyBytes>;
pub(crate) type StorageValueBytes = Vec<u8>; pub(crate) type StorageValueBytes<T> = BoundedVec<u8, <T as Config>::MaxStorageValueBytes>;
type GraduallyUpdateOf<T> = GraduallyUpdate<StorageKeyBytes<T>, StorageValueBytes<T>>;
#[pallet::config] #[pallet::config]
pub trait Config: frame_system::Config { pub trait Config: frame_system::Config {
...@@ -76,6 +76,15 @@ pub mod module { ...@@ -76,6 +76,15 @@ pub mod module {
/// Weight information for extrinsics in this module. /// Weight information for extrinsics in this module.
type WeightInfo: WeightInfo; type WeightInfo: WeightInfo;
/// Maximum active gradual updates
type MaxGraduallyUpdate: Get<u32>;
/// Maximum size of storage key
type MaxStorageKeyBytes: Get<u32>;
/// Maximum size of storage value
type MaxStorageValueBytes: Get<u32>;
} }
#[pallet::error] #[pallet::error]
...@@ -88,23 +97,30 @@ pub mod module { ...@@ -88,23 +97,30 @@ pub mod module {
GraduallyUpdateHasExisted, GraduallyUpdateHasExisted,
/// No update exists to cancel. /// No update exists to cancel.
GraduallyUpdateNotFound, GraduallyUpdateNotFound,
/// Maximum updates exceeded
MaxGraduallyUpdateExceeded,
/// Maximum key size exceeded
MaxStorageKeyBytesExceeded,
/// Maximum value size exceeded
MaxStorageValueBytesExceeded,
} }
#[pallet::event] #[pallet::event]
#[pallet::generate_deposit(pub(crate) fn deposit_event)] #[pallet::generate_deposit(pub(crate) fn deposit_event)]
pub enum Event<T: Config> { pub enum Event<T: Config> {
/// Gradually update added. [key, per_block, target_value] /// Gradually update added. [key, per_block, target_value]
GraduallyUpdateAdded(StorageKeyBytes, StorageValueBytes, StorageValueBytes), GraduallyUpdateAdded(StorageKeyBytes<T>, StorageValueBytes<T>, StorageValueBytes<T>),
/// Gradually update cancelled. [key] /// Gradually update cancelled. [key]
GraduallyUpdateCancelled(StorageKeyBytes), GraduallyUpdateCancelled(StorageKeyBytes<T>),
/// Gradually update applied. [block_number, key, target_value] /// Gradually update applied. [block_number, key, target_value]
Updated(T::BlockNumber, StorageKeyBytes, StorageValueBytes), Updated(T::BlockNumber, StorageKeyBytes<T>, StorageValueBytes<T>),
} }
/// All the on-going updates /// All the on-going updates
#[pallet::storage] #[pallet::storage]
#[pallet::getter(fn gradually_updates)] #[pallet::getter(fn gradually_updates)]
pub(crate) type GraduallyUpdates<T: Config> = StorageValue<_, Vec<GraduallyUpdate>, ValueQuery>; pub(crate) type GraduallyUpdates<T: Config> =
StorageValue<_, BoundedVec<GraduallyUpdateOf<T>, T::MaxGraduallyUpdate>, ValueQuery>;
/// The last updated block number /// The last updated block number
#[pallet::storage] #[pallet::storage]
...@@ -135,7 +151,7 @@ pub mod module { ...@@ -135,7 +151,7 @@ pub mod module {
impl<T: Config> Pallet<T> { impl<T: Config> Pallet<T> {
/// Add gradually_update to adjust numeric parameter. /// Add gradually_update to adjust numeric parameter.
#[pallet::weight(T::WeightInfo::gradually_update())] #[pallet::weight(T::WeightInfo::gradually_update())]
pub fn gradually_update(origin: OriginFor<T>, update: GraduallyUpdate) -> DispatchResultWithPostInfo { pub fn gradually_update(origin: OriginFor<T>, update: GraduallyUpdateOf<T>) -> DispatchResultWithPostInfo {
T::DispatchOrigin::try_origin(origin).map(|_| ()).or_else(ensure_root)?; T::DispatchOrigin::try_origin(origin).map(|_| ()).or_else(ensure_root)?;
// Support max value is u128, ensure per_block and target_value <= 16 bytes. // Support max value is u128, ensure per_block and target_value <= 16 bytes.
...@@ -145,7 +161,7 @@ pub mod module { ...@@ -145,7 +161,7 @@ pub mod module {
); );
if storage::unhashed::exists(&update.key) { if storage::unhashed::exists(&update.key) {
let current_value = storage::unhashed::get::<StorageValueBytes>(&update.key).unwrap(); let current_value = storage::unhashed::get::<StorageValueBytes<T>>(&update.key).unwrap();
ensure!( ensure!(
current_value.len() == update.target_value.len(), current_value.len() == update.target_value.len(),
Error::<T>::InvalidTargetValue Error::<T>::InvalidTargetValue
...@@ -158,7 +174,9 @@ pub mod module { ...@@ -158,7 +174,9 @@ pub mod module {
Error::<T>::GraduallyUpdateHasExisted Error::<T>::GraduallyUpdateHasExisted
); );
gradually_updates.push(update.clone()); gradually_updates
.try_push(update.clone())
.map_err(|_| Error::<T>::MaxGraduallyUpdateExceeded)?;
Ok(()) Ok(())
})?; })?;
...@@ -173,7 +191,7 @@ pub mod module { ...@@ -173,7 +191,7 @@ pub mod module {
/// Cancel gradually_update to adjust numeric parameter. /// Cancel gradually_update to adjust numeric parameter.
#[pallet::weight(T::WeightInfo::cancel_gradually_update())] #[pallet::weight(T::WeightInfo::cancel_gradually_update())]
pub fn cancel_gradually_update(origin: OriginFor<T>, key: StorageKeyBytes) -> DispatchResultWithPostInfo { pub fn cancel_gradually_update(origin: OriginFor<T>, key: StorageKeyBytes<T>) -> DispatchResultWithPostInfo {
T::DispatchOrigin::try_origin(origin).map(|_| ()).or_else(ensure_root)?; T::DispatchOrigin::try_origin(origin).map(|_| ()).or_else(ensure_root)?;
GraduallyUpdates::<T>::try_mutate(|gradually_updates| -> DispatchResult { GraduallyUpdates::<T>::try_mutate(|gradually_updates| -> DispatchResult {
...@@ -206,7 +224,7 @@ impl<T: Config> Pallet<T> { ...@@ -206,7 +224,7 @@ impl<T: Config> Pallet<T> {
gradually_updates.retain(|update| { gradually_updates.retain(|update| {
let mut keep = true; let mut keep = true;
let current_value = storage::unhashed::get::<StorageValueBytes>(&update.key).unwrap_or_default(); let current_value = storage::unhashed::get::<StorageValueBytes<T>>(&update.key).unwrap_or_default();
let current_value_u128 = u128::from_le_bytes(Self::convert_vec_to_u8(&current_value)); let current_value_u128 = u128::from_le_bytes(Self::convert_vec_to_u8(&current_value));
let frequency_u128: u128 = T::UpdateFrequency::get().saturated_into(); let frequency_u128: u128 = T::UpdateFrequency::get().saturated_into();
...@@ -232,7 +250,9 @@ impl<T: Config> Pallet<T> { ...@@ -232,7 +250,9 @@ impl<T: Config> Pallet<T> {
storage::unhashed::put(&update.key, &value); storage::unhashed::put(&update.key, &value);
Self::deposit_event(Event::Updated(now, update.key.clone(), value)); let bounded_value: StorageValueBytes<T> = value.to_vec().try_into().unwrap();
Self::deposit_event(Event::Updated(now, update.key.clone(), bounded_value));
keep keep
}); });
...@@ -246,7 +266,7 @@ impl<T: Config> Pallet<T> { ...@@ -246,7 +266,7 @@ impl<T: Config> Pallet<T> {
} }
#[allow(clippy::ptr_arg)] #[allow(clippy::ptr_arg)]
fn convert_vec_to_u8(input: &StorageValueBytes) -> [u8; 16] { fn convert_vec_to_u8(input: &StorageValueBytes<T>) -> [u8; 16] {
let mut array: [u8; 16] = [0; 16]; let mut array: [u8; 16] = [0; 16];
for (i, v) in input.iter().enumerate() { for (i, v) in input.iter().enumerate() {
array[i] = *v; array[i] = *v;
......
...@@ -44,6 +44,9 @@ impl frame_system::Config for Runtime { ...@@ -44,6 +44,9 @@ impl frame_system::Config for Runtime {
parameter_types! { parameter_types! {
pub const UpdateFrequency: BlockNumber = 10; pub const UpdateFrequency: BlockNumber = 10;
pub MaxGraduallyUpdate: u32 = 3;
pub MaxStorageKeyBytes: u32 = 100_000;
pub MaxStorageValueBytes: u32 = 100_000;
} }
impl Config for Runtime { impl Config for Runtime {
...@@ -51,6 +54,9 @@ impl Config for Runtime { ...@@ -51,6 +54,9 @@ impl Config for Runtime {
type UpdateFrequency = UpdateFrequency; type UpdateFrequency = UpdateFrequency;
type DispatchOrigin = frame_system::EnsureRoot<AccountId>; type DispatchOrigin = frame_system::EnsureRoot<AccountId>;
type WeightInfo = (); type WeightInfo = ();
type MaxGraduallyUpdate = MaxGraduallyUpdate;
type MaxStorageKeyBytes = MaxStorageKeyBytes;
type MaxStorageValueBytes = MaxStorageValueBytes;
} }
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Runtime>; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Runtime>;
......
...@@ -7,13 +7,17 @@ use codec::Encode; ...@@ -7,13 +7,17 @@ use codec::Encode;
use frame_support::{assert_noop, assert_ok}; use frame_support::{assert_noop, assert_ok};
use mock::{Event, *}; use mock::{Event, *};
use sp_runtime::{FixedPointNumber, FixedU128, Permill}; use sp_runtime::{FixedPointNumber, FixedU128, Permill};
use sp_std::convert::TryInto;
fn storage_set(key: &Vec<u8>, value: &Vec<u8>) { fn storage_set(key: &Vec<u8>, value: &Vec<u8>) {
// let bounded_key: StorageValueBytes<Runtime> =
// key.to_vec().try_into().unwrap(); let bounded_value:
// StorageValueBytes<Runtime> = key.to_vec().try_into().unwrap();
frame_support::storage::unhashed::put(key, value); frame_support::storage::unhashed::put(key, value);
} }
fn storage_get(key: &Vec<u8>) -> Vec<u8> { fn storage_get(key: &Vec<u8>) -> StorageValueBytes<Runtime> {
frame_support::storage::unhashed::get::<StorageValueBytes>(key).unwrap_or_default() frame_support::storage::unhashed::get::<StorageValueBytes<Runtime>>(key).unwrap_or_default()
} }
#[test] #[test]
...@@ -21,10 +25,10 @@ fn gradually_update_should_work() { ...@@ -21,10 +25,10 @@ fn gradually_update_should_work() {
ExtBuilder::default().build().execute_with(|| { ExtBuilder::default().build().execute_with(|| {
System::set_block_number(1); System::set_block_number(1);
let update = GraduallyUpdate { let update: GraduallyUpdate<StorageKeyBytes<Runtime>, StorageValueBytes<Runtime>> = GraduallyUpdate {
key: vec![1], key: vec![1].try_into().unwrap(),
target_value: vec![9], target_value: vec![9].try_into().unwrap(),
per_block: vec![1], per_block: vec![1].try_into().unwrap(),
}; };
assert_ok!(GraduallyUpdateModule::gradually_update(Origin::root(), update.clone())); assert_ok!(GraduallyUpdateModule::gradually_update(Origin::root(), update.clone()));
...@@ -42,29 +46,29 @@ fn gradually_update_should_work() { ...@@ -42,29 +46,29 @@ fn gradually_update_should_work() {
#[test] #[test]
fn gradually_update_should_fail() { fn gradually_update_should_fail() {
ExtBuilder::default().build().execute_with(|| { ExtBuilder::default().build().execute_with(|| {
let update = GraduallyUpdate { let update: GraduallyUpdate<StorageKeyBytes<Runtime>, StorageValueBytes<Runtime>> = GraduallyUpdate {
key: vec![1], key: vec![1].try_into().unwrap(),
target_value: 9u32.encode(), target_value: 9u32.encode().try_into().unwrap(),
per_block: 1u64.encode(), per_block: 1u64.encode().try_into().unwrap(),
}; };
assert_noop!( assert_noop!(
GraduallyUpdateModule::gradually_update(Origin::root(), update.clone()), GraduallyUpdateModule::gradually_update(Origin::root(), update.clone()),
Error::<Runtime>::InvalidPerBlockOrTargetValue Error::<Runtime>::InvalidPerBlockOrTargetValue
); );
let update = GraduallyUpdate { let update: GraduallyUpdate<StorageKeyBytes<Runtime>, StorageValueBytes<Runtime>> = GraduallyUpdate {
key: vec![1], key: vec![1].try_into().unwrap(),
target_value: 90u32.encode(), target_value: 90u32.encode().try_into().unwrap(),
per_block: 1u32.encode(), per_block: 1u32.encode().try_into().unwrap(),
}; };
assert_ok!(GraduallyUpdateModule::gradually_update(Origin::root(), update.clone())); assert_ok!(GraduallyUpdateModule::gradually_update(Origin::root(), update.clone()));
GraduallyUpdateModule::on_finalize(20); GraduallyUpdateModule::on_finalize(20);
let new_update = GraduallyUpdate { let new_update = GraduallyUpdate {
key: vec![1], key: vec![1].try_into().unwrap(),
target_value: 9u64.encode(), target_value: 9u64.encode().try_into().unwrap(),
per_block: 1u64.encode(), per_block: 1u64.encode().try_into().unwrap(),
}; };
assert_noop!( assert_noop!(
GraduallyUpdateModule::gradually_update(Origin::root(), new_update.clone()), GraduallyUpdateModule::gradually_update(Origin::root(), new_update.clone()),
...@@ -83,10 +87,10 @@ fn cancel_gradually_update_should_work() { ...@@ -83,10 +87,10 @@ fn cancel_gradually_update_should_work() {
ExtBuilder::default().build().execute_with(|| { ExtBuilder::default().build().execute_with(|| {
System::set_block_number(1); System::set_block_number(1);
let update = GraduallyUpdate { let update: GraduallyUpdate<StorageKeyBytes<Runtime>, StorageValueBytes<Runtime>> = GraduallyUpdate {
key: vec![1], key: vec![1].try_into().unwrap(),
target_value: vec![9], target_value: vec![9].try_into().unwrap(),
per_block: vec![1], per_block: vec![1].try_into().unwrap(),
}; };
assert_ok!(GraduallyUpdateModule::gradually_update(Origin::root(), update.clone())); assert_ok!(GraduallyUpdateModule::gradually_update(Origin::root(), update.clone()));
let gradually_update_event = Event::gradually_update(crate::Event::GraduallyUpdateAdded( let gradually_update_event = Event::gradually_update(crate::Event::GraduallyUpdateAdded(
...@@ -102,7 +106,8 @@ fn cancel_gradually_update_should_work() { ...@@ -102,7 +106,8 @@ fn cancel_gradually_update_should_work() {
Origin::root(), Origin::root(),
update.key.clone() update.key.clone()
)); ));
let cancel_gradually_update_event = Event::gradually_update(crate::Event::GraduallyUpdateCancelled(update.key)); let cancel_gradually_update_event =
Event::gradually_update(crate::Event::GraduallyUpdateCancelled(update.key.clone()));
assert!(System::events() assert!(System::events()
.iter() .iter()
.any(|record| record.event == cancel_gradually_update_event)); .any(|record| record.event == cancel_gradually_update_event));
...@@ -112,10 +117,10 @@ fn cancel_gradually_update_should_work() { ...@@ -112,10 +117,10 @@ fn cancel_gradually_update_should_work() {
#[test] #[test]
fn cancel_gradually_update_should_fail() { fn cancel_gradually_update_should_fail() {
ExtBuilder::default().build().execute_with(|| { ExtBuilder::default().build().execute_with(|| {
let update = GraduallyUpdate { let update: GraduallyUpdate<StorageKeyBytes<Runtime>, StorageValueBytes<Runtime>> = GraduallyUpdate {
key: vec![1], key: vec![1].try_into().unwrap(),
target_value: 9u32.encode(), target_value: 9u32.encode().try_into().unwrap(),
per_block: 1u32.encode(), per_block: 1u32.encode().try_into().unwrap(),
}; };
assert_noop!( assert_noop!(
GraduallyUpdateModule::cancel_gradually_update(Origin::root(), update.key.clone()), GraduallyUpdateModule::cancel_gradually_update(Origin::root(), update.key.clone()),
...@@ -136,21 +141,26 @@ fn add_on_finalize_should_work() { ...@@ -136,21 +141,26 @@ fn add_on_finalize_should_work() {
ExtBuilder::default().build().execute_with(|| { ExtBuilder::default().build().execute_with(|| {
System::set_block_number(1); System::set_block_number(1);
let update = GraduallyUpdate { let update: GraduallyUpdate<StorageKeyBytes<Runtime>, StorageValueBytes<Runtime>> = GraduallyUpdate {
key: vec![1], key: vec![1].try_into().unwrap(),
target_value: vec![30], target_value: vec![30].try_into().unwrap(),
per_block: vec![1], per_block: vec![1].try_into().unwrap(),
}; };
assert_ok!(GraduallyUpdateModule::gradually_update(Origin::root(), update.clone())); assert_ok!(GraduallyUpdateModule::gradually_update(Origin::root(), update.clone()));
assert_eq!(storage_get(&update.key), Vec::<u8>::new()); assert_eq!(storage_get(&update.key), Vec::<u8>::new());
GraduallyUpdateModule::on_finalize(10); GraduallyUpdateModule::on_finalize(10);
assert_eq!(storage_get(&update.key), vec![10]); assert_eq!(storage_get(&update.key), vec![10]);
let gradually_update_blocknumber_event = let gradually_update_blocknumber_event = Event::gradually_update(crate::Event::Updated(
Event::gradually_update(crate::Event::Updated(10, update.key.clone(), vec![10])); 10,
assert!(System::events() update.key.clone(),
.iter() vec![10].try_into().unwrap(),
.any(|record| record.event == gradually_update_blocknumber_event)); ));
println!("Length {}", System::events().len());
assert!(System::events().iter().any(|record| {
println!("{:?}", record.event);
record.event == gradually_update_blocknumber_event
}));
assert_eq!(System::events().len(), 2); assert_eq!(System::events().len(), 2);
GraduallyUpdateModule::on_finalize(15); GraduallyUpdateModule::on_finalize(15);
...@@ -159,8 +169,11 @@ fn add_on_finalize_should_work() { ...@@ -159,8 +169,11 @@ fn add_on_finalize_should_work() {
GraduallyUpdateModule::on_finalize(20); GraduallyUpdateModule::on_finalize(20);
assert_eq!(storage_get(&update.key), vec![20]); assert_eq!(storage_get(&update.key), vec![20]);
let gradually_update_blocknumber_event = let gradually_update_blocknumber_event = Event::gradually_update(crate::Event::Updated(
Event::gradually_update(crate::Event::Updated(20, update.key.clone(), vec![20])); 20,
update.key.clone(),
vec![20].try_into().unwrap(),
));
assert!(System::events() assert!(System::events()
.iter() .iter()
.any(|record| record.event == gradually_update_blocknumber_event)); .any(|record| record.event == gradually_update_blocknumber_event));
...@@ -168,8 +181,11 @@ fn add_on_finalize_should_work() { ...@@ -168,8 +181,11 @@ fn add_on_finalize_should_work() {
GraduallyUpdateModule::on_finalize(40); GraduallyUpdateModule::on_finalize(40);
assert_eq!(storage_get(&update.key), vec![30]); assert_eq!(storage_get(&update.key), vec![30]);
let gradually_update_blocknumber_event = let gradually_update_blocknumber_event = Event::gradually_update(crate::Event::Updated(
Event::gradually_update(crate::Event::Updated(40, update.key.clone(), vec![30])); 40,
update.key.clone(),
vec![30].try_into().unwrap(),
));
assert!(System::events() assert!(System::events()
.iter() .iter()
.any(|record| record.event == gradually_update_blocknumber_event)); .any(|record| record.event == gradually_update_blocknumber_event));
...@@ -181,10 +197,10 @@ fn sub_on_finalize_should_work() { ...@@ -181,10 +197,10 @@ fn sub_on_finalize_should_work() {
ExtBuilder::default().build().execute_with(|| { ExtBuilder::default().build().execute_with(|| {
System::set_block_number(1); System::set_block_number(1);
let update = GraduallyUpdate { let update: GraduallyUpdate<StorageKeyBytes<Runtime>, StorageValueBytes<Runtime>> = GraduallyUpdate {
key: vec![1], key: vec![1].try_into().unwrap(),
target_value: vec![5], target_value: vec![5].try_into().unwrap(),
per_block: vec![1], per_block: vec![1].try_into().unwrap(),
}; };
storage_set(&update.key, &vec![30]); storage_set(&update.key, &vec![30]);
...@@ -193,8 +209,11 @@ fn sub_on_finalize_should_work() { ...@@ -193,8 +209,11 @@ fn sub_on_finalize_should_work() {
GraduallyUpdateModule::on_finalize(10); GraduallyUpdateModule::on_finalize(10);
assert_eq!(storage_get(&update.key), vec![20]); assert_eq!(storage_get(&update.key), vec![20]);
let gradually_update_blocknumber_event = let gradually_update_blocknumber_event = Event::gradually_update(crate::Event::Updated(
Event::gradually_update(crate::Event::Updated(10, update.key.clone(), vec![20])); 10,
update.key.clone(),
vec![20].try_into().unwrap(),
));
assert!(System::events() assert!(System::events()
.iter() .iter()
.any(|record| record.event == gradually_update_blocknumber_event)); .any(|record| record.event == gradually_update_blocknumber_event));
...@@ -206,8 +225,11 @@ fn sub_on_finalize_should_work() { ...@@ -206,8 +225,11 @@ fn sub_on_finalize_should_work() {
GraduallyUpdateModule::on_finalize(20); GraduallyUpdateModule::on_finalize(20);
assert_eq!(storage_get(&update.key), vec![10]); assert_eq!(storage_get(&update.key), vec![10]);
let gradually_update_blocknumber_event = let gradually_update_blocknumber_event = Event::gradually_update(crate::Event::Updated(
Event::gradually_update(crate::Event::Updated(20, update.key.clone(), vec![10])); 20,
update.key.clone(),
vec![10].try_into().unwrap(),
));
assert!(System::events() assert!(System::events()
.iter() .iter()
.any(|record| record.event == gradually_update_blocknumber_event)); .any(|record| record.event == gradually_update_blocknumber_event));
...@@ -215,8 +237,11 @@ fn sub_on_finalize_should_work() { ...@@ -215,8 +237,11 @@ fn sub_on_finalize_should_work() {
GraduallyUpdateModule::on_finalize(40); GraduallyUpdateModule::on_finalize(40);
assert_eq!(storage_get(&update.key), vec![5]); assert_eq!(storage_get(&update.key), vec![5]);
let gradually_update_blocknumber_event = let gradually_update_blocknumber_event = Event::gradually_update(crate::Event::Updated(
Event::gradually_update(crate::Event::Updated(40, update.key.clone(), vec![5])); 40,
update.key.clone(),
vec![5].try_into().unwrap(),
));
assert!(System::events() assert!(System::events()
.iter() .iter()
.any(|record| record.event == gradually_update_blocknumber_event)); .any(|record| record.event == gradually_update_blocknumber_event));
...@@ -226,10 +251,10 @@ fn sub_on_finalize_should_work() { ...@@ -226,10 +251,10 @@ fn sub_on_finalize_should_work() {
#[test] #[test]
fn u32_should_work() { fn u32_should_work() {
ExtBuilder::default().build().execute_with(|| { ExtBuilder::default().build().execute_with(|| {
let update = GraduallyUpdate { let update: GraduallyUpdate<StorageKeyBytes<Runtime>, StorageValueBytes<Runtime>> = GraduallyUpdate {
key: vec![1], key: vec![1].try_into().unwrap(),
target_value: 30u32.encode(), target_value: 30u32.encode().try_into().unwrap(),
per_block: 1u32.encode(), per_block: 1u32.encode().try_into().unwrap(),
}; };
assert_ok!(GraduallyUpdateModule::gradually_update(Origin::root(), update.clone())); assert_ok!(GraduallyUpdateModule::gradually_update(Origin::root(), update.clone()));
assert_eq!(storage_get(&update.key), Vec::<u8>::new()); assert_eq!(storage_get(&update.key), Vec::<u8>::new());
...@@ -247,10 +272,10 @@ fn u32_should_work() { ...@@ -247,10 +272,10 @@ fn u32_should_work() {
#[test] #[test]
fn u128_should_work() { fn u128_should_work() {
ExtBuilder::default().build().execute_with(|| { ExtBuilder::default().build().execute_with(|| {
let update = GraduallyUpdate { let update: GraduallyUpdate<StorageKeyBytes<Runtime>, StorageValueBytes<Runtime>> = GraduallyUpdate {
key: vec![1], key: vec![1].try_into().unwrap(),
target_value: 30u128.encode(), target_value: 30u128.encode().try_into().unwrap(),
per_block: 1u128.encode(), per_block: 1u128.encode().try_into().unwrap(),
}; };
assert_ok!(GraduallyUpdateModule::gradually_update(Origin::root(), update.clone())); assert_ok!(GraduallyUpdateModule::gradually_update(Origin::root(), update.clone()));
assert_eq!(storage_get(&update.key), Vec::<u8>::new()); assert_eq!(storage_get(&update.key), Vec::<u8>::new());
...@@ -280,10 +305,10 @@ fn u128_should_work() { ...@@ -280,10 +305,10 @@ fn u128_should_work() {
#[test] #[test]
fn permill_should_work() { fn permill_should_work() {
ExtBuilder::default().build().execute_with(|| { ExtBuilder::default().build().execute_with(|| {
let update = GraduallyUpdate { let update: GraduallyUpdate<StorageKeyBytes<Runtime>, StorageValueBytes<Runtime>> = GraduallyUpdate {
key: vec![1], key: vec![1].try_into().unwrap(),
target_value: Permill::from_percent(30).encode(), target_value: Permill::from_percent(30).encode().try_into().unwrap(),
per_block: Permill::from_percent(1).encode(), per_block: Permill::from_percent(1).encode().try_into().unwrap(),
}; };
assert_ok!(GraduallyUpdateModule::gradually_update(Origin::root(), update.clone())); assert_ok!(GraduallyUpdateModule::gradually_update(Origin::root(), update.clone()));
assert_eq!(storage_get(&update.key), Vec::<u8>::new()); assert_eq!(storage_get(&update.key), Vec::<u8>::new());
...@@ -301,10 +326,10 @@ fn permill_should_work() { ...@@ -301,10 +326,10 @@ fn permill_should_work() {
#[test] #[test]
fn fixedu128_should_work() { fn fixedu128_should_work() {
ExtBuilder::default().build().execute_with(|| { ExtBuilder::default().build().execute_with(|| {
let update = GraduallyUpdate { let update: GraduallyUpdate<StorageKeyBytes<Runtime>, StorageValueBytes<Runtime>> = GraduallyUpdate {
key: vec![1], key: vec![1].try_into().unwrap(),
target_value: FixedU128::saturating_from_rational(30, 1).encode(), target_value: FixedU128::saturating_from_rational(30, 1).encode().try_into().unwrap(),
per_block: FixedU128::saturating_from_rational(1, 1).encode(), per_block: FixedU128::saturating_from_rational(1, 1).encode().try_into().unwrap(),
}; };
assert_ok!(GraduallyUpdateModule::gradually_update(Origin::root(), update.clone())); assert_ok!(GraduallyUpdateModule::gradually_update(Origin::root(), update.clone()));
assert_eq!(storage_get(&update.key), Vec::<u8>::new()); assert_eq!(storage_get(&update.key), Vec::<u8>::new());
...@@ -336,20 +361,20 @@ fn finish_multiple_on_finalize_should_work() { ...@@ -336,20 +361,20 @@ fn finish_multiple_on_finalize_should_work() {
ExtBuilder::default().build().execute_with(|| { ExtBuilder::default().build().execute_with(|| {
System::set_block_number(1); System::set_block_number(1);
let update = GraduallyUpdate { let update: GraduallyUpdate<StorageKeyBytes<Runtime>, StorageValueBytes<Runtime>> = GraduallyUpdate {
key: vec![10], key: vec![10].try_into().unwrap(),
target_value: vec![30], target_value: vec![30].try_into().unwrap(),
per_block: vec![1], per_block: vec![1].try_into().unwrap(),
}; };
let update2 = GraduallyUpdate { let update2: GraduallyUpdate<StorageKeyBytes<Runtime>, StorageValueBytes<Runtime>> = GraduallyUpdate {
key: vec![20], key: vec![20].try_into().unwrap(),
target_value: vec![60], target_value: vec![60].try_into().unwrap(),
per_block: vec![2], per_block: vec![2].try_into().unwrap(),
}; };
let update3 = GraduallyUpdate { let update3: GraduallyUpdate<StorageKeyBytes<Runtime>, StorageValueBytes<Runtime>> = GraduallyUpdate {
key: vec![30], key: vec![30].try_into().unwrap(),
target_value: vec![100], target_value: vec![100].try_into().unwrap(),
per_block: vec![3], per_block: vec![3].try_into().unwrap(),
}; };
assert_ok!(GraduallyUpdateModule::gradually_update(Origin::root(), update.clone())); assert_ok!(GraduallyUpdateModule::gradually_update(Origin::root(), update.clone()));
assert_ok!(GraduallyUpdateModule::gradually_update(Origin::root(), update2.clone())); assert_ok!(GraduallyUpdateModule::gradually_update(Origin::root(), update2.clone()));
...@@ -381,3 +406,50 @@ fn finish_multiple_on_finalize_should_work() { ...@@ -381,3 +406,50 @@ fn finish_multiple_on_finalize_should_work() {
assert_eq!(storage_get(&update3.key), vec![100]); assert_eq!(storage_get(&update3.key), vec![100]);
}); });
} }
#[test]
fn exceeding_max_gradually_updates_should_fail() {
ExtBuilder::default().build().execute_with(|| {
System::set_block_number(1);
let update: GraduallyUpdate<StorageKeyBytes<Runtime>, StorageValueBytes<Runtime>> = GraduallyUpdate {
key: vec![10].try_into().unwrap(),
target_value: vec![30].try_into().unwrap(),
per_block: vec![1].try_into().unwrap(),
};
let update2: GraduallyUpdate<StorageKeyBytes<Runtime>, StorageValueBytes<Runtime>> = GraduallyUpdate {
key: vec![20].try_into().unwrap(),
target_value: vec![60].try_into().unwrap(),
per_block: vec![2].try_into().unwrap(),
};
let update3: GraduallyUpdate<StorageKeyBytes<Runtime>, StorageValueBytes<Runtime>> = GraduallyUpdate {
key: vec![30].try_into().unwrap(),
target_value: vec![100].try_into().unwrap(),
per_block: vec![3].try_into().unwrap(),
};
let update4: GraduallyUpdate<StorageKeyBytes<Runtime>, StorageValueBytes<Runtime>> = GraduallyUpdate {
key: vec![40].try_into().unwrap(),
target_value: vec![120].try_into().unwrap(),
per_block: vec![4].try_into().unwrap(),
};
assert_ok!(GraduallyUpdateModule::gradually_update(Origin::root(), update.clone()));
assert_ok!(GraduallyUpdateModule::gradually_update(Origin::root(), update2.clone()));
assert_ok!(GraduallyUpdateModule::gradually_update(Origin::root(), update3.clone()));
assert_noop!(
GraduallyUpdateModule::gradually_update(Origin::root(), update4.clone()),
Error::<Runtime>::MaxGraduallyUpdateExceeded
);
GraduallyUpdateModule::on_finalize(10);
GraduallyUpdateModule::on_finalize(20);
GraduallyUpdateModule::on_finalize(30);
assert_ok!(GraduallyUpdateModule::gradually_update(Origin::root(), update4.clone()));
GraduallyUpdateModule::on_finalize(40);
GraduallyUpdateModule::on_finalize(50);
GraduallyUpdateModule::on_finalize(60);
assert_eq!(storage_get(&update.key), vec![30]);
assert_eq!(storage_get(&update2.key), vec![60]);
assert_eq!(storage_get(&update3.key), vec![100]);
assert_eq!(storage_get(&update4.key), vec![120]);
});
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment