Newer
Older
// Copyright 2017 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 bitvec::BigEndian;
use sr_primitives::traits::{Hash as HashT, BlakeTwo256, Member};
use primitives::{Hash, parachain::{Id as ParaId, Chain, DutyRoster, AttestedCandidate, Statement, AccountIdConversion}};
use {system, session};
use srml_support::{StorageValue, StorageMap, Parameter, dispatch::Result};
#[cfg(feature = "std")]
use srml_support::storage::hashed::generator;
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;
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/// 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<T>>::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<T>>::insert(id, code);
<Parachains<T>>::put(parachains);
<Heads<T>>::insert(id, initial_head_data);
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<T>>::remove(id);
<Heads<T>>::remove(id);
// clear all routing entries to and from other parachains.
for other in parachains.iter().cloned() {
<Routing<T>>::remove((id, other));
<Routing<T>>::remove((other, id));
}
<Parachains<T>>::put(parachains);
Ok(())
}
}
pub trait Trait: session::Trait {
}
// result of <NodeCodec<Blake2Hasher> as trie_db::NodeCodec<Blake2Hasher>>::hashed_null_node()
const EMPTY_TRIE_ROOT: [u8; 32] = [
3, 23, 10, 46, 117, 151, 183, 183, 227, 216, 76, 5, 57, 29, 19, 154,
98, 177, 87, 231, 135, 134, 216, 192, 130, 242, 157, 207, 76, 17, 19, 20
];
trait Store for Module<T: Trait> as Parachains {
// Vector of all parachain IDs.
pub Parachains get(active_parachains): Vec<ParaId>;
pub Code get(parachain_code): map ParaId => Option<Vec<u8>>;
// The heads of the parachains registered at present.
pub Heads get(parachain_head): map ParaId => Option<Vec<u8>>;
// message routing roots (from, to).
pub Routing: map (ParaId, ParaId) => Option<Hash>;
// Did the parachain heads get updated in this block?
/// The next unused ParaId value.
NextFreeId: ParaId;
config(parachains): Vec<(ParaId, Vec<u8>, Vec<u8>)>;
build(|storage: &mut StorageOverlay, _: &mut ChildrenStorageOverlay, config: &GenesisConfig<T>| {
let mut p = config.parachains.clone();
p.sort_unstable_by_key(|&(ref id, _, _)| id.clone());
p.dedup_by_key(|&mut (ref id, _, _)| id.clone());
let only_ids: Vec<_> = p.iter().map(|&(ref id, _, _)| id).cloned().collect();
<Parachains<T> as generator::StorageValue<_>>::put(&only_ids, storage);
// no ingress -- a chain cannot be routed to until it is live.
<Code<T> as generator::StorageMap<_, _>>::insert(&id, &code, storage);
<Heads<T> as generator::StorageMap<_, _>>::insert(&id, &genesis, storage);
}
});
}
}
decl_module! {
/// Parachains module.
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
/// Provide candidate receipts for parachains, in ascending order by id.
fn set_heads(origin, heads: Vec<AttestedCandidate>) -> Result {
ensure!(!<DidUpdate<T>>::exists(), "Parachain heads must be updated only once in the block");
let active_parachains = Self::active_parachains();
// perform integrity checks before writing to storage.
{
let n_parachains = active_parachains.len();
ensure!(heads.len() <= n_parachains, "Too many parachain candidates");
let mut last_id = None;
let mut iter = active_parachains.iter();
for head in &heads {
// proposed heads must be ascending order by parachain ID without duplicate.
ensure!(
last_id.as_ref().map_or(true, |x| x < &head.parachain_index()),
"Parachain candidates out of order by ID"
);
// must be unknown since active parachains are always sorted.
ensure!(
iter.find(|x| x == &&head.parachain_index()).is_some(),
"Submitted candidate for unregistered or out-of-order parachain {}"
);
Self::check_egress_queue_roots(&head, &active_parachains)?;
last_id = Some(head.parachain_index());
Self::check_attestations(&heads)?;
let id = head.parachain_index();
<Heads<T>>::insert(id, head.candidate.head_data.0);
// update egress.
for &(to, root) in &head.candidate.egress_queue_roots {
<Routing<T>>::insert((id, to), root);
}
}
<DidUpdate<T>>::put(true);
Ok(())
}
/// Register a parachain with given code.
/// Fails if given ID is already used.
pub fn register_parachain(id: ParaId, code: Vec<u8>, initial_head_data: Vec<u8>) -> Result {
<Self as ParachainRegistrar<T::AccountId>>::register_parachain(id, code, initial_head_data)
Loading full blame...