Skip to content

Commit

Permalink
Initial staking integration (paritytech#127)
Browse files Browse the repository at this point in the history
* Add initial staking module with only origin APIs defined

* Add staking types

* Add staking traits

* Add vote_weight primitive

* Add staking utils functions

* Impl bond check

* Fix ci

* Impl rebond and unbond check

* Impl partial apply_bond/rebond/unbond

* unbonded chunks

* Add ComputeVoteWeight trait

* Impl Staking Claim

* Impl apply_bond/rebond/unbond

* Add staking module to runtime

* Add mock

* Possibly need a upgrade

* Make staking test work after upgrading to rc4

* Add basic bond/rebond/unbond tests

* Impl withdraw_unbonded

* Fix rc4 migration

* Nits

* Be consistent with chainx primitives for VoteWeight trait

* Improve the namings

* Nits
  • Loading branch information
liuchengxu committed Jul 2, 2020
1 parent 71481da commit 4862016
Show file tree
Hide file tree
Showing 16 changed files with 1,751 additions and 64 deletions.
31 changes: 31 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ members = [
"cli",
"runtime",
"primitives",
"primitives/staking",
"rpc",

"xpallets/assets",
Expand All @@ -23,6 +24,7 @@ members = [
"xpallets/contracts/common",
"xpallets/contracts/rpc",
"xpallets/contracts/rpc/runtime-api",
"xpallets/mining/staking",
"xpallets/protocol",
"xpallets/support",
"xpallets/transaction-payment",
Expand Down
6 changes: 4 additions & 2 deletions cli/src/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use chainx_runtime::{
use chainx_runtime::{AccountId, AssetId, Balance, Runtime, Signature, WASM_BINARY};
use chainx_runtime::{
AuraConfig, GenesisConfig, GrandpaConfig, SudoConfig, SystemConfig, XAssetsConfig,
XBridgeBitcoinConfig, XContractsConfig, XSystemConfig,
XBridgeBitcoinConfig, XContractsConfig, XMiningStakingConfig, XSystemConfig,
};

use sc_service::ChainType;
Expand Down Expand Up @@ -146,7 +146,8 @@ fn pcx() -> (AssetId, AssetInfo, AssetRestrictions) {
AssetRestriction::Deposit
| AssetRestriction::Withdraw
| AssetRestriction::DestroyWithdrawal
| AssetRestriction::DestroyFree,
| AssetRestriction::DestroyFree
| AssetRestriction::Move,
)
}

Expand Down Expand Up @@ -220,6 +221,7 @@ fn testnet_genesis(
btc_withdrawal_fee: 500000,
max_withdrawal_count: 100,
}),
xpallet_mining_staking: Some(Default::default()),
xpallet_contracts: Some(XContractsConfig {
current_schedule: ContractsSchedule {
enable_println, // this should only be enabled on development chains
Expand Down
22 changes: 22 additions & 0 deletions primitives/staking/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[package]
name = "xp-staking"
version = "0.1.0"
authors = ["ChainX community <https://www.chainx.org>"]
edition = "2018"

[dependencies]
# Substrate primitives
sp-std = { git = "https://github.com/paritytech/substrate.git", tag = "v2.0.0-rc4", default-features = false }
sp-runtime = { git = "https://github.com/paritytech/substrate.git", tag = "v2.0.0-rc4", default-features = false }

# ChainX primitives
chainx-primitives = { path = "../../primitives", default-features = false }

[features]
default = ["std"]
std = [
"sp-std/std",
"sp-runtime/std",

"chainx-primitives/std",
]
52 changes: 52 additions & 0 deletions primitives/staking/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#![cfg_attr(not(feature = "std"), no_std)]

//! A crate which contains primitives that are useful for implementation that uses staking
//! approaches in general. Definitions related to sessions, slashing, etc go here.

mod vote_weight;

pub use vote_weight::*;

use chainx_primitives::AssetId;
use sp_std::prelude::Vec;

/// Simple index type with which we can count sessions.
pub type SessionIndex = u32;

/// Simple index type with which we can count unbonded entries.
pub type UnbondedIndex = u32;

/// Type for calculating staker's vote weight.
pub type VoteWeight = u128;

/// Type for measuring the non-validator entity's mining power.
pub type MiningPower = u128;

///
pub trait CollectAssetMiningInfo {
///
fn collect_asset_mining_info() -> Vec<(AssetId, MiningPower)>;

///
fn total_mining_power() -> MiningPower {
Self::collect_asset_mining_info()
.iter()
.map(|(_, power)| power)
.sum()
}
}

impl CollectAssetMiningInfo for () {
fn collect_asset_mining_info() -> Vec<(AssetId, MiningPower)> {
Vec::new()
}
}

/// Issue the fresh PCX to the non-validator mining entities.
pub trait OnMinting<MiningEntity, Balance> {
fn mint(_: &MiningEntity, _: Balance);
}

impl<MiningEntity, Balance> OnMinting<MiningEntity, Balance> for () {
fn mint(_: &MiningEntity, _: Balance) {}
}
109 changes: 109 additions & 0 deletions primitives/staking/src/vote_weight.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
use crate::VoteWeight;
use sp_std::result::Result;

/// The getter and setter methods for the further vote weight processing.
pub trait BaseVoteWeight<BlockNumber> {
fn amount(&self) -> u128;
fn set_amount(&mut self, new: u128);

fn last_acum_weight(&self) -> VoteWeight;
fn set_last_acum_weight(&mut self, s: VoteWeight);

fn last_acum_weight_update(&self) -> u32;
fn set_last_acum_weight_update(&mut self, num: BlockNumber);
}

#[derive(Clone, Copy, sp_runtime::RuntimeDebug)]
pub enum Delta {
Add(u128),
Sub(u128),
Zero,
}

/// General logic for stage changes of the vote weight operations.
pub trait VoteWightTrait<BlockNumber>: BaseVoteWeight<BlockNumber> {
/// Set the new amount after settling the change of nomination.
fn settle_and_set_amount(&mut self, delta: &Delta) {
let new = match *delta {
Delta::Add(x) => self.amount() + x,
Delta::Sub(x) => self.amount() - x,
Delta::Zero => return,
};
self.set_amount(new);
}

/// This action doesn't involve in a change of amount, used for tokens module only.
fn set_state_weight(&mut self, latest_acum_weight: VoteWeight, current_block: BlockNumber) {
self.set_last_acum_weight(latest_acum_weight);
self.set_last_acum_weight_update(current_block);
}

/// Set new state on nominate, unnominate and renominate.
///
/// This is similar to set_state_on_claim with the settlement of amount added.
fn set_state(
&mut self,
latest_acum_weight: VoteWeight,
current_block: BlockNumber,
delta: &Delta,
) {
self.set_state_weight(latest_acum_weight, current_block);
self.settle_and_set_amount(delta);
}
}

impl<BlockNumber, T: BaseVoteWeight<BlockNumber>> VoteWightTrait<BlockNumber> for T {}

/// Formula: Latest Vote Weight = last_acum_weight(VoteWeight) + amount(u64) * duration(u64)
pub type WeightFactors = (VoteWeight, u128, u32);

pub struct ZeroVoteWeightError;

pub trait ComputeVoteWeight<AccountId> {
/// The entity that holds the funds of claimers.
type Claimee;
type Error: From<ZeroVoteWeightError>;

fn claimer_weight_factors(_: &AccountId, _: &Self::Claimee, _: u32) -> WeightFactors;
fn claimee_weight_factors(_: &Self::Claimee, _: u32) -> WeightFactors;

fn settle_claimer_weight(
who: &AccountId,
target: &Self::Claimee,
current_block: u32,
) -> VoteWeight {
Self::calc_latest_vote_weight(Self::claimer_weight_factors(who, target, current_block))
}

fn settle_claimee_weight(target: &Self::Claimee, current_block: u32) -> VoteWeight {
Self::calc_latest_vote_weight(Self::claimee_weight_factors(target, current_block))
}

fn settle_weight_on_claim(
who: &AccountId,
target: &Self::Claimee,
current_block: u32,
) -> Result<(VoteWeight, VoteWeight), Self::Error> {
let claimer_weight = Self::settle_claimer_weight(who, target, current_block);

if claimer_weight == 0 {
return Err(ZeroVoteWeightError.into());
}

let claimee_weight = Self::settle_claimee_weight(target, current_block);

Ok((claimer_weight, claimee_weight))
}

fn calc_latest_vote_weight(weight_factors: WeightFactors) -> VoteWeight {
let (last_acum_weight, amount, duration) = weight_factors;
last_acum_weight + VoteWeight::from(amount) * VoteWeight::from(duration)
}
}

pub trait Claim<AccountId> {
type Claimee;
type Error;

fn claim(claimer: &AccountId, claimee: &Self::Claimee) -> Result<(), Self::Error>;
}
2 changes: 2 additions & 0 deletions runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ xpallet-bridge-bitcoin = { path = "../xpallets/bridge/bitcoin", default-features
xpallet-contracts = { path = "../xpallets/contracts", default-features = false }
xpallet-contracts-primitives = { path = "../xpallets/contracts/common", default-features = false }
xpallet-contracts-rpc-runtime-api = { path = "../xpallets/contracts/rpc/runtime-api", default-features = false }
xpallet-mining-staking = { path = "../xpallets/mining/staking", default-features = false }
xpallet-transaction-payment = { path = "../xpallets/transaction-payment", default-features = false }
xpallet-transaction-payment-rpc-runtime-api = { path = "../xpallets/transaction-payment/rpc/runtime-api", default-features = false }

Expand Down Expand Up @@ -97,6 +98,7 @@ std = [
"xpallet-contracts/std",
"xpallet-contracts-primitives/std",
"xpallet-contracts-rpc-runtime-api/std",
"xpallet-mining-staking/std",
"xpallet-transaction-payment/std",
"xpallet-transaction-payment-rpc-runtime-api/std",
]
7 changes: 7 additions & 0 deletions runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,12 @@ impl xpallet_contracts::Trait for Runtime {
type WeightPrice = xpallet_transaction_payment::Module<Self>;
}

impl xpallet_mining_staking::Trait for Runtime {
type Event = Event;
type CollectAssetMiningInfo = ();
type OnMinting = ();
}

parameter_types! {
pub const TransactionByteFee: Balance = 1; // TODO change in future
pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25);
Expand Down Expand Up @@ -332,6 +338,7 @@ construct_runtime!(
XAssets: xpallet_assets::{Module, Call, Storage, Event<T>, Config<T>},
XBridgeBitcoin: xpallet_bridge_bitcoin::{Module, Call, Storage, Event<T>, Config},
XContracts: xpallet_contracts::{Module, Call, Config, Storage, Event<T>},
XMiningStaking: xpallet_mining_staking::{Module, Call, Storage, Event<T>, Config<T>},
XTransactionPayment: xpallet_transaction_payment::{Module, Storage},
}
);
Expand Down
Loading

0 comments on commit 4862016

Please sign in to comment.