From aadf3e2493ef48188abf15205795bb2c393634a2 Mon Sep 17 00:00:00 2001 From: Gav <gavin@parity.io> Date: Sat, 10 Mar 2018 18:42:50 +0100 Subject: [PATCH] Tests for staking reserved balances & slashing. --- substrate/demo/runtime/src/runtime/staking.rs | 238 +++++++++++++----- substrate/demo/runtime/src/runtime/system.rs | 26 +- 2 files changed, 185 insertions(+), 79 deletions(-) diff --git a/substrate/demo/runtime/src/runtime/staking.rs b/substrate/demo/runtime/src/runtime/staking.rs index e97a9830b4c..6a30a743142 100644 --- a/substrate/demo/runtime/src/runtime/staking.rs +++ b/substrate/demo/runtime/src/runtime/staking.rs @@ -112,6 +112,7 @@ pub fn bondage(who: &AccountId) -> Bondage { } #[derive(PartialEq, Copy, Clone)] +#[cfg_attr(test, derive(Debug))] pub enum LockStatus { Liquid, LockedUntil(BlockNumber), @@ -486,11 +487,12 @@ pub mod internal { } /// Moves `value` from reserved balance to balance. - pub fn transfer_reserved_balance(slashed: &AccountId, beneficiary: &AccountId, value: Balance) { + pub fn transfer_reserved_balance(slashed: &AccountId, beneficiary: &AccountId, value: Balance) -> bool { let b = reserved_balance(slashed); - let value = cmp::min(b, value); - set_reserved_balance(slashed, b - value); - set_free_balance(beneficiary, free_balance(beneficiary) + value); + let slash = cmp::min(b, value); + set_reserved_balance(slashed, b - slash); + set_free_balance(beneficiary, free_balance(beneficiary) + slash); + slash == value } } @@ -536,23 +538,19 @@ pub mod testing { use super::*; use runtime_io::{twox_128, TestExternalities}; use codec::{Joiner, KeyedVec}; - use keyring::Keyring; + use keyring::Keyring::*; use runtime::session; pub fn externalities(session_length: u64, sessions_per_era: u64, current_era: u64) -> TestExternalities { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - let three = [3u8; 32]; - let extras: TestExternalities = map![ twox_128(INTENTION_COUNT).to_vec() => vec![].and(&3u32), - twox_128(&0u32.to_keyed_vec(INTENTION_AT)).to_vec() => one.to_vec(), - twox_128(&1u32.to_keyed_vec(INTENTION_AT)).to_vec() => two.to_vec(), - twox_128(&2u32.to_keyed_vec(INTENTION_AT)).to_vec() => three.to_vec(), + twox_128(&0u32.to_keyed_vec(INTENTION_AT)).to_vec() => Alice.to_raw_public_vec(), + twox_128(&1u32.to_keyed_vec(INTENTION_AT)).to_vec() => Bob.to_raw_public_vec(), + twox_128(&2u32.to_keyed_vec(INTENTION_AT)).to_vec() => Charlie.to_raw_public_vec(), twox_128(SESSIONS_PER_ERA).to_vec() => vec![].and(&sessions_per_era), twox_128(VALIDATOR_COUNT).to_vec() => vec![].and(&3u64), twox_128(CURRENT_ERA).to_vec() => vec![].and(¤t_era), - twox_128(&one.to_keyed_vec(BALANCE_OF)).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] + twox_128(&Alice.to_raw_public().to_keyed_vec(BALANCE_OF)).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] ]; session::testing::externalities(session_length).into_iter().chain(extras.into_iter()).collect() } @@ -567,18 +565,13 @@ mod tests { use runtime_io::{with_externalities, twox_128, TestExternalities}; use codec::{KeyedVec, Joiner}; - use keyring::Keyring; + use keyring::Keyring::*; use environment::with_env; use demo_primitives::AccountId; use runtime::{staking, session}; #[test] fn staking_should_work() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - let three = [3u8; 32]; - let four = [4u8; 32]; - let mut t: TestExternalities = map![ twox_128(session::SESSION_LENGTH).to_vec() => vec![].and(&1u64), twox_128(session::VALIDATOR_COUNT).to_vec() => vec![].and(&2u32), @@ -588,10 +581,10 @@ mod tests { twox_128(VALIDATOR_COUNT).to_vec() => vec![].and(&2u32), twox_128(BONDING_DURATION).to_vec() => vec![].and(&3u64), twox_128(TOTAL_STAKE).to_vec() => vec![].and(&100u64), - twox_128(&one.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].and(&10u64), - twox_128(&two.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].and(&20u64), - twox_128(&three.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].and(&30u64), - twox_128(&four.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].and(&40u64) + twox_128(&Alice.to_raw_public().to_keyed_vec(BALANCE_OF)).to_vec() => vec![].and(&10u64), + twox_128(&Bob.to_raw_public().to_keyed_vec(BALANCE_OF)).to_vec() => vec![].and(&20u64), + twox_128(&Charlie.to_raw_public().to_keyed_vec(BALANCE_OF)).to_vec() => vec![].and(&30u64), + twox_128(&Dave.to_raw_public().to_keyed_vec(BALANCE_OF)).to_vec() => vec![].and(&40u64) ]; with_externalities(&mut t, || { @@ -602,48 +595,48 @@ mod tests { // Block 1: Add three validators. No obvious change. with_env(|e| e.block_number = 1); - stake(&one); - stake(&two); - stake(&four); + stake(&Alice); + stake(&Bob); + stake(&Dave); check_new_era(); assert_eq!(session::validators(), vec![[10u8; 32], [20u8; 32]]); // Block 2: New validator set now. with_env(|e| e.block_number = 2); check_new_era(); - assert_eq!(session::validators(), vec![four.clone(), two.clone()]); + assert_eq!(session::validators(), vec![Dave.to_raw_public(), Bob.into()]); // Block 3: Unstake highest, introduce another staker. No change yet. with_env(|e| e.block_number = 3); - stake(&three); - unstake(&four); + stake(&Charlie); + unstake(&Dave); check_new_era(); // Block 4: New era - validators change. with_env(|e| e.block_number = 4); check_new_era(); - assert_eq!(session::validators(), vec![three.clone(), two.clone()]); + assert_eq!(session::validators(), vec![Charlie.to_raw_public(), Bob.into()]); // Block 5: Transfer stake from highest to lowest. No change yet. with_env(|e| e.block_number = 5); - transfer(&four, &one, 40); + transfer(&Dave, &Alice, 40); check_new_era(); // Block 6: Lowest now validator. with_env(|e| e.block_number = 6); check_new_era(); - assert_eq!(session::validators(), vec![one.clone(), three.clone()]); + assert_eq!(session::validators(), vec![Alice.to_raw_public(), Charlie.into()]); // Block 7: Unstake three. No change yet. with_env(|e| e.block_number = 7); - unstake(&three); + unstake(&Charlie); check_new_era(); - assert_eq!(session::validators(), vec![one.clone(), three.clone()]); + assert_eq!(session::validators(), vec![Alice.to_raw_public(), Charlie.into()]); // Block 8: Back to one and two. with_env(|e| e.block_number = 8); check_new_era(); - assert_eq!(session::validators(), vec![one.clone(), two.clone()]); + assert_eq!(session::validators(), vec![Alice.to_raw_public(), Bob.into()]); }); } @@ -713,48 +706,173 @@ mod tests { #[test] fn staking_balance_works() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); + with_externalities(&mut TestExternalities::default(), || { + set_free_balance(&Alice, 42); + assert_eq!(free_balance(&Alice), 42); + assert_eq!(reserved_balance(&Alice), 0); + assert_eq!(balance(&Alice), 42); + assert_eq!(free_balance(&Bob), 0); + assert_eq!(reserved_balance(&Bob), 0); + assert_eq!(balance(&Bob), 0); + }); + } - let mut t: TestExternalities = map![ - twox_128(&one.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].and(&42u64) - ]; + #[test] + fn staking_balance_transfer_works() { + with_externalities(&mut TestExternalities::default(), || { + set_free_balance(&Alice, 111); + transfer(&Alice, &Bob, 69); + assert_eq!(balance(&Alice), 42); + assert_eq!(balance(&Bob), 69); + }); + } - with_externalities(&mut t, || { - assert_eq!(balance(&one), 42); - assert_eq!(balance(&two), 0); + #[test] + #[should_panic] + fn staking_balance_transfer_when_bonded_panics() { + with_externalities(&mut TestExternalities::default(), || { + set_free_balance(&Alice, 111); + stake(&Alice); + transfer(&Alice, &Bob, 69); }); } #[test] - fn staking_balance_transfer_works() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); + fn reserving_balance_should_work() { + with_externalities(&mut TestExternalities::default(), || { + set_free_balance(&Alice, 111); - let mut t: TestExternalities = map![ - twox_128(&one.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].and(&111u64) - ]; + assert_eq!(balance(&Alice), 111); + assert_eq!(free_balance(&Alice), 111); + assert_eq!(reserved_balance(&Alice), 0); - with_externalities(&mut t, || { - transfer(&one, &two, 69); - assert_eq!(balance(&one), 42); - assert_eq!(balance(&two), 69); + reserve_balance(&Alice, 69); + + assert_eq!(balance(&Alice), 111); + assert_eq!(free_balance(&Alice), 42); + assert_eq!(reserved_balance(&Alice), 69); }); } #[test] #[should_panic] - fn staking_balance_transfer_when_bonded_doesnt_work() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); + fn staking_balance_transfer_when_reserved_panics() { + with_externalities(&mut TestExternalities::default(), || { + set_free_balance(&Alice, 111); + reserve_balance(&Alice, 69); + transfer(&Alice, &Bob, 69); + }); + } + #[test] + fn deducting_balance_should_work() { + with_externalities(&mut TestExternalities::default(), || { + set_free_balance(&Alice, 111); + assert!(deduct_unbonded(&Alice, 69)); + assert_eq!(free_balance(&Alice), 42); + }); + } + + #[test] + fn deducting_balance_should_fail_when_bonded() { let mut t: TestExternalities = map![ - twox_128(&one.to_keyed_vec(BALANCE_OF)).to_vec() => vec![].and(&111u64) + twox_128(&Alice.to_raw_public().to_keyed_vec(BALANCE_OF)).to_vec() => vec![].and(&111u64), + twox_128(&Alice.to_raw_public().to_keyed_vec(BONDAGE_OF)).to_vec() => vec![].and(&2u64) ]; - with_externalities(&mut t, || { - stake(&one); - transfer(&one, &two, 69); + with_env(|e| e.block_number = 1); + assert_eq!(unlock_block(&Alice), LockStatus::LockedUntil(2)); + assert!(!deduct_unbonded(&Alice, 69)); + }); + } + + #[test] + fn refunding_balance_should_work() { + with_externalities(&mut TestExternalities::default(), || { + set_free_balance(&Alice, 42); + refund(&Alice, 69); + assert_eq!(free_balance(&Alice), 111); + }); + } + + #[test] + fn slashing_balance_should_work() { + with_externalities(&mut TestExternalities::default(), || { + set_free_balance(&Alice, 111); + reserve_balance(&Alice, 69); + assert!(slash(&Alice, 69)); + assert_eq!(free_balance(&Alice), 0); + assert_eq!(reserved_balance(&Alice), 42); + }); + } + + #[test] + fn slashing_incomplete_balance_should_work() { + with_externalities(&mut TestExternalities::default(), || { + set_free_balance(&Alice, 42); + reserve_balance(&Alice, 21); + assert!(!slash(&Alice, 69)); + assert_eq!(free_balance(&Alice), 0); + assert_eq!(reserved_balance(&Alice), 0); + }); + } + + #[test] + fn unreserving_balance_should_work() { + with_externalities(&mut TestExternalities::default(), || { + set_free_balance(&Alice, 111); + reserve_balance(&Alice, 111); + unreserve_balance(&Alice, 42); + assert_eq!(reserved_balance(&Alice), 69); + assert_eq!(free_balance(&Alice), 42); + }); + } + + #[test] + fn slashing_reserved_balance_should_work() { + with_externalities(&mut TestExternalities::default(), || { + set_free_balance(&Alice, 111); + reserve_balance(&Alice, 111); + assert!(slash_reserved(&Alice, 42)); + assert_eq!(reserved_balance(&Alice), 69); + assert_eq!(free_balance(&Alice), 0); + }); + } + + #[test] + fn slashing_incomplete_reserved_balance_should_work() { + with_externalities(&mut TestExternalities::default(), || { + set_free_balance(&Alice, 111); + reserve_balance(&Alice, 42); + assert!(!slash_reserved(&Alice, 69)); + assert_eq!(free_balance(&Alice), 69); + assert_eq!(reserved_balance(&Alice), 0); + }); + } + + #[test] + fn transferring_reserved_balance_should_work() { + with_externalities(&mut TestExternalities::default(), || { + set_free_balance(&Alice, 111); + reserve_balance(&Alice, 111); + assert!(transfer_reserved_balance(&Alice, &Bob, 42)); + assert_eq!(reserved_balance(&Alice), 69); + assert_eq!(free_balance(&Alice), 0); + assert_eq!(reserved_balance(&Bob), 0); + assert_eq!(free_balance(&Bob), 42); + }); + } + + #[test] + fn transferring_incomplete_reserved_balance_should_work() { + with_externalities(&mut TestExternalities::default(), || { + set_free_balance(&Alice, 111); + reserve_balance(&Alice, 42); + assert!(!transfer_reserved_balance(&Alice, &Bob, 69)); + assert_eq!(reserved_balance(&Alice), 0); + assert_eq!(free_balance(&Alice), 69); + assert_eq!(reserved_balance(&Bob), 0); + assert_eq!(free_balance(&Bob), 42); }); } } diff --git a/substrate/demo/runtime/src/runtime/system.rs b/substrate/demo/runtime/src/runtime/system.rs index 1344e365c17..ede71a69d18 100644 --- a/substrate/demo/runtime/src/runtime/system.rs +++ b/substrate/demo/runtime/src/runtime/system.rs @@ -243,7 +243,7 @@ mod tests { use runtime_io::{with_externalities, twox_128, TestExternalities}; use codec::{Joiner, KeyedVec, Slicable}; - use keyring::Keyring; + use keyring::Keyring::*; use environment::with_env; use primitives::hexdisplay::HexDisplay; use demo_primitives::{Header, Digest, UncheckedTransaction, Transaction, Function}; @@ -251,26 +251,23 @@ mod tests { #[test] fn staking_balance_transfer_dispatch_works() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - let mut t: TestExternalities = map![ - twox_128(&one.to_keyed_vec(staking::BALANCE_OF)).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] + twox_128(&One.to_raw_public().to_keyed_vec(staking::BALANCE_OF)).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0] ]; let tx = UncheckedTransaction { transaction: Transaction { - signed: one.clone(), + signed: One.into(), nonce: 0, - function: Function::StakingTransfer(two, 69), + function: Function::StakingTransfer(Two.into(), 69), }, signature: hex!("5f9832c5a4a39e2dd4a3a0c5b400e9836beb362cb8f7d845a8291a2ae6fe366612e080e4acd0b5a75c3d0b6ee69614a68fb63698c1e76bf1f2dcd8fa617ddf05").into(), }; with_externalities(&mut t, || { internal::execute_transaction(tx, Header::from_block_number(1)); - assert_eq!(staking::balance(&one), 42); - assert_eq!(staking::balance(&two), 69); + assert_eq!(staking::balance(&One), 42); + assert_eq!(staking::balance(&Two), 69); }); } @@ -280,15 +277,12 @@ mod tests { #[test] fn block_import_works() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - let mut t = new_test_ext(); let h = Header { parent_hash: [69u8; 32].into(), number: 1, - state_root: hex!("52eb24906a4110a605d29d4e2f01b43cb169d375d709b138cc8ce50ad5f7ce85").into(), + state_root: hex!("f4f6408fe3ce1d78d30bb7ed625b32f91e45b8b566023df309cfd93c6f4af9a4").into(), transaction_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), digest: Digest { logs: vec![], }, }; @@ -306,9 +300,6 @@ mod tests { #[test] #[should_panic] fn block_import_of_bad_state_root_fails() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - let mut t = new_test_ext(); let h = Header { @@ -332,9 +323,6 @@ mod tests { #[test] #[should_panic] fn block_import_of_bad_transaction_root_fails() { - let one = Keyring::One.to_raw_public(); - let two = Keyring::Two.to_raw_public(); - let mut t = new_test_ext(); let h = Header { -- GitLab