Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add BoundedVec to gradually-update #498

Merged
merged 4 commits into from
May 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 43 additions & 23 deletions gradually-update/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ use frame_support::{
ensure,
pallet_prelude::*,
storage,
traits::{EnsureOrigin, Get},
traits::{EnsureOrigin, Get, MaxEncodedLen},
BoundedVec,
};
use frame_system::pallet_prelude::*;
use sp_runtime::{traits::SaturatedConversion, DispatchResult, RuntimeDebug};
use sp_std::prelude::Vec;
use sp_std::convert::TryInto;

mod default_weight;
mod mock;
Expand All @@ -38,14 +39,11 @@ mod tests;
/// Gradually update a value stored at `key` to `target_value`,
/// change `per_block` * `T::UpdateFrequency` per `T::UpdateFrequency`
/// blocks.
#[derive(Encode, Decode, Clone, Eq, PartialEq, RuntimeDebug)]
pub struct GraduallyUpdate {
/// The storage key of the value to update
pub key: StorageKeyBytes,
/// The target value
pub target_value: StorageValueBytes,
/// The amount of the value to update per one block
pub per_block: StorageValueBytes,
#[derive(Encode, Decode, Clone, Eq, PartialEq, MaxEncodedLen, RuntimeDebug)]
pub struct GraduallyUpdate<Key, Value> {
pub key: Key,
pub target_value: Value,
pub per_block: Value,
}

pub use module::*;
Expand All @@ -60,8 +58,10 @@ pub mod module {
fn on_finalize(u: u32) -> Weight;
}

pub(crate) type StorageKeyBytes = Vec<u8>;
pub(crate) type StorageValueBytes = Vec<u8>;
pub(crate) type StorageKeyBytes<T> = BoundedVec<u8, <T as Config>::MaxStorageKeyBytes>;
pub(crate) type StorageValueBytes<T> = BoundedVec<u8, <T as Config>::MaxStorageValueBytes>;

type GraduallyUpdateOf<T> = GraduallyUpdate<StorageKeyBytes<T>, StorageValueBytes<T>>;

#[pallet::config]
pub trait Config: frame_system::Config {
Expand All @@ -76,6 +76,15 @@ pub mod module {

/// Weight information for extrinsics in this module.
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]
Expand All @@ -88,23 +97,30 @@ pub mod module {
GraduallyUpdateHasExisted,
/// No update exists to cancel.
GraduallyUpdateNotFound,
/// Maximum updates exceeded
MaxGraduallyUpdateExceeded,
/// Maximum key size exceeded
MaxStorageKeyBytesExceeded,
/// Maximum value size exceeded
MaxStorageValueBytesExceeded,
}

#[pallet::event]
#[pallet::generate_deposit(pub(crate) fn deposit_event)]
pub enum Event<T: Config> {
/// Gradually update added. [key, per_block, target_value]
GraduallyUpdateAdded(StorageKeyBytes, StorageValueBytes, StorageValueBytes),
GraduallyUpdateAdded(StorageKeyBytes<T>, StorageValueBytes<T>, StorageValueBytes<T>),
/// Gradually update cancelled. [key]
GraduallyUpdateCancelled(StorageKeyBytes),
GraduallyUpdateCancelled(StorageKeyBytes<T>),
/// 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
#[pallet::storage]
#[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
#[pallet::storage]
Expand Down Expand Up @@ -135,7 +151,7 @@ pub mod module {
impl<T: Config> Pallet<T> {
/// Add gradually_update to adjust numeric parameter.
#[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)?;

// Support max value is u128, ensure per_block and target_value <= 16 bytes.
Expand All @@ -145,7 +161,7 @@ pub mod module {
);

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!(
current_value.len() == update.target_value.len(),
Error::<T>::InvalidTargetValue
Expand All @@ -158,7 +174,9 @@ pub mod module {
Error::<T>::GraduallyUpdateHasExisted
);

gradually_updates.push(update.clone());
gradually_updates
.try_push(update.clone())
.map_err(|_| Error::<T>::MaxGraduallyUpdateExceeded)?;

Ok(())
})?;
Expand All @@ -173,7 +191,7 @@ pub mod module {

/// Cancel gradually_update to adjust numeric parameter.
#[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)?;

GraduallyUpdates::<T>::try_mutate(|gradually_updates| -> DispatchResult {
Expand Down Expand Up @@ -206,7 +224,7 @@ impl<T: Config> Pallet<T> {

gradually_updates.retain(|update| {
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 frequency_u128: u128 = T::UpdateFrequency::get().saturated_into();
Expand All @@ -232,7 +250,9 @@ impl<T: Config> Pallet<T> {

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
});
Expand All @@ -246,7 +266,7 @@ impl<T: Config> Pallet<T> {
}

#[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];
for (i, v) in input.iter().enumerate() {
array[i] = *v;
Expand Down
6 changes: 6 additions & 0 deletions gradually-update/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,19 @@ impl frame_system::Config for Runtime {

parameter_types! {
pub const UpdateFrequency: BlockNumber = 10;
pub MaxGraduallyUpdate: u32 = 3;
pub MaxStorageKeyBytes: u32 = 100_000;
pub MaxStorageValueBytes: u32 = 100_000;
}

impl Config for Runtime {
type Event = Event;
type UpdateFrequency = UpdateFrequency;
type DispatchOrigin = frame_system::EnsureRoot<AccountId>;
type WeightInfo = ();
type MaxGraduallyUpdate = MaxGraduallyUpdate;
type MaxStorageKeyBytes = MaxStorageKeyBytes;
type MaxStorageValueBytes = MaxStorageValueBytes;
}

type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Runtime>;
Expand Down
Loading