Skip to content

Commit

Permalink
Merge pull request #46 from Cerebellum-Network/feature/ddc-staking-te…
Browse files Browse the repository at this point in the history
…sts-benchmarks

Tests and updated weights for DDC staking
  • Loading branch information
khssnv authored Jul 4, 2023
2 parents 18daeb1 + 8911b9d commit 54d945c
Show file tree
Hide file tree
Showing 13 changed files with 766 additions and 59 deletions.
104 changes: 104 additions & 0 deletions .maintain/frame-weight-template.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
//! Autogenerated weights for {{pallet}}
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION {{version}}
//! DATE: {{date}}, STEPS: `{{cmd.steps}}`, REPEAT: {{cmd.repeat}}, LOW RANGE: `{{cmd.lowest_range_values}}`, HIGH RANGE: `{{cmd.highest_range_values}}`
//! HOSTNAME: `{{hostname}}`, CPU: `{{cpuname}}`
//! EXECUTION: {{cmd.execution}}, WASM-EXECUTION: {{cmd.wasm_execution}}, CHAIN: {{cmd.chain}}, DB CACHE: {{cmd.db_cache}}

// Executed Command:
{{#each args as |arg|}}
// {{arg}}
{{/each}}

#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]

use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
use sp_std::marker::PhantomData;

/// Weight functions needed for {{pallet}}.
pub trait WeightInfo {
{{#each benchmarks as |benchmark|}}
fn {{benchmark.name~}}
(
{{~#each benchmark.components as |c| ~}}
{{c.name}}: u32, {{/each~}}
) -> Weight;
{{/each}}
}

/// Weights for {{pallet}} using the Substrate node and recommended hardware.
pub struct SubstrateWeight<T>(PhantomData<T>);
{{#if (eq pallet "frame_system")}}
impl<T: crate::Config> WeightInfo for SubstrateWeight<T> {
{{else}}
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
{{/if}}
{{#each benchmarks as |benchmark|}}
{{#each benchmark.comments as |comment|}}
// {{comment}}
{{/each}}
{{#each benchmark.component_ranges as |range|}}
/// The range of component `{{range.name}}` is `[{{range.min}}, {{range.max}}]`.
{{/each}}
fn {{benchmark.name~}}
(
{{~#each benchmark.components as |c| ~}}
{{~#if (not c.is_used)}}_{{/if}}{{c.name}}: u32, {{/each~}}
) -> Weight {
Weight::from_ref_time({{underscore benchmark.base_weight}} as u64)
{{#each benchmark.component_weight as |cw|}}
// Standard Error: {{underscore cw.error}}
.saturating_add(Weight::from_ref_time({{underscore cw.slope}} as u64).saturating_mul({{cw.name}} as u64))
{{/each}}
{{#if (ne benchmark.base_reads "0")}}
.saturating_add(T::DbWeight::get().reads({{benchmark.base_reads}} as u64))
{{/if}}
{{#each benchmark.component_reads as |cr|}}
.saturating_add(T::DbWeight::get().reads(({{cr.slope}} as u64).saturating_mul({{cr.name}} as u64)))
{{/each}}
{{#if (ne benchmark.base_writes "0")}}
.saturating_add(T::DbWeight::get().writes({{benchmark.base_writes}} as u64))
{{/if}}
{{#each benchmark.component_writes as |cw|}}
.saturating_add(T::DbWeight::get().writes(({{cw.slope}} as u64).saturating_mul({{cw.name}} as u64)))
{{/each}}
}
{{/each}}
}

// For backwards compatibility and tests
impl WeightInfo for () {
{{#each benchmarks as |benchmark|}}
{{#each benchmark.comments as |comment|}}
// {{comment}}
{{/each}}
{{#each benchmark.component_ranges as |range|}}
/// The range of component `{{range.name}}` is `[{{range.min}}, {{range.max}}]`.
{{/each}}
fn {{benchmark.name~}}
(
{{~#each benchmark.components as |c| ~}}
{{~#if (not c.is_used)}}_{{/if}}{{c.name}}: u32, {{/each~}}
) -> Weight {
Weight::from_ref_time({{underscore benchmark.base_weight}} as u64)
{{#each benchmark.component_weight as |cw|}}
// Standard Error: {{underscore cw.error}}
.saturating_add(Weight::from_ref_time({{underscore cw.slope}} as u64).saturating_mul({{cw.name}} as u64))
{{/each}}
{{#if (ne benchmark.base_reads "0")}}
.saturating_add(RocksDbWeight::get().reads({{benchmark.base_reads}} as u64))
{{/if}}
{{#each benchmark.component_reads as |cr|}}
.saturating_add(RocksDbWeight::get().reads(({{cr.slope}} as u64).saturating_mul({{cr.name}} as u64)))
{{/each}}
{{#if (ne benchmark.base_writes "0")}}
.saturating_add(RocksDbWeight::get().writes({{benchmark.base_writes}} as u64))
{{/if}}
{{#each benchmark.component_writes as |cw|}}
.saturating_add(RocksDbWeight::get().writes(({{cw.slope}} as u64).saturating_mul({{cw.name}} as u64)))
{{/each}}
}
{{/each}}
}
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [vNext]

### Changed
### Added

- ...
- Handlebars template to generate weights file
- Genesis config for `pallet-ddc-staking` to set genesis DDC participants (empty by default) and staking settings
- Unit tests in `pallet-ddc-staking` for basic staking scenario

## [4.7.0]

Expand Down
4 changes: 4 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions node/service/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ pub fn cere_dev_genesis(
stakers,
..Default::default()
},
ddc_staking: cere_dev::DdcStakingConfig::default(),
democracy: cere_dev::DemocracyConfig::default(),
elections: cere_dev::ElectionsConfig {
members: endowed_accounts
Expand Down
9 changes: 6 additions & 3 deletions pallets/ddc-staking/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ edition = "2021"

[dependencies]
codec = { package = "parity-scale-codec", version = "3.1.5", default-features = false, features = ["derive"] }
frame-benchmarking = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.29", optional = true }
frame-support = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.29" }
frame-system = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.29" }
scale-info = { version = "2.1.2", default-features = false, features = ["derive"] }
Expand All @@ -13,18 +14,20 @@ sp-runtime = { version = "6.0.0", default-features = false, git = "https://githu
sp-staking = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.29" }
sp-std = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.29" }

frame-benchmarking = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.29", optional = true }

[dev-dependencies]
pallet-balances = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.29" }
pallet-timestamp = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.29" }
sp-core = { version = "6.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.29" }
sp-tracing = { version = "5.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.29" }
substrate-test-utils = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.29" }

[features]
default = ["std"]
std = [
"codec/std",
"frame-benchmarking/std",
"frame-support/std",
"frame-system/std",
"frame-benchmarking/std",
"scale-info/std",
"sp-io/std",
"sp-runtime/std",
Expand Down
15 changes: 15 additions & 0 deletions pallets/ddc-staking/README.md
Original file line number Diff line number Diff line change
@@ -1 +1,16 @@
# DDC Staking Pallet

The DDC Staking module is used to manage funds at stake by Cere DDC participants.

## Overview

The DDC Staking module is the means by which an account can voluntarily place funds under deposit to join DDC CDN or storage network.

### Terminology

- DDC Staking: The process of locking up funds for some time in order to become a participant of the DDC.
- Stash account: The account holding an owner's funds used for staking.
- Controller account: The account that controls an owner's funds for staking.
- Edge: CDN participant.
- Storage: Storage network participant.
- Era: A time period of DDC participants activity data capture and accumulation which will further be used to calculate pay outs.
3 changes: 3 additions & 0 deletions pallets/ddc-staking/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ benchmarks! {
let (edge_stash, edge_controller) = create_stash_controller_with_balance::<T>(0, T::DefaultEdgeBondSize::get())?;
DdcStaking::<T>::serve(RawOrigin::Signed(edge_controller.clone()).into(), 1)?;
assert!(Edges::<T>::contains_key(&edge_stash));
CurrentEra::<T>::put(1);
DdcStaking::<T>::chill(RawOrigin::Signed(edge_controller.clone()).into())?;
CurrentEra::<T>::put(1 + Settings::<T>::get(1).edge_chill_delay);

whitelist_account!(edge_controller);
}: _(RawOrigin::Signed(edge_controller))
Expand Down
113 changes: 96 additions & 17 deletions pallets/ddc-staking/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,35 @@
//! # DDC Staking Pallet
//!
//! The DDC Staking pallet is used to manage funds at stake by CDN and storage network maintainers.
//!
//! - [`Config`]
//! - [`Call`]
//! - [`Pallet`]
//!
//! ## GenesisConfig
//!
//! The DDC Staking pallet depends on the [`GenesisConfig`]. The
//! `GenesisConfig` is optional and allow to set some initial stakers in DDC.

#![cfg_attr(not(feature = "std"), no_std)]
#![recursion_limit = "256"]

#[cfg(feature = "runtime-benchmarks")]
pub mod benchmarking;

#[cfg(any(feature = "runtime-benchmarks", test))]
pub mod testing_utils;

#[cfg(test)]
pub(crate) mod mock;
#[cfg(test)]
mod tests;

pub mod weights;
use crate::weights::WeightInfo;

use codec::{Decode, Encode, HasCompact};
use frame_support::{
assert_ok,
pallet_prelude::*,
parameter_types,
traits::{
Expand Down Expand Up @@ -227,6 +245,83 @@ pub mod pallet {
#[pallet::getter(fn current_era)]
pub type CurrentEra<T> = StorageValue<_, EraIndex>;

#[pallet::genesis_config]
pub struct GenesisConfig<T: Config> {
pub edges: Vec<(T::AccountId, T::AccountId, BalanceOf<T>, ClusterId)>,
pub storages: Vec<(T::AccountId, T::AccountId, BalanceOf<T>, ClusterId)>,
pub settings: Vec<(ClusterId, BalanceOf<T>, EraIndex, BalanceOf<T>, EraIndex)>,
}

#[cfg(feature = "std")]
impl<T: Config> Default for GenesisConfig<T> {
fn default() -> Self {
GenesisConfig {
edges: Default::default(),
storages: Default::default(),
settings: Default::default(),
}
}
}

#[pallet::genesis_build]
impl<T: Config> GenesisBuild<T> for GenesisConfig<T> {
fn build(&self) {
// clusters' settings
for &(
cluster,
edge_bond_size,
edge_chill_delay,
storage_bond_size,
storage_chill_delay,
) in &self.settings
{
Settings::<T>::insert(
cluster,
ClusterSettings::<T> {
edge_bond_size,
edge_chill_delay,
storage_bond_size,
storage_chill_delay,
},
);
}

// Add initial CDN participants
for &(ref stash, ref controller, balance, cluster) in &self.edges {
assert!(
T::Currency::free_balance(&stash) >= balance,
"Stash do not have enough balance to participate in CDN."
);
assert_ok!(Pallet::<T>::bond(
T::Origin::from(Some(stash.clone()).into()),
T::Lookup::unlookup(controller.clone()),
balance,
));
assert_ok!(Pallet::<T>::serve(
T::Origin::from(Some(controller.clone()).into()),
cluster,
));
}

// Add initial storage network participants
for &(ref stash, ref controller, balance, cluster) in &self.storages {
assert!(
T::Currency::free_balance(&stash) >= balance,
"Stash do not have enough balance to participate in storage network."
);
assert_ok!(Pallet::<T>::bond(
T::Origin::from(Some(stash.clone()).into()),
T::Lookup::unlookup(controller.clone()),
balance,
));
assert_ok!(Pallet::<T>::store(
T::Origin::from(Some(controller.clone()).into()),
cluster,
));
}
}
}

#[pallet::event]
#[pallet::generate_deposit(pub(crate) fn deposit_event)]
pub enum Event<T: Config> {
Expand Down Expand Up @@ -709,43 +804,27 @@ pub mod pallet {
/// This function will add a CDN participant to the `Edges` storage map.
///
/// If the CDN participant already exists, their cluster will be updated.
///
/// NOTE: you must ALWAYS use this function to add a CDN participant to the system. Any
/// access to `Edges` outside of this function is almost certainly
/// wrong.
pub fn do_add_edge(who: &T::AccountId, cluster: ClusterId) {
Edges::<T>::insert(who, cluster);
}

/// This function will remove a CDN participant from the `Edges` map.
///
/// Returns true if `who` was removed from `Edges`, otherwise false.
///
/// NOTE: you must ALWAYS use this function to remove a storage network participant from the
/// system. Any access to `Edges` outside of this function is almost certainly
/// wrong.
pub fn do_remove_edge(who: &T::AccountId) -> bool {
Edges::<T>::take(who).is_some()
}

/// This function will add a storage network participant to the `Storages` storage map.
///
/// If the storage network participant already exists, their cluster will be updated.
///
/// NOTE: you must ALWAYS use this function to add a storage network participant to the
/// system. Any access to `Storages` outside of this function is almost certainly
/// wrong.
pub fn do_add_storage(who: &T::AccountId, cluster: ClusterId) {
Storages::<T>::insert(who, cluster);
}

/// This function will remove a storage network participant from the `Storages` map.
///
/// Returns true if `who` was removed from `Storages`, otherwise false.
///
/// NOTE: you must ALWAYS use this function to remove a storage network participant from the
/// system. Any access to `Storages` outside of this function is almost certainly
/// wrong.
pub fn do_remove_storage(who: &T::AccountId) -> bool {
Storages::<T>::take(who).is_some()
}
Expand Down
Loading

0 comments on commit 54d945c

Please sign in to comment.