Add grandpa telemetry (+ other minor improvements) (#1997)

* Support skipping the interactive purge prompt

Skip it via `cargo run -- purge-chain -y`.

* Fix typos

* Add Grandpa telemetry

* Address comments

* Revert unnecessary version bump

* Version bump to make CI run

* Remove unnecessary cast

* Do not bump version
This commit is contained in:
Michael Müller
2019-03-15 15:04:01 +01:00
committed by Bastian Köcher
parent 35a67b31e5
commit c52c528ee8
31 changed files with 139 additions and 45 deletions
+1 -1
View File
@@ -47,7 +47,7 @@ When reviewing a pull request, the end-goal is to suggest useful changes to the
== Helping out
We use https://github.com/paritytech/substrate/labels[labels] to manage PRs and issues and communicate state of a PR. Please familiarize yourself with them. Further more we are organising issues in https://github.com/paritytech/substrate/milestones[milestones]. Best way to get started is to a pick a ticket from the current milestone tagged https://github.com/paritytech/substrate/issues?q=is%3Aissue+is%3Aopen+label%3AQ2-easy[`easy`] or https://github.com/paritytech/substrate/issues?q=is%3Aissue+is%3Aopen+label%3AQ3-medium[`medium`] and get going or https://github.com/paritytech/substrate/issues?q=is%3Aissue+is%3Aopen+label%3AX1-mentor[`mentor`] and get in contact with the mentor offering their support on that larger task.
We use https://github.com/paritytech/substrate/labels[labels] to manage PRs and issues and communicate state of a PR. Please familiarize yourself with them. Furthermore we are organising issues in https://github.com/paritytech/substrate/milestones[milestones]. Best way to get started is to a pick a ticket from the current milestone tagged https://github.com/paritytech/substrate/issues?q=is%3Aissue+is%3Aopen+label%3AQ2-easy[`easy`] or https://github.com/paritytech/substrate/issues?q=is%3Aissue+is%3Aopen+label%3AQ3-medium[`medium`] and get going or https://github.com/paritytech/substrate/issues?q=is%3Aissue+is%3Aopen+label%3AX1-mentor[`mentor`] and get in contact with the mentor offering their support on that larger task.
== Releases
+1
View File
@@ -3612,6 +3612,7 @@ dependencies = [
"substrate-consensus-common 0.1.0",
"substrate-inherents 0.1.0",
"substrate-primitives 0.1.0",
"substrate-telemetry 0.3.1",
"substrate-test-client 0.1.0",
"substrate-transaction-pool 0.1.0",
]
@@ -14,6 +14,7 @@ consensus_common = { package = "substrate-consensus-common", path = "../../core/
primitives = { package = "substrate-primitives", path = "../../core/primitives" }
inherents = { package = "substrate-inherents", path = "../inherents" }
transaction_pool = { package = "substrate-transaction-pool", path = "../../core/transaction-pool" }
substrate-telemetry = { path = "../telemetry" }
[dev-dependencies]
test-client = { package = "substrate-test-client", path = "../../core/test-client" }
@@ -37,6 +37,7 @@ use runtime_primitives::generic::BlockId;
use runtime_primitives::ApplyError;
use transaction_pool::txpool::{self, Pool as TransactionPool};
use inherents::InherentData;
use substrate_telemetry::{telemetry, CONSENSUS_INFO};
/// Build new blocks.
pub trait BlockBuilder<Block: BlockT> {
@@ -252,6 +253,10 @@ impl<Block, C, A> Proposer<Block, C, A> where
.collect::<Vec<_>>()
.join(", ")
);
telemetry!(CONSENSUS_INFO; "prepared_block_for_proposing";
"number" => ?block.header().number(),
"hash" => ?<<C as AuthoringApi>::Block as BlockT>::Hash::from(block.header().hash()),
);
let substrate_block = Decode::decode(&mut block.encode().as_slice())
.expect("blocks are defined to serialize to substrate blocks correctly; qed");
+17 -12
View File
@@ -574,23 +574,28 @@ where
S: FnOnce(&str) -> Result<Option<ChainSpec<FactoryGenesis<F>>>, String>,
{
let config = create_config_with_db_path::<F, _>(spec_factory, &cli.shared_params, version)?;
let db_path = config.database_path;
print!("Are you sure to remove {:?}? (y/n)", &db_path);
stdout().flush().expect("failed to flush stdout");
let mut input = String::new();
stdin().read_line(&mut input)?;
let input = input.trim();
if cli.yes == false {
print!("Are you sure to remove {:?}? (y/n)", &db_path);
stdout().flush().expect("failed to flush stdout");
match input.chars().nth(0) {
Some('y') | Some('Y') => {
fs::remove_dir_all(&db_path)?;
println!("{:?} removed.", &db_path);
},
_ => println!("Aborted"),
let mut input = String::new();
stdin().read_line(&mut input)?;
let input = input.trim();
match input.chars().nth(0) {
Some('y') | Some('Y') => {},
_ => {
println!("Aborted");
return Ok(());
},
}
}
fs::remove_dir_all(&db_path)?;
println!("{:?} removed.", &db_path);
Ok(())
}
+4
View File
@@ -338,6 +338,10 @@ impl_get_log_filter!(RevertCmd);
/// The `purge-chain` command used to remove the whole chain.
#[derive(Debug, StructOpt, Clone)]
pub struct PurgeChainCmd {
/// Skip interactive prompt by answering yes automatically.
#[structopt(short = "y")]
pub yes: bool,
#[allow(missing_docs)]
#[structopt(flatten)]
pub shared_params: SharedParams,
@@ -109,7 +109,7 @@ impl<H: Hasher, S: StateBackend<H>, B: Block> CachingState<H, S, B> {
}
}
/// Propagate local cache into the shared cache and synchonize
/// Propagate local cache into the shared cache and synchronize
/// the shared cache with the best block state.
/// This function updates the shared cache by removing entries
/// that are invalidated by chain reorganization. `sync_cache`
@@ -22,6 +22,7 @@ use substrate_primitives::ed25519;
use grandpa::VoterSet;
use parity_codec::{Encode, Decode};
use log::{debug, info};
use substrate_telemetry::{telemetry, CONSENSUS_INFO};
use std::cmp::Ord;
use std::fmt::Debug;
@@ -261,6 +262,9 @@ where
// apply this change: make the set canonical
info!(target: "finality", "Applying authority set change forced at block #{:?}",
change.canon_height);
telemetry!(CONSENSUS_INFO; "afg.applying_forced_authority_set_change";
"block" => ?change.canon_height
);
let median_last_finalized = match change.delay_kind {
DelayKind::Best { ref median_last_finalized } => median_last_finalized.clone(),
@@ -324,6 +328,9 @@ where
if let Some(change) = change {
info!(target: "finality", "Applying authority set change scheduled at block #{:?}",
change.canon_height);
telemetry!(CONSENSUS_INFO; "afg.applying_scheduled_authority_set_change";
"block" => ?change.canon_height
);
self.current_authorities = change.next_authorities;
self.set_id += 1;
@@ -21,11 +21,13 @@ use std::collections::HashMap;
use std::sync::Arc;
use grandpa::VoterSet;
use grandpa::Message::{Prevote, Precommit};
use futures::prelude::*;
use futures::sync::mpsc;
use log::{debug, trace};
use parity_codec::{Encode, Decode};
use substrate_primitives::{ed25519, Pair};
use substrate_telemetry::{telemetry, CONSENSUS_INFO};
use runtime_primitives::traits::Block as BlockT;
use tokio::timer::Interval;
use crate::{Error, Network, Message, SignedMessage, Commit,
@@ -283,6 +285,24 @@ pub(crate) fn checked_message_stream<Block: BlockT, S>(
debug!(target: "afg", "Skipping message from unknown voter {}", msg.message.id);
return Ok(None);
}
match &msg.message.message {
Prevote(prevote) => {
telemetry!(CONSENSUS_INFO; "afg.received_prevote";
"voter" => ?format!("{}", msg.message.id),
"target_number" => ?prevote.target_number,
"target_hash" => ?prevote.target_hash,
);
},
Precommit(precommit) => {
telemetry!(CONSENSUS_INFO; "afg.received_precommit";
"voter" => ?format!("{}", msg.message.id),
"target_number" => ?precommit.target_number,
"target_hash" => ?precommit.target_hash,
);
},
};
Ok(Some(msg.message))
}
_ => {
@@ -436,6 +456,15 @@ pub(crate) fn checked_commit_stream<Block: BlockT, S>(
match msg {
GossipMessage::Commit(msg) => {
let round = msg.round;
let precommits_signed_by: Vec<String> =
msg.message.auth_data.iter().map(move |(_, a)| {
format!("{}", a)
}).collect();
telemetry!(CONSENSUS_INFO; "afg.received_commit";
"contains_precommits_signed_by" => ?precommits_signed_by,
"target_number" => ?msg.message.target_number,
"target_hash" => ?msg.message.target_hash,
);
check_compact_commit::<Block>(msg.message, &*voters).map(move |c| (round, c))
},
_ => {
@@ -477,6 +506,9 @@ impl<Block: BlockT, N: Network<Block>> Sink for CommitsOut<Block, N> {
}
let (round, commit) = input;
telemetry!(CONSENSUS_INFO; "afg.commit_issued";
"target_number" => ?commit.target_number, "target_hash" => ?commit.target_hash,
);
let (precommits, auth_data) = commit.precommits.into_iter()
.map(|signed| (signed.precommit, (signed.signature, signed.id)))
.unzip();
@@ -34,6 +34,7 @@ use runtime_primitives::traits::{
As, Block as BlockT, Header as HeaderT, NumberFor, One, Zero,
};
use substrate_primitives::{Blake2Hasher, ed25519, H256, Pair};
use substrate_telemetry::{telemetry, CONSENSUS_INFO};
use crate::{
Commit, Config, Error, Network, Precommit, Prevote,
@@ -469,6 +470,9 @@ pub(crate) fn finalize_block<B, Block: BlockT<Hash=H256>, E, RA>(
warn!(target: "finality", "Error applying finality to block {:?}: {:?}", (hash, number), e);
e
})?;
telemetry!(CONSENSUS_INFO; "afg.finalized_blocks_up_to";
"number" => ?number, "hash" => ?hash,
);
let new_authorities = if let Some((canon_hash, canon_number)) = status.new_set_block {
// the authority set has changed.
@@ -480,6 +484,11 @@ pub(crate) fn finalize_block<B, Block: BlockT<Hash=H256>, E, RA>(
info!("Applying GRANDPA set change to new set {:?}", set_ref);
}
telemetry!(CONSENSUS_INFO; "afg.generating_new_authority_set";
"number" => ?canon_number, "hash" => ?canon_hash,
"authorities" => ?set_ref.to_vec(),
"set_id" => ?new_id,
);
Some(NewAuthoritySet {
canon_hash,
canon_number,
@@ -44,6 +44,7 @@ use runtime_primitives::traits::{
};
use substrate_primitives::{ed25519, H256};
use ed25519::Public as AuthorityId;
use substrate_telemetry::{telemetry, CONSENSUS_INFO};
use crate::justification::GrandpaJustification;
@@ -170,14 +171,14 @@ fn do_check_finality_proof<Block: BlockT<Hash=H256>, C, J>(
}
}
// check that the last header in finalization path is the jsutification target block
// check that the last header in finalization path is the justification target block
let just_block = proof.justification.target_block();
{
let finalized_header = proof.finalization_path.last()
.expect("checked above that proof.finalization_path is not empty; qed");
if *finalized_header.number() != just_block.0 || finalized_header.hash() != just_block.1 {
return Err(ClientErrorKind::BadJustification(
"finality proof: target jsutification block is not a part of finalized path".into()
"finality proof: target justification block is not a part of finalized path".into()
).into());
}
}
@@ -196,6 +197,8 @@ fn do_check_finality_proof<Block: BlockT<Hash=H256>, C, J>(
// and now check justification
proof.justification.verify(set_id, &grandpa_authorities.into_iter().collect())?;
telemetry!(CONSENSUS_INFO; "afg.finality_proof_ok";
"set_id" => ?set_id, "finalized_header_hash" => ?block.1);
Ok(proof.finalization_path)
}
+29 -2
View File
@@ -69,7 +69,7 @@ use fg_primitives::GrandpaApi;
use inherents::InherentDataProviders;
use runtime_primitives::generic::BlockId;
use substrate_primitives::{ed25519, H256, Blake2Hasher, Pair};
use substrate_telemetry::{telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG, CONSENSUS_WARN};
use substrate_telemetry::{telemetry, CONSENSUS_TRACE, CONSENSUS_DEBUG, CONSENSUS_WARN, CONSENSUS_INFO};
use srml_finality_tracker;
@@ -388,6 +388,17 @@ impl<Block: BlockT> GossipValidator<Block> {
}
let topic = commit_topic::<Block>(full.set_id);
let precommits_signed_by: Vec<String> = full.message.auth_data.iter().map(move |(_, a)| {
format!("{}", a)
}).collect();
telemetry!(CONSENSUS_INFO; "afg.received_commit_msg";
"contains_precommits_signed_by" => ?precommits_signed_by,
"round" => ?full.round,
"set_id" => ?full.set_id,
"topic" => ?topic,
"block_hash" => ?full.message,
);
network_gossip::ValidationResult::Valid(topic)
}
}
@@ -750,7 +761,13 @@ fn register_finality_tracker_inherent_data_provider<B, E, Block: BlockT<Hash=H25
.register_provider(srml_finality_tracker::InherentDataProvider::new(move || {
match client.backend().blockchain().info() {
Err(e) => Err(std::borrow::Cow::Owned(e.to_string())),
Ok(info) => Ok(info.finalized_number),
Ok(info) => {
telemetry!(CONSENSUS_INFO; "afg.finalized";
"finalized_number" => ?info.finalized_number,
"finalized_hash" => ?info.finalized_hash,
);
Ok(info.finalized_number)
},
}
}))
.map_err(|err| consensus_common::ErrorKind::InherentData(err.into()).into())
@@ -862,6 +879,16 @@ pub fn run_grandpa<B, E, Block: BlockT<Hash=H256>, N, RA>(
let handle_voter_command = move |command: VoterCommand<_, _>, voter_commands_rx| {
match command {
VoterCommand::ChangeAuthorities(new) => {
let voters: Vec<String> = new.authorities.iter().map(move |(a, _)| {
format!("{}", a)
}).collect();
telemetry!(CONSENSUS_INFO; "afg.voter_command_change_authorities";
"number" => ?new.canon_number,
"hash" => ?new.canon_hash,
"voters" => ?voters,
"set_id" => ?new.set_id,
);
// start the new authority set using the block where the
// set changed (not where the signal happened!) as the base.
let genesis_state = RoundState::genesis((new.canon_hash, new.canon_number));
+1 -1
View File
@@ -399,7 +399,7 @@ pub trait ProvideInherent {
fn create_inherent(data: &InherentData) -> Option<Self::Call>;
/// Check the given inherent if it is valid.
/// Checking the inherent is optional and can be ommitted.
/// Checking the inherent is optional and can be omitted.
fn check_inherent(_: &Self::Call, _: &InherentData) -> Result<(), Self::Error> {
Ok(())
}
@@ -315,7 +315,7 @@ impl<B: BlockT> ConsensusGossip<B> {
use std::collections::hash_map::Entry;
let engine_id = message.engine_id;
//validate the message
// validate the message
let (topic, status) = match self.validators.get(&engine_id)
.map(|v| v.validate(&message.data))
{
+1 -1
View File
@@ -164,7 +164,7 @@ pub const MEM_UNLIMITED: u32 = -1i32 as u32;
/// For FFI purposes.
pub const ERR_OK: u32 = 0;
/// Validation or instantiation error occured when creating new
/// Validation or instantiation error occurred when creating new
/// sandboxed module instance.
///
/// For FFI purposes.
@@ -51,7 +51,7 @@ const API_VERSION_ATTRIBUTE: &str = "api_version";
/// Is used when the function signature changed between different versions of a trait.
/// This attribute should be placed on the old signature of the function.
const CHANGED_IN_ATTRIBUTE: &str = "changed_in";
/// All attributes that we support in the declaratio of a runtime api trait.
/// All attributes that we support in the declaration of a runtime api trait.
const SUPPORTED_ATTRIBUTE_NAMES: &[&str] = &[
CORE_TRAIT_ATTRIBUTE, API_VERSION_ATTRIBUTE, CHANGED_IN_ATTRIBUTE
];
@@ -127,7 +127,7 @@ fn return_type_is_using_block(ty: &ReturnType) -> bool {
visitor.result
}
/// Replace all occurences of `Block` with `NodeBlock`
/// Replace all occurrences of `Block` with `NodeBlock`
struct ReplaceBlockWithNodeBlock {}
impl Fold for ReplaceBlockWithNodeBlock {
@@ -140,13 +140,13 @@ impl Fold for ReplaceBlockWithNodeBlock {
}
}
/// Replace all occurences of `Block` with `NodeBlock`
/// Replace all occurrences of `Block` with `NodeBlock`
fn fn_arg_replace_block_with_node_block(fn_arg: FnArg) -> FnArg {
let mut replace = ReplaceBlockWithNodeBlock {};
fold::fold_fn_arg(&mut replace, fn_arg)
}
/// Replace all occurences of `Block` with `NodeBlock`
/// Replace all occurrences of `Block` with `NodeBlock`
fn return_type_replace_block_with_node_block(return_type: ReturnType) -> ReturnType {
let mut replace = ReplaceBlockWithNodeBlock {};
fold::fold_return_type(&mut replace, return_type)
@@ -162,7 +162,7 @@ fn generate_native_call_generators(decl: &ItemTrait) -> Result<TokenStream> {
let trait_ = &decl.ident;
let crate_ = generate_crate_access(HIDDEN_INCLUDES_ID);
// Auxilariy function that is used to convert between types that use different block types.
// Auxiliary function that is used to convert between types that use different block types.
// The function expects that both a convertable by encoding the one and decoding the other.
result.push(quote!(
#[cfg(any(feature = "std", test))]
@@ -407,7 +407,7 @@ fn generate_api_impl_for_runtime(impls: &[ItemImpl]) -> Result<TokenStream> {
}
/// Auxilariy data structure that is used to convert `impl Api for Runtime` to
/// Auxiliary data structure that is used to convert `impl Api for Runtime` to
/// `impl Api for RuntimeApi`.
/// This requires us to replace the runtime `Block` with the node `Block`,
/// `impl Api for Runtime` with `impl Api for RuntimeApi` and replace the method implementations
@@ -483,7 +483,7 @@ impl<'a> Fold for ApiRuntimeImplToApiRuntimeApiImpl<'a> {
-> #crate_::error::Result<#crate_::runtime_api::NativeOrEncoded<#ret_type>>
);
// Generate the new method implementation that calls into the runime.
// Generate the new method implementation that calls into the runtime.
parse_quote!(
{
// Get the error to the user (if we have one).
+1 -1
View File
@@ -155,7 +155,7 @@ pub fn impl_runtime_apis(input: TokenStream) -> TokenStream {
///
/// To support versioning of the traits, the macro supports the attribute `#[api_version(1)]`.
/// The attribute supports any `u32` as version. By default, each trait is at version `1`, if no
/// version is provided. We also support chaning the signature of a method. This signature
/// version is provided. We also support changing the signature of a method. This signature
/// change is highlighted with the `#[changed_in(2)]` attribute above a method. A method that is
/// tagged with this attribute is callable by the name `METHOD_before_version_VERSION`. This
/// method will only support calling into wasm, trying to call into native will fail (change the
+1 -1
View File
@@ -54,7 +54,7 @@ pub fn generate_hidden_includes(unique_id: &'static str) -> TokenStream {
}.into()
}
/// Generates the access to the `subtrate_client` crate.
/// Generates the access to the `substrate_client` crate.
pub fn generate_crate_access(unique_id: &'static str) -> TokenStream {
if env::var("CARGO_PKG_NAME").unwrap() == "substrate-client" {
quote!( crate )
+1 -1
View File
@@ -580,7 +580,7 @@ pub fn sr25519_verify<P: AsRef<[u8]>>(sig: &[u8; 64], msg: &[u8], pubkey: P) ->
/// Verify and recover a SECP256k1 ECDSA signature.
/// - `sig` is passed in RSV format. V should be either 0/1 or 27/28.
/// - returns `None` if the signatue is bad, the 64-byte pubkey (doesn't include the 0x04 prefix).
/// - returns `None` if the signature is bad, the 64-byte pubkey (doesn't include the 0x04 prefix).
pub fn secp256k1_ecdsa_recover(sig: &[u8; 65], msg: &[u8; 32]) -> Result<[u8; 64], EcdsaVerifyError> {
let mut pubkey = [0u8; 64];
match unsafe {
+3 -3
View File
@@ -625,7 +625,7 @@ macro_rules! impl_outer_log {
}
impl $crate::codec::Decode for $name {
/// `generic::DigestItem` binray compatible decode.
/// `generic::DigestItem` binary compatible decode.
fn decode<I: $crate::codec::Input>(input: &mut I) -> Option<Self> {
let gen: $crate::generic::DigestItem<$($genarg),*> =
$crate::codec::Decode::decode(input)?;
@@ -634,7 +634,7 @@ macro_rules! impl_outer_log {
}
impl $crate::codec::Encode for $name {
/// `generic::DigestItem` binray compatible encode.
/// `generic::DigestItem` binary compatible encode.
fn encode(&self) -> Vec<u8> {
match self.dref() {
Some(dref) => dref.encode(),
@@ -665,7 +665,7 @@ macro_rules! impl_outer_log {
};
}
/// Simple blob to hold an extrinsic without commiting to its format and ensure it is serialized
/// Simple blob to hold an extrinsic without committing to its format and ensure it is serialized
/// correctly.
#[derive(PartialEq, Eq, Clone, Default, Encode, Decode)]
#[cfg_attr(feature = "std", derive(Debug))]
+1 -1
View File
@@ -140,7 +140,7 @@ impl<T> EnvironmentDefinitionBuilder<T> {
}
}
/// Register a host function in this environment defintion.
/// Register a host function in this environment definition.
///
/// NOTE that there is no constraints on type of this function. An instance
/// can import function passed here with any signature it wants. It can even import
+2 -2
View File
@@ -214,7 +214,7 @@ cfg_if! {
pub trait TestAPI {
/// Return the balance of the given account id.
fn balance_of(id: AccountId) -> u64;
/// A benchmkark function that adds one to the given value and returns the result.
/// A benchmark function that adds one to the given value and returns the result.
fn benchmark_add_one(val: &u64) -> u64;
/// A benchmark function that adds one to each value in the given vector and returns the
/// result.
@@ -239,7 +239,7 @@ cfg_if! {
pub trait TestAPI {
/// Return the balance of the given account id.
fn balance_of(id: AccountId) -> u64;
/// A benchmkark function that adds one to the given value and returns the result.
/// A benchmark function that adds one to the given value and returns the result.
fn benchmark_add_one(val: &u64) -> u64;
/// A benchmark function that adds one to each value in the given vector and returns the
/// result.
+1 -1
View File
@@ -52,7 +52,7 @@ pub fn nonce_of(who: AccountId) -> u64 {
storage::get_or(&who.to_keyed_vec(NONCE_OF), 0)
}
/// Get authorities ar given block.
/// Get authorities at given block.
pub fn authorities() -> Vec<AuthorityId> {
let len: u32 = storage::unhashed::get(well_known_keys::AUTHORITY_COUNT)
.expect("There are always authorities in test-runtime");
+1 -1
View File
@@ -213,7 +213,7 @@ pub trait DefaultByte {
fn default_byte(&self) -> Vec<u8>;
}
/// Wrapper over dyn pointer for accessing a cached once byet value.
/// Wrapper over dyn pointer for accessing a cached once byte value.
#[derive(Clone)]
pub struct DefaultByteGetter(pub &'static dyn DefaultByte);
+1 -1
View File
@@ -30,7 +30,7 @@ pub use srml_metadata::{
/// A type that can not be instantiated.
pub enum Never {}
/// Result of a module function call; either nothing (functions are only called for "side efeects")
/// Result of a module function call; either nothing (functions are only called for "side effects")
/// or an error message.
pub type Result = result::Result<(), &'static str>;
+1 -1
View File
@@ -121,7 +121,7 @@ pub trait StorageDoubleMap {
fn derive_key2(key2_data: Vec<u8>) -> Vec<u8>;
/// Returns a compound key that consist of the two parts: (prefix, `k1`) and `k2`.
/// The first part is hased and then concatenated with a hash of `k2`.
/// The first part is hashed and then concatenated with a hash of `k2`.
fn full_key<Q, R>(k1: &Q, k2: &R) -> Vec<u8>
where
Self::Key1: Borrow<Q>,
+1 -1
View File
@@ -67,7 +67,7 @@ pub use srml_metadata::{EventMetadata, DecodeDifferent, OuterEventMetadata, FnEn
///
/// mod event2 {
/// // Event that uses the generic parameter `Balance`.
/// // If no name for the generic parameter is speciefied explicitly,
/// // If no name for the generic parameter is specified explicitly,
/// // the name will be taken from the type name of the trait.
/// decl_event!(
/// pub enum Event<T> where <T as super::Trait>::Balance {
+3 -3
View File
@@ -176,7 +176,7 @@ pub trait Currency<AccountId> {
/// they can be individually replaced or removed.
pub type LockIdentifier = [u8; 8];
/// A currency whose accounts can have liquidity restructions.
/// A currency whose accounts can have liquidity restrictions.
pub trait LockableCurrency<AccountId>: Currency<AccountId> {
/// The quantity used to denote time; usually just a `BlockNumber`.
type Moment;
@@ -210,7 +210,7 @@ pub trait LockableCurrency<AccountId>: Currency<AccountId> {
/// Charge bytes fee trait
pub trait ChargeBytesFee<AccountId> {
/// Charge fees from `transactor` for an extrinsic (transaction) of encoded length
/// `encoded_len` bytes. Return Ok iff the payment was successful.
/// `encoded_len` bytes. Return Ok if the payment was successful.
fn charge_base_bytes_fee(transactor: &AccountId, encoded_len: usize) -> Result<(), &'static str>;
}
@@ -222,7 +222,7 @@ pub trait ChargeFee<AccountId>: ChargeBytesFee<AccountId> {
/// Charge `amount` of fees from `transactor`. Return Ok iff the payment was successful.
fn charge_fee(transactor: &AccountId, amount: Self::Amount) -> Result<(), &'static str>;
/// Refund `amount` of previous charged fees from `transactor`. Return Ok iff the refund was successful.
/// Refund `amount` of previous charged fees from `transactor`. Return Ok if the refund was successful.
fn refund_fee(transactor: &AccountId, amount: Self::Amount) -> Result<(), &'static str>;
}