mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-06 07:58:02 +00:00
2c0e73b78c
In order to have authorities (validators) discover each other, they need
to publish their public addresses by their ip address on the Kademlia
Dht indexed by their public key. This payload needs to be signed by a
key identifying them as a valid authority.
Code inside `/core` does not know the current set of authorities nor
can it assume what kind of cryptography primitives are currently in use.
Instead it can retrieve its public key and the current set of
authorities from the runtime and have it sign and verify Dht payloads.
This commit enables code in `/core` to do so by introducing a srml
module and runtime api to:
1. Retrieve own public key.
2. Retrieve public keys of current authority set.
3. Sign a Dht payload.
4. Verify a Dht payload.
This commit makes the logic from the previous commit
(`core/consensus/common/primitives.ConsensusApi`)
cf80af9255 obsolete and thus removes it.
410 lines
13 KiB
Rust
410 lines
13 KiB
Rust
//! The Substrate Node Template runtime. This can be compiled with `#[no_std]`, ready for Wasm.
|
|
|
|
#![cfg_attr(not(feature = "std"), no_std)]
|
|
// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
|
|
#![recursion_limit="256"]
|
|
|
|
// Make the WASM binary available.
|
|
#[cfg(feature = "std")]
|
|
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
|
|
|
|
use rstd::prelude::*;
|
|
use primitives::{OpaqueMetadata, crypto::key_types};
|
|
use sr_primitives::{
|
|
ApplyResult, transaction_validity::TransactionValidity, generic, create_runtime_str,
|
|
impl_opaque_keys, AnySignature
|
|
};
|
|
use sr_primitives::traits::{NumberFor, BlakeTwo256, Block as BlockT, DigestFor, StaticLookup, Verify, ConvertInto};
|
|
use sr_primitives::weights::Weight;
|
|
use babe::{AuthorityId as BabeId};
|
|
use grandpa::{AuthorityId as GrandpaId, AuthorityWeight as GrandpaWeight};
|
|
use grandpa::fg_primitives::{self, ScheduledChange};
|
|
use client::{
|
|
block_builder::api::{CheckInherentsResult, InherentData, self as block_builder_api},
|
|
runtime_api as client_api, impl_runtime_apis
|
|
};
|
|
use version::RuntimeVersion;
|
|
#[cfg(feature = "std")]
|
|
use version::NativeVersion;
|
|
|
|
// A few exports that help ease life for downstream crates.
|
|
#[cfg(any(feature = "std", test))]
|
|
pub use sr_primitives::BuildStorage;
|
|
pub use timestamp::Call as TimestampCall;
|
|
pub use balances::Call as BalancesCall;
|
|
pub use sr_primitives::{Permill, Perbill};
|
|
pub use support::{StorageValue, construct_runtime, parameter_types};
|
|
|
|
/// An index to a block.
|
|
pub type BlockNumber = u32;
|
|
|
|
/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.
|
|
pub type Signature = AnySignature;
|
|
|
|
/// Some way of identifying an account on the chain. We intentionally make it equivalent
|
|
/// to the public key of our transaction signing scheme.
|
|
pub type AccountId = <Signature as Verify>::Signer;
|
|
|
|
/// The type for looking up accounts. We don't expect more than 4 billion of them, but you
|
|
/// never know...
|
|
pub type AccountIndex = u32;
|
|
|
|
/// Balance of an account.
|
|
pub type Balance = u128;
|
|
|
|
/// Index of a transaction in the chain.
|
|
pub type Index = u32;
|
|
|
|
/// A hash of some data used by the chain.
|
|
pub type Hash = primitives::H256;
|
|
|
|
/// Digest item type.
|
|
pub type DigestItem = generic::DigestItem<Hash>;
|
|
|
|
/// Used for the module template in `./template.rs`
|
|
mod template;
|
|
|
|
/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
|
|
/// the specifics of the runtime. They can then be made to be agnostic over specific formats
|
|
/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
|
|
/// to even the core datastructures.
|
|
pub mod opaque {
|
|
use super::*;
|
|
|
|
pub use sr_primitives::OpaqueExtrinsic as UncheckedExtrinsic;
|
|
|
|
/// Opaque block header type.
|
|
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
|
|
/// Opaque block type.
|
|
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
|
|
/// Opaque block identifier type.
|
|
pub type BlockId = generic::BlockId<Block>;
|
|
|
|
pub type SessionHandlers = (Grandpa, Babe);
|
|
|
|
impl_opaque_keys! {
|
|
pub struct SessionKeys {
|
|
#[id(key_types::GRANDPA)]
|
|
pub grandpa: GrandpaId,
|
|
#[id(key_types::BABE)]
|
|
pub babe: BabeId,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// This runtime version.
|
|
pub const VERSION: RuntimeVersion = RuntimeVersion {
|
|
spec_name: create_runtime_str!("node-template"),
|
|
impl_name: create_runtime_str!("node-template"),
|
|
authoring_version: 3,
|
|
spec_version: 4,
|
|
impl_version: 4,
|
|
apis: RUNTIME_API_VERSIONS,
|
|
};
|
|
|
|
/// Constants for Babe.
|
|
|
|
/// Since BABE is probabilistic this is the average expected block time that
|
|
/// we are targetting. Blocks will be produced at a minimum duration defined
|
|
/// by `SLOT_DURATION`, but some slots will not be allocated to any
|
|
/// authority and hence no block will be produced. We expect to have this
|
|
/// block time on average following the defined slot duration and the value
|
|
/// of `c` configured for BABE (where `1 - c` represents the probability of
|
|
/// a slot being empty).
|
|
/// This value is only used indirectly to define the unit constants below
|
|
/// that are expressed in blocks. The rest of the code should use
|
|
/// `SLOT_DURATION` instead (like the timestamp module for calculating the
|
|
/// minimum period).
|
|
/// <https://research.web3.foundation/en/latest/polkadot/BABE/Babe/#6-practical-results>
|
|
pub const MILLISECS_PER_BLOCK: u64 = 6000;
|
|
|
|
pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
|
|
|
|
pub const EPOCH_DURATION_IN_BLOCKS: u32 = 10 * MINUTES;
|
|
|
|
// These time units are defined in number of blocks.
|
|
pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
|
|
pub const HOURS: BlockNumber = MINUTES * 60;
|
|
pub const DAYS: BlockNumber = HOURS * 24;
|
|
|
|
// 1 in 4 blocks (on average, not counting collisions) will be primary babe blocks.
|
|
pub const PRIMARY_PROBABILITY: (u64, u64) = (1, 4);
|
|
|
|
/// The version infromation used to identify this runtime when compiled natively.
|
|
#[cfg(feature = "std")]
|
|
pub fn native_version() -> NativeVersion {
|
|
NativeVersion {
|
|
runtime_version: VERSION,
|
|
can_author_with: Default::default(),
|
|
}
|
|
}
|
|
|
|
parameter_types! {
|
|
pub const BlockHashCount: BlockNumber = 250;
|
|
pub const MaximumBlockWeight: Weight = 1_000_000;
|
|
pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
|
|
pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;
|
|
pub const Version: RuntimeVersion = VERSION;
|
|
}
|
|
|
|
impl system::Trait for Runtime {
|
|
/// The identifier used to distinguish between accounts.
|
|
type AccountId = AccountId;
|
|
/// The aggregated dispatch type that is available for extrinsics.
|
|
type Call = Call;
|
|
/// The lookup mechanism to get account ID from whatever is passed in dispatchers.
|
|
type Lookup = Indices;
|
|
/// The index type for storing how many extrinsics an account has signed.
|
|
type Index = Index;
|
|
/// The index type for blocks.
|
|
type BlockNumber = BlockNumber;
|
|
/// The type for hashing blocks and tries.
|
|
type Hash = Hash;
|
|
/// The hashing algorithm used.
|
|
type Hashing = BlakeTwo256;
|
|
/// The header type.
|
|
type Header = generic::Header<BlockNumber, BlakeTwo256>;
|
|
/// The ubiquitous event type.
|
|
type Event = Event;
|
|
/// Update weight (to fee) multiplier per-block.
|
|
type WeightMultiplierUpdate = ();
|
|
/// The ubiquitous origin type.
|
|
type Origin = Origin;
|
|
/// Maximum number of block number to block hash mappings to keep (oldest pruned first).
|
|
type BlockHashCount = BlockHashCount;
|
|
/// Maximum weight of each block. With a default weight system of 1byte == 1weight, 4mb is ok.
|
|
type MaximumBlockWeight = MaximumBlockWeight;
|
|
/// Maximum size of all encoded transactions (in bytes) that are allowed in one block.
|
|
type MaximumBlockLength = MaximumBlockLength;
|
|
/// Portion of the block weight that is available to all normal transactions.
|
|
type AvailableBlockRatio = AvailableBlockRatio;
|
|
type Version = Version;
|
|
}
|
|
|
|
parameter_types! {
|
|
pub const EpochDuration: u64 = EPOCH_DURATION_IN_BLOCKS as u64;
|
|
pub const ExpectedBlockTime: u64 = MILLISECS_PER_BLOCK;
|
|
}
|
|
|
|
impl babe::Trait for Runtime {
|
|
type EpochDuration = EpochDuration;
|
|
type ExpectedBlockTime = ExpectedBlockTime;
|
|
}
|
|
|
|
impl grandpa::Trait for Runtime {
|
|
type Event = Event;
|
|
}
|
|
|
|
impl indices::Trait for Runtime {
|
|
/// The type for recording indexing into the account enumeration. If this ever overflows, there
|
|
/// will be problems!
|
|
type AccountIndex = u32;
|
|
/// Use the standard means of resolving an index hint from an id.
|
|
type ResolveHint = indices::SimpleResolveHint<Self::AccountId, Self::AccountIndex>;
|
|
/// Determine whether an account is dead.
|
|
type IsDeadAccount = Balances;
|
|
/// The ubiquitous event type.
|
|
type Event = Event;
|
|
}
|
|
|
|
parameter_types! {
|
|
pub const MinimumPeriod: u64 = 5000;
|
|
}
|
|
|
|
impl timestamp::Trait for Runtime {
|
|
/// A timestamp: milliseconds since the unix epoch.
|
|
type Moment = u64;
|
|
type OnTimestampSet = Babe;
|
|
type MinimumPeriod = MinimumPeriod;
|
|
}
|
|
|
|
parameter_types! {
|
|
pub const ExistentialDeposit: u128 = 500;
|
|
pub const TransferFee: u128 = 0;
|
|
pub const CreationFee: u128 = 0;
|
|
pub const TransactionBaseFee: u128 = 0;
|
|
pub const TransactionByteFee: u128 = 1;
|
|
}
|
|
|
|
impl balances::Trait for Runtime {
|
|
/// The type for recording an account's balance.
|
|
type Balance = Balance;
|
|
/// What to do if an account's free balance gets zeroed.
|
|
type OnFreeBalanceZero = ();
|
|
/// What to do if a new account is created.
|
|
type OnNewAccount = Indices;
|
|
/// The ubiquitous event type.
|
|
type Event = Event;
|
|
|
|
type TransactionPayment = ();
|
|
type DustRemoval = ();
|
|
type TransferPayment = ();
|
|
type ExistentialDeposit = ExistentialDeposit;
|
|
type TransferFee = TransferFee;
|
|
type CreationFee = CreationFee;
|
|
type TransactionBaseFee = TransactionBaseFee;
|
|
type TransactionByteFee = TransactionByteFee;
|
|
type WeightToFee = ConvertInto;
|
|
}
|
|
|
|
impl sudo::Trait for Runtime {
|
|
type Event = Event;
|
|
type Proposal = Call;
|
|
}
|
|
|
|
/// Used for the module template in `./template.rs`
|
|
impl template::Trait for Runtime {
|
|
type Event = Event;
|
|
}
|
|
|
|
construct_runtime!(
|
|
pub enum Runtime where
|
|
Block = Block,
|
|
NodeBlock = opaque::Block,
|
|
UncheckedExtrinsic = UncheckedExtrinsic
|
|
{
|
|
System: system::{Module, Call, Storage, Config, Event},
|
|
Timestamp: timestamp::{Module, Call, Storage, Inherent},
|
|
Babe: babe::{Module, Call, Storage, Config, Inherent(Timestamp)},
|
|
Grandpa: grandpa::{Module, Call, Storage, Config, Event},
|
|
Indices: indices::{default, Config<T>},
|
|
Balances: balances,
|
|
Sudo: sudo,
|
|
// Used for the module template in `./template.rs`
|
|
TemplateModule: template::{Module, Call, Storage, Event<T>},
|
|
}
|
|
);
|
|
|
|
/// The address format for describing accounts.
|
|
pub type Address = <Indices as StaticLookup>::Source;
|
|
/// Block header type as expected by this runtime.
|
|
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
|
|
/// Block type as expected by this runtime.
|
|
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
|
|
/// A Block signed with a Justification
|
|
pub type SignedBlock = generic::SignedBlock<Block>;
|
|
/// BlockId type as expected by this runtime.
|
|
pub type BlockId = generic::BlockId<Block>;
|
|
/// The SignedExtension to the basic transaction logic.
|
|
pub type SignedExtra = (
|
|
system::CheckVersion<Runtime>,
|
|
system::CheckGenesis<Runtime>,
|
|
system::CheckEra<Runtime>,
|
|
system::CheckNonce<Runtime>,
|
|
system::CheckWeight<Runtime>,
|
|
balances::TakeFees<Runtime>
|
|
);
|
|
/// Unchecked extrinsic type as expected by this runtime.
|
|
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;
|
|
/// Extrinsic type that has already been checked.
|
|
pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra>;
|
|
/// Executive: handles dispatch to the various modules.
|
|
pub type Executive = executive::Executive<Runtime, Block, system::ChainContext<Runtime>, Runtime, AllModules>;
|
|
|
|
impl_runtime_apis! {
|
|
impl client_api::Core<Block> for Runtime {
|
|
fn version() -> RuntimeVersion {
|
|
VERSION
|
|
}
|
|
|
|
fn execute_block(block: Block) {
|
|
Executive::execute_block(block)
|
|
}
|
|
|
|
fn initialize_block(header: &<Block as BlockT>::Header) {
|
|
Executive::initialize_block(header)
|
|
}
|
|
}
|
|
|
|
impl client_api::Metadata<Block> for Runtime {
|
|
fn metadata() -> OpaqueMetadata {
|
|
Runtime::metadata().into()
|
|
}
|
|
}
|
|
|
|
impl block_builder_api::BlockBuilder<Block> for Runtime {
|
|
fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyResult {
|
|
Executive::apply_extrinsic(extrinsic)
|
|
}
|
|
|
|
fn finalize_block() -> <Block as BlockT>::Header {
|
|
Executive::finalize_block()
|
|
}
|
|
|
|
fn inherent_extrinsics(data: InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
|
|
data.create_extrinsics()
|
|
}
|
|
|
|
fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult {
|
|
data.check_extrinsics(&block)
|
|
}
|
|
|
|
fn random_seed() -> <Block as BlockT>::Hash {
|
|
System::random_seed()
|
|
}
|
|
}
|
|
|
|
impl client_api::TaggedTransactionQueue<Block> for Runtime {
|
|
fn validate_transaction(tx: <Block as BlockT>::Extrinsic) -> TransactionValidity {
|
|
Executive::validate_transaction(tx)
|
|
}
|
|
}
|
|
|
|
impl offchain_primitives::OffchainWorkerApi<Block> for Runtime {
|
|
fn offchain_worker(number: NumberFor<Block>) {
|
|
Executive::offchain_worker(number)
|
|
}
|
|
}
|
|
|
|
impl fg_primitives::GrandpaApi<Block> for Runtime {
|
|
fn grandpa_pending_change(digest: &DigestFor<Block>)
|
|
-> Option<ScheduledChange<NumberFor<Block>>>
|
|
{
|
|
Grandpa::pending_change(digest)
|
|
}
|
|
|
|
fn grandpa_forced_change(digest: &DigestFor<Block>)
|
|
-> Option<(NumberFor<Block>, ScheduledChange<NumberFor<Block>>)>
|
|
{
|
|
Grandpa::forced_change(digest)
|
|
}
|
|
|
|
fn grandpa_authorities() -> Vec<(GrandpaId, GrandpaWeight)> {
|
|
Grandpa::grandpa_authorities()
|
|
}
|
|
}
|
|
|
|
impl babe_primitives::BabeApi<Block> for Runtime {
|
|
fn startup_data() -> babe_primitives::BabeConfiguration {
|
|
// The choice of `c` parameter (where `1 - c` represents the
|
|
// probability of a slot being empty), is done in accordance to the
|
|
// slot duration and expected target block time, for safely
|
|
// resisting network delays of maximum two seconds.
|
|
// <https://research.web3.foundation/en/latest/polkadot/BABE/Babe/#6-practical-results>
|
|
babe_primitives::BabeConfiguration {
|
|
median_required_blocks: 1000,
|
|
slot_duration: Babe::slot_duration(),
|
|
c: PRIMARY_PROBABILITY,
|
|
}
|
|
}
|
|
|
|
fn epoch() -> babe_primitives::Epoch {
|
|
babe_primitives::Epoch {
|
|
start_slot: Babe::epoch_start_slot(),
|
|
authorities: Babe::authorities(),
|
|
epoch_index: Babe::epoch_index(),
|
|
randomness: Babe::randomness(),
|
|
duration: EpochDuration::get(),
|
|
secondary_slots: Babe::secondary_slots().0,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl substrate_session::SessionKeys<Block> for Runtime {
|
|
fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
|
|
let seed = seed.as_ref().map(|s| rstd::str::from_utf8(&s).expect("Seed is an utf8 string"));
|
|
opaque::SessionKeys::generate(seed)
|
|
}
|
|
}
|
|
}
|