Skip to content

Commit

Permalink
[MPoW] Avoid double mining (#89)
Browse files Browse the repository at this point in the history
* format code

* change work report data structure, era end updates

* fix report slot timing bug and change test cases

* change chain_spec

* fix unbond and add zero check

* change staking module test cases

* fix onReportWorks update logic
  • Loading branch information
badkk committed Apr 2, 2020
1 parent c762c71 commit 542e765
Show file tree
Hide file tree
Showing 8 changed files with 390 additions and 255 deletions.
50 changes: 29 additions & 21 deletions cstrml/staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ use sp_runtime::{Deserialize, Serialize};

// Crust runtime modules
// TODO: using tee passing into `Trait` like Currency?
use crate::StakerStatus::{Guarantor, Validator};
use tee;
use crate::StakerStatus::{Validator, Guarantor};

const DEFAULT_MINIMUM_VALIDATOR_COUNT: u32 = 4;
const MAX_NOMINATIONS: usize = 16;
Expand Down Expand Up @@ -122,7 +122,7 @@ impl<AccountId> Default for Validations<AccountId> {
fn default() -> Self {
Validations {
commission: Default::default(),
guarantors: vec![]
guarantors: vec![],
}
}
}
Expand Down Expand Up @@ -767,8 +767,10 @@ decl_module! {
}

let era = Self::current_era() + T::BondingDuration::get();
let stake_limit = Self::stake_limit(&ledger.stash).unwrap_or_default();

ledger.unlocking.push(UnlockChunk { value, era });
ledger.valid = ledger.active;
ledger.valid = ledger.active.min(stake_limit);

Self::update_ledger(&controller, &ledger);
}
Expand Down Expand Up @@ -1113,10 +1115,14 @@ impl<T: Trait> Module<T> {
.unwrap();

// total_workloads cannot be zero, or system go panic!
let workloads_to_stakes = ((own_workloads * total_issuance / total_workloads / 2) as u128)
.min(u64::max_value() as u128);
if total_workloads == 0 {
Zero::zero()
} else {
let workloads_to_stakes = ((own_workloads * total_issuance / total_workloads / 2) as u128)
.min(u64::max_value() as u128);

workloads_to_stakes.try_into().ok().unwrap()
workloads_to_stakes.try_into().ok().unwrap()
}
}

// MUTABLES (DANGEROUS)
Expand Down Expand Up @@ -1156,9 +1162,11 @@ impl<T: Trait> Module<T> {
/// - 2n+5 DB entry.
/// MAX(n) = MAX_NOMINATIONS
/// # </weight>
fn upsert_guarantee(v_stash: &T::AccountId,
g_stash: &T::AccountId,
g_votes: BalanceOf<T>) -> (bool, BalanceOf<T>) {
fn upsert_guarantee(
v_stash: &T::AccountId,
g_stash: &T::AccountId,
g_votes: BalanceOf<T>,
) -> (bool, BalanceOf<T>) {
if !<Validators<T>>::exists(v_stash) || g_stash == v_stash {
// v_stash is not validator or you want to vote your self
// you vote NOTHING 🙂
Expand All @@ -1172,11 +1180,11 @@ impl<T: Trait> Module<T> {
// 1. Existed edge
if g_old_votes == g_votes {
// a. safe and sound, do NOTHING 🙂
return (true, g_votes)
return (true, g_votes);
} else if g_old_votes > g_votes {
// b. guarantor reduce his stake: just update edge's weight
<GuaranteeRel<T>>::insert(&edge, g_votes);
return (true, g_votes)
return (true, g_votes);
} else {
// c. guarantor increase his stake: remove it first
new_guarantors.remove_item(g_stash);
Expand All @@ -1202,18 +1210,18 @@ impl<T: Trait> Module<T> {
// a. New validator
let new_validations = Validations {
commission: validations.commission,
guarantors: new_guarantors
guarantors: new_guarantors,
};
<Validators<T>>::insert(v_stash, new_validations);

// c. New edge
let new_weight = (v_limit - v_total_stakes).min(g_votes);
<GuaranteeRel<T>>::insert(&edge, new_weight);
return (true, new_weight)
return (true, new_weight);
}

// Or insert failed, cause there has no credit
return (false, Zero::zero())
return (false, Zero::zero());
}

/// Insert new or update old stake limit
Expand Down Expand Up @@ -1450,13 +1458,12 @@ impl<T: Trait> Module<T> {
// and let the chain keep producing blocks until we can decide on a sufficiently
// substantial set.
// TODO: #2494(paritytech/substrate)
return (Self::slot_stake(), None)
return (Self::slot_stake(), None);
}

let to_votes =
|b: BalanceOf<T>| <T::CurrencyToVote as Convert<BalanceOf<T>, u64>>::convert(b) as u128;
let to_balance =
|e: u128| <T::CurrencyToVote as Convert<u128, BalanceOf<T>>>::convert(e);
let to_balance = |e: u128| <T::CurrencyToVote as Convert<u128, BalanceOf<T>>>::convert(e);

// I. Traverse validators, get `IndividualExposure` and update guarantors
for (v_stash, validations) in &validators {
Expand Down Expand Up @@ -1524,8 +1531,8 @@ impl<T: Trait> Module<T> {
} else {
let v_own_votes = to_votes(v_own_stakes);
// b. total_votes should less than balance max value
let v_total_votes = (v_own_votes + v_guarantors_votes)
.min(u64::max_value() as u128);
let v_total_votes =
(v_own_votes + v_guarantors_votes).min(u64::max_value() as u128);

// c. build struct `Exposure`
let exposure = Exposure {
Expand All @@ -1544,7 +1551,7 @@ impl<T: Trait> Module<T> {
// e. UPDATE NODE: `Validator`
let new_validations = Validations {
commission: validations.commission,
guarantors: new_guarantors
guarantors: new_guarantors,
};
<Validators<T>>::insert(v_stash, new_validations);
}
Expand Down Expand Up @@ -1647,7 +1654,8 @@ impl<T: Trait> Module<T> {
if let Some(ledger) = Self::ledger(&controller) {
Self::upsert_stake_limit(
&ledger.stash,
Self::stake_limit_of(own_workloads, total_workloads));
Self::stake_limit_of(own_workloads, total_workloads),
);
}
}

Expand Down
47 changes: 23 additions & 24 deletions cstrml/staking/src/mock.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Test utilities

use crate::{
inflation, EraIndex, GenesisConfig, Module, Guarantors, RewardDestination, StakerStatus, Trait,
inflation, EraIndex, GenesisConfig, Guarantors, Module, RewardDestination, StakerStatus, Trait,
Validations,
};
use frame_support::{
Expand Down Expand Up @@ -344,7 +344,6 @@ impl ExtBuilder {

// tee genesis
let identities: Vec<u64> = vec![10, 20, 30, 40, 2, 60, 50, 70, 4, 6, 100];

let _ = GenesisConfig::<Test> {
current_era: 0,
stakers: vec![
Expand Down Expand Up @@ -392,28 +391,31 @@ impl ExtBuilder {
}
.assimilate_storage(&mut storage);

let mut work_reports: Vec<((u64, u64), tee::WorkReport)> = identities
.iter()
.map(|id| {
(
(*id, 0),
tee::WorkReport {
pub_key: vec![],
block_number: 0,
block_hash: vec![],
empty_root: vec![],
empty_workload: 20000000000000,
meaningful_workload: 0,
sig: vec![],
},
)
})
.collect();

let _ = tee::GenesisConfig::<Test> {
last_report_slot: 0,
tee_identities: identities
.iter()
.map(|id| (*id, Default::default()))
.collect(),
work_reports: identities
.iter()
.map(|id| {
(
*id,
tee::WorkReport {
pub_key: vec![],
block_number: 0,
block_hash: vec![],
empty_root: vec![],
empty_workload: 20000000000000,
meaningful_workload: 0,
sig: vec![],
},
)
})
.collect(),
work_reports
}
.assimilate_storage(&mut storage);

Expand Down Expand Up @@ -506,10 +508,7 @@ pub fn bond_validator(acc: u64, val: u64) {
RewardDestination::Controller
));
Staking::upsert_stake_limit(&(acc + 1), u64::max_value());
assert_ok!(Staking::validate(
Origin::signed(acc),
Perbill::default()
));
assert_ok!(Staking::validate(Origin::signed(acc), Perbill::default()));
}

pub fn bond_guarantor(acc: u64, val: u64, target: Vec<(u64, u64)>) {
Expand All @@ -534,7 +533,7 @@ pub fn start_session(session_index: SessionIndex) {
// Compensate for session delay
let session_index = session_index + 1;
for i in Session::current_index()..session_index {
System::set_block_number((i + 1).into());
System::set_block_number(((i+1)*100).into());
Timestamp::set_timestamp(System::block_number() * 1000);
Session::on_initialize(System::block_number());
}
Expand Down

0 comments on commit 542e765

Please sign in to comment.