diff --git a/substrate/demo/executor/src/lib.rs b/substrate/demo/executor/src/lib.rs index 5ebece1f609f57e1c52550e20f8db0e640b44319..346f26d1e079ed329a50c7beeb76165dc2233a13 100644 --- a/substrate/demo/executor/src/lib.rs +++ b/substrate/demo/executor/src/lib.rs @@ -247,7 +247,7 @@ mod tests { construct_block( 1, [69u8; 32].into(), - hex!("b97d52254fc967bb94bed485de6a738e9fad05decfda3453711677b8becf6d0a").into(), + hex!("c563199c60df7d914262b1775b284870f3a5da2f24b56d2c6288b37c815a6cd9").into(), vec![BareExtrinsic { signed: alice(), index: 0, @@ -260,7 +260,40 @@ mod tests { construct_block( 2, block1().1, - hex!("a1f018d2faa339f72f5ee29050b4670d971e2e271cc06c41ee9cbe1f4c6feec9").into(), + hex!("83f71d5475f63350825b0301de322233d3711a9f3fcfd74050d1534af47a36b3").into(), + vec![ + BareExtrinsic { + signed: bob(), + index: 0, + function: Call::Staking(staking::Call::transfer(alice().into(), 5)), + }, + BareExtrinsic { + signed: alice(), + index: 1, + function: Call::Staking(staking::Call::transfer(bob().into(), 15)), + } + ] + ) + } + + fn block1_wasm() -> (Vec<u8>, Hash) { + construct_block( + 1, + [69u8; 32].into(), + hex!("b97d52254fc967bb94bed485de6a738e9fad05decfda3453711677b8becf6d0a").into(), + vec![BareExtrinsic { + signed: alice(), + index: 0, + function: Call::Staking(staking::Call::transfer(bob().into(), 69)), + }] + ) + } + + fn block2_wasm() -> (Vec<u8>, Hash) { + construct_block( + 2, + block1().1, + hex!("b820fe09935dba41d200b627c11bd7dd9ebff39c319dee18be3ee4f99fc1eab4").into(), vec![ BareExtrinsic { signed: bob(), @@ -280,7 +313,7 @@ mod tests { construct_block( 1, [69u8; 32].into(), - hex!("41d07010f49aa29b2c9aca542cbaa6f59aafd3dda53cdf711c51ddb7d386912e").into(), + hex!("06d026c0d687ec583660a6052de6f89acdb24ea964d06be3831c837c3c426966").into(), vec![BareExtrinsic { signed: alice(), index: 0, @@ -312,14 +345,14 @@ mod tests { fn full_wasm_block_import_works() { let mut t = new_test_ext(); - WasmExecutor::new(8).call(&mut t, COMPACT_CODE, "execute_block", &block1().0).unwrap(); + WasmExecutor::new(8).call(&mut t, COMPACT_CODE, "execute_block", &block1_wasm().0).unwrap(); runtime_io::with_externalities(&mut t, || { assert_eq!(Staking::voting_balance(&alice()), 41); assert_eq!(Staking::voting_balance(&bob()), 69); }); - WasmExecutor::new(8).call(&mut t, COMPACT_CODE, "execute_block", &block2().0).unwrap(); + WasmExecutor::new(8).call(&mut t, COMPACT_CODE, "execute_block", &block2_wasm().0).unwrap(); runtime_io::with_externalities(&mut t, || { assert_eq!(Staking::voting_balance(&alice()), 30); @@ -338,7 +371,7 @@ mod tests { #[test] fn native_big_block_import_succeeds() { let mut t = new_test_ext(); - + let r = Executor::with_heap_pages(8).call(&mut t, COMPACT_CODE, "execute_block", &block1big().0, true).0; assert!(r.is_ok()); } diff --git a/substrate/polkadot/test-parachains/adder/src/src b/substrate/polkadot/test-parachains/adder/src/src deleted file mode 120000 index e8310385c56dc4bbe379f43400f3181f6a59f260..0000000000000000000000000000000000000000 --- a/substrate/polkadot/test-parachains/adder/src/src +++ /dev/null @@ -1 +0,0 @@ -src \ No newline at end of file diff --git a/substrate/polkadot/test-parachains/adder/src/src b/substrate/polkadot/test-parachains/adder/src/src new file mode 100644 index 0000000000000000000000000000000000000000..e8310385c56dc4bbe379f43400f3181f6a59f260 --- /dev/null +++ b/substrate/polkadot/test-parachains/adder/src/src @@ -0,0 +1 @@ +src \ No newline at end of file diff --git a/substrate/substrate/runtime/contract/src/gas.rs b/substrate/substrate/runtime/contract/src/gas.rs index 662ddc4fbd3adc529f4e7fbfe572d0c7bc16806e..2f2b82d6b0142b1cb370c301c43730459a593830 100644 --- a/substrate/substrate/runtime/contract/src/gas.rs +++ b/substrate/substrate/runtime/contract/src/gas.rs @@ -136,6 +136,7 @@ pub fn buy_gas<T: Trait>( return Err("not enough funds for transaction fee"); } <staking::Module<T>>::set_free_balance(transactor, b - cost); + <staking::Module<T>>::decrease_total_stake_by(cost); Ok(GasMeter { gas_left: gas_limit, gas_price, @@ -147,4 +148,5 @@ pub fn refund_unused_gas<T: Trait>(transactor: &T::AccountId, gas_meter: GasMete let b = <staking::Module<T>>::free_balance(transactor); let refund = <T::Gas as As<T::Balance>>::as_(gas_meter.gas_left) * gas_meter.gas_price; <staking::Module<T>>::set_free_balance(transactor, b + refund); + <staking::Module<T>>::increase_total_stake_by(refund); } diff --git a/substrate/substrate/runtime/contract/src/tests.rs b/substrate/substrate/runtime/contract/src/tests.rs index f79b155cf5d5c107a9f992d7eb28e02f5f929c0e..d9839dae26452c27446bec53820659d401545d33 100644 --- a/substrate/substrate/runtime/contract/src/tests.rs +++ b/substrate/substrate/runtime/contract/src/tests.rs @@ -162,7 +162,9 @@ fn contract_transfer() { <CodeOf<Test>>::insert(1, code_transfer.to_vec()); Staking::set_free_balance(&0, 100_000_000); + Staking::increase_total_stake_by(100_000_000); Staking::set_free_balance(&1, 11); + Staking::increase_total_stake_by(11); assert_ok!(Contract::call(&0, 1, 3, 100_000, Vec::new())); @@ -195,7 +197,9 @@ fn contract_transfer_oog() { <CodeOf<Test>>::insert(1, code_transfer.to_vec()); Staking::set_free_balance(&0, 100_000_000); + Staking::increase_total_stake_by(100_000_000); Staking::set_free_balance(&1, 11); + Staking::increase_total_stake_by(11); assert_err!( Contract::call(&0, 1, 3, 276, Vec::new()), @@ -232,7 +236,9 @@ fn contract_transfer_max_depth() { <CodeOf<Test>>::insert(CONTRACT_SHOULD_TRANSFER_TO, code_transfer.to_vec()); Staking::set_free_balance(&0, 100_000_000); + Staking::increase_total_stake_by(100_000_000); Staking::set_free_balance(&CONTRACT_SHOULD_TRANSFER_TO, 11); + Staking::increase_total_stake_by(11); assert_err!( Contract::call(&0, CONTRACT_SHOULD_TRANSFER_TO, 3, 100_000, Vec::new()), @@ -331,8 +337,10 @@ fn contract_create() { with_externalities(&mut new_test_ext(0, 2), || { Staking::set_free_balance(&0, 100_000_000); + Staking::increase_total_stake_by(100_000_000); Staking::set_free_balance(&1, 0); Staking::set_free_balance(&9, 30); + Staking::increase_total_stake_by(30); <CodeOf<Test>>::insert(1, code_create.to_vec()); @@ -383,7 +391,9 @@ fn top_level_create() { ); Staking::set_free_balance(&0, 100_000_000); + Staking::increase_total_stake_by(100_000_000); Staking::set_free_balance(&derived_address, 30); + Staking::increase_total_stake_by(30); assert_ok!(Contract::create( &0, @@ -423,6 +433,7 @@ fn refunds_unused_gas() { <CodeOf<Test>>::insert(1, code_nop.to_vec()); Staking::set_free_balance(&0, 100_000_000); + Staking::increase_total_stake_by(100_000_000); assert_ok!(Contract::call(&0, 1, 0, 100_000, Vec::new(),)); @@ -436,6 +447,7 @@ fn call_with_zero_value() { <CodeOf<Test>>::insert(1, vec![]); Staking::set_free_balance(&0, 100_000_000); + Staking::increase_total_stake_by(100_000_000); assert_ok!(Contract::call(&0, 1, 0, 100_000, Vec::new(),)); @@ -449,6 +461,7 @@ fn create_with_zero_endowment() { with_externalities(&mut new_test_ext(0, 2), || { Staking::set_free_balance(&0, 100_000_000); + Staking::increase_total_stake_by(100_000_000); assert_ok!(Contract::create(&0, 0, 100_000, code_nop, Vec::new(),)); @@ -467,10 +480,12 @@ fn account_removal_removes_storage() { // Setup two accounts with free balance above than exsistential threshold. { Staking::set_free_balance(&1, 110); + Staking::increase_total_stake_by(110); <StorageOf<Test>>::insert(1, b"foo".to_vec(), b"1".to_vec()); <StorageOf<Test>>::insert(1, b"bar".to_vec(), b"2".to_vec()); Staking::set_free_balance(&2, 110); + Staking::increase_total_stake_by(110); <StorageOf<Test>>::insert(2, b"hello".to_vec(), b"3".to_vec()); <StorageOf<Test>>::insert(2, b"world".to_vec(), b"4".to_vec()); } @@ -515,6 +530,7 @@ fn top_level_call_refunds_even_if_fails() { <CodeOf<Test>>::insert(1, code_unreachable.to_vec()); Staking::set_free_balance(&0, 100_000_000); + Staking::increase_total_stake_by(100_000_000); assert_err!( Contract::call(&0, 1, 0, 100_000, Vec::new()), diff --git a/substrate/substrate/runtime/staking/src/lib.rs b/substrate/substrate/runtime/staking/src/lib.rs index b0bf08e96e3a8e713ad4e81210fa319a0227bcc3..bb89c2be8b34a0797a4f208865cbe404069e0396 100644 --- a/substrate/substrate/runtime/staking/src/lib.rs +++ b/substrate/substrate/runtime/staking/src/lib.rs @@ -302,7 +302,8 @@ impl<T: Trait> Module<T> { }; if transactor != &dest { - Self::set_free_balance(transactor, new_from_balance); + Self::set_free_balance(transactor, new_from_balance); + Self::decrease_total_stake_by(fee); Self::set_free_balance_creating(&dest, new_to_balance); } @@ -424,6 +425,7 @@ impl<T: Trait> Module<T> { /// In that case it will return `AccountKilled`. pub fn set_reserved_balance(who: &T::AccountId, balance: T::Balance) -> UpdateBalanceOutcome { if balance < Self::existential_deposit() { + <ReservedBalance<T>>::insert(who, balance); Self::on_reserved_too_low(who); UpdateBalanceOutcome::AccountKilled } else { @@ -443,6 +445,7 @@ impl<T: Trait> Module<T> { // Commented out for no - but consider it instructive. // assert!(!Self::voting_balance(who).is_zero()); if balance < Self::existential_deposit() { + <FreeBalance<T>>::insert(who, balance); Self::on_free_too_low(who); UpdateBalanceOutcome::AccountKilled } else { @@ -472,7 +475,7 @@ impl<T: Trait> Module<T> { // value of which makes even the `free_balance` unspendable. // TODO: enforce this for the other balance-altering functions. if balance < ed { - Self::on_free_too_low(who); + Self::set_free_balance(who, balance); UpdateBalanceOutcome::AccountKilled } else { if !<FreeBalance<T>>::exists(who) { @@ -481,10 +484,12 @@ impl<T: Trait> Module<T> { NewAccountOutcome::GoodHint => balance + <Module<T>>::reclaim_rebate(), _ => balance, }; - <FreeBalance<T>>::insert(who, credit); - } else { - <FreeBalance<T>>::insert(who, balance); + Self::set_free_balance(who, credit); + Self::increase_total_stake_by(credit - balance); + } else { + Self::set_free_balance(who, balance); } + UpdateBalanceOutcome::Updated } } @@ -498,6 +503,7 @@ impl<T: Trait> Module<T> { let free_balance = Self::free_balance(who); let free_slash = cmp::min(free_balance, value); Self::set_free_balance(who, free_balance - free_slash); + Self::decrease_total_stake_by(free_slash); if free_slash < value { Self::slash_reserved(who, value - free_slash) } else { @@ -513,6 +519,7 @@ impl<T: Trait> Module<T> { return Err("beneficiary account must pre-exist"); } Self::set_free_balance(who, Self::free_balance(who) + value); + Self::increase_total_stake_by(value); Ok(()) } @@ -558,6 +565,7 @@ impl<T: Trait> Module<T> { let b = Self::reserved_balance(who); let slash = cmp::min(b, value); Self::set_reserved_balance(who, b - slash); + Self::decrease_total_stake_by(slash); if value == slash { None } else { @@ -785,6 +793,7 @@ impl<T: Trait> Module<T> { /// Kill an account's free portion. fn on_free_too_low(who: &T::AccountId) { + Self::decrease_total_stake_by(Self::free_balance(who)); <FreeBalance<T>>::remove(who); <Bondage<T>>::remove(who); T::OnAccountKill::on_account_kill(who); @@ -796,11 +805,25 @@ impl<T: Trait> Module<T> { /// Kill an account's reserved portion. fn on_reserved_too_low(who: &T::AccountId) { + Self::decrease_total_stake_by(Self::reserved_balance(who)); <ReservedBalance<T>>::remove(who); if Self::free_balance(who).is_zero() { <system::AccountNonce<T>>::remove(who); } } + + /// Increase TotalStake by Value. + pub fn increase_total_stake_by(value: T::Balance) { + if <TotalStake<T>>::exists() { + <TotalStake<T>>::put(<Module<T>>::total_stake() + value); + } + } + /// Decrease TotalStake by Value. + pub fn decrease_total_stake_by(value: T::Balance) { + if <TotalStake<T>>::exists() { + <TotalStake<T>>::put(<Module<T>>::total_stake() - value); + } + } } impl<T: Trait> Executable for Module<T> { @@ -832,7 +855,8 @@ impl<T: Trait> MakePayment<T::AccountId> for Module<T> { if b < transaction_fee + Self::existential_deposit() { return Err("not enough funds for transaction fee"); } - <FreeBalance<T>>::insert(transactor, b - transaction_fee); + Self::set_free_balance(transactor, b - transaction_fee); + Self::decrease_total_stake_by(transaction_fee); Ok(()) } } diff --git a/substrate/substrate/runtime/staking/src/tests.rs b/substrate/substrate/runtime/staking/src/tests.rs index 36549d534f74c80fdf07a69d4a1c208698134eb3..b8e11cd98ffdeec07b459dc8b32598c3028f0023 100644 --- a/substrate/substrate/runtime/staking/src/tests.rs +++ b/substrate/substrate/runtime/staking/src/tests.rs @@ -28,6 +28,7 @@ fn reward_should_work() { assert_eq!(Staking::voting_balance(&10), 1); assert_ok!(Staking::reward(&10, 10)); assert_eq!(Staking::voting_balance(&10), 11); + assert_eq!(<TotalStake<Test>>::get(), 112); }); } @@ -408,7 +409,7 @@ fn staking_eras_work() { #[test] fn staking_balance_works() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - <FreeBalance<Test>>::insert(1, 42); + Staking::set_free_balance(&1, 42); assert_eq!(Staking::free_balance(&1), 42); assert_eq!(Staking::reserved_balance(&1), 0); assert_eq!(Staking::voting_balance(&1), 42); @@ -421,7 +422,8 @@ fn staking_balance_works() { #[test] fn staking_balance_transfer_works() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - <FreeBalance<Test>>::insert(1, 111); + Staking::set_free_balance(&1, 111); + Staking::increase_total_stake_by(111); assert_ok!(Staking::transfer(&1, 2.into(), 69)); assert_eq!(Staking::voting_balance(&1), 42); assert_eq!(Staking::voting_balance(&2), 69); @@ -431,7 +433,7 @@ fn staking_balance_transfer_works() { #[test] fn staking_balance_transfer_when_bonded_should_not_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - <FreeBalance<Test>>::insert(1, 111); + Staking::set_free_balance(&1, 111); assert_ok!(Staking::stake(&1)); assert_noop!(Staking::transfer(&1, 2.into(), 69), "bondage too high to send value"); }); @@ -440,7 +442,7 @@ fn staking_balance_transfer_when_bonded_should_not_work() { #[test] fn reserving_balance_should_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - <FreeBalance<Test>>::insert(1, 111); + Staking::set_free_balance(&1, 111); assert_eq!(Staking::voting_balance(&1), 111); assert_eq!(Staking::free_balance(&1), 111); @@ -457,7 +459,7 @@ fn reserving_balance_should_work() { #[test] fn staking_balance_transfer_when_reserved_should_not_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - <FreeBalance<Test>>::insert(1, 111); + Staking::set_free_balance(&1, 111); assert_ok!(Staking::reserve(&1, 69)); assert_noop!(Staking::transfer(&1, 2.into(), 69), "balance too low to send value"); }); @@ -466,7 +468,7 @@ fn staking_balance_transfer_when_reserved_should_not_work() { #[test] fn deducting_balance_should_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - <FreeBalance<Test>>::insert(1, 111); + Staking::set_free_balance(&1, 111); assert_ok!(Staking::reserve(&1, 69)); assert_eq!(Staking::free_balance(&1), 42); }); @@ -475,7 +477,7 @@ fn deducting_balance_should_work() { #[test] fn deducting_balance_when_bonded_should_not_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - <FreeBalance<Test>>::insert(1, 111); + Staking::set_free_balance(&1, 111); <Bondage<Test>>::insert(1, 2); System::set_block_number(1); assert_eq!(Staking::unlock_block(&1), LockStatus::LockedUntil(2)); @@ -486,8 +488,8 @@ fn deducting_balance_when_bonded_should_not_work() { #[test] fn refunding_balance_should_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - <FreeBalance<Test>>::insert(1, 42); - <ReservedBalance<Test>>::insert(1, 69); + Staking::set_free_balance(&1, 42); + Staking::set_reserved_balance(&1, 69); Staking::unreserve(&1, 69); assert_eq!(Staking::free_balance(&1), 111); assert_eq!(Staking::reserved_balance(&1), 0); @@ -497,29 +499,33 @@ fn refunding_balance_should_work() { #[test] fn slashing_balance_should_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - <FreeBalance<Test>>::insert(1, 111); + Staking::set_free_balance(&1, 111); + Staking::increase_total_stake_by(111); assert_ok!(Staking::reserve(&1, 69)); assert!(Staking::slash(&1, 69).is_none()); assert_eq!(Staking::free_balance(&1), 0); assert_eq!(Staking::reserved_balance(&1), 42); + assert_eq!(<TotalStake<Test>>::get(), 44); }); } #[test] fn slashing_incomplete_balance_should_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - <FreeBalance<Test>>::insert(1, 42); + Staking::set_free_balance(&1, 42); + Staking::increase_total_stake_by(42); assert_ok!(Staking::reserve(&1, 21)); assert!(Staking::slash(&1, 69).is_some()); assert_eq!(Staking::free_balance(&1), 0); assert_eq!(Staking::reserved_balance(&1), 0); + assert_eq!(<TotalStake<Test>>::get(), 2); }); } #[test] fn unreserving_balance_should_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - <FreeBalance<Test>>::insert(1, 111); + Staking::set_free_balance(&1, 111); assert_ok!(Staking::reserve(&1, 111)); Staking::unreserve(&1, 42); assert_eq!(Staking::reserved_balance(&1), 69); @@ -530,30 +536,34 @@ fn unreserving_balance_should_work() { #[test] fn slashing_reserved_balance_should_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - <FreeBalance<Test>>::insert(1, 111); + Staking::set_free_balance(&1, 111); + Staking::increase_total_stake_by(111); assert_ok!(Staking::reserve(&1, 111)); assert!(Staking::slash_reserved(&1, 42).is_none()); assert_eq!(Staking::reserved_balance(&1), 69); assert_eq!(Staking::free_balance(&1), 0); + assert_eq!(<TotalStake<Test>>::get(), 71); }); } #[test] fn slashing_incomplete_reserved_balance_should_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - <FreeBalance<Test>>::insert(1, 111); + Staking::set_free_balance(&1, 111); + Staking::increase_total_stake_by(111); assert_ok!(Staking::reserve(&1, 42)); assert!(Staking::slash_reserved(&1, 69).is_some()); assert_eq!(Staking::free_balance(&1), 69); assert_eq!(Staking::reserved_balance(&1), 0); + assert_eq!(<TotalStake<Test>>::get(), 71); }); } #[test] fn transferring_reserved_balance_should_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - <FreeBalance<Test>>::insert(1, 110); - <FreeBalance<Test>>::insert(2, 1); + Staking::set_free_balance(&1, 110); + Staking::set_free_balance(&2, 1); assert_ok!(Staking::reserve(&1, 110)); assert_ok!(Staking::transfer_reserved(&1, &2, 41), None); assert_eq!(Staking::reserved_balance(&1), 69); @@ -566,7 +576,7 @@ fn transferring_reserved_balance_should_work() { #[test] fn transferring_reserved_balance_to_nonexistent_should_fail() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - <FreeBalance<Test>>::insert(1, 111); + Staking::set_free_balance(&1, 111); assert_ok!(Staking::reserve(&1, 111)); assert_noop!(Staking::transfer_reserved(&1, &2, 42), "beneficiary account must pre-exist"); }); @@ -575,8 +585,8 @@ fn transferring_reserved_balance_to_nonexistent_should_fail() { #[test] fn transferring_incomplete_reserved_balance_should_work() { with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || { - <FreeBalance<Test>>::insert(1, 110); - <FreeBalance<Test>>::insert(2, 1); + Staking::set_free_balance(&1, 110); + Staking::set_free_balance(&2, 1); assert_ok!(Staking::reserve(&1, 41)); assert!(Staking::transfer_reserved(&1, &2, 69).unwrap().is_some()); assert_eq!(Staking::reserved_balance(&1), 0); @@ -599,5 +609,32 @@ fn transferring_too_high_value_should_not_panic() { assert_eq!(Staking::free_balance(&1), u64::max_value()); assert_eq!(Staking::free_balance(&2), 1); + }); +} + +#[test] +fn account_removal_on_free_too_low() { + with_externalities(&mut new_test_ext(100, 1, 3, 1, false, 0), || { + // Setup two accounts with free balance above the exsistential threshold. + { + Staking::set_free_balance(&1, 110); + Staking::increase_total_stake_by(110); + + Staking::set_free_balance(&2, 110); + Staking::increase_total_stake_by(110); + + assert_eq!(<TotalStake<Test>>::get(), 732); + } + + // Transfer funds from account 1 of such amount that after this transfer + // the balance of account 1 will be below the exsistential threshold. + // This should lead to the removal of all balance of this account. + assert_ok!(Staking::transfer(&1, 2.into(), 20)); + + // Verify free balance removal of account 1. + assert_eq!(Staking::free_balance(&1), 0); + + // Verify that TotalStake tracks balance removal when free balance is too low. + assert_eq!(<TotalStake<Test>>::get(), 642); }); }