Skip to content

Commit

Permalink
update logic for customer unlocks based on unlock delay in blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
Raid5594 committed Nov 8, 2023
1 parent 6b8e6c5 commit 9be9df7
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 41 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion pallets/ddc-customers/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ ddc-primitives = { version = "0.1.0", default-features = false, path = "../../pr
ddc-traits = { version = "0.1.0", default-features = false, path = "../../traits" }
frame-support = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.30" }
frame-system = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.30" }
pallet-ddc-staking = { version = "4.7.0", default-features = false, path = "../ddc-staking" }
scale-info = { version = "2.1.1", default-features = false, features = ["derive"] }
sp-io = { version = "6.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.30" }
sp-runtime = { version = "6.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.30" }
Expand Down
60 changes: 30 additions & 30 deletions pallets/ddc-customers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,11 @@ use frame_support::{
traits::{Currency, DefensiveSaturating, ExistenceRequirement},
BoundedVec, PalletId,
};
pub use pallet_ddc_staking::{self as ddc_staking};
use scale_info::TypeInfo;
use sp_runtime::{
traits::{AccountIdConversion, AtLeast32BitUnsigned, Saturating, Zero},
RuntimeDebug, SaturatedConversion,
};
use sp_staking::EraIndex;
use sp_std::prelude::*;

pub use pallet::*;
Expand All @@ -32,13 +30,14 @@ parameter_types! {

/// Just a Balance/BlockNumber tuple to encode when a chunk of funds will be unlocked.
#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
pub struct UnlockChunk<Balance: HasCompact> {
#[scale_info(skip_type_params(T))]
pub struct UnlockChunk<Balance: HasCompact, T: Config> {
/// Amount of funds to be unlocked.
#[codec(compact)]
value: Balance,
/// Era number at which point it'll be unlocked.
/// Block number at which point it'll be unlocked.
#[codec(compact)]
era: EraIndex,
block: T::BlockNumber,
}

#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
Expand All @@ -55,7 +54,8 @@ pub struct BucketsDetails<Balance: HasCompact> {
}

#[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
pub struct AccountsLedger<AccountId, Balance: HasCompact> {
#[scale_info(skip_type_params(T))]
pub struct AccountsLedger<AccountId, Balance: HasCompact, T: Config> {
/// The owner account whose balance is actually locked and can be used for CDN usage.
pub owner: AccountId,
/// The total amount of the owner's balance that we are currently accounting for.
Expand All @@ -70,11 +70,14 @@ pub struct AccountsLedger<AccountId, Balance: HasCompact> {
/// (assuming that the content owner has to pay for network usage). It is assumed that this
/// will be treated as a first in, first out queue where the new (higher value) eras get pushed
/// on the back.
pub unlocking: BoundedVec<UnlockChunk<Balance>, MaxUnlockingChunks>,
pub unlocking: BoundedVec<UnlockChunk<Balance, T>, MaxUnlockingChunks>,
}

impl<AccountId, Balance: HasCompact + Copy + Saturating + AtLeast32BitUnsigned + Zero>
AccountsLedger<AccountId, Balance>
impl<
AccountId,
Balance: HasCompact + Copy + Saturating + AtLeast32BitUnsigned + Zero,
T: Config,
> AccountsLedger<AccountId, Balance, T>
{
/// Initializes the default object using the given owner.
pub fn default_from(owner: AccountId) -> Self {
Expand All @@ -83,14 +86,14 @@ impl<AccountId, Balance: HasCompact + Copy + Saturating + AtLeast32BitUnsigned +

/// Remove entries from `unlocking` that are sufficiently old and reduce the
/// total by the sum of their balances.
fn consolidate_unlocked(self, current_era: EraIndex) -> Self {
fn consolidate_unlocked(self, current_block: T::BlockNumber) -> Self {
let mut total = self.total;
let unlocking: BoundedVec<_, _> = self
.unlocking
.into_iter()
.filter(|chunk| {
log::debug!("Chunk era: {:?}", chunk.era);
if chunk.era > current_era {
log::debug!("Chunk era: {:?}", chunk.block);
if chunk.block > current_block {
true
} else {
total = total.saturating_sub(chunk.value);
Expand Down Expand Up @@ -146,23 +149,23 @@ pub mod pallet {
pub struct Pallet<T>(_);

#[pallet::config]
pub trait Config: frame_system::Config + ddc_staking::Config {
pub trait Config: frame_system::Config {
/// The accounts's pallet id, used for deriving its sovereign account ID.
#[pallet::constant]
type PalletId: Get<PalletId>;
type Currency: LockableCurrency<Self::AccountId, Moment = Self::BlockNumber>;
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
/// Number of eras that staked funds must remain locked for.
#[pallet::constant]
type LockingDuration: Get<EraIndex>;
type UnlockingDelay: Get<<Self as frame_system::Config>::BlockNumber>;
type ClusterVisitor: ClusterVisitor<Self>;
}

/// Map from all (unlocked) "owner" accounts to the info regarding the staking.
#[pallet::storage]
#[pallet::getter(fn ledger)]
pub type Ledger<T: Config> =
StorageMap<_, Identity, T::AccountId, AccountsLedger<T::AccountId, BalanceOf<T>>>;
StorageMap<_, Identity, T::AccountId, AccountsLedger<T::AccountId, BalanceOf<T>, T>>;

#[pallet::type_value]
pub fn DefaultBucketCount<T: Config>() -> BucketId {
Expand Down Expand Up @@ -214,8 +217,6 @@ pub mod pallet {
NoBucketWithId,
/// Internal state has become somehow corrupted and the operation cannot continue.
BadState,
/// Current era not set during runtime
DDCEraNotSet,
/// Bucket with specified id doesn't exist
BucketDoesNotExist,
/// DDC Cluster with provided id doesn't exist
Expand Down Expand Up @@ -376,20 +377,22 @@ pub mod pallet {
ledger.active = Zero::zero();
}

let current_era = 0;
// Note: locking for extra era to allow for accounting
let era = current_era + <T as pallet::Config>::LockingDuration::get();
log::debug!("Era for the unlock: {:?}", era);
let current_block = <frame_system::Pallet<T>>::block_number();
// Note: locking for extra block to allow for accounting
let block = current_block + <T as pallet::Config>::UnlockingDelay::get();
log::debug!("Block for the unlock: {:?}", block);

if let Some(chunk) = ledger.unlocking.last_mut().filter(|chunk| chunk.era == era) {
if let Some(chunk) =
ledger.unlocking.last_mut().filter(|chunk| chunk.block == block)
{
// To keep the chunk count down, we only keep one chunk per era. Since
// `unlocking` is a FiFo queue, if a chunk exists for `era` we know that it will
// be the last one.
chunk.value = chunk.value.defensive_saturating_add(value)
} else {
ledger
.unlocking
.try_push(UnlockChunk { value, era })
.try_push(UnlockChunk { value, block })
.map_err(|_| Error::<T>::NoMoreChunks)?;
};

Expand All @@ -415,9 +418,8 @@ pub mod pallet {
let owner = ensure_signed(origin)?;
let mut ledger = Self::ledger(&owner).ok_or(Error::<T>::NotOwner)?;
let (owner, old_total) = (ledger.owner.clone(), ledger.total);
let current_era = 0;
ledger = ledger.consolidate_unlocked(current_era);
log::debug!("Current era: {:?}", current_era);
let current_block = <frame_system::Pallet<T>>::block_number();
ledger = ledger.consolidate_unlocked(current_block);

if ledger.unlocking.is_empty() &&
ledger.active < <T as pallet::Config>::Currency::minimum_balance()
Expand Down Expand Up @@ -468,7 +470,7 @@ pub mod pallet {
/// This will also deposit the funds to pallet.
fn update_ledger_and_deposit(
owner: &T::AccountId,
ledger: &AccountsLedger<T::AccountId, BalanceOf<T>>,
ledger: &AccountsLedger<T::AccountId, BalanceOf<T>, T>,
) -> DispatchResult {
let account_id = Self::account_id();

Expand All @@ -486,7 +488,7 @@ pub mod pallet {
/// Update the ledger for a owner.
fn update_ledger(
owner: &T::AccountId,
ledger: &AccountsLedger<T::AccountId, BalanceOf<T>>,
ledger: &AccountsLedger<T::AccountId, BalanceOf<T>, T>,
) {
<Ledger<T>>::insert(owner, ledger);
}
Expand Down Expand Up @@ -523,15 +525,13 @@ pub mod pallet {
ledger.total -= amount;
ledger.active -= amount;
total_charged += amount;
log::debug!("Ledger updated state: {:?}", &ledger);
Self::update_ledger(&content_owner, &ledger);
} else {
let diff = amount - ledger.active;
total_charged += ledger.active;
ledger.total -= ledger.active;
ledger.active = BalanceOf::<T>::zero();
let (ledger, charged) = ledger.charge_unlocking(diff);
log::debug!("Ledger updated state: {:?}", &ledger);
Self::update_ledger(&content_owner, &ledger);
total_charged += charged;
}
Expand Down
11 changes: 4 additions & 7 deletions pallets/ddc-staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,16 @@ use frame_support::{
assert_ok,
pallet_prelude::*,
parameter_types,
traits::{
Currency, DefensiveSaturating, ExistenceRequirement, LockIdentifier, LockableCurrency,
WithdrawReasons,
},
BoundedVec, PalletId,
traits::{Currency, DefensiveSaturating, LockIdentifier, LockableCurrency, WithdrawReasons},
BoundedVec,
};
use frame_system::pallet_prelude::*;
use scale_info::TypeInfo;
use sp_runtime::{
traits::{AccountIdConversion, AtLeast32BitUnsigned, Saturating, StaticLookup, Zero},
traits::{AtLeast32BitUnsigned, Saturating, StaticLookup, Zero},
RuntimeDebug, SaturatedConversion,
};
use sp_std::{collections::btree_map::BTreeMap, prelude::*};
use sp_std::prelude::*;

pub use pallet::*;

Expand Down
4 changes: 2 additions & 2 deletions runtime/cere-dev/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1332,11 +1332,11 @@ impl pallet_ddc_staking::Config for Runtime {

parameter_types! {
pub const DdcCustomersPalletId: PalletId = PalletId(*b"accounts"); // DDC maintainer's stake
pub const LockingDuration: sp_staking::EraIndex = 30 * 24; // 1 hour * 24 = 1 day; (1 era is 2 mins)
pub const UnlockingDelay: BlockNumber = 5256000u32; // 1 hour * 24 * 365 = 1 day; (1 hour is 600 blocks)
}

impl pallet_ddc_customers::Config for Runtime {
type LockingDuration = LockingDuration;
type UnlockingDelay = UnlockingDelay;
type Currency = Balances;
type PalletId = DdcCustomersPalletId;
type RuntimeEvent = RuntimeEvent;
Expand Down

0 comments on commit 9be9df7

Please sign in to comment.