From 06c3310930fa547ec2216ea6b205fb649f4bd33a Mon Sep 17 00:00:00 2001 From: ytqaljn <2716693942@qq.com> Date: Thu, 2 Nov 2023 20:58:42 -0700 Subject: [PATCH] feat: buy space for others --- Cargo.lock | 1 + c-pallets/storage-handler/Cargo.toml | 7 +- c-pallets/storage-handler/src/lib.rs | 135 ++++++++++++++++++++++++- c-pallets/storage-handler/src/types.rs | 20 ++++ runtime/src/lib.rs | 2 +- 5 files changed, 158 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7e0f0526..47560446 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6571,6 +6571,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", + "sp-core", "sp-runtime", "sp-std", ] diff --git a/c-pallets/storage-handler/Cargo.toml b/c-pallets/storage-handler/Cargo.toml index acbbcf90..bcababc9 100644 --- a/c-pallets/storage-handler/Cargo.toml +++ b/c-pallets/storage-handler/Cargo.toml @@ -17,10 +17,13 @@ serde = { version = "1.0.136", optional = true } # substrate pallet frame-support = { version = "4.0.0-dev", git = 'https://github.com/CESSProject/substrate', branch = "cess-polkadot-v0.9.42", default-features = false } frame-system = { version = "4.0.0-dev", git = 'https://github.com/CESSProject/substrate', branch = "cess-polkadot-v0.9.42", default-features = false } -sp-std = { version = "5.0.0", git = 'https://github.com/CESSProject/substrate', branch = "cess-polkadot-v0.9.42", default-features = false } +frame-benchmarking = { version = '4.0.0-dev', git = 'https://github.com/CESSProject/substrate', branch = "cess-polkadot-v0.9.42", default-features = false } pallet-balances = { version = "4.0.0-dev", git = 'https://github.com/CESSProject/substrate', branch = "cess-polkadot-v0.9.42", default-features = false } + +# substrate primitives +sp-core = { version = "7.0.0", git = 'https://github.com/CESSProject/substrate', branch = "cess-polkadot-v0.9.42", default-features = false } +sp-std = { version = "5.0.0", git = 'https://github.com/CESSProject/substrate', branch = "cess-polkadot-v0.9.42", default-features = false } sp-runtime = { version = "7.0.0", git = 'https://github.com/CESSProject/substrate', branch = "cess-polkadot-v0.9.42", default-features = false } -frame-benchmarking = { version = '4.0.0-dev', git = 'https://github.com/CESSProject/substrate', branch = "cess-polkadot-v0.9.42", default-features = false } # local dependencies cp-cess-common = { path = '../../primitives/common', default-features = false } diff --git a/c-pallets/storage-handler/src/lib.rs b/c-pallets/storage-handler/src/lib.rs index 30b5f03f..acd81dac 100644 --- a/c-pallets/storage-handler/src/lib.rs +++ b/c-pallets/storage-handler/src/lib.rs @@ -8,7 +8,7 @@ use frame_support::{ Blake2_128Concat, PalletId, weights::Weight, ensure, transactional, storage::bounded_vec::BoundedVec, traits::{ - StorageVersion, Currency, ReservableCurrency, + StorageVersion, Currency, ReservableCurrency, Randomness, }, pallet_prelude::*, }; @@ -25,6 +25,7 @@ use codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; use cp_cess_common::*; use pallet_cess_treasury::{TreasuryHandle}; +use sp_core::H256; pub mod weights; use weights::WeightInfo; @@ -68,9 +69,6 @@ pub mod pallet { #[pallet::constant] type RewardPalletId: Get; - #[pallet::constant] - type TreasuryPalletId: Get; - #[pallet::constant] type StateStringMax: Get + Clone + Eq + PartialEq; @@ -78,6 +76,8 @@ pub mod pallet { type FrozenDays: Get> + Clone + Eq + PartialEq; type CessTreasuryHandle: TreasuryHandle, BalanceOf>; + + type MyRandomness: Randomness, Self::BlockNumber>; } #[pallet::event] @@ -93,6 +93,10 @@ pub mod pallet { LeaseExpired { acc: AccountOf, size: u128 }, //Storage space expiring within 24 hours LeaseExpireIn24Hours { acc: AccountOf, size: u128 }, + + CreatePayOrder { order_hash: BoundedVec> }, + + PaidOrder { order_hash: BoundedVec> }, } #[pallet::error] @@ -118,6 +122,10 @@ pub mod pallet { LeaseFreeze, LeaseExpired, + + RandomErr, + + NoOrder, } #[pallet::storage] @@ -143,6 +151,10 @@ pub mod pallet { #[pallet::getter(fn purchased_space)] pub(super) type PurchasedSpace = StorageValue<_, u128, ValueQuery>; + #[pallet::storage] + #[pallet::getter(fn pay_order)] + pub(super) type PayOrder = StorageMap<_, Blake2_128Concat, BoundedVec>, OrderInfo>; + #[pallet::pallet] #[pallet::storage_version(STORAGE_VERSION)] pub struct Pallet(PhantomData); @@ -351,10 +363,125 @@ pub mod pallet { Ok(()) }) } + + #[pallet::call_index(6)] + #[transactional] + #[pallet::weight(Weight::zero())] + pub fn create_order(origin: OriginFor, target_acc: AccountOf, order_type: OrderType, gib_count: u32, days: u32) -> DispatchResult { + let sender = ensure_signed(origin)?; + + let price = match order_type { + OrderType::Buy => { + ensure!(!>::contains_key(&target_acc), Error::::PurchasedSpace); + let price = Self::calculate_price(gib_count, days)?; + price + }, + OrderType::Expansion => { + let user_owned_space = >::try_get(&target_acc).map_err(|_| Error::::NotPurchasedSpace)?; + let remain_day = Self::calculate_remain_day(user_owned_space.deadline)?; + let price = Self::calculate_price(gib_count, remain_day.saturated_into())?; + price + }, + OrderType::Renewal => { + let user_owned_space = >::try_get(&target_acc).map_err(|_| Error::::NotPurchasedSpace)?; + let gib_count = user_owned_space.total_space.checked_div(G_BYTE).ok_or(Error::::Overflow)?; + let price = Self::calculate_price(gib_count as u32, days)?; + price + }, + }; + + let pay_order = OrderInfo:: { + pay: price, + gib_count: gib_count, + days, + expired: 10u32.saturated_into(), + pay_acc: sender, + target_acc: target_acc, + order_type, + }; + + let now = >::block_number(); + let (seed, _) = + T::MyRandomness::random(&(T::RewardPalletId::get(), now).encode()); + let seed = match seed { + Some(v) => v, + None => Default::default(), + }; + let random_hash = + ::decode(&mut seed.as_ref()).map_err(|_| Error::::RandomErr)?; + + let random_hash: BoundedVec> = random_hash.as_bytes().to_vec().try_into().map_err(|_| Error::::BoundedVecError)?; + >::insert(&random_hash, pay_order); + + Self::deposit_event(Event::::CreatePayOrder { order_hash: random_hash }); + + Ok(()) + } + + #[pallet::call_index(7)] + #[pallet::weight(Weight::zero())] + pub fn exec_order(origin: OriginFor, order_id: BoundedVec>) -> DispatchResult { + let sender = ensure_signed(origin)?; + + let order = >::try_get(&order_id).map_err(|_| Error::::NoOrder)?; + match order.order_type { + OrderType::Buy => { + ensure!(!>::contains_key(&order.target_acc), Error::::PurchasedSpace); + let space = G_BYTE.checked_mul(order.gib_count as u128).ok_or(Error::::Overflow)?; + Self::add_user_purchased_space(order.target_acc, space, order.days)?; + Self::add_purchased_space(space)?; + }, + OrderType::Expansion => { + ensure!(>::contains_key(&order.target_acc), Error::::NotPurchasedSpace); + let space = G_BYTE.checked_mul(order.gib_count as u128).ok_or(Error::::Overflow)?; + Self::add_purchased_space(space)?; + Self::expension_puchased_package(order.target_acc, space)?; + }, + OrderType::Renewal => { + ensure!(>::contains_key(&order.target_acc), Error::::NotPurchasedSpace); + Self::update_puchased_package(order.target_acc, order.days)?; + }, + }; + + T::CessTreasuryHandle::send_to_sid(sender, order.pay)?; + Self::deposit_event(Event::::PaidOrder { order_hash: order_id }); + + Ok(()) + } } } impl Pallet { + fn calculate_price(gib_count: u32, days: u32) -> Result, DispatchError> { + let unit_price: u128 = >::get().unwrap().try_into().map_err(|_| Error::::Overflow)?; + let gib_count: u128 = gib_count.into(); + let days: u128 = days.into(); + let price = gib_count + .checked_mul(days).ok_or(Error::::Overflow)? + .checked_mul(unit_price).ok_or(Error::::Overflow)?; + + let price: BalanceOf = price.try_into().map_err(|_| Error::::Overflow)?; + Ok(price) + } + + fn calculate_remain_day(deadline: BlockNumberOf) -> Result, DispatchError>{ + let now = >::block_number(); + //Calculate remaining days. + let block_oneday: BlockNumberOf = ::OneDay::get(); + let diff_block = deadline.checked_sub(&now).ok_or(Error::::Overflow)?; + let mut remain_day: u32 = diff_block + .checked_div(&block_oneday) + .ok_or(Error::::Overflow)? + .saturated_into(); + if diff_block % block_oneday != 0u32.saturated_into() { + remain_day = remain_day + .checked_add(1) + .ok_or(Error::::Overflow)? + .saturated_into(); + } + + Ok(remain_day.into()) + } /// helper: update_puchased_package. /// /// How to update the corresponding data after renewing the package. diff --git a/c-pallets/storage-handler/src/types.rs b/c-pallets/storage-handler/src/types.rs index 2d29b7b5..7d22c6eb 100644 --- a/c-pallets/storage-handler/src/types.rs +++ b/c-pallets/storage-handler/src/types.rs @@ -11,4 +11,24 @@ pub struct OwnedSpaceDetails { pub(super) start: BlockNumberOf, pub(super) deadline: BlockNumberOf, pub(super) state: BoundedVec, +} + +#[derive(PartialEq, Eq, Encode, Decode, Clone, RuntimeDebug, MaxEncodedLen, TypeInfo)] +#[scale_info(skip_type_params(T))] +#[codec(mel_bound())] +pub struct OrderInfo { + pub(super) pay: BalanceOf, + pub(super) gib_count: u32, + pub(super) days: u32, + pub(super) expired: BlockNumberOf, + pub(super) pay_acc: AccountOf, + pub(super) target_acc: AccountOf, + pub(super) order_type: OrderType, +} + +#[derive(PartialEq, Eq, Encode, Decode, Clone, RuntimeDebug, MaxEncodedLen, TypeInfo)] +pub enum OrderType { + Buy, + Expansion, + Renewal, } \ No newline at end of file diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index c6ae616d..0fda2c85 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -986,7 +986,7 @@ impl pallet_storage_handler::Config for Runtime { type WeightInfo = pallet_storage_handler::weights::SubstrateWeight; type OneDay = OneDay; type RewardPalletId = RewardPalletId; - type TreasuryPalletId = TreasuryPalletId; + type MyRandomness = pallet_rrsc::ParentBlockRandomness; type StateStringMax = StateStringMax; type FrozenDays = FrozenDays; type CessTreasuryHandle = CessTreasury;