Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
New slashing logic (#570)
Browse files Browse the repository at this point in the history
* New slashing mechanism (#554)

* Slashing improvements

- unstake when balance too low
- unstake after N slashes according to val prefs
- don't early-terminate session/era unless unstaked
- offline grace period before punishment

* Fix warning

* Cleanups and ensure slash_count decays

* Bump authoring version and introduce needed authoring stub

* Rename

* Fix offline tracker

* Fix offline tracker

* Renames

* Add test

* Tests

* Tests.

* Remove accidental merge files.

* Version bump, fixes (#572)

* Bump version, don't propose invalid blocks

* Fix build.

* Fixes.

* More fixes.

* Fix tests.

* Fix more tests

* More tests fixed

* Fix merge

* Fix accidental merge bug

* Fixes.

* Staking failsafes

- Don't slash/unstake/change session when too few staking participants
- Introduce set_balance PrivCall

* Make minimum validator count dynamic.

* test fixes

* Fix tests.

* Fix tests

* Fix tests, update readme.

* Test with release.

* Use safe math when dealing with total stake

* Fix test again.

* Fix grumbles.
  • Loading branch information
gavofyork committed Aug 27, 2018
1 parent 874550c commit 6b0d345
Show file tree
Hide file tree
Showing 18 changed files with 482 additions and 183 deletions.
2 changes: 1 addition & 1 deletion .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ test:rust:stable: &test
- export PATH="${CI_PROJECT_DIR}/cargo/bin/:$PATH"
- ./scripts/build.sh
- ./scripts/build-demos.sh
- time cargo test --all
- time cargo test --all --release
tags:
- rust-stable

Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

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

30 changes: 28 additions & 2 deletions README.adoc
Original file line number Diff line number Diff line change
@@ -1,4 +1,30 @@
# Substrate

Framework for blockchain innovators.
More to come here.
Next-generation framework for blockchain innovation.

## Description

At its heart, Substrate is a combination of three technologies: WebAssembly, Libp2p and AfG Consensus. It is both a library for building new blockchains with and a "skeleton key" of a blockchain client, able to synchronise to any Substrate-based chain.

Substrate chains have two distinct features that make them "next-generation": a dynamic, self-defining state-transition function and a progressive consensus algorithm with fast block production and adaptive, definite finality. The STF, encoded in WebAssembly, is known as the "runtime". This defines the `execute_block` function, and can specify everything from the staking algorithm, transaction semantics, logging mechanisms and governance procedures. Because the runtime is entirely dynamic all of these can be switched out or upgraded at any time. A Substrate chain is very much a "living organism".

## Roadmap

### So far

- 0.1 "PoC-1": PBFT consensus, Wasm runtime engine, basic runtime modules.
- 0.2 "PoC-2": Libp2p
### In progress

- AfG consensus
- Improved PoS
- Smart contract runtime module
### The future

- Splitting out runtime modules into separate repo
- Introduce substrate executable (the skeleton-key runtime)
- Introduce basic but extensible transaction queue and block-builder and place them in the executable.
- DAO runtime module
- Audit
2 changes: 2 additions & 0 deletions demo/cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,12 @@ pub fn run<I, T>(args: I) -> error::Result<()> where
existential_deposit: 500,
balances: vec![(god_key.clone().into(), 1u64 << 63)].into_iter().collect(),
validator_count: 12,
minimum_validator_count: 4,
sessions_per_era: 24, // 24 hours per era.
bonding_duration: 90, // 90 days per bond.
early_era_slash: 10000,
session_reward: 100,
offline_slash_grace: 0,
}),
democracy: Some(DemocracyConfig {
launch_period: 120 * 24 * 14, // 2 weeks per public referendum
Expand Down
14 changes: 11 additions & 3 deletions demo/executor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ mod tests {
fn panic_execution_with_foreign_code_gives_error() {
let mut t: TestExternalities<KeccakHasher> = map![
twox_128(&<staking::FreeBalance<Concrete>>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
twox_128(<staking::TotalStake<Concrete>>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
twox_128(<staking::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![70u8; 8],
twox_128(<staking::TransactionByteFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
twox_128(<staking::ExistentialDeposit<Concrete>>::key()).to_vec() => vec![0u8; 8],
Expand All @@ -121,6 +122,7 @@ mod tests {
fn bad_extrinsic_with_native_equivalent_code_gives_error() {
let mut t: TestExternalities<KeccakHasher> = map![
twox_128(&<staking::FreeBalance<Concrete>>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
twox_128(<staking::TotalStake<Concrete>>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
twox_128(<staking::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![70u8; 8],
twox_128(<staking::TransactionByteFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
twox_128(<staking::ExistentialDeposit<Concrete>>::key()).to_vec() => vec![0u8; 8],
Expand All @@ -140,6 +142,7 @@ mod tests {
fn successful_execution_with_native_equivalent_code_gives_ok() {
let mut t: TestExternalities<KeccakHasher> = map![
twox_128(&<staking::FreeBalance<Concrete>>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
twox_128(<staking::TotalStake<Concrete>>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
twox_128(<staking::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
twox_128(<staking::TransactionByteFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
twox_128(<staking::ExistentialDeposit<Concrete>>::key()).to_vec() => vec![0u8; 8],
Expand All @@ -163,6 +166,7 @@ mod tests {
fn successful_execution_with_foreign_code_gives_ok() {
let mut t: TestExternalities<KeccakHasher> = map![
twox_128(&<staking::FreeBalance<Concrete>>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
twox_128(<staking::TotalStake<Concrete>>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
twox_128(<staking::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
twox_128(<staking::TransactionByteFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
twox_128(<staking::ExistentialDeposit<Concrete>>::key()).to_vec() => vec![0u8; 8],
Expand Down Expand Up @@ -199,6 +203,7 @@ mod tests {
balances: vec![(alice(), 111)],
intentions: vec![alice(), bob(), Charlie.to_raw_public().into()],
validator_count: 3,
minimum_validator_count: 0,
bonding_duration: 0,
transaction_base_fee: 1,
transaction_byte_fee: 0,
Expand All @@ -208,6 +213,7 @@ mod tests {
reclaim_rebate: 0,
early_era_slash: 0,
session_reward: 0,
offline_slash_grace: 0,
}),
democracy: Some(Default::default()),
council: Some(Default::default()),
Expand Down Expand Up @@ -250,7 +256,7 @@ mod tests {
// Blake
// hex!("3437bf4b182ab17bb322af5c67e55f6be487a77084ad2b4e27ddac7242e4ad21").into(),
// Keccak
hex!("c563199c60df7d914262b1775b284870f3a5da2f24b56d2c6288b37c815a6cd9").into(),
hex!("856f39cc430b2ecc2b94f55f0df44b28a25ab3ed341a60bdf0b8f382616f675f").into(),
vec![BareExtrinsic {
signed: alice(),
index: 0,
Expand All @@ -266,7 +272,7 @@ mod tests {
// Blake
// hex!("741fcb660e6fa9f625fbcd993b49f6c1cc4040f5e0cc8727afdedf11fd3c464b").into(),
// Keccak
hex!("83f71d5475f63350825b0301de322233d3711a9f3fcfd74050d1534af47a36b3").into(),
hex!("32cb12103306811f4febf3a93c893ebd896f0df5bcf285912d406b43d9f041aa").into(),
vec![
BareExtrinsic {
signed: bob(),
Expand All @@ -289,7 +295,7 @@ mod tests {
// Blake
// hex!("2c7231a9c210a7aa4bea169d944bc4aaacd517862b244b8021236ffa7f697991").into(),
// Keccak
hex!("06d026c0d687ec583660a6052de6f89acdb24ea964d06be3831c837c3c426966").into(),
hex!("f7bdc5a3409738285c04585ec436c5c9c3887448f7cf1b5086664517681eb7c1").into(),
vec![BareExtrinsic {
signed: alice(),
index: 0,
Expand Down Expand Up @@ -364,6 +370,7 @@ mod tests {
fn panic_execution_gives_error() {
let mut t: TestExternalities<KeccakHasher> = map![
twox_128(&<staking::FreeBalance<Concrete>>::key_for(alice())).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
twox_128(<staking::TotalStake<Concrete>>::key()).to_vec() => vec![69u8, 0, 0, 0, 0, 0, 0, 0],
twox_128(<staking::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![70u8; 8],
twox_128(<staking::TransactionByteFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
twox_128(<staking::ExistentialDeposit<Concrete>>::key()).to_vec() => vec![0u8; 8],
Expand All @@ -384,6 +391,7 @@ mod tests {
fn successful_execution_gives_ok() {
let mut t: TestExternalities<KeccakHasher> = map![
twox_128(&<staking::FreeBalance<Concrete>>::key_for(alice())).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
twox_128(<staking::TotalStake<Concrete>>::key()).to_vec() => vec![111u8, 0, 0, 0, 0, 0, 0, 0],
twox_128(<staking::TransactionBaseFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
twox_128(<staking::TransactionByteFee<Concrete>>::key()).to_vec() => vec![0u8; 8],
twox_128(<staking::ExistentialDeposit<Concrete>>::key()).to_vec() => vec![0u8; 8],
Expand Down
2 changes: 1 addition & 1 deletion demo/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ impl Convert<AccountId, SessionKey> for SessionKeyConversion {
}

impl session::Trait for Concrete {
const NOTE_OFFLINE_POSITION: u32 = 1;
const NOTE_MISSED_PROPOSAL_POSITION: u32 = 1;
type ConvertAccountIdToSessionKey = SessionKeyConversion;
type OnSessionChange = Staking;
}
Expand Down
4 changes: 3 additions & 1 deletion substrate/runtime/contract/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ impl staking::Trait for Test {
type OnAccountKill = Contract;
}
impl session::Trait for Test {
const NOTE_OFFLINE_POSITION: u32 = 1;
const NOTE_MISSED_PROPOSAL_POSITION: u32 = 1;
type ConvertAccountIdToSessionKey = Identity;
type OnSessionChange = Staking;
}
Expand Down Expand Up @@ -100,6 +100,7 @@ fn new_test_ext(existential_deposit: u64, gas_price: u64) -> runtime_io::TestExt
balances: vec![],
intentions: vec![],
validator_count: 2,
minimum_validator_count: 0,
bonding_duration: 0,
transaction_base_fee: 0,
transaction_byte_fee: 0,
Expand All @@ -109,6 +110,7 @@ fn new_test_ext(existential_deposit: u64, gas_price: u64) -> runtime_io::TestExt
reclaim_rebate: 0,
early_era_slash: 0,
session_reward: 0,
offline_slash_grace: 0,
}.build_storage()
.unwrap(),
);
Expand Down
4 changes: 3 additions & 1 deletion substrate/runtime/council/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -653,7 +653,7 @@ mod tests {
type Header = Header;
}
impl session::Trait for Test {
const NOTE_OFFLINE_POSITION: u32 = 1;
const NOTE_MISSED_PROPOSAL_POSITION: u32 = 1;
type ConvertAccountIdToSessionKey = Identity;
type OnSessionChange = staking::Module<Test>;
}
Expand Down Expand Up @@ -688,6 +688,7 @@ mod tests {
balances: vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)],
intentions: vec![],
validator_count: 2,
minimum_validator_count: 0,
bonding_duration: 0,
transaction_base_fee: 0,
transaction_byte_fee: 0,
Expand All @@ -697,6 +698,7 @@ mod tests {
reclaim_rebate: 0,
early_era_slash: 0,
session_reward: 0,
offline_slash_grace: 0,
}.build_storage().unwrap());
t.extend(democracy::GenesisConfig::<Test>{
launch_period: 1,
Expand Down
24 changes: 13 additions & 11 deletions substrate/runtime/democracy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ mod tests {
type Header = Header;
}
impl session::Trait for Test {
const NOTE_OFFLINE_POSITION: u32 = 1;
const NOTE_MISSED_PROPOSAL_POSITION: u32 = 1;
type ConvertAccountIdToSessionKey = Identity;
type OnSessionChange = staking::Module<Test>;
}
Expand Down Expand Up @@ -429,6 +429,7 @@ mod tests {
balances: vec![(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)],
intentions: vec![],
validator_count: 2,
minimum_validator_count: 0,
bonding_duration: 3,
transaction_base_fee: 0,
transaction_byte_fee: 0,
Expand All @@ -438,6 +439,7 @@ mod tests {
reclaim_rebate: 0,
early_era_slash: 0,
session_reward: 0,
offline_slash_grace: 0,
}.build_storage().unwrap());
t.extend(GenesisConfig::<Test>{
launch_period: 1,
Expand Down Expand Up @@ -499,7 +501,7 @@ mod tests {
assert_eq!(Democracy::tally(r), (10, 0));

assert_eq!(Democracy::end_block(System::block_number()), Ok(()));
Staking::on_session_change(0, Vec::new());
Staking::on_session_change(0, true);

assert_eq!(Staking::era_length(), 2);
});
Expand Down Expand Up @@ -577,19 +579,19 @@ mod tests {
System::set_block_number(1);
assert_ok!(Democracy::vote(&1, 0, true));
assert_eq!(Democracy::end_block(System::block_number()), Ok(()));
Staking::on_session_change(0, Vec::new());
Staking::on_session_change(0, true);
assert_eq!(Staking::bonding_duration(), 4);

System::set_block_number(2);
assert_ok!(Democracy::vote(&1, 1, true));
assert_eq!(Democracy::end_block(System::block_number()), Ok(()));
Staking::on_session_change(0, Vec::new());
Staking::on_session_change(0, true);
assert_eq!(Staking::bonding_duration(), 3);

System::set_block_number(3);
assert_ok!(Democracy::vote(&1, 2, true));
assert_eq!(Democracy::end_block(System::block_number()), Ok(()));
Staking::on_session_change(0, Vec::new());
Staking::on_session_change(0, true);
assert_eq!(Staking::bonding_duration(), 2);
});
}
Expand All @@ -610,7 +612,7 @@ mod tests {
assert_eq!(Democracy::tally(r), (10, 0));

assert_eq!(Democracy::end_block(System::block_number()), Ok(()));
Staking::on_session_change(0, Vec::new());
Staking::on_session_change(0, true);

assert_eq!(Staking::era_length(), 2);
});
Expand All @@ -625,7 +627,7 @@ mod tests {
assert_ok!(Democracy::cancel_referendum(r));

assert_eq!(Democracy::end_block(System::block_number()), Ok(()));
Staking::on_session_change(0, Vec::new());
Staking::on_session_change(0, true);

assert_eq!(Staking::era_length(), 1);
});
Expand All @@ -643,7 +645,7 @@ mod tests {
assert_eq!(Democracy::tally(r), (0, 10));

assert_eq!(Democracy::end_block(System::block_number()), Ok(()));
Staking::on_session_change(0, Vec::new());
Staking::on_session_change(0, true);

assert_eq!(Staking::era_length(), 1);
});
Expand All @@ -664,7 +666,7 @@ mod tests {
assert_eq!(Democracy::tally(r), (110, 100));

assert_eq!(Democracy::end_block(System::block_number()), Ok(()));
Staking::on_session_change(0, Vec::new());
Staking::on_session_change(0, true);

assert_eq!(Staking::era_length(), 2);
});
Expand All @@ -681,7 +683,7 @@ mod tests {
assert_eq!(Democracy::tally(r), (60, 50));

assert_eq!(Democracy::end_block(System::block_number()), Ok(()));
Staking::on_session_change(0, Vec::new());
Staking::on_session_change(0, true);

assert_eq!(Staking::era_length(), 1);
});
Expand All @@ -702,7 +704,7 @@ mod tests {
assert_eq!(Democracy::tally(r), (100, 50));

assert_eq!(Democracy::end_block(System::block_number()), Ok(()));
Staking::on_session_change(0, Vec::new());
Staking::on_session_change(0, true);

assert_eq!(Staking::era_length(), 2);
});
Expand Down
10 changes: 6 additions & 4 deletions substrate/runtime/executive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ mod tests {
type Header = Header;
}
impl session::Trait for Test {
const NOTE_OFFLINE_POSITION: u32 = 1;
const NOTE_MISSED_PROPOSAL_POSITION: u32 = 1;
type ConvertAccountIdToSessionKey = Identity;
type OnSessionChange = staking::Module<Test>;
}
Expand All @@ -278,6 +278,7 @@ mod tests {
balances: vec![(1, 111)],
intentions: vec![],
validator_count: 0,
minimum_validator_count: 0,
bonding_duration: 0,
transaction_base_fee: 10,
transaction_byte_fee: 0,
Expand All @@ -287,6 +288,7 @@ mod tests {
reclaim_rebate: 0,
early_era_slash: 0,
session_reward: 0,
offline_slash_grace: 0,
}.build_storage().unwrap());
let xt = primitives::testing::TestXt((1, 0, Call::transfer(2.into(), 69)));
let mut t = runtime_io::TestExternalities::from(t);
Expand Down Expand Up @@ -317,8 +319,8 @@ mod tests {
// Blake
// state_root: hex!("02532989c613369596025dfcfc821339fc9861987003924913a5a1382f87034a").into(),
// Keccak
state_root: hex!("8fad93b6b9e5251a2e4913598fd0d74a138c0e486eb1133ff8081b429b0c56f2").into(),
extrinsics_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(), // REVIEW: I expected this to be wrong with a different hasher?
state_root: hex!("ed456461b82664990b6ebd1caf1360056f6e8a062e73fada331e1c92cd81cad4").into(),
extrinsics_root: hex!("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").into(),
digest: Digest { logs: vec![], },
},
extrinsics: vec![],
Expand Down Expand Up @@ -351,7 +353,7 @@ mod tests {
header: Header {
parent_hash: [69u8; 32].into(),
number: 1,
state_root: hex!("8fad93b6b9e5251a2e4913598fd0d74a138c0e486eb1133ff8081b429b0c56f2").into(),
state_root: hex!("ed456461b82664990b6ebd1caf1360056f6e8a062e73fada331e1c92cd81cad4").into(),
extrinsics_root: [0u8; 32].into(),
digest: Digest { logs: vec![], },
},
Expand Down
5 changes: 4 additions & 1 deletion substrate/runtime/primitives/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ use codec::{Codec, Encode};
pub use integer_sqrt::IntegerSquareRoot;
pub use num_traits::{Zero, One, Bounded};
pub use num_traits::ops::checked::{CheckedAdd, CheckedSub, CheckedMul, CheckedDiv};
use rstd::ops::{Add, Sub, Mul, Div, Rem, AddAssign, SubAssign, MulAssign, DivAssign, RemAssign};
use rstd::ops::{Add, Sub, Mul, Div, Rem, AddAssign, SubAssign, MulAssign, DivAssign,
RemAssign, Shl, Shr};

/// A lazy value.
pub trait Lazy<T: ?Sized> {
Expand Down Expand Up @@ -132,6 +133,7 @@ pub trait SimpleArithmetic:
Mul<Self, Output = Self> + MulAssign<Self> +
Div<Self, Output = Self> + DivAssign<Self> +
Rem<Self, Output = Self> + RemAssign<Self> +
Shl<u32, Output = Self> + Shr<u32, Output = Self> +
CheckedAdd +
CheckedSub +
CheckedMul +
Expand All @@ -145,6 +147,7 @@ impl<T:
Mul<Self, Output = Self> + MulAssign<Self> +
Div<Self, Output = Self> + DivAssign<Self> +
Rem<Self, Output = Self> + RemAssign<Self> +
Shl<u32, Output = Self> + Shr<u32, Output = Self> +
CheckedAdd +
CheckedSub +
CheckedMul +
Expand Down
Loading

0 comments on commit 6b0d345

Please sign in to comment.