mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 07:41:08 +00:00
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:
@@ -9,6 +9,7 @@ serde = { version = "1.0", default_features = false }
|
||||
serde_derive = { version = "1.0", optional = true }
|
||||
safe-mix = { version = "1.0", default_features = false}
|
||||
substrate-codec = { path = "../../codec", default_features = false }
|
||||
substrate-codec-derive = { path = "../../codec/derive", default_features = false }
|
||||
substrate-primitives = { path = "../../primitives", default_features = false }
|
||||
substrate-runtime-std = { path = "../../runtime-std", default_features = false }
|
||||
substrate-runtime-io = { path = "../../runtime-io", default_features = false }
|
||||
@@ -22,6 +23,7 @@ std = [
|
||||
"serde_derive",
|
||||
"safe-mix/std",
|
||||
"substrate-codec/std",
|
||||
"substrate-codec-derive/std",
|
||||
"substrate-primitives/std",
|
||||
"substrate-runtime-std/std",
|
||||
"substrate-runtime-io/std",
|
||||
|
||||
@@ -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 }
|
||||
]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user