Newer
Older
// Copyright 2017-2019 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
//! Main parachains logic. For now this is just the determination of which validators do what.
use rstd::prelude::*;
use rstd::collections::btree_map::BTreeMap;
use codec::{Encode, Decode, HasCompact};
use srml_support::{decl_storage, decl_module, fail, ensure};
use sr_primitives::traits::{Hash as HashT, BlakeTwo256, Member, CheckedConversion, Saturating, One};
use sr_primitives::weights::SimpleDispatchInfo;
use primitives::{Hash, Balance, parachain::{
self, Id as ParaId, Chain, DutyRoster, AttestedCandidate, Statement, AccountIdConversion,
ParachainDispatchOrigin, UpwardMessage, BlockIngressRoots, ValidatorId
use {system, session};
StorageValue, StorageMap, storage::AppendableStorageMap, Parameter, Dispatchable, dispatch::Result,
traits::{Currency, Get, WithdrawReason, ExistenceRequirement}
use inherents::{ProvideInherent, InherentData, RuntimeString, MakeFatalError, InherentIdentifier};
#[cfg(any(feature = "std", test))]
use sr_primitives::{StorageOverlay, ChildrenStorageOverlay};
#[cfg(any(feature = "std", test))]
use rstd::marker::PhantomData;
use system::{ensure_none, ensure_root};
use crate::attestations::{self, IncludedBlocks};
// ranges for iteration of general block number don't work, so this
// is a utility to get around that.
struct BlockNumberRange<N> {
low: N,
high: N,
}
impl<N: Saturating + One + PartialOrd + PartialEq + Clone> Iterator for BlockNumberRange<N> {
type Item = N;
fn next(&mut self) -> Option<N> {
if self.low >= self.high {
return None
}
let item = self.low.clone();
self.low = self.low.clone().saturating_add(One::one());
Some(item)
}
}
// creates a range iterator between `low` and `high`. `low` must be <= `high`.
fn number_range<N>(low: N, high: N) -> BlockNumberRange<N> {
BlockNumberRange { low, high }
}
/// Parachain registration API.
pub trait ParachainRegistrar<AccountId> {
/// An identifier for a parachain.
type ParaId: Member + Parameter + Default + AccountIdConversion<AccountId> + Copy + HasCompact;
/// Create a new unique parachain identity for later registration.
fn new_id() -> Self::ParaId;
/// Register a parachain with given `code` and `initial_head_data`. `id` must not yet be registered or it will
/// result in a error.
fn register_parachain(id: Self::ParaId, code: Vec<u8>, initial_head_data: Vec<u8>) -> Result;
/// Deregister a parachain with given `id`. If `id` is not currently registered, an error is returned.
fn deregister_parachain(id: Self::ParaId) -> Result;
}
impl<T: Trait> ParachainRegistrar<T::AccountId> for Module<T> {
type ParaId = ParaId;
fn new_id() -> ParaId {
<NextFreeId>::mutate(|n| { let r = *n; *n = ParaId::from(u32::from(*n) + 1); r })
}
fn register_parachain(id: ParaId, code: Vec<u8>, initial_head_data: Vec<u8>) -> Result {
let mut parachains = Self::active_parachains();
match parachains.binary_search(&id) {
Ok(_) => fail!("Parachain already exists"),
Err(idx) => parachains.insert(idx, id),
}
<Code>::insert(id, code);
<Parachains>::put(parachains);
<Heads>::insert(id, initial_head_data);
// Because there are no ordering guarantees that inherents
// are applied before regular transactions, a parachain candidate could
// be registered before the `UpdateHeads` inherent is processed. If so, messages
// could be sent to a parachain in the block it is registered.
<Watermarks<T>>::insert(id, <system::Module<T>>::block_number().saturating_sub(One::one()));
Ok(())
}
fn deregister_parachain(id: ParaId) -> Result {
let mut parachains = Self::active_parachains();
match parachains.binary_search(&id) {
Ok(idx) => { parachains.remove(idx); }
Err(_) => return Ok(()),
}
<Code>::remove(id);
<Heads>::remove(id);
let watermark = <Watermarks<T>>::take(id);
// clear all routing entries _to_. But not those _from_.
if let Some(watermark) = watermark {
let now = <system::Module<T>>::block_number();
// iterate over all blocks between watermark and now + 1 (since messages might
// have already been sent to `id` in this block.
for unrouted_block in number_range(watermark, now).map(|n| n.saturating_add(One::one())) {
<UnroutedIngress<T>>::remove(&(unrouted_block, id));
}
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
// wrapper trait because an associated type of `Currency<Self::AccountId,Balance=Balance>`
// doesn't work.`
pub trait ParachainCurrency<AccountId> {
fn free_balance(para_id: ParaId) -> Balance;
fn deduct(para_id: ParaId, amount: Balance) -> Result;
}
impl<AccountId, T: Currency<AccountId>> ParachainCurrency<AccountId> for T where
T::Balance: From<Balance> + Into<Balance>,
ParaId: AccountIdConversion<AccountId>,
{
fn free_balance(para_id: ParaId) -> Balance {
let para_account = para_id.into_account();
T::free_balance(¶_account).into()
}
fn deduct(para_id: ParaId, amount: Balance) -> Result {
let para_account = para_id.into_account();
// burn the fee.
let _ = T::withdraw(
¶_account,
amount.into(),
WithdrawReason::Fee,
ExistenceRequirement::KeepAlive,
)?;
Ok(())
}
}
/// Interface to the persistent (stash) identities of the current validators.
pub struct ValidatorIdentities<T>(rstd::marker::PhantomData<T>);
impl<T: session::Trait> Get<Vec<T::ValidatorId>> for ValidatorIdentities<T> {
fn get() -> Vec<T::ValidatorId> {
<session::Module<T>>::validators()
}
}
pub trait Trait: attestations::Trait {
/// The outer origin type.
type Origin: From<Origin> + From<system::RawOrigin<Self::AccountId>>;
/// The outer call dispatch type.
type Call: Parameter + Dispatchable<Origin=<Self as Trait>::Origin>;
/// Some way of interacting with balances for fees.
type ParachainCurrency: ParachainCurrency<Self::AccountId>;
}
/// Origin for the parachains module.
#[derive(PartialEq, Eq, Clone)]
#[cfg_attr(feature = "std", derive(Debug))]
pub enum Origin {
/// It comes from a parachain.
Parachain(ParaId),
Loading full blame...