Introduce Runtime Events (#607)

* Squashed commit.

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.
Merge remote-tracking branch 'origin/master' into gav-new-pos
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.
Merge remote-tracking branch 'origin/master' into gav-new-pos
Test with release.
Use safe math when dealing with total stake
Fix test again.
Introduce events into runtime.
Fix tests
Add events for account new/reap
Integration-style tests for events.

* Remove old code
This commit is contained in:
Gav Wood
2018-08-28 12:11:40 +01:00
committed by GitHub
parent f5c684dca6
commit 278a054b81
26 changed files with 518 additions and 86 deletions
+115 -7
View File
@@ -19,6 +19,9 @@
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(any(feature = "std", test))]
extern crate substrate_primitives;
#[cfg_attr(any(feature = "std", test), macro_use)]
extern crate substrate_runtime_std as rstd;
@@ -32,8 +35,11 @@ extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate substrate_runtime_io as runtime_io;
#[macro_use]
extern crate substrate_codec_derive;
extern crate substrate_codec as codec;
extern crate substrate_runtime_io as runtime_io;
extern crate substrate_runtime_primitives as primitives;
extern crate safe_mix;
@@ -74,26 +80,50 @@ pub trait Trait: Eq + Clone {
Hash = Self::Hash,
Digest = Self::Digest
>;
type Event: Parameter + Member;
}
decl_module! {
pub struct Module<T: Trait>;
}
/// A phase of a block's execution.
#[derive(Encode, Decode)]
#[cfg_attr(feature = "std", derive(Serialize, PartialEq, Eq, Clone, Debug))]
pub enum Phase {
/// Applying an extrinsic.
ApplyExtrinsic(u32),
/// The end.
Finalization,
}
/// Record of an event happening.
#[derive(Encode, Decode)]
#[cfg_attr(feature = "std", derive(Serialize, PartialEq, Eq, Clone, Debug))]
pub struct EventRecord<E: Parameter + Member> {
/// The phase of the block it happened in.
pub phase: Phase,
/// The event itself.
pub event: E,
}
decl_storage! {
trait Store for Module<T: Trait>;
pub AccountNonce get(account_nonce): b"sys:non" => default map [ T::AccountId => T::Index ];
pub BlockHash get(block_hash): b"sys:old" => required map [ T::BlockNumber => T::Hash ];
pub ExtrinsicIndex get(extrinsic_index): b"sys:xti" => required u32;
pub ExtrinsicData get(extrinsic_data): b"sys:xtd" => required map [ u32 => Vec<u8> ];
ExtrinsicCount: b"sys:extrinsic_count" => u32;
pub ExtrinsicIndex get(extrinsic_index): b"sys:xti" => u32;
ExtrinsicData get(extrinsic_data): b"sys:xtd" => required map [ u32 => Vec<u8> ];
RandomSeed get(random_seed): b"sys:rnd" => required T::Hash;
// The current block number being processed. Set by `execute_block`.
Number get(block_number): b"sys:num" => required T::BlockNumber;
ParentHash get(parent_hash): b"sys:pha" => required T::Hash;
ExtrinsicsRoot get(extrinsics_root): b"sys:txr" => required T::Hash;
Digest get(digest): b"sys:dig" => default T::Digest;
Events get(events): b"sys:events" => default Vec<EventRecord<T::Event>>;
}
impl<T: Trait> Module<T> {
@@ -105,19 +135,23 @@ impl<T: Trait> Module<T> {
<BlockHash<T>>::insert(*number - One::one(), parent_hash);
<ExtrinsicsRoot<T>>::put(txs_root);
<RandomSeed<T>>::put(Self::calculate_random());
<ExtrinsicIndex<T>>::put(0);
<ExtrinsicIndex<T>>::put(0u32);
<Events<T>>::kill();
}
/// Remove temporary "environment" entries in storage.
pub fn finalise() -> T::Header {
<RandomSeed<T>>::kill();
<ExtrinsicIndex<T>>::kill();
<ExtrinsicCount<T>>::kill();
let number = <Number<T>>::take();
let parent_hash = <ParentHash<T>>::take();
let digest = <Digest<T>>::take();
let extrinsics_root = <ExtrinsicsRoot<T>>::take();
let storage_root = T::Hashing::storage_root();
// <Events<T>> stays to be inspected by the client.
<T::Header as traits::Header>::new(number, extrinsics_root, storage_root, parent_hash, digest)
}
@@ -128,6 +162,14 @@ impl<T: Trait> Module<T> {
<Digest<T>>::put(l);
}
/// Deposits an event onto this block's event record.
pub fn deposit_event(event: T::Event) {
let phase = <ExtrinsicIndex<T>>::get().map_or(Phase::Finalization, |c| Phase::ApplyExtrinsic(c));
let mut events = Self::events();
events.push(EventRecord { phase, event });
<Events<T>>::put(events);
}
/// Calculate the current block's random seed.
fn calculate_random() -> T::Hash {
assert!(Self::block_number() > Zero::zero(), "Block number may never be zero");
@@ -180,12 +222,24 @@ impl<T: Trait> Module<T> {
/// Note what the extrinsic data of the current extrinsic index is. If this is called, then
/// ensure `derive_extrinsics` is also called before block-building is completed.
pub fn note_extrinsic(encoded_xt: Vec<u8>) {
<ExtrinsicData<T>>::insert(Self::extrinsic_index(), encoded_xt);
<ExtrinsicData<T>>::insert(<ExtrinsicIndex<T>>::get().unwrap_or_default(), encoded_xt);
}
/// To be called immediately after an extrinsic has been applied.
pub fn note_applied_extrinsic() {
<ExtrinsicIndex<T>>::put(<ExtrinsicIndex<T>>::get().unwrap_or_default() + 1u32);
}
/// To be called immediately after `note_applied_extrinsic` of the last extrinsic of the block
/// has been called.
pub fn note_finished_extrinsics() {
<ExtrinsicCount<T>>::put(<ExtrinsicIndex<T>>::get().unwrap_or_default());
<ExtrinsicIndex<T>>::kill();
}
/// Remove all extrinsics data and save the extrinsics trie root.
pub fn derive_extrinsics() {
let extrinsics = (0..Self::extrinsic_index()).map(<ExtrinsicData<T>>::take).collect();
let extrinsics = (0..<ExtrinsicCount<T>>::get().unwrap_or_default()).map(<ExtrinsicData<T>>::take).collect();
let xts_root = extrinsics_data_root::<T::Hashing>(extrinsics);
<ExtrinsicsRoot<T>>::put(xts_root);
}
@@ -219,3 +273,57 @@ impl<T: Trait> primitives::BuildStorage for GenesisConfig<T>
])
}
}
#[cfg(test)]
mod tests {
use super::*;
use runtime_io::with_externalities;
use substrate_primitives::H256;
use primitives::BuildStorage;
use primitives::traits::BlakeTwo256;
use primitives::testing::{Digest, Header};
#[derive(Clone, Eq, PartialEq)]
pub struct Test;
impl Trait for Test {
type Index = u64;
type BlockNumber = u64;
type Hash = H256;
type Hashing = BlakeTwo256;
type Digest = Digest;
type AccountId = u64;
type Header = Header;
type Event = u16;
}
type System = Module<Test>;
fn new_test_ext() -> runtime_io::TestExternalities<KeccakHasher> {
GenesisConfig::<Test>::default().build_storage().unwrap().into()
}
#[test]
fn deposit_event_should_work() {
with_externalities(&mut new_test_ext(), || {
System::initialise(&1, &[0u8; 32].into(), &[0u8; 32].into());
System::note_finished_extrinsics();
System::deposit_event(1u16);
System::finalise();
assert_eq!(System::events(), vec![EventRecord { phase: Phase::Finalization, event: 1u16 }]);
System::initialise(&2, &[0u8; 32].into(), &[0u8; 32].into());
System::deposit_event(42u16);
System::note_applied_extrinsic();
System::deposit_event(69u16);
System::note_applied_extrinsic();
System::note_finished_extrinsics();
System::deposit_event(3u16);
System::finalise();
assert_eq!(System::events(), vec![
EventRecord { phase: Phase::ApplyExtrinsic(0), event: 42u16 },
EventRecord { phase: Phase::ApplyExtrinsic(1), event: 69u16 },
EventRecord { phase: Phase::Finalization, event: 3u16 }
]);
});
}
}